From 3ac932d4feb8624cc02b8a0c339e171061ac8699 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Fri, 15 Nov 2013 15:01:51 +0100 Subject: [PATCH 001/215] Sync with Glitch_Flo_CAF since -glitched- commit. It did need fixes and adapations for AOSP base. Signed-off-by: Tk-Glitch --- Documentation/HOWTO | 32 +- Documentation/cgroups/timer_slack.txt | 72 + Makefile | 54 +- arch/alpha/kernel/smp.c | 10 +- arch/alpha/kernel/traps.c | 4 +- arch/arm/Kconfig | 31 +- arch/arm/Makefile | 11 +- arch/arm/boot/compressed/Makefile | 17 +- arch/arm/boot/compressed/head.S | 96 + arch/arm/boot/dts/tegra-cardhu.dts | 2 +- arch/arm/common/gic.c | 4 +- arch/arm/configs/flo_defconfig | 3525 +++++++++- arch/arm/crypto/Makefile | 9 + arch/arm/crypto/aes-armv4.S | 1112 +++ arch/arm/crypto/aes_glue.c | 108 + arch/arm/crypto/sha1-armv4-large.S | 503 ++ arch/arm/crypto/sha1_glue.c | 179 + arch/arm/include/asm/kexec.h | 8 + arch/arm/include/asm/rwsem.h | 138 + arch/arm/include/asm/topology.h | 45 + arch/arm/kernel/arch_timer.c | 6 +- arch/arm/kernel/atags.c | 51 +- arch/arm/kernel/hw_breakpoint.c | 4 +- arch/arm/kernel/machine_kexec.c | 22 +- arch/arm/kernel/perf_event.c | 4 +- arch/arm/kernel/relocate_kernel.S | 55 + arch/arm/kernel/smp.c | 11 +- arch/arm/kernel/smp_twd.c | 6 +- arch/arm/kernel/topology.c | 345 +- arch/arm/lib/memset.S | 85 +- arch/arm/mach-exynos/mct.c | 4 +- arch/arm/mach-exynos/platsmp.c | 6 +- arch/arm/mach-highbank/platsmp.c | 4 +- arch/arm/mach-imx/platsmp.c | 4 +- arch/arm/mach-msm/Kconfig | 38 +- arch/arm/mach-msm/Makefile | 3 + arch/arm/mach-msm/acpuclock-8064.c | 313 +- arch/arm/mach-msm/acpuclock-8x60.c | 4 +- arch/arm/mach-msm/acpuclock-krait.c | 222 +- arch/arm/mach-msm/asustek/devices_asustek.c | 15 + arch/arm/mach-msm/asustek/flo/board-flo-gpu.c | 15 +- .../asustek/flo/board-flo-regulator.c | 13 +- arch/arm/mach-msm/asustek/flo/board-flo.c | 8 +- arch/arm/mach-msm/board-8064-gpu.c | 5 + arch/arm/mach-msm/clock-8960.c | 21 +- arch/arm/mach-msm/clock-pll.c | 35 + arch/arm/mach-msm/cpufreq.c | 4 +- arch/arm/mach-msm/devices-8064.c | 8 +- arch/arm/mach-msm/fastchg.c | 104 + arch/arm/mach-msm/include/mach/memory.h | 8 + arch/arm/mach-msm/intelli_plug.c | 346 + arch/arm/mach-msm/msm_dcvs.c | 2 +- arch/arm/mach-msm/msm_mpdecision.c | 1776 +++-- arch/arm/mach-msm/msm_rq_stats.c | 17 + arch/arm/mach-msm/platsmp-8625.c | 8 +- arch/arm/mach-msm/platsmp.c | 16 +- arch/arm/mach-msm/restart.c | 16 + arch/arm/mach-msm/timer.c | 2 +- arch/arm/mach-msm/vdd_limits_8064.h | 3 + arch/arm/mach-omap2/omap-mpuss-lowpower.c | 2 +- arch/arm/mach-omap2/omap-smp.c | 4 +- arch/arm/mach-omap2/omap-wakeupgen.c | 2 +- arch/arm/mach-shmobile/platsmp.c | 4 +- arch/arm/mach-shmobile/smp-r8a7779.c | 4 +- arch/arm/mach-shmobile/smp-sh73a0.c | 4 +- arch/arm/mach-tegra/platsmp.c | 4 +- arch/arm/mach-ux500/platsmp.c | 4 +- arch/arm/plat-versatile/platsmp.c | 8 +- arch/arm/vfp/Makefile | 2 +- arch/blackfin/kernel/perf_event.c | 2 +- arch/blackfin/kernel/setup.c | 4 +- arch/blackfin/mach-bf561/smp.c | 6 +- arch/blackfin/mach-common/cache-c.c | 4 +- arch/blackfin/mach-common/ints-priority.c | 2 +- arch/blackfin/mach-common/smp.c | 12 +- arch/cris/arch-v32/kernel/smp.c | 2 +- arch/frv/kernel/setup.c | 2 +- arch/hexagon/kernel/setup.c | 2 +- arch/hexagon/kernel/smp.c | 4 +- arch/ia64/kernel/acpi.c | 4 +- arch/ia64/kernel/err_inject.c | 8 +- arch/ia64/kernel/mca.c | 12 +- arch/ia64/kernel/numa.c | 4 +- arch/ia64/kernel/palinfo.c | 4 +- arch/ia64/kernel/salinfo.c | 4 +- arch/ia64/kernel/setup.c | 10 +- arch/ia64/kernel/smpboot.c | 12 +- arch/ia64/kernel/topology.c | 18 +- arch/ia64/mm/contig.c | 2 +- arch/ia64/mm/discontig.c | 2 +- arch/ia64/sn/kernel/setup.c | 8 +- arch/ia64/xen/hypervisor.c | 2 +- arch/m32r/kernel/smpboot.c | 2 +- arch/mips/ath79/setup.c | 2 +- arch/mips/cavium-octeon/octeon-irq.c | 8 +- arch/mips/cavium-octeon/smp.c | 6 +- arch/mips/include/asm/uasm.h | 4 +- arch/mips/kernel/cevt-bcm1480.c | 2 +- arch/mips/kernel/cevt-r4k.c | 2 +- arch/mips/kernel/cevt-sb1250.c | 2 +- arch/mips/kernel/cevt-smtc.c | 2 +- arch/mips/kernel/cpu-bugs64.c | 2 +- arch/mips/kernel/cpu-probe.c | 12 +- arch/mips/kernel/smp-bmips.c | 6 +- arch/mips/kernel/smp-mt.c | 6 +- arch/mips/kernel/smp-up.c | 6 +- arch/mips/kernel/smp.c | 8 +- arch/mips/kernel/smtc.c | 2 +- arch/mips/kernel/spram.c | 14 +- arch/mips/kernel/sync-r4k.c | 12 +- arch/mips/kernel/traps.c | 8 +- arch/mips/kernel/watch.c | 2 +- arch/mips/lantiq/irq.c | 2 +- arch/mips/lib/uncached.c | 2 +- arch/mips/mipssim/sim_smtc.c | 6 +- arch/mips/mipssim/sim_time.c | 2 +- arch/mips/mm/c-octeon.c | 4 +- arch/mips/mm/c-r3k.c | 8 +- arch/mips/mm/c-r4k.c | 34 +- arch/mips/mm/c-tx39.c | 2 +- arch/mips/mm/cache.c | 2 +- arch/mips/mm/page.c | 40 +- arch/mips/mm/sc-ip22.c | 2 +- arch/mips/mm/sc-mips.c | 2 +- arch/mips/mm/sc-r5k.c | 2 +- arch/mips/mm/sc-rm7k.c | 12 +- arch/mips/mm/tlb-r3k.c | 2 +- arch/mips/mm/tlb-r4k.c | 4 +- arch/mips/mm/tlb-r8k.c | 4 +- arch/mips/mm/tlbex.c | 102 +- arch/mips/mti-malta/malta-smtc.c | 6 +- arch/mips/mti-malta/malta-time.c | 2 +- arch/mips/netlogic/common/irq.c | 2 +- arch/mips/netlogic/common/smp.c | 4 +- arch/mips/netlogic/common/time.c | 2 +- arch/mips/netlogic/xlr/wakeup.c | 2 +- arch/mips/pci/pci-ip27.c | 2 +- arch/mips/pmc-sierra/msp71xx/msp_smtc.c | 6 +- arch/mips/pmc-sierra/msp71xx/msp_time.c | 2 +- arch/mips/pmc-sierra/yosemite/smp.c | 12 +- arch/mips/pnx833x/common/interrupts.c | 2 +- arch/mips/powertv/time.c | 2 +- arch/mips/sgi-ip27/ip27-init.c | 4 +- arch/mips/sgi-ip27/ip27-smp.c | 6 +- arch/mips/sgi-ip27/ip27-timer.c | 6 +- arch/mips/sgi-ip27/ip27-xtalk.c | 6 +- arch/mips/sibyte/bcm1480/smp.c | 8 +- arch/mips/sibyte/sb1250/smp.c | 8 +- arch/openrisc/kernel/setup.c | 2 +- arch/parisc/kernel/firmware.c | 12 +- arch/parisc/kernel/hardware.c | 2 +- arch/parisc/kernel/processor.c | 6 +- arch/parisc/kernel/smp.c | 8 +- arch/powerpc/include/asm/rtas.h | 4 +- arch/powerpc/kernel/cacheinfo.c | 30 +- arch/powerpc/kernel/idle.c | 14 +- arch/powerpc/kernel/rtas.c | 4 +- arch/powerpc/kernel/smp.c | 10 +- arch/powerpc/kernel/sysfs.c | 6 +- arch/powerpc/kernel/time.c | 2 +- arch/powerpc/mm/44x_mmu.c | 6 +- arch/powerpc/mm/hash_utils_64.c | 2 +- arch/powerpc/mm/mmu_context_nohash.c | 4 +- arch/powerpc/mm/numa.c | 8 +- arch/powerpc/mm/tlb_nohash.c | 2 +- arch/powerpc/perf/core-book3s.c | 4 +- arch/powerpc/platforms/44x/currituck.c | 4 +- arch/powerpc/platforms/44x/iss4xx.c | 4 +- arch/powerpc/platforms/powermac/smp.c | 2 +- arch/powerpc/platforms/powernv/smp.c | 2 +- arch/s390/appldata/appldata_base.c | 8 +- arch/s390/kernel/perf_cpum_cf.c | 2 +- arch/s390/kernel/processor.c | 2 +- arch/s390/kernel/smp.c | 12 +- arch/s390/kernel/sysinfo.c | 2 +- arch/s390/kernel/vtime.c | 2 +- arch/s390/mm/fault.c | 16 +- arch/score/mm/tlb-score.c | 2 +- arch/sh/kernel/cpu/init.c | 18 +- arch/sh/kernel/cpu/sh2/probe.c | 2 +- arch/sh/kernel/cpu/sh2a/probe.c | 2 +- arch/sh/kernel/cpu/sh3/probe.c | 2 +- arch/sh/kernel/cpu/sh4/probe.c | 2 +- arch/sh/kernel/cpu/sh4a/smp-shx3.c | 6 +- arch/sh/kernel/cpu/sh5/probe.c | 2 +- arch/sh/kernel/perf_event.c | 4 +- arch/sh/kernel/process.c | 2 +- arch/sh/kernel/setup.c | 2 +- arch/sh/kernel/smp.c | 8 +- arch/sh/kernel/traps_32.c | 2 +- arch/sh/kernel/traps_64.c | 2 +- arch/sparc/Kconfig | 3 + arch/sparc/kernel/ds.c | 4 +- arch/sparc/kernel/entry.h | 2 +- arch/sparc/kernel/irq_64.c | 4 +- arch/sparc/kernel/leon_smp.c | 4 +- arch/sparc/kernel/mdesc.c | 26 +- arch/sparc/kernel/smp_32.c | 12 +- arch/sparc/kernel/smp_64.c | 8 +- arch/sparc/kernel/sun4d_smp.c | 6 +- arch/sparc/kernel/sun4m_smp.c | 6 +- arch/sparc/kernel/sysfs.c | 4 +- arch/sparc/kernel/systbls_64.S | 2 +- arch/sparc/mm/init_64.c | 2 +- arch/sparc/mm/srmmu.c | 14 +- arch/tile/include/asm/bitops.h | 12 +- arch/tile/kernel/irq.c | 2 +- arch/tile/kernel/messaging.c | 2 +- arch/tile/kernel/setup.c | 10 +- arch/tile/kernel/smpboot.c | 8 +- arch/tile/kernel/time.c | 2 +- arch/um/include/asm/pgtable.h | 10 +- arch/x86/Makefile | 1 + arch/x86/include/asm/mmconfig.h | 4 +- arch/x86/include/asm/mpspec.h | 2 +- arch/x86/include/asm/numa.h | 10 +- arch/x86/include/asm/prom.h | 2 +- arch/x86/include/asm/smp.h | 2 +- arch/x86/kernel/acpi/boot.c | 6 +- arch/x86/kernel/apic/apic.c | 30 +- arch/x86/kernel/apic/apic_numachip.c | 2 +- arch/x86/kernel/apic/es7000_32.c | 2 +- arch/x86/kernel/apic/numaq_32.c | 2 +- arch/x86/kernel/apic/x2apic_cluster.c | 2 +- arch/x86/kernel/apic/x2apic_uv_x.c | 12 +- arch/x86/kernel/cpu/amd.c | 28 +- arch/x86/kernel/cpu/centaur.c | 26 +- arch/x86/kernel/cpu/common.c | 68 +- arch/x86/kernel/cpu/cyrix.c | 40 +- arch/x86/kernel/cpu/hypervisor.c | 2 +- arch/x86/kernel/cpu/intel.c | 24 +- arch/x86/kernel/cpu/intel_cacheinfo.c | 52 +- arch/x86/kernel/cpu/mcheck/mce-severity.c | 16 +- arch/x86/kernel/cpu/mcheck/mce.c | 31 +- arch/x86/kernel/cpu/mcheck/mce_amd.c | 10 +- arch/x86/kernel/cpu/mcheck/therm_throt.c | 8 +- arch/x86/kernel/cpu/perf_event.c | 2 +- arch/x86/kernel/cpu/perf_event_amd.c | 11 +- arch/x86/kernel/cpu/perf_event_amd_ibs.c | 2 +- arch/x86/kernel/cpu/rdrand.c | 2 +- arch/x86/kernel/cpu/scattered.c | 4 +- arch/x86/kernel/cpu/topology.c | 2 +- arch/x86/kernel/cpu/transmeta.c | 6 +- arch/x86/kernel/cpu/umc.c | 2 +- arch/x86/kernel/cpu/vmware.c | 2 +- arch/x86/kernel/cpuid.c | 4 +- arch/x86/kernel/devicetree.c | 2 +- arch/x86/kernel/i387.c | 8 +- arch/x86/kernel/irq_32.c | 2 +- arch/x86/kernel/kvm.c | 8 +- arch/x86/kernel/kvmclock.c | 2 +- arch/x86/kernel/microcode_core.c | 2 +- arch/x86/kernel/mmconf-fam10h_64.c | 12 +- arch/x86/kernel/msr.c | 4 +- arch/x86/kernel/process.c | 2 +- arch/x86/kernel/setup.c | 2 +- arch/x86/kernel/smpboot.c | 26 +- arch/x86/kernel/tboot.c | 4 +- arch/x86/kernel/tsc.c | 4 +- arch/x86/kernel/tsc_sync.c | 18 +- arch/x86/kernel/vsyscall_64.c | 6 +- arch/x86/kernel/x86_init.c | 4 +- arch/x86/kernel/xsave.c | 2 +- arch/x86/mm/numa.c | 18 +- arch/x86/mm/numa_emulation.c | 12 +- arch/x86/mm/setup_nx.c | 4 +- arch/x86/mm/tlb.c | 6 +- arch/x86/pci/amd_bus.c | 6 +- arch/x86/pci/xen.c | 4 + arch/x86/platform/ce4100/ce4100.c | 2 +- arch/x86/platform/mrst/mrst.c | 4 +- arch/x86/platform/sfi/sfi.c | 2 +- arch/x86/tools/relocs.c | 12 + arch/x86/xen/enlighten.c | 4 +- arch/x86/xen/setup.c | 6 +- arch/x86/xen/smp.c | 12 +- arch/x86/xen/spinlock.c | 2 +- arch/x86/xen/xen-ops.h | 2 +- arch/xtensa/kernel/time.c | 2 +- block/Kconfig.iosched | 26 + block/Makefile | 2 + block/blk-iopoll.c | 4 +- block/blk-softirq.c | 4 +- block/fiops-iosched.c | 753 ++ block/sio-iosched.c | 403 ++ crypto/Kconfig | 33 + drivers/acpi/processor_core.c | 8 +- drivers/acpi/processor_driver.c | 4 +- drivers/acpi/processor_idle.c | 6 +- drivers/base/cpu.c | 4 +- drivers/base/topology.c | 8 +- drivers/char/Makefile | 1 + drivers/cpufreq/Kconfig | 18 + drivers/cpufreq/Makefile | 1 + drivers/cpufreq/cpufreq.c | 108 +- drivers/cpufreq/cpufreq_intellidemand.c | 2041 ++++++ drivers/cpufreq/cpufreq_ondemand.c | 4 + drivers/cpufreq/cpufreq_stats.c | 13 +- drivers/cpufreq/db8500-cpufreq.c | 2 +- drivers/cpufreq/longhaul.c | 6 +- drivers/cpufreq/longhaul.h | 26 +- drivers/cpufreq/longrun.c | 6 +- drivers/cpufreq/omap-cpufreq.c | 2 +- drivers/cpufreq/powernow-k7.c | 8 +- drivers/cpufreq/powernow-k8.c | 6 +- drivers/cpuidle/cpuidle.c | 16 +- drivers/cpuidle/driver.c | 24 - drivers/cpuidle/governors/menu.c | 177 +- drivers/cpuidle/sysfs.c | 21 +- drivers/gpio/gpio-mpc8xxx.c | 3 +- drivers/gpu/Makefile | 1 + drivers/gpu/drm/gma500/psb_device.c | 6 +- drivers/gpu/drm/i915/i915_irq.c | 9 +- drivers/gpu/drm/i915/i915_reg.h | 15 + drivers/gpu/drm/i915/intel_display.c | 19 +- drivers/gpu/drm/nouveau/nouveau_bo.c | 2 +- drivers/gpu/ion/Makefile | 1 + drivers/gpu/ion/msm/Makefile | 1 + drivers/gpu/msm/Kconfig | 8 + drivers/gpu/msm/Makefile | 2 +- drivers/gpu/msm/kgsl_pwrctrl.c | 50 +- drivers/gpu/msm/kgsl_pwrscale_trustzone.c | 91 +- drivers/hid/hid-multitouch.c | 5 +- drivers/hid/hid-wiimote-core.c | 16 +- drivers/hid/usbhid/hid-core.c | 61 +- drivers/hwmon/coretemp.c | 28 +- drivers/hwmon/via-cputemp.c | 6 +- drivers/i2c/busses/i2c-davinci.c | 2 +- drivers/i2c/busses/i2c-tegra.c | 13 +- drivers/infiniband/core/umem.c | 2 +- drivers/infiniband/hw/cxgb4/cm.c | 13 +- drivers/infiniband/hw/ehca/ehca_irq.c | 6 +- drivers/input/input-mt.c | 1 - drivers/input/input.c | 213 +- drivers/input/keyboard/gpio_keys.c | 15 + drivers/input/lid.c | 14 +- drivers/input/touchscreen/ektf3k.c | 580 +- drivers/iommu/dmar.c | 4 +- drivers/iommu/intel-iommu.c | 17 +- drivers/isdn/gigaset/capi.c | 26 +- drivers/isdn/gigaset/ev-layer.c | 4 +- drivers/md/md.c | 2 +- drivers/media/common/tuners/xc4000.c | 10 +- drivers/media/common/tuners/xc5000.c | 8 +- drivers/media/dvb/siano/smsusb.c | 2 + drivers/media/video/uvc/uvc_v4l2.c | 2 +- drivers/misc/qseecom.c | 4 +- drivers/mmc/core/cd-gpio.c | 3 + drivers/mmc/host/omap_hsmmc.c | 2 +- drivers/net/phy/phy.c | 2 +- drivers/net/ppp/ppp_generic.c | 4 +- drivers/net/wireless/b43legacy/main.c | 2 - drivers/oprofile/timer_int.c | 2 +- drivers/power/bq27541_battery.c | 11 +- drivers/power/smb345-charger.c | 55 +- drivers/regulator/core.c | 2 + drivers/scsi/Kconfig | 2 +- drivers/scsi/isci/init.c | 2 +- drivers/scsi/mpt2sas/mpt2sas_base.c | 6 +- drivers/spi/spi-fsl-spi.c | 2 +- drivers/staging/Kconfig | 4 + drivers/staging/Makefile | 1 + drivers/staging/android/binder.c | 5 +- drivers/staging/android/persistent_ram.c | 19 +- drivers/staging/comedi/comedi_fops.c | 2 +- drivers/staging/cpupower/Kconfig | 5 + drivers/staging/cpupower/Makefile | 4 + drivers/staging/cpupower/cpu_power.c | 179 + .../prima/CORE/SME/src/csr/csrNeighborRoam.c | 2 +- drivers/staging/prima/Kbuild | 2 +- drivers/thermal/msm8960_tsens.c | 96 +- drivers/thermal/msm_thermal.c | 236 +- drivers/thermal/pm8xxx-tm.c | 62 +- drivers/tty/hvc/hvc_xen.c | 4 +- drivers/tty/serial/8250/8250.c | 9 +- drivers/tty/serial/8250/8250_pci.c | 18 + drivers/tty/serial/mxs-auart.c | 2 + drivers/tty/serial/serial_core.c | 1 + drivers/usb/class/cdc-wdm.c | 31 +- drivers/usb/core/devio.c | 33 +- drivers/usb/core/hub.c | 6 +- drivers/usb/core/quirks.c | 3 + drivers/usb/core/urb.c | 21 + drivers/usb/gadget/f_fs.c | 14 + drivers/usb/gadget/f_qdss.c | 4 +- drivers/usb/gadget/fsl_udc_core.c | 2 + drivers/usb/host/ehci-omap.c | 18 +- drivers/usb/host/ehci-pci.c | 4 +- drivers/usb/host/ehci-platform.c | 2 - drivers/usb/host/ohci-at91.c | 11 +- drivers/usb/host/pci-quirks.c | 32 +- drivers/usb/host/xhci-hub.c | 22 +- drivers/usb/host/xhci-mem.c | 27 + drivers/usb/host/xhci-pci.c | 1 + drivers/usb/host/xhci-ring.c | 22 +- drivers/usb/host/xhci.c | 12 +- drivers/usb/host/xhci.h | 3 + drivers/usb/misc/usbtest.c | 17 +- drivers/usb/otg/gpio_vbus.c | 8 +- drivers/usb/otg/msm_otg.c | 87 +- drivers/usb/serial/ftdi_sio.c | 1 + drivers/usb/serial/ftdi_sio_ids.h | 8 + drivers/usb/serial/ti_usb_3410_5052.c | 6 +- drivers/usb/serial/ti_usb_3410_5052.h | 1 + drivers/usb/serial/usb-serial.c | 9 +- drivers/usb/serial/usb-wwan.h | 8 +- drivers/usb/storage/transport.c | 4 +- drivers/usb/storage/unusual_devs.h | 7 + drivers/video/msm/mipi_novatek.c | 2 +- drivers/video/sh_mobile_lcdcfb.c | 5 +- drivers/video/sh_mobile_lcdcfb.h | 1 + drivers/xen/events.c | 5 +- frandom/Makefile | 2 + frandom/frandom.c | 420 ++ fs/Kconfig | 32 + fs/Makefile | 3 + fs/aio.c | 34 +- fs/btrfs/disk-io.c | 8 +- fs/btrfs/file.c | 3 +- fs/btrfs/ioctl.c | 2 +- fs/dyn_sync_cntrl.c | 206 + fs/eventpoll.c | 156 +- fs/exfat/Kconfig | 19 + fs/exfat/Makefile | 4 + fs/exfat/Makefile.module | 20 + fs/exfat/README.md | 71 + fs/exfat/exfat.h | 675 ++ fs/exfat/exfat_api.c | 563 ++ fs/exfat/exfat_api.h | 221 + fs/exfat/exfat_blkdev.c | 190 + fs/exfat/exfat_blkdev.h | 83 + fs/exfat/exfat_cache.c | 785 +++ fs/exfat/exfat_cache.h | 94 + fs/exfat/exfat_config.h | 102 + fs/exfat/exfat_core.c | 5187 ++++++++++++++ fs/exfat/exfat_data.c | 77 + fs/exfat/exfat_data.h | 83 + fs/exfat/exfat_global.c | 168 + fs/exfat/exfat_global.h | 214 + fs/exfat/exfat_nls.c | 394 ++ fs/exfat/exfat_nls.h | 101 + fs/exfat/exfat_oal.c | 189 + fs/exfat/exfat_oal.h | 88 + fs/exfat/exfat_part.h | 92 + fs/exfat/exfat_super.c | 2306 ++++++ fs/exfat/exfat_super.h | 172 + fs/exfat/exfat_upcase.c | 408 ++ fs/exfat/exfat_version.h | 19 + fs/fuse/control.c | 4 +- fs/jbd/journal.c | 6 +- fs/jbd2/journal.c | 6 +- fs/namei.c | 8 +- fs/namespace.c | 33 +- fs/nfs/inode.c | 2 +- fs/nfs/nfs3proc.c | 2 +- fs/nfs/nfs4proc.c | 4 +- fs/ocfs2/file.c | 5 +- fs/proc/loadavg.c | 6 +- fs/select.c | 12 +- fs/splice.c | 5 +- fs/sync.c | 100 +- glitch.sh | 127 + include/linux/cgroup_subsys.h | 7 + include/linux/cpu.h | 2 +- include/linux/cpufreq.h | 3 + include/linux/cpuidle.h | 4 +- include/linux/debug_locks.h | 4 +- include/linux/fastchg.h | 23 + include/linux/freezer.h | 168 +- include/linux/fs.h | 1 + include/linux/init.h | 12 +- include/linux/input.h | 24 +- include/linux/kexec.h | 19 +- include/linux/memcopy.h | 226 + include/linux/mm.h | 2 +- include/linux/msm_thermal.h | 6 +- include/linux/msm_tsens.h | 2 + include/linux/perf_event.h | 2 +- include/linux/power/cpupower.h | 22 + include/linux/prctl.h | 6 + include/linux/sched.h | 11 + include/linux/sweep2wake.h | 23 + include/linux/tick.h | 6 + include/linux/usb.h | 3 + include/linux/writeback.h | 9 +- include/xen/events.h | 3 + init/Kconfig | 25 +- init/calibrate.c | 10 +- init/main.c | 7 +- ipc/shm.c | 2 +- kernel/Makefile | 1 + kernel/auditsc.c | 2 +- kernel/cgroup.c | 2 + kernel/cgroup_timer_slack.c | 127 + kernel/cpu.c | 6 +- kernel/events/core.c | 4 +- kernel/exit.c | 2 +- kernel/fork.c | 8 +- kernel/freezer.c | 12 + kernel/futex.c | 7 +- kernel/hrtimer.c | 11 +- kernel/kexec.c | 4 + kernel/lockdep.c | 17 +- kernel/module.c | 8 +- kernel/power/process.c | 25 +- kernel/printk.c | 6 +- kernel/profile.c | 2 +- kernel/rcutorture.c | 6 +- kernel/rcutree.c | 6 +- kernel/rcutree.h | 6 +- kernel/rcutree_plugin.h | 14 +- kernel/relay.c | 2 +- kernel/sched/core.c | 39 +- kernel/sched/debug.c | 3 + kernel/sched/fair.c | 2 +- kernel/sched/features.h | 2 +- kernel/sched/rt.c | 3 +- kernel/sched/sched.h | 40 + kernel/signal.c | 2 +- kernel/smp.c | 2 +- kernel/softirq.c | 8 +- kernel/stop_machine.c | 4 +- kernel/sys.c | 3 + kernel/sysctl.c | 2 +- kernel/time/tick-sched.c | 6 +- kernel/timer.c | 10 +- kernel/watchdog.c | 4 +- kernel/workqueue.c | 20 +- lib/Makefile | 3 +- lib/int_sqrt.c | 32 +- lib/memcopy.c | 403 ++ lib/percpu_counter.c | 2 +- lib/string.c | 29 +- mm/ksm.c | 4 +- mm/memcontrol.c | 2 +- mm/mempolicy.c | 41 +- mm/page-writeback.c | 23 +- mm/page_cgroup.c | 10 +- mm/slab.c | 10 +- mm/slub.c | 6 +- mm/vmscan.c | 2 +- mm/vmstat.c | 6 +- net/bluetooth/hci_conn.c | 4 +- net/core/flow.c | 4 +- net/ipv4/tcp_input.c | 3 +- net/iucv/iucv.c | 2 +- net/netfilter/nf_conntrack_h323_main.c | 8 +- net/socket.c | 4 +- net/sunrpc/sched.c | 2 +- net/sunrpc/xdr.c | 6 + net/unix/af_unix.c | 11 +- net/wireless/reg.c | 10 + release/Flashable-flo-AOSP/.gitignore | 1 + release/aroma/META-INF/CERT.RSA | Bin 0 -> 1714 bytes release/aroma/META-INF/CERT.SF | 6232 +++++++++++++++++ release/aroma/META-INF/MANIFEST.MF | 6231 ++++++++++++++++ .../META-INF/com/google/android/aroma-config | 288 + .../com/google/android/aroma/agreement.txt | 9 + .../com/google/android/aroma/changelog.txt | 30 + .../com/google/android/aroma/fonts/big.png | Bin 0 -> 10938 bytes .../com/google/android/aroma/fonts/small.png | Bin 0 -> 5723 bytes .../com/google/android/aroma/glitch.png | Bin 0 -> 196355 bytes .../google/android/aroma/icons/agreement.png | Bin 0 -> 4228 bytes .../com/google/android/aroma/icons/alert.png | Bin 0 -> 3410 bytes .../com/google/android/aroma/icons/apex.png | Bin 0 -> 14738 bytes .../com/google/android/aroma/icons/apps.png | Bin 0 -> 10928 bytes .../android/aroma/icons/battery_aosp_blue.png | Bin 0 -> 529 bytes .../aroma/icons/battery_aosp_green.png | Bin 0 -> 528 bytes .../android/aroma/icons/battery_blue.png | Bin 0 -> 607 bytes .../android/aroma/icons/battery_blue_no.png | Bin 0 -> 564 bytes .../android/aroma/icons/battery_gauge.png | Bin 0 -> 9734 bytes .../aroma/icons/battery_gauge_wide.png | Bin 0 -> 12979 bytes .../android/aroma/icons/battery_green.png | Bin 0 -> 642 bytes .../android/aroma/icons/battery_vertical.png | Bin 0 -> 3208 bytes .../android/aroma/icons/battery_white.png | Bin 0 -> 2768 bytes .../aroma/icons/battery_white_stock.png | Bin 0 -> 1130 bytes .../com/google/android/aroma/icons/device.png | Bin 0 -> 4712 bytes .../com/google/android/aroma/icons/fbhome.png | Bin 0 -> 16939 bytes .../com/google/android/aroma/icons/htc.png | Bin 0 -> 1140 bytes .../com/google/android/aroma/icons/info.png | Bin 0 -> 5767 bytes .../google/android/aroma/icons/install.png | Bin 0 -> 5577 bytes .../com/google/android/aroma/icons/keyb.png | Bin 0 -> 3131 bytes .../com/google/android/aroma/icons/nova.png | Bin 0 -> 16323 bytes .../android/aroma/icons/personalize.png | Bin 0 -> 5741 bytes .../google/android/aroma/icons/security.png | Bin 0 -> 7180 bytes .../google/android/aroma/icons/signal_att.png | Bin 0 -> 5595 bytes .../android/aroma/icons/signal_highdef.png | Bin 0 -> 2497 bytes .../android/aroma/icons/signal_stock.png | Bin 0 -> 575 bytes .../android/aroma/icons/signal_white.png | Bin 0 -> 2574 bytes .../android/aroma/icons/weather_sense4.png | Bin 0 -> 52273 bytes .../android/aroma/icons/weather_stock.png | Bin 0 -> 8152 bytes .../android/aroma/icons/weather_thick.png | Bin 0 -> 8016 bytes .../android/aroma/icons/weather_weezle.png | Bin 0 -> 54159 bytes .../android/aroma/ttf/Roboto-Regular.ttf | Bin 0 -> 172756 bytes .../META-INF/com/google/android/update-binary | Bin 0 -> 627620 bytes .../google/android/update-binary-installer | Bin 0 -> 232504 bytes .../com/google/android/updater-script | 233 + release/aroma/boot/abootimg | Bin 0 -> 76392 bytes release/aroma/boot/cmdline.cfg | 6 + release/aroma/boot/edit_ramdisk.sh | 39 + release/aroma/boot/max_oc.sh | 240 + release/aroma/config/buildconfig.sh | 117 + release/aroma/config/busybox | Bin 0 -> 478912 bytes release/aroma/config/compatibility.sh | 13 + release/aroma/config/settings.conf | 6 + release/aroma/config/systemcheck.sh | 15 + release/aroma/system/bin/fstrim | Bin 0 -> 11189 bytes release/aroma/system/etc/init.d/99glitch | 127 + .../META-INF/com/google/android/update-binary | Bin 0 -> 194596 bytes .../com/google/android/updater-script | 39 + release/zimage/kernel/busybox | Bin 0 -> 478912 bytes release/zimage/kernel/compatibility.sh | 9 + release/zimage/kernel/edit_ramdisk.sh | 61 + release/zimage/kernel/mkbootimg | Bin 0 -> 64076 bytes release/zimage/kernel/mkbootimg.sh | 6 + release/zimage/kernel/unpackbootimg | Bin 0 -> 58952 bytes scripts/mod/modpost.c | 51 +- scripts/setlocalversion | 1 - security/selinux/selinuxfs.c | 1 + sound/soc/codecs/Kconfig | 13 + sound/soc/codecs/Makefile | 5 + sound/soc/codecs/sound_control_3_gpl.c | 276 + sound/soc/codecs/sound_control_gpl.c | 325 + sound/soc/codecs/wcd9310.c | 31 +- sound/usb/mixer.c | 8 +- tools/usb/ffs-test.c | 2 +- 626 files changed, 44148 insertions(+), 2810 deletions(-) create mode 100644 Documentation/cgroups/timer_slack.txt create mode 100644 arch/arm/crypto/Makefile create mode 100644 arch/arm/crypto/aes-armv4.S create mode 100644 arch/arm/crypto/aes_glue.c create mode 100644 arch/arm/crypto/sha1-armv4-large.S create mode 100644 arch/arm/crypto/sha1_glue.c create mode 100644 arch/arm/include/asm/rwsem.h create mode 100644 arch/arm/mach-msm/fastchg.c create mode 100644 arch/arm/mach-msm/intelli_plug.c create mode 100644 arch/arm/mach-msm/vdd_limits_8064.h create mode 100644 block/fiops-iosched.c create mode 100644 block/sio-iosched.c create mode 100644 drivers/cpufreq/cpufreq_intellidemand.c create mode 100644 drivers/staging/cpupower/Kconfig create mode 100644 drivers/staging/cpupower/Makefile create mode 100644 drivers/staging/cpupower/cpu_power.c create mode 100644 frandom/Makefile create mode 100644 frandom/frandom.c create mode 100644 fs/dyn_sync_cntrl.c create mode 100644 fs/exfat/Kconfig create mode 100644 fs/exfat/Makefile create mode 100644 fs/exfat/Makefile.module create mode 100644 fs/exfat/README.md create mode 100644 fs/exfat/exfat.h create mode 100644 fs/exfat/exfat_api.c create mode 100644 fs/exfat/exfat_api.h create mode 100644 fs/exfat/exfat_blkdev.c create mode 100644 fs/exfat/exfat_blkdev.h create mode 100644 fs/exfat/exfat_cache.c create mode 100644 fs/exfat/exfat_cache.h create mode 100644 fs/exfat/exfat_config.h create mode 100644 fs/exfat/exfat_core.c create mode 100644 fs/exfat/exfat_data.c create mode 100644 fs/exfat/exfat_data.h create mode 100644 fs/exfat/exfat_global.c create mode 100644 fs/exfat/exfat_global.h create mode 100644 fs/exfat/exfat_nls.c create mode 100644 fs/exfat/exfat_nls.h create mode 100644 fs/exfat/exfat_oal.c create mode 100644 fs/exfat/exfat_oal.h create mode 100644 fs/exfat/exfat_part.h create mode 100644 fs/exfat/exfat_super.c create mode 100644 fs/exfat/exfat_super.h create mode 100644 fs/exfat/exfat_upcase.c create mode 100644 fs/exfat/exfat_version.h create mode 100755 glitch.sh create mode 100644 include/linux/fastchg.h create mode 100644 include/linux/memcopy.h create mode 100644 include/linux/power/cpupower.h create mode 100644 include/linux/sweep2wake.h create mode 100644 kernel/cgroup_timer_slack.c create mode 100644 lib/memcopy.c create mode 100644 release/Flashable-flo-AOSP/.gitignore create mode 100755 release/aroma/META-INF/CERT.RSA create mode 100755 release/aroma/META-INF/CERT.SF create mode 100755 release/aroma/META-INF/MANIFEST.MF create mode 100755 release/aroma/META-INF/com/google/android/aroma-config create mode 100755 release/aroma/META-INF/com/google/android/aroma/agreement.txt create mode 100755 release/aroma/META-INF/com/google/android/aroma/changelog.txt create mode 100755 release/aroma/META-INF/com/google/android/aroma/fonts/big.png create mode 100755 release/aroma/META-INF/com/google/android/aroma/fonts/small.png create mode 100644 release/aroma/META-INF/com/google/android/aroma/glitch.png create mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/agreement.png create mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/alert.png create mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/apex.png create mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/apps.png create mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/battery_aosp_blue.png create mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/battery_aosp_green.png create mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/battery_blue.png create mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/battery_blue_no.png create mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/battery_gauge.png create mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/battery_gauge_wide.png create mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/battery_green.png create mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/battery_vertical.png create mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/battery_white.png create mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/battery_white_stock.png create mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/device.png create mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/fbhome.png create mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/htc.png create mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/info.png create mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/install.png create mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/keyb.png create mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/nova.png create mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/personalize.png create mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/security.png create mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/signal_att.png create mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/signal_highdef.png create mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/signal_stock.png create mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/signal_white.png create mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/weather_sense4.png create mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/weather_stock.png create mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/weather_thick.png create mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/weather_weezle.png create mode 100755 release/aroma/META-INF/com/google/android/aroma/ttf/Roboto-Regular.ttf create mode 100755 release/aroma/META-INF/com/google/android/update-binary create mode 100755 release/aroma/META-INF/com/google/android/update-binary-installer create mode 100755 release/aroma/META-INF/com/google/android/updater-script create mode 100755 release/aroma/boot/abootimg create mode 100755 release/aroma/boot/cmdline.cfg create mode 100755 release/aroma/boot/edit_ramdisk.sh create mode 100755 release/aroma/boot/max_oc.sh create mode 100755 release/aroma/config/buildconfig.sh create mode 100755 release/aroma/config/busybox create mode 100644 release/aroma/config/compatibility.sh create mode 100755 release/aroma/config/settings.conf create mode 100755 release/aroma/config/systemcheck.sh create mode 100755 release/aroma/system/bin/fstrim create mode 100755 release/aroma/system/etc/init.d/99glitch create mode 100755 release/zimage/META-INF/com/google/android/update-binary create mode 100755 release/zimage/META-INF/com/google/android/updater-script create mode 100644 release/zimage/kernel/busybox create mode 100644 release/zimage/kernel/compatibility.sh create mode 100644 release/zimage/kernel/edit_ramdisk.sh create mode 100644 release/zimage/kernel/mkbootimg create mode 100644 release/zimage/kernel/mkbootimg.sh create mode 100644 release/zimage/kernel/unpackbootimg create mode 100644 sound/soc/codecs/sound_control_3_gpl.c create mode 100644 sound/soc/codecs/sound_control_gpl.c diff --git a/Documentation/HOWTO b/Documentation/HOWTO index f7ade3b3b40..59c080f084e 100644 --- a/Documentation/HOWTO +++ b/Documentation/HOWTO @@ -218,16 +218,16 @@ The development process Linux kernel development process currently consists of a few different main kernel "branches" and lots of different subsystem-specific kernel branches. These different branches are: - - main 2.6.x kernel tree - - 2.6.x.y -stable kernel tree - - 2.6.x -git kernel patches + - main 3.x kernel tree + - 3.x.y -stable kernel tree + - 3.x -git kernel patches - subsystem specific kernel trees and patches - - the 2.6.x -next kernel tree for integration tests + - the 3.x -next kernel tree for integration tests -2.6.x kernel tree +3.x kernel tree ----------------- -2.6.x kernels are maintained by Linus Torvalds, and can be found on -kernel.org in the pub/linux/kernel/v2.6/ directory. Its development +3.x kernels are maintained by Linus Torvalds, and can be found on +kernel.org in the pub/linux/kernel/v3.x/ directory. Its development process is as follows: - As soon as a new kernel is released a two weeks window is open, during this period of time maintainers can submit big diffs to @@ -262,20 +262,20 @@ mailing list about kernel releases: released according to perceived bug status, not according to a preconceived timeline." -2.6.x.y -stable kernel tree +3.x.y -stable kernel tree --------------------------- -Kernels with 4-part versions are -stable kernels. They contain +Kernels with 3-part versions are -stable kernels. They contain relatively small and critical fixes for security problems or significant -regressions discovered in a given 2.6.x kernel. +regressions discovered in a given 3.x kernel. This is the recommended branch for users who want the most recent stable kernel and are not interested in helping test development/experimental versions. -If no 2.6.x.y kernel is available, then the highest numbered 2.6.x +If no 3.x.y kernel is available, then the highest numbered 3.x kernel is the current stable kernel. -2.6.x.y are maintained by the "stable" team , and +3.x.y are maintained by the "stable" team , and are released as needs dictate. The normal release period is approximately two weeks, but it can be longer if there are no pressing problems. A security-related problem, instead, can cause a release to happen almost @@ -285,7 +285,7 @@ The file Documentation/stable_kernel_rules.txt in the kernel tree documents what kinds of changes are acceptable for the -stable tree, and how the release process works. -2.6.x -git patches +3.x -git patches ------------------ These are daily snapshots of Linus' kernel tree which are managed in a git repository (hence the name.) These patches are usually released @@ -317,13 +317,13 @@ revisions to it, and maintainers can mark patches as under review, accepted, or rejected. Most of these patchwork sites are listed at http://patchwork.kernel.org/. -2.6.x -next kernel tree for integration tests +3.x -next kernel tree for integration tests --------------------------------------------- -Before updates from subsystem trees are merged into the mainline 2.6.x +Before updates from subsystem trees are merged into the mainline 3.x tree, they need to be integration-tested. For this purpose, a special testing repository exists into which virtually all subsystem trees are pulled on an almost daily basis: - http://git.kernel.org/?p=linux/kernel/git/sfr/linux-next.git + http://git.kernel.org/?p=linux/kernel/git/next/linux-next.git http://linux.f-seidel.de/linux-next/pmwiki/ This way, the -next kernel gives a summary outlook onto what will be diff --git a/Documentation/cgroups/timer_slack.txt b/Documentation/cgroups/timer_slack.txt new file mode 100644 index 00000000000..6e9cb6a1aaa --- /dev/null +++ b/Documentation/cgroups/timer_slack.txt @@ -0,0 +1,72 @@ +Timer Slack Controller +====================== + +Overview +-------- + +Every task_struct has timer_slack_ns value. This value is used to round +up poll() and select() timeout values. This feature can be useful in +mobile environment where combined wakeups are desired. + +Originally, prctl() was the only way to change timer slack value of +a process. So you was not able change timer slack value of another +process. + +cgroup subsys "timer_slack" implements timer slack controller. It +provides a way to set minimal timer slack value for a group of tasks. +If a task belongs to a cgroup with minimal timer slack value higher than +task's value, cgroup's value will be applied. + +Timer slack controller allows to implement setting timer slack value of +a process based on a policy. For example, you can create foreground and +background cgroups and move tasks between them based on system state. + +User interface +-------------- + +To get timer slack controller functionality you need to enable it in +kernel configuration: + +CONFIG_CGROUP_TIMER_SLACK=y + +The controller provides two files: + +# mount -t cgroup -o timer_slack none /sys/fs/cgroup +# ls /sys/fs/cgroup/timer_slack.* +/sys/fs/cgroup/timer_slack.effective_slack_ns +/sys/fs/cgroup/timer_slack.min_slack_ns + +By default timer_slack.min_slack_ns is 0: + +# cat /sys/fs/cgroup/timer_slack.min_slack_ns +0 + +You can set it to some value: + +# echo 50000 > /sys/fs/cgroup/timer_slack.min_slack_ns +# cat /sys/fs/cgroup/timer_slack.min_slack_ns +50000 + +Tasks still can set task's value below 50000 using prctl(), but in this +case cgroup's value will be applied. + +Timer slack controller supports hierarchical groups. + +# mkdir /sys/fs/cgroup/a +# cat /sys/fs/cgroup/a/timer_slack.min_slack_ns +50000 +# echo 70000 > /sys/fs/cgroup/a/timer_slack.min_slack_ns +# cat /sys/fs/cgroup/a/timer_slack.min_slack_ns +70000 + +You can set any value you want, but effective value will the highest value +up by hierarchy. You can see effective timer slack value for the cgroup from +timer_slack.effective_slack_ns file: + +# cat /sys/fs/cgroup/a/timer_slack.effective_slack_ns +70000 +# echo 100000 > /sys/fs/cgroup/timer_slack.min_slack_ns +# cat /sys/fs/cgroup/a/timer_slack.min_slack_ns +70000 +# cat /sys/fs/cgroup/a/timer_slack.effective_slack_ns +100000 diff --git a/Makefile b/Makefile index 75b36ae3c7d..ba3b12175ce 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 4 -SUBLEVEL = 0 +SUBLEVEL = 1 EXTRAVERSION = NAME = Saber-toothed Squirrel @@ -245,8 +245,13 @@ CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \ HOSTCC = gcc HOSTCXX = g++ +ifdef CONFIG_CC_OPTIMIZE_ALOT +HOSTCFLAGS = -Wall -Wmissing-prototypes -Wstrict-prototypes -O3 -fgcse-lm -fgcse-sm -fsched-spec-load -fforce-addr -fsingle-precision-constant -ftree-vectorize -fomit-frame-pointer +HOSTCXXFLAGS = -O3 -fgcse-lm -fgcse-sm -fsched-spec-load -fforce-addr -fsingle-precision-constant -mcpu=cortex-a15 -mtune=cortex-a15 -marm -mfpu=neon-vfpv4 -ftree-vectorize -mvectorize-with-neon-quad +else HOSTCFLAGS = -Wall -Wmissing-prototypes -Wstrict-prototypes -O2 -fomit-frame-pointer HOSTCXXFLAGS = -O2 +endif # Decide whether to build built-in, modular, or both. # Normally, just do built-in. @@ -351,12 +356,23 @@ CC = $(srctree)/scripts/gcc-wrapper.py $(REAL_CC) CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ \ -Wbitwise -Wno-return-void $(CF) -CFLAGS_MODULE = -AFLAGS_MODULE = -LDFLAGS_MODULE = -CFLAGS_KERNEL = -AFLAGS_KERNEL = +ifdef CONFIG_CC_OPTIMIZE_ALOT +MODFLAGS = -DMODULE -O2 -fgcse-lm -fgcse-sm -fsched-spec-load -fforce-addr -fsingle-precision-constant -mcpu=cortex-a15 -mtune=cortex-a15 -fno-pic -marm -mfpu=neon-vfpv4 -ftree-vectorize -mvectorize-with-neon-quad +else +MODFLAGS = -DMODULE -fgcse-lm -fgcse-sm -fsched-spec-load -fforce-addr -ffast-math -fsingle-precision-constant -mtune=cortex-a8 -fno-pic -marm -mfpu=neon -ftree-vectorize -mvectorize-with-neon-quad +endif + +CFLAGS_MODULE = $(MODFLAGS) +AFLAGS_MODULE = $(MODFLAGS) +LDFLAGS_MODULE = -T $(srctree)/scripts/module-common.lds +ifdef CONFIG_CC_OPTIMIZE_ALOT +CFLAGS_KERNEL = -O3 -fgcse-lm -fgcse-sm -fsched-spec-load -fforce-addr -ffast-math -fsingle-precision-constant -mtune=cortex-a15 -marm -mfpu=neon-vfpv4 -funswitch-loops -mvectorize-with-neon-quad +AFLAGS_KERNEL = -O3 -fgcse-lm -fgcse-sm -fsched-spec-load -fforce-addr -ffast-math -fsingle-precision-constant -mtune=cortex-a15 -marm -mfpu=neon-vfpv4 -funswitch-loops -mvectorize-with-neon-quad +else +CFLAGS_KERNEL = -O2 -fgcse-lm -fgcse-sm -fsched-spec-load -fforce-addr -ffast-math -fsingle-precision-constant -mtune=cortex-a15 -marm -mfpu=neon-vfpv4 -funswitch-loops -mvectorize-with-neon-quad +AFLAGS_KERNEL = CFLAGS_GCOV = -fprofile-arcs -ftest-coverage +endif # Use LINUXINCLUDE when you must reference the include/ directory. @@ -366,18 +382,27 @@ LINUXINCLUDE := -I$(srctree)/arch/$(hdr-arch)/include \ $(if $(KBUILD_SRC), -I$(srctree)/include) \ -include $(srctree)/include/linux/kconfig.h +ifdef CONFIG_CC_OPTIMIZE_ALOT +KBUILD_CPPFLAGS := -D__KERNEL__ -O3 -fgcse-lm -fgcse-sm -fsched-spec-load -fforce-addr -fsingle-precision-constant -mcpu=cortex-a15 -mtune=cortex-a15 -marm -mfpu=neon-vfpv4 -ftree-vectorize -mvectorize-with-neon-quad +else KBUILD_CPPFLAGS := -D__KERNEL__ +endif KBUILD_CFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \ -fno-strict-aliasing -fno-common \ -Werror-implicit-function-declaration \ - -Wno-format-security \ - -fno-delete-null-pointer-checks + -Wno-format-security -Wno-unused-function -Wno-array-bounds -Wno-uninitialized \ + -fno-delete-null-pointer-checks -Wno-unused-variable -Wno-maybe-uninitialized -Wno-cpp -Wno-declaration-after-statement +ifdef CONFIG_CC_OPTIMIZE_ALOT +KBUILD_AFLAGS_KERNEL := -O3 -fgcse-lm -fgcse-sm -fsched-spec-load -fforce-addr -fsingle-precision-constant -mcpu=cortex-a15 -mtune=cortex-a15 -marm -mfpu=neon-vfpv4 -ftree-vectorize -mvectorize-with-neon-quad +KBUILD_CFLAGS_KERNEL := -O3 -fgcse-lm -fgcse-sm -fsched-spec-load -fforce-addr -fsingle-precision-constant -mcpu=cortex-a15 -mtune=cortex-a15 -marm -mfpu=neon-vfpv4 -ftree-vectorize -mvectorize-with-neon-quad +else KBUILD_AFLAGS_KERNEL := KBUILD_CFLAGS_KERNEL := +endif KBUILD_AFLAGS := -D__ASSEMBLY__ KBUILD_AFLAGS_MODULE := -DMODULE -KBUILD_CFLAGS_MODULE := -DMODULE +KBUILD_CFLAGS_MODULE := -DMODULE -fgcse-lm -fgcse-sm -fsched-spec-load -fforce-addr -ffast-math -fsingle-precision-constant -mcpu=cortex-a15 -mtune=cortex-a15 -mfpu=neon-vfpv4 -ftree-vectorize -funswitch-loops -Wno-cpp KBUILD_LDFLAGS_MODULE := -T $(srctree)/scripts/module-common.lds # Read KERNELRELEASE from include/config/kernel.release (if it exists) @@ -564,9 +589,16 @@ all: vmlinux ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE KBUILD_CFLAGS += -Os -else +endif +ifdef CONFIG_CC_OPTIMIZE_DEFAULT KBUILD_CFLAGS += -O2 endif +ifdef CONFIG_CC_OPTIMIZE_ALOT +KBUILD_CFLAGS += -O3 +endif +ifdef CONFIG_CC_OPTIMIZE_FAST +KBUILD_CFLAGS += -Ofast +endif include $(srctree)/arch/$(SRCARCH)/Makefile @@ -712,7 +744,7 @@ export mod_strip_cmd ifeq ($(KBUILD_EXTMOD),) -core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/ +core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/ frandom/ vmlinux-dirs := $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \ $(core-y) $(core-m) $(drivers-y) $(drivers-m) \ diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c index 50d438db1f6..619471c79c2 100644 --- a/arch/alpha/kernel/smp.c +++ b/arch/alpha/kernel/smp.c @@ -116,7 +116,7 @@ wait_boot_cpu_to_stop(int cpuid) /* * Where secondaries begin a life of C. */ -void __cpuinit +void smp_callin(void) { int cpuid = hard_smp_processor_id(); @@ -194,7 +194,7 @@ wait_for_txrdy (unsigned long cpumask) * Send a message to a secondary's console. "START" is one such * interesting message. ;-) */ -static void __cpuinit +static void send_secondary_console_msg(char *str, int cpuid) { struct percpu_struct *cpu; @@ -285,7 +285,7 @@ recv_secondary_console_msg(void) /* * Convince the console to have a secondary cpu begin execution. */ -static int __cpuinit +static int secondary_cpu_start(int cpuid, struct task_struct *idle) { struct percpu_struct *cpu; @@ -356,7 +356,7 @@ secondary_cpu_start(int cpuid, struct task_struct *idle) /* * Bring one cpu online. */ -static int __cpuinit +static int smp_boot_one_cpu(int cpuid) { struct task_struct *idle; @@ -486,7 +486,7 @@ smp_prepare_boot_cpu(void) { } -int __cpuinit +int __cpu_up(unsigned int cpu) { smp_boot_one_cpu(cpu); diff --git a/arch/alpha/kernel/traps.c b/arch/alpha/kernel/traps.c index 80d987c0e9a..c28d03df7d3 100644 --- a/arch/alpha/kernel/traps.c +++ b/arch/alpha/kernel/traps.c @@ -32,7 +32,7 @@ static int opDEC_fix; -static void __cpuinit +static void opDEC_check(void) { __asm__ __volatile__ ( @@ -1066,7 +1066,7 @@ do_entUnaUser(void __user * va, unsigned long opcode, return; } -void __cpuinit +void trap_init(void) { /* Tell PAL-code what global pointer we want in the kernel. */ diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index c450e1db066..a54d7ab9e93 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -160,10 +160,9 @@ config ARM_TICKET_LOCKS config RWSEM_GENERIC_SPINLOCK bool - default y config RWSEM_XCHGADD_ALGORITHM - bool + def_bool y config ARCH_HAS_ILOG2_U32 bool @@ -1582,6 +1581,7 @@ config ARM_CPU_TOPOLOGY config SCHED_MC bool "Multi-core scheduler support" depends on ARM_CPU_TOPOLOGY + default y help Multi-core scheduler support improves the CPU scheduler's decision making when dealing with multi-core CPU chips at a cost of slightly @@ -1590,6 +1590,7 @@ config SCHED_MC config SCHED_SMT bool "SMT scheduler support" depends on ARM_CPU_TOPOLOGY + default y help Improves the CPU scheduler's decision making when dealing with MultiThreading at a cost of slightly increased overhead in some @@ -2180,6 +2181,32 @@ config ATAGS_PROC Should the atags used to boot the kernel be exported in an "atags" file in procfs. Useful with kexec. +config KEXEC_HARDBOOT + bool "Support hard booting to a kexec kernel" + depends on KEXEC + help + Allows hard booting (i.e., with a full hardware reboot) to a kernel + previously loaded in memory by kexec. This works around the problem of + soft-booted kernel hangs due to improper device shutdown and/or + reinitialization. Support is comprised of two components: + + First, a "hardboot" flag is added to the kexec syscall to force a hard + reboot in relocate_new_kernel() (which requires machine-specific assembly + code). This also requires the kexec userspace tool to load the kexec'd + kernel in memory region left untouched by the bootloader (i.e., not + explicitly cleared and not overwritten by the boot kernel). Just prior + to reboot, the kexec kernel arguments are stashed in a machine-specific + memory page that must also be preserved. Note that this hardboot page + need not be reserved during regular kernel execution. + + Second, the zImage decompresor of the boot (bootloader-loaded) kernel is + modified to check the hardboot page for fresh kexec arguments, and if + present, attempts to jump to the kexec'd kernel preserved in memory. + + Note that hardboot support is only required in the boot kernel and any + kernel capable of performing a hardboot kexec. It is _not_ required by a + kexec'd kernel. + config CRASH_DUMP bool "Build kdump crash kernel (EXPERIMENTAL)" depends on EXPERIMENTAL diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 81b5dc9c829..ded63846c4a 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -17,7 +17,7 @@ endif OBJCOPYFLAGS :=-O binary -R .comment -S GZFLAGS :=-9 -#KBUILD_CFLAGS +=-pipe +KBUILD_CFLAGS +=-pipe # Explicitly specifiy 32-bit ARM ISA since toolchain default can be -mthumb: KBUILD_CFLAGS +=$(call cc-option,-marm,) @@ -57,7 +57,7 @@ comma = , # Note that GCC does not numerically define an architecture version # macro, but instead defines a whole series of macros which makes # testing for a specific architecture or later rather impossible. -arch-$(CONFIG_CPU_32v7) :=-D__LINUX_ARM_ARCH__=7 $(call cc-option,-march=armv7-a,-march=armv5t -Wa$(comma)-march=armv7-a) +arch-$(CONFIG_CPU_32v7) :=-D__LINUX_ARM_ARCH__=7 $(call cc-option,-mcpu=cortex-a15 -mfpu=neon -ftree-vectorize -Wa$(comma)-march=armv7-a) arch-$(CONFIG_CPU_32v6) :=-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6,-march=armv5t -Wa$(comma)-march=armv6) # Only override the compiler option if ARMv6. The ARMv6K extensions are # always available in ARMv7 @@ -97,9 +97,9 @@ else CFLAGS_ABI :=$(call cc-option,-mapcs-32,-mabi=apcs-gnu) $(call cc-option,-mno-thumb-interwork,) endif -ifeq ($(CONFIG_ARM_UNWIND),y) -CFLAGS_ABI +=-funwind-tables -endif +#ifeq ($(CONFIG_ARM_UNWIND),y) +#CFLAGS_ABI +=-funwind-tables +#endif ifeq ($(CONFIG_THUMB2_KERNEL),y) AFLAGS_AUTOIT :=$(call as-option,-Wa$(comma)-mimplicit-it=always,-Wa$(comma)-mauto-it) @@ -251,6 +251,7 @@ core-$(CONFIG_VFP) += arch/arm/vfp/ # If we have a machine-specific directory, then include it in the build. core-y += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/ core-y += arch/arm/net/ +core-y += arch/arm/crypto/ core-y += $(machdirs) $(platdirs) drivers-$(CONFIG_OPROFILE) += arch/arm/oprofile/ diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile index bb267562e7e..2ceaab327ac 100644 --- a/arch/arm/boot/compressed/Makefile +++ b/arch/arm/boot/compressed/Makefile @@ -10,20 +10,15 @@ OBJS = # to minimise that number of bocks that have to be read in # order to load it. ifeq ($(CONFIG_ZBOOT_ROM_MMCIF),y) +ifeq ($(CONFIG_ARCH_SH7372),y) OBJS += mmcif-sh7372.o endif - -# Ensure that SDHI loader code appears early in the image -# to minimise that number of bocks that have to be read in -# order to load it. -ifeq ($(CONFIG_ZBOOT_ROM_SH_MOBILE_SDHI),y) -OBJS += sdhi-shmobile.o -OBJS += sdhi-sh7372.o endif AFLAGS_head.o += -DTEXT_OFFSET=$(TEXT_OFFSET) -HEAD = head.o -OBJS += misc.o decompress.o +HEAD = head.o +OBJS += misc.o decompress.o + FONTC = $(srctree)/drivers/video/console/font_acorn_8x8.c # string library code (-Os is enforced to keep it much smaller) @@ -130,7 +125,7 @@ asflags-y := -Wa,-march=all # Supply kernel BSS size to the decompressor via a linker symbol. KBSS_SZ = $(shell $(CROSS_COMPILE)size $(obj)/../../../../vmlinux | \ - awk 'END{print $$3}') + awk 'END{print $$3}') LDFLAGS_vmlinux = --defsym _kernel_bss_size=$(KBSS_SZ) # Supply ZRELADDR to the decompressor via a linker symbol. ifneq ($(CONFIG_AUTO_ZRELADDR),y) @@ -197,4 +192,4 @@ $(obj)/font.c: $(FONTC) $(call cmd,shipped) $(obj)/vmlinux.lds: $(obj)/vmlinux.lds.in arch/arm/boot/Makefile $(KCONFIG_CONFIG) - @sed "$(SEDFLAGS)" < $< > $@ + @sed "$(SEDFLAGS)" < $< > $@ \ No newline at end of file diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index 64a6d6f8d29..f6fa5df63fc 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S @@ -10,6 +10,11 @@ */ #include +#ifdef CONFIG_KEXEC_HARDBOOT + #include + #include +#endif + /* * Debugging stuff * @@ -135,6 +140,97 @@ start: 1: mov r7, r1 @ save architecture ID mov r8, r2 @ save atags pointer +#ifdef CONFIG_KEXEC_HARDBOOT + /* Check hardboot page for a kexec kernel. */ + ldr r3, =KEXEC_HB_PAGE_ADDR + ldr r0, [r3] + ldr r1, =KEXEC_HB_PAGE_MAGIC + teq r0, r1 + bne not_booting_other + + /* Clear hardboot page magic to avoid boot loop. */ + mov r0, #0 + str r0, [r3] + +/* Copy the kernel tagged list (atags): + * + * The kernel requires atags to be located in a direct-mapped region, + * usually below the kernel in the first 16 kB of RAM. If they're above + * (the start of) the kernel, they need to be copied to a suitable + * location, e.g., the machine-defined params_phys. + * + * The assumption is that the tags will only be "out of place" if the + * decompressor code is also, so copying is implemented only in the "won't + * overwrite" case (which should be fixed). Still need to make sure that + * the copied tags don't overwrite either the kernel or decompressor code + * (or rather, the remainder of it since everything up to here has already + * been executed). + * + * Vojtech Bocek : I've moved atags copying from guest + * kernel to the host and rewrote it from C to assembler in order to remove + * the need for guest kernel to be patched. I don't know assembler very well, + * so it doesn't look very good and I have no idea if I didn't accidentally + * break something, causing problems down the road. It's worked every time + * and I didn't notice any problems so far though. + * + * r4: zreladdr (kernel start) + * r8: kexec_boot_atags + * r2: boot_atags */ + ldr r8, [r3, #12] @ kexec_boot_atags (r2: boot_atags) + ldr r4, =zreladdr @ zreladdr + + /* No need to copy atags if they're already below kernel */ + cmp r8, r4 + blo no_atags_cpy + + /* r0: min(zreladdr, pc) */ + mov r0, pc + cmp r4, r0 + movlo r0, r4 + + /* Compute max space for atags, if max <= 0 don't copy. */ + subs r5, r0, r2 @ max = min(zreladdr, pc) - dest + bls no_atags_cpy + + /* Copy atags to params_phys. */ + /* r8 src, r2 dest, r5 max */ + + ldr r0, [r8] @ first tag size + cmp r0, #0 + moveq r4, #8 + beq catags_empty + mov r4, r8 + +catags_foreach: + lsl r0, r0, #2 @ Multiply by 4 + ldr r0, [r4, r0]! @ Load next tag size to r0 and address to r4 + cmp r0, #0 + bne catags_foreach + + rsb r4, r8, r4 @ r4 -= r8 (get only size) + add r4, r4, #8 @ add size of the last tag +catags_empty: + cmp r5, r4 @ if(max <= size) + bcc no_atags_cpy + + mov r5, #0 @ iterator +catags_cpy: + ldr r0, [r8, r5] + str r0, [r2, r5] + add r5, r5, #4 + cmp r5, r4 + blo catags_cpy + +no_atags_cpy: + /* Load boot arguments and jump to kexec kernel. */ + ldr r1, [r3, #8] @ kexec_mach_type + ldr pc, [r3, #4] @ kexec_start_address + + .ltorg + +not_booting_other: +#endif + #ifndef __ARM_ARCH_2__ /* * Booting from Angel - need to enter SVC mode and disable diff --git a/arch/arm/boot/dts/tegra-cardhu.dts b/arch/arm/boot/dts/tegra-cardhu.dts index ac3fb755845..631a86cb11a 100644 --- a/arch/arm/boot/dts/tegra-cardhu.dts +++ b/arch/arm/boot/dts/tegra-cardhu.dts @@ -64,7 +64,7 @@ status = "disable"; }; - sdhci@78000400 { + sdhci@78000600 { support-8bit; }; }; diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c index 9dd434700a9..56272070681 100644 --- a/arch/arm/common/gic.c +++ b/arch/arm/common/gic.c @@ -565,7 +565,7 @@ static void __init gic_dist_init(struct gic_chip_data *gic) mb(); } -static void __cpuinit gic_cpu_init(struct gic_chip_data *gic) +static void gic_cpu_init(struct gic_chip_data *gic) { void __iomem *dist_base = gic_data_dist_base(gic); void __iomem *base = gic_data_cpu_base(gic); @@ -948,7 +948,7 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start, gic_pm_init(gic); } -void __cpuinit gic_secondary_init(unsigned int gic_nr) +void gic_secondary_init(unsigned int gic_nr) { BUG_ON(gic_nr >= MAX_GIC_NR); diff --git a/arch/arm/configs/flo_defconfig b/arch/arm/configs/flo_defconfig index 15454e0ca0f..3506b40fda5 100644 --- a/arch/arm/configs/flo_defconfig +++ b/arch/arm/configs/flo_defconfig @@ -1,122 +1,870 @@ +# +# Automatically generated file; DO NOT EDIT. +# Linux/arm 3.4.1 Kernel Configuration +# +CONFIG_ARM=y +CONFIG_ARM_HAS_SG_CHAIN=y +CONFIG_MIGHT_HAVE_PCI=y +CONFIG_SYS_SUPPORTS_APM_EMULATION=y +CONFIG_GENERIC_GPIO=y +# CONFIG_ARCH_USES_GETTIMEOFFSET is not set +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y +CONFIG_KTIME_SCALAR=y +CONFIG_HAVE_PROC_CPU=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +CONFIG_HARDIRQS_SW_RESEND=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_ARM_TICKET_LOCKS=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_ARCH_HAS_CPUFREQ=y +CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +CONFIG_NEED_DMA_MAP_STATE=y +CONFIG_VECTORS_BASE=0xffff0000 # CONFIG_ARM_PATCH_PHYS_VIRT is not set +CONFIG_NEED_MACH_IO_H=y +CONFIG_NEED_MACH_MEMORY_H=y +CONFIG_PHYS_OFFSET=0x80200000 +CONFIG_GENERIC_BUG=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" +CONFIG_HAVE_IRQ_WORK=y +CONFIG_IRQ_WORK=y + +# +# General setup +# CONFIG_EXPERIMENTAL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_CROSS_COMPILE="" +CONFIG_LOCALVERSION="-Glitch-Flo" +# CONFIG_LOCALVERSION_AUTO is not set +CONFIG_HAVE_KERNEL_GZIP=y +CONFIG_HAVE_KERNEL_LZMA=y +CONFIG_HAVE_KERNEL_XZ=y +CONFIG_HAVE_KERNEL_LZO=y +CONFIG_KERNEL_GZIP=y +# CONFIG_KERNEL_LZMA is not set +# CONFIG_KERNEL_XZ is not set +# CONFIG_KERNEL_LZO is not set +CONFIG_DEFAULT_HOSTNAME="(none)" +# CONFIG_SWAP is not set CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_FHANDLE is not set +# CONFIG_TASKSTATS is not set CONFIG_AUDIT=y +CONFIG_AUDITSYSCALL=y +CONFIG_AUDIT_WATCH=y +CONFIG_AUDIT_TREE=y +# CONFIG_AUDIT_LOGINUID_IMMUTABLE is not set +CONFIG_HAVE_GENERIC_HARDIRQS=y + +# +# IRQ subsystem +# +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_SHOW=y +CONFIG_IRQ_DOMAIN=y +# CONFIG_IRQ_DOMAIN_DEBUG is not set + +# +# RCU Subsystem +# +CONFIG_TREE_PREEMPT_RCU=y +CONFIG_PREEMPT_RCU=y +CONFIG_RCU_FANOUT=32 +# CONFIG_RCU_FANOUT_EXACT is not set +# CONFIG_RCU_FAST_NO_HZ is not set +# CONFIG_TREE_RCU_TRACE is not set +# CONFIG_RCU_BOOST is not set CONFIG_IKCONFIG=y +# CONFIG_IKCONFIG_PROC is not set +CONFIG_LOG_BUF_SHIFT=17 CONFIG_CGROUPS=y -CONFIG_CGROUP_DEBUG=y +# CONFIG_CGROUP_DEBUG is not set CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_TIMER_SLACK=y +# CONFIG_CGROUP_DEVICE is not set +# CONFIG_CPUSETS is not set CONFIG_CGROUP_CPUACCT=y CONFIG_RESOURCE_COUNTERS=y +# CONFIG_CGROUP_MEM_RES_CTLR is not set +# CONFIG_CGROUP_PERF is not set CONFIG_CGROUP_SCHED=y +CONFIG_FAIR_GROUP_SCHED=y +# CONFIG_CFS_BANDWIDTH is not set CONFIG_RT_GROUP_SCHED=y +# CONFIG_BLK_CGROUP is not set +# CONFIG_CHECKPOINT_RESTORE is not set CONFIG_NAMESPACES=y # CONFIG_UTS_NS is not set # CONFIG_IPC_NS is not set # CONFIG_USER_NS is not set # CONFIG_PID_NS is not set # CONFIG_NET_NS is not set +# CONFIG_SCHED_AUTOGROUP is not set +# CONFIG_SYSFS_DEPRECATED is not set +# CONFIG_RELAY is not set CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_RD_GZIP=y CONFIG_RD_BZIP2=y CONFIG_RD_LZMA=y -CONFIG_CC_OPTIMIZE_FOR_SIZE=y +# CONFIG_RD_XZ is not set +# CONFIG_RD_LZO is not set +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +# CONFIG_CC_OPTIMIZE_DEFAULT is not set +CONFIG_CC_OPTIMIZE_ALOT=y +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y CONFIG_PANIC_TIMEOUT=5 +CONFIG_EXPERT=y +CONFIG_UID16=y +# CONFIG_SYSCTL_SYSCALL is not set +CONFIG_KALLSYMS=y CONFIG_KALLSYMS_ALL=y +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_AIO=y CONFIG_EMBEDDED=y +CONFIG_HAVE_PERF_EVENTS=y +CONFIG_PERF_USE_VMALLOC=y + +# +# Kernel Performance Events And Counters +# +CONFIG_PERF_EVENTS=y +# CONFIG_PERF_COUNTERS is not set +# CONFIG_DEBUG_PERF_USE_VMALLOC is not set +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_PCI_QUIRKS=y +# CONFIG_SLUB_DEBUG is not set +CONFIG_COMPAT_BRK=y +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_SLOB is not set CONFIG_PROFILING=y # CONFIG_OPROFILE is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +# CONFIG_JUMP_LABEL is not set +CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y +CONFIG_HAVE_DMA_ATTRS=y +CONFIG_HAVE_DMA_CONTIGUOUS=y +CONFIG_USE_GENERIC_SMP_HELPERS=y +CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y +CONFIG_HAVE_CLK=y +CONFIG_HAVE_DMA_API_DEBUG=y +CONFIG_HAVE_HW_BRKPT_RESERVED_RW_ACCESS=y +CONFIG_HAVE_ARCH_JUMP_LABEL=y + +# +# GCOV-based kernel profiling +# +# CONFIG_GCOV_KERNEL is not set +CONFIG_HAVE_GENERIC_DMA_COHERENT=y +CONFIG_RT_MUTEXES=y +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +CONFIG_MODULE_FORCE_LOAD=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_MODVERSIONS=y +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_STOP_MACHINE=y +CONFIG_BLOCK=y +CONFIG_LBDAF=y +CONFIG_BLK_DEV_BSG=y +# CONFIG_BLK_DEV_BSGLIB is not set +# CONFIG_BLK_DEV_INTEGRITY is not set + +# +# Partition Types +# CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set CONFIG_EFI_PARTITION=y +# CONFIG_SYSV68_PARTITION is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_TEST is not set +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +CONFIG_IOSCHED_FIOPS=y +CONFIG_IOSCHED_SIO=y +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_FIOPS is not set +# CONFIG_DEFAULT_SIO is not set +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" +# CONFIG_INLINE_SPIN_TRYLOCK is not set +# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK is not set +# CONFIG_INLINE_SPIN_LOCK_BH is not set +# CONFIG_INLINE_SPIN_LOCK_IRQ is not set +# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set +CONFIG_UNINLINE_SPIN_UNLOCK=y +# CONFIG_INLINE_SPIN_UNLOCK_BH is not set +# CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set +# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_READ_TRYLOCK is not set +# CONFIG_INLINE_READ_LOCK is not set +# CONFIG_INLINE_READ_LOCK_BH is not set +# CONFIG_INLINE_READ_LOCK_IRQ is not set +# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set +# CONFIG_INLINE_READ_UNLOCK is not set +# CONFIG_INLINE_READ_UNLOCK_BH is not set +# CONFIG_INLINE_READ_UNLOCK_IRQ is not set +# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set +# CONFIG_INLINE_WRITE_TRYLOCK is not set +# CONFIG_INLINE_WRITE_LOCK is not set +# CONFIG_INLINE_WRITE_LOCK_BH is not set +# CONFIG_INLINE_WRITE_LOCK_IRQ is not set +# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set +# CONFIG_INLINE_WRITE_UNLOCK is not set +# CONFIG_INLINE_WRITE_UNLOCK_BH is not set +# CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set +# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set +CONFIG_MUTEX_SPIN_ON_OWNER=y +CONFIG_FREEZER=y + +# +# System Type +# +CONFIG_MMU=y +# CONFIG_ARCH_INTEGRATOR is not set +# CONFIG_ARCH_REALVIEW is not set +# CONFIG_ARCH_VERSATILE is not set +# CONFIG_ARCH_VEXPRESS is not set +# CONFIG_ARCH_AT91 is not set +# CONFIG_ARCH_BCMRING is not set +# CONFIG_ARCH_HIGHBANK is not set +# CONFIG_ARCH_CLPS711X is not set +# CONFIG_ARCH_CNS3XXX is not set +# CONFIG_ARCH_GEMINI is not set +# CONFIG_ARCH_PRIMA2 is not set +# CONFIG_ARCH_EBSA110 is not set +# CONFIG_ARCH_EP93XX is not set +# CONFIG_ARCH_FOOTBRIDGE is not set +# CONFIG_ARCH_MXC is not set +# CONFIG_ARCH_MXS is not set +# CONFIG_ARCH_NETX is not set +# CONFIG_ARCH_H720X is not set +# CONFIG_ARCH_IOP13XX is not set +# CONFIG_ARCH_IOP32X is not set +# CONFIG_ARCH_IOP33X is not set +# CONFIG_ARCH_IXP23XX is not set +# CONFIG_ARCH_IXP2000 is not set +# CONFIG_ARCH_IXP4XX is not set +# CONFIG_ARCH_DOVE is not set +# CONFIG_ARCH_KIRKWOOD is not set +# CONFIG_ARCH_LPC32XX is not set +# CONFIG_ARCH_MV78XX0 is not set +# CONFIG_ARCH_ORION5X is not set +# CONFIG_ARCH_MMP is not set +# CONFIG_ARCH_KS8695 is not set +# CONFIG_ARCH_W90X900 is not set +# CONFIG_ARCH_TEGRA is not set +# CONFIG_ARCH_PICOXCELL is not set +# CONFIG_ARCH_PNX4008 is not set +# CONFIG_ARCH_PXA is not set CONFIG_ARCH_MSM=y +# CONFIG_ARCH_SHMOBILE is not set +# CONFIG_ARCH_RPC is not set +# CONFIG_ARCH_SA1100 is not set +# CONFIG_ARCH_S3C24XX is not set +# CONFIG_ARCH_S3C64XX is not set +# CONFIG_ARCH_S5P64X0 is not set +# CONFIG_ARCH_S5PC100 is not set +# CONFIG_ARCH_S5PV210 is not set +# CONFIG_ARCH_EXYNOS is not set +# CONFIG_ARCH_SHARK is not set +# CONFIG_ARCH_U300 is not set +# CONFIG_ARCH_U8500 is not set +# CONFIG_ARCH_NOMADIK is not set +# CONFIG_ARCH_DAVINCI is not set +# CONFIG_ARCH_OMAP is not set +# CONFIG_PLAT_SPEAR is not set +# CONFIG_ARCH_VT8500 is not set +# CONFIG_ARCH_ZYNQ is not set +# CONFIG_GPIO_PCA953X is not set +# CONFIG_KEYBOARD_GPIO_POLLED is not set + +# +# MSM SoC Type +# +# CONFIG_ARCH_MSM7X01A is not set +# CONFIG_ARCH_MSM7X25 is not set +# CONFIG_ARCH_MSM7X27 is not set +# CONFIG_ARCH_MSM7X30 is not set +# CONFIG_ARCH_QSD8X50 is not set +# CONFIG_ARCH_MSM8X60 is not set CONFIG_ARCH_MSM8960=y CONFIG_ARCH_MSM8930=y CONFIG_ARCH_APQ8064=y +# CONFIG_ARCH_MSM8974 is not set +# CONFIG_ARCH_MPQ8092 is not set +# CONFIG_ARCH_MSM8226 is not set +# CONFIG_ARCH_FSM9XXX is not set +# CONFIG_ARCH_MSM9615 is not set +# CONFIG_ARCH_MSM8625 is not set +# CONFIG_ARCH_MSM9625 is not set +CONFIG_MSM_SOC_REV_NONE=y +# CONFIG_MSM_SOC_REV_A is not set CONFIG_MSM_KRAIT_TBB_ABORT_HANDLER=y +CONFIG_ARCH_MSM_KRAIT=y +CONFIG_MSM_SMP=y +CONFIG_ARCH_MSM_KRAITMP=y +CONFIG_MSM_KRAIT_WFE_FIXUP=y +CONFIG_MSM_RPM=y +# CONFIG_MSM_RPM_SMD is not set +CONFIG_MSM_MPM=y +CONFIG_MSM_XO=y +CONFIG_MSM_REMOTE_SPINLOCK_SFPB=y + +# +# MSM Board Selection +# +# CONFIG_MACH_MSM8960_CDP is not set +# CONFIG_MACH_MSM8960_MTP is not set +# CONFIG_MACH_MSM8960_FLUID is not set +# CONFIG_MACH_MSM8960_LIQUID is not set +# CONFIG_MACH_MSM8930_CDP is not set +# CONFIG_MACH_MSM8930_MTP is not set +# CONFIG_MACH_MSM8930_FLUID is not set +# CONFIG_MACH_MSM8627_CDP is not set +# CONFIG_MACH_MSM8627_MTP is not set +# CONFIG_MACH_APQ8064_CDP is not set +# CONFIG_MACH_APQ8064_MTP is not set +# CONFIG_MACH_APQ8064_LIQUID is not set +# CONFIG_MACH_MPQ8064_CDP is not set +# CONFIG_MACH_MPQ8064_HRD is not set +# CONFIG_MACH_MPQ8064_DTV is not set +# CONFIG_MACH_MSM_DUMMY is not set + +# +# LGE Board Selection +# +CONFIG_BOARD_HEADER_FILE="" +# CONFIG_MACH_APQ8064_MAKO is not set +# CONFIG_MACH_LGE_DUMMY is not set + +# +# LGE Specific Patches +# +# CONFIG_LGE_CRASH_HANDLER is not set +CONFIG_MACH_ASUSTEK=y + +# +# ASUSTek Board Selection +# CONFIG_MACH_APQ8064_FLO=y CONFIG_MACH_APQ8064_DEB=y +# CONFIG_MACH_ASUSTEK_DUMMY is not set + +# +# ASUSTek Specific Feature +# +CONFIG_ASUSTEK_PCBID=y +CONFIG_ASUSTEK_KEYPAD=y # CONFIG_MSM_STACKED_MEMORY is not set CONFIG_KERNEL_MSM_CONTIG_MEM_REGION=y +CONFIG_MSM_AMSS_VERSION=6225 +# CONFIG_MSM_AMSS_VERSION_6210 is not set +# CONFIG_MSM_AMSS_VERSION_6220 is not set +CONFIG_MSM_AMSS_VERSION_6225=y +CONFIG_MSM7X00A_USE_GP_TIMER=y +# CONFIG_MSM7X00A_USE_DG_TIMER is not set +CONFIG_MSM7X00A_SLEEP_MODE_POWER_COLLAPSE_SUSPEND=y +# CONFIG_MSM7X00A_SLEEP_MODE_POWER_COLLAPSE is not set +# CONFIG_MSM7X00A_SLEEP_MODE_APPS_SLEEP is not set +# CONFIG_MSM7X00A_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT is not set +# CONFIG_MSM7X00A_SLEEP_WAIT_FOR_INTERRUPT is not set +CONFIG_MSM7X00A_SLEEP_MODE=0 +# CONFIG_MSM7X00A_IDLE_SLEEP_MODE_POWER_COLLAPSE_SUSPEND is not set +CONFIG_MSM7X00A_IDLE_SLEEP_MODE_POWER_COLLAPSE=y +# CONFIG_MSM7X00A_IDLE_SLEEP_MODE_APPS_SLEEP is not set +# CONFIG_MSM7X00A_IDLE_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT is not set +# CONFIG_MSM7X00A_IDLE_SLEEP_WAIT_FOR_INTERRUPT is not set +CONFIG_MSM7X00A_IDLE_SLEEP_MODE=1 +CONFIG_MSM7X00A_IDLE_SLEEP_MIN_TIME=20000000 +CONFIG_MSM7X00A_IDLE_SPIN_TIME=80000 +CONFIG_MSM_IDLE_STATS=y +CONFIG_MSM_IDLE_STATS_FIRST_BUCKET=62500 +CONFIG_MSM_IDLE_STATS_BUCKET_SHIFT=2 +CONFIG_MSM_IDLE_STATS_BUCKET_COUNT=10 +CONFIG_MSM_SUSPEND_STATS_FIRST_BUCKET=1000000000 +CONFIG_CPU_HAS_L2_PMU=y +# CONFIG_HTC_HEADSET is not set +# CONFIG_HTC_PWRSINK is not set # CONFIG_MSM_FIQ_SUPPORT is not set +# CONFIG_MSM_SERIAL_DEBUGGER is not set # CONFIG_MSM_PROC_COMM is not set CONFIG_MSM_SMD=y +# CONFIG_MSM_SMD_PKG3 is not set CONFIG_MSM_SMD_PKG4=y CONFIG_MSM_PCIE=y +CONFIG_MSM_SMD_DEBUG=y CONFIG_MSM_BAM_DMUX=y +CONFIG_MSM_N_WAY_SMD=y +CONFIG_MSM_N_WAY_SMSM=y +CONFIG_MSM_RESET_MODEM=y +CONFIG_MSM_SMD_LOGGING=y CONFIG_MSM_IPC_LOGGING=y +CONFIG_MSM_SMD_NMEA=y CONFIG_MSM_HSIC_TTY=y +CONFIG_MSM_SMD_TTY=y +CONFIG_MSM_SMD_QMI=y +CONFIG_MSM_SMD_PKT=y CONFIG_MSM_DSPS=y +# CONFIG_MSM_ONCRPCROUTER is not set CONFIG_MSM_IPC_ROUTER=y CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y CONFIG_MSM_IPC_ROUTER_SECURITY=y +# CONFIG_MSM_DALRPC is not set +CONFIG_MSM_MPDEC=y +CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN=y +CONFIG_MSM_CPU_FREQ_SET_MIN_MAX=y +CONFIG_MSM_CPU_FREQ_MAX=2322000 +CONFIG_MSM_CPU_FREQ_MIN=384000 +CONFIG_INTELLI_PLUG=y +CONFIG_CPU_VOLTAGE_TABLE=y CONFIG_MSM_AVS_HW=y # CONFIG_MSM_HW3D is not set +CONFIG_AMSS_7X25_VERSION_2009=y +# CONFIG_AMSS_7X25_VERSION_2008 is not set +CONFIG_RTAC=y +# CONFIG_MSM_VREG_SWITCH_INVERTED is not set +CONFIG_MSM_DMA_TEST=y +# CONFIG_WIFI_CONTROL_FUNC is not set +CONFIG_MSM_SLEEP_TIME_OVERRIDE=y +# CONFIG_MSM_MEMORY_LOW_POWER_MODE is not set +CONFIG_MSM_PM_TIMEOUT_HALT=y +# CONFIG_MSM_PM_TIMEOUT_RESET_MODEM is not set +# CONFIG_MSM_PM_TIMEOUT_RESET_CHIP is not set +CONFIG_MSM_IDLE_WAIT_ON_MODEM=0 +CONFIG_MSM_RPM_REGULATOR=y CONFIG_MSM_SUBSYSTEM_RESTART=y CONFIG_MSM_SYSMON_COMM=y +CONFIG_MSM_PIL=y +# CONFIG_MSM_PIL_MODEM is not set +# CONFIG_MSM_PIL_QDSP6V3 is not set CONFIG_MSM_PIL_QDSP6V4=y +# CONFIG_MSM_PIL_LPASS_QDSP6V5 is not set +# CONFIG_MSM_PIL_MSS_QDSP6V5 is not set CONFIG_MSM_PIL_RIVA=y CONFIG_MSM_PIL_TZAPPS=y CONFIG_MSM_PIL_DSPS=y CONFIG_MSM_PIL_VIDC=y +# CONFIG_MSM_PIL_VENUS is not set CONFIG_MSM_PIL_GSS=y +# CONFIG_MSM_PIL_PRONTO is not set +CONFIG_MSM_SCM=y CONFIG_MSM_MODEM_8960=y CONFIG_MSM_LPASS_8960=y CONFIG_MSM_WCNSS_SSR_8960=y CONFIG_MSM_GSS_SSR_8064=y +CONFIG_MSM_BUSPM_DEV=y CONFIG_MSM_TZ_LOG=y CONFIG_MSM_RPM_LOG=y CONFIG_MSM_RPM_STATS_LOG=y CONFIG_MSM_RPM_RBCPR_STATS_LOG=y +CONFIG_MSM_DIRECT_SCLK_ACCESS=y +CONFIG_IOMMU_API=y +CONFIG_MSM_GPIOMUX=y +CONFIG_MSM_NATIVE_RESTART=y +CONFIG_MSM_PM8X60=y CONFIG_MSM_EVENT_TIMER=y CONFIG_MSM_BUS_SCALING=y CONFIG_MSM_BUS_RPM_MULTI_TIER_ENABLED=y CONFIG_MSM_WATCHDOG=y +# CONFIG_MSM_WATCHDOG_V2 is not set +# CONFIG_MSM_MEMORY_DUMP is not set CONFIG_MSM_DLOAD_MODE=y +# CONFIG_MSM_JTAG is not set +# CONFIG_MSM_JTAG_MM is not set +# CONFIG_MSM_SLEEP_STATS_DEVICE is not set +CONFIG_MSM_RUN_QUEUE_STATS=y +# CONFIG_MSM_STANDALONE_POWER_COLLAPSE is not set +# CONFIG_MSM_GSBI9_UART is not set +CONFIG_MSM_SHOW_RESUME_IRQ=y +# CONFIG_MSM_FAKE_BATTERY is not set +CONFIG_MSM_QDSP6_APR=y +# CONFIG_MSM_QDSP6_APRV2 is not set +CONFIG_MSM_QDSP6_CODECS=y +# CONFIG_MSM_QDSP6V2_CODECS is not set +CONFIG_MSM_AUDIO_QDSP6=y +# CONFIG_MSM_AUDIO_QDSP6V2 is not set CONFIG_MSM_ADSP_LOADER=y +CONFIG_MSM_ULTRASOUND=y +# CONFIG_MSM_SPM_V1 is not set +CONFIG_MSM_SPM_V2=y +CONFIG_MSM_L2_SPM=y +CONFIG_MSM_MULTIMEDIA_USE_ION=y +# CONFIG_MSM_OCMEM is not set +# CONFIG_MSM_RTB is not set CONFIG_MSM_EBI_ERP=y CONFIG_MSM_CACHE_ERP=y CONFIG_MSM_L1_ERR_PANIC=y CONFIG_MSM_L1_ERR_LOG=y +# CONFIG_MSM_L2_ERP_PRINT_ACCESS_ERRORS is not set +# CONFIG_MSM_L2_ERP_1BIT_PANIC is not set CONFIG_MSM_L2_ERP_2BIT_PANIC=y CONFIG_MSM_DCVS=y +# CONFIG_MSM_CPR is not set +CONFIG_HAVE_ARCH_HAS_CURRENT_TIMER=y CONFIG_MSM_CACHE_DUMP=y CONFIG_MSM_CACHE_DUMP_ON_PANIC=y CONFIG_MSM_HSIC_SYSMON=y +# CONFIG_MSM_HSIC_SYSMON_TEST is not set +CONFIG_MSM_CPU_PWRCTL=y +CONFIG_FORCE_FAST_CHARGE=y + +# +# System MMU +# + +# +# Processor Type +# +CONFIG_CPU_V7=y +CONFIG_CPU_32v6K=y +CONFIG_CPU_32v7=y +CONFIG_CPU_ABRT_EV7=y +CONFIG_CPU_PABRT_V7=y +CONFIG_CPU_CACHE_V7=y +CONFIG_CPU_CACHE_VIPT=y +CONFIG_CPU_COPY_V6=y +CONFIG_CPU_TLB_V7=y +CONFIG_CPU_HAS_ASID=y +CONFIG_CPU_CP15=y +CONFIG_CPU_CP15_MMU=y + +# +# Processor Features +# +# CONFIG_ARM_LPAE is not set +# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set +CONFIG_ARM_THUMB=y +# CONFIG_ARM_THUMBEE is not set +CONFIG_SWP_EMULATE=y +# CONFIG_CPU_ICACHE_DISABLE is not set +# CONFIG_CPU_DCACHE_DISABLE is not set +# CONFIG_CPU_BPREDICT_DISABLE is not set +# CONFIG_CACHE_L2X0 is not set +CONFIG_ARM_L1_CACHE_SHIFT_6=y +CONFIG_ARM_L1_CACHE_SHIFT=6 +CONFIG_ARM_DMA_MEM_BUFFERABLE=y CONFIG_STRICT_MEMORY_RWX=y +CONFIG_ARM_NR_BANKS=8 +# CONFIG_RESERVE_FIRST_PAGE is not set +CONFIG_CPU_HAS_PMU=y +CONFIG_MULTI_IRQ_HANDLER=y +# CONFIG_ARM_ERRATA_430973 is not set +# CONFIG_ARM_ERRATA_458693 is not set +# CONFIG_ARM_ERRATA_460075 is not set +# CONFIG_ARM_ERRATA_742230 is not set +# CONFIG_ARM_ERRATA_742231 is not set +# CONFIG_ARM_ERRATA_720789 is not set +# CONFIG_ARM_ERRATA_743622 is not set +# CONFIG_ARM_ERRATA_751472 is not set +# CONFIG_ARM_ERRATA_754322 is not set +# CONFIG_ARM_ERRATA_754327 is not set +# CONFIG_ARM_ERRATA_764369 is not set +# CONFIG_KSAPI is not set +CONFIG_ARM_GIC=y +# CONFIG_FIQ_DEBUGGER is not set + +# +# Bus support +# CONFIG_PCI=y +CONFIG_PCI_SYSCALL=y +CONFIG_ARCH_SUPPORTS_MSI=y CONFIG_PCI_MSI=y +# CONFIG_PCI_DEBUG is not set +# CONFIG_PCI_REALLOC_ENABLE_AUTO is not set +# CONFIG_PCI_STUB is not set +# CONFIG_PCI_IOV is not set +# CONFIG_PCI_PRI is not set +# CONFIG_PCI_PASID is not set +# CONFIG_PCCARD is not set + +# +# Kernel Features +# +CONFIG_TICK_ONESHOT=y CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_HAVE_SMP=y CONFIG_SMP=y # CONFIG_SMP_ON_UP is not set +CONFIG_ARM_CPU_TOPOLOGY=y CONFIG_SCHED_MC=y +# CONFIG_SCHED_SMT is not set +CONFIG_HAVE_ARM_SCU=y +# CONFIG_ARM_ARCH_TIMER is not set +CONFIG_VMSPLIT_3G=y +# CONFIG_VMSPLIT_2G is not set +# CONFIG_VMSPLIT_1G is not set +CONFIG_PAGE_OFFSET=0xC0000000 +CONFIG_NR_CPUS=4 +CONFIG_HOTPLUG_CPU=y +CONFIG_LOCAL_TIMERS=y +CONFIG_ARCH_NR_GPIO=0 +# CONFIG_PREEMPT_NONE is not set +# CONFIG_PREEMPT_VOLUNTARY is not set CONFIG_PREEMPT=y +CONFIG_PREEMPT_COUNT=y +CONFIG_HZ=100 +# CONFIG_THUMB2_KERNEL is not set CONFIG_AEABI=y +CONFIG_OABI_COMPAT=y +CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_SPARSEMEM_DEFAULT=y +CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_HAVE_ARCH_PFN_VALID=y CONFIG_HIGHMEM=y +# CONFIG_HIGHPTE is not set +CONFIG_HW_PERF_EVENTS=y +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_SPARSEMEM_MANUAL=y +CONFIG_SPARSEMEM=y +CONFIG_HAVE_MEMORY_PRESENT=y +CONFIG_SPARSEMEM_EXTREME=y +CONFIG_HAVE_MEMBLOCK=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_COMPACTION is not set +CONFIG_MIGRATION=y +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_BOUNCE=y +CONFIG_VIRT_TO_BUS=y +# CONFIG_KSM is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +CONFIG_CLEANCACHE=y +# CONFIG_ARCH_MEMORY_PROBE is not set +# CONFIG_ARCH_MEMORY_REMOVE is not set +# CONFIG_ENABLE_DMM is not set +# CONFIG_FIX_MOVABLE_ZONE is not set +CONFIG_DONT_MAP_HOLE_AFTER_MEMBANK0=y +# CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG is not set +# CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE is not set +CONFIG_HOLES_IN_ZONE=y +CONFIG_FORCE_MAX_ZONEORDER=11 +CONFIG_ALIGNMENT_TRAP=y +# CONFIG_UACCESS_WITH_MEMCPY is not set +# CONFIG_SECCOMP is not set CONFIG_CC_STACKPROTECTOR=y +# CONFIG_DEPRECATED_PARAM_STRUCT is not set +# CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART is not set +CONFIG_CP_ACCESS=y + +# +# Boot options +# +# CONFIG_USE_OF is not set +CONFIG_ZBOOT_ROM_TEXT=0 +CONFIG_ZBOOT_ROM_BSS=0 +CONFIG_CMDLINE="" +# CONFIG_XIP_KERNEL is not set +CONFIG_KEXEC=y +CONFIG_ATAGS_PROC=y +CONFIG_KEXEC_HARDBOOT=y +# CONFIG_CRASH_DUMP is not set +# CONFIG_AUTO_ZRELADDR is not set + +# +# CPU Power Management +# + +# +# CPU Frequency scaling +# CONFIG_CPU_FREQ=y -CONFIG_CPU_FREQ_GOV_POWERSAVE=y +CONFIG_CPU_FREQ_TABLE=y +CONFIG_CPU_FREQ_STAT=y +# CONFIG_CPU_FREQ_STAT_DETAILS is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set +CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y +# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_INTELLIDEMAND is not set +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set CONFIG_CPU_FREQ_GOV_USERSPACE=y CONFIG_CPU_FREQ_GOV_ONDEMAND=y CONFIG_CPU_FREQ_GOV_INTERACTIVE=y +# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set +CONFIG_CPU_FREQ_GOV_INTELLIDEMAND=y +# CONFIG_CPUFREQ_ID_PERFLOCK is not set + +# +# ARM CPU frequency scaling drivers +# +# CONFIG_ARM_EXYNOS4210_CPUFREQ is not set +# CONFIG_ARM_EXYNOS4X12_CPUFREQ is not set +# CONFIG_ARM_EXYNOS5250_CPUFREQ is not set CONFIG_CPU_IDLE=y +CONFIG_CPU_IDLE_GOV_LADDER=y +CONFIG_CPU_IDLE_GOV_MENU=y +CONFIG_CPU_FREQ_MSM=y + +# +# Floating point emulation +# + +# +# At least one emulation must be selected +# +# CONFIG_FPE_NWFPE is not set +# CONFIG_FPE_FASTFPE is not set CONFIG_VFP=y +CONFIG_VFPv3=y CONFIG_NEON=y + +# +# Userspace binary formats +# +CONFIG_BINFMT_ELF=y +CONFIG_ARCH_BINFMT_ELF_RANDOMIZE_PIE=y # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +CONFIG_HAVE_AOUT=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set + +# +# Power management options +# +CONFIG_SUSPEND=y +CONFIG_SUSPEND_FREEZER=y +CONFIG_HAS_WAKELOCK=y +CONFIG_HAS_EARLYSUSPEND=y CONFIG_WAKELOCK=y +CONFIG_WAKELOCK_STAT=y +CONFIG_USER_WAKELOCK=y +CONFIG_EARLYSUSPEND=y +# CONFIG_NO_USER_SPACE_SCREEN_ACCESS_CONTROL is not set +# CONFIG_CONSOLE_EARLYSUSPEND is not set +CONFIG_FB_EARLYSUSPEND=y +CONFIG_PM_SLEEP=y +CONFIG_PM_SLEEP_SMP=y CONFIG_PM_RUNTIME=y +CONFIG_PM=y CONFIG_PM_DEBUG=y +# CONFIG_PM_ADVANCED_DEBUG is not set +# CONFIG_PM_TEST_SUSPEND is not set +CONFIG_CAN_PM_TRACE=y +# CONFIG_APM_EMULATION is not set +CONFIG_PM_CLK=y +CONFIG_CPU_PM=y +# CONFIG_SUSPEND_TIME is not set +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARM_CPU_SUSPEND=y CONFIG_NET=y + +# +# Networking options +# CONFIG_PACKET=y CONFIG_UNIX=y +# CONFIG_UNIX_DIAG is not set +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set +CONFIG_XFRM_IPCOMP=y +CONFIG_NET_KEY=y +# CONFIG_NET_KEY_MIGRATE is not set CONFIG_INET=y +CONFIG_IP_MULTICAST=y CONFIG_IP_ADVANCED_ROUTER=y +# CONFIG_IP_FIB_TRIE_STATS is not set CONFIG_IP_MULTIPLE_TABLES=y +# CONFIG_IP_ROUTE_MULTIPATH is not set CONFIG_IP_ROUTE_VERBOSE=y CONFIG_IP_PNP=y CONFIG_IP_PNP_DHCP=y -CONFIG_IP_MULTICAST=y +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE_DEMUX is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +CONFIG_INET_ESP=y +# CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set +CONFIG_INET_TUNNEL=y +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y # CONFIG_INET_XFRM_MODE_BEET is not set # CONFIG_INET_LRO is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_INET_UDP_DIAG is not set +CONFIG_TCP_CONG_ADVANCED=y +CONFIG_TCP_CONG_BIC=y +CONFIG_TCP_CONG_CUBIC=y +CONFIG_TCP_CONG_WESTWOOD=y +CONFIG_TCP_CONG_HTCP=y +# CONFIG_TCP_CONG_HSTCP is not set +# CONFIG_TCP_CONG_HYBLA is not set +# CONFIG_TCP_CONG_VEGAS is not set +# CONFIG_TCP_CONG_SCALABLE is not set +# CONFIG_TCP_CONG_LP is not set +CONFIG_TCP_CONG_VENO=y +# CONFIG_TCP_CONG_YEAH is not set +# CONFIG_TCP_CONG_ILLINOIS is not set +# CONFIG_DEFAULT_BIC is not set +# CONFIG_DEFAULT_CUBIC is not set +# CONFIG_DEFAULT_HTCP is not set +# CONFIG_DEFAULT_VENO is not set +CONFIG_DEFAULT_WESTWOOD=y +# CONFIG_DEFAULT_RENO is not set +CONFIG_DEFAULT_TCP_CONG="westwood" +# CONFIG_TCP_MD5SIG is not set +CONFIG_IPV6=y CONFIG_IPV6_PRIVACY=y CONFIG_IPV6_ROUTER_PREF=y CONFIG_IPV6_ROUTE_INFO=y @@ -125,95 +873,306 @@ CONFIG_INET6_AH=y CONFIG_INET6_ESP=y CONFIG_INET6_IPCOMP=y CONFIG_IPV6_MIP6=y +CONFIG_INET6_XFRM_TUNNEL=y +CONFIG_INET6_TUNNEL=y +CONFIG_INET6_XFRM_MODE_TRANSPORT=y +CONFIG_INET6_XFRM_MODE_TUNNEL=y +CONFIG_INET6_XFRM_MODE_BEET=y +# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set +CONFIG_IPV6_SIT=y +# CONFIG_IPV6_SIT_6RD is not set +CONFIG_IPV6_NDISC_NODETYPE=y +# CONFIG_IPV6_TUNNEL is not set CONFIG_IPV6_MULTIPLE_TABLES=y CONFIG_IPV6_SUBTREES=y +# CONFIG_IPV6_MROUTE is not set +# CONFIG_NETLABEL is not set +CONFIG_ANDROID_PARANOID_NETWORK=y +CONFIG_NET_ACTIVITY_STATS=y +CONFIG_NETWORK_SECMARK=y +# CONFIG_NETWORK_PHY_TIMESTAMPING is not set CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_NETFILTER_ADVANCED=y + +# +# Core Netfilter Configuration +# +CONFIG_NETFILTER_NETLINK=y +# CONFIG_NETFILTER_NETLINK_ACCT is not set +CONFIG_NETFILTER_NETLINK_QUEUE=y CONFIG_NETFILTER_NETLINK_LOG=y CONFIG_NF_CONNTRACK=y +CONFIG_NF_CONNTRACK_MARK=y CONFIG_NF_CONNTRACK_SECMARK=y +CONFIG_NF_CONNTRACK_PROCFS=y CONFIG_NF_CONNTRACK_EVENTS=y +# CONFIG_NF_CONNTRACK_TIMEOUT is not set +# CONFIG_NF_CONNTRACK_TIMESTAMP is not set CONFIG_NF_CT_PROTO_DCCP=y +CONFIG_NF_CT_PROTO_GRE=y CONFIG_NF_CT_PROTO_SCTP=y CONFIG_NF_CT_PROTO_UDPLITE=y CONFIG_NF_CONNTRACK_AMANDA=y CONFIG_NF_CONNTRACK_FTP=y CONFIG_NF_CONNTRACK_H323=y CONFIG_NF_CONNTRACK_IRC=y +CONFIG_NF_CONNTRACK_BROADCAST=y CONFIG_NF_CONNTRACK_NETBIOS_NS=y +# CONFIG_NF_CONNTRACK_SNMP is not set CONFIG_NF_CONNTRACK_PPTP=y CONFIG_NF_CONNTRACK_SANE=y # CONFIG_NF_CONNTRACK_SIP is not set CONFIG_NF_CONNTRACK_TFTP=y CONFIG_NF_CT_NETLINK=y +# CONFIG_NF_CT_NETLINK_TIMEOUT is not set CONFIG_NETFILTER_TPROXY=y +CONFIG_NETFILTER_XTABLES=y + +# +# Xtables combined modules +# +CONFIG_NETFILTER_XT_MARK=y +CONFIG_NETFILTER_XT_CONNMARK=y + +# +# Xtables targets +# +# CONFIG_NETFILTER_XT_TARGET_AUDIT is not set +# CONFIG_NETFILTER_XT_TARGET_CHECKSUM is not set CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y CONFIG_NETFILTER_XT_TARGET_CONNMARK=y CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y +# CONFIG_NETFILTER_XT_TARGET_CT is not set +# CONFIG_NETFILTER_XT_TARGET_DSCP is not set +# CONFIG_NETFILTER_XT_TARGET_HL is not set +# CONFIG_NETFILTER_XT_TARGET_IDLETIMER is not set +# CONFIG_NETFILTER_XT_TARGET_LED is not set CONFIG_NETFILTER_XT_TARGET_LOG=y CONFIG_NETFILTER_XT_TARGET_MARK=y +# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y +# CONFIG_NETFILTER_XT_TARGET_NOTRACK is not set +# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set +# CONFIG_NETFILTER_XT_TARGET_TEE is not set +# CONFIG_NETFILTER_XT_TARGET_TPROXY is not set +# CONFIG_NETFILTER_XT_TARGET_TRACE is not set CONFIG_NETFILTER_XT_TARGET_SECMARK=y +# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set +# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set + +# +# Xtables matches +# +# CONFIG_NETFILTER_XT_MATCH_ADDRTYPE is not set +# CONFIG_NETFILTER_XT_MATCH_CLUSTER is not set CONFIG_NETFILTER_XT_MATCH_COMMENT=y +# CONFIG_NETFILTER_XT_MATCH_CONNBYTES is not set CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y CONFIG_NETFILTER_XT_MATCH_CONNMARK=y CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y +# CONFIG_NETFILTER_XT_MATCH_CPU is not set +# CONFIG_NETFILTER_XT_MATCH_DCCP is not set +# CONFIG_NETFILTER_XT_MATCH_DEVGROUP is not set +# CONFIG_NETFILTER_XT_MATCH_DSCP is not set +CONFIG_NETFILTER_XT_MATCH_ECN=y +# CONFIG_NETFILTER_XT_MATCH_ESP is not set CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y CONFIG_NETFILTER_XT_MATCH_HELPER=y +CONFIG_NETFILTER_XT_MATCH_HL=y CONFIG_NETFILTER_XT_MATCH_IPRANGE=y CONFIG_NETFILTER_XT_MATCH_LENGTH=y CONFIG_NETFILTER_XT_MATCH_LIMIT=y CONFIG_NETFILTER_XT_MATCH_MAC=y CONFIG_NETFILTER_XT_MATCH_MARK=y CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y +# CONFIG_NETFILTER_XT_MATCH_NFACCT is not set +# CONFIG_NETFILTER_XT_MATCH_OSF is not set +# CONFIG_NETFILTER_XT_MATCH_OWNER is not set CONFIG_NETFILTER_XT_MATCH_POLICY=y CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y CONFIG_NETFILTER_XT_MATCH_QTAGUID=y CONFIG_NETFILTER_XT_MATCH_QUOTA=y CONFIG_NETFILTER_XT_MATCH_QUOTA2=y CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y +# CONFIG_NETFILTER_XT_MATCH_RATEEST is not set +# CONFIG_NETFILTER_XT_MATCH_REALM is not set +# CONFIG_NETFILTER_XT_MATCH_RECENT is not set +# CONFIG_NETFILTER_XT_MATCH_SCTP is not set CONFIG_NETFILTER_XT_MATCH_SOCKET=y CONFIG_NETFILTER_XT_MATCH_STATE=y CONFIG_NETFILTER_XT_MATCH_STATISTIC=y CONFIG_NETFILTER_XT_MATCH_STRING=y +# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set CONFIG_NETFILTER_XT_MATCH_TIME=y CONFIG_NETFILTER_XT_MATCH_U32=y +# CONFIG_IP_SET is not set +# CONFIG_IP_VS is not set + +# +# IP: Netfilter Configuration +# +CONFIG_NF_DEFRAG_IPV4=y CONFIG_NF_CONNTRACK_IPV4=y +CONFIG_NF_CONNTRACK_PROC_COMPAT=y +# CONFIG_IP_NF_QUEUE is not set CONFIG_IP_NF_IPTABLES=y CONFIG_IP_NF_MATCH_AH=y CONFIG_IP_NF_MATCH_ECN=y +# CONFIG_IP_NF_MATCH_RPFILTER is not set CONFIG_IP_NF_MATCH_TTL=y CONFIG_IP_NF_FILTER=y CONFIG_IP_NF_TARGET_REJECT=y +# CONFIG_IP_NF_TARGET_REJECT_SKERR is not set +# CONFIG_IP_NF_TARGET_ULOG is not set CONFIG_NF_NAT=y +CONFIG_NF_NAT_NEEDED=y CONFIG_IP_NF_TARGET_MASQUERADE=y CONFIG_IP_NF_TARGET_NETMAP=y CONFIG_IP_NF_TARGET_REDIRECT=y +CONFIG_NF_NAT_PROTO_DCCP=y +CONFIG_NF_NAT_PROTO_GRE=y +CONFIG_NF_NAT_PROTO_UDPLITE=y +CONFIG_NF_NAT_PROTO_SCTP=y +CONFIG_NF_NAT_FTP=y +CONFIG_NF_NAT_IRC=y +CONFIG_NF_NAT_TFTP=y +CONFIG_NF_NAT_AMANDA=y +CONFIG_NF_NAT_PPTP=y +CONFIG_NF_NAT_H323=y +# CONFIG_NF_NAT_SIP is not set CONFIG_IP_NF_MANGLE=y +# CONFIG_IP_NF_TARGET_CLUSTERIP is not set +# CONFIG_IP_NF_TARGET_ECN is not set +# CONFIG_IP_NF_TARGET_TTL is not set CONFIG_IP_NF_RAW=y CONFIG_IP_NF_SECURITY=y CONFIG_IP_NF_ARPTABLES=y CONFIG_IP_NF_ARPFILTER=y CONFIG_IP_NF_ARP_MANGLE=y + +# +# IPv6: Netfilter Configuration +# +CONFIG_NF_DEFRAG_IPV6=y CONFIG_NF_CONNTRACK_IPV6=y +# CONFIG_IP6_NF_QUEUE is not set CONFIG_IP6_NF_IPTABLES=y +# CONFIG_IP6_NF_MATCH_AH is not set +# CONFIG_IP6_NF_MATCH_EUI64 is not set +# CONFIG_IP6_NF_MATCH_FRAG is not set +# CONFIG_IP6_NF_MATCH_OPTS is not set +# CONFIG_IP6_NF_MATCH_HL is not set +# CONFIG_IP6_NF_MATCH_IPV6HEADER is not set +# CONFIG_IP6_NF_MATCH_MH is not set +# CONFIG_IP6_NF_MATCH_RPFILTER is not set +# CONFIG_IP6_NF_MATCH_RT is not set +# CONFIG_IP6_NF_TARGET_HL is not set CONFIG_IP6_NF_FILTER=y CONFIG_IP6_NF_TARGET_REJECT=y +# CONFIG_IP6_NF_TARGET_REJECT_SKERR is not set CONFIG_IP6_NF_MANGLE=y CONFIG_IP6_NF_RAW=y +# CONFIG_IP6_NF_SECURITY is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_RDS is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +CONFIG_L2TP=y +# CONFIG_L2TP_DEBUGFS is not set +# CONFIG_L2TP_V3 is not set +# CONFIG_BRIDGE is not set +# CONFIG_NET_DSA is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_PHONET is not set +# CONFIG_IEEE802154 is not set CONFIG_NET_SCHED=y + +# +# Queueing/Scheduling +# +# CONFIG_NET_SCH_CBQ is not set CONFIG_NET_SCH_HTB=y +# CONFIG_NET_SCH_HFSC is not set CONFIG_NET_SCH_PRIO=y +# CONFIG_NET_SCH_MULTIQ is not set +# CONFIG_NET_SCH_RED is not set +# CONFIG_NET_SCH_SFB is not set +# CONFIG_NET_SCH_SFQ is not set +# CONFIG_NET_SCH_TEQL is not set +# CONFIG_NET_SCH_TBF is not set +# CONFIG_NET_SCH_GRED is not set +# CONFIG_NET_SCH_DSMARK is not set +# CONFIG_NET_SCH_NETEM is not set +# CONFIG_NET_SCH_DRR is not set +# CONFIG_NET_SCH_MQPRIO is not set +# CONFIG_NET_SCH_CHOKE is not set +# CONFIG_NET_SCH_QFQ is not set +# CONFIG_NET_SCH_INGRESS is not set +# CONFIG_NET_SCH_PLUG is not set + +# +# Classification +# +CONFIG_NET_CLS=y +# CONFIG_NET_CLS_BASIC is not set +# CONFIG_NET_CLS_TCINDEX is not set +# CONFIG_NET_CLS_ROUTE4 is not set CONFIG_NET_CLS_FW=y CONFIG_NET_CLS_U32=y +# CONFIG_CLS_U32_PERF is not set CONFIG_CLS_U32_MARK=y +# CONFIG_NET_CLS_RSVP is not set +# CONFIG_NET_CLS_RSVP6 is not set CONFIG_NET_CLS_FLOW=y +# CONFIG_NET_CLS_CGROUP is not set CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_STACK=32 CONFIG_NET_EMATCH_CMP=y CONFIG_NET_EMATCH_NBYTE=y CONFIG_NET_EMATCH_U32=y CONFIG_NET_EMATCH_META=y CONFIG_NET_EMATCH_TEXT=y CONFIG_NET_CLS_ACT=y +# CONFIG_NET_ACT_POLICE is not set +# CONFIG_NET_ACT_GACT is not set +# CONFIG_NET_ACT_MIRRED is not set +# CONFIG_NET_ACT_IPT is not set +# CONFIG_NET_ACT_NAT is not set +# CONFIG_NET_ACT_PEDIT is not set +# CONFIG_NET_ACT_SIMP is not set +# CONFIG_NET_ACT_SKBEDIT is not set +# CONFIG_NET_ACT_CSUM is not set +# CONFIG_NET_CLS_IND is not set +CONFIG_NET_SCH_FIFO=y +# CONFIG_DCB is not set +CONFIG_DNS_RESOLVER=y +# CONFIG_BATMAN_ADV is not set +# CONFIG_OPENVSWITCH is not set +CONFIG_RPS=y +CONFIG_RFS_ACCEL=y +CONFIG_XPS=y +# CONFIG_NETPRIO_CGROUP is not set +CONFIG_BQL=y +CONFIG_HAVE_BPF_JIT=y +# CONFIG_BPF_JIT is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +# CONFIG_IRDA is not set CONFIG_BT=y CONFIG_BT_RFCOMM=y CONFIG_BT_RFCOMM_TTY=y @@ -221,159 +1180,1810 @@ CONFIG_BT_BNEP=y CONFIG_BT_BNEP_MC_FILTER=y CONFIG_BT_BNEP_PROTO_FILTER=y CONFIG_BT_HIDP=y + +# +# Bluetooth device drivers +# CONFIG_BT_HCISMD=y +# CONFIG_BT_HCIBTUSB is not set +# CONFIG_BT_HCIBTSDIO is not set CONFIG_BT_HCIUART=y CONFIG_BT_HCIUART_H4=y +# CONFIG_BT_HCIUART_BCSP is not set CONFIG_BT_HCIUART_ATH3K=y +# CONFIG_BT_HCIUART_LL is not set CONFIG_BT_HCIUART_IBS=y +# CONFIG_BT_HCIBCM203X is not set +# CONFIG_BT_HCIBPA10X is not set +# CONFIG_BT_MSM_SLEEP is not set +# CONFIG_BT_HCIBFUSB is not set +# CONFIG_BT_HCIVHCI is not set +# CONFIG_BT_MRVL is not set +CONFIG_MSM_BT_POWER=y +# CONFIG_AF_RXRPC is not set +CONFIG_FIB_RULES=y +CONFIG_WIRELESS=y +CONFIG_WIRELESS_EXT=y +CONFIG_WEXT_CORE=y +CONFIG_WEXT_PROC=y +CONFIG_WEXT_SPY=y +CONFIG_WEXT_PRIV=y CONFIG_CFG80211=y +# CONFIG_NL80211_TESTMODE is not set +# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set +# CONFIG_CFG80211_REG_DEBUG is not set +CONFIG_CFG80211_DEFAULT_PS=y +# CONFIG_CFG80211_DEBUGFS is not set +CONFIG_CFG80211_INTERNAL_REGDB=y # CONFIG_CFG80211_WEXT is not set +# CONFIG_WIRELESS_EXT_SYSFS is not set +# CONFIG_LIB80211 is not set +# CONFIG_CFG80211_ALLOW_RECONNECT is not set +# CONFIG_MAC80211 is not set +# CONFIG_WIMAX is not set CONFIG_RFKILL=y +CONFIG_RFKILL_PM=y +CONFIG_RFKILL_LEDS=y +# CONFIG_RFKILL_INPUT is not set +# CONFIG_RFKILL_REGULATOR is not set +# CONFIG_RFKILL_GPIO is not set +# CONFIG_NET_9P is not set +# CONFIG_CAIF is not set +# CONFIG_CEPH_LIB is not set +# CONFIG_NFC is not set CONFIG_BCM2079X=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="" +# CONFIG_DEVTMPFS is not set +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_EXTRA_FIRMWARE="" +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_GENERIC_CPU_DEVICES is not set +CONFIG_REGMAP=y +CONFIG_REGMAP_I2C=y +CONFIG_REGMAP_SPI=y +CONFIG_DMA_SHARED_BUFFER=y +# CONFIG_GENLOCK is not set CONFIG_SYNC=y CONFIG_SW_SYNC=y +# CONFIG_SW_SYNC_USER is not set CONFIG_CMA=y +# CONFIG_CMA_DEBUG is not set + +# +# Default contiguous memory area size: +# +CONFIG_CMA_SIZE_MBYTES=16 +CONFIG_CMA_SIZE_SEL_MBYTES=y +# CONFIG_CMA_SIZE_SEL_PERCENTAGE is not set +# CONFIG_CMA_SIZE_SEL_MIN is not set +# CONFIG_CMA_SIZE_SEL_MAX is not set +CONFIG_CMA_ALIGNMENT=8 +CONFIG_CMA_AREAS=7 +# CONFIG_CONNECTOR is not set +# CONFIG_MTD is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +# CONFIG_BLK_DEV_COW_COMMON is not set CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_LOOP_MIN_COUNT=8 +# CONFIG_BLK_DEV_CRYPTOLOOP is not set + +# +# DRBD disabled because PROC_FS, INET or CONNECTOR not selected +# +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_NVME is not set +# CONFIG_BLK_DEV_SX8 is not set +# CONFIG_BLK_DEV_UB is not set CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=4096 +# CONFIG_BLK_DEV_XIP is not set +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +# CONFIG_MG_DISK is not set +# CONFIG_BLK_DEV_RBD is not set + +# +# Misc devices +# +# CONFIG_SENSORS_LIS3LV02D is not set +# CONFIG_AD525X_DPOT is not set +CONFIG_ANDROID_PMEM=y +# CONFIG_ATMEL_PWM is not set +# CONFIG_PHANTOM is not set +# CONFIG_INTEL_MID_PTI is not set +# CONFIG_SGI_IOC4 is not set +# CONFIG_TIFM_CORE is not set +# CONFIG_ICS932S401 is not set +# CONFIG_ENCLOSURE_SERVICES is not set +# CONFIG_HP_ILO is not set +# CONFIG_APDS9802ALS is not set +# CONFIG_ISL29003 is not set +# CONFIG_ISL29020 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_SENSORS_BH1780 is not set +# CONFIG_SENSORS_BH1770 is not set +# CONFIG_SENSORS_APDS990X is not set +# CONFIG_HMC6352 is not set +# CONFIG_SENSORS_AK8975 is not set +# CONFIG_DS1682 is not set +# CONFIG_TI_DAC7512 is not set CONFIG_UID_STAT=y +# CONFIG_BMP085 is not set +# CONFIG_PCH_PHUB is not set +# CONFIG_USB_SWITCH_FSA9480 is not set +# CONFIG_WL127X_RFKILL is not set +# CONFIG_TSIF is not set +# CONFIG_TSPP is not set +# CONFIG_HAPTIC_ISA1200 is not set CONFIG_PMIC8XXX_VIBRATOR=y +# CONFIG_ANDROID_VIBRATOR is not set +# CONFIG_TOUCHSENSE_VIBRATOR is not set +# CONFIG_PMIC8XXX_NFC is not set +# CONFIG_PMIC8XXX_UPL is not set CONFIG_QSEECOM=y +# CONFIG_QFP_FUSE is not set CONFIG_USB_HSIC_SMSC_HUB=y +# CONFIG_BU52031NVX is not set +# CONFIG_C2PORT is not set + +# +# EEPROM support +# +# CONFIG_EEPROM_AT24 is not set +# CONFIG_EEPROM_AT25 is not set +# CONFIG_EEPROM_LEGACY is not set +# CONFIG_EEPROM_MAX6875 is not set +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_EEPROM_93XX46 is not set +# CONFIG_CB710_CORE is not set +# CONFIG_IWMC3200TOP is not set + +# +# Texas Instruments shared transport line discipline +# +# CONFIG_TI_ST is not set +# CONFIG_SENSORS_LIS3_SPI is not set +# CONFIG_SENSORS_LIS3_I2C is not set + +# +# Altera FPGA firmware download module +# +# CONFIG_ALTERA_STAPL is not set CONFIG_SLIMPORT_ANX7808=y +CONFIG_HAVE_IDE=y +# CONFIG_IDE is not set + +# +# SCSI device support +# +CONFIG_SCSI_MOD=y +# CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y +CONFIG_SCSI_DMA=y CONFIG_SCSI_TGT=y +# CONFIG_SCSI_NETLINK is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set CONFIG_CHR_DEV_SG=y CONFIG_CHR_DEV_SCH=y CONFIG_SCSI_MULTI_LUN=y CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_LOGGING=y CONFIG_SCSI_SCAN_ASYNC=y +CONFIG_SCSI_WAIT_SCAN=y + +# +# SCSI Transports +# +# CONFIG_SCSI_SPI_ATTRS is not set +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +CONFIG_SCSI_LOWLEVEL=y +# CONFIG_ISCSI_TCP is not set +# CONFIG_ISCSI_BOOT_SYSFS is not set +# CONFIG_SCSI_CXGB3_ISCSI is not set +# CONFIG_SCSI_CXGB4_ISCSI is not set +# CONFIG_SCSI_BNX2_ISCSI is not set +# CONFIG_SCSI_BNX2X_FCOE is not set +# CONFIG_BE2ISCSI is not set +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_HPSA is not set +# CONFIG_SCSI_3W_9XXX is not set +# CONFIG_SCSI_3W_SAS is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AACRAID is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_AIC94XX is not set +# CONFIG_SCSI_MVSAS is not set +# CONFIG_SCSI_MVUMI is not set +# CONFIG_SCSI_DPT_I2O is not set +# CONFIG_SCSI_ADVANSYS is not set +# CONFIG_SCSI_ARCMSR is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set +# CONFIG_MEGARAID_SAS is not set +# CONFIG_SCSI_MPT2SAS is not set +# CONFIG_SCSI_UFSHCD is not set +# CONFIG_SCSI_HPTIOP is not set +# CONFIG_LIBFC is not set +# CONFIG_LIBFCOE is not set +# CONFIG_FCOE is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_STEX is not set +# CONFIG_SCSI_SYM53C8XX_2 is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +# CONFIG_SCSI_QLA_FC is not set +# CONFIG_SCSI_QLA_ISCSI is not set +# CONFIG_SCSI_LPFC is not set +# CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_NSP32 is not set +# CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_PMCRAID is not set +# CONFIG_SCSI_PM8001 is not set +# CONFIG_SCSI_SRP is not set +# CONFIG_SCSI_BFA_FC is not set +# CONFIG_SCSI_DH is not set +# CONFIG_SCSI_OSD_INITIATOR is not set +# CONFIG_ATA is not set CONFIG_MD=y +# CONFIG_BLK_DEV_MD is not set CONFIG_BLK_DEV_DM=y +# CONFIG_DM_DEBUG is not set CONFIG_DM_CRYPT=y +# CONFIG_DM_SNAPSHOT is not set +# CONFIG_DM_THIN_PROVISIONING is not set +# CONFIG_DM_MIRROR is not set +# CONFIG_DM_RAID is not set +# CONFIG_DM_ZERO is not set +# CONFIG_DM_MULTIPATH is not set +# CONFIG_DM_DELAY is not set +# CONFIG_DM_UEVENT is not set +# CONFIG_DM_FLAKEY is not set +# CONFIG_DM_VERITY is not set +# CONFIG_TARGET_CORE is not set +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_FIREWIRE is not set +# CONFIG_FIREWIRE_NOSY is not set +# CONFIG_I2O is not set CONFIG_NETDEVICES=y +CONFIG_NET_CORE=y +# CONFIG_BONDING is not set CONFIG_DUMMY=y +# CONFIG_EQUALIZER is not set +# CONFIG_NET_FC is not set +CONFIG_MII=y +# CONFIG_IFB is not set +# CONFIG_NET_TEAM is not set +# CONFIG_MACVLAN is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set CONFIG_TUN=y +# CONFIG_VETH is not set +# CONFIG_ARCNET is not set + +# +# CAIF transport drivers +# +CONFIG_ETHERNET=y +CONFIG_NET_VENDOR_3COM=y +# CONFIG_VORTEX is not set +# CONFIG_TYPHOON is not set +CONFIG_NET_VENDOR_ADAPTEC=y +# CONFIG_ADAPTEC_STARFIRE is not set +CONFIG_NET_VENDOR_ALTEON=y +# CONFIG_ACENIC is not set +CONFIG_NET_VENDOR_AMD=y +# CONFIG_AMD8111_ETH is not set +# CONFIG_PCNET32 is not set +CONFIG_NET_VENDOR_ATHEROS=y +# CONFIG_ATL2 is not set +# CONFIG_ATL1 is not set +# CONFIG_ATL1E is not set +# CONFIG_ATL1C is not set +CONFIG_NET_VENDOR_BROADCOM=y +# CONFIG_B44 is not set +# CONFIG_BNX2 is not set +# CONFIG_CNIC is not set +# CONFIG_TIGON3 is not set +# CONFIG_BNX2X is not set +CONFIG_NET_VENDOR_BROCADE=y +# CONFIG_BNA is not set +# CONFIG_NET_CALXEDA_XGMAC is not set +CONFIG_NET_VENDOR_CHELSIO=y +# CONFIG_CHELSIO_T1 is not set +# CONFIG_CHELSIO_T3 is not set +# CONFIG_CHELSIO_T4 is not set +# CONFIG_CHELSIO_T4VF is not set +CONFIG_NET_VENDOR_CIRRUS=y +# CONFIG_CS89x0 is not set +CONFIG_NET_VENDOR_CISCO=y +# CONFIG_ENIC is not set +# CONFIG_DM9000 is not set +# CONFIG_DNET is not set +CONFIG_NET_VENDOR_DEC=y +# CONFIG_NET_TULIP is not set +CONFIG_NET_VENDOR_DLINK=y +# CONFIG_DL2K is not set +# CONFIG_SUNDANCE is not set +CONFIG_NET_VENDOR_EMULEX=y +# CONFIG_BE2NET is not set +CONFIG_NET_VENDOR_EXAR=y +# CONFIG_S2IO is not set +# CONFIG_VXGE is not set +CONFIG_NET_VENDOR_FARADAY=y +# CONFIG_FTMAC100 is not set +# CONFIG_FTGMAC100 is not set +CONFIG_NET_VENDOR_HP=y +# CONFIG_HP100 is not set +CONFIG_NET_VENDOR_INTEL=y +# CONFIG_E100 is not set +# CONFIG_E1000 is not set +# CONFIG_E1000E is not set +# CONFIG_IGB is not set +# CONFIG_IGBVF is not set +# CONFIG_IXGB is not set +# CONFIG_IXGBE is not set +# CONFIG_IXGBEVF is not set +CONFIG_NET_VENDOR_I825XX=y +# CONFIG_IP1000 is not set +# CONFIG_JME is not set +CONFIG_NET_VENDOR_MARVELL=y +# CONFIG_SKGE is not set +# CONFIG_SKY2 is not set +CONFIG_NET_VENDOR_MELLANOX=y +# CONFIG_MLX4_EN is not set +# CONFIG_MLX4_CORE is not set +CONFIG_NET_VENDOR_MICREL=y +# CONFIG_KS8851 is not set +# CONFIG_KS8851_MLL is not set +# CONFIG_KSZ884X_PCI is not set +CONFIG_NET_VENDOR_MICROCHIP=y +# CONFIG_ENC28J60 is not set # CONFIG_MSM_RMNET is not set CONFIG_MSM_RMNET_BAM=y CONFIG_MSM_RMNET_SMUX=y +# CONFIG_QFEC is not set +CONFIG_NET_VENDOR_MYRI=y +# CONFIG_MYRI10GE is not set +# CONFIG_FEALNX is not set +CONFIG_NET_VENDOR_NATSEMI=y +# CONFIG_NATSEMI is not set +# CONFIG_NS83820 is not set +CONFIG_NET_VENDOR_8390=y +# CONFIG_AX88796 is not set +# CONFIG_NE2K_PCI is not set +CONFIG_NET_VENDOR_NVIDIA=y +# CONFIG_FORCEDETH is not set +CONFIG_NET_VENDOR_OKI=y +# CONFIG_PCH_GBE is not set +# CONFIG_ETHOC is not set +CONFIG_NET_PACKET_ENGINE=y +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +CONFIG_NET_VENDOR_QLOGIC=y +# CONFIG_QLA3XXX is not set +# CONFIG_QLCNIC is not set +# CONFIG_QLGE is not set +# CONFIG_NETXEN_NIC is not set +CONFIG_NET_VENDOR_REALTEK=y +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +# CONFIG_R8169 is not set +CONFIG_NET_VENDOR_RDC=y +# CONFIG_R6040 is not set +CONFIG_NET_VENDOR_SEEQ=y +# CONFIG_SEEQ8005 is not set +CONFIG_NET_VENDOR_SILAN=y +# CONFIG_SC92031 is not set +CONFIG_NET_VENDOR_SIS=y +# CONFIG_SIS900 is not set +# CONFIG_SIS190 is not set +# CONFIG_SFC is not set +CONFIG_NET_VENDOR_SMSC=y CONFIG_SMC91X=y +# CONFIG_EPIC100 is not set CONFIG_SMC911X=y CONFIG_SMSC911X=y +# CONFIG_SMSC911X_ARCH_HOOKS is not set +# CONFIG_SMSC9420 is not set +CONFIG_NET_VENDOR_STMICRO=y +# CONFIG_STMMAC_ETH is not set +CONFIG_NET_VENDOR_SUN=y +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_CASSINI is not set +# CONFIG_NIU is not set +CONFIG_NET_VENDOR_TEHUTI=y +# CONFIG_TEHUTI is not set +CONFIG_NET_VENDOR_TI=y +# CONFIG_TLAN is not set +CONFIG_NET_VENDOR_VIA=y +# CONFIG_VIA_RHINE is not set +# CONFIG_VIA_VELOCITY is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +CONFIG_PHYLIB=y + +# +# MII PHY device drivers +# +# CONFIG_AMD_PHY is not set +# CONFIG_MARVELL_PHY is not set +# CONFIG_DAVICOM_PHY is not set +# CONFIG_QSEMI_PHY is not set +# CONFIG_LXT_PHY is not set +# CONFIG_CICADA_PHY is not set +# CONFIG_VITESSE_PHY is not set +# CONFIG_SMSC_PHY is not set +# CONFIG_BROADCOM_PHY is not set +# CONFIG_ICPLUS_PHY is not set +# CONFIG_REALTEK_PHY is not set +# CONFIG_NATIONAL_PHY is not set +# CONFIG_STE10XP is not set +# CONFIG_LSI_ET1011C_PHY is not set +# CONFIG_MICREL_PHY is not set +# CONFIG_FIXED_PHY is not set +# CONFIG_MDIO_BITBANG is not set +# CONFIG_MICREL_KS8995MA is not set +CONFIG_PPP=y +CONFIG_PPP_BSDCOMP=y +CONFIG_PPP_DEFLATE=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_MPPE=y +CONFIG_PPP_MULTILINK=y +CONFIG_PPPOE=y +CONFIG_PPPOL2TP=y +CONFIG_PPPOLAC=y +CONFIG_PPPOPNS=y +CONFIG_PPP_ASYNC=y +CONFIG_PPP_SYNC_TTY=y CONFIG_SLIP=y +CONFIG_SLHC=y CONFIG_SLIP_COMPRESSED=y +# CONFIG_SLIP_SMART is not set CONFIG_SLIP_MODE_SLIP6=y +# CONFIG_TR is not set + +# +# USB Network Adapters +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set CONFIG_USB_USBNET=y +CONFIG_USB_NET_AX8817X=y +CONFIG_USB_NET_CDCETHER=y +# CONFIG_USB_NET_CDC_EEM is not set +CONFIG_USB_NET_CDC_NCM=y +# CONFIG_USB_NET_DM9601 is not set +# CONFIG_USB_NET_SMSC75XX is not set +# CONFIG_USB_NET_SMSC95XX is not set +# CONFIG_USB_NET_GL620A is not set +CONFIG_USB_NET_NET1080=y +# CONFIG_USB_NET_PLUSB is not set +# CONFIG_USB_NET_MCS7830 is not set +CONFIG_USB_NET_RNDIS_HOST=y +CONFIG_USB_NET_CDC_SUBSET=y +# CONFIG_USB_ALI_M5632 is not set +# CONFIG_USB_AN2720 is not set +# CONFIG_USB_BELKIN is not set +CONFIG_USB_ARMLINUX=y +# CONFIG_USB_EPSON2888 is not set +# CONFIG_USB_KC2190 is not set +CONFIG_USB_NET_ZAURUS=y +# CONFIG_USB_NET_CX82310_ETH is not set +# CONFIG_USB_NET_KALMIA is not set +CONFIG_USB_NET_QMI_WWAN=y +# CONFIG_USB_HSO is not set +# CONFIG_USB_NET_INT51X1 is not set +# CONFIG_USB_IPHETH is not set +# CONFIG_USB_SIERRA_NET is not set +# CONFIG_USB_VL600 is not set CONFIG_MSM_RMNET_USB=y +CONFIG_WLAN=y +# CONFIG_ATMEL is not set +# CONFIG_PRISM54 is not set +# CONFIG_USB_ZD1201 is not set +CONFIG_USB_NET_RNDIS_WLAN=y +# CONFIG_LIBRA_SDIOIF is not set +# CONFIG_ATH6K_LEGACY_EXT is not set CONFIG_WCNSS_CORE=y +# CONFIG_ATH_COMMON is not set +# CONFIG_BCMDHD is not set +# CONFIG_BRCMFMAC is not set +# CONFIG_HOSTAP is not set +# CONFIG_IPW2100 is not set +# CONFIG_IWM is not set +# CONFIG_LIBERTAS is not set +# CONFIG_MWIFIEX is not set + +# +# Enable WiMAX (Networking options) to see the WiMAX drivers +# +# CONFIG_WAN is not set +# CONFIG_VMXNET3 is not set +# CONFIG_ISDN is not set + +# +# Input device support +# +CONFIG_INPUT=y +CONFIG_INPUT_FF_MEMLESS=y +# CONFIG_INPUT_POLLDEV is not set +# CONFIG_INPUT_SPARSEKMAP is not set + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set +# CONFIG_INPUT_KEYRESET is not set CONFIG_INPUT_LID=y + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +# CONFIG_KEYBOARD_ADP5588 is not set +# CONFIG_KEYBOARD_ADP5589 is not set +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_QT1070 is not set +# CONFIG_KEYBOARD_QT2160 is not set +# CONFIG_KEYBOARD_LKKBD is not set CONFIG_KEYBOARD_GPIO=y +# CONFIG_KEYBOARD_TCA6416 is not set +# CONFIG_KEYBOARD_TCA8418 is not set CONFIG_KEYBOARD_MATRIX=y +# CONFIG_KEYBOARD_LM8323 is not set +# CONFIG_KEYBOARD_MAX7359 is not set +# CONFIG_KEYBOARD_MCS is not set +# CONFIG_KEYBOARD_MPR121 is not set +# CONFIG_KEYBOARD_NEWTON is not set +# CONFIG_KEYBOARD_OPENCORES is not set +# CONFIG_KEYBOARD_PMIC8XXX is not set +# CONFIG_KEYBOARD_SAMSUNG is not set +# CONFIG_KEYBOARD_STOWAWAY is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_OMAP4 is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_QCIKBD is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +CONFIG_MOUSE_PS2_ALPS=y +CONFIG_MOUSE_PS2_LOGIPS2PP=y +CONFIG_MOUSE_PS2_SYNAPTICS=y +CONFIG_MOUSE_PS2_TRACKPOINT=y +# CONFIG_MOUSE_PS2_ELANTECH is not set +# CONFIG_MOUSE_PS2_SENTELIC is not set +# CONFIG_MOUSE_PS2_TOUCHKIT is not set +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_MOUSE_APPLETOUCH is not set +# CONFIG_MOUSE_BCM5974 is not set +# CONFIG_MOUSE_VSXXXAA is not set +# CONFIG_MOUSE_GPIO is not set +# CONFIG_MOUSE_SYNAPTICS_I2C is not set +# CONFIG_MOUSE_QCITP is not set +# CONFIG_MOUSE_SYNAPTICS_USB is not set CONFIG_INPUT_JOYSTICK=y +# CONFIG_JOYSTICK_ANALOG is not set +# CONFIG_JOYSTICK_A3D is not set +# CONFIG_JOYSTICK_ADI is not set +# CONFIG_JOYSTICK_COBRA is not set +# CONFIG_JOYSTICK_GF2K is not set +# CONFIG_JOYSTICK_GRIP is not set +# CONFIG_JOYSTICK_GRIP_MP is not set +# CONFIG_JOYSTICK_GUILLEMOT is not set +# CONFIG_JOYSTICK_INTERACT is not set +# CONFIG_JOYSTICK_SIDEWINDER is not set +# CONFIG_JOYSTICK_TMDC is not set +# CONFIG_JOYSTICK_IFORCE is not set +# CONFIG_JOYSTICK_WARRIOR is not set +# CONFIG_JOYSTICK_MAGELLAN is not set +# CONFIG_JOYSTICK_SPACEORB is not set +# CONFIG_JOYSTICK_SPACEBALL is not set +# CONFIG_JOYSTICK_STINGER is not set +# CONFIG_JOYSTICK_TWIDJOY is not set +# CONFIG_JOYSTICK_ZHENHUA is not set +# CONFIG_JOYSTICK_AS5011 is not set +# CONFIG_JOYSTICK_JOYDUMP is not set CONFIG_JOYSTICK_XPAD=y CONFIG_JOYSTICK_XPAD_FF=y CONFIG_JOYSTICK_XPAD_LEDS=y +# CONFIG_TOUCHDISC_VTD518_SHINETSU is not set +# CONFIG_INPUT_TABLET is not set CONFIG_INPUT_TOUCHSCREEN=y +# CONFIG_TOUCHSCREEN_ADS7846 is not set +# CONFIG_TOUCHSCREEN_AD7877 is not set +# CONFIG_TOUCHSCREEN_ATMEL_MAXTOUCH is not set +# CONFIG_TOUCHSCREEN_AD7879 is not set +# CONFIG_TOUCHSCREEN_ATMEL_MXT is not set +# CONFIG_TOUCHSCREEN_AUO_PIXCIR is not set +# CONFIG_TOUCHSCREEN_BU21013 is not set +# CONFIG_TOUCHSCREEN_CY8CTMG110 is not set +# CONFIG_TOUCHSCREEN_CYTTSP_CORE is not set +# CONFIG_TOUCHSCREEN_DYNAPRO is not set +# CONFIG_TOUCHSCREEN_HAMPSHIRE is not set +# CONFIG_TOUCHSCREEN_EETI is not set +# CONFIG_TOUCHSCREEN_EGALAX is not set +# CONFIG_TOUCHSCREEN_FUJITSU is not set +# CONFIG_TOUCHSCREEN_ILI210X is not set +# CONFIG_TOUCHSCREEN_GUNZE is not set +# CONFIG_TOUCHSCREEN_ELO is not set +# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set +# CONFIG_TOUCHSCREEN_MAX11801 is not set +# CONFIG_TOUCHSCREEN_MCS5000 is not set +# CONFIG_TOUCHSCREEN_MTOUCH is not set +# CONFIG_TOUCHSCREEN_INEXIO is not set +# CONFIG_TOUCHSCREEN_MK712 is not set +# CONFIG_TOUCHSCREEN_PENMOUNT is not set +# CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI is not set +# CONFIG_TOUCHSCREEN_SYNAPTICS_RMI4_I2C is not set +# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set +# CONFIG_TOUCHSCREEN_TOUCHWIN is not set +# CONFIG_TOUCHSCREEN_PIXCIR is not set +# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set +# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set +# CONFIG_TOUCHSCREEN_TSC_SERIO is not set +# CONFIG_TOUCHSCREEN_TSC2005 is not set +# CONFIG_TOUCHSCREEN_TSC2007 is not set +# CONFIG_TOUCHSCREEN_MSM_LEGACY is not set +# CONFIG_TOUCHSCREEN_W90X900 is not set +# CONFIG_TOUCHSCREEN_ST1232 is not set +# CONFIG_TOUCHSCREEN_TPS6507X is not set +# CONFIG_TOUCHSCREEN_CY8C_TS is not set +# CONFIG_TOUCHSCREEN_CYTTSP_I2C_QC is not set +# CONFIG_TOUCHSCREEN_FT5X06 is not set +# CONFIG_TOUCHSCREEN_LGE_COMMON is not set +# CONFIG_TOUCHSCREEN_LGE_SYNAPTICS is not set CONFIG_TOUCHSCREEN_ELAN_TF_3K=y CONFIG_INPUT_MISC=y +# CONFIG_INPUT_AD714X is not set +# CONFIG_INPUT_BMA150 is not set +# CONFIG_INPUT_PM8XXX_VIBRATOR is not set +# CONFIG_INPUT_PMIC8XXX_PWRKEY is not set +# CONFIG_INPUT_MMA8450 is not set CONFIG_INPUT_MPU3050=y +# CONFIG_INPUT_GP2A is not set +# CONFIG_INPUT_GPIO_TILT_POLLED is not set +# CONFIG_INPUT_ATI_REMOTE2 is not set CONFIG_INPUT_KEYCHORD=y +# CONFIG_INPUT_KEYSPAN_REMOTE is not set +# CONFIG_INPUT_KXTJ9 is not set +# CONFIG_INPUT_POWERMATE is not set +# CONFIG_INPUT_YEALINK is not set +# CONFIG_INPUT_CM109 is not set CONFIG_INPUT_UINPUT=y +# CONFIG_INPUT_GPIO is not set +# CONFIG_INPUT_ISA1200_FF_MEMLESS is not set +# CONFIG_INPUT_PCF8574 is not set +# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set +# CONFIG_INPUT_ADXL34X is not set +# CONFIG_INPUT_CMA3000 is not set +# CONFIG_BOSCH_BMA150 is not set CONFIG_STM_LIS3DH=y +# CONFIG_BMP18X is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_PCIPS2 is not set +CONFIG_SERIO_LIBPS2=y +# CONFIG_SERIO_RAW is not set +# CONFIG_SERIO_ALTERA_PS2 is not set +# CONFIG_SERIO_PS2MULT is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_CONSOLE_TRANSLATIONS=y +CONFIG_VT_CONSOLE=y +CONFIG_VT_CONSOLE_SLEEP=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set # CONFIG_LEGACY_PTYS is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_NOZOMI is not set +# CONFIG_N_GSM is not set CONFIG_N_SMUX=y CONFIG_N_SMUX_LOOPBACK=y CONFIG_SMUX_CTL=y +# CONFIG_TRACE_SINK is not set +CONFIG_DEVMEM=y +CONFIG_DEVKMEM=y + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_MAX3100 is not set +# CONFIG_SERIAL_MAX3107 is not set +# CONFIG_SERIAL_MFD_HSU is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_JSM is not set +# CONFIG_SERIAL_MSM is not set CONFIG_SERIAL_MSM_HS=y CONFIG_SERIAL_MSM_HSL=y CONFIG_SERIAL_MSM_HSL_CONSOLE=y +# CONFIG_SERIAL_BCM_BT_LPM is not set +# CONFIG_SERIAL_TIMBERDALE is not set +# CONFIG_SERIAL_ALTERA_JTAGUART is not set +# CONFIG_SERIAL_ALTERA_UART is not set +# CONFIG_SERIAL_IFX6X60 is not set +# CONFIG_SERIAL_PCH_UART is not set +# CONFIG_SERIAL_MSM_SMD is not set +# CONFIG_SERIAL_XILINX_PS_UART is not set + +# +# Diag Support +# +CONFIG_DIAG_CHAR=y + +# +# DIAG traffic over USB +# +CONFIG_DIAG_OVER_USB=y + +# +# SDIO support for DIAG +# + +# +# HSIC/SMUX support for DIAG +# +CONFIG_DIAGFWD_BRIDGE_CODE=y +# CONFIG_TTY_PRINTK is not set +# CONFIG_HVC_DCC is not set +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=y +# CONFIG_HW_RANDOM_TIMERIOMEM is not set CONFIG_HW_RANDOM_MSM=y +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +CONFIG_DEVPORT=y +# CONFIG_DCC_TTY is not set +# CONFIG_RAMOOPS is not set +CONFIG_MSM_ROTATOR=y +CONFIG_MSM_ADSPRPC=y +# CONFIG_MMC_GENERIC_CSDIO is not set CONFIG_I2C=y +CONFIG_I2C_BOARDINFO=y +CONFIG_I2C_COMPAT=y CONFIG_I2C_CHARDEV=y +# CONFIG_I2C_MUX is not set +CONFIG_I2C_HELPER_AUTO=y + +# +# I2C Hardware Bus support +# + +# +# PC SMBus host controller drivers +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_ISCH is not set +# CONFIG_I2C_PIIX4 is not set +# CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set + +# +# I2C system bus drivers (mostly embedded / system-on-chip) +# +# CONFIG_I2C_DESIGNWARE_PLATFORM is not set +# CONFIG_I2C_DESIGNWARE_PCI is not set +# CONFIG_I2C_EG20T is not set +# CONFIG_I2C_GPIO is not set +# CONFIG_I2C_INTEL_MID is not set # CONFIG_I2C_MSM is not set CONFIG_I2C_QUP=y +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PCA_PLATFORM is not set +# CONFIG_I2C_PXA_PCI is not set +# CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_XILINX is not set + +# +# External I2C/SMBus adapter drivers +# +# CONFIG_I2C_DIOLAN_U2C is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_TINY_USB is not set + +# +# Other I2C/SMBus bus drivers +# +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set CONFIG_SPI=y +# CONFIG_SPI_DEBUG is not set +CONFIG_SPI_MASTER=y + +# +# SPI Master Controller Drivers +# +# CONFIG_SPI_ALTERA is not set +# CONFIG_SPI_BITBANG is not set +# CONFIG_SPI_GPIO is not set +# CONFIG_SPI_OC_TINY is not set +# CONFIG_SPI_PXA2XX_PCI is not set +# CONFIG_SPI_TOPCLIFF_PCH is not set +# CONFIG_SPI_XILINX is not set CONFIG_SPI_QUP=y +# CONFIG_SPI_DESIGNWARE is not set + +# +# SPI Protocol Masters +# +# CONFIG_SPI_SPIDEV is not set +# CONFIG_SPI_TLE62X0 is not set +# CONFIG_SPMI is not set +CONFIG_SLIMBUS=y CONFIG_SLIMBUS_MSM_CTRL=y +# CONFIG_HSI is not set + +# +# PPS support +# +# CONFIG_PPS is not set + +# +# PPS generators support +# + +# +# PTP clock support +# + +# +# Enable Device Drivers -> PPS to see the PTP clock options. +# +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y CONFIG_DEBUG_GPIO=y CONFIG_GPIO_SYSFS=y + +# +# Memory mapped GPIO drivers: +# +# CONFIG_GPIO_GENERIC_PLATFORM is not set +# CONFIG_GPIO_MSM_V1 is not set +CONFIG_GPIO_MSM_V2=y +# CONFIG_GPIO_MSM_V3 is not set +# CONFIG_GPIO_FSM9XXX is not set +# CONFIG_GPIO_VX855 is not set + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX7300 is not set +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCF857X is not set CONFIG_GPIO_SX150X=y +# CONFIG_GPIO_ADP5588 is not set + +# +# PCI GPIO expanders: +# +# CONFIG_GPIO_BT8XX is not set +# CONFIG_GPIO_ML_IOH is not set +# CONFIG_GPIO_RDC321X is not set + +# +# SPI GPIO expanders: +# +# CONFIG_GPIO_MAX7301 is not set +# CONFIG_GPIO_MCP23S08 is not set +# CONFIG_GPIO_MC33880 is not set +# CONFIG_GPIO_74X164 is not set + +# +# AC97 GPIO expanders: +# + +# +# MODULbus GPIO expanders: +# +CONFIG_GPIO_PM8XXX=y +CONFIG_GPIO_PM8XXX_MPP=y +# CONFIG_GPIO_PM8XXX_RPC is not set +# CONFIG_W1 is not set CONFIG_POWER_SUPPLY=y +# CONFIG_POWER_SUPPLY_DEBUG is not set +# CONFIG_PDA_POWER is not set +# CONFIG_TEST_POWER is not set CONFIG_CHARGER_SMB345=y +# CONFIG_BATTERY_DS2780 is not set +# CONFIG_BATTERY_DS2781 is not set +# CONFIG_BATTERY_DS2782 is not set +# CONFIG_BATTERY_SBS is not set +# CONFIG_BATTERY_BQ27x00 is not set +# CONFIG_BATTERY_MAX17040 is not set +# CONFIG_BATTERY_MAX17042 is not set +# CONFIG_CHARGER_ISP1704 is not set +# CONFIG_CHARGER_MAX8903 is not set +# CONFIG_CHARGER_LP8727 is not set +# CONFIG_CHARGER_GPIO is not set +# CONFIG_CHARGER_MANAGER is not set # CONFIG_BATTERY_MSM is not set +# CONFIG_BATTERY_MSM8X60 is not set +# CONFIG_SMB137B_CHARGER is not set +# CONFIG_SMB349_CHARGER is not set +# CONFIG_BATTERY_BQ27520 is not set +# CONFIG_BATTERY_BQ27541 is not set +# CONFIG_PM8921_CHARGER is not set +# CONFIG_PM8XXX_CCADC is not set +# CONFIG_LTC4088_CHARGER is not set +# CONFIG_PM8921_BMS is not set +# CONFIG_CHARGER_SMB347 is not set +# CONFIG_WIRELESS_CHARGER is not set +# CONFIG_BATTERY_TEMP_CONTROL is not set CONFIG_BATTERY_ASUS_BQ27541=y +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_HWMON_DEBUG_CHIP is not set + +# +# Native drivers +# +# CONFIG_SENSORS_AD7314 is not set +# CONFIG_SENSORS_AD7414 is not set +# CONFIG_SENSORS_AD7418 is not set +# CONFIG_SENSORS_ADCXX is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1029 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADT7411 is not set +# CONFIG_SENSORS_ADT7462 is not set +# CONFIG_SENSORS_ADT7470 is not set +# CONFIG_SENSORS_ADT7475 is not set +# CONFIG_SENSORS_ASC7621 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS620 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_I5K_AMB is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_F71882FG is not set +# CONFIG_SENSORS_F75375S is not set +# CONFIG_SENSORS_G760A is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_GPIO_FAN is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_JC42 is not set +# CONFIG_SENSORS_LINEAGE is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM70 is not set +# CONFIG_SENSORS_LM73 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_LM93 is not set +# CONFIG_SENSORS_LTC4151 is not set +# CONFIG_SENSORS_LTC4215 is not set +# CONFIG_SENSORS_LTC4245 is not set +# CONFIG_SENSORS_LTC4261 is not set +# CONFIG_SENSORS_LM95241 is not set +# CONFIG_SENSORS_LM95245 is not set +# CONFIG_SENSORS_MAX1111 is not set +# CONFIG_SENSORS_MAX16065 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_MAX1668 is not set +# CONFIG_SENSORS_MAX6639 is not set +# CONFIG_SENSORS_MAX6642 is not set +# CONFIG_SENSORS_MAX6650 is not set +# CONFIG_SENSORS_MCP3021 is not set +# CONFIG_SENSORS_NTC_THERMISTOR is not set CONFIG_SENSORS_PM8XXX_ADC=y CONFIG_SENSORS_EPM_ADC=y +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_PMBUS is not set +# CONFIG_SENSORS_SHT15 is not set +# CONFIG_SENSORS_SHT21 is not set +# CONFIG_SENSORS_SIS5595 is not set +# CONFIG_SENSORS_SMM665 is not set +# CONFIG_SENSORS_DME1737 is not set +# CONFIG_SENSORS_EMC1403 is not set +# CONFIG_SENSORS_EMC2103 is not set +# CONFIG_SENSORS_EMC6W201 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_SCH56XX_COMMON is not set +# CONFIG_SENSORS_SCH5627 is not set +# CONFIG_SENSORS_SCH5636 is not set +# CONFIG_SENSORS_ADS1015 is not set +# CONFIG_SENSORS_ADS7828 is not set +# CONFIG_SENSORS_ADS7871 is not set +# CONFIG_SENSORS_AMC6821 is not set +# CONFIG_SENSORS_THMC50 is not set +# CONFIG_SENSORS_TMP102 is not set +# CONFIG_SENSORS_TMP401 is not set +# CONFIG_SENSORS_TMP421 is not set +# CONFIG_SENSORS_VIA686A is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_VT8231 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83793 is not set +# CONFIG_SENSORS_W83795 is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83L786NG is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set CONFIG_SENSORS_CAP1106=y CONFIG_CAP_SENSOR_RMNET_CTL=y CONFIG_THERMAL=y +CONFIG_THERMAL_HWMON=y +# CONFIG_THERMAL_MSM_POPMEM is not set +# CONFIG_THERMAL_TSENS is not set CONFIG_THERMAL_TSENS8960=y +# CONFIG_THERMAL_TSENS8974 is not set CONFIG_THERMAL_PM8XXX=y CONFIG_THERMAL_MONITOR=y +# CONFIG_WATCHDOG is not set +CONFIG_SSB_POSSIBLE=y + +# +# Sonics Silicon Backplane +# +# CONFIG_SSB is not set +CONFIG_BCMA_POSSIBLE=y + +# +# Broadcom specific AMBA +# +# CONFIG_BCMA is not set + +# +# Multifunction device drivers +# +CONFIG_MFD_CORE=y +# CONFIG_MFD_88PM860X is not set +# CONFIG_MFD_SM501 is not set +# CONFIG_MFD_ASIC3 is not set +# CONFIG_HTC_EGPIO is not set +# CONFIG_HTC_PASIC3 is not set +# CONFIG_HTC_I2CPLD is not set +# CONFIG_TPS6105X is not set +# CONFIG_TPS65010 is not set +# CONFIG_PMIC8058 is not set +# CONFIG_PMIC8901 is not set +# CONFIG_TPS6507X is not set +# CONFIG_MFD_TPS65217 is not set +# CONFIG_MFD_TPS6586X is not set +# CONFIG_MFD_TPS65910 is not set +# CONFIG_MFD_TPS65912_I2C is not set +# CONFIG_MFD_TPS65912_SPI is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_TWL6040_CORE is not set +# CONFIG_MFD_STMPE is not set +# CONFIG_MFD_TC3589X is not set +# CONFIG_MFD_TMIO is not set +# CONFIG_MFD_T7L66XB is not set +# CONFIG_MFD_TC6387XB is not set +# CONFIG_MFD_TC6393XB is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_MFD_DA9052_SPI is not set +# CONFIG_MFD_DA9052_I2C is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_MAX8925 is not set +# CONFIG_MFD_MAX8997 is not set +# CONFIG_MFD_MAX8998 is not set +# CONFIG_MFD_S5M_CORE is not set +# CONFIG_MFD_WM8400 is not set +# CONFIG_MFD_WM831X_I2C is not set +# CONFIG_MFD_WM831X_SPI is not set +# CONFIG_MFD_WM8350_I2C is not set +# CONFIG_MFD_WM8994 is not set +# CONFIG_MFD_PCF50633 is not set +# CONFIG_MFD_MC13XXX is not set +# CONFIG_ABX500_CORE is not set +# CONFIG_EZX_PCAP is not set +# CONFIG_MFD_TIMBERDALE is not set +# CONFIG_LPC_SCH is not set +# CONFIG_MFD_RDC321X is not set +# CONFIG_MFD_JANZ_CMODIO is not set +# CONFIG_MFD_VX855 is not set +# CONFIG_MFD_WL1273_CORE is not set +CONFIG_MFD_PM8XXX=y CONFIG_MFD_PM8921_CORE=y CONFIG_MFD_PM8821_CORE=y +# CONFIG_MFD_PM8018_CORE is not set CONFIG_MFD_PM8038_CORE=y +CONFIG_MFD_PM8XXX_IRQ=y +CONFIG_MFD_PM8821_IRQ=y +# CONFIG_MFD_TPS65090 is not set +# CONFIG_MFD_AAT2870_CORE is not set +CONFIG_MFD_PM8XXX_DEBUG=y +CONFIG_MFD_PM8XXX_PWM=y +CONFIG_MFD_PM8XXX_MISC=y CONFIG_MFD_PM8XXX_SPK=y CONFIG_MFD_PM8XXX_BATT_ALARM=y CONFIG_WCD9304_CODEC=y CONFIG_WCD9310_CODEC=y +# CONFIG_WCD9320_CODEC is not set +# CONFIG_MFD_RC5T583 is not set +CONFIG_REGULATOR=y +# CONFIG_REGULATOR_DEBUG is not set +# CONFIG_REGULATOR_DUMMY is not set +# CONFIG_REGULATOR_FIXED_VOLTAGE is not set +# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set +# CONFIG_REGULATOR_USERSPACE_CONSUMER is not set +# CONFIG_REGULATOR_GPIO is not set +# CONFIG_REGULATOR_AD5398 is not set +# CONFIG_REGULATOR_ISL6271A is not set +# CONFIG_REGULATOR_MAX1586 is not set +# CONFIG_REGULATOR_MAX8649 is not set +# CONFIG_REGULATOR_MAX8660 is not set +# CONFIG_REGULATOR_MAX8952 is not set +# CONFIG_REGULATOR_LP3971 is not set +# CONFIG_REGULATOR_LP3972 is not set +# CONFIG_REGULATOR_TPS62360 is not set +# CONFIG_REGULATOR_TPS65023 is not set +# CONFIG_REGULATOR_TPS6507X is not set +# CONFIG_REGULATOR_TPS6524X is not set CONFIG_REGULATOR_PM8XXX=y CONFIG_REGULATOR_MSM_GPIO=y +# CONFIG_REGULATOR_STUB is not set CONFIG_MEDIA_SUPPORT=y + +# +# Multimedia core support +# CONFIG_MEDIA_CONTROLLER=y CONFIG_VIDEO_DEV=y +CONFIG_VIDEO_V4L2_COMMON=y CONFIG_VIDEO_V4L2_SUBDEV_API=y +# CONFIG_DVB_CORE is not set +CONFIG_VIDEO_MEDIA=y + +# +# Multimedia drivers +# +CONFIG_RC_CORE=y +CONFIG_LIRC=y CONFIG_USER_RC_INPUT=y +CONFIG_RC_MAP=y +CONFIG_IR_NEC_DECODER=y +CONFIG_IR_RC5_DECODER=y +CONFIG_IR_RC6_DECODER=y +CONFIG_IR_JVC_DECODER=y +CONFIG_IR_SONY_DECODER=y +CONFIG_IR_RC5_SZ_DECODER=y +CONFIG_IR_SANYO_DECODER=y +CONFIG_IR_MCE_KBD_DECODER=y +CONFIG_IR_LIRC_CODEC=y +# CONFIG_RC_ATI_REMOTE is not set +# CONFIG_IR_IMON is not set +# CONFIG_IR_MCEUSB is not set +# CONFIG_IR_REDRAT3 is not set +# CONFIG_IR_STREAMZAP is not set +# CONFIG_RC_LOOPBACK is not set CONFIG_IR_GPIO_CIR=y + +# +# Qualcomm MSM Camera And Video +# # CONFIG_MSM_CAMERA is not set +# CONFIG_IMX111 is not set +# CONFIG_IMX111_ACT is not set +# CONFIG_SEKONIX_LENS_ACT is not set +# CONFIG_IMX119 is not set CONFIG_MSM_CAMERA_SENSOR=y CONFIG_MSM_ACTUATOR=y +# CONFIG_MSM_EEPROM is not set +CONFIG_MSM_GEMINI=y +# CONFIG_MSM_CPP is not set CONFIG_MSM_CCI=y CONFIG_MSM_CSI20_HEADER=y +# CONFIG_MSM_CSI30_HEADER is not set CONFIG_MSM_CSIPHY=y CONFIG_MSM_CSID=y CONFIG_MSM_ISPIF=y +# CONFIG_S5K3L1YX is not set +# CONFIG_MSM_V4L2_VIDEO_OVERLAY_DEVICE is not set CONFIG_OV5693=y CONFIG_MI1040=y CONFIG_MSMB_CAMERA=y -CONFIG_MSM_GEMINI=y +# CONFIG_MSMB_CAMERA_DEBUG is not set +# CONFIG_MEDIA_ATTACH is not set +CONFIG_MEDIA_TUNER=y # CONFIG_MEDIA_TUNER_CUSTOMISE is not set +CONFIG_MEDIA_TUNER_SIMPLE=y +CONFIG_MEDIA_TUNER_TDA8290=y +CONFIG_MEDIA_TUNER_TDA827X=y +CONFIG_MEDIA_TUNER_TDA18271=y +CONFIG_MEDIA_TUNER_TDA9887=y +CONFIG_MEDIA_TUNER_TEA5761=y +CONFIG_MEDIA_TUNER_TEA5767=y +CONFIG_MEDIA_TUNER_MT20XX=y +CONFIG_MEDIA_TUNER_XC2028=y +CONFIG_MEDIA_TUNER_XC5000=y +CONFIG_MEDIA_TUNER_XC4000=y +CONFIG_MEDIA_TUNER_MC44S803=y +CONFIG_VIDEO_V4L2=y +CONFIG_VIDEOBUF2_CORE=y +CONFIG_VIDEOBUF2_MEMOPS=y +CONFIG_VIDEOBUF2_DMA_CONTIG=y +CONFIG_VIDEOBUF2_VMALLOC=y +CONFIG_VIDEOBUF2_DMA_SG=y CONFIG_VIDEOBUF2_MSM_MEM=y +CONFIG_VIDEO_CAPTURE_DRIVERS=y +# CONFIG_VIDEO_ADV_DEBUG is not set +# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set CONFIG_VIDEO_HELPER_CHIPS_AUTO=y +CONFIG_VIDEO_IR_I2C=y + +# +# Audio decoders, processors and mixers +# + +# +# RDS decoders +# + +# +# Video decoders +# + +# +# Video and audio decoders +# + +# +# MPEG video encoders +# + +# +# Video encoders +# + +# +# Camera sensor devices +# + +# +# Flash devices +# + +# +# Video improvement chips +# + +# +# Miscelaneous helper chips +# +CONFIG_MSM_VCAP=y +CONFIG_V4L_USB_DRIVERS=y CONFIG_USB_VIDEO_CLASS=y +CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y +CONFIG_USB_GSPCA=y +# CONFIG_USB_M5602 is not set +# CONFIG_USB_STV06XX is not set +# CONFIG_USB_GL860 is not set +# CONFIG_USB_GSPCA_BENQ is not set +# CONFIG_USB_GSPCA_CONEX is not set +# CONFIG_USB_GSPCA_CPIA1 is not set +# CONFIG_USB_GSPCA_ETOMS is not set +# CONFIG_USB_GSPCA_FINEPIX is not set +# CONFIG_USB_GSPCA_JEILINJ is not set +# CONFIG_USB_GSPCA_JL2005BCD is not set +# CONFIG_USB_GSPCA_KINECT is not set +# CONFIG_USB_GSPCA_KONICA is not set +# CONFIG_USB_GSPCA_MARS is not set +# CONFIG_USB_GSPCA_MR97310A is not set +# CONFIG_USB_GSPCA_NW80X is not set +# CONFIG_USB_GSPCA_OV519 is not set +# CONFIG_USB_GSPCA_OV534 is not set +# CONFIG_USB_GSPCA_OV534_9 is not set +# CONFIG_USB_GSPCA_PAC207 is not set +# CONFIG_USB_GSPCA_PAC7302 is not set +# CONFIG_USB_GSPCA_PAC7311 is not set +# CONFIG_USB_GSPCA_SE401 is not set +# CONFIG_USB_GSPCA_SN9C2028 is not set +# CONFIG_USB_GSPCA_SN9C20X is not set +# CONFIG_USB_GSPCA_SONIXB is not set +# CONFIG_USB_GSPCA_SONIXJ is not set +# CONFIG_USB_GSPCA_SPCA500 is not set +# CONFIG_USB_GSPCA_SPCA501 is not set +# CONFIG_USB_GSPCA_SPCA505 is not set +# CONFIG_USB_GSPCA_SPCA506 is not set +# CONFIG_USB_GSPCA_SPCA508 is not set +# CONFIG_USB_GSPCA_SPCA561 is not set +# CONFIG_USB_GSPCA_SPCA1528 is not set +# CONFIG_USB_GSPCA_SQ905 is not set +# CONFIG_USB_GSPCA_SQ905C is not set +# CONFIG_USB_GSPCA_SQ930X is not set +# CONFIG_USB_GSPCA_STK014 is not set +# CONFIG_USB_GSPCA_STV0680 is not set +# CONFIG_USB_GSPCA_SUNPLUS is not set +# CONFIG_USB_GSPCA_T613 is not set +# CONFIG_USB_GSPCA_TOPRO is not set +# CONFIG_USB_GSPCA_TV8532 is not set +# CONFIG_USB_GSPCA_VC032X is not set +# CONFIG_USB_GSPCA_VICAM is not set +# CONFIG_USB_GSPCA_XIRLINK_CIT is not set +# CONFIG_USB_GSPCA_ZC3XX is not set +# CONFIG_VIDEO_PVRUSB2 is not set +# CONFIG_VIDEO_HDPVR is not set +# CONFIG_VIDEO_EM28XX is not set +# CONFIG_VIDEO_CX231XX is not set +# CONFIG_VIDEO_TM6000 is not set +# CONFIG_VIDEO_USBVISION is not set +# CONFIG_USB_ET61X251 is not set +# CONFIG_USB_SN9C102 is not set +# CONFIG_USB_PWC is not set +# CONFIG_VIDEO_CPIA2 is not set +# CONFIG_USB_ZR364XX is not set +# CONFIG_USB_STKWEBCAM is not set +# CONFIG_USB_S2255 is not set +CONFIG_V4L_PCI_DRIVERS=y +# CONFIG_VIDEO_BT848 is not set +# CONFIG_VIDEO_CX88 is not set +# CONFIG_VIDEO_HEXIUM_GEMINI is not set +# CONFIG_VIDEO_HEXIUM_ORION is not set +# CONFIG_VIDEO_IVTV is not set +# CONFIG_VIDEO_MXB is not set +# CONFIG_VIDEO_SAA7134 is not set CONFIG_V4L_PLATFORM_DRIVERS=y +# CONFIG_VIDEO_CAFE_CCIC is not set +# CONFIG_SOC_CAMERA is not set +# CONFIG_V4L_MEM2MEM_DRIVERS is not set CONFIG_MSM_WFD=y +CONFIG_RADIO_ADAPTERS=y +# CONFIG_RADIO_SI470X is not set +# CONFIG_USB_MR800 is not set +# CONFIG_USB_DSBR is not set +# CONFIG_RADIO_MAXIRADIO is not set +# CONFIG_I2C_SI4713 is not set +# CONFIG_RADIO_SI4713 is not set +# CONFIG_USB_KEENE is not set +# CONFIG_RADIO_TEA5764 is not set +# CONFIG_RADIO_SAA7706H is not set +# CONFIG_RADIO_TEF6862 is not set +# CONFIG_RADIO_WL1273 is not set + +# +# Texas Instruments WL128x FM driver (ST based) +# +# CONFIG_RADIO_WL128X is not set CONFIG_RADIO_IRIS=y +# CONFIG_RADIO_IRIS_TRANSPORT is not set + +# +# Graphics support +# +CONFIG_VGA_ARB=y +CONFIG_VGA_ARB_MAX_GPUS=16 +# CONFIG_DRM is not set +# CONFIG_STUB_POULSBO is not set CONFIG_ION=y CONFIG_ION_MSM=y CONFIG_MSM_KGSL=y +# CONFIG_MSM_KGSL_CFF_DUMP is not set +# CONFIG_MSM_KGSL_PSTMRTMDMP_CP_STAT_NO_DETAIL is not set +# CONFIG_MSM_KGSL_PSTMRTMDMP_NO_IB_DUMP is not set +# CONFIG_MSM_KGSL_PSTMRTMDMP_RB_HEX is not set +CONFIG_MSM_KGSL_2D=y CONFIG_KGSL_PER_PROCESS_PAGE_TABLE=y +CONFIG_MSM_KGSL_PAGE_TABLE_SIZE=0xFFF0000 CONFIG_MSM_KGSL_PAGE_TABLE_COUNT=24 +CONFIG_MSM_KGSL_MMU_PAGE_FAULT=y +# CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES is not set +CONFIG_MSM_KGSL_SIMPLE_GOV=y +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set CONFIG_FB=y +# CONFIG_FIRMWARE_EDID is not set +# CONFIG_FB_DDC is not set +# CONFIG_FB_BOOT_VESA_SUPPORT is not set +CONFIG_FB_CFB_FILLRECT=y +CONFIG_FB_CFB_COPYAREA=y +CONFIG_FB_CFB_IMAGEBLIT=y +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +CONFIG_FB_SYS_FILLRECT=y +CONFIG_FB_SYS_COPYAREA=y +CONFIG_FB_SYS_IMAGEBLIT=y +# CONFIG_FB_FOREIGN_ENDIAN is not set +CONFIG_FB_SYS_FOPS=y +# CONFIG_FB_WMT_GE_ROPS is not set +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +# CONFIG_FB_MODE_HELPERS is not set +# CONFIG_FB_TILEBLITTING is not set + +# +# Frame buffer hardware drivers +# +# CONFIG_FB_CIRRUS is not set +# CONFIG_FB_PM2 is not set +# CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_ASILIANT is not set +# CONFIG_FB_IMSTT is not set +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_NVIDIA is not set +# CONFIG_FB_RIVA is not set +# CONFIG_FB_I740 is not set +# CONFIG_FB_MATROX is not set +# CONFIG_FB_RADEON is not set +# CONFIG_FB_ATY128 is not set +# CONFIG_FB_ATY is not set +# CONFIG_FB_S3 is not set +# CONFIG_FB_SAVAGE is not set +# CONFIG_FB_SIS is not set +# CONFIG_FB_NEOMAGIC is not set +# CONFIG_FB_KYRO is not set +# CONFIG_FB_3DFX is not set +# CONFIG_FB_VOODOO1 is not set +# CONFIG_FB_VT8623 is not set +# CONFIG_FB_TRIDENT is not set +# CONFIG_FB_ARK is not set +# CONFIG_FB_PM3 is not set +# CONFIG_FB_CARMINE is not set +# CONFIG_FB_TMIO is not set +# CONFIG_FB_SMSCUFX is not set +# CONFIG_FB_UDL is not set CONFIG_FB_VIRTUAL=y +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_MB862XX is not set +# CONFIG_FB_BROADSHEET is not set +CONFIG_MSM_VIDC=y +CONFIG_MSM_VIDC_1080P=y +CONFIG_MSM_VIDC_VENC=y +CONFIG_MSM_VIDC_VDEC=y +# CONFIG_MSM_VIDC_CONTENT_PROTECTION is not set CONFIG_FB_MSM=y # CONFIG_FB_MSM_BACKLIGHT is not set +# CONFIG_FB_MSM_LOGO is not set +CONFIG_FB_MSM_LCDC_HW=y CONFIG_FB_MSM_TRIPLE_BUFFER=y +CONFIG_FB_MSM_MDP_HW=y +# CONFIG_FB_MSM_MDP22 is not set +# CONFIG_FB_MSM_MDP30 is not set +# CONFIG_FB_MSM_MDP31 is not set CONFIG_FB_MSM_MDP40=y +# CONFIG_FB_MSM_MDSS is not set +# CONFIG_FB_MSM_MDP_NONE is not set +# CONFIG_FB_MSM_EBI2 is not set +# CONFIG_FB_MSM_MDDI is not set +CONFIG_FB_MSM_MIPI_DSI=y +# CONFIG_FB_MSM_LCDC is not set +# CONFIG_FB_MSM_LVDS is not set CONFIG_FB_MSM_OVERLAY=y +CONFIG_FB_MSM_DTV=y +# CONFIG_FB_MSM_EXTMDDI is not set +# CONFIG_FB_MSM_TVOUT is not set +# CONFIG_FB_MSM_MDDI_TOSHIBA_COMMON is not set +# CONFIG_FB_MSM_MDDI_TOSHIBA_COMMON_VGA is not set +# CONFIG_FB_MSM_MDDI_ORISE is not set +# CONFIG_FB_MSM_MDDI_QUICKVX is not set +# CONFIG_FB_MSM_MDDI_AUTO_DETECT is not set +# CONFIG_FB_MSM_LCDC_AUTO_DETECT is not set +# CONFIG_FB_MSM_LCDC_PANEL is not set +# CONFIG_FB_MSM_MIPI_DSI_TOSHIBA is not set +# CONFIG_FB_MSM_MIPI_DSI_LGIT is not set +# CONFIG_FB_MSM_MIPI_DSI_RENESAS is not set +# CONFIG_FB_MSM_MIPI_DSI_SIMULATOR is not set +CONFIG_FB_MSM_MIPI_DSI_NOVATEK=y +CONFIG_FB_MSM_MIPI_DSI_LG=y +CONFIG_FB_MSM_MIPI_DSI_JDI=y +# CONFIG_FB_MSM_MIPI_DSI_ORISE is not set +# CONFIG_FB_MSM_LCDC_ST15_WXGA is not set +# CONFIG_FB_MSM_LCDC_ST15_PANEL is not set +# CONFIG_FB_MSM_LCDC_PRISM_WVGA is not set +# CONFIG_FB_MSM_LCDC_SAMSUNG_WSVGA is not set +# CONFIG_FB_MSM_LCDC_CHIMEI_WXGA is not set +# CONFIG_FB_MSM_LCDC_GORDON_VGA is not set +# CONFIG_FB_MSM_LCDC_TOSHIBA_WVGA_PT is not set +# CONFIG_FB_MSM_LCDC_TOSHIBA_FWVGA_PT is not set +# CONFIG_FB_MSM_LCDC_SHARP_WVGA_PT is not set +# CONFIG_FB_MSM_LCDC_AUO_WVGA is not set +# CONFIG_FB_MSM_LCDC_TRULY_HVGA_IPS3P2335 is not set +# CONFIG_FB_MSM_LCDC_TRULY_HVGA_IPS3P2335_PT_PANEL is not set +# CONFIG_FB_MSM_LCDC_SAMSUNG_OLED_PT is not set +# CONFIG_FB_MSM_LCDC_NT35582_WVGA is not set +# CONFIG_FB_MSM_LCDC_WXGA is not set +# CONFIG_FB_MSM_MIPI_LGIT_VIDEO_WXGA_PT is not set +# CONFIG_FB_MSM_LVDS_CHIMEI_WXGA is not set +# CONFIG_FB_MSM_MIPI_TOSHIBA_VIDEO_WVGA_PT is not set +# CONFIG_FB_MSM_MIPI_TOSHIBA_VIDEO_WSVGA_PT is not set +# CONFIG_FB_MSM_MIPI_TOSHIBA_VIDEO_WUXGA is not set +# CONFIG_FB_MSM_MIPI_NOVATEK_VIDEO_QHD_PT is not set +# CONFIG_FB_MSM_MIPI_NOVATEK_CMD_QHD_PT is not set +CONFIG_FB_MSM_MIPI_NOVATEK_1080_HD_PT=y +CONFIG_FB_MSM_MIPI_LG_1080_HD_PT=y +CONFIG_FB_MSM_MIPI_JDI_1080_HD_PT=y +# CONFIG_FB_MSM_MIPI_ORISE_VIDEO_720P_PT is not set +# CONFIG_FB_MSM_MIPI_ORISE_CMD_720P_PT is not set +# CONFIG_FB_MSM_MIPI_RENESAS_VIDEO_FWVGA_PT is not set +# CONFIG_FB_MSM_MIPI_RENESAS_CMD_FWVGA_PT is not set +# CONFIG_FB_MSM_MIPI_NT35510_VIDEO_WVGA_PT is not set +# CONFIG_FB_MSM_MIPI_NT35510_CMD_WVGA_PT is not set +# CONFIG_FB_MSM_MIPI_NT35516_VIDEO_QHD_PT is not set +# CONFIG_FB_MSM_MIPI_NT35516_CMD_QHD_PT is not set +# CONFIG_FB_MSM_MIPI_CHIMEI_WXGA is not set +# CONFIG_FB_MSM_MIPI_CHIMEI_WUXGA is not set +# CONFIG_FB_MSM_MIPI_SIMULATOR_VIDEO is not set CONFIG_FB_MSM_NO_MDP_PIPE_CTRL=y CONFIG_FB_MSM_OVERLAY0_WRITEBACK=y CONFIG_FB_MSM_OVERLAY1_WRITEBACK=y +# CONFIG_FB_MSM_WRITEBACK_MSM_PANEL is not set CONFIG_FB_MSM_MIPI_NOVATEK_VIDEO_MODE=y CONFIG_FB_MSM_MIPI_LG_VIDEO_MODE=y CONFIG_FB_MSM_MIPI_JDI_CMD_MODE=y +CONFIG_FB_MSM_EXT_INTERFACE_COMMON=y +CONFIG_FB_MSM_HDMI_COMMON=y +CONFIG_FB_MSM_HDMI_3D=y +# CONFIG_FB_MSM_HDMI_ADV7520_PANEL is not set CONFIG_FB_MSM_HDMI_MSM_PANEL=y +# CONFIG_FB_MSM_HDMI_MSM_PANEL_DVI_SUPPORT is not set +# CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT is not set +# CONFIG_FB_MSM_HDMI_MHL_9244 is not set +# CONFIG_FB_MSM_HDMI_MHL_8334 is not set +# CONFIG_FB_MSM_TVOUT_NTSC_M is not set +# CONFIG_FB_MSM_TVOUT_NTSC_J is not set +# CONFIG_FB_MSM_TVOUT_PAL_BDGHIN is not set +# CONFIG_FB_MSM_TVOUT_PAL_M is not set +# CONFIG_FB_MSM_TVOUT_PAL_N is not set +CONFIG_FB_MSM_TVOUT_NONE=y +# CONFIG_FB_MSM_DEFAULT_DEPTH_RGB565 is not set +# CONFIG_FB_MSM_DEFAULT_DEPTH_ARGB8888 is not set +CONFIG_FB_MSM_DEFAULT_DEPTH_RGBA8888=y +# CONFIG_FB_MSM_EBI2_EPSON_S1D_QVGA_PANEL is not set +# CONFIG_FB_MSM_EBI2_PANEL_DETECT is not set +# CONFIG_EXYNOS_VIDEO is not set CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_LCD_CLASS_DEVICE=y +# CONFIG_LCD_L4F00242T03 is not set +# CONFIG_LCD_LMS283GF05 is not set +# CONFIG_LCD_LTV350QV is not set +# CONFIG_LCD_TDO24M is not set +# CONFIG_LCD_VGG2432A4 is not set +# CONFIG_LCD_PLATFORM is not set +# CONFIG_LCD_S6E63M0 is not set +# CONFIG_LCD_LD9040 is not set +# CONFIG_LCD_AMS369FG06 is not set +CONFIG_BACKLIGHT_CLASS_DEVICE=y +CONFIG_BACKLIGHT_GENERIC=y +# CONFIG_BACKLIGHT_ADP8860 is not set +# CONFIG_BACKLIGHT_ADP8870 is not set +# CONFIG_BACKLIGHT_LP855X is not set +# CONFIG_BACKLIGHT_LM3530 is not set +# CONFIG_BACKLIGHT_LM3533 is not set + +# +# Console display driver support +# +CONFIG_DUMMY_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE is not set +# CONFIG_LOGO is not set CONFIG_SOUND=y +# CONFIG_SOUND_OSS_CORE is not set CONFIG_SND=y +CONFIG_SND_TIMER=y +CONFIG_SND_PCM=y +CONFIG_SND_HWDEP=y +CONFIG_SND_RAWMIDI=y +CONFIG_SND_COMPRESS_OFFLOAD=y +CONFIG_SND_JACK=y +# CONFIG_SND_SEQUENCER is not set +# CONFIG_SND_MIXER_OSS is not set +# CONFIG_SND_PCM_OSS is not set +# CONFIG_SND_HRTIMER is not set CONFIG_SND_DYNAMIC_MINORS=y +CONFIG_SND_SUPPORT_OLD_API=y +CONFIG_SND_VERBOSE_PROCFS=y +# CONFIG_SND_VERBOSE_PRINTK is not set +# CONFIG_SND_DEBUG is not set +# CONFIG_SND_RAWMIDI_SEQ is not set +# CONFIG_SND_OPL3_LIB_SEQ is not set +# CONFIG_SND_OPL4_LIB_SEQ is not set +# CONFIG_SND_SBAWE_SEQ is not set +# CONFIG_SND_EMU10K1_SEQ is not set +CONFIG_SND_DRIVERS=y +# CONFIG_SND_DUMMY is not set +# CONFIG_SND_ALOOP is not set +# CONFIG_SND_MTPAV is not set +# CONFIG_SND_SERIAL_U16550 is not set +# CONFIG_SND_MPU401 is not set +CONFIG_SND_PCI=y +# CONFIG_SND_AD1889 is not set +# CONFIG_SND_ALS300 is not set +# CONFIG_SND_ALI5451 is not set +# CONFIG_SND_ATIIXP is not set +# CONFIG_SND_ATIIXP_MODEM is not set +# CONFIG_SND_AU8810 is not set +# CONFIG_SND_AU8820 is not set +# CONFIG_SND_AU8830 is not set +# CONFIG_SND_AW2 is not set +# CONFIG_SND_AZT3328 is not set +# CONFIG_SND_BT87X is not set +# CONFIG_SND_CA0106 is not set +# CONFIG_SND_CMIPCI is not set +# CONFIG_SND_OXYGEN is not set +# CONFIG_SND_CS4281 is not set +# CONFIG_SND_CS46XX is not set +# CONFIG_SND_CS5535AUDIO is not set +# CONFIG_SND_CTXFI is not set +# CONFIG_SND_DARLA20 is not set +# CONFIG_SND_GINA20 is not set +# CONFIG_SND_LAYLA20 is not set +# CONFIG_SND_DARLA24 is not set +# CONFIG_SND_GINA24 is not set +# CONFIG_SND_LAYLA24 is not set +# CONFIG_SND_MONA is not set +# CONFIG_SND_MIA is not set +# CONFIG_SND_ECHO3G is not set +# CONFIG_SND_INDIGO is not set +# CONFIG_SND_INDIGOIO is not set +# CONFIG_SND_INDIGODJ is not set +# CONFIG_SND_INDIGOIOX is not set +# CONFIG_SND_INDIGODJX is not set +# CONFIG_SND_EMU10K1 is not set +# CONFIG_SND_EMU10K1X is not set +# CONFIG_SND_ENS1370 is not set +# CONFIG_SND_ENS1371 is not set +# CONFIG_SND_ES1938 is not set +# CONFIG_SND_ES1968 is not set +# CONFIG_SND_FM801 is not set +# CONFIG_SND_HDA_INTEL is not set +# CONFIG_SND_HDSP is not set +# CONFIG_SND_HDSPM is not set +# CONFIG_SND_ICE1712 is not set +# CONFIG_SND_ICE1724 is not set +# CONFIG_SND_INTEL8X0 is not set +# CONFIG_SND_INTEL8X0M is not set +# CONFIG_SND_KORG1212 is not set +# CONFIG_SND_LOLA is not set +# CONFIG_SND_LX6464ES is not set +# CONFIG_SND_MAESTRO3 is not set +# CONFIG_SND_MIXART is not set +# CONFIG_SND_NM256 is not set +# CONFIG_SND_PCXHR is not set +# CONFIG_SND_RIPTIDE is not set +# CONFIG_SND_RME32 is not set +# CONFIG_SND_RME96 is not set +# CONFIG_SND_RME9652 is not set +# CONFIG_SND_SONICVIBES is not set +# CONFIG_SND_TRIDENT is not set +# CONFIG_SND_VIA82XX is not set +# CONFIG_SND_VIA82XX_MODEM is not set +# CONFIG_SND_VIRTUOSO is not set +# CONFIG_SND_VX222 is not set +# CONFIG_SND_YMFPCI is not set +CONFIG_SND_ARM=y +CONFIG_SND_SPI=y +CONFIG_SND_USB=y CONFIG_SND_USB_AUDIO=y +# CONFIG_SND_USB_UA101 is not set +# CONFIG_SND_USB_CAIAQ is not set +# CONFIG_SND_USB_6FIRE is not set CONFIG_SND_SOC=y + +# +# MSM SoC Audio support +# +CONFIG_SND_SOC_MSM_HOSTLESS_PCM=y +CONFIG_SND_SOC_MSM_QDSP6_HDMI_AUDIO=y +CONFIG_SND_SOC_MSM_QDSP6_INTF=y +# CONFIG_SND_SOC_MSM_QDSP6V2_INTF is not set +CONFIG_SND_SOC_VOICE=y +CONFIG_SND_SOC_QDSP6=y +# CONFIG_SND_SOC_QDSP6V2 is not set CONFIG_SND_SOC_MSM8960=y +# CONFIG_SND_SOC_DUAL_AMIC is not set CONFIG_ASUSTEK_HEADSET=y +CONFIG_SND_SOC_I2C_AND_SPI=y +# CONFIG_SND_SOC_ALL_CODECS is not set +CONFIG_SND_SOC_WCD9304=y +CONFIG_SND_SOC_WCD9310=y +CONFIG_SND_SOC_CS8427=y +CONFIG_SND_SOC_MSM_STUB=y +# CONFIG_SND_SOC_TPA2028D is not set +CONFIG_SOUND_CONTROL_HAX_GPL=y +CONFIG_SOUND_CONTROL_HAX_3_GPL=y +# CONFIG_SOUND_PRIME is not set +CONFIG_HID_SUPPORT=y +CONFIG_HID=y +# CONFIG_HID_BATTERY_STRENGTH is not set +# CONFIG_HIDRAW is not set CONFIG_UHID=y + +# +# USB Input Devices +# +CONFIG_USB_HID=y +# CONFIG_HID_PID is not set +# CONFIG_USB_HIDDEV is not set + +# +# Special HID drivers +# CONFIG_HID_A4TECH=y CONFIG_HID_ACRUX=y CONFIG_HID_ACRUX_FF=y @@ -384,10 +2994,12 @@ CONFIG_HID_CHICONY=y CONFIG_HID_PRODIKEYS=y CONFIG_HID_CYPRESS=y CONFIG_HID_DRAGONRISE=y +# CONFIG_DRAGONRISE_FF is not set CONFIG_HID_EMS_FF=y CONFIG_HID_ELECOM=y CONFIG_HID_EZKEY=y CONFIG_HID_HOLTEK=y +# CONFIG_HOLTEK_FF is not set CONFIG_HID_KEYTOUCH=y CONFIG_HID_KYE=y CONFIG_HID_UCLOGIC=y @@ -397,6 +3009,11 @@ CONFIG_HID_TWINHAN=y CONFIG_HID_KENSINGTON=y CONFIG_HID_LCPOWER=y CONFIG_HID_LOGITECH=y +CONFIG_HID_LOGITECH_DJ=y +# CONFIG_LOGITECH_FF is not set +# CONFIG_LOGIRUMBLEPAD2_FF is not set +# CONFIG_LOGIG940_FF is not set +# CONFIG_LOGIWHEELS_FF is not set CONFIG_HID_MAGICMOUSE=y CONFIG_HID_MICROSOFT=y CONFIG_HID_MONTEREY=y @@ -404,8 +3021,13 @@ CONFIG_HID_MULTITOUCH=y CONFIG_HID_NTRIG=y CONFIG_HID_ORTEK=y CONFIG_HID_PANTHERLORD=y +# CONFIG_PANTHERLORD_FF is not set CONFIG_HID_PETALYNX=y CONFIG_HID_PICOLCD=y +# CONFIG_HID_PICOLCD_FB is not set +# CONFIG_HID_PICOLCD_BACKLIGHT is not set +# CONFIG_HID_PICOLCD_LCD is not set +# CONFIG_HID_PICOLCD_LEDS is not set CONFIG_HID_PRIMAX=y CONFIG_HID_ROCCAT=y CONFIG_HID_SAITEK=y @@ -414,23 +3036,86 @@ CONFIG_HID_SONY=y CONFIG_HID_SPEEDLINK=y CONFIG_HID_SUNPLUS=y CONFIG_HID_GREENASIA=y +# CONFIG_GREENASIA_FF is not set CONFIG_HID_SMARTJOYPLUS=y +# CONFIG_SMARTJOYPLUS_FF is not set CONFIG_HID_TIVO=y CONFIG_HID_TOPSEED=y CONFIG_HID_THRUSTMASTER=y +# CONFIG_THRUSTMASTER_FF is not set CONFIG_HID_WACOM=y +# CONFIG_HID_WACOM_POWER_SUPPLY is not set +# CONFIG_HID_WIIMOTE is not set CONFIG_HID_ZEROPLUS=y +# CONFIG_ZEROPLUS_FF is not set CONFIG_HID_ZYDACRON=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +CONFIG_USB_ARCH_HAS_XHCI=y +CONFIG_USB_SUPPORT=y +CONFIG_USB_COMMON=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set CONFIG_USB_ANNOUNCE_NEW_DEVICES=y + +# +# Miscellaneous USB options +# CONFIG_USB_DEVICEFS=y +CONFIG_USB_DEVICE_CLASS=y +# CONFIG_USB_DYNAMIC_MINORS is not set CONFIG_USB_SUSPEND=y +# CONFIG_USB_OTG is not set +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +# CONFIG_USB_DWC3 is not set +# CONFIG_USB_MON is not set +# CONFIG_USB_WUSB_CBAF is not set + +# +# USB Host Controller Drivers +# +# CONFIG_USB_C67X00_HCD is not set +# CONFIG_USB_XHCI_HCD is not set CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_EHSET=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_EHCI_TT_NEWSCHED=y CONFIG_USB_EHCI_MSM=y CONFIG_USB_EHCI_MSM_HSIC=y CONFIG_USB_EHCI_MSM_HOST4=y +# CONFIG_USB_OXU210HP_HCD is not set +# CONFIG_USB_ISP116X_HCD is not set +# CONFIG_USB_ISP1760_HCD is not set +# CONFIG_USB_ISP1362_HCD is not set +# CONFIG_USB_OHCI_HCD is not set +# CONFIG_USB_EHCI_HCD_PLATFORM is not set +# CONFIG_USB_UHCI_HCD is not set +# CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_PEHCI_HCD is not set +# CONFIG_USB_MUSB_HDRC is not set +# CONFIG_USB_RENESAS_USBHS is not set + +# +# USB Device Class drivers +# CONFIG_USB_ACM=y +# CONFIG_USB_PRINTER is not set +CONFIG_USB_WDM=y +# CONFIG_USB_TMC is not set + +# +# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may +# + +# +# also be needed; see USB_STORAGE Help for more info +# CONFIG_USB_STORAGE=y +# CONFIG_USB_STORAGE_DEBUG is not set +# CONFIG_USB_STORAGE_REALTEK is not set CONFIG_USB_STORAGE_DATAFAB=y CONFIG_USB_STORAGE_FREECOM=y CONFIG_USB_STORAGE_ISD200=y @@ -442,98 +3127,886 @@ CONFIG_USB_STORAGE_ALAUDA=y CONFIG_USB_STORAGE_ONETOUCH=y CONFIG_USB_STORAGE_KARMA=y CONFIG_USB_STORAGE_CYPRESS_ATACB=y +# CONFIG_USB_STORAGE_ENE_UB6250 is not set +# CONFIG_USB_UAS is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set + +# +# USB port drivers +# CONFIG_USB_SERIAL=y +# CONFIG_USB_SERIAL_CONSOLE is not set +# CONFIG_USB_EZUSB is not set +CONFIG_USB_SERIAL_GENERIC=y +# CONFIG_USB_SERIAL_AIRCABLE is not set +# CONFIG_USB_SERIAL_ARK3116 is not set +# CONFIG_USB_SERIAL_BELKIN is not set +# CONFIG_USB_SERIAL_CH341 is not set +# CONFIG_USB_SERIAL_WHITEHEAT is not set +# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set +# CONFIG_USB_SERIAL_CP210X is not set +# CONFIG_USB_SERIAL_CYPRESS_M8 is not set +# CONFIG_USB_SERIAL_EMPEG is not set +# CONFIG_USB_SERIAL_FTDI_SIO is not set +# CONFIG_USB_SERIAL_FUNSOFT is not set +# CONFIG_USB_SERIAL_VISOR is not set +# CONFIG_USB_SERIAL_IPAQ is not set +# CONFIG_USB_SERIAL_IR is not set +# CONFIG_USB_SERIAL_EDGEPORT is not set +# CONFIG_USB_SERIAL_EDGEPORT_TI is not set +# CONFIG_USB_SERIAL_F81232 is not set +# CONFIG_USB_SERIAL_GARMIN is not set +# CONFIG_USB_SERIAL_IPW is not set +# CONFIG_USB_SERIAL_IUU is not set +# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set +# CONFIG_USB_SERIAL_KEYSPAN is not set +# CONFIG_USB_SERIAL_KLSI is not set +# CONFIG_USB_SERIAL_KOBIL_SCT is not set +# CONFIG_USB_SERIAL_MCT_U232 is not set +# CONFIG_USB_SERIAL_METRO is not set +# CONFIG_USB_SERIAL_MOS7720 is not set +# CONFIG_USB_SERIAL_MOS7840 is not set +# CONFIG_USB_SERIAL_MOTOROLA is not set +# CONFIG_USB_SERIAL_NAVMAN is not set +CONFIG_USB_SERIAL_PL2303=y +# CONFIG_USB_SERIAL_OTI6858 is not set +# CONFIG_USB_SERIAL_QCAUX is not set +# CONFIG_USB_SERIAL_QUALCOMM is not set +# CONFIG_USB_SERIAL_SPCP8X5 is not set +# CONFIG_USB_SERIAL_HP4X is not set +# CONFIG_USB_SERIAL_SAFE is not set +# CONFIG_USB_SERIAL_SIEMENS_MPI is not set +# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set +# CONFIG_USB_SERIAL_SYMBOL is not set +# CONFIG_USB_SERIAL_TI is not set +# CONFIG_USB_SERIAL_CYBERJACK is not set +# CONFIG_USB_SERIAL_XIRCOM is not set +CONFIG_USB_SERIAL_WWAN=y +CONFIG_USB_SERIAL_OPTION=y +# CONFIG_USB_SERIAL_OMNINET is not set +# CONFIG_USB_SERIAL_OPTICON is not set +# CONFIG_USB_SERIAL_VIVOPAY_SERIAL is not set +# CONFIG_USB_SERIAL_ZIO is not set +# CONFIG_USB_SERIAL_SSU100 is not set CONFIG_USB_SERIAL_CSVT=y +# CONFIG_USB_SERIAL_DEBUG is not set + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_ADUTUX is not set +# CONFIG_USB_SEVSEG is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set +# CONFIG_USB_CYTHERM is not set +# CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_FTDI_ELAN is not set +# CONFIG_USB_APPLEDISPLAY is not set +# CONFIG_USB_SISUSBVGA is not set +# CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set +# CONFIG_USB_TEST is not set CONFIG_USB_EHSET_TEST_FIXTURE=y +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_YUREX is not set CONFIG_USB_QCOM_DIAG_BRIDGE=y +# CONFIG_USB_QCOM_DIAG_BRIDGE_TEST is not set CONFIG_USB_QCOM_MDM_BRIDGE=y CONFIG_USB_QCOM_KS_BRIDGE=y CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_DEBUG is not set CONFIG_USB_GADGET_DEBUG_FILES=y +# CONFIG_USB_GADGET_DEBUG_FS is not set +CONFIG_USB_GADGET_VBUS_DRAW=500 +CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 + +# +# USB Peripheral Controller +# +# CONFIG_USB_FUSB300 is not set +# CONFIG_USB_R8A66597 is not set +# CONFIG_USB_MV_UDC is not set +# CONFIG_USB_M66592 is not set +# CONFIG_USB_AMD5536UDC is not set +# CONFIG_USB_CI13XXX_PCI is not set +# CONFIG_USB_NET2272 is not set +# CONFIG_USB_NET2280 is not set +# CONFIG_USB_GOKU is not set +# CONFIG_USB_LANGWELL is not set +# CONFIG_USB_EG20T is not set CONFIG_USB_CI13XXX_MSM=y +# CONFIG_USB_CI13XXX_MSM_HSIC is not set +# CONFIG_USB_DWC3_MSM is not set +# CONFIG_USB_MSM_72K is not set +# CONFIG_USB_DUMMY_HCD is not set +CONFIG_USB_GADGET_DUALSPEED=y +# CONFIG_USB_GADGET_SUPERSPEED is not set +# CONFIG_USB_ZERO is not set +# CONFIG_USB_AUDIO is not set +# CONFIG_USB_ETH is not set +# CONFIG_USB_G_NCM is not set +# CONFIG_USB_GADGETFS is not set +# CONFIG_USB_FUNCTIONFS is not set +# CONFIG_USB_FILE_STORAGE is not set +# CONFIG_USB_MASS_STORAGE is not set +# CONFIG_USB_G_SERIAL is not set +# CONFIG_USB_MIDI_GADGET is not set +# CONFIG_USB_G_PRINTER is not set CONFIG_USB_G_ANDROID=y +# CONFIG_USB_CDC_COMPOSITE is not set +# CONFIG_USB_G_ACM_MS is not set +# CONFIG_USB_G_MULTI is not set +# CONFIG_USB_G_HID is not set +# CONFIG_USB_G_DBGP is not set +# CONFIG_USB_G_WEBCAM is not set +CONFIG_USB_CSW_HACK=y +# CONFIG_USB_MSC_PROFILING is not set +CONFIG_MODEM_SUPPORT=y +CONFIG_RMNET_SMD_CTL_CHANNEL="" +CONFIG_RMNET_SMD_DATA_CHANNEL="" +# CONFIG_USB_ANDROID_CDC_ECM is not set + +# +# OTG and related infrastructure +# +CONFIG_USB_OTG_UTILS=y +# CONFIG_USB_OTG_WAKELOCK is not set +# CONFIG_USB_GPIO_VBUS is not set +# CONFIG_USB_ULPI is not set +# CONFIG_USB_MSM_OTG_72K is not set +# CONFIG_NOP_USB_XCEIV is not set +CONFIG_USB_MSM_OTG=y +# CONFIG_USB_MSM_ACA is not set +# CONFIG_UWB is not set CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set CONFIG_MMC_PERF_PROFILING=y CONFIG_MMC_UNSAFE_RESUME=y CONFIG_MMC_CLKGATE=y +# CONFIG_MMC_EMBEDDED_SDIO is not set CONFIG_MMC_PARANOID_SD_INIT=y + +# +# MMC/SD/SDIO Card Drivers +# +CONFIG_MMC_BLOCK=y +# CONFIG_MMC_SECDISCARD is not set CONFIG_MMC_BLOCK_MINORS=32 # CONFIG_MMC_BLOCK_BOUNCE is not set +# CONFIG_MMC_BLOCK_DEFERRED_RESUME is not set +# CONFIG_SDIO_UART is not set +# CONFIG_MMC_TEST is not set + +# +# MMC/SD/SDIO Host Controller Drivers +# +# CONFIG_MMC_SDHCI is not set +# CONFIG_MMC_SDHCI_PXAV3 is not set +# CONFIG_MMC_SDHCI_PXAV2 is not set CONFIG_MMC_MSM=y +# CONFIG_MMC_TIFM_SD is not set +CONFIG_MMC_MSM_SDC1_SUPPORT=y CONFIG_MMC_MSM_SDC1_8_BIT_SUPPORT=y # CONFIG_MMC_MSM_SDC2_SUPPORT is not set +# CONFIG_MMC_MSM_SDC3_SUPPORT is not set +# CONFIG_MMC_MSM_SDC3_POLLING is not set +# CONFIG_MMC_MSM_SDC4_SUPPORT is not set +# CONFIG_MMC_MSM_SDC5_SUPPORT is not set CONFIG_MMC_MSM_SPS_SUPPORT=y +# CONFIG_MMC_CB710 is not set +# CONFIG_MMC_VIA_SDMMC is not set +# CONFIG_MMC_DW is not set +# CONFIG_MMC_VUB300 is not set +# CONFIG_MMC_USHC is not set +# CONFIG_MEMSTICK is not set +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y + +# +# LED drivers +# +# CONFIG_LEDS_LM3530 is not set +# CONFIG_LEDS_PCA9532 is not set +# CONFIG_LEDS_GPIO is not set +# CONFIG_LEDS_MSM_PDM is not set +# CONFIG_LEDS_PMIC_MPP is not set +# CONFIG_LEDS_MSM_TRICOLOR is not set +# CONFIG_LEDS_LP3944 is not set +# CONFIG_LEDS_CPLD is not set +# CONFIG_LEDS_LP5521 is not set +# CONFIG_LEDS_LP5523 is not set +# CONFIG_LEDS_PCA955X is not set CONFIG_LEDS_PM8XXX=y +# CONFIG_LEDS_PCA9633 is not set +# CONFIG_LEDS_DAC124S085 is not set +# CONFIG_LEDS_REGULATOR is not set +# CONFIG_LEDS_BD2802 is not set +# CONFIG_LEDS_MSM_PMIC is not set +# CONFIG_LEDS_LT3593 is not set +# CONFIG_LEDS_RENESAS_TPU is not set +# CONFIG_LEDS_TCA6507 is not set +# CONFIG_LEDS_OT200 is not set CONFIG_LEDS_TRIGGERS=y + +# +# LED Triggers +# +# CONFIG_LEDS_TRIGGER_TIMER is not set CONFIG_LEDS_TRIGGER_HEARTBEAT=y +# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set +# CONFIG_LEDS_TRIGGER_GPIO is not set +# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set +# CONFIG_LEDS_TRIGGER_SLEEP is not set + +# +# iptables trigger is under Netfilter config (LED target) +# CONFIG_SWITCH=y +# CONFIG_SWITCH_GPIO is not set +# CONFIG_SWITCH_FSA8008 is not set +# CONFIG_ACCESSIBILITY is not set +# CONFIG_INFINIBAND is not set +CONFIG_RTC_LIB=y CONFIG_RTC_CLASS=y +CONFIG_RTC_HCTOSYS=y +CONFIG_RTC_HCTOSYS_DEVICE="rtc0" +# CONFIG_RTC_DEBUG is not set + +# +# RTC interfaces +# +CONFIG_RTC_INTF_SYSFS=y +CONFIG_RTC_INTF_PROC=y +CONFIG_RTC_INTF_DEV=y +CONFIG_RTC_INTF_ALARM=y +CONFIG_RTC_INTF_ALARM_DEV=y +# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set +# CONFIG_RTC_DRV_TEST is not set + +# +# I2C RTC drivers +# +# CONFIG_RTC_DRV_DS1307 is not set +# CONFIG_RTC_DRV_DS1374 is not set +# CONFIG_RTC_DRV_DS1672 is not set +# CONFIG_RTC_DRV_DS3232 is not set +# CONFIG_RTC_DRV_MAX6900 is not set +# CONFIG_RTC_DRV_RS5C372 is not set +# CONFIG_RTC_DRV_ISL1208 is not set +# CONFIG_RTC_DRV_ISL12022 is not set +# CONFIG_RTC_DRV_X1205 is not set +# CONFIG_RTC_DRV_PCF8563 is not set +# CONFIG_RTC_DRV_PCF8583 is not set +# CONFIG_RTC_DRV_M41T80 is not set +# CONFIG_RTC_DRV_BQ32K is not set +# CONFIG_RTC_DRV_S35390A is not set +# CONFIG_RTC_DRV_FM3130 is not set +# CONFIG_RTC_DRV_RX8581 is not set +# CONFIG_RTC_DRV_RX8025 is not set +# CONFIG_RTC_DRV_EM3027 is not set +# CONFIG_RTC_DRV_RV3029C2 is not set + +# +# SPI RTC drivers +# +# CONFIG_RTC_DRV_M41T93 is not set +# CONFIG_RTC_DRV_M41T94 is not set +# CONFIG_RTC_DRV_DS1305 is not set +# CONFIG_RTC_DRV_DS1390 is not set +# CONFIG_RTC_DRV_MAX6902 is not set +# CONFIG_RTC_DRV_R9701 is not set +# CONFIG_RTC_DRV_RS5C348 is not set +# CONFIG_RTC_DRV_DS3234 is not set +# CONFIG_RTC_DRV_PCF2123 is not set + +# +# Platform RTC drivers +# +# CONFIG_RTC_DRV_CMOS is not set +# CONFIG_RTC_DRV_DS1286 is not set +# CONFIG_RTC_DRV_DS1511 is not set +# CONFIG_RTC_DRV_DS1553 is not set +# CONFIG_RTC_DRV_DS1742 is not set +# CONFIG_RTC_DRV_STK17TA8 is not set +# CONFIG_RTC_DRV_M48T86 is not set +# CONFIG_RTC_DRV_M48T35 is not set +# CONFIG_RTC_DRV_M48T59 is not set +# CONFIG_RTC_DRV_MSM6242 is not set +# CONFIG_RTC_DRV_BQ4802 is not set +# CONFIG_RTC_DRV_RP5C01 is not set +# CONFIG_RTC_DRV_V3020 is not set + +# +# on-CPU RTC drivers +# # CONFIG_RTC_DRV_MSM is not set +# CONFIG_RTC_DRV_MSM7X00A is not set CONFIG_RTC_DRV_PM8XXX=y +# CONFIG_DMADEVICES is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_UIO is not set + +# +# Virtio drivers +# +# CONFIG_VIRTIO_PCI is not set +# CONFIG_VIRTIO_BALLOON is not set +# CONFIG_VIRTIO_MMIO is not set + +# +# Microsoft Hyper-V guest support +# CONFIG_STAGING=y +# CONFIG_ET131X is not set +# CONFIG_USBIP_CORE is not set +# CONFIG_PRISM2_USB is not set +# CONFIG_ECHO is not set +# CONFIG_ASUS_OLED is not set +# CONFIG_R8187SE is not set +# CONFIG_RTL8192U is not set +# CONFIG_RTLLIB is not set +# CONFIG_R8712U is not set +# CONFIG_RTS_PSTOR is not set +# CONFIG_RTS5139 is not set +# CONFIG_TRANZPORT is not set +# CONFIG_LINE6_USB is not set +# CONFIG_USB_SERIAL_QUATECH2 is not set +# CONFIG_USB_SERIAL_QUATECH_USB2 is not set +# CONFIG_VT6655 is not set +# CONFIG_VT6656 is not set +# CONFIG_VME_BUS is not set +# CONFIG_DX_SEP is not set +# CONFIG_IIO is not set +CONFIG_QCACHE=y +# CONFIG_FB_SM7XX is not set +# CONFIG_CRYSTALHD is not set +# CONFIG_FB_XGI is not set +# CONFIG_USB_ENESTORAGE is not set +# CONFIG_BCM_WIMAX is not set +# CONFIG_FT1000 is not set + +# +# Speakup console speech +# +# CONFIG_SPEAKUP is not set +# CONFIG_TOUCHSCREEN_CLEARPAD_TM1217 is not set +# CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4 is not set +# CONFIG_STAGING_MEDIA is not set + +# +# Android +# CONFIG_ANDROID=y CONFIG_ANDROID_BINDER_IPC=y CONFIG_ASHMEM=y CONFIG_ANDROID_LOGGER=y +CONFIG_ANDROID_PERSISTENT_RAM=y CONFIG_ANDROID_RAM_CONSOLE=y +# CONFIG_PERSISTENT_TRACER is not set +CONFIG_ANDROID_TIMED_OUTPUT=y CONFIG_ANDROID_TIMED_GPIO=y CONFIG_ANDROID_LOW_MEMORY_KILLER=y +CONFIG_ANDROID_LOW_MEMORY_KILLER_AUTODETECT_OOM_ADJ_VALUES=y +# CONFIG_ANDROID_SWITCH is not set +# CONFIG_ANDROID_INTF_ALARM_DEV is not set +# CONFIG_PHONE is not set +# CONFIG_USB_WPAN_HCD is not set + +# +# Qualcomm Atheros Prima WLAN module +# CONFIG_PRIMA_WLAN=y +# CONFIG_PRIMA_WLAN_BTAMP is not set CONFIG_PRIMA_WLAN_LFR=y CONFIG_PRIMA_WLAN_OKC=y +# CONFIG_PRIMA_WLAN_11AC_HIGH_TP is not set +CONFIG_CPUPOWER=y + +# +# Qualcomm MSM specific device drivers +# CONFIG_MSM_SSBI=y CONFIG_SPS=y +# CONFIG_USB_BAM is not set CONFIG_SPS_SUPPORT_BAMDMA=y +# CONFIG_SPS_SUPPORT_NDP_BAM is not set +CONFIG_CLKDEV_LOOKUP=y +CONFIG_HAVE_CLK_PREPARE=y + +# +# Hardware Spinlock drivers +# +CONFIG_IOMMU_SUPPORT=y CONFIG_MSM_IOMMU=y +CONFIG_MSM_IOMMU_GPU_SYNC=y +CONFIG_IOMMU_PGTABLES_L2=y + +# +# Remoteproc drivers (EXPERIMENTAL) +# + +# +# Rpmsg drivers (EXPERIMENTAL) +# +# CONFIG_VIRT_DRIVERS is not set +# CONFIG_PM_DEVFREQ is not set +# CONFIG_MOBICORE_SUPPORT is not set +# CONFIG_CORESIGHT is not set + +# +# File systems +# CONFIG_EXT2_FS=y CONFIG_EXT2_FS_XATTR=y +# CONFIG_EXT2_FS_POSIX_ACL is not set +# CONFIG_EXT2_FS_SECURITY is not set +# CONFIG_EXT2_FS_XIP is not set CONFIG_EXT3_FS=y # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_XATTR=y +# CONFIG_EXT4_FS_POSIX_ACL is not set CONFIG_EXT4_FS_SECURITY=y +# CONFIG_EXT4_DEBUG is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_JBD2=y +# CONFIG_JBD2_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_BTRFS_FS is not set +# CONFIG_NILFS2_FS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_FILE_LOCKING=y +CONFIG_FSNOTIFY=y +CONFIG_DNOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_FANOTIFY is not set +# CONFIG_QUOTA is not set +# CONFIG_QUOTACTL is not set +# CONFIG_AUTOFS4_FS is not set CONFIG_FUSE_FS=y +# CONFIG_CUSE is not set + +# +# Caches +# +# CONFIG_FSCACHE is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +# CONFIG_MSDOS_FS is not set CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +CONFIG_NTFS_FS=y +# CONFIG_NTFS_DEBUG is not set +CONFIG_NTFS_RW=y +CONFIG_EXFAT_FS=m +CONFIG_EXFAT_DEFAULT_CODEPAGE=437 +CONFIG_EXFAT_DEFAULT_IOCHARSET="utf8" + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_SYSCTL=y +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SYSFS=y CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +# CONFIG_TMPFS_XATTR is not set +# CONFIG_HUGETLB_PAGE is not set +# CONFIG_CONFIGFS_FS is not set +CONFIG_MISC_FILESYSTEMS=y +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_ECRYPT_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_LOGFS is not set +# CONFIG_CRAMFS is not set +# CONFIG_SQUASHFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_OMFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_QNX6FS_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_PSTORE is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y CONFIG_NFS_FS=y CONFIG_NFS_V3=y CONFIG_NFS_V3_ACL=y CONFIG_NFS_V4=y +# CONFIG_NFS_V4_1 is not set +# CONFIG_ROOT_NFS is not set +# CONFIG_NFS_USE_LEGACY_DNS is not set +CONFIG_NFS_USE_KERNEL_DNS=y +# CONFIG_NFSD is not set +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_ACL_SUPPORT=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=y +# CONFIG_SUNRPC_DEBUG is not set +# CONFIG_CEPH_FS is not set CONFIG_CIFS=y +# CONFIG_CIFS_STATS is not set +# CONFIG_CIFS_WEAK_PW_HASH is not set +# CONFIG_CIFS_UPCALL is not set +# CONFIG_CIFS_XATTR is not set +# CONFIG_CIFS_DEBUG2 is not set +# CONFIG_CIFS_DFS_UPCALL is not set +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_AFS_FS is not set +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" CONFIG_NLS_CODEPAGE_437=y +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set CONFIG_NLS_ASCII=y CONFIG_NLS_ISO8859_1=y +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set +CONFIG_DYNAMIC_FSYNC=y +CONFIG_RESTRICT_ROOTFS_SLAVE=y + +# +# Kernel hacking +# CONFIG_PRINTK_TIME=y -CONFIG_MAGIC_SYSRQ=y +CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4 +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=2048 +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_STRIP_ASM_SYMS is not set +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +# CONFIG_DEBUG_SECTION_MISMATCH is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +# CONFIG_LOCKUP_DETECTOR is not set +# CONFIG_HARDLOCKUP_DETECTOR is not set +# CONFIG_DETECT_HUNG_TASK is not set # CONFIG_SCHED_DEBUG is not set +# CONFIG_SCHEDSTATS is not set CONFIG_TIMER_STATS=y +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_SLUB_STATS is not set +# CONFIG_DEBUG_KMEMLEAK is not set # CONFIG_DEBUG_PREEMPT is not set +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_SPARSE_RCU_POINTER is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_ATOMIC_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +CONFIG_STACKTRACE=y +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_KOBJECT is not set +# CONFIG_DEBUG_HIGHMEM is not set +# CONFIG_DEBUG_BUGVERBOSE is not set CONFIG_DEBUG_INFO=y +# CONFIG_DEBUG_INFO_REDUCED is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_WRITECOUNT is not set CONFIG_DEBUG_MEMORY_INIT=y -CONFIG_ENABLE_DEFAULT_TRACERS=y +# CONFIG_DEBUG_LIST is not set +# CONFIG_TEST_LIST_SORT is not set +# CONFIG_DEBUG_SG is not set +# CONFIG_DEBUG_NOTIFIERS is not set +# CONFIG_DEBUG_CREDENTIALS is not set +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_RCU_CPU_STALL_TIMEOUT=60 +CONFIG_RCU_CPU_STALL_VERBOSE=y +# CONFIG_RCU_CPU_STALL_INFO is not set +# CONFIG_RCU_TRACE is not set +# CONFIG_BACKTRACE_SELF_TEST is not set +# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set +# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set +# CONFIG_DEBUG_PER_CPU_MAPS is not set +# CONFIG_LKDTM is not set +# CONFIG_CPU_NOTIFIER_ERROR_INJECT is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_DEBUG_PAGEALLOC is not set +CONFIG_HAVE_FUNCTION_TRACER=y +CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y +CONFIG_HAVE_DYNAMIC_FTRACE=y +CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y +CONFIG_HAVE_C_RECORDMCOUNT=y +CONFIG_TRACING_SUPPORT=y +# CONFIG_FTRACE is not set CONFIG_DYNAMIC_DEBUG=y +# CONFIG_DMA_API_DEBUG is not set +# CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_SAMPLES is not set +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_KGDB is not set +# CONFIG_TEST_KSTRTOX is not set +# CONFIG_STRICT_DEVMEM is not set +CONFIG_ARM_UNWIND=y # CONFIG_DEBUG_USER is not set +# CONFIG_DEBUG_RODATA is not set +# CONFIG_DEBUG_LL is not set CONFIG_PID_IN_CONTEXTIDR=y + +# +# Security options +# +CONFIG_KEYS=y +# CONFIG_ENCRYPTED_KEYS is not set +# CONFIG_KEYS_DEBUG_PROC_KEYS is not set +# CONFIG_SECURITY_DMESG_RESTRICT is not set CONFIG_SECURITY=y +# CONFIG_SECURITYFS is not set CONFIG_SECURITY_NETWORK=y +# CONFIG_SECURITY_NETWORK_XFRM is not set +# CONFIG_SECURITY_PATH is not set CONFIG_LSM_MMAP_MIN_ADDR=4096 CONFIG_SECURITY_SELINUX=y +# CONFIG_SECURITY_SELINUX_BOOTPARAM is not set +# CONFIG_SECURITY_SELINUX_DISABLE is not set +CONFIG_SECURITY_SELINUX_DEVELOP=y +CONFIG_SECURITY_SELINUX_AVC_STATS=y +CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1 +# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX is not set +# CONFIG_SECURITY_TOMOYO is not set +# CONFIG_SECURITY_APPARMOR is not set +# CONFIG_SECURITY_YAMA is not set +# CONFIG_IMA is not set +# CONFIG_EVM is not set +CONFIG_DEFAULT_SECURITY_SELINUX=y +# CONFIG_DEFAULT_SECURITY_DAC is not set +CONFIG_DEFAULT_SECURITY="selinux" +CONFIG_CRYPTO=y + +# +# Crypto core or helper +# +CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_ALGAPI2=y +CONFIG_CRYPTO_AEAD=y +CONFIG_CRYPTO_AEAD2=y +CONFIG_CRYPTO_BLKCIPHER=y +CONFIG_CRYPTO_BLKCIPHER2=y +CONFIG_CRYPTO_HASH=y +CONFIG_CRYPTO_HASH2=y +CONFIG_CRYPTO_RNG=y +CONFIG_CRYPTO_RNG2=y +CONFIG_CRYPTO_PCOMP2=y +CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_MANAGER2=y +# CONFIG_CRYPTO_USER is not set +CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_PCRYPT is not set +CONFIG_CRYPTO_WORKQUEUE=y +# CONFIG_CRYPTO_CRYPTD is not set +CONFIG_CRYPTO_AUTHENC=y +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +CONFIG_CRYPTO_CBC=y +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +CONFIG_CRYPTO_ECB=y +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +CONFIG_CRYPTO_HMAC=y +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_VMAC is not set + +# +# Digest +# +CONFIG_CRYPTO_CRC32C=y +# CONFIG_CRYPTO_GHASH is not set +CONFIG_CRYPTO_MD4=y +CONFIG_CRYPTO_MD5=y +# CONFIG_CRYPTO_MICHAEL_MIC is not set +# CONFIG_CRYPTO_RMD128 is not set +# CONFIG_CRYPTO_RMD160 is not set +# CONFIG_CRYPTO_RMD256 is not set +# CONFIG_CRYPTO_RMD320 is not set +CONFIG_CRYPTO_SHA1=y +CONFIG_CRYPTO_SHA1_ARM=y +CONFIG_CRYPTO_SHA256=y +# CONFIG_CRYPTO_SHA512 is not set +# CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_WP512 is not set + +# +# Ciphers +# +CONFIG_CRYPTO_AES=y +CONFIG_CRYPTO_AES_ARM=y +# CONFIG_CRYPTO_ANUBIS is not set +CONFIG_CRYPTO_ARC4=y +# CONFIG_CRYPTO_BLOWFISH is not set +# CONFIG_CRYPTO_CAMELLIA is not set +# CONFIG_CRYPTO_CAST5 is not set +# CONFIG_CRYPTO_CAST6 is not set +CONFIG_CRYPTO_DES=y +# CONFIG_CRYPTO_FCRYPT is not set +# CONFIG_CRYPTO_KHAZAD is not set +# CONFIG_CRYPTO_SALSA20 is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SERPENT is not set +# CONFIG_CRYPTO_TEA is not set CONFIG_CRYPTO_TWOFISH=y -CONFIG_NET_KEY=y -CONFIG_INET_ESP=y -CONFIG_INET_XFRM_MODE_TRANSPORT=y -CONFIG_INET_XFRM_MODE_TUNNEL=y -CONFIG_PPP=y -CONFIG_PPP_DEFLATE=y -CONFIG_PPP_BSDCOMP=y -CONFIG_PPP_FILTER=y -CONFIG_PPP_MPPE=y -CONFIG_PPP_MULTILINK=y -CONFIG_PPPOE=y -CONFIG_L2TP=y -CONFIG_PPPOL2TP=y -CONFIG_PPPOLAC=y -CONFIG_PPPOPNS=y -CONFIG_PPP_ASYNC=y -CONFIG_PPP_SYNC_TTY=y -CONFIG_CFG80211_INTERNAL_REGDB=y -CONFIG_SWAP=n +CONFIG_CRYPTO_TWOFISH_COMMON=y + +# +# Compression +# +CONFIG_CRYPTO_DEFLATE=y +# CONFIG_CRYPTO_ZLIB is not set +# CONFIG_CRYPTO_LZO is not set + +# +# Random Number Generation +# +CONFIG_CRYPTO_ANSI_CPRNG=y +# CONFIG_CRYPTO_USER_API_HASH is not set +# CONFIG_CRYPTO_USER_API_SKCIPHER is not set +CONFIG_CRYPTO_HW=y +# CONFIG_CRYPTO_DEV_HIFN_795X is not set +# CONFIG_CRYPTO_DEV_QCRYPTO is not set +# CONFIG_CRYPTO_DEV_QCE is not set +# CONFIG_CRYPTO_DEV_QCEDEV is not set +# CONFIG_CRYPTO_DEV_OTA_CRYPTO is not set +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +CONFIG_GENERIC_PCI_IOMAP=y +CONFIG_GENERIC_IO=y +CONFIG_CRC_CCITT=y +CONFIG_CRC16=y +# CONFIG_CRC_T10DIF is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC32_SELFTEST is not set +CONFIG_CRC32_SLICEBY8=y +# CONFIG_CRC32_SLICEBY4 is not set +# CONFIG_CRC32_SARWATE is not set +# CONFIG_CRC32_BIT is not set +# CONFIG_CRC7 is not set +CONFIG_LIBCRC32C=y +# CONFIG_CRC8 is not set +CONFIG_AUDIT_GENERIC=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=y +CONFIG_LZO_COMPRESS=y +CONFIG_LZO_DECOMPRESS=y +# CONFIG_XZ_DEC is not set +# CONFIG_XZ_DEC_BCJ is not set +CONFIG_DECOMPRESS_GZIP=y +CONFIG_DECOMPRESS_BZIP2=y +CONFIG_DECOMPRESS_LZMA=y +CONFIG_GENERIC_ALLOCATOR=y +CONFIG_REED_SOLOMON=y +CONFIG_REED_SOLOMON_ENC8=y +CONFIG_REED_SOLOMON_DEC8=y +CONFIG_TEXTSEARCH=y +CONFIG_TEXTSEARCH_KMP=y +CONFIG_TEXTSEARCH_BM=y +CONFIG_TEXTSEARCH_FSM=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_CPU_RMAP=y +CONFIG_DQL=y +CONFIG_NLATTR=y +# CONFIG_AVERAGE is not set +# CONFIG_CORDIC is not set diff --git a/arch/arm/crypto/Makefile b/arch/arm/crypto/Makefile new file mode 100644 index 00000000000..a2c83851bc9 --- /dev/null +++ b/arch/arm/crypto/Makefile @@ -0,0 +1,9 @@ +# +# Arch-specific CryptoAPI modules. +# + +obj-$(CONFIG_CRYPTO_AES_ARM) += aes-arm.o +obj-$(CONFIG_CRYPTO_SHA1_ARM) += sha1-arm.o + +aes-arm-y := aes-armv4.o aes_glue.o +sha1-arm-y := sha1-armv4-large.o sha1_glue.o diff --git a/arch/arm/crypto/aes-armv4.S b/arch/arm/crypto/aes-armv4.S new file mode 100644 index 00000000000..e59b1d505d6 --- /dev/null +++ b/arch/arm/crypto/aes-armv4.S @@ -0,0 +1,1112 @@ +#define __ARM_ARCH__ __LINUX_ARM_ARCH__ +@ ==================================================================== +@ Written by Andy Polyakov for the OpenSSL +@ project. The module is, however, dual licensed under OpenSSL and +@ CRYPTOGAMS licenses depending on where you obtain it. For further +@ details see http://www.openssl.org/~appro/cryptogams/. +@ ==================================================================== + +@ AES for ARMv4 + +@ January 2007. +@ +@ Code uses single 1K S-box and is >2 times faster than code generated +@ by gcc-3.4.1. This is thanks to unique feature of ARMv4 ISA, which +@ allows to merge logical or arithmetic operation with shift or rotate +@ in one instruction and emit combined result every cycle. The module +@ is endian-neutral. The performance is ~42 cycles/byte for 128-bit +@ key [on single-issue Xscale PXA250 core]. + +@ May 2007. +@ +@ AES_set_[en|de]crypt_key is added. + +@ July 2010. +@ +@ Rescheduling for dual-issue pipeline resulted in 12% improvement on +@ Cortex A8 core and ~25 cycles per byte processed with 128-bit key. + +@ February 2011. +@ +@ Profiler-assisted and platform-specific optimization resulted in 16% +@ improvement on Cortex A8 core and ~21.5 cycles per byte. + +@ A little glue here to select the correct code below for the ARM CPU +@ that is being targetted. + +.text +.code 32 + +.type AES_Te,%object +.align 5 +AES_Te: +.word 0xc66363a5, 0xf87c7c84, 0xee777799, 0xf67b7b8d +.word 0xfff2f20d, 0xd66b6bbd, 0xde6f6fb1, 0x91c5c554 +.word 0x60303050, 0x02010103, 0xce6767a9, 0x562b2b7d +.word 0xe7fefe19, 0xb5d7d762, 0x4dababe6, 0xec76769a +.word 0x8fcaca45, 0x1f82829d, 0x89c9c940, 0xfa7d7d87 +.word 0xeffafa15, 0xb25959eb, 0x8e4747c9, 0xfbf0f00b +.word 0x41adadec, 0xb3d4d467, 0x5fa2a2fd, 0x45afafea +.word 0x239c9cbf, 0x53a4a4f7, 0xe4727296, 0x9bc0c05b +.word 0x75b7b7c2, 0xe1fdfd1c, 0x3d9393ae, 0x4c26266a +.word 0x6c36365a, 0x7e3f3f41, 0xf5f7f702, 0x83cccc4f +.word 0x6834345c, 0x51a5a5f4, 0xd1e5e534, 0xf9f1f108 +.word 0xe2717193, 0xabd8d873, 0x62313153, 0x2a15153f +.word 0x0804040c, 0x95c7c752, 0x46232365, 0x9dc3c35e +.word 0x30181828, 0x379696a1, 0x0a05050f, 0x2f9a9ab5 +.word 0x0e070709, 0x24121236, 0x1b80809b, 0xdfe2e23d +.word 0xcdebeb26, 0x4e272769, 0x7fb2b2cd, 0xea75759f +.word 0x1209091b, 0x1d83839e, 0x582c2c74, 0x341a1a2e +.word 0x361b1b2d, 0xdc6e6eb2, 0xb45a5aee, 0x5ba0a0fb +.word 0xa45252f6, 0x763b3b4d, 0xb7d6d661, 0x7db3b3ce +.word 0x5229297b, 0xdde3e33e, 0x5e2f2f71, 0x13848497 +.word 0xa65353f5, 0xb9d1d168, 0x00000000, 0xc1eded2c +.word 0x40202060, 0xe3fcfc1f, 0x79b1b1c8, 0xb65b5bed +.word 0xd46a6abe, 0x8dcbcb46, 0x67bebed9, 0x7239394b +.word 0x944a4ade, 0x984c4cd4, 0xb05858e8, 0x85cfcf4a +.word 0xbbd0d06b, 0xc5efef2a, 0x4faaaae5, 0xedfbfb16 +.word 0x864343c5, 0x9a4d4dd7, 0x66333355, 0x11858594 +.word 0x8a4545cf, 0xe9f9f910, 0x04020206, 0xfe7f7f81 +.word 0xa05050f0, 0x783c3c44, 0x259f9fba, 0x4ba8a8e3 +.word 0xa25151f3, 0x5da3a3fe, 0x804040c0, 0x058f8f8a +.word 0x3f9292ad, 0x219d9dbc, 0x70383848, 0xf1f5f504 +.word 0x63bcbcdf, 0x77b6b6c1, 0xafdada75, 0x42212163 +.word 0x20101030, 0xe5ffff1a, 0xfdf3f30e, 0xbfd2d26d +.word 0x81cdcd4c, 0x180c0c14, 0x26131335, 0xc3ecec2f +.word 0xbe5f5fe1, 0x359797a2, 0x884444cc, 0x2e171739 +.word 0x93c4c457, 0x55a7a7f2, 0xfc7e7e82, 0x7a3d3d47 +.word 0xc86464ac, 0xba5d5de7, 0x3219192b, 0xe6737395 +.word 0xc06060a0, 0x19818198, 0x9e4f4fd1, 0xa3dcdc7f +.word 0x44222266, 0x542a2a7e, 0x3b9090ab, 0x0b888883 +.word 0x8c4646ca, 0xc7eeee29, 0x6bb8b8d3, 0x2814143c +.word 0xa7dede79, 0xbc5e5ee2, 0x160b0b1d, 0xaddbdb76 +.word 0xdbe0e03b, 0x64323256, 0x743a3a4e, 0x140a0a1e +.word 0x924949db, 0x0c06060a, 0x4824246c, 0xb85c5ce4 +.word 0x9fc2c25d, 0xbdd3d36e, 0x43acacef, 0xc46262a6 +.word 0x399191a8, 0x319595a4, 0xd3e4e437, 0xf279798b +.word 0xd5e7e732, 0x8bc8c843, 0x6e373759, 0xda6d6db7 +.word 0x018d8d8c, 0xb1d5d564, 0x9c4e4ed2, 0x49a9a9e0 +.word 0xd86c6cb4, 0xac5656fa, 0xf3f4f407, 0xcfeaea25 +.word 0xca6565af, 0xf47a7a8e, 0x47aeaee9, 0x10080818 +.word 0x6fbabad5, 0xf0787888, 0x4a25256f, 0x5c2e2e72 +.word 0x381c1c24, 0x57a6a6f1, 0x73b4b4c7, 0x97c6c651 +.word 0xcbe8e823, 0xa1dddd7c, 0xe874749c, 0x3e1f1f21 +.word 0x964b4bdd, 0x61bdbddc, 0x0d8b8b86, 0x0f8a8a85 +.word 0xe0707090, 0x7c3e3e42, 0x71b5b5c4, 0xcc6666aa +.word 0x904848d8, 0x06030305, 0xf7f6f601, 0x1c0e0e12 +.word 0xc26161a3, 0x6a35355f, 0xae5757f9, 0x69b9b9d0 +.word 0x17868691, 0x99c1c158, 0x3a1d1d27, 0x279e9eb9 +.word 0xd9e1e138, 0xebf8f813, 0x2b9898b3, 0x22111133 +.word 0xd26969bb, 0xa9d9d970, 0x078e8e89, 0x339494a7 +.word 0x2d9b9bb6, 0x3c1e1e22, 0x15878792, 0xc9e9e920 +.word 0x87cece49, 0xaa5555ff, 0x50282878, 0xa5dfdf7a +.word 0x038c8c8f, 0x59a1a1f8, 0x09898980, 0x1a0d0d17 +.word 0x65bfbfda, 0xd7e6e631, 0x844242c6, 0xd06868b8 +.word 0x824141c3, 0x299999b0, 0x5a2d2d77, 0x1e0f0f11 +.word 0x7bb0b0cb, 0xa85454fc, 0x6dbbbbd6, 0x2c16163a +@ Te4[256] +.byte 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5 +.byte 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76 +.byte 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0 +.byte 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0 +.byte 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc +.byte 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15 +.byte 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a +.byte 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75 +.byte 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0 +.byte 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84 +.byte 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b +.byte 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf +.byte 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85 +.byte 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8 +.byte 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5 +.byte 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2 +.byte 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17 +.byte 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73 +.byte 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88 +.byte 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb +.byte 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c +.byte 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79 +.byte 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9 +.byte 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08 +.byte 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6 +.byte 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a +.byte 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e +.byte 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e +.byte 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94 +.byte 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf +.byte 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68 +.byte 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 +@ rcon[] +.word 0x01000000, 0x02000000, 0x04000000, 0x08000000 +.word 0x10000000, 0x20000000, 0x40000000, 0x80000000 +.word 0x1B000000, 0x36000000, 0, 0, 0, 0, 0, 0 +.size AES_Te,.-AES_Te + +@ void AES_encrypt(const unsigned char *in, unsigned char *out, +@ const AES_KEY *key) { +.global AES_encrypt +.type AES_encrypt,%function +.align 5 +AES_encrypt: + sub r3,pc,#8 @ AES_encrypt + stmdb sp!,{r1,r4-r12,lr} + mov r12,r0 @ inp + mov r11,r2 + sub r10,r3,#AES_encrypt-AES_Te @ Te +#if __ARM_ARCH__<7 + ldrb r0,[r12,#3] @ load input data in endian-neutral + ldrb r4,[r12,#2] @ manner... + ldrb r5,[r12,#1] + ldrb r6,[r12,#0] + orr r0,r0,r4,lsl#8 + ldrb r1,[r12,#7] + orr r0,r0,r5,lsl#16 + ldrb r4,[r12,#6] + orr r0,r0,r6,lsl#24 + ldrb r5,[r12,#5] + ldrb r6,[r12,#4] + orr r1,r1,r4,lsl#8 + ldrb r2,[r12,#11] + orr r1,r1,r5,lsl#16 + ldrb r4,[r12,#10] + orr r1,r1,r6,lsl#24 + ldrb r5,[r12,#9] + ldrb r6,[r12,#8] + orr r2,r2,r4,lsl#8 + ldrb r3,[r12,#15] + orr r2,r2,r5,lsl#16 + ldrb r4,[r12,#14] + orr r2,r2,r6,lsl#24 + ldrb r5,[r12,#13] + ldrb r6,[r12,#12] + orr r3,r3,r4,lsl#8 + orr r3,r3,r5,lsl#16 + orr r3,r3,r6,lsl#24 +#else + ldr r0,[r12,#0] + ldr r1,[r12,#4] + ldr r2,[r12,#8] + ldr r3,[r12,#12] +#ifdef __ARMEL__ + rev r0,r0 + rev r1,r1 + rev r2,r2 + rev r3,r3 +#endif +#endif + bl _armv4_AES_encrypt + + ldr r12,[sp],#4 @ pop out +#if __ARM_ARCH__>=7 +#ifdef __ARMEL__ + rev r0,r0 + rev r1,r1 + rev r2,r2 + rev r3,r3 +#endif + str r0,[r12,#0] + str r1,[r12,#4] + str r2,[r12,#8] + str r3,[r12,#12] +#else + mov r4,r0,lsr#24 @ write output in endian-neutral + mov r5,r0,lsr#16 @ manner... + mov r6,r0,lsr#8 + strb r4,[r12,#0] + strb r5,[r12,#1] + mov r4,r1,lsr#24 + strb r6,[r12,#2] + mov r5,r1,lsr#16 + strb r0,[r12,#3] + mov r6,r1,lsr#8 + strb r4,[r12,#4] + strb r5,[r12,#5] + mov r4,r2,lsr#24 + strb r6,[r12,#6] + mov r5,r2,lsr#16 + strb r1,[r12,#7] + mov r6,r2,lsr#8 + strb r4,[r12,#8] + strb r5,[r12,#9] + mov r4,r3,lsr#24 + strb r6,[r12,#10] + mov r5,r3,lsr#16 + strb r2,[r12,#11] + mov r6,r3,lsr#8 + strb r4,[r12,#12] + strb r5,[r12,#13] + strb r6,[r12,#14] + strb r3,[r12,#15] +#endif +#if __ARM_ARCH__>=5 + ldmia sp!,{r4-r12,pc} +#else + ldmia sp!,{r4-r12,lr} + tst lr,#1 + moveq pc,lr @ be binary compatible with V4, yet + .word 0xe12fff1e @ interoperable with Thumb ISA:-) +#endif +.size AES_encrypt,.-AES_encrypt + +.type _armv4_AES_encrypt,%function +.align 2 +_armv4_AES_encrypt: + str lr,[sp,#-4]! @ push lr + ldmia r11!,{r4-r7} + eor r0,r0,r4 + ldr r12,[r11,#240-16] + eor r1,r1,r5 + eor r2,r2,r6 + eor r3,r3,r7 + sub r12,r12,#1 + mov lr,#255 + + and r7,lr,r0 + and r8,lr,r0,lsr#8 + and r9,lr,r0,lsr#16 + mov r0,r0,lsr#24 +.Lenc_loop: + ldr r4,[r10,r7,lsl#2] @ Te3[s0>>0] + and r7,lr,r1,lsr#16 @ i0 + ldr r5,[r10,r8,lsl#2] @ Te2[s0>>8] + and r8,lr,r1 + ldr r6,[r10,r9,lsl#2] @ Te1[s0>>16] + and r9,lr,r1,lsr#8 + ldr r0,[r10,r0,lsl#2] @ Te0[s0>>24] + mov r1,r1,lsr#24 + + ldr r7,[r10,r7,lsl#2] @ Te1[s1>>16] + ldr r8,[r10,r8,lsl#2] @ Te3[s1>>0] + ldr r9,[r10,r9,lsl#2] @ Te2[s1>>8] + eor r0,r0,r7,ror#8 + ldr r1,[r10,r1,lsl#2] @ Te0[s1>>24] + and r7,lr,r2,lsr#8 @ i0 + eor r5,r5,r8,ror#8 + and r8,lr,r2,lsr#16 @ i1 + eor r6,r6,r9,ror#8 + and r9,lr,r2 + ldr r7,[r10,r7,lsl#2] @ Te2[s2>>8] + eor r1,r1,r4,ror#24 + ldr r8,[r10,r8,lsl#2] @ Te1[s2>>16] + mov r2,r2,lsr#24 + + ldr r9,[r10,r9,lsl#2] @ Te3[s2>>0] + eor r0,r0,r7,ror#16 + ldr r2,[r10,r2,lsl#2] @ Te0[s2>>24] + and r7,lr,r3 @ i0 + eor r1,r1,r8,ror#8 + and r8,lr,r3,lsr#8 @ i1 + eor r6,r6,r9,ror#16 + and r9,lr,r3,lsr#16 @ i2 + ldr r7,[r10,r7,lsl#2] @ Te3[s3>>0] + eor r2,r2,r5,ror#16 + ldr r8,[r10,r8,lsl#2] @ Te2[s3>>8] + mov r3,r3,lsr#24 + + ldr r9,[r10,r9,lsl#2] @ Te1[s3>>16] + eor r0,r0,r7,ror#24 + ldr r7,[r11],#16 + eor r1,r1,r8,ror#16 + ldr r3,[r10,r3,lsl#2] @ Te0[s3>>24] + eor r2,r2,r9,ror#8 + ldr r4,[r11,#-12] + eor r3,r3,r6,ror#8 + + ldr r5,[r11,#-8] + eor r0,r0,r7 + ldr r6,[r11,#-4] + and r7,lr,r0 + eor r1,r1,r4 + and r8,lr,r0,lsr#8 + eor r2,r2,r5 + and r9,lr,r0,lsr#16 + eor r3,r3,r6 + mov r0,r0,lsr#24 + + subs r12,r12,#1 + bne .Lenc_loop + + add r10,r10,#2 + + ldrb r4,[r10,r7,lsl#2] @ Te4[s0>>0] + and r7,lr,r1,lsr#16 @ i0 + ldrb r5,[r10,r8,lsl#2] @ Te4[s0>>8] + and r8,lr,r1 + ldrb r6,[r10,r9,lsl#2] @ Te4[s0>>16] + and r9,lr,r1,lsr#8 + ldrb r0,[r10,r0,lsl#2] @ Te4[s0>>24] + mov r1,r1,lsr#24 + + ldrb r7,[r10,r7,lsl#2] @ Te4[s1>>16] + ldrb r8,[r10,r8,lsl#2] @ Te4[s1>>0] + ldrb r9,[r10,r9,lsl#2] @ Te4[s1>>8] + eor r0,r7,r0,lsl#8 + ldrb r1,[r10,r1,lsl#2] @ Te4[s1>>24] + and r7,lr,r2,lsr#8 @ i0 + eor r5,r8,r5,lsl#8 + and r8,lr,r2,lsr#16 @ i1 + eor r6,r9,r6,lsl#8 + and r9,lr,r2 + ldrb r7,[r10,r7,lsl#2] @ Te4[s2>>8] + eor r1,r4,r1,lsl#24 + ldrb r8,[r10,r8,lsl#2] @ Te4[s2>>16] + mov r2,r2,lsr#24 + + ldrb r9,[r10,r9,lsl#2] @ Te4[s2>>0] + eor r0,r7,r0,lsl#8 + ldrb r2,[r10,r2,lsl#2] @ Te4[s2>>24] + and r7,lr,r3 @ i0 + eor r1,r1,r8,lsl#16 + and r8,lr,r3,lsr#8 @ i1 + eor r6,r9,r6,lsl#8 + and r9,lr,r3,lsr#16 @ i2 + ldrb r7,[r10,r7,lsl#2] @ Te4[s3>>0] + eor r2,r5,r2,lsl#24 + ldrb r8,[r10,r8,lsl#2] @ Te4[s3>>8] + mov r3,r3,lsr#24 + + ldrb r9,[r10,r9,lsl#2] @ Te4[s3>>16] + eor r0,r7,r0,lsl#8 + ldr r7,[r11,#0] + ldrb r3,[r10,r3,lsl#2] @ Te4[s3>>24] + eor r1,r1,r8,lsl#8 + ldr r4,[r11,#4] + eor r2,r2,r9,lsl#16 + ldr r5,[r11,#8] + eor r3,r6,r3,lsl#24 + ldr r6,[r11,#12] + + eor r0,r0,r7 + eor r1,r1,r4 + eor r2,r2,r5 + eor r3,r3,r6 + + sub r10,r10,#2 + ldr pc,[sp],#4 @ pop and return +.size _armv4_AES_encrypt,.-_armv4_AES_encrypt + +.global private_AES_set_encrypt_key +.type private_AES_set_encrypt_key,%function +.align 5 +private_AES_set_encrypt_key: +_armv4_AES_set_encrypt_key: + sub r3,pc,#8 @ AES_set_encrypt_key + teq r0,#0 + moveq r0,#-1 + beq .Labrt + teq r2,#0 + moveq r0,#-1 + beq .Labrt + + teq r1,#128 + beq .Lok + teq r1,#192 + beq .Lok + teq r1,#256 + movne r0,#-1 + bne .Labrt + +.Lok: stmdb sp!,{r4-r12,lr} + sub r10,r3,#_armv4_AES_set_encrypt_key-AES_Te-1024 @ Te4 + + mov r12,r0 @ inp + mov lr,r1 @ bits + mov r11,r2 @ key + +#if __ARM_ARCH__<7 + ldrb r0,[r12,#3] @ load input data in endian-neutral + ldrb r4,[r12,#2] @ manner... + ldrb r5,[r12,#1] + ldrb r6,[r12,#0] + orr r0,r0,r4,lsl#8 + ldrb r1,[r12,#7] + orr r0,r0,r5,lsl#16 + ldrb r4,[r12,#6] + orr r0,r0,r6,lsl#24 + ldrb r5,[r12,#5] + ldrb r6,[r12,#4] + orr r1,r1,r4,lsl#8 + ldrb r2,[r12,#11] + orr r1,r1,r5,lsl#16 + ldrb r4,[r12,#10] + orr r1,r1,r6,lsl#24 + ldrb r5,[r12,#9] + ldrb r6,[r12,#8] + orr r2,r2,r4,lsl#8 + ldrb r3,[r12,#15] + orr r2,r2,r5,lsl#16 + ldrb r4,[r12,#14] + orr r2,r2,r6,lsl#24 + ldrb r5,[r12,#13] + ldrb r6,[r12,#12] + orr r3,r3,r4,lsl#8 + str r0,[r11],#16 + orr r3,r3,r5,lsl#16 + str r1,[r11,#-12] + orr r3,r3,r6,lsl#24 + str r2,[r11,#-8] + str r3,[r11,#-4] +#else + ldr r0,[r12,#0] + ldr r1,[r12,#4] + ldr r2,[r12,#8] + ldr r3,[r12,#12] +#ifdef __ARMEL__ + rev r0,r0 + rev r1,r1 + rev r2,r2 + rev r3,r3 +#endif + str r0,[r11],#16 + str r1,[r11,#-12] + str r2,[r11,#-8] + str r3,[r11,#-4] +#endif + + teq lr,#128 + bne .Lnot128 + mov r12,#10 + str r12,[r11,#240-16] + add r6,r10,#256 @ rcon + mov lr,#255 + +.L128_loop: + and r5,lr,r3,lsr#24 + and r7,lr,r3,lsr#16 + ldrb r5,[r10,r5] + and r8,lr,r3,lsr#8 + ldrb r7,[r10,r7] + and r9,lr,r3 + ldrb r8,[r10,r8] + orr r5,r5,r7,lsl#24 + ldrb r9,[r10,r9] + orr r5,r5,r8,lsl#16 + ldr r4,[r6],#4 @ rcon[i++] + orr r5,r5,r9,lsl#8 + eor r5,r5,r4 + eor r0,r0,r5 @ rk[4]=rk[0]^... + eor r1,r1,r0 @ rk[5]=rk[1]^rk[4] + str r0,[r11],#16 + eor r2,r2,r1 @ rk[6]=rk[2]^rk[5] + str r1,[r11,#-12] + eor r3,r3,r2 @ rk[7]=rk[3]^rk[6] + str r2,[r11,#-8] + subs r12,r12,#1 + str r3,[r11,#-4] + bne .L128_loop + sub r2,r11,#176 + b .Ldone + +.Lnot128: +#if __ARM_ARCH__<7 + ldrb r8,[r12,#19] + ldrb r4,[r12,#18] + ldrb r5,[r12,#17] + ldrb r6,[r12,#16] + orr r8,r8,r4,lsl#8 + ldrb r9,[r12,#23] + orr r8,r8,r5,lsl#16 + ldrb r4,[r12,#22] + orr r8,r8,r6,lsl#24 + ldrb r5,[r12,#21] + ldrb r6,[r12,#20] + orr r9,r9,r4,lsl#8 + orr r9,r9,r5,lsl#16 + str r8,[r11],#8 + orr r9,r9,r6,lsl#24 + str r9,[r11,#-4] +#else + ldr r8,[r12,#16] + ldr r9,[r12,#20] +#ifdef __ARMEL__ + rev r8,r8 + rev r9,r9 +#endif + str r8,[r11],#8 + str r9,[r11,#-4] +#endif + + teq lr,#192 + bne .Lnot192 + mov r12,#12 + str r12,[r11,#240-24] + add r6,r10,#256 @ rcon + mov lr,#255 + mov r12,#8 + +.L192_loop: + and r5,lr,r9,lsr#24 + and r7,lr,r9,lsr#16 + ldrb r5,[r10,r5] + and r8,lr,r9,lsr#8 + ldrb r7,[r10,r7] + and r9,lr,r9 + ldrb r8,[r10,r8] + orr r5,r5,r7,lsl#24 + ldrb r9,[r10,r9] + orr r5,r5,r8,lsl#16 + ldr r4,[r6],#4 @ rcon[i++] + orr r5,r5,r9,lsl#8 + eor r9,r5,r4 + eor r0,r0,r9 @ rk[6]=rk[0]^... + eor r1,r1,r0 @ rk[7]=rk[1]^rk[6] + str r0,[r11],#24 + eor r2,r2,r1 @ rk[8]=rk[2]^rk[7] + str r1,[r11,#-20] + eor r3,r3,r2 @ rk[9]=rk[3]^rk[8] + str r2,[r11,#-16] + subs r12,r12,#1 + str r3,[r11,#-12] + subeq r2,r11,#216 + beq .Ldone + + ldr r7,[r11,#-32] + ldr r8,[r11,#-28] + eor r7,r7,r3 @ rk[10]=rk[4]^rk[9] + eor r9,r8,r7 @ rk[11]=rk[5]^rk[10] + str r7,[r11,#-8] + str r9,[r11,#-4] + b .L192_loop + +.Lnot192: +#if __ARM_ARCH__<7 + ldrb r8,[r12,#27] + ldrb r4,[r12,#26] + ldrb r5,[r12,#25] + ldrb r6,[r12,#24] + orr r8,r8,r4,lsl#8 + ldrb r9,[r12,#31] + orr r8,r8,r5,lsl#16 + ldrb r4,[r12,#30] + orr r8,r8,r6,lsl#24 + ldrb r5,[r12,#29] + ldrb r6,[r12,#28] + orr r9,r9,r4,lsl#8 + orr r9,r9,r5,lsl#16 + str r8,[r11],#8 + orr r9,r9,r6,lsl#24 + str r9,[r11,#-4] +#else + ldr r8,[r12,#24] + ldr r9,[r12,#28] +#ifdef __ARMEL__ + rev r8,r8 + rev r9,r9 +#endif + str r8,[r11],#8 + str r9,[r11,#-4] +#endif + + mov r12,#14 + str r12,[r11,#240-32] + add r6,r10,#256 @ rcon + mov lr,#255 + mov r12,#7 + +.L256_loop: + and r5,lr,r9,lsr#24 + and r7,lr,r9,lsr#16 + ldrb r5,[r10,r5] + and r8,lr,r9,lsr#8 + ldrb r7,[r10,r7] + and r9,lr,r9 + ldrb r8,[r10,r8] + orr r5,r5,r7,lsl#24 + ldrb r9,[r10,r9] + orr r5,r5,r8,lsl#16 + ldr r4,[r6],#4 @ rcon[i++] + orr r5,r5,r9,lsl#8 + eor r9,r5,r4 + eor r0,r0,r9 @ rk[8]=rk[0]^... + eor r1,r1,r0 @ rk[9]=rk[1]^rk[8] + str r0,[r11],#32 + eor r2,r2,r1 @ rk[10]=rk[2]^rk[9] + str r1,[r11,#-28] + eor r3,r3,r2 @ rk[11]=rk[3]^rk[10] + str r2,[r11,#-24] + subs r12,r12,#1 + str r3,[r11,#-20] + subeq r2,r11,#256 + beq .Ldone + + and r5,lr,r3 + and r7,lr,r3,lsr#8 + ldrb r5,[r10,r5] + and r8,lr,r3,lsr#16 + ldrb r7,[r10,r7] + and r9,lr,r3,lsr#24 + ldrb r8,[r10,r8] + orr r5,r5,r7,lsl#8 + ldrb r9,[r10,r9] + orr r5,r5,r8,lsl#16 + ldr r4,[r11,#-48] + orr r5,r5,r9,lsl#24 + + ldr r7,[r11,#-44] + ldr r8,[r11,#-40] + eor r4,r4,r5 @ rk[12]=rk[4]^... + ldr r9,[r11,#-36] + eor r7,r7,r4 @ rk[13]=rk[5]^rk[12] + str r4,[r11,#-16] + eor r8,r8,r7 @ rk[14]=rk[6]^rk[13] + str r7,[r11,#-12] + eor r9,r9,r8 @ rk[15]=rk[7]^rk[14] + str r8,[r11,#-8] + str r9,[r11,#-4] + b .L256_loop + +.Ldone: mov r0,#0 + ldmia sp!,{r4-r12,lr} +.Labrt: tst lr,#1 + moveq pc,lr @ be binary compatible with V4, yet + .word 0xe12fff1e @ interoperable with Thumb ISA:-) +.size private_AES_set_encrypt_key,.-private_AES_set_encrypt_key + +.global private_AES_set_decrypt_key +.type private_AES_set_decrypt_key,%function +.align 5 +private_AES_set_decrypt_key: + str lr,[sp,#-4]! @ push lr +#if 0 + @ kernel does both of these in setkey so optimise this bit out by + @ expecting the key to already have the enc_key work done (see aes_glue.c) + bl _armv4_AES_set_encrypt_key +#else + mov r0,#0 +#endif + teq r0,#0 + ldrne lr,[sp],#4 @ pop lr + bne .Labrt + + stmdb sp!,{r4-r12} + + ldr r12,[r2,#240] @ AES_set_encrypt_key preserves r2, + mov r11,r2 @ which is AES_KEY *key + mov r7,r2 + add r8,r2,r12,lsl#4 + +.Linv: ldr r0,[r7] + ldr r1,[r7,#4] + ldr r2,[r7,#8] + ldr r3,[r7,#12] + ldr r4,[r8] + ldr r5,[r8,#4] + ldr r6,[r8,#8] + ldr r9,[r8,#12] + str r0,[r8],#-16 + str r1,[r8,#16+4] + str r2,[r8,#16+8] + str r3,[r8,#16+12] + str r4,[r7],#16 + str r5,[r7,#-12] + str r6,[r7,#-8] + str r9,[r7,#-4] + teq r7,r8 + bne .Linv + ldr r0,[r11,#16]! @ prefetch tp1 + mov r7,#0x80 + mov r8,#0x1b + orr r7,r7,#0x8000 + orr r8,r8,#0x1b00 + orr r7,r7,r7,lsl#16 + orr r8,r8,r8,lsl#16 + sub r12,r12,#1 + mvn r9,r7 + mov r12,r12,lsl#2 @ (rounds-1)*4 + +.Lmix: and r4,r0,r7 + and r1,r0,r9 + sub r4,r4,r4,lsr#7 + and r4,r4,r8 + eor r1,r4,r1,lsl#1 @ tp2 + + and r4,r1,r7 + and r2,r1,r9 + sub r4,r4,r4,lsr#7 + and r4,r4,r8 + eor r2,r4,r2,lsl#1 @ tp4 + + and r4,r2,r7 + and r3,r2,r9 + sub r4,r4,r4,lsr#7 + and r4,r4,r8 + eor r3,r4,r3,lsl#1 @ tp8 + + eor r4,r1,r2 + eor r5,r0,r3 @ tp9 + eor r4,r4,r3 @ tpe + eor r4,r4,r1,ror#24 + eor r4,r4,r5,ror#24 @ ^= ROTATE(tpb=tp9^tp2,8) + eor r4,r4,r2,ror#16 + eor r4,r4,r5,ror#16 @ ^= ROTATE(tpd=tp9^tp4,16) + eor r4,r4,r5,ror#8 @ ^= ROTATE(tp9,24) + + ldr r0,[r11,#4] @ prefetch tp1 + str r4,[r11],#4 + subs r12,r12,#1 + bne .Lmix + + mov r0,#0 +#if __ARM_ARCH__>=5 + ldmia sp!,{r4-r12,pc} +#else + ldmia sp!,{r4-r12,lr} + tst lr,#1 + moveq pc,lr @ be binary compatible with V4, yet + .word 0xe12fff1e @ interoperable with Thumb ISA:-) +#endif +.size private_AES_set_decrypt_key,.-private_AES_set_decrypt_key + +.type AES_Td,%object +.align 5 +AES_Td: +.word 0x51f4a750, 0x7e416553, 0x1a17a4c3, 0x3a275e96 +.word 0x3bab6bcb, 0x1f9d45f1, 0xacfa58ab, 0x4be30393 +.word 0x2030fa55, 0xad766df6, 0x88cc7691, 0xf5024c25 +.word 0x4fe5d7fc, 0xc52acbd7, 0x26354480, 0xb562a38f +.word 0xdeb15a49, 0x25ba1b67, 0x45ea0e98, 0x5dfec0e1 +.word 0xc32f7502, 0x814cf012, 0x8d4697a3, 0x6bd3f9c6 +.word 0x038f5fe7, 0x15929c95, 0xbf6d7aeb, 0x955259da +.word 0xd4be832d, 0x587421d3, 0x49e06929, 0x8ec9c844 +.word 0x75c2896a, 0xf48e7978, 0x99583e6b, 0x27b971dd +.word 0xbee14fb6, 0xf088ad17, 0xc920ac66, 0x7dce3ab4 +.word 0x63df4a18, 0xe51a3182, 0x97513360, 0x62537f45 +.word 0xb16477e0, 0xbb6bae84, 0xfe81a01c, 0xf9082b94 +.word 0x70486858, 0x8f45fd19, 0x94de6c87, 0x527bf8b7 +.word 0xab73d323, 0x724b02e2, 0xe31f8f57, 0x6655ab2a +.word 0xb2eb2807, 0x2fb5c203, 0x86c57b9a, 0xd33708a5 +.word 0x302887f2, 0x23bfa5b2, 0x02036aba, 0xed16825c +.word 0x8acf1c2b, 0xa779b492, 0xf307f2f0, 0x4e69e2a1 +.word 0x65daf4cd, 0x0605bed5, 0xd134621f, 0xc4a6fe8a +.word 0x342e539d, 0xa2f355a0, 0x058ae132, 0xa4f6eb75 +.word 0x0b83ec39, 0x4060efaa, 0x5e719f06, 0xbd6e1051 +.word 0x3e218af9, 0x96dd063d, 0xdd3e05ae, 0x4de6bd46 +.word 0x91548db5, 0x71c45d05, 0x0406d46f, 0x605015ff +.word 0x1998fb24, 0xd6bde997, 0x894043cc, 0x67d99e77 +.word 0xb0e842bd, 0x07898b88, 0xe7195b38, 0x79c8eedb +.word 0xa17c0a47, 0x7c420fe9, 0xf8841ec9, 0x00000000 +.word 0x09808683, 0x322bed48, 0x1e1170ac, 0x6c5a724e +.word 0xfd0efffb, 0x0f853856, 0x3daed51e, 0x362d3927 +.word 0x0a0fd964, 0x685ca621, 0x9b5b54d1, 0x24362e3a +.word 0x0c0a67b1, 0x9357e70f, 0xb4ee96d2, 0x1b9b919e +.word 0x80c0c54f, 0x61dc20a2, 0x5a774b69, 0x1c121a16 +.word 0xe293ba0a, 0xc0a02ae5, 0x3c22e043, 0x121b171d +.word 0x0e090d0b, 0xf28bc7ad, 0x2db6a8b9, 0x141ea9c8 +.word 0x57f11985, 0xaf75074c, 0xee99ddbb, 0xa37f60fd +.word 0xf701269f, 0x5c72f5bc, 0x44663bc5, 0x5bfb7e34 +.word 0x8b432976, 0xcb23c6dc, 0xb6edfc68, 0xb8e4f163 +.word 0xd731dcca, 0x42638510, 0x13972240, 0x84c61120 +.word 0x854a247d, 0xd2bb3df8, 0xaef93211, 0xc729a16d +.word 0x1d9e2f4b, 0xdcb230f3, 0x0d8652ec, 0x77c1e3d0 +.word 0x2bb3166c, 0xa970b999, 0x119448fa, 0x47e96422 +.word 0xa8fc8cc4, 0xa0f03f1a, 0x567d2cd8, 0x223390ef +.word 0x87494ec7, 0xd938d1c1, 0x8ccaa2fe, 0x98d40b36 +.word 0xa6f581cf, 0xa57ade28, 0xdab78e26, 0x3fadbfa4 +.word 0x2c3a9de4, 0x5078920d, 0x6a5fcc9b, 0x547e4662 +.word 0xf68d13c2, 0x90d8b8e8, 0x2e39f75e, 0x82c3aff5 +.word 0x9f5d80be, 0x69d0937c, 0x6fd52da9, 0xcf2512b3 +.word 0xc8ac993b, 0x10187da7, 0xe89c636e, 0xdb3bbb7b +.word 0xcd267809, 0x6e5918f4, 0xec9ab701, 0x834f9aa8 +.word 0xe6956e65, 0xaaffe67e, 0x21bccf08, 0xef15e8e6 +.word 0xbae79bd9, 0x4a6f36ce, 0xea9f09d4, 0x29b07cd6 +.word 0x31a4b2af, 0x2a3f2331, 0xc6a59430, 0x35a266c0 +.word 0x744ebc37, 0xfc82caa6, 0xe090d0b0, 0x33a7d815 +.word 0xf104984a, 0x41ecdaf7, 0x7fcd500e, 0x1791f62f +.word 0x764dd68d, 0x43efb04d, 0xccaa4d54, 0xe49604df +.word 0x9ed1b5e3, 0x4c6a881b, 0xc12c1fb8, 0x4665517f +.word 0x9d5eea04, 0x018c355d, 0xfa877473, 0xfb0b412e +.word 0xb3671d5a, 0x92dbd252, 0xe9105633, 0x6dd64713 +.word 0x9ad7618c, 0x37a10c7a, 0x59f8148e, 0xeb133c89 +.word 0xcea927ee, 0xb761c935, 0xe11ce5ed, 0x7a47b13c +.word 0x9cd2df59, 0x55f2733f, 0x1814ce79, 0x73c737bf +.word 0x53f7cdea, 0x5ffdaa5b, 0xdf3d6f14, 0x7844db86 +.word 0xcaaff381, 0xb968c43e, 0x3824342c, 0xc2a3405f +.word 0x161dc372, 0xbce2250c, 0x283c498b, 0xff0d9541 +.word 0x39a80171, 0x080cb3de, 0xd8b4e49c, 0x6456c190 +.word 0x7bcb8461, 0xd532b670, 0x486c5c74, 0xd0b85742 +@ Td4[256] +.byte 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38 +.byte 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb +.byte 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87 +.byte 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb +.byte 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d +.byte 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e +.byte 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2 +.byte 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25 +.byte 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16 +.byte 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92 +.byte 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda +.byte 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84 +.byte 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a +.byte 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06 +.byte 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02 +.byte 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b +.byte 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea +.byte 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73 +.byte 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85 +.byte 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e +.byte 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89 +.byte 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b +.byte 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20 +.byte 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4 +.byte 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31 +.byte 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f +.byte 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d +.byte 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef +.byte 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0 +.byte 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61 +.byte 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26 +.byte 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d +.size AES_Td,.-AES_Td + +@ void AES_decrypt(const unsigned char *in, unsigned char *out, +@ const AES_KEY *key) { +.global AES_decrypt +.type AES_decrypt,%function +.align 5 +AES_decrypt: + sub r3,pc,#8 @ AES_decrypt + stmdb sp!,{r1,r4-r12,lr} + mov r12,r0 @ inp + mov r11,r2 + sub r10,r3,#AES_decrypt-AES_Td @ Td +#if __ARM_ARCH__<7 + ldrb r0,[r12,#3] @ load input data in endian-neutral + ldrb r4,[r12,#2] @ manner... + ldrb r5,[r12,#1] + ldrb r6,[r12,#0] + orr r0,r0,r4,lsl#8 + ldrb r1,[r12,#7] + orr r0,r0,r5,lsl#16 + ldrb r4,[r12,#6] + orr r0,r0,r6,lsl#24 + ldrb r5,[r12,#5] + ldrb r6,[r12,#4] + orr r1,r1,r4,lsl#8 + ldrb r2,[r12,#11] + orr r1,r1,r5,lsl#16 + ldrb r4,[r12,#10] + orr r1,r1,r6,lsl#24 + ldrb r5,[r12,#9] + ldrb r6,[r12,#8] + orr r2,r2,r4,lsl#8 + ldrb r3,[r12,#15] + orr r2,r2,r5,lsl#16 + ldrb r4,[r12,#14] + orr r2,r2,r6,lsl#24 + ldrb r5,[r12,#13] + ldrb r6,[r12,#12] + orr r3,r3,r4,lsl#8 + orr r3,r3,r5,lsl#16 + orr r3,r3,r6,lsl#24 +#else + ldr r0,[r12,#0] + ldr r1,[r12,#4] + ldr r2,[r12,#8] + ldr r3,[r12,#12] +#ifdef __ARMEL__ + rev r0,r0 + rev r1,r1 + rev r2,r2 + rev r3,r3 +#endif +#endif + bl _armv4_AES_decrypt + + ldr r12,[sp],#4 @ pop out +#if __ARM_ARCH__>=7 +#ifdef __ARMEL__ + rev r0,r0 + rev r1,r1 + rev r2,r2 + rev r3,r3 +#endif + str r0,[r12,#0] + str r1,[r12,#4] + str r2,[r12,#8] + str r3,[r12,#12] +#else + mov r4,r0,lsr#24 @ write output in endian-neutral + mov r5,r0,lsr#16 @ manner... + mov r6,r0,lsr#8 + strb r4,[r12,#0] + strb r5,[r12,#1] + mov r4,r1,lsr#24 + strb r6,[r12,#2] + mov r5,r1,lsr#16 + strb r0,[r12,#3] + mov r6,r1,lsr#8 + strb r4,[r12,#4] + strb r5,[r12,#5] + mov r4,r2,lsr#24 + strb r6,[r12,#6] + mov r5,r2,lsr#16 + strb r1,[r12,#7] + mov r6,r2,lsr#8 + strb r4,[r12,#8] + strb r5,[r12,#9] + mov r4,r3,lsr#24 + strb r6,[r12,#10] + mov r5,r3,lsr#16 + strb r2,[r12,#11] + mov r6,r3,lsr#8 + strb r4,[r12,#12] + strb r5,[r12,#13] + strb r6,[r12,#14] + strb r3,[r12,#15] +#endif +#if __ARM_ARCH__>=5 + ldmia sp!,{r4-r12,pc} +#else + ldmia sp!,{r4-r12,lr} + tst lr,#1 + moveq pc,lr @ be binary compatible with V4, yet + .word 0xe12fff1e @ interoperable with Thumb ISA:-) +#endif +.size AES_decrypt,.-AES_decrypt + +.type _armv4_AES_decrypt,%function +.align 2 +_armv4_AES_decrypt: + str lr,[sp,#-4]! @ push lr + ldmia r11!,{r4-r7} + eor r0,r0,r4 + ldr r12,[r11,#240-16] + eor r1,r1,r5 + eor r2,r2,r6 + eor r3,r3,r7 + sub r12,r12,#1 + mov lr,#255 + + and r7,lr,r0,lsr#16 + and r8,lr,r0,lsr#8 + and r9,lr,r0 + mov r0,r0,lsr#24 +.Ldec_loop: + ldr r4,[r10,r7,lsl#2] @ Td1[s0>>16] + and r7,lr,r1 @ i0 + ldr r5,[r10,r8,lsl#2] @ Td2[s0>>8] + and r8,lr,r1,lsr#16 + ldr r6,[r10,r9,lsl#2] @ Td3[s0>>0] + and r9,lr,r1,lsr#8 + ldr r0,[r10,r0,lsl#2] @ Td0[s0>>24] + mov r1,r1,lsr#24 + + ldr r7,[r10,r7,lsl#2] @ Td3[s1>>0] + ldr r8,[r10,r8,lsl#2] @ Td1[s1>>16] + ldr r9,[r10,r9,lsl#2] @ Td2[s1>>8] + eor r0,r0,r7,ror#24 + ldr r1,[r10,r1,lsl#2] @ Td0[s1>>24] + and r7,lr,r2,lsr#8 @ i0 + eor r5,r8,r5,ror#8 + and r8,lr,r2 @ i1 + eor r6,r9,r6,ror#8 + and r9,lr,r2,lsr#16 + ldr r7,[r10,r7,lsl#2] @ Td2[s2>>8] + eor r1,r1,r4,ror#8 + ldr r8,[r10,r8,lsl#2] @ Td3[s2>>0] + mov r2,r2,lsr#24 + + ldr r9,[r10,r9,lsl#2] @ Td1[s2>>16] + eor r0,r0,r7,ror#16 + ldr r2,[r10,r2,lsl#2] @ Td0[s2>>24] + and r7,lr,r3,lsr#16 @ i0 + eor r1,r1,r8,ror#24 + and r8,lr,r3,lsr#8 @ i1 + eor r6,r9,r6,ror#8 + and r9,lr,r3 @ i2 + ldr r7,[r10,r7,lsl#2] @ Td1[s3>>16] + eor r2,r2,r5,ror#8 + ldr r8,[r10,r8,lsl#2] @ Td2[s3>>8] + mov r3,r3,lsr#24 + + ldr r9,[r10,r9,lsl#2] @ Td3[s3>>0] + eor r0,r0,r7,ror#8 + ldr r7,[r11],#16 + eor r1,r1,r8,ror#16 + ldr r3,[r10,r3,lsl#2] @ Td0[s3>>24] + eor r2,r2,r9,ror#24 + + ldr r4,[r11,#-12] + eor r0,r0,r7 + ldr r5,[r11,#-8] + eor r3,r3,r6,ror#8 + ldr r6,[r11,#-4] + and r7,lr,r0,lsr#16 + eor r1,r1,r4 + and r8,lr,r0,lsr#8 + eor r2,r2,r5 + and r9,lr,r0 + eor r3,r3,r6 + mov r0,r0,lsr#24 + + subs r12,r12,#1 + bne .Ldec_loop + + add r10,r10,#1024 + + ldr r5,[r10,#0] @ prefetch Td4 + ldr r6,[r10,#32] + ldr r4,[r10,#64] + ldr r5,[r10,#96] + ldr r6,[r10,#128] + ldr r4,[r10,#160] + ldr r5,[r10,#192] + ldr r6,[r10,#224] + + ldrb r0,[r10,r0] @ Td4[s0>>24] + ldrb r4,[r10,r7] @ Td4[s0>>16] + and r7,lr,r1 @ i0 + ldrb r5,[r10,r8] @ Td4[s0>>8] + and r8,lr,r1,lsr#16 + ldrb r6,[r10,r9] @ Td4[s0>>0] + and r9,lr,r1,lsr#8 + + ldrb r7,[r10,r7] @ Td4[s1>>0] + ldrb r1,[r10,r1,lsr#24] @ Td4[s1>>24] + ldrb r8,[r10,r8] @ Td4[s1>>16] + eor r0,r7,r0,lsl#24 + ldrb r9,[r10,r9] @ Td4[s1>>8] + eor r1,r4,r1,lsl#8 + and r7,lr,r2,lsr#8 @ i0 + eor r5,r5,r8,lsl#8 + and r8,lr,r2 @ i1 + ldrb r7,[r10,r7] @ Td4[s2>>8] + eor r6,r6,r9,lsl#8 + ldrb r8,[r10,r8] @ Td4[s2>>0] + and r9,lr,r2,lsr#16 + + ldrb r2,[r10,r2,lsr#24] @ Td4[s2>>24] + eor r0,r0,r7,lsl#8 + ldrb r9,[r10,r9] @ Td4[s2>>16] + eor r1,r8,r1,lsl#16 + and r7,lr,r3,lsr#16 @ i0 + eor r2,r5,r2,lsl#16 + and r8,lr,r3,lsr#8 @ i1 + ldrb r7,[r10,r7] @ Td4[s3>>16] + eor r6,r6,r9,lsl#16 + ldrb r8,[r10,r8] @ Td4[s3>>8] + and r9,lr,r3 @ i2 + + ldrb r9,[r10,r9] @ Td4[s3>>0] + ldrb r3,[r10,r3,lsr#24] @ Td4[s3>>24] + eor r0,r0,r7,lsl#16 + ldr r7,[r11,#0] + eor r1,r1,r8,lsl#8 + ldr r4,[r11,#4] + eor r2,r9,r2,lsl#8 + ldr r5,[r11,#8] + eor r3,r6,r3,lsl#24 + ldr r6,[r11,#12] + + eor r0,r0,r7 + eor r1,r1,r4 + eor r2,r2,r5 + eor r3,r3,r6 + + sub r10,r10,#1024 + ldr pc,[sp],#4 @ pop and return +.size _armv4_AES_decrypt,.-_armv4_AES_decrypt +.asciz "AES for ARMv4, CRYPTOGAMS by " +.align 2 diff --git a/arch/arm/crypto/aes_glue.c b/arch/arm/crypto/aes_glue.c new file mode 100644 index 00000000000..59f7877ead6 --- /dev/null +++ b/arch/arm/crypto/aes_glue.c @@ -0,0 +1,108 @@ +/* + * Glue Code for the asm optimized version of the AES Cipher Algorithm + */ + +#include +#include +#include + +#define AES_MAXNR 14 + +typedef struct { + unsigned int rd_key[4 *(AES_MAXNR + 1)]; + int rounds; +} AES_KEY; + +struct AES_CTX { + AES_KEY enc_key; + AES_KEY dec_key; +}; + +asmlinkage void AES_encrypt(const u8 *in, u8 *out, AES_KEY *ctx); +asmlinkage void AES_decrypt(const u8 *in, u8 *out, AES_KEY *ctx); +asmlinkage int private_AES_set_decrypt_key(const unsigned char *userKey, const int bits, AES_KEY *key); +asmlinkage int private_AES_set_encrypt_key(const unsigned char *userKey, const int bits, AES_KEY *key); + +static void aes_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) +{ + struct AES_CTX *ctx = crypto_tfm_ctx(tfm); + AES_encrypt(src, dst, &ctx->enc_key); +} + +static void aes_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) +{ + struct AES_CTX *ctx = crypto_tfm_ctx(tfm); + AES_decrypt(src, dst, &ctx->dec_key); +} + +static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, + unsigned int key_len) +{ + struct AES_CTX *ctx = crypto_tfm_ctx(tfm); + + switch (key_len) { + case AES_KEYSIZE_128: + key_len = 128; + break; + case AES_KEYSIZE_192: + key_len = 192; + break; + case AES_KEYSIZE_256: + key_len = 256; + break; + default: + tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; + return -EINVAL; + } + + if (private_AES_set_encrypt_key(in_key, key_len, &ctx->enc_key) == -1) { + tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; + return -EINVAL; + } + /* private_AES_set_decrypt_key expects an encryption key as input */ + ctx->dec_key = ctx->enc_key; + if (private_AES_set_decrypt_key(in_key, key_len, &ctx->dec_key) == -1) { + tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; + return -EINVAL; + } + return 0; +} + +static struct crypto_alg aes_alg = { + .cra_name = "aes", + .cra_driver_name = "aes-asm", + .cra_priority = 200, + .cra_flags = CRYPTO_ALG_TYPE_CIPHER, + .cra_blocksize = AES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct AES_CTX), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(aes_alg.cra_list), + .cra_u = { + .cipher = { + .cia_min_keysize = AES_MIN_KEY_SIZE, + .cia_max_keysize = AES_MAX_KEY_SIZE, + .cia_setkey = aes_set_key, + .cia_encrypt = aes_encrypt, + .cia_decrypt = aes_decrypt + } + } +}; + +static int __init aes_init(void) +{ + return crypto_register_alg(&aes_alg); +} + +static void __exit aes_fini(void) +{ + crypto_unregister_alg(&aes_alg); +} + +module_init(aes_init); +module_exit(aes_fini); + +MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm (ASM)"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("aes"); +MODULE_ALIAS("aes-asm"); +MODULE_AUTHOR("David McCullough "); diff --git a/arch/arm/crypto/sha1-armv4-large.S b/arch/arm/crypto/sha1-armv4-large.S new file mode 100644 index 00000000000..7050ab133b9 --- /dev/null +++ b/arch/arm/crypto/sha1-armv4-large.S @@ -0,0 +1,503 @@ +#define __ARM_ARCH__ __LINUX_ARM_ARCH__ +@ ==================================================================== +@ Written by Andy Polyakov for the OpenSSL +@ project. The module is, however, dual licensed under OpenSSL and +@ CRYPTOGAMS licenses depending on where you obtain it. For further +@ details see http://www.openssl.org/~appro/cryptogams/. +@ ==================================================================== + +@ sha1_block procedure for ARMv4. +@ +@ January 2007. + +@ Size/performance trade-off +@ ==================================================================== +@ impl size in bytes comp cycles[*] measured performance +@ ==================================================================== +@ thumb 304 3212 4420 +@ armv4-small 392/+29% 1958/+64% 2250/+96% +@ armv4-compact 740/+89% 1552/+26% 1840/+22% +@ armv4-large 1420/+92% 1307/+19% 1370/+34%[***] +@ full unroll ~5100/+260% ~1260/+4% ~1300/+5% +@ ==================================================================== +@ thumb = same as 'small' but in Thumb instructions[**] and +@ with recurring code in two private functions; +@ small = detached Xload/update, loops are folded; +@ compact = detached Xload/update, 5x unroll; +@ large = interleaved Xload/update, 5x unroll; +@ full unroll = interleaved Xload/update, full unroll, estimated[!]; +@ +@ [*] Manually counted instructions in "grand" loop body. Measured +@ performance is affected by prologue and epilogue overhead, +@ i-cache availability, branch penalties, etc. +@ [**] While each Thumb instruction is twice smaller, they are not as +@ diverse as ARM ones: e.g., there are only two arithmetic +@ instructions with 3 arguments, no [fixed] rotate, addressing +@ modes are limited. As result it takes more instructions to do +@ the same job in Thumb, therefore the code is never twice as +@ small and always slower. +@ [***] which is also ~35% better than compiler generated code. Dual- +@ issue Cortex A8 core was measured to process input block in +@ ~990 cycles. + +@ August 2010. +@ +@ Rescheduling for dual-issue pipeline resulted in 13% improvement on +@ Cortex A8 core and in absolute terms ~870 cycles per input block +@ [or 13.6 cycles per byte]. + +@ February 2011. +@ +@ Profiler-assisted and platform-specific optimization resulted in 10% +@ improvement on Cortex A8 core and 12.2 cycles per byte. + +.text + +.global sha1_block_data_order +.type sha1_block_data_order,%function + +.align 2 +sha1_block_data_order: + stmdb sp!,{r4-r12,lr} + add r2,r1,r2,lsl#6 @ r2 to point at the end of r1 + ldmia r0,{r3,r4,r5,r6,r7} +.Lloop: + ldr r8,.LK_00_19 + mov r14,sp + sub sp,sp,#15*4 + mov r5,r5,ror#30 + mov r6,r6,ror#30 + mov r7,r7,ror#30 @ [6] +.L_00_15: +#if __ARM_ARCH__<7 + ldrb r10,[r1,#2] + ldrb r9,[r1,#3] + ldrb r11,[r1,#1] + add r7,r8,r7,ror#2 @ E+=K_00_19 + ldrb r12,[r1],#4 + orr r9,r9,r10,lsl#8 + eor r10,r5,r6 @ F_xx_xx + orr r9,r9,r11,lsl#16 + add r7,r7,r3,ror#27 @ E+=ROR(A,27) + orr r9,r9,r12,lsl#24 +#else + ldr r9,[r1],#4 @ handles unaligned + add r7,r8,r7,ror#2 @ E+=K_00_19 + eor r10,r5,r6 @ F_xx_xx + add r7,r7,r3,ror#27 @ E+=ROR(A,27) +#ifdef __ARMEL__ + rev r9,r9 @ byte swap +#endif +#endif + and r10,r4,r10,ror#2 + add r7,r7,r9 @ E+=X[i] + eor r10,r10,r6,ror#2 @ F_00_19(B,C,D) + str r9,[r14,#-4]! + add r7,r7,r10 @ E+=F_00_19(B,C,D) +#if __ARM_ARCH__<7 + ldrb r10,[r1,#2] + ldrb r9,[r1,#3] + ldrb r11,[r1,#1] + add r6,r8,r6,ror#2 @ E+=K_00_19 + ldrb r12,[r1],#4 + orr r9,r9,r10,lsl#8 + eor r10,r4,r5 @ F_xx_xx + orr r9,r9,r11,lsl#16 + add r6,r6,r7,ror#27 @ E+=ROR(A,27) + orr r9,r9,r12,lsl#24 +#else + ldr r9,[r1],#4 @ handles unaligned + add r6,r8,r6,ror#2 @ E+=K_00_19 + eor r10,r4,r5 @ F_xx_xx + add r6,r6,r7,ror#27 @ E+=ROR(A,27) +#ifdef __ARMEL__ + rev r9,r9 @ byte swap +#endif +#endif + and r10,r3,r10,ror#2 + add r6,r6,r9 @ E+=X[i] + eor r10,r10,r5,ror#2 @ F_00_19(B,C,D) + str r9,[r14,#-4]! + add r6,r6,r10 @ E+=F_00_19(B,C,D) +#if __ARM_ARCH__<7 + ldrb r10,[r1,#2] + ldrb r9,[r1,#3] + ldrb r11,[r1,#1] + add r5,r8,r5,ror#2 @ E+=K_00_19 + ldrb r12,[r1],#4 + orr r9,r9,r10,lsl#8 + eor r10,r3,r4 @ F_xx_xx + orr r9,r9,r11,lsl#16 + add r5,r5,r6,ror#27 @ E+=ROR(A,27) + orr r9,r9,r12,lsl#24 +#else + ldr r9,[r1],#4 @ handles unaligned + add r5,r8,r5,ror#2 @ E+=K_00_19 + eor r10,r3,r4 @ F_xx_xx + add r5,r5,r6,ror#27 @ E+=ROR(A,27) +#ifdef __ARMEL__ + rev r9,r9 @ byte swap +#endif +#endif + and r10,r7,r10,ror#2 + add r5,r5,r9 @ E+=X[i] + eor r10,r10,r4,ror#2 @ F_00_19(B,C,D) + str r9,[r14,#-4]! + add r5,r5,r10 @ E+=F_00_19(B,C,D) +#if __ARM_ARCH__<7 + ldrb r10,[r1,#2] + ldrb r9,[r1,#3] + ldrb r11,[r1,#1] + add r4,r8,r4,ror#2 @ E+=K_00_19 + ldrb r12,[r1],#4 + orr r9,r9,r10,lsl#8 + eor r10,r7,r3 @ F_xx_xx + orr r9,r9,r11,lsl#16 + add r4,r4,r5,ror#27 @ E+=ROR(A,27) + orr r9,r9,r12,lsl#24 +#else + ldr r9,[r1],#4 @ handles unaligned + add r4,r8,r4,ror#2 @ E+=K_00_19 + eor r10,r7,r3 @ F_xx_xx + add r4,r4,r5,ror#27 @ E+=ROR(A,27) +#ifdef __ARMEL__ + rev r9,r9 @ byte swap +#endif +#endif + and r10,r6,r10,ror#2 + add r4,r4,r9 @ E+=X[i] + eor r10,r10,r3,ror#2 @ F_00_19(B,C,D) + str r9,[r14,#-4]! + add r4,r4,r10 @ E+=F_00_19(B,C,D) +#if __ARM_ARCH__<7 + ldrb r10,[r1,#2] + ldrb r9,[r1,#3] + ldrb r11,[r1,#1] + add r3,r8,r3,ror#2 @ E+=K_00_19 + ldrb r12,[r1],#4 + orr r9,r9,r10,lsl#8 + eor r10,r6,r7 @ F_xx_xx + orr r9,r9,r11,lsl#16 + add r3,r3,r4,ror#27 @ E+=ROR(A,27) + orr r9,r9,r12,lsl#24 +#else + ldr r9,[r1],#4 @ handles unaligned + add r3,r8,r3,ror#2 @ E+=K_00_19 + eor r10,r6,r7 @ F_xx_xx + add r3,r3,r4,ror#27 @ E+=ROR(A,27) +#ifdef __ARMEL__ + rev r9,r9 @ byte swap +#endif +#endif + and r10,r5,r10,ror#2 + add r3,r3,r9 @ E+=X[i] + eor r10,r10,r7,ror#2 @ F_00_19(B,C,D) + str r9,[r14,#-4]! + add r3,r3,r10 @ E+=F_00_19(B,C,D) + teq r14,sp + bne .L_00_15 @ [((11+4)*5+2)*3] +#if __ARM_ARCH__<7 + ldrb r10,[r1,#2] + ldrb r9,[r1,#3] + ldrb r11,[r1,#1] + add r7,r8,r7,ror#2 @ E+=K_00_19 + ldrb r12,[r1],#4 + orr r9,r9,r10,lsl#8 + eor r10,r5,r6 @ F_xx_xx + orr r9,r9,r11,lsl#16 + add r7,r7,r3,ror#27 @ E+=ROR(A,27) + orr r9,r9,r12,lsl#24 +#else + ldr r9,[r1],#4 @ handles unaligned + add r7,r8,r7,ror#2 @ E+=K_00_19 + eor r10,r5,r6 @ F_xx_xx + add r7,r7,r3,ror#27 @ E+=ROR(A,27) +#ifdef __ARMEL__ + rev r9,r9 @ byte swap +#endif +#endif + and r10,r4,r10,ror#2 + add r7,r7,r9 @ E+=X[i] + eor r10,r10,r6,ror#2 @ F_00_19(B,C,D) + str r9,[r14,#-4]! + add r7,r7,r10 @ E+=F_00_19(B,C,D) + ldr r9,[r14,#15*4] + ldr r10,[r14,#13*4] + ldr r11,[r14,#7*4] + add r6,r8,r6,ror#2 @ E+=K_xx_xx + ldr r12,[r14,#2*4] + eor r9,r9,r10 + eor r11,r11,r12 @ 1 cycle stall + eor r10,r4,r5 @ F_xx_xx + mov r9,r9,ror#31 + add r6,r6,r7,ror#27 @ E+=ROR(A,27) + eor r9,r9,r11,ror#31 + str r9,[r14,#-4]! + and r10,r3,r10,ror#2 @ F_xx_xx + @ F_xx_xx + add r6,r6,r9 @ E+=X[i] + eor r10,r10,r5,ror#2 @ F_00_19(B,C,D) + add r6,r6,r10 @ E+=F_00_19(B,C,D) + ldr r9,[r14,#15*4] + ldr r10,[r14,#13*4] + ldr r11,[r14,#7*4] + add r5,r8,r5,ror#2 @ E+=K_xx_xx + ldr r12,[r14,#2*4] + eor r9,r9,r10 + eor r11,r11,r12 @ 1 cycle stall + eor r10,r3,r4 @ F_xx_xx + mov r9,r9,ror#31 + add r5,r5,r6,ror#27 @ E+=ROR(A,27) + eor r9,r9,r11,ror#31 + str r9,[r14,#-4]! + and r10,r7,r10,ror#2 @ F_xx_xx + @ F_xx_xx + add r5,r5,r9 @ E+=X[i] + eor r10,r10,r4,ror#2 @ F_00_19(B,C,D) + add r5,r5,r10 @ E+=F_00_19(B,C,D) + ldr r9,[r14,#15*4] + ldr r10,[r14,#13*4] + ldr r11,[r14,#7*4] + add r4,r8,r4,ror#2 @ E+=K_xx_xx + ldr r12,[r14,#2*4] + eor r9,r9,r10 + eor r11,r11,r12 @ 1 cycle stall + eor r10,r7,r3 @ F_xx_xx + mov r9,r9,ror#31 + add r4,r4,r5,ror#27 @ E+=ROR(A,27) + eor r9,r9,r11,ror#31 + str r9,[r14,#-4]! + and r10,r6,r10,ror#2 @ F_xx_xx + @ F_xx_xx + add r4,r4,r9 @ E+=X[i] + eor r10,r10,r3,ror#2 @ F_00_19(B,C,D) + add r4,r4,r10 @ E+=F_00_19(B,C,D) + ldr r9,[r14,#15*4] + ldr r10,[r14,#13*4] + ldr r11,[r14,#7*4] + add r3,r8,r3,ror#2 @ E+=K_xx_xx + ldr r12,[r14,#2*4] + eor r9,r9,r10 + eor r11,r11,r12 @ 1 cycle stall + eor r10,r6,r7 @ F_xx_xx + mov r9,r9,ror#31 + add r3,r3,r4,ror#27 @ E+=ROR(A,27) + eor r9,r9,r11,ror#31 + str r9,[r14,#-4]! + and r10,r5,r10,ror#2 @ F_xx_xx + @ F_xx_xx + add r3,r3,r9 @ E+=X[i] + eor r10,r10,r7,ror#2 @ F_00_19(B,C,D) + add r3,r3,r10 @ E+=F_00_19(B,C,D) + + ldr r8,.LK_20_39 @ [+15+16*4] + sub sp,sp,#25*4 + cmn sp,#0 @ [+3], clear carry to denote 20_39 +.L_20_39_or_60_79: + ldr r9,[r14,#15*4] + ldr r10,[r14,#13*4] + ldr r11,[r14,#7*4] + add r7,r8,r7,ror#2 @ E+=K_xx_xx + ldr r12,[r14,#2*4] + eor r9,r9,r10 + eor r11,r11,r12 @ 1 cycle stall + eor r10,r5,r6 @ F_xx_xx + mov r9,r9,ror#31 + add r7,r7,r3,ror#27 @ E+=ROR(A,27) + eor r9,r9,r11,ror#31 + str r9,[r14,#-4]! + eor r10,r4,r10,ror#2 @ F_xx_xx + @ F_xx_xx + add r7,r7,r9 @ E+=X[i] + add r7,r7,r10 @ E+=F_20_39(B,C,D) + ldr r9,[r14,#15*4] + ldr r10,[r14,#13*4] + ldr r11,[r14,#7*4] + add r6,r8,r6,ror#2 @ E+=K_xx_xx + ldr r12,[r14,#2*4] + eor r9,r9,r10 + eor r11,r11,r12 @ 1 cycle stall + eor r10,r4,r5 @ F_xx_xx + mov r9,r9,ror#31 + add r6,r6,r7,ror#27 @ E+=ROR(A,27) + eor r9,r9,r11,ror#31 + str r9,[r14,#-4]! + eor r10,r3,r10,ror#2 @ F_xx_xx + @ F_xx_xx + add r6,r6,r9 @ E+=X[i] + add r6,r6,r10 @ E+=F_20_39(B,C,D) + ldr r9,[r14,#15*4] + ldr r10,[r14,#13*4] + ldr r11,[r14,#7*4] + add r5,r8,r5,ror#2 @ E+=K_xx_xx + ldr r12,[r14,#2*4] + eor r9,r9,r10 + eor r11,r11,r12 @ 1 cycle stall + eor r10,r3,r4 @ F_xx_xx + mov r9,r9,ror#31 + add r5,r5,r6,ror#27 @ E+=ROR(A,27) + eor r9,r9,r11,ror#31 + str r9,[r14,#-4]! + eor r10,r7,r10,ror#2 @ F_xx_xx + @ F_xx_xx + add r5,r5,r9 @ E+=X[i] + add r5,r5,r10 @ E+=F_20_39(B,C,D) + ldr r9,[r14,#15*4] + ldr r10,[r14,#13*4] + ldr r11,[r14,#7*4] + add r4,r8,r4,ror#2 @ E+=K_xx_xx + ldr r12,[r14,#2*4] + eor r9,r9,r10 + eor r11,r11,r12 @ 1 cycle stall + eor r10,r7,r3 @ F_xx_xx + mov r9,r9,ror#31 + add r4,r4,r5,ror#27 @ E+=ROR(A,27) + eor r9,r9,r11,ror#31 + str r9,[r14,#-4]! + eor r10,r6,r10,ror#2 @ F_xx_xx + @ F_xx_xx + add r4,r4,r9 @ E+=X[i] + add r4,r4,r10 @ E+=F_20_39(B,C,D) + ldr r9,[r14,#15*4] + ldr r10,[r14,#13*4] + ldr r11,[r14,#7*4] + add r3,r8,r3,ror#2 @ E+=K_xx_xx + ldr r12,[r14,#2*4] + eor r9,r9,r10 + eor r11,r11,r12 @ 1 cycle stall + eor r10,r6,r7 @ F_xx_xx + mov r9,r9,ror#31 + add r3,r3,r4,ror#27 @ E+=ROR(A,27) + eor r9,r9,r11,ror#31 + str r9,[r14,#-4]! + eor r10,r5,r10,ror#2 @ F_xx_xx + @ F_xx_xx + add r3,r3,r9 @ E+=X[i] + add r3,r3,r10 @ E+=F_20_39(B,C,D) + teq r14,sp @ preserve carry + bne .L_20_39_or_60_79 @ [+((12+3)*5+2)*4] + bcs .L_done @ [+((12+3)*5+2)*4], spare 300 bytes + + ldr r8,.LK_40_59 + sub sp,sp,#20*4 @ [+2] +.L_40_59: + ldr r9,[r14,#15*4] + ldr r10,[r14,#13*4] + ldr r11,[r14,#7*4] + add r7,r8,r7,ror#2 @ E+=K_xx_xx + ldr r12,[r14,#2*4] + eor r9,r9,r10 + eor r11,r11,r12 @ 1 cycle stall + eor r10,r5,r6 @ F_xx_xx + mov r9,r9,ror#31 + add r7,r7,r3,ror#27 @ E+=ROR(A,27) + eor r9,r9,r11,ror#31 + str r9,[r14,#-4]! + and r10,r4,r10,ror#2 @ F_xx_xx + and r11,r5,r6 @ F_xx_xx + add r7,r7,r9 @ E+=X[i] + add r7,r7,r10 @ E+=F_40_59(B,C,D) + add r7,r7,r11,ror#2 + ldr r9,[r14,#15*4] + ldr r10,[r14,#13*4] + ldr r11,[r14,#7*4] + add r6,r8,r6,ror#2 @ E+=K_xx_xx + ldr r12,[r14,#2*4] + eor r9,r9,r10 + eor r11,r11,r12 @ 1 cycle stall + eor r10,r4,r5 @ F_xx_xx + mov r9,r9,ror#31 + add r6,r6,r7,ror#27 @ E+=ROR(A,27) + eor r9,r9,r11,ror#31 + str r9,[r14,#-4]! + and r10,r3,r10,ror#2 @ F_xx_xx + and r11,r4,r5 @ F_xx_xx + add r6,r6,r9 @ E+=X[i] + add r6,r6,r10 @ E+=F_40_59(B,C,D) + add r6,r6,r11,ror#2 + ldr r9,[r14,#15*4] + ldr r10,[r14,#13*4] + ldr r11,[r14,#7*4] + add r5,r8,r5,ror#2 @ E+=K_xx_xx + ldr r12,[r14,#2*4] + eor r9,r9,r10 + eor r11,r11,r12 @ 1 cycle stall + eor r10,r3,r4 @ F_xx_xx + mov r9,r9,ror#31 + add r5,r5,r6,ror#27 @ E+=ROR(A,27) + eor r9,r9,r11,ror#31 + str r9,[r14,#-4]! + and r10,r7,r10,ror#2 @ F_xx_xx + and r11,r3,r4 @ F_xx_xx + add r5,r5,r9 @ E+=X[i] + add r5,r5,r10 @ E+=F_40_59(B,C,D) + add r5,r5,r11,ror#2 + ldr r9,[r14,#15*4] + ldr r10,[r14,#13*4] + ldr r11,[r14,#7*4] + add r4,r8,r4,ror#2 @ E+=K_xx_xx + ldr r12,[r14,#2*4] + eor r9,r9,r10 + eor r11,r11,r12 @ 1 cycle stall + eor r10,r7,r3 @ F_xx_xx + mov r9,r9,ror#31 + add r4,r4,r5,ror#27 @ E+=ROR(A,27) + eor r9,r9,r11,ror#31 + str r9,[r14,#-4]! + and r10,r6,r10,ror#2 @ F_xx_xx + and r11,r7,r3 @ F_xx_xx + add r4,r4,r9 @ E+=X[i] + add r4,r4,r10 @ E+=F_40_59(B,C,D) + add r4,r4,r11,ror#2 + ldr r9,[r14,#15*4] + ldr r10,[r14,#13*4] + ldr r11,[r14,#7*4] + add r3,r8,r3,ror#2 @ E+=K_xx_xx + ldr r12,[r14,#2*4] + eor r9,r9,r10 + eor r11,r11,r12 @ 1 cycle stall + eor r10,r6,r7 @ F_xx_xx + mov r9,r9,ror#31 + add r3,r3,r4,ror#27 @ E+=ROR(A,27) + eor r9,r9,r11,ror#31 + str r9,[r14,#-4]! + and r10,r5,r10,ror#2 @ F_xx_xx + and r11,r6,r7 @ F_xx_xx + add r3,r3,r9 @ E+=X[i] + add r3,r3,r10 @ E+=F_40_59(B,C,D) + add r3,r3,r11,ror#2 + teq r14,sp + bne .L_40_59 @ [+((12+5)*5+2)*4] + + ldr r8,.LK_60_79 + sub sp,sp,#20*4 + cmp sp,#0 @ set carry to denote 60_79 + b .L_20_39_or_60_79 @ [+4], spare 300 bytes +.L_done: + add sp,sp,#80*4 @ "deallocate" stack frame + ldmia r0,{r8,r9,r10,r11,r12} + add r3,r8,r3 + add r4,r9,r4 + add r5,r10,r5,ror#2 + add r6,r11,r6,ror#2 + add r7,r12,r7,ror#2 + stmia r0,{r3,r4,r5,r6,r7} + teq r1,r2 + bne .Lloop @ [+18], total 1307 + +#if __ARM_ARCH__>=5 + ldmia sp!,{r4-r12,pc} +#else + ldmia sp!,{r4-r12,lr} + tst lr,#1 + moveq pc,lr @ be binary compatible with V4, yet + .word 0xe12fff1e @ interoperable with Thumb ISA:-) +#endif +.align 2 +.LK_00_19: .word 0x5a827999 +.LK_20_39: .word 0x6ed9eba1 +.LK_40_59: .word 0x8f1bbcdc +.LK_60_79: .word 0xca62c1d6 +.size sha1_block_data_order,.-sha1_block_data_order +.asciz "SHA1 block transform for ARMv4, CRYPTOGAMS by " +.align 2 diff --git a/arch/arm/crypto/sha1_glue.c b/arch/arm/crypto/sha1_glue.c new file mode 100644 index 00000000000..76cd976230b --- /dev/null +++ b/arch/arm/crypto/sha1_glue.c @@ -0,0 +1,179 @@ +/* + * Cryptographic API. + * Glue code for the SHA1 Secure Hash Algorithm assembler implementation + * + * This file is based on sha1_generic.c and sha1_ssse3_glue.c + * + * Copyright (c) Alan Smithee. + * Copyright (c) Andrew McDonald + * Copyright (c) Jean-Francois Dive + * Copyright (c) Mathias Krause + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +struct SHA1_CTX { + uint32_t h0,h1,h2,h3,h4; + u64 count; + u8 data[SHA1_BLOCK_SIZE]; +}; + +asmlinkage void sha1_block_data_order(struct SHA1_CTX *digest, + const unsigned char *data, unsigned int rounds); + + +static int sha1_init(struct shash_desc *desc) +{ + struct SHA1_CTX *sctx = shash_desc_ctx(desc); + memset(sctx, 0, sizeof(*sctx)); + sctx->h0 = SHA1_H0; + sctx->h1 = SHA1_H1; + sctx->h2 = SHA1_H2; + sctx->h3 = SHA1_H3; + sctx->h4 = SHA1_H4; + return 0; +} + + +static int __sha1_update(struct SHA1_CTX *sctx, const u8 *data, + unsigned int len, unsigned int partial) +{ + unsigned int done = 0; + + sctx->count += len; + + if (partial) { + done = SHA1_BLOCK_SIZE - partial; + memcpy(sctx->data + partial, data, done); + sha1_block_data_order(sctx, sctx->data, 1); + } + + if (len - done >= SHA1_BLOCK_SIZE) { + const unsigned int rounds = (len - done) / SHA1_BLOCK_SIZE; + sha1_block_data_order(sctx, data + done, rounds); + done += rounds * SHA1_BLOCK_SIZE; + } + + memcpy(sctx->data, data + done, len - done); + return 0; +} + + +static int sha1_update(struct shash_desc *desc, const u8 *data, + unsigned int len) +{ + struct SHA1_CTX *sctx = shash_desc_ctx(desc); + unsigned int partial = sctx->count % SHA1_BLOCK_SIZE; + int res; + + /* Handle the fast case right here */ + if (partial + len < SHA1_BLOCK_SIZE) { + sctx->count += len; + memcpy(sctx->data + partial, data, len); + return 0; + } + res = __sha1_update(sctx, data, len, partial); + return res; +} + + +/* Add padding and return the message digest. */ +static int sha1_final(struct shash_desc *desc, u8 *out) +{ + struct SHA1_CTX *sctx = shash_desc_ctx(desc); + unsigned int i, index, padlen; + __be32 *dst = (__be32 *)out; + __be64 bits; + static const u8 padding[SHA1_BLOCK_SIZE] = { 0x80, }; + + bits = cpu_to_be64(sctx->count << 3); + + /* Pad out to 56 mod 64 and append length */ + index = sctx->count % SHA1_BLOCK_SIZE; + padlen = (index < 56) ? (56 - index) : ((SHA1_BLOCK_SIZE+56) - index); + /* We need to fill a whole block for __sha1_update() */ + if (padlen <= 56) { + sctx->count += padlen; + memcpy(sctx->data + index, padding, padlen); + } else { + __sha1_update(sctx, padding, padlen, index); + } + __sha1_update(sctx, (const u8 *)&bits, sizeof(bits), 56); + + /* Store state in digest */ + for (i = 0; i < 5; i++) + dst[i] = cpu_to_be32(((u32 *)sctx)[i]); + + /* Wipe context */ + memset(sctx, 0, sizeof(*sctx)); + return 0; +} + + +static int sha1_export(struct shash_desc *desc, void *out) +{ + struct SHA1_CTX *sctx = shash_desc_ctx(desc); + memcpy(out, sctx, sizeof(*sctx)); + return 0; +} + + +static int sha1_import(struct shash_desc *desc, const void *in) +{ + struct SHA1_CTX *sctx = shash_desc_ctx(desc); + memcpy(sctx, in, sizeof(*sctx)); + return 0; +} + + +static struct shash_alg alg = { + .digestsize = SHA1_DIGEST_SIZE, + .init = sha1_init, + .update = sha1_update, + .final = sha1_final, + .export = sha1_export, + .import = sha1_import, + .descsize = sizeof(struct SHA1_CTX), + .statesize = sizeof(struct SHA1_CTX), + .base = { + .cra_name = "sha1", + .cra_driver_name= "sha1-asm", + .cra_priority = 150, + .cra_flags = CRYPTO_ALG_TYPE_SHASH, + .cra_blocksize = SHA1_BLOCK_SIZE, + .cra_module = THIS_MODULE, + } +}; + + +static int __init sha1_mod_init(void) +{ + return crypto_register_shash(&alg); +} + + +static void __exit sha1_mod_fini(void) +{ + crypto_unregister_shash(&alg); +} + + +module_init(sha1_mod_init); +module_exit(sha1_mod_fini); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm (ARM)"); +MODULE_ALIAS("sha1"); +MODULE_AUTHOR("David McCullough "); diff --git a/arch/arm/include/asm/kexec.h b/arch/arm/include/asm/kexec.h index c2b9b4bdec0..564c55b394e 100644 --- a/arch/arm/include/asm/kexec.h +++ b/arch/arm/include/asm/kexec.h @@ -17,6 +17,10 @@ #define KEXEC_ARM_ATAGS_OFFSET 0x1000 #define KEXEC_ARM_ZIMAGE_OFFSET 0x8000 +#ifdef CONFIG_KEXEC_HARDBOOT + #define KEXEC_HB_PAGE_MAGIC 0x4a5db007 +#endif + #ifndef __ASSEMBLY__ /** @@ -53,6 +57,10 @@ static inline void crash_setup_regs(struct pt_regs *newregs, /* Function pointer to optional machine-specific reinitialization */ extern void (*kexec_reinit)(void); +#ifdef CONFIG_KEXEC_HARDBOOT +extern void (*kexec_hardboot_hook)(void); +#endif + #endif /* __ASSEMBLY__ */ #endif /* CONFIG_KEXEC */ diff --git a/arch/arm/include/asm/rwsem.h b/arch/arm/include/asm/rwsem.h new file mode 100644 index 00000000000..067fbfa28a4 --- /dev/null +++ b/arch/arm/include/asm/rwsem.h @@ -0,0 +1,138 @@ +/* rwsem.h: R/W semaphores implemented using ARM atomic functions. + * + * Copyright (c) 2010, Code Aurora Forum. 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 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#ifndef _ASM_ARM_RWSEM_H +#define _ASM_ARM_RWSEM_H + +#ifndef _LINUX_RWSEM_H +#error "please don't include asm/rwsem.h directly, use linux/rwsem.h instead" +#endif + +#ifdef __KERNEL__ +#include +#include + +#define RWSEM_UNLOCKED_VALUE 0x00000000 +#define RWSEM_ACTIVE_BIAS 0x00000001 +#define RWSEM_ACTIVE_MASK 0x0000ffff +#define RWSEM_WAITING_BIAS (-0x00010000) +#define RWSEM_ACTIVE_READ_BIAS RWSEM_ACTIVE_BIAS +#define RWSEM_ACTIVE_WRITE_BIAS (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS) + +/* + * lock for reading + */ +static inline void __down_read(struct rw_semaphore *sem) +{ + if (atomic_inc_return((atomic_t *)(&sem->count)) < 0) + rwsem_down_read_failed(sem); +} + +static inline int __down_read_trylock(struct rw_semaphore *sem) +{ + int tmp; + + while ((tmp = sem->count) >= 0) { + if (tmp == cmpxchg(&sem->count, tmp, + tmp + RWSEM_ACTIVE_READ_BIAS)) { + return 1; + } + } + return 0; +} + +/* + * lock for writing + */ +static inline void __down_write(struct rw_semaphore *sem) +{ + int tmp; + + tmp = atomic_add_return(RWSEM_ACTIVE_WRITE_BIAS, + (atomic_t *)(&sem->count)); + if (tmp != RWSEM_ACTIVE_WRITE_BIAS) + rwsem_down_write_failed(sem); +} + +static inline int __down_write_trylock(struct rw_semaphore *sem) +{ + int tmp; + + tmp = cmpxchg(&sem->count, RWSEM_UNLOCKED_VALUE, + RWSEM_ACTIVE_WRITE_BIAS); + return tmp == RWSEM_UNLOCKED_VALUE; +} + +/* + * unlock after reading + */ +static inline void __up_read(struct rw_semaphore *sem) +{ + int tmp; + + tmp = atomic_dec_return((atomic_t *)(&sem->count)); + if (tmp < -1 && (tmp & RWSEM_ACTIVE_MASK) == 0) + rwsem_wake(sem); +} + +/* + * unlock after writing + */ +static inline void __up_write(struct rw_semaphore *sem) +{ + if (atomic_sub_return(RWSEM_ACTIVE_WRITE_BIAS, + (atomic_t *)(&sem->count)) < 0) + rwsem_wake(sem); +} + +/* + * implement atomic add functionality + */ +static inline void rwsem_atomic_add(int delta, struct rw_semaphore *sem) +{ + atomic_add(delta, (atomic_t *)(&sem->count)); +} + +/* + * downgrade write lock to read lock + */ +static inline void __downgrade_write(struct rw_semaphore *sem) +{ + int tmp; + + tmp = atomic_add_return(-RWSEM_WAITING_BIAS, (atomic_t *)(&sem->count)); + if (tmp < 0) + rwsem_downgrade_wake(sem); +} + +static inline void __down_write_nested(struct rw_semaphore *sem, int subclass) +{ + __down_write(sem); +} + +/* + * implement exchange and add functionality + */ +static inline int rwsem_atomic_update(int delta, struct rw_semaphore *sem) +{ + return atomic_add_return(delta, (atomic_t *)(&sem->count)); +} + +#endif /* __KERNEL__ */ +#endif /* _ASM_ARM_RWSEM_H */ \ No newline at end of file diff --git a/arch/arm/include/asm/topology.h b/arch/arm/include/asm/topology.h index 58b8b84adcd..8aae906c118 100644 --- a/arch/arm/include/asm/topology.h +++ b/arch/arm/include/asm/topology.h @@ -6,6 +6,7 @@ #include struct cputopo_arm { + int id; int thread_id; int core_id; int socket_id; @@ -27,11 +28,55 @@ void init_cpu_topology(void); void store_cpu_topology(unsigned int cpuid); const struct cpumask *cpu_coregroup_mask(int cpu); +void set_power_scale(unsigned int cpu, unsigned int power); +int topology_register_notifier(struct notifier_block *nb); +int topology_unregister_notifier(struct notifier_block *nb); + #else static inline void init_cpu_topology(void) { } static inline void store_cpu_topology(unsigned int cpuid) { } +static inline void set_power_scale(unsigned int cpu, unsigned int power) { } +static inline int topology_register_notifier(struct notifier_block *nb) { } +static inline int topology_unregister_notifier(struct notifier_block *nb) { } + +#endif + +/* Topology notifier event */ +#define TOPOLOGY_POSTCHANGE 0 + +/* Common values for CPUs */ +#ifndef SD_CPU_INIT +#define SD_CPU_INIT (struct sched_domain) { \ + .min_interval = 1, \ + .max_interval = 4, \ + .busy_factor = 64, \ + .imbalance_pct = 125, \ + .cache_nice_tries = 1, \ + .busy_idx = 2, \ + .idle_idx = 1, \ + .newidle_idx = 0, \ + .wake_idx = 0, \ + .forkexec_idx = 0, \ + \ + .flags = 1*SD_LOAD_BALANCE \ + | 1*SD_BALANCE_NEWIDLE \ + | 1*SD_BALANCE_EXEC \ + | 1*SD_BALANCE_FORK \ + | 0*SD_BALANCE_WAKE \ + | 1*SD_WAKE_AFFINE \ + | 0*SD_PREFER_LOCAL \ + | 0*SD_SHARE_CPUPOWER \ + | 0*SD_SHARE_PKG_RESOURCES \ + | 0*SD_SERIALIZE \ + | arch_sd_sibling_asym_packing() \ + | sd_balance_for_package_power() \ + | sd_power_saving_flags() \ + , \ + .last_balance = jiffies, \ + .balance_interval = 1, \ +} #endif #include diff --git a/arch/arm/kernel/arch_timer.c b/arch/arm/kernel/arch_timer.c index 2455d1f6567..aae0e493073 100644 --- a/arch/arm/kernel/arch_timer.c +++ b/arch/arm/kernel/arch_timer.c @@ -221,7 +221,7 @@ static int arch_timer_set_next_event(unsigned long evt, return 0; } -static int __cpuinit arch_timer_setup(struct clock_event_device *clk) +static int arch_timer_setup(struct clock_event_device *clk) { /* setup clock event only once for CPU 0 */ if (!smp_processor_id() && clk->irq == arch_timer_ppi) @@ -366,7 +366,7 @@ static u32 notrace arch_timer_update_sched_clock(void) return arch_counter_get_cntvct32(); } -static void __cpuinit arch_timer_stop(struct clock_event_device *clk) +static void arch_timer_stop(struct clock_event_device *clk) { pr_debug("arch_timer_teardown disable IRQ%d cpu #%d\n", clk->irq, smp_processor_id()); @@ -376,7 +376,7 @@ static void __cpuinit arch_timer_stop(struct clock_event_device *clk) arch_timer_set_mode(CLOCK_EVT_MODE_UNUSED, clk); } -static struct local_timer_ops arch_timer_ops __cpuinitdata = { +static struct local_timer_ops arch_timer_ops = { .setup = arch_timer_setup, .stop = arch_timer_stop, }; diff --git a/arch/arm/kernel/atags.c b/arch/arm/kernel/atags.c index 42a1a1415fa..0cfd7e48038 100644 --- a/arch/arm/kernel/atags.c +++ b/arch/arm/kernel/atags.c @@ -4,29 +4,45 @@ #include #include +/* + * [PATCH] Backport arch/arm/kernel/atags.c from 3.10 + * + * There is a bug in older kernels, causing kexec-tools binary to + * only read first 1024 bytes from /proc/atags. I guess the bug is + * somewhere in /fs/proc/, since I don't think the callback in atags.c + * does something wrong. It might affect all procfs files using that + * old read callback instead of fops. Doesn't matter though, since it + * was accidentally fixed when 3.10 removed it. + * + * This might have no particular effect on real devices, because the + * atags _might_ be organized "just right", but it might be very hard + * to track down on a device where it causes problems. + * + */ + struct buffer { size_t size; char data[]; }; -static int -read_buffer(char* page, char** start, off_t off, int count, - int* eof, void* data) -{ - struct buffer *buffer = (struct buffer *)data; - - if (off >= buffer->size) { - *eof = 1; - return 0; - } - - count = min((int) (buffer->size - off), count); +static struct buffer* atags_buffer = NULL; - memcpy(page, &buffer->data[off], count); - - return count; +static ssize_t atags_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + // These are introduced in kernel 3.10. I don't want to backport + // the whole chunk, and other things (ram_console) use static + // variable to keep data too, so I guess it's okay. + //struct buffer *b = PDE_DATA(file_inode(file)); + struct buffer *b = atags_buffer; + return simple_read_from_buffer(buf, count, ppos, b->data, b->size); } +static const struct file_operations atags_fops = { + .read = atags_read, + .llseek = default_llseek, +}; + #define BOOT_PARAMS_SIZE 1536 static char __initdata atags_copy[BOOT_PARAMS_SIZE]; @@ -66,12 +82,13 @@ static int __init init_atags_procfs(void) b->size = size; memcpy(b->data, atags_copy, size); - tags_entry = create_proc_read_entry("atags", 0400, - NULL, read_buffer, b); + tags_entry = proc_create_data("atags", 0400, NULL, &atags_fops, b); if (!tags_entry) goto nomem; + atags_buffer = b; + return 0; nomem: diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c index 8fa8b2063ab..21920cebf83 100644 --- a/arch/arm/kernel/hw_breakpoint.c +++ b/arch/arm/kernel/hw_breakpoint.c @@ -962,7 +962,7 @@ static void reset_ctrl_regs(void *unused) } } -static int __cpuinit dbg_reset_notify(struct notifier_block *self, +static int dbg_reset_notify(struct notifier_block *self, unsigned long action, void *cpu) { if (action == CPU_ONLINE) @@ -971,7 +971,7 @@ static int __cpuinit dbg_reset_notify(struct notifier_block *self, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata dbg_reset_nb = { +static struct notifier_block dbg_reset_nb = { .notifier_call = dbg_reset_notify, }; diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c index c355aebdf2d..449394d81fb 100644 --- a/arch/arm/kernel/machine_kexec.c +++ b/arch/arm/kernel/machine_kexec.c @@ -14,6 +14,7 @@ #include #include #include +#include extern const unsigned char relocate_new_kernel[]; extern const unsigned int relocate_new_kernel_size; @@ -22,6 +23,10 @@ extern unsigned long kexec_start_address; extern unsigned long kexec_indirection_page; extern unsigned long kexec_mach_type; extern unsigned long kexec_boot_atags; +#ifdef CONFIG_KEXEC_HARDBOOT +extern unsigned long kexec_hardboot; +void (*kexec_hardboot_hook)(void); +#endif static atomic_t waiting_for_crash_ipi; @@ -120,10 +125,13 @@ void machine_kexec(struct kimage *image) reboot_code_buffer = page_address(image->control_code_page); /* Prepare parameters for reboot_code_buffer*/ - kexec_start_address = image->start; - kexec_indirection_page = page_list; - kexec_mach_type = machine_arch_type; - kexec_boot_atags = image->start - KEXEC_ARM_ZIMAGE_OFFSET + KEXEC_ARM_ATAGS_OFFSET; + mem_text_write_kernel_word(&kexec_start_address, image->start); + mem_text_write_kernel_word(&kexec_indirection_page, page_list); + mem_text_write_kernel_word(&kexec_mach_type, machine_arch_type); + mem_text_write_kernel_word(&kexec_boot_atags, image->start - KEXEC_ARM_ZIMAGE_OFFSET + KEXEC_ARM_ATAGS_OFFSET); +#ifdef CONFIG_KEXEC_HARDBOOT + mem_text_write_kernel_word(&kexec_hardboot, image->hardboot); +#endif /* copy our kernel relocation code to the control code page */ memcpy(reboot_code_buffer, @@ -137,5 +145,11 @@ void machine_kexec(struct kimage *image) if (kexec_reinit) kexec_reinit(); +#ifdef CONFIG_KEXEC_HARDBOOT + /* Run any final machine-specific shutdown code. */ + if (image->hardboot && kexec_hardboot_hook) + kexec_hardboot_hook(); +#endif + soft_restart(reboot_code_buffer_phys); } diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c index 8fb93d07de0..52aae9bd2fe 100644 --- a/arch/arm/kernel/perf_event.c +++ b/arch/arm/kernel/perf_event.c @@ -775,7 +775,7 @@ void disable_irq_callback(void *info) * UNKNOWN at reset, the PMU must be explicitly reset to avoid reading * junk values out of them. */ -static int __cpuinit pmu_cpu_notify(struct notifier_block *b, +static int pmu_cpu_notify(struct notifier_block *b, unsigned long action, void *hcpu) { int irq; @@ -845,7 +845,7 @@ static void armpmu_update_counters(void) } } -static struct notifier_block __cpuinitdata pmu_cpu_notifier = { +static struct notifier_block pmu_cpu_notifier = { .notifier_call = pmu_cpu_notify, }; diff --git a/arch/arm/kernel/relocate_kernel.S b/arch/arm/kernel/relocate_kernel.S index d0cdedf4864..f5342939d95 100644 --- a/arch/arm/kernel/relocate_kernel.S +++ b/arch/arm/kernel/relocate_kernel.S @@ -4,6 +4,15 @@ #include +#ifdef CONFIG_KEXEC_HARDBOOT +#include +#if defined(CONFIG_ARCH_TEGRA_2x_SOC) || defined(CONFIG_ARCH_TEGRA_3x_SOC) + #include +#elif defined(CONFIG_ARCH_APQ8064) + #include +#endif +#endif + .globl relocate_new_kernel relocate_new_kernel: @@ -52,6 +61,12 @@ relocate_new_kernel: b 0b 2: +#ifdef CONFIG_KEXEC_HARDBOOT + ldr r0, kexec_hardboot + teq r0, #0 + bne hardboot +#endif + /* Jump to relocated kernel */ mov lr,r1 mov r0,#0 @@ -60,6 +75,40 @@ relocate_new_kernel: ARM( mov pc, lr ) THUMB( bx lr ) +#ifdef CONFIG_KEXEC_HARDBOOT +hardboot: + /* Stash boot arguments in hardboot page: + * 0: KEXEC_HB_PAGE_MAGIC + * 4: kexec_start_address + * 8: kexec_mach_type + * 12: kexec_boot_atags */ + ldr r0, =KEXEC_HB_PAGE_ADDR + str r1, [r0, #4] + ldr r1, kexec_mach_type + str r1, [r0, #8] + ldr r1, kexec_boot_atags + str r1, [r0, #12] + ldr r1, =KEXEC_HB_PAGE_MAGIC + str r1, [r0] + +#if defined(CONFIG_ARCH_TEGRA_2x_SOC) || defined(CONFIG_ARCH_TEGRA_3x_SOC) + ldr r0, =TEGRA_PMC_BASE + ldr r1, [r0] + orr r1, r1, #0x10 + str r1, [r0] +loop: b loop +#elif defined(CONFIG_ARCH_APQ8064) + /* Restart using the PMIC chip, see mach-msm/restart.c */ + ldr r0, =APQ8064_TLMM_PHYS + mov r1, #0 + str r1, [r0, #0x820] @ PSHOLD_CTL_SU +loop: b loop +#else +#error "No reboot method defined for hardboot." +#endif + + .ltorg +#endif .align .globl kexec_start_address @@ -79,6 +128,12 @@ kexec_mach_type: kexec_boot_atags: .long 0x0 +#ifdef CONFIG_KEXEC_HARDBOOT + .globl kexec_hardboot +kexec_hardboot: + .long 0x0 +#endif + relocate_new_kernel_end: .globl relocate_new_kernel_size diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index e46fd92b451..f99d85d3921 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -32,6 +32,7 @@ #include #include #include + #include #include #include @@ -62,7 +63,7 @@ enum ipi_msg_type { static DECLARE_COMPLETION(cpu_running); -int __cpuinit __cpu_up(unsigned int cpu) +int __cpu_up(unsigned int cpu) { struct cpuinfo_arm *ci = &per_cpu(cpu_data, cpu); struct task_struct *idle = ci->idle; @@ -233,7 +234,7 @@ void __ref cpu_die(void) * Called by both boot and secondaries to move global data into * per-processor storage. */ -static void __cpuinit smp_store_cpu_info(unsigned int cpuid) +static void smp_store_cpu_info(unsigned int cpuid) { struct cpuinfo_arm *cpu_info = &per_cpu(cpu_data, cpuid); @@ -246,7 +247,7 @@ static void __cpuinit smp_store_cpu_info(unsigned int cpuid) * This is the secondary CPU boot entry. We're using this CPUs * idle thread stack, but a set of temporary page tables. */ -asmlinkage void __cpuinit secondary_start_kernel(void) +asmlinkage void secondary_start_kernel(void) { struct mm_struct *mm = &init_mm; unsigned int cpu = smp_processor_id(); @@ -438,7 +439,7 @@ static void broadcast_timer_set_mode(enum clock_event_mode mode, { } -static void __cpuinit broadcast_timer_setup(struct clock_event_device *evt) +static void broadcast_timer_setup(struct clock_event_device *evt) { evt->name = "dummy_timer"; evt->features = CLOCK_EVT_FEAT_ONESHOT | @@ -464,7 +465,7 @@ int local_timer_register(struct local_timer_ops *ops) } #endif -void __cpuinit percpu_timer_setup(void) +void percpu_timer_setup(void) { unsigned int cpu = smp_processor_id(); struct clock_event_device *evt = &per_cpu(percpu_clockevent, cpu); diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c index fef42b21cec..7c3a4449c9a 100644 --- a/arch/arm/kernel/smp_twd.c +++ b/arch/arm/kernel/smp_twd.c @@ -142,7 +142,7 @@ core_initcall(twd_cpufreq_init); #endif -static void __cpuinit twd_calibrate_rate(void) +static void twd_calibrate_rate(void) { unsigned long count; u64 waitjiffies; @@ -225,7 +225,7 @@ static struct clk *twd_get_clock(void) /* * Setup the local clock events for a CPU. */ -static int __cpuinit twd_timer_setup(struct clock_event_device *clk) +static int twd_timer_setup(struct clock_event_device *clk) { struct clock_event_device **this_cpu_clk; @@ -257,7 +257,7 @@ static int __cpuinit twd_timer_setup(struct clock_event_device *clk) return 0; } -static struct local_timer_ops twd_lt_ops __cpuinitdata = { +static struct local_timer_ops twd_lt_ops = { .setup = twd_timer_setup, .stop = twd_timer_stop, }; diff --git a/arch/arm/kernel/topology.c b/arch/arm/kernel/topology.c index 8200deaa14f..ab85d949393 100644 --- a/arch/arm/kernel/topology.c +++ b/arch/arm/kernel/topology.c @@ -18,10 +18,20 @@ #include #include #include +#include +#include +#include + +#ifdef CONFIG_DEBUG_FS +#include +#include /* for copy_from_user */ +#endif #include #include +#define ARM_FAMILY_MASK 0xFF0FFFF0 + #define MPIDR_SMP_BITMASK (0x3 << 30) #define MPIDR_SMP_VALUE (0x2 << 30) @@ -43,11 +53,202 @@ struct cputopo_arm cpu_topology[NR_CPUS]; + +/* + * cpu power scale management + * a per cpu data structure should be better because each cpu is mainly + * using its own cpu_power even it's not always true because of + * nohz_idle_balance + */ + +static DEFINE_PER_CPU(unsigned int, cpu_scale); + +/* + * cpu topology mask update management + */ + +static unsigned int prev_sched_mc_power_savings = 0; +static unsigned int prev_sched_smt_power_savings = 0; + +ATOMIC_NOTIFIER_HEAD(topology_update_notifier_list); + +/* + * Update the cpu power of the scheduler + */ +unsigned long arch_scale_freq_power(struct sched_domain *sd, int cpu) +{ + return per_cpu(cpu_scale, cpu); +} + +void set_power_scale(unsigned int cpu, unsigned int power) +{ + per_cpu(cpu_scale, cpu) = power; +} + +int topology_register_notifier(struct notifier_block *nb) +{ + + return atomic_notifier_chain_register( + &topology_update_notifier_list, nb); +} + +int topology_unregister_notifier(struct notifier_block *nb) +{ + + return atomic_notifier_chain_unregister( + &topology_update_notifier_list, nb); +} + +/* + * sched_domain flag configuration + */ +/* TODO add a config flag for this function */ +int arch_sd_sibling_asym_packing(void) +{ + if (sched_smt_power_savings || sched_mc_power_savings) + return SD_ASYM_PACKING; + return 0; +} + +/* + * default topology function + */ const struct cpumask *cpu_coregroup_mask(int cpu) { return &cpu_topology[cpu].core_sibling; } +/* + * clear cpu topology masks + */ +static void clear_cpu_topology_mask(void) +{ + unsigned int cpuid; + for_each_possible_cpu(cpuid) { + struct cputopo_arm *cpuid_topo = &(cpu_topology[cpuid]); + cpumask_clear(&cpuid_topo->core_sibling); + cpumask_clear(&cpuid_topo->thread_sibling); + } + smp_wmb(); +} + +/* + * default_cpu_topology_mask set the core and thread mask as described in the + * ARM ARM + */ +static void default_cpu_topology_mask(unsigned int cpuid) +{ + struct cputopo_arm *cpuid_topo = &cpu_topology[cpuid]; + unsigned int cpu; + + for_each_possible_cpu(cpu) { + struct cputopo_arm *cpu_topo = &cpu_topology[cpu]; + + if (cpuid_topo->socket_id == cpu_topo->socket_id) { + cpumask_set_cpu(cpuid, &cpu_topo->core_sibling); + if (cpu != cpuid) + cpumask_set_cpu(cpu, + &cpuid_topo->core_sibling); + + if (cpuid_topo->core_id == cpu_topo->core_id) { + cpumask_set_cpu(cpuid, + &cpu_topo->thread_sibling); + if (cpu != cpuid) + cpumask_set_cpu(cpu, + &cpuid_topo->thread_sibling); + } + } + } + smp_wmb(); +} + +static void normal_cpu_topology_mask(void) +{ + unsigned int cpuid; + + for_each_possible_cpu(cpuid) { + default_cpu_topology_mask(cpuid); + } + smp_wmb(); +} + +/* + * For Cortex-A9 MPcore, we emulate a multi-package topology in power mode. + * The goal is to gathers tasks on 1 virtual package + */ +static void power_cpu_topology_mask_CA9(unsigned int cpuid) +{ + struct cputopo_arm *cpuid_topo = &cpu_topology[cpuid]; + unsigned int cpu; + + for_each_possible_cpu(cpu) { + struct cputopo_arm *cpu_topo = &cpu_topology[cpu]; + + if ((cpuid_topo->socket_id == cpu_topo->socket_id) + && ((cpuid & 0x1) == (cpu & 0x1))) { + cpumask_set_cpu(cpuid, &cpu_topo->core_sibling); + if (cpu != cpuid) + cpumask_set_cpu(cpu, + &cpuid_topo->core_sibling); + + if (cpuid_topo->core_id == cpu_topo->core_id) { + cpumask_set_cpu(cpuid, + &cpu_topo->thread_sibling); + if (cpu != cpuid) + cpumask_set_cpu(cpu, + &cpuid_topo->thread_sibling); + } + } + } + smp_wmb(); +} + +static int need_topology_update(void) +{ + int update; + + update = ((prev_sched_mc_power_savings ^ sched_mc_power_savings) + || (prev_sched_smt_power_savings ^ sched_smt_power_savings)); + + prev_sched_mc_power_savings = sched_mc_power_savings; + prev_sched_smt_power_savings = sched_smt_power_savings; + + return update; +} + +#define ARM_CORTEX_A9_FAMILY 0x410FC090 + +/* update_cpu_topology_policy select a cpu topology policy according to the + * available cores. + * TODO: The current version assumes that all cores are exactly the same which + * might not be true. We need to update it to take into account various + * configuration among which system with different kind of core. + */ +static int update_cpu_topology_mask(void) +{ + unsigned long cpuid; + + if (sched_mc_power_savings == POWERSAVINGS_BALANCE_NONE) { + normal_cpu_topology_mask(); + return 0; + } + + for_each_possible_cpu(cpuid) { + struct cputopo_arm *cpuid_topo = &(cpu_topology[cpuid]); + + switch (cpuid_topo->id) { + case ARM_CORTEX_A9_FAMILY: + power_cpu_topology_mask_CA9(cpuid); + break; + default: + default_cpu_topology_mask(cpuid); + break; + } + } + + return 0; +} + /* * store_cpu_topology is called at boot when only one cpu is running * and with the mutex cpu_hotplug.lock locked, when several cpus have booted, @@ -57,7 +258,6 @@ void store_cpu_topology(unsigned int cpuid) { struct cputopo_arm *cpuid_topo = &cpu_topology[cpuid]; unsigned int mpidr; - unsigned int cpu; /* If the cpu topology has been already set, just return */ if (cpuid_topo->core_id != -1) @@ -88,6 +288,9 @@ void store_cpu_topology(unsigned int cpuid) cpuid_topo->socket_id = (mpidr >> MPIDR_LEVEL1_SHIFT) & MPIDR_LEVEL1_MASK; } + + cpuid_topo->id = read_cpuid_id() & ARM_FAMILY_MASK; + } else { /* * This is an uniprocessor system @@ -99,26 +302,12 @@ void store_cpu_topology(unsigned int cpuid) cpuid_topo->socket_id = -1; } - /* update core and thread sibling masks */ - for_each_possible_cpu(cpu) { - struct cputopo_arm *cpu_topo = &cpu_topology[cpu]; + /* + * The core and thread sibling masks can also be updated during the + * call of arch_update_cpu_topology + */ + default_cpu_topology_mask(cpuid); - if (cpuid_topo->socket_id == cpu_topo->socket_id) { - cpumask_set_cpu(cpuid, &cpu_topo->core_sibling); - if (cpu != cpuid) - cpumask_set_cpu(cpu, - &cpuid_topo->core_sibling); - - if (cpuid_topo->core_id == cpu_topo->core_id) { - cpumask_set_cpu(cpuid, - &cpu_topo->thread_sibling); - if (cpu != cpuid) - cpumask_set_cpu(cpu, - &cpuid_topo->thread_sibling); - } - } - } - smp_wmb(); printk(KERN_INFO "CPU%u: thread %d, cpu %d, socket %d, mpidr %x\n", cpuid, cpu_topology[cpuid].thread_id, @@ -126,6 +315,28 @@ void store_cpu_topology(unsigned int cpuid) cpu_topology[cpuid].socket_id, mpidr); } +/* + * arch_update_cpu_topology is called by the scheduler before building + * a new sched_domain hierarchy. + */ +int arch_update_cpu_topology(void) +{ + if (!need_topology_update()) + return 0; + + /* clear core threads mask */ + clear_cpu_topology_mask(); + + /* set topology mask */ + update_cpu_topology_mask(); + + /* notify the topology update */ + atomic_notifier_call_chain(&topology_update_notifier_list, + TOPOLOGY_POSTCHANGE, (void *)sched_mc_power_savings); + + return 1; +} + /* * init_cpu_topology is called at boot when only one cpu is running * which prevent simultaneous write access to cpu_topology array @@ -138,11 +349,105 @@ void init_cpu_topology(void) for_each_possible_cpu(cpu) { struct cputopo_arm *cpu_topo = &(cpu_topology[cpu]); + cpu_topo->id = -1; cpu_topo->thread_id = -1; cpu_topo->core_id = -1; cpu_topo->socket_id = -1; cpumask_clear(&cpu_topo->core_sibling); cpumask_clear(&cpu_topo->thread_sibling); + + per_cpu(cpu_scale, cpu) = SCHED_POWER_SCALE; } smp_wmb(); } + +/* + * debugfs interface for scaling cpu power + */ + +#ifdef CONFIG_DEBUG_FS +static struct dentry *topo_debugfs_root; + +static ssize_t dbg_write(struct file *file, const char __user *buf, + size_t size, loff_t *off) +{ + unsigned int *value = file->f_dentry->d_inode->i_private; + char cdata[128]; + unsigned long tmp; + + if (size < (sizeof(cdata)-1)) { + if (copy_from_user(cdata, buf, size)) + return -EFAULT; + cdata[size] = 0; + if (!strict_strtoul(cdata, 10, &tmp)) { + *value = tmp; + } + return size; + } + return -EINVAL; +} + +static ssize_t dbg_read(struct file *file, char __user *buf, + size_t size, loff_t *off) +{ + unsigned int *value = file->f_dentry->d_inode->i_private; + char cdata[128]; + unsigned int len; + + len = sprintf(cdata, "%u\n", *value); + return simple_read_from_buffer(buf, size, off, cdata, len); +} + +static const struct file_operations debugfs_fops = { + .read = dbg_read, + .write = dbg_write, +}; + +static struct dentry *topo_debugfs_register(unsigned int cpu, + struct dentry *parent) +{ + struct dentry *cpu_d, *d; + char cpu_name[16]; + + sprintf(cpu_name, "cpu%u", cpu); + + cpu_d = debugfs_create_dir(cpu_name, parent); + if (!cpu_d) + return NULL; + + d = debugfs_create_file("cpu_power", S_IRUGO | S_IWUGO, + cpu_d, &per_cpu(cpu_scale, cpu), &debugfs_fops); + if (!d) + goto err_out; + + return cpu_d; + +err_out: + debugfs_remove_recursive(cpu_d); + return NULL; +} + +static int __init topo_debugfs_init(void) +{ + struct dentry *d; + unsigned int cpu; + + d = debugfs_create_dir("cpu_topo", NULL); + if (!d) + return -ENOMEM; + topo_debugfs_root = d; + + for_each_possible_cpu(cpu) { + d = topo_debugfs_register(cpu, topo_debugfs_root); + if (d == NULL) + goto err_out; + } + return 0; + +err_out: + debugfs_remove_recursive(topo_debugfs_root); + return -ENOMEM; +} + +late_initcall(topo_debugfs_init); +#endif diff --git a/arch/arm/lib/memset.S b/arch/arm/lib/memset.S index 650d5923ab8..d912e7397ec 100644 --- a/arch/arm/lib/memset.S +++ b/arch/arm/lib/memset.S @@ -19,9 +19,9 @@ 1: subs r2, r2, #4 @ 1 do we have enough blt 5f @ 1 bytes to align with? cmp r3, #2 @ 1 - strltb r1, [r0], #1 @ 1 - strleb r1, [r0], #1 @ 1 - strb r1, [r0], #1 @ 1 + strltb r1, [ip], #1 @ 1 + strleb r1, [ip], #1 @ 1 + strb r1, [ip], #1 @ 1 add r2, r2, r3 @ 1 (r2 = r2 - (4 - r3)) /* * The pointer is now aligned and the length is adjusted. Try doing the @@ -29,10 +29,14 @@ */ ENTRY(memset) - ands r3, r0, #3 @ 1 unaligned? +/* + * Preserve the contents of r0 for the return value. + */ + mov ip, r0 + ands r3, ip, #3 @ 1 unaligned? bne 1b @ 1 /* - * we know that the pointer in r0 is aligned to a word boundary. + * we know that the pointer in ip is aligned to a word boundary. */ orr r1, r1, r1, lsl #8 orr r1, r1, r1, lsl #16 @@ -43,29 +47,28 @@ ENTRY(memset) #if ! CALGN(1)+0 /* - * We need an extra register for this loop - save the return address and - * use the LR + * We need 2 extra registers for this loop - use r8 and the LR */ - str lr, [sp, #-4]! - mov ip, r1 + stmfd sp!, {r8, lr} + mov r8, r1 mov lr, r1 2: subs r2, r2, #64 - stmgeia r0!, {r1, r3, ip, lr} @ 64 bytes at a time. - stmgeia r0!, {r1, r3, ip, lr} - stmgeia r0!, {r1, r3, ip, lr} - stmgeia r0!, {r1, r3, ip, lr} + stmgeia ip!, {r1, r3, r8, lr} @ 64 bytes at a time. + stmgeia ip!, {r1, r3, r8, lr} + stmgeia ip!, {r1, r3, r8, lr} + stmgeia ip!, {r1, r3, r8, lr} bgt 2b - ldmeqfd sp!, {pc} @ Now <64 bytes to go. + ldmeqfd sp!, {r8, pc} @ Now <64 bytes to go. /* * No need to correct the count; we're only testing bits from now on */ tst r2, #32 - stmneia r0!, {r1, r3, ip, lr} - stmneia r0!, {r1, r3, ip, lr} + stmneia ip!, {r1, r3, r8, lr} + stmneia ip!, {r1, r3, r8, lr} tst r2, #16 - stmneia r0!, {r1, r3, ip, lr} - ldr lr, [sp], #4 + stmneia ip!, {r1, r3, r8, lr} + ldmfd sp!, {r8, lr} #else @@ -74,54 +77,54 @@ ENTRY(memset) * whole cache lines at once. */ - stmfd sp!, {r4-r7, lr} + stmfd sp!, {r4-r8, lr} mov r4, r1 mov r5, r1 mov r6, r1 mov r7, r1 - mov ip, r1 + mov r8, r1 mov lr, r1 cmp r2, #96 - tstgt r0, #31 + tstgt ip, #31 ble 3f - and ip, r0, #31 - rsb ip, ip, #32 - sub r2, r2, ip - movs ip, ip, lsl #(32 - 4) - stmcsia r0!, {r4, r5, r6, r7} - stmmiia r0!, {r4, r5} - tst ip, #(1 << 30) - mov ip, r1 - strne r1, [r0], #4 + and r8, ip, #31 + rsb r8, r8, #32 + sub r2, r2, r8 + movs r8, r8, lsl #(32 - 4) + stmcsia ip!, {r4, r5, r6, r7} + stmmiia ip!, {r4, r5} + tst r8, #(1 << 30) + mov r8, r1 + strne r1, [ip], #4 3: subs r2, r2, #64 - stmgeia r0!, {r1, r3-r7, ip, lr} - stmgeia r0!, {r1, r3-r7, ip, lr} + stmgeia ip!, {r1, r3-r8, lr} + stmgeia ip!, {r1, r3-r8, lr} bgt 3b - ldmeqfd sp!, {r4-r7, pc} + ldmeqfd sp!, {r4-r8, pc} tst r2, #32 - stmneia r0!, {r1, r3-r7, ip, lr} + stmneia ip!, {r1, r3-r8, lr} tst r2, #16 - stmneia r0!, {r4-r7} - ldmfd sp!, {r4-r7, lr} + stmneia ip!, {r4-r7} + ldmfd sp!, {r4-r8, lr} #endif 4: tst r2, #8 - stmneia r0!, {r1, r3} + stmneia ip!, {r1, r3} tst r2, #4 - strne r1, [r0], #4 + strne r1, [ip], #4 /* * When we get here, we've got less than 4 bytes to zero. We * may have an unaligned pointer as well. */ 5: tst r2, #2 - strneb r1, [r0], #1 - strneb r1, [r0], #1 + strneb r1, [ip], #1 + strneb r1, [ip], #1 tst r2, #1 - strneb r1, [r0], #1 + strneb r1, [ip], #1 mov pc, lr ENDPROC(memset) diff --git a/arch/arm/mach-exynos/mct.c b/arch/arm/mach-exynos/mct.c index 897d9a9cf22..b10e2d96287 100644 --- a/arch/arm/mach-exynos/mct.c +++ b/arch/arm/mach-exynos/mct.c @@ -384,7 +384,7 @@ static struct irqaction mct_tick1_event_irq = { .handler = exynos4_mct_tick_isr, }; -static int __cpuinit exynos4_local_timer_setup(struct clock_event_device *evt) +static int exynos4_local_timer_setup(struct clock_event_device *evt) { struct mct_clock_event_device *mevt; unsigned int cpu = smp_processor_id(); @@ -443,7 +443,7 @@ static void exynos4_local_timer_stop(struct clock_event_device *evt) disable_percpu_irq(EXYNOS_IRQ_MCT_LOCALTIMER); } -static struct local_timer_ops exynos4_mct_tick_ops __cpuinitdata = { +static struct local_timer_ops exynos4_mct_tick_ops = { .setup = exynos4_local_timer_setup, .stop = exynos4_local_timer_stop, }; diff --git a/arch/arm/mach-exynos/platsmp.c b/arch/arm/mach-exynos/platsmp.c index 36c3984aaa4..067d6d9234e 100644 --- a/arch/arm/mach-exynos/platsmp.c +++ b/arch/arm/mach-exynos/platsmp.c @@ -42,7 +42,7 @@ extern void exynos4_secondary_startup(void); * boot "holding pen" */ -volatile int __cpuinitdata pen_release = -1; +volatile int pen_release = -1; /* * Write pen_release in a way that is guaranteed to be visible to all @@ -64,7 +64,7 @@ static void __iomem *scu_base_addr(void) static DEFINE_SPINLOCK(boot_lock); -void __cpuinit platform_secondary_init(unsigned int cpu) +void platform_secondary_init(unsigned int cpu) { /* * if any interrupts are already enabled for the primary @@ -86,7 +86,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu) spin_unlock(&boot_lock); } -int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) +int boot_secondary(unsigned int cpu, struct task_struct *idle) { unsigned long timeout; diff --git a/arch/arm/mach-highbank/platsmp.c b/arch/arm/mach-highbank/platsmp.c index d01364c72b4..ee738d017e4 100644 --- a/arch/arm/mach-highbank/platsmp.c +++ b/arch/arm/mach-highbank/platsmp.c @@ -25,12 +25,12 @@ extern void secondary_startup(void); -void __cpuinit platform_secondary_init(unsigned int cpu) +void platform_secondary_init(unsigned int cpu) { gic_secondary_init(0); } -int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) +int boot_secondary(unsigned int cpu, struct task_struct *idle) { gic_raise_softirq(cpumask_of(cpu), 0); return 0; diff --git a/arch/arm/mach-imx/platsmp.c b/arch/arm/mach-imx/platsmp.c index ab98c6fec9e..41927d6d648 100644 --- a/arch/arm/mach-imx/platsmp.c +++ b/arch/arm/mach-imx/platsmp.c @@ -41,7 +41,7 @@ void __init imx_scu_map_io(void) scu_base = IMX_IO_ADDRESS(base); } -void __cpuinit platform_secondary_init(unsigned int cpu) +void platform_secondary_init(unsigned int cpu) { /* * if any interrupts are already enabled for the primary @@ -51,7 +51,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu) gic_secondary_init(0); } -int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) +int boot_secondary(unsigned int cpu, struct task_struct *idle) { imx_set_cpu_jump(cpu, v7_secondary_startup); imx_enable_cpu(cpu, true); diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig index 10efe055e01..93669196fa5 100644 --- a/arch/arm/mach-msm/Kconfig +++ b/arch/arm/mach-msm/Kconfig @@ -1608,6 +1608,21 @@ config MSM_DALRPC_TEST help Exercises DAL RPC calls to QDSP6. +config MSM_MPDEC + bool "Enable kernel based mpdecision" + depends on MSM_SMP + default n + help + This enables kernel based multi core control. + (up/down hotplug based on load) + +config MSM_MPDEC_INPUTBOOST_CPUMIN + bool "Enable kernel based mpdecision" + depends on MSM_MPDEC + default n + help + This pushes the cpu min speed to predefined values on input events. + if CPU_FREQ_MSM config MSM_CPU_FREQ_SET_MIN_MAX @@ -1620,15 +1635,27 @@ config MSM_CPU_FREQ_SET_MIN_MAX config MSM_CPU_FREQ_MAX int "Max CPU Frequency" depends on MSM_CPU_FREQ_SET_MIN_MAX - default 384000 + default 2322000 config MSM_CPU_FREQ_MIN int "Min CPU Frequency" depends on MSM_CPU_FREQ_SET_MIN_MAX - default 245760 + default 384000 endif # CPU_FREQ_MSM +config INTELLI_PLUG + bool "Enable intelli-plug cpu hotplug driver" + default n + help + Generic Intelli-plug cpu hotplug driver for ARM SOCs + +config CPU_VOLTAGE_TABLE + bool "Enable CPU Voltage Table via sysfs for adjustements" + default n + help + Krait User Votlage Control + config MSM_AVS_HW bool "Enable Adaptive Voltage Scaling (AVS)" default n @@ -2618,4 +2645,11 @@ config MSM_CPU_PWRCTL stand alone power collapse operation. Selecting this option ensures that they are always off. +config FORCE_FAST_CHARGE + bool "Force AC charge mode at will" + default y + help + A simple sysfs interface to force adapters that + are detected as USB to charge as AC. + endif diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile index 63e99f5ddff..2783612867f 100644 --- a/arch/arm/mach-msm/Makefile +++ b/arch/arm/mach-msm/Makefile @@ -6,6 +6,8 @@ obj-y += timer.o endif obj-y += clock.o clock-voter.o clock-dummy.o obj-y += modem_notifier.o subsystem_map.o +obj-$(CONFIG_MSM_MPDEC) += msm_mpdecision.o +obj-$(CONFIG_INTELLI_PLUG) += intelli_plug.o obj-$(CONFIG_CPU_FREQ_MSM) += cpufreq.o obj-$(CONFIG_DEBUG_FS) += nohlt.o clock-debug.o obj-$(CONFIG_KEXEC) += msm_kexec.o @@ -388,6 +390,7 @@ obj-$(CONFIG_MSM_HSIC_SYSMON_TEST) += hsic_sysmon_test.o obj-$(CONFIG_MSM_RPM_SMD) += rpm-smd.o obj-$(CONFIG_MSM_CPR) += msm_cpr.o obj-$(CONFIG_MSM_VP_REGULATOR) += msm_vp.o +obj-$(CONFIG_FORCE_FAST_CHARGE) += fastchg.o ifdef CONFIG_MSM_CPR obj-$(CONFIG_DEBUG_FS) += msm_cpr-debug.o diff --git a/arch/arm/mach-msm/acpuclock-8064.c b/arch/arm/mach-msm/acpuclock-8064.c index 0fe1793d5df..60880dc8167 100644 --- a/arch/arm/mach-msm/acpuclock-8064.c +++ b/arch/arm/mach-msm/acpuclock-8064.c @@ -21,6 +21,9 @@ #include "mach/socinfo.h" #include "acpuclock.h" #include "acpuclock-krait.h" +#include "vdd_limits_8064.h" + +int opt_bin = 1; static struct hfpll_data hfpll_data __initdata = { .mode_offset = 0x00, @@ -37,7 +40,7 @@ static struct hfpll_data hfpll_data __initdata = { .vdd[HFPLL_VDD_NONE] = 0, .vdd[HFPLL_VDD_LOW] = 945000, .vdd[HFPLL_VDD_NOM] = 1050000, - .vdd[HFPLL_VDD_HIGH] = 1150000, + .vdd[HFPLL_VDD_HIGH] = MEM_DIG_MAX_VDD, }; static struct scalable scalable[] __initdata = { @@ -47,9 +50,9 @@ static struct scalable scalable[] __initdata = { .aux_clk_sel = 3, .sec_clk_sel = 2, .l2cpmr_iaddr = 0x4501, - .vreg[VREG_CORE] = { "krait0", 1300000 }, - .vreg[VREG_MEM] = { "krait0_mem", 1150000 }, - .vreg[VREG_DIG] = { "krait0_dig", 1150000 }, + .vreg[VREG_CORE] = { "krait0", SC_MAX_VDD }, + .vreg[VREG_MEM] = { "krait0_mem", MEM_DIG_MAX_VDD }, + .vreg[VREG_DIG] = { "krait0_dig", MEM_DIG_MAX_VDD }, .vreg[VREG_HFPLL_A] = { "krait0_hfpll", 1800000 }, }, [CPU1] = { @@ -58,9 +61,9 @@ static struct scalable scalable[] __initdata = { .aux_clk_sel = 3, .sec_clk_sel = 2, .l2cpmr_iaddr = 0x5501, - .vreg[VREG_CORE] = { "krait1", 1300000 }, - .vreg[VREG_MEM] = { "krait1_mem", 1150000 }, - .vreg[VREG_DIG] = { "krait1_dig", 1150000 }, + .vreg[VREG_CORE] = { "krait1", SC_MAX_VDD }, + .vreg[VREG_MEM] = { "krait1_mem", MEM_DIG_MAX_VDD }, + .vreg[VREG_DIG] = { "krait1_dig", MEM_DIG_MAX_VDD }, .vreg[VREG_HFPLL_A] = { "krait1_hfpll", 1800000 }, }, [CPU2] = { @@ -69,9 +72,9 @@ static struct scalable scalable[] __initdata = { .aux_clk_sel = 3, .sec_clk_sel = 2, .l2cpmr_iaddr = 0x6501, - .vreg[VREG_CORE] = { "krait2", 1300000 }, - .vreg[VREG_MEM] = { "krait2_mem", 1150000 }, - .vreg[VREG_DIG] = { "krait2_dig", 1150000 }, + .vreg[VREG_CORE] = { "krait2", SC_MAX_VDD }, + .vreg[VREG_MEM] = { "krait2_mem", MEM_DIG_MAX_VDD }, + .vreg[VREG_DIG] = { "krait2_dig", MEM_DIG_MAX_VDD }, .vreg[VREG_HFPLL_A] = { "krait2_hfpll", 1800000 }, }, [CPU3] = { @@ -80,9 +83,9 @@ static struct scalable scalable[] __initdata = { .aux_clk_sel = 3, .sec_clk_sel = 2, .l2cpmr_iaddr = 0x7501, - .vreg[VREG_CORE] = { "krait3", 1300000 }, - .vreg[VREG_MEM] = { "krait3_mem", 1150000 }, - .vreg[VREG_DIG] = { "krait3_dig", 1150000 }, + .vreg[VREG_CORE] = { "krait3", SC_MAX_VDD }, + .vreg[VREG_MEM] = { "krait3_mem", MEM_DIG_MAX_VDD }, + .vreg[VREG_DIG] = { "krait3_dig", MEM_DIG_MAX_VDD }, .vreg[VREG_HFPLL_A] = { "krait3_hfpll", 1800000 }, }, [L2] = { @@ -106,6 +109,9 @@ static struct msm_bus_paths bw_level_tbl[] __initdata = { [3] = BW_MBPS(2128), /* At least 266 MHz on bus. */ [4] = BW_MBPS(3200), /* At least 400 MHz on bus. */ [5] = BW_MBPS(4264), /* At least 533 MHz on bus. */ + [6] = BW_MBPS(4660), /* At least 583 MHz on bus. */ + [7] = BW_MBPS(4800), /* At least 600 MHz on bus. */ + [8] = BW_MBPS(4960), /* At least 620 MHz on bus. */ }; static struct msm_bus_scale_pdata bus_scale_data __initdata = { @@ -134,6 +140,101 @@ static struct l2_level l2_freq_tbl[] __initdata = { { } }; +static struct l2_level l2_freq_tbl_oc1[] __initdata = { + [0] = { { 384000, PLL_8, 0, 0x00 }, 950000, 1050000, 1 }, + [1] = { { 432000, HFPLL, 2, 0x20 }, 1050000, 1050000, 2 }, + [2] = { { 486000, HFPLL, 2, 0x24 }, 1050000, 1050000, 2 }, + [3] = { { 540000, HFPLL, 2, 0x28 }, 1050000, 1050000, 2 }, + [4] = { { 594000, HFPLL, 1, 0x16 }, 1050000, 1050000, 2 }, + [5] = { { 648000, HFPLL, 1, 0x18 }, 1050000, 1050000, 4 }, + [6] = { { 702000, HFPLL, 1, 0x1A }, 1150000, 1150000, 4 }, + [7] = { { 756000, HFPLL, 1, 0x1C }, 1150000, 1150000, 4 }, + [8] = { { 810000, HFPLL, 1, 0x1E }, 1150000, 1150000, 4 }, + [9] = { { 864000, HFPLL, 1, 0x20 }, 1150000, 1150000, 4 }, + [10] = { { 918000, HFPLL, 1, 0x22 }, 1150000, 1150000, 5 }, + [11] = { { 972000, HFPLL, 1, 0x24 }, 1150000, 1150000, 5 }, + [12] = { { 1026000, HFPLL, 1, 0x26 }, 1150000, 1150000, 5 }, + [13] = { { 1080000, HFPLL, 1, 0x28 }, 1150000, 1150000, 5 }, + [14] = { { 1188000, HFPLL, 1, 0x2C }, 1150000, 1150000, 5 }, + { } +}; + +static struct l2_level l2_freq_tbl_oc2[] __initdata = { + [0] = { { 384000, PLL_8, 0, 0x00 }, 950000, 1050000, 1 }, + [1] = { { 432000, HFPLL, 2, 0x20 }, 1050000, 1050000, 2 }, + [2] = { { 486000, HFPLL, 2, 0x24 }, 1050000, 1050000, 2 }, + [3] = { { 540000, HFPLL, 2, 0x28 }, 1050000, 1050000, 2 }, + [4] = { { 594000, HFPLL, 1, 0x16 }, 1050000, 1050000, 2 }, + [5] = { { 648000, HFPLL, 1, 0x18 }, 1050000, 1050000, 4 }, + [6] = { { 702000, HFPLL, 1, 0x1A }, 1150000, 1150000, 4 }, + [7] = { { 756000, HFPLL, 1, 0x1C }, 1150000, 1150000, 4 }, + [8] = { { 810000, HFPLL, 1, 0x1E }, 1150000, 1150000, 4 }, + [9] = { { 864000, HFPLL, 1, 0x20 }, 1150000, 1150000, 4 }, + [10] = { { 918000, HFPLL, 1, 0x22 }, 1150000, 1150000, 6 }, + [11] = { { 972000, HFPLL, 1, 0x24 }, 1150000, 1150000, 6 }, + [12] = { { 1026000, HFPLL, 1, 0x26 }, 1150000, 1150000, 6 }, + [13] = { { 1080000, HFPLL, 1, 0x28 }, 1150000, 1150000, 6 }, + [14] = { { 1215000, HFPLL, 1, 0x2D }, 1175000, 1175000, 6 }, + { } +}; + +static struct l2_level l2_freq_tbl_oc3[] __initdata = { + [0] = { { 384000, PLL_8, 0, 0x00 }, 950000, 1050000, 1 }, + [1] = { { 432000, HFPLL, 2, 0x20 }, 1050000, 1050000, 2 }, + [2] = { { 486000, HFPLL, 2, 0x24 }, 1050000, 1050000, 2 }, + [3] = { { 540000, HFPLL, 2, 0x28 }, 1050000, 1050000, 2 }, + [4] = { { 594000, HFPLL, 1, 0x16 }, 1050000, 1050000, 2 }, + [5] = { { 648000, HFPLL, 1, 0x18 }, 1050000, 1050000, 4 }, + [6] = { { 702000, HFPLL, 1, 0x1A }, 1150000, 1150000, 4 }, + [7] = { { 756000, HFPLL, 1, 0x1C }, 1150000, 1150000, 4 }, + [8] = { { 810000, HFPLL, 1, 0x1E }, 1150000, 1150000, 4 }, + [9] = { { 864000, HFPLL, 1, 0x20 }, 1150000, 1150000, 4 }, + [10] = { { 918000, HFPLL, 1, 0x22 }, 1150000, 1150000, 6 }, + [11] = { { 972000, HFPLL, 1, 0x24 }, 1150000, 1150000, 6 }, + [12] = { { 1026000, HFPLL, 1, 0x26 }, 1150000, 1150000, 6 }, + [13] = { { 1134000, HFPLL, 1, 0x2A }, 1150000, 1150000, 6 }, + [14] = { { 1350000, HFPLL, 1, 0x32 }, 1200000, 1200000, 6 }, + { } +}; + +static struct l2_level l2_freq_tbl_oc4[] __initdata = { + [0] = { { 384000, PLL_8, 0, 0x00 }, 950000, 1050000, 1 }, + [1] = { { 432000, HFPLL, 2, 0x20 }, 1050000, 1050000, 2 }, + [2] = { { 486000, HFPLL, 2, 0x24 }, 1050000, 1050000, 2 }, + [3] = { { 540000, HFPLL, 2, 0x28 }, 1050000, 1050000, 2 }, + [4] = { { 594000, HFPLL, 1, 0x16 }, 1050000, 1050000, 2 }, + [5] = { { 648000, HFPLL, 1, 0x18 }, 1050000, 1050000, 4 }, + [6] = { { 702000, HFPLL, 1, 0x1A }, 1150000, 1150000, 4 }, + [7] = { { 756000, HFPLL, 1, 0x1C }, 1150000, 1150000, 4 }, + [8] = { { 810000, HFPLL, 1, 0x1E }, 1150000, 1150000, 4 }, + [9] = { { 864000, HFPLL, 1, 0x20 }, 1150000, 1150000, 4 }, + [10] = { { 918000, HFPLL, 1, 0x22 }, 1150000, 1150000, 7 }, + [11] = { { 972000, HFPLL, 1, 0x24 }, 1150000, 1150000, 7 }, + [12] = { { 1026000, HFPLL, 1, 0x26 }, 1150000, 1150000, 7 }, + [13] = { { 1188000, HFPLL, 1, 0x2C }, 1175000, 1175000, 7 }, + [14] = { { 1431000, HFPLL, 1, 0x35 }, 1225000, 1225000, 7 }, + { } +}; + +static struct l2_level l2_freq_tbl_oc5[] __initdata = { + [0] = { { 384000, PLL_8, 0, 0x00 }, 950000, 1050000, 1 }, + [1] = { { 432000, HFPLL, 2, 0x20 }, 1050000, 1050000, 2 }, + [2] = { { 486000, HFPLL, 2, 0x24 }, 1050000, 1050000, 2 }, + [3] = { { 540000, HFPLL, 2, 0x28 }, 1050000, 1050000, 2 }, + [4] = { { 594000, HFPLL, 1, 0x16 }, 1050000, 1050000, 2 }, + [5] = { { 648000, HFPLL, 1, 0x18 }, 1050000, 1050000, 4 }, + [6] = { { 702000, HFPLL, 1, 0x1A }, 1150000, 1150000, 4 }, + [7] = { { 756000, HFPLL, 1, 0x1C }, 1150000, 1150000, 4 }, + [8] = { { 810000, HFPLL, 1, 0x1E }, 1150000, 1150000, 4 }, + [9] = { { 864000, HFPLL, 1, 0x20 }, 1150000, 1150000, 4 }, + [10] = { { 918000, HFPLL, 1, 0x22 }, 1150000, 1150000, 7 }, + [11] = { { 972000, HFPLL, 1, 0x24 }, 1150000, 1150000, 7 }, + [12] = { { 1026000, HFPLL, 1, 0x26 }, 1150000, 1150000, 7 }, + [13] = { { 1215000, HFPLL, 1, 0x2D }, 1175000, 1175000, 7 }, + [14] = { { 1485000, HFPLL, 1, 0x37 }, MEM_DIG_MAX_VDD, MEM_DIG_MAX_VDD, 8 }, + { } +}; + static struct acpu_level tbl_slow[] __initdata = { { 1, { 384000, PLL_8, 0, 0x00 }, L2(0), 950000 }, { 0, { 432000, HFPLL, 2, 0x20 }, L2(5), 975000 }, @@ -246,11 +347,23 @@ static struct acpu_level tbl_PVS0_1512MHz[] __initdata = { { 1, { 810000, HFPLL, 1, 0x1E }, L2(5), 1000000 }, { 1, { 918000, HFPLL, 1, 0x22 }, L2(5), 1025000 }, { 1, { 1026000, HFPLL, 1, 0x26 }, L2(5), 1037500 }, - { 1, { 1134000, HFPLL, 1, 0x2A }, L2(14), 1075000 }, - { 1, { 1242000, HFPLL, 1, 0x2E }, L2(14), 1087500 }, - { 1, { 1350000, HFPLL, 1, 0x32 }, L2(14), 1125000 }, - { 1, { 1458000, HFPLL, 1, 0x36 }, L2(14), 1150000 }, + { 1, { 1134000, HFPLL, 1, 0x2A }, L2(13), 1075000 }, + { 1, { 1242000, HFPLL, 1, 0x2E }, L2(13), 1087500 }, + { 1, { 1350000, HFPLL, 1, 0x32 }, L2(13), 1125000 }, + { 1, { 1458000, HFPLL, 1, 0x36 }, L2(13), 1150000 }, { 1, { 1512000, HFPLL, 1, 0x38 }, L2(14), 1162500 }, + { 1, { 1620000, HFPLL, 1, 0x3C }, L2(14), 1187500 }, + { 1, { 1728000, HFPLL, 1, 0x40 }, L2(14), 1212500 }, + { 1, { 1836000, HFPLL, 1, 0x44 }, L2(14), 1237500 }, + { 1, { 1890000, HFPLL, 1, 0x46 }, L2(14), 1250000 }, + { 1, { 1944000, HFPLL, 1, 0x48 }, L2(14), 1275000 }, + { 1, { 1998000, HFPLL, 1, 0x4A }, L2(14), 1300000 }, + { 1, { 2052000, HFPLL, 1, 0x4C }, L2(14), 1312500 }, + { 1, { 2106000, HFPLL, 1, 0x4E }, L2(14), 1325000 }, + { 1, { 2160000, HFPLL, 1, 0x4F }, L2(14), 1337500 }, + { 1, { 2214000, HFPLL, 1, 0x50 }, L2(14), 1350000 }, + { 1, { 2268000, HFPLL, 1, 0x52 }, L2(14), 1375000 }, + { 1, { 2322000, HFPLL, 1, 0x54 }, L2(14), 1400000 }, { 0, { 0 } } }; @@ -262,11 +375,23 @@ static struct acpu_level tbl_PVS1_1512MHz[] __initdata = { { 1, { 810000, HFPLL, 1, 0x1E }, L2(5), 975000 }, { 1, { 918000, HFPLL, 1, 0x22 }, L2(5), 1000000 }, { 1, { 1026000, HFPLL, 1, 0x26 }, L2(5), 1012500 }, - { 1, { 1134000, HFPLL, 1, 0x2A }, L2(14), 1037500 }, - { 1, { 1242000, HFPLL, 1, 0x2E }, L2(14), 1050000 }, - { 1, { 1350000, HFPLL, 1, 0x32 }, L2(14), 1087500 }, - { 1, { 1458000, HFPLL, 1, 0x36 }, L2(14), 1112500 }, + { 1, { 1134000, HFPLL, 1, 0x2A }, L2(13), 1037500 }, + { 1, { 1242000, HFPLL, 1, 0x2E }, L2(13), 1050000 }, + { 1, { 1350000, HFPLL, 1, 0x32 }, L2(13), 1087500 }, + { 1, { 1458000, HFPLL, 1, 0x36 }, L2(13), 1112500 }, { 1, { 1512000, HFPLL, 1, 0x38 }, L2(14), 1125000 }, + { 1, { 1620000, HFPLL, 1, 0x3C }, L2(14), 1150000 }, + { 1, { 1728000, HFPLL, 1, 0x40 }, L2(14), 1175000 }, + { 1, { 1836000, HFPLL, 1, 0x44 }, L2(14), 1200000 }, + { 1, { 1890000, HFPLL, 1, 0x46 }, L2(14), 1212500 }, + { 1, { 1944000, HFPLL, 1, 0x48 }, L2(14), 1225000 }, + { 1, { 1998000, HFPLL, 1, 0x4A }, L2(14), 1250000 }, + { 1, { 2052000, HFPLL, 1, 0x4C }, L2(14), 1275000 }, + { 1, { 2106000, HFPLL, 1, 0x4E }, L2(14), 1300000 }, + { 1, { 2160000, HFPLL, 1, 0x4F }, L2(14), 1325000 }, + { 1, { 2214000, HFPLL, 1, 0x50 }, L2(14), 1337500 }, + { 1, { 2268000, HFPLL, 1, 0x52 }, L2(14), 1350000 }, + { 1, { 2322000, HFPLL, 1, 0x54 }, L2(14), 1375000 }, { 0, { 0 } } }; @@ -278,11 +403,23 @@ static struct acpu_level tbl_PVS2_1512MHz[] __initdata = { { 1, { 810000, HFPLL, 1, 0x1E }, L2(5), 937500 }, { 1, { 918000, HFPLL, 1, 0x22 }, L2(5), 950000 }, { 1, { 1026000, HFPLL, 1, 0x26 }, L2(5), 975000 }, - { 1, { 1134000, HFPLL, 1, 0x2A }, L2(14), 1000000 }, - { 1, { 1242000, HFPLL, 1, 0x2E }, L2(14), 1012500 }, - { 1, { 1350000, HFPLL, 1, 0x32 }, L2(14), 1037500 }, - { 1, { 1458000, HFPLL, 1, 0x36 }, L2(14), 1075000 }, + { 1, { 1134000, HFPLL, 1, 0x2A }, L2(13), 1000000 }, + { 1, { 1242000, HFPLL, 1, 0x2E }, L2(13), 1012500 }, + { 1, { 1350000, HFPLL, 1, 0x32 }, L2(13), 1037500 }, + { 1, { 1458000, HFPLL, 1, 0x36 }, L2(13), 1075000 }, { 1, { 1512000, HFPLL, 1, 0x38 }, L2(14), 1087500 }, + { 1, { 1620000, HFPLL, 1, 0x3C }, L2(14), 1112500 }, + { 1, { 1728000, HFPLL, 1, 0x40 }, L2(14), 1137500 }, + { 1, { 1836000, HFPLL, 1, 0x44 }, L2(14), 1162500 }, + { 1, { 1890000, HFPLL, 1, 0x46 }, L2(14), 1175000 }, + { 1, { 1944000, HFPLL, 1, 0x48 }, L2(14), 1187500 }, + { 1, { 1998000, HFPLL, 1, 0x4A }, L2(14), 1212500 }, + { 1, { 2052000, HFPLL, 1, 0x4C }, L2(14), 1237500 }, + { 1, { 2106000, HFPLL, 1, 0x4E }, L2(14), 1262500 }, + { 1, { 2160000, HFPLL, 1, 0x4F }, L2(14), 1287500 }, + { 1, { 2214000, HFPLL, 1, 0x50 }, L2(14), 1312500 }, + { 1, { 2268000, HFPLL, 1, 0x52 }, L2(14), 1337500 }, + { 1, { 2322000, HFPLL, 1, 0x54 }, L2(14), 1362500 }, { 0, { 0 } } }; @@ -294,11 +431,23 @@ static struct acpu_level tbl_PVS3_1512MHz[] __initdata = { { 1, { 810000, HFPLL, 1, 0x1E }, L2(5), 900000 }, { 1, { 918000, HFPLL, 1, 0x22 }, L2(5), 925000 }, { 1, { 1026000, HFPLL, 1, 0x26 }, L2(5), 950000 }, - { 1, { 1134000, HFPLL, 1, 0x2A }, L2(14), 975000 }, - { 1, { 1242000, HFPLL, 1, 0x2E }, L2(14), 987500 }, - { 1, { 1350000, HFPLL, 1, 0x32 }, L2(14), 1000000 }, - { 1, { 1458000, HFPLL, 1, 0x36 }, L2(14), 1037500 }, + { 1, { 1134000, HFPLL, 1, 0x2A }, L2(13), 975000 }, + { 1, { 1242000, HFPLL, 1, 0x2E }, L2(13), 987500 }, + { 1, { 1350000, HFPLL, 1, 0x32 }, L2(13), 1000000 }, + { 1, { 1458000, HFPLL, 1, 0x36 }, L2(13), 1037500 }, { 1, { 1512000, HFPLL, 1, 0x38 }, L2(14), 1050000 }, + { 1, { 1620000, HFPLL, 1, 0x3C }, L2(14), 1075000 }, + { 1, { 1728000, HFPLL, 1, 0x40 }, L2(14), 1100000 }, + { 1, { 1836000, HFPLL, 1, 0x44 }, L2(14), 1125000 }, + { 1, { 1890000, HFPLL, 1, 0x46 }, L2(14), 1137500 }, + { 1, { 1944000, HFPLL, 1, 0x48 }, L2(14), 1150000 }, + { 1, { 1998000, HFPLL, 1, 0x4A }, L2(14), 1175000 }, + { 1, { 2052000, HFPLL, 1, 0x4C }, L2(14), 1200000 }, + { 1, { 2106000, HFPLL, 1, 0x4E }, L2(14), 1225000 }, + { 1, { 2160000, HFPLL, 1, 0x4F }, L2(14), 1250000 }, + { 1, { 2214000, HFPLL, 1, 0x50 }, L2(14), 1275000 }, + { 1, { 2268000, HFPLL, 1, 0x52 }, L2(14), 1312500 }, + { 1, { 2322000, HFPLL, 1, 0x54 }, L2(14), 1350000 }, { 0, { 0 } } }; @@ -310,11 +459,23 @@ static struct acpu_level tbl_PVS4_1512MHz[] __initdata = { { 1, { 810000, HFPLL, 1, 0x1E }, L2(5), 887500 }, { 1, { 918000, HFPLL, 1, 0x22 }, L2(5), 900000 }, { 1, { 1026000, HFPLL, 1, 0x26 }, L2(5), 925000 }, - { 1, { 1134000, HFPLL, 1, 0x2A }, L2(14), 950000 }, - { 1, { 1242000, HFPLL, 1, 0x2E }, L2(14), 962500 }, - { 1, { 1350000, HFPLL, 1, 0x32 }, L2(14), 975000 }, - { 1, { 1458000, HFPLL, 1, 0x36 }, L2(14), 1000000 }, + { 1, { 1134000, HFPLL, 1, 0x2A }, L2(13), 950000 }, + { 1, { 1242000, HFPLL, 1, 0x2E }, L2(13), 962500 }, + { 1, { 1350000, HFPLL, 1, 0x32 }, L2(13), 975000 }, + { 1, { 1458000, HFPLL, 1, 0x36 }, L2(13), 1000000 }, { 1, { 1512000, HFPLL, 1, 0x38 }, L2(14), 1012500 }, + { 1, { 1620000, HFPLL, 1, 0x3C }, L2(14), 1037500 }, + { 1, { 1728000, HFPLL, 1, 0x40 }, L2(14), 1062500 }, + { 1, { 1836000, HFPLL, 1, 0x44 }, L2(14), 1087500 }, + { 1, { 1890000, HFPLL, 1, 0x46 }, L2(14), 1100000 }, + { 1, { 1944000, HFPLL, 1, 0x48 }, L2(14), 1112500 }, + { 1, { 1998000, HFPLL, 1, 0x4A }, L2(14), 1137500 }, + { 1, { 2052000, HFPLL, 1, 0x4C }, L2(14), 1175000 }, + { 1, { 2106000, HFPLL, 1, 0x4E }, L2(14), 1200000 }, + { 1, { 2160000, HFPLL, 1, 0x4F }, L2(14), 1225000 }, + { 1, { 2214000, HFPLL, 1, 0x50 }, L2(14), 1250000 }, + { 1, { 2268000, HFPLL, 1, 0x52 }, L2(14), 1275000 }, + { 1, { 2322000, HFPLL, 1, 0x54 }, L2(14), 1300000 }, { 0, { 0 } } }; @@ -326,11 +487,23 @@ static struct acpu_level tbl_PVS5_1512MHz[] __initdata = { { 1, { 810000, HFPLL, 1, 0x1E }, L2(5), 887500 }, { 1, { 918000, HFPLL, 1, 0x22 }, L2(5), 900000 }, { 1, { 1026000, HFPLL, 1, 0x26 }, L2(5), 925000 }, - { 1, { 1134000, HFPLL, 1, 0x2A }, L2(14), 937500 }, - { 1, { 1242000, HFPLL, 1, 0x2E }, L2(14), 950000 }, - { 1, { 1350000, HFPLL, 1, 0x32 }, L2(14), 962500 }, - { 1, { 1458000, HFPLL, 1, 0x36 }, L2(14), 987500 }, + { 1, { 1134000, HFPLL, 1, 0x2A }, L2(13), 937500 }, + { 1, { 1242000, HFPLL, 1, 0x2E }, L2(13), 950000 }, + { 1, { 1350000, HFPLL, 1, 0x32 }, L2(13), 962500 }, + { 1, { 1458000, HFPLL, 1, 0x36 }, L2(13), 987500 }, { 1, { 1512000, HFPLL, 1, 0x38 }, L2(14), 1000000 }, + { 1, { 1620000, HFPLL, 1, 0x3C }, L2(14), 1025000 }, + { 1, { 1728000, HFPLL, 1, 0x40 }, L2(14), 1050000 }, + { 1, { 1836000, HFPLL, 1, 0x44 }, L2(14), 1075000 }, + { 1, { 1890000, HFPLL, 1, 0x46 }, L2(14), 1087500 }, + { 1, { 1944000, HFPLL, 1, 0x48 }, L2(14), 1100000 }, + { 1, { 1998000, HFPLL, 1, 0x4A }, L2(14), 1137500 }, + { 1, { 2052000, HFPLL, 1, 0x4C }, L2(14), 1162500 }, + { 1, { 2106000, HFPLL, 1, 0x4E }, L2(14), 1187500 }, + { 1, { 2160000, HFPLL, 1, 0x4F }, L2(14), 1212500 }, + { 1, { 2214000, HFPLL, 1, 0x50 }, L2(14), 1237500 }, + { 1, { 2268000, HFPLL, 1, 0x54 }, L2(14), 1250000 }, + { 1, { 2322000, HFPLL, 1, 0x56 }, L2(14), 1275000 }, { 0, { 0 } } }; @@ -342,11 +515,23 @@ static struct acpu_level tbl_PVS6_1512MHz[] __initdata = { { 1, { 810000, HFPLL, 1, 0x1E }, L2(5), 887500 }, { 1, { 918000, HFPLL, 1, 0x22 }, L2(5), 900000 }, { 1, { 1026000, HFPLL, 1, 0x26 }, L2(5), 925000 }, - { 1, { 1134000, HFPLL, 1, 0x2A }, L2(14), 937500 }, - { 1, { 1242000, HFPLL, 1, 0x2E }, L2(14), 950000 }, - { 1, { 1350000, HFPLL, 1, 0x32 }, L2(14), 962500 }, - { 1, { 1458000, HFPLL, 1, 0x36 }, L2(14), 975000 }, + { 1, { 1134000, HFPLL, 1, 0x2A }, L2(13), 937500 }, + { 1, { 1242000, HFPLL, 1, 0x2E }, L2(13), 950000 }, + { 1, { 1350000, HFPLL, 1, 0x32 }, L2(13), 962500 }, + { 1, { 1458000, HFPLL, 1, 0x36 }, L2(13), 975000 }, { 1, { 1512000, HFPLL, 1, 0x38 }, L2(14), 987500 }, + { 1, { 1620000, HFPLL, 1, 0x3C }, L2(14), 1012500 }, + { 1, { 1728000, HFPLL, 1, 0x40 }, L2(14), 1037500 }, + { 1, { 1836000, HFPLL, 1, 0x44 }, L2(14), 1062500 }, + { 1, { 1890000, HFPLL, 1, 0x46 }, L2(14), 1075000 }, + { 1, { 1944000, HFPLL, 1, 0x48 }, L2(14), 1087500 }, + { 1, { 1998000, HFPLL, 1, 0x4A }, L2(14), 1125000 }, + { 1, { 2052000, HFPLL, 1, 0x4C }, L2(14), 1150000 }, + { 1, { 2106000, HFPLL, 1, 0x4E }, L2(14), 1175000 }, + { 1, { 2160000, HFPLL, 1, 0x4F }, L2(14), 1200000 }, + { 1, { 2214000, HFPLL, 1, 0x50 }, L2(14), 1225000 }, + { 1, { 2268000, HFPLL, 1, 0x54 }, L2(14), 1250000 }, + { 1, { 2322000, HFPLL, 1, 0x56 }, L2(14), 1275000 }, { 0, { 0 } } }; @@ -652,6 +837,28 @@ static struct acpuclk_krait_params acpuclk_8064_params __initdata = { .stby_khz = 384000, }; +static int __init get_opt_level(char *l2_opt) +{ + if (strcmp(l2_opt, "0") == 0) { + opt_bin = 0; + } else if (strcmp(l2_opt, "1") == 0) { + opt_bin = 1; + } else if (strcmp(l2_opt, "2") == 0) { + opt_bin = 2; + } else if (strcmp(l2_opt, "3") == 0) { + opt_bin = 3; + } else if (strcmp(l2_opt, "4") == 0) { + opt_bin = 4; + } else if (strcmp(l2_opt, "5") == 0) { + opt_bin = 5; + } else { + opt_bin = 0; + } + return 0; +} + +__setup("l2_opt=", get_opt_level); + static int __init acpuclk_8064_probe(struct platform_device *pdev) { if (cpu_is_apq8064ab() || @@ -659,6 +866,30 @@ static int __init acpuclk_8064_probe(struct platform_device *pdev) acpuclk_8064_params.hfpll_data->low_vdd_l_max = 37; acpuclk_8064_params.hfpll_data->nom_vdd_l_max = 74; } + if (opt_bin == 1) { + acpuclk_8064_params.l2_freq_tbl = l2_freq_tbl_oc1; + acpuclk_8064_params.l2_freq_tbl_size = sizeof(l2_freq_tbl_oc1); + } + + if (opt_bin == 2) { + acpuclk_8064_params.l2_freq_tbl = l2_freq_tbl_oc2; + acpuclk_8064_params.l2_freq_tbl_size = sizeof(l2_freq_tbl_oc2); + } + + if (opt_bin == 3) { + acpuclk_8064_params.l2_freq_tbl = l2_freq_tbl_oc3; + acpuclk_8064_params.l2_freq_tbl_size = sizeof(l2_freq_tbl_oc3); + } + + if (opt_bin == 4) { + acpuclk_8064_params.l2_freq_tbl = l2_freq_tbl_oc4; + acpuclk_8064_params.l2_freq_tbl_size = sizeof(l2_freq_tbl_oc4); + } + + if (opt_bin == 5) { + acpuclk_8064_params.l2_freq_tbl = l2_freq_tbl_oc5; + acpuclk_8064_params.l2_freq_tbl_size = sizeof(l2_freq_tbl_oc5); + } return acpuclk_krait_init(&pdev->dev, &acpuclk_8064_params); } diff --git a/arch/arm/mach-msm/acpuclock-8x60.c b/arch/arm/mach-msm/acpuclock-8x60.c index de63febfba2..26b86c6d8f5 100644 --- a/arch/arm/mach-msm/acpuclock-8x60.c +++ b/arch/arm/mach-msm/acpuclock-8x60.c @@ -952,7 +952,7 @@ static void __init cpufreq_table_init(void) {} #endif #define HOT_UNPLUG_KHZ MAX_AXI -static int __cpuinit acpuclock_cpu_callback(struct notifier_block *nfb, +static int acpuclock_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { static int prev_khz[NR_CPUS]; @@ -980,7 +980,7 @@ static int __cpuinit acpuclock_cpu_callback(struct notifier_block *nfb, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata acpuclock_cpu_notifier = { +static struct notifier_block acpuclock_cpu_notifier = { .notifier_call = acpuclock_cpu_callback, }; diff --git a/arch/arm/mach-msm/acpuclock-krait.c b/arch/arm/mach-msm/acpuclock-krait.c index 64b162e3e1d..5bdd5439cb3 100644 --- a/arch/arm/mach-msm/acpuclock-krait.c +++ b/arch/arm/mach-msm/acpuclock-krait.c @@ -38,6 +38,7 @@ #include "acpuclock.h" #include "acpuclock-krait.h" #include "avs.h" +#include "vdd_limits_8064.h" /* MUX source selects. */ #define PRI_SRC_SEL_SEC_SRC 0 @@ -46,6 +47,112 @@ #define SECCLKAGD BIT(4) +#define FREQ_TABLE_SIZE 44 + +/** elementalx defs **/ + +int uv_bin = 0; +uint32_t arg_max_oc0 = 1512000; +uint32_t arg_max_oc1 = 1512000; +uint32_t arg_max_oc2 = 1512000; +uint32_t arg_max_oc3 = 1512000; + +/* boot arg max_oc */ +static int __init cpufreq_read_arg_max_oc0(char *max_oc0) +{ + unsigned long ui_khz; + int err; + err = strict_strtoul(max_oc0, 0, &ui_khz); + if (err) { + arg_max_oc0 = 1512000; + printk(KERN_INFO "[glitch]: max_oc0='%i'\n", arg_max_oc0); + return 1; + } + + arg_max_oc0 = ui_khz; + + return 0; +} +__setup("max_oc0=", cpufreq_read_arg_max_oc0); + +static int __init cpufreq_read_arg_max_oc1(char *max_oc1) +{ + unsigned long ui_khz; + int err; + err = strict_strtoul(max_oc1, 0, &ui_khz); + if (err) { + arg_max_oc1 = 1512000; + printk(KERN_INFO "[glitch]: max_oc1='%i'\n", arg_max_oc1); + return 1; + } + + arg_max_oc1 = ui_khz; + + return 0; +} +__setup("max_oc1=", cpufreq_read_arg_max_oc1); + +static int __init cpufreq_read_arg_max_oc2(char *max_oc2) +{ + unsigned long ui_khz; + int err; + err = strict_strtoul(max_oc2, 0, &ui_khz); + if (err) { + arg_max_oc2 = 1512000; + printk(KERN_INFO "[glitch]: max_oc2='%i'\n", arg_max_oc2); + return 1; + } + + arg_max_oc2 = ui_khz; + + return 0; +} +__setup("max_oc2=", cpufreq_read_arg_max_oc2); + +static int __init cpufreq_read_arg_max_oc3(char *max_oc3) +{ + unsigned long ui_khz; + int err; + err = strict_strtoul(max_oc3, 0, &ui_khz); + if (err) { + arg_max_oc3 = 1512000; + printk(KERN_INFO "[glitch]: max_oc3='%i'\n", arg_max_oc3); + return 1; + } + + arg_max_oc3 = ui_khz; + + return 0; +} +__setup("max_oc3=", cpufreq_read_arg_max_oc3); + +static int __init get_uv_level(char *vdd_uv) +{ + if (strcmp(vdd_uv, "0") == 0) { + uv_bin = 0; + } else if (strcmp(vdd_uv, "1") == 0) { + uv_bin = 1; + } else if (strcmp(vdd_uv, "2") == 0) { + uv_bin = 2; + } else if (strcmp(vdd_uv, "3") == 0) { + uv_bin = 3; + } else if (strcmp(vdd_uv, "4") == 0) { + uv_bin = 4; + } else if (strcmp(vdd_uv, "5") == 0) { + uv_bin = 5; + } else if (strcmp(vdd_uv, "6") == 0) { + uv_bin = 6; + } else { + uv_bin = 0; + } + return 0; +} + +__setup("vdd_uv=", get_uv_level); + +/** end elementalx defs **/ + + static DEFINE_MUTEX(driver_lock); static DEFINE_SPINLOCK(l2_lock); @@ -80,7 +187,7 @@ static void set_pri_clk_src(struct scalable *sc, u32 pri_src_sel) } /* Select a source on the secondary MUX. */ -static void __cpuinit set_sec_clk_src(struct scalable *sc, u32 sec_src_sel) +static void set_sec_clk_src(struct scalable *sc, u32 sec_src_sel) { u32 regval; @@ -607,7 +714,7 @@ static struct acpuclk_data acpuclk_krait_data = { }; /* Initialize a HFPLL at a given rate and enable it. */ -static void __cpuinit hfpll_init(struct scalable *sc, +static void hfpll_init(struct scalable *sc, const struct core_speed *tgt_s) { dev_dbg(drv.dev, "Initializing HFPLL%d\n", sc - drv.scalable); @@ -634,7 +741,7 @@ static void __cpuinit hfpll_init(struct scalable *sc, hfpll_enable(sc, false); } -static int __cpuinit rpm_regulator_init(struct scalable *sc, enum vregs vreg, +static int rpm_regulator_init(struct scalable *sc, enum vregs vreg, int vdd, bool enable) { int ret; @@ -674,7 +781,7 @@ static int __cpuinit rpm_regulator_init(struct scalable *sc, enum vregs vreg, return ret; } -static void __cpuinit rpm_regulator_cleanup(struct scalable *sc, +static void rpm_regulator_cleanup(struct scalable *sc, enum vregs vreg) { if (!sc->vreg[vreg].rpm_reg) @@ -685,7 +792,7 @@ static void __cpuinit rpm_regulator_cleanup(struct scalable *sc, } /* Voltage regulator initialization. */ -static int __cpuinit regulator_init(struct scalable *sc, +static int regulator_init(struct scalable *sc, const struct acpu_level *acpu_level) { int ret, vdd_mem, vdd_dig, vdd_core; @@ -766,7 +873,7 @@ static int __cpuinit regulator_init(struct scalable *sc, return ret; } -static void __cpuinit regulator_cleanup(struct scalable *sc) +static void regulator_cleanup(struct scalable *sc) { regulator_disable(sc->vreg[VREG_CORE].reg); regulator_put(sc->vreg[VREG_CORE].reg); @@ -777,7 +884,7 @@ static void __cpuinit regulator_cleanup(struct scalable *sc) } /* Set initial rate for a given core. */ -static int __cpuinit init_clock_sources(struct scalable *sc, +static int init_clock_sources(struct scalable *sc, const struct core_speed *tgt_s) { u32 regval; @@ -809,21 +916,21 @@ static int __cpuinit init_clock_sources(struct scalable *sc, return 0; } -static void __cpuinit fill_cur_core_speed(struct core_speed *s, +static void fill_cur_core_speed(struct core_speed *s, struct scalable *sc) { s->pri_src_sel = get_l2_indirect_reg(sc->l2cpmr_iaddr) & 0x3; s->pll_l_val = readl_relaxed(sc->hfpll_base + drv.hfpll_data->l_offset); } -static bool __cpuinit speed_equal(const struct core_speed *s1, +static bool speed_equal(const struct core_speed *s1, const struct core_speed *s2) { return (s1->pri_src_sel == s2->pri_src_sel && s1->pll_l_val == s2->pll_l_val); } -static const struct acpu_level __cpuinit *find_cur_acpu_level(int cpu) +static const struct acpu_level *find_cur_acpu_level(int cpu) { struct scalable *sc = &drv.scalable[cpu]; const struct acpu_level *l; @@ -849,7 +956,7 @@ static const struct l2_level __init *find_cur_l2_level(void) return NULL; } -static const struct acpu_level __cpuinit *find_min_acpu_level(void) +static const struct acpu_level *find_min_acpu_level(void) { struct acpu_level *l; @@ -860,7 +967,7 @@ static const struct acpu_level __cpuinit *find_min_acpu_level(void) return NULL; } -static int __cpuinit per_cpu_init(int cpu) +static int per_cpu_init(int cpu) { struct scalable *sc = &drv.scalable[cpu]; const struct acpu_level *acpu_level; @@ -925,19 +1032,66 @@ static void __init bus_init(const struct l2_level *l2_level) dev_err(drv.dev, "initial bandwidth req failed (%d)\n", ret); } +#ifdef CONFIG_CPU_VOLTAGE_TABLE + +ssize_t acpuclk_get_vdd_levels_str(char *buf) { + + int i, len = 0; + + if (buf) { + mutex_lock(&driver_lock); + + for (i = 0; drv.acpu_freq_tbl[i].speed.khz; i++) { + /* updated to use uv required by 8x60 architecture - faux123 */ + len += sprintf(buf + len, "%8lu: %8d\n", drv.acpu_freq_tbl[i].speed.khz, + drv.acpu_freq_tbl[i].vdd_core ); + } + + mutex_unlock(&driver_lock); + } + return len; +} + +/* updated to use uv required by 8x60 architecture - faux123 */ +void acpuclk_set_vdd(unsigned int khz, int vdd_uv) { + + int i; + unsigned int new_vdd_uv; + + mutex_lock(&driver_lock); + + for (i = 0; drv.acpu_freq_tbl[i].speed.khz; i++) { + if (khz == 0) + new_vdd_uv = min(max((unsigned int)(drv.acpu_freq_tbl[i].vdd_core + vdd_uv), + (unsigned int)SC_MIN_VDD), (unsigned int)SC_MAX_VDD); + else if ( drv.acpu_freq_tbl[i].speed.khz == khz) + new_vdd_uv = min(max((unsigned int)vdd_uv, + (unsigned int)SC_MIN_VDD), (unsigned int)SC_MAX_VDD); + else + continue; + + drv.acpu_freq_tbl[i].vdd_core = new_vdd_uv; + } + pr_warn("faux123: user voltage table modified!\n"); + mutex_unlock(&driver_lock); +} +#endif /* CONFIG_CPU_VOTALGE_TABLE */ + #ifdef CONFIG_CPU_FREQ_MSM -static struct cpufreq_frequency_table freq_table[NR_CPUS][35]; +static struct cpufreq_frequency_table freq_table[NR_CPUS][FREQ_TABLE_SIZE]; static void __init cpufreq_table_init(void) { int cpu; + uint32_t limit_max_oc[4] = {arg_max_oc0, arg_max_oc1, arg_max_oc2, arg_max_oc3}; + for_each_possible_cpu(cpu) { int i, freq_cnt = 0; /* Construct the freq_table tables from acpu_freq_tbl. */ for (i = 0; drv.acpu_freq_tbl[i].speed.khz != 0 && freq_cnt < ARRAY_SIZE(*freq_table); i++) { - if (drv.acpu_freq_tbl[i].use_for_scaling) { + if (drv.acpu_freq_tbl[i].speed.khz <= limit_max_oc[cpu]) { freq_table[cpu][freq_cnt].index = freq_cnt; freq_table[cpu][freq_cnt].frequency = drv.acpu_freq_tbl[i].speed.khz; @@ -972,7 +1126,7 @@ static void __init dcvs_freq_init(void) drv.acpu_freq_tbl[i].vdd_core / 1000); } -static int __cpuinit acpuclk_cpu_callback(struct notifier_block *nfb, +static int acpuclk_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { static int prev_khz[NR_CPUS]; @@ -1010,7 +1164,7 @@ static int __cpuinit acpuclk_cpu_callback(struct notifier_block *nfb, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata acpuclk_cpu_notifier = { +static struct notifier_block acpuclk_cpu_notifier = { .notifier_call = acpuclk_cpu_callback, }; @@ -1035,6 +1189,39 @@ static void krait_apply_vmin(struct acpu_level *tbl) } } +static void apply_undervolting(void) +{ + if (uv_bin == 6) { + drv.acpu_freq_tbl[0].vdd_core = 725000; + printk(KERN_INFO "[elementalx]: min_voltage='%i'\n", drv.acpu_freq_tbl[0].vdd_core ); + } + + if (uv_bin == 5) { + drv.acpu_freq_tbl[0].vdd_core = 750000; + printk(KERN_INFO "[elementalx]: min_voltage='%i'\n", drv.acpu_freq_tbl[0].vdd_core ); + } + + if (uv_bin == 4) { + drv.acpu_freq_tbl[0].vdd_core = 775000; + printk(KERN_INFO "[elementalx]: min_voltage='%i'\n", drv.acpu_freq_tbl[0].vdd_core ); + } + + if (uv_bin == 3) { + drv.acpu_freq_tbl[0].vdd_core = 800000; + printk(KERN_INFO "[elementalx]: min_voltage='%i'\n", drv.acpu_freq_tbl[0].vdd_core ); + } + + if (uv_bin == 2) { + drv.acpu_freq_tbl[0].vdd_core = 825000; + printk(KERN_INFO "[elementalx]: min_voltage='%i'\n", drv.acpu_freq_tbl[0].vdd_core ); + } + + if (uv_bin == 1) { + drv.acpu_freq_tbl[0].vdd_core = 850000; + printk(KERN_INFO "[elementalx]: min_voltage='%i'\n", drv.acpu_freq_tbl[0].vdd_core ); + } +} + static int __init get_speed_bin(u32 pte_efuse) { uint32_t speed_bin; @@ -1139,6 +1326,9 @@ static void __init hw_init(void) if (krait_needs_vmin()) krait_apply_vmin(drv.acpu_freq_tbl); + if (uv_bin) + apply_undervolting(); + l2->hfpll_base = ioremap(l2->hfpll_phys_base, SZ_32); BUG_ON(!l2->hfpll_base); diff --git a/arch/arm/mach-msm/asustek/devices_asustek.c b/arch/arm/mach-msm/asustek/devices_asustek.c index 85ed946db17..43ab567d503 100644 --- a/arch/arm/mach-msm/asustek/devices_asustek.c +++ b/arch/arm/mach-msm/asustek/devices_asustek.c @@ -17,6 +17,10 @@ #include #include +#ifdef CONFIG_KEXEC_HARDBOOT +#include +#endif + #include #include #include @@ -56,6 +60,17 @@ void __init asustek_add_persistent_ram(void) void __init asustek_reserve(void) { +#ifdef CONFIG_KEXEC_HARDBOOT + // Reserve space for hardboot page, just before the ram_console + struct membank* bank = &meminfo.bank[0]; + phys_addr_t start = bank->start + bank->size - SZ_1M - ASUSTEK_PERSISTENT_RAM_SIZE; + int ret = memblock_remove(start, SZ_1M); + if(!ret) + pr_info("Hardboot page reserved at 0x%X\n", start); + else + pr_err("Failed to reserve space for hardboot page at 0x%X!\n", start); +#endif + asustek_add_persistent_ram(); } diff --git a/arch/arm/mach-msm/asustek/flo/board-flo-gpu.c b/arch/arm/mach-msm/asustek/flo/board-flo-gpu.c index ecafb4b5a39..86138812611 100644 --- a/arch/arm/mach-msm/asustek/flo/board-flo-gpu.c +++ b/arch/arm/mach-msm/asustek/flo/board-flo-gpu.c @@ -93,13 +93,13 @@ static struct msm_bus_vectors grp3d_low_vectors[] = { .src = MSM_BUS_MASTER_GRAPHICS_3D, .dst = MSM_BUS_SLAVE_EBI_CH0, .ab = 0, - .ib = KGSL_CONVERT_TO_MBPS(1000), + .ib = KGSL_CONVERT_TO_MBPS(1200), }, { .src = MSM_BUS_MASTER_GRAPHICS_3D_PORT1, .dst = MSM_BUS_SLAVE_EBI_CH0, .ab = 0, - .ib = KGSL_CONVERT_TO_MBPS(1000), + .ib = KGSL_CONVERT_TO_MBPS(1200), }, }; @@ -138,13 +138,13 @@ static struct msm_bus_vectors grp3d_max_vectors[] = { .src = MSM_BUS_MASTER_GRAPHICS_3D, .dst = MSM_BUS_SLAVE_EBI_CH0, .ab = 0, - .ib = KGSL_CONVERT_TO_MBPS(4264), + .ib = KGSL_CONVERT_TO_MBPS(4960), }, { .src = MSM_BUS_MASTER_GRAPHICS_3D_PORT1, .dst = MSM_BUS_SLAVE_EBI_CH0, .ab = 0, - .ib = KGSL_CONVERT_TO_MBPS(4264), + .ib = KGSL_CONVERT_TO_MBPS(4960), }, }; @@ -221,7 +221,7 @@ static struct kgsl_device_iommu_data kgsl_3d0_iommu_data[] = { static struct kgsl_device_platform_data kgsl_3d0_pdata = { .pwrlevel = { { - .gpu_freq = 400000000, + .gpu_freq = 450000000, .bus_freq = 4, .io_fraction = 0, }, @@ -272,6 +272,11 @@ struct platform_device device_kgsl_3d0 = { }, }; +void SetMAXGPUFreq(unsigned long freq) +{ + kgsl_3d0_pdata.pwrlevel[0].gpu_freq = freq; +} + void __init apq8064_init_gpu(void) { unsigned int version = socinfo_get_version(); diff --git a/arch/arm/mach-msm/asustek/flo/board-flo-regulator.c b/arch/arm/mach-msm/asustek/flo/board-flo-regulator.c index 05de2e5c5d8..8e74db7ec19 100644 --- a/arch/arm/mach-msm/asustek/flo/board-flo-regulator.c +++ b/arch/arm/mach-msm/asustek/flo/board-flo-regulator.c @@ -14,6 +14,7 @@ #include #include "board-flo.h" +#include "../../vdd_limits_8064.h" #define VREG_CONSUMERS(_id) \ static struct regulator_consumer_supply vreg_consumers_##_id[] @@ -567,15 +568,15 @@ mpq8064_gpio_regulator_pdata[] __devinitdata = { /* SAW regulator constraints */ struct regulator_init_data msm8064_saw_regulator_pdata_8921_s5 = /* ID vreg_name min_uV max_uV */ - SAW_VREG_INIT(S5, "8921_s5", 850000, 1300000); + SAW_VREG_INIT(S5, "8921_s5", SC_MIN_VDD, SC_MAX_VDD); struct regulator_init_data msm8064_saw_regulator_pdata_8921_s6 = - SAW_VREG_INIT(S6, "8921_s6", 850000, 1300000); + SAW_VREG_INIT(S6, "8921_s6", SC_MIN_VDD, SC_MAX_VDD); struct regulator_init_data msm8064_saw_regulator_pdata_8821_s0 = /* ID vreg_name min_uV max_uV */ - SAW_VREG_INIT(8821_S0, "8821_s0", 850000, 1300000); + SAW_VREG_INIT(8821_S0, "8821_s0", SC_MIN_VDD, SC_MAX_VDD); struct regulator_init_data msm8064_saw_regulator_pdata_8821_s1 = - SAW_VREG_INIT(8821_S1, "8821_s1", 850000, 1300000); + SAW_VREG_INIT(8821_S1, "8821_s1", SC_MIN_VDD, SC_MAX_VDD); /* PM8921 regulator constraints */ struct pm8xxx_regulator_platform_data @@ -623,7 +624,7 @@ apq8064_rpm_regulator_init_data[] __devinitdata = { /* ID a_on pd ss min_uV max_uV supply sys_uA freq fm ss_fm */ RPM_SMPS(S1, 1, 1, 0, 1225000, 1225000, NULL, 100000, 3p20, NONE, NONE), RPM_SMPS(S2, 0, 1, 0, 1300000, 1300000, NULL, 0, 1p60, NONE, NONE), - RPM_SMPS(S3, 0, 1, 1, 500000, 1150000, NULL, 100000, 4p80, NONE, NONE), + RPM_SMPS(S3, 0, 1, 1, 500000, MEM_DIG_MAX_VDD, NULL, 100000, 4p80, NONE, NONE), RPM_SMPS(S4, 1, 1, 0, 1800000, 1800000, NULL, 100000, 1p60, AUTO, AUTO), RPM_SMPS(S7, 0, 0, 0, 1300000, 1300000, NULL, 100000, 3p20, NONE, NONE), RPM_SMPS(S8, 0, 1, 0, 2200000, 2200000, NULL, 0, 1p60, NONE, NONE), @@ -650,7 +651,7 @@ apq8064_rpm_regulator_init_data[] __devinitdata = { RPM_LDO(L21, 0, 1, 0, 1050000, 1050000, NULL, 0, 0), RPM_LDO(L22, 0, 1, 0, 2600000, 2600000, NULL, 0, 0), RPM_LDO(L23, 0, 1, 0, 1800000, 1800000, NULL, 0, 0), - RPM_LDO(L24, 0, 1, 1, 750000, 1150000, "8921_s1", 10000, 10000), + RPM_LDO(L24, 0, 1, 1, 750000, MEM_DIG_MAX_VDD, "8921_s1", 10000, 10000), RPM_LDO(L25, 1, 1, 0, 1250000, 1250000, "8921_s1", 10000, 10000), RPM_LDO(L27, 0, 0, 0, 1100000, 1100000, "8921_s7", 0, 0), RPM_LDO(L28, 0, 1, 0, 1050000, 1050000, "8921_s7", 0, 0), diff --git a/arch/arm/mach-msm/asustek/flo/board-flo.c b/arch/arm/mach-msm/asustek/flo/board-flo.c index f4c5c10a1e5..f56a1936237 100644 --- a/arch/arm/mach-msm/asustek/flo/board-flo.c +++ b/arch/arm/mach-msm/asustek/flo/board-flo.c @@ -2085,10 +2085,10 @@ static struct platform_device msm_tsens_device = { static struct msm_thermal_data msm_thermal_pdata = { .sensor_id = 7, - .poll_ms = 250, +/* .poll_ms = 250, .limit_temp_degC = 60, .temp_hysteresis_degC = 10, - .freq_step = 2, + .freq_step = 2,*/ }; #define MSM_SHARED_RAM_PHYS 0x80000000 @@ -2222,13 +2222,13 @@ static struct msm_rpmrs_platform_data msm_rpmrs_data __initdata = { [MSM_RPMRS_VDD_MEM_RET_LOW] = 750000, [MSM_RPMRS_VDD_MEM_RET_HIGH] = 750000, [MSM_RPMRS_VDD_MEM_ACTIVE] = 1050000, - [MSM_RPMRS_VDD_MEM_MAX] = 1150000, + [MSM_RPMRS_VDD_MEM_MAX] = 1250000, }, .vdd_dig_levels = { [MSM_RPMRS_VDD_DIG_RET_LOW] = 500000, [MSM_RPMRS_VDD_DIG_RET_HIGH] = 750000, [MSM_RPMRS_VDD_DIG_ACTIVE] = 950000, - [MSM_RPMRS_VDD_DIG_MAX] = 1150000, + [MSM_RPMRS_VDD_DIG_MAX] = 1250000, }, .vdd_mask = 0x7FFFFF, .rpmrs_target_id = { diff --git a/arch/arm/mach-msm/board-8064-gpu.c b/arch/arm/mach-msm/board-8064-gpu.c index ad87e0a7748..4cca16794b8 100644 --- a/arch/arm/mach-msm/board-8064-gpu.c +++ b/arch/arm/mach-msm/board-8064-gpu.c @@ -272,6 +272,11 @@ struct platform_device device_kgsl_3d0 = { }, }; +void SetMAXGPUFreq(unsigned long freq) +{ + kgsl_3d0_pdata.pwrlevel[0].gpu_freq = freq; +} + void __init apq8064_init_gpu(void) { unsigned int version = socinfo_get_version(); diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c index 3c66d3ab884..f78acdd1948 100644 --- a/arch/arm/mach-msm/clock-8960.c +++ b/arch/arm/mach-msm/clock-8960.c @@ -3586,7 +3586,7 @@ static unsigned long fmax_gfx3d_8064ab[VDD_DIG_NUM] = { static unsigned long fmax_gfx3d_8064[VDD_DIG_NUM] = { [VDD_DIG_LOW] = 128000000, [VDD_DIG_NOMINAL] = 325000000, - [VDD_DIG_HIGH] = 400000000 + [VDD_DIG_HIGH] = 450000000 }; static unsigned long fmax_gfx3d_8930[VDD_DIG_NUM] = { @@ -6335,7 +6335,7 @@ static struct pll_config pll4_config_393 __initdata = { .main_output_mask = BIT(23), }; -static struct pll_config_regs pll15_regs __initdata = { +static struct pll_config_regs pll15_regs = { .l_reg = MM_PLL3_L_VAL_REG, .m_reg = MM_PLL3_M_VAL_REG, .n_reg = MM_PLL3_N_VAL_REG, @@ -6343,7 +6343,7 @@ static struct pll_config_regs pll15_regs __initdata = { .mode_reg = MM_PLL3_MODE_REG, }; -static struct pll_config pll15_config __initdata = { +static struct pll_config pll15_config = { .l = (0x24 | BVAL(31, 7, 0x620)), .m = 0x1, .n = 0x9, @@ -6600,6 +6600,21 @@ static void __init reg_init(void) } } +extern void configure_pllOC(struct pll_config *config, + struct pll_config_regs *regs, u32 ena_fsm_mode); + +void __ref SetGPUpll_config(u32 loc, unsigned long freq) +{ + /* Program PLL15 to 900MHZ */ + pll15_config.l = loc | BVAL(31, 7, 0x620); + pll15_config.m = 0x1; + pll15_config.n = 0x3; + configure_pllOC(&pll15_config, &pll15_regs, 0); + //fmax_gfx3d_8064ab[VDD_DIG_HIGH] = freq; + //gfx3d_clk.c.fmax = fmax_gfx3d_8064ab; + //gfx3d_clk.freq_tbl[ARRAY_SIZE(clk_tbl_gfx3d)-1].freq_hz = freq; + pr_alert("SET GPU OC-%d-%ld", loc, freq / 1000000); +} struct clock_init_data msm8960_clock_init_data __initdata; static void __init msm8960_clock_pre_init(void) { diff --git a/arch/arm/mach-msm/clock-pll.c b/arch/arm/mach-msm/clock-pll.c index aeb1c5ed0c7..0df064a56d1 100644 --- a/arch/arm/mach-msm/clock-pll.c +++ b/arch/arm/mach-msm/clock-pll.c @@ -501,6 +501,41 @@ void __init __configure_pll(struct pll_config *config, writel_relaxed(regval, PLL_CONFIG_REG(regs)); } +void configure_pllOC(struct pll_config *config, + struct pll_config_regs *regs, u32 ena_fsm_mode) +{ + u32 regval; + + writel_relaxed(config->l, PLL_L_REG(regs)); + writel_relaxed(config->m, PLL_M_REG(regs)); + writel_relaxed(config->n, PLL_N_REG(regs)); + + regval = readl_relaxed(PLL_CONFIG_REG(regs)); + + /* Enable the MN accumulator */ + if (config->mn_ena_mask) { + regval &= ~config->mn_ena_mask; + regval |= config->mn_ena_val; + } + + /* Enable the main output */ + if (config->main_output_mask) { + regval &= ~config->main_output_mask; + regval |= config->main_output_val; + } + + /* Set pre-divider and post-divider values */ + regval &= ~config->pre_div_mask; + regval |= config->pre_div_val; + regval &= ~config->post_div_mask; + regval |= config->post_div_val; + + /* Select VCO setting */ + regval &= ~config->vco_mask; + regval |= config->vco_val; + writel_relaxed(regval, PLL_CONFIG_REG(regs)); +} + void __init configure_sr_pll(struct pll_config *config, struct pll_config_regs *regs, u32 ena_fsm_mode) { diff --git a/arch/arm/mach-msm/cpufreq.c b/arch/arm/mach-msm/cpufreq.c index 9d9ea5cb3c9..0e8e0cb8a90 100644 --- a/arch/arm/mach-msm/cpufreq.c +++ b/arch/arm/mach-msm/cpufreq.c @@ -192,7 +192,7 @@ int msm_cpufreq_set_freq_limits(uint32_t cpu, uint32_t min, uint32_t max) } EXPORT_SYMBOL(msm_cpufreq_set_freq_limits); -static int __cpuinit msm_cpufreq_init(struct cpufreq_policy *policy) +static int msm_cpufreq_init(struct cpufreq_policy *policy) { int cur_freq; int index; @@ -249,7 +249,7 @@ static int __cpuinit msm_cpufreq_init(struct cpufreq_policy *policy) return 0; } -static int __cpuinit msm_cpufreq_cpu_callback(struct notifier_block *nfb, +static int msm_cpufreq_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { unsigned int cpu = (unsigned long)hcpu; diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c index 862437a3bbe..53d0ccfdf71 100644 --- a/arch/arm/mach-msm/devices-8064.c +++ b/arch/arm/mach-msm/devices-8064.c @@ -1325,26 +1325,26 @@ static struct msm_bus_vectors vidc_venc_1080p_turbo_vectors[] = { { .src = MSM_BUS_MASTER_VIDEO_ENC, .dst = MSM_BUS_SLAVE_EBI_CH0, - .ab = 222298112, + .ab = 372244480, .ib = 3522000000U, }, { .src = MSM_BUS_MASTER_VIDEO_DEC, .dst = MSM_BUS_SLAVE_EBI_CH0, - .ab = 330301440, + .ab = 501219328, .ib = 3522000000U, }, { .src = MSM_BUS_MASTER_AMPSS_M0, .dst = MSM_BUS_SLAVE_EBI_CH0, .ab = 2500000, - .ib = 700000000, + .ib = 5000000, }, { .src = MSM_BUS_MASTER_AMPSS_M0, .dst = MSM_BUS_SLAVE_EBI_CH0, .ab = 2500000, - .ib = 10000000, + .ib = 5000000, }, }; static struct msm_bus_vectors vidc_vdec_1080p_turbo_vectors[] = { diff --git a/arch/arm/mach-msm/fastchg.c b/arch/arm/mach-msm/fastchg.c new file mode 100644 index 00000000000..228acee5525 --- /dev/null +++ b/arch/arm/mach-msm/fastchg.c @@ -0,0 +1,104 @@ +/* + * Author: Chad Froebel + * + * Simple port to Nexus 4 : motley + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + * + */ + +/* + * Possible values for "force_fast_charge" are : + * + * 0 - disabled (default) + * 1 - substitute AC to USB unconditional +*/ + +#include +#include +#include +#include + +int force_fast_charge = 0; +static int __init get_fastcharge_opt(char *ffc) +{ + if (strcmp(ffc, "0") == 0) { + force_fast_charge = 0; + } else if (strcmp(ffc, "1") == 0) { + force_fast_charge = 1; + } else { + force_fast_charge = 0; + } + return 1; +} + +__setup("ffc=", get_fastcharge_opt); + +static ssize_t force_fast_charge_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) +{ + size_t count = 0; + count += sprintf(buf, "%d\n", force_fast_charge); + return count; +} + +static ssize_t force_fast_charge_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) +{ + if (buf[0] >= '0' && buf[0] <= '1' && buf[1] == '\n') + if (force_fast_charge != buf[0] - '0') + force_fast_charge = buf[0] - '0'; + + return count; +} + +static struct kobj_attribute force_fast_charge_attribute = +__ATTR(force_fast_charge, 0666, force_fast_charge_show, force_fast_charge_store); + +static struct attribute *force_fast_charge_attrs[] = { +&force_fast_charge_attribute.attr, +NULL, +}; + +static struct attribute_group force_fast_charge_attr_group = { +.attrs = force_fast_charge_attrs, +}; + +/* Initialize fast charge sysfs folder */ +static struct kobject *force_fast_charge_kobj; + +int force_fast_charge_init(void) +{ + int force_fast_charge_retval; + +// force_fast_charge = FAST_CHARGE_DISABLED; /* Forced fast charge disabled by default */ + + force_fast_charge_kobj = kobject_create_and_add("fast_charge", kernel_kobj); + if (!force_fast_charge_kobj) { + return -ENOMEM; + } + + force_fast_charge_retval = sysfs_create_group(force_fast_charge_kobj, &force_fast_charge_attr_group); + + if (force_fast_charge_retval) + kobject_put(force_fast_charge_kobj); + + if (force_fast_charge_retval) + kobject_put(force_fast_charge_kobj); + + return (force_fast_charge_retval); +} + +void force_fast_charge_exit(void) +{ + kobject_put(force_fast_charge_kobj); +} + +module_init(force_fast_charge_init); +module_exit(force_fast_charge_exit); + diff --git a/arch/arm/mach-msm/include/mach/memory.h b/arch/arm/mach-msm/include/mach/memory.h index 83296117c70..43b0e063a99 100644 --- a/arch/arm/mach-msm/include/mach/memory.h +++ b/arch/arm/mach-msm/include/mach/memory.h @@ -20,6 +20,14 @@ /* physical offset of RAM */ #define PLAT_PHYS_OFFSET UL(CONFIG_PHYS_OFFSET) +#if defined(CONFIG_KEXEC_HARDBOOT) +#if defined(CONFIG_MACH_APQ8064_FLO) +#define KEXEC_HB_PAGE_ADDR UL(0x88C00000) +#else +#error "Adress for kexec hardboot page not defined" +#endif +#endif + #define MAX_PHYSMEM_BITS 32 #define SECTION_SIZE_BITS 28 diff --git a/arch/arm/mach-msm/intelli_plug.c b/arch/arm/mach-msm/intelli_plug.c new file mode 100644 index 00000000000..44fa649184a --- /dev/null +++ b/arch/arm/mach-msm/intelli_plug.c @@ -0,0 +1,346 @@ +/* + * Author: Paul Reioux aka Faux123 + * + * Copyright 2012 Paul Reioux + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#include +#include +#include +#include +#include +#include +#include + +//#define DEBUG_INTELLI_PLUG +#undef DEBUG_INTELLI_PLUG + +#define INTELLI_PLUG_MAJOR_VERSION 1 +#define INTELLI_PLUG_MINOR_VERSION 6 + +#define DEF_SAMPLING_RATE (50000) +#define DEF_SAMPLING_MS (200) + +#define DUAL_CORE_PERSISTENCE 15 +#define TRI_CORE_PERSISTENCE 12 +#define QUAD_CORE_PERSISTENCE 9 + +#define RUN_QUEUE_THRESHOLD 38 + +#define CPU_DOWN_FACTOR 3 + +static DEFINE_MUTEX(intelli_plug_mutex); + +struct delayed_work intelli_plug_work; + +static unsigned int intelli_plug_active = 0; +module_param(intelli_plug_active, uint, 0644); + +static unsigned int eco_mode_active = 0; +module_param(eco_mode_active, uint, 0644); + +static unsigned int persist_count = 0; +static bool suspended = false; + +#define NR_FSHIFT 3 +static unsigned int nr_fshift = NR_FSHIFT; +module_param(nr_fshift, uint, 0644); + +static unsigned int nr_run_thresholds_full[] = { +/* 1, 2, 3, 4 - on-line cpus target */ + 5, 7, 9, UINT_MAX /* avg run threads * 2 (e.g., 9 = 2.25 threads) */ + }; + +static unsigned int nr_run_thresholds_eco[] = { +/* 1, 2, - on-line cpus target */ + 3, UINT_MAX /* avg run threads * 2 (e.g., 9 = 2.25 threads) */ + }; + +static unsigned int nr_run_hysteresis = 4; /* 0.5 thread */ +module_param(nr_run_hysteresis, uint, 0644); + +static unsigned int nr_run_last; + +static unsigned int NwNs_Threshold[] = { 19, 30, 19, 11, 19, 11, 0, 11}; +static unsigned int TwTs_Threshold[] = {140, 0, 140, 190, 140, 190, 0, 190}; + +static int mp_decision(void) +{ + static bool first_call = true; + int new_state = 0; + int nr_cpu_online; + int index; + unsigned int rq_depth; + static cputime64_t total_time = 0; + static cputime64_t last_time; + cputime64_t current_time; + cputime64_t this_time = 0; + + current_time = ktime_to_ms(ktime_get()); + if (first_call) { + first_call = false; + } else { + this_time = current_time - last_time; + } + total_time += this_time; + + rq_depth = rq_info.rq_avg; + //pr_info(" rq_deptch = %u", rq_depth); + nr_cpu_online = num_online_cpus(); + + if (nr_cpu_online) { + index = (nr_cpu_online - 1) * 2; + if ((nr_cpu_online < 4) && (rq_depth >= NwNs_Threshold[index])) { + if (total_time >= TwTs_Threshold[index]) { + new_state = 1; + } + } else if (rq_depth <= NwNs_Threshold[index+1]) { + if (total_time >= TwTs_Threshold[index+1] ) { + new_state = 0; + } + } else { + total_time = 0; + } + } else { + total_time = 0; + } + + last_time = ktime_to_ms(ktime_get()); + + return new_state; +} + +static unsigned int calculate_thread_stats(void) +{ + unsigned int avg_nr_run = avg_nr_running(); + unsigned int nr_run; + unsigned int threshold_size; + + if (!eco_mode_active) { + threshold_size = ARRAY_SIZE(nr_run_thresholds_full); + nr_run_hysteresis = 8; + nr_fshift = 3; +#ifdef DEBUG_INTELLI_PLUG + pr_info("intelliplug: full mode active!"); +#endif + } + else { + threshold_size = ARRAY_SIZE(nr_run_thresholds_eco); + nr_run_hysteresis = 4; + nr_fshift = 1; +#ifdef DEBUG_INTELLI_PLUG + pr_info("intelliplug: eco mode active!"); +#endif + } + + for (nr_run = 1; nr_run < threshold_size; nr_run++) { + unsigned int nr_threshold; + if (!eco_mode_active) + nr_threshold = nr_run_thresholds_full[nr_run - 1]; + else + nr_threshold = nr_run_thresholds_eco[nr_run - 1]; + + if (nr_run_last <= nr_run) + nr_threshold += nr_run_hysteresis; + if (avg_nr_run <= (nr_threshold << (FSHIFT - nr_fshift))) + break; + } + nr_run_last = nr_run; + + return nr_run; +} + +static void __cpuinit intelli_plug_work_fn(struct work_struct *work) +{ + unsigned int nr_run_stat; + unsigned int cpu_count = 0; + unsigned int nr_cpus = 0; + + int decision = 0; + int i; + + if (intelli_plug_active == 1) { + nr_run_stat = calculate_thread_stats(); +#ifdef DEBUG_INTELLI_PLUG + pr_info("nr_run_stat: %u\n", nr_run_stat); +#endif + cpu_count = nr_run_stat; + // detect artificial loads or constant loads + // using msm rqstats + nr_cpus = num_online_cpus(); + if (!eco_mode_active && (nr_cpus >= 1 && nr_cpus < 4)) { + decision = mp_decision(); + if (decision) { + switch (nr_cpus) { + case 2: + cpu_count = 3; +#ifdef DEBUG_INTELLI_PLUG + pr_info("nr_run(2) => %u\n", nr_run_stat); +#endif + break; + case 3: + cpu_count = 4; +#ifdef DEBUG_INTELLI_PLUG + pr_info("nr_run(3) => %u\n", nr_run_stat); +#endif + break; + } + } + } + + if (!suspended) { + switch (cpu_count) { + case 1: + if (persist_count > 0) + persist_count--; + if (persist_count == 0) { + //take down everyone + for (i = 3; i > 0; i--) + cpu_down(i); + } +#ifdef DEBUG_INTELLI_PLUG + pr_info("case 1: %u\n", persist_count); +#endif + break; + case 2: + persist_count = DUAL_CORE_PERSISTENCE; + if (!decision) + persist_count = DUAL_CORE_PERSISTENCE / CPU_DOWN_FACTOR; + if (nr_cpus < 2) { + for (i = 1; i < cpu_count; i++) + cpu_up(i); + } else { + for (i = 3; i > 1; i--) + cpu_down(i); + } +#ifdef DEBUG_INTELLI_PLUG + pr_info("case 2: %u\n", persist_count); +#endif + break; + case 3: + persist_count = TRI_CORE_PERSISTENCE; + if (!decision) + persist_count = TRI_CORE_PERSISTENCE / CPU_DOWN_FACTOR; + if (nr_cpus < 3) { + for (i = 1; i < cpu_count; i++) + cpu_up(i); + } else { + for (i = 3; i > 2; i--) + cpu_down(i); + } +#ifdef DEBUG_INTELLI_PLUG + pr_info("case 3: %u\n", persist_count); +#endif + break; + case 4: + persist_count = QUAD_CORE_PERSISTENCE; + if (!decision) + persist_count = QUAD_CORE_PERSISTENCE / CPU_DOWN_FACTOR; + if (nr_cpus < 4) + for (i = 1; i < cpu_count; i++) + cpu_up(i); +#ifdef DEBUG_INTELLI_PLUG + pr_info("case 4: %u\n", persist_count); +#endif + break; + default: + pr_err("Run Stat Error: Bad value %u\n", nr_run_stat); + break; + } + } +#ifdef DEBUG_INTELLI_PLUG + else + pr_info("intelli_plug is suspened!\n"); +#endif + } + schedule_delayed_work_on(0, &intelli_plug_work, + msecs_to_jiffies(DEF_SAMPLING_MS)); +} + +#ifdef CONFIG_HAS_EARLYSUSPEND +static void intelli_plug_early_suspend(struct early_suspend *handler) +{ + int i; + int num_of_active_cores = 4; + + cancel_delayed_work_sync(&intelli_plug_work); + + mutex_lock(&intelli_plug_mutex); + suspended = true; + mutex_unlock(&intelli_plug_mutex); + + // put rest of the cores to sleep! + for (i = num_of_active_cores - 1; i > 0; i--) { + cpu_down(i); + } +} + +static void __cpuinit intelli_plug_late_resume(struct early_suspend *handler) +{ + int num_of_active_cores; + int i; + + mutex_lock(&intelli_plug_mutex); + /* keep cores awake long enough for faster wake up */ + persist_count = DUAL_CORE_PERSISTENCE; + suspended = false; + mutex_unlock(&intelli_plug_mutex); + + /* wake up everyone */ + if (eco_mode_active) + num_of_active_cores = 2; + else + num_of_active_cores = 4; + + for (i = 1; i < num_of_active_cores; i++) { + cpu_up(i); + } + + schedule_delayed_work_on(0, &intelli_plug_work, + msecs_to_jiffies(10)); +} + +static struct early_suspend intelli_plug_early_suspend_struct_driver = { + .level = EARLY_SUSPEND_LEVEL_DISABLE_FB + 10, + .suspend = intelli_plug_early_suspend, + .resume = intelli_plug_late_resume, +}; +#endif /* CONFIG_HAS_EARLYSUSPEND */ + +int __init intelli_plug_init(void) +{ + /* We want all CPUs to do sampling nearly on same jiffy */ + int delay = usecs_to_jiffies(DEF_SAMPLING_RATE); + + if (num_online_cpus() > 1) + delay -= jiffies % delay; + + //pr_info("intelli_plug: scheduler delay is: %d\n", delay); + pr_info("intelli_plug: version %d.%d by faux123\n", + INTELLI_PLUG_MAJOR_VERSION, + INTELLI_PLUG_MINOR_VERSION); + + INIT_DELAYED_WORK(&intelli_plug_work, intelli_plug_work_fn); + schedule_delayed_work_on(0, &intelli_plug_work, delay); + +#ifdef CONFIG_HAS_EARLYSUSPEND + register_early_suspend(&intelli_plug_early_suspend_struct_driver); +#endif + return 0; +} + +MODULE_AUTHOR("Paul Reioux "); +MODULE_DESCRIPTION("'intell_plug' - An intelligent cpu hotplug driver for " + "Low Latency Frequency Transition capable processors"); +MODULE_LICENSE("GPL"); + +late_initcall(intelli_plug_init); diff --git a/arch/arm/mach-msm/msm_dcvs.c b/arch/arm/mach-msm/msm_dcvs.c index 9e0be639597..91e639e4730 100644 --- a/arch/arm/mach-msm/msm_dcvs.c +++ b/arch/arm/mach-msm/msm_dcvs.c @@ -146,7 +146,7 @@ static struct dcvs_core core_list[CORES_MAX]; static struct kobject *cores_kobj; -#define DCVS_MAX_NUM_FREQS 15 +#define DCVS_MAX_NUM_FREQS 24 static struct msm_dcvs_freq_entry cpu_freq_tbl[DCVS_MAX_NUM_FREQS]; static unsigned num_cpu_freqs; static struct msm_dcvs_platform_data *dcvs_pdata; diff --git a/arch/arm/mach-msm/msm_mpdecision.c b/arch/arm/mach-msm/msm_mpdecision.c index 52b9ec316a9..1f133c05c3d 100644 --- a/arch/arm/mach-msm/msm_mpdecision.c +++ b/arch/arm/mach-msm/msm_mpdecision.c @@ -1,726 +1,1184 @@ - /* Copyright (c) 2012, The Linux Foundation. All rights reserved. +/* + * arch/arm/mach-msm/msm_mpdecision.c + * + * This program features: + * -cpu auto-hotplug/unplug based on system load for MSM multicore cpus + * -single core while screen is off + * -extensive sysfs tuneables + * + * Copyright (c) 2012-2013, Dennis Rassmann * * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. + * 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. + * 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. */ -#define pr_fmt(fmt) "mpd %s: " fmt, __func__ - -#include -#include +#include #include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include #include +#include +#include +#ifdef CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN +#include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#define CREATE_TRACE_POINTS -#include - -#define DEFAULT_RQ_AVG_POLL_MS (1) -#define DEFAULT_RQ_AVG_DIVIDE (25) - -struct mpd_attrib { - struct kobj_attribute enabled; - struct kobj_attribute rq_avg_poll_ms; - struct kobj_attribute iowait_threshold_pct; - - struct kobj_attribute rq_avg_divide; - struct kobj_attribute em_win_size_min_us; - struct kobj_attribute em_win_size_max_us; - struct kobj_attribute em_max_util_pct; - struct kobj_attribute mp_em_rounding_point_min; - struct kobj_attribute mp_em_rounding_point_max; - struct kobj_attribute online_util_pct_min; - struct kobj_attribute online_util_pct_max; - struct kobj_attribute slack_time_min_us; - struct kobj_attribute slack_time_max_us; - struct kobj_attribute hp_up_max_ms; - struct kobj_attribute hp_up_ms; - struct kobj_attribute hp_up_count; - struct kobj_attribute hp_dw_max_ms; - struct kobj_attribute hp_dw_ms; - struct kobj_attribute hp_dw_count; - struct attribute_group attrib_group; -}; +#endif +#include "acpuclock.h" + +#define DEBUG 0 + +#define MPDEC_TAG "[MPDEC]: " +#define MSM_MPDEC_STARTDELAY 20000 +#define MSM_MPDEC_DELAY 130 +#define MSM_MPDEC_PAUSE 10000 +#define MSM_MPDEC_IDLE_FREQ 486000 +#ifdef CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN +#define MSM_MPDEC_BOOSTTIME 1000 +#define MSM_MPDEC_BOOSTFREQ_CPU0 1026000 +#define MSM_MPDEC_BOOSTFREQ_CPU1 810000 +#define MSM_MPDEC_BOOSTFREQ_CPU2 702000 +#define MSM_MPDEC_BOOSTFREQ_CPU3 594000 +#endif -struct msm_mpd_scm_data { - enum msm_dcvs_scm_event event; - int nr; +enum { + MSM_MPDEC_DISABLED = 0, + MSM_MPDEC_IDLE, + MSM_MPDEC_DOWN, + MSM_MPDEC_UP, }; -struct mpdecision { - uint32_t enabled; - atomic_t algo_cpu_mask; - uint32_t rq_avg_poll_ms; - uint32_t iowait_threshold_pct; - uint32_t rq_avg_divide; - ktime_t next_update; - uint32_t slack_us; - struct msm_mpd_algo_param mp_param; - struct mpd_attrib attrib; - struct mutex lock; - struct task_struct *task; - struct task_struct *hptask; - struct hrtimer slack_timer; - struct msm_mpd_scm_data data; - int hpupdate; - wait_queue_head_t wait_q; - wait_queue_head_t wait_hpq; +struct msm_mpdec_cpudata_t { + struct mutex hotplug_mutex; + int online; + int device_suspended; + cputime64_t on_time; + cputime64_t on_time_total; + long long unsigned int times_cpu_hotplugged; + long long unsigned int times_cpu_unplugged; +#ifdef CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN + struct mutex boost_mutex; + struct mutex unboost_mutex; + unsigned long int norm_min_freq; + unsigned long int boost_freq; + cputime64_t boost_until; + bool is_boosted; + bool revib_wq_running; +#endif }; - -struct hp_latency { - int hp_up_max_ms; - int hp_up_ms; - int hp_up_count; - int hp_dw_max_ms; - int hp_dw_ms; - int hp_dw_count; +static DEFINE_PER_CPU(struct msm_mpdec_cpudata_t, msm_mpdec_cpudata); + +static struct delayed_work msm_mpdec_work; +static struct workqueue_struct *msm_mpdec_workq; +static DEFINE_MUTEX(mpdec_msm_cpu_lock); +#ifdef CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN +static struct workqueue_struct *mpdec_input_wq; +static DEFINE_PER_CPU(struct work_struct, mpdec_input_work); +static struct workqueue_struct *msm_mpdec_revib_workq; +static DEFINE_PER_CPU(struct delayed_work, msm_mpdec_revib_work); +#endif + +static struct msm_mpdec_tuners { + unsigned int startdelay; + unsigned int delay; + unsigned int pause; + bool scroff_single_core; + unsigned long int idle_freq; + unsigned int max_cpus; + unsigned int min_cpus; +#ifdef CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN + bool boost_enabled; + unsigned int boost_time; + unsigned long int boost_freq[4]; +#endif +} msm_mpdec_tuners_ins = { + .startdelay = MSM_MPDEC_STARTDELAY, + .delay = MSM_MPDEC_DELAY, + .pause = MSM_MPDEC_PAUSE, + .scroff_single_core = true, + .idle_freq = MSM_MPDEC_IDLE_FREQ, + .max_cpus = CONFIG_NR_CPUS, + .min_cpus = 1, +#ifdef CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN + .boost_enabled = true, + .boost_time = MSM_MPDEC_BOOSTTIME, + .boost_freq = { + MSM_MPDEC_BOOSTFREQ_CPU0, + MSM_MPDEC_BOOSTFREQ_CPU1, + MSM_MPDEC_BOOSTFREQ_CPU2, + MSM_MPDEC_BOOSTFREQ_CPU3 + }, +#endif }; -static DEFINE_PER_CPU(struct hrtimer, rq_avg_poll_timer); -static DEFINE_SPINLOCK(rq_avg_lock); +static unsigned int NwNs_Threshold[8] = {12, 0, 20, 7, 25, 10, 0, 18}; +static unsigned int TwTs_Threshold[8] = {140, 0, 140, 190, 140, 190, 0, 190}; -enum { - MSM_MPD_DEBUG_NOTIFIER = BIT(0), - MSM_MPD_CORE_STATUS = BIT(1), - MSM_MPD_SLACK_TIMER = BIT(2), -}; +extern unsigned int get_rq_info(void); +extern unsigned long acpuclk_get_rate(int); -enum { - HPUPDATE_WAITING = 0, /* we are waiting for cpumask update */ - HPUPDATE_SCHEDULED = 1, /* we are in the process of hotplugging */ - HPUPDATE_IN_PROGRESS = 2, /* we are in the process of hotplugging */ -}; +unsigned int state = MSM_MPDEC_IDLE; +bool was_paused = false; +#ifdef CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN +bool is_screen_on = true; +static int update_cpu_min_freq(struct cpufreq_policy *cpu_policy, + int cpu, int new_freq); +static void unboost_cpu(int cpu); +#endif +static cputime64_t mpdec_paused_until = 0; -static int msm_mpd_enabled = 1; -module_param_named(enabled, msm_mpd_enabled, int, S_IRUGO | S_IWUSR | S_IWGRP); +static unsigned long get_rate(int cpu) { + return acpuclk_get_rate(cpu); +} + +static int get_slowest_cpu(void) { + int i, cpu = 0; + unsigned long rate, slow_rate = 0; + + for (i = 1; i < CONFIG_NR_CPUS; i++) { + if (!cpu_online(i)) + continue; + rate = get_rate(i); + if (slow_rate == 0) { + slow_rate = rate; + } + if ((rate <= slow_rate) && (slow_rate != 0)) { + cpu = i; + slow_rate = rate; + } + } + + return cpu; +} -static struct dentry *debugfs_base; -static struct mpdecision msm_mpd; +static unsigned long get_slowest_cpu_rate(void) { + int i = 0; + unsigned long rate, slow_rate = 0; + + for (i = 0; i < CONFIG_NR_CPUS; i++) { + if (!cpu_online(i)) + continue; + rate = get_rate(i); + if ((rate < slow_rate) && (slow_rate != 0)) { + slow_rate = rate; + } + if (slow_rate == 0) { + slow_rate = rate; + } + } + + return slow_rate; +} -static struct hp_latency hp_latencies; +static void mpdec_cpu_up(int cpu) { + if (!cpu_online(cpu)) { + mutex_lock(&per_cpu(msm_mpdec_cpudata, cpu).hotplug_mutex); + cpu_up(cpu); + per_cpu(msm_mpdec_cpudata, cpu).on_time = ktime_to_ms(ktime_get()); + per_cpu(msm_mpdec_cpudata, cpu).online = true; + per_cpu(msm_mpdec_cpudata, cpu).times_cpu_hotplugged += 1; + pr_info(MPDEC_TAG"CPU[%d] off->on | Mask=[%d%d%d%d]\n", + cpu, cpu_online(0), cpu_online(1), cpu_online(2), cpu_online(3)); + mutex_unlock(&per_cpu(msm_mpdec_cpudata, cpu).hotplug_mutex); + } +} +EXPORT_SYMBOL_GPL(mpdec_cpu_up); + +static void mpdec_cpu_down(int cpu) { + cputime64_t on_time = 0; + if (cpu_online(cpu)) { + mutex_lock(&per_cpu(msm_mpdec_cpudata, cpu).hotplug_mutex); + cpu_down(cpu); + on_time = (ktime_to_ms(ktime_get()) - per_cpu(msm_mpdec_cpudata, cpu).on_time); + per_cpu(msm_mpdec_cpudata, cpu).online = false; + per_cpu(msm_mpdec_cpudata, cpu).on_time_total += on_time; + per_cpu(msm_mpdec_cpudata, cpu).times_cpu_unplugged += 1; + pr_info(MPDEC_TAG"CPU[%d] on->off | Mask=[%d%d%d%d] | time online: %llu\n", + cpu, cpu_online(0), cpu_online(1), cpu_online(2), cpu_online(3), on_time); + mutex_unlock(&per_cpu(msm_mpdec_cpudata, cpu).hotplug_mutex); + } +} +EXPORT_SYMBOL_GPL(mpdec_cpu_down); + +static int mp_decision(void) { + static bool first_call = true; + int new_state = MSM_MPDEC_IDLE; + int nr_cpu_online; + int index; + unsigned int rq_depth; + static cputime64_t total_time = 0; + static cputime64_t last_time; + cputime64_t current_time; + cputime64_t this_time = 0; + + if (state == MSM_MPDEC_DISABLED) + return MSM_MPDEC_DISABLED; + + current_time = ktime_to_ms(ktime_get()); + if (current_time <= msm_mpdec_tuners_ins.startdelay) + return MSM_MPDEC_IDLE; + + if (first_call) { + first_call = false; + } else { + this_time = current_time - last_time; + } + total_time += this_time; + + rq_depth = get_rq_info(); + nr_cpu_online = num_online_cpus(); + + if (nr_cpu_online) { + index = (nr_cpu_online - 1) * 2; + if ((nr_cpu_online < CONFIG_NR_CPUS) && (rq_depth >= NwNs_Threshold[index])) { + if ((total_time >= TwTs_Threshold[index]) && + (nr_cpu_online < msm_mpdec_tuners_ins.max_cpus)) { + new_state = MSM_MPDEC_UP; + if (get_slowest_cpu_rate() <= msm_mpdec_tuners_ins.idle_freq) + new_state = MSM_MPDEC_IDLE; + } + } else if ((nr_cpu_online > 1) && (rq_depth <= NwNs_Threshold[index+1])) { + if ((total_time >= TwTs_Threshold[index+1]) && + (nr_cpu_online > msm_mpdec_tuners_ins.min_cpus)) { + new_state = MSM_MPDEC_DOWN; + if (get_slowest_cpu_rate() > msm_mpdec_tuners_ins.idle_freq) + new_state = MSM_MPDEC_IDLE; + } + } else { + new_state = MSM_MPDEC_IDLE; + total_time = 0; + } + } else { + total_time = 0; + } + + if (new_state != MSM_MPDEC_IDLE) { + total_time = 0; + } + + last_time = ktime_to_ms(ktime_get()); +#if DEBUG + pr_info(MPDEC_TAG"[DEBUG] rq: %u, new_state: %i | Mask=[%d%d%d%d]\n", + rq_depth, new_state, cpu_online(0), cpu_online(1), cpu_online(2), cpu_online(3)); +#endif + return new_state; +} -static unsigned long last_nr; -static int num_present_hundreds; -static ktime_t last_down_time; +static void msm_mpdec_work_thread(struct work_struct *work) { + unsigned int cpu = nr_cpu_ids; + bool suspended = false; + + if (ktime_to_ms(ktime_get()) <= msm_mpdec_tuners_ins.startdelay) + goto out; + + /* Check if we are paused */ + if (mpdec_paused_until >= ktime_to_ms(ktime_get())) + goto out; + + for_each_possible_cpu(cpu) { + if ((per_cpu(msm_mpdec_cpudata, cpu).device_suspended == true)) { + suspended = true; + break; + } + } + if (suspended == true) + goto out; + + if (!mutex_trylock(&mpdec_msm_cpu_lock)) + goto out; + + /* if sth messed with the cpus, update the check vars so we can proceed */ + if (was_paused) { + for_each_possible_cpu(cpu) { + if (cpu_online(cpu)) + per_cpu(msm_mpdec_cpudata, cpu).online = true; + else if (!cpu_online(cpu)) + per_cpu(msm_mpdec_cpudata, cpu).online = false; + } + was_paused = false; + } + + state = mp_decision(); + switch (state) { + case MSM_MPDEC_DISABLED: + case MSM_MPDEC_IDLE: + break; + case MSM_MPDEC_DOWN: + cpu = get_slowest_cpu(); + if (cpu < nr_cpu_ids) { + if ((per_cpu(msm_mpdec_cpudata, cpu).online == true) && (cpu_online(cpu))) { +#ifdef CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN + unboost_cpu(cpu); +#endif + mpdec_cpu_down(cpu); + } else if (per_cpu(msm_mpdec_cpudata, cpu).online != cpu_online(cpu)) { + pr_info(MPDEC_TAG"CPU[%d] was controlled outside of mpdecision! | pausing [%d]ms\n", + cpu, msm_mpdec_tuners_ins.pause); + mpdec_paused_until = ktime_to_ms(ktime_get()) + msm_mpdec_tuners_ins.pause; + was_paused = true; + } + } + break; + case MSM_MPDEC_UP: + cpu = cpumask_next_zero(0, cpu_online_mask); + if (cpu < nr_cpu_ids) { + if ((per_cpu(msm_mpdec_cpudata, cpu).online == false) && (!cpu_online(cpu))) { + mpdec_cpu_up(cpu); +#ifdef CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN + unboost_cpu(cpu); +#endif + } else if (per_cpu(msm_mpdec_cpudata, cpu).online != cpu_online(cpu)) { + pr_info(MPDEC_TAG"CPU[%d] was controlled outside of mpdecision! | pausing [%d]ms\n", + cpu, msm_mpdec_tuners_ins.pause); + mpdec_paused_until = ktime_to_ms(ktime_get()) + msm_mpdec_tuners_ins.pause; + was_paused = true; + } + } + break; + default: + pr_err(MPDEC_TAG"%s: invalid mpdec hotplug state %d\n", + __func__, state); + } + mutex_unlock(&mpdec_msm_cpu_lock); -static bool ok_to_update_tz(int nr, int last_nr) -{ - /* - * Exclude unnecessary TZ reports if run queue haven't changed much from - * the last reported value. The divison by rq_avg_divide is to - * filter out small changes in the run queue average which won't cause - * a online cpu mask change. Also if the cpu online count does not match - * the count requested by TZ and we are not in the process of bringing - * cpus online as indicated by a HPUPDATE_IN_PROGRESS in msm_mpd.hpdata - */ - return - (((nr / msm_mpd.rq_avg_divide) - != (last_nr / msm_mpd.rq_avg_divide)) - || ((hweight32(atomic_read(&msm_mpd.algo_cpu_mask)) - != num_online_cpus()) - && (msm_mpd.hpupdate != HPUPDATE_IN_PROGRESS))); -} - -static enum hrtimer_restart msm_mpd_rq_avg_poll_timer(struct hrtimer *timer) -{ - int nr, nr_iowait; - ktime_t curr_time = ktime_get(); - unsigned long flags; - int cpu = smp_processor_id(); - enum hrtimer_restart restart = HRTIMER_RESTART; +out: + if (state != MSM_MPDEC_DISABLED) + queue_delayed_work(msm_mpdec_workq, &msm_mpdec_work, + msecs_to_jiffies(msm_mpdec_tuners_ins.delay)); + return; +} - spin_lock_irqsave(&rq_avg_lock, flags); - /* If running on the wrong cpu, don't restart */ - if (&per_cpu(rq_avg_poll_timer, cpu) != timer) - restart = HRTIMER_NORESTART; +#ifdef CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN +static int update_cpu_min_freq(struct cpufreq_policy *cpu_policy, + int cpu, int new_freq) { + int ret = 0; - if (ktime_to_ns(ktime_sub(curr_time, msm_mpd.next_update)) < 0) - goto out; + if (!cpu_policy) + return -EINVAL; - msm_mpd.next_update = ktime_add_ns(curr_time, - (msm_mpd.rq_avg_poll_ms * NSEC_PER_MSEC)); + cpufreq_verify_within_limits(cpu_policy, new_freq, cpu_policy->max); + cpu_policy->user_policy.min = new_freq; - sched_get_nr_running_avg(&nr, &nr_iowait); + ret = cpufreq_update_policy(cpu); + if (!ret) { + pr_debug(MPDEC_TAG"Touch event! Setting CPU%d min frequency to %d\n", + cpu, new_freq); + } + return ret; +} - if ((nr_iowait >= msm_mpd.iowait_threshold_pct) && (nr < last_nr)) - nr = last_nr; +static void unboost_cpu(int cpu) { + struct cpufreq_policy *cpu_policy = NULL; + + if (cpu_online(cpu)) { + if (per_cpu(msm_mpdec_cpudata, cpu).is_boosted) { + if (mutex_trylock(&per_cpu(msm_mpdec_cpudata, cpu).unboost_mutex)) { + cpu_policy = cpufreq_cpu_get(cpu); + if (!cpu_policy) { + pr_debug(MPDEC_TAG"NULL policy on cpu %d\n", cpu); + return; + } +#if DEBUG + pr_info(MPDEC_TAG"un boosted cpu%i to %lu", cpu, per_cpu(msm_mpdec_cpudata, cpu).norm_min_freq); +#endif + per_cpu(msm_mpdec_cpudata, cpu).is_boosted = false; + per_cpu(msm_mpdec_cpudata, cpu).revib_wq_running = false; + if ((cpu_policy->min != per_cpu(msm_mpdec_cpudata, cpu).boost_freq) && + (cpu_policy->min != per_cpu(msm_mpdec_cpudata, cpu).norm_min_freq)) { + pr_info(MPDEC_TAG"cpu%u min was changed while boosted (%lu->%u), using new min", + cpu, per_cpu(msm_mpdec_cpudata, cpu).norm_min_freq, cpu_policy->min); + per_cpu(msm_mpdec_cpudata, cpu).norm_min_freq = cpu_policy->min; + } + update_cpu_min_freq(cpu_policy, cpu, per_cpu(msm_mpdec_cpudata, cpu).norm_min_freq); + cpufreq_cpu_put(cpu_policy); + mutex_unlock(&per_cpu(msm_mpdec_cpudata, cpu).unboost_mutex); + } + } + } + + return; +} - if (nr > num_present_hundreds) - nr = num_present_hundreds; +static void msm_mpdec_revib_work_thread(struct work_struct *work) { + int cpu = smp_processor_id(); + + if (per_cpu(msm_mpdec_cpudata, cpu).is_boosted) { + per_cpu(msm_mpdec_cpudata, cpu).revib_wq_running = true; + if (ktime_to_ms(ktime_get()) > per_cpu(msm_mpdec_cpudata, cpu).boost_until) { + unboost_cpu(cpu); + } else { + queue_delayed_work_on(cpu, + msm_mpdec_revib_workq, + &per_cpu(msm_mpdec_revib_work, cpu), + msecs_to_jiffies((per_cpu(msm_mpdec_cpudata, cpu).boost_until - ktime_to_ms(ktime_get())))); + } + } else { + per_cpu(msm_mpdec_cpudata, cpu).revib_wq_running = false; + } + return; +} - trace_msm_mp_runq("nr_running", nr); +static void mpdec_input_callback(struct work_struct *unused) { + struct cpufreq_policy *cpu_policy = NULL; + int cpu = smp_processor_id(); + bool boosted = false; + + if (!per_cpu(msm_mpdec_cpudata, cpu).is_boosted) { + if (mutex_trylock(&per_cpu(msm_mpdec_cpudata, cpu).boost_mutex)) { + cpu_policy = cpufreq_cpu_get(cpu); + if (!cpu_policy) { + pr_debug(MPDEC_TAG"NULL policy on cpu %d\n", cpu); + return; + } + per_cpu(msm_mpdec_cpudata, cpu).norm_min_freq = cpu_policy->min; + update_cpu_min_freq(cpu_policy, cpu, per_cpu(msm_mpdec_cpudata, cpu).boost_freq); +#if DEBUG + pr_info(MPDEC_TAG"boosted cpu%i to %lu", cpu, per_cpu(msm_mpdec_cpudata, cpu).boost_freq); +#endif + per_cpu(msm_mpdec_cpudata, cpu).is_boosted = true; + per_cpu(msm_mpdec_cpudata, cpu).boost_until = ktime_to_ms(ktime_get()) + MSM_MPDEC_BOOSTTIME; + boosted = true; + cpufreq_cpu_put(cpu_policy); + mutex_unlock(&per_cpu(msm_mpdec_cpudata, cpu).boost_mutex); + } + } else { + boosted = true; + } + if (boosted && !per_cpu(msm_mpdec_cpudata, cpu).revib_wq_running) { + per_cpu(msm_mpdec_cpudata, cpu).revib_wq_running = true; + queue_delayed_work_on(cpu, + msm_mpdec_revib_workq, + &per_cpu(msm_mpdec_revib_work, cpu), + msecs_to_jiffies(MSM_MPDEC_BOOSTTIME)); + } else if (boosted && per_cpu(msm_mpdec_cpudata, cpu).revib_wq_running) { + per_cpu(msm_mpdec_cpudata, cpu).boost_until = ktime_to_ms(ktime_get()) + MSM_MPDEC_BOOSTTIME; + } + + return; +} - if (ok_to_update_tz(nr, last_nr)) { - hrtimer_try_to_cancel(&msm_mpd.slack_timer); - msm_mpd.data.nr = nr; - msm_mpd.data.event = MSM_DCVS_SCM_RUNQ_UPDATE; - wake_up(&msm_mpd.wait_q); - last_nr = nr; - } +static void mpdec_input_event(struct input_handle *handle, unsigned int type, + unsigned int code, int value) { + int i = 0; -out: - hrtimer_set_expires(timer, msm_mpd.next_update); - spin_unlock_irqrestore(&rq_avg_lock, flags); - /* set next expiration */ - return restart; + if (!msm_mpdec_tuners_ins.boost_enabled) + return; + + if (!is_screen_on) + return; + + for_each_online_cpu(i) { + queue_work_on(i, mpdec_input_wq, &per_cpu(mpdec_input_work, i)); + } +} + +static int input_dev_filter(const char *input_dev_name) { + if (strstr(input_dev_name, "touch") || + strstr(input_dev_name, "keypad")) { + return 0; + } else { + return 1; + } +} + +static int mpdec_input_connect(struct input_handler *handler, + struct input_dev *dev, const struct input_device_id *id) { + struct input_handle *handle; + int error; + + if (input_dev_filter(dev->name)) + return -ENODEV; + + handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL); + if (!handle) + return -ENOMEM; + + handle->dev = dev; + handle->handler = handler; + handle->name = "mpdec"; + + error = input_register_handle(handle); + if (error) + goto err2; + + error = input_open_device(handle); + if (error) + goto err1; + + return 0; +err1: + input_unregister_handle(handle); +err2: + kfree(handle); + return error; +} + +static void mpdec_input_disconnect(struct input_handle *handle) { + input_close_device(handle); + input_unregister_handle(handle); + kfree(handle); +} + +static const struct input_device_id mpdec_ids[] = { + { .driver_info = 1 }, + { }, +}; + +static struct input_handler mpdec_input_handler = { + .event = mpdec_input_event, + .connect = mpdec_input_connect, + .disconnect = mpdec_input_disconnect, + .name = "mpdec_inputreq", + .id_table = mpdec_ids, +}; +#endif + +static void msm_mpdec_early_suspend(struct early_suspend *h) { + int cpu = nr_cpu_ids; +#ifdef CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN + is_screen_on = false; +#endif + + if (!msm_mpdec_tuners_ins.scroff_single_core) { + pr_info(MPDEC_TAG"Screen -> off\n"); + return; + } + + /* main work thread can sleep now */ + cancel_delayed_work_sync(&msm_mpdec_work); + + for_each_possible_cpu(cpu) { +#ifdef CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN + unboost_cpu(cpu); +#endif + if ((cpu >= 1) && (cpu_online(cpu))) { + mpdec_cpu_down(cpu); + } + per_cpu(msm_mpdec_cpudata, cpu).device_suspended = true; + } + + pr_info(MPDEC_TAG"Screen -> off. Deactivated mpdecision.\n"); } -static void bring_up_cpu(int cpu) +static void msm_mpdec_late_resume(struct early_suspend *h) { + int cpu = nr_cpu_ids; +#ifdef CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN + is_screen_on = true; +#endif + + for_each_possible_cpu(cpu) + per_cpu(msm_mpdec_cpudata, cpu).device_suspended = false; + + if (msm_mpdec_tuners_ins.scroff_single_core) { + /* wake up main work thread */ + was_paused = true; + queue_delayed_work(msm_mpdec_workq, &msm_mpdec_work, 0); + + /* restore min/max cpus limits */ + for (cpu=1; cpu msm_mpdec_tuners_ins.max_cpus) { + if (cpu_online(cpu)) + mpdec_cpu_down(cpu); + } + } + + pr_info(MPDEC_TAG"Screen -> on. Activated mpdecision. | Mask=[%d%d%d%d]\n", + cpu_online(0), cpu_online(1), cpu_online(2), cpu_online(3)); + } else { + pr_info(MPDEC_TAG"Screen -> on\n"); + } +} + +static struct early_suspend msm_mpdec_early_suspend_handler = { + .level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN, + .suspend = msm_mpdec_early_suspend, + .resume = msm_mpdec_late_resume, +}; + +/**************************** SYSFS START ****************************/ +struct kobject *msm_mpdec_kobject; + +#define show_one(file_name, object) \ +static ssize_t show_##file_name \ +(struct kobject *kobj, struct attribute *attr, char *buf) \ +{ \ + return sprintf(buf, "%u\n", msm_mpdec_tuners_ins.object); \ +} + +show_one(startdelay, startdelay); +show_one(delay, delay); +show_one(pause, pause); +show_one(scroff_single_core, scroff_single_core); +show_one(min_cpus, min_cpus); +show_one(max_cpus, max_cpus); +#ifdef CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN +show_one(boost_enabled, boost_enabled); +show_one(boost_time, boost_time); +#endif + +#define show_one_twts(file_name, arraypos) \ +static ssize_t show_##file_name \ +(struct kobject *kobj, struct attribute *attr, char *buf) \ +{ \ + return sprintf(buf, "%u\n", TwTs_Threshold[arraypos]); \ +} +show_one_twts(twts_threshold_0, 0); +show_one_twts(twts_threshold_1, 1); +show_one_twts(twts_threshold_2, 2); +show_one_twts(twts_threshold_3, 3); +show_one_twts(twts_threshold_4, 4); +show_one_twts(twts_threshold_5, 5); +show_one_twts(twts_threshold_6, 6); +show_one_twts(twts_threshold_7, 7); + +#define store_one_twts(file_name, arraypos) \ +static ssize_t store_##file_name \ +(struct kobject *a, struct attribute *b, const char *buf, size_t count) \ +{ \ + unsigned int input; \ + int ret; \ + ret = sscanf(buf, "%u", &input); \ + if (ret != 1) \ + return -EINVAL; \ + TwTs_Threshold[arraypos] = input; \ + return count; \ +} \ +define_one_global_rw(file_name); +store_one_twts(twts_threshold_0, 0); +store_one_twts(twts_threshold_1, 1); +store_one_twts(twts_threshold_2, 2); +store_one_twts(twts_threshold_3, 3); +store_one_twts(twts_threshold_4, 4); +store_one_twts(twts_threshold_5, 5); +store_one_twts(twts_threshold_6, 6); +store_one_twts(twts_threshold_7, 7); + +#define show_one_nwns(file_name, arraypos) \ +static ssize_t show_##file_name \ +(struct kobject *kobj, struct attribute *attr, char *buf) \ +{ \ + return sprintf(buf, "%u\n", NwNs_Threshold[arraypos]); \ +} +show_one_nwns(nwns_threshold_0, 0); +show_one_nwns(nwns_threshold_1, 1); +show_one_nwns(nwns_threshold_2, 2); +show_one_nwns(nwns_threshold_3, 3); +show_one_nwns(nwns_threshold_4, 4); +show_one_nwns(nwns_threshold_5, 5); +show_one_nwns(nwns_threshold_6, 6); +show_one_nwns(nwns_threshold_7, 7); + +#define store_one_nwns(file_name, arraypos) \ +static ssize_t store_##file_name \ +(struct kobject *a, struct attribute *b, const char *buf, size_t count) \ +{ \ + unsigned int input; \ + int ret; \ + ret = sscanf(buf, "%u", &input); \ + if (ret != 1) \ + return -EINVAL; \ + NwNs_Threshold[arraypos] = input; \ + return count; \ +} \ +define_one_global_rw(file_name); +store_one_nwns(nwns_threshold_0, 0); +store_one_nwns(nwns_threshold_1, 1); +store_one_nwns(nwns_threshold_2, 2); +store_one_nwns(nwns_threshold_3, 3); +store_one_nwns(nwns_threshold_4, 4); +store_one_nwns(nwns_threshold_5, 5); +store_one_nwns(nwns_threshold_6, 6); +store_one_nwns(nwns_threshold_7, 7); + +static ssize_t show_idle_freq (struct kobject *kobj, struct attribute *attr, + char *buf) { - int cpu_action_time_ms; - int time_taken_ms; - int ret, ret1, ret2; - - cpu_action_time_ms = ktime_to_ms(ktime_get()); - ret = cpu_up(cpu); - if (ret) { - pr_debug("Error %d online core %d\n", ret, cpu); - } else { - time_taken_ms = ktime_to_ms(ktime_get()) - cpu_action_time_ms; - if (time_taken_ms > hp_latencies.hp_up_max_ms) - hp_latencies.hp_up_max_ms = time_taken_ms; - hp_latencies.hp_up_ms += time_taken_ms; - hp_latencies.hp_up_count++; - ret = msm_dcvs_scm_event( - CPU_OFFSET + cpu, - MSM_DCVS_SCM_CORE_ONLINE, - cpufreq_get(cpu), - (uint32_t) time_taken_ms * USEC_PER_MSEC, - &ret1, &ret2); - if (ret) - pr_err("Error sending hotplug scm event err=%d\n", ret); - } -} - -static void bring_down_cpu(int cpu) + return sprintf(buf, "%lu\n", msm_mpdec_tuners_ins.idle_freq); +} + +static ssize_t show_enabled(struct kobject *a, struct attribute *b, + char *buf) { - int cpu_action_time_ms; - int time_taken_ms; - int ret, ret1, ret2; - - BUG_ON(cpu == 0); - cpu_action_time_ms = ktime_to_ms(ktime_get()); - ret = cpu_down(cpu); - if (ret) { - pr_debug("Error %d offline" "core %d\n", ret, cpu); - } else { - time_taken_ms = ktime_to_ms(ktime_get()) - cpu_action_time_ms; - if (time_taken_ms > hp_latencies.hp_dw_max_ms) - hp_latencies.hp_dw_max_ms = time_taken_ms; - hp_latencies.hp_dw_ms += time_taken_ms; - hp_latencies.hp_dw_count++; - ret = msm_dcvs_scm_event( - CPU_OFFSET + cpu, - MSM_DCVS_SCM_CORE_OFFLINE, - (uint32_t) time_taken_ms * USEC_PER_MSEC, - 0, - &ret1, &ret2); - if (ret) - pr_err("Error sending hotplug scm event err=%d\n", ret); - } -} - -static int __ref msm_mpd_update_scm(enum msm_dcvs_scm_event event, int nr) + unsigned int enabled; + switch (state) { + case MSM_MPDEC_DISABLED: + enabled = 0; + break; + case MSM_MPDEC_IDLE: + case MSM_MPDEC_DOWN: + case MSM_MPDEC_UP: + enabled = 1; + break; + default: + enabled = 333; + } + return sprintf(buf, "%u\n", enabled); +} + +static ssize_t store_startdelay(struct kobject *a, struct attribute *b, + const char *buf, size_t count) { - int ret = 0; - uint32_t req_cpu_mask = 0; - uint32_t slack_us = 0; - uint32_t param0 = 0; - - if (event == MSM_DCVS_SCM_RUNQ_UPDATE) - param0 = nr; - - ret = msm_dcvs_scm_event(0, event, param0, 0, - &req_cpu_mask, &slack_us); - - if (ret) { - pr_err("Error (%d) sending event %d, param %d\n", ret, event, - param0); - return ret; - } - - trace_msm_mp_cpusonline("cpu_online_mp", req_cpu_mask); - trace_msm_mp_slacktime("slack_time_mp", slack_us); - msm_mpd.slack_us = slack_us; - atomic_set(&msm_mpd.algo_cpu_mask, req_cpu_mask); - msm_mpd.hpupdate = HPUPDATE_SCHEDULED; - wake_up(&msm_mpd.wait_hpq); - - /* Start MP Decision slack timer */ - if (slack_us) { - hrtimer_cancel(&msm_mpd.slack_timer); - ret = hrtimer_start(&msm_mpd.slack_timer, - ktime_set(0, slack_us * NSEC_PER_USEC), - HRTIMER_MODE_REL_PINNED); - if (ret) - pr_err("Failed to register slack timer (%d) %d\n", - slack_us, ret); - } - - return ret; -} - -static enum hrtimer_restart msm_mpd_slack_timer(struct hrtimer *timer) + unsigned int input; + int ret; + ret = sscanf(buf, "%u", &input); + if (ret != 1) + return -EINVAL; + + msm_mpdec_tuners_ins.startdelay = input; + + return count; +} + +static ssize_t store_delay(struct kobject *a, struct attribute *b, + const char *buf, size_t count) { - unsigned long flags; + unsigned int input; + int ret; + ret = sscanf(buf, "%u", &input); + if (ret != 1) + return -EINVAL; - trace_printk("mpd:slack_timer_fired!\n"); + msm_mpdec_tuners_ins.delay = input; - spin_lock_irqsave(&rq_avg_lock, flags); - if (msm_mpd.data.event == MSM_DCVS_SCM_RUNQ_UPDATE) - goto out; + return count; +} - msm_mpd.data.nr = 0; - msm_mpd.data.event = MSM_DCVS_SCM_MPD_QOS_TIMER_EXPIRED; - wake_up(&msm_mpd.wait_q); -out: - spin_unlock_irqrestore(&rq_avg_lock, flags); - return HRTIMER_NORESTART; +static ssize_t store_pause(struct kobject *a, struct attribute *b, + const char *buf, size_t count) +{ + unsigned int input; + int ret; + ret = sscanf(buf, "%u", &input); + if (ret != 1) + return -EINVAL; + + msm_mpdec_tuners_ins.pause = input; + + return count; } -static int msm_mpd_idle_notifier(struct notifier_block *self, - unsigned long cmd, void *v) +static ssize_t store_idle_freq(struct kobject *a, struct attribute *b, + const char *buf, size_t count) { - int cpu = smp_processor_id(); - unsigned long flags; - - switch (cmd) { - case CPU_PM_EXIT: - spin_lock_irqsave(&rq_avg_lock, flags); - hrtimer_start(&per_cpu(rq_avg_poll_timer, cpu), - msm_mpd.next_update, - HRTIMER_MODE_ABS_PINNED); - spin_unlock_irqrestore(&rq_avg_lock, flags); - break; - case CPU_PM_ENTER: - hrtimer_cancel(&per_cpu(rq_avg_poll_timer, cpu)); - break; - default: - break; - } - - return NOTIFY_OK; -} - -static int msm_mpd_hotplug_notifier(struct notifier_block *self, - unsigned long action, void *hcpu) + long unsigned int input; + int ret; + ret = sscanf(buf, "%lu", &input); + if (ret != 1) + return -EINVAL; + + msm_mpdec_tuners_ins.idle_freq = input; + + return count; +} + +static ssize_t store_scroff_single_core(struct kobject *a, struct attribute *b, + const char *buf, size_t count) { - int cpu = (int)hcpu; - unsigned long flags; - - switch (action & (~CPU_TASKS_FROZEN)) { - case CPU_STARTING: - spin_lock_irqsave(&rq_avg_lock, flags); - hrtimer_start(&per_cpu(rq_avg_poll_timer, cpu), - msm_mpd.next_update, - HRTIMER_MODE_ABS_PINNED); - spin_unlock_irqrestore(&rq_avg_lock, flags); - break; - default: - break; - } - - return NOTIFY_OK; -} - -static struct notifier_block msm_mpd_idle_nb = { - .notifier_call = msm_mpd_idle_notifier, -}; + unsigned int input; + int ret; + ret = sscanf(buf, "%u", &input); + if (ret != 1) + return -EINVAL; + switch (buf[0]) { + case '0': + case '1': + msm_mpdec_tuners_ins.scroff_single_core = input; + break; + default: + ret = -EINVAL; + } + return count; +} -static struct notifier_block msm_mpd_hotplug_nb = { - .notifier_call = msm_mpd_hotplug_notifier, -}; +static ssize_t store_max_cpus(struct kobject *a, struct attribute *b, + const char *buf, size_t count) +{ + unsigned int input; + int ret, cpu; + ret = sscanf(buf, "%u", &input); + if ((ret != 1) || input > CONFIG_NR_CPUS || input < msm_mpdec_tuners_ins.min_cpus) + return -EINVAL; + + msm_mpdec_tuners_ins.max_cpus = input; + if (num_online_cpus() > input) { + for (cpu=CONFIG_NR_CPUS; cpu>0; cpu--) { + if (num_online_cpus() <= input) + break; + if (!cpu_online(cpu)) + continue; + mpdec_cpu_down(cpu); + } + pr_info(MPDEC_TAG"max_cpus set to %u. Affected CPUs were unplugged!\n", input); + } + + return count; +} -static int __cpuinit msm_mpd_do_hotplug(void *data) +static ssize_t store_min_cpus(struct kobject *a, struct attribute *b, + const char *buf, size_t count) { - int *event = (int *)data; - int cpu; - - while (1) { - wait_event(msm_mpd.wait_hpq, *event || kthread_should_stop()); - if (kthread_should_stop()) - break; - - msm_mpd.hpupdate = HPUPDATE_IN_PROGRESS; - /* - * Bring online any offline cores, then offline any online - * cores. Whenever a core is off/onlined restart the procedure - * in case a new core is desired to be brought online in the - * mean time. - */ -restart: - for_each_possible_cpu(cpu) { - if ((atomic_read(&msm_mpd.algo_cpu_mask) & (1 << cpu)) - && !cpu_online(cpu)) { - bring_up_cpu(cpu); - if (cpu_online(cpu)) - goto restart; - } - } - - if (ktime_to_ns(ktime_sub(ktime_get(), last_down_time)) > - 100 * NSEC_PER_MSEC) - for_each_possible_cpu(cpu) - if (!(atomic_read(&msm_mpd.algo_cpu_mask) & - (1 << cpu)) && cpu_online(cpu)) { - bring_down_cpu(cpu); - last_down_time = ktime_get(); - break; - } - msm_mpd.hpupdate = HPUPDATE_WAITING; - msm_dcvs_apply_gpu_floor(0); - msm_dcvs_update_algo_params(); - } - - return 0; -} - -static int msm_mpd_do_update_scm(void *data) + unsigned int input; + int ret, cpu; + ret = sscanf(buf, "%u", &input); + if ((ret != 1) || input < 1 || input > msm_mpdec_tuners_ins.max_cpus) + return -EINVAL; + + msm_mpdec_tuners_ins.min_cpus = input; + if (num_online_cpus() < input) { + for (cpu=1; cpu= input) + break; + if (cpu_online(cpu)) + continue; + mpdec_cpu_up(cpu); + } + pr_info(MPDEC_TAG"min_cpus set to %u. Affected CPUs were hotplugged!\n", input); + } + + return count; +} + +static ssize_t store_enabled(struct kobject *a, struct attribute *b, + const char *buf, size_t count) { - struct msm_mpd_scm_data *scm_data = (struct msm_mpd_scm_data *)data; - unsigned long flags; - enum msm_dcvs_scm_event event; - int nr; + unsigned int cpu, input, enabled; + int ret; + ret = sscanf(buf, "%u", &input); + if (ret != 1) + return -EINVAL; + + switch (state) { + case MSM_MPDEC_DISABLED: + enabled = 0; + break; + case MSM_MPDEC_IDLE: + case MSM_MPDEC_DOWN: + case MSM_MPDEC_UP: + enabled = 1; + break; + default: + enabled = 333; + } + + if (buf[0] == enabled) + return -EINVAL; + + switch (buf[0]) { + case '0': + state = MSM_MPDEC_DISABLED; + pr_info(MPDEC_TAG"nap time... Hot plugging offline CPUs...\n"); + for (cpu = 1; cpu < CONFIG_NR_CPUS; cpu++) + if (!cpu_online(cpu)) + mpdec_cpu_up(cpu); + break; + case '1': + state = MSM_MPDEC_IDLE; + was_paused = true; + queue_delayed_work(msm_mpdec_workq, &msm_mpdec_work, + msecs_to_jiffies(msm_mpdec_tuners_ins.delay)); + pr_info(MPDEC_TAG"firing up mpdecision...\n"); + break; + default: + ret = -EINVAL; + } + return count; +} - while (1) { - wait_event(msm_mpd.wait_q, - msm_mpd.data.event == MSM_DCVS_SCM_MPD_QOS_TIMER_EXPIRED - || msm_mpd.data.event == MSM_DCVS_SCM_RUNQ_UPDATE - || kthread_should_stop()); +#ifdef CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN +static ssize_t store_boost_enabled(struct kobject *a, struct attribute *b, + const char *buf, size_t count) +{ + unsigned int input; + int ret; + ret = sscanf(buf, "%u", &input); + if (ret != 1) + return -EINVAL; + + msm_mpdec_tuners_ins.boost_enabled = input; + + return count; +} - if (kthread_should_stop()) - break; +static ssize_t store_boost_time(struct kobject *a, struct attribute *b, + const char *buf, size_t count) +{ + unsigned int input; + int ret; + ret = sscanf(buf, "%u", &input); + if (ret != 1) + return -EINVAL; - spin_lock_irqsave(&rq_avg_lock, flags); - event = scm_data->event; - nr = scm_data->nr; - scm_data->event = 0; - scm_data->nr = 0; - spin_unlock_irqrestore(&rq_avg_lock, flags); + msm_mpdec_tuners_ins.boost_time = input; - msm_mpd_update_scm(event, nr); - } - return 0; + return count; } -static int __ref msm_mpd_set_enabled(uint32_t enable) +static ssize_t show_boost_freqs(struct kobject *a, struct attribute *b, + char *buf) { - int ret = 0; - int ret0 = 0; - int ret1 = 0; - int cpu; - static uint32_t last_enable; - - enable = (enable > 0) ? 1 : 0; - if (last_enable == enable) - return ret; - - if (enable) { - ret = msm_mpd_scm_set_algo_params(&msm_mpd.mp_param); - if (ret) { - pr_err("Error(%d): msm_mpd_scm_set_algo_params failed\n", - ret); - return ret; - } - } - - ret = msm_dcvs_scm_event(0, MSM_DCVS_SCM_MPD_ENABLE, enable, 0, - &ret0, &ret1); - if (ret) { - pr_err("Error(%d) %s MP Decision\n", - ret, (enable ? "enabling" : "disabling")); - } else { - last_enable = enable; - last_nr = 0; - } - if (enable) { - msm_mpd.next_update = ktime_add_ns(ktime_get(), - (msm_mpd.rq_avg_poll_ms * NSEC_PER_MSEC)); - msm_mpd.task = kthread_run(msm_mpd_do_update_scm, - &msm_mpd.data, "msm_mpdecision"); - if (IS_ERR(msm_mpd.task)) - return -EFAULT; - - msm_mpd.hptask = kthread_run(msm_mpd_do_hotplug, - &msm_mpd.hpupdate, "msm_hp"); - if (IS_ERR(msm_mpd.hptask)) - return -EFAULT; - - for_each_online_cpu(cpu) - hrtimer_start(&per_cpu(rq_avg_poll_timer, cpu), - msm_mpd.next_update, - HRTIMER_MODE_ABS_PINNED); - cpu_pm_register_notifier(&msm_mpd_idle_nb); - register_cpu_notifier(&msm_mpd_hotplug_nb); - msm_mpd.enabled = 1; - } else { - for_each_online_cpu(cpu) - hrtimer_cancel(&per_cpu(rq_avg_poll_timer, cpu)); - kthread_stop(msm_mpd.hptask); - kthread_stop(msm_mpd.task); - cpu_pm_unregister_notifier(&msm_mpd_idle_nb); - unregister_cpu_notifier(&msm_mpd_hotplug_nb); - msm_mpd.enabled = 0; - } - - return ret; -} - -static int msm_mpd_set_rq_avg_poll_ms(uint32_t val) + ssize_t len = 0; + int cpu = 0; + + for_each_present_cpu(cpu) { + len += sprintf(buf + len, "%lu\n", per_cpu(msm_mpdec_cpudata, cpu).boost_freq); + } + return len; +} +static ssize_t store_boost_freqs(struct kobject *a, struct attribute *b, + const char *buf, size_t count) { - /* - * No need to do anything. Just let the timer set its own next poll - * interval when it next fires. - */ - msm_mpd.rq_avg_poll_ms = val; - return 0; + int i = 0; + unsigned int cpu = 0; + long unsigned int hz = 0; + const char *chz = NULL; + + for (i=0; idev.platform_data; - - module_kobj = kset_find_obj(module_kset, KBUILD_MODNAME); - if (!module_kobj) { - pr_err("Cannot find kobject for module %s\n", KBUILD_MODNAME); - ret = -ENOENT; - goto done; - } - - msm_mpd.attrib.attrib_group.attrs = - kzalloc(attr_count * sizeof(struct attribute *), GFP_KERNEL); - if (!msm_mpd.attrib.attrib_group.attrs) { - ret = -ENOMEM; - goto done; - } - - MPD_RW_ATTRIB(0, enabled); - MPD_RW_ATTRIB(1, rq_avg_poll_ms); - MPD_RW_ATTRIB(2, iowait_threshold_pct); - MPD_RW_ATTRIB(3, rq_avg_divide); - MPD_RW_ATTRIB(4, em_win_size_min_us); - MPD_RW_ATTRIB(5, em_win_size_max_us); - MPD_RW_ATTRIB(6, em_max_util_pct); - MPD_RW_ATTRIB(7, mp_em_rounding_point_min); - MPD_RW_ATTRIB(8, mp_em_rounding_point_max); - MPD_RW_ATTRIB(9, online_util_pct_min); - MPD_RW_ATTRIB(10, online_util_pct_max); - MPD_RW_ATTRIB(11, slack_time_min_us); - MPD_RW_ATTRIB(12, slack_time_max_us); - MPD_RW_ATTRIB(13, hp_up_max_ms); - MPD_RW_ATTRIB(14, hp_up_ms); - MPD_RW_ATTRIB(15, hp_up_count); - MPD_RW_ATTRIB(16, hp_dw_max_ms); - MPD_RW_ATTRIB(17, hp_dw_ms); - MPD_RW_ATTRIB(18, hp_dw_count); - - msm_mpd.attrib.attrib_group.attrs[19] = NULL; - ret = sysfs_create_group(module_kobj, &msm_mpd.attrib.attrib_group); - if (ret) - pr_err("Unable to create sysfs objects :%d\n", ret); - - msm_mpd.rq_avg_poll_ms = DEFAULT_RQ_AVG_POLL_MS; - msm_mpd.rq_avg_divide = DEFAULT_RQ_AVG_DIVIDE; - - memcpy(&msm_mpd.mp_param, param, sizeof(struct msm_mpd_algo_param)); - - debugfs_base = debugfs_create_dir("msm_mpdecision", NULL); - if (!debugfs_base) { - pr_err("Cannot create debugfs base msm_mpdecision\n"); - ret = -ENOENT; - goto done; - } - -done: - if (ret && debugfs_base) - debugfs_remove(debugfs_base); - - return ret; -} - -static int __devexit msm_mpd_remove(struct platform_device *pdev) + ssize_t len = 0; + int cpu = 0; + + for_each_possible_cpu(cpu) { + len += sprintf(buf + len, "%i %llu\n", cpu, per_cpu(msm_mpdec_cpudata, cpu).times_cpu_hotplugged); + } + + return len; +} +define_one_global_ro(times_cpus_hotplugged); + +static ssize_t show_times_cpus_unplugged(struct kobject *a, struct attribute *b, + char *buf) { - platform_set_drvdata(pdev, NULL); + ssize_t len = 0; + int cpu = 0; + + for_each_possible_cpu(cpu) { + len += sprintf(buf + len, "%i %llu\n", cpu, per_cpu(msm_mpdec_cpudata, cpu).times_cpu_unplugged); + } - return 0; + return len; } +define_one_global_ro(times_cpus_unplugged); -static struct platform_driver msm_mpd_driver = { - .probe = msm_mpd_probe, - .remove = __devexit_p(msm_mpd_remove), - .driver = { - .name = "msm_mpdecision", - .owner = THIS_MODULE, - }, +static struct attribute *msm_mpdec_stats_attributes[] = { + &time_cpus_on.attr, + ×_cpus_hotplugged.attr, + ×_cpus_unplugged.attr, + NULL }; -static int __init msm_mpdecision_init(void) -{ - int cpu; - if (!msm_mpd_enabled) { - pr_info("Not enabled\n"); - return 0; - } - - num_present_hundreds = 100 * num_present_cpus(); - - hrtimer_init(&msm_mpd.slack_timer, CLOCK_MONOTONIC, - HRTIMER_MODE_REL_PINNED); - msm_mpd.slack_timer.function = msm_mpd_slack_timer; - - for_each_possible_cpu(cpu) { - hrtimer_init(&per_cpu(rq_avg_poll_timer, cpu), - CLOCK_MONOTONIC, HRTIMER_MODE_ABS_PINNED); - per_cpu(rq_avg_poll_timer, cpu).function - = msm_mpd_rq_avg_poll_timer; - } - mutex_init(&msm_mpd.lock); - init_waitqueue_head(&msm_mpd.wait_q); - init_waitqueue_head(&msm_mpd.wait_hpq); - return platform_driver_register(&msm_mpd_driver); -} -late_initcall(msm_mpdecision_init); + +static struct attribute_group msm_mpdec_stats_attr_group = { + .attrs = msm_mpdec_stats_attributes, + .name = "stats", +}; +/**************************** SYSFS END ****************************/ + +static int __init msm_mpdec_init(void) { + int cpu, rc, err = 0; +#ifdef CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN + int i; + unsigned long int boost_freq = 0; +#endif + + for_each_possible_cpu(cpu) { + mutex_init(&(per_cpu(msm_mpdec_cpudata, cpu).hotplug_mutex)); + per_cpu(msm_mpdec_cpudata, cpu).device_suspended = false; + per_cpu(msm_mpdec_cpudata, cpu).online = true; + per_cpu(msm_mpdec_cpudata, cpu).on_time_total = 0; + per_cpu(msm_mpdec_cpudata, cpu).times_cpu_unplugged = 0; + per_cpu(msm_mpdec_cpudata, cpu).times_cpu_hotplugged = 0; +#ifdef CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN + per_cpu(msm_mpdec_cpudata, cpu).norm_min_freq = CONFIG_MSM_CPU_FREQ_MIN; + switch (cpu) { + case 0: + case 1: + case 2: + boost_freq = msm_mpdec_tuners_ins.boost_freq[cpu]; + break; + default: + boost_freq = msm_mpdec_tuners_ins.boost_freq[3]; + break; + } + per_cpu(msm_mpdec_cpudata, cpu).boost_freq = boost_freq; + per_cpu(msm_mpdec_cpudata, cpu).is_boosted = false; + per_cpu(msm_mpdec_cpudata, cpu).revib_wq_running = false; + per_cpu(msm_mpdec_cpudata, cpu).boost_until = 0; + mutex_init(&(per_cpu(msm_mpdec_cpudata, cpu).boost_mutex)); + mutex_init(&(per_cpu(msm_mpdec_cpudata, cpu).unboost_mutex)); +#endif + } + + was_paused = true; + + msm_mpdec_workq = alloc_workqueue("mpdec", + WQ_UNBOUND | WQ_RESCUER | WQ_FREEZABLE, + 1); + if (!msm_mpdec_workq) + return -ENOMEM; + INIT_DELAYED_WORK(&msm_mpdec_work, msm_mpdec_work_thread); + +#ifdef CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN + mpdec_input_wq = create_workqueue("mpdeciwq"); + if (!mpdec_input_wq) { + printk(KERN_ERR "%s: Failed to create mpdeciwq workqueue\n", __func__); + return -EFAULT; + } + msm_mpdec_revib_workq = create_workqueue("mpdecribwq"); + if (!msm_mpdec_revib_workq) { + printk(KERN_ERR "%s: Failed to create mpdecrevibwq workqueue\n", __func__); + return -EFAULT; + } + for_each_possible_cpu(i) { + INIT_WORK(&per_cpu(mpdec_input_work, i), mpdec_input_callback); + INIT_DELAYED_WORK(&per_cpu(msm_mpdec_revib_work, i), msm_mpdec_revib_work_thread); + } + rc = input_register_handler(&mpdec_input_handler); +#endif + + if (state != MSM_MPDEC_DISABLED) + queue_delayed_work(msm_mpdec_workq, &msm_mpdec_work, + msecs_to_jiffies(msm_mpdec_tuners_ins.delay)); + + register_early_suspend(&msm_mpdec_early_suspend_handler); + + msm_mpdec_kobject = kobject_create_and_add("msm_mpdecision", kernel_kobj); + if (msm_mpdec_kobject) { + rc = sysfs_create_group(msm_mpdec_kobject, + &msm_mpdec_attr_group); + if (rc) { + pr_warn(MPDEC_TAG"sysfs: ERROR, could not create sysfs group"); + } + rc = sysfs_create_group(msm_mpdec_kobject, + &msm_mpdec_stats_attr_group); + if (rc) { + pr_warn(MPDEC_TAG"sysfs: ERROR, could not create sysfs stats group"); + } + } else + pr_warn(MPDEC_TAG"sysfs: ERROR, could not create sysfs kobj"); + + pr_info(MPDEC_TAG"%s init complete.", __func__); + + return err; +} +late_initcall(msm_mpdec_init); + +void msm_mpdec_exit(void) { +#ifdef CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN + input_unregister_handler(&mpdec_input_handler); + destroy_workqueue(msm_mpdec_revib_workq); + destroy_workqueue(mpdec_input_wq); +#endif + destroy_workqueue(msm_mpdec_workq); +} + diff --git a/arch/arm/mach-msm/msm_rq_stats.c b/arch/arm/mach-msm/msm_rq_stats.c index aa440eae8f6..a787e475641 100644 --- a/arch/arm/mach-msm/msm_rq_stats.c +++ b/arch/arm/mach-msm/msm_rq_stats.c @@ -236,6 +236,23 @@ static ssize_t hotplug_disable_show(struct kobject *kobj, } static struct kobj_attribute hotplug_disabled_attr = __ATTR_RO(hotplug_disable); +#ifdef CONFIG_MSM_MPDEC +unsigned int get_rq_info(void) +{ + unsigned long flags = 0; + unsigned int rq = 0; + + spin_lock_irqsave(&rq_lock, flags); + + rq = rq_info.rq_avg; + rq_info.rq_avg = 0; + + spin_unlock_irqrestore(&rq_lock, flags); + + return rq; +} +EXPORT_SYMBOL(get_rq_info); +#endif static void def_work_fn(struct work_struct *work) { diff --git a/arch/arm/mach-msm/platsmp-8625.c b/arch/arm/mach-msm/platsmp-8625.c index 8e7e7d2838b..2e02ec0cb25 100644 --- a/arch/arm/mach-msm/platsmp-8625.c +++ b/arch/arm/mach-msm/platsmp-8625.c @@ -47,7 +47,7 @@ static void __iomem *reset_core1_base; * observers, irrespective of whether they're taking part in coherency * or not. This is necessary for the hotplug code to work reliably. */ -static void __cpuinit write_pen_release(int val) +static void write_pen_release(int val) { pen_release = val; smp_wmb(); @@ -91,7 +91,7 @@ static void clear_pending_spi(unsigned int irq) local_irq_enable(); } -void __cpuinit platform_secondary_init(unsigned int cpu) +void platform_secondary_init(unsigned int cpu) { pr_debug("CPU%u: Booted secondary processor\n", cpu); @@ -124,7 +124,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu) spin_unlock(&boot_lock); } -static int __cpuinit msm8625_release_secondary(void) +static int msm8625_release_secondary(void) { void __iomem *base_ptr; int value = 0; @@ -166,7 +166,7 @@ void __iomem *core1_reset_base(void) return reset_core1_base; } -int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) +int boot_secondary(unsigned int cpu, struct task_struct *idle) { unsigned long timeout; diff --git a/arch/arm/mach-msm/platsmp.c b/arch/arm/mach-msm/platsmp.c index d3c77972c75..36da6395603 100644 --- a/arch/arm/mach-msm/platsmp.c +++ b/arch/arm/mach-msm/platsmp.c @@ -47,7 +47,7 @@ volatile int pen_release = -1; * observers, irrespective of whether they're taking part in coherency * or not. This is necessary for the hotplug code to work reliably. */ -static void __cpuinit write_pen_release(int val) +static void write_pen_release(int val) { pen_release = val; smp_wmb(); @@ -57,7 +57,7 @@ static void __cpuinit write_pen_release(int val) static DEFINE_SPINLOCK(boot_lock); -void __cpuinit platform_secondary_init(unsigned int cpu) +void platform_secondary_init(unsigned int cpu) { WARN_ON(msm_platform_secondary_init(cpu)); @@ -81,7 +81,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu) spin_unlock(&boot_lock); } -static int __cpuinit scorpion_release_secondary(void) +static int scorpion_release_secondary(void) { void *base_ptr = ioremap_nocache(0x00902000, SZ_4K*2); if (!base_ptr) @@ -97,7 +97,7 @@ static int __cpuinit scorpion_release_secondary(void) return 0; } -static int __cpuinit krait_release_secondary_sim(unsigned long base, int cpu) +static int krait_release_secondary_sim(unsigned long base, int cpu) { void *base_ptr = ioremap_nocache(base + (cpu * 0x10000), SZ_4K); if (!base_ptr) @@ -113,7 +113,7 @@ static int __cpuinit krait_release_secondary_sim(unsigned long base, int cpu) return 0; } -static int __cpuinit krait_release_secondary(unsigned long base, int cpu) +static int krait_release_secondary(unsigned long base, int cpu) { void *base_ptr = ioremap_nocache(base + (cpu * 0x10000), SZ_4K); if (!base_ptr) @@ -144,7 +144,7 @@ static int __cpuinit krait_release_secondary(unsigned long base, int cpu) return 0; } -static int __cpuinit krait_release_secondary_p3(unsigned long base, int cpu) +static int krait_release_secondary_p3(unsigned long base, int cpu) { void *base_ptr = ioremap_nocache(base + (cpu * 0x10000), SZ_4K); if (!base_ptr) @@ -169,7 +169,7 @@ static int __cpuinit krait_release_secondary_p3(unsigned long base, int cpu) return 0; } -static int __cpuinit release_secondary(unsigned int cpu) +static int release_secondary(unsigned int cpu) { BUG_ON(cpu >= get_core_count()); @@ -198,7 +198,7 @@ static int cold_boot_flags[] = { SCM_FLAG_COLDBOOT_CPU3, }; -int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) +int boot_secondary(unsigned int cpu, struct task_struct *idle) { int ret; unsigned int flag = 0; diff --git a/arch/arm/mach-msm/restart.c b/arch/arm/mach-msm/restart.c index 369f70dceb8..bc497218574 100644 --- a/arch/arm/mach-msm/restart.c +++ b/arch/arm/mach-msm/restart.c @@ -35,6 +35,10 @@ #include "msm_watchdog.h" #include "timer.h" +#ifdef CONFIG_KEXEC_HARDBOOT +#include +#endif + extern unsigned get_cable_status(void); #define WDT0_RST 0x38 @@ -337,6 +341,14 @@ static int __init msm_pmic_restart_init(void) late_initcall(msm_pmic_restart_init); +#ifdef CONFIG_KEXEC_HARDBOOT +static void msm_kexec_hardboot_hook(void) +{ + // Set PMIC to restart-on-poweroff + pm8xxx_reset_pwr_off(1); +} +#endif + static int __init msm_restart_init(void) { #ifdef CONFIG_MSM_DLOAD_MODE @@ -352,6 +364,10 @@ static int __init msm_restart_init(void) restart_reason = MSM_IMEM_BASE + RESTART_REASON_ADDR; pm_power_off = msm_power_off; +#ifdef CONFIG_KEXEC_HARDBOOT + kexec_hardboot_hook = msm_kexec_hardboot_hook; +#endif + return 0; } early_initcall(msm_restart_init); diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c index 795e1d69bda..8675ef72503 100644 --- a/arch/arm/mach-msm/timer.c +++ b/arch/arm/mach-msm/timer.c @@ -953,7 +953,7 @@ static void __init msm_sched_clock_init(void) } #ifdef CONFIG_LOCAL_TIMERS -int __cpuinit local_timer_setup(struct clock_event_device *evt) +int local_timer_setup(struct clock_event_device *evt) { static DEFINE_PER_CPU(bool, first_boot) = true; struct msm_clock *clock = &msm_clocks[msm_global_timer]; diff --git a/arch/arm/mach-msm/vdd_limits_8064.h b/arch/arm/mach-msm/vdd_limits_8064.h new file mode 100644 index 00000000000..011d08df4d6 --- /dev/null +++ b/arch/arm/mach-msm/vdd_limits_8064.h @@ -0,0 +1,3 @@ +#define SC_MAX_VDD 1400000 +#define SC_MIN_VDD 700000 +#define MEM_DIG_MAX_VDD 1250000 diff --git a/arch/arm/mach-omap2/omap-mpuss-lowpower.c b/arch/arm/mach-omap2/omap-mpuss-lowpower.c index 13670aa84e5..c2cdd8181a6 100644 --- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c +++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c @@ -297,7 +297,7 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state) * @cpu : CPU ID * @power_state: CPU low power state. */ -int __cpuinit omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state) +int omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state) { unsigned int cpu_state = 0; diff --git a/arch/arm/mach-omap2/omap-smp.c b/arch/arm/mach-omap2/omap-smp.c index deffbf1c962..f7213304523 100644 --- a/arch/arm/mach-omap2/omap-smp.c +++ b/arch/arm/mach-omap2/omap-smp.c @@ -41,7 +41,7 @@ void __iomem *omap4_get_scu_base(void) return scu_base; } -void __cpuinit platform_secondary_init(unsigned int cpu) +void platform_secondary_init(unsigned int cpu) { /* * Configure ACTRL and enable NS SMP bit access on CPU1 on HS device. @@ -69,7 +69,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu) spin_unlock(&boot_lock); } -int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) +int boot_secondary(unsigned int cpu, struct task_struct *idle) { static struct clockdomain *cpu1_clkdm; static bool booted; diff --git a/arch/arm/mach-omap2/omap-wakeupgen.c b/arch/arm/mach-omap2/omap-wakeupgen.c index 42cd7fb5241..a43852123e6 100644 --- a/arch/arm/mach-omap2/omap-wakeupgen.c +++ b/arch/arm/mach-omap2/omap-wakeupgen.c @@ -283,7 +283,7 @@ static void irq_save_secure_context(void) #endif #ifdef CONFIG_HOTPLUG_CPU -static int __cpuinit irq_cpu_hotplug_notify(struct notifier_block *self, +static int irq_cpu_hotplug_notify(struct notifier_block *self, unsigned long action, void *hcpu) { unsigned int cpu = (unsigned int)hcpu; diff --git a/arch/arm/mach-shmobile/platsmp.c b/arch/arm/mach-shmobile/platsmp.c index 45fa3924c6a..71fc93d4384 100644 --- a/arch/arm/mach-shmobile/platsmp.c +++ b/arch/arm/mach-shmobile/platsmp.c @@ -51,7 +51,7 @@ int shmobile_platform_cpu_kill(unsigned int cpu) return 1; } -void __cpuinit platform_secondary_init(unsigned int cpu) +void platform_secondary_init(unsigned int cpu) { trace_hardirqs_off(); @@ -62,7 +62,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu) r8a7779_secondary_init(cpu); } -int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) +int boot_secondary(unsigned int cpu, struct task_struct *idle) { if (is_sh73a0()) return sh73a0_boot_secondary(cpu); diff --git a/arch/arm/mach-shmobile/smp-r8a7779.c b/arch/arm/mach-shmobile/smp-r8a7779.c index 6d1d0238cbf..d0b72fc35b9 100644 --- a/arch/arm/mach-shmobile/smp-r8a7779.c +++ b/arch/arm/mach-shmobile/smp-r8a7779.c @@ -113,12 +113,12 @@ int r8a7779_platform_cpu_kill(unsigned int cpu) return ret ? ret : 1; } -void __cpuinit r8a7779_secondary_init(unsigned int cpu) +void r8a7779_secondary_init(unsigned int cpu) { gic_secondary_init(0); } -int __cpuinit r8a7779_boot_secondary(unsigned int cpu) +int r8a7779_boot_secondary(unsigned int cpu) { struct r8a7779_pm_ch *ch = NULL; int ret = -EIO; diff --git a/arch/arm/mach-shmobile/smp-sh73a0.c b/arch/arm/mach-shmobile/smp-sh73a0.c index e36c41c4ab4..9165901a6d2 100644 --- a/arch/arm/mach-shmobile/smp-sh73a0.c +++ b/arch/arm/mach-shmobile/smp-sh73a0.c @@ -71,12 +71,12 @@ unsigned int __init sh73a0_get_core_count(void) return scu_get_core_count(scu_base); } -void __cpuinit sh73a0_secondary_init(unsigned int cpu) +void sh73a0_secondary_init(unsigned int cpu) { gic_secondary_init(0); } -int __cpuinit sh73a0_boot_secondary(unsigned int cpu) +int sh73a0_boot_secondary(unsigned int cpu) { cpu = cpu_logical_map(cpu); diff --git a/arch/arm/mach-tegra/platsmp.c b/arch/arm/mach-tegra/platsmp.c index 1a208dbf682..d2ca327111b 100644 --- a/arch/arm/mach-tegra/platsmp.c +++ b/arch/arm/mach-tegra/platsmp.c @@ -50,7 +50,7 @@ static void __iomem *scu_base = IO_ADDRESS(TEGRA_ARM_PERIF_BASE); #define CPU_CLOCK(cpu) (0x1<<(8+cpu)) #define CPU_RESET(cpu) (0x1111ul<<(cpu)) -void __cpuinit platform_secondary_init(unsigned int cpu) +void platform_secondary_init(unsigned int cpu) { /* * if any interrupts are already enabled for the primary @@ -117,7 +117,7 @@ static int tegra30_power_up_cpu(unsigned int cpu) return 0; } -int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) +int boot_secondary(unsigned int cpu, struct task_struct *idle) { int status; diff --git a/arch/arm/mach-ux500/platsmp.c b/arch/arm/mach-ux500/platsmp.c index eff5842f623..e444aecc1a9 100644 --- a/arch/arm/mach-ux500/platsmp.c +++ b/arch/arm/mach-ux500/platsmp.c @@ -60,7 +60,7 @@ static void __iomem *scu_base_addr(void) static DEFINE_SPINLOCK(boot_lock); -void __cpuinit platform_secondary_init(unsigned int cpu) +void platform_secondary_init(unsigned int cpu) { /* * if any interrupts are already enabled for the primary @@ -82,7 +82,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu) spin_unlock(&boot_lock); } -int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) +int boot_secondary(unsigned int cpu, struct task_struct *idle) { unsigned long timeout; diff --git a/arch/arm/plat-versatile/platsmp.c b/arch/arm/plat-versatile/platsmp.c index 49c7db48c7f..992693a682c 100644 --- a/arch/arm/plat-versatile/platsmp.c +++ b/arch/arm/plat-versatile/platsmp.c @@ -23,14 +23,14 @@ * control for which core is the next to come out of the secondary * boot "holding pen" */ -volatile int __cpuinitdata pen_release = -1; +volatile int pen_release = -1; /* * Write pen_release in a way that is guaranteed to be visible to all * observers, irrespective of whether they're taking part in coherency * or not. This is necessary for the hotplug code to work reliably. */ -static void __cpuinit write_pen_release(int val) +static void write_pen_release(int val) { pen_release = val; smp_wmb(); @@ -40,7 +40,7 @@ static void __cpuinit write_pen_release(int val) static DEFINE_SPINLOCK(boot_lock); -void __cpuinit platform_secondary_init(unsigned int cpu) +void platform_secondary_init(unsigned int cpu) { /* * if any interrupts are already enabled for the primary @@ -62,7 +62,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu) spin_unlock(&boot_lock); } -int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) +int boot_secondary(unsigned int cpu, struct task_struct *idle) { unsigned long timeout; diff --git a/arch/arm/vfp/Makefile b/arch/arm/vfp/Makefile index a81404c09d5..e7b053cf8b1 100644 --- a/arch/arm/vfp/Makefile +++ b/arch/arm/vfp/Makefile @@ -7,7 +7,7 @@ # ccflags-y := -DDEBUG # asflags-y := -DDEBUG -KBUILD_AFLAGS :=$(KBUILD_AFLAGS:-msoft-float=-Wa,-mfpu=softvfp+vfp -mfloat-abi=soft) +KBUILD_AFLAGS :=$(KBUILD_AFLAGS:-msoft-float=-Wa,-mfpu=neon -mfloat-abi=hard) LDFLAGS +=--no-warn-mismatch obj-y += vfp.o diff --git a/arch/blackfin/kernel/perf_event.c b/arch/blackfin/kernel/perf_event.c index e47d19ae3e0..974e55496db 100644 --- a/arch/blackfin/kernel/perf_event.c +++ b/arch/blackfin/kernel/perf_event.c @@ -468,7 +468,7 @@ static void bfin_pmu_setup(int cpu) memset(cpuhw, 0, sizeof(struct cpu_hw_events)); } -static int __cpuinit +static int bfin_pmu_notifier(struct notifier_block *self, unsigned long action, void *hcpu) { unsigned int cpu = (long)hcpu; diff --git a/arch/blackfin/kernel/setup.c b/arch/blackfin/kernel/setup.c index 2ad747e909f..36510c56324 100644 --- a/arch/blackfin/kernel/setup.c +++ b/arch/blackfin/kernel/setup.c @@ -96,7 +96,7 @@ void __init generate_cplb_tables(void) } #endif -void __cpuinit bfin_setup_caches(unsigned int cpu) +void bfin_setup_caches(unsigned int cpu) { #ifdef CONFIG_BFIN_ICACHE bfin_icache_init(icplb_tbl[cpu]); @@ -162,7 +162,7 @@ void __cpuinit bfin_setup_caches(unsigned int cpu) #endif } -void __cpuinit bfin_setup_cpudata(unsigned int cpu) +void bfin_setup_cpudata(unsigned int cpu) { struct blackfin_cpudata *cpudata = &per_cpu(cpu_data, cpu); diff --git a/arch/blackfin/mach-bf561/smp.c b/arch/blackfin/mach-bf561/smp.c index ab1c617b9cf..7748b84f1e5 100644 --- a/arch/blackfin/mach-bf561/smp.c +++ b/arch/blackfin/mach-bf561/smp.c @@ -48,7 +48,7 @@ int __init setup_profiling_timer(unsigned int multiplier) /* not supported */ return -EINVAL; } -void __cpuinit platform_secondary_init(unsigned int cpu) +void platform_secondary_init(unsigned int cpu) { /* Clone setup for peripheral interrupt sources from CoreA. */ bfin_write_SICB_IMASK0(bfin_read_SIC_IMASK0()); @@ -74,7 +74,7 @@ void __cpuinit platform_secondary_init(unsigned int cpu) spin_unlock(&boot_lock); } -int __cpuinit platform_boot_secondary(unsigned int cpu, struct task_struct *idle) +int platform_boot_secondary(unsigned int cpu, struct task_struct *idle) { unsigned long timeout; @@ -155,7 +155,7 @@ void platform_clear_ipi(unsigned int cpu, int irq) * Setup core B's local core timer. * In SMP, core timer is used for clock event device. */ -void __cpuinit bfin_local_timer_setup(void) +void bfin_local_timer_setup(void) { #if defined(CONFIG_TICKSOURCE_CORETMR) struct irq_data *data = irq_get_irq_data(IRQ_CORETMR); diff --git a/arch/blackfin/mach-common/cache-c.c b/arch/blackfin/mach-common/cache-c.c index a60a24f5035..0e1e451fd7d 100644 --- a/arch/blackfin/mach-common/cache-c.c +++ b/arch/blackfin/mach-common/cache-c.c @@ -52,7 +52,7 @@ bfin_cache_init(struct cplb_entry *cplb_tbl, unsigned long cplb_addr, } #ifdef CONFIG_BFIN_ICACHE -void __cpuinit bfin_icache_init(struct cplb_entry *icplb_tbl) +void bfin_icache_init(struct cplb_entry *icplb_tbl) { bfin_cache_init(icplb_tbl, ICPLB_ADDR0, ICPLB_DATA0, IMEM_CONTROL, (IMC | ENICPLB)); @@ -60,7 +60,7 @@ void __cpuinit bfin_icache_init(struct cplb_entry *icplb_tbl) #endif #ifdef CONFIG_BFIN_DCACHE -void __cpuinit bfin_dcache_init(struct cplb_entry *dcplb_tbl) +void bfin_dcache_init(struct cplb_entry *dcplb_tbl) { /* * Anomaly notes: diff --git a/arch/blackfin/mach-common/ints-priority.c b/arch/blackfin/mach-common/ints-priority.c index 332dace6af3..71ed47e1872 100644 --- a/arch/blackfin/mach-common/ints-priority.c +++ b/arch/blackfin/mach-common/ints-priority.c @@ -919,7 +919,7 @@ static struct irq_chip bfin_gpio_irqchip = { .irq_set_wake = bfin_gpio_set_wake, }; -void __cpuinit init_exception_vectors(void) +void init_exception_vectors(void) { /* cannot program in software: * evt0 - emulation (jtag) diff --git a/arch/blackfin/mach-common/smp.c b/arch/blackfin/mach-common/smp.c index ac8f8a43158..21b6c7e7dd8 100644 --- a/arch/blackfin/mach-common/smp.c +++ b/arch/blackfin/mach-common/smp.c @@ -46,7 +46,7 @@ struct corelock_slot corelock __attribute__ ((__section__(".l2.bss"))); unsigned long blackfin_iflush_l1_entry[NR_CPUS]; #endif -struct blackfin_initial_pda __cpuinitdata initial_pda_coreb; +struct blackfin_initial_pda initial_pda_coreb; #define BFIN_IPI_TIMER 0 #define BFIN_IPI_RESCHEDULE 1 @@ -340,7 +340,7 @@ void smp_send_stop(void) return; } -int __cpuinit __cpu_up(unsigned int cpu) +int __cpu_up(unsigned int cpu) { int ret; struct blackfin_cpudata *ci = &per_cpu(cpu_data, cpu); @@ -370,7 +370,7 @@ int __cpuinit __cpu_up(unsigned int cpu) return ret; } -static void __cpuinit setup_secondary(unsigned int cpu) +static void setup_secondary(unsigned int cpu) { unsigned long ilat; @@ -388,7 +388,7 @@ static void __cpuinit setup_secondary(unsigned int cpu) IMASK_IVG10 | IMASK_IVG9 | IMASK_IVG8 | IMASK_IVG7 | IMASK_IVGHW; } -void __cpuinit secondary_start_kernel(void) +void secondary_start_kernel(void) { unsigned int cpu = smp_processor_id(); struct mm_struct *mm = &init_mm; @@ -512,7 +512,7 @@ EXPORT_SYMBOL(resync_core_dcache); #endif #ifdef CONFIG_HOTPLUG_CPU -int __cpuexit __cpu_disable(void) +int __cpu_disable(void) { unsigned int cpu = smp_processor_id(); @@ -525,7 +525,7 @@ int __cpuexit __cpu_disable(void) static DECLARE_COMPLETION(cpu_killed); -int __cpuexit __cpu_die(unsigned int cpu) +int __cpu_die(unsigned int cpu) { return wait_for_completion_timeout(&cpu_killed, 5000); } diff --git a/arch/cris/arch-v32/kernel/smp.c b/arch/cris/arch-v32/kernel/smp.c index 0b99df72d2a..df84b3ce3e9 100644 --- a/arch/cris/arch-v32/kernel/smp.c +++ b/arch/cris/arch-v32/kernel/smp.c @@ -207,7 +207,7 @@ int setup_profiling_timer(unsigned int multiplier) */ unsigned long cache_decay_ticks = 1; -int __cpuinit __cpu_up(unsigned int cpu) +int __cpu_up(unsigned int cpu) { smp_boot_one_cpu(cpu); return cpu_online(cpu) ? 0 : -ENOSYS; diff --git a/arch/frv/kernel/setup.c b/arch/frv/kernel/setup.c index 75cf7f4b2fa..699d381ed2d 100644 --- a/arch/frv/kernel/setup.c +++ b/arch/frv/kernel/setup.c @@ -707,7 +707,7 @@ static void __init reserve_dma_coherent(void) /* * calibrate the delay loop */ -void __cpuinit calibrate_delay(void) +void calibrate_delay(void) { loops_per_jiffy = __delay_loops_MHz * (1000000 / HZ); diff --git a/arch/hexagon/kernel/setup.c b/arch/hexagon/kernel/setup.c index 94a38783500..aa5ea33165b 100644 --- a/arch/hexagon/kernel/setup.c +++ b/arch/hexagon/kernel/setup.c @@ -41,7 +41,7 @@ static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE; int on_simulator; -void __cpuinit calibrate_delay(void) +void calibrate_delay(void) { loops_per_jiffy = thread_freq_mhz * 1000000 / HZ; } diff --git a/arch/hexagon/kernel/smp.c b/arch/hexagon/kernel/smp.c index 6fa1dc28fd6..7856111ce32 100644 --- a/arch/hexagon/kernel/smp.c +++ b/arch/hexagon/kernel/smp.c @@ -146,7 +146,7 @@ void __init smp_prepare_boot_cpu(void) * to point to current thread info */ -void __cpuinit start_secondary(void) +void start_secondary(void) { unsigned int cpu; unsigned long thread_ptr; @@ -196,7 +196,7 @@ void __cpuinit start_secondary(void) * maintains control until "cpu_online(cpu)" is set. */ -int __cpuinit __cpu_up(unsigned int cpu) +int __cpu_up(unsigned int cpu) { struct task_struct *idle; struct thread_info *thread; diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c index 6f38b6120d9..2deae9a9128 100644 --- a/arch/ia64/kernel/acpi.c +++ b/arch/ia64/kernel/acpi.c @@ -804,7 +804,7 @@ int acpi_isa_irq_to_gsi(unsigned isa_irq, u32 *gsi) * ACPI based hotplug CPU support */ #ifdef CONFIG_ACPI_HOTPLUG_CPU -static __cpuinit +static int acpi_map_cpu2node(acpi_handle handle, int cpu, int physid) { #ifdef CONFIG_ACPI_NUMA @@ -879,7 +879,7 @@ __init void prefill_possible_map(void) set_cpu_possible(i, true); } -static int __cpuinit _acpi_map_lsapic(acpi_handle handle, int *pcpu) +static int _acpi_map_lsapic(acpi_handle handle, int *pcpu) { struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; union acpi_object *obj; diff --git a/arch/ia64/kernel/err_inject.c b/arch/ia64/kernel/err_inject.c index 2d67317a1ec..4dc334c71db 100644 --- a/arch/ia64/kernel/err_inject.c +++ b/arch/ia64/kernel/err_inject.c @@ -225,17 +225,17 @@ static struct attribute_group err_inject_attr_group = { .name = "err_inject" }; /* Add/Remove err_inject interface for CPU device */ -static int __cpuinit err_inject_add_dev(struct device * sys_dev) +static int err_inject_add_dev(struct device * sys_dev) { return sysfs_create_group(&sys_dev->kobj, &err_inject_attr_group); } -static int __cpuinit err_inject_remove_dev(struct device * sys_dev) +static int err_inject_remove_dev(struct device * sys_dev) { sysfs_remove_group(&sys_dev->kobj, &err_inject_attr_group); return 0; } -static int __cpuinit err_inject_cpu_callback(struct notifier_block *nfb, +static int err_inject_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { unsigned int cpu = (unsigned long)hcpu; @@ -256,7 +256,7 @@ static int __cpuinit err_inject_cpu_callback(struct notifier_block *nfb, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata err_inject_cpu_notifier = +static struct notifier_block err_inject_cpu_notifier = { .notifier_call = err_inject_cpu_callback, }; diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c index 65bf9cd3904..41028334289 100644 --- a/arch/ia64/kernel/mca.c +++ b/arch/ia64/kernel/mca.c @@ -631,7 +631,7 @@ ia64_mca_register_cpev (int cpev) * Outputs * None */ -void __cpuinit +void ia64_mca_cmc_vector_setup (void) { cmcv_reg_t cmcv; @@ -1814,7 +1814,7 @@ static struct irqaction mca_cpep_irqaction = { * format most of the fields. */ -static void __cpuinit +static void format_mca_init_stack(void *mca_data, unsigned long offset, const char *type, int cpu) { @@ -1844,7 +1844,7 @@ static void * __init_refok mca_bootmem(void) } /* Do per-CPU MCA-related initialization. */ -void __cpuinit +void ia64_mca_cpu_init(void *cpu_data) { void *pal_vaddr; @@ -1896,7 +1896,7 @@ ia64_mca_cpu_init(void *cpu_data) PAGE_KERNEL)); } -static void __cpuinit ia64_mca_cmc_vector_adjust(void *dummy) +static void ia64_mca_cmc_vector_adjust(void *dummy) { unsigned long flags; @@ -1906,7 +1906,7 @@ static void __cpuinit ia64_mca_cmc_vector_adjust(void *dummy) local_irq_restore(flags); } -static int __cpuinit mca_cpu_callback(struct notifier_block *nfb, +static int mca_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { @@ -1922,7 +1922,7 @@ static int __cpuinit mca_cpu_callback(struct notifier_block *nfb, return NOTIFY_OK; } -static struct notifier_block mca_cpu_notifier __cpuinitdata = { +static struct notifier_block mca_cpu_notifier = { .notifier_call = mca_cpu_callback }; diff --git a/arch/ia64/kernel/numa.c b/arch/ia64/kernel/numa.c index c93420c9740..d288cde9360 100644 --- a/arch/ia64/kernel/numa.c +++ b/arch/ia64/kernel/numa.c @@ -30,7 +30,7 @@ EXPORT_SYMBOL(cpu_to_node_map); cpumask_t node_to_cpu_mask[MAX_NUMNODES] __cacheline_aligned; EXPORT_SYMBOL(node_to_cpu_mask); -void __cpuinit map_cpu_to_node(int cpu, int nid) +void map_cpu_to_node(int cpu, int nid) { int oldnid; if (nid < 0) { /* just initialize by zero */ @@ -51,7 +51,7 @@ void __cpuinit map_cpu_to_node(int cpu, int nid) return; } -void __cpuinit unmap_cpu_from_node(int cpu, int nid) +void unmap_cpu_from_node(int cpu, int nid) { WARN_ON(!cpu_isset(cpu, node_to_cpu_mask[nid])); WARN_ON(cpu_to_node_map[cpu] != nid); diff --git a/arch/ia64/kernel/palinfo.c b/arch/ia64/kernel/palinfo.c index 77597e5ea60..6c198815c3e 100644 --- a/arch/ia64/kernel/palinfo.c +++ b/arch/ia64/kernel/palinfo.c @@ -968,7 +968,7 @@ palinfo_read_entry(char *page, char **start, off_t off, int count, int *eof, voi return len; } -static void __cpuinit +static void create_palinfo_proc_entries(unsigned int cpu) { # define CPUSTR "cpu%d" @@ -1027,7 +1027,7 @@ remove_palinfo_proc_entries(unsigned int hcpu) } } -static int __cpuinit palinfo_cpu_callback(struct notifier_block *nfb, +static int palinfo_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { unsigned int hotcpu = (unsigned long)hcpu; diff --git a/arch/ia64/kernel/salinfo.c b/arch/ia64/kernel/salinfo.c index 79802e540e5..787c7939c51 100644 --- a/arch/ia64/kernel/salinfo.c +++ b/arch/ia64/kernel/salinfo.c @@ -575,7 +575,7 @@ static const struct file_operations salinfo_data_fops = { .llseek = default_llseek, }; -static int __cpuinit +static int salinfo_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu) { unsigned int i, cpu = (unsigned long)hcpu; @@ -616,7 +616,7 @@ salinfo_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu return NOTIFY_OK; } -static struct notifier_block salinfo_cpu_notifier __cpuinitdata = +static struct notifier_block salinfo_cpu_notifier = { .notifier_call = salinfo_cpu_callback, .priority = 0, diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c index aaefd9b94f2..88fc6ce8b3c 100644 --- a/arch/ia64/kernel/setup.c +++ b/arch/ia64/kernel/setup.c @@ -748,7 +748,7 @@ const struct seq_operations cpuinfo_op = { #define MAX_BRANDS 8 static char brandname[MAX_BRANDS][128]; -static char * __cpuinit +static char * get_model_name(__u8 family, __u8 model) { static int overflow; @@ -778,7 +778,7 @@ get_model_name(__u8 family, __u8 model) return "Unknown"; } -static void __cpuinit +static void identify_cpu (struct cpuinfo_ia64 *c) { union { @@ -850,7 +850,7 @@ identify_cpu (struct cpuinfo_ia64 *c) * 2. the minimum of the i-cache stride sizes for "flush_icache_range()". * 3. the minimum of the cache stride sizes for "clflush_cache_range()". */ -static void __cpuinit +static void get_cache_info(void) { unsigned long line_size, max = 1; @@ -915,10 +915,10 @@ get_cache_info(void) * cpu_init() initializes state that is per-CPU. This function acts * as a 'CPU state barrier', nothing should get across. */ -void __cpuinit +void cpu_init (void) { - extern void __cpuinit ia64_mmu_init (void *); + extern void ia64_mmu_init (void *); static unsigned long max_num_phys_stacked = IA64_NUM_PHYS_STACK_REG; unsigned long num_phys_stacked; pal_vm_info_2_u_t vmi; diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c index 796f6a5b966..a99701012d1 100644 --- a/arch/ia64/kernel/smpboot.c +++ b/arch/ia64/kernel/smpboot.c @@ -365,7 +365,7 @@ smp_setup_percpu_timer (void) { } -static void __cpuinit +static void smp_callin (void) { int cpuid, phys_id, itc_master; @@ -458,7 +458,7 @@ smp_callin (void) /* * Activate a secondary processor. head.S calls this. */ -int __cpuinit +int start_secondary (void *unused) { /* Early console may use I/O ports */ @@ -475,7 +475,7 @@ start_secondary (void *unused) return 0; } -struct pt_regs * __cpuinit idle_regs(struct pt_regs *regs) +struct pt_regs * idle_regs(struct pt_regs *regs) { return NULL; } @@ -487,7 +487,7 @@ struct create_idle { int cpu; }; -void __cpuinit +void do_fork_idle(struct work_struct *work) { struct create_idle *c_idle = @@ -497,7 +497,7 @@ do_fork_idle(struct work_struct *work) complete(&c_idle->done); } -static int __cpuinit +static int do_boot_cpu (int sapicid, int cpu) { int timeout; @@ -792,7 +792,7 @@ set_cpu_sibling_map(int cpu) } } -int __cpuinit +int __cpu_up (unsigned int cpu) { int ret; diff --git a/arch/ia64/kernel/topology.c b/arch/ia64/kernel/topology.c index c64460b9c70..3032795acf8 100644 --- a/arch/ia64/kernel/topology.c +++ b/arch/ia64/kernel/topology.c @@ -135,11 +135,11 @@ struct cpu_cache_info { struct kobject kobj; }; -static struct cpu_cache_info all_cpu_cache_info[NR_CPUS] __cpuinitdata; +static struct cpu_cache_info all_cpu_cache_info[NR_CPUS]; #define LEAF_KOBJECT_PTR(x,y) (&all_cpu_cache_info[x].cache_leaves[y]) #ifdef CONFIG_SMP -static void __cpuinit cache_shared_cpu_map_setup( unsigned int cpu, +static void cache_shared_cpu_map_setup( unsigned int cpu, struct cache_info * this_leaf) { pal_cache_shared_info_t csi; @@ -174,7 +174,7 @@ static void __cpuinit cache_shared_cpu_map_setup( unsigned int cpu, &csi) == PAL_STATUS_SUCCESS); } #else -static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, +static void cache_shared_cpu_map_setup(unsigned int cpu, struct cache_info * this_leaf) { cpu_set(cpu, this_leaf->shared_cpu_map); @@ -298,7 +298,7 @@ static struct kobj_type cache_ktype_percpu_entry = { .sysfs_ops = &cache_sysfs_ops, }; -static void __cpuinit cpu_cache_sysfs_exit(unsigned int cpu) +static void cpu_cache_sysfs_exit(unsigned int cpu) { kfree(all_cpu_cache_info[cpu].cache_leaves); all_cpu_cache_info[cpu].cache_leaves = NULL; @@ -307,7 +307,7 @@ static void __cpuinit cpu_cache_sysfs_exit(unsigned int cpu) return; } -static int __cpuinit cpu_cache_sysfs_init(unsigned int cpu) +static int cpu_cache_sysfs_init(unsigned int cpu) { unsigned long i, levels, unique_caches; pal_cache_config_info_t cci; @@ -351,7 +351,7 @@ static int __cpuinit cpu_cache_sysfs_init(unsigned int cpu) } /* Add cache interface for CPU device */ -static int __cpuinit cache_add_dev(struct device * sys_dev) +static int cache_add_dev(struct device * sys_dev) { unsigned int cpu = sys_dev->id; unsigned long i, j; @@ -401,7 +401,7 @@ static int __cpuinit cache_add_dev(struct device * sys_dev) } /* Remove cache interface for CPU device */ -static int __cpuinit cache_remove_dev(struct device * sys_dev) +static int cache_remove_dev(struct device * sys_dev) { unsigned int cpu = sys_dev->id; unsigned long i; @@ -425,7 +425,7 @@ static int __cpuinit cache_remove_dev(struct device * sys_dev) * When a cpu is hot-plugged, do a check and initiate * cache kobject if necessary */ -static int __cpuinit cache_cpu_callback(struct notifier_block *nfb, +static int cache_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { unsigned int cpu = (unsigned long)hcpu; @@ -445,7 +445,7 @@ static int __cpuinit cache_cpu_callback(struct notifier_block *nfb, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata cache_cpu_notifier = +static struct notifier_block cache_cpu_notifier = { .notifier_call = cache_cpu_callback }; diff --git a/arch/ia64/mm/contig.c b/arch/ia64/mm/contig.c index 1516d1dc11f..8d32e16a6dd 100644 --- a/arch/ia64/mm/contig.c +++ b/arch/ia64/mm/contig.c @@ -154,7 +154,7 @@ static void *cpu_data; * * Allocate and setup per-cpu data areas. */ -void * __cpuinit +void * per_cpu_init (void) { static bool first_time = true; diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c index c641333cd99..fb7548badcd 100644 --- a/arch/ia64/mm/discontig.c +++ b/arch/ia64/mm/discontig.c @@ -593,7 +593,7 @@ void __init find_memory(void) * find_pernode_space() does most of this already, we just need to set * local_per_cpu_offset */ -void __cpuinit *per_cpu_init(void) +void *per_cpu_init(void) { int cpu; static int first_time = 1; diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c index f82e7b462b7..53b01b8e2f1 100644 --- a/arch/ia64/sn/kernel/setup.c +++ b/arch/ia64/sn/kernel/setup.c @@ -192,7 +192,7 @@ void __init early_sn_setup(void) } extern int platform_intr_list[]; -static int __cpuinitdata shub_1_1_found; +static int shub_1_1_found; /* * sn_check_for_wars @@ -200,7 +200,7 @@ static int __cpuinitdata shub_1_1_found; * Set flag for enabling shub specific wars */ -static inline int __cpuinit is_shub_1_1(int nasid) +static inline int is_shub_1_1(int nasid) { unsigned long id; int rev; @@ -212,7 +212,7 @@ static inline int __cpuinit is_shub_1_1(int nasid) return rev <= 2; } -static void __cpuinit sn_check_for_wars(void) +static void sn_check_for_wars(void) { int cnode; @@ -558,7 +558,7 @@ static void __init sn_init_pdas(char **cmdline_p) * Also sets up a few fields in the nodepda. Also known as * platform_cpu_init() by the ia64 machvec code. */ -void __cpuinit sn_cpu_init(void) +void sn_cpu_init(void) { int cpuid; int cpuphyid; diff --git a/arch/ia64/xen/hypervisor.c b/arch/ia64/xen/hypervisor.c index 52172eee859..fab62528a80 100644 --- a/arch/ia64/xen/hypervisor.c +++ b/arch/ia64/xen/hypervisor.c @@ -74,7 +74,7 @@ void __init xen_setup_vcpu_info_placement(void) xen_vcpu_setup(cpu); } -void __cpuinit +void xen_cpu_init(void) { xen_smp_intr_init(); diff --git a/arch/m32r/kernel/smpboot.c b/arch/m32r/kernel/smpboot.c index cfdbe5d1500..ab2deda6ba9 100644 --- a/arch/m32r/kernel/smpboot.c +++ b/arch/m32r/kernel/smpboot.c @@ -347,7 +347,7 @@ static void __init do_boot_cpu(int phys_id) } } -int __cpuinit __cpu_up(unsigned int cpu_id) +int __cpu_up(unsigned int cpu_id) { int timeout; diff --git a/arch/mips/ath79/setup.c b/arch/mips/ath79/setup.c index 80a7d4023d7..8db0fc0fb25 100644 --- a/arch/mips/ath79/setup.c +++ b/arch/mips/ath79/setup.c @@ -160,7 +160,7 @@ const char *get_system_type(void) return ath79_sys_type; } -unsigned int __cpuinit get_c0_compare_int(void) +unsigned int get_c0_compare_int(void) { return CP0_LEGACY_COMPARE_IRQ; } diff --git a/arch/mips/cavium-octeon/octeon-irq.c b/arch/mips/cavium-octeon/octeon-irq.c index ffd4ae660f7..01345f43d94 100644 --- a/arch/mips/cavium-octeon/octeon-irq.c +++ b/arch/mips/cavium-octeon/octeon-irq.c @@ -847,14 +847,14 @@ static void (*octeon_irq_ip2)(void); static void (*octeon_irq_ip3)(void); static void (*octeon_irq_ip4)(void); -void __cpuinitdata (*octeon_irq_setup_secondary)(void); +void (*octeon_irq_setup_secondary)(void); -static void __cpuinit octeon_irq_percpu_enable(void) +static void octeon_irq_percpu_enable(void) { irq_cpu_online(); } -static void __cpuinit octeon_irq_init_ciu_percpu(void) +static void octeon_irq_init_ciu_percpu(void) { int coreid = cvmx_get_core_num(); /* @@ -869,7 +869,7 @@ static void __cpuinit octeon_irq_init_ciu_percpu(void) cvmx_read_csr(CVMX_CIU_INTX_SUM0((coreid * 2))); } -static void __cpuinit octeon_irq_setup_secondary_ciu(void) +static void octeon_irq_setup_secondary_ciu(void) { __get_cpu_var(octeon_irq_ciu0_en_mirror) = 0; diff --git a/arch/mips/cavium-octeon/smp.c b/arch/mips/cavium-octeon/smp.c index 97e7ce9b50e..2055571883f 100644 --- a/arch/mips/cavium-octeon/smp.c +++ b/arch/mips/cavium-octeon/smp.c @@ -173,7 +173,7 @@ static void octeon_boot_secondary(int cpu, struct task_struct *idle) * After we've done initial boot, this function is called to allow the * board code to clean up state, if needed */ -static void __cpuinit octeon_init_secondary(void) +static void octeon_init_secondary(void) { unsigned int sr; @@ -381,7 +381,7 @@ static int octeon_update_boot_vector(unsigned int cpu) return 0; } -static int __cpuinit octeon_cpu_callback(struct notifier_block *nfb, +static int octeon_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { unsigned int cpu = (unsigned long)hcpu; @@ -400,7 +400,7 @@ static int __cpuinit octeon_cpu_callback(struct notifier_block *nfb, return NOTIFY_OK; } -static int __cpuinit register_cavium_notifier(void) +static int register_cavium_notifier(void) { hotcpu_notifier(octeon_cpu_callback, 0); return 0; diff --git a/arch/mips/include/asm/uasm.h b/arch/mips/include/asm/uasm.h index 504d40aedfa..ce1a7d9f667 100644 --- a/arch/mips/include/asm/uasm.h +++ b/arch/mips/include/asm/uasm.h @@ -16,8 +16,8 @@ #define __uasminitdata #define UASM_EXPORT_SYMBOL(sym) EXPORT_SYMBOL(sym) #else -#define __uasminit __cpuinit -#define __uasminitdata __cpuinitdata +#define __uasminit +#define __uasminitdatadata #define UASM_EXPORT_SYMBOL(sym) #endif diff --git a/arch/mips/kernel/cevt-bcm1480.c b/arch/mips/kernel/cevt-bcm1480.c index 69bbfae183b..f7313ac05d4 100644 --- a/arch/mips/kernel/cevt-bcm1480.c +++ b/arch/mips/kernel/cevt-bcm1480.c @@ -109,7 +109,7 @@ static DEFINE_PER_CPU(struct clock_event_device, sibyte_hpt_clockevent); static DEFINE_PER_CPU(struct irqaction, sibyte_hpt_irqaction); static DEFINE_PER_CPU(char [18], sibyte_hpt_name); -void __cpuinit sb1480_clockevent_init(void) +void sb1480_clockevent_init(void) { unsigned int cpu = smp_processor_id(); unsigned int irq = K_BCM1480_INT_TIMER_0 + cpu; diff --git a/arch/mips/kernel/cevt-r4k.c b/arch/mips/kernel/cevt-r4k.c index 51095dd9599..b68197eaa80 100644 --- a/arch/mips/kernel/cevt-r4k.c +++ b/arch/mips/kernel/cevt-r4k.c @@ -162,7 +162,7 @@ int c0_compare_int_usable(void) #ifndef CONFIG_MIPS_MT_SMTC -int __cpuinit r4k_clockevent_init(void) +int r4k_clockevent_init(void) { unsigned int cpu = smp_processor_id(); struct clock_event_device *cd; diff --git a/arch/mips/kernel/cevt-sb1250.c b/arch/mips/kernel/cevt-sb1250.c index e73439fd685..d47071f26b0 100644 --- a/arch/mips/kernel/cevt-sb1250.c +++ b/arch/mips/kernel/cevt-sb1250.c @@ -107,7 +107,7 @@ static DEFINE_PER_CPU(struct clock_event_device, sibyte_hpt_clockevent); static DEFINE_PER_CPU(struct irqaction, sibyte_hpt_irqaction); static DEFINE_PER_CPU(char [18], sibyte_hpt_name); -void __cpuinit sb1250_clockevent_init(void) +void sb1250_clockevent_init(void) { unsigned int cpu = smp_processor_id(); unsigned int irq = K_INT_TIMER_0 + cpu; diff --git a/arch/mips/kernel/cevt-smtc.c b/arch/mips/kernel/cevt-smtc.c index 2e72d30b2f0..4ce4aa7b43b 100644 --- a/arch/mips/kernel/cevt-smtc.c +++ b/arch/mips/kernel/cevt-smtc.c @@ -248,7 +248,7 @@ irqreturn_t c0_compare_interrupt(int irq, void *dev_id) } -int __cpuinit smtc_clockevent_init(void) +int smtc_clockevent_init(void) { uint64_t mips_freq = mips_hpt_frequency; unsigned int cpu = smp_processor_id(); diff --git a/arch/mips/kernel/cpu-bugs64.c b/arch/mips/kernel/cpu-bugs64.c index d6a18644365..28c9cb5ec53 100644 --- a/arch/mips/kernel/cpu-bugs64.c +++ b/arch/mips/kernel/cpu-bugs64.c @@ -167,7 +167,7 @@ static inline void check_mult_sh(void) panic(bug64hit, !R4000_WAR ? r4kwar : nowar); } -static volatile int daddi_ov __cpuinitdata; +static volatile int daddi_ov; asmlinkage void __init do_daddi_ov(struct pt_regs *regs) { diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 5099201fb7b..08564ddfc6d 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -126,7 +126,7 @@ static int __init wait_disable(char *s) __setup("nowait", wait_disable); -static int __cpuinitdata mips_fpu_disabled; +static int mips_fpu_disabled; static int __init fpu_disable(char *s) { @@ -138,7 +138,7 @@ static int __init fpu_disable(char *s) __setup("nofpu", fpu_disable); -int __cpuinitdata mips_dsp_disabled; +int mips_dsp_disabled; static int __init dsp_disable(char *s) { @@ -640,7 +640,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu) } } -static char unknown_isa[] __cpuinitdata = KERN_ERR \ +static char unknown_isa[] = KERN_ERR \ "Unsupported ISA type, c0.config0: %d."; static inline unsigned int decode_config0(struct cpuinfo_mips *c) @@ -761,7 +761,7 @@ static inline unsigned int decode_config4(struct cpuinfo_mips *c) return config4 & MIPS_CONF_M; } -static void __cpuinit decode_configs(struct cpuinfo_mips *c) +static void decode_configs(struct cpuinfo_mips *c) { int ok; @@ -1093,7 +1093,7 @@ EXPORT_SYMBOL(__ua_limit); const char *__cpu_name[NR_CPUS]; const char *__elf_platform; -__cpuinit void cpu_probe(void) +void cpu_probe(void) { struct cpuinfo_mips *c = ¤t_cpu_data; unsigned int cpu = smp_processor_id(); @@ -1177,7 +1177,7 @@ __cpuinit void cpu_probe(void) #endif } -__cpuinit void cpu_report(void) +void cpu_report(void) { struct cpuinfo_mips *c = ¤t_cpu_data; diff --git a/arch/mips/kernel/smp-bmips.c b/arch/mips/kernel/smp-bmips.c index 3046e298600..addd2b3796c 100644 --- a/arch/mips/kernel/smp-bmips.c +++ b/arch/mips/kernel/smp-bmips.c @@ -382,7 +382,7 @@ struct plat_smp_ops bmips_smp_ops = { * UP BMIPS systems as well. ***********************************************************************/ -static void __cpuinit bmips_wr_vec(unsigned long dst, char *start, char *end) +static void bmips_wr_vec(unsigned long dst, char *start, char *end) { memcpy((void *)dst, start, end - start); dma_cache_wback((unsigned long)start, end - start); @@ -390,7 +390,7 @@ static void __cpuinit bmips_wr_vec(unsigned long dst, char *start, char *end) instruction_hazard(); } -static inline void __cpuinit bmips_nmi_handler_setup(void) +static inline void bmips_nmi_handler_setup(void) { bmips_wr_vec(BMIPS_NMI_RESET_VEC, &bmips_reset_nmi_vec, &bmips_reset_nmi_vec_end); @@ -398,7 +398,7 @@ static inline void __cpuinit bmips_nmi_handler_setup(void) &bmips_smp_int_vec_end); } -void __cpuinit bmips_ebase_setup(void) +void bmips_ebase_setup(void) { unsigned long new_ebase = ebase; void __iomem __maybe_unused *cbr; diff --git a/arch/mips/kernel/smp-mt.c b/arch/mips/kernel/smp-mt.c index ff17868734c..cf2e29f2a9d 100644 --- a/arch/mips/kernel/smp-mt.c +++ b/arch/mips/kernel/smp-mt.c @@ -148,7 +148,7 @@ static void vsmp_send_ipi_mask(const struct cpumask *mask, unsigned int action) vsmp_send_ipi_single(i, action); } -static void __cpuinit vsmp_init_secondary(void) +static void vsmp_init_secondary(void) { extern int gic_present; @@ -161,7 +161,7 @@ static void __cpuinit vsmp_init_secondary(void) STATUSF_IP6 | STATUSF_IP7); } -static void __cpuinit vsmp_smp_finish(void) +static void vsmp_smp_finish(void) { /* CDFIXME: remove this? */ write_c0_compare(read_c0_count() + (8* mips_hpt_frequency/HZ)); @@ -187,7 +187,7 @@ static void vsmp_cpus_done(void) * (unsigned long)idle->thread_info the gp * assumes a 1:1 mapping of TC => VPE */ -static void __cpuinit vsmp_boot_secondary(int cpu, struct task_struct *idle) +static void vsmp_boot_secondary(int cpu, struct task_struct *idle) { struct thread_info *gp = task_thread_info(idle); dvpe(); diff --git a/arch/mips/kernel/smp-up.c b/arch/mips/kernel/smp-up.c index 00500fea275..7fde3e4d978 100644 --- a/arch/mips/kernel/smp-up.c +++ b/arch/mips/kernel/smp-up.c @@ -28,11 +28,11 @@ static inline void up_send_ipi_mask(const struct cpumask *mask, * After we've done initial boot, this function is called to allow the * board code to clean up state, if needed */ -static void __cpuinit up_init_secondary(void) +static void up_init_secondary(void) { } -static void __cpuinit up_smp_finish(void) +static void up_smp_finish(void) { } @@ -44,7 +44,7 @@ static void up_cpus_done(void) /* * Firmware CPU startup hook */ -static void __cpuinit up_boot_secondary(int cpu, struct task_struct *idle) +static void up_boot_secondary(int cpu, struct task_struct *idle) { } diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index ba9376bf52a..6e2e5bfd28d 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c @@ -84,7 +84,7 @@ static inline void set_cpu_sibling_map(int cpu) struct plat_smp_ops *mp_ops; -__cpuinit void register_smp_ops(struct plat_smp_ops *ops) +void register_smp_ops(struct plat_smp_ops *ops) { if (mp_ops) printk(KERN_WARNING "Overriding previously set SMP ops\n"); @@ -96,7 +96,7 @@ __cpuinit void register_smp_ops(struct plat_smp_ops *ops) * First C code run on the secondary CPUs after being started up by * the master. */ -asmlinkage __cpuinit void start_secondary(void) +asmlinkage void start_secondary(void) { unsigned int cpu; @@ -200,7 +200,7 @@ struct create_idle { int cpu; }; -static void __cpuinit do_fork_idle(struct work_struct *work) +static void do_fork_idle(struct work_struct *work) { struct create_idle *c_idle = container_of(work, struct create_idle, work); @@ -209,7 +209,7 @@ static void __cpuinit do_fork_idle(struct work_struct *work) complete(&c_idle->done); } -int __cpuinit __cpu_up(unsigned int cpu) +int __cpu_up(unsigned int cpu) { struct task_struct *idle; diff --git a/arch/mips/kernel/smtc.c b/arch/mips/kernel/smtc.c index f5dd38f1d01..7c199498c39 100644 --- a/arch/mips/kernel/smtc.c +++ b/arch/mips/kernel/smtc.c @@ -583,7 +583,7 @@ void smtc_prepare_cpus(int cpus) * (unsigned long)idle->thread_info the gp * */ -void __cpuinit smtc_boot_secondary(int cpu, struct task_struct *idle) +void smtc_boot_secondary(int cpu, struct task_struct *idle) { extern u32 kernelsp[NR_CPUS]; unsigned long flags; diff --git a/arch/mips/kernel/spram.c b/arch/mips/kernel/spram.c index 6af08d896e2..93f86817f20 100644 --- a/arch/mips/kernel/spram.c +++ b/arch/mips/kernel/spram.c @@ -37,7 +37,7 @@ /* * Different semantics to the set_c0_* function built by __BUILD_SET_C0 */ -static __cpuinit unsigned int bis_c0_errctl(unsigned int set) +static unsigned int bis_c0_errctl(unsigned int set) { unsigned int res; res = read_c0_errctl(); @@ -45,7 +45,7 @@ static __cpuinit unsigned int bis_c0_errctl(unsigned int set) return res; } -static __cpuinit void ispram_store_tag(unsigned int offset, unsigned int data) +static void ispram_store_tag(unsigned int offset, unsigned int data) { unsigned int errctl; @@ -64,7 +64,7 @@ static __cpuinit void ispram_store_tag(unsigned int offset, unsigned int data) } -static __cpuinit unsigned int ispram_load_tag(unsigned int offset) +static unsigned int ispram_load_tag(unsigned int offset) { unsigned int data; unsigned int errctl; @@ -82,7 +82,7 @@ static __cpuinit unsigned int ispram_load_tag(unsigned int offset) return data; } -static __cpuinit void dspram_store_tag(unsigned int offset, unsigned int data) +static void dspram_store_tag(unsigned int offset, unsigned int data) { unsigned int errctl; @@ -98,7 +98,7 @@ static __cpuinit void dspram_store_tag(unsigned int offset, unsigned int data) } -static __cpuinit unsigned int dspram_load_tag(unsigned int offset) +static unsigned int dspram_load_tag(unsigned int offset) { unsigned int data; unsigned int errctl; @@ -115,7 +115,7 @@ static __cpuinit unsigned int dspram_load_tag(unsigned int offset) return data; } -static __cpuinit void probe_spram(char *type, +static void probe_spram(char *type, unsigned int base, unsigned int (*read)(unsigned int), void (*write)(unsigned int, unsigned int)) @@ -196,7 +196,7 @@ static __cpuinit void probe_spram(char *type, offset += 2 * SPRAM_TAG_STRIDE; } } -void __cpuinit spram_config(void) +void spram_config(void) { struct cpuinfo_mips *c = ¤t_cpu_data; unsigned int config0; diff --git a/arch/mips/kernel/sync-r4k.c b/arch/mips/kernel/sync-r4k.c index 99f913c8d7a..7cbb650fa46 100644 --- a/arch/mips/kernel/sync-r4k.c +++ b/arch/mips/kernel/sync-r4k.c @@ -20,15 +20,15 @@ #include #include -static atomic_t __cpuinitdata count_start_flag = ATOMIC_INIT(0); -static atomic_t __cpuinitdata count_count_start = ATOMIC_INIT(0); -static atomic_t __cpuinitdata count_count_stop = ATOMIC_INIT(0); -static atomic_t __cpuinitdata count_reference = ATOMIC_INIT(0); +static atomic_t count_start_flag = ATOMIC_INIT(0); +static atomic_t count_count_start = ATOMIC_INIT(0); +static atomic_t count_count_stop = ATOMIC_INIT(0); +static atomic_t count_reference = ATOMIC_INIT(0); #define COUNTON 100 #define NR_LOOPS 5 -void __cpuinit synchronise_count_master(void) +void synchronise_count_master(void) { int i; unsigned long flags; @@ -108,7 +108,7 @@ void __cpuinit synchronise_count_master(void) printk("done.\n"); } -void __cpuinit synchronise_count_slave(void) +void synchronise_count_slave(void) { int i; unsigned long flags; diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index cfdaaa4cffc..c7bf91a4c12 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -1506,7 +1506,7 @@ int cp0_compare_irq_shift; int cp0_perfcount_irq; EXPORT_SYMBOL_GPL(cp0_perfcount_irq); -static int __cpuinitdata noulri; +static int noulri; static int __init ulri_disable(char *s) { @@ -1517,7 +1517,7 @@ static int __init ulri_disable(char *s) } __setup("noulri", ulri_disable); -void __cpuinit per_cpu_trap_init(void) +void per_cpu_trap_init(void) { unsigned int cpu = smp_processor_id(); unsigned int status_set = ST0_CU0; @@ -1638,7 +1638,7 @@ void __init set_handler(unsigned long offset, void *addr, unsigned long size) local_flush_icache_range(ebase + offset, ebase + offset + size); } -static char panic_null_cerr[] __cpuinitdata = +static char panic_null_cerr[] = "Trying to set NULL cache error exception handler"; /* @@ -1646,7 +1646,7 @@ static char panic_null_cerr[] __cpuinitdata = * This is suitable only for the cache error exception which is the only * exception handler that is being run uncached. */ -void __cpuinit set_uncached_handler(unsigned long offset, void *addr, +void set_uncached_handler(unsigned long offset, void *addr, unsigned long size) { unsigned long uncached_ebase = CKSEG1ADDR(ebase); diff --git a/arch/mips/kernel/watch.c b/arch/mips/kernel/watch.c index c1540696803..63ddb105205 100644 --- a/arch/mips/kernel/watch.c +++ b/arch/mips/kernel/watch.c @@ -100,7 +100,7 @@ void mips_clear_watch_registers(void) } } -__cpuinit void mips_probe_watch_registers(struct cpuinfo_mips *c) +void mips_probe_watch_registers(struct cpuinfo_mips *c) { unsigned int t; diff --git a/arch/mips/lantiq/irq.c b/arch/mips/lantiq/irq.c index d673731c538..f089949e267 100644 --- a/arch/mips/lantiq/irq.c +++ b/arch/mips/lantiq/irq.c @@ -317,7 +317,7 @@ void __init arch_init_irq(void) #endif } -unsigned int __cpuinit get_c0_compare_int(void) +unsigned int get_c0_compare_int(void) { return CP0_LEGACY_COMPARE_IRQ; } diff --git a/arch/mips/lib/uncached.c b/arch/mips/lib/uncached.c index a6d1c77034d..12b2ede12d2 100644 --- a/arch/mips/lib/uncached.c +++ b/arch/mips/lib/uncached.c @@ -36,7 +36,7 @@ * values, so we can avoid sharing the same stack area between a cached * and the uncached mode. */ -unsigned long __cpuinit run_uncached(void *func) +unsigned long run_uncached(void *func) { register long sp __asm__("$sp"); register long ret __asm__("$2"); diff --git a/arch/mips/mipssim/sim_smtc.c b/arch/mips/mipssim/sim_smtc.c index 3c104abd8aa..de3382591d5 100644 --- a/arch/mips/mipssim/sim_smtc.c +++ b/arch/mips/mipssim/sim_smtc.c @@ -55,7 +55,7 @@ static inline void ssmtc_send_ipi_mask(const struct cpumask *mask, /* * Post-config but pre-boot cleanup entry point */ -static void __cpuinit ssmtc_init_secondary(void) +static void ssmtc_init_secondary(void) { smtc_init_secondary(); } @@ -63,7 +63,7 @@ static void __cpuinit ssmtc_init_secondary(void) /* * SMP initialization finalization entry point */ -static void __cpuinit ssmtc_smp_finish(void) +static void ssmtc_smp_finish(void) { smtc_smp_finish(); } @@ -78,7 +78,7 @@ static void ssmtc_cpus_done(void) /* * Platform "CPU" startup hook */ -static void __cpuinit ssmtc_boot_secondary(int cpu, struct task_struct *idle) +static void ssmtc_boot_secondary(int cpu, struct task_struct *idle) { smtc_boot_secondary(cpu, idle); } diff --git a/arch/mips/mipssim/sim_time.c b/arch/mips/mipssim/sim_time.c index 77bad3c0428..c86b0e98cca 100644 --- a/arch/mips/mipssim/sim_time.c +++ b/arch/mips/mipssim/sim_time.c @@ -84,7 +84,7 @@ static void mips_timer_dispatch(void) } -unsigned __cpuinit get_c0_compare_int(void) +unsigned get_c0_compare_int(void) { #ifdef MSC01E_INT_BASE if (cpu_has_veic) { diff --git a/arch/mips/mm/c-octeon.c b/arch/mips/mm/c-octeon.c index 47037ec5589..29a4e598574 100644 --- a/arch/mips/mm/c-octeon.c +++ b/arch/mips/mm/c-octeon.c @@ -177,7 +177,7 @@ static void octeon_flush_kernel_vmap_range(unsigned long vaddr, int size) * Probe Octeon's caches * */ -static void __cpuinit probe_octeon(void) +static void probe_octeon(void) { unsigned long icache_size; unsigned long dcache_size; @@ -253,7 +253,7 @@ static void __cpuinit probe_octeon(void) * Setup the Octeon cache flush routines * */ -void __cpuinit octeon_cache_init(void) +void octeon_cache_init(void) { extern unsigned long ebase; extern char except_vec2_octeon; diff --git a/arch/mips/mm/c-r3k.c b/arch/mips/mm/c-r3k.c index 031c4c2cdf2..c7e5b5d83f3 100644 --- a/arch/mips/mm/c-r3k.c +++ b/arch/mips/mm/c-r3k.c @@ -26,7 +26,7 @@ static unsigned long icache_size, dcache_size; /* Size in bytes */ static unsigned long icache_lsize, dcache_lsize; /* Size in bytes */ -unsigned long __cpuinit r3k_cache_size(unsigned long ca_flags) +unsigned long r3k_cache_size(unsigned long ca_flags) { unsigned long flags, status, dummy, size; volatile unsigned long *p; @@ -61,7 +61,7 @@ unsigned long __cpuinit r3k_cache_size(unsigned long ca_flags) return size * sizeof(*p); } -unsigned long __cpuinit r3k_cache_lsize(unsigned long ca_flags) +unsigned long r3k_cache_lsize(unsigned long ca_flags) { unsigned long flags, status, lsize, i; volatile unsigned long *p; @@ -90,7 +90,7 @@ unsigned long __cpuinit r3k_cache_lsize(unsigned long ca_flags) return lsize * sizeof(*p); } -static void __cpuinit r3k_probe_cache(void) +static void r3k_probe_cache(void) { dcache_size = r3k_cache_size(ST0_ISC); if (dcache_size) @@ -312,7 +312,7 @@ static void r3k_dma_cache_wback_inv(unsigned long start, unsigned long size) r3k_flush_dcache_range(start, start + size); } -void __cpuinit r3k_cache_init(void) +void r3k_cache_init(void) { extern void build_clear_page(void); extern void build_copy_page(void); diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c index bda8eb26ece..6eb82ed57ff 100644 --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c @@ -106,7 +106,7 @@ static inline void r4k_blast_dcache_page_dc64(unsigned long addr) blast_dcache64_page(addr); } -static void __cpuinit r4k_blast_dcache_page_setup(void) +static void r4k_blast_dcache_page_setup(void) { unsigned long dc_lsize = cpu_dcache_line_size(); @@ -122,7 +122,7 @@ static void __cpuinit r4k_blast_dcache_page_setup(void) static void (* r4k_blast_dcache_page_indexed)(unsigned long addr); -static void __cpuinit r4k_blast_dcache_page_indexed_setup(void) +static void r4k_blast_dcache_page_indexed_setup(void) { unsigned long dc_lsize = cpu_dcache_line_size(); @@ -138,7 +138,7 @@ static void __cpuinit r4k_blast_dcache_page_indexed_setup(void) static void (* r4k_blast_dcache)(void); -static void __cpuinit r4k_blast_dcache_setup(void) +static void r4k_blast_dcache_setup(void) { unsigned long dc_lsize = cpu_dcache_line_size(); @@ -225,7 +225,7 @@ static inline void tx49_blast_icache32_page_indexed(unsigned long page) static void (* r4k_blast_icache_page)(unsigned long addr); -static void __cpuinit r4k_blast_icache_page_setup(void) +static void r4k_blast_icache_page_setup(void) { unsigned long ic_lsize = cpu_icache_line_size(); @@ -242,7 +242,7 @@ static void __cpuinit r4k_blast_icache_page_setup(void) static void (* r4k_blast_icache_page_indexed)(unsigned long addr); -static void __cpuinit r4k_blast_icache_page_indexed_setup(void) +static void r4k_blast_icache_page_indexed_setup(void) { unsigned long ic_lsize = cpu_icache_line_size(); @@ -266,7 +266,7 @@ static void __cpuinit r4k_blast_icache_page_indexed_setup(void) static void (* r4k_blast_icache)(void); -static void __cpuinit r4k_blast_icache_setup(void) +static void r4k_blast_icache_setup(void) { unsigned long ic_lsize = cpu_icache_line_size(); @@ -287,7 +287,7 @@ static void __cpuinit r4k_blast_icache_setup(void) static void (* r4k_blast_scache_page)(unsigned long addr); -static void __cpuinit r4k_blast_scache_page_setup(void) +static void r4k_blast_scache_page_setup(void) { unsigned long sc_lsize = cpu_scache_line_size(); @@ -305,7 +305,7 @@ static void __cpuinit r4k_blast_scache_page_setup(void) static void (* r4k_blast_scache_page_indexed)(unsigned long addr); -static void __cpuinit r4k_blast_scache_page_indexed_setup(void) +static void r4k_blast_scache_page_indexed_setup(void) { unsigned long sc_lsize = cpu_scache_line_size(); @@ -323,7 +323,7 @@ static void __cpuinit r4k_blast_scache_page_indexed_setup(void) static void (* r4k_blast_scache)(void); -static void __cpuinit r4k_blast_scache_setup(void) +static void r4k_blast_scache_setup(void) { unsigned long sc_lsize = cpu_scache_line_size(); @@ -786,11 +786,11 @@ static inline void rm7k_erratum31(void) } } -static char *way_string[] __cpuinitdata = { NULL, "direct mapped", "2-way", +static char *way_string[] = { NULL, "direct mapped", "2-way", "3-way", "4-way", "5-way", "6-way", "7-way", "8-way" }; -static void __cpuinit probe_pcache(void) +static void probe_pcache(void) { struct cpuinfo_mips *c = ¤t_cpu_data; unsigned int config = read_c0_config(); @@ -1107,7 +1107,7 @@ static void __cpuinit probe_pcache(void) * executes in KSEG1 space or else you will crash and burn badly. You have * been warned. */ -static int __cpuinit probe_scache(void) +static int probe_scache(void) { unsigned long flags, addr, begin, end, pow2; unsigned int config = read_c0_config(); @@ -1184,7 +1184,7 @@ extern int r5k_sc_init(void); extern int rm7k_sc_init(void); extern int mips_sc_init(void); -static void __cpuinit setup_scache(void) +static void setup_scache(void) { struct cpuinfo_mips *c = ¤t_cpu_data; unsigned int config = read_c0_config(); @@ -1320,7 +1320,7 @@ static void nxp_pr4450_fixup_config(void) NXP_BARRIER(); } -static int __cpuinitdata cca = -1; +static int cca = -1; static int __init cca_setup(char *str) { @@ -1331,7 +1331,7 @@ static int __init cca_setup(char *str) __setup("cca=", cca_setup); -static void __cpuinit coherency_setup(void) +static void coherency_setup(void) { if (cca < 0 || cca > 7) cca = read_c0_config() & CONF_CM_CMASK; @@ -1373,7 +1373,7 @@ static void __cpuinit coherency_setup(void) #if defined(CONFIG_DMA_NONCOHERENT) -static int __cpuinitdata coherentio; +static int coherentio; static int __init setcoherentio(char *str) { @@ -1385,7 +1385,7 @@ static int __init setcoherentio(char *str) __setup("coherentio", setcoherentio); #endif -void __cpuinit r4k_cache_init(void) +void r4k_cache_init(void) { extern void build_clear_page(void); extern void build_copy_page(void); diff --git a/arch/mips/mm/c-tx39.c b/arch/mips/mm/c-tx39.c index 87d23cada6d..d69a19532e6 100644 --- a/arch/mips/mm/c-tx39.c +++ b/arch/mips/mm/c-tx39.c @@ -344,7 +344,7 @@ static __init void tx39_probe_cache(void) } } -void __cpuinit tx39_cache_init(void) +void tx39_cache_init(void) { extern void build_clear_page(void); extern void build_copy_page(void); diff --git a/arch/mips/mm/cache.c b/arch/mips/mm/cache.c index 829320c7b17..cef3f0eb804 100644 --- a/arch/mips/mm/cache.c +++ b/arch/mips/mm/cache.c @@ -181,7 +181,7 @@ static inline void setup_protection_map(void) } } -void __cpuinit cpu_cache_init(void) +void cpu_cache_init(void) { if (cpu_has_3k_cache) { extern void __weak r3k_cache_init(void); diff --git a/arch/mips/mm/page.c b/arch/mips/mm/page.c index cc0b626858b..dc7cacae78c 100644 --- a/arch/mips/mm/page.c +++ b/arch/mips/mm/page.c @@ -65,8 +65,8 @@ UASM_L_LA(_copy_pref_both) UASM_L_LA(_copy_pref_store) /* We need one branch and therefore one relocation per target label. */ -static struct uasm_label __cpuinitdata labels[5]; -static struct uasm_reloc __cpuinitdata relocs[5]; +static struct uasm_label labels[5]; +static struct uasm_reloc relocs[5]; #define cpu_is_r4600_v1_x() ((read_c0_prid() & 0xfffffff0) == 0x00002010) #define cpu_is_r4600_v2_x() ((read_c0_prid() & 0xfffffff0) == 0x00002020) @@ -110,23 +110,23 @@ void copy_page(void *to, void *from) __attribute__((alias("copy_page_array"))); EXPORT_SYMBOL(copy_page); -static int pref_bias_clear_store __cpuinitdata; -static int pref_bias_copy_load __cpuinitdata; -static int pref_bias_copy_store __cpuinitdata; +static int pref_bias_clear_store; +static int pref_bias_copy_load; +static int pref_bias_copy_store; -static u32 pref_src_mode __cpuinitdata; -static u32 pref_dst_mode __cpuinitdata; +static u32 pref_src_mode; +static u32 pref_dst_mode; -static int clear_word_size __cpuinitdata; -static int copy_word_size __cpuinitdata; +static int clear_word_size; +static int copy_word_size; -static int half_clear_loop_size __cpuinitdata; -static int half_copy_loop_size __cpuinitdata; +static int half_clear_loop_size; +static int half_copy_loop_size; -static int cache_line_size __cpuinitdata; +static int cache_line_size; #define cache_line_mask() (cache_line_size - 1) -static inline void __cpuinit +static inline void pg_addiu(u32 **buf, unsigned int reg1, unsigned int reg2, unsigned int off) { if (cpu_has_64bit_gp_regs && DADDI_WAR && r4k_daddiu_bug()) { @@ -146,7 +146,7 @@ pg_addiu(u32 **buf, unsigned int reg1, unsigned int reg2, unsigned int off) } } -static void __cpuinit set_prefetch_parameters(void) +static void set_prefetch_parameters(void) { if (cpu_has_64bit_gp_regs || cpu_has_64bit_zero_reg) clear_word_size = 8; @@ -246,7 +246,7 @@ static void __cpuinit set_prefetch_parameters(void) 4 * copy_word_size)); } -static void __cpuinit build_clear_store(u32 **buf, int off) +static void build_clear_store(u32 **buf, int off) { if (cpu_has_64bit_gp_regs || cpu_has_64bit_zero_reg) { uasm_i_sd(buf, ZERO, off, A0); @@ -255,7 +255,7 @@ static void __cpuinit build_clear_store(u32 **buf, int off) } } -static inline void __cpuinit build_clear_pref(u32 **buf, int off) +static inline void build_clear_pref(u32 **buf, int off) { if (off & cache_line_mask()) return; @@ -282,7 +282,7 @@ static inline void __cpuinit build_clear_pref(u32 **buf, int off) } } -void __cpuinit build_clear_page(void) +void build_clear_page(void) { int off; u32 *buf = (u32 *)&clear_page_array; @@ -370,7 +370,7 @@ void __cpuinit build_clear_page(void) pr_debug("\t.set pop\n"); } -static void __cpuinit build_copy_load(u32 **buf, int reg, int off) +static void build_copy_load(u32 **buf, int reg, int off) { if (cpu_has_64bit_gp_regs) { uasm_i_ld(buf, reg, off, A1); @@ -379,7 +379,7 @@ static void __cpuinit build_copy_load(u32 **buf, int reg, int off) } } -static void __cpuinit build_copy_store(u32 **buf, int reg, int off) +static void build_copy_store(u32 **buf, int reg, int off) { if (cpu_has_64bit_gp_regs) { uasm_i_sd(buf, reg, off, A0); @@ -424,7 +424,7 @@ static inline void build_copy_store_pref(u32 **buf, int off) } } -void __cpuinit build_copy_page(void) +void build_copy_page(void) { int off; u32 *buf = (u32 *)©_page_array; diff --git a/arch/mips/mm/sc-ip22.c b/arch/mips/mm/sc-ip22.c index 1eb708ef75f..2895f7d1747 100644 --- a/arch/mips/mm/sc-ip22.c +++ b/arch/mips/mm/sc-ip22.c @@ -167,7 +167,7 @@ static struct bcache_ops indy_sc_ops = { .bc_inv = indy_sc_wback_invalidate }; -void __cpuinit indy_sc_init(void) +void indy_sc_init(void) { if (indy_sc_probe()) { indy_sc_enable(); diff --git a/arch/mips/mm/sc-mips.c b/arch/mips/mm/sc-mips.c index 93d937b4b1b..8361c2377bf 100644 --- a/arch/mips/mm/sc-mips.c +++ b/arch/mips/mm/sc-mips.c @@ -134,7 +134,7 @@ static inline int __init mips_sc_probe(void) return 1; } -int __cpuinit mips_sc_init(void) +int mips_sc_init(void) { int found = mips_sc_probe(); if (found) { diff --git a/arch/mips/mm/sc-r5k.c b/arch/mips/mm/sc-r5k.c index 8d90ff25b12..3873e9ef550 100644 --- a/arch/mips/mm/sc-r5k.c +++ b/arch/mips/mm/sc-r5k.c @@ -98,7 +98,7 @@ static struct bcache_ops r5k_sc_ops = { .bc_inv = r5k_dma_cache_inv_sc }; -void __cpuinit r5k_sc_init(void) +void r5k_sc_init(void) { if (r5k_sc_probe()) { r5k_sc_enable(); diff --git a/arch/mips/mm/sc-rm7k.c b/arch/mips/mm/sc-rm7k.c index 274af3be144..aaffbba3370 100644 --- a/arch/mips/mm/sc-rm7k.c +++ b/arch/mips/mm/sc-rm7k.c @@ -104,7 +104,7 @@ static void blast_rm7k_tcache(void) /* * This function is executed in uncached address space. */ -static __cpuinit void __rm7k_tc_enable(void) +static void __rm7k_tc_enable(void) { int i; @@ -117,7 +117,7 @@ static __cpuinit void __rm7k_tc_enable(void) cache_op(Index_Store_Tag_T, CKSEG0ADDR(i)); } -static __cpuinit void rm7k_tc_enable(void) +static void rm7k_tc_enable(void) { if (read_c0_config() & RM7K_CONF_TE) return; @@ -130,7 +130,7 @@ static __cpuinit void rm7k_tc_enable(void) /* * This function is executed in uncached address space. */ -static __cpuinit void __rm7k_sc_enable(void) +static void __rm7k_sc_enable(void) { int i; @@ -143,7 +143,7 @@ static __cpuinit void __rm7k_sc_enable(void) cache_op(Index_Store_Tag_SD, CKSEG0ADDR(i)); } -static __cpuinit void rm7k_sc_enable(void) +static void rm7k_sc_enable(void) { if (read_c0_config() & RM7K_CONF_SE) return; @@ -184,7 +184,7 @@ static struct bcache_ops rm7k_sc_ops = { * This is a probing function like the one found in c-r4k.c, we look for the * wrap around point with different addresses. */ -static __cpuinit void __probe_tcache(void) +static void __probe_tcache(void) { unsigned long flags, addr, begin, end, pow2; @@ -226,7 +226,7 @@ static __cpuinit void __probe_tcache(void) local_irq_restore(flags); } -void __cpuinit rm7k_sc_init(void) +void rm7k_sc_init(void) { struct cpuinfo_mips *c = ¤t_cpu_data; unsigned int config = read_c0_config(); diff --git a/arch/mips/mm/tlb-r3k.c b/arch/mips/mm/tlb-r3k.c index a63d1ed0827..9aca10994cd 100644 --- a/arch/mips/mm/tlb-r3k.c +++ b/arch/mips/mm/tlb-r3k.c @@ -276,7 +276,7 @@ void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, } } -void __cpuinit tlb_init(void) +void tlb_init(void) { local_flush_tlb_all(); diff --git a/arch/mips/mm/tlb-r4k.c b/arch/mips/mm/tlb-r4k.c index d2572cb232d..d727fe71c73 100644 --- a/arch/mips/mm/tlb-r4k.c +++ b/arch/mips/mm/tlb-r4k.c @@ -376,7 +376,7 @@ void add_wired_entry(unsigned long entrylo0, unsigned long entrylo1, EXIT_CRITICAL(flags); } -static int __cpuinitdata ntlb; +static int ntlb; static int __init set_ntlb(char *str) { get_option(&str, &ntlb); @@ -385,7 +385,7 @@ static int __init set_ntlb(char *str) __setup("ntlb=", set_ntlb); -void __cpuinit tlb_init(void) +void tlb_init(void) { /* * You should never change this register: diff --git a/arch/mips/mm/tlb-r8k.c b/arch/mips/mm/tlb-r8k.c index 91c2499f806..6a99733a444 100644 --- a/arch/mips/mm/tlb-r8k.c +++ b/arch/mips/mm/tlb-r8k.c @@ -213,14 +213,14 @@ void __update_tlb(struct vm_area_struct * vma, unsigned long address, pte_t pte) local_irq_restore(flags); } -static void __cpuinit probe_tlb(unsigned long config) +static void probe_tlb(unsigned long config) { struct cpuinfo_mips *c = ¤t_cpu_data; c->tlbsize = 3 * 128; /* 3 sets each 128 entries */ } -void __cpuinit tlb_init(void) +void tlb_init(void) { unsigned int config = read_c0_config(); unsigned long status; diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index 0bc485b3cd6..7f61bfb554f 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -135,7 +135,7 @@ static int scratchpad_offset(int i) * why; it's not an issue caused by the core RTL. * */ -static int __cpuinit m4kc_tlbp_war(void) +static int m4kc_tlbp_war(void) { return (current_cpu_data.processor_id & 0xffff00) == (PRID_COMP_MIPS | PRID_IMP_4KC); @@ -226,21 +226,21 @@ static inline void dump_handler(const u32 *handler, int count) * We deliberately chose a buffer size of 128, so we won't scribble * over anything important on overflow before we panic. */ -static u32 tlb_handler[128] __cpuinitdata; +static u32 tlb_handler[128]; /* simply assume worst case size for labels and relocs */ -static struct uasm_label labels[128] __cpuinitdata; -static struct uasm_reloc relocs[128] __cpuinitdata; +static struct uasm_label labels[128]; +static struct uasm_reloc relocs[128]; #ifdef CONFIG_64BIT -static int check_for_high_segbits __cpuinitdata; +static int check_for_high_segbits; #endif -static int check_for_high_segbits __cpuinitdata; +static int check_for_high_segbits; -static unsigned int kscratch_used_mask __cpuinitdata; +static unsigned int kscratch_used_mask; -static int __cpuinit allocate_kscratch(void) +static int allocate_kscratch(void) { int r; unsigned int a = cpu_data[0].kscratch_mask & ~kscratch_used_mask; @@ -257,11 +257,11 @@ static int __cpuinit allocate_kscratch(void) return r; } -static int scratch_reg __cpuinitdata; -static int pgd_reg __cpuinitdata; +static int scratch_reg; +static int pgd_reg; enum vmalloc64_mode {not_refill, refill_scratch, refill_noscratch}; -static struct work_registers __cpuinit build_get_work_registers(u32 **p) +static struct work_registers build_get_work_registers(u32 **p) { struct work_registers r; @@ -317,7 +317,7 @@ static struct work_registers __cpuinit build_get_work_registers(u32 **p) return r; } -static void __cpuinit build_restore_work_registers(u32 **p) +static void build_restore_work_registers(u32 **p) { if (scratch_reg > 0) { UASM_i_MFC0(p, 1, 31, scratch_reg); @@ -342,7 +342,7 @@ extern unsigned long pgd_current[]; /* * The R3000 TLB handler is simple. */ -static void __cpuinit build_r3000_tlb_refill_handler(void) +static void build_r3000_tlb_refill_handler(void) { long pgdc = (long)pgd_current; u32 *p; @@ -387,7 +387,7 @@ static void __cpuinit build_r3000_tlb_refill_handler(void) * other one.To keep things simple, we first assume linear space, * then we relocate it to the final handler layout as needed. */ -static u32 final_handler[64] __cpuinitdata; +static u32 final_handler[64]; /* * Hazards @@ -411,7 +411,7 @@ static u32 final_handler[64] __cpuinitdata; * * As if we MIPS hackers wouldn't know how to nop pipelines happy ... */ -static void __cpuinit __maybe_unused build_tlb_probe_entry(u32 **p) +static void __maybe_unused build_tlb_probe_entry(u32 **p) { switch (current_cpu_type()) { /* Found by experiment: R4600 v2.0/R4700 needs this, too. */ @@ -436,7 +436,7 @@ static void __cpuinit __maybe_unused build_tlb_probe_entry(u32 **p) */ enum tlb_write_entry { tlb_random, tlb_indexed }; -static void __cpuinit build_tlb_write_entry(u32 **p, struct uasm_label **l, +static void build_tlb_write_entry(u32 **p, struct uasm_label **l, struct uasm_reloc **r, enum tlb_write_entry wmode) { @@ -581,7 +581,7 @@ static void __cpuinit build_tlb_write_entry(u32 **p, struct uasm_label **l, } } -static __cpuinit __maybe_unused void build_convert_pte_to_entrylo(u32 **p, +static __maybe_unused void build_convert_pte_to_entrylo(u32 **p, unsigned int reg) { if (kernel_uses_smartmips_rixi) { @@ -598,7 +598,7 @@ static __cpuinit __maybe_unused void build_convert_pte_to_entrylo(u32 **p, #ifdef CONFIG_HUGETLB_PAGE -static __cpuinit void build_restore_pagemask(u32 **p, +static void build_restore_pagemask(u32 **p, struct uasm_reloc **r, unsigned int tmp, enum label_id lid, @@ -641,7 +641,7 @@ static __cpuinit void build_restore_pagemask(u32 **p, } } -static __cpuinit void build_huge_tlb_write_entry(u32 **p, +static void build_huge_tlb_write_entry(u32 **p, struct uasm_label **l, struct uasm_reloc **r, unsigned int tmp, @@ -661,7 +661,7 @@ static __cpuinit void build_huge_tlb_write_entry(u32 **p, /* * Check if Huge PTE is present, if so then jump to LABEL. */ -static void __cpuinit +static void build_is_huge_pte(u32 **p, struct uasm_reloc **r, unsigned int tmp, unsigned int pmd, int lid) { @@ -674,7 +674,7 @@ build_is_huge_pte(u32 **p, struct uasm_reloc **r, unsigned int tmp, } } -static __cpuinit void build_huge_update_entries(u32 **p, +static void build_huge_update_entries(u32 **p, unsigned int pte, unsigned int tmp) { @@ -706,7 +706,7 @@ static __cpuinit void build_huge_update_entries(u32 **p, UASM_i_MTC0(p, pte, C0_ENTRYLO1); /* load it */ } -static __cpuinit void build_huge_handler_tail(u32 **p, +static void build_huge_handler_tail(u32 **p, struct uasm_reloc **r, struct uasm_label **l, unsigned int pte, @@ -729,7 +729,7 @@ static __cpuinit void build_huge_handler_tail(u32 **p, * TMP and PTR are scratch. * TMP will be clobbered, PTR will hold the pmd entry. */ -static void __cpuinit +static void build_get_pmde64(u32 **p, struct uasm_label **l, struct uasm_reloc **r, unsigned int tmp, unsigned int ptr) { @@ -821,7 +821,7 @@ build_get_pmde64(u32 **p, struct uasm_label **l, struct uasm_reloc **r, * BVADDR is the faulting address, PTR is scratch. * PTR will hold the pgd for vmalloc. */ -static void __cpuinit +static void build_get_pgd_vmalloc64(u32 **p, struct uasm_label **l, struct uasm_reloc **r, unsigned int bvaddr, unsigned int ptr, enum vmalloc64_mode mode) @@ -891,7 +891,7 @@ build_get_pgd_vmalloc64(u32 **p, struct uasm_label **l, struct uasm_reloc **r, * TMP and PTR are scratch. * TMP will be clobbered, PTR will hold the pgd entry. */ -static void __cpuinit __maybe_unused +static void __maybe_unused build_get_pgde32(u32 **p, unsigned int tmp, unsigned int ptr) { long pgdc = (long)pgd_current; @@ -926,7 +926,7 @@ build_get_pgde32(u32 **p, unsigned int tmp, unsigned int ptr) #endif /* !CONFIG_64BIT */ -static void __cpuinit build_adjust_context(u32 **p, unsigned int ctx) +static void build_adjust_context(u32 **p, unsigned int ctx) { unsigned int shift = 4 - (PTE_T_LOG2 + 1) + PAGE_SHIFT - 12; unsigned int mask = (PTRS_PER_PTE / 2 - 1) << (PTE_T_LOG2 + 1); @@ -952,7 +952,7 @@ static void __cpuinit build_adjust_context(u32 **p, unsigned int ctx) uasm_i_andi(p, ctx, ctx, mask); } -static void __cpuinit build_get_ptep(u32 **p, unsigned int tmp, unsigned int ptr) +static void build_get_ptep(u32 **p, unsigned int tmp, unsigned int ptr) { /* * Bug workaround for the Nevada. It seems as if under certain @@ -977,7 +977,7 @@ static void __cpuinit build_get_ptep(u32 **p, unsigned int tmp, unsigned int ptr UASM_i_ADDU(p, ptr, ptr, tmp); /* add in offset */ } -static void __cpuinit build_update_entries(u32 **p, unsigned int tmp, +static void build_update_entries(u32 **p, unsigned int tmp, unsigned int ptep) { /* @@ -1043,7 +1043,7 @@ struct mips_huge_tlb_info { int restore_scratch; }; -static struct mips_huge_tlb_info __cpuinit +static struct mips_huge_tlb_info build_fast_tlb_refill_handler (u32 **p, struct uasm_label **l, struct uasm_reloc **r, unsigned int tmp, unsigned int ptr, int c0_scratch) @@ -1225,7 +1225,7 @@ build_fast_tlb_refill_handler (u32 **p, struct uasm_label **l, */ #define MIPS64_REFILL_INSNS 32 -static void __cpuinit build_r4000_tlb_refill_handler(void) +static void build_r4000_tlb_refill_handler(void) { u32 *p = tlb_handler; struct uasm_label *l = labels; @@ -1410,7 +1410,7 @@ u32 handle_tlbm[FASTPATH_SIZE] __cacheline_aligned; #ifdef CONFIG_MIPS_PGD_C0_CONTEXT u32 tlbmiss_handler_setup_pgd[16] __cacheline_aligned; -static void __cpuinit build_r4000_setup_pgd(void) +static void build_r4000_setup_pgd(void) { const int a0 = 4; const int a1 = 5; @@ -1457,7 +1457,7 @@ static void __cpuinit build_r4000_setup_pgd(void) } #endif -static void __cpuinit +static void iPTE_LW(u32 **p, unsigned int pte, unsigned int ptr) { #ifdef CONFIG_SMP @@ -1477,7 +1477,7 @@ iPTE_LW(u32 **p, unsigned int pte, unsigned int ptr) #endif } -static void __cpuinit +static void iPTE_SW(u32 **p, struct uasm_reloc **r, unsigned int pte, unsigned int ptr, unsigned int mode) { @@ -1537,7 +1537,7 @@ iPTE_SW(u32 **p, struct uasm_reloc **r, unsigned int pte, unsigned int ptr, * the page table where this PTE is located, PTE will be re-loaded * with it's original value. */ -static void __cpuinit +static void build_pte_present(u32 **p, struct uasm_reloc **r, int pte, int ptr, int scratch, enum label_id lid) { @@ -1565,7 +1565,7 @@ build_pte_present(u32 **p, struct uasm_reloc **r, } /* Make PTE valid, store result in PTR. */ -static void __cpuinit +static void build_make_valid(u32 **p, struct uasm_reloc **r, unsigned int pte, unsigned int ptr) { @@ -1578,7 +1578,7 @@ build_make_valid(u32 **p, struct uasm_reloc **r, unsigned int pte, * Check if PTE can be written to, if not branch to LABEL. Regardless * restore PTE with value from PTR when done. */ -static void __cpuinit +static void build_pte_writable(u32 **p, struct uasm_reloc **r, unsigned int pte, unsigned int ptr, int scratch, enum label_id lid) @@ -1598,7 +1598,7 @@ build_pte_writable(u32 **p, struct uasm_reloc **r, /* Make PTE writable, update software status bits as well, then store * at PTR. */ -static void __cpuinit +static void build_make_write(u32 **p, struct uasm_reloc **r, unsigned int pte, unsigned int ptr) { @@ -1612,7 +1612,7 @@ build_make_write(u32 **p, struct uasm_reloc **r, unsigned int pte, * Check if PTE can be modified, if not branch to LABEL. Regardless * restore PTE with value from PTR when done. */ -static void __cpuinit +static void build_pte_modifiable(u32 **p, struct uasm_reloc **r, unsigned int pte, unsigned int ptr, int scratch, enum label_id lid) @@ -1641,7 +1641,7 @@ build_pte_modifiable(u32 **p, struct uasm_reloc **r, * This places the pte into ENTRYLO0 and writes it with tlbwi. * Then it returns. */ -static void __cpuinit +static void build_r3000_pte_reload_tlbwi(u32 **p, unsigned int pte, unsigned int tmp) { uasm_i_mtc0(p, pte, C0_ENTRYLO0); /* cp0 delay */ @@ -1657,7 +1657,7 @@ build_r3000_pte_reload_tlbwi(u32 **p, unsigned int pte, unsigned int tmp) * may have the probe fail bit set as a result of a trap on a * kseg2 access, i.e. without refill. Then it returns. */ -static void __cpuinit +static void build_r3000_tlb_reload_write(u32 **p, struct uasm_label **l, struct uasm_reloc **r, unsigned int pte, unsigned int tmp) @@ -1675,7 +1675,7 @@ build_r3000_tlb_reload_write(u32 **p, struct uasm_label **l, uasm_i_rfe(p); /* branch delay */ } -static void __cpuinit +static void build_r3000_tlbchange_handler_head(u32 **p, unsigned int pte, unsigned int ptr) { @@ -1695,7 +1695,7 @@ build_r3000_tlbchange_handler_head(u32 **p, unsigned int pte, uasm_i_tlbp(p); /* load delay */ } -static void __cpuinit build_r3000_tlb_load_handler(void) +static void build_r3000_tlb_load_handler(void) { u32 *p = handle_tlbl; struct uasm_label *l = labels; @@ -1725,7 +1725,7 @@ static void __cpuinit build_r3000_tlb_load_handler(void) dump_handler(handle_tlbl, ARRAY_SIZE(handle_tlbl)); } -static void __cpuinit build_r3000_tlb_store_handler(void) +static void build_r3000_tlb_store_handler(void) { u32 *p = handle_tlbs; struct uasm_label *l = labels; @@ -1755,7 +1755,7 @@ static void __cpuinit build_r3000_tlb_store_handler(void) dump_handler(handle_tlbs, ARRAY_SIZE(handle_tlbs)); } -static void __cpuinit build_r3000_tlb_modify_handler(void) +static void build_r3000_tlb_modify_handler(void) { u32 *p = handle_tlbm; struct uasm_label *l = labels; @@ -1789,7 +1789,7 @@ static void __cpuinit build_r3000_tlb_modify_handler(void) /* * R4000 style TLB load/store/modify handlers. */ -static struct work_registers __cpuinit +static struct work_registers build_r4000_tlbchange_handler_head(u32 **p, struct uasm_label **l, struct uasm_reloc **r) { @@ -1825,7 +1825,7 @@ build_r4000_tlbchange_handler_head(u32 **p, struct uasm_label **l, return wr; } -static void __cpuinit +static void build_r4000_tlbchange_handler_tail(u32 **p, struct uasm_label **l, struct uasm_reloc **r, unsigned int tmp, unsigned int ptr) @@ -1843,7 +1843,7 @@ build_r4000_tlbchange_handler_tail(u32 **p, struct uasm_label **l, #endif } -static void __cpuinit build_r4000_tlb_load_handler(void) +static void build_r4000_tlb_load_handler(void) { u32 *p = handle_tlbl; struct uasm_label *l = labels; @@ -1992,7 +1992,7 @@ static void __cpuinit build_r4000_tlb_load_handler(void) dump_handler(handle_tlbl, ARRAY_SIZE(handle_tlbl)); } -static void __cpuinit build_r4000_tlb_store_handler(void) +static void build_r4000_tlb_store_handler(void) { u32 *p = handle_tlbs; struct uasm_label *l = labels; @@ -2039,7 +2039,7 @@ static void __cpuinit build_r4000_tlb_store_handler(void) dump_handler(handle_tlbs, ARRAY_SIZE(handle_tlbs)); } -static void __cpuinit build_r4000_tlb_modify_handler(void) +static void build_r4000_tlb_modify_handler(void) { u32 *p = handle_tlbm; struct uasm_label *l = labels; @@ -2087,7 +2087,7 @@ static void __cpuinit build_r4000_tlb_modify_handler(void) dump_handler(handle_tlbm, ARRAY_SIZE(handle_tlbm)); } -void __cpuinit build_tlb_refill_handler(void) +void build_tlb_refill_handler(void) { /* * The refill handler is generated per-CPU, multi-node systems @@ -2145,7 +2145,7 @@ void __cpuinit build_tlb_refill_handler(void) } } -void __cpuinit flush_tlb_handlers(void) +void flush_tlb_handlers(void) { local_flush_icache_range((unsigned long)handle_tlbl, (unsigned long)handle_tlbl + sizeof(handle_tlbl)); diff --git a/arch/mips/mti-malta/malta-smtc.c b/arch/mips/mti-malta/malta-smtc.c index 1efc8c39448..ed39c489c14 100644 --- a/arch/mips/mti-malta/malta-smtc.c +++ b/arch/mips/mti-malta/malta-smtc.c @@ -32,7 +32,7 @@ static void msmtc_send_ipi_mask(const struct cpumask *mask, unsigned int action) /* * Post-config but pre-boot cleanup entry point */ -static void __cpuinit msmtc_init_secondary(void) +static void msmtc_init_secondary(void) { int myvpe; @@ -53,7 +53,7 @@ static void __cpuinit msmtc_init_secondary(void) /* * Platform "CPU" startup hook */ -static void __cpuinit msmtc_boot_secondary(int cpu, struct task_struct *idle) +static void msmtc_boot_secondary(int cpu, struct task_struct *idle) { smtc_boot_secondary(cpu, idle); } @@ -61,7 +61,7 @@ static void __cpuinit msmtc_boot_secondary(int cpu, struct task_struct *idle) /* * SMP initialization finalization entry point */ -static void __cpuinit msmtc_smp_finish(void) +static void msmtc_smp_finish(void) { smtc_smp_finish(); } diff --git a/arch/mips/mti-malta/malta-time.c b/arch/mips/mti-malta/malta-time.c index 115f5bc0600..7b7fc803867 100644 --- a/arch/mips/mti-malta/malta-time.c +++ b/arch/mips/mti-malta/malta-time.c @@ -125,7 +125,7 @@ static void __init plat_perf_setup(void) } } -unsigned int __cpuinit get_c0_compare_int(void) +unsigned int get_c0_compare_int(void) { #ifdef MSC01E_INT_BASE if (cpu_has_veic) { diff --git a/arch/mips/netlogic/common/irq.c b/arch/mips/netlogic/common/irq.c index e52bfcbce09..d0014b18a85 100644 --- a/arch/mips/netlogic/common/irq.c +++ b/arch/mips/netlogic/common/irq.c @@ -212,7 +212,7 @@ void __init arch_init_irq(void) write_c0_eimr(nlm_irq_mask); } -void __cpuinit nlm_smp_irq_init(void) +void nlm_smp_irq_init(void) { /* set interrupt mask for non-zero cpus */ write_c0_eimr(nlm_irq_mask); diff --git a/arch/mips/netlogic/common/smp.c b/arch/mips/netlogic/common/smp.c index fab316de57e..6bd07eb752b 100644 --- a/arch/mips/netlogic/common/smp.c +++ b/arch/mips/netlogic/common/smp.c @@ -106,7 +106,7 @@ void nlm_early_init_secondary(int cpu) /* * Code to run on secondary just after probing the CPU */ -static void __cpuinit nlm_init_secondary(void) +static void nlm_init_secondary(void) { current_cpu_data.core = hard_smp_processor_id() / 4; nlm_smp_irq_init(); @@ -232,7 +232,7 @@ static int nlm_parse_cpumask(u32 cpu_mask) return 0; } -int __cpuinit nlm_wakeup_secondary_cpus(u32 wakeup_mask) +int nlm_wakeup_secondary_cpus(u32 wakeup_mask) { unsigned long reset_vec; char *reset_data; diff --git a/arch/mips/netlogic/common/time.c b/arch/mips/netlogic/common/time.c index bd3e498157f..754f12fe6ec 100644 --- a/arch/mips/netlogic/common/time.c +++ b/arch/mips/netlogic/common/time.c @@ -38,7 +38,7 @@ #include #include -unsigned int __cpuinit get_c0_compare_int(void) +unsigned int get_c0_compare_int(void) { return IRQ_TIMER; } diff --git a/arch/mips/netlogic/xlr/wakeup.c b/arch/mips/netlogic/xlr/wakeup.c index db5d987d488..481010819f9 100644 --- a/arch/mips/netlogic/xlr/wakeup.c +++ b/arch/mips/netlogic/xlr/wakeup.c @@ -48,7 +48,7 @@ #include #include -int __cpuinit xlr_wakeup_secondary_cpus(void) +int xlr_wakeup_secondary_cpus(void) { unsigned int i, boot_cpu; diff --git a/arch/mips/pci/pci-ip27.c b/arch/mips/pci/pci-ip27.c index 0fbe4c0c170..c1336762a5d 100644 --- a/arch/mips/pci/pci-ip27.c +++ b/arch/mips/pci/pci-ip27.c @@ -42,7 +42,7 @@ int irq_to_slot[MAX_PCI_BUSSES * MAX_DEVICES_PER_PCIBUS]; extern struct pci_ops bridge_pci_ops; -int __cpuinit bridge_probe(nasid_t nasid, int widget_id, int masterwid) +int bridge_probe(nasid_t nasid, int widget_id, int masterwid) { unsigned long offset = NODE_OFFSET(nasid); struct bridge_controller *bc; diff --git a/arch/mips/pmc-sierra/msp71xx/msp_smtc.c b/arch/mips/pmc-sierra/msp71xx/msp_smtc.c index c8dcc1c01e1..6aa91401ddf 100644 --- a/arch/mips/pmc-sierra/msp71xx/msp_smtc.c +++ b/arch/mips/pmc-sierra/msp71xx/msp_smtc.c @@ -33,7 +33,7 @@ static void msp_smtc_send_ipi_mask(const struct cpumask *mask, /* * Post-config but pre-boot cleanup entry point */ -static void __cpuinit msp_smtc_init_secondary(void) +static void msp_smtc_init_secondary(void) { int myvpe; @@ -48,7 +48,7 @@ static void __cpuinit msp_smtc_init_secondary(void) /* * Platform "CPU" startup hook */ -static void __cpuinit msp_smtc_boot_secondary(int cpu, +static void msp_smtc_boot_secondary(int cpu, struct task_struct *idle) { smtc_boot_secondary(cpu, idle); @@ -57,7 +57,7 @@ static void __cpuinit msp_smtc_boot_secondary(int cpu, /* * SMP initialization finalization entry point */ -static void __cpuinit msp_smtc_smp_finish(void) +static void msp_smtc_smp_finish(void) { smtc_smp_finish(); } diff --git a/arch/mips/pmc-sierra/msp71xx/msp_time.c b/arch/mips/pmc-sierra/msp71xx/msp_time.c index 8b42f307a7a..98b426eb39b 100644 --- a/arch/mips/pmc-sierra/msp71xx/msp_time.c +++ b/arch/mips/pmc-sierra/msp71xx/msp_time.c @@ -88,7 +88,7 @@ void __init plat_time_init(void) mips_hpt_frequency = cpu_rate/2; } -unsigned int __cpuinit get_c0_compare_int(void) +unsigned int get_c0_compare_int(void) { /* MIPS_MT modes may want timer for second VPE */ if ((get_current_vpe()) && !tim_installed) { diff --git a/arch/mips/pmc-sierra/yosemite/smp.c b/arch/mips/pmc-sierra/yosemite/smp.c index b71fae23104..7e3b591f78e 100644 --- a/arch/mips/pmc-sierra/yosemite/smp.c +++ b/arch/mips/pmc-sierra/yosemite/smp.c @@ -8,10 +8,10 @@ #define LAUNCHSTACK_SIZE 256 -static __cpuinitdata arch_spinlock_t launch_lock = __ARCH_SPIN_LOCK_UNLOCKED; +static arch_spinlock_t launch_lock = __ARCH_SPIN_LOCK_UNLOCKED; -static unsigned long secondary_sp __cpuinitdata; -static unsigned long secondary_gp __cpuinitdata; +static unsigned long secondary_sp; +static unsigned long secondary_gp; static unsigned char launchstack[LAUNCHSTACK_SIZE] __initdata __attribute__((aligned(2 * sizeof(long)))); @@ -113,12 +113,12 @@ static void yos_send_ipi_mask(const struct cpumask *mask, unsigned int action) * After we've done initial boot, this function is called to allow the * board code to clean up state, if needed */ -static void __cpuinit yos_init_secondary(void) +static void yos_init_secondary(void) { set_c0_status(ST0_CO | ST0_IE | ST0_IM); } -static void __cpuinit yos_smp_finish(void) +static void yos_smp_finish(void) { } @@ -134,7 +134,7 @@ static void yos_cpus_done(void) * stack so the first thing we do is throw away that stuff and load useful * values into the registers ... */ -static void __cpuinit yos_boot_secondary(int cpu, struct task_struct *idle) +static void yos_boot_secondary(int cpu, struct task_struct *idle) { unsigned long gp = (unsigned long) task_thread_info(idle); unsigned long sp = __KSTK_TOS(idle); diff --git a/arch/mips/pnx833x/common/interrupts.c b/arch/mips/pnx833x/common/interrupts.c index a86d5d5fceb..ff5cd9ab120 100644 --- a/arch/mips/pnx833x/common/interrupts.c +++ b/arch/mips/pnx833x/common/interrupts.c @@ -281,7 +281,7 @@ void __init arch_init_irq(void) write_c0_status(read_c0_status() | IE_IRQ2); } -unsigned int __cpuinit get_c0_compare_int(void) +unsigned int get_c0_compare_int(void) { if (cpu_has_vint) set_vi_handler(cp0_compare_irq, pnx833x_timer_dispatch); diff --git a/arch/mips/powertv/time.c b/arch/mips/powertv/time.c index 9fd7b67f2af..f38b0d45eca 100644 --- a/arch/mips/powertv/time.c +++ b/arch/mips/powertv/time.c @@ -25,7 +25,7 @@ #include "powertv-clock.h" -unsigned int __cpuinit get_c0_compare_int(void) +unsigned int get_c0_compare_int(void) { return irq_mips_timer; } diff --git a/arch/mips/sgi-ip27/ip27-init.c b/arch/mips/sgi-ip27/ip27-init.c index 923c080f77b..2abd0377f2c 100644 --- a/arch/mips/sgi-ip27/ip27-init.c +++ b/arch/mips/sgi-ip27/ip27-init.c @@ -54,7 +54,7 @@ extern void pcibr_setup(cnodeid_t); extern void xtalk_probe_node(cnodeid_t nid); -static void __cpuinit per_hub_init(cnodeid_t cnode) +static void per_hub_init(cnodeid_t cnode) { struct hub_data *hub = hub_data(cnode); nasid_t nasid = COMPACT_TO_NASID_NODEID(cnode); @@ -110,7 +110,7 @@ static void __cpuinit per_hub_init(cnodeid_t cnode) } } -void __cpuinit per_cpu_init(void) +void per_cpu_init(void) { int cpu = smp_processor_id(); int slice = LOCAL_HUB_L(PI_CPU_NUM); diff --git a/arch/mips/sgi-ip27/ip27-smp.c b/arch/mips/sgi-ip27/ip27-smp.c index 735b43bf8f8..2db745955e8 100644 --- a/arch/mips/sgi-ip27/ip27-smp.c +++ b/arch/mips/sgi-ip27/ip27-smp.c @@ -173,12 +173,12 @@ static void ip27_send_ipi_mask(const struct cpumask *mask, unsigned int action) ip27_send_ipi_single(i, action); } -static void __cpuinit ip27_init_secondary(void) +static void ip27_init_secondary(void) { per_cpu_init(); } -static void __cpuinit ip27_smp_finish(void) +static void ip27_smp_finish(void) { extern void hub_rt_clock_event_init(void); @@ -195,7 +195,7 @@ static void __init ip27_cpus_done(void) * set sp to the kernel stack of the newly created idle process, gp to the proc * struct so that current_thread_info() will work. */ -static void __cpuinit ip27_boot_secondary(int cpu, struct task_struct *idle) +static void ip27_boot_secondary(int cpu, struct task_struct *idle) { unsigned long gp = (unsigned long)task_thread_info(idle); unsigned long sp = __KSTK_TOS(idle); diff --git a/arch/mips/sgi-ip27/ip27-timer.c b/arch/mips/sgi-ip27/ip27-timer.c index 13cfeab5052..8788f0142d2 100644 --- a/arch/mips/sgi-ip27/ip27-timer.c +++ b/arch/mips/sgi-ip27/ip27-timer.c @@ -106,7 +106,7 @@ struct irqaction hub_rt_irqaction = { #define NSEC_PER_CYCLE 800 #define CYCLES_PER_SEC (NSEC_PER_SEC / NSEC_PER_CYCLE) -void __cpuinit hub_rt_clock_event_init(void) +void hub_rt_clock_event_init(void) { unsigned int cpu = smp_processor_id(); struct clock_event_device *cd = &per_cpu(hub_rt_clockevent, cpu); @@ -173,7 +173,7 @@ void __init plat_time_init(void) hub_rt_clock_event_init(); } -void __cpuinit cpu_time_init(void) +void cpu_time_init(void) { lboard_t *board; klcpu_t *cpu; @@ -194,7 +194,7 @@ void __cpuinit cpu_time_init(void) set_c0_status(SRB_TIMOCLK); } -void __cpuinit hub_rtc_init(cnodeid_t cnode) +void hub_rtc_init(cnodeid_t cnode) { /* diff --git a/arch/mips/sgi-ip27/ip27-xtalk.c b/arch/mips/sgi-ip27/ip27-xtalk.c index 5e871e75a8d..88490a63664 100644 --- a/arch/mips/sgi-ip27/ip27-xtalk.c +++ b/arch/mips/sgi-ip27/ip27-xtalk.c @@ -23,7 +23,7 @@ extern int bridge_probe(nasid_t nasid, int widget, int masterwid); -static int __cpuinit probe_one_port(nasid_t nasid, int widget, int masterwid) +static int probe_one_port(nasid_t nasid, int widget, int masterwid) { widgetreg_t widget_id; xwidget_part_num_t partnum; @@ -47,7 +47,7 @@ static int __cpuinit probe_one_port(nasid_t nasid, int widget, int masterwid) return 0; } -static int __cpuinit xbow_probe(nasid_t nasid) +static int xbow_probe(nasid_t nasid) { lboard_t *brd; klxbow_t *xbow_p; @@ -100,7 +100,7 @@ static int __cpuinit xbow_probe(nasid_t nasid) return 0; } -void __cpuinit xtalk_probe_node(cnodeid_t nid) +void xtalk_probe_node(cnodeid_t nid) { volatile u64 hubreg; nasid_t nasid; diff --git a/arch/mips/sibyte/bcm1480/smp.c b/arch/mips/sibyte/bcm1480/smp.c index de88e22694a..54e2c4de15c 100644 --- a/arch/mips/sibyte/bcm1480/smp.c +++ b/arch/mips/sibyte/bcm1480/smp.c @@ -60,7 +60,7 @@ static void *mailbox_0_regs[] = { /* * SMP init and finish on secondary CPUs */ -void __cpuinit bcm1480_smp_init(void) +void bcm1480_smp_init(void) { unsigned int imask = STATUSF_IP4 | STATUSF_IP3 | STATUSF_IP2 | STATUSF_IP1 | STATUSF_IP0; @@ -95,7 +95,7 @@ static void bcm1480_send_ipi_mask(const struct cpumask *mask, /* * Code to run on secondary just after probing the CPU */ -static void __cpuinit bcm1480_init_secondary(void) +static void bcm1480_init_secondary(void) { extern void bcm1480_smp_init(void); @@ -106,7 +106,7 @@ static void __cpuinit bcm1480_init_secondary(void) * Do any tidying up before marking online and running the idle * loop */ -static void __cpuinit bcm1480_smp_finish(void) +static void bcm1480_smp_finish(void) { extern void sb1480_clockevent_init(void); @@ -125,7 +125,7 @@ static void bcm1480_cpus_done(void) * Setup the PC, SP, and GP of a secondary processor and start it * running! */ -static void __cpuinit bcm1480_boot_secondary(int cpu, struct task_struct *idle) +static void bcm1480_boot_secondary(int cpu, struct task_struct *idle) { int retval; diff --git a/arch/mips/sibyte/sb1250/smp.c b/arch/mips/sibyte/sb1250/smp.c index 285cfef4ebc..d7b942db0ea 100644 --- a/arch/mips/sibyte/sb1250/smp.c +++ b/arch/mips/sibyte/sb1250/smp.c @@ -48,7 +48,7 @@ static void *mailbox_regs[] = { /* * SMP init and finish on secondary CPUs */ -void __cpuinit sb1250_smp_init(void) +void sb1250_smp_init(void) { unsigned int imask = STATUSF_IP4 | STATUSF_IP3 | STATUSF_IP2 | STATUSF_IP1 | STATUSF_IP0; @@ -83,7 +83,7 @@ static inline void sb1250_send_ipi_mask(const struct cpumask *mask, /* * Code to run on secondary just after probing the CPU */ -static void __cpuinit sb1250_init_secondary(void) +static void sb1250_init_secondary(void) { extern void sb1250_smp_init(void); @@ -94,7 +94,7 @@ static void __cpuinit sb1250_init_secondary(void) * Do any tidying up before marking online and running the idle * loop */ -static void __cpuinit sb1250_smp_finish(void) +static void sb1250_smp_finish(void) { extern void sb1250_clockevent_init(void); @@ -113,7 +113,7 @@ static void sb1250_cpus_done(void) * Setup the PC, SP, and GP of a secondary processor and start it * running! */ -static void __cpuinit sb1250_boot_secondary(int cpu, struct task_struct *idle) +static void sb1250_boot_secondary(int cpu, struct task_struct *idle) { int retval; diff --git a/arch/openrisc/kernel/setup.c b/arch/openrisc/kernel/setup.c index f4d5bedc3b4..d7359ffbcbd 100644 --- a/arch/openrisc/kernel/setup.c +++ b/arch/openrisc/kernel/setup.c @@ -267,7 +267,7 @@ void __init detect_unit_config(unsigned long upr, unsigned long mask, * */ -void __cpuinit calibrate_delay(void) +void calibrate_delay(void) { const int *val; struct device_node *cpu = NULL; diff --git a/arch/parisc/kernel/firmware.c b/arch/parisc/kernel/firmware.c index f65fa480c90..4e6a60470bc 100644 --- a/arch/parisc/kernel/firmware.c +++ b/arch/parisc/kernel/firmware.c @@ -150,7 +150,7 @@ static void convert_to_wide(unsigned long *addr) } #ifdef CONFIG_64BIT -void __cpuinit set_firmware_width_unlocked(void) +void set_firmware_width_unlocked(void) { int ret; @@ -167,7 +167,7 @@ void __cpuinit set_firmware_width_unlocked(void) * This function must be called before any pdc_* function that uses the * convert_to_wide function. */ -void __cpuinit set_firmware_width(void) +void set_firmware_width(void) { unsigned long flags; spin_lock_irqsave(&pdc_lock, flags); @@ -175,11 +175,11 @@ void __cpuinit set_firmware_width(void) spin_unlock_irqrestore(&pdc_lock, flags); } #else -void __cpuinit set_firmware_width_unlocked(void) { +void set_firmware_width_unlocked(void) { return; } -void __cpuinit set_firmware_width(void) { +void set_firmware_width(void) { return; } #endif /*CONFIG_64BIT*/ @@ -301,7 +301,7 @@ int pdc_chassis_warn(unsigned long *warn) return retval; } -int __cpuinit pdc_coproc_cfg_unlocked(struct pdc_coproc_cfg *pdc_coproc_info) +int pdc_coproc_cfg_unlocked(struct pdc_coproc_cfg *pdc_coproc_info) { int ret; @@ -322,7 +322,7 @@ int __cpuinit pdc_coproc_cfg_unlocked(struct pdc_coproc_cfg *pdc_coproc_info) * This PDC call returns the presence and status of all the coprocessors * attached to the processor. */ -int __cpuinit pdc_coproc_cfg(struct pdc_coproc_cfg *pdc_coproc_info) +int pdc_coproc_cfg(struct pdc_coproc_cfg *pdc_coproc_info) { int ret; unsigned long flags; diff --git a/arch/parisc/kernel/hardware.c b/arch/parisc/kernel/hardware.c index f48a640b55f..7ccc146d748 100644 --- a/arch/parisc/kernel/hardware.c +++ b/arch/parisc/kernel/hardware.c @@ -1366,7 +1366,7 @@ parisc_hardware_description(struct parisc_device_id *id) /* Interpret hversion (ret[0]) from PDC_MODEL(4)/PDC_MODEL_INFO(0) */ -enum cpu_type __cpuinit +enum cpu_type parisc_get_cpu_type(unsigned long hversion) { struct hp_cpu_type_mask *ptr; diff --git a/arch/parisc/kernel/processor.c b/arch/parisc/kernel/processor.c index c8fb61ed32f..a128a94204e 100644 --- a/arch/parisc/kernel/processor.c +++ b/arch/parisc/kernel/processor.c @@ -73,7 +73,7 @@ extern int update_cr16_clocksource(void); /* from time.c */ * * FIXME: doesn't do much yet... */ -static void __cpuinit +static void init_percpu_prof(unsigned long cpunum) { struct cpuinfo_parisc *p; @@ -92,7 +92,7 @@ init_percpu_prof(unsigned long cpunum) * (return 1). If so, initialize the chip and tell other partners in crime * they have work to do. */ -static int __cpuinit processor_probe(struct parisc_device *dev) +static int processor_probe(struct parisc_device *dev) { unsigned long txn_addr; unsigned long cpuid; @@ -299,7 +299,7 @@ void __init collect_boot_cpu_data(void) * * o Enable CPU profiling hooks. */ -int __cpuinit init_per_cpu(int cpunum) +int init_per_cpu(int cpunum) { int ret; struct pdc_coproc_cfg coproc_cfg; diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c index 4dc7b7942b4..f3494c83536 100644 --- a/arch/parisc/kernel/smp.c +++ b/arch/parisc/kernel/smp.c @@ -62,9 +62,9 @@ static int smp_debug_lvl = 0; volatile struct task_struct *smp_init_current_idle_task; /* track which CPU is booting */ -static volatile int cpu_now_booting __cpuinitdata; +static volatile int cpu_now_booting; -static int parisc_max_cpus __cpuinitdata = 1; +static int parisc_max_cpus = 1; static DEFINE_PER_CPU(spinlock_t, ipi_lock); @@ -340,7 +340,7 @@ void __init smp_callin(void) /* * Bring one cpu online. */ -int __cpuinit smp_boot_one_cpu(int cpuid) +int smp_boot_one_cpu(int cpuid) { const struct cpuinfo_parisc *p = &per_cpu(cpu_data, cpuid); struct task_struct *idle; @@ -455,7 +455,7 @@ void smp_cpus_done(unsigned int cpu_max) } -int __cpuinit __cpu_up(unsigned int cpu) +int __cpu_up(unsigned int cpu) { if (cpu != 0 && cpu < parisc_max_cpus) smp_boot_one_cpu(cpu); diff --git a/arch/powerpc/include/asm/rtas.h b/arch/powerpc/include/asm/rtas.h index 557cff845de..b3ca19a7753 100644 --- a/arch/powerpc/include/asm/rtas.h +++ b/arch/powerpc/include/asm/rtas.h @@ -342,8 +342,8 @@ static inline u32 rtas_config_addr(int busno, int devfn, int reg) (devfn << 8) | (reg & 0xff); } -extern void __cpuinit rtas_give_timebase(void); -extern void __cpuinit rtas_take_timebase(void); +extern void rtas_give_timebase(void); +extern void rtas_take_timebase(void); #ifdef CONFIG_PPC_RTAS static inline int page_is_rtas_user_buf(unsigned long pfn) diff --git a/arch/powerpc/kernel/cacheinfo.c b/arch/powerpc/kernel/cacheinfo.c index 92c6b008dd2..eea4c3a4778 100644 --- a/arch/powerpc/kernel/cacheinfo.c +++ b/arch/powerpc/kernel/cacheinfo.c @@ -131,7 +131,7 @@ static const char *cache_type_string(const struct cache *cache) return cache_type_info[cache->type].name; } -static void __cpuinit cache_init(struct cache *cache, int type, int level, struct device_node *ofnode) +static void cache_init(struct cache *cache, int type, int level, struct device_node *ofnode) { cache->type = type; cache->level = level; @@ -140,7 +140,7 @@ static void __cpuinit cache_init(struct cache *cache, int type, int level, struc list_add(&cache->list, &cache_list); } -static struct cache *__cpuinit new_cache(int type, int level, struct device_node *ofnode) +static struct cache *new_cache(int type, int level, struct device_node *ofnode) { struct cache *cache; @@ -324,7 +324,7 @@ static bool cache_node_is_unified(const struct device_node *np) return of_get_property(np, "cache-unified", NULL); } -static struct cache *__cpuinit cache_do_one_devnode_unified(struct device_node *node, int level) +static struct cache *cache_do_one_devnode_unified(struct device_node *node, int level) { struct cache *cache; @@ -335,7 +335,7 @@ static struct cache *__cpuinit cache_do_one_devnode_unified(struct device_node * return cache; } -static struct cache *__cpuinit cache_do_one_devnode_split(struct device_node *node, int level) +static struct cache *cache_do_one_devnode_split(struct device_node *node, int level) { struct cache *dcache, *icache; @@ -357,7 +357,7 @@ static struct cache *__cpuinit cache_do_one_devnode_split(struct device_node *no return NULL; } -static struct cache *__cpuinit cache_do_one_devnode(struct device_node *node, int level) +static struct cache *cache_do_one_devnode(struct device_node *node, int level) { struct cache *cache; @@ -369,7 +369,7 @@ static struct cache *__cpuinit cache_do_one_devnode(struct device_node *node, in return cache; } -static struct cache *__cpuinit cache_lookup_or_instantiate(struct device_node *node, int level) +static struct cache *cache_lookup_or_instantiate(struct device_node *node, int level) { struct cache *cache; @@ -385,7 +385,7 @@ static struct cache *__cpuinit cache_lookup_or_instantiate(struct device_node *n return cache; } -static void __cpuinit link_cache_lists(struct cache *smaller, struct cache *bigger) +static void link_cache_lists(struct cache *smaller, struct cache *bigger) { while (smaller->next_local) { if (smaller->next_local == bigger) @@ -396,13 +396,13 @@ static void __cpuinit link_cache_lists(struct cache *smaller, struct cache *bigg smaller->next_local = bigger; } -static void __cpuinit do_subsidiary_caches_debugcheck(struct cache *cache) +static void do_subsidiary_caches_debugcheck(struct cache *cache) { WARN_ON_ONCE(cache->level != 1); WARN_ON_ONCE(strcmp(cache->ofnode->type, "cpu")); } -static void __cpuinit do_subsidiary_caches(struct cache *cache) +static void do_subsidiary_caches(struct cache *cache) { struct device_node *subcache_node; int level = cache->level; @@ -423,7 +423,7 @@ static void __cpuinit do_subsidiary_caches(struct cache *cache) } } -static struct cache *__cpuinit cache_chain_instantiate(unsigned int cpu_id) +static struct cache *cache_chain_instantiate(unsigned int cpu_id) { struct device_node *cpu_node; struct cache *cpu_cache = NULL; @@ -448,7 +448,7 @@ static struct cache *__cpuinit cache_chain_instantiate(unsigned int cpu_id) return cpu_cache; } -static struct cache_dir *__cpuinit cacheinfo_create_cache_dir(unsigned int cpu_id) +static struct cache_dir *cacheinfo_create_cache_dir(unsigned int cpu_id) { struct cache_dir *cache_dir; struct device *dev; @@ -653,7 +653,7 @@ static struct kobj_type cache_index_type = { .default_attrs = cache_index_default_attrs, }; -static void __cpuinit cacheinfo_create_index_opt_attrs(struct cache_index_dir *dir) +static void cacheinfo_create_index_opt_attrs(struct cache_index_dir *dir) { const char *cache_name; const char *cache_type; @@ -696,7 +696,7 @@ static void __cpuinit cacheinfo_create_index_opt_attrs(struct cache_index_dir *d kfree(buf); } -static void __cpuinit cacheinfo_create_index_dir(struct cache *cache, int index, struct cache_dir *cache_dir) +static void cacheinfo_create_index_dir(struct cache *cache, int index, struct cache_dir *cache_dir) { struct cache_index_dir *index_dir; int rc; @@ -722,7 +722,7 @@ static void __cpuinit cacheinfo_create_index_dir(struct cache *cache, int index, kfree(index_dir); } -static void __cpuinit cacheinfo_sysfs_populate(unsigned int cpu_id, struct cache *cache_list) +static void cacheinfo_sysfs_populate(unsigned int cpu_id, struct cache *cache_list) { struct cache_dir *cache_dir; struct cache *cache; @@ -740,7 +740,7 @@ static void __cpuinit cacheinfo_sysfs_populate(unsigned int cpu_id, struct cache } } -void __cpuinit cacheinfo_cpu_online(unsigned int cpu_id) +void cacheinfo_cpu_online(unsigned int cpu_id) { struct cache *cache; diff --git a/arch/powerpc/kernel/idle.c b/arch/powerpc/kernel/idle.c index 6d2209ac0c4..04d79093d7a 100644 --- a/arch/powerpc/kernel/idle.c +++ b/arch/powerpc/kernel/idle.c @@ -113,6 +113,9 @@ void cpu_idle(void) } } +static void do_nothing(void *unused) +{ +} /* * cpu_idle_wait - Used to ensure that all the CPUs come out of the old @@ -123,16 +126,9 @@ void cpu_idle(void) */ void cpu_idle_wait(void) { - int cpu; smp_mb(); - - /* kick all the CPUs so that they exit out of old idle routine */ - get_online_cpus(); - for_each_online_cpu(cpu) { - if (cpu != smp_processor_id()) - smp_send_reschedule(cpu); - } - put_online_cpus(); + /* kick all the CPUs so that they exit out of pm_idle */ + smp_call_function(do_nothing, NULL, 1); } EXPORT_SYMBOL_GPL(cpu_idle_wait); diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index fcec38241f7..5de4c64202c 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c @@ -1060,7 +1060,7 @@ int __init early_init_dt_scan_rtas(unsigned long node, static arch_spinlock_t timebase_lock; static u64 timebase = 0; -void __cpuinit rtas_give_timebase(void) +void rtas_give_timebase(void) { unsigned long flags; @@ -1077,7 +1077,7 @@ void __cpuinit rtas_give_timebase(void) local_irq_restore(flags); } -void __cpuinit rtas_take_timebase(void) +void rtas_take_timebase(void) { while (!timebase) barrier(); diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index d9f94410fd7..0337086a2b8 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -64,7 +64,7 @@ */ #ifdef CONFIG_HOTPLUG_CPU /* - * Needed only for CONFIG_HOTPLUG_CPU because __cpuinitdata is + * Needed only for CONFIG_HOTPLUG_CPU because is * removed after init for !CONFIG_HOTPLUG_CPU. */ static DEFINE_PER_CPU(struct task_struct *, idle_thread_array); @@ -75,7 +75,7 @@ static DEFINE_PER_CPU(struct task_struct *, idle_thread_array); static DEFINE_PER_CPU(int, cpu_state) = { 0 }; #else -static struct task_struct *idle_thread_array[NR_CPUS] __cpuinitdata ; +static struct task_struct *idle_thread_array[NR_CPUS] ; #define get_idle_for_cpu(x) (idle_thread_array[(x)]) #define set_idle_for_cpu(x, p) (idle_thread_array[(x)] = (p)) #endif @@ -436,7 +436,7 @@ struct create_idle { int cpu; }; -static void __cpuinit do_fork_idle(struct work_struct *work) +static void do_fork_idle(struct work_struct *work) { struct create_idle *c_idle = container_of(work, struct create_idle, work); @@ -445,7 +445,7 @@ static void __cpuinit do_fork_idle(struct work_struct *work) complete(&c_idle->done); } -static int __cpuinit create_idle(unsigned int cpu) +static int create_idle(unsigned int cpu) { struct thread_info *ti; struct create_idle c_idle = { @@ -482,7 +482,7 @@ static int __cpuinit create_idle(unsigned int cpu) return 0; } -int __cpuinit __cpu_up(unsigned int cpu) +int __cpu_up(unsigned int cpu) { int rc, c; diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c index 3529446c2ab..a6289ae14e8 100644 --- a/arch/powerpc/kernel/sysfs.c +++ b/arch/powerpc/kernel/sysfs.c @@ -331,7 +331,7 @@ static struct device_attribute pa6t_attrs[] = { #endif /* HAS_PPC_PMC_PA6T */ #endif /* HAS_PPC_PMC_CLASSIC */ -static void __cpuinit register_cpu_online(unsigned int cpu) +static void register_cpu_online(unsigned int cpu) { struct cpu *c = &per_cpu(cpu_devices, cpu); struct device *s = &c->dev; @@ -492,7 +492,7 @@ ssize_t arch_cpu_release(const char *buf, size_t count) #endif /* CONFIG_HOTPLUG_CPU */ -static int __cpuinit sysfs_cpu_notify(struct notifier_block *self, +static int sysfs_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) { unsigned int cpu = (unsigned int)(long)hcpu; @@ -512,7 +512,7 @@ static int __cpuinit sysfs_cpu_notify(struct notifier_block *self, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata sysfs_cpu_nb = { +static struct notifier_block sysfs_cpu_nb = { .notifier_call = sysfs_cpu_notify, }; diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 2c42cd72d0f..a6ceb9f4b6d 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -596,7 +596,7 @@ static int __init get_freq(char *name, int cells, unsigned long *val) return found; } -/* should become __cpuinit when secondary_cpu_time_init also is */ +/* should become when secondary_cpu_time_init also is */ void start_cpu_decrementer(void) { #if defined(CONFIG_BOOKE) || defined(CONFIG_40x) diff --git a/arch/powerpc/mm/44x_mmu.c b/arch/powerpc/mm/44x_mmu.c index 2c9441ee6bb..82b1ff759e2 100644 --- a/arch/powerpc/mm/44x_mmu.c +++ b/arch/powerpc/mm/44x_mmu.c @@ -41,7 +41,7 @@ int icache_44x_need_flush; unsigned long tlb_47x_boltmap[1024/8]; -static void __cpuinit ppc44x_update_tlb_hwater(void) +static void ppc44x_update_tlb_hwater(void) { extern unsigned int tlb_44x_patch_hwater_D[]; extern unsigned int tlb_44x_patch_hwater_I[]; @@ -134,7 +134,7 @@ static void __init ppc47x_update_boltmap(void) /* * "Pins" a 256MB TLB entry in AS0 for kernel lowmem for 47x type MMU */ -static void __cpuinit ppc47x_pin_tlb(unsigned int virt, unsigned int phys) +static void ppc47x_pin_tlb(unsigned int virt, unsigned int phys) { unsigned int rA; int bolted; @@ -229,7 +229,7 @@ void setup_initial_memory_limit(phys_addr_t first_memblock_base, } #ifdef CONFIG_SMP -void __cpuinit mmu_init_secondary(int cpu) +void mmu_init_secondary(int cpu) { unsigned long addr; unsigned long memstart = memstart_addr & ~(PPC_PIN_SIZE - 1); diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index 377e5cbedbb..a03ea91998e 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c @@ -762,7 +762,7 @@ void __init early_init_mmu(void) } #ifdef CONFIG_SMP -void __cpuinit early_init_mmu_secondary(void) +void early_init_mmu_secondary(void) { /* Initialize hash table for that CPU */ if (!firmware_has_feature(FW_FEATURE_LPAR)) diff --git a/arch/powerpc/mm/mmu_context_nohash.c b/arch/powerpc/mm/mmu_context_nohash.c index 5b63bd3da4a..6c3f2f44d8f 100644 --- a/arch/powerpc/mm/mmu_context_nohash.c +++ b/arch/powerpc/mm/mmu_context_nohash.c @@ -329,7 +329,7 @@ void destroy_context(struct mm_struct *mm) #ifdef CONFIG_SMP -static int __cpuinit mmu_context_cpu_notify(struct notifier_block *self, +static int mmu_context_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) { unsigned int cpu = (unsigned int)(long)hcpu; @@ -370,7 +370,7 @@ static int __cpuinit mmu_context_cpu_notify(struct notifier_block *self, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata mmu_context_cpu_nb = { +static struct notifier_block mmu_context_cpu_nb = { .notifier_call = mmu_context_cpu_notify, }; diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index b6edbb3b4a5..8c34b7fa51b 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c @@ -79,7 +79,7 @@ static void __init setup_node_to_cpumask_map(void) dbg("Node to cpumask map for %d nodes\n", nr_node_ids); } -static int __cpuinit fake_numa_create_new_node(unsigned long end_pfn, +static int fake_numa_create_new_node(unsigned long end_pfn, unsigned int *nid) { unsigned long long mem; @@ -539,7 +539,7 @@ static int of_drconf_to_nid_single(struct of_drconf_cell *drmem, * Figure out to which domain a cpu belongs and stick it there. * Return the id of the domain used. */ -static int __cpuinit numa_setup_cpu(unsigned long lcpu) +static int numa_setup_cpu(unsigned long lcpu) { int nid = 0; struct device_node *cpu = of_get_cpu_node(lcpu, NULL); @@ -561,7 +561,7 @@ static int __cpuinit numa_setup_cpu(unsigned long lcpu) return nid; } -static int __cpuinit cpu_numa_callback(struct notifier_block *nfb, +static int cpu_numa_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { @@ -942,7 +942,7 @@ static void __init *careful_zallocation(int nid, unsigned long size, return ret; } -static struct notifier_block __cpuinitdata ppc64_numa_nb = { +static struct notifier_block ppc64_numa_nb = { .notifier_call = cpu_numa_callback, .priority = 1 /* Must run before sched domains notifier. */ }; diff --git a/arch/powerpc/mm/tlb_nohash.c b/arch/powerpc/mm/tlb_nohash.c index df32a838dcf..b284c53bb0e 100644 --- a/arch/powerpc/mm/tlb_nohash.c +++ b/arch/powerpc/mm/tlb_nohash.c @@ -634,7 +634,7 @@ void __init early_init_mmu(void) __early_init_mmu(1); } -void __cpuinit early_init_mmu_secondary(void) +void early_init_mmu_secondary(void) { __early_init_mmu(0); } diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c index 02aee03e713..aa2e3790f8e 100644 --- a/arch/powerpc/perf/core-book3s.c +++ b/arch/powerpc/perf/core-book3s.c @@ -1443,7 +1443,7 @@ static void power_pmu_setup(int cpu) cpuhw->mmcr[0] = MMCR0_FC; } -static int __cpuinit +static int power_pmu_notifier(struct notifier_block *self, unsigned long action, void *hcpu) { unsigned int cpu = (long)hcpu; @@ -1460,7 +1460,7 @@ power_pmu_notifier(struct notifier_block *self, unsigned long action, void *hcpu return NOTIFY_OK; } -int __cpuinit register_power_pmu(struct power_pmu *pmu) +int register_power_pmu(struct power_pmu *pmu) { if (ppmu) return -EBUSY; /* something's already registered */ diff --git a/arch/powerpc/platforms/44x/currituck.c b/arch/powerpc/platforms/44x/currituck.c index 583e67fee37..845e9d98260 100644 --- a/arch/powerpc/platforms/44x/currituck.c +++ b/arch/powerpc/platforms/44x/currituck.c @@ -92,12 +92,12 @@ static void __init ppc47x_init_irq(void) } #ifdef CONFIG_SMP -static void __cpuinit smp_ppc47x_setup_cpu(int cpu) +static void smp_ppc47x_setup_cpu(int cpu) { mpic_setup_this_cpu(); } -static int __cpuinit smp_ppc47x_kick_cpu(int cpu) +static int smp_ppc47x_kick_cpu(int cpu) { struct device_node *cpunode = of_get_cpu_node(cpu, NULL); const u64 *spin_table_addr_prop; diff --git a/arch/powerpc/platforms/44x/iss4xx.c b/arch/powerpc/platforms/44x/iss4xx.c index a28a8629727..4241bc82580 100644 --- a/arch/powerpc/platforms/44x/iss4xx.c +++ b/arch/powerpc/platforms/44x/iss4xx.c @@ -81,12 +81,12 @@ static void __init iss4xx_init_irq(void) } #ifdef CONFIG_SMP -static void __cpuinit smp_iss4xx_setup_cpu(int cpu) +static void smp_iss4xx_setup_cpu(int cpu) { mpic_setup_this_cpu(); } -static int __cpuinit smp_iss4xx_kick_cpu(int cpu) +static int smp_iss4xx_kick_cpu(int cpu) { struct device_node *cpunode = of_get_cpu_node(cpu, NULL); const u64 *spin_table_addr_prop; diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c index b4ddaa3fbb2..54b862711d5 100644 --- a/arch/powerpc/platforms/powermac/smp.c +++ b/arch/powerpc/platforms/powermac/smp.c @@ -885,7 +885,7 @@ static int smp_core99_cpu_notify(struct notifier_block *self, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata smp_core99_cpu_nb = { +static struct notifier_block smp_core99_cpu_nb = { .notifier_call = smp_core99_cpu_notify, }; #endif /* CONFIG_HOTPLUG_CPU */ diff --git a/arch/powerpc/platforms/powernv/smp.c b/arch/powerpc/platforms/powernv/smp.c index 3ef46254c35..a4a5955e674 100644 --- a/arch/powerpc/platforms/powernv/smp.c +++ b/arch/powerpc/platforms/powernv/smp.c @@ -40,7 +40,7 @@ #define DBG(fmt...) #endif -static void __cpuinit pnv_smp_setup_cpu(int cpu) +static void pnv_smp_setup_cpu(int cpu) { if (cpu != boot_cpuid) xics_setup_cpu(); diff --git a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c index 24bff4f1cc5..6bf612df018 100644 --- a/arch/s390/appldata/appldata_base.c +++ b/arch/s390/appldata/appldata_base.c @@ -567,7 +567,7 @@ static struct platform_driver appldata_pdrv = { /******************************* init / exit *********************************/ -static void __cpuinit appldata_online_cpu(int cpu) +static void appldata_online_cpu(int cpu) { init_virt_timer(&per_cpu(appldata_timer, cpu)); per_cpu(appldata_timer, cpu).function = appldata_timer_function; @@ -579,7 +579,7 @@ static void __cpuinit appldata_online_cpu(int cpu) spin_unlock(&appldata_timer_lock); } -static void __cpuinit appldata_offline_cpu(int cpu) +static void appldata_offline_cpu(int cpu) { del_virt_timer(&per_cpu(appldata_timer, cpu)); if (atomic_dec_and_test(&appldata_expire_count)) { @@ -591,7 +591,7 @@ static void __cpuinit appldata_offline_cpu(int cpu) spin_unlock(&appldata_timer_lock); } -static int __cpuinit appldata_cpu_notify(struct notifier_block *self, +static int appldata_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) { @@ -610,7 +610,7 @@ static int __cpuinit appldata_cpu_notify(struct notifier_block *self, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata appldata_nb = { +static struct notifier_block appldata_nb = { .notifier_call = appldata_cpu_notify, }; diff --git a/arch/s390/kernel/perf_cpum_cf.c b/arch/s390/kernel/perf_cpum_cf.c index cb019f429e8..f91b125201d 100644 --- a/arch/s390/kernel/perf_cpum_cf.c +++ b/arch/s390/kernel/perf_cpum_cf.c @@ -636,7 +636,7 @@ static struct pmu cpumf_pmu = { .cancel_txn = cpumf_pmu_cancel_txn, }; -static int __cpuinit cpumf_pmu_notifier(struct notifier_block *self, +static int cpumf_pmu_notifier(struct notifier_block *self, unsigned long action, void *hcpu) { unsigned int cpu = (long) hcpu; diff --git a/arch/s390/kernel/processor.c b/arch/s390/kernel/processor.c index 6e0073e43f5..510027dcad7 100644 --- a/arch/s390/kernel/processor.c +++ b/arch/s390/kernel/processor.c @@ -23,7 +23,7 @@ static DEFINE_PER_CPU(struct cpuid, cpu_id); /* * cpu_init - initializes state that is per-CPU. */ -void __cpuinit cpu_init(void) +void cpu_init(void) { struct cpuid *id = &per_cpu(cpu_id, smp_processor_id()); diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 1f77227669e..621a39455f2 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -186,7 +186,7 @@ static void pcpu_ec_call(struct pcpu *pcpu, int ec_bit) pcpu_sigp_retry(pcpu, order, 0); } -static int __cpuinit pcpu_alloc_lowcore(struct pcpu *pcpu, int cpu) +static int pcpu_alloc_lowcore(struct pcpu *pcpu, int cpu) { struct _lowcore *lc; @@ -697,7 +697,7 @@ static void __init smp_detect_cpus(void) /* * Activate a secondary processor. */ -static void __cpuinit smp_start_secondary(void *cpuvoid) +static void smp_start_secondary(void *cpuvoid) { S390_lowcore.last_update_clock = get_clock(); S390_lowcore.restart_stack = (unsigned long) restart_stack; @@ -728,7 +728,7 @@ struct create_idle { int cpu; }; -static void __cpuinit smp_fork_idle(struct work_struct *work) +static void smp_fork_idle(struct work_struct *work) { struct create_idle *c_idle; @@ -738,7 +738,7 @@ static void __cpuinit smp_fork_idle(struct work_struct *work) } /* Upping and downing of CPUs */ -int __cpuinit __cpu_up(unsigned int cpu) +int __cpu_up(unsigned int cpu) { struct create_idle c_idle; struct pcpu *pcpu; @@ -1028,7 +1028,7 @@ static struct attribute_group cpu_online_attr_group = { .attrs = cpu_online_attrs, }; -static int __cpuinit smp_cpu_notify(struct notifier_block *self, +static int smp_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) { unsigned int cpu = (unsigned int)(long)hcpu; @@ -1052,7 +1052,7 @@ static int __cpuinit smp_cpu_notify(struct notifier_block *self, return notifier_from_errno(err); } -static struct notifier_block __cpuinitdata smp_cpu_nb = { +static struct notifier_block smp_cpu_nb = { .notifier_call = smp_cpu_notify, }; diff --git a/arch/s390/kernel/sysinfo.c b/arch/s390/kernel/sysinfo.c index 2a94b774695..e1e5068a380 100644 --- a/arch/s390/kernel/sysinfo.c +++ b/arch/s390/kernel/sysinfo.c @@ -460,7 +460,7 @@ void s390_adjust_jiffies(void) /* * calibrate the delay loop */ -void __cpuinit calibrate_delay(void) +void calibrate_delay(void) { s390_adjust_jiffies(); /* Print the good old Bogomips line .. */ diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c index 39ebff50694..27af9740ad8 100644 --- a/arch/s390/kernel/vtime.c +++ b/arch/s390/kernel/vtime.c @@ -474,7 +474,7 @@ void init_cpu_vtimer(void) set_vtimer(0x7fffffffffffffffULL); } -static int __cpuinit s390_nohz_notify(struct notifier_block *self, +static int s390_nohz_notify(struct notifier_block *self, unsigned long action, void *hcpu) { struct s390_idle_data *idle; diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index 46ef3fd0663..d02a1463680 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c @@ -574,6 +574,7 @@ static void pfault_interrupt(struct ext_code ext_code, tsk->thread.pfault_wait = 0; list_del(&tsk->thread.list); wake_up_process(tsk); + put_task_struct(tsk); } else { /* Completion interrupt was faster than initial * interrupt. Set pfault_wait to -1 so the initial @@ -588,14 +589,22 @@ static void pfault_interrupt(struct ext_code ext_code, put_task_struct(tsk); } else { /* signal bit not set -> a real page is missing. */ - if (tsk->thread.pfault_wait == -1) { + if (tsk->thread.pfault_wait == 1) { + /* Already on the list with a reference: put to sleep */ + set_task_state(tsk, TASK_UNINTERRUPTIBLE); + set_tsk_need_resched(tsk); + } else if (tsk->thread.pfault_wait == -1) { /* Completion interrupt was faster than the initial * interrupt (pfault_wait == -1). Set pfault_wait * back to zero and exit. */ tsk->thread.pfault_wait = 0; } else { /* Initial interrupt arrived before completion - * interrupt. Let the task sleep. */ + * interrupt. Let the task sleep. + * An extra task reference is needed since a different + * cpu may set the task state to TASK_RUNNING again + * before the scheduler is reached. */ + get_task_struct(tsk); tsk->thread.pfault_wait = 1; list_add(&tsk->thread.list, &pfault_list); set_task_state(tsk, TASK_UNINTERRUPTIBLE); @@ -605,7 +614,7 @@ static void pfault_interrupt(struct ext_code ext_code, spin_unlock(&pfault_lock); } -static int __cpuinit pfault_cpu_notify(struct notifier_block *self, +static int pfault_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) { struct thread_struct *thread, *next; @@ -620,6 +629,7 @@ static int __cpuinit pfault_cpu_notify(struct notifier_block *self, list_del(&thread->list); tsk = container_of(thread, struct task_struct, thread); wake_up_process(tsk); + put_task_struct(tsk); } spin_unlock_irq(&pfault_lock); break; diff --git a/arch/score/mm/tlb-score.c b/arch/score/mm/tlb-score.c index 6fdb100244c..004073717de 100644 --- a/arch/score/mm/tlb-score.c +++ b/arch/score/mm/tlb-score.c @@ -240,7 +240,7 @@ void __update_tlb(struct vm_area_struct *vma, unsigned long address, pte_t pte) local_irq_restore(flags); } -void __cpuinit tlb_init(void) +void tlb_init(void) { tlblock_set(0); local_flush_tlb_all(); diff --git a/arch/sh/kernel/cpu/init.c b/arch/sh/kernel/cpu/init.c index 61a07dafcd4..0a2ef460e19 100644 --- a/arch/sh/kernel/cpu/init.c +++ b/arch/sh/kernel/cpu/init.c @@ -43,9 +43,9 @@ * peripherals (nofpu, nodsp, and so forth). */ #define onchip_setup(x) \ -static int x##_disabled __cpuinitdata = !cpu_has_##x; \ +static int x##_disabled = !cpu_has_##x; \ \ -static int __cpuinit x##_setup(char *opts) \ +static int x##_setup(char *opts) \ { \ x##_disabled = 1; \ return 1; \ @@ -59,7 +59,7 @@ onchip_setup(dsp); #define CPUOPM 0xff2f0000 #define CPUOPM_RABD (1 << 5) -static void __cpuinit speculative_execution_init(void) +static void speculative_execution_init(void) { /* Clear RABD */ __raw_writel(__raw_readl(CPUOPM) & ~CPUOPM_RABD, CPUOPM); @@ -78,7 +78,7 @@ static void __cpuinit speculative_execution_init(void) #define EXPMASK_BRDSSLP (1 << 1) #define EXPMASK_MMCAW (1 << 4) -static void __cpuinit expmask_init(void) +static void expmask_init(void) { unsigned long expmask = __raw_readl(EXPMASK); @@ -217,7 +217,7 @@ static void detect_cache_shape(void) l2_cache_shape = -1; /* No S-cache */ } -static void __cpuinit fpu_init(void) +static void fpu_init(void) { /* Disable the FPU */ if (fpu_disabled && (current_cpu_data.flags & CPU_HAS_FPU)) { @@ -230,7 +230,7 @@ static void __cpuinit fpu_init(void) } #ifdef CONFIG_SH_DSP -static void __cpuinit release_dsp(void) +static void release_dsp(void) { unsigned long sr; @@ -244,7 +244,7 @@ static void __cpuinit release_dsp(void) ); } -static void __cpuinit dsp_init(void) +static void dsp_init(void) { unsigned long sr; @@ -276,7 +276,7 @@ static void __cpuinit dsp_init(void) release_dsp(); } #else -static inline void __cpuinit dsp_init(void) { } +static inline void dsp_init(void) { } #endif /* CONFIG_SH_DSP */ /** @@ -295,7 +295,7 @@ static inline void __cpuinit dsp_init(void) { } * Each processor family is still responsible for doing its own probing * and cache configuration in cpu_probe(). */ -asmlinkage void __cpuinit cpu_init(void) +asmlinkage void cpu_init(void) { current_thread_info()->cpu = hard_smp_processor_id(); diff --git a/arch/sh/kernel/cpu/sh2/probe.c b/arch/sh/kernel/cpu/sh2/probe.c index bab8e75958a..6c687ae812e 100644 --- a/arch/sh/kernel/cpu/sh2/probe.c +++ b/arch/sh/kernel/cpu/sh2/probe.c @@ -13,7 +13,7 @@ #include #include -void __cpuinit cpu_probe(void) +void cpu_probe(void) { #if defined(CONFIG_CPU_SUBTYPE_SH7619) boot_cpu_data.type = CPU_SH7619; diff --git a/arch/sh/kernel/cpu/sh2a/probe.c b/arch/sh/kernel/cpu/sh2a/probe.c index 48e97a2a0c8..23709ec57a2 100644 --- a/arch/sh/kernel/cpu/sh2a/probe.c +++ b/arch/sh/kernel/cpu/sh2a/probe.c @@ -13,7 +13,7 @@ #include #include -void __cpuinit cpu_probe(void) +void cpu_probe(void) { boot_cpu_data.family = CPU_FAMILY_SH2A; diff --git a/arch/sh/kernel/cpu/sh3/probe.c b/arch/sh/kernel/cpu/sh3/probe.c index bf23c322e16..426e1e1dced 100644 --- a/arch/sh/kernel/cpu/sh3/probe.c +++ b/arch/sh/kernel/cpu/sh3/probe.c @@ -16,7 +16,7 @@ #include #include -void __cpuinit cpu_probe(void) +void cpu_probe(void) { unsigned long addr0, addr1, data0, data1, data2, data3; diff --git a/arch/sh/kernel/cpu/sh4/probe.c b/arch/sh/kernel/cpu/sh4/probe.c index 971cf0fce4f..041cd84a115 100644 --- a/arch/sh/kernel/cpu/sh4/probe.c +++ b/arch/sh/kernel/cpu/sh4/probe.c @@ -15,7 +15,7 @@ #include #include -void __cpuinit cpu_probe(void) +void cpu_probe(void) { unsigned long pvr, prr, cvr; unsigned long size; diff --git a/arch/sh/kernel/cpu/sh4a/smp-shx3.c b/arch/sh/kernel/cpu/sh4a/smp-shx3.c index 03f2b55757c..4a298808789 100644 --- a/arch/sh/kernel/cpu/sh4a/smp-shx3.c +++ b/arch/sh/kernel/cpu/sh4a/smp-shx3.c @@ -124,7 +124,7 @@ static void shx3_update_boot_vector(unsigned int cpu) __raw_writel(STBCR_RESET, STBCR_REG(cpu)); } -static int __cpuinit +static int shx3_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { unsigned int cpu = (unsigned int)hcpu; @@ -143,11 +143,11 @@ shx3_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) return NOTIFY_OK; } -static struct notifier_block __cpuinitdata shx3_cpu_notifier = { +static struct notifier_block shx3_cpu_notifier = { .notifier_call = shx3_cpu_callback, }; -static int __cpuinit register_shx3_cpu_notifier(void) +static int register_shx3_cpu_notifier(void) { register_hotcpu_notifier(&shx3_cpu_notifier); return 0; diff --git a/arch/sh/kernel/cpu/sh5/probe.c b/arch/sh/kernel/cpu/sh5/probe.c index 9e882409e4e..eca427c2f2f 100644 --- a/arch/sh/kernel/cpu/sh5/probe.c +++ b/arch/sh/kernel/cpu/sh5/probe.c @@ -17,7 +17,7 @@ #include #include -void __cpuinit cpu_probe(void) +void cpu_probe(void) { unsigned long long cir; diff --git a/arch/sh/kernel/perf_event.c b/arch/sh/kernel/perf_event.c index 068b8a2759b..b9cefebda55 100644 --- a/arch/sh/kernel/perf_event.c +++ b/arch/sh/kernel/perf_event.c @@ -367,7 +367,7 @@ static void sh_pmu_setup(int cpu) memset(cpuhw, 0, sizeof(struct cpu_hw_events)); } -static int __cpuinit +static int sh_pmu_notifier(struct notifier_block *self, unsigned long action, void *hcpu) { unsigned int cpu = (long)hcpu; @@ -384,7 +384,7 @@ sh_pmu_notifier(struct notifier_block *self, unsigned long action, void *hcpu) return NOTIFY_OK; } -int __cpuinit register_sh_pmu(struct sh_pmu *_pmu) +int register_sh_pmu(struct sh_pmu *_pmu) { if (sh_pmu) return -EBUSY; diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c index 325f98b1736..727c0bcea75 100644 --- a/arch/sh/kernel/process.c +++ b/arch/sh/kernel/process.c @@ -92,7 +92,7 @@ void arch_task_cache_init(void) # define HAVE_SOFTFP 0 #endif -void __cpuinit init_thread_xstate(void) +void init_thread_xstate(void) { if (boot_cpu_data.flags & CPU_HAS_FPU) xstate_size = sizeof(struct sh_fpu_hard_struct); diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index 7b57bf1dc85..1aced4e9701 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c @@ -172,7 +172,7 @@ void __init check_for_initrd(void) #endif } -void __cpuinit calibrate_delay(void) +void calibrate_delay(void) { struct clk *clk = clk_get(NULL, "cpu_clk"); diff --git a/arch/sh/kernel/smp.c b/arch/sh/kernel/smp.c index eaebdf6a5c7..f3f9522574a 100644 --- a/arch/sh/kernel/smp.c +++ b/arch/sh/kernel/smp.c @@ -37,7 +37,7 @@ struct plat_smp_ops *mp_ops = NULL; /* State of each CPU */ DEFINE_PER_CPU(int, cpu_state) = { 0 }; -void __cpuinit register_smp_ops(struct plat_smp_ops *ops) +void register_smp_ops(struct plat_smp_ops *ops) { if (mp_ops) printk(KERN_WARNING "Overriding previously set SMP ops\n"); @@ -45,7 +45,7 @@ void __cpuinit register_smp_ops(struct plat_smp_ops *ops) mp_ops = ops; } -static inline void __cpuinit smp_store_cpu_info(unsigned int cpu) +static inline void smp_store_cpu_info(unsigned int cpu) { struct sh_cpuinfo *c = cpu_data + cpu; @@ -179,7 +179,7 @@ void native_play_dead(void) } #endif -asmlinkage void __cpuinit start_secondary(void) +asmlinkage void start_secondary(void) { unsigned int cpu = smp_processor_id(); struct mm_struct *mm = &init_mm; @@ -220,7 +220,7 @@ extern struct { void *thread_info; } stack_start; -int __cpuinit __cpu_up(unsigned int cpu) +int __cpu_up(unsigned int cpu) { struct task_struct *tsk; unsigned long timeout; diff --git a/arch/sh/kernel/traps_32.c b/arch/sh/kernel/traps_32.c index a37175deb73..8c33e811040 100644 --- a/arch/sh/kernel/traps_32.c +++ b/arch/sh/kernel/traps_32.c @@ -839,7 +839,7 @@ asmlinkage void do_exception_error(unsigned long r4, unsigned long r5, die_if_kernel("exception", regs, ex); } -void __cpuinit per_cpu_trap_init(void) +void per_cpu_trap_init(void) { extern void *vbr_base; diff --git a/arch/sh/kernel/traps_64.c b/arch/sh/kernel/traps_64.c index 6c0486094e4..09b9a99dd78 100644 --- a/arch/sh/kernel/traps_64.c +++ b/arch/sh/kernel/traps_64.c @@ -953,7 +953,7 @@ asmlinkage void do_debug_interrupt(unsigned long code, struct pt_regs *regs) poke_real_address_q(DM_EXP_CAUSE_PHY, 0x0); } -void __cpuinit per_cpu_trap_init(void) +void per_cpu_trap_init(void) { /* Nothing to do for now, VBR initialization later. */ } diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 6c0683d3fcb..76c7ccfb1eb 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -584,6 +584,9 @@ config SYSVIPC_COMPAT depends on COMPAT && SYSVIPC default y +config KEYS_COMPAT + def_bool y if COMPAT && KEYS + endmenu source "net/Kconfig" diff --git a/arch/sparc/kernel/ds.c b/arch/sparc/kernel/ds.c index b93c2c9ccb1..ee571271bad 100644 --- a/arch/sparc/kernel/ds.c +++ b/arch/sparc/kernel/ds.c @@ -528,7 +528,7 @@ static void dr_cpu_mark(struct ds_data *resp, int cpu, int ncpus, } } -static int __cpuinit dr_cpu_configure(struct ds_info *dp, +static int dr_cpu_configure(struct ds_info *dp, struct ds_cap_state *cp, u64 req_num, cpumask_t *mask) @@ -627,7 +627,7 @@ static int dr_cpu_unconfigure(struct ds_info *dp, return 0; } -static void __cpuinit dr_cpu_data(struct ds_info *dp, +static void dr_cpu_data(struct ds_info *dp, struct ds_cap_state *cp, void *buf, int len) { diff --git a/arch/sparc/kernel/entry.h b/arch/sparc/kernel/entry.h index 0c218e4c088..138dcb5cf1a 100644 --- a/arch/sparc/kernel/entry.h +++ b/arch/sparc/kernel/entry.h @@ -243,7 +243,7 @@ extern struct ino_bucket *ivector_table; extern unsigned long ivector_table_pa; extern void init_irqwork_curcpu(void); -extern void __cpuinit sun4v_register_mondo_queues(int this_cpu); +extern void sun4v_register_mondo_queues(int this_cpu); #endif /* CONFIG_SPARC32 */ #endif /* _ENTRY_H */ diff --git a/arch/sparc/kernel/irq_64.c b/arch/sparc/kernel/irq_64.c index dff2c3d7d37..54cddddb957 100644 --- a/arch/sparc/kernel/irq_64.c +++ b/arch/sparc/kernel/irq_64.c @@ -835,7 +835,7 @@ void notrace init_irqwork_curcpu(void) * Therefore you cannot make any OBP calls, not even prom_printf, * from these two routines. */ -static void __cpuinit notrace register_one_mondo(unsigned long paddr, unsigned long type, unsigned long qmask) +static void notrace register_one_mondo(unsigned long paddr, unsigned long type, unsigned long qmask) { unsigned long num_entries = (qmask + 1) / 64; unsigned long status; @@ -848,7 +848,7 @@ static void __cpuinit notrace register_one_mondo(unsigned long paddr, unsigned l } } -void __cpuinit notrace sun4v_register_mondo_queues(int this_cpu) +void notrace sun4v_register_mondo_queues(int this_cpu) { struct trap_per_cpu *tb = &trap_block[this_cpu]; diff --git a/arch/sparc/kernel/leon_smp.c b/arch/sparc/kernel/leon_smp.c index 160cac9c403..ae188adf129 100644 --- a/arch/sparc/kernel/leon_smp.c +++ b/arch/sparc/kernel/leon_smp.c @@ -71,7 +71,7 @@ static inline unsigned long do_swap(volatile unsigned long *ptr, static void smp_setup_percpu_timer(void); -void __cpuinit leon_callin(void) +void leon_callin(void) { int cpuid = hard_smpleon_processor_id(); @@ -204,7 +204,7 @@ void __init leon_boot_cpus(void) } -int __cpuinit leon_boot_one_cpu(int i) +int leon_boot_one_cpu(int i) { struct task_struct *p; diff --git a/arch/sparc/kernel/mdesc.c b/arch/sparc/kernel/mdesc.c index 6dc79628058..f7b1b22a7a2 100644 --- a/arch/sparc/kernel/mdesc.c +++ b/arch/sparc/kernel/mdesc.c @@ -571,7 +571,7 @@ static void __init report_platform_properties(void) mdesc_release(hp); } -static void __cpuinit fill_in_one_cache(cpuinfo_sparc *c, +static void fill_in_one_cache(cpuinfo_sparc *c, struct mdesc_handle *hp, u64 mp) { @@ -616,7 +616,7 @@ static void __cpuinit fill_in_one_cache(cpuinfo_sparc *c, } } -static void __cpuinit mark_core_ids(struct mdesc_handle *hp, u64 mp, int core_id) +static void mark_core_ids(struct mdesc_handle *hp, u64 mp, int core_id) { u64 a; @@ -649,7 +649,7 @@ static void __cpuinit mark_core_ids(struct mdesc_handle *hp, u64 mp, int core_id } } -static void __cpuinit set_core_ids(struct mdesc_handle *hp) +static void set_core_ids(struct mdesc_handle *hp) { int idx; u64 mp; @@ -674,7 +674,7 @@ static void __cpuinit set_core_ids(struct mdesc_handle *hp) } } -static void __cpuinit mark_proc_ids(struct mdesc_handle *hp, u64 mp, int proc_id) +static void mark_proc_ids(struct mdesc_handle *hp, u64 mp, int proc_id) { u64 a; @@ -693,7 +693,7 @@ static void __cpuinit mark_proc_ids(struct mdesc_handle *hp, u64 mp, int proc_id } } -static void __cpuinit __set_proc_ids(struct mdesc_handle *hp, const char *exec_unit_name) +static void __set_proc_ids(struct mdesc_handle *hp, const char *exec_unit_name) { int idx; u64 mp; @@ -714,13 +714,13 @@ static void __cpuinit __set_proc_ids(struct mdesc_handle *hp, const char *exec_u } } -static void __cpuinit set_proc_ids(struct mdesc_handle *hp) +static void set_proc_ids(struct mdesc_handle *hp) { __set_proc_ids(hp, "exec_unit"); __set_proc_ids(hp, "exec-unit"); } -static void __cpuinit get_one_mondo_bits(const u64 *p, unsigned int *mask, +static void get_one_mondo_bits(const u64 *p, unsigned int *mask, unsigned long def, unsigned long max) { u64 val; @@ -742,7 +742,7 @@ static void __cpuinit get_one_mondo_bits(const u64 *p, unsigned int *mask, *mask = ((1U << def) * 64U) - 1U; } -static void __cpuinit get_mondo_data(struct mdesc_handle *hp, u64 mp, +static void get_mondo_data(struct mdesc_handle *hp, u64 mp, struct trap_per_cpu *tb) { static int printed; @@ -769,7 +769,7 @@ static void __cpuinit get_mondo_data(struct mdesc_handle *hp, u64 mp, } } -static void * __cpuinit mdesc_iterate_over_cpus(void *(*func)(struct mdesc_handle *, u64, int, void *), void *arg, cpumask_t *mask) +static void * mdesc_iterate_over_cpus(void *(*func)(struct mdesc_handle *, u64, int, void *), void *arg, cpumask_t *mask) { struct mdesc_handle *hp = mdesc_grab(); void *ret = NULL; @@ -799,7 +799,7 @@ static void * __cpuinit mdesc_iterate_over_cpus(void *(*func)(struct mdesc_handl return ret; } -static void * __cpuinit record_one_cpu(struct mdesc_handle *hp, u64 mp, int cpuid, void *arg) +static void * record_one_cpu(struct mdesc_handle *hp, u64 mp, int cpuid, void *arg) { ncpus_probed++; #ifdef CONFIG_SMP @@ -808,7 +808,7 @@ static void * __cpuinit record_one_cpu(struct mdesc_handle *hp, u64 mp, int cpui return NULL; } -void __cpuinit mdesc_populate_present_mask(cpumask_t *mask) +void mdesc_populate_present_mask(cpumask_t *mask) { if (tlb_type != hypervisor) return; @@ -817,7 +817,7 @@ void __cpuinit mdesc_populate_present_mask(cpumask_t *mask) mdesc_iterate_over_cpus(record_one_cpu, NULL, mask); } -static void * __cpuinit fill_in_one_cpu(struct mdesc_handle *hp, u64 mp, int cpuid, void *arg) +static void * fill_in_one_cpu(struct mdesc_handle *hp, u64 mp, int cpuid, void *arg) { const u64 *cfreq = mdesc_get_property(hp, mp, "clock-frequency", NULL); struct trap_per_cpu *tb; @@ -866,7 +866,7 @@ static void * __cpuinit fill_in_one_cpu(struct mdesc_handle *hp, u64 mp, int cpu return NULL; } -void __cpuinit mdesc_fill_in_cpu_data(cpumask_t *mask) +void mdesc_fill_in_cpu_data(cpumask_t *mask) { struct mdesc_handle *hp; diff --git a/arch/sparc/kernel/smp_32.c b/arch/sparc/kernel/smp_32.c index f671e7fd6dd..7071fedcf5c 100644 --- a/arch/sparc/kernel/smp_32.c +++ b/arch/sparc/kernel/smp_32.c @@ -36,7 +36,7 @@ #include "irq.h" -volatile unsigned long cpu_callin_map[NR_CPUS] __cpuinitdata = {0,}; +volatile unsigned long cpu_callin_map[NR_CPUS] = {0,}; cpumask_t smp_commenced_mask = CPU_MASK_NONE; @@ -48,7 +48,7 @@ cpumask_t smp_commenced_mask = CPU_MASK_NONE; * instruction which is much better... */ -void __cpuinit smp_store_cpu_info(int id) +void smp_store_cpu_info(int id) { int cpu_node; int mid; @@ -123,7 +123,7 @@ void cpu_panic(void) panic("SMP bolixed\n"); } -struct linux_prom_registers smp_penguin_ctable __cpuinitdata = { 0 }; +struct linux_prom_registers smp_penguin_ctable = { 0 }; void smp_send_reschedule(int cpu) { @@ -411,10 +411,10 @@ void __init smp_prepare_boot_cpu(void) set_cpu_possible(cpuid, true); } -int __cpuinit __cpu_up(unsigned int cpu) +int __cpu_up(unsigned int cpu) { - extern int __cpuinit smp4m_boot_one_cpu(int); - extern int __cpuinit smp4d_boot_one_cpu(int); + extern int smp4m_boot_one_cpu(int); + extern int smp4d_boot_one_cpu(int); int ret=0; switch(sparc_cpu_model) { diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c index 3b1bd7c5016..67d6426cd1e 100644 --- a/arch/sparc/kernel/smp_64.c +++ b/arch/sparc/kernel/smp_64.c @@ -87,7 +87,7 @@ extern void setup_sparc64_timer(void); static volatile unsigned long callin_flag = 0; -void __cpuinit smp_callin(void) +void smp_callin(void) { int cpuid = hard_smp_processor_id(); @@ -282,7 +282,7 @@ static unsigned long kimage_addr_to_ra(void *p) return kern_base + (val - KERNBASE); } -static void __cpuinit ldom_startcpu_cpuid(unsigned int cpu, unsigned long thread_reg, void **descrp) +static void ldom_startcpu_cpuid(unsigned int cpu, unsigned long thread_reg, void **descrp) { extern unsigned long sparc64_ttable_tl0; extern unsigned long kern_locked_tte_data; @@ -343,7 +343,7 @@ extern unsigned long sparc64_cpu_startup; */ static struct thread_info *cpu_new_thread = NULL; -static int __cpuinit smp_boot_one_cpu(unsigned int cpu) +static int smp_boot_one_cpu(unsigned int cpu) { unsigned long entry = (unsigned long)(&sparc64_cpu_startup); @@ -1227,7 +1227,7 @@ void __devinit smp_fill_in_sib_core_maps(void) } } -int __cpuinit __cpu_up(unsigned int cpu) +int __cpu_up(unsigned int cpu) { int ret = smp_boot_one_cpu(cpu); diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c index 540b2fec09f..a1b64606565 100644 --- a/arch/sparc/kernel/sun4d_smp.c +++ b/arch/sparc/kernel/sun4d_smp.c @@ -47,7 +47,7 @@ static inline void show_leds(int cpuid) "i" (ASI_M_CTL)); } -void __cpuinit smp4d_callin(void) +void smp4d_callin(void) { int cpuid = hard_smp4d_processor_id(); unsigned long flags; @@ -127,7 +127,7 @@ void __init smp4d_boot_cpus(void) local_flush_cache_all(); } -int __cpuinit smp4d_boot_one_cpu(int i) +int smp4d_boot_one_cpu(int i) { unsigned long *entry = &sun4d_cpu_startup; struct task_struct *p; @@ -393,7 +393,7 @@ void smp4d_percpu_timer_interrupt(struct pt_regs *regs) set_irq_regs(old_regs); } -static void __cpuinit smp_setup_percpu_timer(void) +static void smp_setup_percpu_timer(void) { int cpu = hard_smp4d_processor_id(); diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c index 02db9a0412c..ba9c46b1680 100644 --- a/arch/sparc/kernel/sun4m_smp.c +++ b/arch/sparc/kernel/sun4m_smp.c @@ -33,7 +33,7 @@ swap_ulong(volatile unsigned long *ptr, unsigned long val) static void smp4m_ipi_init(void); static void smp_setup_percpu_timer(void); -void __cpuinit smp4m_callin(void) +void smp4m_callin(void) { int cpuid = hard_smp_processor_id(); @@ -91,7 +91,7 @@ void __init smp4m_boot_cpus(void) local_flush_cache_all(); } -int __cpuinit smp4m_boot_one_cpu(int i) +int smp4m_boot_one_cpu(int i) { unsigned long *entry = &sun4m_cpu_startup; struct task_struct *p; @@ -280,7 +280,7 @@ void smp4m_percpu_timer_interrupt(struct pt_regs *regs) set_irq_regs(old_regs); } -static void __cpuinit smp_setup_percpu_timer(void) +static void smp_setup_percpu_timer(void) { int cpu = smp_processor_id(); diff --git a/arch/sparc/kernel/sysfs.c b/arch/sparc/kernel/sysfs.c index 654e8aad3bb..c21c673e5f7 100644 --- a/arch/sparc/kernel/sysfs.c +++ b/arch/sparc/kernel/sysfs.c @@ -246,7 +246,7 @@ static void unregister_cpu_online(unsigned int cpu) } #endif -static int __cpuinit sysfs_cpu_notify(struct notifier_block *self, +static int sysfs_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) { unsigned int cpu = (unsigned int)(long)hcpu; @@ -266,7 +266,7 @@ static int __cpuinit sysfs_cpu_notify(struct notifier_block *self, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata sysfs_cpu_nb = { +static struct notifier_block sysfs_cpu_nb = { .notifier_call = sysfs_cpu_notify, }; diff --git a/arch/sparc/kernel/systbls_64.S b/arch/sparc/kernel/systbls_64.S index db86b1a0e9a..3a58e0d66f5 100644 --- a/arch/sparc/kernel/systbls_64.S +++ b/arch/sparc/kernel/systbls_64.S @@ -74,7 +74,7 @@ sys_call_table32: .word sys_timer_delete, compat_sys_timer_create, sys_ni_syscall, compat_sys_io_setup, sys_io_destroy /*270*/ .word sys32_io_submit, sys_io_cancel, compat_sys_io_getevents, sys32_mq_open, sys_mq_unlink .word compat_sys_mq_timedsend, compat_sys_mq_timedreceive, compat_sys_mq_notify, compat_sys_mq_getsetattr, compat_sys_waitid -/*280*/ .word sys32_tee, sys_add_key, sys_request_key, sys_keyctl, compat_sys_openat +/*280*/ .word sys32_tee, sys_add_key, sys_request_key, compat_sys_keyctl, compat_sys_openat .word sys_mkdirat, sys_mknodat, sys_fchownat, compat_sys_futimesat, compat_sys_fstatat64 /*290*/ .word sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat .word sys_fchmodat, sys_faccessat, compat_sys_pselect6, compat_sys_ppoll, sys_unshare diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c index 21faaeea85d..4aff8f39fce 100644 --- a/arch/sparc/mm/init_64.c +++ b/arch/sparc/mm/init_64.c @@ -1675,7 +1675,7 @@ static void __init sun4v_ktsb_init(void) #endif } -void __cpuinit sun4v_ktsb_register(void) +void sun4v_ktsb_register(void) { unsigned long pa, ret; diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c index cbef74e793b..5bd7ac95e0e 100644 --- a/arch/sparc/mm/srmmu.c +++ b/arch/sparc/mm/srmmu.c @@ -1256,7 +1256,7 @@ static inline void map_kernel(void) /* Paging initialization on the Sparc Reference MMU. */ extern void sparc_context_init(int); -void (*poke_srmmu)(void) __cpuinitdata = NULL; +void (*poke_srmmu)(void) = NULL; extern unsigned long bootmem_init(unsigned long *pages_avail); @@ -1451,7 +1451,7 @@ static void __init init_vac_layout(void) (int)vac_cache_size, (int)vac_line_size); } -static void __cpuinit poke_hypersparc(void) +static void poke_hypersparc(void) { volatile unsigned long clear; unsigned long mreg = srmmu_get_mmureg(); @@ -1506,7 +1506,7 @@ static void __init init_hypersparc(void) hypersparc_setup_blockops(); } -static void __cpuinit poke_cypress(void) +static void poke_cypress(void) { unsigned long mreg = srmmu_get_mmureg(); unsigned long faddr, tagval; @@ -1594,7 +1594,7 @@ static void __init init_cypress_605(unsigned long mrev) init_cypress_common(); } -static void __cpuinit poke_swift(void) +static void poke_swift(void) { unsigned long mreg; @@ -1776,7 +1776,7 @@ static void turbosparc_flush_tlb_page(struct vm_area_struct *vma, unsigned long } -static void __cpuinit poke_turbosparc(void) +static void poke_turbosparc(void) { unsigned long mreg = srmmu_get_mmureg(); unsigned long ccreg; @@ -1839,7 +1839,7 @@ static void __init init_turbosparc(void) poke_srmmu = poke_turbosparc; } -static void __cpuinit poke_tsunami(void) +static void poke_tsunami(void) { unsigned long mreg = srmmu_get_mmureg(); @@ -1881,7 +1881,7 @@ static void __init init_tsunami(void) tsunami_setup_blockops(); } -static void __cpuinit poke_viking(void) +static void poke_viking(void) { unsigned long mreg = srmmu_get_mmureg(); static int smp_catch; diff --git a/arch/tile/include/asm/bitops.h b/arch/tile/include/asm/bitops.h index 16f1fa51fea..bd186c4eaa5 100644 --- a/arch/tile/include/asm/bitops.h +++ b/arch/tile/include/asm/bitops.h @@ -77,6 +77,11 @@ static inline int ffs(int x) return __builtin_ffs(x); } +static inline int fls64(__u64 w) +{ + return (sizeof(__u64) * 8) - __builtin_clzll(w); +} + /** * fls - find last set bit in word * @x: the word to search @@ -90,12 +95,7 @@ static inline int ffs(int x) */ static inline int fls(int x) { - return (sizeof(int) * 8) - __builtin_clz(x); -} - -static inline int fls64(__u64 w) -{ - return (sizeof(__u64) * 8) - __builtin_clzll(w); + return fls64((unsigned int) x); } static inline unsigned int __arch_hweight32(unsigned int w) diff --git a/arch/tile/kernel/irq.c b/arch/tile/kernel/irq.c index 02e62806501..3ccf2cd7182 100644 --- a/arch/tile/kernel/irq.c +++ b/arch/tile/kernel/irq.c @@ -220,7 +220,7 @@ void __init init_IRQ(void) ipi_init(); } -void __cpuinit setup_irq_regs(void) +void setup_irq_regs(void) { /* Enable interrupt delivery. */ unmask_irqs(~0UL); diff --git a/arch/tile/kernel/messaging.c b/arch/tile/kernel/messaging.c index 0858ee6b520..00331af9525 100644 --- a/arch/tile/kernel/messaging.c +++ b/arch/tile/kernel/messaging.c @@ -25,7 +25,7 @@ /* All messages are stored here */ static DEFINE_PER_CPU(HV_MsgState, msg_state); -void __cpuinit init_messaging(void) +void init_messaging(void) { /* Allocate storage for messages in kernel space */ HV_MsgState *state = &__get_cpu_var(msg_state); diff --git a/arch/tile/kernel/setup.c b/arch/tile/kernel/setup.c index bff23f47611..7bd2060b1e1 100644 --- a/arch/tile/kernel/setup.c +++ b/arch/tile/kernel/setup.c @@ -53,8 +53,8 @@ EXPORT_SYMBOL(node_data); static bootmem_data_t __initdata node0_bdata; /* Information on the NUMA nodes that we compute early */ -unsigned long __cpuinitdata node_start_pfn[MAX_NUMNODES]; -unsigned long __cpuinitdata node_end_pfn[MAX_NUMNODES]; +unsigned long node_start_pfn[MAX_NUMNODES]; +unsigned long node_end_pfn[MAX_NUMNODES]; unsigned long __initdata node_memmap_pfn[MAX_NUMNODES]; unsigned long __initdata node_percpu_pfn[MAX_NUMNODES]; unsigned long __initdata node_free_pfn[MAX_NUMNODES]; @@ -63,7 +63,7 @@ static unsigned long __initdata node_percpu[MAX_NUMNODES]; #ifdef CONFIG_HIGHMEM /* Page frame index of end of lowmem on each controller. */ -unsigned long __cpuinitdata node_lowmem_end_pfn[MAX_NUMNODES]; +unsigned long node_lowmem_end_pfn[MAX_NUMNODES]; /* Number of pages that can be mapped into lowmem. */ static unsigned long __initdata mappable_physpages; @@ -269,7 +269,7 @@ static void *__init setup_pa_va_mapping(void) * This is up to 4 mappings for lowmem, one mapping per memory * controller, plus one for our text segment. */ -static void __cpuinit store_permanent_mappings(void) +static void store_permanent_mappings(void) { int i; @@ -860,7 +860,7 @@ subsys_initcall(topology_init); * * Called from setup_arch() on the boot cpu, or online_secondary(). */ -void __cpuinit setup_cpu(int boot) +void setup_cpu(int boot) { /* The boot cpu sets up its permanent mappings much earlier. */ if (!boot) diff --git a/arch/tile/kernel/smpboot.c b/arch/tile/kernel/smpboot.c index 172aef7d315..3e51e70903f 100644 --- a/arch/tile/kernel/smpboot.c +++ b/arch/tile/kernel/smpboot.c @@ -133,14 +133,14 @@ static __init int reset_init_affinity(void) } late_initcall(reset_init_affinity); -static struct cpumask cpu_started __cpuinitdata; +static struct cpumask cpu_started; /* * Activate a secondary processor. Very minimal; don't add anything * to this path without knowing what you're doing, since SMP booting * is pretty fragile. */ -static void __cpuinit start_secondary(void) +static void start_secondary(void) { int cpuid = smp_processor_id(); @@ -183,7 +183,7 @@ static void __cpuinit start_secondary(void) /* * Bring a secondary processor online. */ -void __cpuinit online_secondary(void) +void online_secondary(void) { /* * low-memory mappings have been cleared, flush them from @@ -222,7 +222,7 @@ void __cpuinit online_secondary(void) cpu_idle(); } -int __cpuinit __cpu_up(unsigned int cpu) +int __cpu_up(unsigned int cpu) { /* Wait 5s total for all CPUs for them to come online */ static int timeout; diff --git a/arch/tile/kernel/time.c b/arch/tile/kernel/time.c index f6f50f2a5e3..e85ada940c7 100644 --- a/arch/tile/kernel/time.c +++ b/arch/tile/kernel/time.c @@ -159,7 +159,7 @@ static DEFINE_PER_CPU(struct clock_event_device, tile_timer) = { .set_mode = tile_timer_set_mode, }; -void __cpuinit setup_tile_timer(void) +void setup_tile_timer(void) { struct clock_event_device *evt = &__get_cpu_var(tile_timer); diff --git a/arch/um/include/asm/pgtable.h b/arch/um/include/asm/pgtable.h index 6a3f9845743..5888f1b8347 100644 --- a/arch/um/include/asm/pgtable.h +++ b/arch/um/include/asm/pgtable.h @@ -273,6 +273,12 @@ static inline void set_pte(pte_t *pteptr, pte_t pteval) } #define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval) +#define __HAVE_ARCH_PTE_SAME +static inline int pte_same(pte_t pte_a, pte_t pte_b) +{ + return !((pte_val(pte_a) ^ pte_val(pte_b)) & ~_PAGE_NEWPAGE); +} + /* * Conversion functions: convert a page and protection to a page entry, * and a page entry and page directory to the page they refer to. @@ -348,11 +354,11 @@ extern pte_t *virt_to_pte(struct mm_struct *mm, unsigned long addr); #define update_mmu_cache(vma,address,ptep) do ; while (0) /* Encode and de-code a swap entry */ -#define __swp_type(x) (((x).val >> 4) & 0x3f) +#define __swp_type(x) (((x).val >> 5) & 0x1f) #define __swp_offset(x) ((x).val >> 11) #define __swp_entry(type, offset) \ - ((swp_entry_t) { ((type) << 4) | ((offset) << 11) }) + ((swp_entry_t) { ((type) << 5) | ((offset) << 11) }) #define __pte_to_swp_entry(pte) \ ((swp_entry_t) { pte_val(pte_mkuptodate(pte)) }) #define __swp_entry_to_pte(x) ((pte_t) { (x).val }) diff --git a/arch/x86/Makefile b/arch/x86/Makefile index 94e91e401da..b1c611e6da6 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -206,6 +206,7 @@ archclean: $(Q)rm -rf $(objtree)/arch/i386 $(Q)rm -rf $(objtree)/arch/x86_64 $(Q)$(MAKE) $(clean)=$(boot) + $(Q)$(MAKE) $(clean)=arch/x86/tools define archhelp echo '* bzImage - Compressed kernel image (arch/x86/boot/bzImage)' diff --git a/arch/x86/include/asm/mmconfig.h b/arch/x86/include/asm/mmconfig.h index 9b119da1d10..04a3fed22cf 100644 --- a/arch/x86/include/asm/mmconfig.h +++ b/arch/x86/include/asm/mmconfig.h @@ -2,8 +2,8 @@ #define _ASM_X86_MMCONFIG_H #ifdef CONFIG_PCI_MMCONFIG -extern void __cpuinit fam10h_check_enable_mmcfg(void); -extern void __cpuinit check_enable_amd_mmconf_dmi(void); +extern void fam10h_check_enable_mmcfg(void); +extern void check_enable_amd_mmconf_dmi(void); #else static inline void fam10h_check_enable_mmcfg(void) { } static inline void check_enable_amd_mmconf_dmi(void) { } diff --git a/arch/x86/include/asm/mpspec.h b/arch/x86/include/asm/mpspec.h index 9c7d95f6174..97063b9b363 100644 --- a/arch/x86/include/asm/mpspec.h +++ b/arch/x86/include/asm/mpspec.h @@ -94,7 +94,7 @@ static inline void early_reserve_e820_mpc_new(void) { } #define default_get_smp_config x86_init_uint_noop #endif -void __cpuinit generic_processor_info(int apicid, int version); +void generic_processor_info(int apicid, int version); #ifdef CONFIG_ACPI extern void mp_register_ioapic(int id, u32 address, u32 gsi_base); extern void mp_override_legacy_irq(u8 bus_irq, u8 polarity, u8 trigger, diff --git a/arch/x86/include/asm/numa.h b/arch/x86/include/asm/numa.h index bfacd2ccf65..f6e37933ce7 100644 --- a/arch/x86/include/asm/numa.h +++ b/arch/x86/include/asm/numa.h @@ -39,7 +39,7 @@ static inline void set_apicid_to_node(int apicid, s16 node) __apicid_to_node[apicid] = node; } -extern int __cpuinit numa_cpu_node(int cpu); +extern int numa_cpu_node(int cpu); #else /* CONFIG_NUMA */ static inline void set_apicid_to_node(int apicid, s16 node) @@ -59,11 +59,11 @@ static inline int numa_cpu_node(int cpu) #endif #ifdef CONFIG_NUMA -extern void __cpuinit numa_set_node(int cpu, int node); -extern void __cpuinit numa_clear_node(int cpu); +extern void numa_set_node(int cpu, int node); +extern void numa_clear_node(int cpu); extern void __init init_cpu_to_node(void); -extern void __cpuinit numa_add_cpu(int cpu); -extern void __cpuinit numa_remove_cpu(int cpu); +extern void numa_add_cpu(int cpu); +extern void numa_remove_cpu(int cpu); #else /* CONFIG_NUMA */ static inline void numa_set_node(int cpu, int node) { } static inline void numa_clear_node(int cpu) { } diff --git a/arch/x86/include/asm/prom.h b/arch/x86/include/asm/prom.h index 60bef663609..bade6ac3b14 100644 --- a/arch/x86/include/asm/prom.h +++ b/arch/x86/include/asm/prom.h @@ -27,7 +27,7 @@ extern int of_ioapic; extern u64 initial_dtb; extern void add_dtb(u64 data); extern void x86_add_irq_domains(void); -void __cpuinit x86_of_pci_init(void); +void x86_of_pci_init(void); void x86_dtb_init(void); #else static inline void add_dtb(u64 data) { } diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h index 0434c400287..7ecdedb358b 100644 --- a/arch/x86/include/asm/smp.h +++ b/arch/x86/include/asm/smp.h @@ -180,7 +180,7 @@ static inline int wbinvd_on_all_cpus(void) } #endif /* CONFIG_SMP */ -extern unsigned disabled_cpus __cpuinitdata; +extern unsigned disabled_cpusdata; #ifdef CONFIG_X86_32_SMP /* diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 7c439fe4941..d4686c94067 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -195,7 +195,7 @@ static int __init acpi_parse_madt(struct acpi_table_header *table) return 0; } -static void __cpuinit acpi_register_lapic(int id, u8 enabled) +static void acpi_register_lapic(int id, u8 enabled) { unsigned int ver = 0; @@ -593,7 +593,7 @@ void __init acpi_set_irq_model_ioapic(void) #ifdef CONFIG_ACPI_HOTPLUG_CPU #include -static void __cpuinit acpi_map_cpu2node(acpi_handle handle, int cpu, int physid) +static void acpi_map_cpu2node(acpi_handle handle, int cpu, int physid) { #ifdef CONFIG_ACPI_NUMA int nid; @@ -606,7 +606,7 @@ static void __cpuinit acpi_map_cpu2node(acpi_handle handle, int cpu, int physid) #endif } -static int __cpuinit _acpi_map_lsapic(acpi_handle handle, int *pcpu) +static int _acpi_map_lsapic(acpi_handle handle, int *pcpu) { struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; union acpi_object *obj; diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index edc24480469..aaab1245802 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -56,7 +56,7 @@ unsigned int num_processors; -unsigned disabled_cpus __cpuinitdata; +unsigned disabled_cpus; /* Processor that is doing the boot up */ unsigned int boot_cpu_physical_apicid = -1U; @@ -519,7 +519,7 @@ static DEFINE_PER_CPU(struct clock_event_device, lapic_events); * Setup the local APIC timer for this CPU. Copy the initialized values * of the boot CPU and register the clock event in the framework. */ -static void __cpuinit setup_APIC_timer(void) +static void setup_APIC_timer(void) { struct clock_event_device *levt = &__get_cpu_var(lapic_events); @@ -831,7 +831,7 @@ void __init setup_boot_APIC_clock(void) setup_APIC_timer(); } -void __cpuinit setup_secondary_APIC_clock(void) +void setup_secondary_APIC_clock(void) { setup_APIC_timer(); } @@ -1176,7 +1176,7 @@ void __init init_bsp_APIC(void) apic_write(APIC_LVT1, value); } -static void __cpuinit lapic_setup_esr(void) +static void lapic_setup_esr(void) { unsigned int oldvalue, value, maxlvt; @@ -1223,7 +1223,7 @@ static void __cpuinit lapic_setup_esr(void) * Used to setup local APIC while initializing BSP or bringin up APs. * Always called with preemption disabled. */ -void __cpuinit setup_local_APIC(void) +void setup_local_APIC(void) { int cpu = smp_processor_id(); unsigned int value, queued; @@ -1416,7 +1416,7 @@ void __cpuinit setup_local_APIC(void) #endif } -void __cpuinit end_local_APIC_setup(void) +void end_local_APIC_setup(void) { lapic_setup_esr(); @@ -2024,7 +2024,7 @@ void disconnect_bsp_APIC(int virt_wire_setup) apic_write(APIC_LVT1, value); } -void __cpuinit generic_processor_info(int apicid, int version) +void generic_processor_info(int apicid, int version) { int cpu, max = nr_cpu_ids; bool boot_cpu_detected = physid_isset(boot_cpu_physical_apicid, @@ -2261,7 +2261,7 @@ static struct syscore_ops lapic_syscore_ops = { .suspend = lapic_suspend, }; -static void __cpuinit apic_pm_activate(void) +static void apic_pm_activate(void) { apic_pm_state.active = 1; } @@ -2286,7 +2286,7 @@ static void apic_pm_activate(void) { } #ifdef CONFIG_X86_64 -static int __cpuinit apic_cluster_num(void) +static int apic_cluster_num(void) { int i, clusters, zeros; unsigned id; @@ -2331,10 +2331,10 @@ static int __cpuinit apic_cluster_num(void) return clusters; } -static int __cpuinitdata multi_checked; -static int __cpuinitdata multi; +static int multi_checked; +static int multi; -static int __cpuinit set_multi(const struct dmi_system_id *d) +static int set_multi(const struct dmi_system_id *d) { if (multi) return 0; @@ -2343,7 +2343,7 @@ static int __cpuinit set_multi(const struct dmi_system_id *d) return 0; } -static const __cpuinitconst struct dmi_system_id multi_dmi_table[] = { +static const struct dmi_system_id multi_dmi_table[] = { { .callback = set_multi, .ident = "IBM System Summit2", @@ -2355,7 +2355,7 @@ static const __cpuinitconst struct dmi_system_id multi_dmi_table[] = { {} }; -static void __cpuinit dmi_check_multi(void) +static void dmi_check_multi(void) { if (multi_checked) return; @@ -2372,7 +2372,7 @@ static void __cpuinit dmi_check_multi(void) * multi-chassis. * Use DMI to check them */ -__cpuinit int apic_is_clustered_box(void) +int apic_is_clustered_box(void) { dmi_check_multi(); if (multi) diff --git a/arch/x86/kernel/apic/apic_numachip.c b/arch/x86/kernel/apic/apic_numachip.c index 23e75422e01..bd8eb638138 100644 --- a/arch/x86/kernel/apic/apic_numachip.c +++ b/arch/x86/kernel/apic/apic_numachip.c @@ -83,7 +83,7 @@ static void numachip_vector_allocation_domain(int cpu, struct cpumask *retmask) cpumask_set_cpu(cpu, retmask); } -static int __cpuinit numachip_wakeup_secondary(int phys_apicid, unsigned long start_rip) +static int numachip_wakeup_secondary(int phys_apicid, unsigned long start_rip) { union numachip_csr_g3_ext_irq_gen int_gen; diff --git a/arch/x86/kernel/apic/es7000_32.c b/arch/x86/kernel/apic/es7000_32.c index e42d1d3b913..1e43839de8e 100644 --- a/arch/x86/kernel/apic/es7000_32.c +++ b/arch/x86/kernel/apic/es7000_32.c @@ -130,7 +130,7 @@ int es7000_plat; */ -static int __cpuinit wakeup_secondary_cpu_via_mip(int cpu, unsigned long eip) +static int wakeup_secondary_cpu_via_mip(int cpu, unsigned long eip) { unsigned long vect = 0, psaival = 0; diff --git a/arch/x86/kernel/apic/numaq_32.c b/arch/x86/kernel/apic/numaq_32.c index 00d2422ca7c..7e7b9822014 100644 --- a/arch/x86/kernel/apic/numaq_32.c +++ b/arch/x86/kernel/apic/numaq_32.c @@ -105,7 +105,7 @@ static void __init smp_dump_qct(void) } } -void __cpuinit numaq_tsc_disable(void) +void numaq_tsc_disable(void) { if (!found_numaq) return; diff --git a/arch/x86/kernel/apic/x2apic_cluster.c b/arch/x86/kernel/apic/x2apic_cluster.c index 48f3103b3c9..b6802b2c678 100644 --- a/arch/x86/kernel/apic/x2apic_cluster.c +++ b/arch/x86/kernel/apic/x2apic_cluster.c @@ -147,7 +147,7 @@ static void init_x2apic_ldr(void) /* * At CPU state changes, update the x2apic cluster sibling info. */ -static int __cpuinit +static int update_clusterinfo(struct notifier_block *nfb, unsigned long action, void *hcpu) { unsigned int this_cpu = (unsigned long)hcpu; diff --git a/arch/x86/kernel/apic/x2apic_uv_x.c b/arch/x86/kernel/apic/x2apic_uv_x.c index 87bfa69e216..687f7dc6040 100644 --- a/arch/x86/kernel/apic/x2apic_uv_x.c +++ b/arch/x86/kernel/apic/x2apic_uv_x.c @@ -196,7 +196,7 @@ static void uv_vector_allocation_domain(int cpu, struct cpumask *retmask) cpumask_set_cpu(cpu, retmask); } -static int __cpuinit uv_wakeup_secondary(int phys_apicid, unsigned long start_rip) +static int uv_wakeup_secondary(int phys_apicid, unsigned long start_rip) { #ifdef CONFIG_SMP unsigned long val; @@ -410,7 +410,7 @@ static struct apic __refdata apic_x2apic_uv_x = { .safe_wait_icr_idle = native_safe_x2apic_wait_icr_idle, }; -static __cpuinit void set_x2apic_extra_bits(int pnode) +static void set_x2apic_extra_bits(int pnode) { __this_cpu_write(x2apic_extra_bits, pnode << uvh_apicid.s.pnode_shift); } @@ -565,7 +565,7 @@ static void uv_heartbeat(unsigned long ignored) mod_timer_pinned(timer, jiffies + SCIR_CPU_HB_INTERVAL); } -static void __cpuinit uv_heartbeat_enable(int cpu) +static void uv_heartbeat_enable(int cpu) { while (!uv_cpu_hub_info(cpu)->scir.enabled) { struct timer_list *timer = &uv_cpu_hub_info(cpu)->scir.timer; @@ -582,7 +582,7 @@ static void __cpuinit uv_heartbeat_enable(int cpu) } #ifdef CONFIG_HOTPLUG_CPU -static void __cpuinit uv_heartbeat_disable(int cpu) +static void uv_heartbeat_disable(int cpu) { if (uv_cpu_hub_info(cpu)->scir.enabled) { uv_cpu_hub_info(cpu)->scir.enabled = 0; @@ -594,7 +594,7 @@ static void __cpuinit uv_heartbeat_disable(int cpu) /* * cpu hotplug notifier */ -static __cpuinit int uv_scir_cpu_notify(struct notifier_block *self, +static int uv_scir_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) { long cpu = (long)hcpu; @@ -665,7 +665,7 @@ int uv_set_vga_state(struct pci_dev *pdev, bool decode, * Called on each cpu to initialize the per_cpu UV data area. * FIXME: hotplug not supported yet */ -void __cpuinit uv_cpu_init(void) +void uv_cpu_init(void) { /* CPU 0 initilization will be done via uv_system_init. */ if (!uv_blade_info) diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index 146bb6218ee..d40b9ca6a56 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -37,7 +37,7 @@ extern void vide(void); __asm__(".align 4\nvide: ret"); -static void __cpuinit init_amd_k5(struct cpuinfo_x86 *c) +static void init_amd_k5(struct cpuinfo_x86 *c) { /* * General Systems BIOSen alias the cpu frequency registers @@ -55,7 +55,7 @@ static void __cpuinit init_amd_k5(struct cpuinfo_x86 *c) } -static void __cpuinit init_amd_k6(struct cpuinfo_x86 *c) +static void init_amd_k6(struct cpuinfo_x86 *c) { u32 l, h; int mbytes = num_physpages >> (20-PAGE_SHIFT); @@ -147,7 +147,7 @@ static void __cpuinit init_amd_k6(struct cpuinfo_x86 *c) } } -static void __cpuinit amd_k7_smp_check(struct cpuinfo_x86 *c) +static void amd_k7_smp_check(struct cpuinfo_x86 *c) { /* calling is from identify_secondary_cpu() ? */ if (!c->cpu_index) @@ -194,7 +194,7 @@ static void __cpuinit amd_k7_smp_check(struct cpuinfo_x86 *c) ; } -static void __cpuinit init_amd_k7(struct cpuinfo_x86 *c) +static void init_amd_k7(struct cpuinfo_x86 *c) { u32 l, h; @@ -239,7 +239,7 @@ static void __cpuinit init_amd_k7(struct cpuinfo_x86 *c) * To workaround broken NUMA config. Read the comment in * srat_detect_node(). */ -static int __cpuinit nearby_node(int apicid) +static int nearby_node(int apicid) { int i, node; @@ -264,7 +264,7 @@ static int __cpuinit nearby_node(int apicid) * (2) AMD processors supporting compute units */ #ifdef CONFIG_X86_HT -static void __cpuinit amd_get_topology(struct cpuinfo_x86 *c) +static void amd_get_topology(struct cpuinfo_x86 *c) { u32 nodes, cores_per_cu = 1; u8 node_id; @@ -314,7 +314,7 @@ static void __cpuinit amd_get_topology(struct cpuinfo_x86 *c) * On a AMD dual core setup the lower bits of the APIC id distingush the cores. * Assumes number of cores is a power of two. */ -static void __cpuinit amd_detect_cmp(struct cpuinfo_x86 *c) +static void amd_detect_cmp(struct cpuinfo_x86 *c) { #ifdef CONFIG_X86_HT unsigned bits; @@ -341,7 +341,7 @@ int amd_get_nb_id(int cpu) } EXPORT_SYMBOL_GPL(amd_get_nb_id); -static void __cpuinit srat_detect_node(struct cpuinfo_x86 *c) +static void srat_detect_node(struct cpuinfo_x86 *c) { #ifdef CONFIG_NUMA int cpu = smp_processor_id(); @@ -393,7 +393,7 @@ static void __cpuinit srat_detect_node(struct cpuinfo_x86 *c) #endif } -static void __cpuinit early_init_amd_mc(struct cpuinfo_x86 *c) +static void early_init_amd_mc(struct cpuinfo_x86 *c) { #ifdef CONFIG_X86_HT unsigned bits, ecx; @@ -419,7 +419,7 @@ static void __cpuinit early_init_amd_mc(struct cpuinfo_x86 *c) #endif } -static void __cpuinit bsp_init_amd(struct cpuinfo_x86 *c) +static void bsp_init_amd(struct cpuinfo_x86 *c) { if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) { @@ -447,7 +447,7 @@ static void __cpuinit bsp_init_amd(struct cpuinfo_x86 *c) } } -static void __cpuinit early_init_amd(struct cpuinfo_x86 *c) +static void early_init_amd(struct cpuinfo_x86 *c) { early_init_amd_mc(c); @@ -482,7 +482,7 @@ static void __cpuinit early_init_amd(struct cpuinfo_x86 *c) #endif } -static void __cpuinit init_amd(struct cpuinfo_x86 *c) +static void init_amd(struct cpuinfo_x86 *c) { u32 dummy; @@ -687,7 +687,7 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) } #ifdef CONFIG_X86_32 -static unsigned int __cpuinit amd_size_cache(struct cpuinfo_x86 *c, +static unsigned int amd_size_cache(struct cpuinfo_x86 *c, unsigned int size) { /* AMD errata T13 (order #21922) */ @@ -704,7 +704,7 @@ static unsigned int __cpuinit amd_size_cache(struct cpuinfo_x86 *c, } #endif -static const struct cpu_dev __cpuinitconst amd_cpu_dev = { +static const struct cpu_dev amd_cpu_dev = { .c_vendor = "AMD", .c_ident = { "AuthenticAMD" }, #ifdef CONFIG_X86_32 diff --git a/arch/x86/kernel/cpu/centaur.c b/arch/x86/kernel/cpu/centaur.c index 159103c0b1f..fbf6c3bc240 100644 --- a/arch/x86/kernel/cpu/centaur.c +++ b/arch/x86/kernel/cpu/centaur.c @@ -11,7 +11,7 @@ #ifdef CONFIG_X86_OOSTORE -static u32 __cpuinit power2(u32 x) +static u32 power2(u32 x) { u32 s = 1; @@ -25,7 +25,7 @@ static u32 __cpuinit power2(u32 x) /* * Set up an actual MCR */ -static void __cpuinit centaur_mcr_insert(int reg, u32 base, u32 size, int key) +static void centaur_mcr_insert(int reg, u32 base, u32 size, int key) { u32 lo, hi; @@ -42,7 +42,7 @@ static void __cpuinit centaur_mcr_insert(int reg, u32 base, u32 size, int key) * * Shortcut: We know you can't put 4Gig of RAM on a winchip */ -static u32 __cpuinit ramtop(void) +static u32 ramtop(void) { u32 clip = 0xFFFFFFFFUL; u32 top = 0; @@ -91,7 +91,7 @@ static u32 __cpuinit ramtop(void) /* * Compute a set of MCR's to give maximum coverage */ -static int __cpuinit centaur_mcr_compute(int nr, int key) +static int centaur_mcr_compute(int nr, int key) { u32 mem = ramtop(); u32 root = power2(mem); @@ -157,7 +157,7 @@ static int __cpuinit centaur_mcr_compute(int nr, int key) return ct; } -static void __cpuinit centaur_create_optimal_mcr(void) +static void centaur_create_optimal_mcr(void) { int used; int i; @@ -181,7 +181,7 @@ static void __cpuinit centaur_create_optimal_mcr(void) wrmsr(MSR_IDT_MCR0+i, 0, 0); } -static void __cpuinit winchip2_create_optimal_mcr(void) +static void winchip2_create_optimal_mcr(void) { u32 lo, hi; int used; @@ -217,7 +217,7 @@ static void __cpuinit winchip2_create_optimal_mcr(void) /* * Handle the MCR key on the Winchip 2. */ -static void __cpuinit winchip2_unprotect_mcr(void) +static void winchip2_unprotect_mcr(void) { u32 lo, hi; u32 key; @@ -229,7 +229,7 @@ static void __cpuinit winchip2_unprotect_mcr(void) wrmsr(MSR_IDT_MCR_CTRL, lo, hi); } -static void __cpuinit winchip2_protect_mcr(void) +static void winchip2_protect_mcr(void) { u32 lo, hi; @@ -247,7 +247,7 @@ static void __cpuinit winchip2_protect_mcr(void) #define RNG_ENABLED (1 << 3) #define RNG_ENABLE (1 << 6) /* MSR_VIA_RNG */ -static void __cpuinit init_c3(struct cpuinfo_x86 *c) +static void init_c3(struct cpuinfo_x86 *c) { u32 lo, hi; @@ -318,7 +318,7 @@ enum { EAMD3D = 1<<20, }; -static void __cpuinit early_init_centaur(struct cpuinfo_x86 *c) +static void early_init_centaur(struct cpuinfo_x86 *c) { switch (c->x86) { #ifdef CONFIG_X86_32 @@ -337,7 +337,7 @@ static void __cpuinit early_init_centaur(struct cpuinfo_x86 *c) #endif } -static void __cpuinit init_centaur(struct cpuinfo_x86 *c) +static void init_centaur(struct cpuinfo_x86 *c) { #ifdef CONFIG_X86_32 char *name; @@ -468,7 +468,7 @@ static void __cpuinit init_centaur(struct cpuinfo_x86 *c) #endif } -static unsigned int __cpuinit +static unsigned int centaur_size_cache(struct cpuinfo_x86 *c, unsigned int size) { #ifdef CONFIG_X86_32 @@ -488,7 +488,7 @@ centaur_size_cache(struct cpuinfo_x86 *c, unsigned int size) return size; } -static const struct cpu_dev __cpuinitconst centaur_cpu_dev = { +static const struct cpu_dev centaur_cpu_dev = { .c_vendor = "Centaur", .c_ident = { "CentaurHauls" }, .c_early_init = early_init_centaur, diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index cf79302198a..34f4060f537 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -61,7 +61,7 @@ void __init setup_cpu_local_masks(void) alloc_bootmem_cpumask_var(&cpu_sibling_setup_mask); } -static void __cpuinit default_init(struct cpuinfo_x86 *c) +static void default_init(struct cpuinfo_x86 *c) { #ifdef CONFIG_X86_64 cpu_detect_cache_sizes(c); @@ -78,13 +78,13 @@ static void __cpuinit default_init(struct cpuinfo_x86 *c) #endif } -static const struct cpu_dev __cpuinitconst default_cpu = { +static const struct cpu_dev default_cpu = { .c_init = default_init, .c_vendor = "Unknown", .c_x86_vendor = X86_VENDOR_UNKNOWN, }; -static const struct cpu_dev *this_cpu __cpuinitdata = &default_cpu; +static const struct cpu_dev *this_cpu = &default_cpu; DEFINE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page) = { .gdt = { #ifdef CONFIG_X86_64 @@ -156,8 +156,8 @@ static int __init x86_xsaveopt_setup(char *s) __setup("noxsaveopt", x86_xsaveopt_setup); #ifdef CONFIG_X86_32 -static int cachesize_override __cpuinitdata = -1; -static int disable_x86_serial_nr __cpuinitdata = 1; +static int cachesize_override = -1; +static int disable_x86_serial_nr = 1; static int __init cachesize_setup(char *str) { @@ -211,12 +211,12 @@ static inline int flag_is_changeable_p(u32 flag) } /* Probe for the CPUID instruction */ -static int __cpuinit have_cpuid_p(void) +static int have_cpuid_p(void) { return flag_is_changeable_p(X86_EFLAGS_ID); } -static void __cpuinit squash_the_stupid_serial_number(struct cpuinfo_x86 *c) +static void squash_the_stupid_serial_number(struct cpuinfo_x86 *c) { unsigned long lo, hi; @@ -257,7 +257,7 @@ static inline void squash_the_stupid_serial_number(struct cpuinfo_x86 *c) } #endif -static int disable_smep __cpuinitdata; +static int disable_smep; static __init int setup_disable_smep(char *arg) { disable_smep = 1; @@ -265,7 +265,7 @@ static __init int setup_disable_smep(char *arg) } __setup("nosmep", setup_disable_smep); -static __cpuinit void setup_smep(struct cpuinfo_x86 *c) +static void setup_smep(struct cpuinfo_x86 *c) { if (cpu_has(c, X86_FEATURE_SMEP)) { if (unlikely(disable_smep)) { @@ -286,7 +286,7 @@ struct cpuid_dependent_feature { u32 level; }; -static const struct cpuid_dependent_feature __cpuinitconst +static const struct cpuid_dependent_feature cpuid_dependent_features[] = { { X86_FEATURE_MWAIT, 0x00000005 }, { X86_FEATURE_DCA, 0x00000009 }, @@ -294,7 +294,7 @@ cpuid_dependent_features[] = { { 0, 0 } }; -static void __cpuinit filter_cpuid_features(struct cpuinfo_x86 *c, bool warn) +static void filter_cpuid_features(struct cpuinfo_x86 *c, bool warn) { const struct cpuid_dependent_feature *df; @@ -332,7 +332,7 @@ static void __cpuinit filter_cpuid_features(struct cpuinfo_x86 *c, bool warn) */ /* Look up CPU names by table lookup. */ -static const char *__cpuinit table_lookup_model(struct cpuinfo_x86 *c) +static const char *table_lookup_model(struct cpuinfo_x86 *c) { const struct cpu_model_info *info; @@ -352,8 +352,8 @@ static const char *__cpuinit table_lookup_model(struct cpuinfo_x86 *c) return NULL; /* Not found */ } -__u32 cpu_caps_cleared[NCAPINTS] __cpuinitdata; -__u32 cpu_caps_set[NCAPINTS] __cpuinitdata; +__u32 cpu_caps_cleared[NCAPINTS]; +__u32 cpu_caps_set[NCAPINTS]; void load_percpu_segment(int cpu) { @@ -382,9 +382,9 @@ void switch_to_new_gdt(int cpu) load_percpu_segment(cpu); } -static const struct cpu_dev *__cpuinitdata cpu_devs[X86_VENDOR_NUM] = {}; +static const struct cpu_dev *cpu_devs[X86_VENDOR_NUM] = {}; -static void __cpuinit get_model_name(struct cpuinfo_x86 *c) +static void get_model_name(struct cpuinfo_x86 *c) { unsigned int *v; char *p, *q; @@ -413,7 +413,7 @@ static void __cpuinit get_model_name(struct cpuinfo_x86 *c) } } -void __cpuinit cpu_detect_cache_sizes(struct cpuinfo_x86 *c) +void cpu_detect_cache_sizes(struct cpuinfo_x86 *c) { unsigned int n, dummy, ebx, ecx, edx, l2size; @@ -452,7 +452,7 @@ void __cpuinit cpu_detect_cache_sizes(struct cpuinfo_x86 *c) c->x86_cache_size = l2size; } -void __cpuinit detect_ht(struct cpuinfo_x86 *c) +void detect_ht(struct cpuinfo_x86 *c) { #ifdef CONFIG_X86_HT u32 eax, ebx, ecx, edx; @@ -503,7 +503,7 @@ void __cpuinit detect_ht(struct cpuinfo_x86 *c) #endif } -static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c) +static void get_cpu_vendor(struct cpuinfo_x86 *c) { char *v = c->x86_vendor_id; int i; @@ -530,7 +530,7 @@ static void __cpuinit get_cpu_vendor(struct cpuinfo_x86 *c) this_cpu = &default_cpu; } -void __cpuinit cpu_detect(struct cpuinfo_x86 *c) +void cpu_detect(struct cpuinfo_x86 *c) { /* Get vendor name */ cpuid(0x00000000, (unsigned int *)&c->cpuid_level, @@ -560,7 +560,7 @@ void __cpuinit cpu_detect(struct cpuinfo_x86 *c) } } -void __cpuinit get_cpu_cap(struct cpuinfo_x86 *c) +void get_cpu_cap(struct cpuinfo_x86 *c) { u32 tfms, xlvl; u32 ebx; @@ -611,7 +611,7 @@ void __cpuinit get_cpu_cap(struct cpuinfo_x86 *c) init_scattered_cpuid_features(c); } -static void __cpuinit identify_cpu_without_cpuid(struct cpuinfo_x86 *c) +static void identify_cpu_without_cpuid(struct cpuinfo_x86 *c) { #ifdef CONFIG_X86_32 int i; @@ -729,7 +729,7 @@ void __init early_cpu_init(void) * unless we can find a reliable way to detect all the broken cases. * Enable it explicitly on 64-bit for non-constant inputs of cpu_has(). */ -static void __cpuinit detect_nopl(struct cpuinfo_x86 *c) +static void detect_nopl(struct cpuinfo_x86 *c) { #ifdef CONFIG_X86_32 clear_cpu_cap(c, X86_FEATURE_NOPL); @@ -738,7 +738,7 @@ static void __cpuinit detect_nopl(struct cpuinfo_x86 *c) #endif } -static void __cpuinit generic_identify(struct cpuinfo_x86 *c) +static void generic_identify(struct cpuinfo_x86 *c) { c->extended_cpuid_level = 0; @@ -777,7 +777,7 @@ static void __cpuinit generic_identify(struct cpuinfo_x86 *c) /* * This does the hard work of actually picking apart the CPU stuff... */ -static void __cpuinit identify_cpu(struct cpuinfo_x86 *c) +static void identify_cpu(struct cpuinfo_x86 *c) { int i; @@ -913,7 +913,7 @@ void __init identify_boot_cpu(void) #endif } -void __cpuinit identify_secondary_cpu(struct cpuinfo_x86 *c) +void identify_secondary_cpu(struct cpuinfo_x86 *c) { BUG_ON(c == &boot_cpu_data); identify_cpu(c); @@ -928,14 +928,14 @@ struct msr_range { unsigned max; }; -static const struct msr_range msr_range_array[] __cpuinitconst = { +static const struct msr_range msr_range_array[] = { { 0x00000000, 0x00000418}, { 0xc0000000, 0xc000040b}, { 0xc0010000, 0xc0010142}, { 0xc0011000, 0xc001103b}, }; -static void __cpuinit __print_cpu_msr(void) +static void __print_cpu_msr(void) { unsigned index_min, index_max; unsigned index; @@ -954,7 +954,7 @@ static void __cpuinit __print_cpu_msr(void) } } -static int show_msr __cpuinitdata; +static int show_msr; static __init int setup_show_msr(char *arg) { @@ -975,7 +975,7 @@ static __init int setup_noclflush(char *arg) } __setup("noclflush", setup_noclflush); -void __cpuinit print_cpu_info(struct cpuinfo_x86 *c) +void print_cpu_info(struct cpuinfo_x86 *c) { const char *vendor = NULL; @@ -1002,7 +1002,7 @@ void __cpuinit print_cpu_info(struct cpuinfo_x86 *c) print_cpu_msr(c); } -void __cpuinit print_cpu_msr(struct cpuinfo_x86 *c) +void print_cpu_msr(struct cpuinfo_x86 *c) { if (c->cpu_index < show_msr) __print_cpu_msr(); @@ -1122,7 +1122,7 @@ DEFINE_PER_CPU_ALIGNED(struct stack_canary, stack_canary); #endif /* Make sure %fs and %gs are initialized properly in idle threads */ -struct pt_regs * __cpuinit idle_regs(struct pt_regs *regs) +struct pt_regs * idle_regs(struct pt_regs *regs) { memset(regs, 0, sizeof(struct pt_regs)); regs->fs = __KERNEL_PERCPU; @@ -1171,7 +1171,7 @@ static void dbg_restore_debug_regs(void) */ #ifdef CONFIG_X86_64 -void __cpuinit cpu_init(void) +void cpu_init(void) { struct orig_ist *oist; struct task_struct *me; @@ -1268,7 +1268,7 @@ void __cpuinit cpu_init(void) #else -void __cpuinit cpu_init(void) +void cpu_init(void) { int cpu = smp_processor_id(); struct task_struct *curr = current; diff --git a/arch/x86/kernel/cpu/cyrix.c b/arch/x86/kernel/cpu/cyrix.c index 4fbd384fb64..af33c4eee3a 100644 --- a/arch/x86/kernel/cpu/cyrix.c +++ b/arch/x86/kernel/cpu/cyrix.c @@ -15,7 +15,7 @@ /* * Read NSC/Cyrix DEVID registers (DIR) to get more detailed info. about the CPU */ -static void __cpuinit __do_cyrix_devid(unsigned char *dir0, unsigned char *dir1) +static void __do_cyrix_devid(unsigned char *dir0, unsigned char *dir1) { unsigned char ccr2, ccr3; @@ -44,7 +44,7 @@ static void __cpuinit __do_cyrix_devid(unsigned char *dir0, unsigned char *dir1) } } -static void __cpuinit do_cyrix_devid(unsigned char *dir0, unsigned char *dir1) +static void do_cyrix_devid(unsigned char *dir0, unsigned char *dir1) { unsigned long flags; @@ -59,25 +59,25 @@ static void __cpuinit do_cyrix_devid(unsigned char *dir0, unsigned char *dir1) * Actually since bugs.h doesn't even reference this perhaps someone should * fix the documentation ??? */ -static unsigned char Cx86_dir0_msb __cpuinitdata = 0; +static unsigned char Cx86_dir0_msb = 0; -static const char __cpuinitconst Cx86_model[][9] = { +static const char Cx86_model[][9] = { "Cx486", "Cx486", "5x86 ", "6x86", "MediaGX ", "6x86MX ", "M II ", "Unknown" }; -static const char __cpuinitconst Cx486_name[][5] = { +static const char Cx486_name[][5] = { "SLC", "DLC", "SLC2", "DLC2", "SRx", "DRx", "SRx2", "DRx2" }; -static const char __cpuinitconst Cx486S_name[][4] = { +static const char Cx486S_name[][4] = { "S", "S2", "Se", "S2e" }; -static const char __cpuinitconst Cx486D_name[][4] = { +static const char Cx486D_name[][4] = { "DX", "DX2", "?", "?", "?", "DX4" }; -static char Cx86_cb[] __cpuinitdata = "?.5x Core/Bus Clock"; -static const char __cpuinitconst cyrix_model_mult1[] = "12??43"; -static const char __cpuinitconst cyrix_model_mult2[] = "12233445"; +static char Cx86_cb[] = "?.5x Core/Bus Clock"; +static const char cyrix_model_mult1[] = "12??43"; +static const char cyrix_model_mult2[] = "12233445"; /* * Reset the slow-loop (SLOP) bit on the 686(L) which is set by some old @@ -87,7 +87,7 @@ static const char __cpuinitconst cyrix_model_mult2[] = "12233445"; * FIXME: our newer udelay uses the tsc. We don't need to frob with SLOP */ -static void __cpuinit check_cx686_slop(struct cpuinfo_x86 *c) +static void check_cx686_slop(struct cpuinfo_x86 *c) { unsigned long flags; @@ -112,7 +112,7 @@ static void __cpuinit check_cx686_slop(struct cpuinfo_x86 *c) } -static void __cpuinit set_cx86_reorder(void) +static void set_cx86_reorder(void) { u8 ccr3; @@ -127,7 +127,7 @@ static void __cpuinit set_cx86_reorder(void) setCx86(CX86_CCR3, ccr3); } -static void __cpuinit set_cx86_memwb(void) +static void set_cx86_memwb(void) { printk(KERN_INFO "Enable Memory-Write-back mode on Cyrix/NSC processor.\n"); @@ -143,7 +143,7 @@ static void __cpuinit set_cx86_memwb(void) * Configure later MediaGX and/or Geode processor. */ -static void __cpuinit geode_configure(void) +static void geode_configure(void) { unsigned long flags; u8 ccr3; @@ -166,7 +166,7 @@ static void __cpuinit geode_configure(void) local_irq_restore(flags); } -static void __cpuinit early_init_cyrix(struct cpuinfo_x86 *c) +static void early_init_cyrix(struct cpuinfo_x86 *c) { unsigned char dir0, dir0_msn, dir1 = 0; @@ -185,7 +185,7 @@ static void __cpuinit early_init_cyrix(struct cpuinfo_x86 *c) } } -static void __cpuinit init_cyrix(struct cpuinfo_x86 *c) +static void init_cyrix(struct cpuinfo_x86 *c) { unsigned char dir0, dir0_msn, dir0_lsn, dir1 = 0; char *buf = c->x86_model_id; @@ -355,7 +355,7 @@ static void __cpuinit init_cyrix(struct cpuinfo_x86 *c) /* * Handle National Semiconductor branded processors */ -static void __cpuinit init_nsc(struct cpuinfo_x86 *c) +static void init_nsc(struct cpuinfo_x86 *c) { /* * There may be GX1 processors in the wild that are branded @@ -404,7 +404,7 @@ static inline int test_cyrix_52div(void) return (unsigned char) (test >> 8) == 0x02; } -static void __cpuinit cyrix_identify(struct cpuinfo_x86 *c) +static void cyrix_identify(struct cpuinfo_x86 *c) { /* Detect Cyrix with disabled CPUID */ if (c->x86 == 4 && test_cyrix_52div()) { @@ -440,7 +440,7 @@ static void __cpuinit cyrix_identify(struct cpuinfo_x86 *c) } } -static const struct cpu_dev __cpuinitconst cyrix_cpu_dev = { +static const struct cpu_dev cyrix_cpu_dev = { .c_vendor = "Cyrix", .c_ident = { "CyrixInstead" }, .c_early_init = early_init_cyrix, @@ -451,7 +451,7 @@ static const struct cpu_dev __cpuinitconst cyrix_cpu_dev = { cpu_dev_register(cyrix_cpu_dev); -static const struct cpu_dev __cpuinitconst nsc_cpu_dev = { +static const struct cpu_dev nsc_cpu_dev = { .c_vendor = "NSC", .c_ident = { "Geode by NSC" }, .c_init = init_nsc, diff --git a/arch/x86/kernel/cpu/hypervisor.c b/arch/x86/kernel/cpu/hypervisor.c index 755f64fb074..e0000119938 100644 --- a/arch/x86/kernel/cpu/hypervisor.c +++ b/arch/x86/kernel/cpu/hypervisor.c @@ -57,7 +57,7 @@ detect_hypervisor_vendor(void) } } -void __cpuinit init_hypervisor(struct cpuinfo_x86 *c) +void init_hypervisor(struct cpuinfo_x86 *c) { if (x86_hyper && x86_hyper->set_cpu_features) x86_hyper->set_cpu_features(c); diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c index 3e6ff6cbf42..0474e62912c 100644 --- a/arch/x86/kernel/cpu/intel.c +++ b/arch/x86/kernel/cpu/intel.c @@ -27,7 +27,7 @@ #include #endif -static void __cpuinit early_init_intel(struct cpuinfo_x86 *c) +static void early_init_intel(struct cpuinfo_x86 *c) { u64 misc_enable; @@ -152,7 +152,7 @@ static void __cpuinit early_init_intel(struct cpuinfo_x86 *c) * This is called before we do cpu ident work */ -int __cpuinit ppro_with_ram_bug(void) +int ppro_with_ram_bug(void) { /* Uses data from early_cpu_detect now */ if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL && @@ -166,7 +166,7 @@ int __cpuinit ppro_with_ram_bug(void) } #ifdef CONFIG_X86_F00F_BUG -static void __cpuinit trap_init_f00f_bug(void) +static void trap_init_f00f_bug(void) { __set_fixmap(FIX_F00F_IDT, __pa(&idt_table), PAGE_KERNEL_RO); @@ -179,7 +179,7 @@ static void __cpuinit trap_init_f00f_bug(void) } #endif -static void __cpuinit intel_smp_check(struct cpuinfo_x86 *c) +static void intel_smp_check(struct cpuinfo_x86 *c) { /* calling is from identify_secondary_cpu() ? */ if (!c->cpu_index) @@ -199,7 +199,7 @@ static void __cpuinit intel_smp_check(struct cpuinfo_x86 *c) } } -static void __cpuinit intel_workarounds(struct cpuinfo_x86 *c) +static void intel_workarounds(struct cpuinfo_x86 *c) { unsigned long lo, hi; @@ -280,12 +280,12 @@ static void __cpuinit intel_workarounds(struct cpuinfo_x86 *c) intel_smp_check(c); } #else -static void __cpuinit intel_workarounds(struct cpuinfo_x86 *c) +static void intel_workarounds(struct cpuinfo_x86 *c) { } #endif -static void __cpuinit srat_detect_node(struct cpuinfo_x86 *c) +static void srat_detect_node(struct cpuinfo_x86 *c) { #ifdef CONFIG_NUMA unsigned node; @@ -305,7 +305,7 @@ static void __cpuinit srat_detect_node(struct cpuinfo_x86 *c) /* * find out the number of processor cores on the die */ -static int __cpuinit intel_num_cpu_cores(struct cpuinfo_x86 *c) +static int intel_num_cpu_cores(struct cpuinfo_x86 *c) { unsigned int eax, ebx, ecx, edx; @@ -320,7 +320,7 @@ static int __cpuinit intel_num_cpu_cores(struct cpuinfo_x86 *c) return 1; } -static void __cpuinit detect_vmx_virtcap(struct cpuinfo_x86 *c) +static void detect_vmx_virtcap(struct cpuinfo_x86 *c) { /* Intel VMX MSR indicated features */ #define X86_VMX_FEATURE_PROC_CTLS_TPR_SHADOW 0x00200000 @@ -358,7 +358,7 @@ static void __cpuinit detect_vmx_virtcap(struct cpuinfo_x86 *c) } } -static void __cpuinit init_intel(struct cpuinfo_x86 *c) +static void init_intel(struct cpuinfo_x86 *c) { unsigned int l2 = 0; @@ -477,7 +477,7 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c) } #ifdef CONFIG_X86_32 -static unsigned int __cpuinit intel_size_cache(struct cpuinfo_x86 *c, unsigned int size) +static unsigned int intel_size_cache(struct cpuinfo_x86 *c, unsigned int size) { /* * Intel PIII Tualatin. This comes in two flavours. @@ -491,7 +491,7 @@ static unsigned int __cpuinit intel_size_cache(struct cpuinfo_x86 *c, unsigned i } #endif -static const struct cpu_dev __cpuinitconst intel_cpu_dev = { +static const struct cpu_dev intel_cpu_dev = { .c_vendor = "Intel", .c_ident = { "GenuineIntel" }, #ifdef CONFIG_X86_32 diff --git a/arch/x86/kernel/cpu/intel_cacheinfo.c b/arch/x86/kernel/cpu/intel_cacheinfo.c index b8f3653dddb..687e62b367e 100644 --- a/arch/x86/kernel/cpu/intel_cacheinfo.c +++ b/arch/x86/kernel/cpu/intel_cacheinfo.c @@ -37,7 +37,7 @@ struct _cache_table { /* All the cache descriptor types we care about (no TLB or trace cache entries) */ -static const struct _cache_table __cpuinitconst cache_table[] = +static const struct _cache_table cache_table[] = { { 0x06, LVL_1_INST, 8 }, /* 4-way set assoc, 32 byte line size */ { 0x08, LVL_1_INST, 16 }, /* 4-way set assoc, 32 byte line size */ @@ -203,7 +203,7 @@ union l3_cache { unsigned val; }; -static const unsigned short __cpuinitconst assocs[] = { +static const unsigned short assocs[] = { [1] = 1, [2] = 2, [4] = 4, @@ -217,10 +217,10 @@ static const unsigned short __cpuinitconst assocs[] = { [0xf] = 0xffff /* fully associative - no way to show this currently */ }; -static const unsigned char __cpuinitconst levels[] = { 1, 1, 2, 3 }; -static const unsigned char __cpuinitconst types[] = { 1, 2, 3, 3 }; +static const unsigned char levels[] = { 1, 1, 2, 3 }; +static const unsigned char types[] = { 1, 2, 3, 3 }; -static void __cpuinit +static void amd_cpuid4(int leaf, union _cpuid4_leaf_eax *eax, union _cpuid4_leaf_ebx *ebx, union _cpuid4_leaf_ecx *ecx) @@ -303,7 +303,7 @@ struct _cache_attr { /* * L3 cache descriptors */ -static void __cpuinit amd_calc_l3_indices(struct amd_northbridge *nb) +static void amd_calc_l3_indices(struct amd_northbridge *nb) { struct amd_l3_cache *l3 = &nb->l3_cache; unsigned int sc0, sc1, sc2, sc3; @@ -326,7 +326,7 @@ static void __cpuinit amd_calc_l3_indices(struct amd_northbridge *nb) l3->indices = (max(max3(sc0, sc1, sc2), sc3) << 10) - 1; } -static void __cpuinit amd_init_l3_cache(struct _cpuid4_info_regs *this_leaf, int index) +static void amd_init_l3_cache(struct _cpuid4_info_regs *this_leaf, int index) { int node; @@ -529,7 +529,7 @@ static struct _cache_attr subcaches = #endif /* CONFIG_AMD_NB */ static int -__cpuinit cpuid4_cache_lookup_regs(int index, +cpuid4_cache_lookup_regs(int index, struct _cpuid4_info_regs *this_leaf) { union _cpuid4_leaf_eax eax; @@ -557,7 +557,7 @@ __cpuinit cpuid4_cache_lookup_regs(int index, return 0; } -static int __cpuinit find_num_cache_leaves(void) +static int find_num_cache_leaves(void) { unsigned int eax, ebx, ecx, edx; union _cpuid4_leaf_eax cache_eax; @@ -572,7 +572,7 @@ static int __cpuinit find_num_cache_leaves(void) return i; } -unsigned int __cpuinit init_intel_cacheinfo(struct cpuinfo_x86 *c) +unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c) { /* Cache sizes */ unsigned int trace = 0, l1i = 0, l1d = 0, l2 = 0, l3 = 0; @@ -725,7 +725,7 @@ static DEFINE_PER_CPU(struct _cpuid4_info *, ici_cpuid4_info); #ifdef CONFIG_SMP -static int __cpuinit cache_shared_amd_cpu_map_setup(unsigned int cpu, int index) +static int cache_shared_amd_cpu_map_setup(unsigned int cpu, int index) { struct _cpuid4_info *this_leaf; int ret, i, sibling; @@ -761,7 +761,7 @@ static int __cpuinit cache_shared_amd_cpu_map_setup(unsigned int cpu, int index) return ret; } -static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index) +static void cache_shared_cpu_map_setup(unsigned int cpu, int index) { struct _cpuid4_info *this_leaf, *sibling_leaf; unsigned long num_threads_sharing; @@ -796,7 +796,7 @@ static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index) } } } -static void __cpuinit cache_remove_shared_cpu_map(unsigned int cpu, int index) +static void cache_remove_shared_cpu_map(unsigned int cpu, int index) { struct _cpuid4_info *this_leaf, *sibling_leaf; int sibling; @@ -809,16 +809,16 @@ static void __cpuinit cache_remove_shared_cpu_map(unsigned int cpu, int index) } } #else -static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, int index) +static void cache_shared_cpu_map_setup(unsigned int cpu, int index) { } -static void __cpuinit cache_remove_shared_cpu_map(unsigned int cpu, int index) +static void cache_remove_shared_cpu_map(unsigned int cpu, int index) { } #endif -static void __cpuinit free_cache_attributes(unsigned int cpu) +static void free_cache_attributes(unsigned int cpu) { int i; @@ -829,7 +829,7 @@ static void __cpuinit free_cache_attributes(unsigned int cpu) per_cpu(ici_cpuid4_info, cpu) = NULL; } -static void __cpuinit get_cpu_leaves(void *_retval) +static void get_cpu_leaves(void *_retval) { int j, *retval = _retval, cpu = smp_processor_id(); @@ -849,7 +849,7 @@ static void __cpuinit get_cpu_leaves(void *_retval) } } -static int __cpuinit detect_cache_attributes(unsigned int cpu) +static int detect_cache_attributes(unsigned int cpu) { int retval; @@ -983,7 +983,7 @@ static struct attribute *default_attrs[] = { }; #ifdef CONFIG_AMD_NB -static struct attribute ** __cpuinit amd_l3_attrs(void) +static struct attribute ** amd_l3_attrs(void) { static struct attribute **attrs; int n; @@ -1059,7 +1059,7 @@ static struct kobj_type ktype_percpu_entry = { .sysfs_ops = &sysfs_ops, }; -static void __cpuinit cpuid4_cache_sysfs_exit(unsigned int cpu) +static void cpuid4_cache_sysfs_exit(unsigned int cpu) { kfree(per_cpu(ici_cache_kobject, cpu)); kfree(per_cpu(ici_index_kobject, cpu)); @@ -1068,7 +1068,7 @@ static void __cpuinit cpuid4_cache_sysfs_exit(unsigned int cpu) free_cache_attributes(cpu); } -static int __cpuinit cpuid4_cache_sysfs_init(unsigned int cpu) +static int cpuid4_cache_sysfs_init(unsigned int cpu) { int err; @@ -1100,7 +1100,7 @@ static int __cpuinit cpuid4_cache_sysfs_init(unsigned int cpu) static DECLARE_BITMAP(cache_dev_map, NR_CPUS); /* Add/Remove cache interface for CPU device */ -static int __cpuinit cache_add_dev(struct device *dev) +static int cache_add_dev(struct device *dev) { unsigned int cpu = dev->id; unsigned long i, j; @@ -1151,7 +1151,7 @@ static int __cpuinit cache_add_dev(struct device *dev) return 0; } -static void __cpuinit cache_remove_dev(struct device *dev) +static void cache_remove_dev(struct device *dev) { unsigned int cpu = dev->id; unsigned long i; @@ -1168,7 +1168,7 @@ static void __cpuinit cache_remove_dev(struct device *dev) cpuid4_cache_sysfs_exit(cpu); } -static int __cpuinit cacheinfo_cpu_callback(struct notifier_block *nfb, +static int cacheinfo_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { unsigned int cpu = (unsigned long)hcpu; @@ -1188,11 +1188,11 @@ static int __cpuinit cacheinfo_cpu_callback(struct notifier_block *nfb, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata cacheinfo_cpu_notifier = { +static struct notifier_block cacheinfo_cpu_notifier = { .notifier_call = cacheinfo_cpu_callback, }; -static int __cpuinit cache_sysfs_init(void) +static int cache_sysfs_init(void) { int i; diff --git a/arch/x86/kernel/cpu/mcheck/mce-severity.c b/arch/x86/kernel/cpu/mcheck/mce-severity.c index 0c82091b165..1ccd453903d 100644 --- a/arch/x86/kernel/cpu/mcheck/mce-severity.c +++ b/arch/x86/kernel/cpu/mcheck/mce-severity.c @@ -165,15 +165,19 @@ static struct severity { }; /* - * If the EIPV bit is set, it means the saved IP is the - * instruction which caused the MCE. + * If mcgstatus indicated that ip/cs on the stack were + * no good, then "m->cs" will be zero and we will have + * to assume the worst case (IN_KERNEL) as we actually + * have no idea what we were executing when the machine + * check hit. + * If we do have a good "m->cs" (or a faked one in the + * case we were executing in VM86 mode) we can use it to + * distinguish an exception taken in user from from one + * taken in the kernel. */ static int error_context(struct mce *m) { - if (m->mcgstatus & MCG_STATUS_EIPV) - return (m->ip && (m->cs & 3) == 3) ? IN_USER : IN_KERNEL; - /* Unknown, assume kernel */ - return IN_KERNEL; + return ((m->cs & 3) == 3) ? IN_USER : IN_KERNEL; } int mce_severity(struct mce *m, int tolerant, char **msg) diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index 11c9166c333..6640374cdcc 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c @@ -437,6 +437,14 @@ static inline void mce_gather_info(struct mce *m, struct pt_regs *regs) if (m->mcgstatus & (MCG_STATUS_RIPV|MCG_STATUS_EIPV)) { m->ip = regs->ip; m->cs = regs->cs; + + /* + * When in VM86 mode make the cs look like ring 3 + * always. This is a lie, but it's better than passing + * the additional vm86 bit around everywhere. + */ + if (v8086_mode(regs)) + m->cs |= 3; } /* Use accurate RIP reporting if available. */ if (rip_msr) @@ -1315,7 +1323,7 @@ int mce_notify_irq(void) } EXPORT_SYMBOL_GPL(mce_notify_irq); -static int __cpuinit __mcheck_cpu_mce_banks_init(void) +static int __mcheck_cpu_mce_banks_init(void) { int i; @@ -1334,7 +1342,7 @@ static int __cpuinit __mcheck_cpu_mce_banks_init(void) /* * Initialize Machine Checks for a CPU. */ -static int __cpuinit __mcheck_cpu_cap_init(void) +static int __mcheck_cpu_cap_init(void) { unsigned b; u64 cap; @@ -1401,7 +1409,7 @@ static void __mcheck_cpu_init_generic(void) } /* Add per CPU specific workarounds here */ -static int __cpuinit __mcheck_cpu_apply_quirks(struct cpuinfo_x86 *c) +static int __mcheck_cpu_apply_quirks(struct cpuinfo_x86 *c) { if (c->x86_vendor == X86_VENDOR_UNKNOWN) { pr_info("MCE: unknown CPU type - not enabling MCE support.\n"); @@ -1469,7 +1477,7 @@ static int __cpuinit __mcheck_cpu_apply_quirks(struct cpuinfo_x86 *c) return 0; } -static int __cpuinit __mcheck_cpu_ancient_init(struct cpuinfo_x86 *c) +static int __mcheck_cpu_ancient_init(struct cpuinfo_x86 *c) { if (c->x86 != 5) return 0; @@ -1534,7 +1542,7 @@ void (*machine_check_vector)(struct pt_regs *, long error_code) = * Called for each booted CPU to set up machine checks. * Must be called with preempt off: */ -void __cpuinit mcheck_cpu_init(struct cpuinfo_x86 *c) +void mcheck_cpu_init(struct cpuinfo_x86 *c) { if (mce_disabled) return; @@ -1948,7 +1956,6 @@ static struct bus_type mce_subsys = { DEFINE_PER_CPU(struct device *, mce_device); -__cpuinitdata void (*threshold_cpu_callback)(unsigned long action, unsigned int cpu); static inline struct mce_bank *attr_to_bank(struct device_attribute *attr) @@ -2094,7 +2101,7 @@ static void mce_device_release(struct device *dev) } /* Per cpu device init. All of the cpus still share the same ctrl bank: */ -static __cpuinit int mce_device_create(unsigned int cpu) +static int mce_device_create(unsigned int cpu) { struct device *dev; int err; @@ -2140,7 +2147,7 @@ static __cpuinit int mce_device_create(unsigned int cpu) return err; } -static __cpuinit void mce_device_remove(unsigned int cpu) +static void mce_device_remove(unsigned int cpu) { struct device *dev = per_cpu(mce_device, cpu); int i; @@ -2160,7 +2167,7 @@ static __cpuinit void mce_device_remove(unsigned int cpu) } /* Make sure there are no machine checks on offlined CPUs. */ -static void __cpuinit mce_disable_cpu(void *h) +static void mce_disable_cpu(void *h) { unsigned long action = *(unsigned long *)h; int i; @@ -2178,7 +2185,7 @@ static void __cpuinit mce_disable_cpu(void *h) } } -static void __cpuinit mce_reenable_cpu(void *h) +static void mce_reenable_cpu(void *h) { unsigned long action = *(unsigned long *)h; int i; @@ -2197,7 +2204,7 @@ static void __cpuinit mce_reenable_cpu(void *h) } /* Get notified when a cpu comes on/off. Be hotplug friendly. */ -static int __cpuinit +static int mce_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { unsigned int cpu = (unsigned long)hcpu; @@ -2238,7 +2245,7 @@ mce_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) return NOTIFY_OK; } -static struct notifier_block mce_cpu_notifier __cpuinitdata = { +static struct notifier_block mce_cpu_notifier = { .notifier_call = mce_cpu_callback, }; diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c index 99b57179f91..25785f7d1ce 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_amd.c +++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c @@ -432,7 +432,7 @@ static struct kobj_type threshold_ktype = { .default_attrs = default_attrs, }; -static __cpuinit int allocate_threshold_blocks(unsigned int cpu, +static int allocate_threshold_blocks(unsigned int cpu, unsigned int bank, unsigned int block, u32 address) @@ -511,7 +511,7 @@ static __cpuinit int allocate_threshold_blocks(unsigned int cpu, return err; } -static __cpuinit long +static long local_allocate_threshold_blocks(int cpu, unsigned int bank) { return allocate_threshold_blocks(cpu, bank, 0, @@ -519,7 +519,7 @@ local_allocate_threshold_blocks(int cpu, unsigned int bank) } /* symlinks sibling shared banks to first core. first core owns dir/files. */ -static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank) +static int threshold_create_bank(unsigned int cpu, unsigned int bank) { int i, err = 0; struct threshold_bank *b = NULL; @@ -607,7 +607,7 @@ static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank) } /* create dir/files for all valid threshold banks */ -static __cpuinit int threshold_create_device(unsigned int cpu) +static int threshold_create_device(unsigned int cpu) { unsigned int bank; int err = 0; @@ -708,7 +708,7 @@ static void threshold_remove_device(unsigned int cpu) } /* get notified when a cpu comes on/off */ -static void __cpuinit +static void amd_64_threshold_cpu_callback(unsigned long action, unsigned int cpu) { switch (action) { diff --git a/arch/x86/kernel/cpu/mcheck/therm_throt.c b/arch/x86/kernel/cpu/mcheck/therm_throt.c index 47a1870279a..7b7e8fdd771 100644 --- a/arch/x86/kernel/cpu/mcheck/therm_throt.c +++ b/arch/x86/kernel/cpu/mcheck/therm_throt.c @@ -221,7 +221,7 @@ static int thresh_event_valid(int event) #ifdef CONFIG_SYSFS /* Add/Remove thermal_throttle interface for CPU device: */ -static __cpuinit int thermal_throttle_add_dev(struct device *dev, +static int thermal_throttle_add_dev(struct device *dev, unsigned int cpu) { int err; @@ -248,7 +248,7 @@ static __cpuinit int thermal_throttle_add_dev(struct device *dev, return err; } -static __cpuinit void thermal_throttle_remove_dev(struct device *dev) +static void thermal_throttle_remove_dev(struct device *dev) { sysfs_remove_group(&dev->kobj, &thermal_attr_group); } @@ -257,7 +257,7 @@ static __cpuinit void thermal_throttle_remove_dev(struct device *dev) static DEFINE_MUTEX(therm_cpu_lock); /* Get notified when a cpu comes on/off. Be hotplug friendly. */ -static __cpuinit int +static int thermal_throttle_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) @@ -288,7 +288,7 @@ thermal_throttle_cpu_callback(struct notifier_block *nfb, return notifier_from_errno(err); } -static struct notifier_block thermal_throttle_cpu_notifier __cpuinitdata = +static struct notifier_block thermal_throttle_cpu_notifier = { .notifier_call = thermal_throttle_cpu_callback, }; diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index bb8e03407e1..6df73209461 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c @@ -1260,7 +1260,7 @@ perf_event_nmi_handler(unsigned int cmd, struct pt_regs *regs) struct event_constraint emptyconstraint; struct event_constraint unconstrained; -static int __cpuinit +static int x86_pmu_notifier(struct notifier_block *self, unsigned long action, void *hcpu) { unsigned int cpu = (long)hcpu; diff --git a/arch/x86/kernel/cpu/perf_event_amd.c b/arch/x86/kernel/cpu/perf_event_amd.c index 95e7fe1c5f0..9edc786aef8 100644 --- a/arch/x86/kernel/cpu/perf_event_amd.c +++ b/arch/x86/kernel/cpu/perf_event_amd.c @@ -493,6 +493,7 @@ static __initconst const struct x86_pmu amd_pmu = { * 0x023 DE PERF_CTL[2:0] * 0x02D LS PERF_CTL[3] * 0x02E LS PERF_CTL[3,0] + * 0x031 LS PERF_CTL[2:0] (**) * 0x043 CU PERF_CTL[2:0] * 0x045 CU PERF_CTL[2:0] * 0x046 CU PERF_CTL[2:0] @@ -506,10 +507,12 @@ static __initconst const struct x86_pmu amd_pmu = { * 0x0DD LS PERF_CTL[5:0] * 0x0DE LS PERF_CTL[5:0] * 0x0DF LS PERF_CTL[5:0] + * 0x1C0 EX PERF_CTL[5:3] * 0x1D6 EX PERF_CTL[5:0] * 0x1D8 EX PERF_CTL[5:0] * - * (*) depending on the umask all FPU counters may be used + * (*) depending on the umask all FPU counters may be used + * (**) only one unitmask enabled at a time */ static struct event_constraint amd_f15_PMC0 = EVENT_CONSTRAINT(0, 0x01, 0); @@ -559,6 +562,12 @@ amd_get_event_constraints_f15h(struct cpu_hw_events *cpuc, struct perf_event *ev return &amd_f15_PMC3; case 0x02E: return &amd_f15_PMC30; + case 0x031: + if (hweight_long(hwc->config & ARCH_PERFMON_EVENTSEL_UMASK) <= 1) + return &amd_f15_PMC20; + return &emptyconstraint; + case 0x1C0: + return &amd_f15_PMC53; default: return &amd_f15_PMC50; } diff --git a/arch/x86/kernel/cpu/perf_event_amd_ibs.c b/arch/x86/kernel/cpu/perf_event_amd_ibs.c index 3b8a2d30d14..522de7e068e 100644 --- a/arch/x86/kernel/cpu/perf_event_amd_ibs.c +++ b/arch/x86/kernel/cpu/perf_event_amd_ibs.c @@ -244,7 +244,7 @@ static void clear_APIC_ibs(void *dummy) setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_FIX, 1); } -static int __cpuinit +static int perf_ibs_cpu_notifier(struct notifier_block *self, unsigned long action, void *hcpu) { switch (action & ~CPU_TASKS_FROZEN) { diff --git a/arch/x86/kernel/cpu/rdrand.c b/arch/x86/kernel/cpu/rdrand.c index feca286c2bb..88db010845c 100644 --- a/arch/x86/kernel/cpu/rdrand.c +++ b/arch/x86/kernel/cpu/rdrand.c @@ -52,7 +52,7 @@ static inline int rdrand_long(unsigned long *v) */ #define RESEED_LOOP ((512*128)/sizeof(unsigned long)) -void __cpuinit x86_init_rdrand(struct cpuinfo_x86 *c) +void x86_init_rdrand(struct cpuinfo_x86 *c) { #ifdef CONFIG_ARCH_RANDOM unsigned long tmp; diff --git a/arch/x86/kernel/cpu/scattered.c b/arch/x86/kernel/cpu/scattered.c index addf9e82a7f..354c4e024da 100644 --- a/arch/x86/kernel/cpu/scattered.c +++ b/arch/x86/kernel/cpu/scattered.c @@ -24,13 +24,13 @@ enum cpuid_regs { CR_EBX }; -void __cpuinit init_scattered_cpuid_features(struct cpuinfo_x86 *c) +void init_scattered_cpuid_features(struct cpuinfo_x86 *c) { u32 max_level; u32 regs[4]; const struct cpuid_bit *cb; - static const struct cpuid_bit __cpuinitconst cpuid_bits[] = { + static const struct cpuid_bit cpuid_bits[] = { { X86_FEATURE_DTS, CR_EAX, 0, 0x00000006, 0 }, { X86_FEATURE_IDA, CR_EAX, 1, 0x00000006, 0 }, { X86_FEATURE_ARAT, CR_EAX, 2, 0x00000006, 0 }, diff --git a/arch/x86/kernel/cpu/topology.c b/arch/x86/kernel/cpu/topology.c index 4397e987a1c..4c60eaf0571 100644 --- a/arch/x86/kernel/cpu/topology.c +++ b/arch/x86/kernel/cpu/topology.c @@ -26,7 +26,7 @@ * exists, use it for populating initial_apicid and cpu topology * detection. */ -void __cpuinit detect_extended_topology(struct cpuinfo_x86 *c) +void detect_extended_topology(struct cpuinfo_x86 *c) { #ifdef CONFIG_SMP unsigned int eax, ebx, ecx, edx, sub_index; diff --git a/arch/x86/kernel/cpu/transmeta.c b/arch/x86/kernel/cpu/transmeta.c index 28000743bbb..aa0430d69b9 100644 --- a/arch/x86/kernel/cpu/transmeta.c +++ b/arch/x86/kernel/cpu/transmeta.c @@ -5,7 +5,7 @@ #include #include "cpu.h" -static void __cpuinit early_init_transmeta(struct cpuinfo_x86 *c) +static void early_init_transmeta(struct cpuinfo_x86 *c) { u32 xlvl; @@ -17,7 +17,7 @@ static void __cpuinit early_init_transmeta(struct cpuinfo_x86 *c) } } -static void __cpuinit init_transmeta(struct cpuinfo_x86 *c) +static void init_transmeta(struct cpuinfo_x86 *c) { unsigned int cap_mask, uk, max, dummy; unsigned int cms_rev1, cms_rev2; @@ -98,7 +98,7 @@ static void __cpuinit init_transmeta(struct cpuinfo_x86 *c) #endif } -static const struct cpu_dev __cpuinitconst transmeta_cpu_dev = { +static const struct cpu_dev transmeta_cpu_dev = { .c_vendor = "Transmeta", .c_ident = { "GenuineTMx86", "TransmetaCPU" }, .c_early_init = early_init_transmeta, diff --git a/arch/x86/kernel/cpu/umc.c b/arch/x86/kernel/cpu/umc.c index fd2c37bf7ac..202759a1412 100644 --- a/arch/x86/kernel/cpu/umc.c +++ b/arch/x86/kernel/cpu/umc.c @@ -8,7 +8,7 @@ * so no special init takes place. */ -static const struct cpu_dev __cpuinitconst umc_cpu_dev = { +static const struct cpu_dev umc_cpu_dev = { .c_vendor = "UMC", .c_ident = { "UMC UMC UMC" }, .c_models = { diff --git a/arch/x86/kernel/cpu/vmware.c b/arch/x86/kernel/cpu/vmware.c index d22d0c4edcf..676c0cbb79f 100644 --- a/arch/x86/kernel/cpu/vmware.c +++ b/arch/x86/kernel/cpu/vmware.c @@ -119,7 +119,7 @@ static bool __init vmware_platform(void) * so that the kernel could just trust the hypervisor with providing a * reliable virtual TSC that is suitable for timekeeping. */ -static void __cpuinit vmware_set_cpu_features(struct cpuinfo_x86 *c) +static void vmware_set_cpu_features(struct cpuinfo_x86 *c) { set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC); set_cpu_cap(c, X86_FEATURE_TSC_RELIABLE); diff --git a/arch/x86/kernel/cpuid.c b/arch/x86/kernel/cpuid.c index 39472dd2323..e051e8b328e 100644 --- a/arch/x86/kernel/cpuid.c +++ b/arch/x86/kernel/cpuid.c @@ -137,7 +137,7 @@ static const struct file_operations cpuid_fops = { .open = cpuid_open, }; -static __cpuinit int cpuid_device_create(int cpu) +static int cpuid_device_create(int cpu) { struct device *dev; @@ -151,7 +151,7 @@ static void cpuid_device_destroy(int cpu) device_destroy(cpuid_class, MKDEV(CPUID_MAJOR, cpu)); } -static int __cpuinit cpuid_class_cpu_callback(struct notifier_block *nfb, +static int cpuid_class_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c index 3ae2ced4a87..d8df45dd77b 100644 --- a/arch/x86/kernel/devicetree.c +++ b/arch/x86/kernel/devicetree.c @@ -133,7 +133,7 @@ static void x86_of_pci_irq_disable(struct pci_dev *dev) { } -void __cpuinit x86_of_pci_init(void) +void x86_of_pci_init(void) { pcibios_enable_irq = x86_of_pci_irq_enable; pcibios_disable_irq = x86_of_pci_irq_disable; diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c index 2d6e6498c17..95bc326863e 100644 --- a/arch/x86/kernel/i387.c +++ b/arch/x86/kernel/i387.c @@ -123,9 +123,9 @@ static unsigned int mxcsr_feature_mask __read_mostly = 0xffffffffu; unsigned int xstate_size; EXPORT_SYMBOL_GPL(xstate_size); unsigned int sig_xstate_ia32_size = sizeof(struct _fpstate_ia32); -static struct i387_fxsave_struct fx_scratch __cpuinitdata; +static struct i387_fxsave_struct fx_scratch; -static void __cpuinit mxcsr_feature_mask_init(void) +static void mxcsr_feature_mask_init(void) { unsigned long mask = 0; @@ -141,7 +141,7 @@ static void __cpuinit mxcsr_feature_mask_init(void) stts(); } -static void __cpuinit init_thread_xstate(void) +static void init_thread_xstate(void) { /* * Note that xstate_size might be overwriten later during @@ -170,7 +170,7 @@ static void __cpuinit init_thread_xstate(void) * into all processes. */ -void __cpuinit fpu_init(void) +void fpu_init(void) { unsigned long cr0; unsigned long cr4_mask = 0; diff --git a/arch/x86/kernel/irq_32.c b/arch/x86/kernel/irq_32.c index 58b7f27cb3e..64fab518144 100644 --- a/arch/x86/kernel/irq_32.c +++ b/arch/x86/kernel/irq_32.c @@ -119,7 +119,7 @@ execute_on_irq_stack(int overflow, struct irq_desc *desc, int irq) /* * allocate per-cpu stacks for hardirq and for softirq processing */ -void __cpuinit irq_ctx_init(int cpu) +void irq_ctx_init(int cpu) { union irq_ctx *irqctx; diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c index e554e5ad2fe..4ec4605f7bb 100644 --- a/arch/x86/kernel/kvm.c +++ b/arch/x86/kernel/kvm.c @@ -283,7 +283,7 @@ static void kvm_register_steal_time(void) cpu, __pa(st)); } -void __cpuinit kvm_guest_cpu_init(void) +void kvm_guest_cpu_init(void) { if (!kvm_para_available()) return; @@ -363,7 +363,7 @@ static void __init kvm_smp_prepare_boot_cpu(void) native_smp_prepare_boot_cpu(); } -static void __cpuinit kvm_guest_cpu_online(void *dummy) +static void kvm_guest_cpu_online(void *dummy) { kvm_guest_cpu_init(); } @@ -375,7 +375,7 @@ static void kvm_guest_cpu_offline(void *dummy) apf_task_wake_all(); } -static int __cpuinit kvm_cpu_notify(struct notifier_block *self, +static int kvm_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) { int cpu = (unsigned long)hcpu; @@ -395,7 +395,7 @@ static int __cpuinit kvm_cpu_notify(struct notifier_block *self, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata kvm_cpu_notifier = { +static struct notifier_block kvm_cpu_notifier = { .notifier_call = kvm_cpu_notify, }; #endif diff --git a/arch/x86/kernel/kvmclock.c b/arch/x86/kernel/kvmclock.c index f8492da65bf..96e25c1bdc8 100644 --- a/arch/x86/kernel/kvmclock.c +++ b/arch/x86/kernel/kvmclock.c @@ -146,7 +146,7 @@ static void kvm_restore_sched_clock_state(void) } #ifdef CONFIG_X86_LOCAL_APIC -static void __cpuinit kvm_setup_secondary_clock(void) +static void kvm_setup_secondary_clock(void) { /* * Now that the first cpu already had this clocksource initialized, diff --git a/arch/x86/kernel/microcode_core.c b/arch/x86/kernel/microcode_core.c index c9bda6d6035..937cb7e0c65 100644 --- a/arch/x86/kernel/microcode_core.c +++ b/arch/x86/kernel/microcode_core.c @@ -461,7 +461,7 @@ static struct syscore_ops mc_syscore_ops = { .resume = mc_bp_resume, }; -static __cpuinit int +static int mc_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu) { unsigned int cpu = (unsigned long)hcpu; diff --git a/arch/x86/kernel/mmconf-fam10h_64.c b/arch/x86/kernel/mmconf-fam10h_64.c index ac861b8348e..33fd4e6407b 100644 --- a/arch/x86/kernel/mmconf-fam10h_64.c +++ b/arch/x86/kernel/mmconf-fam10h_64.c @@ -24,14 +24,14 @@ struct pci_hostbridge_probe { u32 device; }; -static u64 __cpuinitdata fam10h_pci_mmconf_base; +static u64 fam10h_pci_mmconf_base; -static struct pci_hostbridge_probe pci_probes[] __cpuinitdata = { +static struct pci_hostbridge_probe pci_probes[] = { { 0, 0x18, PCI_VENDOR_ID_AMD, 0x1200 }, { 0xff, 0, PCI_VENDOR_ID_AMD, 0x1200 }, }; -static int __cpuinit cmp_range(const void *x1, const void *x2) +static int cmp_range(const void *x1, const void *x2) { const struct range *r1 = x1; const struct range *r2 = x2; @@ -49,7 +49,7 @@ static int __cpuinit cmp_range(const void *x1, const void *x2) /* need to avoid (0xfd<<32), (0xfe<<32), and (0xff<<32), ht used space */ #define FAM10H_PCI_MMCONF_BASE (0xfcULL<<32) #define BASE_VALID(b) ((b) + MMCONF_SIZE <= (0xfdULL<<32) || (b) >= (1ULL<<40)) -static void __cpuinit get_fam10h_pci_mmconf_base(void) +static void get_fam10h_pci_mmconf_base(void) { int i; unsigned bus; @@ -166,7 +166,7 @@ static void __cpuinit get_fam10h_pci_mmconf_base(void) fam10h_pci_mmconf_base = base; } -void __cpuinit fam10h_check_enable_mmcfg(void) +void fam10h_check_enable_mmcfg(void) { u64 val; u32 address; @@ -230,7 +230,7 @@ static const struct dmi_system_id __initconst mmconf_dmi_table[] = { {} }; -/* Called from a __cpuinit function, but only on the BSP. */ +/* Called from a function, but only on the BSP. */ void __ref check_enable_amd_mmconf_dmi(void) { dmi_check_system(mmconf_dmi_table); diff --git a/arch/x86/kernel/msr.c b/arch/x86/kernel/msr.c index eb113693f04..3757df2721e 100644 --- a/arch/x86/kernel/msr.c +++ b/arch/x86/kernel/msr.c @@ -198,7 +198,7 @@ static const struct file_operations msr_fops = { .compat_ioctl = msr_ioctl, }; -static int __cpuinit msr_device_create(int cpu) +static int msr_device_create(int cpu) { struct device *dev; @@ -212,7 +212,7 @@ static void msr_device_destroy(int cpu) device_destroy(msr_class, MKDEV(MSR_MAJOR, cpu)); } -static int __cpuinit msr_class_cpu_callback(struct notifier_block *nfb, +static int msr_class_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { unsigned int cpu = (unsigned long)hcpu; diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index fdd151cef9b..a0f82b24974 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -661,7 +661,7 @@ static void amd_e400_idle(void) default_idle(); } -void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c) +void select_idle_routine(const struct cpuinfo_x86 *c) { #ifdef CONFIG_SMP if (pm_idle == poll_idle && smp_num_siblings > 1) { diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index d6c956e674c..a3e9be27539 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -176,7 +176,7 @@ static struct resource bss_resource = { #ifdef CONFIG_X86_32 /* cpu data as detected by the assembly code in head.S */ -struct cpuinfo_x86 new_cpu_data __cpuinitdata = {0, 0, 0, 0, -1, 1, 0, 0, -1}; +struct cpuinfo_x86 new_cpu_data = {0, 0, 0, 0, -1, 1, 0, 0, -1}; /* common cpu data for all cpus */ struct cpuinfo_x86 boot_cpu_data __read_mostly = {0, 0, 0, 0, -1, 1, 0, 0, -1}; EXPORT_SYMBOL(boot_cpu_data); diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 6e1e406038c..b993c5f0a09 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -82,7 +82,7 @@ DEFINE_PER_CPU(int, cpu_state) = { 0 }; */ #ifdef CONFIG_HOTPLUG_CPU /* - * Needed only for CONFIG_HOTPLUG_CPU because __cpuinitdata is + * Needed only for CONFIG_HOTPLUG_CPU because is * removed after init for !CONFIG_HOTPLUG_CPU. */ static DEFINE_PER_CPU(struct task_struct *, idle_thread_array); @@ -108,7 +108,7 @@ void cpu_hotplug_driver_unlock(void) ssize_t arch_cpu_probe(const char *buf, size_t count) { return -1; } ssize_t arch_cpu_release(const char *buf, size_t count) { return -1; } #else -static struct task_struct *idle_thread_array[NR_CPUS] __cpuinitdata ; +static struct task_struct *idle_thread_array[NR_CPUS] ; #define get_idle_for_cpu(x) (idle_thread_array[(x)]) #define set_idle_for_cpu(x, p) (idle_thread_array[(x)] = (p)) #endif @@ -140,7 +140,7 @@ atomic_t init_deasserted; * Report back to the Boot Processor. * Running on AP. */ -static void __cpuinit smp_callin(void) +static void smp_callin(void) { int cpuid, phys_id; unsigned long timeout; @@ -243,7 +243,7 @@ static void __cpuinit smp_callin(void) /* * Activate a secondary processor. */ -notrace static void __cpuinit start_secondary(void *unused) +notrace static void start_secondary(void *unused) { /* * Don't put *anything* before cpu_init(), SMP booting is too @@ -305,7 +305,7 @@ notrace static void __cpuinit start_secondary(void *unused) * a given CPU */ -void __cpuinit smp_store_cpu_info(int id) +void smp_store_cpu_info(int id) { struct cpuinfo_x86 *c = &cpu_data(id); @@ -315,7 +315,7 @@ void __cpuinit smp_store_cpu_info(int id) identify_secondary_cpu(c); } -static void __cpuinit link_thread_siblings(int cpu1, int cpu2) +static void link_thread_siblings(int cpu1, int cpu2) { cpumask_set_cpu(cpu1, cpu_sibling_mask(cpu2)); cpumask_set_cpu(cpu2, cpu_sibling_mask(cpu1)); @@ -326,7 +326,7 @@ static void __cpuinit link_thread_siblings(int cpu1, int cpu2) } -void __cpuinit set_cpu_sibling_map(int cpu) +void set_cpu_sibling_map(int cpu) { int i; struct cpuinfo_x86 *c = &cpu_data(cpu); @@ -469,7 +469,7 @@ void __inquire_remote_apic(int apicid) * INIT, INIT, STARTUP sequence will reset the chip hard for us, and this * won't ... remember to clear down the APIC, etc later. */ -int __cpuinit +int wakeup_secondary_cpu_via_nmi(int logical_apicid, unsigned long start_eip) { unsigned long send_status, accept_status = 0; @@ -503,7 +503,7 @@ wakeup_secondary_cpu_via_nmi(int logical_apicid, unsigned long start_eip) return (send_status | accept_status); } -static int __cpuinit +static int wakeup_secondary_cpu_via_init(int phys_apicid, unsigned long start_eip) { unsigned long send_status, accept_status = 0; @@ -625,7 +625,7 @@ struct create_idle { int cpu; }; -static void __cpuinit do_fork_idle(struct work_struct *work) +static void do_fork_idle(struct work_struct *work) { struct create_idle *c_idle = container_of(work, struct create_idle, work); @@ -635,7 +635,7 @@ static void __cpuinit do_fork_idle(struct work_struct *work) } /* reduce the number of lines printed when booting a large cpu count system */ -static void __cpuinit announce_cpu(int cpu, int apicid) +static void announce_cpu(int cpu, int apicid) { static int current_node = -1; int node = early_cpu_to_node(cpu); @@ -660,7 +660,7 @@ static void __cpuinit announce_cpu(int cpu, int apicid) * Returns zero if CPU booted OK, else error code from * ->wakeup_secondary_cpu. */ -static int __cpuinit do_boot_cpu(int apicid, int cpu) +static int do_boot_cpu(int apicid, int cpu) { unsigned long boot_error = 0; unsigned long start_ip; @@ -818,7 +818,7 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu) return boot_error; } -int __cpuinit native_cpu_up(unsigned int cpu) +int native_cpu_up(unsigned int cpu) { int apicid = apic->cpu_present_to_apicid(cpu); unsigned long flags; diff --git a/arch/x86/kernel/tboot.c b/arch/x86/kernel/tboot.c index 6410744ac5c..12adbef476d 100644 --- a/arch/x86/kernel/tboot.c +++ b/arch/x86/kernel/tboot.c @@ -318,7 +318,7 @@ static int tboot_wait_for_aps(int num_aps) return !(atomic_read((atomic_t *)&tboot->num_in_wfs) == num_aps); } -static int __cpuinit tboot_cpu_callback(struct notifier_block *nfb, +static int tboot_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { switch (action) { @@ -332,7 +332,7 @@ static int __cpuinit tboot_cpu_callback(struct notifier_block *nfb, return NOTIFY_OK; } -static struct notifier_block tboot_cpu_notifier __cpuinitdata = +static struct notifier_block tboot_cpu_notifier = { .notifier_call = tboot_cpu_callback, }; diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index fc0a147e372..d3dc60f3537 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c @@ -818,7 +818,7 @@ static void __init check_system_tsc_reliable(void) * Make an educated guess if the TSC is trustworthy and synchronized * over all CPUs. */ -__cpuinit int unsynchronized_tsc(void) +int unsynchronized_tsc(void) { if (!cpu_has_tsc || tsc_unstable) return 1; @@ -1011,7 +1011,7 @@ void __init tsc_init(void) * been calibrated. This assumes that CONSTANT_TSC applies to all * cpus in the socket - this should be a safe assumption. */ -unsigned long __cpuinit calibrate_delay_is_known(void) +unsigned long calibrate_delay_is_known(void) { int i, cpu = smp_processor_id(); diff --git a/arch/x86/kernel/tsc_sync.c b/arch/x86/kernel/tsc_sync.c index fc25e60a588..adfdf56a371 100644 --- a/arch/x86/kernel/tsc_sync.c +++ b/arch/x86/kernel/tsc_sync.c @@ -25,24 +25,24 @@ * Entry/exit counters that make sure that both CPUs * run the measurement code at once: */ -static __cpuinitdata atomic_t start_count; -static __cpuinitdata atomic_t stop_count; +static atomic_t start_count; +static atomic_t stop_count; /* * We use a raw spinlock in this exceptional case, because * we want to have the fastest, inlined, non-debug version * of a critical section, to be able to prove TSC time-warps: */ -static __cpuinitdata arch_spinlock_t sync_lock = __ARCH_SPIN_LOCK_UNLOCKED; +static arch_spinlock_t sync_lock = __ARCH_SPIN_LOCK_UNLOCKED; -static __cpuinitdata cycles_t last_tsc; -static __cpuinitdata cycles_t max_warp; -static __cpuinitdata int nr_warps; +static cycles_t last_tsc; +static cycles_t max_warp; +static int nr_warps; /* * TSC-warp measurement loop running on both CPUs: */ -static __cpuinit void check_tsc_warp(unsigned int timeout) +static void check_tsc_warp(unsigned int timeout) { cycles_t start, now, prev, end; int i; @@ -121,7 +121,7 @@ static inline unsigned int loop_timeout(int cpu) * Source CPU calls into this - it waits for the freshly booted * target CPU to arrive and then starts the measurement: */ -void __cpuinit check_tsc_sync_source(int cpu) +void check_tsc_sync_source(int cpu) { int cpus = 2; @@ -187,7 +187,7 @@ void __cpuinit check_tsc_sync_source(int cpu) /* * Freshly booted CPUs call into this: */ -void __cpuinit check_tsc_sync_target(void) +void check_tsc_sync_target(void) { int cpus = 2; diff --git a/arch/x86/kernel/vsyscall_64.c b/arch/x86/kernel/vsyscall_64.c index 7515cf0e180..64ee9062e1a 100644 --- a/arch/x86/kernel/vsyscall_64.c +++ b/arch/x86/kernel/vsyscall_64.c @@ -286,7 +286,7 @@ bool emulate_vsyscall(struct pt_regs *regs, unsigned long address) * Assume __initcall executes before all user space. Hopefully kmod * doesn't violate that. We'll find out if it does. */ -static void __cpuinit vsyscall_set_cpu(int cpu) +static void vsyscall_set_cpu(int cpu) { unsigned long d; unsigned long node = 0; @@ -308,13 +308,13 @@ static void __cpuinit vsyscall_set_cpu(int cpu) write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_PER_CPU, &d, DESCTYPE_S); } -static void __cpuinit cpu_vsyscall_init(void *arg) +static void cpu_vsyscall_init(void *arg) { /* preemption should be already off */ vsyscall_set_cpu(raw_smp_processor_id()); } -static int __cpuinit +static int cpu_vsyscall_notifier(struct notifier_block *n, unsigned long action, void *arg) { long cpu = (long)arg; diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c index 9cf71d0b2d3..d36d4b4f71e 100644 --- a/arch/x86/kernel/x86_init.c +++ b/arch/x86/kernel/x86_init.c @@ -23,7 +23,7 @@ #include #include -void __cpuinit x86_init_noop(void) { } +void x86_init_noop(void) { } void __init x86_init_uint_noop(unsigned int unused) { } void __init x86_init_pgd_noop(pgd_t *unused) { } int __init iommu_init_noop(void) { return 0; } @@ -90,7 +90,7 @@ struct x86_init_ops x86_init __initdata = { }, }; -struct x86_cpuinit_ops x86_cpuinit __cpuinitdata = { +struct x86_cpuinit_ops x86_cpuinit = { .early_percpu_clock_init = x86_init_noop, .setup_percpu_clockev = setup_secondary_APIC_clock, }; diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c index e62728e30b0..7cf3fbc1d65 100644 --- a/arch/x86/kernel/xsave.c +++ b/arch/x86/kernel/xsave.c @@ -459,7 +459,7 @@ static void __init xstate_enable_boot_cpu(void) * This is somewhat obfuscated due to the lack of powerful enough * overrides for the section checks. */ -void __cpuinit xsave_init(void) +void xsave_init(void) { static __refdata void (*next_func)(void) = xstate_enable_boot_cpu; void (*this_func)(void); diff --git a/arch/x86/mm/numa.c b/arch/x86/mm/numa.c index 19d3fa08b11..5c276390aca 100644 --- a/arch/x86/mm/numa.c +++ b/arch/x86/mm/numa.c @@ -56,11 +56,11 @@ early_param("numa", numa_setup); /* * apicid, cpu, node mappings */ -s16 __apicid_to_node[MAX_LOCAL_APIC] __cpuinitdata = { +s16 __apicid_to_node[MAX_LOCAL_APIC] = { [0 ... MAX_LOCAL_APIC-1] = NUMA_NO_NODE }; -int __cpuinit numa_cpu_node(int cpu) +int numa_cpu_node(int cpu) { int apicid = early_per_cpu(x86_cpu_to_apicid, cpu); @@ -78,7 +78,7 @@ EXPORT_SYMBOL(node_to_cpumask_map); DEFINE_EARLY_PER_CPU(int, x86_cpu_to_node_map, NUMA_NO_NODE); EXPORT_EARLY_PER_CPU_SYMBOL(x86_cpu_to_node_map); -void __cpuinit numa_set_node(int cpu, int node) +void numa_set_node(int cpu, int node) { int *cpu_to_node_map = early_per_cpu_ptr(x86_cpu_to_node_map); @@ -101,7 +101,7 @@ void __cpuinit numa_set_node(int cpu, int node) set_cpu_numa_node(cpu, node); } -void __cpuinit numa_clear_node(int cpu) +void numa_clear_node(int cpu) { numa_set_node(cpu, NUMA_NO_NODE); } @@ -705,12 +705,12 @@ void __init init_cpu_to_node(void) #ifndef CONFIG_DEBUG_PER_CPU_MAPS # ifndef CONFIG_NUMA_EMU -void __cpuinit numa_add_cpu(int cpu) +void numa_add_cpu(int cpu) { cpumask_set_cpu(cpu, node_to_cpumask_map[early_cpu_to_node(cpu)]); } -void __cpuinit numa_remove_cpu(int cpu) +void numa_remove_cpu(int cpu) { cpumask_clear_cpu(cpu, node_to_cpumask_map[early_cpu_to_node(cpu)]); } @@ -777,17 +777,17 @@ void debug_cpumask_set_cpu(int cpu, int node, bool enable) } # ifndef CONFIG_NUMA_EMU -static void __cpuinit numa_set_cpumask(int cpu, bool enable) +static void numa_set_cpumask(int cpu, bool enable) { debug_cpumask_set_cpu(cpu, early_cpu_to_node(cpu), enable); } -void __cpuinit numa_add_cpu(int cpu) +void numa_add_cpu(int cpu) { numa_set_cpumask(cpu, true); } -void __cpuinit numa_remove_cpu(int cpu) +void numa_remove_cpu(int cpu) { numa_set_cpumask(cpu, false); } diff --git a/arch/x86/mm/numa_emulation.c b/arch/x86/mm/numa_emulation.c index 53489ff6bf8..326a0ad4c9d 100644 --- a/arch/x86/mm/numa_emulation.c +++ b/arch/x86/mm/numa_emulation.c @@ -10,7 +10,7 @@ #include "numa_internal.h" -static int emu_nid_to_phys[MAX_NUMNODES] __cpuinitdata; +static int emu_nid_to_phys[MAX_NUMNODES]; static char *emu_cmdline __initdata; void __init numa_emu_cmdline(char *str) @@ -440,7 +440,7 @@ void __init numa_emulation(struct numa_meminfo *numa_meminfo, int numa_dist_cnt) } #ifndef CONFIG_DEBUG_PER_CPU_MAPS -void __cpuinit numa_add_cpu(int cpu) +void numa_add_cpu(int cpu) { int physnid, nid; @@ -458,7 +458,7 @@ void __cpuinit numa_add_cpu(int cpu) cpumask_set_cpu(cpu, node_to_cpumask_map[nid]); } -void __cpuinit numa_remove_cpu(int cpu) +void numa_remove_cpu(int cpu) { int i; @@ -466,7 +466,7 @@ void __cpuinit numa_remove_cpu(int cpu) cpumask_clear_cpu(cpu, node_to_cpumask_map[i]); } #else /* !CONFIG_DEBUG_PER_CPU_MAPS */ -static void __cpuinit numa_set_cpumask(int cpu, bool enable) +static void numa_set_cpumask(int cpu, bool enable) { int nid, physnid; @@ -486,12 +486,12 @@ static void __cpuinit numa_set_cpumask(int cpu, bool enable) } } -void __cpuinit numa_add_cpu(int cpu) +void numa_add_cpu(int cpu) { numa_set_cpumask(cpu, true); } -void __cpuinit numa_remove_cpu(int cpu) +void numa_remove_cpu(int cpu) { numa_set_cpumask(cpu, false); } diff --git a/arch/x86/mm/setup_nx.c b/arch/x86/mm/setup_nx.c index 410531d3c29..90555bf60aa 100644 --- a/arch/x86/mm/setup_nx.c +++ b/arch/x86/mm/setup_nx.c @@ -5,7 +5,7 @@ #include #include -static int disable_nx __cpuinitdata; +static int disable_nx; /* * noexec = on|off @@ -29,7 +29,7 @@ static int __init noexec_setup(char *str) } early_param("noexec", noexec_setup); -void __cpuinit x86_configure_nx(void) +void x86_configure_nx(void) { if (cpu_has_nx && !disable_nx) __supported_pte_mask |= _PAGE_NX; diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c index d6c0418c3e4..c8abce3c339 100644 --- a/arch/x86/mm/tlb.c +++ b/arch/x86/mm/tlb.c @@ -217,7 +217,7 @@ void native_flush_tlb_others(const struct cpumask *cpumask, flush_tlb_others_ipi(cpumask, mm, va); } -static void __cpuinit calculate_tlb_offset(void) +static void calculate_tlb_offset(void) { int cpu, node, nr_node_vecs, idx = 0; /* @@ -248,7 +248,7 @@ static void __cpuinit calculate_tlb_offset(void) } } -static int __cpuinit tlb_cpuhp_notify(struct notifier_block *n, +static int tlb_cpuhp_notify(struct notifier_block *n, unsigned long action, void *hcpu) { switch (action & 0xf) { @@ -259,7 +259,7 @@ static int __cpuinit tlb_cpuhp_notify(struct notifier_block *n, return NOTIFY_OK; } -static int __cpuinit init_smp_flush(void) +static int init_smp_flush(void) { int i; diff --git a/arch/x86/pci/amd_bus.c b/arch/x86/pci/amd_bus.c index 0567df3890e..5d1a27f6b16 100644 --- a/arch/x86/pci/amd_bus.c +++ b/arch/x86/pci/amd_bus.c @@ -330,7 +330,7 @@ static int __init early_fill_mp_bus_info(void) #define ENABLE_CF8_EXT_CFG (1ULL << 46) -static void __cpuinit enable_pci_io_ecs(void *unused) +static void enable_pci_io_ecs(void *unused) { u64 reg; rdmsrl(MSR_AMD64_NB_CFG, reg); @@ -340,7 +340,7 @@ static void __cpuinit enable_pci_io_ecs(void *unused) } } -static int __cpuinit amd_cpu_notify(struct notifier_block *self, +static int amd_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) { int cpu = (long)hcpu; @@ -355,7 +355,7 @@ static int __cpuinit amd_cpu_notify(struct notifier_block *self, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata amd_cpu_notifier = { +static struct notifier_block amd_cpu_notifier = { .notifier_call = amd_cpu_notify, }; diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c index 7415aa92791..56ab74989cf 100644 --- a/arch/x86/pci/xen.c +++ b/arch/x86/pci/xen.c @@ -64,6 +64,10 @@ static int xen_register_pirq(u32 gsi, int gsi_override, int triggering, int shareable = 0; char *name; + irq = xen_irq_from_gsi(gsi); + if (irq > 0) + return irq; + if (set_pirq) pirq = gsi; diff --git a/arch/x86/platform/ce4100/ce4100.c b/arch/x86/platform/ce4100/ce4100.c index 4c61b52191e..766befc9c52 100644 --- a/arch/x86/platform/ce4100/ce4100.c +++ b/arch/x86/platform/ce4100/ce4100.c @@ -118,7 +118,7 @@ static void __init sdv_arch_setup(void) } #ifdef CONFIG_X86_IO_APIC -static void __cpuinit sdv_pci_init(void) +static void sdv_pci_init(void) { x86_of_pci_init(); /* We can't set this earlier, because we need to calibrate the timer */ diff --git a/arch/x86/platform/mrst/mrst.c b/arch/x86/platform/mrst/mrst.c index e31bcd8f2ee..789a9aff087 100644 --- a/arch/x86/platform/mrst/mrst.c +++ b/arch/x86/platform/mrst/mrst.c @@ -65,7 +65,7 @@ * lapic (always-on,ARAT) ------ 150 */ -__cpuinitdata enum mrst_timer_options mrst_timer_options; +enum mrst_timer_options mrst_timer_options; static u32 sfi_mtimer_usage[SFI_MTMR_MAX_NUM]; static struct sfi_timer_table_entry sfi_mtimer_array[SFI_MTMR_MAX_NUM]; @@ -248,7 +248,7 @@ static void __init mrst_time_init(void) apbt_time_init(); } -static void __cpuinit mrst_arch_setup(void) +static void mrst_arch_setup(void) { if (boot_cpu_data.x86 == 6 && boot_cpu_data.x86_model == 0x27) __mrst_cpu_chip = MRST_CPU_CHIP_PENWELL; diff --git a/arch/x86/platform/sfi/sfi.c b/arch/x86/platform/sfi/sfi.c index 7785b72ecc3..662b87b3b7e 100644 --- a/arch/x86/platform/sfi/sfi.c +++ b/arch/x86/platform/sfi/sfi.c @@ -35,7 +35,7 @@ static unsigned long sfi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE; /* All CPUs enumerated by SFI must be present and enabled */ -static void __cpuinit mp_sfi_register_lapic(u8 id) +static void mp_sfi_register_lapic(u8 id) { if (MAX_LOCAL_APIC - id <= 0) { pr_warning("Processor #%d invalid (max %d)\n", diff --git a/arch/x86/tools/relocs.c b/arch/x86/tools/relocs.c index b43cfcd9bf4..b685296d446 100644 --- a/arch/x86/tools/relocs.c +++ b/arch/x86/tools/relocs.c @@ -60,6 +60,18 @@ static const char * const sym_regex_kernel[S_NSYMTYPES] = { "__x86_cpu_dev_(start|end)|" "(__parainstructions|__alt_instructions)(|_end)|" "(__iommu_table|__apicdrivers|__smp_locks)(|_end)|" + "__(start|end)_pci_.*|" + "__(start|end)_builtin_fw|" + "__(start|stop)___ksymtab(|_gpl|_unused|_unused_gpl|_gpl_future)|" + "__(start|stop)___kcrctab(|_gpl|_unused|_unused_gpl|_gpl_future)|" + "__(start|stop)___param|" + "__(start|stop)___modver|" + "__(start|stop)___bug_table|" + "__tracedata_(start|end)|" + "__(start|stop)_notes|" + "__end_rodata|" + "__initramfs_start|" + "(jiffies|jiffies_64)|" "_end)$" }; diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 95dccce8e97..ad6c4e06498 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -1473,7 +1473,7 @@ void __ref xen_hvm_init_shared_info(void) } #ifdef CONFIG_XEN_PVHVM -static int __cpuinit xen_hvm_cpu_notify(struct notifier_block *self, +static int xen_hvm_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) { int cpu = (long)hcpu; @@ -1489,7 +1489,7 @@ static int __cpuinit xen_hvm_cpu_notify(struct notifier_block *self, return NOTIFY_OK; } -static struct notifier_block xen_hvm_cpu_notifier __cpuinitdata = { +static struct notifier_block xen_hvm_cpu_notifier = { .notifier_call = xen_hvm_cpu_notify, }; diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c index 1ba8dff2675..ad1cd644894 100644 --- a/arch/x86/xen/setup.c +++ b/arch/x86/xen/setup.c @@ -336,7 +336,7 @@ static void __init fiddle_vdso(void) #endif } -static int __cpuinit register_callback(unsigned type, const void *func) +static int register_callback(unsigned type, const void *func) { struct callback_register callback = { .type = type, @@ -347,7 +347,7 @@ static int __cpuinit register_callback(unsigned type, const void *func) return HYPERVISOR_callback_op(CALLBACKOP_register, &callback); } -void __cpuinit xen_enable_sysenter(void) +void xen_enable_sysenter(void) { int ret; unsigned sysenter_feature; @@ -366,7 +366,7 @@ void __cpuinit xen_enable_sysenter(void) setup_clear_cpu_cap(sysenter_feature); } -void __cpuinit xen_enable_syscall(void) +void xen_enable_syscall(void) { #ifdef CONFIG_X86_64 int ret; diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index 0503c0c493a..b46afc0b677 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c @@ -57,7 +57,7 @@ static irqreturn_t xen_reschedule_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -static void __cpuinit cpu_bringup(void) +static void cpu_bringup(void) { int cpu; @@ -91,7 +91,7 @@ static void __cpuinit cpu_bringup(void) wmb(); /* make sure everything is out */ } -static void __cpuinit cpu_bringup_and_idle(void) +static void cpu_bringup_and_idle(void) { cpu_bringup(); cpu_idle(); @@ -279,7 +279,7 @@ static void __init xen_smp_prepare_cpus(unsigned int max_cpus) } } -static int __cpuinit +static int cpu_initialize_context(unsigned int cpu, struct task_struct *idle) { struct vcpu_guest_context *ctxt; @@ -346,7 +346,7 @@ cpu_initialize_context(unsigned int cpu, struct task_struct *idle) return 0; } -static int __cpuinit xen_cpu_up(unsigned int cpu) +static int xen_cpu_up(unsigned int cpu) { struct task_struct *idle = idle_task(cpu); int rc; @@ -425,7 +425,7 @@ static void xen_cpu_die(unsigned int cpu) alternatives_smp_switch(0); } -static void __cpuinit xen_play_dead(void) /* used only with HOTPLUG_CPU */ +static void xen_play_dead(void) /* used only with HOTPLUG_CPU */ { play_dead_common(); HYPERVISOR_vcpu_op(VCPUOP_down, smp_processor_id(), NULL); @@ -562,7 +562,7 @@ static void __init xen_hvm_smp_prepare_cpus(unsigned int max_cpus) xen_init_lock_cpu(0); } -static int __cpuinit xen_hvm_cpu_up(unsigned int cpu) +static int xen_hvm_cpu_up(unsigned int cpu) { int rc; rc = native_cpu_up(cpu); diff --git a/arch/x86/xen/spinlock.c b/arch/x86/xen/spinlock.c index d69cc6c3f80..b6eb7d2af60 100644 --- a/arch/x86/xen/spinlock.c +++ b/arch/x86/xen/spinlock.c @@ -360,7 +360,7 @@ static irqreturn_t dummy_handler(int irq, void *dev_id) return IRQ_HANDLED; } -void __cpuinit xen_init_lock_cpu(int cpu) +void xen_init_lock_cpu(int cpu) { int irq; const char *name; diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h index b095739ccd4..c35fa2df311 100644 --- a/arch/x86/xen/xen-ops.h +++ b/arch/x86/xen/xen-ops.h @@ -74,7 +74,7 @@ static inline void xen_hvm_smp_init(void) {} #ifdef CONFIG_PARAVIRT_SPINLOCKS void __init xen_init_spinlocks(void); -void __cpuinit xen_init_lock_cpu(int cpu); +void xen_init_lock_cpu(int cpu); void xen_uninit_lock_cpu(int cpu); #else static inline void xen_init_spinlocks(void) diff --git a/arch/xtensa/kernel/time.c b/arch/xtensa/kernel/time.c index ac62f9cf1e1..1bb04405f47 100644 --- a/arch/xtensa/kernel/time.c +++ b/arch/xtensa/kernel/time.c @@ -106,7 +106,7 @@ irqreturn_t timer_interrupt (int irq, void *dev_id) } #ifndef CONFIG_GENERIC_CALIBRATE_DELAY -void __cpuinit calibrate_delay(void) +void calibrate_delay(void) { loops_per_jiffy = CCOUNT_PER_JIFFY; printk("Calibrating delay loop (skipped)... " diff --git a/block/Kconfig.iosched b/block/Kconfig.iosched index 4142d919b75..4e7030d9c1d 100644 --- a/block/Kconfig.iosched +++ b/block/Kconfig.iosched @@ -54,6 +54,24 @@ config CFQ_GROUP_IOSCHED ---help--- Enable group IO scheduling in CFQ. +config IOSCHED_FIOPS + tristate "IOPS based I/O scheduler" + default y + ---help--- + This is an IOPS based I/O scheduler. It will try to distribute + IOPS equally among all processes in the system. It's mainly for + Flash based storage. + +config IOSCHED_SIO + tristate "Simple I/O scheduler" + default y + ---help--- + The Simple I/O scheduler is an extremely simple scheduler, + based on noop and deadline, that relies on deadlines to + ensure fairness. The algorithm does not do any sorting but + basic merging, trying to keep a minimum overhead. It is aimed + mainly for aleatory access devices (eg: flash devices). + choice prompt "Default I/O scheduler" default DEFAULT_CFQ @@ -67,6 +85,12 @@ choice config DEFAULT_CFQ bool "CFQ" if IOSCHED_CFQ=y + config DEFAULT_FIOPS + bool "FIOPS" if IOSCHED_FIOPS=y + + config DEFAULT_SIO + bool "SIO" if IOSCHED_SIO=y + config DEFAULT_NOOP bool "No-op" @@ -76,6 +100,8 @@ config DEFAULT_IOSCHED string default "deadline" if DEFAULT_DEADLINE default "cfq" if DEFAULT_CFQ + default "fiops" if DEFAULT_FIOPS + default "sio" if DEFAULT_SIO default "noop" if DEFAULT_NOOP endmenu diff --git a/block/Makefile b/block/Makefile index 436b220cecc..109892dd0bc 100644 --- a/block/Makefile +++ b/block/Makefile @@ -16,6 +16,8 @@ obj-$(CONFIG_IOSCHED_NOOP) += noop-iosched.o obj-$(CONFIG_IOSCHED_DEADLINE) += deadline-iosched.o obj-$(CONFIG_IOSCHED_CFQ) += cfq-iosched.o obj-$(CONFIG_IOSCHED_TEST) += test-iosched.o +obj-$(CONFIG_IOSCHED_FIOPS) += fiops-iosched.o +obj-$(CONFIG_IOSCHED_SIO) += sio-iosched.o obj-$(CONFIG_BLOCK_COMPAT) += compat_ioctl.o obj-$(CONFIG_BLK_DEV_INTEGRITY) += blk-integrity.o diff --git a/block/blk-iopoll.c b/block/blk-iopoll.c index 58916afbbda..4f1a7bd6f91 100644 --- a/block/blk-iopoll.c +++ b/block/blk-iopoll.c @@ -189,7 +189,7 @@ void blk_iopoll_init(struct blk_iopoll *iop, int weight, blk_iopoll_fn *poll_fn) } EXPORT_SYMBOL(blk_iopoll_init); -static int __cpuinit blk_iopoll_cpu_notify(struct notifier_block *self, +static int blk_iopoll_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) { /* @@ -209,7 +209,7 @@ static int __cpuinit blk_iopoll_cpu_notify(struct notifier_block *self, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata blk_iopoll_cpu_notifier = { +static struct notifier_block blk_iopoll_cpu_notifier = { .notifier_call = blk_iopoll_cpu_notify, }; diff --git a/block/blk-softirq.c b/block/blk-softirq.c index 467c8de8864..443ce632b64 100644 --- a/block/blk-softirq.c +++ b/block/blk-softirq.c @@ -78,7 +78,7 @@ static int raise_blk_irq(int cpu, struct request *rq) } #endif -static int __cpuinit blk_cpu_notify(struct notifier_block *self, +static int blk_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) { /* @@ -98,7 +98,7 @@ static int __cpuinit blk_cpu_notify(struct notifier_block *self, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata blk_cpu_notifier = { +static struct notifier_block blk_cpu_notifier = { .notifier_call = blk_cpu_notify, }; diff --git a/block/fiops-iosched.c b/block/fiops-iosched.c new file mode 100644 index 00000000000..671b1d33157 --- /dev/null +++ b/block/fiops-iosched.c @@ -0,0 +1,753 @@ +/* + * IOPS based IO scheduler. Based on CFQ. + * Copyright (C) 2003 Jens Axboe + * Shaohua Li + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include "blk.h" + +#define VIOS_SCALE_SHIFT 10 +#define VIOS_SCALE (1 << VIOS_SCALE_SHIFT) + +#define VIOS_READ_SCALE (1) +#define VIOS_WRITE_SCALE (1) +#define VIOS_SYNC_SCALE (2) +#define VIOS_ASYNC_SCALE (5) + +#define VIOS_PRIO_SCALE (5) + +struct fiops_rb_root { + struct rb_root rb; + struct rb_node *left; + unsigned count; + + u64 min_vios; +}; +#define FIOPS_RB_ROOT (struct fiops_rb_root) { .rb = RB_ROOT} + +enum wl_prio_t { + IDLE_WORKLOAD = 0, + BE_WORKLOAD = 1, + RT_WORKLOAD = 2, + FIOPS_PRIO_NR, +}; + +struct fiops_data { + struct request_queue *queue; + + struct fiops_rb_root service_tree[FIOPS_PRIO_NR]; + + unsigned int busy_queues; + unsigned int in_flight[2]; + + struct work_struct unplug_work; + + unsigned int read_scale; + unsigned int write_scale; + unsigned int sync_scale; + unsigned int async_scale; +}; + +struct fiops_ioc { + struct io_cq icq; + + unsigned int flags; + struct fiops_data *fiopsd; + struct rb_node rb_node; + u64 vios; /* key in service_tree */ + struct fiops_rb_root *service_tree; + + unsigned int in_flight; + + struct rb_root sort_list; + struct list_head fifo; + + pid_t pid; + unsigned short ioprio; + enum wl_prio_t wl_type; +}; + +#define ioc_service_tree(ioc) (&((ioc)->fiopsd->service_tree[(ioc)->wl_type])) +#define RQ_CIC(rq) icq_to_cic((rq)->elv.icq) + +enum ioc_state_flags { + FIOPS_IOC_FLAG_on_rr = 0, /* on round-robin busy list */ + FIOPS_IOC_FLAG_prio_changed, /* task priority has changed */ +}; + +#define FIOPS_IOC_FNS(name) \ +static inline void fiops_mark_ioc_##name(struct fiops_ioc *ioc) \ +{ \ + ioc->flags |= (1 << FIOPS_IOC_FLAG_##name); \ +} \ +static inline void fiops_clear_ioc_##name(struct fiops_ioc *ioc) \ +{ \ + ioc->flags &= ~(1 << FIOPS_IOC_FLAG_##name); \ +} \ +static inline int fiops_ioc_##name(const struct fiops_ioc *ioc) \ +{ \ + return ((ioc)->flags & (1 << FIOPS_IOC_FLAG_##name)) != 0; \ +} + +FIOPS_IOC_FNS(on_rr); +FIOPS_IOC_FNS(prio_changed); +#undef FIOPS_IOC_FNS + +#define fiops_log_ioc(fiopsd, ioc, fmt, args...) \ + blk_add_trace_msg((fiopsd)->queue, "ioc%d " fmt, (ioc)->pid, ##args) +#define fiops_log(fiopsd, fmt, args...) \ + blk_add_trace_msg((fiopsd)->queue, "fiops " fmt, ##args) + +enum wl_prio_t fiops_wl_type(short prio_class) +{ + if (prio_class == IOPRIO_CLASS_RT) + return RT_WORKLOAD; + if (prio_class == IOPRIO_CLASS_BE) + return BE_WORKLOAD; + return IDLE_WORKLOAD; +} + +static inline struct fiops_ioc *icq_to_cic(struct io_cq *icq) +{ + /* cic->icq is the first member, %NULL will convert to %NULL */ + return container_of(icq, struct fiops_ioc, icq); +} + +static inline struct fiops_ioc *fiops_cic_lookup(struct fiops_data *fiopsd, + struct io_context *ioc) +{ + if (ioc) + return icq_to_cic(ioc_lookup_icq(ioc, fiopsd->queue)); + return NULL; +} + +/* + * The below is leftmost cache rbtree addon + */ +static struct fiops_ioc *fiops_rb_first(struct fiops_rb_root *root) +{ + /* Service tree is empty */ + if (!root->count) + return NULL; + + if (!root->left) + root->left = rb_first(&root->rb); + + if (root->left) + return rb_entry(root->left, struct fiops_ioc, rb_node); + + return NULL; +} + +static void rb_erase_init(struct rb_node *n, struct rb_root *root) +{ + rb_erase(n, root); + RB_CLEAR_NODE(n); +} + +static void fiops_rb_erase(struct rb_node *n, struct fiops_rb_root *root) +{ + if (root->left == n) + root->left = NULL; + rb_erase_init(n, &root->rb); + --root->count; +} + +static inline u64 max_vios(u64 min_vios, u64 vios) +{ + s64 delta = (s64)(vios - min_vios); + if (delta > 0) + min_vios = vios; + + return min_vios; +} + +static void fiops_update_min_vios(struct fiops_rb_root *service_tree) +{ + struct fiops_ioc *ioc; + + ioc = fiops_rb_first(service_tree); + if (!ioc) + return; + service_tree->min_vios = max_vios(service_tree->min_vios, ioc->vios); +} + +/* + * The fiopsd->service_trees holds all pending fiops_ioc's that have + * requests waiting to be processed. It is sorted in the order that + * we will service the queues. + */ +static void fiops_service_tree_add(struct fiops_data *fiopsd, + struct fiops_ioc *ioc) +{ + struct rb_node **p, *parent; + struct fiops_ioc *__ioc; + struct fiops_rb_root *service_tree = ioc_service_tree(ioc); + u64 vios; + int left; + + /* New added IOC */ + if (RB_EMPTY_NODE(&ioc->rb_node)) { + if (ioc->in_flight > 0) + vios = ioc->vios; + else + vios = max_vios(service_tree->min_vios, ioc->vios); + } else { + vios = ioc->vios; + /* ioc->service_tree might not equal to service_tree */ + fiops_rb_erase(&ioc->rb_node, ioc->service_tree); + ioc->service_tree = NULL; + } + + fiops_log_ioc(fiopsd, ioc, "service tree add, vios %lld", vios); + + left = 1; + parent = NULL; + ioc->service_tree = service_tree; + p = &service_tree->rb.rb_node; + while (*p) { + struct rb_node **n; + + parent = *p; + __ioc = rb_entry(parent, struct fiops_ioc, rb_node); + + /* + * sort by key, that represents service time. + */ + if (vios < __ioc->vios) + n = &(*p)->rb_left; + else { + n = &(*p)->rb_right; + left = 0; + } + + p = n; + } + + if (left) + service_tree->left = &ioc->rb_node; + + ioc->vios = vios; + rb_link_node(&ioc->rb_node, parent, p); + rb_insert_color(&ioc->rb_node, &service_tree->rb); + service_tree->count++; + + fiops_update_min_vios(service_tree); +} + +/* + * Update ioc's position in the service tree. + */ +static void fiops_resort_rr_list(struct fiops_data *fiopsd, + struct fiops_ioc *ioc) +{ + /* + * Resorting requires the ioc to be on the RR list already. + */ + if (fiops_ioc_on_rr(ioc)) + fiops_service_tree_add(fiopsd, ioc); +} + +/* + * add to busy list of queues for service, trying to be fair in ordering + * the pending list according to last request service + */ +static void fiops_add_ioc_rr(struct fiops_data *fiopsd, struct fiops_ioc *ioc) +{ + BUG_ON(fiops_ioc_on_rr(ioc)); + fiops_mark_ioc_on_rr(ioc); + + fiopsd->busy_queues++; + + fiops_resort_rr_list(fiopsd, ioc); +} + +/* + * Called when the ioc no longer has requests pending, remove it from + * the service tree. + */ +static void fiops_del_ioc_rr(struct fiops_data *fiopsd, struct fiops_ioc *ioc) +{ + BUG_ON(!fiops_ioc_on_rr(ioc)); + fiops_clear_ioc_on_rr(ioc); + + if (!RB_EMPTY_NODE(&ioc->rb_node)) { + fiops_rb_erase(&ioc->rb_node, ioc->service_tree); + ioc->service_tree = NULL; + } + + BUG_ON(!fiopsd->busy_queues); + fiopsd->busy_queues--; +} + +/* + * rb tree support functions + */ +static void fiops_del_rq_rb(struct request *rq) +{ + struct fiops_ioc *ioc = RQ_CIC(rq); + + elv_rb_del(&ioc->sort_list, rq); +} + +static void fiops_add_rq_rb(struct request *rq) +{ + struct fiops_ioc *ioc = RQ_CIC(rq); + struct fiops_data *fiopsd = ioc->fiopsd; + + elv_rb_add(&ioc->sort_list, rq); + + if (!fiops_ioc_on_rr(ioc)) + fiops_add_ioc_rr(fiopsd, ioc); +} + +static void fiops_reposition_rq_rb(struct fiops_ioc *ioc, struct request *rq) +{ + elv_rb_del(&ioc->sort_list, rq); + fiops_add_rq_rb(rq); +} + +static void fiops_remove_request(struct request *rq) +{ + list_del_init(&rq->queuelist); + fiops_del_rq_rb(rq); +} + +static u64 fiops_scaled_vios(struct fiops_data *fiopsd, + struct fiops_ioc *ioc, struct request *rq) +{ + int vios = VIOS_SCALE; + + if (rq_data_dir(rq) == WRITE) + vios = vios * fiopsd->write_scale / fiopsd->read_scale; + + if (!rq_is_sync(rq)) + vios = vios * fiopsd->async_scale / fiopsd->sync_scale; + + vios += vios * (ioc->ioprio - IOPRIO_NORM) / VIOS_PRIO_SCALE; + + return vios; +} + +/* return vios dispatched */ +static u64 fiops_dispatch_request(struct fiops_data *fiopsd, + struct fiops_ioc *ioc) +{ + struct request *rq; + struct request_queue *q = fiopsd->queue; + + rq = rq_entry_fifo(ioc->fifo.next); + + fiops_remove_request(rq); + elv_dispatch_add_tail(q, rq); + + fiopsd->in_flight[rq_is_sync(rq)]++; + ioc->in_flight++; + + return fiops_scaled_vios(fiopsd, ioc, rq); +} + +static int fiops_forced_dispatch(struct fiops_data *fiopsd) +{ + struct fiops_ioc *ioc; + int dispatched = 0; + int i; + + for (i = RT_WORKLOAD; i >= IDLE_WORKLOAD; i--) { + while (!RB_EMPTY_ROOT(&fiopsd->service_tree[i].rb)) { + ioc = fiops_rb_first(&fiopsd->service_tree[i]); + + while (!list_empty(&ioc->fifo)) { + fiops_dispatch_request(fiopsd, ioc); + dispatched++; + } + if (fiops_ioc_on_rr(ioc)) + fiops_del_ioc_rr(fiopsd, ioc); + } + } + return dispatched; +} + +static struct fiops_ioc *fiops_select_ioc(struct fiops_data *fiopsd) +{ + struct fiops_ioc *ioc; + struct fiops_rb_root *service_tree = NULL; + int i; + struct request *rq; + + for (i = RT_WORKLOAD; i >= IDLE_WORKLOAD; i--) { + if (!RB_EMPTY_ROOT(&fiopsd->service_tree[i].rb)) { + service_tree = &fiopsd->service_tree[i]; + break; + } + } + + if (!service_tree) + return NULL; + + ioc = fiops_rb_first(service_tree); + + rq = rq_entry_fifo(ioc->fifo.next); + /* + * we are the only async task and sync requests are in flight, delay a + * moment. If there are other tasks coming, sync tasks have no chance + * to be starved, don't delay + */ + if (!rq_is_sync(rq) && fiopsd->in_flight[1] != 0 && + service_tree->count == 1) { + fiops_log_ioc(fiopsd, ioc, + "postpone async, in_flight async %d sync %d", + fiopsd->in_flight[0], fiopsd->in_flight[1]); + return NULL; + } + + return ioc; +} + +static void fiops_charge_vios(struct fiops_data *fiopsd, + struct fiops_ioc *ioc, u64 vios) +{ + struct fiops_rb_root *service_tree = ioc->service_tree; + ioc->vios += vios; + + fiops_log_ioc(fiopsd, ioc, "charge vios %lld, new vios %lld", vios, ioc->vios); + + if (RB_EMPTY_ROOT(&ioc->sort_list)) + fiops_del_ioc_rr(fiopsd, ioc); + else + fiops_resort_rr_list(fiopsd, ioc); + + fiops_update_min_vios(service_tree); +} + +static int fiops_dispatch_requests(struct request_queue *q, int force) +{ + struct fiops_data *fiopsd = q->elevator->elevator_data; + struct fiops_ioc *ioc; + u64 vios; + + if (unlikely(force)) + return fiops_forced_dispatch(fiopsd); + + ioc = fiops_select_ioc(fiopsd); + if (!ioc) + return 0; + + vios = fiops_dispatch_request(fiopsd, ioc); + + fiops_charge_vios(fiopsd, ioc, vios); + return 1; +} + +static void fiops_init_prio_data(struct fiops_ioc *cic) +{ + struct task_struct *tsk = current; + struct io_context *ioc = cic->icq.ioc; + int ioprio_class; + + if (!fiops_ioc_prio_changed(cic)) + return; + + ioprio_class = IOPRIO_PRIO_CLASS(ioc->ioprio); + switch (ioprio_class) { + default: + printk(KERN_ERR "fiops: bad prio %x\n", ioprio_class); + case IOPRIO_CLASS_NONE: + /* + * no prio set, inherit CPU scheduling settings + */ + cic->ioprio = task_nice_ioprio(tsk); + cic->wl_type = fiops_wl_type(task_nice_ioclass(tsk)); + break; + case IOPRIO_CLASS_RT: + cic->ioprio = task_ioprio(ioc); + cic->wl_type = fiops_wl_type(IOPRIO_CLASS_RT); + break; + case IOPRIO_CLASS_BE: + cic->ioprio = task_ioprio(ioc); + cic->wl_type = fiops_wl_type(IOPRIO_CLASS_BE); + break; + case IOPRIO_CLASS_IDLE: + cic->wl_type = fiops_wl_type(IOPRIO_CLASS_IDLE); + cic->ioprio = 7; + break; + } + + fiops_clear_ioc_prio_changed(cic); +} + +static void fiops_insert_request(struct request_queue *q, struct request *rq) +{ + struct fiops_ioc *ioc = RQ_CIC(rq); + + fiops_init_prio_data(ioc); + + list_add_tail(&rq->queuelist, &ioc->fifo); + + fiops_add_rq_rb(rq); +} + +/* + * scheduler run of queue, if there are requests pending and no one in the + * driver that will restart queueing + */ +static inline void fiops_schedule_dispatch(struct fiops_data *fiopsd) +{ + if (fiopsd->busy_queues) + kblockd_schedule_work(fiopsd->queue, &fiopsd->unplug_work); +} + +static void fiops_completed_request(struct request_queue *q, struct request *rq) +{ + struct fiops_data *fiopsd = q->elevator->elevator_data; + struct fiops_ioc *ioc = RQ_CIC(rq); + + fiopsd->in_flight[rq_is_sync(rq)]--; + ioc->in_flight--; + + fiops_log_ioc(fiopsd, ioc, "in_flight %d, busy queues %d", + ioc->in_flight, fiopsd->busy_queues); + + if (fiopsd->in_flight[0] + fiopsd->in_flight[1] == 0) + fiops_schedule_dispatch(fiopsd); +} + +static struct request * +fiops_find_rq_fmerge(struct fiops_data *fiopsd, struct bio *bio) +{ + struct task_struct *tsk = current; + struct fiops_ioc *cic; + + cic = fiops_cic_lookup(fiopsd, tsk->io_context); + + if (cic) { + sector_t sector = bio->bi_sector + bio_sectors(bio); + + return elv_rb_find(&cic->sort_list, sector); + } + + return NULL; +} + +static int fiops_merge(struct request_queue *q, struct request **req, + struct bio *bio) +{ + struct fiops_data *fiopsd = q->elevator->elevator_data; + struct request *__rq; + + __rq = fiops_find_rq_fmerge(fiopsd, bio); + if (__rq && elv_rq_merge_ok(__rq, bio)) { + *req = __rq; + return ELEVATOR_FRONT_MERGE; + } + + return ELEVATOR_NO_MERGE; +} + +static void fiops_merged_request(struct request_queue *q, struct request *req, + int type) +{ + if (type == ELEVATOR_FRONT_MERGE) { + struct fiops_ioc *ioc = RQ_CIC(req); + + fiops_reposition_rq_rb(ioc, req); + } +} + +static void +fiops_merged_requests(struct request_queue *q, struct request *rq, + struct request *next) +{ + struct fiops_ioc *ioc = RQ_CIC(rq); + struct fiops_data *fiopsd = q->elevator->elevator_data; + + fiops_remove_request(next); + + ioc = RQ_CIC(next); + /* + * all requests of this task are merged to other tasks, delete it + * from the service tree. + */ + if (fiops_ioc_on_rr(ioc) && RB_EMPTY_ROOT(&ioc->sort_list)) + fiops_del_ioc_rr(fiopsd, ioc); +} + +static int fiops_allow_merge(struct request_queue *q, struct request *rq, + struct bio *bio) +{ + struct fiops_data *fiopsd = q->elevator->elevator_data; + struct fiops_ioc *cic; + + /* + * Lookup the ioc that this bio will be queued with. Allow + * merge only if rq is queued there. + */ + cic = fiops_cic_lookup(fiopsd, current->io_context); + + return cic == RQ_CIC(rq); +} + +static void fiops_exit_queue(struct elevator_queue *e) +{ + struct fiops_data *fiopsd = e->elevator_data; + + cancel_work_sync(&fiopsd->unplug_work); + + kfree(fiopsd); +} + +static void fiops_kick_queue(struct work_struct *work) +{ + struct fiops_data *fiopsd = + container_of(work, struct fiops_data, unplug_work); + struct request_queue *q = fiopsd->queue; + + spin_lock_irq(q->queue_lock); + __blk_run_queue(q); + spin_unlock_irq(q->queue_lock); +} + +static void *fiops_init_queue(struct request_queue *q) +{ + struct fiops_data *fiopsd; + int i; + + fiopsd = kzalloc_node(sizeof(*fiopsd), GFP_KERNEL, q->node); + if (!fiopsd) + return NULL; + + fiopsd->queue = q; + + for (i = IDLE_WORKLOAD; i <= RT_WORKLOAD; i++) + fiopsd->service_tree[i] = FIOPS_RB_ROOT; + + INIT_WORK(&fiopsd->unplug_work, fiops_kick_queue); + + fiopsd->read_scale = VIOS_READ_SCALE; + fiopsd->write_scale = VIOS_WRITE_SCALE; + fiopsd->sync_scale = VIOS_SYNC_SCALE; + fiopsd->async_scale = VIOS_ASYNC_SCALE; + + return fiopsd; +} + +static void fiops_init_icq(struct io_cq *icq) +{ + struct fiops_data *fiopsd = icq->q->elevator->elevator_data; + struct fiops_ioc *ioc = icq_to_cic(icq); + + RB_CLEAR_NODE(&ioc->rb_node); + INIT_LIST_HEAD(&ioc->fifo); + ioc->sort_list = RB_ROOT; + + ioc->fiopsd = fiopsd; + + ioc->pid = current->pid; + fiops_mark_ioc_prio_changed(ioc); +} + +/* + * sysfs parts below --> + */ +static ssize_t +fiops_var_show(unsigned int var, char *page) +{ + return sprintf(page, "%d\n", var); +} + +static ssize_t +fiops_var_store(unsigned int *var, const char *page, size_t count) +{ + char *p = (char *) page; + + *var = simple_strtoul(p, &p, 10); + return count; +} + +#define SHOW_FUNCTION(__FUNC, __VAR) \ +static ssize_t __FUNC(struct elevator_queue *e, char *page) \ +{ \ + struct fiops_data *fiopsd = e->elevator_data; \ + return fiops_var_show(__VAR, (page)); \ +} +SHOW_FUNCTION(fiops_read_scale_show, fiopsd->read_scale); +SHOW_FUNCTION(fiops_write_scale_show, fiopsd->write_scale); +SHOW_FUNCTION(fiops_sync_scale_show, fiopsd->sync_scale); +SHOW_FUNCTION(fiops_async_scale_show, fiopsd->async_scale); +#undef SHOW_FUNCTION + +#define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX) \ +static ssize_t __FUNC(struct elevator_queue *e, const char *page, size_t count) \ +{ \ + struct fiops_data *fiopsd = e->elevator_data; \ + unsigned int __data; \ + int ret = fiops_var_store(&__data, (page), count); \ + if (__data < (MIN)) \ + __data = (MIN); \ + else if (__data > (MAX)) \ + __data = (MAX); \ + *(__PTR) = __data; \ + return ret; \ +} +STORE_FUNCTION(fiops_read_scale_store, &fiopsd->read_scale, 1, 100); +STORE_FUNCTION(fiops_write_scale_store, &fiopsd->write_scale, 1, 100); +STORE_FUNCTION(fiops_sync_scale_store, &fiopsd->sync_scale, 1, 100); +STORE_FUNCTION(fiops_async_scale_store, &fiopsd->async_scale, 1, 100); +#undef STORE_FUNCTION + +#define FIOPS_ATTR(name) \ + __ATTR(name, S_IRUGO|S_IWUSR, fiops_##name##_show, fiops_##name##_store) + +static struct elv_fs_entry fiops_attrs[] = { + FIOPS_ATTR(read_scale), + FIOPS_ATTR(write_scale), + FIOPS_ATTR(sync_scale), + FIOPS_ATTR(async_scale), + __ATTR_NULL +}; + +static struct elevator_type iosched_fiops = { + .ops = { + .elevator_merge_fn = fiops_merge, + .elevator_merged_fn = fiops_merged_request, + .elevator_merge_req_fn = fiops_merged_requests, + .elevator_allow_merge_fn = fiops_allow_merge, + .elevator_dispatch_fn = fiops_dispatch_requests, + .elevator_add_req_fn = fiops_insert_request, + .elevator_completed_req_fn = fiops_completed_request, + .elevator_former_req_fn = elv_rb_former_request, + .elevator_latter_req_fn = elv_rb_latter_request, + .elevator_init_icq_fn = fiops_init_icq, + .elevator_init_fn = fiops_init_queue, + .elevator_exit_fn = fiops_exit_queue, + }, + .icq_size = sizeof(struct fiops_ioc), + .icq_align = __alignof__(struct fiops_ioc), + .elevator_attrs = fiops_attrs, + .elevator_name = "fiops", + .elevator_owner = THIS_MODULE, +}; + +static int __init fiops_init(void) +{ + return elv_register(&iosched_fiops); +} + +static void __exit fiops_exit(void) +{ + elv_unregister(&iosched_fiops); +} + +module_init(fiops_init); +module_exit(fiops_exit); + +MODULE_AUTHOR("Jens Axboe, Shaohua Li "); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("IOPS based IO scheduler"); diff --git a/block/sio-iosched.c b/block/sio-iosched.c new file mode 100644 index 00000000000..3661a9a9207 --- /dev/null +++ b/block/sio-iosched.c @@ -0,0 +1,403 @@ +/* + * Simple IO scheduler + * Based on Noop, Deadline and V(R) IO schedulers. + * + * Copyright (C) 2012 Miguel Boton + * + * + * This algorithm does not do any kind of sorting, as it is aimed for + * aleatory access devices, but it does some basic merging. We try to + * keep minimum overhead to achieve low latency. + * + * Asynchronous and synchronous requests are not treated separately, but + * we relay on deadlines to ensure fairness. + * + */ +#include +#include +#include +#include +#include +#include + +enum { ASYNC, SYNC }; + +/* Tunables */ +static const int sync_read_expire = HZ / 2; /* max time before a sync read is submitted. */ +static const int sync_write_expire = 2 * HZ; /* max time before a sync write is submitted. */ + +static const int async_read_expire = 4 * HZ; /* ditto for async, these limits are SOFT! */ +static const int async_write_expire = 16 * HZ; /* ditto for async, these limits are SOFT! */ + +static const int writes_starved = 2; /* max times reads can starve a write */ +static const int fifo_batch = 8; /* # of sequential requests treated as one + by the above parameters. For throughput. */ + +/* Elevator data */ +struct sio_data { + /* Request queues */ + struct list_head fifo_list[2][2]; + + /* Attributes */ + unsigned int batched; + unsigned int starved; + + /* Settings */ + int fifo_expire[2][2]; + int fifo_batch; + int writes_starved; +}; + +static void +sio_merged_requests(struct request_queue *q, struct request *rq, + struct request *next) +{ + /* + * If next expires before rq, assign its expire time to rq + * and move into next position (next will be deleted) in fifo. + */ + if (!list_empty(&rq->queuelist) && !list_empty(&next->queuelist)) { + if (time_before(rq_fifo_time(next), rq_fifo_time(rq))) { + list_move(&rq->queuelist, &next->queuelist); + rq_set_fifo_time(rq, rq_fifo_time(next)); + } + } + + /* Delete next request */ + rq_fifo_clear(next); +} + +static void +sio_add_request(struct request_queue *q, struct request *rq) +{ + struct sio_data *sd = q->elevator->elevator_data; + const int sync = rq_is_sync(rq); + const int data_dir = rq_data_dir(rq); + + /* + * Add request to the proper fifo list and set its + * expire time. + */ + rq_set_fifo_time(rq, jiffies + sd->fifo_expire[sync][data_dir]); + list_add_tail(&rq->queuelist, &sd->fifo_list[sync][data_dir]); +} + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,38) +static int +sio_queue_empty(struct request_queue *q) +{ + struct sio_data *sd = q->elevator->elevator_data; + + /* Check if fifo lists are empty */ + return list_empty(&sd->fifo_list[SYNC][READ]) && list_empty(&sd->fifo_list[SYNC][WRITE]) && + list_empty(&sd->fifo_list[ASYNC][READ]) && list_empty(&sd->fifo_list[ASYNC][WRITE]); +} +#endif + +static struct request * +sio_expired_request(struct sio_data *sd, int sync, int data_dir) +{ + struct list_head *list = &sd->fifo_list[sync][data_dir]; + struct request *rq; + + if (list_empty(list)) + return NULL; + + /* Retrieve request */ + rq = rq_entry_fifo(list->next); + + /* Request has expired */ + if (time_after(jiffies, rq_fifo_time(rq))) + return rq; + + return NULL; +} + +static struct request * +sio_choose_expired_request(struct sio_data *sd) +{ + struct request *rq; + + /* + * Check expired requests. + * Asynchronous requests have priority over synchronous. + * Write requests have priority over read. + */ + rq = sio_expired_request(sd, ASYNC, WRITE); + if (rq) + return rq; + rq = sio_expired_request(sd, ASYNC, READ); + if (rq) + return rq; + + rq = sio_expired_request(sd, SYNC, WRITE); + if (rq) + return rq; + rq = sio_expired_request(sd, SYNC, READ); + if (rq) + return rq; + + return NULL; +} + +static struct request * +sio_choose_request(struct sio_data *sd, int data_dir) +{ + struct list_head *sync = sd->fifo_list[SYNC]; + struct list_head *async = sd->fifo_list[ASYNC]; + + /* + * Retrieve request from available fifo list. + * Synchronous requests have priority over asynchronous. + * Read requests have priority over write. + */ + if (!list_empty(&sync[data_dir])) + return rq_entry_fifo(sync[data_dir].next); + if (!list_empty(&async[data_dir])) + return rq_entry_fifo(async[data_dir].next); + + if (!list_empty(&sync[!data_dir])) + return rq_entry_fifo(sync[!data_dir].next); + if (!list_empty(&async[!data_dir])) + return rq_entry_fifo(async[!data_dir].next); + + return NULL; +} + +static inline void +sio_dispatch_request(struct sio_data *sd, struct request *rq) +{ + /* + * Remove the request from the fifo list + * and dispatch it. + */ + rq_fifo_clear(rq); + elv_dispatch_add_tail(rq->q, rq); + + sd->batched++; + + if (rq_data_dir(rq)) + sd->starved = 0; + else + sd->starved++; +} + +static int +sio_dispatch_requests(struct request_queue *q, int force) +{ + struct sio_data *sd = q->elevator->elevator_data; + struct request *rq = NULL; + int data_dir = READ; + + /* + * Retrieve any expired request after a batch of + * sequential requests. + */ + if (sd->batched > sd->fifo_batch) { + sd->batched = 0; + rq = sio_choose_expired_request(sd); + } + + /* Retrieve request */ + if (!rq) { + if (sd->starved > sd->writes_starved) + data_dir = WRITE; + + rq = sio_choose_request(sd, data_dir); + if (!rq) + return 0; + } + + /* Dispatch request */ + sio_dispatch_request(sd, rq); + + return 1; +} + +static struct request * +sio_former_request(struct request_queue *q, struct request *rq) +{ + struct sio_data *sd = q->elevator->elevator_data; + const int sync = rq_is_sync(rq); + const int data_dir = rq_data_dir(rq); + + if (rq->queuelist.prev == &sd->fifo_list[sync][data_dir]) + return NULL; + + /* Return former request */ + return list_entry(rq->queuelist.prev, struct request, queuelist); +} + +static struct request * +sio_latter_request(struct request_queue *q, struct request *rq) +{ + struct sio_data *sd = q->elevator->elevator_data; + const int sync = rq_is_sync(rq); + const int data_dir = rq_data_dir(rq); + + if (rq->queuelist.next == &sd->fifo_list[sync][data_dir]) + return NULL; + + /* Return latter request */ + return list_entry(rq->queuelist.next, struct request, queuelist); +} + +static void * +sio_init_queue(struct request_queue *q) +{ + struct sio_data *sd; + + /* Allocate structure */ + sd = kmalloc_node(sizeof(*sd), GFP_KERNEL, q->node); + if (!sd) + return NULL; + + /* Initialize fifo lists */ + INIT_LIST_HEAD(&sd->fifo_list[SYNC][READ]); + INIT_LIST_HEAD(&sd->fifo_list[SYNC][WRITE]); + INIT_LIST_HEAD(&sd->fifo_list[ASYNC][READ]); + INIT_LIST_HEAD(&sd->fifo_list[ASYNC][WRITE]); + + /* Initialize data */ + sd->batched = 0; + sd->fifo_expire[SYNC][READ] = sync_read_expire; + sd->fifo_expire[SYNC][WRITE] = sync_write_expire; + sd->fifo_expire[ASYNC][READ] = async_read_expire; + sd->fifo_expire[ASYNC][WRITE] = async_write_expire; + sd->fifo_batch = fifo_batch; + + return sd; +} + +static void +sio_exit_queue(struct elevator_queue *e) +{ + struct sio_data *sd = e->elevator_data; + + BUG_ON(!list_empty(&sd->fifo_list[SYNC][READ])); + BUG_ON(!list_empty(&sd->fifo_list[SYNC][WRITE])); + BUG_ON(!list_empty(&sd->fifo_list[ASYNC][READ])); + BUG_ON(!list_empty(&sd->fifo_list[ASYNC][WRITE])); + + /* Free structure */ + kfree(sd); +} + +/* + * sysfs code + */ + +static ssize_t +sio_var_show(int var, char *page) +{ + return sprintf(page, "%d\n", var); +} + +static ssize_t +sio_var_store(int *var, const char *page, size_t count) +{ + char *p = (char *) page; + + *var = simple_strtol(p, &p, 10); + return count; +} + +#define SHOW_FUNCTION(__FUNC, __VAR, __CONV) \ +static ssize_t __FUNC(struct elevator_queue *e, char *page) \ +{ \ + struct sio_data *sd = e->elevator_data; \ + int __data = __VAR; \ + if (__CONV) \ + __data = jiffies_to_msecs(__data); \ + return sio_var_show(__data, (page)); \ +} +SHOW_FUNCTION(sio_sync_read_expire_show, sd->fifo_expire[SYNC][READ], 1); +SHOW_FUNCTION(sio_sync_write_expire_show, sd->fifo_expire[SYNC][WRITE], 1); +SHOW_FUNCTION(sio_async_read_expire_show, sd->fifo_expire[ASYNC][READ], 1); +SHOW_FUNCTION(sio_async_write_expire_show, sd->fifo_expire[ASYNC][WRITE], 1); +SHOW_FUNCTION(sio_fifo_batch_show, sd->fifo_batch, 0); +SHOW_FUNCTION(sio_writes_starved_show, sd->writes_starved, 0); +#undef SHOW_FUNCTION + +#define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV) \ +static ssize_t __FUNC(struct elevator_queue *e, const char *page, size_t count) \ +{ \ + struct sio_data *sd = e->elevator_data; \ + int __data; \ + int ret = sio_var_store(&__data, (page), count); \ + if (__data < (MIN)) \ + __data = (MIN); \ + else if (__data > (MAX)) \ + __data = (MAX); \ + if (__CONV) \ + *(__PTR) = msecs_to_jiffies(__data); \ + else \ + *(__PTR) = __data; \ + return ret; \ +} +STORE_FUNCTION(sio_sync_read_expire_store, &sd->fifo_expire[SYNC][READ], 0, INT_MAX, 1); +STORE_FUNCTION(sio_sync_write_expire_store, &sd->fifo_expire[SYNC][WRITE], 0, INT_MAX, 1); +STORE_FUNCTION(sio_async_read_expire_store, &sd->fifo_expire[ASYNC][READ], 0, INT_MAX, 1); +STORE_FUNCTION(sio_async_write_expire_store, &sd->fifo_expire[ASYNC][WRITE], 0, INT_MAX, 1); +STORE_FUNCTION(sio_fifo_batch_store, &sd->fifo_batch, 0, INT_MAX, 0); +STORE_FUNCTION(sio_writes_starved_store, &sd->writes_starved, 0, INT_MAX, 0); +#undef STORE_FUNCTION + +#define DD_ATTR(name) \ + __ATTR(name, S_IRUGO|S_IWUSR, sio_##name##_show, \ + sio_##name##_store) + +static struct elv_fs_entry sio_attrs[] = { + DD_ATTR(sync_read_expire), + DD_ATTR(sync_write_expire), + DD_ATTR(async_read_expire), + DD_ATTR(async_write_expire), + DD_ATTR(fifo_batch), + DD_ATTR(writes_starved), + __ATTR_NULL +}; + +static struct elevator_type iosched_sio = { + .ops = { + .elevator_merge_req_fn = sio_merged_requests, + .elevator_dispatch_fn = sio_dispatch_requests, + .elevator_add_req_fn = sio_add_request, +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,38) + .elevator_queue_empty_fn = sio_queue_empty, +#endif + .elevator_former_req_fn = sio_former_request, + .elevator_latter_req_fn = sio_latter_request, + .elevator_init_fn = sio_init_queue, + .elevator_exit_fn = sio_exit_queue, + }, + + .elevator_attrs = sio_attrs, + .elevator_name = "sio", + .elevator_owner = THIS_MODULE, +}; + +static int __init sio_init(void) +{ + /* Register elevator */ + elv_register(&iosched_sio); + + return 0; +} + +static void __exit sio_exit(void) +{ + /* Unregister elevator */ + elv_unregister(&iosched_sio); +} + +#ifdef CONFIG_FAST_RESUME +beforeresume_initcall(sio_init); +#else +module_init(sio_init); +#endif +module_exit(sio_exit); + +MODULE_AUTHOR("Miguel Boton"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Simple IO scheduler"); +MODULE_VERSION("0.2"); diff --git a/crypto/Kconfig b/crypto/Kconfig index 8e84225c096..2615d4cfc61 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -423,6 +423,15 @@ config CRYPTO_SHA1_SSSE3 using Supplemental SSE3 (SSSE3) instructions or Advanced Vector Extensions (AVX), when available. +config CRYPTO_SHA1_ARM + tristate "SHA1 digest algorithm (ARM-asm)" + depends on ARM + select CRYPTO_SHA1 + select CRYPTO_HASH + help + SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2) implemented + using optimized ARM assembler. + config CRYPTO_SHA256 tristate "SHA224 and SHA256 digest algorithm" select CRYPTO_HASH @@ -577,6 +586,30 @@ config CRYPTO_AES_NI_INTEL ECB, CBC, LRW, PCBC, XTS. The 64 bit version has additional acceleration for CTR. +config CRYPTO_AES_ARM + tristate "AES cipher algorithms (ARM-asm)" + depends on ARM + select CRYPTO_ALGAPI + select CRYPTO_AES + help + Use optimized AES assembler routines for ARM platforms. + + AES cipher algorithms (FIPS-197). AES uses the Rijndael + algorithm. + + Rijndael appears to be consistently a very good performer in + both hardware and software across a wide range of computing + environments regardless of its use in feedback or non-feedback + modes. Its key setup time is excellent, and its key agility is + good. Rijndael's very low memory requirements make it very well + suited for restricted-space environments, in which it also + demonstrates excellent performance. Rijndael's operations are + among the easiest to defend against power and timing attacks. + + The AES specifies three key sizes: 128, 192 and 256 bits + + See for more information. + config CRYPTO_ANUBIS tristate "Anubis cipher algorithm" select CRYPTO_ALGAPI diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index c850de4c9a1..f9f09d1ac66 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -252,7 +252,7 @@ static bool __init processor_physically_present(acpi_handle handle) return true; } -static void __cpuinit acpi_set_pdc_bits(u32 *buf) +static void acpi_set_pdc_bits(u32 *buf) { buf[0] = ACPI_PDC_REVISION_ID; buf[1] = 1; @@ -264,7 +264,7 @@ static void __cpuinit acpi_set_pdc_bits(u32 *buf) arch_acpi_set_pdc_bits(buf); } -static struct acpi_object_list *__cpuinit acpi_processor_alloc_pdc(void) +static struct acpi_object_list *acpi_processor_alloc_pdc(void) { struct acpi_object_list *obj_list; union acpi_object *obj; @@ -307,7 +307,7 @@ static struct acpi_object_list *__cpuinit acpi_processor_alloc_pdc(void) * _PDC is required for a BIOS-OS handshake for most of the newer * ACPI processor features. */ -static int __cpuinit +static int acpi_processor_eval_pdc(acpi_handle handle, struct acpi_object_list *pdc_in) { acpi_status status = AE_OK; @@ -335,7 +335,7 @@ acpi_processor_eval_pdc(acpi_handle handle, struct acpi_object_list *pdc_in) return status; } -void __cpuinit acpi_processor_set_pdc(acpi_handle handle) +void acpi_processor_set_pdc(acpi_handle handle) { struct acpi_object_list *obj_list; diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index 0734086537b..ada43215f1c 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c @@ -464,7 +464,7 @@ static struct notifier_block acpi_cpu_notifier = * acpi_cpu_soft_notify(). Getting it __cpuinit{data} is difficult, the * root cause seem to be that acpi_processor_uninstall_hotplug_notify() * is in the module_exit (__exit) func. Allowing acpi_processor_start() - * to not be in __cpuinit section, but being called from __cpuinit funcs + * to not be in section, but being called from funcs * via __ref looks like the right thing to do here. */ static __ref int acpi_processor_start(struct acpi_processor *pr) @@ -525,7 +525,7 @@ static __ref int acpi_processor_start(struct acpi_processor *pr) * (cpu_data(cpu)) values, like CPU feature flags, family, model, etc. * Such things have to be put in and set up above in acpi_processor_start() */ -static int __cpuinit acpi_processor_add(struct acpi_device *device) +static int acpi_processor_add(struct acpi_device *device) { struct acpi_processor *pr = NULL; int result = 0; diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index f3decb30223..e7ccfd690e2 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -106,9 +106,9 @@ static int set_max_cstate(const struct dmi_system_id *id) return 0; } -/* Actually this shouldn't be __cpuinitdata, would be better to fix the +/* Actually this shouldn't be, would be better to fix the callers to only run once -AK */ -static struct dmi_system_id __cpuinitdata processor_power_dmi_table[] = { +static struct dmi_system_id processor_power_dmi_table[] = { { set_max_cstate, "Clevo 5600D", { DMI_MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"), DMI_MATCH(DMI_BIOS_VERSION,"SHE845M0.86C.0013.D.0302131307")}, @@ -1227,7 +1227,7 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr) static int acpi_processor_registered; -int __cpuinit acpi_processor_power_init(struct acpi_processor *pr, +int acpi_processor_power_init(struct acpi_processor *pr, struct acpi_device *device) { acpi_status status = 0; diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index adf937bf409..32763ef3da0 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c @@ -64,7 +64,7 @@ static ssize_t __ref store_online(struct device *dev, } static DEVICE_ATTR(online, 0644, show_online, store_online); -static void __cpuinit register_cpu_control(struct cpu *cpu) +static void register_cpu_control(struct cpu *cpu) { device_create_file(&cpu->dev, &dev_attr_online); } @@ -236,7 +236,7 @@ static void cpu_device_release(struct device *dev) * * Initialize and register the CPU device. */ -int __cpuinit register_cpu(struct cpu *cpu, int num) +int register_cpu(struct cpu *cpu, int num) { int error; diff --git a/drivers/base/topology.c b/drivers/base/topology.c index ae989c57cd5..cc30237d2ec 100644 --- a/drivers/base/topology.c +++ b/drivers/base/topology.c @@ -143,21 +143,21 @@ static struct attribute_group topology_attr_group = { }; /* Add/Remove cpu_topology interface for CPU device */ -static int __cpuinit topology_add_dev(unsigned int cpu) +static int topology_add_dev(unsigned int cpu) { struct device *dev = get_cpu_device(cpu); return sysfs_create_group(&dev->kobj, &topology_attr_group); } -static void __cpuinit topology_remove_dev(unsigned int cpu) +static void topology_remove_dev(unsigned int cpu) { struct device *dev = get_cpu_device(cpu); sysfs_remove_group(&dev->kobj, &topology_attr_group); } -static int __cpuinit topology_cpu_callback(struct notifier_block *nfb, +static int topology_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { unsigned int cpu = (unsigned long)hcpu; @@ -178,7 +178,7 @@ static int __cpuinit topology_cpu_callback(struct notifier_block *nfb, return notifier_from_errno(rc); } -static int __cpuinit topology_sysfs_init(void) +static int topology_sysfs_init(void) { int cpu; int rc; diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 8032f0b033b..bec0718fde8 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile @@ -5,6 +5,7 @@ obj-y += mem.o random.o obj-$(CONFIG_TTY_PRINTK) += ttyprintk.o obj-y += misc.o +obj-$(CONFIG_FRANDOM) += frandom.o obj-$(CONFIG_ATARI_DSP56K) += dsp56k.o obj-$(CONFIG_VIRTIO_CONSOLE) += virtio_console.o obj-$(CONFIG_RAW_DRIVER) += raw.o diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig index 57f96ebbce4..5ca8bcc492b 100644 --- a/drivers/cpufreq/Kconfig +++ b/drivers/cpufreq/Kconfig @@ -109,6 +109,13 @@ config CPU_FREQ_DEFAULT_GOV_INTERACTIVE loading your cpufreq low-level hardware driver, using the 'interactive' governor for latency-sensitive workloads. +config CPU_FREQ_DEFAULT_GOV_INTELLIDEMAND + + bool "intellidemand" + select CPU_FREQ_GOV_INTELLIDEMAND + help + Use the CPUFreq governor 'intellidemand' as default. + endchoice config CPU_FREQ_GOV_PERFORMANCE @@ -206,6 +213,17 @@ config CPU_FREQ_GOV_CONSERVATIVE If in doubt, say N. +config CPU_FREQ_GOV_INTELLIDEMAND + tristate "'intellidemand' cpufreq governor" + depends on CPU_FREQ + +config CPUFREQ_ID_PERFLOCK + bool "Intellidemand Performance Lock" + depends on CPU_FREQ_GOV_INTELLIDEMAND + default n + help + Minimum CPU performance lock for Intellidemand governor + menu "x86 CPU frequency scaling drivers" depends on X86 source "drivers/cpufreq/Kconfig.x86" diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index 46756c51847..08ee9535fec 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -10,6 +10,7 @@ obj-$(CONFIG_CPU_FREQ_GOV_USERSPACE) += cpufreq_userspace.o obj-$(CONFIG_CPU_FREQ_GOV_ONDEMAND) += cpufreq_ondemand.o obj-$(CONFIG_CPU_FREQ_GOV_CONSERVATIVE) += cpufreq_conservative.o obj-$(CONFIG_CPU_FREQ_GOV_INTERACTIVE) += cpufreq_interactive.o +obj-$(CONFIG_CPU_FREQ_GOV_INTELLIDEMAND) += cpufreq_intellidemand.o # CPUfreq cross-arch helpers obj-$(CONFIG_CPU_FREQ_TABLE) += freq_table.o diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 5df0a7de6bf..527022d5910 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -644,6 +644,68 @@ static ssize_t show_bios_limit(struct cpufreq_policy *policy, char *buf) return sprintf(buf, "%u\n", policy->cpuinfo.max_freq); } +#ifdef CONFIG_CPU_VOLTAGE_TABLE + +extern ssize_t acpuclk_get_vdd_levels_str(char *buf); +extern void acpuclk_set_vdd(unsigned acpu_khz, int vdd); + +static ssize_t show_vdd_levels(struct kobject *a, struct attribute *b, char *buf) { + return acpuclk_get_vdd_levels_str(buf); +} + +static ssize_t store_vdd_levels(struct kobject *a, struct attribute *b, const char *buf, size_t count) { + + int i = 0, j; + int pair[2] = { 0, 0 }; + int sign = 0; + + if (count < 1) + return 0; + + if (buf[0] == '-') { + sign = -1; + i++; + } + else if (buf[0] == '+') { + sign = 1; + i++; + } + + for (j = 0; i < count; i++) { + + char c = buf[i]; + + if ((c >= '0') && (c <= '9')) { + pair[j] *= 10; + pair[j] += (c - '0'); + } + else if ((c == ' ') || (c == '\t')) { + if (pair[j] != 0) { + j++; + + if ((sign != 0) || (j > 1)) + break; + } + } + else + break; + } + + if (sign != 0) { + if (pair[0] > 0) + acpuclk_set_vdd(0, sign * pair[0]); + } + else { + if ((pair[0] > 0) && (pair[1] > 0)) + acpuclk_set_vdd((unsigned)pair[0], pair[1]); + else + return -EINVAL; + } + return count; +} + +#endif /* CONFIG_CPU_VOLTAGE_TABLE */ + cpufreq_freq_attr_ro_perm(cpuinfo_cur_freq, 0400); cpufreq_freq_attr_ro(cpuinfo_min_freq); cpufreq_freq_attr_ro(cpuinfo_max_freq); @@ -660,6 +722,9 @@ cpufreq_freq_attr_rw(scaling_max_freq); cpufreq_freq_attr_rw(scaling_governor); cpufreq_freq_attr_rw(scaling_setspeed); cpufreq_freq_attr_rw(dvfs_test); +#ifdef CONFIG_CPU_VOLTAGE_TABLE +define_one_global_rw(vdd_levels); +#endif static struct attribute *default_attrs[] = { &cpuinfo_min_freq.attr, @@ -678,6 +743,18 @@ static struct attribute *default_attrs[] = { NULL }; +#ifdef CONFIG_CPU_VOLTAGE_TABLE +static struct attribute *vddtbl_attrs[] = { + &vdd_levels.attr, + NULL +}; + +static struct attribute_group vddtbl_attr_group = { + .attrs = vddtbl_attrs, + .name = "vdd_table", +}; +#endif /* CONFIG_CPU_VOLTAGE_TABLE */ + struct kobject *cpufreq_global_kobject; EXPORT_SYMBOL(cpufreq_global_kobject); @@ -1031,6 +1108,13 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) pr_debug("initialization failed\n"); goto err_unlock_policy; } + + /* + * affected cpus must always be the one, which are online. We aren't + * managing offline cpus here. + */ + cpumask_and(policy->cpus, policy->cpus, cpu_online_mask); + policy->user_policy.min = policy->min; policy->user_policy.max = policy->max; @@ -1135,10 +1219,10 @@ static int __cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif #ifdef CONFIG_HOTPLUG_CPU strncpy(per_cpu(cpufreq_policy_save, cpu).gov, data->governor->name, CPUFREQ_NAME_LEN); - per_cpu(cpufreq_policy_save, cpu).min = data->min; - per_cpu(cpufreq_policy_save, cpu).max = data->max; - pr_debug("Saving CPU%d policy min %d and max %d\n", - cpu, data->min, data->max); + per_cpu(cpufreq_policy_save, cpu).min = data->user_policy.min; + per_cpu(cpufreq_policy_save, cpu).max = data->user_policy.max; + pr_debug("Saving CPU%d user policy min %d and max %d\n", + cpu, data->user_policy.min, data->user_policy.max); #endif /* if we have other CPUs still registered, we need to unlink them, @@ -1164,9 +1248,11 @@ static int __cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif #ifdef CONFIG_HOTPLUG_CPU strncpy(per_cpu(cpufreq_policy_save, j).gov, data->governor->name, CPUFREQ_NAME_LEN); - per_cpu(cpufreq_policy_save, j).min = data->min; - per_cpu(cpufreq_policy_save, j).max = data->max; - pr_debug("Saving CPU%d policy min %d and max %d\n", + per_cpu(cpufreq_policy_save, j).min + = data->user_policy.min; + per_cpu(cpufreq_policy_save, j).max + = data->user_policy.max; + pr_debug("Saving CPU%d user policy min %d and max %d\n", j, data->min, data->max); #endif cpu_dev = get_cpu_device(j); @@ -1873,7 +1959,7 @@ int cpufreq_update_policy(unsigned int cpu) } EXPORT_SYMBOL(cpufreq_update_policy); -static int __cpuinit cpufreq_cpu_callback(struct notifier_block *nfb, +static int cpufreq_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { unsigned int cpu = (unsigned long)hcpu; @@ -2014,6 +2100,9 @@ EXPORT_SYMBOL_GPL(cpufreq_unregister_driver); static int __init cpufreq_core_init(void) { int cpu; +#ifdef CONFIG_CPU_VOLTAGE_TABLE + int rc; +#endif /* CONFIG_CPU_VOLTAGE_TABLE */ if (cpufreq_disabled()) return -ENODEV; @@ -2026,6 +2115,9 @@ static int __init cpufreq_core_init(void) cpufreq_global_kobject = kobject_create_and_add("cpufreq", &cpu_subsys.dev_root->kobj); BUG_ON(!cpufreq_global_kobject); register_syscore_ops(&cpufreq_syscore_ops); +#ifdef CONFIG_CPU_VOLTAGE_TABLE + rc = sysfs_create_group(cpufreq_global_kobject, &vddtbl_attr_group); +#endif /* CONFIG_CPU_VOLTAGE_TABLE */ return 0; } diff --git a/drivers/cpufreq/cpufreq_intellidemand.c b/drivers/cpufreq/cpufreq_intellidemand.c new file mode 100644 index 00000000000..cfb47ed1f62 --- /dev/null +++ b/drivers/cpufreq/cpufreq_intellidemand.c @@ -0,0 +1,2041 @@ +/* + * drivers/cpufreq/cpufreq_intellidemand.c + * + * Copyright (C) 2001 Russell King + * (C) 2003 Venkatesh Pallipadi . + * Jun Nakajima + * (C) 2012 Paul Reioux + * (C) 2013 Paul Reioux + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_EARLYSUSPEND +#include +#endif +#include + +#include +#include + +#define INTELLIDEMAND_MAJOR_VERSION 4 +#define INTELLIDEMAND_MINOR_VERSION 2 + +/* + * dbs is used in this file as a shortform for demandbased switching + * It helps to keep variable names smaller, simpler + */ + +#define DEF_FREQUENCY_DOWN_DIFFERENTIAL (10) +#define DEF_FREQUENCY_UP_THRESHOLD (75) +#define DEF_SAMPLING_DOWN_FACTOR (1) +#define BOOSTED_SAMPLING_DOWN_FACTOR (10) +#define MAX_SAMPLING_DOWN_FACTOR (100000) +#define MICRO_FREQUENCY_DOWN_DIFFERENTIAL (3) +#define MICRO_FREQUENCY_UP_THRESHOLD (75) +#define MICRO_FREQUENCY_MIN_SAMPLE_RATE (15000) +#define MIN_FREQUENCY_UP_THRESHOLD (11) +#define MAX_FREQUENCY_UP_THRESHOLD (100) +#define MIN_FREQUENCY_DOWN_DIFFERENTIAL (1) +#define DEFAULT_FREQ_BOOST_TIME (2500000) +#define DEF_SAMPLING_RATE (50000) +#define BOOSTED_SAMPLING_RATE (15000) +#define DBS_INPUT_EVENT_MIN_FREQ (1026000) +#define DBS_SYNC_FREQ (702000) +#define DBS_OPTIMAL_FREQ (1458000) + +#ifdef CONFIG_CPUFREQ_ID_PERFLOCK +#define DBS_PERFLOCK_MIN_FREQ (594000) +#endif + +static u64 freq_boosted_time; +/* + * The polling frequency of this governor depends on the capability of + * the processor. Default polling frequency is 1000 times the transition + * latency of the processor. The governor will work on any processor with + * transition latency <= 10mS, using appropriate sampling + * rate. + * For CPUs with transition latency > 10mS (mostly drivers with CPUFREQ_ETERNAL) + * this governor will not work. + * All times here are in uS. + */ +#define MIN_SAMPLING_RATE_RATIO (2) + +static unsigned int min_sampling_rate; +#ifdef CONFIG_EARLYSUSPEND +static unsigned long stored_sampling_rate; +#endif + +#define LATENCY_MULTIPLIER (1000) +#define MIN_LATENCY_MULTIPLIER (20) +#define TRANSITION_LATENCY_LIMIT (10 * 1000 * 1000) + +#define POWERSAVE_BIAS_MAXLEVEL (1000) +#define POWERSAVE_BIAS_MINLEVEL (-1000) + +/* have the timer rate booted for this much time 2.5s*/ +#define TIMER_RATE_BOOST_TIME 2500000 +static int sampling_rate_boosted; +static u64 sampling_rate_boosted_time; +static unsigned int current_sampling_rate; + +#ifdef CONFIG_CPUFREQ_ID_PERFLOCK +static unsigned int saved_policy_min = 0; +#endif + +static void do_dbs_timer(struct work_struct *work); +static int cpufreq_governor_dbs(struct cpufreq_policy *policy, + unsigned int event); + +#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_INTELLIDEMAND +static +#endif +struct cpufreq_governor cpufreq_gov_intellidemand = { + .name = "intellidemand", + .governor = cpufreq_governor_dbs, + .max_transition_latency = TRANSITION_LATENCY_LIMIT, + .owner = THIS_MODULE, +}; + +/* Sampling types */ +enum {DBS_NORMAL_SAMPLE, DBS_SUB_SAMPLE}; + +struct cpu_dbs_info_s { + cputime64_t prev_cpu_idle; + cputime64_t prev_cpu_iowait; + cputime64_t prev_cpu_wall; + cputime64_t prev_cpu_nice; + struct cpufreq_policy *cur_policy; + struct delayed_work work; + struct cpufreq_frequency_table *freq_table; + unsigned int freq_lo; + unsigned int freq_lo_jiffies; + unsigned int freq_hi_jiffies; + unsigned int rate_mult; + unsigned int prev_load; + unsigned int max_load; + int cpu; + unsigned int sample_type:1; + /* + * percpu mutex that serializes governor limit change with + * do_dbs_timer invocation. We do not want do_dbs_timer to run + * when user is changing the governor or limits. + */ + struct mutex timer_mutex; +}; +static DEFINE_PER_CPU(struct cpu_dbs_info_s, id_cpu_dbs_info); + +static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info); +static inline void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info); + +static unsigned int dbs_enable; /* number of CPUs using this policy */ + +/* + * dbs_mutex protects dbs_enable in governor start/stop. + */ +static DEFINE_MUTEX(dbs_mutex); + +static struct workqueue_struct *input_wq; + +struct dbs_work_struct { + struct work_struct work; + unsigned int cpu; +}; + +static DEFINE_PER_CPU(struct dbs_work_struct, dbs_refresh_work); + +static struct dbs_tuners { + unsigned int sampling_rate; + unsigned int up_threshold; + unsigned int up_threshold_multi_core; + unsigned int down_differential; + unsigned int down_differential_multi_core; + unsigned int optimal_freq; + unsigned int up_threshold_any_cpu_load; + unsigned int sync_freq; + unsigned int ignore_nice; + unsigned int sampling_down_factor; + int powersave_bias; + unsigned int io_is_busy; + unsigned int boosted; + unsigned int freq_boost_time; + unsigned int boostfreq; + unsigned int two_phase_freq; +} dbs_tuners_ins = { + .up_threshold_multi_core = DEF_FREQUENCY_UP_THRESHOLD, + .up_threshold = DEF_FREQUENCY_UP_THRESHOLD, + .sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR, + .down_differential = DEF_FREQUENCY_DOWN_DIFFERENTIAL, + .down_differential_multi_core = MICRO_FREQUENCY_DOWN_DIFFERENTIAL, + .up_threshold_any_cpu_load = DEF_FREQUENCY_UP_THRESHOLD, + .ignore_nice = 0, + .powersave_bias = 0, + .sync_freq = DBS_SYNC_FREQ, + .optimal_freq = DBS_OPTIMAL_FREQ, + .freq_boost_time = DEFAULT_FREQ_BOOST_TIME, + .two_phase_freq = 0, +}; + +static inline cputime64_t get_cpu_idle_time_jiffy(unsigned int cpu, + cputime64_t *wall) +{ + u64 idle_time; + u64 cur_wall_time; + u64 busy_time; + + cur_wall_time = jiffies64_to_cputime64(get_jiffies_64()); + + busy_time = kcpustat_cpu(cpu).cpustat[CPUTIME_USER]; + busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_SYSTEM]; + busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_IRQ]; + busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_SOFTIRQ]; + busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_STEAL]; + busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_NICE]; + + idle_time = cur_wall_time - busy_time; + if (wall) + *wall = jiffies_to_usecs(cur_wall_time); + + return jiffies_to_usecs(idle_time); +} + +static inline cputime64_t get_cpu_idle_time(unsigned int cpu, cputime64_t *wall) +{ + u64 idle_time = get_cpu_idle_time_us(cpu, NULL); + + if (idle_time == -1ULL) + return get_cpu_idle_time_jiffy(cpu, wall); + else + idle_time += get_cpu_iowait_time_us(cpu, wall); + + return idle_time; +} + +static inline cputime64_t get_cpu_iowait_time(unsigned int cpu, cputime64_t *wall) +{ + u64 iowait_time = get_cpu_iowait_time_us(cpu, wall); + + if (iowait_time == -1ULL) + return 0; + + return iowait_time; +} + +/* + * Find right freq to be set now with powersave_bias on. + * Returns the freq_hi to be used right now and will set freq_hi_jiffies, + * freq_lo, and freq_lo_jiffies in percpu area for averaging freqs. + */ +static unsigned int powersave_bias_target(struct cpufreq_policy *policy, + unsigned int freq_next, + unsigned int relation) +{ + unsigned int freq_req, freq_avg; + unsigned int freq_hi, freq_lo; + unsigned int index = 0; + unsigned int jiffies_total, jiffies_hi, jiffies_lo; + int freq_reduc; + struct cpu_dbs_info_s *dbs_info = &per_cpu(id_cpu_dbs_info, + policy->cpu); + + if (!dbs_info->freq_table) { + dbs_info->freq_lo = 0; + dbs_info->freq_lo_jiffies = 0; + return freq_next; + } + + cpufreq_frequency_table_target(policy, dbs_info->freq_table, freq_next, + relation, &index); + freq_req = dbs_info->freq_table[index].frequency; + freq_reduc = freq_req * dbs_tuners_ins.powersave_bias / 1000; + freq_avg = freq_req - freq_reduc; + + /* Find freq bounds for freq_avg in freq_table */ + index = 0; + cpufreq_frequency_table_target(policy, dbs_info->freq_table, freq_avg, + CPUFREQ_RELATION_H, &index); + freq_lo = dbs_info->freq_table[index].frequency; + index = 0; + cpufreq_frequency_table_target(policy, dbs_info->freq_table, freq_avg, + CPUFREQ_RELATION_L, &index); + freq_hi = dbs_info->freq_table[index].frequency; + + /* Find out how long we have to be in hi and lo freqs */ + if (freq_hi == freq_lo) { + dbs_info->freq_lo = 0; + dbs_info->freq_lo_jiffies = 0; + return freq_lo; + } + jiffies_total = usecs_to_jiffies(dbs_tuners_ins.sampling_rate); + jiffies_hi = (freq_avg - freq_lo) * jiffies_total; + jiffies_hi += ((freq_hi - freq_lo) / 2); + jiffies_hi /= (freq_hi - freq_lo); + jiffies_lo = jiffies_total - jiffies_hi; + dbs_info->freq_lo = freq_lo; + dbs_info->freq_lo_jiffies = jiffies_lo; + dbs_info->freq_hi_jiffies = jiffies_hi; + return freq_hi; +} + +static int intellidemand_powersave_bias_setspeed(struct cpufreq_policy *policy, + struct cpufreq_policy *altpolicy, + int level) +{ + if (level == POWERSAVE_BIAS_MAXLEVEL) { + /* maximum powersave; set to lowest frequency */ + __cpufreq_driver_target(policy, + (altpolicy) ? altpolicy->min : policy->min, + CPUFREQ_RELATION_L); + return 1; + } else if (level == POWERSAVE_BIAS_MINLEVEL) { + /* minimum powersave; set to highest frequency */ + __cpufreq_driver_target(policy, + (altpolicy) ? altpolicy->max : policy->max, + CPUFREQ_RELATION_H); + return 1; + } + return 0; +} + +static void intellidemand_powersave_bias_init_cpu(int cpu) +{ + struct cpu_dbs_info_s *dbs_info = &per_cpu(id_cpu_dbs_info, cpu); + dbs_info->freq_table = cpufreq_frequency_get_table(cpu); + dbs_info->freq_lo = 0; +} + +static void intellidemand_powersave_bias_init(void) +{ + int i; + for_each_online_cpu(i) { + intellidemand_powersave_bias_init_cpu(i); + } +} + +/************************** sysfs interface ************************/ + +static ssize_t show_sampling_rate_min(struct kobject *kobj, + struct attribute *attr, char *buf) +{ + return sprintf(buf, "%u\n", min_sampling_rate); +} + +define_one_global_ro(sampling_rate_min); + +/* cpufreq_intellidemand Governor Tunables */ +#define show_one(file_name, object) \ +static ssize_t show_##file_name \ +(struct kobject *kobj, struct attribute *attr, char *buf) \ +{ \ + return sprintf(buf, "%u\n", dbs_tuners_ins.object); \ +} +show_one(sampling_rate, sampling_rate); +show_one(io_is_busy, io_is_busy); +show_one(up_threshold, up_threshold); +show_one(up_threshold_multi_core, up_threshold_multi_core); +show_one(down_differential, down_differential); +show_one(sampling_down_factor, sampling_down_factor); +show_one(ignore_nice_load, ignore_nice); +show_one(optimal_freq, optimal_freq); +show_one(up_threshold_any_cpu_load, up_threshold_any_cpu_load); +show_one(sync_freq, sync_freq); +show_one(boostpulse, boosted); +show_one(boosttime, freq_boost_time); +show_one(boostfreq, boostfreq); +show_one(two_phase_freq, two_phase_freq); + +#ifdef CONFIG_CPUFREQ_LIMIT_MAX_FREQ +void set_lmf_browsing_state(bool onOff); +void set_lmf_active_max_freq(unsigned long freq); +void set_lmf_inactive_max_freq(unsigned long freq); +void set_lmf_active_load(unsigned long freq); +void set_lmf_inactive_load(unsigned long freq); +bool get_lmf_browsing_state(void); +unsigned long get_lmf_active_max_freq(void); +unsigned long get_lmf_inactive_max_freq(void); +unsigned long get_lmf_active_load(void); +unsigned long get_lmf_inactive_load(void); + +static ssize_t show_lmf_browser(struct kobject *kobj, + struct attribute *attr, char *buf) +{ + return sprintf(buf, "%u\n", get_lmf_browsing_state()); +} + +static ssize_t show_lmf_active_max_freq(struct kobject *kobj, + struct attribute *attr, char *buf) +{ + return sprintf(buf, "%ld\n", get_lmf_active_max_freq()); +} + +static ssize_t show_lmf_inactive_max_freq(struct kobject *kobj, + struct attribute *attr, char *buf) +{ + return sprintf(buf, "%ld\n", get_lmf_inactive_max_freq()); +} + +static ssize_t show_lmf_active_load(struct kobject *kobj, + struct attribute *attr, char *buf) +{ + return sprintf(buf, "%ld\n", get_lmf_active_load()); +} + +static ssize_t show_lmf_inactive_load(struct kobject *kobj, + struct attribute *attr, char *buf) +{ + return sprintf(buf, "%ld\n", get_lmf_inactive_load()); +} +#endif + +static ssize_t show_powersave_bias +(struct kobject *kobj, struct attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%d\n", dbs_tuners_ins.powersave_bias); +} + +static ssize_t store_boosttime(struct kobject *kobj, struct attribute *attr, + const char *buf, size_t count) +{ + unsigned int input; + int ret; + + ret = sscanf(buf, "%u", &input); + if (ret != 1) + return -EINVAL; + + dbs_tuners_ins.freq_boost_time = input; + return count; +} + +static ssize_t store_boostpulse(struct kobject *kobj, struct attribute *attr, + const char *buf, size_t count) +{ + int ret; + unsigned long val; + + ret = kstrtoul(buf, 0, &val); + if (ret < 0) { + pr_err("Bad Boost reqeust!\n"); + return ret; + } + + //pr_info("Boost requested!\n"); + + dbs_tuners_ins.boosted = 1; + freq_boosted_time = ktime_to_us(ktime_get()); + + if (sampling_rate_boosted) { + sampling_rate_boosted = 0; + dbs_tuners_ins.sampling_rate = current_sampling_rate; + //pr_info("Boosted Sampling rate %u\n", current_sampling_rate); + } + return count; +} + +static ssize_t store_boostfreq(struct kobject *a, struct attribute *b, + const char *buf, size_t count) +{ + unsigned int input; + int ret; + + ret = sscanf(buf, "%u", &input); + if (ret != 1) + return -EINVAL; + dbs_tuners_ins.boostfreq = input; + return count; +} + +/** + * update_sampling_rate - update sampling rate effective immediately if needed. + * @new_rate: new sampling rate + * + * If new rate is smaller than the old, simply updaing + * dbs_tuners_int.sampling_rate might not be appropriate. For example, + * if the original sampling_rate was 1 second and the requested new sampling + * rate is 10 ms because the user needs immediate reaction from ondemand + * governor, but not sure if higher frequency will be required or not, + * then, the governor may change the sampling rate too late; up to 1 second + * later. Thus, if we are reducing the sampling rate, we need to make the + * new value effective immediately. + */ +static void update_sampling_rate(unsigned int new_rate) +{ + int cpu; + + dbs_tuners_ins.sampling_rate = new_rate + = max(new_rate, min_sampling_rate); + + for_each_online_cpu(cpu) { + struct cpufreq_policy *policy; + struct cpu_dbs_info_s *dbs_info; + unsigned long next_sampling, appointed_at; + + policy = cpufreq_cpu_get(cpu); + if (!policy) + continue; + dbs_info = &per_cpu(id_cpu_dbs_info, policy->cpu); + cpufreq_cpu_put(policy); + + mutex_lock(&dbs_info->timer_mutex); + + if (!delayed_work_pending(&dbs_info->work)) { + mutex_unlock(&dbs_info->timer_mutex); + continue; + } + + next_sampling = jiffies + usecs_to_jiffies(new_rate); + appointed_at = dbs_info->work.timer.expires; + + + if (time_before(next_sampling, appointed_at)) { + + mutex_unlock(&dbs_info->timer_mutex); + cancel_delayed_work_sync(&dbs_info->work); + mutex_lock(&dbs_info->timer_mutex); + + schedule_delayed_work_on(dbs_info->cpu, &dbs_info->work, + usecs_to_jiffies(new_rate)); + + } + mutex_unlock(&dbs_info->timer_mutex); + } +} + +static ssize_t store_sampling_rate(struct kobject *a, struct attribute *b, + const char *buf, size_t count) +{ + unsigned int input; + int ret; + ret = sscanf(buf, "%u", &input); + if (ret != 1) + return -EINVAL; + update_sampling_rate(input); + current_sampling_rate = dbs_tuners_ins.sampling_rate; + return count; +} + +static ssize_t store_two_phase_freq(struct kobject *a, struct attribute *b, + const char *buf, size_t count) +{ + unsigned int input; + int ret; + ret = sscanf(buf, "%u", &input); + if (ret != 1) + return -EINVAL; + + dbs_tuners_ins.two_phase_freq = input; + + return count; +} + +static ssize_t store_sync_freq(struct kobject *a, struct attribute *b, + const char *buf, size_t count) +{ + unsigned int input; + int ret; + + ret = sscanf(buf, "%u", &input); + if (ret != 1) + return -EINVAL; + dbs_tuners_ins.sync_freq = input; + return count; +} + +static ssize_t store_io_is_busy(struct kobject *a, struct attribute *b, + const char *buf, size_t count) +{ + unsigned int input; + int ret; + + ret = sscanf(buf, "%u", &input); + if (ret != 1) + return -EINVAL; + dbs_tuners_ins.io_is_busy = !!input; + return count; +} + +static ssize_t store_optimal_freq(struct kobject *a, struct attribute *b, + const char *buf, size_t count) +{ + unsigned int input; + int ret; + + ret = sscanf(buf, "%u", &input); + if (ret != 1) + return -EINVAL; + dbs_tuners_ins.optimal_freq = input; + return count; +} + +static ssize_t store_up_threshold(struct kobject *a, struct attribute *b, + const char *buf, size_t count) +{ + unsigned int input; + int ret; + ret = sscanf(buf, "%u", &input); + + if (ret != 1 || input > MAX_FREQUENCY_UP_THRESHOLD || + input < MIN_FREQUENCY_UP_THRESHOLD) { + return -EINVAL; + } + dbs_tuners_ins.up_threshold = input; + return count; +} + +static ssize_t store_up_threshold_multi_core(struct kobject *a, + struct attribute *b, const char *buf, size_t count) +{ + unsigned int input; + int ret; + ret = sscanf(buf, "%u", &input); + + if (ret != 1 || input > MAX_FREQUENCY_UP_THRESHOLD || + input < MIN_FREQUENCY_UP_THRESHOLD) { + return -EINVAL; + } + dbs_tuners_ins.up_threshold_multi_core = input; + return count; +} + +static ssize_t store_up_threshold_any_cpu_load(struct kobject *a, + struct attribute *b, const char *buf, size_t count) +{ + unsigned int input; + int ret; + ret = sscanf(buf, "%u", &input); + + if (ret != 1 || input > MAX_FREQUENCY_UP_THRESHOLD || + input < MIN_FREQUENCY_UP_THRESHOLD) { + return -EINVAL; + } + dbs_tuners_ins.up_threshold_any_cpu_load = input; + return count; +} + +static ssize_t store_down_differential(struct kobject *a, struct attribute *b, + const char *buf, size_t count) +{ + unsigned int input; + int ret; + ret = sscanf(buf, "%u", &input); + + if (ret != 1 || input >= dbs_tuners_ins.up_threshold || + input < MIN_FREQUENCY_DOWN_DIFFERENTIAL) { + return -EINVAL; + } + + dbs_tuners_ins.down_differential = input; + + return count; +} + +static ssize_t store_sampling_down_factor(struct kobject *a, + struct attribute *b, const char *buf, size_t count) +{ + unsigned int input, j; + int ret; + ret = sscanf(buf, "%u", &input); + + if (ret != 1 || input > MAX_SAMPLING_DOWN_FACTOR || input < 1) + return -EINVAL; + dbs_tuners_ins.sampling_down_factor = input; + + /* Reset down sampling multiplier in case it was active */ + for_each_online_cpu(j) { + struct cpu_dbs_info_s *dbs_info; + dbs_info = &per_cpu(id_cpu_dbs_info, j); + dbs_info->rate_mult = 1; + } + return count; +} + +static ssize_t store_ignore_nice_load(struct kobject *a, struct attribute *b, + const char *buf, size_t count) +{ + unsigned int input; + int ret; + + unsigned int j; + + ret = sscanf(buf, "%u", &input); + if (ret != 1) + return -EINVAL; + + if (input > 1) + input = 1; + + if (input == dbs_tuners_ins.ignore_nice) { /* nothing to do */ + return count; + } + dbs_tuners_ins.ignore_nice = input; + + /* we need to re-evaluate prev_cpu_idle */ + for_each_online_cpu(j) { + struct cpu_dbs_info_s *dbs_info; + dbs_info = &per_cpu(id_cpu_dbs_info, j); + dbs_info->prev_cpu_idle = get_cpu_idle_time(j, + &dbs_info->prev_cpu_wall); + if (dbs_tuners_ins.ignore_nice) + dbs_info->prev_cpu_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE]; + } + return count; +} + +static ssize_t store_powersave_bias(struct kobject *a, struct attribute *b, + const char *buf, size_t count) +{ + int input = 0; + int bypass = 0; + int ret, cpu, reenable_timer, j; + struct cpu_dbs_info_s *dbs_info; + + struct cpumask cpus_timer_done; + cpumask_clear(&cpus_timer_done); + + ret = sscanf(buf, "%d", &input); + + if (ret != 1) + return -EINVAL; + + if (input >= POWERSAVE_BIAS_MAXLEVEL) { + input = POWERSAVE_BIAS_MAXLEVEL; + bypass = 1; + } else if (input <= POWERSAVE_BIAS_MINLEVEL) { + input = POWERSAVE_BIAS_MINLEVEL; + bypass = 1; + } + + if (input == dbs_tuners_ins.powersave_bias) { + /* no change */ + return count; + } + + reenable_timer = ((dbs_tuners_ins.powersave_bias == + POWERSAVE_BIAS_MAXLEVEL) || + (dbs_tuners_ins.powersave_bias == + POWERSAVE_BIAS_MINLEVEL)); + + dbs_tuners_ins.powersave_bias = input; + if (!bypass) { + if (reenable_timer) { + /* reinstate dbs timer */ + for_each_online_cpu(cpu) { + if (lock_policy_rwsem_write(cpu) < 0) + continue; + + dbs_info = &per_cpu(id_cpu_dbs_info, cpu); + + for_each_cpu(j, &cpus_timer_done) { + if (!dbs_info->cur_policy) { + printk(KERN_ERR + "%s Dbs policy is NULL\n", + __func__); + goto skip_this_cpu; + } + if (cpumask_test_cpu(j, dbs_info-> + cur_policy->cpus)) + goto skip_this_cpu; + } + + cpumask_set_cpu(cpu, &cpus_timer_done); + if (dbs_info->cur_policy) { + /* restart dbs timer */ + dbs_timer_init(dbs_info); + } +skip_this_cpu: + unlock_policy_rwsem_write(cpu); + } + } + intellidemand_powersave_bias_init(); + } else { + /* running at maximum or minimum frequencies; cancel + dbs timer as periodic load sampling is not necessary */ + for_each_online_cpu(cpu) { + if (lock_policy_rwsem_write(cpu) < 0) + continue; + + dbs_info = &per_cpu(id_cpu_dbs_info, cpu); + + for_each_cpu(j, &cpus_timer_done) { + if (!dbs_info->cur_policy) { + printk(KERN_ERR + "%s Dbs policy is NULL\n", + __func__); + goto skip_this_cpu_bypass; + } + if (cpumask_test_cpu(j, dbs_info-> + cur_policy->cpus)) + goto skip_this_cpu_bypass; + } + + cpumask_set_cpu(cpu, &cpus_timer_done); + + if (dbs_info->cur_policy) { + /* cpu using intellidemand, cancel dbs timer */ + mutex_lock(&dbs_info->timer_mutex); + dbs_timer_exit(dbs_info); + + intellidemand_powersave_bias_setspeed( + dbs_info->cur_policy, + NULL, + input); + + mutex_unlock(&dbs_info->timer_mutex); + } +skip_this_cpu_bypass: + unlock_policy_rwsem_write(cpu); + } + } + + return count; +} + +#ifdef CONFIG_CPUFREQ_LIMIT_MAX_FREQ +static ssize_t store_lmf_browser(struct kobject *a, struct attribute *b, + const char *buf, size_t count) +{ + unsigned int input; + int ret; + + ret = sscanf(buf, "%u", &input); + if (ret != 1) + return -EINVAL; + + mutex_lock(&dbs_mutex); + set_lmf_browsing_state(input); + mutex_unlock(&dbs_mutex); + + return count; +} + +static ssize_t store_lmf_active_max_freq(struct kobject *a, struct attribute *b, + const char *buf, size_t count) +{ + unsigned long input; + int ret; + + ret = sscanf(buf, "%ld", &input); + if (ret != 1) + return -EINVAL; + + mutex_lock(&dbs_mutex); + set_lmf_active_max_freq(input); + mutex_unlock(&dbs_mutex); + + return count; +} +static ssize_t store_lmf_inactive_max_freq(struct kobject *a, struct attribute *b, + const char *buf, size_t count) +{ + unsigned long input; + int ret; + + ret = sscanf(buf, "%ld", &input); + if (ret != 1) + return -EINVAL; + + mutex_lock(&dbs_mutex); + set_lmf_inactive_max_freq(input); + mutex_unlock(&dbs_mutex); + + return count; +} + +static ssize_t store_lmf_active_load(struct kobject *a, struct attribute *b, + const char *buf, size_t count) +{ + unsigned long input; + int ret; + + ret = sscanf(buf, "%ld", &input); + if (ret != 1) + return -EINVAL; + + mutex_lock(&dbs_mutex); + set_lmf_active_load(input); + mutex_unlock(&dbs_mutex); + + return count; +} + +static ssize_t store_lmf_inactive_load(struct kobject *a, struct attribute *b, + const char *buf, size_t count) +{ + unsigned long input; + int ret; + + ret = sscanf(buf, "%ld", &input); + if (ret != 1) + return -EINVAL; + + mutex_lock(&dbs_mutex); + set_lmf_inactive_load(input); + mutex_unlock(&dbs_mutex); + + return count; +} +#endif + +define_one_global_rw(sampling_rate); +define_one_global_rw(io_is_busy); +define_one_global_rw(up_threshold); +define_one_global_rw(down_differential); +define_one_global_rw(sampling_down_factor); +define_one_global_rw(ignore_nice_load); +define_one_global_rw(powersave_bias); +define_one_global_rw(up_threshold_multi_core); +define_one_global_rw(optimal_freq); +define_one_global_rw(up_threshold_any_cpu_load); +define_one_global_rw(sync_freq); +define_one_global_rw(boostpulse); +define_one_global_rw(boosttime); +define_one_global_rw(boostfreq); +define_one_global_rw(two_phase_freq); + +#ifdef CONFIG_CPUFREQ_LIMIT_MAX_FREQ +define_one_global_rw(lmf_browser); +define_one_global_rw(lmf_active_max_freq); +define_one_global_rw(lmf_inactive_max_freq); +define_one_global_rw(lmf_active_load); +define_one_global_rw(lmf_inactive_load); +#endif + +static struct attribute *dbs_attributes[] = { + &sampling_rate_min.attr, + &sampling_rate.attr, + &up_threshold.attr, + &down_differential.attr, + &sampling_down_factor.attr, + &ignore_nice_load.attr, + &powersave_bias.attr, + &io_is_busy.attr, + &up_threshold_multi_core.attr, + &optimal_freq.attr, + &up_threshold_any_cpu_load.attr, + &sync_freq.attr, + &boostpulse.attr, + &boosttime.attr, + &boostfreq.attr, + &two_phase_freq.attr, +#ifdef CONFIG_CPUFREQ_LIMIT_MAX_FREQ + &lmf_browser.attr, + &lmf_active_max_freq.attr, + &lmf_inactive_max_freq.attr, + &lmf_active_load.attr, + &lmf_inactive_load.attr, +#endif + NULL +}; + +static struct attribute_group dbs_attr_group = { + .attrs = dbs_attributes, + .name = "intellidemand", +}; + +/************************** sysfs end ************************/ + +static void dbs_freq_increase(struct cpufreq_policy *p, unsigned int freq) +{ + if (dbs_tuners_ins.powersave_bias) + freq = powersave_bias_target(p, freq, CPUFREQ_RELATION_H); + else if (p->cur == p->max) + return; + + __cpufreq_driver_target(p, freq, dbs_tuners_ins.powersave_bias ? + CPUFREQ_RELATION_L : CPUFREQ_RELATION_H); +} + +int id_set_two_phase_freq(int cpufreq) +{ + dbs_tuners_ins.two_phase_freq = cpufreq; + return 0; +} + +static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) +{ + /* Extrapolated load of this CPU */ + unsigned int load_at_max_freq = 0; + unsigned int max_load_freq; + /* Current load across this CPU */ + unsigned int cur_load = 0; + unsigned int max_load_other_cpu = 0; + struct cpufreq_policy *policy; + unsigned int j; + static unsigned int phase = 0; + static unsigned int counter = 0; + + this_dbs_info->freq_lo = 0; + policy = this_dbs_info->cur_policy; + + /* Only core0 controls the boost */ + if (dbs_tuners_ins.boosted && policy->cpu == 0) { + if (ktime_to_us(ktime_get()) - freq_boosted_time >= + dbs_tuners_ins.freq_boost_time) { + dbs_tuners_ins.boosted = 0; + } + } + + /* Only core0 controls the timer_rate */ + if (sampling_rate_boosted && policy->cpu == 0) { + if (ktime_to_us(ktime_get()) - sampling_rate_boosted_time >= + TIMER_RATE_BOOST_TIME) { + + dbs_tuners_ins.sampling_rate = current_sampling_rate; + sampling_rate_boosted = 0; + } + } + + /* + * Every sampling_rate, we check, if current idle time is less + * than 20% (default), then we try to increase frequency + * Every sampling_rate, we look for a the lowest + * frequency which can sustain the load while keeping idle time over + * 30%. If such a frequency exist, we try to decrease to this frequency. + * + * Any frequency increase takes it to the maximum frequency. + * Frequency reduction happens at minimum steps of + * 5% (default) of current frequency + */ + + /* Get Absolute Load - in terms of freq */ + max_load_freq = 0; + + for_each_cpu(j, policy->cpus) { + struct cpu_dbs_info_s *j_dbs_info; + cputime64_t cur_wall_time, cur_idle_time, cur_iowait_time; + unsigned int idle_time, wall_time, iowait_time; + unsigned int load_freq; + int freq_avg; + + j_dbs_info = &per_cpu(id_cpu_dbs_info, j); + + cur_idle_time = get_cpu_idle_time(j, &cur_wall_time); + cur_iowait_time = get_cpu_iowait_time(j, &cur_wall_time); + + wall_time = (unsigned int) + (cur_wall_time - j_dbs_info->prev_cpu_wall); + j_dbs_info->prev_cpu_wall = cur_wall_time; + + idle_time = (unsigned int) + (cur_idle_time - j_dbs_info->prev_cpu_idle); + j_dbs_info->prev_cpu_idle = cur_idle_time; + + iowait_time = (unsigned int) + (cur_iowait_time - j_dbs_info->prev_cpu_iowait); + j_dbs_info->prev_cpu_iowait = cur_iowait_time; + + if (dbs_tuners_ins.ignore_nice) { + u64 cur_nice; + unsigned long cur_nice_jiffies; + + cur_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE] - + j_dbs_info->prev_cpu_nice; + /* + * Assumption: nice time between sampling periods will + * be less than 2^32 jiffies for 32 bit sys + */ + cur_nice_jiffies = (unsigned long) + cputime64_to_jiffies64(cur_nice); + + j_dbs_info->prev_cpu_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE]; + idle_time += jiffies_to_usecs(cur_nice_jiffies); + } + + /* + * For the purpose of intellidemand, waiting for disk IO is an + * indication that you're performance critical, and not that + * the system is actually idle. So subtract the iowait time + * from the cpu idle time. + */ + + if (dbs_tuners_ins.io_is_busy && idle_time >= iowait_time) + idle_time -= iowait_time; + + if (unlikely(!wall_time || wall_time < idle_time)) + continue; + + cur_load = 100 * (wall_time - idle_time) / wall_time; + j_dbs_info->max_load = max(cur_load, j_dbs_info->prev_load); + j_dbs_info->prev_load = cur_load; + freq_avg = __cpufreq_driver_getavg(policy, j); + if (freq_avg <= 0) + freq_avg = policy->cur; + + load_freq = cur_load * freq_avg; + if (load_freq > max_load_freq) + max_load_freq = load_freq; + } + + for_each_online_cpu(j) { + struct cpu_dbs_info_s *j_dbs_info; + j_dbs_info = &per_cpu(id_cpu_dbs_info, j); + + if (j == policy->cpu) + continue; + + if (max_load_other_cpu < j_dbs_info->max_load) + max_load_other_cpu = j_dbs_info->max_load; + /* + * The other cpu could be running at higher frequency + * but may not have completed it's sampling_down_factor. + * For that case consider other cpu is loaded so that + * frequency imbalance does not occur. + */ + + if ((j_dbs_info->cur_policy != NULL) + && (j_dbs_info->cur_policy->cur == + j_dbs_info->cur_policy->max)) { + + if (policy->cur >= dbs_tuners_ins.optimal_freq) + max_load_other_cpu = + dbs_tuners_ins.up_threshold_any_cpu_load; + } + } + /* calculate the scaled load across CPU */ + load_at_max_freq = (cur_load * policy->cur)/policy->cpuinfo.max_freq; + + cpufreq_notify_utilization(policy, load_at_max_freq); + + /* Check for frequency increase */ + if (max_load_freq > dbs_tuners_ins.up_threshold * policy->cur) { + /* If switching to max speed, apply sampling_down_factor */ + if (counter < 5) { + counter++; + if (counter > 2) { + /* change to busy phase */ + phase = 1; + } + } + if (dbs_tuners_ins.two_phase_freq != 0 && phase == 0) { + /* idle phase */ + dbs_freq_increase(policy, + (((dbs_tuners_ins.two_phase_freq)> (int)(policy->max*80/100)) + ?(dbs_tuners_ins.two_phase_freq) : (int)(policy->max*80/100)) ); + } else { + /* busy phase */ + if (policy->cur < policy->max) { + if (sampling_rate_boosted && + (dbs_tuners_ins.sampling_down_factor < + BOOSTED_SAMPLING_DOWN_FACTOR)) { + this_dbs_info->rate_mult = + BOOSTED_SAMPLING_DOWN_FACTOR; + } else { + this_dbs_info->rate_mult = + dbs_tuners_ins.sampling_down_factor; + } + } + dbs_freq_increase(policy, policy->max); + } + return; + } + if (counter > 0) { + counter--; + if (counter == 0) { + /* change to idle phase */ + phase = 0; + } + } + + if (num_online_cpus() > 1) { + + if (max_load_other_cpu > + dbs_tuners_ins.up_threshold_any_cpu_load) { + if (policy->cur < dbs_tuners_ins.sync_freq) + dbs_freq_increase(policy, + dbs_tuners_ins.sync_freq); + return; + } + + if (max_load_freq > dbs_tuners_ins.up_threshold_multi_core * + policy->cur) { + if (policy->cur < dbs_tuners_ins.optimal_freq) + dbs_freq_increase(policy, + dbs_tuners_ins.optimal_freq); + return; + } + } + + /* Check for frequency decrease */ + /* if we cannot reduce the frequency anymore, break out early */ + if (policy->cur == policy->min) + return; + + /* + * The optimal frequency is the frequency that is the lowest that + * can support the current CPU usage without triggering the up + * policy. To be safe, we focus 10 points under the threshold. + */ + if (max_load_freq < + (dbs_tuners_ins.up_threshold - dbs_tuners_ins.down_differential) * + policy->cur) { + unsigned int freq_next; + freq_next = max_load_freq / + (dbs_tuners_ins.up_threshold - + dbs_tuners_ins.down_differential); + + if (dbs_tuners_ins.boosted && + freq_next < dbs_tuners_ins.boostfreq) { + freq_next = dbs_tuners_ins.boostfreq; + } + + /* No longer fully busy, reset rate_mult */ + this_dbs_info->rate_mult = 1; + + if (freq_next < policy->min) + freq_next = policy->min; + + if (num_online_cpus() > 1) { + if (max_load_other_cpu > + (dbs_tuners_ins.up_threshold_multi_core - + dbs_tuners_ins.down_differential) && + freq_next < dbs_tuners_ins.sync_freq) + freq_next = dbs_tuners_ins.sync_freq; + + if (max_load_freq > + ((dbs_tuners_ins.up_threshold_multi_core - + dbs_tuners_ins.down_differential_multi_core) * + policy->cur) && + freq_next < dbs_tuners_ins.optimal_freq) + freq_next = dbs_tuners_ins.optimal_freq; + + } + + if (!dbs_tuners_ins.powersave_bias) { + __cpufreq_driver_target(policy, freq_next, + CPUFREQ_RELATION_L); + } else { + int freq = powersave_bias_target(policy, freq_next, + CPUFREQ_RELATION_L); + __cpufreq_driver_target(policy, freq, + CPUFREQ_RELATION_L); + } + } +} + +#ifdef CONFIG_CPUFREQ_LIMIT_MAX_FREQ + +enum { + SET_MIN = 0, + SET_MAX +}; + +enum { + BOOT_CPU = 0, + NON_BOOT_CPU1, + NON_BOOT_CPU2, + NON_BOOT_CPU3, +}; + +#define SAMPLE_DURATION_MSEC (10*1000) // 10 secs >= 10000 msec +#define ACTIVE_DURATION_MSEC (3*60*1000) // 3 mins +#define INACTIVE_DURATION_MSEC (1*60*1000) // 1 mins +#define MAX_ACTIVE_FREQ_LIMIT 30 // % +#define MAX_INACTIVE_FREQ_LIMIT 20 // % +#define ACTIVE_MAX_FREQ CONFIG_INTELLI_MAX_ACTIVE_FREQ // 1.512GHZ +#define INACTIVE_MAX_FREQ CONFIG_INTELLI_MAX_INACTIVE_FREQ // 1.134GHZ + +#define NUM_ACTIVE_LOAD_ARRAY (ACTIVE_DURATION_MSEC/SAMPLE_DURATION_MSEC) +#define NUM_INACTIVE_LOAD_ARRAY (INACTIVE_DURATION_MSEC/SAMPLE_DURATION_MSEC) + +bool lmf_browsing_state = true; +bool lmf_screen_state = true; + +static unsigned long lmf_active_max_limit = ACTIVE_MAX_FREQ; +static unsigned long lmf_inactive_max_limit = INACTIVE_MAX_FREQ; +static unsigned long lmf_active_load_limit = MAX_ACTIVE_FREQ_LIMIT; +static unsigned long lmf_inactive_load_limit = MAX_INACTIVE_FREQ_LIMIT; + +static unsigned long jiffies_old = 0; +static unsigned long time_int = 0; +static unsigned long time_int1 = 0; +static unsigned long load_state_total0 = 0; +static unsigned long load_state_total1 = 0; +static unsigned long load_limit_index = 0; +static unsigned long load_limit_total[NUM_ACTIVE_LOAD_ARRAY]; +static unsigned long msecs_limit_total = 0; +static bool active_state = true; +static bool lmf_old_state = false; + +extern int cpufreq_set_limits(int cpu, unsigned int limit, unsigned int value); +extern int cpufreq_set_limits_off(int cpu, unsigned int limit, unsigned int value); + +void set_lmf_browsing_state(bool onOff) +{ + if (onOff) + lmf_browsing_state = true; + else + lmf_browsing_state = false; +} + +void set_lmf_active_max_freq(unsigned long freq) +{ + lmf_active_max_limit = freq; +} + +void set_lmf_inactive_max_freq(unsigned long freq) +{ + lmf_inactive_max_limit = freq; +} + +void set_lmf_active_load(unsigned long freq) +{ + lmf_active_load_limit = freq; +} + +void set_lmf_inactive_load(unsigned long freq) +{ + lmf_inactive_load_limit = freq; +} + +bool get_lmf_browsing_state(void) +{ + return lmf_browsing_state; +} + +unsigned long get_lmf_active_max_freq(void) +{ + return lmf_active_max_limit; +} + +unsigned long get_lmf_inactive_max_freq(void) +{ + return lmf_inactive_max_limit; +} + +unsigned long get_lmf_active_load(void) +{ + return lmf_active_load_limit; +} + +unsigned long get_lmf_inactive_load(void) +{ + return lmf_inactive_load_limit; +} +#endif + +static unsigned int rq_persist_count = 0; + +static void do_dbs_timer(struct work_struct *work) +{ + struct cpu_dbs_info_s *dbs_info = + container_of(work, struct cpu_dbs_info_s, work.work); + unsigned int cpu = dbs_info->cpu; + int sample_type = dbs_info->sample_type; + + int delay; +#ifdef CONFIG_CPUFREQ_ID_PERFLOCK + struct cpufreq_policy *policy; + + policy = dbs_info->cur_policy; +#endif + + if (num_online_cpus() >= 2 && rq_info.rq_avg > 38) + rq_persist_count++; + else + if (rq_persist_count > 0) + rq_persist_count--; + +#ifdef CONFIG_CPUFREQ_ID_PERFLOCK + if (cpu == 0) { + if (num_online_cpus() >= 2) { + if (saved_policy_min != 0) + policy->min = saved_policy_min; + } else if (num_online_cpus() == 1) { + saved_policy_min = policy->min; + policy->min = DBS_PERFLOCK_MIN_FREQ; + } + } +#endif + +#ifdef CONFIG_CPUFREQ_LIMIT_MAX_FREQ + if (rq_persist_count > 3) { + lmf_browsing_state = false; + rq_persist_count = 0; + } + else + lmf_browsing_state = true; + //pr_info("Run Queue Average: %u\n", rq_info.rq_avg); + + if (!lmf_browsing_state && lmf_screen_state) + { + if (cpu == BOOT_CPU) + { + if (lmf_old_state == true) + { + pr_warn("LMF: disabled!\n"); + lmf_old_state = false; + } + + if (!active_state) + { + /* set freq to 1.5GHz */ + //pr_info("LMF: CPU0 set max freq to: %lu\n", lmf_active_max_limit); + cpufreq_set_limits(BOOT_CPU, SET_MAX, lmf_active_max_limit); + + //pr_info("LMF: CPUX set max freq to: %lu\n", lmf_active_max_limit); + if (cpu_online(NON_BOOT_CPU1) || + cpu_online(NON_BOOT_CPU2) || + cpu_online(NON_BOOT_CPU3)) { + cpufreq_set_limits(NON_BOOT_CPU1, SET_MAX, lmf_active_max_limit); + cpufreq_set_limits(NON_BOOT_CPU2, SET_MAX, lmf_active_max_limit); + cpufreq_set_limits(NON_BOOT_CPU3, SET_MAX, lmf_active_max_limit); + } else { + cpufreq_set_limits_off(NON_BOOT_CPU1, SET_MAX, lmf_active_max_limit); + cpufreq_set_limits_off(NON_BOOT_CPU2, SET_MAX, lmf_active_max_limit); + cpufreq_set_limits_off(NON_BOOT_CPU3, SET_MAX, lmf_active_max_limit); + } + } + + jiffies_old = 0; + time_int = 0; + time_int1 = 0; + load_state_total0 = 0; + load_state_total1 = 0; + msecs_limit_total = 0; + load_limit_index = 0; + active_state = true; + } + } + else if (lmf_browsing_state && lmf_screen_state) // lmf_browsing_state -> TRUE + { + struct cpufreq_policy *policy; + unsigned long load_state_cpu = 0; + unsigned int delay_msec = 0; + unsigned long load_total = 0; + unsigned long jiffies_cur = jiffies; + + if (cpu == NON_BOOT_CPU1 || cpu == NON_BOOT_CPU2 || cpu == NON_BOOT_CPU3) + { + delay_msec = (dbs_tuners_ins.sampling_rate * dbs_info->rate_mult) / 1000; + policy = dbs_info->cur_policy; + load_state_cpu = ((policy->cur) * delay_msec)/10000; + + time_int1 += delay_msec; + load_state_total1 += load_state_cpu; + } + else + { + if (lmf_old_state == false) + { + pr_warn("LMF: enabled!\n"); + lmf_old_state = true; + } + + if (jiffies_old == 0) + { + jiffies_old = jiffies_cur; + } + else + { + delay_msec = jiffies_to_msecs(jiffies_cur - jiffies_old); + jiffies_old = jiffies_cur; + policy = dbs_info->cur_policy; + load_state_cpu = ((policy->cur) * delay_msec)/10000; + + time_int += delay_msec; + load_state_total0 += load_state_cpu; + + /* average */ + if (time_int >= SAMPLE_DURATION_MSEC) + { + int i = 0; + unsigned long ave_max = 0; + unsigned long average = 0; + unsigned long average_dec = 0; + unsigned long total_load = 0; + + load_total = load_state_total0 + load_state_total1; + ave_max = (time_int / 10) * ((lmf_active_max_limit/1000) * 2); + average = (load_total * 100) / ave_max; + average_dec = (load_total * 100) % ave_max; + + msecs_limit_total += time_int; + load_limit_total[load_limit_index++] = average; + + //pr_warn("LMF: average = %ld.%ld, (%ld:%ld) (%ld:%ld) (%ld:%ld)\n", + // average, average_dec, time_int, time_int1, load_state_total0, load_state_total1, load_limit_index-1, msecs_limit_total); + + time_int = 0; + time_int1 = 0; + load_state_total0 = 0; + load_state_total1 = 0; + + /* active */ + if (active_state) + { + if (load_limit_index >= NUM_ACTIVE_LOAD_ARRAY) + { + load_limit_index = 0; + } + + if (msecs_limit_total > ACTIVE_DURATION_MSEC) + { + for (i=0; i lmf_active_load_limit) + { + msecs_limit_total = 0; + load_limit_index = 0; + active_state = false; + + /* set freq to 1.0GHz */ + //pr_info("LMF: CPU0 set max freq to: %lu\n", lmf_inactive_max_limit); + cpufreq_set_limits(BOOT_CPU, SET_MAX, lmf_inactive_max_limit); + + //pr_info("LMF: CPUX set max freq to: %lu\n", lmf_inactive_max_limit); + if (cpu_online(NON_BOOT_CPU1) || + cpu_online(NON_BOOT_CPU2) || + cpu_online(NON_BOOT_CPU3)) { + cpufreq_set_limits(NON_BOOT_CPU1, SET_MAX, lmf_inactive_max_limit); + cpufreq_set_limits(NON_BOOT_CPU2, SET_MAX, lmf_inactive_max_limit); + cpufreq_set_limits(NON_BOOT_CPU3, SET_MAX, lmf_inactive_max_limit); + } else { + cpufreq_set_limits_off(NON_BOOT_CPU1, SET_MAX, lmf_inactive_max_limit); + cpufreq_set_limits_off(NON_BOOT_CPU2, SET_MAX, lmf_inactive_max_limit); + cpufreq_set_limits_off(NON_BOOT_CPU3, SET_MAX, lmf_inactive_max_limit); + } + } + else + { + msecs_limit_total = ACTIVE_DURATION_MSEC; // to prevent overflow + } + } + } + else /* inactive */ + { + if (load_limit_index >= NUM_INACTIVE_LOAD_ARRAY) + { + load_limit_index = 0; + } + + if (msecs_limit_total > INACTIVE_DURATION_MSEC) + { + for (i=0; itimer_mutex); + + /* Common NORMAL_SAMPLE setup */ + dbs_info->sample_type = DBS_NORMAL_SAMPLE; + if (!dbs_tuners_ins.powersave_bias || + sample_type == DBS_NORMAL_SAMPLE) { + dbs_check_cpu(dbs_info); + if (dbs_info->freq_lo) { + /* Setup timer for SUB_SAMPLE */ + dbs_info->sample_type = DBS_SUB_SAMPLE; + delay = dbs_info->freq_hi_jiffies; + } else { + /* We want all CPUs to do sampling nearly on + * same jiffy + */ + delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate + * dbs_info->rate_mult); + + if (num_online_cpus() > 1) + delay -= jiffies % delay; + } + } else { + __cpufreq_driver_target(dbs_info->cur_policy, + dbs_info->freq_lo, CPUFREQ_RELATION_H); + delay = dbs_info->freq_lo_jiffies; + } + schedule_delayed_work_on(cpu, &dbs_info->work, delay); + mutex_unlock(&dbs_info->timer_mutex); +} + +static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info) +{ + /* We want all CPUs to do sampling nearly on same jiffy */ + int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate); + + if (num_online_cpus() > 1) + delay -= jiffies % delay; + + dbs_info->sample_type = DBS_NORMAL_SAMPLE; + INIT_DELAYED_WORK_DEFERRABLE(&dbs_info->work, do_dbs_timer); + schedule_delayed_work_on(dbs_info->cpu, &dbs_info->work, delay); +} + +static inline void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info) +{ + cancel_delayed_work_sync(&dbs_info->work); +} + +/* + * Not all CPUs want IO time to be accounted as busy; this dependson how + * efficient idling at a higher frequency/voltage is. + * Pavel Machek says this is not so for various generations of AMD and old + * Intel systems. + * Mike Chan (androidlcom) calis this is also not true for ARM. + * Because of this, whitelist specific known (series) of CPUs by default, and + * leave all others up to the user. + */ +static int should_io_be_busy(void) +{ +#if defined(CONFIG_X86) + /* + * For Intel, Core 2 (model 15) andl later have an efficient idle. + */ + if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL && + boot_cpu_data.x86 == 6 && + boot_cpu_data.x86_model >= 15) + return 1; +#endif +#if defined(CONFIG_ARM) + return 1; /* tread I/O as busy always for ARM */ +#else + return 0; +#endif +} + +#define AID_SYSTEM (1000) +static void dbs_chown(void) +{ + int ret; + + ret = + sys_chown("/sys/devices/system/cpu/cpufreq/intellidemand/sampling_rate", + low2highuid(AID_SYSTEM), low2highgid(0)); + ret = + sys_chown("/sys/devices/system/cpu/cpufreq/intellidemand/boostpulse", + low2highuid(AID_SYSTEM), low2highgid(0)); + if (ret) + pr_err("sys_chown: boostpulse error: %d", ret); +} + +static void dbs_refresh_callback(struct work_struct *work) +{ + struct cpufreq_policy *policy; + struct cpu_dbs_info_s *this_dbs_info; + struct dbs_work_struct *dbs_work; + unsigned int cpu; + + dbs_work = container_of(work, struct dbs_work_struct, work); + cpu = dbs_work->cpu; + + get_online_cpus(); + + if (lock_policy_rwsem_write(cpu) < 0) + goto bail_acq_sema_failed; + + this_dbs_info = &per_cpu(id_cpu_dbs_info, cpu); + policy = this_dbs_info->cur_policy; + if (!policy) { + /* CPU not using intellidemand governor */ + goto bail_incorrect_governor; + } + + if (policy->cur < DBS_INPUT_EVENT_MIN_FREQ) { +#if 0 + pr_info("%s: set cpufreq to DBS_INPUT_EVENT_MIN_FREQ(%d) \ + directly due to input events!\n", __func__, \ + DBS_INPUT_EVENT_MIN_FREQ); +#endif + /* + * Arch specific cpufreq driver may fail. + * Don't update governor frequency upon failure. + */ + if (__cpufreq_driver_target(policy, DBS_INPUT_EVENT_MIN_FREQ, + CPUFREQ_RELATION_L) >= 0); + policy->cur = DBS_INPUT_EVENT_MIN_FREQ; + this_dbs_info->prev_cpu_idle = get_cpu_idle_time(cpu, + &this_dbs_info->prev_cpu_wall); + } +bail_incorrect_governor: + unlock_policy_rwsem_write(cpu); + +bail_acq_sema_failed: + put_online_cpus(); + return; +} + +static unsigned int enable_dbs_input_event = 1; +static void dbs_input_event(struct input_handle *handle, unsigned int type, + unsigned int code, int value) +{ + int i; + + if (enable_dbs_input_event) { + + if ((dbs_tuners_ins.powersave_bias == POWERSAVE_BIAS_MAXLEVEL) || + (dbs_tuners_ins.powersave_bias == POWERSAVE_BIAS_MINLEVEL)) { + /* nothing to do */ + return; + } + + if (current_sampling_rate > BOOSTED_SAMPLING_RATE) { + dbs_tuners_ins.sampling_rate = BOOSTED_SAMPLING_RATE; + sampling_rate_boosted_time = ktime_to_us(ktime_get()); + sampling_rate_boosted = 1; + } + + for_each_online_cpu(i) + queue_work_on(i, input_wq, &per_cpu(dbs_refresh_work, i).work); + } +} + +#if 1 +static int input_dev_filter(const char *input_dev_name) +{ + if (strstr(input_dev_name, "elan-touchscreen") || + strstr(input_dev_name, "-keypad") || + strstr(input_dev_name, "-nav") || + strstr(input_dev_name, "-oj")) { + return 0; + } else { + return 1; + } +} +#endif + +static int dbs_input_connect(struct input_handler *handler, + struct input_dev *dev, const struct input_device_id *id) +{ + struct input_handle *handle; + int error; + +#if 1 + /* filter out those input_dev that we don't care */ + if (input_dev_filter(dev->name)) + return -ENODEV; +#endif + + handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL); + if (!handle) + return -ENOMEM; + + handle->dev = dev; + handle->handler = handler; + handle->name = "cpufreq"; + + error = input_register_handle(handle); + if (error) + goto err2; + + error = input_open_device(handle); + if (error) + goto err1; + + return 0; +err1: + input_unregister_handle(handle); +err2: + kfree(handle); + return error; +} + +static void dbs_input_disconnect(struct input_handle *handle) +{ + input_close_device(handle); + input_unregister_handle(handle); + kfree(handle); +} + +static const struct input_device_id dbs_ids[] = { + { .driver_info = 1 }, + { }, +}; + +static struct input_handler dbs_input_handler = { + .event = dbs_input_event, + .connect = dbs_input_connect, + .disconnect = dbs_input_disconnect, + .name = "cpufreq_intelli", + .id_table = dbs_ids, +}; + +static int cpufreq_governor_dbs(struct cpufreq_policy *policy, + unsigned int event) +{ + unsigned int cpu = policy->cpu; + struct cpu_dbs_info_s *this_dbs_info; + unsigned int j; + int rc; + + this_dbs_info = &per_cpu(id_cpu_dbs_info, cpu); + + switch (event) { + case CPUFREQ_GOV_START: + if ((!cpu_online(cpu)) || (!policy->cur)) + return -EINVAL; + + mutex_lock(&dbs_mutex); + + dbs_chown(); + + dbs_enable++; + for_each_cpu(j, policy->cpus) { + struct cpu_dbs_info_s *j_dbs_info; + j_dbs_info = &per_cpu(id_cpu_dbs_info, j); + j_dbs_info->cur_policy = policy; + + j_dbs_info->prev_cpu_idle = get_cpu_idle_time(j, + &j_dbs_info->prev_cpu_wall); + if (dbs_tuners_ins.ignore_nice) { + j_dbs_info->prev_cpu_nice + = kcpustat_cpu(j).cpustat[CPUTIME_NICE]; + } + } + this_dbs_info->cpu = cpu; + this_dbs_info->rate_mult = 1; + intellidemand_powersave_bias_init_cpu(cpu); + /* + * Start the timerschedule work, when this governor + * is used for first time + */ + if (dbs_enable == 1) { + unsigned int latency; + + rc = sysfs_create_group(cpufreq_global_kobject, + &dbs_attr_group); + if (rc) { + mutex_unlock(&dbs_mutex); + return rc; + } + + /* policy latency is in nS. Convert it to uS first */ + latency = policy->cpuinfo.transition_latency / 1000; + if (latency == 0) + latency = 1; + /* Bring kernel and HW constraints together */ + min_sampling_rate = max(min_sampling_rate, + MIN_LATENCY_MULTIPLIER * latency); + dbs_tuners_ins.sampling_rate = + max(min_sampling_rate, + latency * LATENCY_MULTIPLIER); + dbs_tuners_ins.io_is_busy = should_io_be_busy(); + + if (dbs_tuners_ins.optimal_freq == 0) + dbs_tuners_ins.optimal_freq = policy->min; + + if (dbs_tuners_ins.sync_freq == 0) + dbs_tuners_ins.sync_freq = policy->min; + } + if (!cpu) + rc = input_register_handler(&dbs_input_handler); + mutex_unlock(&dbs_mutex); + + if (!intellidemand_powersave_bias_setspeed( + this_dbs_info->cur_policy, + NULL, + dbs_tuners_ins.powersave_bias)) + dbs_timer_init(this_dbs_info); + break; + + case CPUFREQ_GOV_STOP: + dbs_timer_exit(this_dbs_info); + + mutex_lock(&dbs_mutex); + dbs_enable--; + /* If device is being removed, policy is no longer + * valid. */ + this_dbs_info->cur_policy = NULL; + if (!cpu) + input_unregister_handler(&dbs_input_handler); + if (!dbs_enable) + sysfs_remove_group(cpufreq_global_kobject, + &dbs_attr_group); + mutex_unlock(&dbs_mutex); + + break; + + case CPUFREQ_GOV_LIMITS: + mutex_lock(&this_dbs_info->timer_mutex); + if (policy->max < this_dbs_info->cur_policy->cur) + __cpufreq_driver_target(this_dbs_info->cur_policy, + policy->max, CPUFREQ_RELATION_H); + else if (policy->min > this_dbs_info->cur_policy->cur) + __cpufreq_driver_target(this_dbs_info->cur_policy, + policy->min, CPUFREQ_RELATION_L); + else if (dbs_tuners_ins.powersave_bias != 0) + intellidemand_powersave_bias_setspeed( + this_dbs_info->cur_policy, + policy, + dbs_tuners_ins.powersave_bias); + mutex_unlock(&this_dbs_info->timer_mutex); + break; + } + return 0; +} + +#ifdef CONFIG_EARLYSUSPEND +static void cpufreq_intellidemand_early_suspend(struct early_suspend *h) +{ + mutex_lock(&dbs_mutex); + stored_sampling_rate = dbs_tuners_ins.sampling_rate; + dbs_tuners_ins.sampling_rate = DEF_SAMPLING_RATE * 6; + update_sampling_rate(dbs_tuners_ins.sampling_rate); + mutex_unlock(&dbs_mutex); +} + +static void cpufreq_intellidemand_late_resume(struct early_suspend *h) +{ + mutex_lock(&dbs_mutex); + dbs_tuners_ins.sampling_rate = stored_sampling_rate; + update_sampling_rate(dbs_tuners_ins.sampling_rate); + mutex_unlock(&dbs_mutex); +} + +static struct early_suspend cpufreq_intellidemand_early_suspend_info = { + .suspend = cpufreq_intellidemand_early_suspend, + .resume = cpufreq_intellidemand_late_resume, + .level = EARLY_SUSPEND_LEVEL_DISABLE_FB+1, +}; +#endif + +static int __init cpufreq_gov_dbs_init(void) +{ + u64 idle_time; + unsigned int i; + int cpu = get_cpu(); + + idle_time = get_cpu_idle_time_us(cpu, NULL); + put_cpu(); + if (idle_time != -1ULL) { + /* Idle micro accounting is supported. Use finer thresholds */ + dbs_tuners_ins.up_threshold = MICRO_FREQUENCY_UP_THRESHOLD; + dbs_tuners_ins.down_differential = + MICRO_FREQUENCY_DOWN_DIFFERENTIAL; + /* + * In no_hz/micro accounting case we set the minimum frequency + * not depending on HZ, but fixed (very low). The deferred + * timer might skip some samples if idle/sleeping as needed. + */ + min_sampling_rate = MICRO_FREQUENCY_MIN_SAMPLE_RATE; + } else { + /* For correct statistics, we need 10 ticks for each measure */ + min_sampling_rate = + MIN_SAMPLING_RATE_RATIO * jiffies_to_usecs(10); + } + + input_wq = create_workqueue("iewq"); + if (!input_wq) { + printk(KERN_ERR "Failed to create iewq workqueue\n"); + return -EFAULT; + } + for_each_possible_cpu(i) { + struct cpu_dbs_info_s *this_dbs_info = + &per_cpu(id_cpu_dbs_info, i); + struct dbs_work_struct *dbs_work = + &per_cpu(dbs_refresh_work, i); + + mutex_init(&this_dbs_info->timer_mutex); + INIT_WORK(&dbs_work->work, dbs_refresh_callback); + dbs_work->cpu = i; + } + +#ifdef CONFIG_EARLYSUSPEND + register_early_suspend(&cpufreq_intellidemand_early_suspend_info); +#endif + return cpufreq_register_governor(&cpufreq_gov_intellidemand); +} + +static void __exit cpufreq_gov_dbs_exit(void) +{ + unsigned int i; + + cpufreq_unregister_governor(&cpufreq_gov_intellidemand); + for_each_possible_cpu(i) { + struct cpu_dbs_info_s *this_dbs_info = + &per_cpu(id_cpu_dbs_info, i); + mutex_destroy(&this_dbs_info->timer_mutex); + } +#ifdef CONFIG_EARLYSUSPEND + unregister_early_suspend(&cpufreq_intellidemand_early_suspend_info); +#endif + destroy_workqueue(input_wq); +} + +static int set_enable_dbs_input_event_param(const char *val, struct kernel_param *kp) +{ + int ret = 0; + + ret = param_set_uint(val, kp); + if (ret) + pr_err("%s: error setting value %d\n", __func__, ret); + + return ret; +} +module_param_call(enable_dbs_input_event, set_enable_dbs_input_event_param, param_get_uint, + &enable_dbs_input_event, S_IWUSR | S_IRUGO); + +MODULE_AUTHOR("Venkatesh Pallipadi "); +MODULE_AUTHOR("Alexey Starikovskiy "); +MODULE_AUTHOR("Paul Reioux "); +MODULE_DESCRIPTION("'cpufreq_intellidemand' - An intelligent dynamic cpufreq governor for " + "Low Latency Frequency Transition capable processors"); +MODULE_LICENSE("GPL"); + +#ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_INTELLIDEMAND +fs_initcall(cpufreq_gov_dbs_init); +#else +module_init(cpufreq_gov_dbs_init); +#endif +module_exit(cpufreq_gov_dbs_exit); + diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index 0bf6aa3d546..b1e41c5b3a1 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -27,6 +27,7 @@ #include #include #include +#include /* * dbs is used in this file as a shortform for demandbased switching @@ -1132,6 +1133,9 @@ static void dbs_input_event(struct input_handle *handle, unsigned int type, return; } + if (throttled_bin > 0) + return; + for_each_online_cpu(i) queue_work_on(i, dbs_wq, &per_cpu(dbs_refresh_work, i)); } diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index 1a9a6a5eb57..01de0f10be7 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c @@ -337,7 +337,7 @@ static int cpufreq_stats_create_table_cpu(unsigned int cpu) return ret; } -static int __cpuinit cpufreq_stat_cpu_callback(struct notifier_block *nfb, +static int cpufreq_stat_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { @@ -389,18 +389,21 @@ static int __init cpufreq_stats_init(void) if (ret) return ret; + register_hotcpu_notifier(&cpufreq_stat_cpu_notifier); + for_each_online_cpu(cpu) + cpufreq_update_policy(cpu); + ret = cpufreq_register_notifier(¬ifier_trans_block, CPUFREQ_TRANSITION_NOTIFIER); if (ret) { cpufreq_unregister_notifier(¬ifier_policy_block, CPUFREQ_POLICY_NOTIFIER); + unregister_hotcpu_notifier(&cpufreq_stat_cpu_notifier); + for_each_online_cpu(cpu) + cpufreq_stats_free_table(cpu); return ret; } - register_hotcpu_notifier(&cpufreq_stat_cpu_notifier); - for_each_online_cpu(cpu) { - cpufreq_update_policy(cpu); - } return 0; } static void __exit cpufreq_stats_exit(void) diff --git a/drivers/cpufreq/db8500-cpufreq.c b/drivers/cpufreq/db8500-cpufreq.c index 0bf1b8910ee..b15cee36048 100644 --- a/drivers/cpufreq/db8500-cpufreq.c +++ b/drivers/cpufreq/db8500-cpufreq.c @@ -107,7 +107,7 @@ static unsigned int db8500_cpufreq_getspeed(unsigned int cpu) return freq_table[i].frequency; } -static int __cpuinit db8500_cpufreq_init(struct cpufreq_policy *policy) +static int db8500_cpufreq_init(struct cpufreq_policy *policy) { int i, res; diff --git a/drivers/cpufreq/longhaul.c b/drivers/cpufreq/longhaul.c index 53ddbc760af..07de3922a13 100644 --- a/drivers/cpufreq/longhaul.c +++ b/drivers/cpufreq/longhaul.c @@ -422,7 +422,7 @@ static int guess_fsb(int mult) } -static int __cpuinit longhaul_get_ranges(void) +static int longhaul_get_ranges(void) { unsigned int i, j, k = 0; unsigned int ratio; @@ -526,7 +526,7 @@ static int __cpuinit longhaul_get_ranges(void) } -static void __cpuinit longhaul_setup_voltagescaling(void) +static void longhaul_setup_voltagescaling(void) { union msr_longhaul longhaul; struct mV_pos minvid, maxvid, vid; @@ -780,7 +780,7 @@ static int longhaul_setup_southbridge(void) return 0; } -static int __cpuinit longhaul_cpu_init(struct cpufreq_policy *policy) +static int longhaul_cpu_init(struct cpufreq_policy *policy) { struct cpuinfo_x86 *c = &cpu_data(0); char *cpuname = NULL; diff --git a/drivers/cpufreq/longhaul.h b/drivers/cpufreq/longhaul.h index cbf48fbca88..1928b923a57 100644 --- a/drivers/cpufreq/longhaul.h +++ b/drivers/cpufreq/longhaul.h @@ -56,7 +56,7 @@ union msr_longhaul { /* * VIA C3 Samuel 1 & Samuel 2 (stepping 0) */ -static const int __cpuinitdata samuel1_mults[16] = { +static const int samuel1_mults[16] = { -1, /* 0000 -> RESERVED */ 30, /* 0001 -> 3.0x */ 40, /* 0010 -> 4.0x */ @@ -75,7 +75,7 @@ static const int __cpuinitdata samuel1_mults[16] = { -1, /* 1111 -> RESERVED */ }; -static const int __cpuinitdata samuel1_eblcr[16] = { +static const int samuel1_eblcr[16] = { 50, /* 0000 -> RESERVED */ 30, /* 0001 -> 3.0x */ 40, /* 0010 -> 4.0x */ @@ -97,7 +97,7 @@ static const int __cpuinitdata samuel1_eblcr[16] = { /* * VIA C3 Samuel2 Stepping 1->15 */ -static const int __cpuinitdata samuel2_eblcr[16] = { +static const int samuel2_eblcr[16] = { 50, /* 0000 -> 5.0x */ 30, /* 0001 -> 3.0x */ 40, /* 0010 -> 4.0x */ @@ -119,7 +119,7 @@ static const int __cpuinitdata samuel2_eblcr[16] = { /* * VIA C3 Ezra */ -static const int __cpuinitdata ezra_mults[16] = { +static const int ezra_mults[16] = { 100, /* 0000 -> 10.0x */ 30, /* 0001 -> 3.0x */ 40, /* 0010 -> 4.0x */ @@ -138,7 +138,7 @@ static const int __cpuinitdata ezra_mults[16] = { 120, /* 1111 -> 12.0x */ }; -static const int __cpuinitdata ezra_eblcr[16] = { +static const int ezra_eblcr[16] = { 50, /* 0000 -> 5.0x */ 30, /* 0001 -> 3.0x */ 40, /* 0010 -> 4.0x */ @@ -160,7 +160,7 @@ static const int __cpuinitdata ezra_eblcr[16] = { /* * VIA C3 (Ezra-T) [C5M]. */ -static const int __cpuinitdata ezrat_mults[32] = { +static const int ezrat_mults[32] = { 100, /* 0000 -> 10.0x */ 30, /* 0001 -> 3.0x */ 40, /* 0010 -> 4.0x */ @@ -196,7 +196,7 @@ static const int __cpuinitdata ezrat_mults[32] = { -1, /* 1111 -> RESERVED (12.0x) */ }; -static const int __cpuinitdata ezrat_eblcr[32] = { +static const int ezrat_eblcr[32] = { 50, /* 0000 -> 5.0x */ 30, /* 0001 -> 3.0x */ 40, /* 0010 -> 4.0x */ @@ -235,7 +235,7 @@ static const int __cpuinitdata ezrat_eblcr[32] = { /* * VIA C3 Nehemiah */ -static const int __cpuinitdata nehemiah_mults[32] = { +static const int nehemiah_mults[32] = { 100, /* 0000 -> 10.0x */ -1, /* 0001 -> 16.0x */ 40, /* 0010 -> 4.0x */ @@ -270,7 +270,7 @@ static const int __cpuinitdata nehemiah_mults[32] = { -1, /* 1111 -> 12.0x */ }; -static const int __cpuinitdata nehemiah_eblcr[32] = { +static const int nehemiah_eblcr[32] = { 50, /* 0000 -> 5.0x */ 160, /* 0001 -> 16.0x */ 40, /* 0010 -> 4.0x */ @@ -315,7 +315,7 @@ struct mV_pos { unsigned short pos; }; -static const struct mV_pos __cpuinitdata vrm85_mV[32] = { +static const struct mV_pos vrm85_mV[32] = { {1250, 8}, {1200, 6}, {1150, 4}, {1100, 2}, {1050, 0}, {1800, 30}, {1750, 28}, {1700, 26}, {1650, 24}, {1600, 22}, {1550, 20}, {1500, 18}, @@ -326,14 +326,14 @@ static const struct mV_pos __cpuinitdata vrm85_mV[32] = { {1475, 17}, {1425, 15}, {1375, 13}, {1325, 11} }; -static const unsigned char __cpuinitdata mV_vrm85[32] = { +static const unsigned char mV_vrm85[32] = { 0x04, 0x14, 0x03, 0x13, 0x02, 0x12, 0x01, 0x11, 0x00, 0x10, 0x0f, 0x1f, 0x0e, 0x1e, 0x0d, 0x1d, 0x0c, 0x1c, 0x0b, 0x1b, 0x0a, 0x1a, 0x09, 0x19, 0x08, 0x18, 0x07, 0x17, 0x06, 0x16, 0x05, 0x15 }; -static const struct mV_pos __cpuinitdata mobilevrm_mV[32] = { +static const struct mV_pos mobilevrm_mV[32] = { {1750, 31}, {1700, 30}, {1650, 29}, {1600, 28}, {1550, 27}, {1500, 26}, {1450, 25}, {1400, 24}, {1350, 23}, {1300, 22}, {1250, 21}, {1200, 20}, @@ -344,7 +344,7 @@ static const struct mV_pos __cpuinitdata mobilevrm_mV[32] = { {675, 3}, {650, 2}, {625, 1}, {600, 0} }; -static const unsigned char __cpuinitdata mV_mobilevrm[32] = { +static const unsigned char mV_mobilevrm[32] = { 0x1f, 0x1e, 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, diff --git a/drivers/cpufreq/longrun.c b/drivers/cpufreq/longrun.c index 8bc9f5fbbae..0fe041d1f77 100644 --- a/drivers/cpufreq/longrun.c +++ b/drivers/cpufreq/longrun.c @@ -33,7 +33,7 @@ static unsigned int longrun_low_freq, longrun_high_freq; * Reads the current LongRun policy by access to MSR_TMTA_LONGRUN_FLAGS * and MSR_TMTA_LONGRUN_CTRL */ -static void __cpuinit longrun_get_policy(struct cpufreq_policy *policy) +static void longrun_get_policy(struct cpufreq_policy *policy) { u32 msr_lo, msr_hi; @@ -163,7 +163,7 @@ static unsigned int longrun_get(unsigned int cpu) * TMTA rules: * performance_pctg = (target_freq - low_freq)/(high_freq - low_freq) */ -static int __cpuinit longrun_determine_freqs(unsigned int *low_freq, +static int longrun_determine_freqs(unsigned int *low_freq, unsigned int *high_freq) { u32 msr_lo, msr_hi; @@ -256,7 +256,7 @@ static int __cpuinit longrun_determine_freqs(unsigned int *low_freq, } -static int __cpuinit longrun_cpu_init(struct cpufreq_policy *policy) +static int longrun_cpu_init(struct cpufreq_policy *policy) { int result = 0; diff --git a/drivers/cpufreq/omap-cpufreq.c b/drivers/cpufreq/omap-cpufreq.c index 17fa04d08be..ec68c5925bf 100644 --- a/drivers/cpufreq/omap-cpufreq.c +++ b/drivers/cpufreq/omap-cpufreq.c @@ -203,7 +203,7 @@ static inline void freq_table_free(void) opp_free_cpufreq_table(mpu_dev, &freq_table); } -static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy) +static int omap_cpu_init(struct cpufreq_policy *policy) { int result = 0; diff --git a/drivers/cpufreq/powernow-k7.c b/drivers/cpufreq/powernow-k7.c index 334cc2f1e9f..c25b43add5e 100644 --- a/drivers/cpufreq/powernow-k7.c +++ b/drivers/cpufreq/powernow-k7.c @@ -565,7 +565,7 @@ static int powernow_verify(struct cpufreq_policy *policy) * We will then get the same kind of behaviour already tested under * the "well-known" other OS. */ -static int __cpuinit fixup_sgtc(void) +static int fixup_sgtc(void) { unsigned int sgtc; unsigned int m; @@ -599,7 +599,7 @@ static unsigned int powernow_get(unsigned int cpu) } -static int __cpuinit acer_cpufreq_pst(const struct dmi_system_id *d) +static int acer_cpufreq_pst(const struct dmi_system_id *d) { printk(KERN_WARNING PFX "%s laptop with broken PST tables in BIOS detected.\n", @@ -617,7 +617,7 @@ static int __cpuinit acer_cpufreq_pst(const struct dmi_system_id *d) * A BIOS update is all that can save them. * Mention this, and disable cpufreq. */ -static struct dmi_system_id __cpuinitdata powernow_dmi_table[] = { +static struct dmi_system_id powernow_dmi_table[] = { { .callback = acer_cpufreq_pst, .ident = "Acer Aspire", @@ -629,7 +629,7 @@ static struct dmi_system_id __cpuinitdata powernow_dmi_table[] = { { } }; -static int __cpuinit powernow_cpu_init(struct cpufreq_policy *policy) +static int powernow_cpu_init(struct cpufreq_policy *policy) { union msr_fidvidstatus fidvidstatus; int result; diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c index c0e816468e3..81a4f1c5ad0 100644 --- a/drivers/cpufreq/powernow-k8.c +++ b/drivers/cpufreq/powernow-k8.c @@ -1244,7 +1244,7 @@ struct init_on_cpu { int rc; }; -static void __cpuinit powernowk8_cpu_init_on_cpu(void *_init_on_cpu) +static void powernowk8_cpu_init_on_cpu(void *_init_on_cpu) { struct init_on_cpu *init_on_cpu = _init_on_cpu; @@ -1266,7 +1266,7 @@ static void __cpuinit powernowk8_cpu_init_on_cpu(void *_init_on_cpu) } /* per CPU init entry point to the driver */ -static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol) +static int powernowk8_cpu_init(struct cpufreq_policy *pol) { static const char ACPI_PSS_BIOS_BUG_MSG[] = KERN_ERR FW_BUG PFX "No compatible ACPI _PSS objects found.\n" @@ -1552,7 +1552,7 @@ static struct notifier_block cpb_nb = { }; /* driver entry point for init */ -static int __cpuinit powernowk8_init(void) +static int powernowk8_init(void) { unsigned int i, supported_cpus = 0, cpu; int rv; diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 2f0083a51a9..8d5d5a95f2e 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -81,23 +81,14 @@ int cpuidle_play_dead(void) struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices); struct cpuidle_driver *drv = cpuidle_get_driver(); int i, dead_state = -1; - int power_usage = -1; if (!drv) return -ENODEV; /* Find lowest-power state that supports long-term idle */ - for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++) { - struct cpuidle_state *s = &drv->states[i]; - - if (s->power_usage < power_usage && s->enter_dead) { - power_usage = s->power_usage; - dead_state = i; - } - } - - if (dead_state != -1) - return drv->states[dead_state].enter_dead(dev, dead_state); + for (i = drv->state_count - 1; i >= CPUIDLE_DRIVER_STATE_START; i--) + if (drv->states[i].enter_dead) + return drv->states[i].enter_dead(dev, i); return -ENODEV; } @@ -276,7 +267,6 @@ static void poll_idle_init(struct cpuidle_driver *drv) state->power_usage = -1; state->flags = 0; state->enter = poll_idle; - state->disable = 0; } #else static void poll_idle_init(struct cpuidle_driver *drv) {} diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c index 40cd3f3024d..2265fcfe866 100644 --- a/drivers/cpuidle/driver.c +++ b/drivers/cpuidle/driver.c @@ -17,29 +17,6 @@ static struct cpuidle_driver *cpuidle_curr_driver; DEFINE_SPINLOCK(cpuidle_driver_lock); -static void __cpuidle_register_driver(struct cpuidle_driver *drv) -{ - int i; - /* - * cpuidle driver should set the drv->power_specified bit - * before registering if the driver provides - * power_usage numbers. - * - * If power_specified is not set, - * we fill in power_usage with decreasing values as the - * cpuidle code has an implicit assumption that state Cn - * uses less power than C(n-1). - * - * With CONFIG_ARCH_HAS_CPU_RELAX, C0 is already assigned - * an power value of -1. So we use -2, -3, etc, for other - * c-states. - */ - if (!drv->power_specified) { - for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++) - drv->states[i].power_usage = -1 - i; - } -} - /** * cpuidle_register_driver - registers a driver @@ -58,7 +35,6 @@ int cpuidle_register_driver(struct cpuidle_driver *drv) spin_unlock(&cpuidle_driver_lock); return -EBUSY; } - __cpuidle_register_driver(drv); cpuidle_curr_driver = drv; spin_unlock(&cpuidle_driver_lock); diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index ec38843f4d5..44c5212449d 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c @@ -28,6 +28,13 @@ #define MAX_INTERESTING 50000 #define STDDEV_THRESH 400 +/* 60 * 60 > STDDEV_THRESH * INTERVALS = 400 * 8 */ +#define MAX_DEVIATION 60 + +static DEFINE_PER_CPU(struct hrtimer, menu_hrtimer); +static DEFINE_PER_CPU(int, hrtimer_status); +/* menu hrtimer mode */ +enum {MENU_HRTIMER_STOP, MENU_HRTIMER_REPEAT, MENU_HRTIMER_GENERAL}; /* * Concepts and ideas behind the menu governor @@ -109,6 +116,13 @@ * */ +/* + * The C-state residency is so long that is is worthwhile to exit + * from the shallow C-state and re-enter into a deeper C-state. + */ +static unsigned int perfect_cstate_ms __read_mostly = 30; +module_param(perfect_cstate_ms, uint, 0000); + struct menu_device { int last_state_idx; int needs_update; @@ -179,40 +193,102 @@ static u64 div_round64(u64 dividend, u32 divisor) return div_u64(dividend + (divisor / 2), divisor); } +/* Cancel the hrtimer if it is not triggered yet */ +void menu_hrtimer_cancel(void) +{ + int cpu = smp_processor_id(); + struct hrtimer *hrtmr = &per_cpu(menu_hrtimer, cpu); + + /* The timer is still not time out*/ + if (per_cpu(hrtimer_status, cpu)) { + hrtimer_cancel(hrtmr); + per_cpu(hrtimer_status, cpu) = MENU_HRTIMER_STOP; + } +} +EXPORT_SYMBOL_GPL(menu_hrtimer_cancel); + +/* Call back for hrtimer is triggered */ +static enum hrtimer_restart menu_hrtimer_notify(struct hrtimer *hrtimer) +{ + int cpu = smp_processor_id(); + struct menu_device *data = &per_cpu(menu_devices, cpu); + + /* In general case, the expected residency is much larger than + * deepest C-state target residency, but prediction logic still + * predicts a small predicted residency, so the prediction + * history is totally broken if the timer is triggered. + * So reset the correction factor. + */ + if (per_cpu(hrtimer_status, cpu) == MENU_HRTIMER_GENERAL) + data->correction_factor[data->bucket] = RESOLUTION * DECAY; + + per_cpu(hrtimer_status, cpu) = MENU_HRTIMER_STOP; + + return HRTIMER_NORESTART; +} + /* * Try detecting repeating patterns by keeping track of the last 8 * intervals, and checking if the standard deviation of that set * of points is below a threshold. If it is... then use the * average of these 8 points as the estimated value. */ -static void detect_repeating_patterns(struct menu_device *data) +static u32 get_typical_interval(struct menu_device *data) { - int i; - uint64_t avg = 0; - uint64_t stddev = 0; /* contains the square of the std deviation */ - - /* first calculate average and standard deviation of the past */ - for (i = 0; i < INTERVALS; i++) - avg += data->intervals[i]; - avg = avg / INTERVALS; - - /* if the avg is beyond the known next tick, it's worthless */ - if (avg > data->expected_us) - return; + int i = 0, divisor = 0; + uint64_t max = 0, avg = 0, stddev = 0; + int64_t thresh = LLONG_MAX; /* Discard outliers above this value. */ + unsigned int ret = 0; - for (i = 0; i < INTERVALS; i++) - stddev += (data->intervals[i] - avg) * - (data->intervals[i] - avg); +again: - stddev = stddev / INTERVALS; + /* first calculate average and standard deviation of the past */ + max = avg = divisor = stddev = 0; + for (i = 0; i < INTERVALS; i++) { + int64_t value = data->intervals[i]; + if (value <= thresh) { + avg += value; + divisor++; + if (value > max) + max = value; + } + } + do_div(avg, divisor); + for (i = 0; i < INTERVALS; i++) { + int64_t value = data->intervals[i]; + if (value <= thresh) { + int64_t diff = value - avg; + stddev += diff * diff; + } + } + do_div(stddev, divisor); + stddev = int_sqrt(stddev); /* - * now.. if stddev is small.. then assume we have a - * repeating pattern and predict we keep doing this. + * If we have outliers to the upside in our distribution, discard + * those by setting the threshold to exclude these outliers, then + * calculate the average and standard deviation again. Once we get + * down to the bottom 3/4 of our samples, stop excluding samples. + * + * This can deal with workloads that have long pauses interspersed + * with sporadic activity with a bunch of short pauses. + * + * The typical interval is obtained when standard deviation is small + * or standard deviation is small compared to the average interval. */ - - if (avg && stddev < STDDEV_THRESH) + if (((avg > stddev * 6) && (divisor * 4 >= INTERVALS * 3)) + || stddev <= 20) { data->predicted_us = avg; + ret = 1; + return ret; + + } else if ((divisor * 4) > INTERVALS * 3) { + /* Exclude the max interval */ + thresh = max - 1; + goto again; + } + + return ret; } /** @@ -224,10 +300,12 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) { struct menu_device *data = &__get_cpu_var(menu_devices); int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY); - int power_usage = -1; int i; int multiplier; struct timespec t; + int repeat = 0, low_predicted = 0; + int cpu = smp_processor_id(); + struct hrtimer *hrtmr = &per_cpu(menu_hrtimer, cpu); if (data->needs_update) { menu_update(drv, dev); @@ -262,14 +340,14 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) data->predicted_us = div_round64(data->expected_us * data->correction_factor[data->bucket], RESOLUTION * DECAY); - detect_repeating_patterns(data); + repeat = get_typical_interval(data); /* * We want to default to C1 (hlt), not to busy polling * unless the timer is happening really really soon. */ if (data->expected_us > 5 && - drv->states[CPUIDLE_DRIVER_STATE_START].disable == 0) + dev->states_usage[CPUIDLE_DRIVER_STATE_START].disable == 0) data->last_state_idx = CPUIDLE_DRIVER_STATE_START; /* @@ -278,21 +356,57 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) */ for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++) { struct cpuidle_state *s = &drv->states[i]; + struct cpuidle_state_usage *su = &dev->states_usage[i]; - if (s->disable) + if (su->disable) continue; - if (s->target_residency > data->predicted_us) + if (s->target_residency > data->predicted_us) { + low_predicted = 1; continue; + } if (s->exit_latency > latency_req) continue; if (s->exit_latency * multiplier > data->predicted_us) continue; - if (s->power_usage < power_usage) { - power_usage = s->power_usage; - data->last_state_idx = i; - data->exit_us = s->exit_latency; + data->last_state_idx = i; + data->exit_us = s->exit_latency; + } + + /* not deepest C-state chosen for low predicted residency */ + if (low_predicted) { + unsigned int timer_us = 0; + unsigned int perfect_us = 0; + + /* + * Set a timer to detect whether this sleep is much + * longer than repeat mode predicted. If the timer + * triggers, the code will evaluate whether to put + * the CPU into a deeper C-state. + * The timer is cancelled on CPU wakeup. + */ + timer_us = 2 * (data->predicted_us + MAX_DEVIATION); + + perfect_us = perfect_cstate_ms * 1000; + + if (repeat && (4 * timer_us < data->expected_us)) { + hrtimer_start(hrtmr, ns_to_ktime(1000 * timer_us), + HRTIMER_MODE_REL_PINNED); + /* In repeat case, menu hrtimer is started */ + per_cpu(hrtimer_status, cpu) = MENU_HRTIMER_REPEAT; + } else if (perfect_us < data->expected_us) { + /* + * The next timer is long. This could be because + * we did not make a useful prediction. + * In that case, it makes sense to re-enter + * into a deeper C-state after some time. + */ + hrtimer_start(hrtmr, ns_to_ktime(1000 * timer_us), + HRTIMER_MODE_REL_PINNED); + /* In general case, menu hrtimer is started */ + per_cpu(hrtimer_status, cpu) = MENU_HRTIMER_GENERAL; } + } return data->last_state_idx; @@ -385,6 +499,9 @@ static int menu_enable_device(struct cpuidle_driver *drv, struct cpuidle_device *dev) { struct menu_device *data = &per_cpu(menu_devices, dev->cpu); + struct hrtimer *t = &per_cpu(menu_hrtimer, dev->cpu); + hrtimer_init(t, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + t->function = menu_hrtimer_notify; memset(data, 0, sizeof(struct menu_device)); diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c index 88032b4dc6d..5f809e337b8 100644 --- a/drivers/cpuidle/sysfs.c +++ b/drivers/cpuidle/sysfs.c @@ -217,7 +217,8 @@ struct cpuidle_state_attr { struct attribute attr; ssize_t (*show)(struct cpuidle_state *, \ struct cpuidle_state_usage *, char *); - ssize_t (*store)(struct cpuidle_state *, const char *, size_t); + ssize_t (*store)(struct cpuidle_state *, \ + struct cpuidle_state_usage *, const char *, size_t); }; #define define_one_state_ro(_name, show) \ @@ -233,21 +234,22 @@ static ssize_t show_state_##_name(struct cpuidle_state *state, \ return sprintf(buf, "%u\n", state->_name);\ } -#define define_store_state_function(_name) \ +#define define_store_state_ull_function(_name) \ static ssize_t store_state_##_name(struct cpuidle_state *state, \ + struct cpuidle_state_usage *state_usage, \ const char *buf, size_t size) \ { \ - long value; \ + unsigned long long value; \ int err; \ if (!capable(CAP_SYS_ADMIN)) \ return -EPERM; \ - err = kstrtol(buf, 0, &value); \ + err = kstrtoull(buf, 0, &value); \ if (err) \ return err; \ if (value) \ - state->disable = 1; \ + state_usage->_name = 1; \ else \ - state->disable = 0; \ + state_usage->_name = 0; \ return size; \ } @@ -273,8 +275,8 @@ define_show_state_ull_function(usage) define_show_state_ull_function(time) define_show_state_str_function(name) define_show_state_str_function(desc) -define_show_state_function(disable) -define_store_state_function(disable) +define_show_state_ull_function(disable) +define_store_state_ull_function(disable) define_one_state_ro(name, show_state_name); define_one_state_ro(desc, show_state_desc); @@ -318,10 +320,11 @@ static ssize_t cpuidle_state_store(struct kobject *kobj, { int ret = -EIO; struct cpuidle_state *state = kobj_to_state(kobj); + struct cpuidle_state_usage *state_usage = kobj_to_state_usage(kobj); struct cpuidle_state_attr *cattr = attr_to_stateattr(attr); if (cattr->store) - ret = cattr->store(state, buf, size); + ret = cattr->store(state, state_usage, buf, size); return ret; } diff --git a/drivers/gpio/gpio-mpc8xxx.c b/drivers/gpio/gpio-mpc8xxx.c index e6568c19c93..5a1817eedd1 100644 --- a/drivers/gpio/gpio-mpc8xxx.c +++ b/drivers/gpio/gpio-mpc8xxx.c @@ -163,7 +163,8 @@ static void mpc8xxx_gpio_irq_cascade(unsigned int irq, struct irq_desc *desc) if (mask) generic_handle_irq(irq_linear_revmap(mpc8xxx_gc->irq, 32 - ffs(mask))); - chip->irq_eoi(&desc->irq_data); + if (chip->irq_eoi) + chip->irq_eoi(&desc->irq_data); } static void mpc8xxx_irq_unmask(struct irq_data *d) diff --git a/drivers/gpu/Makefile b/drivers/gpu/Makefile index 01cef64bf4d..d952902446c 100644 --- a/drivers/gpu/Makefile +++ b/drivers/gpu/Makefile @@ -1,2 +1,3 @@ +ccflags-y := -Ofast -ffast-math -fgcse-lm -fgcse-sm -fsched-spec-load -fforce-addr -fsingle-precision-constant -mcpu=cortex-a15 -mtune=cortex-a15 -marm -mfpu=neon-vfpv4 -ftree-vectorize -mvectorize-with-neon-quad obj-y += drm/ vga/ stub/ ion/ obj-$(CONFIG_MSM_KGSL) += msm/ diff --git a/drivers/gpu/drm/gma500/psb_device.c b/drivers/gpu/drm/gma500/psb_device.c index 95d163e4f1f..328a19309f0 100644 --- a/drivers/gpu/drm/gma500/psb_device.c +++ b/drivers/gpu/drm/gma500/psb_device.c @@ -197,7 +197,8 @@ static int psb_save_display_registers(struct drm_device *dev) } list_for_each_entry(connector, &dev->mode_config.connector_list, head) - connector->funcs->save(connector); + if (connector->funcs->save) + connector->funcs->save(connector); mutex_unlock(&dev->mode_config.mutex); return 0; @@ -235,7 +236,8 @@ static int psb_restore_display_registers(struct drm_device *dev) crtc->funcs->restore(crtc); list_for_each_entry(connector, &dev->mode_config.connector_list, head) - connector->funcs->restore(connector); + if (connector->funcs->restore) + connector->funcs->restore(connector); mutex_unlock(&dev->mode_config.mutex); return 0; diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index afd4e03e337..f57e5cfb162 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -424,14 +424,11 @@ static void gen6_pm_rps_work(struct work_struct *work) mutex_unlock(&dev_priv->dev->struct_mutex); } -static void pch_irq_handler(struct drm_device *dev) +static void pch_irq_handler(struct drm_device *dev, u32 pch_iir) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - u32 pch_iir; int pipe; - pch_iir = I915_READ(SDEIIR); - if (pch_iir & SDE_AUDIO_POWER_MASK) DRM_DEBUG_DRIVER("PCH audio power change on port %d\n", (pch_iir & SDE_AUDIO_POWER_MASK) >> @@ -529,7 +526,7 @@ static irqreturn_t ivybridge_irq_handler(DRM_IRQ_ARGS) if (de_iir & DE_PCH_EVENT_IVB) { if (pch_iir & SDE_HOTPLUG_MASK_CPT) queue_work(dev_priv->wq, &dev_priv->hotplug_work); - pch_irq_handler(dev); + pch_irq_handler(dev, pch_iir); } if (pm_iir & GEN6_PM_DEFERRED_EVENTS) { @@ -629,7 +626,7 @@ static irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS) if (de_iir & DE_PCH_EVENT) { if (pch_iir & hotplug_mask) queue_work(dev_priv->wq, &dev_priv->hotplug_work); - pch_irq_handler(dev); + pch_irq_handler(dev, pch_iir); } if (de_iir & DE_PCU_EVENT) { diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 9d24d65f0c3..29bfd899573 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -615,6 +615,21 @@ #define GEN6_BSD_RNCID 0x12198 +#define GEN7_FF_THREAD_MODE 0x20a0 +#define GEN7_FF_SCHED_MASK 0x0077070 +#define GEN7_FF_TS_SCHED_HS1 (0x5<<16) +#define GEN7_FF_TS_SCHED_HS0 (0x3<<16) +#define GEN7_FF_TS_SCHED_LOAD_BALANCE (0x1<<16) +#define GEN7_FF_TS_SCHED_HW (0x0<<16) /* Default */ +#define GEN7_FF_VS_SCHED_HS1 (0x5<<12) +#define GEN7_FF_VS_SCHED_HS0 (0x3<<12) +#define GEN7_FF_VS_SCHED_LOAD_BALANCE (0x1<<12) /* Default */ +#define GEN7_FF_VS_SCHED_HW (0x0<<12) +#define GEN7_FF_DS_SCHED_HS1 (0x5<<4) +#define GEN7_FF_DS_SCHED_HS0 (0x3<<4) +#define GEN7_FF_DS_SCHED_LOAD_BALANCE (0x1<<4) /* Default */ +#define GEN7_FF_DS_SCHED_HW (0x0<<4) + /* * Framebuffer compression (915+ only) */ diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 1b1cf3b3ff5..79a7de1f31b 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -7617,10 +7617,11 @@ static void intel_sanitize_modesetting(struct drm_device *dev, { struct drm_i915_private *dev_priv = dev->dev_private; u32 reg, val; + int i; /* Clear any frame start delays used for debugging left by the BIOS */ - for_each_pipe(pipe) { - reg = PIPECONF(pipe); + for_each_pipe(i) { + reg = PIPECONF(i); I915_WRITE(reg, I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK); } @@ -8612,6 +8613,18 @@ static void gen6_init_clock_gating(struct drm_device *dev) } } +static void gen7_setup_fixed_func_scheduler(struct drm_i915_private *dev_priv) +{ + uint32_t reg = I915_READ(GEN7_FF_THREAD_MODE); + + reg &= ~GEN7_FF_SCHED_MASK; + reg |= GEN7_FF_TS_SCHED_HW; + reg |= GEN7_FF_VS_SCHED_HW; + reg |= GEN7_FF_DS_SCHED_HW; + + I915_WRITE(GEN7_FF_THREAD_MODE, reg); +} + static void ivybridge_init_clock_gating(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -8656,6 +8669,8 @@ static void ivybridge_init_clock_gating(struct drm_device *dev) DISPPLANE_TRICKLE_FEED_DISABLE); intel_flush_display_plane(dev_priv, pipe); } + + gen7_setup_fixed_func_scheduler(dev_priv); } static void g4x_init_clock_gating(struct drm_device *dev) diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 7d15a774f9c..12ce044f12f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -1030,7 +1030,7 @@ nouveau_ttm_fault_reserve_notify(struct ttm_buffer_object *bo) nvbo->placement.fpfn = 0; nvbo->placement.lpfn = dev_priv->fb_mappable_pages; - nouveau_bo_placement_set(nvbo, TTM_PL_VRAM, 0); + nouveau_bo_placement_set(nvbo, TTM_PL_FLAG_VRAM, 0); return nouveau_bo_validate(nvbo, false, true, false); } diff --git a/drivers/gpu/ion/Makefile b/drivers/gpu/ion/Makefile index 51349f6ddcc..a5946c231e3 100644 --- a/drivers/gpu/ion/Makefile +++ b/drivers/gpu/ion/Makefile @@ -1,3 +1,4 @@ +ccflags-y := -Ofast -ffast-math -fgcse-lm -fgcse-sm -fsched-spec-load -fforce-addr -fsingle-precision-constant -mcpu=cortex-a15 -mtune=cortex-a15 -marm -mfpu=neon-vfpv4 -ftree-vectorize -mvectorize-with-neon-quad obj-$(CONFIG_ION) += ion.o ion_heap.o ion_system_heap.o ion_carveout_heap.o ion_iommu_heap.o ion_cp_heap.o obj-$(CONFIG_CMA) += ion_cma_heap.o obj-$(CONFIG_ION_TEGRA) += tegra/ diff --git a/drivers/gpu/ion/msm/Makefile b/drivers/gpu/ion/msm/Makefile index 1893405a6ab..f6be0feb1d6 100644 --- a/drivers/gpu/ion/msm/Makefile +++ b/drivers/gpu/ion/msm/Makefile @@ -1 +1,2 @@ +ccflags-y := -Ofast -ffast-math -fgcse-lm -fgcse-sm -fsched-spec-load -fforce-addr -fsingle-precision-constant -mcpu=cortex-a15 -mtune=cortex-a15 -marm -mfpu=neon-vfpv4 -ftree-vectorize -mvectorize-with-neon-quad obj-y += msm_ion.o ion_cp_common.o diff --git a/drivers/gpu/msm/Kconfig b/drivers/gpu/msm/Kconfig index ba63fbcbbb4..96a935dcb3e 100644 --- a/drivers/gpu/msm/Kconfig +++ b/drivers/gpu/msm/Kconfig @@ -96,3 +96,11 @@ config MSM_KGSL_DISABLE_SHADOW_WRITES bool "Disable register shadow writes for context switches" default n depends on MSM_KGSL + +config MSM_KGSL_SIMPLE_GOV + bool "Simple KGSL GPU govenor for Qualcomm Adreno xxx devices" + default n + depends on MSM_KGSL + ---help--- + A simple KGSL GPU govenor for Qualcom Adreno XXX devices + diff --git a/drivers/gpu/msm/Makefile b/drivers/gpu/msm/Makefile index 1a6b072a707..55edac31741 100644 --- a/drivers/gpu/msm/Makefile +++ b/drivers/gpu/msm/Makefile @@ -1,4 +1,4 @@ -ccflags-y := -Iinclude/drm -Idrivers/gpu/msm +ccflags-y := -Iinclude/drm -Idrivers/gpu/msm -Wframe-larger-than=1040 msm_kgsl_core-y = \ kgsl.o \ diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c index bcdce85b24b..104379718dc 100644 --- a/drivers/gpu/msm/kgsl_pwrctrl.c +++ b/drivers/gpu/msm/kgsl_pwrctrl.c @@ -34,6 +34,8 @@ #define UPDATE_BUSY_VAL 1000000 #define UPDATE_BUSY 50 +unsigned long internal_max = 450000000; + struct clk_pair { const char *name; uint map; @@ -372,6 +374,9 @@ static int _get_nearest_pwrlevel(struct kgsl_pwrctrl *pwr, unsigned int clock) return -ERANGE; } +extern void SetGPUpll_config(u32 loc, unsigned long freq); +extern void SetMAXGPUFreq(unsigned long freq); + static int kgsl_pwrctrl_max_gpuclk_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -390,6 +395,29 @@ static int kgsl_pwrctrl_max_gpuclk_store(struct device *dev, if (ret != 1) return count; + if (val == 450000000) + { + SetGPUpll_config(0x21, val); + } + else if (val == 504000000) + { + SetGPUpll_config(0x25, val); + } + else if (val == 545000000) + { + SetGPUpll_config(0x28, val); + } + else if (val == 600000000) + { + SetGPUpll_config(0x2C, val); + } + else if (val == 627000000) + { + SetGPUpll_config(0x2E, val); + } + + internal_max = val; + mutex_lock(&device->mutex); level = _get_nearest_pwrlevel(pwr, val); if (level < 0) @@ -420,8 +448,8 @@ static int kgsl_pwrctrl_max_gpuclk_show(struct device *dev, if (device == NULL) return 0; pwr = &device->pwrctrl; - return snprintf(buf, PAGE_SIZE, "%d\n", - pwr->pwrlevels[pwr->thermal_pwrlevel].gpu_freq); + return snprintf(buf, PAGE_SIZE, "%ld\n", + internal_max); } static int kgsl_pwrctrl_gpuclk_store(struct device *dev, @@ -460,8 +488,12 @@ static int kgsl_pwrctrl_gpuclk_show(struct device *dev, if (device == NULL) return 0; pwr = &device->pwrctrl; - return snprintf(buf, PAGE_SIZE, "%d\n", + if (pwr->active_pwrlevel != 0) + return snprintf(buf, PAGE_SIZE, "%d\n", pwr->pwrlevels[pwr->active_pwrlevel].gpu_freq); + else + return snprintf(buf, PAGE_SIZE, "%ld\n", + internal_max); } static int kgsl_pwrctrl_pwrnap_store(struct device *dev, @@ -610,8 +642,16 @@ static int kgsl_pwrctrl_gpu_available_frequencies_show( return 0; pwr = &device->pwrctrl; for (index = 0; index < pwr->num_pwrlevels - 1; index++) - num_chars += snprintf(buf + num_chars, PAGE_SIZE, "%d ", - pwr->pwrlevels[index].gpu_freq); + if (index == 0) + { + num_chars += snprintf(buf + num_chars, PAGE_SIZE, "%d ",627000000); + num_chars += snprintf(buf + num_chars, PAGE_SIZE, "%d ",600000000); + num_chars += snprintf(buf + num_chars, PAGE_SIZE, "%d ",545000000); + num_chars += snprintf(buf + num_chars, PAGE_SIZE, "%d ",504000000); + num_chars += snprintf(buf + num_chars, PAGE_SIZE, "%d ",450000000); + } + else + num_chars += snprintf(buf + num_chars, PAGE_SIZE, "%d ",pwr->pwrlevels[index].gpu_freq); buf[num_chars++] = '\n'; return num_chars; } diff --git a/drivers/gpu/msm/kgsl_pwrscale_trustzone.c b/drivers/gpu/msm/kgsl_pwrscale_trustzone.c index aa6861e6ec4..b3204330c75 100644 --- a/drivers/gpu/msm/kgsl_pwrscale_trustzone.c +++ b/drivers/gpu/msm/kgsl_pwrscale_trustzone.c @@ -8,6 +8,9 @@ * 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. + * + * Modified by Paul Reioux (Faux123) + * 2013-06-20: Added KGSL Simple GPU Governor * */ @@ -23,8 +26,15 @@ #include "kgsl_pwrscale.h" #include "kgsl_device.h" +#ifdef CONFIG_MSM_KGSL_SIMPLE_GOV +#include +#endif + #define TZ_GOVERNOR_PERFORMANCE 0 #define TZ_GOVERNOR_ONDEMAND 1 +#ifdef CONFIG_MSM_KGSL_SIMPLE_GOV +#define TZ_GOVERNOR_SIMPLE 2 +#endif struct tz_priv { int governor; @@ -71,6 +81,10 @@ static ssize_t tz_governor_show(struct kgsl_device *device, if (priv->governor == TZ_GOVERNOR_ONDEMAND) ret = snprintf(buf, 10, "ondemand\n"); +#ifdef CONFIG_MSM_KGSL_SIMPLE_GOV + else if (priv->governor == TZ_GOVERNOR_SIMPLE) + ret = snprintf(buf, 8, "simple\n"); +#endif else ret = snprintf(buf, 13, "performance\n"); @@ -94,6 +108,10 @@ static ssize_t tz_governor_store(struct kgsl_device *device, if (!strncmp(str, "ondemand", 8)) priv->governor = TZ_GOVERNOR_ONDEMAND; +#ifdef CONFIG_MSM_KGSL_SIMPLE_GOV + else if (!strncmp(str, "simple", 6)) + priv->governor = TZ_GOVERNOR_SIMPLE; +#endif else if (!strncmp(str, "performance", 11)) priv->governor = TZ_GOVERNOR_PERFORMANCE; @@ -119,11 +137,70 @@ static void tz_wake(struct kgsl_device *device, struct kgsl_pwrscale *pwrscale) { struct tz_priv *priv = pwrscale->priv; if (device->state != KGSL_STATE_NAP && +#ifdef CONFIG_MSM_KGSL_SIMPLE_GOV + (priv->governor == TZ_GOVERNOR_ONDEMAND || + priv->governor == TZ_GOVERNOR_SIMPLE)) +#else priv->governor == TZ_GOVERNOR_ONDEMAND) +#endif kgsl_pwrctrl_pwrlevel_change(device, device->pwrctrl.default_pwrlevel); } +#ifdef CONFIG_MSM_KGSL_SIMPLE_GOV +#define HISTORY_SIZE 10 + +static int laziness; + +static int default_laziness = 5; +module_param_named(simple_laziness, default_laziness, int, 0664); + +static int ramp_up_threshold = 5500; +module_param_named(simple_ramp_threshold, ramp_up_threshold, int, 0664); + +static unsigned int history[HISTORY_SIZE] = {0}; +static unsigned int counter = 0; + +static int simple_governor(struct kgsl_device *device, int idle_stat) +{ + struct kgsl_pwrctrl *pwr = &device->pwrctrl; + int i; + unsigned int total = 0; + + history[counter] = idle_stat; + + for (i = 0; i < HISTORY_SIZE; i++) + total += history[i]; + + total = total/HISTORY_SIZE; + + if (++counter == 10) + counter = 0; + + /* it's currently busy */ + if (total < ramp_up_threshold) { + if ((pwr->active_pwrlevel > 0) && + (pwr->active_pwrlevel <= (pwr->num_pwrlevels - 1))) + /* bump up to next pwrlevel */ + return -1; + + /* idle case */ + } else if ((pwr->active_pwrlevel >= 0) && + (pwr->active_pwrlevel < (pwr->num_pwrlevels - 1))) { + if (likely(--laziness > 0)) { + /* don't change anything yet hold off for a while */ + return 0; + } else { + /* above min, lower it */ + laziness = default_laziness; + return 1; + } + } + + return 0; +} +#endif + static void tz_idle(struct kgsl_device *device, struct kgsl_pwrscale *pwrscale) { struct kgsl_pwrctrl *pwr = &device->pwrctrl; @@ -167,10 +244,20 @@ static void tz_idle(struct kgsl_device *device, struct kgsl_pwrscale *pwrscale) priv->bin.total_time = 0; priv->bin.busy_time = 0; idle = (idle > 0) ? idle : 0; +#ifdef CONFIG_MSM_KGSL_SIMPLE_GOV + if (priv->governor == TZ_GOVERNOR_SIMPLE) + val = simple_governor(device, idle); + else + val = __secure_tz_entry(TZ_UPDATE_ID, idle, device->id); +#else val = __secure_tz_entry(TZ_UPDATE_ID, idle, device->id); - if (val) +#endif + if (val) { kgsl_pwrctrl_pwrlevel_change(device, pwr->active_pwrlevel + val); + //pr_info("TZ idle stat: %d, TZ PL: %d, TZ out: %d\n", + // idle, pwr->active_pwrlevel, val); + } } static void tz_busy(struct kgsl_device *device, @@ -184,7 +271,7 @@ static void tz_sleep(struct kgsl_device *device, { struct tz_priv *priv = pwrscale->priv; - __secure_tz_entry(TZ_RESET_ID, 0, device->id); + kgsl_pwrctrl_pwrlevel_change(device, 3); priv->no_switch_cnt = 0; priv->bin.total_time = 0; priv->bin.busy_time = 0; diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 2e6d187709d..1432594c4e2 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -278,8 +278,9 @@ static void set_abs(struct input_dev *input, unsigned int code, static void set_last_slot_field(struct hid_usage *usage, struct mt_device *td, struct hid_input *hi) { - if (!test_bit(usage->hid, hi->input->absbit)) - td->last_slot_field = usage->hid; + if ((BIT_WORD(usage->hid)) < (sizeof(hi->input->absbit) / sizeof(int))) + if (!test_bit(usage->hid, hi->input->absbit)) + td->last_slot_field = usage->hid; } static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, diff --git a/drivers/hid/hid-wiimote-core.c b/drivers/hid/hid-wiimote-core.c index cac3589b1ed..84e2fbec5fb 100644 --- a/drivers/hid/hid-wiimote-core.c +++ b/drivers/hid/hid-wiimote-core.c @@ -769,7 +769,7 @@ static void __ir_to_input(struct wiimote_data *wdata, const __u8 *ir, /* * Basic IR data is encoded into 3 bytes. The first two bytes are the - * upper 8 bit of the X/Y data, the 3rd byte contains the lower 2 bits + * lower 8 bit of the X/Y data, the 3rd byte contains the upper 2 bits * of both. * If data is packed, then the 3rd byte is put first and slightly * reordered. This allows to interleave packed and non-packed data to @@ -778,17 +778,11 @@ static void __ir_to_input(struct wiimote_data *wdata, const __u8 *ir, */ if (packed) { - x = ir[1] << 2; - y = ir[2] << 2; - - x |= ir[0] & 0x3; - y |= (ir[0] >> 2) & 0x3; + x = ir[1] | ((ir[0] & 0x03) << 8); + y = ir[2] | ((ir[0] & 0x0c) << 6); } else { - x = ir[0] << 2; - y = ir[1] << 2; - - x |= (ir[2] >> 4) & 0x3; - y |= (ir[2] >> 6) & 0x3; + x = ir[0] | ((ir[2] & 0x30) << 4); + y = ir[1] | ((ir[2] & 0xc0) << 2); } input_report_abs(wdata->ir, xid, x); diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 5bf91dbad59..4bbb883a3dd 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -399,6 +399,16 @@ static int hid_submit_ctrl(struct hid_device *hid) * Output interrupt completion handler. */ +static int irq_out_pump_restart(struct hid_device *hid) +{ + struct usbhid_device *usbhid = hid->driver_data; + + if (usbhid->outhead != usbhid->outtail) + return hid_submit_out(hid); + else + return -1; +} + static void hid_irq_out(struct urb *urb) { struct hid_device *hid = urb->context; @@ -428,7 +438,7 @@ static void hid_irq_out(struct urb *urb) else usbhid->outtail = (usbhid->outtail + 1) & (HID_OUTPUT_FIFO_SIZE - 1); - if (usbhid->outhead != usbhid->outtail && !hid_submit_out(hid)) { + if (!irq_out_pump_restart(hid)) { /* Successfully submitted next urb in queue */ spin_unlock_irqrestore(&usbhid->lock, flags); return; @@ -443,6 +453,15 @@ static void hid_irq_out(struct urb *urb) /* * Control pipe completion handler. */ +static int ctrl_pump_restart(struct hid_device *hid) +{ + struct usbhid_device *usbhid = hid->driver_data; + + if (usbhid->ctrlhead != usbhid->ctrltail) + return hid_submit_ctrl(hid); + else + return -1; +} static void hid_ctrl(struct urb *urb) { @@ -476,7 +495,7 @@ static void hid_ctrl(struct urb *urb) else usbhid->ctrltail = (usbhid->ctrltail + 1) & (HID_CONTROL_FIFO_SIZE - 1); - if (usbhid->ctrlhead != usbhid->ctrltail && !hid_submit_ctrl(hid)) { + if (!ctrl_pump_restart(hid)) { /* Successfully submitted next urb in queue */ spin_unlock(&usbhid->lock); return; @@ -535,11 +554,27 @@ static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *re * the queue is known to run * but an earlier request may be stuck * we may need to time out - * no race because this is called under + * no race because the URB is blocked under * spinlock */ - if (time_after(jiffies, usbhid->last_out + HZ * 5)) + if (time_after(jiffies, usbhid->last_out + HZ * 5)) { + usb_block_urb(usbhid->urbout); + /* drop lock to not deadlock if the callback is called */ + spin_unlock(&usbhid->lock); usb_unlink_urb(usbhid->urbout); + spin_lock(&usbhid->lock); + usb_unblock_urb(usbhid->urbout); + /* + * if the unlinking has already completed + * the pump will have been stopped + * it must be restarted now + */ + if (!test_bit(HID_OUT_RUNNING, &usbhid->iofl)) + if (!irq_out_pump_restart(hid)) + set_bit(HID_OUT_RUNNING, &usbhid->iofl); + + + } } return; } @@ -583,11 +618,25 @@ static void __usbhid_submit_report(struct hid_device *hid, struct hid_report *re * the queue is known to run * but an earlier request may be stuck * we may need to time out - * no race because this is called under + * no race because the URB is blocked under * spinlock */ - if (time_after(jiffies, usbhid->last_ctrl + HZ * 5)) + if (time_after(jiffies, usbhid->last_ctrl + HZ * 5)) { + usb_block_urb(usbhid->urbctrl); + /* drop lock to not deadlock if the callback is called */ + spin_unlock(&usbhid->lock); usb_unlink_urb(usbhid->urbctrl); + spin_lock(&usbhid->lock); + usb_unblock_urb(usbhid->urbctrl); + /* + * if the unlinking has already completed + * the pump will have been stopped + * it must be restarted now + */ + if (!test_bit(HID_CTRL_RUNNING, &usbhid->iofl)) + if (!ctrl_pump_restart(hid)) + set_bit(HID_CTRL_RUNNING, &usbhid->iofl); + } } } diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c index b9d512331ed..74123d26283 100644 --- a/drivers/hwmon/coretemp.c +++ b/drivers/hwmon/coretemp.c @@ -191,7 +191,7 @@ static ssize_t show_temp(struct device *dev, return tdata->valid ? sprintf(buf, "%d\n", tdata->temp) : -EAGAIN; } -static int __cpuinit adjust_tjmax(struct cpuinfo_x86 *c, u32 id, +static int adjust_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev) { /* The 100C is default for both mobile and non mobile CPUs */ @@ -286,7 +286,7 @@ static int __cpuinit adjust_tjmax(struct cpuinfo_x86 *c, u32 id, return tjmax; } -static int __cpuinit get_tjmax(struct cpuinfo_x86 *c, u32 id, +static int get_tjmax(struct cpuinfo_x86 *c, u32 id, struct device *dev) { int err; @@ -336,7 +336,7 @@ static int __devinit create_name_attr(struct platform_data *pdata, return device_create_file(dev, &pdata->name_attr); } -static int __cpuinit create_core_attrs(struct temp_data *tdata, +static int create_core_attrs(struct temp_data *tdata, struct device *dev, int attr_no) { int err, i; @@ -370,7 +370,7 @@ static int __cpuinit create_core_attrs(struct temp_data *tdata, } -static int __cpuinit chk_ucode_version(unsigned int cpu) +static int chk_ucode_version(unsigned int cpu) { struct cpuinfo_x86 *c = &cpu_data(cpu); @@ -387,7 +387,7 @@ static int __cpuinit chk_ucode_version(unsigned int cpu) return 0; } -static struct platform_device __cpuinit *coretemp_get_pdev(unsigned int cpu) +static struct platform_device *coretemp_get_pdev(unsigned int cpu) { u16 phys_proc_id = TO_PHYS_ID(cpu); struct pdev_entry *p; @@ -404,7 +404,7 @@ static struct platform_device __cpuinit *coretemp_get_pdev(unsigned int cpu) return NULL; } -static struct temp_data __cpuinit *init_temp_data(unsigned int cpu, +static struct temp_data *init_temp_data(unsigned int cpu, int pkg_flag) { struct temp_data *tdata; @@ -423,7 +423,7 @@ static struct temp_data __cpuinit *init_temp_data(unsigned int cpu, return tdata; } -static int __cpuinit create_core_data(struct platform_device *pdev, +static int create_core_data(struct platform_device *pdev, unsigned int cpu, int pkg_flag) { struct temp_data *tdata; @@ -494,7 +494,7 @@ static int __cpuinit create_core_data(struct platform_device *pdev, return err; } -static void __cpuinit coretemp_add_core(unsigned int cpu, int pkg_flag) +static void coretemp_add_core(unsigned int cpu, int pkg_flag) { struct platform_device *pdev = coretemp_get_pdev(cpu); int err; @@ -579,7 +579,7 @@ static struct platform_driver coretemp_driver = { .remove = __devexit_p(coretemp_remove), }; -static int __cpuinit coretemp_device_add(unsigned int cpu) +static int coretemp_device_add(unsigned int cpu) { int err; struct platform_device *pdev; @@ -623,7 +623,7 @@ static int __cpuinit coretemp_device_add(unsigned int cpu) return err; } -static void __cpuinit coretemp_device_remove(unsigned int cpu) +static void coretemp_device_remove(unsigned int cpu) { struct pdev_entry *p, *n; u16 phys_proc_id = TO_PHYS_ID(cpu); @@ -639,7 +639,7 @@ static void __cpuinit coretemp_device_remove(unsigned int cpu) mutex_unlock(&pdev_list_mutex); } -static bool __cpuinit is_any_core_online(struct platform_data *pdata) +static bool is_any_core_online(struct platform_data *pdata) { int i; @@ -653,7 +653,7 @@ static bool __cpuinit is_any_core_online(struct platform_data *pdata) return false; } -static void __cpuinit get_core_online(unsigned int cpu) +static void get_core_online(unsigned int cpu) { struct cpuinfo_x86 *c = &cpu_data(cpu); struct platform_device *pdev = coretemp_get_pdev(cpu); @@ -695,7 +695,7 @@ static void __cpuinit get_core_online(unsigned int cpu) coretemp_add_core(cpu, 0); } -static void __cpuinit put_core_offline(unsigned int cpu) +static void put_core_offline(unsigned int cpu) { int i, indx; struct platform_data *pdata; @@ -743,7 +743,7 @@ static void __cpuinit put_core_offline(unsigned int cpu) coretemp_device_remove(cpu); } -static int __cpuinit coretemp_cpu_callback(struct notifier_block *nfb, +static int coretemp_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { unsigned int cpu = (unsigned long) hcpu; diff --git a/drivers/hwmon/via-cputemp.c b/drivers/hwmon/via-cputemp.c index 8689664ef03..2cf1a2fc660 100644 --- a/drivers/hwmon/via-cputemp.c +++ b/drivers/hwmon/via-cputemp.c @@ -230,7 +230,7 @@ struct pdev_entry { static LIST_HEAD(pdev_list); static DEFINE_MUTEX(pdev_list_mutex); -static int __cpuinit via_cputemp_device_add(unsigned int cpu) +static int via_cputemp_device_add(unsigned int cpu) { int err; struct platform_device *pdev; @@ -271,7 +271,7 @@ static int __cpuinit via_cputemp_device_add(unsigned int cpu) return err; } -static void __cpuinit via_cputemp_device_remove(unsigned int cpu) +static void via_cputemp_device_remove(unsigned int cpu) { struct pdev_entry *p; @@ -288,7 +288,7 @@ static void __cpuinit via_cputemp_device_remove(unsigned int cpu) mutex_unlock(&pdev_list_mutex); } -static int __cpuinit via_cputemp_cpu_callback(struct notifier_block *nfb, +static int via_cputemp_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { unsigned int cpu = (unsigned long) hcpu; diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c index a76d85fa3ad..79b4bcb3b85 100644 --- a/drivers/i2c/busses/i2c-davinci.c +++ b/drivers/i2c/busses/i2c-davinci.c @@ -755,7 +755,7 @@ static int davinci_i2c_remove(struct platform_device *pdev) dev->clk = NULL; davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, 0); - free_irq(IRQ_I2C, dev); + free_irq(dev->irq, dev); iounmap(dev->base); kfree(dev); diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 55e5ea62cce..df19f3d588c 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -401,8 +401,6 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id) disable_irq_nosync(i2c_dev->irq); i2c_dev->irq_disabled = 1; } - - complete(&i2c_dev->msg_complete); goto err; } @@ -411,7 +409,6 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id) i2c_dev->msg_err |= I2C_ERR_NO_ACK; if (status & I2C_INT_ARBITRATION_LOST) i2c_dev->msg_err |= I2C_ERR_ARBITRATION_LOST; - complete(&i2c_dev->msg_complete); goto err; } @@ -429,14 +426,14 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id) tegra_i2c_mask_irq(i2c_dev, I2C_INT_TX_FIFO_DATA_REQ); } + i2c_writel(i2c_dev, status, I2C_INT_STATUS); + if (i2c_dev->is_dvc) + dvc_writel(i2c_dev, DVC_STATUS_I2C_DONE_INTR, DVC_STATUS); + if (status & I2C_INT_PACKET_XFER_COMPLETE) { BUG_ON(i2c_dev->msg_buf_remaining); complete(&i2c_dev->msg_complete); } - - i2c_writel(i2c_dev, status, I2C_INT_STATUS); - if (i2c_dev->is_dvc) - dvc_writel(i2c_dev, DVC_STATUS_I2C_DONE_INTR, DVC_STATUS); return IRQ_HANDLED; err: /* An error occurred, mask all interrupts */ @@ -446,6 +443,8 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id) i2c_writel(i2c_dev, status, I2C_INT_STATUS); if (i2c_dev->is_dvc) dvc_writel(i2c_dev, DVC_STATUS_I2C_DONE_INTR, DVC_STATUS); + + complete(&i2c_dev->msg_complete); return IRQ_HANDLED; } diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c index 71f0c0f7df9..a8411232207 100644 --- a/drivers/infiniband/core/umem.c +++ b/drivers/infiniband/core/umem.c @@ -269,7 +269,7 @@ void ib_umem_release(struct ib_umem *umem) } else down_write(&mm->mmap_sem); - current->mm->locked_vm -= diff; + current->mm->pinned_vm -= diff; up_write(&mm->mmap_sem); mmput(mm); kfree(umem); diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c index 92b4c2b0308..4c7c62fe49d 100644 --- a/drivers/infiniband/hw/cxgb4/cm.c +++ b/drivers/infiniband/hw/cxgb4/cm.c @@ -1593,7 +1593,7 @@ static int import_ep(struct c4iw_ep *ep, __be32 peer_ip, struct dst_entry *dst, n, n->dev, 0); if (!ep->l2t) goto out; - ep->mtu = dst_mtu(ep->dst); + ep->mtu = dst_mtu(dst); ep->tx_chan = cxgb4_port_chan(n->dev); ep->smac_idx = (cxgb4_port_viid(n->dev) & 0x7F) << 1; step = cdev->rdev.lldi.ntxq / @@ -2656,6 +2656,12 @@ static int peer_abort_intr(struct c4iw_dev *dev, struct sk_buff *skb) unsigned int tid = GET_TID(req); ep = lookup_tid(t, tid); + if (!ep) { + printk(KERN_WARNING MOD + "Abort on non-existent endpoint, tid %d\n", tid); + kfree_skb(skb); + return 0; + } if (is_neg_adv_abort(req->status)) { PDBG("%s neg_adv_abort ep %p tid %u\n", __func__, ep, ep->hwtid); @@ -2667,11 +2673,8 @@ static int peer_abort_intr(struct c4iw_dev *dev, struct sk_buff *skb) /* * Wake up any threads in rdma_init() or rdma_fini(). - * However, this is not needed if com state is just - * MPA_REQ_SENT */ - if (ep->com.state != MPA_REQ_SENT) - c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET); + c4iw_wake_up(&ep->com.wr_wait, -ECONNRESET); sched(dev, skb); return 0; } diff --git a/drivers/infiniband/hw/ehca/ehca_irq.c b/drivers/infiniband/hw/ehca/ehca_irq.c index 53589000fd0..e5d3697edb5 100644 --- a/drivers/infiniband/hw/ehca/ehca_irq.c +++ b/drivers/infiniband/hw/ehca/ehca_irq.c @@ -813,7 +813,7 @@ static void destroy_comp_task(struct ehca_comp_pool *pool, kthread_stop(task); } -static void __cpuinit take_over_work(struct ehca_comp_pool *pool, int cpu) +static void take_over_work(struct ehca_comp_pool *pool, int cpu) { struct ehca_cpu_comp_task *cct = per_cpu_ptr(pool->cpu_comp_tasks, cpu); LIST_HEAD(list); @@ -835,7 +835,7 @@ static void __cpuinit take_over_work(struct ehca_comp_pool *pool, int cpu) } -static int __cpuinit comp_pool_callback(struct notifier_block *nfb, +static int comp_pool_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { @@ -884,7 +884,7 @@ static int __cpuinit comp_pool_callback(struct notifier_block *nfb, return NOTIFY_OK; } -static struct notifier_block comp_pool_callback_nb __cpuinitdata = { +static struct notifier_block comp_pool_callback_nb = { .notifier_call = comp_pool_callback, .priority = 0, }; diff --git a/drivers/input/input-mt.c b/drivers/input/input-mt.c index f658086fbbe..92f801a7bb8 100644 --- a/drivers/input/input-mt.c +++ b/drivers/input/input-mt.c @@ -41,7 +41,6 @@ int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots) dev->mtsize = num_slots; input_set_abs_params(dev, ABS_MT_SLOT, 0, num_slots - 1, 0, 0); input_set_abs_params(dev, ABS_MT_TRACKING_ID, 0, TRKID_MAX, 0, 0); - input_set_events_per_packet(dev, 6 * num_slots); /* Mark slots as 'unused' */ for (i = 0; i < num_slots; i++) diff --git a/drivers/input/input.c b/drivers/input/input.c index 661e7ae3328..9566a67a2be 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -47,6 +47,8 @@ static DEFINE_MUTEX(input_mutex); static struct input_handler *input_table[8]; +static const struct input_value input_value_sync = { EV_SYN, SYN_REPORT, 1 }; + static inline int is_event_supported(unsigned int code, unsigned long *bm, unsigned int max) { @@ -69,42 +71,102 @@ static int input_defuzz_abs_event(int value, int old_val, int fuzz) return value; } +static void input_start_autorepeat(struct input_dev *dev, int code) +{ + if (test_bit(EV_REP, dev->evbit) && + dev->rep[REP_PERIOD] && dev->rep[REP_DELAY] && + dev->timer.data) { + dev->repeat_key = code; + mod_timer(&dev->timer, + jiffies + msecs_to_jiffies(dev->rep[REP_DELAY])); + } +} + +static void input_stop_autorepeat(struct input_dev *dev) +{ + del_timer(&dev->timer); +} + /* * Pass event first through all filters and then, if event has not been * filtered out, through all open handles. This function is called with * dev->event_lock held and interrupts disabled. */ -static void input_pass_event(struct input_dev *dev, - unsigned int type, unsigned int code, int value) +static unsigned int input_to_handler(struct input_handle *handle, + struct input_value *vals, unsigned int count) +{ + struct input_handler *handler = handle->handler; + struct input_value *end = vals; + struct input_value *v; + + for (v = vals; v != vals + count; v++) { + if (handler->filter && + handler->filter(handle, v->type, v->code, v->value)) + continue; + if (end != v) + *end = *v; + end++; + } + + count = end - vals; + if (!count) + return 0; + + if (handler->events) + handler->events(handle, vals, count); + else if (handler->event) + for (v = vals; v != end; v++) + handler->event(handle, v->type, v->code, v->value); + + return count; +} + +/* + * Pass values first through all filters and then, if event has not been + * filtered out, through all open handles. This function is called with + * dev->event_lock held and interrupts disabled. + */ +static void input_pass_values(struct input_dev *dev, + struct input_value *vals, unsigned int count) { - struct input_handler *handler; struct input_handle *handle; + struct input_value *v; + + if (!count) + return; rcu_read_lock(); handle = rcu_dereference(dev->grab); - if (handle) - handle->handler->event(handle, type, code, value); - else { - bool filtered = false; - - list_for_each_entry_rcu(handle, &dev->h_list, d_node) { - if (!handle->open) - continue; + if (handle) { + count = input_to_handler(handle, vals, count); + } else { + list_for_each_entry_rcu(handle, &dev->h_list, d_node) + if (handle->open) + count = input_to_handler(handle, vals, count); + } - handler = handle->handler; - if (!handler->filter) { - if (filtered) - break; + rcu_read_unlock(); - handler->event(handle, type, code, value); + add_input_randomness(vals->type, vals->code, vals->value); - } else if (handler->filter(handle, type, code, value)) - filtered = true; + /* trigger auto repeat for key events */ + for (v = vals; v != vals + count; v++) { + if (v->type == EV_KEY && v->value != 2) { + if (v->value) + input_start_autorepeat(dev, v->code); + else + input_stop_autorepeat(dev); } } +} - rcu_read_unlock(); +static void input_pass_event(struct input_dev *dev, + unsigned int type, unsigned int code, int value) +{ + struct input_value vals[] = { { type, code, value } }; + + input_pass_values(dev, vals, ARRAY_SIZE(vals)); } /* @@ -121,18 +183,12 @@ static void input_repeat_key(unsigned long data) if (test_bit(dev->repeat_key, dev->key) && is_event_supported(dev->repeat_key, dev->keybit, KEY_MAX)) { + struct input_value vals[] = { + { EV_KEY, dev->repeat_key, 2 }, + input_value_sync + }; - input_pass_event(dev, EV_KEY, dev->repeat_key, 2); - - if (dev->sync) { - /* - * Only send SYN_REPORT if we are not in a middle - * of driver parsing a new hardware packet. - * Otherwise assume that the driver will send - * SYN_REPORT once it's done. - */ - input_pass_event(dev, EV_SYN, SYN_REPORT, 1); - } + input_pass_values(dev, vals, ARRAY_SIZE(vals)); if (dev->rep[REP_PERIOD]) mod_timer(&dev->timer, jiffies + @@ -142,25 +198,11 @@ static void input_repeat_key(unsigned long data) spin_unlock_irqrestore(&dev->event_lock, flags); } -static void input_start_autorepeat(struct input_dev *dev, int code) -{ - if (test_bit(EV_REP, dev->evbit) && - dev->rep[REP_PERIOD] && dev->rep[REP_DELAY] && - dev->timer.data) { - dev->repeat_key = code; - mod_timer(&dev->timer, - jiffies + msecs_to_jiffies(dev->rep[REP_DELAY])); - } -} - -static void input_stop_autorepeat(struct input_dev *dev) -{ - del_timer(&dev->timer); -} - #define INPUT_IGNORE_EVENT 0 #define INPUT_PASS_TO_HANDLERS 1 #define INPUT_PASS_TO_DEVICE 2 +#define INPUT_SLOT 4 +#define INPUT_FLUSH 8 #define INPUT_PASS_TO_ALL (INPUT_PASS_TO_HANDLERS | INPUT_PASS_TO_DEVICE) static int input_handle_abs_event(struct input_dev *dev, @@ -207,14 +249,14 @@ static int input_handle_abs_event(struct input_dev *dev, /* Flush pending "slot" event */ if (is_mt_event && dev->slot != input_abs_get_val(dev, ABS_MT_SLOT)) { input_abs_set_val(dev, ABS_MT_SLOT, dev->slot); - input_pass_event(dev, EV_ABS, ABS_MT_SLOT, dev->slot); + return INPUT_PASS_TO_HANDLERS | INPUT_SLOT; } return INPUT_PASS_TO_HANDLERS; } -static void input_handle_event(struct input_dev *dev, - unsigned int type, unsigned int code, int value) +static int input_get_disposition(struct input_dev *dev, + unsigned int type, unsigned int code, int value) { int disposition = INPUT_IGNORE_EVENT; @@ -227,13 +269,9 @@ static void input_handle_event(struct input_dev *dev, break; case SYN_REPORT: - if (!dev->sync) { - dev->sync = true; - disposition = INPUT_PASS_TO_HANDLERS; - } + disposition = INPUT_PASS_TO_HANDLERS | INPUT_FLUSH; break; case SYN_MT_REPORT: - dev->sync = false; disposition = INPUT_PASS_TO_HANDLERS; break; } @@ -317,14 +355,48 @@ static void input_handle_event(struct input_dev *dev, break; } - if (disposition != INPUT_IGNORE_EVENT && type != EV_SYN) - dev->sync = false; + return disposition; +} + +static void input_handle_event(struct input_dev *dev, + unsigned int type, unsigned int code, int value) +{ + int disposition; + + disposition = input_get_disposition(dev, type, code, value); if ((disposition & INPUT_PASS_TO_DEVICE) && dev->event) dev->event(dev, type, code, value); - if (disposition & INPUT_PASS_TO_HANDLERS) - input_pass_event(dev, type, code, value); + if (!dev->vals) + return; + + if (disposition & INPUT_PASS_TO_HANDLERS) { + struct input_value *v; + + if (disposition & INPUT_SLOT) { + v = &dev->vals[dev->num_vals++]; + v->type = EV_ABS; + v->code = ABS_MT_SLOT; + v->value = dev->slot; + } + + v = &dev->vals[dev->num_vals++]; + v->type = type; + v->code = code; + v->value = value; + } + + if (disposition & INPUT_FLUSH) { + if (dev->num_vals >= 2) + input_pass_values(dev, dev->vals, dev->num_vals); + dev->num_vals = 0; + } else if (dev->num_vals >= dev->max_vals - 2) { + dev->vals[dev->num_vals++] = input_value_sync; + input_pass_values(dev, dev->vals, dev->num_vals); + dev->num_vals = 0; + } + } /** @@ -352,7 +424,6 @@ void input_event(struct input_dev *dev, if (is_event_supported(type, dev->evbit, EV_MAX)) { spin_lock_irqsave(&dev->event_lock, flags); - add_input_randomness(type, code, value); input_handle_event(dev, type, code, value); spin_unlock_irqrestore(&dev->event_lock, flags); } @@ -831,10 +902,12 @@ int input_set_keycode(struct input_dev *dev, if (test_bit(EV_KEY, dev->evbit) && !is_event_supported(old_keycode, dev->keybit, KEY_MAX) && __test_and_clear_bit(old_keycode, dev->key)) { + struct input_value vals[] = { + { EV_KEY, old_keycode, 0 }, + input_value_sync + }; - input_pass_event(dev, EV_KEY, old_keycode, 0); - if (dev->sync) - input_pass_event(dev, EV_SYN, SYN_REPORT, 1); + input_pass_values(dev, vals, ARRAY_SIZE(vals)); } out: @@ -1416,6 +1489,7 @@ static void input_dev_release(struct device *device) input_ff_destroy(dev); input_mt_destroy_slots(dev); kfree(dev->absinfo); + kfree(dev->vals); kfree(dev); module_put(THIS_MODULE); @@ -1781,6 +1855,9 @@ static unsigned int input_estimate_events_per_packet(struct input_dev *dev) if (test_bit(i, dev->relbit)) events++; + /* Make room for KEY and MSC events */ + events += 7; + return events; } @@ -1819,6 +1896,7 @@ int input_register_device(struct input_dev *dev) { static atomic_t input_no = ATOMIC_INIT(0); struct input_handler *handler; + unsigned int packet_size; const char *path; int error; @@ -1831,9 +1909,14 @@ int input_register_device(struct input_dev *dev) /* Make sure that bitmasks not mentioned in dev->evbit are clean. */ input_cleanse_bitmasks(dev); - if (!dev->hint_events_per_packet) - dev->hint_events_per_packet = - input_estimate_events_per_packet(dev); + packet_size = input_estimate_events_per_packet(dev); + if (dev->hint_events_per_packet < packet_size) + dev->hint_events_per_packet = packet_size; + + dev->max_vals = max(dev->hint_events_per_packet, packet_size) + 2; + dev->vals = kcalloc(dev->max_vals, sizeof(*dev->vals), GFP_KERNEL); + if (!dev->vals) + return -ENOMEM; /* * If delay and period are pre-set by the driver, then autorepeating diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index 9f03500288b..e4f2e8d8e4d 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -30,6 +30,10 @@ #include #include +#include + +int pwr_key_pressed = 0; + struct gpio_button_data { const struct gpio_keys_button *button; struct input_dev *input; @@ -345,6 +349,7 @@ static void gpio_keys_gpio_report_event(struct gpio_button_data *bdata) } else { input_event(input, type, button->code, !!state); } + input_sync(input); } @@ -362,6 +367,12 @@ static void gpio_keys_gpio_work_func(struct work_struct *work) if ((button->code <= KEY_POWER) && (button->code >= KEY_VOLUMEDOWN)) pr_info("gpio_keys: %s %s\n", state ? "Pressed" : "Released", key_descriptions[button->code - KEY_VOLUMEDOWN]); + +/*s2w*/ + if (button->code == 116 && state) { + pwr_key_pressed = 1; + } + #endif gpio_keys_gpio_report_event(bdata); } @@ -754,6 +765,10 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) } input_sync(input); + sweep2wake_setdev(input); + printk(KERN_INFO "[sweep2wake]: set device %s\n", input->name); + + device_init_wakeup(&pdev->dev, wakeup); return 0; diff --git a/drivers/input/lid.c b/drivers/input/lid.c index 3e55c3f7571..cd6b34a7daa 100644 --- a/drivers/input/lid.c +++ b/drivers/input/lid.c @@ -30,6 +30,9 @@ struct delayed_work lid_hall_sensor_work; +int enable_lid = 1; +module_param( enable_lid, int, 0644 ); + /* * functions declaration */ @@ -70,11 +73,14 @@ static ssize_t show_lid_status(struct device *class, static irqreturn_t lid_interrupt_handler(int irq, void *dev_id) { - if (irq == hall_sensor_irq) { - LID_NOTICE("LID interrupt handler...gpio: %d..\n", - gpio_get_value(hall_sensor_gpio)); - queue_delayed_work(lid_wq, &lid_hall_sensor_work, 0); + if (enable_lid) { + if (irq == hall_sensor_irq) { + LID_NOTICE("LID interrupt handler...gpio: %d..\n", + gpio_get_value(hall_sensor_gpio)); + queue_delayed_work(lid_wq, &lid_hall_sensor_work, 0); + } } + return IRQ_HANDLED; } diff --git a/drivers/input/touchscreen/ektf3k.c b/drivers/input/touchscreen/ektf3k.c index 4b6a7e7a51d..7ab0f541707 100755 --- a/drivers/input/touchscreen/ektf3k.c +++ b/drivers/input/touchscreen/ektf3k.c @@ -2,6 +2,9 @@ * * Copyright (C) 2011 Elan Microelectronics Corporation. * + * Sweep2wake and Doubletap2wake for Nexus 7 (flo) + * Copyright (C) 2013 Aaron Segaert (flar2) asegaert at gmail.com. All rights reserved. + * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and * may be copied, distributed, and modified under those terms. @@ -28,6 +31,8 @@ #include #include +#include + // for linux 2.6.36.3 #include #include @@ -196,6 +201,264 @@ static int debug = DEBUG_INFO; printk("[ektf3k]:" __VA_ARGS__); \ } while (0) + +/* sweep2wake */ +static struct input_dev *sweep2wake_pwrdev; +static DEFINE_MUTEX(s2w_lock); +static bool scr_suspended = false; + +static int pwrkey_suspend = 1; +static int s2w_orientation = 0; +static int shortsweep = 0; +static int dt2w_switch = 1; +static int dt2w_switch_temp = 1; +static int dt2w_changed = 0; +static int s2w_switch = 1; +static int s2w_switch_temp = 1; +static int s2w_changed = 0; + +static int s2w_begin_v = 150; +static int s2w_end_v = 1200; +static int s2w_begin_h = 350; +static int s2w_end_h = 1900; +static int tripoff_vl = 0; +static int tripoff_vr = 0; +static int tripoff_hd = 0; +static int tripoff_hu = 0; +static int tripon_vl = 0; +static int tripon_vr = 0; +static int tripon_hd = 0; +static int tripon_hu = 0; +static unsigned long triptime_vl = 0; +static unsigned long triptime_vr = 0; +static unsigned long triptime_hd = 0; +static unsigned long triptime_hu = 0; + +static unsigned long dt2w_time[2] = {0, 0}; +static unsigned int dt2w_x[2] = {0, 0}; +static unsigned int dt2w_y[2] = {0, 0}; +static unsigned int dt2w_2_x[2] = {0, 0}; +static unsigned int dt2w_2_y[2] = {0, 0}; + +#define S2W_TIMEOUT 50 +#define DT2W_TIMEOUT_MAX 50 +#define DT2W_TIMEOUT_MIN 4 +#define DT2W_DELTA 150 + +void sweep2wake_setdev(struct input_dev * input_device) { + sweep2wake_pwrdev = input_device; + return; +} + +EXPORT_SYMBOL(sweep2wake_setdev); + +static void reset_sweep2wake(int s2w, int dt2w) +{ + //reset sweep2wake + if (s2w) { + tripoff_vl = 0; + tripoff_vr = 0; + tripoff_hd = 0; + tripoff_hu = 0; + tripon_vl = 0; + tripon_vr = 0; + tripon_hd = 0; + tripon_hu = 0; + triptime_vl = 0; + triptime_vr = 0; + triptime_hd = 0; + triptime_hu = 0; + } + + //reset doubletap2wake + if (dt2w) { + dt2w_time[0] = 0; + dt2w_x[0] = 0; + dt2w_y[0] = 0; + dt2w_time[1] = 0; + dt2w_x[1] = 0; + dt2w_y[1] = 0; + dt2w_2_x[0] = 0; + dt2w_2_x[1] = 0; + dt2w_2_y[0] = 0; + dt2w_2_y[1] = 0; + } + return; +} + +static void sweep2wake_presspwr(struct work_struct *sweep2wake_presspwr_work) +{ + reset_sweep2wake(1,1); + + input_event(sweep2wake_pwrdev, EV_KEY, KEY_POWER, 1); + input_event(sweep2wake_pwrdev, EV_SYN, 0, 0); + msleep(20); + input_event(sweep2wake_pwrdev, EV_KEY, KEY_POWER, 0); + input_event(sweep2wake_pwrdev, EV_SYN, 0, 0); + msleep(20); + mutex_unlock(&s2w_lock); +} + +static DECLARE_WORK(sweep2wake_presspwr_work, sweep2wake_presspwr); + +void sweep2wake_pwrtrigger(void) +{ + if (mutex_trylock(&s2w_lock)) + schedule_work(&sweep2wake_presspwr_work); +} + +static void sweep2wake_func(int x, int y, unsigned long time, int i) +{ + if (x < 0 || i > 0) { + reset_sweep2wake(1,0); + return; + } + + if (scr_suspended == true && s2w_switch == 1) { + //left->right + if (y < s2w_begin_v) { + tripon_vr = 1; + triptime_vr = time; + } else if (tripon_vr == 1 && y > 488 && time - triptime_vr < 20) { + tripon_vr = 2; + } else if (tripon_vr == 2 && y > 896 && time - triptime_vr < 40) { + tripon_vr = 3; + } else if (tripon_vr == 3 && (y > s2w_end_v) && time - triptime_vr < S2W_TIMEOUT) { + printk(KERN_INFO "[s2w]: ON"); + sweep2wake_pwrtrigger(); + } + //right->left + if (y > s2w_end_v) { + tripon_vl = 1; + triptime_vl = time; + } else if (tripon_vl == 1 && y < 896 && time - triptime_vl < 20) { + tripon_vl = 2; + } else if (tripon_vl == 2 && y < 488 && time - triptime_vl < 40) { + tripon_vl = 3; + } else if (tripon_vl == 3 && y < s2w_begin_v && (time - triptime_vl < S2W_TIMEOUT)) { + printk(KERN_INFO "[s2w]: ON"); + sweep2wake_pwrtrigger(); + } + //top->bottom + if (x < s2w_begin_h) { + tripon_hd = 1; + triptime_hd = time; + } else if (tripon_hd == 1 && x > 748 && time - triptime_hd < 25) { + tripon_hd = 2; + } else if (tripon_hd == 2 && x > 1496 && time - triptime_hd < 45) { + tripon_hd = 3; + } else if (tripon_hd == 3 && x > s2w_end_h && (time - triptime_hd < S2W_TIMEOUT)) { + printk(KERN_INFO "[s2w]: ON"); + sweep2wake_pwrtrigger(); + } + //bottom->top + if (x > s2w_end_h) { + tripon_hu = 1; + triptime_hu = time; + } else if (tripon_hu == 1 && x < 1496 && time - triptime_hu < 25) { + tripon_hu = 2; + } else if (tripon_hu == 2 && x < 748 && time - triptime_hu < 45) { + tripon_hu = 3; + } else if (tripon_hu == 3 && x < s2w_begin_h && (time - triptime_hu < S2W_TIMEOUT)) { + printk(KERN_INFO "[s2w]: ON"); + sweep2wake_pwrtrigger(); + } + } + + if (scr_suspended == false && s2w_switch > 0) { + //right->left portrait mode normal + if (y > s2w_end_v && x > 2140 && (s2w_orientation == 0 || s2w_orientation == 1)) { + tripoff_vl = 1; + triptime_vl = time; + } else if (tripoff_vl == 1 && y < 896 && time - triptime_vl < 20) { + tripoff_vl = 2; + } else if (tripoff_vl == 2 && y < 488 && time - triptime_vl < 40) { + tripoff_vl = 3; + } else if (tripoff_vl == 3 && y < (s2w_begin_v) && (time - triptime_vl < S2W_TIMEOUT)) { + printk(KERN_INFO "[s2w]: OFF"); + sweep2wake_pwrtrigger(); + } + //left->right portrait mode upside down + if (y < s2w_begin_v && x < 100 && (s2w_orientation == 0 || s2w_orientation == 1)) { + tripoff_vr = 1; + triptime_vr = time; + } else if (tripoff_vr == 1 && y > 488 && time - triptime_vr < 20) { + tripoff_vr = 2; + } else if (tripoff_vr == 2 && y > 896 && time - triptime_vr < 40) { + tripoff_vr = 3; + } else if (tripoff_vr == 3 && y > s2w_end_v && time - triptime_vr < S2W_TIMEOUT) { + printk(KERN_INFO "[s2w]: OFF"); + sweep2wake_pwrtrigger(); + } + //top->bottom + if (x < s2w_begin_h && y > 1244 && (s2w_orientation == 0 || s2w_orientation == 2)) { + tripoff_hd = 1; + triptime_hd = time; + } else if (tripoff_hd == 1 && x > 748 && time - triptime_hd < 25) { + tripoff_hd = 2; + } else if (tripoff_hd == 2 && x > 1496 && time - triptime_hd < 45) { + tripoff_hd = 3; + } else if (tripoff_hd == 3 && x > s2w_end_h && (time - triptime_hd < S2W_TIMEOUT)) { + printk(KERN_INFO "[s2w]: OFF"); + sweep2wake_pwrtrigger(); + } + //bottom->top + if (x > s2w_end_h && y < 100 && (s2w_orientation == 0 || s2w_orientation == 2)) { + tripoff_hu = 1; + triptime_hu = time; + } else if (tripoff_hu == 1 && x < 1496 && time - triptime_hu < 25) { + tripoff_hu = 2; + } else if (tripoff_hu == 2 && x < 748 && time - triptime_hu < 45) { + tripoff_hu = 3; + } else if (tripoff_hu == 3 && x < s2w_begin_h && (time - triptime_hu < S2W_TIMEOUT)) { + printk(KERN_INFO "[s2w]: OFF"); + sweep2wake_pwrtrigger(); + } + } +} + +static void doubletap2wake_func(int x, int y) +{ + + int delta_x = 0; + int delta_y = 0; + + //printk("x=%d y=%d\n", x, y); + + dt2w_x[1] = dt2w_x[0]; + dt2w_x[0] = x; + dt2w_y[1] = dt2w_y[0]; + dt2w_y[0] = y; + + if (x < 0) { + dt2w_2_x[1] = dt2w_2_x[0]; + dt2w_2_x[0] = dt2w_x[1]; + dt2w_2_y[1] = dt2w_2_y[0]; + dt2w_2_y[0] = dt2w_y[1]; + dt2w_time[1] = dt2w_time[0]; + dt2w_time[0] = jiffies; + + //printk("x0=%d x1=%d time0=%lu time1=%lu\n", dt2w_2_x[0], dt2w_2_x[1], dt2w_time[0], dt2w_time[1]); + + delta_x = (dt2w_2_x[0]-dt2w_2_x[1]); + delta_y = (dt2w_2_y[0]-dt2w_2_y[1]); + + if ((abs(delta_x) < DT2W_DELTA) && (abs(delta_y) < DT2W_DELTA)) { + if ( ((dt2w_time[0] - dt2w_time[1]) > DT2W_TIMEOUT_MIN) + && ((dt2w_time[0] - dt2w_time[1]) < DT2W_TIMEOUT_MAX)) { + + printk("[dt2w]: OFF->ON\n"); + sweep2wake_pwrtrigger(); + } + } + } + + return; +} + +/* end sweep2wake */ + + int elan_iap_open(struct inode *inode, struct file *filp){ touch_debug(DEBUG_INFO, "[ELAN]into elan_iap_open\n"); if (private_ts == NULL) touch_debug(DEBUG_ERROR, "private_ts is NULL~~~"); @@ -381,6 +644,147 @@ static ssize_t elan_show_status(struct device *dev, struct device_attribute *dev DEVICE_ATTR(elan_touchpanel_status, S_IRUGO, elan_show_status, NULL); + + +/* sweep2wake sysfs */ +static ssize_t elan_ktf3k_sweep2wake_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + size_t count = 0; + + if (s2w_switch == s2w_switch_temp ) + count += sprintf(buf, "%d\n", s2w_switch); + else + count += sprintf(buf, "%d->%d\n", s2w_switch, s2w_switch_temp); + + return count; +} + +static ssize_t elan_ktf3k_sweep2wake_dump(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + if (buf[0] >= '0' && buf[0] <= '2' && buf[1] == '\n') + if (s2w_switch != buf[0] - '0') { + s2w_switch_temp = buf[0] - '0'; + if (!scr_suspended) + s2w_switch = s2w_switch_temp; + else + s2w_changed = 1; + } + + return count; +} + +static DEVICE_ATTR(sweep2wake, (S_IWUSR|S_IRUGO), + elan_ktf3k_sweep2wake_show, elan_ktf3k_sweep2wake_dump); + +static ssize_t elan_ktf3k_pwrkey_suspend_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + size_t count = 0; + count += sprintf(buf, "%d\n", pwrkey_suspend); + return count; +} + +static ssize_t elan_ktf3k_pwrkey_suspend_dump(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + if (buf[0] >= '0' && buf[0] <= '1' && buf[1] == '\n') + if (pwrkey_suspend != buf[0] - '0') + pwrkey_suspend = buf[0] - '0'; + + return count; +} + +static DEVICE_ATTR(pwrkey_suspend, (S_IWUSR|S_IRUGO), + elan_ktf3k_pwrkey_suspend_show, elan_ktf3k_pwrkey_suspend_dump); + +static ssize_t elan_ktf3k_orientation_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + size_t count = 0; + count += sprintf(buf, "%d\n", s2w_orientation); + return count; +} + +static ssize_t elan_ktf3k_orientation_dump(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + if (buf[0] >= '0' && buf[0] <= '2' && buf[1] == '\n') + if (s2w_orientation != buf[0] - '0') + s2w_orientation = buf[0] - '0'; + + return count; +} + +static DEVICE_ATTR(orientation, (S_IWUSR|S_IRUGO), + elan_ktf3k_orientation_show, elan_ktf3k_orientation_dump); + +static ssize_t elan_ktf3k_shortsweep_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + size_t count = 0; + count += sprintf(buf, "%d\n", shortsweep); + return count; +} + +static ssize_t elan_ktf3k_shortsweep_dump(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + if (buf[0] >= '0' && buf[0] <= '1' && buf[1] == '\n') + if (shortsweep != buf[0] - '0') + shortsweep = buf[0] - '0'; + + if (shortsweep) { + s2w_begin_v = 400 ; + s2w_end_v = 950; + s2w_begin_h = 650; + s2w_end_h = 1600; + } else { + s2w_begin_v = 150; + s2w_end_v = 1200; + s2w_begin_h = 350; + s2w_end_h = 1900; + } + + return count; +} + +static DEVICE_ATTR(shortsweep, (S_IWUSR|S_IRUGO), + elan_ktf3k_shortsweep_show, elan_ktf3k_shortsweep_dump); + +static ssize_t elan_ktf3k_doubletap2wake_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + size_t count = 0; + + if (dt2w_switch == dt2w_switch_temp) + count += sprintf(buf, "%d\n", dt2w_switch); + else + count += sprintf(buf, "%d->%d\n", dt2w_switch, dt2w_switch_temp); + + return count; +} + +static ssize_t elan_ktf3k_doubletap2wake_dump(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + if (buf[0] >= '0' && buf[0] <= '1' && buf[1] == '\n') + if (dt2w_switch != buf[0] - '0') { + dt2w_switch_temp = buf[0] - '0'; + if (!scr_suspended) + dt2w_switch = dt2w_switch_temp; + else + dt2w_changed = 1; + } + + return count; +} + +static DEVICE_ATTR(doubletap2wake, (S_IWUSR|S_IRUGO), + elan_ktf3k_doubletap2wake_show, elan_ktf3k_doubletap2wake_dump); + +/* end sweep2wake sysfs*/ + + static int check_fw_version(const unsigned char*firmware, unsigned int size, int fw_version){ int id, version; @@ -404,7 +808,6 @@ static int check_fw_version(const unsigned char*firmware, unsigned int size, int } - /* static ssize_t update_firmware(struct device *dev, struct device_attribute *devattr,const char *buf, size_t count) { @@ -459,12 +862,18 @@ static struct attribute *elan_attr[] = { &dev_attr_vendor.attr, &dev_attr_gpio.attr, //&dev_attr_update_fw.attr, +/* sweep2wake sysfs */ + &dev_attr_sweep2wake.attr, + &dev_attr_doubletap2wake.attr, + &dev_attr_shortsweep.attr, + &dev_attr_pwrkey_suspend.attr, + &dev_attr_orientation.attr, NULL }; static struct kobject *android_touch_kobj; -/* + static int elan_ktf3k_touch_sysfs_init(void) { int ret ; @@ -475,7 +884,7 @@ static int elan_ktf3k_touch_sysfs_init(void) ret = -ENOMEM; return ret; } - ret = sysfs_create_file(android_touch_kobj, &dev_attr_gpio.attr); +/* ret = sysfs_create_file(android_touch_kobj, &dev_attr_gpio.attr); if (ret) { touch_debug(DEBUG_ERROR, "[elan]%s: sysfs_create_file failed\n", __func__); return ret; @@ -485,13 +894,46 @@ static int elan_ktf3k_touch_sysfs_init(void) touch_debug(DEBUG_ERROR, "[elan]%s: sysfs_create_group failed\n", __func__); return ret; } +*/ +/* sweep2wake sysfs */ + ret = sysfs_create_file(android_touch_kobj, &dev_attr_sweep2wake.attr); + if (ret) { + touch_debug(DEBUG_ERROR, "[elan]%s: sysfs_create_group failed\n", __func__); + return ret; + } + ret = sysfs_create_file(android_touch_kobj, &dev_attr_doubletap2wake.attr); + if (ret) { + touch_debug(DEBUG_ERROR, "[elan]%s: sysfs_create_group failed\n", __func__); + return ret; + } + ret = sysfs_create_file(android_touch_kobj, &dev_attr_shortsweep.attr); + if (ret) { + touch_debug(DEBUG_ERROR, "[elan]%s: sysfs_create_group failed\n", __func__); + return ret; + } + ret = sysfs_create_file(android_touch_kobj, &dev_attr_pwrkey_suspend.attr); + if (ret) { + touch_debug(DEBUG_ERROR, "[elan]%s: sysfs_create_group failed\n", __func__); + return ret; + } + ret = sysfs_create_file(android_touch_kobj, &dev_attr_orientation.attr); + if (ret) { + touch_debug(DEBUG_ERROR, "[elan]%s: sysfs_create_group failed\n", __func__); + return ret; + } return 0 ; } -*/ + static void elan_touch_sysfs_deinit(void) { - sysfs_remove_file(android_touch_kobj, &dev_attr_vendor.attr); - sysfs_remove_file(android_touch_kobj, &dev_attr_gpio.attr); +// sysfs_remove_file(android_touch_kobj, &dev_attr_vendor.attr); +// sysfs_remove_file(android_touch_kobj, &dev_attr_gpio.attr); +/* sweep2wake sysfs */ + sysfs_remove_file(android_touch_kobj, &dev_attr_sweep2wake.attr); + sysfs_remove_file(android_touch_kobj, &dev_attr_doubletap2wake.attr); + sysfs_remove_file(android_touch_kobj, &dev_attr_shortsweep.attr); + sysfs_remove_file(android_touch_kobj, &dev_attr_pwrkey_suspend.attr); + sysfs_remove_file(android_touch_kobj, &dev_attr_orientation.attr); kobject_del(android_touch_kobj); } @@ -931,7 +1373,7 @@ static void elan_ktf3k_ts_report_data(struct i2c_client *client, uint8_t *buf) { struct elan_ktf3k_ts_data *ts = i2c_get_clientdata(client); struct input_dev *idev = ts->input_dev; - uint16_t x, y, touch_size, pressure_size; + uint16_t x = 0, y = 0, touch_size, pressure_size; uint16_t fbits=0, checksum=0; uint8_t i, num; static uint8_t size_index[10] = {35, 35, 36, 36, 37, 37, 38, 38, 39, 39}; @@ -961,19 +1403,21 @@ static void elan_ktf3k_ts_report_data(struct i2c_client *client, uint8_t *buf) input_report_abs(idev, ABS_MT_POSITION_X, y); input_report_abs(idev, ABS_MT_POSITION_Y, x); if(unlikely(gPrint_point)) touch_debug(DEBUG_INFO, "[elan] finger id=%d X=%d y=%d size=%d pressure=%d\n", i, x, y, touch_size, pressure_size); - } + + } } mTouchStatus[i] = active; fbits = fbits >> 1; idx += 3; } + input_sync(idev); } // checksum else { checksum_err +=1; touch_debug(DEBUG_ERROR, "[elan] Checksum Error %d byte[2]=%X\n", checksum_err, buf[2]); } - + return; } @@ -987,43 +1431,62 @@ static void elan_ktf3k_ts_report_data2(struct i2c_client *client, uint8_t *buf) uint16_t active = 0; uint8_t idx=IDX_FINGER; - num = buf[2] & 0xf; + num = buf[2] & 0xf; for (i=0; i<34;i++) checksum +=buf[i]; - + if ( (num < 3) || ((checksum & 0x00ff) == buf[34])) { - fbits = buf[2] & 0x30; - fbits = (fbits << 4) | buf[1]; - //input_report_key(idev, BTN_TOUCH, 1); - for(i = 0; i < FINGER_NUM; i++){ - active = fbits & 0x1; - if(active || mTouchStatus[i]){ - input_mt_slot(ts->input_dev, i); - input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, active); - if(active){ - elan_ktf3k_ts_parse_xy(&buf[idx], &x, &y); - x = x > ts->abs_x_max ? 0 : ts->abs_x_max - x; - y = y > ts->abs_y_max ? ts->abs_y_max : y; - touch_size = buf[35 + i]; - pressure_size = buf[45 + i]; - input_report_abs(idev, ABS_MT_TOUCH_MAJOR, touch_size); - input_report_abs(idev, ABS_MT_PRESSURE, pressure_size); - input_report_abs(idev, ABS_MT_POSITION_X, y); - input_report_abs(idev, ABS_MT_POSITION_Y, x); - if(unlikely(gPrint_point)) touch_debug(DEBUG_INFO, "[elan] finger id=%d X=%d y=%d size=%d pressure=%d\n", i, x, y, touch_size, pressure_size); - } - } - mTouchStatus[i] = active; - fbits = fbits >> 1; - idx += 3; - } - input_sync(idev); + fbits = buf[2] & 0x30; + fbits = (fbits << 4) | buf[1]; + + //input_report_key(idev, BTN_TOUCH, 1); + + for(i = 0; i < FINGER_NUM; i++){ + active = fbits & 0x1; + if(active || mTouchStatus[i]){ + input_mt_slot(ts->input_dev, i); + input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, active); + if(active){ + elan_ktf3k_ts_parse_xy(&buf[idx], &x, &y); + x = x > ts->abs_x_max ? 0 : ts->abs_x_max - x; + y = y > ts->abs_y_max ? ts->abs_y_max : y; + touch_size = buf[35 + i]; + pressure_size = buf[45 + i]; + input_report_abs(idev, ABS_MT_TOUCH_MAJOR, touch_size); + input_report_abs(idev, ABS_MT_PRESSURE, pressure_size); + input_report_abs(idev, ABS_MT_POSITION_X, y); + input_report_abs(idev, ABS_MT_POSITION_Y, x); + if(unlikely(gPrint_point)) + touch_debug(DEBUG_INFO, "[elan] finger id=%d X=%d y=%d size=%d pressure=%d\n", i, x, y, touch_size, pressure_size); + /* sweep2wake */ + if (s2w_switch > 0) + sweep2wake_func(x, y, jiffies, i); + if (dt2w_switch && scr_suspended) + doubletap2wake_func(x, y); + /* end sweep2wake */ + } + } + mTouchStatus[i] = active; + fbits = fbits >> 1; + idx += 3; + } + input_sync(idev); } // checksum + else { checksum_err +=1; touch_debug(DEBUG_ERROR, "[elan] Checksum Error %d byte[2]=%X\n", checksum_err, buf[2]); } + /* sweep2wake */ + if (checksum == 99) { + if (s2w_switch > 0) + sweep2wake_func(-1, -1, jiffies, i); + if (dt2w_switch && scr_suspended) + doubletap2wake_func(-1, -1); + } + /* end sweep2wake */ + return; } @@ -1588,7 +2051,7 @@ static int elan_ktf3k_ts_probe(struct i2c_client *client, private_ts = ts; - //elan_ktf2k_touch_sysfs_init(); + elan_ktf3k_touch_sysfs_init(); ts->attrs.attrs = elan_attr; err = sysfs_create_group(&client->dev.kobj, &ts->attrs); if (err) { @@ -1711,14 +2174,26 @@ static int elan_ktf3k_ts_suspend(struct i2c_client *client, pm_message_t mesg) int rc = 0; touch_debug(DEBUG_INFO, "[elan] %s: enter\n", __func__); - disable_irq(client->irq); + +/*s2w*/ + if ((s2w_switch == 1 || dt2w_switch == 1) ) { + enable_irq_wake(client->irq); + } else { + disable_irq(client->irq); + } + force_release_pos(client); rc = cancel_work_sync(&ts->work); if (rc) enable_irq(client->irq); - if(work_lock == 0) - rc = elan_ktf3k_ts_set_power_state(client, PWR_STATE_DEEP_SLEEP); +/*s2w*/ + if(((s2w_switch != 1 && !dt2w_switch) || (pwrkey_suspend && pwr_key_pressed)) && work_lock == 0) { + pwr_key_pressed = 0; + rc = elan_ktf3k_ts_set_power_state(client, PWR_STATE_DEEP_SLEEP); + } +/*s2w*/ + scr_suspended = true; return 0; } @@ -1727,8 +2202,8 @@ static int elan_ktf3k_ts_resume(struct i2c_client *client) { int rc = 0, retry = 5; - //struct elan_ktf3k_ts_data *ts = i2c_get_clientdata(client); - //int delay_time; + //struct elan_ktf3k_ts_data *ts = i2c_get_clientdata(client); + //int delay_time; //gpio_direction_output(31, 0); @@ -1745,7 +2220,23 @@ static int elan_ktf3k_ts_resume(struct i2c_client *client) } while (--retry); } //force_release_pos(client); - enable_irq(client->irq); + +/* s2w */ + if (s2w_switch == 1 || dt2w_switch == 1) { + disable_irq_wake(client->irq); + } else { + enable_irq(client->irq); + } + + if (s2w_changed) + s2w_switch = s2w_switch_temp; + if (dt2w_changed) + dt2w_switch = dt2w_switch_temp; + + scr_suspended = false; + pwr_key_pressed = 0; +/* end s2w */ + return 0; } @@ -1800,3 +2291,4 @@ module_exit(elan_ktf3k_ts_exit); MODULE_DESCRIPTION("ELAN KTF3K Touchscreen Driver"); MODULE_LICENSE("GPL"); + diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index 35c1e17fce1..97b2e21ac46 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c @@ -1056,8 +1056,8 @@ static const char *intr_remap_fault_reasons[] = const char *dmar_get_fault_reason(u8 fault_reason, int *fault_type) { - if (fault_reason >= 0x20 && (fault_reason <= 0x20 + - ARRAY_SIZE(intr_remap_fault_reasons))) { + if (fault_reason >= 0x20 && (fault_reason - 0x20 < + ARRAY_SIZE(intr_remap_fault_reasons))) { *fault_type = INTR_REMAP; return intr_remap_fault_reasons[fault_reason - 0x20]; } else if (fault_reason < ARRAY_SIZE(dma_remap_fault_reasons)) { diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index f93d5ac8f81..5fda348702c 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -2286,12 +2286,6 @@ static int domain_add_dev_info(struct dmar_domain *domain, if (!info) return -ENOMEM; - ret = domain_context_mapping(domain, pdev, translation); - if (ret) { - free_devinfo_mem(info); - return ret; - } - info->segment = pci_domain_nr(pdev->bus); info->bus = pdev->bus->number; info->devfn = pdev->devfn; @@ -2304,6 +2298,17 @@ static int domain_add_dev_info(struct dmar_domain *domain, pdev->dev.archdata.iommu = info; spin_unlock_irqrestore(&device_domain_lock, flags); + ret = domain_context_mapping(domain, pdev, translation); + if (ret) { + spin_lock_irqsave(&device_domain_lock, flags); + list_del(&info->link); + list_del(&info->global); + pdev->dev.archdata.iommu = NULL; + spin_unlock_irqrestore(&device_domain_lock, flags); + free_devinfo_mem(info); + return ret; + } + return 0; } diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c index 343b5c80cb7..579aa021a65 100644 --- a/drivers/isdn/gigaset/capi.c +++ b/drivers/isdn/gigaset/capi.c @@ -14,6 +14,7 @@ #include "gigaset.h" #include #include +#include #include #include #include @@ -223,10 +224,14 @@ get_appl(struct gigaset_capi_ctr *iif, u16 appl) static inline void dump_cmsg(enum debuglevel level, const char *tag, _cmsg *p) { #ifdef CONFIG_GIGASET_DEBUG + /* dump at most 20 messages in 20 secs */ + static DEFINE_RATELIMIT_STATE(msg_dump_ratelimit, 20 * HZ, 20); _cdebbuf *cdb; if (!(gigaset_debuglevel & level)) return; + if (!___ratelimit(&msg_dump_ratelimit, tag)) + return; cdb = capi_cmsg2str(p); if (cdb) { @@ -1882,6 +1887,9 @@ static void do_disconnect_req(struct gigaset_capi_ctr *iif, /* check for active logical connection */ if (bcs->apconnstate >= APCONN_ACTIVE) { + /* clear it */ + bcs->apconnstate = APCONN_SETUP; + /* * emit DISCONNECT_B3_IND with cause 0x3301 * use separate cmsg structure, as the content of iif->acmsg @@ -1906,6 +1914,7 @@ static void do_disconnect_req(struct gigaset_capi_ctr *iif, } capi_cmsg2message(b3cmsg, __skb_put(b3skb, CAPI_DISCONNECT_B3_IND_BASELEN)); + dump_cmsg(DEBUG_CMD, __func__, b3cmsg); kfree(b3cmsg); capi_ctr_handle_message(&iif->ctr, ap->id, b3skb); } @@ -2058,12 +2067,6 @@ static void do_reset_b3_req(struct gigaset_capi_ctr *iif, CapiResetProcedureNotSupportedByCurrentProtocol); } -/* - * dump unsupported/ignored messages at most twice per minute, - * some apps send those very frequently - */ -static unsigned long ignored_msg_dump_time; - /* * unsupported CAPI message handler */ @@ -2073,8 +2076,7 @@ static void do_unsupported(struct gigaset_capi_ctr *iif, { /* decode message */ capi_message2cmsg(&iif->acmsg, skb->data); - if (printk_timed_ratelimit(&ignored_msg_dump_time, 30 * 1000)) - dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); + dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); send_conf(iif, ap, skb, CapiMessageNotSupportedInCurrentState); } @@ -2085,11 +2087,9 @@ static void do_nothing(struct gigaset_capi_ctr *iif, struct gigaset_capi_appl *ap, struct sk_buff *skb) { - if (printk_timed_ratelimit(&ignored_msg_dump_time, 30 * 1000)) { - /* decode message */ - capi_message2cmsg(&iif->acmsg, skb->data); - dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); - } + /* decode message */ + capi_message2cmsg(&iif->acmsg, skb->data); + dump_cmsg(DEBUG_CMD, __func__, &iif->acmsg); dev_kfree_skb_any(skb); } diff --git a/drivers/isdn/gigaset/ev-layer.c b/drivers/isdn/gigaset/ev-layer.c index 624a8256a77..685638ac116 100644 --- a/drivers/isdn/gigaset/ev-layer.c +++ b/drivers/isdn/gigaset/ev-layer.c @@ -190,6 +190,7 @@ struct reply_t gigaset_tab_nocid[] = ACT_INIT} }, {RSP_OK, 121, 121, -1, 0, 0, {ACT_GOTVER, ACT_INIT} }, + {RSP_NONE, 121, 121, -1, 120, 0, {ACT_GETSTRING} }, /* leave dle mode */ {RSP_INIT, 0, 0, SEQ_DLE0, 201, 5, {0}, "^SDLE=0\r"}, @@ -1314,8 +1315,9 @@ static void do_action(int action, struct cardstate *cs, s = ev->ptr; if (!strcmp(s, "OK")) { + /* OK without version string: assume old response */ *p_genresp = 1; - *p_resp_code = RSP_ERROR; + *p_resp_code = RSP_NONE; break; } diff --git a/drivers/md/md.c b/drivers/md/md.c index 01233d855eb..2b30ffdb81b 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -452,7 +452,7 @@ static void submit_flushes(struct work_struct *ws) atomic_inc(&rdev->nr_pending); atomic_inc(&rdev->nr_pending); rcu_read_unlock(); - bi = bio_alloc_mddev(GFP_KERNEL, 0, mddev); + bi = bio_alloc_mddev(GFP_NOIO, 0, mddev); bi->bi_end_io = md_end_flush; bi->bi_private = rdev; bi->bi_bdev = rdev->bdev; diff --git a/drivers/media/common/tuners/xc4000.c b/drivers/media/common/tuners/xc4000.c index 98a057f1318..075f54ab81d 100644 --- a/drivers/media/common/tuners/xc4000.c +++ b/drivers/media/common/tuners/xc4000.c @@ -933,7 +933,7 @@ static int check_firmware(struct dvb_frontend *fe, unsigned int type, struct xc4000_priv *priv = fe->tuner_priv; struct firmware_properties new_fw; int rc = 0, is_retry = 0; - u16 hwmodel; + u16 hwmodel = 0; v4l2_std_id std0; u8 hw_major = 0, hw_minor = 0, fw_major = 0, fw_minor = 0; @@ -1095,12 +1095,12 @@ static int check_firmware(struct dvb_frontend *fe, unsigned int type, static void xc_debug_dump(struct xc4000_priv *priv) { - u16 adc_envelope; + u16 adc_envelope = 0; u32 freq_error_hz = 0; - u16 lock_status; + u16 lock_status = 0; u32 hsync_freq_hz = 0; - u16 frame_lines; - u16 quality; + u16 frame_lines = 0; + u16 quality = 0; u16 signal = 0; u16 noise = 0; u8 hw_majorversion = 0, hw_minorversion = 0; diff --git a/drivers/media/common/tuners/xc5000.c b/drivers/media/common/tuners/xc5000.c index eab2ea42420..e6c8ecee5ec 100644 --- a/drivers/media/common/tuners/xc5000.c +++ b/drivers/media/common/tuners/xc5000.c @@ -641,12 +641,12 @@ static int xc5000_fwupload(struct dvb_frontend *fe) static void xc_debug_dump(struct xc5000_priv *priv) { - u16 adc_envelope; + u16 adc_envelope = 0; u32 freq_error_hz = 0; - u16 lock_status; + u16 lock_status = 0; u32 hsync_freq_hz = 0; - u16 frame_lines; - u16 quality; + u16 frame_lines = 0; + u16 quality = 0; u8 hw_majorversion = 0, hw_minorversion = 0; u8 fw_majorversion = 0, fw_minorversion = 0; u16 fw_buildversion = 0; diff --git a/drivers/media/dvb/siano/smsusb.c b/drivers/media/dvb/siano/smsusb.c index b1fe5137df0..63c004a25e0 100644 --- a/drivers/media/dvb/siano/smsusb.c +++ b/drivers/media/dvb/siano/smsusb.c @@ -542,6 +542,8 @@ static const struct usb_device_id smsusb_id_table[] __devinitconst = { .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, { USB_DEVICE(0x2040, 0xc090), .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, + { USB_DEVICE(0x2040, 0xc0a0), + .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, { } /* Terminating entry */ }; diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c index ff2cdddf9bc..53ab9729c29 100644 --- a/drivers/media/video/uvc/uvc_v4l2.c +++ b/drivers/media/video/uvc/uvc_v4l2.c @@ -687,7 +687,7 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) break; } pin = iterm->id; - } else if (pin < selector->bNrInPins) { + } else if (index < selector->bNrInPins) { pin = selector->baSourceID[index]; list_for_each_entry(iterm, &chain->entities, chain) { if (!UVC_ENTITY_IS_ITERM(iterm)) diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c index 613ddd502ad..83453cfaa54 100644 --- a/drivers/misc/qseecom.c +++ b/drivers/misc/qseecom.c @@ -2021,8 +2021,8 @@ static long qseecom_ioctl(struct file *file, unsigned cmd, ret = qseecom_receive_req(data); atomic_dec(&data->ioctl_count); wake_up_all(&data->abort_wq); - if (ret) - pr_err("failed qseecom_receive_req: %d\n", ret); + //if (ret) + // pr_err("failed qseecom_receive_req: %d\n", ret); break; } case QSEECOM_IOCTL_SEND_RESP_REQ: { diff --git a/drivers/mmc/core/cd-gpio.c b/drivers/mmc/core/cd-gpio.c index 2c14be73254..f13e38decea 100644 --- a/drivers/mmc/core/cd-gpio.c +++ b/drivers/mmc/core/cd-gpio.c @@ -73,6 +73,9 @@ void mmc_cd_gpio_free(struct mmc_host *host) { struct mmc_cd_gpio *cd = host->hotplug.handler_priv; + if (!cd) + return; + free_irq(host->hotplug.irq, host); gpio_free(cd->gpio); kfree(cd); diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 56d4499d438..71a0c4ea1bc 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -1969,7 +1969,7 @@ static int __devinit omap_hsmmc_probe(struct platform_device *pdev) ret = request_threaded_irq(mmc_slot(host).card_detect_irq, NULL, omap_hsmmc_detect, - IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, mmc_hostname(mmc), host); if (ret) { dev_dbg(mmc_dev(host->mmc), diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 3cbda0851f8..cd7228ee9df 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -192,7 +192,7 @@ static inline int phy_find_setting(int speed, int duplex) * the mask in features. Returns the index of the last setting * if nothing else matches. */ -static inline int phy_find_valid(int idx, u32 features) +static inline int phy_find_valid(unsigned int idx, u32 features) { while (idx < MAX_NUM_SETTINGS && !(settings[idx].setting & features)) idx++; diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c index 21d7151fb0a..2de3ec5f163 100644 --- a/drivers/net/ppp/ppp_generic.c +++ b/drivers/net/ppp/ppp_generic.c @@ -741,7 +741,7 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) #ifdef CONFIG_PPP_FILTER case PPPIOCSPASS: { - struct sock_filter *code; + struct sock_filter *code = NULL; err = get_filter(argp, &code); if (err >= 0) { ppp_lock(ppp); @@ -755,7 +755,7 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) } case PPPIOCSACTIVE: { - struct sock_filter *code; + struct sock_filter *code = NULL; err = get_filter(argp, &code); if (err >= 0) { ppp_lock(ppp); diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index df7e16dfb36..a98db30b7ac 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -1571,8 +1571,6 @@ static void b43legacy_request_firmware(struct work_struct *work) const char *filename; int err; - /* do dummy read */ - ssb_read32(dev->dev, SSB_TMSHIGH); if (!fw->ucode) { if (rev == 2) filename = "ucode2"; diff --git a/drivers/oprofile/timer_int.c b/drivers/oprofile/timer_int.c index 93404f72dfa..235659af2c4 100644 --- a/drivers/oprofile/timer_int.c +++ b/drivers/oprofile/timer_int.c @@ -74,7 +74,7 @@ static void oprofile_hrtimer_stop(void) put_online_cpus(); } -static int __cpuinit oprofile_cpu_notify(struct notifier_block *self, +static int oprofile_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) { long cpu = (long) hcpu; diff --git a/drivers/power/bq27541_battery.c b/drivers/power/bq27541_battery.c index c3e63910bd8..e8a216bd43d 100644 --- a/drivers/power/bq27541_battery.c +++ b/drivers/power/bq27541_battery.c @@ -32,6 +32,8 @@ #include #include +#include + #define SMBUS_RETRY (0) #define GPIOPIN_LOW_BATTERY_DETECT 29 #define BATTERY_POLLING_RATE (60) @@ -159,8 +161,13 @@ void bq27541_check_cabe_type(void) usb_on = 0; } else if(bq27541_battery_cable_status == USB_Cable) { - usb_on = 1; - ac_on = 0; + if (force_fast_charge == 1) { + ac_on = 1; + usb_on = 0; + } else { + usb_on = 1; + ac_on = 0; + } } else { ac_on = 0; diff --git a/drivers/power/smb345-charger.c b/drivers/power/smb345-charger.c index 60f330a7b88..1f193052533 100644 --- a/drivers/power/smb345-charger.c +++ b/drivers/power/smb345-charger.c @@ -119,6 +119,9 @@ extern int bq27541_battery_callback(unsigned usb_cable_state); extern int bq27541_wireless_callback(unsigned wireless_state); extern void touch_callback(unsigned cable_status); static ssize_t smb345_reg_show(struct device *dev, struct device_attribute *attr, char *buf); +static ssize_t smb345_float_voltage_show(struct device *dev, struct device_attribute *attr, char *buf); +static ssize_t smb345_float_voltage_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); /* Global variables */ static struct smb345_charger *charger; @@ -132,12 +135,16 @@ extern int ac_on; extern int usb_on; static bool wpc_en; static bool disable_DCIN; +static int float_volt_setting = 4300; /* Sysfs interface */ static DEVICE_ATTR(reg_status, S_IWUSR | S_IRUGO, smb345_reg_show, NULL); +static DEVICE_ATTR(float_voltage, 0644, smb345_float_voltage_show, + smb345_float_voltage_store); static struct attribute *smb345_attributes[] = { &dev_attr_reg_status.attr, + &dev_attr_float_voltage.attr, NULL }; @@ -942,6 +949,30 @@ static ssize_t smb345_reg_show(struct device *dev, struct device_attribute *attr return strlen(buf); } +static ssize_t smb345_float_voltage_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + return sprintf(buf, "%u\n", float_volt_setting); +} + +/* Set charger float voltage; desired value in mV. */ +static ssize_t smb345_float_voltage_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int val = 0; + + if(kstrtoint(buf, 0, &val) != 0) + goto error; + val = (val / 20) * 20; /* the charger can only do 20mV increments */ + if(val < 3800 || val > 4300) + goto error; + + float_volt_setting = val; + + return count; +error: + return -EINVAL; +} + static int smb345_otg_setting(struct i2c_client *client) { int ret; @@ -1101,6 +1132,18 @@ int smb345_config_thermal_charging(int temp, int volt, int rule) struct i2c_client *client = charger->client; int ret = 0, retval, setting = 0; int BAT_Mid_Temp = BAT_Mid_Temp_Wired; + /*Charger float voltage for normal temperature conditions. Default 4.3V.*/ + int flt_volt_43 = FLOAT_VOLT_43V; + /*Charger float voltage for high temperature conditions. Default 4.1V.*/ + int flt_volt_low = FLOAT_VOLT_LOW; + + flt_volt_43 = (float_volt_setting - 3500) / 20; + + if(flt_volt_43 < 0 || flt_volt_43 > FLOAT_VOLT_43V) { + SMB_NOTICE("BUG: Invalid float voltage setting calculated: %d\n", flt_volt_43); + flt_volt_43 = FLOAT_VOLT_43V; + } + if(flt_volt_low > flt_volt_43) flt_volt_low = flt_volt_43; if (rule == THERMAL_RULE1) BAT_Mid_Temp = BAT_Mid_Temp_Wired; @@ -1129,10 +1172,10 @@ int smb345_config_thermal_charging(int temp, int volt, int rule) if (temp <= BAT_Mid_Temp || (temp > BAT_Mid_Temp && volt > FLOAT_VOLT_LOW_DECIMAL) || temp > BAT_Hot_Limit) { - if (setting != FLOAT_VOLT_43V) { + if (setting != flt_volt_43) { setting = retval & (~FLOAT_VOLT_MASK); - setting |= FLOAT_VOLT_43V; - SMB_NOTICE("Set Float Volt, retval=%x setting=%x\n", retval, setting); + setting |= flt_volt_43; + SMB_NOTICE("Set Float Volt, retval=%x setting=%x V=%dmV\n", retval, setting, float_volt_setting); ret = smb345_write(client, smb345_FLOAT_VLTG, setting); if (ret < 0) { dev_err(&client->dev, "%s(): Failed in writing 0x%02x to register" @@ -1140,11 +1183,11 @@ int smb345_config_thermal_charging(int temp, int volt, int rule) goto error; } } else - SMB_NOTICE("Bypass set Float Volt=%x\n", retval); + SMB_NOTICE("Bypass set Float Volt setting=%x V=%dmV\n", retval, float_volt_setting); } else { - if (setting != FLOAT_VOLT_LOW) { + if (setting != flt_volt_low) { setting = retval & (~FLOAT_VOLT_MASK); - setting |= FLOAT_VOLT_LOW; + setting |= flt_volt_low; SMB_NOTICE("Set Float Volt, retval=%x setting=%x\n", retval, setting); ret = smb345_write(client, smb345_FLOAT_VLTG, setting); if (ret < 0) { diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 57cde4595d6..41450eeced5 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -3393,6 +3393,8 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, unset_regulator_supplies(rdev); scrub: + if (rdev->supply) + regulator_put(rdev->supply); kfree(rdev->constraints); device_unregister(&rdev->dev); /* device core frees rdev */ diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 29684c8142b..d022008372e 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -265,7 +265,7 @@ config SCSI_SCAN_ASYNC config SCSI_WAIT_SCAN tristate # No prompt here, this is an invisible symbol. - default m + default y depends on SCSI depends on MODULES # scsi_wait_scan is a loadable module which waits until all the async scans are diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index 5137db5a5d8..bc6cf888631 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -476,7 +476,7 @@ static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_devic if (!orom) orom = isci_request_oprom(pdev); - for (i = 0; orom && i < ARRAY_SIZE(orom->ctrl); i++) { + for (i = 0; orom && i < num_controllers(pdev); i++) { if (sci_oem_parameters_validate(&orom->ctrl[i], orom->hdr.version)) { dev_warn(&pdev->dev, diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index 8a59a772fdf..18084788ee3 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c @@ -3343,7 +3343,7 @@ _base_get_port_facts(struct MPT2SAS_ADAPTER *ioc, int port, int sleep_flag) } pfacts = &ioc->pfacts[port]; - memset(pfacts, 0, sizeof(Mpi2PortFactsReply_t)); + memset(pfacts, 0, sizeof(struct mpt2sas_port_facts)); pfacts->PortNumber = mpi_reply.PortNumber; pfacts->VP_ID = mpi_reply.VP_ID; pfacts->VF_ID = mpi_reply.VF_ID; @@ -3385,7 +3385,7 @@ _base_get_ioc_facts(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) } facts = &ioc->facts; - memset(facts, 0, sizeof(Mpi2IOCFactsReply_t)); + memset(facts, 0, sizeof(struct mpt2sas_facts)); facts->MsgVersion = le16_to_cpu(mpi_reply.MsgVersion); facts->HeaderVersion = le16_to_cpu(mpi_reply.HeaderVersion); facts->VP_ID = mpi_reply.VP_ID; @@ -4262,7 +4262,7 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) goto out_free_resources; ioc->pfacts = kcalloc(ioc->facts.NumberOfPorts, - sizeof(Mpi2PortFactsReply_t), GFP_KERNEL); + sizeof(struct mpt2sas_port_facts), GFP_KERNEL); if (!ioc->pfacts) { r = -ENOMEM; goto out_free_resources; diff --git a/drivers/spi/spi-fsl-spi.c b/drivers/spi/spi-fsl-spi.c index 5f748c0d96b..6a62934ca74 100644 --- a/drivers/spi/spi-fsl-spi.c +++ b/drivers/spi/spi-fsl-spi.c @@ -933,7 +933,7 @@ static struct spi_master * __devinit fsl_spi_probe(struct device *dev, static void fsl_spi_cs_control(struct spi_device *spi, bool on) { - struct device *dev = spi->dev.parent; + struct device *dev = spi->dev.parent->parent; struct mpc8xxx_spi_probe_info *pinfo = to_of_pinfo(dev->platform_data); u16 cs = spi->chip_select; int gpio = pinfo->gpios[cs]; diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index ce8276f5df2..9e7605bdb76 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -136,4 +136,8 @@ source "drivers/staging/ozwpan/Kconfig" source "drivers/staging/prima/Kconfig" +source "drivers/staging/media/Kconfig" + +source "drivers/staging/cpupower/Kconfig" + endif # STAGING diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 993786ccb63..266da6b3d53 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -53,6 +53,7 @@ obj-$(CONFIG_TOUCHSCREEN_CLEARPAD_TM1217) += cptm1217/ obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4) += ste_rmi4/ obj-$(CONFIG_INTEL_MEI) += mei/ obj-$(CONFIG_MFD_NVEC) += nvec/ +obj-$(CONFIG_CPUPOWER) +=cpupower/ obj-$(CONFIG_DRM_OMAP) += omapdrm/ obj-$(CONFIG_ANDROID) += android/ obj-$(CONFIG_PHONE) += telephony/ diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c index f1364a860ac..80793e84ae0 100644 --- a/drivers/staging/android/binder.c +++ b/drivers/staging/android/binder.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -2308,13 +2309,13 @@ static int binder_thread_read(struct binder_proc *proc, if (!binder_has_proc_work(proc, thread)) ret = -EAGAIN; } else - ret = wait_event_interruptible_exclusive(proc->wait, binder_has_proc_work(proc, thread)); + ret = wait_event_freezable_exclusive(proc->wait, binder_has_proc_work(proc, thread)); } else { if (non_block) { if (!binder_has_thread_work(thread)) ret = -EAGAIN; } else - ret = wait_event_interruptible(thread->wait, binder_has_thread_work(thread)); + ret = wait_event_freezable(thread->wait, binder_has_thread_work(thread)); } binder_lock(__func__); diff --git a/drivers/staging/android/persistent_ram.c b/drivers/staging/android/persistent_ram.c index 35cc95bffec..07b16799758 100644 --- a/drivers/staging/android/persistent_ram.c +++ b/drivers/staging/android/persistent_ram.c @@ -79,23 +79,6 @@ static inline void buffer_size_add(struct persistent_ram_zone *prz, size_t a) } while (atomic_cmpxchg(&prz->buffer->size, old, new) != old); } -/* increase the size counter, retuning an error if it hits the max size */ -static inline ssize_t buffer_size_add_clamp(struct persistent_ram_zone *prz, - size_t a) -{ - size_t old; - size_t new; - - do { - old = atomic_read(&prz->buffer->size); - new = old + a; - if (new > prz->buffer_size) - return -ENOMEM; - } while (atomic_cmpxchg(&prz->buffer->size, old, new) != old); - - return 0; -} - static void notrace persistent_ram_encode_rs8(struct persistent_ram_zone *prz, uint8_t *data, size_t len, uint8_t *ecc) { @@ -304,7 +287,7 @@ int notrace persistent_ram_write(struct persistent_ram_zone *prz, c = prz->buffer_size; } - buffer_size_add_clamp(prz, c); + buffer_size_add(prz, c); start = buffer_start_add(prz, c); diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index 9bcf87ae4c0..a796964bfff 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -280,7 +280,7 @@ static int do_devconfig_ioctl(struct comedi_device *dev, if (ret == 0) { if (!try_module_get(dev->driver->module)) { comedi_device_detach(dev); - return -ENOSYS; + ret = -ENOSYS; } } diff --git a/drivers/staging/cpupower/Kconfig b/drivers/staging/cpupower/Kconfig new file mode 100644 index 00000000000..e07dd983fda --- /dev/null +++ b/drivers/staging/cpupower/Kconfig @@ -0,0 +1,5 @@ +config CPUPOWER + tristate "cpupower driver" + depends on SCHED_MC && ARM_CPU_TOPOLOGY + help + Say Y here if you have dual cortex-A9 diff --git a/drivers/staging/cpupower/Makefile b/drivers/staging/cpupower/Makefile new file mode 100644 index 00000000000..b16bad10226 --- /dev/null +++ b/drivers/staging/cpupower/Makefile @@ -0,0 +1,4 @@ +# +# Makefile for ARM cpupower driver +# +obj-y += cpu_power.o diff --git a/drivers/staging/cpupower/cpu_power.c b/drivers/staging/cpupower/cpu_power.c new file mode 100644 index 00000000000..9f971a7a508 --- /dev/null +++ b/drivers/staging/cpupower/cpu_power.c @@ -0,0 +1,179 @@ +/* + * arch/arm/kernel/topology.c + * + * Copyright (C) 2011 Linaro Limited. + * Written by: Vincent Guittot + * + * based on arch/sh/kernel/topology.c + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static struct cputopo_power **table_config = NULL; + +struct cputopo_scale { + int id; + int freq; + struct cputopo_power *power; +}; + +/* + * The table will be mostly used by one cpu which will update the + * configuration for all cpu on a cpufreq notification + * or a sched_mc level change + */ +static struct cputopo_scale cpu_power[NR_CPUS]; + +static void set_cpufreq_scale(unsigned int cpuid, unsigned int freq) +{ + unsigned int idx; + + cpu_power[cpuid].freq = freq; + + idx = freq / cpu_power[cpuid].power->step; + if (idx >= cpu_power[cpuid].power->max) + idx = cpu_power[cpuid].power->max - 1; + + set_power_scale(cpuid, cpu_power[cpuid].power->table[idx]); + smp_wmb(); +} + +static void update_power_scale(unsigned int cpu, unsigned int idx) +{ + cpu_power[cpu].id = idx; + cpu_power[cpu].power = table_config[idx]; + + set_cpufreq_scale(cpu, cpu_power[cpu].freq); +} + +static int topo_cpufreq_transition(struct notifier_block *nb, + unsigned long state, void *data) +{ + struct cpufreq_freqs *freqs = data; + + if (state == CPUFREQ_POSTCHANGE || state == CPUFREQ_RESUMECHANGE) + set_cpufreq_scale(freqs->cpu, freqs->new); + + return NOTIFY_OK; +} + +static struct notifier_block topo_cpufreq_nb = { + .notifier_call = topo_cpufreq_transition, +}; + +static int topo_cpufreq_init(struct platform_device *pdev) +{ + unsigned int cpu; + + /* get cpu_power table */ + table_config = dev_get_platdata(&pdev->dev); + + /* init core mask */ + for_each_possible_cpu(cpu) { + cpu_power[cpu].freq = 0; + update_power_scale(cpu, ARM_DEFAULT_SCALE); + } + + /* register cpufreq notification */ + return cpufreq_register_notifier(&topo_cpufreq_nb, + CPUFREQ_TRANSITION_NOTIFIER); +} + +static int topo_cpufreq_exit(struct platform_device *pdev) +{ + unsigned int cpu; + + /* unregister cpufreq notification */ + cpufreq_unregister_notifier(&topo_cpufreq_nb, + CPUFREQ_TRANSITION_NOTIFIER); + + /* cleay core mask */ + for_each_possible_cpu(cpu) { + cpu_power[cpu].freq = 0; + cpu_power[cpu].power = NULL; + } + + /* clear cpu_power table */ + table_config = NULL; + + return 0; +} + +static int topo_policy_transition(struct notifier_block *nb, + unsigned long state, void *data) +{ + int cpu, idx, level = (int)data; + + if (level == POWERSAVINGS_BALANCE_NONE) + idx = ARM_DEFAULT_SCALE; + else + idx = ARM_POWER_SCALE; + + for_each_possible_cpu(cpu) + update_power_scale(cpu, cpu ? ARM_DEFAULT_SCALE : idx ); + + return NOTIFY_OK; +} + +static struct notifier_block topo_policy_nb = { + .notifier_call = topo_policy_transition, +}; + +static int __devinit cpupower_probe(struct platform_device *pdev) +{ + topo_cpufreq_init(pdev); + + /* register cpufreq notifer */ + topology_register_notifier(&topo_policy_nb); + + return 0; +} + +static int __devexit cpupower_remove(struct platform_device *pdev) +{ + /* unregister cpufreq notifer */ + topology_unregister_notifier(&topo_policy_nb); + + topo_cpufreq_exit(pdev); + + return 0; +} + + +static struct platform_driver cpupower_driver = { + .driver = { + .owner = THIS_MODULE, + .name = "cpupower", + }, + .probe = cpupower_probe, + .remove = __devexit_p(cpupower_remove), +}; + +static int __init cpupower_init(void) +{ + return platform_driver_register(&cpupower_driver); +} + +static void __exit cpupower_exit(void) +{ + platform_driver_unregister(&cpupower_driver); +} + +core_initcall(cpupower_init); +module_exit(cpupower_exit); + +MODULE_AUTHOR("vincent Guittot"); +MODULE_DESCRIPTION("update cpu_power according to current cpu load driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:" DRIVER_NAME); diff --git a/drivers/staging/prima/CORE/SME/src/csr/csrNeighborRoam.c b/drivers/staging/prima/CORE/SME/src/csr/csrNeighborRoam.c index edbc954d683..57f1f67ab65 100644 --- a/drivers/staging/prima/CORE/SME/src/csr/csrNeighborRoam.c +++ b/drivers/staging/prima/CORE/SME/src/csr/csrNeighborRoam.c @@ -86,7 +86,7 @@ #include "csrCcx.h" #endif -#define WLAN_FEATURE_NEIGHBOR_ROAMING_DEBUG 1 +/* #define WLAN_FEATURE_NEIGHBOR_ROAMING_DEBUG 1 */ #ifdef WLAN_FEATURE_NEIGHBOR_ROAMING_DEBUG #define NEIGHBOR_ROAM_DEBUG smsLog #else diff --git a/drivers/staging/prima/Kbuild b/drivers/staging/prima/Kbuild index f1e81846812..adb1b113b08 100644 --- a/drivers/staging/prima/Kbuild +++ b/drivers/staging/prima/Kbuild @@ -618,7 +618,7 @@ CDEFINES += -DWLAN_OPEN_SOURCE endif # Fix build for GCC 4.7 -EXTRA_CFLAGS += -Wno-maybe-uninitialized -Wno-unused-function +EXTRA_CFLAGS += -Wno-maybe-uninitialized -Wno-unused-function -Wno-array-bounds KBUILD_CPPFLAGS += $(CDEFINES) diff --git a/drivers/thermal/msm8960_tsens.c b/drivers/thermal/msm8960_tsens.c index c571de6acea..c826c8b9e00 100644 --- a/drivers/thermal/msm8960_tsens.c +++ b/drivers/thermal/msm8960_tsens.c @@ -145,7 +145,7 @@ struct tsens_tm_device_sensor { struct thermal_zone_device *tz_dev; enum thermal_device_mode mode; unsigned int sensor_num; - struct work_struct work; + struct work_struct *work; int offset; int calib_data; int calib_data_backup; @@ -232,6 +232,20 @@ static int tsens_tz_get_temp(struct thermal_zone_device *thermal, return 0; } +int tsens_get_sensor_temp(int sensor_num, unsigned long *temp) +{ + if (!tmdev) + return -ENODEV; + + if (sensor_num < 0 || sensor_num >= TSENS_MAX_SENSORS || !temp) + return -EINVAL; + + tsens8960_get_temp(sensor_num, temp); + + return 0; +} +EXPORT_SYMBOL(tsens_get_sensor_temp); + int tsens_get_temp(struct tsens_device *device, unsigned long *temp) { if (!tmdev) @@ -590,6 +604,42 @@ static int tsens_tz_set_trip_temp(struct thermal_zone_device *thermal, return 0; } +static int +tsens_set_tz_trip_temp_degC(int sensor_num, enum tsens_trip_type trip, int temp, struct work_struct *work) +{ + struct thermal_zone_device *thermal; + int ret; + + if (! tmdev || sensor_num < 0 || sensor_num >= tmdev->tsens_num_sensor) + return -EINVAL; + + thermal = tmdev->sensor[sensor_num].tz_dev; + + ret = tsens_tz_set_trip_temp(thermal, trip, temp); + if (ret < 0) + return ret; + + ret = tsens_tz_activate_trip_type(thermal, trip, THERMAL_TRIP_ACTIVATION_ENABLED); + if (ret < 0) + return ret; + + tmdev->sensor[sensor_num].work = work; + + return 0; +} + +int +tsens_set_tz_warm_temp_degC(int sensor_num, int temp, struct work_struct *work) +{ + return tsens_set_tz_trip_temp_degC(sensor_num, TSENS_TRIP_STAGE2, temp, work); +} + +int +tsens_set_tz_cool_temp_degC(int sensor_num, int temp, struct work_struct *work) +{ + return tsens_set_tz_trip_temp_degC(sensor_num, TSENS_TRIP_STAGE1, temp, work); +} + static struct thermal_zone_device_ops tsens_thermal_zone_ops = { .get_temp = tsens_tz_get_temp, .get_mode = tsens_tz_get_mode, @@ -602,15 +652,6 @@ static struct thermal_zone_device_ops tsens_thermal_zone_ops = { .notify = tsens_tz_notify, }; -static void notify_uspace_tsens_fn(struct work_struct *work) -{ - struct tsens_tm_device_sensor *tm = container_of(work, - struct tsens_tm_device_sensor, work); - - sysfs_notify(&tm->tz_dev->device.kobj, - NULL, "type"); -} - static void tsens_scheduler_fn(struct work_struct *work) { struct tsens_tm_device *tm = container_of(work, struct tsens_tm_device, @@ -618,7 +659,7 @@ static void tsens_scheduler_fn(struct work_struct *work) unsigned int threshold, threshold_low, i, code, reg, sensor, mask; unsigned int sensor_addr; bool upper_th_x, lower_th_x; - int adc_code; + unsigned triggered = 0; if (tmdev->hw_type == APQ_8064) { reg = readl_relaxed(TSENS_8064_STATUS_CNTL); @@ -649,7 +690,7 @@ static void tsens_scheduler_fn(struct work_struct *work) for (i = 0; i < tmdev->tsens_num_sensor; i++) { if (i == TSENS_8064_SEQ_SENSORS) sensor_addr += TSENS_8064_S4_S5_OFFSET; - if (sensor & TSENS_MASK1) { + if ((sensor & TSENS_MASK1) != 0 && tm->sensor[i].work) { code = readl_relaxed(sensor_addr); upper_th_x = code >= threshold; lower_th_x = code <= threshold_low; @@ -658,11 +699,7 @@ static void tsens_scheduler_fn(struct work_struct *work) if (lower_th_x) mask |= TSENS_LOWER_STATUS_CLR; if (upper_th_x || lower_th_x) { - /* Notify user space */ - schedule_work(&tm->sensor[i].work); - adc_code = readl_relaxed(sensor_addr); - pr_debug("Trigger (%d degrees) for sensor %d\n", - tsens_tz_code_to_degC(adc_code, i), i); + triggered |= (1 << i); } } sensor >>= 1; @@ -673,6 +710,26 @@ static void tsens_scheduler_fn(struct work_struct *work) else writel_relaxed(reg & mask, TSENS_CNTL_ADDR); mb(); + + /* Actually schedule the work after changing the masks so that + * we don't overwrite any changes that these callbacks want + * to make. + * + * Put a memory barrier before to ensure that we have actually + * made the change to the sensor. + */ + + if (triggered) + for (i = 0; i < tmdev->tsens_num_sensor; i++) + if ((triggered & (1 <sensor[i].work; + tm->sensor[i].work = NULL; + if (work) + schedule_work(work); + } } static irqreturn_t tsens_isr(int irq, void *data) @@ -872,8 +929,7 @@ static int tsens_calib_sensors8660(void) tmdev->sensor[TSENS_MAIN_SENSOR].calib_data; tmdev->prev_reading_avail = false; - INIT_WORK(&tmdev->sensor[TSENS_MAIN_SENSOR].work, - notify_uspace_tsens_fn); + tmdev->sensor[TSENS_MAIN_SENSOR].work = NULL; return 0; } @@ -901,7 +957,7 @@ static int tsens_calib_sensors8960(void) - (tmdev->sensor[i].calib_data * tmdev->sensor[i].slope_mul_tsens_factor); tmdev->prev_reading_avail = false; - INIT_WORK(&tmdev->sensor[i].work, notify_uspace_tsens_fn); + tmdev->sensor[i].work = NULL; } return 0; diff --git a/drivers/thermal/msm_thermal.c b/drivers/thermal/msm_thermal.c index 0e3daeb70ae..5540d9262ea 100644 --- a/drivers/thermal/msm_thermal.c +++ b/drivers/thermal/msm_thermal.c @@ -24,173 +24,171 @@ #include #include #include +#include -static int enabled; -static struct msm_thermal_data msm_thermal_info; -static uint32_t limited_max_freq = MSM_CPUFREQ_NO_LIMIT; -static struct delayed_work check_temp_work; +#define NO_RELEASE_TEMPERATURE 0 +#define NO_TRIGGER_TEMPERATURE -1 -static int limit_idx; -static int limit_idx_low; -static int limit_idx_high; -static struct cpufreq_frequency_table *table; +#define N_TEMP_LIMITS 4 -static int msm_thermal_get_freq_table(void) -{ - int ret = 0; - int i = 0; +static unsigned temp_hysteresis = 5; +static unsigned int limit_temp_degC[N_TEMP_LIMITS] = { 80, 85, 92, 102 }; +static unsigned int limit_freq[N_TEMP_LIMITS] = { 1512000, 1350000, 918000, 384000 }; - table = cpufreq_frequency_get_table(0); - if (table == NULL) { - pr_debug("%s: error reading cpufreq table\n", __func__); - ret = -EINVAL; - goto fail; - } +module_param_array(limit_temp_degC, uint, NULL, 0644); +module_param_array(limit_freq, uint, NULL, 0644); - while (table[i].frequency != CPUFREQ_TABLE_END) - i++; +int throttled_bin = -1; - limit_idx_low = 0; - limit_idx_high = limit_idx = i - 1; - BUG_ON(limit_idx_high <= 0 || limit_idx_high <= limit_idx_low); -fail: - return ret; +module_param(throttled_bin, int, 0444); + +static struct msm_thermal_data msm_thermal_info; +static struct delayed_work first_work; +static struct work_struct trip_work; + +static int max_freq(int throttled_bin) +{ + if (throttled_bin < 0) return MSM_CPUFREQ_NO_LIMIT; + else return limit_freq[throttled_bin]; } -static int update_cpu_max_freq(int cpu, uint32_t max_freq) +static int limit_temp(int throttled_bin) { - int ret = 0; + if (throttled_bin < 0) return limit_temp_degC[0]; + else if (throttled_bin == N_TEMP_LIMITS-1) return NO_TRIGGER_TEMPERATURE; + else return limit_temp_degC[throttled_bin+1]; +} + +static int release_temp(int throttled_bin) +{ + if (throttled_bin < 0) return NO_RELEASE_TEMPERATURE; + else return limit_temp_degC[throttled_bin] - temp_hysteresis; +} - ret = msm_cpufreq_set_freq_limits(cpu, MSM_CPUFREQ_NO_LIMIT, max_freq); +static int update_cpu_max_freq(int cpu, int throttled_bin, unsigned temp) +{ + int ret; + int max_frequency = max_freq(throttled_bin); + + ret = msm_cpufreq_set_freq_limits(cpu, MSM_CPUFREQ_NO_LIMIT, max_frequency); if (ret) return ret; - limited_max_freq = max_freq; - if (max_freq != MSM_CPUFREQ_NO_LIMIT) - pr_info("msm_thermal: Limiting cpu%d max frequency to %d\n", - cpu, max_freq); - else - pr_info("msm_thermal: Max frequency reset for cpu%d\n", cpu); - ret = cpufreq_update_policy(cpu); + if (ret) + return ret; + + if (max_frequency != MSM_CPUFREQ_NO_LIMIT) { + struct cpufreq_policy policy; + + if ((ret = cpufreq_get_policy(&policy, cpu)) == 0) + ret = cpufreq_driver_target(&policy, max_frequency, CPUFREQ_RELATION_L); + } + + if (max_frequency != MSM_CPUFREQ_NO_LIMIT) + pr_info("msm_thermal: limiting cpu%d max frequency to %d at %u degC\n", + cpu, max_frequency, temp); + else + pr_info("msm_thermal: Max frequency reset for cpu%d at %u degC\n", cpu, temp); return ret; } -static void check_temp(struct work_struct *work) +static void +update_all_cpus_max_freq_if_changed(int new_throttled_bin, unsigned temp) { - static int limit_init; - struct tsens_device tsens_dev; - unsigned long temp = 0; - uint32_t max_freq = limited_max_freq; - int cpu = 0; - int ret = 0; + int cpu; + int ret; - tsens_dev.sensor_num = msm_thermal_info.sensor_id; - ret = tsens_get_temp(&tsens_dev, &temp); - if (ret) { - pr_debug("msm_thermal: Unable to read TSENS sensor %d\n", - tsens_dev.sensor_num); - goto reschedule; - } + if (throttled_bin == new_throttled_bin) + return; - if (!limit_init) { - ret = msm_thermal_get_freq_table(); - if (ret) - goto reschedule; - else - limit_init = 1; - } +#ifdef CONFIG_PERFLOCK_BOOT_LOCK + release_boot_lock(); +#endif - if (temp >= msm_thermal_info.limit_temp_degC) { - if (limit_idx == limit_idx_low) - goto reschedule; - - limit_idx -= msm_thermal_info.freq_step; - if (limit_idx < limit_idx_low) - limit_idx = limit_idx_low; - max_freq = table[limit_idx].frequency; - } else if (temp < msm_thermal_info.limit_temp_degC - - msm_thermal_info.temp_hysteresis_degC) { - if (limit_idx == limit_idx_high) - goto reschedule; - - limit_idx += msm_thermal_info.freq_step; - if (limit_idx >= limit_idx_high) { - limit_idx = limit_idx_high; - max_freq = MSM_CPUFREQ_NO_LIMIT; - } else - max_freq = table[limit_idx].frequency; - } - if (max_freq == limited_max_freq) - goto reschedule; + throttled_bin = new_throttled_bin; + - /* Update new limits */ for_each_possible_cpu(cpu) { - ret = update_cpu_max_freq(cpu, max_freq); + ret = update_cpu_max_freq(cpu, throttled_bin, temp); if (ret) - pr_debug("Unable to limit cpu%d max freq to %d\n", - cpu, max_freq); + pr_warn("Unable to limit cpu%d\n", cpu); } - -reschedule: - if (enabled) - schedule_delayed_work(&check_temp_work, - msecs_to_jiffies(msm_thermal_info.poll_ms)); } -static void disable_msm_thermal(void) +static void +configure_sensor_trip_points(void) { - int cpu = 0; + int trigger_temperature = limit_temp(throttled_bin); + int release_temperature = release_temp(throttled_bin); - /* make sure check_temp is no longer running */ - cancel_delayed_work(&check_temp_work); - flush_scheduled_work(); + pr_info("msm_thermal: setting trip range %d..%d on sensor %d.\n", release_temperature, trigger_temperature, msm_thermal_info.sensor_id); + if (trigger_temperature != NO_TRIGGER_TEMPERATURE) + tsens_set_tz_warm_temp_degC(msm_thermal_info.sensor_id, trigger_temperature, &trip_work); - if (limited_max_freq == MSM_CPUFREQ_NO_LIMIT) - return; + if (release_temperature != NO_RELEASE_TEMPERATURE) + tsens_set_tz_cool_temp_degC(msm_thermal_info.sensor_id, release_temperature, &trip_work); +} - for_each_possible_cpu(cpu) { - update_cpu_max_freq(cpu, MSM_CPUFREQ_NO_LIMIT); +static int +select_throttled_bin(unsigned temp) +{ + int i; + int new_bin = -1; + + for (i = 0; i < N_TEMP_LIMITS; i++) { + if (temp >= limit_temp_degC[i]) new_bin = i; } + + if (new_bin > throttled_bin) return new_bin; + if (temp <= release_temp(throttled_bin)) return new_bin; + return throttled_bin; } -static int set_enabled(const char *val, const struct kernel_param *kp) +static void check_temp_and_throttle_if_needed(struct work_struct *work) { - int ret = 0; + struct tsens_device tsens_dev; + unsigned long temp_ul = 0; + unsigned temp; + int new_bin; + int ret; - ret = param_set_bool(val, kp); - if (!enabled) - disable_msm_thermal(); - else - pr_info("msm_thermal: no action for enabled = %d\n", enabled); + tsens_dev.sensor_num = msm_thermal_info.sensor_id; + ret = tsens_get_temp(&tsens_dev, &temp_ul); + if (ret) { + pr_warn("msm_thermal: Unable to read TSENS sensor %d\n", + tsens_dev.sensor_num); + return; + } - pr_info("msm_thermal: enabled = %d\n", enabled); + temp = (unsigned) temp_ul; + new_bin = select_throttled_bin(temp); - return ret; + pr_debug("msm_thermal: TSENS sensor %d is %u degC old-bin %d new-bin %d\n", + tsens_dev.sensor_num, temp, throttled_bin, new_bin); + update_all_cpus_max_freq_if_changed(new_bin, temp); } -static struct kernel_param_ops module_ops = { - .set = set_enabled, - .get = param_get_bool, -}; - -module_param_cb(enabled, &module_ops, &enabled, 0644); -MODULE_PARM_DESC(enabled, "enforce thermal limit on cpu"); +static void check_temp(struct work_struct *work) +{ + check_temp_and_throttle_if_needed(work); + configure_sensor_trip_points(); +} int __devinit msm_thermal_init(struct msm_thermal_data *pdata) { - int ret = 0; BUG_ON(!pdata); BUG_ON(pdata->sensor_id >= TSENS_MAX_SENSORS); memcpy(&msm_thermal_info, pdata, sizeof(struct msm_thermal_data)); - enabled = 1; - INIT_DELAYED_WORK(&check_temp_work, check_temp); - schedule_delayed_work(&check_temp_work, 0); + INIT_DELAYED_WORK(&first_work, check_temp); + INIT_WORK(&trip_work, check_temp); - return ret; + schedule_delayed_work(&first_work, msecs_to_jiffies(5*1000)); + + return 0; } static int __devinit msm_thermal_dev_probe(struct platform_device *pdev) @@ -207,7 +205,7 @@ static int __devinit msm_thermal_dev_probe(struct platform_device *pdev) goto fail; WARN_ON(data.sensor_id >= TSENS_MAX_SENSORS); - key = "qcom,poll-ms"; +/* key = "qcom,poll-ms"; ret = of_property_read_u32(node, key, &data.poll_ms); if (ret) goto fail; @@ -223,7 +221,7 @@ static int __devinit msm_thermal_dev_probe(struct platform_device *pdev) goto fail; key = "qcom,freq-step"; - ret = of_property_read_u32(node, key, &data.freq_step); + ret = of_property_read_u32(node, key, &data.freq_step);*/ fail: if (ret) diff --git a/drivers/thermal/pm8xxx-tm.c b/drivers/thermal/pm8xxx-tm.c index ec043692a63..456893381f3 100644 --- a/drivers/thermal/pm8xxx-tm.c +++ b/drivers/thermal/pm8xxx-tm.c @@ -33,29 +33,32 @@ #include /* Register TEMP_ALARM_CTRL bits */ -#define TEMP_ALARM_CTRL_ST3_SD 0x80 -#define TEMP_ALARM_CTRL_ST2_SD 0x40 -#define TEMP_ALARM_CTRL_STATUS_MASK 0x30 -#define TEMP_ALARM_CTRL_STATUS_SHIFT 4 -#define TEMP_ALARM_CTRL_THRESH_MASK 0x0C -#define TEMP_ALARM_CTRL_THRESH_SHIFT 2 -#define TEMP_ALARM_CTRL_OVRD_ST3 0x02 -#define TEMP_ALARM_CTRL_OVRD_ST2 0x01 -#define TEMP_ALARM_CTRL_OVRD_MASK 0x03 - -#define TEMP_STAGE_STEP 20000 /* Stage step: 20.000 C */ -#define TEMP_STAGE_HYSTERESIS 2000 - -#define TEMP_THRESH_MIN 105000 /* Threshold Min: 105 C */ -#define TEMP_THRESH_STEP 5000 /* Threshold step: 5 C */ +#define TEMP_ALARM_CTRL_ST3_SD 0x80 +#define TEMP_ALARM_CTRL_ST2_SD 0x40 +#define TEMP_ALARM_CTRL_STATUS_MASK 0x30 +#define TEMP_ALARM_CTRL_STATUS_SHIFT 4 +#define TEMP_ALARM_CTRL_THRESH_MASK 0x0C +#define TEMP_ALARM_CTRL_THRESH_SHIFT 2 +#define TEMP_ALARM_CTRL_OVRD_ST3 0x02 +#define TEMP_ALARM_CTRL_OVRD_ST2 0x01 +#define TEMP_ALARM_CTRL_OVRD_MASK 0x03 + +#define TEMP_STAGE_STEP 20000 /* Stage step: 20.000 C */ +#define TEMP_STAGE_HYSTERESIS 2000 + +#define TEMP_THRESH_MIN 105000 /* Threshold Min: 105 C */ +#define TEMP_THRESH_STEP 5000 /* Threshold step: 5 C */ /* Register TEMP_ALARM_PWM bits */ -#define TEMP_ALARM_PWM_EN_MASK 0xC0 -#define TEMP_ALARM_PWM_EN_SHIFT 6 -#define TEMP_ALARM_PWM_PER_PRE_MASK 0x38 -#define TEMP_ALARM_PWM_PER_PRE_SHIFT 3 -#define TEMP_ALARM_PWM_PER_DIV_MASK 0x07 -#define TEMP_ALARM_PWM_PER_DIV_SHIFT 0 +#define TEMP_ALARM_PWM_EN_MASK 0xC0 +#define TEMP_ALARM_PWM_EN_NEVER 0x00 +#define TEMP_ALARM_PWM_EN_SLEEP_B 0x40 +#define TEMP_ALARM_PWM_EN_PWM 0x80 +#define TEMP_ALARM_PWM_EN_ALWAYS 0xC0 +#define TEMP_ALARM_PWM_PER_PRE_MASK 0x38 +#define TEMP_ALARM_PWM_PER_PRE_SHIFT 3 +#define TEMP_ALARM_PWM_PER_DIV_MASK 0x07 +#define TEMP_ALARM_PWM_PER_DIV_SHIFT 0 /* Trips: from critical to less critical */ #define TRIP_STAGE3 0 @@ -516,16 +519,15 @@ static int pm8xxx_tm_init_reg(struct pm8xxx_tm_chip *chip) return rc; /* - * Set the PMIC alarm module PWM to have a frequency of 8 Hz. This - * helps cut down on the number of unnecessary interrupts fired when - * changing between thermal stages. Also, Enable the over temperature - * PWM whenever the PMIC is enabled. + * Set the PMIC temperature alarm module to be always on. This ensures + * that die temperature monitoring is active even if CXO is disabled + * (i.e. when sleep_b is low). This is necessary since CXO can be + * disabled while the system is still heavily loaded. Also, using + * the alway-on instead of PWM-enabled configurations ensures that the + * die temperature can be measured by the PMIC ADC without reconfiguring + * the temperature alarm module first. */ - reg = (1 << TEMP_ALARM_PWM_EN_SHIFT) - | (3 << TEMP_ALARM_PWM_PER_PRE_SHIFT) - | (3 << TEMP_ALARM_PWM_PER_DIV_SHIFT); - - rc = pm8xxx_tm_write_pwm(chip, reg); + rc = pm8xxx_tm_write_pwm(chip, TEMP_ALARM_PWM_EN_ALWAYS); return rc; } diff --git a/drivers/tty/hvc/hvc_xen.c b/drivers/tty/hvc/hvc_xen.c index 83d5c88e716..d3d91dae065 100644 --- a/drivers/tty/hvc/hvc_xen.c +++ b/drivers/tty/hvc/hvc_xen.c @@ -430,9 +430,9 @@ static int __devinit xencons_probe(struct xenbus_device *dev, if (devid == 0) return -ENODEV; - info = kzalloc(sizeof(struct xencons_info), GFP_KERNEL | __GFP_ZERO); + info = kzalloc(sizeof(struct xencons_info), GFP_KERNEL); if (!info) - goto error_nomem; + return -ENOMEM; dev_set_drvdata(&dev->dev, info); info->xbdev = dev; info->vtermno = xenbus_devid_to_vtermno(devid); diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c index 5c27f7e6c9f..d537431d7e2 100644 --- a/drivers/tty/serial/8250/8250.c +++ b/drivers/tty/serial/8250/8250.c @@ -2280,10 +2280,11 @@ serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, quot++; if (up->capabilities & UART_CAP_FIFO && port->fifosize > 1) { - if (baud < 2400) - fcr = UART_FCR_ENABLE_FIFO | UART_FCR_TRIGGER_1; - else - fcr = uart_config[port->type].fcr; + fcr = uart_config[port->type].fcr; + if (baud < 2400) { + fcr &= ~UART_FCR_TRIGGER_MASK; + fcr |= UART_FCR_TRIGGER_1; + } } /* diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index 858dca865d6..3614973c999 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -1609,54 +1609,72 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { { .vendor = PCI_VENDOR_ID_INTEL, .device = 0x8811, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, .init = pci_eg20t_init, .setup = pci_default_setup, }, { .vendor = PCI_VENDOR_ID_INTEL, .device = 0x8812, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, .init = pci_eg20t_init, .setup = pci_default_setup, }, { .vendor = PCI_VENDOR_ID_INTEL, .device = 0x8813, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, .init = pci_eg20t_init, .setup = pci_default_setup, }, { .vendor = PCI_VENDOR_ID_INTEL, .device = 0x8814, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, .init = pci_eg20t_init, .setup = pci_default_setup, }, { .vendor = 0x10DB, .device = 0x8027, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, .init = pci_eg20t_init, .setup = pci_default_setup, }, { .vendor = 0x10DB, .device = 0x8028, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, .init = pci_eg20t_init, .setup = pci_default_setup, }, { .vendor = 0x10DB, .device = 0x8029, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, .init = pci_eg20t_init, .setup = pci_default_setup, }, { .vendor = 0x10DB, .device = 0x800C, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, .init = pci_eg20t_init, .setup = pci_default_setup, }, { .vendor = 0x10DB, .device = 0x800D, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, .init = pci_eg20t_init, .setup = pci_default_setup, }, diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c index 55fd362b987..039c054349e 100644 --- a/drivers/tty/serial/mxs-auart.c +++ b/drivers/tty/serial/mxs-auart.c @@ -369,6 +369,8 @@ static void mxs_auart_settermios(struct uart_port *u, writel(ctrl, u->membase + AUART_LINECTRL); writel(ctrl2, u->membase + AUART_CTRL2); + + uart_update_timeout(u, termios->c_cflag, baud); } static irqreturn_t mxs_auart_irq_handle(int irq, void *context) diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 9ca64ac0033..450c891e12f 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -2289,6 +2289,7 @@ void uart_unregister_driver(struct uart_driver *drv) tty_unregister_driver(p); put_tty_driver(p); kfree(drv->state); + drv->state = NULL; drv->tty_driver = NULL; } diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 0bb2b3248da..4c8321ea4c5 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -309,9 +309,6 @@ static void free_urbs(struct wdm_device *desc) static void cleanup(struct wdm_device *desc) { - spin_lock(&wdm_device_list_lock); - list_del(&desc->device_list); - spin_unlock(&wdm_device_list_lock); kfree(desc->sbuf); kfree(desc->inbuf); kfree(desc->orq); @@ -530,11 +527,13 @@ static int wdm_flush(struct file *file, fl_owner_t id) struct wdm_device *desc = file->private_data; wait_event(desc->wait, !test_bit(WDM_IN_USE, &desc->flags)); - if (desc->werr < 0) + + /* cannot dereference desc->intf if WDM_DISCONNECTING */ + if (desc->werr < 0 && !test_bit(WDM_DISCONNECTING, &desc->flags)) dev_err(&desc->intf->dev, "Error in flush path: %d\n", desc->werr); - return desc->werr; + return usb_translate_errors(desc->werr); } static unsigned int wdm_poll(struct file *file, struct poll_table_struct *wait) @@ -545,7 +544,7 @@ static unsigned int wdm_poll(struct file *file, struct poll_table_struct *wait) spin_lock_irqsave(&desc->iuspin, flags); if (test_bit(WDM_DISCONNECTING, &desc->flags)) { - mask = POLLERR; + mask = POLLHUP | POLLERR; spin_unlock_irqrestore(&desc->iuspin, flags); goto desc_out; } @@ -621,10 +620,15 @@ static int wdm_release(struct inode *inode, struct file *file) mutex_unlock(&desc->wlock); if (!desc->count) { - dev_dbg(&desc->intf->dev, "wdm_release: cleanup"); - kill_urbs(desc); - if (!test_bit(WDM_DISCONNECTING, &desc->flags)) + if (!test_bit(WDM_DISCONNECTING, &desc->flags)) { + dev_dbg(&desc->intf->dev, "wdm_release: cleanup"); + kill_urbs(desc); desc->manage_power(desc->intf, 0); + } else { + /* must avoid dev_printk here as desc->intf is invalid */ + pr_debug(KBUILD_MODNAME " %s: device gone - cleaning up\n", __func__); + cleanup(desc); + } } mutex_unlock(&wdm_mutex); return 0; @@ -771,6 +775,9 @@ static int wdm_create(struct usb_interface *intf, struct usb_endpoint_descriptor out: return rv; err: + spin_lock(&wdm_device_list_lock); + list_del(&desc->device_list); + spin_unlock(&wdm_device_list_lock); cleanup(desc); return rv; } @@ -896,6 +903,12 @@ static void wdm_disconnect(struct usb_interface *intf) cancel_work_sync(&desc->rxwork); mutex_unlock(&desc->wlock); mutex_unlock(&desc->rlock); + + /* the desc->intf pointer used as list key is now invalid */ + spin_lock(&wdm_device_list_lock); + list_del(&desc->device_list); + spin_unlock(&wdm_device_list_lock); + if (!desc->count) cleanup(desc); mutex_unlock(&wdm_mutex); diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 8df4b76465a..4e577728ead 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -333,17 +333,14 @@ static struct async *async_getcompleted(struct dev_state *ps) static struct async *async_getpending(struct dev_state *ps, void __user *userurb) { - unsigned long flags; struct async *as; - spin_lock_irqsave(&ps->lock, flags); list_for_each_entry(as, &ps->async_pending, asynclist) if (as->userurb == userurb) { list_del_init(&as->asynclist); - spin_unlock_irqrestore(&ps->lock, flags); return as; } - spin_unlock_irqrestore(&ps->lock, flags); + return NULL; } @@ -398,6 +395,7 @@ static void cancel_bulk_urbs(struct dev_state *ps, unsigned bulk_addr) __releases(ps->lock) __acquires(ps->lock) { + struct urb *urb; struct async *as; /* Mark all the pending URBs that match bulk_addr, up to but not @@ -420,8 +418,11 @@ __acquires(ps->lock) list_for_each_entry(as, &ps->async_pending, asynclist) { if (as->bulk_status == AS_UNLINK) { as->bulk_status = 0; /* Only once */ + urb = as->urb; + usb_get_urb(urb); spin_unlock(&ps->lock); /* Allow completions */ - usb_unlink_urb(as->urb); + usb_unlink_urb(urb); + usb_put_urb(urb); spin_lock(&ps->lock); goto rescan; } @@ -472,6 +473,7 @@ static void async_completed(struct urb *urb) static void destroy_async(struct dev_state *ps, struct list_head *list) { + struct urb *urb; struct async *as; unsigned long flags; @@ -479,10 +481,13 @@ static void destroy_async(struct dev_state *ps, struct list_head *list) while (!list_empty(list)) { as = list_entry(list->next, struct async, asynclist); list_del_init(&as->asynclist); + urb = as->urb; + usb_get_urb(urb); /* drop the spinlock so the completion handler can run */ spin_unlock_irqrestore(&ps->lock, flags); - usb_kill_urb(as->urb); + usb_kill_urb(urb); + usb_put_urb(urb); spin_lock_irqsave(&ps->lock, flags); } spin_unlock_irqrestore(&ps->lock, flags); @@ -1410,12 +1415,24 @@ static int proc_submiturb(struct dev_state *ps, void __user *arg) static int proc_unlinkurb(struct dev_state *ps, void __user *arg) { + struct urb *urb; struct async *as; + unsigned long flags; + spin_lock_irqsave(&ps->lock, flags); as = async_getpending(ps, arg); - if (!as) + if (!as) { + spin_unlock_irqrestore(&ps->lock, flags); return -EINVAL; - usb_kill_urb(as->urb); + } + + urb = as->urb; + usb_get_urb(urb); + spin_unlock_irqrestore(&ps->lock, flags); + + usb_kill_urb(urb); + usb_put_urb(urb); + return 0; } diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index d97d5480d93..d30a1676e68 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2602,6 +2602,10 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) NULL, 0, USB_CTRL_SET_TIMEOUT); + /* Try to enable USB2 hardware LPM again */ + if (udev->usb2_hw_lpm_capable == 1) + usb_set_usb2_hardware_lpm(udev, 1); + /* System sleep transitions should never fail */ if (!PMSG_IS_AUTO(msg)) status = 0; @@ -2735,7 +2739,7 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg) struct usb_hub *hub = hdev_to_hub(udev->parent); int port1 = udev->portnum; int status; - u16 portchange, portstatus; + u16 portchange = 0, portstatus = 0; /* Skip the initial Clear-Suspend step for a remote wakeup */ status = hub_port_status(hub, port1, &portstatus, &portchange); diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index 200dc9bfeec..1df3f0683d7 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -123,6 +123,9 @@ static const struct usb_device_id usb_quirk_list[] = { /* Guillemot Webcam Hercules Dualpix Exchange*/ { USB_DEVICE(0x06f8, 0x3005), .driver_info = USB_QUIRK_RESET_RESUME }, + /* Midiman M-Audio Keystation 88es */ + { USB_DEVICE(0x0763, 0x0192), .driver_info = USB_QUIRK_RESET_RESUME }, + /* M-Systems Flash Disk Pioneers */ { USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME }, diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c index cd9b3a2cd8a..9d912bfdcff 100644 --- a/drivers/usb/core/urb.c +++ b/drivers/usb/core/urb.c @@ -680,6 +680,27 @@ void usb_unpoison_urb(struct urb *urb) } EXPORT_SYMBOL_GPL(usb_unpoison_urb); +/** + * usb_block_urb - reliably prevent further use of an URB + * @urb: pointer to URB to be blocked, may be NULL + * + * After the routine has run, attempts to resubmit the URB will fail + * with error -EPERM. Thus even if the URB's completion handler always + * tries to resubmit, it will not succeed and the URB will become idle. + * + * The URB must not be deallocated while this routine is running. In + * particular, when a driver calls this routine, it must insure that the + * completion handler cannot deallocate the URB. + */ +void usb_block_urb(struct urb *urb) +{ + if (!urb) + return; + + atomic_inc(&urb->reject); +} +EXPORT_SYMBOL_GPL(usb_block_urb); + /** * usb_kill_anchored_urbs - cancel transfer requests en masse * @anchor: anchor the requests are bound to diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c index f52cb1ae45d..1d4c535671a 100644 --- a/drivers/usb/gadget/f_fs.c +++ b/drivers/usb/gadget/f_fs.c @@ -1473,8 +1473,22 @@ static int functionfs_bind_config(struct usb_composite_dev *cdev, static void ffs_func_free(struct ffs_function *func) { + struct ffs_ep *ep = func->eps; + unsigned count = func->ffs->eps_count; + unsigned long flags; + ENTER(); + /* cleanup after autoconfig */ + spin_lock_irqsave(&func->ffs->eps_lock, flags); + do { + if (ep->ep && ep->req) + usb_ep_free_request(ep->ep, ep->req); + ep->req = NULL; + ++ep; + } while (--count); + spin_unlock_irqrestore(&func->ffs->eps_lock, flags); + ffs_data_put(func->ffs); kfree(func->eps); diff --git a/drivers/usb/gadget/f_qdss.c b/drivers/usb/gadget/f_qdss.c index 26e4bd53642..e588849f961 100644 --- a/drivers/usb/gadget/f_qdss.c +++ b/drivers/usb/gadget/f_qdss.c @@ -583,7 +583,7 @@ static int qdss_bind_config(struct usb_configuration *c, const char *name) spin_lock_irqsave(&d_lock, flags); list_for_each_entry(ch, &usb_qdss_ch_list, list) { - if (!strncmp(name, ch->name, sizeof(ch->name))) { + if (!strncmp(name, ch->name, sizeof(*ch->name))) { found = 1; break; } @@ -737,7 +737,7 @@ struct usb_qdss_ch *usb_qdss_open(const char *name, void *priv, spin_lock_irqsave(&d_lock, flags); /* Check if we already have a channel with this name */ list_for_each_entry(ch, &usb_qdss_ch_list, list) { - if (!strncmp(name, ch->name, sizeof(ch->name))) { + if (!strncmp(name, ch->name, sizeof(*ch->name))) { found = 1; break; } diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index 55abfb6bd61..188a89f9514 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -736,6 +736,8 @@ static void fsl_queue_td(struct fsl_ep *ep, struct fsl_req *req) lastreq = list_entry(ep->queue.prev, struct fsl_req, queue); lastreq->tail->next_td_ptr = cpu_to_hc32(req->head->td_dma & DTD_ADDR_MASK); + /* Ensure dTD's next dtd pointer to be updated */ + wmb(); /* Read prime bit, if 1 goto done */ if (fsl_readl(&dr_regs->endpointprime) & bitmask) return; diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c index 5c78f9e7146..e669c6a7e91 100644 --- a/drivers/usb/host/ehci-omap.c +++ b/drivers/usb/host/ehci-omap.c @@ -242,15 +242,6 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev) ehci_reset(omap_ehci); - ret = usb_add_hcd(hcd, irq, IRQF_SHARED); - if (ret) { - dev_err(dev, "failed to add hcd with err %d\n", ret); - goto err_add_hcd; - } - - /* root ports should always stay powered */ - ehci_port_power(omap_ehci, 1); - if (pdata->phy_reset) { /* Hold the PHY in RESET for enough time till * PHY is settled and ready @@ -264,6 +255,15 @@ static int ehci_hcd_omap_probe(struct platform_device *pdev) gpio_set_value(pdata->reset_gpio_port[1], 1); } + ret = usb_add_hcd(hcd, irq, IRQF_SHARED); + if (ret) { + dev_err(dev, "failed to add hcd with err %d\n", ret); + goto err_add_hcd; + } + + /* root ports should always stay powered */ + ehci_port_power(omap_ehci, 1); + return 0; err_add_hcd: diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index fe8dc069164..bc94d7bf072 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -368,7 +368,9 @@ static bool usb_is_intel_switchable_ehci(struct pci_dev *pdev) { return pdev->class == PCI_CLASS_SERIAL_USB_EHCI && pdev->vendor == PCI_VENDOR_ID_INTEL && - pdev->device == 0x1E26; + (pdev->device == 0x1E26 || + pdev->device == 0x8C2D || + pdev->device == 0x8C26); } static void ehci_enable_xhci_companion(void) diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c index d238b4e24bb..82c1eb8b18d 100644 --- a/drivers/usb/host/ehci-platform.c +++ b/drivers/usb/host/ehci-platform.c @@ -75,8 +75,6 @@ static const struct hc_driver ehci_platform_hc_driver = { .relinquish_port = ehci_relinquish_port, .port_handed_over = ehci_port_handed_over, - .update_device = ehci_update_device, - .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, }; diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index 13ebeca8e73..55d3d641447 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -223,7 +223,7 @@ static void __devexit usb_hcd_at91_remove(struct usb_hcd *hcd, /*-------------------------------------------------------------------------*/ static int __devinit -ohci_at91_start (struct usb_hcd *hcd) +ohci_at91_reset (struct usb_hcd *hcd) { struct at91_usbh_data *board = hcd->self.controller->platform_data; struct ohci_hcd *ohci = hcd_to_ohci (hcd); @@ -233,6 +233,14 @@ ohci_at91_start (struct usb_hcd *hcd) return ret; ohci->num_ports = board->ports; + return 0; +} + +static int __devinit +ohci_at91_start (struct usb_hcd *hcd) +{ + struct ohci_hcd *ohci = hcd_to_ohci (hcd); + int ret; if ((ret = ohci_run(ohci)) < 0) { err("can't start %s", hcd->self.bus_name); @@ -418,6 +426,7 @@ static const struct hc_driver ohci_at91_hc_driver = { /* * basic lifecycle operations */ + .reset = ohci_at91_reset, .start = ohci_at91_start, .stop = ohci_stop, .shutdown = ohci_shutdown, diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index 32dada8c8b4..df0828cb2aa 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -9,6 +9,7 @@ */ #include +#include #include #include #include @@ -712,12 +713,28 @@ static int handshake(void __iomem *ptr, u32 mask, u32 done, return -ETIMEDOUT; } -bool usb_is_intel_switchable_xhci(struct pci_dev *pdev) +#define PCI_DEVICE_ID_INTEL_LYNX_POINT_XHCI 0x8C31 + +bool usb_is_intel_ppt_switchable_xhci(struct pci_dev *pdev) { return pdev->class == PCI_CLASS_SERIAL_USB_XHCI && pdev->vendor == PCI_VENDOR_ID_INTEL && pdev->device == PCI_DEVICE_ID_INTEL_PANTHERPOINT_XHCI; } + +/* The Intel Lynx Point chipset also has switchable ports. */ +bool usb_is_intel_lpt_switchable_xhci(struct pci_dev *pdev) +{ + return pdev->class == PCI_CLASS_SERIAL_USB_XHCI && + pdev->vendor == PCI_VENDOR_ID_INTEL && + pdev->device == PCI_DEVICE_ID_INTEL_LYNX_POINT_XHCI; +} + +bool usb_is_intel_switchable_xhci(struct pci_dev *pdev) +{ + return usb_is_intel_ppt_switchable_xhci(pdev) || + usb_is_intel_lpt_switchable_xhci(pdev); +} EXPORT_SYMBOL_GPL(usb_is_intel_switchable_xhci); /* @@ -742,6 +759,19 @@ void usb_enable_xhci_ports(struct pci_dev *xhci_pdev) { u32 ports_available; + /* Don't switchover the ports if the user hasn't compiled the xHCI + * driver. Otherwise they will see "dead" USB ports that don't power + * the devices. + */ + if (!IS_ENABLED(CONFIG_USB_XHCI_HCD)) { + dev_warn(&xhci_pdev->dev, + "CONFIG_USB_XHCI_HCD is turned off, " + "defaulting to EHCI.\n"); + dev_warn(&xhci_pdev->dev, + "USB 3.0 devices will work at USB 2.0 speeds.\n"); + return; + } + ports_available = 0xffffffff; /* Write USB3_PSSEN, the USB 3.0 Port SuperSpeed Enable * Register, to turn on SuperSpeed terminations for all diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 78ece8d13e7..68a0523b635 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -568,6 +568,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, xhci_dbg(xhci, "Resume USB2 port %d\n", wIndex + 1); bus_state->resume_done[wIndex] = 0; + clear_bit(wIndex, &bus_state->resuming_ports); xhci_set_link_state(xhci, port_array, wIndex, XDEV_U0); xhci_dbg(xhci, "set port %d resume\n", @@ -861,7 +862,12 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf) /* Initial status is no changes */ retval = (max_ports + 8) / 8; memset(buf, 0, retval); - status = 0; + + /* + * Inform the usbcore about resume-in-progress by returning + * a non-zero value even if there are no status changes. + */ + status = bus_state->resuming_ports; mask = PORT_CSC | PORT_PEC | PORT_OCC | PORT_PLC | PORT_WRC; @@ -901,15 +907,11 @@ int xhci_bus_suspend(struct usb_hcd *hcd) spin_lock_irqsave(&xhci->lock, flags); if (hcd->self.root_hub->do_remote_wakeup) { - port_index = max_ports; - while (port_index--) { - if (bus_state->resume_done[port_index] != 0) { - spin_unlock_irqrestore(&xhci->lock, flags); - xhci_dbg(xhci, "suspend failed because " - "port %d is resuming\n", - port_index + 1); - return -EBUSY; - } + if (bus_state->resuming_ports) { + spin_unlock_irqrestore(&xhci->lock, flags); + xhci_dbg(xhci, "suspend failed because " + "a port is resuming\n"); + return -EBUSY; } } diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 68eaa908ac8..497ed7723e4 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1791,6 +1791,14 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) { struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller); struct dev_info *dev_info, *next; + struct list_head *tt_list_head; + struct list_head *tt; + struct list_head *endpoints; + struct list_head *ep, *q; + struct xhci_tt_bw_info *tt_info; + struct xhci_interval_bw_table *bwt; + struct xhci_virt_ep *virt_ep; + unsigned long flags; int size; int i; @@ -1807,6 +1815,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) xhci->event_ring = NULL; xhci_dbg(xhci, "Freed event ring\n"); + xhci->cmd_ring_reserved_trbs = 0; if (xhci->cmd_ring) xhci_ring_free(xhci, xhci->cmd_ring); xhci->cmd_ring = NULL; @@ -1849,8 +1858,26 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) } spin_unlock_irqrestore(&xhci->lock, flags); + bwt = &xhci->rh_bw->bw_table; + for (i = 0; i < XHCI_MAX_INTERVAL; i++) { + endpoints = &bwt->interval_bw[i].endpoints; + list_for_each_safe(ep, q, endpoints) { + virt_ep = list_entry(ep, struct xhci_virt_ep, bw_endpoint_list); + list_del(&virt_ep->bw_endpoint_list); + kfree(virt_ep); + } + } + + tt_list_head = &xhci->rh_bw->tts; + list_for_each_safe(tt, q, tt_list_head) { + tt_info = list_entry(tt, struct xhci_tt_bw_info, tt_list); + list_del(tt); + kfree(tt_info); + } + xhci->num_usb2_ports = 0; xhci->num_usb3_ports = 0; + xhci->num_active_eps = 0; kfree(xhci->usb2_ports); kfree(xhci->usb3_ports); kfree(xhci->port_array); diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 7a856a767e7..19e89216436 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -72,6 +72,7 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) xhci_dbg(xhci, "QUIRK: Fresco Logic revision %u " "has broken MSI implementation\n", pdev->revision); + xhci->quirks |= XHCI_TRUST_TX_LENGTH; } if (pdev->vendor == PCI_VENDOR_ID_NEC) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 3d9422f16a2..525a1ee8127 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1377,6 +1377,7 @@ static void handle_port_status(struct xhci_hcd *xhci, xhci_dbg(xhci, "resume HS port %d\n", port_id); bus_state->resume_done[faked_port_index] = jiffies + msecs_to_jiffies(20); + set_bit(faked_port_index, &bus_state->resuming_ports); mod_timer(&hcd->rh_timer, bus_state->resume_done[faked_port_index]); /* Do the rest in GetPortStatus */ @@ -1786,8 +1787,12 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td, /* handle completion code */ switch (trb_comp_code) { case COMP_SUCCESS: - frame->status = 0; - break; + if (TRB_LEN(le32_to_cpu(event->transfer_len)) == 0) { + frame->status = 0; + break; + } + if ((xhci->quirks & XHCI_TRUST_TX_LENGTH)) + trb_comp_code = COMP_SHORT_TX; case COMP_SHORT_TX: frame->status = td->urb->transfer_flags & URB_SHORT_NOT_OK ? -EREMOTEIO : 0; @@ -1803,6 +1808,7 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td, break; case COMP_DEV_ERR: case COMP_STALL: + case COMP_TX_ERR: frame->status = -EPROTO; skip_td = true; break; @@ -1883,13 +1889,16 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td, switch (trb_comp_code) { case COMP_SUCCESS: /* Double check that the HW transferred everything. */ - if (event_trb != td->last_trb) { + if (event_trb != td->last_trb || + TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) { xhci_warn(xhci, "WARN Successful completion " "on short TX\n"); if (td->urb->transfer_flags & URB_SHORT_NOT_OK) *status = -EREMOTEIO; else *status = 0; + if ((xhci->quirks & XHCI_TRUST_TX_LENGTH)) + trb_comp_code = COMP_SHORT_TX; } else { *status = 0; } @@ -2048,6 +2057,13 @@ static int handle_tx_event(struct xhci_hcd *xhci, * transfer type */ case COMP_SUCCESS: + if (TRB_LEN(le32_to_cpu(event->transfer_len)) == 0) + break; + if (xhci->quirks & XHCI_TRUST_TX_LENGTH) + trb_comp_code = COMP_SHORT_TX; + else + xhci_warn(xhci, "WARN Successful completion on short TX: " + "needs XHCI_TRUST_TX_LENGTH quirk?\n"); case COMP_SHORT_TX: break; case COMP_STOP: diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 2c26998499a..73356dcb9ae 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -152,7 +152,7 @@ int xhci_reset(struct xhci_hcd *xhci) { u32 command; u32 state; - int ret; + int ret, i; state = xhci_readl(xhci, &xhci->op_regs->status); if ((state & STS_HALT) == 0) { @@ -175,7 +175,15 @@ int xhci_reset(struct xhci_hcd *xhci) * xHCI cannot write to any doorbells or operational registers other * than status until the "Controller Not Ready" flag is cleared. */ - return handshake(xhci, &xhci->op_regs->status, STS_CNR, 0, 250 * 1000); + ret = handshake(xhci, &xhci->op_regs->status, STS_CNR, 0, 250 * 1000); + + for (i = 0; i < 2; ++i) { + xhci->bus_state[i].port_c_suspend = 0; + xhci->bus_state[i].suspended_ports = 0; + xhci->bus_state[i].resuming_ports = 0; + } + + return ret; } #ifdef CONFIG_PCI diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 127b0e9af1b..b15d80052f0 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1362,6 +1362,8 @@ struct xhci_bus_state { u32 suspended_ports; u32 port_remote_wakeup; unsigned long resume_done[USB_MAXCHILDREN]; + /* which ports have started to resume */ + unsigned long resuming_ports; }; static inline unsigned int hcd_index(struct usb_hcd *hcd) @@ -1479,6 +1481,7 @@ struct xhci_hcd { #define XHCI_RESET_ON_RESUME (1 << 7) #define XHCI_SW_BW_CHECKING (1 << 8) #define XHCI_AMD_0x96_HOST (1 << 9) +#define XHCI_TRUST_TX_LENGTH (1 << 10 /* * In Synopsis DWC3 controller, PORTSC register access involves multiple clock * domains. When the software does a PORTSC write, handshakes are needed diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index 9dcb68f04f0..055b84adeda 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c @@ -1028,7 +1028,10 @@ test_ctrl_queue(struct usbtest_dev *dev, struct usbtest_param *param) case 13: /* short read, resembling case 10 */ req.wValue = cpu_to_le16((USB_DT_CONFIG << 8) | 0); /* last data packet "should" be DATA1, not DATA0 */ - len = 1024 - udev->descriptor.bMaxPacketSize0; + if (udev->speed == USB_SPEED_SUPER) + len = 1024 - 512; + else + len = 1024 - udev->descriptor.bMaxPacketSize0; expected = -EREMOTEIO; break; case 14: /* short read; try to fill the last packet */ @@ -1387,11 +1390,15 @@ static int test_halt(struct usbtest_dev *tdev, int ep, struct urb *urb) static int halt_simple(struct usbtest_dev *dev) { - int ep; - int retval = 0; - struct urb *urb; + int ep; + int retval = 0; + struct urb *urb; + struct usb_device *udev = testdev_to_usbdev(dev); - urb = simple_alloc_urb(testdev_to_usbdev(dev), 0, 512); + if (udev->speed == USB_SPEED_SUPER) + urb = simple_alloc_urb(udev, 0, 1024); + else + urb = simple_alloc_urb(udev, 0, 512); if (urb == NULL) return -ENOMEM; diff --git a/drivers/usb/otg/gpio_vbus.c b/drivers/usb/otg/gpio_vbus.c index a0a2178974f..fe208643a74 100644 --- a/drivers/usb/otg/gpio_vbus.c +++ b/drivers/usb/otg/gpio_vbus.c @@ -37,7 +37,7 @@ struct gpio_vbus_data { struct regulator *vbus_draw; int vbus_draw_enabled; unsigned mA; - struct work_struct work; + struct delayed_work work; }; @@ -94,7 +94,7 @@ static int is_vbus_powered(struct gpio_vbus_mach_info *pdata) static void gpio_vbus_work(struct work_struct *work) { struct gpio_vbus_data *gpio_vbus = - container_of(work, struct gpio_vbus_data, work); + container_of(work, struct gpio_vbus_data, work.work); struct gpio_vbus_mach_info *pdata = gpio_vbus->dev->platform_data; int gpio, status; @@ -152,7 +152,7 @@ static irqreturn_t gpio_vbus_irq(int irq, void *data) otg->gadget ? otg->gadget->name : "none"); if (otg->gadget) - schedule_work(&gpio_vbus->work); + schedule_delayed_work(&gpio_vbus->work, msecs_to_jiffies(100)); return IRQ_HANDLED; } @@ -300,7 +300,7 @@ static int __init gpio_vbus_probe(struct platform_device *pdev) ATOMIC_INIT_NOTIFIER_HEAD(&gpio_vbus->phy.notifier); - INIT_WORK(&gpio_vbus->work, gpio_vbus_work); + INIT_DELAYED_WORK(&gpio_vbus->work, gpio_vbus_work); gpio_vbus->vbus_draw = regulator_get(&pdev->dev, "vbus_draw"); if (IS_ERR(gpio_vbus->vbus_draw)) { diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c index 54603bb5932..b0b5f5cc7ae 100755 --- a/drivers/usb/otg/msm_otg.c +++ b/drivers/usb/otg/msm_otg.c @@ -55,6 +55,11 @@ #include #include +#ifdef CONFIG_FORCE_FAST_CHARGE +#include +#define USB_FASTCHG_LOAD 1000 /* uA */ +#endif + #define MSM_USB_BASE (motg->regs) #define DRIVER_NAME "msm_otg" @@ -93,6 +98,10 @@ static struct workqueue_struct *msm_otg_id_pin_wq; static int global_vbus_suspend_status; static int global_id_pin_suspend_status; +//otg+charge: sysfs entry +static bool usbhost_charge_mode = false; +module_param(usbhost_charge_mode, bool, 0755); + /* APQ8064 GPIO pin definition */ #define APQ_AP_ACOK 23 #define APQ_OTG_ID_PIN 77 @@ -158,6 +167,9 @@ static void asus_chg_set_chg_mode(enum usb_chg_type chg_src) printk(KERN_INFO "The USB cable status = CHARGER_CDP\n"); break; case USB_ACA_A_CHARGER: + usb_cable_type_detect(CHARGER_ACA); + printk(KERN_INFO "The USB cable status = CHARGER_ACA\n"); + break; case USB_ACA_B_CHARGER: case USB_ACA_C_CHARGER: case USB_ACA_DOCK_CHARGER: @@ -1130,8 +1142,9 @@ static int msm_otg_notify_host_mode(struct msm_otg *motg, bool host_mode) if (!psy) goto psy_not_supported; - - if (host_mode) { + //otg+charge: need to set POWER_SUPPLY_SCOPE_DEVICE or else it doesn't + //detect vbus + if (host_mode && !usbhost_charge_mode) { ret = power_supply_set_scope(psy, POWER_SUPPLY_SCOPE_SYSTEM); } else { ret = power_supply_set_scope(psy, POWER_SUPPLY_SCOPE_DEVICE); @@ -1228,7 +1241,14 @@ static void msm_otg_notify_charger(struct msm_otg *motg, unsigned mA) if (motg->cur_power == mA) return; - +#ifdef CONFIG_FORCE_FAST_CHARGE + if (force_fast_charge == 1) { + mA = USB_FASTCHG_LOAD; + pr_info("USB fast charging is ON - 1000mA.\n"); + } else { + pr_info("USB fast charging is OFF.\n"); + } +#endif dev_info(motg->phy.dev, "Avail curr from USB = %u\n", mA); pm8921_charger_vbus_draw(mA); @@ -1267,7 +1287,12 @@ static void msm_otg_start_host(struct usb_otg *otg, int on) if (on) { dev_dbg(otg->phy->dev, "host on\n"); - smb345_otg_status(true); + + //otg+charge: don't use battery to power perhipherals in host mode + if (usbhost_charge_mode) + smb345_otg_status(false); + else + smb345_otg_status(true); otg_host_on = 1; // Reset to apply new parameter for host. @@ -1383,6 +1408,13 @@ static void msm_hsusb_vbus_power(struct msm_otg *motg, bool on) int ret; static bool vbus_is_on; + //otg+charge: just to be safe, turn off battery power to otg perhipheral + if (usbhost_charge_mode) { + printk("[usbhost_charge_mode]: Do not supply power in host mode\n"); + msm_otg_notify_host_mode(motg, on); + return; + } + if (vbus_is_on == on) return; @@ -2244,11 +2276,17 @@ static void msm_chg_detect_work(struct work_struct *w) break; } - if (line_state) /* DP > VLGC or/and DM > VLGC */ - motg->chg_type = USB_PROPRIETARY_CHARGER; - else + if (line_state) { /* DP > VLGC or/and DM > VLGC */ + //otg+charge + if (usbhost_charge_mode) { + motg->chg_type = USB_ACA_A_CHARGER; + } else { + motg->chg_type = USB_PROPRIETARY_CHARGER; + } + } else { motg->chg_type = USB_SDP_CHARGER; - + } + motg->chg_state = USB_CHG_STATE_DETECTED; delay = 0; } @@ -2400,6 +2438,7 @@ static void msm_otg_sm_work(struct work_struct *w) work = 1; break; } + clear_bit(B_BUS_REQ, &motg->inputs); set_bit(A_BUS_REQ, &motg->inputs); otg->phy->state = OTG_STATE_A_IDLE; @@ -2672,6 +2711,7 @@ static void msm_otg_sm_work(struct work_struct *w) msm_otg_notify_charger(motg, 0); else msm_hsusb_vbus_power(motg, 1); + msm_otg_start_timer(motg, TA_WAIT_VRISE, A_WAIT_VRISE); } else { pr_debug("No session requested\n"); @@ -2753,6 +2793,16 @@ static void msm_otg_sm_work(struct work_struct *w) } else if (test_bit(ID_A, &motg->inputs)) { msm_hsusb_vbus_power(motg, 0); } else if (!test_bit(A_BUS_REQ, &motg->inputs)) { + //otg+charge: if there is current, start charging + if (usbhost_charge_mode) { + if (test_bit(B_SESS_VLD, &motg->inputs)) { + pr_debug("b_sess_vld\n"); + usleep_range(10000, 12000); + if (motg->chg_state == USB_CHG_STATE_UNDEFINED) + msm_chg_detect_work(&motg->chg_work.work); + } + } + /* * If TA_WAIT_BCON is infinite, we don;t * turn off VBUS. Enter low power mode. @@ -3108,15 +3158,29 @@ static void msm_otg_set_vbus_state(int online) struct usb_otg *otg = motg->phy.otg; /* In A Host Mode, ignore received BSV interrupts */ - if (otg->phy->state >= OTG_STATE_A_IDLE) + //otg+charge: ignore unless usbhost_charge_mode, then we want to sense vbus + if (!usbhost_charge_mode && otg->phy->state >= OTG_STATE_A_IDLE) return; if (online) { pr_debug("PMIC: BSV set\n"); + //printk("connected charger\n"); set_bit(B_SESS_VLD, &motg->inputs); } else { pr_debug("PMIC: BSV clear\n"); + //printk("disconnected charger\n"); clear_bit(B_SESS_VLD, &motg->inputs); + + //otg+charge: cancel charging when power is disconnected + if (otg->phy->state >= OTG_STATE_A_IDLE && usbhost_charge_mode) { + printk("[usbhost_charge_mode]: chg_work cancel from set vbus state"); + cancel_delayed_work_sync(&motg->chg_work); + motg->chg_state = USB_CHG_STATE_UNDEFINED; + motg->chg_type = USB_INVALID_CHARGER; + asus_chg_set_chg_mode(USB_INVALID_CHARGER); + msm_otg_notify_charger(motg, 0); + msm_otg_reset(otg->phy); + } } if (!init) { @@ -3162,6 +3226,9 @@ static void id_pin_irq_work_function(struct work_struct *work) else { pr_debug("%s: gpio_get_value(APQ_OTG_ID_PIN) = %d\n", __func__, gpio_get_value(APQ_OTG_ID_PIN)); if (gpio == 0 && otg_host_on == 0) { + //otg+charge: this needs a slight delay or else it doesn't start charging + if (usbhost_charge_mode) + msleep(20); pr_info("%s: APQ_OTG_ID_PIN is low : Host mode\n", __func__); set_bit(A_BUS_REQ, &motg->inputs); clear_bit(ID, &motg->inputs); @@ -4347,3 +4414,5 @@ module_exit(msm_otg_exit); MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("MSM USB transceiver driver"); + + diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 02e7f2d32d5..95bba992416 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -809,6 +809,7 @@ static struct usb_device_id id_table_combined [] = { .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { USB_DEVICE(LARSENBRUSGAARD_VID, LB_ALTITRACK_PID) }, { USB_DEVICE(GN_OTOMETRICS_VID, AURICAL_USB_PID) }, + { USB_DEVICE(PI_VID, PI_E861_PID) }, { USB_DEVICE(BAYER_VID, BAYER_CONTOUR_CABLE_PID) }, { USB_DEVICE(FTDI_VID, MARVELL_OPENRD_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 0838baf892f..f3c7c78ede3 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -785,6 +785,14 @@ #define RTSYSTEMS_SERIAL_VX7_PID 0x9e52 /* Serial converter for VX-7 Radios using FT232RL */ #define RTSYSTEMS_CT29B_PID 0x9e54 /* CT29B Radio Cable */ + +/* + * Physik Instrumente + * http://www.physikinstrumente.com/en/products/ + */ +#define PI_VID 0x1a72 /* Vendor ID */ +#define PI_E861_PID 0x1008 /* E-861 piezo controller USB connection */ + /* * Bayer Ascensia Contour blood glucose meter USB-converter cable. * http://winglucofacts.com/cables/ diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index ab74123d658..3377437550d 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -165,7 +165,7 @@ static unsigned int product_5052_count; /* the array dimension is the number of default entries plus */ /* TI_EXTRA_VID_PID_COUNT user defined entries plus 1 terminating */ /* null entry */ -static struct usb_device_id ti_id_table_3410[14+TI_EXTRA_VID_PID_COUNT+1] = { +static struct usb_device_id ti_id_table_3410[15+TI_EXTRA_VID_PID_COUNT+1] = { { USB_DEVICE(TI_VENDOR_ID, TI_3410_PRODUCT_ID) }, { USB_DEVICE(TI_VENDOR_ID, TI_3410_EZ430_ID) }, { USB_DEVICE(MTS_VENDOR_ID, MTS_GSM_NO_FW_PRODUCT_ID) }, @@ -180,6 +180,7 @@ static struct usb_device_id ti_id_table_3410[14+TI_EXTRA_VID_PID_COUNT+1] = { { USB_DEVICE(IBM_VENDOR_ID, IBM_454B_PRODUCT_ID) }, { USB_DEVICE(IBM_VENDOR_ID, IBM_454C_PRODUCT_ID) }, { USB_DEVICE(ABBOTT_VENDOR_ID, ABBOTT_PRODUCT_ID) }, + { USB_DEVICE(TI_VENDOR_ID, FRI2_PRODUCT_ID) }, }; static struct usb_device_id ti_id_table_5052[5+TI_EXTRA_VID_PID_COUNT+1] = { @@ -189,7 +190,7 @@ static struct usb_device_id ti_id_table_5052[5+TI_EXTRA_VID_PID_COUNT+1] = { { USB_DEVICE(TI_VENDOR_ID, TI_5052_FIRMWARE_PRODUCT_ID) }, }; -static struct usb_device_id ti_id_table_combined[18+2*TI_EXTRA_VID_PID_COUNT+1] = { +static struct usb_device_id ti_id_table_combined[19+2*TI_EXTRA_VID_PID_COUNT+1] = { { USB_DEVICE(TI_VENDOR_ID, TI_3410_PRODUCT_ID) }, { USB_DEVICE(TI_VENDOR_ID, TI_3410_EZ430_ID) }, { USB_DEVICE(MTS_VENDOR_ID, MTS_GSM_NO_FW_PRODUCT_ID) }, @@ -208,6 +209,7 @@ static struct usb_device_id ti_id_table_combined[18+2*TI_EXTRA_VID_PID_COUNT+1] { USB_DEVICE(IBM_VENDOR_ID, IBM_454B_PRODUCT_ID) }, { USB_DEVICE(IBM_VENDOR_ID, IBM_454C_PRODUCT_ID) }, { USB_DEVICE(ABBOTT_VENDOR_ID, ABBOTT_PRODUCT_ID) }, + { USB_DEVICE(TI_VENDOR_ID, FRI2_PRODUCT_ID) }, { } }; diff --git a/drivers/usb/serial/ti_usb_3410_5052.h b/drivers/usb/serial/ti_usb_3410_5052.h index f140f1b9d5c..b353e7e3d48 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.h +++ b/drivers/usb/serial/ti_usb_3410_5052.h @@ -37,6 +37,7 @@ #define TI_5152_BOOT_PRODUCT_ID 0x5152 /* no EEPROM, no firmware */ #define TI_5052_EEPROM_PRODUCT_ID 0x505A /* EEPROM, no firmware */ #define TI_5052_FIRMWARE_PRODUCT_ID 0x505F /* firmware is running */ +#define FRI2_PRODUCT_ID 0x5053 /* Fish River Island II */ /* Multi-Tech vendor and product ids */ #define MTS_VENDOR_ID 0x06E0 diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 97355a15bbe..6933355c964 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -1338,7 +1338,6 @@ static int usb_serial_register(struct usb_serial_driver *driver) driver->description); return -EINVAL; } - driver->usb_driver->supports_autosuspend = 1; /* Add this device to our list of devices */ mutex_lock(&table_lock); @@ -1373,7 +1372,7 @@ static void usb_serial_deregister(struct usb_serial_driver *device) * @serial_drivers: NULL-terminated array of pointers to drivers to be registered * * Registers @udriver and all the drivers in the @serial_drivers array. - * Automatically fills in the .no_dynamic_id field in @udriver and + * Automatically fills in the .no_dynamic_id and PM fields in @udriver and * the .usb_driver field in each serial driver. */ int usb_serial_register_drivers(struct usb_driver *udriver, @@ -1392,11 +1391,17 @@ int usb_serial_register_drivers(struct usb_driver *udriver, * the serial drivers are registered, because the probe would * simply fail for lack of a matching serial driver. * Therefore save off udriver's id_table until we are all set. + * + * Suspend/resume support is implemented in the usb-serial core, + * so fill in the PM-related fields in udriver. */ saved_id_table = udriver->id_table; udriver->id_table = NULL; udriver->no_dynamic_id = 1; + udriver->supports_autosuspend = 1; + udriver->suspend = usb_serial_suspend; + udriver->resume = usb_serial_resume; rc = usb_register(udriver); if (rc) return rc; diff --git a/drivers/usb/serial/usb-wwan.h b/drivers/usb/serial/usb-wwan.h index 98b399fe3d4..84336d61d82 100644 --- a/drivers/usb/serial/usb-wwan.h +++ b/drivers/usb/serial/usb-wwan.h @@ -33,10 +33,10 @@ extern int usb_wwan_resume(struct usb_serial *serial); /* per port private data */ -#define N_IN_URB 5 -#define N_OUT_URB 5 -#define IN_BUFLEN 16384 -#define OUT_BUFLEN 65536 +#define N_IN_URB 4 +#define N_OUT_URB 4 +#define IN_BUFLEN 4096 +#define OUT_BUFLEN 4096 struct usb_wwan_intf_private { spinlock_t susp_lock; diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c index c70109e5d60..32a21c09d11 100644 --- a/drivers/usb/storage/transport.c +++ b/drivers/usb/storage/transport.c @@ -467,7 +467,7 @@ static int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe, int usb_stor_bulk_srb(struct us_data* us, unsigned int pipe, struct scsi_cmnd* srb) { - unsigned int partial; + unsigned int partial = 0; int result = usb_stor_bulk_transfer_sglist(us, pipe, scsi_sglist(srb), scsi_sg_count(srb), scsi_bufflen(srb), &partial); @@ -490,7 +490,7 @@ int usb_stor_bulk_transfer_sg(struct us_data* us, unsigned int pipe, void *buf, unsigned int length_left, int use_sg, int *residual) { int result; - unsigned int partial; + unsigned int partial = 0; /* are we scatter-gathering? */ if (use_sg) { diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 856ad92c40d..8f3cbb8dc81 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1885,6 +1885,13 @@ UNUSUAL_DEV( 0x1652, 0x6600, 0x0201, 0x0201, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE ), +/* Reported by Jesse Feddema */ +UNUSUAL_DEV( 0x177f, 0x0400, 0x0000, 0x0000, + "Yarvik", + "PMP400", + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_BULK_IGNORE_TAG | US_FL_MAX_SECTORS_64 ), + /* Reported by Hans de Goede * These Appotech controllers are found in Picture Frames, they provide a * (buggy) emulation of a cdrom drive which contains the windows software diff --git a/drivers/video/msm/mipi_novatek.c b/drivers/video/msm/mipi_novatek.c index 09630531767..e5f343a6db4 100644 --- a/drivers/video/msm/mipi_novatek.c +++ b/drivers/video/msm/mipi_novatek.c @@ -680,7 +680,7 @@ static ssize_t mipi_dsi_3d_barrier_read(struct device *dev, struct device_attribute *attr, char *buf) { - return snprintf((char *)buf, sizeof(buf), "%u\n", barrier_mode); + return snprintf((char *)buf, sizeof(*buf), "%u\n", barrier_mode); } static ssize_t mipi_dsi_3d_barrier_write(struct device *dev, diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c index 7a0b301587f..e672698bd82 100644 --- a/drivers/video/sh_mobile_lcdcfb.c +++ b/drivers/video/sh_mobile_lcdcfb.c @@ -758,7 +758,7 @@ static void __sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) } lcdc_write_chan(ch, LDDFR, tmp); - lcdc_write_chan(ch, LDMLSR, ch->pitch); + lcdc_write_chan(ch, LDMLSR, ch->line_size); lcdc_write_chan(ch, LDSA1R, ch->base_addr_y); if (ch->format->yuv) lcdc_write_chan(ch, LDSA2R, ch->base_addr_c); @@ -847,6 +847,7 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) ch->base_addr_y = ch->dma_handle; ch->base_addr_c = ch->base_addr_y + ch->xres * ch->yres_virtual; + ch->line_size = ch->pitch; /* Enable MERAM if possible. */ if (mdev == NULL || mdev->ops == NULL || @@ -882,7 +883,7 @@ static int sh_mobile_lcdc_start(struct sh_mobile_lcdc_priv *priv) meram = mdev->ops->meram_register(mdev, ch->cfg->meram_cfg, ch->pitch, ch->yres, pixelformat, - &ch->pitch); + &ch->line_size); if (!IS_ERR(meram)) { mdev->ops->meram_update(mdev, meram, ch->base_addr_y, ch->base_addr_c, diff --git a/drivers/video/sh_mobile_lcdcfb.h b/drivers/video/sh_mobile_lcdcfb.h index da1c26e78a5..5c3bddd2cb7 100644 --- a/drivers/video/sh_mobile_lcdcfb.h +++ b/drivers/video/sh_mobile_lcdcfb.h @@ -84,6 +84,7 @@ struct sh_mobile_lcdc_chan { unsigned long base_addr_y; unsigned long base_addr_c; + unsigned int line_size; int (*notify)(struct sh_mobile_lcdc_chan *ch, enum sh_mobile_lcdc_entity_event event, diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 0a8a17cd80b..6908e4ce2a0 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c @@ -611,7 +611,7 @@ static void disable_pirq(struct irq_data *data) disable_dynirq(data); } -static int find_irq_by_gsi(unsigned gsi) +int xen_irq_from_gsi(unsigned gsi) { struct irq_info *info; @@ -625,6 +625,7 @@ static int find_irq_by_gsi(unsigned gsi) return -1; } +EXPORT_SYMBOL_GPL(xen_irq_from_gsi); /* * Do not make any assumptions regarding the relationship between the @@ -644,7 +645,7 @@ int xen_bind_pirq_gsi_to_irq(unsigned gsi, mutex_lock(&irq_mapping_update_lock); - irq = find_irq_by_gsi(gsi); + irq = xen_irq_from_gsi(gsi); if (irq != -1) { printk(KERN_INFO "xen_map_pirq_gsi: returning irq %d for gsi %u\n", irq, gsi); diff --git a/frandom/Makefile b/frandom/Makefile new file mode 100644 index 00000000000..87224029ced --- /dev/null +++ b/frandom/Makefile @@ -0,0 +1,2 @@ +obj-m := frandom.o +PWD := $(shell pwd) diff --git a/frandom/frandom.c b/frandom/frandom.c new file mode 100644 index 00000000000..b824f66bfb1 --- /dev/null +++ b/frandom/frandom.c @@ -0,0 +1,420 @@ +/* +** frandom.c +** Fast pseudo-random generator +** +** (c) Copyright 2003-2011 Eli Billauer +** http://www.billauer.co.il +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** +*/ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define INTERNAL_SEED 0 +#define EXTERNAL_SEED 1 + +#define FRANDOM_MAJOR 235 +#define FRANDOM_MINOR 11 +#define ERANDOM_MINOR 12 + +static struct file_operations frandom_fops; /* Values assigned below */ + +static int erandom_seeded = 0; /* Internal flag */ + +static int frandom_major = FRANDOM_MAJOR; +static int frandom_minor = FRANDOM_MINOR; +static int erandom_minor = ERANDOM_MINOR; +static int frandom_bufsize = 256; +static int frandom_chunklimit = 0; /* =0 means unlimited */ + +static struct cdev frandom_cdev; +static struct cdev erandom_cdev; +static struct class *frandom_class; +struct device *frandom_device; +struct device *erandom_device; + +MODULE_DESCRIPTION("Fast pseudo-random number generator"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Eli Billauer"); +module_param(frandom_major, int, 0); +module_param(frandom_minor, int, 0); +module_param(erandom_minor, int, 0); +module_param(frandom_bufsize, int, 0); +module_param(frandom_chunklimit, int, 0); + +MODULE_PARM_DESC(frandom_major,"Major number of /dev/frandom and /dev/erandom"); +MODULE_PARM_DESC(frandom_minor,"Minor number of /dev/frandom"); +MODULE_PARM_DESC(erandom_minor,"Minor number of /dev/erandom"); +MODULE_PARM_DESC(frandom_bufsize,"Internal buffer size in bytes. Default is 256. Must be >= 256"); +MODULE_PARM_DESC(frandom_chunklimit,"Limit for read() blocks size. 0 (default) is unlimited, otherwise must be >= 256"); + +struct frandom_state +{ + struct semaphore sem; /* Semaphore on the state structure */ + + u8 S[256]; /* The state array */ + u8 i; + u8 j; + + char *buf; +}; + +static struct frandom_state *erandom_state; + +static inline void swap_byte(u8 *a, u8 *b) +{ + u8 swapByte; + + swapByte = *a; + *a = *b; + *b = swapByte; +} + +static void init_rand_state(struct frandom_state *state, int seedflag); + +void erandom_get_random_bytes(char *buf, size_t count) +{ + struct frandom_state *state = erandom_state; + int k; + + unsigned int i; + unsigned int j; + u8 *S; + + /* If we fail to get the semaphore, we revert to external random data. + Since semaphore blocking is expected to be very rare, and interrupts + during these rare and very short periods of time even less frequent, + we take the better-safe-than-sorry approach, and fill the buffer + some expensive random data, in case the caller wasn't aware of this + possibility, and expects random data anyhow. + */ + + if (down_interruptible(&state->sem)) { + get_random_bytes(buf, count); + return; + } + + /* We seed erandom as late as possible, hoping that the kernel's main + RNG is already restored in the boot sequence (not critical, but + better. + */ + + if (!erandom_seeded) { + erandom_seeded = 1; + init_rand_state(state, EXTERNAL_SEED); + printk(KERN_INFO "frandom: Seeded global generator now (used by erandom)\n"); + } + + i = state->i; + j = state->j; + S = state->S; + + for (k=0; ki = i; + state->j = j; + + up(&state->sem); +} + +static void init_rand_state(struct frandom_state *state, int seedflag) +{ + unsigned int i, j, k; + u8 *S; + u8 *seed = state->buf; + + if (seedflag == INTERNAL_SEED) + erandom_get_random_bytes(seed, 256); + else + get_random_bytes(seed, 256); + + S = state->S; + for (i=0; i<256; i++) + *S++=i; + + j=0; + S = state->S; + + for (i=0; i<256; i++) { + j = (j + S[i] + *seed++) & 0xff; + swap_byte(&S[i], &S[j]); + } + + /* It's considered good practice to discard the first 256 bytes + generated. So we do it: + */ + + i=0; j=0; + for (k=0; k<256; k++) { + i = (i + 1) & 0xff; + j = (j + S[i]) & 0xff; + swap_byte(&S[i], &S[j]); + } + + state->i = i; /* Save state */ + state->j = j; +} + +static int frandom_open(struct inode *inode, struct file *filp) +{ + + struct frandom_state *state; + + int num = iminor(inode); + + /* This should never happen, now when the minors are regsitered + * explicitly + */ + if ((num != frandom_minor) && (num != erandom_minor)) return -ENODEV; + + state = kmalloc(sizeof(struct frandom_state), GFP_KERNEL); + if (!state) + return -ENOMEM; + + state->buf = kmalloc(frandom_bufsize, GFP_KERNEL); + if (!state->buf) { + kfree(state); + return -ENOMEM; + } + + sema_init(&state->sem, 1); /* Init semaphore as a mutex */ + + if (num == frandom_minor) + init_rand_state(state, EXTERNAL_SEED); + else + init_rand_state(state, INTERNAL_SEED); + + filp->private_data = state; + + return 0; /* Success */ +} + +static int frandom_release(struct inode *inode, struct file *filp) +{ + + struct frandom_state *state = filp->private_data; + + kfree(state->buf); + kfree(state); + + return 0; +} + +static ssize_t frandom_read(struct file *filp, char *buf, size_t count, + loff_t *f_pos) +{ + struct frandom_state *state = filp->private_data; + ssize_t ret; + int dobytes, k; + char *localbuf; + + unsigned int i; + unsigned int j; + u8 *S; + + if (down_interruptible(&state->sem)) + return -ERESTARTSYS; + + if ((frandom_chunklimit > 0) && (count > frandom_chunklimit)) + count = frandom_chunklimit; + + ret = count; /* It's either everything or an error... */ + + i = state->i; + j = state->j; + S = state->S; + + while (count) { + if (count > frandom_bufsize) + dobytes = frandom_bufsize; + else + dobytes = count; + + localbuf = state->buf; + + for (k=0; kbuf, dobytes)) { + ret = -EFAULT; + goto out; + } + + buf += dobytes; + count -= dobytes; + } + + out: + state->i = i; + state->j = j; + + up(&state->sem); + return ret; +} + +static struct file_operations frandom_fops = { + read: frandom_read, + open: frandom_open, + release: frandom_release, +}; + +static void frandom_cleanup_module(void) { + unregister_chrdev_region(MKDEV(frandom_major, erandom_minor), 1); + cdev_del(&erandom_cdev); + device_destroy(frandom_class, MKDEV(frandom_major, erandom_minor)); + + unregister_chrdev_region(MKDEV(frandom_major, frandom_minor), 1); + cdev_del(&frandom_cdev); + device_destroy(frandom_class, MKDEV(frandom_major, frandom_minor)); + class_destroy(frandom_class); + + kfree(erandom_state->buf); + kfree(erandom_state); +} + + +static int frandom_init_module(void) +{ + int result; + + /* The buffer size MUST be at least 256 bytes, because we assume that + minimal length in init_rand_state(). + */ + if (frandom_bufsize < 256) { + printk(KERN_ERR "frandom: Refused to load because frandom_bufsize=%d < 256\n",frandom_bufsize); + return -EINVAL; + } + if ((frandom_chunklimit != 0) && (frandom_chunklimit < 256)) { + printk(KERN_ERR "frandom: Refused to load because frandom_chunklimit=%d < 256 and != 0\n",frandom_chunklimit); + return -EINVAL; + } + + erandom_state = kmalloc(sizeof(struct frandom_state), GFP_KERNEL); + if (!erandom_state) + return -ENOMEM; + + /* This specific buffer is only used for seeding, so we need + 256 bytes exactly */ + erandom_state->buf = kmalloc(256, GFP_KERNEL); + if (!erandom_state->buf) { + kfree(erandom_state); + return -ENOMEM; + } + + sema_init(&erandom_state->sem, 1); /* Init semaphore as a mutex */ + + erandom_seeded = 0; + + frandom_class = class_create(THIS_MODULE, "fastrng"); + if (IS_ERR(frandom_class)) { + result = PTR_ERR(frandom_class); + printk(KERN_WARNING "frandom: Failed to register class fastrng\n"); + goto error0; + } + + /* + * Register your major, and accept a dynamic number. This is the + * first thing to do, in order to avoid releasing other module's + * fops in frandom_cleanup_module() + */ + + cdev_init(&frandom_cdev, &frandom_fops); + frandom_cdev.owner = THIS_MODULE; + result = cdev_add(&frandom_cdev, MKDEV(frandom_major, frandom_minor), 1); + if (result) { + printk(KERN_WARNING "frandom: Failed to add cdev for /dev/frandom\n"); + goto error1; + } + + result = register_chrdev_region(MKDEV(frandom_major, frandom_minor), 1, "/dev/frandom"); + if (result < 0) { + printk(KERN_WARNING "frandom: can't get major/minor %d/%d\n", frandom_major, frandom_minor); + goto error2; + } + + frandom_device = device_create(frandom_class, NULL, MKDEV(frandom_major, frandom_minor), NULL, "frandom"); + + if (IS_ERR(frandom_device)) { + printk(KERN_WARNING "frandom: Failed to create frandom device\n"); + goto error3; + } + + cdev_init(&erandom_cdev, &frandom_fops); + erandom_cdev.owner = THIS_MODULE; + result = cdev_add(&erandom_cdev, MKDEV(frandom_major, erandom_minor), 1); + if (result) { + printk(KERN_WARNING "frandom: Failed to add cdev for /dev/erandom\n"); + goto error4; + } + + result = register_chrdev_region(MKDEV(frandom_major, erandom_minor), 1, "/dev/erandom"); + if (result < 0) { + printk(KERN_WARNING "frandom: can't get major/minor %d/%d\n", frandom_major, erandom_minor); + goto error5; + } + + erandom_device = device_create(frandom_class, NULL, MKDEV(frandom_major, erandom_minor), NULL, "erandom"); + + if (IS_ERR(erandom_device)) { + printk(KERN_WARNING "frandom: Failed to create erandom device\n"); + goto error6; + } + return 0; /* succeed */ + + error6: + unregister_chrdev_region(MKDEV(frandom_major, erandom_minor), 1); + error5: + cdev_del(&erandom_cdev); + error4: + device_destroy(frandom_class, MKDEV(frandom_major, frandom_minor)); + error3: + unregister_chrdev_region(MKDEV(frandom_major, frandom_minor), 1); + error2: + cdev_del(&frandom_cdev); + error1: + class_destroy(frandom_class); + error0: + kfree(erandom_state->buf); + kfree(erandom_state); + + return result; +} + +module_init(frandom_init_module); +module_exit(frandom_cleanup_module); + +EXPORT_SYMBOL(erandom_get_random_bytes); + +MODULE_AUTHOR("Eli Billauer "); +MODULE_DESCRIPTION("'char_random_frandom' - A fast random generator for " +"general usage"); +MODULE_LICENSE("GPL"); diff --git a/fs/Kconfig b/fs/Kconfig index 1dd49481854..be949d479d7 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -103,6 +103,7 @@ menu "DOS/FAT/NT Filesystems" source "fs/fat/Kconfig" source "fs/ntfs/Kconfig" +source "fs/exfat/Kconfig" endmenu endif # BLOCK @@ -280,4 +281,35 @@ endif # NETWORK_FILESYSTEMS source "fs/nls/Kconfig" source "fs/dlm/Kconfig" +config DYNAMIC_FSYNC + bool "dynamic file sync control" + default n + help + An experimental file sync control using Android's early suspend / late resume drivers + +config RESTRICT_ROOTFS_SLAVE + bool "Android: Restrict rootfs slave mountspace to /storage" + help + Restrict slave mountspace so Dalvik apps can mount system-wide volumes + + Android 4.2 implements multi-user storage using per-process mount + namespaces. Everything under "/" (the entire filesystem hierarchy) is + marked as a recursive-slave mountspace for all zygote instances. This is + done so that user-storage sandbox mounts under /storage/emulated are hidden + from other apps and users. Unfortunately this means that any Dalvik app + (actually, any program whose clone/fork ancestry includes a Dalvik zygote, + which is everything except services spawned directly from init) cannot + mount system-wide volumes. + + This option restricts rootfs-slave calls to /storage (and + /mnt/shell/emulated) so that Dalvik apps can mount system-wide volumes + elsewhere (with appropriate permission, as in earlier versions of Android), + while retaining full multi-user storage compatibility. It is made + available as a kernel-based workaround for instances where libdvm can not + be modified. + + This option requires that a tmpfs volume is mounted as /storage in + Android init.rc. If this volume is unavailable, then we fall back to the + previous behavior of marking the entire filesystem hierarchy as slave. + endmenu diff --git a/fs/Makefile b/fs/Makefile index 95cf9de6ae0..2be95180636 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -94,6 +94,7 @@ obj-$(CONFIG_CIFS) += cifs/ obj-$(CONFIG_NCP_FS) += ncpfs/ obj-$(CONFIG_HPFS_FS) += hpfs/ obj-$(CONFIG_NTFS_FS) += ntfs/ +obj-$(CONFIG_EXFAT_FS) += exfat/ obj-$(CONFIG_UFS_FS) += ufs/ obj-$(CONFIG_EFS_FS) += efs/ obj-$(CONFIG_JFFS2_FS) += jffs2/ @@ -128,3 +129,5 @@ obj-$(CONFIG_PSTORE) += pstore/ # Patched by YAFFS obj-$(CONFIG_YAFFS_FS) += yaffs2/ + +obj-$(CONFIG_DYNAMIC_FSYNC) += dyn_sync_cntrl.o diff --git a/fs/aio.c b/fs/aio.c index 67a6db3e1b6..c4ee8a72e7b 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -1456,6 +1456,10 @@ static ssize_t aio_setup_vectored_rw(int type, struct kiocb *kiocb, bool compat) if (ret < 0) goto out; + ret = rw_verify_area(type, kiocb->ki_filp, &kiocb->ki_pos, ret); + if (ret < 0) + goto out; + kiocb->ki_nr_segs = kiocb->ki_nbytes; kiocb->ki_cur_seg = 0; /* ki_nbytes/left now reflect bytes instead of segs */ @@ -1467,11 +1471,17 @@ static ssize_t aio_setup_vectored_rw(int type, struct kiocb *kiocb, bool compat) return ret; } -static ssize_t aio_setup_single_vector(struct kiocb *kiocb) +static ssize_t aio_setup_single_vector(int type, struct file * file, struct kiocb *kiocb) { + int bytes; + + bytes = rw_verify_area(type, file, &kiocb->ki_pos, kiocb->ki_left); + if (bytes < 0) + return bytes; + kiocb->ki_iovec = &kiocb->ki_inline_vec; kiocb->ki_iovec->iov_base = kiocb->ki_buf; - kiocb->ki_iovec->iov_len = kiocb->ki_left; + kiocb->ki_iovec->iov_len = bytes; kiocb->ki_nr_segs = 1; kiocb->ki_cur_seg = 0; return 0; @@ -1496,10 +1506,7 @@ static ssize_t aio_setup_iocb(struct kiocb *kiocb, bool compat) if (unlikely(!access_ok(VERIFY_WRITE, kiocb->ki_buf, kiocb->ki_left))) break; - ret = security_file_permission(file, MAY_READ); - if (unlikely(ret)) - break; - ret = aio_setup_single_vector(kiocb); + ret = aio_setup_single_vector(READ, file, kiocb); if (ret) break; ret = -EINVAL; @@ -1514,10 +1521,7 @@ static ssize_t aio_setup_iocb(struct kiocb *kiocb, bool compat) if (unlikely(!access_ok(VERIFY_READ, kiocb->ki_buf, kiocb->ki_left))) break; - ret = security_file_permission(file, MAY_WRITE); - if (unlikely(ret)) - break; - ret = aio_setup_single_vector(kiocb); + ret = aio_setup_single_vector(WRITE, file, kiocb); if (ret) break; ret = -EINVAL; @@ -1528,9 +1532,6 @@ static ssize_t aio_setup_iocb(struct kiocb *kiocb, bool compat) ret = -EBADF; if (unlikely(!(file->f_mode & FMODE_READ))) break; - ret = security_file_permission(file, MAY_READ); - if (unlikely(ret)) - break; ret = aio_setup_vectored_rw(READ, kiocb, compat); if (ret) break; @@ -1542,9 +1543,6 @@ static ssize_t aio_setup_iocb(struct kiocb *kiocb, bool compat) ret = -EBADF; if (unlikely(!(file->f_mode & FMODE_WRITE))) break; - ret = security_file_permission(file, MAY_WRITE); - if (unlikely(ret)) - break; ret = aio_setup_vectored_rw(WRITE, kiocb, compat); if (ret) break; @@ -1682,7 +1680,6 @@ long do_io_submit(aio_context_t ctx_id, long nr, struct kioctx *ctx; long ret = 0; int i = 0; - struct blk_plug plug; struct kiocb_batch batch; if (unlikely(nr < 0)) @@ -1702,8 +1699,6 @@ long do_io_submit(aio_context_t ctx_id, long nr, kiocb_batch_init(&batch, nr); - blk_start_plug(&plug); - /* * AKPM: should this return a partial result if some of the IOs were * successfully submitted? @@ -1726,7 +1721,6 @@ long do_io_submit(aio_context_t ctx_id, long nr, if (ret) break; } - blk_finish_plug(&plug); kiocb_batch_free(ctx, &batch); put_ioctx(ctx); diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index a7ffc88a7db..94705d5109f 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -3210,8 +3210,8 @@ void btrfs_btree_balance_dirty(struct btrfs_root *root, unsigned long nr) num_dirty = root->fs_info->dirty_metadata_bytes; if (num_dirty > thresh) { - balance_dirty_pages_ratelimited_nr( - root->fs_info->btree_inode->i_mapping, 1); + balance_dirty_pages_ratelimited( + root->fs_info->btree_inode->i_mapping); } return; } @@ -3231,8 +3231,8 @@ void __btrfs_btree_balance_dirty(struct btrfs_root *root, unsigned long nr) num_dirty = root->fs_info->dirty_metadata_bytes; if (num_dirty > thresh) { - balance_dirty_pages_ratelimited_nr( - root->fs_info->btree_inode->i_mapping, 1); + balance_dirty_pages_ratelimited( + root->fs_info->btree_inode->i_mapping); } return; } diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 53bf2d764bb..721f4f35e62 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -1285,8 +1285,7 @@ static noinline ssize_t __btrfs_buffered_write(struct file *file, cond_resched(); - balance_dirty_pages_ratelimited_nr(inode->i_mapping, - dirty_pages); + balance_dirty_pages_ratelimited(inode->i_mapping); if (dirty_pages < (root->leafsize >> PAGE_CACHE_SHIFT) + 1) btrfs_btree_balance_dirty(root, 1); diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 14f8e1faa46..0825321522c 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -1179,7 +1179,7 @@ int btrfs_defrag_file(struct inode *inode, struct file *file, } defrag_count += ret; - balance_dirty_pages_ratelimited_nr(inode->i_mapping, ret); + balance_dirty_pages_ratelimited(inode->i_mapping); mutex_unlock(&inode->i_mutex); if (newer_than) { diff --git a/fs/dyn_sync_cntrl.c b/fs/dyn_sync_cntrl.c new file mode 100644 index 00000000000..e7464e72703 --- /dev/null +++ b/fs/dyn_sync_cntrl.c @@ -0,0 +1,206 @@ +/* + * Author: Paul Reioux aka Faux123 + * + * Copyright 2013 Paul Reioux + * Copyright 2012 Paul Reioux + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define DYN_FSYNC_VERSION_MAJOR 1 +#define DYN_FSYNC_VERSION_MINOR 2 + +/* + * fsync_mutex protects dyn_fsync_active during early suspend / late resume + * transitions + */ +static DEFINE_MUTEX(fsync_mutex); + +bool early_suspend_active __read_mostly = false; +bool dyn_fsync_active __read_mostly = true; + +static ssize_t dyn_fsync_active_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + return sprintf(buf, "%u\n", (dyn_fsync_active ? 1 : 0)); +} + +static ssize_t dyn_fsync_active_store(struct kobject *kobj, + struct kobj_attribute *attr, const char *buf, size_t count) +{ + unsigned int data; + + if(sscanf(buf, "%u\n", &data) == 1) { + if (data == 1) { + pr_info("%s: dynamic fsync enabled\n", __FUNCTION__); + dyn_fsync_active = true; + } + else if (data == 0) { + pr_info("%s: dyanamic fsync disabled\n", __FUNCTION__); + dyn_fsync_active = false; + } + else + pr_info("%s: bad value: %u\n", __FUNCTION__, data); + } else + pr_info("%s: unknown input!\n", __FUNCTION__); + + return count; +} + +static ssize_t dyn_fsync_version_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + return sprintf(buf, "version: %u.%u by faux123\n", + DYN_FSYNC_VERSION_MAJOR, + DYN_FSYNC_VERSION_MINOR); +} + +static ssize_t dyn_fsync_earlysuspend_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + return sprintf(buf, "early suspend active: %u\n", early_suspend_active); +} + +static struct kobj_attribute dyn_fsync_active_attribute = + __ATTR(Dyn_fsync_active, 0666, + dyn_fsync_active_show, + dyn_fsync_active_store); + +static struct kobj_attribute dyn_fsync_version_attribute = + __ATTR(Dyn_fsync_version, 0444, dyn_fsync_version_show, NULL); + +static struct kobj_attribute dyn_fsync_earlysuspend_attribute = + __ATTR(Dyn_fsync_earlysuspend, 0444, dyn_fsync_earlysuspend_show, NULL); + +static struct attribute *dyn_fsync_active_attrs[] = + { + &dyn_fsync_active_attribute.attr, + &dyn_fsync_version_attribute.attr, + &dyn_fsync_earlysuspend_attribute.attr, + NULL, + }; + +static struct attribute_group dyn_fsync_active_attr_group = + { + .attrs = dyn_fsync_active_attrs, + }; + +static struct kobject *dyn_fsync_kobj; + +static void dyn_fsync_force_flush(void) +{ + /* flush all outstanding buffers */ + wakeup_flusher_threads(0, WB_REASON_SYNC); + sync_filesystems(0); + sync_filesystems(1); +} + +static void dyn_fsync_early_suspend(struct early_suspend *h) +{ + mutex_lock(&fsync_mutex); + if (dyn_fsync_active) { + early_suspend_active = true; + dyn_fsync_force_flush(); + } + mutex_unlock(&fsync_mutex); +} + +static void dyn_fsync_late_resume(struct early_suspend *h) +{ + mutex_lock(&fsync_mutex); + early_suspend_active = false; + mutex_unlock(&fsync_mutex); +} + +static struct early_suspend dyn_fsync_early_suspend_handler = + { + .level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN, + .suspend = dyn_fsync_early_suspend, + .resume = dyn_fsync_late_resume, + }; + +static int dyn_fsync_panic_event(struct notifier_block *this, + unsigned long event, void *ptr) +{ + early_suspend_active = true; + dyn_fsync_force_flush(); + //pr_warn("dyn fsync: panic: force flush!\n"); + + return NOTIFY_DONE; +} + +static struct notifier_block dyn_fsync_panic_block = { + .notifier_call = dyn_fsync_panic_event, + .priority = INT_MAX, +}; + +static int dyn_fsync_notify_sys(struct notifier_block *this, unsigned long code, + void *unused) +{ + if (code == SYS_DOWN || code == SYS_HALT) { + early_suspend_active = true; + dyn_fsync_force_flush(); + //pr_warn("dyn fsync: reboot: force flush!\n"); + } + return NOTIFY_DONE; +} + +static struct notifier_block dyn_fsync_notifier = { + .notifier_call = dyn_fsync_notify_sys, +}; + +static int dyn_fsync_init(void) +{ + int sysfs_result; + + register_early_suspend(&dyn_fsync_early_suspend_handler); + register_reboot_notifier(&dyn_fsync_notifier); + atomic_notifier_chain_register(&panic_notifier_list, + &dyn_fsync_panic_block); + + dyn_fsync_kobj = kobject_create_and_add("dyn_fsync", kernel_kobj); + if (!dyn_fsync_kobj) { + pr_err("%s dyn_fsync kobject create failed!\n", __FUNCTION__); + return -ENOMEM; + } + + sysfs_result = sysfs_create_group(dyn_fsync_kobj, + &dyn_fsync_active_attr_group); + + if (sysfs_result) { + pr_info("%s dyn_fsync sysfs create failed!\n", __FUNCTION__); + kobject_put(dyn_fsync_kobj); + } + return sysfs_result; +} + +static void dyn_fsync_exit(void) +{ + unregister_early_suspend(&dyn_fsync_early_suspend_handler); + unregister_reboot_notifier(&dyn_fsync_notifier); + atomic_notifier_chain_unregister(&panic_notifier_list, + &dyn_fsync_panic_block); + + if (dyn_fsync_kobj != NULL) + kobject_put(dyn_fsync_kobj); +} + +module_init(dyn_fsync_init); +module_exit(dyn_fsync_exit); diff --git a/fs/eventpoll.c b/fs/eventpoll.c index c0b3c70ee87..b163f891bc3 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -33,10 +33,12 @@ #include #include #include +#include #include #include #include #include +#include /* * LOCKING: @@ -127,8 +129,12 @@ struct nested_calls { * have an entry of this type linked to the "rbr" RB tree. */ struct epitem { - /* RB tree node used to link this structure to the eventpoll RB tree */ - struct rb_node rbn; + union { + /* RB tree node links this structure to the eventpoll RB tree */ + struct rb_node rbn; + /* Used to free the struct epitem */ + struct rcu_head rcu; + }; /* List header used to link this structure to the eventpoll ready list */ struct list_head rdllink; @@ -156,6 +162,9 @@ struct epitem { /* The structure that describe the interested events and the source fd */ struct epoll_event event; + + /* The fllink is in use. Since rcu can't do 'list_del_init()' */ + int on_list; }; /* @@ -536,14 +545,14 @@ static void ep_unregister_pollwait(struct eventpoll *ep, struct epitem *epi) * @sproc: Pointer to the scan callback. * @priv: Private opaque data passed to the @sproc callback. * @depth: The current depth of recursive f_op->poll calls. + * @ep_locked: caller already holds ep->mtx * * Returns: The same integer error code returned by the @sproc callback. */ static int ep_scan_ready_list(struct eventpoll *ep, int (*sproc)(struct eventpoll *, struct list_head *, void *), - void *priv, - int depth) + void *priv, int depth, bool ep_locked) { int error, pwake = 0; unsigned long flags; @@ -554,7 +563,9 @@ static int ep_scan_ready_list(struct eventpoll *ep, * We need to lock this because we could be hit by * eventpoll_release_file() and epoll_ctl(). */ - mutex_lock_nested(&ep->mtx, depth); + + if (!ep_locked) + mutex_lock_nested(&ep->mtx, depth); /* * Steal the ready list, and re-init the original one to the @@ -615,7 +626,8 @@ static int ep_scan_ready_list(struct eventpoll *ep, } spin_unlock_irqrestore(&ep->lock, flags); - mutex_unlock(&ep->mtx); + if (!ep_locked) + mutex_unlock(&ep->mtx); /* We have to call this outside the lock */ if (pwake) @@ -624,6 +636,12 @@ static int ep_scan_ready_list(struct eventpoll *ep, return error; } +static void epi_rcu_free(struct rcu_head *head) +{ + struct epitem *epi = container_of(head, struct epitem, rcu); + kmem_cache_free(epi_cache, epi); +} + /* * Removes a "struct epitem" from the eventpoll RB tree and deallocates * all the associated resources. Must be called with "mtx" held. @@ -645,8 +663,10 @@ static int ep_remove(struct eventpoll *ep, struct epitem *epi) /* Remove the current item from the list of epoll hooks */ spin_lock(&file->f_lock); - if (ep_is_linked(&epi->fllink)) - list_del_init(&epi->fllink); + if (epi->on_list) { + list_del_rcu(&epi->fllink); + epi->on_list = 0; + } spin_unlock(&file->f_lock); rb_erase(&epi->rbn, &ep->rbr); @@ -656,8 +676,14 @@ static int ep_remove(struct eventpoll *ep, struct epitem *epi) list_del_init(&epi->rdllink); spin_unlock_irqrestore(&ep->lock, flags); - /* At this point it is safe to free the eventpoll item */ - kmem_cache_free(epi_cache, epi); + /* + * At this point it is safe to free the eventpoll item. Use the union + * field epi->rcu, since we are trying to minimize the size of + * 'struct epitem'. The 'rbn' field is no longer in use. Protected by + * ep->mtx. The rcu read side, reverse_path_check_proc(), does not make + * use of the rbn field. + */ + call_rcu(&epi->rcu, epi_rcu_free); atomic_long_dec(&ep->user->epoll_watches); @@ -744,15 +770,34 @@ static int ep_read_events_proc(struct eventpoll *ep, struct list_head *head, return 0; } +static void ep_ptable_queue_proc(struct file *file, wait_queue_head_t *whead, + poll_table *pt); + +struct readyevents_arg { + struct eventpoll *ep; + bool locked; +}; + static int ep_poll_readyevents_proc(void *priv, void *cookie, int call_nests) { - return ep_scan_ready_list(priv, ep_read_events_proc, NULL, call_nests + 1); + struct readyevents_arg *arg = priv; + + return ep_scan_ready_list(arg->ep, ep_read_events_proc, NULL, + call_nests + 1, arg->locked); } static unsigned int ep_eventpoll_poll(struct file *file, poll_table *wait) { int pollflags; struct eventpoll *ep = file->private_data; + struct readyevents_arg arg; + + /* + * During ep_insert() we already hold the ep->mtx for the tfile. + * Prevent re-aquisition. + */ + arg.locked = wait && (wait->_qproc == ep_ptable_queue_proc); + arg.ep = ep; /* Insert inside our poll wait queue */ poll_wait(file, &ep->poll_wait, wait); @@ -764,7 +809,7 @@ static unsigned int ep_eventpoll_poll(struct file *file, poll_table *wait) * could re-enter here. */ pollflags = ep_call_nested(&poll_readywalk_ncalls, EP_MAX_NESTS, - ep_poll_readyevents_proc, ep, ep, current); + ep_poll_readyevents_proc, &arg, ep, current); return pollflags != -1 ? pollflags : 0; } @@ -783,7 +828,6 @@ static const struct file_operations eventpoll_fops = { */ void eventpoll_release_file(struct file *file) { - struct list_head *lsthead = &file->f_ep_links; struct eventpoll *ep; struct epitem *epi; @@ -801,17 +845,12 @@ void eventpoll_release_file(struct file *file) * Besides, ep_remove() acquires the lock, so we can't hold it here. */ mutex_lock(&epmutex); - - while (!list_empty(lsthead)) { - epi = list_first_entry(lsthead, struct epitem, fllink); - + list_for_each_entry_rcu(epi, &file->f_ep_links, fllink) { ep = epi->ep; - list_del_init(&epi->fllink); mutex_lock_nested(&ep->mtx, 0); ep_remove(ep, epi); mutex_unlock(&ep->mtx); } - mutex_unlock(&epmutex); } @@ -1039,7 +1078,9 @@ static int reverse_path_check_proc(void *priv, void *cookie, int call_nests) struct file *child_file; struct epitem *epi; - list_for_each_entry(epi, &file->f_ep_links, fllink) { + /* CTL_DEL can remove links here, but that can't increase our count */ + rcu_read_lock(); + list_for_each_entry_rcu(epi, &file->f_ep_links, fllink) { child_file = epi->ep->file; if (is_file_epoll(child_file)) { if (list_empty(&child_file->f_ep_links)) { @@ -1061,6 +1102,7 @@ static int reverse_path_check_proc(void *priv, void *cookie, int call_nests) "file is not an ep!\n"); } } + rcu_read_unlock(); return error; } @@ -1095,7 +1137,7 @@ static int reverse_path_check(void) * Must be called with "mtx" held. */ static int ep_insert(struct eventpoll *ep, struct epoll_event *event, - struct file *tfile, int fd) + struct file *tfile, int fd, int full_check) { int error, revents, pwake = 0; unsigned long flags; @@ -1118,6 +1160,7 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event, epi->event = *event; epi->nwait = 0; epi->next = EP_UNACTIVE_PTR; + epi->on_list = 0; /* Initialize the poll table using the queue callback */ epq.epi = epi; @@ -1144,7 +1187,8 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event, /* Add the current item to the list of active epoll hook for this file */ spin_lock(&tfile->f_lock); - list_add_tail(&epi->fllink, &tfile->f_ep_links); + list_add_tail_rcu(&epi->fllink, &tfile->f_ep_links); + epi->on_list = 1; spin_unlock(&tfile->f_lock); /* @@ -1155,7 +1199,7 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event, /* now check if we've created too many backpaths */ error = -EINVAL; - if (reverse_path_check()) + if (full_check && reverse_path_check()) goto error_remove_epi; /* We have to drop the new item inside our item list to keep track of it */ @@ -1184,8 +1228,8 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event, error_remove_epi: spin_lock(&tfile->f_lock); - if (ep_is_linked(&epi->fllink)) - list_del_init(&epi->fllink); + if (epi->on_list) + list_del_rcu(&epi->fllink); spin_unlock(&tfile->f_lock); rb_erase(&epi->rbn, &ep->rbr); @@ -1332,7 +1376,7 @@ static int ep_send_events(struct eventpoll *ep, esed.maxevents = maxevents; esed.events = events; - return ep_scan_ready_list(ep, ep_send_events_proc, &esed, 0); + return ep_scan_ready_list(ep, ep_send_events_proc, &esed, 0, false); } static inline struct timespec ep_set_mstimeout(long ms) @@ -1415,7 +1459,8 @@ static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events, } spin_unlock_irqrestore(&ep->lock, flags); - if (!schedule_hrtimeout_range(to, slack, HRTIMER_MODE_ABS)) + if (!freezable_schedule_hrtimeout_range(to, slack, + HRTIMER_MODE_ABS)) timed_out = 1; spin_lock_irqsave(&ep->lock, flags); @@ -1602,11 +1647,12 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd, struct epoll_event __user *, event) { int error; - int did_lock_epmutex = 0; + int full_check = 0; struct file *file, *tfile; struct eventpoll *ep; struct epitem *epi; struct epoll_event epds; + struct eventpoll *tep = NULL; error = -EFAULT; if (ep_op_has_event(op) && @@ -1652,26 +1698,39 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd, * and hang them on the tfile_check_list, so we can check that we * haven't created too many possible wakeup paths. * - * We need to hold the epmutex across both ep_insert and ep_remove - * b/c we want to make sure we are looking at a coherent view of - * epoll network. + * We do not need to take the global 'epumutex' on EPOLL_CTL_ADD when + * the epoll file descriptor is attaching directly to a wakeup source, + * unless the epoll file descriptor is nested. The purpose of taking the + * 'epmutex' on add is to prevent complex toplogies such as loops and + * deep wakeup paths from forming in parallel through multiple + * EPOLL_CTL_ADD operations. */ - if (op == EPOLL_CTL_ADD || op == EPOLL_CTL_DEL) { - mutex_lock(&epmutex); - did_lock_epmutex = 1; - } if (op == EPOLL_CTL_ADD) { - if (is_file_epoll(tfile)) { - error = -ELOOP; - if (ep_loop_check(ep, tfile) != 0) { - clear_tfile_check_list(); - goto error_tgt_fput; + if (!list_empty(&file->f_ep_links) || + is_file_epoll(tfile)) { + full_check = 1; + mutex_unlock(&ep->mtx); + mutex_lock(&epmutex); + if (is_file_epoll(tfile)) { + error = -ELOOP; + if (ep_loop_check(ep, tfile) != 0) { + clear_tfile_check_list(); + goto error_tgt_fput; + } + } else + list_add(&tfile->f_tfile_llink, + &tfile_check_list); + mutex_lock_nested(&ep->mtx, 0); + if (is_file_epoll(tfile)) { + tep = tfile->private_data; + mutex_lock_nested(&tep->mtx, 1); } - } else - list_add(&tfile->f_tfile_llink, &tfile_check_list); + } + } + if (op == EPOLL_CTL_DEL && is_file_epoll(tfile)) { + tep = tfile->private_data; + mutex_lock_nested(&tep->mtx, 1); } - - mutex_lock_nested(&ep->mtx, 0); /* * Try to lookup the file inside our RB tree, Since we grabbed "mtx" @@ -1685,10 +1744,11 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd, case EPOLL_CTL_ADD: if (!epi) { epds.events |= POLLERR | POLLHUP; - error = ep_insert(ep, &epds, tfile, fd); + error = ep_insert(ep, &epds, tfile, fd, full_check); } else error = -EEXIST; - clear_tfile_check_list(); + if (full_check) + clear_tfile_check_list(); break; case EPOLL_CTL_DEL: if (epi) @@ -1704,10 +1764,12 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd, error = -ENOENT; break; } + if (tep != NULL) + mutex_unlock(&tep->mtx); mutex_unlock(&ep->mtx); error_tgt_fput: - if (did_lock_epmutex) + if (full_check) mutex_unlock(&epmutex); fput(tfile); diff --git a/fs/exfat/Kconfig b/fs/exfat/Kconfig new file mode 100644 index 00000000000..144b6eccabe --- /dev/null +++ b/fs/exfat/Kconfig @@ -0,0 +1,19 @@ +config EXFAT_FS + tristate "exFAT filesystem support" + select NLS + help + exFAT driver from Samsung + +config EXFAT_DEFAULT_CODEPAGE + int "Default codepage for exFAT" + depends on EXFAT_FS + default 437 + help + This option should be set to the codepage of your exFAT filesystems. + +config EXFAT_DEFAULT_IOCHARSET + string "Default iocharset for exFAT" + depends on EXFAT_FS + default "utf8" + help + Set this to the default input/output character set you'd like exFAT to use. diff --git a/fs/exfat/Makefile b/fs/exfat/Makefile new file mode 100644 index 00000000000..77dc36c6183 --- /dev/null +++ b/fs/exfat/Makefile @@ -0,0 +1,4 @@ +obj-$(CONFIG_EXFAT_FS) += exfat.o + +exfat-y := exfat_core.o exfat_api.o exfat_blkdev.o exfat_cache.o exfat_super.o \ + exfat_data.o exfat_global.o exfat_nls.o exfat_oal.o exfat_upcase.o diff --git a/fs/exfat/Makefile.module b/fs/exfat/Makefile.module new file mode 100644 index 00000000000..2e97826d059 --- /dev/null +++ b/fs/exfat/Makefile.module @@ -0,0 +1,20 @@ +EXTRA_FLAGS += -I$(PWD) + +#KDIR := /usr/src/linux/ +KDIR := /lib/modules/$(shell uname -r)/build +PWD := $(shell pwd) + +export CONFIG_EXFAT_FS := m + +all: + $(MAKE) -C $(KDIR) M=$(PWD) modules + +clean: + $(MAKE) -C $(KDIR) M=$(PWD) clean + +help: + $(MAKE) -C $(KDIR) M=$(PWD) help + +.PHONY : install +install : all + sudo $(MAKE) -C $(KDIR) M=$(PWD) modules_install; sudo depmod diff --git a/fs/exfat/README.md b/fs/exfat/README.md new file mode 100644 index 00000000000..e14291263ae --- /dev/null +++ b/fs/exfat/README.md @@ -0,0 +1,71 @@ +exfat-nofuse +============ + +Linux non-fuse read/write kernel driver for the exFAT file system.
+Originally ported from android kernel v3.0. + + +Kudos to ksv1986 for the mutex patch!
+Thanks to JackNorris for being awesome and providing the clear_inode() patch.
+
+Big thanks to lqs for completing the driver! +Big thanks to benpicco for fixing 3.11.y compatibility! + + +Special thanks to github user AndreiLux for spreading the word about the leak!
+ + +Installation as stand alone module: +==================================== + + make -f Makefile.module KDIR="path to kernel source" CROSS_COMPILE="path to android chain tools (as linaro)/bin/SOMETHING- (see your folder for clues)" + +Example how it's works for me! + + make -f Makefile.module CROSS_COMPILE=../dorimanx-SG2-I9100-Kernel/android-toolchain/bin/arm-eabi- KDIR=../dorimanx-SG2-I9100-Kernel/ + +exfat.ko module file will be created in exfat source folder. and will work with kernel source you have used. + + make -f Makefile.module install + +To load the driver manually, run this as root: + + modprobe exfat + +To add to kernel you need to do this: +====================================== + +cd your kernel source dir + +mkdir fs/exfat + +copy all files (except .git and .gitignore) from exfat-nofuse to your kernel source fs/exfat/ + +see +https://github.com/dorimanx/Dorimanx-SG2-I9100-Kernel/commit/e8fc728a68096db9ffcebff40244ebfb60a3de18 + +edit fs/Kconfig +edit fs/Makefile + +cd your kernel source +make menuconfig + +Go to: +> File systems > DOS/FAT/NT > check the exfat as MODULE (M) +> (437) Default codepage for exFAT +> (utf8) Default iocharset for exFAT + +> ESC to main menu +> Save an Alternate Configuration File +> ESC ESC + +build your kernel. + +and you will have new module! + +exfat.ko + +have fun. + +Free Software for the Free Minds! +===================================== diff --git a/fs/exfat/exfat.h b/fs/exfat/exfat.h new file mode 100644 index 00000000000..a37f4b15406 --- /dev/null +++ b/fs/exfat/exfat.h @@ -0,0 +1,675 @@ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * 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. + */ + +/************************************************************************/ +/* */ +/* PROJECT : exFAT & FAT12/16/32 File System */ +/* FILE : exfat.h */ +/* PURPOSE : Header File for exFAT File Manager */ +/* */ +/*----------------------------------------------------------------------*/ +/* NOTES */ +/* */ +/*----------------------------------------------------------------------*/ +/* REVISION HISTORY (Ver 0.9) */ +/* */ +/* - 2010.11.15 [Joosun Hahn] : first writing */ +/* */ +/************************************************************************/ + +#ifndef _EXFAT_H +#define _EXFAT_H + +#include "exfat_config.h" +#include "exfat_global.h" +#include "exfat_data.h" +#include "exfat_oal.h" + +#include "exfat_blkdev.h" +#include "exfat_cache.h" +#include "exfat_nls.h" +#include "exfat_api.h" +#include "exfat_cache.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#if EXFAT_CONFIG_KERNEL_DEBUG + /* For Debugging Purpose */ + /* IOCTL code 'f' used by + * - file systems typically #0~0x1F + * - embedded terminal devices #128~ + * - exts for debugging purpose #99 + * number 100 and 101 is availble now but has possible conflicts + */ +#define EXFAT_IOC_GET_DEBUGFLAGS _IOR('f', 100, long) +#define EXFAT_IOC_SET_DEBUGFLAGS _IOW('f', 101, long) + +#define EXFAT_DEBUGFLAGS_INVALID_UMOUNT 0x01 +#define EXFAT_DEBUGFLAGS_ERROR_RW 0x02 +#endif /* EXFAT_CONFIG_KERNEL_DEBUG */ + + /*----------------------------------------------------------------------*/ + /* Constant & Macro Definitions */ + /*----------------------------------------------------------------------*/ + +#define MAX_VOLUME 4 // max num of volumes per device + +#define DENTRY_SIZE 32 // dir entry size +#define DENTRY_SIZE_BITS 5 + + /* PBR entries */ +#define PBR_SIGNATURE 0xAA55 +#define EXT_SIGNATURE 0xAA550000 +#define VOL_LABEL "NO NAME " // size should be 11 +#define OEM_NAME "MSWIN4.1" // size should be 8 +#define STR_FAT12 "FAT12 " // size should be 8 +#define STR_FAT16 "FAT16 " // size should be 8 +#define STR_FAT32 "FAT32 " // size should be 8 +#define STR_EXFAT "EXFAT " // size should be 8 +#define VOL_CLEAN 0x0000 +#define VOL_DIRTY 0x0002 + + /* max number of clusters */ +#define FAT12_THRESHOLD 4087 // 2^12 - 1 + 2 (clu 0 & 1) +#define FAT16_THRESHOLD 65527 // 2^16 - 1 + 2 +#define FAT32_THRESHOLD 268435457 // 2^28 - 1 + 2 +#define EXFAT_THRESHOLD 268435457 // 2^28 - 1 + 2 + + /* file types */ +#define TYPE_UNUSED 0x0000 +#define TYPE_DELETED 0x0001 +#define TYPE_INVALID 0x0002 +#define TYPE_CRITICAL_PRI 0x0100 +#define TYPE_BITMAP 0x0101 +#define TYPE_UPCASE 0x0102 +#define TYPE_VOLUME 0x0103 +#define TYPE_DIR 0x0104 +#define TYPE_FILE 0x011F +#define TYPE_SYMLINK 0x015F +#define TYPE_CRITICAL_SEC 0x0200 +#define TYPE_STREAM 0x0201 +#define TYPE_EXTEND 0x0202 +#define TYPE_ACL 0x0203 +#define TYPE_BENIGN_PRI 0x0400 +#define TYPE_GUID 0x0401 +#define TYPE_PADDING 0x0402 +#define TYPE_ACLTAB 0x0403 +#define TYPE_BENIGN_SEC 0x0800 +#define TYPE_ALL 0x0FFF + + /* time modes */ +#define TM_CREATE 0 +#define TM_MODIFY 1 +#define TM_ACCESS 2 + + /* checksum types */ +#define CS_DIR_ENTRY 0 +#define CS_PBR_SECTOR 1 +#define CS_DEFAULT 2 + +#define CLUSTER_16(x) ((UINT16)(x)) +#define CLUSTER_32(x) ((UINT32)(x)) + +#define START_SECTOR(x) \ + ( (((x)-2) << p_fs->sectors_per_clu_bits) + p_fs->data_start_sector ) + +#define IS_LAST_SECTOR_IN_CLUSTER(sec) \ + ( (((sec) - p_fs->data_start_sector + 1) & ((1 << p_fs->sectors_per_clu_bits) -1)) == 0) + +#define GET_CLUSTER_FROM_SECTOR(sec) \ + ((((sec) - p_fs->data_start_sector) >> p_fs->sectors_per_clu_bits) +2) + +#define GET16(p_src) \ + ( ((UINT16)(p_src)[0]) | (((UINT16)(p_src)[1]) << 8) ) +#define GET32(p_src) \ + ( ((UINT32)(p_src)[0]) | (((UINT32)(p_src)[1]) << 8) | \ + (((UINT32)(p_src)[2]) << 16) | (((UINT32)(p_src)[3]) << 24) ) +#define GET64(p_src) \ + ( ((UINT64)(p_src)[0]) | (((UINT64)(p_src)[1]) << 8) | \ + (((UINT64)(p_src)[2]) << 16) | (((UINT64)(p_src)[3]) << 24) | \ + (((UINT64)(p_src)[4]) << 32) | (((UINT64)(p_src)[5]) << 40) | \ + (((UINT64)(p_src)[6]) << 48) | (((UINT64)(p_src)[7]) << 56) ) + + +#define SET16(p_dst,src) \ + do { \ + (p_dst)[0]=(UINT8)(src); \ + (p_dst)[1]=(UINT8)(((UINT16)(src)) >> 8); \ + } while (0) +#define SET32(p_dst,src) \ + do { \ + (p_dst)[0]=(UINT8)(src); \ + (p_dst)[1]=(UINT8)(((UINT32)(src)) >> 8); \ + (p_dst)[2]=(UINT8)(((UINT32)(src)) >> 16); \ + (p_dst)[3]=(UINT8)(((UINT32)(src)) >> 24); \ + } while (0) +#define SET64(p_dst,src) \ + do { \ + (p_dst)[0]=(UINT8)(src); \ + (p_dst)[1]=(UINT8)(((UINT64)(src)) >> 8); \ + (p_dst)[2]=(UINT8)(((UINT64)(src)) >> 16); \ + (p_dst)[3]=(UINT8)(((UINT64)(src)) >> 24); \ + (p_dst)[4]=(UINT8)(((UINT64)(src)) >> 32); \ + (p_dst)[5]=(UINT8)(((UINT64)(src)) >> 40); \ + (p_dst)[6]=(UINT8)(((UINT64)(src)) >> 48); \ + (p_dst)[7]=(UINT8)(((UINT64)(src)) >> 56); \ + } while (0) + +#ifdef __LITTLE_ENDIAN +#define GET16_A(p_src) (*((UINT16 *)(p_src))) +#define GET32_A(p_src) (*((UINT32 *)(p_src))) +#define GET64_A(p_src) (*((UINT64 *)(p_src))) +#define SET16_A(p_dst,src) *((UINT16 *)(p_dst)) = (UINT16)(src) +#define SET32_A(p_dst,src) *((UINT32 *)(p_dst)) = (UINT32)(src) +#define SET64_A(p_dst,src) *((UINT64 *)(p_dst)) = (UINT64)(src) +#else +#define GET16_A(p_src) GET16(p_src) +#define GET32_A(p_src) GET32(p_src) +#define GET64_A(p_src) GET64(p_src) +#define SET16_A(p_dst,src) SET16(p_dst, src) +#define SET32_A(p_dst,src) SET32(p_dst, src) +#define SET64_A(p_dst,src) SET64(p_dst, src) +#endif + + /* Upcase tabel mecro */ +#define HIGH_INDEX_BIT (8) +#define HIGH_INDEX_MASK (0xFF00) +#define LOW_INDEX_BIT (16-HIGH_INDEX_BIT) +#define UTBL_ROW_COUNT (1<> LOW_INDEX_BIT; + } + static inline UINT16 get_row_index(UINT16 i) + { + return i & ~HIGH_INDEX_MASK; + } + /*----------------------------------------------------------------------*/ + /* Type Definitions */ + /*----------------------------------------------------------------------*/ + + /* MS_DOS FAT partition boot record (512 bytes) */ + typedef struct { + UINT8 jmp_boot[3]; + UINT8 oem_name[8]; + UINT8 bpb[109]; + UINT8 boot_code[390]; + UINT8 signature[2]; + } PBR_SECTOR_T; + + /* MS-DOS FAT12/16 BIOS parameter block (51 bytes) */ + typedef struct { + UINT8 sector_size[2]; + UINT8 sectors_per_clu; + UINT8 num_reserved[2]; + UINT8 num_fats; + UINT8 num_root_entries[2]; + UINT8 num_sectors[2]; + UINT8 media_type; + UINT8 num_fat_sectors[2]; + UINT8 sectors_in_track[2]; + UINT8 num_heads[2]; + UINT8 num_hid_sectors[4]; + UINT8 num_huge_sectors[4]; + + UINT8 phy_drv_no; + UINT8 reserved; + UINT8 ext_signature; + UINT8 vol_serial[4]; + UINT8 vol_label[11]; + UINT8 vol_type[8]; + } BPB16_T; + + /* MS-DOS FAT32 BIOS parameter block (79 bytes) */ + typedef struct { + UINT8 sector_size[2]; + UINT8 sectors_per_clu; + UINT8 num_reserved[2]; + UINT8 num_fats; + UINT8 num_root_entries[2]; + UINT8 num_sectors[2]; + UINT8 media_type; + UINT8 num_fat_sectors[2]; + UINT8 sectors_in_track[2]; + UINT8 num_heads[2]; + UINT8 num_hid_sectors[4]; + UINT8 num_huge_sectors[4]; + UINT8 num_fat32_sectors[4]; + UINT8 ext_flags[2]; + UINT8 fs_version[2]; + UINT8 root_cluster[4]; + UINT8 fsinfo_sector[2]; + UINT8 backup_sector[2]; + UINT8 reserved[12]; + + UINT8 phy_drv_no; + UINT8 ext_reserved; + UINT8 ext_signature; + UINT8 vol_serial[4]; + UINT8 vol_label[11]; + UINT8 vol_type[8]; + } BPB32_T; + + /* MS-DOS EXFAT BIOS parameter block (109 bytes) */ + typedef struct { + UINT8 reserved1[53]; + UINT8 vol_offset[8]; + UINT8 vol_length[8]; + UINT8 fat_offset[4]; + UINT8 fat_length[4]; + UINT8 clu_offset[4]; + UINT8 clu_count[4]; + UINT8 root_cluster[4]; + UINT8 vol_serial[4]; + UINT8 fs_version[2]; + UINT8 vol_flags[2]; + UINT8 sector_size_bits; + UINT8 sectors_per_clu_bits; + UINT8 num_fats; + UINT8 phy_drv_no; + UINT8 perc_in_use; + UINT8 reserved2[7]; + } BPBEX_T; + + /* MS-DOS FAT file system information sector (512 bytes) */ + typedef struct { + UINT8 signature1[4]; // aligned + UINT8 reserved1[480]; + UINT8 signature2[4]; // aligned + UINT8 free_cluster[4]; // aligned + UINT8 next_cluster[4]; // aligned + UINT8 reserved2[14]; + UINT8 signature3[2]; + } FSI_SECTOR_T; + + /* MS-DOS FAT directory entry (32 bytes) */ + typedef struct { + UINT8 dummy[32]; + } DENTRY_T; + + typedef struct { + UINT8 name[DOS_NAME_LENGTH]; + UINT8 attr; + UINT8 lcase; + UINT8 create_time_ms; + UINT8 create_time[2]; // aligned + UINT8 create_date[2]; // aligned + UINT8 access_date[2]; // aligned + UINT8 start_clu_hi[2]; // aligned + UINT8 modify_time[2]; // aligned + UINT8 modify_date[2]; // aligned + UINT8 start_clu_lo[2]; // aligned + UINT8 size[4]; // aligned + } DOS_DENTRY_T; + + /* MS-DOS FAT extended directory entry (32 bytes) */ + typedef struct { + UINT8 order; + UINT8 unicode_0_4[10]; + UINT8 attr; + UINT8 sysid; + UINT8 checksum; + UINT8 unicode_5_10[12]; // aligned + UINT8 start_clu[2]; // aligned + UINT8 unicode_11_12[4]; // aligned + } EXT_DENTRY_T; + + /* MS-DOS EXFAT file directory entry (32 bytes) */ + typedef struct { + UINT8 type; + UINT8 num_ext; + UINT8 checksum[2]; // aligned + UINT8 attr[2]; // aligned + UINT8 reserved1[2]; + UINT8 create_time[2]; // aligned + UINT8 create_date[2]; // aligned + UINT8 modify_time[2]; // aligned + UINT8 modify_date[2]; // aligned + UINT8 access_time[2]; // aligned + UINT8 access_date[2]; // aligned + UINT8 create_time_ms; + UINT8 modify_time_ms; + UINT8 access_time_ms; + UINT8 reserved2[9]; + } FILE_DENTRY_T; + + /* MS-DOS EXFAT stream extension directory entry (32 bytes) */ + typedef struct { + UINT8 type; + UINT8 flags; + UINT8 reserved1; + UINT8 name_len; + UINT8 name_hash[2]; // aligned + UINT8 reserved2[2]; + UINT8 valid_size[8]; // aligned + UINT8 reserved3[4]; // aligned + UINT8 start_clu[4]; // aligned + UINT8 size[8]; // aligned + } STRM_DENTRY_T; + + /* MS-DOS EXFAT file name directory entry (32 bytes) */ + typedef struct { + UINT8 type; + UINT8 flags; + UINT8 unicode_0_14[30]; // aligned + } NAME_DENTRY_T; + + /* MS-DOS EXFAT allocation bitmap directory entry (32 bytes) */ + typedef struct { + UINT8 type; + UINT8 flags; + UINT8 reserved[18]; + UINT8 start_clu[4]; // aligned + UINT8 size[8]; // aligned + } BMAP_DENTRY_T; + + /* MS-DOS EXFAT up-case table directory entry (32 bytes) */ + typedef struct { + UINT8 type; + UINT8 reserved1[3]; + UINT8 checksum[4]; // aligned + UINT8 reserved2[12]; + UINT8 start_clu[4]; // aligned + UINT8 size[8]; // aligned + } CASE_DENTRY_T; + + /* MS-DOS EXFAT volume label directory entry (32 bytes) */ + typedef struct { + UINT8 type; + UINT8 label_len; + UINT8 unicode_0_10[22]; // aligned + UINT8 reserved[8]; + } VOLM_DENTRY_T; + + /* unused entry hint information */ + typedef struct { + UINT32 dir; + INT32 entry; + CHAIN_T clu; + } UENTRY_T; + + /* file system volume information structure */ + typedef struct __FS_STRUCT_T { + UINT32 mounted; + struct super_block *sb; + struct semaphore v_sem; + } FS_STRUCT_T; + + typedef struct { + INT32 (*alloc_cluster)(struct super_block *sb, INT32 num_alloc, CHAIN_T *p_chain); + void (*free_cluster)(struct super_block *sb, CHAIN_T *p_chain, INT32 do_relse); + INT32 (*count_used_clusters)(struct super_block *sb); + + INT32 (*init_dir_entry)(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, UINT32 type, + UINT32 start_clu, UINT64 size); + INT32 (*init_ext_entry)(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, INT32 num_entries, + UNI_NAME_T *p_uniname, DOS_NAME_T *p_dosname); + INT32 (*find_dir_entry)(struct super_block *sb, CHAIN_T *p_dir, UNI_NAME_T *p_uniname, INT32 num_entries, DOS_NAME_T *p_dosname, UINT32 type); + void (*delete_dir_entry)(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, INT32 offset, INT32 num_entries); + void (*get_uni_name_from_ext_entry)(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, UINT16 *uniname); + INT32 (*count_ext_entries)(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, DENTRY_T *p_entry); + INT32 (*calc_num_entries)(UNI_NAME_T *p_uniname); + + UINT32 (*get_entry_type)(DENTRY_T *p_entry); + void (*set_entry_type)(DENTRY_T *p_entry, UINT32 type); + UINT32 (*get_entry_attr)(DENTRY_T *p_entry); + void (*set_entry_attr)(DENTRY_T *p_entry, UINT32 attr); + UINT8 (*get_entry_flag)(DENTRY_T *p_entry); + void (*set_entry_flag)(DENTRY_T *p_entry, UINT8 flag); + UINT32 (*get_entry_clu0)(DENTRY_T *p_entry); + void (*set_entry_clu0)(DENTRY_T *p_entry, UINT32 clu0); + UINT64 (*get_entry_size)(DENTRY_T *p_entry); + void (*set_entry_size)(DENTRY_T *p_entry, UINT64 size); + void (*get_entry_time)(DENTRY_T *p_entry, TIMESTAMP_T *tp, UINT8 mode); + void (*set_entry_time)(DENTRY_T *p_entry, TIMESTAMP_T *tp, UINT8 mode); + } FS_FUNC_T; + + typedef struct __FS_INFO_T { + UINT32 drv; // drive ID + UINT32 vol_type; // volume FAT type + UINT32 vol_id; // volume serial number + + UINT32 num_sectors; // num of sectors in volume + UINT32 num_clusters; // num of clusters in volume + UINT32 cluster_size; // cluster size in bytes + UINT32 cluster_size_bits; + UINT32 sectors_per_clu; // cluster size in sectors + UINT32 sectors_per_clu_bits; + + UINT32 PBR_sector; // PBR sector + UINT32 FAT1_start_sector; // FAT1 start sector + UINT32 FAT2_start_sector; // FAT2 start sector + UINT32 root_start_sector; // root dir start sector + UINT32 data_start_sector; // data area start sector + UINT32 num_FAT_sectors; // num of FAT sectors + + UINT32 root_dir; // root dir cluster + UINT32 dentries_in_root; // num of dentries in root dir + UINT32 dentries_per_clu; // num of dentries per cluster + + UINT32 vol_flag; // volume dirty flag + struct buffer_head *pbr_bh; // PBR sector + + UINT32 map_clu; // allocation bitmap start cluster + UINT32 map_sectors; // num of allocation bitmap sectors + struct buffer_head **vol_amap; // allocation bitmap + + UINT16 **vol_utbl; // upcase table + + UINT32 clu_srch_ptr; // cluster search pointer + UINT32 used_clusters; // number of used clusters + UENTRY_T hint_uentry; // unused entry hint information + + UINT32 dev_ejected; // block device operation error flag + + FS_FUNC_T *fs_func; + + /* FAT cache */ + BUF_CACHE_T FAT_cache_array[FAT_CACHE_SIZE]; + BUF_CACHE_T FAT_cache_lru_list; + BUF_CACHE_T FAT_cache_hash_list[FAT_CACHE_HASH_SIZE]; + + /* buf cache */ + BUF_CACHE_T buf_cache_array[BUF_CACHE_SIZE]; + BUF_CACHE_T buf_cache_lru_list; + BUF_CACHE_T buf_cache_hash_list[BUF_CACHE_HASH_SIZE]; + } FS_INFO_T; + +#define ES_2_ENTRIES 2 +#define ES_3_ENTRIES 3 +#define ES_ALL_ENTRIES 0 + + typedef struct { + UINT32 sector; // sector number that contains file_entry + INT32 offset; // byte offset in the sector + INT32 alloc_flag; // flag in stream entry. 01 for cluster chain, 03 for contig. clusteres. + UINT32 num_entries; + + // __buf should be the last member + void *__buf; + } ENTRY_SET_CACHE_T; + + /*----------------------------------------------------------------------*/ + /* External Function Declarations */ + /*----------------------------------------------------------------------*/ + + /* file system initialization & shutdown functions */ + INT32 ffsInit(void); + INT32 ffsShutdown(void); + + /* volume management functions */ + INT32 ffsMountVol(struct super_block *sb, INT32 drv); + INT32 ffsUmountVol(struct super_block *sb); + INT32 ffsCheckVol(struct super_block *sb); + INT32 ffsGetVolInfo(struct super_block *sb, VOL_INFO_T *info); + INT32 ffsSyncVol(struct super_block *sb, INT32 do_sync); + + /* file management functions */ + INT32 ffsLookupFile(struct inode *inode, UINT8 *path, FILE_ID_T *fid); + INT32 ffsCreateFile(struct inode *inode, UINT8 *path, UINT8 mode, FILE_ID_T *fid); + INT32 ffsReadFile(struct inode *inode, FILE_ID_T *fid, void *buffer, UINT64 count, UINT64 *rcount); + INT32 ffsWriteFile(struct inode *inode, FILE_ID_T *fid, void *buffer, UINT64 count, UINT64 *wcount); + INT32 ffsTruncateFile(struct inode *inode, UINT64 old_size, UINT64 new_size); + INT32 ffsMoveFile(struct inode *old_parent_inode, FILE_ID_T *fid, struct inode *new_parent_inode, struct dentry *new_dentry); + INT32 ffsRemoveFile(struct inode *inode, FILE_ID_T *fid); + INT32 ffsSetAttr(struct inode *inode, UINT32 attr); + INT32 ffsGetStat(struct inode *inode, DIR_ENTRY_T *info); + INT32 ffsSetStat(struct inode *inode, DIR_ENTRY_T *info); + INT32 ffsMapCluster(struct inode *inode, INT32 clu_offset, UINT32 *clu); + + /* directory management functions */ + INT32 ffsCreateDir(struct inode *inode, UINT8 *path, FILE_ID_T *fid); + INT32 ffsReadDir(struct inode *inode, DIR_ENTRY_T *dir_ent); + INT32 ffsRemoveDir(struct inode *inode, FILE_ID_T *fid); + + /*----------------------------------------------------------------------*/ + /* External Function Declarations (NOT TO UPPER LAYER) */ + /*----------------------------------------------------------------------*/ + + /* fs management functions */ + INT32 fs_init(void); + INT32 fs_shutdown(void); + void fs_set_vol_flags(struct super_block *sb, UINT32 new_flag); + void fs_sync(struct super_block *sb, INT32 do_sync); + void fs_error(struct super_block *sb); + + /* cluster management functions */ + INT32 clear_cluster(struct super_block *sb, UINT32 clu); + INT32 fat_alloc_cluster(struct super_block *sb, INT32 num_alloc, CHAIN_T *p_chain); + INT32 exfat_alloc_cluster(struct super_block *sb, INT32 num_alloc, CHAIN_T *p_chain); + void fat_free_cluster(struct super_block *sb, CHAIN_T *p_chain, INT32 do_relse); + void exfat_free_cluster(struct super_block *sb, CHAIN_T *p_chain, INT32 do_relse); + UINT32 find_last_cluster(struct super_block *sb, CHAIN_T *p_chain); + INT32 count_num_clusters(struct super_block *sb, CHAIN_T *dir); + INT32 fat_count_used_clusters(struct super_block *sb); + INT32 exfat_count_used_clusters(struct super_block *sb); + void exfat_chain_cont_cluster(struct super_block *sb, UINT32 chain, INT32 len); + + /* allocation bitmap management functions */ + INT32 load_alloc_bitmap(struct super_block *sb); + void free_alloc_bitmap(struct super_block *sb); + INT32 set_alloc_bitmap(struct super_block *sb, UINT32 clu); + INT32 clr_alloc_bitmap(struct super_block *sb, UINT32 clu); + UINT32 test_alloc_bitmap(struct super_block *sb, UINT32 clu); + void sync_alloc_bitmap(struct super_block *sb); + + /* upcase table management functions */ + INT32 load_upcase_table(struct super_block *sb); + void free_upcase_table(struct super_block *sb); + + /* dir entry management functions */ + UINT32 fat_get_entry_type(DENTRY_T *p_entry); + UINT32 exfat_get_entry_type(DENTRY_T *p_entry); + void fat_set_entry_type(DENTRY_T *p_entry, UINT32 type); + void exfat_set_entry_type(DENTRY_T *p_entry, UINT32 type); + UINT32 fat_get_entry_attr(DENTRY_T *p_entry); + UINT32 exfat_get_entry_attr(DENTRY_T *p_entry); + void fat_set_entry_attr(DENTRY_T *p_entry, UINT32 attr); + void exfat_set_entry_attr(DENTRY_T *p_entry, UINT32 attr); + UINT8 fat_get_entry_flag(DENTRY_T *p_entry); + UINT8 exfat_get_entry_flag(DENTRY_T *p_entry); + void fat_set_entry_flag(DENTRY_T *p_entry, UINT8 flag); + void exfat_set_entry_flag(DENTRY_T *p_entry, UINT8 flag); + UINT32 fat_get_entry_clu0(DENTRY_T *p_entry); + UINT32 exfat_get_entry_clu0(DENTRY_T *p_entry); + void fat_set_entry_clu0(DENTRY_T *p_entry, UINT32 start_clu); + void exfat_set_entry_clu0(DENTRY_T *p_entry, UINT32 start_clu); + UINT64 fat_get_entry_size(DENTRY_T *p_entry); + UINT64 exfat_get_entry_size(DENTRY_T *p_entry); + void fat_set_entry_size(DENTRY_T *p_entry, UINT64 size); + void exfat_set_entry_size(DENTRY_T *p_entry, UINT64 size); + void fat_get_entry_time(DENTRY_T *p_entry, TIMESTAMP_T *tp, UINT8 mode); + void exfat_get_entry_time(DENTRY_T *p_entry, TIMESTAMP_T *tp, UINT8 mode); + void fat_set_entry_time(DENTRY_T *p_entry, TIMESTAMP_T *tp, UINT8 mode); + void exfat_set_entry_time(DENTRY_T *p_entry, TIMESTAMP_T *tp, UINT8 mode); + INT32 fat_init_dir_entry(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, UINT32 type, UINT32 start_clu, UINT64 size); + INT32 exfat_init_dir_entry(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, UINT32 type, UINT32 start_clu, UINT64 size); + INT32 fat_init_ext_dir_entry(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, INT32 num_entries, UNI_NAME_T *p_uniname, DOS_NAME_T *p_dosname); + INT32 exfat_init_ext_dir_entry(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, INT32 num_entries, UNI_NAME_T *p_uniname, DOS_NAME_T *p_dosname); + void init_dos_entry(DOS_DENTRY_T *ep, UINT32 type, UINT32 start_clu); + void init_ext_entry(EXT_DENTRY_T *ep, INT32 order, UINT8 chksum, UINT16 *uniname); + void init_file_entry(FILE_DENTRY_T *ep, UINT32 type); + void init_strm_entry(STRM_DENTRY_T *ep, UINT8 flags, UINT32 start_clu, UINT64 size); + void init_name_entry(NAME_DENTRY_T *ep, UINT16 *uniname); + void fat_delete_dir_entry(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, INT32 order, INT32 num_entries); + void exfat_delete_dir_entry(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, INT32 order, INT32 num_entries); + + INT32 find_location(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, UINT32 *sector, INT32 *offset); + DENTRY_T *get_entry_with_sector(struct super_block *sb, UINT32 sector, INT32 offset); + DENTRY_T *get_entry_in_dir(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, UINT32 *sector); + ENTRY_SET_CACHE_T *get_entry_set_in_dir (struct super_block *sb, CHAIN_T *p_dir, INT32 entry, UINT32 type, DENTRY_T **file_ep); + void release_entry_set (ENTRY_SET_CACHE_T *es); + INT32 write_whole_entry_set (struct super_block *sb, ENTRY_SET_CACHE_T *es); + INT32 write_partial_entries_in_entry_set (struct super_block *sb, ENTRY_SET_CACHE_T *es, DENTRY_T *ep, UINT32 count); + INT32 search_deleted_or_unused_entry(struct super_block *sb, CHAIN_T *p_dir, INT32 num_entries); + INT32 find_empty_entry(struct inode *inode, CHAIN_T *p_dir, INT32 num_entries); + INT32 fat_find_dir_entry(struct super_block *sb, CHAIN_T *p_dir, UNI_NAME_T *p_uniname, INT32 num_entries, DOS_NAME_T *p_dosname, UINT32 type); + INT32 exfat_find_dir_entry(struct super_block *sb, CHAIN_T *p_dir, UNI_NAME_T *p_uniname, INT32 num_entries, DOS_NAME_T *p_dosname, UINT32 type); + INT32 fat_count_ext_entries(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, DENTRY_T *p_entry); + INT32 exfat_count_ext_entries(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, DENTRY_T *p_entry); + INT32 count_dos_name_entries(struct super_block *sb, CHAIN_T *p_dir, UINT32 type); + void update_dir_checksum(struct super_block *sb, CHAIN_T *p_dir, INT32 entry); + void update_dir_checksum_with_entry_set (struct super_block *sb, ENTRY_SET_CACHE_T *es); + BOOL is_dir_empty(struct super_block *sb, CHAIN_T *p_dir); + + /* name conversion functions */ + INT32 get_num_entries_and_dos_name(struct super_block *sb, CHAIN_T *p_dir, UNI_NAME_T *p_uniname, INT32 *entries, DOS_NAME_T *p_dosname); + void get_uni_name_from_dos_entry(struct super_block *sb, DOS_DENTRY_T *ep, UNI_NAME_T *p_uniname, UINT8 mode); + void fat_get_uni_name_from_ext_entry(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, UINT16 *uniname); + void exfat_get_uni_name_from_ext_entry(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, UINT16 *uniname); + INT32 extract_uni_name_from_ext_entry(EXT_DENTRY_T *ep, UINT16 *uniname, INT32 order); + INT32 extract_uni_name_from_name_entry(NAME_DENTRY_T *ep, UINT16 *uniname, INT32 order); + INT32 fat_generate_dos_name(struct super_block *sb, CHAIN_T *p_dir, DOS_NAME_T *p_dosname); + void fat_attach_count_to_dos_name(UINT8 *dosname, INT32 count); + INT32 fat_calc_num_entries(UNI_NAME_T *p_uniname); + INT32 exfat_calc_num_entries(UNI_NAME_T *p_uniname); + UINT8 calc_checksum_1byte(void *data, INT32 len, UINT8 chksum); + UINT16 calc_checksum_2byte(void *data, INT32 len, UINT16 chksum, INT32 type); + UINT32 calc_checksum_4byte(void *data, INT32 len, UINT32 chksum, INT32 type); + + /* name resolution functions */ + INT32 resolve_path(struct inode *inode, UINT8 *path, CHAIN_T *p_dir, UNI_NAME_T *p_uniname); + INT32 resolve_name(UINT8 *name, UINT8 **arg); + + /* file operation functions */ + INT32 fat16_mount(struct super_block *sb, PBR_SECTOR_T *p_pbr); + INT32 fat32_mount(struct super_block *sb, PBR_SECTOR_T *p_pbr); + INT32 exfat_mount(struct super_block *sb, PBR_SECTOR_T *p_pbr); + INT32 create_dir(struct inode *inode, CHAIN_T *p_dir, UNI_NAME_T *p_uniname, FILE_ID_T *fid); + INT32 create_file(struct inode *inode, CHAIN_T *p_dir, UNI_NAME_T *p_uniname, UINT8 mode, FILE_ID_T *fid); + void remove_file(struct inode *inode, CHAIN_T *p_dir, INT32 entry); + INT32 rename_file(struct inode *inode, CHAIN_T *p_dir, INT32 old_entry, UNI_NAME_T *p_uniname, FILE_ID_T *fid); + INT32 move_file(struct inode *inode, CHAIN_T *p_olddir, INT32 oldentry, CHAIN_T *p_newdir, UNI_NAME_T *p_uniname, FILE_ID_T *fid); + + /* sector read/write functions */ + INT32 sector_read(struct super_block *sb, UINT32 sec, struct buffer_head **bh, INT32 read); + INT32 sector_write(struct super_block *sb, UINT32 sec, struct buffer_head *bh, INT32 sync); + INT32 multi_sector_read(struct super_block *sb, UINT32 sec, struct buffer_head **bh, INT32 num_secs, INT32 read); + INT32 multi_sector_write(struct super_block *sb, UINT32 sec, struct buffer_head *bh, INT32 num_secs, INT32 sync); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _EXFAT_H */ + +/* end of exfat.h */ diff --git a/fs/exfat/exfat_api.c b/fs/exfat/exfat_api.c new file mode 100644 index 00000000000..5423181260b --- /dev/null +++ b/fs/exfat/exfat_api.c @@ -0,0 +1,563 @@ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * 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. + */ + +/************************************************************************/ +/* */ +/* PROJECT : exFAT & FAT12/16/32 File System */ +/* FILE : exfat_api.c */ +/* PURPOSE : exFAT API Glue Layer */ +/* */ +/*----------------------------------------------------------------------*/ +/* NOTES */ +/* */ +/*----------------------------------------------------------------------*/ +/* REVISION HISTORY (Ver 0.9) */ +/* */ +/* - 2010.11.15 [Joosun Hahn] : first writing */ +/* */ +/************************************************************************/ + +#include +#include +#include + +#include "exfat_version.h" +#include "exfat_config.h" +#include "exfat_global.h" +#include "exfat_data.h" +#include "exfat_oal.h" + +#include "exfat_part.h" +#include "exfat_nls.h" +#include "exfat_api.h" +#include "exfat_super.h" +#include "exfat.h" + +/*----------------------------------------------------------------------*/ +/* Constant & Macro Definitions */ +/*----------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------*/ +/* Global Variable Definitions */ +/*----------------------------------------------------------------------*/ + +extern FS_STRUCT_T fs_struct[]; + +extern struct semaphore z_sem; + +/*----------------------------------------------------------------------*/ +/* Local Variable Definitions */ +/*----------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------*/ +/* Local Function Declarations */ +/*----------------------------------------------------------------------*/ + +/*======================================================================*/ +/* Global Function Definitions */ +/* - All functions for global use have same return value format, */ +/* that is, FFS_SUCCESS on success and several FS error code on */ +/* various error condition. */ +/*======================================================================*/ + +/*----------------------------------------------------------------------*/ +/* exFAT Filesystem Init & Exit Functions */ +/*----------------------------------------------------------------------*/ + +INT32 FsInit(void) +{ + INT32 i; + + /* initialize all volumes as un-mounted */ + for (i = 0; i < MAX_DRIVE; i++) { + fs_struct[i].mounted = FALSE; + fs_struct[i].sb = NULL; + sm_init(&(fs_struct[i].v_sem)); + } + + return(ffsInit()); +} + +INT32 FsShutdown(void) +{ + INT32 i; + + /* unmount all volumes */ + for (i = 0; i < MAX_DRIVE; i++) { + if (!fs_struct[i].mounted) continue; + + ffsUmountVol(fs_struct[i].sb); + } + + return(ffsShutdown()); +} + +/*----------------------------------------------------------------------*/ +/* Volume Management Functions */ +/*----------------------------------------------------------------------*/ + +/* FsMountVol : mount the file system volume */ +INT32 FsMountVol(struct super_block *sb) +{ + INT32 err, drv; + + sm_P(&z_sem); + + for (drv = 0; drv < MAX_DRIVE; drv++) { + if (!fs_struct[drv].mounted) break; + } + + if (drv >= MAX_DRIVE) return(FFS_ERROR); + + /* acquire the lock for file system critical section */ + sm_P(&(fs_struct[drv].v_sem)); + + err = buf_init(sb); + if (!err) { + err = ffsMountVol(sb, drv); + } + + /* release the lock for file system critical section */ + sm_V(&(fs_struct[drv].v_sem)); + + if (!err) { + fs_struct[drv].mounted = TRUE; + fs_struct[drv].sb = sb; + } else { + buf_shutdown(sb); + } + + sm_V(&z_sem); + + return(err); +} /* end of FsMountVol */ + +/* FsUmountVol : unmount the file system volume */ +INT32 FsUmountVol(struct super_block *sb) +{ + INT32 err; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + sm_P(&z_sem); + + /* acquire the lock for file system critical section */ + sm_P(&(fs_struct[p_fs->drv].v_sem)); + + err = ffsUmountVol(sb); + buf_shutdown(sb); + + /* release the lock for file system critical section */ + sm_V(&(fs_struct[p_fs->drv].v_sem)); + + fs_struct[p_fs->drv].mounted = FALSE; + fs_struct[p_fs->drv].sb = NULL; + + sm_V(&z_sem); + + return(err); +} /* end of FsUmountVol */ + +/* FsGetVolInfo : get the information of a file system volume */ +INT32 FsGetVolInfo(struct super_block *sb, VOL_INFO_T *info) +{ + INT32 err; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + /* check the validity of pointer parameters */ + if (info == NULL) return(FFS_ERROR); + + /* acquire the lock for file system critical section */ + sm_P(&(fs_struct[p_fs->drv].v_sem)); + + err = ffsGetVolInfo(sb, info); + + /* release the lock for file system critical section */ + sm_V(&(fs_struct[p_fs->drv].v_sem)); + + return(err); +} /* end of FsGetVolInfo */ + +/* FsSyncVol : synchronize a file system volume */ +INT32 FsSyncVol(struct super_block *sb, INT32 do_sync) +{ + INT32 err; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + /* acquire the lock for file system critical section */ + sm_P(&(fs_struct[p_fs->drv].v_sem)); + + err = ffsSyncVol(sb, do_sync); + + /* release the lock for file system critical section */ + sm_V(&(fs_struct[p_fs->drv].v_sem)); + + return(err); +} /* end of FsSyncVol */ + + +/*----------------------------------------------------------------------*/ +/* File Operation Functions */ +/*----------------------------------------------------------------------*/ + +/* FsCreateFile : create a file */ +INT32 FsLookupFile(struct inode *inode, UINT8 *path, FILE_ID_T *fid) +{ + INT32 err; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + /* check the validity of pointer parameters */ + if ((fid == NULL) || (path == NULL) || (*path == '\0')) + return(FFS_ERROR); + + /* acquire the lock for file system critical section */ + sm_P(&(fs_struct[p_fs->drv].v_sem)); + + err = ffsLookupFile(inode, path, fid); + + /* release the lock for file system critical section */ + sm_V(&(fs_struct[p_fs->drv].v_sem)); + + return(err); +} /* end of FsLookupFile */ + +/* FsCreateFile : create a file */ +INT32 FsCreateFile(struct inode *inode, UINT8 *path, UINT8 mode, FILE_ID_T *fid) +{ + INT32 err; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + /* check the validity of pointer parameters */ + if ((fid == NULL) || (path == NULL) || (*path == '\0')) + return(FFS_ERROR); + + /* acquire the lock for file system critical section */ + sm_P(&(fs_struct[p_fs->drv].v_sem)); + + err = ffsCreateFile(inode, path, mode, fid); + + /* release the lock for file system critical section */ + sm_V(&(fs_struct[p_fs->drv].v_sem)); + + return(err); +} /* end of FsCreateFile */ + +INT32 FsReadFile(struct inode *inode, FILE_ID_T *fid, void *buffer, UINT64 count, UINT64 *rcount) +{ + INT32 err; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + /* check the validity of the given file id */ + if (fid == NULL) return(FFS_INVALIDFID); + + /* check the validity of pointer parameters */ + if (buffer == NULL) return(FFS_ERROR); + + /* acquire the lock for file system critical section */ + sm_P(&(fs_struct[p_fs->drv].v_sem)); + + err = ffsReadFile(inode, fid, buffer, count, rcount); + + /* release the lock for file system critical section */ + sm_V(&(fs_struct[p_fs->drv].v_sem)); + + return(err); +} /* end of FsReadFile */ + +INT32 FsWriteFile(struct inode *inode, FILE_ID_T *fid, void *buffer, UINT64 count, UINT64 *wcount) +{ + INT32 err; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + /* check the validity of the given file id */ + if (fid == NULL) return(FFS_INVALIDFID); + + /* check the validity of pointer parameters */ + if (buffer == NULL) return(FFS_ERROR); + + /* acquire the lock for file system critical section */ + sm_P(&(fs_struct[p_fs->drv].v_sem)); + + err = ffsWriteFile(inode, fid, buffer, count, wcount); + + /* release the lock for file system critical section */ + sm_V(&(fs_struct[p_fs->drv].v_sem)); + + return(err); +} /* end of FsWriteFile */ + +/* FsTruncateFile : resize the file length */ +INT32 FsTruncateFile(struct inode *inode, UINT64 old_size, UINT64 new_size) +{ + INT32 err; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + /* acquire the lock for file system critical section */ + sm_P(&(fs_struct[p_fs->drv].v_sem)); + + PRINTK("FsTruncateFile entered (inode %p size %llu)\n", inode, new_size); + + err = ffsTruncateFile(inode, old_size, new_size); + + PRINTK("FsTruncateFile exitted (%d)\n", err); + + /* release the lock for file system critical section */ + sm_V(&(fs_struct[p_fs->drv].v_sem)); + + return(err); +} /* end of FsTruncateFile */ + +/* FsMoveFile : move(rename) a old file into a new file */ +INT32 FsMoveFile(struct inode *old_parent_inode, FILE_ID_T *fid, struct inode *new_parent_inode, struct dentry *new_dentry) +{ + INT32 err; + struct super_block *sb = old_parent_inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + /* check the validity of the given file id */ + if (fid == NULL) return(FFS_INVALIDFID); + + /* acquire the lock for file system critical section */ + sm_P(&(fs_struct[p_fs->drv].v_sem)); + + err = ffsMoveFile(old_parent_inode, fid, new_parent_inode, new_dentry); + + /* release the lock for file system critical section */ + sm_V(&(fs_struct[p_fs->drv].v_sem)); + + return(err); +} /* end of FsMoveFile */ + +/* FsRemoveFile : remove a file */ +INT32 FsRemoveFile(struct inode *inode, FILE_ID_T *fid) +{ + INT32 err; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + /* check the validity of the given file id */ + if (fid == NULL) return(FFS_INVALIDFID); + + /* acquire the lock for file system critical section */ + sm_P(&(fs_struct[p_fs->drv].v_sem)); + + err = ffsRemoveFile(inode, fid); + + /* release the lock for file system critical section */ + sm_V(&(fs_struct[p_fs->drv].v_sem)); + + return(err); +} /* end of FsRemoveFile */ + +/* FsSetAttr : set the attribute of a given file */ +INT32 FsSetAttr(struct inode *inode, UINT32 attr) +{ + INT32 err; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + /* acquire the lock for file system critical section */ + sm_P(&(fs_struct[p_fs->drv].v_sem)); + + err = ffsSetAttr(inode, attr); + + /* release the lock for file system critical section */ + sm_V(&(fs_struct[p_fs->drv].v_sem)); + + return(err); +} /* end of FsSetAttr */ + +/* FsReadStat : get the information of a given file */ +INT32 FsReadStat(struct inode *inode, DIR_ENTRY_T *info) +{ + INT32 err; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + /* acquire the lock for file system critical section */ + sm_P(&(fs_struct[p_fs->drv].v_sem)); + + err = ffsGetStat(inode, info); + + /* release the lock for file system critical section */ + sm_V(&(fs_struct[p_fs->drv].v_sem)); + + return(err); +} /* end of FsReadStat */ + +/* FsWriteStat : set the information of a given file */ +INT32 FsWriteStat(struct inode *inode, DIR_ENTRY_T *info) +{ + INT32 err; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + /* acquire the lock for file system critical section */ + sm_P(&(fs_struct[p_fs->drv].v_sem)); + + PRINTK("FsWriteStat entered (inode %p info %p\n", inode, info); + + err = ffsSetStat(inode, info); + + /* release the lock for file system critical section */ + sm_V(&(fs_struct[p_fs->drv].v_sem)); + + PRINTK("FsWriteStat exited (%d)\n", err); + + return(err); +} /* end of FsWriteStat */ + +/* FsMapCluster : return the cluster number in the given cluster offset */ +INT32 FsMapCluster(struct inode *inode, INT32 clu_offset, UINT32 *clu) +{ + INT32 err; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + /* check the validity of pointer parameters */ + if (clu == NULL) return(FFS_ERROR); + + /* acquire the lock for file system critical section */ + sm_P(&(fs_struct[p_fs->drv].v_sem)); + + err = ffsMapCluster(inode, clu_offset, clu); + + /* release the lock for file system critical section */ + sm_V(&(fs_struct[p_fs->drv].v_sem)); + + return(err); +} /* end of FsMapCluster */ + +/*----------------------------------------------------------------------*/ +/* Directory Operation Functions */ +/*----------------------------------------------------------------------*/ + +/* FsCreateDir : create(make) a directory */ +INT32 FsCreateDir(struct inode *inode, UINT8 *path, FILE_ID_T *fid) +{ + INT32 err; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + /* check the validity of pointer parameters */ + if ((fid == NULL) || (path == NULL) || (*path == '\0')) + return(FFS_ERROR); + + /* acquire the lock for file system critical section */ + sm_P(&(fs_struct[p_fs->drv].v_sem)); + + err = ffsCreateDir(inode, path, fid); + + /* release the lock for file system critical section */ + sm_V(&(fs_struct[p_fs->drv].v_sem)); + + return(err); +} /* end of FsCreateDir */ + +/* FsReadDir : read a directory entry from the opened directory */ +INT32 FsReadDir(struct inode *inode, DIR_ENTRY_T *dir_entry) +{ + INT32 err; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + /* check the validity of pointer parameters */ + if (dir_entry == NULL) return(FFS_ERROR); + + /* acquire the lock for file system critical section */ + sm_P(&(fs_struct[p_fs->drv].v_sem)); + + err = ffsReadDir(inode, dir_entry); + + /* release the lock for file system critical section */ + sm_V(&(fs_struct[p_fs->drv].v_sem)); + + return(err); +} /* end of FsReadDir */ + +/* FsRemoveDir : remove a directory */ +INT32 FsRemoveDir(struct inode *inode, FILE_ID_T *fid) +{ + INT32 err; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + /* check the validity of the given file id */ + if (fid == NULL) return(FFS_INVALIDFID); + + /* acquire the lock for file system critical section */ + sm_P(&(fs_struct[p_fs->drv].v_sem)); + + err = ffsRemoveDir(inode, fid); + + /* release the lock for file system critical section */ + sm_V(&(fs_struct[p_fs->drv].v_sem)); + + return(err); +} /* end of FsRemoveDir */ + +EXPORT_SYMBOL(FsMountVol); +EXPORT_SYMBOL(FsUmountVol); +EXPORT_SYMBOL(FsGetVolInfo); +EXPORT_SYMBOL(FsSyncVol); +EXPORT_SYMBOL(FsLookupFile); +EXPORT_SYMBOL(FsCreateFile); +EXPORT_SYMBOL(FsReadFile); +EXPORT_SYMBOL(FsWriteFile); +EXPORT_SYMBOL(FsTruncateFile); +EXPORT_SYMBOL(FsMoveFile); +EXPORT_SYMBOL(FsRemoveFile); +EXPORT_SYMBOL(FsSetAttr); +EXPORT_SYMBOL(FsReadStat); +EXPORT_SYMBOL(FsWriteStat); +EXPORT_SYMBOL(FsMapCluster); +EXPORT_SYMBOL(FsCreateDir); +EXPORT_SYMBOL(FsReadDir); +EXPORT_SYMBOL(FsRemoveDir); + +#if EXFAT_CONFIG_KERNEL_DEBUG +/* FsReleaseCache: Release FAT & buf cache */ +INT32 FsReleaseCache(struct super_block *sb) +{ + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + /* acquire the lock for file system critical section */ + sm_P(&(fs_struct[p_fs->drv].v_sem)); + + FAT_release_all(sb); + buf_release_all(sb); + + /* release the lock for file system critical section */ + sm_V(&(fs_struct[p_fs->drv].v_sem)); + + return 0; +} +/* FsReleaseCache */ + +EXPORT_SYMBOL(FsReleaseCache); +#endif /* EXFAT_CONFIG_KERNEL_DEBUG */ + +/*======================================================================*/ +/* Local Function Definitions */ +/*======================================================================*/ + +/* end of exfat_api.c */ diff --git a/fs/exfat/exfat_api.h b/fs/exfat/exfat_api.h new file mode 100644 index 00000000000..d89b8fed596 --- /dev/null +++ b/fs/exfat/exfat_api.h @@ -0,0 +1,221 @@ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * 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. + */ + +/************************************************************************/ +/* */ +/* PROJECT : exFAT & FAT12/16/32 File System */ +/* FILE : exfat_api.h */ +/* PURPOSE : Header File for exFAT API Glue Layer */ +/* */ +/*----------------------------------------------------------------------*/ +/* NOTES */ +/* */ +/*----------------------------------------------------------------------*/ +/* REVISION HISTORY (Ver 0.9) */ +/* */ +/* - 2010.11.15 [Joosun Hahn] : first writing */ +/* */ +/************************************************************************/ + +#ifndef _EXFAT_API_H +#define _EXFAT_API_H + +#include "exfat_config.h" +#include "exfat_global.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + /*----------------------------------------------------------------------*/ + /* Constant & Macro Definitions */ + /*----------------------------------------------------------------------*/ + +#define EXFAT_SUPER_MAGIC (0x2011BAB0L) +#define EXFAT_ROOT_INO 1 + + /* FAT types */ +#define FAT12 0x01 // FAT12 +#define FAT16 0x0E // Win95 FAT16 (LBA) +#define FAT32 0x0C // Win95 FAT32 (LBA) +#define EXFAT 0x07 // exFAT + + /* file name lengths */ +#define MAX_CHARSET_SIZE 3 // max size of multi-byte character +#define MAX_PATH_DEPTH 15 // max depth of path name +#define MAX_NAME_LENGTH 256 // max len of file name including NULL +#define MAX_PATH_LENGTH 260 // max len of path name including NULL +#define DOS_NAME_LENGTH 11 // DOS file name length excluding NULL +#define DOS_PATH_LENGTH 80 // DOS path name length excluding NULL + + /* file attributes */ +#define ATTR_NORMAL 0x0000 +#define ATTR_READONLY 0x0001 +#define ATTR_HIDDEN 0x0002 +#define ATTR_SYSTEM 0x0004 +#define ATTR_VOLUME 0x0008 +#define ATTR_SUBDIR 0x0010 +#define ATTR_ARCHIVE 0x0020 +#define ATTR_SYMLINK 0x0040 +#define ATTR_EXTEND 0x000F +#define ATTR_RWMASK 0x007E + + /* file creation modes */ +#define FM_REGULAR 0x00 +#define FM_SYMLINK 0x40 + + /* return values */ +#define FFS_SUCCESS 0 +#define FFS_MEDIAERR 1 +#define FFS_FORMATERR 2 +#define FFS_MOUNTED 3 +#define FFS_NOTMOUNTED 4 +#define FFS_ALIGNMENTERR 5 +#define FFS_SEMAPHOREERR 6 +#define FFS_INVALIDPATH 7 +#define FFS_INVALIDFID 8 +#define FFS_NOTFOUND 9 +#define FFS_FILEEXIST 10 +#define FFS_PERMISSIONERR 11 +#define FFS_NOTOPENED 12 +#define FFS_MAXOPENED 13 +#define FFS_FULL 14 +#define FFS_EOF 15 +#define FFS_DIRBUSY 16 +#define FFS_MEMORYERR 17 +#define FFS_NAMETOOLONG 18 +#define FFS_ERROR 19 // generic error code + + /*----------------------------------------------------------------------*/ + /* Type Definitions */ + /*----------------------------------------------------------------------*/ + + typedef struct { + UINT16 Year; + UINT16 Month; + UINT16 Day; + UINT16 Hour; + UINT16 Minute; + UINT16 Second; + UINT16 MilliSecond; + } DATE_TIME_T; + + typedef struct { + UINT32 Offset; // start sector number of the partition + UINT32 Size; // in sectors + } PART_INFO_T; + + typedef struct { + UINT32 SecSize; // sector size in bytes + UINT32 DevSize; // block device size in sectors + } DEV_INFO_T; + + typedef struct { + UINT32 FatType; + UINT32 ClusterSize; + UINT32 NumClusters; + UINT32 FreeClusters; + UINT32 UsedClusters; + } VOL_INFO_T; + + /* directory structure */ + typedef struct { + UINT32 dir; + INT32 size; + UINT8 flags; + } CHAIN_T; + + /* file id structure */ + typedef struct { + CHAIN_T dir; + UINT8 flags; + INT32 entry; + UINT32 type; + UINT32 attr; + UINT32 start_clu; + INT32 hint_last_off; + UINT32 hint_last_clu; + INT64 rwoffset; + UINT64 size; + } FILE_ID_T; + + typedef struct { + INT8 Name[MAX_NAME_LENGTH *MAX_CHARSET_SIZE]; + INT8 ShortName[DOS_NAME_LENGTH + 2]; // used only for FAT12/16/32, not used for exFAT + UINT32 Attr; + UINT64 Size; + UINT32 NumSubdirs; + DATE_TIME_T CreateTimestamp; + DATE_TIME_T ModifyTimestamp; + DATE_TIME_T AccessTimestamp; + } DIR_ENTRY_T; + + /*======================================================================*/ + /* */ + /* API FUNCTION DECLARATIONS */ + /* (CHANGE THIS PART IF REQUIRED) */ + /* */ + /*======================================================================*/ + + /*----------------------------------------------------------------------*/ + /* External Function Declarations */ + /*----------------------------------------------------------------------*/ + + /* file system initialization & shutdown functions */ + INT32 FsInit(void); + INT32 FsShutdown(void); + + /* volume management functions */ + INT32 FsMountVol(struct super_block *sb); + INT32 FsUmountVol(struct super_block *sb); + INT32 FsGetVolInfo(struct super_block *sb, VOL_INFO_T *info); + INT32 FsSyncVol(struct super_block *sb, INT32 do_sync); + + /* file management functions */ + INT32 FsLookupFile(struct inode *inode, UINT8 *path, FILE_ID_T *fid); + INT32 FsCreateFile(struct inode *inode, UINT8 *path, UINT8 mode, FILE_ID_T *fid); + INT32 FsReadFile(struct inode *inode, FILE_ID_T *fid, void *buffer, UINT64 count, UINT64 *rcount); + INT32 FsWriteFile(struct inode *inode, FILE_ID_T *fid, void *buffer, UINT64 count, UINT64 *wcount); + INT32 FsTruncateFile(struct inode *inode, UINT64 old_size, UINT64 new_size); + INT32 FsMoveFile(struct inode *old_parent_inode, FILE_ID_T *fid, struct inode *new_parent_inode, struct dentry *new_dentry); + INT32 FsRemoveFile(struct inode *inode, FILE_ID_T *fid); + INT32 FsSetAttr(struct inode *inode, UINT32 attr); + INT32 FsReadStat(struct inode *inode, DIR_ENTRY_T *info); + INT32 FsWriteStat(struct inode *inode, DIR_ENTRY_T *info); + INT32 FsMapCluster(struct inode *inode, INT32 clu_offset, UINT32 *clu); + + /* directory management functions */ + INT32 FsCreateDir(struct inode *inode, UINT8 *path, FILE_ID_T *fid); + INT32 FsReadDir(struct inode *inode, DIR_ENTRY_T *dir_entry); + INT32 FsRemoveDir(struct inode *inode, FILE_ID_T *fid); + + /* debug functions */ + INT32 FsReleaseCache(struct super_block *sb); + + /* partition management functions */ +//INT32 FsSetPartition(INT32 dev, INT32 num_vol, PART_INFO_T *vol_spec); +//INT32 FsGetPartition(INT32 dev, INT32 *num_vol, PART_INFO_T *vol_spec); +//INT32 FsGetDevInfo(INT32 dev, DEV_INFO_T *info); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _EXFAT_API_H */ + +/* end of exfat_api.h */ diff --git a/fs/exfat/exfat_blkdev.c b/fs/exfat/exfat_blkdev.c new file mode 100644 index 00000000000..154b444b26f --- /dev/null +++ b/fs/exfat/exfat_blkdev.c @@ -0,0 +1,190 @@ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * 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. + */ + +/************************************************************************/ +/* */ +/* PROJECT : exFAT & FAT12/16/32 File System */ +/* FILE : exfat_blkdev.c */ +/* PURPOSE : exFAT Block Device Driver Glue Layer */ +/* */ +/*----------------------------------------------------------------------*/ +/* NOTES */ +/* */ +/*----------------------------------------------------------------------*/ +/* REVISION HISTORY (Ver 0.9) */ +/* */ +/* - 2010.11.15 [Joosun Hahn] : first writing */ +/* */ +/************************************************************************/ + +#include + +#include "exfat_config.h" +#include "exfat_global.h" +#include "exfat_blkdev.h" +#include "exfat_data.h" +#include "exfat_api.h" +#include "exfat_super.h" + +/*----------------------------------------------------------------------*/ +/* Constant & Macro Definitions */ +/*----------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------*/ +/* Global Variable Definitions */ +/*----------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------*/ +/* Local Variable Definitions */ +/*----------------------------------------------------------------------*/ + +/*======================================================================*/ +/* Function Definitions */ +/*======================================================================*/ + +INT32 bdev_init(void) +{ + return(FFS_SUCCESS); +} + +INT32 bdev_shutdown(void) +{ + return(FFS_SUCCESS); +} + +INT32 bdev_open(struct super_block *sb) +{ + BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); + + if (p_bd->opened) return(FFS_SUCCESS); + + p_bd->sector_size = bdev_logical_block_size(sb->s_bdev); + p_bd->sector_size_bits = my_log2(p_bd->sector_size); + p_bd->sector_size_mask = p_bd->sector_size - 1; + p_bd->num_sectors = i_size_read(sb->s_bdev->bd_inode) >> p_bd->sector_size_bits; + + p_bd->opened = TRUE; + + return(FFS_SUCCESS); +} + +INT32 bdev_close(struct super_block *sb) +{ + BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); + + if (!p_bd->opened) return(FFS_SUCCESS); + + p_bd->opened = FALSE; + return(FFS_SUCCESS); +} + +INT32 bdev_read(struct super_block *sb, UINT32 secno, struct buffer_head **bh, UINT32 num_secs, INT32 read) +{ + BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); +#if EXFAT_CONFIG_KERNEL_DEBUG + struct exfat_sb_info *sbi = EXFAT_SB(sb); + long flags = sbi->debug_flags; + + if (flags & EXFAT_DEBUGFLAGS_ERROR_RW) return (FFS_MEDIAERR); +#endif /* EXFAT_CONFIG_KERNEL_DEBUG */ + + if (!p_bd->opened) return(FFS_MEDIAERR); + + if (*bh) __brelse(*bh); + + if (read) + *bh = __bread(sb->s_bdev, secno, num_secs << p_bd->sector_size_bits); + else + *bh = __getblk(sb->s_bdev, secno, num_secs << p_bd->sector_size_bits); + + if (*bh) return(FFS_SUCCESS); + + WARN(!p_fs->dev_ejected, + "[EXFAT] No bh, device seems wrong or to be ejected.\n"); + + return(FFS_MEDIAERR); +} + +INT32 bdev_write(struct super_block *sb, UINT32 secno, struct buffer_head *bh, UINT32 num_secs, INT32 sync) +{ + INT32 count; + struct buffer_head *bh2; + BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); +#if EXFAT_CONFIG_KERNEL_DEBUG + struct exfat_sb_info *sbi = EXFAT_SB(sb); + long flags = sbi->debug_flags; + + if (flags & EXFAT_DEBUGFLAGS_ERROR_RW) return (FFS_MEDIAERR); +#endif /* EXFAT_CONFIG_KERNEL_DEBUG */ + + if (!p_bd->opened) return(FFS_MEDIAERR); + + if (secno == bh->b_blocknr) { + lock_buffer(bh); + set_buffer_uptodate(bh); + mark_buffer_dirty(bh); + unlock_buffer(bh); + if (sync && (sync_dirty_buffer(bh) != 0)) + return (FFS_MEDIAERR); + } else { + count = num_secs << p_bd->sector_size_bits; + + bh2 = __getblk(sb->s_bdev, secno, count); + + if (bh2 == NULL) + goto no_bh; + + lock_buffer(bh2); + MEMCPY(bh2->b_data, bh->b_data, count); + set_buffer_uptodate(bh2); + mark_buffer_dirty(bh2); + unlock_buffer(bh2); + if (sync && (sync_dirty_buffer(bh2) != 0)) { + __brelse(bh2); + goto no_bh; + } + __brelse(bh2); + } + + return(FFS_SUCCESS); + +no_bh: + WARN(!p_fs->dev_ejected, + "[EXFAT] No bh, device seems wrong or to be ejected.\n"); + + return (FFS_MEDIAERR); +} + +INT32 bdev_sync(struct super_block *sb) +{ + BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); +#if EXFAT_CONFIG_KERNEL_DEBUG + struct exfat_sb_info *sbi = EXFAT_SB(sb); + long flags = sbi->debug_flags; + + if (flags & EXFAT_DEBUGFLAGS_ERROR_RW) return (FFS_MEDIAERR); +#endif /* EXFAT_CONFIG_KERNEL_DEBUG */ + + if (!p_bd->opened) return(FFS_MEDIAERR); + + return sync_blockdev(sb->s_bdev); +} + +/* end of exfat_blkdev.c */ diff --git a/fs/exfat/exfat_blkdev.h b/fs/exfat/exfat_blkdev.h new file mode 100644 index 00000000000..c1f0c28cacb --- /dev/null +++ b/fs/exfat/exfat_blkdev.h @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * 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. + */ + +/************************************************************************/ +/* */ +/* PROJECT : exFAT & FAT12/16/32 File System */ +/* FILE : exfat_blkdev.h */ +/* PURPOSE : Header File for exFAT Block Device Driver Glue Layer */ +/* */ +/*----------------------------------------------------------------------*/ +/* NOTES */ +/* */ +/*----------------------------------------------------------------------*/ +/* REVISION HISTORY (Ver 0.9) */ +/* */ +/* - 2010.11.15 [Joosun Hahn] : first writing */ +/* */ +/************************************************************************/ + +#ifndef _EXFAT_BLKDEV_H +#define _EXFAT_BLKDEV_H + +#include "exfat_config.h" +#include "exfat_global.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + /*----------------------------------------------------------------------*/ + /* Constant & Macro Definitions (Non-Configurable) */ + /*----------------------------------------------------------------------*/ + + /*----------------------------------------------------------------------*/ + /* Type Definitions */ + /*----------------------------------------------------------------------*/ + + typedef struct __BD_INFO_T { + INT32 sector_size; // in bytes + INT32 sector_size_bits; + INT32 sector_size_mask; + INT32 num_sectors; // total number of sectors in this block device + BOOL opened; // opened or not + } BD_INFO_T; + + /*----------------------------------------------------------------------*/ + /* External Variable Declarations */ + /*----------------------------------------------------------------------*/ + + /*----------------------------------------------------------------------*/ + /* External Function Declarations */ + /*----------------------------------------------------------------------*/ + + INT32 bdev_init(void); + INT32 bdev_shutdown(void); + INT32 bdev_open(struct super_block *sb); + INT32 bdev_close(struct super_block *sb); + INT32 bdev_read(struct super_block *sb, UINT32 secno, struct buffer_head **bh, UINT32 num_secs, INT32 read); + INT32 bdev_write(struct super_block *sb, UINT32 secno, struct buffer_head *bh, UINT32 num_secs, INT32 sync); + INT32 bdev_sync(struct super_block *sb); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _EXFAT_BLKDEV_H */ + +/* end of exfat_blkdev.h */ diff --git a/fs/exfat/exfat_cache.c b/fs/exfat/exfat_cache.c new file mode 100644 index 00000000000..05c61365301 --- /dev/null +++ b/fs/exfat/exfat_cache.c @@ -0,0 +1,785 @@ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * 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. + */ + +/************************************************************************/ +/* */ +/* PROJECT : exFAT & FAT12/16/32 File System */ +/* FILE : exfat_cache.c */ +/* PURPOSE : exFAT Cache Manager */ +/* (FAT Cache & Buffer Cache) */ +/* */ +/*----------------------------------------------------------------------*/ +/* NOTES */ +/* */ +/*----------------------------------------------------------------------*/ +/* REVISION HISTORY (Ver 0.9) */ +/* */ +/* - 2010.11.15 [Sung-Kwan Kim] : first writing */ +/* */ +/************************************************************************/ + +#include "exfat_config.h" +#include "exfat_global.h" +#include "exfat_data.h" + +#include "exfat_cache.h" +#include "exfat_super.h" +#include "exfat.h" + +/*----------------------------------------------------------------------*/ +/* Global Variable Definitions */ +/*----------------------------------------------------------------------*/ + +extern FS_STRUCT_T fs_struct[]; + +#define sm_P(s) +#define sm_V(s) + +static INT32 __FAT_read(struct super_block *sb, UINT32 loc, UINT32 *content); +static INT32 __FAT_write(struct super_block *sb, UINT32 loc, UINT32 content); + +static BUF_CACHE_T *FAT_cache_find(struct super_block *sb, UINT32 sec); +static BUF_CACHE_T *FAT_cache_get(struct super_block *sb, UINT32 sec); +static void FAT_cache_insert_hash(struct super_block *sb, BUF_CACHE_T *bp); +static void FAT_cache_remove_hash(BUF_CACHE_T *bp); + +static UINT8 *__buf_getblk(struct super_block *sb, UINT32 sec); + +static BUF_CACHE_T *buf_cache_find(struct super_block *sb, UINT32 sec); +static BUF_CACHE_T *buf_cache_get(struct super_block *sb, UINT32 sec); +static void buf_cache_insert_hash(struct super_block *sb, BUF_CACHE_T *bp); +static void buf_cache_remove_hash(BUF_CACHE_T *bp); + +static void push_to_mru(BUF_CACHE_T *bp, BUF_CACHE_T *list); +static void push_to_lru(BUF_CACHE_T *bp, BUF_CACHE_T *list); +static void move_to_mru(BUF_CACHE_T *bp, BUF_CACHE_T *list); +static void move_to_lru(BUF_CACHE_T *bp, BUF_CACHE_T *list); + +/*======================================================================*/ +/* Cache Initialization Functions */ +/*======================================================================*/ + +INT32 buf_init(struct super_block *sb) +{ + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + INT32 i; + + /* LRU list */ + p_fs->FAT_cache_lru_list.next = p_fs->FAT_cache_lru_list.prev = &p_fs->FAT_cache_lru_list; + + for (i = 0; i < FAT_CACHE_SIZE; i++) { + p_fs->FAT_cache_array[i].drv = -1; + p_fs->FAT_cache_array[i].sec = ~0; + p_fs->FAT_cache_array[i].flag = 0; + p_fs->FAT_cache_array[i].buf_bh = NULL; + p_fs->FAT_cache_array[i].prev = p_fs->FAT_cache_array[i].next = NULL; + push_to_mru(&(p_fs->FAT_cache_array[i]), &p_fs->FAT_cache_lru_list); + } + + p_fs->buf_cache_lru_list.next = p_fs->buf_cache_lru_list.prev = &p_fs->buf_cache_lru_list; + + for (i = 0; i < BUF_CACHE_SIZE; i++) { + p_fs->buf_cache_array[i].drv = -1; + p_fs->buf_cache_array[i].sec = ~0; + p_fs->buf_cache_array[i].flag = 0; + p_fs->buf_cache_array[i].buf_bh = NULL; + p_fs->buf_cache_array[i].prev = p_fs->buf_cache_array[i].next = NULL; + push_to_mru(&(p_fs->buf_cache_array[i]), &p_fs->buf_cache_lru_list); + } + + /* HASH list */ + for (i = 0; i < FAT_CACHE_HASH_SIZE; i++) { + p_fs->FAT_cache_hash_list[i].drv = -1; + p_fs->FAT_cache_hash_list[i].sec = ~0; + p_fs->FAT_cache_hash_list[i].hash_next = p_fs->FAT_cache_hash_list[i].hash_prev = &(p_fs->FAT_cache_hash_list[i]); + } + + for (i = 0; i < FAT_CACHE_SIZE; i++) { + FAT_cache_insert_hash(sb, &(p_fs->FAT_cache_array[i])); + } + + for (i = 0; i < BUF_CACHE_HASH_SIZE; i++) { + p_fs->buf_cache_hash_list[i].drv = -1; + p_fs->buf_cache_hash_list[i].sec = ~0; + p_fs->buf_cache_hash_list[i].hash_next = p_fs->buf_cache_hash_list[i].hash_prev = &(p_fs->buf_cache_hash_list[i]); + } + + for (i = 0; i < BUF_CACHE_SIZE; i++) { + buf_cache_insert_hash(sb, &(p_fs->buf_cache_array[i])); + } + + return(FFS_SUCCESS); +} /* end of buf_init */ + +INT32 buf_shutdown(struct super_block *sb) +{ + return(FFS_SUCCESS); +} /* end of buf_shutdown */ + +/*======================================================================*/ +/* FAT Read/Write Functions */ +/*======================================================================*/ + +/* in : sb, loc + * out: content + * returns 0 on success + * -1 on error + */ +INT32 FAT_read(struct super_block *sb, UINT32 loc, UINT32 *content) +{ + INT32 ret; + + sm_P(&f_sem); + + ret = __FAT_read(sb, loc, content); + + sm_V(&f_sem); + + return(ret); +} /* end of FAT_read */ + +INT32 FAT_write(struct super_block *sb, UINT32 loc, UINT32 content) +{ + INT32 ret; + + sm_P(&f_sem); + + ret = __FAT_write(sb, loc, content); + + sm_V(&f_sem); + + return(ret); +} /* end of FAT_write */ + +static INT32 __FAT_read(struct super_block *sb, UINT32 loc, UINT32 *content) +{ + INT32 off; + UINT32 sec, _content; + UINT8 *fat_sector, *fat_entry; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); + + if (p_fs->vol_type == FAT12) { + sec = p_fs->FAT1_start_sector + ((loc + (loc >> 1)) >> p_bd->sector_size_bits); + off = (loc + (loc >> 1)) & p_bd->sector_size_mask; + + if (off == (p_bd->sector_size-1)) { + fat_sector = FAT_getblk(sb, sec); + if (!fat_sector) + return -1; + + _content = (UINT32) fat_sector[off]; + + fat_sector = FAT_getblk(sb, ++sec); + if (!fat_sector) + return -1; + + _content |= (UINT32) fat_sector[0] << 8; + } else { + fat_sector = FAT_getblk(sb, sec); + if (!fat_sector) + return -1; + + fat_entry = &(fat_sector[off]); + _content = GET16(fat_entry); + } + + if (loc & 1) _content >>= 4; + + _content &= 0x00000FFF; + + if (_content >= CLUSTER_16(0x0FF8)) { + *content = CLUSTER_32(~0); + return 0; + } else { + *content = CLUSTER_32(_content); + return 0; + } + } else if (p_fs->vol_type == FAT16) { + sec = p_fs->FAT1_start_sector + (loc >> (p_bd->sector_size_bits-1)); + off = (loc << 1) & p_bd->sector_size_mask; + + fat_sector = FAT_getblk(sb, sec); + if (!fat_sector) + return -1; + + fat_entry = &(fat_sector[off]); + + _content = GET16_A(fat_entry); + + _content &= 0x0000FFFF; + + if (_content >= CLUSTER_16(0xFFF8)) { + *content = CLUSTER_32(~0); + return 0; + } else { + *content = CLUSTER_32(_content); + return 0; + } + } else if (p_fs->vol_type == FAT32) { + sec = p_fs->FAT1_start_sector + (loc >> (p_bd->sector_size_bits-2)); + off = (loc << 2) & p_bd->sector_size_mask; + + fat_sector = FAT_getblk(sb, sec); + if (!fat_sector) + return -1; + + fat_entry = &(fat_sector[off]); + + _content = GET32_A(fat_entry); + + _content &= 0x0FFFFFFF; + + if (_content >= CLUSTER_32(0x0FFFFFF8)) { + *content = CLUSTER_32(~0); + return 0; + } else { + *content = CLUSTER_32(_content); + return 0; + } + } else { + sec = p_fs->FAT1_start_sector + (loc >> (p_bd->sector_size_bits-2)); + off = (loc << 2) & p_bd->sector_size_mask; + + fat_sector = FAT_getblk(sb, sec); + if (!fat_sector) + return -1; + + fat_entry = &(fat_sector[off]); + _content = GET32_A(fat_entry); + + if (_content >= CLUSTER_32(0xFFFFFFF8)) { + *content = CLUSTER_32(~0); + return 0; + } else { + *content = CLUSTER_32(_content); + return 0; + } + } + + *content = CLUSTER_32(~0); + return 0; +} /* end of __FAT_read */ + +static INT32 __FAT_write(struct super_block *sb, UINT32 loc, UINT32 content) +{ + INT32 off; + UINT32 sec; + UINT8 *fat_sector, *fat_entry; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); + + if (p_fs->vol_type == FAT12) { + + content &= 0x00000FFF; + + sec = p_fs->FAT1_start_sector + ((loc + (loc >> 1)) >> p_bd->sector_size_bits); + off = (loc + (loc >> 1)) & p_bd->sector_size_mask; + + fat_sector = FAT_getblk(sb, sec); + if (!fat_sector) + return -1; + + if (loc & 1) { /* odd */ + + content <<= 4; + + if (off == (p_bd->sector_size-1)) { + fat_sector[off] = (UINT8)(content | (fat_sector[off] & 0x0F)); + FAT_modify(sb, sec); + + fat_sector = FAT_getblk(sb, ++sec); + if (!fat_sector) + return -1; + + fat_sector[0] = (UINT8)(content >> 8); + } else { + fat_entry = &(fat_sector[off]); + content |= GET16(fat_entry) & 0x000F; + + SET16(fat_entry, content); + } + } else { /* even */ + fat_sector[off] = (UINT8)(content); + + if (off == (p_bd->sector_size-1)) { + fat_sector[off] = (UINT8)(content); + FAT_modify(sb, sec); + + fat_sector = FAT_getblk(sb, ++sec); + fat_sector[0] = (UINT8)((fat_sector[0] & 0xF0) | (content >> 8)); + } else { + fat_entry = &(fat_sector[off]); + content |= GET16(fat_entry) & 0xF000; + + SET16(fat_entry, content); + } + } + } + + else if (p_fs->vol_type == FAT16) { + + content &= 0x0000FFFF; + + sec = p_fs->FAT1_start_sector + (loc >> (p_bd->sector_size_bits-1)); + off = (loc << 1) & p_bd->sector_size_mask; + + fat_sector = FAT_getblk(sb, sec); + if (!fat_sector) + return -1; + + fat_entry = &(fat_sector[off]); + + SET16_A(fat_entry, content); + } + + else if (p_fs->vol_type == FAT32) { + + content &= 0x0FFFFFFF; + + sec = p_fs->FAT1_start_sector + (loc >> (p_bd->sector_size_bits-2)); + off = (loc << 2) & p_bd->sector_size_mask; + + fat_sector = FAT_getblk(sb, sec); + if (!fat_sector) + return -1; + + fat_entry = &(fat_sector[off]); + + content |= GET32_A(fat_entry) & 0xF0000000; + + SET32_A(fat_entry, content); + } + + else { /* p_fs->vol_type == EXFAT */ + + sec = p_fs->FAT1_start_sector + (loc >> (p_bd->sector_size_bits-2)); + off = (loc << 2) & p_bd->sector_size_mask; + + fat_sector = FAT_getblk(sb, sec); + if (!fat_sector) + return -1; + + fat_entry = &(fat_sector[off]); + + SET32_A(fat_entry, content); + } + + FAT_modify(sb, sec); + return 0; +} /* end of __FAT_write */ + +UINT8 *FAT_getblk(struct super_block *sb, UINT32 sec) +{ + BUF_CACHE_T *bp; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + bp = FAT_cache_find(sb, sec); + if (bp != NULL) { + move_to_mru(bp, &p_fs->FAT_cache_lru_list); + return(bp->buf_bh->b_data); + } + + bp = FAT_cache_get(sb, sec); + + FAT_cache_remove_hash(bp); + + bp->drv = p_fs->drv; + bp->sec = sec; + bp->flag = 0; + + FAT_cache_insert_hash(sb, bp); + + if (sector_read(sb, sec, &(bp->buf_bh), 1) != FFS_SUCCESS) { + FAT_cache_remove_hash(bp); + bp->drv = -1; + bp->sec = ~0; + bp->flag = 0; + bp->buf_bh = NULL; + + move_to_lru(bp, &p_fs->FAT_cache_lru_list); + return NULL; + } + + return(bp->buf_bh->b_data); +} /* end of FAT_getblk */ + +void FAT_modify(struct super_block *sb, UINT32 sec) +{ + BUF_CACHE_T *bp; + + bp = FAT_cache_find(sb, sec); + if (bp != NULL) { + sector_write(sb, sec, bp->buf_bh, 0); + } +} /* end of FAT_modify */ + +void FAT_release_all(struct super_block *sb) +{ + BUF_CACHE_T *bp; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + sm_P(&f_sem); + + bp = p_fs->FAT_cache_lru_list.next; + while (bp != &p_fs->FAT_cache_lru_list) { + if (bp->drv == p_fs->drv) { + bp->drv = -1; + bp->sec = ~0; + bp->flag = 0; + + if(bp->buf_bh) { + __brelse(bp->buf_bh); + bp->buf_bh = NULL; + } + } + bp = bp->next; + } + + sm_V(&f_sem); +} /* end of FAT_release_all */ + +void FAT_sync(struct super_block *sb) +{ + BUF_CACHE_T *bp; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + sm_P(&f_sem); + + bp = p_fs->FAT_cache_lru_list.next; + while (bp != &p_fs->FAT_cache_lru_list) { + if ((bp->drv == p_fs->drv) && (bp->flag & DIRTYBIT)) { + sync_dirty_buffer(bp->buf_bh); + bp->flag &= ~(DIRTYBIT); + } + bp = bp->next; + } + + sm_V(&f_sem); +} /* end of FAT_sync */ + +static BUF_CACHE_T *FAT_cache_find(struct super_block *sb, UINT32 sec) +{ + INT32 off; + BUF_CACHE_T *bp, *hp; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + off = (sec + (sec >> p_fs->sectors_per_clu_bits)) & (FAT_CACHE_HASH_SIZE - 1); + + hp = &(p_fs->FAT_cache_hash_list[off]); + for (bp = hp->hash_next; bp != hp; bp = bp->hash_next) { + if ((bp->drv == p_fs->drv) && (bp->sec == sec)) { + + WARN(!bp->buf_bh, "[EXFAT] FAT_cache has no bh. " + "It will make system panic.\n"); + + touch_buffer(bp->buf_bh); + return(bp); + } + } + return(NULL); +} /* end of FAT_cache_find */ + +static BUF_CACHE_T *FAT_cache_get(struct super_block *sb, UINT32 sec) +{ + BUF_CACHE_T *bp; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + bp = p_fs->FAT_cache_lru_list.prev; + + + move_to_mru(bp, &p_fs->FAT_cache_lru_list); + return(bp); +} /* end of FAT_cache_get */ + +static void FAT_cache_insert_hash(struct super_block *sb, BUF_CACHE_T *bp) +{ + INT32 off; + BUF_CACHE_T *hp; + FS_INFO_T *p_fs; + + p_fs = &(EXFAT_SB(sb)->fs_info); + off = (bp->sec + (bp->sec >> p_fs->sectors_per_clu_bits)) & (FAT_CACHE_HASH_SIZE-1); + + hp = &(p_fs->FAT_cache_hash_list[off]); + bp->hash_next = hp->hash_next; + bp->hash_prev = hp; + hp->hash_next->hash_prev = bp; + hp->hash_next = bp; +} /* end of FAT_cache_insert_hash */ + +static void FAT_cache_remove_hash(BUF_CACHE_T *bp) +{ + (bp->hash_prev)->hash_next = bp->hash_next; + (bp->hash_next)->hash_prev = bp->hash_prev; +} /* end of FAT_cache_remove_hash */ + +/*======================================================================*/ +/* Buffer Read/Write Functions */ +/*======================================================================*/ + +UINT8 *buf_getblk(struct super_block *sb, UINT32 sec) +{ + UINT8 *buf; + + sm_P(&b_sem); + + buf = __buf_getblk(sb, sec); + + sm_V(&b_sem); + + return(buf); +} /* end of buf_getblk */ + +static UINT8 *__buf_getblk(struct super_block *sb, UINT32 sec) +{ + BUF_CACHE_T *bp; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + bp = buf_cache_find(sb, sec); + if (bp != NULL) { + move_to_mru(bp, &p_fs->buf_cache_lru_list); + return(bp->buf_bh->b_data); + } + + bp = buf_cache_get(sb, sec); + + buf_cache_remove_hash(bp); + + bp->drv = p_fs->drv; + bp->sec = sec; + bp->flag = 0; + + buf_cache_insert_hash(sb, bp); + + if (sector_read(sb, sec, &(bp->buf_bh), 1) != FFS_SUCCESS) { + buf_cache_remove_hash(bp); + bp->drv = -1; + bp->sec = ~0; + bp->flag = 0; + bp->buf_bh = NULL; + + move_to_lru(bp, &p_fs->buf_cache_lru_list); + return NULL; + } + + return(bp->buf_bh->b_data); + +} /* end of __buf_getblk */ + +void buf_modify(struct super_block *sb, UINT32 sec) +{ + BUF_CACHE_T *bp; + + sm_P(&b_sem); + + bp = buf_cache_find(sb, sec); + if (likely(bp != NULL)) { + sector_write(sb, sec, bp->buf_bh, 0); + } + + WARN(!bp, "[EXFAT] failed to find buffer_cache(sector:%u).\n", sec); + + sm_V(&b_sem); +} /* end of buf_modify */ + +void buf_lock(struct super_block *sb, UINT32 sec) +{ + BUF_CACHE_T *bp; + + sm_P(&b_sem); + + bp = buf_cache_find(sb, sec); + if (likely(bp != NULL)) bp->flag |= LOCKBIT; + + WARN(!bp, "[EXFAT] failed to find buffer_cache(sector:%u).\n", sec); + + sm_V(&b_sem); +} /* end of buf_lock */ + +void buf_unlock(struct super_block *sb, UINT32 sec) +{ + BUF_CACHE_T *bp; + + sm_P(&b_sem); + + bp = buf_cache_find(sb, sec); + if (likely(bp != NULL)) bp->flag &= ~(LOCKBIT); + + WARN(!bp, "[EXFAT] failed to find buffer_cache(sector:%u).\n", sec); + + sm_V(&b_sem); +} /* end of buf_unlock */ + +void buf_release(struct super_block *sb, UINT32 sec) +{ + BUF_CACHE_T *bp; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + sm_P(&b_sem); + + bp = buf_cache_find(sb, sec); + if (likely(bp != NULL)) { + bp->drv = -1; + bp->sec = ~0; + bp->flag = 0; + + if(bp->buf_bh) { + __brelse(bp->buf_bh); + bp->buf_bh = NULL; + } + + move_to_lru(bp, &p_fs->buf_cache_lru_list); + } + + sm_V(&b_sem); +} /* end of buf_release */ + +void buf_release_all(struct super_block *sb) +{ + BUF_CACHE_T *bp; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + sm_P(&b_sem); + + bp = p_fs->buf_cache_lru_list.next; + while (bp != &p_fs->buf_cache_lru_list) { + if (bp->drv == p_fs->drv) { + bp->drv = -1; + bp->sec = ~0; + bp->flag = 0; + + if(bp->buf_bh) { + __brelse(bp->buf_bh); + bp->buf_bh = NULL; + } + } + bp = bp->next; + } + + sm_V(&b_sem); +} /* end of buf_release_all */ + +void buf_sync(struct super_block *sb) +{ + BUF_CACHE_T *bp; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + sm_P(&b_sem); + + bp = p_fs->buf_cache_lru_list.next; + while (bp != &p_fs->buf_cache_lru_list) { + if ((bp->drv == p_fs->drv) && (bp->flag & DIRTYBIT)) { + sync_dirty_buffer(bp->buf_bh); + bp->flag &= ~(DIRTYBIT); + } + bp = bp->next; + } + + sm_V(&b_sem); +} /* end of buf_sync */ + +static BUF_CACHE_T *buf_cache_find(struct super_block *sb, UINT32 sec) +{ + INT32 off; + BUF_CACHE_T *bp, *hp; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + off = (sec + (sec >> p_fs->sectors_per_clu_bits)) & (BUF_CACHE_HASH_SIZE - 1); + + hp = &(p_fs->buf_cache_hash_list[off]); + for (bp = hp->hash_next; bp != hp; bp = bp->hash_next) { + if ((bp->drv == p_fs->drv) && (bp->sec == sec)) { + touch_buffer(bp->buf_bh); + return(bp); + } + } + return(NULL); +} /* end of buf_cache_find */ + +static BUF_CACHE_T *buf_cache_get(struct super_block *sb, UINT32 sec) +{ + BUF_CACHE_T *bp; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + bp = p_fs->buf_cache_lru_list.prev; + while (bp->flag & LOCKBIT) bp = bp->prev; + + + move_to_mru(bp, &p_fs->buf_cache_lru_list); + return(bp); +} /* end of buf_cache_get */ + +static void buf_cache_insert_hash(struct super_block *sb, BUF_CACHE_T *bp) +{ + INT32 off; + BUF_CACHE_T *hp; + FS_INFO_T *p_fs; + + p_fs = &(EXFAT_SB(sb)->fs_info); + off = (bp->sec + (bp->sec >> p_fs->sectors_per_clu_bits)) & (BUF_CACHE_HASH_SIZE-1); + + hp = &(p_fs->buf_cache_hash_list[off]); + bp->hash_next = hp->hash_next; + bp->hash_prev = hp; + hp->hash_next->hash_prev = bp; + hp->hash_next = bp; +} /* end of buf_cache_insert_hash */ + +static void buf_cache_remove_hash(BUF_CACHE_T *bp) +{ + (bp->hash_prev)->hash_next = bp->hash_next; + (bp->hash_next)->hash_prev = bp->hash_prev; +} /* end of buf_cache_remove_hash */ + +/*======================================================================*/ +/* Local Function Definitions */ +/*======================================================================*/ + +static void push_to_mru(BUF_CACHE_T *bp, BUF_CACHE_T *list) +{ + bp->next = list->next; + bp->prev = list; + list->next->prev = bp; + list->next = bp; +} /* end of buf_cache_push_to_mru */ + +static void push_to_lru(BUF_CACHE_T *bp, BUF_CACHE_T *list) +{ + bp->prev = list->prev; + bp->next = list; + list->prev->next = bp; + list->prev = bp; +} /* end of buf_cache_push_to_lru */ + +static void move_to_mru(BUF_CACHE_T *bp, BUF_CACHE_T *list) +{ + bp->prev->next = bp->next; + bp->next->prev = bp->prev; + push_to_mru(bp, list); +} /* end of buf_cache_move_to_mru */ + +static void move_to_lru(BUF_CACHE_T *bp, BUF_CACHE_T *list) +{ + bp->prev->next = bp->next; + bp->next->prev = bp->prev; + push_to_lru(bp, list); +} /* end of buf_cache_move_to_lru */ + +/* end of exfat_cache.c */ diff --git a/fs/exfat/exfat_cache.h b/fs/exfat/exfat_cache.h new file mode 100644 index 00000000000..056636b4e48 --- /dev/null +++ b/fs/exfat/exfat_cache.h @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * 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. + */ + +/************************************************************************/ +/* */ +/* PROJECT : exFAT & FAT12/16/32 File System */ +/* FILE : exfat_cache.h */ +/* PURPOSE : Header File for exFAT Cache Manager */ +/* (FAT Cache & Buffer Cache) */ +/* */ +/*----------------------------------------------------------------------*/ +/* NOTES */ +/* */ +/*----------------------------------------------------------------------*/ +/* REVISION HISTORY (Ver 0.9) */ +/* */ +/* - 2010.11.15 [Sung-Kwan Kim] : first writing */ +/* */ +/************************************************************************/ + +#ifndef _EXFAT_CACHE_H +#define _EXFAT_CACHE_H + +#include "exfat_config.h" +#include "exfat_global.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + /*----------------------------------------------------------------------*/ + /* Constant & Macro Definitions */ + /*----------------------------------------------------------------------*/ + +#define LOCKBIT 0x01 +#define DIRTYBIT 0x02 + + /*----------------------------------------------------------------------*/ + /* Type Definitions */ + /*----------------------------------------------------------------------*/ + + typedef struct __BUF_CACHE_T { + struct __BUF_CACHE_T *next; + struct __BUF_CACHE_T *prev; + struct __BUF_CACHE_T *hash_next; + struct __BUF_CACHE_T *hash_prev; + INT32 drv; + UINT32 sec; + UINT32 flag; + struct buffer_head *buf_bh; + } BUF_CACHE_T; + + /*----------------------------------------------------------------------*/ + /* External Function Declarations */ + /*----------------------------------------------------------------------*/ + + INT32 buf_init(struct super_block *sb); + INT32 buf_shutdown(struct super_block *sb); + INT32 FAT_read(struct super_block *sb, UINT32 loc, UINT32 *content); + INT32 FAT_write(struct super_block *sb, UINT32 loc, UINT32 content); + UINT8 *FAT_getblk(struct super_block *sb, UINT32 sec); + void FAT_modify(struct super_block *sb, UINT32 sec); + void FAT_release_all(struct super_block *sb); + void FAT_sync(struct super_block *sb); + UINT8 *buf_getblk(struct super_block *sb, UINT32 sec); + void buf_modify(struct super_block *sb, UINT32 sec); + void buf_lock(struct super_block *sb, UINT32 sec); + void buf_unlock(struct super_block *sb, UINT32 sec); + void buf_release(struct super_block *sb, UINT32 sec); + void buf_release_all(struct super_block *sb); + void buf_sync(struct super_block *sb); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _EXFAT_CACHE_H */ + +/* end of exfat_cache.h */ diff --git a/fs/exfat/exfat_config.h b/fs/exfat/exfat_config.h new file mode 100644 index 00000000000..d16c882f88c --- /dev/null +++ b/fs/exfat/exfat_config.h @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * 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. + */ + +/************************************************************************/ +/* */ +/* PROJECT : exFAT & FAT12/16/32 File System */ +/* FILE : exfat_config.h */ +/* PURPOSE : Header File for exFAT Configuable Policies */ +/* */ +/*----------------------------------------------------------------------*/ +/* NOTES */ +/* */ +/*----------------------------------------------------------------------*/ +/* REVISION HISTORY (Ver 0.9) */ +/* */ +/* - 2010.11.15 [Joosun Hahn] : first writing */ +/* */ +/************************************************************************/ + +#ifndef _EXFAT_CONFIG_H +#define _EXFAT_CONFIG_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/*======================================================================*/ +/* */ +/* FFS CONFIGURATIONS */ +/* (CHANGE THIS PART IF REQUIRED) */ +/* */ +/*======================================================================*/ + +/*----------------------------------------------------------------------*/ +/* Target OS Platform */ +/*----------------------------------------------------------------------*/ + +#define OS_NONOS 1 +#define OS_LINUX 2 + +#define FFS_CONFIG_OS OS_LINUX + +/*----------------------------------------------------------------------*/ +/* Set this definition to 1 to support APIs with pointer parameters */ +/* to 32-bit variables (e.g. read, write, seek, get_filesize) */ +/*----------------------------------------------------------------------*/ +#define FFS_CONFIG_LEGACY_32BIT_API 0 + +/*----------------------------------------------------------------------*/ +/* Set this definition to 1 to support APIs with pointer parameters */ +/* to 32-bit variables (e.g. read, write, seek, get_filesize) */ +/*----------------------------------------------------------------------*/ +#define FFS_CONFIG_LEGACY_32BIT_API 0 + +/*----------------------------------------------------------------------*/ +/* Set appropriate definitions to 1's to support the languages */ +/*----------------------------------------------------------------------*/ +#define FFS_CONFIG_SUPPORT_CP1250 1 // Central Europe +#define FFS_CONFIG_SUPPORT_CP1251 1 // Cyrillic +#define FFS_CONFIG_SUPPORT_CP1252 1 // Latin I +#define FFS_CONFIG_SUPPORT_CP1253 1 // Greek +#define FFS_CONFIG_SUPPORT_CP1254 1 // Turkish +#define FFS_CONFIG_SUPPORT_CP1255 1 // Hebrew +#define FFS_CONFIG_SUPPORT_CP1256 1 // Arabic +#define FFS_CONFIG_SUPPORT_CP1257 1 // Baltic +#define FFS_CONFIG_SUPPORT_CP1258 1 // Vietnamese +#define FFS_CONFIG_SUPPORT_CP874 1 // Thai +#define FFS_CONFIG_SUPPORT_CP932 1 // Japanese +#define FFS_CONFIG_SUPPORT_CP936 1 // Simplified Chinese +#define FFS_CONFIG_SUPPORT_CP949 1 // Korean +#define FFS_CONFIG_SUPPORT_CP950 1 // Traditional Chinese +#define FFS_CONFIG_SUPPORT_UTF8 1 // UTF8 encoding + +/*----------------------------------------------------------------------*/ +/* Feature Config */ +/*----------------------------------------------------------------------*/ +#define EXFAT_CONFIG_DISCARD 1 // mount option -o discard support +#define EXFAT_CONFIG_KERNEL_DEBUG 1 // kernel debug features via ioctl +#define EXFAT_CONFIG_DEBUG_MSG 0 // debugging message on/off + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _EXFAT_CONFIG_H */ + +/* end of exfat_config.h */ diff --git a/fs/exfat/exfat_core.c b/fs/exfat/exfat_core.c new file mode 100644 index 00000000000..2ab28dc32da --- /dev/null +++ b/fs/exfat/exfat_core.c @@ -0,0 +1,5187 @@ +/* Some of the source code in this file came from "linux/fs/fat/misc.c". */ +/* + * linux/fs/fat/misc.c + * + * Written 1992,1993 by Werner Almesberger + * 22/11/2000 - Fixed fat_date_unix2dos for dates earlier than 01/01/1980 + * and date_dos2unix for date==0 by Igor Zhbanov(bsg@uniyar.ac.ru) + */ + +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * 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. + */ + +/************************************************************************/ +/* */ +/* PROJECT : exFAT & FAT12/16/32 File System */ +/* FILE : exfat.c */ +/* PURPOSE : exFAT File Manager */ +/* */ +/*----------------------------------------------------------------------*/ +/* NOTES */ +/* */ +/*----------------------------------------------------------------------*/ +/* REVISION HISTORY (Ver 0.9) */ +/* */ +/* - 2010.11.15 [Joosun Hahn] : first writing */ +/* */ +/************************************************************************/ + +#include + +#include "exfat_config.h" +#include "exfat_global.h" +#include "exfat_data.h" +#include "exfat_oal.h" + +#include "exfat_blkdev.h" +#include "exfat_cache.h" +#include "exfat_nls.h" +#include "exfat_api.h" +#include "exfat_super.h" +#include "exfat.h" + +#include + +/*----------------------------------------------------------------------*/ +/* Constant & Macro Definitions */ +/*----------------------------------------------------------------------*/ + +#define THERE_IS_MBR 0 /* if there is no MBR (e.g. memory card), +set this macro to 0 */ + +#if (THERE_IS_MBR == 1) +#include "exfat_part.h" +#endif + +#define DELAYED_SYNC 0 + +#define ELAPSED_TIME 0 + +#if (ELAPSED_TIME == 1) +#include + +static UINT32 __t1, __t2; +static UINT32 get_current_msec(void) +{ + struct timeval tm; + do_gettimeofday(&tm); + return (UINT32)(tm.tv_sec*1000000 + tm.tv_usec); +} +#define TIME_START() do {__t1 = get_current_msec(); } while (0) +#define TIME_END() do {__t2 = get_current_msec(); } while (0) +#define PRINT_TIME(n) do {printk("[EXFAT] Elapsed time %d = %d (usec)\n", n, (__t2 - __t1)); } while (0) +#else +#define TIME_START() +#define TIME_END() +#define PRINT_TIME(n) +#endif + +static void __set_sb_dirty(struct super_block *sb) +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0) + sb->s_dirt = 1; +#else + struct exfat_sb_info *sbi = EXFAT_SB(sb); + sbi->s_dirt = 1; +#endif +} + +/*----------------------------------------------------------------------*/ +/* Global Variable Definitions */ +/*----------------------------------------------------------------------*/ + +extern UINT8 uni_upcase[]; + +/*----------------------------------------------------------------------*/ +/* Local Variable Definitions */ +/*----------------------------------------------------------------------*/ + +static UINT8 name_buf[MAX_PATH_LENGTH *MAX_CHARSET_SIZE]; + +static INT8 *reserved_names[] = { + "AUX ", "CON ", "NUL ", "PRN ", + "COM1 ", "COM2 ", "COM3 ", "COM4 ", + "COM5 ", "COM6 ", "COM7 ", "COM8 ", "COM9 ", + "LPT1 ", "LPT2 ", "LPT3 ", "LPT4 ", + "LPT5 ", "LPT6 ", "LPT7 ", "LPT8 ", "LPT9 ", + NULL +}; + +static UINT8 free_bit[] = { + 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, /* 0 ~ 19 */ + 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, /* 20 ~ 39 */ + 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, /* 40 ~ 59 */ + 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, /* 60 ~ 79 */ + 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, /* 80 ~ 99 */ + 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, /* 100 ~ 119 */ + 0, 1, 0, 2, 0, 1, 0, 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, /* 120 ~ 139 */ + 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, /* 140 ~ 159 */ + 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, /* 160 ~ 179 */ + 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3, /* 180 ~ 199 */ + 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, /* 200 ~ 219 */ + 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, /* 220 ~ 239 */ + 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 /* 240 ~ 254 */ +}; + +static UINT8 used_bit[] = { + 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, /* 0 ~ 19 */ + 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, /* 20 ~ 39 */ + 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, /* 40 ~ 59 */ + 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, /* 60 ~ 79 */ + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, /* 80 ~ 99 */ + 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, /* 100 ~ 119 */ + 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, /* 120 ~ 139 */ + 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, /* 140 ~ 159 */ + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, /* 160 ~ 179 */ + 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5, /* 180 ~ 199 */ + 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, /* 200 ~ 219 */ + 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, /* 220 ~ 239 */ + 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 /* 240 ~ 255 */ +}; + +/*======================================================================*/ +/* Global Function Definitions */ +/*======================================================================*/ + +/* ffsInit : roll back to the initial state of the file system */ +INT32 ffsInit(void) +{ + INT32 ret; + + ret = bdev_init(); + if (ret) + return ret; + + ret = fs_init(); + if (ret) + return ret; + + return FFS_SUCCESS; +} /* end of ffsInit */ + +/* ffsShutdown : make free all memory-alloced global buffers */ +INT32 ffsShutdown(void) +{ + INT32 ret; + ret = fs_shutdown(); + if (ret) + return ret; + + ret = bdev_shutdown(); + if (ret) + return ret; + + return FFS_SUCCESS; +} /* end of ffsShutdown */ + +/* ffsMountVol : mount the file system volume */ +INT32 ffsMountVol(struct super_block *sb, INT32 drv) +{ + INT32 i, ret; +#if (THERE_IS_MBR == 1) + MBR_SECTOR_T *p_mbr; + PART_ENTRY_T *p_pte; +#endif + PBR_SECTOR_T *p_pbr; + struct buffer_head *tmp_bh = NULL; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); + + PRINTK("[EXFAT] trying to mount...\n"); + + p_fs->drv = drv; + p_fs->dev_ejected = FALSE; + + /* open the block device */ + if (bdev_open(sb)) + return FFS_MEDIAERR; + + if (p_bd->sector_size < sb->s_blocksize) + return FFS_MEDIAERR; + if (p_bd->sector_size > sb->s_blocksize) + sb_set_blocksize(sb, p_bd->sector_size); + + /* read Sector 0 */ + if (sector_read(sb, 0, &tmp_bh, 1) != FFS_SUCCESS) + return FFS_MEDIAERR; + +#if (THERE_IS_MBR == 1) + if (buf[0] != 0xEB) { + /* MBR is read */ + p_mbr = (MBR_SECTOR_T *) tmp_bh->b_data; + + /* check the validity of MBR */ + if (GET16_A(p_mbr->signature) != MBR_SIGNATURE) { + brelse(tmp_bh); + bdev_close(sb); + return FFS_FORMATERR; + } + + p_pte = (PART_ENTRY_T *) p_mbr->partition + 0; + p_fs->PBR_sector = GET32(p_pte->start_sector); + p_fs->num_sectors = GET32(p_pte->num_sectors); + + if (p_fs->num_sectors == 0) { + brelse(tmp_bh); + bdev_close(sb); + return FFS_ERROR; + } + + /* read PBR */ + if (sector_read(sb, p_fs->PBR_sector, &tmp_bh, 1) != FFS_SUCCESS) { + bdev_close(sb); + return FFS_MEDIAERR; + } + } else { +#endif + /* PRB is read */ + p_fs->PBR_sector = 0; +#if (THERE_IS_MBR == 1) + } +#endif + + p_pbr = (PBR_SECTOR_T *) tmp_bh->b_data; + + /* check the validity of PBR */ + if (GET16_A(p_pbr->signature) != PBR_SIGNATURE) { + brelse(tmp_bh); + bdev_close(sb); + return FFS_FORMATERR; + } + + /* fill fs_stuct */ + for (i = 0; i < 53; i++) + if (p_pbr->bpb[i]) + break; + + if (i < 53) { + if (GET16(p_pbr->bpb+11)) /* num_fat_sectors */ + ret = fat16_mount(sb, p_pbr); + else + ret = fat32_mount(sb, p_pbr); + } else { + ret = exfat_mount(sb, p_pbr); + } + + brelse(tmp_bh); + + if (ret) { + bdev_close(sb); + return ret; + } + + if (p_fs->vol_type == EXFAT) { + ret = load_alloc_bitmap(sb); + if (ret) { + bdev_close(sb); + return ret; + } + ret = load_upcase_table(sb); + if (ret) { + free_alloc_bitmap(sb); + bdev_close(sb); + return ret; + } + } + + if (p_fs->dev_ejected) { + if (p_fs->vol_type == EXFAT) { + free_upcase_table(sb); + free_alloc_bitmap(sb); + } + bdev_close(sb); + return FFS_MEDIAERR; + } + + PRINTK("[EXFAT] mounted successfully\n"); + return FFS_SUCCESS; +} /* end of ffsMountVol */ + +/* ffsUmountVol : umount the file system volume */ +INT32 ffsUmountVol(struct super_block *sb) +{ + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + PRINTK("[EXFAT] trying to unmount...\n"); + + fs_sync(sb, 0); + fs_set_vol_flags(sb, VOL_CLEAN); + + if (p_fs->vol_type == EXFAT) { + free_upcase_table(sb); + free_alloc_bitmap(sb); + } + + FAT_release_all(sb); + buf_release_all(sb); + + /* close the block device */ + bdev_close(sb); + + if (p_fs->dev_ejected) { + PRINTK( "[EXFAT] unmounted with media errors. " + "device's already ejected.\n"); + return FFS_MEDIAERR; + } + + PRINTK("[EXFAT] unmounted successfully\n"); + return FFS_SUCCESS; +} /* end of ffsUmountVol */ + +/* ffsGetVolInfo : get the information of a file system volume */ +INT32 ffsGetVolInfo(struct super_block *sb, VOL_INFO_T *info) +{ + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + if (p_fs->used_clusters == (UINT32) ~0) + p_fs->used_clusters = p_fs->fs_func->count_used_clusters(sb); + + info->FatType = p_fs->vol_type; + info->ClusterSize = p_fs->cluster_size; + info->NumClusters = p_fs->num_clusters - 2; /* clu 0 & 1 */ + info->UsedClusters = p_fs->used_clusters; + info->FreeClusters = info->NumClusters - info->UsedClusters; + + if (p_fs->dev_ejected) + return FFS_MEDIAERR; + + return FFS_SUCCESS; +} /* end of ffsGetVolInfo */ + +/* ffsSyncVol : synchronize all file system volumes */ +INT32 ffsSyncVol(struct super_block *sb, INT32 do_sync) +{ + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + /* synchronize the file system */ + fs_sync(sb, do_sync); + fs_set_vol_flags(sb, VOL_CLEAN); + + if (p_fs->dev_ejected) + return FFS_MEDIAERR; + + return FFS_SUCCESS; +} /* end of ffsSyncVol */ + +/*----------------------------------------------------------------------*/ +/* File Operation Functions */ +/*----------------------------------------------------------------------*/ + +/* ffsLookupFile : lookup a file */ +INT32 ffsLookupFile(struct inode *inode, UINT8 *path, FILE_ID_T *fid) +{ + INT32 ret, dentry, num_entries; + CHAIN_T dir; + UNI_NAME_T uni_name; + DOS_NAME_T dos_name; + DENTRY_T *ep, *ep2; + ENTRY_SET_CACHE_T *es=NULL; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + PRINTK("ffsLookupFile entered\n"); + + /* check the validity of directory name in the given pathname */ + ret = resolve_path(inode, path, &dir, &uni_name); + if (ret) + return ret; + + ret = get_num_entries_and_dos_name(sb, &dir, &uni_name, &num_entries, &dos_name); + if (ret) + return ret; + + /* search the file name for directories */ + dentry = p_fs->fs_func->find_dir_entry(sb, &dir, &uni_name, num_entries, &dos_name, TYPE_ALL); + if (dentry < -1) + return FFS_NOTFOUND; + + fid->dir.dir = dir.dir; + fid->dir.size = dir.size; + fid->dir.flags = dir.flags; + fid->entry = dentry; + + if (dentry == -1) { + fid->type = TYPE_DIR; + fid->rwoffset = 0; + fid->hint_last_off = -1; + + fid->attr = ATTR_SUBDIR; + fid->flags = 0x01; + fid->size = 0; + fid->start_clu = p_fs->root_dir; + } else { + if (p_fs->vol_type == EXFAT) { + es = get_entry_set_in_dir(sb, &dir, dentry, ES_2_ENTRIES, &ep); + if (!es) + return FFS_MEDIAERR; + ep2 = ep+1; + } else { + ep = get_entry_in_dir(sb, &dir, dentry, NULL); + if (!ep) + return FFS_MEDIAERR; + ep2 = ep; + } + + fid->type = p_fs->fs_func->get_entry_type(ep); + fid->rwoffset = 0; + fid->hint_last_off = -1; + fid->attr = p_fs->fs_func->get_entry_attr(ep); + + fid->size = p_fs->fs_func->get_entry_size(ep2); + if ((fid->type == TYPE_FILE) && (fid->size == 0)) { + fid->flags = (p_fs->vol_type == EXFAT) ? 0x03 : 0x01; + fid->start_clu = CLUSTER_32(~0); + } else { + fid->flags = p_fs->fs_func->get_entry_flag(ep2); + fid->start_clu = p_fs->fs_func->get_entry_clu0(ep2); + } + + if (p_fs->vol_type == EXFAT) + release_entry_set(es); + } + + if (p_fs->dev_ejected) + return FFS_MEDIAERR; + + PRINTK("ffsLookupFile exited successfully\n"); + + return FFS_SUCCESS; +} /* end of ffsLookupFile */ + +/* ffsCreateFile : create a file */ +INT32 ffsCreateFile(struct inode *inode, UINT8 *path, UINT8 mode, FILE_ID_T *fid) +{ + INT32 ret/*, dentry*/; + CHAIN_T dir; + UNI_NAME_T uni_name; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + /* check the validity of directory name in the given pathname */ + ret = resolve_path(inode, path, &dir, &uni_name); + if (ret) + return ret; + + fs_set_vol_flags(sb, VOL_DIRTY); + + /* create a new file */ + ret = create_file(inode, &dir, &uni_name, mode, fid); + +#if (DELAYED_SYNC == 0) + fs_sync(sb, 0); + fs_set_vol_flags(sb, VOL_CLEAN); +#endif + + if (p_fs->dev_ejected) + return FFS_MEDIAERR; + + return ret; +} /* end of ffsCreateFile */ + +/* ffsReadFile : read data from a opened file */ +INT32 ffsReadFile(struct inode *inode, FILE_ID_T *fid, void *buffer, UINT64 count, UINT64 *rcount) +{ + INT32 offset, sec_offset, clu_offset; + UINT32 clu, LogSector; + UINT64 oneblkread, read_bytes; + struct buffer_head *tmp_bh = NULL; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); + + /* check if the given file ID is opened */ + if (fid->type != TYPE_FILE) + return FFS_PERMISSIONERR; + + if (fid->rwoffset > fid->size) + fid->rwoffset = fid->size; + + if (count > (fid->size - fid->rwoffset)) + count = fid->size - fid->rwoffset; + + if (count == 0) { + if (rcount != NULL) + *rcount = 0; + return FFS_EOF; + } + + read_bytes = 0; + + while (count > 0) { + clu_offset = (INT32)(fid->rwoffset >> p_fs->cluster_size_bits); + clu = fid->start_clu; + + if (fid->flags == 0x03) { + clu += clu_offset; + } else { + /* hint information */ + if ((clu_offset > 0) && (fid->hint_last_off > 0) && + (clu_offset >= fid->hint_last_off)) { + clu_offset -= fid->hint_last_off; + clu = fid->hint_last_clu; + } + + while (clu_offset > 0) { + /* clu = FAT_read(sb, clu); */ + if (FAT_read(sb, clu, &clu) == -1) + return FFS_MEDIAERR; + + clu_offset--; + } + } + + /* hint information */ + fid->hint_last_off = (INT32)(fid->rwoffset >> p_fs->cluster_size_bits); + fid->hint_last_clu = clu; + + offset = (INT32)(fid->rwoffset & (p_fs->cluster_size-1)); /* byte offset in cluster */ + sec_offset = offset >> p_bd->sector_size_bits; /* sector offset in cluster */ + offset &= p_bd->sector_size_mask; /* byte offset in sector */ + + LogSector = START_SECTOR(clu) + sec_offset; + + oneblkread = (UINT64)(p_bd->sector_size - offset); + if (oneblkread > count) + oneblkread = count; + + if ((offset == 0) && (oneblkread == p_bd->sector_size)) { + if (sector_read(sb, LogSector, &tmp_bh, 1) != FFS_SUCCESS) + goto err_out; + MEMCPY(((INT8 *) buffer)+read_bytes, ((INT8 *) tmp_bh->b_data), (INT32) oneblkread); + } else { + if (sector_read(sb, LogSector, &tmp_bh, 1) != FFS_SUCCESS) + goto err_out; + MEMCPY(((INT8 *) buffer)+read_bytes, ((INT8 *) tmp_bh->b_data)+offset, (INT32) oneblkread); + } + count -= oneblkread; + read_bytes += oneblkread; + fid->rwoffset += oneblkread; + } + brelse(tmp_bh); + +err_out: + /* set the size of read bytes */ + if (rcount != NULL) + *rcount = read_bytes; + + if (p_fs->dev_ejected) + return FFS_MEDIAERR; + + return FFS_SUCCESS; +} /* end of ffsReadFile */ + +/* ffsWriteFile : write data into a opened file */ +INT32 ffsWriteFile(struct inode *inode, FILE_ID_T *fid, void *buffer, UINT64 count, UINT64 *wcount) +{ + INT32 modified = FALSE, offset, sec_offset, clu_offset; + INT32 num_clusters, num_alloc, num_alloced = (INT32) ~0; + UINT32 clu, last_clu, LogSector, sector = 0; + UINT64 oneblkwrite, write_bytes; + CHAIN_T new_clu; + TIMESTAMP_T tm; + DENTRY_T *ep, *ep2; + ENTRY_SET_CACHE_T *es = NULL; + struct buffer_head *tmp_bh = NULL; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); + + /* check if the given file ID is opened */ + if (fid->type != TYPE_FILE) + return FFS_PERMISSIONERR; + + if (fid->rwoffset > fid->size) + fid->rwoffset = fid->size; + + if (count == 0) { + if (wcount != NULL) + *wcount = 0; + return FFS_SUCCESS; + } + + fs_set_vol_flags(sb, VOL_DIRTY); + + if (fid->size == 0) + num_clusters = 0; + else + num_clusters = (INT32)((fid->size-1) >> p_fs->cluster_size_bits) + 1; + + write_bytes = 0; + + while (count > 0) { + clu_offset = (INT32)(fid->rwoffset >> p_fs->cluster_size_bits); + clu = last_clu = fid->start_clu; + + if (fid->flags == 0x03) { + if ((clu_offset > 0) && (clu != CLUSTER_32(~0))) { + last_clu += clu_offset - 1; + + if (clu_offset == num_clusters) + clu = CLUSTER_32(~0); + else + clu += clu_offset; + } + } else { + /* hint information */ + if ((clu_offset > 0) && (fid->hint_last_off > 0) && + (clu_offset >= fid->hint_last_off)) { + clu_offset -= fid->hint_last_off; + clu = fid->hint_last_clu; + } + + while ((clu_offset > 0) && (clu != CLUSTER_32(~0))) { + last_clu = clu; + /* clu = FAT_read(sb, clu); */ + if (FAT_read(sb, clu, &clu) == -1) + return FFS_MEDIAERR; + + clu_offset--; + } + } + + if (clu == CLUSTER_32(~0)) { + num_alloc = (INT32)((count-1) >> p_fs->cluster_size_bits) + 1; + new_clu.dir = (last_clu == CLUSTER_32(~0)) ? CLUSTER_32(~0) : last_clu+1; + new_clu.size = 0; + new_clu.flags = fid->flags; + + /* (1) allocate a chain of clusters */ + num_alloced = p_fs->fs_func->alloc_cluster(sb, num_alloc, &new_clu); + if (num_alloced == 0) + break; + + /* (2) append to the FAT chain */ + if (last_clu == CLUSTER_32(~0)) { + if (new_clu.flags == 0x01) + fid->flags = 0x01; + fid->start_clu = new_clu.dir; + modified = TRUE; + } else { + if (new_clu.flags != fid->flags) { + exfat_chain_cont_cluster(sb, fid->start_clu, num_clusters); + fid->flags = 0x01; + modified = TRUE; + } + if (new_clu.flags == 0x01) + FAT_write(sb, last_clu, new_clu.dir); + } + + num_clusters += num_alloced; + clu = new_clu.dir; + } + + /* hint information */ + fid->hint_last_off = (INT32)(fid->rwoffset >> p_fs->cluster_size_bits); + fid->hint_last_clu = clu; + + offset = (INT32)(fid->rwoffset & (p_fs->cluster_size-1)); /* byte offset in cluster */ + sec_offset = offset >> p_bd->sector_size_bits; /* sector offset in cluster */ + offset &= p_bd->sector_size_mask; /* byte offset in sector */ + + LogSector = START_SECTOR(clu) + sec_offset; + + oneblkwrite = (UINT64)(p_bd->sector_size - offset); + if (oneblkwrite > count) + oneblkwrite = count; + + if ((offset == 0) && (oneblkwrite == p_bd->sector_size)) { + if (sector_read(sb, LogSector, &tmp_bh, 0) != FFS_SUCCESS) + goto err_out; + MEMCPY(((INT8 *) tmp_bh->b_data), ((INT8 *) buffer)+write_bytes, (INT32) oneblkwrite); + if (sector_write(sb, LogSector, tmp_bh, 0) != FFS_SUCCESS) { + brelse(tmp_bh); + goto err_out; + } + } else { + if ((offset > 0) || ((fid->rwoffset+oneblkwrite) < fid->size)) { + if (sector_read(sb, LogSector, &tmp_bh, 1) != FFS_SUCCESS) + goto err_out; + } else { + if (sector_read(sb, LogSector, &tmp_bh, 0) != FFS_SUCCESS) + goto err_out; + } + + MEMCPY(((INT8 *) tmp_bh->b_data)+offset, ((INT8 *) buffer)+write_bytes, (INT32) oneblkwrite); + if (sector_write(sb, LogSector, tmp_bh, 0) != FFS_SUCCESS) { + brelse(tmp_bh); + goto err_out; + } + } + + count -= oneblkwrite; + write_bytes += oneblkwrite; + fid->rwoffset += oneblkwrite; + + fid->attr |= ATTR_ARCHIVE; + + if (fid->size < fid->rwoffset) { + fid->size = fid->rwoffset; + modified = TRUE; + } + } + + brelse(tmp_bh); + + /* (3) update the direcoty entry */ + if (p_fs->vol_type == EXFAT) { + es = get_entry_set_in_dir(sb, &(fid->dir), fid->entry, ES_ALL_ENTRIES, &ep); + if (es == NULL) + goto err_out; + ep2 = ep+1; + } else { + ep = get_entry_in_dir(sb, &(fid->dir), fid->entry, §or); + if (!ep) + goto err_out; + ep2 = ep; + } + + p_fs->fs_func->set_entry_time(ep, tm_current(&tm), TM_MODIFY); + p_fs->fs_func->set_entry_attr(ep, fid->attr); + + if (p_fs->vol_type != EXFAT) + buf_modify(sb, sector); + + if (modified) { + if (p_fs->fs_func->get_entry_flag(ep2) != fid->flags) + p_fs->fs_func->set_entry_flag(ep2, fid->flags); + + if (p_fs->fs_func->get_entry_size(ep2) != fid->size) + p_fs->fs_func->set_entry_size(ep2, fid->size); + + if (p_fs->fs_func->get_entry_clu0(ep2) != fid->start_clu) + p_fs->fs_func->set_entry_clu0(ep2, fid->start_clu); + + if (p_fs->vol_type != EXFAT) + buf_modify(sb, sector); + } + + if (p_fs->vol_type == EXFAT) { + update_dir_checksum_with_entry_set(sb, es); + release_entry_set(es); + } + +#if (DELAYED_SYNC == 0) + fs_sync(sb, 0); + fs_set_vol_flags(sb, VOL_CLEAN); +#endif + +err_out: + /* set the size of written bytes */ + if (wcount != NULL) + *wcount = write_bytes; + + if (num_alloced == 0) + return FFS_FULL; + + if (p_fs->dev_ejected) + return FFS_MEDIAERR; + + return FFS_SUCCESS; +} /* end of ffsWriteFile */ + +/* ffsTruncateFile : resize the file length */ +INT32 ffsTruncateFile(struct inode *inode, UINT64 old_size, UINT64 new_size) +{ + INT32 num_clusters; + UINT32 last_clu = CLUSTER_32(0), sector = 0; + CHAIN_T clu; + TIMESTAMP_T tm; + DENTRY_T *ep, *ep2; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + FILE_ID_T *fid = &(EXFAT_I(inode)->fid); + ENTRY_SET_CACHE_T *es=NULL; + + /* check if the given file ID is opened */ + if (fid->type != TYPE_FILE) + return FFS_PERMISSIONERR; + + if (fid->size != old_size) { + printk(KERN_ERR "[EXFAT] truncate : can't skip it because of " + "size-mismatch(old:%lld->fid:%lld).\n" + ,old_size, fid->size); + } + + if (old_size <= new_size) + return FFS_SUCCESS; + + fs_set_vol_flags(sb, VOL_DIRTY); + + clu.dir = fid->start_clu; + clu.size = (INT32)((old_size-1) >> p_fs->cluster_size_bits) + 1; + clu.flags = fid->flags; + + if (new_size > 0) { + num_clusters = (INT32)((new_size-1) >> p_fs->cluster_size_bits) + 1; + + if (clu.flags == 0x03) { + clu.dir += num_clusters; + } else { + while (num_clusters > 0) { + last_clu = clu.dir; + if (FAT_read(sb, clu.dir, &(clu.dir)) == -1) + return FFS_MEDIAERR; + num_clusters--; + } + } + + clu.size -= num_clusters; + } + + fid->size = new_size; + fid->attr |= ATTR_ARCHIVE; + if (new_size == 0) { + fid->flags = (p_fs->vol_type == EXFAT) ? 0x03 : 0x01; + fid->start_clu = CLUSTER_32(~0); + } + + /* (1) update the directory entry */ + if (p_fs->vol_type == EXFAT) { + es = get_entry_set_in_dir(sb, &(fid->dir), fid->entry, ES_ALL_ENTRIES, &ep); + if (es == NULL) + return FFS_MEDIAERR; + ep2 = ep+1; + } else { + ep = get_entry_in_dir(sb, &(fid->dir), fid->entry, §or); + if (!ep) + return FFS_MEDIAERR; + ep2 = ep; + } + + p_fs->fs_func->set_entry_time(ep, tm_current(&tm), TM_MODIFY); + p_fs->fs_func->set_entry_attr(ep, fid->attr); + + p_fs->fs_func->set_entry_size(ep2, new_size); + if (new_size == 0) { + p_fs->fs_func->set_entry_flag(ep2, 0x01); + p_fs->fs_func->set_entry_clu0(ep2, CLUSTER_32(0)); + } + + if (p_fs->vol_type != EXFAT) + buf_modify(sb, sector); + else { + update_dir_checksum_with_entry_set(sb, es); + release_entry_set(es); + } + + /* (2) cut off from the FAT chain */ + if (last_clu != CLUSTER_32(0)) { + if (fid->flags == 0x01) + FAT_write(sb, last_clu, CLUSTER_32(~0)); + } + + /* (3) free the clusters */ + p_fs->fs_func->free_cluster(sb, &clu, 0); + + /* hint information */ + fid->hint_last_off = -1; + if (fid->rwoffset > fid->size) { + fid->rwoffset = fid->size; + } + +#if (DELAYED_SYNC == 0) + fs_sync(sb, 0); + fs_set_vol_flags(sb, VOL_CLEAN); +#endif + + if (p_fs->dev_ejected) + return FFS_MEDIAERR; + + return FFS_SUCCESS; +} /* end of ffsTruncateFile */ + +static void update_parent_info( FILE_ID_T *fid, struct inode *parent_inode) +{ + FS_INFO_T *p_fs = &(EXFAT_SB(parent_inode->i_sb)->fs_info); + FILE_ID_T *parent_fid = &(EXFAT_I(parent_inode)->fid); + + if (unlikely((parent_fid->flags != fid->dir.flags) + || (parent_fid->size != (fid->dir.size<cluster_size_bits)) + || (parent_fid->start_clu != fid->dir.dir))) { + + fid->dir.dir = parent_fid->start_clu; + fid->dir.flags = parent_fid->flags; + fid->dir.size = ((parent_fid->size + (p_fs->cluster_size-1)) + >> p_fs->cluster_size_bits); + } +} + +/* ffsMoveFile : move(rename) a old file into a new file */ +INT32 ffsMoveFile(struct inode *old_parent_inode, FILE_ID_T *fid, struct inode *new_parent_inode, struct dentry *new_dentry) +{ + INT32 ret; + INT32 dentry; + CHAIN_T olddir, newdir; + CHAIN_T *p_dir=NULL; + UNI_NAME_T uni_name; + DENTRY_T *ep; + struct super_block *sb = old_parent_inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + UINT8 *new_path = (UINT8 *) new_dentry->d_name.name; + struct inode *new_inode = new_dentry->d_inode; + int num_entries; + FILE_ID_T *new_fid = NULL; + INT32 new_entry=0; + + /* check the validity of pointer parameters */ + if ((new_path == NULL) || (*new_path == '\0')) + return FFS_ERROR; + + update_parent_info(fid, old_parent_inode); + + olddir.dir = fid->dir.dir; + olddir.size = fid->dir.size; + olddir.flags = fid->dir.flags; + + dentry = fid->entry; + + /* check if the old file is "." or ".." */ + if (p_fs->vol_type != EXFAT) { + if ((olddir.dir != p_fs->root_dir) && (dentry < 2)) + return FFS_PERMISSIONERR; + } + + ep = get_entry_in_dir(sb, &olddir, dentry, NULL); + if (!ep) + return FFS_MEDIAERR; + + if (p_fs->fs_func->get_entry_attr(ep) & ATTR_READONLY) + return FFS_PERMISSIONERR; + + /* check whether new dir is existing directory and empty */ + if (new_inode) { + UINT32 entry_type; + + ret = FFS_MEDIAERR; + new_fid = &EXFAT_I(new_inode)->fid; + + update_parent_info(new_fid, new_parent_inode); + + p_dir = &(new_fid->dir); + new_entry = new_fid->entry; + ep = get_entry_in_dir(sb, p_dir, new_entry, NULL); + if (!ep) + goto out; + + entry_type = p_fs->fs_func->get_entry_type(ep); + + if (entry_type == TYPE_DIR) { + CHAIN_T new_clu; + new_clu.dir = new_fid->start_clu; + new_clu.size = (INT32)((new_fid->size-1) >> p_fs->cluster_size_bits) + 1; + new_clu.flags = new_fid->flags; + + if (!is_dir_empty(sb, &new_clu)) + return FFS_FILEEXIST; + } + } + + /* check the validity of directory name in the given new pathname */ + ret = resolve_path(new_parent_inode, new_path, &newdir, &uni_name); + if (ret) + return ret; + + fs_set_vol_flags(sb, VOL_DIRTY); + + if (olddir.dir == newdir.dir) + ret = rename_file(new_parent_inode, &olddir, dentry, &uni_name, fid); + else + ret = move_file(new_parent_inode, &olddir, dentry, &newdir, &uni_name, fid); + + if ((ret == FFS_SUCCESS) && new_inode) { + /* delete entries of new_dir */ + ep = get_entry_in_dir(sb, p_dir, new_entry, NULL); + if (!ep) + goto out; + + num_entries = p_fs->fs_func->count_ext_entries(sb, p_dir, new_entry, ep); + if (num_entries < 0) + goto out; + p_fs->fs_func->delete_dir_entry(sb, p_dir, new_entry, 0, num_entries+1); + } +out: +#if (DELAYED_SYNC == 0) + fs_sync(sb, 0); + fs_set_vol_flags(sb, VOL_CLEAN); +#endif + + if (p_fs->dev_ejected) + return FFS_MEDIAERR; + + return ret; +} /* end of ffsMoveFile */ + +/* ffsRemoveFile : remove a file */ +INT32 ffsRemoveFile(struct inode *inode, FILE_ID_T *fid) +{ + INT32 dentry; + CHAIN_T dir, clu_to_free; + DENTRY_T *ep; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + dir.dir = fid->dir.dir; + dir.size = fid->dir.size; + dir.flags = fid->dir.flags; + + dentry = fid->entry; + + ep = get_entry_in_dir(sb, &dir, dentry, NULL); + if (!ep) + return FFS_MEDIAERR; + + if (p_fs->fs_func->get_entry_attr(ep) & ATTR_READONLY) + return FFS_PERMISSIONERR; + + fs_set_vol_flags(sb, VOL_DIRTY); + + /* (1) update the directory entry */ + remove_file(inode, &dir, dentry); + + clu_to_free.dir = fid->start_clu; + clu_to_free.size = (INT32)((fid->size-1) >> p_fs->cluster_size_bits) + 1; + clu_to_free.flags = fid->flags; + + /* (2) free the clusters */ + p_fs->fs_func->free_cluster(sb, &clu_to_free, 0); + + fid->size = 0; + fid->start_clu = CLUSTER_32(~0); + fid->flags = (p_fs->vol_type == EXFAT)? 0x03: 0x01; + +#if (DELAYED_SYNC == 0) + fs_sync(sb, 0); + fs_set_vol_flags(sb, VOL_CLEAN); +#endif + + if (p_fs->dev_ejected) + return FFS_MEDIAERR; + + return FFS_SUCCESS; +} /* end of ffsRemoveFile */ + +/* ffsSetAttr : set the attribute of a given file */ +INT32 ffsSetAttr(struct inode *inode, UINT32 attr) +{ + UINT32 type, sector = 0; + DENTRY_T *ep; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + FILE_ID_T *fid = &(EXFAT_I(inode)->fid); + UINT8 is_dir = (fid->type == TYPE_DIR) ? 1 : 0; + ENTRY_SET_CACHE_T *es = NULL; + + if (fid->attr == attr) { + if (p_fs->dev_ejected) + return FFS_MEDIAERR; + return FFS_SUCCESS; + } + + if (is_dir) { + if ((fid->dir.dir == p_fs->root_dir) && + (fid->entry == -1)) { + if (p_fs->dev_ejected) + return FFS_MEDIAERR; + return FFS_SUCCESS; + } + } + + /* get the directory entry of given file */ + if (p_fs->vol_type == EXFAT) { + es = get_entry_set_in_dir(sb, &(fid->dir), fid->entry, ES_ALL_ENTRIES, &ep); + if (es == NULL) + return FFS_MEDIAERR; + } else { + ep = get_entry_in_dir(sb, &(fid->dir), fid->entry, §or); + if (!ep) + return FFS_MEDIAERR; + } + + type = p_fs->fs_func->get_entry_type(ep); + + if (((type == TYPE_FILE) && (attr & ATTR_SUBDIR)) || + ((type == TYPE_DIR) && (!(attr & ATTR_SUBDIR)))) { + INT32 err; + if (p_fs->dev_ejected) + err = FFS_MEDIAERR; + else + err = FFS_ERROR; + + if (p_fs->vol_type == EXFAT) + release_entry_set(es); + return err; + } + + fs_set_vol_flags(sb, VOL_DIRTY); + + /* set the file attribute */ + fid->attr = attr; + p_fs->fs_func->set_entry_attr(ep, attr); + + if (p_fs->vol_type != EXFAT) + buf_modify(sb, sector); + else { + update_dir_checksum_with_entry_set(sb, es); + release_entry_set(es); + } + +#if (DELAYED_SYNC == 0) + fs_sync(sb, 0); + fs_set_vol_flags(sb, VOL_CLEAN); +#endif + + if (p_fs->dev_ejected) + return FFS_MEDIAERR; + + return FFS_SUCCESS; +} /* end of ffsSetAttr */ + +/* ffsGetStat : get the information of a given file */ +INT32 ffsGetStat(struct inode *inode, DIR_ENTRY_T *info) +{ + UINT32 sector = 0; + INT32 count; + CHAIN_T dir; + UNI_NAME_T uni_name; + TIMESTAMP_T tm; + DENTRY_T *ep, *ep2; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + FILE_ID_T *fid = &(EXFAT_I(inode)->fid); + ENTRY_SET_CACHE_T *es=NULL; + UINT8 is_dir = (fid->type == TYPE_DIR) ? 1 : 0; + + PRINTK("ffsGetStat entered\n"); + + if (is_dir) { + if ((fid->dir.dir == p_fs->root_dir) && + (fid->entry == -1)) { + info->Attr = ATTR_SUBDIR; + MEMSET((INT8 *) &info->CreateTimestamp, 0, sizeof(DATE_TIME_T)); + MEMSET((INT8 *) &info->ModifyTimestamp, 0, sizeof(DATE_TIME_T)); + MEMSET((INT8 *) &info->AccessTimestamp, 0, sizeof(DATE_TIME_T)); + STRCPY(info->ShortName, "."); + STRCPY(info->Name, "."); + + dir.dir = p_fs->root_dir; + dir.flags = 0x01; + + if (p_fs->root_dir == CLUSTER_32(0)) /* FAT16 root_dir */ + info->Size = p_fs->dentries_in_root << DENTRY_SIZE_BITS; + else + info->Size = count_num_clusters(sb, &dir) << p_fs->cluster_size_bits; + + count = count_dos_name_entries(sb, &dir, TYPE_DIR); + if (count < 0) + return FFS_MEDIAERR; + info->NumSubdirs = count; + + if (p_fs->dev_ejected) + return FFS_MEDIAERR; + return FFS_SUCCESS; + } + } + + /* get the directory entry of given file or directory */ + if (p_fs->vol_type == EXFAT) { + es = get_entry_set_in_dir(sb, &(fid->dir), fid->entry, ES_2_ENTRIES, &ep); + if (es == NULL) + return FFS_MEDIAERR; + ep2 = ep+1; + } else { + ep = get_entry_in_dir(sb, &(fid->dir), fid->entry, §or); + if (!ep) + return FFS_MEDIAERR; + ep2 = ep; + buf_lock(sb, sector); + } + + /* set FILE_INFO structure using the acquired DENTRY_T */ + info->Attr = p_fs->fs_func->get_entry_attr(ep); + + p_fs->fs_func->get_entry_time(ep, &tm, TM_CREATE); + info->CreateTimestamp.Year = tm.year; + info->CreateTimestamp.Month = tm.mon; + info->CreateTimestamp.Day = tm.day; + info->CreateTimestamp.Hour = tm.hour; + info->CreateTimestamp.Minute = tm.min; + info->CreateTimestamp.Second = tm.sec; + info->CreateTimestamp.MilliSecond = 0; + + p_fs->fs_func->get_entry_time(ep, &tm, TM_MODIFY); + info->ModifyTimestamp.Year = tm.year; + info->ModifyTimestamp.Month = tm.mon; + info->ModifyTimestamp.Day = tm.day; + info->ModifyTimestamp.Hour = tm.hour; + info->ModifyTimestamp.Minute = tm.min; + info->ModifyTimestamp.Second = tm.sec; + info->ModifyTimestamp.MilliSecond = 0; + + MEMSET((INT8 *) &info->AccessTimestamp, 0, sizeof(DATE_TIME_T)); + + *(uni_name.name) = 0x0; + /* XXX this is very bad for exfat cuz name is already included in es. + API should be revised */ + p_fs->fs_func->get_uni_name_from_ext_entry(sb, &(fid->dir), fid->entry, uni_name.name); + if (*(uni_name.name) == 0x0) + get_uni_name_from_dos_entry(sb, (DOS_DENTRY_T *) ep, &uni_name, 0x1); + nls_uniname_to_cstring(sb, info->Name, &uni_name); + + if (p_fs->vol_type == EXFAT) { + info->NumSubdirs = 2; + } else { + buf_unlock(sb, sector); + get_uni_name_from_dos_entry(sb, (DOS_DENTRY_T *) ep, &uni_name, 0x0); + nls_uniname_to_cstring(sb, info->ShortName, &uni_name); + info->NumSubdirs = 0; + } + + info->Size = p_fs->fs_func->get_entry_size(ep2); + + if (p_fs->vol_type == EXFAT) + release_entry_set(es); + + if (is_dir) { + dir.dir = fid->start_clu; + dir.flags = 0x01; + + if (info->Size == 0) + info->Size = (UINT64) count_num_clusters(sb, &dir) << p_fs->cluster_size_bits; + + count = count_dos_name_entries(sb, &dir, TYPE_DIR); + if (count < 0) + return FFS_MEDIAERR; + info->NumSubdirs += count; + } + + if (p_fs->dev_ejected) + return FFS_MEDIAERR; + + PRINTK("ffsGetStat exited successfully\n"); + return FFS_SUCCESS; +} /* end of ffsGetStat */ + +/* ffsSetStat : set the information of a given file */ +INT32 ffsSetStat(struct inode *inode, DIR_ENTRY_T *info) +{ + UINT32 sector = 0; + TIMESTAMP_T tm; + DENTRY_T *ep, *ep2; + ENTRY_SET_CACHE_T *es=NULL; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + FILE_ID_T *fid = &(EXFAT_I(inode)->fid); + UINT8 is_dir = (fid->type == TYPE_DIR) ? 1 : 0; + + if (is_dir) { + if ((fid->dir.dir == p_fs->root_dir) && + (fid->entry == -1)) { + if (p_fs->dev_ejected) + return FFS_MEDIAERR; + return FFS_SUCCESS; + } + } + + fs_set_vol_flags(sb, VOL_DIRTY); + + /* get the directory entry of given file or directory */ + if (p_fs->vol_type == EXFAT) { + es = get_entry_set_in_dir(sb, &(fid->dir), fid->entry, ES_ALL_ENTRIES, &ep); + if (es == NULL) + return FFS_MEDIAERR; + ep2 = ep+1; + } else { + /* for other than exfat */ + ep = get_entry_in_dir(sb, &(fid->dir), fid->entry, §or); + if (!ep) + return FFS_MEDIAERR; + ep2 = ep; + } + + + p_fs->fs_func->set_entry_attr(ep, info->Attr); + + /* set FILE_INFO structure using the acquired DENTRY_T */ + tm.sec = info->CreateTimestamp.Second; + tm.min = info->CreateTimestamp.Minute; + tm.hour = info->CreateTimestamp.Hour; + tm.day = info->CreateTimestamp.Day; + tm.mon = info->CreateTimestamp.Month; + tm.year = info->CreateTimestamp.Year; + p_fs->fs_func->set_entry_time(ep, &tm, TM_CREATE); + + tm.sec = info->ModifyTimestamp.Second; + tm.min = info->ModifyTimestamp.Minute; + tm.hour = info->ModifyTimestamp.Hour; + tm.day = info->ModifyTimestamp.Day; + tm.mon = info->ModifyTimestamp.Month; + tm.year = info->ModifyTimestamp.Year; + p_fs->fs_func->set_entry_time(ep, &tm, TM_MODIFY); + + + p_fs->fs_func->set_entry_size(ep2, info->Size); + + if (p_fs->vol_type != EXFAT) { + buf_modify(sb, sector); + } else { + update_dir_checksum_with_entry_set(sb, es); + release_entry_set(es); + } + + if (p_fs->dev_ejected) + return FFS_MEDIAERR; + + return FFS_SUCCESS; +} /* end of ffsSetStat */ + +INT32 ffsMapCluster(struct inode *inode, INT32 clu_offset, UINT32 *clu) +{ + INT32 num_clusters, num_alloced, modified = FALSE; + UINT32 last_clu, sector = 0; + CHAIN_T new_clu; + DENTRY_T *ep; + ENTRY_SET_CACHE_T *es = NULL; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + FILE_ID_T *fid = &(EXFAT_I(inode)->fid); + + fid->rwoffset = (INT64)(clu_offset) << p_fs->cluster_size_bits; + + if (EXFAT_I(inode)->mmu_private == 0) + num_clusters = 0; + else + num_clusters = (INT32)((EXFAT_I(inode)->mmu_private-1) >> p_fs->cluster_size_bits) + 1; + + *clu = last_clu = fid->start_clu; + + if (fid->flags == 0x03) { + if ((clu_offset > 0) && (*clu != CLUSTER_32(~0))) { + last_clu += clu_offset - 1; + + if (clu_offset == num_clusters) + *clu = CLUSTER_32(~0); + else + *clu += clu_offset; + } + } else { + /* hint information */ + if ((clu_offset > 0) && (fid->hint_last_off > 0) && + (clu_offset >= fid->hint_last_off)) { + clu_offset -= fid->hint_last_off; + *clu = fid->hint_last_clu; + } + + while ((clu_offset > 0) && (*clu != CLUSTER_32(~0))) { + last_clu = *clu; + if (FAT_read(sb, *clu, clu) == -1) + return FFS_MEDIAERR; + clu_offset--; + } + } + + if (*clu == CLUSTER_32(~0)) { + fs_set_vol_flags(sb, VOL_DIRTY); + + new_clu.dir = (last_clu == CLUSTER_32(~0)) ? CLUSTER_32(~0) : last_clu+1; + new_clu.size = 0; + new_clu.flags = fid->flags; + + /* (1) allocate a cluster */ + num_alloced = p_fs->fs_func->alloc_cluster(sb, 1, &new_clu); + if (num_alloced < 1) + return FFS_FULL; + + /* (2) append to the FAT chain */ + if (last_clu == CLUSTER_32(~0)) { + if (new_clu.flags == 0x01) + fid->flags = 0x01; + fid->start_clu = new_clu.dir; + modified = TRUE; + } else { + if (new_clu.flags != fid->flags) { + exfat_chain_cont_cluster(sb, fid->start_clu, num_clusters); + fid->flags = 0x01; + modified = TRUE; + } + if (new_clu.flags == 0x01) + FAT_write(sb, last_clu, new_clu.dir); + } + + *clu = new_clu.dir; + + if (p_fs->vol_type == EXFAT) { + es = get_entry_set_in_dir(sb, &(fid->dir), fid->entry, ES_ALL_ENTRIES, &ep); + if (es == NULL) + return FFS_MEDIAERR; + /* get stream entry */ + ep++; + } + + /* (3) update directory entry */ + if (modified) { + if (p_fs->vol_type != EXFAT) { + ep = get_entry_in_dir(sb, &(fid->dir), fid->entry, §or); + if (!ep) + return FFS_MEDIAERR; + } + + if (p_fs->fs_func->get_entry_flag(ep) != fid->flags) + p_fs->fs_func->set_entry_flag(ep, fid->flags); + + if (p_fs->fs_func->get_entry_clu0(ep) != fid->start_clu) + p_fs->fs_func->set_entry_clu0(ep, fid->start_clu); + + if (p_fs->vol_type != EXFAT) + buf_modify(sb, sector); + } + + if (p_fs->vol_type == EXFAT) { + update_dir_checksum_with_entry_set(sb, es); + release_entry_set(es); + } + + /* add number of new blocks to inode */ + inode->i_blocks += num_alloced << (p_fs->cluster_size_bits - 9); + } + + /* hint information */ + fid->hint_last_off = (INT32)(fid->rwoffset >> p_fs->cluster_size_bits); + fid->hint_last_clu = *clu; + + if (p_fs->dev_ejected) + return FFS_MEDIAERR; + + return FFS_SUCCESS; +} /* end of ffsMapCluster */ + +/*----------------------------------------------------------------------*/ +/* Directory Operation Functions */ +/*----------------------------------------------------------------------*/ + +/* ffsCreateDir : create(make) a directory */ +INT32 ffsCreateDir(struct inode *inode, UINT8 *path, FILE_ID_T *fid) +{ + INT32 ret/*, dentry*/; + CHAIN_T dir; + UNI_NAME_T uni_name; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + PRINTK("ffsCreateDir entered\n"); + + /* check the validity of directory name in the given old pathname */ + ret = resolve_path(inode, path, &dir, &uni_name); + if (ret) + return ret; + + fs_set_vol_flags(sb, VOL_DIRTY); + + ret = create_dir(inode, &dir, &uni_name, fid); + +#if (DELAYED_SYNC == 0) + fs_sync(sb, 0); + fs_set_vol_flags(sb, VOL_CLEAN); +#endif + + if (p_fs->dev_ejected) + return FFS_MEDIAERR; + + return ret; +} /* end of ffsCreateDir */ + +/* ffsReadDir : read a directory entry from the opened directory */ +INT32 ffsReadDir(struct inode *inode, DIR_ENTRY_T *dir_entry) +{ + INT32 i, dentry, clu_offset; + INT32 dentries_per_clu, dentries_per_clu_bits = 0; + UINT32 type, sector; + CHAIN_T dir, clu; + UNI_NAME_T uni_name; + TIMESTAMP_T tm; + DENTRY_T *ep; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + FILE_ID_T *fid = &(EXFAT_I(inode)->fid); + + /* check if the given file ID is opened */ + if (fid->type != TYPE_DIR) + return FFS_PERMISSIONERR; + + if (fid->entry == -1) { + dir.dir = p_fs->root_dir; + dir.flags = 0x01; + } else { + dir.dir = fid->start_clu; + dir.size = (INT32)(fid->size >> p_fs->cluster_size_bits); + dir.flags = fid->flags; + } + + dentry = (INT32) fid->rwoffset; + + if (dir.dir == CLUSTER_32(0)) { /* FAT16 root_dir */ + dentries_per_clu = p_fs->dentries_in_root; + + if (dentry == dentries_per_clu) { + clu.dir = CLUSTER_32(~0); + } else { + clu.dir = dir.dir; + clu.size = dir.size; + clu.flags = dir.flags; + } + } else { + dentries_per_clu = p_fs->dentries_per_clu; + dentries_per_clu_bits = my_log2(dentries_per_clu); + + clu_offset = dentry >> dentries_per_clu_bits; + clu.dir = dir.dir; + clu.size = dir.size; + clu.flags = dir.flags; + + if (clu.flags == 0x03) { + clu.dir += clu_offset; + clu.size -= clu_offset; + } else { + /* hint_information */ + if ((clu_offset > 0) && (fid->hint_last_off > 0) && + (clu_offset >= fid->hint_last_off)) { + clu_offset -= fid->hint_last_off; + clu.dir = fid->hint_last_clu; + } + + while (clu_offset > 0) { + /* clu.dir = FAT_read(sb, clu.dir); */ + if (FAT_read(sb, clu.dir, &(clu.dir)) == -1) + return FFS_MEDIAERR; + + clu_offset--; + } + } + } + + while (clu.dir != CLUSTER_32(~0)) { + if (p_fs->dev_ejected) + break; + + if (dir.dir == CLUSTER_32(0)) /* FAT16 root_dir */ + i = dentry % dentries_per_clu; + else + i = dentry & (dentries_per_clu-1); + + for ( ; i < dentries_per_clu; i++, dentry++) { + ep = get_entry_in_dir(sb, &clu, i, §or); + if (!ep) + return FFS_MEDIAERR; + + type = p_fs->fs_func->get_entry_type(ep); + + if (type == TYPE_UNUSED) + break; + + if ((type != TYPE_FILE) && (type != TYPE_DIR)) + continue; + + buf_lock(sb, sector); + dir_entry->Attr = p_fs->fs_func->get_entry_attr(ep); + + p_fs->fs_func->get_entry_time(ep, &tm, TM_CREATE); + dir_entry->CreateTimestamp.Year = tm.year; + dir_entry->CreateTimestamp.Month = tm.mon; + dir_entry->CreateTimestamp.Day = tm.day; + dir_entry->CreateTimestamp.Hour = tm.hour; + dir_entry->CreateTimestamp.Minute = tm.min; + dir_entry->CreateTimestamp.Second = tm.sec; + dir_entry->CreateTimestamp.MilliSecond = 0; + + p_fs->fs_func->get_entry_time(ep, &tm, TM_MODIFY); + dir_entry->ModifyTimestamp.Year = tm.year; + dir_entry->ModifyTimestamp.Month = tm.mon; + dir_entry->ModifyTimestamp.Day = tm.day; + dir_entry->ModifyTimestamp.Hour = tm.hour; + dir_entry->ModifyTimestamp.Minute = tm.min; + dir_entry->ModifyTimestamp.Second = tm.sec; + dir_entry->ModifyTimestamp.MilliSecond = 0; + + MEMSET((INT8 *) &dir_entry->AccessTimestamp, 0, sizeof(DATE_TIME_T)); + + *(uni_name.name) = 0x0; + p_fs->fs_func->get_uni_name_from_ext_entry(sb, &dir, dentry, uni_name.name); + if (*(uni_name.name) == 0x0) + get_uni_name_from_dos_entry(sb, (DOS_DENTRY_T *) ep, &uni_name, 0x1); + nls_uniname_to_cstring(sb, dir_entry->Name, &uni_name); + buf_unlock(sb, sector); + + if (p_fs->vol_type == EXFAT) { + ep = get_entry_in_dir(sb, &clu, i+1, NULL); + if (!ep) + return FFS_MEDIAERR; + } else { + get_uni_name_from_dos_entry(sb, (DOS_DENTRY_T *) ep, &uni_name, 0x0); + nls_uniname_to_cstring(sb, dir_entry->ShortName, &uni_name); + } + + dir_entry->Size = p_fs->fs_func->get_entry_size(ep); + + /* hint information */ + if (dir.dir == CLUSTER_32(0)) { /* FAT16 root_dir */ + } else { + fid->hint_last_off = dentry >> dentries_per_clu_bits; + fid->hint_last_clu = clu.dir; + } + + fid->rwoffset = (INT64) ++dentry; + + if (p_fs->dev_ejected) + return FFS_MEDIAERR; + + return FFS_SUCCESS; + } + + if (dir.dir == CLUSTER_32(0)) + break; /* FAT16 root_dir */ + + if (clu.flags == 0x03) { + if ((--clu.size) > 0) + clu.dir++; + else + clu.dir = CLUSTER_32(~0); + } else { + /* clu.dir = FAT_read(sb, clu.dir); */ + if (FAT_read(sb, clu.dir, &(clu.dir)) == -1) + return FFS_MEDIAERR; + } + } + + *(dir_entry->Name) = '\0'; + + fid->rwoffset = (INT64) ++dentry; + + if (p_fs->dev_ejected) + return FFS_MEDIAERR; + + return FFS_SUCCESS; +} /* end of ffsReadDir */ + +/* ffsRemoveDir : remove a directory */ +INT32 ffsRemoveDir(struct inode *inode, FILE_ID_T *fid) +{ + INT32 dentry; + CHAIN_T dir, clu_to_free; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + dir.dir = fid->dir.dir; + dir.size = fid->dir.size; + dir.flags = fid->dir.flags; + + dentry = fid->entry; + + /* check if the file is "." or ".." */ + if (p_fs->vol_type != EXFAT) { + if ((dir.dir != p_fs->root_dir) && (dentry < 2)) + return FFS_PERMISSIONERR; + } + + clu_to_free.dir = fid->start_clu; + clu_to_free.size = (INT32)((fid->size-1) >> p_fs->cluster_size_bits) + 1; + clu_to_free.flags = fid->flags; + + if (!is_dir_empty(sb, &clu_to_free)) + return FFS_FILEEXIST; + + fs_set_vol_flags(sb, VOL_DIRTY); + + /* (1) update the directory entry */ + remove_file(inode, &dir, dentry); + + /* (2) free the clusters */ + p_fs->fs_func->free_cluster(sb, &clu_to_free, 1); + + fid->size = 0; + fid->start_clu = CLUSTER_32(~0); + fid->flags = (p_fs->vol_type == EXFAT)? 0x03: 0x01; + +#if (DELAYED_SYNC == 0) + fs_sync(sb, 0); + fs_set_vol_flags(sb, VOL_CLEAN); +#endif + + if (p_fs->dev_ejected) + return FFS_MEDIAERR; + + return FFS_SUCCESS; +} /* end of ffsRemoveDir */ + +/*======================================================================*/ +/* Local Function Definitions */ +/*======================================================================*/ + +/* + * File System Management Functions + */ + +INT32 fs_init(void) +{ + /* critical check for system requirement on size of DENTRY_T structure */ + if (sizeof(DENTRY_T) != DENTRY_SIZE) { + return FFS_ALIGNMENTERR; + } + + if (sizeof(DOS_DENTRY_T) != DENTRY_SIZE) { + return FFS_ALIGNMENTERR; + } + + if (sizeof(EXT_DENTRY_T) != DENTRY_SIZE) { + return FFS_ALIGNMENTERR; + } + + if (sizeof(FILE_DENTRY_T) != DENTRY_SIZE) { + return FFS_ALIGNMENTERR; + } + + if (sizeof(STRM_DENTRY_T) != DENTRY_SIZE) { + return FFS_ALIGNMENTERR; + } + + if (sizeof(NAME_DENTRY_T) != DENTRY_SIZE) { + return FFS_ALIGNMENTERR; + } + + if (sizeof(BMAP_DENTRY_T) != DENTRY_SIZE) { + return FFS_ALIGNMENTERR; + } + + if (sizeof(CASE_DENTRY_T) != DENTRY_SIZE) { + return FFS_ALIGNMENTERR; + } + + if (sizeof(VOLM_DENTRY_T) != DENTRY_SIZE) { + return FFS_ALIGNMENTERR; + } + + return FFS_SUCCESS; +} /* end of fs_init */ + +INT32 fs_shutdown(void) +{ + return FFS_SUCCESS; +} /* end of fs_shutdown */ + +void fs_set_vol_flags(struct super_block *sb, UINT32 new_flag) +{ + PBR_SECTOR_T *p_pbr; + BPBEX_T *p_bpb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + if (p_fs->vol_flag == new_flag) + return; + + p_fs->vol_flag = new_flag; + + if (p_fs->vol_type == EXFAT) { + if (p_fs->pbr_bh == NULL) { + if (sector_read(sb, p_fs->PBR_sector, &(p_fs->pbr_bh), 1) != FFS_SUCCESS) + return; + } + + p_pbr = (PBR_SECTOR_T *) p_fs->pbr_bh->b_data; + p_bpb = (BPBEX_T *) p_pbr->bpb; + SET16(p_bpb->vol_flags, (UINT16) new_flag); + + /* XXX duyoung + what can we do here? (cuz fs_set_vol_flags() is void) */ + if ((new_flag == VOL_DIRTY) && (!buffer_dirty(p_fs->pbr_bh))) + sector_write(sb, p_fs->PBR_sector, p_fs->pbr_bh, 1); + else + sector_write(sb, p_fs->PBR_sector, p_fs->pbr_bh, 0); + } +} /* end of fs_set_vol_flags */ + +void fs_sync(struct super_block *sb, INT32 do_sync) +{ + if (do_sync) + bdev_sync(sb); +} /* end of fs_sync */ + +void fs_error(struct super_block *sb) +{ + struct exfat_mount_options *opts = &EXFAT_SB(sb)->options; + + if (opts->errors == EXFAT_ERRORS_PANIC) + panic("[EXFAT] Filesystem panic from previous error\n"); + else if ((opts->errors == EXFAT_ERRORS_RO) && !(sb->s_flags & MS_RDONLY)) { + sb->s_flags |= MS_RDONLY; + printk(KERN_ERR "[EXFAT] Filesystem has been set read-only\n"); + } +} + +/* + * Cluster Management Functions + */ + +INT32 clear_cluster(struct super_block *sb, UINT32 clu) +{ + UINT32 s, n; + INT32 ret = FFS_SUCCESS; + struct buffer_head *tmp_bh = NULL; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); + + if (clu == CLUSTER_32(0)) { /* FAT16 root_dir */ + s = p_fs->root_start_sector; + n = p_fs->data_start_sector; + } else { + s = START_SECTOR(clu); + n = s + p_fs->sectors_per_clu; + } + + for ( ; s < n; s++) { + if ((ret = sector_read(sb, s, &tmp_bh, 0)) != FFS_SUCCESS) + return ret; + + MEMSET((INT8 *) tmp_bh->b_data, 0x0, p_bd->sector_size); + if ((ret = sector_write(sb, s, tmp_bh, 0)) !=FFS_SUCCESS) + break; + } + + brelse(tmp_bh); + return ret; +} /* end of clear_cluster */ + +INT32 fat_alloc_cluster(struct super_block *sb, INT32 num_alloc, CHAIN_T *p_chain) +{ + INT32 i, num_clusters = 0; + UINT32 new_clu, last_clu = CLUSTER_32(~0), read_clu; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + new_clu = p_chain->dir; + if (new_clu == CLUSTER_32(~0)) + new_clu = p_fs->clu_srch_ptr; + else if (new_clu >= p_fs->num_clusters) + new_clu = 2; + + __set_sb_dirty(sb); + + p_chain->dir = CLUSTER_32(~0); + + for (i = 2; i < p_fs->num_clusters; i++) { + if (FAT_read(sb, new_clu, &read_clu) != 0) + return 0; + + if (read_clu == CLUSTER_32(0)) { + FAT_write(sb, new_clu, CLUSTER_32(~0)); + num_clusters++; + + if (p_chain->dir == CLUSTER_32(~0)) + p_chain->dir = new_clu; + else + FAT_write(sb, last_clu, new_clu); + + last_clu = new_clu; + + if ((--num_alloc) == 0) { + p_fs->clu_srch_ptr = new_clu; + if (p_fs->used_clusters != (UINT32) ~0) + p_fs->used_clusters += num_clusters; + + return(num_clusters); + } + } + if ((++new_clu) >= p_fs->num_clusters) + new_clu = 2; + } + + p_fs->clu_srch_ptr = new_clu; + if (p_fs->used_clusters != (UINT32) ~0) + p_fs->used_clusters += num_clusters; + + return(num_clusters); +} /* end of fat_alloc_cluster */ + +INT32 exfat_alloc_cluster(struct super_block *sb, INT32 num_alloc, CHAIN_T *p_chain) +{ + INT32 num_clusters = 0; + UINT32 hint_clu, new_clu, last_clu = CLUSTER_32(~0); + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + hint_clu = p_chain->dir; + if (hint_clu == CLUSTER_32(~0)) { + hint_clu = test_alloc_bitmap(sb, p_fs->clu_srch_ptr-2); + if (hint_clu == CLUSTER_32(~0)) + return 0; + } else if (hint_clu >= p_fs->num_clusters) { + hint_clu = 2; + p_chain->flags = 0x01; + } + + __set_sb_dirty(sb); + + p_chain->dir = CLUSTER_32(~0); + + while ((new_clu = test_alloc_bitmap(sb, hint_clu-2)) != CLUSTER_32(~0)) { + if (new_clu != hint_clu) { + if (p_chain->flags == 0x03) { + exfat_chain_cont_cluster(sb, p_chain->dir, num_clusters); + p_chain->flags = 0x01; + } + } + + if (set_alloc_bitmap(sb, new_clu-2) != FFS_SUCCESS) + return 0; + + num_clusters++; + + if (p_chain->flags == 0x01) + FAT_write(sb, new_clu, CLUSTER_32(~0)); + + if (p_chain->dir == CLUSTER_32(~0)) { + p_chain->dir = new_clu; + } else { + if (p_chain->flags == 0x01) + FAT_write(sb, last_clu, new_clu); + } + last_clu = new_clu; + + if ((--num_alloc) == 0) { + p_fs->clu_srch_ptr = hint_clu; + if (p_fs->used_clusters != (UINT32) ~0) + p_fs->used_clusters += num_clusters; + + p_chain->size += num_clusters; + return(num_clusters); + } + + hint_clu = new_clu + 1; + if (hint_clu >= p_fs->num_clusters) { + hint_clu = 2; + + if (p_chain->flags == 0x03) { + exfat_chain_cont_cluster(sb, p_chain->dir, num_clusters); + p_chain->flags = 0x01; + } + } + } + + p_fs->clu_srch_ptr = hint_clu; + if (p_fs->used_clusters != (UINT32) ~0) + p_fs->used_clusters += num_clusters; + + p_chain->size += num_clusters; + return(num_clusters); +} /* end of exfat_alloc_cluster */ + +void fat_free_cluster(struct super_block *sb, CHAIN_T *p_chain, INT32 do_relse) +{ + INT32 num_clusters = 0; + UINT32 clu, prev; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + INT32 i; + UINT32 sector; + + if ((p_chain->dir == CLUSTER_32(0)) || (p_chain->dir == CLUSTER_32(~0))) + return; + __set_sb_dirty(sb); + clu = p_chain->dir; + + if (p_chain->size <= 0) + return; + + do { + if (p_fs->dev_ejected) + break; + + if (do_relse) { + sector = START_SECTOR(clu); + for (i = 0; i < p_fs->sectors_per_clu; i++) { + buf_release(sb, sector+i); + } + } + + prev = clu; + if (FAT_read(sb, clu, &clu) == -1) + break; + + FAT_write(sb, prev, CLUSTER_32(0)); + num_clusters++; + + } while (clu != CLUSTER_32(~0)); + + if (p_fs->used_clusters != (UINT32) ~0) + p_fs->used_clusters -= num_clusters; +} /* end of fat_free_cluster */ + +void exfat_free_cluster(struct super_block *sb, CHAIN_T *p_chain, INT32 do_relse) +{ + INT32 num_clusters = 0; + UINT32 clu; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + INT32 i; + UINT32 sector; + + if ((p_chain->dir == CLUSTER_32(0)) || (p_chain->dir == CLUSTER_32(~0))) + return; + + if (p_chain->size <= 0) { + printk(KERN_ERR "[EXFAT] free_cluster : skip free-req clu:%u, " + "because of zero-size truncation\n" + ,p_chain->dir); + return; + } + + __set_sb_dirty(sb); + clu = p_chain->dir; + + if (p_chain->flags == 0x03) { + do { + if (do_relse) { + sector = START_SECTOR(clu); + for (i = 0; i < p_fs->sectors_per_clu; i++) { + buf_release(sb, sector+i); + } + } + + if (clr_alloc_bitmap(sb, clu-2) != FFS_SUCCESS) + break; + clu++; + + num_clusters++; + } while (num_clusters < p_chain->size); + } else { + do { + if (p_fs->dev_ejected) + break; + + if (do_relse) { + sector = START_SECTOR(clu); + for (i = 0; i < p_fs->sectors_per_clu; i++) { + buf_release(sb, sector+i); + } + } + + if (clr_alloc_bitmap(sb, clu-2) != FFS_SUCCESS) + break; + + if (FAT_read(sb, clu, &clu) == -1) + break; + num_clusters++; + } while ((clu != CLUSTER_32(0)) && (clu != CLUSTER_32(~0))); + } + + if (p_fs->used_clusters != (UINT32) ~0) + p_fs->used_clusters -= num_clusters; +} /* end of exfat_free_cluster */ + +UINT32 find_last_cluster(struct super_block *sb, CHAIN_T *p_chain) +{ + UINT32 clu, next; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + clu = p_chain->dir; + + if (p_chain->flags == 0x03) { + clu += p_chain->size - 1; + } else { + while((FAT_read(sb, clu, &next) == 0) && (next != CLUSTER_32(~0))) { + if (p_fs->dev_ejected) + break; + clu = next; + } + } + + return(clu); +} /* end of find_last_cluster */ + +INT32 count_num_clusters(struct super_block *sb, CHAIN_T *p_chain) +{ + INT32 i, count = 0; + UINT32 clu; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + if ((p_chain->dir == CLUSTER_32(0)) || (p_chain->dir == CLUSTER_32(~0))) + return 0; + + clu = p_chain->dir; + + if (p_chain->flags == 0x03) { + count = p_chain->size; + } else { + for (i = 2; i < p_fs->num_clusters; i++) { + count++; + if (FAT_read(sb, clu, &clu) != 0) + return 0; + if (clu == CLUSTER_32(~0)) + break; + } + } + + return(count); +} /* end of count_num_clusters */ + +INT32 fat_count_used_clusters(struct super_block *sb) +{ + INT32 i, count = 0; + UINT32 clu; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + for (i = 2; i < p_fs->num_clusters; i++) { + if (FAT_read(sb, i, &clu) != 0) + break; + if (clu != CLUSTER_32(0)) + count++; + } + + return(count); +} /* end of fat_count_used_clusters */ + +INT32 exfat_count_used_clusters(struct super_block *sb) +{ + INT32 i, map_i, map_b, count = 0; + UINT8 k; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); + + map_i = map_b = 0; + + for (i = 2; i < p_fs->num_clusters; i += 8) { + k = *(((UINT8 *) p_fs->vol_amap[map_i]->b_data) + map_b); + count += used_bit[k]; + + if ((++map_b) >= p_bd->sector_size) { + map_i++; + map_b = 0; + } + } + + return(count); +} /* end of exfat_count_used_clusters */ + +void exfat_chain_cont_cluster(struct super_block *sb, UINT32 chain, INT32 len) +{ + if (len == 0) + return; + + while (len > 1) { + FAT_write(sb, chain, chain+1); + chain++; + len--; + } + FAT_write(sb, chain, CLUSTER_32(~0)); +} /* end of exfat_chain_cont_cluster */ + +/* + * Allocation Bitmap Management Functions + */ + +INT32 load_alloc_bitmap(struct super_block *sb) +{ + INT32 i, j, ret; + UINT32 map_size; + UINT32 type, sector; + CHAIN_T clu; + BMAP_DENTRY_T *ep; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); + + clu.dir = p_fs->root_dir; + clu.flags = 0x01; + + while (clu.dir != CLUSTER_32(~0)) { + if (p_fs->dev_ejected) + break; + + for (i = 0; i < p_fs->dentries_per_clu; i++) { + ep = (BMAP_DENTRY_T *) get_entry_in_dir(sb, &clu, i, NULL); + if (!ep) + return FFS_MEDIAERR; + + type = p_fs->fs_func->get_entry_type((DENTRY_T *) ep); + + if (type == TYPE_UNUSED) + break; + if (type != TYPE_BITMAP) + continue; + + if (ep->flags == 0x0) { + p_fs->map_clu = GET32_A(ep->start_clu); + map_size = (UINT32) GET64_A(ep->size); + + p_fs->map_sectors = ((map_size-1) >> p_bd->sector_size_bits) + 1; + + p_fs->vol_amap = (struct buffer_head **) MALLOC(sizeof(struct buffer_head *) * p_fs->map_sectors); + if (p_fs->vol_amap == NULL) + return FFS_MEMORYERR; + + sector = START_SECTOR(p_fs->map_clu); + + for (j = 0; j < p_fs->map_sectors; j++) { + p_fs->vol_amap[j] = NULL; + ret = sector_read(sb, sector+j, &(p_fs->vol_amap[j]), 1); + if (ret != FFS_SUCCESS) { + /* release all buffers and free vol_amap */ + i=0; + while (i < j) + brelse(p_fs->vol_amap[i++]); + + FREE(p_fs->vol_amap); + p_fs->vol_amap = NULL; + return ret; + } + } + + p_fs->pbr_bh = NULL; + return FFS_SUCCESS; + } + } + + if (FAT_read(sb, clu.dir, &(clu.dir)) != 0) + return FFS_MEDIAERR; + } + + return FFS_FORMATERR; +} /* end of load_alloc_bitmap */ + +void free_alloc_bitmap(struct super_block *sb) +{ + INT32 i; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + brelse(p_fs->pbr_bh); + + for (i = 0; i < p_fs->map_sectors; i++) { + __brelse(p_fs->vol_amap[i]); + } + + FREE(p_fs->vol_amap); + p_fs->vol_amap = NULL; +} /* end of free_alloc_bitmap */ + +INT32 set_alloc_bitmap(struct super_block *sb, UINT32 clu) +{ + INT32 i, b; + UINT32 sector; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); + + i = clu >> (p_bd->sector_size_bits + 3); + b = clu & ((p_bd->sector_size << 3) - 1); + + sector = START_SECTOR(p_fs->map_clu) + i; + + Bitmap_set((UINT8 *) p_fs->vol_amap[i]->b_data, b); + + return (sector_write(sb, sector, p_fs->vol_amap[i], 0)); +} /* end of set_alloc_bitmap */ + +INT32 clr_alloc_bitmap(struct super_block *sb, UINT32 clu) +{ + INT32 i, b; + UINT32 sector; +#if EXFAT_CONFIG_DISCARD + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct exfat_mount_options *opts = &sbi->options; + int ret; +#endif /* EXFAT_CONFIG_DISCARD */ + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); + + i = clu >> (p_bd->sector_size_bits + 3); + b = clu & ((p_bd->sector_size << 3) - 1); + + sector = START_SECTOR(p_fs->map_clu) + i; + + Bitmap_clear((UINT8 *) p_fs->vol_amap[i]->b_data, b); + + return (sector_write(sb, sector, p_fs->vol_amap[i], 0)); + +#if EXFAT_CONFIG_DISCARD + if (opts->discard) { +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) + ret = sb_issue_discard(sb, START_SECTOR(clu), (1 << p_fs->sectors_per_clu_bits)); +#else + ret = sb_issue_discard(sb, START_SECTOR(clu), (1 << p_fs->sectors_per_clu_bits), GFP_NOFS, 0); +#endif + if (ret == -EOPNOTSUPP) { + printk(KERN_WARNING "discard not supported by device, disabling"); + opts->discard = 0; + } + } +#endif /* EXFAT_CONFIG_DISCARD */ +} /* end of clr_alloc_bitmap */ + +UINT32 test_alloc_bitmap(struct super_block *sb, UINT32 clu) +{ + INT32 i, map_i, map_b; + UINT32 clu_base, clu_free; + UINT8 k, clu_mask; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); + + clu_base = (clu & ~(0x7)) + 2; + clu_mask = (1 << (clu - clu_base + 2)) - 1; + + map_i = clu >> (p_bd->sector_size_bits + 3); + map_b = (clu >> 3) & p_bd->sector_size_mask; + + for (i = 2; i < p_fs->num_clusters; i += 8) { + k = *(((UINT8 *) p_fs->vol_amap[map_i]->b_data) + map_b); + if (clu_mask > 0) { + k |= clu_mask; + clu_mask = 0; + } + if (k < 0xFF) { + clu_free = clu_base + free_bit[k]; + if (clu_free < p_fs->num_clusters) + return(clu_free); + } + clu_base += 8; + + if (((++map_b) >= p_bd->sector_size) || (clu_base >= p_fs->num_clusters)) { + if ((++map_i) >= p_fs->map_sectors) { + clu_base = 2; + map_i = 0; + } + map_b = 0; + } + } + + return(CLUSTER_32(~0)); +} /* end of test_alloc_bitmap */ + +void sync_alloc_bitmap(struct super_block *sb) +{ + INT32 i; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + if (p_fs->vol_amap == NULL) + return; + + for (i = 0; i < p_fs->map_sectors; i++) { + sync_dirty_buffer(p_fs->vol_amap[i]); + } +} /* end of sync_alloc_bitmap */ + +/* + * Upcase table Management Functions + */ +INT32 __load_upcase_table(struct super_block *sb, UINT32 sector, UINT32 num_sectors, UINT32 utbl_checksum) +{ + INT32 i, ret = FFS_ERROR; + UINT32 j; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); + struct buffer_head *tmp_bh = NULL; + + UINT8 skip = FALSE; + UINT32 index = 0; + UINT16 uni = 0; + UINT16 **upcase_table; + + UINT32 checksum = 0; + + upcase_table = p_fs->vol_utbl = (UINT16 **) MALLOC(UTBL_COL_COUNT * sizeof(UINT16 *)); + if(upcase_table == NULL) + return FFS_MEMORYERR; + MEMSET(upcase_table, 0, UTBL_COL_COUNT * sizeof(UINT16 *)); + + num_sectors += sector; + + while(sector < num_sectors) { + ret = sector_read(sb, sector, &tmp_bh, 1); + if (ret != FFS_SUCCESS) { + PRINTK("sector read (0x%X)fail\n", sector); + goto error; + } + sector++; + + for(i = 0; i < p_bd->sector_size && index <= 0xFFFF; i += 2) { + uni = GET16(((UINT8 *) tmp_bh->b_data)+i); + + checksum = ((checksum & 1) ? 0x80000000 : 0 ) + (checksum >> 1) + *(((UINT8 *) tmp_bh->b_data)+i); + checksum = ((checksum & 1) ? 0x80000000 : 0 ) + (checksum >> 1) + *(((UINT8 *) tmp_bh->b_data)+(i+1)); + + if(skip) { + PRINTK("skip from 0x%X ", index); + index += uni; + PRINTK("to 0x%X (amount of 0x%X)\n", index, uni); + skip = FALSE; + } else if(uni == index) + index++; + else if(uni == 0xFFFF) + skip = TRUE; + else { /* uni != index , uni != 0xFFFF */ + UINT16 col_index = get_col_index(index); + + if(upcase_table[col_index]== NULL) { + PRINTK("alloc = 0x%X\n", col_index); + upcase_table[col_index] = (UINT16 *) MALLOC(UTBL_ROW_COUNT * sizeof(UINT16)); + if(upcase_table[col_index] == NULL) { + ret = FFS_MEMORYERR; + goto error; + } + + for(j = 0 ; j < UTBL_ROW_COUNT ; j++) + upcase_table[col_index][j] = (col_index << LOW_INDEX_BIT) | j; + } + + upcase_table[col_index][get_row_index(index)] = uni; + index++; + } + } + } + if(index >= 0xFFFF && utbl_checksum == checksum) { + if(tmp_bh) + brelse(tmp_bh); + return FFS_SUCCESS; + } + ret = FFS_ERROR; +error: + if(tmp_bh) + brelse(tmp_bh); + free_upcase_table(sb); + return ret; +} + +INT32 __load_default_upcase_table(struct super_block *sb) +{ + INT32 i, ret = FFS_ERROR; + UINT32 j; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + UINT8 skip = FALSE; + UINT32 index = 0; + UINT16 uni = 0; + UINT16 **upcase_table; + + upcase_table = p_fs->vol_utbl = (UINT16 **) MALLOC(UTBL_COL_COUNT * sizeof(UINT16 *)); + if(upcase_table == NULL) + return FFS_MEMORYERR; + MEMSET(upcase_table, 0, UTBL_COL_COUNT * sizeof(UINT16 *)); + + for(i = 0; index <= 0xFFFF && i < NUM_UPCASE*2; i += 2) { + uni = GET16(uni_upcase + i); + if(skip) { + PRINTK("skip from 0x%X ", index); + index += uni; + PRINTK("to 0x%X (amount of 0x%X)\n", index, uni); + skip = FALSE; + } else if(uni == index) + index++; + else if(uni == 0xFFFF) + skip = TRUE; + else { /* uni != index , uni != 0xFFFF */ + UINT16 col_index = get_col_index(index); + + if(upcase_table[col_index]== NULL) { + PRINTK("alloc = 0x%X\n", col_index); + upcase_table[col_index] = (UINT16 *) MALLOC(UTBL_ROW_COUNT * sizeof(UINT16)); + if(upcase_table[col_index] == NULL) { + ret = FFS_MEMORYERR; + goto error; + } + + for(j = 0 ; j < UTBL_ROW_COUNT ; j++) + upcase_table[col_index][j] = (col_index << LOW_INDEX_BIT) | j; + } + + upcase_table[col_index][get_row_index(index)] = uni; + index ++; + } + } + + if(index >= 0xFFFF) + return FFS_SUCCESS; + +error: + /* FATAL error: default upcase table has error */ + free_upcase_table(sb); + return ret; +} + +INT32 load_upcase_table(struct super_block *sb) +{ + INT32 i; + UINT32 tbl_clu, tbl_size; + UINT32 type, sector, num_sectors; + CHAIN_T clu; + CASE_DENTRY_T *ep; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); + + clu.dir = p_fs->root_dir; + clu.flags = 0x01; + + if (p_fs->dev_ejected) + return FFS_MEDIAERR; + + while (clu.dir != CLUSTER_32(~0)) { + for (i = 0; i < p_fs->dentries_per_clu; i++) { + ep = (CASE_DENTRY_T *) get_entry_in_dir(sb, &clu, i, NULL); + if (!ep) + return FFS_MEDIAERR; + + type = p_fs->fs_func->get_entry_type((DENTRY_T *) ep); + + if (type == TYPE_UNUSED) + break; + if (type != TYPE_UPCASE) + continue; + + tbl_clu = GET32_A(ep->start_clu); + tbl_size = (UINT32) GET64_A(ep->size); + + sector = START_SECTOR(tbl_clu); + num_sectors = ((tbl_size-1) >> p_bd->sector_size_bits) + 1; + if(__load_upcase_table(sb, sector, num_sectors, GET32_A(ep->checksum)) != FFS_SUCCESS) + break; + else + return FFS_SUCCESS; + } + if (FAT_read(sb, clu.dir, &(clu.dir)) != 0) + return FFS_MEDIAERR; + } + /* load default upcase table */ + return __load_default_upcase_table(sb); +} /* end of load_upcase_table */ + +void free_upcase_table(struct super_block *sb) +{ + UINT32 i; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + UINT16 **upcase_table; + + upcase_table = p_fs->vol_utbl; + for(i = 0 ; i < UTBL_COL_COUNT ; i ++) + FREE(upcase_table[i]); + + FREE(p_fs->vol_utbl); + + p_fs->vol_utbl = NULL; +} /* end of free_upcase_table */ + +/* + * Directory Entry Management Functions + */ + +UINT32 fat_get_entry_type(DENTRY_T *p_entry) +{ + DOS_DENTRY_T *ep = (DOS_DENTRY_T *) p_entry; + + if (*(ep->name) == 0x0) + return TYPE_UNUSED; + + else if (*(ep->name) == 0xE5) + return TYPE_DELETED; + + else if (ep->attr == ATTR_EXTEND) + return TYPE_EXTEND; + + else if ((ep->attr & (ATTR_SUBDIR|ATTR_VOLUME)) == ATTR_VOLUME) + return TYPE_VOLUME; + + else if ((ep->attr & (ATTR_SUBDIR|ATTR_VOLUME)) == ATTR_SUBDIR) + return TYPE_DIR; + + return TYPE_FILE; +} /* end of fat_get_entry_type */ + +UINT32 exfat_get_entry_type(DENTRY_T *p_entry) +{ + FILE_DENTRY_T *ep = (FILE_DENTRY_T *) p_entry; + + if (ep->type == 0x0) { + return TYPE_UNUSED; + } else if (ep->type < 0x80) { + return TYPE_DELETED; + } else if (ep->type == 0x80) { + return TYPE_INVALID; + } else if (ep->type < 0xA0) { + if (ep->type == 0x81) { + return TYPE_BITMAP; + } else if (ep->type == 0x82) { + return TYPE_UPCASE; + } else if (ep->type == 0x83) { + return TYPE_VOLUME; + } else if (ep->type == 0x85) { + if (GET16_A(ep->attr) & ATTR_SUBDIR) + return TYPE_DIR; + else + return TYPE_FILE; + } + return TYPE_CRITICAL_PRI; + } else if (ep->type < 0xC0) { + if (ep->type == 0xA0) { + return TYPE_GUID; + } else if (ep->type == 0xA1) { + return TYPE_PADDING; + } else if (ep->type == 0xA2) { + return TYPE_ACLTAB; + } + return TYPE_BENIGN_PRI; + } else if (ep->type < 0xE0) { + if (ep->type == 0xC0) { + return TYPE_STREAM; + } else if (ep->type == 0xC1) { + return TYPE_EXTEND; + } else if (ep->type == 0xC2) { + return TYPE_ACL; + } + return TYPE_CRITICAL_SEC; + } + + return TYPE_BENIGN_SEC; +} /* end of exfat_get_entry_type */ + +void fat_set_entry_type(DENTRY_T *p_entry, UINT32 type) +{ + DOS_DENTRY_T *ep = (DOS_DENTRY_T *) p_entry; + + if (type == TYPE_UNUSED) + *(ep->name) = 0x0; + + else if (type == TYPE_DELETED) + *(ep->name) = 0xE5; + + else if (type == TYPE_EXTEND) + ep->attr = ATTR_EXTEND; + + else if (type == TYPE_DIR) + ep->attr = ATTR_SUBDIR; + + else if (type == TYPE_FILE) + ep->attr = ATTR_ARCHIVE; + + else if (type == TYPE_SYMLINK) + ep->attr = ATTR_ARCHIVE | ATTR_SYMLINK; +} /* end of fat_set_entry_type */ + +void exfat_set_entry_type(DENTRY_T *p_entry, UINT32 type) +{ + FILE_DENTRY_T *ep = (FILE_DENTRY_T *) p_entry; + + if (type == TYPE_UNUSED) { + ep->type = 0x0; + } else if (type == TYPE_DELETED) { + ep->type &= ~0x80; + } else if (type == TYPE_STREAM) { + ep->type = 0xC0; + } else if (type == TYPE_EXTEND) { + ep->type = 0xC1; + } else if (type == TYPE_BITMAP) { + ep->type = 0x81; + } else if (type == TYPE_UPCASE) { + ep->type = 0x82; + } else if (type == TYPE_VOLUME) { + ep->type = 0x83; + } else if (type == TYPE_DIR) { + ep->type = 0x85; + SET16_A(ep->attr, ATTR_SUBDIR); + } else if (type == TYPE_FILE) { + ep->type = 0x85; + SET16_A(ep->attr, ATTR_ARCHIVE); + } else if (type == TYPE_SYMLINK) { + ep->type = 0x85; + SET16_A(ep->attr, ATTR_ARCHIVE | ATTR_SYMLINK); + } +} /* end of exfat_set_entry_type */ + +UINT32 fat_get_entry_attr(DENTRY_T *p_entry) +{ + DOS_DENTRY_T *ep = (DOS_DENTRY_T *) p_entry; + return((UINT32) ep->attr); +} /* end of fat_get_entry_attr */ + +UINT32 exfat_get_entry_attr(DENTRY_T *p_entry) +{ + FILE_DENTRY_T *ep = (FILE_DENTRY_T *) p_entry; + return((UINT32) GET16_A(ep->attr)); +} /* end of exfat_get_entry_attr */ + +void fat_set_entry_attr(DENTRY_T *p_entry, UINT32 attr) +{ + DOS_DENTRY_T *ep = (DOS_DENTRY_T *) p_entry; + ep->attr = (UINT8) attr; +} /* end of fat_set_entry_attr */ + +void exfat_set_entry_attr(DENTRY_T *p_entry, UINT32 attr) +{ + FILE_DENTRY_T *ep = (FILE_DENTRY_T *) p_entry; + SET16_A(ep->attr, (UINT16) attr); +} /* end of exfat_set_entry_attr */ + +UINT8 fat_get_entry_flag(DENTRY_T *p_entry) +{ + return 0x01; +} /* end of fat_get_entry_flag */ + +UINT8 exfat_get_entry_flag(DENTRY_T *p_entry) +{ + STRM_DENTRY_T *ep = (STRM_DENTRY_T *) p_entry; + return(ep->flags); +} /* end of exfat_get_entry_flag */ + +void fat_set_entry_flag(DENTRY_T *p_entry, UINT8 flags) +{ +} /* end of fat_set_entry_flag */ + +void exfat_set_entry_flag(DENTRY_T *p_entry, UINT8 flags) +{ + STRM_DENTRY_T *ep = (STRM_DENTRY_T *) p_entry; + ep->flags = flags; +} /* end of exfat_set_entry_flag */ + +UINT32 fat_get_entry_clu0(DENTRY_T *p_entry) +{ + DOS_DENTRY_T *ep = (DOS_DENTRY_T *) p_entry; + return((GET32_A(ep->start_clu_hi) << 16) | GET16_A(ep->start_clu_lo)); +} /* end of fat_get_entry_clu0 */ + +UINT32 exfat_get_entry_clu0(DENTRY_T *p_entry) +{ + STRM_DENTRY_T *ep = (STRM_DENTRY_T *) p_entry; + return(GET32_A(ep->start_clu)); +} /* end of exfat_get_entry_clu0 */ + +void fat_set_entry_clu0(DENTRY_T *p_entry, UINT32 start_clu) +{ + DOS_DENTRY_T *ep = (DOS_DENTRY_T *) p_entry; + SET16_A(ep->start_clu_lo, CLUSTER_16(start_clu)); + SET16_A(ep->start_clu_hi, CLUSTER_16(start_clu >> 16)); +} /* end of fat_set_entry_clu0 */ + +void exfat_set_entry_clu0(DENTRY_T *p_entry, UINT32 start_clu) +{ + STRM_DENTRY_T *ep = (STRM_DENTRY_T *) p_entry; + SET32_A(ep->start_clu, start_clu); +} /* end of exfat_set_entry_clu0 */ + +UINT64 fat_get_entry_size(DENTRY_T *p_entry) +{ + DOS_DENTRY_T *ep = (DOS_DENTRY_T *) p_entry; + return((UINT64) GET32_A(ep->size)); +} /* end of fat_get_entry_size */ + +UINT64 exfat_get_entry_size(DENTRY_T *p_entry) +{ + STRM_DENTRY_T *ep = (STRM_DENTRY_T *) p_entry; + return(GET64_A(ep->valid_size)); +} /* end of exfat_get_entry_size */ + +void fat_set_entry_size(DENTRY_T *p_entry, UINT64 size) +{ + DOS_DENTRY_T *ep = (DOS_DENTRY_T *) p_entry; + SET32_A(ep->size, (UINT32) size); +} /* end of fat_set_entry_size */ + +void exfat_set_entry_size(DENTRY_T *p_entry, UINT64 size) +{ + STRM_DENTRY_T *ep = (STRM_DENTRY_T *) p_entry; + SET64_A(ep->valid_size, size); + SET64_A(ep->size, size); +} /* end of exfat_set_entry_size */ + +void fat_get_entry_time(DENTRY_T *p_entry, TIMESTAMP_T *tp, UINT8 mode) +{ + UINT16 t = 0x00, d = 0x21; + DOS_DENTRY_T *ep = (DOS_DENTRY_T *) p_entry; + + switch (mode) { + case TM_CREATE: + t = GET16_A(ep->create_time); + d = GET16_A(ep->create_date); + break; + case TM_MODIFY: + t = GET16_A(ep->modify_time); + d = GET16_A(ep->modify_date); + break; + } + + tp->sec = (t & 0x001F) << 1; + tp->min = (t >> 5) & 0x003F; + tp->hour = (t >> 11); + tp->day = (d & 0x001F); + tp->mon = (d >> 5) & 0x000F; + tp->year = (d >> 9); +} /* end of fat_get_entry_time */ + +void exfat_get_entry_time(DENTRY_T *p_entry, TIMESTAMP_T *tp, UINT8 mode) +{ + UINT16 t = 0x00, d = 0x21; + FILE_DENTRY_T *ep = (FILE_DENTRY_T *) p_entry; + + switch (mode) { + case TM_CREATE: + t = GET16_A(ep->create_time); + d = GET16_A(ep->create_date); + break; + case TM_MODIFY: + t = GET16_A(ep->modify_time); + d = GET16_A(ep->modify_date); + break; + case TM_ACCESS: + t = GET16_A(ep->access_time); + d = GET16_A(ep->access_date); + break; + } + + tp->sec = (t & 0x001F) << 1; + tp->min = (t >> 5) & 0x003F; + tp->hour = (t >> 11); + tp->day = (d & 0x001F); + tp->mon = (d >> 5) & 0x000F; + tp->year = (d >> 9); +} /* end of exfat_get_entry_time */ + +void fat_set_entry_time(DENTRY_T *p_entry, TIMESTAMP_T *tp, UINT8 mode) +{ + UINT16 t, d; + DOS_DENTRY_T *ep = (DOS_DENTRY_T *) p_entry; + + t = (tp->hour << 11) | (tp->min << 5) | (tp->sec >> 1); + d = (tp->year << 9) | (tp->mon << 5) | tp->day; + + switch (mode) { + case TM_CREATE: + SET16_A(ep->create_time, t); + SET16_A(ep->create_date, d); + break; + case TM_MODIFY: + SET16_A(ep->modify_time, t); + SET16_A(ep->modify_date, d); + break; + } +} /* end of fat_set_entry_time */ + +void exfat_set_entry_time(DENTRY_T *p_entry, TIMESTAMP_T *tp, UINT8 mode) +{ + UINT16 t, d; + FILE_DENTRY_T *ep = (FILE_DENTRY_T *) p_entry; + + t = (tp->hour << 11) | (tp->min << 5) | (tp->sec >> 1); + d = (tp->year << 9) | (tp->mon << 5) | tp->day; + + switch (mode) { + case TM_CREATE: + SET16_A(ep->create_time, t); + SET16_A(ep->create_date, d); + break; + case TM_MODIFY: + SET16_A(ep->modify_time, t); + SET16_A(ep->modify_date, d); + break; + case TM_ACCESS: + SET16_A(ep->access_time, t); + SET16_A(ep->access_date, d); + break; + } +} /* end of exfat_set_entry_time */ + +INT32 fat_init_dir_entry(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, UINT32 type, + UINT32 start_clu, UINT64 size) +{ + UINT32 sector; + DOS_DENTRY_T *dos_ep; + + dos_ep = (DOS_DENTRY_T *) get_entry_in_dir(sb, p_dir, entry, §or); + if (!dos_ep) + return FFS_MEDIAERR; + + init_dos_entry(dos_ep, type, start_clu); + buf_modify(sb, sector); + + return FFS_SUCCESS; +} /* end of fat_init_dir_entry */ + +INT32 exfat_init_dir_entry(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, UINT32 type, + UINT32 start_clu, UINT64 size) +{ + UINT32 sector; + UINT8 flags; + FILE_DENTRY_T *file_ep; + STRM_DENTRY_T *strm_ep; + + flags = (type == TYPE_FILE) ? 0x01 : 0x03; + + /* we cannot use get_entry_set_in_dir here because file ep is not initialized yet */ + file_ep = (FILE_DENTRY_T *) get_entry_in_dir(sb, p_dir, entry, §or); + if (!file_ep) + return FFS_MEDIAERR; + + strm_ep = (STRM_DENTRY_T *) get_entry_in_dir(sb, p_dir, entry+1, §or); + if (!strm_ep) + return FFS_MEDIAERR; + + init_file_entry(file_ep, type); + buf_modify(sb, sector); + + init_strm_entry(strm_ep, flags, start_clu, size); + buf_modify(sb, sector); + + return FFS_SUCCESS; +} /* end of exfat_init_dir_entry */ + +INT32 fat_init_ext_entry(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, INT32 num_entries, + UNI_NAME_T *p_uniname, DOS_NAME_T *p_dosname) +{ + INT32 i; + UINT32 sector; + UINT8 chksum; + UINT16 *uniname = p_uniname->name; + DOS_DENTRY_T *dos_ep; + EXT_DENTRY_T *ext_ep; + + dos_ep = (DOS_DENTRY_T *) get_entry_in_dir(sb, p_dir, entry, §or); + if (!dos_ep) + return FFS_MEDIAERR; + + dos_ep->lcase = p_dosname->name_case; + MEMCPY(dos_ep->name, p_dosname->name, DOS_NAME_LENGTH); + buf_modify(sb, sector); + + if ((--num_entries) > 0) { + chksum = calc_checksum_1byte((void *) dos_ep->name, DOS_NAME_LENGTH, 0); + + for (i = 1; i < num_entries; i++) { + ext_ep = (EXT_DENTRY_T *) get_entry_in_dir(sb, p_dir, entry-i, §or); + if (!ext_ep) + return FFS_MEDIAERR; + + init_ext_entry(ext_ep, i, chksum, uniname); + buf_modify(sb, sector); + uniname += 13; + } + + ext_ep = (EXT_DENTRY_T *) get_entry_in_dir(sb, p_dir, entry-i, §or); + if (!ext_ep) + return FFS_MEDIAERR; + + init_ext_entry(ext_ep, i+0x40, chksum, uniname); + buf_modify(sb, sector); + } + + return FFS_SUCCESS; +} /* end of fat_init_ext_entry */ + +INT32 exfat_init_ext_entry(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, INT32 num_entries, + UNI_NAME_T *p_uniname, DOS_NAME_T *p_dosname) +{ + INT32 i; + UINT32 sector; + UINT16 *uniname = p_uniname->name; + FILE_DENTRY_T *file_ep; + STRM_DENTRY_T *strm_ep; + NAME_DENTRY_T *name_ep; + + file_ep = (FILE_DENTRY_T *) get_entry_in_dir(sb, p_dir, entry, §or); + if (!file_ep) + return FFS_MEDIAERR; + + file_ep->num_ext = (UINT8)(num_entries - 1); + buf_modify(sb, sector); + + strm_ep = (STRM_DENTRY_T *) get_entry_in_dir(sb, p_dir, entry+1, §or); + if (!strm_ep) + return FFS_MEDIAERR; + + strm_ep->name_len = p_uniname->name_len; + SET16_A(strm_ep->name_hash, p_uniname->name_hash); + buf_modify(sb, sector); + + for (i = 2; i < num_entries; i++) { + name_ep = (NAME_DENTRY_T *) get_entry_in_dir(sb, p_dir, entry+i, §or); + if (!name_ep) + return FFS_MEDIAERR; + + init_name_entry(name_ep, uniname); + buf_modify(sb, sector); + uniname += 15; + } + + update_dir_checksum(sb, p_dir, entry); + + return FFS_SUCCESS; +} /* end of exfat_init_ext_entry */ + +void init_dos_entry(DOS_DENTRY_T *ep, UINT32 type, UINT32 start_clu) +{ + TIMESTAMP_T tm, *tp; + + fat_set_entry_type((DENTRY_T *) ep, type); + SET16_A(ep->start_clu_lo, CLUSTER_16(start_clu)); + SET16_A(ep->start_clu_hi, CLUSTER_16(start_clu >> 16)); + SET32_A(ep->size, 0); + + tp = tm_current(&tm); + fat_set_entry_time((DENTRY_T *) ep, tp, TM_CREATE); + fat_set_entry_time((DENTRY_T *) ep, tp, TM_MODIFY); + SET16_A(ep->access_date, 0); + ep->create_time_ms = 0; +} /* end of init_dos_entry */ + +void init_ext_entry(EXT_DENTRY_T *ep, INT32 order, UINT8 chksum, UINT16 *uniname) +{ + INT32 i; + UINT8 end = FALSE; + + fat_set_entry_type((DENTRY_T *) ep, TYPE_EXTEND); + ep->order = (UINT8) order; + ep->sysid = 0; + ep->checksum = chksum; + SET16_A(ep->start_clu, 0); + + for (i = 0; i < 10; i += 2) { + if (!end) { + SET16(ep->unicode_0_4+i, *uniname); + if (*uniname == 0x0) + end = TRUE; + else + uniname++; + } else { + SET16(ep->unicode_0_4+i, 0xFFFF); + } + } + + for (i = 0; i < 12; i += 2) { + if (!end) { + SET16_A(ep->unicode_5_10+i, *uniname); + if (*uniname == 0x0) + end = TRUE; + else + uniname++; + } else { + SET16_A(ep->unicode_5_10+i, 0xFFFF); + } + } + + for (i = 0; i < 4; i += 2) { + if (!end) { + SET16_A(ep->unicode_11_12+i, *uniname); + if (*uniname == 0x0) + end = TRUE; + else + uniname++; + } else { + SET16_A(ep->unicode_11_12+i, 0xFFFF); + } + } +} /* end of init_ext_entry */ + +void init_file_entry(FILE_DENTRY_T *ep, UINT32 type) +{ + TIMESTAMP_T tm, *tp; + + exfat_set_entry_type((DENTRY_T *) ep, type); + + tp = tm_current(&tm); + exfat_set_entry_time((DENTRY_T *) ep, tp, TM_CREATE); + exfat_set_entry_time((DENTRY_T *) ep, tp, TM_MODIFY); + exfat_set_entry_time((DENTRY_T *) ep, tp, TM_ACCESS); + ep->create_time_ms = 0; + ep->modify_time_ms = 0; + ep->access_time_ms = 0; +} /* end of init_file_entry */ + +void init_strm_entry(STRM_DENTRY_T *ep, UINT8 flags, UINT32 start_clu, UINT64 size) +{ + exfat_set_entry_type((DENTRY_T *) ep, TYPE_STREAM); + ep->flags = flags; + SET32_A(ep->start_clu, start_clu); + SET64_A(ep->valid_size, size); + SET64_A(ep->size, size); +} /* end of init_strm_entry */ + +void init_name_entry(NAME_DENTRY_T *ep, UINT16 *uniname) +{ + INT32 i; + + exfat_set_entry_type((DENTRY_T *) ep, TYPE_EXTEND); + ep->flags = 0x0; + + for (i = 0; i < 30; i++, i++) { + SET16_A(ep->unicode_0_14+i, *uniname); + if (*uniname == 0x0) + break; + uniname++; + } +} /* end of init_name_entry */ + +void fat_delete_dir_entry(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, INT32 order, INT32 num_entries) +{ + INT32 i; + UINT32 sector; + DENTRY_T *ep; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + for (i = num_entries-1; i >= order; i--) { + ep = get_entry_in_dir(sb, p_dir, entry-i, §or); + if (!ep) + return; + + p_fs->fs_func->set_entry_type(ep, TYPE_DELETED); + buf_modify(sb, sector); + } +} /* end of fat_delete_dir_entry */ + +void exfat_delete_dir_entry(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, INT32 order, INT32 num_entries) +{ + INT32 i; + UINT32 sector; + DENTRY_T *ep; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + for (i = order; i < num_entries; i++) { + ep = get_entry_in_dir(sb, p_dir, entry+i, §or); + if (!ep) + return; + + p_fs->fs_func->set_entry_type(ep, TYPE_DELETED); + buf_modify(sb, sector); + } +} /* end of exfat_delete_dir_entry */ + +void update_dir_checksum(struct super_block *sb, CHAIN_T *p_dir, INT32 entry) +{ + INT32 i, num_entries; + UINT32 sector; + UINT16 chksum; + FILE_DENTRY_T *file_ep; + DENTRY_T *ep; + + file_ep = (FILE_DENTRY_T *) get_entry_in_dir(sb, p_dir, entry, §or); + if (!file_ep) + return; + + buf_lock(sb, sector); + + num_entries = (INT32) file_ep->num_ext + 1; + chksum = calc_checksum_2byte((void *) file_ep, DENTRY_SIZE, 0, CS_DIR_ENTRY); + + for (i = 1; i < num_entries; i++) { + ep = get_entry_in_dir(sb, p_dir, entry+i, NULL); + if (!ep) { + buf_unlock(sb, sector); + return; + } + + chksum = calc_checksum_2byte((void *) ep, DENTRY_SIZE, chksum, CS_DEFAULT); + } + + SET16_A(file_ep->checksum, chksum); + buf_modify(sb, sector); + buf_unlock(sb, sector); +} /* end of update_dir_checksum */ + +void update_dir_checksum_with_entry_set (struct super_block *sb, ENTRY_SET_CACHE_T *es) +{ + DENTRY_T *ep; + UINT16 chksum = 0; + INT32 chksum_type = CS_DIR_ENTRY, i; + + ep = (DENTRY_T *)&(es->__buf); + for (i=0; i < es->num_entries; i++) { + PRINTK ("update_dir_checksum_with_entry_set ep %p\n", ep); + chksum = calc_checksum_2byte((void *) ep, DENTRY_SIZE, chksum, chksum_type); + ep++; + chksum_type = CS_DEFAULT; + } + + ep = (DENTRY_T *)&(es->__buf); + SET16_A(((FILE_DENTRY_T *)ep)->checksum, chksum); + write_whole_entry_set(sb, es); +} + +static INT32 _walk_fat_chain (struct super_block *sb, CHAIN_T *p_dir, INT32 byte_offset, UINT32 *clu) +{ + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + INT32 clu_offset; + UINT32 cur_clu; + + clu_offset = byte_offset >> p_fs->cluster_size_bits; + cur_clu = p_dir->dir; + + if (p_dir->flags == 0x03) { + cur_clu += clu_offset; + } else { + while (clu_offset > 0) { + if (FAT_read(sb, cur_clu, &cur_clu) == -1) + return FFS_MEDIAERR; + clu_offset--; + } + } + + if (clu) + *clu = cur_clu; + return FFS_SUCCESS; +} +INT32 find_location(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, UINT32 *sector, INT32 *offset) +{ + INT32 off, ret; + UINT32 clu=0; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); + + off = entry << DENTRY_SIZE_BITS; + + if (p_dir->dir == CLUSTER_32(0)) { /* FAT16 root_dir */ + *offset = off & p_bd->sector_size_mask; + *sector = off >> p_bd->sector_size_bits; + *sector += p_fs->root_start_sector; + } else { + ret =_walk_fat_chain(sb, p_dir, off, &clu); + if (ret != FFS_SUCCESS) + return ret; + + off &= p_fs->cluster_size - 1; /* byte offset in cluster */ + + *offset = off & p_bd->sector_size_mask; /* byte offset in sector */ + *sector = off >> p_bd->sector_size_bits; /* sector offset in cluster */ + *sector += START_SECTOR(clu); + } + return FFS_SUCCESS; +} /* end of find_location */ + +DENTRY_T *get_entry_with_sector(struct super_block *sb, UINT32 sector, INT32 offset) +{ + UINT8 *buf; + + buf = buf_getblk(sb, sector); + + if (buf == NULL) + return NULL; + + return((DENTRY_T *)(buf + offset)); +} /* end of get_entry_with_sector */ + +DENTRY_T *get_entry_in_dir(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, UINT32 *sector) +{ + INT32 off; + UINT32 sec; + UINT8 *buf; + + if (find_location(sb, p_dir, entry, &sec, &off) != FFS_SUCCESS) + return NULL; + + buf = buf_getblk(sb, sec); + + if (buf == NULL) + return NULL; + + if (sector != NULL) + *sector = sec; + return((DENTRY_T *)(buf + off)); +} /* end of get_entry_in_dir */ + + +/* returns a set of dentries for a file or dir. + * Note that this is a copy (dump) of dentries so that user should call write_entry_set() + * to apply changes made in this entry set to the real device. + * in: + * sb+p_dir+entry: indicates a file/dir + * type: specifies how many dentries should be included. + * out: + * file_ep: will point the first dentry(= file dentry) on success + * return: + * pointer of entry set on success, + * NULL on failure. + */ + +#define ES_MODE_STARTED 0 +#define ES_MODE_GET_FILE_ENTRY 1 +#define ES_MODE_GET_STRM_ENTRY 2 +#define ES_MODE_GET_NAME_ENTRY 3 +#define ES_MODE_GET_CRITICAL_SEC_ENTRY 4 +ENTRY_SET_CACHE_T *get_entry_set_in_dir (struct super_block *sb, CHAIN_T *p_dir, INT32 entry, UINT32 type, DENTRY_T **file_ep) +{ + INT32 off, ret, byte_offset; + UINT32 clu=0; + UINT32 sec, entry_type; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); + ENTRY_SET_CACHE_T *es = NULL; + DENTRY_T *ep, *pos; + UINT8 *buf; + UINT8 num_entries; + INT32 mode = ES_MODE_STARTED; + + PRINTK("get_entry_set_in_dir entered\n"); + PRINTK("p_dir dir %u flags %x size %d\n", p_dir->dir, p_dir->flags, p_dir->size); + + byte_offset = entry << DENTRY_SIZE_BITS; + ret =_walk_fat_chain(sb, p_dir, byte_offset, &clu); + if (ret != FFS_SUCCESS) + return NULL; + + + byte_offset &= p_fs->cluster_size - 1; /* byte offset in cluster */ + + off = byte_offset & p_bd->sector_size_mask; /* byte offset in sector */ + sec = byte_offset >> p_bd->sector_size_bits; /* sector offset in cluster */ + sec += START_SECTOR(clu); + + buf = buf_getblk(sb, sec); + if (buf == NULL) + goto err_out; + + + ep = (DENTRY_T *)(buf + off); + entry_type = p_fs->fs_func->get_entry_type(ep); + + if ((entry_type != TYPE_FILE) + && (entry_type != TYPE_DIR)) + goto err_out; + + if (type == ES_ALL_ENTRIES) + num_entries = ((FILE_DENTRY_T *)ep)->num_ext+1; + else + num_entries = type; + + PRINTK("trying to malloc %x bytes for %d entries\n", offsetof(ENTRY_SET_CACHE_T, __buf) + (num_entries) * sizeof(DENTRY_T), num_entries); + es = MALLOC(offsetof(ENTRY_SET_CACHE_T, __buf) + (num_entries) * sizeof(DENTRY_T)); + if (es == NULL) + goto err_out; + + es->num_entries = num_entries; + es->sector = sec; + es->offset = off; + es->alloc_flag = p_dir->flags; + + pos = (DENTRY_T *) &(es->__buf); + + while(num_entries) { + /* instead of copying whole sector, we will check every entry. + * this will provide minimum stablity and consistancy. + */ + + entry_type = p_fs->fs_func->get_entry_type(ep); + + if ((entry_type == TYPE_UNUSED) || (entry_type == TYPE_DELETED)) + goto err_out; + + switch(mode) { + case ES_MODE_STARTED: + if ((entry_type == TYPE_FILE) || (entry_type == TYPE_DIR)) + mode = ES_MODE_GET_FILE_ENTRY; + else + goto err_out; + break; + case ES_MODE_GET_FILE_ENTRY: + if (entry_type == TYPE_STREAM) + mode = ES_MODE_GET_STRM_ENTRY; + else + goto err_out; + break; + case ES_MODE_GET_STRM_ENTRY: + if (entry_type == TYPE_EXTEND) + mode = ES_MODE_GET_NAME_ENTRY; + else + goto err_out; + break; + case ES_MODE_GET_NAME_ENTRY: + if (entry_type == TYPE_EXTEND) + break; + else if (entry_type == TYPE_STREAM) + goto err_out; + else if (entry_type & TYPE_CRITICAL_SEC) + mode = ES_MODE_GET_CRITICAL_SEC_ENTRY; + else + goto err_out; + break; + case ES_MODE_GET_CRITICAL_SEC_ENTRY: + if ((entry_type == TYPE_EXTEND) || (entry_type == TYPE_STREAM)) + goto err_out; + else if ((entry_type & TYPE_CRITICAL_SEC) != TYPE_CRITICAL_SEC) + goto err_out; + break; + } + + COPY_DENTRY(pos, ep); + + if (--num_entries == 0) + break; + + if (((off + DENTRY_SIZE) & p_bd->sector_size_mask) < (off & p_bd->sector_size_mask)) { + /* get the next sector */ + if (IS_LAST_SECTOR_IN_CLUSTER(sec)) { + if (es->alloc_flag == 0x03) { + clu++; + } else { + if (FAT_read(sb, clu, &clu) == -1) + goto err_out; + } + sec = START_SECTOR(clu); + } else { + sec++; + } + buf = buf_getblk(sb, sec); + if (buf == NULL) + goto err_out; + off = 0; + ep = (DENTRY_T *)(buf); + } else { + ep++; + off += DENTRY_SIZE; + } + pos++; + } + + if (file_ep) + *file_ep = (DENTRY_T *)&(es->__buf); + + PRINTK("es sec %u offset %d flags %d, num_entries %u buf ptr %p\n", + es->sector, es->offset, es->alloc_flag, es->num_entries, &(es->__buf)); + PRINTK("get_entry_set_in_dir exited %p\n", es); + return es; +err_out: + PRINTK("get_entry_set_in_dir exited NULL (es %p)\n", es); + FREE(es); + return NULL; +} + +void release_entry_set (ENTRY_SET_CACHE_T *es) +{ + PRINTK("release_entry_set %p\n", es); + FREE(es); +} + + +static INT32 __write_partial_entries_in_entry_set (struct super_block *sb, ENTRY_SET_CACHE_T *es, UINT32 sec, INT32 off, UINT32 count) +{ + INT32 num_entries, buf_off = (off - es->offset); + UINT32 remaining_byte_in_sector, copy_entries; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); + UINT32 clu; + UINT8 *buf, *esbuf = (UINT8 *)&(es->__buf); + + PRINTK("__write_partial_entries_in_entry_set entered\n"); + PRINTK("es %p sec %u off %d count %d\n", es, sec, off, count); + num_entries = count; + + while(num_entries) { + /* white per sector base */ + remaining_byte_in_sector = (1 << p_bd->sector_size_bits) - off; + copy_entries = MIN(remaining_byte_in_sector>> DENTRY_SIZE_BITS , num_entries); + buf = buf_getblk(sb, sec); + if (buf == NULL) + goto err_out; + PRINTK("es->buf %p buf_off %u\n", esbuf, buf_off); + PRINTK("copying %d entries from %p to sector %u\n", copy_entries, (esbuf + buf_off), sec); + MEMCPY(buf + off, esbuf + buf_off, copy_entries << DENTRY_SIZE_BITS); + buf_modify(sb, sec); + num_entries -= copy_entries; + + if (num_entries) { + /* get next sector */ + if (IS_LAST_SECTOR_IN_CLUSTER(sec)) { + clu = GET_CLUSTER_FROM_SECTOR(sec); + if (es->alloc_flag == 0x03) { + clu++; + } else { + if (FAT_read(sb, clu, &clu) == -1) + goto err_out; + } + sec = START_SECTOR(clu); + } else { + sec++; + } + off = 0; + buf_off += copy_entries << DENTRY_SIZE_BITS; + } + } + + PRINTK("__write_partial_entries_in_entry_set exited successfully\n"); + return FFS_SUCCESS; +err_out: + PRINTK("__write_partial_entries_in_entry_set failed\n"); + return FFS_ERROR; +} + +/* write back all entries in entry set */ +INT32 write_whole_entry_set (struct super_block *sb, ENTRY_SET_CACHE_T *es) +{ + return (__write_partial_entries_in_entry_set(sb, es, es->sector,es->offset, es->num_entries)); +} + +/* write back some entries in entry set */ +INT32 write_partial_entries_in_entry_set (struct super_block *sb, ENTRY_SET_CACHE_T *es, DENTRY_T *ep, UINT32 count) +{ + INT32 ret, byte_offset, off; + UINT32 clu=0, sec; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); + CHAIN_T dir; + + /* vaidity check */ + if (ep + count > ((DENTRY_T *)&(es->__buf)) + es->num_entries) + return FFS_ERROR; + + dir.dir = GET_CLUSTER_FROM_SECTOR(es->sector); + dir.flags = es->alloc_flag; + dir.size = 0xffffffff; /* XXX */ + + byte_offset = (es->sector - START_SECTOR(dir.dir)) << p_bd->sector_size_bits; + byte_offset += ((INT32 *)ep - (INT32 *)&(es->__buf)) + es->offset; + + ret =_walk_fat_chain(sb, &dir, byte_offset, &clu); + if (ret != FFS_SUCCESS) + return ret; + byte_offset &= p_fs->cluster_size - 1; /* byte offset in cluster */ + off = byte_offset & p_bd->sector_size_mask; /* byte offset in sector */ + sec = byte_offset >> p_bd->sector_size_bits; /* sector offset in cluster */ + sec += START_SECTOR(clu); + return (__write_partial_entries_in_entry_set(sb, es, sec, off, count)); +} + +/* search EMPTY CONTINUOUS "num_entries" entries */ +INT32 search_deleted_or_unused_entry(struct super_block *sb, CHAIN_T *p_dir, INT32 num_entries) +{ + INT32 i, dentry, num_empty = 0; + INT32 dentries_per_clu; + UINT32 type; + CHAIN_T clu; + DENTRY_T *ep; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + if (p_dir->dir == CLUSTER_32(0)) /* FAT16 root_dir */ + dentries_per_clu = p_fs->dentries_in_root; + else + dentries_per_clu = p_fs->dentries_per_clu; + + if (p_fs->hint_uentry.dir == p_dir->dir) { + if (p_fs->hint_uentry.entry == -1) + return -1; + + clu.dir = p_fs->hint_uentry.clu.dir; + clu.size = p_fs->hint_uentry.clu.size; + clu.flags = p_fs->hint_uentry.clu.flags; + + dentry = p_fs->hint_uentry.entry; + } else { + p_fs->hint_uentry.entry = -1; + + clu.dir = p_dir->dir; + clu.size = p_dir->size; + clu.flags = p_dir->flags; + + dentry = 0; + } + + while (clu.dir != CLUSTER_32(~0)) { + if (p_fs->dev_ejected) + break; + + if (p_dir->dir == CLUSTER_32(0)) /* FAT16 root_dir */ + i = dentry % dentries_per_clu; + else + i = dentry & (dentries_per_clu-1); + + for ( ; i < dentries_per_clu; i++, dentry++) { + ep = get_entry_in_dir(sb, &clu, i, NULL); + if (!ep) + return -1; + + type = p_fs->fs_func->get_entry_type(ep); + + if (type == TYPE_UNUSED) { + num_empty++; + if (p_fs->hint_uentry.entry == -1) { + p_fs->hint_uentry.dir = p_dir->dir; + p_fs->hint_uentry.entry = dentry; + + p_fs->hint_uentry.clu.dir = clu.dir; + p_fs->hint_uentry.clu.size = clu.size; + p_fs->hint_uentry.clu.flags = clu.flags; + } + } else if (type == TYPE_DELETED) { + num_empty++; + } else { + num_empty = 0; + } + + if (num_empty >= num_entries) { + p_fs->hint_uentry.dir = CLUSTER_32(~0); + p_fs->hint_uentry.entry = -1; + + if (p_fs->vol_type == EXFAT) + return(dentry - (num_entries-1)); + else + return(dentry); + } + } + + if (p_dir->dir == CLUSTER_32(0)) + break; /* FAT16 root_dir */ + + if (clu.flags == 0x03) { + if ((--clu.size) > 0) + clu.dir++; + else + clu.dir = CLUSTER_32(~0); + } else { + if (FAT_read(sb, clu.dir, &(clu.dir)) != 0) + return -1; + } + } + + return -1; +} /* end of search_deleted_or_unused_entry */ + +INT32 find_empty_entry(struct inode *inode, CHAIN_T *p_dir, INT32 num_entries) +{ + INT32 ret, dentry; + UINT32 last_clu, sector; + UINT64 size = 0; + CHAIN_T clu; + DENTRY_T *ep = NULL; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + FILE_ID_T *fid = &(EXFAT_I(inode)->fid); + + if (p_dir->dir == CLUSTER_32(0)) /* FAT16 root_dir */ + return(search_deleted_or_unused_entry(sb, p_dir, num_entries)); + + while ((dentry = search_deleted_or_unused_entry(sb, p_dir, num_entries)) < 0) { + if (p_fs->dev_ejected) + break; + + if (p_fs->vol_type == EXFAT) { + if (p_dir->dir != p_fs->root_dir) { + size = i_size_read(inode); + } + } + + last_clu = find_last_cluster(sb, p_dir); + clu.dir = last_clu + 1; + clu.size = 0; + clu.flags = p_dir->flags; + + /* (1) allocate a cluster */ + ret = p_fs->fs_func->alloc_cluster(sb, 1, &clu); + if (ret < 1) + return -1; + + if (clear_cluster(sb, clu.dir) != FFS_SUCCESS) + return -1; + + /* (2) append to the FAT chain */ + if (clu.flags != p_dir->flags) { + exfat_chain_cont_cluster(sb, p_dir->dir, p_dir->size); + p_dir->flags = 0x01; + p_fs->hint_uentry.clu.flags = 0x01; + } + if (clu.flags == 0x01) + FAT_write(sb, last_clu, clu.dir); + + if (p_fs->hint_uentry.entry == -1) { + p_fs->hint_uentry.dir = p_dir->dir; + p_fs->hint_uentry.entry = p_dir->size << (p_fs->cluster_size_bits - DENTRY_SIZE_BITS); + + p_fs->hint_uentry.clu.dir = clu.dir; + p_fs->hint_uentry.clu.size = 0; + p_fs->hint_uentry.clu.flags = clu.flags; + } + p_fs->hint_uentry.clu.size++; + p_dir->size++; + + /* (3) update the directory entry */ + if (p_fs->vol_type == EXFAT) { + if (p_dir->dir != p_fs->root_dir) { + size += p_fs->cluster_size; + + ep = get_entry_in_dir(sb, &(fid->dir), fid->entry+1, §or); + if (!ep) + return -1; + p_fs->fs_func->set_entry_size(ep, size); + p_fs->fs_func->set_entry_flag(ep, p_dir->flags); + buf_modify(sb, sector); + + update_dir_checksum(sb, &(fid->dir), fid->entry); + } + } + + i_size_write(inode, i_size_read(inode)+p_fs->cluster_size); + EXFAT_I(inode)->mmu_private += p_fs->cluster_size; + EXFAT_I(inode)->fid.size += p_fs->cluster_size; + EXFAT_I(inode)->fid.flags = p_dir->flags; + inode->i_blocks += 1 << (p_fs->cluster_size_bits - 9); + } + + return(dentry); +} /* end of find_empty_entry */ + +/* return values of fat_find_dir_entry() + >= 0 : return dir entiry position with the name in dir + -1 : (root dir, ".") it is the root dir itself + -2 : entry with the name does not exist */ +INT32 fat_find_dir_entry(struct super_block *sb, CHAIN_T *p_dir, UNI_NAME_T *p_uniname, INT32 num_entries, DOS_NAME_T *p_dosname, UINT32 type) +{ + INT32 i, dentry = 0, len; + INT32 order = 0, is_feasible_entry = TRUE, has_ext_entry = FALSE; + INT32 dentries_per_clu; + UINT32 entry_type; + UINT16 entry_uniname[14], *uniname = NULL, unichar; + CHAIN_T clu; + DENTRY_T *ep; + DOS_DENTRY_T *dos_ep; + EXT_DENTRY_T *ext_ep; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + if (p_dir->dir == p_fs->root_dir) { + if ((!nls_uniname_cmp(sb, p_uniname->name, (UINT16 *) UNI_CUR_DIR_NAME)) || + (!nls_uniname_cmp(sb, p_uniname->name, (UINT16 *) UNI_PAR_DIR_NAME))) + return -1; // special case, root directory itself + } + + if (p_dir->dir == CLUSTER_32(0)) /* FAT16 root_dir */ + dentries_per_clu = p_fs->dentries_in_root; + else + dentries_per_clu = p_fs->dentries_per_clu; + + clu.dir = p_dir->dir; + clu.flags = p_dir->flags; + + while (clu.dir != CLUSTER_32(~0)) { + if (p_fs->dev_ejected) + break; + + for (i = 0; i < dentries_per_clu; i++, dentry++) { + ep = get_entry_in_dir(sb, &clu, i, NULL); + if (!ep) + return -2; + + entry_type = p_fs->fs_func->get_entry_type(ep); + + if ((entry_type == TYPE_FILE) || (entry_type == TYPE_DIR)) { + if ((type == TYPE_ALL) || (type == entry_type)) { + if (is_feasible_entry && has_ext_entry) + return(dentry); + + dos_ep = (DOS_DENTRY_T *) ep; + if (!nls_dosname_cmp(sb, p_dosname->name, dos_ep->name)) + return(dentry); + } + is_feasible_entry = TRUE; + has_ext_entry = FALSE; + } else if (entry_type == TYPE_EXTEND) { + if (is_feasible_entry) { + ext_ep = (EXT_DENTRY_T *) ep; + if (ext_ep->order > 0x40) { + order = (INT32)(ext_ep->order - 0x40); + uniname = p_uniname->name + 13 * (order-1); + } else { + order = (INT32) ext_ep->order; + uniname -= 13; + } + + len = extract_uni_name_from_ext_entry(ext_ep, entry_uniname, order); + + unichar = *(uniname+len); + *(uniname+len) = 0x0; + + if (nls_uniname_cmp(sb, uniname, entry_uniname)) { + is_feasible_entry = FALSE; + } + + *(uniname+len) = unichar; + } + has_ext_entry = TRUE; + } else if (entry_type == TYPE_UNUSED) { + return -2; + } else { + is_feasible_entry = TRUE; + has_ext_entry = FALSE; + } + } + + if (p_dir->dir == CLUSTER_32(0)) + break; /* FAT16 root_dir */ + + if (FAT_read(sb, clu.dir, &(clu.dir)) != 0) + return -2; + } + + return -2; +} /* end of fat_find_dir_entry */ + +/* return values of exfat_find_dir_entry() + >= 0 : return dir entiry position with the name in dir + -1 : (root dir, ".") it is the root dir itself + -2 : entry with the name does not exist */ +INT32 exfat_find_dir_entry(struct super_block *sb, CHAIN_T *p_dir, UNI_NAME_T *p_uniname, INT32 num_entries, DOS_NAME_T *p_dosname, UINT32 type) +{ + INT32 i, dentry = 0, num_ext_entries = 0, len; + INT32 order = 0, is_feasible_entry = FALSE; + INT32 dentries_per_clu, num_empty = 0; + UINT32 entry_type; + UINT16 entry_uniname[16], *uniname = NULL, unichar; + CHAIN_T clu; + DENTRY_T *ep; + FILE_DENTRY_T *file_ep; + STRM_DENTRY_T *strm_ep; + NAME_DENTRY_T *name_ep; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + if (p_dir->dir == p_fs->root_dir) { + if ((!nls_uniname_cmp(sb, p_uniname->name, (UINT16 *) UNI_CUR_DIR_NAME)) || + (!nls_uniname_cmp(sb, p_uniname->name, (UINT16 *) UNI_PAR_DIR_NAME))) + return -1; // special case, root directory itself + } + + if (p_dir->dir == CLUSTER_32(0)) /* FAT16 root_dir */ + dentries_per_clu = p_fs->dentries_in_root; + else + dentries_per_clu = p_fs->dentries_per_clu; + + clu.dir = p_dir->dir; + clu.size = p_dir->size; + clu.flags = p_dir->flags; + + p_fs->hint_uentry.dir = p_dir->dir; + p_fs->hint_uentry.entry = -1; + + while (clu.dir != CLUSTER_32(~0)) { + if (p_fs->dev_ejected) + break; + + for (i = 0; i < dentries_per_clu; i++, dentry++) { + ep = get_entry_in_dir(sb, &clu, i, NULL); + if (!ep) + return -2; + + entry_type = p_fs->fs_func->get_entry_type(ep); + + if ((entry_type == TYPE_UNUSED) || (entry_type == TYPE_DELETED)) { + is_feasible_entry = FALSE; + + if (p_fs->hint_uentry.entry == -1) { + num_empty++; + + if (num_empty == 1) { + p_fs->hint_uentry.clu.dir = clu.dir; + p_fs->hint_uentry.clu.size = clu.size; + p_fs->hint_uentry.clu.flags = clu.flags; + } + if ((num_empty >= num_entries) || (entry_type == TYPE_UNUSED)) { + p_fs->hint_uentry.entry = dentry - (num_empty-1); + } + } + + if (entry_type == TYPE_UNUSED) { + return -2; + } + } else { + num_empty = 0; + + if ((entry_type == TYPE_FILE) || (entry_type == TYPE_DIR)) { + if ((type == TYPE_ALL) || (type == entry_type)) { + file_ep = (FILE_DENTRY_T *) ep; + num_ext_entries = file_ep->num_ext; + is_feasible_entry = TRUE; + } else { + is_feasible_entry = FALSE; + } + } else if (entry_type == TYPE_STREAM) { + if (is_feasible_entry) { + strm_ep = (STRM_DENTRY_T *) ep; + if (p_uniname->name_len == strm_ep->name_len) { + order = 1; + } else { + is_feasible_entry = FALSE; + } + } + } else if (entry_type == TYPE_EXTEND) { + if (is_feasible_entry) { + name_ep = (NAME_DENTRY_T *) ep; + + if ((++order) == 2) + uniname = p_uniname->name; + else + uniname += 15; + + len = extract_uni_name_from_name_entry(name_ep, entry_uniname, order); + + unichar = *(uniname+len); + *(uniname+len) = 0x0; + + if (nls_uniname_cmp(sb, uniname, entry_uniname)) { + is_feasible_entry = FALSE; + } else if (order == num_ext_entries) { + p_fs->hint_uentry.dir = CLUSTER_32(~0); + p_fs->hint_uentry.entry = -1; + return(dentry - (num_ext_entries)); + } + + *(uniname+len) = unichar; + } + } else { + is_feasible_entry = FALSE; + } + } + } + + if (p_dir->dir == CLUSTER_32(0)) + break; /* FAT16 root_dir */ + + if (clu.flags == 0x03) { + if ((--clu.size) > 0) + clu.dir++; + else + clu.dir = CLUSTER_32(~0); + } else { + if (FAT_read(sb, clu.dir, &(clu.dir)) != 0) + return -2; + } + } + + return -2; +} /* end of exfat_find_dir_entry */ + +/* returns -1 on error */ +INT32 fat_count_ext_entries(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, DENTRY_T *p_entry) +{ + INT32 count = 0; + UINT8 chksum; + DOS_DENTRY_T *dos_ep = (DOS_DENTRY_T *) p_entry; + EXT_DENTRY_T *ext_ep; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + chksum = calc_checksum_1byte((void *) dos_ep->name, DOS_NAME_LENGTH, 0); + + for (entry--; entry >= 0; entry--) { + ext_ep = (EXT_DENTRY_T *) get_entry_in_dir(sb, p_dir, entry, NULL); + if (!ext_ep) + return -1; + + if ((p_fs->fs_func->get_entry_type((DENTRY_T *) ext_ep) == TYPE_EXTEND) && + (ext_ep->checksum == chksum)) { + count++; + if (ext_ep->order > 0x40) + return(count); + } else { + return(count); + } + } + + return(count); +} /* end of fat_count_ext_entries */ + +/* returns -1 on error */ +INT32 exfat_count_ext_entries(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, DENTRY_T *p_entry) +{ + INT32 i, count = 0; + UINT32 type; + FILE_DENTRY_T *file_ep = (FILE_DENTRY_T *) p_entry; + DENTRY_T *ext_ep; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + for (i = 0, entry++; i < file_ep->num_ext; i++, entry++) { + ext_ep = get_entry_in_dir(sb, p_dir, entry, NULL); + if (!ext_ep) + return -1; + + type = p_fs->fs_func->get_entry_type(ext_ep); + if ((type == TYPE_EXTEND) || (type == TYPE_STREAM)) { + count++; + } else { + return(count); + } + } + + return(count); +} /* end of exfat_count_ext_entries */ + +/* returns -1 on error */ +INT32 count_dos_name_entries(struct super_block *sb, CHAIN_T *p_dir, UINT32 type) +{ + INT32 i, count = 0; + INT32 dentries_per_clu; + UINT32 entry_type; + CHAIN_T clu; + DENTRY_T *ep; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + if (p_dir->dir == CLUSTER_32(0)) /* FAT16 root_dir */ + dentries_per_clu = p_fs->dentries_in_root; + else + dentries_per_clu = p_fs->dentries_per_clu; + + clu.dir = p_dir->dir; + clu.size = p_dir->size; + clu.flags = p_dir->flags; + + while (clu.dir != CLUSTER_32(~0)) { + if (p_fs->dev_ejected) + break; + + for (i = 0; i < dentries_per_clu; i++) { + ep = get_entry_in_dir(sb, &clu, i, NULL); + if (!ep) + return -1; + + entry_type = p_fs->fs_func->get_entry_type(ep); + + if (entry_type == TYPE_UNUSED) + return(count); + if (!(type & TYPE_CRITICAL_PRI) && !(type & TYPE_BENIGN_PRI)) + continue; + + if ((type == TYPE_ALL) || (type == entry_type)) + count++; + } + + if (p_dir->dir == CLUSTER_32(0)) + break; /* FAT16 root_dir */ + + if (clu.flags == 0x03) { + if ((--clu.size) > 0) + clu.dir++; + else + clu.dir = CLUSTER_32(~0); + } else { + if (FAT_read(sb, clu.dir, &(clu.dir)) != 0) + return -1; + } + } + + return(count); +} /* end of count_dos_name_entries */ + +BOOL is_dir_empty(struct super_block *sb, CHAIN_T *p_dir) +{ + INT32 i, count = 0; + INT32 dentries_per_clu; + UINT32 type; + CHAIN_T clu; + DENTRY_T *ep; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + if (p_dir->dir == CLUSTER_32(0)) /* FAT16 root_dir */ + dentries_per_clu = p_fs->dentries_in_root; + else + dentries_per_clu = p_fs->dentries_per_clu; + + clu.dir = p_dir->dir; + clu.size = p_dir->size; + clu.flags = p_dir->flags; + + while (clu.dir != CLUSTER_32(~0)) { + if (p_fs->dev_ejected) + break; + + for (i = 0; i < dentries_per_clu; i++) { + ep = get_entry_in_dir(sb, &clu, i, NULL); + if (!ep) + break; + + type = p_fs->fs_func->get_entry_type(ep); + + if (type == TYPE_UNUSED) + return TRUE; + if ((type != TYPE_FILE) && (type != TYPE_DIR)) + continue; + + if (p_dir->dir == CLUSTER_32(0)) { /* FAT16 root_dir */ + return FALSE; + } else { + if (p_fs->vol_type == EXFAT) + return FALSE; + if ((p_dir->dir == p_fs->root_dir) || ((++count) > 2)) + return FALSE; + } + } + + if (p_dir->dir == CLUSTER_32(0)) + break; /* FAT16 root_dir */ + + if (clu.flags == 0x03) { + if ((--clu.size) > 0) + clu.dir++; + else + clu.dir = CLUSTER_32(~0); + } else { + if (FAT_read(sb, clu.dir, &(clu.dir)) != 0) + break; + } + } + + return TRUE; +} /* end of is_dir_empty */ + +/* + * Name Conversion Functions + */ + +/* input : dir, uni_name + output : num_of_entry, dos_name(format : aaaaaa~1.bbb) */ +INT32 get_num_entries_and_dos_name(struct super_block *sb, CHAIN_T *p_dir, UNI_NAME_T *p_uniname, INT32 *entries, DOS_NAME_T *p_dosname) +{ + INT32 ret, num_entries, lossy = FALSE; + INT8 **r; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + num_entries = p_fs->fs_func->calc_num_entries(p_uniname); + if (num_entries == 0) + return FFS_INVALIDPATH; + + if (p_fs->vol_type != EXFAT) { + nls_uniname_to_dosname(sb, p_dosname, p_uniname, &lossy); + + if (lossy) { + ret = fat_generate_dos_name(sb, p_dir, p_dosname); + if (ret) + return ret; + } else { + for (r = reserved_names; *r; r++) { + if (!STRNCMP((void *) p_dosname->name, *r, 8)) + return FFS_INVALIDPATH; + } + + if (p_dosname->name_case != 0xFF) + num_entries = 1; + } + + if (num_entries > 1) + p_dosname->name_case = 0x0; + } + + *entries = num_entries; + + return FFS_SUCCESS; +} /* end of get_num_entries_and_dos_name */ + +void get_uni_name_from_dos_entry(struct super_block *sb, DOS_DENTRY_T *ep, UNI_NAME_T *p_uniname, UINT8 mode) +{ + DOS_NAME_T dos_name; + + if (mode == 0x0) + dos_name.name_case = 0x0; + else + dos_name.name_case = ep->lcase; + + MEMCPY(dos_name.name, ep->name, DOS_NAME_LENGTH); + nls_dosname_to_uniname(sb, p_uniname, &dos_name); +} /* end of get_uni_name_from_dos_entry */ + +void fat_get_uni_name_from_ext_entry(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, UINT16 *uniname) +{ + INT32 i; + EXT_DENTRY_T *ep; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + for (entry--, i = 1; entry >= 0; entry--, i++) { + ep = (EXT_DENTRY_T *) get_entry_in_dir(sb, p_dir, entry, NULL); + if (!ep) + return; + + if (p_fs->fs_func->get_entry_type((DENTRY_T *) ep) == TYPE_EXTEND) { + extract_uni_name_from_ext_entry(ep, uniname, i); + if (ep->order > 0x40) + return; + } else { + return; + } + + uniname += 13; + } +} /* end of fat_get_uni_name_from_ext_entry */ + +void exfat_get_uni_name_from_ext_entry(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, UINT16 *uniname) +{ + INT32 i; + DENTRY_T *ep; + ENTRY_SET_CACHE_T *es; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + es = get_entry_set_in_dir(sb, p_dir, entry, ES_ALL_ENTRIES, &ep); + if (es == NULL || es->num_entries < 3) { + if(es) { + release_entry_set(es); + } + return; + } + + ep += 2; + + /* + * First entry : file entry + * Second entry : stream-extension entry + * Third entry : first file-name entry + * So, the index of first file-name dentry should start from 2. + */ + for (i = 2; i < es->num_entries; i++, ep++) { + if (p_fs->fs_func->get_entry_type(ep) == TYPE_EXTEND) { + extract_uni_name_from_name_entry((NAME_DENTRY_T *)ep, uniname, i); + } else { + /* end of name entry */ + goto out; + } + uniname += 15; + } + +out: + release_entry_set(es); +} /* end of exfat_get_uni_name_from_ext_entry */ + +INT32 extract_uni_name_from_ext_entry(EXT_DENTRY_T *ep, UINT16 *uniname, INT32 order) +{ + INT32 i, len = 0; + + for (i = 0; i < 10; i += 2) { + *uniname = GET16(ep->unicode_0_4+i); + if (*uniname == 0x0) + return(len); + uniname++; + len++; + } + + if (order < 20) { + for (i = 0; i < 12; i += 2) { + *uniname = GET16_A(ep->unicode_5_10+i); + if (*uniname == 0x0) + return(len); + uniname++; + len++; + } + } else { + for (i = 0; i < 8; i += 2) { + *uniname = GET16_A(ep->unicode_5_10+i); + if (*uniname == 0x0) + return(len); + uniname++; + len++; + } + *uniname = 0x0; /* uniname[MAX_NAME_LENGTH-1] */ + return(len); + } + + for (i = 0; i < 4; i += 2) { + *uniname = GET16_A(ep->unicode_11_12+i); + if (*uniname == 0x0) + return(len); + uniname++; + len++; + } + + *uniname = 0x0; + return(len); + +} /* end of extract_uni_name_from_ext_entry */ + +INT32 extract_uni_name_from_name_entry(NAME_DENTRY_T *ep, UINT16 *uniname, INT32 order) +{ + INT32 i, len = 0; + + for (i = 0; i < 30; i += 2) { + *uniname = GET16_A(ep->unicode_0_14+i); + if (*uniname == 0x0) + return(len); + uniname++; + len++; + } + + *uniname = 0x0; + return(len); + +} /* end of extract_uni_name_from_name_entry */ + +INT32 fat_generate_dos_name(struct super_block *sb, CHAIN_T *p_dir, DOS_NAME_T *p_dosname) +{ + INT32 i, j, count = 0, count_begin = FALSE; + INT32 dentries_per_clu; + UINT32 type; + UINT8 bmap[128/* 1 ~ 1023 */]; + CHAIN_T clu; + DOS_DENTRY_T *ep; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + Bitmap_clear_all(bmap, 128); + Bitmap_set(bmap, 0); + + if (p_dir->dir == CLUSTER_32(0)) /* FAT16 root_dir */ + dentries_per_clu = p_fs->dentries_in_root; + else + dentries_per_clu = p_fs->dentries_per_clu; + + clu.dir = p_dir->dir; + clu.flags = p_dir->flags; + + while (clu.dir != CLUSTER_32(~0)) { + if (p_fs->dev_ejected) + break; + + for (i = 0; i < dentries_per_clu; i++) { + ep = (DOS_DENTRY_T *) get_entry_in_dir(sb, &clu, i, NULL); + if (!ep) + return FFS_MEDIAERR; + + type = p_fs->fs_func->get_entry_type((DENTRY_T *) ep); + + if (type == TYPE_UNUSED) + break; + if ((type != TYPE_FILE) && (type != TYPE_DIR)) + continue; + + count = 0; + count_begin = FALSE; + + for (j = 0; j < 8; j++) { + if (ep->name[j] == ' ') + break; + + if (ep->name[j] == '~') { + count_begin = TRUE; + } else if (count_begin) { + if ((ep->name[j] >= '0') && (ep->name[j] <= '9')) { + count = count * 10 + (ep->name[j] - '0'); + } else { + count = 0; + count_begin = FALSE; + } + } + } + + if ((count > 0) && (count < 1024)) + Bitmap_set(bmap, count); + } + + if (p_dir->dir == CLUSTER_32(0)) + break; /* FAT16 root_dir */ + + if (FAT_read(sb, clu.dir, &(clu.dir)) != 0) + return FFS_MEDIAERR; + } + + count = 0; + for (i = 0; i < 128; i++) { + if (bmap[i] != 0xFF) { + for (j = 0; j < 8; j++) { + if (Bitmap_test(&(bmap[i]), j) == 0) { + count = (i << 3) + j; + break; + } + } + if (count != 0) + break; + } + } + + if ((count == 0) || (count >= 1024)) + return FFS_FILEEXIST; + else + fat_attach_count_to_dos_name(p_dosname->name, count); + + /* Now dos_name has DOS~????.EXT */ + return FFS_SUCCESS; +} /* end of generate_dos_name */ + +void fat_attach_count_to_dos_name(UINT8 *dosname, INT32 count) +{ + INT32 i, j, length; + INT8 str_count[6]; + + str_count[0] = '~'; + str_count[1] = '\0'; + my_itoa(&(str_count[1]), count); + length = STRLEN(str_count); + + i = j = 0; + while (j <= (8 - length)) { + i = j; + if (dosname[j] == ' ') + break; + if (dosname[j] & 0x80) + j += 2; + else + j++; + } + + for (j = 0; j < length; i++, j++) + dosname[i] = (UINT8) str_count[j]; + + if (i == 7) + dosname[7] = ' '; + +} /* end of attach_count_to_dos_name */ + +INT32 fat_calc_num_entries(UNI_NAME_T *p_uniname) +{ + INT32 len; + + len = p_uniname->name_len; + if (len == 0) + return 0; + + /* 1 dos name entry + extended entries */ + return((len-1) / 13 + 2); + +} /* end of calc_num_enties */ + +INT32 exfat_calc_num_entries(UNI_NAME_T *p_uniname) +{ + INT32 len; + + len = p_uniname->name_len; + if (len == 0) + return 0; + + /* 1 file entry + 1 stream entry + name entries */ + return((len-1) / 15 + 3); + +} /* end of exfat_calc_num_enties */ + +UINT8 calc_checksum_1byte(void *data, INT32 len, UINT8 chksum) +{ + INT32 i; + UINT8 *c = (UINT8 *) data; + + for (i = 0; i < len; i++, c++) + chksum = (((chksum & 1) << 7) | ((chksum & 0xFE) >> 1)) + *c; + + return(chksum); +} /* end of calc_checksum_1byte */ + +UINT16 calc_checksum_2byte(void *data, INT32 len, UINT16 chksum, INT32 type) +{ + INT32 i; + UINT8 *c = (UINT8 *) data; + + switch (type) { + case CS_DIR_ENTRY: + for (i = 0; i < len; i++, c++) { + if ((i == 2) || (i == 3)) + continue; + chksum = (((chksum & 1) << 15) | ((chksum & 0xFFFE) >> 1)) + (UINT16) *c; + } + break; + default + : + for (i = 0; i < len; i++, c++) { + chksum = (((chksum & 1) << 15) | ((chksum & 0xFFFE) >> 1)) + (UINT16) *c; + } + } + + return(chksum); +} /* end of calc_checksum_2byte */ + +UINT32 calc_checksum_4byte(void *data, INT32 len, UINT32 chksum, INT32 type) +{ + INT32 i; + UINT8 *c = (UINT8 *) data; + + switch (type) { + case CS_PBR_SECTOR: + for (i = 0; i < len; i++, c++) { + if ((i == 106) || (i == 107) || (i == 112)) + continue; + chksum = (((chksum & 1) << 31) | ((chksum & 0xFFFFFFFE) >> 1)) + (UINT32) *c; + } + break; + default + : + for (i = 0; i < len; i++, c++) { + chksum = (((chksum & 1) << 31) | ((chksum & 0xFFFFFFFE) >> 1)) + (UINT32) *c; + } + } + + return(chksum); +} /* end of calc_checksum_4byte */ + +/* + * Name Resolution Functions + */ + +/* return values of resolve_path() + > 0 : return the length of the path + < 0 : return error */ +INT32 resolve_path(struct inode *inode, UINT8 *path, CHAIN_T *p_dir, UNI_NAME_T *p_uniname) +{ + INT32 lossy = FALSE; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + FILE_ID_T *fid = &(EXFAT_I(inode)->fid); + + if (STRLEN(path) >= (MAX_NAME_LENGTH * MAX_CHARSET_SIZE)) + return(FFS_INVALIDPATH); + + STRCPY(name_buf, path); + + nls_cstring_to_uniname(sb, p_uniname, name_buf, &lossy); + if (lossy) + return(FFS_INVALIDPATH); + + fid->size = i_size_read(inode); + + p_dir->dir = fid->start_clu; + p_dir->size = (INT32)(fid->size >> p_fs->cluster_size_bits); + p_dir->flags = fid->flags; + + return(FFS_SUCCESS); +} + +/* + * File Operation Functions + */ +static FS_FUNC_T fat_fs_func = { + .alloc_cluster = fat_alloc_cluster, + .free_cluster = fat_free_cluster, + .count_used_clusters = fat_count_used_clusters, + + .init_dir_entry = fat_init_dir_entry, + .init_ext_entry = fat_init_ext_entry, + .find_dir_entry = fat_find_dir_entry, + .delete_dir_entry = fat_delete_dir_entry, + .get_uni_name_from_ext_entry = fat_get_uni_name_from_ext_entry, + .count_ext_entries = fat_count_ext_entries, + .calc_num_entries = fat_calc_num_entries, + + .get_entry_type = fat_get_entry_type, + .set_entry_type = fat_set_entry_type, + .get_entry_attr = fat_get_entry_attr, + .set_entry_attr = fat_set_entry_attr, + .get_entry_flag = fat_get_entry_flag, + .set_entry_flag = fat_set_entry_flag, + .get_entry_clu0 = fat_get_entry_clu0, + .set_entry_clu0 = fat_set_entry_clu0, + .get_entry_size = fat_get_entry_size, + .set_entry_size = fat_set_entry_size, + .get_entry_time = fat_get_entry_time, + .set_entry_time = fat_set_entry_time, +}; + + +INT32 fat16_mount(struct super_block *sb, PBR_SECTOR_T *p_pbr) +{ + INT32 num_reserved, num_root_sectors; + BPB16_T *p_bpb = (BPB16_T *) p_pbr->bpb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); + + if (p_bpb->num_fats == 0) + return FFS_FORMATERR; + + num_root_sectors = GET16(p_bpb->num_root_entries) << DENTRY_SIZE_BITS; + num_root_sectors = ((num_root_sectors-1) >> p_bd->sector_size_bits) + 1; + + p_fs->sectors_per_clu = p_bpb->sectors_per_clu; + p_fs->sectors_per_clu_bits = my_log2(p_bpb->sectors_per_clu); + p_fs->cluster_size_bits = p_fs->sectors_per_clu_bits + p_bd->sector_size_bits; + p_fs->cluster_size = 1 << p_fs->cluster_size_bits; + + p_fs->num_FAT_sectors = GET16(p_bpb->num_fat_sectors); + + p_fs->FAT1_start_sector = p_fs->PBR_sector + GET16(p_bpb->num_reserved); + if (p_bpb->num_fats == 1) + p_fs->FAT2_start_sector = p_fs->FAT1_start_sector; + else + p_fs->FAT2_start_sector = p_fs->FAT1_start_sector + p_fs->num_FAT_sectors; + + p_fs->root_start_sector = p_fs->FAT2_start_sector + p_fs->num_FAT_sectors; + p_fs->data_start_sector = p_fs->root_start_sector + num_root_sectors; + + p_fs->num_sectors = GET16(p_bpb->num_sectors); + if (p_fs->num_sectors == 0) + p_fs->num_sectors = GET32(p_bpb->num_huge_sectors); + + num_reserved = p_fs->data_start_sector - p_fs->PBR_sector; + p_fs->num_clusters = ((p_fs->num_sectors - num_reserved) >> p_fs->sectors_per_clu_bits) + 2; + /* because the cluster index starts with 2 */ + + if (p_fs->num_clusters < FAT12_THRESHOLD) + p_fs->vol_type = FAT12; + else + p_fs->vol_type = FAT16; + p_fs->vol_id = GET32(p_bpb->vol_serial); + + p_fs->root_dir = 0; + p_fs->dentries_in_root = GET16(p_bpb->num_root_entries); + p_fs->dentries_per_clu = 1 << (p_fs->cluster_size_bits - DENTRY_SIZE_BITS); + + p_fs->vol_flag = VOL_CLEAN; + p_fs->clu_srch_ptr = 2; + p_fs->used_clusters = (UINT32) ~0; + + p_fs->fs_func = &fat_fs_func; + + return FFS_SUCCESS; +} /* end of fat16_mount */ + +INT32 fat32_mount(struct super_block *sb, PBR_SECTOR_T *p_pbr) +{ + INT32 num_reserved; + BPB32_T *p_bpb = (BPB32_T *) p_pbr->bpb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); + + if (p_bpb->num_fats == 0) + return FFS_FORMATERR; + + p_fs->sectors_per_clu = p_bpb->sectors_per_clu; + p_fs->sectors_per_clu_bits = my_log2(p_bpb->sectors_per_clu); + p_fs->cluster_size_bits = p_fs->sectors_per_clu_bits + p_bd->sector_size_bits; + p_fs->cluster_size = 1 << p_fs->cluster_size_bits; + + p_fs->num_FAT_sectors = GET32(p_bpb->num_fat32_sectors); + + p_fs->FAT1_start_sector = p_fs->PBR_sector + GET16(p_bpb->num_reserved); + if (p_bpb->num_fats == 1) + p_fs->FAT2_start_sector = p_fs->FAT1_start_sector; + else + p_fs->FAT2_start_sector = p_fs->FAT1_start_sector + p_fs->num_FAT_sectors; + + p_fs->root_start_sector = p_fs->FAT2_start_sector + p_fs->num_FAT_sectors; + p_fs->data_start_sector = p_fs->root_start_sector; + + p_fs->num_sectors = GET32(p_bpb->num_huge_sectors); + num_reserved = p_fs->data_start_sector - p_fs->PBR_sector; + + p_fs->num_clusters = ((p_fs->num_sectors-num_reserved) >> p_fs->sectors_per_clu_bits) + 2; + /* because the cluster index starts with 2 */ + + p_fs->vol_type = FAT32; + p_fs->vol_id = GET32(p_bpb->vol_serial); + + p_fs->root_dir = GET32(p_bpb->root_cluster); + p_fs->dentries_in_root = 0; + p_fs->dentries_per_clu = 1 << (p_fs->cluster_size_bits - DENTRY_SIZE_BITS); + + p_fs->vol_flag = VOL_CLEAN; + p_fs->clu_srch_ptr = 2; + p_fs->used_clusters = (UINT32) ~0; + + p_fs->fs_func = &fat_fs_func; + + return FFS_SUCCESS; +} /* end of fat32_mount */ + +static FS_FUNC_T exfat_fs_func = { + .alloc_cluster = exfat_alloc_cluster, + .free_cluster = exfat_free_cluster, + .count_used_clusters = exfat_count_used_clusters, + + .init_dir_entry = exfat_init_dir_entry, + .init_ext_entry = exfat_init_ext_entry, + .find_dir_entry = exfat_find_dir_entry, + .delete_dir_entry = exfat_delete_dir_entry, + .get_uni_name_from_ext_entry = exfat_get_uni_name_from_ext_entry, + .count_ext_entries = exfat_count_ext_entries, + .calc_num_entries = exfat_calc_num_entries, + + .get_entry_type = exfat_get_entry_type, + .set_entry_type = exfat_set_entry_type, + .get_entry_attr = exfat_get_entry_attr, + .set_entry_attr = exfat_set_entry_attr, + .get_entry_flag = exfat_get_entry_flag, + .set_entry_flag = exfat_set_entry_flag, + .get_entry_clu0 = exfat_get_entry_clu0, + .set_entry_clu0 = exfat_set_entry_clu0, + .get_entry_size = exfat_get_entry_size, + .set_entry_size = exfat_set_entry_size, + .get_entry_time = exfat_get_entry_time, + .set_entry_time = exfat_set_entry_time, +}; + +INT32 exfat_mount(struct super_block *sb, PBR_SECTOR_T *p_pbr) +{ + BPBEX_T *p_bpb = (BPBEX_T *) p_pbr->bpb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); + + if (p_bpb->num_fats == 0) + return FFS_FORMATERR; + + p_fs->sectors_per_clu = 1 << p_bpb->sectors_per_clu_bits; + p_fs->sectors_per_clu_bits = p_bpb->sectors_per_clu_bits; + p_fs->cluster_size_bits = p_fs->sectors_per_clu_bits + p_bd->sector_size_bits; + p_fs->cluster_size = 1 << p_fs->cluster_size_bits; + + p_fs->num_FAT_sectors = GET32(p_bpb->fat_length); + + p_fs->FAT1_start_sector = p_fs->PBR_sector + GET32(p_bpb->fat_offset); + if (p_bpb->num_fats == 1) + p_fs->FAT2_start_sector = p_fs->FAT1_start_sector; + else + p_fs->FAT2_start_sector = p_fs->FAT1_start_sector + p_fs->num_FAT_sectors; + + p_fs->root_start_sector = p_fs->PBR_sector + GET32(p_bpb->clu_offset); + p_fs->data_start_sector = p_fs->root_start_sector; + + p_fs->num_sectors = GET64(p_bpb->vol_length); + p_fs->num_clusters = GET32(p_bpb->clu_count) + 2; + /* because the cluster index starts with 2 */ + + p_fs->vol_type = EXFAT; + p_fs->vol_id = GET32(p_bpb->vol_serial); + + p_fs->root_dir = GET32(p_bpb->root_cluster); + p_fs->dentries_in_root = 0; + p_fs->dentries_per_clu = 1 << (p_fs->cluster_size_bits - DENTRY_SIZE_BITS); + + p_fs->vol_flag = (UINT32) GET16(p_bpb->vol_flags); + p_fs->clu_srch_ptr = 2; + p_fs->used_clusters = (UINT32) ~0; + + p_fs->fs_func = &exfat_fs_func; + + return FFS_SUCCESS; +} /* end of exfat_mount */ + +INT32 create_dir(struct inode *inode, CHAIN_T *p_dir, UNI_NAME_T *p_uniname, FILE_ID_T *fid) +{ + INT32 ret, dentry, num_entries; + UINT64 size; + CHAIN_T clu; + DOS_NAME_T dos_name, dot_name; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + ret = get_num_entries_and_dos_name(sb, p_dir, p_uniname, &num_entries, &dos_name); + if (ret) + return ret; + + /* find_empty_entry must be called before alloc_cluster */ + dentry = find_empty_entry(inode, p_dir, num_entries); + if (dentry < 0) + return FFS_FULL; + + clu.dir = CLUSTER_32(~0); + clu.size = 0; + clu.flags = (p_fs->vol_type == EXFAT) ? 0x03 : 0x01; + + /* (1) allocate a cluster */ + ret = p_fs->fs_func->alloc_cluster(sb, 1, &clu); + if (ret < 1) + return FFS_FULL; + + ret = clear_cluster(sb, clu.dir); + if (ret != FFS_SUCCESS) + return ret; + + if (p_fs->vol_type == EXFAT) { + size = p_fs->cluster_size; + } else { + size = 0; + + /* initialize the . and .. entry + Information for . points to itself + Information for .. points to parent dir */ + + dot_name.name_case = 0x0; + MEMCPY(dot_name.name, DOS_CUR_DIR_NAME, DOS_NAME_LENGTH); + + ret = p_fs->fs_func->init_dir_entry(sb, &clu, 0, TYPE_DIR, clu.dir, 0); + if (ret != FFS_SUCCESS) + return ret; + + ret = p_fs->fs_func->init_ext_entry(sb, &clu, 0, 1, NULL, &dot_name); + if (ret != FFS_SUCCESS) + return ret; + + MEMCPY(dot_name.name, DOS_PAR_DIR_NAME, DOS_NAME_LENGTH); + + if (p_dir->dir == p_fs->root_dir) + ret = p_fs->fs_func->init_dir_entry(sb, &clu, 1, TYPE_DIR, CLUSTER_32(0), 0); + else + ret = p_fs->fs_func->init_dir_entry(sb, &clu, 1, TYPE_DIR, p_dir->dir, 0); + + if (ret != FFS_SUCCESS) + return ret; + + ret = p_fs->fs_func->init_ext_entry(sb, &clu, 1, 1, NULL, &dot_name); + if (ret != FFS_SUCCESS) + return ret; + } + + /* (2) update the directory entry */ + /* make sub-dir entry in parent directory */ + ret = p_fs->fs_func->init_dir_entry(sb, p_dir, dentry, TYPE_DIR, clu.dir, size); + if (ret != FFS_SUCCESS) + return ret; + + ret = p_fs->fs_func->init_ext_entry(sb, p_dir, dentry, num_entries, p_uniname, &dos_name); + if (ret != FFS_SUCCESS) + return ret; + + fid->dir.dir = p_dir->dir; + fid->dir.size = p_dir->size; + fid->dir.flags = p_dir->flags; + fid->entry = dentry; + + fid->attr = ATTR_SUBDIR; + fid->flags = (p_fs->vol_type == EXFAT) ? 0x03 : 0x01; + fid->size = size; + fid->start_clu = clu.dir; + + fid->type= TYPE_DIR; + fid->rwoffset = 0; + fid->hint_last_off = -1; + + return FFS_SUCCESS; +} /* end of create_dir */ + +INT32 create_file(struct inode *inode, CHAIN_T *p_dir, UNI_NAME_T *p_uniname, UINT8 mode, FILE_ID_T *fid) +{ + INT32 ret, dentry, num_entries; + DOS_NAME_T dos_name; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + ret = get_num_entries_and_dos_name(sb, p_dir, p_uniname, &num_entries, &dos_name); + if (ret) + return ret; + + /* find_empty_entry must be called before alloc_cluster() */ + dentry = find_empty_entry(inode, p_dir, num_entries); + if (dentry < 0) + return FFS_FULL; + + /* (1) update the directory entry */ + /* fill the dos name directory entry information of the created file. + the first cluster is not determined yet. (0) */ + ret = p_fs->fs_func->init_dir_entry(sb, p_dir, dentry, TYPE_FILE | mode, CLUSTER_32(0), 0); + if (ret != FFS_SUCCESS) + return ret; + + ret = p_fs->fs_func->init_ext_entry(sb, p_dir, dentry, num_entries, p_uniname, &dos_name); + if (ret != FFS_SUCCESS) + return ret; + + fid->dir.dir = p_dir->dir; + fid->dir.size = p_dir->size; + fid->dir.flags = p_dir->flags; + fid->entry = dentry; + + fid->attr = ATTR_ARCHIVE | mode; + fid->flags = (p_fs->vol_type == EXFAT) ? 0x03 : 0x01; + fid->size = 0; + fid->start_clu = CLUSTER_32(~0); + + fid->type= TYPE_FILE; + fid->rwoffset = 0; + fid->hint_last_off = -1; + + return FFS_SUCCESS; +} /* end of create_file */ + +void remove_file(struct inode *inode, CHAIN_T *p_dir, INT32 entry) +{ + INT32 num_entries; + UINT32 sector; + DENTRY_T *ep; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + ep = get_entry_in_dir(sb, p_dir, entry, §or); + if (!ep) + return; + + buf_lock(sb, sector); + + /* buf_lock() before call count_ext_entries() */ + num_entries = p_fs->fs_func->count_ext_entries(sb, p_dir, entry, ep); + if (num_entries < 0) { + buf_unlock(sb, sector); + return; + } + num_entries++; + + buf_unlock(sb, sector); + + /* (1) update the directory entry */ + p_fs->fs_func->delete_dir_entry(sb, p_dir, entry, 0, num_entries); +} /* end of remove_file */ + +INT32 rename_file(struct inode *inode, CHAIN_T *p_dir, INT32 oldentry, UNI_NAME_T *p_uniname, FILE_ID_T *fid) +{ + INT32 ret, newentry = -1, num_old_entries, num_new_entries; + UINT32 sector_old, sector_new; + DOS_NAME_T dos_name; + DENTRY_T *epold, *epnew; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + epold = get_entry_in_dir(sb, p_dir, oldentry, §or_old); + if (!epold) + return FFS_MEDIAERR; + + buf_lock(sb, sector_old); + + /* buf_lock() before call count_ext_entries() */ + num_old_entries = p_fs->fs_func->count_ext_entries(sb, p_dir, oldentry, epold); + if (num_old_entries < 0) { + buf_unlock(sb, sector_old); + return FFS_MEDIAERR; + } + num_old_entries++; + + ret = get_num_entries_and_dos_name(sb, p_dir, p_uniname, &num_new_entries, &dos_name); + if (ret) { + buf_unlock(sb, sector_old); + return ret; + } + + if (num_old_entries < num_new_entries) { + newentry = find_empty_entry(inode, p_dir, num_new_entries); + if (newentry < 0) { + buf_unlock(sb, sector_old); + return FFS_FULL; + } + + epnew = get_entry_in_dir(sb, p_dir, newentry, §or_new); + if (!epnew) { + buf_unlock(sb, sector_old); + return FFS_MEDIAERR; + } + + MEMCPY((void *) epnew, (void *) epold, DENTRY_SIZE); + if (p_fs->fs_func->get_entry_type(epnew) == TYPE_FILE) { + p_fs->fs_func->set_entry_attr(epnew, p_fs->fs_func->get_entry_attr(epnew) | ATTR_ARCHIVE); + fid->attr |= ATTR_ARCHIVE; + } + buf_modify(sb, sector_new); + buf_unlock(sb, sector_old); + + if (p_fs->vol_type == EXFAT) { + epold = get_entry_in_dir(sb, p_dir, oldentry+1, §or_old); + buf_lock(sb, sector_old); + epnew = get_entry_in_dir(sb, p_dir, newentry+1, §or_new); + + if (!epold || !epnew) { + buf_unlock(sb, sector_old); + return FFS_MEDIAERR; + } + + MEMCPY((void *) epnew, (void *) epold, DENTRY_SIZE); + buf_modify(sb, sector_new); + buf_unlock(sb, sector_old); + } + + ret = p_fs->fs_func->init_ext_entry(sb, p_dir, newentry, num_new_entries, p_uniname, &dos_name); + if (ret != FFS_SUCCESS) + return ret; + + p_fs->fs_func->delete_dir_entry(sb, p_dir, oldentry, 0, num_old_entries); + fid->entry = newentry; + } else { + if (p_fs->fs_func->get_entry_type(epold) == TYPE_FILE) { + p_fs->fs_func->set_entry_attr(epold, p_fs->fs_func->get_entry_attr(epold) | ATTR_ARCHIVE); + fid->attr |= ATTR_ARCHIVE; + } + buf_modify(sb, sector_old); + buf_unlock(sb, sector_old); + + ret = p_fs->fs_func->init_ext_entry(sb, p_dir, oldentry, num_new_entries, p_uniname, &dos_name); + if (ret != FFS_SUCCESS) + return ret; + + p_fs->fs_func->delete_dir_entry(sb, p_dir, oldentry, num_new_entries, num_old_entries); + } + + return FFS_SUCCESS; +} /* end of rename_file */ + +INT32 move_file(struct inode *inode, CHAIN_T *p_olddir, INT32 oldentry, CHAIN_T *p_newdir, UNI_NAME_T *p_uniname, FILE_ID_T *fid) +{ + INT32 ret, newentry, num_new_entries, num_old_entries; + UINT32 sector_mov, sector_new; + CHAIN_T clu; + DOS_NAME_T dos_name; + DENTRY_T *epmov, *epnew; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + epmov = get_entry_in_dir(sb, p_olddir, oldentry, §or_mov); + if (!epmov) + return FFS_MEDIAERR; + + /* check if the source and target directory is the same */ + if (p_fs->fs_func->get_entry_type(epmov) == TYPE_DIR && + p_fs->fs_func->get_entry_clu0(epmov) == p_newdir->dir) + return FFS_INVALIDPATH; + + buf_lock(sb, sector_mov); + + /* buf_lock() before call count_ext_entries() */ + num_old_entries = p_fs->fs_func->count_ext_entries(sb, p_olddir, oldentry, epmov); + if (num_old_entries < 0) { + buf_unlock(sb, sector_mov); + return FFS_MEDIAERR; + } + num_old_entries++; + + ret = get_num_entries_and_dos_name(sb, p_newdir, p_uniname, &num_new_entries, &dos_name); + if (ret) { + buf_unlock(sb, sector_mov); + return ret; + } + + newentry = find_empty_entry(inode, p_newdir, num_new_entries); + if (newentry < 0) { + buf_unlock(sb, sector_mov); + return FFS_FULL; + } + + epnew = get_entry_in_dir(sb, p_newdir, newentry, §or_new); + if (!epnew) { + buf_unlock(sb, sector_mov); + return FFS_MEDIAERR; + } + + MEMCPY((void *) epnew, (void *) epmov, DENTRY_SIZE); + if (p_fs->fs_func->get_entry_type(epnew) == TYPE_FILE) { + p_fs->fs_func->set_entry_attr(epnew, p_fs->fs_func->get_entry_attr(epnew) | ATTR_ARCHIVE); + fid->attr |= ATTR_ARCHIVE; + } + buf_modify(sb, sector_new); + buf_unlock(sb, sector_mov); + + if (p_fs->vol_type == EXFAT) { + epmov = get_entry_in_dir(sb, p_olddir, oldentry+1, §or_mov); + buf_lock(sb, sector_mov); + epnew = get_entry_in_dir(sb, p_newdir, newentry+1, §or_new); + if (!epmov || !epnew) { + buf_unlock(sb, sector_mov); + return FFS_MEDIAERR; + } + + MEMCPY((void *) epnew, (void *) epmov, DENTRY_SIZE); + buf_modify(sb, sector_new); + buf_unlock(sb, sector_mov); + } else if (p_fs->fs_func->get_entry_type(epnew) == TYPE_DIR) { + /* change ".." pointer to new parent dir */ + clu.dir = p_fs->fs_func->get_entry_clu0(epnew); + clu.flags = 0x01; + + epnew = get_entry_in_dir(sb, &clu, 1, §or_new); + if (!epnew) + return FFS_MEDIAERR; + + if (p_newdir->dir == p_fs->root_dir) + p_fs->fs_func->set_entry_clu0(epnew, CLUSTER_32(0)); + else + p_fs->fs_func->set_entry_clu0(epnew, p_newdir->dir); + buf_modify(sb, sector_new); + } + + ret = p_fs->fs_func->init_ext_entry(sb, p_newdir, newentry, num_new_entries, p_uniname, &dos_name); + if (ret != FFS_SUCCESS) + return ret; + + p_fs->fs_func->delete_dir_entry(sb, p_olddir, oldentry, 0, num_old_entries); + + fid->dir.dir = p_newdir->dir; + fid->dir.size = p_newdir->size; + fid->dir.flags = p_newdir->flags; + + fid->entry = newentry; + + return FFS_SUCCESS; +} /* end of move_file */ + +/* + * Sector Read/Write Functions + */ + +INT32 sector_read(struct super_block *sb, UINT32 sec, struct buffer_head **bh, INT32 read) +{ + INT32 ret = FFS_MEDIAERR; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + if ((sec >= (p_fs->PBR_sector+p_fs->num_sectors)) && (p_fs->num_sectors > 0)) { + PRINT("[EXFAT] sector_read: out of range error! (sec = %d)\n", sec); + fs_error(sb); + return ret; + } + + if (!p_fs->dev_ejected) { + ret = bdev_read(sb, sec, bh, 1, read); + if (ret != FFS_SUCCESS) + p_fs->dev_ejected = TRUE; + } + + return ret; +} /* end of sector_read */ + +INT32 sector_write(struct super_block *sb, UINT32 sec, struct buffer_head *bh, INT32 sync) +{ + INT32 ret = FFS_MEDIAERR; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + if (sec >= (p_fs->PBR_sector+p_fs->num_sectors) && (p_fs->num_sectors > 0)) { + PRINT("[EXFAT] sector_write: out of range error! (sec = %d)\n", sec); + fs_error(sb); + return ret; + } + if (bh == NULL) { + PRINT("[EXFAT] sector_write: bh is NULL!\n"); + fs_error(sb); + return ret; + } + + if (!p_fs->dev_ejected) { + ret = bdev_write(sb, sec, bh, 1, sync); + if (ret != FFS_SUCCESS) + p_fs->dev_ejected = TRUE; + } + + return ret; +} /* end of sector_write */ + +INT32 multi_sector_read(struct super_block *sb, UINT32 sec, struct buffer_head **bh, INT32 num_secs, INT32 read) +{ + INT32 ret = FFS_MEDIAERR; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + if (((sec+num_secs) > (p_fs->PBR_sector+p_fs->num_sectors)) && (p_fs->num_sectors > 0)) { + PRINT("[EXFAT] multi_sector_read: out of range error! (sec = %d, num_secs = %d)\n", sec, num_secs); + fs_error(sb); + return ret; + } + + if (!p_fs->dev_ejected) { + ret = bdev_read(sb, sec, bh, num_secs, read); + if (ret != FFS_SUCCESS) + p_fs->dev_ejected = TRUE; + } + + return ret; +} /* end of multi_sector_read */ + +INT32 multi_sector_write(struct super_block *sb, UINT32 sec, struct buffer_head *bh, INT32 num_secs, INT32 sync) +{ + INT32 ret = FFS_MEDIAERR; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + if ((sec+num_secs) > (p_fs->PBR_sector+p_fs->num_sectors) && (p_fs->num_sectors > 0)) { + PRINT("[EXFAT] multi_sector_write: out of range error! (sec = %d, num_secs = %d)\n", sec, num_secs); + fs_error(sb); + return ret; + } + if (bh == NULL) { + PRINT("[EXFAT] multi_sector_write: bh is NULL!\n"); + fs_error(sb); + return ret; + } + + if (!p_fs->dev_ejected) { + ret = bdev_write(sb, sec, bh, num_secs, sync); + if (ret != FFS_SUCCESS) + p_fs->dev_ejected = TRUE; + } + + return ret; +} /* end of multi_sector_write */ + +/* end of exfat_core.c */ diff --git a/fs/exfat/exfat_data.c b/fs/exfat/exfat_data.c new file mode 100644 index 00000000000..37e1932109b --- /dev/null +++ b/fs/exfat/exfat_data.c @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * 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. + */ + +/************************************************************************/ +/* */ +/* PROJECT : exFAT & FAT12/16/32 File System */ +/* FILE : exfat_data.c */ +/* PURPOSE : exFAT Configuable Data Definitions */ +/* */ +/*----------------------------------------------------------------------*/ +/* NOTES */ +/* */ +/*----------------------------------------------------------------------*/ +/* REVISION HISTORY (Ver 0.9) */ +/* */ +/* - 2010.11.15 [Joosun Hahn] : first writing */ +/* */ +/************************************************************************/ + +#include "exfat_config.h" +#include "exfat_global.h" +#include "exfat_data.h" +#include "exfat_oal.h" + +#include "exfat_blkdev.h" +#include "exfat_cache.h" +#include "exfat_nls.h" +#include "exfat_super.h" +#include "exfat.h" + +/*======================================================================*/ +/* */ +/* GLOBAL VARIABLE DEFINITIONS */ +/* */ +/*======================================================================*/ + +/*----------------------------------------------------------------------*/ +/* File Manager */ +/*----------------------------------------------------------------------*/ + +/* file system volume table */ +FS_STRUCT_T fs_struct[MAX_DRIVE]; + +#if 0 +/*----------------------------------------------------------------------*/ +/* Buffer Manager */ +/*----------------------------------------------------------------------*/ + +/* FAT cache */ +DECLARE_MUTEX(f_sem); +BUF_CACHE_T FAT_cache_array[FAT_CACHE_SIZE]; +BUF_CACHE_T FAT_cache_lru_list; +BUF_CACHE_T FAT_cache_hash_list[FAT_CACHE_HASH_SIZE]; + +/* buf cache */ +DECLARE_MUTEX(b_sem); +BUF_CACHE_T buf_cache_array[BUF_CACHE_SIZE]; +BUF_CACHE_T buf_cache_lru_list; +BUF_CACHE_T buf_cache_hash_list[BUF_CACHE_HASH_SIZE]; +#endif + +/* end of exfat_data.c */ diff --git a/fs/exfat/exfat_data.h b/fs/exfat/exfat_data.h new file mode 100644 index 00000000000..f1a0332c961 --- /dev/null +++ b/fs/exfat/exfat_data.h @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * 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. + */ + +/************************************************************************/ +/* */ +/* PROJECT : exFAT & FAT12/16/32 File System */ +/* FILE : exfat_data.h */ +/* PURPOSE : Header File for exFAT Configuable Constants */ +/* */ +/*----------------------------------------------------------------------*/ +/* NOTES */ +/* */ +/*----------------------------------------------------------------------*/ +/* REVISION HISTORY (Ver 0.9) */ +/* */ +/* - 2010.11.15 [Joosun Hahn] : first writing */ +/* */ +/************************************************************************/ + +#ifndef _EXFAT_DATA_H +#define _EXFAT_DATA_H + +#include "exfat_config.h" +#include "exfat_global.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + /*======================================================================*/ + /* */ + /* FFS CONFIGURATIONS */ + /* (CHANGE THIS PART IF REQUIRED) */ + /* */ + /*======================================================================*/ + + /* max number of block devices */ +#define MAX_DEVICE 2 + + /* max number of volumes on all block devices */ +#define MAX_DRIVE 2 + + /* max number of open files */ +#define MAX_OPEN 20 + + /* max number of root directory entries in FAT12/16 */ + /* (should be an exponential value of 2) */ +#define MAX_DENTRY 512 + + /* cache size (in number of sectors) */ + /* (should be an exponential value of 2) */ +#define FAT_CACHE_SIZE 128 +#define FAT_CACHE_HASH_SIZE 64 +#define BUF_CACHE_SIZE 256 +#define BUF_CACHE_HASH_SIZE 64 + +#ifndef CONFIG_EXFAT_DEFAULT_CODEPAGE +#define CONFIG_EXFAT_DEFAULT_CODEPAGE 437 +#define CONFIG_EXFAT_DEFAULT_IOCHARSET "utf8" +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _EXFAT_DATA_H */ + +/* end of exfat_data.h */ diff --git a/fs/exfat/exfat_global.c b/fs/exfat/exfat_global.c new file mode 100644 index 00000000000..036f08eb0a9 --- /dev/null +++ b/fs/exfat/exfat_global.c @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * 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. + */ + +/************************************************************************/ +/* */ +/* PROJECT : exFAT & FAT12/16/32 File System */ +/* FILE : exfat_global.c */ +/* PURPOSE : exFAT Miscellaneous Functions */ +/* */ +/*----------------------------------------------------------------------*/ +/* NOTES */ +/* */ +/*----------------------------------------------------------------------*/ +/* REVISION HISTORY (Ver 0.9) */ +/* */ +/* - 2010.11.15 [Joosun Hahn] : first writing */ +/* */ +/************************************************************************/ + +#include "exfat_config.h" +#include "exfat_global.h" + +/*----------------------------------------------------------------------*/ +/* Global Variable Definitions */ +/*----------------------------------------------------------------------*/ + +/*======================================================================*/ +/* */ +/* LIBRARY FUNCTION DEFINITIONS -- WELL-KNOWN FUNCTIONS */ +/* */ +/*======================================================================*/ + +/*----------------------------------------------------------------------*/ +/* String Manipulation Functions */ +/* (defined if no system memory functions are available) */ +/*----------------------------------------------------------------------*/ + +INT32 __wstrchr(UINT16 *str, UINT16 wchar) +{ + while (*str) { + if (*(str++) == wchar) return(1); + } + return(0); +} + +INT32 __wstrlen(UINT16 *str) +{ + INT32 length = 0; + + while (*(str++)) length++; + return(length); +} + +/*======================================================================*/ +/* */ +/* LIBRARY FUNCTION DEFINITIONS -- OTHER UTILITY FUNCTIONS */ +/* */ +/*======================================================================*/ + +/*----------------------------------------------------------------------*/ +/* Bitmap Manipulation Functions */ +/*----------------------------------------------------------------------*/ + +#define BITMAP_LOC(v) ((v) >> 3) +#define BITMAP_SHIFT(v) ((v) & 0x07) + +void Bitmap_set_all(UINT8 *bitmap, INT32 mapsize) +{ + MEMSET(bitmap, 0xFF, mapsize); +} /* end of Bitmap_set_all */ + +void Bitmap_clear_all(UINT8 *bitmap, INT32 mapsize) +{ + MEMSET(bitmap, 0x0, mapsize); +} /* end of Bitmap_clear_all */ + +INT32 Bitmap_test(UINT8 *bitmap, INT32 i) +{ + UINT8 data; + + data = bitmap[BITMAP_LOC(i)]; + if ((data >> BITMAP_SHIFT(i)) & 0x01) return(1); + return(0); +} /* end of Bitmap_test */ + +void Bitmap_set(UINT8 *bitmap, INT32 i) +{ + bitmap[BITMAP_LOC(i)] |= (0x01 << BITMAP_SHIFT(i)); +} /* end of Bitmap_set */ + +void Bitmap_clear(UINT8 *bitmap, INT32 i) +{ + bitmap[BITMAP_LOC(i)] &= ~(0x01 << BITMAP_SHIFT(i)); +} /* end of Bitmap_clear */ + +void Bitmap_nbits_set(UINT8 *bitmap, INT32 offset, INT32 nbits) +{ + INT32 i; + + for (i = 0; i < nbits; i++) { + Bitmap_set(bitmap, offset+i); + } +} /* end of Bitmap_nbits_set */ + +void Bitmap_nbits_clear(UINT8 *bitmap, INT32 offset, INT32 nbits) +{ + INT32 i; + + for (i = 0; i < nbits; i++) { + Bitmap_clear(bitmap, offset+i); + } +} /* end of Bitmap_nbits_clear */ + +/*----------------------------------------------------------------------*/ +/* Miscellaneous Library Functions */ +/*----------------------------------------------------------------------*/ + +/* integer to ascii conversion */ +void my_itoa(INT8 *buf, INT32 v) +{ + INT32 mod[10]; + INT32 i; + + for (i = 0; i < 10; i++) { + mod[i] = (v % 10); + v = v / 10; + if (v == 0) break; + } + + if (i == 10) + i--; + + for (; i >= 0; i--) { + *buf = (UINT8) ('0' + mod[i]); + buf++; + } + *buf = '\0'; +} /* end of my_itoa */ + +/* value to base 2 log conversion */ +INT32 my_log2(UINT32 v) +{ + UINT32 bits = 0; + + while (v > 1) { + if (v & 0x01) return(-1); + v >>= 1; + bits++; + } + return(bits); +} /* end of my_log2 */ + +/* end of exfat_global.c */ diff --git a/fs/exfat/exfat_global.h b/fs/exfat/exfat_global.h new file mode 100644 index 00000000000..890bd390de3 --- /dev/null +++ b/fs/exfat/exfat_global.h @@ -0,0 +1,214 @@ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * 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. + */ + +/************************************************************************/ +/* */ +/* PROJECT : exFAT & FAT12/16/32 File System */ +/* FILE : exfat_global.h */ +/* PURPOSE : Header File for exFAT Global Definitions & Misc Functions */ +/* */ +/*----------------------------------------------------------------------*/ +/* NOTES */ +/* */ +/*----------------------------------------------------------------------*/ +/* REVISION HISTORY (Ver 0.9) */ +/* */ +/* - 2010.11.15 [Joosun Hahn] : first writing */ +/* */ +/************************************************************************/ + +#ifndef _EXFAT_GLOBAL_H +#define _EXFAT_GLOBAL_H + +#include +#include +#include +#include +#include + +#include "exfat_config.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + /*======================================================================*/ + /* */ + /* CONSTANT & MACRO DEFINITIONS */ + /* */ + /*======================================================================*/ + + /*----------------------------------------------------------------------*/ + /* Well-Known Constants (DO NOT CHANGE THIS PART !!) */ + /*----------------------------------------------------------------------*/ + +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef OK +#define OK 0 +#endif +#ifndef FAIL +#define FAIL 1 +#endif +#ifndef NULL +#define NULL 0 +#endif + + /* Min/Max macro */ +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) + + /*======================================================================*/ + /* */ + /* TYPE DEFINITIONS */ + /* (CHANGE THIS PART IF REQUIRED) */ + /* */ + /*======================================================================*/ + + /* type definitions for primitive types; + these should be re-defined to meet its size for each OS platform; + these should be used instead of primitive types for portability. */ + + typedef char INT8; // 1 byte signed integer + typedef short INT16; // 2 byte signed integer + typedef int INT32; // 4 byte signed integer + typedef long long INT64; // 8 byte signed integer + + typedef unsigned char UINT8; // 1 byte unsigned integer + typedef unsigned short UINT16; // 2 byte unsigned integer + typedef unsigned int UINT32; // 4 byte unsigned integer + typedef unsigned long long UINT64; // 8 byte ussigned integer + + typedef unsigned char BOOL; + + + /*======================================================================*/ + /* */ + /* LIBRARY FUNCTION DECLARATIONS -- WELL-KNOWN FUNCTIONS */ + /* (CHANGE THIS PART IF REQUIRED) */ + /* */ + /*======================================================================*/ + + /*----------------------------------------------------------------------*/ + /* Memory Manipulation Macros & Functions */ + /*----------------------------------------------------------------------*/ + +#ifdef MALLOC +#undef MALLOC +#endif +#ifdef FREE +#undef FREE +#endif +#ifdef MEMSET +#undef MEMSET +#endif +#ifdef MEMCPY +#undef MEMCPY +#endif +#ifdef MEMCMP +#undef MEMCMP +#endif + +#define MALLOC(size) kmalloc(size, GFP_KERNEL) +#define FREE(mem) if (mem) kfree(mem) +#define MEMSET(mem, value, size) memset(mem, value, size) +#define MEMCPY(dest, src, size) memcpy(dest, src, size) +#define MEMCMP(mem1, mem2, size) memcmp(mem1, mem2, size) +#define COPY_DENTRY(dest, src) memcpy(dest, src, sizeof(DENTRY_T)) + + /*----------------------------------------------------------------------*/ + /* String Manipulation Macros & Functions */ + /*----------------------------------------------------------------------*/ + +#define STRCPY(dest, src) strcpy(dest, src) +#define STRNCPY(dest, src, n) strncpy(dest, src, n) +#define STRCAT(str1, str2) strcat(str1, str2) +#define STRCMP(str1, str2) strcmp(str1, str2) +#define STRNCMP(str1, str2, n) strncmp(str1, str2, n) +#define STRLEN(str) strlen(str) + + INT32 __wstrchr(UINT16 *str, UINT16 wchar); + INT32 __wstrlen(UINT16 *str); + +#define WSTRCHR(str, wchar) __wstrchr(str, wchar) +#define WSTRLEN(str) __wstrlen(str) + + /*----------------------------------------------------------------------*/ + /* Debugging Macros & Functions */ + /* EXFAT_CONFIG_DEBUG_MSG is configured in exfat_config.h */ + /*----------------------------------------------------------------------*/ +#if EXFAT_CONFIG_DEBUG_MSG +#define PRINTK(...) \ + do { \ + printk("[EXFAT] " __VA_ARGS__); \ + } while(0) +#else +#define PRINTK(...) +#endif + + /*======================================================================*/ + /* */ + /* LIBRARY FUNCTION DECLARATIONS -- OTHER UTILITY FUNCTIONS */ + /* (DO NOT CHANGE THIS PART !!) */ + /* */ + /*======================================================================*/ + + /*----------------------------------------------------------------------*/ + /* Bitmap Manipulation Functions */ + /*----------------------------------------------------------------------*/ + + void Bitmap_set_all(UINT8 *bitmap, INT32 mapsize); + void Bitmap_clear_all(UINT8 *bitmap, INT32 mapsize); + INT32 Bitmap_test(UINT8 *bitmap, INT32 i); + void Bitmap_set(UINT8 *bitmap, INT32 i); + void Bitmap_clear(UINT8 *bitmpa, INT32 i); + void Bitmap_nbits_set(UINT8 *bitmap, INT32 offset, INT32 nbits); + void Bitmap_nbits_clear(UINT8 *bitmap, INT32 offset, INT32 nbits); + + /*----------------------------------------------------------------------*/ + /* Miscellaneous Library Functions */ + /*----------------------------------------------------------------------*/ + + void my_itoa(INT8 *buf, INT32 v); + INT32 my_log2(UINT32 v); + + /*======================================================================*/ + /* */ + /* DEFINITIONS FOR DEBUGGING */ + /* (CHANGE THIS PART IF REQUIRED) */ + /* */ + /*======================================================================*/ + + /* debug message ouput macro */ +#ifdef PRINT +#undef PRINT +#endif + +#define PRINT printk + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _EXFAT_GLOBAL_H */ + +/* end of exfat_global.h */ diff --git a/fs/exfat/exfat_nls.c b/fs/exfat/exfat_nls.c new file mode 100644 index 00000000000..f80af8b186b --- /dev/null +++ b/fs/exfat/exfat_nls.c @@ -0,0 +1,394 @@ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * 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. + */ + +/************************************************************************/ +/* */ +/* PROJECT : exFAT & FAT12/16/32 File System */ +/* FILE : exfat_nls.c */ +/* PURPOSE : exFAT NLS Manager */ +/* */ +/*----------------------------------------------------------------------*/ +/* NOTES */ +/* */ +/*----------------------------------------------------------------------*/ +/* REVISION HISTORY (Ver 0.9) */ +/* */ +/* - 2010.11.15 [Joosun Hahn] : first writing */ +/* */ +/************************************************************************/ + +#include "exfat_config.h" +#include "exfat_global.h" +#include "exfat_data.h" + +#include "exfat_nls.h" +#include "exfat_api.h" +#include "exfat_super.h" +#include "exfat.h" + +#include + +/*----------------------------------------------------------------------*/ +/* Global Variable Definitions */ +/*----------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------*/ +/* Local Variable Definitions */ +/*----------------------------------------------------------------------*/ + +static UINT16 bad_dos_chars[] = { + /* + , ; = [ ] */ + 0x002B, 0x002C, 0x003B, 0x003D, 0x005B, 0x005D, + 0xFF0B, 0xFF0C, 0xFF1B, 0xFF1D, 0xFF3B, 0xFF3D, + 0 +}; + +static UINT16 bad_uni_chars[] = { + /* " * / : < > ? \ | */ + 0x0022, 0x002A, 0x002F, 0x003A, + 0x003C, 0x003E, 0x003F, 0x005C, 0x007C, + 0 +}; + +/*----------------------------------------------------------------------*/ +/* Local Function Declarations */ +/*----------------------------------------------------------------------*/ + +static INT32 convert_uni_to_ch(struct nls_table *nls, UINT8 *ch, UINT16 uni, INT32 *lossy); +static INT32 convert_ch_to_uni(struct nls_table *nls, UINT16 *uni, UINT8 *ch, INT32 *lossy); + +/*======================================================================*/ +/* Global Function Definitions */ +/*======================================================================*/ + +UINT16 nls_upper(struct super_block *sb, UINT16 a) +{ + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + if (EXFAT_SB(sb)->options.casesensitive) + return(a); + if (p_fs->vol_utbl != NULL && (p_fs->vol_utbl)[get_col_index(a)] != NULL) + return (p_fs->vol_utbl)[get_col_index(a)][get_row_index(a)]; + else + return a; +} + +INT32 nls_dosname_cmp(struct super_block *sb, UINT8 *a, UINT8 *b) +{ + return(STRNCMP((void *) a, (void *) b, DOS_NAME_LENGTH)); +} /* end of nls_dosname_cmp */ + +INT32 nls_uniname_cmp(struct super_block *sb, UINT16 *a, UINT16 *b) +{ + INT32 i; + + for (i = 0; i < MAX_NAME_LENGTH; i++, a++, b++) { + if (nls_upper(sb, *a) != nls_upper(sb, *b)) return(1); + if (*a == 0x0) return(0); + } + return(0); +} /* end of nls_uniname_cmp */ + +void nls_uniname_to_dosname(struct super_block *sb, DOS_NAME_T *p_dosname, UNI_NAME_T *p_uniname, INT32 *p_lossy) +{ + INT32 i, j, len, lossy = FALSE; + UINT8 buf[MAX_CHARSET_SIZE]; + UINT8 lower = 0, upper = 0; + UINT8 *dosname = p_dosname->name; + UINT16 *uniname = p_uniname->name; + UINT16 *p, *last_period; + struct nls_table *nls = EXFAT_SB(sb)->nls_disk; + + for (i = 0; i < DOS_NAME_LENGTH; i++) { + *(dosname+i) = ' '; + } + + if (!nls_uniname_cmp(sb, uniname, (UINT16 *) UNI_CUR_DIR_NAME)) { + *(dosname) = '.'; + p_dosname->name_case = 0x0; + if (p_lossy != NULL) *p_lossy = FALSE; + return; + } + + if (!nls_uniname_cmp(sb, uniname, (UINT16 *) UNI_PAR_DIR_NAME)) { + *(dosname) = '.'; + *(dosname+1) = '.'; + p_dosname->name_case = 0x0; + if (p_lossy != NULL) *p_lossy = FALSE; + return; + } + + /* search for the last embedded period */ + last_period = NULL; + for (p = uniname; *p; p++) { + if (*p == (UINT16) '.') last_period = p; + } + + i = 0; + while (i < DOS_NAME_LENGTH) { + if (i == 8) { + if (last_period == NULL) break; + + if (uniname <= last_period) { + if (uniname < last_period) lossy = TRUE; + uniname = last_period + 1; + } + } + + if (*uniname == (UINT16) '\0') { + break; + } else if (*uniname == (UINT16) ' ') { + lossy = TRUE; + } else if (*uniname == (UINT16) '.') { + if (uniname < last_period) lossy = TRUE; + else i = 8; + } else if (WSTRCHR(bad_dos_chars, *uniname)) { + lossy = TRUE; + *(dosname+i) = '_'; + i++; + } else { + len = convert_uni_to_ch(nls, buf, *uniname, &lossy); + + if (len > 1) { + if ((i >= 8) && ((i+len) > DOS_NAME_LENGTH)) { + break; + } + if ((i < 8) && ((i+len) > 8)) { + i = 8; + continue; + } + + lower = 0xFF; + + for (j = 0; j < len; j++, i++) { + *(dosname+i) = *(buf+j); + } + } else { /* len == 1 */ + if ((*buf >= 'a') && (*buf <= 'z')) { + *(dosname+i) = *buf - ('a' - 'A'); + + if (i < 8) lower |= 0x08; + else lower |= 0x10; + } else if ((*buf >= 'A') && (*buf <= 'Z')) { + *(dosname+i) = *buf; + + if (i < 8) upper |= 0x08; + else upper |= 0x10; + } else { + *(dosname+i) = *buf; + } + i++; + } + } + + uniname++; + } + + if (*dosname == 0xE5) *dosname = 0x05; + if (*uniname != 0x0) lossy = TRUE; + + if (upper & lower) p_dosname->name_case = 0xFF; + else p_dosname->name_case = lower; + + if (p_lossy != NULL) *p_lossy = lossy; +} /* end of nls_uniname_to_dosname */ + +void nls_dosname_to_uniname(struct super_block *sb, UNI_NAME_T *p_uniname, DOS_NAME_T *p_dosname) +{ + INT32 i = 0, j, n = 0; + UINT8 buf[DOS_NAME_LENGTH+2]; + UINT8 *dosname = p_dosname->name; + UINT16 *uniname = p_uniname->name; + struct nls_table *nls = EXFAT_SB(sb)->nls_disk; + + if (*dosname == 0x05) { + *buf = 0xE5; + i++; + n++; + } + + for ( ; i < 8; i++, n++) { + if (*(dosname+i) == ' ') break; + + if ((*(dosname+i) >= 'A') && (*(dosname+i) <= 'Z') && (p_dosname->name_case & 0x08)) + *(buf+n) = *(dosname+i) + ('a' - 'A'); + else + *(buf+n) = *(dosname+i); + } + if (*(dosname+8) != ' ') { + *(buf+n) = '.'; + n++; + } + + for (i = 8; i < DOS_NAME_LENGTH; i++, n++) { + if (*(dosname+i) == ' ') break; + + if ((*(dosname+i) >= 'A') && (*(dosname+i) <= 'Z') && (p_dosname->name_case & 0x10)) + *(buf+n) = *(dosname+i) + ('a' - 'A'); + else + *(buf+n) = *(dosname+i); + } + *(buf+n) = '\0'; + + i = j = 0; + while (j < (MAX_NAME_LENGTH-1)) { + if (*(buf+i) == '\0') break; + + i += convert_ch_to_uni(nls, uniname, (buf+i), NULL); + + uniname++; + j++; + } + + *uniname = (UINT16) '\0'; +} /* end of nls_dosname_to_uniname */ + +void nls_uniname_to_cstring(struct super_block *sb, UINT8 *p_cstring, UNI_NAME_T *p_uniname) +{ + INT32 i, j, len; + UINT8 buf[MAX_CHARSET_SIZE]; + UINT16 *uniname = p_uniname->name; + struct nls_table *nls = EXFAT_SB(sb)->nls_io; + + i = 0; + while (i < (MAX_NAME_LENGTH-1)) { + if (*uniname == (UINT16) '\0') break; + + len = convert_uni_to_ch(nls, buf, *uniname, NULL); + + if (len > 1) { + for (j = 0; j < len; j++) + *p_cstring++ = (INT8) *(buf+j); + } else { /* len == 1 */ + *p_cstring++ = (INT8) *buf; + } + + uniname++; + i++; + } + + *p_cstring = '\0'; +} /* end of nls_uniname_to_cstring */ + +void nls_cstring_to_uniname(struct super_block *sb, UNI_NAME_T *p_uniname, UINT8 *p_cstring, INT32 *p_lossy) +{ + INT32 i, j, lossy = FALSE; + UINT8 *end_of_name; + UINT8 upname[MAX_NAME_LENGTH * 2]; + UINT16 *uniname = p_uniname->name; + struct nls_table *nls = EXFAT_SB(sb)->nls_io; + + + /* strip all trailing spaces */ + end_of_name = p_cstring + STRLEN((INT8 *) p_cstring); + + while (*(--end_of_name) == ' ') { + if (end_of_name < p_cstring) break; + } + *(++end_of_name) = '\0'; + + if (STRCMP((INT8 *) p_cstring, ".") && STRCMP((INT8 *) p_cstring, "..")) { + + /* strip all trailing periods */ + while (*(--end_of_name) == '.') { + if (end_of_name < p_cstring) break; + } + *(++end_of_name) = '\0'; + } + + if (*p_cstring == '\0') + lossy = TRUE; + + i = j = 0; + while (j < (MAX_NAME_LENGTH-1)) { + if (*(p_cstring+i) == '\0') break; + + i += convert_ch_to_uni(nls, uniname, (UINT8 *)(p_cstring+i), &lossy); + + if ((*uniname < 0x0020) || WSTRCHR(bad_uni_chars, *uniname)) + lossy = TRUE; + + SET16_A(upname + j * 2, nls_upper(sb, *uniname)); + + uniname++; + j++; + } + + if (*(p_cstring+i) != '\0') + lossy = TRUE; + *uniname = (UINT16) '\0'; + + p_uniname->name_len = j; + p_uniname->name_hash = calc_checksum_2byte((void *) upname, j<<1, 0, CS_DEFAULT); + + if (p_lossy != NULL) + *p_lossy = lossy; +} /* end of nls_cstring_to_uniname */ + +/*======================================================================*/ +/* Local Function Definitions */ +/*======================================================================*/ + +static INT32 convert_ch_to_uni(struct nls_table *nls, UINT16 *uni, UINT8 *ch, INT32 *lossy) +{ + int len; + + *uni = 0x0; + + if (ch[0] < 0x80) { + *uni = (UINT16) ch[0]; + return(1); + } + + if ((len = nls->char2uni(ch, NLS_MAX_CHARSET_SIZE, uni)) < 0) { + /* conversion failed */ + printk("%s: fail to use nls \n", __func__); + if (lossy != NULL) + *lossy = TRUE; + *uni = (UINT16) '_'; + if (!strcmp(nls->charset, "utf8")) return(1); + else return(2); + } + + return(len); +} /* end of convert_ch_to_uni */ + +static INT32 convert_uni_to_ch(struct nls_table *nls, UINT8 *ch, UINT16 uni, INT32 *lossy) +{ + int len; + + ch[0] = 0x0; + + if (uni < 0x0080) { + ch[0] = (UINT8) uni; + return(1); + } + + if ((len = nls->uni2char(uni, ch, NLS_MAX_CHARSET_SIZE)) < 0) { + /* conversion failed */ + printk("%s: fail to use nls \n", __func__); + if (lossy != NULL) *lossy = TRUE; + ch[0] = '_'; + return(1); + } + + return(len); + +} /* end of convert_uni_to_ch */ + +/* end of exfat_nls.c */ diff --git a/fs/exfat/exfat_nls.h b/fs/exfat/exfat_nls.h new file mode 100644 index 00000000000..5b14cef0246 --- /dev/null +++ b/fs/exfat/exfat_nls.h @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * 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. + */ + +/************************************************************************/ +/* */ +/* PROJECT : exFAT & FAT12/16/32 File System */ +/* FILE : exfat_nls.h */ +/* PURPOSE : Header File for exFAT NLS Manager */ +/* */ +/*----------------------------------------------------------------------*/ +/* NOTES */ +/* */ +/*----------------------------------------------------------------------*/ +/* REVISION HISTORY (Ver 0.9) */ +/* */ +/* - 2010.11.15 [Joosun Hahn] : first writing */ +/* */ +/************************************************************************/ + +#ifndef _EXFAT_NLS_H +#define _EXFAT_NLS_H + +#include + +#include "exfat_config.h" +#include "exfat_global.h" +#include "exfat_api.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + /*----------------------------------------------------------------------*/ + /* Constant & Macro Definitions */ + /*----------------------------------------------------------------------*/ + +#define NUM_UPCASE 2918 + +#define DOS_CUR_DIR_NAME ". " +#define DOS_PAR_DIR_NAME ".. " + +#ifdef __LITTLE_ENDIAN +#define UNI_CUR_DIR_NAME ".\0" +#define UNI_PAR_DIR_NAME ".\0.\0" +#else +#define UNI_CUR_DIR_NAME "\0." +#define UNI_PAR_DIR_NAME "\0.\0." +#endif + +/*----------------------------------------------------------------------*/ +/* Type Definitions */ +/*----------------------------------------------------------------------*/ + +/* DOS name stucture */ +typedef struct { + UINT8 name[DOS_NAME_LENGTH]; + UINT8 name_case; +} DOS_NAME_T; + +/* unicode name stucture */ +typedef struct { + UINT16 name[MAX_NAME_LENGTH]; + UINT16 name_hash; + UINT8 name_len; +} UNI_NAME_T; + +/*----------------------------------------------------------------------*/ +/* External Function Declarations */ +/*----------------------------------------------------------------------*/ + +/* NLS management function */ +UINT16 nls_upper(struct super_block *sb, UINT16 a); +INT32 nls_dosname_cmp(struct super_block *sb, UINT8 *a, UINT8 *b); +INT32 nls_uniname_cmp(struct super_block *sb, UINT16 *a, UINT16 *b); +void nls_uniname_to_dosname(struct super_block *sb, DOS_NAME_T *p_dosname, UNI_NAME_T *p_uniname, INT32 *p_lossy); +void nls_dosname_to_uniname(struct super_block *sb, UNI_NAME_T *p_uniname, DOS_NAME_T *p_dosname); +void nls_uniname_to_cstring(struct super_block *sb, UINT8 *p_cstring, UNI_NAME_T *p_uniname); +void nls_cstring_to_uniname(struct super_block *sb, UNI_NAME_T *p_uniname, UINT8 *p_cstring, INT32 *p_lossy); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _EXFAT_NLS_H */ + +/* end of exfat_nls.h */ diff --git a/fs/exfat/exfat_oal.c b/fs/exfat/exfat_oal.c new file mode 100644 index 00000000000..8d1a9b93bcc --- /dev/null +++ b/fs/exfat/exfat_oal.c @@ -0,0 +1,189 @@ +/* Some of the source code in this file came from "linux/fs/fat/misc.c". */ +/* + * linux/fs/fat/misc.c + * + * Written 1992,1993 by Werner Almesberger + * 22/11/2000 - Fixed fat_date_unix2dos for dates earlier than 01/01/1980 + * and date_dos2unix for date==0 by Igor Zhbanov(bsg@uniyar.ac.ru) + */ + +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * 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. + */ + +/************************************************************************/ +/* */ +/* PROJECT : exFAT & FAT12/16/32 File System */ +/* FILE : exfat_oal.c */ +/* PURPOSE : exFAT OS Adaptation Layer */ +/* (Semaphore Functions & Real-Time Clock Functions) */ +/* */ +/*----------------------------------------------------------------------*/ +/* NOTES */ +/* */ +/*----------------------------------------------------------------------*/ +/* REVISION HISTORY (Ver 0.9) */ +/* */ +/* - 2010.11.15 [Joosun Hahn] : first writing */ +/* */ +/************************************************************************/ + +#include +#include + +#include "exfat_config.h" +#include "exfat_global.h" +#include "exfat_api.h" +#include "exfat_oal.h" + +/*======================================================================*/ +/* */ +/* SEMAPHORE FUNCTIONS */ +/* */ +/*======================================================================*/ + +DECLARE_MUTEX(z_sem); + +INT32 sm_init(struct semaphore *sm) +{ + sema_init(sm, 1); + return(0); +} /* end of sm_init */ + +INT32 sm_P(struct semaphore *sm) +{ + down(sm); + return 0; +} /* end of sm_P */ + +void sm_V(struct semaphore *sm) +{ + up(sm); +} /* end of sm_V */ + + +/*======================================================================*/ +/* */ +/* REAL-TIME CLOCK FUNCTIONS */ +/* */ +/*======================================================================*/ + +extern struct timezone sys_tz; + +/* + * The epoch of FAT timestamp is 1980. + * : bits : value + * date: 0 - 4: day (1 - 31) + * date: 5 - 8: month (1 - 12) + * date: 9 - 15: year (0 - 127) from 1980 + * time: 0 - 4: sec (0 - 29) 2sec counts + * time: 5 - 10: min (0 - 59) + * time: 11 - 15: hour (0 - 23) + */ +#define UNIX_SECS_1980 315532800L + +#if BITS_PER_LONG == 64 +#define UNIX_SECS_2108 4354819200L +#endif +/* days between 1.1.70 and 1.1.80 (2 leap days) */ +#define DAYS_DELTA_DECADE (365 * 10 + 2) +/* 120 (2100 - 1980) isn't leap year */ +#define NO_LEAP_YEAR_2100 (120) +#define IS_LEAP_YEAR(y) (!((y) & 3) && (y) != NO_LEAP_YEAR_2100) + +#define SECS_PER_MIN (60) +#define SECS_PER_HOUR (60 * SECS_PER_MIN) +#define SECS_PER_DAY (24 * SECS_PER_HOUR) + +#define MAKE_LEAP_YEAR(leap_year, year) \ + do { \ + if (unlikely(year > NO_LEAP_YEAR_2100)) \ + leap_year = ((year + 3) / 4) - 1; \ + else \ + leap_year = ((year + 3) / 4); \ + } while(0) + +/* Linear day numbers of the respective 1sts in non-leap years. */ +static time_t accum_days_in_year[] = { + /* Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec */ + 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, +}; + +TIMESTAMP_T *tm_current(TIMESTAMP_T *tp) +{ + struct timespec ts = CURRENT_TIME_SEC; + time_t second = ts.tv_sec; + time_t day, leap_day, month, year; + + second -= sys_tz.tz_minuteswest * SECS_PER_MIN; + + /* Jan 1 GMT 00:00:00 1980. But what about another time zone? */ + if (second < UNIX_SECS_1980) { + tp->sec = 0; + tp->min = 0; + tp->hour = 0; + tp->day = 1; + tp->mon = 1; + tp->year = 0; + return(tp); + } +#if BITS_PER_LONG == 64 + if (second >= UNIX_SECS_2108) { + tp->sec = 59; + tp->min = 59; + tp->hour = 23; + tp->day = 31; + tp->mon = 12; + tp->year = 127; + return(tp); + } +#endif + + day = second / SECS_PER_DAY - DAYS_DELTA_DECADE; + year = day / 365; + + MAKE_LEAP_YEAR(leap_day, year); + if (year * 365 + leap_day > day) + year--; + + MAKE_LEAP_YEAR(leap_day, year); + + day -= year * 365 + leap_day; + + if (IS_LEAP_YEAR(year) && day == accum_days_in_year[3]) { + month = 2; + } else { + if (IS_LEAP_YEAR(year) && day > accum_days_in_year[3]) + day--; + for (month = 1; month < 12; month++) { + if (accum_days_in_year[month + 1] > day) + break; + } + } + day -= accum_days_in_year[month]; + + tp->sec = second % SECS_PER_MIN; + tp->min = (second / SECS_PER_MIN) % 60; + tp->hour = (second / SECS_PER_HOUR) % 24; + tp->day = day + 1; + tp->mon = month; + tp->year = year; + + return(tp); +} /* end of tm_current */ + +/* end of exfat_oal.c */ diff --git a/fs/exfat/exfat_oal.h b/fs/exfat/exfat_oal.h new file mode 100644 index 00000000000..ca3f956eead --- /dev/null +++ b/fs/exfat/exfat_oal.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * 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. + */ + +/************************************************************************/ +/* */ +/* PROJECT : exFAT & FAT12/16/32 File System */ +/* FILE : exfat_oal.h */ +/* PURPOSE : Header File for exFAT OS Adaptation Layer */ +/* (Semaphore Functions & Real-Time Clock Functions) */ +/* */ +/*----------------------------------------------------------------------*/ +/* NOTES */ +/* */ +/*----------------------------------------------------------------------*/ +/* REVISION HISTORY (Ver 0.9) */ +/* */ +/* - 2010.11.15 [Joosun Hahn] : first writing */ +/* */ +/************************************************************************/ + +#ifndef _EXFAT_OAL_H +#define _EXFAT_OAL_H + +#include "exfat_config.h" +#include "exfat_global.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + /*----------------------------------------------------------------------*/ + /* Constant & Macro Definitions (Configurable) */ + /*----------------------------------------------------------------------*/ + + /*----------------------------------------------------------------------*/ + /* Constant & Macro Definitions (Non-Configurable) */ + /*----------------------------------------------------------------------*/ + + /*----------------------------------------------------------------------*/ + /* Type Definitions */ + /*----------------------------------------------------------------------*/ + + typedef struct { + UINT16 sec; /* 0 ~ 59 */ + UINT16 min; /* 0 ~ 59 */ + UINT16 hour; /* 0 ~ 23 */ + UINT16 day; /* 1 ~ 31 */ + UINT16 mon; /* 1 ~ 12 */ + UINT16 year; /* 0 ~ 127 (since 1980) */ + } TIMESTAMP_T; + + /*----------------------------------------------------------------------*/ + /* External Function Declarations */ + /*----------------------------------------------------------------------*/ + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37) +#define DECLARE_MUTEX(m) DEFINE_SEMAPHORE(m) +#endif + + INT32 sm_init(struct semaphore *sm); + INT32 sm_P(struct semaphore *sm); + void sm_V(struct semaphore *sm); + + TIMESTAMP_T *tm_current(TIMESTAMP_T *tm); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _EXFAT_OAL_H */ + +/* end of exfat_oal.h */ diff --git a/fs/exfat/exfat_part.h b/fs/exfat/exfat_part.h new file mode 100644 index 00000000000..94dd8862f5e --- /dev/null +++ b/fs/exfat/exfat_part.h @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * 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. + */ + +/************************************************************************/ +/* */ +/* PROJECT : exFAT & FAT12/16/32 File System */ +/* FILE : exfat_part.h */ +/* PURPOSE : Header File for exFAT Partition Manager */ +/* */ +/*----------------------------------------------------------------------*/ +/* NOTES */ +/* */ +/*----------------------------------------------------------------------*/ +/* REVISION HISTORY (Ver 0.9) */ +/* */ +/* - 2010.11.15 [Joosun Hahn] : first writing */ +/* */ +/************************************************************************/ + +#ifndef _EXFAT_PART_H +#define _EXFAT_PART_H + +#include "exfat_config.h" +#include "exfat_global.h" +#include "exfat_api.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + /*----------------------------------------------------------------------*/ + /* Constant & Macro Definitions */ + /*----------------------------------------------------------------------*/ + +#define MBR_SIGNATURE 0xAA55 + + /*----------------------------------------------------------------------*/ + /* Type Definitions */ + /*----------------------------------------------------------------------*/ + + /* MS-DOS FAT master boot record (512 bytes) */ + typedef struct { + UINT8 boot_code[446]; + UINT8 partition[64]; + UINT8 signature[2]; + } MBR_SECTOR_T; + + /* MS-DOS FAT partition table (64 bytes) */ + typedef struct { + UINT8 def_boot; + UINT8 bgn_chs[3]; + UINT8 sys_type; + UINT8 end_chs[3]; + UINT8 start_sector[4]; + UINT8 num_sectors[4]; + } PART_ENTRY_T; + + /*----------------------------------------------------------------------*/ + /* External Function Declarations */ + /*----------------------------------------------------------------------*/ + + /* volume management functions */ + INT32 ffsSetPartition(INT32 dev, INT32 num_vol, PART_INFO_T *vol_spec); + INT32 ffsGetPartition(INT32 dev, INT32 *num_vol, PART_INFO_T *vol_spec); + INT32 ffsGetDevInfo(INT32 dev, DEV_INFO_T *info); + + /*----------------------------------------------------------------------*/ + /* External Function Declarations (NOT TO UPPER LAYER) */ + /*----------------------------------------------------------------------*/ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _EXFAT_PART_H */ + +/* end of exfat_part.h */ diff --git a/fs/exfat/exfat_super.c b/fs/exfat/exfat_super.c new file mode 100644 index 00000000000..1bc3b0d2104 --- /dev/null +++ b/fs/exfat/exfat_super.c @@ -0,0 +1,2306 @@ +/* Some of the source code in this file came from "linux/fs/fat/file.c","linux/fs/fat/inode.c" and "linux/fs/fat/misc.c". */ +/* + * linux/fs/fat/file.c + * + * Written 1992,1993 by Werner Almesberger + * + * regular file handling primitives for fat-based filesystems + */ + +/* + * linux/fs/fat/inode.c + * + * Written 1992,1993 by Werner Almesberger + * VFAT extensions by Gordon Chaffee, merged with msdos fs by Henrik Storner + * Rewritten for the constant inumbers support by Al Viro + * + * Fixes: + * + * Max Cohan: Fixed invalid FSINFO offset when info_sector is 0 + */ + +/* + * linux/fs/fat/misc.c + * + * Written 1992,1993 by Werner Almesberger + * 22/11/2000 - Fixed fat_date_unix2dos for dates earlier than 01/01/1980 + * and date_dos2unix for date==0 by Igor Zhbanov(bsg@uniyar.ac.ru) + */ + +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include +#include +#include +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) +#include +#endif + +#include "exfat_version.h" +#include "exfat_config.h" +#include "exfat_global.h" +#include "exfat_data.h" +#include "exfat_oal.h" + +#include "exfat_blkdev.h" +#include "exfat_cache.h" +#include "exfat_part.h" +#include "exfat_nls.h" +#include "exfat_api.h" +#include "exfat.h" + +#include "exfat_super.h" + +static struct kmem_cache *exfat_inode_cachep; + +static int exfat_default_codepage = CONFIG_EXFAT_DEFAULT_CODEPAGE; +static char exfat_default_iocharset[] = CONFIG_EXFAT_DEFAULT_IOCHARSET; + +extern struct timezone sys_tz; + +#define CHECK_ERR(x) BUG_ON(x) +#define ELAPSED_TIME 0 + +#if (ELAPSED_TIME == 1) +#include + +static UINT32 __t1, __t2; +static UINT32 get_current_msec(void) +{ + struct timeval tm; + do_gettimeofday(&tm); + return((UINT32)(tm.tv_sec*1000000 + tm.tv_usec)); +} +#define TIME_START() do {__t1 = get_current_msec();} while (0) +#define TIME_END() do {__t2 = get_current_msec();} while (0) +#define PRINT_TIME(n) do {printk("[EXFAT] Elapsed time %d = %d (usec)\n", n, (__t2 - __t1));} while (0) +#else +#define TIME_START() +#define TIME_END() +#define PRINT_TIME(n) +#endif + +#define UNIX_SECS_1980 315532800L + +#if BITS_PER_LONG == 64 +#define UNIX_SECS_2108 4354819200L +#endif +/* days between 1.1.70 and 1.1.80 (2 leap days) */ +#define DAYS_DELTA_DECADE (365 * 10 + 2) +/* 120 (2100 - 1980) isn't leap year */ +#define NO_LEAP_YEAR_2100 (120) +#define IS_LEAP_YEAR(y) (!((y) & 0x3) && (y) != NO_LEAP_YEAR_2100) + +#define SECS_PER_MIN (60) +#define SECS_PER_HOUR (60 * SECS_PER_MIN) +#define SECS_PER_DAY (24 * SECS_PER_HOUR) + +#define MAKE_LEAP_YEAR(leap_year, year) \ + do { \ + if (unlikely(year > NO_LEAP_YEAR_2100)) \ + leap_year = ((year + 3) / 4) - 1; \ + else \ + leap_year = ((year + 3) / 4); \ + } while(0) + +/* Linear day numbers of the respective 1sts in non-leap years. */ +static time_t accum_days_in_year[] = { + /* Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec */ + 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, +}; + +static void _exfat_truncate(struct inode *inode, loff_t old_size); + +/* Convert a FAT time/date pair to a UNIX date (seconds since 1 1 70). */ +void exfat_time_fat2unix(struct exfat_sb_info *sbi, struct timespec *ts, + DATE_TIME_T *tp) +{ + time_t year = tp->Year; + time_t ld; + + MAKE_LEAP_YEAR(ld, year); + + if (IS_LEAP_YEAR(year) && (tp->Month) > 2) + ld++; + + ts->tv_sec = tp->Second + tp->Minute * SECS_PER_MIN + + tp->Hour * SECS_PER_HOUR + + (year * 365 + ld + accum_days_in_year[(tp->Month)] + (tp->Day - 1) + DAYS_DELTA_DECADE) * SECS_PER_DAY + + sys_tz.tz_minuteswest * SECS_PER_MIN; + ts->tv_nsec = 0; +} + +/* Convert linear UNIX date to a FAT time/date pair. */ +void exfat_time_unix2fat(struct exfat_sb_info *sbi, struct timespec *ts, + DATE_TIME_T *tp) +{ + time_t second = ts->tv_sec; + time_t day, month, year; + time_t ld; + + second -= sys_tz.tz_minuteswest * SECS_PER_MIN; + + /* Jan 1 GMT 00:00:00 1980. But what about another time zone? */ + if (second < UNIX_SECS_1980) { + tp->Second = 0; + tp->Minute = 0; + tp->Hour = 0; + tp->Day = 1; + tp->Month = 1; + tp->Year = 0; + return; + } +#if (BITS_PER_LONG == 64) + if (second >= UNIX_SECS_2108) { + tp->Second = 59; + tp->Minute = 59; + tp->Hour = 23; + tp->Day = 31; + tp->Month = 12; + tp->Year = 127; + return; + } +#endif + day = second / SECS_PER_DAY - DAYS_DELTA_DECADE; + year = day / 365; + MAKE_LEAP_YEAR(ld, year); + if (year * 365 + ld > day) + year--; + + MAKE_LEAP_YEAR(ld, year); + day -= year * 365 + ld; + + if (IS_LEAP_YEAR(year) && day == accum_days_in_year[3]) { + month = 2; + } else { + if (IS_LEAP_YEAR(year) && day > accum_days_in_year[3]) + day--; + for (month = 1; month < 12; month++) { + if (accum_days_in_year[month + 1] > day) + break; + } + } + day -= accum_days_in_year[month]; + + tp->Second = second % SECS_PER_MIN; + tp->Minute = (second / SECS_PER_MIN) % 60; + tp->Hour = (second / SECS_PER_HOUR) % 24; + tp->Day = day + 1; + tp->Month = month; + tp->Year = year; +} + +static struct inode *exfat_iget(struct super_block *sb, loff_t i_pos); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) +static int exfat_generic_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); +#else +static long exfat_generic_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); +#endif +static int exfat_sync_inode(struct inode *inode); +static struct inode *exfat_build_inode(struct super_block *sb, FILE_ID_T *fid, loff_t i_pos); +static void exfat_detach(struct inode *inode); +static void exfat_attach(struct inode *inode, loff_t i_pos); +static inline unsigned long exfat_hash(loff_t i_pos); +static int exfat_write_inode(struct inode *inode, struct writeback_control *wbc); +static void exfat_write_super(struct super_block *sb); + +static void __lock_super(struct super_block *sb) +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0) + lock_super(sb); +#else + struct exfat_sb_info *sbi = EXFAT_SB(sb); + mutex_lock(&sbi->s_lock); +#endif +} + +static void __unlock_super(struct super_block *sb) +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0) + unlock_super(sb); +#else + struct exfat_sb_info *sbi = EXFAT_SB(sb); + mutex_unlock(&sbi->s_lock); +#endif +} + +static int __is_sb_dirty(struct super_block *sb) +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0) + return sb->s_dirt; +#else + struct exfat_sb_info *sbi = EXFAT_SB(sb); + return sbi->s_dirt; +#endif +} + +static void __set_sb_clean(struct super_block *sb) +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0) + sb->s_dirt = 0; +#else + struct exfat_sb_info *sbi = EXFAT_SB(sb); + sbi->s_dirt = 0; +#endif +} + +/*======================================================================*/ +/* Directory Entry Operations */ +/*======================================================================*/ + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0) +static int exfat_readdir(struct file *filp, struct dir_context *ctx) +#else +static int exfat_readdir(struct file *filp, void *dirent, filldir_t filldir) +#endif +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0) + struct inode *inode = file_inode(filp); +#else + struct inode *inode = filp->f_path.dentry->d_inode; +#endif + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + FS_INFO_T *p_fs = &(sbi->fs_info); + BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); + DIR_ENTRY_T de; + unsigned long inum; + loff_t cpos; + int err = 0; + + __lock_super(sb); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0) + cpos = ctx->pos; +#else + cpos = filp->f_pos; +#endif + /* Fake . and .. for the root directory. */ + if ((p_fs->vol_type == EXFAT) || (inode->i_ino == EXFAT_ROOT_INO)) { + while (cpos < 2) { + if (inode->i_ino == EXFAT_ROOT_INO) + inum = EXFAT_ROOT_INO; + else if (cpos == 0) + inum = inode->i_ino; + else /* (cpos == 1) */ + inum = parent_ino(filp->f_path.dentry); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0) + if (!dir_emit_dots(filp, ctx)) +#else + if (filldir(dirent, "..", cpos+1, cpos, inum, DT_DIR) < 0) +#endif + goto out; + cpos++; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0) + ctx->pos++; +#else + filp->f_pos++; +#endif + } + if (cpos == 2) { + cpos = 0; + } + } + if (cpos & (DENTRY_SIZE - 1)) { + err = -ENOENT; + goto out; + } + +get_new: + EXFAT_I(inode)->fid.size = i_size_read(inode); + EXFAT_I(inode)->fid.rwoffset = cpos >> DENTRY_SIZE_BITS; + + err = FsReadDir(inode, &de); + if (err) { + /* at least we tried to read a sector + * move cpos to next sector position (should be aligned) + */ + if (err == FFS_MEDIAERR) { + cpos += 1 << p_bd->sector_size_bits; + cpos &= ~((1 << p_bd->sector_size_bits)-1); + } + + err = -EIO; + goto end_of_dir; + } + + cpos = EXFAT_I(inode)->fid.rwoffset << DENTRY_SIZE_BITS; + + if (!de.Name[0]) + goto end_of_dir; + + if (!memcmp(de.ShortName, DOS_CUR_DIR_NAME, DOS_NAME_LENGTH)) { + inum = inode->i_ino; + } else if (!memcmp(de.ShortName, DOS_PAR_DIR_NAME, DOS_NAME_LENGTH)) { + inum = parent_ino(filp->f_path.dentry); + } else { + loff_t i_pos = ((loff_t) EXFAT_I(inode)->fid.start_clu << 32) | + ((EXFAT_I(inode)->fid.rwoffset-1) & 0xffffffff); + + struct inode *tmp = exfat_iget(sb, i_pos); + if (tmp) { + inum = tmp->i_ino; + iput(tmp); + } else { + inum = iunique(sb, EXFAT_ROOT_INO); + } + } + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0) + if (!dir_emit(ctx, de.Name, strlen(de.Name), inum, + (de.Attr & ATTR_SUBDIR) ? DT_DIR : DT_REG)) +#else + if (filldir(dirent, de.Name, strlen(de.Name), cpos-1, inum, + (de.Attr & ATTR_SUBDIR) ? DT_DIR : DT_REG) < 0) +#endif + goto out; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0) + ctx->pos = cpos; +#else + filp->f_pos = cpos; +#endif + goto get_new; + +end_of_dir: +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0) + ctx->pos = cpos; +#else + filp->f_pos = cpos; +#endif +out: + __unlock_super(sb); + return err; +} + +static int exfat_ioctl_volume_id(struct inode *dir) +{ + struct super_block *sb = dir->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + FS_INFO_T *p_fs = &(sbi->fs_info); + + return p_fs->vol_id; +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) +static int exfat_generic_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +#else +static long exfat_generic_ioctl(struct file *filp, + unsigned int cmd, unsigned long arg) +#endif +{ +#if EXFAT_CONFIG_KERNEL_DEBUG +#if !(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)) + struct inode *inode = filp->f_dentry->d_inode; +#endif + unsigned int flags; +#endif /* EXFAT_CONFIG_KERNEL_DEBUG */ + + switch (cmd) { + case EXFAT_IOCTL_GET_VOLUME_ID: + return exfat_ioctl_volume_id(inode); +#if EXFAT_CONFIG_KERNEL_DEBUG + case EXFAT_IOC_GET_DEBUGFLAGS: { + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + + flags = sbi->debug_flags; + return put_user(flags, (int __user *)arg); + } + case EXFAT_IOC_SET_DEBUGFLAGS: { + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + if (get_user(flags, (int __user *) arg)) + return -EFAULT; + + __lock_super(sb); + sbi->debug_flags = flags; + __unlock_super(sb); + + return 0; + } +#endif /* EXFAT_CONFIG_KERNEL_DEBUG */ + default: + return -ENOTTY; /* Inappropriate ioctl for device */ + } +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) +static int exfat_file_fsync(struct file *filp, int datasync) +{ + struct inode *inode = filp->f_mapping->host; + struct super_block *sb = inode->i_sb; + int res, err; + + res = generic_file_fsync(filp, datasync); + err = FsSyncVol(sb, 1); + + return res ? res : err; +} +#endif + +const struct file_operations exfat_dir_operations = { + .llseek = generic_file_llseek, + .read = generic_read_dir, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0) + .iterate = exfat_readdir, +#else + .readdir = exfat_readdir, +#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) + .ioctl = exfat_generic_ioctl, + .fsync = exfat_file_fsync, +#else + .unlocked_ioctl = exfat_generic_ioctl, + .fsync = generic_file_fsync, +#endif +}; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,00) +static int exfat_create(struct inode *dir, struct dentry *dentry, umode_t mode, + bool excl) +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,00) +static int exfat_create(struct inode *dir, struct dentry *dentry, umode_t mode, + struct nameidata *nd) +#else +static int exfat_create(struct inode *dir, struct dentry *dentry, int mode, + struct nameidata *nd) +#endif +{ + struct super_block *sb = dir->i_sb; + struct inode *inode; + struct timespec ts; + FILE_ID_T fid; + loff_t i_pos; + int err; + + __lock_super(sb); + + PRINTK("exfat_create entered\n"); + + ts = CURRENT_TIME_SEC; + + err = FsCreateFile(dir, (UINT8 *) dentry->d_name.name, FM_REGULAR, &fid); + if (err) { + if (err == FFS_INVALIDPATH) + err = -EINVAL; + else if (err == FFS_FILEEXIST) + err = -EEXIST; + else if (err == FFS_FULL) + err = -ENOSPC; + else if (err == FFS_NAMETOOLONG) + err = -ENAMETOOLONG; + else + err = -EIO; + goto out; + } + dir->i_version++; + dir->i_ctime = dir->i_mtime = dir->i_atime = ts; + if (IS_DIRSYNC(dir)) + (void) exfat_sync_inode(dir); + else + mark_inode_dirty(dir); + + i_pos = ((loff_t) fid.dir.dir << 32) | (fid.entry & 0xffffffff); + + inode = exfat_build_inode(sb, &fid, i_pos); + if (IS_ERR(inode)) { + err = PTR_ERR(inode); + goto out; + } + inode->i_version++; + inode->i_mtime = inode->i_atime = inode->i_ctime = ts; + /* timestamp is already written, so mark_inode_dirty() is unnecessary. */ + + dentry->d_time = dentry->d_parent->d_inode->i_version; + d_instantiate(dentry, inode); + +out: + __unlock_super(sb); + PRINTK("exfat_create exited\n"); + return err; +} + +static int exfat_find(struct inode *dir, struct qstr *qname, + FILE_ID_T *fid) +{ + int err; + + if (qname->len == 0) + return -ENOENT; + + err = FsLookupFile(dir, (UINT8 *) qname->name, fid); + if (err) + return -ENOENT; + + return 0; +} + +static int exfat_d_anon_disconn(struct dentry *dentry) +{ + return IS_ROOT(dentry) && (dentry->d_flags & DCACHE_DISCONNECTED); +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,00) +static struct dentry *exfat_lookup(struct inode *dir, struct dentry *dentry, + unsigned int flags) +#else +static struct dentry *exfat_lookup(struct inode *dir, struct dentry *dentry, + struct nameidata *nd) +#endif +{ + struct super_block *sb = dir->i_sb; + struct inode *inode; + struct dentry *alias; + int err; + FILE_ID_T fid; + loff_t i_pos; + UINT64 ret; + mode_t i_mode; + + __lock_super(sb); + PRINTK("exfat_lookup entered\n"); + err = exfat_find(dir, &dentry->d_name, &fid); + if (err) { + if (err == -ENOENT) { + inode = NULL; + goto out; + } + goto error; + } + + i_pos = ((loff_t) fid.dir.dir << 32) | (fid.entry & 0xffffffff); + inode = exfat_build_inode(sb, &fid, i_pos); + if (IS_ERR(inode)) { + err = PTR_ERR(inode); + goto error; + } + + i_mode = inode->i_mode; + if (S_ISLNK(i_mode)) { + EXFAT_I(inode)->target = MALLOC(i_size_read(inode)+1); + if (!EXFAT_I(inode)->target) { + err = -ENOMEM; + goto error; + } + FsReadFile(dir, &fid, EXFAT_I(inode)->target, i_size_read(inode), &ret); + *(EXFAT_I(inode)->target + i_size_read(inode)) = '\0'; + } + + alias = d_find_alias(inode); + if (alias && !exfat_d_anon_disconn(alias)) { + CHECK_ERR(d_unhashed(alias)); + if (!S_ISDIR(i_mode)) + d_move(alias, dentry); + iput(inode); + __unlock_super(sb); + PRINTK("exfat_lookup exited 1\n"); + return alias; + } else { + dput(alias); + } +out: + __unlock_super(sb); + dentry->d_time = dentry->d_parent->d_inode->i_version; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38) + dentry->d_op = sb->s_root->d_op; + dentry = d_splice_alias(inode, dentry); + if (dentry) { + dentry->d_op = sb->s_root->d_op; + dentry->d_time = dentry->d_parent->d_inode->i_version; + } +#else + dentry = d_splice_alias(inode, dentry); + if (dentry) + dentry->d_time = dentry->d_parent->d_inode->i_version; +#endif + PRINTK("exfat_lookup exited 2\n"); + return dentry; + +error: + __unlock_super(sb); + PRINTK("exfat_lookup exited 3\n"); + return ERR_PTR(err); +} + +static int exfat_unlink(struct inode *dir, struct dentry *dentry) +{ + struct inode *inode = dentry->d_inode; + struct super_block *sb = dir->i_sb; + struct timespec ts; + int err; + + __lock_super(sb); + + PRINTK("exfat_unlink entered\n"); + + ts = CURRENT_TIME_SEC; + + EXFAT_I(inode)->fid.size = i_size_read(inode); + + err = FsRemoveFile(dir, &(EXFAT_I(inode)->fid)); + if (err) { + if (err == FFS_PERMISSIONERR) + err = -EPERM; + else + err = -EIO; + goto out; + } + dir->i_version++; + dir->i_mtime = dir->i_atime = ts; + if (IS_DIRSYNC(dir)) + (void) exfat_sync_inode(dir); + else + mark_inode_dirty(dir); + + clear_nlink(inode); + inode->i_mtime = inode->i_atime = ts; + exfat_detach(inode); + remove_inode_hash(inode); + +out: + __unlock_super(sb); + PRINTK("exfat_unlink exited\n"); + return err; +} + +static int exfat_symlink(struct inode *dir, struct dentry *dentry, const char *target) +{ + struct super_block *sb = dir->i_sb; + struct inode *inode; + struct timespec ts; + FILE_ID_T fid; + loff_t i_pos; + int err; + UINT64 len = (UINT64) strlen(target); + UINT64 ret; + + __lock_super(sb); + + PRINTK("exfat_symlink entered\n"); + + ts = CURRENT_TIME_SEC; + + err = FsCreateFile(dir, (UINT8 *) dentry->d_name.name, FM_SYMLINK, &fid); + if (err) { + if (err == FFS_INVALIDPATH) + err = -EINVAL; + else if (err == FFS_FILEEXIST) + err = -EEXIST; + else if (err == FFS_FULL) + err = -ENOSPC; + else + err = -EIO; + goto out; + } + + err = FsWriteFile(dir, &fid, (char *) target, len, &ret); + + if (err) { + FsRemoveFile(dir, &fid); + + if (err == FFS_FULL) + err = -ENOSPC; + else + err = -EIO; + goto out; + } + + dir->i_version++; + dir->i_ctime = dir->i_mtime = dir->i_atime = ts; + if (IS_DIRSYNC(dir)) + (void) exfat_sync_inode(dir); + else + mark_inode_dirty(dir); + + i_pos = ((loff_t) fid.dir.dir << 32) | (fid.entry & 0xffffffff); + + inode = exfat_build_inode(sb, &fid, i_pos); + if (IS_ERR(inode)) { + err = PTR_ERR(inode); + goto out; + } + inode->i_version++; + inode->i_mtime = inode->i_atime = inode->i_ctime = ts; + /* timestamp is already written, so mark_inode_dirty() is unneeded. */ + + EXFAT_I(inode)->target = MALLOC(len+1); + if (!EXFAT_I(inode)->target) { + err = -ENOMEM; + goto out; + } + MEMCPY(EXFAT_I(inode)->target, target, len+1); + + dentry->d_time = dentry->d_parent->d_inode->i_version; + d_instantiate(dentry, inode); + +out: + __unlock_super(sb); + PRINTK("exfat_symlink exited\n"); + return err; +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,00) +static int exfat_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) +#else +static int exfat_mkdir(struct inode *dir, struct dentry *dentry, int mode) +#endif +{ + struct super_block *sb = dir->i_sb; + struct inode *inode; + struct timespec ts; + FILE_ID_T fid; + loff_t i_pos; + int err; + + __lock_super(sb); + + PRINTK("exfat_mkdir entered\n"); + + ts = CURRENT_TIME_SEC; + + err = FsCreateDir(dir, (UINT8 *) dentry->d_name.name, &fid); + if (err) { + if (err == FFS_INVALIDPATH) + err = -EINVAL; + else if (err == FFS_FILEEXIST) + err = -EEXIST; + else if (err == FFS_FULL) + err = -ENOSPC; + else if (err == FFS_NAMETOOLONG) + err = -ENAMETOOLONG; + else + err = -EIO; + goto out; + } + dir->i_version++; + dir->i_ctime = dir->i_mtime = dir->i_atime = ts; + if (IS_DIRSYNC(dir)) + (void) exfat_sync_inode(dir); + else + mark_inode_dirty(dir); + inc_nlink(dir); + + i_pos = ((loff_t) fid.dir.dir << 32) | (fid.entry & 0xffffffff); + + inode = exfat_build_inode(sb, &fid, i_pos); + if (IS_ERR(inode)) { + err = PTR_ERR(inode); + goto out; + } + inode->i_version++; + inode->i_mtime = inode->i_atime = inode->i_ctime = ts; + /* timestamp is already written, so mark_inode_dirty() is unneeded. */ + + dentry->d_time = dentry->d_parent->d_inode->i_version; + d_instantiate(dentry, inode); + +out: + __unlock_super(sb); + PRINTK("exfat_mkdir exited\n"); + return err; +} + +static int exfat_rmdir(struct inode *dir, struct dentry *dentry) +{ + struct inode *inode = dentry->d_inode; + struct super_block *sb = dir->i_sb; + struct timespec ts; + int err; + + __lock_super(sb); + + PRINTK("exfat_rmdir entered\n"); + + ts = CURRENT_TIME_SEC; + + EXFAT_I(inode)->fid.size = i_size_read(inode); + + err = FsRemoveDir(dir, &(EXFAT_I(inode)->fid)); + if (err) { + if (err == FFS_INVALIDPATH) + err = -EINVAL; + else if (err == FFS_FILEEXIST) + err = -ENOTEMPTY; + else if (err == FFS_NOTFOUND) + err = -ENOENT; + else if (err == FFS_DIRBUSY) + err = -EBUSY; + else + err = -EIO; + goto out; + } + dir->i_version++; + dir->i_mtime = dir->i_atime = ts; + if (IS_DIRSYNC(dir)) + (void) exfat_sync_inode(dir); + else + mark_inode_dirty(dir); + drop_nlink(dir); + + clear_nlink(inode); + inode->i_mtime = inode->i_atime = ts; + exfat_detach(inode); + remove_inode_hash(inode); + +out: + __unlock_super(sb); + PRINTK("exfat_rmdir exited\n"); + return err; +} + +static int exfat_rename(struct inode *old_dir, struct dentry *old_dentry, + struct inode *new_dir, struct dentry *new_dentry) +{ + struct inode *old_inode, *new_inode; + struct super_block *sb = old_dir->i_sb; + struct timespec ts; + loff_t i_pos; + int err; + + __lock_super(sb); + + PRINTK("exfat_rename entered\n"); + + old_inode = old_dentry->d_inode; + new_inode = new_dentry->d_inode; + + ts = CURRENT_TIME_SEC; + + EXFAT_I(old_inode)->fid.size = i_size_read(old_inode); + + err = FsMoveFile(old_dir, &(EXFAT_I(old_inode)->fid), new_dir, new_dentry); + if (err) { + if (err == FFS_PERMISSIONERR) + err = -EPERM; + else if (err == FFS_INVALIDPATH) + err = -EINVAL; + else if (err == FFS_FILEEXIST) + err = -EEXIST; + else if (err == FFS_NOTFOUND) + err = -ENOENT; + else if (err == FFS_FULL) + err = -ENOSPC; + else + err = -EIO; + goto out; + } + new_dir->i_version++; + new_dir->i_ctime = new_dir->i_mtime = new_dir->i_atime = ts; + if (IS_DIRSYNC(new_dir)) + (void) exfat_sync_inode(new_dir); + else + mark_inode_dirty(new_dir); + + i_pos = ((loff_t) EXFAT_I(old_inode)->fid.dir.dir << 32) | + (EXFAT_I(old_inode)->fid.entry & 0xffffffff); + + exfat_detach(old_inode); + exfat_attach(old_inode, i_pos); + if (IS_DIRSYNC(new_dir)) + (void) exfat_sync_inode(old_inode); + else + mark_inode_dirty(old_inode); + + if ((S_ISDIR(old_inode->i_mode)) && (old_dir != new_dir)) { + drop_nlink(old_dir); + if (!new_inode) inc_nlink(new_dir); + } + + old_dir->i_version++; + old_dir->i_ctime = old_dir->i_mtime = ts; + if (IS_DIRSYNC(old_dir)) + (void) exfat_sync_inode(old_dir); + else + mark_inode_dirty(old_dir); + + if (new_inode) { + exfat_detach(new_inode); + drop_nlink(new_inode); + if (S_ISDIR(new_inode->i_mode)) + drop_nlink(new_inode); + new_inode->i_ctime = ts; + } + +out: + __unlock_super(sb); + PRINTK("exfat_rename exited\n"); + return err; +} + +static int exfat_cont_expand(struct inode *inode, loff_t size) +{ + struct address_space *mapping = inode->i_mapping; + loff_t start = i_size_read(inode), count = size - i_size_read(inode); + int err, err2; + + if ((err = generic_cont_expand_simple(inode, size)) != 0) + return err; + + inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC; + mark_inode_dirty(inode); + + if (IS_SYNC(inode)) { + err = filemap_fdatawrite_range(mapping, start, start + count - 1); + err2 = sync_mapping_buffers(mapping); + err = (err)?(err):(err2); + err2 = write_inode_now(inode, 1); + err = (err)?(err):(err2); + if (!err) { + err = filemap_fdatawait_range(mapping, start, start + count - 1); + } + } + return err; +} + +static int exfat_allow_set_time(struct exfat_sb_info *sbi, struct inode *inode) +{ + mode_t allow_utime = sbi->options.allow_utime; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0) + if (!uid_eq(current_fsuid(), inode->i_uid)) +#else + if (current_fsuid() != inode->i_uid) +#endif + { + if (in_group_p(inode->i_gid)) + allow_utime >>= 3; + if (allow_utime & MAY_WRITE) + return 1; + } + + /* use a default check */ + return 0; +} + +static int exfat_sanitize_mode(const struct exfat_sb_info *sbi, + struct inode *inode, umode_t *mode_ptr) +{ + mode_t i_mode, mask, perm; + + i_mode = inode->i_mode; + + if (S_ISREG(i_mode) || S_ISLNK(i_mode)) + mask = sbi->options.fs_fmask; + else + mask = sbi->options.fs_dmask; + + perm = *mode_ptr & ~(S_IFMT | mask); + + /* Of the r and x bits, all (subject to umask) must be present.*/ + if ((perm & (S_IRUGO | S_IXUGO)) != (i_mode & (S_IRUGO|S_IXUGO))) + return -EPERM; + + if (exfat_mode_can_hold_ro(inode)) { + /* Of the w bits, either all (subject to umask) or none must be present. */ + if ((perm & S_IWUGO) && ((perm & S_IWUGO) != (S_IWUGO & ~mask))) + return -EPERM; + } else { + /* If exfat_mode_can_hold_ro(inode) is false, can't change w bits. */ + if ((perm & S_IWUGO) != (S_IWUGO & ~mask)) + return -EPERM; + } + + *mode_ptr &= S_IFMT | perm; + + return 0; +} + +static int exfat_setattr(struct dentry *dentry, struct iattr *attr) +{ + + struct exfat_sb_info *sbi = EXFAT_SB(dentry->d_sb); + struct inode *inode = dentry->d_inode; + unsigned int ia_valid; + int error; + loff_t old_size; + + PRINTK("exfat_setattr entered\n"); + + if ((attr->ia_valid & ATTR_SIZE) + && (attr->ia_size > i_size_read(inode))) { + error = exfat_cont_expand(inode, attr->ia_size); + if (error || attr->ia_valid == ATTR_SIZE) + return error; + attr->ia_valid &= ~ATTR_SIZE; + } + + ia_valid = attr->ia_valid; + + if ((ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET)) + && exfat_allow_set_time(sbi, inode)) { + attr->ia_valid &= ~(ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET); + } + + error = inode_change_ok(inode, attr); + attr->ia_valid = ia_valid; + if (error) { + return error; + } + + if (((attr->ia_valid & ATTR_UID) && +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0) + (!uid_eq(attr->ia_uid, sbi->options.fs_uid))) || + ((attr->ia_valid & ATTR_GID) && + (!gid_eq(attr->ia_gid, sbi->options.fs_gid))) || +#else + (attr->ia_uid != sbi->options.fs_uid)) || + ((attr->ia_valid & ATTR_GID) && + (attr->ia_gid != sbi->options.fs_gid)) || +#endif + ((attr->ia_valid & ATTR_MODE) && + (attr->ia_mode & ~(S_IFREG | S_IFLNK | S_IFDIR | S_IRWXUGO)))) { + return -EPERM; + } + + /* + * We don't return -EPERM here. Yes, strange, but this is too + * old behavior. + */ + if (attr->ia_valid & ATTR_MODE) { + if (exfat_sanitize_mode(sbi, inode, &attr->ia_mode) < 0) + attr->ia_valid &= ~ATTR_MODE; + } + + EXFAT_I(inode)->fid.size = i_size_read(inode); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) + if (attr->ia_valid) + error = inode_setattr(inode, attr); +#else + if (attr->ia_valid & ATTR_SIZE) { + old_size = i_size_read(inode); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,00) + down_write(&EXFAT_I(inode)->truncate_lock); + truncate_setsize(inode, attr->ia_size); + _exfat_truncate(inode, old_size); + up_write(&EXFAT_I(inode)->truncate_lock); +#else + truncate_setsize(inode, attr->ia_size); + _exfat_truncate(inode, old_size); +#endif + } + setattr_copy(inode, attr); + mark_inode_dirty(inode); +#endif + + PRINTK("exfat_setattr exited\n"); + return error; +} + +static int exfat_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) +{ + struct inode *inode = dentry->d_inode; + + PRINTK("exfat_getattr entered\n"); + + generic_fillattr(inode, stat); + stat->blksize = EXFAT_SB(inode->i_sb)->fs_info.cluster_size; + + PRINTK("exfat_getattr exited\n"); + return 0; +} + +const struct inode_operations exfat_dir_inode_operations = { + .create = exfat_create, + .lookup = exfat_lookup, + .unlink = exfat_unlink, + .symlink = exfat_symlink, + .mkdir = exfat_mkdir, + .rmdir = exfat_rmdir, + .rename = exfat_rename, + .setattr = exfat_setattr, + .getattr = exfat_getattr, +}; + +/*======================================================================*/ +/* File Operations */ +/*======================================================================*/ + +static void *exfat_follow_link(struct dentry *dentry, struct nameidata *nd) +{ + struct exfat_inode_info *ei = EXFAT_I(dentry->d_inode); + nd_set_link(nd, (char *)(ei->target)); + return NULL; +} + +const struct inode_operations exfat_symlink_inode_operations = { + .readlink = generic_readlink, + .follow_link = exfat_follow_link, +}; + +static int exfat_file_release(struct inode *inode, struct file *filp) +{ + struct super_block *sb = inode->i_sb; + + EXFAT_I(inode)->fid.size = i_size_read(inode); + FsSyncVol(sb, 0); + return 0; +} + +const struct file_operations exfat_file_operations = { + .llseek = generic_file_llseek, + .read = do_sync_read, + .write = do_sync_write, + .aio_read = generic_file_aio_read, + .aio_write = generic_file_aio_write, + .mmap = generic_file_mmap, + .release = exfat_file_release, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) + .ioctl = exfat_generic_ioctl, + .fsync = exfat_file_fsync, +#else + .unlocked_ioctl = exfat_generic_ioctl, + .fsync = generic_file_fsync, +#endif + .splice_read = generic_file_splice_read, +}; + +static void _exfat_truncate(struct inode *inode, loff_t old_size) +{ + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + FS_INFO_T *p_fs = &(sbi->fs_info); + int err; + + __lock_super(sb); + + /* + * This protects against truncating a file bigger than it was then + * trying to write into the hole. + */ + if (EXFAT_I(inode)->mmu_private > i_size_read(inode)) + EXFAT_I(inode)->mmu_private = i_size_read(inode); + + if (EXFAT_I(inode)->fid.start_clu == 0) goto out; + + err = FsTruncateFile(inode, old_size, i_size_read(inode)); + if (err) goto out; + + inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC; + if (IS_DIRSYNC(inode)) + (void) exfat_sync_inode(inode); + else + mark_inode_dirty(inode); + + inode->i_blocks = ((i_size_read(inode) + (p_fs->cluster_size - 1)) + & ~((loff_t)p_fs->cluster_size - 1)) >> 9; +out: + __unlock_super(sb); +} + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,36) +static void exfat_truncate(struct inode *inode) +{ + _exfat_truncate(inode, i_size_read(inode)); +} +#endif + +const struct inode_operations exfat_file_inode_operations = { +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,36) + .truncate = exfat_truncate, +#endif + .setattr = exfat_setattr, + .getattr = exfat_getattr, +}; + +/*======================================================================*/ +/* Address Space Operations */ +/*======================================================================*/ + +static int exfat_bmap(struct inode *inode, sector_t sector, sector_t *phys, + unsigned long *mapped_blocks, int *create) +{ + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + FS_INFO_T *p_fs = &(sbi->fs_info); + BD_INFO_T *p_bd = &(sbi->bd_info); + const unsigned long blocksize = sb->s_blocksize; + const unsigned char blocksize_bits = sb->s_blocksize_bits; + sector_t last_block; + int err, clu_offset, sec_offset; + unsigned int cluster; + + *phys = 0; + *mapped_blocks = 0; + + if ((p_fs->vol_type == FAT12) || (p_fs->vol_type == FAT16)) { + if (inode->i_ino == EXFAT_ROOT_INO) { + if (sector < (p_fs->dentries_in_root >> (p_bd->sector_size_bits-DENTRY_SIZE_BITS))) { + *phys = sector + p_fs->root_start_sector; + *mapped_blocks = 1; + } + return 0; + } + } + + last_block = (i_size_read(inode) + (blocksize - 1)) >> blocksize_bits; + if (sector >= last_block) { + if (*create == 0) return 0; + } else { + *create = 0; + } + + clu_offset = sector >> p_fs->sectors_per_clu_bits; /* cluster offset */ + sec_offset = sector & (p_fs->sectors_per_clu - 1); /* sector offset in cluster */ + + EXFAT_I(inode)->fid.size = i_size_read(inode); + + err = FsMapCluster(inode, clu_offset, &cluster); + + if (err) { + if (err == FFS_FULL) + return -ENOSPC; + else + return -EIO; + } else if (cluster != CLUSTER_32(~0)) { + *phys = START_SECTOR(cluster) + sec_offset; + *mapped_blocks = p_fs->sectors_per_clu - sec_offset; + } + + return 0; +} + +static int exfat_get_block(struct inode *inode, sector_t iblock, + struct buffer_head *bh_result, int create) +{ + struct super_block *sb = inode->i_sb; + unsigned long max_blocks = bh_result->b_size >> inode->i_blkbits; + int err; + unsigned long mapped_blocks; + sector_t phys; + + __lock_super(sb); + + err = exfat_bmap(inode, iblock, &phys, &mapped_blocks, &create); + if (err) { + __unlock_super(sb); + return err; + } + + if (phys) { + max_blocks = min(mapped_blocks, max_blocks); + if (create) { + EXFAT_I(inode)->mmu_private += max_blocks << sb->s_blocksize_bits; + set_buffer_new(bh_result); + } + map_bh(bh_result, sb, phys); + } + + bh_result->b_size = max_blocks << sb->s_blocksize_bits; + __unlock_super(sb); + + return 0; +} + +static int exfat_readpage(struct file *file, struct page *page) +{ + int ret; + ret = mpage_readpage(page, exfat_get_block); + return ret; +} + +static int exfat_readpages(struct file *file, struct address_space *mapping, + struct list_head *pages, unsigned nr_pages) +{ + int ret; + ret = mpage_readpages(mapping, pages, nr_pages, exfat_get_block); + return ret; +} + +static int exfat_writepage(struct page *page, struct writeback_control *wbc) +{ + int ret; + ret = block_write_full_page(page, exfat_get_block, wbc); + return ret; +} + +static int exfat_writepages(struct address_space *mapping, + struct writeback_control *wbc) +{ + int ret; + ret = mpage_writepages(mapping, wbc, exfat_get_block); + return ret; +} + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,34) +static void exfat_write_failed(struct address_space *mapping, loff_t to) +{ + struct inode *inode = mapping->host; + if (to > i_size_read(inode)) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,12,0) + truncate_pagecache(inode, i_size_read(inode)); +#else + truncate_pagecache(inode, to, i_size_read(inode)); +#endif + EXFAT_I(inode)->fid.size = i_size_read(inode); + _exfat_truncate(inode, i_size_read(inode)); + } +} +#endif + + +static int exfat_write_begin(struct file *file, struct address_space *mapping, + loff_t pos, unsigned len, unsigned flags, + struct page **pagep, void **fsdata) +{ + int ret; + *pagep = NULL; + ret = cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata, + exfat_get_block, + &EXFAT_I(mapping->host)->mmu_private); + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,34) + if (ret < 0) + exfat_write_failed(mapping, pos+len); +#endif + return ret; +} + +static int exfat_write_end(struct file *file, struct address_space *mapping, + loff_t pos, unsigned len, unsigned copied, + struct page *pagep, void *fsdata) +{ + struct inode *inode = mapping->host; + FILE_ID_T *fid = &(EXFAT_I(inode)->fid); + int err; + + err = generic_write_end(file, mapping, pos, len, copied, pagep, fsdata); + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,34) + if (err < len) + exfat_write_failed(mapping, pos+len); +#endif + + if (!(err < 0) && !(fid->attr & ATTR_ARCHIVE)) { + inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC; + fid->attr |= ATTR_ARCHIVE; + mark_inode_dirty(inode); + } + return err; +} + +static ssize_t exfat_direct_IO(int rw, struct kiocb *iocb, + const struct iovec *iov, + loff_t offset, unsigned long nr_segs) +{ + struct inode *inode = iocb->ki_filp->f_mapping->host; +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,34) + struct address_space *mapping = iocb->ki_filp->f_mapping; +#endif + ssize_t ret; + + if (rw == WRITE) { + if (EXFAT_I(inode)->mmu_private < (offset + iov_length(iov, nr_segs))) + return 0; + } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,00) + ret = blockdev_direct_IO(rw, iocb, inode, iov, + offset, nr_segs, exfat_get_block); +#else + ret = blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov, + offset, nr_segs, exfat_get_block, NULL); +#endif + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,34) + if ((ret < 0) && (rw & WRITE)) + exfat_write_failed(mapping, offset+iov_length(iov, nr_segs)); +#endif + return ret; +} + +static sector_t _exfat_bmap(struct address_space *mapping, sector_t block) +{ + sector_t blocknr; + + /* exfat_get_cluster() assumes the requested blocknr isn't truncated. */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,00) + down_read(&EXFAT_I(mapping->host)->truncate_lock); + blocknr = generic_block_bmap(mapping, block, exfat_get_block); + up_read(&EXFAT_I(mapping->host)->truncate_lock); +#else + down_read(&EXFAT_I(mapping->host)->i_alloc_sem); + blocknr = generic_block_bmap(mapping, block, exfat_get_block); + up_read(&EXFAT_I(mapping->host)->i_alloc_sem); +#endif + + return blocknr; +} + +const struct address_space_operations exfat_aops = { + .readpage = exfat_readpage, + .readpages = exfat_readpages, + .writepage = exfat_writepage, + .writepages = exfat_writepages, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39) + .sync_page = block_sync_page, +#endif + .write_begin = exfat_write_begin, + .write_end = exfat_write_end, + .direct_IO = exfat_direct_IO, + .bmap = _exfat_bmap +}; + +/*======================================================================*/ +/* Super Operations */ +/*======================================================================*/ + +static inline unsigned long exfat_hash(loff_t i_pos) +{ + return hash_32(i_pos, EXFAT_HASH_BITS); +} + +static struct inode *exfat_iget(struct super_block *sb, loff_t i_pos) { + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct exfat_inode_info *info; + struct hlist_head *head = sbi->inode_hashtable + exfat_hash(i_pos); + struct inode *inode = NULL; +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,9,0) + struct hlist_node *node; + + spin_lock(&sbi->inode_hash_lock); + hlist_for_each_entry(info, node, head, i_hash_fat) { +#else + spin_lock(&sbi->inode_hash_lock); + hlist_for_each_entry(info, head, i_hash_fat) { +#endif + CHECK_ERR(info->vfs_inode.i_sb != sb); + + if (i_pos != info->i_pos) + continue; + inode = igrab(&info->vfs_inode); + if (inode) + break; + } + spin_unlock(&sbi->inode_hash_lock); + return inode; +} + +static void exfat_attach(struct inode *inode, loff_t i_pos) +{ + struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb); + struct hlist_head *head = sbi->inode_hashtable + exfat_hash(i_pos); + + spin_lock(&sbi->inode_hash_lock); + EXFAT_I(inode)->i_pos = i_pos; + hlist_add_head(&EXFAT_I(inode)->i_hash_fat, head); + spin_unlock(&sbi->inode_hash_lock); +} + +static void exfat_detach(struct inode *inode) +{ + struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb); + + spin_lock(&sbi->inode_hash_lock); + hlist_del_init(&EXFAT_I(inode)->i_hash_fat); + EXFAT_I(inode)->i_pos = 0; + spin_unlock(&sbi->inode_hash_lock); +} + +/* doesn't deal with root inode */ +static int exfat_fill_inode(struct inode *inode, FILE_ID_T *fid) +{ + struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb); + FS_INFO_T *p_fs = &(sbi->fs_info); + DIR_ENTRY_T info; + + memcpy(&(EXFAT_I(inode)->fid), fid, sizeof(FILE_ID_T)); + + FsReadStat(inode, &info); + + EXFAT_I(inode)->i_pos = 0; + EXFAT_I(inode)->target = NULL; + inode->i_uid = sbi->options.fs_uid; + inode->i_gid = sbi->options.fs_gid; + inode->i_version++; + inode->i_generation = get_seconds(); + + if (info.Attr & ATTR_SUBDIR) { /* directory */ + inode->i_generation &= ~1; + inode->i_mode = exfat_make_mode(sbi, info.Attr, S_IRWXUGO); + inode->i_op = &exfat_dir_inode_operations; + inode->i_fop = &exfat_dir_operations; + + i_size_write(inode, info.Size); + EXFAT_I(inode)->mmu_private = i_size_read(inode); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,00) + set_nlink(inode,info.NumSubdirs); +#else + inode->i_nlink = info.NumSubdirs; +#endif + } else if (info.Attr & ATTR_SYMLINK) { /* symbolic link */ + inode->i_generation |= 1; + inode->i_mode = exfat_make_mode(sbi, info.Attr, S_IRWXUGO); + inode->i_op = &exfat_symlink_inode_operations; + + i_size_write(inode, info.Size); + EXFAT_I(inode)->mmu_private = i_size_read(inode); + } else { /* regular file */ + inode->i_generation |= 1; + inode->i_mode = exfat_make_mode(sbi, info.Attr, S_IRWXUGO); + inode->i_op = &exfat_file_inode_operations; + inode->i_fop = &exfat_file_operations; + inode->i_mapping->a_ops = &exfat_aops; + inode->i_mapping->nrpages = 0; + + i_size_write(inode, info.Size); + EXFAT_I(inode)->mmu_private = i_size_read(inode); + } + exfat_save_attr(inode, info.Attr); + + inode->i_blocks = ((i_size_read(inode) + (p_fs->cluster_size - 1)) + & ~((loff_t)p_fs->cluster_size - 1)) >> 9; + + exfat_time_fat2unix(sbi, &inode->i_mtime, &info.ModifyTimestamp); + exfat_time_fat2unix(sbi, &inode->i_ctime, &info.CreateTimestamp); + exfat_time_fat2unix(sbi, &inode->i_atime, &info.AccessTimestamp); + + return 0; +} + +static struct inode *exfat_build_inode(struct super_block *sb, + FILE_ID_T *fid, loff_t i_pos) { + struct inode *inode; + int err; + + inode = exfat_iget(sb, i_pos); + if (inode) + goto out; + inode = new_inode(sb); + if (!inode) { + inode = ERR_PTR(-ENOMEM); + goto out; + } + inode->i_ino = iunique(sb, EXFAT_ROOT_INO); + inode->i_version = 1; + err = exfat_fill_inode(inode, fid); + if (err) { + iput(inode); + inode = ERR_PTR(err); + goto out; + } + exfat_attach(inode, i_pos); + insert_inode_hash(inode); +out: + return inode; +} + +static int exfat_sync_inode(struct inode *inode) +{ + return exfat_write_inode(inode, NULL); +} + +static struct inode *exfat_alloc_inode(struct super_block *sb) { + struct exfat_inode_info *ei; + + ei = kmem_cache_alloc(exfat_inode_cachep, GFP_NOFS); + if (!ei) + return NULL; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,00) + init_rwsem(&ei->truncate_lock); +#endif + + return &ei->vfs_inode; +} + +static void exfat_destroy_inode(struct inode *inode) +{ + FREE(EXFAT_I(inode)->target); + EXFAT_I(inode)->target = NULL; + + kmem_cache_free(exfat_inode_cachep, EXFAT_I(inode)); +} + +static int exfat_write_inode(struct inode *inode, struct writeback_control *wbc) +{ + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + DIR_ENTRY_T info; + + if (inode->i_ino == EXFAT_ROOT_INO) + return 0; + + info.Attr = exfat_make_attr(inode); + info.Size = i_size_read(inode); + + exfat_time_unix2fat(sbi, &inode->i_mtime, &info.ModifyTimestamp); + exfat_time_unix2fat(sbi, &inode->i_ctime, &info.CreateTimestamp); + exfat_time_unix2fat(sbi, &inode->i_atime, &info.AccessTimestamp); + + FsWriteStat(inode, &info); + + return 0; +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) +static void exfat_delete_inode(struct inode *inode) +{ + truncate_inode_pages(&inode->i_data, 0); + clear_inode(inode); +} + +static void exfat_clear_inode(struct inode *inode) +{ + exfat_detach(inode); + remove_inode_hash(inode); +} +#else +static void exfat_evict_inode(struct inode *inode) +{ + truncate_inode_pages(&inode->i_data, 0); + + if (!inode->i_nlink) + i_size_write(inode, 0); + invalidate_inode_buffers(inode); +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,00) + end_writeback(inode); +#else + clear_inode(inode); +#endif + exfat_detach(inode); + + remove_inode_hash(inode); +} +#endif + +static void exfat_free_super(struct exfat_sb_info *sbi) +{ + if (sbi->nls_disk) + unload_nls(sbi->nls_disk); + if (sbi->nls_io) + unload_nls(sbi->nls_io); + if (sbi->options.iocharset != exfat_default_iocharset) + kfree(sbi->options.iocharset); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) + /* mutex_init is in exfat_fill_super function. only for 3.7+ */ + mutex_destroy(&sbi->s_lock); +#endif + kfree(sbi); +} + +static void exfat_put_super(struct super_block *sb) +{ + struct exfat_sb_info *sbi = EXFAT_SB(sb); + if (__is_sb_dirty(sb)) + exfat_write_super(sb); + + FsUmountVol(sb); + + sb->s_fs_info = NULL; + exfat_free_super(sbi); +} + +static void exfat_write_super(struct super_block *sb) +{ + __lock_super(sb); + + __set_sb_clean(sb); + + if (!(sb->s_flags & MS_RDONLY)) + FsSyncVol(sb, 1); + + __unlock_super(sb); +} + +static int exfat_sync_fs(struct super_block *sb, int wait) +{ + int err = 0; + + if (__is_sb_dirty(sb)) { + __lock_super(sb); + __set_sb_clean(sb); + err = FsSyncVol(sb, 1); + __unlock_super(sb); + } + + return err; +} + +static int exfat_statfs(struct dentry *dentry, struct kstatfs *buf) +{ + struct super_block *sb = dentry->d_sb; + u64 id = huge_encode_dev(sb->s_bdev->bd_dev); + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + VOL_INFO_T info; + + if (p_fs->used_clusters == (UINT32) ~0) { + if (FFS_MEDIAERR == FsGetVolInfo(sb, &info)) + return -EIO; + + } else { + info.FatType = p_fs->vol_type; + info.ClusterSize = p_fs->cluster_size; + info.NumClusters = p_fs->num_clusters - 2; + info.UsedClusters = p_fs->used_clusters; + info.FreeClusters = info.NumClusters - info.UsedClusters; + + if (p_fs->dev_ejected) + return -EIO; + } + + buf->f_type = sb->s_magic; + buf->f_bsize = info.ClusterSize; + buf->f_blocks = info.NumClusters; + buf->f_bfree = info.FreeClusters; + buf->f_bavail = info.FreeClusters; + buf->f_fsid.val[0] = (u32)id; + buf->f_fsid.val[1] = (u32)(id >> 32); + buf->f_namelen = 260; + + return 0; +} + +static int exfat_remount(struct super_block *sb, int *flags, char *data) +{ + *flags |= MS_NODIRATIME; + return 0; +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,00) +static int exfat_show_options(struct seq_file *m, struct dentry *root) +{ + struct exfat_sb_info *sbi = EXFAT_SB(root->d_sb); +#else +static int exfat_show_options(struct seq_file *m, struct vfsmount *mnt) +{ + struct exfat_sb_info *sbi = EXFAT_SB(mnt->mnt_sb); +#endif + struct exfat_mount_options *opts = &sbi->options; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0) + if (__kuid_val(opts->fs_uid)) + seq_printf(m, ",uid=%u", __kuid_val(opts->fs_uid)); + if (__kgid_val(opts->fs_gid)) + seq_printf(m, ",gid=%u", __kgid_val(opts->fs_gid)); +#else + if (opts->fs_uid != 0) + seq_printf(m, ",uid=%u", opts->fs_uid); + if (opts->fs_gid != 0) + seq_printf(m, ",gid=%u", opts->fs_gid); +#endif + seq_printf(m, ",fmask=%04o", opts->fs_fmask); + seq_printf(m, ",dmask=%04o", opts->fs_dmask); + if (opts->allow_utime) + seq_printf(m, ",allow_utime=%04o", opts->allow_utime); + if (sbi->nls_disk) + seq_printf(m, ",codepage=%s", sbi->nls_disk->charset); + if (sbi->nls_io) + seq_printf(m, ",iocharset=%s", sbi->nls_io->charset); + seq_printf(m, ",namecase=%u", opts->casesensitive); + if (opts->errors == EXFAT_ERRORS_CONT) + seq_puts(m, ",errors=continue"); + else if (opts->errors == EXFAT_ERRORS_PANIC) + seq_puts(m, ",errors=panic"); + else + seq_puts(m, ",errors=remount-ro"); +#if EXFAT_CONFIG_DISCARD + if (opts->discard) + seq_printf(m, ",discard"); +#endif + return 0; +} + +const struct super_operations exfat_sops = { + .alloc_inode = exfat_alloc_inode, + .destroy_inode = exfat_destroy_inode, + .write_inode = exfat_write_inode, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) + .delete_inode = exfat_delete_inode, + .clear_inode = exfat_clear_inode, +#else + .evict_inode = exfat_evict_inode, +#endif + .put_super = exfat_put_super, +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0) + .write_super = exfat_write_super, +#endif + .sync_fs = exfat_sync_fs, + .statfs = exfat_statfs, + .remount_fs = exfat_remount, + .show_options = exfat_show_options, +}; + +/*======================================================================*/ +/* Super Block Read Operations */ +/*======================================================================*/ + +enum { + Opt_uid, + Opt_gid, + Opt_umask, + Opt_dmask, + Opt_fmask, + Opt_allow_utime, + Opt_codepage, + Opt_charset, + Opt_namecase, + Opt_debug, + Opt_err_cont, + Opt_err_panic, + Opt_err_ro, + Opt_err, +#if EXFAT_CONFIG_DISCARD + Opt_discard, +#endif /* EXFAT_CONFIG_DISCARD */ +}; + +static const match_table_t exfat_tokens = { + {Opt_uid, "uid=%u"}, + {Opt_gid, "gid=%u"}, + {Opt_umask, "umask=%o"}, + {Opt_dmask, "dmask=%o"}, + {Opt_fmask, "fmask=%o"}, + {Opt_allow_utime, "allow_utime=%o"}, + {Opt_codepage, "codepage=%u"}, + {Opt_charset, "iocharset=%s"}, + {Opt_namecase, "namecase=%u"}, + {Opt_debug, "debug"}, + {Opt_err_cont, "errors=continue"}, + {Opt_err_panic, "errors=panic"}, + {Opt_err_ro, "errors=remount-ro"}, +#if EXFAT_CONFIG_DISCARD + {Opt_discard, "discard"}, +#endif /* EXFAT_CONFIG_DISCARD */ + {Opt_err, NULL} +}; + +static int parse_options(char *options, int silent, int *debug, + struct exfat_mount_options *opts) +{ + char *p; + substring_t args[MAX_OPT_ARGS]; + int option; + char *iocharset; + + opts->fs_uid = current_uid(); + opts->fs_gid = current_gid(); + opts->fs_fmask = opts->fs_dmask = current->fs->umask; + opts->allow_utime = (unsigned short) -1; + opts->codepage = exfat_default_codepage; + opts->iocharset = exfat_default_iocharset; + opts->casesensitive = 0; + opts->errors = EXFAT_ERRORS_RO; +#if EXFAT_CONFIG_DISCARD + opts->discard = 0; +#endif + *debug = 0; + + if (!options) + goto out; + + while ((p = strsep(&options, ",")) != NULL) { + int token; + if (!*p) + continue; + + token = match_token(p, exfat_tokens, args); + switch (token) { + case Opt_uid: + if (match_int(&args[0], &option)) + return 0; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0) + opts->fs_uid = KUIDT_INIT(option); +#else + opts->fs_uid = option; +#endif + break; + case Opt_gid: + if (match_int(&args[0], &option)) + return 0; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0) + opts->fs_gid = KGIDT_INIT(option); +#else + opts->fs_gid = option; +#endif + break; + case Opt_umask: + case Opt_dmask: + case Opt_fmask: + if (match_octal(&args[0], &option)) + return 0; + if (token != Opt_dmask) + opts->fs_fmask = option; + if (token != Opt_fmask) + opts->fs_dmask = option; + break; + case Opt_allow_utime: + if (match_octal(&args[0], &option)) + return 0; + opts->allow_utime = option & (S_IWGRP | S_IWOTH); + break; + case Opt_codepage: + if (match_int(&args[0], &option)) + return 0; + opts->codepage = option; + break; + case Opt_charset: + if (opts->iocharset != exfat_default_iocharset) + kfree(opts->iocharset); + iocharset = match_strdup(&args[0]); + if (!iocharset) + return -ENOMEM; + opts->iocharset = iocharset; + break; + case Opt_namecase: + if (match_int(&args[0], &option)) + return 0; + opts->casesensitive = option; + break; + case Opt_err_cont: + opts->errors = EXFAT_ERRORS_CONT; + break; + case Opt_err_panic: + opts->errors = EXFAT_ERRORS_PANIC; + break; + case Opt_err_ro: + opts->errors = EXFAT_ERRORS_RO; + break; + case Opt_debug: + *debug = 1; + break; +#if EXFAT_CONFIG_DISCARD + case Opt_discard: + opts->discard = 1; + break; +#endif /* EXFAT_CONFIG_DISCARD */ + default: + if (!silent) { + printk(KERN_ERR "[EXFAT] Unrecognized mount option %s or missing value\n", p); + } + return -EINVAL; + } + } + +out: + if (opts->allow_utime == (unsigned short) -1) + opts->allow_utime = ~opts->fs_dmask & (S_IWGRP | S_IWOTH); + + return 0; +} + +static void exfat_hash_init(struct super_block *sb) +{ + struct exfat_sb_info *sbi = EXFAT_SB(sb); + int i; + + spin_lock_init(&sbi->inode_hash_lock); + for (i = 0; i < EXFAT_HASH_SIZE; i++) + INIT_HLIST_HEAD(&sbi->inode_hashtable[i]); +} + +static int exfat_read_root(struct inode *inode) +{ + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct timespec ts; + FS_INFO_T *p_fs = &(sbi->fs_info); + DIR_ENTRY_T info; + + ts = CURRENT_TIME_SEC; + + EXFAT_I(inode)->fid.dir.dir = p_fs->root_dir; + EXFAT_I(inode)->fid.dir.flags = 0x01; + EXFAT_I(inode)->fid.entry = -1; + EXFAT_I(inode)->fid.start_clu = p_fs->root_dir; + EXFAT_I(inode)->fid.flags = 0x01; + EXFAT_I(inode)->fid.type = TYPE_DIR; + EXFAT_I(inode)->fid.rwoffset = 0; + EXFAT_I(inode)->fid.hint_last_off = -1; + + EXFAT_I(inode)->target = NULL; + + FsReadStat(inode, &info); + + inode->i_uid = sbi->options.fs_uid; + inode->i_gid = sbi->options.fs_gid; + inode->i_version++; + inode->i_generation = 0; + inode->i_mode = exfat_make_mode(sbi, ATTR_SUBDIR, S_IRWXUGO); + inode->i_op = &exfat_dir_inode_operations; + inode->i_fop = &exfat_dir_operations; + + i_size_write(inode, info.Size); + inode->i_blocks = ((i_size_read(inode) + (p_fs->cluster_size - 1)) + & ~((loff_t)p_fs->cluster_size - 1)) >> 9; + EXFAT_I(inode)->i_pos = ((loff_t) p_fs->root_dir << 32) | 0xffffffff; + EXFAT_I(inode)->mmu_private = i_size_read(inode); + + exfat_save_attr(inode, ATTR_SUBDIR); + inode->i_mtime = inode->i_atime = inode->i_ctime = ts; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,00) + set_nlink(inode,info.NumSubdirs + 2); +#else + inode->i_nlink = info.NumSubdirs + 2; +#endif + + return 0; +} + +static int exfat_fill_super(struct super_block *sb, void *data, int silent) +{ + struct inode *root_inode = NULL; + struct exfat_sb_info *sbi; + int debug, ret; + long error; + char buf[50]; + + /* + * GFP_KERNEL is ok here, because while we do hold the + * supeblock lock, memory pressure can't call back into + * the filesystem, since we're only just about to mount + * it and have no inodes etc active! + */ + sbi = kzalloc(sizeof(struct exfat_sb_info), GFP_KERNEL); + if (!sbi) + return -ENOMEM; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) + mutex_init(&sbi->s_lock); +#endif + sb->s_fs_info = sbi; + + sb->s_flags |= MS_NODIRATIME; + sb->s_magic = EXFAT_SUPER_MAGIC; + sb->s_op = &exfat_sops; + + error = parse_options(data, silent, &debug, &sbi->options); + if (error) + goto out_fail; + + error = -EIO; + sb_min_blocksize(sb, 512); + sb->s_maxbytes = 0x7fffffffffffffffLL; // maximum file size + + ret = FsMountVol(sb); + if (ret) { + if (!silent) + printk(KERN_ERR "[EXFAT] FsMountVol failed\n"); + + goto out_fail; + } + + /* set up enough so that it can read an inode */ + exfat_hash_init(sb); + + /* + * The low byte of FAT's first entry must have same value with + * media-field. But in real world, too many devices is + * writing wrong value. So, removed that validity check. + * + * if (FAT_FIRST_ENT(sb, media) != first) + */ + + if (sbi->fs_info.vol_type != EXFAT) { + error = -EINVAL; + sprintf(buf, "cp%d", sbi->options.codepage); + sbi->nls_disk = load_nls(buf); + if (!sbi->nls_disk) { + printk(KERN_ERR "[EXFAT] Codepage %s not found\n", buf); + goto out_fail2; + } + } + + sbi->nls_io = load_nls(sbi->options.iocharset); + if (!sbi->nls_io) { + printk(KERN_ERR "[EXFAT] IO charset %s not found\n", + sbi->options.iocharset); + goto out_fail2; + } + + error = -ENOMEM; + root_inode = new_inode(sb); + if (!root_inode) + goto out_fail2; + root_inode->i_ino = EXFAT_ROOT_INO; + root_inode->i_version = 1; + error = exfat_read_root(root_inode); + if (error < 0) + goto out_fail2; + error = -ENOMEM; + exfat_attach(root_inode, EXFAT_I(root_inode)->i_pos); + insert_inode_hash(root_inode); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,00) + sb->s_root = d_make_root(root_inode); +#else + sb->s_root = d_alloc_root(root_inode); +#endif + if (!sb->s_root) { + printk(KERN_ERR "[EXFAT] Getting the root inode failed\n"); + goto out_fail2; + } + + return 0; + +out_fail2: + FsUmountVol(sb); +out_fail: + if (root_inode) + iput(root_inode); + sb->s_fs_info = NULL; + exfat_free_super(sbi); + return error; +} +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) +static int exfat_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, + void *data, struct vfsmount *mnt) +{ + return get_sb_bdev(fs_type, flags, dev_name, data, exfat_fill_super, mnt); +} +#else +static struct dentry *exfat_fs_mount(struct file_system_type *fs_type, + int flags, const char *dev_name, + void *data) { + return mount_bdev(fs_type, flags, dev_name, data, exfat_fill_super); +} +#endif + +static void init_once(void *foo) +{ + struct exfat_inode_info *ei = (struct exfat_inode_info *)foo; + + INIT_HLIST_NODE(&ei->i_hash_fat); + inode_init_once(&ei->vfs_inode); +} + +static int __init exfat_init_inodecache(void) +{ + exfat_inode_cachep = kmem_cache_create("exfat_inode_cache", + sizeof(struct exfat_inode_info), + 0, (SLAB_RECLAIM_ACCOUNT| + SLAB_MEM_SPREAD), + init_once); + if (exfat_inode_cachep == NULL) + return -ENOMEM; + return 0; +} + +static void __exit exfat_destroy_inodecache(void) +{ + kmem_cache_destroy(exfat_inode_cachep); +} + +#if EXFAT_CONFIG_KERNEL_DEBUG +static void exfat_debug_kill_sb(struct super_block *sb) +{ + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct block_device *bdev = sb->s_bdev; + + long flags; + + if (sbi) { + flags = sbi->debug_flags; + + if (flags & EXFAT_DEBUGFLAGS_INVALID_UMOUNT) { + /* invalidate_bdev drops all device cache include dirty. + we use this to simulate device removal */ + FsReleaseCache(sb); + invalidate_bdev(bdev); + } + } + + kill_block_super(sb); +} +#endif /* EXFAT_CONFIG_KERNEL_DEBUG */ + +static struct file_system_type exfat_fs_type = { + .owner = THIS_MODULE, + .name = "exfat", +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) + .get_sb = exfat_get_sb, +#else + .mount = exfat_fs_mount, +#endif +#if EXFAT_CONFIG_KERNEL_DEBUG + .kill_sb = exfat_debug_kill_sb, +#else + .kill_sb = kill_block_super, +#endif /* EXFAT_CONFIG_KERNLE_DEBUG */ + .fs_flags = FS_REQUIRES_DEV, +}; + +static int __init init_exfat(void) +{ + int err; + + err = FsInit(); + if (err) { + if (err == FFS_MEMORYERR) + return -ENOMEM; + else + return -EIO; + } + + printk(KERN_INFO "exFAT: Version %s\n", EXFAT_VERSION); + + err = exfat_init_inodecache(); + if (err) goto out; + + err = register_filesystem(&exfat_fs_type); + if (err) goto out; + + return 0; +out: + FsShutdown(); + return err; +} + +static void __exit exit_exfat(void) +{ + exfat_destroy_inodecache(); + unregister_filesystem(&exfat_fs_type); + FsShutdown(); +} + +module_init(init_exfat); +module_exit(exit_exfat); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("exFAT Filesystem Driver"); +#ifdef MODULE_ALIAS_FS +MODULE_ALIAS_FS("exfat"); +#endif diff --git a/fs/exfat/exfat_super.h b/fs/exfat/exfat_super.h new file mode 100644 index 00000000000..c9201dd7925 --- /dev/null +++ b/fs/exfat/exfat_super.h @@ -0,0 +1,172 @@ +/* Some of the source code in this file came from "linux/fs/fat/fat.h". */ + +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _EXFAT_LINUX_H +#define _EXFAT_LINUX_H + +#include +#include +#include +#include +#include +#include + +#include "exfat_config.h" +#include "exfat_global.h" +#include "exfat_data.h" +#include "exfat_oal.h" + +#include "exfat_blkdev.h" +#include "exfat_cache.h" +#include "exfat_part.h" +#include "exfat_nls.h" +#include "exfat_api.h" +#include "exfat.h" + +#define EXFAT_ERRORS_CONT 1 /* ignore error and continue */ +#define EXFAT_ERRORS_PANIC 2 /* panic on error */ +#define EXFAT_ERRORS_RO 3 /* remount r/o on error */ + +/* ioctl command */ +#define EXFAT_IOCTL_GET_VOLUME_ID _IOR('r', 0x12, __u32) + +struct exfat_mount_options { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0) + kuid_t fs_uid; + kgid_t fs_gid; +#else + uid_t fs_uid; + gid_t fs_gid; +#endif + unsigned short fs_fmask; + unsigned short fs_dmask; + unsigned short allow_utime; /* permission for setting the [am]time */ + unsigned short codepage; /* codepage for shortname conversions */ + char *iocharset; /* charset for filename input/display */ + unsigned char casesensitive; + unsigned char errors; /* on error: continue, panic, remount-ro */ +#if EXFAT_CONFIG_DISCARD + unsigned char discard; /* flag on if -o dicard specified and device support discard() */ +#endif /* EXFAT_CONFIG_DISCARD */ +}; + +#define EXFAT_HASH_BITS 8 +#define EXFAT_HASH_SIZE (1UL << EXFAT_HASH_BITS) + +/* + * EXFAT file system in-core superblock data + */ +struct exfat_sb_info { + FS_INFO_T fs_info; + BD_INFO_T bd_info; + + struct exfat_mount_options options; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,00) + int s_dirt; + struct mutex s_lock; +#endif + struct nls_table *nls_disk; /* Codepage used on disk */ + struct nls_table *nls_io; /* Charset used for input and display */ + + struct inode *fat_inode; + + spinlock_t inode_hash_lock; + struct hlist_head inode_hashtable[EXFAT_HASH_SIZE]; +#if EXFAT_CONFIG_KERNEL_DEBUG + long debug_flags; +#endif /* EXFAT_CONFIG_KERNEL_DEBUG */ +}; + +/* + * EXFAT file system inode data in memory + */ +struct exfat_inode_info { + FILE_ID_T fid; + char *target; + /* NOTE: mmu_private is 64bits, so must hold ->i_mutex to access */ + loff_t mmu_private; /* physically allocated size */ + loff_t i_pos; /* on-disk position of directory entry or 0 */ + struct hlist_node i_hash_fat; /* hash by i_location */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,00) + struct rw_semaphore truncate_lock; +#endif + struct inode vfs_inode; + struct rw_semaphore i_alloc_sem; /* protect bmap against truncate */ +}; + +#define EXFAT_SB(sb) ((struct exfat_sb_info *)((sb)->s_fs_info)) + +static inline struct exfat_inode_info *EXFAT_I(struct inode *inode) { + return container_of(inode, struct exfat_inode_info, vfs_inode); +} + +/* + * If ->i_mode can't hold S_IWUGO (i.e. ATTR_RO), we use ->i_attrs to + * save ATTR_RO instead of ->i_mode. + * + * If it's directory and !sbi->options.rodir, ATTR_RO isn't read-only + * bit, it's just used as flag for app. + */ +static inline int exfat_mode_can_hold_ro(struct inode *inode) +{ + struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb); + + if (S_ISDIR(inode->i_mode)) + return 0; + + if ((~sbi->options.fs_fmask) & S_IWUGO) + return 1; + return 0; +} + +/* Convert attribute bits and a mask to the UNIX mode. */ +static inline mode_t exfat_make_mode(struct exfat_sb_info *sbi, + u32 attr, mode_t mode) +{ + if ((attr & ATTR_READONLY) && !(attr & ATTR_SUBDIR)) + mode &= ~S_IWUGO; + + if (attr & ATTR_SUBDIR) + return (mode & ~sbi->options.fs_dmask) | S_IFDIR; + else if (attr & ATTR_SYMLINK) + return (mode & ~sbi->options.fs_dmask) | S_IFLNK; + else + return (mode & ~sbi->options.fs_fmask) | S_IFREG; +} + +/* Return the FAT attribute byte for this inode */ +static inline u32 exfat_make_attr(struct inode *inode) +{ + if (exfat_mode_can_hold_ro(inode) && !(inode->i_mode & S_IWUGO)) + return ((EXFAT_I(inode)->fid.attr) | ATTR_READONLY); + else + return (EXFAT_I(inode)->fid.attr); +} + +static inline void exfat_save_attr(struct inode *inode, u32 attr) +{ + if (exfat_mode_can_hold_ro(inode)) + EXFAT_I(inode)->fid.attr = attr & ATTR_RWMASK; + else + EXFAT_I(inode)->fid.attr = attr & (ATTR_RWMASK | ATTR_READONLY); +} + +#endif /* _EXFAT_LINUX_H */ diff --git a/fs/exfat/exfat_upcase.c b/fs/exfat/exfat_upcase.c new file mode 100644 index 00000000000..10e48d28b29 --- /dev/null +++ b/fs/exfat/exfat_upcase.c @@ -0,0 +1,408 @@ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * 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. + */ + +/************************************************************************/ +/* */ +/* PROJECT : exFAT & FAT12/16/32 File System */ +/* FILE : exfat_upcase.c */ +/* PURPOSE : exFAT Up-case Table */ +/* */ +/*----------------------------------------------------------------------*/ +/* NOTES */ +/* */ +/*----------------------------------------------------------------------*/ +/* REVISION HISTORY (Ver 0.9) */ +/* */ +/* - 2010.11.15 [Joosun Hahn] : first writing */ +/* */ +/************************************************************************/ + +#include "exfat_config.h" +#include "exfat_global.h" + +#include "exfat_nls.h" + +UINT8 uni_upcase[NUM_UPCASE<<1] = { + 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, + 0x08, 0x00, 0x09, 0x00, 0x0A, 0x00, 0x0B, 0x00, 0x0C, 0x00, 0x0D, 0x00, 0x0E, 0x00, 0x0F, 0x00, + 0x10, 0x00, 0x11, 0x00, 0x12, 0x00, 0x13, 0x00, 0x14, 0x00, 0x15, 0x00, 0x16, 0x00, 0x17, 0x00, + 0x18, 0x00, 0x19, 0x00, 0x1A, 0x00, 0x1B, 0x00, 0x1C, 0x00, 0x1D, 0x00, 0x1E, 0x00, 0x1F, 0x00, + 0x20, 0x00, 0x21, 0x00, 0x22, 0x00, 0x23, 0x00, 0x24, 0x00, 0x25, 0x00, 0x26, 0x00, 0x27, 0x00, + 0x28, 0x00, 0x29, 0x00, 0x2A, 0x00, 0x2B, 0x00, 0x2C, 0x00, 0x2D, 0x00, 0x2E, 0x00, 0x2F, 0x00, + 0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00, 0x36, 0x00, 0x37, 0x00, + 0x38, 0x00, 0x39, 0x00, 0x3A, 0x00, 0x3B, 0x00, 0x3C, 0x00, 0x3D, 0x00, 0x3E, 0x00, 0x3F, 0x00, + 0x40, 0x00, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, 0x44, 0x00, 0x45, 0x00, 0x46, 0x00, 0x47, 0x00, + 0x48, 0x00, 0x49, 0x00, 0x4A, 0x00, 0x4B, 0x00, 0x4C, 0x00, 0x4D, 0x00, 0x4E, 0x00, 0x4F, 0x00, + 0x50, 0x00, 0x51, 0x00, 0x52, 0x00, 0x53, 0x00, 0x54, 0x00, 0x55, 0x00, 0x56, 0x00, 0x57, 0x00, + 0x58, 0x00, 0x59, 0x00, 0x5A, 0x00, 0x5B, 0x00, 0x5C, 0x00, 0x5D, 0x00, 0x5E, 0x00, 0x5F, 0x00, + 0x60, 0x00, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, 0x44, 0x00, 0x45, 0x00, 0x46, 0x00, 0x47, 0x00, + 0x48, 0x00, 0x49, 0x00, 0x4A, 0x00, 0x4B, 0x00, 0x4C, 0x00, 0x4D, 0x00, 0x4E, 0x00, 0x4F, 0x00, + 0x50, 0x00, 0x51, 0x00, 0x52, 0x00, 0x53, 0x00, 0x54, 0x00, 0x55, 0x00, 0x56, 0x00, 0x57, 0x00, + 0x58, 0x00, 0x59, 0x00, 0x5A, 0x00, 0x7B, 0x00, 0x7C, 0x00, 0x7D, 0x00, 0x7E, 0x00, 0x7F, 0x00, + 0x80, 0x00, 0x81, 0x00, 0x82, 0x00, 0x83, 0x00, 0x84, 0x00, 0x85, 0x00, 0x86, 0x00, 0x87, 0x00, + 0x88, 0x00, 0x89, 0x00, 0x8A, 0x00, 0x8B, 0x00, 0x8C, 0x00, 0x8D, 0x00, 0x8E, 0x00, 0x8F, 0x00, + 0x90, 0x00, 0x91, 0x00, 0x92, 0x00, 0x93, 0x00, 0x94, 0x00, 0x95, 0x00, 0x96, 0x00, 0x97, 0x00, + 0x98, 0x00, 0x99, 0x00, 0x9A, 0x00, 0x9B, 0x00, 0x9C, 0x00, 0x9D, 0x00, 0x9E, 0x00, 0x9F, 0x00, + 0xA0, 0x00, 0xA1, 0x00, 0xA2, 0x00, 0xA3, 0x00, 0xA4, 0x00, 0xA5, 0x00, 0xA6, 0x00, 0xA7, 0x00, + 0xA8, 0x00, 0xA9, 0x00, 0xAA, 0x00, 0xAB, 0x00, 0xAC, 0x00, 0xAD, 0x00, 0xAE, 0x00, 0xAF, 0x00, + 0xB0, 0x00, 0xB1, 0x00, 0xB2, 0x00, 0xB3, 0x00, 0xB4, 0x00, 0xB5, 0x00, 0xB6, 0x00, 0xB7, 0x00, + 0xB8, 0x00, 0xB9, 0x00, 0xBA, 0x00, 0xBB, 0x00, 0xBC, 0x00, 0xBD, 0x00, 0xBE, 0x00, 0xBF, 0x00, + 0xC0, 0x00, 0xC1, 0x00, 0xC2, 0x00, 0xC3, 0x00, 0xC4, 0x00, 0xC5, 0x00, 0xC6, 0x00, 0xC7, 0x00, + 0xC8, 0x00, 0xC9, 0x00, 0xCA, 0x00, 0xCB, 0x00, 0xCC, 0x00, 0xCD, 0x00, 0xCE, 0x00, 0xCF, 0x00, + 0xD0, 0x00, 0xD1, 0x00, 0xD2, 0x00, 0xD3, 0x00, 0xD4, 0x00, 0xD5, 0x00, 0xD6, 0x00, 0xD7, 0x00, + 0xD8, 0x00, 0xD9, 0x00, 0xDA, 0x00, 0xDB, 0x00, 0xDC, 0x00, 0xDD, 0x00, 0xDE, 0x00, 0xDF, 0x00, + 0xC0, 0x00, 0xC1, 0x00, 0xC2, 0x00, 0xC3, 0x00, 0xC4, 0x00, 0xC5, 0x00, 0xC6, 0x00, 0xC7, 0x00, + 0xC8, 0x00, 0xC9, 0x00, 0xCA, 0x00, 0xCB, 0x00, 0xCC, 0x00, 0xCD, 0x00, 0xCE, 0x00, 0xCF, 0x00, + 0xD0, 0x00, 0xD1, 0x00, 0xD2, 0x00, 0xD3, 0x00, 0xD4, 0x00, 0xD5, 0x00, 0xD6, 0x00, 0xF7, 0x00, + 0xD8, 0x00, 0xD9, 0x00, 0xDA, 0x00, 0xDB, 0x00, 0xDC, 0x00, 0xDD, 0x00, 0xDE, 0x00, 0x78, 0x01, + 0x00, 0x01, 0x00, 0x01, 0x02, 0x01, 0x02, 0x01, 0x04, 0x01, 0x04, 0x01, 0x06, 0x01, 0x06, 0x01, + 0x08, 0x01, 0x08, 0x01, 0x0A, 0x01, 0x0A, 0x01, 0x0C, 0x01, 0x0C, 0x01, 0x0E, 0x01, 0x0E, 0x01, + 0x10, 0x01, 0x10, 0x01, 0x12, 0x01, 0x12, 0x01, 0x14, 0x01, 0x14, 0x01, 0x16, 0x01, 0x16, 0x01, + 0x18, 0x01, 0x18, 0x01, 0x1A, 0x01, 0x1A, 0x01, 0x1C, 0x01, 0x1C, 0x01, 0x1E, 0x01, 0x1E, 0x01, + 0x20, 0x01, 0x20, 0x01, 0x22, 0x01, 0x22, 0x01, 0x24, 0x01, 0x24, 0x01, 0x26, 0x01, 0x26, 0x01, + 0x28, 0x01, 0x28, 0x01, 0x2A, 0x01, 0x2A, 0x01, 0x2C, 0x01, 0x2C, 0x01, 0x2E, 0x01, 0x2E, 0x01, + 0x30, 0x01, 0x31, 0x01, 0x32, 0x01, 0x32, 0x01, 0x34, 0x01, 0x34, 0x01, 0x36, 0x01, 0x36, 0x01, + 0x38, 0x01, 0x39, 0x01, 0x39, 0x01, 0x3B, 0x01, 0x3B, 0x01, 0x3D, 0x01, 0x3D, 0x01, 0x3F, 0x01, + 0x3F, 0x01, 0x41, 0x01, 0x41, 0x01, 0x43, 0x01, 0x43, 0x01, 0x45, 0x01, 0x45, 0x01, 0x47, 0x01, + 0x47, 0x01, 0x49, 0x01, 0x4A, 0x01, 0x4A, 0x01, 0x4C, 0x01, 0x4C, 0x01, 0x4E, 0x01, 0x4E, 0x01, + 0x50, 0x01, 0x50, 0x01, 0x52, 0x01, 0x52, 0x01, 0x54, 0x01, 0x54, 0x01, 0x56, 0x01, 0x56, 0x01, + 0x58, 0x01, 0x58, 0x01, 0x5A, 0x01, 0x5A, 0x01, 0x5C, 0x01, 0x5C, 0x01, 0x5E, 0x01, 0x5E, 0x01, + 0x60, 0x01, 0x60, 0x01, 0x62, 0x01, 0x62, 0x01, 0x64, 0x01, 0x64, 0x01, 0x66, 0x01, 0x66, 0x01, + 0x68, 0x01, 0x68, 0x01, 0x6A, 0x01, 0x6A, 0x01, 0x6C, 0x01, 0x6C, 0x01, 0x6E, 0x01, 0x6E, 0x01, + 0x70, 0x01, 0x70, 0x01, 0x72, 0x01, 0x72, 0x01, 0x74, 0x01, 0x74, 0x01, 0x76, 0x01, 0x76, 0x01, + 0x78, 0x01, 0x79, 0x01, 0x79, 0x01, 0x7B, 0x01, 0x7B, 0x01, 0x7D, 0x01, 0x7D, 0x01, 0x7F, 0x01, + 0x43, 0x02, 0x81, 0x01, 0x82, 0x01, 0x82, 0x01, 0x84, 0x01, 0x84, 0x01, 0x86, 0x01, 0x87, 0x01, + 0x87, 0x01, 0x89, 0x01, 0x8A, 0x01, 0x8B, 0x01, 0x8B, 0x01, 0x8D, 0x01, 0x8E, 0x01, 0x8F, 0x01, + 0x90, 0x01, 0x91, 0x01, 0x91, 0x01, 0x93, 0x01, 0x94, 0x01, 0xF6, 0x01, 0x96, 0x01, 0x97, 0x01, + 0x98, 0x01, 0x98, 0x01, 0x3D, 0x02, 0x9B, 0x01, 0x9C, 0x01, 0x9D, 0x01, 0x20, 0x02, 0x9F, 0x01, + 0xA0, 0x01, 0xA0, 0x01, 0xA2, 0x01, 0xA2, 0x01, 0xA4, 0x01, 0xA4, 0x01, 0xA6, 0x01, 0xA7, 0x01, + 0xA7, 0x01, 0xA9, 0x01, 0xAA, 0x01, 0xAB, 0x01, 0xAC, 0x01, 0xAC, 0x01, 0xAE, 0x01, 0xAF, 0x01, + 0xAF, 0x01, 0xB1, 0x01, 0xB2, 0x01, 0xB3, 0x01, 0xB3, 0x01, 0xB5, 0x01, 0xB5, 0x01, 0xB7, 0x01, + 0xB8, 0x01, 0xB8, 0x01, 0xBA, 0x01, 0xBB, 0x01, 0xBC, 0x01, 0xBC, 0x01, 0xBE, 0x01, 0xF7, 0x01, + 0xC0, 0x01, 0xC1, 0x01, 0xC2, 0x01, 0xC3, 0x01, 0xC4, 0x01, 0xC5, 0x01, 0xC4, 0x01, 0xC7, 0x01, + 0xC8, 0x01, 0xC7, 0x01, 0xCA, 0x01, 0xCB, 0x01, 0xCA, 0x01, 0xCD, 0x01, 0xCD, 0x01, 0xCF, 0x01, + 0xCF, 0x01, 0xD1, 0x01, 0xD1, 0x01, 0xD3, 0x01, 0xD3, 0x01, 0xD5, 0x01, 0xD5, 0x01, 0xD7, 0x01, + 0xD7, 0x01, 0xD9, 0x01, 0xD9, 0x01, 0xDB, 0x01, 0xDB, 0x01, 0x8E, 0x01, 0xDE, 0x01, 0xDE, 0x01, + 0xE0, 0x01, 0xE0, 0x01, 0xE2, 0x01, 0xE2, 0x01, 0xE4, 0x01, 0xE4, 0x01, 0xE6, 0x01, 0xE6, 0x01, + 0xE8, 0x01, 0xE8, 0x01, 0xEA, 0x01, 0xEA, 0x01, 0xEC, 0x01, 0xEC, 0x01, 0xEE, 0x01, 0xEE, 0x01, + 0xF0, 0x01, 0xF1, 0x01, 0xF2, 0x01, 0xF1, 0x01, 0xF4, 0x01, 0xF4, 0x01, 0xF6, 0x01, 0xF7, 0x01, + 0xF8, 0x01, 0xF8, 0x01, 0xFA, 0x01, 0xFA, 0x01, 0xFC, 0x01, 0xFC, 0x01, 0xFE, 0x01, 0xFE, 0x01, + 0x00, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x04, 0x02, 0x04, 0x02, 0x06, 0x02, 0x06, 0x02, + 0x08, 0x02, 0x08, 0x02, 0x0A, 0x02, 0x0A, 0x02, 0x0C, 0x02, 0x0C, 0x02, 0x0E, 0x02, 0x0E, 0x02, + 0x10, 0x02, 0x10, 0x02, 0x12, 0x02, 0x12, 0x02, 0x14, 0x02, 0x14, 0x02, 0x16, 0x02, 0x16, 0x02, + 0x18, 0x02, 0x18, 0x02, 0x1A, 0x02, 0x1A, 0x02, 0x1C, 0x02, 0x1C, 0x02, 0x1E, 0x02, 0x1E, 0x02, + 0x20, 0x02, 0x21, 0x02, 0x22, 0x02, 0x22, 0x02, 0x24, 0x02, 0x24, 0x02, 0x26, 0x02, 0x26, 0x02, + 0x28, 0x02, 0x28, 0x02, 0x2A, 0x02, 0x2A, 0x02, 0x2C, 0x02, 0x2C, 0x02, 0x2E, 0x02, 0x2E, 0x02, + 0x30, 0x02, 0x30, 0x02, 0x32, 0x02, 0x32, 0x02, 0x34, 0x02, 0x35, 0x02, 0x36, 0x02, 0x37, 0x02, + 0x38, 0x02, 0x39, 0x02, 0x65, 0x2C, 0x3B, 0x02, 0x3B, 0x02, 0x3D, 0x02, 0x66, 0x2C, 0x3F, 0x02, + 0x40, 0x02, 0x41, 0x02, 0x41, 0x02, 0x43, 0x02, 0x44, 0x02, 0x45, 0x02, 0x46, 0x02, 0x46, 0x02, + 0x48, 0x02, 0x48, 0x02, 0x4A, 0x02, 0x4A, 0x02, 0x4C, 0x02, 0x4C, 0x02, 0x4E, 0x02, 0x4E, 0x02, + 0x50, 0x02, 0x51, 0x02, 0x52, 0x02, 0x81, 0x01, 0x86, 0x01, 0x55, 0x02, 0x89, 0x01, 0x8A, 0x01, + 0x58, 0x02, 0x8F, 0x01, 0x5A, 0x02, 0x90, 0x01, 0x5C, 0x02, 0x5D, 0x02, 0x5E, 0x02, 0x5F, 0x02, + 0x93, 0x01, 0x61, 0x02, 0x62, 0x02, 0x94, 0x01, 0x64, 0x02, 0x65, 0x02, 0x66, 0x02, 0x67, 0x02, + 0x97, 0x01, 0x96, 0x01, 0x6A, 0x02, 0x62, 0x2C, 0x6C, 0x02, 0x6D, 0x02, 0x6E, 0x02, 0x9C, 0x01, + 0x70, 0x02, 0x71, 0x02, 0x9D, 0x01, 0x73, 0x02, 0x74, 0x02, 0x9F, 0x01, 0x76, 0x02, 0x77, 0x02, + 0x78, 0x02, 0x79, 0x02, 0x7A, 0x02, 0x7B, 0x02, 0x7C, 0x02, 0x64, 0x2C, 0x7E, 0x02, 0x7F, 0x02, + 0xA6, 0x01, 0x81, 0x02, 0x82, 0x02, 0xA9, 0x01, 0x84, 0x02, 0x85, 0x02, 0x86, 0x02, 0x87, 0x02, + 0xAE, 0x01, 0x44, 0x02, 0xB1, 0x01, 0xB2, 0x01, 0x45, 0x02, 0x8D, 0x02, 0x8E, 0x02, 0x8F, 0x02, + 0x90, 0x02, 0x91, 0x02, 0xB7, 0x01, 0x93, 0x02, 0x94, 0x02, 0x95, 0x02, 0x96, 0x02, 0x97, 0x02, + 0x98, 0x02, 0x99, 0x02, 0x9A, 0x02, 0x9B, 0x02, 0x9C, 0x02, 0x9D, 0x02, 0x9E, 0x02, 0x9F, 0x02, + 0xA0, 0x02, 0xA1, 0x02, 0xA2, 0x02, 0xA3, 0x02, 0xA4, 0x02, 0xA5, 0x02, 0xA6, 0x02, 0xA7, 0x02, + 0xA8, 0x02, 0xA9, 0x02, 0xAA, 0x02, 0xAB, 0x02, 0xAC, 0x02, 0xAD, 0x02, 0xAE, 0x02, 0xAF, 0x02, + 0xB0, 0x02, 0xB1, 0x02, 0xB2, 0x02, 0xB3, 0x02, 0xB4, 0x02, 0xB5, 0x02, 0xB6, 0x02, 0xB7, 0x02, + 0xB8, 0x02, 0xB9, 0x02, 0xBA, 0x02, 0xBB, 0x02, 0xBC, 0x02, 0xBD, 0x02, 0xBE, 0x02, 0xBF, 0x02, + 0xC0, 0x02, 0xC1, 0x02, 0xC2, 0x02, 0xC3, 0x02, 0xC4, 0x02, 0xC5, 0x02, 0xC6, 0x02, 0xC7, 0x02, + 0xC8, 0x02, 0xC9, 0x02, 0xCA, 0x02, 0xCB, 0x02, 0xCC, 0x02, 0xCD, 0x02, 0xCE, 0x02, 0xCF, 0x02, + 0xD0, 0x02, 0xD1, 0x02, 0xD2, 0x02, 0xD3, 0x02, 0xD4, 0x02, 0xD5, 0x02, 0xD6, 0x02, 0xD7, 0x02, + 0xD8, 0x02, 0xD9, 0x02, 0xDA, 0x02, 0xDB, 0x02, 0xDC, 0x02, 0xDD, 0x02, 0xDE, 0x02, 0xDF, 0x02, + 0xE0, 0x02, 0xE1, 0x02, 0xE2, 0x02, 0xE3, 0x02, 0xE4, 0x02, 0xE5, 0x02, 0xE6, 0x02, 0xE7, 0x02, + 0xE8, 0x02, 0xE9, 0x02, 0xEA, 0x02, 0xEB, 0x02, 0xEC, 0x02, 0xED, 0x02, 0xEE, 0x02, 0xEF, 0x02, + 0xF0, 0x02, 0xF1, 0x02, 0xF2, 0x02, 0xF3, 0x02, 0xF4, 0x02, 0xF5, 0x02, 0xF6, 0x02, 0xF7, 0x02, + 0xF8, 0x02, 0xF9, 0x02, 0xFA, 0x02, 0xFB, 0x02, 0xFC, 0x02, 0xFD, 0x02, 0xFE, 0x02, 0xFF, 0x02, + 0x00, 0x03, 0x01, 0x03, 0x02, 0x03, 0x03, 0x03, 0x04, 0x03, 0x05, 0x03, 0x06, 0x03, 0x07, 0x03, + 0x08, 0x03, 0x09, 0x03, 0x0A, 0x03, 0x0B, 0x03, 0x0C, 0x03, 0x0D, 0x03, 0x0E, 0x03, 0x0F, 0x03, + 0x10, 0x03, 0x11, 0x03, 0x12, 0x03, 0x13, 0x03, 0x14, 0x03, 0x15, 0x03, 0x16, 0x03, 0x17, 0x03, + 0x18, 0x03, 0x19, 0x03, 0x1A, 0x03, 0x1B, 0x03, 0x1C, 0x03, 0x1D, 0x03, 0x1E, 0x03, 0x1F, 0x03, + 0x20, 0x03, 0x21, 0x03, 0x22, 0x03, 0x23, 0x03, 0x24, 0x03, 0x25, 0x03, 0x26, 0x03, 0x27, 0x03, + 0x28, 0x03, 0x29, 0x03, 0x2A, 0x03, 0x2B, 0x03, 0x2C, 0x03, 0x2D, 0x03, 0x2E, 0x03, 0x2F, 0x03, + 0x30, 0x03, 0x31, 0x03, 0x32, 0x03, 0x33, 0x03, 0x34, 0x03, 0x35, 0x03, 0x36, 0x03, 0x37, 0x03, + 0x38, 0x03, 0x39, 0x03, 0x3A, 0x03, 0x3B, 0x03, 0x3C, 0x03, 0x3D, 0x03, 0x3E, 0x03, 0x3F, 0x03, + 0x40, 0x03, 0x41, 0x03, 0x42, 0x03, 0x43, 0x03, 0x44, 0x03, 0x45, 0x03, 0x46, 0x03, 0x47, 0x03, + 0x48, 0x03, 0x49, 0x03, 0x4A, 0x03, 0x4B, 0x03, 0x4C, 0x03, 0x4D, 0x03, 0x4E, 0x03, 0x4F, 0x03, + 0x50, 0x03, 0x51, 0x03, 0x52, 0x03, 0x53, 0x03, 0x54, 0x03, 0x55, 0x03, 0x56, 0x03, 0x57, 0x03, + 0x58, 0x03, 0x59, 0x03, 0x5A, 0x03, 0x5B, 0x03, 0x5C, 0x03, 0x5D, 0x03, 0x5E, 0x03, 0x5F, 0x03, + 0x60, 0x03, 0x61, 0x03, 0x62, 0x03, 0x63, 0x03, 0x64, 0x03, 0x65, 0x03, 0x66, 0x03, 0x67, 0x03, + 0x68, 0x03, 0x69, 0x03, 0x6A, 0x03, 0x6B, 0x03, 0x6C, 0x03, 0x6D, 0x03, 0x6E, 0x03, 0x6F, 0x03, + 0x70, 0x03, 0x71, 0x03, 0x72, 0x03, 0x73, 0x03, 0x74, 0x03, 0x75, 0x03, 0x76, 0x03, 0x77, 0x03, + 0x78, 0x03, 0x79, 0x03, 0x7A, 0x03, 0xFD, 0x03, 0xFE, 0x03, 0xFF, 0x03, 0x7E, 0x03, 0x7F, 0x03, + 0x80, 0x03, 0x81, 0x03, 0x82, 0x03, 0x83, 0x03, 0x84, 0x03, 0x85, 0x03, 0x86, 0x03, 0x87, 0x03, + 0x88, 0x03, 0x89, 0x03, 0x8A, 0x03, 0x8B, 0x03, 0x8C, 0x03, 0x8D, 0x03, 0x8E, 0x03, 0x8F, 0x03, + 0x90, 0x03, 0x91, 0x03, 0x92, 0x03, 0x93, 0x03, 0x94, 0x03, 0x95, 0x03, 0x96, 0x03, 0x97, 0x03, + 0x98, 0x03, 0x99, 0x03, 0x9A, 0x03, 0x9B, 0x03, 0x9C, 0x03, 0x9D, 0x03, 0x9E, 0x03, 0x9F, 0x03, + 0xA0, 0x03, 0xA1, 0x03, 0xA2, 0x03, 0xA3, 0x03, 0xA4, 0x03, 0xA5, 0x03, 0xA6, 0x03, 0xA7, 0x03, + 0xA8, 0x03, 0xA9, 0x03, 0xAA, 0x03, 0xAB, 0x03, 0x86, 0x03, 0x88, 0x03, 0x89, 0x03, 0x8A, 0x03, + 0xB0, 0x03, 0x91, 0x03, 0x92, 0x03, 0x93, 0x03, 0x94, 0x03, 0x95, 0x03, 0x96, 0x03, 0x97, 0x03, + 0x98, 0x03, 0x99, 0x03, 0x9A, 0x03, 0x9B, 0x03, 0x9C, 0x03, 0x9D, 0x03, 0x9E, 0x03, 0x9F, 0x03, + 0xA0, 0x03, 0xA1, 0x03, 0xA3, 0x03, 0xA3, 0x03, 0xA4, 0x03, 0xA5, 0x03, 0xA6, 0x03, 0xA7, 0x03, + 0xA8, 0x03, 0xA9, 0x03, 0xAA, 0x03, 0xAB, 0x03, 0x8C, 0x03, 0x8E, 0x03, 0x8F, 0x03, 0xCF, 0x03, + 0xD0, 0x03, 0xD1, 0x03, 0xD2, 0x03, 0xD3, 0x03, 0xD4, 0x03, 0xD5, 0x03, 0xD6, 0x03, 0xD7, 0x03, + 0xD8, 0x03, 0xD8, 0x03, 0xDA, 0x03, 0xDA, 0x03, 0xDC, 0x03, 0xDC, 0x03, 0xDE, 0x03, 0xDE, 0x03, + 0xE0, 0x03, 0xE0, 0x03, 0xE2, 0x03, 0xE2, 0x03, 0xE4, 0x03, 0xE4, 0x03, 0xE6, 0x03, 0xE6, 0x03, + 0xE8, 0x03, 0xE8, 0x03, 0xEA, 0x03, 0xEA, 0x03, 0xEC, 0x03, 0xEC, 0x03, 0xEE, 0x03, 0xEE, 0x03, + 0xF0, 0x03, 0xF1, 0x03, 0xF9, 0x03, 0xF3, 0x03, 0xF4, 0x03, 0xF5, 0x03, 0xF6, 0x03, 0xF7, 0x03, + 0xF7, 0x03, 0xF9, 0x03, 0xFA, 0x03, 0xFA, 0x03, 0xFC, 0x03, 0xFD, 0x03, 0xFE, 0x03, 0xFF, 0x03, + 0x00, 0x04, 0x01, 0x04, 0x02, 0x04, 0x03, 0x04, 0x04, 0x04, 0x05, 0x04, 0x06, 0x04, 0x07, 0x04, + 0x08, 0x04, 0x09, 0x04, 0x0A, 0x04, 0x0B, 0x04, 0x0C, 0x04, 0x0D, 0x04, 0x0E, 0x04, 0x0F, 0x04, + 0x10, 0x04, 0x11, 0x04, 0x12, 0x04, 0x13, 0x04, 0x14, 0x04, 0x15, 0x04, 0x16, 0x04, 0x17, 0x04, + 0x18, 0x04, 0x19, 0x04, 0x1A, 0x04, 0x1B, 0x04, 0x1C, 0x04, 0x1D, 0x04, 0x1E, 0x04, 0x1F, 0x04, + 0x20, 0x04, 0x21, 0x04, 0x22, 0x04, 0x23, 0x04, 0x24, 0x04, 0x25, 0x04, 0x26, 0x04, 0x27, 0x04, + 0x28, 0x04, 0x29, 0x04, 0x2A, 0x04, 0x2B, 0x04, 0x2C, 0x04, 0x2D, 0x04, 0x2E, 0x04, 0x2F, 0x04, + 0x10, 0x04, 0x11, 0x04, 0x12, 0x04, 0x13, 0x04, 0x14, 0x04, 0x15, 0x04, 0x16, 0x04, 0x17, 0x04, + 0x18, 0x04, 0x19, 0x04, 0x1A, 0x04, 0x1B, 0x04, 0x1C, 0x04, 0x1D, 0x04, 0x1E, 0x04, 0x1F, 0x04, + 0x20, 0x04, 0x21, 0x04, 0x22, 0x04, 0x23, 0x04, 0x24, 0x04, 0x25, 0x04, 0x26, 0x04, 0x27, 0x04, + 0x28, 0x04, 0x29, 0x04, 0x2A, 0x04, 0x2B, 0x04, 0x2C, 0x04, 0x2D, 0x04, 0x2E, 0x04, 0x2F, 0x04, + 0x00, 0x04, 0x01, 0x04, 0x02, 0x04, 0x03, 0x04, 0x04, 0x04, 0x05, 0x04, 0x06, 0x04, 0x07, 0x04, + 0x08, 0x04, 0x09, 0x04, 0x0A, 0x04, 0x0B, 0x04, 0x0C, 0x04, 0x0D, 0x04, 0x0E, 0x04, 0x0F, 0x04, + 0x60, 0x04, 0x60, 0x04, 0x62, 0x04, 0x62, 0x04, 0x64, 0x04, 0x64, 0x04, 0x66, 0x04, 0x66, 0x04, + 0x68, 0x04, 0x68, 0x04, 0x6A, 0x04, 0x6A, 0x04, 0x6C, 0x04, 0x6C, 0x04, 0x6E, 0x04, 0x6E, 0x04, + 0x70, 0x04, 0x70, 0x04, 0x72, 0x04, 0x72, 0x04, 0x74, 0x04, 0x74, 0x04, 0x76, 0x04, 0x76, 0x04, + 0x78, 0x04, 0x78, 0x04, 0x7A, 0x04, 0x7A, 0x04, 0x7C, 0x04, 0x7C, 0x04, 0x7E, 0x04, 0x7E, 0x04, + 0x80, 0x04, 0x80, 0x04, 0x82, 0x04, 0x83, 0x04, 0x84, 0x04, 0x85, 0x04, 0x86, 0x04, 0x87, 0x04, + 0x88, 0x04, 0x89, 0x04, 0x8A, 0x04, 0x8A, 0x04, 0x8C, 0x04, 0x8C, 0x04, 0x8E, 0x04, 0x8E, 0x04, + 0x90, 0x04, 0x90, 0x04, 0x92, 0x04, 0x92, 0x04, 0x94, 0x04, 0x94, 0x04, 0x96, 0x04, 0x96, 0x04, + 0x98, 0x04, 0x98, 0x04, 0x9A, 0x04, 0x9A, 0x04, 0x9C, 0x04, 0x9C, 0x04, 0x9E, 0x04, 0x9E, 0x04, + 0xA0, 0x04, 0xA0, 0x04, 0xA2, 0x04, 0xA2, 0x04, 0xA4, 0x04, 0xA4, 0x04, 0xA6, 0x04, 0xA6, 0x04, + 0xA8, 0x04, 0xA8, 0x04, 0xAA, 0x04, 0xAA, 0x04, 0xAC, 0x04, 0xAC, 0x04, 0xAE, 0x04, 0xAE, 0x04, + 0xB0, 0x04, 0xB0, 0x04, 0xB2, 0x04, 0xB2, 0x04, 0xB4, 0x04, 0xB4, 0x04, 0xB6, 0x04, 0xB6, 0x04, + 0xB8, 0x04, 0xB8, 0x04, 0xBA, 0x04, 0xBA, 0x04, 0xBC, 0x04, 0xBC, 0x04, 0xBE, 0x04, 0xBE, 0x04, + 0xC0, 0x04, 0xC1, 0x04, 0xC1, 0x04, 0xC3, 0x04, 0xC3, 0x04, 0xC5, 0x04, 0xC5, 0x04, 0xC7, 0x04, + 0xC7, 0x04, 0xC9, 0x04, 0xC9, 0x04, 0xCB, 0x04, 0xCB, 0x04, 0xCD, 0x04, 0xCD, 0x04, 0xC0, 0x04, + 0xD0, 0x04, 0xD0, 0x04, 0xD2, 0x04, 0xD2, 0x04, 0xD4, 0x04, 0xD4, 0x04, 0xD6, 0x04, 0xD6, 0x04, + 0xD8, 0x04, 0xD8, 0x04, 0xDA, 0x04, 0xDA, 0x04, 0xDC, 0x04, 0xDC, 0x04, 0xDE, 0x04, 0xDE, 0x04, + 0xE0, 0x04, 0xE0, 0x04, 0xE2, 0x04, 0xE2, 0x04, 0xE4, 0x04, 0xE4, 0x04, 0xE6, 0x04, 0xE6, 0x04, + 0xE8, 0x04, 0xE8, 0x04, 0xEA, 0x04, 0xEA, 0x04, 0xEC, 0x04, 0xEC, 0x04, 0xEE, 0x04, 0xEE, 0x04, + 0xF0, 0x04, 0xF0, 0x04, 0xF2, 0x04, 0xF2, 0x04, 0xF4, 0x04, 0xF4, 0x04, 0xF6, 0x04, 0xF6, 0x04, + 0xF8, 0x04, 0xF8, 0x04, 0xFA, 0x04, 0xFA, 0x04, 0xFC, 0x04, 0xFC, 0x04, 0xFE, 0x04, 0xFE, 0x04, + 0x00, 0x05, 0x00, 0x05, 0x02, 0x05, 0x02, 0x05, 0x04, 0x05, 0x04, 0x05, 0x06, 0x05, 0x06, 0x05, + 0x08, 0x05, 0x08, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0C, 0x05, 0x0C, 0x05, 0x0E, 0x05, 0x0E, 0x05, + 0x10, 0x05, 0x10, 0x05, 0x12, 0x05, 0x12, 0x05, 0x14, 0x05, 0x15, 0x05, 0x16, 0x05, 0x17, 0x05, + 0x18, 0x05, 0x19, 0x05, 0x1A, 0x05, 0x1B, 0x05, 0x1C, 0x05, 0x1D, 0x05, 0x1E, 0x05, 0x1F, 0x05, + 0x20, 0x05, 0x21, 0x05, 0x22, 0x05, 0x23, 0x05, 0x24, 0x05, 0x25, 0x05, 0x26, 0x05, 0x27, 0x05, + 0x28, 0x05, 0x29, 0x05, 0x2A, 0x05, 0x2B, 0x05, 0x2C, 0x05, 0x2D, 0x05, 0x2E, 0x05, 0x2F, 0x05, + 0x30, 0x05, 0x31, 0x05, 0x32, 0x05, 0x33, 0x05, 0x34, 0x05, 0x35, 0x05, 0x36, 0x05, 0x37, 0x05, + 0x38, 0x05, 0x39, 0x05, 0x3A, 0x05, 0x3B, 0x05, 0x3C, 0x05, 0x3D, 0x05, 0x3E, 0x05, 0x3F, 0x05, + 0x40, 0x05, 0x41, 0x05, 0x42, 0x05, 0x43, 0x05, 0x44, 0x05, 0x45, 0x05, 0x46, 0x05, 0x47, 0x05, + 0x48, 0x05, 0x49, 0x05, 0x4A, 0x05, 0x4B, 0x05, 0x4C, 0x05, 0x4D, 0x05, 0x4E, 0x05, 0x4F, 0x05, + 0x50, 0x05, 0x51, 0x05, 0x52, 0x05, 0x53, 0x05, 0x54, 0x05, 0x55, 0x05, 0x56, 0x05, 0x57, 0x05, + 0x58, 0x05, 0x59, 0x05, 0x5A, 0x05, 0x5B, 0x05, 0x5C, 0x05, 0x5D, 0x05, 0x5E, 0x05, 0x5F, 0x05, + 0x60, 0x05, 0x31, 0x05, 0x32, 0x05, 0x33, 0x05, 0x34, 0x05, 0x35, 0x05, 0x36, 0x05, 0x37, 0x05, + 0x38, 0x05, 0x39, 0x05, 0x3A, 0x05, 0x3B, 0x05, 0x3C, 0x05, 0x3D, 0x05, 0x3E, 0x05, 0x3F, 0x05, + 0x40, 0x05, 0x41, 0x05, 0x42, 0x05, 0x43, 0x05, 0x44, 0x05, 0x45, 0x05, 0x46, 0x05, 0x47, 0x05, + 0x48, 0x05, 0x49, 0x05, 0x4A, 0x05, 0x4B, 0x05, 0x4C, 0x05, 0x4D, 0x05, 0x4E, 0x05, 0x4F, 0x05, + 0x50, 0x05, 0x51, 0x05, 0x52, 0x05, 0x53, 0x05, 0x54, 0x05, 0x55, 0x05, 0x56, 0x05, 0xFF, 0xFF, + 0xF6, 0x17, 0x63, 0x2C, 0x7E, 0x1D, 0x7F, 0x1D, 0x80, 0x1D, 0x81, 0x1D, 0x82, 0x1D, 0x83, 0x1D, + 0x84, 0x1D, 0x85, 0x1D, 0x86, 0x1D, 0x87, 0x1D, 0x88, 0x1D, 0x89, 0x1D, 0x8A, 0x1D, 0x8B, 0x1D, + 0x8C, 0x1D, 0x8D, 0x1D, 0x8E, 0x1D, 0x8F, 0x1D, 0x90, 0x1D, 0x91, 0x1D, 0x92, 0x1D, 0x93, 0x1D, + 0x94, 0x1D, 0x95, 0x1D, 0x96, 0x1D, 0x97, 0x1D, 0x98, 0x1D, 0x99, 0x1D, 0x9A, 0x1D, 0x9B, 0x1D, + 0x9C, 0x1D, 0x9D, 0x1D, 0x9E, 0x1D, 0x9F, 0x1D, 0xA0, 0x1D, 0xA1, 0x1D, 0xA2, 0x1D, 0xA3, 0x1D, + 0xA4, 0x1D, 0xA5, 0x1D, 0xA6, 0x1D, 0xA7, 0x1D, 0xA8, 0x1D, 0xA9, 0x1D, 0xAA, 0x1D, 0xAB, 0x1D, + 0xAC, 0x1D, 0xAD, 0x1D, 0xAE, 0x1D, 0xAF, 0x1D, 0xB0, 0x1D, 0xB1, 0x1D, 0xB2, 0x1D, 0xB3, 0x1D, + 0xB4, 0x1D, 0xB5, 0x1D, 0xB6, 0x1D, 0xB7, 0x1D, 0xB8, 0x1D, 0xB9, 0x1D, 0xBA, 0x1D, 0xBB, 0x1D, + 0xBC, 0x1D, 0xBD, 0x1D, 0xBE, 0x1D, 0xBF, 0x1D, 0xC0, 0x1D, 0xC1, 0x1D, 0xC2, 0x1D, 0xC3, 0x1D, + 0xC4, 0x1D, 0xC5, 0x1D, 0xC6, 0x1D, 0xC7, 0x1D, 0xC8, 0x1D, 0xC9, 0x1D, 0xCA, 0x1D, 0xCB, 0x1D, + 0xCC, 0x1D, 0xCD, 0x1D, 0xCE, 0x1D, 0xCF, 0x1D, 0xD0, 0x1D, 0xD1, 0x1D, 0xD2, 0x1D, 0xD3, 0x1D, + 0xD4, 0x1D, 0xD5, 0x1D, 0xD6, 0x1D, 0xD7, 0x1D, 0xD8, 0x1D, 0xD9, 0x1D, 0xDA, 0x1D, 0xDB, 0x1D, + 0xDC, 0x1D, 0xDD, 0x1D, 0xDE, 0x1D, 0xDF, 0x1D, 0xE0, 0x1D, 0xE1, 0x1D, 0xE2, 0x1D, 0xE3, 0x1D, + 0xE4, 0x1D, 0xE5, 0x1D, 0xE6, 0x1D, 0xE7, 0x1D, 0xE8, 0x1D, 0xE9, 0x1D, 0xEA, 0x1D, 0xEB, 0x1D, + 0xEC, 0x1D, 0xED, 0x1D, 0xEE, 0x1D, 0xEF, 0x1D, 0xF0, 0x1D, 0xF1, 0x1D, 0xF2, 0x1D, 0xF3, 0x1D, + 0xF4, 0x1D, 0xF5, 0x1D, 0xF6, 0x1D, 0xF7, 0x1D, 0xF8, 0x1D, 0xF9, 0x1D, 0xFA, 0x1D, 0xFB, 0x1D, + 0xFC, 0x1D, 0xFD, 0x1D, 0xFE, 0x1D, 0xFF, 0x1D, 0x00, 0x1E, 0x00, 0x1E, 0x02, 0x1E, 0x02, 0x1E, + 0x04, 0x1E, 0x04, 0x1E, 0x06, 0x1E, 0x06, 0x1E, 0x08, 0x1E, 0x08, 0x1E, 0x0A, 0x1E, 0x0A, 0x1E, + 0x0C, 0x1E, 0x0C, 0x1E, 0x0E, 0x1E, 0x0E, 0x1E, 0x10, 0x1E, 0x10, 0x1E, 0x12, 0x1E, 0x12, 0x1E, + 0x14, 0x1E, 0x14, 0x1E, 0x16, 0x1E, 0x16, 0x1E, 0x18, 0x1E, 0x18, 0x1E, 0x1A, 0x1E, 0x1A, 0x1E, + 0x1C, 0x1E, 0x1C, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x20, 0x1E, 0x20, 0x1E, 0x22, 0x1E, 0x22, 0x1E, + 0x24, 0x1E, 0x24, 0x1E, 0x26, 0x1E, 0x26, 0x1E, 0x28, 0x1E, 0x28, 0x1E, 0x2A, 0x1E, 0x2A, 0x1E, + 0x2C, 0x1E, 0x2C, 0x1E, 0x2E, 0x1E, 0x2E, 0x1E, 0x30, 0x1E, 0x30, 0x1E, 0x32, 0x1E, 0x32, 0x1E, + 0x34, 0x1E, 0x34, 0x1E, 0x36, 0x1E, 0x36, 0x1E, 0x38, 0x1E, 0x38, 0x1E, 0x3A, 0x1E, 0x3A, 0x1E, + 0x3C, 0x1E, 0x3C, 0x1E, 0x3E, 0x1E, 0x3E, 0x1E, 0x40, 0x1E, 0x40, 0x1E, 0x42, 0x1E, 0x42, 0x1E, + 0x44, 0x1E, 0x44, 0x1E, 0x46, 0x1E, 0x46, 0x1E, 0x48, 0x1E, 0x48, 0x1E, 0x4A, 0x1E, 0x4A, 0x1E, + 0x4C, 0x1E, 0x4C, 0x1E, 0x4E, 0x1E, 0x4E, 0x1E, 0x50, 0x1E, 0x50, 0x1E, 0x52, 0x1E, 0x52, 0x1E, + 0x54, 0x1E, 0x54, 0x1E, 0x56, 0x1E, 0x56, 0x1E, 0x58, 0x1E, 0x58, 0x1E, 0x5A, 0x1E, 0x5A, 0x1E, + 0x5C, 0x1E, 0x5C, 0x1E, 0x5E, 0x1E, 0x5E, 0x1E, 0x60, 0x1E, 0x60, 0x1E, 0x62, 0x1E, 0x62, 0x1E, + 0x64, 0x1E, 0x64, 0x1E, 0x66, 0x1E, 0x66, 0x1E, 0x68, 0x1E, 0x68, 0x1E, 0x6A, 0x1E, 0x6A, 0x1E, + 0x6C, 0x1E, 0x6C, 0x1E, 0x6E, 0x1E, 0x6E, 0x1E, 0x70, 0x1E, 0x70, 0x1E, 0x72, 0x1E, 0x72, 0x1E, + 0x74, 0x1E, 0x74, 0x1E, 0x76, 0x1E, 0x76, 0x1E, 0x78, 0x1E, 0x78, 0x1E, 0x7A, 0x1E, 0x7A, 0x1E, + 0x7C, 0x1E, 0x7C, 0x1E, 0x7E, 0x1E, 0x7E, 0x1E, 0x80, 0x1E, 0x80, 0x1E, 0x82, 0x1E, 0x82, 0x1E, + 0x84, 0x1E, 0x84, 0x1E, 0x86, 0x1E, 0x86, 0x1E, 0x88, 0x1E, 0x88, 0x1E, 0x8A, 0x1E, 0x8A, 0x1E, + 0x8C, 0x1E, 0x8C, 0x1E, 0x8E, 0x1E, 0x8E, 0x1E, 0x90, 0x1E, 0x90, 0x1E, 0x92, 0x1E, 0x92, 0x1E, + 0x94, 0x1E, 0x94, 0x1E, 0x96, 0x1E, 0x97, 0x1E, 0x98, 0x1E, 0x99, 0x1E, 0x9A, 0x1E, 0x9B, 0x1E, + 0x9C, 0x1E, 0x9D, 0x1E, 0x9E, 0x1E, 0x9F, 0x1E, 0xA0, 0x1E, 0xA0, 0x1E, 0xA2, 0x1E, 0xA2, 0x1E, + 0xA4, 0x1E, 0xA4, 0x1E, 0xA6, 0x1E, 0xA6, 0x1E, 0xA8, 0x1E, 0xA8, 0x1E, 0xAA, 0x1E, 0xAA, 0x1E, + 0xAC, 0x1E, 0xAC, 0x1E, 0xAE, 0x1E, 0xAE, 0x1E, 0xB0, 0x1E, 0xB0, 0x1E, 0xB2, 0x1E, 0xB2, 0x1E, + 0xB4, 0x1E, 0xB4, 0x1E, 0xB6, 0x1E, 0xB6, 0x1E, 0xB8, 0x1E, 0xB8, 0x1E, 0xBA, 0x1E, 0xBA, 0x1E, + 0xBC, 0x1E, 0xBC, 0x1E, 0xBE, 0x1E, 0xBE, 0x1E, 0xC0, 0x1E, 0xC0, 0x1E, 0xC2, 0x1E, 0xC2, 0x1E, + 0xC4, 0x1E, 0xC4, 0x1E, 0xC6, 0x1E, 0xC6, 0x1E, 0xC8, 0x1E, 0xC8, 0x1E, 0xCA, 0x1E, 0xCA, 0x1E, + 0xCC, 0x1E, 0xCC, 0x1E, 0xCE, 0x1E, 0xCE, 0x1E, 0xD0, 0x1E, 0xD0, 0x1E, 0xD2, 0x1E, 0xD2, 0x1E, + 0xD4, 0x1E, 0xD4, 0x1E, 0xD6, 0x1E, 0xD6, 0x1E, 0xD8, 0x1E, 0xD8, 0x1E, 0xDA, 0x1E, 0xDA, 0x1E, + 0xDC, 0x1E, 0xDC, 0x1E, 0xDE, 0x1E, 0xDE, 0x1E, 0xE0, 0x1E, 0xE0, 0x1E, 0xE2, 0x1E, 0xE2, 0x1E, + 0xE4, 0x1E, 0xE4, 0x1E, 0xE6, 0x1E, 0xE6, 0x1E, 0xE8, 0x1E, 0xE8, 0x1E, 0xEA, 0x1E, 0xEA, 0x1E, + 0xEC, 0x1E, 0xEC, 0x1E, 0xEE, 0x1E, 0xEE, 0x1E, 0xF0, 0x1E, 0xF0, 0x1E, 0xF2, 0x1E, 0xF2, 0x1E, + 0xF4, 0x1E, 0xF4, 0x1E, 0xF6, 0x1E, 0xF6, 0x1E, 0xF8, 0x1E, 0xF8, 0x1E, 0xFA, 0x1E, 0xFB, 0x1E, + 0xFC, 0x1E, 0xFD, 0x1E, 0xFE, 0x1E, 0xFF, 0x1E, 0x08, 0x1F, 0x09, 0x1F, 0x0A, 0x1F, 0x0B, 0x1F, + 0x0C, 0x1F, 0x0D, 0x1F, 0x0E, 0x1F, 0x0F, 0x1F, 0x08, 0x1F, 0x09, 0x1F, 0x0A, 0x1F, 0x0B, 0x1F, + 0x0C, 0x1F, 0x0D, 0x1F, 0x0E, 0x1F, 0x0F, 0x1F, 0x18, 0x1F, 0x19, 0x1F, 0x1A, 0x1F, 0x1B, 0x1F, + 0x1C, 0x1F, 0x1D, 0x1F, 0x16, 0x1F, 0x17, 0x1F, 0x18, 0x1F, 0x19, 0x1F, 0x1A, 0x1F, 0x1B, 0x1F, + 0x1C, 0x1F, 0x1D, 0x1F, 0x1E, 0x1F, 0x1F, 0x1F, 0x28, 0x1F, 0x29, 0x1F, 0x2A, 0x1F, 0x2B, 0x1F, + 0x2C, 0x1F, 0x2D, 0x1F, 0x2E, 0x1F, 0x2F, 0x1F, 0x28, 0x1F, 0x29, 0x1F, 0x2A, 0x1F, 0x2B, 0x1F, + 0x2C, 0x1F, 0x2D, 0x1F, 0x2E, 0x1F, 0x2F, 0x1F, 0x38, 0x1F, 0x39, 0x1F, 0x3A, 0x1F, 0x3B, 0x1F, + 0x3C, 0x1F, 0x3D, 0x1F, 0x3E, 0x1F, 0x3F, 0x1F, 0x38, 0x1F, 0x39, 0x1F, 0x3A, 0x1F, 0x3B, 0x1F, + 0x3C, 0x1F, 0x3D, 0x1F, 0x3E, 0x1F, 0x3F, 0x1F, 0x48, 0x1F, 0x49, 0x1F, 0x4A, 0x1F, 0x4B, 0x1F, + 0x4C, 0x1F, 0x4D, 0x1F, 0x46, 0x1F, 0x47, 0x1F, 0x48, 0x1F, 0x49, 0x1F, 0x4A, 0x1F, 0x4B, 0x1F, + 0x4C, 0x1F, 0x4D, 0x1F, 0x4E, 0x1F, 0x4F, 0x1F, 0x50, 0x1F, 0x59, 0x1F, 0x52, 0x1F, 0x5B, 0x1F, + 0x54, 0x1F, 0x5D, 0x1F, 0x56, 0x1F, 0x5F, 0x1F, 0x58, 0x1F, 0x59, 0x1F, 0x5A, 0x1F, 0x5B, 0x1F, + 0x5C, 0x1F, 0x5D, 0x1F, 0x5E, 0x1F, 0x5F, 0x1F, 0x68, 0x1F, 0x69, 0x1F, 0x6A, 0x1F, 0x6B, 0x1F, + 0x6C, 0x1F, 0x6D, 0x1F, 0x6E, 0x1F, 0x6F, 0x1F, 0x68, 0x1F, 0x69, 0x1F, 0x6A, 0x1F, 0x6B, 0x1F, + 0x6C, 0x1F, 0x6D, 0x1F, 0x6E, 0x1F, 0x6F, 0x1F, 0xBA, 0x1F, 0xBB, 0x1F, 0xC8, 0x1F, 0xC9, 0x1F, + 0xCA, 0x1F, 0xCB, 0x1F, 0xDA, 0x1F, 0xDB, 0x1F, 0xF8, 0x1F, 0xF9, 0x1F, 0xEA, 0x1F, 0xEB, 0x1F, + 0xFA, 0x1F, 0xFB, 0x1F, 0x7E, 0x1F, 0x7F, 0x1F, 0x88, 0x1F, 0x89, 0x1F, 0x8A, 0x1F, 0x8B, 0x1F, + 0x8C, 0x1F, 0x8D, 0x1F, 0x8E, 0x1F, 0x8F, 0x1F, 0x88, 0x1F, 0x89, 0x1F, 0x8A, 0x1F, 0x8B, 0x1F, + 0x8C, 0x1F, 0x8D, 0x1F, 0x8E, 0x1F, 0x8F, 0x1F, 0x98, 0x1F, 0x99, 0x1F, 0x9A, 0x1F, 0x9B, 0x1F, + 0x9C, 0x1F, 0x9D, 0x1F, 0x9E, 0x1F, 0x9F, 0x1F, 0x98, 0x1F, 0x99, 0x1F, 0x9A, 0x1F, 0x9B, 0x1F, + 0x9C, 0x1F, 0x9D, 0x1F, 0x9E, 0x1F, 0x9F, 0x1F, 0xA8, 0x1F, 0xA9, 0x1F, 0xAA, 0x1F, 0xAB, 0x1F, + 0xAC, 0x1F, 0xAD, 0x1F, 0xAE, 0x1F, 0xAF, 0x1F, 0xA8, 0x1F, 0xA9, 0x1F, 0xAA, 0x1F, 0xAB, 0x1F, + 0xAC, 0x1F, 0xAD, 0x1F, 0xAE, 0x1F, 0xAF, 0x1F, 0xB8, 0x1F, 0xB9, 0x1F, 0xB2, 0x1F, 0xBC, 0x1F, + 0xB4, 0x1F, 0xB5, 0x1F, 0xB6, 0x1F, 0xB7, 0x1F, 0xB8, 0x1F, 0xB9, 0x1F, 0xBA, 0x1F, 0xBB, 0x1F, + 0xBC, 0x1F, 0xBD, 0x1F, 0xBE, 0x1F, 0xBF, 0x1F, 0xC0, 0x1F, 0xC1, 0x1F, 0xC2, 0x1F, 0xC3, 0x1F, + 0xC4, 0x1F, 0xC5, 0x1F, 0xC6, 0x1F, 0xC7, 0x1F, 0xC8, 0x1F, 0xC9, 0x1F, 0xCA, 0x1F, 0xCB, 0x1F, + 0xC3, 0x1F, 0xCD, 0x1F, 0xCE, 0x1F, 0xCF, 0x1F, 0xD8, 0x1F, 0xD9, 0x1F, 0xD2, 0x1F, 0xD3, 0x1F, + 0xD4, 0x1F, 0xD5, 0x1F, 0xD6, 0x1F, 0xD7, 0x1F, 0xD8, 0x1F, 0xD9, 0x1F, 0xDA, 0x1F, 0xDB, 0x1F, + 0xDC, 0x1F, 0xDD, 0x1F, 0xDE, 0x1F, 0xDF, 0x1F, 0xE8, 0x1F, 0xE9, 0x1F, 0xE2, 0x1F, 0xE3, 0x1F, + 0xE4, 0x1F, 0xEC, 0x1F, 0xE6, 0x1F, 0xE7, 0x1F, 0xE8, 0x1F, 0xE9, 0x1F, 0xEA, 0x1F, 0xEB, 0x1F, + 0xEC, 0x1F, 0xED, 0x1F, 0xEE, 0x1F, 0xEF, 0x1F, 0xF0, 0x1F, 0xF1, 0x1F, 0xF2, 0x1F, 0xF3, 0x1F, + 0xF4, 0x1F, 0xF5, 0x1F, 0xF6, 0x1F, 0xF7, 0x1F, 0xF8, 0x1F, 0xF9, 0x1F, 0xFA, 0x1F, 0xFB, 0x1F, + 0xF3, 0x1F, 0xFD, 0x1F, 0xFE, 0x1F, 0xFF, 0x1F, 0x00, 0x20, 0x01, 0x20, 0x02, 0x20, 0x03, 0x20, + 0x04, 0x20, 0x05, 0x20, 0x06, 0x20, 0x07, 0x20, 0x08, 0x20, 0x09, 0x20, 0x0A, 0x20, 0x0B, 0x20, + 0x0C, 0x20, 0x0D, 0x20, 0x0E, 0x20, 0x0F, 0x20, 0x10, 0x20, 0x11, 0x20, 0x12, 0x20, 0x13, 0x20, + 0x14, 0x20, 0x15, 0x20, 0x16, 0x20, 0x17, 0x20, 0x18, 0x20, 0x19, 0x20, 0x1A, 0x20, 0x1B, 0x20, + 0x1C, 0x20, 0x1D, 0x20, 0x1E, 0x20, 0x1F, 0x20, 0x20, 0x20, 0x21, 0x20, 0x22, 0x20, 0x23, 0x20, + 0x24, 0x20, 0x25, 0x20, 0x26, 0x20, 0x27, 0x20, 0x28, 0x20, 0x29, 0x20, 0x2A, 0x20, 0x2B, 0x20, + 0x2C, 0x20, 0x2D, 0x20, 0x2E, 0x20, 0x2F, 0x20, 0x30, 0x20, 0x31, 0x20, 0x32, 0x20, 0x33, 0x20, + 0x34, 0x20, 0x35, 0x20, 0x36, 0x20, 0x37, 0x20, 0x38, 0x20, 0x39, 0x20, 0x3A, 0x20, 0x3B, 0x20, + 0x3C, 0x20, 0x3D, 0x20, 0x3E, 0x20, 0x3F, 0x20, 0x40, 0x20, 0x41, 0x20, 0x42, 0x20, 0x43, 0x20, + 0x44, 0x20, 0x45, 0x20, 0x46, 0x20, 0x47, 0x20, 0x48, 0x20, 0x49, 0x20, 0x4A, 0x20, 0x4B, 0x20, + 0x4C, 0x20, 0x4D, 0x20, 0x4E, 0x20, 0x4F, 0x20, 0x50, 0x20, 0x51, 0x20, 0x52, 0x20, 0x53, 0x20, + 0x54, 0x20, 0x55, 0x20, 0x56, 0x20, 0x57, 0x20, 0x58, 0x20, 0x59, 0x20, 0x5A, 0x20, 0x5B, 0x20, + 0x5C, 0x20, 0x5D, 0x20, 0x5E, 0x20, 0x5F, 0x20, 0x60, 0x20, 0x61, 0x20, 0x62, 0x20, 0x63, 0x20, + 0x64, 0x20, 0x65, 0x20, 0x66, 0x20, 0x67, 0x20, 0x68, 0x20, 0x69, 0x20, 0x6A, 0x20, 0x6B, 0x20, + 0x6C, 0x20, 0x6D, 0x20, 0x6E, 0x20, 0x6F, 0x20, 0x70, 0x20, 0x71, 0x20, 0x72, 0x20, 0x73, 0x20, + 0x74, 0x20, 0x75, 0x20, 0x76, 0x20, 0x77, 0x20, 0x78, 0x20, 0x79, 0x20, 0x7A, 0x20, 0x7B, 0x20, + 0x7C, 0x20, 0x7D, 0x20, 0x7E, 0x20, 0x7F, 0x20, 0x80, 0x20, 0x81, 0x20, 0x82, 0x20, 0x83, 0x20, + 0x84, 0x20, 0x85, 0x20, 0x86, 0x20, 0x87, 0x20, 0x88, 0x20, 0x89, 0x20, 0x8A, 0x20, 0x8B, 0x20, + 0x8C, 0x20, 0x8D, 0x20, 0x8E, 0x20, 0x8F, 0x20, 0x90, 0x20, 0x91, 0x20, 0x92, 0x20, 0x93, 0x20, + 0x94, 0x20, 0x95, 0x20, 0x96, 0x20, 0x97, 0x20, 0x98, 0x20, 0x99, 0x20, 0x9A, 0x20, 0x9B, 0x20, + 0x9C, 0x20, 0x9D, 0x20, 0x9E, 0x20, 0x9F, 0x20, 0xA0, 0x20, 0xA1, 0x20, 0xA2, 0x20, 0xA3, 0x20, + 0xA4, 0x20, 0xA5, 0x20, 0xA6, 0x20, 0xA7, 0x20, 0xA8, 0x20, 0xA9, 0x20, 0xAA, 0x20, 0xAB, 0x20, + 0xAC, 0x20, 0xAD, 0x20, 0xAE, 0x20, 0xAF, 0x20, 0xB0, 0x20, 0xB1, 0x20, 0xB2, 0x20, 0xB3, 0x20, + 0xB4, 0x20, 0xB5, 0x20, 0xB6, 0x20, 0xB7, 0x20, 0xB8, 0x20, 0xB9, 0x20, 0xBA, 0x20, 0xBB, 0x20, + 0xBC, 0x20, 0xBD, 0x20, 0xBE, 0x20, 0xBF, 0x20, 0xC0, 0x20, 0xC1, 0x20, 0xC2, 0x20, 0xC3, 0x20, + 0xC4, 0x20, 0xC5, 0x20, 0xC6, 0x20, 0xC7, 0x20, 0xC8, 0x20, 0xC9, 0x20, 0xCA, 0x20, 0xCB, 0x20, + 0xCC, 0x20, 0xCD, 0x20, 0xCE, 0x20, 0xCF, 0x20, 0xD0, 0x20, 0xD1, 0x20, 0xD2, 0x20, 0xD3, 0x20, + 0xD4, 0x20, 0xD5, 0x20, 0xD6, 0x20, 0xD7, 0x20, 0xD8, 0x20, 0xD9, 0x20, 0xDA, 0x20, 0xDB, 0x20, + 0xDC, 0x20, 0xDD, 0x20, 0xDE, 0x20, 0xDF, 0x20, 0xE0, 0x20, 0xE1, 0x20, 0xE2, 0x20, 0xE3, 0x20, + 0xE4, 0x20, 0xE5, 0x20, 0xE6, 0x20, 0xE7, 0x20, 0xE8, 0x20, 0xE9, 0x20, 0xEA, 0x20, 0xEB, 0x20, + 0xEC, 0x20, 0xED, 0x20, 0xEE, 0x20, 0xEF, 0x20, 0xF0, 0x20, 0xF1, 0x20, 0xF2, 0x20, 0xF3, 0x20, + 0xF4, 0x20, 0xF5, 0x20, 0xF6, 0x20, 0xF7, 0x20, 0xF8, 0x20, 0xF9, 0x20, 0xFA, 0x20, 0xFB, 0x20, + 0xFC, 0x20, 0xFD, 0x20, 0xFE, 0x20, 0xFF, 0x20, 0x00, 0x21, 0x01, 0x21, 0x02, 0x21, 0x03, 0x21, + 0x04, 0x21, 0x05, 0x21, 0x06, 0x21, 0x07, 0x21, 0x08, 0x21, 0x09, 0x21, 0x0A, 0x21, 0x0B, 0x21, + 0x0C, 0x21, 0x0D, 0x21, 0x0E, 0x21, 0x0F, 0x21, 0x10, 0x21, 0x11, 0x21, 0x12, 0x21, 0x13, 0x21, + 0x14, 0x21, 0x15, 0x21, 0x16, 0x21, 0x17, 0x21, 0x18, 0x21, 0x19, 0x21, 0x1A, 0x21, 0x1B, 0x21, + 0x1C, 0x21, 0x1D, 0x21, 0x1E, 0x21, 0x1F, 0x21, 0x20, 0x21, 0x21, 0x21, 0x22, 0x21, 0x23, 0x21, + 0x24, 0x21, 0x25, 0x21, 0x26, 0x21, 0x27, 0x21, 0x28, 0x21, 0x29, 0x21, 0x2A, 0x21, 0x2B, 0x21, + 0x2C, 0x21, 0x2D, 0x21, 0x2E, 0x21, 0x2F, 0x21, 0x30, 0x21, 0x31, 0x21, 0x32, 0x21, 0x33, 0x21, + 0x34, 0x21, 0x35, 0x21, 0x36, 0x21, 0x37, 0x21, 0x38, 0x21, 0x39, 0x21, 0x3A, 0x21, 0x3B, 0x21, + 0x3C, 0x21, 0x3D, 0x21, 0x3E, 0x21, 0x3F, 0x21, 0x40, 0x21, 0x41, 0x21, 0x42, 0x21, 0x43, 0x21, + 0x44, 0x21, 0x45, 0x21, 0x46, 0x21, 0x47, 0x21, 0x48, 0x21, 0x49, 0x21, 0x4A, 0x21, 0x4B, 0x21, + 0x4C, 0x21, 0x4D, 0x21, 0x32, 0x21, 0x4F, 0x21, 0x50, 0x21, 0x51, 0x21, 0x52, 0x21, 0x53, 0x21, + 0x54, 0x21, 0x55, 0x21, 0x56, 0x21, 0x57, 0x21, 0x58, 0x21, 0x59, 0x21, 0x5A, 0x21, 0x5B, 0x21, + 0x5C, 0x21, 0x5D, 0x21, 0x5E, 0x21, 0x5F, 0x21, 0x60, 0x21, 0x61, 0x21, 0x62, 0x21, 0x63, 0x21, + 0x64, 0x21, 0x65, 0x21, 0x66, 0x21, 0x67, 0x21, 0x68, 0x21, 0x69, 0x21, 0x6A, 0x21, 0x6B, 0x21, + 0x6C, 0x21, 0x6D, 0x21, 0x6E, 0x21, 0x6F, 0x21, 0x60, 0x21, 0x61, 0x21, 0x62, 0x21, 0x63, 0x21, + 0x64, 0x21, 0x65, 0x21, 0x66, 0x21, 0x67, 0x21, 0x68, 0x21, 0x69, 0x21, 0x6A, 0x21, 0x6B, 0x21, + 0x6C, 0x21, 0x6D, 0x21, 0x6E, 0x21, 0x6F, 0x21, 0x80, 0x21, 0x81, 0x21, 0x82, 0x21, 0x83, 0x21, + 0x83, 0x21, 0xFF, 0xFF, 0x4B, 0x03, 0xB6, 0x24, 0xB7, 0x24, 0xB8, 0x24, 0xB9, 0x24, 0xBA, 0x24, + 0xBB, 0x24, 0xBC, 0x24, 0xBD, 0x24, 0xBE, 0x24, 0xBF, 0x24, 0xC0, 0x24, 0xC1, 0x24, 0xC2, 0x24, + 0xC3, 0x24, 0xC4, 0x24, 0xC5, 0x24, 0xC6, 0x24, 0xC7, 0x24, 0xC8, 0x24, 0xC9, 0x24, 0xCA, 0x24, + 0xCB, 0x24, 0xCC, 0x24, 0xCD, 0x24, 0xCE, 0x24, 0xCF, 0x24, 0xFF, 0xFF, 0x46, 0x07, 0x00, 0x2C, + 0x01, 0x2C, 0x02, 0x2C, 0x03, 0x2C, 0x04, 0x2C, 0x05, 0x2C, 0x06, 0x2C, 0x07, 0x2C, 0x08, 0x2C, + 0x09, 0x2C, 0x0A, 0x2C, 0x0B, 0x2C, 0x0C, 0x2C, 0x0D, 0x2C, 0x0E, 0x2C, 0x0F, 0x2C, 0x10, 0x2C, + 0x11, 0x2C, 0x12, 0x2C, 0x13, 0x2C, 0x14, 0x2C, 0x15, 0x2C, 0x16, 0x2C, 0x17, 0x2C, 0x18, 0x2C, + 0x19, 0x2C, 0x1A, 0x2C, 0x1B, 0x2C, 0x1C, 0x2C, 0x1D, 0x2C, 0x1E, 0x2C, 0x1F, 0x2C, 0x20, 0x2C, + 0x21, 0x2C, 0x22, 0x2C, 0x23, 0x2C, 0x24, 0x2C, 0x25, 0x2C, 0x26, 0x2C, 0x27, 0x2C, 0x28, 0x2C, + 0x29, 0x2C, 0x2A, 0x2C, 0x2B, 0x2C, 0x2C, 0x2C, 0x2D, 0x2C, 0x2E, 0x2C, 0x5F, 0x2C, 0x60, 0x2C, + 0x60, 0x2C, 0x62, 0x2C, 0x63, 0x2C, 0x64, 0x2C, 0x65, 0x2C, 0x66, 0x2C, 0x67, 0x2C, 0x67, 0x2C, + 0x69, 0x2C, 0x69, 0x2C, 0x6B, 0x2C, 0x6B, 0x2C, 0x6D, 0x2C, 0x6E, 0x2C, 0x6F, 0x2C, 0x70, 0x2C, + 0x71, 0x2C, 0x72, 0x2C, 0x73, 0x2C, 0x74, 0x2C, 0x75, 0x2C, 0x75, 0x2C, 0x77, 0x2C, 0x78, 0x2C, + 0x79, 0x2C, 0x7A, 0x2C, 0x7B, 0x2C, 0x7C, 0x2C, 0x7D, 0x2C, 0x7E, 0x2C, 0x7F, 0x2C, 0x80, 0x2C, + 0x80, 0x2C, 0x82, 0x2C, 0x82, 0x2C, 0x84, 0x2C, 0x84, 0x2C, 0x86, 0x2C, 0x86, 0x2C, 0x88, 0x2C, + 0x88, 0x2C, 0x8A, 0x2C, 0x8A, 0x2C, 0x8C, 0x2C, 0x8C, 0x2C, 0x8E, 0x2C, 0x8E, 0x2C, 0x90, 0x2C, + 0x90, 0x2C, 0x92, 0x2C, 0x92, 0x2C, 0x94, 0x2C, 0x94, 0x2C, 0x96, 0x2C, 0x96, 0x2C, 0x98, 0x2C, + 0x98, 0x2C, 0x9A, 0x2C, 0x9A, 0x2C, 0x9C, 0x2C, 0x9C, 0x2C, 0x9E, 0x2C, 0x9E, 0x2C, 0xA0, 0x2C, + 0xA0, 0x2C, 0xA2, 0x2C, 0xA2, 0x2C, 0xA4, 0x2C, 0xA4, 0x2C, 0xA6, 0x2C, 0xA6, 0x2C, 0xA8, 0x2C, + 0xA8, 0x2C, 0xAA, 0x2C, 0xAA, 0x2C, 0xAC, 0x2C, 0xAC, 0x2C, 0xAE, 0x2C, 0xAE, 0x2C, 0xB0, 0x2C, + 0xB0, 0x2C, 0xB2, 0x2C, 0xB2, 0x2C, 0xB4, 0x2C, 0xB4, 0x2C, 0xB6, 0x2C, 0xB6, 0x2C, 0xB8, 0x2C, + 0xB8, 0x2C, 0xBA, 0x2C, 0xBA, 0x2C, 0xBC, 0x2C, 0xBC, 0x2C, 0xBE, 0x2C, 0xBE, 0x2C, 0xC0, 0x2C, + 0xC0, 0x2C, 0xC2, 0x2C, 0xC2, 0x2C, 0xC4, 0x2C, 0xC4, 0x2C, 0xC6, 0x2C, 0xC6, 0x2C, 0xC8, 0x2C, + 0xC8, 0x2C, 0xCA, 0x2C, 0xCA, 0x2C, 0xCC, 0x2C, 0xCC, 0x2C, 0xCE, 0x2C, 0xCE, 0x2C, 0xD0, 0x2C, + 0xD0, 0x2C, 0xD2, 0x2C, 0xD2, 0x2C, 0xD4, 0x2C, 0xD4, 0x2C, 0xD6, 0x2C, 0xD6, 0x2C, 0xD8, 0x2C, + 0xD8, 0x2C, 0xDA, 0x2C, 0xDA, 0x2C, 0xDC, 0x2C, 0xDC, 0x2C, 0xDE, 0x2C, 0xDE, 0x2C, 0xE0, 0x2C, + 0xE0, 0x2C, 0xE2, 0x2C, 0xE2, 0x2C, 0xE4, 0x2C, 0xE5, 0x2C, 0xE6, 0x2C, 0xE7, 0x2C, 0xE8, 0x2C, + 0xE9, 0x2C, 0xEA, 0x2C, 0xEB, 0x2C, 0xEC, 0x2C, 0xED, 0x2C, 0xEE, 0x2C, 0xEF, 0x2C, 0xF0, 0x2C, + 0xF1, 0x2C, 0xF2, 0x2C, 0xF3, 0x2C, 0xF4, 0x2C, 0xF5, 0x2C, 0xF6, 0x2C, 0xF7, 0x2C, 0xF8, 0x2C, + 0xF9, 0x2C, 0xFA, 0x2C, 0xFB, 0x2C, 0xFC, 0x2C, 0xFD, 0x2C, 0xFE, 0x2C, 0xFF, 0x2C, 0xA0, 0x10, + 0xA1, 0x10, 0xA2, 0x10, 0xA3, 0x10, 0xA4, 0x10, 0xA5, 0x10, 0xA6, 0x10, 0xA7, 0x10, 0xA8, 0x10, + 0xA9, 0x10, 0xAA, 0x10, 0xAB, 0x10, 0xAC, 0x10, 0xAD, 0x10, 0xAE, 0x10, 0xAF, 0x10, 0xB0, 0x10, + 0xB1, 0x10, 0xB2, 0x10, 0xB3, 0x10, 0xB4, 0x10, 0xB5, 0x10, 0xB6, 0x10, 0xB7, 0x10, 0xB8, 0x10, + 0xB9, 0x10, 0xBA, 0x10, 0xBB, 0x10, 0xBC, 0x10, 0xBD, 0x10, 0xBE, 0x10, 0xBF, 0x10, 0xC0, 0x10, + 0xC1, 0x10, 0xC2, 0x10, 0xC3, 0x10, 0xC4, 0x10, 0xC5, 0x10, 0xFF, 0xFF, 0x1B, 0xD2, 0x21, 0xFF, + 0x22, 0xFF, 0x23, 0xFF, 0x24, 0xFF, 0x25, 0xFF, 0x26, 0xFF, 0x27, 0xFF, 0x28, 0xFF, 0x29, 0xFF, + 0x2A, 0xFF, 0x2B, 0xFF, 0x2C, 0xFF, 0x2D, 0xFF, 0x2E, 0xFF, 0x2F, 0xFF, 0x30, 0xFF, 0x31, 0xFF, + 0x32, 0xFF, 0x33, 0xFF, 0x34, 0xFF, 0x35, 0xFF, 0x36, 0xFF, 0x37, 0xFF, 0x38, 0xFF, 0x39, 0xFF, + 0x3A, 0xFF, 0x5B, 0xFF, 0x5C, 0xFF, 0x5D, 0xFF, 0x5E, 0xFF, 0x5F, 0xFF, 0x60, 0xFF, 0x61, 0xFF, + 0x62, 0xFF, 0x63, 0xFF, 0x64, 0xFF, 0x65, 0xFF, 0x66, 0xFF, 0x67, 0xFF, 0x68, 0xFF, 0x69, 0xFF, + 0x6A, 0xFF, 0x6B, 0xFF, 0x6C, 0xFF, 0x6D, 0xFF, 0x6E, 0xFF, 0x6F, 0xFF, 0x70, 0xFF, 0x71, 0xFF, + 0x72, 0xFF, 0x73, 0xFF, 0x74, 0xFF, 0x75, 0xFF, 0x76, 0xFF, 0x77, 0xFF, 0x78, 0xFF, 0x79, 0xFF, + 0x7A, 0xFF, 0x7B, 0xFF, 0x7C, 0xFF, 0x7D, 0xFF, 0x7E, 0xFF, 0x7F, 0xFF, 0x80, 0xFF, 0x81, 0xFF, + 0x82, 0xFF, 0x83, 0xFF, 0x84, 0xFF, 0x85, 0xFF, 0x86, 0xFF, 0x87, 0xFF, 0x88, 0xFF, 0x89, 0xFF, + 0x8A, 0xFF, 0x8B, 0xFF, 0x8C, 0xFF, 0x8D, 0xFF, 0x8E, 0xFF, 0x8F, 0xFF, 0x90, 0xFF, 0x91, 0xFF, + 0x92, 0xFF, 0x93, 0xFF, 0x94, 0xFF, 0x95, 0xFF, 0x96, 0xFF, 0x97, 0xFF, 0x98, 0xFF, 0x99, 0xFF, + 0x9A, 0xFF, 0x9B, 0xFF, 0x9C, 0xFF, 0x9D, 0xFF, 0x9E, 0xFF, 0x9F, 0xFF, 0xA0, 0xFF, 0xA1, 0xFF, + 0xA2, 0xFF, 0xA3, 0xFF, 0xA4, 0xFF, 0xA5, 0xFF, 0xA6, 0xFF, 0xA7, 0xFF, 0xA8, 0xFF, 0xA9, 0xFF, + 0xAA, 0xFF, 0xAB, 0xFF, 0xAC, 0xFF, 0xAD, 0xFF, 0xAE, 0xFF, 0xAF, 0xFF, 0xB0, 0xFF, 0xB1, 0xFF, + 0xB2, 0xFF, 0xB3, 0xFF, 0xB4, 0xFF, 0xB5, 0xFF, 0xB6, 0xFF, 0xB7, 0xFF, 0xB8, 0xFF, 0xB9, 0xFF, + 0xBA, 0xFF, 0xBB, 0xFF, 0xBC, 0xFF, 0xBD, 0xFF, 0xBE, 0xFF, 0xBF, 0xFF, 0xC0, 0xFF, 0xC1, 0xFF, + 0xC2, 0xFF, 0xC3, 0xFF, 0xC4, 0xFF, 0xC5, 0xFF, 0xC6, 0xFF, 0xC7, 0xFF, 0xC8, 0xFF, 0xC9, 0xFF, + 0xCA, 0xFF, 0xCB, 0xFF, 0xCC, 0xFF, 0xCD, 0xFF, 0xCE, 0xFF, 0xCF, 0xFF, 0xD0, 0xFF, 0xD1, 0xFF, + 0xD2, 0xFF, 0xD3, 0xFF, 0xD4, 0xFF, 0xD5, 0xFF, 0xD6, 0xFF, 0xD7, 0xFF, 0xD8, 0xFF, 0xD9, 0xFF, + 0xDA, 0xFF, 0xDB, 0xFF, 0xDC, 0xFF, 0xDD, 0xFF, 0xDE, 0xFF, 0xDF, 0xFF, 0xE0, 0xFF, 0xE1, 0xFF, + 0xE2, 0xFF, 0xE3, 0xFF, 0xE4, 0xFF, 0xE5, 0xFF, 0xE6, 0xFF, 0xE7, 0xFF, 0xE8, 0xFF, 0xE9, 0xFF, + 0xEA, 0xFF, 0xEB, 0xFF, 0xEC, 0xFF, 0xED, 0xFF, 0xEE, 0xFF, 0xEF, 0xFF, 0xF0, 0xFF, 0xF1, 0xFF, + 0xF2, 0xFF, 0xF3, 0xFF, 0xF4, 0xFF, 0xF5, 0xFF, 0xF6, 0xFF, 0xF7, 0xFF, 0xF8, 0xFF, 0xF9, 0xFF, + 0xFA, 0xFF, 0xFB, 0xFF, 0xFC, 0xFF, 0xFD, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF +}; + +/* end of exfat_upcase.c */ diff --git a/fs/exfat/exfat_version.h b/fs/exfat/exfat_version.h new file mode 100644 index 00000000000..44289678311 --- /dev/null +++ b/fs/exfat/exfat_version.h @@ -0,0 +1,19 @@ +/************************************************************************/ +/* */ +/* PROJECT : exFAT & FAT12/16/32 File System */ +/* FILE : exfat_version.h */ +/* PURPOSE : exFAT File Manager */ +/* */ +/*----------------------------------------------------------------------*/ +/* NOTES */ +/* */ +/*----------------------------------------------------------------------*/ +/* REVISION HISTORY */ +/* */ +/* - 2012.02.10 : Release Version 1.1.0 */ +/* - 2012.04.02 : P1 : Change Module License to Samsung Proprietary */ +/* - 2012.06.07 : P2 : Fixed incorrect filename problem */ +/* */ +/************************************************************************/ + +#define EXFAT_VERSION "1.2.5" diff --git a/fs/fuse/control.c b/fs/fuse/control.c index 42593c587d4..2f0b4f34ab9 100644 --- a/fs/fuse/control.c +++ b/fs/fuse/control.c @@ -123,7 +123,7 @@ static ssize_t fuse_conn_max_background_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - unsigned val; + unsigned val = 0; ssize_t ret; ret = fuse_conn_limit_write(file, buf, count, ppos, &val, @@ -160,7 +160,7 @@ static ssize_t fuse_conn_congestion_threshold_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - unsigned val; + unsigned val = 0; ssize_t ret; ret = fuse_conn_limit_write(file, buf, count, ppos, &val, diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c index 0971e921780..2d4fa2f5a2f 100644 --- a/fs/jbd/journal.c +++ b/fs/jbd/journal.c @@ -680,7 +680,7 @@ int journal_bmap(journal_t *journal, unsigned int blocknr, struct journal_head *journal_get_descriptor_buffer(journal_t *journal) { struct buffer_head *bh; - unsigned int blocknr; + unsigned int blocknr = 0; int err; err = journal_next_log_block(journal, &blocknr); @@ -824,7 +824,7 @@ journal_t * journal_init_inode (struct inode *inode) journal_t *journal = journal_init_common(); int err; int n; - unsigned int blocknr; + unsigned int blocknr = 0; if (!journal) return NULL; @@ -936,7 +936,7 @@ static int journal_reset(journal_t *journal) **/ int journal_create(journal_t *journal) { - unsigned int blocknr; + unsigned int blocknr = 0; struct buffer_head *bh; journal_superblock_t *sb; int i, err; diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index 1afb701622b..2791a222bd7 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c @@ -667,7 +667,7 @@ int jbd2_log_wait_commit(journal_t *journal, tid_t tid) int jbd2_journal_next_log_block(journal_t *journal, unsigned long long *retp) { - unsigned long blocknr; + unsigned long blocknr = 0; write_lock(&journal->j_state_lock); J_ASSERT(journal->j_free > 1); @@ -724,7 +724,7 @@ int jbd2_journal_bmap(journal_t *journal, unsigned long blocknr, struct journal_head *jbd2_journal_get_descriptor_buffer(journal_t *journal) { struct buffer_head *bh; - unsigned long long blocknr; + unsigned long long blocknr = 0; int err; err = jbd2_journal_next_log_block(journal, &blocknr); @@ -1098,7 +1098,7 @@ journal_t * jbd2_journal_init_inode (struct inode *inode) char *p; int err; int n; - unsigned long long blocknr; + unsigned long long blocknr = 0; if (!journal) return NULL; diff --git a/fs/namei.c b/fs/namei.c index c42791914f8..4a353b8aad1 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -2743,7 +2743,7 @@ int vfs_rmdir(struct inode *dir, struct dentry *dentry) static long do_rmdir(int dfd, const char __user *pathname) { int error = 0; - char * name; + char * name = NULL; struct dentry *dentry; struct nameidata nd; @@ -2839,7 +2839,7 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry) static long do_unlinkat(int dfd, const char __user *pathname) { int error; - char *name; + char *name = NULL; struct dentry *dentry; struct nameidata nd; struct inode *inode = NULL; @@ -3239,8 +3239,8 @@ SYSCALL_DEFINE4(renameat, int, olddfd, const char __user *, oldname, struct dentry *old_dentry, *new_dentry; struct dentry *trap; struct nameidata oldnd, newnd; - char *from; - char *to; + char *from = NULL; + char *to = NULL; int error; error = user_path_parent(olddfd, oldname, &oldnd, &from); diff --git a/fs/namespace.c b/fs/namespace.c index e6081996c9a..0968eb5d8f5 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -2141,6 +2141,35 @@ long do_mount(char *dev_name, char *dir_name, char *type_page, if (data_page) ((char *)data_page)[PAGE_SIZE - 1] = 0; +#ifdef CONFIG_RESTRICT_ROOTFS_SLAVE + /* Check if this is an attempt to mark "/" as recursive-slave. */ + if (strcmp(dir_name, "/") == 0 && flags == (MS_SLAVE | MS_REC)) { + static const char storage[] = "/storage"; + static const char source[] = "/mnt/shell/emulated"; + long res; + + /* Mark /storage as recursive-slave instead. */ + if ((res = do_mount(NULL, (char *)storage, NULL, (MS_SLAVE | MS_REC), NULL)) == 0) { + /* Unfortunately bind mounts from outside /storage may retain the + * recursive-shared property (bug?). This means any additional + * namespace-specific bind mounts (e.g., /storage/emulated/0/Android/obb) + * will also appear, shared in all namespaces, at their respective source + * paths (e.g., /mnt/shell/emulated/0/Android/obb), possibly leading to + * hundreds of /proc/mounts-visible bind mounts. As a workaround, mark + * /mnt/shell/emulated also as recursive-slave so that subsequent bind + * mounts are confined to their namespaces. */ + if ((res = do_mount(NULL, (char *)source, NULL, (MS_SLAVE | MS_REC), NULL)) == 0) + /* Both paths successfully marked as slave, leave the rest of the + * filesystem hierarchy alone. */ + return 0; + else + pr_warn("Failed to mount %s as MS_SLAVE: %ld\n", source, res); + } else { + pr_warn("Failed to mount %s as MS_SLAVE: %ld\n", storage, res); + } + /* Fallback: Mark rootfs as recursive-slave as requested. */ + } +#endif /* ... and get the mountpoint */ retval = kern_path(dir_name, LOOKUP_FOLLOW, &path); if (retval) @@ -2361,9 +2390,9 @@ SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name, char __user *, type, unsigned long, flags, void __user *, data) { int ret; - char *kernel_type; + char *kernel_type = NULL; char *kernel_dir; - char *kernel_dev; + char *kernel_dev = NULL; unsigned long data_page; ret = copy_mount_string(type, &kernel_type); diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index e8bbfa5b350..2c0c609a45a 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -79,7 +79,7 @@ int nfs_wait_bit_killable(void *word) { if (fatal_signal_pending(current)) return -ERESTARTSYS; - freezable_schedule(); + freezable_schedule_unsafe(); return 0; } diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index 5242eae6711..2ab36b4caa6 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c @@ -33,7 +33,7 @@ nfs3_rpc_wrapper(struct rpc_clnt *clnt, struct rpc_message *msg, int flags) res = rpc_call_sync(clnt, msg, flags); if (res != -EJUKEBOX && res != -EKEYEXPIRED) break; - freezable_schedule_timeout_killable(NFS_JUKEBOX_RETRY_TIME); + freezable_schedule_timeout_killable_unsafe(NFS_JUKEBOX_RETRY_TIME); res = -ERESTARTSYS; } while (!fatal_signal_pending(current)); return res; diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 99650aaf893..bf6b8dfa3e2 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -248,7 +248,7 @@ static int nfs4_delay(struct rpc_clnt *clnt, long *timeout) *timeout = NFS4_POLL_RETRY_MIN; if (*timeout > NFS4_POLL_RETRY_MAX) *timeout = NFS4_POLL_RETRY_MAX; - freezable_schedule_timeout_killable(*timeout); + freezable_schedule_timeout_killable_unsafe(*timeout); if (fatal_signal_pending(current)) res = -ERESTARTSYS; *timeout <<= 1; @@ -4161,7 +4161,7 @@ int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4 static unsigned long nfs4_set_lock_task_retry(unsigned long timeout) { - freezable_schedule_timeout_killable(timeout); + freezable_schedule_timeout_killable_unsafe(timeout); timeout <<= 1; if (timeout > NFS4_LOCK_MAXTIMEOUT) return NFS4_LOCK_MAXTIMEOUT; diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 061591a3ab0..da47ae766fa 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -2506,18 +2506,15 @@ static ssize_t ocfs2_file_splice_write(struct pipe_inode_info *pipe, ret = sd.num_spliced; if (ret > 0) { - unsigned long nr_pages; int err; - nr_pages = (ret + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; - err = generic_write_sync(out, *ppos, ret); if (err) ret = err; else *ppos += ret; - balance_dirty_pages_ratelimited_nr(mapping, nr_pages); + balance_dirty_pages_ratelimited(mapping); } return ret; diff --git a/fs/proc/loadavg.c b/fs/proc/loadavg.c index 1afa4dd4cae..8d95888b22c 100644 --- a/fs/proc/loadavg.c +++ b/fs/proc/loadavg.c @@ -13,15 +13,17 @@ static int loadavg_proc_show(struct seq_file *m, void *v) { unsigned long avnrun[3]; + unsigned long time_avnrun = avg_nr_running(); get_avenrun(avnrun, FIXED_1/200, 0); - seq_printf(m, "%lu.%02lu %lu.%02lu %lu.%02lu %ld/%d %d\n", + seq_printf(m, "%lu.%02lu %lu.%02lu %lu.%02lu %ld/%d %d %lu.%02lu\n", LOAD_INT(avnrun[0]), LOAD_FRAC(avnrun[0]), LOAD_INT(avnrun[1]), LOAD_FRAC(avnrun[1]), LOAD_INT(avnrun[2]), LOAD_FRAC(avnrun[2]), nr_running(), nr_threads, - task_active_pid_ns(current)->last_pid); + task_active_pid_ns(current)->last_pid, + LOAD_INT(time_avnrun), LOAD_FRAC(time_avnrun)); return 0; } diff --git a/fs/select.c b/fs/select.c index 17d33d09fc1..c4aa6a5971b 100644 --- a/fs/select.c +++ b/fs/select.c @@ -26,7 +26,7 @@ #include #include #include - +#include #include @@ -69,7 +69,6 @@ static long __estimate_accuracy(struct timespec *tv) long select_estimate_accuracy(struct timespec *tv) { - unsigned long ret; struct timespec now; /* @@ -81,10 +80,8 @@ long select_estimate_accuracy(struct timespec *tv) ktime_get_ts(&now); now = timespec_sub(*tv, now); - ret = __estimate_accuracy(&now); - if (ret < current->timer_slack_ns) - return current->timer_slack_ns; - return ret; + return min_t(long, __estimate_accuracy(&now), + task_get_effective_timer_slack(current)); } @@ -236,7 +233,8 @@ int poll_schedule_timeout(struct poll_wqueues *pwq, int state, set_current_state(state); if (!pwq->triggered) - rc = schedule_hrtimeout_range(expires, slack, HRTIMER_MODE_ABS); + rc = freezable_schedule_hrtimeout_range(expires, slack, + HRTIMER_MODE_ABS); __set_current_state(TASK_RUNNING); /* diff --git a/fs/splice.c b/fs/splice.c index f8476841eb0..034567d86b2 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -1016,17 +1016,14 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out, ret = sd.num_spliced; if (ret > 0) { - unsigned long nr_pages; int err; - nr_pages = (ret + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; - err = generic_write_sync(out, *ppos, ret); if (err) ret = err; else *ppos += ret; - balance_dirty_pages_ratelimited_nr(mapping, nr_pages); + balance_dirty_pages_ratelimited(mapping); } return ret; diff --git a/fs/sync.c b/fs/sync.c index 0e8db939d96..1685951792d 100644 --- a/fs/sync.c +++ b/fs/sync.c @@ -17,6 +17,11 @@ #include #include "internal.h" +#ifdef CONFIG_DYNAMIC_FSYNC +extern bool early_suspend_active; +extern bool dyn_fsync_active; +#endif + #define VALID_FLAGS (SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE| \ SYNC_FILE_RANGE_WAIT_AFTER) @@ -86,7 +91,7 @@ static void sync_one_sb(struct super_block *sb, void *arg) * Sync all the data for all the filesystems (called by sys_sync() and * emergency sync) */ -static void sync_filesystems(int wait) +void sync_filesystems(int wait) { iterate_supers(sync_one_sb, &wait); } @@ -95,13 +100,67 @@ static void sync_filesystems(int wait) * sync everything. Start out by waking pdflush, because that writes back * all queues in parallel. */ -SYSCALL_DEFINE0(sync) +static void do_sync(void) { wakeup_flusher_threads(0, WB_REASON_SYNC); sync_filesystems(0); sync_filesystems(1); if (unlikely(laptop_mode)) laptop_sync_completion(); + return; +} + +static DEFINE_MUTEX(sync_mutex); /* One do_sync() at a time. */ +static unsigned long sync_seq; /* Many sync()s from one do_sync(). */ + /* Overflow harmless, extra wait. */ + +/* + * Only allow one task to do sync() at a time, and further allow + * concurrent sync() calls to be satisfied by a single do_sync() + * invocation. + */ +SYSCALL_DEFINE0(sync) +{ + unsigned long snap; + unsigned long snap_done; + + snap = ACCESS_ONCE(sync_seq); + smp_mb(); /* Prevent above from bleeding into critical section. */ + mutex_lock(&sync_mutex); + snap_done = sync_seq; + + /* + * If the value in snap is odd, we need to wait for the current + * do_sync() to complete, then wait for the next one, in other + * words, we need the value of snap_done to be three larger than + * the value of snap. On the other hand, if the value in snap is + * even, we only have to wait for the next request to complete, + * in other words, we need the value of snap_done to be only two + * greater than the value of snap. The "(snap + 3) & 0x1" computes + * this for us (thank you, Linus!). + */ + if (ULONG_CMP_GE(snap_done, (snap + 3) & ~0x1)) { + /* + * A full do_sync() executed between our two fetches from + * sync_seq, so our work is done! + */ + smp_mb(); /* Order test with caller's subsequent code. */ + mutex_unlock(&sync_mutex); + return 0; + } + + /* Record the start of do_sync(). */ + ACCESS_ONCE(sync_seq)++; + WARN_ON_ONCE((sync_seq & 0x1) != 1); + smp_mb(); /* Keep prior increment out of do_sync(). */ + + do_sync(); + + /* Record the end of do_sync(). */ + smp_mb(); /* Keep subsequent increment out of do_sync(). */ + ACCESS_ONCE(sync_seq)++; + WARN_ON_ONCE((sync_seq & 0x1) != 0); + mutex_unlock(&sync_mutex); return 0; } @@ -164,9 +223,17 @@ SYSCALL_DEFINE1(syncfs, int, fd) */ int vfs_fsync_range(struct file *file, loff_t start, loff_t end, int datasync) { +#ifdef CONFIG_DYNAMIC_FSYNC + if (likely(dyn_fsync_active && !early_suspend_active)) + return 0; + else { +#endif if (!file->f_op || !file->f_op->fsync) return -EINVAL; return file->f_op->fsync(file, start, end, datasync); +#ifdef CONFIG_DYNAMIC_FSYNC + } +#endif } EXPORT_SYMBOL(vfs_fsync_range); @@ -188,22 +255,33 @@ static int do_fsync(unsigned int fd, int datasync) { struct file *file; int ret = -EBADF; + int fput_needed; - file = fget(fd); + file = fget_light(fd, &fput_needed); if (file) { ret = vfs_fsync(file, datasync); - fput(file); + fput_light(file, fput_needed); } return ret; } SYSCALL_DEFINE1(fsync, unsigned int, fd) { +#ifdef CONFIG_DYNAMIC_FSYNC + if (likely(dyn_fsync_active && !early_suspend_active)) + return 0; + else +#endif return do_fsync(fd, 0); } SYSCALL_DEFINE1(fdatasync, unsigned int, fd) { +#if 0 + if (likely(dyn_fsync_active && !early_suspend_active)) + return 0; + else +#endif return do_fsync(fd, 1); } @@ -274,6 +352,12 @@ EXPORT_SYMBOL(generic_write_sync); SYSCALL_DEFINE(sync_file_range)(int fd, loff_t offset, loff_t nbytes, unsigned int flags) { +#ifdef CONFIG_DYNAMIC_FSYNC + if (likely(dyn_fsync_active && !early_suspend_active)) + return 0; + else { +#endif + int ret; struct file *file; struct address_space *mapping; @@ -353,6 +437,9 @@ SYSCALL_DEFINE(sync_file_range)(int fd, loff_t offset, loff_t nbytes, fput_light(file, fput_needed); out: return ret; +#ifdef CONFIG_DYNAMIC_FSYNC + } +#endif } #ifdef CONFIG_HAVE_SYSCALL_WRAPPERS asmlinkage long SyS_sync_file_range(long fd, loff_t offset, loff_t nbytes, @@ -369,6 +456,11 @@ SYSCALL_ALIAS(sys_sync_file_range, SyS_sync_file_range); SYSCALL_DEFINE(sync_file_range2)(int fd, unsigned int flags, loff_t offset, loff_t nbytes) { +#ifdef CONFIG_DYNAMIC_FSYNC + if (likely(dyn_fsync_active && !early_suspend_active)) + return 0; + else +#endif return sys_sync_file_range(fd, offset, nbytes, flags); } #ifdef CONFIG_HAVE_SYSCALL_WRAPPERS diff --git a/glitch.sh b/glitch.sh new file mode 100755 index 00000000000..e545e1d1fe5 --- /dev/null +++ b/glitch.sh @@ -0,0 +1,127 @@ +#!/bin/bash + +# Glitch kernel build-script +# +# clean : clean the build directory. +# cleank : clean the built kernel packages +# aosp : build an aosp compatible kernel + +# CM repo path : +repo=~/android/system + +# Toolchain : +export ARCH="arm" +#export CROSS_PREFIX="$repo/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi-" +#export CROSS_PREFIX="$repo/prebuilts/gcc/linux-x86/arm/linaro_4.8.2-2013.09/bin/arm-gnueabi-" +export CROSS_PREFIX="$repo/prebuilts/gcc/linux-x86/arm/sabermod-androideabi-4.8/bin/arm-linux-androideabi-" + +setup () +{ + + if [ x = "x$repo" ] ; then + echo "Android build environment must be configured" + exit 1 + fi + . "$repo"/build/envsetup.sh + +# Arch-dependent definitions + case `uname -s` in + Darwin) + KERNEL_DIR="$(dirname "$(greadlink -f "$0")")" + CROSS_PREFIX="$repo/prebuilts/gcc/darwin-x86/arm/arm-eabi-4.8/bin/arm-eabi-" + ;; + *) + KERNEL_DIR="$(dirname "$(readlink -f "$0")")" + CROSS_PREFIX="$CROSS_PREFIX" + ;; + esac + + BUILD_DIR="../glitch-build/kernel" + + if [ x = "x$NO_CCACHE" ] && ccache -V &>/dev/null ; then + CCACHE=ccache + CCACHE_BASEDIR="$KERNEL_DIR" + CCACHE_COMPRESS=1 + CCACHE_DIR="$repo/kernel/Asus/.ccache" + export CCACHE_DIR CCACHE_COMPRESS CCACHE_BASEDIR + else + CCACHE="" + fi + +} + +build () +{ + + local target=flo + echo "Building for flo" + local target_dir="$BUILD_DIR/flo" + local module + rm -fr "$target_dir" + mkdir -p "$target_dir" + + mka -C "$KERNEL_DIR" O="$target_dir" flo_defconfig HOSTCC="$CCACHE gcc" + mka -C "$KERNEL_DIR" O="$target_dir" HOSTCC="$CCACHE gcc" CROSS_COMPILE="$CCACHE $CROSS_PREFIX" zImage modules + +[[ -d release ]] || { + echo "must be in kernel root dir" + exit 1; +} + +echo "copying modules and zImage" +mkdir -p $KERNEL_DIR/release/aroma/system/lib/modules/ +cd $target_dir +find -name '*.ko' -exec cp -av {} $KERNEL_DIR/release/aroma/system/lib/modules/ \; +"$CROSS_PREFIX"strip --strip-unneeded $KERNEL_DIR/release/aroma/system/lib/modules/* +cd $KERNEL_DIR +mv $target_dir/arch/arm/boot/zImage $KERNEL_DIR/release/aroma/boot/glitch.zImage + +echo "packaging it up" +cd release/aroma + +. $KERNEL_DIR/../rev + +counter=$((counter + 1)) + +mkdir -p $KERNEL_DIR/release/Flashable-flo-AOSP +REL=Glitch-flo-r$counter.zip + + zip -q -r ${REL} boot config META-INF system + #sha256sum ${REL} > ${REL}.sha256sum + mv ${REL}* $KERNEL_DIR/release/Flashable-flo-AOSP/ + +echo counter=$counter > $KERNEL_DIR/../rev; + +rm boot/glitch.zImage +rm -r system/lib/modules/* +cd $KERNEL_DIR +echo "" +echo ${REL} +} + +setup + +if [ "$1" = clean ] ; then + rm -fr "$BUILD_DIR"/* + cd release + rm `find ./ -name '*.*~'` -rf + rm `find ./ -name '*~'` -rf + cd $KERNEL_DIR + echo "" + echo "Old build cleaned" + +else + +if [ "$1" = cleank ] ; then + rm -fr "$KERNEL_DIR"/release/Flashable-flo-AOSP/* + echo "Built kernels cleaned" + +else + +time { + + build flo + +} +fi +fi diff --git a/include/linux/cgroup_subsys.h b/include/linux/cgroup_subsys.h index 0bd390ce98b..535e1ac9835 100644 --- a/include/linux/cgroup_subsys.h +++ b/include/linux/cgroup_subsys.h @@ -72,3 +72,10 @@ SUBSYS(net_prio) #endif /* */ + +#ifdef CONFIG_CGROUP_TIMER_SLACK +SUBSYS(timer_slack) +#endif + +/* */ + diff --git a/include/linux/cpu.h b/include/linux/cpu.h index 11dd01b8f82..1743b63de2c 100644 --- a/include/linux/cpu.h +++ b/include/linux/cpu.h @@ -116,7 +116,7 @@ enum { /* Need to know about CPUs going up/down? */ #if defined(CONFIG_HOTPLUG_CPU) || !defined(MODULE) #define cpu_notifier(fn, pri) { \ - static struct notifier_block fn##_nb __cpuinitdata = \ + static struct notifier_block fn##_nb = \ { .notifier_call = fn, .priority = pri }; \ register_cpu_notifier(&fn##_nb); \ } diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 34edac89eca..1903f2b5e5e 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -379,6 +379,9 @@ extern struct cpufreq_governor cpufreq_gov_conservative; #elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE) extern struct cpufreq_governor cpufreq_gov_interactive; #define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_interactive) +#elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_INTELLIDEMAND) +extern struct cpufreq_governor cpufreq_gov_intellidemand; +#define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_intellidemand) #endif diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index 6c26a3da0e0..fa7d3dcd36f 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h @@ -34,6 +34,7 @@ struct cpuidle_driver; struct cpuidle_state_usage { void *driver_data; + unsigned long long disable; unsigned long long usage; unsigned long long time; /* in US */ }; @@ -46,7 +47,6 @@ struct cpuidle_state { unsigned int exit_latency; /* in US */ int power_usage; /* in mW */ unsigned int target_residency; /* in US */ - unsigned int disable; int (*enter) (struct cpuidle_device *dev, struct cpuidle_driver *drv, @@ -124,9 +124,9 @@ struct cpuidle_driver { const char *name; struct module *owner; - unsigned int power_specified:1; /* set to 1 to use the core cpuidle time keeping (for all states). */ unsigned int en_core_tk_irqen:1; + /* states array must be ordered in decreasing power consumption */ struct cpuidle_state states[CPUIDLE_STATE_MAX]; int state_count; int safe_state_index; diff --git a/include/linux/debug_locks.h b/include/linux/debug_locks.h index 3bd46f76675..a975de1ff59 100644 --- a/include/linux/debug_locks.h +++ b/include/linux/debug_locks.h @@ -51,7 +51,7 @@ struct task_struct; extern void debug_show_all_locks(void); extern void debug_show_held_locks(struct task_struct *task); extern void debug_check_no_locks_freed(const void *from, unsigned long len); -extern void debug_check_no_locks_held(struct task_struct *task); +extern void debug_check_no_locks_held(void); #else static inline void debug_show_all_locks(void) { @@ -67,7 +67,7 @@ debug_check_no_locks_freed(const void *from, unsigned long len) } static inline void -debug_check_no_locks_held(struct task_struct *task) +debug_check_no_locks_held(void) { } #endif diff --git a/include/linux/fastchg.h b/include/linux/fastchg.h new file mode 100644 index 00000000000..0570e039e22 --- /dev/null +++ b/include/linux/fastchg.h @@ -0,0 +1,23 @@ +/* + * Author: Chad Froebel + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + * + */ + +#ifndef _LINUX_FASTCHG_H +#define _LINUX_FASTCHG_H + +extern int force_fast_charge; + +#define FAST_CHARGE_DISABLED 0 /* default */ +#define FAST_CHARGE_FORCE_AC 1 + +#endif diff --git a/include/linux/freezer.h b/include/linux/freezer.h index 80e7faee928..6a060aeb3d5 100644 --- a/include/linux/freezer.h +++ b/include/linux/freezer.h @@ -3,6 +3,7 @@ #ifndef FREEZER_H_INCLUDED #define FREEZER_H_INCLUDED +#include #include #include #include @@ -41,7 +42,11 @@ extern int freeze_kernel_threads(void); extern void thaw_processes(void); extern void thaw_kernel_threads(void); -static inline bool try_to_freeze(void) +/* + * DO NOT ADD ANY NEW CALLERS OF THIS FUNCTION + * If try_to_freeze causes a lockdep warning it means the caller may deadlock + */ +static inline bool try_to_freeze_unsafe(void) { /* This causes problems for ARM targets and is a known * problem upstream. @@ -52,6 +57,13 @@ static inline bool try_to_freeze(void) return __refrigerator(false); } +static inline bool try_to_freeze(void) +{ + if (!(current->flags & PF_NOFREEZE)) + debug_check_no_locks_held(); + return try_to_freeze_unsafe(); +} + extern bool freeze_task(struct task_struct *p); extern bool set_freezable(void); @@ -94,8 +106,24 @@ static inline void freezer_count(void) try_to_freeze(); } -/* - * Check if the task should be counted as freezable by the freezer + +/* DO NOT ADD ANY NEW CALLERS OF THIS FUNCTION */ +static inline void freezer_count_unsafe(void) +{ + current->flags &= ~PF_FREEZER_SKIP; + smp_mb(); + try_to_freeze_unsafe(); +} + +/** + * freezer_should_skip - whether to skip a task when determining frozen + * state is reached + * @p: task in quesion + * + * This function is used by freezers after establishing %true freezing() to + * test whether a task should be skipped when determining the target frozen + * state is reached. IOW, if this function returns %true, @p is considered + * frozen enough. */ static inline int freezer_should_skip(struct task_struct *p) { @@ -110,22 +138,80 @@ static inline int freezer_should_skip(struct task_struct *p) */ /* Like schedule(), but should not block the freezer. */ -#define freezable_schedule() \ -({ \ - freezer_do_not_count(); \ - schedule(); \ - freezer_count(); \ -}) +static inline void freezable_schedule(void) +{ + freezer_do_not_count(); + schedule(); + freezer_count(); +} + +/* DO NOT ADD ANY NEW CALLERS OF THIS FUNCTION */ +static inline void freezable_schedule_unsafe(void) +{ + freezer_do_not_count(); + schedule(); + freezer_count_unsafe(); +} + +/* + * Like freezable_schedule_timeout(), but should not block the freezer. Do not + * call this with locks held. + */ +static inline long freezable_schedule_timeout(long timeout) +{ + long __retval; + freezer_do_not_count(); + __retval = schedule_timeout(timeout); + freezer_count(); + return __retval; +} + +/* + * Like schedule_timeout_interruptible(), but should not block the freezer. Do not + * call this with locks held. + */ +static inline long freezable_schedule_timeout_interruptible(long timeout) +{ + long __retval; + freezer_do_not_count(); + __retval = schedule_timeout_interruptible(timeout); + freezer_count(); + return __retval; +} /* Like schedule_timeout_killable(), but should not block the freezer. */ -#define freezable_schedule_timeout_killable(timeout) \ -({ \ - long __retval; \ - freezer_do_not_count(); \ - __retval = schedule_timeout_killable(timeout); \ - freezer_count(); \ - __retval; \ -}) +static inline long freezable_schedule_timeout_killable(long timeout) +{ + long __retval; + freezer_do_not_count(); + __retval = schedule_timeout_killable(timeout); + freezer_count(); + return __retval; +} + +/* DO NOT ADD ANY NEW CALLERS OF THIS FUNCTION */ +static inline long freezable_schedule_timeout_killable_unsafe(long timeout) +{ + long __retval; + freezer_do_not_count(); + __retval = schedule_timeout_killable(timeout); + freezer_count_unsafe(); + return __retval; +} + +/* + * Like schedule_hrtimeout_range(), but should not block the freezer. Do not + * call this with locks held. + */ +static inline int freezable_schedule_hrtimeout_range(ktime_t *expires, + unsigned long delta, const enum hrtimer_mode mode) +{ + int __retval; + freezer_do_not_count(); + __retval = schedule_hrtimeout_range(expires, delta, mode); + freezer_count(); + return __retval; +} /* * Freezer-friendly wrappers around wait_event_interruptible(), @@ -145,30 +231,32 @@ static inline int freezer_should_skip(struct task_struct *p) #define wait_event_freezable(wq, condition) \ ({ \ int __retval; \ - for (;;) { \ - __retval = wait_event_interruptible(wq, \ - (condition) || freezing(current)); \ - if (__retval || (condition)) \ - break; \ - try_to_freeze(); \ - } \ + freezer_do_not_count(); \ + __retval = wait_event_interruptible(wq, (condition)); \ + freezer_count(); \ __retval; \ }) #define wait_event_freezable_timeout(wq, condition, timeout) \ ({ \ long __retval = timeout; \ - for (;;) { \ - __retval = wait_event_interruptible_timeout(wq, \ - (condition) || freezing(current), \ - __retval); \ - if (__retval <= 0 || (condition)) \ - break; \ - try_to_freeze(); \ - } \ + freezer_do_not_count(); \ + __retval = wait_event_interruptible_timeout(wq, (condition), \ + __retval); \ + freezer_count(); \ + __retval; \ +}) + +#define wait_event_freezable_exclusive(wq, condition) \ +({ \ + int __retval; \ + freezer_do_not_count(); \ + __retval = wait_event_interruptible_exclusive(wq, condition); \ + freezer_count(); \ __retval; \ }) + #else /* !CONFIG_FREEZER */ static inline bool frozen(struct task_struct *p) { return false; } static inline bool freezing(struct task_struct *p) { return false; } @@ -189,15 +277,31 @@ static inline void set_freezable(void) {} #define freezable_schedule() schedule() +#define freezable_schedule_unsafe() schedule() + +#define freezable_schedule_timeout(timeout) schedule_timeout(timeout) + +#define freezable_schedule_timeout_interruptible(timeout) \ + schedule_timeout_interruptible(timeout) + #define freezable_schedule_timeout_killable(timeout) \ schedule_timeout_killable(timeout) +#define freezable_schedule_timeout_killable_unsafe(timeout) \ + schedule_timeout_killable(timeout) + +#define freezable_schedule_hrtimeout_range(expires, delta, mode) \ + schedule_hrtimeout_range(expires, delta, mode) + #define wait_event_freezable(wq, condition) \ wait_event_interruptible(wq, condition) #define wait_event_freezable_timeout(wq, condition, timeout) \ wait_event_interruptible_timeout(wq, condition, timeout) +#define wait_event_freezable_exclusive(wq, condition) \ + wait_event_interruptible_exclusive(wq, condition) + #define wait_event_freezekillable(wq, condition) \ wait_event_killable(wq, condition) diff --git a/include/linux/fs.h b/include/linux/fs.h index 093f0b8878c..2e787eb7d1d 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2079,6 +2079,7 @@ static inline int thaw_bdev(struct block_device *bdev, struct super_block *sb) } #endif extern int sync_filesystem(struct super_block *); +extern void sync_filesystems(int wait); extern const struct file_operations def_blk_fops; extern const struct file_operations def_chr_fops; extern const struct file_operations bad_sock_fops; diff --git a/include/linux/init.h b/include/linux/init.h index 6b951095a42..6ee608caf24 100644 --- a/include/linux/init.h +++ b/include/linux/init.h @@ -91,12 +91,12 @@ #define __devexitconst __section(.devexit.rodata) /* Used for HOTPLUG_CPU */ -#define __cpuinit __section(.cpuinit.text) __cold notrace -#define __cpuinitdata __section(.cpuinit.data) -#define __cpuinitconst __section(.cpuinit.rodata) -#define __cpuexit __section(.cpuexit.text) __exitused __cold notrace -#define __cpuexitdata __section(.cpuexit.data) -#define __cpuexitconst __section(.cpuexit.rodata) +#define __cpuinit __cold +#define __cpuinitdata +#define __cpuinitconst +#define __cpuexit __exitused __cold +#define __cpuexitdata +#define __cpuexitconst /* Used for MEMORY_HOTPLUG */ #define __meminit __section(.meminit.text) __cold notrace diff --git a/include/linux/input.h b/include/linux/input.h index d4cdb02c9de..798443e090c 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -1171,6 +1171,18 @@ struct ff_effect { #include #include +/** + * struct input_value - input value representation + * @type: type of value (EV_KEY, EV_ABS, etc) + * @code: the value code + * @value: the value + */ +struct input_value { + __u16 type; + __u16 code; + __s32 value; +}; + /** * struct input_dev - represents an input device * @name: name of the device @@ -1247,7 +1259,6 @@ struct ff_effect { * last user closes the device * @going_away: marks devices that are in a middle of unregistering and * causes input_open_device*() fail with -ENODEV. - * @sync: set to %true when there were no new events since last EV_SYN * @dev: driver model's view of this device * @h_list: list of input handles associated with the device. When * accessing the list dev->mutex must be held @@ -1315,12 +1326,14 @@ struct input_dev { unsigned int users; bool going_away; - bool sync; - struct device dev; struct list_head h_list; struct list_head node; + + unsigned int num_vals; + unsigned int max_vals; + struct input_value *vals; }; #define to_input_dev(d) container_of(d, struct input_dev, dev) @@ -1381,6 +1394,9 @@ struct input_handle; * @event: event handler. This method is being called by input core with * interrupts disabled and dev->event_lock spinlock held and so * it may not sleep + * @events: event sequence handler. This method is being called by + * input core with interrupts disabled and dev->event_lock + * spinlock held and so it may not sleep * @filter: similar to @event; separates normal event handlers from * "filters". * @match: called after comparing device's id with handler's id_table @@ -1417,6 +1433,8 @@ struct input_handler { void *private; void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, int value); + void (*events)(struct input_handle *handle, + const struct input_value *vals, unsigned int count); bool (*filter)(struct input_handle *handle, unsigned int type, unsigned int code, int value); bool (*match)(struct input_handler *handler, struct input_dev *dev); int (*connect)(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id); diff --git a/include/linux/kexec.h b/include/linux/kexec.h index af84a25ef6b..a4509adc86a 100644 --- a/include/linux/kexec.h +++ b/include/linux/kexec.h @@ -111,6 +111,10 @@ struct kimage { #define KEXEC_TYPE_CRASH 1 unsigned int preserve_context : 1; +#ifdef CONFIG_KEXEC_HARDBOOT + unsigned int hardboot : 1; +#endif + #ifdef ARCH_HAS_KIMAGE_ARCH struct kimage_arch arch; #endif @@ -178,6 +182,11 @@ extern struct kimage *kexec_crash_image; #define KEXEC_ON_CRASH 0x00000001 #define KEXEC_PRESERVE_CONTEXT 0x00000002 + +#ifdef CONFIG_KEXEC_HARDBOOT +#define KEXEC_HARDBOOT 0x00000004 +#endif + #define KEXEC_ARCH_MASK 0xffff0000 /* These values match the ELF architecture values. @@ -196,10 +205,14 @@ extern struct kimage *kexec_crash_image; #define KEXEC_ARCH_MIPS ( 8 << 16) /* List of defined/legal kexec flags */ -#ifndef CONFIG_KEXEC_JUMP -#define KEXEC_FLAGS KEXEC_ON_CRASH -#else +#if defined(CONFIG_KEXEC_JUMP) && defined(CONFIG_KEXEC_HARDBOOT) +#define KEXEC_FLAGS (KEXEC_ON_CRASH | KEXEC_PRESERVE_CONTEXT | KEXEC_HARDBOOT) +#elif defined(CONFIG_KEXEC_JUMP) #define KEXEC_FLAGS (KEXEC_ON_CRASH | KEXEC_PRESERVE_CONTEXT) +#elif defined(CONFIG_KEXEC_HARDBOOT) +#define KEXEC_FLAGS (KEXEC_ON_CRASH | KEXEC_HARDBOOT) +#else +#define KEXEC_FLAGS (KEXEC_ON_CRASH) #endif #define VMCOREINFO_BYTES (4096) diff --git a/include/linux/memcopy.h b/include/linux/memcopy.h new file mode 100644 index 00000000000..a7b157391fd --- /dev/null +++ b/include/linux/memcopy.h @@ -0,0 +1,226 @@ +/* + * memcopy.h -- definitions for memory copy functions. Generic C version. + * + * 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.1 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., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * The code is derived from the GNU C Library. + * Copyright (C) 1991, 1992, 1993, 1997, 2004 Free Software Foundation, Inc. + */ +#ifndef _LINUX_MEMCOPY_H_ +#define _LINUX_MEMCOPY_H_ + +/* + * The strategy of the memory functions is: + * + * 1. Copy bytes until the destination pointer is aligned. + * + * 2. Copy words in unrolled loops. If the source and destination + * are not aligned in the same way, use word memory operations, + * but shift and merge two read words before writing. + * + * 3. Copy the few remaining bytes. + * + * This is fast on processors that have at least 10 registers for + * allocation by GCC, and that can access memory at reg+const in one + * instruction. + */ + +#include +#include +#include + +/* + * The macros defined in this file are: + * + * BYTE_COPY_FWD(dst_beg_ptr, src_beg_ptr, nbytes_to_copy) + * + * BYTE_COPY_BWD(dst_end_ptr, src_end_ptr, nbytes_to_copy) + * + * WORD_COPY_FWD(dst_beg_ptr, src_beg_ptr, nbytes_remaining, nbytes_to_copy) + * + * WORD_COPY_BWD(dst_end_ptr, src_end_ptr, nbytes_remaining, nbytes_to_copy) + * + * MERGE(old_word, sh_1, new_word, sh_2) + * + * MEM_COPY_FWD(dst_beg_ptr, src_beg_ptr, nbytes_to_copy) + * + * MEM_COPY_BWD(dst_end_ptr, src_end_ptr, nbytes_to_copy) + */ + +#define OP_T_THRESHOLD 16 + +/* + * Type to use for aligned memory operations. + * This should normally be the biggest type supported by a single load + * and store. + */ +#define op_t unsigned long int +#define OPSIZ (sizeof(op_t)) + +/* Type to use for unaligned operations. */ +typedef unsigned char byte; + +#ifndef MERGE +# ifdef __LITTLE_ENDIAN +# define MERGE(w0, sh_1, w1, sh_2) (((w0) >> (sh_1)) | ((w1) << (sh_2))) +# elif defined(__BIG_ENDIAN) +# define MERGE(w0, sh_1, w1, sh_2) (((w0) << (sh_1)) | ((w1) >> (sh_2))) +# else +# error "Macro MERGE() hasn't defined!" +# endif +#endif + +/* + * Copy exactly NBYTES bytes from SRC_BP to DST_BP, + * without any assumptions about alignment of the pointers. + */ +#ifndef BYTE_COPY_FWD +#define BYTE_COPY_FWD(dst_bp, src_bp, nbytes) \ +do { \ + size_t __nbytes = (nbytes); \ + while (__nbytes > 0) { \ + byte __x = ((byte *) src_bp)[0]; \ + src_bp += 1; \ + __nbytes -= 1; \ + ((byte *) dst_bp)[0] = __x; \ + dst_bp += 1; \ + } \ +} while (0) +#endif + +/* + * Copy exactly NBYTES_TO_COPY bytes from SRC_END_PTR to DST_END_PTR, + * beginning at the bytes right before the pointers and continuing towards + * smaller addresses. Don't assume anything about alignment of the + * pointers. + */ +#ifndef BYTE_COPY_BWD +#define BYTE_COPY_BWD(dst_ep, src_ep, nbytes) \ +do { \ + size_t __nbytes = (nbytes); \ + while (__nbytes > 0) { \ + byte __x; \ + src_ep -= 1; \ + __x = ((byte *) src_ep)[0]; \ + dst_ep -= 1; \ + __nbytes -= 1; \ + ((byte *) dst_ep)[0] = __x; \ + } \ +} while (0) +#endif +/* + * Copy *up to* NBYTES bytes from SRC_BP to DST_BP, with + * the assumption that DST_BP is aligned on an OPSIZ multiple. If + * not all bytes could be easily copied, store remaining number of bytes + * in NBYTES_LEFT, otherwise store 0. + */ +extern void _wordcopy_fwd_aligned(long int, long int, size_t); +extern void _wordcopy_fwd_dest_aligned(long int, long int, size_t); +#ifndef WORD_COPY_FWD +#define WORD_COPY_FWD(dst_bp, src_bp, nbytes_left, nbytes) \ +do { \ + if (src_bp % OPSIZ == 0) \ + _wordcopy_fwd_aligned (dst_bp, src_bp, (nbytes) / OPSIZ); \ + else \ + _wordcopy_fwd_dest_aligned (dst_bp, src_bp, (nbytes) / OPSIZ);\ + \ + src_bp += (nbytes) & -OPSIZ; \ + dst_bp += (nbytes) & -OPSIZ; \ + (nbytes_left) = (nbytes) % OPSIZ; \ +} while (0) +#endif + +/* + * Copy *up to* NBYTES_TO_COPY bytes from SRC_END_PTR to DST_END_PTR, + * beginning at the words (of type op_t) right before the pointers and + * continuing towards smaller addresses. May take advantage of that + * DST_END_PTR is aligned on an OPSIZ multiple. If not all bytes could be + * easily copied, store remaining number of bytes in NBYTES_REMAINING, + * otherwise store 0. + */ +extern void _wordcopy_bwd_aligned(long int, long int, size_t); +extern void _wordcopy_bwd_dest_aligned(long int, long int, size_t); +#ifndef WORD_COPY_BWD +#define WORD_COPY_BWD(dst_ep, src_ep, nbytes_left, nbytes) \ +do { \ + if (src_ep % OPSIZ == 0) \ + _wordcopy_bwd_aligned (dst_ep, src_ep, (nbytes) / OPSIZ); \ + else \ + _wordcopy_bwd_dest_aligned (dst_ep, src_ep, (nbytes) / OPSIZ);\ + \ + src_ep -= (nbytes) & -OPSIZ; \ + dst_ep -= (nbytes) & -OPSIZ; \ + (nbytes_left) = (nbytes) % OPSIZ; \ +} while (0) +#endif + +/* Copy memory from the beginning to the end */ +#ifndef MEM_COPY_FWD +static __always_inline void mem_copy_fwd(unsigned long dstp, + unsigned long srcp, + size_t count) +{ + /* If there not too few bytes to copy, use word copy. */ + if (count >= OP_T_THRESHOLD) { + /* Copy just a few bytes to make dstp aligned. */ + count -= (-dstp) % OPSIZ; + BYTE_COPY_FWD(dstp, srcp, (-dstp) % OPSIZ); + + /* + * Copy from srcp to dstp taking advantage of the known + * alignment of dstp. Number if bytes remaining is put in + * the third argument. + */ + WORD_COPY_FWD(dstp, srcp, count, count); + + /* Fall out and copy the tail. */ + } + + /* There are just a few bytes to copy. Use byte memory operations. */ + BYTE_COPY_FWD(dstp, srcp, count); +} +#endif + +/* Copy memory from the end to the beginning. */ +#ifndef MEM_COPY_BWD +static __always_inline void mem_copy_bwd(unsigned long dstp, + unsigned long srcp, + size_t count) +{ + srcp += count; + dstp += count; + + /* If there not too few bytes to copy, use word copy. */ + if (count >= OP_T_THRESHOLD) { + /* Copy just a few bytes to make dstp aligned. */ + count -= dstp % OPSIZ; + BYTE_COPY_BWD(dstp, srcp, dstp % OPSIZ); + + /* + * Copy from srcp to dstp taking advantage of the known + * alignment of dstp. Number if bytes remaining is put in + * the third argument. + */ + WORD_COPY_BWD(dstp, srcp, count, count); + + /* Fall out and copy the tail. */ + } + + /* There are just a few bytes to copy. Use byte memory operations. */ + BYTE_COPY_BWD (dstp, srcp, count); +} +#endif + +#endif diff --git a/include/linux/mm.h b/include/linux/mm.h index ddfb7c5dd51..777117b1c3d 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -1425,7 +1425,7 @@ int write_one_page(struct page *page, int wait); void task_dirty_inc(struct task_struct *tsk); /* readahead.c */ -#define VM_MAX_READAHEAD 128 /* kbytes */ +#define VM_MAX_READAHEAD 256 /* kbytes */ #define VM_MIN_READAHEAD 16 /* kbytes (includes current page) */ int force_page_cache_readahead(struct address_space *mapping, struct file *filp, diff --git a/include/linux/msm_thermal.h b/include/linux/msm_thermal.h index 2c9a613ab84..0d1c23efbf2 100644 --- a/include/linux/msm_thermal.h +++ b/include/linux/msm_thermal.h @@ -14,12 +14,14 @@ #ifndef __MSM_THERMAL_H #define __MSM_THERMAL_H +extern int throttled_bin; + struct msm_thermal_data { uint32_t sensor_id; - uint32_t poll_ms; +/* uint32_t poll_ms; uint32_t limit_temp_degC; uint32_t temp_hysteresis_degC; - uint32_t freq_step; + uint32_t freq_step;*/ }; #ifdef CONFIG_THERMAL_MONITOR diff --git a/include/linux/msm_tsens.h b/include/linux/msm_tsens.h index 5837094b05e..ef23d70f26b 100644 --- a/include/linux/msm_tsens.h +++ b/include/linux/msm_tsens.h @@ -39,6 +39,8 @@ struct tsens_device { uint32_t sensor_num; }; +int tsens_set_tz_warm_temp_degC(int sensor_num, int temp, struct work_struct *work); +int tsens_set_tz_cool_temp_degC(int sensor_num, int temp, struct work_struct *work); int32_t tsens_get_temp(struct tsens_device *dev, unsigned long *temp); int msm_tsens_early_init(struct tsens_platform_data *pdata); diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index ddbb6a901f6..bacc7518859 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -1337,7 +1337,7 @@ static inline void perf_event_task_tick(void) { } */ #define perf_cpu_notifier(fn) \ do { \ - static struct notifier_block fn##_nb __cpuinitdata = \ + static struct notifier_block fn##_nb = \ { .notifier_call = fn, .priority = CPU_PRI_PERF }; \ fn(&fn##_nb, (unsigned long)CPU_UP_PREPARE, \ (void *)(unsigned long)smp_processor_id()); \ diff --git a/include/linux/power/cpupower.h b/include/linux/power/cpupower.h new file mode 100644 index 00000000000..9bc7039a03f --- /dev/null +++ b/include/linux/power/cpupower.h @@ -0,0 +1,22 @@ +/* + * cpupower.h + * + * Copyright (c) 2011 Vincent Guittot + * + * This file is released under the GPLv2 + * + */ + +#ifndef _CPUPOWER_H_ +#define _CPUPOWER_H_ + +#define ARM_DEFAULT_SCALE 0 +#define ARM_POWER_SCALE 1 + +struct cputopo_power { + int max; /* max idx in the table */ + unsigned int step; /* frequency step for the table */ + unsigned int *table; /* table of cpu_power */ +}; + +#endif diff --git a/include/linux/prctl.h b/include/linux/prctl.h index e0cfec2490a..be9042b2ca7 100644 --- a/include/linux/prctl.h +++ b/include/linux/prctl.h @@ -124,4 +124,10 @@ #define PR_SET_CHILD_SUBREAPER 36 #define PR_GET_CHILD_SUBREAPER 37 + /* + * Get effective timerslack value for the process. + * It can be higher than PR_GET_TIMERSLACK. + */ +#define PR_GET_EFFECTIVE_TIMERSLACK 38 + #endif /* _LINUX_PRCTL_H */ diff --git a/include/linux/sched.h b/include/linux/sched.h index ff6bb0ff8c9..78ccca7b32f 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -139,6 +139,7 @@ extern int nr_processes(void); extern unsigned long nr_running(void); extern unsigned long nr_uninterruptible(void); extern unsigned long nr_iowait(void); +extern unsigned long avg_nr_running(void); extern unsigned long nr_iowait_cpu(int cpu); extern unsigned long this_cpu_load(void); @@ -2836,4 +2837,14 @@ static inline unsigned long rlimit_max(unsigned int limit) #endif /* __KERNEL__ */ +#ifdef CONFIG_CGROUP_TIMER_SLACK +extern unsigned long task_get_effective_timer_slack(struct task_struct *tsk); +#else +static inline unsigned long task_get_effective_timer_slack( + struct task_struct *tsk) +{ + return tsk->timer_slack_ns; +} +#endif + #endif diff --git a/include/linux/sweep2wake.h b/include/linux/sweep2wake.h new file mode 100644 index 00000000000..d2a083649a7 --- /dev/null +++ b/include/linux/sweep2wake.h @@ -0,0 +1,23 @@ +/* +* include/linux/sweep2wake.h +* +* Copyright (c) 2013, Aaron Segaert (flar2) asegaert at gmail.com +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along +* with this program; if not, write to the Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + + +extern void sweep2wake_setdev(struct input_dev * input_device); +extern int pwr_key_pressed; diff --git a/include/linux/tick.h b/include/linux/tick.h index 494a3141dba..94759671062 100644 --- a/include/linux/tick.h +++ b/include/linux/tick.h @@ -140,4 +140,10 @@ static inline u64 get_cpu_idle_time_us(int cpu, u64 *unused) { return -1; } static inline u64 get_cpu_iowait_time_us(int cpu, u64 *unused) { return -1; } # endif /* !NO_HZ */ +# ifdef CONFIG_CPU_IDLE_GOV_MENU +extern void menu_hrtimer_cancel(void); +# else +static inline void menu_hrtimer_cancel(void) {} +# endif /* CONFIG_CPU_IDLE_GOV_MENU */ + #endif diff --git a/include/linux/usb.h b/include/linux/usb.h index e8114f0211c..70a8c857715 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -1435,6 +1435,7 @@ extern int usb_unlink_urb(struct urb *urb); extern void usb_kill_urb(struct urb *urb); extern void usb_poison_urb(struct urb *urb); extern void usb_unpoison_urb(struct urb *urb); +extern void usb_block_urb(struct urb *urb); extern void usb_kill_anchored_urbs(struct usb_anchor *anchor); extern void usb_poison_anchored_urbs(struct usb_anchor *anchor); extern void usb_unpoison_anchored_urbs(struct usb_anchor *anchor); @@ -1447,6 +1448,8 @@ extern struct urb *usb_get_from_anchor(struct usb_anchor *anchor); extern void usb_scuttle_anchored_urbs(struct usb_anchor *anchor); extern int usb_anchor_empty(struct usb_anchor *anchor); +#define usb_unblock_urb usb_unpoison_urb + /** * usb_urb_dir_in - check if an URB describes an IN transfer * @urb: URB to be checked diff --git a/include/linux/writeback.h b/include/linux/writeback.h index a2b84f598e2..19d1d780cf2 100644 --- a/include/linux/writeback.h +++ b/include/linux/writeback.h @@ -166,14 +166,7 @@ void __bdi_update_bandwidth(struct backing_dev_info *bdi, unsigned long start_time); void page_writeback_init(void); -void balance_dirty_pages_ratelimited_nr(struct address_space *mapping, - unsigned long nr_pages_dirtied); - -static inline void -balance_dirty_pages_ratelimited(struct address_space *mapping) -{ - balance_dirty_pages_ratelimited_nr(mapping, 1); -} +void balance_dirty_pages_ratelimited(struct address_space *mapping); typedef int (*writepage_t)(struct page *page, struct writeback_control *wbc, void *data); diff --git a/include/xen/events.h b/include/xen/events.h index 0f773708e02..04399b28e82 100644 --- a/include/xen/events.h +++ b/include/xen/events.h @@ -103,6 +103,9 @@ int xen_irq_from_pirq(unsigned pirq); /* Return the pirq allocated to the irq. */ int xen_pirq_from_irq(unsigned irq); +/* Return the irq allocated to the gsi */ +int xen_irq_from_gsi(unsigned gsi); + /* Determine whether to ignore this IRQ if it is passed to a guest. */ int xen_test_irq_shared(int irq); diff --git a/init/Kconfig b/init/Kconfig index e4b67a1dddf..258c8d47963 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -608,6 +608,14 @@ config CGROUP_FREEZER Provides a way to freeze and unfreeze all tasks in a cgroup. +config CGROUP_TIMER_SLACK + bool "Timer slack cgroup controller" + help + Provides a way to set minimal timer slack value for tasks in + a cgroup. + It's useful in mobile devices where certain background apps + are attached to a cgroup and combined wakeups are desired. + config CGROUP_DEVICE bool "Device controller for cgroups" help @@ -939,13 +947,20 @@ source "usr/Kconfig" endif +choice + prompt "Optimization level" + default CC_OPTIMIZE_DEFAULT + config CC_OPTIMIZE_FOR_SIZE - bool "Optimize for size" - help - Enabling this option will pass "-Os" instead of "-O2" to gcc - resulting in a smaller kernel. + bool "Use -Os" - If unsure, say Y. +config CC_OPTIMIZE_DEFAULT + bool "Use -O2" + +config CC_OPTIMIZE_ALOT + bool "Use -O3" + +endchoice config SYSCTL bool diff --git a/init/calibrate.c b/init/calibrate.c index fda0a7b0f06..fe85c605c7d 100644 --- a/init/calibrate.c +++ b/init/calibrate.c @@ -31,7 +31,7 @@ __setup("lpj=", lpj_setup); #define DELAY_CALIBRATION_TICKS ((HZ < 100) ? 1 : (HZ/100)) #define MAX_DIRECT_CALIBRATION_RETRIES 5 -static unsigned long __cpuinit calibrate_delay_direct(void) +static unsigned long calibrate_delay_direct(void) { unsigned long pre_start, start, post_start; unsigned long pre_end, end, post_end; @@ -166,7 +166,7 @@ static unsigned long __cpuinit calibrate_delay_direct(void) return 0; } #else -static unsigned long __cpuinit calibrate_delay_direct(void) {return 0;} +static unsigned long calibrate_delay_direct(void) {return 0;} #endif /* @@ -180,7 +180,7 @@ static unsigned long __cpuinit calibrate_delay_direct(void) {return 0;} */ #define LPS_PREC 8 -static unsigned long __cpuinit calibrate_delay_converge(void) +static unsigned long calibrate_delay_converge(void) { /* First stage - slowly accelerate to find initial bounds */ unsigned long lpj, lpj_base, ticks, loopadd, loopadd_base, chop_limit; @@ -254,12 +254,12 @@ static DEFINE_PER_CPU(unsigned long, cpu_loops_per_jiffy) = { 0 }; * Architectures should override this function if a faster calibration * method is available. */ -unsigned long __attribute__((weak)) __cpuinit calibrate_delay_is_known(void) +unsigned long __attribute__((weak)) calibrate_delay_is_known(void) { return 0; } -void __cpuinit calibrate_delay(void) +void calibrate_delay(void) { unsigned long lpj; static bool printed; diff --git a/init/main.c b/init/main.c index 737ab05f4ad..032cf65b4cb 100644 --- a/init/main.c +++ b/init/main.c @@ -562,9 +562,6 @@ asmlinkage void __init start_kernel(void) early_boot_irqs_disabled = false; local_irq_enable(); - /* Interrupts are enabled now so all GFP allocations are safe. */ - gfp_allowed_mask = __GFP_BITS_MASK; - kmem_cache_init_late(); /* @@ -844,6 +841,10 @@ static int __init kernel_init(void * unused) * Wait until kthreadd is all set-up. */ wait_for_completion(&kthreadd_done); + + /* Now the scheduler is fully set up and can do blocking allocations */ + gfp_allowed_mask = __GFP_BITS_MASK; + /* * init can allocate pages on any node */ diff --git a/ipc/shm.c b/ipc/shm.c index 406c5b20819..cb4c16cf374 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -1087,7 +1087,7 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr) SYSCALL_DEFINE3(shmat, int, shmid, char __user *, shmaddr, int, shmflg) { - unsigned long ret; + unsigned long ret = 0; long err; err = do_shmat(shmid, shmaddr, shmflg, &ret); diff --git a/kernel/Makefile b/kernel/Makefile index cb41b9547c9..446798f8f54 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -58,6 +58,7 @@ obj-$(CONFIG_BACKTRACE_SELF_TEST) += backtracetest.o obj-$(CONFIG_COMPAT) += compat.o obj-$(CONFIG_CGROUPS) += cgroup.o obj-$(CONFIG_CGROUP_FREEZER) += cgroup_freezer.o +obj-$(CONFIG_CGROUP_TIMER_SLACK) += cgroup_timer_slack.o obj-$(CONFIG_CPUSETS) += cpuset.o obj-$(CONFIG_UTS_NS) += utsname.o obj-$(CONFIG_USER_NS) += user_namespace.o diff --git a/kernel/auditsc.c b/kernel/auditsc.c index af1de0f34ea..e3fd8e597b8 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -913,7 +913,7 @@ static int audit_filter_inode_name(struct task_struct *tsk, int h = audit_hash_ino((u32)n->ino); struct list_head *list = &audit_inode_hash[h]; struct audit_entry *e; - enum audit_state state; + enum audit_state state = 0; word = AUDIT_WORD(ctx->major); bit = AUDIT_BIT(ctx->major); diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 2f0d7542c0d..5303ec8591b 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -2880,6 +2880,7 @@ int cgroup_scan_tasks(struct cgroup_scanner *scan) struct ptr_heap tmp_heap; struct ptr_heap *heap; struct timespec latest_time = { 0, 0 }; + it.task = NULL; if (scan->heap) { /* The caller supplied our heap and pre-allocated its memory */ @@ -3216,6 +3217,7 @@ int cgroupstats_build(struct cgroupstats *stats, struct dentry *dentry) struct cgroup *cgrp; struct cgroup_iter it; struct task_struct *tsk; + it.task = NULL; /* * Validate dentry by checking the superblock operations, diff --git a/kernel/cgroup_timer_slack.c b/kernel/cgroup_timer_slack.c new file mode 100644 index 00000000000..d320eea04b8 --- /dev/null +++ b/kernel/cgroup_timer_slack.c @@ -0,0 +1,127 @@ +/* + * cgroup_timer_slack.c - control group timer slack subsystem + * + * Copyright Nokia Corparation, 2011 + * Author: Kirill A. Shutemov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include + +struct cgroup_subsys timer_slack_subsys; +struct tslack_cgroup { + struct cgroup_subsys_state css; + unsigned long min_slack_ns; +}; + +static struct tslack_cgroup *cgroup_to_tslack(struct cgroup *cgroup) +{ + struct cgroup_subsys_state *css; + + css = cgroup_subsys_state(cgroup, timer_slack_subsys.subsys_id); + return container_of(css, struct tslack_cgroup, css); +} + +static struct cgroup_subsys_state *tslack_create(struct cgroup *cgroup) +{ + struct tslack_cgroup *tslack_cgroup; + + tslack_cgroup = kmalloc(sizeof(*tslack_cgroup), GFP_KERNEL); + if (!tslack_cgroup) + return ERR_PTR(-ENOMEM); + + if (cgroup->parent) { + struct tslack_cgroup *parent; + + parent = cgroup_to_tslack(cgroup->parent); + tslack_cgroup->min_slack_ns = parent->min_slack_ns; + } else + tslack_cgroup->min_slack_ns = 0UL; + + return &tslack_cgroup->css; +} + +static void tslack_destroy(struct cgroup *cgroup) +{ + kfree(cgroup_to_tslack(cgroup)); +} + +static u64 tslack_read_min(struct cgroup *cgroup, struct cftype *cft) +{ + return cgroup_to_tslack(cgroup)->min_slack_ns; +} + +static int tslack_write_min(struct cgroup *cgroup, struct cftype *cft, u64 val) +{ + if (val > ULONG_MAX) + return -EINVAL; + + cgroup_to_tslack(cgroup)->min_slack_ns = val; + + return 0; +} + +static u64 tslack_read_effective(struct cgroup *cgroup, struct cftype *cft) +{ + unsigned long min; + + min = cgroup_to_tslack(cgroup)->min_slack_ns; + while (cgroup->parent) { + cgroup = cgroup->parent; + min = max(cgroup_to_tslack(cgroup)->min_slack_ns, min); + } + + return min; +} + +static struct cftype files[] = { + { + .name = "min_slack_ns", + .read_u64 = tslack_read_min, + .write_u64 = tslack_write_min, + }, + { + .name = "effective_slack_ns", + .read_u64 = tslack_read_effective, + }, +}; + +static int tslack_populate(struct cgroup_subsys *subsys, struct cgroup *cgroup) +{ + return cgroup_add_files(cgroup, subsys, files, ARRAY_SIZE(files)); +} + +struct cgroup_subsys timer_slack_subsys = { + .name = "timer_slack", + .subsys_id = timer_slack_subsys_id, + .create = tslack_create, + .destroy = tslack_destroy, + .populate = tslack_populate, +}; + +unsigned long task_get_effective_timer_slack(struct task_struct *tsk) +{ + struct cgroup *cgroup; + unsigned long slack; + + rcu_read_lock(); + cgroup = task_cgroup(tsk, timer_slack_subsys.subsys_id); + slack = tslack_read_effective(cgroup, NULL); + rcu_read_unlock(); + + return max(tsk->timer_slack_ns, slack); +} diff --git a/kernel/cpu.c b/kernel/cpu.c index fb4a5acc016..48663d332f6 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -290,7 +290,7 @@ EXPORT_SYMBOL(cpu_down); #endif /*CONFIG_HOTPLUG_CPU*/ /* Requires cpu_add_remove_lock to be held */ -static int __cpuinit _cpu_up(unsigned int cpu, int tasks_frozen) +static int _cpu_up(unsigned int cpu, int tasks_frozen) { int ret, nr_calls = 0; void *hcpu = (void *)(long)cpu; @@ -325,7 +325,7 @@ static int __cpuinit _cpu_up(unsigned int cpu, int tasks_frozen) return ret; } -int __cpuinit cpu_up(unsigned int cpu) +int cpu_up(unsigned int cpu) { int err = 0; @@ -560,7 +560,7 @@ core_initcall(cpu_hotplug_pm_sync_init); * It must be called by the arch code on the new cpu, before the new cpu * enables interrupts and before the "boot" cpu returns from __cpu_up(). */ -void __cpuinit notify_cpu_starting(unsigned int cpu) +void notify_cpu_starting(unsigned int cpu) { unsigned long val = CPU_STARTING; diff --git a/kernel/events/core.c b/kernel/events/core.c index aafa4c1acd9..8b0f750a958 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -6983,7 +6983,7 @@ static void __init perf_event_init_all_cpus(void) } } -static void __cpuinit perf_event_init_cpu(int cpu) +static void perf_event_init_cpu(int cpu) { struct swevent_htable *swhash = &per_cpu(swevent_htable, cpu); @@ -7072,7 +7072,7 @@ static struct notifier_block perf_reboot_notifier = { .priority = INT_MIN, }; -static int __cpuinit +static int perf_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) { unsigned int cpu = (long)hcpu; diff --git a/kernel/exit.c b/kernel/exit.c index 6096e809bf9..bc7d69084fd 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -1030,7 +1030,7 @@ void do_exit(long code) /* * Make sure we are holding no locks: */ - debug_check_no_locks_held(tsk); + debug_check_no_locks_held(); /* * We can do this unlocked here. The futex code uses this flag * just to verify whether the pi state cleanup has been done diff --git a/kernel/fork.c b/kernel/fork.c index 0de735c9b6b..2a3cd0aea6a 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1235,6 +1235,10 @@ static struct task_struct *copy_process(unsigned long clone_flags, memset(&p->rss_stat, 0, sizeof(p->rss_stat)); #endif + /* + * Save current task's (not effective) timer slack value as default + * timer slack value for new task. + */ p->default_timer_slack_ns = current->timer_slack_ns; task_io_accounting_init(&p->ioac); @@ -1524,7 +1528,7 @@ static struct task_struct *copy_process(unsigned long clone_flags, return ERR_PTR(retval); } -noinline struct pt_regs * __cpuinit __attribute__((weak)) idle_regs(struct pt_regs *regs) +noinline struct pt_regs * __attribute__((weak)) idle_regs(struct pt_regs *regs) { memset(regs, 0, sizeof(struct pt_regs)); return regs; @@ -1540,7 +1544,7 @@ static inline void init_idle_pids(struct pid_link *links) } } -struct task_struct * __cpuinit fork_idle(int cpu) +struct task_struct * fork_idle(int cpu) { struct task_struct *task; struct pt_regs regs; diff --git a/kernel/freezer.c b/kernel/freezer.c index 11f82a4d4ea..d1db42318b3 100644 --- a/kernel/freezer.c +++ b/kernel/freezer.c @@ -110,6 +110,18 @@ bool freeze_task(struct task_struct *p) { unsigned long flags; + /* + * This check can race with freezer_do_not_count, but worst case that + * will result in an extra wakeup being sent to the task. It does not + * race with freezer_count(), the barriers in freezer_count() and + * freezer_should_skip() ensure that either freezer_count() sees + * freezing == true in try_to_freeze() and freezes, or + * freezer_should_skip() sees !PF_FREEZE_SKIP and freezes the task + * normally. + */ + if (freezer_should_skip(p)) + return false; + spin_lock_irqsave(&freezer_lock, flags); if (!freezing(p) || frozen(p)) { spin_unlock_irqrestore(&freezer_lock, flags); diff --git a/kernel/futex.c b/kernel/futex.c index e2b0fb9a0b3..577deef7166 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -60,6 +60,7 @@ #include #include #include +#include #include @@ -1786,7 +1787,7 @@ static void futex_wait_queue_me(struct futex_hash_bucket *hb, struct futex_q *q, * is no timeout, or if it has yet to expire. */ if (!timeout || timeout->task) - schedule(); + freezable_schedule(); } __set_current_state(TASK_RUNNING); } @@ -1888,7 +1889,7 @@ static int futex_wait(u32 __user *uaddr, unsigned int flags, u32 val, HRTIMER_MODE_ABS); hrtimer_init_sleeper(to, current); hrtimer_set_expires_range_ns(&to->timer, *abs_time, - current->timer_slack_ns); + task_get_effective_timer_slack(current)); } retry: @@ -2282,7 +2283,7 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags, HRTIMER_MODE_ABS); hrtimer_init_sleeper(to, current); hrtimer_set_expires_range_ns(&to->timer, *abs_time, - current->timer_slack_ns); + task_get_effective_timer_slack(current)); } /* diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index d1e73a4eed9..a2ffb7a85c1 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c @@ -45,6 +45,7 @@ #include #include #include +#include #include @@ -1502,7 +1503,7 @@ static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mod t->task = NULL; if (likely(t->task)) - schedule(); + freezable_schedule(); hrtimer_cancel(&t->timer); mode = HRTIMER_MODE_ABS; @@ -1565,7 +1566,7 @@ long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp, int ret = 0; unsigned long slack; - slack = current->timer_slack_ns; + slack = task_get_effective_timer_slack(current); if (rt_task(current)) slack = 0; @@ -1615,7 +1616,7 @@ SYSCALL_DEFINE2(nanosleep, struct timespec __user *, rqtp, /* * Functions related to boot-time initialization: */ -static void __cpuinit init_hrtimers_cpu(int cpu) +static void init_hrtimers_cpu(int cpu) { struct hrtimer_cpu_base *cpu_base = &per_cpu(hrtimer_bases, cpu); int i; @@ -1696,7 +1697,7 @@ static void migrate_hrtimers(int scpu) #endif /* CONFIG_HOTPLUG_CPU */ -static int __cpuinit hrtimer_cpu_notify(struct notifier_block *self, +static int hrtimer_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) { int scpu = (long)hcpu; @@ -1729,7 +1730,7 @@ static int __cpuinit hrtimer_cpu_notify(struct notifier_block *self, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata hrtimers_nb = { +static struct notifier_block hrtimers_nb = { .notifier_call = hrtimer_cpu_notify, }; diff --git a/kernel/kexec.c b/kernel/kexec.c index 4e2e472f6ae..aef789344c2 100644 --- a/kernel/kexec.c +++ b/kernel/kexec.c @@ -1004,6 +1004,10 @@ SYSCALL_DEFINE4(kexec_load, unsigned long, entry, unsigned long, nr_segments, if (flags & KEXEC_PRESERVE_CONTEXT) image->preserve_context = 1; +#ifdef CONFIG_KEXEC_HARDBOOT + if (flags & KEXEC_HARDBOOT) + image->hardboot = 1; +#endif result = machine_kexec_prepare(image); if (result) goto out; diff --git a/kernel/lockdep.c b/kernel/lockdep.c index ea9ee4518c3..fdcf7ec6c88 100644 --- a/kernel/lockdep.c +++ b/kernel/lockdep.c @@ -4044,7 +4044,7 @@ void debug_check_no_locks_freed(const void *mem_from, unsigned long mem_len) } EXPORT_SYMBOL_GPL(debug_check_no_locks_freed); -static void print_held_locks_bug(struct task_struct *curr) +static void print_held_locks_bug(void) { if (!debug_locks_off()) return; @@ -4053,22 +4053,21 @@ static void print_held_locks_bug(struct task_struct *curr) printk("\n"); printk("=====================================\n"); - printk("[ BUG: lock held at task exit time! ]\n"); + printk("[ BUG: %s/%d still has locks held! ]\n", + current->comm, task_pid_nr(current)); print_kernel_ident(); printk("-------------------------------------\n"); - printk("%s/%d is exiting with locks still held!\n", - curr->comm, task_pid_nr(curr)); - lockdep_print_held_locks(curr); - + lockdep_print_held_locks(current); printk("\nstack backtrace:\n"); dump_stack(); } -void debug_check_no_locks_held(struct task_struct *task) +void debug_check_no_locks_held(void) { - if (unlikely(task->lockdep_depth > 0)) - print_held_locks_bug(task); + if (unlikely(current->lockdep_depth > 0)) + print_held_locks_bug(); } +EXPORT_SYMBOL_GPL(debug_check_no_locks_held); void debug_show_all_locks(void) { diff --git a/kernel/module.c b/kernel/module.c index 78ac6ec1e42..b1c79e395de 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -868,7 +868,7 @@ static inline void print_unload_info(struct seq_file *m, struct module *mod) void __symbol_put(const char *symbol) { - struct module *owner; + struct module *owner = NULL; preempt_disable(); if (!find_symbol(symbol, &owner, NULL, true, false)) @@ -1200,7 +1200,7 @@ static const struct kernel_symbol *resolve_symbol(struct module *mod, const char *name, char ownername[]) { - struct module *owner; + struct module *owner = NULL; const struct kernel_symbol *sym; const unsigned long *crc; int err; @@ -1838,7 +1838,7 @@ static void free_module(struct module *mod) void *__symbol_get(const char *symbol) { - struct module *owner; + struct module *owner = NULL; const struct kernel_symbol *sym; preempt_disable(); @@ -1860,7 +1860,7 @@ EXPORT_SYMBOL_GPL(__symbol_get); static int verify_export_symbols(struct module *mod) { unsigned int i; - struct module *owner; + struct module *owner = NULL; const struct kernel_symbol *s; struct { const struct kernel_symbol *sym; diff --git a/kernel/power/process.c b/kernel/power/process.c index 00259a85c85..93ab3aee230 100644 --- a/kernel/power/process.c +++ b/kernel/power/process.c @@ -32,9 +32,10 @@ static int try_to_freeze_tasks(bool user_only) unsigned int todo; bool wq_busy = false; struct timeval start, end; - u64 elapsed_csecs64; - unsigned int elapsed_csecs; + u64 elapsed_msecs64; + unsigned int elapsed_msecs; bool wakeup = false; + int sleep_usecs = USEC_PER_MSEC; do_gettimeofday(&start); @@ -87,13 +88,15 @@ static int try_to_freeze_tasks(bool user_only) * We need to retry, but first give the freezing tasks some * time to enter the regrigerator. */ - msleep(10); + usleep_range(sleep_usecs / 2, sleep_usecs); + if (sleep_usecs < 8 * USEC_PER_MSEC) + sleep_usecs *= 2; } do_gettimeofday(&end); - elapsed_csecs64 = timeval_to_ns(&end) - timeval_to_ns(&start); - do_div(elapsed_csecs64, NSEC_PER_SEC / 100); - elapsed_csecs = elapsed_csecs64; + elapsed_msecs64 = timeval_to_ns(&end) - timeval_to_ns(&start); + do_div(elapsed_msecs64, NSEC_PER_MSEC); + elapsed_msecs = elapsed_msecs64; if (todo) { /* This does not unfreeze processes that are already frozen @@ -108,10 +111,10 @@ static int try_to_freeze_tasks(bool user_only) } else { printk("\n"); - printk(KERN_ERR "Freezing of tasks %s after %d.%02d seconds " + printk(KERN_ERR "Freezing of tasks %s after %d.%03d seconds " "(%d tasks refusing to freeze, wq_busy=%d):\n", wakeup ? "aborted" : "failed", - elapsed_csecs / 100, elapsed_csecs % 100, + elapsed_msecs / 1000, elapsed_msecs % 1000, todo - wq_busy, wq_busy); } @@ -120,14 +123,14 @@ static int try_to_freeze_tasks(bool user_only) do_each_thread(g, p) { if (p != current && !freezer_should_skip(p) && freezing(p) && !frozen(p) && - elapsed_csecs > 100) + elapsed_msecs > 1000) sched_show_task(p); } while_each_thread(g, p); read_unlock(&tasklist_lock); } } else { - printk("(elapsed %d.%02d seconds) ", elapsed_csecs / 100, - elapsed_csecs % 100); + printk("(elapsed %d.%03d seconds) ", elapsed_msecs / 1000, + elapsed_msecs % 1000); } return todo ? -EBUSY : 0; diff --git a/kernel/printk.c b/kernel/printk.c index 8e3af827913..86590409dc0 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -1212,13 +1212,13 @@ void resume_console(void) console_unlock(); } -static void __cpuinit console_flush(struct work_struct *work) +static void console_flush(struct work_struct *work) { console_lock(); console_unlock(); } -static __cpuinitdata DECLARE_WORK(console_cpu_notify_work, console_flush); +static DECLARE_WORK(console_cpu_notify_work, console_flush); /** * console_cpu_notify - print deferred console messages after CPU hotplug @@ -1234,7 +1234,7 @@ static __cpuinitdata DECLARE_WORK(console_cpu_notify_work, console_flush); * Special handling must be done for cases invoked from an atomic context, * as we can't be taking the console semaphore here. */ -static int __cpuinit console_cpu_notify(struct notifier_block *self, +static int console_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) { switch (action) { diff --git a/kernel/profile.c b/kernel/profile.c index 76b8e77773e..e59628518d5 100644 --- a/kernel/profile.c +++ b/kernel/profile.c @@ -352,7 +352,7 @@ static void do_profile_hits(int type, void *__pc, unsigned int nr_hits) put_cpu(); } -static int __cpuinit profile_cpu_callback(struct notifier_block *info, +static int profile_cpu_callback(struct notifier_block *info, unsigned long action, void *__cpu) { int node, cpu = (unsigned long)__cpu; diff --git a/kernel/rcutorture.c b/kernel/rcutorture.c index a89b381a8c6..05ddf0b7d06 100644 --- a/kernel/rcutorture.c +++ b/kernel/rcutorture.c @@ -1409,7 +1409,7 @@ rcu_torture_shutdown(void *arg) * Execute random CPU-hotplug operations at the interval specified * by the onoff_interval. */ -static int __cpuinit +static int rcu_torture_onoff(void *arg) { int cpu; @@ -1462,7 +1462,7 @@ rcu_torture_onoff(void *arg) return 0; } -static int __cpuinit +static int rcu_torture_onoff_init(void) { int ret; @@ -1503,7 +1503,7 @@ static void rcu_torture_onoff_cleanup(void) * CPU-stall kthread. It waits as specified by stall_cpu_holdoff, then * induces a CPU stall for the time specified by stall_cpu. */ -static int __cpuinit rcu_torture_stall(void *args) +static int rcu_torture_stall(void *args) { unsigned long stop_at; diff --git a/kernel/rcutree.c b/kernel/rcutree.c index 4eec66e0350..d494b93c9f0 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c @@ -2276,7 +2276,7 @@ rcu_boot_init_percpu_data(int cpu, struct rcu_state *rsp) * can accept some slop in the rsp->completed access due to the fact * that this CPU cannot possibly have any RCU callbacks in flight yet. */ -static void __cpuinit +static void rcu_init_percpu_data(int cpu, struct rcu_state *rsp, int preemptible) { unsigned long flags; @@ -2333,7 +2333,7 @@ rcu_init_percpu_data(int cpu, struct rcu_state *rsp, int preemptible) raw_spin_unlock_irqrestore(&rsp->onofflock, flags); } -static void __cpuinit rcu_prepare_cpu(int cpu) +static void rcu_prepare_cpu(int cpu) { rcu_init_percpu_data(cpu, &rcu_sched_state, 0); rcu_init_percpu_data(cpu, &rcu_bh_state, 0); @@ -2343,7 +2343,7 @@ static void __cpuinit rcu_prepare_cpu(int cpu) /* * Handle CPU online/offline notification events. */ -static int __cpuinit rcu_cpu_notify(struct notifier_block *self, +static int rcu_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) { long cpu = (long)hcpu; diff --git a/kernel/rcutree.h b/kernel/rcutree.h index cdd1be0a407..1d7ee6bc915 100644 --- a/kernel/rcutree.h +++ b/kernel/rcutree.h @@ -449,7 +449,7 @@ static void rcu_report_exp_rnp(struct rcu_state *rsp, struct rcu_node *rnp, #endif /* #if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_TREE_PREEMPT_RCU) */ static int rcu_preempt_pending(int cpu); static int rcu_preempt_cpu_has_callbacks(int cpu); -static void __cpuinit rcu_preempt_init_percpu_data(int cpu); +static void rcu_preempt_init_percpu_data(int cpu); static void rcu_preempt_cleanup_dying_cpu(void); static void __init __rcu_init_preempt(void); static void rcu_initiate_boost(struct rcu_node *rnp, unsigned long flags); @@ -460,14 +460,14 @@ static bool rcu_is_callbacks_kthread(void); static void rcu_preempt_do_callbacks(void); static void rcu_boost_kthread_setaffinity(struct rcu_node *rnp, cpumask_var_t cm); -static int __cpuinit rcu_spawn_one_boost_kthread(struct rcu_state *rsp, +static int rcu_spawn_one_boost_kthread(struct rcu_state *rsp, struct rcu_node *rnp, int rnp_index); static void invoke_rcu_node_kthread(struct rcu_node *rnp); static void rcu_yield(void (*f)(unsigned long), unsigned long arg); #endif /* #ifdef CONFIG_RCU_BOOST */ static void rcu_cpu_kthread_setrt(int cpu, int to_rt); -static void __cpuinit rcu_prepare_kthreads(int cpu); +static void rcu_prepare_kthreads(int cpu); static void rcu_prepare_for_idle_init(int cpu); static void rcu_cleanup_after_idle(int cpu); static void rcu_prepare_for_idle(int cpu); diff --git a/kernel/rcutree_plugin.h b/kernel/rcutree_plugin.h index c023464816b..d968f0c8187 100644 --- a/kernel/rcutree_plugin.h +++ b/kernel/rcutree_plugin.h @@ -947,7 +947,7 @@ EXPORT_SYMBOL_GPL(rcu_barrier); /* * Initialize preemptible RCU's per-CPU data. */ -static void __cpuinit rcu_preempt_init_percpu_data(int cpu) +static void rcu_preempt_init_percpu_data(int cpu) { rcu_init_percpu_data(cpu, &rcu_preempt_state, 1); } @@ -1190,7 +1190,7 @@ EXPORT_SYMBOL_GPL(rcu_barrier); * Because preemptible RCU does not exist, there is no per-CPU * data to initialize. */ -static void __cpuinit rcu_preempt_init_percpu_data(int cpu) +static void rcu_preempt_init_percpu_data(int cpu) { } @@ -1447,7 +1447,7 @@ static void rcu_preempt_boost_start_gp(struct rcu_node *rnp) * already exist. We only create this kthread for preemptible RCU. * Returns zero if all is well, a negated errno otherwise. */ -static int __cpuinit rcu_spawn_one_boost_kthread(struct rcu_state *rsp, +static int rcu_spawn_one_boost_kthread(struct rcu_state *rsp, struct rcu_node *rnp, int rnp_index) { @@ -1679,7 +1679,7 @@ static int rcu_cpu_kthread(void *arg) * rcu_cpu_kthread() will wait until it is fully online, and then do * the binding. */ -static int __cpuinit rcu_spawn_one_cpu_kthread(int cpu) +static int rcu_spawn_one_cpu_kthread(int cpu) { struct sched_param sp; struct task_struct *t; @@ -1786,7 +1786,7 @@ static void rcu_node_kthread_setaffinity(struct rcu_node *rnp, int outgoingcpu) * during runtime, with the main CPU-hotplug locks held. So only * one of these can be executing at a time. */ -static int __cpuinit rcu_spawn_one_node_kthread(struct rcu_state *rsp, +static int rcu_spawn_one_node_kthread(struct rcu_state *rsp, struct rcu_node *rnp) { unsigned long flags; @@ -1836,7 +1836,7 @@ static int __init rcu_spawn_kthreads(void) } early_initcall(rcu_spawn_kthreads); -static void __cpuinit rcu_prepare_kthreads(int cpu) +static void rcu_prepare_kthreads(int cpu) { struct rcu_data *rdp = per_cpu_ptr(rcu_state->rda, cpu); struct rcu_node *rnp = rdp->mynode; @@ -1893,7 +1893,7 @@ static int __init rcu_scheduler_really_started(void) } early_initcall(rcu_scheduler_really_started); -static void __cpuinit rcu_prepare_kthreads(int cpu) +static void rcu_prepare_kthreads(int cpu) { } diff --git a/kernel/relay.c b/kernel/relay.c index ab56a1764d4..1175b4cfb0e 100644 --- a/kernel/relay.c +++ b/kernel/relay.c @@ -516,7 +516,7 @@ static void setup_callbacks(struct rchan *chan, * * Returns the success/failure of the operation. (%NOTIFY_OK, %NOTIFY_BAD) */ -static int __cpuinit relay_hotcpu_callback(struct notifier_block *nb, +static int relay_hotcpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu) { diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 1cee48f07d9..eea5ec83927 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -2165,6 +2165,33 @@ unsigned long nr_iowait(void) return sum; } +unsigned long avg_nr_running(void) +{ + unsigned long i, sum = 0; + unsigned int seqcnt, ave_nr_running; + + for_each_online_cpu(i) { + struct rq *q = cpu_rq(i); + + /* + * Update average to avoid reading stalled value if there were + * no run-queue changes for a long time. On the other hand if + * the changes are happening right now, just read current value + * directly. + */ + seqcnt = read_seqcount_begin(&q->ave_seqcnt); + ave_nr_running = do_avg_nr_running(q); + if (read_seqcount_retry(&q->ave_seqcnt, seqcnt)) { + read_seqcount_begin(&q->ave_seqcnt); + ave_nr_running = q->ave_nr_running; + } + + sum += ave_nr_running; + } + + return sum; +} + unsigned long nr_iowait_cpu(int cpu) { struct rq *this = cpu_rq(cpu); @@ -4926,7 +4953,7 @@ void show_state_filter(unsigned long state_filter) debug_show_all_locks(); } -void __cpuinit init_idle_bootup_task(struct task_struct *idle) +void init_idle_bootup_task(struct task_struct *idle) { idle->sched_class = &idle_sched_class; } @@ -4939,7 +4966,7 @@ void __cpuinit init_idle_bootup_task(struct task_struct *idle) * NOTE: this function does not set the idle thread's NEED_RESCHED * flag, to make booting more robust. */ -void __cpuinit init_idle(struct task_struct *idle, int cpu) +void init_idle(struct task_struct *idle, int cpu) { struct rq *rq = cpu_rq(cpu); unsigned long flags; @@ -5429,7 +5456,7 @@ static void set_rq_offline(struct rq *rq) * migration_call - callback that gets triggered when a CPU is added. * Here we can start up the necessary migration thread for the new CPU. */ -static int __cpuinit +static int migration_call(struct notifier_block *nfb, unsigned long action, void *hcpu) { int cpu = (long)hcpu; @@ -5482,12 +5509,12 @@ migration_call(struct notifier_block *nfb, unsigned long action, void *hcpu) * happens before everything else. This has to be lower priority than * the notifier in the perf_event subsystem, though. */ -static struct notifier_block __cpuinitdata migration_notifier = { +static struct notifier_block migration_notifier = { .notifier_call = migration_call, .priority = CPU_PRI_MIGRATION, }; -static int __cpuinit sched_cpu_active(struct notifier_block *nfb, +static int sched_cpu_active(struct notifier_block *nfb, unsigned long action, void *hcpu) { switch (action & ~CPU_TASKS_FROZEN) { @@ -5500,7 +5527,7 @@ static int __cpuinit sched_cpu_active(struct notifier_block *nfb, } } -static int __cpuinit sched_cpu_inactive(struct notifier_block *nfb, +static int sched_cpu_inactive(struct notifier_block *nfb, unsigned long action, void *hcpu) { switch (action & ~CPU_TASKS_FROZEN) { diff --git a/kernel/sched/debug.c b/kernel/sched/debug.c index 09acaa15161..06d172eb5ce 100644 --- a/kernel/sched/debug.c +++ b/kernel/sched/debug.c @@ -266,6 +266,9 @@ static void print_cpu(struct seq_file *m, int cpu) SEQ_printf(m, " .%-30s: %Ld.%06ld\n", #x, SPLIT_NS(rq->x)) P(nr_running); + SEQ_printf(m, " .%-30s: %d.%03d \n", "ave_nr_running", + rq->ave_nr_running / FIXED_1, + ((rq->ave_nr_running % FIXED_1) * 1000) / FIXED_1); SEQ_printf(m, " .%-30s: %lu\n", "load", rq->load.weight); P(nr_switches); diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index fc60d5b3a25..ca424764da4 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -4910,7 +4910,7 @@ void select_nohz_load_balancer(int stop_tick) return; } -static int __cpuinit sched_ilb_notifier(struct notifier_block *nfb, +static int sched_ilb_notifier(struct notifier_block *nfb, unsigned long action, void *hcpu) { switch (action & ~CPU_TASKS_FROZEN) { diff --git a/kernel/sched/features.h b/kernel/sched/features.h index de00a486c5c..d98ae909e32 100644 --- a/kernel/sched/features.h +++ b/kernel/sched/features.h @@ -42,7 +42,7 @@ SCHED_FEAT(CACHE_HOT_BUDDY, true) /* * Use arch dependent cpu power functions */ -SCHED_FEAT(ARCH_POWER, false) +SCHED_FEAT(ARCH_POWER, true) SCHED_FEAT(HRTICK, false) SCHED_FEAT(DOUBLE_TICK, false) diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c index 8f32475d0ee..4b2761f093e 100644 --- a/kernel/sched/rt.c +++ b/kernel/sched/rt.c @@ -1261,8 +1261,7 @@ select_task_rq_rt(struct task_struct *p, int sd_flag, int flags) */ if (curr && unlikely(rt_task(curr)) && (curr->rt.nr_cpus_allowed < 2 || - curr->prio <= p->prio) && - (p->rt.nr_cpus_allowed > 1)) { + curr->prio <= p->prio)) { int target = find_lowest_rq(p); if (target != -1) diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index 5370bcb8e77..3ae7dc7438d 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -365,6 +365,11 @@ struct rq { #endif int skip_clock_update; + /* time-based average load */ + u64 nr_last_stamp; + unsigned int ave_nr_running; + seqcount_t ave_seqcnt; + /* capture load from *all* tasks on this cpu: */ struct load_weight load; unsigned long nr_load_updates; @@ -924,16 +929,51 @@ extern void cpuacct_charge(struct task_struct *tsk, u64 cputime); static inline void cpuacct_charge(struct task_struct *tsk, u64 cputime) {} #endif +/* 27 ~= 134217728ns = 134.2ms + * 26 ~= 67108864ns = 67.1ms + * 25 ~= 33554432ns = 33.5ms + * 24 ~= 16777216ns = 16.8ms + */ +#define NR_AVE_PERIOD_EXP 27 +#define NR_AVE_SCALE(x) ((x) << FSHIFT) +#define NR_AVE_PERIOD (1 << NR_AVE_PERIOD_EXP) +#define NR_AVE_DIV_PERIOD(x) ((x) >> NR_AVE_PERIOD_EXP) + +static inline unsigned int do_avg_nr_running(struct rq *rq) +{ + s64 nr, deltax; + unsigned int ave_nr_running = rq->ave_nr_running; + + deltax = rq->clock_task - rq->nr_last_stamp; + nr = NR_AVE_SCALE(rq->nr_running); + + if (deltax > NR_AVE_PERIOD) + ave_nr_running = nr; + else + ave_nr_running += + NR_AVE_DIV_PERIOD(deltax * (nr - ave_nr_running)); + + return ave_nr_running; +} + static inline void inc_nr_running(struct rq *rq) { sched_update_nr_prod(cpu_of(rq), rq->nr_running, true); + write_seqcount_begin(&rq->ave_seqcnt); + rq->ave_nr_running = do_avg_nr_running(rq); + rq->nr_last_stamp = rq->clock_task; rq->nr_running++; + write_seqcount_end(&rq->ave_seqcnt); } static inline void dec_nr_running(struct rq *rq) { sched_update_nr_prod(cpu_of(rq), rq->nr_running, false); + write_seqcount_begin(&rq->ave_seqcnt); + rq->ave_nr_running = do_avg_nr_running(rq); + rq->nr_last_stamp = rq->clock_task; rq->nr_running--; + write_seqcount_end(&rq->ave_seqcnt); } extern void update_rq_clock(struct rq *rq); diff --git a/kernel/signal.c b/kernel/signal.c index 9f70f45f944..dde41622e34 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -2764,7 +2764,7 @@ int do_sigtimedwait(const sigset_t *which, siginfo_t *info, recalc_sigpending(); spin_unlock_irq(&tsk->sighand->siglock); - timeout = schedule_timeout_interruptible(timeout); + timeout = freezable_schedule_timeout_interruptible(timeout); spin_lock_irq(&tsk->sighand->siglock); __set_task_blocked(tsk, &tsk->real_blocked); diff --git a/kernel/smp.c b/kernel/smp.c index 2f8b10ecf75..ecc3638dac6 100644 --- a/kernel/smp.c +++ b/kernel/smp.c @@ -70,7 +70,7 @@ hotplug_cfd(struct notifier_block *nfb, unsigned long action, void *hcpu) return NOTIFY_OK; } -static struct notifier_block __cpuinitdata hotplug_cfd_notifier = { +static struct notifier_block hotplug_cfd_notifier = { .notifier_call = hotplug_cfd, }; diff --git a/kernel/softirq.c b/kernel/softirq.c index 671f9594e36..0df8be0885c 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c @@ -679,7 +679,7 @@ void send_remote_softirq(struct call_single_data *cp, int cpu, int softirq) } EXPORT_SYMBOL(send_remote_softirq); -static int __cpuinit remote_softirq_cpu_notify(struct notifier_block *self, +static int remote_softirq_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) { /* @@ -708,7 +708,7 @@ static int __cpuinit remote_softirq_cpu_notify(struct notifier_block *self, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata remote_softirq_cpu_notifier = { +static struct notifier_block remote_softirq_cpu_notifier = { .notifier_call = remote_softirq_cpu_notify, }; @@ -837,7 +837,7 @@ static void takeover_tasklets(unsigned int cpu) } #endif /* CONFIG_HOTPLUG_CPU */ -static int __cpuinit cpu_callback(struct notifier_block *nfb, +static int cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { @@ -888,7 +888,7 @@ static int __cpuinit cpu_callback(struct notifier_block *nfb, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata cpu_nfb = { +static struct notifier_block cpu_nfb = { .notifier_call = cpu_callback }; diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c index 2f194e96571..9e4017a58b3 100644 --- a/kernel/stop_machine.c +++ b/kernel/stop_machine.c @@ -299,7 +299,7 @@ static int cpu_stopper_thread(void *data) extern void sched_set_stop_task(int cpu, struct task_struct *stop); /* manage stopper for a cpu, mostly lifted from sched migration thread mgmt */ -static int __cpuinit cpu_stop_cpu_callback(struct notifier_block *nfb, +static int cpu_stop_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { unsigned int cpu = (unsigned long)hcpu; @@ -362,7 +362,7 @@ static int __cpuinit cpu_stop_cpu_callback(struct notifier_block *nfb, * cpu notifiers. It currently shares the same priority as sched * migration_notifier. */ -static struct notifier_block __cpuinitdata cpu_stop_cpu_notifier = { +static struct notifier_block cpu_stop_cpu_notifier = { .notifier_call = cpu_stop_cpu_callback, .priority = 10, }; diff --git a/kernel/sys.c b/kernel/sys.c index 6e08068f359..7095efafff6 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -1935,6 +1935,9 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, current->timer_slack_ns = arg2; error = 0; break; + case PR_GET_EFFECTIVE_TIMERSLACK: + error = task_get_effective_timer_slack(current); + break; case PR_MCE_KILL: if (arg4 | arg5) return -EINVAL; diff --git a/kernel/sysctl.c b/kernel/sysctl.c index b69314289ae..178759331b4 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -2040,7 +2040,7 @@ static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table, int int vleft, first = 1, err = 0; unsigned long page = 0; size_t left; - char *kbuf; + char *kbuf = NULL; if (!data || !table->maxlen || !*lenp || (*ppos && !write)) { *lenp = 0; diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index c6cd85b8852..30d7bebe94f 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -503,7 +503,9 @@ void tick_nohz_irq_exit(void) if (!ts->inidle) return; - + + /* Cancel the timer because CPU already waken up from the C-states*/ + menu_hrtimer_cancel(); tick_nohz_stop_sched_tick(ts); } @@ -567,6 +569,8 @@ void tick_nohz_idle_exit(void) ts->inidle = 0; + /* Cancel the timer because CPU already waken up from the C-states*/ + menu_hrtimer_cancel(); if (ts->idle_active || ts->tick_stopped) now = ktime_get(); diff --git a/kernel/timer.c b/kernel/timer.c index 02dbb092efa..e2e6145486e 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -1645,11 +1645,11 @@ SYSCALL_DEFINE1(sysinfo, struct sysinfo __user *, info) return 0; } -static int __cpuinit init_timers_cpu(int cpu) +static int init_timers_cpu(int cpu) { int j; struct tvec_base *base; - static char __cpuinitdata tvec_base_done[NR_CPUS]; + static char tvec_base_done[NR_CPUS]; if (!tvec_base_done[cpu]) { static char boot_done; @@ -1718,7 +1718,7 @@ static void migrate_timer_list(struct tvec_base *new_base, struct list_head *hea } } -static void __cpuinit migrate_timers(int cpu) +static void migrate_timers(int cpu) { struct tvec_base *old_base; struct tvec_base *new_base; @@ -1751,7 +1751,7 @@ static void __cpuinit migrate_timers(int cpu) } #endif /* CONFIG_HOTPLUG_CPU */ -static int __cpuinit timer_cpu_notify(struct notifier_block *self, +static int timer_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) { long cpu = (long)hcpu; @@ -1776,7 +1776,7 @@ static int __cpuinit timer_cpu_notify(struct notifier_block *self, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata timers_nb = { +static struct notifier_block timers_nb = { .notifier_call = timer_cpu_notify, }; diff --git a/kernel/watchdog.c b/kernel/watchdog.c index df30ee08bdd..6959c6fbeee 100644 --- a/kernel/watchdog.c +++ b/kernel/watchdog.c @@ -546,7 +546,7 @@ int proc_dowatchdog(struct ctl_table *table, int write, /* * Create/destroy watchdog threads as CPUs come and go: */ -static int __cpuinit +static int cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { int hotcpu = (unsigned long)hcpu; @@ -581,7 +581,7 @@ cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) return NOTIFY_OK; } -static struct notifier_block __cpuinitdata cpu_nfb = { +static struct notifier_block cpu_nfb = { .notifier_call = cpu_callback }; diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 7da267c8d0d..2cbbbb0b14e 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -3309,7 +3309,7 @@ EXPORT_SYMBOL_GPL(work_busy); __ret1 < 0 ? -1 : 0; \ }) -static int __cpuinit trustee_thread(void *__gcwq) +static int trustee_thread(void *__gcwq) { struct global_cwq *gcwq = __gcwq; struct worker *worker; @@ -3475,7 +3475,7 @@ static int __cpuinit trustee_thread(void *__gcwq) * spin_lock_irq(gcwq->lock) which may be released and regrabbed * multiple times. To be used by cpu_callback. */ -static void __cpuinit wait_trustee_state(struct global_cwq *gcwq, int state) +static void wait_trustee_state(struct global_cwq *gcwq, int state) __releases(&gcwq->lock) __acquires(&gcwq->lock) { @@ -3489,7 +3489,7 @@ __acquires(&gcwq->lock) } } -static int __devinit workqueue_cpu_callback(struct notifier_block *nfb, +static int workqueue_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { @@ -3660,7 +3660,12 @@ void freeze_workqueues_begin(void) gcwq->flags |= GCWQ_FREEZING; list_for_each_entry(wq, &workqueues, list) { - struct cpu_workqueue_struct *cwq = get_cwq(cpu, wq); + + struct cpu_workqueue_struct *cwq; + if (cpu < CONFIG_NR_CPUS) + cwq = get_cwq(cpu, wq); + else + continue; if (cwq && wq->flags & WQ_FREEZABLE) cwq->max_active = 0; @@ -3701,7 +3706,12 @@ bool freeze_workqueues_busy(void) * to peek without lock. */ list_for_each_entry(wq, &workqueues, list) { - struct cpu_workqueue_struct *cwq = get_cwq(cpu, wq); + + struct cpu_workqueue_struct *cwq; + if (cpu < CONFIG_NR_CPUS) + cwq = get_cwq(cpu, wq); + else + continue; if (!cwq || !(wq->flags & WQ_FREEZABLE)) continue; diff --git a/lib/Makefile b/lib/Makefile index acd68695763..07086c99fe1 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -12,7 +12,8 @@ lib-y := ctype.o string.o vsprintf.o cmdline.o \ idr.o int_sqrt.o extable.o prio_tree.o \ sha1.o md5.o irq_regs.o reciprocal_div.o argv_split.o \ proportions.o prio_heap.o ratelimit.o show_mem.o \ - is_single_threaded.o plist.o decompress.o memory_alloc.o + is_single_threaded.o plist.o decompress.o memory_alloc.o \ + memcopy.o lib-$(CONFIG_MMU) += ioremap.o lib-$(CONFIG_SMP) += cpumask.o diff --git a/lib/int_sqrt.c b/lib/int_sqrt.c index fc2eeb7cb2e..1ef4cc34497 100644 --- a/lib/int_sqrt.c +++ b/lib/int_sqrt.c @@ -1,3 +1,9 @@ +/* + * Copyright (C) 2013 Davidlohr Bueso + * + * Based on the shift-and-subtract algorithm for computing integer + * square root from Guy L. Steele. + */ #include #include @@ -10,23 +16,23 @@ */ unsigned long int_sqrt(unsigned long x) { - unsigned long op, res, one; + unsigned long b, m, y = 0; - op = x; - res = 0; + if (x <= 1) + return x; - one = 1UL << (BITS_PER_LONG - 2); - while (one > op) - one >>= 2; + m = 1UL << (BITS_PER_LONG - 2); + while (m != 0) { + b = y + m; + y >>= 1; - while (one != 0) { - if (op >= res + one) { - op = op - (res + one); - res = res + 2 * one; + if (x >= b) { + x -= b; + y += m; } - res /= 2; - one /= 4; + m >>= 2; } - return res; + + return y; } EXPORT_SYMBOL(int_sqrt); diff --git a/lib/memcopy.c b/lib/memcopy.c new file mode 100644 index 00000000000..d2d3376f738 --- /dev/null +++ b/lib/memcopy.c @@ -0,0 +1,403 @@ +/* + * memcopy.c -- subroutines for memory copy functions. + * + * 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.1 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., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * The code is derived from the GNU C Library. + * Copyright (C) 1991, 1992, 1993, 1997, 2004 Free Software Foundation, Inc. + */ + +/* BE VERY CAREFUL IF YOU CHANGE THIS CODE...! */ + +#include + +/* + * _wordcopy_fwd_aligned -- Copy block beginning at SRCP to block beginning + * at DSTP with LEN `op_t' words (not LEN bytes!). + * Both SRCP and DSTP should be aligned for memory operations on `op_t's. + */ +void _wordcopy_fwd_aligned (long int dstp, long int srcp, size_t len) +{ + op_t a0, a1; + + switch (len % 8) { + case 2: + a0 = ((op_t *) srcp)[0]; + srcp -= 6 * OPSIZ; + dstp -= 7 * OPSIZ; + len += 6; + goto do1; + case 3: + a1 = ((op_t *) srcp)[0]; + srcp -= 5 * OPSIZ; + dstp -= 6 * OPSIZ; + len += 5; + goto do2; + case 4: + a0 = ((op_t *) srcp)[0]; + srcp -= 4 * OPSIZ; + dstp -= 5 * OPSIZ; + len += 4; + goto do3; + case 5: + a1 = ((op_t *) srcp)[0]; + srcp -= 3 * OPSIZ; + dstp -= 4 * OPSIZ; + len += 3; + goto do4; + case 6: + a0 = ((op_t *) srcp)[0]; + srcp -= 2 * OPSIZ; + dstp -= 3 * OPSIZ; + len += 2; + goto do5; + case 7: + a1 = ((op_t *) srcp)[0]; + srcp -= 1 * OPSIZ; + dstp -= 2 * OPSIZ; + len += 1; + goto do6; + case 0: + if (OP_T_THRESHOLD <= 3 * OPSIZ && len == 0) + return; + a0 = ((op_t *) srcp)[0]; + srcp -= 0 * OPSIZ; + dstp -= 1 * OPSIZ; + goto do7; + case 1: + a1 = ((op_t *) srcp)[0]; + srcp -=-1 * OPSIZ; + dstp -= 0 * OPSIZ; + len -= 1; + if (OP_T_THRESHOLD <= 3 * OPSIZ && len == 0) + goto do0; + goto do8; /* No-op. */ + } + + do { +do8: + a0 = ((op_t *) srcp)[0]; + ((op_t *) dstp)[0] = a1; +do7: + a1 = ((op_t *) srcp)[1]; + ((op_t *) dstp)[1] = a0; +do6: + a0 = ((op_t *) srcp)[2]; + ((op_t *) dstp)[2] = a1; +do5: + a1 = ((op_t *) srcp)[3]; + ((op_t *) dstp)[3] = a0; +do4: + a0 = ((op_t *) srcp)[4]; + ((op_t *) dstp)[4] = a1; +do3: + a1 = ((op_t *) srcp)[5]; + ((op_t *) dstp)[5] = a0; +do2: + a0 = ((op_t *) srcp)[6]; + ((op_t *) dstp)[6] = a1; +do1: + a1 = ((op_t *) srcp)[7]; + ((op_t *) dstp)[7] = a0; + + srcp += 8 * OPSIZ; + dstp += 8 * OPSIZ; + len -= 8; + } while (len != 0); + + /* + * This is the right position for do0. Please don't move it into + * the loop. + */ +do0: + ((op_t *) dstp)[0] = a1; +} + +/* + * _wordcopy_fwd_dest_aligned -- Copy block beginning at SRCP to block + * beginning at DSTP with LEN `op_t' words (not LEN bytes!). DSTP should + * be aligned for memory operations on `op_t's, but SRCP must *not* be aligned. + */ + +void _wordcopy_fwd_dest_aligned (long int dstp, long int srcp, size_t len) +{ + op_t a0, a1, a2, a3; + int sh_1, sh_2; + + /* + * Calculate how to shift a word read at the memory operation aligned + * srcp to make it aligned for copy. + */ + sh_1 = 8 * (srcp % OPSIZ); + sh_2 = 8 * OPSIZ - sh_1; + + /* + * Make SRCP aligned by rounding it down to the beginning of the `op_t' + * it points in the middle of. + */ + srcp &= -OPSIZ; + + switch (len % 4) { + case 2: + a1 = ((op_t *) srcp)[0]; + a2 = ((op_t *) srcp)[1]; + srcp -= 1 * OPSIZ; + dstp -= 3 * OPSIZ; + len += 2; + goto do1; + case 3: + a0 = ((op_t *) srcp)[0]; + a1 = ((op_t *) srcp)[1]; + srcp -= 0 * OPSIZ; + dstp -= 2 * OPSIZ; + len += 1; + goto do2; + case 0: + if (OP_T_THRESHOLD <= 3 * OPSIZ && len == 0) + return; + a3 = ((op_t *) srcp)[0]; + a0 = ((op_t *) srcp)[1]; + srcp -=-1 * OPSIZ; + dstp -= 1 * OPSIZ; + len += 0; + goto do3; + case 1: + a2 = ((op_t *) srcp)[0]; + a3 = ((op_t *) srcp)[1]; + srcp -=-2 * OPSIZ; + dstp -= 0 * OPSIZ; + len -= 1; + if (OP_T_THRESHOLD <= 3 * OPSIZ && len == 0) + goto do0; + goto do4; /* No-op. */ + } + + do { +do4: + a0 = ((op_t *) srcp)[0]; + ((op_t *) dstp)[0] = MERGE (a2, sh_1, a3, sh_2); +do3: + a1 = ((op_t *) srcp)[1]; + ((op_t *) dstp)[1] = MERGE (a3, sh_1, a0, sh_2); +do2: + a2 = ((op_t *) srcp)[2]; + ((op_t *) dstp)[2] = MERGE (a0, sh_1, a1, sh_2); +do1: + a3 = ((op_t *) srcp)[3]; + ((op_t *) dstp)[3] = MERGE (a1, sh_1, a2, sh_2); + + srcp += 4 * OPSIZ; + dstp += 4 * OPSIZ; + len -= 4; + } while (len != 0); + + /* + * This is the right position for do0. Please don't move it into + * the loop. + */ +do0: + ((op_t *) dstp)[0] = MERGE (a2, sh_1, a3, sh_2); +} + +/* + * _wordcopy_bwd_aligned -- Copy block finishing right before + * SRCP to block finishing right before DSTP with LEN `op_t' words (not LEN + * bytes!). Both SRCP and DSTP should be aligned for memory operations + * on `op_t's. + */ +void _wordcopy_bwd_aligned (long int dstp, long int srcp, size_t len) +{ + op_t a0, a1; + + switch (len % 8) { + case 2: + srcp -= 2 * OPSIZ; + dstp -= 1 * OPSIZ; + a0 = ((op_t *) srcp)[1]; + len += 6; + goto do1; + case 3: + srcp -= 3 * OPSIZ; + dstp -= 2 * OPSIZ; + a1 = ((op_t *) srcp)[2]; + len += 5; + goto do2; + case 4: + srcp -= 4 * OPSIZ; + dstp -= 3 * OPSIZ; + a0 = ((op_t *) srcp)[3]; + len += 4; + goto do3; + case 5: + srcp -= 5 * OPSIZ; + dstp -= 4 * OPSIZ; + a1 = ((op_t *) srcp)[4]; + len += 3; + goto do4; + case 6: + srcp -= 6 * OPSIZ; + dstp -= 5 * OPSIZ; + a0 = ((op_t *) srcp)[5]; + len += 2; + goto do5; + case 7: + srcp -= 7 * OPSIZ; + dstp -= 6 * OPSIZ; + a1 = ((op_t *) srcp)[6]; + len += 1; + goto do6; + case 0: + if (OP_T_THRESHOLD <= 3 * OPSIZ && len == 0) + return; + srcp -= 8 * OPSIZ; + dstp -= 7 * OPSIZ; + a0 = ((op_t *) srcp)[7]; + goto do7; + case 1: + srcp -= 9 * OPSIZ; + dstp -= 8 * OPSIZ; + a1 = ((op_t *) srcp)[8]; + len -= 1; + if (OP_T_THRESHOLD <= 3 * OPSIZ && len == 0) + goto do0; + goto do8; /* No-op. */ + } + + do { +do8: + a0 = ((op_t *) srcp)[7]; + ((op_t *) dstp)[7] = a1; +do7: + a1 = ((op_t *) srcp)[6]; + ((op_t *) dstp)[6] = a0; +do6: + a0 = ((op_t *) srcp)[5]; + ((op_t *) dstp)[5] = a1; +do5: + a1 = ((op_t *) srcp)[4]; + ((op_t *) dstp)[4] = a0; +do4: + a0 = ((op_t *) srcp)[3]; + ((op_t *) dstp)[3] = a1; +do3: + a1 = ((op_t *) srcp)[2]; + ((op_t *) dstp)[2] = a0; +do2: + a0 = ((op_t *) srcp)[1]; + ((op_t *) dstp)[1] = a1; +do1: + a1 = ((op_t *) srcp)[0]; + ((op_t *) dstp)[0] = a0; + + srcp -= 8 * OPSIZ; + dstp -= 8 * OPSIZ; + len -= 8; + } while (len != 0); + + /* + * This is the right position for do0. Please don't move it into + * the loop. + */ +do0: + ((op_t *) dstp)[7] = a1; +} + +/* + * _wordcopy_bwd_dest_aligned -- Copy block finishing right before SRCP to + * block finishing right before DSTP with LEN `op_t' words (not LEN bytes!). + * DSTP should be aligned for memory operations on `op_t', but SRCP must *not* + * be aligned. + */ +void _wordcopy_bwd_dest_aligned (long int dstp, long int srcp, size_t len) +{ + op_t a0, a1, a2, a3; + int sh_1, sh_2; + + /* + * Calculate how to shift a word read at the memory operation aligned + * srcp to make it aligned for copy. + */ + + sh_1 = 8 * (srcp % OPSIZ); + sh_2 = 8 * OPSIZ - sh_1; + + /* + * Make srcp aligned by rounding it down to the beginning of the op_t + * it points in the middle of. + */ + srcp &= -OPSIZ; + srcp += OPSIZ; + + switch (len % 4) { + case 2: + srcp -= 3 * OPSIZ; + dstp -= 1 * OPSIZ; + a2 = ((op_t *) srcp)[2]; + a1 = ((op_t *) srcp)[1]; + len += 2; + goto do1; + case 3: + srcp -= 4 * OPSIZ; + dstp -= 2 * OPSIZ; + a3 = ((op_t *) srcp)[3]; + a2 = ((op_t *) srcp)[2]; + len += 1; + goto do2; + case 0: + if (OP_T_THRESHOLD <= 3 * OPSIZ && len == 0) + return; + srcp -= 5 * OPSIZ; + dstp -= 3 * OPSIZ; + a0 = ((op_t *) srcp)[4]; + a3 = ((op_t *) srcp)[3]; + goto do3; + case 1: + srcp -= 6 * OPSIZ; + dstp -= 4 * OPSIZ; + a1 = ((op_t *) srcp)[5]; + a0 = ((op_t *) srcp)[4]; + len -= 1; + if (OP_T_THRESHOLD <= 3 * OPSIZ && len == 0) + goto do0; + goto do4; /* No-op. */ + } + + do { +do4: + a3 = ((op_t *) srcp)[3]; + ((op_t *) dstp)[3] = MERGE (a0, sh_1, a1, sh_2); +do3: + a2 = ((op_t *) srcp)[2]; + ((op_t *) dstp)[2] = MERGE (a3, sh_1, a0, sh_2); +do2: + a1 = ((op_t *) srcp)[1]; + ((op_t *) dstp)[1] = MERGE (a2, sh_1, a3, sh_2); +do1: + a0 = ((op_t *) srcp)[0]; + ((op_t *) dstp)[0] = MERGE (a1, sh_1, a2, sh_2); + + srcp -= 4 * OPSIZ; + dstp -= 4 * OPSIZ; + len -= 4; + } while (len != 0); + + /* + * This is the right position for do0. Please don't move it into + * the loop. + */ +do0: + ((op_t *) dstp)[3] = MERGE (a0, sh_1, a1, sh_2); +} + diff --git a/lib/percpu_counter.c b/lib/percpu_counter.c index f8a3f1a829b..40bbe68c2f3 100644 --- a/lib/percpu_counter.c +++ b/lib/percpu_counter.c @@ -158,7 +158,7 @@ static void compute_batch_value(void) percpu_counter_batch = max(32, nr*2); } -static int __cpuinit percpu_counter_hotcpu_callback(struct notifier_block *nb, +static int percpu_counter_hotcpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu) { #ifdef CONFIG_HOTPLUG_CPU diff --git a/lib/string.c b/lib/string.c index e5878de4f10..070a3edbeb3 100644 --- a/lib/string.c +++ b/lib/string.c @@ -26,6 +26,7 @@ #include #include #include +#include #ifndef __HAVE_ARCH_STRNICMP /** @@ -598,11 +599,11 @@ EXPORT_SYMBOL(memset); */ void *memcpy(void *dest, const void *src, size_t count) { - char *tmp = dest; - const char *s = src; + unsigned long dstp = (unsigned long)dest; + unsigned long srcp = (unsigned long)src; - while (count--) - *tmp++ = *s++; + /* Copy from the beginning to the end */ + mem_copy_fwd(dstp, srcp, count); return dest; } EXPORT_SYMBOL(memcpy); @@ -619,21 +620,15 @@ EXPORT_SYMBOL(memcpy); */ void *memmove(void *dest, const void *src, size_t count) { - char *tmp; - const char *s; + unsigned long dstp = (unsigned long)dest; + unsigned long srcp = (unsigned long)src; - if (dest <= src) { - tmp = dest; - s = src; - while (count--) - *tmp++ = *s++; + if (dest - src >= count) { + /* Copy from the beginning to the end */ + mem_copy_fwd(dstp, srcp, count); } else { - tmp = dest; - tmp += count; - s = src; - s += count; - while (count--) - *--tmp = *--s; + /* Copy from the end to the beginning */ + mem_copy_bwd(dstp, srcp, count); } return dest; } diff --git a/mm/ksm.c b/mm/ksm.c index 47c88536889..f1c4fe6cfd6 100644 --- a/mm/ksm.c +++ b/mm/ksm.c @@ -184,10 +184,10 @@ static unsigned long ksm_pages_unshared; static unsigned long ksm_rmap_items; /* Number of pages ksmd should scan in one batch */ -static unsigned int ksm_thread_pages_to_scan = 100; +static unsigned int ksm_thread_pages_to_scan = 256; /* Milliseconds ksmd should sleep between batches */ -static unsigned int ksm_thread_sleep_millisecs = 20; +static unsigned int ksm_thread_sleep_millisecs = 1500; #define KSM_RUN_STOP 0 #define KSM_RUN_MERGE 1 diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 7685d4a0b3c..33a177ae444 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -2154,7 +2154,7 @@ static void mem_cgroup_drain_pcp_counter(struct mem_cgroup *memcg, int cpu) spin_unlock(&memcg->pcp_counter_lock); } -static int __cpuinit memcg_cpu_hotplug_callback(struct notifier_block *nb, +static int memcg_cpu_hotplug_callback(struct notifier_block *nb, unsigned long action, void *hcpu) { diff --git a/mm/mempolicy.c b/mm/mempolicy.c index b1956913752..bf5b485ecd3 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -607,27 +607,6 @@ check_range(struct mm_struct *mm, unsigned long start, unsigned long end, return first; } -/* Apply policy to a single VMA */ -static int policy_vma(struct vm_area_struct *vma, struct mempolicy *new) -{ - int err = 0; - struct mempolicy *old = vma->vm_policy; - - pr_debug("vma %lx-%lx/%lx vm_ops %p vm_file %p set_policy %p\n", - vma->vm_start, vma->vm_end, vma->vm_pgoff, - vma->vm_ops, vma->vm_file, - vma->vm_ops ? vma->vm_ops->set_policy : NULL); - - if (vma->vm_ops && vma->vm_ops->set_policy) - err = vma->vm_ops->set_policy(vma, new); - if (!err) { - mpol_get(new); - vma->vm_policy = new; - mpol_put(old); - } - return err; -} - /* Step 2: apply policy to a range and do splits. */ static int mbind_range(struct mm_struct *mm, unsigned long start, unsigned long end, struct mempolicy *new_pol) @@ -676,9 +655,23 @@ static int mbind_range(struct mm_struct *mm, unsigned long start, if (err) goto out; } - err = policy_vma(vma, new_pol); - if (err) - goto out; + + /* + * Apply policy to a single VMA. The reference counting of + * policy for vma_policy linkages has already been handled by + * vma_merge and split_vma as necessary. If this is a shared + * policy then ->set_policy will increment the reference count + * for an sp node. + */ + pr_debug("vma %lx-%lx/%lx vm_ops %p vm_file %p set_policy %p\n", + vma->vm_start, vma->vm_end, vma->vm_pgoff, + vma->vm_ops, vma->vm_file, + vma->vm_ops ? vma->vm_ops->set_policy : NULL); + if (vma->vm_ops && vma->vm_ops->set_policy) { + err = vma->vm_ops->set_policy(vma, new_pol); + if (err) + goto out; + } } out: diff --git a/mm/page-writeback.c b/mm/page-writeback.c index 26adea8ca2e..102b62f8534 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c @@ -65,7 +65,7 @@ static long ratelimit_pages = 32; /* * Start background writeback (via writeback threads) at this percentage */ -int dirty_background_ratio = 10; +int dirty_background_ratio = 1; /* * dirty_background_bytes starts at 0 (disabled) so that it is a function of @@ -82,7 +82,7 @@ int vm_highmem_is_dirtyable; /* * The generator of dirty data starts writeback at this percentage */ -int vm_dirty_ratio = 20; +int vm_dirty_ratio = 2; /* * vm_dirty_bytes starts at 0 (disabled) so that it is a function of @@ -93,14 +93,14 @@ unsigned long vm_dirty_bytes; /* * The interval between `kupdate'-style writebacks */ -unsigned int dirty_writeback_interval = 5 * 100; /* centiseconds */ +unsigned int dirty_writeback_interval = 3 * 100; /* centiseconds */ EXPORT_SYMBOL_GPL(dirty_writeback_interval); /* * The longest time for which data is allowed to remain dirty */ -unsigned int dirty_expire_interval = 30 * 100; /* centiseconds */ +unsigned int dirty_expire_interval = 50; /* centiseconds */ /* * Flag that makes the machine dump writes/reads and block dirtyings. @@ -1041,7 +1041,7 @@ static void bdi_update_bandwidth(struct backing_dev_info *bdi, } /* - * After a task dirtied this many pages, balance_dirty_pages_ratelimited_nr() + * After a task dirtied this many pages, balance_dirty_pages_ratelimited() * will look to see if it needs to start dirty throttling. * * If dirty_poll_interval is too low, big NUMA machines will call the expensive @@ -1408,9 +1408,8 @@ static DEFINE_PER_CPU(int, bdp_ratelimits); DEFINE_PER_CPU(int, dirty_throttle_leaks) = 0; /** - * balance_dirty_pages_ratelimited_nr - balance dirty memory state + * balance_dirty_pages_ratelimited - balance dirty memory state * @mapping: address_space which was dirtied - * @nr_pages_dirtied: number of pages which the caller has just dirtied * * Processes which are dirtying memory should call in here once for each page * which was newly dirtied. The function will periodically check the system's @@ -1421,8 +1420,7 @@ DEFINE_PER_CPU(int, dirty_throttle_leaks) = 0; * limit we decrease the ratelimiting by a lot, to prevent individual processes * from overshooting the limit by (ratelimit_pages) each. */ -void balance_dirty_pages_ratelimited_nr(struct address_space *mapping, - unsigned long nr_pages_dirtied) +void balance_dirty_pages_ratelimited(struct address_space *mapping) { struct backing_dev_info *bdi = mapping->backing_dev_info; int ratelimit; @@ -1456,6 +1454,7 @@ void balance_dirty_pages_ratelimited_nr(struct address_space *mapping, */ p = &__get_cpu_var(dirty_throttle_leaks); if (*p > 0 && current->nr_dirtied < ratelimit) { + unsigned long nr_pages_dirtied; nr_pages_dirtied = min(*p, ratelimit - current->nr_dirtied); *p -= nr_pages_dirtied; current->nr_dirtied += nr_pages_dirtied; @@ -1465,7 +1464,7 @@ void balance_dirty_pages_ratelimited_nr(struct address_space *mapping, if (unlikely(current->nr_dirtied >= ratelimit)) balance_dirty_pages(mapping, current->nr_dirtied); } -EXPORT_SYMBOL(balance_dirty_pages_ratelimited_nr); +EXPORT_SYMBOL(balance_dirty_pages_ratelimited); void throttle_vm_writeout(gfp_t gfp_mask) { @@ -1573,14 +1572,14 @@ void writeback_set_ratelimit(void) ratelimit_pages = 16; } -static int __cpuinit +static int ratelimit_handler(struct notifier_block *self, unsigned long u, void *v) { writeback_set_ratelimit(); return NOTIFY_DONE; } -static struct notifier_block __cpuinitdata ratelimit_nb = { +static struct notifier_block ratelimit_nb = { .notifier_call = ratelimit_handler, .next = NULL, }; diff --git a/mm/page_cgroup.c b/mm/page_cgroup.c index 1ccbd714059..fa9ac6263c3 100644 --- a/mm/page_cgroup.c +++ b/mm/page_cgroup.c @@ -285,7 +285,15 @@ void __init page_cgroup_init(void) pfn < end_pfn; pfn = ALIGN(pfn + 1, PAGES_PER_SECTION)) { - if (!pfn_valid(pfn)) + /* + * even if the first pfn is invalid, that doesn't mean + * that the entire section is not used. + * so we should check if the section has the mem map. + * if it has the mem map then we should go ahead and + * create the page cgroup. + */ + struct mem_section *section = __pfn_to_section(pfn); + if (!section->section_mem_map) continue; /* * Nodes's pfns can be overlapping. diff --git a/mm/slab.c b/mm/slab.c index e901a36e252..10d0d001df8 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -909,7 +909,7 @@ static void next_reap_node(void) * the CPUs getting into lockstep and contending for the global cache chain * lock. */ -static void __cpuinit start_cpu_timer(int cpu) +static void start_cpu_timer(int cpu) { struct delayed_work *reap_work = &per_cpu(slab_reap_work, cpu); @@ -1184,7 +1184,7 @@ static int init_cache_nodelists_node(int node) return 0; } -static void __cpuinit cpuup_canceled(long cpu) +static void cpuup_canceled(long cpu) { struct kmem_cache *cachep; struct kmem_list3 *l3 = NULL; @@ -1249,7 +1249,7 @@ static void __cpuinit cpuup_canceled(long cpu) } } -static int __cpuinit cpuup_prepare(long cpu) +static int cpuup_prepare(long cpu) { struct kmem_cache *cachep; struct kmem_list3 *l3 = NULL; @@ -1329,7 +1329,7 @@ static int __cpuinit cpuup_prepare(long cpu) return -ENOMEM; } -static int __cpuinit cpuup_callback(struct notifier_block *nfb, +static int cpuup_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { long cpu = (long)hcpu; @@ -1385,7 +1385,7 @@ static int __cpuinit cpuup_callback(struct notifier_block *nfb, return notifier_from_errno(err); } -static struct notifier_block __cpuinitdata cpucache_notifier = { +static struct notifier_block cpucache_notifier = { &cpuup_callback, NULL, 0 }; diff --git a/mm/slub.c b/mm/slub.c index 925484e795d..4941dc9cf72 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -2629,7 +2629,7 @@ EXPORT_SYMBOL(kmem_cache_free); * take the list_lock. */ static int slub_min_order; -static int slub_max_order = PAGE_ALLOC_COSTLY_ORDER; +static int slub_max_order = 0; static int slub_min_objects; /* @@ -3990,7 +3990,7 @@ EXPORT_SYMBOL(kmem_cache_create); * Use the cpu notifier to insure that the cpu slabs are flushed when * necessary. */ -static int __cpuinit slab_cpuup_callback(struct notifier_block *nfb, +static int slab_cpuup_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { long cpu = (long)hcpu; @@ -4016,7 +4016,7 @@ static int __cpuinit slab_cpuup_callback(struct notifier_block *nfb, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata slab_notifier = { +static struct notifier_block slab_notifier = { .notifier_call = slab_cpuup_callback }; diff --git a/mm/vmscan.c b/mm/vmscan.c index 33dc256033b..fd8ef669f36 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -3236,7 +3236,7 @@ unsigned long shrink_all_memory(unsigned long nr_to_reclaim) not required for correctness. So if the last cpu in a node goes away, we get changed to run anywhere: as the first one comes back, restore their cpu bindings. */ -static int __devinit cpu_callback(struct notifier_block *nfb, +static int cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { int nid; diff --git a/mm/vmstat.c b/mm/vmstat.c index 8e18d6b44c1..760ae659731 100644 --- a/mm/vmstat.c +++ b/mm/vmstat.c @@ -1153,7 +1153,7 @@ static void vmstat_update(struct work_struct *w) round_jiffies_relative(sysctl_stat_interval)); } -static void __cpuinit start_cpu_timer(int cpu) +static void start_cpu_timer(int cpu) { struct delayed_work *work = &per_cpu(vmstat_work, cpu); @@ -1165,7 +1165,7 @@ static void __cpuinit start_cpu_timer(int cpu) * Use the cpu notifier to insure that the thresholds are recalculated * when necessary. */ -static int __cpuinit vmstat_cpuup_callback(struct notifier_block *nfb, +static int vmstat_cpuup_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { @@ -1197,7 +1197,7 @@ static int __cpuinit vmstat_cpuup_callback(struct notifier_block *nfb, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata vmstat_notifier = +static struct notifier_block vmstat_notifier = { &vmstat_cpuup_callback, NULL, 0 }; #endif diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 50f73bebdd2..4412e8a276a 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -393,7 +393,7 @@ void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8], } EXPORT_SYMBOL(hci_le_start_enc); -void hci_le_ltk_reply(struct hci_conn *conn, u8 ltk[16]) +void hci_le_ltk_reply(struct hci_conn *conn, __u8 ltk[16]) { struct hci_dev *hdev = conn->hdev; struct hci_cp_le_ltk_reply cp; @@ -403,7 +403,7 @@ void hci_le_ltk_reply(struct hci_conn *conn, u8 ltk[16]) memset(&cp, 0, sizeof(cp)); cp.handle = cpu_to_le16(conn->handle); - memcpy(cp.ltk, ltk, sizeof(ltk)); + memcpy(cp.ltk, ltk, sizeof(*ltk)); hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp); } diff --git a/net/core/flow.c b/net/core/flow.c index e318c7e9804..b42d1414a1b 100644 --- a/net/core/flow.c +++ b/net/core/flow.c @@ -370,7 +370,7 @@ void flow_cache_flush_deferred(void) schedule_work(&flow_cache_flush_work); } -static int __cpuinit flow_cache_cpu_prepare(struct flow_cache *fc, int cpu) +static int flow_cache_cpu_prepare(struct flow_cache *fc, int cpu) { struct flow_cache_percpu *fcp = per_cpu_ptr(fc->percpu, cpu); size_t sz = sizeof(struct hlist_head) * flow_cache_hash_size(fc); @@ -388,7 +388,7 @@ static int __cpuinit flow_cache_cpu_prepare(struct flow_cache *fc, int cpu) return 0; } -static int __cpuinit flow_cache_cpu(struct notifier_block *nfb, +static int flow_cache_cpu(struct notifier_block *nfb, unsigned long action, void *hcpu) { diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 257b61789ee..4988e3e436f 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -4373,10 +4373,11 @@ static void tcp_sack_remove(struct tcp_sock *tp) return; } + BUG_ON(num_sacks > 4); for (this_sack = 0; this_sack < num_sacks;) { /* Check if the start of the sack is covered by RCV.NXT. */ if (!before(tp->rcv_nxt, sp->start_seq)) { - int i; + int i = 0; /* RCV.NXT must cover all the block! */ WARN_ON(before(tp->rcv_nxt, sp->end_seq)); diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c index 3ad1f9db5f8..a58216e4548 100644 --- a/net/iucv/iucv.c +++ b/net/iucv/iucv.c @@ -621,7 +621,7 @@ static void iucv_disable(void) put_online_cpus(); } -static int __cpuinit iucv_cpu_notify(struct notifier_block *self, +static int iucv_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) { cpumask_t cpumask; diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c index 722291f8af7..70512e9a5ed 100644 --- a/net/netfilter/nf_conntrack_h323_main.c +++ b/net/netfilter/nf_conntrack_h323_main.c @@ -566,8 +566,8 @@ static int h245_help(struct sk_buff *skb, unsigned int protoff, { static MultimediaSystemControlMessage mscm; unsigned char *data = NULL; - int datalen; - int dataoff; + int datalen = 0; + int dataoff = 0; int ret; /* Until there's been traffic both ways, don't look in packets. */ @@ -1118,8 +1118,8 @@ static int q931_help(struct sk_buff *skb, unsigned int protoff, { static Q931 q931; unsigned char *data = NULL; - int datalen; - int dataoff; + int datalen = 0; + int dataoff = 0; int ret; /* Until there's been traffic both ways, don't look in packets. */ diff --git a/net/socket.c b/net/socket.c index 851edcd6b09..5e6e6218684 100644 --- a/net/socket.c +++ b/net/socket.c @@ -1322,7 +1322,7 @@ EXPORT_SYMBOL(sock_create_kern); SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol) { int retval; - struct socket *sock; + struct socket *sock = NULL; int flags; /* Check the SOCK_* constants for consistency. */ @@ -1363,7 +1363,7 @@ SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol) SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol, int __user *, usockvec) { - struct socket *sock1, *sock2; + struct socket *sock1 = NULL, *sock2; int fd1, fd2, err; struct file *newfile1, *newfile2; int flags; diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index 994cfea2bad..0c20629952c 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c @@ -233,7 +233,7 @@ static int rpc_wait_bit_killable(void *word) { if (fatal_signal_pending(current)) return -ERESTARTSYS; - freezable_schedule(); + freezable_schedule_unsafe(); return 0; } diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c index b97a3dd9a60..a95081721c2 100644 --- a/net/sunrpc/xdr.c +++ b/net/sunrpc/xdr.c @@ -880,6 +880,8 @@ int read_bytes_from_xdr_buf(struct xdr_buf *buf, unsigned int base, void *obj, u { struct xdr_buf subbuf; int status; + subbuf.pages = 0; + subbuf.page_base = 0; status = xdr_buf_subsegment(buf, &subbuf, base, len); if (status != 0) @@ -911,6 +913,8 @@ int write_bytes_to_xdr_buf(struct xdr_buf *buf, unsigned int base, void *obj, un { struct xdr_buf subbuf; int status; + subbuf.pages = 0; + subbuf.page_base = 0; status = xdr_buf_subsegment(buf, &subbuf, base, len); if (status != 0) @@ -950,6 +954,8 @@ EXPORT_SYMBOL_GPL(xdr_encode_word); int xdr_buf_read_netobj(struct xdr_buf *buf, struct xdr_netobj *obj, unsigned int offset) { struct xdr_buf subbuf; + subbuf.pages = 0; + subbuf.page_base = 0; if (xdr_decode_word(buf, offset, &obj->len)) return -EFAULT; diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 109e30beaa6..a3fe72ad969 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -114,6 +114,7 @@ #include #include #include +#include struct hlist_head unix_socket_table[UNIX_HASH_SIZE + 1]; EXPORT_SYMBOL_GPL(unix_socket_table); @@ -824,7 +825,7 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) struct dentry *dentry = NULL; struct path path; int err; - unsigned hash; + unsigned hash = 0; struct unix_address *addr; struct hlist_head *list; @@ -964,7 +965,7 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr, struct net *net = sock_net(sk); struct sockaddr_un *sunaddr = (struct sockaddr_un *)addr; struct sock *other; - unsigned hash; + unsigned hash = 0; int err; if (addr->sa_family != AF_UNSPEC) { @@ -1062,7 +1063,7 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr, struct sock *newsk = NULL; struct sock *other = NULL; struct sk_buff *skb = NULL; - unsigned hash; + unsigned hash = 0; int st; int err; long timeo; @@ -1437,7 +1438,7 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock, struct sock *other = NULL; int namelen = 0; /* fake GCC */ int err; - unsigned hash; + unsigned hash = 0; struct sk_buff *skb; long timeo; struct scm_cookie tmp_scm; @@ -1874,7 +1875,7 @@ static long unix_stream_data_wait(struct sock *sk, long timeo) set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); unix_state_unlock(sk); - timeo = schedule_timeout(timeo); + timeo = freezable_schedule_timeout(timeo); unix_state_lock(sk); clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); } diff --git a/net/wireless/reg.c b/net/wireless/reg.c index e9a0ac83b84..15f347477a9 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -388,7 +388,15 @@ static void reg_regdb_query(const char *alpha2) schedule_work(®_regdb_work); } + +/* Feel free to add any other sanity checks here */ +static void reg_regdb_size_check(void) +{ + /* We should ideally BUILD_BUG_ON() but then random builds would fail */ + WARN_ONCE(!reg_regdb_size, "db.txt is empty, you should update it..."); +} #else +static inline void reg_regdb_size_check(void) {} static inline void reg_regdb_query(const char *alpha2) {} #endif /* CONFIG_CFG80211_INTERNAL_REGDB */ @@ -2322,6 +2330,8 @@ int __init regulatory_init(void) spin_lock_init(®_requests_lock); spin_lock_init(®_pending_beacons_lock); + reg_regdb_size_check(); + cfg80211_regdomain = cfg80211_world_regdom; user_alpha2[0] = '9'; diff --git a/release/Flashable-flo-AOSP/.gitignore b/release/Flashable-flo-AOSP/.gitignore new file mode 100644 index 00000000000..c4c4ffc6aa4 --- /dev/null +++ b/release/Flashable-flo-AOSP/.gitignore @@ -0,0 +1 @@ +*.zip diff --git a/release/aroma/META-INF/CERT.RSA b/release/aroma/META-INF/CERT.RSA new file mode 100755 index 0000000000000000000000000000000000000000..708be758cb8d4d6126a499597bbc5e49ed033fbf GIT binary patch literal 1714 zcmXqLVq3??snzDu_MMlJooPW6+kAs2w%JUKjE39>oNTPxe9TNztPBR+2t|wwnpoBt zG_kBOXkwnQfSHMriHVb8a^9MK?4KC#8}PyvGO_~oHBJGW!yL-OCd?EXY$$9X$Ohza z2y;0n=47Vj7v*Ip8j2Z+fCSlvd42Os^GXsk^Ay4|Q_Bqn4ER9eT*B;*c_~HtnJF+4 zZVVA-gou)X0^ALpjAFux5WNmiS}!?2*Fa93*TBNS$jH*b(Ae0-EJ~c$*wnz>&>YGg ztj=y?R6q`3Mpg#qCPrQcgC<4}rY1&4hHH~0S?(RE6!$LuE<-?wLIq;-){byrjh?|+Lf<#e*VJNJ7vd{e~T_Z3;XyeeTDS?O$J*l z4zW1z^C^7_>R}-043f44tApl z4b#QnWw9DZK3g{Bjn3vzEen>Uov4~}!`hJ3D&1U9KSk(3Uar%}2#Ndum>bXVTyeRT zbNBELl?X`>#?7iJ!v6d3%{Zx1?s5BTdR7Q;W5|i!r`UHsat}2YJd!=@d;YyQXZkXq zpICIEuR={>iv7%@S{s&sMKfh*-k-hBV! z9LEFliZBbS0W%}xf8^u=%zwb-!N^dxep=7#fFq8qff5&PtzOR<-BlK)zFc(Cp)LMO zBBK9qonz*V+P_5iJ3B{FjzZ?s!+Cetu`uk@bk*VTK2*1DVcnX!`y_M}{5A#)ehIyy zvMucPlRHWd6Lm}5{&h^1WnA%Z>$)hXgy7g8CWfpkN^U)7k94%+eonb2d)*-G$;oe1 zr57L6mz5N`drV#`>6Y#f^>57omL^#1gz)aIVVq;OYtt;J!h_=XgKTae{oGjP`QZIB zp1t)Y;&oO2lD5uYl-P^X@_c-oAMTB6E*&v=xBO6+ zjOXPtu87t3QcY(jcY7FGIIHYsVf-Z|W)%?5m*H#J#CQsrMUDXrHG{@QgEU5w%TT0p z7pXV}=604QMut!;b9FV#ZL6H3C(h;lcBR{3acdQy!g`s7f(J`(FXWu@+10V)&7#f^ z?2V@)!%eDKf6QC>w6yCWgJ9P2k4tD5_4NQ}j8y&r literal 0 HcmV?d00001 diff --git a/release/aroma/META-INF/CERT.SF b/release/aroma/META-INF/CERT.SF new file mode 100755 index 00000000000..7830ffd8ac5 --- /dev/null +++ b/release/aroma/META-INF/CERT.SF @@ -0,0 +1,6232 @@ +Signature-Version: 1.0 +Created-By: 1.0 (Android SignApk) +SHA1-Digest-Manifest: DKlveLyFsaaoOXUXJIUlwTU/kjA= + +Name: system/etc/security/cacerts/87d3cf09.0 +SHA1-Digest: 8ZCcYu2OkYcLpII3VSP6d36ZQno= + +Name: system/bin/udhcpd +SHA1-Digest: krEiLY/k9Jr/+9pqA28fvsw5sSg= + +Name: system/lib/libpowermanager.so +SHA1-Digest: cil4ma+WH5c6KM7V0tQrlio2VX0= + +Name: system/lib/libchromatix_vd6869_hfr.so +SHA1-Digest: 4ucunef7qQe9Cjk/ZcBMUFfBo/s= + +Name: system/lib/libstagefright_soft_aacdec.so +SHA1-Digest: RvBjqoJ/Z9sA8Y6piUXpFR006Vk= + +Name: system/etc/permissions/android.hardware.sensor.accelerometer.xml +SHA1-Digest: 2wEa/9FPcNbDmbsyKNJp5TwVgOE= + +Name: system/customize/resource/wallpapers_b_02.jpg +SHA1-Digest: N11M//8KXkFbKny21s2y+ODgaSs= + +Name: system/fonts/DFHEIA7A.ttf +SHA1-Digest: A2mXBjXzAO7W9WVPBY6zDoYwHD4= + +Name: system/etc/dhcpcd/dhcpcd-hooks/20-dns.conf +SHA1-Digest: VPIIUnYFs4j9yMZ+a+S12pnlS/0= + +Name: system/media/audio/ringtones/Crimson.mp3 +SHA1-Digest: qiDQ7fQfCnCZkjtvySj6TcWxu/w= + +Name: system/lib/libchromatix_vd6869_hfr_60fps.so +SHA1-Digest: GETh7rYzzYF92Mnr+m6jiYbugGA= + +Name: system/lib/libaudioeffect_jni.so +SHA1-Digest: fKY0xfiGQYmEQ+MlRzuFhVPmypw= + +Name: system/app/Browser.apk +SHA1-Digest: l1I690bEkOQdaa58lG9F7cOMhaY= + +Name: system/lib/libexiv2.so +SHA1-Digest: aYxWpbqCzuI0xnnIZVXcYoNurTM= + +Name: system/lib/libdrm1_jni.so +SHA1-Digest: cjZ+o8fwIIyy+Sgi9X7EDOto3xM= + +Name: system/vendor/pittpatt/models/detection/multi_pose_face_landmark + _detectors.7/nose_base-y0-yi45-p0-pi45-r0-ri20.lg_32/full_model.bin +SHA1-Digest: QWTMOw4GkuzG+r1zay8B6MxuB8M= + +Name: system/media/weather/weather_partly_sunny.mp4 +SHA1-Digest: c0RXFTbPdpGlQ+jNPrU7ft7V2SM= + +Name: additions/fonts/klavika/Roboto-Bold.ttf +SHA1-Digest: rxZ0Qf4S8Dabz/pZ3ofElciDAYs= + +Name: system/lib/libwfduibcinterface.so +SHA1-Digest: uXlwjZpXG9pP2moRMs+foxqJf/U= + +Name: system/etc/image_htc_earbud_2vol.bin +SHA1-Digest: H9PA04mtTHBqQmZJpDNrHC+Dl+s= + +Name: system/lib/libusbhost.so +SHA1-Digest: 6Kw1ZfWhfaW3IiZOMakfe/0TvHc= + +Name: system/fonts/AndroidClock_Solid.ttf +SHA1-Digest: PKbiQAyAy5xWcCKKDeM6mpdw3B8= + +Name: system/usr/srec/en-US/embed_phone_nn_model +SHA1-Digest: OvLDxuz3u6qqRppHXnxe+P+HgZw= + +Name: system/etc/security/cacerts/81b9768f.0 +SHA1-Digest: Abtfwk1XW6grFct1OuViAxz88dE= + +Name: system/lib/libDxDtcpClient.so +SHA1-Digest: 8I0pZM0gpJbXLMQpCuXqzWj3IeU= + +Name: system/framework/com.htc.weather.res.apk +SHA1-Digest: rk8l04TKto0PORWzPVAgFXGAyuE= + +Name: system/fonts/gcsh00d-hkscs.ttf +SHA1-Digest: 8xR0dAeqgHxrdUOV7+cDT4aW9bI= + +Name: system/lib/libyuvimage.so +SHA1-Digest: 1UKviuNJ8bBtKj/r2KisBFuinTk= + +Name: system/app/HtcScreenTimeoutWidget.apk +SHA1-Digest: KTjTiEKrFKIGo6XCliMfw9dbrZk= + +Name: system/lib/libAnalyst.so +SHA1-Digest: 4CYkNEZlL0vYcilzNAQ/DIselL8= + +Name: system/bin/sdcard +SHA1-Digest: MfwQRXNtr5/dj8X8a+ruSMG+UEI= + +Name: system/framework/ext.jar +SHA1-Digest: 9N0eqDvbEz60S83dFhgLQS01X9M= + +Name: system/media/audio/ringtones/Lavender.mp3 +SHA1-Digest: nnCdW1npkBGp80bKQTUuPUEqgcc= + +Name: system/app/MySketcher.apk +SHA1-Digest: aAu62FxQOJIdjNRE2OlCsKMMTz8= + +Name: system/etc/image_ibeats_solo.bin +SHA1-Digest: 9ZRrh74237S4JzQ0CAcwA0QNSr8= + +Name: system/media/weather/weather_l_partly_cloud_day.mp4 +SHA1-Digest: hRUsy8QabfX+kwP1ycP0D2aUEl4= + +Name: system/bin/smd +SHA1-Digest: oIwazVmMpddeThsXDlD2ZYeR6k8= + +Name: system/etc/security/cacerts/ed049835.0 +SHA1-Digest: DvbVqcuD1h/TVMgfyfSYy3n1G0Y= + +Name: data/app/com.facebook.katana-1.apk +SHA1-Digest: e2HpWUog/7ZbJvtE7L5ERy1Ut6U= + +Name: system/lib/libgnmc_id3tag.2.5.9.4.so +SHA1-Digest: XwkOVmhb07RK6Cngr7J5Qzr/7fo= + +Name: system/app/Phonesky.apk +SHA1-Digest: naHy576C4/EeBx95LOjmng71rvc= + +Name: system/media/audio/ui/Volume-6.flac +SHA1-Digest: xP8/3OLNtl9qfrTH0Cd/imGsSU8= + +Name: system/etc/security/cacerts/a3896b44.0 +SHA1-Digest: Lt7IRY6srSXDk8xe/2MpiiNof+U= + +Name: system/etc/security/cacerts/9f533518.0 +SHA1-Digest: 2P7X1cWxI3NzjMsygIUOy6dxMCw= + +Name: system/customize/CID/default.xml +SHA1-Digest: 4j+3ZIDvTmXtxbn8MI2ypW++k1Q= + +Name: META-INF/com/google/android/aroma/icons/alert.png +SHA1-Digest: vg/4Y3GcDsD3gIqqDjClKzufnak= + +Name: system/framework/com.broadcom.bt.le.jar +SHA1-Digest: QepLQ46oru48FZf7jbWyp2gKk6k= + +Name: system/lib/libstagefright_soft_mpeg4enc.so +SHA1-Digest: zzp04at2GnecxAgGdWAw1fqKN08= + +Name: system/media/audio/notifications/Claret.mp3 +SHA1-Digest: +WCc2yiPvSfrLhcnM25f6/vCkxo= + +Name: system/lib/libwpa_client.so +SHA1-Digest: U8wj3Rv6w+YiEuXztwbfEruQ1eo= + +Name: system/media/audio/ui/LowBattery.ogg +SHA1-Digest: 1UaA9zNnhg53IXetB/ze0AVzvFw= + +Name: system/bin/linker +SHA1-Digest: HGmDRNqa4RbY+7jVoBGlhRX9GgE= + +Name: system/lib/libhtcsunny2engine.so +SHA1-Digest: cTLGOMGPLC8xBWCz2Q2pLVjm1eQ= + +Name: system/lib/libmllite.so +SHA1-Digest: IwFTWaFpZvdJn/Y68y2gL1fU7ag= + +Name: system/media/weather/weather_partly_cloud_day.mp4 +SHA1-Digest: sfBGdPbvyL2kPgB7HwHo+bqz/ws= + +Name: additions/fonts/veggieburger/Roboto-Bold.ttf +SHA1-Digest: mr6dx7dKeVVF5Fjsak84Q8KbjmQ= + +Name: META-INF/com/google/android/aroma/trickdroid.png +SHA1-Digest: gwxCzpCfLKXkQ2t0oiM6wpCFn8I= + +Name: system/media/audio/ui/media_volume.ogg +SHA1-Digest: dZq6eHLUwc3Gx5LytSNtNG9f7uM= + +Name: system/app/IMEXT9Bulgaria.apk +SHA1-Digest: DcZPVHv7of2GPcVKTK+IYq09ACc= + +Name: system/media/GPU/dot_mask_3.bmp +SHA1-Digest: OCtDmOfCOhrRsMF0/Gx0FNRa6cs= + +Name: system/etc/secureproperty.xml +SHA1-Digest: rDlp8Jj01UJHiC1X2WaHTxo+AaQ= + +Name: additions/fonts/asap/Roboto-BoldItalic.ttf +SHA1-Digest: xYOqmv3m9vD4lUMuZW1neFHmvxg= + +Name: system/app/IMEXT9Russian.apk +SHA1-Digest: z6l3FVALvvya6JvpahA3UBo670s= + +Name: system/etc/permissions/android.hardware.usb.accessory.xml +SHA1-Digest: lKVhbliD+5NmYq61xsHEVEZTfsE= + +Name: system/media/zchgd/batt_40.rle +SHA1-Digest: hwcERp4tgnvb54nlWGld9plxM3c= + +Name: system/media/audio/ringtones/Persimmon.mp3 +SHA1-Digest: q4b/q7+GEUrh3UrYCtOAqZgOZKw= + +Name: system/fonts/Roboto-Regular.ttf +SHA1-Digest: jlT03ygs6K+WSYdmRK9fhzTkT+Y= + +Name: system/lib/libDivxDrm.so +SHA1-Digest: BlkVOddGp2vjZfQ8CvuZ9YI6B0o= + +Name: system/bin/mtpd +SHA1-Digest: dAQpfdMibqIXMW16f1A+uoDZfPk= + +Name: system/customize/resource/quicklaunch_21408.xml +SHA1-Digest: X+BqKjv78FVdAIZE9qezJz0k4I4= + +Name: system/customize/resource/allapplication_22288.xml +SHA1-Digest: 1+tqbej0Al5pUF3GpojUI0LjjtQ= + +Name: system/app/Nfc.apk +SHA1-Digest: R8ooyfgKex3fubW8hZCONqFuW9I= + +Name: system/usr/share/bmd/RFFspeed_501.bmd +SHA1-Digest: O4W+YPqIxPg5c57Ny/tsqS1RV8M= + +Name: system/etc/security/cacerts/635ccfd5.0 +SHA1-Digest: iOfrRlIkQ9CJR88NZ3FS2RQ+icw= + +Name: system/etc/security/cacerts/2e8714cb.0 +SHA1-Digest: pN27bgE5+KCmhIkYxNaJ83eT1rI= + +Name: system/media/GPU/CurveWarm.bmp +SHA1-Digest: bVHEn9I0GYNPacm8/kFUrIRudkA= + +Name: system/app/JETCET_PRINT_Resources.apk +SHA1-Digest: NkNfBLPE2u5RLifmCdvpbi5q8sw= + +Name: system/app/VoiceDictation.apk +SHA1-Digest: vO5zkTWMClF1/mD5UYuUR9sflNs= + +Name: META-INF/com/google/android/aroma/icons/gps.png +SHA1-Digest: IAf4Aztre45kqdZmske0USwCyzo= + +Name: system/xbin/nc +SHA1-Digest: TXl3E00ZXXlmbHJ4vcK9fNTZLgc= + +Name: data/app/com.google.android.marvin.talkback-1.apk +SHA1-Digest: KMuwXLtXQAft8LEh0rkdTzKaeR0= + +Name: system/etc/permissions/android.hardware.location.gps.xml +SHA1-Digest: 5BoPvzraABvx8iNcW0s9BCY42l4= + +Name: system/fonts/Roboto-Bold.ttf +SHA1-Digest: tohglY0iiJgDoncAZyqqWqBz6XM= + +Name: system/lib/libGLES_direct.so +SHA1-Digest: TFIx6Eoa4l9TcjXz93nyYDTqsAE= + +Name: system/app/CustomizationSetup.apk +SHA1-Digest: PWCVLOOx/9F3852eIltrcT0WhzY= + +Name: system/app/MusicChannel.apk +SHA1-Digest: wABMNHTB4Jty1b1tt+cSgrk5rxo= + +Name: system/etc/image_ibeats.bin +SHA1-Digest: 6FYxVxkES3iWcUdzMFp49xutx7k= + +Name: system/etc/image_gec_bt.bin +SHA1-Digest: IM5sFxGB3+amjCXJzJfifoE0fws= + +Name: system/lib/libcsd-client.so +SHA1-Digest: 88MoVy4odlMowHp1ESD8avNVtnk= + +Name: system/bin/RescueServer +SHA1-Digest: ze8q9UF5ZyYTjgEL9al67joHC3M= + +Name: additions/fonts/comicsans/Roboto-Italic.ttf +SHA1-Digest: xn52EsNMWUZnhTwV4ECKNWe6F/M= + +Name: system/etc/security/cacerts/5f16ce45.0 +SHA1-Digest: nRjUndhZNOejX3w/Yr7ol30Xc/I= + +Name: system/etc/security/otacerts.zip +SHA1-Digest: fWXPx5r3NdvulGzMrMs0mh9OeR8= + +Name: system/bin/stop +SHA1-Digest: Fv6hdRIUitCwfI8lPijekF1nLxA= + +Name: system/bin/htc_ebdlogd +SHA1-Digest: oqJWtA5oyYRNyEIBMQ3SN6kzwac= + +Name: system/lib/libpatts_engine_jni_api.so +SHA1-Digest: +rzAJro6Sh+VO647jFXieIgGJps= + +Name: system/lib/libglcv.so +SHA1-Digest: 5Jmozenu7ZOBTgpl9Hb7mO19xUA= + +Name: system/etc/security/cacerts/0c364b2d.0 +SHA1-Digest: m6475NwJ+vZiyjNpJVOX38j1uy4= + +Name: system/etc/firmware/fw_bcm4335_apsta_b0.bin +SHA1-Digest: y6rnSBDUHKtovU48tCk/B9Qp5C4= + +Name: system/lib/bluez-plugin/audio.so +SHA1-Digest: 6/3ijWBPxDrYLDK1CredLld6kM4= + +Name: system/lib/libsrsprocessing.so +SHA1-Digest: 4m6CftbwvbCUshSpd6BVbt7d+Ok= + +Name: system/lib/hw/audio_policy.default.so +SHA1-Digest: IDQfcMpsJa93jE8tiUfRexxvy30= + +Name: system/lib/libchromatix_ov8838_hfr.so +SHA1-Digest: CjtF8Iu6m9GetsLBU4vQRoGi9q0= + +Name: system/etc/soundimage/srs_global.cfg +SHA1-Digest: IOJLmVKbRbNn97QDBgVjMco4c1A= + +Name: system/lib/libicuuc.so +SHA1-Digest: UZlm4RhT981gfhxnzwP1fMSd3K4= + +Name: system/app/HtcMusicWidget.apk +SHA1-Digest: UY3XwZ6O3XGuCIZOzQA5inNWKvs= + +Name: system/lib/libnetsharing.so +SHA1-Digest: 4mAlZR6YGFikmR8sjGp55DFAPCc= + +Name: system/usr/keylayout/qwerty.kl +SHA1-Digest: AvLds66wuKFqzBu7lpUMr/ZIL+I= + +Name: system/etc/soundimage/srs_geq10.cfg +SHA1-Digest: WGRKxJYg1j5adpGI86zvLx3fwyY= + +Name: system/etc/security/cacerts/b5f329fa.0 +SHA1-Digest: EtCEMsveXUzOZEYvLIqXHFA+jXU= + +Name: system/bin/schedtop +SHA1-Digest: jyhC2bIsGjWN6DlyJDpiYWyoNc4= + +Name: system/lib/libstagefrighthw.so +SHA1-Digest: FLaB5R1NpT1McXHGJ8c4ssQthzc= + +Name: system/bin/chmod +SHA1-Digest: 0MqurJjzSmSy8JAeep8n0n4zrUs= + +Name: system/app/HtcMessageProvider.apk +SHA1-Digest: hF4IwimpGZWW4Nx6lXMWVwc1DZc= + +Name: additions/wipe/wipe.sh +SHA1-Digest: v6LEQ41l2RyqkxDcumy+g5gzsFc= + +Name: system/lib/libmtp.so +SHA1-Digest: k0A8S8DG+RZt6eeXydihBL7k8KQ= + +Name: system/etc/tfa/deftcoefA.speaker +SHA1-Digest: wtjbWpsy42NLfyzW3OlAUt67zh4= + +Name: system/customize/resource/wallpapers_b_05.jpg +SHA1-Digest: 4Lf7CA6uE0FVw7lDp43CH0WKJH0= + +Name: system/app/HtcDropboxGLRPlugin.apk +SHA1-Digest: cRYTEgRdLfXDENP98xBqP1aZ4iU= + +Name: system/app/IMEXT9Portuguese.apk +SHA1-Digest: 3icxnWX7MMSCgyDdTSTJORtDVi4= + +Name: system/app/HtcRingtoneWidget.apk +SHA1-Digest: 7fXTNiEIR9WbEaEtDqabCFFycMs= + +Name: system/etc/security/cacerts/e268a4c5.0 +SHA1-Digest: aUfrGa2UxFs8hGDtl0m8Koqa9GY= + +Name: system/app/HtcContactWidgets.apk +SHA1-Digest: eBf6ZjsHMCqG6KqaNomA4xN4/ow= + +Name: system/lib/libchromatix_ar0260_hdr.so +SHA1-Digest: /ySTdlA6/+XAReWKyz5lvi69Ng4= + +Name: system/lib/libmmcamera_rawchipproc.so +SHA1-Digest: +f0dSPuvtb6aCvP96j/mvDy++gg= + +Name: system/fonts/HelveticaNeueLTPro35Th.ttf +SHA1-Digest: dqm2oNB0jyOwy3o4CGg+z9VXTcg= + +Name: system/lib/libstagefright_soft_vpxdec.so +SHA1-Digest: WJTQtw0nI98y3kcYp20IN11ro8c= + +Name: system/lib/liboemcamera.so +SHA1-Digest: jr6+jSHe2BceZdCbGmd0NtJULyg= + +Name: additions/gps/europe/etc/gps.conf +SHA1-Digest: AaQog3UpIe9UXkxDD42AnjkvKcc= + +Name: system/bin/usbhub_init +SHA1-Digest: 0pFDKZvi6r8Vqhs1pHgLWQFg/Bw= + +Name: system/usr/srec/config/en.us/dictionary/enroll.ok +SHA1-Digest: RuJqPgJuq9pkqvVscU5w1p03aas= + +Name: system/media/audio/ringtones/Red.mp3 +SHA1-Digest: IQ6trD1wah1m7YEnwHCEXrzBjiQ= + +Name: system/bin/ATFWD-daemon +SHA1-Digest: DHHe9ifS9D3qz5y0sw3yIdpJb0c= + +Name: system/bin/mm-jpeg-dec-test-client +SHA1-Digest: Hq2CpSQ5709ZI8O9tLDKlnc0ghA= + +Name: system/etc/security/cacerts/56657bde.0 +SHA1-Digest: OeQPYfZ4mWVdC4vcxJy56002ySk= + +Name: system/lib/libCommandSvc.so +SHA1-Digest: 5mefyxKlpmRk9ZhNhr53Wi8Rths= + +Name: system/lib/libwt6xlsrdr.so +SHA1-Digest: plBBT6MvMz4I0oqFXiV+TE2MtGk= + +Name: system/lib/libOmxCore.so +SHA1-Digest: 5LD0wUtT8vopu1K9LGfR8PpP1lQ= + +Name: system/lib/libpixelflinger.so +SHA1-Digest: ZurFBaCQeOgajaVxpGgh5xURy+I= + +Name: system/lib/libmm-omxcore.so +SHA1-Digest: hKBNIj33yRHPXBLYCBcHEOGeYyk= + +Name: system/bin/RescueStarter +SHA1-Digest: +6gxA6+F7EaL/ohhWGv5YRkzFlI= + +Name: system/etc/ppp/ip-up-vpn +SHA1-Digest: uMw/gE4SJkSr5seC7eFIkF3hGTg= + +Name: system/lib/libandroid.so +SHA1-Digest: y4nN2TBf0XdYysnfRUK6unl+UOU= + +Name: system/lib/libcrypto.so +SHA1-Digest: AKxPsRlC+nv7lhNHk+H8J7NvXyE= + +Name: system/lib/hw/audio.primary.msm8960.so +SHA1-Digest: 6XbfYDVR0uW+PoVl/nByLlmdV9A= + +Name: system/app/Updater.apk +SHA1-Digest: VAPDuYHAitCKaw4cyk8KlQUYVAo= + +Name: system/customize/resource/allapplication_23210.xml +SHA1-Digest: G8ZkBUBPFQ8OHbNUThnSkYE9OG4= + +Name: system/lib/libext4_utils.so +SHA1-Digest: B+7RbjOZ7x2KB5X/TYxMUb7MjBA= + +Name: system/customize/resource/ConfigH.bin +SHA1-Digest: Gzg+wmcxhGxSPcTj3WytTKk7BVI= + +Name: system/lib/egl/libq3dtools_adreno200.so +SHA1-Digest: Y5ypo8dbLtaLa6v6484I20gUMt8= + +Name: system/lib/libOpenMAXAL.so +SHA1-Digest: 1Z3ZGeGdm/0QV72RYtkab88oafw= + +Name: system/etc/security/cacerts/1df5ec47.0 +SHA1-Digest: Qxp979sc7+YKhsMsGesH1DjUOJI= + +Name: system/customize/resource/wallpapers_c_04.jpg +SHA1-Digest: 3DYZGHdhyCZSwnrY0WXQvFvLSu4= + +Name: system/lib/plugins/com.adobe.flashplayer/libflashplayer.so +SHA1-Digest: zdiYvO8Y3OvJfIGTYPmrZg9sjPg= + +Name: system/framework/com.htc.resources.apk +SHA1-Digest: TsyDXA9Meyxtf42hEcDCJKx5w10= + +Name: system/etc/dhcpcd/dhcpcd-hooks/95-configured +SHA1-Digest: KWDLg1JU1szJDOSPDL6OvD3iOk4= + +Name: system/framework/input.jar +SHA1-Digest: LwNYSj4w6CpQSRq9xUQJPZib/5g= + +Name: system/etc/tfa/playbackbeats_l.config +SHA1-Digest: VQZt2bIP+QgdGt+Z7I/sBiivjqQ= + +Name: system/etc/security/cacerts/85cde254.0 +SHA1-Digest: vcr8bqyL/bCXu4bxqRiOyJ8rkls= + +Name: system/lib/libchromatix_s5k6a2ya_default_video.so +SHA1-Digest: dlYZ9gBjjy5wLmKmITRL+n5e5rY= + +Name: system/etc/tfa/recorder.preset +SHA1-Digest: tNWWfwOrlxvpWmpUZwllEnmbRFY= + +Name: system/etc/security/cacerts/0481cb65.0 +SHA1-Digest: /kQ1voFMErA39wsigwqxUluo9sg= + +Name: system/bin/printenv +SHA1-Digest: WJXRgyY6v3bypciRMFwiKCsQqbk= + +Name: system/media/audio/notifications/Viridian.mp3 +SHA1-Digest: apsyWWfgVbC5JJR4x0q/9YSUtzI= + +Name: system/bin/svc +SHA1-Digest: /1od6413nm4+hNXDHR4zepttND8= + +Name: system/framework/usbnet.jar +SHA1-Digest: LCnfPinR9anJWjStDOIqEpCbYHo= + +Name: system/framework/android.test.runner.jar +SHA1-Digest: FLAP1uf4P6zYSySOLSKapmXg/W4= + +Name: system/customize/resource/quicklaunch_23410.xml +SHA1-Digest: kgO2FR/dHmT33zD+YGRoqeSg/g8= + +Name: system/customize/resource/allapplication_65502.xml +SHA1-Digest: /PHrR7QqB2uw2LSoI2hFWuy1y/0= + +Name: system/etc/security/cacerts/2fb1850a.0 +SHA1-Digest: tpQ/ebm+s27cmkePsnMxlzdMwcc= + +Name: system/lib/libstagefright_soft_amrnbenc.so +SHA1-Digest: U/+wlZ+POoPFwe+B+zSq8iHzpG8= + +Name: system/lib/libQSEEComAPI.so +SHA1-Digest: 2CZQM6FHd/5MdKdarXqO87mye6o= + +Name: additions/fonts/roboto/Roboto-Regular.ttf +SHA1-Digest: UeXcQyRH9Fec2LT/BsgBv9kIcMw= + +Name: system/etc/tfa/fm.config +SHA1-Digest: FfNCE6iEk/5sNEdNf3VxamXpF/M= + +Name: system/etc/firmware/leia_pfp_470.fw +SHA1-Digest: MmyTkoBM53apTZk+VQC1uDHQdcE= + +Name: system/media/zchgd/batt_5.rle +SHA1-Digest: nanA9ExRNqw2oicC78rIf1LGd4k= + +Name: system/vendor/lib/libwvdrm_L1.so +SHA1-Digest: 9yEk46zaGm0YpdeuTdeUkpViS2c= + +Name: system/tts/lang_pico/es-ES_zl0_sg.bin +SHA1-Digest: dX1TIDkkkvgY3gnXGkcrIO1D/Fs= + +Name: system/app/PureC_UserDictionaryProvider.apk +SHA1-Digest: I/4ZFC4YUANxnyc1z4/c5VMEnlY= + +Name: system/lib/libqdp.so +SHA1-Digest: RalffA7l1ss5G1lAbEh9cwtxRoI= + +Name: system/lib/libcam_oem_plugin.so +SHA1-Digest: xrSqKRRZHMRyDmh9OJQ1FuJce+A= + +Name: system/etc/firmware/a225p5_pm4.fw +SHA1-Digest: K++5fIxr0AJPB7tCep7AfwsmzPs= + +Name: system/lib/libchromatix_vd6869_default_video.so +SHA1-Digest: c8XAaI/S5/DqcM78C5WSgxXgBXI= + +Name: system/etc/security/cacerts/709afd2b.0 +SHA1-Digest: 5OSTAsmLWAhmGMiYIVKh1IyxqL8= + +Name: system/bin/pnpmgr +SHA1-Digest: FGZbG/Z2f/gEaqkmUiZMAXqvAFA= + +Name: system/lib/libnmsp_speex.so +SHA1-Digest: juq0NaaYSZNmqtJNIRarusfP2QU= + +Name: system/xbin/sysrw +SHA1-Digest: 4ZhXNrRvG7piGpyJaCWV7UrRt38= + +Name: system/lib/libvideoeditorplayer.so +SHA1-Digest: aBwdJ1VA2OaHUiX3750JePoy9mo= + +Name: system/lib/libdrm1.so +SHA1-Digest: pOJ3yW9V+JZ/IYzV9D9p9B+yWK0= + +Name: system/customize/clientid/default.prop +SHA1-Digest: n2sIyqHOAstZHdIrOyYpHz3bQYM= + +Name: system/etc/permissions/com.htc.android.bluetooth.le.xml +SHA1-Digest: EfSDNpuiqM1BMYG2kxz9OBbgv1g= + +Name: system/etc/security/cacerts/1e8e7201.0 +SHA1-Digest: KqgVoWSCtWsuVVi9KeH1TTJ4rlU= + +Name: META-INF/com/google/android/aroma/icons/confirm.png +SHA1-Digest: tRQmwyaUo60uMn6QRe2DOPkRefU= + +Name: system/etc/security/cacerts/46b2fd3b.0 +SHA1-Digest: ncfFJuS33zLgLepbQtRcOp1nNTU= + +Name: system/lib/libwfduibcsrc.so +SHA1-Digest: knfV4e0LIwEyhHI12m8lVUMuCKg= + +Name: system/xbin/sysro +SHA1-Digest: mYu/dAcGZN8+y6oAWTUwxrNbuFo= + +Name: system/media/zchgd/batt_70.rle +SHA1-Digest: 7MMKIPzaeTlsIMD1ActDqLG67r4= + +Name: system/customize/resource/rp_ce_0700_i.png +SHA1-Digest: YQnLG7Ql3VXyJP2nb5fqsbgucQA= + +Name: system/lib/libstlport.so +SHA1-Digest: oWTzsPHEI7U4QfqNFa1VDwBFqSk= + +Name: system/media/weather/weather_thunderstorm_night.mp4 +SHA1-Digest: lXzummcIKe8shs3m9rU6SOfb7vw= + +Name: additions/fonts/roboto/Roboto-Bold.ttf +SHA1-Digest: 03Clm0bwbIuvbFncdpQsexZcu6Q= + +Name: system/etc/permissions/android.software.sip.voip.xml +SHA1-Digest: qPho8aR6qQ+pK8ybcLgZiHGkyEo= + +Name: system/bin/mdnsd +SHA1-Digest: Zb/sgtFDsXx5Asa6rr+yWWY0Uxc= + +Name: system/lib/libjnigraphics.so +SHA1-Digest: CsEDetPouqquavvcMs5hqGMABL4= + +Name: system/bin/ping +SHA1-Digest: 3ZuWEFmdAHWk5qoJniJ9/TTE+i0= + +Name: system/lib/libsysutils.so +SHA1-Digest: e5TgYNveAlnZ0eC1S0MLI7ofAK0= + +Name: system/lib/ssl/engines/libkeystore.so +SHA1-Digest: qjsva2pcYMqc8R2DhjG1M3gC8ZM= + +Name: system/app/GoogleBackupTransport.apk +SHA1-Digest: 0YvyntynzGSIpwVW/9I9e4U6Cwo= + +Name: META-INF/com/google/android/aroma/themes/sense/dialog_titlebar.9 + .png +SHA1-Digest: 6cZtD07kpdT+LpgfIrmN5skm7ho= + +Name: system/lib/libdmt_speex.so +SHA1-Digest: Vrq3yfNY9Yn02A+CdeeufyGcBkM= + +Name: additions/fonts/helveticaneue/Roboto-Regular.ttf +SHA1-Digest: 7f/b8q3TAEG5iZCZl4AHxmb2r4I= + +Name: system/lib/libgps.utils.so +SHA1-Digest: cq2GbReaUMClQLJ7cWRsEw65C+M= + +Name: system/customize/resource/quicklaunch_24007.xml +SHA1-Digest: dlQAOpoWZnybV/udOF2n7Jm5zuU= + +Name: system/app/RebootWarningWin.apk +SHA1-Digest: Mue9PcDdhlx2N/k16B6oV85KUsk= + +Name: system/etc/security/cacerts/a0bc6fbb.0 +SHA1-Digest: V0mHojd9hDTNmkRMn2gBBUc//E4= + +Name: system/bin/hciattach +SHA1-Digest: 9qqCR5FRNpmebVnUkvtuOft8j6o= + +Name: system/media/audio/notifications/Mantis.mp3 +SHA1-Digest: sfGTikezDwxDuQtacFdz1gLWd14= + +Name: system/etc/soundimage/srsfx_trumedia_51.cfg +SHA1-Digest: sFewTyxjx4MtCEI7WPaB3UPG3i0= + +Name: system/bin/iftop +SHA1-Digest: h4CYGQaCzALKqCTJyvRR7AGlhzM= + +Name: system/etc/security/cacerts/cf701eeb.0 +SHA1-Digest: YIKVSOwnG2XtUxSGW9n6w3exUq4= + +Name: system/etc/wifioffloadpkg.xml +SHA1-Digest: 15BrVJxxSn4gzb7IEwWUU1qXK9w= + +Name: system/framework/com.htc.browsermodule.res.apk +SHA1-Digest: 22TLk+PQyPlFkKDGcSO4n0H43yk= + +Name: system/etc/security/cacerts/67495436.0 +SHA1-Digest: ZVlG1by+ahNsQ6Uv4zmahjj+oCw= + +Name: system/lib/libaudcal.so +SHA1-Digest: 0IpgJXECWTucXaEwlDSGB4drKfw= + +Name: system/lib/libFileMux.so +SHA1-Digest: CcZsne0ww0ZuwNTJ9Cl6SVaHcLc= + +Name: system/etc/audio_policy.conf +SHA1-Digest: zj2LuVIigncZRJoBtnnxHKBAp18= + +Name: system/customize/resource/quicklaunch_228.xml +SHA1-Digest: Y8TSc9//Lny0TZHhlPHMaqJZJfo= + +Name: system/customize/resource/allapplication_65510.xml +SHA1-Digest: IdOvWMfv94KZ/II48iavCP6fOII= + +Name: system/usr/srec/config/en.us/baseline11k.par +SHA1-Digest: LAxT4ug59UO7cj2ezMGlctM/8iM= + +Name: system/lib/libext2_e2p.so +SHA1-Digest: fzrQMMsebb2x/chFgSNPP9GC8LQ= + +Name: system/app/Frisbee.apk +SHA1-Digest: rfnFt/WIv9yBYBtL5mdmVI2Q/TM= + +Name: system/lib/libchromatix_s5k3h2yx_preview.so +SHA1-Digest: EUkC+AyE8GNuZ2arl1VfLF+Xuh4= + +Name: system/lib/libqdMetaData.so +SHA1-Digest: tkm+tMrLd/LMbHqlsXo34b6pTRM= + +Name: system/etc/tfa/tfa9887.config +SHA1-Digest: UiD+6Xb8wXYeVGNh4sJe7EFZtzI= + +Name: META-INF/com/google/android/aroma/fonts/small.png +SHA1-Digest: J8lq7Wi2r7b9rEVUmrcwpBBnhZQ= + +Name: system/lib/libv8.so +SHA1-Digest: dchlIchWazth+Eda7/rNPItcZKE= + +Name: system/app/DownloadProvider.apk +SHA1-Digest: CoPnAguf2UBbo+bN27VCUJW5yYY= + +Name: system/lib/libril-qc-qmi-1.so +SHA1-Digest: r1y5lOu4gxkpR9u4e84IbX1l+cY= + +Name: system/bin/touch +SHA1-Digest: TkTufs2gEKsSWdL+eVfy1lYdCLI= + +Name: system/fonts/HelveticaNeueOTS.ttf +SHA1-Digest: x+vbU1ICaoCS6HAqlz1nlcGHUm4= + +Name: system/media/weather/weather_windy_night.mp4 +SHA1-Digest: 610NoN1UpfNlJVXT0CvFIA0Rmx8= + +Name: system/bin/mm-jpeg-enc-test-client +SHA1-Digest: ROYFElMidSYQI06AMR1tygklQrI= + +Name: system/lib/libqcci_legacy.so +SHA1-Digest: VtsemgSxQzQN4luNmp4YtNvVxvE= + +Name: system/etc/security/cacerts/bcdd5959.0 +SHA1-Digest: wUXicMukZB4UlU9/xSoCKEwh6jo= + +Name: additions/fonts/segoewp/Roboto-Regular.ttf +SHA1-Digest: A7sBtaR2beR/cqxLXAdsQyGe7is= + +Name: system/etc/security/cacerts/97fecd7d.0 +SHA1-Digest: eGd39Hr29uPL1cFzSy0LxGWJiC0= + +Name: system/bin/keystore +SHA1-Digest: w4UBTX7ePRXPlKszmAxVbVaLuiA= + +Name: system/bin/awb_camera +SHA1-Digest: Uud1Z7mzZ6ndrCS3pqWt1zEQj0A= + +Name: system/lib/modules/moc_platform_mod.ko.3.4.10 +SHA1-Digest: RkAKNk7k5eBEXDQuJ+6h56uRdic= + +Name: system/app/IMEXT9Czech.apk +SHA1-Digest: Az/c0ubMVQ4trLp+s+IH54dxBGg= + +Name: system/bin/nandread +SHA1-Digest: Ad76Zci/anGSAE0VgDCtlGZEfAc= + +Name: system/bin/bma150_usr +SHA1-Digest: 3m+lg2zZkFLDxwjM0djQwuWX4Fw= + +Name: system/media/audio/ui/Unlock.ogg +SHA1-Digest: myFHw2IIAJpwfZNEKNS0sdsTqtw= + +Name: system/etc/tfa/fm_l.preset +SHA1-Digest: HFL+I9FZAQhEl3cv2cNYEeP2OQw= + +Name: system/lib/modules/moc_crypto.ko +SHA1-Digest: Vx+NTDZ9TV5Q9CcVLn/EmeoyrPk= + +Name: system/fonts/Clockopia.ttf +SHA1-Digest: +vgYgkUemnpjfwZ99j4TWmseawE= + +Name: system/xbin/su +SHA1-Digest: ivfCc8pZ8mQCFXnQ+obbbwzbphg= + +Name: system/lib/libdmt_elvis.so +SHA1-Digest: wly8LAxia07HKq9boQVYnfZB3w8= + +Name: system/lib/libfilterfw.so +SHA1-Digest: luS6LcfcPGtil2hewuqA3MohJko= + +Name: system/media/weather/weather_cloudy_night.mp4 +SHA1-Digest: hsLw9cFbPcYdRraMQymr9AjVyro= + +Name: system/etc/image_htc_midtier_2vol.bin +SHA1-Digest: z0hxADw/FKSp8QqM8/jKcztNv0k= + +Name: system/fonts/DroidNaskh-Bold.ttf +SHA1-Digest: fwLjvQI4iM0Nvsq0mX5whsEIzhs= + +Name: system/etc/tfa/video.config +SHA1-Digest: Ew36B63+fuqSZxRunA6e9JkTywY= + +Name: system/lib/libcutils.so +SHA1-Digest: +qH7/sZKd1lRteq1SQ2kGASwAhA= + +Name: system/lib/libmmparser.so +SHA1-Digest: dVRwYS20qhyCjbTuldhBmO3+bJo= + +Name: system/media/zchgd/batt_30.rle +SHA1-Digest: FIPyXjYGxlhwxzkG2gwlnIS30Bw= + +Name: system/fonts/RobotoCondensed-Bold.ttf +SHA1-Digest: ZCg1lMs131P06MLQgm2d/Hailvs= + +Name: system/app/HtcInternalSettingsProvider.apk +SHA1-Digest: AP1l5/yjABxe6qRGvayGjTFeVsA= + +Name: META-INF/com/google/android/aroma/themes/sense/bg.9.png +SHA1-Digest: 9GI9XxGdHNyODUJIRFZEQeJihvQ= + +Name: system/lib/libchromatix_vd6869_preview.so +SHA1-Digest: 2uRV1mFZ8eKvjJVW3DzTi326Slc= + +Name: system/lib/libcameraface.so +SHA1-Digest: gm+x8fV8/AbxhSbZqdqB8BPCcYc= + +Name: system/customize/resource/allapplication_21404.xml +SHA1-Digest: huaA0lU7IEG9/WGMK9aaoiGYpzo= + +Name: system/framework/com.android.nfc_extras.jar +SHA1-Digest: qsPDx6QpUuAgaCIB3JnEcNsdMWc= + +Name: system/bin/bu +SHA1-Digest: ssJV8rKixa6InHKnBAhyFrsGwa8= + +Name: system/etc/soundimage/srs_bypass.cfg +SHA1-Digest: UwWHCemaEAeChf/A79z3iwbSfqs= + +Name: system/etc/sound_mfg_DMIC.txt +SHA1-Digest: rpTr47oShzL3OgGm4nfb5Fjjmwg= + +Name: system/lib/hw/audio.primary.default.so +SHA1-Digest: FFRQ47LpjBjRHQH2pjwRi8fe89w= + +Name: system/usr/share/partials/partials_A_gb.csv +SHA1-Digest: dSmTCHUgTwDPIQlTMjDjSfivVfk= + +Name: system/lib/libchromatix_imx175_preview.so +SHA1-Digest: P8XTc5VWSoV0EfmNuwZyJHTYlj0= + +Name: system/lib/libnetutils.so +SHA1-Digest: 3Phe9Q1FJREq0DO3gsX+vpMB8lM= + +Name: system/media/audio/ui/Volume-1.flac +SHA1-Digest: G60DY/kdy4VD5Nif9XNM550IPvE= + +Name: system/customize/resource/quicklaunch_28001.xml +SHA1-Digest: eU5HQZAVFSFyrKi/Ep7uXtvPjwE= + +Name: system/customize/resource/rp_ce_0678.png +SHA1-Digest: 7twk6OXGmp7qOa2Wgavkuawbqqg= + +Name: system/lib/libimage-omx-common.so +SHA1-Digest: Gcl42ovD3k9QzUCngA05PvQOXFg= + +Name: system/etc/firmware/fw_bcm4335_p2p.bin +SHA1-Digest: jsXbGFnpVaIkIlcopDb62XndEYU= + +Name: system/etc/security/cacerts/23f4c490.0 +SHA1-Digest: swYiy1QiVyTMlhy6V0v0qzD1Ty0= + +Name: system/lib/modules/gspca_main.ko +SHA1-Digest: VXP6dwMOnxqDQm0McXFzt0FPLP4= + +Name: system/app/HTCShoeboxShare.apk +SHA1-Digest: 45+v6rtjdlEduhOUiWQ/I69kPbs= + +Name: system/customize/MNS/default.xml +SHA1-Digest: Q8pV6m8yiw1kG5xvVbFfwfxHom0= + +Name: system/app/HTMLViewer.apk +SHA1-Digest: YJEAmGPoJwNIEf/WCqlV1rTPiX8= + +Name: system/bin/mm-qcamera-test +SHA1-Digest: EjBZN4UpyTH13TbjzlTB1u7XQXQ= + +Name: system/bin/am +SHA1-Digest: JU7gkgpcGs2BY+uIS5nNG1/nRtY= + +Name: system/etc/bluetooth/auto_pairing.conf +SHA1-Digest: SPc0OzG5Xfm2TPetGFnjUxYan9Y= + +Name: system/etc/tfa/fm.eq +SHA1-Digest: mvLm1ceGsSM6opsaJy+PFY2w3do= + +Name: system/app/SocialManager.apk +SHA1-Digest: 8L019tqzLqJppfKWth4bh2nDfKE= + +Name: system/etc/firmware/ILP0100_IPM_Code_out.bin +SHA1-Digest: bL5o56wRmZlVcVXu6wRKrvnF8MA= + +Name: system/app/Transfer.apk +SHA1-Digest: /gFzTblnPFo0K56ctlqKXuRKdHE= + +Name: system/bin/df +SHA1-Digest: jGLWgCm9QmvH6/qetbOi/GqrFOE= + +Name: system/app/WeatherSyncProvider.apk +SHA1-Digest: JbI3ptG6JggDpdwGr9M+NmPE7rs= + +Name: system/app/HtcWeatherLiveWallpaper.apk +SHA1-Digest: U6cgNh3CjwDNtOFtNXC1MlKbgkQ= + +Name: system/bin/dd +SHA1-Digest: 6lMGBoet/af17l3XySv99L/R4c8= + +Name: system/lib/hw/keystore.default.so +SHA1-Digest: cTDeTRawJqZQoxX9fhOWviKosZY= + +Name: system/bin/bluetoothd +SHA1-Digest: Ing60m+r7Musn1ZPoNnJXk5L+YQ= + +Name: system/customize/resource/quicklaunch_22288.xml +SHA1-Digest: WoRvx95L1XhotmetvpDDs/JaXps= + +Name: system/etc/security/cacerts/9d6523ce.0 +SHA1-Digest: vE5/LZQwY6jpSaq4Tnfywc0Nf6Q= + +Name: system/lib/libDxDrmCAPI.so +SHA1-Digest: Jn39E6+vzVmEZjjd9aqy3yPudnU= + +Name: system/media/audio/notifications/Glitter.mp3 +SHA1-Digest: 8xwWxRN47HFDxG84tQIypr9Lu6A= + +Name: system/etc/tfa/playbackbeats.preset +SHA1-Digest: PC0c9KHkxMg9IY8tbXq330N1H9c= + +Name: system/lib/libbluetoothd.so +SHA1-Digest: Kf1k4plLaWh4HqZA3Wl+gvPSLi8= + +Name: META-INF/com/google/android/aroma/icons/Thumbs.db +SHA1-Digest: xvG5zD3j90Z2zcoSuIrMsqPNQPY= + +Name: system/app/Prism_SocialFeedProvider.apk +SHA1-Digest: LcXWD2Dhm442dY22/IOP1DeHDJg= + +Name: system/fonts/DroidSansHebrew-Bold.ttf +SHA1-Digest: TuR/SCZHlNxWFl5ftrhCebjvNrI= + +Name: system/app/HTCShoeboxEngine.apk +SHA1-Digest: zZuZIgE6nPfVnOYpmocOW/8Xkhc= + +Name: system/app/HtcBackgroundDataWidget.apk +SHA1-Digest: wwZboWB6jFkQGeOAQkBFElxPkNQ= + +Name: system/vendor/lib/libwvm.so +SHA1-Digest: xtuBL9F/Iw9U3uCPom8N5cnKkNU= + +Name: system/media/audio/notifications/Rust.mp3 +SHA1-Digest: TVj8Av7JGO0+kxHmyF0cT4ZiSR4= + +Name: system/lib/soundfx/libbundlewrapper.so +SHA1-Digest: GAYYoXeb3xA7bbgymcuD7pRt98U= + +Name: system/bin/rmmod +SHA1-Digest: uPMvvrg7WP5WaQ6KhDaIjN8/6Jw= + +Name: system/media/weather/weather_l_fog_night.mp4 +SHA1-Digest: iVJD7mjM9MUEvJZ5fIZV5jxwrGE= + +Name: system/lib/hw/gralloc.default.so +SHA1-Digest: ofqqngjz68qeHxl7Mo/GhjwElwI= + +Name: additions/desense/Nova.apk +SHA1-Digest: Ce8iKCBW4trvTsIG5z0YLM00+7o= + +Name: additions/battery/bluep/app/SystemUI.apk +SHA1-Digest: CFdceWIbUPrhnYbl4yNuI+Dt5v4= + +Name: system/lib/libril-qcril-hook-oem.so +SHA1-Digest: tbOnWjJm9pXd1LcL0pJL2nN/fGo= + +Name: system/usr/srec/config/en.us/models/generic.swiarb +SHA1-Digest: ji4QTXKau8N4AjzzU5UsqY8aQ7c= + +Name: system/media/audio/ringtones/Sense.mp3 +SHA1-Digest: v2kVQsjzGjnHTEFpe1jwbSDXZ4s= + +Name: system/etc/bluetooth/audio.conf +SHA1-Digest: rqcq4pfB6gnsm400Ue4v9FQukus= + +Name: system/app/FacebookEngine.apk +SHA1-Digest: unEXelTyVUxzJ6Z3AVmVJyYxYXo= + +Name: system/etc/security/cacerts/a7d2cf64.0 +SHA1-Digest: ue9ZDnsNcXdGKbdrk7MpOk3dLUM= + +Name: system/lib/libbtio.so +SHA1-Digest: FTMd78TBCSNJKxVajFu2R53PRbM= + +Name: system/bin/uptime +SHA1-Digest: lXf7kRRv7nXBW6xaNv4z8SOgPgI= + +Name: system/app/KidMode-google.apk +SHA1-Digest: SyX6gr5hMONtIL/4v1Ci4VStKSg= + +Name: system/etc/security/cacerts/3c58f906.0 +SHA1-Digest: TfWYQv3pjUCWxBCz5mSQzgH9OKk= + +Name: system/lib/libvideoeditor_osal.so +SHA1-Digest: M9KN6MZEW+Wyawc6LMR5aDX/h6o= + +Name: system/customize/cid_map.xml +SHA1-Digest: LcDHJDcRwmOZUGuvulz6RW69gY4= + +Name: system/bin/wpa_cli +SHA1-Digest: P2MhsFUY1/II1yOuRq8cd/irmDc= + +Name: system/etc/security/cacerts/d16a5865.0 +SHA1-Digest: HwEya3RYnDLYdyMkC8yCmJzSKhs= + +Name: additions/fonts/klavika/Roboto-Italic.ttf +SHA1-Digest: jclIVHKvfdnQioiQk/Kgoo/fCLA= + +Name: system/lib/libdss.so +SHA1-Digest: u2DI11Sm5jl6UAQEoo4w/DOJuQ8= + +Name: system/etc/security/cacerts/882de061.0 +SHA1-Digest: C44riBaYmFJys31UFiqhZTMc7Ig= + +Name: system/customize/resource/wallpapers_a_04.jpg +SHA1-Digest: f7toV7fN4/+q1BfrF0iyhJxPw+w= + +Name: META-INF/com/google/android/aroma/themes/sense/nav.9.png +SHA1-Digest: wvj1TM+Wvf4eIYnWvMbnS5lFnrc= + +Name: system/etc/security/cacerts/8470719d.0 +SHA1-Digest: 3gm79ScbKCIpUzG6Fq+8xe+sGnw= + +Name: system/customize/resource/rp_ce_0560.png +SHA1-Digest: hFEF1g+Vj4KgFyRTsTOilss+azc= + +Name: system/etc/security/cacerts/e775ed2d.0 +SHA1-Digest: QnV/erxTCKUTQ8iuLmezodkrswc= + +Name: system/etc/firmware/vidc.b03 +SHA1-Digest: dg6KpFSRatn6L/ugYLCi30+n2Wo= + +Name: system/etc/firmware/vidc.b02 +SHA1-Digest: YSXzJYbrbxurueOJHfDHQ7N5W+Q= + +Name: system/media/GPU/stylizeContrastRamp.bmp +SHA1-Digest: byEwbeK2WiDAeJZHW1EHCG+p2qU= + +Name: system/etc/firmware/vidc.b01 +SHA1-Digest: uDqET53DNXtQ4y3Q4m6JjU32g4Y= + +Name: system/lib/libqmi_common_so.so +SHA1-Digest: gach3Ovy3fH42qnI1gHJNqzwoSw= + +Name: system/lib/libmm-audio-resampler.so +SHA1-Digest: DzlGiC+aFW5LA76fKZf55oEeNWc= + +Name: system/etc/soundimage/srsfx_trumedia_music.cfg +SHA1-Digest: B+99y1yk8dYqYyWoTfC/EIJ6l0E= + +Name: system/customize/resource/allapplication_24001.xml +SHA1-Digest: KatjPxCXN3IgNC1j2x2qWBCngwQ= + +Name: additions/battery/greenp/app/SystemUI.apk +SHA1-Digest: J3mybY6MUqvghObCiCddrTqieBc= + +Name: system/etc/security/cacerts/c9f83a1c.0 +SHA1-Digest: f3imgBTggzJSdmhd0Xk1YU+iT54= + +Name: system/lib/libgnmc_decoder.2.5.9.4.so +SHA1-Digest: BQ42wCRSi98k/GXnCWmdNqf7E7Q= + +Name: system/fonts/HelveticaNeueLTPro-Cn.otf +SHA1-Digest: jELk06Ol8P0BI7WKfng0GMhgs4c= + +Name: system/app/HtcAirplaneModeWidget.apk +SHA1-Digest: +eKr0JYjwdB+BQ6osP7x9NgQ5ys= + +Name: system/bin/bmgr +SHA1-Digest: bBpREmgN5x0uzCxgS8dQhyklSCA= + +Name: system/app/HtcWiFiWidget.apk +SHA1-Digest: mD7i8AHd7Ojsbld1N0bcsX9RyJE= + +Name: system/etc/security/cacerts/895cad1a.0 +SHA1-Digest: ZfoxSCSC3uyNPPMG27Jrd3n1Ej8= + +Name: system/usr/srec/config/en.us/dictionary/cmu6plus.ok.zip +SHA1-Digest: ACsZaiNkJjr+osByDLYlAO7jbjo= + +Name: system/app/HtcNotesPainterView.apk +SHA1-Digest: o8/hN4j5v7uViNNtGs+f3BhY/Tk= + +Name: system/media/audio/notifications/Creme.mp3 +SHA1-Digest: 5CSXz5MEIK563WBXF1CXPaJ1LW4= + +Name: system/bin/gzip +SHA1-Digest: JyvMJh12ypgvyR830X5HCttpwHQ= + +Name: system/customize/resource/quicklaunch_250.xml +SHA1-Digest: eP6cTXc2z5D6AMAIW/yNEF9nFAI= + +Name: system/etc/tfa/voiceWB_l.eq +SHA1-Digest: 72hg+IrsxZZsykZj86tVEhqcZAs= + +Name: system/media/weather/weather_l_hot.mp4 +SHA1-Digest: eQev9Zca/qWTtsthmuECQGe9C2Q= + +Name: system/bin/lsc_camera +SHA1-Digest: IGd8Lornm9e7XOzG/ynhF4MWOUs= + +Name: system/app/HtcMessageUploader.apk +SHA1-Digest: yPG1Pwt74eJaJBRU/9DVEaDVLwk= + +Name: system/etc/security/cacerts/1dac3003.0 +SHA1-Digest: xqnEkR4Urw+Mekb6eWImjmF2AMM= + +Name: system/lib/libMusicVisualizer.so +SHA1-Digest: EYF49bAZKhmwbeNh2OhOEexvUEo= + +Name: system/app/PolarisOffice.apk +SHA1-Digest: JFvYAR7qE2souad1p6oR1S+dg0w= + +Name: system/etc/firmware/vidc.b00 +SHA1-Digest: hLHwO/SVUNir7KdAQLI/7uz1M6s= + +Name: system/app/IMEXT9Ukrainian.apk +SHA1-Digest: zu1owczQHpRLW2EHdrHm+YfTjjI= + +Name: system/bin/zchgd +SHA1-Digest: Sh5o2VJM0UuH+DIV2QKidFPBLg4= + +Name: system/etc/permissions/platform.xml +SHA1-Digest: B4DaWYYzqfuysBG6ebWmi56BR74= + +Name: system/lib/libwt6pptrdr.so +SHA1-Digest: pu0gqop15ZPmahIdDqH9aq97ZM0= + +Name: system/app/HtcDataStripWidget.apk +SHA1-Digest: akpLCRldAjmSJ9pPT5BOqnpfX+w= + +Name: system/app/HtcContactsDNATransfer.apk +SHA1-Digest: Dv7cq/cvF/OWdQovTtwFiOyRpFU= + +Name: system/etc/security/cacerts/c3a6a9ad.0 +SHA1-Digest: fbdLZbwmByGAC1L8jv9+TWtc61s= + +Name: system/lib/hw/copybit.msm8960.so +SHA1-Digest: 2sX4Ht1ng5blGlYsYfnbQQfmpFE= + +Name: system/lib/libaah_rtp.so +SHA1-Digest: A7NTkR3B4hWwTrgJw4EUUwQlqIE= + +Name: system/bin/start +SHA1-Digest: /3LV6Ws6VkFzwNSJkoyN2LGdNdw= + +Name: system/lib/libchromatix_s5k6a1gx_default_video.so +SHA1-Digest: gzEvq5ZrnkjOtQ7K2rpN6B1eCec= + +Name: system/etc/NOTICE.html.gz +SHA1-Digest: twWFZX7EFH6o07wunRbXuPNFX8I= + +Name: system/bin/mm-mpo-dec-test +SHA1-Digest: VLghETRXdLUDvFRSeh914q9wGvs= + +Name: system/lib/pp_proc_plugin.so +SHA1-Digest: 8OAvdozqrci06WDu6ydsi7GaRX8= + +Name: system/bin/hd +SHA1-Digest: uXqHkK1skY7C3lHsU/j969msqwc= + +Name: system/app/HTCWeatherClockWidgetAgent.apk +SHA1-Digest: RV4UQyZlVBIXwCygsvjFsdt1HHo= + +Name: system/media/audio/notifications/Olive.mp3 +SHA1-Digest: wUE56b5AqoklljGbDlKMAlKw9Qo= + +Name: system/app/Facebook.apk +SHA1-Digest: +kqYKx6qa1piDrrlWmwrgArCdqc= + +Name: system/media/zchgd/batt_20.rle +SHA1-Digest: xP1qebJOAFu8kO4BRgVcnfHDFOg= + +Name: system/app/HtcCalendarWidgets.apk +SHA1-Digest: vZhSStJmVr7KERwe3NjPH27wr24= + +Name: system/app/VoiceSearchStub.apk +SHA1-Digest: e7bLPllwwcDBcshfeV8z2/iT3c0= + +Name: system/media/zchgd/charging_09.rle +SHA1-Digest: QEchPYa+nGV/huI0/6+hg0aBONc= + +Name: system/lib/libmorpho_edit_engine.so +SHA1-Digest: HPUdkF61w2+3FfOac7PsO3cwQ9c= + +Name: META-INF/com/google/android/aroma/themes/sense/cb_on_sel.png +SHA1-Digest: 4OtiBiLhfOrOuJ2QT/UNRjr8bb0= + +Name: system/media/GPU/dot_mask_16x16.bmp +SHA1-Digest: ZGGV5rcruhPC7rb3du6G5Z2+dtk= + +Name: system/lib/libchromatix_ov8838_preview.so +SHA1-Digest: 4RFtACgp3+ZzHbFGNgy4ybRxgJU= + +Name: system/media/zchgd/charging_03.rle +SHA1-Digest: ekhart7hOvO1puEySttLB1i8r6Q= + +Name: system/etc/permissions/com.broadcom.bt.le.xml +SHA1-Digest: yjJIFy4CXQIFhE3de74RcEEiCjY= + +Name: system/media/GPU/ContrastCurveSet.bmp +SHA1-Digest: RIZsUiF7vgCiusq0P+jt/PoJa1s= + +Name: system/lib/libGLES_trace.so +SHA1-Digest: INzhxnQRFUQ0gN4ObhTn5Bf/hkw= + +Name: system/etc/security/cacerts/3e7271e8.0 +SHA1-Digest: RuWAcBguGdtlhixJYoOZcOECH4g= + +Name: META-INF/com/google/android/update-binary +SHA1-Digest: +Hc5mmK0diiOVs20WtZ2N6S2LqI= + +Name: system/etc/security/cacerts/89c02a45.0 +SHA1-Digest: loal9vEQNuqt054EQZ5Bc4v5bGE= + +Name: system/lib/libcameraasd.so +SHA1-Digest: DK0DoHcVsH35Cg2nnq+ZaQsglD4= + +Name: system/etc/tfa/voice_l.eq +SHA1-Digest: 11MY2YuU0QrbVYohMeReYItzFuM= + +Name: system/lib/libETC1.so +SHA1-Digest: ZVJtwNVK38JnU5JcNuvTLtb7/+Y= + +Name: system/fonts/Lohit-Bengali.ttf +SHA1-Digest: 8YyKXrXjV+v9Ocb9fWaRfBuhWdY= + +Name: system/media/zchgd/charging_05.rle +SHA1-Digest: tfGPbZxD1yMf1NNlWDad68dcCrs= + +Name: system/bin/screenshot +SHA1-Digest: QcsdkyUUq2+sheevzyAP5rX9Bak= + +Name: system/media/audio/ringtones/Vanilla.mp3 +SHA1-Digest: g1WeLc6dErQDWPotfPJLd/czOA8= + +Name: system/lib/libOpenCL.so +SHA1-Digest: JEoO/L8onFJXCywVVnDmaJh6P7g= + +Name: system/bin/cir_fw_update +SHA1-Digest: U0uQJPZHcFK5wwSZYr5aZ4MfvhU= + +Name: system/media/audio/notifications/Pear.mp3 +SHA1-Digest: w6KCOyC6V/tEv5SznvaGGwLz82o= + +Name: system/media/mms/kddi_earthquake_alert.mp3 +SHA1-Digest: /yk4s4lxpTfqF9BSM2Gb38LcEa0= + +Name: system/lib/bluez-plugin/network.so +SHA1-Digest: 6BWG8qvmf8MSHu5+4H0LKgf1bg8= + +Name: system/lib/libvideoeditor_core.so +SHA1-Digest: suOl0ljW9hEhSKvwpOO++sqlC/A= + +Name: system/lib/libexpat.so +SHA1-Digest: Rb0vWNk69RbealZadCYx0Dy8Gm0= + +Name: system/bin/thermald +SHA1-Digest: nrkMQSFV0kxCabGELaMpowyvuhU= + +Name: META-INF/com/google/android/aroma/themes/sense/radio_on_sel.png +SHA1-Digest: Gwz5HlyhTkojSpWYOMTzcvQbSdY= + +Name: system/app/HtcModeClient.apk +SHA1-Digest: 32X3jfQp7M5vRsfQ4c79jJTzOcE= + +Name: system/customize/resource/trickdroid.jpg +SHA1-Digest: by8iSHYhr+O/5wxDPOjAXN9zgMg= + +Name: META-INF/com/google/android/aroma/fonts/big.png +SHA1-Digest: KpRWRiPGaUoFVDl0JWboNJb3kfk= + +Name: system/app/Flashlight.apk +SHA1-Digest: HcVaR9W4wD6jYOuJ2bm6bNbVCEo= + +Name: system/etc/security/cacerts/27af790d.0 +SHA1-Digest: 0cY3bpCx4tRkNSVNjHyk12XB36Q= + +Name: system/lib/libaudioutils.so +SHA1-Digest: Yvr0K/4tKgT9etrrtUL26ahlbYk= + +Name: system/customize/resource/quicklaunch_20201.xml +SHA1-Digest: rwXDAslQp8xBCcxUJnJ8CJIlUXA= + +Name: system/etc/hltof.bin +SHA1-Digest: E6HnhglLpohiT66gffeteHF1gWg= + +Name: system/vendor/pittpatt/models/detection/yaw_roll_face_detectors. + 6/head-y0-yi45-p0-pi45-rn30-ri30.5-v24/full_model.bin +SHA1-Digest: MK+pzoM4WfbE9qVi0dNWTVqG4fk= + +Name: system/bin/ndc +SHA1-Digest: L2DiqqXI/gXsJc9f0p3jll6l2uY= + +Name: system/lib/libsqlite_jni.so +SHA1-Digest: /dp3RYPLyOeNkZF85oSVSQOpkZk= + +Name: system/lib/libskia.so +SHA1-Digest: eTs4bc0g0NBOUmY7YKAD7qcZUxQ= + +Name: system/usr/srec/en-US/google_hotword.config +SHA1-Digest: u15PKfBvK1oxEnD02hPRCZy5Ez4= + +Name: system/lib/libdrmframework.so +SHA1-Digest: YC5O2B3yFmjHeNUw7zq7Tyx46j4= + +Name: system/lib/libandroid_runtime.so +SHA1-Digest: mSn68M7/cC8JjKcxNBywUY6d8UI= + +Name: system/lib/modules/moc_crypto.ko.3.4.10 +SHA1-Digest: LoH2y/67VcUXbDcSyHtWaAlcxBs= + +Name: system/lib/libgabi++.so +SHA1-Digest: tvlZmxwNOKHVV9wzmrczWHrQT5E= + +Name: system/bin/ip +SHA1-Digest: sFPEmZn4s/h/tSqxXlBqFDm0ua8= + +Name: additions/fonts/segoewp/Roboto-Italic.ttf +SHA1-Digest: gYwfIM7YiamQ8LbsmJyQxwRPk8o= + +Name: system/bin/rtspserver +SHA1-Digest: 7AA9maQRx8u+aTKlS1smUsBD1tk= + +Name: system/etc/permissions/android.hardware.camera.flash-autofocus.x + ml +SHA1-Digest: aDfHvVEe0svv+HGWg3e4S1UZY1k= + +Name: system/bin/id +SHA1-Digest: Tg1r0n8FAqaLfIIMOOvPSuCINFk= + +Name: META-INF/com/google/android/aroma/icons/personalize.png +SHA1-Digest: J8xJz95qwUKrTDbgbqbfNFHoUus= + +Name: system/bin/setprop +SHA1-Digest: c7E/TK82xoZwPO8f1t1AMhXABrY= + +Name: system/lib/libstagefright_soft_rawdec.so +SHA1-Digest: 8G+s9aImm6wKxevQoDxofCNwj4w= + +Name: system/bin/kill +SHA1-Digest: ZM4BTwhKGJcdH3BjMPSJOm3AfwE= + +Name: system/etc/image_htc_earbud.bin +SHA1-Digest: CXqwEDbDsU5pxYviO6SHIIrchrY= + +Name: system/app/OneTimeInitializer.apk +SHA1-Digest: I7gBGYaAMlfc846vxsQWFHSeOfo= + +Name: system/usr/share/partials/ticklist.csv +SHA1-Digest: hf6Xd219x7zu+QnONGHZYNryBIU= + +Name: system/app/JETCET_PRINT_S50.apk +SHA1-Digest: KBNUWUeiDoFp7virDScfnmTcFDc= + +Name: system/etc/permissions/com.android.location.provider.xml +SHA1-Digest: amS9x3HUOepZjI/MyRzFmoDrRd0= + +Name: system/lib/libzeroeditor_videofilters.so +SHA1-Digest: 2ZELTdGUSReItUbmyTEV14ni9j4= + +Name: system/lib/libChange.so +SHA1-Digest: pIRy2vqW8avXhBleDg19l9OaoxM= + +Name: system/bin/ln +SHA1-Digest: p9+8eSYK/dYwxpTsBpGa807nv2k= + +Name: system/etc/capability.xml +SHA1-Digest: zMt3LK6q5/6xTWQpFwGB+bU+8H0= + +Name: system/bin/ls +SHA1-Digest: oVGslBM2u80MkNXXi9dBXNbdxMc= + +Name: META-INF/com/google/android/aroma/icons/customize.png +SHA1-Digest: envvq/UioWgJ0FmKVyuWyqaZVwk= + +Name: system/bin/mksh +SHA1-Digest: SDK79qz88hb7ajBOtAlBtWmLPrs= + +Name: system/etc/tfa/fm.preset +SHA1-Digest: r4QDvqDV9VrpQz8kSeaRsSURtmc= + +Name: system/media/audio/ringtones/Pearl.mp3 +SHA1-Digest: ivSx/6gSoIt1/v91SSXoXeN6BvI= + +Name: system/etc/permissions/com.orange.authentication.simcard.xml +SHA1-Digest: ymx4aLoY1maYXcz1PdSz0gfiJvk= + +Name: system/customize/resource/allapplication_23801.xml +SHA1-Digest: DkvCSwQpAwK65A0UuC8SRnn8EKY= + +Name: system/media/audio/notifications/Saffron.mp3 +SHA1-Digest: dUePQaaFmtO/Ul1aIXMAPzUOg4U= + +Name: META-INF/com/google/android/aroma/icons/nova.png +SHA1-Digest: kGBOFfg0gV4/+6A/YM4fkpT29P8= + +Name: system/bin/ks +SHA1-Digest: 5cz+U+l5Wh5yrx4BjelOfQc54ew= + +Name: system/lib/libm.so +SHA1-Digest: 0fY2xDEtyemq405b93Lm8/daDak= + +Name: system/lib/libdrmdecrypt.so +SHA1-Digest: wEZplOEiPdEJdS8po6oPuCtKB9c= + +Name: system/media/zchgd/charging_02.rle +SHA1-Digest: V8XXH0zjVf+UYS98Zgyf8rHERK8= + +Name: system/bin/hostapd +SHA1-Digest: hFqMKoGrtFWrGldHrAHFLxEY1m0= + +Name: system/tts/lang_pico/de-DE_ta.bin +SHA1-Digest: UxOTX6s/ImMF3+i9MWBJSPZ52Hs= + +Name: system/lib/libmm-abl-oem.so +SHA1-Digest: RON+y9Xd4UjJDmAX8xhlGfHBAi8= + +Name: system/etc/voicemail-conf.xml +SHA1-Digest: cpbegTHSEXbwpD146kWK9nSW+jI= + +Name: system/app/HtcCompressViewer.apk +SHA1-Digest: JSyR4UahTfAqOsjtocKH72voXsI= + +Name: system/usr/srec/en-US/offensive_word_normalizer +SHA1-Digest: JlWzqRWPoWw50GU8zCZrADdDH+E= + +Name: META-INF/com/google/android/aroma/changelog.txt +SHA1-Digest: DGmPbFSCsgFJDysnqWjZZzJfyDk= + +Name: system/media/audio/ringtones/Pink.mp3 +SHA1-Digest: WwK1p3HPPcW1Xzibg0BVuBlvHT0= + +Name: system/lib/libchromatix_vd6869_hdr.so +SHA1-Digest: vJmVfedV940c1tKdl8GespTlic8= + +Name: system/media/PFFprec_600.emd +SHA1-Digest: tY5XAqhHwXuMXM5dlnwKhnKvt/A= + +Name: system/usr/share/partials/partials_H_gb.csv +SHA1-Digest: fv0hDkjmNqIxK0f0Uf9tSOT9yfM= + +Name: system/app/SoundSetDownloadManager.apk +SHA1-Digest: pzx4o376t7z3MisdkNmU9+wGSus= + +Name: system/lib/libjavacore.so +SHA1-Digest: jlxoVgJ2TwLJussjhmMnzch28OA= + +Name: system/lib/libwlwpscli +SHA1-Digest: GFV2r0fGjT8wKpvyKp+n6432GEA= + +Name: system/media/audio/ringtones/Brass.mp3 +SHA1-Digest: wGEOhvW27Q2qcU664/fNa0WixVA= + +Name: additions/wipe/bash +SHA1-Digest: KPGXHEUCSWS7mah9DpGJO94czkA= + +Name: system/customize/resource/quicklaunch_65501.xml +SHA1-Digest: kGnxQlcVCBmXmK/zxW8fWCgbFIo= + +Name: system/usr/share/partials/partials_CW_rr.csv +SHA1-Digest: 2UXIVf653OLrELajiXGbfCufxnw= + +Name: system/etc/security/cacerts/7651b327.0 +SHA1-Digest: XHbRZvJn9XfMIFtTqDSXFV3AzRM= + +Name: system/bin/ioctl +SHA1-Digest: 05TebPkXcYMvqOgd8Vkse4BX6GA= + +Name: system/app/IMEXT9Italian.apk +SHA1-Digest: pQJ7t7Lch1k126ZxOBE1u5lrWLY= + +Name: system/bin/mv +SHA1-Digest: Yul+yVkdWwUkHoVRKMp0BAc1nw0= + +Name: system/lib/hw/lights.msm8960.so +SHA1-Digest: 76y6imO8vl50iq7DQ04msl5OJAk= + +Name: data/app/com.google.android.apps.plus-1.apk +SHA1-Digest: 9WU0JqJ3doLKW33WCMSwM1+IU+w= + +Name: system/media/audio/ringtones/Cerise.mp3 +SHA1-Digest: Qxuwzsd2qK4KcpXgeLi+LYN1SQ8= + +Name: system/etc/security/cacerts/219d9499.0 +SHA1-Digest: h/DoWPK51SL4obNm8yCTilqR0+8= + +Name: system/lib/libmmcamera_statsproc31.so +SHA1-Digest: e5J+f6bBB9WjQfpvnNmC2E/GFFI= + +Name: system/usr/icu/icudt48l.dat +SHA1-Digest: kanMdtwKTwlxkx1DtKWAJmwzCXw= + +Name: system/fonts/ARDJ-KK.ttf +SHA1-Digest: pGUbOB8+3o3rp9q+YY3ezzwgC4Q= + +Name: system/lib/libDxAndroidSpecific.so +SHA1-Digest: dKdWRM+D61L2sWiZoqCmOWW1F70= + +Name: system/app/VpnDialogs.apk +SHA1-Digest: pFLiB6M+S2d65MAA0PDhyujBImE= + +Name: system/app/IMEXT9Swedish.apk +SHA1-Digest: HVwZ5+ZXlX9govJieMI3tdSm9VA= + +Name: system/lib/libpphwrcore.so +SHA1-Digest: 4ZYZIsH9XB67Geym4B/ydBJHnHg= + +Name: system/media/audio/alarms/Jade.mp3 +SHA1-Digest: de1jJWm4UI253FRMXUditS8ntug= + +Name: system/etc/security/cacerts/60afe812.0 +SHA1-Digest: ttJEIPTia8N+uVOS3mUfCJzhFvI= + +Name: system/usr/srec/en-US/hotword_symbols +SHA1-Digest: dbEFacb+0FC8zwiG1opgbrzcACQ= + +Name: system/app/ZeroEditing.apk +SHA1-Digest: A1Y9H9yE78+Yx+HnmTVKzV1pe5M= + +Name: system/app/Trim_n_Slow.apk +SHA1-Digest: u+C8g7i9hdWAhd148BOn5Hcl1Lg= + +Name: system/etc/security/cacerts/f0a38a80.0 +SHA1-Digest: Hm9gf50Bu8p9qGUTsxt/fvnJteU= + +Name: system/vendor/pittpatt/models/detection/yaw_roll_face_detectors. + 6/head-y0-yi45-p0-pi45-rp30-ri30.5-v24/full_model.bin +SHA1-Digest: zylgR6Y3XLkv3CWuB04/XsCJjbE= + +Name: system/lib/hw/power.default.so +SHA1-Digest: tN3SujJIGPPXk9Ca8eTqttzjCBw= + +Name: system/lib/libmmwfdsinkinterface.so +SHA1-Digest: a8CN1rDFDnvFOyeQKcmOtgG04oI= + +Name: system/lib/libdbus.so +SHA1-Digest: xMQppjZUkYcjSryk10RyTnGt2cw= + +Name: system/bin/input +SHA1-Digest: fmnGVSPBoXqAUgaTVBG6zdBwPNY= + +Name: system/lib/libalmashot-seamless.so +SHA1-Digest: OBea13pOI++tVc9Ul93/MYasfk8= + +Name: system/customize/resource/wallpapers_a_01.jpg +SHA1-Digest: oIO8YIu9JAx8B0kZ9jd8e0ZmwjY= + +Name: system/lib/libmmwfdinterface.so +SHA1-Digest: tYQ74gGUNhhOanfCrdGAv8+KJkM= + +Name: system/lib/hw/local_time.default.so +SHA1-Digest: anrPxzoXpjstXkH/+VDMpjOttS8= + +Name: system/media/zchgd/batt_60.rle +SHA1-Digest: Ci0cVjXfi3uHBdU7/R8kJ/pwaOg= + +Name: system/lib/libext2_com_err.so +SHA1-Digest: JdZ2atQG7H+wbPx6yWnf9z+nGT0= + +Name: system/bin/pm +SHA1-Digest: ZZqEROz0ggs5Pz1SZjKHP/AP6xw= + +Name: system/bin/mm-mpo-enc-test +SHA1-Digest: kCIOhg3fYX4iR1GhvYkOP2pA9Go= + +Name: system/etc/firmware/fw_bcm4335.bin +SHA1-Digest: k9ATLXVv7+F2jeHkrbjoc6whcRE= + +Name: additions/desense/Apex.apk +SHA1-Digest: 1ib2ZE7cAUCq7e2lToFqfZzblto= + +Name: system/bin/ps +SHA1-Digest: OPLUXuOPhY18Zi7PSOoRZuJPXjg= + +Name: system/etc/firmware/a300_pm4.fw +SHA1-Digest: ISjYgZpYq77YSXg2WGUDsl2xLJc= + +Name: system/lib/libchromatix_ov2722_hdr.so +SHA1-Digest: oelR4ErCfu0PnkSk92mWIZHaPxk= + +Name: system/media/audio/alarms/Amazon.mp3 +SHA1-Digest: A1hEgekWvzvyNsqEM6c+d3fub7M= + +Name: system/etc/tfa/voiceWB.eq +SHA1-Digest: EQQ5dOV9sCue4lsOOPhSihud02E= + +Name: additions/camera_4.2/lib/libjni_filtershow_filters.so +SHA1-Digest: ytVQD2l9BW3Wgvi5ekA5FF1HKlI= + +Name: system/bin/port-bridge +SHA1-Digest: Bx2n57Aq0Fly6IaIYgDdqud4eU4= + +Name: system/app/IMEXT9Norwegian.apk +SHA1-Digest: mBMOR6uLgf4NQv4IJV6Dkq2aWJY= + +Name: system/etc/sdk/sdkinfo.xml +SHA1-Digest: VVobJulw9nm+TbKcDgRcDTAu1oI= + +Name: system/lib/libImageAlignment.so +SHA1-Digest: q8yn6YsZkZgAtFUnyXMvrMl71/o= + +Name: system/bin/dalvik_coredump.sh +SHA1-Digest: o2J9r+hGyYCZMXthnRKemxKbBCs= + +Name: system/fonts/Lohit-Telugu.ttf +SHA1-Digest: abw73bBK9fbGs9tX2WASfCr7QvA= + +Name: system/etc/image_ibeats_2vol.bin +SHA1-Digest: Tnay7C4pHloO2refAYca0P/1NtA= + +Name: system/app/BackupRestoreConfirmation.apk +SHA1-Digest: YgB0NolrJqLztOZXWafuzaIT3JQ= + +Name: system/tts/lang_pico/es-ES_ta.bin +SHA1-Digest: iomlWBJnyeAmuhpPJfKYJkKDUEw= + +Name: system/lib/libstagefright_enc_common.so +SHA1-Digest: eFMlMpgGo0Bgj3a7FEBdneQBIaM= + +Name: system/lib/libsurfaceflinger.so +SHA1-Digest: C7J6nn0ong8ir2IVPlCXfzVRjCo= + +Name: system/media/audio/notifications/Capri.mp3 +SHA1-Digest: ARuq6LzlgMZ1CcNgHLtWWVmIMTY= + +Name: system/etc/updatecmds/google_generic_update.txt +SHA1-Digest: /JTgfNkrdifcko4L7i/FD70eeaA= + +Name: system/bin/tc +SHA1-Digest: EK+BjCgltQY5Sbf+vsYliPaQKXo= + +Name: system/bin/dmagent +SHA1-Digest: TA87HnbbgTpWv/nmWgqzjyFzVFM= + +Name: system/fonts/MTLmr3m.ttf +SHA1-Digest: lq6qXjY2kKKL6Rf1iBi0b5nkumA= + +Name: system/lib/libOlaEngineNew.so +SHA1-Digest: 3e/s4RP7Q8V/cwxyBIQVvF5pMlw= + +Name: system/bin/brcmapd +SHA1-Digest: h1ySdqwhLVz1KzJUIcEcXSRwJwE= + +Name: system/media/audio/ringtones/Yellow.mp3 +SHA1-Digest: gQarkiMhIuXOGwOQ7J5EQW6qlJc= + +Name: system/etc/security/cacerts/a15b3b6b.0 +SHA1-Digest: Ga8+gSid8GucSUYQ4UcWClt0eZI= + +Name: system/customize/resource/allapplication_26801.xml +SHA1-Digest: 0q41RuHWovB8oGPHk333zn6omc0= + +Name: system/etc/security/cacerts/33815e15.0 +SHA1-Digest: sxrwaxlAJHZVh6z+sNYj97iZIuA= + +Name: system/lib/libstagefright_soft_amrwbenc.so +SHA1-Digest: mi/2CUKJSkgdL0v8hMdQe9Xv8KY= + +Name: system/usr/srec/en-US/google_hotword_logistic +SHA1-Digest: sYH+W7m9I89ltQfiDWM1Pi6quVg= + +Name: system/etc/AudioBTIDnew.csv +SHA1-Digest: OqoJD98zSi+0bgQ71GlQ61s/D5I= + +Name: system/lib/libOpenSLES.so +SHA1-Digest: Kl1FYgKYPFTqSUR/wBupW0kxyS0= + +Name: system/lib/libgnmc_aactag.2.5.9.4.so +SHA1-Digest: SqiphGmt8er5d/uIqLqOX56dILE= + +Name: system/lib/libwebcore.so +SHA1-Digest: L/si2K329/yV62czlJM7jfgsY9M= + +Name: system/lib/libhwui.so +SHA1-Digest: njdGivGkB7wjEm3I5U9Lt0Vhr3Y= + +Name: system/media/audio/notifications/Lilac.mp3 +SHA1-Digest: 4v8zhTEMyL+qQze1B3o3aM7KeaI= + +Name: system/etc/tfa/voice.preset +SHA1-Digest: AHdeBzE+aWvVm1+lPSFIH9aVQ5Q= + +Name: system/media/audio/ringtones/Mustard.mp3 +SHA1-Digest: F9G9K6OBnLZjOknDhcmUN99i6e8= + +Name: system/media/weather/weather_l_thunderstorm_night.mp4 +SHA1-Digest: 933h42nOwxpmjBMtfeRffjhQY9M= + +Name: system/usr/share/partials/partials_A_rr.csv +SHA1-Digest: 7N+zrRg29j67fnbxIs/RKj+DHsY= + +Name: system/lib/libsrec_jni.so +SHA1-Digest: m6ENj91zQKcDhi1YXCFHQT2SxjU= + +Name: system/fonts/DroidSans-Bold.ttf +SHA1-Digest: WDG+d/J10mMQJ/zJyy0IqmMxQiI= + +Name: system/media/GPU/header32bpp.bmp +SHA1-Digest: PjhggTIP61boB4JqIvcpyJGbEv4= + +Name: system/etc/agps_rm +SHA1-Digest: eeIWQXwn7SfkaNiZ7b0Z+n+0oYo= + +Name: system/bin/akmd +SHA1-Digest: wwGmCKhzKRFsHioX4nUZ3EnOFY8= + +Name: system/app/MyGoogleTaskPlugin.apk +SHA1-Digest: 9DbAEYx2cca7XFpCDoR7Y15StmI= + +Name: system/lib/modules/bcmdhd.ko +SHA1-Digest: L2BqmFnLoAXmSjk7J4WjW0aZuW0= + +Name: system/lib/libmmipl.so +SHA1-Digest: AdWbW5mMg9reEHgh2AnKlqbOa5g= + +Name: system/etc/bluetooth/iop_device_list.conf +SHA1-Digest: JU1lqbNnhuHR/03bQ5Vvx86lb6k= + +Name: system/lib/libdmt_vocalizer.so +SHA1-Digest: vjVTMrqUu81Kaukl/GMrZjn/1hs= + +Name: system/etc/security/cacerts/10531352.0 +SHA1-Digest: y9ENJVY4/0yK+jqASHt1m0dczag= + +Name: additions/fonts/veggieburger/Roboto-BoldItalic.ttf +SHA1-Digest: bVb8HaPeeRPVr6cZgHkN2065hbc= + +Name: system/lib/libOmxVdec.so +SHA1-Digest: io5j7ZLtF9P0aJWzRzGqtpDujQE= + +Name: system/customize/resource/quicklaunch_21403.xml +SHA1-Digest: nc95ItwlVDnuDZ4/RD5CGYA4zPk= + +Name: system/app/HTCMediaAutoUploadSetting.apk +SHA1-Digest: kVx6Rp1glXw3Wx3lQfm3GGRqRoA= + +Name: system/bin/wpscli_test_cmd +SHA1-Digest: LuqBakNoBSNkjWwif7/6yDzhCAs= + +Name: system/lib/libchromatix_vd6869_video_hdr.so +SHA1-Digest: lMZHdaaPvE3M7ZIfXYPEJ2FXe9E= + +Name: system/lib/soundfx/libaudiopreprocessing.so +SHA1-Digest: auqvCwBX1Dh5Wo/aATaks+HxL3c= + +Name: system/customize/resource/allapplication_228.xml +SHA1-Digest: LGWAL0yrs6N5euEueAgerd//nJQ= + +Name: system/bin/dhcpcd +SHA1-Digest: ayY0ds68jiqrivUM4p4IeuPHMZU= + +Name: data/app/com.melodis.midomiMusicIdentifier.freemium-1.apk +SHA1-Digest: 03W6zO2d43p8ezJvyRQKtbA4ge8= + +Name: system/bin/l2_profile_exchange +SHA1-Digest: NWfzn7y0GDSUc+oph3TziQiG+Og= + +Name: system/lib/libloc_adapter.so +SHA1-Digest: lO9tZT9hdp8h4nOoUjP0xnPfFUU= + +Name: system/fonts/AndroidClock_Highlight.ttf +SHA1-Digest: UpUMgtFG6S4ktliTHrzjzh2Sb2E= + +Name: system/framework/com.htc.android.home.res.apk +SHA1-Digest: 2Co+tF+Irj51LK6BRN8U/hLw0/c= + +Name: system/bin/rm +SHA1-Digest: TwRPPHXmTAdrr25J0pC4RHg3n3g= + +Name: system/lib/libgoogle_endpointer_jni.so +SHA1-Digest: K1wXzd9qotSo3gwAdcKZtlthrro= + +Name: system/lib/libchromatix_imx135_zsl.so +SHA1-Digest: 7PZhONTWhBzBM8+yOUsFyTEhKDE= + +Name: system/media/audio/alarms/Turquoise.mp3 +SHA1-Digest: yXv9K97/G/Gf7dMp//Y0/uWS3nw= + +Name: system/lib/libbt-aptx-4.1.1.so +SHA1-Digest: tMjeiercoBpSJw3w5zAcwBjhIpw= + +Name: system/framework/requestsync.jar +SHA1-Digest: yd+irPspht8oiF9OAUNXr1O9ntk= + +Name: system/etc/permissions/android.hardware.nfc.xml +SHA1-Digest: HUIRpkagOLqayoGvTHbaDrcSTdc= + +Name: system/lib/hw/nfc.m7.so +SHA1-Digest: sbVxluVaDcNN29fNcAbvadMHGaI= + +Name: system/customize/resource/wallpapers_a_00.jpg +SHA1-Digest: WEx2MBpoxHDIBSN82fWjODWPCqk= + +Name: system/media/zchgd/batt_90.rle +SHA1-Digest: OJYeVZJzbDUIf2TCdBFkH78fw6A= + +Name: system/app/Tag.apk +SHA1-Digest: UoW0O0UfJ0aha9uYVsSg0qJfHXU= + +Name: system/lib/libdvm.so +SHA1-Digest: Jq9m+FnHKzJQCEPEFvFgH/KGv9U= + +Name: system/customize/resource/bootanimation.zip +SHA1-Digest: mZlVPgBP/svEc+9ESCJSb4dzcIA= + +Name: system/bin/sh +SHA1-Digest: dOr7EkmJu1IGtF1CyJwHMi1BtE0= + +Name: system/lib/libmdnssd.so +SHA1-Digest: WU8T7eLcvQBhrk9d5grr+qlsIAo= + +Name: system/etc/security/cacerts/ee7cd6fb.0 +SHA1-Digest: bkvA4zNXQeEiBJAmk+PXsF/pHKY= + +Name: system/app/FlickrEngine.apk +SHA1-Digest: yj6M/h+XANr32jSBR3QSuu2ov40= + +Name: system/media/audio/ringtones/Aqua.mp3 +SHA1-Digest: AsnPEvmilTGXNDg12+pLKP54uUc= + +Name: system/app/LocationPicker.apk +SHA1-Digest: Q9qZMpl4Ddz2Bus1eaNQjxYxU+k= + +Name: system/customize/resource/quicklaunch_23802.xml +SHA1-Digest: ZfBmyM/+qEJ/mVwYxhQrTd955IQ= + +Name: system/vendor/pittpatt/models/detection/yaw_roll_face_detectors. + 6/head-y0-yi45-p0-pi45-r0-ri30.4a-v24/full_model.bin +SHA1-Digest: CzQS2Q926UpzY1pj03Kjd1YbDNs= + +Name: additions/dormancy/dormancy.sh +SHA1-Digest: LXHsFAenVTzPhKD9rU3tUI345pQ= + +Name: system/app/HtcDLNAMiddleLayer.apk +SHA1-Digest: b8faWJZH8gqscn0+P/HGlALPvtM= + +Name: system/media/audio/notifications/Lime.mp3 +SHA1-Digest: T13WnRczblO5mxJb3YWGWobNJw0= + +Name: system/lib/libconfigdb.so +SHA1-Digest: KZvUX40Je/buKLGZm4os4HSvJok= + +Name: system/fonts/DroidSansHebrew-Regular.ttf +SHA1-Digest: vCyI5L4+fY5R89LvPsNi6paN1xU= + +Name: system/etc/security/cacerts/c8763593.0 +SHA1-Digest: +gdb++qnd0mWyTgp0LJzn5wDIrE= + +Name: system/bin/route +SHA1-Digest: gHUuofyUlDMflRogtpBAPKkz6E8= + +Name: system/usr/idc/qwerty.idc +SHA1-Digest: XSU+bbgHHEbEG/bF1WUYrQ9Nj/A= + +Name: system/lib/libhtcflag_native.so +SHA1-Digest: cz6J5RIvsJsiWHCkG75OQvgF1Pk= + +Name: system/media/audio/ui/Volume-2.flac +SHA1-Digest: AhcTvmDTuDYbtfj+QgyualjZBfs= + +Name: additions/fonts/helveticaneue/Roboto-Bold.ttf +SHA1-Digest: Q6EJJWzqQ1LxrkDVTYyleESzOZ4= + +Name: system/customize/resource/quicklaunch_28010.xml +SHA1-Digest: YHb55lJk2PHJTwfpy1RpraJ0XO4= + +Name: additions/gps/oceania/etc/gps.conf +SHA1-Digest: LsvW3krIB9w0I8BIB/dO6oQJR4g= + +Name: META-INF/com/google/android/aroma/themes/sense/titlebar.9.png +SHA1-Digest: HPInA6gixR/lSTi+REkYNBsjchI= + +Name: system/customize/resource/allapplication_65507.xml +SHA1-Digest: k4HYSzTI1A5BF/zD9Vf1F1GBa1c= + +Name: system/media/audio/notifications/Fuchsia.mp3 +SHA1-Digest: OW9DCX05PaSihqhfcz2tqHPnB88= + +Name: system/lib/libSkiaWarper.so +SHA1-Digest: LgpMolEgmz8ZSf1riteZgfBtzZ4= + +Name: system/media/weather/weather_sunny.mp4 +SHA1-Digest: 0tqYOKz0w4Zs7kRU1Mvz37WFD08= + +Name: system/framework/com.htc.android.bluetooth.jar +SHA1-Digest: /RY1AjaZYJlv8Ah73M/Cl98Imgw= + +Name: system/bin/mm-jpeg-dec-test +SHA1-Digest: 88vn/NOarwauvVOpGKBkP+9NxJc= + +Name: system/lib/libxt_native.so +SHA1-Digest: owK21ES5kW8gYpXm32Liht5Vj0A= + +Name: system/etc/security/cacerts/1dcd6f4c.0 +SHA1-Digest: J/9p1bSc/vj7DXamP+uHmvUOn2c= + +Name: system/etc/security/cacerts/9772ca32.0 +SHA1-Digest: LX2TMuCYXRh8QFOPADSkAjvHbuE= + +Name: system/media/weather/weather_cloudy_day.mp4 +SHA1-Digest: R/knv9o+P3UQP6hZIPgDaCJ71Sk= + +Name: data/app/com.google.android.street-1.apk +SHA1-Digest: /hv1zxVHNeDYmqgJA2ujE0vs5YI= + +Name: system/app/PhaseBeam.apk +SHA1-Digest: tG0+E849amQzmhBrycg7Ib21dac= + +Name: system/etc/security/cacerts/5e4e69e7.0 +SHA1-Digest: OPYnMzF7mxzqxH56G6+9Io0+wns= + +Name: system/etc/firmware/hcheck.b03 +SHA1-Digest: GPRM/l2NMcKylFH8+zsgdzxLQmY= + +Name: system/lib/libqmi_encdec.so +SHA1-Digest: r8S8/jdbJAmqizRKAMD2mD+u8Ac= + +Name: system/lib/libSR_AudioIn.so +SHA1-Digest: ZvAWqejA31cQtCSogywkwFfe/eY= + +Name: system/customize/resource/allapplication_24201.xml +SHA1-Digest: gDpuLVefExqtoLsKIuY91R8sRB8= + +Name: system/fonts/DroidSerif-Regular.ttf +SHA1-Digest: rdDAMVoPkeYHrAGCh/yUOvTm5UE= + +Name: META-INF/com/google/android/aroma/themes/sense/dialog.9.png +SHA1-Digest: mnNNn3dIEnvvW/cpB6vQjin58Cg= + +Name: system/etc/firmware/hcheck.b02 +SHA1-Digest: /jCgwrCADQNqwKNzD0ySVE3GAv8= + +Name: system/etc/firmware/hcheck.b01 +SHA1-Digest: nKHb3UysKozicEsRl4v+laz5BRs= + +Name: system/etc/firmware/hcheck.b00 +SHA1-Digest: cu5aebFBYncQ4f7iTeS4RmbBEKo= + +Name: system/media/weather/weather_l_thunderstorm_day.mp4 +SHA1-Digest: dbCxlAvlJPz/K2waolaqqKzC9EU= + +Name: system/etc/vold.fstab +SHA1-Digest: Y8bxVdlq3B6hbvq12aPX8yJfteo= + +Name: system/bin/ip6tables +SHA1-Digest: wCceVLKMhMq0g+j04fd8iuIMgBg= + +Name: system/bin/system_server +SHA1-Digest: SIkU/oY+tC8xUZZvWR+kR4NE2bY= + +Name: system/media/audio/ringtones/Navy.mp3 +SHA1-Digest: F4IW4r5WScTfGcpDbM0cWkeYpF0= + +Name: system/lib/libmmcamera_wavelet_lib.so +SHA1-Digest: SMya68qET4/Cln4UBEg2MPBpTEI= + +Name: system/media/audio/alarms/Steel.mp3 +SHA1-Digest: m1RXbH+1GjBi8ZPNyxzanb3K8Fs= + +Name: system/customize/resource/quicklaunch_23420.xml +SHA1-Digest: SVCjHpVqLLLiqMWrxac5NWOnOCw= + +Name: system/usr/share/partials/partials_H.dat +SHA1-Digest: lG+VGfsDTmtHFA9oUBbtS7QbWRc= + +Name: system/etc/tfa/playback.preset +SHA1-Digest: IKLscUobhcgfw/DnpdGEmglYOJA= + +Name: system/media/weather/weather_partly_cloud_night.mp4 +SHA1-Digest: 01Rk4i3kp8kjV4SvPAY+YA4QPsM= + +Name: system/media/audio/ringtones/Laquer.mp3 +SHA1-Digest: 2QFp9EPNR/v9rnqZKk7XDbTnhJA= + +Name: system/bin/sendevent +SHA1-Digest: rYRPw4b9e4gkkTsC66H3ztOJdNE= + +Name: system/etc/security/cacerts/08aef7bb.0 +SHA1-Digest: XVcxHM5N/xsTnkuy9vaaWCBrlTw= + +Name: system/bin/wl +SHA1-Digest: OQdlUrtmkgnphJ15J/s15hok3Go= + +Name: system/app/Settings.apk +SHA1-Digest: 4By+MceBBK7URTHYe79jqQ0TB6w= + +Name: system/lib/libstagefright_soft_mp3dec.so +SHA1-Digest: UH6hjIceVIFxd/6MoEPQwo1uKx0= + +Name: system/etc/firmware/fw_bcm4335_p2p_b0.bin +SHA1-Digest: l5lP68M201qLReKuCKPa246GGo8= + +Name: system/lib/libttspico.so +SHA1-Digest: 1yH0Ide+mM9FHhNxKzPXFgJZ9l4= + +Name: system/lib/libBeautyChat.so +SHA1-Digest: IoFMDKIokKPmrpwaUK+72+vpIn0= + +Name: system/customize/resource/allapplication_24801.xml +SHA1-Digest: fVhSVQFv4WcinppHBPKMTbSeiWs= + +Name: system/lib/libnfc.so +SHA1-Digest: xrLIk5FrAqy11mA7QYZF1j+UedE= + +Name: system/etc/security/cacerts/87753b0d.0 +SHA1-Digest: pDoFkt0ow4oMrnwoJ8V53XXw608= + +Name: system/etc/security/cacerts/1d657651.0 +SHA1-Digest: Nnt+JruWEZcGnA8niaYbmGxn1f0= + +Name: system/app/HtcPowerStripWidget.apk +SHA1-Digest: hGjQX9QGid+AZ78zfKtri9tAZqA= + +Name: system/usr/keylayout/Vendor_046d_Product_c532.kl +SHA1-Digest: uLc7pyyR3HK7SZbqxNhxTnBjvQU= + +Name: system/bin/climax +SHA1-Digest: M+KYGET+N+PWthN8exobPmK5StY= + +Name: system/lib/libc2d2_z180.so +SHA1-Digest: d7o/IDYyC0q+FpGrYqkNCiXeLzM= + +Name: system/media/audio/notifications/Magenta.mp3 +SHA1-Digest: WN6F04usQrI7mkff/OLOW8URHMs= + +Name: system/app/WorldClock.apk +SHA1-Digest: wy0fN+853RdFGRz9wxEJ1aR/vt4= + +Name: system/lib/libqmi_client_qmux.so +SHA1-Digest: Ft3VeuRXsfWmrqBVyCCl/xirwT0= + +Name: system/fonts/AndroidClock.ttf +SHA1-Digest: SwKcMGDzVbbA3ny3+tJbieABH4s= + +Name: system/lib/libchromatix_s5k3h2yx_hfr.so +SHA1-Digest: 6OLyZ8USV8Ka9y1FXYwA1sZdVao= + +Name: system/etc/security/cacerts/76579174.0 +SHA1-Digest: pzzaX91VWO/hKUAL6vLTr/M9//8= + +Name: system/etc/security/cacerts/48478734.0 +SHA1-Digest: DD+Jf/xyWUb9vB7awEI1t/6+AM0= + +Name: system/lib/libvorbisidec.so +SHA1-Digest: HpuJ4g4HT01NWdMVqzVxB/BG7o8= + +Name: system/app/HtcNotesProvider.apk +SHA1-Digest: uNo+ac+iwWnnguLi4x/CU1DTZzI= + +Name: system/customize/resource/allapplication_23407.xml +SHA1-Digest: WJtJykoC0urdDyYlaPffojNy6+w= + +Name: system/media/audio/ringtones/Cyan.mp3 +SHA1-Digest: jTlup3iRS7gYouSkQRgqkAUArKY= + +Name: system/bin/ionice +SHA1-Digest: 3CEFbc3lIVHpriR9iowFnWHIbqg= + +Name: system/media/weather/weather_l_windy_day.mp4 +SHA1-Digest: py1l/yQtfoP6yxIc/tloV1whcaw= + +Name: system/lib/soundfx/libdownmix.so +SHA1-Digest: V3bmPjOo3C1gl+jh6aAtRM2CewM= + +Name: system/etc/image_ibeats_v2.bin +SHA1-Digest: yrtDyORccn24flPqVUDEy+rsvYY= + +Name: system/etc/snd_soc_msm/snd_soc_msm_2x_Fusion3_DMIC +SHA1-Digest: jgdmdCfgWk5QKWHJblRSS9raHf0= + +Name: system/bin/pand +SHA1-Digest: HVUXS6xM4bfif1v0xYhQW9fyO50= + +Name: system/usr/keychars/Virtual.kcm +SHA1-Digest: 9uQOx02FYajtTIKVRSyjp4oMPWM= + +Name: system/lib/libbcc.so +SHA1-Digest: GDX6MwnQkH0z0LOmNI+d+NraXfc= + +Name: system/lib/libchromatix_ov8838_hdr.so +SHA1-Digest: 1jDyx7S1a+7DSbRjlHpSei7RJdI= + +Name: system/lib/hw/alsa.msm8960.so +SHA1-Digest: ATyiDD+FadGgmF4Vv+ZCUUllaW8= + +Name: system/customize/resource/allapplication_24008.xml +SHA1-Digest: dXKTNsL1lKpvIevUWul7dSkEVwg= + +Name: system/lib/libstdc++.so +SHA1-Digest: MRzKLx3PiQUa3JWLShNO/ktKHO0= + +Name: system/lib/libtcpfinaggr.so +SHA1-Digest: fDqEE9zfOvk2PGff2lLTnfZL0Fk= + +Name: system/lib/hw/camera.msm8960.so +SHA1-Digest: kWPMYJS6eRFndidzp9ibeEzbYwQ= + +Name: system/bin/aplay +SHA1-Digest: BYJh5AgvFptF0WaN42BM1uFmask= + +Name: system/lib/libcameraservice.so +SHA1-Digest: iMFOT/cAbYyIcoan7uvFgFQngTY= + +Name: additions/fonts/segoewp/Roboto-BoldItalic.ttf +SHA1-Digest: V4A/5csAB03WjIUXgAvi0hHrIX8= + +Name: system/media/audio/notifications/Azure.mp3 +SHA1-Digest: LtqOknf1tpoKi7Xa1eG6lfM5xJI= + +Name: META-INF/com/google/android/aroma/themes/sense/radio_sel.png +SHA1-Digest: seBUwREyFfHhc3t9FaUpWRc8v1M= + +Name: system/lib/libchromatix_ar0260_default_video.so +SHA1-Digest: Y2gtGxt6C8R2QWj2FtJr+Pi5EpU= + +Name: system/app/HtcSpeakNGF.apk +SHA1-Digest: hdlb3jzWb/V134gl6u8faP1HAXQ= + +Name: system/usr/share/zoneinfo/zoneinfo.dat +SHA1-Digest: 3bNLXP6MzuugMmpyUxw5kRipvbc= + +Name: system/media/audio/notifications/Vermillion.mp3 +SHA1-Digest: qCAiIzq5nY66wEKjE8pbVv5y8FI= + +Name: system/app/MyTask.apk +SHA1-Digest: IbgsXO31oGCEnV1cFg7NOMcr/G0= + +Name: META-INF/com/google/android/aroma/themes/sense/cb.png +SHA1-Digest: otH0B2KK+X+pBC/lOuajvnTDWwM= + +Name: system/framework/uiautomator.jar +SHA1-Digest: Sp1TQcUsfvSaDwUZU5VALZINlfA= + +Name: system/lib/libhardware.so +SHA1-Digest: 6+JECohsz82ljXyp2pcaOFfx0vw= + +Name: additions/fonts/helveticaneue/Roboto-Italic.ttf +SHA1-Digest: GHaEjf4U2l+YTb2u0BtcTx/G6a4= + +Name: system/lib/libpphwr.so +SHA1-Digest: s3W0b4A2yBXiVeXQcCh803s2HhU= + +Name: system/customize/resource/downanimation.zip +SHA1-Digest: iC4e8Xngli3tCBYzP20GwIFiMIE= + +Name: system/lib/libc.so +SHA1-Digest: 5/ugqLeBLFWR2G3vk4s//RjDcDU= + +Name: system/etc/security/cacerts/60f083f8.0 +SHA1-Digest: aj1D0xqgrp24x4HTQIeDYqwRDDI= + +Name: system/etc/permissions/com.htc.software.market.xml +SHA1-Digest: AaDdllNGEOMXv8mIV7BCFuJYTGA= + +Name: system/lib/libext2_profile.so +SHA1-Digest: cy63T6xVxSx/WV4qP2BznWzZaxk= + +Name: system/lib/libgui.so +SHA1-Digest: rf7ylid2migXIESNiOTbwLHJ7hQ= + +Name: system/bin/qseecomd +SHA1-Digest: C0cJn/J6WfISwCkBSqZy/zNNuV4= + +Name: system/media/zchgd/charging_08.rle +SHA1-Digest: gX0zh+1tUH+r3U17Zqjqtn3SgnM= + +Name: system/usr/idc/projector_input.idc +SHA1-Digest: PRYvjiPekMTt2IIrX0QRUkERcd0= + +Name: system/app/WeatherProvider.apk +SHA1-Digest: 92S7vGK/u5jGWsJyDgdJfF3LhFI= + +Name: system/bin/fusermount +SHA1-Digest: iCiRvrTRlDUM0mZmmSPpakL9IaI= + +Name: system/media/audio/notifications/Purple.mp3 +SHA1-Digest: jul63XvZnAFXJqnH36crUYmyVYk= + +Name: system/lib/libinput.so +SHA1-Digest: zNa5EYdFR00GSK70DLglDtUJmUk= + +Name: system/lib/libgoogle_recognizer_jni.so +SHA1-Digest: 7ri4BbwNSD99TrYEyU/7PrsKklE= + +Name: system/bin/dmesg +SHA1-Digest: gsZHB8KXidrgYtH/MQ/0YNhbeKw= + +Name: system/customize/resource/allapplication.xml +SHA1-Digest: 5MLlgce+wTFngYWMm5cfSE58vc8= + +Name: META-INF/com/google/android/aroma/icons/welcome.png +SHA1-Digest: fYixHffIAobmHhXPb9KlqbdyR40= + +Name: system/media/audio/notifications/Ruby.mp3 +SHA1-Digest: T5LEoKwV4e4XdYh0LdIUh5yib3w= + +Name: system/etc/security/cacerts/418595b9.0 +SHA1-Digest: EurtZmuo2p5AcFiyeJVA1GXOrHs= + +Name: system/app/HtcCupd.apk +SHA1-Digest: 7qhwHEVM8jVHkJBILBquXhM/8nI= + +Name: system/fonts/DroidKufi-Bold.ttf +SHA1-Digest: rGF1p7Z7NPJVWgYz8gl5g94DTj4= + +Name: system/app/HTC_CIR.apk +SHA1-Digest: bpmMVuRAf2Sfv/W9fM6oW6lDEF8= + +Name: system/etc/bluetooth/blacklist.conf +SHA1-Digest: /NVpapHNK5NICIClWd0zLSqpX2Y= + +Name: system/usr/srec/en-US/symbols +SHA1-Digest: X3eWxk+MQsrhAd6FOn03af84C5I= + +Name: system/media/GPU/CurveCold.bmp +SHA1-Digest: sOGl7dhD5vnH9hZn1Iu2kJCavOI= + +Name: system/etc/soundimage/srsfx_trumedia_voice.cfg +SHA1-Digest: RndG81JIozmd3D7uioPQ1PeU48g= + +Name: system/etc/firmware/vidc.mdt +SHA1-Digest: OGFwf5U2qAHXKLNEGCiRkvCCIIw= + +Name: system/lib/libmedia_jni.so +SHA1-Digest: tui0VO7QMqC/nlHOcyHynhmPscs= + +Name: system/bin/applypatch +SHA1-Digest: Rmm3Q5BMoWXdCjbzKx8AXjI98rw= + +Name: system/app/IMEXT9BahasaMalaysia.apk +SHA1-Digest: bBud4bit6ebA3w+gNYQHTNgHv6s= + +Name: system/etc/mkshrc +SHA1-Digest: AXWBhFfy48EBsMirawoVQJ6RzHI= + +Name: system/lib/libpower.so +SHA1-Digest: 1Z0pFdkihuPI4sCZ+IEIZJuilZI= + +Name: system/etc/security/cacerts/d8274e24.0 +SHA1-Digest: ggueFUwteH2USaNRFI+bu48RY2w= + +Name: system/lib/libimu.so +SHA1-Digest: UXOupjyuBnXgO0YNUdQWQ/Q8/1k= + +Name: system/etc/permissions/com.google.android.maps.xml +SHA1-Digest: QaPNB5FUfwkZ5T3fG1bXJpF8pNY= + +Name: system/app/HtcWeatherClockWidget.apk +SHA1-Digest: RQcrUieRNrK31JbElWsYLwEOxEI= + +Name: system/lib/libsonivox.so +SHA1-Digest: vR1wuMiAvyK7BfiuMjTQC15hwV4= + +Name: system/lib/libstagefright.so +SHA1-Digest: fYSus60fQ+jDy9cHZlPsDoeXths= + +Name: system/etc/permissions/android.hardware.sensor.gyroscope.xml +SHA1-Digest: DhtVHxHAeMpMhNawakMGfQRTkR0= + +Name: system/app/IMEXT9Dutch.apk +SHA1-Digest: 5y4cahExfFBYX/NWbxbNT9kyhA4= + +Name: system/usr/srec/en-US/dict +SHA1-Digest: AXBx0Bz53vO1Keed7lCO425AmBc= + +Name: system/customize/resource/quicklaunch_21406.xml +SHA1-Digest: AWjqtVcxi/ZNuY8yZJGc1vx6dtc= + +Name: system/media/audio/alarms/Citrine.mp3 +SHA1-Digest: 8jtsUdGmvNKkldvykvSN/Bk61gI= + +Name: system/media/audio/notifications/Smoke.mp3 +SHA1-Digest: Ot8pg8/oUoLUr+TS9UfYyTEOLgs= + +Name: system/etc/security/cacerts/d777342d.0 +SHA1-Digest: KqcaEKbpbxK/ZskNhdSlNwqFbY4= + +Name: system/media/audio/ringtones/Orange.mp3 +SHA1-Digest: /Y+mbPEthQ3IE17N0oU/mcHIrYE= + +Name: system/lib/libchromatix_s5k6a1gx_zsl.so +SHA1-Digest: 8iNeuMu9oxBFxXYmBXDrcTFihDY= + +Name: system/bin/venc-widi +SHA1-Digest: uTYNS02YLDr9njD97va6rihcWT0= + +Name: system/media/weather/weather_l_sunny.mp4 +SHA1-Digest: pmi42pNKvDy+mDpFZfhUIuHNEog= + +Name: system/etc/security/cacerts/84cba82f.0 +SHA1-Digest: RbfVG4qh9BQlLNlkl+9eQ/iwr90= + +Name: system/lib/libchromatix_ar0260_preview.so +SHA1-Digest: T1Qi4QJHsjgavJNKTVP/XWmcTnc= + +Name: system/lib/libwfdcommonutils.so +SHA1-Digest: vwl5C20x61qpS14Lh6Rkb1y4MT8= + +Name: system/etc/security/cacerts/399e7759.0 +SHA1-Digest: C7nniIwXMNqhQza0pF0/S/7ALuk= + +Name: system/framework/am.jar +SHA1-Digest: byLKmUjp4MtYwoAR2h6mAPI8OJ8= + +Name: system/media/audio/notifications/Rose.mp3 +SHA1-Digest: z3QuX0C2fxcjT25K8X1GKv8RkGg= + +Name: system/lib/libmedia_native.so +SHA1-Digest: jx/9VAk+0ec9OQjl4AFvAr6Cdtw= + +Name: system/app/KeyChain.apk +SHA1-Digest: 3vA6JhjDV6r9I7mhrIpjj2zHD7c= + +Name: system/etc/security/cacerts/c33a80d4.0 +SHA1-Digest: j+oS/ELhscXEs8jsZgH1YZdo0Yk= + +Name: system/lib/librs_jni.so +SHA1-Digest: yCROPfwCRQhLlVbWpXquW4g+Mrw= + +Name: system/media/audio/ringtones/Blue.mp3 +SHA1-Digest: Ba1ddb3TO+29FawDxv5NpCSvqEM= + +Name: system/media/audio/notifications/Cobalt.mp3 +SHA1-Digest: v0oCG6zJcTTYmjrddpJzJlTQGdo= + +Name: system/etc/security/cacerts/bc3f2570.0 +SHA1-Digest: Djn1z26jqNrHK/cY3pNLU/I9bN8= + +Name: system/bin/mm-qcamera-app +SHA1-Digest: Gj0TXVvCGzCDhzvk0FooEopa7bQ= + +Name: system/bin/asound +SHA1-Digest: zOADLfJdjHHyBtVTSKf+vAheGxc= + +Name: system/lib/libwt6docxrdr.so +SHA1-Digest: WcgoibecQbe8Luu5d+4xamDqBE4= + +Name: system/lib/libdsutils.so +SHA1-Digest: MPpPbpY6S4WtL8zUlz9iOa+dIYI= + +Name: system/lib/libgetzip.so +SHA1-Digest: g9lq/P9WQh0gDlTdNpuLRy0T6vQ= + +Name: system/app/IMEXT9Lithuanian.apk +SHA1-Digest: POole4XX0AfwFzvmarPql0s2Aw4= + +Name: system/lib/libmode10.so +SHA1-Digest: Pn2nLBJpq+o2Qf6TEYRGrZYJBhU= + +Name: system/media/weather/weather_l_fog_day.mp4 +SHA1-Digest: yOAPNP78Vlio7k7Ib/PybPuIZqU= + +Name: system/lib/libsuspend.so +SHA1-Digest: JEobXXx2+4iLklfHPGt82EnSOs0= + +Name: system/lib/libzeroeditorplayer.so +SHA1-Digest: 9lDAbFLanipmj0Mu/mwVPhRyucQ= + +Name: system/bin/run-as +SHA1-Digest: vv0XB9PuCuGrYGXPDZzrSTR0XcY= + +Name: system/app/NewsPlugin.apk +SHA1-Digest: N4kXYQ2wOOnYXGMivnQuWww78qA= + +Name: system/etc/security/cacerts/73da149b.0 +SHA1-Digest: 7cmlEdkiJbcZT7yljZ32CLuOb+w= + +Name: system/customize/resource/rp_pct.png +SHA1-Digest: Be1I75CUYHlN5Ls2n607uIxRVig= + +Name: system/customize/resource/rp_ce_0678_i.png +SHA1-Digest: XipoQXhxul8pBJuXY9trmd6VPV0= + +Name: system/usr/srec/config/en.us/models/generic8_m.swimdl +SHA1-Digest: XJZq9k/wtjPuUrP1MbJNulTtfGM= + +Name: system/framework/svc.jar +SHA1-Digest: YrodjHp0I5+Fifs6LgPSwZZ8Ng0= + +Name: system/fonts/DroidSerif-Italic.ttf +SHA1-Digest: aCx+e4yyj8kOYcR5otukddlLoMo= + +Name: system/framework/HTCDev.jar +SHA1-Digest: j1L3wgS1mh6iHbKNu3EP36rouD8= + +Name: system/etc/calibration_EMEA +SHA1-Digest: uRTWUBer/lqKeJ2gFIzBtOrNdmk= + +Name: system/etc/bluetooth/a2dp_avrcp.conf +SHA1-Digest: NlkTOsv3ZiP4svSRZAIvwRpWqw8= + +Name: system/customize/resource/rp_ce_0682.png +SHA1-Digest: uIRmYCqvz2wPoE28lQegeDXvcP8= + +Name: system/lib/libbluetooth.so +SHA1-Digest: mai1lv4Zn46PnVLqidoAu/uw2E8= + +Name: additions/fonts/sonysketchef/Roboto-Regular.ttf +SHA1-Digest: lDROUZu6Oz9zcaSfVrBtY95SpJY= + +Name: system/etc/snd_soc_msm/snd_soc_msm +SHA1-Digest: bBeGPT2by8zbsjZI+It3dAOCpas= + +Name: system/customize/resource/quicklaunch_27205.xml +SHA1-Digest: VBKE0GatLtLCs1qmDsYCJdJnWwE= + +Name: system/etc/security/cacerts/d59297b8.0 +SHA1-Digest: TqrmlyeuzKiljmAPGWKtMKLCpAA= + +Name: system/lib/libqmi_csi.so +SHA1-Digest: bwq87eoeJxBEkLccueg99mXRkqM= + +Name: system/etc/permissions/android.hardware.wifi.direct.xml +SHA1-Digest: iPmbEsXxaKyWbEdVZcAxkacBUr0= + +Name: system/media/audio/ringtones/Khaki.mp3 +SHA1-Digest: irpirz//OwRY39BxoC444KAs4SQ= + +Name: system/app/HTC_IME.apk +SHA1-Digest: yRnGh/ab3PMpQm6R2aUZ5/k1Mc8= + +Name: META-INF/com/google/android/aroma/icons/agreement.png +SHA1-Digest: ibAcfqhbZ3H32/KMQIip/od/qkA= + +Name: system/etc/security/cacerts/0e82f83a.0 +SHA1-Digest: xEq3keiHRd9SnhRy+UqNOh/kDrs= + +Name: system/customize/resource/allapplication_26803.xml +SHA1-Digest: 4p4vJdqyBDLtVB8AXL+U0+mgHw4= + +Name: system/customize/resource/quicklaunch_65507.xml +SHA1-Digest: +bkSDL4ocUaADLb4Y74kNP3xafk= + +Name: system/app/SettingsProvider.apk +SHA1-Digest: Ldf/gSc1L0e8QIlUGUoTQWxpx1U= + +Name: system/bin/wipe +SHA1-Digest: Mz+bmG1S9V6Hgz8Pq5XzXwZh7hA= + +Name: system/etc/tfa/fm_l.eq +SHA1-Digest: JHHxqTumKfmNAWK7jGQNakAWYK8= + +Name: system/media/audio/alarms/Cinnabar.mp3 +SHA1-Digest: h4qo4N2u1M2jSktZfSr3rku2aXQ= + +Name: system/lib/libdmt_sse.so +SHA1-Digest: jmoMFkLJX9bKZarT2DIVh0XEdTg= + +Name: system/etc/security/cacerts/d537fba6.0 +SHA1-Digest: 4R+LXj2wGe4iRwjgn1A1cvhf/n8= + +Name: system/app/HtcImageWallpaper.apk +SHA1-Digest: UDJFr5Wz/efm0oL83cxZnDOA+CE= + +Name: system/usr/share/partials/partials_H_rr.csv +SHA1-Digest: SdVrP6Qyuj5Dy8HsjZiLNVbebsA= + +Name: system/lib/libmpl_jni.so +SHA1-Digest: j8OjRonuiSFuGBu7F387ZaHqooA= + +Name: system/lib/libnativehelper.so +SHA1-Digest: hT8AQKpX6iiypkm+vpad+bkeGTg= + +Name: system/customize/resource/allapplication_21401.xml +SHA1-Digest: YNkcLskRkz8fXkJ7AhCvFVlB5lE= + +Name: system/bin/netcfg +SHA1-Digest: QgnxLUFalIH7f6liBF7mX0S9piE= + +Name: system/bin/hcheck +SHA1-Digest: sUF0yNcHBoACcQOXnbHvusvHTdM= + +Name: system/etc/security/cacerts/0d188d89.0 +SHA1-Digest: FzoOvFUf3dNV/AEJ20wcfK1JUGk= + +Name: system/app/IMEXT9Spanish.apk +SHA1-Digest: PGkzNTDFl+iww658ib3ik8aRdzA= + +Name: system/etc/firmware/vidc_1080p.fw +SHA1-Digest: Z6gbTAYS4ObPGq6kO0CXW8AWNPM= + +Name: system/lib/libwt6xlsxrdr.so +SHA1-Digest: jsrRzt7/6lWMOotgA3BGO+ZW+O8= + +Name: system/etc/init.d/98permissions +SHA1-Digest: w2PPeuPCimdnbmp45rvkfvox2L8= + +Name: system/app/Picasa_GLRplugin.apk +SHA1-Digest: ICWBGz+hPhklXB+JEyAgOLXRtyc= + +Name: system/usr/idc/qwerty2.idc +SHA1-Digest: CxeFAjbR656/zttheEGexLMYZio= + +Name: system/bin/efsks +SHA1-Digest: gOktRfLkIJlrVKqwmseQ90MkpJY= + +Name: system/etc/res_ctrl.conf +SHA1-Digest: YgH4bLCC4AyfYf8e6z7u4dse85U= + +Name: system/bin/tune2fs +SHA1-Digest: NVUF8wExJBsGi7oaTsCuiumbJRY= + +Name: system/etc/libdvhwrc.so +SHA1-Digest: /tfgt+zY6FvGBl/HqCTnm+F4+FI= + +Name: system/lib/libaddrsdetection.so +SHA1-Digest: 9nn+AmEARA9Eu8vEZX/J7SXYJh8= + +Name: system/media/audio/ringtones/Coral.mp3 +SHA1-Digest: LIo7TXUlYvYoT+nwasC2AnuCT+0= + +Name: system/etc/tfa/voip_l.eq +SHA1-Digest: M7bmyz3Ii2FYKS1hAaiNtS6n/bs= + +Name: system/lib/libchromatix_s5k6a2ya_hfr.so +SHA1-Digest: Qi4mbSlFGxKnLE1rDIoYaM7M0y8= + +Name: system/lib/libwsp.so +SHA1-Digest: nGPk65m0G4LxjDZLVTGuGSyDUQc= + +Name: system/fonts/RobotoCondensed-Italic.ttf +SHA1-Digest: HjOk01XwQ2PScIy0Q1HS5ekk5+E= + +Name: system/bin/renice +SHA1-Digest: bg47hJEc+ukaAoM4k+cF5DH5ALw= + +Name: system/app/idlescreen_shortcut.apk +SHA1-Digest: 0lRa3WO6SjIMeS6EfU9lUHdbpmY= + +Name: system/lib/soundfx/libsrsfx.so +SHA1-Digest: XLqFNtEFIQKGKWIN2iwz313MZRI= + +Name: system/usr/srec/en-US/normalizer +SHA1-Digest: 4iCTB9icELI1BJdqCXr2ZLXF120= + +Name: system/app/IMEXT9Hungarian.apk +SHA1-Digest: yBiR0qpWEhXzeMz0EABf3q0HH6U= + +Name: system/app/SystemUI.apk +SHA1-Digest: mfZJIjPzt7T7pT3K+vLBZxANuIQ= + +Name: META-INF/com/google/android/aroma/themes/sense/theme.prop +SHA1-Digest: uzGkY17JqmPF0PoHloc5zTYL0QE= + +Name: system/media/audio/notifications/Licorice.mp3 +SHA1-Digest: r4wi6TAIdsjIK2FCsd+99gujT6s= + +Name: system/customize/resource/allapplication_20404.xml +SHA1-Digest: IyQuoTej816CiJ0liXtRhn+j7V0= + +Name: system/lib/libchromatix_imx135_hfr.so +SHA1-Digest: 8CtXXsOn/M82JZXnmze8PYG4umM= + +Name: additions/fonts/veggieburger/Roboto-Italic.ttf +SHA1-Digest: 95gI0tiQ4JO/vec8ZA3GT+z7rmQ= + +Name: system/media/audio/ringtones/Sapphire.mp3 +SHA1-Digest: lJDiFVTinX0KYFEgVXw0l8vf0+c= + +Name: system/bin/cat +SHA1-Digest: KUyhy0ZoKz1cXTDbUegpNJLva7g= + +Name: system/framework/content.jar +SHA1-Digest: Bso+OnPUeV1AyeJJEtjD2asbm9Y= + +Name: system/etc/priorityd.sh +SHA1-Digest: 17dY6yKME3SLQaOsOwaEtVfLYQQ= + +Name: system/framework/com.google.android.media.effects.jar +SHA1-Digest: PD7Al1WUenLQfEEGairnxJHGACE= + +Name: system/customize/resource/quicklaunch_22201.xml +SHA1-Digest: ZJL7LaozR6FK6YpLu+7VmR3glvo= + +Name: META-INF/com/google/android/aroma/themes/sense/select_push.9.png +SHA1-Digest: 5S4mWeE8z3nPBdjxWfl0viqHtJI= + +Name: system/lib/libacc.so +SHA1-Digest: 7VLlxLV3zqDXV5lRW2F7Z3O88Eg= + +Name: system/lib/libmorpho_image_stitcher3.so +SHA1-Digest: RmpA5hxwOyGEMNM6h4CFt8knHSA= + +Name: system/framework/framework.jar +SHA1-Digest: wSwXw+JFG6qDx2WvmlSyELwa0OQ= + +Name: system/etc/security/FotaSign_PubKey.der +SHA1-Digest: N/aZKtIVna/mcnhl99ssySqMBFE= + +Name: system/bin/mount +SHA1-Digest: fKvsg1cW9ujWQMdkW0Q22qRJSzY= + +Name: system/lib/libaricentomxplugin.so +SHA1-Digest: xhXHHfYJHW9g2dsUQ/EKQw7mS8M= + +Name: system/media/audio/ringtones/Neon.mp3 +SHA1-Digest: VepX2fFmM/l3JxoOtzsFGqHhbQg= + +Name: system/etc/security/cacerts/1dbdda5b.0 +SHA1-Digest: Z8P5gTMftWn5WsxGoaWi5Ewsbjc= + +Name: system/lib/libexif_jni.so +SHA1-Digest: IROWgTVDHzja2IkF/V4Q9osCdxo= + +Name: system/customize/resource/wallpapers_c_02.jpg +SHA1-Digest: zOXPka/BgqekYZ0MX2Sa/KHCmsI= + +Name: system/etc/firmware/a225_pfp.fw +SHA1-Digest: JXnk+hLjb41rBPpvRTxNe6dba2Q= + +Name: system/app/IdleScreen_Music.apk +SHA1-Digest: PMGAk0lRV2hm4JjL6N+FsmyGrsQ= + +Name: system/lib/libqdi.so +SHA1-Digest: bxzEhxTMmtZj9MV9bmT/N4+l140= + +Name: system/bin/sync +SHA1-Digest: jVmFV1ds4PqXMCix5z3OId8dJpY= + +Name: system/etc/gps.conf +SHA1-Digest: RHhyPtQaWA3yAooxUs1CdQZe/6c= + +Name: system/customize/resource/allapplication_21419.xml +SHA1-Digest: 2of0589sAC1LJ5V3toTuB301Ksk= + +Name: system/bin/dalvikvm +SHA1-Digest: 6M2CFaMsKqhuLaCcVd/AJxxcQcI= + +Name: system/app/HtcRingtoneTrimmer.apk +SHA1-Digest: b4HD+gW4D9aAGQmiDKqPBQ1taTM= + +Name: system/etc/security/cacerts/75680d2e.0 +SHA1-Digest: zmqh8h2o8Hm6tDQfcCh8iNtUuUc= + +Name: system/lib/libxml.so +SHA1-Digest: HQv7lVu8DuelrRb84vNnioEj0EI= + +Name: system/lib/libdivxdrmdecrypt.so +SHA1-Digest: GHc4stKNP7L0nhxr4wdmMwcmiwQ= + +Name: system/lib/libvideoeditor_videofilters.so +SHA1-Digest: GZHqM7U5znS9v5TpC1UWwKikTCw= + +Name: system/media/weather/weather_rain_night.mp4 +SHA1-Digest: bqegZe3VgA1xXQRZtBSbaWCpLmM= + +Name: system/customize/resource/quicklaunch_20210.xml +SHA1-Digest: tVje1ibdXVTB6aTS4zKEIb0joaA= + +Name: system/lib/libsnfc.so +SHA1-Digest: CC9aUhMiwuQyPsQ8yAsUJAf7Dv0= + +Name: system/lib/libmemalloc.so +SHA1-Digest: mn2ZEle3ujP7WH6J8tcVZiYbZXA= + +Name: system/media/audio/notifications/Slate.mp3 +SHA1-Digest: u8uvKRqmxN/UDFzj35oqdPvbcAI= + +Name: system/app/InputDevices.apk +SHA1-Digest: NEOxB65++3xfKWgZ8ngLoSMwn5U= + +Name: system/app/HtcSyncWidget.apk +SHA1-Digest: 7bNxWqaGgG/6Ig+YwXlPpNtk8XI= + +Name: system/fonts/DroidSerif-Bold.ttf +SHA1-Digest: MlOUKslixMSZJEtMW5rgRjkfMq4= + +Name: additions/openvpn/xbin/openvpn +SHA1-Digest: rCpMAOJ1M64vjMl+LyCTHlv1KfY= + +Name: system/usr/keylayout/keypad_8960.kl +SHA1-Digest: ddkS1H1fJkiTLkCpbwTO7LC3EdA= + +Name: system/bin/mm-jps-enc-test +SHA1-Digest: DsBNQhUTyacmHKd41cteMDdN0iM= + +Name: system/framework/bmgr.jar +SHA1-Digest: Bdlc18itOeXFgVUJeGoaFmygzSw= + +Name: system/lib/libchromatix_imx175_hfr.so +SHA1-Digest: 4RkjsVnPLFVG/+9TwdgruNcJI/k= + +Name: system/customize/resource/quicklaunch_23407.xml +SHA1-Digest: 7kH4nPdwTWCnWKlCFKXF3idZkfs= + +Name: system/etc/security/cacerts/7672ac4b.0 +SHA1-Digest: ZvDdi25zaHa3+F+HBUDiaEjzgrA= + +Name: system/etc/security/cacerts/00673b5b.0 +SHA1-Digest: bC6baGqpg7WySAQXIdpwsoA9xLA= + +Name: system/etc/tfa/ring.eq +SHA1-Digest: 4luSW/fn+3qnGJ9ELxyvDqQ/AX8= + +Name: system/lib/libexif.so +SHA1-Digest: MEQwRnyJgtjyko3cIU3WTlzAnP0= + +Name: system/bin/umount +SHA1-Digest: PJo4zqzS5BfU6A3O+bq3dBjayJk= + +Name: system/lib/libwfdhdcpcp.so +SHA1-Digest: InL+k8uz3h7KEATn0Jx+oNeF7ow= + +Name: system/etc/security/cacerts/6e8bf996.0 +SHA1-Digest: VlozgKv+QbW1H/99/nImmPiyEOI= + +Name: system/lib/egl/libGLESv1_CM_adreno200.so +SHA1-Digest: gwprO3sKhU7nrPUHCoeT/+pZigA= + +Name: system/etc/tfa/video_l.eq +SHA1-Digest: 39AAkesJZDW1hCnZ6qFfGBa+B3E= + +Name: system/lib/libsoundpool.so +SHA1-Digest: l5Tdhg5V53Gd193liRb/CNH36LI= + +Name: system/media/audio/ui/Volume-4.flac +SHA1-Digest: UwmGIIUqyxsXRyWXu0cngmm0958= + +Name: additions/fonts/roboto/Roboto-BoldItalic.ttf +SHA1-Digest: BLLUGzekHTI7qddxiB3d8Y0juxE= + +Name: system/etc/security/cacerts/5021a0a2.0 +SHA1-Digest: OsZKswcn/xRvpTKd7JaZpcHdR+o= + +Name: system/bin/netmgrd +SHA1-Digest: M6NHUjMQjlR2KRaH6Yje5+W+Ty8= + +Name: system/etc/fallback_fonts.xml +SHA1-Digest: T+aQo4vmIpSseZd0vz0O/WM52VY= + +Name: system/app/GoogleTTS.apk +SHA1-Digest: AflpmS9CoJhaMzOdpHgK1pGTlJQ= + +Name: system/lib/libtilerenderer.so +SHA1-Digest: aNLD1NMDL+56S8JpngtdZ5oZfEw= + +Name: system/app/FDHttpd.apk +SHA1-Digest: kVJQ5poEcWVtXg2OLx2EBidEPM0= + +Name: system/lib/qnet-plugin.so +SHA1-Digest: dpAXlO7iYxN56kb/orXnzqly+G8= + +Name: META-INF/com/google/android/aroma/icons/license.png +SHA1-Digest: p42J8rgNtbZL30syGVJdpF13Y9s= + +Name: system/etc/security/cacerts/9fae0770.0 +SHA1-Digest: GAPh+uzlba5nB+JrHSVpIU7wbyQ= + +Name: system/bin/make_ext4fs +SHA1-Digest: 4y7Ar7Ogb1z483nzMHk+U0ChmVM= + +Name: system/vendor/pittpatt/models/detection/multi_pose_face_landmark + _detectors.7/right_eye-y0-yi45-p0-pi45-r0-ri20.lg_32-2/full_model.bin +SHA1-Digest: Pvsuib7v1Y1CLewHRtiIm/N9W54= + +Name: system/bin/rmdir +SHA1-Digest: CtBkDwE3MSJ4Wgd1yuuaq/N6JH4= + +Name: system/customize/resource/allapplication_21416.xml +SHA1-Digest: plYc1a/i+cY7NstoAmT2htpgXIs= + +Name: system/app/HtcSpeak_HFM.apk +SHA1-Digest: eXydZhugZZJ4VjG1FFf9mULC6RA= + +Name: system/etc/security/cacerts/bda4cc84.0 +SHA1-Digest: /ZztxwPHRyN202+l2rSGg6udDJE= + +Name: system/usr/srec/en-US/dictation.config +SHA1-Digest: dAG0jruo14Cvr/u888Yg9c8UGMo= + +Name: system/lib/libharfbuzz.so +SHA1-Digest: xAKdmpe2G1VE+m64KjY6WBq7Zbw= + +Name: system/tts/lang_pico/fr-FR_ta.bin +SHA1-Digest: xsa/hqJTXz8Rc7l3UTQXz1ikriw= + +Name: META-INF/com/google/android/aroma/themes/sense/cb_sel.png +SHA1-Digest: FH8/F/Sm+KTbT80qWTj5dksties= + +Name: data/app/com.google.android.apps.translate-1.apk +SHA1-Digest: FUaRH0BaaKsy0htFVWVOEG8CrtY= + +Name: system/etc/tfa/ring_l.eq +SHA1-Digest: b0PCFbsirfmVnMKjATkmIGb3s0o= + +Name: system/customize/resource/ConfigP.bin +SHA1-Digest: tyfXGVlq3TP6dUKiUenkfsL3yHI= + +Name: system/customize/resource/quicklaunch_24001.xml +SHA1-Digest: mldsHEAyR5CU90F02FX62Sms3TQ= + +Name: system/etc/security/cacerts/6adf0799.0 +SHA1-Digest: yOpUlfl7ZFCprMcTVr1bX0nCx28= + +Name: system/bin/mpdecision +SHA1-Digest: pXJ8xS/Nch0re1FdR5pd3P5cbsE= + +Name: system/framework/bouncycastle.jar +SHA1-Digest: s3oKrD3ywnHrCUBRlZDbQ/xQ5oc= + +Name: system/lib/libctest.so +SHA1-Digest: i5yNDyqNnOIGUEgEDmguoFzcLtU= + +Name: system/lib/libwebrtc_audio_preprocessing.so +SHA1-Digest: Aa33rMJv8VYRgUdQf3UDfHnqiTE= + +Name: system/customize/resource/quicklaunch_24008.xml +SHA1-Digest: i7xR6xqRyXfLVbUgT+YtlyTl0DY= + +Name: system/app/GoogleContactsSyncAdapter.apk +SHA1-Digest: 0wX05Cuyht3zhwAwBvGe28IMwGM= + +Name: system/usr/srec/config/en.us/models/generic11_f.swimdl +SHA1-Digest: 5eK+Uqn7V9+/aGXZDDzZ5MstkII= + +Name: system/etc/security/cacerts/4fbd6bfa.0 +SHA1-Digest: S6TGnIWLIWVHbHri7sRkvgXJHPo= + +Name: system/lib/libhtccamera_yushaniiproc.so +SHA1-Digest: vAED5EE+GLdECI3wEpr6kVSqowo= + +Name: META-INF/com/google/android/updater-script +SHA1-Digest: +S+ufnwCLW/gW0K9/3HYkNg/fZE= + +Name: system/etc/sound_mfg.txt +SHA1-Digest: AN7WINwvsjlVvjf+SPKTX6w0MXs= + +Name: system/lib/libchromatix_imx175_hdr.so +SHA1-Digest: Yj0wkZZeFebIqU1PkkbOeHXAJs4= + +Name: system/customize/resource/allapplication_20201.xml +SHA1-Digest: YDbdj4SQyRljcF5pspNE3yXddVU= + +Name: system/lib/libsnfc_ndef.so +SHA1-Digest: jKOUv7tU4dinM+XJtI9OyFfMEaU= + +Name: system/etc/tfa/playback.config +SHA1-Digest: P5zxhyDI7JZdLvRnRz4J2uoCyl8= + +Name: system/fonts/DroidSans.ttf +SHA1-Digest: AuiJIJMNRa/jDLEZK4Jns75Z2u4= + +Name: system/customize/resource/allapplication_28010.xml +SHA1-Digest: 0Kh8mMJcaEXDIqd8nntcuTDjYDU= + +Name: additions/gps/australia/etc/gps.conf +SHA1-Digest: kULxyLDy8GH4Gv/6bF7PBSY0YPY= + +Name: system/lib/libjUPnPCP.so +SHA1-Digest: Yu+U/yPgUSFjX8HeRoEfwEBu+EQ= + +Name: system/etc/image_beats_speaker.bin +SHA1-Digest: eMeu7tLJ4kKJt7erNC95CGLsVXs= + +Name: system/etc/security/KeyServer_PubKey.der +SHA1-Digest: lDlSctHdJLEuf53ZM2YZaXCKfkg= + +Name: system/lib/libmmcamera_aec.so +SHA1-Digest: whW7N4LJG2C8kNI9x6+yzTT8cZE= + +Name: system/lib/libchromatix_s5k3h2yx_hdr.so +SHA1-Digest: ZjVqacHeCdFtHwmSuy4kOu/3wTQ= + +Name: system/etc/security/cacerts/fde84897.0 +SHA1-Digest: 1Q5mh0RLzUt7mJgES/HlLi2LFqE= + +Name: system/etc/firmware/leia_pm4_470.fw +SHA1-Digest: BFO3gNEnY1H82fEQBZ1FOXmSBYQ= + +Name: system/customize/resource/quicklaunch_23801.xml +SHA1-Digest: cqxyXV8MvuyN0hV/7f78SiKt1Rk= + +Name: system/media/zchgd/charging_00.rle +SHA1-Digest: d8bbQ4r9gOqYEJwhsceUOPG8ZXI= + +Name: system/framework/bu.jar +SHA1-Digest: BTF3lS1JL/z1s7e06Fo11RE+j5M= + +Name: system/app/HTCAlbum.apk +SHA1-Digest: 5Cn+DE641P2qXaTf6Lm8naurIjk= + +Name: system/app/Calendar.apk +SHA1-Digest: zOxveMD+euIOwVXlWuMO1FkPEmg= + +Name: system/bin/fsck_msdos +SHA1-Digest: lPU/oX5W6C5uGs5TMnsALC5xzhs= + +Name: system/etc/firmware/BCM4335A0_001.001.038.0015.0020.hcd +SHA1-Digest: 8TRbLQgUTbM3/8ofAc+t40SEoB0= + +Name: system/app/HtcFMRadioWidget.apk +SHA1-Digest: x6JAVoZsvEfiVvSSddI5FN1sBYo= + +Name: system/app/HtcContacts.apk +SHA1-Digest: wa6h/Q3KebwI6SVBUAkBw9FB39s= + +Name: system/bin/drmserver +SHA1-Digest: biOAgsaThR4eNo34iE/WH9tGMoQ= + +Name: system/lib/liboverlay.so +SHA1-Digest: lpHazt3lNorVWy1r9mMh3PtgN7w= + +Name: system/etc/permissions/com.htc.fusion.fx.xml +SHA1-Digest: MT0zMcwC2cm9yU+MpnSbZgI3zag= + +Name: system/etc/security/cacerts/052e396b.0 +SHA1-Digest: DZ81ptcnRpSHtb9evRwrx5aFhFg= + +Name: system/customize/resource/rp_ac_with_nfc.png +SHA1-Digest: /xZnw8GFpomK5WRrcBaS4qcqFfU= + +Name: system/lib/modules/moc_crypto.ko.sig.3.4.10 +SHA1-Digest: TKfYEscEI9/CJEY2yi+tRuQnJNY= + +Name: system/bin/e2fsck +SHA1-Digest: QHpJtJPLjLSdUsBh8v4IOkN99WE= + +Name: system/customize/resource/wallpapers_a_05.jpg +SHA1-Digest: wYOYxPXBRtvATVdfYdyLHVDMtls= + +Name: system/media/audio/ringtones/QuietlyBrilliant.mp3 +SHA1-Digest: +0cjCoXJdOdFaap3B9zPkP0jc+Y= + +Name: system/lib/libvideochat_jni.so +SHA1-Digest: AGchaBSlU7cDNw7bPMCKj7ytmUA= + +Name: system/usr/keychars/qwerty2.kcm +SHA1-Digest: daI1+jRsBLH0AaORU4xCM1Bp4/M= + +Name: system/framework/apache-xml.jar +SHA1-Digest: yp7qBABAWpRkC9MQafc+MUVdZTU= + +Name: system/media/GPU/CurveCross.bmp +SHA1-Digest: MX2+KHC75avjfNxEsu4W/Yykpd0= + +Name: system/lib/libGLESv2.so +SHA1-Digest: HawW980PAsROnP4Ur75q0bXOxFg= + +Name: system/usr/srec/en-US/lintrans_model +SHA1-Digest: kpgCxKz87KHw265e+HcUMuVMhlQ= + +Name: system/media/audio/notifications/Jasper.mp3 +SHA1-Digest: n1jpnkw4MA+Qc6VYiaAKNiVAcb4= + +Name: additions/fonts/klavika/Roboto-BoldItalic.ttf +SHA1-Digest: TX5YPBSL/cZfEmoGflOO9Tjv6AU= + +Name: system/build.prop +SHA1-Digest: kn2BGI5dEK9w/25tVZiMKqDjCP4= + +Name: system/lib/modules/moc_platform_mod.ko +SHA1-Digest: 44WtQK1NWpYnFvtZP+xWmzZ3eKg= + +Name: system/app/TelephonyProvider.apk +SHA1-Digest: QUduWYjugD+Kw/PJGQ6+1Wb/XqA= + +Name: system/bin/qmuxd +SHA1-Digest: FItwYHuH9P8pvqY7GWJZM1Prv1Y= + +Name: system/lib/egl/libEGL_adreno200.so +SHA1-Digest: jUuNJH/HsXhv/8E5M4ghsyghLwQ= + +Name: system/bin/debuggerd +SHA1-Digest: QYqUUNNOYd+X9zdmujvszKZZRWc= + +Name: system/lib/libpng.so +SHA1-Digest: EV2ljSKqDjAerLnFxwsgq2hcxw0= + +Name: META-INF/com/google/android/aroma/themes/sense/radio_on.png +SHA1-Digest: /mnI1Z1pwbSalzzsCUDJClEpneM= + +Name: system/lib/libcorkscrew.so +SHA1-Digest: rD/hGF3WIGW0FciF3Ac8LG25bQk= + +Name: system/customize/AAInfo.txt +SHA1-Digest: RV6F1rEu6yXkMmMKnaHVeZ3GvQc= + +Name: system/media/audio/ui/Volume-7.flac +SHA1-Digest: c79ptpPXIA8z5D5mMMHVRpFYyjg= + +Name: system/app/FMRadioService.apk +SHA1-Digest: 7nSK9gbcLhcbabY8Lm6q34fZe/U= + +Name: system/etc/security/cacerts/524d9b43.0 +SHA1-Digest: k2297HCYvN3BAhcl4kjnmOImy4g= + +Name: system/etc/security/cacerts/1eb37bdf.0 +SHA1-Digest: iEZtf6Bn7/kWs6HdB0tR9qNkl1I= + +Name: system/bin/logwrapper +SHA1-Digest: ef6A3igwr39uKD2uToHHxFP2MLY= + +Name: system/media/GPU/dot_mask_128x128.bmp +SHA1-Digest: RCj4FOMQHtkNTPmiMIeHvQXMT5k= + +Name: data/app/com.koushikdutta.superuser-1.apk +SHA1-Digest: K3UCnEsr2PWr1OmTIGIeRYhWTQI= + +Name: system/etc/snd_soc_msm/snd_soc_msm_Sitar +SHA1-Digest: vjgnZ+/DF0C+V/tn13tRkvx8/zQ= + +Name: system/lib/libRS.so +SHA1-Digest: aKxszPbesoHFdLRMcG1OD7m+/yo= + +Name: system/customize/resource/wallpapers_c_01.jpg +SHA1-Digest: ugxIiFpJKMaagm/Z46WJv4DfwXw= + +Name: system/etc/security/cacerts/455f1b52.0 +SHA1-Digest: kAWSB8ILogPZzBtuKBpjQvO6wGU= + +Name: system/etc/permissions/android.hardware.touchscreen.multitouch.j + azzhand.xml +SHA1-Digest: +jpP1GhT6HwDfDHhPbF4fqQTwB8= + +Name: system/etc/security/cacerts/03e16f6c.0 +SHA1-Digest: NU+kXb+8/njmA2M/T0gBfUiAMw4= + +Name: system/media/audio/notifications/Maize.mp3 +SHA1-Digest: JOPJ2B0wUdJ1YpbTis6Ls/hvfTA= + +Name: system/usr/srec/en-US/compile_grammar.config +SHA1-Digest: mdpUNdm82426woOidVS5ExtlbTQ= + +Name: system/usr/keylayout/Generic.kl +SHA1-Digest: fIrDip0pbaTuslI8pbUBHoBPS58= + +Name: system/lib/libaudioflinger.so +SHA1-Digest: cO/Bk3PzEHZpk+3+wn8qAyfojsY= + +Name: system/media/GPU/mask_vignette_legacy.bmp +SHA1-Digest: UkD7py3wdeRqiXYsYjTsldM2eeI= + +Name: system/customize/resource/quicklaunch_28020.xml +SHA1-Digest: D0ImwjegPrVsFHm2Lvv6p+fPMcs= + +Name: system/usr/keylayout/dummy_keypad.kl +SHA1-Digest: U2k1GE0KNq0lGhB6bgkZJhSPFmw= + +Name: system/bin/dbus-daemon +SHA1-Digest: GyEIqtCdnCCA+moMXYsZx0U/eHc= + +Name: system/media/audio/ui/camera_click.ogg +SHA1-Digest: V7fhbEaJIXo2h/p1lguCCaLW6qk= + +Name: system/lib/libstagefright_soft_aacenc.so +SHA1-Digest: GURrnkB4thJiQvAfQBWhCq+yMP0= + +Name: system/lib/libext2fs.so +SHA1-Digest: MLQUNKXqnD23KWj/fT5NEg/hmHw= + +Name: system/lib/libllvm-a3xx.so +SHA1-Digest: 2GnN8GHqNjI+UEIDdDC+69KgaFU= + +Name: system/etc/tfa/tfa9887_l.patch +SHA1-Digest: 0VJpWQFPVRYdJ4EGAzL9eBZDvbg= + +Name: system/app/SetupWizard.apk +SHA1-Digest: V2FqvWxQCjwBKpT1mMTXEZnagoY= + +Name: system/app/HtcNotes.apk +SHA1-Digest: Ckraw+UO1QBBioD3tVP/3gnKKF8= + +Name: system/etc/snd_soc_msm/snd_soc_msm_2x_Fusion3 +SHA1-Digest: yXQfZsxZRUlI0Fsz574lYKuy3Ic= + +Name: system/media/weather/weather_l_cloudy_day.mp4 +SHA1-Digest: 2ad2jPTcN08/Fz9IqaabG8bJUrI= + +Name: system/customize/resource/wallpapers_b_01.jpg +SHA1-Digest: Qhc0ajCPGXYjPvMohZlWmkgBnLg= + +Name: system/app/Mail+nonprime.apk +SHA1-Digest: MR5lrEaF9CeAZDA1nSY+ArONTvk= + +Name: system/etc/security/cacerts/cdaebb72.0 +SHA1-Digest: boCUiF4OQ/Bc6b9xuzVVDs8BBkk= + +Name: system/usr/keylayout/Vendor_045e_Product_028e.kl +SHA1-Digest: 5vqCZTOVkoSpc0kmFfaNUhf5FbE= + +Name: system/lib/libwt6docrdr.so +SHA1-Digest: WrDRasG7xvTHPlWnb/2rl/Mvzb8= + +Name: system/customize/resource/quicklaunch_63102.xml +SHA1-Digest: 29yXw3o1lTltww2+7gpOib6e9yI= + +Name: system/lib/modules/lcd.ko +SHA1-Digest: rndArHiiK4U1POSkjpq2f2QuMWM= + +Name: system/etc/fallback_fonts-ja.xml +SHA1-Digest: z2fFfpqzlK/fJYgl0/ISK1xxNjU= + +Name: system/app/Automotive_Traffic.apk +SHA1-Digest: GA294MlsVBSfxrAjLfezKM1pjxI= + +Name: system/etc/security/cacerts/dbc54cab.0 +SHA1-Digest: mLY39lqUQs7ml8zsoOpALdtZjMk= + +Name: system/lib/libdefcontainer_jni.so +SHA1-Digest: K7GvikoWnY+JCh3UhB+Zbo8eRhI= + +Name: system/bin/btld +SHA1-Digest: MKJsyx/COSXQ7w3pS4lPgyrFBsM= + +Name: system/etc/permissions/handheld_core_hardware.xml +SHA1-Digest: F4hDcGHqWxsTh4I+siOHqZJtIlQ= + +Name: system/etc/image_htc_midtier.bin +SHA1-Digest: K3AuJkRycsl4u41aCaVv65rWJ08= + +Name: system/etc/tfa/ring.config +SHA1-Digest: vp0Z5j8P3tSbQfhd3TX1QzkHElY= + +Name: system/app/MyHTC.apk +SHA1-Digest: 4+JRmBCm8lhSlVAWvANxLwOhXpE= + +Name: system/app/CheckinProvider.apk +SHA1-Digest: QPZgI8MJdc1Ow4hlP50v0Kou25Q= + +Name: system/customize/resource/quicklaunch_24801.xml +SHA1-Digest: Xa2aGR1lr575hocOep84Upntxxg= + +Name: system/framework/monkey.jar +SHA1-Digest: MkmzaOT9qYqS59wQLx22K+NioIU= + +Name: system/lib/libhtcflash.so +SHA1-Digest: TQSPk3eosSohCQWXpA5MwTIXcUI= + +Name: system/fonts/DroidSerif-BoldItalic.ttf +SHA1-Digest: 9yrTa21bS7lrxMqVUy9FELRQ5WM= + +Name: system/lib/libwsp_jni.so +SHA1-Digest: +zcdvT6LGB0OOCbkzowaeBKN8Lk= + +Name: system/etc/security/cacerts/5046c355.0 +SHA1-Digest: OQH1BPU6CROY/RgHEc+aJJM9Lcs= + +Name: system/lib/libwivu.so +SHA1-Digest: R3hrlu+eMZTjvKiMB0wdCp1PtzE= + +Name: system/bin/surfaceflinger +SHA1-Digest: 2qmr2aL5TAPukvq667gIVGkyQtk= + +Name: system/lib/libcpt9core.so +SHA1-Digest: NP7L6hhyTVBsOCbGHWeu4pFY8IA= + +Name: system/etc/security/cacerts/ce1adacf.0 +SHA1-Digest: Ou6tsrEpMUV7CScsC6XMlmto+9I= + +Name: system/app/IdleScreen_No_lock_screen.apk +SHA1-Digest: p25buBhqy++M+WCuxDda/Lbmm0U= + +Name: system/bin/memlock +SHA1-Digest: RcWgny934lOB35Ht6tKSldgK3Xw= + +Name: system/etc/security/cacerts/11f154d6.0 +SHA1-Digest: N3mD6hj2jNRv/GRshgLKaXmOtaY= + +Name: system/etc/security/cacerts/5a5372fc.0 +SHA1-Digest: Fb0tYUiGRziyUpyHHetf0/rTWWU= + +Name: system/etc/security/cacerts/9685a493.0 +SHA1-Digest: uQOYnTRtD38Rh9THdcalO+4cPsI= + +Name: system/media/GPU/dot_mask_2.bmp +SHA1-Digest: ePCPruIAtEN9jvd++wLUw0EuuR0= + +Name: system/etc/tfa/recorder_l.config +SHA1-Digest: aAViz/nsb9kNIE42WjaKFSRjsfM= + +Name: additions/fonts/comicsans/Roboto-Bold.ttf +SHA1-Digest: j/PZDPmw1f3ho31euZFpwEKP5ss= + +Name: system/media/zchgd/batt_95.rle +SHA1-Digest: DHOlOsXEwzaYFltcNOM04oZQV78= + +Name: system/app/IMEXT9English.apk +SHA1-Digest: SHE0TI7r65ez9ylXakrL99f48oQ= + +Name: system/lib/libwt6epprndrv.so +SHA1-Digest: exGfwLsLL1PdbbtmzqVFcpzV/Wo= + +Name: system/etc/tfa/ring_l.config +SHA1-Digest: T5byfbh4wTg+1ji6PtDoT/9Bnd8= + +Name: system/lib/libdsprofile.so +SHA1-Digest: vWmvGf0Du1yz0Sv1Wj5Gjapshn4= + +Name: system/etc/tfa/recorder_l.eq +SHA1-Digest: bBkshORbpfxCjRB7MT/pTcpqb/4= + +Name: system/lib/libDxDrmJava.so +SHA1-Digest: jDD58xXLtRzU5DHI26xKFaVtMfM= + +Name: system/media/audio/ringtones/Emerald.mp3 +SHA1-Digest: 5p7C+6BZXNwMG7EWCPT66emmFAk= + +Name: system/customize/resource/allapplication_28001.xml +SHA1-Digest: u5gd0TLGYUUhV0S8kqQTjxsjJ2s= + +Name: system/lib/chiaddict.dat +SHA1-Digest: jKkE8OjVEpdNSRYvaAp2pZYRJYQ= + +Name: system/bin/netd +SHA1-Digest: g55N861xb+nbqhC7R0xNX6WGeOo= + +Name: system/etc/image_gec_2vol.bin +SHA1-Digest: 8E2vv/LialvvztFPjhcdKUzJx20= + +Name: system/etc/htcfs.conf +SHA1-Digest: 7U9m+U7G1dY6oJecxU/nDpsMh4Q= + +Name: system/media/weather/weather_rain_day.mp4 +SHA1-Digest: GKKdtxUFHsJoMLFHrGfup5R8BQ4= + +Name: system/etc/security/cacerts/d64f06f3.0 +SHA1-Digest: rJ+XZX/zYV6CfIibccm6aeg3E8Y= + +Name: system/bin/schedtest +SHA1-Digest: 79TTHeYMFVcsu212JsTCwVPL4qM= + +Name: system/app/CertInstaller.apk +SHA1-Digest: hPAU3/4e16V9g7k1K6RBefJbygg= + +Name: system/usr/srec/en-US/grammar.config +SHA1-Digest: i0kpjrtpyO9CYP1yXMnKNwVLv6U= + +Name: system/media/weather/weather_l_cloudy_night.mp4 +SHA1-Digest: u41T0CONl/OZDiUWXPtxZyadZRU= + +Name: system/app/Liveretouch.apk +SHA1-Digest: r8r/ZaXfywZCvgW5TcEYMdMOFwk= + +Name: system/media/audio/ringtones/Grey.mp3 +SHA1-Digest: nNLSGLck6f1bwD7p1m8gtQXz33A= + +Name: system/etc/security/cacerts/d2adc77d.0 +SHA1-Digest: soKD09dcMHFX0hjD+rJQypQWLqM= + +Name: system/app/CustomizationSettingsProvider.apk +SHA1-Digest: LNLWqQFVpTCLVEdKmzQsqC5FOVg= + +Name: system/lib/libstagefright_soft_flacenc.so +SHA1-Digest: TcOCo+hR6OU/OTXDXpqAgYG4FOA= + +Name: system/lib/libfilterpack_facedetect.so +SHA1-Digest: G4gdGHlFL/RryALdFEJAQ3aWuYs= + +Name: system/media/audio/ringtones/Ultramarine.mp3 +SHA1-Digest: SOCNlHgKrXXOys4whSWMrhzAiJo= + +Name: system/lib/libmmstillomx.so +SHA1-Digest: Y43b2rqJ41jdMttwug3vkSiDu+U= + +Name: system/app/NetworkLocation.apk +SHA1-Digest: PY9WUQXh7LHQZMO/kszERBxA9zQ= + +Name: system/lib/libgsl.so +SHA1-Digest: Clb42VzvPf62A/B2GNLx43l2VOs= + +Name: system/etc/tfa/voip.preset +SHA1-Digest: nzd/u9J610RTa1J06s56MpAarB0= + +Name: system/etc/image_gec.bin +SHA1-Digest: no0rxo2odQyCl671MdeRXbNZ5Sw= + +Name: system/app/FM_Radio.apk +SHA1-Digest: cI55Z5UFdXu2hu0Udh8CSwULPYk= + +Name: system/lib/libmmwfdsrcinterface.so +SHA1-Digest: qxpirYYwJARgfi4EGhpKgTVP7Ws= + +Name: system/usr/srec/en-US/acoustic_model +SHA1-Digest: Bzsv1FQKC7SoKYlOYai42KLLvAc= + +Name: system/lib/libusbnetjni.so +SHA1-Digest: FjIEsbp9Kc+/SEOBMwZ+q9Xrhss= + +Name: system/bin/v4l2-qcamera-app +SHA1-Digest: wop8IV+2HfdgeJUDvmZ0k0KnUOw= + +Name: system/lib/libswapheap.so +SHA1-Digest: X+K6qJwQOO6zZOsbjM+kMRp4fgw= + +Name: system/lib/libwfdrtsp.so +SHA1-Digest: XeMSeCQ1CcxBwC8kfbdaLvic8Ng= + +Name: system/bin/atrace +SHA1-Digest: DK0xp5iRZ5DQJdqRYpH1qWVT33c= + +Name: system/bin/mm-qcamera-daemon +SHA1-Digest: 5Mz9mWphrBpQLPAPhYmf+XJT8y4= + +Name: system/etc/permissions/android.software.live_wallpaper.xml +SHA1-Digest: AyPpQw5IN0UBn608llm8t77fiPY= + +Name: system/fonts/DroidSansArmenian.ttf +SHA1-Digest: ZqNiJp/UISxsUJB+Xj4nlWWRPT8= + +Name: system/bin/mediaserver +SHA1-Digest: 2RSiZw/H8Q0MGq/RMV0imHSq6PM= + +Name: system/media/zchgd/batt_0.rle +SHA1-Digest: A4vbAFbLotgT+iEZiSbbNo/mcNU= + +Name: system/etc/security/cacerts/57692373.0 +SHA1-Digest: EskvxfpDUOk0oqxCTSEsSQR+P6g= + +Name: system/app/HtcProfilesWidget.apk +SHA1-Digest: zlSCeGitNNxnRbKUP8EGD08/1i8= + +Name: system/lib/libandroidfw.so +SHA1-Digest: IRG30e+cRwhUIRTS29ec+7Ol9nA= + +Name: system/lib/libjpeg.so +SHA1-Digest: cUjm6sHRhr1jv9V0G4tvoXD0Hd0= + +Name: system/media/audio/ringtones/Tangerine.mp3 +SHA1-Digest: Ze6NMjnGzJeJMRV8CoBfjLQdIcM= + +Name: system/lib/modules/msm-buspm-dev.ko +SHA1-Digest: 2np61brl2AOEmviP1bYXad0EuQc= + +Name: additions/fonts/comfortaa/Roboto-Regular.ttf +SHA1-Digest: XOc3d+Q6ZPzZSunfqxnFMKyzGWU= + +Name: system/lib/libdumppcm.so +SHA1-Digest: pAs7NlFsLOM6usGY2rqLvxA5+Yg= + +Name: system/etc/tfa/voice.config +SHA1-Digest: cvb/y9BZioN2wM9PRoIRQePdSow= + +Name: system/etc/tfa/recorder.eq +SHA1-Digest: b7YaGmv7Xu4rODdez3eRlk00JZw= + +Name: system/media/audio/alarms/Taupe.mp3 +SHA1-Digest: pIoWko3vsMo5A4TiuBNtDwWxlrA= + +Name: system/lib/libwt6bjprndrv.so +SHA1-Digest: GFqFQUt15r6p9Bit27sAkLyM1RQ= + +Name: system/etc/security/cacerts/7a819ef2.0 +SHA1-Digest: Ig0Zi/k4BqWAYNZWWgJjpKVsDHs= + +Name: system/framework/com.dropboxpartner.jar +SHA1-Digest: axVoQ38TBr/xquuVBRBtdT2yGjU= + +Name: system/lib/libchromatix_imx175_default_video.so +SHA1-Digest: NLBeF6M37nFeZK1JwN60asbEG3E= + +Name: data/app/com.google.android.apps.maps-1.apk +SHA1-Digest: +tTZZYAOoDSxEJTjbxWuNwBxnGQ= + +Name: system/etc/init.qcom.bt.sh +SHA1-Digest: GoEymPhK8EdX962l/M7nOIM6W2E= + +Name: system/lib/libext2_uuid.so +SHA1-Digest: i7g7GxfXcgQWlRLyigJnSt5ouDs= + +Name: system/fonts/AndroidEmoji.ttf +SHA1-Digest: irAmQlWMaVfKS2WbXf6WPUKnkfI= + +Name: system/fonts/ucsh00d_c.ttf +SHA1-Digest: FF+ClHJNof/U9r2Ooj7HLPA7SjM= + +Name: system/etc/thermald_boot.conf +SHA1-Digest: kpjCZLxFp1Wn1m6oJ9The1KIj9k= + +Name: META-INF/com/google/android/aroma/themes/sense/radio.png +SHA1-Digest: S42xKueiiE6TUmu9NwkfcrekzlA= + +Name: system/etc/security/cacerts/8ccb5f6d.0 +SHA1-Digest: E7FbxirzVSqvpXtf38OurNlrqfw= + +Name: system/framework/com.htc.android.bluetooth.le.jar +SHA1-Digest: rty+oj59TGDphdvtjzr5qV7Y+WE= + +Name: system/app/IMEXT9Hebrew.apk +SHA1-Digest: AgT9S9Rn79ZhmBHDi7LUyhQ/CCY= + +Name: system/vendor/tmo_cm/demoutil +SHA1-Digest: v/1/QNUfZZnXtB44k9fBKxm9dMk= + +Name: system/lib/libtzsrv.so +SHA1-Digest: 8I5T86LmWpPbjqRXN+4qEnAS7Aw= + +Name: system/media/weather/weather_l_partly_sunny.mp4 +SHA1-Digest: Wvw/WrrZd/Rf1fHM3am4SVnEihY= + +Name: system/usr/share/partials/partials_CW.dat +SHA1-Digest: /rzyHT6AMAejio0aC1tthzjKqT8= + +Name: system/customize/resource/allapplication_26003.xml +SHA1-Digest: OXCYG9LTxP6bOuChsDhcOKOb80U= + +Name: system/etc/tfa/deftcoefA_l.speaker +SHA1-Digest: qxlPE8Oa6KZuMFIfLkrkhbOBBNU= + +Name: system/vendor/lib/libWVStreamControlAPI_L1.so +SHA1-Digest: +RyYf1fJpQCZ9gjd4DK/hTAotWs= + +Name: system/usr/srec/config/en.us/models/generic11.lda +SHA1-Digest: gCp5FAUl5aR0GnFC/tkkamX7ic8= + +Name: system/etc/firmware/hcheck.mdt +SHA1-Digest: l3jA3PcSX/yUUGCpzA2WEDv4uXM= + +Name: system/app/Camera.apk +SHA1-Digest: 2RpMwYyt8WzAUJGRMTn+Qt7Q5bY= + +Name: META-INF/com/google/android/aroma/scripts/restore.sh +SHA1-Digest: +IFiQ87RD/mBgFk3nO1EVpUZoEA= + +Name: system/app/HtcResetNotify.apk +SHA1-Digest: 5fU00pE+ZkRWBi9sXi9iy6Xj+LA= + +Name: system/lib/liboma-drm1-fs.so +SHA1-Digest: tXHTRquBOPSLL4i5ovm/kayrx10= + +Name: system/etc/tfa/playbackbeats_l.eq +SHA1-Digest: +M8Q2RJodUbgkVcTi0aPa96zoaM= + +Name: system/media/GPU/dot_mask_1.bmp +SHA1-Digest: 0FS1Rq1IuGptrsIASMoZJuajNz0= + +Name: system/etc/permissions/com.android.nfc_extras.xml +SHA1-Digest: Qi+tQ+6ZJcMQyV/l49XjYlVTiHk= + +Name: system/etc/permissions/com.google.widevine.software.drm.xml +SHA1-Digest: MvejKuFQO4VpexrZo29KXJ+HiE0= + +Name: system/lib/liblog.so +SHA1-Digest: ri8qM9tyEfeIIFgH98xHZoYp71s= + +Name: system/vendor/lib/drm/libdrmwvmplugin.so +SHA1-Digest: POSlWZHYhwsHJBQxLVZkpxlRhZ8= + +Name: system/etc/tfa/video.eq +SHA1-Digest: Dp4yAwQQcqyl+1dS1Sn2d2+myjk= + +Name: system/media/audio/alarms/Metal.mp3 +SHA1-Digest: YZ+I0awmNJthQhv7r1j8nu8MmmM= + +Name: system/etc/firmware/BCM4335B0_002.001.006.0042.0044.hcd +SHA1-Digest: X+iOdsNt8Ynh1ROzUwLtyki0twk= + +Name: system/etc/tfa/tfa9887_l.speaker +SHA1-Digest: kemyp/nV0lUfI5SIOo2l7Bxf3LE= + +Name: system/etc/tfa/voip_l.preset +SHA1-Digest: AiUIPnv0eAPZ85xkvzoR3KpCSG0= + +Name: system/customize/resource/quicklaunch_21910.xml +SHA1-Digest: yDmSwysEv+KAwqnAxESa+45UC2c= + +Name: system/app/DeviceManagement.apk +SHA1-Digest: r2udjBSMgIEeHT+4YrS7JGGdkYA= + +Name: system/framework/framework2.jar +SHA1-Digest: HFENq4WIXLBzcDq5LnJkbzylFac= + +Name: system/lib/modules/qcrypto.ko +SHA1-Digest: TtehboObBgutlAWk39hipZSGLFA= + +Name: system/bin/iptables +SHA1-Digest: vP0hwB0wB2UrqUTHNooWbBpTq5Y= + +Name: system/lib/libchromatix_ov5693_default_video.so +SHA1-Digest: q7n/2KqLaeprA6aGO+9jNpvbQtk= + +Name: system/lib/libchromatix_imx135_hdr.so +SHA1-Digest: RtM5wWJ0Gxrq3iPLwVt/yhjwyHs= + +Name: system/lib/libmmcamera_frameproc.so +SHA1-Digest: R7ncBjN27ct15KyLm6MFbF5ja5Y= + +Name: system/etc/security/cacerts/bdacca6f.0 +SHA1-Digest: GIoKYjYZDMCLnDmLcIXSPHiDtmc= + +Name: system/lib/libdrmtime.so +SHA1-Digest: poYQE6pFCKw8CMGUHptcn/cUCR0= + +Name: system/lib/libmorpho_frame_overlay.so +SHA1-Digest: gbVlf47RojfdfDgYHfPDP7bLgFk= + +Name: system/media/audio/notifications/Ivory.mp3 +SHA1-Digest: hmK8RlxgveGD5SyMrkE+GVhT6C0= + +Name: system/app/HtcSettingsProvider.apk +SHA1-Digest: bxjX1Lj4cRoG0YaZXhisEoO2BBY= + +Name: system/lib/libwt6pdfrdr.so +SHA1-Digest: B+GCLLFrgHg/D7OuDZlf/hFg1QA= + +Name: system/etc/tfa/ring.preset +SHA1-Digest: vzK8FP9UHfN6O7t7OG7XpmMDv7g= + +Name: system/lib/libchromatix_s5k6a1gx_hdr.so +SHA1-Digest: PWtqDeWbLuzRWMjewirD5PAmbMw= + +Name: system/lib/libgccdemangle.so +SHA1-Digest: zuXmNt8TPZ20EzljdjbSNWM/qqo= + +Name: system/app/IMEXT9Croatian.apk +SHA1-Digest: Qeiaq8+F3t8Zgzb0n2DDsG6UtSg= + +Name: system/etc/pnp.xml +SHA1-Digest: H4VoWJ7UKQwr4fx5mhoicuZ2518= + +Name: system/app/HtcAlbumMapView.apk +SHA1-Digest: wZrL5/adG2UdiThOhqxaCN1N0GU= + +Name: system/app/IMEXT9Kazakh.apk +SHA1-Digest: XA4b+bIaRwMZ8waGbca+lHCzmts= + +Name: system/app/COTAClient.apk +SHA1-Digest: MYENtyP3sM2QkGpUZgVTi6ZlXRQ= + +Name: system/etc/firmware/a225_pm4.fw +SHA1-Digest: XA4uOpkFkKHZLr/AR3MBZiTP258= + +Name: system/app/DownloadProviderUi.apk +SHA1-Digest: Ts3kpdy7RB0TTudBPb25fNMhCSI= + +Name: system/etc/security/cacerts/d78a75c7.0 +SHA1-Digest: KjqNAg7rqiKjiInNH3f2Iw3g6lo= + +Name: system/media/audio/ui/Effect_Tick.ogg +SHA1-Digest: zjEY3W+2jVwKElh2zJYZzLLjRE4= + +Name: system/media/weather/weather_l_snow_day.mp4 +SHA1-Digest: GomNkwvZBLxYwgMsJl+0Xg2l47Q= + +Name: system/lib/libdrmfs.so +SHA1-Digest: bwpPYLzuTtPgtjXn2e6kHEeQeEY= + +Name: system/etc/security/cacerts/86212b19.0 +SHA1-Digest: qWrS3UkHFWMxfILKNINl2lbaHMU= + +Name: system/lib/libstagefright_soft_aacdec1.so +SHA1-Digest: oB07pxZuRY4qhAugsnLiSdesh5E= + +Name: system/customize/resource/wallpapers_c_03.jpg +SHA1-Digest: Xu2V6yZkQTiej/8ML+mi29OK8i0= + +Name: system/lib/libmorpho_image_transform.so +SHA1-Digest: FJ8iZgeyA1uR2kq448yOvbdqYMI= + +Name: additions/openvpn/xbin/bb/placeholder +SHA1-Digest: VsY8qMTJY2AtLHJaNPXQY6YhoHU= + +Name: system/lib/libfuse.so +SHA1-Digest: dxpdoTqPZTJE3ZZQ420P68neBMA= + +Name: system/etc/tfa/voice.eq +SHA1-Digest: bcJn0BeKcW3qiAk5Kk12Cwn34ys= + +Name: system/etc/wfdconfig.xml +SHA1-Digest: Xn544gPZ7XZBcrchver+OSt6Uk4= + +Name: system/bin/getevent +SHA1-Digest: jyJF2/MqB/fdA8FZls4TTnLwsbE= + +Name: system/tts/lang_pico/it-IT_cm0_sg.bin +SHA1-Digest: rnh7Xn11wgxlksoos2j4/cAF2+I= + +Name: system/lib/modules/ansi_cprng.ko +SHA1-Digest: Bjedkn80a+dDlXOQuNs+wOVQ62U= + +Name: system/bin/diag_uart_log +SHA1-Digest: yih7EjhghzPsZ0KUizJ9s3MuRp8= + +Name: system/bin/pppd +SHA1-Digest: Vt2JveeRqPfLTr/9HeL/fALyWz4= + +Name: system/lib/libbeatscorehtc.so +SHA1-Digest: zX/7I0xHeFfzyd9j9RfF2wHmdw0= + +Name: system/lib/libchromatix_s5k6a2ya_hdr.so +SHA1-Digest: GQzK5zYLu4tKlMcOAneZ+Mb7TVA= + +Name: system/lib/modules/qce40.ko +SHA1-Digest: om3IJToQ5gEtM7NAPjyvN4ttM90= + +Name: system/lib/soundfx/libvisualizer.so +SHA1-Digest: VOFEmt/JQoqbVTQ5ht7iiGEeU1w= + +Name: system/lib/libqdcbutils.so +SHA1-Digest: bY8sDp6onZxGzsBVz0yMK/Jqh80= + +Name: system/framework/com.android.future.usb.accessory.jar +SHA1-Digest: MnGPJU6giBw4K6/TQDp9KwvEVkA= + +Name: system/app/Message+Nonprime.apk +SHA1-Digest: iTIvO/nEwLIBmyh8n34c9gU0sGE= + +Name: system/customize/resource/allapplication_21407.xml +SHA1-Digest: dMyxtMyLSm3khse/Km+6SQI+BYA= + +Name: system/lib/libiculx.so +SHA1-Digest: +2ROc4e+MLsQvysJqxJ9h8dgP+Y= + +Name: system/lib/libmode10fx.so +SHA1-Digest: dyAg+HL4o61jqScUuTg53ntIQUU= + +Name: system/lib/modules/evbug.ko +SHA1-Digest: +m/bbNDyk2J3io9zgMMyBoRDhEs= + +Name: system/app/HtcMediaCacheService.apk +SHA1-Digest: WXKyX+ycK7scpeW9J5YIrBtlw2I= + +Name: system/bin/installd +SHA1-Digest: pG2UoqfqrDFdH8FeIr4+iCU1sMY= + +Name: system/usr/keychars/qwerty.kcm +SHA1-Digest: Z/WKxPvIkR28R++ZAs/Acj5tvbw= + +Name: system/etc/permissions/android.software.sip.xml +SHA1-Digest: 9UTSCo9zY5j/DOZVZMjh7ozBOFE= + +Name: system/etc/security/cwcerts.zip +SHA1-Digest: sPG4eRyxb5c4TTGX2JPy7KEOZcs= + +Name: system/media/mms/atis_tia_cmas_alert.mp3 +SHA1-Digest: L7S6WJtNyvSN7YriPwX04gDCF+M= + +Name: system/framework/com.htc.lockscreen.fusion.jar +SHA1-Digest: m6qzyXS8H/CZgqZAfcS4JQmqWYI= + +Name: system/lib/plugins/com.adobe.flashplayer/libstagefright_honeycom + b.so +SHA1-Digest: q0h3Rv9yyal3c19kb6O2YgGkvqc= + +Name: system/customize/resource/rp_ce_0700.png +SHA1-Digest: v7F0xMXe45bPSig6vrS7gIQ2wqg= + +Name: system/lib/libjDTCPServer.so +SHA1-Digest: FUl5wM+qEWAKkeGtzwWHqk5SqJ8= + +Name: system/customize/resource/quicklaunch_20601.xml +SHA1-Digest: h2yzFJ7GC3jbUTuQo/iYYY/gYsQ= + +Name: system/bin/cmp +SHA1-Digest: Y5T4jDFDZs6zEzwr9ZsR01gIj7Q= + +Name: system/lib/libNEONImage.so +SHA1-Digest: u5p5I6j6LxSjLPFuCJgWmFvoPB0= + +Name: system/bin/insmod +SHA1-Digest: CF4EingoEEicimLEYbnXuhI3JGs= + +Name: system/lib/libchromatix_s5k6a1gx_hfr.so +SHA1-Digest: /hrnV0MFd2LVHfc0h/doxN5MxFo= + +Name: system/usr/srec/en-US/endpointer_voicesearch.config +SHA1-Digest: MgyAh0x/DUBKQE/gm2rmLwyDODg= + +Name: system/lib/libjni_fe.so +SHA1-Digest: 9fBJ9HCfjWTibyp/vFlkJXe+f3E= + +Name: system/lib/libopencv_java.so +SHA1-Digest: +QWBOPiG++GYLv5DygI81qsU0Jg= + +Name: system/app/HomePersonalize.apk +SHA1-Digest: GPmUURLwP3EpuM9YHoJEwKOTriY= + +Name: system/lib/hw/gps.default.so +SHA1-Digest: ny3DaVrJVxAIUAlV23a2g76VgZ4= + +Name: system/etc/security/cacerts/b0f3e76e.0 +SHA1-Digest: 0wOZM5sOi9oFQTTpvoJC+0fuSmc= + +Name: system/usr/share/partials/partials_A.dat +SHA1-Digest: MsZfd3Sh8KJLEmKi51AQMuyifno= + +Name: system/lib/modules/dm-crypt.ko +SHA1-Digest: haD7H9tZbXTPnHUjp0CBcW7UWJs= + +Name: additions/screenshot/screenshot.sh +SHA1-Digest: sQz1dLmN24swbFfivxOjllH5L4s= + +Name: system/lib/libmlplatform.so +SHA1-Digest: YUmP4T7bnyyAqM01vKoSRXUTiqc= + +Name: system/media/zchgd/batt_10.rle +SHA1-Digest: uSiHDjZDP1MnhBIzPP3BCqu6dHc= + +Name: system/customize/resource/allapplication_20205.xml +SHA1-Digest: 4kr1GLIAEf5ixO+HqGYC1UVnHOc= + +Name: system/usr/keylayout/Vendor_054c_Product_0268.kl +SHA1-Digest: iwHzEwj5WX7NvOdertR+r9nuRsk= + +Name: system/lib/libgnmc_fpx.2.5.9.4.so +SHA1-Digest: /Ip5KP/CWmjMcPV8E0JRNNGlMo0= + +Name: system/lib/libgenlock.so +SHA1-Digest: fuUHtDVQW8Tj4Pemc+d6dol4Zic= + +Name: system/app/HtcMobileNetworkWidget.apk +SHA1-Digest: Wups6DNdXr28hWXwXJSNI9+D8XY= + +Name: system/etc/init.d/99complete +SHA1-Digest: R38JsJrPdpB2Ne7I1Fp/iBELBhw= + +Name: system/fonts/DroidSansFallback-htc.ttf +SHA1-Digest: 0R5Cccj9M9oQI22nYm9KEIOrSk8= + +Name: system/bin/rild +SHA1-Digest: Dg+6j0dDUBtvnMCBzOXvsRNqieQ= + +Name: system/bin/logcat2 +SHA1-Digest: 7Xc63MXm7/d6p749M0tZsp/7wuU= + +Name: system/lib/libhtc_rilhook.so +SHA1-Digest: byBYA8+ysxTSaRcmrch63a/cKm0= + +Name: system/etc/wifi/wpa_supplicant.conf +SHA1-Digest: FtmOFmIrZRtpuTgL9V/rpfsYYDk= + +Name: system/customize/resource/allapplication_26806.xml +SHA1-Digest: waWxu+bWyHBdN0HJdc12vNjU3I0= + +Name: system/xbin/bttest +SHA1-Digest: p7uc529Tjh3Ihn10STfG6IC6KsY= + +Name: system/lib/libiprouteutil.so +SHA1-Digest: naTz9lLr1u5eCUbUQujR9FlT0tI= + +Name: system/customize/resource/allapplication_22201.xml +SHA1-Digest: 4mH10Pu0YPh2I9QN1bcs+1RPCNU= + +Name: system/app/PureC_PackageInstaller.apk +SHA1-Digest: z/VA10vym5uqxV4Nwz8ewJZ8ZEM= + +Name: additions/camera_4.2/app/GmsCore.apk +SHA1-Digest: zMX3n0qREjPgwLY6ZvH3pqfYvSk= + +Name: system/fonts/DroidSansTamil-Regular.ttf +SHA1-Digest: d/a5ySWr4uOYlmRQ/GVVxmtcfDk= + +Name: system/usr/srec/config/en.us/grammars/boolean.g2g +SHA1-Digest: IaXNuE4WOK1Xeb/yfielIx9Z4P8= + +Name: system/lib/libzeroeditor_osal.so +SHA1-Digest: 72fzz0iXk4ZNZ1b4/HGF6Agz1E4= + +Name: system/media/weather/weather_fog_day.mp4 +SHA1-Digest: 2BJJjHgJJmChAf3ANGkXtPFYefU= + +Name: system/lib/libmorpho_image_converter.so +SHA1-Digest: 7VmgYJpv0DFnfpt//joPmNYwFeo= + +Name: system/fonts/DroidKufi-Regular.ttf +SHA1-Digest: yYCvuiwVrMbyw5ISV3ba2OZ1zoU= + +Name: system/etc/fallback_fonts-HTC__J15.xml +SHA1-Digest: 5d+S8w87iCgH3YnHOxUnKmc1BQg= + +Name: system/lib/libhtcdrm1.so +SHA1-Digest: mcBukB0FRIHFjz4bB27skHSai3M= + +Name: system/usr/keylayout/Vendor_046d_Product_c299.kl +SHA1-Digest: N64rO5ir6UJhDLlL6vtA277M/n0= + +Name: system/customize/resource/allapplication_28020.xml +SHA1-Digest: nhiXU7xgEIe7zyW5d85uyVOV6Gk= + +Name: system/customize/resource/wallpapers_a_07.jpg +SHA1-Digest: rD6ZUfJ/tRCBTXLEiKLphZi1J0Y= + +Name: system/lib/libimage-jpeg-enc-omx-comp.so +SHA1-Digest: HRe1pdqqHyucUC/8eD2akmlqWPs= + +Name: system/lib/libmediaplayerservice.so +SHA1-Digest: pQueBISOcUpex8fia7K2vPnJDBE= + +Name: system/etc/security/cacerts/6b3f8240.0 +SHA1-Digest: 3I0ujeIwJOwFszifeBp0o8qMJQQ= + +Name: system/bin/log +SHA1-Digest: AZEUVqKb3UoIq1X3sE4OOqq/2Wo= + +Name: system/lib/libsensorservice.so +SHA1-Digest: KK/cGeoiyXIIayLEEsIqmNDn+ag= + +Name: system/lib/libEGL.so +SHA1-Digest: qq/qzn2H2sq5GI7F677ZFMhio/g= + +Name: system/bin/hdmid +SHA1-Digest: x3HXee0Z570O4FcxyAcruOF6zrk= + +Name: system/app/HtcHotspotWidget.apk +SHA1-Digest: XHMPERNPAHrfSW49gVxTVUvbRFk= + +Name: system/lib/libt9.so +SHA1-Digest: x5CleNw5JpAasMkmBcM9USOO/cQ= + +Name: system/bin/dexopt +SHA1-Digest: jfxGZp5Hday8mZSHbdMFZ6olCIY= + +Name: additions/fonts/helveticaneue/Roboto-BoldItalic.ttf +SHA1-Digest: nfsnY6gTEe6cMYaSuQ65Nb5cjJg= + +Name: system/media/zchgd/charging_06.rle +SHA1-Digest: LsydjjfZHDQcEBK7Gf4/f0a59+c= + +Name: system/app/PrivInit.apk +SHA1-Digest: EV007z7aT/E+q5auPFbz69+rlEY= + +Name: system/etc/firmware/vidcfw.elf +SHA1-Digest: rhXGC85w0om5FgIC+8//PD+2/7I= + +Name: system/etc/init.post_boot.sh +SHA1-Digest: yzW3xsjDjJyn+Ynrv6G+Sato6MA= + +Name: data/app/com.adobe.reader-1.apk +SHA1-Digest: L2QjUb1uv46hatREfZMoq70Aykg= + +Name: system/customize/resource/rp_ce_0560_i.png +SHA1-Digest: PnWwLXbc2v3oa/GkzxQNP2/aYgY= + +Name: system/customize/resource/allapplication_20601.xml +SHA1-Digest: +KZplE3XGBCEpyYowniKJYKTrb4= + +Name: system/etc/tfa/tfa9887.speaker +SHA1-Digest: LLSy88cA2gRdbFTAorLNVXTFBt4= + +Name: system/app/CustomAppInstaller.apk +SHA1-Digest: 85lIe5L2/tWRW8UN/a0O+3JTwBM= + +Name: system/app/IMEXT9Romanian.apk +SHA1-Digest: LKjLlwBZu4LrPrKwcdR7Ss/JWdA= + +Name: system/app/SelectPlayer.apk +SHA1-Digest: 3CgyH0fSvUaMRu18Ewc9Q9DbSj0= + +Name: system/etc/permissions/com.nxp.mifare.xml +SHA1-Digest: EbIle6B9w6yccdVJMcnCw23QJfc= + +Name: system/lib/libmorpho_memory_allocator.so +SHA1-Digest: d08BuL1nVzqGB0lr9bndr+07BqM= + +Name: system/etc/security/cacerts/7d453d8f.0 +SHA1-Digest: cA140QKiXig4ceJ7hyHJpuo224E= + +Name: additions/fonts/sonysketchef/Roboto-Italic.ttf +SHA1-Digest: aRM1HZHitSCbFit+cthH1govBD8= + +Name: system/customize/resource/quicklaunch_21419.xml +SHA1-Digest: Xl+dEFLy7PfwhJ+1W66GLrQFTec= + +Name: system/customize/resource/allapplication_23802.xml +SHA1-Digest: Bah8MgCCo4y6o6+AfmvsPqoYXh4= + +Name: system/etc/hosts +SHA1-Digest: +OtKCCSMljlpySKxhuN+zzZS88s= + +Name: system/media/audio/notifications/Lily.mp3 +SHA1-Digest: b30Y4nAPegXSdB5NvIZhJ2nMri0= + +Name: system/bin/qcks +SHA1-Digest: cMSmAHbLew3NESH89SZuhCPchHQ= + +Name: system/lib/libstagefright_foundation.so +SHA1-Digest: w/KOEfRfVs3qxmGp6I5GTdl/u/c= + +Name: system/media/audio/ringtones/Auburn.mp3 +SHA1-Digest: r39/U4ixvtZDtDVZAnW5wS9x1Zc= + +Name: system/lib/libstagefright_omx.so +SHA1-Digest: oC6HYs4zGcRSlUL6DX79Sm3oFjk= + +Name: system/etc/security/cacerts/add67345.0 +SHA1-Digest: BBZuvZg7SZem+qk/+qhuNIjw13A= + +Name: system/customize/resource/wallpapers_a_02.jpg +SHA1-Digest: TpyORqyeegJk9sPat+c2YjtO2kY= + +Name: system/lib/bluez-plugin/bluetooth-health.so +SHA1-Digest: sqs+99Zp4zb1z0XrT3xVHaEIhi4= + +Name: system/lib/libstagefright_soft_amrdec.so +SHA1-Digest: kWQVlyIqWb9PoC5ZPku2JyzQwYw= + +Name: system/usr/srec/config/en.us/grammars/VoiceDialer.g2g +SHA1-Digest: 6wv+uJnGUhIlJyoUJeIPbB+anro= + +Name: system/lib/modules/ks8851.ko +SHA1-Digest: kAgNUhRUYWyaKQW3EtTRj3Ztklk= + +Name: system/customize/resource/allapplication_24002.xml +SHA1-Digest: p+ENmY2oCc0RZ7dea9xU8U9Vns0= + +Name: system/lib/libmmrtpdecoder.so +SHA1-Digest: hXSa/tUQWRHSVNBJfD14hTV+aqY= + +Name: system/customize/resource/allapplication_23410.xml +SHA1-Digest: l5FhPtV99qzxOgsgcvYXbT4bzpw= + +Name: system/app/HtcLavaLiveWallpaper.apk +SHA1-Digest: JjNJL0+r+1VmPC6ZEzQgZ1bjDlA= + +Name: system/xbin/tcpdump +SHA1-Digest: GcI1cmfqUvkkEJLdkO5h+EHjLvY= + +Name: system/media/weather/weather_l_rain_night.mp4 +SHA1-Digest: 1qwxO1jxgSQ5Zupnr+9kVOuzzkI= + +Name: system/usr/share/bmd/RFFstd_501.bmd +SHA1-Digest: C0S/D/gyoOXBfe27iJkWBkJGc28= + +Name: system/bin/arec +SHA1-Digest: 3ZEvJ8K3c87q9KLSDkbqkaRdUaY= + +Name: system/media/weather/weather_fog_night.mp4 +SHA1-Digest: F1b1sHQ91NVfzgPSFKaIvjcvOyw= + +Name: system/framework/com.google.android.maps.jar +SHA1-Digest: fRt08xUFyTFpkn4QFMNXJAqzOnk= + +Name: system/media/audio/notifications/Pistachio.mp3 +SHA1-Digest: 8DSmU9sbyE1dBnUOqpU79DEmpBA= + +Name: system/bin/monkey +SHA1-Digest: WfWmGLdcQp2C3BlQ/nd56hRSN4M= + +Name: system/etc/firmware/tzapps.b03 +SHA1-Digest: RocT85k/WvAoPW1dD68npZqqe80= + +Name: system/etc/security/cacerts/17b51fe6.0 +SHA1-Digest: TF8DP16R0P3dLAbPoykKOGfTFrE= + +Name: system/bin/mm-vdec-omx-test +SHA1-Digest: IzB0v5b/nnoozAvTplkVv5mAOIM= + +Name: system/app/HtcMediaUploader.apk +SHA1-Digest: /B3ta4ot60KtLMXDGAWMMWmX0G0= + +Name: system/app/IMEXT9Slovenian.apk +SHA1-Digest: kJF7FN2xwqp/mUuTpA107TWzXG8= + +Name: system/lib/libchromatix_s5k6a1gx_preview.so +SHA1-Digest: 7rtlj9XIQMhiBPh5ZcC0PEjIVUI= + +Name: system/etc/firmware/tzapps.b01 +SHA1-Digest: GYR6PZVehWLZ+4iDuaHbZQ2jIDo= + +Name: system/fonts/DroidSansThai.ttf +SHA1-Digest: qrdCj47VL3j4/yEIwxqV+BM3IM0= + +Name: system/vendor/pittpatt/models/recognition/face.face.y0-y0-22-b-N + /full_model.bin +SHA1-Digest: zGut66M6P1Qi+iZT+iL2rTSfOWE= + +Name: system/etc/firmware/tzapps.b02 +SHA1-Digest: xGu+uRbMscGqBbCQylkLh2EKjqQ= + +Name: system/lib/libcommon_time_client.so +SHA1-Digest: RaK5F5IjhhZjYVeZz8yRxxARHLc= + +Name: system/etc/firmware/tzapps.b00 +SHA1-Digest: PYh07Ihkyaie2IP3Y68Y2YG8viU= + +Name: system/etc/security/cacerts/119afc2e.0 +SHA1-Digest: juMSLklsnjDd89OdzOhmdhh86b0= + +Name: system/bin/watchprops +SHA1-Digest: rVi0KO/rXSV+B0Zqs+CZzy4+gX0= + +Name: system/framework/browsermanagement.jar +SHA1-Digest: GQz97jDQIh0G3Fbl2VcLru54vFg= + +Name: system/app/GoogleServicesFramework.apk +SHA1-Digest: emeC9LDY+3EZFUJGf1j+jFZ6OuE= + +Name: META-INF/com/google/android/aroma/themes/sense/button.9.png +SHA1-Digest: 7KaJc9RyFKyk5aBmABch6EwwqBc= + +Name: system/media/audio/ui/Volume-5.flac +SHA1-Digest: VYzWS/U/znmHOaY1j+Yj4XbLhD8= + +Name: system/app/HTC_IR_Remote.apk +SHA1-Digest: iOYu+dC5zyYT4OL2F5+WN0R3+oQ= + +Name: system/lib/libstagefright_amrnb_common.so +SHA1-Digest: vho9Ypch07RLrJ9pTHklac/W88I= + +Name: system/app/HtcBtWidget.apk +SHA1-Digest: xYhdQWCQNrXsCWFqVJa321zLkzE= + +Name: system/customize/resource/wallpapers_b_06.jpg +SHA1-Digest: ewtQbQYZP2Cg3cZq4ECPW8d2xKQ= + +Name: system/customize/resource/rp_ac_no_nfc.png +SHA1-Digest: PJnfpIEfY9GB8l7IrPvDgxb+QM0= + +Name: system/framework/com.htc.fusion.fx.jar +SHA1-Digest: 1S/fpjL7E25RvXjS+8fMurMZMEE= + +Name: system/etc/dhcpcd/dhcpcd-run-hooks +SHA1-Digest: wlZAlg8sJGqNf67T6lXIETPzJxk= + +Name: system/lib/libmorpho_jpeg_io.so +SHA1-Digest: psc//o3vRza+y2DOzt4J6y1GIk4= + +Name: system/etc/security/cacerts/e7b8d656.0 +SHA1-Digest: bCEbhSbq/GjuAX/qoGBoN21YJuo= + +Name: system/etc/firmware/fw_bcm4335_apsta.bin +SHA1-Digest: x2+rDmFMd3c8WyCaJKg6ujcTrAg= + +Name: system/media/LMprec_508.emd +SHA1-Digest: P3ntvXeluWhTgyVlRyER0VRvzT4= + +Name: system/lib/libwlwpscli.so +SHA1-Digest: DUPG6tJdOqvwukRr9PTEFs8QQ9M= + +Name: system/lib/libspeex_sh.so +SHA1-Digest: tAuSG6ZD6iJ4UAa9PUwV2ponC1Y= + +Name: system/customize/resource/quicklaunch_234.xml +SHA1-Digest: 9BZOvNqHqO8g/LrYXOKjwuy3uJE= + +Name: system/etc/tfa/playbackbeats.config +SHA1-Digest: zFWqhuoYKHwrHgZELWBBXhpxnFw= + +Name: system/lib/libbcc.so.sha1 +SHA1-Digest: J/AeVx28TseGg1d4D2l3X25H9Yg= + +Name: system/bin/wpa_supplicant +SHA1-Digest: tY9Pj+FU/G/CNYVGu4z2uVzODZU= + +Name: system/app/ChromeBookmarksSyncAdapter.apk +SHA1-Digest: 4RQQmTFT4s2GAwxmPKzD6sHIPhE= + +Name: system/usr/srec/en-US/norm_fst +SHA1-Digest: yPCdX0EcppUA9o9xNvA5KBY7mUo= + +Name: system/media/weather/weather_l_partly_cloud_night.mp4 +SHA1-Digest: KGVl87qq7XxBvEf4nVirASRcN8o= + +Name: system/media/audio/alarms/Sea_Green.mp3 +SHA1-Digest: 6uwaXp8aCiPA0s66r/jVRRAr2EA= + +Name: system/lib/libril.so +SHA1-Digest: RVoivmiZdo52E1SWEUHvhVFoUug= + +Name: system/lib/libwt6docintr.so +SHA1-Digest: k/C2wZsheT7Jlzm7tmPIhkhHmjQ= + +Name: system/etc/permissions/com.htc.lockscreen.fusion.xml +SHA1-Digest: xDwHovhQsZ91x2Uok5Fkdp41qwo= + +Name: system/media/audio/ringtones/Violet.mp3 +SHA1-Digest: hCoDBZIIRTEmME686s9uGkQ4jn8= + +Name: system/etc/dbus.conf +SHA1-Digest: d6cc2Bt6sxy6Yzv4CTZl1X6sweY= + +Name: system/app/SmartDim.apk +SHA1-Digest: WwN7s9XcJbb0m7CUZLUIpJJgHvk= + +Name: system/etc/tfa/playbackbeats.eq +SHA1-Digest: 4B5p+K4WF2OwN1e2UO2b8VmZdFs= + +Name: system/lib/libdnshostprio.so +SHA1-Digest: ptLm4pujwPN5fBvXo4cB44F93jU= + +Name: system/lib/libttscompat.so +SHA1-Digest: 3YPguQTFjzvsxm7fxPzRGsFR4Kw= + +Name: system/app/HtcScreenBrightnessWidget.apk +SHA1-Digest: rijfDWQB2uPiSXkMzPrjgNHz/vM= + +Name: system/lib/libmmcamera_faceproc.so +SHA1-Digest: LyCqbfWUlPrumRmhY3ixT4u2luY= + +Name: system/bin/sdptool +SHA1-Digest: pNrMIU/dKkhf9JkkzORTuKctg0c= + +Name: system/media/audio/ui/KeypressReturn.ogg +SHA1-Digest: iYH8DQ0v9kvYnxCWM4nm70dYz7I= + +Name: system/usr/srec/config/en.us/baseline.par +SHA1-Digest: M4pck9N5JkEe9alJyTrxUpaKRd8= + +Name: system/bin/test_gemini +SHA1-Digest: QUT56NOIVSG03ywzQ54uc05IMkU= + +Name: META-INF/com/google/android/aroma/icons/update.png +SHA1-Digest: lkr8LjGc0VQptQ7ubRduxZr8zT0= + +Name: META-INF/com/google/android/update-binary-installer +SHA1-Digest: 80ouIw7SwSi1O7aqJJonSgZYfNY= + +Name: META-INF/com/google/android/aroma/themes/sense/cb_on.png +SHA1-Digest: bs1vf9xjcGOwDrYbOQNH+pKlPs4= + +Name: system/lib/bluez-plugin/input.so +SHA1-Digest: fYOyLs9+Aurt1iwfF70oIdizAUs= + +Name: data/app/com.google.android.gms-1.apk +SHA1-Digest: dQ887zLtKJRIYH978Rlor18qK0E= + +Name: system/app/AndroidHtcSync.apk +SHA1-Digest: A8CPczjYJla7YfquRVTOyTkHkEQ= + +Name: system/etc/permissions/android.hardware.touchscreen.multitouch.d + istinct.xml +SHA1-Digest: +ecLNHyCJcTgt86gz93pkIwcJ+c= + +Name: system/customize/resource/allapplication_21406.xml +SHA1-Digest: aJB1oVeQabIXk7Y3CRsaTfTdBx8= + +Name: system/bin/sleep +SHA1-Digest: 9libFqVtNipfKd041p5ESQDBFG8= + +Name: system/app/CalculatorWidget.apk +SHA1-Digest: x/ub7xVYqs1jMOb0LEhx8607BNE= + +Name: system/fonts/AnjaliNewLipi-light.ttf +SHA1-Digest: TXtkBSsmdd04OAXePzPNnSx+Vdc= + +Name: system/etc/security/cacerts/4e18c148.0 +SHA1-Digest: AC2kb6vDxMM9PpuxWWSvwbGQ+fo= + +Name: system/app/Basic.apk +SHA1-Digest: s/q6lm+7Mas5AWRYH3UeF4p2G+w= + +Name: system/app/IMEXT9Turkish.apk +SHA1-Digest: yaNbDmiq5rarikNgk50f2owunG8= + +Name: system/etc/security/cacerts/ff783690.0 +SHA1-Digest: uwa7DANnTSVTBT+3cPJVrv4kphk= + +Name: system/lib/libwt6imgrdr.so +SHA1-Digest: qAz9KRSQZ4ARkADJgg+7d9lFOJc= + +Name: system/bin/app_process +SHA1-Digest: SbWVq4U5vPF+9w2KjoyzNs+f7tA= + +Name: system/lib/plugins/com.adobe.flashplayer/libstagefright_froyo.so +SHA1-Digest: ivPwyUrCdxDSFUy0G64Wg/GeeMY= + +Name: system/media/zchgd/batt_100.rle +SHA1-Digest: m5MSMDD1fADP9RFjYCJm6ZePUWU= + +Name: system/lib/libstagefright_soft_h264dec.so +SHA1-Digest: 5CxbjmGEBI+E3HV5y7IBS9V3yrQ= + +Name: system/lib/libhtcpainting.so +SHA1-Digest: BQZRmBf8uSofJQJIIz2cDHWbn3k= + +Name: system/lib/libssl.so +SHA1-Digest: ueOfAvZYcpT0MWWyQcFXxAhUul0= + +Name: system/app/HtcPowerManager.apk +SHA1-Digest: NSK9+iXszubPvzwIaux0dLKQxoM= + +Name: system/bin/radish +SHA1-Digest: vp5Tq2dMAydZc7s7toiy5uD+9c0= + +Name: additions/smson/app/Message.apk +SHA1-Digest: rnXZn//zi9kTkgyWdb1JrUYX5Hc= + +Name: system/lib/libicule.so +SHA1-Digest: ahqhxS2GoYeVil4hDe74ZUYIyq8= + +Name: system/lib/libsc-a2xx.so +SHA1-Digest: RbTsmTu0Hvn33r1Wsvz118iDuFc= + +Name: system/media/zchgd/batt_80.rle +SHA1-Digest: ehGvAsA5GM+eE+bBhCv+TuF9BEg= + +Name: system/lib/tcp-connections.so +SHA1-Digest: EAGdxWVXzqk8cAvf4BzcbAzcQsE= + +Name: system/lib/libwfdmmsrc.so +SHA1-Digest: Batr2a9f11vKqfI5wrhGVds6Lqk= + +Name: system/lib/libchromatix_ov5693_hdr.so +SHA1-Digest: sJXZQNj3m4GcGvb7zl/1Ry7dKCY= + +Name: system/media/audio/ringtones/Indigo.mp3 +SHA1-Digest: E2bt/jqisKGMUm+gaosWWZA0dbU= + +Name: system/app/IMEXT9Arabic.apk +SHA1-Digest: QXvKHafsRjZRgdBIUxXJ3TIsnBM= + +Name: system/usr/srec/en-US/hmmsyms +SHA1-Digest: Fln/PQLUYTKhhm652kNflbC8Bv8= + +Name: system/usr/keychars/Generic.kcm +SHA1-Digest: ydpzvFLPpnkO8f4mH6S/QxmVMkg= + +Name: system/lib/libawDTCP.so +SHA1-Digest: VbYMSaaCWvPo2icuBUGTE15woVE= + +Name: system/framework/framework-res.apk +SHA1-Digest: a5BEOfUTEwYHlewNixviAkByLwY= + +Name: system/etc/tfa/voip.eq +SHA1-Digest: qhH+GMu5vwrIEMn9ouJWtWCH9IY= + +Name: system/fonts/HTCHand.ttf +SHA1-Digest: F8IpJV/YMT1MEi/m47xfoNy/lR0= + +Name: system/media/audio/ringtones/Chrome.mp3 +SHA1-Digest: 9lO8Sem8vny1CNKUQWNbluuaVl4= + +Name: system/framework/javax.obex.jar +SHA1-Digest: VhRlDoSmpM2CksGp/86sLrZySNA= + +Name: system/lib/libicui18n.so +SHA1-Digest: VzBzwvx0JyY495rafK6iTs/Tx6M= + +Name: system/lib/libmmcamera_interface2.so +SHA1-Digest: EDV25daRYtU/uUlJWdIK6uZwErg= + +Name: system/etc/security/cacerts/e8651083.0 +SHA1-Digest: pTCqliEJ3Q0TNsBDd6B+1e0I5nU= + +Name: system/etc/ar0260_1 +SHA1-Digest: QKnM/RS5ae8QNcxDNUVma4emeqI= + +Name: system/customize/resource/allapplication_234.xml +SHA1-Digest: 8bJFZyeyXGbTHMqG6HEZ+20XZwA= + +Name: system/bin/dnsmasq +SHA1-Digest: AYRKrUNjSDGj9U9KYA6vt5b4vlY= + +Name: system/lib/libglib.so +SHA1-Digest: 5jCi0rSwNKHlCUm2nwVM19Gr4kg= + +Name: system/etc/firmware/ILP0100_IPM_Data_out.bin +SHA1-Digest: KfvuhMuBeWLwiIkDhxChUNVP+ac= + +Name: system/etc/security/cacerts/aaa45464.0 +SHA1-Digest: xpHvANASM4utyFC+6Q3F3wh1Ys0= + +Name: system/etc/security/cacerts/613f892a.0 +SHA1-Digest: u4UojKzGDVs3PoKEWKv6snsYrIE= + +Name: additions/fonts/roboto/Roboto-Italic.ttf +SHA1-Digest: 6rQE9q8RGQRSFqC5wj8x3cFu9kI= + +Name: system/bin/mm-venc-omx-test720p +SHA1-Digest: bhlK0w71+8orkuJV3R4wcwdhmuo= + +Name: system/bin/content +SHA1-Digest: PyF7E/iuWk4+agaPGfAomR/pre4= + +Name: system/lib/libFFTEm.so +SHA1-Digest: XP8nHO95883H6AqL5yYOLWRETFc= + +Name: system/bin/date +SHA1-Digest: PPXSdz4sEw5eZGPAdLJAqjoYN2A= + +Name: system/lib/hw/sensors.m7.so +SHA1-Digest: NtZAVC8zlOYhHlLLJ90WsRC55X4= + +Name: system/usr/keylayout/Vendor_05ac_Product_0239.kl +SHA1-Digest: aBBF8yCxbsyLsypxLAxv1OlR2pk= + +Name: system/bin/mm-video-driver-test +SHA1-Digest: IRToKXmHGv2upaAZxYVumUDUJtU= + +Name: system/app/Usage.apk +SHA1-Digest: UKtHxQn0YchgOYNUmNKAzwpTiV8= + +Name: system/lib/libsc-a3xx.so +SHA1-Digest: BIWGF+g3PxChWpt8QIB5qugtpGg= + +Name: META-INF/com/google/android/aroma/scripts/save.sh +SHA1-Digest: vrYK/AoRaZBx+okEOHmUzh0B74Q= + +Name: additions/fonts/klavika/Roboto-Regular.ttf +SHA1-Digest: ciaRq3tsOK/Ke/dK8uZAvJxJE3E= + +Name: system/bin/mm-pp-daemon +SHA1-Digest: tHi1QrgbtQr2H/mW5xEHNIzq8ps= + +Name: system/fonts/DroidSansEthiopic-Regular.ttf +SHA1-Digest: U8h+g8V+6bpPaxzFPXVV+bsYq74= + +Name: system/framework/core-junit.jar +SHA1-Digest: +AAsrrXAwIGmFNCFk5vEusCNIqU= + +Name: additions/fonts/segoewp/Roboto-Bold.ttf +SHA1-Digest: 3h0w/uUFFJnc1ex3BXWL82A8q4A= + +Name: system/lib/libhtccamera.so +SHA1-Digest: ZRFfdutSxi9pqtXtXJ9Yz+Uwn78= + +Name: system/usr/srec/en-US/endpointer_dictation.config +SHA1-Digest: j/ixWk0Vzc1Re76RugKSBPSkHbw= + +Name: system/media/weather/weather_thunderstorm_day.mp4 +SHA1-Digest: yh5iPUYR6jSsntfCorxoFyNs4Mw= + +Name: system/lib/libvideochat_stabilize.so +SHA1-Digest: txEUDS8EnRRlhU8NCE9ldcIfoOo= + +Name: additions/gps/south_america/etc/gps.conf +SHA1-Digest: 5GwTcGELf4z+xgYvn8fwD8bHP28= + +Name: system/lib/libmode10GLES20.so +SHA1-Digest: 5qSsIGqZhUNnNVJsgSXl6bXH5pQ= + +Name: system/media/audio/alarms/Celedon.mp3 +SHA1-Digest: pvg9awAINiFozX4Zov4xCO6VAIs= + +Name: system/app/HtcDialer.apk +SHA1-Digest: gZOejpO+sizM2ZkWaEaCeqfok5k= + +Name: system/lib/libchromatix_ar0260_zsl.so +SHA1-Digest: 9yno7wqwASdnJJNIG+JXnzwLaJg= + +Name: system/tts/lang_pico/it-IT_ta.bin +SHA1-Digest: t4tHCovvvrsnb4fc09cpVofPZOk= + +Name: system/bin/newfs_msdos +SHA1-Digest: KGdqAutaCs2PvkI4hG1nBQztpc8= + +Name: additions/fonts/sonysketchef/Roboto-Bold.ttf +SHA1-Digest: sta2G6y77yNSNg0upEmuXR4etKc= + +Name: data/app/com.google.android.gm-1.apk +SHA1-Digest: 4VBgzK9eIDMwgPYR4rbTRxJBIBU= + +Name: system/media/GPU/twoToneMaskH.bmp +SHA1-Digest: xWeWCFQ1Rp/R0fFb01M4TfLoY4Q= + +Name: system/app/Prism_AppUpdate_DummpPackage.apk +SHA1-Digest: AbCLTuM3f+iqnTX7E5lyDeaYpi0= + +Name: system/lib/libWVphoneAPI.so +SHA1-Digest: NeRHbPbXB5A6ls7y00dXUSefc7A= + +Name: system/etc/security/cacerts/aeb67534.0 +SHA1-Digest: ud63QfbrYmZs4yriaRbj9lIsun8= + +Name: system/etc/permissions/android.hardware.sensor.light.xml +SHA1-Digest: Pn0I13jrVn51nOyc4S/jiw/Xw6U= + +Name: system/lib/libchromatix_ov5693_preview.so +SHA1-Digest: 4gO38ZvRB8WqQ529SAwNcR1skl4= + +Name: system/app/HtcMusicEnhancer.apk +SHA1-Digest: kOcVPJp2lU3zbl2m21pJxL3r2T4= + +Name: system/lib/libmmmpo.so +SHA1-Digest: lpU59utd0Fadlo6fAtcN8c5oiJY= + +Name: system/media/audio/ringtones/Silver.mp3 +SHA1-Digest: cGHQTgTlkDHF4UwqLsZeuwyGB7U= + +Name: system/lib/libqmiservices.so +SHA1-Digest: EBsoJ0M6eLF3bAtpFzsLsR/1vPw= + +Name: system/etc/tfa/playbackbeats_l.preset +SHA1-Digest: Q0TZIziqcpclRmObniL1er8Got4= + +Name: system/lib/drm/libhtcomaplugin.so +SHA1-Digest: nMHqmgZFRAdNMAyEUgnuqpMWt1M= + +Name: system/lib/libimage-jpeg-dec-omx-comp.so +SHA1-Digest: 4DYGsXK/zOcrrlcdIAAsytw8vOE= + +Name: system/media/audio/notifications/Pine.mp3 +SHA1-Digest: 2THq5LMbYiDNI3m/yKRU9AB3RZU= + +Name: system/lib/libdmt_native_utils.so +SHA1-Digest: FX1lbng++9Gs8DDpIPaD3MLwUyE= + +Name: system/app/IMEXT9German.apk +SHA1-Digest: l11AQTg8B1cbRf1hG0kwe1AuR3o= + +Name: system/etc/security/cacerts/ed62f4e3.0 +SHA1-Digest: KW0dSbYbK/i9Crtcd9f/fVpSbDE= + +Name: system/bin/uiautomator +SHA1-Digest: EiHYAGH42TXmzxcRoUP3lkgEJMg= + +Name: system/bin/mm-video-encdrv-test +SHA1-Digest: f+KGvutmd/M+bw3AXIFQHb5zJdA= + +Name: system/media/audio/ringtones/Plum.mp3 +SHA1-Digest: RsGgQnEXfp+mFtCBZv9euT6b2dg= + +Name: system/bin/chown +SHA1-Digest: TrfLtV+viHMlpIimA1jIFQk3rCo= + +Name: system/app/MusicVisualization.apk +SHA1-Digest: llgR8WcTKjQ8knsmvNnraI/Iw9c= + +Name: system/etc/tfa/tfa9887.patch +SHA1-Digest: suMmSifogGempOYsW+xvvM+nBdE= + +Name: system/etc/security/cacerts/f61bff45.0 +SHA1-Digest: T+qB4/2WaUuV16PYtu7WwP3b0gE= + +Name: system/app/HtcLocationService.apk +SHA1-Digest: ul5Mizp1t3enKMj1cWeIRMoN/cQ= + +Name: system/fonts/RobotoCondensed-BoldItalic.ttf +SHA1-Digest: V7BP9MVj0P5pYIh0SmIaP/EMkQo= + +Name: system/etc/image_ibeats_v2_2vol.bin +SHA1-Digest: DnSL6Klxjoag7verZXjNCDqzDj4= + +Name: system/lib/libC2D2.so +SHA1-Digest: ZCQi1vZcYcKqfr+D5Uy17McH0v8= + +Name: system/lib/libhtcirinterface_jni.so +SHA1-Digest: p8EX57AmrP/L05qron9CBCOQ9iY= + +Name: system/customize/resource/quicklaunch_23210.xml +SHA1-Digest: Xu2aZuMkhrIRc7N0FElEaawAhBk= + +Name: system/media/audio/alarms/Beige.mp3 +SHA1-Digest: txglnjYcfUj6COkbCo2mlNMPxHI= + +Name: system/app/HtcCarGps.apk +SHA1-Digest: tEPFkAklXgA1Ka7VkDX+k/yFSiU= + +Name: system/etc/image_ibeats_solo_v2.bin +SHA1-Digest: v9Db4C6c+YeDp85uSvMWuN9hB6k= + +Name: system/lib/libOmxMux.so +SHA1-Digest: 7Yx11FnrxVUdIKiE92B/Jw4tG7Q= + +Name: system/bin/sensorservice +SHA1-Digest: 6iATkATjNRNF3YHr2F3U819IXzY= + +Name: system/fonts/DFHEIA5A.ttf +SHA1-Digest: 84Z3W6Q+eumM70rJDS/uGptCPHs= + +Name: system/usr/share/partials/partials.dat +SHA1-Digest: UTJxbMVvrG6dkhTB7qqPAN/2Cig= + +Name: system/usr/keylayout/Vendor_046d_Product_c294.kl +SHA1-Digest: FEu4tbv/pfG+jZWhYQQVPaclr8Y= + +Name: system/media/audio/ringtones/Snow.mp3 +SHA1-Digest: LZFG5uLY6WL/LSg29j69+5m2/g8= + +Name: system/lib/libstagefright_soft_h264enc.so +SHA1-Digest: AqeRtQnbC7K82K+2DfxdLslutso= + +Name: system/etc/init.goldfish.sh +SHA1-Digest: D3Ehu4SxtQQqVaZr1ifP/Prf93E= + +Name: additions/gps/north_america/etc/gps.conf +SHA1-Digest: DCebaPJa7hDrT9/6c1vxQyBkLFg= + +Name: system/app/Weather.apk +SHA1-Digest: L9Ok6edL+yV02GdlwcoZ5753Wc4= + +Name: system/lib/libchromatix_imx135_default_video.so +SHA1-Digest: /gfdOKFRcBuhF0K4aCFndg3O/HY= + +Name: system/lib/libthread_db.so +SHA1-Digest: vPJCBwzilN8TWjh4QlIOZZGMM+M= + +Name: META-INF/com/google/android/aroma/themes/sense/button_press.9.pn + g +SHA1-Digest: nL1yytK4nOHkeUrWs1fCO28OGzg= + +Name: system/bin/vdc +SHA1-Digest: oWcoYQLY9XoiTX2nLFqCZi6pkTc= + +Name: system/lib/libpagecurl.so +SHA1-Digest: z50tWJsW7DesATjOuO24BsPrm2o= + +Name: system/bin/qmiproxy +SHA1-Digest: DfDijwSciHTPbuAF2CZo7p8XPvI= + +Name: system/bin/getprop +SHA1-Digest: z4G855jswNjE/BhwYD7VGBBU2NE= + +Name: system/fonts/Roboto-BoldItalic.ttf +SHA1-Digest: b18bhiBhpPwzpvMDiEeVWLwx6Uc= + +Name: system/etc/security/cacerts/f4996e82.0 +SHA1-Digest: NFib+Gt/85AoEla6GdaHBKkqcA0= + +Name: system/usr/srec/config/en.us/grammars/phone_type_choice.g2g +SHA1-Digest: KPYJAVJTCr7vOBWM2qlErKU+otg= + +Name: system/fonts/Roboto-Light.ttf +SHA1-Digest: bpJiUAPuXulTMdeRsm1UuaCcnMo= + +Name: system/media/audio/alarms/Twilight.mp3 +SHA1-Digest: WY84OgsIc96QeCRipngQiDcvKIw= + +Name: system/app/Calculator.apk +SHA1-Digest: Y2oHvYw12kY2c60gWdc0ITN0SoY= + +Name: additions/gps/south_africa/etc/gps.conf +SHA1-Digest: NcoJGKFFd14LXP+sW0Syurx5VGY= + +Name: system/lib/libchromatix_s5k3h2yx_zsl.so +SHA1-Digest: JZkJ++64ERD5Z3lor9fiZMY2VXQ= + +Name: system/media/audio/notifications/Jasmine.mp3 +SHA1-Digest: 3VQZdT2cVc4F9VbbE6UGWrNgDcU= + +Name: system/usr/keylayout/Vendor_046d_Product_c216.kl +SHA1-Digest: 334eygJ7+pqLeyMJvz5L56ffVVY= + +Name: system/lib/libloc_eng.so +SHA1-Digest: IApohNePX8MPvlm/gKwaJOPR0Tk= + +Name: system/lib/libzeroeditor_jni.so +SHA1-Digest: omMS7BKsEHBPyt56nwP23MCMTWg= + +Name: system/lib/libmmjps.so +SHA1-Digest: FlJ5Yp/HRCr11TFCE/RUV94PM4k= + +Name: system/etc/tfa/video_l.config +SHA1-Digest: jWakpYCv2zkvgmSaBkeSMTiqNdM= + +Name: system/media/audio/ringtones/Ao.mp3 +SHA1-Digest: PQK7ZTe7oPTgTmPnk2JuYVHGXeY= + +Name: system/etc/tfa/playback_l.eq +SHA1-Digest: 5LAtUXn6Eyj3WC3JlRhpzZ/35Ng= + +Name: system/fonts/Roboto-Italic.ttf +SHA1-Digest: 5ipbgj463XjLbp5Mgkaxo9XZCDs= + +Name: system/media/audio/ringtones/Icterine.mp3 +SHA1-Digest: /wptp4Gq4I6FcOVl6kqAtJLvhWs= + +Name: system/lib/libbcinfo.so +SHA1-Digest: chlT4uOARA9QrhGj43rzh3jo6R4= + +Name: system/lib/libnfc_ndef.so +SHA1-Digest: 0c3Dddj4fbYCs30w0IFCcJNctBQ= + +Name: system/bin/notify +SHA1-Digest: rTWUwJn9oHB892gzXMc16hvae6U= + +Name: system/customize/resource/quicklaunch_420.xml +SHA1-Digest: JlAaOAkZTmVWQAl0p9WK6Y59IKc= + +Name: system/customize/resource/quicklaunch_21404.xml +SHA1-Digest: 1gtunsQsyygzOMyBCBKj/RVaKog= + +Name: system/etc/tfa/ring_l.preset +SHA1-Digest: +F37yHZP90FckmptjVvkAEKcJiE= + +Name: system/lib/libmmosal.so +SHA1-Digest: MuJA+Qi6+d26prR5vNGsT85ZPbU= + +Name: system/etc/tfa/playback_l.preset +SHA1-Digest: GULLLq6MoArA2166ns11ra2LXp4= + +Name: system/framework/com.orange.authentication.simcard.jar +SHA1-Digest: KYr204+jv13+8h2lS3qJVXf+3/o= + +Name: system/media/GPU/dot_mask_0.bmp +SHA1-Digest: ag0Fq3nt+YKQ74CbgAGPRZpR4J0= + +Name: system/app/IMEXT9Serbian.apk +SHA1-Digest: xbyby2PkrqtB3HAGCJBPS8EZSd8= + +Name: system/etc/security/cacerts/74c26bd0.0 +SHA1-Digest: JPSZvZ3Tx+8fME4kV3U1NQInDwk= + +Name: system/lib/libalsa-intf.so +SHA1-Digest: URj08O9p2YfgSgq5WSOY665/d8g= + +Name: system/customize/resource/icon_launcher_mail.png +SHA1-Digest: ktCYh5h+5iWLP1r1Z6Z8alABXaw= + +Name: system/lib/libOmxVenc.so +SHA1-Digest: cXe/TqyWZDyptEuz9wL+m8OCT3c= + +Name: system/bin/rtspclient +SHA1-Digest: 2YHz3OJkGrzvule+bJnu11xwNN0= + +Name: system/framework/com.playstation.playstationcertified.jar +SHA1-Digest: FrfFys+jI//GV1lOK2lpJiUYcv0= + +Name: system/fonts/Lohit-Kannada.ttf +SHA1-Digest: qHTrL92TrDbIdXwjer7+zqQUZf8= + +Name: system/usr/keylayout/synaptics-rmi-touchscreen.kl +SHA1-Digest: m5ofoFqImJCHzLiS6dJEgE6OlRg= + +Name: system/lib/libutils.so +SHA1-Digest: HjaAyeXA2S0jyVVbuMBQJlqqYs4= + +Name: system/lib/libc2d2_a3xx.so +SHA1-Digest: GaBWy1TM2uDZMwHJwIs0C7oAZQ0= + +Name: system/etc/tfa/video_l.preset +SHA1-Digest: XZ+MlvUOVl9GLYT8SwnELn0W+z8= + +Name: system/xbin/dexdump +SHA1-Digest: DjHijikQSM1xS5/1fnUy6DNUN8Y= + +Name: META-INF/com/google/android/aroma/icons/apps.png +SHA1-Digest: Zk3Qpx7ckFAxEptOqb7dNE8H5Eo= + +Name: system/app/MediaUploader.apk +SHA1-Digest: GcIaJ12HGP/78kaXOiG3tLUvftg= + +Name: system/etc/security/cacerts/a2df7ad7.0 +SHA1-Digest: RjuHalVKlyJZTzlSUI6VbkP70KU= + +Name: system/app/IMEXT9BahasaIndonesia.apk +SHA1-Digest: AlIJ8Iayp3+++2u3NTW5RIq2vIU= + +Name: system/media/weather/weather_hot.mp4 +SHA1-Digest: 1/Bzu8Of0SzR+HJB21HfMOVataw= + +Name: additions/camera_4.2/lib/libjni_mosaic.so +SHA1-Digest: Zv0SR3lCdDUVMNHKxmE9n8oGiPI= + +Name: system/app/GenieWidget.apk +SHA1-Digest: z+W0UnPRAxfnRwcVSgyKl6byn6I= + +Name: system/etc/security/cacerts/a7605362.0 +SHA1-Digest: Z0AbnajZ3GPkGwTegW8+BCjdbFI= + +Name: system/usr/share/partials/partials_A_bb.csv +SHA1-Digest: tvd7LYflGgVMWsB919FkEVJrPzs= + +Name: system/etc/security/cacerts/56b8a0b6.0 +SHA1-Digest: BbeXAaF1+TrUH67tzOrpG2PoDbM= + +Name: META-INF/com/google/android/aroma/icons/install.png +SHA1-Digest: wumpyMrgwC25f10MrBJ2W1MnF2s= + +Name: system/customize/resource/icon_launcher_hotmail.png +SHA1-Digest: lMcd7sRaou47W+UVAGdK/RDoy8M= + +Name: data/app/com.google.android.youtube-1.apk +SHA1-Digest: Ctg53ZZS/YBx1d7B7eu66psmuwo= + +Name: system/lib/addict.dat +SHA1-Digest: D7FAhoXfMRz2YXQ4GYk2ELF0MHo= + +Name: system/lib/libnativedocviewer.so +SHA1-Digest: l9Z8+bRQs9H6rSIrpapUgoyPq6c= + +Name: system/media/GPU/CurveSepia.bmp +SHA1-Digest: ZejsYRyq+WQjBq0RzqkGT0nxA4Y= + +Name: system/bin/netsharing +SHA1-Digest: gcFLn/w8oetZXVCoQNuc+hQBOGw= + +Name: system/app/Phone.apk +SHA1-Digest: FaakWN7ffUTcgaBopUNX3yiT4dA= + +Name: system/media/zchgd/charging_04.rle +SHA1-Digest: dOSxjb6Cm7yRboOF3ohM3RySLsw= + +Name: system/lib/libchromatix_ov8838_zsl.so +SHA1-Digest: j252XxBe46QzAO0A504mkDM/Le8= + +Name: system/app/PureC_ApplicationsProvider.apk +SHA1-Digest: oZWU6jAUb7b/wK9Mp+1R407wYUQ= + +Name: additions/fonts/ubuntu/Roboto-Regular.ttf +SHA1-Digest: wuI0G6Y816DgS7XtXxCYzEWQDyM= + +Name: system/lib/libbluedroid.so +SHA1-Digest: jdOd3wszmJPIirQPqfavNqA8FmE= + +Name: META-INF/com/google/android/aroma/requirements.txt +SHA1-Digest: Rohd883z51SfKNiUGz8Yu/xk/sc= + +Name: system/customize/resource/allapplication_21408.xml +SHA1-Digest: 4F2ptWc2oWGSU1g8OiVmZhU1s+E= + +Name: system/fonts/DroidSansMono.ttf +SHA1-Digest: c95nnXS8f3Ki6JMBrBxt2DG/pB4= + +Name: system/framework/android.policy.jar +SHA1-Digest: Ufq+iNGNjOZzYUnKDu7S4cIW5q0= + +Name: system/lib/libHTC_DIS.so +SHA1-Digest: 8EvgK+H8mHa+tx8131mKhZpwInE= + +Name: system/customize/resource/quicklaunch_21407.xml +SHA1-Digest: 5LrDADj2+VcxMPEOMe83X0srzek= + +Name: system/lib/libdsi_netctrl.so +SHA1-Digest: E2t1cPdZBHDFbRSyjWq+uQgrzoo= + +Name: system/etc/security/cacerts/7a481e66.0 +SHA1-Digest: Qrug23rc7GLUystiW+B7d4bzaJw= + +Name: META-INF/com/google/android/aroma/themes/sense/button_focus.9.pn + g +SHA1-Digest: StAvalhPxNmH70D4vXRIHmO6ASU= + +Name: system/lib/libnotesprovider_jni.so +SHA1-Digest: V3IY2du9sl/h7ESQH9spJ8Z93vI= + +Name: system/media/GPU/dot_mask.bmp +SHA1-Digest: 3O94/Rp7XSC2nwJfLxNRRuPcZ08= + +Name: system/app/IMEXT9Danish.apk +SHA1-Digest: iaQ08LYCLXAi4Lbn2UDfKrXu1Vc= + +Name: system/etc/security/cacerts/5a3f0ff8.0 +SHA1-Digest: ZHheT+DD2seVYhDReWK8HQa1FoY= + +Name: system/app/WifiRouter.apk +SHA1-Digest: 3bRUJFeCNFy33tKT8zRQB65qL00= + +Name: system/media/audio/ui/KeypressStandard.ogg +SHA1-Digest: WSD7VCgtBBhkGoFGei4G/W0G3Kw= + +Name: additions/fonts/ubuntu/Roboto-Bold.ttf +SHA1-Digest: g30zOU7f6Pdfabgd91hK6ajDgVA= + +Name: system/lib/libGLESv1_CM.so +SHA1-Digest: 0kcTNT8GRMG9AKHtn9nDyE0FZbk= + +Name: system/lib/libeffects.so +SHA1-Digest: LvAbIGjxHSCSV3rnyBDTdLQfztg= + +Name: system/app/IMEXT9Slovak.apk +SHA1-Digest: RIsbdqmAgNZZ2lKqjceaAdpEYYw= + +Name: system/lib/libmmcamera_image_stab.so +SHA1-Digest: BUX1fzicFOtz4r+pOF7nnWZVNaY= + +Name: system/etc/security/cacerts/e48193cf.0 +SHA1-Digest: UXw27ZZFF2Dc7iZjui9EOHuDgpQ= + +Name: system/etc/security/cacerts/4d654d1d.0 +SHA1-Digest: RiffZAyYlk3Z5RE5r3Eimp4hoCQ= + +Name: system/lib/libchromium_net.so +SHA1-Digest: dKicHajqfxlnMy5+E3lkV392glQ= + +Name: system/lib/libdrmframework_jni.so +SHA1-Digest: mxmw4qMThZTp1ISQA7/Zv4dhOlw= + +Name: system/lib/egl/libGLESv2S3D_adreno200.so +SHA1-Digest: yKrF37f31+7nk6dPn6o1tmOOKt8= + +Name: system/customize/resource/allapplication_27205.xml +SHA1-Digest: dHEgc+kr2e2cfpg63/GdSSMLFks= + +Name: system/media/zchgd/error.rle +SHA1-Digest: 4QY+gkSiSwxpDnYvfNqpERxsSc8= + +Name: system/lib/libchromatix_ov2722_zsl.so +SHA1-Digest: x8VXF9/c4j6iDwEERrseVcV3TGs= + +Name: system/fonts/Roboto-LightItalic.ttf +SHA1-Digest: /WLukeHzJHHKYaWWlSfU7iLz6Ug= + +Name: system/lib/modules/qcedev.ko +SHA1-Digest: xXBoXivuETB8J7IGCAWdcjPqU6U= + +Name: system/app/Automotive_InternetRadio.apk +SHA1-Digest: WPeYPFDAcVZM9QV+sR0XpevabFI= + +Name: system/app/FlexNet.apk +SHA1-Digest: UnPV413Umm3CpBCiHkhvutPo8Ng= + +Name: additions/fonts/sonysketchef/Roboto-BoldItalic.ttf +SHA1-Digest: dXgXv+z3vAUFYteuuYcX71L5ETo= + +Name: system/etc/permissions/android.hardware.telephony.gsm.xml +SHA1-Digest: VedgY17d+3Q4Wvr4BUBh8n6kIt4= + +Name: system/usr/share/partials/partials_A_gr.csv +SHA1-Digest: /n9Urmy7jVo/AGrw22Fh4RAv0gc= + +Name: system/customize/resource/wallpapers_b_03.jpg +SHA1-Digest: dFczPlC3dQas2UTFBN2X5h1G2Qg= + +Name: META-INF/com/google/android/aroma/ttf/Roboto-Regular.ttf +SHA1-Digest: 44m+VfT30MwizlyBK13EzrelmyY= + +Name: system/etc/firmware/lscbuffer_rev2.bin +SHA1-Digest: oee0bMCVNFyjMOeZqtb5Go6U0ho= + +Name: system/framework/HTCCommonctrl.jar +SHA1-Digest: QAWIw4tIgHuSFb5YVTfWkhTPwgM= + +Name: system/media/audio/alarms/Chartreuse.mp3 +SHA1-Digest: MBQlhEXTTaIX9ASLApP3V3juhxo= + +Name: system/etc/searchabledb.conf +SHA1-Digest: S5y/v4ny4JTeqbtLO0+RgkxoacA= + +Name: system/app/LinkedIn_Fsplugin.apk +SHA1-Digest: LqIqPYolDj505Mw8JCbo9NBakyI= + +Name: system/media/weather/weather_snow_night.mp4 +SHA1-Digest: eALDZ5DDW0sZpO09jQoEKI33GIA= + +Name: META-INF/com/google/android/aroma/icons/default.png +SHA1-Digest: Yhs0q06XbKp0vJUs91GNf1iJJjM= + +Name: system/media/audio/ui/Volume-3.flac +SHA1-Digest: oesbXHtU6zkl91dasm+wDrAqk98= + +Name: system/media/weather/weather_l_snow_night.mp4 +SHA1-Digest: sTLivo4tZrqfKJQ687oiIvGMzIU= + +Name: system/etc/security/cacerts/ab5346f4.0 +SHA1-Digest: JR31iZjUtae696itSOA/gRp+YY0= + +Name: system/customize/resource/quicklaunch_26003.xml +SHA1-Digest: eCqFT9mQwBYwsexrenDL+hgEq9c= + +Name: system/etc/security/cacerts/c215bc69.0 +SHA1-Digest: n3bzg8K5bD8w4yGFJSki+vVIDiw= + +Name: system/etc/security/cacerts/6fcc125d.0 +SHA1-Digest: dxoW8n5icyMm+Np/IAxgMBCnnt8= + +Name: system/lib/libcamera_client.so +SHA1-Digest: nZNA0I4cbZVXDUGO7/lGs7YDGbQ= + +Name: system/app/IMEHWRPenPower.apk +SHA1-Digest: EOVTOqTPWCK/B+RbLU20PS7UTpA= + +Name: system/lib/libNewTimeBreakin.so +SHA1-Digest: jLtJv7uQXFMse2QEiR50MxYQaS8= + +Name: system/etc/bluetooth/network.conf +SHA1-Digest: crKuOFEm+RBwaID7QozPTtbB6YY= + +Name: system/media/audio/notifications/Peach.mp3 +SHA1-Digest: 7XPoBTFTNcWHlmUFXG88WTBEzdc= + +Name: system/etc/security/cacerts/7d3cd826.0 +SHA1-Digest: 9A93UolYEp2zLqOTDQS6H+32euM= + +Name: system/bin/bootanimation +SHA1-Digest: WIf2qfyvaymeBbRa/QfqcDShmGU= + +Name: system/app/HTCSetupWizard.apk +SHA1-Digest: RBoywLBY4YNJLdr7+bh0N1u51lM= + +Name: system/lib/modules/reset_modem.ko +SHA1-Digest: KoazTbClyBu4PoR4uYCTCBIXRRI= + +Name: system/customize/resource/wallpapers_a_06.jpg +SHA1-Digest: U/n8WL22D0JlovZwc2nadcaf0yI= + +Name: system/lib/libnetlink.so +SHA1-Digest: jWveqHbWqI3y2/+uYDfmK7p3R1w= + +Name: system/media/audio/ringtones/Aero.mp3 +SHA1-Digest: c6wbkxr7eg01qydYj/FDWzetiZQ= + +Name: system/lib/libwfdsm.so +SHA1-Digest: oiar2HEK1wgfvtfU/LGzFxeAkcQ= + +Name: system/framework/com.android.location.provider.jar +SHA1-Digest: t8pRLzCXgm0n9b5u5NCaqOLH/P8= + +Name: system/bin/flash_camera +SHA1-Digest: h7mzWBfoTG96QT7sKefJ3Gnxtrc= + +Name: system/etc/firmware/tzapps.mdt +SHA1-Digest: pO2z0RNhw36QckT77RaDpqfO1AY= + +Name: system/media/audio/ui/VideoRecord.ogg +SHA1-Digest: op0jkXcHGjUiRs4Ps9209mGlsNE= + +Name: system/usr/srec/config/en.us/dictionary/basic.ok +SHA1-Digest: jtEEAE60jUZP6V7Rz23Hu8XXsMo= + +Name: system/bin/screencap +SHA1-Digest: sp32egnkI9v6643+kB/clgBXnpc= + +Name: system/customize/resource/allapplication_24007.xml +SHA1-Digest: LXs6oMVyHiFgB+3JJh5c3mTmehA= + +Name: system/lib/libalmashot-clr.so +SHA1-Digest: qTetNE+Fv/XMNLWx/V8J+q9WXfM= + +Name: system/bin/radvd +SHA1-Digest: nS+OsUl5EglEotSm4cHPFQq6OWA= + +Name: system/etc/security/cacerts/594f1775.0 +SHA1-Digest: b8fylO1vYs50OMpD7EuUt+mZmQs= + +Name: system/app/HTCSyncManager.apk +SHA1-Digest: TtUnTimsyXFl0rWogBrqpq/0z/8= + +Name: additions/fonts/asap/Roboto-Bold.ttf +SHA1-Digest: V4dKj2LU73Tfslr8kvC160T9pdo= + +Name: system/bin/bridgemgrd +SHA1-Digest: Dph+C9/+nJbwip5I9h0YioIGSy4= + +Name: system/usr/srec/en-US/clg +SHA1-Digest: M1NeTS6D64i9L1/b+048/LDqKe8= + +Name: system/etc/security/cacerts/2fa87019.0 +SHA1-Digest: RI7spWByA4m8BiATKQhVCZPh1kg= + +Name: system/app/Idlescreen_Base.apk +SHA1-Digest: mrnftpKmMyeemqLyLRvlNc3Bgok= + +Name: system/etc/thermald.conf +SHA1-Digest: ShcUv8dFRGpmiR3HPmLIuaYVsis= + +Name: system/etc/event-log-tags +SHA1-Digest: W0Oja3PYmai+SyVOi9tXyi3WYYE= + +Name: system/bin/mm-qcamera-testsuite-client +SHA1-Digest: 9BA2kenPlvvGn5+nafrWhkb7uMI= + +Name: system/etc/calibration +SHA1-Digest: XN6cTQaTuXiZubymE7rO1sZuLos= + +Name: system/fonts/DroidNaskh-Regular-SystemUI.ttf +SHA1-Digest: bwVSgcJ3NdZfsnHmCZ2QrM7zjB8= + +Name: system/app/IMEXT9Greek.apk +SHA1-Digest: 6cL7jr3h3HFGe0CN2GVxLBuLtLI= + +Name: system/usr/keylayout/Vendor_22b8_Product_093d.kl +SHA1-Digest: 94UqYM02uQuqPT7U58C9UD8Plaw= + +Name: system/xbin/busybox +SHA1-Digest: 8E/3tj8N2azeeWgsnWOtitpoXR8= + +Name: system/lib/libchromatix_ov2722_preview.so +SHA1-Digest: ZsHx9LcvmZgp6rVa4LAeHB0Ver0= + +Name: system/app/Twitter.apk +SHA1-Digest: wve6Tcoo2Jcf+orWhjRDoeE6sBA= + +Name: system/etc/permissions/android.hardware.sensor.compass.xml +SHA1-Digest: PruFWW+ufsGh/T3LCec2MGlHPeA= + +Name: system/bin/mm-jpeg-enc-test +SHA1-Digest: e/wL022CV/Q6itXE78UvZbKx5ps= + +Name: system/etc/security/cacerts/fac084d7.0 +SHA1-Digest: kVbZi1tMnjKCdaDIG1+QC0uymEk= + +Name: system/lib/libqmi_cci.so +SHA1-Digest: ourvnfDszP3F5L9EkgF7EocjTLw= + +Name: system/usr/srec/config/en.us/models/generic8_f.swimdl +SHA1-Digest: OUQtGxyzBG46RkofSQn8ez34OlE= + +Name: system/customize/resource/icon_launcher_gmail.png +SHA1-Digest: lUDKBTZUS81T4wP9tWC9ap5ch5U= + +Name: system/bin/usbhub +SHA1-Digest: vNgBg+PGdm7KUSyxNl0KmHFfYMA= + +Name: system/bin/vold +SHA1-Digest: hNTtIgGtMZGRnow9UmwvEHZQE0A= + +Name: system/app/Watch.apk +SHA1-Digest: iXG5DzpfZX3OCdQlRfnWUW5TNHw= + +Name: system/usr/keylayout/projector-Keypad.kl +SHA1-Digest: 3Ti3XtXwuJ1ydUUHapHUPYRLQZo= + +Name: system/app/FaceLock.apk +SHA1-Digest: NuhH6Nrj9YmtE/+I9tcS1qZx6cs= + +Name: system/fonts/RobotoCondensed-Regular.ttf +SHA1-Digest: mB9hDORpS3N2Odl07kEleF5SRy8= + +Name: system/media/audio/notifications/Almond.mp3 +SHA1-Digest: K0J803ByerQfJSjZHZXKlxv9lkw= + +Name: system/usr/srec/en-US/google_hotword_clg +SHA1-Digest: LMFoDJ5AhwQs1sYdBn6Cw/fH1cE= + +Name: system/bin/ime +SHA1-Digest: RpNbbWSd+bvmP5Bk8IPErzl4iN4= + +Name: system/etc/timezones.db +SHA1-Digest: qlHmvXKew9L7FiRRraI6IR23kUE= + +Name: system/media/audio/notifications/Teal.mp3 +SHA1-Digest: vjuO4xWewe4g9SLni1O49s3+UiM= + +Name: system/media/weather/weather_l_clear.mp4 +SHA1-Digest: WLcDczYS8xCr70fWqZ1rSLVxv7Q= + +Name: system/usr/srec/en-US/embed_phone_nn_state_sym +SHA1-Digest: WdfxealU/CvP2D0CmAfrqDt16J0= + +Name: system/lib/libacdbloader.so +SHA1-Digest: /Ar64yl/+gVpOX6DJNrWflhnmj4= + +Name: system/usr/srec/config/en.us/models/generic8.lda +SHA1-Digest: OYQ/W3VpcPHMWi23NHXjTYvQcIM= + +Name: system/app/Prism_AppUpdate_UpdatingScreen.apk +SHA1-Digest: h/aOTRHM0gJyWSV6oznA8PPCmoI= + +Name: system/etc/security/cacerts/ed524cf5.0 +SHA1-Digest: YUUDaE+eI4AQpO1M9Eel4WIxTGI= + +Name: system/etc/security/cacerts/9ec3a561.0 +SHA1-Digest: qRdHoQ5ZrOBV71toEWCbreo7vPM= + +Name: system/customize/resource/quicklaunch_65510.xml +SHA1-Digest: rqyrBJ+PS7IAJaHdd061sYDvkfo= + +Name: system/etc/security/cacerts/7999be0d.0 +SHA1-Digest: Y1fSp79Il7ssJJxn6Hi1lfyqI5Y= + +Name: system/lib/libchromatix_vd6869_night.so +SHA1-Digest: 60qhiT7TfN1d4gt12zxo4GZR6nw= + +Name: system/app/MyPen.apk +SHA1-Digest: ScWpivpwpsel+monzq4g/qaCr+Q= + +Name: system/bin/DxDrmServerIpc +SHA1-Digest: 8dD5qK0EfR3Cv+0yPtp5+KCigRo= + +Name: system/lib/libkeystore_client.so +SHA1-Digest: bl/SgJ77PeH9wMUPo4Esfl64TjY= + +Name: system/lib/libgemini.so +SHA1-Digest: mdFZ/KR9JJ0m2AkPKPeHnpqlFYY= + +Name: system/lib/libz.so +SHA1-Digest: Fs3dZaHzM87UPD3iacqO/uwNoqc= + +Name: system/bin/requestsync +SHA1-Digest: XkE8EJuMNX9lldXnHHdHoskUaeE= + +Name: system/etc/security/cacerts/111e6273.0 +SHA1-Digest: Ws4Pq966Jvp4ZXfGW5/zAefw3Es= + +Name: system/lib/libcneapiclient.so +SHA1-Digest: gA7oWvyOtuGAmYHt2f+GWyhyUPI= + +Name: system/etc/cir.img +SHA1-Digest: jnGPsNcYFTpehrTBOhSUsHTkM9w= + +Name: system/etc/security/cacerts/e60bf0c0.0 +SHA1-Digest: qso/01ui1WfhOpSAedhVrLUBpW0= + +Name: system/customize/resource/allapplication_20210.xml +SHA1-Digest: bg6ngqGb+g4Lb2WVz3eNFX40VKM= + +Name: system/etc/tfa/recorder.config +SHA1-Digest: ykYYK/c2dcBU73ncRP03GbucjOI= + +Name: system/etc/firmware/a300_pfp.fw +SHA1-Digest: pH7SOSDvT0+QoaQLwmjMzdNEEpE= + +Name: system/media/GPU/twoToneMaskV.bmp +SHA1-Digest: 2zakIRZyyu3xXJ1BjXYCfW0Bkhw= + +Name: system/etc/security/cacerts/3ad48a91.0 +SHA1-Digest: HZXjr9IxEdl/bLsWXl0vBzOswmE= + +Name: system/bin/amix +SHA1-Digest: GJXunroM9gUTI/S0TY4o7UUBEO4= + +Name: system/media/weather/weather_l_rain_day.mp4 +SHA1-Digest: st5DdhjDvFtSNyAjdLtQss95hkM= + +Name: system/lib/libmpl.so +SHA1-Digest: 0vf4hGZ+KUPyvaUTJp2YNOVN6R4= + +Name: system/lib/libposteffect.so +SHA1-Digest: lMi3p+1Pqqfkfh2r/N7xD4utEhk= + +Name: system/etc/init.qcom.post_boot.sh +SHA1-Digest: hx6jFq2OrLUDHDL7/ZNJNuKkhmY= + +Name: additions/camera_4.2/app/GalleryGoogle.apk +SHA1-Digest: eXI+kl1iz9x08xyjtcAlh274qo0= + +Name: system/etc/bluetooth/main.conf +SHA1-Digest: 5RkqoQQaXaFMJREY82g5hwcE1PM= + +Name: system/tts/lang_pico/fr-FR_nk0_sg.bin +SHA1-Digest: uJPDIkoo44Xdhg1IvPQ7n+AiG7M= + +Name: system/etc/security/cacerts/3c860d51.0 +SHA1-Digest: 3MirMMMxVPDIjrUJzJT9kQaASwQ= + +Name: system/app/IMEXT9Polish.apk +SHA1-Digest: ViD31OrtgfWeczVelW6U9hVD9Ks= + +Name: system/bin/vmstat +SHA1-Digest: qPoTHrfziBT1aLF78BsObMPg8u0= + +Name: system/lib/libemoji.so +SHA1-Digest: gRBMqCTHrajikXG3qvHtKWdAOWg= + +Name: system/lib/libstagefright_soft_mpeg4dec.so +SHA1-Digest: JwckNPKVzwn+D9RKgnj6/7k3eaA= + +Name: system/framework/framework-htc-res.apk +SHA1-Digest: dL/kBADS3oeD2aweqViA1xq2bKs= + +Name: system/app/SenseTV_Home.apk +SHA1-Digest: OtlHr1JtTra5rIXT0gsERklHiIE= + +Name: system/media/weather/weather_windy_day.mp4 +SHA1-Digest: RD30Nd1OvTGema47qPZKWCcCDrI= + +Name: system/app/HtcAutoRotateWidget.apk +SHA1-Digest: aSqKAV7cKN6cA8SjEE1R0yOrqT0= + +Name: system/lib/libwt6hpprndrv.so +SHA1-Digest: PqILQalRMzCIyJILAUNHxzVHuzw= + +Name: system/media/audio/alarms/Rajah.mp3 +SHA1-Digest: wdkZ5eh29OaTLbvZiektybOsjCo= + +Name: system/etc/PCTOOL.ISO +SHA1-Digest: /hLdJwScogPQLq12OmEg/cXu3y0= + +Name: additions/fonts/ubuntu/Roboto-Italic.ttf +SHA1-Digest: NUvpq8QWMFIJpZk9jrI/Us11tNc= + +Name: system/app/Stock.apk +SHA1-Digest: GrO7UBMjFChYld+DMqFZK8SBNUU= + +Name: system/lib/libsystem_server.so +SHA1-Digest: UnCvIb6pqZLLjjmulWXOyudUbmU= + +Name: system/etc/security/cacerts/9339512a.0 +SHA1-Digest: mQ4WSgNEy6kTq/gCEHGaZMW5sY0= + +Name: system/app/LMW.apk +SHA1-Digest: MFRK/FnyyI5aKLP6wE8/tgQ3Mlw= + +Name: system/bin/charging +SHA1-Digest: a2UWJwJdGPmimWYLnc4sTN5aGY4= + +Name: system/app/IdleScreen_Photo.apk +SHA1-Digest: bfZTpKNfXv/ffNxO5UEvvfCIvRs= + +Name: system/etc/permissions/android.hardware.wifi.xml +SHA1-Digest: oHkBECWfFLtDqANIBIPZoPQ2mkU= + +Name: system/bin/racoon +SHA1-Digest: llJyjXiPfXEnwCmt94BpGyGA3lI= + +Name: system/bin/netstat +SHA1-Digest: KUzhcfJlDVdkejY7AYglLJLTtbE= + +Name: system/etc/security/cacerts/f80cc7f6.0 +SHA1-Digest: W8bDrAuHeemBUG1E6My97G/SuFg= + +Name: system/usr/srec/en-US/g2p_fst +SHA1-Digest: l8/XYD+Shc9RuLVFVZjR/GYc/Us= + +Name: system/customize/resource/allapplication_20810.xml +SHA1-Digest: 41S0C1M7DZXYQ4mmP5w7aSg87No= + +Name: system/app/GoogleCalendarSyncAdapter.apk +SHA1-Digest: PzwMbvQgDD2z0/5nlE/GYFiuGkE= + +Name: system/etc/security/cacerts/69105f4f.0 +SHA1-Digest: jltP5Tn1V+xLjDQLZwAgoHqzxc0= + +Name: system/etc/bluetooth/input.conf +SHA1-Digest: Y/By99uRCUpOsQ7WtQZrnrEoLaI= + +Name: system/etc/image_ibeats_solo_v2_2vol.bin +SHA1-Digest: VgoVxk9+8ojZmlWclTuFKD9a0cQ= + +Name: system/lib/libwfduibcsrcinterface.so +SHA1-Digest: +wLbg7IUzVCW2OEbukzp2uOf70w= + +Name: system/bin/lsmod +SHA1-Digest: AZ+2VohmiVR9xQaVrDBXqxEmonY= + +Name: system/customize/resource/allapplication_23420.xml +SHA1-Digest: CZHdqJr20PAgttOkUmxWoR1Lv2s= + +Name: system/etc/security/cacerts/5cf9d536.0 +SHA1-Digest: EX93MpxobY/BeHpdRW+gBO+pVKE= + +Name: system/app/HoloSpiral.apk +SHA1-Digest: 2SlfN9VMTyZPR93kweAM1I7VxXo= + +Name: system/bin/reboot +SHA1-Digest: /dXywgBL1YWDV3o+cEpCwrLmB8U= + +Name: system/lib/hw/audio.a2dp.default.so +SHA1-Digest: LGyb83q2jGUyuLDLLZP9b346xqk= + +Name: system/etc/firmware/fw_bcm4335_b0.bin +SHA1-Digest: /lJcLfK8cwy7GE8BGUCGA34wQr0= + +Name: system/media/GPU/header8bpp.bmp +SHA1-Digest: ssnGfYivLrVgcmXAPAgseLpV7Bs= + +Name: system/lib/libchromatix_s5k3h2yx_default_video.so +SHA1-Digest: 6ewCy57u4uyD+rnf0t1cbl7ITEA= + +Name: system/etc/tfa/voip_l.config +SHA1-Digest: M1+NT3W/Jlju4Qu5UbGbWRBMoRA= + +Name: system/lib/libstagefright_soft_vorbisdec.so +SHA1-Digest: VPmV56HIERjGd55K7m2T2wagS7g= + +Name: system/lib/libchromatix_vd6869_zsl.so +SHA1-Digest: 4LvUDP0T/e9IiadvtZqAEX5YcuA= + +Name: system/bin/htcfs +SHA1-Digest: 1LWOQTHfhcKFvit2sKy9pXzrq7o= + +Name: system/vendor/pittpatt/models/detection/multi_pose_face_landmark + _detectors.7/left_eye-y0-yi45-p0-pi45-r0-ri20.lg_32/full_model.bin +SHA1-Digest: dwEn0myGUfjd7vy7JX7yh6urTJU= + +Name: system/etc/security/cacerts/fb126c6d.0 +SHA1-Digest: 7lobtNCl//Q03nIbGlcwTyJqJGc= + +Name: system/usr/srec/en-US/rescoring_lm +SHA1-Digest: 3WHFz2o3uGTMAlgIyQ+ZXBCk66w= + +Name: system/customize/resource/allapplication_21403.xml +SHA1-Digest: mPk9sa5nDdZR08spwn/ba9ppttg= + +Name: system/customize/resource/allapplication_23806.xml +SHA1-Digest: 6EyS0LK6bFutLEiv7ArNexEofVU= + +Name: system/etc/security/cacerts/ccb919f9.0 +SHA1-Digest: 7VWT/WcAU6T9mjvE7onES7hpMbc= + +Name: system/etc/init.d/96Tweaks +SHA1-Digest: sf8jHA3f3isYP7kibOFa0E3BuXQ= + +Name: system/usr/srec/en-US/ep_acoustic_model +SHA1-Digest: TRJvr6ElzKlRSjdRODtxGDwejN4= + +Name: system/app/HtcGpsWidget.apk +SHA1-Digest: ab4AVHlWP+1UW/R4oFu/6wCvGPI= + +Name: system/etc/media_codecs.xml +SHA1-Digest: 0SVknIR5QUYdXLP236lVtGwwdSY= + +Name: system/lib/libwfdmmsink.so +SHA1-Digest: PHoy+HDlRdMfDNILGRvVaffhGj0= + +Name: system/etc/tfa/voip.config +SHA1-Digest: DFdN8cNIlzLvqILuqsVDvHJ2+9k= + +Name: system/lib/libui.so +SHA1-Digest: u0aNwBPXeB7lT4wl6k7TFobCy0U= + +Name: system/etc/security/cacerts/19899da5.0 +SHA1-Digest: Wzo6JYKWmTiD3ttZm0h2QNK9HrA= + +Name: system/lib/libfrsdk.so +SHA1-Digest: alZ3crgL13yR0dD68lcHixDzRd8= + +Name: system/usr/share/partials/partials_CW_gb.csv +SHA1-Digest: lsgq0ojgoiKAq3w+Ga7cZFz6JjA= + +Name: system/etc/security/cacerts/bf64f35b.0 +SHA1-Digest: PatpGMTkqlaTNx343GS4IRRAciA= + +Name: system/lib/libchromatix_ov2722_default_video.so +SHA1-Digest: 3zZBMr2Qn9yg3YUmki02ldSHhJs= + +Name: system/lib/libOpenVG.so +SHA1-Digest: 7lwwhQd/M3cqsw1Zx2oWeGvYMTA= + +Name: system/media/audio/alarms/Topaz.mp3 +SHA1-Digest: tj13XPSUlh9+tOQiMkP08fSbeGQ= + +Name: system/lib/libmm-color-convertor.so +SHA1-Digest: tr0uHzgcPD5sPb7wYfH1jcRZQf4= + +Name: system/etc/security/cacerts/ddc328ff.0 +SHA1-Digest: UgwJP9g4O1D5SSYH0ozmn6x/BKg= + +Name: META-INF/com/google/android/aroma/themes/sense/select.9.png +SHA1-Digest: wlV86JXTAm/MyV8VgyAjgNkhNWo= + +Name: system/etc/hsml.key +SHA1-Digest: myTg62oTw70c+xnz2HxdGE5Lsfk= + +Name: system/lib/librtp_jni.so +SHA1-Digest: zTJHUs2o1lxFyT1/xgAdQE9AWlI= + +Name: system/lib/egl/eglsubAndroid.so +SHA1-Digest: RX9770n7xnFXmz1G2ZvdFyGz5Kc= + +Name: system/media/weather/weather_l_windy_night.mp4 +SHA1-Digest: 657X3MoEv7xeFgTDzw+MB3nfQZs= + +Name: system/lib/modules/eeprom_93cx6.ko +SHA1-Digest: kZQU7Hl+wSRN8RNHeHtdrHvjtP4= + +Name: system/usr/srec/config/en.us/models/generic11_m.swimdl +SHA1-Digest: REX20baAUwoqpKFT+1FzKuave5I= + +Name: additions/fonts/comicsans/Roboto-Regular.ttf +SHA1-Digest: tgy9oyM7AJDWdj+Ysl+Gjt3G/8g= + +Name: system/etc/wifi/p2p_supplicant.conf +SHA1-Digest: 7ZLmeR14YO1bqd4WO09fcCYgvN4= + +Name: additions/fonts/asap/Roboto-Regular.ttf +SHA1-Digest: tP27/68ADAWzU6PT53N427dqLz8= + +Name: system/etc/ov2722_1 +SHA1-Digest: BWSHMIN8MNqOqER+L/PzaJZAlQ8= + +Name: data/app/com.adobe.flashplayer-1.apk +SHA1-Digest: Il/alwTzNLQ/ry6hCye+ozoQAdg= + +Name: system/bin/top +SHA1-Digest: UJ+vWLLalE+ev7TFnSCtqOozK7c= + +Name: system/lib/libqdutils.so +SHA1-Digest: AhsH8PCm+47FmKWzqr+HFmQVh+0= + +Name: system/etc/media_profiles.xml +SHA1-Digest: M9W+1pFsmP1X9v/NWljjso3hZ3Y= + +Name: system/app/HtcBackupReset.apk +SHA1-Digest: cultZx34wjobQybrk9QcIuSoWF8= + +Name: system/etc/tfa/recorder_l.preset +SHA1-Digest: cDZJyUVni8/H4BL4PsorzvWhb4Y= + +Name: system/customize/resource/icon_launcher_active_sync.png +SHA1-Digest: 6dZT1LxR08dTeAKPmatUy7gZqqo= + +Name: system/etc/security/cacerts/72f369af.0 +SHA1-Digest: B0FekN7giev0q4MtHFobsMO8JOw= + +Name: additions/gps/asia/etc/gps.conf +SHA1-Digest: 0DgcjLbRiR1zPk6YC3D7Zb3Amqw= + +Name: system/lib/libchromatix_s5k6a2ya_preview.so +SHA1-Digest: F9VqF8QAE8Bsf+GGJRnFox+sgS4= + +Name: system/customize/resource/icon_launcher_yahoo.png +SHA1-Digest: 7PHbmnYtD4Ry1swbRqbqEqbplC8= + +Name: system/media/weather/weather_clear.mp4 +SHA1-Digest: C8aLG84uaZPpRVJkJAebCRu0pKU= + +Name: system/media/audio/notifications/Magnolia.mp3 +SHA1-Digest: X3s4iU4hmGvHAL2OCn0Sk3aADFI= + +Name: system/framework/core.jar +SHA1-Digest: 2pKHl6EISazUBxjavJIurbURdWc= + +Name: system/media/audio/ui/Lock.ogg +SHA1-Digest: Z8fphp0j4uyfkRUuFIB6KHwHc3c= + +Name: system/media/zchgd/batt_50.rle +SHA1-Digest: t2qt0NS6ZF62IfkC+tnuMLV8EVc= + +Name: system/customize/resource/allapplication_232.xml +SHA1-Digest: VXUin3Fw3nyZc16fWYhbeJJaZZY= + +Name: system/lib/libwfdnative.so +SHA1-Digest: FOlqsylhOJt56FzFdKaPz0bxPaM= + +Name: system/framework/ime.jar +SHA1-Digest: KpPJDm4y3Mi0hYsFSRu+GM+1fx0= + +Name: system/customize/resource/quicklaunch_26806.xml +SHA1-Digest: BRXfQf1tcd1rP6BttdWC59jiJwo= + +Name: META-INF/com/google/android/aroma/icons/apex.png +SHA1-Digest: S5fbqhLG8GgJK4i9Zc5iVsYb3JI= + +Name: system/etc/security/cacerts/b7db1890.0 +SHA1-Digest: PnsdiNOuklg1r+/IRDgFBHM0gW8= + +Name: system/lib/libloc_api_v02.so +SHA1-Digest: szbY9rCuP4bXQLWEczs8aZ2f0QM= + +Name: system/etc/security/cacerts/412bea73.0 +SHA1-Digest: 1lSpCLZh5dp3WIcNHNj0NwNm6bE= + +Name: system/lib/libwt6pptxrdr.so +SHA1-Digest: cEFhVkOVzusj/ye5mjuKE5z7Yz0= + +Name: system/app/SharedStorageBackup.apk +SHA1-Digest: fHIKNB27H+tHhpM15YHgjPQlMSc= + +Name: system/lib/libstagefright_yuv.so +SHA1-Digest: grYHAQs0Rr4DIKbeb+YdtLaO078= + +Name: system/framework/modemwarmup.jar +SHA1-Digest: kqOtzrkIcSK7cXO1MMJhbeH3khw= + +Name: system/app/HTCBackup.apk +SHA1-Digest: 4CoJgW0Kdtqt90ZU2Wb5IJQmz/8= + +Name: system/usr/idc/synaptics-rmi-touchscreen.idc +SHA1-Digest: lab85HH2Cs9C40C3y2aLJU4Hpmc= + +Name: system/usr/srec/en-US/c_fst +SHA1-Digest: WbnZvDieUD1i8/vibs9Xx1Wx4sk= + +Name: system/etc/tfa/playback_l.config +SHA1-Digest: gphLjEG4rx+ZzxEvlj/dHj8UHdw= + +Name: system/app/Prism_LocalFeedProvider.apk +SHA1-Digest: 1sIyjmYm24ek/Tj4FPEyx0Ydqs8= + +Name: system/bin/logcat +SHA1-Digest: VRSKwMY83oB/I0FCcjGwxf4x/K0= + +Name: system/bin/mke2fs +SHA1-Digest: zbUy2F9srEcyQS3QrvuA1vWlVkM= + +Name: system/lib/libnotes_jni.so +SHA1-Digest: wpVs1BtCBVFF9lZ0js9no0xdka4= + +Name: system/etc/hltrd.bin +SHA1-Digest: 3sYn8UrJq3ExmZnnBfYJ3vzyUSg= + +Name: system/lib/libspeexwrapper.so +SHA1-Digest: goX7MyYJrrJ5gSf56ChkN/Ecqgc= + +Name: system/bin/dumpstate +SHA1-Digest: gy8GdVjEQLJ+82gNGHOd/pZ5WZM= + +Name: system/usr/share/partials/partials_H_gr.csv +SHA1-Digest: ZNj3aJy8pxjCk1K+8k9xLjgqtNM= + +Name: system/customize/resource/quicklaunch_26803.xml +SHA1-Digest: wanDss5dSktZ68VjA39ekLFTgEI= + +Name: system/etc/AlarmGroupQueueList.xml +SHA1-Digest: YgTUbvgOQwN7obaZlSZ2cCmbNbI= + +Name: system/bin/mkdir +SHA1-Digest: 1EmuA6Ym95jLVFY1N32uhoWkmiM= + +Name: system/app/HtcLockScreen.apk +SHA1-Digest: vJPk3dQCtR/i00t+Sk2Iuuh4rSc= + +Name: additions/fonts/comicsans/Roboto-BoldItalic.ttf +SHA1-Digest: a6Yzf5INecHzMJaCV51iLx2OfNc= + +Name: system/fonts/DroidSansFallback.ttf +SHA1-Digest: AVoIMOYxESTcwCXbQXfPqT6ROIA= + +Name: additions/fonts/comfortaa/Roboto-BoldItalic.ttf +SHA1-Digest: uXQkzJFpt44Ayw/bevVAkl7BLv8= + +Name: system/etc/security/cacerts/1920cacb.0 +SHA1-Digest: jnyFPukRwUWlDtLf5/32Yj9FaSY= + +Name: system/media/GPU/stylizeColorRamp.bmp +SHA1-Digest: qdmxYxbHuskGeAETArT/mtJ6yRQ= + +Name: system/app/DefaultContainerService.apk +SHA1-Digest: LAXeKYGyDZM1vgPxEiZL9Lj3zEo= + +Name: system/app/FilePicker.apk +SHA1-Digest: cpGKX7VtGXH61HkBDH/cjPgOzWM= + +Name: system/lib/libbinder.so +SHA1-Digest: yWzsT645IQXOHeR/IoVs/okpqOo= + +Name: system/app/MyDropbox.apk +SHA1-Digest: JIv1FUdW7r44+WWcUEnfy9nhHJ0= + +Name: system/app/HtcDataRoamingWidget.apk +SHA1-Digest: ugpem+ZpGJT8bGjV5QZ6SbT0OQs= + +Name: system/lib/libmmjpeg.so +SHA1-Digest: 9LGuPJDniFb07i8NyiqMyocx79E= + +Name: system/lib/libchromatix_s5k6a2ya_zsl.so +SHA1-Digest: iSDxGxtJPcgx66KTRKwAEYxY4RE= + +Name: system/etc/security/cacerts/9dbefe7b.0 +SHA1-Digest: yGiY2vyvGY8f13llDmyVgk0uikM= + +Name: system/lib/libalbum_util2e.so +SHA1-Digest: 3tlxqGM8fzYrhYHGeu7RITnkVZE= + +Name: system/etc/init.qcom.fm.sh +SHA1-Digest: vCm0EohH9ulqvdFWI7FYYC++5Ic= + +Name: system/customize/resource/allapplication_65501.xml +SHA1-Digest: FFTUxstTRxw9XRsTlBEhReTzjTs= + +Name: system/etc/security/cacerts/2afc57aa.0 +SHA1-Digest: nPKWafPr4jvpuNF1YPzwOiNGfjw= + +Name: system/customize/resource/quicklaunch_20810.xml +SHA1-Digest: vxVKX7hC4CLQRBkqrFM7Gl05K6U= + +Name: system/etc/security/cacerts/343eb6cb.0 +SHA1-Digest: rYcngakSpBQiNzp/GrZRITUXhlE= + +Name: system/app/HtcAccessoryService.apk +SHA1-Digest: kGpL+dG7PUWa1u5aan36Qbi1c5s= + +Name: system/customize/resource/quicklaunch_23806.xml +SHA1-Digest: 7jPh89tioFJ8eDAwC3lnFhzijmc= + +Name: system/app/CalendarProvider.apk +SHA1-Digest: wb8b9TRUkzs3DxsKppdM90f65fg= + +Name: system/etc/permissions/com.playstation.playstationcertified.xml +SHA1-Digest: PFvZQJi9dc7GlvjjKwSE3aeOs8c= + +Name: system/etc/security/cacerts/3e3744fd.0 +SHA1-Digest: IwRhl/a5N/2khuBeFSvzFoAtwcY= + +Name: system/bin/service +SHA1-Digest: 0R56vXBvoTExxFjripbzoIrjG+A= + +Name: system/bin/ois_camera +SHA1-Digest: 7uPyecBaJLotk93u1xg+FjpYyyw= + +Name: system/media/audio/alarms/Scarlet.mp3 +SHA1-Digest: KH51i/rPPBswEYsBhyAQav7/9+8= + +Name: system/app/HtcPhotoEnhancer.apk +SHA1-Digest: z4fMJ28xdRkC5pi9EZ+kftupN2A= + +Name: system/lib/libI420colorconvert.so +SHA1-Digest: HmVHNdrW7p3KsEbMxb6V2gUwgtI= + +Name: system/etc/security/cacerts/2edf7016.0 +SHA1-Digest: xyC9NTzY91oxJhxlL/1jiDTgB5g= + +Name: system/media/audio/notifications/Regalia.mp3 +SHA1-Digest: P4eaZ4Az8NkQmOffm7TanIQweCY= + +Name: system/etc/soundimage/srsfx_trumedia_movie.cfg +SHA1-Digest: NEa0d9QtPHE6IdLs9LAn9N6KCAU= + +Name: system/app/Automotive_Home.apk +SHA1-Digest: 07Gh1XQED2Rzk4UawmjAnzDaTc0= + +Name: system/lib/libhtcflag-jni.so +SHA1-Digest: 7i7wK/8Mg4/9aLHojbX25v9Be2Y= + +Name: system/bin/servicemanager +SHA1-Digest: 5gMBLDIDuhgiF6IZ0SbP82NeZNI= + +Name: system/etc/security/cacerts/0dbd0096.0 +SHA1-Digest: DYnXLEQ1aXDBnX4A+RfapiTz4nI= + +Name: system/media/audio/ui/KeypressSpacebar.ogg +SHA1-Digest: vJK46s6r2X/zJslrzS0KftDoq2E= + +Name: system/usr/share/zoneinfo/zoneinfo.idx +SHA1-Digest: 7SC0/Qh30fU10nBi4b/Fz+ROgsY= + +Name: additions/camera_4.2/lib/liblightcycle.so +SHA1-Digest: jzz5HoxsxdXYpCF0DL53HaJvmcg= + +Name: system/customize/mns_map.xml +SHA1-Digest: r52y39sn5wathoGFI2MFDf7Ok6M= + +Name: system/lib/libqmi.so +SHA1-Digest: kFnY12RsdkkPQ1IBhOfNfo6wK68= + +Name: system/customize/resource/rp_ce_0682_i.png +SHA1-Digest: WKHDKtKzRMxIzllQrKn7QHFiPrQ= + +Name: system/lib/libvideoeditor_jni.so +SHA1-Digest: DdbChcjps5WaEVLA7+r9eojxZvQ= + +Name: system/media/audio/alarms/Flame.mp3 +SHA1-Digest: gOLjmeuJKqafUwM0Y4j77UifN7U= + +Name: system/etc/RT5501 +SHA1-Digest: yv5GxwCaHTB3Iuzw+w08O+Zymlg= + +Name: system/app/Tube2_Configuration.apk +SHA1-Digest: CdXayply5QHfmKHtXnzRK1GihBc= + +Name: system/lib/modules/scsi_wait_scan.ko +SHA1-Digest: lB6dUM+7kgWnwWkMpgAnMz8T/mY= + +Name: system/framework/services.jar +SHA1-Digest: UGZjsSBuvC5tnK0lyaoemQAxFqI= + +Name: system/usr/srec/en-US/phonelist +SHA1-Digest: S2L0nVL6UG1/1SM58nULzylbpFY= + +Name: system/lib/libchromatix_vd6869_zoe.so +SHA1-Digest: 3/bbKYDuEk4EARUb6HtY2BpHfjA= + +Name: system/customize/resource/allapplication_420.xml +SHA1-Digest: kZtDN2GddbEfYmTQ7MlfPstAQtI= + +Name: system/bin/hostapd_cli +SHA1-Digest: CD1v5Nq4fJ/KE9A7fpUhB+2pk+4= + +Name: system/etc/init.qcom.coex.sh +SHA1-Digest: FR3i7XbfPq4T4S6W4FDXPWHNZ7E= + +Name: system/lib/hw/gralloc.msm8960.so +SHA1-Digest: mSjvOQ3P+ys9zpLuai4ZYJ9u5b8= + +Name: system/lib/libAudioTrimmer.so +SHA1-Digest: 0MjKqcBx3qrGvjWzsFrpRLnCZcA= + +Name: system/media/zchgd/charging_01.rle +SHA1-Digest: JcEiL3zNIXAmvN++fw9RS54Mrv8= + +Name: system/vendor/firmware/libpn544_fw.so +SHA1-Digest: SPf3hp3lircgbMnhTIJJGJYosN4= + +Name: system/lib/libdl.so +SHA1-Digest: VHNK7fGKavNrBoCdYwXERNwPF9o= + +Name: system/etc/tfa/voice_l.preset +SHA1-Digest: kDZMLMLsUEgpp51qMwbQT7teqd0= + +Name: additions/seeder/app/Seeder-2.0.0.apk +SHA1-Digest: NiHREDWwRHkWWFlSu2VkTOAkffQ= + +Name: system/bin/adaptive +SHA1-Digest: pO7YMDfo9BW3zl0PvRFQG54NdeU= + +Name: additions/fonts/ubuntu/Roboto-BoldItalic.ttf +SHA1-Digest: UyQMQ1PxkXqpAlGUP5TtL6qOPZ4= + +Name: system/etc/security/cacerts/b413391d.0 +SHA1-Digest: OlTPiY0ZtV+Jeqnl2ANvTa3BMeU= + +Name: system/etc/tfa/playback.eq +SHA1-Digest: pizpUtQoy5M7h5msVhr8m7aa/cg= + +Name: system/app/Talk.apk +SHA1-Digest: rJA1/6WChLlvHJ9rMKdU4mQirmw= + +Name: system/usr/srec/en-US/metadata +SHA1-Digest: KGPX1W+FZfaR/73RY0nIPfxsrcQ= + +Name: system/etc/libpmhwrl.so +SHA1-Digest: yvWh33yNnurSbPOntunZgVd/icM= + +Name: system/usr/srec/en-US/contacts.abnf +SHA1-Digest: iQQ63Xbl9ApZU2QzQYi80ayVbZA= + +Name: system/customize/resource/quicklaunch_232.xml +SHA1-Digest: C0Wbf6mcqyiDjafHNWbVOG4y96A= + +Name: system/tts/lang_pico/de-DE_gl0_sg.bin +SHA1-Digest: ScYyzXaktqrP2gdGvGwnttbNyVw= + +Name: system/lib/libandroid_simlock.so +SHA1-Digest: RrUW88EdrC4QfM9vyDkH4AypSyw= + +Name: META-INF/com/google/android/aroma/icons/info.png +SHA1-Digest: 7f5jW9mAVWrLoUspbijsj4gAkS0= + +Name: system/usr/share/zoneinfo/zoneinfo.version +SHA1-Digest: 2fI97bQ2ZyWLXtpTWG7caV9Ozzg= + +Name: system/lib/libmmmpod.so +SHA1-Digest: aUBK5VuuHUkVYF7HHt7dVS6Iwmc= + +Name: system/app/HtcVideoPlayer.apk +SHA1-Digest: Y4lFLyW4GQxamswaG3dJdOe7sOE= + +Name: system/media/audio/ringtones/Ocean.mp3 +SHA1-Digest: 6NKT94oqUUipEfUTvM8T6LfN+WQ= + +Name: boot.img +SHA1-Digest: g7fYb8Pd6hOm4ibygeL9DUIXbBM= + +Name: system/lib/libsqlite.so +SHA1-Digest: nEtH1P3X9/MLO9OIw/0WnGZgmBw= + +Name: system/etc/AudioBTID.csv +SHA1-Digest: CInBgnfhK5c1Vy69h8+uTFFhffA= + +Name: system/etc/permissions/android.hardware.camera.front.xml +SHA1-Digest: brba3Lj1cD+5FUB6sCkGYr27DvU= + +Name: system/customize/resource/quicklaunch_24201.xml +SHA1-Digest: ku/al2B9OfkVUz4bPU297LDCiag= + +Name: system/lib/libzeroeditor_core.so +SHA1-Digest: JDlqOefX1qz1+q5THpm6MolCcL8= + +Name: system/etc/security/cacerts/58a44af1.0 +SHA1-Digest: 4NuW5gozKsdwb1kgkbS9CS2AMzU= + +Name: system/etc/permissions/com.cisco.anyconnect.permissions.patch.ht + c.xml +SHA1-Digest: MXR25A+j2qIehrS6brcUqa2Marc= + +Name: system/etc/security/cacerts/1155c94b.0 +SHA1-Digest: Itv/d3FpM7SIr1DMDQhBhUgrq+c= + +Name: system/etc/security/cacerts/12d55845.0 +SHA1-Digest: oaj59fzV/q9qjIGZjotc01lpf9A= + +Name: system/lib/libwilhelm.so +SHA1-Digest: IbWFAO3GkotSFIMURK6uFZL+xag= + +Name: system/etc/permissions/com.google.android.media.effects.xml +SHA1-Digest: j/P++0UEThlMLHb5ewoUXe96pQ4= + +Name: system/fonts/DroidSansDevanagari-Regular.ttf +SHA1-Digest: YAhglQpSW2PkVPPeXBILe0Nx7BA= + +Name: system/customize/resource/quicklaunch.xml +SHA1-Digest: vzq+YJI/lr6aIfQzg+Ej4mqsqKw= + +Name: system/media/zchgd/charging_07.rle +SHA1-Digest: 4dams2U6rz8fcWcxjTBGDR1FL9Y= + +Name: system/app/GooglePartnerSetup.apk +SHA1-Digest: tEU24VZiJ4TLagvbXv/qpXq/9FM= + +Name: system/lib/libclcore_neon.bc +SHA1-Digest: IgUoLVtkK8FeBYy6FgG/wABo8aU= + +Name: system/lib/libclcore.bc +SHA1-Digest: kx7/I5zjVQRa2TbkUZnNjWS5WcQ= + +Name: system/customize/resource/wallpapers_b_04.jpg +SHA1-Digest: 3S4MmJqXQMsLhxttz7cpLNTQVVw= + +Name: system/bin/cand +SHA1-Digest: MCSVuKfLSuwuVc8CbWW88lEqZt0= + +Name: system/bin/lsof +SHA1-Digest: VcpBaMqEtljvrLbnQcKUYtb5AQ4= + +Name: system/lib/libpdfviewer.so +SHA1-Digest: SIhkGxLgJcZb/52Njtz6zHN+cnU= + +Name: system/lib/libmedia.so +SHA1-Digest: a+tYL/WwNQfnUPBMSiYAUDHZym8= + +Name: system/lib/libfacelock_jni.so +SHA1-Digest: iqvINeQDiCl1jyNwRsPVsitKnsw= + +Name: system/lib/libfilterpack_imageproc.so +SHA1-Digest: lkGtHR8jiy7H2H1mhPWCJcb6COo= + +Name: system/lib/modules/bluetooth-power.ko +SHA1-Digest: F6f43/WPUKsM7IZ4r0iSWZxSwHU= + +Name: system/usr/share/partials/partials_H_bb.csv +SHA1-Digest: z2A1DJTbdzcx0lWzn5WWnQU5PnY= + +Name: system/lib/libmm-abl.so +SHA1-Digest: YmVIr6Q4JLSXcblF5d3moILU0/c= + +Name: system/usr/share/partials/partials_CW_bb.csv +SHA1-Digest: H/oAhiLegM5EVK1IX1Y1UQxFpO8= + +Name: additions/fonts/asap/Roboto-Italic.ttf +SHA1-Digest: xHDqZ+fRWcdOtgL4QuuNri7GYN4= + +Name: system/app/Prism.apk +SHA1-Digest: FBR3GVo4P1T0ZVnk05+z9Cj3kos= + +Name: system/app/PluginManager.apk +SHA1-Digest: i7DozftSyy2Yro1Cy0Dtm3mMKtE= + +Name: system/vendor/firmware/mfg.bin +SHA1-Digest: ZcQMPSS4UC0C8EvWkbdOUBqw27A= + +Name: system/etc/system_fonts.xml +SHA1-Digest: jLNfZULcuazUesCv/tfD7W17xXA= + +Name: system/customize/resource/quicklaunch_262.xml +SHA1-Digest: r0UngEa1VzAAQcnmUbuNWC2lihc= + +Name: system/app/IMEXT9Latvian.apk +SHA1-Digest: GczboxIDj8YH+E/etPJ3AFkkrrM= + +Name: system/lib/soundfx/libreverbwrapper.so +SHA1-Digest: j4G7RiEvoDuiZVN26wTcHuGtKt4= + +Name: system/fonts/DroidNaskh-Regular.ttf +SHA1-Digest: UNiU8/FeO2boS+hjDrvun3Oq3tc= + +Name: system/etc/permissions/android.hardware.usb.host.xml +SHA1-Digest: 4e0iQFffHEDh5vP8Oa9PBa1PxGo= + +Name: system/lib/libmmcamera_hdr_lib.so +SHA1-Digest: i+JN1igz8EN3ywqkOFaVlhwPWwc= + +Name: system/app/Flickr.apk +SHA1-Digest: GuabfffINyjiy1Q7kHuanImerOA= + +Name: system/customize/resource/quicklaunch_26801.xml +SHA1-Digest: GIwp1ydu2jvqw9i5rgrWujUtJww= + +Name: system/etc/snd_soc_msm/snd_soc_msm_2x +SHA1-Digest: pJvz1tbUV8UL/mUYvaQTc/DVvyM= + +Name: additions/fonts/comfortaa/Roboto-Bold.ttf +SHA1-Digest: C0O41MVvXmK9r/SCd0osf0IPzTo= + +Name: system/app/CIMEXT9.apk +SHA1-Digest: 4px82M/N/QT7JCVgEZOHwS5pGIs= + +Name: system/app/HtcSoundRecorder.apk +SHA1-Digest: 1sE6H7Dg5NFVJb4hMVjmnipZCY0= + +Name: system/media/audio/alarms/Gold.mp3 +SHA1-Digest: nY30eAs7BHFgHFMcg8p5ApCzFvU= + +Name: system/etc/audio_effects.conf +SHA1-Digest: UXHpWqlGmFvLcW3+h2XH3LZa8V8= + +Name: system/customize/resource/quicklaunch_21401.xml +SHA1-Digest: GSgB6IK1YTP1jKL1ZyUJ3E9OVGA= + +Name: system/framework/pm.jar +SHA1-Digest: aeivCuZKxuop0ukIwK0eBDTVtN0= + +Name: system/etc/image_ibeats_solo_2vol.bin +SHA1-Digest: X7DEwM7Qh7Umqotba3D+Wfd29TQ= + +Name: system/app/NoiseField.apk +SHA1-Digest: GDkB+0b25OzjS4kDK6sMGEUx/BE= + +Name: system/lib/libdiag.so +SHA1-Digest: HJI3iIIPlNN+OOp62M2fcPhHexo= + +Name: data/app/com.google.android.googlequicksearchbox-1.apk +SHA1-Digest: o7zALTlG+CI2sNYLWGiSM+QA/mI= + +Name: data/app/com.twitter.android-1.apk +SHA1-Digest: Njvi+Iy6uJqhg2YtviAZGQGXY1U= + +Name: system/bin/toolbox +SHA1-Digest: 0CS+bNClQb17GONHN9G1PXB2XtM= + +Name: system/customize/resource/allapplication_63102.xml +SHA1-Digest: DvImVnO8XdPerR6nGGAe4yTcGSE= + +Name: system/etc/security/cacerts/eb375c3e.0 +SHA1-Digest: 9jrnwjglpn8uhR8xCTFy4wec+Ww= + +Name: system/lib/libwfdmmutils.so +SHA1-Digest: /h2YECLdRiySQSqAoAlD0Z1P1Yg= + +Name: system/lib/plugins/com.adobe.flashplayer/libysshared.so +SHA1-Digest: MJvCNwSlNiLR1Mth8d18l7bGUng= + +Name: system/etc/nfcee_access.xml +SHA1-Digest: 2z89gPlqpgchFCWC6+PmyhnaNYU= + +Name: META-INF/com/google/android/aroma-config +SHA1-Digest: 97W+p/aWegmVbzItS8rkupLV4Ig= + +Name: system/app/IMEXT9French.apk +SHA1-Digest: yn9MSajjgKMm6CpvTCG3Lz1tj8A= + +Name: system/framework/com.google.widevine.software.drm.jar +SHA1-Digest: Xh2UVVj5kEVRLGQuhBDPaGcB/P8= + +Name: system/framework/com.htc.videowidget.res.apk +SHA1-Digest: 3kpUSj48wcdHlfSfXWj4U9kHkV0= + +Name: system/bin/ipv6tether +SHA1-Digest: FWgQgBm1f/IZk8wlEkTQ67PwP7A= + +Name: system/etc/tfa/video.preset +SHA1-Digest: LchSL4ppfSBn9M0BoSatykA2iP8= + +Name: system/media/weather/weather_snow_day.mp4 +SHA1-Digest: ZWBFDLr0cVh0v2c8k8S9nI8xcwA= + +Name: system/customize/resource/allapplication_262.xml +SHA1-Digest: rv4iV7Gp1gx65XtWFZeTNUDfSiY= + +Name: system/etc/security/cacerts/4f19d2b4.0 +SHA1-Digest: mq4atZ6EcT4H7DaCR/BaKTlCKDQ= + +Name: system/etc/security/cacerts/ea169617.0 +SHA1-Digest: YCD1HGf7ZhS7lIrL78/hxupCFtA= + +Name: system/lib/hw/hwcomposer.msm8960.so +SHA1-Digest: SHy0GejAtEtlEBn3P8JojEXXnIs= + +Name: system/etc/security/cacerts/72fa7371.0 +SHA1-Digest: sw/ScEhE17ZGzZHg7RJLvGMTN2I= + +Name: system/etc/security/cacerts/3d441de8.0 +SHA1-Digest: kgXAr2tpkHl35rHXGMamr1Cpxd4= + +Name: system/lib/libcpt9.so +SHA1-Digest: qmQHE7VcmotG7j5l7eRrTNMRXjU= + +Name: additions/exchange/app/Mail.apk +SHA1-Digest: xHrLOuI2ijR8xwH7uYT8EEkP6Gg= + +Name: system/etc/security/cacerts/facacbc6.0 +SHA1-Digest: bZhsIsflntPIp9DFlV2R0Pc4eqc= + +Name: system/app/HtcGetStarted.apk +SHA1-Digest: hgpu6uuIPsOxcQ3umVIt/6kNmww= + +Name: system/lib/libprojector.so +SHA1-Digest: k6cncE9/WbjtErkot8hGtom9WZM= + +Name: system/lib/libidl.so +SHA1-Digest: 4D7DzabihSKcYIZENxBjHRVTnKQ= + +Name: system/framework/HTCExtension.jar +SHA1-Digest: BBwXW9q2Lfsc2cOP9lomy9AyPUQ= + +Name: system/lib/libcpt9provider.so +SHA1-Digest: cploiCWCBN0Apb0z7hE2Fht5Vhg= + +Name: system/lib/libhardware_legacy.so +SHA1-Digest: KtKT9chPgoKL0i73CM/uwmvc7Dk= + +Name: system/usr/srec/config/en.us/baseline8k.par +SHA1-Digest: xxkwHYqQ6wMwPFVXTMJScnVstGM= + +Name: system/lib/libwt6prnddi.so +SHA1-Digest: 5OuFUDg9iHLRNj78Eovlt3S0HLM= + +Name: system/app/TwitterEngine.apk +SHA1-Digest: A6hjoBuMQh8ji3W3uVhRVg0esZs= + +Name: system/etc/permissions/android.hardware.sensor.proximity.xml +SHA1-Digest: XnS+P6QtWXi//4uZhn9zCGLFAOk= + +Name: system/lib/libstagefright_soft_g711dec.so +SHA1-Digest: Dd2A2VHq4kXywd1MEzVvUtXztH8= + +Name: system/bin/shutdown +SHA1-Digest: b9n30BLB6DJIcBOyl/xip0Kj3D4= + +Name: system/usr/srec/config/en.us/g2p/en-US-ttp.data +SHA1-Digest: TMoAJlQxGPS0YwmkBuVSOTH3Ewg= + +Name: system/lib/libchromatix_ov5693_hfr.so +SHA1-Digest: ss4blvbqv9MF6FYc6w87kQGSYhM= + +Name: system/lib/libvariablespeed.so +SHA1-Digest: hl7xKWD79EUfcNioEbjM8OV8DL8= + +Name: system/lib/modules/spidev.ko +SHA1-Digest: VwEW3LuG/yOXrWEa4bEsHdkUv7o= + +Name: system/bin/nl_listener +SHA1-Digest: KGhJO/ADNGsl9oR6ivgkd1xgq6I= + +Name: system/app/Stk.apk +SHA1-Digest: H8VfrLbAzKIc1yPyO5IFoW5W1rU= + +Name: system/lib/libnfc_jni.so +SHA1-Digest: TwfOC6SAWUwNTxbFraWCrFoH/tc= + +Name: system/etc/security/cacerts/ccc52f49.0 +SHA1-Digest: O0+cfSTNAOmAaDWYHOWEHop+Czc= + +Name: data/app/tunein.player-1.apk +SHA1-Digest: SCsoHJcVX7VbN9ENTyU6TV6HziE= + +Name: system/lib/libchromatix_imx175_zsl.so +SHA1-Digest: JHQvQ2v7PtwDmR9qyhi4+U6ztJA= + +Name: system/framework/com.htc.socialnetwork.res.apk +SHA1-Digest: Ufsmj13nsAUtZvH4Yd8+6DG7oU4= + +Name: additions/fonts/comfortaa/Roboto-Italic.ttf +SHA1-Digest: YtmXnSrAAlQHs9TCx4mJ+lG7Nv4= + +Name: system/customize/resource/quicklaunch_20205.xml +SHA1-Digest: APl8Ptm3nYwlKMlmOALIiaI+A/8= + +Name: system/app/IMEXT9Estonian.apk +SHA1-Digest: m3W0j9DmidKIcP+gK2VR3ndGR9c= + +Name: system/etc/security/cacerts/d0081655.0 +SHA1-Digest: lNTj+/VAIpCdtuWWvc9Z7xY8iX0= + +Name: system/etc/security/cacerts/34d760b2.0 +SHA1-Digest: 50/DzWfq0F6oVJRfiP4yiQcLsv8= + +Name: system/lib/libspeexresampler.so +SHA1-Digest: 7WWvp0/D/bmygY4yvMJUKIJ6Qb4= + +Name: system/bin/ds_fmc_appd +SHA1-Digest: It7lTm9VOXijmC4C0Q2AWk6809Q= + +Name: system/etc/spn-conf.xml +SHA1-Digest: 27/5n0weOKYT3PcMPQra8hjR4Us= + +Name: system/etc/hldm.bin +SHA1-Digest: nnT7IdiQ7VXIbAHj/kH1Z6YX9DA= + +Name: system/lib/libcamerapp.so +SHA1-Digest: /j9xnMlsC8Z2wMilaUhnYUIK3ec= + +Name: system/fonts/DroidSansGeorgian.ttf +SHA1-Digest: TcKNYOeiNvn93qI0a4VO4OsezbA= + +Name: system/etc/tfa/fm_l.config +SHA1-Digest: b6pLXWHOdArgyXDP6MvVHbO6GCg= + +Name: system/customize/resource/allapplication_250.xml +SHA1-Digest: SeZXqBbu5HGhV/BA/4PG26RgL9Y= + +Name: system/etc/security/cacerts/c7e2a638.0 +SHA1-Digest: FNY7YX9aUI4JunnbSM/rvcUd32A= + +Name: system/app/IMEXT9Finnish.apk +SHA1-Digest: 4YM/rYyWEeHom4NXuyKM4bps2Vk= + +Name: system/bin/dumpsys +SHA1-Digest: uc5ewjzvLT6VoP3mDb8HMXCsfZg= + +Name: system/app/GoogleLoginService.apk +SHA1-Digest: mN8ICUC4kJHQr4Ps6d/jitNC/yM= + +Name: system/lib/libandroid_servers.so +SHA1-Digest: 8vCO8MYjqKY6bnyjtzRVnzhx0lk= + +Name: system/media/audio/notifications/Verdigris.mp3 +SHA1-Digest: 84lpXgkNBXm+hYZsvGK/hz+V0Hc= + +Name: system/bin/hci_qcomm_init +SHA1-Digest: TXizsKByQ3vfo0s0FGwmtAeBH0Q= + +Name: system/lib/libmmrtpencoder.so +SHA1-Digest: T9mPiI9BZBAphi1tUtqwlzCDlGw= + +Name: system/etc/image_beats_wireless_bt.bin +SHA1-Digest: hjN5rdNOd8tepCcZ+FrBVg2FvZo= + +Name: system/media/audio/ui/KeypressDelete.ogg +SHA1-Digest: VPKqb3uV7dbibtW5woFWXBcSN+M= + +Name: system/usr/share/partials/partials_CW_gr.csv +SHA1-Digest: gAUUYLqzAgSiY3uwRo+jh/CkOV0= + +Name: data/app/com.estrongs.android.pop-1.apk +SHA1-Digest: PnRrvNbBPSBRZ0wpH9dXAbHU1ik= + +Name: system/app/Idlescreen_productivity.apk +SHA1-Digest: Pqrlxc6rJF+NnvEhFy+qPsAQ3f8= + +Name: system/customize/resource/quicklaunch_65502.xml +SHA1-Digest: DQnk65pNRL2GX6+WM/D1tVS+eEw= + +Name: system/app/MediaProvider.apk +SHA1-Digest: OokEgx3q2b2QoLey38da1DupvkI= + +Name: system/bin/wmdsi +SHA1-Digest: UyzhqibByeIs7xJ0iRziF2jg+Ig= + +Name: system/lib/egl/egl.cfg +SHA1-Digest: y/87VoK0H7VIrFPbmtXvdY1n6gA= + +Name: system/etc/security/cacerts/11a09b38.0 +SHA1-Digest: R669axPhbXAdwOxMeYoDQernEpI= + +Name: system/app/HtcMusic.apk +SHA1-Digest: Bty+q8AzXVj+c+XmNRpLI5na1Ac= + +Name: system/etc/security/cacerts/c527e4ab.0 +SHA1-Digest: zRMmakm1sS3WLz+jAxVfL05XL0k= + +Name: system/customize/resource/allapplication_21910.xml +SHA1-Digest: i79JVoogPm3jv4tbMIP04FnsGSM= + +Name: system/bin/adb +SHA1-Digest: AyqWlH1Q5xCOwe0CWVB7C1N4NXo= + +Name: system/app/ContactsProvider.apk +SHA1-Digest: f8O4TLMZEg6BnmUIokx6p8kNkic= + +Name: additions/fonts/veggieburger/Roboto-Regular.ttf +SHA1-Digest: ZT/jve8vcRhC0XxvTMtwUP1Zdd0= + +Name: system/lib/libnetmgr.so +SHA1-Digest: +k4F516tG1p0hPa6MVm3AFWVqX8= + +Name: system/etc/security/cacerts/95aff9e3.0 +SHA1-Digest: 1GRiRyM4dxD3loVZew6tSzCwVBY= + +Name: system/bin/ifconfig +SHA1-Digest: npeumq00l0cYaxlYSKU4rl6+uvM= + +Name: system/lib/libqc-opt.so +SHA1-Digest: XTtoY/nOHGgA6bC2VXg9F15THNA= + +Name: system/lib/libalbum_imagelib.so +SHA1-Digest: e1Xe0ZnV9m0GFX8K/vm/l/qvX8E= + +Name: system/xbin/dexus +SHA1-Digest: dM8PUVtaDdjf1BX/Fvr8CZR81LQ= + +Name: system/lib/libext2_blkid.so +SHA1-Digest: tytcsJZGOovAw1286BzpxHDFrrk= + +Name: system/lib/egl/libGLESv2_adreno200.so +SHA1-Digest: iMRWj21EscIFc39EfHjiu3MrWr8= + +Name: system/etc/security/cacerts/8f7b96c4.0 +SHA1-Digest: lDZRYJyvALtGjuqSKR0e/O5iFq0= + +Name: system/customize/resource/quicklaunch_20404.xml +SHA1-Digest: +a2CJ41n8YYkTqetRZQUUlJNGbI= + +Name: system/lib/libmmcamera_rubik.so +SHA1-Digest: jPPts5yGKFs16Qh0Xorp6dXCFD4= + +Name: system/etc/security/cacerts/58546a39.0 +SHA1-Digest: 473pDMwaRrwq+3jG4bQw3k+3HUI= + +Name: system/bin/bugreport +SHA1-Digest: iCWefAb7f32Ty/OvmgrQYgAfaXc= + +Name: system/lib/egl/libGLES_android.so +SHA1-Digest: bBpJY9bMeRoAZAdGSyOzN0lhOZc= + +Name: system/lib/libstagefright_avc_common.so +SHA1-Digest: BtTF+4ahI0FVaDiTYk3l3AIXrVY= + +Name: system/lib/libchromatix_imx135_preview.so +SHA1-Digest: HGZ1+94/Y6Nr0WGHXMDpYO0Ljkg= + +Name: system/app/BrcmBluetoothServices.apk +SHA1-Digest: qrRZSFfgbrb+fS2i5qQC9iKFKIw= + +Name: system/customize/resource/wallpapers_a_03.jpg +SHA1-Digest: 8RY+MUBbvnQUFJSv91arbPdsF+c= + +Name: system/lib/libchromatix_ov8838_default_video.so +SHA1-Digest: zHj7ebwXAI+xiP5M3ynx5WZS1H0= + +Name: system/lib/libVDRecognitionAPI-jni.so +SHA1-Digest: aQvzk+4K7no0QMgKTJIVGXzEnKo= + +Name: system/lib/libdiskconfig.so +SHA1-Digest: VSnvy5BbXzdVXjm08Ca9nv5KbgA= + +Name: system/bin/md5 +SHA1-Digest: jWvu7/NiF0a4jTMpNYkwHUSLqXA= + +Name: system/app/Bluetooth.apk +SHA1-Digest: LUyi4uDvG0o2UDsSBRU8oQa54SA= + +Name: system/lib/libmode10AutoTest.so +SHA1-Digest: 68tyKlCv0oWwvKur6SQzIc9AZMI= + +Name: system/customize/resource/CCInfo.txt +SHA1-Digest: /jZfBXY0Al6Gv6wOibTEkwcPiLY= + +Name: system/lib/liblz.so +SHA1-Digest: ke71LqCfi2XM36qzzJ+IdIWRNHY= + +Name: system/etc/security/cacerts/f58a60fe.0 +SHA1-Digest: 68/j3gHkt1C4pcp35lL5Y5cLsM8= + +Name: system/usr/keylayout/AVRCP.kl +SHA1-Digest: QuW9bT29OeTZExCprXrP8pA3gzE= + +Name: system/framework/wimax.jar +SHA1-Digest: sTo97xjCatVK8Ke7h0NijLsgrfo= + +Name: system/fonts/DroidSansTamil-Bold.ttf +SHA1-Digest: oSDuoNatRJoV24tZWDAT4L26Fw0= + +Name: system/app/GSD.apk +SHA1-Digest: 12zGK8D6momXGf56oG9knpp1wRc= + +Name: system/lib/libpolarisoffice_Clipboard.so +SHA1-Digest: TBSyhXyuB6IOFjsCfBujx9CMZA0= + +Name: system/etc/security/cacerts/c19d42c7.0 +SHA1-Digest: nXSR1rdjKTm3ugwRQ/JqDMBzLC4= + +Name: system/media/GPU/mask_vignette_wide.bmp +SHA1-Digest: 1SqKi5VvUhucAdwuEhrUQHa5010= + +Name: system/etc/security/cacerts/3a3b02ce.0 +SHA1-Digest: SQgeiwC1dSnuF8xaVn3NAriZV0M= + +Name: system/etc/image_beatbox_bt.bin +SHA1-Digest: XrcM4+m48vUeHVNR9smiOCVliiQ= + +Name: system/lib/libchromatix_ov5693_zsl.so +SHA1-Digest: s9OpRyEn6XDnFaqS1L3DKIrjvjc= + +Name: system/etc/tfa/voice_l.config +SHA1-Digest: iVbhOpsi7AOVilnNgxAQtIDWKxo= + +Name: system/bin/setconsole +SHA1-Digest: 1XRP1FO1G4TTlIQrL/0pueb6040= + +Name: system/media/audio/ringtones/Eggshell.mp3 +SHA1-Digest: YbzKnciuNFXuS1FCvIL6mBP0d68= + +Name: system/customize/resource/quicklaunch_21416.xml +SHA1-Digest: YblfW35M5Jqg/LFEQy9CKY/uTjA= + +Name: data/app/com.dropbox.android-1.apk +SHA1-Digest: oyvr7H44My9F9tJY9OCAN0ync5E= + +Name: system/customize/resource/quicklaunch_24002.xml +SHA1-Digest: W3fsa9bWB6bPhZoKBBdm/Qhor20= + diff --git a/release/aroma/META-INF/MANIFEST.MF b/release/aroma/META-INF/MANIFEST.MF new file mode 100755 index 00000000000..11fe6a70e8a --- /dev/null +++ b/release/aroma/META-INF/MANIFEST.MF @@ -0,0 +1,6231 @@ +Manifest-Version: 1.0 +Created-By: 1.0 (Android SignApk) + +Name: system/etc/security/cacerts/87d3cf09.0 +SHA1-Digest: SEvFz4ELxIbs56LRzjo3NgdBMaI= + +Name: system/bin/udhcpd +SHA1-Digest: ICYQQiAY904jCH1dYyaysa/YVa4= + +Name: system/lib/libpowermanager.so +SHA1-Digest: MORUwsrDzN0bPdXQKk0uLd+WJkA= + +Name: system/lib/libstagefright_soft_aacdec.so +SHA1-Digest: Ck4zlKZQmvqLQQDwKG/U2clXZ2o= + +Name: system/lib/libchromatix_vd6869_hfr.so +SHA1-Digest: B0zvKcnvgiDByjPiXnBriK6WjMs= + +Name: system/customize/resource/wallpapers_b_02.jpg +SHA1-Digest: xK8TsbrmohwCiuAa/Mec/rXcgvQ= + +Name: system/etc/permissions/android.hardware.sensor.accelerometer.xml +SHA1-Digest: H/ej10L8o81LMOjg3YIBw6GjoiI= + +Name: system/fonts/DFHEIA7A.ttf +SHA1-Digest: jraRllXz4lXhFQAQJwh6Z4739mA= + +Name: system/etc/dhcpcd/dhcpcd-hooks/20-dns.conf +SHA1-Digest: d1dqXCfxg0GO1o8tbtrKcixcoP0= + +Name: system/media/audio/ringtones/Crimson.mp3 +SHA1-Digest: o7xwLMcPANL9tgyHDqHHZ6xXeag= + +Name: system/lib/libchromatix_vd6869_hfr_60fps.so +SHA1-Digest: v2ozOKaVIzWBbTUx+6bvbXBaIic= + +Name: system/lib/libaudioeffect_jni.so +SHA1-Digest: N+/49eJpANno573xc57sTje/gnk= + +Name: system/app/Browser.apk +SHA1-Digest: MZeezBbeW5M2CspoOWK5sy0VOOA= + +Name: system/lib/libexiv2.so +SHA1-Digest: xMhoaY0xJle1MtDnsctRcGMpAPQ= + +Name: system/lib/libdrm1_jni.so +SHA1-Digest: YzNBS82OnBXvIVGMJYq++/FGF2s= + +Name: system/vendor/pittpatt/models/detection/multi_pose_face_landmark + _detectors.7/nose_base-y0-yi45-p0-pi45-r0-ri20.lg_32/full_model.bin +SHA1-Digest: eI6ovSLIm3HCCBrDqsxX2Q/Ei2s= + +Name: system/media/weather/weather_partly_sunny.mp4 +SHA1-Digest: Z+gWdLxgUcy8xv7twDfUe4ExolU= + +Name: additions/fonts/klavika/Roboto-Bold.ttf +SHA1-Digest: ktvGBDYTMDFPLQ14CSjsitANs70= + +Name: system/lib/libwfduibcinterface.so +SHA1-Digest: ugrz1oyVZVPOe3nZDDpuk+IQS8o= + +Name: system/etc/image_htc_earbud_2vol.bin +SHA1-Digest: WIs7nGT5LJbKwcpAuPojnAl6OKo= + +Name: system/lib/libusbhost.so +SHA1-Digest: V7bdb7BIejsifZ8dQa56f1vTBXQ= + +Name: system/fonts/AndroidClock_Solid.ttf +SHA1-Digest: 0vRHOkM++Y5hREyvokR3HBnI2ig= + +Name: system/usr/srec/en-US/embed_phone_nn_model +SHA1-Digest: MVunhgmY/DSaOzfB2Xc+O/LHNcs= + +Name: system/etc/security/cacerts/81b9768f.0 +SHA1-Digest: 4erTsgDtkF3RUrNOypxOujy6Zeo= + +Name: system/lib/libDxDtcpClient.so +SHA1-Digest: lK4TzZSutj4fykOPkjBkwUr5kH8= + +Name: system/framework/com.htc.weather.res.apk +SHA1-Digest: 61qMtJi4XR0xZHXTKFGw6dCgops= + +Name: system/fonts/gcsh00d-hkscs.ttf +SHA1-Digest: 1M0itSuFKi2mVAJ+izWFbLvsI/s= + +Name: system/lib/libyuvimage.so +SHA1-Digest: Q/mE0gt20kUypL9y51rTrPDZdsI= + +Name: system/app/HtcScreenTimeoutWidget.apk +SHA1-Digest: 08yopP2PL3m9T1fuBEhpTeAjtJ4= + +Name: system/lib/libAnalyst.so +SHA1-Digest: 4rEUfTdKOOhjxD+ExvSZacoufhw= + +Name: system/bin/sdcard +SHA1-Digest: JkjhVSwvvxYamYbcNjJFMqd6utY= + +Name: system/framework/ext.jar +SHA1-Digest: rnZ/HdpD8ExGmwo4+Q7C+ksBlbw= + +Name: system/media/audio/ringtones/Lavender.mp3 +SHA1-Digest: 402J4OoPp4eh7vFA4M/BzVFIMBw= + +Name: system/app/MySketcher.apk +SHA1-Digest: nTh5DoVVR0PclhrxhhyhHEe44J0= + +Name: system/etc/image_ibeats_solo.bin +SHA1-Digest: rW+4jB7c23PSDBTWJVHs98rZ2cM= + +Name: system/media/weather/weather_l_partly_cloud_day.mp4 +SHA1-Digest: fVXtKss1zrCNz07DzyDH7B1GrIM= + +Name: system/bin/smd +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/etc/security/cacerts/ed049835.0 +SHA1-Digest: qfwv5fm9WuVJSoOfaW0MTXSQraU= + +Name: data/app/com.facebook.katana-1.apk +SHA1-Digest: DcQH7kiI1zeEIuAQZpTsxmzueSY= + +Name: system/app/Phonesky.apk +SHA1-Digest: nIJ143RgNUPCdsajQAZIJSxDDXE= + +Name: system/lib/libgnmc_id3tag.2.5.9.4.so +SHA1-Digest: PS9cMyZXauQF63C0EMibFH1XRAk= + +Name: system/media/audio/ui/Volume-6.flac +SHA1-Digest: JjjeOlpdXTjl8uR9mFQN1qmfZ6I= + +Name: system/etc/security/cacerts/9f533518.0 +SHA1-Digest: AZtPDtYCuXAjFbgZptviWf6or4o= + +Name: system/etc/security/cacerts/a3896b44.0 +SHA1-Digest: ZLbceCx+C2qAgw+u1XPHRG5oKOw= + +Name: system/customize/CID/default.xml +SHA1-Digest: 8KAO8QboF3gb37TigGvB3JX2+BY= + +Name: META-INF/com/google/android/aroma/icons/alert.png +SHA1-Digest: 4vVPQ4oeO+xcr1ttQ56VRZ+7nRU= + +Name: system/framework/com.broadcom.bt.le.jar +SHA1-Digest: hZWbjQDYlKpdy0b4PySH7jocpBo= + +Name: system/lib/libstagefright_soft_mpeg4enc.so +SHA1-Digest: Njo56YAyfa+nIu3Gqc6hBtuXQ3s= + +Name: system/media/audio/notifications/Claret.mp3 +SHA1-Digest: rjxEbzJGIB1VQy0Bc1iqqVPrIWA= + +Name: system/lib/libwpa_client.so +SHA1-Digest: 34BVv0QT4i8PAQv+b17SV4WFgUI= + +Name: system/media/audio/ui/LowBattery.ogg +SHA1-Digest: uuIldXjG+4uO9pGKN3pjkar13pA= + +Name: system/bin/linker +SHA1-Digest: 02EtQtgXZ9Hk0UYHNOWcoe5Fmuk= + +Name: system/lib/libhtcsunny2engine.so +SHA1-Digest: AMcVQjyAMAtQ7pN7zoqVfF1OXa8= + +Name: system/lib/libmllite.so +SHA1-Digest: nFnhkw56G2Yi5eK+rO8j6dYdzU0= + +Name: system/media/weather/weather_partly_cloud_day.mp4 +SHA1-Digest: L70Lt52toKCCLeE4aj3UJ8hE7PE= + +Name: additions/fonts/veggieburger/Roboto-Bold.ttf +SHA1-Digest: vqC6OfKIK+uned2YmV09YK3dTLE= + +Name: META-INF/com/google/android/aroma/trickdroid.png +SHA1-Digest: menCFRnjUaVA2x9WyPcw5tVAjPs= + +Name: system/media/audio/ui/media_volume.ogg +SHA1-Digest: 3My0Ro04VTBOMDcfDucgkfcYkkQ= + +Name: system/app/IMEXT9Bulgaria.apk +SHA1-Digest: E5go9fvJ+lCivI1omVK1TWROeHA= + +Name: system/media/GPU/dot_mask_3.bmp +SHA1-Digest: B6JIoYVFR1iw8UeYx476FnEI+OI= + +Name: system/etc/secureproperty.xml +SHA1-Digest: 67uk8SBU7aXMrgV0KC9FUb5f7IU= + +Name: additions/fonts/asap/Roboto-BoldItalic.ttf +SHA1-Digest: Tc7CBKbNIpVRaAgaAaerhcw1uyY= + +Name: system/app/IMEXT9Russian.apk +SHA1-Digest: Cb/QzF2AwqOI4W+VfKI0QcOadgU= + +Name: system/etc/permissions/android.hardware.usb.accessory.xml +SHA1-Digest: FqpJrpvkKQ0UpylOSdp44H4smXo= + +Name: system/media/zchgd/batt_40.rle +SHA1-Digest: iYWRM++q9nAhIzkLnTWYwWW4z6w= + +Name: system/media/audio/ringtones/Persimmon.mp3 +SHA1-Digest: HwUsaVwP56xvkJwsyZyIsoDg5vQ= + +Name: system/fonts/Roboto-Regular.ttf +SHA1-Digest: Z9cynTXQb4TYTpzUSFMVfKk/tTc= + +Name: system/lib/libDivxDrm.so +SHA1-Digest: QGCKZ6H+psPbNnbfQRPRwNFDIfk= + +Name: system/bin/mtpd +SHA1-Digest: HHKag5D5o4pCnd/Bp6F/Eh9VJdY= + +Name: system/customize/resource/quicklaunch_21408.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/customize/resource/allapplication_22288.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/app/Nfc.apk +SHA1-Digest: Ukj8nEJVKrd7dzX4ZRerTSGNGfY= + +Name: system/usr/share/bmd/RFFspeed_501.bmd +SHA1-Digest: U8VAt4ToJM9cf23UWSW02bJYN+M= + +Name: system/etc/security/cacerts/635ccfd5.0 +SHA1-Digest: fEdbGydFBhoJjXNJXzEVa18unJ0= + +Name: system/etc/security/cacerts/2e8714cb.0 +SHA1-Digest: B52F0B9cohH697PhOwRGCzELdTw= + +Name: system/media/GPU/CurveWarm.bmp +SHA1-Digest: 1zAKIDQrpBz6UoXmWFbWP7kvi1s= + +Name: system/app/JETCET_PRINT_Resources.apk +SHA1-Digest: Unz/6TBE7Szc/keNt1hOThLniCU= + +Name: system/app/VoiceDictation.apk +SHA1-Digest: Lw46+mQ5gNkvEqqKperlyjQWpqw= + +Name: META-INF/com/google/android/aroma/icons/gps.png +SHA1-Digest: /fuHyjV7VcRMGsrWh41SyLvvKkY= + +Name: system/xbin/nc +SHA1-Digest: JJE+yImZJSlJ3rCNFl4j7ZSRB7A= + +Name: data/app/com.google.android.marvin.talkback-1.apk +SHA1-Digest: LVvWQ1CfxMa1GET5I/xZShrj3ZA= + +Name: system/etc/permissions/android.hardware.location.gps.xml +SHA1-Digest: ydG3KogqmSduNEKpFzBYmpQFX1c= + +Name: system/fonts/Roboto-Bold.ttf +SHA1-Digest: Ykc18CQi8T5QzPRm8NKe3aBa2zY= + +Name: system/lib/libGLES_direct.so +SHA1-Digest: Q89nbZ2bx3MJcWNr5W7tVNttqjk= + +Name: system/app/CustomizationSetup.apk +SHA1-Digest: gTS4PSKwUvB3cOu2SKALBJLVbos= + +Name: system/app/MusicChannel.apk +SHA1-Digest: ciWFeCFIer+Ct/TyozFIQB0QQ6U= + +Name: system/etc/image_ibeats.bin +SHA1-Digest: X08lPbW7p7cgywYQokNcIXrjg9k= + +Name: system/etc/image_gec_bt.bin +SHA1-Digest: W873c0G9gw4/bBA3L4yMLUX4FjU= + +Name: system/lib/libcsd-client.so +SHA1-Digest: HI8vFJ5sh9uN57pHJ5bhH/AOu0U= + +Name: system/bin/RescueServer +SHA1-Digest: qWDoVCW2cB48MJcB5PpTQUa7pyk= + +Name: additions/fonts/comicsans/Roboto-Italic.ttf +SHA1-Digest: yfjgrSTLZI+MEqcsxa/l2nhsMIA= + +Name: system/etc/security/cacerts/5f16ce45.0 +SHA1-Digest: CR5ngcPg+GhEF4lVh4M7sbRV3Hc= + +Name: system/etc/security/otacerts.zip +SHA1-Digest: E4kiOM61KkKokn2eIpqJkkW66qA= + +Name: system/bin/stop +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/bin/htc_ebdlogd +SHA1-Digest: qlUPTF1QEqz3j8XS7ee1+on2BPM= + +Name: system/lib/libpatts_engine_jni_api.so +SHA1-Digest: YrCR4O7XonOvv9ISeoe9WTjZPoY= + +Name: system/lib/libglcv.so +SHA1-Digest: cIKwdQHtKSxo7YWm4HqwRnBmW+E= + +Name: system/etc/firmware/fw_bcm4335_apsta_b0.bin +SHA1-Digest: uJMxJ3MkPLcTV1cMI2rm37qvk5k= + +Name: system/etc/security/cacerts/0c364b2d.0 +SHA1-Digest: W8eUtQrdCtbH5zZbkCDjlJgwhWM= + +Name: system/lib/libsrsprocessing.so +SHA1-Digest: VBBOu2dxNLOxOG1sGNAvpu22Gy8= + +Name: system/lib/bluez-plugin/audio.so +SHA1-Digest: D4mFDntmcVZy7tQ6c9lCUcieDpk= + +Name: system/lib/hw/audio_policy.default.so +SHA1-Digest: qThVt3mzx1I4ru994vnRjrlzv6M= + +Name: system/lib/libchromatix_ov8838_hfr.so +SHA1-Digest: eAUTj1TEZBU/EHpBVBvDlNrwRT4= + +Name: system/etc/soundimage/srs_global.cfg +SHA1-Digest: tczDSklQzgifcr56AGYV5l4snkM= + +Name: system/lib/libicuuc.so +SHA1-Digest: DnBGOiWQWhYzSW8y5r1QeAHvHSs= + +Name: system/app/HtcMusicWidget.apk +SHA1-Digest: m89XS5KwhzYZz2X9ojto7EtS3Ls= + +Name: system/lib/libnetsharing.so +SHA1-Digest: SnS12zE4I94jofnoeroNXfeEPxw= + +Name: system/usr/keylayout/qwerty.kl +SHA1-Digest: 8/B84i3bQPu2tSLenvsrd+0YolI= + +Name: system/etc/security/cacerts/b5f329fa.0 +SHA1-Digest: StMAnoljP1hXqiJcZYbmEssAnJk= + +Name: system/etc/soundimage/srs_geq10.cfg +SHA1-Digest: tIQaXxMaShowHXYfAAagY2+QX5c= + +Name: system/lib/libstagefrighthw.so +SHA1-Digest: Cpj4bysXshhtZjkBGTHWvhIS084= + +Name: system/bin/schedtop +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/bin/chmod +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/app/HtcMessageProvider.apk +SHA1-Digest: VJZKx4YD7YH4YlKPOx8saV6uZIU= + +Name: system/lib/libmtp.so +SHA1-Digest: 05jOPlWXrErIJCCnLckmxdGfU3c= + +Name: additions/wipe/wipe.sh +SHA1-Digest: cx54+cFy0h15QJ1DmLm9cMmr5yA= + +Name: system/customize/resource/wallpapers_b_05.jpg +SHA1-Digest: Qrj4Qp1GHo1sQOhMgNvA1BshBIk= + +Name: system/etc/tfa/deftcoefA.speaker +SHA1-Digest: gsLxDUQ+FIJVMB2pqmIkWDyioPM= + +Name: system/app/HtcDropboxGLRPlugin.apk +SHA1-Digest: b+PuostABgQK7yAo00+lUHGjFr0= + +Name: system/app/HtcRingtoneWidget.apk +SHA1-Digest: Vu50iaCVxDrvTzA4CrTAzjLQwV0= + +Name: system/app/IMEXT9Portuguese.apk +SHA1-Digest: a+nfSrEWJlKv9QCfMQ8i1aloIyY= + +Name: system/etc/security/cacerts/e268a4c5.0 +SHA1-Digest: m5F+mEcMoF+8u8DBD6e9pEogIk8= + +Name: system/app/HtcContactWidgets.apk +SHA1-Digest: atqXG9dZ1ls22nZ5C4+sALdEHo0= + +Name: system/lib/libchromatix_ar0260_hdr.so +SHA1-Digest: fgb3Ftj2LsX7L0leGVf3jfuSE1E= + +Name: system/lib/libmmcamera_rawchipproc.so +SHA1-Digest: DzDEfnc/dJVCu6iKaaIA0R5nUPE= + +Name: system/fonts/HelveticaNeueLTPro35Th.ttf +SHA1-Digest: cSJmjVS5DnDDAXRSSKSL/w/9DRo= + +Name: system/lib/libstagefright_soft_vpxdec.so +SHA1-Digest: zR6gdZ24MxkGHS0XrspUQpDlJJc= + +Name: system/lib/liboemcamera.so +SHA1-Digest: 5lRAXG7bZR7hAj2TdMJAa3XNYQY= + +Name: additions/gps/europe/etc/gps.conf +SHA1-Digest: +XeSYP/cwNlriWknNc/ynSlEPi4= + +Name: system/bin/usbhub_init +SHA1-Digest: /rGFX6XmI14zpeW2U1uxk/acqTo= + +Name: system/usr/srec/config/en.us/dictionary/enroll.ok +SHA1-Digest: rcl7CO9ZOIxVX+yaPLoqJv8ZtwY= + +Name: system/media/audio/ringtones/Red.mp3 +SHA1-Digest: T+48wiN95iILjhoQLezHDIvXPvg= + +Name: system/bin/mm-jpeg-dec-test-client +SHA1-Digest: Jp1ZGNBLYmopygN9kLw9Sigf6BI= + +Name: system/bin/ATFWD-daemon +SHA1-Digest: eXxEZcgXeLpbtKUWMHSnuwwBxOY= + +Name: system/etc/security/cacerts/56657bde.0 +SHA1-Digest: OXPix8Y5jubMndNxaBClQGy9Bac= + +Name: system/lib/libCommandSvc.so +SHA1-Digest: 492in0O89MvYOGzeN2kDqlNJglg= + +Name: system/lib/libwt6xlsrdr.so +SHA1-Digest: w0J5AFyw4QGRL3v/7vCu4r2zyls= + +Name: system/lib/libOmxCore.so +SHA1-Digest: EHDNGS7zjUs3qEgR7Qoy5BHF8Wg= + +Name: system/lib/libpixelflinger.so +SHA1-Digest: RR7d6/BwUIPBy9M+P870M6YweTs= + +Name: system/bin/RescueStarter +SHA1-Digest: c/jazM0uc+RxFBAJJnMv/81MLaA= + +Name: system/lib/libmm-omxcore.so +SHA1-Digest: pqmwQZ0q5qxsoOeHlV65gX2g2/Q= + +Name: system/etc/ppp/ip-up-vpn +SHA1-Digest: CXnecb4k4Mn5g3hdEHTquN7PUcY= + +Name: system/lib/libandroid.so +SHA1-Digest: gEX7YAOBEY++LGBMF5w0CmPeDkg= + +Name: system/lib/libcrypto.so +SHA1-Digest: eDbAsV89FAEkvXuRxuDfUPj/eNY= + +Name: system/app/Updater.apk +SHA1-Digest: ICmDyKhy+HM7fkmgGa4WKfN3Hc4= + +Name: system/lib/hw/audio.primary.msm8960.so +SHA1-Digest: tspOLjpGQfry6lyr9+czVfc8vnk= + +Name: system/customize/resource/allapplication_23210.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/lib/libext4_utils.so +SHA1-Digest: 1CnzR/0HZDNdZVimKHeo9RvCf9c= + +Name: system/customize/resource/ConfigH.bin +SHA1-Digest: m0Qoky+wTVeedsMjdE5kLy2/5Jc= + +Name: system/lib/libOpenMAXAL.so +SHA1-Digest: MYgmWEVFSGwXoDXDabC91pANHzQ= + +Name: system/lib/egl/libq3dtools_adreno200.so +SHA1-Digest: PRNVFjAWP2dZ9LY7CywY+WfC3bY= + +Name: system/etc/security/cacerts/1df5ec47.0 +SHA1-Digest: UujKW9YI89cjOO6uCaBGaKKEdIQ= + +Name: system/lib/plugins/com.adobe.flashplayer/libflashplayer.so +SHA1-Digest: VdarjMW0yjKajHGXemvkCmYy27g= + +Name: system/customize/resource/wallpapers_c_04.jpg +SHA1-Digest: BYj83VTJTKiETaKJT7cHGMjhudg= + +Name: system/framework/com.htc.resources.apk +SHA1-Digest: DmH2Nut+hrC/yLTw1FZHZQjntS0= + +Name: system/etc/dhcpcd/dhcpcd-hooks/95-configured +SHA1-Digest: n21FxtoLF/bqDP+kxPLFVdyzXE8= + +Name: system/etc/tfa/playbackbeats_l.config +SHA1-Digest: j6S5V89FwvUw8PmIK737fBvqmO4= + +Name: system/framework/input.jar +SHA1-Digest: akcCB8GSs9P/7zfOavMR8ZWFWSQ= + +Name: system/etc/security/cacerts/85cde254.0 +SHA1-Digest: R9VocfbkwOamdyjLfP1NDBc/kug= + +Name: system/lib/libchromatix_s5k6a2ya_default_video.so +SHA1-Digest: gz6UUSlC1pq6pP25Sp92v195htc= + +Name: system/bin/printenv +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/etc/security/cacerts/0481cb65.0 +SHA1-Digest: eUDnOJWQG+0Mq73qo4bkRPu78z0= + +Name: system/etc/tfa/recorder.preset +SHA1-Digest: ZIWhTsSVk2FQh+JqEczz/+vRDeQ= + +Name: system/media/audio/notifications/Viridian.mp3 +SHA1-Digest: OIMHInxfNZZ7TXa3aUlXVIisGa8= + +Name: system/bin/svc +SHA1-Digest: laWKf0PV0fXkGCVIDLsyLTOEAMc= + +Name: system/framework/android.test.runner.jar +SHA1-Digest: CznXOzRKZf6f4KrS0zzYhytFHbs= + +Name: system/framework/usbnet.jar +SHA1-Digest: Y00mvgIlw27s/vNByWclrNj217c= + +Name: system/customize/resource/quicklaunch_23410.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/customize/resource/allapplication_65502.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/etc/security/cacerts/2fb1850a.0 +SHA1-Digest: 5FY7vEW9oM3Pyb/ez0M7eSlco+Y= + +Name: system/lib/libstagefright_soft_amrnbenc.so +SHA1-Digest: u/sofmApIfrfaibn7guEnXET+qI= + +Name: system/lib/libQSEEComAPI.so +SHA1-Digest: VhqE0Dnd7pRC+q4Vn7coCpKfIPc= + +Name: additions/fonts/roboto/Roboto-Regular.ttf +SHA1-Digest: Z9cynTXQb4TYTpzUSFMVfKk/tTc= + +Name: system/etc/tfa/fm.config +SHA1-Digest: mcDPznDmbQbzvQ1yOzfS3mAX2n0= + +Name: system/etc/firmware/leia_pfp_470.fw +SHA1-Digest: RqjOgh0hg1n/foRttdzBWzG91co= + +Name: system/media/zchgd/batt_5.rle +SHA1-Digest: mTf5wlQitI2OSGQ5ZVH3otlcoD0= + +Name: system/vendor/lib/libwvdrm_L1.so +SHA1-Digest: iSMDSbyVS1cczOIzcSrBNvjDsEk= + +Name: system/tts/lang_pico/es-ES_zl0_sg.bin +SHA1-Digest: /gTDSWCUKfTXAlH/biqyNzYk1Yg= + +Name: system/app/PureC_UserDictionaryProvider.apk +SHA1-Digest: eKflp8acbknSlFvQ0+jMM6DNJXs= + +Name: system/lib/libqdp.so +SHA1-Digest: 93/hEy/0LFl5cETrCw7THy2IG6U= + +Name: system/etc/firmware/a225p5_pm4.fw +SHA1-Digest: AuX7JsEh04gQS8ag8xgR36kfGCg= + +Name: system/lib/libcam_oem_plugin.so +SHA1-Digest: rHaYCWxFAn5s4Vuivjl4aR980eM= + +Name: system/lib/libchromatix_vd6869_default_video.so +SHA1-Digest: uSHznNV44UrOBccfwGYO0tyv5t0= + +Name: system/bin/pnpmgr +SHA1-Digest: Vy4Vbu4eXCFxPaH+yGfXP246XUs= + +Name: system/etc/security/cacerts/709afd2b.0 +SHA1-Digest: KGT1Ull1qgWICgtxU3/55nw/4uM= + +Name: system/lib/libnmsp_speex.so +SHA1-Digest: rgmO+eaj75rcbY2C2VDDekOnhWo= + +Name: system/xbin/sysrw +SHA1-Digest: rRps8RoUnWtGRd9F9IAQfTH9XTU= + +Name: system/lib/libvideoeditorplayer.so +SHA1-Digest: cmQOiIlvBC/LzknfMZSFNwAv3f4= + +Name: system/customize/clientid/default.prop +SHA1-Digest: AscF550NfHVQFC+Z7pvfsgv7wVw= + +Name: system/lib/libdrm1.so +SHA1-Digest: C31dRgDxPMm+ODh0Wn4sFJ7TGrY= + +Name: system/etc/permissions/com.htc.android.bluetooth.le.xml +SHA1-Digest: Jofz0dJK3Vk0K9IXRh4dyoggaDc= + +Name: META-INF/com/google/android/aroma/icons/confirm.png +SHA1-Digest: YeJPRW3VKUhuHZf6Y0a5iznavIA= + +Name: system/etc/security/cacerts/1e8e7201.0 +SHA1-Digest: AjTvkNYA86SfWxtzL6wQkemMoBs= + +Name: system/etc/security/cacerts/46b2fd3b.0 +SHA1-Digest: qcEpnsYeagaaeB94Fmlp1prYt3g= + +Name: system/lib/libwfduibcsrc.so +SHA1-Digest: 3YSVDi/Du/huYnAtdoAoFKKlF+Q= + +Name: system/xbin/sysro +SHA1-Digest: ff02R0/YaPW3I5ywDdoFZ5IZ7gQ= + +Name: system/media/zchgd/batt_70.rle +SHA1-Digest: VB2HqgtLseMqkl4Ik/NLl5/dXlY= + +Name: system/customize/resource/rp_ce_0700_i.png +SHA1-Digest: UGI5KGSeTQPMYqmL7qnAJfWw3Qg= + +Name: system/lib/libstlport.so +SHA1-Digest: hnVy+XlrBQXBM+bEbPjCHfdUX30= + +Name: system/media/weather/weather_thunderstorm_night.mp4 +SHA1-Digest: VjkbK4QDyi9uc6dvG6SYTpSFDtQ= + +Name: additions/fonts/roboto/Roboto-Bold.ttf +SHA1-Digest: Ykc18CQi8T5QzPRm8NKe3aBa2zY= + +Name: system/etc/permissions/android.software.sip.voip.xml +SHA1-Digest: qrhF2jqAj3LTjMn5u0PyAXph4X8= + +Name: system/bin/mdnsd +SHA1-Digest: 2OrmXCnG/YnFlNtScWNoyW+D0xo= + +Name: system/lib/libjnigraphics.so +SHA1-Digest: wTiZqoyzkioNm03yN6nJQjTS2Mg= + +Name: system/bin/ping +SHA1-Digest: ZbyK03myR5eRM9L0qnc5GmZ14W4= + +Name: system/lib/libsysutils.so +SHA1-Digest: n61harAISM3aIRP7eu+cmqK84+0= + +Name: system/lib/ssl/engines/libkeystore.so +SHA1-Digest: i3di5pdD3Km7Yz+gL50XiTGP3iA= + +Name: system/app/GoogleBackupTransport.apk +SHA1-Digest: 5DQ1KS2UzPp86rTeATEyPUkVbeQ= + +Name: META-INF/com/google/android/aroma/themes/sense/dialog_titlebar.9 + .png +SHA1-Digest: ZuhQ+jwdSiXNUSLIhMaANsclNnY= + +Name: system/lib/libdmt_speex.so +SHA1-Digest: Ln81AgCDfS2yTdCGRlMK+KLZcQc= + +Name: additions/fonts/helveticaneue/Roboto-Regular.ttf +SHA1-Digest: Ag4WCAlIdfsROGQIFQls/Byifrs= + +Name: system/lib/libgps.utils.so +SHA1-Digest: P4H+Yt98m2auKJaWAOebN+eCq6Y= + +Name: system/customize/resource/quicklaunch_24007.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/app/RebootWarningWin.apk +SHA1-Digest: rWJiLEASvgKcD47/DRAbuFKQtG8= + +Name: system/etc/security/cacerts/a0bc6fbb.0 +SHA1-Digest: NWKfQevFapMePZRehJiiL3l2b/A= + +Name: system/bin/hciattach +SHA1-Digest: sbOHlsLTY6saOGKu5+914Kp3UkM= + +Name: system/media/audio/notifications/Mantis.mp3 +SHA1-Digest: xX+XvtTHFrGcMoonpy48TRCUAn0= + +Name: system/etc/soundimage/srsfx_trumedia_51.cfg +SHA1-Digest: wlYxA19kBnDd8l7lWPyidjrvBmo= + +Name: system/bin/iftop +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/etc/security/cacerts/cf701eeb.0 +SHA1-Digest: EJ+vugw2T3Rx/5SHC912B2Lc1AA= + +Name: system/etc/wifioffloadpkg.xml +SHA1-Digest: V4kLYM5/b/JRAaxS0lQRHbFH5TY= + +Name: system/framework/com.htc.browsermodule.res.apk +SHA1-Digest: cjGxhGqq9Hg47ctm6EEMRGUbP1E= + +Name: system/etc/security/cacerts/67495436.0 +SHA1-Digest: YTT/bqjqefQaDmHNLvdFEV4CLqE= + +Name: system/lib/libaudcal.so +SHA1-Digest: nbolEaLO5TtS88tZeRNVkiQhqaw= + +Name: system/lib/libFileMux.so +SHA1-Digest: lf9wC4Yk/cJ74WJ2Oz6ZFPOsaRg= + +Name: system/etc/audio_policy.conf +SHA1-Digest: q9qbm60+wECXJFaM8Gp6QMJqsv8= + +Name: system/customize/resource/quicklaunch_228.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/customize/resource/allapplication_65510.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/usr/srec/config/en.us/baseline11k.par +SHA1-Digest: Mq1IVDJlLzTaUQHLe+XE3eS3jPQ= + +Name: system/lib/libext2_e2p.so +SHA1-Digest: 33VPKMi7fie8LNOiYpWZB2ZbQ4g= + +Name: system/app/Frisbee.apk +SHA1-Digest: NlDalMEIq2fxk58storhUdg/A58= + +Name: system/lib/libchromatix_s5k3h2yx_preview.so +SHA1-Digest: jg3fWy6T4HdqIcWwdSPZT81OrRQ= + +Name: system/lib/libqdMetaData.so +SHA1-Digest: SzGHNOVk8qlyoTTKAhuG9cN3kxk= + +Name: system/etc/tfa/tfa9887.config +SHA1-Digest: gyvcECYDl8FeI8LlmyOTfQPiJNg= + +Name: META-INF/com/google/android/aroma/fonts/small.png +SHA1-Digest: oHYrbDXlnhjFwHqNQePor+/Vf/A= + +Name: system/lib/libv8.so +SHA1-Digest: zabtPZyGyUa63l+QXI7gJkpHD9o= + +Name: system/app/DownloadProvider.apk +SHA1-Digest: 7TJ+skb/OfzDBCO7uHS7IScbw2g= + +Name: system/lib/libril-qc-qmi-1.so +SHA1-Digest: t6hRA6Prqzsp0pMQNzdUlBLU1xQ= + +Name: system/bin/touch +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/fonts/HelveticaNeueOTS.ttf +SHA1-Digest: cZ0Da8Hkqx8UuwK/LHEMD8H1L9s= + +Name: system/media/weather/weather_windy_night.mp4 +SHA1-Digest: zRYAoh5YklqbHBaLKJCwMcpYyrE= + +Name: system/bin/mm-jpeg-enc-test-client +SHA1-Digest: /qwcTMDPXNrI+VamDqQ3FUHx/YE= + +Name: system/lib/libqcci_legacy.so +SHA1-Digest: WFV68Oec4O2xur7WYvexqWnkbhk= + +Name: system/etc/security/cacerts/bcdd5959.0 +SHA1-Digest: mqSe0pzB0HImT/8Q9HI7sCP7FyQ= + +Name: additions/fonts/segoewp/Roboto-Regular.ttf +SHA1-Digest: QtOqY32WXX7LiT5Iur74jDKa5gA= + +Name: system/etc/security/cacerts/97fecd7d.0 +SHA1-Digest: 3spPf/i94EWIhdbNLwN/QDT8d4k= + +Name: system/bin/keystore +SHA1-Digest: AKSAfcwIR89pjBzIN3PpCQVLIF4= + +Name: system/bin/awb_camera +SHA1-Digest: gGaXimGKHzC/W9RfebCTzPVw+w0= + +Name: system/lib/modules/moc_platform_mod.ko.3.4.10 +SHA1-Digest: /a3egfHcdDg/9sn2cqzNTBmpgc8= + +Name: system/app/IMEXT9Czech.apk +SHA1-Digest: GexOcXPl9sd8oLgaq5tRhXop+yk= + +Name: system/bin/nandread +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/bin/bma150_usr +SHA1-Digest: 3VYydgZq2PF92YX557JxNX3gL+I= + +Name: system/media/audio/ui/Unlock.ogg +SHA1-Digest: F9KA4TW+Gp7zDkIj6GjLT7I1KCE= + +Name: system/etc/tfa/fm_l.preset +SHA1-Digest: 5sbhFGjzewa4Pfs10aaWH7c80Ew= + +Name: system/lib/modules/moc_crypto.ko +SHA1-Digest: P2mbWXOwwNsOMU2yzf/+aFkZkSo= + +Name: system/fonts/Clockopia.ttf +SHA1-Digest: iw96Cm9uf/w/SbVQekBynrfv48I= + +Name: system/xbin/su +SHA1-Digest: zHxPpqr9D5YGHzZMFfX6VrZ8dj4= + +Name: system/lib/libdmt_elvis.so +SHA1-Digest: 9KmiXSvBv5ZXnLnSJIchdWhcsvQ= + +Name: system/lib/libfilterfw.so +SHA1-Digest: AQjn8SbVPeWOfwFtZHLH8cwdkRs= + +Name: system/media/weather/weather_cloudy_night.mp4 +SHA1-Digest: 9/QjibnIK9fIVBGjPPgfOqNlv7Y= + +Name: system/etc/image_htc_midtier_2vol.bin +SHA1-Digest: R37IgU56A2CD+WeOI2wbE1qSzbM= + +Name: system/fonts/DroidNaskh-Bold.ttf +SHA1-Digest: VeIrLgRpCvr8H4wYbwzQb48k8eI= + +Name: system/etc/tfa/video.config +SHA1-Digest: mcDPznDmbQbzvQ1yOzfS3mAX2n0= + +Name: system/lib/libcutils.so +SHA1-Digest: eLqgXW8SrY4XHkDgJz6S84vl8zc= + +Name: system/lib/libmmparser.so +SHA1-Digest: j+AlCpNgyGbpCCxuLKjEPVeD7fA= + +Name: system/media/zchgd/batt_30.rle +SHA1-Digest: Upz3AuGR4pHfuaOhzVzOjIZjm14= + +Name: system/fonts/RobotoCondensed-Bold.ttf +SHA1-Digest: IIA82t9wxAtGgB9tHwt16IBinrQ= + +Name: system/app/HtcInternalSettingsProvider.apk +SHA1-Digest: l+woGnwnp4fVV9FgYAIaVu77wL0= + +Name: META-INF/com/google/android/aroma/themes/sense/bg.9.png +SHA1-Digest: InlGz7Cq45PigWMA4uPLHlms3+0= + +Name: system/lib/libchromatix_vd6869_preview.so +SHA1-Digest: yx+5Mx4GRFNKAuJwpVIY+nC2gJA= + +Name: system/lib/libcameraface.so +SHA1-Digest: km4j+8o+0kWqM800zNKtc3d+r5o= + +Name: system/customize/resource/allapplication_21404.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/framework/com.android.nfc_extras.jar +SHA1-Digest: QlWKCE8PrdciN0PB7IJ1amq81JU= + +Name: system/bin/bu +SHA1-Digest: qZ1ifCg2IqfafLkirzAP4dMjOro= + +Name: system/etc/soundimage/srs_bypass.cfg +SHA1-Digest: X37NMhOuhn1HdWL2ngW7auz8uGo= + +Name: system/etc/sound_mfg_DMIC.txt +SHA1-Digest: j/gKOE8iUqvcIuoNQ8JSpnSnGjE= + +Name: system/lib/hw/audio.primary.default.so +SHA1-Digest: SRxklM1aIq33mo3YTMc8o8/mGnw= + +Name: system/usr/share/partials/partials_A_gb.csv +SHA1-Digest: VIxIrgVGX2kG8+c51NduCfOVR3o= + +Name: system/lib/libchromatix_imx175_preview.so +SHA1-Digest: 0qhmyIQCFmlvr5qy046WISvIRUw= + +Name: system/lib/libnetutils.so +SHA1-Digest: LmQoMK52xp4fub06favUVZU5eEA= + +Name: system/media/audio/ui/Volume-1.flac +SHA1-Digest: C6ClE+7lNVzPOVG5CZeVHFFTpGw= + +Name: system/customize/resource/quicklaunch_28001.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/customize/resource/rp_ce_0678.png +SHA1-Digest: 4dGbvvlcMK9bEePatdS4fbLpm28= + +Name: system/lib/libimage-omx-common.so +SHA1-Digest: MNmhyWWpm+Bw0UIHhNTYkvqYwN4= + +Name: system/etc/firmware/fw_bcm4335_p2p.bin +SHA1-Digest: xmuNdIdduLdBGDKSfXL3O6FpdSw= + +Name: system/etc/security/cacerts/23f4c490.0 +SHA1-Digest: V/L3KgnCcIYZZFFbYbX2T0h9s5o= + +Name: system/lib/modules/gspca_main.ko +SHA1-Digest: KlLsTlXLahSqyPXUuGIAXnGEIms= + +Name: system/app/HTCShoeboxShare.apk +SHA1-Digest: QEbVt+qQFY0i1Tf134T/LAe63pk= + +Name: system/customize/MNS/default.xml +SHA1-Digest: z47LYgzlDKCwBwl9mBHusnPwjhs= + +Name: system/app/HTMLViewer.apk +SHA1-Digest: yMCsh1IO4sUwHp6N2/sEJFPt81U= + +Name: system/bin/mm-qcamera-test +SHA1-Digest: EF5+wtDx1q7KbKodN8Ws+scymd8= + +Name: system/bin/am +SHA1-Digest: tGduMx5JPECn+7U+fdIzcrCdrlk= + +Name: system/etc/bluetooth/auto_pairing.conf +SHA1-Digest: fb/w7V4UP/xpqHx8XMBbGn+pv/s= + +Name: system/etc/tfa/fm.eq +SHA1-Digest: PM6hx2pEVi+SuZ9Ef8C0eIPB808= + +Name: system/app/SocialManager.apk +SHA1-Digest: NqZf4AjkcCd8ydn5vq7CclydhSU= + +Name: system/etc/firmware/ILP0100_IPM_Code_out.bin +SHA1-Digest: DOSeFIkMt3Ikrg28LBJGaDPnZow= + +Name: system/app/Transfer.apk +SHA1-Digest: QO4BegU2QMSi0hMOfUGPBXH7eps= + +Name: system/bin/df +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/app/WeatherSyncProvider.apk +SHA1-Digest: 6CP9l+MN1VbZItebFFGjK/iQnC0= + +Name: system/app/HtcWeatherLiveWallpaper.apk +SHA1-Digest: w7imRD489Vqfwku6TobrDI9S6qg= + +Name: system/bin/dd +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/lib/hw/keystore.default.so +SHA1-Digest: Kw7S4QLStJVpdNG1TJuzfdcMmLk= + +Name: system/bin/bluetoothd +SHA1-Digest: 7sBnRXVMe/GmjkepS7xhIlybtVg= + +Name: system/customize/resource/quicklaunch_22288.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/etc/security/cacerts/9d6523ce.0 +SHA1-Digest: w//rjddcx+4ATCiAMsrJludK9w8= + +Name: system/lib/libDxDrmCAPI.so +SHA1-Digest: tEwmNKb4KtpDbSNoakPymxx/wb4= + +Name: system/media/audio/notifications/Glitter.mp3 +SHA1-Digest: rty15s/42rnP0lnT3zGX+BZBjio= + +Name: system/etc/tfa/playbackbeats.preset +SHA1-Digest: JYWGCVyXl3c9Rz9ndzK8oEuGmqk= + +Name: system/lib/libbluetoothd.so +SHA1-Digest: Hz17q18yvMR0kBFDMexqNR1fW+A= + +Name: META-INF/com/google/android/aroma/icons/Thumbs.db +SHA1-Digest: X9OsSoU/rnK/nV4e0VHprniiwgQ= + +Name: system/app/Prism_SocialFeedProvider.apk +SHA1-Digest: dHKG+JN2x8hojKS4aNeoa6mZ5AU= + +Name: system/fonts/DroidSansHebrew-Bold.ttf +SHA1-Digest: bnHHY3zVhU5icp9deYBYiLskRlM= + +Name: system/app/HTCShoeboxEngine.apk +SHA1-Digest: TYvp8xpwpBqYWg2PImZZVptlJFU= + +Name: system/app/HtcBackgroundDataWidget.apk +SHA1-Digest: jraLC1cknYx79fg5ieq8ZQWWt6M= + +Name: system/vendor/lib/libwvm.so +SHA1-Digest: ptdoe8vhKa6go0xhB4I9MbcX61s= + +Name: system/media/audio/notifications/Rust.mp3 +SHA1-Digest: c1Pf722FGAbxAM4raX1DyRrQPOM= + +Name: system/lib/soundfx/libbundlewrapper.so +SHA1-Digest: 1MghHxF0Qz8bCdp3kD2QUhozEAk= + +Name: system/bin/rmmod +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/media/weather/weather_l_fog_night.mp4 +SHA1-Digest: XN6Fgljv4Va/sNrw62edXwG4ums= + +Name: system/lib/hw/gralloc.default.so +SHA1-Digest: rGGOcIAZ/M4QSHm9RkRSHP83sbQ= + +Name: additions/desense/Nova.apk +SHA1-Digest: 1eVsnCKW6UinaJRJl9EMs/1Dut0= + +Name: additions/battery/bluep/app/SystemUI.apk +SHA1-Digest: qVbHJasTVDOW+xOfpkZM/bJoXEk= + +Name: system/lib/libril-qcril-hook-oem.so +SHA1-Digest: be3wqhWFo50pXZbU+r1RFH/ZPqQ= + +Name: system/usr/srec/config/en.us/models/generic.swiarb +SHA1-Digest: QGzUh5WkfKQRmuaI+sJtXBZrEFg= + +Name: system/media/audio/ringtones/Sense.mp3 +SHA1-Digest: gWLpBEu/EWnftqMy0ujTAwRipu0= + +Name: system/etc/bluetooth/audio.conf +SHA1-Digest: Mn9R6t7GUhTTFiY8C0BnVlE9ZPk= + +Name: system/app/FacebookEngine.apk +SHA1-Digest: eXpk9TbK5e9j9TTNFsEfnZyuFls= + +Name: system/etc/security/cacerts/a7d2cf64.0 +SHA1-Digest: ovUCtI0EY0f9I+ptWEk2GL/6+2Y= + +Name: system/lib/libbtio.so +SHA1-Digest: bxJog3JGeHJlfJ/4kFjDQOLgcrc= + +Name: system/bin/uptime +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/app/KidMode-google.apk +SHA1-Digest: uMAqf+vxSkG3rq3D00TAfrWKfCE= + +Name: system/etc/security/cacerts/3c58f906.0 +SHA1-Digest: /+9N6BT7ZtaVjBA7JzJT/bxXV7w= + +Name: system/lib/libvideoeditor_osal.so +SHA1-Digest: LiCj95XIBHPbxtkhtaNEgl8iBmo= + +Name: system/customize/cid_map.xml +SHA1-Digest: xWmNWm5qkKwdkxxKDxT1cj8LD/I= + +Name: system/bin/wpa_cli +SHA1-Digest: 3RfyiqfOHQQMUfI40GSxh+UC3PM= + +Name: system/etc/security/cacerts/d16a5865.0 +SHA1-Digest: uhdS7HZmT6TkFszu7r9Y2xzhX2w= + +Name: additions/fonts/klavika/Roboto-Italic.ttf +SHA1-Digest: IiFl+/BBcNqYP0q2dECLEoDLGoE= + +Name: system/lib/libdss.so +SHA1-Digest: wTFNKSD3d724zSu+hq4O61HW+FM= + +Name: system/etc/security/cacerts/882de061.0 +SHA1-Digest: fCt4s0+592o+QOkmDeYrj+o9kCI= + +Name: system/customize/resource/wallpapers_a_04.jpg +SHA1-Digest: T4D18RMWNdkL4kgL13z94ow46fY= + +Name: META-INF/com/google/android/aroma/themes/sense/nav.9.png +SHA1-Digest: aM5gHxPbCzYbkn/idDhNbfU01Q8= + +Name: system/etc/security/cacerts/8470719d.0 +SHA1-Digest: f5QED3DbZCbDT1sNmR7e40z3aao= + +Name: system/customize/resource/rp_ce_0560.png +SHA1-Digest: wST8AmAajkDNdy69DLoM7ITiFXo= + +Name: system/etc/security/cacerts/e775ed2d.0 +SHA1-Digest: 0GkuHmAcEDLQf+8r8yG75doHYQ4= + +Name: system/etc/firmware/vidc.b03 +SHA1-Digest: zvMTXDOkNwpbPkEqqr+douzUurA= + +Name: system/etc/firmware/vidc.b02 +SHA1-Digest: xRSzjS+YH2eHexFe51xH6Zs/JYo= + +Name: system/media/GPU/stylizeContrastRamp.bmp +SHA1-Digest: f/sWG+Rz0zuBnFAYWEidLb8Ov6Y= + +Name: system/etc/firmware/vidc.b01 +SHA1-Digest: ljBiUzT6+KKzOK4Z6xGaDGENZvY= + +Name: system/lib/libqmi_common_so.so +SHA1-Digest: jBuoamOOXTMVFujkXnO30Zg6JvU= + +Name: system/lib/libmm-audio-resampler.so +SHA1-Digest: 0FCirfvUw/aoxvgAFuZ8ikoVIpM= + +Name: system/etc/soundimage/srsfx_trumedia_music.cfg +SHA1-Digest: 1hPAjcb1kqGpWbhoSoRVZUc4qfA= + +Name: system/customize/resource/allapplication_24001.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: additions/battery/greenp/app/SystemUI.apk +SHA1-Digest: teUcNPNEiRebW8MyEKO2xDhP/rQ= + +Name: system/etc/security/cacerts/c9f83a1c.0 +SHA1-Digest: 9i3z/3hCXgOYpEWeFkt7O27uy4g= + +Name: system/lib/libgnmc_decoder.2.5.9.4.so +SHA1-Digest: cZh1S1h4FqhhMxcvmF7S0NXnlz0= + +Name: system/fonts/HelveticaNeueLTPro-Cn.otf +SHA1-Digest: G7YRo/dTEkda3YYdfuhU0P8S7Ck= + +Name: system/app/HtcAirplaneModeWidget.apk +SHA1-Digest: hl4DIIfXiW+w/pt6NwEt7u7S8eI= + +Name: system/bin/bmgr +SHA1-Digest: txVKgTGjXkxUtbIhsor6EUCfLsM= + +Name: system/app/HtcWiFiWidget.apk +SHA1-Digest: 9nTVBC3bg9oNjZ3TYL4omvNGcRQ= + +Name: system/etc/security/cacerts/895cad1a.0 +SHA1-Digest: I6mXiEZNYMrute2XDIugRzsK/f8= + +Name: system/usr/srec/config/en.us/dictionary/cmu6plus.ok.zip +SHA1-Digest: gix9zeNXUv3/qb72caDqmlPws9U= + +Name: system/app/HtcNotesPainterView.apk +SHA1-Digest: UFVGp3UU3lsaqTQxO2fDEHajD7Q= + +Name: system/media/audio/notifications/Creme.mp3 +SHA1-Digest: eY+Bw9iDZ5jM0tVE6B8Fydg9iwE= + +Name: system/bin/gzip +SHA1-Digest: 1vab/ZEiI2NqAujm3NoLAy9fQKk= + +Name: system/customize/resource/quicklaunch_250.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/etc/tfa/voiceWB_l.eq +SHA1-Digest: akzJZd8ilz4aAsWHG6uC3H5L+tk= + +Name: system/media/weather/weather_l_hot.mp4 +SHA1-Digest: spPYbhPUE7F72TdHD8OPch8w+sg= + +Name: system/bin/lsc_camera +SHA1-Digest: rkt4qcEY9dLXtQRPN37TL6QCCAU= + +Name: system/app/HtcMessageUploader.apk +SHA1-Digest: 6WRmDCSjTWKKCJCQTab4u2rtaOM= + +Name: system/etc/security/cacerts/1dac3003.0 +SHA1-Digest: mgJ5j9kIbAF3wxCvrgctrBj5mEI= + +Name: system/lib/libMusicVisualizer.so +SHA1-Digest: wFucyEWcD14CXKxeOcRZrD08C8E= + +Name: system/app/PolarisOffice.apk +SHA1-Digest: SLH9RO+IH8658ftoMGT3oxn75RY= + +Name: system/etc/firmware/vidc.b00 +SHA1-Digest: yfS8/3kMSaL0+ItjAbIMptehGm0= + +Name: system/app/IMEXT9Ukrainian.apk +SHA1-Digest: hfj3GUHC/rFymobDyS+cOfoVPRo= + +Name: system/bin/zchgd +SHA1-Digest: FoQo5zaAUntpEpKxCY4Ij8K6nDo= + +Name: system/etc/permissions/platform.xml +SHA1-Digest: S36kP7qxXw/1k5VR0iZNNzfRycg= + +Name: system/lib/libwt6pptrdr.so +SHA1-Digest: yV9ut9izv9pC3uHuwGusX73po50= + +Name: system/app/HtcDataStripWidget.apk +SHA1-Digest: ilW8Kf+5P8fEGWDCiLP9QsUOahw= + +Name: system/app/HtcContactsDNATransfer.apk +SHA1-Digest: Y/LKOoUnzguc5LBzs5uAVCsNoz4= + +Name: system/etc/security/cacerts/c3a6a9ad.0 +SHA1-Digest: fLZHDOpbrGZWvLkuE3qgKE8NxuU= + +Name: system/lib/hw/copybit.msm8960.so +SHA1-Digest: xHGReRk1BCM7kcZ8rI5X9e3HEpU= + +Name: system/lib/libaah_rtp.so +SHA1-Digest: qd8eMrRU+Jw8l1H/vjttFqhJSiE= + +Name: system/bin/start +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/lib/libchromatix_s5k6a1gx_default_video.so +SHA1-Digest: oXZchM6Km012QC4pyTlRjpp3nKY= + +Name: system/etc/NOTICE.html.gz +SHA1-Digest: biuUwzhCgq5GjrKgeiwO+uJ0xWA= + +Name: system/lib/pp_proc_plugin.so +SHA1-Digest: uPqlxh4p3dtUEbNWzJMSHdphVrY= + +Name: system/bin/mm-mpo-dec-test +SHA1-Digest: VvJ1QwHTRyof+f6nnBPwnJOKfs4= + +Name: system/bin/hd +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/app/HTCWeatherClockWidgetAgent.apk +SHA1-Digest: 77fowdXm0shCLvQ6PgCVrDF4D3Q= + +Name: system/media/audio/notifications/Olive.mp3 +SHA1-Digest: 4Qt31whgN0ERMv9hrYejogl7S4g= + +Name: system/media/zchgd/batt_20.rle +SHA1-Digest: H94fJLAo1VJ12d4VgM7RqrxEJQI= + +Name: system/app/Facebook.apk +SHA1-Digest: Prwx/foKi7WktdFJHENqiugdIWQ= + +Name: system/app/HtcCalendarWidgets.apk +SHA1-Digest: 9dbVmm1DnXDtieCR2CBIM1HSODA= + +Name: system/app/VoiceSearchStub.apk +SHA1-Digest: mB+R5R/hWaSuwUaxF8zQ1VYbtLU= + +Name: system/media/zchgd/charging_09.rle +SHA1-Digest: S48C90ViaLLTNuLvRQ95MBU8/DM= + +Name: system/lib/libmorpho_edit_engine.so +SHA1-Digest: sn2u9olIS//pqmIFPXbT04JYjd8= + +Name: META-INF/com/google/android/aroma/themes/sense/cb_on_sel.png +SHA1-Digest: GFe5LzZlbXSly+JDxME4ogZqEZw= + +Name: system/media/GPU/dot_mask_16x16.bmp +SHA1-Digest: qrLAwxXlluYbqatU06+Rg6TiKS8= + +Name: system/lib/libchromatix_ov8838_preview.so +SHA1-Digest: y2tKKWPQry3P/TEIQ+0hJ3Xfv54= + +Name: system/media/zchgd/charging_03.rle +SHA1-Digest: nTXp2Ml9w2TPiqd8Vi6NR1wpmYc= + +Name: system/media/GPU/ContrastCurveSet.bmp +SHA1-Digest: roYDdcsfTVFwpM/ZIzVQrBie/7A= + +Name: system/etc/permissions/com.broadcom.bt.le.xml +SHA1-Digest: QPYcOsj6a6cagjBQZJDy23evcYM= + +Name: system/lib/libGLES_trace.so +SHA1-Digest: /7AU8F7zLukLhk/p+EVAhJI2ZCk= + +Name: META-INF/com/google/android/update-binary +SHA1-Digest: VtCr1jnXgXMfBohepsvLkllYIg0= + +Name: system/etc/security/cacerts/3e7271e8.0 +SHA1-Digest: exnkaZiA8uIb4yIVkEyv4B8Mo40= + +Name: system/etc/security/cacerts/89c02a45.0 +SHA1-Digest: 6k/+zqCB5f/qyWJjkf/PvVoNG64= + +Name: system/etc/tfa/voice_l.eq +SHA1-Digest: akzJZd8ilz4aAsWHG6uC3H5L+tk= + +Name: system/lib/libcameraasd.so +SHA1-Digest: iMQBAZr0WL+9RaP4uevXuWrxIPI= + +Name: system/lib/libETC1.so +SHA1-Digest: DisCtmBA8J/88Xn3Y+OY7EZXTvg= + +Name: system/fonts/Lohit-Bengali.ttf +SHA1-Digest: L8kDnfbVNjOJMtDSZTd/OjkndS8= + +Name: system/media/zchgd/charging_05.rle +SHA1-Digest: RxWagAYJ9pk2xnZppBnwdNUpdxo= + +Name: system/media/audio/ringtones/Vanilla.mp3 +SHA1-Digest: 1SxbgXxMdYvn4EXMSHMPh8GVdQA= + +Name: system/bin/screenshot +SHA1-Digest: /E332dYacBltFf8H8F/zw3oBZjM= + +Name: system/lib/libOpenCL.so +SHA1-Digest: 2U/EshFRq11j4eO+XBr3mWkYM4M= + +Name: system/bin/cir_fw_update +SHA1-Digest: navUdcWtB/ORyzaZ3XN6SiFG+fk= + +Name: system/media/audio/notifications/Pear.mp3 +SHA1-Digest: /sAdGHGjmvas8wjGpd1QNAbgiRo= + +Name: system/media/mms/kddi_earthquake_alert.mp3 +SHA1-Digest: pabH2nWTXdOSLBAI+pJya7MR/r4= + +Name: system/lib/libvideoeditor_core.so +SHA1-Digest: QJ7mokQcRuTYZts+UF0nZ3YP+Z8= + +Name: system/lib/bluez-plugin/network.so +SHA1-Digest: Qr1Y0OxuVpgErhfyQesfBDIo/l4= + +Name: system/bin/thermald +SHA1-Digest: Wr+mMKa/8d+VBbBWkhmGqA+2qLI= + +Name: system/lib/libexpat.so +SHA1-Digest: CIai+dbiAT4X2hD/OBIyBmnPXQY= + +Name: META-INF/com/google/android/aroma/themes/sense/radio_on_sel.png +SHA1-Digest: ResWXZhJLGsmdQXzieaC7zI84/8= + +Name: system/app/HtcModeClient.apk +SHA1-Digest: i5kc3hPIp+8VF3FzqdGNbxX45hg= + +Name: system/customize/resource/trickdroid.jpg +SHA1-Digest: 3NwsI8FC0rXGxfcHxfn1x/bJkUE= + +Name: system/app/Flashlight.apk +SHA1-Digest: k9X07SW1eOeHcDCztT8gNsJEzPg= + +Name: META-INF/com/google/android/aroma/fonts/big.png +SHA1-Digest: oHYrbDXlnhjFwHqNQePor+/Vf/A= + +Name: system/etc/security/cacerts/27af790d.0 +SHA1-Digest: tWr5feX55f+zArlEQVaA+3FTUZk= + +Name: system/customize/resource/quicklaunch_20201.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/lib/libaudioutils.so +SHA1-Digest: mDBmNK8faRMvHrJXReTkud2pMvI= + +Name: system/etc/hltof.bin +SHA1-Digest: axmU3A62c/M9Vx5bhZJfCFNPaXo= + +Name: system/vendor/pittpatt/models/detection/yaw_roll_face_detectors. + 6/head-y0-yi45-p0-pi45-rn30-ri30.5-v24/full_model.bin +SHA1-Digest: zd4aqRFsrWVCg9MMHAQMpm8tWyY= + +Name: system/lib/libsqlite_jni.so +SHA1-Digest: 7wxca+iSFexD8BXG8ula5zZ5P3Y= + +Name: system/bin/ndc +SHA1-Digest: eNgJroW7M3Klt/t/m75BdCRGHHU= + +Name: system/lib/libskia.so +SHA1-Digest: EZG3k40O/U9SOJ8W6+7Dgaoi5EI= + +Name: system/usr/srec/en-US/google_hotword.config +SHA1-Digest: Q8EXKoSue5BQvI8aQIC5FgDXr7M= + +Name: system/lib/libdrmframework.so +SHA1-Digest: HJX1qqHjuw4Hnr4l4GqoU5q2Wls= + +Name: system/lib/modules/moc_crypto.ko.3.4.10 +SHA1-Digest: wGyXq6GEMzMsKIdOwWD7NVhuMP8= + +Name: system/lib/libandroid_runtime.so +SHA1-Digest: 0i75no3JWAtjL8L1ZNMqcx2B8eI= + +Name: system/lib/libgabi++.so +SHA1-Digest: 5XuI+2FjNoarhaQBX0/mDHFI2gk= + +Name: system/bin/ip +SHA1-Digest: S1K6wQEVcIhGji4ZNVRl6NaCQw4= + +Name: system/bin/rtspserver +SHA1-Digest: HV6HaJdUpLldUaQDM8RePzn/NXI= + +Name: additions/fonts/segoewp/Roboto-Italic.ttf +SHA1-Digest: GJbcewXmkyB3YcV4qvzeo4E7k0c= + +Name: system/etc/permissions/android.hardware.camera.flash-autofocus.x + ml +SHA1-Digest: B9lECmkbQ6pSctxuPBeUiDPmthA= + +Name: system/bin/id +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: META-INF/com/google/android/aroma/icons/personalize.png +SHA1-Digest: mnAYF0GaMh88zuP56SKiEcxq2pk= + +Name: system/lib/libstagefright_soft_rawdec.so +SHA1-Digest: Ga+toLhkzPGD2fRM3Fh6XkM1VYM= + +Name: system/bin/setprop +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/bin/kill +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/etc/image_htc_earbud.bin +SHA1-Digest: BQvgRVzmndETmB2zqTO7nDfu05c= + +Name: system/app/OneTimeInitializer.apk +SHA1-Digest: vNp5PcD4OMPv/kdCktZh+Ym1GLs= + +Name: system/usr/share/partials/ticklist.csv +SHA1-Digest: /KbguW9SBGbKSzULShtwb5UkaLE= + +Name: system/app/JETCET_PRINT_S50.apk +SHA1-Digest: 9VXwMt6DgEL63siq5knL0+AtlrQ= + +Name: system/etc/permissions/com.android.location.provider.xml +SHA1-Digest: LTdinhy89ODvYRYxUm8yTOSA5VM= + +Name: system/lib/libzeroeditor_videofilters.so +SHA1-Digest: MhKTiBo1+CFolLw++j0TlgYnVDI= + +Name: system/bin/ln +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/lib/libChange.so +SHA1-Digest: 72HvBVw5Fgj9jvfl47G2qLaoSY0= + +Name: system/etc/capability.xml +SHA1-Digest: k+jsHQZ+/yBYeXC+p3She4CvEZ4= + +Name: system/bin/ls +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: META-INF/com/google/android/aroma/icons/customize.png +SHA1-Digest: BaZ7Q5/xMfjVC22hsYmQ3lfKfBw= + +Name: system/bin/mksh +SHA1-Digest: AtbTC0Y345Q8WUktAbZDG2IfbpY= + +Name: system/etc/tfa/fm.preset +SHA1-Digest: 5sbhFGjzewa4Pfs10aaWH7c80Ew= + +Name: system/media/audio/ringtones/Pearl.mp3 +SHA1-Digest: Y7Bq9HYiesPOPZ4zZIOF5V7zx/s= + +Name: system/etc/permissions/com.orange.authentication.simcard.xml +SHA1-Digest: epCNDZ7eEVaCAtm40i+f5+XFoXs= + +Name: system/customize/resource/allapplication_23801.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/media/audio/notifications/Saffron.mp3 +SHA1-Digest: +FdZMPoLejhfa9CPC/QYkFdEQYo= + +Name: META-INF/com/google/android/aroma/icons/nova.png +SHA1-Digest: Gx/1cvONcm447ffX5qizF3IxASg= + +Name: system/bin/ks +SHA1-Digest: x+AEts2KwouOQ9L/279//gmTFh0= + +Name: system/lib/libm.so +SHA1-Digest: OmrEBW5pnXLTquKcOd7mAcs2wvg= + +Name: system/lib/libdrmdecrypt.so +SHA1-Digest: es0IN1VgjrwJUAcwNb52T9sr0hY= + +Name: system/media/zchgd/charging_02.rle +SHA1-Digest: EXqLHmDATH06bTfx8yaOikW1qOE= + +Name: system/tts/lang_pico/de-DE_ta.bin +SHA1-Digest: 4+D9z4UNIRauW5tuRA/6Z8gjRZo= + +Name: system/bin/hostapd +SHA1-Digest: fMu31XZwo01HY5cOlnmiIQunxYw= + +Name: system/etc/voicemail-conf.xml +SHA1-Digest: gEhglUYhKRFe/gLhE94bPPBBkis= + +Name: system/lib/libmm-abl-oem.so +SHA1-Digest: uBp7lWNkxS4wmsAwAcp5lxotpjo= + +Name: system/usr/srec/en-US/offensive_word_normalizer +SHA1-Digest: RIsPYtNeY/zpfXhd80jm+FtPTEk= + +Name: system/app/HtcCompressViewer.apk +SHA1-Digest: vxZUe/m8Xzsp7qS1GjCt+/smPrw= + +Name: META-INF/com/google/android/aroma/changelog.txt +SHA1-Digest: o2QwUA/8EDFcz6GBRndT/PwBKi8= + +Name: system/media/audio/ringtones/Pink.mp3 +SHA1-Digest: gR43IxTs1H5pyreV9nasXQs3eIY= + +Name: system/lib/libchromatix_vd6869_hdr.so +SHA1-Digest: pFxSeF/efHQATVq4GV9S51GAFBM= + +Name: system/media/PFFprec_600.emd +SHA1-Digest: Lp6CpxDd7/os6xa7v/mAzUATs9g= + +Name: system/usr/share/partials/partials_H_gb.csv +SHA1-Digest: 6Wde5jH/xw/Icvl+fVnJJg04/6A= + +Name: system/app/SoundSetDownloadManager.apk +SHA1-Digest: B/pLMa5+yu2iq08J9EsA2yfGptQ= + +Name: system/lib/libwlwpscli +SHA1-Digest: NUaizgnrnzhRVL2RlE14srPeXJE= + +Name: system/lib/libjavacore.so +SHA1-Digest: yEafnvlNdxnzH66U6FtN4xpfauA= + +Name: system/media/audio/ringtones/Brass.mp3 +SHA1-Digest: rtkyk28W/Vwn5xyqRHJsvdlqFBw= + +Name: system/customize/resource/quicklaunch_65501.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: additions/wipe/bash +SHA1-Digest: F69Mawxw1zmAOQLGd0uxGGKimhA= + +Name: system/usr/share/partials/partials_CW_rr.csv +SHA1-Digest: QGpuL87jnCrX6qj+w6CvO+Yr7+M= + +Name: system/etc/security/cacerts/7651b327.0 +SHA1-Digest: j/CjK50zYtj/xzaZFhptUghXaPk= + +Name: system/bin/ioctl +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/bin/mv +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/app/IMEXT9Italian.apk +SHA1-Digest: tPMuKDobkkYFEZRFnFTfMeQSUE4= + +Name: data/app/com.google.android.apps.plus-1.apk +SHA1-Digest: QAB8+ZNxBkl+9l3N05269ljXCoA= + +Name: system/lib/hw/lights.msm8960.so +SHA1-Digest: gqFab0FjUHHiVj7166kfG6QtQnI= + +Name: system/media/audio/ringtones/Cerise.mp3 +SHA1-Digest: I8CAHjfUuAgTIWNkTtL9cZ2M/Vk= + +Name: system/etc/security/cacerts/219d9499.0 +SHA1-Digest: kAbEu38ad02aTzdrF222x0w0M0o= + +Name: system/lib/libmmcamera_statsproc31.so +SHA1-Digest: DX1NdQQqpsUGQErdcbQ//jfSlA0= + +Name: system/usr/icu/icudt48l.dat +SHA1-Digest: bqcC8epqeTv8IrZ8PKMsVCHLIOk= + +Name: system/fonts/ARDJ-KK.ttf +SHA1-Digest: L0wleYpEe9myxwgMOqVm/8e0HsU= + +Name: system/app/VpnDialogs.apk +SHA1-Digest: c8TzYq9l7TookjWKdLjIghkZCBQ= + +Name: system/lib/libDxAndroidSpecific.so +SHA1-Digest: rQT3QlVF1jXaIEsBqnDZnxkaya4= + +Name: system/media/audio/alarms/Jade.mp3 +SHA1-Digest: st/f7XW9r0PEAVsJ0jMO5w8rGdA= + +Name: system/lib/libpphwrcore.so +SHA1-Digest: f1uhaPpKnaj+Kmjv5fCPZErdjL8= + +Name: system/app/IMEXT9Swedish.apk +SHA1-Digest: LhKkqC1KDlIvxYWMsjmF1OHiu9U= + +Name: system/etc/security/cacerts/60afe812.0 +SHA1-Digest: q2HXyTTJrYXtlcX9A4n+Smodlco= + +Name: system/usr/srec/en-US/hotword_symbols +SHA1-Digest: 7qeVa2EIhFOtRUo55/SFRc4EIzE= + +Name: system/app/ZeroEditing.apk +SHA1-Digest: mOLSwSm9bsuD3nPPvvhX9T4DMlc= + +Name: system/app/Trim_n_Slow.apk +SHA1-Digest: AZEfKG/xEPUAIwVE+jGNBaZYdxQ= + +Name: system/etc/security/cacerts/f0a38a80.0 +SHA1-Digest: 477jilsDvssMgn9iF5DSp2L1dBg= + +Name: system/vendor/pittpatt/models/detection/yaw_roll_face_detectors. + 6/head-y0-yi45-p0-pi45-rp30-ri30.5-v24/full_model.bin +SHA1-Digest: 759/0Df6xJs4gqdB7a/kA81yX44= + +Name: system/lib/hw/power.default.so +SHA1-Digest: KocExwwT9Wlsko41O/XG5hcJC1M= + +Name: system/lib/libmmwfdsinkinterface.so +SHA1-Digest: bKq2GUyzGBAvw4B0nt+N50JkLEM= + +Name: system/lib/libdbus.so +SHA1-Digest: p1ww3oTzHuLjdDpP+Bm8WOTiaso= + +Name: system/bin/input +SHA1-Digest: QALzgk6btxyAeKYglJuc20newks= + +Name: system/customize/resource/wallpapers_a_01.jpg +SHA1-Digest: 0HAE1p7QQHJZkqh+wgOHMYLXSxI= + +Name: system/lib/libalmashot-seamless.so +SHA1-Digest: odBXwbyZHasOa2yazKJXHW7XRaQ= + +Name: system/media/zchgd/batt_60.rle +SHA1-Digest: HITkPml3u3zwomD5uAVs2cNcEoU= + +Name: system/lib/hw/local_time.default.so +SHA1-Digest: wVJsmcRTLw0INlGLg5xosWzeM5k= + +Name: system/lib/libmmwfdinterface.so +SHA1-Digest: e1K+IdYrlEgxRKnBxK3zQMt0ZQ8= + +Name: system/bin/pm +SHA1-Digest: XY3kUD4TG6bh8EMZiFFrRWiG7Ec= + +Name: system/lib/libext2_com_err.so +SHA1-Digest: BSLIAt5ebdmwN9ekWwGR3O13rm4= + +Name: system/etc/firmware/fw_bcm4335.bin +SHA1-Digest: xmuNdIdduLdBGDKSfXL3O6FpdSw= + +Name: system/bin/mm-mpo-enc-test +SHA1-Digest: FlKv0JpU9BEcqz2fVsd0y41FbVA= + +Name: system/bin/ps +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: additions/desense/Apex.apk +SHA1-Digest: yU8lUBgl5xbhGwJfgVRaJAEXbBA= + +Name: system/etc/firmware/a300_pm4.fw +SHA1-Digest: QrPhH4bO2hPUjoQPVsQsXEBBB+w= + +Name: system/lib/libchromatix_ov2722_hdr.so +SHA1-Digest: /J4dEZtuQF+qjuesj/K23RCHXHQ= + +Name: system/media/audio/alarms/Amazon.mp3 +SHA1-Digest: XFh/W7gZE4T3l7gSJ7jIzJrd1xk= + +Name: system/etc/tfa/voiceWB.eq +SHA1-Digest: akzJZd8ilz4aAsWHG6uC3H5L+tk= + +Name: system/bin/port-bridge +SHA1-Digest: G3WlcqGqIhZPLjXxq1+4mmAAC5I= + +Name: additions/camera_4.2/lib/libjni_filtershow_filters.so +SHA1-Digest: vvad3jmOu8bieJWshtJkzVGu23s= + +Name: system/app/IMEXT9Norwegian.apk +SHA1-Digest: tX/b7yQ9VRT2TaAcbNs2KFSqM+o= + +Name: system/etc/sdk/sdkinfo.xml +SHA1-Digest: strBQ803H7m7Mmxlc4JuWgJPzPs= + +Name: system/lib/libImageAlignment.so +SHA1-Digest: LPIBnUI34KZg/FtVJAxC+90hmlY= + +Name: system/bin/dalvik_coredump.sh +SHA1-Digest: 7YfCyuA6+7KtXknKMOXdB4sgz/w= + +Name: system/fonts/Lohit-Telugu.ttf +SHA1-Digest: W03fOM/KRs6NXuT+IWU6wXXW2QY= + +Name: system/etc/image_ibeats_2vol.bin +SHA1-Digest: vjvhr7ejqmQ60pXuUxqB9veV0pk= + +Name: system/tts/lang_pico/es-ES_ta.bin +SHA1-Digest: NqpVUDr2Zot71OE2b9H9alSFvmU= + +Name: system/app/BackupRestoreConfirmation.apk +SHA1-Digest: qDntanWX+MnYNhoO2RrVJD87mf8= + +Name: system/lib/libstagefright_enc_common.so +SHA1-Digest: +uGp308y3njBj1+q+Ez+d+qGcBI= + +Name: system/media/audio/notifications/Capri.mp3 +SHA1-Digest: fb0f2+DEm9/IZf59qQnNlT7qUOE= + +Name: system/lib/libsurfaceflinger.so +SHA1-Digest: hEkIGnHbCwac26zeYAvxLwnbC7s= + +Name: system/bin/tc +SHA1-Digest: 8ZXftveIrr6x1KKzb8a3wovrgqY= + +Name: system/etc/updatecmds/google_generic_update.txt +SHA1-Digest: 1Vp4IR8a20SbLBsHcaOPbkUf+NE= + +Name: system/bin/dmagent +SHA1-Digest: s2W0Pg6erv4oQ26QEd78D3jSdEw= + +Name: system/fonts/MTLmr3m.ttf +SHA1-Digest: Btnmblk0kwRaZjo2AkofmEVA7Os= + +Name: system/lib/libOlaEngineNew.so +SHA1-Digest: FwCZ9bC1z9o3XNY48HgLrHVmTJ4= + +Name: system/bin/brcmapd +SHA1-Digest: +shHcui55nH5pIxgOMjZvdfheMg= + +Name: system/media/audio/ringtones/Yellow.mp3 +SHA1-Digest: 5Rs/XQrj0a56+wwQ8FyPzWpIh4Q= + +Name: system/etc/security/cacerts/a15b3b6b.0 +SHA1-Digest: 8ZOob41YQP9QUVzJd/7ktNxnMRw= + +Name: system/customize/resource/allapplication_26801.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/etc/security/cacerts/33815e15.0 +SHA1-Digest: Tg2OusUL9dKQej4AiGYCRSEgVyY= + +Name: system/usr/srec/en-US/google_hotword_logistic +SHA1-Digest: ockBZc2VMYxuaYq6KET9/bVJbtA= + +Name: system/lib/libstagefright_soft_amrwbenc.so +SHA1-Digest: Zm+NDMWcQI/sUAKSa6efaHHQQDk= + +Name: system/etc/AudioBTIDnew.csv +SHA1-Digest: Gqh/UYdUamQ0hhKaMR4rftiJS6M= + +Name: system/lib/libOpenSLES.so +SHA1-Digest: Nlrm0ZmW33UuQ232fA7tPULKFGU= + +Name: system/lib/libgnmc_aactag.2.5.9.4.so +SHA1-Digest: az7H58js2u60b15IB/ckj2nAzSo= + +Name: system/lib/libwebcore.so +SHA1-Digest: iKlwYnQeokdWgKAQrWeI7sl6NMc= + +Name: system/media/audio/notifications/Lilac.mp3 +SHA1-Digest: w+lAsOjMjvDGROYnkhUVYaGLEys= + +Name: system/lib/libhwui.so +SHA1-Digest: UoAbW8Q/oPhsOseLlhCU5IOWHKc= + +Name: system/media/audio/ringtones/Mustard.mp3 +SHA1-Digest: frTfMvAlgAaaFiuqQ8uhoNrfNG8= + +Name: system/etc/tfa/voice.preset +SHA1-Digest: OVBiITpEEwnpRzjGcCTdTkgmGA4= + +Name: system/media/weather/weather_l_thunderstorm_night.mp4 +SHA1-Digest: xeaglmdE6nR7llDH3GPZj+kCNOU= + +Name: system/usr/share/partials/partials_A_rr.csv +SHA1-Digest: sTqwPLgB5lu1fU2zG83kvGOpDBk= + +Name: system/lib/libsrec_jni.so +SHA1-Digest: suu6aNn6SkQtawHo52QvreQvxZM= + +Name: system/media/GPU/header32bpp.bmp +SHA1-Digest: cVd7vUZ5xiCRD3XhuTFpPUjxC0w= + +Name: system/fonts/DroidSans-Bold.ttf +SHA1-Digest: Ykc18CQi8T5QzPRm8NKe3aBa2zY= + +Name: system/etc/agps_rm +SHA1-Digest: 2jmj7l5rSw0yVb/vlWAYkK/YBwk= + +Name: system/lib/modules/bcmdhd.ko +SHA1-Digest: 7433DTw/6R0GuMYjNT3f6hK28Qo= + +Name: system/app/MyGoogleTaskPlugin.apk +SHA1-Digest: 4gBWeaGazltpjDNH9aeY/1aZbjs= + +Name: system/bin/akmd +SHA1-Digest: 1rnxMQDAvhxkKBbWTLgO2Rf8vm4= + +Name: system/etc/bluetooth/iop_device_list.conf +SHA1-Digest: TdKSuRkPZjKgvTvEC8jyGaCSdr8= + +Name: system/lib/libmmipl.so +SHA1-Digest: rLSAhTG3L0rwxBzqS2zxb1uktEs= + +Name: system/lib/libdmt_vocalizer.so +SHA1-Digest: sLaTmgeTwSz5MXjCdZLgzJ7uNmA= + +Name: system/lib/libOmxVdec.so +SHA1-Digest: Xx794TUu1yBalixHbvb4FEzZI/k= + +Name: additions/fonts/veggieburger/Roboto-BoldItalic.ttf +SHA1-Digest: 5v6ke/vpr2ZsccH1w33Ogr5YAbA= + +Name: system/etc/security/cacerts/10531352.0 +SHA1-Digest: x031sSTTrg99nYnqERvbmDu8aP8= + +Name: system/customize/resource/quicklaunch_21403.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/app/HTCMediaAutoUploadSetting.apk +SHA1-Digest: Nu7rneZwk3Y5VE40//G8RPBs0bY= + +Name: system/bin/wpscli_test_cmd +SHA1-Digest: 8mEoufwud+K7DoqomZo5ysFUZjg= + +Name: system/lib/soundfx/libaudiopreprocessing.so +SHA1-Digest: OGmb+76DPWV8aUIrhOaNNMOqPig= + +Name: system/lib/libchromatix_vd6869_video_hdr.so +SHA1-Digest: CXe+Qq3saE7qCRPDWJccNQRAokc= + +Name: system/customize/resource/allapplication_228.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/bin/dhcpcd +SHA1-Digest: GCXsC3peq3eZxlBG1gWdGIJa99k= + +Name: data/app/com.melodis.midomiMusicIdentifier.freemium-1.apk +SHA1-Digest: 8kqn6tJQS00oUx0SCWI1IlHJnZE= + +Name: system/bin/l2_profile_exchange +SHA1-Digest: a8m3prEi4PBFVD9X8YMRw5X+3YM= + +Name: system/fonts/AndroidClock_Highlight.ttf +SHA1-Digest: 0vRHOkM++Y5hREyvokR3HBnI2ig= + +Name: system/lib/libloc_adapter.so +SHA1-Digest: miK40rr48n7kDIZBXx3vn/lGLHA= + +Name: system/bin/rm +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/framework/com.htc.android.home.res.apk +SHA1-Digest: re117fgRZeW2tVx2p1JKtMChGUk= + +Name: system/media/audio/alarms/Turquoise.mp3 +SHA1-Digest: UibvlSTXFjMIdQ/y/DXqDSmVSl0= + +Name: system/lib/libchromatix_imx135_zsl.so +SHA1-Digest: YZFAn1ti4/djMLUMAqZ2hXvBhUc= + +Name: system/lib/libgoogle_endpointer_jni.so +SHA1-Digest: kX/O1CZ4pT6phlKrbw58QLLbxfA= + +Name: system/lib/libbt-aptx-4.1.1.so +SHA1-Digest: rZNVP7xWHQX1KdgkGtpAjtS7XKE= + +Name: system/framework/requestsync.jar +SHA1-Digest: MZzwRoXa1GjyxtsTIBl/BhMh3U0= + +Name: system/etc/permissions/android.hardware.nfc.xml +SHA1-Digest: GIaOjWIx6Re8D6cSufWoe3tSkw4= + +Name: system/lib/hw/nfc.m7.so +SHA1-Digest: PtlsI0eQwDu+rjiepUf2NuXeX3s= + +Name: system/media/zchgd/batt_90.rle +SHA1-Digest: 3rIXvJMnp/LK3LWpJB3ohkz9TNo= + +Name: system/customize/resource/wallpapers_a_00.jpg +SHA1-Digest: dg46UFdE7l2FDYlgdi13jn8AhfM= + +Name: system/app/Tag.apk +SHA1-Digest: XsuowlwMALDbq3jjMOqucg0RoiY= + +Name: system/customize/resource/bootanimation.zip +SHA1-Digest: Tw1xSnBQ+Cx0EMGuYNLpGyakSqU= + +Name: system/lib/libdvm.so +SHA1-Digest: vkchp8WS5UIbIhUfiAEvnWOI+5o= + +Name: system/bin/sh +SHA1-Digest: PHOOpAG9IpARYrBB1CtNeBbyugQ= + +Name: system/lib/libmdnssd.so +SHA1-Digest: U4Qb9R8jnuAOfrQgekqZqb0Tayw= + +Name: system/app/FlickrEngine.apk +SHA1-Digest: uEJLrtNP5Ytz3uiqoS+p+7zeSLk= + +Name: system/etc/security/cacerts/ee7cd6fb.0 +SHA1-Digest: UwvGu9gadYis3G+kKIIPVzHgGRk= + +Name: system/media/audio/ringtones/Aqua.mp3 +SHA1-Digest: pXW9Xsy3UIIzS/d/jxdybBCwJjQ= + +Name: system/app/LocationPicker.apk +SHA1-Digest: RKkwziKH/3I7fFaXh1t5zXtt3Ro= + +Name: system/vendor/pittpatt/models/detection/yaw_roll_face_detectors. + 6/head-y0-yi45-p0-pi45-r0-ri30.4a-v24/full_model.bin +SHA1-Digest: qC6ZM1KBN5XExmxhUXM5McociJ8= + +Name: system/customize/resource/quicklaunch_23802.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: additions/dormancy/dormancy.sh +SHA1-Digest: Pmig1OJ+4mh3pKKV03INFu3K6FM= + +Name: system/media/audio/notifications/Lime.mp3 +SHA1-Digest: 1K5E3SRxUBEPb+u7vMicCwIn+/Y= + +Name: system/app/HtcDLNAMiddleLayer.apk +SHA1-Digest: /QT/WWOxQN7s66EpGbZPW7TZemQ= + +Name: system/lib/libconfigdb.so +SHA1-Digest: viC/s/cNiFQUKUjeyjUK0vS7EKs= + +Name: system/fonts/DroidSansHebrew-Regular.ttf +SHA1-Digest: x+RcN58KCjuoXGnq7mti4m/7gag= + +Name: system/bin/route +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/etc/security/cacerts/c8763593.0 +SHA1-Digest: kZMwI4zPBDpymR428YsYQNm4Etw= + +Name: system/usr/idc/qwerty.idc +SHA1-Digest: 5oeOyx5R5vdh3tPnK4A+NyN9jzg= + +Name: system/media/audio/ui/Volume-2.flac +SHA1-Digest: WIvWiqi1f2nRqevMotkyhRR9WUM= + +Name: system/lib/libhtcflag_native.so +SHA1-Digest: MJgp6r54goA8xL1gEN3b+NVwRRw= + +Name: system/customize/resource/quicklaunch_28010.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: additions/fonts/helveticaneue/Roboto-Bold.ttf +SHA1-Digest: ejK3MxV4VpZhZJKLZFuKgfpgBo8= + +Name: additions/gps/oceania/etc/gps.conf +SHA1-Digest: oHvd+/TVsst/c5x3sZWI5vxhciQ= + +Name: META-INF/com/google/android/aroma/themes/sense/titlebar.9.png +SHA1-Digest: V36x7nmB4rgSAEDMj2KmQX+CqsE= + +Name: system/media/audio/notifications/Fuchsia.mp3 +SHA1-Digest: rKZ05GIDryb35jFmHHhJwuuNsf0= + +Name: system/customize/resource/allapplication_65507.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/lib/libSkiaWarper.so +SHA1-Digest: sXKNz4gEz5r6ZrwQoVVLgRLEcls= + +Name: system/media/weather/weather_sunny.mp4 +SHA1-Digest: TsJqq606vjdFWXRKx4xv7VUfQjQ= + +Name: system/framework/com.htc.android.bluetooth.jar +SHA1-Digest: lEYxDi8EkalOFQiEftYNwm4myeE= + +Name: system/bin/mm-jpeg-dec-test +SHA1-Digest: NMuLZXB3pQ/c3MJXfOpGnZWtzFc= + +Name: system/lib/libxt_native.so +SHA1-Digest: unlur90tEoRiJSwiErDS42a2uNQ= + +Name: system/etc/security/cacerts/1dcd6f4c.0 +SHA1-Digest: ZD4839PLxZdYujgVOpN7nvdxfvs= + +Name: system/etc/security/cacerts/9772ca32.0 +SHA1-Digest: gLmISuqfwLlRD8jocBuF5N3MkTM= + +Name: system/media/weather/weather_cloudy_day.mp4 +SHA1-Digest: wh2Nv12FGXhv/ZzjMi4oNsd0tvM= + +Name: data/app/com.google.android.street-1.apk +SHA1-Digest: gy7wRgDM+/QJWcqujoRdJcZFtgM= + +Name: system/app/PhaseBeam.apk +SHA1-Digest: ielPdSX3mNLQgYX+tTV7iLby5wo= + +Name: system/etc/security/cacerts/5e4e69e7.0 +SHA1-Digest: RU4Glj5/5C9MVwUct4nnQREaDf4= + +Name: system/etc/firmware/hcheck.b03 +SHA1-Digest: 2JeO5ns1SDnurjw+EjmLaxMgqng= + +Name: system/lib/libSR_AudioIn.so +SHA1-Digest: s8dQygjzJPQjSmX9GaT90IjK/bA= + +Name: system/lib/libqmi_encdec.so +SHA1-Digest: 26CSKQvdSdrV9UwnkfMowP1Rlq4= + +Name: system/customize/resource/allapplication_24201.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/fonts/DroidSerif-Regular.ttf +SHA1-Digest: gFxfl14C9Ij6HdHdDUTtT5Ow+rQ= + +Name: system/etc/firmware/hcheck.b02 +SHA1-Digest: WlNOjg0efF87NE9MRwsYKmsc544= + +Name: META-INF/com/google/android/aroma/themes/sense/dialog.9.png +SHA1-Digest: az4c50d0N5ecMDHxjZQp6nyXdvw= + +Name: system/etc/firmware/hcheck.b01 +SHA1-Digest: gd2tz4h9OJJrN+J3gUqi9XC/gnA= + +Name: system/etc/firmware/hcheck.b00 +SHA1-Digest: C4BmB/sEgIUA00GQ6FJLLDh3saw= + +Name: system/media/weather/weather_l_thunderstorm_day.mp4 +SHA1-Digest: TeZiLThX0Unuvd4ZEtfLxLLATw8= + +Name: system/etc/vold.fstab +SHA1-Digest: ucuLszvO3SHZOfQiNA0CMp/tV1I= + +Name: system/media/audio/ringtones/Navy.mp3 +SHA1-Digest: bAEA1Q4xbJcsoFm6sGFVI/pkDH0= + +Name: system/bin/system_server +SHA1-Digest: TaJbGo4Y4VsP7Go/qIbooGmPWsw= + +Name: system/bin/ip6tables +SHA1-Digest: 2qpoMVnCR1qe7GENPgGD/+FpOZs= + +Name: system/lib/libmmcamera_wavelet_lib.so +SHA1-Digest: yLp7X2iU9TWT7qLurgNzRAG0w28= + +Name: system/media/audio/alarms/Steel.mp3 +SHA1-Digest: K66Y4hc1crmgbP0ndNq5A2R1jR4= + +Name: system/usr/share/partials/partials_H.dat +SHA1-Digest: 6dQX7CVJ1gVAwOKdtEiWhm3hYnE= + +Name: system/customize/resource/quicklaunch_23420.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/media/weather/weather_partly_cloud_night.mp4 +SHA1-Digest: i37+qFiRsf1xCZRncomlEb9Q1vw= + +Name: system/etc/tfa/playback.preset +SHA1-Digest: 580uOSSwzkh9I7l9PyiZgNlsUg8= + +Name: system/media/audio/ringtones/Laquer.mp3 +SHA1-Digest: sFtlaRFuRdUS6BltC2r5nN+XOsQ= + +Name: system/bin/sendevent +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/etc/security/cacerts/08aef7bb.0 +SHA1-Digest: UDr/oMgTCEDGW8P/MLGetyQV6u8= + +Name: system/bin/wl +SHA1-Digest: X2QXpEp8OVHPEeaU4NwGySlLmi8= + +Name: system/app/Settings.apk +SHA1-Digest: gHKYSqeqFXvkmHvzntdHJRCJ+Us= + +Name: system/lib/libstagefright_soft_mp3dec.so +SHA1-Digest: xpKEFKirOyhSFUksQ0ygWkb0K1I= + +Name: system/etc/firmware/fw_bcm4335_p2p_b0.bin +SHA1-Digest: s8ujoESTcrSfW/Q17UP/DzlEQo8= + +Name: system/lib/libttspico.so +SHA1-Digest: i05v1BTdOkIdh1jLD0T5fe5cctY= + +Name: system/customize/resource/allapplication_24801.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/lib/libBeautyChat.so +SHA1-Digest: fRzA/rj3ymM5xj72Ktq+00t1UGc= + +Name: system/lib/libnfc.so +SHA1-Digest: L583ggGB4ltbSstF71w4/xvkfwM= + +Name: system/etc/security/cacerts/1d657651.0 +SHA1-Digest: AJPWrMhCJR8Rc5W2NOtk7GsZq8w= + +Name: system/etc/security/cacerts/87753b0d.0 +SHA1-Digest: tDVMAZ7hAGg3lwrrlN+4kvp3Jkc= + +Name: system/app/HtcPowerStripWidget.apk +SHA1-Digest: WkcXkk/gTUwshGBXCJxg0urJuhA= + +Name: system/usr/keylayout/Vendor_046d_Product_c532.kl +SHA1-Digest: iT7ZHxI43pKBUzjQc541oOM22hc= + +Name: system/bin/climax +SHA1-Digest: GP7jOba2djn5PYv/ZlFb9+Su0Fs= + +Name: system/lib/libc2d2_z180.so +SHA1-Digest: 08rTYYnzPDddF5ahoGgHGzZu3LI= + +Name: system/media/audio/notifications/Magenta.mp3 +SHA1-Digest: ifqL1FH3yjmLzMzROxEZSo3ESxE= + +Name: system/lib/libqmi_client_qmux.so +SHA1-Digest: RWDhR0WS4cwUkLDDl996WKB20qQ= + +Name: system/app/WorldClock.apk +SHA1-Digest: HSV8bYlyRtTb7cBo3ZYIYzt+qdw= + +Name: system/fonts/AndroidClock.ttf +SHA1-Digest: 0vRHOkM++Y5hREyvokR3HBnI2ig= + +Name: system/lib/libchromatix_s5k3h2yx_hfr.so +SHA1-Digest: zYQg3LtJHryGbO2EGqKcHcQm4rI= + +Name: system/lib/libvorbisidec.so +SHA1-Digest: M0x1pISGdE2H9QtBqcfJyv71pBg= + +Name: system/etc/security/cacerts/48478734.0 +SHA1-Digest: CCkvYaE7BOlkHFDTReqBRiiR8II= + +Name: system/etc/security/cacerts/76579174.0 +SHA1-Digest: Uw9KFPBW37XtteEhKlq5eRnOm1w= + +Name: system/app/HtcNotesProvider.apk +SHA1-Digest: 2yYt03vBV2Cyr4umli/XmLlLgbU= + +Name: system/customize/resource/allapplication_23407.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/media/audio/ringtones/Cyan.mp3 +SHA1-Digest: /nDN/N7hPG1jMDFA0uwMrzGDFBY= + +Name: system/bin/ionice +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/media/weather/weather_l_windy_day.mp4 +SHA1-Digest: FCHMbwmJrbjeQH4KoQMQgctIWfw= + +Name: system/lib/soundfx/libdownmix.so +SHA1-Digest: WVOGcq7JOqrf6VNF+AOGd/IpxGw= + +Name: system/etc/image_ibeats_v2.bin +SHA1-Digest: sk5OXKhrlVALM7wlPCRxNjlrmRk= + +Name: system/usr/keychars/Virtual.kcm +SHA1-Digest: xYiPhd++Jpvl6ARXJyusriz4pqE= + +Name: system/bin/pand +SHA1-Digest: ZMXBK9eGlsTKQBacuifpjgwTvzQ= + +Name: system/etc/snd_soc_msm/snd_soc_msm_2x_Fusion3_DMIC +SHA1-Digest: GMpUgtLfs21E9UG4/9Y4pW6q/3w= + +Name: system/lib/libbcc.so +SHA1-Digest: dsB9BNyeUFQ3bQH725qzLGprOYc= + +Name: system/lib/libchromatix_ov8838_hdr.so +SHA1-Digest: 4rpYmxobRs4QoOkCEh6Ua5v6O2w= + +Name: system/lib/libstdc++.so +SHA1-Digest: 3YTMdOtqO+yHg0KoU/wW0upylbs= + +Name: system/customize/resource/allapplication_24008.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/lib/hw/alsa.msm8960.so +SHA1-Digest: mY5ojcsvM/1g6t77GzOG7OuPd/M= + +Name: system/lib/libtcpfinaggr.so +SHA1-Digest: KJMIASBMHzCQxpnp+O5Kki22O7M= + +Name: system/lib/hw/camera.msm8960.so +SHA1-Digest: Qu/8X2nmNJs3vCys+brzVipz85E= + +Name: system/bin/aplay +SHA1-Digest: 6NYQVPkLIRJBjKCw1oTuCpXWSDw= + +Name: system/lib/libcameraservice.so +SHA1-Digest: 4ZRayTkbaYSiHJyEsUJt8YcnZao= + +Name: additions/fonts/segoewp/Roboto-BoldItalic.ttf +SHA1-Digest: giRk6fDZ0SHi824wIO5nYW7UXtk= + +Name: system/media/audio/notifications/Azure.mp3 +SHA1-Digest: G3ucPWq/kTonTGmvgdrYFyfp7kA= + +Name: META-INF/com/google/android/aroma/themes/sense/radio_sel.png +SHA1-Digest: 7pjS+lUbSC+PIKz/ZFlYi1Q0qbo= + +Name: system/app/HtcSpeakNGF.apk +SHA1-Digest: uOPzoHwciI5o4KsYaiAfkoqOsXA= + +Name: system/lib/libchromatix_ar0260_default_video.so +SHA1-Digest: Py3Pc5Mo89hSl3XuoYYzgUKGFLU= + +Name: system/usr/share/zoneinfo/zoneinfo.dat +SHA1-Digest: bShcRYsKQq5TEPhpXvhJMaks+Ns= + +Name: system/media/audio/notifications/Vermillion.mp3 +SHA1-Digest: vJiXbzdF8poe/UUrL2FsrNVMN2A= + +Name: system/app/MyTask.apk +SHA1-Digest: wm6Eonrqhvf/486tyPlAh8ccqFo= + +Name: META-INF/com/google/android/aroma/themes/sense/cb.png +SHA1-Digest: RcJookrxsxmN98b0pdHWj1BOhsY= + +Name: system/framework/uiautomator.jar +SHA1-Digest: MOp4VoDD9cckeAqOBVeEfXhPXGY= + +Name: system/lib/libhardware.so +SHA1-Digest: gE+aDB6Znb8dWVDvy6HDTvXJzpg= + +Name: additions/fonts/helveticaneue/Roboto-Italic.ttf +SHA1-Digest: U1PDOx+d2cxdKKeXmmkyO5N+dUo= + +Name: system/lib/libpphwr.so +SHA1-Digest: NDzimzJdwblwsFBMzfcgJZ/XGgk= + +Name: system/customize/resource/downanimation.zip +SHA1-Digest: W10ZlwFkdSe/NfDkFLTUKU9usCA= + +Name: system/etc/permissions/com.htc.software.market.xml +SHA1-Digest: E/BqBu8ugtHZ1OGY+h4Bgqs48G0= + +Name: system/etc/security/cacerts/60f083f8.0 +SHA1-Digest: 6bEJK4/D+kSqeKMInAqbqBJVuro= + +Name: system/lib/libc.so +SHA1-Digest: koteUSFbvpNCyJSQMiLudw/IdgA= + +Name: system/lib/libext2_profile.so +SHA1-Digest: HdOoe5pQH/R0TV4X7RZ04h4ncGM= + +Name: system/bin/qseecomd +SHA1-Digest: hslOr2KtEHWqqtuNWPVpvILccdU= + +Name: system/lib/libgui.so +SHA1-Digest: G0hOOuwMyGS12XQuFmaQxsbqjwg= + +Name: system/media/zchgd/charging_08.rle +SHA1-Digest: nTXp2Ml9w2TPiqd8Vi6NR1wpmYc= + +Name: system/usr/idc/projector_input.idc +SHA1-Digest: jdmpS6Rrbyb9aEDdfIKHDIcMGdw= + +Name: system/app/WeatherProvider.apk +SHA1-Digest: gIZTrmv1RhXgxM/u7lduTpiLSKU= + +Name: system/bin/fusermount +SHA1-Digest: Pq3IHhSy+8CgIoF3ioQv/8J9GTQ= + +Name: system/media/audio/notifications/Purple.mp3 +SHA1-Digest: BdDCNlOVajs46E0wuyW3owciqnY= + +Name: system/lib/libinput.so +SHA1-Digest: RoebUdb5YHN+OGZyXVIv76iU+5Q= + +Name: system/bin/dmesg +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/lib/libgoogle_recognizer_jni.so +SHA1-Digest: XSsNFriGTcQNVMjgEsK/X5CE0/k= + +Name: system/customize/resource/allapplication.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: META-INF/com/google/android/aroma/icons/welcome.png +SHA1-Digest: ZjyGs/r4la7VrriRQUXPk33edrw= + +Name: system/media/audio/notifications/Ruby.mp3 +SHA1-Digest: YwrWSqwmAuZq0aDEO+VueJVWh3I= + +Name: system/etc/security/cacerts/418595b9.0 +SHA1-Digest: B6oXTUKiu1cnRTfY8Ck3pr4h5Jc= + +Name: system/app/HtcCupd.apk +SHA1-Digest: SsRCrkVUUtnQbZE8gQg+GW/IEso= + +Name: system/fonts/DroidKufi-Bold.ttf +SHA1-Digest: WQhlrdI9jAsNoe1Su0Uyd9gk4ZU= + +Name: system/app/HTC_CIR.apk +SHA1-Digest: h7YZ2pj8YegPphoN0vYnjFn3eLU= + +Name: system/etc/bluetooth/blacklist.conf +SHA1-Digest: tzfL29uwKo39KMrIZp8Cd3Wa36Y= + +Name: system/usr/srec/en-US/symbols +SHA1-Digest: VssslP42+1LcOram2NHS9Gxlu94= + +Name: system/media/GPU/CurveCold.bmp +SHA1-Digest: 8nF+MLzdnJFSMudXwC/q7WrO6LI= + +Name: system/etc/soundimage/srsfx_trumedia_voice.cfg +SHA1-Digest: xPIju7qeidETr0QJ6TkJ20bur9Y= + +Name: system/etc/firmware/vidc.mdt +SHA1-Digest: Kwo/hMLh12h5rFoRbcGuU0ukJSs= + +Name: system/bin/applypatch +SHA1-Digest: QK+KvNKbomEv4kSe4F79oinnE1E= + +Name: system/lib/libmedia_jni.so +SHA1-Digest: yhPDMpzu3osPBcw7BNL/WSEHZAE= + +Name: system/app/IMEXT9BahasaMalaysia.apk +SHA1-Digest: h7bQyCebLsqtfnp06EAmaSTsqWM= + +Name: system/lib/libpower.so +SHA1-Digest: 81LO2NWhRbM6yRximbHfdTxxf4E= + +Name: system/etc/mkshrc +SHA1-Digest: ymRp0Mh4Si4DSGQjbO2HFBivOTU= + +Name: system/etc/security/cacerts/d8274e24.0 +SHA1-Digest: z2/j38mQezRg/RCv/RJ9aCSpKZ4= + +Name: system/lib/libimu.so +SHA1-Digest: aDR3Dn3nxW5ubqLTmqEhm4wYZJc= + +Name: system/app/HtcWeatherClockWidget.apk +SHA1-Digest: GekMrORXYACTIRO5VW6pwhRcghY= + +Name: system/etc/permissions/com.google.android.maps.xml +SHA1-Digest: BbK4aFOA+G3wd2qESxbxITfwZYM= + +Name: system/lib/libsonivox.so +SHA1-Digest: vZUIvkMfkZ+iZpv7ZJH4zHZmtkQ= + +Name: system/lib/libstagefright.so +SHA1-Digest: V0F5MTH2nbjmuHeltDoDSGsCVR8= + +Name: system/etc/permissions/android.hardware.sensor.gyroscope.xml +SHA1-Digest: brL84JgL2wCWqFvQAQDPM5lm+4o= + +Name: system/app/IMEXT9Dutch.apk +SHA1-Digest: PlpfZOm8ZFF1Q4Styd4/aphbpzs= + +Name: system/usr/srec/en-US/dict +SHA1-Digest: h7Q/ArygyOrwdPMa0NL4+48riLc= + +Name: system/media/audio/alarms/Citrine.mp3 +SHA1-Digest: nndkVIHcYaWnNiMLcRxaPHMNOU4= + +Name: system/customize/resource/quicklaunch_21406.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/media/audio/notifications/Smoke.mp3 +SHA1-Digest: 2YbI9Krioe6M2m9m3aATGR1OCEw= + +Name: system/etc/security/cacerts/d777342d.0 +SHA1-Digest: WdQWfF7rZDzaXOGfoJMJS1qOuYU= + +Name: system/media/audio/ringtones/Orange.mp3 +SHA1-Digest: CxKx+6Q5OXffZALJLNGjyXlaRDI= + +Name: system/lib/libchromatix_s5k6a1gx_zsl.so +SHA1-Digest: rcP3nNaS9qv1nASjVvMaaJQXtI4= + +Name: system/bin/venc-widi +SHA1-Digest: cowCUbQjqb2zX2FKdpB3h/8vyas= + +Name: system/media/weather/weather_l_sunny.mp4 +SHA1-Digest: uyLd5pchxzv4zA/i3LZQkG5SsgY= + +Name: system/etc/security/cacerts/84cba82f.0 +SHA1-Digest: m8/Q3u0mnTMsbDO41AfCzDSrMvg= + +Name: system/lib/libwfdcommonutils.so +SHA1-Digest: jAMFWx5jyCYi4Rbhe04RqrJo7a0= + +Name: system/lib/libchromatix_ar0260_preview.so +SHA1-Digest: DUTrZyPpZlLIvuUM24s5UQ/6sNQ= + +Name: system/etc/security/cacerts/399e7759.0 +SHA1-Digest: UAbvBS8lvF2AOEsEs98fRQGKiwo= + +Name: system/media/audio/notifications/Rose.mp3 +SHA1-Digest: l9jmqMhdJymmIWlz0Cxv+UzLgAk= + +Name: system/framework/am.jar +SHA1-Digest: RuFCYnMyrosieGVuBpKjrbyf/LM= + +Name: system/lib/libmedia_native.so +SHA1-Digest: p09lfRLy/qM3aXb3KXsK2lus15g= + +Name: system/app/KeyChain.apk +SHA1-Digest: frVpXHZFKxla0aiCbXodnWTVcb8= + +Name: system/etc/security/cacerts/c33a80d4.0 +SHA1-Digest: rNpc82k59uWEFW5aGR7MLPbTGbI= + +Name: system/lib/librs_jni.so +SHA1-Digest: 1RR4mqRUuiRyRJpYsql9vEcsGko= + +Name: system/media/audio/ringtones/Blue.mp3 +SHA1-Digest: 3dd4USTc2lpmh9CmLN99R4/+ZcY= + +Name: system/media/audio/notifications/Cobalt.mp3 +SHA1-Digest: HdFILyI++GWExpNfvHJ4dP996rw= + +Name: system/etc/security/cacerts/bc3f2570.0 +SHA1-Digest: T0YolQvu92p5y+/IKRYPyfG1tQs= + +Name: system/bin/mm-qcamera-app +SHA1-Digest: R5uBJXvMGLtoboVGmHJAWng7gnw= + +Name: system/bin/asound +SHA1-Digest: tr1Lz3UjyOXEGicp6Ld0ePsKrK8= + +Name: system/lib/libwt6docxrdr.so +SHA1-Digest: FvkjkrqIWmngv7ca5nyaFw4ho+I= + +Name: system/lib/libdsutils.so +SHA1-Digest: JkQlzdBDWOlw4fE0kcOx3vGo3+c= + +Name: system/lib/libgetzip.so +SHA1-Digest: OYhw+CnZlkkMLB2QEhRCuvS9in0= + +Name: system/app/IMEXT9Lithuanian.apk +SHA1-Digest: M1kGJx6WWkybgPjjxKsBDyFVa3A= + +Name: system/lib/libmode10.so +SHA1-Digest: tgb/0mYrJsbmsM/DhdcdKyCYG8o= + +Name: system/media/weather/weather_l_fog_day.mp4 +SHA1-Digest: HQdXquqVt46a900WjDhjY4/cDmM= + +Name: system/lib/libsuspend.so +SHA1-Digest: /DJdOpz4VCTs+vgjoL4pmTk1J1A= + +Name: system/lib/libzeroeditorplayer.so +SHA1-Digest: axpPpMFqm0m3jb0mNUWi1ehEzUE= + +Name: system/bin/run-as +SHA1-Digest: hx9/aOVvMgtxG66iNmjlU1OfEWY= + +Name: system/app/NewsPlugin.apk +SHA1-Digest: taupwIVbRhPO7kZmquFpUKU93Gk= + +Name: system/etc/security/cacerts/73da149b.0 +SHA1-Digest: ZMH3aJsy2YBcWh1dq/Pq0xRGuAw= + +Name: system/customize/resource/rp_pct.png +SHA1-Digest: r1eCZ3sgAL2DZIG+nOjj9IVMwPQ= + +Name: system/customize/resource/rp_ce_0678_i.png +SHA1-Digest: QcdYwynqePRy5S+yjCqmjCBU+gA= + +Name: system/usr/srec/config/en.us/models/generic8_m.swimdl +SHA1-Digest: bFt0FGX1o+r+WlmE2dUzuoGlyao= + +Name: system/framework/svc.jar +SHA1-Digest: dzmluNqjY6rka7DAMjxykM//OQk= + +Name: system/fonts/DroidSerif-Italic.ttf +SHA1-Digest: vdiq1easVG0R5zeL36vqx8y9rfw= + +Name: system/framework/HTCDev.jar +SHA1-Digest: YJnljdIZS5DHAZczapMLR2kYgLg= + +Name: system/etc/calibration_EMEA +SHA1-Digest: 7baJRpUcgPwijs9O87vUJihnsO8= + +Name: system/etc/bluetooth/a2dp_avrcp.conf +SHA1-Digest: wJ3llWKQ+xtnKrQGf8GPwJRNJsI= + +Name: system/customize/resource/rp_ce_0682.png +SHA1-Digest: SR9O4zypMKzAhv4TE0rg1PRbtwI= + +Name: system/lib/libbluetooth.so +SHA1-Digest: C3923f3taBldsRGTlaWnwPMYUU0= + +Name: additions/fonts/sonysketchef/Roboto-Regular.ttf +SHA1-Digest: EMDAO+K2QAZphYvpq41fCdaYVzk= + +Name: system/etc/snd_soc_msm/snd_soc_msm +SHA1-Digest: o3bFCVwsteawrBQVy5QXfsAegWk= + +Name: system/customize/resource/quicklaunch_27205.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/etc/security/cacerts/d59297b8.0 +SHA1-Digest: EzYjzIwGO6iEh1Tk+7MTNXd/AaE= + +Name: system/lib/libqmi_csi.so +SHA1-Digest: rUUEJwiHfTrsjeqqKpyD4GCKFpI= + +Name: system/etc/permissions/android.hardware.wifi.direct.xml +SHA1-Digest: 26Zih/5IpKCLJgM/cg+lI9zxZ4Q= + +Name: system/media/audio/ringtones/Khaki.mp3 +SHA1-Digest: AjDFyx9+vDgzVdoFoD5fTBRM+lA= + +Name: system/app/HTC_IME.apk +SHA1-Digest: w47UWIC6ZXGBE3Qp2jZKaF3Gcdk= + +Name: META-INF/com/google/android/aroma/icons/agreement.png +SHA1-Digest: BLCgQbcevGAuuV0SxkEF+2IKpMM= + +Name: system/etc/security/cacerts/0e82f83a.0 +SHA1-Digest: 0ntDMr2qchEGTju9oHhfb1h53sw= + +Name: system/customize/resource/allapplication_26803.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/customize/resource/quicklaunch_65507.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/app/SettingsProvider.apk +SHA1-Digest: zScbEEsECUcpAtlTWlRBfogNVIY= + +Name: system/bin/wipe +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/etc/tfa/fm_l.eq +SHA1-Digest: PM6hx2pEVi+SuZ9Ef8C0eIPB808= + +Name: system/media/audio/alarms/Cinnabar.mp3 +SHA1-Digest: HBt23TwCVLI6WqiPf92TxBK4DJs= + +Name: system/lib/libdmt_sse.so +SHA1-Digest: fqywsXgma0tT7ggXDocV+ETl+lo= + +Name: system/etc/security/cacerts/d537fba6.0 +SHA1-Digest: fpmK/UpGvaATZvclHSu6ryqfKbU= + +Name: system/app/HtcImageWallpaper.apk +SHA1-Digest: jSvsayHcmLqO7oYv/5wBofD0uhI= + +Name: system/usr/share/partials/partials_H_rr.csv +SHA1-Digest: Z9/32RI5ujeuYS0CQCyM3eJ0uKw= + +Name: system/lib/libmpl_jni.so +SHA1-Digest: TsofTQBH2CnLU3StUSwRKISUbMQ= + +Name: system/lib/libnativehelper.so +SHA1-Digest: 8ZvHOAFdkmzXXWPAQIxHBPCcMrQ= + +Name: system/customize/resource/allapplication_21401.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/bin/netcfg +SHA1-Digest: /XE2tGorWihZb9UPh2t/r6dzMAk= + +Name: system/bin/hcheck +SHA1-Digest: 2QwrwUi0fys2KMUzXLDgMnCh5sk= + +Name: system/etc/security/cacerts/0d188d89.0 +SHA1-Digest: u89PgYhymechdBRRkE2kQEwXY/E= + +Name: system/app/IMEXT9Spanish.apk +SHA1-Digest: bsNk6NfNQsZNbwX+IXB5I1RFAvE= + +Name: system/etc/firmware/vidc_1080p.fw +SHA1-Digest: gqKcZYBg08EkYPnkeK+Enjp+HBY= + +Name: system/lib/libwt6xlsxrdr.so +SHA1-Digest: Lp6CqOuO1ZW/ZUu/re+oIZSSTWs= + +Name: system/etc/init.d/98permissions +SHA1-Digest: grvdXwEXHuuJS340Pl63cdMSWn0= + +Name: system/app/Picasa_GLRplugin.apk +SHA1-Digest: ltQ+brxccIr2E1RKharJ24WhG/o= + +Name: system/usr/idc/qwerty2.idc +SHA1-Digest: /k6dNiHz49smZosdSvGtSb0EYtA= + +Name: system/bin/efsks +SHA1-Digest: gBxjIEyjA/lbTF624YUo/kSJ6ZE= + +Name: system/etc/res_ctrl.conf +SHA1-Digest: KmRlUl4bp1NIL2Fhbmrv8paVah8= + +Name: system/bin/tune2fs +SHA1-Digest: 4/CV20c7VmLx3Z5JLuM4WsXanCU= + +Name: system/etc/libdvhwrc.so +SHA1-Digest: +EWukgBrL0RRdllVFHX2rBMwb2g= + +Name: system/lib/libaddrsdetection.so +SHA1-Digest: +0QElNcLXtVKeu7hOkgHMTktnxc= + +Name: system/media/audio/ringtones/Coral.mp3 +SHA1-Digest: RImr/WaHlGMCHMBMWRVGPXU8UQs= + +Name: system/etc/tfa/voip_l.eq +SHA1-Digest: akzJZd8ilz4aAsWHG6uC3H5L+tk= + +Name: system/lib/libchromatix_s5k6a2ya_hfr.so +SHA1-Digest: eNuiaeikRv9je/KlLoxga77mqnw= + +Name: system/lib/libwsp.so +SHA1-Digest: FdbsSRYW39nqDa0CoBWRfM8bVL0= + +Name: system/fonts/RobotoCondensed-Italic.ttf +SHA1-Digest: NKhBTHMcBPw7pwPS/BseTh6QXIY= + +Name: system/bin/renice +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/app/idlescreen_shortcut.apk +SHA1-Digest: pBFu9y0DZPUj/5sX8cc48KouQmI= + +Name: system/lib/soundfx/libsrsfx.so +SHA1-Digest: 2JKU/k68txIbvOJXUubdithIRnQ= + +Name: system/usr/srec/en-US/normalizer +SHA1-Digest: a+2nBo6Uy8cIhMZ4fRNuUxTriU4= + +Name: system/app/IMEXT9Hungarian.apk +SHA1-Digest: oZnZ0/IVAxZ+X8/SejxfEs7Q5hc= + +Name: system/app/SystemUI.apk +SHA1-Digest: IEwtDhlSXEkcAA8cKLYUOpF7hiU= + +Name: META-INF/com/google/android/aroma/themes/sense/theme.prop +SHA1-Digest: Yz5tb5g0tT9fChUum1jvE913gyE= + +Name: system/media/audio/notifications/Licorice.mp3 +SHA1-Digest: 5wA/j7AK7pDTYzBVIVmfAA5CUdY= + +Name: system/customize/resource/allapplication_20404.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/lib/libchromatix_imx135_hfr.so +SHA1-Digest: I1dk3hMidqp1cfg55Lfwk155bFg= + +Name: additions/fonts/veggieburger/Roboto-Italic.ttf +SHA1-Digest: Vhq5Pc0f7QDwQAeDuWWtQ4Jv6AQ= + +Name: system/media/audio/ringtones/Sapphire.mp3 +SHA1-Digest: JCkPpw/iOZTI/FppUwM3zmVuvxo= + +Name: system/bin/cat +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/framework/content.jar +SHA1-Digest: duOd+EdAcZpoGhB7w5AyARDLeu8= + +Name: system/etc/priorityd.sh +SHA1-Digest: C7jajOmGRwQmdPqt6X+JsE+0d7Y= + +Name: system/framework/com.google.android.media.effects.jar +SHA1-Digest: AUO08uWhTl7NmmwZGD07Ggg2bpU= + +Name: system/customize/resource/quicklaunch_22201.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: META-INF/com/google/android/aroma/themes/sense/select_push.9.png +SHA1-Digest: wvmedWe4h/6eEbWYDRhLYEuk70A= + +Name: system/lib/libacc.so +SHA1-Digest: rc420sUj7Jtzw5Rc8xhVHYLx3pw= + +Name: system/lib/libmorpho_image_stitcher3.so +SHA1-Digest: gHT+Fzrh6Jc9K36VCDEwSpILkiU= + +Name: system/framework/framework.jar +SHA1-Digest: UPiN80ttZtF3e4R9yUS8pOCXUNM= + +Name: system/etc/security/FotaSign_PubKey.der +SHA1-Digest: hpRUdVe1bjjhrmKbqvFBUk49wFk= + +Name: system/bin/mount +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/lib/libaricentomxplugin.so +SHA1-Digest: Zk3azoDxsqanCAb95Jf7ssxHgg8= + +Name: system/media/audio/ringtones/Neon.mp3 +SHA1-Digest: kuALt75+0iqM+0jOFia7gG8uKeI= + +Name: system/etc/security/cacerts/1dbdda5b.0 +SHA1-Digest: Pvfb+Mx0s9ZkvrdvSJCmchuTHpM= + +Name: system/lib/libexif_jni.so +SHA1-Digest: DTsfUp1mSPWTXKEx+zi9hJC3D3w= + +Name: system/customize/resource/wallpapers_c_02.jpg +SHA1-Digest: /UaU6oCe0Ragnxzcmf9hCsOyRxE= + +Name: system/etc/firmware/a225_pfp.fw +SHA1-Digest: e6QAN5YoXTbBJfq+RTtF1eIYUMw= + +Name: system/app/IdleScreen_Music.apk +SHA1-Digest: XvbDzjop40JdxREo3KGFwj1aZCc= + +Name: system/lib/libqdi.so +SHA1-Digest: yYHAQlouk6ZP0GWfUQkWmm6Ux7o= + +Name: system/bin/sync +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/etc/gps.conf +SHA1-Digest: OgKe2mCQxfu/GvkoVtCoNjaJijA= + +Name: system/customize/resource/allapplication_21419.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/bin/dalvikvm +SHA1-Digest: JrCBcdjQPnUVB33opNhr70q2iiE= + +Name: system/app/HtcRingtoneTrimmer.apk +SHA1-Digest: dZ5qYRdJCHDoPbPTW1A35UfHvyU= + +Name: system/etc/security/cacerts/75680d2e.0 +SHA1-Digest: xKfC4N5pEuEgXN2tZ44LcEXXY5s= + +Name: system/lib/libxml.so +SHA1-Digest: fot1OMClyO4qokS/HfMfLLc+sP4= + +Name: system/lib/libdivxdrmdecrypt.so +SHA1-Digest: oDqyznowMx/6Vyo7SGKN0DJ+7x0= + +Name: system/lib/libvideoeditor_videofilters.so +SHA1-Digest: IHrnJdoac+oL5tNTVC5fz2+81r8= + +Name: system/media/weather/weather_rain_night.mp4 +SHA1-Digest: I5L+abZ4jGUUDEd+KEjg7OXY67g= + +Name: system/customize/resource/quicklaunch_20210.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/lib/libsnfc.so +SHA1-Digest: mwzgx2UqRssL863ZYTPm0oYdV3o= + +Name: system/lib/libmemalloc.so +SHA1-Digest: jpFojqzx4rSQFLr2tE4HqW9CH0I= + +Name: system/media/audio/notifications/Slate.mp3 +SHA1-Digest: xb+HoEobEEz3qfBegsUVJSxtsXI= + +Name: system/app/InputDevices.apk +SHA1-Digest: FUnvm84KB01PAOr1QEYxmnPyKCg= + +Name: system/app/HtcSyncWidget.apk +SHA1-Digest: 3gY8BrIZDuLh/PTtal0p78J0FAk= + +Name: system/fonts/DroidSerif-Bold.ttf +SHA1-Digest: KU+pnOr2B3q2M7Wnx9t2Hi92z4w= + +Name: additions/openvpn/xbin/openvpn +SHA1-Digest: 5v+Yuy7ZjRYGHtcqcmC/6ujs1zc= + +Name: system/usr/keylayout/keypad_8960.kl +SHA1-Digest: IIOk+zhgi7afHkxlyl82NdD77rY= + +Name: system/bin/mm-jps-enc-test +SHA1-Digest: mUaccGUCFe6x+/p9/ZOWKi3qaTA= + +Name: system/framework/bmgr.jar +SHA1-Digest: e/dXKGKrmgoAIPsRdm8QR2ZukX8= + +Name: system/lib/libchromatix_imx175_hfr.so +SHA1-Digest: D8LSrZQwnG6bEiMygZU6nS1mFB0= + +Name: system/customize/resource/quicklaunch_23407.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/etc/security/cacerts/7672ac4b.0 +SHA1-Digest: rVlRiFPQlGlMwhz5m6Ak2XDc2KM= + +Name: system/etc/security/cacerts/00673b5b.0 +SHA1-Digest: G5keTPZotrFLEINobTM5FTRYmLA= + +Name: system/etc/tfa/ring.eq +SHA1-Digest: PM6hx2pEVi+SuZ9Ef8C0eIPB808= + +Name: system/lib/libexif.so +SHA1-Digest: TouCCtku0jQ9vNm9HV4EbtCGtrQ= + +Name: system/bin/umount +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/lib/libwfdhdcpcp.so +SHA1-Digest: dGEtDG+yLuu1OMX71ZyPfn5Sqxg= + +Name: system/etc/security/cacerts/6e8bf996.0 +SHA1-Digest: p7GnxdBahRQFK6WFiKO8zA1I1FA= + +Name: system/lib/egl/libGLESv1_CM_adreno200.so +SHA1-Digest: cAZCFpvmAHYoao83wKupn26Mi+A= + +Name: system/etc/tfa/video_l.eq +SHA1-Digest: yVnitUPrXicZNKfZWIRmiKsUotA= + +Name: system/lib/libsoundpool.so +SHA1-Digest: 3C7cAST77VP8GhUWSvnIYpqu+4M= + +Name: system/media/audio/ui/Volume-4.flac +SHA1-Digest: P9cUKKRKCbyS9vHXNcNuuo2zpOY= + +Name: additions/fonts/roboto/Roboto-BoldItalic.ttf +SHA1-Digest: VYDbVJTNb2eL1eOY4SYWXg+P4PE= + +Name: system/etc/security/cacerts/5021a0a2.0 +SHA1-Digest: CI19Ue/cTwI484BmRLdR5TbCY7I= + +Name: system/bin/netmgrd +SHA1-Digest: o3T/3Uod1c4qw/kklD5+sbrEqg4= + +Name: system/etc/fallback_fonts.xml +SHA1-Digest: S5MUd49ldVxJTSz3bE/3gh3fGfo= + +Name: system/app/GoogleTTS.apk +SHA1-Digest: JsJQulafhOvc0/9D4kibYPkj7d8= + +Name: system/lib/libtilerenderer.so +SHA1-Digest: jPzbjr7YnyThaAbe2UY/snAABbM= + +Name: system/app/FDHttpd.apk +SHA1-Digest: inJe8LTXx1IBSnk+riZTJjjhxxU= + +Name: system/lib/qnet-plugin.so +SHA1-Digest: nvZKgsSuVO+Uth0Yy4KPSkIs2y0= + +Name: META-INF/com/google/android/aroma/icons/license.png +SHA1-Digest: Ne75iY0xgnD40gRcUCzOQh3q4/M= + +Name: system/etc/security/cacerts/9fae0770.0 +SHA1-Digest: LgctgBWI+ELcn1TUtd6wcus2h3I= + +Name: system/bin/make_ext4fs +SHA1-Digest: PePb8zRPRvKq4mEuBqiQJFqar0w= + +Name: system/vendor/pittpatt/models/detection/multi_pose_face_landmark + _detectors.7/right_eye-y0-yi45-p0-pi45-r0-ri20.lg_32-2/full_model.bin +SHA1-Digest: AVjVyo3+d6RuT9gQEL1j2A4yQCA= + +Name: system/bin/rmdir +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/customize/resource/allapplication_21416.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/app/HtcSpeak_HFM.apk +SHA1-Digest: e9YgIqKlnN/ScgaEGZWqSQOT7nU= + +Name: system/etc/security/cacerts/bda4cc84.0 +SHA1-Digest: cfrYr6hqVNGZ0HN4nhlR9hRwrPg= + +Name: system/usr/srec/en-US/dictation.config +SHA1-Digest: zSaq9OS/+DTEJgF7GYk4324GoCo= + +Name: system/lib/libharfbuzz.so +SHA1-Digest: k9uxPG303FkzDi89qyK0/zUV6c8= + +Name: system/tts/lang_pico/fr-FR_ta.bin +SHA1-Digest: k5eoGN7uJD6gPoD62ErDAhLNV3k= + +Name: META-INF/com/google/android/aroma/themes/sense/cb_sel.png +SHA1-Digest: n31tGc578dhSV8i3jfhdnSmQ0oM= + +Name: data/app/com.google.android.apps.translate-1.apk +SHA1-Digest: jkzaquApYqUHbOA58P/qWJHhu2Q= + +Name: system/etc/tfa/ring_l.eq +SHA1-Digest: PM6hx2pEVi+SuZ9Ef8C0eIPB808= + +Name: system/customize/resource/ConfigP.bin +SHA1-Digest: 7D+XC/yPY7DmScf5vTLbnji/ziY= + +Name: system/customize/resource/quicklaunch_24001.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/etc/security/cacerts/6adf0799.0 +SHA1-Digest: AdlddUEzDH/iR/px2uzU8RQlpxg= + +Name: system/bin/mpdecision +SHA1-Digest: 5dNSjaqjtC5fC59ELh3MAzqsW94= + +Name: system/framework/bouncycastle.jar +SHA1-Digest: DPnnUKOkEQzsMnB33VA9Wnzl1Sg= + +Name: system/lib/libctest.so +SHA1-Digest: 35NN9yTJRrBoPL09IBLd4iMpjfg= + +Name: system/lib/libwebrtc_audio_preprocessing.so +SHA1-Digest: ITe++q770lDJs4f5PekopdABhHc= + +Name: system/customize/resource/quicklaunch_24008.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/app/GoogleContactsSyncAdapter.apk +SHA1-Digest: Zwl6Wwpm6094Y/zeJm8wi+f5UQ4= + +Name: system/usr/srec/config/en.us/models/generic11_f.swimdl +SHA1-Digest: 5e8IIA7SPCk0zXso+yzwYfaIl4Q= + +Name: system/etc/security/cacerts/4fbd6bfa.0 +SHA1-Digest: n3+dvWbE0UcGOz9eUcbG8BT7IdU= + +Name: system/lib/libhtccamera_yushaniiproc.so +SHA1-Digest: vIPQ6qRoKl9A+owmk62YWdEdKvU= + +Name: META-INF/com/google/android/updater-script +SHA1-Digest: ixinSyWKgr33ZST6nH8NAfvTCdk= + +Name: system/etc/sound_mfg.txt +SHA1-Digest: q/uKM6MZpJZWI+bIpLWChCRtLU4= + +Name: system/lib/libchromatix_imx175_hdr.so +SHA1-Digest: 0XZLbtCR/18OS0lJ8r1PC+iftXg= + +Name: system/customize/resource/allapplication_20201.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/lib/libsnfc_ndef.so +SHA1-Digest: DYM7j3ais+je1juF6K95iIWClRI= + +Name: system/etc/tfa/playback.config +SHA1-Digest: mcDPznDmbQbzvQ1yOzfS3mAX2n0= + +Name: system/fonts/DroidSans.ttf +SHA1-Digest: Z9cynTXQb4TYTpzUSFMVfKk/tTc= + +Name: system/customize/resource/allapplication_28010.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: additions/gps/australia/etc/gps.conf +SHA1-Digest: nroBXNimUD4NF6JWtHpYHV0r8xE= + +Name: system/lib/libjUPnPCP.so +SHA1-Digest: vaopdM61+7qPkeer03WliwwX42o= + +Name: system/etc/image_beats_speaker.bin +SHA1-Digest: zlnEYty/dzXh9ohcIvRrpNP0s8I= + +Name: system/etc/security/KeyServer_PubKey.der +SHA1-Digest: U3W3nVoWgllu1mADcOUDQtRQa9s= + +Name: system/lib/libmmcamera_aec.so +SHA1-Digest: lmjrXRBXP1s+Fa5+CSMYF8SvEMs= + +Name: system/lib/libchromatix_s5k3h2yx_hdr.so +SHA1-Digest: bifkrneLL8rL+oDTjpzrhhhoNz0= + +Name: system/etc/security/cacerts/fde84897.0 +SHA1-Digest: iUIGZoxaUSmKyq84n5poAuNYHgg= + +Name: system/etc/firmware/leia_pm4_470.fw +SHA1-Digest: mTZLCv2U5JbMyDPKBCTdaFO5cdU= + +Name: system/customize/resource/quicklaunch_23801.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/media/zchgd/charging_00.rle +SHA1-Digest: RxWagAYJ9pk2xnZppBnwdNUpdxo= + +Name: system/framework/bu.jar +SHA1-Digest: z19B50fkFSf5eaptvZQw2tgzVfg= + +Name: system/app/HTCAlbum.apk +SHA1-Digest: 9h0TWDSkgk7l+ngKXTCKrBt1Fug= + +Name: system/app/Calendar.apk +SHA1-Digest: pQxSDQczKKgxq1PaF2Ywn3nDPec= + +Name: system/bin/fsck_msdos +SHA1-Digest: y5dF/aFpyChS/0urza6lpom2soQ= + +Name: system/etc/firmware/BCM4335A0_001.001.038.0015.0020.hcd +SHA1-Digest: vO8yCkln/F/B37QPZ5CiPu/unaA= + +Name: system/app/HtcFMRadioWidget.apk +SHA1-Digest: 4G0Poj5Y9Mi8silmomPPKvAIVCI= + +Name: system/app/HtcContacts.apk +SHA1-Digest: Gq0/+UJy38JrPgNKkHuSd9/rySI= + +Name: system/bin/drmserver +SHA1-Digest: U0x34YMoJTQjYSdqJB83v5wky7A= + +Name: system/lib/liboverlay.so +SHA1-Digest: 008Znk8mIA++m3pBL2bew+OrSWg= + +Name: system/etc/permissions/com.htc.fusion.fx.xml +SHA1-Digest: JPnWpxVThb8VsMttUQzLG2Qt+MY= + +Name: system/etc/security/cacerts/052e396b.0 +SHA1-Digest: 200jVgTclSNIhG4o7lvN+mFHZ6E= + +Name: system/customize/resource/rp_ac_with_nfc.png +SHA1-Digest: Stl55tSmRUa9B6xR4UGRf5Hcq/s= + +Name: system/lib/modules/moc_crypto.ko.sig.3.4.10 +SHA1-Digest: nYTXrUdepbvacQ7ESSHMPwBq4ng= + +Name: system/bin/e2fsck +SHA1-Digest: MQskU5DlqAgQJzuQLoc2x9tjSbg= + +Name: system/customize/resource/wallpapers_a_05.jpg +SHA1-Digest: S6qUDEgmc2ACGO3o9i8W9lIH3ls= + +Name: system/media/audio/ringtones/QuietlyBrilliant.mp3 +SHA1-Digest: CqKwkDHXpzqnDOReQ8mjHvjI3Ww= + +Name: system/lib/libvideochat_jni.so +SHA1-Digest: x9HVQGQWyTQJe9KKBgTqbBSjqwc= + +Name: system/usr/keychars/qwerty2.kcm +SHA1-Digest: qPZSGYC9afTwkRU3aCThctqnOdQ= + +Name: system/framework/apache-xml.jar +SHA1-Digest: 726UBIoXvriXHLpmGKCFUR+2ma0= + +Name: system/media/GPU/CurveCross.bmp +SHA1-Digest: 0jlE4XxN3GFh/6bgUnOXQFhqqCg= + +Name: system/lib/libGLESv2.so +SHA1-Digest: mcWW9B4AUh56ak8w1ok1fQ2uwMo= + +Name: system/usr/srec/en-US/lintrans_model +SHA1-Digest: ZES3OS6OKnK1lLKetEkUi+PgL4I= + +Name: system/media/audio/notifications/Jasper.mp3 +SHA1-Digest: DVCjzvDToL+qUcpgxJVQn8IZHK0= + +Name: additions/fonts/klavika/Roboto-BoldItalic.ttf +SHA1-Digest: Es6W1ntnwfUennlakydhCrk9COY= + +Name: system/build.prop +SHA1-Digest: w75xfXXoLMim+TsW7R8Wdr7AOIE= + +Name: system/lib/modules/moc_platform_mod.ko +SHA1-Digest: p5dbkTb7Q3GnrtCdFcmHjcyywjE= + +Name: system/app/TelephonyProvider.apk +SHA1-Digest: PZRVe81IyY08YDaBjaaHrhCvm8I= + +Name: system/bin/qmuxd +SHA1-Digest: EwS3kqJqQZIeV4fglBuKgeaH4x4= + +Name: system/lib/egl/libEGL_adreno200.so +SHA1-Digest: 5RIlj+9d9BZD3Pi1PiQ6+9eKRQk= + +Name: system/bin/debuggerd +SHA1-Digest: 4n0TUd4xCFZwldJ2rVrjEJR9ZLQ= + +Name: system/lib/libpng.so +SHA1-Digest: zUA1jH4ZH9rbImKG3M4f73EGatE= + +Name: META-INF/com/google/android/aroma/themes/sense/radio_on.png +SHA1-Digest: y06yW42n0e7ueDV5DVRx7odUtrw= + +Name: system/lib/libcorkscrew.so +SHA1-Digest: jega2j1r1/SvfkZgW1rjLV46Tik= + +Name: system/customize/AAInfo.txt +SHA1-Digest: pdhBxRntxO/v05VEMJHgJBOP5OY= + +Name: system/media/audio/ui/Volume-7.flac +SHA1-Digest: KyE0g7KRVX5Uf4680FmU7pqUA3E= + +Name: system/app/FMRadioService.apk +SHA1-Digest: tDhEJHl+yVKD6VGQDquYdlWRKco= + +Name: system/etc/security/cacerts/524d9b43.0 +SHA1-Digest: rOw80KrUjM6OhWVNkxN1dgNU2W4= + +Name: system/etc/security/cacerts/1eb37bdf.0 +SHA1-Digest: vHz58A2QzT7wd83T0nvUMdAkBps= + +Name: system/bin/logwrapper +SHA1-Digest: P81qhmlKrcTz4FE4vYncuFxFw+Y= + +Name: system/media/GPU/dot_mask_128x128.bmp +SHA1-Digest: GB5y4r0gtHy5zl9McUq/0s6I+pc= + +Name: data/app/com.koushikdutta.superuser-1.apk +SHA1-Digest: jwXPCa2WmEeom8wzvKuYb50H+wg= + +Name: system/etc/snd_soc_msm/snd_soc_msm_Sitar +SHA1-Digest: dI1aRl8EWe4XieDJ6ixXJaqLMHs= + +Name: system/lib/libRS.so +SHA1-Digest: CTTR86seXl6r8n4DexZ1BcGTNvo= + +Name: system/customize/resource/wallpapers_c_01.jpg +SHA1-Digest: PBukbupwv6CWRLPdpDTL+45P4cA= + +Name: system/etc/security/cacerts/455f1b52.0 +SHA1-Digest: IK/26zCMyRWnrIwW2qASL3px2sU= + +Name: system/etc/permissions/android.hardware.touchscreen.multitouch.j + azzhand.xml +SHA1-Digest: +3w9s8y7aS1ccCYaDZP65k5lMVM= + +Name: system/etc/security/cacerts/03e16f6c.0 +SHA1-Digest: joMfuOODTdwYLn+o/FBfOobAp90= + +Name: system/media/audio/notifications/Maize.mp3 +SHA1-Digest: 7Y3rDIFovmU3ISyo1L2syRQEmq0= + +Name: system/usr/srec/en-US/compile_grammar.config +SHA1-Digest: M9bLVAEUN3cV/AB6Ng0mW2ljUGg= + +Name: system/usr/keylayout/Generic.kl +SHA1-Digest: 2Bn3gvxfnE10qV2h0uMsTJ6IRwo= + +Name: system/lib/libaudioflinger.so +SHA1-Digest: WidozZNbCHHWr3TIMCqOdMVIe68= + +Name: system/media/GPU/mask_vignette_legacy.bmp +SHA1-Digest: sptkLNnJq1p64FZslLh7sDENx1Q= + +Name: system/customize/resource/quicklaunch_28020.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/usr/keylayout/dummy_keypad.kl +SHA1-Digest: PDYRL0v0BqshAyIbN0KSP7Ei4Qk= + +Name: system/bin/dbus-daemon +SHA1-Digest: vLCWtNQClOzRPIQsve+0gHAZAuk= + +Name: system/media/audio/ui/camera_click.ogg +SHA1-Digest: jet4ZWI3QDsJT8T3YoNr9gH1NUc= + +Name: system/lib/libstagefright_soft_aacenc.so +SHA1-Digest: IWMCawTf/vpkOobJ8/VH9wjR6og= + +Name: system/lib/libext2fs.so +SHA1-Digest: jZqcTyc3ejb5VSIIVB1iW8UtOS0= + +Name: system/lib/libllvm-a3xx.so +SHA1-Digest: WO6rJvPjmmha7yiXjCvH5e9clz0= + +Name: system/etc/tfa/tfa9887_l.patch +SHA1-Digest: Kd02luAPrgU9ys9kn6jt3QLZdqk= + +Name: system/app/SetupWizard.apk +SHA1-Digest: yYpqA4bYT0xyW35QSy71HL5X9rE= + +Name: system/app/HtcNotes.apk +SHA1-Digest: Of5RW11wB63HtuBSoMDFMgClW3E= + +Name: system/etc/snd_soc_msm/snd_soc_msm_2x_Fusion3 +SHA1-Digest: pMkCwM+W9M9vdC2O3Ac3sTzOwuc= + +Name: system/media/weather/weather_l_cloudy_day.mp4 +SHA1-Digest: bqSdABAAbdbnLYoj2nuYG9TSeoY= + +Name: system/customize/resource/wallpapers_b_01.jpg +SHA1-Digest: CYURrn521O+KKiLOTihLWcW608o= + +Name: system/app/Mail+nonprime.apk +SHA1-Digest: YsL/O92Lp+PIXnRDV4RPMOZJo/o= + +Name: system/etc/security/cacerts/cdaebb72.0 +SHA1-Digest: 9xXJaJxcsRt52ZKmLTb10lCP8fM= + +Name: system/usr/keylayout/Vendor_045e_Product_028e.kl +SHA1-Digest: BsTBZddUa0mpDkeAEr4ZC/V3iX8= + +Name: system/lib/libwt6docrdr.so +SHA1-Digest: 7coR/U9TJL1PcJ1aA494cKidvQQ= + +Name: system/customize/resource/quicklaunch_63102.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/lib/modules/lcd.ko +SHA1-Digest: p2KD0JE9mSm14TUJMnLUyWm28TY= + +Name: system/etc/fallback_fonts-ja.xml +SHA1-Digest: hFw+wrKp3DC0jQjjI1j35jo7Lmc= + +Name: system/app/Automotive_Traffic.apk +SHA1-Digest: nM6tLvlAY8+lQQny3RLypLoz1yY= + +Name: system/etc/security/cacerts/dbc54cab.0 +SHA1-Digest: G7ilNysmUiKqjP0b0/CgdRCDdpE= + +Name: system/lib/libdefcontainer_jni.so +SHA1-Digest: UTtx60yLAvONe2tc2OMA79WMYyk= + +Name: system/bin/btld +SHA1-Digest: OffE5oP8VHmc1/0nC9HjaoRY+Ms= + +Name: system/etc/permissions/handheld_core_hardware.xml +SHA1-Digest: whHNJSrlPVXT63+1hEtHspIBsV0= + +Name: system/etc/image_htc_midtier.bin +SHA1-Digest: BQvgRVzmndETmB2zqTO7nDfu05c= + +Name: system/etc/tfa/ring.config +SHA1-Digest: mcDPznDmbQbzvQ1yOzfS3mAX2n0= + +Name: system/app/MyHTC.apk +SHA1-Digest: UOTbH+RhAvxYfUOH/n8R0Iim9eY= + +Name: system/app/CheckinProvider.apk +SHA1-Digest: OFAA6QUQgH5JM/DQXnSSpMPAeZ0= + +Name: system/customize/resource/quicklaunch_24801.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/framework/monkey.jar +SHA1-Digest: Kfe4Z7HMOx36ROXlGQaB8kQLAjU= + +Name: system/lib/libhtcflash.so +SHA1-Digest: icfl/z8ks/YUfItg1Xb9NTwHcJY= + +Name: system/fonts/DroidSerif-BoldItalic.ttf +SHA1-Digest: t/LTfDoGK+Zxd0/1L0/ZXL74E84= + +Name: system/lib/libwsp_jni.so +SHA1-Digest: 35uE8D9wGKJSjhnp3hDXjuryhJU= + +Name: system/etc/security/cacerts/5046c355.0 +SHA1-Digest: yq910Cd0R0uzSNpNm6fYzr5Q5Ho= + +Name: system/lib/libwivu.so +SHA1-Digest: JPKZ5bsWYjO31qs3MSIgIZkBngg= + +Name: system/bin/surfaceflinger +SHA1-Digest: Nzd11E5dNzy+pj8QMti9NjEYpnk= + +Name: system/lib/libcpt9core.so +SHA1-Digest: yQuLEK5jcxzCXisprspXorgsQw4= + +Name: system/etc/security/cacerts/ce1adacf.0 +SHA1-Digest: cIi2wLDmlyHctdMiDeeu/VF3g1c= + +Name: system/app/IdleScreen_No_lock_screen.apk +SHA1-Digest: 2Eg4YSmM0hGFdqXVReUt2SNCpSk= + +Name: system/bin/memlock +SHA1-Digest: gQy7+jwKorad5h5KhsY8HB8Sk0s= + +Name: system/etc/security/cacerts/11f154d6.0 +SHA1-Digest: zkNyiWna542K/kWuC7wUAMTPM0Y= + +Name: system/etc/security/cacerts/5a5372fc.0 +SHA1-Digest: lRZnSCW+h2OrdLdhSE/61v9FF5g= + +Name: system/etc/security/cacerts/9685a493.0 +SHA1-Digest: kaSX6pI0rQB+TDbRWSlOP44RXUE= + +Name: system/media/GPU/dot_mask_2.bmp +SHA1-Digest: sjcQcSVjA2XM1TxpkSbHjsxbDF8= + +Name: system/etc/tfa/recorder_l.config +SHA1-Digest: mcDPznDmbQbzvQ1yOzfS3mAX2n0= + +Name: additions/fonts/comicsans/Roboto-Bold.ttf +SHA1-Digest: 1vu6g8g0wpPV9wtnDqmeZv/44CA= + +Name: system/media/zchgd/batt_95.rle +SHA1-Digest: 4MVAx4a7RzDHup8UZBR1bxcMMwo= + +Name: system/app/IMEXT9English.apk +SHA1-Digest: Lt9vqMB+TDpKWAfTKsT7tsk/3Nk= + +Name: system/lib/libwt6epprndrv.so +SHA1-Digest: DivO8hstWF82Qz59KZqcfPbdIKc= + +Name: system/etc/tfa/ring_l.config +SHA1-Digest: mcDPznDmbQbzvQ1yOzfS3mAX2n0= + +Name: system/lib/libdsprofile.so +SHA1-Digest: sA2FesTFJAf4f67bqF9IhYSXKFw= + +Name: system/etc/tfa/recorder_l.eq +SHA1-Digest: yVnitUPrXicZNKfZWIRmiKsUotA= + +Name: system/lib/libDxDrmJava.so +SHA1-Digest: QyPndMGblkKvHV4OZ5E6s/7JBto= + +Name: system/media/audio/ringtones/Emerald.mp3 +SHA1-Digest: Gh51VoohEE1bdGYLkq7bbQhGQh8= + +Name: system/customize/resource/allapplication_28001.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/lib/chiaddict.dat +SHA1-Digest: 85pAZ/jBIMhVFp3HKNeiyVE5WqQ= + +Name: system/bin/netd +SHA1-Digest: KxsVClbuTlqxb6fe7d517VQiVQI= + +Name: system/etc/image_gec_2vol.bin +SHA1-Digest: c3h5EiPq0vgBG4R2HBL/c17QSxs= + +Name: system/etc/htcfs.conf +SHA1-Digest: HeXpVVeMwj4YPEiLlsiwMzjYJ40= + +Name: system/media/weather/weather_rain_day.mp4 +SHA1-Digest: KEfSq7YK0eJH3C9m+mAstKK0HXE= + +Name: system/etc/security/cacerts/d64f06f3.0 +SHA1-Digest: 0RWeUYy8yvPc5W09WdfTXhlSn7A= + +Name: system/bin/schedtest +SHA1-Digest: 60DcaKewo7d7KqtxIJppcZ12FEU= + +Name: system/app/CertInstaller.apk +SHA1-Digest: VjxzxabP+8M0I+Eqany0AIcshF8= + +Name: system/usr/srec/en-US/grammar.config +SHA1-Digest: +twRBfiA7IzTU1sLmK3tG316qUM= + +Name: system/media/weather/weather_l_cloudy_night.mp4 +SHA1-Digest: yJ+y0IAMkSi2f8BCptEigyJbsJI= + +Name: system/app/Liveretouch.apk +SHA1-Digest: llzVpH+/tc22GSBAcP5t/Qi9otI= + +Name: system/media/audio/ringtones/Grey.mp3 +SHA1-Digest: 1DWo0fvo6VSyRSgFr+xWeQbyboY= + +Name: system/etc/security/cacerts/d2adc77d.0 +SHA1-Digest: ubLdIu8HnKW70iqEOAjEVa0wb7E= + +Name: system/app/CustomizationSettingsProvider.apk +SHA1-Digest: LJTL72fe4gTO2NWhVoVTbRKkAWQ= + +Name: system/lib/libstagefright_soft_flacenc.so +SHA1-Digest: RmB9eqtlD3N94l4pvj7iU5j/JJc= + +Name: system/lib/libfilterpack_facedetect.so +SHA1-Digest: kduWGk1cz2zwFnv/PqJejadfrKw= + +Name: system/media/audio/ringtones/Ultramarine.mp3 +SHA1-Digest: z+I1piLy0ys8STWPjHa+DmneuQ0= + +Name: system/lib/libmmstillomx.so +SHA1-Digest: NIqu8AWrgVpUz/RQ9MYaZmRGPgQ= + +Name: system/app/NetworkLocation.apk +SHA1-Digest: OEv5L2BDvqj0WX/OwQ8SC6YM21Q= + +Name: system/lib/libgsl.so +SHA1-Digest: A5oLBdLBAeOvTswhqi1BzCjXsm4= + +Name: system/etc/tfa/voip.preset +SHA1-Digest: OVBiITpEEwnpRzjGcCTdTkgmGA4= + +Name: system/etc/image_gec.bin +SHA1-Digest: f997e72Hw94tjKgYBxm0sr48UZI= + +Name: system/app/FM_Radio.apk +SHA1-Digest: 8NASxviuaV2bb6E+yG2h34toPL4= + +Name: system/lib/libmmwfdsrcinterface.so +SHA1-Digest: oLubjM57VO/TbHmXey26hXnZbfI= + +Name: system/usr/srec/en-US/acoustic_model +SHA1-Digest: cfkvAc/HaQ1I8nrAw+GLdvrr2oc= + +Name: system/lib/libusbnetjni.so +SHA1-Digest: OWohQT0SsuwTVMciPvGBLwcVADM= + +Name: system/bin/v4l2-qcamera-app +SHA1-Digest: 7gvTDFVnEd/QJRifDhFg3kw2opY= + +Name: system/lib/libswapheap.so +SHA1-Digest: uSBGNOr/JuRG9ZOuwn3fKXiLT20= + +Name: system/lib/libwfdrtsp.so +SHA1-Digest: IwSZFYZlRJswU0oz0TlEGAmbVyw= + +Name: system/bin/atrace +SHA1-Digest: oAIPhNcMnmoHb03JNVsbPuc9Wr0= + +Name: system/bin/mm-qcamera-daemon +SHA1-Digest: Evh8sDNPO2l51znGMPbwgiiWZpY= + +Name: system/etc/permissions/android.software.live_wallpaper.xml +SHA1-Digest: XSE9c962K3wJVmHaaJ4PglJg9iQ= + +Name: system/fonts/DroidSansArmenian.ttf +SHA1-Digest: lC+raRjA3Jv1n2KrFeP9OHNrvo0= + +Name: system/bin/mediaserver +SHA1-Digest: 9F9xOzk836QYl9R4E2VPO3o/5C8= + +Name: system/media/zchgd/batt_0.rle +SHA1-Digest: pxzRkTs4X+F5+2a0W+ThQYarA0Q= + +Name: system/etc/security/cacerts/57692373.0 +SHA1-Digest: cxktqBsx3bsf1do5QynEaxTvX64= + +Name: system/app/HtcProfilesWidget.apk +SHA1-Digest: yVBE3tM3KlvzBjwcm9mxyHCHaFE= + +Name: system/lib/libandroidfw.so +SHA1-Digest: jd2DLIwwIjNnzdrHwlbPbJoWZl0= + +Name: system/lib/libjpeg.so +SHA1-Digest: T3UJ41FfePmAwYh1MWsUEUZuTbU= + +Name: system/media/audio/ringtones/Tangerine.mp3 +SHA1-Digest: tVkPUTi2D7rUXdNF8LpviMe3Nwc= + +Name: system/lib/modules/msm-buspm-dev.ko +SHA1-Digest: Cw7O74pnvnOM2O+NgSdhQN+tbYY= + +Name: additions/fonts/comfortaa/Roboto-Regular.ttf +SHA1-Digest: 2p1tyuEu2DmaDtDgX8hfYUUU6iI= + +Name: system/lib/libdumppcm.so +SHA1-Digest: Bpe+qsMbPkq04Xq53iNUXiGWSq4= + +Name: system/etc/tfa/voice.config +SHA1-Digest: HKUbwkwyeWNkWCWTnAgcEbOJbpQ= + +Name: system/etc/tfa/recorder.eq +SHA1-Digest: yVnitUPrXicZNKfZWIRmiKsUotA= + +Name: system/media/audio/alarms/Taupe.mp3 +SHA1-Digest: x7HaNTdM9IGZhZMXtELhkknxjBI= + +Name: system/lib/libwt6bjprndrv.so +SHA1-Digest: tKKavt5fW8gzEf3YeVyrfH5DY6A= + +Name: system/etc/security/cacerts/7a819ef2.0 +SHA1-Digest: sPFvH0vDqnbyji1Ydpg3E5Jsph8= + +Name: system/framework/com.dropboxpartner.jar +SHA1-Digest: 49iathKtlRnATkLFBV+ykocqG3I= + +Name: system/lib/libchromatix_imx175_default_video.so +SHA1-Digest: ApWU1yreGwFXecrytZ06LkIYqCQ= + +Name: data/app/com.google.android.apps.maps-1.apk +SHA1-Digest: 2BwczxCxJPaUJQ+QJa1xqCcFva8= + +Name: system/etc/init.qcom.bt.sh +SHA1-Digest: kVjq1GcV+qMGYnbUSp9GrvhraA4= + +Name: system/lib/libext2_uuid.so +SHA1-Digest: 4CnYPTuKmsCDazcosPEwBoTlhvA= + +Name: system/fonts/AndroidEmoji.ttf +SHA1-Digest: ZBbXr5sxLSyugwpq55Z15ajrX84= + +Name: system/fonts/ucsh00d_c.ttf +SHA1-Digest: HVQrSni9pygKOOT38dwxiXhQP8Q= + +Name: system/etc/thermald_boot.conf +SHA1-Digest: 78zY9hqxtRpnnI/IRdSh5LNog3I= + +Name: META-INF/com/google/android/aroma/themes/sense/radio.png +SHA1-Digest: 1wbvEt+0D4I0q/rFu1t19w4Gqow= + +Name: system/etc/security/cacerts/8ccb5f6d.0 +SHA1-Digest: RiH8pECN67dnw5z0r+NP3XM5Lw0= + +Name: system/framework/com.htc.android.bluetooth.le.jar +SHA1-Digest: 0rpN6wUBYRo25q0EzGGKwaqEV/Q= + +Name: system/app/IMEXT9Hebrew.apk +SHA1-Digest: KYshzfQSG8csCAFqTJ6e3P9yjfg= + +Name: system/vendor/tmo_cm/demoutil +SHA1-Digest: FGie6hvQPvklcsleJVa1/DCcdyQ= + +Name: system/lib/libtzsrv.so +SHA1-Digest: va4N5zf2EKkqtxmNDmxc4tE9v7k= + +Name: system/media/weather/weather_l_partly_sunny.mp4 +SHA1-Digest: HRDmwgjrIkn08jW1GVmcK3YZ5og= + +Name: system/usr/share/partials/partials_CW.dat +SHA1-Digest: QM66QXBaDtvPMgoYA6Us3ARHjfQ= + +Name: system/customize/resource/allapplication_26003.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/etc/tfa/deftcoefA_l.speaker +SHA1-Digest: SKR62eVqVHRTCir6cWJ9OE2ezUo= + +Name: system/vendor/lib/libWVStreamControlAPI_L1.so +SHA1-Digest: BB1gSObJzUFhIrVZMBes4e/V+2o= + +Name: system/usr/srec/config/en.us/models/generic11.lda +SHA1-Digest: /y/sXjBSqRQkFc848OCkAh9PhTE= + +Name: system/etc/firmware/hcheck.mdt +SHA1-Digest: kpgwhIcZ5cfbiZZ3c/LDaCiDvLA= + +Name: system/app/Camera.apk +SHA1-Digest: vJzwJD/1BPe390OxazKGU+N60DI= + +Name: META-INF/com/google/android/aroma/scripts/restore.sh +SHA1-Digest: vRdoYWSdDNGNVXs2dq0E2HZOuDk= + +Name: system/app/HtcResetNotify.apk +SHA1-Digest: mQeLikCqCW9ZBXpoIo0QazwoTK8= + +Name: system/lib/liboma-drm1-fs.so +SHA1-Digest: 4ov3R6J9WJz6w+vybFX93XoCa78= + +Name: system/etc/tfa/playbackbeats_l.eq +SHA1-Digest: GRbTA4TG5srGNohUHz6/IXX9Ffo= + +Name: system/media/GPU/dot_mask_1.bmp +SHA1-Digest: Wax3umuK2HuUtQBi6arUPTP2WPc= + +Name: system/etc/permissions/com.android.nfc_extras.xml +SHA1-Digest: ZvocFvtXygXFd7nw2Ja+V7G7PR4= + +Name: system/etc/permissions/com.google.widevine.software.drm.xml +SHA1-Digest: Gggf4BO2xlvJgH9ml/1pz/WZTAE= + +Name: system/lib/liblog.so +SHA1-Digest: +gHvJkV1p5Y18EfkwxHDSWDrKhk= + +Name: system/vendor/lib/drm/libdrmwvmplugin.so +SHA1-Digest: Ebyulhu+DJrZwZGv4+uC182OV4I= + +Name: system/etc/tfa/video.eq +SHA1-Digest: yVnitUPrXicZNKfZWIRmiKsUotA= + +Name: system/media/audio/alarms/Metal.mp3 +SHA1-Digest: fpZhnFeMMo3VpXTZUSpYDd3zFcc= + +Name: system/etc/firmware/BCM4335B0_002.001.006.0042.0044.hcd +SHA1-Digest: spwgfp+HFxE7G1LAMC/wM90T+FY= + +Name: system/etc/tfa/tfa9887_l.speaker +SHA1-Digest: sw/pJtd7xyhONVoxqf9knMu5s/c= + +Name: system/etc/tfa/voip_l.preset +SHA1-Digest: OVBiITpEEwnpRzjGcCTdTkgmGA4= + +Name: system/customize/resource/quicklaunch_21910.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/app/DeviceManagement.apk +SHA1-Digest: I4VtjQHhZJTxdTNj8rAFMlNm/1g= + +Name: system/framework/framework2.jar +SHA1-Digest: 66IZBoOGdnGAkiijrTM3SMV1Nlg= + +Name: system/lib/modules/qcrypto.ko +SHA1-Digest: Ni5oyZEvvjgQFlTJYfyGArIs8Ic= + +Name: system/bin/iptables +SHA1-Digest: 2Yp8m4EFPry2awwZt5aBBjaFd1c= + +Name: system/lib/libchromatix_ov5693_default_video.so +SHA1-Digest: rm/zEvmmaXZu39ipCPXvZOuBneM= + +Name: system/lib/libchromatix_imx135_hdr.so +SHA1-Digest: CuXA/vJ+5WBphZamfxsAXvNUYDk= + +Name: system/lib/libmmcamera_frameproc.so +SHA1-Digest: 3fbV7O/u6K1FwBRF0UElF/qJ0ZM= + +Name: system/etc/security/cacerts/bdacca6f.0 +SHA1-Digest: 6zbSCMgMZa9LslRYITBh6DFKQSY= + +Name: system/lib/libdrmtime.so +SHA1-Digest: R+VHrLTTgQOITEhkOAlveQlq4R4= + +Name: system/lib/libmorpho_frame_overlay.so +SHA1-Digest: mwItnbN3XLYfV0ttYAM1S9BNbSg= + +Name: system/media/audio/notifications/Ivory.mp3 +SHA1-Digest: dGvQgq+o4pPceW5wXEkw3ASWqBY= + +Name: system/app/HtcSettingsProvider.apk +SHA1-Digest: LgFmDJVDNdAx7R0wUvgJ1hFKk7Y= + +Name: system/lib/libwt6pdfrdr.so +SHA1-Digest: zD6aYZT9jbZHjUT6yLKAh42np7Q= + +Name: system/etc/tfa/ring.preset +SHA1-Digest: gFz2Zw5riOxrVU5rGDqqz6MwXYI= + +Name: system/lib/libchromatix_s5k6a1gx_hdr.so +SHA1-Digest: PNAC3Y4r+OTMVGl1NQK3qKv1tAA= + +Name: system/lib/libgccdemangle.so +SHA1-Digest: w5+dUn8Aeb8vEnHRG0w7Vircp0o= + +Name: system/app/IMEXT9Croatian.apk +SHA1-Digest: SBiV8dxn1oonNaGzuXbSaDY4SvY= + +Name: system/etc/pnp.xml +SHA1-Digest: VAdO916JdGgtDk88gLxBHlcy1fw= + +Name: system/app/HtcAlbumMapView.apk +SHA1-Digest: jRomM3zEV34PkSib+onlOG2G6Ug= + +Name: system/app/IMEXT9Kazakh.apk +SHA1-Digest: HbrImUPCYO6yr5HldiscOCbMEV4= + +Name: system/app/COTAClient.apk +SHA1-Digest: x9ha/w3v1RWfFe/Y/MGDE8UdhnM= + +Name: system/etc/firmware/a225_pm4.fw +SHA1-Digest: h9byfKCLUhzDNh9j8GMaH+8kA6w= + +Name: system/app/DownloadProviderUi.apk +SHA1-Digest: 0B0Kr6sXMMvReo+nWVJ83Zo45xQ= + +Name: system/etc/security/cacerts/d78a75c7.0 +SHA1-Digest: jRLGGp/ersc4b9xR3gfIJpalIK0= + +Name: system/media/audio/ui/Effect_Tick.ogg +SHA1-Digest: jdIBk/wZcXKAuBBFS0XV0YpPWNw= + +Name: system/media/weather/weather_l_snow_day.mp4 +SHA1-Digest: UEAete7q4zTgaOmLqJZIF/ThM6E= + +Name: system/lib/libdrmfs.so +SHA1-Digest: UijPliPLfknHZbBFsiOcWgzBuV8= + +Name: system/etc/security/cacerts/86212b19.0 +SHA1-Digest: z5oVrRiZngoDfKl6smrTYg59YWM= + +Name: system/lib/libstagefright_soft_aacdec1.so +SHA1-Digest: d6trVJMYtBd71+BqS1tzytrmBwc= + +Name: system/customize/resource/wallpapers_c_03.jpg +SHA1-Digest: aYZVl15XqVYu7uGhLnCtaznrYck= + +Name: system/lib/libmorpho_image_transform.so +SHA1-Digest: b98BD4Y8WRNobNTHfFX2+vMvhPw= + +Name: additions/openvpn/xbin/bb/placeholder +SHA1-Digest: 2jmj7l5rSw0yVb/vlWAYkK/YBwk= + +Name: system/lib/libfuse.so +SHA1-Digest: 1bnxYpVPN31kddW9VwMkK10tdjk= + +Name: system/etc/tfa/voice.eq +SHA1-Digest: akzJZd8ilz4aAsWHG6uC3H5L+tk= + +Name: system/etc/wfdconfig.xml +SHA1-Digest: WtcnhaAVQR0lKxzsfzuX1x51g+Y= + +Name: system/bin/getevent +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/tts/lang_pico/it-IT_cm0_sg.bin +SHA1-Digest: z7Ft7pwEG46mPScafCDOoqZt8HE= + +Name: system/lib/modules/ansi_cprng.ko +SHA1-Digest: rXVXGV2Ia4PsLRJYyQLOQ9iDyNo= + +Name: system/bin/diag_uart_log +SHA1-Digest: 19q3MUyJ8TtQ65AOR35CNDfsW2M= + +Name: system/bin/pppd +SHA1-Digest: 5VzcXeD3kOye440tK3zSIcmwV5E= + +Name: system/lib/libbeatscorehtc.so +SHA1-Digest: 0Fas1vcZaoWEEQK4fD1wKkG3DF4= + +Name: system/lib/libchromatix_s5k6a2ya_hdr.so +SHA1-Digest: dMjTlkTv8rJxhfuDffKTerLqXrM= + +Name: system/lib/modules/qce40.ko +SHA1-Digest: F2VksRKR7IGkaYYQGepHRA9zQFQ= + +Name: system/lib/soundfx/libvisualizer.so +SHA1-Digest: yLn/2BuFnHJdK5j5MBnl//hvqYU= + +Name: system/lib/libqdcbutils.so +SHA1-Digest: X0qjs+57Xnw9Xt3gB52F2Ij4tDE= + +Name: system/framework/com.android.future.usb.accessory.jar +SHA1-Digest: +cUBlanPKJOyUNPWTeuauMgH9lI= + +Name: system/app/Message+Nonprime.apk +SHA1-Digest: INL8ZGLvnTsZDnGT3oOHliFs7rc= + +Name: system/customize/resource/allapplication_21407.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/lib/libiculx.so +SHA1-Digest: TFeAc/ZJL9fyAHMgutH6ZsaPhDo= + +Name: system/lib/libmode10fx.so +SHA1-Digest: l4GwEMvWuivktE6foJU1va6p7mE= + +Name: system/lib/modules/evbug.ko +SHA1-Digest: +XH+Oxrhtq97b0wjwVLvYV5ynus= + +Name: system/app/HtcMediaCacheService.apk +SHA1-Digest: avJjdnSTlCyiY4CKak1ToOUJCmg= + +Name: system/bin/installd +SHA1-Digest: acEr58yRetZ7tN0f3ZDjQdmLQoU= + +Name: system/usr/keychars/qwerty.kcm +SHA1-Digest: TsWF0/tutWtAi0whFMCQCDu+uZg= + +Name: system/etc/permissions/android.software.sip.xml +SHA1-Digest: 1GKUjmqd+/qTc9Ke8c+RbW3a1jk= + +Name: system/etc/security/cwcerts.zip +SHA1-Digest: xNqzvX4C4xGsQrVMWIVxm4z/8yA= + +Name: system/media/mms/atis_tia_cmas_alert.mp3 +SHA1-Digest: LssUZvBfcn9LUQMvsj+RnvVGa/8= + +Name: system/framework/com.htc.lockscreen.fusion.jar +SHA1-Digest: 8GnpugUMNUA8XYBFMI+DVbiULEI= + +Name: system/lib/plugins/com.adobe.flashplayer/libstagefright_honeycom + b.so +SHA1-Digest: uWjsCs50ibuut/XTIp3J94p4HSo= + +Name: system/customize/resource/rp_ce_0700.png +SHA1-Digest: Nlz8m5UiVPcOs8ynWRYzBgWMqx8= + +Name: system/lib/libjDTCPServer.so +SHA1-Digest: YsvrOx6D/ipBSmuknx2QcEIoiNQ= + +Name: system/customize/resource/quicklaunch_20601.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/bin/cmp +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/lib/libNEONImage.so +SHA1-Digest: 3IKqQsrcobW6FSodXVwVffdAins= + +Name: system/bin/insmod +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/lib/libchromatix_s5k6a1gx_hfr.so +SHA1-Digest: bZqm1iwAYfwvIuNDjcAQJw3zzJo= + +Name: system/usr/srec/en-US/endpointer_voicesearch.config +SHA1-Digest: nhkSWehXFaaI7ycDX+V9HMkl0m0= + +Name: system/lib/libjni_fe.so +SHA1-Digest: hlQUpmjshanl1eBgH1uQPO34jrs= + +Name: system/lib/libopencv_java.so +SHA1-Digest: nenUMgD0CwQmI5BNr6SMneu/gu4= + +Name: system/app/HomePersonalize.apk +SHA1-Digest: rdBD2DqXz7VziiG12H0ZHlUBELA= + +Name: system/lib/hw/gps.default.so +SHA1-Digest: Z0OioAf19Krb6KN/U+YjH4mPNmc= + +Name: system/etc/security/cacerts/b0f3e76e.0 +SHA1-Digest: Xyiw528S3pbKQvg1OVh6hyfYS8k= + +Name: system/usr/share/partials/partials_A.dat +SHA1-Digest: xZzfW8IVOK8KFwWXGOEUbHuh69M= + +Name: system/lib/modules/dm-crypt.ko +SHA1-Digest: Df4JmM94KLbR7HrMKtyEi4+J4PE= + +Name: additions/screenshot/screenshot.sh +SHA1-Digest: +ZWG4bOr+IAoYljI+NgPyrB1M08= + +Name: system/lib/libmlplatform.so +SHA1-Digest: Ft84I4vZerg+XlJxK0jExyWz9Yw= + +Name: system/media/zchgd/batt_10.rle +SHA1-Digest: hH7rhOpOgTqVZLwooLGMDXkoYWc= + +Name: system/customize/resource/allapplication_20205.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/usr/keylayout/Vendor_054c_Product_0268.kl +SHA1-Digest: AHzPYrfjA0QHSpO6s67YfBjJQZU= + +Name: system/lib/libgnmc_fpx.2.5.9.4.so +SHA1-Digest: 8ez4St4BoPHoMjScZ4SQBuFis1w= + +Name: system/lib/libgenlock.so +SHA1-Digest: J0pjn4zMVKj+ocwUtRBeqyH3Bmw= + +Name: system/app/HtcMobileNetworkWidget.apk +SHA1-Digest: +Ztrbac+ub6/EeN9qIerLQxeDdU= + +Name: system/etc/init.d/99complete +SHA1-Digest: CnRVb2+/yVfPYZCj8AG5fWjPmNk= + +Name: system/fonts/DroidSansFallback-htc.ttf +SHA1-Digest: DWwjun5t3d3PeHfrFs8/TYTdXRE= + +Name: system/bin/rild +SHA1-Digest: HB9YpIJkGb9cj1PP0AcGwtmzJW4= + +Name: system/bin/logcat2 +SHA1-Digest: 6TafioEigwWHrC6otd7YlLJCRNo= + +Name: system/lib/libhtc_rilhook.so +SHA1-Digest: l7WnlLGKg7vN2zTtW7VkdVGThEY= + +Name: system/etc/wifi/wpa_supplicant.conf +SHA1-Digest: gnijNFdlV/VI2tMxz7KcnFewPuA= + +Name: system/customize/resource/allapplication_26806.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/xbin/bttest +SHA1-Digest: 6+BO9zoiX5X2O4tniaMMIBh9MsM= + +Name: system/lib/libiprouteutil.so +SHA1-Digest: ZRcT8RXBzbFs5MPoU77lxybGXvo= + +Name: system/customize/resource/allapplication_22201.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/app/PureC_PackageInstaller.apk +SHA1-Digest: 1lN/ofD+V/G3//ApYVGO3YWWXSk= + +Name: additions/camera_4.2/app/GmsCore.apk +SHA1-Digest: q6CT0jzv1Ror8dZprbIhyBRvQFg= + +Name: system/fonts/DroidSansTamil-Regular.ttf +SHA1-Digest: /e/ks+E8syMC6xadn01QJRV6mwg= + +Name: system/usr/srec/config/en.us/grammars/boolean.g2g +SHA1-Digest: Y6aiso1+39wx/fFSodB1MOdR7GQ= + +Name: system/lib/libzeroeditor_osal.so +SHA1-Digest: S5KHswnBrw9QL2q+NK6qxf2whbQ= + +Name: system/media/weather/weather_fog_day.mp4 +SHA1-Digest: zvAggeABRU3wx0RdwiJam2W9gSY= + +Name: system/lib/libmorpho_image_converter.so +SHA1-Digest: sDD/ahc6gG/2mzwp0mh34BW2opk= + +Name: system/fonts/DroidKufi-Regular.ttf +SHA1-Digest: 8qblYJhDwV7V6UscEs+VrSPgqjY= + +Name: system/etc/fallback_fonts-HTC__J15.xml +SHA1-Digest: wwDIFQFgqxmpCQXnggRhsY7lwRI= + +Name: system/lib/libhtcdrm1.so +SHA1-Digest: IxQj0Pm3qbjElIIwy2HELUNDN0c= + +Name: system/usr/keylayout/Vendor_046d_Product_c299.kl +SHA1-Digest: wIcNdtms/WYTXXig4lG68oFo/4A= + +Name: system/customize/resource/allapplication_28020.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/customize/resource/wallpapers_a_07.jpg +SHA1-Digest: QISjVTiPyhffZCfj0ZfoxpcWO/4= + +Name: system/lib/libimage-jpeg-enc-omx-comp.so +SHA1-Digest: 7LhOjPtOchiJsoHRIAehb2NU3bw= + +Name: system/lib/libmediaplayerservice.so +SHA1-Digest: BqAjujCtAEHP9YFdwxGBqkUyPQQ= + +Name: system/etc/security/cacerts/6b3f8240.0 +SHA1-Digest: 8bN1lqw6g87ShwSbO699nOS1KMM= + +Name: system/bin/log +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/lib/libsensorservice.so +SHA1-Digest: WGlSJx+uffDfyAll4kyILRYxfwc= + +Name: system/lib/libEGL.so +SHA1-Digest: HHq4wVnpdEk86yEoCARLjxZgjHM= + +Name: system/bin/hdmid +SHA1-Digest: +OwNWh2+4yyDvwYUlO1Elc6Q56U= + +Name: system/app/HtcHotspotWidget.apk +SHA1-Digest: hEkQk8aUV1jsrMzVPwDOTzPRe4Y= + +Name: system/lib/libt9.so +SHA1-Digest: ritqzaUaR88WsC/Aug2jeMsAoEE= + +Name: system/bin/dexopt +SHA1-Digest: bBBbMZ16oQHZiTqgH9q/1k1gW5w= + +Name: additions/fonts/helveticaneue/Roboto-BoldItalic.ttf +SHA1-Digest: hrfo9+REAhOTrclAM/0Q2aDTPtw= + +Name: system/media/zchgd/charging_06.rle +SHA1-Digest: 5sXmisNHh+5iyc5fMW1QUefvkHw= + +Name: system/app/PrivInit.apk +SHA1-Digest: tmlPsM+O/Th5a5pEuM1m7UsJy1I= + +Name: system/etc/firmware/vidcfw.elf +SHA1-Digest: Mx4rvApSUBdci9CXVoQAtIaY1jQ= + +Name: system/etc/init.post_boot.sh +SHA1-Digest: PETLFfEv+49NzIYR4JpnwJMJJZc= + +Name: data/app/com.adobe.reader-1.apk +SHA1-Digest: BqQn/+RpyR3gfjEouL+FSrIbvUw= + +Name: system/customize/resource/rp_ce_0560_i.png +SHA1-Digest: ficP8So1xl78fsNO60wU7+CobCM= + +Name: system/customize/resource/allapplication_20601.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/etc/tfa/tfa9887.speaker +SHA1-Digest: dDOaM5M/giSViXya0furAKBJ2nk= + +Name: system/app/CustomAppInstaller.apk +SHA1-Digest: UBxJOh3N5RObX6pTLFsT5lGtX5Q= + +Name: system/app/IMEXT9Romanian.apk +SHA1-Digest: MSxxDWuVCefhexCkAzYiY88VABA= + +Name: system/app/SelectPlayer.apk +SHA1-Digest: 2XsY4OwW6Emn0/h+nB7TEm2egE4= + +Name: system/etc/permissions/com.nxp.mifare.xml +SHA1-Digest: NHX3y1UpJ+hZmxuIG3M5wc2meZQ= + +Name: system/lib/libmorpho_memory_allocator.so +SHA1-Digest: XoN/HJrKoupLdpJcq/4wZiVIsSs= + +Name: system/etc/security/cacerts/7d453d8f.0 +SHA1-Digest: KA7EPB8eqmgYlxbOQtVKnWf+GDk= + +Name: additions/fonts/sonysketchef/Roboto-Italic.ttf +SHA1-Digest: 1zCsX+RdRK2+Hip1fVXHo514Rlo= + +Name: system/customize/resource/quicklaunch_21419.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/customize/resource/allapplication_23802.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/etc/hosts +SHA1-Digest: 0jQXewud5TCfeP9Tnl6v6gDgad8= + +Name: system/media/audio/notifications/Lily.mp3 +SHA1-Digest: TRyYEW/06CgGWJFGoGZlqRqCgCo= + +Name: system/bin/qcks +SHA1-Digest: iLfliqcx1yJSz2S38lwlBtrCb9k= + +Name: system/lib/libstagefright_foundation.so +SHA1-Digest: vdi/Jm4HpfEcyNXAT3gjTvEALzk= + +Name: system/media/audio/ringtones/Auburn.mp3 +SHA1-Digest: 5QqIIrEs2e0RXsYC3GzzAVcVzH4= + +Name: system/lib/libstagefright_omx.so +SHA1-Digest: LdLnKzmaFvd7AUbkWO2R0ei8hu8= + +Name: system/etc/security/cacerts/add67345.0 +SHA1-Digest: 7q4BGtgTYUE358iZPLoaZft9+1U= + +Name: system/customize/resource/wallpapers_a_02.jpg +SHA1-Digest: 4l2b/97vCQGSPlx2CwNx3RlBX2k= + +Name: system/lib/bluez-plugin/bluetooth-health.so +SHA1-Digest: RV6FTb4q2okmKaxxQqfpbdZYEqw= + +Name: system/lib/libstagefright_soft_amrdec.so +SHA1-Digest: fDo5foBZ2lQxXrgMpAjwXrfUCZs= + +Name: system/usr/srec/config/en.us/grammars/VoiceDialer.g2g +SHA1-Digest: XmIZbaPyRCbQlbRk8avvfTN0VF4= + +Name: system/lib/modules/ks8851.ko +SHA1-Digest: d2rbxTyVPBSXPEXBcwRIxHFMR3g= + +Name: system/customize/resource/allapplication_24002.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/lib/libmmrtpdecoder.so +SHA1-Digest: TDVHa4JTGgFCOeXocES9R7OdDe0= + +Name: system/customize/resource/allapplication_23410.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/app/HtcLavaLiveWallpaper.apk +SHA1-Digest: HHcCSXypyN6pvStwQm3hty4+fFU= + +Name: system/xbin/tcpdump +SHA1-Digest: B9jgs60m1dMUmthmb5W2Qvq5N2A= + +Name: system/media/weather/weather_l_rain_night.mp4 +SHA1-Digest: BP6xNBn+l7AzUx8hINepsIkfmLk= + +Name: system/usr/share/bmd/RFFstd_501.bmd +SHA1-Digest: 0k98ukIhHL0h2zs4tRS2FMidCtE= + +Name: system/bin/arec +SHA1-Digest: +Ida7XXk/3YOIEVSbTpWDPaDMqM= + +Name: system/media/weather/weather_fog_night.mp4 +SHA1-Digest: 1tlC0yLo9lrT817DAHeVu3LP6EE= + +Name: system/framework/com.google.android.maps.jar +SHA1-Digest: bVajguL94nh7v1GkrPjARHw08zE= + +Name: system/media/audio/notifications/Pistachio.mp3 +SHA1-Digest: OayW/hU0w8NZEQZe1LmbDO6ITH0= + +Name: system/bin/monkey +SHA1-Digest: n6hOeaWcDYXtOM/S/BuElL10hfQ= + +Name: system/etc/firmware/tzapps.b03 +SHA1-Digest: /XR+GskqqT8KrDwQ7sDCPdVUzOA= + +Name: system/etc/security/cacerts/17b51fe6.0 +SHA1-Digest: hKFYfH2Zix7tBH5I1wFZbo/Uu1M= + +Name: system/bin/mm-vdec-omx-test +SHA1-Digest: /ynpAtMDzrHEUpKJycxasmg0BpU= + +Name: system/app/HtcMediaUploader.apk +SHA1-Digest: DuBN0D14qUEFKFmROCDQSEMdALI= + +Name: system/app/IMEXT9Slovenian.apk +SHA1-Digest: W9yQa+2WZGEFoZBBj4h8yg8VR3w= + +Name: system/lib/libchromatix_s5k6a1gx_preview.so +SHA1-Digest: M9+FuF7eLy76ADXb5myjVHN+qKc= + +Name: system/etc/firmware/tzapps.b01 +SHA1-Digest: 6EhkhARvMZD8gj0qjMuPWWvHi2s= + +Name: system/fonts/DroidSansThai.ttf +SHA1-Digest: 90bP0Gb6wvJfiap86bLKmXUIXpg= + +Name: system/vendor/pittpatt/models/recognition/face.face.y0-y0-22-b-N + /full_model.bin +SHA1-Digest: KblDOYF2yaers6P16X1U78FNHmo= + +Name: system/etc/firmware/tzapps.b02 +SHA1-Digest: nl4uvPbTSuKaUXBRxTCwv99kQTY= + +Name: system/lib/libcommon_time_client.so +SHA1-Digest: Wv9+6a+IJILSDBARvk6419S3PM0= + +Name: system/etc/firmware/tzapps.b00 +SHA1-Digest: ajmdiAw4ldokY5nVSdc6jH+1Fv0= + +Name: system/etc/security/cacerts/119afc2e.0 +SHA1-Digest: EWDvjIKz5iXOM8ywruinfBcudRs= + +Name: system/bin/watchprops +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/framework/browsermanagement.jar +SHA1-Digest: N81zoXfQjR572GywvaGR/NYRgjU= + +Name: system/app/GoogleServicesFramework.apk +SHA1-Digest: VHzT2lsiVAN675/KJK2CPUWRf2I= + +Name: META-INF/com/google/android/aroma/themes/sense/button.9.png +SHA1-Digest: InlGz7Cq45PigWMA4uPLHlms3+0= + +Name: system/media/audio/ui/Volume-5.flac +SHA1-Digest: ewkQuipEljWSztx0GZkDjC/T9Fo= + +Name: system/app/HTC_IR_Remote.apk +SHA1-Digest: HV7gFcxr6RAdjZw+0NsbJXkjbus= + +Name: system/lib/libstagefright_amrnb_common.so +SHA1-Digest: dxPR/svY1yVFA83S1UiUkyD228g= + +Name: system/app/HtcBtWidget.apk +SHA1-Digest: Yr1HhSH9x1RXUfcHvyw6FqF9fBo= + +Name: system/customize/resource/wallpapers_b_06.jpg +SHA1-Digest: jFHHhCqbnq8FrglsJOLbl2pL6Lc= + +Name: system/customize/resource/rp_ac_no_nfc.png +SHA1-Digest: 350zjLKXC0/TIruGqGLQOswctQM= + +Name: system/framework/com.htc.fusion.fx.jar +SHA1-Digest: eje7d/ifUw8hN1MSlnXEQH7p1xM= + +Name: system/etc/dhcpcd/dhcpcd-run-hooks +SHA1-Digest: 45jhBTsJr35CEQZApn9fjYeWTYA= + +Name: system/lib/libmorpho_jpeg_io.so +SHA1-Digest: nxbUbQNumyF4BO6VN42ruXXB3pU= + +Name: system/etc/security/cacerts/e7b8d656.0 +SHA1-Digest: H+gcIZ25xZ2zXtjkS4UDXDJdo7o= + +Name: system/etc/firmware/fw_bcm4335_apsta.bin +SHA1-Digest: tOGU7t2PAjHx4SyMN0ODOq33Q5Y= + +Name: system/media/LMprec_508.emd +SHA1-Digest: 6FhFfYVqFx0dhdkGKfVq/4ek+GY= + +Name: system/lib/libwlwpscli.so +SHA1-Digest: NUaizgnrnzhRVL2RlE14srPeXJE= + +Name: system/lib/libspeex_sh.so +SHA1-Digest: kvsBu1cUoOw4tCvXnDfeF2TYKQA= + +Name: system/customize/resource/quicklaunch_234.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/etc/tfa/playbackbeats.config +SHA1-Digest: j6S5V89FwvUw8PmIK737fBvqmO4= + +Name: system/lib/libbcc.so.sha1 +SHA1-Digest: Iz1kPz6CHH55kQCrIwbkuoRYlfk= + +Name: system/bin/wpa_supplicant +SHA1-Digest: 9O/IOgmSBhu2MBcb1GL4Mi2FHCo= + +Name: system/app/ChromeBookmarksSyncAdapter.apk +SHA1-Digest: 7+Ainsjkh0eQzisgg61adorIbYI= + +Name: system/usr/srec/en-US/norm_fst +SHA1-Digest: 32Va9kDkSjxVzWPqPAuaFcGR824= + +Name: system/media/weather/weather_l_partly_cloud_night.mp4 +SHA1-Digest: eXPCSlmRkUbObdGF0BDSKlvQF8w= + +Name: system/media/audio/alarms/Sea_Green.mp3 +SHA1-Digest: AW72uwxPQnW6LD6EOfJlbep9qcw= + +Name: system/lib/libril.so +SHA1-Digest: xtM5qbO0otiQb4Lf3MA5j1liBiE= + +Name: system/lib/libwt6docintr.so +SHA1-Digest: cMuuHbQ4YRR12qq3fsh4VRg6xNk= + +Name: system/etc/permissions/com.htc.lockscreen.fusion.xml +SHA1-Digest: fMICRSZIHAqkIugRoyji09kbU7w= + +Name: system/media/audio/ringtones/Violet.mp3 +SHA1-Digest: xckKz52mp++IoqDt0RoAKg2zwxs= + +Name: system/etc/dbus.conf +SHA1-Digest: tFSSxBd60rDOWFVGzFY7lMyaFcs= + +Name: system/app/SmartDim.apk +SHA1-Digest: DpDJNBJseuD9ZYPOlHtxwgTcdFg= + +Name: system/etc/tfa/playbackbeats.eq +SHA1-Digest: GRbTA4TG5srGNohUHz6/IXX9Ffo= + +Name: system/lib/libdnshostprio.so +SHA1-Digest: mZQPXUw71EJxOzmdz91kN9P+wdQ= + +Name: system/lib/libttscompat.so +SHA1-Digest: CmBjDj/n2wSRL4NDdtW5QK4fGpk= + +Name: system/app/HtcScreenBrightnessWidget.apk +SHA1-Digest: NrOGeNLycZ5xV/dYnopxwI6vSCA= + +Name: system/lib/libmmcamera_faceproc.so +SHA1-Digest: 8D8rJPbt+VvBtZ0blTOWgWfb18A= + +Name: system/bin/sdptool +SHA1-Digest: 9ZTFNlZ95GcqWWaZbY/GPfJLFi4= + +Name: system/media/audio/ui/KeypressReturn.ogg +SHA1-Digest: AhKAuhFRUYILt2u43zNK389U9hE= + +Name: system/usr/srec/config/en.us/baseline.par +SHA1-Digest: mOE8GQoDRu/VLgUGSPxYHPuTfIc= + +Name: system/bin/test_gemini +SHA1-Digest: QCxZBkfqAnnFUJh854ow4yU7hms= + +Name: META-INF/com/google/android/aroma/icons/update.png +SHA1-Digest: /TMHtx0Qm4TkPEEeYHxdW6dBApY= + +Name: META-INF/com/google/android/update-binary-installer +SHA1-Digest: GZ+9X0ra+kM28qh/Dsrgb0KaIQA= + +Name: META-INF/com/google/android/aroma/themes/sense/cb_on.png +SHA1-Digest: 9VS4RbjDR4WXSrUKhpx828IJREI= + +Name: system/lib/bluez-plugin/input.so +SHA1-Digest: Xky071GSJofAmhM29sIfvhFiRiM= + +Name: data/app/com.google.android.gms-1.apk +SHA1-Digest: wN5vHNB3EYgxbAIfFV0AJGWaK1Q= + +Name: system/app/AndroidHtcSync.apk +SHA1-Digest: o8JzqbMaE6/zYAh1iY4L6HDWqe0= + +Name: system/etc/permissions/android.hardware.touchscreen.multitouch.d + istinct.xml +SHA1-Digest: 6bH+JNF8K7loeVqBinWWVhatvEU= + +Name: system/customize/resource/allapplication_21406.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/bin/sleep +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/app/CalculatorWidget.apk +SHA1-Digest: MAx/MqvXBSSpbgCFul3jyWlETAM= + +Name: system/fonts/AnjaliNewLipi-light.ttf +SHA1-Digest: rU+cXSq1srM57xAO9aHbB+WV8No= + +Name: system/etc/security/cacerts/4e18c148.0 +SHA1-Digest: 1Cu+Q2UOC9j8wfjVMl1AK6h2IPo= + +Name: system/app/Basic.apk +SHA1-Digest: 6FgOxuXOQd0pkcwWQuGb+ogXIoU= + +Name: system/app/IMEXT9Turkish.apk +SHA1-Digest: v0hfNh9uEDFedhE45xQxDR9Vyo4= + +Name: system/etc/security/cacerts/ff783690.0 +SHA1-Digest: 7sOkn8zxphGUXHNkddKmw5n9Lrw= + +Name: system/lib/libwt6imgrdr.so +SHA1-Digest: gvVKNg9lMEbn2bL8cRllFaLVumw= + +Name: system/bin/app_process +SHA1-Digest: WvPCmzYJRLX9uaJEpBabdCns+NE= + +Name: system/lib/plugins/com.adobe.flashplayer/libstagefright_froyo.so +SHA1-Digest: vQEUytAuigLJJbJWsXDNaf/YSuU= + +Name: system/media/zchgd/batt_100.rle +SHA1-Digest: DqypThdyPWCZQTQ1TTbGt94te2o= + +Name: system/lib/libstagefright_soft_h264dec.so +SHA1-Digest: XdBsOuVDvbb4QfOxCPpVslufVF8= + +Name: system/lib/libhtcpainting.so +SHA1-Digest: i1tLwPyuVEgPk1M4oc8rNUbhC94= + +Name: system/lib/libssl.so +SHA1-Digest: SFV4A69frH0oevUOL/iCMpSGF70= + +Name: system/app/HtcPowerManager.apk +SHA1-Digest: nQpau0Ci9Dd0/D2qoZRMkUm9e1o= + +Name: system/bin/radish +SHA1-Digest: ZuH0aX+bOVnBm6LqLW3Ao5L+NHU= + +Name: additions/smson/app/Message.apk +SHA1-Digest: sAzIlEutDRa6NvwrAg6J/XEQmJw= + +Name: system/lib/libicule.so +SHA1-Digest: RFWGAf562CzfoH/hsfGhibTJDOI= + +Name: system/lib/libsc-a2xx.so +SHA1-Digest: h+Rqx/lpDSgBfVDo9bZ5KIRlegA= + +Name: system/media/zchgd/batt_80.rle +SHA1-Digest: c7okre4LVo5tBcQ9oP/g35t2NB0= + +Name: system/lib/tcp-connections.so +SHA1-Digest: HfuhcZxgF/H4/GE7BeLVpAe6/1Y= + +Name: system/lib/libwfdmmsrc.so +SHA1-Digest: jWdRj7Di+hhrY6tO3frTWz+rIxU= + +Name: system/lib/libchromatix_ov5693_hdr.so +SHA1-Digest: XC9+clcrEQoWK3oNCwk5H4RoXXc= + +Name: system/media/audio/ringtones/Indigo.mp3 +SHA1-Digest: uYAaWSSkaf3LEjeRLl9D3Ywj2SA= + +Name: system/app/IMEXT9Arabic.apk +SHA1-Digest: w5a6xDXfLyFiXZSmQWDfsLf2tlM= + +Name: system/usr/srec/en-US/hmmsyms +SHA1-Digest: 91T/MhByCAfKs+vOQQiZsYXNWsM= + +Name: system/usr/keychars/Generic.kcm +SHA1-Digest: OIjK3iqPcTGY5f9GOefCLwVUTSo= + +Name: system/lib/libawDTCP.so +SHA1-Digest: ePlt7ugg+bAyp32M3X/eqRcJAew= + +Name: system/framework/framework-res.apk +SHA1-Digest: 0kleShctAfGcGP8cB/iakD3qqZE= + +Name: system/etc/tfa/voip.eq +SHA1-Digest: akzJZd8ilz4aAsWHG6uC3H5L+tk= + +Name: system/fonts/HTCHand.ttf +SHA1-Digest: 7n7FxCJtne87cdOvZgS11BHxFoA= + +Name: system/media/audio/ringtones/Chrome.mp3 +SHA1-Digest: PpJnx3JqMdGsUpnePXxYnSZRKSU= + +Name: system/framework/javax.obex.jar +SHA1-Digest: s8baZXkZ8fbuhdIDTM1k0tkVHXk= + +Name: system/lib/libicui18n.so +SHA1-Digest: N13+lhhqDCxc/yXtBQdxCHoIFaw= + +Name: system/lib/libmmcamera_interface2.so +SHA1-Digest: Hx5y2BMF1NoySn3BWaBW17WpCic= + +Name: system/etc/security/cacerts/e8651083.0 +SHA1-Digest: WgJxTbOn+kJyfUYGkHMdssJ14+4= + +Name: system/etc/ar0260_1 +SHA1-Digest: P8BRHTNEk4ZkOWaSvNi1nLT3aiM= + +Name: system/customize/resource/allapplication_234.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/bin/dnsmasq +SHA1-Digest: tAuBH1Pthk5Qsjn28X1kaR8o+b8= + +Name: system/lib/libglib.so +SHA1-Digest: Z6jH5i1N9Wfk6pT5FkXjwiqvsnY= + +Name: system/etc/firmware/ILP0100_IPM_Data_out.bin +SHA1-Digest: Lv1yzkNB68uxzCvj1audhYdjB7c= + +Name: system/etc/security/cacerts/aaa45464.0 +SHA1-Digest: hPmjRDs4R8Z0AstXNTrfuQx92jQ= + +Name: system/etc/security/cacerts/613f892a.0 +SHA1-Digest: Vtbly9XYW23L/7ACZufcLj3bvFw= + +Name: additions/fonts/roboto/Roboto-Italic.ttf +SHA1-Digest: UoLSclAdePMifNNIYtx6LAHL9Us= + +Name: system/bin/mm-venc-omx-test720p +SHA1-Digest: F3Hy/4M466IKOAO0m5nIKfBmaqU= + +Name: system/bin/content +SHA1-Digest: 6POL0bmUWZQ4ZznC7yaw+OKUcs0= + +Name: system/lib/libFFTEm.so +SHA1-Digest: OFM8rnycbA1w5W8A/YzpMRAeuw4= + +Name: system/bin/date +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/lib/hw/sensors.m7.so +SHA1-Digest: IA+bUAEzAIIlwjxwZeZHfdXSwNs= + +Name: system/usr/keylayout/Vendor_05ac_Product_0239.kl +SHA1-Digest: 0R+he6vcnn7eY/jqIcFaCiCK7rE= + +Name: system/bin/mm-video-driver-test +SHA1-Digest: fQ1YbIvgPHX2WMWh1LV9fmmXn5Q= + +Name: system/app/Usage.apk +SHA1-Digest: Diw8nDozHr6CSfXUiZV2vvvIZ/I= + +Name: system/lib/libsc-a3xx.so +SHA1-Digest: zKqvJBWcrnsgX+70n9v4zje73go= + +Name: META-INF/com/google/android/aroma/scripts/save.sh +SHA1-Digest: GTL6976QW8zlzkaNNd/ezvASMz0= + +Name: additions/fonts/klavika/Roboto-Regular.ttf +SHA1-Digest: WHIxRNJuAltbRkdU7rHB9nQ2AfQ= + +Name: system/bin/mm-pp-daemon +SHA1-Digest: 7AG+TpFZseIuZbHPBlr6uagrgNU= + +Name: system/fonts/DroidSansEthiopic-Regular.ttf +SHA1-Digest: iFu88W2tFX67p/lLUPlONycOIdU= + +Name: system/framework/core-junit.jar +SHA1-Digest: DFWeZOPPVB3iHxLEVZTR4i70w2c= + +Name: additions/fonts/segoewp/Roboto-Bold.ttf +SHA1-Digest: pwKJLD+hi6FeGBMj1lkCD/AU7lU= + +Name: system/lib/libhtccamera.so +SHA1-Digest: sSvxUY+aqECkCvbl2tkwHOI/iQc= + +Name: system/usr/srec/en-US/endpointer_dictation.config +SHA1-Digest: +WnICju2l/yud03mhNLtzPFtppY= + +Name: system/media/weather/weather_thunderstorm_day.mp4 +SHA1-Digest: nDyReD5EeGwIMVHxh9IqlA5Y/5o= + +Name: system/lib/libvideochat_stabilize.so +SHA1-Digest: 51zUOY6tjmgc4biG/R8+WTwQvgc= + +Name: additions/gps/south_america/etc/gps.conf +SHA1-Digest: lWgC/Z1PboORJ+qeZ1NYXFWATnQ= + +Name: system/lib/libmode10GLES20.so +SHA1-Digest: CCSwoltPLHCrYA1t4YeLPu6uG+o= + +Name: system/media/audio/alarms/Celedon.mp3 +SHA1-Digest: 0VKOTOh45ctwqNCVTdcXpRpbZTA= + +Name: system/app/HtcDialer.apk +SHA1-Digest: 1s5oTJBj3XEtcnE+33YPBNXJxDs= + +Name: system/lib/libchromatix_ar0260_zsl.so +SHA1-Digest: Kj0VI+A2GccEu7Ot+KlnmVG4jzI= + +Name: system/tts/lang_pico/it-IT_ta.bin +SHA1-Digest: HKQqkLPKlZzLKMjUtrSHc56oLsw= + +Name: system/bin/newfs_msdos +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: additions/fonts/sonysketchef/Roboto-Bold.ttf +SHA1-Digest: V2q2Mh+gmO4mB5vcclK6VQjb8H4= + +Name: data/app/com.google.android.gm-1.apk +SHA1-Digest: 81MvNoL8PoyiE4PPRKmC+DI1MHE= + +Name: system/media/GPU/twoToneMaskH.bmp +SHA1-Digest: xju58t119afsTQgOLGLjXJZylb0= + +Name: system/app/Prism_AppUpdate_DummpPackage.apk +SHA1-Digest: Rxu4Y3ItKiJyWNrnK60Scz9C1Fo= + +Name: system/lib/libWVphoneAPI.so +SHA1-Digest: tfhAPiVo+Fp/al91zrUzmbiij8k= + +Name: system/etc/security/cacerts/aeb67534.0 +SHA1-Digest: 3niKiQPKP7O/zD2IkVJZqxha7s4= + +Name: system/etc/permissions/android.hardware.sensor.light.xml +SHA1-Digest: o5fC0OmTC1XhEfP9A5C41jbAt2w= + +Name: system/lib/libchromatix_ov5693_preview.so +SHA1-Digest: +8YZGzQVSveOyAbb5SQhsJ2o9kM= + +Name: system/app/HtcMusicEnhancer.apk +SHA1-Digest: xdbz9gXDS+ZCJmlQSv86O2+Erl8= + +Name: system/lib/libmmmpo.so +SHA1-Digest: TKcwQmWeuJc3Kc87mXLSOgT5MNc= + +Name: system/media/audio/ringtones/Silver.mp3 +SHA1-Digest: rsdVdsQredwmS1AzA+da++X+GEo= + +Name: system/lib/libqmiservices.so +SHA1-Digest: gwZhzMTCWF31takbrlaBx5OVVo0= + +Name: system/etc/tfa/playbackbeats_l.preset +SHA1-Digest: JYWGCVyXl3c9Rz9ndzK8oEuGmqk= + +Name: system/lib/drm/libhtcomaplugin.so +SHA1-Digest: m3mZnETp7k9G66LiTlx15cDwcf8= + +Name: system/lib/libimage-jpeg-dec-omx-comp.so +SHA1-Digest: ICZzQfoGovmXQVvoU+6CJhPXqvc= + +Name: system/media/audio/notifications/Pine.mp3 +SHA1-Digest: lB/YaqhyHoimiswvkhxOIyI7ZXo= + +Name: system/lib/libdmt_native_utils.so +SHA1-Digest: 6P8SpdE1r3CXHT90RYbtDgjW3pg= + +Name: system/app/IMEXT9German.apk +SHA1-Digest: vlK9sDi4HA/dC8RhAySMFLAMyiE= + +Name: system/etc/security/cacerts/ed62f4e3.0 +SHA1-Digest: /rUe4P3d/iSrFrAVuxlri5RIGWo= + +Name: system/bin/uiautomator +SHA1-Digest: 4tR5BSwIaFPIGk76lJrXZYZ2P28= + +Name: system/bin/mm-video-encdrv-test +SHA1-Digest: TaZdZhFUK7SI3fzuaA2wiBiRyyU= + +Name: system/media/audio/ringtones/Plum.mp3 +SHA1-Digest: X23ZUi3Pg5VrHwwCJUsKDfw9wtE= + +Name: system/bin/chown +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/app/MusicVisualization.apk +SHA1-Digest: b3jB/4niU3X544HwSfdSRvChu0Y= + +Name: system/etc/tfa/tfa9887.patch +SHA1-Digest: Kd02luAPrgU9ys9kn6jt3QLZdqk= + +Name: system/etc/security/cacerts/f61bff45.0 +SHA1-Digest: d3A25cK0u8CKtQwP0QHb01XjqXU= + +Name: system/app/HtcLocationService.apk +SHA1-Digest: fDETx6ISrFcOIYGCy7TIIzavPVs= + +Name: system/fonts/RobotoCondensed-BoldItalic.ttf +SHA1-Digest: urWUX1xs52/IukAulDtzt91OkPo= + +Name: system/etc/image_ibeats_v2_2vol.bin +SHA1-Digest: pTIJmH3i3zx9ELCVq8H8g/upAv0= + +Name: system/lib/libC2D2.so +SHA1-Digest: KHveEZGGzHmMzvupGBxt0a8KKB4= + +Name: system/lib/libhtcirinterface_jni.so +SHA1-Digest: wXD+k1OlJW7ac1k9gT6zhpFv1zU= + +Name: system/customize/resource/quicklaunch_23210.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/media/audio/alarms/Beige.mp3 +SHA1-Digest: 2lQr/z0TwvIPi0RBW1XzRjokBhU= + +Name: system/app/HtcCarGps.apk +SHA1-Digest: gpbW3q1Q9ml6qpc9ZgFGkXLD3jM= + +Name: system/etc/image_ibeats_solo_v2.bin +SHA1-Digest: UotezM2rsyllTt3c8Yc/R1IIcW8= + +Name: system/lib/libOmxMux.so +SHA1-Digest: Shn5kMCnrsikB4N8xL83jZ6M4y4= + +Name: system/bin/sensorservice +SHA1-Digest: LP7Ov/1BSwY9eXtP43YERlNwX18= + +Name: system/fonts/DFHEIA5A.ttf +SHA1-Digest: nKbBSUH3LiqZ+hEfHZywHJJA1Rk= + +Name: system/usr/share/partials/partials.dat +SHA1-Digest: yMWni8PMW+loCQCK8J9i1xN7MMM= + +Name: system/usr/keylayout/Vendor_046d_Product_c294.kl +SHA1-Digest: n8G5GZJh3RRh04UYBCiVlEHimDU= + +Name: system/media/audio/ringtones/Snow.mp3 +SHA1-Digest: HGW+EDMikVmz2AhN/XfEtOztsCo= + +Name: system/lib/libstagefright_soft_h264enc.so +SHA1-Digest: fIDI8QtWGgP+oYuhz8/X54hfb7Y= + +Name: system/etc/init.goldfish.sh +SHA1-Digest: oVAMzXnCy588jqkgurss/oczzDA= + +Name: additions/gps/north_america/etc/gps.conf +SHA1-Digest: 68asJMwdPHiBQYzs8QMvJ+ac+90= + +Name: system/app/Weather.apk +SHA1-Digest: 7Ug5iu81KE4Im8imK4PwJSJOLCQ= + +Name: system/lib/libchromatix_imx135_default_video.so +SHA1-Digest: oitRbpklaND3p9QI7y2cNVG2Ge8= + +Name: system/lib/libthread_db.so +SHA1-Digest: HrDOWUiApB5sexO54NCcCVdixOI= + +Name: META-INF/com/google/android/aroma/themes/sense/button_press.9.pn + g +SHA1-Digest: kcHcD4rK2BxI7gl+rIx8czWi+QA= + +Name: system/bin/vdc +SHA1-Digest: mQih+J8qbeXVAKrOOeDQqnfVBJg= + +Name: system/lib/libpagecurl.so +SHA1-Digest: De2IEUdsaixmdJLjRRx+o+N1Y6Y= + +Name: system/bin/qmiproxy +SHA1-Digest: 76GuJCvplRx3y01VsNeOpBgCtlo= + +Name: system/bin/getprop +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/fonts/Roboto-BoldItalic.ttf +SHA1-Digest: VYDbVJTNb2eL1eOY4SYWXg+P4PE= + +Name: system/etc/security/cacerts/f4996e82.0 +SHA1-Digest: e7OjBFQ1iru2cH13tni5XjfcfHw= + +Name: system/usr/srec/config/en.us/grammars/phone_type_choice.g2g +SHA1-Digest: Z3YKR+VbcDEuAiO5Qd2G4wsvIVg= + +Name: system/fonts/Roboto-Light.ttf +SHA1-Digest: +RPUxNPpLsZ8LSXfUkfgctYerrA= + +Name: system/media/audio/alarms/Twilight.mp3 +SHA1-Digest: 3Aeiy0/h9X4juVjXW5vYwa2wecU= + +Name: system/app/Calculator.apk +SHA1-Digest: KlsSdXKxTRL+vUtpG/oJffhOpOk= + +Name: additions/gps/south_africa/etc/gps.conf +SHA1-Digest: shrruXhq5DGjgROrCyv1OYb3J98= + +Name: system/lib/libchromatix_s5k3h2yx_zsl.so +SHA1-Digest: +SQpws0S6M6dmSUNR9hgZ5vXkuI= + +Name: system/media/audio/notifications/Jasmine.mp3 +SHA1-Digest: iB1oqrWQYHW9fXRULid+igsnZ40= + +Name: system/usr/keylayout/Vendor_046d_Product_c216.kl +SHA1-Digest: l5FztcNn+7EF/aXwMPgibvC1XXE= + +Name: system/lib/libloc_eng.so +SHA1-Digest: jtWTjPyeN8EoIQdTk0N/1apnxiI= + +Name: system/lib/libzeroeditor_jni.so +SHA1-Digest: xZCpggShFY5Xsf+hLAtYEWkl8zI= + +Name: system/lib/libmmjps.so +SHA1-Digest: CEvRYbjxzkD6BlngVUpiHgpAADk= + +Name: system/etc/tfa/video_l.config +SHA1-Digest: mcDPznDmbQbzvQ1yOzfS3mAX2n0= + +Name: system/media/audio/ringtones/Ao.mp3 +SHA1-Digest: 1u/NxiCTgu2gfUzpZie3XUiJnqE= + +Name: system/etc/tfa/playback_l.eq +SHA1-Digest: vq86JS6uyWcHNWiP3yEKg+8JCXQ= + +Name: system/fonts/Roboto-Italic.ttf +SHA1-Digest: UoLSclAdePMifNNIYtx6LAHL9Us= + +Name: system/media/audio/ringtones/Icterine.mp3 +SHA1-Digest: aP5LEa6FdDKVoC+5LBv8boAg6Nw= + +Name: system/lib/libbcinfo.so +SHA1-Digest: rw3LNo82QqZaegTX3uukZXyWUXc= + +Name: system/lib/libnfc_ndef.so +SHA1-Digest: fmd7R7lF53tuY5rxJb4gFJk0+Jo= + +Name: system/bin/notify +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/customize/resource/quicklaunch_420.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/customize/resource/quicklaunch_21404.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/etc/tfa/ring_l.preset +SHA1-Digest: NDpQDq6Ee/6Q/YEhmqXfFGXPVP0= + +Name: system/lib/libmmosal.so +SHA1-Digest: 4YD6JeWoVqE8VllWp9scJhfo+a4= + +Name: system/etc/tfa/playback_l.preset +SHA1-Digest: 95X1TUPDgbbUrIKwgfEXGc069HQ= + +Name: system/framework/com.orange.authentication.simcard.jar +SHA1-Digest: ypu7QN97yd7a3xcfDRjHAkSoZVE= + +Name: system/media/GPU/dot_mask_0.bmp +SHA1-Digest: sAn8AkmRls6yJuJQujf9oJ3xCDg= + +Name: system/app/IMEXT9Serbian.apk +SHA1-Digest: jje8OmPaSXek4FjZ2mDeO2n3G1M= + +Name: system/etc/security/cacerts/74c26bd0.0 +SHA1-Digest: OaKWMuPk9pCf4isRHaBDfJj//V4= + +Name: system/lib/libalsa-intf.so +SHA1-Digest: gb16Mfb5qAMe5btW+LIWxONUELM= + +Name: system/customize/resource/icon_launcher_mail.png +SHA1-Digest: FRf1YnrwgMhqMxSGrzcr4JUAs/U= + +Name: system/lib/libOmxVenc.so +SHA1-Digest: WXYRSL/LBhCv4BNRybuxIfjGgnE= + +Name: system/bin/rtspclient +SHA1-Digest: qG0rGkomB0b7fN6ku2nwLLKrLlQ= + +Name: system/framework/com.playstation.playstationcertified.jar +SHA1-Digest: xMAftjL+VhmkF4bAF++wCGmeUMY= + +Name: system/fonts/Lohit-Kannada.ttf +SHA1-Digest: e+cag/VBf8+7uop4vUTQbpk22qE= + +Name: system/usr/keylayout/synaptics-rmi-touchscreen.kl +SHA1-Digest: IQcIzYOfqpGYPTRy0AtLk1vMfz8= + +Name: system/lib/libutils.so +SHA1-Digest: Gqf+CCM9+BIY9C/tolknwYxI/3g= + +Name: system/lib/libc2d2_a3xx.so +SHA1-Digest: s4rpme3VwG5ISEgOxxYVlwdwya4= + +Name: system/etc/tfa/video_l.preset +SHA1-Digest: gLyUQwAim17CsSVazvxBjmG77tQ= + +Name: system/xbin/dexdump +SHA1-Digest: J1YamenP4hAHBZs/PqaU1OclGho= + +Name: META-INF/com/google/android/aroma/icons/apps.png +SHA1-Digest: PfvyF/zQeOBuTVbIBl7Wb+TonE0= + +Name: system/app/MediaUploader.apk +SHA1-Digest: Jb8yqCvQBeX5XIO3PgSW6xJtywQ= + +Name: system/etc/security/cacerts/a2df7ad7.0 +SHA1-Digest: +xwpSUIGj8RMEb/Xl28K69HmZLc= + +Name: system/app/IMEXT9BahasaIndonesia.apk +SHA1-Digest: 7XjJ2jR+pov9G8l1M5eAD3GAvp4= + +Name: system/media/weather/weather_hot.mp4 +SHA1-Digest: TY/GwOH3Gw3gZUDIctB7BYTZyGA= + +Name: additions/camera_4.2/lib/libjni_mosaic.so +SHA1-Digest: M1/kJbLfeKPWydQnYPUkw5cwJ1M= + +Name: system/app/GenieWidget.apk +SHA1-Digest: XiTzeRUija4ISyy5l0cWYgRkpZ4= + +Name: system/usr/share/partials/partials_A_bb.csv +SHA1-Digest: Eh6+/JGzpbNSY9dIETqiXqU7MnA= + +Name: system/etc/security/cacerts/a7605362.0 +SHA1-Digest: ydDNX6E+RFIn8R4w9i4iJXOLoOE= + +Name: META-INF/com/google/android/aroma/icons/install.png +SHA1-Digest: 4jQwvaI7rzIWej0OwJJDRtr9hF4= + +Name: system/etc/security/cacerts/56b8a0b6.0 +SHA1-Digest: LSyf6A501o2tD7CKNauSUSoXSJU= + +Name: system/customize/resource/icon_launcher_hotmail.png +SHA1-Digest: +lvjvcq+1MsKzD688ACzHYGgdVw= + +Name: data/app/com.google.android.youtube-1.apk +SHA1-Digest: Y3H/kZRzccAkgJz+iXvnGcHGopE= + +Name: system/lib/addict.dat +SHA1-Digest: 4H0zWmhejpZ0NeoBB8Yz2wU3l+s= + +Name: system/lib/libnativedocviewer.so +SHA1-Digest: 6C2cEHlgQLTxsRCy6v0D0hb1sHk= + +Name: system/media/GPU/CurveSepia.bmp +SHA1-Digest: 30cjruI5GORG96DTq3dcz4kz5N0= + +Name: system/bin/netsharing +SHA1-Digest: +gT5huWi3HJicH/vmF66HGqsjkI= + +Name: system/app/Phone.apk +SHA1-Digest: G3DpCJnghYXgbvQDE8fGXmvit5c= + +Name: system/media/zchgd/charging_04.rle +SHA1-Digest: S48C90ViaLLTNuLvRQ95MBU8/DM= + +Name: system/lib/libchromatix_ov8838_zsl.so +SHA1-Digest: nHmo57hQE6HG9CzAH3E143TnoRo= + +Name: system/app/PureC_ApplicationsProvider.apk +SHA1-Digest: SJR7EfyX8nt+XAR1YQh2uIZzuKY= + +Name: additions/fonts/ubuntu/Roboto-Regular.ttf +SHA1-Digest: Do4jwIp9qHyjkFfqU311iWT/7AA= + +Name: META-INF/com/google/android/aroma/requirements.txt +SHA1-Digest: k8MUSCbWtXAMQbYGt3LxYu0bQjU= + +Name: system/lib/libbluedroid.so +SHA1-Digest: 3xcNyw7TezSyQj117g75VhAswMo= + +Name: system/customize/resource/allapplication_21408.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/fonts/DroidSansMono.ttf +SHA1-Digest: Ez+2zybqBztFb7VXuUzoxGFDsRc= + +Name: system/framework/android.policy.jar +SHA1-Digest: 7SA6H6NljMdWNExBiEz0hZQPqPk= + +Name: system/lib/libHTC_DIS.so +SHA1-Digest: lnTwhSl3Y9yhbZ4qSk0UftW5MIU= + +Name: system/customize/resource/quicklaunch_21407.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: META-INF/com/google/android/aroma/themes/sense/button_focus.9.pn + g +SHA1-Digest: qedWodmyPtpvTVBa5oh+kEhfRbs= + +Name: system/etc/security/cacerts/7a481e66.0 +SHA1-Digest: SA1ZMXDrMT0bFLrkIXeyPdSCldI= + +Name: system/lib/libdsi_netctrl.so +SHA1-Digest: t05ojITUQ+wNBDOx3i0rOE+SRUY= + +Name: system/media/GPU/dot_mask.bmp +SHA1-Digest: oSDtm4iAj/b5A9SIk+P0x2UfXtg= + +Name: system/lib/libnotesprovider_jni.so +SHA1-Digest: Wdh/Z80JsK4h9sL2kJMYChtA5KY= + +Name: system/app/IMEXT9Danish.apk +SHA1-Digest: oJkcExcRgVQNm2Ms+voRd0HKhIQ= + +Name: system/etc/security/cacerts/5a3f0ff8.0 +SHA1-Digest: D5NgyenT/uE9GAWVJqapSAwCRC4= + +Name: system/app/WifiRouter.apk +SHA1-Digest: vdqnawB107cfDoetLpwu7HvXzr4= + +Name: system/media/audio/ui/KeypressStandard.ogg +SHA1-Digest: WFdYi785ujyp6JwqtdsHziO5hjU= + +Name: additions/fonts/ubuntu/Roboto-Bold.ttf +SHA1-Digest: rq3ZO1oCm8CTnanH/Zf3LyO18RU= + +Name: system/app/IMEXT9Slovak.apk +SHA1-Digest: z7H/60ekio9IWMtchLXF8NidDUY= + +Name: system/lib/libeffects.so +SHA1-Digest: IiD7VBTNo5oQcby43dxSM/GIsvU= + +Name: system/lib/libGLESv1_CM.so +SHA1-Digest: 7Ux4NBloMYNsc9A3RSmgJ4wvqRw= + +Name: system/etc/security/cacerts/4d654d1d.0 +SHA1-Digest: toWvfEMJLsSRpeuXhuMMajO/iiQ= + +Name: system/etc/security/cacerts/e48193cf.0 +SHA1-Digest: 4QUQZs0nSjATJqFpt84dfehXF/4= + +Name: system/lib/libmmcamera_image_stab.so +SHA1-Digest: ua0+bnV6OjIk35IDohjjR4qi004= + +Name: system/lib/libchromium_net.so +SHA1-Digest: zpFCCxPptH74gTVfpK3EiSp1ciQ= + +Name: system/lib/libdrmframework_jni.so +SHA1-Digest: IB4FoyJzXHpn2s6YPwBG2NZWbgA= + +Name: system/customize/resource/allapplication_27205.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/lib/egl/libGLESv2S3D_adreno200.so +SHA1-Digest: me8zPb/3KzQIbERPMpeCaBWU2Q8= + +Name: system/media/zchgd/error.rle +SHA1-Digest: BWaADBe8pcLSYBl4fA+034BcA4I= + +Name: system/lib/libchromatix_ov2722_zsl.so +SHA1-Digest: OmYn5YzcMGrQxXVwIY88uqwrR20= + +Name: system/fonts/Roboto-LightItalic.ttf +SHA1-Digest: Q0C/Q8zT4VcjEgGFGwTtWOhdW3k= + +Name: system/lib/modules/qcedev.ko +SHA1-Digest: ckYKOnlf1lFgPaNCn0eT6PzIO0k= + +Name: system/app/Automotive_InternetRadio.apk +SHA1-Digest: b8D1sIoaSgitqbfJ3pTKpbIT5FA= + +Name: system/app/FlexNet.apk +SHA1-Digest: U0ffGHuHwClWke+w5pnNOwZF9FY= + +Name: additions/fonts/sonysketchef/Roboto-BoldItalic.ttf +SHA1-Digest: uFf98lNK2CuS0rghoIYKfwBCTD4= + +Name: system/usr/share/partials/partials_A_gr.csv +SHA1-Digest: AKIkzhOqfcSzrb1K1jTWWZCy/rQ= + +Name: system/etc/permissions/android.hardware.telephony.gsm.xml +SHA1-Digest: nvdtSduykpjyEj1aCRzJQBwuh+c= + +Name: system/customize/resource/wallpapers_b_03.jpg +SHA1-Digest: LKBoWw7+/vMvJI/uGxBb7A6SpjA= + +Name: META-INF/com/google/android/aroma/ttf/Roboto-Regular.ttf +SHA1-Digest: aXrRiEJkMD14GvrKNCxOpkbt7nc= + +Name: system/etc/firmware/lscbuffer_rev2.bin +SHA1-Digest: L9bFwDw2ScJ5H98TwtvdmmBQqCw= + +Name: system/media/audio/alarms/Chartreuse.mp3 +SHA1-Digest: I9UvkhacKlrDRk+aUbXtXQ3TgfI= + +Name: system/framework/HTCCommonctrl.jar +SHA1-Digest: krx6jdVzi95nVakzqrEBSRmjjmU= + +Name: system/etc/searchabledb.conf +SHA1-Digest: ZCh6WPvzRQaMaft6m7p6ixkNXlM= + +Name: system/app/LinkedIn_Fsplugin.apk +SHA1-Digest: BTPYpsGjdi7CuybVYZ+AJf9lzNg= + +Name: system/media/weather/weather_snow_night.mp4 +SHA1-Digest: Np6FCe3cWe2ybFjMfl2G5C6EasM= + +Name: META-INF/com/google/android/aroma/icons/default.png +SHA1-Digest: 75xqsrZegulFIjheicul/9p3vDI= + +Name: system/media/weather/weather_l_snow_night.mp4 +SHA1-Digest: +SAY1uuWIU2aGoJEi2rrrmDl6e8= + +Name: system/media/audio/ui/Volume-3.flac +SHA1-Digest: J4P4GrN6UbJeBFR0ob5ZRc/IZvs= + +Name: system/etc/security/cacerts/ab5346f4.0 +SHA1-Digest: sSqWJJT/XZpH/LXyVH22pHuXL3I= + +Name: system/customize/resource/quicklaunch_26003.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/etc/security/cacerts/c215bc69.0 +SHA1-Digest: quX/iNXdfSEwfOpAJ7UjjBlmlo8= + +Name: system/etc/security/cacerts/6fcc125d.0 +SHA1-Digest: gD/RtuZNrRkHd/Kf7B4e3urcpfs= + +Name: system/lib/libNewTimeBreakin.so +SHA1-Digest: ZEFVmAyvprl9LwNlSoZTe5gtdjo= + +Name: system/app/IMEHWRPenPower.apk +SHA1-Digest: h92ywSRdXWZoWbFiP/1aiYUxoec= + +Name: system/lib/libcamera_client.so +SHA1-Digest: xSnZAJZUGGG6iAJiCzvnDwE3EiI= + +Name: system/media/audio/notifications/Peach.mp3 +SHA1-Digest: ymL1P1ksEjti5eQuiwCumhNXcYI= + +Name: system/etc/bluetooth/network.conf +SHA1-Digest: nu2dYktiZ0gI1G/0bmJQ0vG9GTw= + +Name: system/bin/bootanimation +SHA1-Digest: 24Yb1yQTf6X2uc//DRN5zwN1L7A= + +Name: system/etc/security/cacerts/7d3cd826.0 +SHA1-Digest: L/MwBTuZjUtda8j0poy4nGz3j+I= + +Name: system/app/HTCSetupWizard.apk +SHA1-Digest: BqzbMxAKUhfljqRnxx9j3ECZLmc= + +Name: system/lib/modules/reset_modem.ko +SHA1-Digest: N/sGiNea7wgZSkyBy9v8LTlA4MY= + +Name: system/customize/resource/wallpapers_a_06.jpg +SHA1-Digest: 5LdlMFoT9UnuzvwhAcOYbMhhcZY= + +Name: system/lib/libnetlink.so +SHA1-Digest: J3yzDrTFSoJhM5U3UPLsnjQsQeo= + +Name: system/media/audio/ringtones/Aero.mp3 +SHA1-Digest: h9R+AZZXjJ55zkS/xD/hbPiNhW4= + +Name: system/lib/libwfdsm.so +SHA1-Digest: 2LBzWvL/z1Xk71ZXtDD9Az2LW1w= + +Name: system/framework/com.android.location.provider.jar +SHA1-Digest: kgxRjEPXNXaB02KQnU9/gwpSrr0= + +Name: system/bin/flash_camera +SHA1-Digest: /YWptCbuJQYnQsnaCrMLgA8rYLA= + +Name: system/usr/srec/config/en.us/dictionary/basic.ok +SHA1-Digest: /nwZFjqTU6CKLzpmEnxPxb7aqks= + +Name: system/media/audio/ui/VideoRecord.ogg +SHA1-Digest: lNxenUZXTJQfFT2OxJHkWx8URbg= + +Name: system/etc/firmware/tzapps.mdt +SHA1-Digest: Iwf+i6zrBITqZaRImyM0+Aig/U4= + +Name: system/bin/screencap +SHA1-Digest: QwcRhuq+uie8NIklTk18DcTWF+U= + +Name: system/customize/resource/allapplication_24007.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/lib/libalmashot-clr.so +SHA1-Digest: 7P4/bNoos1tk+eAaug6AJ9tDFys= + +Name: system/bin/radvd +SHA1-Digest: M9C8/hBXLoy5zlkjDZqLwEVmDKA= + +Name: additions/fonts/asap/Roboto-Bold.ttf +SHA1-Digest: 3Rm+5MW1h8ODs0v/Lf1r+/eOzqg= + +Name: system/app/HTCSyncManager.apk +SHA1-Digest: JL1ux00jOd3R21gBAn2ZSFecc7w= + +Name: system/etc/security/cacerts/594f1775.0 +SHA1-Digest: rB1X3r8ms6gP9FsYn8TKeNfNeFg= + +Name: system/usr/srec/en-US/clg +SHA1-Digest: i9WVIl/L+yb/jaO4rLxhQP7k/wg= + +Name: system/bin/bridgemgrd +SHA1-Digest: RPDKnxjmMu/EVkw6CUM/z//Lbwk= + +Name: system/app/Idlescreen_Base.apk +SHA1-Digest: TyrclWrz82Koe5QloTyYL0A8bqo= + +Name: system/etc/security/cacerts/2fa87019.0 +SHA1-Digest: PB53+gvlezFU7Jj+8YJ0mh+UzAM= + +Name: system/etc/event-log-tags +SHA1-Digest: xA1plne+LBYz1eFKlWoxMYS0HfA= + +Name: system/etc/thermald.conf +SHA1-Digest: x+qoOykK3A9D753DjqDTgaJ5N3o= + +Name: system/etc/calibration +SHA1-Digest: lTV0aszMLrptXcobTj5m3kE6Jzk= + +Name: system/bin/mm-qcamera-testsuite-client +SHA1-Digest: zwlAtEkAs2epwVMh4jH3xV+OIg0= + +Name: system/app/IMEXT9Greek.apk +SHA1-Digest: 49ATrOz6yUAEu8KwMYPkEFlKD18= + +Name: system/fonts/DroidNaskh-Regular-SystemUI.ttf +SHA1-Digest: /YLqFkhUkwWAbuSlqkVAGnVHze0= + +Name: system/xbin/busybox +SHA1-Digest: /xCDxHWWoisUg/jBaID9qpaxuf4= + +Name: system/usr/keylayout/Vendor_22b8_Product_093d.kl +SHA1-Digest: SNU5mBeA6Kxhy0czF4BOLpoOan8= + +Name: system/lib/libchromatix_ov2722_preview.so +SHA1-Digest: B9JZ/szR02JnV1moLRx6RzD4uVs= + +Name: system/app/Twitter.apk +SHA1-Digest: 5ymRIXvO2rcAi7re+9AVzVOHKWg= + +Name: system/etc/permissions/android.hardware.sensor.compass.xml +SHA1-Digest: 5lFtWpy4NCGP+VUxJOxCJ6wvNcs= + +Name: system/bin/mm-jpeg-enc-test +SHA1-Digest: xeDii/rfIiQ5Aqzdd/MlgeNwaTA= + +Name: system/usr/srec/config/en.us/models/generic8_f.swimdl +SHA1-Digest: GgnYWcIdaKmXR6fAvPMIhiEu1Wo= + +Name: system/lib/libqmi_cci.so +SHA1-Digest: GDQLrVqk6JlyFKeQEvZdaAPDOhs= + +Name: system/etc/security/cacerts/fac084d7.0 +SHA1-Digest: JrK7FVoKOO/8bvPLla8wo5xTToE= + +Name: system/customize/resource/icon_launcher_gmail.png +SHA1-Digest: 5kiKKBaBFTSP1WJqOWpUxaW5btk= + +Name: system/bin/usbhub +SHA1-Digest: vE6JfRSIlqRRaEE+ezhzdWfzOV0= + +Name: system/bin/vold +SHA1-Digest: CsOzGuP6l38w+9hFA3EnBm8g4A8= + +Name: system/usr/keylayout/projector-Keypad.kl +SHA1-Digest: gx7IMdEqFXd9j8P4kPbXmTfw/EA= + +Name: system/app/Watch.apk +SHA1-Digest: Tke36FZGf5fkqEsWMWJEVV/5YFE= + +Name: system/app/FaceLock.apk +SHA1-Digest: uUKqZkThdouzBu87kJMhWVvxfCs= + +Name: system/fonts/RobotoCondensed-Regular.ttf +SHA1-Digest: qY1rjMjPiMivTe+AYG+lleCOGYc= + +Name: system/usr/srec/en-US/google_hotword_clg +SHA1-Digest: k3aCqpXWQM5DIn7znzZjsU9SJ24= + +Name: system/media/audio/notifications/Almond.mp3 +SHA1-Digest: u5D+XxQySwPKM7pmnshOd2FK14s= + +Name: system/bin/ime +SHA1-Digest: tRT4xXnmwLMmpCiARGf1xmn/8K0= + +Name: system/media/weather/weather_l_clear.mp4 +SHA1-Digest: nEd35PcerVC7tCPhsERSgUGTceo= + +Name: system/media/audio/notifications/Teal.mp3 +SHA1-Digest: B1O5UU4hnW/9/d8yh9eJk0FFEHc= + +Name: system/etc/timezones.db +SHA1-Digest: 2f/R5IXEykAILEmJiuOJUUR1pnI= + +Name: system/usr/srec/en-US/embed_phone_nn_state_sym +SHA1-Digest: T8+zEXNoKbioXdyuELp0PzOMY3c= + +Name: system/usr/srec/config/en.us/models/generic8.lda +SHA1-Digest: /y/sXjBSqRQkFc848OCkAh9PhTE= + +Name: system/lib/libacdbloader.so +SHA1-Digest: gcDVxBVY8xWNQMUZ4BZs6EoJT9M= + +Name: system/app/Prism_AppUpdate_UpdatingScreen.apk +SHA1-Digest: Wxt0dFOS/VLVOpJL9mTUugO5UAc= + +Name: system/etc/security/cacerts/ed524cf5.0 +SHA1-Digest: yTN26RsNrb/CudFl/v0+xfETrU8= + +Name: system/customize/resource/quicklaunch_65510.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/etc/security/cacerts/9ec3a561.0 +SHA1-Digest: Ks4msL8rX99I9sph+SVRWp56LLw= + +Name: system/etc/security/cacerts/7999be0d.0 +SHA1-Digest: IsAGvSZ42ierGS9JE3DG/92df74= + +Name: system/lib/libchromatix_vd6869_night.so +SHA1-Digest: ju32fIoVrHY6g06KqcRBo4PKzO4= + +Name: system/app/MyPen.apk +SHA1-Digest: hQMmOqZJR1YphJVnYSdX56b08lM= + +Name: system/bin/DxDrmServerIpc +SHA1-Digest: B/khYap8U+IsHXo4eOeQUVSanOM= + +Name: system/lib/libkeystore_client.so +SHA1-Digest: gHZPh7PIN4pfyTol4+H0f8RkMIc= + +Name: system/lib/libgemini.so +SHA1-Digest: gOcIcvsHIy1bJWm5yhohGdlDbpc= + +Name: system/lib/libz.so +SHA1-Digest: RalaGOwZWuxB6e0enf5eK61HlGY= + +Name: system/bin/requestsync +SHA1-Digest: rYhU5wsWgx+19p9hyVYoPtrvMhQ= + +Name: system/etc/security/cacerts/111e6273.0 +SHA1-Digest: p+zFXiO2e0tv0nws8olvT8Aek/M= + +Name: system/lib/libcneapiclient.so +SHA1-Digest: QNV1EkKHUFtXhshGKIaG1KdV2Aw= + +Name: system/etc/cir.img +SHA1-Digest: Pv8H10C1z+OkuPHHrvyhWoDXHa4= + +Name: system/etc/security/cacerts/e60bf0c0.0 +SHA1-Digest: J9pHPWumPXu348/ay/6TIhWXEQE= + +Name: system/customize/resource/allapplication_20210.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/etc/tfa/recorder.config +SHA1-Digest: mcDPznDmbQbzvQ1yOzfS3mAX2n0= + +Name: system/etc/firmware/a300_pfp.fw +SHA1-Digest: iZ2/rUgSCElxz8H/MPBqS0XC00w= + +Name: system/media/GPU/twoToneMaskV.bmp +SHA1-Digest: qwqnegSS7y93ykkmEFdP7tHZtyM= + +Name: system/etc/security/cacerts/3ad48a91.0 +SHA1-Digest: fiM/NEifCut6APMA4lYBH+/tUUA= + +Name: system/bin/amix +SHA1-Digest: Lg4AgytLAT1XL4Quw5iGXn6xMzA= + +Name: system/media/weather/weather_l_rain_day.mp4 +SHA1-Digest: cSHTqHnmLVRhBBag4G8h4DbdqLM= + +Name: system/lib/libposteffect.so +SHA1-Digest: 5vfal77EdZb0zL1jlPLNvFnLXiU= + +Name: system/lib/libmpl.so +SHA1-Digest: +KnVDngG0CrNz9dw+RzM6ESoK5I= + +Name: system/etc/init.qcom.post_boot.sh +SHA1-Digest: Vxokp11pfAjDvLmIyoM2zDinMak= + +Name: additions/camera_4.2/app/GalleryGoogle.apk +SHA1-Digest: gt/HaSMaax3cwQru6AIYZeKqO0U= + +Name: system/etc/bluetooth/main.conf +SHA1-Digest: oKXWcTolFUhYL4eb8XNIXgyN6U0= + +Name: system/tts/lang_pico/fr-FR_nk0_sg.bin +SHA1-Digest: FJvhnnxrIuE3NSTkPFjQuepe1yM= + +Name: system/etc/security/cacerts/3c860d51.0 +SHA1-Digest: NEjSItc3RYcgBxmnDxIXD4Eqy28= + +Name: system/app/IMEXT9Polish.apk +SHA1-Digest: D0HDPAVrREjfPVIvMetnGFwDkM8= + +Name: system/bin/vmstat +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/lib/libemoji.so +SHA1-Digest: ro9Wy2cWrVaEF7WL/VsSImLw+eQ= + +Name: system/lib/libstagefright_soft_mpeg4dec.so +SHA1-Digest: 6m3nwfqE2lzAHywZd399wMqUqdE= + +Name: system/framework/framework-htc-res.apk +SHA1-Digest: cHhXGxL1Bit3kEGMReLkRKv9mZY= + +Name: system/app/SenseTV_Home.apk +SHA1-Digest: ZwkB+dw2a8USrWwDZrZinBq9mZI= + +Name: system/media/weather/weather_windy_day.mp4 +SHA1-Digest: ZLybKR1cVR2AjjduU4w8W03JdI4= + +Name: system/app/HtcAutoRotateWidget.apk +SHA1-Digest: nRZ6dYR58M1KJW7iIOlAs7Vh+wk= + +Name: system/lib/libwt6hpprndrv.so +SHA1-Digest: gs9ftbIQwJEvPSmL9OiGnAPfYWs= + +Name: system/media/audio/alarms/Rajah.mp3 +SHA1-Digest: q8fZq/jLjgh9NUgdj0p2EcI19Wg= + +Name: system/etc/PCTOOL.ISO +SHA1-Digest: 1WrLSM00uaSV+bli/JaER4GiHxk= + +Name: additions/fonts/ubuntu/Roboto-Italic.ttf +SHA1-Digest: 60VoOZG3a5twaesOqklAVrUI+0M= + +Name: system/app/Stock.apk +SHA1-Digest: rx/aMR9X65no6sz6Wo7oE8XACLs= + +Name: system/lib/libsystem_server.so +SHA1-Digest: /Im4WYgHrNYlzJYiUlvv7dALZHs= + +Name: system/etc/security/cacerts/9339512a.0 +SHA1-Digest: hsOnlnqeX401dhi0nNmDk65W+/4= + +Name: system/bin/charging +SHA1-Digest: 7Q3Uinh9xZxprO9bV24Y9CQfEpQ= + +Name: system/app/LMW.apk +SHA1-Digest: pOpNe/0BO1uawsc1QyxikRzZp50= + +Name: system/app/IdleScreen_Photo.apk +SHA1-Digest: Ede9u3EENvWWeoT+VZpUWOym1oE= + +Name: system/bin/racoon +SHA1-Digest: wVXHHRCSsQ869NYoXil5UeO9NLE= + +Name: system/etc/permissions/android.hardware.wifi.xml +SHA1-Digest: 2QUUSx+bDnRPeI0RKInztkPY0L8= + +Name: system/bin/netstat +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/usr/srec/en-US/g2p_fst +SHA1-Digest: 56BTKRSLceP1JQBIw26sU7rnRg8= + +Name: system/etc/security/cacerts/f80cc7f6.0 +SHA1-Digest: KIRiP3e2KnZuw1n5MOiP4r/DfXo= + +Name: system/customize/resource/allapplication_20810.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/app/GoogleCalendarSyncAdapter.apk +SHA1-Digest: LxmcE/37BL8GjgTkGPTeqtgK8j8= + +Name: system/etc/security/cacerts/69105f4f.0 +SHA1-Digest: +kWiVJ8jvMUCSABOD1q0wrmOwls= + +Name: system/etc/bluetooth/input.conf +SHA1-Digest: Tgwt4ltLhyMYLAEDfZMe0/GHQ8c= + +Name: system/etc/image_ibeats_solo_v2_2vol.bin +SHA1-Digest: Eoz94iefZEs4CIG3BXZhUHJe8WI= + +Name: system/lib/libwfduibcsrcinterface.so +SHA1-Digest: Tog4xhqnS/g2J9quFS8OzjcNjOI= + +Name: system/customize/resource/allapplication_23420.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/bin/lsmod +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/etc/security/cacerts/5cf9d536.0 +SHA1-Digest: TwWGlhUS/XyYTVbiXyDEu4yCHOk= + +Name: system/app/HoloSpiral.apk +SHA1-Digest: IUpd9tg3DlDsFiYOf7PajFQwl0s= + +Name: system/bin/reboot +SHA1-Digest: I8x9/T8IJUHst+9mTffQBrfKN7M= + +Name: system/lib/hw/audio.a2dp.default.so +SHA1-Digest: FDO/HUlaoEEXyLWt63JcGJ5udNM= + +Name: system/media/GPU/header8bpp.bmp +SHA1-Digest: VlMyBckc5chNrS2FChiEEZgZQ6Y= + +Name: system/etc/firmware/fw_bcm4335_b0.bin +SHA1-Digest: s8ujoESTcrSfW/Q17UP/DzlEQo8= + +Name: system/lib/libchromatix_s5k3h2yx_default_video.so +SHA1-Digest: xptMw90p6xZ2RzEtQAPHLcTN8mM= + +Name: system/lib/libstagefright_soft_vorbisdec.so +SHA1-Digest: W51bwn8wsBJwbuDL6joCynE7wdQ= + +Name: system/etc/tfa/voip_l.config +SHA1-Digest: HKUbwkwyeWNkWCWTnAgcEbOJbpQ= + +Name: system/lib/libchromatix_vd6869_zsl.so +SHA1-Digest: qWd+XgpNdHAFrnvMALbUN8XeK3I= + +Name: system/bin/htcfs +SHA1-Digest: VGSiL+tb6f3B8/ivAw5HYmejx3g= + +Name: system/vendor/pittpatt/models/detection/multi_pose_face_landmark + _detectors.7/left_eye-y0-yi45-p0-pi45-r0-ri20.lg_32/full_model.bin +SHA1-Digest: 2RO6gFG2Qc2bgM8YcmcjeX1ieuI= + +Name: system/etc/security/cacerts/fb126c6d.0 +SHA1-Digest: IWQN7rJtQQHN57H5dd6OTOg45Bw= + +Name: system/usr/srec/en-US/rescoring_lm +SHA1-Digest: 6GyGVA+P2g8W+DkDc/dPWTIDcmc= + +Name: system/customize/resource/allapplication_21403.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/customize/resource/allapplication_23806.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/etc/init.d/96Tweaks +SHA1-Digest: TG6FqP4J/ntSWhsMi7UbHvNu4TU= + +Name: system/etc/security/cacerts/ccb919f9.0 +SHA1-Digest: GrKodXYQ6yyhwcC2Aeon0asWWHI= + +Name: system/usr/srec/en-US/ep_acoustic_model +SHA1-Digest: 8PLUJrKu4KdJRfExvDQgyCW3w0I= + +Name: system/app/HtcGpsWidget.apk +SHA1-Digest: AnCbMYFFCqRFRbNXemf4va+/Et4= + +Name: system/etc/media_codecs.xml +SHA1-Digest: agzpZ6xk+1LUBBa36hVb4jmDDyY= + +Name: system/lib/libwfdmmsink.so +SHA1-Digest: CGU26anRhWWwYn0WjI9S7dfaNM0= + +Name: system/etc/tfa/voip.config +SHA1-Digest: HKUbwkwyeWNkWCWTnAgcEbOJbpQ= + +Name: system/lib/libui.so +SHA1-Digest: 5U4hil0vCG9HBfXWgCu221wqw0s= + +Name: system/etc/security/cacerts/19899da5.0 +SHA1-Digest: +UmV9YdO6tXmnuyAqdwmaQRUjag= + +Name: system/lib/libfrsdk.so +SHA1-Digest: zCAgqawgYyfceORBN6OdlzJInBI= + +Name: system/usr/share/partials/partials_CW_gb.csv +SHA1-Digest: 46+b7bjNw9xCRwVfWEiE8Mqc9DY= + +Name: system/etc/security/cacerts/bf64f35b.0 +SHA1-Digest: C9BPEBWg6QPfoVIADHUCxuXpPo0= + +Name: system/lib/libchromatix_ov2722_default_video.so +SHA1-Digest: 4Mi4hBE3vUoS6H+bRiuKwI8eWew= + +Name: system/lib/libOpenVG.so +SHA1-Digest: +Uwi23fBjZ/WXyYXHGpf6XbA6DA= + +Name: system/media/audio/alarms/Topaz.mp3 +SHA1-Digest: zCYU22lanMN0X9Q8U2lXEDHfej4= + +Name: system/lib/libmm-color-convertor.so +SHA1-Digest: EOBxEHhZUDgBEwwNoMughtDuXs4= + +Name: META-INF/com/google/android/aroma/themes/sense/select.9.png +SHA1-Digest: /S9wdSsjM2HOisLSogibe57BvD4= + +Name: system/etc/security/cacerts/ddc328ff.0 +SHA1-Digest: rQJV0QS5EjB+JDM0B2vSegD4f8c= + +Name: system/etc/hsml.key +SHA1-Digest: czCkPuRCXsueGicln2eH5xyAw3E= + +Name: system/lib/librtp_jni.so +SHA1-Digest: wOIppFTkyE7GJCxQKC/o+YQrf8I= + +Name: system/lib/egl/eglsubAndroid.so +SHA1-Digest: QNMdorgIk98JO9ln6ZZxeQVzhzg= + +Name: system/media/weather/weather_l_windy_night.mp4 +SHA1-Digest: Jdv//CAJ/HvFl6WXAUHqFRVcXL4= + +Name: system/usr/srec/config/en.us/models/generic11_m.swimdl +SHA1-Digest: N2jOonTixJLNBvuNMlZ1cmcMhzU= + +Name: system/lib/modules/eeprom_93cx6.ko +SHA1-Digest: l0W+6AxuGi+ZwQrSJbIoVEdXqCc= + +Name: additions/fonts/comicsans/Roboto-Regular.ttf +SHA1-Digest: 3H/7DHILeP5YaFf1M5+OGT5BQhM= + +Name: additions/fonts/asap/Roboto-Regular.ttf +SHA1-Digest: 2i3Y+rL5W0C8NRJuxSuGDpjzkGU= + +Name: system/etc/wifi/p2p_supplicant.conf +SHA1-Digest: gnijNFdlV/VI2tMxz7KcnFewPuA= + +Name: data/app/com.adobe.flashplayer-1.apk +SHA1-Digest: bHgFjf3MX8sSwyfwmcrGnWABh/o= + +Name: system/etc/ov2722_1 +SHA1-Digest: P8BRHTNEk4ZkOWaSvNi1nLT3aiM= + +Name: system/lib/libqdutils.so +SHA1-Digest: /7sCeTTYgSLJputfkQ6QspGJjT0= + +Name: system/bin/top +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/etc/media_profiles.xml +SHA1-Digest: x7T2Lt4eYUFpufhh9uFg3lIx+zo= + +Name: system/app/HtcBackupReset.apk +SHA1-Digest: Oj7hzUS+QtPFaQgTK+VY7slW7EQ= + +Name: system/etc/tfa/recorder_l.preset +SHA1-Digest: ZIWhTsSVk2FQh+JqEczz/+vRDeQ= + +Name: system/customize/resource/icon_launcher_active_sync.png +SHA1-Digest: J9ZTXgbThiTNedL+9nw3jv24TCY= + +Name: system/etc/security/cacerts/72f369af.0 +SHA1-Digest: kDG+4qnGpf1LhqDTY1b++EDoMAI= + +Name: additions/gps/asia/etc/gps.conf +SHA1-Digest: bV8Qal0r4TZ65mrlH4e8lb9rNnA= + +Name: system/lib/libchromatix_s5k6a2ya_preview.so +SHA1-Digest: cWtBl0zWUbjPDYhGEZ2oPX3siWY= + +Name: system/media/weather/weather_clear.mp4 +SHA1-Digest: xMbQ70LkzOLa0YMCMdg7A+CT+1w= + +Name: system/customize/resource/icon_launcher_yahoo.png +SHA1-Digest: 4zrDzP2De2eCAV3wpPQm4zvfDy0= + +Name: system/media/audio/notifications/Magnolia.mp3 +SHA1-Digest: GpiUgNJ/bR6utCxj4xjpN9R+Lf4= + +Name: system/media/audio/ui/Lock.ogg +SHA1-Digest: m1O0ZlYq8HMVfUAz7JuG28NXwxQ= + +Name: system/framework/core.jar +SHA1-Digest: YDmBWCkWD+seFvQPPfqB2Lvd9SA= + +Name: system/media/zchgd/batt_50.rle +SHA1-Digest: bW741QkPmOXetEgJpp4vweToIek= + +Name: system/lib/libwfdnative.so +SHA1-Digest: wENU8g3NkgFpB5FuSptJyyZA3PE= + +Name: system/customize/resource/allapplication_232.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/framework/ime.jar +SHA1-Digest: GSJ7k17MSlHYXqvj3qzwNsGsCic= + +Name: system/customize/resource/quicklaunch_26806.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: META-INF/com/google/android/aroma/icons/apex.png +SHA1-Digest: akhGWuuQ3xUBorLR4mvPN1cXAvk= + +Name: system/etc/security/cacerts/b7db1890.0 +SHA1-Digest: 2szR4UBPkIHU3s5s690BvX+1zuk= + +Name: system/lib/libloc_api_v02.so +SHA1-Digest: 0xAwh+xAT+JiDuK10Bbn6ZWrKkM= + +Name: system/etc/security/cacerts/412bea73.0 +SHA1-Digest: IzFpXikosbCidRWhJIDcs/X7LNA= + +Name: system/lib/libwt6pptxrdr.so +SHA1-Digest: RoDj8twq/34sEZHJle4yIs6rtNw= + +Name: system/app/SharedStorageBackup.apk +SHA1-Digest: c7xODp2TjlAprh8YxZTtzPLHGUs= + +Name: system/lib/libstagefright_yuv.so +SHA1-Digest: 0HToHiT/n1mTKB1vCZbwVEWOEAQ= + +Name: system/framework/modemwarmup.jar +SHA1-Digest: QQd4sRTzCLMS2dENDFw6qm6THr4= + +Name: system/app/HTCBackup.apk +SHA1-Digest: aR4ER4pzg7XGMPZ5pMMpXK8uzts= + +Name: system/usr/idc/synaptics-rmi-touchscreen.idc +SHA1-Digest: 6JEfMdlyDan77GFkNoKg2WEZEZk= + +Name: system/usr/srec/en-US/c_fst +SHA1-Digest: V2x/Tax3DLB7jG4K359SkvtizQ0= + +Name: system/app/Prism_LocalFeedProvider.apk +SHA1-Digest: 2rPadGHal7rS0Cp2c/Ti5U0yGwY= + +Name: system/etc/tfa/playback_l.config +SHA1-Digest: mcDPznDmbQbzvQ1yOzfS3mAX2n0= + +Name: system/bin/logcat +SHA1-Digest: z4Byfm16+LdHBseQivHnr82RK0I= + +Name: system/bin/mke2fs +SHA1-Digest: kNU14h7raZkOtasdoo/GnbEf3Qk= + +Name: system/lib/libnotes_jni.so +SHA1-Digest: OIOZFKTyfXCPkI8VvcPECpknkZA= + +Name: system/etc/hltrd.bin +SHA1-Digest: Ym1kH+mpPRnjJ7Xz9MTNHjTf1kU= + +Name: system/lib/libspeexwrapper.so +SHA1-Digest: M3sx2CRBxoNO4l9n0UKt3WuTXXc= + +Name: system/bin/dumpstate +SHA1-Digest: SLgxmRplJdnOoTf84QRtuQN6u/M= + +Name: system/usr/share/partials/partials_H_gr.csv +SHA1-Digest: x3H1K0s8nIfhStMBJ1ml3INv6g4= + +Name: system/customize/resource/quicklaunch_26803.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/etc/AlarmGroupQueueList.xml +SHA1-Digest: vrBNOXzkLD/tVWD6+YeqblgEr+c= + +Name: system/bin/mkdir +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/app/HtcLockScreen.apk +SHA1-Digest: kS35HRJ7v13teUc1lNZ4nBQ4xBg= + +Name: additions/fonts/comicsans/Roboto-BoldItalic.ttf +SHA1-Digest: JGZVL5b7jSLrk3LMJK7phFPyg8s= + +Name: system/fonts/DroidSansFallback.ttf +SHA1-Digest: PsxABdyJmBV/NOdZluIGqPPzIT4= + +Name: additions/fonts/comfortaa/Roboto-BoldItalic.ttf +SHA1-Digest: /35z/1Nkw4zfuX4GbhNRmxDFhkc= + +Name: system/etc/security/cacerts/1920cacb.0 +SHA1-Digest: R7QRICoLwPUp6AhMzbXPpFGE8ho= + +Name: system/media/GPU/stylizeColorRamp.bmp +SHA1-Digest: ssv57ZtVn6dDDbUW1MzY1avYzuE= + +Name: system/app/FilePicker.apk +SHA1-Digest: rjMNoC24q2QK/alv/idtkd6Q8qY= + +Name: system/app/DefaultContainerService.apk +SHA1-Digest: OBlxwCyVH7+0FXG1WyZ2Ze2SjV0= + +Name: system/lib/libbinder.so +SHA1-Digest: kQLYdUwx2/oYFVuL33d9z+ngSyg= + +Name: system/app/MyDropbox.apk +SHA1-Digest: al9MGR+POmf9Jx5Gtt+IyhhZYGE= + +Name: system/app/HtcDataRoamingWidget.apk +SHA1-Digest: vB96sxPiIF7MuG+CmWmMrCCiC70= + +Name: system/lib/libmmjpeg.so +SHA1-Digest: EDqj9jj2hfC342UyVdAM+WINqeM= + +Name: system/lib/libchromatix_s5k6a2ya_zsl.so +SHA1-Digest: 9nKEs/Z8eTiBlkha6y7H0gE1tIs= + +Name: system/etc/security/cacerts/9dbefe7b.0 +SHA1-Digest: EPhp4B4/b2pUwm0D3ZjC5np6RpI= + +Name: system/lib/libalbum_util2e.so +SHA1-Digest: oVM2Wt1z5ZolHFY/F0CsUUTmYu4= + +Name: system/etc/init.qcom.fm.sh +SHA1-Digest: C08X0QRMGyiedbHR/ucZ1NMa2cA= + +Name: system/customize/resource/allapplication_65501.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/etc/security/cacerts/2afc57aa.0 +SHA1-Digest: EkhgecDeewZKqIaZMoXgIPqbsQM= + +Name: system/customize/resource/quicklaunch_20810.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/app/HtcAccessoryService.apk +SHA1-Digest: 3B1ejiyaEa0j85AFUAkdDuKOkRA= + +Name: system/etc/security/cacerts/343eb6cb.0 +SHA1-Digest: O+vAjCl4L2DEpmcXgqljeBNzRgw= + +Name: system/customize/resource/quicklaunch_23806.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/app/CalendarProvider.apk +SHA1-Digest: AOHTj3KmClCZGyGUhqotz/fJxWM= + +Name: system/etc/permissions/com.playstation.playstationcertified.xml +SHA1-Digest: nVjSmkPikQF9xTTZo1SgdBSvYGI= + +Name: system/bin/service +SHA1-Digest: 6nGxxM9K+Xtwnat7jFsVFcLulG4= + +Name: system/etc/security/cacerts/3e3744fd.0 +SHA1-Digest: vASvqfaKbXK7xfFL5JUfZnMLtWM= + +Name: system/media/audio/alarms/Scarlet.mp3 +SHA1-Digest: YHmfzFkL4rPX2or9InI5c4mFqsE= + +Name: system/bin/ois_camera +SHA1-Digest: iTIUECc95oRWv2lEYh9jBBr+YfE= + +Name: system/app/HtcPhotoEnhancer.apk +SHA1-Digest: qjz+FJdwOC/eMXKo0nlWYTHExH0= + +Name: system/etc/security/cacerts/2edf7016.0 +SHA1-Digest: qaI/Jledqev96e95cWVbRtxDzdA= + +Name: system/lib/libI420colorconvert.so +SHA1-Digest: 54LKYxmGJX3Ns5+wbfRGSv7rjr0= + +Name: system/media/audio/notifications/Regalia.mp3 +SHA1-Digest: dOguRyeA7e/c4z49OKdm5EJfAlw= + +Name: system/etc/soundimage/srsfx_trumedia_movie.cfg +SHA1-Digest: L9EmttwiCIxAPEQCWKJ2RZCQgS0= + +Name: system/app/Automotive_Home.apk +SHA1-Digest: WLXPdpZG4OolaFoakS6bQBprnk8= + +Name: system/bin/servicemanager +SHA1-Digest: mzGF2ORzj7Zt7Jexmxtoti+JXoQ= + +Name: system/lib/libhtcflag-jni.so +SHA1-Digest: CXC2Uvdw0yuip74h8yZJPy0LIQg= + +Name: system/etc/security/cacerts/0dbd0096.0 +SHA1-Digest: wOf/ufGVHjhFv2iS9c0YutoTNhQ= + +Name: system/media/audio/ui/KeypressSpacebar.ogg +SHA1-Digest: W5H8TwiuPBEoXIq85+hJWUrkOVU= + +Name: system/usr/share/zoneinfo/zoneinfo.idx +SHA1-Digest: m5//InzwugFOH2ZQxTdoK+x2MMk= + +Name: system/lib/libqmi.so +SHA1-Digest: GaIMAMkZUnA77cUvBF9PdtrkREA= + +Name: system/customize/mns_map.xml +SHA1-Digest: xWmNWm5qkKwdkxxKDxT1cj8LD/I= + +Name: additions/camera_4.2/lib/liblightcycle.so +SHA1-Digest: kXD0YGYtnvaYnWMUVS/i+J6w3uU= + +Name: system/lib/libvideoeditor_jni.so +SHA1-Digest: xdDGtjaE4KpmVRrmed8Z3VRsW9I= + +Name: system/customize/resource/rp_ce_0682_i.png +SHA1-Digest: MPFDvWPN/dtjToDg0dFEd+j3ql8= + +Name: system/media/audio/alarms/Flame.mp3 +SHA1-Digest: xxKH8avP+cwPx+keF0OhlAmDu4A= + +Name: system/etc/RT5501 +SHA1-Digest: AMGLnOuJ9+oyGb/krqH7tDbrnQk= + +Name: system/app/Tube2_Configuration.apk +SHA1-Digest: L0mn/dA8Pll++KWx87hmLnJEWWs= + +Name: system/lib/modules/scsi_wait_scan.ko +SHA1-Digest: m/QV2ZO8XJ6InW3js0Y2qPre0z4= + +Name: system/framework/services.jar +SHA1-Digest: E/WZFm9MDDcX6VEwKFofwew1Qzk= + +Name: system/usr/srec/en-US/phonelist +SHA1-Digest: UXoRA4i+4slLvj7BwxfVXzFgK0Q= + +Name: system/customize/resource/allapplication_420.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/lib/libchromatix_vd6869_zoe.so +SHA1-Digest: +Tf9eE+qWHPG9r++iQhaaOAEX8Q= + +Name: system/bin/hostapd_cli +SHA1-Digest: PUbMwiu76TGMgof3OlFG8idyEOU= + +Name: system/etc/init.qcom.coex.sh +SHA1-Digest: Qn0udCSEPgfUvHcL8pWOad4QERI= + +Name: system/lib/hw/gralloc.msm8960.so +SHA1-Digest: Z2T9uIST+h4d20R9ihin3+Yx0zE= + +Name: system/lib/libAudioTrimmer.so +SHA1-Digest: 2ol/zGXeF7RhaSxT161h5a2i+fc= + +Name: system/media/zchgd/charging_01.rle +SHA1-Digest: 5sXmisNHh+5iyc5fMW1QUefvkHw= + +Name: system/vendor/firmware/libpn544_fw.so +SHA1-Digest: 2TS1uqpe82e/P2sHI7H75nr0m4Q= + +Name: additions/seeder/app/Seeder-2.0.0.apk +SHA1-Digest: AmhI8h/aTClfVVdvzRH4qkpikog= + +Name: system/etc/tfa/voice_l.preset +SHA1-Digest: OVBiITpEEwnpRzjGcCTdTkgmGA4= + +Name: system/lib/libdl.so +SHA1-Digest: 3txFCvD04/L1VxTwEe7XrVqYLIE= + +Name: additions/fonts/ubuntu/Roboto-BoldItalic.ttf +SHA1-Digest: XTo42R6xZv0bq2wDzQz0PvlqM6s= + +Name: system/bin/adaptive +SHA1-Digest: E8tsEwE7cmroacvJPUvSP/NEf94= + +Name: system/etc/security/cacerts/b413391d.0 +SHA1-Digest: lehk0//w6Yyx1L2BnNMZoRZKluc= + +Name: system/usr/srec/en-US/metadata +SHA1-Digest: YPYK5NG59a30DaQyjp8lHVJfo48= + +Name: system/app/Talk.apk +SHA1-Digest: HPyifh93uiJhKS4VINUBUsY9WEE= + +Name: system/etc/tfa/playback.eq +SHA1-Digest: ioyR7ioJoO6yab62er4b74v4YhQ= + +Name: system/usr/srec/en-US/contacts.abnf +SHA1-Digest: 7OXPIU1ePgerziVbKoBu2RcikeA= + +Name: system/etc/libpmhwrl.so +SHA1-Digest: Jnedoe4Se6fF59bMDc4y2eybuk4= + +Name: system/tts/lang_pico/de-DE_gl0_sg.bin +SHA1-Digest: AqYOydFO+UHIftz1QE8h+6cjU+s= + +Name: system/customize/resource/quicklaunch_232.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/lib/libandroid_simlock.so +SHA1-Digest: LLT7TC7NOhRDAM+LC2OLdzQPXw8= + +Name: system/usr/share/zoneinfo/zoneinfo.version +SHA1-Digest: C3jhoc/P5UgYjouhc4bZw3TcmeA= + +Name: META-INF/com/google/android/aroma/icons/info.png +SHA1-Digest: cUFToRrZ3Xv7BsscGsCW8a+wXXQ= + +Name: system/media/audio/ringtones/Ocean.mp3 +SHA1-Digest: n+GLdCDo7g9/CpQgj1iTVDHShHo= + +Name: system/app/HtcVideoPlayer.apk +SHA1-Digest: teXCH7b33Grv7XPWz/bkfA3M8hM= + +Name: system/lib/libmmmpod.so +SHA1-Digest: 84nlFZD8ykNNOWejAY303ZpNPhM= + +Name: boot.img +SHA1-Digest: P3rDJfT3UeB6sdl8RKM4VFyDiGk= + +Name: system/lib/libsqlite.so +SHA1-Digest: /fiK6C43s8RwQjvRV9QuKdZly3A= + +Name: system/etc/AudioBTID.csv +SHA1-Digest: Gqh/UYdUamQ0hhKaMR4rftiJS6M= + +Name: system/etc/permissions/android.hardware.camera.front.xml +SHA1-Digest: UHlHrvWjU+j2mP35N5eTTCJsGKo= + +Name: system/customize/resource/quicklaunch_24201.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/lib/libzeroeditor_core.so +SHA1-Digest: S2HmhIBOoZbCFQnsOCoCCb1uDSg= + +Name: system/etc/permissions/com.cisco.anyconnect.permissions.patch.ht + c.xml +SHA1-Digest: +2+iPfdnszYMIo0aZVtE47s5XHU= + +Name: system/etc/security/cacerts/58a44af1.0 +SHA1-Digest: t3CGdgkkwdvHlDpdrK1fU2hm7VM= + +Name: system/etc/security/cacerts/1155c94b.0 +SHA1-Digest: s4MqqrFEF/72+iq+wIGqr5PcZAs= + +Name: system/etc/security/cacerts/12d55845.0 +SHA1-Digest: Dl66XTBMvMhwxbJmyV6GBJ6brpk= + +Name: system/lib/libwilhelm.so +SHA1-Digest: e6ZCFDPcd9H6HnF8UgX8MNZ+QPg= + +Name: system/etc/permissions/com.google.android.media.effects.xml +SHA1-Digest: 1ymq8QA4Aky6u6O7KNmEtnQRsho= + +Name: system/fonts/DroidSansDevanagari-Regular.ttf +SHA1-Digest: rcDk7w2X12yWFtec3dheokLZP7Y= + +Name: system/customize/resource/quicklaunch.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/media/zchgd/charging_07.rle +SHA1-Digest: EXqLHmDATH06bTfx8yaOikW1qOE= + +Name: system/app/GooglePartnerSetup.apk +SHA1-Digest: ztiFVIJXpgHa+MR5KZopt6qvb88= + +Name: system/lib/libclcore.bc +SHA1-Digest: B1+4TwzZ4lL0Qb/Ord20AIlruwk= + +Name: system/lib/libclcore_neon.bc +SHA1-Digest: OR0PB7cN5Otkgd4lrNXFsT8DheM= + +Name: system/customize/resource/wallpapers_b_04.jpg +SHA1-Digest: KAgiQy4/IH7XzoWjWCoFsbh6XIk= + +Name: system/bin/lsof +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/bin/cand +SHA1-Digest: 7Ggz8CRViN4vqDOtYfvbnI29HB0= + +Name: system/lib/libpdfviewer.so +SHA1-Digest: uFCKw2Nb8ECjcEWdQkAJFGqvw00= + +Name: system/lib/libfacelock_jni.so +SHA1-Digest: ZWJMjaHj8gmUvAfIPm5jmo1xn68= + +Name: system/lib/libmedia.so +SHA1-Digest: WPtRnRat1cE5UF+1GqobEPo38uE= + +Name: system/lib/libfilterpack_imageproc.so +SHA1-Digest: roc4s57JfSFjG5jjNCmzOw9Vhg0= + +Name: system/lib/modules/bluetooth-power.ko +SHA1-Digest: H/+LuShLo0Q+gqT686s1uhoNqI8= + +Name: system/usr/share/partials/partials_H_bb.csv +SHA1-Digest: 3Q3qT2QP7+oby0sCeg2DVnX33jI= + +Name: system/usr/share/partials/partials_CW_bb.csv +SHA1-Digest: N+ejER4kXRjOwMUkDjEY+gWIdGk= + +Name: system/lib/libmm-abl.so +SHA1-Digest: TpzopUDSJmY3Pl7IuMQOUta+ioA= + +Name: additions/fonts/asap/Roboto-Italic.ttf +SHA1-Digest: sVPgPJUSOxnZgqIoFaGvCU/vRNw= + +Name: system/app/PluginManager.apk +SHA1-Digest: I/RRszMgfSJurTtjA2QmtunTz70= + +Name: system/app/Prism.apk +SHA1-Digest: Ud6S/8tldGhCLUt/aqidkCzD5Zo= + +Name: system/vendor/firmware/mfg.bin +SHA1-Digest: h+7kLgkbGybwIyGt6Vpej2Nj3Lk= + +Name: system/etc/system_fonts.xml +SHA1-Digest: +AFAJEzDoN8rlf6Jboc5EHuDwFg= + +Name: system/customize/resource/quicklaunch_262.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/app/IMEXT9Latvian.apk +SHA1-Digest: VQ6ZPnIux+tkpe9+02XXXDOjbVM= + +Name: system/lib/soundfx/libreverbwrapper.so +SHA1-Digest: jPJNweOjdXsN6nEnRUilEtgbca0= + +Name: system/fonts/DroidNaskh-Regular.ttf +SHA1-Digest: UlmKZJTwpi0qnPC8KApnbHJiosQ= + +Name: system/etc/permissions/android.hardware.usb.host.xml +SHA1-Digest: Na0AbBFcnB2Br8zB+hMI2Y53zys= + +Name: system/app/Flickr.apk +SHA1-Digest: xCptiwsZYo3Pw09cDQISxZiL/Q0= + +Name: system/lib/libmmcamera_hdr_lib.so +SHA1-Digest: 3aF4x20mC2yzZmdSW/vWhEBkgHA= + +Name: system/customize/resource/quicklaunch_26801.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/etc/snd_soc_msm/snd_soc_msm_2x +SHA1-Digest: a1cCYKU154XoMVmsXqQz9Fl2vYg= + +Name: system/app/CIMEXT9.apk +SHA1-Digest: Lnkp0+G9zpJKidHwb0tWwlKkXJg= + +Name: additions/fonts/comfortaa/Roboto-Bold.ttf +SHA1-Digest: G2bLol7a6Kcue8P7a+sLda6U/Bk= + +Name: system/app/HtcSoundRecorder.apk +SHA1-Digest: uVWOQYl9J11LcW74S3J6y5nR1UU= + +Name: system/media/audio/alarms/Gold.mp3 +SHA1-Digest: EyYq1nhqZ6Qr8HGJZFNbC9RcUmE= + +Name: system/etc/audio_effects.conf +SHA1-Digest: UIu/6M+4Z9jE0VBhYxYIt5hQoJY= + +Name: system/customize/resource/quicklaunch_21401.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/etc/image_ibeats_solo_2vol.bin +SHA1-Digest: nvzAjLdyidqP8V4UNUiSmf5Kn24= + +Name: system/framework/pm.jar +SHA1-Digest: e++O044GpPSgchnVlOlDHQNlCM0= + +Name: system/app/NoiseField.apk +SHA1-Digest: uXjJo3Y4nTwxe4lxfomzOq+T1H4= + +Name: system/lib/libdiag.so +SHA1-Digest: f6EADf0JxGJE7eXW/Kew6jGMv8k= + +Name: data/app/com.twitter.android-1.apk +SHA1-Digest: xiDcu9vlE4kYb93vu33DeaK4Sv4= + +Name: data/app/com.google.android.googlequicksearchbox-1.apk +SHA1-Digest: 5jVjrlDZyL8HLRl3zoedJ4f97Ag= + +Name: system/bin/toolbox +SHA1-Digest: j3eLJl1JFEoS/ACfsVGQlX/uAIo= + +Name: system/customize/resource/allapplication_63102.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/etc/security/cacerts/eb375c3e.0 +SHA1-Digest: tmCwIHz56faNDn0roOj08Yyrv0E= + +Name: system/lib/plugins/com.adobe.flashplayer/libysshared.so +SHA1-Digest: TB891nh0tUUz+nsrHzpoSik8nMA= + +Name: system/lib/libwfdmmutils.so +SHA1-Digest: uqKruruA4V3poQY7ppuWmLo/te4= + +Name: META-INF/com/google/android/aroma-config +SHA1-Digest: 5tmXTnBNRM+FTnbgvU4Zvw7eBIs= + +Name: system/etc/nfcee_access.xml +SHA1-Digest: TgL7tDwvgXVKDC/jEltr/83iPPQ= + +Name: system/app/IMEXT9French.apk +SHA1-Digest: SFH+luypioo+vXtpj43SuSlCz+I= + +Name: system/framework/com.google.widevine.software.drm.jar +SHA1-Digest: +qbuOxdtyIu/AQZLR8qCxopyN90= + +Name: system/bin/ipv6tether +SHA1-Digest: 0RaTsspOHB3JLyn0o7zSLyfa9zM= + +Name: system/framework/com.htc.videowidget.res.apk +SHA1-Digest: MZEzmMO/yyYm/Hd0NPs4EnT33B0= + +Name: system/media/weather/weather_snow_day.mp4 +SHA1-Digest: Gpb/DamZOkmv7mv1p+FmsWDPM2E= + +Name: system/etc/tfa/video.preset +SHA1-Digest: gLyUQwAim17CsSVazvxBjmG77tQ= + +Name: system/customize/resource/allapplication_262.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/etc/security/cacerts/4f19d2b4.0 +SHA1-Digest: hr7OO548ug4ki+JB3UhR3NJvru0= + +Name: system/etc/security/cacerts/ea169617.0 +SHA1-Digest: smRXb6WPNBJ4NICRtncXV/vuQiY= + +Name: system/etc/security/cacerts/3d441de8.0 +SHA1-Digest: bswrWmxovthgf13lTWpmpt5/X/Y= + +Name: system/etc/security/cacerts/72fa7371.0 +SHA1-Digest: O84yTu+CcVyjxjgoAYqQZpR9xI8= + +Name: system/lib/hw/hwcomposer.msm8960.so +SHA1-Digest: qJPRtnt8wrlWZhBvP26iUbJRgEk= + +Name: system/lib/libcpt9.so +SHA1-Digest: CFtKbAxU+7cVGYLd7OUKqcvS2A4= + +Name: additions/exchange/app/Mail.apk +SHA1-Digest: 0/qoQPnDF6YXDnrq2lz+epbScbs= + +Name: system/etc/security/cacerts/facacbc6.0 +SHA1-Digest: /tkMzD2t5DcEEHz19euP7w+unGY= + +Name: system/app/HtcGetStarted.apk +SHA1-Digest: qldS5QI2yvvqGtn8+cd/kc+CgfQ= + +Name: system/lib/libprojector.so +SHA1-Digest: jRqmE7on2zuK8MDiMMm+IyxWcSU= + +Name: system/lib/libidl.so +SHA1-Digest: 52s99Y2Ue3P4p/awhXBDLP1kBmI= + +Name: system/framework/HTCExtension.jar +SHA1-Digest: hRs/1ZRv7AYJ5nsA8XY0Q0RhIJY= + +Name: system/lib/libcpt9provider.so +SHA1-Digest: 41+2Jxxgntz7iz5drfCm9n4aaoI= + +Name: system/lib/libhardware_legacy.so +SHA1-Digest: m/lX5JVU18gON9I58uopDEjWMwQ= + +Name: system/usr/srec/config/en.us/baseline8k.par +SHA1-Digest: cR3ErVVeWITO4QendRZRkkfChHc= + +Name: system/lib/libwt6prnddi.so +SHA1-Digest: lZ7gRr5kLfU2sV56wvXaht6T1GQ= + +Name: system/app/TwitterEngine.apk +SHA1-Digest: flZBqEpA4U9zeJR8sleiIunqrls= + +Name: system/etc/permissions/android.hardware.sensor.proximity.xml +SHA1-Digest: Ir4TfyGxk4QiuORZa9Esndgmxfk= + +Name: system/lib/libstagefright_soft_g711dec.so +SHA1-Digest: EuZ1FOfGI4lFfHFyj1P+higw4XQ= + +Name: system/usr/srec/config/en.us/g2p/en-US-ttp.data +SHA1-Digest: EeTucxvP4KvwmGxmWn6mzatobhQ= + +Name: system/bin/shutdown +SHA1-Digest: XsHDC1ougaip0TcxuKl4P0+2huU= + +Name: system/lib/libchromatix_ov5693_hfr.so +SHA1-Digest: W4iXehh+/IlJJ4UnIgvYGGOmPXs= + +Name: system/lib/libvariablespeed.so +SHA1-Digest: rPE11kp8EQzuXL+LD4kqpgM3ZDQ= + +Name: system/lib/modules/spidev.ko +SHA1-Digest: dTPqk0ahf3jMtL4rspKQ5btIQ+c= + +Name: system/bin/nl_listener +SHA1-Digest: 7rZrAjymyIKZLbaOCC3FnftsceA= + +Name: system/app/Stk.apk +SHA1-Digest: YM4/rYqam4Byd2uN3F78VbGxGoE= + +Name: system/lib/libnfc_jni.so +SHA1-Digest: lpxse3k8wgRK2PcZHFSlVKjDShE= + +Name: system/etc/security/cacerts/ccc52f49.0 +SHA1-Digest: 8vnIJSGmWI5J6d7i+2tVGHvD5i0= + +Name: data/app/tunein.player-1.apk +SHA1-Digest: 3ib4NtvpqV0edCJUZ8B3n5Ur8+g= + +Name: system/lib/libchromatix_imx175_zsl.so +SHA1-Digest: 2DtYs/3o06QSvTE1yRBoliZ08nY= + +Name: additions/fonts/comfortaa/Roboto-Italic.ttf +SHA1-Digest: FD5Rg9PAMNslUz8+KIO69W/UC4M= + +Name: system/framework/com.htc.socialnetwork.res.apk +SHA1-Digest: CzzNxbO0yf4O8kqfwyFwPra8eEE= + +Name: system/customize/resource/quicklaunch_20205.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/app/IMEXT9Estonian.apk +SHA1-Digest: eSzu36cr2HN9YAAPh6nWBDVTPx4= + +Name: system/etc/security/cacerts/d0081655.0 +SHA1-Digest: Ez6pwhMlUxmpGLkfoVyymK1LdBA= + +Name: system/etc/security/cacerts/34d760b2.0 +SHA1-Digest: 6JmKjb1sxRq4tbDi9K8OatWlBis= + +Name: system/lib/libspeexresampler.so +SHA1-Digest: QCU1ObIPcsMakYiBncBZCmaIxQ0= + +Name: system/bin/ds_fmc_appd +SHA1-Digest: tGFQUY5RWrDe8kvIIdzYY++b/mA= + +Name: system/etc/spn-conf.xml +SHA1-Digest: e4aOGIw34uYo5aZxeys5bXSTuLU= + +Name: system/etc/hldm.bin +SHA1-Digest: 9OvfF+g5Z1T11E7xlK6Lssdw9/c= + +Name: system/lib/libcamerapp.so +SHA1-Digest: xkMJP0WQbYup90m3RnuEmW16CGs= + +Name: system/fonts/DroidSansGeorgian.ttf +SHA1-Digest: qGy+CDCNRhdxla4YsZpnovwHGGM= + +Name: system/etc/tfa/fm_l.config +SHA1-Digest: mcDPznDmbQbzvQ1yOzfS3mAX2n0= + +Name: system/customize/resource/allapplication_250.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/etc/security/cacerts/c7e2a638.0 +SHA1-Digest: 9ya3Pspxo12STfIyX8NIsr5A/7c= + +Name: system/app/IMEXT9Finnish.apk +SHA1-Digest: wpW93NqfbJxg+9M8+eLcsQAUwH8= + +Name: system/bin/dumpsys +SHA1-Digest: AhelssiTpzulZJISDs3bQ1ZUv4w= + +Name: system/app/GoogleLoginService.apk +SHA1-Digest: PD9V04uBXIrFaZNr8YjfcBFKD78= + +Name: system/media/audio/notifications/Verdigris.mp3 +SHA1-Digest: mHsVS/jKDzfKdflpv7ThAWZlgno= + +Name: system/lib/libandroid_servers.so +SHA1-Digest: RFhR+vMZltpT5kluPQF4QyriPzE= + +Name: system/bin/hci_qcomm_init +SHA1-Digest: S0Xcr75dW5UGi6EBVe3gWlc2vd8= + +Name: system/lib/libmmrtpencoder.so +SHA1-Digest: aqv8kwkl8hT5s+RxW1KiqSGYETg= + +Name: system/etc/image_beats_wireless_bt.bin +SHA1-Digest: XFROhQCo3zqAvzn90oj42boldH8= + +Name: system/usr/share/partials/partials_CW_gr.csv +SHA1-Digest: +n5gUnrxus6DupV6WP7jVOZ2+6Q= + +Name: system/media/audio/ui/KeypressDelete.ogg +SHA1-Digest: bZEM7p2jzlwy0AICXAOSF3LdqGw= + +Name: data/app/com.estrongs.android.pop-1.apk +SHA1-Digest: i4qJTljs0jlro13CKAShhunMPbg= + +Name: system/app/Idlescreen_productivity.apk +SHA1-Digest: S3PZauHq6OnGehGz59PX4+oLFhQ= + +Name: system/customize/resource/quicklaunch_65502.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/app/MediaProvider.apk +SHA1-Digest: eaqUACetsBXAb751OaaMfTdRIg0= + +Name: system/bin/wmdsi +SHA1-Digest: j3eLJl1JFEoS/ACfsVGQlX/uAIo= + +Name: system/lib/egl/egl.cfg +SHA1-Digest: gSZVwUFEbiJSML4A429+nW64kQY= + +Name: system/app/HtcMusic.apk +SHA1-Digest: qbT7LnFTjplTIbmglp6mxnGq5kE= + +Name: system/etc/security/cacerts/11a09b38.0 +SHA1-Digest: WAuD+V8HYjv2J8L6RjLCvz0/eXI= + +Name: system/etc/security/cacerts/c527e4ab.0 +SHA1-Digest: Htxt63bTyJOKdCrkatkDPmVvkhs= + +Name: system/customize/resource/allapplication_21910.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/bin/adb +SHA1-Digest: FcAl3iUM+RfrW3qZNvY+B984JN8= + +Name: system/app/ContactsProvider.apk +SHA1-Digest: 5yOp0Wo/mGVibiWrI+150x4sv84= + +Name: additions/fonts/veggieburger/Roboto-Regular.ttf +SHA1-Digest: Wmfs/7ddF/Fbm10Rfh9eri+OtXo= + +Name: system/lib/libnetmgr.so +SHA1-Digest: OR7o3//BGAQOFrF01AtGo4xnRys= + +Name: system/etc/security/cacerts/95aff9e3.0 +SHA1-Digest: 1FyDHWZk97rejAOqX84plYw2Dik= + +Name: system/lib/libqc-opt.so +SHA1-Digest: 8mXjFG05pBbeyGHzO4DIPnpKDq0= + +Name: system/bin/ifconfig +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/lib/libalbum_imagelib.so +SHA1-Digest: EJJQtnePbvDVz1T4BuYk0x9U0yM= + +Name: system/xbin/dexus +SHA1-Digest: ZLa/57bXQry9uH3eqmezYVytmQs= + +Name: system/etc/security/cacerts/8f7b96c4.0 +SHA1-Digest: QfxKn6PfoE0C352mOtyffWA172I= + +Name: system/lib/egl/libGLESv2_adreno200.so +SHA1-Digest: AMIj/L6GRcJMr+gKGdO/hFwlM/g= + +Name: system/lib/libext2_blkid.so +SHA1-Digest: tMHS6rxl5aKI0GTBzy/jm6pwQ0A= + +Name: system/customize/resource/quicklaunch_20404.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/bin/bugreport +SHA1-Digest: 3+6f66+v91o3OCeBaHh4FwT8jQo= + +Name: system/etc/security/cacerts/58546a39.0 +SHA1-Digest: QKH0gKtdbsPsdzQ2/mfmfqKzaHM= + +Name: system/lib/libmmcamera_rubik.so +SHA1-Digest: FSD6HoU01NRtBXreaBBWRPKSKGc= + +Name: system/lib/egl/libGLES_android.so +SHA1-Digest: FHBVLd1WKuQEDAo+IOKaaJBCJJQ= + +Name: system/lib/libstagefright_avc_common.so +SHA1-Digest: 0sfq1IbkelkviReLiD8xJBwGbAQ= + +Name: system/lib/libchromatix_imx135_preview.so +SHA1-Digest: cQjiJ+LKCP7beE/dOhaVeenpXX0= + +Name: system/app/BrcmBluetoothServices.apk +SHA1-Digest: fVownm6g4lj70cO/9FbXZlgMIp8= + +Name: system/customize/resource/wallpapers_a_03.jpg +SHA1-Digest: A+IzIxm/nJelEphlXWCTj+wIaj8= + +Name: system/lib/libchromatix_ov8838_default_video.so +SHA1-Digest: w3BpqXKEPOooHvvZzefCfUgneYc= + +Name: system/lib/libVDRecognitionAPI-jni.so +SHA1-Digest: HRpasglAV3sgRYSiIHfsitDeIhc= + +Name: system/lib/libdiskconfig.so +SHA1-Digest: SHkL2KT2vlcd3JNpJtRBJT7Zt0s= + +Name: system/bin/md5 +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/app/Bluetooth.apk +SHA1-Digest: 2DYPNTgMoCdFyhAa/UfMZiwNqTc= + +Name: system/customize/resource/CCInfo.txt +SHA1-Digest: VmIGhE4OKzAsCZuOpz4o0riUTww= + +Name: system/lib/libmode10AutoTest.so +SHA1-Digest: ejW5BuSYaS+bt8Qnw0kJmDb7jkg= + +Name: system/lib/liblz.so +SHA1-Digest: Ub18k/qSmpblpCjeCzISinIxOGA= + +Name: system/etc/security/cacerts/f58a60fe.0 +SHA1-Digest: A9xf8h5F7uhACk3LuvV2KFpjaR8= + +Name: system/usr/keylayout/AVRCP.kl +SHA1-Digest: XnlMR1We/Ygio+9C2HOkzyIpbjQ= + +Name: system/framework/wimax.jar +SHA1-Digest: x9Te2YB5qgIxw8tEXQWZumcRE6o= + +Name: system/lib/libpolarisoffice_Clipboard.so +SHA1-Digest: 78uPvk3STomxiLln549Pu2U06hg= + +Name: system/app/GSD.apk +SHA1-Digest: +MuFIFeXNd2mYmcltiMADDy+fRo= + +Name: system/fonts/DroidSansTamil-Bold.ttf +SHA1-Digest: mKyxCfCv+wTh1xiep9O2FLktnPQ= + +Name: system/etc/security/cacerts/c19d42c7.0 +SHA1-Digest: xIy8/UfYWjSn64KCqIwcfN3P5J0= + +Name: system/media/GPU/mask_vignette_wide.bmp +SHA1-Digest: JYMBuLpGEVRVp4jEkZ8pQxrxunU= + +Name: system/etc/security/cacerts/3a3b02ce.0 +SHA1-Digest: I8WzZpsm5HGEorbt5jlzpTt3jQ8= + +Name: system/etc/image_beatbox_bt.bin +SHA1-Digest: W873c0G9gw4/bBA3L4yMLUX4FjU= + +Name: system/lib/libchromatix_ov5693_zsl.so +SHA1-Digest: K/dRA4kBAjUzZwWEu/Fxf844gmE= + +Name: system/etc/tfa/voice_l.config +SHA1-Digest: HKUbwkwyeWNkWCWTnAgcEbOJbpQ= + +Name: system/bin/setconsole +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/media/audio/ringtones/Eggshell.mp3 +SHA1-Digest: 1c50J3YQkiGr8FRkZ28W5ZpkzqY= + +Name: system/customize/resource/quicklaunch_21416.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/customize/resource/quicklaunch_24002.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: data/app/com.dropbox.android-1.apk +SHA1-Digest: A37YG/+dSeI4A0OnIfUfdBGIv78= + diff --git a/release/aroma/META-INF/com/google/android/aroma-config b/release/aroma/META-INF/com/google/android/aroma-config new file mode 100755 index 00000000000..1f31527cc44 --- /dev/null +++ b/release/aroma/META-INF/com/google/android/aroma-config @@ -0,0 +1,288 @@ +### LICENSE: +# +# Copyright (C) 2011 Ahmad Amarullah ( http://amarullz.com/ ) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +### FILE INFO: +# +# AROMA Installer 2.70 - AROMA Installer Test Script Configuration +# (c) 2011-2012 by Ahmad Amarullah +# amarullz - xda-developers +# http://www.amarullz.com/ +# +# Binary Version : 2.70B6 +# Binary Codename : Flamboyan +# +### INFO: +# +# * AROMA Resource Dir = META-INF/com/google/android/aroma +# +# * AROMA Temporary Dir = /tmp/aroma/ + +ini_set("rom_name", "Glitch kernel"); +ini_set("rom_version", "Flo-CAF"); +ini_set("rom_author", "Tk-Glitch"); +ini_set("rom_device", "Nexus 7 (2013)"); +ini_set("rom_date", "November 2013"); + +ini_set("force_colorspace","rgba"); +#ini_set("dp","6"); + +fontresload( "0", "ttf/Roboto-Regular.ttf", "12" ); +fontresload( "1", "ttf/Roboto-Regular.ttf", "18" ); + +splash(3500, "glitch"); + + +viewbox( + "Welcome", + "You are about to flash "+ + ini_get("rom_name")+ + "\nfor "+ini_get("rom_device")+".\n\n"+ + + + " VERSION\t: <#selectbg_g>"+ini_get("rom_version")+"\n"+ + " AUTHOR \t: <#selectbg_g>"+ini_get("rom_author")+"\n"+ + " RELEASED\t: <#selectbg_g>"+ini_get("rom_date")+"\n\n\n"+ + + "Press Next to Continue...", + "@welcome" +); + +agreebox("Terms Of Use","Please read the Glitch kernel Terms of Use...","icons/agreement", + "" + readfile_aroma("agreement.txt"), + "I Agree with these Terms Of Use...", + "Please check the box..." +); + +textbox("Changelog",ini_get("rom_name") + " Changelog","icons/info",readfile_aroma("changelog.txt")); + +alert( + "PLEASE NOTE:", + "This kernel will allow you to choose hardware settings that may not work with your device. If you install this and have problems such as instability or random reboots, please reinstall with a lower CPU frequency or higher voltage.", + "@alert", + "OK" +); + +selectbox( + "Set each CPU core separately","If you say yes here you will have the option to set the max freq for each core individually\n","@personalize","cpuopt.prop", + "No","(default)",1, + "Yes","",0 +); + +if file_getprop("/tmp/aroma/cpuopt.prop","selected.0") == "1" +then + +selectbox( + "Maximum CPU Frequency","Select maximum CPU frequency\n","@personalize","freq0.prop", + "1512MHz","(stock)",0, + "1620MHz","",0, + "1728MHz","(balanced)",1, + "1836MHz","",0, + "1890MHz","(performance)",0, + "1944MHz","",0, + "1998MHz","(high)",0, + "2052MHz","",0, + "2106MHz","(very high)",0, + "2160MHz","",0, + "2214MHz","(extreme)",0, + "2268MHz","",0, + "2322MHz","(glitchy)",0 +); + +endif; + +if file_getprop("/tmp/aroma/cpuopt.prop","selected.0") == "2" +then + +selectbox( + "Maximum CPU Frequency","Select maximum frequency for first CPU core\n","@personalize","freq0.prop", + "1512MHz","(stock)",0, + "1620MHz","",0, + "1728MHz","(balanced)",1, + "1836MHz","",0, + "1890MHz","(performance)",0, + "1944MHz","",0, + "1998MHz","(high)",0, + "2052MHz","",0, + "2106MHz","(very high)",0, + "2160MHz","",0, + "2214MHz","(extreme)",0, + "2268MHz","",0, + "2322MHz","(glitchy)",0 +); + +selectbox( + "Maximum CPU Frequency","Select maximum frequency for second CPU core\n","@personalize","freq1.prop", + "1512MHz","(stock)",0, + "1620MHz","",0, + "1728MHz","(balanced)",1, + "1836MHz","",0, + "1890MHz","(performance)",0, + "1944MHz","",0, + "1998MHz","(high)",0, + "2052MHz","",0, + "2106MHz","(very high)",0, + "2160MHz","",0, + "2214MHz","(extreme)",0, + "2268MHz","",0, + "2322MHz","(glitchy)",0 +); + +selectbox( + "Maximum CPU Frequency","Select maximum frequency for third CPU core\n","@personalize","freq2.prop", + "1512MHz","(stock)",0, + "1620MHz","",0, + "1728MHz","(balanced)",1, + "1836MHz","",0, + "1890MHz","(performance)",0, + "1944MHz","",0, + "1998MHz","(high)",0, + "2052MHz","",0, + "2106MHz","(very high)",0, + "2160MHz","",0, + "2214MHz","(extreme)",0, + "2268MHz","",0, + "2322MHz","(glitchy)",0 +); + +selectbox( + "Maximum CPU Frequency","Select maximum frequency for fourth CPU core\n","@personalize","freq3.prop", + "1512MHz","(stock)",0, + "1620MHz","",0, + "1728MHz","(balanced)",1, + "1836MHz","",0, + "1890MHz","(performance)",0, + "1944MHz","",0, + "1998MHz","(high)",0, + "2052MHz","",0, + "2106MHz","(very high)",0, + "2160MHz","",0, + "2214MHz","(extreme)",0, + "2268MHz","",0, + "2322MHz","(glitchy)",0 +); + +endif; + +selectbox( + "Select CPU optimization level","Overclocks L2 cache and bus bandwidth. If you experience instability, choose stock\n","@personalize","opt.prop", + "stock","(1.13GHz-4.26GBps)",0, + "improved","(1.19GHz-4.26GBps)",0, + "balanced","(1.22GHz-4.66GBps)",1, + "fast","(1.35GHz-4.66GBps)",0, + "extreme","(1.43GHz-4.80GBps)",0, + "glitchy","(1.49GHz-4.96GBps)",0 +); + +selectbox( + "Auto Undervolting","Lowers the voltage for the lowest cpu frequency. Undervolting may cause instability.\n","@personalize","uv.prop", + "Stock (no undervolt)","",1, + "Undervolt (850 min)","",0, + "Undervolt (825 min)","",0, + "Undervolt (800 min)","",0, + "Undervolt (775 min)","",0, + "Undervolt (750 min)","",0, + "Undervolt (725 min)","",0 +); + +selectbox( + "Select thermal settings","Determines the amount of thermal throttling for the CPU\n","@personalize","thermal.prop", + "run cool","more thermal throttling",0, + "default","default thermal throttling",1, + "run hot","less thermal throttling",0 +); + +selectbox( + "Select GPU governor","\n","@personalize","gpugov.prop", + "Ondemand","(stock)",1, + "Simple","",0 +); + +selectbox( + "Select Battery life eXtender settings","Sets the charge voltage of the battery to extend its lifespan\n","@personalize","ble.prop", + "4.3V","(100% - stock)",0, + "4.2V","(93% - balanced)",1, + "4.1V","(83% - conservative)",0, + "4.0V","(73% - very conservative)",0 +); + +checkbox( + "Other settings","Select the mods you want to install\n","@personalize","mods.prop", + "Sweep2Wake","Sweep across buttons to sleep/wake device",0, + "Sweep2Sleep Only","Sweep across buttons to sleep device",1, + "S2W/DT2W power toggle","Makes the power button toggle s2w/dt2w",0, + "Shortsweep","Shorter sweep distance for Sweep2Wake",1, + "DoubleTap2Wake","Double tap screen to wake device",1, + "Disable magnetic on/off","",0, + "Enable USB OTG+Charge mode","Allows charging in USB host mode (disables self-powered OTG)",0 +); + +if file_getprop("/tmp/aroma/mods.prop","item.0.1") == "1" && file_getprop("/tmp/aroma/mods.prop","item.0.2") == "1" +then +alert( + "PLEASE NOTE:", + "You must choose either sweep2wake OR sweep2sleep only. You can't choose both", + "@alert", + "OK" +); +back("1"); +endif; + +if file_getprop("/tmp/aroma/mods.prop","item.0.2") == "1" +then +selectbox( + "Select S2S orientation settings","Controls whether sweep2sleep works in portrait, landscape, or both\n","@personalize","orientation.prop", + "Both","",1, + "Portrait only","",0, + "Landscape only","",0 +); +endif; + +menubox( + "Glitch Kernel Installer", + "Ready to install", + "@info", + "menu.prop", + "I want to Glitch my device, install it now !","","@install", + "Abort installation","","@default" +); + +if prop("menu.prop","selected")=="2" +then + exit(""); +endif; + +setvar("retstatus", +install( + "Installing", + "Installing Glitch Kernel...\nPlease wait...", + "@install") +); + +ini_set("text_next", "Finish"); + +if getvar("retstatus")=="0" then + viewbox( + "Installation Completed", + "<#080>Congratulations...\n\n"+ + "Glitch kernel has been installed successfully!\n\n"+ + "Please let your phone boot completely...\n\n"+ + "Enjoy!", + "@info" +); +else + viewbox("Installation Failed","\n\nInstaller Status: "+ getvar("retstatus"),"@alert"); +endif; + diff --git a/release/aroma/META-INF/com/google/android/aroma/agreement.txt b/release/aroma/META-INF/com/google/android/aroma/agreement.txt new file mode 100755 index 00000000000..f27053708e6 --- /dev/null +++ b/release/aroma/META-INF/com/google/android/aroma/agreement.txt @@ -0,0 +1,9 @@ + + +Agreement: + +<*>This kernel is provided as-is without warranty. You are installing this at your own risks + +<*>I'm not responsible for any problem you may encounter with your phone or if your cat suddenly dies. + +<*>By using this kernel, you agree with the above terms! diff --git a/release/aroma/META-INF/com/google/android/aroma/changelog.txt b/release/aroma/META-INF/com/google/android/aroma/changelog.txt new file mode 100755 index 00000000000..400d9a746bb --- /dev/null +++ b/release/aroma/META-INF/com/google/android/aroma/changelog.txt @@ -0,0 +1,30 @@ +Glitch kernel "CAF" for flo + +- Based on CyanogenMod 3.4.0 kernel source for MSM devices updated to linux 3.4.1 +- CPU OC up to 2.3Ghz with OV/UV support +- L2/bus speed OC up to 1.49GHz / 4.96GBPS +- GPU OC up to 627 MHz + - Faux Simple GPU governor support + +- CPU governors : Faux's intellidemand, interactive, ondemand +- I/O schedulers: noop, deadline, row, cfq, fiops, sio + +- Kernel based thermal control by crpalmer and flar2 +- Kernel based msm_mpdecision hotplug driver by Showp1984's + - Faux123 Intelli-plug hotplug driver support + +- tni.andro's battery life extender support +- Sweep2wake/Sweep2sleep/Doubletap2wake support by flar2 +- Magnetic on/off + +- FauxSound support +- Dynamic Fsync by Faux123 +- USB fast charging support +- USB OTG charge hack support by flar2 + +- Optimized algorithms and libraries +- Various performance and power saving tweaks +- NTFS and exFAT support +- Kexec-hardboot support + +- Compiled with latest SaberMod 4.8.x toolchain / -O3 (optimize a lot) diff --git a/release/aroma/META-INF/com/google/android/aroma/fonts/big.png b/release/aroma/META-INF/com/google/android/aroma/fonts/big.png new file mode 100755 index 0000000000000000000000000000000000000000..458f00c89389a726d72c3edc4cd8caf1043b3175 GIT binary patch literal 10938 zcmXwf2UJr{(6$PKR13YU2$2#Iq(c$~q&Gq75@`ZLq}L=wx+oA42rV?Fh;$59AoME5 zP$In-MVgcZ2;t-XzW=}H?B3mb=Iq@wGrMQznJ32BP>Y3;m+``d3oJU?8YUMm(2kss z`L58N_hwGLVdpPeA2pq)SI!^A700*da|TasOP>oDINSbf7fmH!Eu4Sk^nGmMtM2V& z=j-b6`sPztn9~JmX(<_bDQW4)wF|e-CHVi7F!gxp8(`<{bm5VshrQEHO;>NH01t0B zpPTBYa$eO-@)s`Lyr84;=xHE!GjlU}sV

YI4S-Ww;f?5`t34i^$$|Aybq&7z6yt&;p!*MY4thX{B7ec6v#+%tO_*cQo;&&w z?0pLITeRJ89>t>MGf8!5G~&$KrJ1OR=m@F=WP;X_zNkOXNc{w=HnMUI5^@#!4Il*7 zB_i2TJ59%~<(L*yOHNfqjpgYC9uh?Eu7{)g2Gao$@A=+|6V_PQ?yrjvJ> zp&EUGW%^CK%3dXa-4lzR<7I!X4-H(1?9TDe$qmTaeUdYm5gO3p@e@NC&-vv%2zf^% zq&_mtmqFvae9r43~Yxf^-5Imw`|44w{ANZUSec~jC`z8-k4{;$C_`S4;d0aW)vXOnTw zs8Do$^F=BhCChIvihC9BK!b+T+#|=Zs}B)bTQraq!A`H&dIOtdUC(Z|Y80zB0vy3_ z@ZHWeB1-|?Bm*X2V~=z+*SO-+{`lJbbh#o@Mt&5s;QNlQ`F+``K%G1x#x=`X&^>oL zGWc3Z2AWe)))rN`CE^UA>nqL#8dA%a*Zkr%8SS;;8}TJ4>I=u#G;{Q8sLZLm6WXrO zfSqf^>vK8DntdsEkGPcHGP5Wme_BH)vFkz*&r|T=X5`__>l{}dbm{z?>}`k!F{HD% za9S@ugyB;*EdTFC2vrO$X~-$G;_yjzZFG7tW(9FZoYs`w10IV;8e@VHR=X!#KHm!m z{Uhht{809(SJj(Pk5^m!^_kj&fvSNYS~Bc#U{&I1d3X>@-U2`Ik1992MvuCp3Rj{t}3jbCMjxBq5_(A*;JA$px`a;UX3)erN|N$O4j^hG+EWoU16gd%2Yma&=Le{@5iC5%Uq1@D7Sa`$x%q|3P}GzJlJDrHJT*BN>3vwnvRg2a&|%%=5}>TtQSM_8p)}qi^m-`8pUKu;W8sMZey5cmh~0k zP^N>Y@Ut2ytNjg80o4vLcB91ZoxP%-C5dIUDH7T6O&nrE;z<(kzYAICWMV3-SClG=p3l>=6<+SOTf2sV|&n&|vzBTVx zRAh^o@{^uRi8%n5CzEOcvFlmR4N7ZmqJgZxGsEUQN|MWHGv~KjX;<(sFT*TI_1r~F zZZvmKRiCa4dL~LI_44oA7={g91NZ+vv+&6 zSIlDaBbWI6tt_Jjn{poLPay~2S=k-07Qj!Fy@p6l)~L-BwOF6$dX~hV)V08E7^Lj8 zimP_ebETB9*rUvRLD$mkMfJbIQg?ElKJUqhf|Mnk%cG7aH6~^y`h0Rb1*0}6)*IIk zKh9oM0Au!THWt(uwgK)^xF!+ixE0?|aoiZ{k-+%%>;jHY#iD;G@8=W=n83P)M4#Gv z!vUlE`OU+J6LWEPzgE9%H#ztY(&8hz#N;7akrys2BI5AICU+(-jt$-=>KApgQ zV>5nC^)305%s4SGLuZ$0Cy`-&r7M^N(`I29qdB&Yy=*x%Ka{fZ*wpv6Bdnz}p?*OC z=jOTP)|t5?e*H1%3qxiD`<;vO35Jthsdwo=-H3=n2x|9>W;)TX<&*$-cFpD=&?ijz z4wm3ws!d_9I{pmy{b4qmqcpKGNPX zxbb5pa7Wpf_y%=jq9!o{ZM|s4T68CI{q*S#+2{n{s?TyUmpAAm7_(!aWg{#L0#!HAjW|9xXLIqqoDhYg<#=#y7jQMYl0JDDyM zpZ0YQ$H?1d>W4REGCUc1!subN-26;P|G>^CWz%hL`bkNL73$s*aG0E32k#<y}Y^^2IGBwP$i3c@H)P4rj$WJg%c zm7jYqmAF_xzb<+d@sd@(70TchG*I&pxJ5J4+udSi3wMpUzpvu=(dIAAbW-`wAS_pS zI8!#Su?)-P<#@#C#xx)Z7Cm1!S4T9j&$4Fofu9426r5;bca#8=2shP9 znN?D$YD_Uhv5b=v!d8!Zae{n&7!Fjm_t$_$ z4X$tVpro5Hob{#T_m_nH5=-#w8_UW1C;xD?7;~9Tx9HVmeK@D=)Lc~+;&Lxei=^Mb z5DT3|bwI{+9%02Z6os-+xHb)!<5uREW8Dz5!_>#Uu2hu@*?mSl$}CoRYi40iYwc0$NUPQv+87T zwtg=Y9MbWHebXbK*z0(6^u44hnJ7j)T9-j#@>l??`rHey757uli(IHly`wlzjw{xy zTOb)S37pwc`Swh|kB8gQ^Inn@@^?V~jH%u=k?gi_=~e&oUaiS(r@RZgw)Eh&Q9A>1 z4U%xxmTnsSV2J|n*yLc}s47jhpbMp;IxvB_z2KL{YDB(hQEUzU)lWg5Z3hR#mPTao zt{<{PbAL|bv}nyNmJI5)A|J(W_w&E517%UeGH5`DI+J9!Qxd#u6IA85HRI*Ogawm@ zx4;D~2uk8gR%TPGMaWb2z*nsTYtH+k!lW)1Vm5F|dLDB3*6^~^T10I$vEIF`T<&#t zy_jM^=QhguvwuYNtxrDLL#L!^|F59-$ywaIE=Y`fF)Ra0gZ?cWnYahJyvF=m&^4=k z<0={55b;mhgnEshT&IV)uVWt{smusa(Q15Nodo3qFLpid(^IP+jmP=DOk>9cFCf$A z&n|AWMXxzDN7DZmHm!?JJ>&abn@ooh0*&l%$0+~sGw~75D-W-#*h(QE$L+s+c5b9V z%NtX^-DsF$e7w)mhru{pvxy{Z<;}M6PPz7!zO~6(M9M*hp+3|F{p5t!X;JCI?`B?$ z=FnRQ`KNW8H_l8SI{!#wyE3D4P^(VY7lYuD_;SKQ6B1ebX@HdvQw44B@ow&b^k9F@ujXmZY3~JqN2c8P=uZR_u?s z`TqQ7M6#U%7kZAVPxA*`CcOq1)H1#)ehismRYf(Z3Hy?Bq>8*8PLo1zLb!B^uN3Fa z%};R&nv9GJ0N_+ss^KUNd*sxIIl8q$#nWU)jBJQIU>b?)`u)Z2sr(kI_07}{oROTg zye2p-xw4FQ*JHQw%*ZrM_7;h)qavlSF46st(xxzew5q!*5VUkAqrX0uE;ood6w+~*w-kGI=o0)H%Y zc>g#v460rYcod{(Db?9rKmS9yv&9K;KD#rM zqCPsvk=@u=P17G;V6q)`Mz$Kv*1ok2Z|k!aHg$haJA)l)fuNP9d=I|Z#rnkZ9 zle!Rag^iBvVxk=+5hEOvCPGcD{IKWn5YkwC%Vj%Tk_|&ZSb1PGgArJd(z8{-zMS3i;R$+c6NZC4>x*=Bt%OmU&`^pkJ)5mp6s&sj4eHZP-BL$w z?`sZeVLCe;h8jENm&bFC0`)Al2qYrg9m_u?4{;}USQJGQ^-!2~{X>13jz^i>gB7RQ znDBj0ehdX1wM4x}I32ef%Ly9<8Ko+WdqWadpNXuiTXI=XcE5~WcR7S3+kJO#eK>qP zSUY@WYJ2SG?G*S6y%R5i86EY$jlTNOL*#&We+1vy^?@|}yaMP?wwfB0e0Y{;p zWxR;87xpk~9}=@Is%x_s)X|fPwsUUo5bCLxO5G89Dbe&#YKf`|))Cp%nUa5^SsC(B z<_Rgkj3-#yvBYG5kb}3HsA}p%xyAm^D#}S!Kxj1$UI6+SDO;ifO$-<}3~X&6P>+uJ z`lX!y%uip;{%g#Fvv)ygK_|wAFpZyY?~_`xaEEVh!;)B#gDLrC?96C-?5DSW>XvaR zq`32bt4fBnN0hJ7+s}8SBxD&IhO;tVqcnZBca#XC?QAe8=XW|vdOa{);lnQW`dZoL zT8)WNq*;L&B3nPu;XuCw#;P*R-;4TvzfnjpMD_8ieTcVVOC-e>t)$hym|d~T8jiZ~ zIlLjg804+gNh?KO8WUFF6c;J-A8j^n0iG~e$R1~)E$Qjqddc}0UtmrB&9 z!7~a+C+susPb2V^Tm2HQ^-89w7p|){TMS_DVaagI%FACX!8jyBm;4~jttL0bP|LD! z$@)9>3hU^>k;u>HbiE#l8Kf(G9ieP0QE_%3@CIiXR{Uiws~blhmS z5w{N*VYh{L9*RH1%dSRwx0zDV6#_-3RXjAV-%FYN*xh(O2ImUsFYqV3x*GL$^x_l< zH7{;L$}cO7gTLSs-SBk%-j8RW-j$Gj)?)MutM=RzAaJzI*&XrF;u9JR;7NV@b31>=(Fb0F1=CsW4EZcK+~9t=6w5s zX{PkzfCh4mAoweBT=0Hga(u4GrF`src7u^e54s*^*kAPEU#a_GZt;=*y`A=4;*K<@ zi*A~+AaI2!(@Jkxonx?GtgE!sKbkM)zH`=bo`u2oo&^4~&XNOPRD2?|E!_VMSE|Lp z2r(mYS>Jf9ChWf|yAdM6gA4Vm(oIMS{m2}bx7L_H@FD+L{aZFacMZ?BV%oU3ly~Zv z)A8W+nrGbfe;6u(o88e5weW5q{wezy-Y}v&yQUAzsgFeSt>nNyHCM@ZM~mPuiEzA4 z*Qhtk`)Hx|Ai$zgkX^t&$bCqCKxU_S_ts(M%e_?BcT(3TQxgv9+1j%2B~|`S)aUEj zFy7UR?x>Eb4oPkSj33yeOewh7CC)iB#Ac{}wwQ+aj$Z4BY&L>_jHX!Ncw{ipsYZqWS%em)`%Hnp+XC18`s2Krhe*AvSK0aPuCkLT#d8k;4^hwKy}YVWVIn7 z>EIC)T6FP|b6>oqLo+s>GXr@O&$STgN4e``MDJwc_2yGa_7D!av#vV<;1iolH-YkG zRh(Ig7K(&uZq^|?9MhdZx0pALUdU1Vb7flR?n+h0UKVE8ly*ELx?Z;8!gSf^QFN^t zMC|&MbgXkGAV)h_ymi>xyLAg)3p)vYdx=9oFLQ_6 zyId?w&B}r1>J2h4;Y5;~a4Np$!`i4Qu?qr+v4w0|PYO6aR=PPL092gM7VJI!+SOox z#WYxbB!yCur?6r$mar$Tt~W`Dk#`TJw-_wknT=Q#yw8H@FfK`SZIW#}gl~zwR=I2d zzg<#$`c%L`h()ZNZLOn~XLXMeZ&I+lobU2_!Qtk%v2G9t_5ltsa;HxF_i|IBYm}c1 z>=SkeUuByhL99{x#{AEUd`(4$Kr()`M56oXAEin4&5hj|3%AL<3(kM= zG%*6zLGPm;Vj6SAx%g&#&*WON+qW^aeA1f6Af7$XHz^)z*D%z4CGoq_~yBv%bZ3&%cc!+pj` z1_iwa;4m9wC*BRWab0b?+Q=x@zz=6yloY!Nv%i0N32@(O3$Ux;4L{R$=p}$ZeNtMJ<3uw zui0EK3)2i(msHSL>rB8e;>YtWMJrj*DmdQk2%(_CkyS0P7L^aBIx{g8ZgEVN^atWf z`aW4d&o9Gis+b>mKr55o!7!|P*z)KbCEZj)$nKP+Tky#G1vWf>a*7aQ11Om23pd2- z&1BH(h-7Aes*k+t6=E73>e}os1G^*e!=`s5Xh1neg|lzYqOZIMtBbL%u?su1MoiSjWmSGuR(A+e zxAbRT$VCyX%Ai=tA^FjaDfk7=oRox zu0h|88y9_^!05Bh_!l;s0L<~p+3Yok38N~*fFV1}g>t8|Xhd}lU|*frG`G>d{%f$~ z(dAK${Hrww3yg!}hpoivBfgCwxdkUVIj~I1v#@L$u0yUY(J{nNp4))-~HwLLv_OQ3o&wUwpekB$KBQAivEu*5i-d z@6bNg%y0EP_Zxc+l1T~cLKbb6lhL0MvTq+L zFE&S!x^<6)x3ao^954Wwl*zyY`_v;3#dzV6F`FxqiMvBdaX(3Q@LxCB!=YX~G+^z) zU1)gQ?`F)yJM^wZ@WZ9+ls>I(4u_xfkpoKzHp{`ja`Gh0gT9XEkb}+>8TJ2=@}xcI^|cpw^iUDctW}hBbVA zlfK-GmJI>9?C%TY6M>U;)r4Bxv!d>`WAh#S))$g_*3K*QH_pT0rNv@MCB>x$-sYe5 zY;R7>U8A3j`4|gI6(`DWNsyMNXN~Hlf(-xG;@ug{v6QPnk3xN?-7Eop&E4pQ%!8B) zxj~E}hplc%qzH_Sz7Kjg#gQ`CdwvrZAxd_P!$k$Yzspo!B%jiNUF8>`Yt`iPpJ4i{ zW%}XWW(BT*c(LJ2UPH_+W3c!!e_7}5Lq%aKX0(CN9e6|j{9eZhD zshENE5V%oV1X1GPcY#kjx}a`A7P~7(x6}Q>tq@RBu<%i#4`wB?(XPNwdGb5`f#hb_ zvq>YnPX=O^lPBLtZ5b9{fG>4YGpO4vo&WrdOvTEJhJ2(I=LMFf#UBj%x_fTvQ^m-a z@%FX8*q6My7i;%>AF6JPw9dT`&A%tZw{C%vw_}Q{cwHVZI3aj5_6gj261}lLAHW0> zE0hWF%?e$13~n+ISM@7P4Pyw~T-CiBBS(^a=ot6~ie* zX{^)*#63F+p@iM~c($z%4 z_XDs;qnW;R)28LK4-IqH{PkLYf0HKEUQ*8qq?%ftXiPd|`A<81%zqiwaY*Dgvi>FI znTD+i^`g5u)&Qw2`_XT@KG!X*_8W^8?nuO3cE%b6JC;rF_}HwvqdgP{P|tGpnXXoe z*Ia&e58_mYmh496fX&P?<(8-6jpg>c5)%_+2D#yyd_6;bp<>t@XNC5L(F&vYnZQ(mTku{=~)M~AH4t-E6wrY z30Zfe5ft0D>*a+Zxv*HPzAI5`K`PMqup>e3-eU5vwjl;$cTqji|A0LyuK&4nFk^Xl zH*M*I*%WTCVx$z0VC22P(~!1-a(37yE5M(i7?qIXEZ~3EXVVK}oRamKG4h!LQjx{_ zCHkUhR_x6QhJVVZ+tjS1u6$ zd%9QFQeL~O-vGmxTD&<@6_1tfP99#2LEn%?LfK~++fB4GJxMB6(*g58{<-zqw=6EJ z6*ni=s0HEnMQrUYRp%A5V1AQBCE4ufAU`V^cu{SC_^sWqg3myh5u^Isc;q=ueFWwB z)2|ruA-I816Wf}(&t>a&U_HgW0=tPailQdFhA~kWY+vQa?2imT)VmoBF?<0#_x|6> z`9=OtHgq`V%6k_sFw*_U1!x?6OA}!WmTX3G9E}Mn#U^b=6@YCCWv=d~U2+Nvk+U)W zkVk)9Ce1>jyTKr?3oDKy5wXZpkU@sv^K}vz(xBSp4p2&o=wT}^bfc> z6VT@Iqd%_7gTKo(AIy#fIhGZ^xH~jP!2XR9&Un(}#?x0!(65>e@5Kop0IrDG=%~Dx zH=V8Gq{|fZ=rtmQ?wcIgm}o>iU{-YNf=+5H9f{fWKw`w7Z$uUhg>nb#e=t2@fffJl zI1*%XV&05T&2_g~oNwl63l~pHcvCL&n~P8#vqy6P$233q8KeiAuUS5l#q}E%69g_YQzG?f3qgHhq4Wdu$8guY7r!`{i_%iWT8)Y_Z@u#P4-pbL9h@)= zbpooWsVm^hEj$e8O!3tN4BOLjX);lpy*L`M@u1RLzMC{11@YF8D%>l()B4XsETC28 zlNfY8!I4*TrH-!hy$D~9E1#6!RC_oUX!w)QGUR!46kjvS4Z%zX@|x5fy<3FV52zR+PO6hy;CfeRsTpRR08AC@)|u%Y(uts{#LJ)AdzM zq1O@!mFWnfTC$Xqiv0XZv78vdON((4Wn;N9FpPTpz~3Q#(TQ9TOq$kotF zaL<&$g7L9VKaj{)c<8*LnyNpNZ1|hx0i{#rHkEeij< z^LOFmINJJ4rt{7n65GELKHPbvyUI#VmQ`*j;3e}jsph}v!OH}-^lMFfd>Zc7XbSbN z8sH3+d@f**^3Ied38vbtlnJ@U0;hUTDBY4P~+zT2Rf z&`vR<>E4seo0GIGi3{ojo7uaABO27tEMmOC`|ia0#lK1XPb*#R@xG(8{}ukE4SsLm zdJ=GFvyp*irYD@%bE)eX=*RqfjMa;WFY~CS$G<@~q&8HaJ04HGiFS(_MJY zg9njqP;!!+f|l5za)7%o3DLlyG-J596taK*yeT5dDx+f5T0Oty;p$jZZV6*w!Fmd1 zl{;4`A-teW>$PglLVfOYf0K*5TKWY%|5{60>AwYx7uOE9`f-eb5^I>W5V1FiKl99S zZ!>kquAl9-DPOxcW*YdN9oj#j6_@>hm@_cU+87|iGA;pzZ*)`gDzs!+5dWMVOTTGE z-TN7|;NjR5z)y}_H1!6`I@qf7i3S_K=s7X}l<}GYth@P$+RWm5_V_Yvf_Z?(R?|l{ z`a_kM5R>dtNB;T_wv^}Y$!`->pUvFYayjS|8JH>fZ)T!vQGfCW6c>#Q=OpOEpjGjYqtf9<4;fg_SqL5G)P2_h7 zM)fo_rkhaBx&8*-lrwQpSc&^MXjC#$V@cn+15HfEHRFeCE-6H{4LP`e_qUiNx%CZn zn_O`BpU;idG|bkXDZK)74BW;zsad!u{r@yjCkn98eaD57Wu~?J+Hm4=X*A5m^zZ)D z`PLl^83UKm{b`;#)Tc9`9;D+#cB0&IDfcC?DCVCi65a|aiJ975Q4h-{H>-iwpsjRk zT^dc?>4)c~w-sf6`pW0^Id`LIpBKT4ca`NaTocAIZXWv}90y*W-rzZU|4&a+nQR<| zcYM#^NTnIDsMxXSbo>@-acxlGcZ#r{%DuC>-YH3)hY^0Fjqdr&yQyE;PMk3Z3oXT=1{m!0^;=B`?tJ5c14h80D$>Mx*}%WC`t@B3T_EpSS*^(S zx;O=}rNnRM8Pc>(mJn9T6hb;`{>%pEa<@y)59h0#2q_D2u zh@PPiAIKhXF!|H=`>5`mvXvvmpZW64vvY`}D46$5<6FLA3?^5q!r&2qFX(3cAFTwZ z$P~NKm7{;V%y-90GEe;PHgoWM9-CcW>&P3Y7ma?aC2^0jv8)nv1r7r-7ZKo*66jnrLxH@x*FMH272lG_G4cX%} literal 0 HcmV?d00001 diff --git a/release/aroma/META-INF/com/google/android/aroma/fonts/small.png b/release/aroma/META-INF/com/google/android/aroma/fonts/small.png new file mode 100755 index 0000000000000000000000000000000000000000..adbdef4afce7b725e29da1f80664df1ac150117d GIT binary patch literal 5723 zcmV-h7NqHkP)?!r3miTMDo66@}a(D?I&w0Pp7@gf$A0Hp9&xLUf;Be_oSHeAjmru>ah7B7wY}l~j z+2aAgBhJ@>?$PN|YvSBIZqSwW5x^0^ZiRgJjbSY`FHxr(KEK$b>tluLf7O5PgGXT}@@L+xkLBD`X|96zQ9BjH{fO;u`{x73{YlZiLnpVU z@DYu(T7M!q&TM^0yhe5E$BN>iH7%g!p^Bfy^R(_N@ghE%KI$KtbFN@K7LQ3>+kb0) zVNKdz&RAJed)U4-2ubcRk-aR#*5mV@oF;MmdDGETA#|s z%>niPT*FuUzkfcH&es8a<4hWB=CKFxYXBbtcpJd`=*G&@`TiHDZKA?jXkMaDH@x|{ zg4Tt;g07EwP@ZM;&N^sZK`c1+YH@-B21Q1}3;t*#xW;&5C4HOcZ6Ak%*iUo?xsaj9 z>JD8a)x34KjHGXk2~OA%d|6vPWNYCX9lzvbhe7eY=^rZ33f4eSb;f>h+vinGdHz zaE(}ot9G#Mb?9kFGN%|mOH!V5SD7fQYBDlICKr~%Ie8T1V}Gf9l_IXfT4-LPPTy3l zwmSBj!OBXnLsN!%*aeMQ3k!2s5a$|*6kr@=8RK5iDZ$4|qq0VU{eZCobHrdplL!00 zCRC~96Py5xi0jKp`nH@tJ=0LJd+5t#6=Q`_qXxb-Wl zH9=O8w-@V>3YRisGUG@oku_taM%RvkeM9^y{8})N7A13zfe5r2aIFR+4FJC?(_$bp zUSxpW8Tv(}KL+mr%|B(A8guNoEoG)GvV5;en_;a6L(O5^Y9Ioq#=nJ~KO$!-og&dY zTPH`H%4Tm|dV`VhbGrv+iZ}jz|6yHc&Ro^!I2P$-eQLZe2I8gjJ%{FIAkIh2u9D9K zGC36)h=kJDo3OTl=oN4ZQDB(-l(I*mymxWE@U@C}w899HkNtg%dI$8Am@;078yA@D#^;Zxp zKE?gcw#5=uGOsFOiZ{DrHx(2-Qw>E`?+=29L;u)uPp653Rnj7*JL@lA2`0T3V?3kF zF?81$zm+a=-4JIA&9x0g_8X)nM?UXdJe$_eInldf!mN=646@I+EuF|dUFKBD`blXBtG$0PVaEzD=YYGXs9QvN zk;h`mxaI zz-c{`SG$A2mLW?Yl?6C$CpF(&nylxn?QPrglOXN_^K|zZ??NetucM#?S2o|4sx5qY zw$=S5hOPFBRteH_;U+R%sk3K!bLYm+{O=!ChmoC9GZ0JVeF$OGy#wGA4DIp>fOnQM z5DSJue}&UdYK^1pAw9doGRHvNiFXP#2n)umeF_C*!4`Q^Ir;ek{Sw1Ku6cehVIWcn z5ZUT!fu2l(=>}qEgj;0Bn;leYfH996)Jk3}lp?EETa_Xb)w6Gtdl6TK+5D+2+(J8E zvd7aR@9Miz1<(Jr`@P3_(y)q$cOF?BF-*)+n`Oq)oGp(nbQP^74a6yYw$NPDK(yNn z=g_Aom1EbBd+#JDBKh1Oa&#bZmDa(+eWJTKNzFpMu-R=?Bgh~cv$rXx+Cj}Olr#a8yKc|euL&MA~z zYB$IpvHSzZdIk-0K9pmg=O;H1(HV!4P4>va6BY zio_53?~#AVZU=BHH~>790%Ir7$a86N2?Nm&o@~-Ah>f+W24eP|Ci{V(L@fN4A2q

ji-9I#CZL7uw-|%j)ph8{VUpzffO}Ff_h2V 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 N002ovPDHLkV1h?&Vh8{L literal 0 HcmV?d00001 diff --git a/release/aroma/META-INF/com/google/android/aroma/glitch.png b/release/aroma/META-INF/com/google/android/aroma/glitch.png new file mode 100644 index 0000000000000000000000000000000000000000..ed14cd64c03141902b9737b056520f748f3ea50c GIT binary patch literal 196355 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�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

  • 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 ap!hrv<3p7sA)K*+8 zl6CS}9(&Bp>mR$rot>Q_mlP=$1;4-}XWn}=^L^j>{eJKF-VSVF0~^@D1~#yP4XiCr zCE>N*V&vi{YhL>ITLOnqC6VjR2|!Zj?mhC2|Jbu{;@x|IpRYGB zZM_Kq9Be^*a3K0b`=P-HrJ4|WEEWq*rK;b#H2><^S*-Qs_J6{RPj<^4ox9?X$|@x= z(nvimT6QJx{z{)bvfkX*-GWXfh#uP6^kTzk;v>SG764cVvZgi^${LBt<k$io+$dBkKw2UaYwT*gaOvmDuzvQ|v{(Pt#SL?@+nWgW4L6?- zch)zPn=5T}3*#k}0AXa%8zXx6j?K>9~b((M48LD z+NG9}CfK&AC3NYE@&07?U;k@nZ5OjQM4+#2m;Kuhb$>e)uWrDY_nWVLP~KhWl5lNR zU;p&gx4w5)y}L>@J+bBjeYKCsf$eo?V*9on6vnj32NTDjy$>m=bvIZ!wEBiIUN< zy)7C1^jh*?(;daH57O8@)N~>gud640t+Y`93arpoUVm?zYpHVk(KR?S6h_W$F1Ic- zgI*mD$8YL5{`GV3{phKm@vF5M!(dS1Ak3S=lz$`T$C?QA2U`h^4b`3qZEbBW%XvH~NZ~zGi+py7 z|3VFfF^}F}U)9&&c=G$Bw5*u4FS}L7t5CdM`Qh^-EI} z=_wjUdTt%+uKx7F=0((80ajh0hdXKQ+ur&!s`dDw(BX#3lqs&iKc99YU1Kt7!byb-_0GTO5$+pDMK;tt< zn+aA(c}c9QK*xvWc-zj7&&r6kv}-vignR@F2Q2Uo)8$YKL0U8pcO89ZMBe#SPlb

    6LX1|bLsy*o!jwgpufR&r?qjn%c?!|i7h)go3YgT=6F z0^JuE#~MdFZx=ExeD`_0s+Az(;}DUMPyXX8zJgpz)D3rUKhUl}a)0ObFQryRpcngT z>fPV@6+IS;kV}_$Sk#&XRblTAHIZe+ARDFu(x7v1?-LJg(MFbcaXGGApg$fac;Alj z(=|7B_L7~ce2Oh-A`sL>y}Q&zodPLPCYV{2kw#_bP}x~jW(Jj+0lQ>pAa#*YTU|?k zvg+hFcTjsh=U26d1wCYpp`K;#t=1*Ud!oC^s;6zYVdttgt-v6bI>Wk0)D zGR_qVw66ti`%vAJk^a^#WM_Q)Da%4-=226ZP?vuR6X#%l5|oiQfx^>uO%Qb1vXl_A zr+*J&+@c9dxrhSDg5FH+NEcuJ<|x(69qY0MdN=_u4vPaVQJ zH9G}YK7h;b!}Jv}GDT4wZ(4}_##q25kR~A%6h#*kc#GsHLO86+?gKE7Xz1tgcpLY8 zHnF@hFI%AYC{_IuTINkFrciO`rwckd@VRm_-86KnD+>VtPtSI$Fr z-g^-C8+O%cJ{A-Viu|6C%dJWT@G0)Nq-LR}i@~8dPu`y!?tE9j( zQKo^Kx`uV`EL{6ApR4$|fDj&WVj%`WKrhWPH3?xm26>3>c`pz5T{tg%P1D@VZ=4+A zmQ@$%^e~aWEp?Aax3nfzdKxu5gLVEK>e7dh%ajhp{WcdF1R@`#1Fm-}3$vJK407Dp zcLwtiNo63|KrEi%=@&*S%djiXgN`J$!!0*;+>bRY)P?h?=}8u{whG937V>?Xs^QFU z2brEJW}4v;#ACqaLWP~z(bEqs;os#dpX`ZqW`-3@SH}@CRk2wbwg&m9S1$N} zO0%Sky}Xxg?Y%rE<|YCvOQ|?ZxsZnyx!ul+NM3$R@Y3IvbNtw-#xuusw5!?T62o>C zr*%NlWo5xqq^nJWut3?@&mo%nxp&7De+9g{B7wfQi<+CeI33zdi<&A9N;uyllnl7c z?Usl~N(z2;3I6Tv@-IHxVuc$@N?nO!C|VH0A&3x#HYYzje%Z$v(CevA#yRkJNpgUu>(O2>ZSO21tS4-plX3 zdH~PeM^Ac(H=z&4`Q7Ry!AN-&>PhgWaEx{}>HT0&ad7p)Uo_zuoB$5qtkY0iu2OQd zL?~k+NZUW*E05<1sH%atTr9)11l3L?q| z_~lPH{ikp9```NSd~Q_YVu#x4>>A{ZkOaIwYAdk_*BkUK?$_XMFU)YdVWQ_u0!E?a z%!N9qwfR0{DGnZW3-s&*6I2@726*g&essZxc@{059qog026 z-RDk=a|q`f*L*m5(($VF8IziUa1*WZIA8qkp8W3Pf3BGuDoLU`VGDGdeG~tG`m?DR^s828U=Dq5D`YhTH{8#A} z6y;vcJJ)Vr#oc!nD>a3@I8T#JCwg;?T^&{QNU^+K#{Z8{3UxWd`JY_mb*B-A3S|R% osA#R;y(y|_crLW?_XaVQQ&TdYtVf&{nXP`o%4 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 literal 0 HcmV?d00001 diff --git a/release/aroma/META-INF/com/google/android/aroma/icons/apps.png b/release/aroma/META-INF/com/google/android/aroma/icons/apps.png new file mode 100755 index 0000000000000000000000000000000000000000..ca75fff16d2513a6017d98fb25e4cd5b4285959d GIT binary patch literal 10928 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 F697V_1YH0C literal 0 HcmV?d00001 diff --git a/release/aroma/META-INF/com/google/android/aroma/icons/battery_aosp_green.png b/release/aroma/META-INF/com/google/android/aroma/icons/battery_aosp_green.png new file mode 100755 index 0000000000000000000000000000000000000000..bfd824b9493c0ab3fbfc8e929c1ca4894c555112 GIT binary patch literal 528 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 literal 0 HcmV?d00001 diff --git a/release/aroma/META-INF/com/google/android/aroma/icons/battery_vertical.png b/release/aroma/META-INF/com/google/android/aroma/icons/battery_vertical.png new file mode 100755 index 0000000000000000000000000000000000000000..9bbf5251fc83e0aef851f70c67292c32345d1c29 GIT binary patch literal 3208 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 VR34Dh4TDwzNQAjTjh@@R{{W|&OvwNM literal 0 HcmV?d00001 diff --git a/release/aroma/META-INF/com/google/android/aroma/icons/battery_white_stock.png b/release/aroma/META-INF/com/google/android/aroma/icons/battery_white_stock.png new file mode 100755 index 0000000000000000000000000000000000000000..ba99de5192e2eeea3765ab528b22865e6a687473 GIT binary patch literal 1130 zcmeAS@N?(olHy`uVBq!ia0vp^J|N7&3?x5zE|g?oU`z_|332`Z|34QO7at#=u&}VC zq@(*`Cwr$_Oedo@dt5>gHx^(IC<;zc;II(~K{sRXN96o&b!i5VL zFJ3%%?%ctH2ag^-diLyDAos?N8`rK~yLIc({S8e*6Fi?<$_TZa_zrmIV0)Gt9&e=EDHcFKgDU z0eS%w0A0Hi=*0cUAm9u#xO@`|fDU>F18;!f^XH#GQ`el)Wnf@(@^o=g!=jA^xdo^3|4<$A4>gEcYq0dz<&o z@8hEa3mLv&>i_OI*|B+|J*jUp4@Mk&Cl!~zSyjMUj3tRPeMN#~w~Nx^+qb97 z+;ii(ER?x5B>Cm4Bd0Ta&5wCp*qCAR>uO7RU}`UqdaBH6zY`nO(oaX|i2Y7Gl;HE@ zgz?UWx+nP0QbuN}9$LODW*w<*yPVhlBHid`cZRz$-+RSr8=rd_uSzR4 zF1Ynp=o*j;c-RzMacCI}R> z@K9gnSLh8C6Osj4%9->t!zOT7Kxt=m+vUFWGujU}@NDc^IwddU?jyScndL5DY^VP6 zEmTBv&tDEu`tU8_Y zN{{%$Rz}n-)t^zGQ~AZh{-N`yIY9BLbuD#|%}*A@o!$6r4$thO zZGUp^2ivglYx(?QSr?XNa&1ja;Wu^DTgRL-KiKHc5R_JE?YX(Lb)(Xc^??lU<|i9I d0LFe_w$9@%s{RaavaDGB`T6;uKYH}& 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 z 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 FV1oIWD|Y|@ literal 0 HcmV?d00001 diff --git a/release/aroma/META-INF/com/google/android/aroma/icons/install.png b/release/aroma/META-INF/com/google/android/aroma/icons/install.png new file mode 100755 index 0000000000000000000000000000000000000000..44caaf5d553bde9f584768cfe76caad873fd6041 GIT binary patch literal 5577 zcmV;)6*lULP)a|*=%-pcV>5<_tkyQ`T57`)3@)P zJ2Q87he!EKo!q{Cd%915`}_Nz-|u%$uM!cyPfYbB(Jv$hE;wEBu_n>jW_xX*T!PiDb6}-t(UKT(6XRyi)2M?s2PWtpSuVMk$n1 zTBEhr#uybo6RnNW#w14T)FdV`;b5bc(OMg=lu}A*aMpY8oU=Cfrq+7k+UMVN*V=KC z)S~)*B&}gFh}S4BAf7$5LG8q#TW-1K=8G@B_^ne@Q+V&s1D47K3!tljs{qwd(^{9G zT33J5fj$bv3%=<8#>NI4o&I}|{`}AW?&*g~jlxPwc2R<@8(clbYlWC(Z!Fptpqp>L z`GpG$3m>`i$}4Lk!hX8qC`j?<<8}mRbi3LBs{L}#@y&036PgRpzViBO@9!_8YC?ay zL6#U?BgH2gpCpI^8WV!Ft&3@`f2`GN)c~xu=Z3@>+YX%A;tdzBSbiVJI1#~nkM|y9 z46Rm+_1^juYAwE=SrVhLeT&u#?;Of#ln5w2xvOmpkQ6;L#(c-w6F;}Q)>bA}_eTaf z=YRmJNs>hONR-E*FM)?C=24}b{aGaP_weQ_}&gQ_E#h|p*>_T+lwLWJ!EdTaw!#l=LV)WryvDmjAk4r2fX3XRe#FbIVb zki9tBjtm+Hkk*>x$B(nQxjFPCce34v_Nu5-NzV%F@_{b zFvgIkDYaUSG)+nC4I1@2Nv%$jB-HCEX_~ThW`(2AdM2-W#mnjS`$Ojz0q;DCL7bqR zMwCXh4uGM-7?j!rhjwHTK$0ZocKn{_IjgIyq-nYZh;iHFVw?d$NdPDb03}IEn$}2? zI%%y=n$|FB08J&D&32b=KOY+EqruZbsm>nOzOx?j!qJ?eny^K^cbxY z@hI=SNpNU%Gr^`BXA&ez6hW-_he6u`RAtDJND`C~RrxHGGHh2Fq|io%8>Q?#5MmoI z9`P3IG)m_v1dovS`#9^ih;|q>z}nm;4QwL?rI5toFS?j^yG>o0aQYn-VRC?Ce6bTi zRf?Au6Qy|9A#x2*Io?#!!pIZ;OyYmuBiaWxxiC_R2ub2G-s7?iajqDes;(Otl-tbC zX|gOqjwgTg*Iqh@9z3mH{X+-e{@;M=cf<3V)V4h|ju25mtAbj!QH?3MQw+~)uutm( z7|=TG8zQ;@MPw}A`ll^}`3It%0|GWvNJ z=W>kEBLHc<_gI^Gz$v}yMWiPlK(!R=)_YF>`iH-;`1-jdom_*q1t^YOWjs=8RbV1e z)u6G$qi_*5_@&CYpf}+C02u2W&Uw5G;_aNp*_=*0qutJMF2{R^Qo~Vp89?T_1+39H zFJ7F4WHyw7)Gry+y6^5&Z@T`x0g5g*3QiTEs*Uc8aA`GQ%ectf<~ezuAxHs~MX*?B z5rn*N>2|sZJ-qaBEn{h$;^%KS~X%1at8e-OZdgzWaJw({+CT4WH%7*B;=v|KcZTwVJ%|ckbfu z+aKYwE9Q8^J8$6dWpgx|3GaKyXIWqEmKUqKySK_-_KZhg@uk&wyu@ZS#k*OLCot6) z-3&zvl>WoJ7vFNdSNSWCUh>|Pdj@Ed3Szb7P!8=yH&pyK7^uQ8B4wr>t-mp1bsvd$m2 z-WSzIUw|TE5GX|tK>ZAoeDMp5Z+_MFhyV1pap&C8#db?Z%ip(guQ-ZV&oZQ63cB5l zUN;L>E$isE`*iy~Z0-P$cb?5|n{Ky9r{5*d^05!Eh@F&kzU{^1d|-{2_!+i`o5zbR zc+bCl{=}RA;Oo3~i+gMfP<2!p*LFs(2!X;wEASisoA_JQ1_~K<-r=1KH$@?^J_xoH z+ai8^zpBSdI6k!EH|LR}`AT!n*>l(Z#B*x_=l8skl}g@)_9| z%MmeHj?4q0c)EUYqk+8vAdyNx3Sc6;M_KMg@OTx^S9L2XwgabwG7X+tQRYS6q_w^t z`0B0zZO53c3>synD%?u8{4x;oV)#djnF(JE_r+87#myJm;bZMte8C>SrEd{L5kFw1 z2%-vjWB^zUF9z5M%BbT?$;*x|{Mnt=E}u7p;+3S5R#3Qqhy zaZ_`zyW#Myr$=$vkwM!56gxGlMS;e|5PHiossOR9I{p*dA!YPLpq({bxN?kx+-{j9@PFExc2j{t-b6qSo4>c`Sm-DUrS9tVWYozs1cJVIEg++jrQkA~?IP)l8BKre-5~Gi$se1K| zM{fN$fVH!zx%r(F*B#>^=Nx&SZ)rn9UDcx@WCr`k#!sr6qz>lT#d{ukXoCw6w0Qdm zp36J`>Uq5Kx2_}4ZHQw;aNd&VdC8)oeiiyASQX_#A*8AL`>E;LwKpEQ_22NYb_OLA zR2Fv>Y3CeSmXYUqxj)bIZ3D&9ePVu5DTBnwxd`#`rK?GquVvkwZa3$-FTRRb{pPcn zy>N=ti*2T6Y9y&DAA&C)oV9i+sSe+r05sG2E{dkn(y!Ibn{RsD`)>tUTR}&qOeUx- z?x;c5TKfGy{bKe2AWhSi1ax3)vmaLzV^($-^h0Q&A9|vHj(Kk%r{EtO16d}qN<53rCSZ^LgDaEJI83@mtTK1FM91Yfa1)ljiPoP80LJqUTY>LNi>d>S_7GIXC?D<-Fo;*D*Uk#p%WM5WHzqjQJ8)94Nqhl!lr4Iw*xv2J3Rp zw2#rxSLxYRGTX*U7D~I490m@H45H`g5LwwMvs9{Qh7DJv1*7xYEhYmrnp%;I#sOp?Fj6EJ&Up)9_pq99*I|AOgGM6hQE*DpE zjX!%Or;fKnnN)J>$vjiFDOTGnWpWubD9oVrZJW)`X}b9ttm_B1DMJk7V&WN7i86B^ zWMBaJBG|GMIoB=#MfZyFMzpc11_L%#XE=mHivTGCxDyYp(eLGGBiP)7g5~vNoYe{5 z+hT$d6oxF{WWBdY$F3lfqqRXP4FXOC6(5d_3p-*74$ADkV9sR+_5q;LNIKe1f#RTZ z!|vuq(4wfN2_Jp`S2%HOotM1z2WidJ$vZW`lG`3yCnz+T?XuBbq@A6{<1jiwDTDW* zib1KYc~@&ZRQw8tG^i+nr0mgljDuVyDU7xqgSN9c3_CAq6+pV{U%$x-xOkF&`vl-v>z!b&djjWs7!!a&!}JBZoX5AhrQhpSYTf}PV+@j~cwfaSFj{Lx zEin)85ubAq=`jqdy4QB!l~yRDFa}z+8jHs^dG~8R%_F~>@#8OkEUw$;#PY-R-CAWT z8IqdNU4c)3@GM$`b&iFF1+KZ~M?y_V2C2r<@-nT1r~iE6s@_)=TF126iIX%*vjYb% z_=kN3Xs<4|onUJdz!Aa-qE)CQI_vq+&7bAV_g=zJy=D$G(?eE6Nm7b(snVL>Cj9#+ z&lG3%JnczW@Vx7uPcB*6mo!aTI{iP~{x>K7_CNmjL-+0#i0y1gfULD+lhwVfx>tHo z)=0F%RAy#%>d{8?#m}GQp|7voWikpF%l@SO?mm>IS*&(B1*swcHV1tlD-H>4A%dbU_4CV@Qp`sIdAZ ztkE?jI-%Z7Sy{^Y&~HD=9Uoj{YN|%91-W%aDJ0Bkx#GOexiUx0vaD<&n-39m?hzl> z10n9*z?lf3(OOWJWfO_CNGRWl2#MC1V)!4LxbvafmuQ2jDUww2nU5{=!CyN`XW1}! zQG#_2ZHSW(0Obm|YAq z)+nvZ`nC9Qj49$DlNcVpzs)UgJkD3|>~rvvCab4hh=pVQdE~*xK33D9#j{`x@&lKi zJ2)`GFh3e7?rmXtoZS%6#d6b_)M_1W+Ie&l)5NNx)|y_|^07Z&2xMKd5EPzbaC@Oe1^$YH2^~@>v#P4qW|dJ zT!{t9IznAr=-ECKhX56zAi*!f3;#3Gl;9F2-7%1FP1_!!`7G7oe(0 zkJ7dpSx;m|HF4_#&OuqE3LiB`T|%Q?r*)`Bt(LO6u|YFyu)elRtyZJaXbj!pUak|5|DI`3bp=JY+Z}ss1T;w! zTCG;O@64GqIBQv3Un4n{qK%>7?_*4YF^)!~!RE&1mRCHx-R`!Gi0{)*O-&82lb$fb z--}I@i$S>AX0yrC(h|L1Z|v)s)>;l9K8)6ye!m}FwBN^jPrujW!3V#EbvcPiXttUx zToPE-&%+dVOeY$R23eM|va&KZ)^g47|#_@Ao--_Uzb> z=XuV;!UCI{n`~@sV2q(&uT!hnNKC?JyTiuDCQ2y|9z4j?pZZi<%_jFh@C}YV`Y5$D z#W~0P{5x!CBUCu0l`Jn#TZOH13n?W~ld+wHQxzFw}^(OQ#d8MCu9 z%+Abm`Q?}Mq$m9V7hX8e#TQ+~Ki_s6r%s=y)oPV*Ii5OoihJ(4hgz*R_J);G<$JT$ z0I~Y+>VDa-YZOP9x-2d(?s&qOcU9RZgjv-C2M=<1VS)LJE@paWhJU{8Ha>O79W)w^ z;p0VET3Xtb4dY%9ove^IxlN=&d%0*V_E$}7O}pLUOJDvn-+uUE>h(Iy%gd~-tuZw< zb$!xwiAQ&eggyp7la)aW1WLV z#(&oeW=g5gE2UoJz29He`wm!`S}xx{d}u$Na2lw;5JN_GH05{!q)60RQBC`JuzCWgvQaNzjop;{(iG4r$cOv@y|78CM XCWCjN-V2+b00000NkvXXu0mjf4sz+Q literal 0 HcmV?d00001 diff --git a/release/aroma/META-INF/com/google/android/aroma/icons/keyb.png b/release/aroma/META-INF/com/google/android/aroma/icons/keyb.png new file mode 100755 index 0000000000000000000000000000000000000000..fdfb11fe0d490d1230738f7ad0c17e6154848cd2 GIT binary patch literal 3131 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 BoMX)O1hJnWw6! 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 literal 0 HcmV?d00001 diff --git a/release/aroma/META-INF/com/google/android/aroma/icons/personalize.png b/release/aroma/META-INF/com/google/android/aroma/icons/personalize.png new file mode 100755 index 0000000000000000000000000000000000000000..c6f679800bc949371451f679000dc16ab8062954 GIT binary patch literal 5741 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 literal 0 HcmV?d00001 diff --git a/release/aroma/META-INF/com/google/android/aroma/icons/signal_highdef.png b/release/aroma/META-INF/com/google/android/aroma/icons/signal_highdef.png new file mode 100755 index 0000000000000000000000000000000000000000..d25ac4f0667c7c6c4bd50b0915c3767c5e18a0a5 GIT binary patch literal 2497 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 literal 0 HcmV?d00001 diff --git a/release/aroma/META-INF/com/google/android/aroma/icons/signal_stock.png b/release/aroma/META-INF/com/google/android/aroma/icons/signal_stock.png new file mode 100755 index 0000000000000000000000000000000000000000..4f2a6b8b5e1dccec859822fd652dd3de41f3e939 GIT binary patch literal 575 zcmeAS@N?(olHy`uVBq!ia0vp^Mj*_=3?wxlRx|^tEdf3uuK$N1kPu1V19ZPlNswPK z!{PsDX8xHofAXTw2hJa3*|>*e*2?U9=ih$=mEL{QHTC7W@kr$O#KqU_RaMMcT^NrD zdfPHPv6*=AI`T=k-kxI%H0PhEi(`n#@weBm^EDZWuqD`Z34f1U@E~r-^WXcYPm78c zUbDPY+3=tFoM|-+xto^#brxpexTM8$y~X4C)=%6!ower*#y*}p=YZ~>8mB`w32VA+ z6rCPFWRCMQ(0=Cp#b3bo*HcmD&Yx#hl~fz%*TuN~ai12I%qHjf>kWHOc(m0Yu+kKH*)&0} z>x*mBW41EuH*3Du8Et6c2}seHB$$_wtT*e#PM>8yGmIq*I}0*x;{!IvXv$dnuQAtR xudWu{z4y{>W6KC`_m8r+@BIGnpZ$9dW3GsJ(KLnib-<8d@O1TaS?83{1OV#BReS&d literal 0 HcmV?d00001 diff --git a/release/aroma/META-INF/com/google/android/aroma/icons/signal_white.png b/release/aroma/META-INF/com/google/android/aroma/icons/signal_white.png new file mode 100755 index 0000000000000000000000000000000000000000..23d37cfca5b8eb3d2163b406378b287a00214cec GIT binary patch literal 2574 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 Jtj+|V@P97c?9u=L literal 0 HcmV?d00001 diff --git a/release/aroma/META-INF/com/google/android/aroma/icons/weather_sense4.png b/release/aroma/META-INF/com/google/android/aroma/icons/weather_sense4.png new file mode 100755 index 0000000000000000000000000000000000000000..b93f8f89482050c49135ee1f3a3fb413d2dfe4bc GIT binary patch literal 52273 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≫wk+f-j)@ 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 CtOP&+ literal 0 HcmV?d00001 diff --git a/release/aroma/META-INF/com/google/android/aroma/ttf/Roboto-Regular.ttf b/release/aroma/META-INF/com/google/android/aroma/ttf/Roboto-Regular.ttf new file mode 100755 index 0000000000000000000000000000000000000000..43b3c4fa133bcd96c3d418b20ed5c0ef8c21e964 GIT binary patch literal 172756 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

    ~8&J3^=(A=Hi#YDWmQBZS%!LhT5lc7#wnLZ}@f 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�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�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

    @7jFIr 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 literal 0 HcmV?d00001 diff --git a/release/aroma/META-INF/com/google/android/update-binary-installer b/release/aroma/META-INF/com/google/android/update-binary-installer new file mode 100755 index 0000000000000000000000000000000000000000..2afb7f6cd734600eb9ae172c2bed738a50c9170a GIT binary patch literal 232504 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

    L+WIYOwnE)<_it&54it+ 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ñ~~=zoyPDt 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 x`+ mpdecision_bck"); +ui_print(" /system/bin/thermald -> thermald_bck"); +run_program("/tmp/compatibility.sh"); + +ui_print("Installing system files"); +package_extract_dir("system", "/system"); +set_perm_recursive(0, 2000, 0777, 0777, "/system/etc/init.d/99glitch"); +set_perm_recursive(0, 0, 0644, 0644, "/system/lib/modules"); +set_perm_recursive(0, 2000, 0755, 0755, "/system/bin/fstrim"); + +set_perm(0, 0, 0777, "/tmp/buildconfig.sh"); +run_program("/tmp/buildconfig.sh"); +run_program("/tmp/busybox", "cp", "/tmp/settings.conf", "/system/etc/settings.conf"); +set_perm(0, 0, 0666, "/system/etc/settings.conf"); + +set_progress(0.6); + +package_extract_dir("boot", "/tmp"); +set_perm(0, 0, 0777, "/tmp/max_oc.sh"); +set_perm(0, 0, 0777, "/tmp/edit_ramdisk.sh"); +set_perm(0, 0, 0777, "/tmp/abootimg"); + +run_program("/tmp/busybox", "dd", "if=/dev/block/mmcblk0p14", "of=/tmp/boot.img"); +run_program("/tmp/abootimg", "-x", "/tmp/boot.img", "/tmp/bootimg.cfg", "/tmp/zImage", "/tmp/initrd.img"); +run_program("/tmp/max_oc.sh"); +run_program("/tmp/edit_ramdisk.sh"); +run_program("/tmp/abootimg", "-u", "/tmp/boot.img", "-f", "/tmp/cmdline.cfg", "-k", "/tmp/glitch.zImage", "-r", "/tmp/initrd.img"); + +ui_print("@Installing Kernel"); +run_program("/tmp/busybox", "dd", "if=/tmp/boot.img", "of=/dev/block/mmcblk0p14"); + +ui_print(""); +set_progress(0.9); + +ui_print(""); + +ui_print(""); +set_progress(1.0); +ui_print("Finished!"); diff --git a/release/aroma/boot/abootimg b/release/aroma/boot/abootimg new file mode 100755 index 0000000000000000000000000000000000000000..fa4bbf8dfb44410abadcfefbc47284f432308877 GIT binary patch literal 76392 zcmbTf3qVw5`ak}jGiNRg0}S8=5%bKTg`hTgDJ-iI$0ML6UNW+_4%%hV+SuCtu2#DZ zpe33ch!tw)ptb9z3s`Pa8KkvccfU}&KQmj;%!n7TIuyomo&V=KGZ?mhZ-3j@bIyBt z-sk>2?`7O4X3dp2j$;FVc$UWKtI@;Q6g;c1(%SS>n8*aQC9rs{UF(lN45i7yX+=+! zRu*ozVq8VI6c1x8YZ_yQNc;Sj-`+#7zx<=MqY|Tvvw%}pNw`!4Fckr9R0jWvVO}4z zdIN&^j9+j(;~$a5T9Z*|ZWGE7loY~)`k_>?3Fm%Q>la~pZe+;=jT~|;7Y);0*+NI%|0Cp<>{>N2Lz?^6!C@lGx1}ukG=`t*pHv~ z5x%J7P$v+7P{$E}{(_8At~_NDv;Eh82)yu4cn$ws7%$XusMGL5oraeY^O->3518-I@iP19TUu~qcn_zHg62(9l$3B z_>>av4&Xk3w}WU1=p`CaE+R5H{w$R5ryd_+U*Jm42;k76f{mK>;!H&+e&JiAOYjMf zrv=mtWZNdd6rAWYs9i6*6w-C{J0)Bk1Ko5!EkGB|0@x2A~1?RR? zLjJZ>WS<=7g^bOd*nEl;KR-pbje3qp{Sl1cCpIe~;J;7&+{(ny^&v|_;y(aG8#`zW z!KFI#tE6*8JJFp=bcz3?|WOTI02ikE}0 zGlv{Hzi3$oy9?6{A043iIkD*!^zsx3nssb}4SH|Zv22CtAQ_QdpqBxDOsS7gEA{Cb zxv+0=f`)wH%I*vd2b>9vtqXndL13(KCvbNug5$7{{6XpDL4Oe} z{}rboo7S<5yuNGUdqY#c3}m97o=G%!qu?J4y#8CfLDv9W z4evX>KKPQ>5F4WD4)J0P_#RsHA$_+p2DuH=v5;u-hnU_^azQMxK}H;C=ZN17{2ttw z@&r!GfAa~I8Q2)BYK+r2#Rs{Jc)T62>uR=qQra#3@KX1aKa_P#Kkn#$@<*1@(ZtdX z4at&jnsHi!%EcL*xy*zP&l7wDJsWT0GHcoZH7oz!;@PkN$UKxY1TT{p^h^!s6Ut@U zIwEbl%d~wPX%jBfb~@5#xJ=v0NL%7%+KxrqhFqqtIns8=W!gTCwEf{SZHFUm*IcIU z-ALQ5mucG{X`6YOw$~zUf4ofFUm|TUT&B$%X|on@Z~0|jw;64E7RM-0)O?E7>)Rez z>ElGFf8$LhKE@VmJ_@$o$}YBf{;iE~^ai%yv=RQ-;j8@5QjTNO1LO}Z5xCp0uJl!C z@FoYyfANue(hqeI&V&QiAr=9LaGbhaJGF6EZ{U}0t-w>wpKxw$1g4t*a}Ik~gb(^b z^9|&;x1lYj(d$z&cQJe6Y~#Rqq{O}I?kG_-Nzd_U;s z;J>e<966b>Er;`q{g97G9O4|_KzxGNmpBQ0fv=>#9CL~~vD8+B_ZqzK z#Ji2l_t`k7m})~k-fQr_6YmT@A$3x1ye+{S|NS5taL6y=M-qwm@tAA0xYY09!}?%S zCbTSI3^wfznAB~jbj}Iqz6gcd42ZoOnNHDJXJ|g0vH1b6QB>eV&CFVuO*D2vxBpBRL#$v-&ersqO$W?@ckkrSony6PKtJBONYUkgs3bYIwW!X+KDFfX zF!J>OHy9*CD1uoaSu$@G=%_@{XpPg>APcLQ!>fZ1Ceqr5w|NvD1J1w!>zfuPmbDPw zuxs)c;N|}w7PD?^xd_i%*&6k~;ITx$Y`f2<|AM#Jy zIuiO|^&B*ThQMUtg7>rPyb0&#dMjI8Br~+@Jj~C5mqQ#IT97ATZM@|a5B`g6LyN<^ zp@m}b5VoyFhdgdP`siSLQyhP9naci7ZLJH_&YaO@d3{sGzqjx;>lEq(pQZKTSwSGb zc2i51caxs09qDJa-o&o~ufV$6KV975&nn*FkFG#YVBOG?B5r7D20WT8PV@$Hlua$P zhBJV-ru=ohkiRaW)_Oc%@NUuX^B#}4S~m;@odK(3gPv>rGyr+{VjG`USn-AyOXG%? z4bamp$i&hJ+>yIMW@V7qIxFCFVq*X~pJIVcp*|I3CtJaL&TIB_BIjS{ErmZ>5*Ps; z;NgpSy#F0|=W2OIK_D!DU4r0Uqw#Pj`ssn^b2O)Sbqj-z3ixKK2>Z(qyoYvY;|4$B zOY{(Zru^|Ogfj!KZ$#iCuY=257(i}^9QxT7y_MDjj|2p<^36)h zc%(Ttfp53^FiA4eb~oB-ER7@lX`XL%v%uPYd#H(i_ovIQC;*0-X@Uc((w-ArU;CURA0SJT0k*u}=GZzv9V_!D%9U(S3#lnnp7BVb}4p7cV%T!e>!d8ltzK6sVCq2*oR zL2a>v+Nk~$)H@ot!#{=l4~(@mZa+iq;B`wQ`WV3j20WwibTw`8tIr%f`zGTU`G*tz z*n`0HIG(Vlz%e|@H|?6gy=7PC_Ld>=Px}046y}5t$TR#p$FpaMKKLjz;b;Lp1A5LX z;P2RKJ@}|YoJn4cIo*Kawrz*MdiD%o@$4C$qewZNiE$422gsXX%>pdMS3mPYw`ysf zv!TUYyk7as6Hh506?=V8m6R)pPd+d40b_LRHuwuA09}NCc*^hL%HjJF+rF&B^b9Ol8gjG4dUD4$}jU(yr) zMnD_tlbhIT|34#jrbyk$*wy}{kvc2t5X+KMQAhiO?Hp^J?%3F(&YEyeP)hwyM=5Lt zGLpT%y(e$>$FcX$!hZc5@7~}yIXC!sKeGXKubid&OP?>|`{}bJV-s{C$GWYBd|v@< z)dCw})_gztCbGwP;Q7)5*rW%(3%oH{!#@97#98v&f(V<2@2C8RVrZNKI6rJ_i9(&8 zgsrRz$7(?-@e}WO^e221zPZ_Nfo)hSHnmj! z=LUZg;w$1!z*HQjN$&~w+xXBgX$;er1DuJ5wF%o=?3fRJIDq+eX0JDq<>&jY-gSwd zN!x~6fb-f(@R6V;YJwN~Lpj3g7PUK!BiX)D#9Rt&PuIrLty?-<~lU>irVW-{VQ`cM_O!9NSKj{==~ zhB=^n+}B}$k|cVx*kG}GTC`ZvSk>ZeENgik>z`ui9>rqLNxJ9tIjx&oT1bx}1Bz=- z2Yftm9FW%#$C{QfJa132UdAS3heNyuNJm#M&Gx}y^LCh1xUbgiU?;L|*n z5nU6YYf%sWlK%s`_Op&TCtcYR#%o(kLj*61y@U^9PK38%Tu7gP1U|GrO@rJF>^AIc zgkv+w;xOvS&sLJ|AkVXit??tj1E0_r{a?iRPcm5>*(K@l z{ooIed9=K`{h5l-Fa~3h^C708JdJ`p2k+j%M|hIoIt18RpyhY@q0^id>m%JzMaQki z8nDbSG;SOsG_u6z-V?Fj(~D~r@XGfWk`<_ERjRW7-F_H8uf%M#r`QdBHcN_}jI6SA|f0ME22w%UtWixmN zUbgDQLx?S_TPpEQ^T2N$AMlIhuW3B?;sQ+=U!nEUbU@RI)%b>w#~S5UvYB@_n4I2u7FNW{D_fQsWfnpH(GT?W7tp_@X_cfViTFfI|A)L6zjc54AvNHnq-#M1= z@5Y|ADYFFpS{#VOI4kDUH+pT>M(^Y&F{ib0u0Q)3#Ae8!U_AZ)T7}^7o~kpv=jkvU z>wFCk!(0q{EI7&#u5Jrtffwkj(Q^xMpY;oRZr12o9JmSd5+z_*HH|j7(#GO;9YH|=M?hLwzcvG|5L@`{AJDjCzW}qGs?()ATx@6;8`ng ztvbWW682x$oB@u0q8WQR$;RK5Dr@1dvx+IdW3WXp?NPLnK0s%yux3uyVqaulE9P}f z@|>EBzDpn4;HUmrOSBElHK5l5+c-qWJvm&{ZQxIHL7!Wef>zMiMm9pW2%Cm&cmwxG z;=~lI2kn(-v)F`lp}2~(OxbqU7F}_k)`PZakM_nU;k+)&dbmXg`3lyJr%dcH^0BhBBzsQG_M5~;`0=V1JI)>WF=S)m{RYaje(hjw z^n3u%(RjiJ1C+Orjq{Bg6k7j$)Pr0Gv3jnfs>LXN*@C?U*n63u@;QdM@n4OrkBrM< zRmjc5eM7S&@fCK1_!O{sH~2#@hS!%Ak7_A)I>WgV**A1H@hIq~cu#8zBk-d5XK@0a zb3=<4bI>=n)0%?Xss2^e8&Ur^@W5lW()naED+%Xe)E}`ju+sDWY3AL~@=OFz!L!!y zq_YB#+iLQZ;l2Uz^K59b1BU8geh=)6ayYU@!R7Tm4}1lu$Hzx43hX6cn~u3LhTs$b z>}lwi?e)!p+$n$9fw6qlkO1ODBAw+{MBv4V%pU{!Vy`HXc@PskUfuKLdq9&3a0njZ zc`xv!x&i!Y4yu0`^{)Y*7x3WElbNXaOgK9-ioCXeaJwC69us*#H?B1CYS2=Pe(-_G zb-)SnLZjy%(89!g|0>L@S`++Z@%#_;-G@Hd(?}+|h-WnC06x6a8*pN7;s<@ ziqW~+PwU=%z|+=DjbVT3v8MQ+Xtek*z(18dQ|2caDXz8308GfUBK*lD{x}l+;A1k;fEJE}NBasyAJIlM;?99aBf%v)5#U-sL4V{r8b5lV zN5AC9KwpaEghLZ>ApRMF1N9xi0rUs-4sT!={0r$K@^~}lepc9}`c&A4=OXUu8Zid* zo5V8s4a&o-ux7{JY$NvS;5!7=8697?#9%*<_9F)Dn%3d8{wCkV%h*>chHiSiJE0eQ zaODPi=!36NV9yIFuI^#-!+usA@S8je{LyXNdIff&*^R;L^&!7Oez@2NK5rR@eS8`> zY^OI~6qhA9?B00mOmBSrBc<`_$jQjgDR;aQ>i~Lxv=(_^MY!&#u29<;>@`MJm-)6b zqr!ljk=+g*!dkmxv%<-=_Gal+hqyh-Tv6_bD!yMKcm(UW&d_OV1nvM#A7DmRuLitm zB^u+f9uC7|PFka;Qys^glME|8z6QvJasVC45HP{pKr_ZOuh*9xq03mYoN=;ON4k}~ z)9Vu}mie!}-RqmO+3QPphwY8V4zDWr4VmfnoyT}R(TUuJtA%}`?OoK3gTIMBQ0jXg zXA3MJGGKRv>8#zVaQR_6sgBE^HOXAN-Vt59Orf#SfVHY3bo!rwLGNVaR8M;we@30Q zkC9alxJJc@eKU=Bjw%H-MtFxa2heMFlsR-2;GNs!Be_7oG`WyG8UTmBNyfz63Ve?N zzQ&cM;3M#@Abf8N!!CYa;VK63#ePUd?j&>ZQx0SCvPmcfP8SS?z;_nU&2GAXN$G{4W7-%K4yL;@J+=YW%@ky6D#iXClB-b zu7hl@U4=83#cQySial@0iSQV^3+GGEmHTKd`#VSIH0>Le4B%Mn)#?}E+k!oU0a;ZN z?ZrRKN>8#X9-tkvDxN(_ACVQo9gx)uz!{Jg)sw8QC)i$`DIiwsAg?WqM;;xPmwu4E zv^vO&WTta0RgB<+3FEFZLEj(~_VGtPzTi{e3wlnWbCiu1i&DY!ily;cg-a{7Taqf3 z@o77-kF@}Mf5?~f;dk@Bx*>-7Si{rWM_(G@qZ#<)oQHf0>;O*#Xr(oTQG|{;$R21f z48Fh-AfM^u!N-ApqE7e}vU|>hF;2AQqrdF+J*)YK1)6V2h}aPMg`o?*@fUr=veNjm zE5osea)Z&}4aKS7VI4R-M zxb!{%^EhCVZ>VM_ zzz>>1pXM8~io(8OFnvj7Vc*b#@fw}ppXuC>y0nN7+yb8kIY5uXK5#Idn%^3rvv!3> zC+XNq@a#VUL({j4Fz>whj;dY@9WyJJ@GRmJG@gM@jc1>;rpSVf%o;c^fe3 zn|v7Q@OpfcuZ})Y2LEr;?7|fBVT0|0>Mq)a$F0y?H~FK+67P8{?n4e_Rkf34EyIb`>!PX=eV%_CzaSOX&aUCNj0$l z`CEhMvyQ~MD`;jf|pYSceUXXHg zsMgW7%w6M7te>6tsEbo1{4M2d|8~ZDYC9CPx!HFW$-(dB=xp?szgru<@Vp~~SN8{R z$|-z+`qTz*$PwD}IeOm{tXa;!v!cHWDRsbh-rUnZ@lGgoXnssM)?&=AH2zUnZJt5a*$IX)2t6YM_+C^qi7xj+2`429mlm^Pi<)#&^a_w?B z74P!2`Z2lgg0Z=~9IISe%8{VMbD*8Y>6=IA*>ZPjy(TF4JutC;e^r!6V zhAhea)ybf!SaNR-#xlZThnrK+_HZKhy`N$YYk_FI^lje1>hxpL4CBxBRT8! z?fGn)WVIXA?yfb#yFD%?4LwX+kD{J}dbc~PF5SH^TWCtn+3hCSzYR^4GZpb-uf;v4 z`d{CZri?<3SsQmVYQ9@KS{Z?wXsyOYeU=SVhF$D)J@r`@qa<8}GYK^l?-7)^92;ya z)aeY7)PAgI>^w>>$`+LED5WUBL)nV55oJBf8k9ex{2ql%gB0co(wf>>X{hA<@sMYp zd!EXf+__oODpy};LK{nC>bstMBj4sWrEXc|9r8fiUp+Fu=c$5;`ggZd-7e3aTAg02 zQ?}6J()%N@#6}gXnMHF zIDUDd(6Fy)PvJ_X&b{-BRF&gr&tc-pU`pL?dHATaa*r#m&|SEz@MO?ZGc(tf)9vD) zU*%fq60TyET!pUcR^^{TOU3O{4rKaDtN6}evh$BSiuyV~>M4Sp3nYsv!KjVnTf;SI+Ih<*Fv_>@Z+E8_~Yw8oC#bZWIXZHJ+FUzhBZuv{H{b9 zgV-Oto`|1pC?6p1EWs0+HRGujf;8)aCztD1u&WE3cEewdlNyuyIzK&MQ^eqxCVf+L3;29rvCAbsa zsr5?HljV;Xgd+w;DPro1P*wV?0U$i92Q z&+&K?t+O5|SuRM%74D>Q5|`E2S#Z9vNJ^QgQJC0A9_eXNX!t2i;dD@#sZsb@PZ;0H zgD9L23geo^2!)gDPZtq}cel=6IzVNxKRhZaG(1<#@QM zM!8LHk*HMuagoaZ*FQidjp^toD(}{)%+{!U9JD>HFg6TN2~VO?ke*sDJuo51Rzz~! z)k{>_dczcb**`$h(g;PL_Wvxivq4Q}n$77TGhflV^7$8KRvDqDu0JVP)TmjiQ6mDg zzx0#DrfD*}ttb8>giB>se32R&vq7UK*hez^x+g5NM(E|+CmGAZb0wa|`vu9K<8u=w zGka~hiko!hN@$?9UV+A~=pU7vCfT*xJAxx~mp+gNtL4;NgClbN%fs*Ug2Qu{t_Z*9 z28ZVQBkwbViMjSj{~LnwxyYLMaIb5EvG|fBUsngy!1b5?oHhkA@sQoR>E3Ux;J*DN2V zMr0Kg9!Y@(Rd$E9r>l>%2a3q1=XE6ghExC2eKMGHXmQXYCb~0VSG5;4hAiv7z5$IP zi~PFpMqwl|D^lHqzI)ROw z-DGO#V$p8b_r$hyswKjS-)fvdAKtctQ&R!gNpQgj($%%)jThlwe+k@zK5+$M_1D%g zCkQJ6qgiD1zjJZqCF8UDYF4muH#hBejgz9Z>}`50G8VV_hU14e2(U-Fy z39jXdZ_QmNgD*4!N2|%5Rv##O;}Th&?Hw#DeVEW@1 zB=+egW6$)S3{FuNBTwYr$>2p@7v3~a>*%w&dppz5lNU(qrW~Xf`uop+G4@z3dXDMP(8j zCpU$l!<_p2?taZ5Fm*}45q3$oy}h?PZ+C&oZLNPx!z2q9)Yi-I?(O`c&00r2{?z+T zFv~-k;+I_|u!rw8dnoJW>^ag5>3a09=_mhsGUz>gYtX`U(Dk>#y}Mg)k%c2hg&^ki zCTXzTy@|@d=Cl^XyGPU?fEG9rBd9$k!XvTnnC1;boqy=2`uBQ12&Q>H2zoXa7O`>5 zn!eEJNbGLbyfjmP>LWU2V0k_GDwf?EG>P%<_(8O+(P()Zv{0|Ki?lqb(bA~VGHMVl z*GFhMa_ASd6b{hh?@7{N@t|ezWoY?pPgqyPy4^X2@a&<^;TkOkpv3`NR&Tr+D-sW^ zC$}k|WZgwxX1j*Tv7YF5&O-KN=s^yp-V+S#>gPSAY4f3LOl|Gs(qh4FhaamAN3z?l zSyVQ>zfsepjlhpQ%D$fA3NksO1HIBO`XAysS@hD2c$R41FVuOs3)nr3Tmqc_gU0E* zx*pe}K2v9Coc4l;PxhP)zFB!|FzOeaZt5YeIo1k{(d&_(0j)U@B&}JY(dPyo16uPW z=pe0ezyAwPFB{7iU*V|t7wsFQ?ZnyU?yv;fyN4+DoQ#4|?y=}qS^mC; zIrVs{dq79hBD~jw_iG>aF3*%ECly@L+o^nSUs0E&muO82u6~~>O-S;t;HHLKo4!wV z>yc+eOMZy1x61})OSbUUun4S^!BJYC>o~#K-(F{I>ORJ1qL2?+@hW3G>#&|dd5oT~ zFov}v8;Yk4KXX4yJj&F)j2*?;mvKrm63=g6qnzbO2D4Hg@F`F6R&2IGyYSFMr)enIcJHf4|Ab*`1nI z-PG$uR%EjGc5XbERL5O&%dEEM#}sDIM1*Im7rEC!Tqi9^>kVsxRnuLA`71o09x`rs%-LmKQc*N8|QFX-Y5!9Nl0WFvuksKd98GM&C3$`_aEVe6F)@jyi z>o!OZaIUxW%5!0#aHuPG@4{eO3fED5%X=3Z=M8PXVlNYSwp)2-n|V&)98$d0-`O0| z;k{kpi-k+QGibGlfVnVeN@1xsd6_Jt*Md-fU806Ve`jMzP$)0#?|dip$1{jE3OGA| zN+#`Xm?5bx*<6!e{iu6%ZOjGFuMnro(*7UzGN4rV-42*TOhL{wDop=epas2t1tBH+?WVt{YJWF&(fjPKtCf+Fp4+sZf75#YLHql<-cd?wQ8eO!wZ6Zz zt#1UhJkSki`!M&jCHrU!tD8I$~vE7Va zg(vZCWX_@5uyxF+(yNw!Za4J$VdmDWt-%NCMCgLK*Cz22FZOoI=i_sEag~cl?UM7{ zE7aQ4GtioU-ki(XslB%|@4RWwj4k1{+B!{^zOHPI$0xpI%m+N?{sntVc(3iUI4G~5 zT(4LE-ZxJTO^vc~@{LM(C1rIZKY*>W?w8AlswTaziN0<_#-F-;a-C9CJ$q`as87Ql zMQG}q+Iq{fj6W(C>DBta)D=l?XPwaQfnlyL5NZMN6D(j?07vw`2SFT(2%bHs-vYCR5g8S`E)r`7C-KRSmZ8_;U2BIEX9 zj2FeD<)Fp0!!#xv1?h^T`l6P)tww`eFPj=>7Jb-eFeEjw)G|3v2_RQiiY7_bvss$q zL{0e&)ycdipv)mC*CbC!ViUhTLDFOm#IH;7Dc1Dqvyeesf5yA@QW&E=4I?{nv7i+1 zA39erJ?=`YA2LTNz`DEFAYGv(`lys~#0^4{!<%_nXRaH=1xsN#c9He;_A zWk^mj_P~eC)vI^4CFVTtO2w+=llp`?33-pX9(C#3KWB-{W(F-Ihpt#OsVuul?nG>y zqAa5PR`vA}PMn>vGRr2+tXB`U79Tw2XY4(|t_Ds^da#DDf(-rX;q9 zCU+jCR@(jjws}I13p;#z)zj+y;XfUE@K`UgG^vTT#|c;6GDg)2W}9$f!S5R}VumbS zxPR4Z`H!v`<)!vTEK^!!@9F&XdslGG;T5TgbaaZ&TdUz!E83!RtWh`FT7`jY+q3$7s`c&HH9_z zycCRWoDY9Yx&Lv{odtgU15W|ZAmi98*cQ6m}xsSU<*;&VIdUeS;5mC`&7aTpEXTP@|d=h=F`}Jza zIqO04v7yeUkRYvvB|gqllM38o-3<5cY<&}Rcby?WcP^w;OyJ*%bDd{M=R5ZsQ2W=A zUXtH1U`$5R=uvmN$JZ6Q>#|dtu9C*MgJ&$j;*A~wnHTBn$D!ehBy+DZJ1;vVz52mf z&PLBq&kF4(@LI2$&P|u8=Nloa(W_!>|G`Hvk4fTo>(#lC9L@mJGMYl2YQG?5z2QKX zF|Xt6hxO|CUX~^t$F84lX9*jVtSBWhIk9s{d*r2DHTk{hyui|#`siHJ`j<;+Kj&28 zj-|Gx!cllI8;{IyOrIz{e(;rlFt!WDi}E5$?3=p%x;?ZX&u!$@ChUY*oVwcL*>QQ+ z{o&oSz4hze-1X~amSH@;uBa;8{Po@4p5Axc&G;2|w7YSiF33ek%YwqI%{`pLR8`Y) z2VmnD)$<;j%k}VGkGnk5dh8!xA=N``x#pXte<;gyM)?-wkfw)PXU?6L^HA%Z zx8Q^e{h8X?Ra-t&SYp{%!mCkS)HuGG=9tnqPkLne4Cy*aMI6~ze)CVENBCA9S65<& z)D0&r4cV&5g9?6MNuqL7a%Pjqb^44`S|Igw2EWa8f7)g=ayb8XK)aZ_6+8S*E-O|; zGI=I(XoTYO{*Q3?<90;Kv{t<|Qkf_HGbng7-M7v9>ezKS8|mr%;@jW2C%Zo$SuCF% zajlFMCV5y|O=%n}>Zg6>(9|?oZ15S@umo}>KTCcMCdx|6t@}AON*9&EH8GJ>psT&) z(`X(4*3HADxAOkrDwnn*587Q2?IzEbgMF1W&0Fc<yy#@V&)p_@u23q0~lZLOGu%$=#x zB?Kk9KVKT>+gW~>G3uyo#Zq^y`%s(Nd{+N|I53G}S#4tMQBSxbe|sQO~Vk2zM;ML=;KmqQDQyi0#V&N%AG$YTliKB$HqC;cRcg; zBJ@x7Q7-A371NB^!&q9>*G1s<+ihv}!d6{JarV9oY@WV}a)!Abtgxo!MJ0CYj`F}g z*&Uu=lP8U>pC?7Z&&M(v_aaVCoazRTW&1qWJFu9<=9=et9z;2QCG8KqszbIvt*)Or-<&u+FMQe)})dScIW3m zIw##W>&*suE1a3M)|uOM?5XS#$Dw6rvFOt_9S^VGX69`2QaO^>SmarhCA+%NVo#R6 z<)SKbH6;@j{{u?Vp>`I_?8equ^L*gOIVLvQikO(XLY8g67(XU5zNY-GHnY*DidrOz z)-o+ecSZd&_dD5fU)tSGBTkMK<@=$b723KKtDcN$=!Lz9zNwmqtnW#~dLmaMz2F?t z(208#NI?u|aiLBfWfTrkxoSmLI5UgbZy+clVsU^xrSYnwnsP|qah1%jx*zs0#wNQ- z9(GL+{Mf%{3KK_aYtLVQ9**y15BT?ca4r(+EbF%(gznF<%=Jj@%Ew(}+%LQDcN>-c z$TL|6|4kZjGt68xb$EN|+K!`R+-&@J@CM=i=3$?N_spNHg^&D6s2G|v8mFB@5zm=h z*u&XyI_lOxr+bdCOsvZS-TQ$JMT%uz9x3`_&OebGIn{?Z3Qt?RaxSiEwEny(6 zvBo^`G0yf-CYH}#fksi~dQWg!b>dZEAQOD71?&o5pMT#NaJwG zC~?&S_FD8(em!N@xM@`)w9nLW_Eb5waA{$ZV#%4UdJH6KUVSUbZD!SD<*|i@g^oJ% z0eaOKG}X;kOAO>Oq*jaJ&n5i_|MfS<;@&jPG43~M=jar*lL{6&xQ(3pBTjf@odO~^ zYcK&PI+tHxUc7%K;U#fLO-1?0Qh4>+prcMu^Fy@iA?^)R_P7^bu~&=kyNb%R=)O7< z-80;Z7Tq(Dk&6<}tZ)_>UJvM@e-=$oDT13o^Zh+(k`2!ff3YUO*)v*-4_bkH@IzV? ztgY3S4w#b3C zEOzOpEBf7tclnDDp#=3`p(tbq28k@5GAnZrn>d74XAZMyf^=BJ)0>fVVs6q6;tA=* z^oZ?Hbn5DQxt!Sw#u+WhqC%YuyI9)d zW=KTw$`e(S#ajqZ(daFAssi$|c*VBD@2Y!EQ9V1m5%EL>~83f(pbtudpb9suPINLY#pBbOvzh9y57_IzGd+KDJo!bASf1KOyHbQfze3$07xqCYAJAbuobEmlRi;W)YV=0jX)qhBqBfZ~>7V75 zvDoK1AXUR7;{3?SGJb0Q#LvdYw2RR(?I}@AnJpcVl7igzOgSL!Y!@NfC2{PB{iVD& zKRDiMaG>95t!D_Jb%jk-9Z_ z{|nv+&pGh^D(YuS>?&R{i>${u96Fw{quqf_{im&K)Ux5PF-pRND8K+2W)D){q$ zeyeHoyV(aCrb}GV=*?7~%hqYFh{^q??Qf!GiewBLyxcX>XJ$*oA?5Up%;xKH>xG#x zi=FQ=CH?y>am^L8ex9X*W~p|~I?&*fSkUCXJLUB0pXVv*H*F2iqtoU&cDg#qIY^Tn z7ScEJ6BoW}KF#co>&;ggd-zGDYiI>k7rq*kFSw7|w0K|Jj*+5%>uL1pG zt$$6Lbo%GEulr2f!Yz96@^y?hVYGSB=uacCW9=`V`FUJJq&CK0b>?-#W)LNHkv5Bc z&6%^*Hi(j)k+vxN@6Qzdf{JG&Z903=nLWgvEhO_W7oUo>CD`vcvx3^HpS;+%D$+L8 ze)E~39iF={#eaFEHOYSCApGx+)EexQ&kUBx~`41 z54T63*+uvblFqnDTfDvRv?ldIbd8L(CEC9~y@&WQh_0AOTeRJGT9f!7tqS#qrDn2! zc{(id!7@`Lt-Sq%L9%X%)avc^r&-1m9aq0<9IxLN`;GA8vJ@uj?3)=yiAl;U1)b6#}x+Y=k2*eu4Ib&}0mhfGhQe+4^^-ujV+RB18j6clSzuv|D zJGXVeMM|unBPU6MBB&4cu+*LMGDKk3fbdOsZ01e)R#^Y)g<}tv)q1d67$U`2ex7>( zYnU+PzXv}sBpG?^5n9Ei^-g4MH}qg%T3y^7Wg}WG_{{)r=DbZKbZRoqEJgOaY)4_b-$#&t% zsfBOHTzF+w-tO4Z3-;s&g*#&|y!mMSwu!GlpTkmT1ck?kkB)kl8~X-!&L5GtfBVeV z_fqnLmg%uoiB*=WAr(V6TAv^GT-1wt#9$s-0cSQS!=%Y8A5LKz7br`(E^70{*Z;1th}cF}Y|i}q93oIIPP-p?lMC+mN${Y`K5-!irr-@8~X{x)*vfBSEs-{9xn z+#znVo=W(?bnWdX-N5%`eTVjb$0aijv`XCl7*GFAz?*}{YU6Lwy{NkZZ|~@wT(35M zt}t0YlN++RNs4;@gk;#hQHrf>54@{IH|&p9TZ7zmmhoh>IQd3JQaMA(8H%f>w3KiJ z;-k`kLIhf}*U}!E4o>k&&BNVy*T-$Wad&)mygb5f+WPmPwGroDIA6Cm;x?rtx(=s+ zPP-fT1&qR!n2kmy(M@$@ouZqYikga;EiAp^r<-42m>p9kse)nlnds__R0d44&s;B2 ztW8hXHH9N^wo;8~Z&7}}$Bp$7Z0%ST?kU@OWB`bj7c+n{>CnE%Ozokpy}&iGIo>^u zaNT8<xAR9bb(}AKH}DdiF8(w1jow+0&FMIIc6>IPi@$2Yt2NpL#ygapE=1n9n9W z(edSLgiD_E38M4>KD)a=0u+iH%}^>$d)Mk&l?yF2E>t3|{I;AJ6>mm^<@4sxHL3Q+H` z77$!P36DM@ZIpfxxFc^EtVfsZo)1`INX9AL)G?}2r)xI}U!G&!-_IF1hoTyEN9y$4 zk%#rVqf2(>qj!q(h{1f6upvCcW4Wnsb}`2gWyzjl9qgeU?G~M>VWivGgxzjU7r3dL z&@L$9uT)JllBBPO(;UXlY@GS{H|Gqg6T}7C%i3n@P@B4BFDw=(#^3wj!9F5sGf}=# zGBrfE8!fR-_orhYz|Ps@`jST~V9A zWn0TombhQbf!tL#Ckm97&6=Tdo{`wGa;kk#?f9S((rcsy>Ve21Jc{= zvm#iU>tHF-ynSFM;Rs8u{VsRCsY<8R;WN- zB>hR7j>GIk6ZT(d{vr5RTd^y}n=2o#1I$N{L-U$bxUZMadh8pPVSyxOndhnZnt6qI zQE&o%9=C3$)2R~d6|wfv^*E!drCn3u_yqfB?JPR4m{+WuGg9Xizk@6}{hL4U2H*eq zamq_l?1e243sM1oU!dPeyy)({>-z%9ktqbZ5oTL==h^S{TZj))X=PH|iB$YT!x4Rt zR0jCNHtQ64na@DeXIrwnju{l|7DwvP&C%FLttxIRHgB<3bLow3`1b%Sxi&tUJE0mU z9mP$k=&OPEeQ`sZBmB}ZJ=S1p=cDc4kgjpf?Z#2m(`;_DM9)+2GY`XUh1$o>TR~&( z)>*>WKNxeMuUxcAAu7#VJ}2#r{tOVRu%msy*|a6O{_nx0icQi8|B_u3Z1hfc4DXm? z^Jy`$Va$l~vo-$+YpylK|H39OXU~(AcG&Yi*z+S~&p1u8Odq8b8%&pY z0&Z&R+TqHQU1ZDNh%K8h+OmBmFw}8V$x5RJS#%Ob8O>`5Q&?)OuL*Zz-h7lScL`=O zY!6!_*5y-A1`k{(sl36ejS!|h<|023TQyHzY35Vgl@m1bF`|$3ZX@hIJoX4~@7qRk zQw^1LHpOEX`L|oTTqFtW*Guuc00#b98+GcGAZbEC%BlOLjYS7$?P>@}I^5px?yT!6 zlMFAAP7#-5;U&TG#yfnMa(b|*YzJ@m{jYdCUilHctp#s?bJ16hQ69!xDa_}H?_0}F z{h3qo%97p0<(deWEtlo8FojFKFT!ca#{I7|1F{DPrfrlSbH!Huw>rS{@N{29eEKhR zK=bMUr4H;R?2rj){`~)@1BT7uF*9y4s9aS1OuB-iTG;R%#Siwqb`avQ7+1~k(&uPJjUB|TX`;C4Z)Ls6BH|c)x>3(n)nQiU8ZZ- z!7J{RgytI+wAK2g@rvOEK{fJ@Nr)rk4AsWX^IDsta$9EDM$l?3<s{@RjNcb%Mvvz1kH{AiqOPmWb;jiZkyjn)NquQ+TvtY-4| zX2~N)^Y%yOweGT%JokEeVagoYm_hK(fFGtK<0AAx*~Hi5sy%7H;6}AIb)j72w#pwT z6}r80&Skk_x(KDQEH1(g(=g&j!lqTO=*npqxnY(j?ux4*ZlvN4TpBoWqcj{`QO4%T zkGjnAW_Q91*|^uR1*@6MapOzPdlBE)1K-cuEIdmeeqyF#wdcuRcdT5NB)fOYGgFp@ zDa|x$G7ELS6{Io0DT8!xh=Htr`(fTL-ROzCdx2ftrfE{bv)4jaDbjtCb;2>=b~3m~ zpAOtePH~VE@Yo}uMcPW4Go-fk{cnD!XX^p1_8vH1P! zY<`Av^b+_R@$h{7GCmtH~~vqpEjhDg?{n@`*= z-y;FG^<+>G0AF0`N`g)`BpK5HzZmeD^T*6mg6{Aa?4`_;{a6LA{4@u&h>y8e%Gb;5 z-32M&4J*E&VvNAsIhWI`Q?q-EIG6e~pVg@vy)16>Y?Qr4#oM55d9WC$ibq zqfX3H7Rtv#?{VN`&HNN^Gg1yAYcY=d6u5%}lcF#qPWP(%JJ*HuTWQ{zrS<{pAB$-} zVA6<<$0V))IRDekdrYw zAKr1ToIjvVnq~BNzNn2W7~oI!JlAL$qr{Tr+qJ!yweHenbM=>sc`KK}pJ)euuX~p4 z#k!(#qD}L|DI_&`;?KzkuXpFUv*hZOg(+*{3kGaCEQum*rc}&Cp1{0?#~C}VNn)Gw zcHb=v)1ulrJ{cCA=e{ZFnFyZQ->g+gR_h03WhHCM3Cn7dW=-PdWHq^eKvr#@LDsq} zY^|HT1J-(ptVA)FWVOmQLY_~u8W*uuvV_Tbnyj*sf4{$;vFA`q*5SNjEzU@v#sA3+ z%EOy*j}YYu_9^zEoLqyu?I;gyWNZ;i^J?6CNBMOnV|Stax&rkmpOxY_yeRMe33t6v z27KdSze=8QUBoleu2+BOp+1)Oc=N=)*3Ef)601ibJ{HJ{)$81)u$saCPY=BNJNKgZ zz3Bb0G3#i|X495uU;)EVOd_s&f8*Zg);L;W1xNSE#pLrf?a0K)KVf7}^Bu5x6XMC3 z%DmTv8=>XqE*Gpn+Isaj@O7@dVtDXm*lL~InDK}l=Xy&PfF+IpbzjaqmMwX^Oj~0% zug`v^;ftgNN!)15#`U<_Lzvyw_i=sRF2feXXm-`_WtM(p#}BVsaq@jO)Zh8-!Mr{3 zqn~!CXgzcLa?q36bfa&_{WZhZ#JVK(I}$<``S>gC7U9mI#gbolO-Z@m1V6Zv_Fyg5(YR5b+%#O7yQdU;1G9fpAKMo+ zRE$&OxH&?BrC`=g9dWy86^K2U|9GNf=q{`z?4eHa0I#m;iMcTO54eT?;KB34dfeZ@ z-G+xZFt!wh{e{lY1<8^_zr_yU9i{tIeVw~{(!m=M)PLW5>7CrZPLFo}zVXlaO(P23 z3BWzbqLIcJ3Eu5!RM8CF3&3wcf?^%7xANX3ncaL%3ZeCds%xWcQXYl|^-o#U|5EGu@*w z;k4UclwI#FXC15OzI%Z^k%${XeVsRkc9th%&p_W)h+9Wqc~17uLX%Q$oZDcP!UNJ@73O-ApUN?G`T8Vw)+y+-_lAo%el* zJ4ub$tCPw0aF4+O55RC|t?mk$***zcJf8%u)*S5S4Y6|eaZ*?3_-_&W=tdvo-3x%t z4LwGzF~>nax;n4;mZg2)>_3AWFJ*^7#{r!E(!GXvQ5sR`Y~Y%?*XEYs#2R^!=c!t` zU=h5V&izG@d056BSlfPFJL%>gmwY>J?uheKK7&TjQ!UYYcT8Kfj;k84Jmik-P_G-jO>tk}46(qR@{A*S- zz=IdgLnG6I=%?NO#vOX2c1qIv5@SRs(Y@#>eyfgW(-D&AkF#gYHA*ue&$ZZxOvSI0 zhEF(#m0oD-Bj211c91l2w~wT|4ZplRtKE3~G9ukrNLPqN?6vr<{Q$S`!##w&<|zuh zk|eIPvnq!~66c=d)dl@wXbjKnn^|C<5^~iOK;l{}Hql|08Ji{3AF7d`>x! z-%^uxVZTG;4rV60#&y$;&EBVe*!k~zfm_8Q-6rLRBs?z`AbC>LC z6KH{Sp-ozr(z1kAHX)?xrKJc3)Iq>80i8+38LFsLMImK#0mrgwTR;k^gMdt{Fj7QQ z7L`$S5(+Z~ie6wU&_GR~B_Un%|DKxy&iv+m;d6S=JvsO6%dKWZ%$(3{1(Jm^JYS_`15lKbJ}PmB4eiVMbK#x;`|B{<2kEf&Jbf7 zb{cnPu97jv*^|XGrQXgO4PyBxs+uG%EjPvHbJB#%oWWxWn(C@EAIx)OVNd-Uc4@%(PG+3<#eAI=Y*72+SC5#k4Jf(-X) zI@4xZ9b@FgE!IFCmDn?bUv}seELvUHXQlgzg^Nj&?FdhSH$c_^ zIj*#sVdfS|(}?k7NP5Zu<^p5lMaFm}kjm)8Oh7GUqYT;w$0%V-G}vQzPn(+JKRR9Gp3>p*EmlM~2zpe(Pla(%-Cg z!{W?T(x-=ca*N2VvWy6`fk{m=wy(I~%G5(rM*IyhQGUE;H0#dsFMUKUmy(wvGY@0k@+a?b{PVKwY@XF4(@Y-8H__$cc z7oYznPJ*-$e|>sWN;dMhApfM}zU2Ia?nO;pHn)X7dh zsgPgSY2Wzdh))~)jZZ%{7BpzIC0U~-1Gw`0wP-=hMg3Y%OET`KzL9h8Y!>QV!Od}6 zYkpO)3TGDTg>*L7U(_lGanFQK2)%L3s@1S1QD)V7RIu(tCGm_+iro3mVp~BdO>eSW zLTMJ7y5$;lN&W$QK?r^Xs=Gin*I2)@NskgJ4=lMl&6yqQYt)KNzkQaX-Y)2+EP@__ zzD5O&2wu#wueOu)bjM}8T>A34YxE{2?xQG=1{cEX2y`V!tv@ZVVvJRw=<6_IUq`Z} zmdb>w9%_RLyC*l@zYOxB{aT8cCz=ei$+~3sq!w2yqFUG~IE z9u+1xHQ5UtWIYk__q}}%DwW6fWBLttC`6~g^os;9bdb%19Sa>sGnF}2dv>+1er9ig zQ$n+ysSUv3j(xOUE6RMUV=G%%FQ`aKv;P>IDI>S7C(h0Cp9x-%dLDHqP*Bz>UpBd61;@G1GV))Q_9l7&+vlcYYs z4856n4e_ny;)fFxzo9{xD==a<)(l^uDkZj(F^&&b|= zNW^Kh#Qllx)87hl0_n@F$4dMT_vV_^@YgF z(ff7z4}=H^Q@^KcBQ$;DG%7o~)K+DE!BcHr480UHV0VR}@Ir^Bv&#AmV4cYh&fygK zbGY^U^`-hNxG(L{aopKC6xy_}TjzK(3rV`E@N2uww_JD-eriR}L{{X3Q^lDnf@PjWQcbt|Cxxe?yY&$}%q)UMPx&*m?btdeEhC?sh z#r%>9LR|Q@)-0HvzW*iX>oxf|E_^ljKTF)1(^!vD8H2OoL6Q~rFc=XIBSN(w24fsr zAoD#IA>-b;Pftt1Grehs!Bl8*PD|eD6kscjG0!FMS=$;S!G4`GAq6F@vJUaUK0_d$ z>n4ErHH@wzYfkul8mwu=GrVs(i8uH1r$U3|n}89r^Il-U+OVSC+N5QXHw)`2>vd~d zIQC|sKG8lF`nxi^#*jvTy;ILj7>qM+Aa?9OpxHzBK^oc_`i>AyK0R@WbBQfRD6__R z%B>t`>~Ke4yFyeIYRzvZ%K}(ZBosUe$xGsX9^a(>s((F&u^t({(^!(O2NjNI==Udjq^9w*>iUdFC&_gc}SQ9AcMqxZ! zxU{32n1&LyI6B@WJZcXG|9qWFwLaT19(KD{5oTmxhk*Xjepu0-(6@w)y4NN-*tXVY;b7wl|J{?kIoODRJf1MDi%42m;oda%L6_|G*Dg7gL>CQn~x6BSD6 z3=NRR*acnXNHC#85S~;TJZAt=)069(H$(c}-Eq*Wgk=8&jPU(6Hb=Iet59wr znY}m5&M_u%nym?TZass$#$e~Re4O|36uyb!Hdr&g$y=>AbL3O?3J&%9HxF0uA#yUm^h-LO?AK~WkC?z^4>E(G+HS1Gn!PHrrYfi$y{ zOW8{N-M-k0)_~3;aeWiL7eYm)6v`!p#R%_hUnlK$;*YE>%~O=VWD5mfzn%gfJn@HD zDk^3rYwX0|dbp}NR};HS2MNI=?Z8q8 zhzvdX`iQY*x^jlv-)dcLUy*FgQe9xnQ$` zMdKaK;*!?pT1~I!(kT+({!FO(N>WR+Lqp%dGaBD>AbXZcQ?HK$1>@oBHk-zGTv>mE zX!bXY()h5aVNGWppvdv)gX;TGMyak0oaqT)Lhopb8$4-nu%)2EX?%XCO|_Bq40k*O1lqF5M^bu42s<_D*l43g4Ph1D%&6{ ze?5iE;Oc*Z-gtMDR!6ZGenYAdH=Ie6uP2ZINEMm>@^{fH@QCyxG0E2{Aw?r=fZe@P zg}_02DOOZ&P8IkK>gca!X$F2htjuKn;7)}s3zJTayosK5d4vhXDa&&1oCp3}i}?r6 zTmYQTp5qcOASE5U0=hAfT~lnhbD6@Mj_gGX{_@(XiJzXZugQ4x>xpeIZ7Ybg)lHIOH3bD$cj6Ygki~_(?tsN=Zg^GWkln4xG< z7HuaZj)V4ppjnHxS(-@82sMjY{$|HGYgY@o^6kK2xOK;Bs+;*NmJ>Q(2gw|zYA7D>h%0z67mB{Ma}=dS08hR6a1GJH;ehGE1&KS64>d2 z&7|1(a>k!?H1EJ@@6eowy@i#uzJ;{RXq{&;CI{a*CQS zYkGQbHI==Si z*Y5T9pnHN)d(%-e=OXP#wlLX7a~#3kbTnUHf)ipK&I>gpL}J0A^?h#5#^_~upKacb zwu(u#~blp=6+F^$TxoqR0i zaA1t?x<^}VPgWL$-m>%!;~-qk&N@EhS!jIprPeXYQ|kEPE7I zLobB-l>W_d*uBp7Jz`|YU))~kuzur%N&7Sg+866>8(@)Q4{S|Yj*-pu3}8KsX_A9+ z#7NXLtb9mRQ5=rOsJ7vh>hGX=_@nTH09a4`gHNUU!KcxX!6_Hy><&{#Hp_%Sq5%-S%)^KopnO7qyGoI0`ANS+Ix3HW6lMHO_R%-B8&Y4ZT^@ zH5+~k6-FcmoFb$a|r7`%fn*!1~v>5 z*)sIwJX;|vS7#@A`LYu=B~*5ukNci-oS>AWDVEE1fDu~>HH7*1106&?NjNKFnM1zIwDo{o1n^qYPG?vyGL z%*I-{b|or z-jj=3_C&~LrUJ7n<$^s;>5qf)yo4UXb& zekBv~&Py4T$$6QyWC4(`n3bt?Bet$@F&RYsAFZs;b0$+>i^e(pj^13DW$^CHGlCjT zEjX^sd8y%rbd*-22Me;i;*ZeknP& zRQGOUamFBvf5S?CL_F5Wr-1>4N*Yn=!|0tsGH!YYKsIyvO5!g$Y#zjVNI&)+rHI@U z%~@?8x}RQH3F|a~yG+7z$g-&W0k+EI8}>kgP~N6KBolR+4esb0sbYpD2Ak@Vp<^3q>UWcqTOAocvj z2U2+}-CCi)ps8m>nr0r<=J_BnR5@Nah#s+LL96WBM?_8~dZ2kw;MZ}Yc}!nH10Acv z;%AbFfPy<_KbwtTD+Um##?f4vS@9WVLG4^b_)YL@vHLFaE38pVO_Mch)(D;x;;1!h6&+(;DqZVJxNP&p2=*%NINfne?zOGQ0fr{+C%Y$EI?aXC@YJ? zaJ{`nD4AjrNR{AGJv2=2jSeLI=!h`>ZK1TjGCPGPvzITrMACH|AZxZk4!bWZQz&@& zDubMiIFm5LOF=a<;Ph2@jFWI^g^&ff?jTRJQ^jBymK&zlLsE<_Tw4PT8pEZ-uf%R9V z=l;>!W>dTay7ET8v=|odW-B{`e{UZn^*jM2Cucd0AJzm zXy><7S|!*jJsY$?GRSnEm@@ApQOhZZIoiRX3*ti+kH_=S?#tpxXowM18bEtBbR9q87NUJMO zw*jZGckBoyip_Z}eyePCr7UVnnYXA(J4*+-=Ll9DcQJPBHOSb&KtKAY z^w9YPJP{temG^F=2H=D4A9V&@VL;Iz zy>&y4GF}dM+uXej)vK<4^OVi~VI3vCMjAD?sYWI;S&3fV=3_PNmWO_B zY5q>yckCJ9vYRy`FvKKd^Y+d1dogG}>=^+ZId2aqx=|uZ-K^UTuJiVpxm=T4y*#JC zcW2Ztg-n0JGF|=t=I=Jsu~VN%+xCoUR`2ljF9 zF7{@Q$=lKVcZ%_A#x&bE_o<295?=${gnh31ryIQ~T}di8>GV%GlJ31JE`a`YBjMh= z_B36SC&F=Mkm2ij%Za0Y91)q!Ta zhSJ=60RmKZ$*|;smKy}WG092knc%%wl?n=~BeziFlataAQ<~scs&0D+4dx}v7X5|u zWDQojX{;XbE45g1FrdGuA9AkRJh;0TT27UR0>xB+#Kf2m1!g0r6rg=WjMYn_Q=nI} zkaEmIUaC2wq%ebW65#WQIT$RvF$u6)G=3FQ*#_amfEn6qy0d7Lc1wsccK36-3{Q99 z64a{11F_Tnzlr_9CuglWz0dtN+2AS2QPmgZplfAz8?q2C5dzR$Ht+s=4Y{QU=-dvpL0Yf!n9#6Z@zdX%K!Es zSYEA~%8VuHuh_ns_x-$|AAjoceOAU(lq3^Vt2ZFV48MuIe((ThE(9f4&>sK}F^*)l zd6}^%=be6-8BPXiaojATRA z8ro$Yb?N~z1(10rtX&fS7^IX415c5`%()k>On)<_Rw>mcdbopjWDO$mZA}M7GA-Ws0W1Ce22FDufgUm8p9S7XMBbj0F>+gIr5(NU8|4`qRa1G}m@@NK$#K}G6=nHm9p z-w=`+_JXr1lfgz3WI@NzNhTiHejFI|Vz#LLu1Rv|YVb}M3B1E#{PtEQ+W`*aj65Se_&#*%b|a^UMcm-j89E^|dM` zbP`=N<$L3Yy$?(dqcT))=hHHT+d=;?#JC7{PX-9Kka9dL1cS9ry>j{SmfMl%iftym zZ)wU-R(RvEqNc-&F14Vli-5ke6Fahh>rhDDC_o8_zOZAq1gTTSd zlx))y<3KS9{3BR|?S#LYPl^BYj)5j#;z$ka6ss9C@qYsQ^kgIH69*{_>eB`mf&HCr zlagaRB~Im(bym6eh*ObYZspw>cKEIF3`MJczD8HqE2zI<=JbLWr)TGcQU9ZuhdyXe z)K?Vo&x8%d`l|cy$MJpw@8$#ZtLf=-9B0d3oF;ahE6H8wN=w%nBu*rksn6TU#OarZ z!&fj*N*ndAFRt>IL5)VswnkD5-(8lsMIG6HRY&$-<;X^awO3)G@UotKah3WBKK*-K zIq-@ezzU9)PL~W%XiBmXqR649p9qO=o=%Ig>Q9w z_LAP%{SuoAe_tqD+0`!kl>C08-_*D8-Lmht34Uj(uk|Jt&)azNM%N`4zDP07@K@|= z98F5_jjNH7{Il<9w7}}E_LXQKd?mwATQhu=%HV5Ejy&{tp2q37sGlbV7pWgj>XY^f|FYI1 ztN~gdgStvk=ZAOeLp}6&TJI{9LF;79E8(}V;3B?J63ePaS`ICnF;-qKvV3v%I{N9S zzK-n$mwFNx3m>b<_f8`zdZ&@gi@yYjMXHk&ywg}j%bX)anX9BS<#ap?RyWc%)3(zx z>(LL|PwK0cjxT*qMHk#RNBGFN>HXWPsl@mm*x-O(K$ogv0v}c+1)nNwMN@Oed-eP#zv#7v@u;d`(irU zQD3>Ok@iV$f9)buT6tMr@U}?nUr6&-ZfvA+Ihk{jGpjFQ&8QiyzZg6LO#0NQm)1x7 zOY5J5G!|uGT{S74t1qfbS6?KhD;uAuWp%ZItIU-8M=Dn~{*jgeKekv87?NlkS=FPL z)3HaZW=_eU;|*Pp!1)k0>&h&>Pg?z4YY zU*%q$_XuWbZ=ju|v{4IRyzt41w!hU#*Dm!5N_}Zc=K$J4eeapE-bWZQHsoy)cEzQ- z>H6o;ccZwiF&60$A^j%$IuhrTvTLj z<3%|-^5s=!?Mke7dXBy)oudZyQEOj`_RP3!ELhptldcVY<>fwP<)t6s3Va-`1$bJ5TUE);&ERdCT%1JlWWTjtjBi9Kr9Y$ge~n>7Gu; zdVnuuX-;@^TH}iI5#J@WzYoTqwvCANtpBp>tdF+w41T}98}=9w4kKK3Q22|@FPp3c zBIJHrzLZu^)AIEP=z&7YDg9l7qX0oIgmq^9pOR&e1~XO5=-muY zVTbMv0Qbc#R8H;)+QJW`9(woDd18r6#5s)hGUFoVyn?QC&RBU-kMnEAS)A9kB_gcc zUBua)iF-gg-+t5+=^WByTmg?xeY1*MB70geIaTX&ZZeZ1!S=AKBHamljs)0|ky^2j z1fOhE!}9r#7YTXbfMQEunH*`eBh;2Dz3XM7d}|*Kvyp7N9c*Zx5QQVlC$*5F-C%h( z#Vy;zZ1@6}V{Qk(Y`zaqvc;V6TxNIApE6mGBU1@zc6y8cImpzvygr}lqXb6`a!*nn z#MliU26$t<@Objv;;byWXMUF4yD7xLhE5jbfZ0BJV_LS_PGO!kPKp!qlrjx^`G6AF z8!Y6BP0&c7mfkN#jMb4~TPM{>=yeei_(eP4nBaWXseB;L&#F0ZFERQ?28BJB;bTH9 z%#>`ITW+gRP;1)tTakod0ZZOoI{aorByfuhk1XVWaOm$mDLf zvpx;_d&s9$%YYw-gZ~WKVcCGMr1N_McO;dkw^v7dvHc3Q%s35JpsBV9UF$@`={n!0 z(r`Lyhf-^mv>bhSzH>&3!%pp$nw-Gc=9=u>Ir_^I*zAn%=DT^tJJf#V{Kep%BfvMF z33}ZA$)Tv-R}Ofj*^?yM!S4YbhfEJkap5K7Q@}Cm^WYH5G2%guAQ`uSQx6o50psls zX+U7UN?4s)Ta}~s&d&jEy-*L^$2Yy4xFBhZUTar?9@Afd6u3rTP14}a&qyWX9vpnj z+k7P#?NA(GAVu|MBo_M!&@nyFBzdtC;iKHws(OM_PfsM-I?l;&0L@`8Uoj(LU5IfR zKm!4lWspQ=QPN*PWf>$-(_}z#ay25A-IA!&9|c6CsDh`4tl;Oz1hGKmJabFosZhIhmL1gSi>I$ZyYo z1l%8#2w5n5{xp&PD)%b;DY||y%Fhv%u(lY@QI!8+R}Qt5}#es{k()qn$3l^;M>6$Z_E|wTfFpEbb}Sv zf)ca_940D@Oa>}0Fh*j6Pc-${pd?TAF`6f>Xooh?3)0=-Ua|~HcR&*aTqvT-D09n% zn6vzQa-WP+jffspqo+K2iE8wK@i)dniA>ol>%4Qh$-nW?8U}ba=ja+3@A@2V{Rfn4 zWMqspb5K6RdgtaS-Hb_TRpHcrwLJ}7y2wzHhTpPf_R%8u9$U_~$^Eec)5d9cv@wjs zW=(SV8W#@`=SpSH{QoIajWTDor*%n{MTT+qMJP9hmRg2V1E7htamhQ{2xCof*e0P= z#za@hnk%xhjA~W20`>@Gi*KgmQqvHI9S9D#oSDgR5E0pgWiT(q| zEd6th7%u(0wfi~nzD}Oheh2MLXxbLm8j2=U+pyIBF;l9l=?+;%>d*8g+wGuumH7y~ z)OFl?ej~|mB(f#w;tPG=N|3Xkj}^ev|zuJ6V>i*idX+G24v$fLeh) zJBg6|hY1;70>2dd{RiS70!85u3SmVR#j#^rS1w@pW;prrpps<8QVM|sXABQ&#s;7g z9chqGpb{ok(AMSqWJ&lq=%x{l`il7jcBO@d)!mukXJn@^Sro3I6wcQ{FN~PY^$EG! ze$*>dCM3U$;a!)PD@QRVGbE&~?No=zCCDI~`+6HZ#0A67M?{9}+PZuGRG0Yb`BM~R!zeO6A z1*USqbacoFegv0hbPm9Hb%G)yhkR}%IHiqs@|ib1)UyWc(BZpNUFSdvtR3SN;QR+- zsAPB6pS&fY%uQ+{+9#UUE>856G!Z`D&&lEioOOM<%rc3;+Pel+3hr2d=es9CemKO{ zGBga|0?JuT0-sQ-RC^fkkAI%sT)+?S7KjYJ<1Hai8vbAawUy2BkaTh0RZt!)tYO&Q za6#V(HS#iHry^F6>g3}5oB}oW=TYNiKcmo9gXSU9T2Cb=3q3;2tMP%z2sxgRBCx6w zNWw;?&LhXHqzi!HUZp-Xa_|g!7vUSOjc>Qx95!0J+=G+&drGN;j^p>iD}LCJPQXfB z;9T%ItU?dv(wSBOM~)u37h&s;&g%r+ZjZqZ_3V*-?Rsc-$XXkUBEjxg=NEnz+HZ=% zoWpC`)eIx_H{dxW12U4?(0SttXFZ9#i}6sO3j|(P4r8viAbhzEa6XeDiG*0&n>z@S=Jp;Oad#GKJ z$LvCx{}?;Anl7&o2xbaJrN#tK%XW)M!Upz z)}CRq+RGe#F50dK*Rb%MqiFKg_Xycr8NGXWSbjL6c@4gOvf)2G5?l~5!++nwq?c@7 zjKeyG`pi$Es)b8!a%p^aT*a-{kMR#X)H0CV9J5?Kkg3=AVMPtKsl~%0*5=Df$**qF zPnJW9Ngf5H2~>eTs#Um?t{7ClZ)E$N`<<7apF%Si9uUA$wuARe`}b7j11t3o@bGs` zdb=$ythfo?bG@mFCD1e^-5{?!{yVCBs3$9}ecXHPjdsN;Xk4O%fn6ooA`vnf>mr!2 z*#44}j={@z#(%N~Fo%7=)pB#xN-~7_%UrCfSD3p^Th%Sh`E#r}*caL+xnhZxYf`X} zqzuq7u#Yw}EWb5dMf^&3c$jTveRAbrl?p%4j0`hDrH_#pD~X@w9td+c)3VP(+Zghmnc-Dw|- zzLolDd>4KEtGz?&qa9z{yS_fvdE9qGA@}i0>>tkN=SYzq_S?-rg=}MULy96$=$+T9 z|E^?=iLjA)L`L=Cx>@HH@@{o@qFv+J?M#A>m=YtGj8c=kO8rY`rm)w3+P(v$`cp`W zHeihxodi_O_y=PAc)*;*|IUiXt+FOgzBt98A$~nG93%0v3j0I$Kv;IuX?RB|hdu3K zVXhUtLv5jw@w1ANVa08&PeH!EW#L9)tP%`wV->unIvW}|^l@ijKPP`6Nh!t&k2y_# zPJ0~IO%7R^Q@tP!n^;IPZ+hnzk}N+)t9Zc6wr+)gw$}PXF7#eCEyv}*(d326Nsv~)kUvff=?qn-ka$idjx3C+=`AFP@_?RWMXC+bLwFi(y5r3(>|QNH>g_9QtQqb^X^#9# z$mSZNb&*aAE6nrUEQFPp(QIG}L!~rIm|W*-tIGS3{YDLA>K11G=reTv=GZ5TNrh!O z$~tQI^AoGqeIleUI1!33P+&d0k8y2BC6*77>Rv(imtv6`A>dT#`Pory&3-po6?yb8z ztf2q9^4b+Yh1z>X$Li^hOab%YItq;I1jP+7FYu=H&Ak;^T5t&((fFcX`eMeV_`oEc zbVrXMHy>L5Q|S2bqi4@j+Y5l=3AIY1J{};-KAulnT@#tQ)U;G_N2}}ESgjnE7C*6k z9f+0VeU?E>uv#lD{zSY@QfaYTnKvy*sJ?>ll=)ci5nEHw&z=C&gu1lsa*Ou#mEX-u7>chrj08@7-&z^zcLu%Iiqd{%j{^@%EIghw z-YsI6vNdxGp*4p+N(K}EsuJw7elOeBIh9E+?9f+BqI-66$;gC#R+oQKNs#W?($D^D z#~yNiBAt^;IZmIR(UtKyv|Py7(G!1pbjKEb)3sx-%V1Ti2hC>`|5VtkYsWrNsH;i6 zw__F9vAu+sr5!sKJ67>uJGKgCR7qt-g8kd61Z{N3R*wAd9Xs9r%m3K1<=C;1osf1c zYyrTMOMDUCu}`AhC%ejRYa>JGj-CBgbjQ9c?bvTH0?{2i&aq9}vE%X0_^xj*wncZW zxyRidy9BxDjx{2eQOZSkY%<=GyT19R?O;Hs)6`ema|G``^I3Z?;I16(xJ7nT{ZFBW5!A*IcC9wSsf9F`9_vXBPE+)@ICSr}IEcIbV0?6D zO54T?U)aysciVrlm%y{GA+7Jdy=Ij5nog^LKc+*LZvwH3dwY#6w~UtdnnufEuXTs+ zc67JZnUD0&z}kcivO*#4wueVxZ)lqw1UIA>I?{y>%n5nIIlz(Jq|hn6Q=1fuC+r-w zhoMpTgh`~a)Xcd~)-zLiG?2h3QJQq45KB&y=U=)py=R3?1ZS{9Up

    f*+aMERUAXQsn)%y6@*d`+Tz-l=QY-Tutw13p<1ykA?^mGWx zBY@>9v>ycY@?`hPfKsc)nu5J@9FV%uUZyTo)oqaBSZMEzx2&(bkA3z;=G?*@ixr zJLfuctxRBmc1{ZIVNWaisE~PX8fIJFNmS-AVkpRa+d8?PY6Ct2Jy(NUE?E5H$~>`j zT4~-=%xabMTPFz&P-I(=0w=Rgi;fhh_{=&``pVXs>68mjXPn_ZtHpn8<#WkdUZXg6 z%DdM7^?YDJ?4NSdu@l=bcG`XfC60r9@ncrddbQv9w6Yk>CTn~>ZM6w{dItBhgcxtJ zmGLKblKzV!AxPnAD=Z!#!MtHsMlF(h>S|h?Z1Kx+a#lr4C1{^Eo6eyk)$$j>t*ci4 zdJe|`%ce4Ma)H)C<<%|zYcAq{?l5te0;b;!*#13)=MX+FfJD%v;CUc!Kv; z>A)NC%-sszMTFPze(DkMv9}Nc6m;28yuX6?D!eBnOrJ)`i@?L{H^Uz&;?oen{16xy zc-oP+2Jug3p-jYogZNU!8!8AHiui2A)A5{w=W3*VHWhj;GYJ`t_$tKrBHmsO913Aq z8QP7obqe0m)_#b;fcW!>55?1r=e~CdIh%*JppCyp`~$?_M?4epWr#0D{8>DU@I3ks z_zH-#i1$PM+fDEvoC`(@`tTv*w}5otMB9GC^G7_NM%roQ+qe;aXAtZNEZ+S{--kf$ zPS3}49-am~wFvMu{u^o+0J;)QkX7-gL&gwvA%7}-RMXVbYkvdQ3amH%Gf)jcRWxzf zU6i_Avf@kJiAz_wllVXe`z~g>cm;*CUswT%05Iv)2bS2duS|4b9i;mT{z;{Mh5a}J zzg6H?<63`QoQT^XLxD4#O>rCx9R_wwoX0}7&mIe%SZA2ewXR=$%D&#N97gf-zXUQE zvtST6JHM;$?VK(7ZT=l(Q0%{($6YJe=)z*DtRb!Rc|L#b_WAHh7%UM-;#}EmA z8|rZxxS~9e0I2KHV%w|0Cb5?nzk@SC?%+@+ZGB5gqVr8q3?8H$ z&YLz@x}Q@|Z#t*>JdmoJRR1sBeCTd|RAOOiPE6gr964_KrE-0SV1^QmE6|#Paj(xxd0)4n=Vn3vd?; zg@mpGX1FTB44uIjBV^z(j8DVAqrKT^O|KhQc>EsjlJ3|dK|;0ornc*wd66ZB$AG)+ zKOThwDfY4e`6w*(KJvXU<)g4rCEhB#zM2&IjqOp}P3012Y9>|#pN`$OZ^ldZXC!#% zl@S!)0hDta`z1EP2?=&S7Vu7Nb_%fL9rxg!*(h;#SBZv5n(%>i_g@FRGfbUv586qm z(9YsyE$>(I-NStFcpx_RFRiW_N{U;MUa+Q7>x(7Glbt~E3q|*^;?_43hEX@-V((G+ zU>+OWp3n4;!aMI;qR`GfKs)^*`!ha!-aSYsjY2xw)JzH~+=X>|q7(`1i2WO29j}gu zg&hgj;qSvbWl>lMRFGf8I!U6Kdr^W{;xUG<%N0&(ZuI{f-l@+$E9J$B)(K1L@_rXF zLOa7YHBNwYA%n4pz^zYoZo;~s?F45@^LP$hM^A(nFSm)FI=yjwb7jCfGw&X}jwYF?f4X*?Y^xSEDFX(z?z>gs zLZ1vBpTTWaq@BcxcM_-FNt||SSfG4V5I_z7G$&NQD~H=e{D)m%frBLjqy>1G*8W$J*``VaEEpkVkAg#Lg$N;To#-LezxD$ggD}{kSXmu6Hfq(My9$|UlYn*DxlT9&D z7Pfz6x4r_LrS;W~yxMyh^x`3j3OG22S&>hnU~VhHiq(dhb|x@Ie$DZO(A~}H*c6J zuL73z7AG%jd2ml8IQR3((=>qNJ^`FNAhy673&=~`MC5cA{SjY}`1^?e!vb3)h(C<@X2j))8xdcO_>Tf1PvPmo^VC~} z#38;E@llBXxE6M)CPJtn2e!Wu=MeuR;;Ru)K{&hy`h*hzhuBaa;)mV@U*JK&DcOKg z5Wg@U?MK{+_*jIWk%#h3V+1?3G-fslEkX8|T~^ttj^OYJ>7#`#L7d39$yzC7LOOWl zgWV_XF$H%T_U4jLz^)g#C*U8q1k-#*iLamsy@m29*Hn?4)0ZEoSPkwJ;?G-t&6!~? zu|9vcHlITDOKk5sDUXG#d&ZfXfZMeTp8v%;UNQglngno(Q}l@~!9&fHQbG!O8`F|- zrqH?F`fwd?&E*-+kj-jPVu!D=GIblQdD7WI{Jodoz5;)5f-9jV_{@!hPahO_O!+W( zqqW%fy8G(@v2_IJ+@R2wGc>@t$jSH=s@xp8(9LTH-2K}Scpvy}PH2A@1Xg7o*ricE zB9W^heKumvbp*e>z6H0;)T0ZX?Y6|Er-6s}D}7_i8+mW$zHCF<`j>3=q2tdM+t7nzSlnKJ$0l1RFI8>)@ZuO}vGa2$ zvyLrQYzV_=q>5(-TKwfD-TVqUQ=W`oDCKg**CzZ9P!h|*&T|P{(GQeS2D&tI?GBus zR>Q`eTK}>VWm&OpQsG+MSJ{pgzyo)<8l9&@hRP4DsUFBHNU+3Cz!JNiJ0NfVRPIw< zd-1b2z!Va8p(iV%a0I1(R%M)eBKHX?j|s8}6k-@#lZmGuw9f7|uvdYU9$hfReX1uc zMjVmO3Y-Cy{wX_EkUOKRrsZu^TjdeYI%RFnT|~k*{Kn^BfIij+7=Y<#EhPhY!#x%T~tr?slmBJq&%EBICpSY?g4E~ z8C%{GoN&FkCNrPg#%@_+W6MV;D7I19n=5@d5p>BSK;M(x;&AovJfGs6x7MYmJD_tx z&z6m^Lz)tMZ#l^Ugfu{j!3lM(}@vEx{nTYr_#7E+3!}AlQ?QC_ukbzr7Nmf{D1F`gdW;Z|@ zJhMikWa2$1Q_JF(*<<+%Hq&Bp$6UJ$cfev-4mS=Od5rQhC@rwH5$4(*4$K>Q#A(7E zBa~Q?s{ywNIDY^3UVjH!>^1N#U_C9Fe`ZqymSpz!DMtg&O zr~Q(hr0sC?KeH9tj^56x+yxzWI?7&X1!3jz^X=Q-n%er9r+B*j&3})?D zOj^5*4Xf@%F&LG^NjrrxFOFg`4CDK|>I5(tLm~WM*G-o&7<&{yFmH=uFqG!%I*4zk zqK2tb4O_)4^we?v#hOM>ozkR?1|hQbn@JFuHd%PZ{*2wsm| zdMQ_O*V&UEGUfo6r7a!U(;?A(A%lVHMJ|3KSceO+mK?DQd+MpbaLQfbD6CB zOFPyFFj%u^FK7eblsxV9Vl5pj=?*HK#cu$WC?5V%$_iIm4Zws!EkFJ@!<@o)+mH5* zR$x0s>3+;%w=3P{xW$t7TO5A|Rbh7twIZ6-{=vn^3f}^*T;`nT7}bRh`-z5HUD zpHoea6Yt+Da-XE5i#NNa4jw8lQdZE`jDTGxqL8j7y3vSa^iebtB;0rvsB`k$-o znJ6amAFHcU{AcdJq_WG!Uz}$!!hf~)hMlhH%DUfzf8_q7s|C|TKcJ5PTvPo|eVhBO z^t(}9R7h{Gi8Vv;)N`r0$^JJt0F*pf905=H-c5Em_i$Goy+d?e&GgjdH~nf=t?F7; zKm8X+V8X9f6(}f_hbOHnnYcT5k5pnuuq8rRp#5t*BWN|BkLG*{SWh zJG$~WL>3lqsNM$3VU%-6`2gxuTe`3iSWL~`(v|a@$mV=H`yb9&Vzb-l6mEq4$9r~# zcdwWRsQbeig_JHLd&+)OnVOkWzwR!!6Q%isM|_{=uj=9u%TK+Y`$kvkWs&>b;T6Dt z``^QV(*S@*Ck_*EcQ_MiA~2BrA_U+nk(EkrRLb`h}OOA@vJT?_Vak;C!0 zlXBZkjv>H+AIzpUHXpYi4;gArVrnMrZvJ2F7q`!UV862a*zc23XvGMNvy{?r*(u#Y zDdNMq4@*7lCC>UUO8*v#7k(L({+$lB_)zXcQa(W zgpl5dKacnh#IFsfEh~g ztjAM}Gza1b5kI~Rbs+vc;+2ShHxzgd;suCrM*QXjct?B*;-?UQ7S9uSQhlc%5aRIu zG~P!eF1`vHtr_-7alal$T!pwD@t$}-isze1Q)Wb^thjn5Y=75w9v5|x!PECykdlrQ zMxRc^xn!rcy)Ic;UJf zhI~^Y>F6lR*WL!_+P!{jg0$X5X zr=m^Mz!6(yci5F9VA~eI&4$!F=|imk>JXpv5hON0DkkK z3o;;baG@1yXcjNe0j|~`@5z8Pr~gCo8;ZHU5?0JQ z6UwsOeAkuG`_F(Q3#S|d?gU$w&ci;7&T{h&td5OG`lB?+;;CQ*i?rKR0llgLJS--V z3dopK=3A9boH7sA@~pzG;P_uAB`@+UqSiEg3UytQ!o>MN*Gq$MH;g!|fCm#;_vZBl zc|SmI;U$}{@F3{mO2KcG%=WNH(~*#JKl+YcI)4`e&D>2LPI;uwtOyC}cE*W)xB%B<=4zN}58 z-_q~ibi}~xTB5DA2W>Zoi=;n;a7gGE{nfPL-YOY& zgJN-VPp|6HSR;Q7t3j7fhV`S4;Lq&};b1jpO?yNkqa#2593=mhY4Dw!_DSMsVK*>B zc!|gOz0yS2S3wwStN&gOGyobQaDEoGU*T z6H<%71X5USK9x3{?N$pK%gk;hOLp!t*h@I_%%Y}-1}p0e6KNa(R_NtOE7*LUxHEG3H1h$<8+omY;taBnd1nUNxeq#`)DG2m5smcxCc+vAKvwux z@Z}rHfHIPt3u@+7rwe_YWMG@OpLpJxUfpX71AM8Qy=-##-2Qz@A6e0@p#Fy3bPF^q z<|DNrhpwn=7PFDtz;3)1%)KG|C{19|j+r-Z1>3LFd_Ufx?b>nuu|hJS!Fw7y$R8j2 z_(vfJG$o8dF+$OSZd2s~)f+KlPoex~qdf-HmqE^f&QwU-rScypn9+W|IXhYHsRE9h z0sR8msrKN6PP!i{{fEkh9+t1x_$Gs0s*gk6Yp1uc&wm`!TSCG2+L+BGEwLyOS}Md{bby0wsUG+V z?}=(a-|;fz`wIU~?4D$RCco0FMC(YqMr1OR-7@G?Gh?YHI?1~2WkzQeSrSPCZ68T@ zrRfiFc3!aBSJ*j6wnGUS<@Vs)oucGBIeKG|K$!y8fcjCrg$k?w{8Ns;4p*A!9D_O% zp+_z|*A71@R2KJ^M<8}0J7%^V58*rmY z(ln;+_ET5VoOb7O>n`_)_LJvu(?Cao_i`^91xv^ZB!p9N=vz)gOkd+pGxa4!50L1@8*k{n!c^ z3;TkcCku=pLodixup570F8YgTxp~F>zWAhZhZt|HL|V9LEB)PGA!6lN-W8R`O^8`6 z>qU#PRGgB>>@!1xH4^LzyLEp$Klvfj2U4}-06~>@GdTDcQp1d(H%~A8+Tu+XEqTme zM@#uTp^x*#`3I%^YFPB8J~M6xd;Vgqxm9c)r^+gGGb89Z6qauKW-l{vuN!(P#z)1W zdCbQdQW?~55?#>@QJkA1nxGv(K>uShIB$YDVCv+3uYf}f`+dmehwLy*MvHy!efuR+ zW6x!FeU*)`)ZVL3lEIw61xe4zWiF*jOuSddXUKic8z;60-)!#(xFi;1LU7(P##qs4 z)Y1_$tLWb%IV^PZBHf2n--=lBs{B~*RWTfi=})B4+7B=mLM_5>gp~+?LZIhY?EdMX z;}jj(T-9?o=^L{?buV_IzUQW1o9I5h6`U2uDZEgbKNPk{m)N>*Qg2Au$d<~ngJDTG zlmrS$k%fbN`}dIJr}W#OLeBsmdgcwC&}IY1n!pPmx8}V%7qYQ)q4_Y<$vMB-)I*?J zHo@TIq3MuGgY@JWgaLwZRCsOI5*whWQho#Vx5`(IEr!$=sK7-lf$P^W4?x1c^s$ge zuL2F0rMeW7RS<*wtRVL$i4G?-YEE*RJvYT}UjUvE-#}~W32SfXyi8fTvmm6>Cl)IK z^Gn}WJ<+6j?%$_RUg?|pxc56jZG#UvMN?uB|A=3XyPm0k2Jc+Sbn*Gj*~sy1=1k9G zq=a41h{c&td0x&e@VtQco3447b)pQ3^PMD9fxZ%0dDzyDZI)qyHMKP7`VjR8Yw>$m z*qu08My1;)L8s~AD|s!h!q>0l`CY12SH=}TnWgd+W+^<2vSgkYvN%t17NpJrBkR-i znmE<-S71Q}x_M6c(9HAms%0(D{FQki54Ko-e`Rd(Gnq7%L8?Pa)vM;w(qDQErCU^w zULkFoTRUOVZiB4=DU2$wg%naNEANRkR*t{QyvZV;{;tTTZ=%-R#{Cwx6C*3d8RLbJ zvUa|pg8iAjHqw&f*~{s?VNZm!>`qE=xZ z5))cniEcIL{hR=}T!u6Yyuu>)GS-7!_P~_{ zzaBn;GM#22(CaAtpI$|ZOD7BP9Ph@rcK%nt^%mCtj8$C)8smp^Lu$e}yJ2tK4j$;l zjvm`_3F};02JOfvnocfe&d@QW7HYWkU(fjmZP7VDvpfNsgxx)vqTQLDvcOKV*bB^1 zlU*TVZLALl*R_!fx;Bn1XGW<(8~T6kU3+*`)wN%fgb+f2$V0-@LqaqOWC*WoKpuIH zgjZrfg#sogGbfob^K#A%Nqpsi_@*ruDj>9?wKaqY30H4Ht;UvCY_(0STJUObw9;y= zHBvMI)ZE|N=bV`dqPM-@cmKLMUrv5!@4fbG?X}llXV2dIoJhCqirsmct*keueW~pQ z>^fAicXXN)Ck?j8ewajs^(li-zIK%@_Tgfj?e>6e?c~_ZLD;u-Nw{>yan zjmiBUI~$%fx1ook>`uxoF^1bjUjUyq%T zS~<3ZTVOa+d)HC^5cWTcGsvJj zQ3EbNrQX|1(q}36UQmyj9gvE4%$j3`PEOo<>`~B5Gz{~WGJ11brDfj9Vi~_1Q|8cc zDfWp{q_pWd4eR1MraCj6m(&-gtf{vQe&_YMwjtQ1#pS?E+^J8OLMoFiyK!3mw%DCD zw)@wtz+TeBSaCbbkRj}S9LlwZWi@n4<){uB-x_B=vOKxY(L-fNr#N$j#9&2V>~Y*VvxHmzMCQ*?63%n0jzrmY-|8!8Ya;zFNB=?{wd&y;!@9ZDco8pgptCrfAZMX_?bIvNP9oW_GQ~oY4_? z;*n4CX;4PliAh~@=8E4}XO25rpIOqGD)#xscA{sO;CKE6NXFun=QEM|6`h%9%1Wl< zd%el+3y>n88EFA^;)v5YLl$%uSsj^Yw6%!2_7b?MG_?c&EBJh;7_7s#B*mj=+*vRd z=}-x43UFpZrIR%)z7F%Y-j@=@mB_gO=fPP1KSTL`|yK0LG|zM1>| zcFdf{Zo+v%NmF1;B%S-5&kjn8MT~mvWTPoq2a}QTJl@tVLyqpT#lU)??z3l+mOZcg z4g6e5^8LM(6W!u!| zv!J~pM`v-t>n!6^Q_Pwsm_u0^Rk9ww9Ejv_mxPmW@ioQux1VGn3iSj#FuBXhIc4g znVmxgr_%+ehYK!WhUesxgsvfH_RZuq4$R;8=anE0@ON63vkW~DC-+A47o%OqS=yuX z_XWY3jiaR!*|9>@&Zx@-_Yj*sj~3;c|%+_aIk&^DU6axYprI z*Y(Eaq&Sns2=F9+O`Y0aW_xirzDF*Na^hqjoMyeu_Wr5!J)7|rz>?c|&B9%ISW5ug zi@)=>1@E+*apU|DVT*0H`Ndw}Yoqr1f(y&y9=c>)Y5iENo$l$(o*vuDewHh6hVJx) z=lMB$pKl89^QDfqoav*mOP{}K!Dp$lmS^2`M4YF#)P`{>W_+8Q_xa8p*);*wmv$sx z9^aK{jq6CZ4(Uj+UfMYf*2+ANHOvFy!((b{AyRu|- z*DTvV#0AT z-|bZFyWLVS1N&~XI+hiWIAQ55!0y=fyh9zW_98wj?J;e2iGNKjPR{zQ=W+b{wd4hSk1uDu zbEJ@+R(wTq?cm9;y%|5`wPm0imQ5&%Lv2!r-B=vz2iUUn%~3=cD)Tt4!@q z7`{)&&iF3ul5by*Ju5%jlvexEVSI})qoCvWy>a_w=QYK1|1<8Byy5=h37w^QLp$G7 zgwgo79ci_2Ri#wYr?;z9Y6s0;TDhaQAbGccM{j=n9T*XI^yW!g?-yxlm1D3+U@6Ym zJKt0M7EBaNUc4Fk!WnCRNLMgr%iD#n~ZU;*Rme=%tWmD zzc;m8N=kL{{{5wGX;{@Ae{wB>&#@V z_Uf8NaMmgTuj1yXfb4O&)LMR26}!*tP=iQy(FR;*mP&mvAlrkIuj)p{9#p03fX^dE zN-*CjS+<1e)vg+;+T~WH42M!JhulHQD|-|{4X$$bnPGCh5Joln)88zZ93eGIc~M%I z*A)yntVljWuUAD9b-8FH5i(1U6xAr%XgHJO(zxK=6{i zY9*7O>p0ZPw`t#LfYRK&G0?|UCO5qrCpeE!&+NzYHDjSu6?3V1ZSE^DZf55lV?EBT$Fu7pxT5`&&6!dY)z-e@}uXecUk}n_yor+{It`6OcJ5wNN?I-rx z_JG2S{a2eYsuiW^HvEPrG;)$9uTp0Sndlm-Js=0|PG|^mxvE9EquN(=5SNO^uX6kB zwUR^G=&~!*B^4Sc*dW=R3Oq#xxv7)@cW}kQ43amp8uFnn>jJKz%UgpqlzNxSk4AQ! zxZ0ow6%R8;Tr3AjfdxShD55kf_sXCX(tyOJ?2uVlqg7eX%(mnxEO>Iz7ih31QsP$| zM=F65nx9CtF1kV+C`;D`LIo_8(pCH=Cc;A3#HU_HC1>T<<=vJN`GC#X0;-uUq{(bY`>wfiCL1{Cp#qB z;Rqm2MI^X<*zI%FD)sWLg`4*>kId>6>^QsE?vhOE>VO<^Ab|(4Y}QV zKtI;?3lZu%s?GWZGV4^y<5Dq7LAF&^W|7_irVJrz;Se%QZdS~#cx#{sGtwQI64DF$ zd|)#qKEor|OYkHXE8>JW15t8lH!p<44!MT(2tmWWBo;FfU9U7ZAsN*a z&w8_nM{Wu6!2GL1dmCC2{VLFqNc<^e7iHr^79q+uv=C+6iOY@dgO<@pM=_u%K_vha zg0ibAyOy#8l&y-I7-J;q;~zzaHi`^bWQ@n$`=h1C=v81Y1cK_K$;^f`!lDu|+S-g{ zD3wU-n58xdOm0K6AXpG+lYe242p_{f>S zHx$2vnPSvQ=wjg?EgMW^P()&w{0T?lCN_jgL@)>0L-4y&R@MSFyQd z3~W)g$$(DW2yJO-MkqwHZc!t#V8w+6)itX=nCm%mhmgN^ScMFl>RdEBOiCyNj#KRm zc^wE=0s*gYVY)*+@mL{bKWti{Xww9LSA_?!T9}A3Mj;2yhyIy4YxbPE|8`~Wy!?W~ zqGB6isEG2EtL!ioDT9?vCasiL;*0E7reV=vMpzec?)iq51;b1YhSd}m*DH2zTPQsvi2_KT82Y^-Pn8nj zB<)U@+rictmqJl#b)Z3#Yh;&~N<%QXt0j-(;qsPoom3SzK8yvg3w7hf%n}qtSrJk| zxhaHtI;cok6%{JhTPf9UUmdMBHK5NAOIFw?M!LZUzruzLn6Vm4N#{5DI3ct&*&rsEh-{9DF5aIh8<&g05;8-W&oDu#KQD#F&X!LX7q-no5Xl!+dvhNp-r}EN@DXmV@6HO|C593;OInx8w-m z-6kNCm4iVUwt?ugg{w;N<`xLqgCUrn5e}KfFmfv~WKXHr$9rfET^P9sDCml)vOVDP zqr;;!8a6>S^b9wG?DaXohYMoZqdir(FDSZMwGXdnqT}k_+3Z=mW<^OA*~4kVLYAY7 zyV~VJ<&=8A=#55y)~Quyk?4{t1Pn?5b{v~bkS_=TzvW=Mpw1Vlr83!G%Pq)3E-#D# z2)u(z#hW-s;pPjXg_zg;5>=%@xW&sJ$nqUvZ_uTpyR*imRRIr6hv6#3`(()Lvg?{t zP;l;$Z3l&$NRPMz((iKm{1Tdp1rTYM+g3@cU$H}q>|qrtbOm$45IhoArLGgXAB(XL z`X2Rl=gUUfHw)f&GSA$Rb^%gXNJgA`H`ItTBHkgA{@;O1E+ zq*4`n&S;*n8V;#2K4}&7j{@PYERF%pJKnFVfKFp^@ zgt%JvxG*a8Pb*&^zG13-H4rbPJSYn-g2zXbj`j#z`WAE9B8Fb-WaD&ojJ)T8;D;G>l#0fur2$!FU7G`$I$!mcfTd5OcsX-C{%u zC>vomIfy;$Kon4TDj4NOM}amGwpeMM7cK5!;}o0&|5-TL*ufwqM155-zgqO*gIqpy*_4DN!n{bHU*Nyq9 zej#~zc~X8sY5D4sl~?0cL@HS+5ylETEh)|~lU5Y3C@o(r6_%ElUt6}iq;w^fth_FN zc}bBZg7b@t%8OU6GOBC$hwz@`Bd$9n5(Blt25^xOXgKjIAjnoIp4E^9_k1ZGmS$}M z!NV3%l(3tB$GG6ix!@WEnsKBUaUK&=IOXr$Gq?Ac+W3%ys=lHw#AxHxH?AK z1#bDnPJzlRuP{m#`(g@!?{8dkCF7$z#(RKyr}pMN3fwmN*t2f{=Uo12ZBikQQNOa` z7x{&>@5G(g&)HZ=$5+;PUN}%l3m>R_Z_PV}d0U^VpLA$UQQ61uzVY7pWkuh6eMS85 zy0xNb?>({e@T+?l%znJ-^|a4Q<}G~uOwku3emv_3JGcHW;puhhg}xR?M*Q(aGySpN zK~Ft(WV`Ltvx`57EzMmqYf{eHC3Ty>Wqw~7heVQvVknm4Xb{EIV8WOEFn2bTl4uwW zrxBD)m(WNWMWbm9T}opq1$-P&6KEn$qRDg_;ecUEr8JsK>2x_=fn_h5ltt5MI*y;S zVzGJ-&7@g0o9575`Zv0ga%mpTr>kfIEu=-XnD9FoRgoR5Mir{28ggRg=#5m1)uSHr zVg;$6ZlVBIg$5}^8!^jMk3~>7(>hvD8|VhApvwPM{9CYw^ftPk8cD<2(9LuQZJ|5q zF1nlUp?m2*x}Ubvx9L0dUD`$u5I!4AIBK3Aq@A>jc4K+c9@L41JpuK&_Oyxt<*+`>EG!|dW!yoeo9B^C_PQj(6d-&`WzPgw$lsr zb9^%Q82yrdMK98EdWn8bzoD1u75XjxjykB5UZvmDYxFw3L4TkVbdui0`qa1RZTchq z7Z#MiL+{d`=sh|`f2P0C`}6_*l|H1u(MR-m`k1=u6FN=*pfmI-eMUXhOK0gE*3*7Y zU(lC?=7#{p#KsMZADl2GacI)8;UkhS898e7m`lf|j2k~;;-tx!NmEkOrlwzhMMh@U zwCUN_8Ic)|`ByDixM*>nKBrORblq6%_IQ2%n*wSuw6U(f;pTPgH{4KB`Sszq+zu;^3jyw!{DaVSJ)MPxF@;)6&Jn?|9o*-E^_Gv z1>%ai$i?B|e7^3%$mRbGz>1&;FKIq|g;~e6JV}7+Ccyn z=R4RxI-R>jUi(E}(f*vineR*Sk#shLKB?`1h0|#s&;BS8t}KyGg(&Bv;`xxES$sLu z=>Crl?rUVvrXe~`9IE5;i8_w%(s5hgmyNAMH0>?M)+VhormwO0%f80-v3+p2YK#Xg zZQ8^*-Q9|GnSKq@OCUJO+HgT9v*8=47J!`nz1vY6X z7!M_Dt4Hc|4#q=q+Vs)vZql{^3Fiu|AJf+u2duwTr`sy9S$hk3Ao;LXKUVkOCa_sM z1MEV*$|mXQtN}KSXw#kq9t0Lm(cQNKIltrSeT|0(w`on8I(;j!S$j##n8xmdTCcz+ zji$r>MPK7|M))^n0}+4640bnZX9TurTW7JmSz9n$r|X)_bQ85T^ZOcGV%xO0fI*~l z>jFLAR>r1r+7aPy*7hz$`4;0l2a7noS^Jy7Rs);0V4faN6L?VDnykzY5E%Q?Le^-XBgdW&>-LNV~rc43OimS%L6FIQ4dw zPS*w8g7i+f^!VD1x_?q_U*i*?e+$@pC|-NnjrK(S-t%yHt9Flc8NPk;^{o}P0s?LwDpiaLfq|>zuY|(P-`Wll!Pn-K1lYzbW>-?Db zZKm6=trvJe+aj<@+a<77YZBP3wF^9``M<;TP1-Sm;FIC*1s*$(Jie>vo688k9|InN zzhj&3-vZ?Joc@5GPLaUOW38mmoPRB(SpGJ;Quz@bd;+_gg0xS16e-S?_v68ZJ)p+%I;QeIV0LH z<%k|$$#^JH%l#R<4{CdlF}7$$ztY|9#~E8SdI`8cUTb1RdAk|W|8jq=yXyr){|JO0 z`wirDae@|ng~MAlKXCoIzQ!kkhn5`Ha{mB-l!H!k_(9F_CL{F4z%{^u0S*jsV1NSy z92nrh00#y*@Qob6(snT=#dzBo@tTX*zlh&AMm7Q`dn}k0z!}#-esNy}j0LU%#sQr` zo)6Z5@xc3l{F43{5T}38Gr%FhSAbaJNpAy(0=t1pz;nQ1zyz-aGo(0s1~>wEIgqD@ z762~+t_F?-Rsu%>1HjS1O~5h02Y{CX_W{QO+kh#+Ujliq`Xq2X@UOrLz_Y-KzyzNK zbFY|i22KWM11|#>0wrKMa0>7SU@CAkFb%j5I2HIDFdf(l%YlCet^it83#|lB z29^Tn0?UBwf!6>x0n34p09OG!fvbT%z-xiSf)=_CI1hL|a5-=da2;?h@Mhq*fIETf zfK9;lz!!lVfPVzu0Q?kK0UQysP$h67PzJ68RspvF?Z7=i2k;pnrqSp(z-r*Tz#8E2 zjTX$d00Y2cpbE4D zgTUK>A>el4MqmrD4tN|`5BxK*0eBvWV^Aom-a@wkCjf5+P6P7qHVc6`T8YYljlf!< z2D}Bh3Ahco8Q2261Nc+m`?2W9K=ZmS1GI%`uSFL6!Ey_Iv@{aNGzmY34*0%>?)fET z{zdTp=QtbjIne$B?T2USCl-341AP~_2e*tn7k=A7lLK6Wdk*ehaPPyt0MA9ZhmE$- z4!F&$<1WbjCbaJk=n34*aSvPr92nrh00#y*Fu;KU4h(Q$fCB>@7~sGF2L?DWz<~h{ z{Qu=Z+yzzVISQV4;CTq1gW$Oc|MQW#g$u|p>cltO`}wcGNSe3)i)ki`+15z1trto2 zo_{h;bIzCNQFj<|*e?llDVWj`^ECX-wea79|H=3sBIau-5A&@%EYy0tg^o_Ogy)X$ zOxK@hG+4-dUWjM9y0CD*lyUXSYcr)e);U(5uVjAnJTM~ysK$q7$1|<-@_BMoR^%!d zS$Mv5P=5IeY2%d?pEx)_!7?N!F*eCEGH$eGjAd+Wie-Gvgjj4+5QnRPm?nQZ_7bwH zPHc$6Rywi(0UvLoA}f-z!h-|!N0+0XtXS>F+d?bkKtOIFYxFbk7d8EPi>FFf zPRWYJcSw}1HQ37~e8^gbMgLYlOapu1$cjbkinYcY0)^X=jiu_m$x_c1o1Fr#D(oZx zJt!(1N>!+axA<`R|G8@@$hb{-UcFtz4Q%PcKjT6(iHqBn>0)sEWy~YKgR{1IGTXSA z|9tU0xJkEK>?;s%|6Gmz)iaxIvH!z4e)<%{V!O`fmjGO!HMHiRbY zbN=k)%cSRdW}e#@vIe>Y(DB^Ad71h0eDMg}Og9>IqrWCSp7-UnnQkKJCVmYa&-0pe zd7#S!U7nd4!X(^$@jR_br$OE|%rD*}LiB%T6rQIw>3CiSJ8%y+J%L+5$G>fumzmx}@Ian^(|<4M m__qV|;> /tmp/ramdisk/init.rc + echo "service userinit /system/xbin/busybox run-parts /system/etc/init.d" >> /tmp/ramdisk/init.rc + echo " oneshot" >> /tmp/ramdisk/init.rc + echo " class late_start" >> /tmp/ramdisk/init.rc + echo " user root" >> /tmp/ramdisk/init.rc + echo " group root" >> /tmp/ramdisk/init.rc +fi + +#remove governor overrides, use kernel default +sed -i '/\/sys\/devices\/system\/cpu\/cpu0\/cpufreq\/scaling_governor/d' /tmp/ramdisk/init.flo.rc +sed -i '/\/sys\/devices\/system\/cpu\/cpu1\/cpufreq\/scaling_governor/d' /tmp/ramdisk/init.flo.rc +sed -i '/\/sys\/devices\/system\/cpu\/cpu2\/cpufreq\/scaling_governor/d' /tmp/ramdisk/init.flo.rc +sed -i '/\/sys\/devices\/system\/cpu\/cpu3\/cpufreq\/scaling_governor/d' /tmp/ramdisk/init.flo.rc + +#add line for CIFs +tmpfs=$(find /tmp/ramdisk/init.rc -type f | xargs grep -oh "mount tmpfs /storage mode=050,uid=0,gid=1028"); +if [ "$tmpfs" != 'mount tmpfs /storage mode=050,uid=0,gid=1028' ]; then + echo "CIF hack found!"; +else +sed '/mkdir /storage 0050 root sdcard_r/a \ +> mount tmpfs /storage mode=0050,uid=0,gid=1028' /tmp/ramdisk/init.flo.rc; + echo "CIF hack added"; +fi + +find . | cpio -o -H newc | gzip > /tmp/initrd.img diff --git a/release/aroma/boot/max_oc.sh b/release/aroma/boot/max_oc.sh new file mode 100755 index 00000000000..faf5c1763f0 --- /dev/null +++ b/release/aroma/boot/max_oc.sh @@ -0,0 +1,240 @@ +#!/sbin/sh + +#set max_oc +val0=$(cat /tmp/aroma-data/freq0.prop | cut -d '=' -f2) + +case $val0 in + + 1) + max_oc0="max_oc0=1512000" + ;; + 2) + max_oc0="max_oc0=1620000" + ;; + 3) + max_oc0="max_oc0=1728000" + ;; + 4) + max_oc0="max_oc0=1836000" + ;; + 5) + max_oc0="max_oc0=1890000" + ;; + 6) + max_oc0="max_oc0=1944000" + ;; + 7) + max_oc0="max_oc0=1998000" + ;; + 8) + max_oc0="max_oc0=2052000" + ;; + 9) + max_oc0="max_oc0=2106000" + ;; + 10) + max_oc0="max_oc0=2160000" + ;; + 11) + max_oc0="max_oc0=2214000" + ;; + 12) + max_oc0="max_oc0=2268000" + ;; + 13) + max_oc0="max_oc0=2322000" + ;; +esac + +if [ ! -e /tmp/aroma-data/freq1.prop ]; then + cp /tmp/aroma-data/freq0.prop /tmp/aroma-data/freq1.prop; + cp /tmp/aroma-data/freq0.prop /tmp/aroma-data/freq2.prop; + cp /tmp/aroma-data/freq0.prop /tmp/aroma-data/freq3.prop; +fi + +val1=$(cat /tmp/aroma-data/freq1.prop | cut -d '=' -f2) +case $val1 in + + 1) + max_oc1="max_oc1=1512000" + ;; + 2) + max_oc1="max_oc1=1620000" + ;; + 3) + max_oc1="max_oc1=1728000" + ;; + 4) + max_oc1="max_oc1=1836000" + ;; + 5) + max_oc1="max_oc1=1890000" + ;; + 6) + max_oc1="max_oc1=1944000" + ;; + 7) + max_oc1="max_oc1=1998000" + ;; + 8) + max_oc1="max_oc1=2052000" + ;; + 9) + max_oc1="max_oc1=2106000" + ;; + 10) + max_oc1="max_oc1=2160000" + ;; + 11) + max_oc1="max_oc1=2214000" + ;; + 12) + max_oc1="max_oc1=2268000" + ;; + 13) + max_oc1="max_oc1=2322000" + ;; +esac + +val2=$(cat /tmp/aroma-data/freq2.prop | cut -d '=' -f2) +case $val2 in + + 1) + max_oc2="max_oc2=1512000" + ;; + 2) + max_oc2="max_oc2=1620000" + ;; + 3) + max_oc2="max_oc2=1728000" + ;; + 4) + max_oc2="max_oc2=1836000" + ;; + 5) + max_oc2="max_oc2=1890000" + ;; + 6) + max_oc2="max_oc2=1944000" + ;; + 7) + max_oc2="max_oc2=1998000" + ;; + 8) + max_oc2="max_oc2=2052000" + ;; + 9) + max_oc2="max_oc2=2106000" + ;; + 10) + max_oc2="max_oc2=2160000" + ;; + 11) + max_oc2="max_oc2=2214000" + ;; + 12) + max_oc2="max_oc2=2268000" + ;; + 13) + max_oc2="max_oc2=2322000" + ;; +esac + +val3=$(cat /tmp/aroma-data/freq3.prop | cut -d '=' -f2) +case $val3 in + + 1) + max_oc3="max_oc3=1512000" + ;; + 2) + max_oc3="max_oc3=1620000" + ;; + 3) + max_oc3="max_oc3=1728000" + ;; + 4) + max_oc3="max_oc3=1836000" + ;; + 5) + max_oc3="max_oc3=1890000" + ;; + 6) + max_oc3="max_oc3=1944000" + ;; + 7) + max_oc3="max_oc3=1998000" + ;; + 8) + max_oc3="max_oc3=2052000" + ;; + 9) + max_oc3="max_oc3=2106000" + ;; + 10) + max_oc3="max_oc3=2160000" + ;; + 11) + max_oc3="max_oc3=2214000" + ;; + 12) + max_oc3="max_oc3=2268000" + ;; + 13) + max_oc3="max_oc3=2322000" + ;; +esac + +#set optimization level +val4=$(cat /tmp/aroma-data/opt.prop | cut -d '=' -f2) + +case $val4 in + 1) + l2_opt="l2_opt=0" + ;; + 2) + l2_opt="l2_opt=1" + ;; + 3) + l2_opt="l2_opt=2" + ;; + 4) + l2_opt="l2_opt=3" + ;; + 5) + l2_opt="l2_opt=4" + ;; + 6) + l2_opt="l2_opt=5" + ;; +esac + +#set undervolting +val7=$(cat /tmp/aroma-data/uv.prop | cut -d '=' -f2) + +case $val7 in + 1) + vdd_uv="vdd_uv=0" + ;; + 2) + vdd_uv="vdd_uv=1" + ;; + 3) + vdd_uv="vdd_uv=2" + ;; + 4) + vdd_uv="vdd_uv=3" + ;; + 5) + vdd_uv="vdd_uv=4" + ;; + 6) + vdd_uv="vdd_uv=5" + ;; + 7) + vdd_uv="vdd_uv=6" + ;; +esac + +null="abc" + +echo "cmdline = console=ttyHSL0,115200,n8 androidboot.hardware=flo user_debug=31 msm_rtb.filter=0x3F ehci-hcd.park=3" $l2_opt $vdd_uv $max_oc0 $max_oc1 $max_oc2 $max_oc3 $null >> /tmp/cmdline.cfg diff --git a/release/aroma/config/buildconfig.sh b/release/aroma/config/buildconfig.sh new file mode 100755 index 00000000000..481ad454e9a --- /dev/null +++ b/release/aroma/config/buildconfig.sh @@ -0,0 +1,117 @@ +#!/sbin/sh + +#Build config file +CONFIGFILE="/tmp/settings.conf" + +#S2W +S2W=`grep "item.0.1" /tmp/aroma/mods.prop | cut -d '=' -f2` +S2S=`grep "item.0.2" /tmp/aroma/mods.prop | cut -d '=' -f2` +echo -e "\n\n##### Sweep2Wake Settings #####\n# 0 to disable sweep2wake" >> $CONFIGFILE +echo -e "# 1 to enable sweep2wake and sweep2sleep (default)\n# 2 to enable sweep2sleep and disable sweep2wake\n" >> $CONFIGFILE +if [ $S2W = 1 ]; then + echo "SWEEP2WAKE=1" >> $CONFIGFILE; +elif [ $S2S = 1 ]; then + echo "SWEEP2WAKE=2" >> $CONFIGFILE; +else + echo "SWEEP2WAKE=0" >> $CONFIGFILE; +fi + +#PWR_TOGGLE +PWR_TOGGLE=`grep "item.0.3" /tmp/aroma/mods.prop | cut -d '=' -f2` +echo -e "\n\n##### S2W/DT2W power button toggle Settings #####\n# 0 to disable S2W/DT2W power button toggle" >> $CONFIGFILE +echo -e "# 1 to enable S2W/DT2W power button toggle\n" >> $CONFIGFILE +if [ $PWR_TOGGLE = 1 ]; then + echo "PWR_TOGGLE=1" >> $CONFIGFILE; +else + echo "PWR_TOGGLE=0" >> $CONFIGFILE; +fi + +#S2S_ORIENTATION +S2S_ORIENTATION=`cat /tmp/aroma/orientation.prop | cut -d '=' -f2` +echo -e "\n\n##### S2S orientation Settings #####\n# 0 for both" >> $CONFIGFILE +echo -e "# 1 for portrait only\n# 2 for landscape only\n" >> $CONFIGFILE +if [ $S2S_ORIENTATION = 2 ]; then + echo "S2S_ORIENTATION=1" >> $CONFIGFILE; +elif [ $S2S_ORIENTATION = 3 ]; then + echo "S2S_ORIENTATION=2" >> $CONFIGFILE; +else + echo "S2S_ORIENTATION=0" >> $CONFIGFILE; +fi + +#Shortsweep +SHORTSWEEP=`grep "item.0.4" /tmp/aroma/mods.prop | cut -d '=' -f2` +echo -e "\n\n##### Shortsweep Settings #####\n# 0 to disable Shortsweep" >> $CONFIGFILE +echo -e "# 1 to enable Shortsweep\n" >> $CONFIGFILE +if [ $SHORTSWEEP = 1 ]; then + echo "SHORTSWEEP=1" >> $CONFIGFILE; +else + echo "SHORTSWEEP=0" >> $CONFIGFILE; +fi + +#DT2W +DT2W=`grep "item.0.5" /tmp/aroma/mods.prop | cut -d '=' -f2` +echo -e "\n\n##### DoubleTap2Wake Settings #####\n# 0 to disable DoubleTap2Wake" >> $CONFIGFILE +echo -e "# 1 to enable DoubleTap2Wake\n" >> $CONFIGFILE +if [ $DT2W = 1 ]; then + echo "DT2WAKE=1" >> $CONFIGFILE; +else + echo "DT2WAKE=0" >> $CONFIGFILE; +fi + +#Magnetic on/off +LID=`grep "item.0.6" /tmp/aroma/mods.prop | cut -d '=' -f2` +echo -e "\n\n##### Magnetic on/off Settings #####\n# 0 to disable Magnetic on/off" >> $CONFIGFILE +echo -e "# 1 to enable Magnetic on/off\n" >> $CONFIGFILE +if [ $LID = 1 ]; then + echo "LID=0" >> $CONFIGFILE; +else + echo "LID=1" >> $CONFIGFILE; +fi + +#USB Host mode charging +OTGCM=`grep "item.0.7" /tmp/aroma/mods.prop | cut -d '=' -f2` +echo -e "\n\n##### USB OTG+Charge Settings ######\n# 1 to enable USB host mode charging\n# 0 to disable USB host mode charging\n" >> $CONFIGFILE +if [ $OTGCM = 1 ]; then + echo "OTGCM=1" >> $CONFIGFILE; +else + echo "OTGCM=0" >> $CONFIGFILE; +fi + +#THERMAL +THERM=`cat /tmp/aroma/thermal.prop | cut -d '=' -f2` +echo -e "\n\n##### Thermal Settings #####\n# 0 for default thermal throttling" >> $CONFIGFILE +echo -e "# 1 to run cool\n# 2 to run hot\n" >> $CONFIGFILE +if [ $THERM = 1 ]; then + echo "THERM=1" >> $CONFIGFILE; +elif [ $THERM = 3 ]; then + echo "THERM=2" >> $CONFIGFILE; +else + echo "THERM=0" >> $CONFIGFILE; +fi + +#GPU Governor +GPU_GOV=`cat /tmp/aroma/gpugov.prop | cut -d '=' -f2` +echo -e "\n\n##### GPU Governor #####\n# 1 Ondemand (default)" >> $CONFIGFILE +echo -e "\n# 2 Simple\n# 3 Performance\n" >> $CONFIGFILE +if [ $GPU_GOV = 2 ]; then + echo "GPU_GOV=2" >> $CONFIGFILE; +else + echo "GPU_GOV=1" >> $CONFIGFILE; +fi + +#Battery life extender +BLE=`cat /tmp/aroma/ble.prop | cut -d '=' -f2` +echo -e "\n\n##### Battery life eXtender #####\n# 1 4.3V (stock - 100%)" >> $CONFIGFILE +echo -e "\n# 2 4.2V (balanced - 93%)\n# 3 4.1V (conservative - 83%)\n# 4 4.0V (very conservative - 73%)\n" >> $CONFIGFILE +if [ $BLE = 2 ]; then + echo "BLE=2" >> $CONFIGFILE; +elif [ $BLE = 3 ]; then + echo "BLE=3" >> $CONFIGFILE; +elif [ $BLE = 4 ]; then + echo "BLE=4" >> $CONFIGFILE; +else + echo "BLE=1" >> $CONFIGFILE; +fi + +echo -e "\n\n##############################" >> $CONFIGFILE +#END diff --git a/release/aroma/config/busybox b/release/aroma/config/busybox new file mode 100755 index 0000000000000000000000000000000000000000..e7acacfb6249eb7eefa5e3f41edb2e41ca3d3198 GIT binary patch literal 478912 zcmbTe3w%>W+CM&X&dIf*P1*vXR5ykq=#}@2~ZGNb`2Lb3Tj37eetqO z+JYj2o3^O5c8qK7E8~X|^2VPC(e}gVbU(O)z5ei@3P&U8S7%?+lI%xyYH?gk z2rB|$tR(*%L;^u#4ul2qmm$Ia%h0PUXwN&){KHQU zo&%G?5s7Q(yvW8x#V~^pO99`V1iv)}yg3Q}Kni$668ymw@Qq1uB?Y`T37(b${%{if z-4yWEN$~el!0%3i|1kx8SrYtc3i#qA_y;NAbCckX6z~~IaAyj*GYS4bDd3Zm;7e1$ zOOxO;Q^1Rp;O!~kc}ei=Q^0eQ;5Vj#XC}e<6mVk_Tu1@ulHl4D@C(bov)`-~@Gq0# z*(u;XN${VhfQORc#VOz?lHfO|fd4rO{*x5&qe<}pNC7{b1pn_8@Yj>z1u5Wrli-FF z@E4Qd#uV_~NpMpNcykgwJq5fW37(MxzA*{@Q3`l%68xPM@Q3^1gE|7iD12Bo*>-Ml zf4^vwpR4Zg$9&y@zZ;(d-yKQx-cAAkX%hTM3iyH~_**I9wvswq=0{&1W$$k3&4l<<4*%}MY*Dc}wL@TmLh z&kFnDQTKQ8$Hsm*iFU?Gv@1@DJ4ndfEW|84;uC6iT>Y5{mpH_zU*Bt>gXzfjTKOP2i`mI&WZ^8 z$_Kx7s=GwVh{!gvgo7##9-&PqV0Xzeh0?7&sf%9(=q%Eqy^fVC~FGIyymqpd(FuL~Ab27;Q(b-}`gfuMHb`rs&UAgJ>`7971M z5Y(@EJXo|L5HxJq5FE2L5HxOmB3Qg95KP;%F{tPQ=f;)?g6BZn&eqaDqcIsYT%a)v zG^#*j323YUja8uWAZR=a8tXt~6KHG!jcuUuE6{kUpT_t;8bkjTjq#u{3p8Ayu>>@# zKw}kXtN@KiLE}Nt*aRBuKw}$dYypjzK;u{aG@wf+huCp%h|NFKDc0Sjf2MB*ebaxM zdfw!W?dNK*1x$oJ+q()#M^_;gVb7Rb($P_v+qpS3U?0irg^GRW%^21VvvKBoIWjNE z*#k8+HxRUC*92|Wnjl**)Qok}S6sX}SB^OjZiSDkr-;$0jDoqQZWIqnHSqSY8Q4Gk zUjLfGn&5A04RVe^QGcoAOJLh(UjeftY7YeABWJMp3+}+VOH4n|4R=jz(CAjjRC2by z{(H?G4)#vW9fjaU^_P^%K?32~m&gTTW;`7{2i)DF88Hc-v&_CwbZyN!J)Y(#Yd$yU z#J;FRI~&9NEsd{nn#7Ua#P09rNog<}>t7J@4!i>V3P%FL>A)>OpFD8uMTV#0^GftF z7YDzXg?e;t1J2<$;!J*17S8uZiZO)P;p^4CFPI(;1cztP3wQRC3y`k|(ZYBC;IF7C z%A_L@Oq_Zyi0;6@i1M-XHucVuj&cD%xE$Ng5%zT+}Lk_&q%@I1r$r{s=Al4G* z!G8vG)WiJRMEIw~_z%M+XeaKj?t){1U@6+zGXcMkG*gf89@Z4_j>D7TF4QjxrYGTt zjrQS3yGjfA5o7f5<*mWtfVH~2f(00h_^L+(f6d;R--eIxNpuLILh$u3`G#BrcvZfa zz$db?BwMv1ri%jTJyG>Gt7AQ2-jZxBA(}!7q6x8iK`dm$98t(lnZ611o!oaIJ}1>| z9w9e;051lDYjA$VBKt>jtRB3L_OSB^mm_~9hD zCk6cVB>0;t;CqwcniTLC`{4unVCUye{r!@45a{nWu>O+!cckdQCK! zex3qen*^Vb0{(CkydedAbrSrO6!5!~;HOi-mnFepO95Y;1Ye&5J~s(Ia1Qj7@6JCn z0EgpO&%3vz81MWy<0k>G>mUDeit(lYW_&T=BQZXCKBuqk%M&Nhzu1pwVE);BZc9OL zND{r(Dd6cz@KpNH0-mrKkf4$$@+h4pkI=mboBR2*8kQ0{gUnJ_x=5-I41<& zDfY!l@Q1-1LYlGXGCys!+Tf4*NXfsIVn75X>rtY}kWXUrHPzFV@<2;e8k0 zpToP2x`Q_A5c6$l$NMh4KZkb$Uz=arYO!SoEdNN-Ba30+pR<_$ETA<~To$r(eLB|5 zS9iMzi7@}Ik8VH1Vx~VQ5)m!pqz1yvym^YcHxe=@OmV)#-ee@^rA{W(NcL_=ENAyP zDPqMD{c?#+F3`!!xDPghd;nyzz&QaFd-f%lZTMWCz#NOoH>Ct~#9*Ao7Q+72!v-Do*3qctZIp+gmtV~Y1fO60piJDi@5TOlLgQE`b1ZJM+hjuWWNOa8QlCKP zhwZ+D8#rnS(;=|wcLHJCkWH`&=$%xDh&dSIXjYh?5D4Z^=x-NShY+@g7!S9iAH{iJ zlz)agc|G$_h%+>PnV5HlveNzXyuocOp6n6b73lL6_UgIeEc8Jt`Oq!se+lBpK*fzPjCvxJm{v98fSz_Ya>+UvM9`_zyq&I@7A zUNj-UfY|3mc1LZ<1Ut4M{$uljww`R9IWSj$W^2fvThnFc0$seLN)~cz0-(DKboU4j zIXKc$6+(>tqRFv^>E&oPcoxMKA-fO=S~y>@BzwKeqsg(NuN}5y5qv=nY?$$0f_?+< zxSQyIm>**~wk*`G zzdDK>2jVv$^hwRozojOh^`jMAK%=G<@8xVx)@H8{XAG&qItVZuImhS$uLXFStx@amjzu;hJYUY25z0S;oN6b}_?FG!11-2)UKqK1f;gEVV;6Ko}k=O$~6cQ)pRs5blmPLqfY z-Gb;#O%rs?pvUM6;<#?ukvdn5b{Mp;(1rXIK9(z~%i>Co@I3Kd*$s& z-ADsdLPj6>uMUKD?hW$ux2>1o#vH9*x(Z=HS4xfm6507?Qy*`B8(?+)Ez$UO(0zu`M2hX{PznjeqD|+zD z^7QJQnIWU^pdND+E&~kj=c3?wmao3MfUN<{t6<;U%~uoT7`L9$6B43K9#0^c?c0nz z{N`?~#~dEH1T*Vr4}`7u54r`|*f2cdk9+cqu;xWB#3R4Q`fxQHWUjy8F!6(Kw|`4F zM{W(5`?hGPe^_XteH};qfh@g!v*snp{a?Vr@G)7CZwd>oTQz%Ik6SA3Te|h`4P0yB zxJ7Vp$jrbzQQ!Mv-nT)%AG#uBA?z?v2fx3O+K;O3dc;U*%ZI#Wv^6b61IEykfsN4f z;_zV5;@F;r_g_J#o0$&57y9$ieuG--D zXyjIJ*5slun;&cpM&y%vn0^L92cmCFcS*ne$UEm0K~Fqv1!wadMsqG;Ojktg^E*>f zXJZA_nXOB}rH7oz{q_*w)1Yx{n5%g&oZrvC6ZA~|w4viHp>;i{3j`?kOC#=jdIn@r z;LB9rnJ;U7lC7gFGEnn?Jy z>(<&KBU#ryIa%hwmhSWDhi!nZvnw(q4})CT`p|fch0h6(!&9)=g^Dn5cD0SkH;?7# zU#Db4h|u-2@dx_32)vA!K0go$_M)x>E|xc;e&`W%Nqrd0Y}37dufArzOafbhcX8N_ zwaLbs&6`6fIQVtQ3_XFxMVRXVp9Y<=xnOl*8vu(f1i`y`$jcrrN$;h9~svwPyeI(NX<+*8#1H)aC@_!+QQ^vC`~a*%84 zIfH%a3}`VLoPD``qy&9okFaNq+1~v}@I>71klDRX177%I@c$;-Dls3-rV+P89|7KM zU#HO^F3SU4)eHO>_hxcdt>6k%-$#s*uR}l4^ zt*YPZ$hhYTDL~0ZVS5?#jTHG&=C^?hXU(i|CGoKs!}u4<=8*Jsu_x9QyB9)xPA6Fx z`l!E6-`_SoeO>6o{x&n(;9ITvXk&MP|DdFY?Y)!j*ni~Oki%ZvjXfbqJ&>8adG6Pr z{wO41@5vx9on!UyKX;rn{Di?aof`xm)x839RkrxmGl^Vuq%w+2mI(C{Pm}> zLBu0$zYye_5Yt!YY2?z~eKMG^e>DF0KbL{Xfp9wT>#H}18ty}Ug?+%jRC~L%>Du!vwWr72Q&Y+p%gIy=9|f8xElK^#(k-}@v7^W#bylm zDd5$Uh2g&-uGHbl=DsmwbEp#YY;YroPk|M?_hQo2s+GLy0MNSt6Qb(uy27}>#?SQ7vmU@eR4eAjeRT}Q+aS>j)`$b z40ji>!BOBN3cQo;^{}fN*i}t8!_Vk2JF5S8c6CpmT``+-l#c4|<7<0&gsmaaWWH;_ zZjyOnwu`fwk=e)9kU`7#4AvKQHU~%0W`G>^%x19uOt@EJcMIS>2f2iv$znb9Q`60K zb2sx{Sci;v6P~J`*jk4i6mkHsk)odmIB~}8;eeOXU^YK6&pPnR`Y}DRHH>-c5#WRV z%3^l##AMik@t30HLbReUM!OTbVYaKrtg)TX{t08YyhzA#luamaAsBK0j(ztT2pHoZ5l@OWXE|b)`9tfF<8R2O@Iium(_l0DBCnmp8O@<`__Ei*+kW8C znCFEsCX4ws4VjnK#_(-mHaRcM?n?8Jk2fR!5OMa?h#O?+EVzfoGk`nFvR!;C)w6k&0-$nx7*_|_N9&ru! zFzAQc4~Hx5zBA0X;@$;5eO-4mbO)XG@Zw?YQR})9+rTCkFu!qPz!##w5qA+Pj!ulP zSNo{8pxVZI)Dhd@95A1)osG<1)~S6Kvsl3B#9HdBFMz+i{ct(f1Y(RZ_721c&hx0X_<$Rm^@R;YQcnD~*7zl9#VnD>H&;_$C#`|pWF8x5B zTU2=#gdL#EYyg(q`CNq1}dB8XJPw1_OGdG^)&FjxnkAyhAF2v+U{xnB-f33WM zYz~!IBi_MSh6g#t9%d7;-$ul|IqII*PuC2(_EO)OS?Ig$zCOCs@y_TmTB?2XgJpp< zWb^c~p{jj@e?|*--MtL*mZLvgZ){x>JP|*K?_}$K{lRnNaX(v5>d%#vt3OL*_|Fk} z`#D>h|8sUOv8DOcr`TT?uhcvH+dI@JN28x}78Dyw3Ca|dIVej}?nkLXsYls`(uQ&f zr3)p95{vfZkbwimhEjqu1!WG(Qk45qYEbG?cA>PP975?r38KVg6$hPj zUScxPngH5RcA>Nd)HWhR){*cr(4Pr%v)Jot_)`b+3YFL^*tk@E4*nndy!7w-*f)oM z^6&bHn?onR{XRc>v6IbrkojmMY{Xzj9cTGg_#*I21?*=O-|ZO8M{sU$IHM(X=Xk6| zHs4fq!u}e&_2Q9kQoz<$UAKrF9Fvp9Ry+SeF0kizJpb9*{)>y>Kijid2K!478;AUV zWER$nPW-SNXKwg`x)3|JGT3>*Dsk3j^~ALP{gthgYUn<&Ih5GZ7i+UzZY%Z%;y~_) ztpTiS*lE@WcsDsVhuD6f4tWsg2iYD*9GkoU2%gwGgJtx?Si6jN7IVA_*?nen2tF0x zvtdk)8ehS$he%*^_kJc9Vh{o61qZt)^?A*DUmY>|HY4{D2zgbG8}mM7cqNG^CvY&|mI2)}pB9Cl@Qp~%CDdPq47`JII){)+MdWYAb(x$Q zIf2o&JjP^kqieISLf;PbgOAO52Y8uo7_Z}im;V7?Zd4t!xt@2?5BU_eUtYgX#xb4P zGegB_XFMaW2^XNR0zMdiro#*ecof&+n}a~uSX8Up7n^?=anE~6GT{suVe&+gvoYiQ z6($$P_xurku#u^Bh5kMRGBe&Z{q#CPkMXDLrw2LvXo0TA9tgL>XE0kUM%>3@J2QM) z^znn|*qUbRlSdo#6DIOOHwQl;h?`j~3w!wxK4Wu84}Os2=^lg}P!{+Y$fs3fe4+zu z@7SiWZAPw~zc|-yBI7M4a-HQqLekiM2=B4Un{o~XH%&ScqzlyiwFS9vEdv-aOR zAl~V_cW|!=nXf~h8g~j74SayDFE{>NhF>np-YwV3JA%(;bWp~FdLP01BOhl6?-txi z0Dp+}Wp_HseMQ!<`>CKEeJ$731xtXR^(_%PfY0|myzCBx*#fte!Z)#dhbwn79AYh_ z7I!v;To;Cqw{T1OP%U!)y!|=c+u(fcuITH7?|0Z9fVm9jFE+_+K4Fi>8jn9%=V`DY zpPR$<#(02U!b~0p<8TiGTc@lKbdNjX@raM%WAE^@m@o%;SUxm|zoUWmwV!|MIG z)@IjSxd&l5S^cJ=H7fppWot`RTXV_0Y?E<65@h#lGeMunT^gMmz&+~vU>?3lWVUUa zyFMu5TST&g=`cOS@@*VhK)-eTD#XuP$8rb7&*2_)nFzRNftrUOs8cOs*mqH6w96mM zoJSJV-2s~k_niZMeh7Q%U%z%SmA*gGd2>U`@E7P z57~x16@1CD<)5yHNx-X>*9Xh-?6ZyWu#@X(BW#P!H{*lip6Zw2i_Q1rcw(-x&H}-W z7{l5GHs_e9doX4I#_o>>?CVDuQ{(Ul*Wg*_ZU`>N^AQGzts=%L=0-KJ?|_TpyBFVd zlN>%=JP)x2nNfqahd3h~m{b>Jcf`zwnSHV+)%sOiBt%y01MMs)lC9>?=Y%;&{~b*r z@ErWiiv#ymBp_q`&tviai^PFDS$8;O49G#!F&{BJ_B}W3%!dM-*~#Q5RlyS6pJ(IF zlZ_L_<(c-pfF*lsz+$PZwG`l7VV)PTu=s?Xjk48T1^n*Tfcm{HZS9L)!o7(|VL8rI z`|E;DM9=&p`u~{u{bHfDMW!By>JM2P&J(4`-P+T9UiG}ia9_rFhM#>i#=aLD!21E( z)Ap|iPJ9!9v6zoOe8i#JKWn4JQL5eG3%-jzhL9?DcELIY4(RhB#uEql?w3#RTR{-N z@HiV8A!88ohRR{9OwQ}_zPmHC*3||F&kF>PV?5h)e<<&7&|ZW%DQ$nP${UlH@$y4? zRsII#ZCx(2d^D5yFp~@KdYs4EnVjvltexdW{eZE%3BG&-aC0*I9#+L`Z^WHVpB`Bo zlN;wUJMUX2YuEUK1>U|nVmYf9frIHYnQzwq5ZViq`S$&QZ(kpNm2Y2V-#qp6&Bkx( z=ljY$*`YJEGrpHy;hW7@AK&VH_4AFzT|B_I9`kh@=8NL{${%Cz%U#Rt59eXbor%oB zJiF^*r}+yoW*+*9_B%u4mj{9+b-25@^Rb}441Q)Sa)YDmRJ$~Q2NPm}RsC{n_XmPw zQJ7vCjPW3tt=z=e=g)Zj>vq!VoloV?jzrISWp`J{`hBlJ}u{evz--F*n;mbFn|MqT1m*KlYqkk@08^h1$leaIGnQn^o z$kSM{Uf+8!NGlHqw+Wn#uTSNAlS%edDw{gC$kbYsXDVut$60q_ZOmc*Y$NP2i+Te5 zVBK7HK53-Y+S-1-8ktOJ3u7L7*i#1`u=@nP2-}06&~7CC-*K?@!~7kKpV*y1FS~Pu zf1nPG@c`yV|7x5gR39=|^&y!*@F7?~7Rv**mckA2A=S{H04I+?9o9qu2QzBK+OnL7GxleOWy4SZ7agxyemr_6A%@qfp7 z_OA89Hc*%kVeN0AJ#GJE!1++{dj$77b-WZ zeu+=U*KcpEjoF%t&#_$A!QKkjfDhneKB$F_$NQD}Y3*yj8|`dzB-DEL434vwwW= zTMzrppNl!2&3uOF4PCby-?iayL`oVEyOttH23;{8SdKm$diV76q}%_UzhE%tFRlTM zt>c2CJ|8g{Pt|w$nO*d)V;%Dq{=Ru)ZPY)#RL6XUd#TLMS_~I~uaJO?)rCszH7Lwy z4A99248G_bU%pPo|2^FObH>^jUN&z$e1rkETA&~B5pMxM)o}v+WLG1o_a^0T`+qy_4@+zK0zYlh-k^TBa19u>}}k) zPZpW*Ms0bLKH8=LUSvF>tz6^EiB7nnku~aD$%Wa`#CTCMA0+KPA8SYy1z%cDxyB|) zQ=`&Ft#rI?T5iUV%B7#X?#lhP*L+TYz+RmxmrG-$Z+rFUJO@O{7TvG(^}pugQkx}a z;cKdoR1=vLh!Sp%YC3__ypM6Biv|_*LB^|IvPd}?`4fc{(Gyfe?2THULPYaH(4YOO zQdRStR{Yir4WBCRU4<{=w~epYNo17b(lmVIy5PF#n(X~mTmG7>$2y|xeaqJnJZpTp zl2I0=tD>2S^}xwVyp-sDCqasS(RExQ_N=HS!_@hS_Q8*-xCl^^pXhxJ&{dsu6e*k| zlX2coQR166Ow&l>0k>q6a-uuG@yHlUYIWSlMbf3-37=7MjC3f^*pldNO6c3@sOw}R z-VlA_+w!(gAVH&!|7eV=UH>;EPiQJ^pbeU>8>aEngdR~_)J{iHk!uvA|C!*LY0H^5 zQk;3Ruz6Bjkz{+p){x(j*I3YasdrM(^G<8KC~3Niq)E}^pI?(dwyH=HqrXo)@8mj* zq&d;2m2$7xcB>+cBxBZ|f9PeqG`bb~{-r2sU%1r!@MolG?fHjae)KFUD3t!|ER!#M zmQ2%;OOlSbFeiMAh8+4xL#p=;k}T7Uq=#IVSvk>;i;ucKRU94W=~aqJe8^?+n!PjE zXd*tce5}6fQ)Qfd+4Wawawmrdztfk`%hd-z`%ptF`{`VA>4+6{aAqU>R62duc=j8ORNkhU zPVEo5F7@vHLVuvB-zuvQ{v6}Y`x3pMB~*Kx*6frzx8?BTY^O(zyhM+)h< zMw+9H^OMoM>{4_-VS;($4yW#v5Yg$6D`wvur6|x<5j!s2L~nE`qdJ7i*Nl9|89K3K z1jDf|B@Q}47{FmXp$J!S&?`9Z9l>y5CLbs5Y%K`V@8a`*J_zgk-WTX-qsQPkzNo9u z^5`4(OZr%%M7KlVyg;#43-xmqo9C(O~WI(TO{7E zZTvkjmPkjWy^(P>`D?;3M>Uz~n!irOn4BZGENG=;ThE#*Ew}zZ>C9ha(1qwkcS#r#&d~ zjem@gwAoQ&5+Y9;X@g1Dv@C{Y&r?jY0h~|8`wYA@c@BW`KTc`u`4(-ArX7m#h9eQJ zi8l9P`am(Y{xOnf?8D_t6CxXp+9ujKNdB>6vTGWF)jpHGwJ^NEX&=D(#VOjNizRM) zKd0KoH~DgYY&|sm%ba?rK1Mm?>C=kXA?(yO%~D2_DN2!jmQv)=%eoyxlcd<}l2TNy z-#JYwB7TYKbnSV~%Y$GKY^C?vhY$8a?%60k-kL3qz}hGI!u2_l<4eJD)Gd_NIWKl; ze=FRelXDc#O-tt~h1F|vrz(YHuQPs9yNBctiq|dWMt;2T1N43+?z``sE{iuyBJs7= zi@i@+r^3I~Ilt**c#R_sz{30IDr3mB5l&@HbtSBamc8Qq>g3N1B(F@`lWUPM*JfH; z>%4H%DACc{7li9KFBD3>7EN@d2A0(^^nxb77j$OzXf!TGbpNAE8*^xA-XaSh9Z9NS z$(a{ObQ;c$x8=GN8{x_xvgnc^zjclVj6u4)W=ARiq0}TbOC&E#%94L#S*Ya0ehaG^ zF2eKX64cZ5_i_r$dlpcB_Hju{>icw!c3 zR#!isi4Osf%}&OC!>~+zg!Q9UuyMl$`X%R#chZ}uRa|@GHRtb7b4@dI7fD-(-yj_x z<_4#w(g%vrVT`QTBznL4mgIx)68`DaXv>!Qt%t316=BJbAzQuE(0RW_8y%SrO2C^Q zFPh4<1n; z9+OPVRxK1t$hZrgbh1OqcPv!r*QikYUMGKo*hr*K^Y^p5)Lzm27qS>b1 z@v_qqJ?yKbnrrYck>WZ(Z_6#qC{Xin*gqu~ffN zaa-3kjLKAW9quLTDi#7VltIY4in(2M;&+glNsx-~L2gQdlz$IWk^~Vt*H!fKSuU?p zDfaO)5`6}E8K!bNz-49<#PmIgCJDlK_F)|)(-LZ*=nXiF+R5-;_%#ftH|uYl=&Add zh*89VY`@eS0O2_(bVvph>sVVg3@9uDHzo7sx)lJ-inE* zgzbZx9~m}em~~N36Yn=#J0R%t>qcyY-U_diuCDSUxW8S!8O? zY0|got)x*O;nECE!<%(2v_aeafuiq7^d7l<8c$LrckxZ|mu6x7@U6U;jMbeq#;EbF zvv)|sO`7IsoWJSHP~)VVD%Dt5-CuXyL&cg_ef^+@<1ak;VtV6g#riYzZ%-?^x5GQn z&+rWKT;0_~yU}IU=9B+3-De@xr>y@0UpC6~<}gpi*Gp>Kb&^MVLwdD>|D@G9u6>>Ks^rc+trYon{vn8{Go+0A zM(oYHCPPdx%*fR>=$g4$qI`cv_9=Z6i%e;RGs1tHk45N}U3QfDkBH)2$|#Xe2%eR( zKR?bLl{8NyFLJXmX@A94rz~Fmc1?sDhQae6!_LZfNw%|#{=@3dE}CgM+n+VtPbkFK zB^?DmdNW|Y17|au7E7A#txnAeT4vZGK~LK4+vNALtG*M_8+46*J8MS6A0zrJd$dV5 zHnY8SF7{itlREK^-L!RJH~q({jtEVoF>2Dayc;2gjOI_U(|;lvvD2H3LS#cfrj5qF zomqEfXV#_InT;)e7Y|(EM_Znwg}xlt!{CO*sNs(hs{2F5zV-}hnlwf7ORu)SC(V%F zi|Eo0Lxb;t_R)%$+nc0XDG2?yw{Mf?AUYZ%?Qfqeu^t~*yw-jcdsCB?2I%$DNGVHl z0=iX7YrzieGqK-lLrdCDJOkR6pX5$c@D{#}pR5`#*IH|p73S}H zp?!H@{~x~9uAH)RUaoL`-E!{kE?}IQTerNr&!0>YBswbJd%{bKCv@&wDX*+?mY(>r zH*e)tYnHEk+Bu|?jvd-1-qW@B?AO5CJL9|v7E|_a+fa8_b&F%$z9~h_a65;N1X7ybr!o(4QbDi z`BgP{`<0m;6l;oGRkvzRF8&x{MeT}1tJ-3E{>X~Mt4Q(Zr>duscKg0T=)L~#g7nX; zH0Zf1_bN_Uv3|u{t6o)m9$B?+m2T|cPaTPgntO53?z=k>k+cR~|QaDDH8#CfTD-yy&TMs*}XUk9|$ACtVdTbIvV zamypF?Tf~Fr*0u}--Gn-P9?XM)I0B}xSQe}+n{)>uWgg=g~panyZ0Bl6087o-{riQ zi%~tv%a%C#kg~!_ONA0=#W$x(9{&QBH&)S7*S)(Dsj+&tG&^^QM4vq@%|%2zs(L8a zLS?(`I*lDMSJ79$JM3A-Ta&S7S_SQ*<8PL;U!jwM-K2>)b!}31lyZhn#ADnf-!iFF zS+$H#=)kX5?yGy%x_22j(S$K{9Cw3kcVydW2x(C_##`brre ztLa4Wv05wl)xByRzZ1BU0WQv*1$Li4)~sg~ip;dcfnV;9PnFz`satVUFsFI9I%#J` zv@21e?j6>zwZw!oZuP#AGY3hJxU|xU86&1Y?0U$R<0+D^nl&t%d+AY^Icm)iI_)@% zC3=0zD7oXSX=a+|IPb$b)S;h~dqj71?}d-)q)(N~4ix#4t4c{XZ-S@Rdp}hscVtYz zlEoGIE9>aTj%8Ydo#k^f^Tv%cJ5_&oX)G1~M{wA>mmnE}I<{%p;@c z6Vw)1NNfdmp`{W zf5q|@Ig)IpWj@6#;zY4l>DqPA%-rX0?^}<7$0*}z_7Lgg*3V{nnjdv#G#IvkV&+e` zX{0A4Q6e_B0~Z87RW{WvhUMMho!5A=_o=_%wl%$Z>WGpxTx2RSaEMQ3oW;@t3fKDD z5<2N-Zd#Ac#?B9PBI4a@uACHqapJb7^k#NqtG05HDRh}MMB#j>rxQGFN+#l&yyEj+ zqSq$TyxCq_+A(ZzjELDE*0wMoCVQJlZsMv{ja)k!0$WPaB2 z%sR=uQx~b#>*Gsq*&zK@X}w?5@QYmR!TCbuF;U-WRCo4tnZ%dOITq1sEwNSHu?Qg* zIE!c_CTeM}cjkPejW3y-8C%8UypD5w-8IP1WSi=9IB;w>HP6X0HmB8Fyt;aQGk#G| zYu@Pm`1lk_vjceN(UPp#DzZAaLJ_MIV}5@+4QJow(jQ`)j9+!Vk9?aZ?wOVKvMGLi zb(f@n#?)YZ_PBIf86UuIUk&MuvwI#ND@4+?uUCxhEcMoN){pYelgw(bc%E2hj%ak6 zPjg~M6Jnu8&W|Xl`L>oy?52s{DHk)Evk;$ke0kVc>UEwcS!Es;sR!g&HesXU;KdlsykfSr;|S47bX=@9{y2_^HDVzJQ~KAE;{ zO|CA!Vu_C*$UHX>9*fE`X z3n7;W+BA1M62l-YQ7%-o@Sh*j?M5Lr!aAdHiu* zWxFPp&l_wXTIoeiRQm$f&>&Ib>aUl`GxX_1ujaC5D=E^P5bs)gSE)2sy4)K`z=xFW zUK#cX@~t=n>kouI$P1MhDJd4_bAu$h+dI#NEr3lCVg5CJHF)r=h zKAskQpk%kwd@ZotMl?HK`;N08r^P(rqPP{DEl!Ki`Y|{)ro~pIF|ORo*jC1EAE(8E z5C1o37_Umv%KCp;@qNzTQ#qq0;7zBGSIu)MqdT%+6)j$wXQ|>d%yYh3xK5Z%i*N4Dc{!~GQA(Z}r*2KW z3cB=am~D`&zdoVeVHxvYJ1y8}rKK8$<~BRIQ-iVZ^_<<-CN$Cb(bd#ul#$VSl$K1+ z6e1t}$Is07+dBe5RQR#i@ff3hB4vE8leCZ2gtU28X-zr3&N+&k1g_nN{E1{)J zT{XxIrN@NyX5<*x47avZaW2aQLG9@=n%;`M z9=(~zIgc91wS!Ix@yzK$++JyjZ~RYve9vmlv&3d-;Ohsyyh}#xYCIIt>z_GGBXwyc zFD-7LLCcORZrdy1x*9&CW~npxMP!yq{xj0~v-$TvCoLMGZPeG3d~MT{&f8D$u@X+d zb)$1nJ8qI}EUFl-STNf!IF*ySrfm{MoZ^!TOA66~dZ(9$D9@^SV? z=NIaJ|IFF9B57%exqPRUY(Lx8r{kn5sy7JJzGb_zAzt&4K3?N}u_AVo-|Ece8-!xM zQ`lld=JnpQB;WkvhgG!fx6X?=OPKd$%fGR1R~+VN!3*-y@ablS_Z_O5B0YtuezW3` zb@8p!XzAn1Vf*5Wb0>wk^%jzs9``@+3^MlHq_MIde_KFHU&wju}7R3Ws_LR^4MmAw^nH=WS3KRD?rBKDqTR>8$a9J5n%dE7njNJkbD1epsc&@t zy^CqYY@6MquT1pzC_>!#&}cO$Z$cK-D6O&55{;~fS5!6r&Z+~rVxqW4Xu2{FFE;`~WbqBfF8CnkDd zRc@=$pTMmXyL-?Z<6Cb@j~zDjoDHz(()fa;k7v#lr4}W7j;0@fi-PYfRjl;7MDG?w z1AXc!jc3j>#Wz0Eg7d_7=NBh6xGCjqd>*|q(Oavam8^Hhad$L8ca8FzGo)tEF!O7U zRvbM^3Sn6fqpZxoce^w1geF#^6SnSj`jzTC_O#zNf^X8aq+QewGhWn|Bl{Go&>G|k z3ir7vS#h#iq+BB+|E19DxCsZHU!E44X5!l9dyY&E z+*8-{<^B1$FTI@>(bL3cTfuaC@Zz$&0xPqu&n` z4a)A7q&W99XiiV`j)$fzzFbt2=tZ0-+3rd7j>VHnnCR8x&1wsI6TLj%61|n`@2%hd zybbe#u|rU=_|i}N#w^9yL1?+$`#ogGjf|fqPG)gt;~p#n;J>uJMez`tY=l;D!;Sh!FGGO;@`tIFZY%tmU_7{ zmQK-o#QVU3yp?@9mCL;!Uta1Rz5Mp&!kFxKVq> z-lNFr_`43CQ+|m%eeZHFH&)v<>_DP-O@fN}zwc~IJ&E4ci9Bzocj1Bjm5H(3@ue%t z7|p3ZDdBQ~xed)+Q7Qor5b&q%|&U^!PX8UHJb87b2%5UJw6ejlOcxQIXL}intSl5JhUR zTbxlKlgEhK@aVbAm?yhV7OoLG$<=Rnh9J*jd^3S_D(+qn?9-4JP=13F-G_N}Jkffe zG%|XZl08$vncpi7Ta)N@!w--JM6^lZdTwrX$wdvmw9uX~sT5vQDVXG9$%}6Z*nRBA z#K$qJDQ_o*^Lsjf7V0#paqcstbYu?buygT_>A%I74{K`4XazU%5AJ@*wY_rtj5WAp z-#+sZ*NxHzm#Kb`KfNKN@sNZwm}BeA?5KdfbdiEDq-@sc+ZTD6y<4O2;QI|hDmrkV zoUPDb?vGuYaiKGR%{5~+UC6Su{sHwbJ2{z*CDBX14KvLzJmMPe&5HUmczgqKp?C3T z9Q?zD-a9_ynBMa;u_}f~AG@60M9){xdLu60Vug>S>2JizY|Mw4j=kO5#%Dtfw#DE*cXk6jZh3U!=X(2y=0V8I8aa<7`??d|c6rpvSY<}VC zHcd=#(gWvG@O&z=(mTwXd(~YY!-1>4MtOiM_(Aj-!=(Cq#x@b>SdXtfTJ-s8#nC#n zWpGnLGijvtxh?O1m1g4__{P~i!%Kzw>t|9s*Tb9i{`bC0%b(q2E!8%rMH6YJt+RU4 zs2)+IrrtiC>%r|=-qaow#W|urySb=oNQ+_14bfYbcZaTUFTeT{!V-?GFJ7v zcHpc|ocJ4QCy5M_4I3PVzw#om#|w51nT`5+Jk7`{{kl*G`}}I!tusGWJoS&bzHw#6 z(gfTdIMOBa=qlJd@oS^MzPM7-c?46Xf| z3qQoZtvl~{fcYnF7uMv~5z&V)6WfUB$jh&5vOgxx4e*R_#O}>7cU{yNK6ZRL1$}0p zKe>8Dbm3)+ercBzy?0(-A@A4Gt|8HaiwAVV$K^9eN2%@+S9s|Ko$lia(=Q4Sxope0 zkH=%>q8d%n@?KE8IQeAgo`*jv}t=o4Q0x>g%`!cd8R#kW-A zMwH`)n8}E`2cBL3i1rsQr;3AOyiWeL$1N>V^kzN2WXOrmNZ=iJyI*xJ9$%QOr2mka-u}V|rkA4%c`H!EYr9jNI;x4!K{fc|K zxCqr-6}qXj;?6G2U7!&&d=z)54GP6O#rvWzt_*L12HYeat)QK>tXytXIMfBT&Xw6w z=TX}tC*%5PUj2aZ+@`VclUY{xKNeD|%|`0fSI zD&wo4QO0{-bCOT8C7dOy(O6rsPD?vs4QA}%8~=|kmF*KX(g zr%`wJ?P&`|m9N>vR_Eos$l^5KHM0|UYwNKFhI{#^U3WRWoS(+??w}=nMADhZ!0NSc z*2cR&RD2KO-kbb%HW%@k*1BFo9_>@5`ViW)e|*c#++Vne?UIW=BgyPLAiI*~p53$F z$VH6${piU>9wX9*>fC^no~9+Dv`66xzhj^Cnp4Or_(?p^tB>jR2E^I>VGHamv@m$N)<#@c(EpnGRh3swUxVC# zp{(&TDw>F-`Q66hGQFXTt(l#Zl`PMj&a6|=g6=hi^93qQou!y>Q~dmr_acJ+lw$XQ z-#d=s`KXWHNUjcc(aB`oU%GVtcC~k;j;uqu7iBfdJ0tK!sYYQj1IgETUEWT70i}~_ zXE?sR(Z<$(P32+b(eZ~dLr=6K(wUHhC}{^Q{IkV1ZPeSPJi3BTID}uDGDLjJ3R|0F ziP^P}DS|vi;$=;QhwL1_!-gN6z~EJnKqYZe6~v?L%dJs}M064q&w(#TU{Gmuuz4Gk%O4lS~#d zr$6NSGdQJVKREs7QoLo;NY{fa%z|u_iV!m`zRa|toN~`XU*n^$0MXSjWv$N8X@hDxp{sP{7|LXn@hEzft3T_Vjf^Aj+yI*xPl`|Z zo|LlNg;D&d>~>w@#==jP4nN7quMefeKHEN>^=p>CaVf4#uC*>&KLh9aLmPgJe8Wbk zqw^J~@dQOiv*q?*xUe!K>xJhx{B+o_efjdnw%tx$Cm<_s#Eh-ucWihtcbgCX!6C%A z&D*}|-rODQ%(8K;j(q{Bwq3RP-rN!EwKBd|=<9>}j`g+!*%Ci$V_}+PkT*K{E)#0n zLQc+>gi*Ree3!;<4eUngM8)3I2hUx`cX9sVI`S0CCX|gR_o7tq8#;^Gjt~#b7vlb< z`m0{Ji=9>OS}DXAc&v7IR?)=DNuqbbe3`RZNwu^b)wxKQ1Hr_4bt0e>2g&z+~(mt=d#%%|hCJ>>^z z-2W&a*@O>_D|5H{u9Fv8X*rF*I=4Y7L6%p4|BPHdQp?qEpe2c-df!{^d_>OV;&096 zPUTp+_#6HG7Od8mmf@a&mgM7iB4P-GmtwWyTh-jfcjHzI-&!^*<2o9ZtIdm-O~GHy z)hXl1HMlp-^m6Ejb~1%<@wmGVJ*d|b)sghBrn{?xqiGo%iC&_3 zMWRfvSwjcu|G>u=+&+9(CwbI0PnrDaJf(7#^}4L_IBEE3i9V(=jTm#CB0Qsk zcz8NQ3+A@S+zjE*2Zm4Aw?#TLOvk5uov5yL>N^3SxA^Y8adI2ZoFc`!kg`))%`)ip z>tQkFEf|MN`%JcFHC=;HAm9mJ7zw9%=5P;xMwrb z(Z{fIi8%Cv_G_J-;idL=H7EM&t&b}uYOaWu<&OPZSIewz)0u5Nj!-@{o(|HVn(- z!16y7c<$ulzSTp4=`6$KxjYgQkNzQtZzOTJ8~sO&mAlqVC;5GIy}K$qR=^=|i42uq zpk*&9{~vpA8W+`-uZ^xf)C2_-gIYj=H8>OkTA(;Z6DVK{YScuNpfQ~S95y(SsY6B! zG-;zI0a3%C31|irGk}Td(9uYePLAD4x~nufjTw$x?QRU1WS3IbW~#c+Doo#V&VA4Q zy&vv}`{Dhts&?&Kd+oK?Uc-NQ{?FRH#IU2#RF^)+ea*Y&Mvpjj`=spAJi7mshf3UI z+*iHp{*}vmBbVmCq$$m7aJZee{X?w((d^U@3fA+0MV~e}1dqJ89uz|ML%oM+w#j z{HtfCw<*AMCSjY~@5R`=9qXUIP1$~Wd3k(!L)r2& z#_zu^(p9TuIBJ#5uCSJm{+osVd)cTV?MN4FDzX>fB}mWXcnQ8Ekp4bSLq0-kMA9OC zK2}4HAU%hKwLUNX2I62!aeC1s1=R%x-xAg?0C%u>oO}VOdY}$8qo{+CK&&!fvSH*V ziVViM(Uo_duR5=|CEyIq31X@|UBSGpBEBMq7tSjiyM_yZFfhQ9u`E@dsI-=j9+?#& z0$~40m6H_-=iJc7$0{zIBRGmx<_N82vxTwp*MpJ8<~5OFy^lspB!%c0K0QW5R==Vm z(<~}-^{krw1-~gq;Z1yxhpIUefk@fo5wKKHD@wBb%3ywKypM}X?Ka$K^V<}D-ffC@ zbpl;$v$yp|>+78N4(`4V@2%_U-gw(pFMN&jRN?-7n_`-mWXw}c85BR0gnRs)KGH>1rWrn`X@6P!t={U49U|Hr1($eb#WerZ}xfRL;J)X)*{3LH6@Il`SWi~v{ z^D^4}B>#|~90n@EFgm+UeYVs+N{vWv8?5 zcm1um_`JzQhyAV7Y0srsEJMz(|65Kga=MXI zESzE}FEth|#GPZz1xkXR$NQXNiZB)^Gw{?NJns^u3E}4^7L_phMtSB8%sdX%)j1IO z=aor9+KxQvxA>iv?j{rQOsfT@=pNbzp}@=#O4Bp54Y<#NQ@G3O+^ecFn(!TGtfqIh zNTI;;&;u1moox4gu@E(0W&ebbS*KYjw z@So7%sPEVD8nO<_a9nevp2m#19gKN}VmGD8GLX&%igBLdWCrq79nZTy@_=!%N}#j# z3dNW~bHRJ&V>oU1juom1{LUybeX|1B=#!)!E8fMLLa%4Mp}=24xWbefK~V(u49%iD zR?tKVz2b``8d!WE3w;38C-1ev zgR#?E2sx~vkn`9C-lDOxQa;YAtz;sV!ya)+kNohfUOapBxfeuXl&dVQ zes>i!yI!Dvhb199&Wu?K`+Vqi*!FnKd1bLX6mW*fq^$+Fh)O{Od^~D1=G{^ao`SP< z?_g$z0@R3D(|+JY?c6#kt{m^bLX8H%)liR}{(Cb9JhQM>WhTzAu8KPsRDaS)Nk; zonmyvD;hU5t52i;THUupKNE2oC!ix0OVAl~I{$mC4=7o6I=}mYm8O}Bg{b>#qCdj_ zp}@C67XA<&sZ+8Hc^x|cmsGA~mu={Rt^t2g@H@psm?pm2p~TiLGIjbwF-*fg++Rod zzH6d8j+I)$&bVT2&cCWDsO7=yI{ z=~rAwihN**o`2`XQMsA+k9SaqPeZeXV16i|3AP_2lcSb|0&MWf0)sSNl`*mh^{G+^1fNM6XQ~tt_ zx1#fz&}Mfj8fb8#K+k|>!!{w-7s0tUe5W<|B3O(829|Kk8Evz3_NjQGxo|i2kRTGS zt;2yafNMq$ZO9ekd=ZRA*68O5`o2GNhs#5O`q0e_iH%AYQ>A8SjJMrHb9+Wq{&g;u zfBzkb8uDc@p}^7Lp$+95jFKaT{@*onPBEI#DKiYq5Dfra78?qz4yychO`jcvnOW4Ecb{EHsQXwge$0!i*|WqZM>Tx0%!k!z9`lCZ4+nvRRuVB6uDti$g3 zwCj-9`d3i<{vl=iqM$cexH%VtrmTT}dW3=sKn1;Y!9&oNdqG7qEG`tG`wZ z?Oh$Oh{ydkTNBP)!kRm{IVtJ>!szZ`plYPFVuy3aDU}c%>5a_1dP&BMKN#8-Sp z+*x=bz7YzJ#oopG$-;MGgUe8o+Tr<2ZFZ3<|L(m*nP*xARNB0GhE8^3t>A>sxM&_pfA5q* zxC1LR{?9mas>|q2BJgDHf}e>*;GDitDblkO)1^xyjiWPpN-Iwr4M3O>b0~035j$)^ z+%exmDCgQNQUJoFPg(j=q_NIUczQX8ouf#YPNMquBbP&7$l@0k#m z7qEV>4h33AsAc8g2whoW>w$#ALrT-*pB}}5e;yse+OI#Us15ny)t|}*u~bS3O9mg) zf9G*j=EzuS^3e09s9&WKefy0$?d>7lCkP~z=``l1^&=}36K2Emkx-y*D0p)GE-e|3 z(2y6AsGM@5tht>`OkbQ9mQ`pi3l!68voH{_Uxxi*9qbURvr>4>0958S`1CAn(PO_< zc=MM)5RUbwFw`yq+cfZH`|pggWX$|hNiY~O&RAa-_a!_H2A>i5g|=m1Dkg{8#rooL z)?xTknc#RUJJrnlo0oqH?LFQ%0VN$;@uf1`ps`t9mt67Y3ZWG^<+1yez@2?#8>t)z z4Whm3Qw@hqHRHMi)5r6#DnezdYfz2 z>|I!`-m|@T=eUS!^#K)*7L2P!vRHvM?*HSpTgNdkEHSNCCYu=_r>%8PJG(n6)3fM$ z=;0I2wC-yX^$2(i$9R}#=hgB2U8?Q9ciqLjK=ao+6Onh^jlA*Q7jNW^rap!`)k~d) zI_hDlQ{#xo5nHFhk=nx?SPXju*Yuq8&9i?1s_u2?V&KCjd5V*{v=>jo-?1?|pTp;v zb8%^i|Il#Ve@RWPx(S$Kc;wsLd~xcVfba|5%qh$XW_oDqKsSyyl1cB}^U@v6%ns+E z_ip1R?TbH&$Vi@4``Z_~->3>B2{U!x0}o8u#e) zPP>P>`Jv?Z{A5d1H#2WbDlco8e`t3SXYYd8B!NX4_f#!6-66dPKPs)|D?V1mAZM!d zvfo|6_q+25y!1w^!RkabWlGf?SY`Q_K63JBZhLfAHIx0k^SXzY?_NsFrzKc2xo&oT zp=?(5^emOltYv;uRbsd_T_*h>WjZz8WC}{P7%c4kwEV;>;E(BV+(n1nXqEXI+A6a` znFHN8THQu&5?~QffRVPP=?UD3Jw_dltqwX0! zN_l5oPvCe|8UWFlj}wFgr?jxSXwGRHrwgQxj_5xGr;C@2#6HuLnRM7Wib&X+__O`j zmDkcie6eg&Rk_I|aduTV-mHnCZ`PC`#o6&hdanDERQwODXkt~XFODsz?{zL}Yr=b- z5`M24#5xYE46f>8vg@3RH`$mZ#G29mk;Gh5wXCYaWJ;dl3Wm7}{=Xa-Oa8aVMZy0W z7yoBm{Qr4eEXXsOM7EFDlL;o5raE@ofm3S1fH-t_jbM7s7pvkj8zH;oUR_o5NuOSO zq_9igUGq8O3RS?peT-jQYrxs9#T@Ep72eIv7~>1&_`R{WcoMHC7E3b(SeEaO$-J-o zv(DXM#+U_WjCB_#3(Sl*Cy~o)=F$J}C7FKD7CES8W~hg>*JEZrlo*<%9@5;=)u-3| zZ2G;kOI}_RlRPzr9u?JSgh_}8VRm5-+XX~SEBty|H@^2{Jz;154xeN)c&v34dB@CZ z#yWS>`3ye$y;?BG{5J8|I!*3w^^^6?EwAjWNNNFt_HPHvr}`gM%9c_w9D3+cmWYlcRx{GSoJ}*tE$!XsdP)G>D*`6YSjx; zPbE*Pey#8G|7A&6-J5i@EETXMOwQYQroX$_nRZL#Gbf!JBahb_y|kq!3B1=UO%h8uzls(_`)N=AkL~xcmp(Bwb@RFZ-gYk2 zWGUR<6PO9Ky$fW9CmHwB{3>8)`B$7P&ho+wkQ&h1Eid3buZ16vX(bcT?{u0zK7yIi ztgx-Eh0ox#-;4K0P}kLCWKNahK`H#3&go~LPu^&H&6##~hQMT^$2~@nbmx9s&CI~j z1}>97g|m0#_-^{W+sU0V_B@C6@TIqFleWlelH^K~YLlLGCb<|O%@U;9r?$W{YdFhF z2B9V?5wQmxc$^FZ&CMe>C)MCcMG{@qqCxGydSRTP>txJU>8WFCecsjfl0<1i;fzx^ z3Hd@O=_Vks+Ez2!n~c9rYyfY=-;H)*>2=?I0|Db@2iDlpaxJMdgI)^NoMHOY=pk@udZoIUgz4Dh({%|{lrIyn!Gk{Ki4HBxo*8T=1D z$+EP6|NV%)ovZ}pAIT&ZzYS}}MX$IXD@aMX*R|OdcsCOvQ1uB5?E<_t+LqN@5j z6qp|}mxcm!Lz6^T>HEmdo(%=2hgwTf8ew1^Nv2o1CUx+>DI^Q^j1Rq5peNsWuJ}N`|Iartp88gX+4J&Jw{ShX#R)HGke0sm&IS6yyns^2Xq+PWu^HzDeX>mXH5>K-{HK zf5SIwniy+7BE~|2XM-qHrT&I%R3j>D^xQTeCvpYSkR?nJB9FpOIArLI1fr4kq@w2a zJx3@a)*Q=^L3w`$0x+?NZK^H^m$)|+SQ8u)zf)R#W~O{Z&EuP3X0qh<8f@$l-jb{Eu&sX|ipJcbIS#o4 z`S2gj#~`1L2Tm3GO*lr6F`MN11JTfJ0{Oh4vohvvc+yPr^Z{^&Sy|ZQPlWw~dY9g( z*F5T)xFbCxzgLyUzBN%{584HcKOOZuwC;e7sF&F7h$(mrK8jG_K*;tC> z#>JixMj^)QvkEXhM~7$@~1Gq4%Yg7!jj!==1Bd_>5 zOK|_|+Kpka1m_uzCtVvF9rxAZY?M$14?u9+0hNlF&{ovv@>Dz1P-xsEu=|*%Br&3o z1zMMDh;XT@V>1t&S^+C@?$v3vvGW-Rm)R8lP0!i8wHG-7Rx8M!o)5w$| z&&pKDP?7L54@F)d>x)r^CcR-)4>1#aO=_VnsuzMI$$EU zk5^wnw9G+R5%Ln(B*M;j4=sJ0dtvp4B^g105NBJ`6N=G7*tds<%40>X`I| zbJ^8SndAP{$FtL`m?=g@vn;Age+u8`CIyI#i3_VZ>nxzbr+ZY@F`16;C*D13Y%;~9 zrFUmlgAF6nB6Iqu71Bj~p?SE<02#-G(g*`IK7Io+#SnJpZhTJZs4`_?l;+5(Ka-YK zDeUy=RW?L`XbiM1Xg*ifYSU)eA3`}e>ll4LoJSiyZW1oslDV2nzXTY)*;K;SYAaHW zv@O3_+WV#MPrx>7AS|-St@Mr$ zs~f6xJ~e9-aJ3HYQHOj4S4KWkU0T&y{W+v>8sLN-m-t%)c(T-M#y^naA2XB=<#Z5#I*D+!i;isv^GRIy>&aPt8=2jDh%g}fsN4q&I zqUd*TQ&{&3iA{T?dL`OuZuK9ko6(aNO57CKXu`32B>iT@SKQ*IZ(v?G$(-v!>ua?> zj*Cg3f!?((mG&*#^0a?lNJiOROd87ml07vCrGhcn^K1DxRexB`Rk1UZ!hI}9zH(&_ zBB$v4KzUkR?*?u+lD>~>=u*YF`haQ9KWR^65&aR$VJtUQw+T9oCt`yR;0D%Iza8Iv z9|xU;(=pSV6t=F(xdWg5UVR_KQenKlcI2*GzSU1Xq+4 z{?(*+u`LvvPRzWN0SSR4R9hJJs?s@41=hEv{cdxzydVJcbl2NyNNv(|+uen+CX6B0(A{M!*KVK5+B zM1&9*<}GPglOsg|4N zd5TJ~cSM9)H3I?dPlgUHo`RF?RVqn?BZ}ZTHq0Y#hw5X`p^RXSiYQ2aB<%Q+Ms0BBg1FY#Aeu4O)a&=XPkcT$Ka=zZkUR?7ah2uKfvo zs59l?k1#C+h&Zm1r*`FATtl+VjzIq~&y@EL=gAKa(Gs|C zlTc5i964y~}U4^&@a z8?%u2t6>ILx_{ytb2}Eve;DDK(*)K<*>#Qb`Jt^RAH}oMbT85^NCqT~*99-PbM@NS z>x2{`^Cfs&fik!r*#9%FQ+oK?kB7#0u#I!@9`}bb8p(u7OZd7c3!;2l-60`XvWpaj zk#Gu}7?x~AlVNPtffKMbQPvD@0-u-`5#=Pa&znZaZ<%q)lLZcFmREaeo#~lmxpy2FCfwR=vnBwF+ybBu7$d~M+>xd5qmiK;DE-)xpv&j13_~= zaJ|piF-a8UT*l(ky}<(|qdj_F(H^Q@G6=8ld4;b9f0#=ta6<+~RG0ylxCX=;@0l$` z9DTev5^+R`$58`0Q&0AfK`fpd-cTLU9ppq!-!{#dj)%|#{!yxHVbWRe1JJiGl^SI> zhV|TsV_TU~HsE;6=yAV$Ybs)SY&0IoW$bs~LVxAUZu(0$$Bh0mhyNot{>vTBIc@xn z>+->a6Ta4|*~5BPg?ryhd>Z>nCF3a>Jz8q67`+dT843lS2%1YZKsfUbOU0iQ-k@zX zmukUxW3Hp}%2lrR8)igzhqc6=BTJ$7R$291gT;e52+6_Sy z=HVj?h<(TtFPSS6MOLmEF6q1^y28hg4cj{ti+aTBf;nOW>U}|6C|-13f*<;_*C>qY zS$CuV-1(N8n14}|bR1v)SxqJk@nkxVDOT{FY(nyo7?1+w7zlX+MDMmtLgwT9H9JV( zx2nip`2WC@RCnTG8Hs}Io+Hn@Y;YvYbwgH>b(vjhVxB8YNZ$-rOGh9urI+$=@j|qa zDw##DdKy;793jD*B}7=ZfBaEvRr&S;Kp6-OUbYJ9_b@Zg7~x~vI^d<}DTeFa5M`pWV)haSX+77XtWg=_ zEx+msBYnGOrp_Sj0@K}j<%8C#Sjko(atb=SYuo-A^8Q~i=UP^qfRDU?l97AUjJf5H zmnRjQVZ#apYJZIKRYlkq-UVwMcHh&Vz+Sd7|3*JQ65ht=0i@@UvIV`xdL#t?D)3zk z+m!?DbgpBXV5KB^!qwztIWPdmYatHfKUww-R5^*|bCp@R9+i#z?Y^81ZIRB_e;?S^ zjG8${TS+w-g=fIr1k4F-t5;uFlOG>fk&OYKwBh^L=j5K)iD%2LC6>A+g`cyS_h@iw>N-p0ftg+?_^D*{p6-h@DRS{8?$t^BqI-<24f;JizO2yGd9BD&Q zK6j+U5@{{LmGds+={DK$e8a)k3M2T~wf^n*GvH}7L!QzONH~``Vzx4f+232mI1=Tc z@(m(W=*S=E$pXiVp4p)saANH_~#KMtjRQSU1F^ ztG;(wN@$%8dduaWw4yn%$tK9Z4BBrTeLq+vWJ`Eg(Jw0H=CTfR#bOIV9P;hL3Dkd7 z=cVnkKWG=3*U`U%8^kX<(!|6?Od99CS`vq7OGc7QRyb@Gh)hPLt$Qi!iNk!!Nc1zV z_;&Q;nQ{>%!J04=(w&f?lEnJ(DEvl=@^d%(7mbspeeCliYI68d75N;A#>WmntRgu$ zeh`VS^|vlLugtD@!%jO!(4emk6i^vk0}Pw3vj~>#2L?Y^NGmhzCd@qj;2D0xW2r!7 zb#A*qcPZ=5#aulT_Cb4TxV}zsH7zxH$}5=k9jE%lsP3^+vuN2|@6>o*o9&&eL<_B{ z*CiS{k}G4MYq^bl~Nm?ciO@ zh82DUGVo{wto*ym%W7gm8^$BO|A>lwc~K1+HCcWNdl=-(3BlZ}p;+EJPQEl~?BK#H z+V_Z`T_i^h7*1M|KmK^6z&?`q2rt|Y4$N4u`|-U>e3#{k++MwPuQH|!HtyVIz5247 zVTDZ;;^p;2bEG;Y8Y!l$?C~YNdJB0RcC00$u%s7zoFT5jfhb<~+XURpAhkVu@lo4j zdA;n^y-HNql3p&CX+p_mU*rS%Kmf=+$k{` z4iB3#-$OE1dq4DT!JMP}{zKo!m<65>5osNbPbOxm*C2i9yDuiv1I`uNW54^*_uH5P zZ;r%ZrvrA8;EBD#gusQHsW+i*1#!=FM9hrTfiWv+>d z#b+`FzD?(dYD^Tz$?qr;IJYJyK75XwkR)pMFjz|?>vW9~P1@!h`Samz z;nsM`OXXk28z*Pd`3$pWW{i%aZiu6kvyiD+K_?~2zTjMF6@ObiL!Ni#@q%r_*Mhb$ z5}H)Vu@rjlP9Yjmh07p28@jFs>_5YrY{`**!!+hpH3J;-U7bEQ=F3xHUa`_QfSJY0 zg4L2tx#YbVu7%dCRU*w@MR}N^obb6N$Ojb8k|ci`)HKI+7|@&bL1tRy_mew62F0%Fm)Wqd!Hr0tdI%k70;gc7QMIdv4TenV7=cv0J}XTWpf(5Nzfk#)0*0fYGAYZ zZB6UKdg!}HaphGoW#qn|g#Z6Kcv9hGPbzGdHoRtQ)ATp242F(2ISs1 zbY2!mkXz_{n2vzTA=~l$aS%>k*b=xy))%MhO~_+{bQ7#wYZnd za~idK_Dg?2Pa@dW!z@g*B*+mV*SlsR`t|Dp{bl-YOx}g^aF7G<2~;L?a0R^3o6@I5lvBJ7(yzd^ou`O{EbBUX>_tXl3_g>!jQ^wE{Y7$v@T zZB)Hk&^P%5-M`Sg=x~=m1zGT>O!wS|oEB)LKMgZe7kI*DfC+;vHGA2q6Fe572)gOL zp{S-@XeCVhGBEt)$n!&n&H`MQFCA3c4V%-_J$!dwn%=V{P4G^T?oZ3`Jd&2@RY~*0 zWyi}8h1f~7?oWm5o`;_G^GK~Qxija+lT8cd9=Q$w?;4@4WA`i*{DFBtPr&FrsYGX; zR16pLd!uu~Jv5ReMKsQo$Axl*(V8ehV<(;G$H~tQ(|++FxFeF}b0fSEC$Apa-lIcq z5_0!w!0)8l^FBBsmMvn~Ws5kTu6Np()nozYsRSI8t33Jsw<_}QNZm-CSo;d`-)tla zzrRBI8`6D9SxB>xv8PIcL3>0q{t>_8pd51PaPwq!C#_uV{ij!z@m-%#+W;a#qwqEWDKgpJgb^ERL0rho+ewRq5g? zO~NS-vm0`KF?a1JeUyb0R@ zn`ZN@54XE_=ukyMW1TbdY`Tajt*^_9=-eGIZ-Rw`$lc0uXd?aqAHJIQyJvCrm^9wA z5?5O=S9S~?+Bquok);WAweO@7S)6oOw0&s7mEAwln%(Dx45Zoo^{qv>hU3zghUK=~ zFxOK_?p6<#_{{Y4-V(2X|IAAr_?5d9vApQZOT1G>v;nkZsyAv+eT*LX((oZsEr?rWz;^;t3KG_6%QkQ%G>dWaBG||b z$7?I{E9=Evv2lR`Wf{;1yEZJ8|1CVe{y0p}VcpInlXz&Pv#=^N+6<|z!d5|}09wVi z3fN_C$N0TsE(JH{_q?xwY>`>!df-6sdN4taO9vJbJ4m?1C8<9psdFd0-p(zrXssv} z!Kc<$Vp`nG08LQla+SvWw5%1}*GHXy{cdG4W3{;A232yI$jr_jWUd)=9r@Hw2CO9_ zEEZjTJa*yL#|_l7Z3NrcqN${N{YqDbD}V1KUa& z3)6z={;D|GLm6<(7m(|LNxi&qxzhk{7V67u^?UN)rL1^UcEDQA@P=+(v2GF5%nT8S zVU3#rD>2M8oh~b0>&d86^6`+d!t9WA-<)x z*jV1W@HvVeH8bXY;cxhbh!(8TpI>ZV*i!U<613k*PdW9l005_@8q+~*|G`DRk^1se zLk9d-^X(T$?=v=}X^O7f;Uw2yt>qgH$PpEanHc5&_w}_vltqEd*q}Qi@UspJ3kOxf zdwc&<6%WsLG3M-nU^XO%Wq6~1(iEK1K#rhnyND;f>C7>@w}{Vcn90n)evG~aSU2%h zUnw)7A^#BEmWt;|Cs#M&jxo67*TI-Nx;n3|jo4?yP95*Bosx2PMMNWm9bX2$_+2(x z7@Go#2b^(?t{qHAhW11$qKTrw7S%F2B?7HaN01<*{egQPO5`NiIlcrJ<(~=*2fUGe znrLR$b4o$Z^s1N^#1DOYhwzUc{>7++YQMHP%D+?8`IU#k4g5lse}9DvoS#qb%{&Mp%av;iqhN{t=NktiXO>8|GbPvJApXa1yGT z)OChBt!t4h_v(8K`Ga7f3r73-#ZL=*|7o!QwchuJ5v`$TvByW`zA-6$bL_s`jI|^x zMZ51UW86OMD51)|ni&_rj~!C`6ZXv)%u*a8wp0-dDGO&qeDhtmf!PpsU>y$>MtZ?- zMRyx$iSYBQC_5vE-GKhAT(&UTs|v4xv61o)@;NUSe*c42NRU7gN9vZ%CZLNWE0<3S zuU8XV)C8pgaa^Kgw4x27ieL6-ji2>#(Mx;X;r)iReGvpUk-D{lwsBcO zd|hN?Z9xM1Mn-EweWDcC^h}Ames@89lYTII@EIdGIp=EY5fl5Sx(R!{=rN5A2&moT)5!y~Az;#Lygzy$P&U%uH2dL^JX4 zFO5vu?^HEx?KiwLCu~bjdi#B7m;S&fzo4(Jw+VC6`zYIrd+VSV5nKNEE24a&mf9#I z_kJkc40*et?g;H22Vz=U3f)(AHQ#t3|CfhWo|sP+(eJX!zXqlWr%Qh9~7q5)d48F$ckfx~a)2Yj2Pwu&wyW)1TD^L0DFI#tF+YSGK)Zn7YA!@6bz#syU+Rj3Q@2 z13(lwzZZO;h=tJ}XfyKJh(uo8>I{5OQ6~HWZ<1BK-Dq{uUx*65_LBQdlDcWxAbS;& z9I3aV9peynM6Nct4UIKM#?LPYJ9qSdD3`OC^oZ`5PG%OFIBt-;rfL4k_=0o6w_8b} zbiU*DL``Fjv-(@iCuL1Q!WmKwh}OogJH&1*!l%9w`;(~|Nl^F|9)dYY~?;yrIsyh%r`g8n9b zV~k`_tX<2M48t;!G)7b;>qm^l|p|Jjp>by}rATv?LZTJ~-STHfrcghh*EX2-?3 z%FG?RoL_suZdm5+xm5Z`WkMG$*&gPmOQn&*>7K(IN;h=pyL)~2x0aWcTQ}4>dCy&@ z_2rN(XBoo&%4dfi9j#?lPD6YzWCF@c7;;!ETgxw0e$q2Lyl3JA$JKO{EsMgsoTUIu z0m}fmC}3Ai9aal&te%u_(0x1bSCC$bUGoFAie|%7Fn8!_=Py7VP%BKNmuX}-}6)gOVMG;Y1TlrG}gz%_8%GkJ#7GfWi>Bp!z_yN^5g-!mNySk4WS&dQ;$Q28LU*1 zwlym9cYMz}&SJ+3ARnOzJu`F=ehghv=!r3*}h~$q0By_kzsb7z+FnYQ^W35V4i7IlN}n*3p5v}~i$4BSx-fTTl>ei3{0wzpt$ww# z+f-xwcnN-&v5~INE-=$?$9M%IP7OrdBt!ace5%8U zZ68+CH_H+cp<^a7s-HUH4)?Tw3 zWo%|$;6&CkR$^|>)%I=EYNZk&9eBsFK3H{q+iOqg3v}wSnKaB)FZw@)iTql zl75Rlrudkro!q&ZNlfjmA+mOq?P70NJgZ+Xto|zuXsg#9Eqwe#`y zr%6Qfj6u#HTgUc&#sD7@%{S`mqld^^nJo zTM5=KnV(yj8i}_VmHQtG5B^};t8Jq4$3l~K5A_~y?SJ4MRpTW=l>%8}U*y5Jom&Ha zZ-Z%iBKpC)Y?m0eVd-IE`qwy;So0JA+Tmzarvl&d2=8+f#^MhcuKdauOR?uon5%hh z{`H}Ur%Hz^FI6@>Q_hxEk}1r0e{eGA@~;oyZ>ek*`K)pBBZ^c;bu5Z0m)27Y%b8Gl zC8A-!OG+v$<5K>p*xi@P4p&YQvE$I{*g;laWm4xKDzl4_9+)&&y11zDtFsO|KmRUz z-Kd|D_#RY^m$Wv^mMK6yP#@djE#~#s3J+u<%a+6IsXkq{CBl0QGv6hU^B)Fhh->}f z^_KOF8M`$^Xy=;Om#vpJ=cQg)N9^Bv+qPJ@lyAAOum*DDziHzQ0d-~WhcOp5`;JM;`8i_|J9a>)Y1T_3Xq2V$~kiTAG&e*~k0_ zNQKo$k_4UQ6D2o}r@KRfp=bBnDF5~{dkWA65}55xzn-rvjq=x(VULP`oo_~djZOO& z>W~8+nThfrDr4$TFIw7Pci&^!zw2f~>I^B6y5iV6iYh%n3@;gYB|e6>icxH=N4X%)la0&x8AhsZWK*^4Tzb5{$MS;R5obhb&MG^HnzLKlwMz zBZi3tF*SFN*ZSS}%@uAnscd;Vv%v3zopWs{@IK9P2Xb(8g_S1WrmD}=iR1BKxXoU> zaeYk0*ztS|y+U=6#^z%lLv#>jj7!bj@vjIWQw^ts&3+Gf-?Re-i9i~DtD7ruHu_d; zgNcf|o#3r~tfh5gW&--Gq%Wg)y0ftFEHAxu4>J>cBAC?@_LVwP8|Ki7^?l35P4%5a z+i~g!Jl#5Vvt}}}35xcKcnh;90%%PZnCtxEQ426yVJ-a7E$5XlKW2f9!ydcfG7zHC z?iC*?9~jhvroL7{{UXz_BN}ZpTDKX&(v6xH0;XK1?@Lu>wPTR=p^mEBB-C!=8#`jA z@ZF1)N#+MkNDvVltLh1{3So_BC;HIG+GI%+ zz79Gyy$Ww^EBniMwJ(yvbr0<_<`=H+j{IL;sk=+aFJ#W73QvQDI~q^BZ-`#6Zh5tI z;={U04D8)T^ykCSKWQ)2zCH0)2M{kR-_1SQiDf| ztq=FdCiF-(*^mCHX7DDS9O~*syP`iP9{!)}|Ml=_ z{T~qV1TM#adh+w#qgVYupZO2NmW{3Djz!0IJXY{b64zGZ0@ck)bT3#*2^z# zxF`7^<}$%yM3Hv709gk+euJ|82BiV7~_8 zQy1}x8fKDfv(oX(=93*4MPk!SrJ}jwv(>JOTXUJ|*vF3UWM@Dm)xKH4c&_ZeFoPQdCa(iwSH`j z^09b3{Z|fEnuQlkua&{;Sw(x+v&fa>X{-Ee;%j9nq05Aw_Qrv=o?2_ShH~FMTxqE+ zG5vXUYZ;kxjo!n-$;Rl9eAtiAYm<%oXK_tW&rJ9;)eiVF&H24-uET|VhFypn8m-CQ zA#=y!%0^Rb8571PaKP0j!0#P>16O;q{O6GB1~zNQQ#8ip+5&g@9X=!M!5e%^L0_59 z3;8$R;H^sb5_1{dhk;CF-gy!T2s-5v{jZvw*5ArX>2R2g{Rnryq9}ymArMOk>)75(pqT| z*%YSbP+1f7UI)bmZ&AULzRV5Pi7|mY-(Rp|Ybr zX7sdsVWlsYS1Wc%zr(G^)qWFge_N8z6 z-S^m+)V4oazzbJbJ|o17un8?=-(sMnx>rSFv=c328XxB8NBFo1t3)hjF#_dG0|Fj) z_N@HXBwc~Gby^y1B6In(KSEN+&b9_!=iP~{^r7>rcewxt5O4YF@vHMdj&Y%suFO%p~PtouT;dp6AUyBxPZagY#l4l7}SUD{1@Gu?X0H-?{|!J zxU#u8-nW?rTPb)KRn{UopyYNQRBkhL__D~ogYMxI@CLWd^+#PLCZl{V_=d;`nD%hT;=x0euZzo!t!3}HVzA4^gdgaY zqt}t8Dc-o3#(~qzC_f*JYRPwLgy`m4?5X=P5U#UJBU&h1++(F_Vm}bk`bJ~tg$;9D zJ>~aF=8dymlh+ua8521a9ih5u5oB5pyI*kmy>at^<6(X*JtWpGaCAcMsBBztvBC}? zGhNGqf$Iam)<_hKV1KaVvnxow|iUV!ryk zhtPxQe>VKrxM1`tdNz=0r@i245-n?rMjl`~a8OJotW=8DX9eu-}ezROYk`>;I z3Gl zjTN7&A1v5jp?Z7ek)eWo)5q8s3K-FTa$l5xcXbeZ_Z;zYTI!Le$jz~G!NBX31+3~w z+4Sneo%@xQmYtoah0B#C9jZ4)pv*>dJ*$ArY3p?lWB&L8W9uvX=mMFXEBsP+8%EIr z8FO*RUr@_T3AWXTvsN>Xt;W6fLGJ;Zj9BUzKOI3aSE{)EpR6XpGPWxKNY6-Vb0$7=?9)8={^eLZbM z6ZOeXMx8XzcRa1EanSeY#8H1%7WOQB^MMkRL0&n`N)GJlQ!{LKp?wSmX=^+Q-KT}= zX|sW-$x5?$?A?wuos^R{!!z&H;hp*YUHOyG&P>bl%u1{9#z{-k)ZMqHEj+U*ZKh{& zn#-Fe-Iv?VGf`0e%UwZ5tisaM7tzeoq%G-w-!CtPFM4bC* zxJ@j=?DZ(l0qh_i6358Bp*LWgiZ>oDtN&*SB-6@~*TkcACcNKcGWQ1`&yYFIxx}q; zua~JXbBy+MDuXh&g!*gW_V-Z9AW2H!5Z_^Qkx5g_H{ht;MJyHNlSE)Tgslaf^%2to z`SOSv{DgDR;~IkIj-(>GTT-l?H{t-QDo(z4_$aU)cFY(WA@{@H3Oa|VJ7xj>l2(~7 zYl$7w<&Fg^UjnfJzu!F!Su(s=4E4dx-l`@}jOEQpXCNa!jdVXvD^z3y(w#_lVI;62 zWX8-l5AE^>q?gyrT==5-(j34z-7H_V~i;LKab)->%BOfkC?ONe}+Uzf!XrKP*DffNM^{tA5s;wW;`!sM2Zon`O}f#TBauKY^v=r zcII4+Yzq~M(J8U=g%OpICExtZ!y+%N@0g9_*}rUeYR*kcnj;)Z><_&CBaM`rAw<|1 zbNU@=U=Xrm?7cWb!uwQGZHLON?f&n!z_SR;Dc}7ssa2vY{u)bv;QpUiB`!{ffgKWi7xPkOXqi&h0p$sFTjiK?QOL|}ChWnl%vej!)` z$*JwPsmRV^+D;seA(@_3jo5N;yaZouN{3I!-aA+ed2Sqy>$WhK6Y$*aJ{2M40h1ch zxvGkh8l69SXUNrI9#twMk1~UdrILQu5xlFbzvwb?Eh0|e!!yw%MEY{uI_4Mmqg8d{ zyoF?l@lkeC4_3KcW4nu=84nqGt;A-k&e4%p9Rd=3GU_(@ymGn@XjNZ4yF8H%*Kn(` z0d_T4YVOrdNx4^FE{hoA2bcEN>FTgY4sEHYueADN;puAkpWbpH9A}&>XwOk8{bm2@ za@u+&sr`Wmue{-Z|9)dJ3w%O!pH8m_=HGbo z29g~~`GD$f%2Hm?*rEhmk=cSbBy#YdAQmwjZ0W#HyWQ6UOMW4f=^hwMWk=-CE2)2V zqNf{Jf_gBJFcIZbqs}?dHxNtQ-XG9kS%X*&2kQ{5RsDfgSE7X#0(Qc}69oIT9S(=N z>i=TvP2iiV^1ktNlbf|^n>KApOAATULb|8WLJ=L)Hoc?^ZIQ)-ph0xJpkf6a%c2C( z0S8B0irU2mWt;(AXh0k@F0IQr&NEvw(s|e%uH!QUwop$Irsmfka0!1u31^4L_`>|1k>*^^Yhb-{)}f~45}~V-kw0&E#D(; zh=m`({9u3e-kz;4yKuVhVyJP?4%g|1WnhEc>6!tI)WP)$^zRclVMK@2#r@g6z+-Dl z1KZASWCzc5KJCZoy523!rJse|!p(GXsC+$lWxT!U777lF>qY#$Di; zJTT_6136nMd=Wy%Z$#ldKI+Cu1pI%Oy09Vyr|+3BLS}5STa{gv*uHTT2n^(&1D~M* z2&O+&3ku6LIv7%7Rs-Uw{d;6YQ*;?2E005iEvAmE*i)Hf&Re!PottMU{9Tas$JiUj zALHn!)91y##ot2m7s8&f0P$OhPCNi^=`j3HPTcR^t{I8A-^Z)LZjSF~A>L~VT{y1E z8g*@J*a^mJeq4k2{v^d*At4Rz;;9CAa1y_z#*N4*axm_A39TQUHv9`d2S+mOHKO{w z4j~VE%S9~A*HKd%Ig!PDjDxvY?@aJhA!jI(`V(qwMI8$&IBNyW2I*g4+aOEAN zvjlEl1f0N(f?xMysHttC zDBFz3mH&QENSdc?+cSOCrG0^K*TKI_HWtHcoTOJ|u7a-{w(iLVVzK{jusW;)0!0B` z|LIBA_pztv<6(sYPpC`)`_9skl`t-z$0qUQ8)^kT&Y|pBA}BHut9qz}217W?G1oue zt-x1SBP_)e{0Ddd#3w&z?iwW*kmeYA}Q9 zpJ#d9ktG>(ak$54 z=Q*p9W*}NC$!8I+jja9-QCsJ@SXZ_my0F$whS*upw5d6PQo49v-Mm^3@gzH3s&)tN@><9XOvz$k>JV*<%!W=#VDM^GTpPJOvY)#b~wkhW>`mz0P&nGVtpE2HEHoEB_LB~lALR3eb{U0Ga=Ttxj2UL;$+v)YCs&eun#hI ztYpKnT!3W3BHmIA31b2M9jth3EtX~_WLds}cwV6k`-8Uc_}Hi|g%pLdGwii}?5C z@$Emvc;{V_=ZEl~j%LKyLw2Y;p(a5rKSyElva|4eu`K^F+;NI9-G6Ol(|2F^k^gc% z;vVFf!D#`-(So0WrvXgLNp#b=#jle!10yYAj9y08GwF~8Jv52l4_O`azlF(yS-1xJ zS>>!67UjAP^I@d;VyM*%2CBA@%f_D8veT96&XkeeWzZh1^$D<5Tk5QcgFU?R?xyLY z>HwZ!y&D-D5zExNETn5zySL>dGJF= zTPK-5Jr<35kM@J_&?YiF!yeN6K`&1nJ~df}((eYpJql}=We=%|8OwB(?Sa*S^^`Fe^dU&H4rE?QjqJjA zsW`_Wf_E17S>B8JOcOm84k2=L5p-ZZxEPG| z%?Ky3y$#r#lNQNi`~pb!@$|t7jODk^8?dPDz?D~G{wc$8A58q|5;w~sl(M*$JvU=a zx+16ukL52uL{?j@vp$;tpc=F!kw_NGFHuLt7_l#{c@Z1icht2ZhXvo3EFeEcbsVg^ zx>hE;sM}%=7}_N%uCEasYt%?-OSUfn8w6)NjNepq!*fXr^n{Ec9hhE`rq z{Qyy^$-pzK9h?2SklGU0sqWsl=If?q#fk$Mefs9oAHhS;_W`LruSNW6h2ny;`{jy% zoxcyWI;YppS9SiZ>fDzvNPL$*H#3+gsyd)2DS)2K>_E2m3OQ!ZNuTv5K&Md+egdQ= zZ`_ZwurCeP;W?`Au8N(1T^^d_=&0I$zOriYd?IG`Ca`O=ZAl@!xq=v+WU$N;fNi0g>vE55zz&Hu#i z4I$c*C}ESd-Cp&B2K0>&h*$-Xu}19ypI_5~@uHLOSl474hD(6oT8i3HSW~o!0wK;t zGky&ODtm`^d>zhz^V~H0(Ks3W%-}>`Qkv5TQMTh&J)Rd}-n9=wJs z%qc8(Vgc1ns^JOwD468W!d)M}r0li}F_=ZHg0)tgxgBF|0Gq%D02l$B1|o%pPEK8$?{Qk)}?N-YXcp!j&p=_BTAa zvOX$L4CA*3GDRB7UeuRi`6!kbQE$2#{C`;fH+TZSS}2cq$jAAy%mC5+Np5>Lw6x{} zJ6xk+Q!seC+;hYh*R2PTH<{$)X;<%lp*n>3XNR^!jEV!#RTqHc#3batop+pjo?uoS znN$m{Zd+5c=F1RiRrWuFr=Lf?6F#+}KesbpSn1mjy<^&NDT$}gj)DOI^T1saYi(q| z)GiO@G*7umg*+RdkZk< zPlv4D?JLZii+B*CT-oA-MjJe#10!6gydJeo=;Cc>&bP$8e+Vo!epn|IXHqefD-rRw z5_ZO0CB|)#7>FGPH5Nc3MhShaB10 z)aw4c4*uvgniDd26&?Uv)R8&#zR}p>9ooVpEGzc;P(cT==LLv$vwCKmrOn!=>(B43 zfM%OHS>|`U3lKqQq<w#A_iqh8Tl#QN}@_Jo)uFPyCQQ-bFcyvIpfElur(; z$w4glqx=Hv9VpF+t5?A$z*s5M@U5sOpw-y(FTau!^V1>CejJOs3s=jp zOpDn&q}{#*%kM{Whk&=X8R>5#vDKuNeP>IrnDc;w7+3auctx?F&BU;0$MU05d6xS-{PIXue9abh;!&t{iT}A?ro6w z6NkN=aoDcR#^_Aixb~k)uwhsi&{Lyc#F=75iop}$t8)l((2bg^xN~vzw-d6>%B~Bl zaU{#=j&ZXhh2Ax;67H2W|5yD|SYcL5T6-o&RZi~|@^Str!M>*Tu`?5l&T;f8WIOe_ z&)lEYv>?vB94+b|&FI#Tkx=D;mSo7BBl82$sI-5-)ad^|uWQ5k!Sf|?c6~6T%PCY) z3zyM`eYg}lI5x9&x}>mcgU9jwcv8*@2~--hv>I6k28^RzX9_(tW^L6n81+1$U#Csj=Wysg{;lwdJSwY8QqoCsLpskg}xIZt$GW~zWF?Q z(c$sOfxzjR`21TnmxY*we)udbB$)?n9Ze@K-Fg0u?sJ-^UMJ#LNq;%^ zSRCQ-|6176Iqb{m_*66fG$dtk+YXO}f&58=+^jfyZ6ttizwg=wuey_ybtKY2XulV+ zE)B|HKzbBcupO{=`h1YdGr4gUj&8-#ap$zKN|$3+NurCOk@SHjln+?Dn`V$aYwPd@ zOD6$;%hTTI6&1qp$d>PR|L2H8#@S*gbg$QNE~B$S;~Z}HW_FO-CfLduM>PiwKu!2~ zg)(?jT$O&pW00klF@xu?e6_lC_X(`n$bnNKLM|K zhq9e$61C)8qs=L=QFyy)jMxIdiZlH1Dd|dA<4g zjLvEw>0oF66lYF44+bx>E`5uK;JDAgn8uyU?9fQ;EFZC7=UGO3TZaiT$Xpg<_4^1G z%WQd6QSB?zZJHEcd(p{M4msSCc8pBDMVrNRd?;{J#nxxBQ6yA zskge)JPyHj%t+^sbu<{MGk&KFE+BCrpA+90j;>xJKb?*y{I2;UzkJb@!qs0nMwG>X%^ z(BC+T{ojT9IpAu%7$UoG2U=;Gs2<#_UlE#Z)cMFPt+c&id-YD-X_+tw{1R$mpO3&& zFZnbtJX($AuC36u9<60uJmW5Ho4z%sy-47t%`&r&iSC{F5xj%>urKuZ9k7n-!afQ1 z)JDdW`j!`dAuGct$J1W{iX^pkd<8}UagCb&$^ zf&NQ>Lp);{v-iivcgA%u9pD%uz*0Xz3}Ax>hsSo!r{H03@qP7eitVd!lej;9Yqb68 z+eDN&jSsWcX-@jtJXFQIEdF=j(GxgII9A4L&_izbhx(j+Q^$%h<#6hu?oI8k!07LEq2eT z$$>3{we!xf9=sJFNPV#3hFyiV&FBj`XxYu-*e;v!74FXnTp-i@=Fs)wuW;Y2E;=W% zJ&dy7SKl#*uEN$tE?T#3g74zMycE;HuCX}m0?R_Qe;z>p+yNQ#DU?=^n%s%y3Y29i zZWI?v<EltPb#55g(@59~h4;Jtt@E%c1W zk>QbwA*+xp_s~x;E6t%7A(t{QpgQm&a#RhEbOaj%e)!eCYy>n@nS0JA6E!t%=UxH=|9Ok-w0A%hScg>Wr4Hu7nx~ z-m>0f#P?@}rc{lr1oyx@#$_wA+4l!Z`px)>=Fk=JdV&|OQ%y2)4BEcDt7kpt z*Wr=(u9gAiW}@$p)z)&*VbV4|Emh+fBJP58@2(|X$lbeM=U=r}C9PinTE$~Qu8ZVu z3-aB@7nQ(Id;so-X+dT$p<*%e+9e2tX#a&6#4|_seu1tsH2a| zoNzsjQK(EJ!zRuSNuy`nD>VD&tY4B|ycT?{ku0-gedP?NFn6s$D<(K84fn_1=b=$z z{~s`w71P>Ly_789#d(eDG`v_+*!B02ku>89ZaEu-(Fl8irL97BAsR_oAA!!2WfA1J zyz5=GKn?-$r3=jd6P2oVvO09r(I!o;fmdwG_4> zqYv+_+2TQ)z&`bkcby06Xx#<>u}0;|2#T9B;_19dPK`!5+Vq}EkDjqx$@P=$Y|mDe zi_HTGR?lOI<;U7utLHrphnY?C+=3dMx9XpsNj3HcLV5)vUKjXT_O?ny@BB;Tz*h9N z=XA*6ogt8H2bjyg2kz5I)5kwU9dy!LN#6Itkc#g&$hrZ1K4HtYc;FD4@LZqIQ;|Qf zQj?coRFg;NgMSkx3-zooy0M;w!tkh^WgqfVmexCf&3oL%zE&=%aNLFQ?Xy;bjEkIp z)Ws~;+(D9G7m)4RK~Ia(&mGULGfT6Dtu1b$j81~OdVX@cbfm%za zC_|y1S*a#{Xa{B+*^HduFx_G)A7Lh_&L}a@=JRmkl ztuKmHD*z&RO-r)h2|N@(?^9@jd307pCBcVD-Q%V7j}x$azr{g@yAjl(wv>K~u}FE2 zA#F|c+YmpmR4m1}c8j%)eg>Q4)nGhYw+Y?^mSH;y7WX-@MS529rNllO1Uo8h$c*vc zLE}RLeQ69HBDVsFtjDunO? z^z-huB9j?LLmm%jv3S@xlZgG;b}d?~5=LTH$FLjh_rfs_=zb+yC53)9>hUlnDn0cq z^J~S}uKmkAqTxl7%ItM&3B0F1=6{Kd z^h6lv@aqv?P#npp1;84|1Bv*X67aFuSuPXkA|hA70qc_}=`)?+_ba3I$l;?wzL|~+ zO<+b#ph{!3$eFi~dUh7tMMxuaFCB&B;;$ zmd>;UDHmTPkPy@mNcFS(il;qeMTLssHDDMN(zTImSG2NzyA=0Tff9WOjAzyfKHEQ! zvRUX4;Gk>9{U!r*lL=OsT9M0D1au;oqlb4QGGdck*b?!G4~y4E#LL8Xa{(XhsDP!? z!dbGVt@5uw%D-kvw=mpBCYQObKr7o*GkqOX941ET&H`nykFk~jG5sU?sMGRMO5j1> zk=NLKh53Jqzu7F7`K-_Y3NM@eo)&A1)6Ck5^^H5*qvK>!J^1v;lEBl;ybES2N7QE6 zJ;3yg*+h*H<6kGLq;+CiOPbG-s}A1LVgnZDW<1k&XkRQ--=p%geGaYjYdkCFV&G_Q zpQ|GIIDhl0Y4A5@BO^=LEU#^@!QeyeaXNj)Ipp z!{&*V7_VMrqyzX&=2aQKl#>C!6^?2TLrcY5IdecwM(4m*j_VC!*^hD><$V-32h_r% zk_QZWj%@LaLmqn}U4bmcCnIrEu4u~O3iCWM!A8;SuavKRax^s~2j^dhTq=)9ib4bS zJ&!v?ewwg|9&WtK@+1QZA>4zW`{#(V5Z@Q}`8|uwfK&s&Gqz5b_`>O^{Yb8jjAVgJ zJThVpKP-x38SDWZ@?GR&KX%4{T>)2*V>j%i#I_E-xKvUVmf_e#5e<%cY3dA0*eoL> zKM6NOVvme$3OD*haR-k6;>r^h`~{M)_-YHV>Z%Kj-8nMCZ3`;pm%Nh4%dHmpr)x?U$7uZ9^lnFt3alr}_tDqgH0* zp^X}FhtYVSbCX`Ixp2;h<#TS7&-o#&*_Wq!L`^Zcy4vLaw&-F=^s*S-)P}VBG@Lb> z_xCZE6UQG8?-o3M_N*^stqgieWTX>oM)Wx*<^6E&labqmUAQLWve95W`^M&m-T3ba zH{$7~{YXlE3a-sE4nGDNB{K5k@UE%rt;O2^ z|9XcbH3ECaa_spRNUZF7PmAKw{T<>vQ=Pk5bnS8AfcpKluvwjxIZOE(7 zgBP#o(EobgG5Lve!_2du3F(OSlRe;6V$VDiYkhw9meR1+;b+g3jJ0Mzn}3i;2J22g z<1>$p=&&BW-_Wxukgd#!`$)t4c?!NkcAt01ci1$!3a!O{zcIN-UUtj%9g|I{`v%PI zzsCI|A2nemcB;f-c^3La0A<6o(eWZ3?bjAbuaCA~j#P~C!h!4Ujo3tRx&LRp*o5(d z!+5dOmn-W1_hS^fe`*vluv)xP^s7nsj4NRAKrUU}gF<4z>!))15_@2(|187xC!S&B zi6S$tZu;UKcx#zpf3SOM;hi+29W)ZgiOE7>|B8XEWSpIG^p6phSl~~T=gMOGEXFG* zJg^sWpLu@Ie_~a1{~6ts!Bs7KKPN~1#N*q+IJyKFEL``Gg(~uMl#fslld_0m8~HjF zteWeZIP0>x#o&r(W9p8^s1Aa$2R_`VdbTgt9(&BSy&BTVnyo-@;*=mh>!Lj7G9QYDix%5{)Tr+GW;+q;jXcL|5npJPT7{5TDbf@Sr=QIj=3_6 zjV*_TCnc^!DW26NoYoccy?Im<16zGed_Y^M3{D60i@skY#TFuaM5h;QbTVfZJPah} z^f1T4<7ZWL?5XPL1tyULF0$lKsaxajMfR43i%&OzS1Jamc#CWuC$NrlaUa01l+?Rf zs0W6`3nX?+Cw_alYj^pR_wzcV|=4e|? zLt8v}iF6brZ-7_UM|WOdc^udwZ#pChEBd55LOSB;VA$?st)EE$KF*|Q$g2;L!kyRW z9dCp_^zZN@^p6UZGV}u`lTWk3&x@P-7fxqjq z_n=>^F2H(mXw0P_j@R>$Mc?s;T=1*tnP)A}&Ci3)8eXwa(}5-E8HN2Fx`u&qYyRLN z%Y*D11BRqV*kp0e7qLD47<9JpCv}qEj%^lgFJpK}l%@RqFq6$yvc4`(Fb(4h#;`cp zKI}erX0(nLTzTWkv=s5u{2|mK`{ZY^635ZI!>)QYS#pS%IVD*;UA3r4^@-9i$_PSCqg}*pO+C$vqEI7(qqLz}L-8{$dE&OkavS z0sg0A`od%~w0)hp3yflYu(pwWZEq!dp3P@;v&?_R^rw??vMy@!nXpe>V3`lS5+esE zBOR=G_D3)>AxnwORl(${=`+AfjPXE?Ipr9ZujFEU%wYBg#;+GkJI8XN{j-tnJsG3* zL;Yj_seekn^Wlvok9gncyahJ>m4~=EYYukvkzc#j4 z{H^F03V|}ABaaWN(H^S?RroIs?!tf9phjR!xyk^`caRo*M5?bYgHMmiTZ?5pJsVw5 zMf_FH0iIU{s;k}d) z-;6tL8le_CS0gYbEZ<9HBnJ{;%sFMpF5o$m>2Jn!U_rVAUO&d8Fg>D#Hemk>Jy2g* zT~u3Cv(@z_>@(XC$H4Ab6}Ua5Cr5A(Jr%L?I;%DJCcv}JvdrHR;kx3E-aU^%NU`t544u0Xk-qas&PB$TI7MlruXfn_xcdykuIj`!?? zRcD(k7a1)+d-dV!F}zJ=v#`KFb1d)8jrHW<ea_x$N`)6ocm7PiOqJV>}RrkCS)=}hZwtBH=ua(*nEmDlh;IEx?Vss;ltE1Yyj@x2j%XsFSslf&Mt6 z>#hY34o?JT?gW|wd%Bp>|2K3r0XXC=}bp>?pO%|1eaL4EO%{kfb2N#MFP`xt^h9VFd8(5|-5XAt6+z1IMX)5v+G$f_acxT1Q6X=)JJV>d^Ne8qnz# z2leRlI(QrSwyIjVeyX)^0?P@WJ>(^BRkwp-yG?n}A@InoSORIJa%{KI;sa*MkW7Qf z>l6p<4+k%7EbJ{jzTMaGw$_X(x_;wl`zSlbMNO)7Hg7&iQ4CNt`S3CU*=Hd+fO?U|<V(VFB z3Mp02-eSQq+XfU}dcUR%u>f7~H?eD2S(Kv>F&Oe3lZxwAQT-UUz+T&m875nPlN4ig z`p?uv!t!gj?vB38e9S8jl;=_BKTUr{aX}o@vO*wbQj;_(1&Zd*?kQ*DU8D zuJh5669Znz5F{%BT-Tg!yC+FnkEeQffLUr2;GgC!Egrqpg3+jKbUpe;l}F5UhK%>q zku6sddn(6f4((yKA2Y7*h2*zP?oa4T;0}ltT;Rq=J~!kc?TE-+YF0#@7-ED}DfvIo z6Bm5emm(rYF|6NQ~V@KBfVA_x%YV9EC5*cMQU4Mm#!rf5 z!z+AB|E?3TZOh!>T(D?%ytJA(^q&BG1|LkI)yQ{~J6k3Fca1J)o9p(~u#(I^%WM0A znnh*?3p~LhWHS!F{C5xy$MNdGpWOZ5rrVetaW}q|lVX=f-{1dj(i>m6?;5y6*)VXE zf^Azinq~HhwXiSRpH84J!GH8I=Br}(goOO%TmcI zwYLArhC~_z`#g&uEe02aL1HzE@!g1UO{8=T2z$XNZ?nkP*{@FMe;c;uM6nU`!&~m7 z@|hDyRni;s`oM-_8Y5phL0#5w-+-rsFQKnN&IA~h(ZLk`gN(k%mwW%q?gqp@BiD!Z z=~{3hDh!B-2B-OeLQzcr6-t&8srRA&Z;fy011m9JaG7zG!+72%-_zehDyh|d8)U6J zAWQuvlx04NoVR@sl?Kjoxf|WRM<1Miz}-8&&8(Py#MS%8#_8>4G%2!M=n>12r){@; zi7cg^#Bu3T^ZMzXAA^hRaW`gvjRT<>tqS#spYjj(=WYOJx9qEd zJr8kMOr|kR#bJ@WHG$jYy(>cyVMV@;jS4SbzU=pjeAhnS+<)Lil=0i!z><%{bX9HtcE?8eE&DU_Y9kdx0T@QAWVn0mH6x%LWbU36*Wq}a{t`x|_S-svk7R)!3gs9snjYn;G+BYk|m6 z086T}iRLHGLuUT@VxesP@JQmf$jW3_oT-A;p#v_W7&db4w<*4|iy~_(7s${FUHcp3E|{v2?ksr|PROb=}IYz!chaIpd)` zA->?%~IySa#9KjZE1NPdO zuyGjcQbR&8b%SvO#^Ji?$SUXXv2d1XHXmn2AJ7VBzY#WDI&%6-Cg<*TRv16jKE`ZM zp$3v2>)DM=RY|lAe5elA`@FLo@?{%hp)^bOrLOWgrOuFv6x!p0ouMS7)#pbn_Xop; zU^e-U*s4tHKZB^bv&xiy#4~b@f`Qs$(KFCz$6<4aBnnQl2{Z8CE-Fp(5@&tF^Reea zGY_e#2=QLKV6FQLlNRYep*yVhA-hB))0Z3*PGm-5{EWYVB{qZ^G=!W~TXv|)CX@{* zO!uEvKf8f>-bvQukgAc@DCTB~jfvW#*nsTo3hFJ$#WMlBf~8DYBC?+2pmW0bZFGw( zah)B=nFag6$;e0naCaQo#hwlKh)QKrze3jAu8%9MyI?bcjSlmM8`zAWR8pgeTvRzGn4qX;=d8Ik?NnqZf>uHJgRoKu~!*h99q!zyd zYd&OvVWWct_qb8#uz3lT|YgRA(Y` z`9Q4}G0R{*<63LVpf9C)kke05D?C%rFknnadJHkys$p*&XPqx`V~UCN0TN#vz?^}s ze5di9OAb6$U34t z?BV9z8On5=9A=zkpAvJwva?Ob&Ta%|h1lXHv;cu@Kd!Rt&s@9=&N+=nsZ?^7BE(XI zzs6?s91^RPu3pP^Vmah_U9>A2-4(srRH~|?&gHLrUK4}d;_8atOe$4WP;%RAp2MQ@ zdY|^a8{YWzUfcDbt~-pQR0EuDR~3)rjH=i1I~h+N6J%Fe0UtWU9}(nX>oe31sJK@> z$eQ>ym^_fJN(1lo?V(K14F4?{-{5I}Y>k-VdsQq4KNj9b_Dt9ejtGS{Wg?4LR}Lt2 zXQwdxk&#!%EWV$5`rv)$O4Tg#=oN<21J6~#LTFdOVF3ZKD5UeSzWuHUxD@giR4BFm zOjl$4oY7_7WEQ>^X2m`^#&UJDwYOpGgjF4DwPR|bAWZ{ZoE;N@<(Vz#Os?>;@e(|X zll@Z`MJIl32zx{o8=dx8h!bW%4^d$G(X-&PLmxGOdteUAfpp04w?t+7znhs22KhV) z=ZHnm`xL%b#*_)(0(cdp96~>;dACO;{0Nu?W^FA6cbK;^i9U`v2`a~GEYF|skt;^Z2@@Si6Y%k@Qz9d(JouSDyUbTg$na(&+7eANGO zYJZE)B$dkbvlrV@|MJxSPMt<#Iay-q)`>D<1Iwc*4Zz;#L}a=5wgfsO%upG_7g)TR z27b2n!XdD}Fn`B>*b&O`9k-1$c|s8YkI6{cU@2o%=(7mmD4OC_xQYH`Y#wXHy-|Gd z7dJ)6B5OQHy5l&qrhp^0`5dXjaxRvqP#(?W$idX8o*IvM!X>i(D3)AUY=JvC2E4rD1tl`1-Xw8d7z5L}wk61}GiTBZ zzmT$X9xa$`@;BpJDj=$2=^w|-1g_LY_2XQYRl>WoX+w&ItQV;wdxS>c0!URo-#Yxm z8pCM?@UafyjWyCW#0IhK@ecaLI9JMLHK9Gf1p}Ik{%efyh^5(K4O;)B;8oxEz>KEL z_CgMJiRX~1Bo#e~$$b6T2N7a;J1hn_S9H)jaW5|V+bKja5mdsAu3|v{PkXXl4#pn)Kf^3mi4esI* zo8^eXIoE`hDw1uEbzb+bAeo4FL*M+(0K-jKL@qmlR)&D8LbN4??#T2;@BC<+V9r?t z6tj@K*Z}TKo_-m^SLx1c%3xg4h%Vsb%fI3WpH#DW!%bqymC)iupU?t#Q5tAPtP({_Iby&_?Gb~d%4F9y0P}(^=M7ee zm_S{)AH+jv*HtNC8FEp}D7*&o?y8;F9|K}sj-G>@@_ven)U*Kmg=OQsX#Zhyei44N z__=U0;;{Ge~JO4thjMFDcfX&1X_XXr7PS_ICZcc=AnYmUbP z1Ys~tdaH4t-zBMtP{Mqkx$d2r_@V{y$Y<0dvOIADXor_}8bn*XYM{&O4wTdrs_V3ObGh?t1 zk$54qkcJbV3oye zV4!)hz7jnr#n2t&z`S+L!MoL9%pvyRg|EeG`0AN2%|NG(B~2ZlIL3iV&doBj!D~sn z6@y+*aSXQXjMOyd|576lAJ=K1=U|}=KWm-?u7oGy)0+-_TOx99p&UiI4`nw>bZ#-q znBB!>h>k|s2*Gk0v5|IOD7RQG zW97gH^`;AU^*Cv@opH}{bGddS@VF+r4LY5PK03*Dy3@H{o(}lePI2vFgDh z6@%|bB~;Qsgq32RkC(pyl5L|9~wQnHNEW>;;D{J*Ys z9DIjAT5?T0wp1_C>#oF-z~LI^=zrvzPa7SdIs3H z4{ma+545-pf)W@EzWq;9Hu9LP20#91-s23Hpwc|o9pa4H;2F{ig!;XAgS!IkpcuhU zc^NL3FX@42t(1NiMt_{GkhoICY|V3;?zEQNTtjeWIyYa_W)ZzUU@NijE?~0I59e#z z*&Y~O7-Q$CAEV3nj2B6#nTpXZj86!zV#gk64{@+t5fF2}4{XaBh7Yt9F$`t?mBJj1^ah#} zR&;7-E|Z>|uED&fD&W2%*-27ahKUYMti=0KVZ3=D2J^|cm)EEUwaTVuRY=pL3Tb;Z zU}Jnku!%8X1i-l2&A4nydlML5zh>k+t+l~%wXAIP4u;KO?OkehGl)}=?3zGMM&ozw+K4fdZi%v zc6RgR-$wXl<5l22<1Dd2J{KUqmthj-1oAWP7Z>`{S_&|KH?z98B+JEyIH|M1?fQ7(`lUk^{Fhv3 zG!rZ46);l`j zQLbgdkS#wN!)te;CjaDwNVW%(#{wFMY|zXacYQ($bT5}}qzPku z31i3@f{tOJ`IAiE%XY`YmylhbEqhoQI@~}PMQnApnjJ2N4hIJb&zMPI<;{Y}wQ)Ca zOfG8Vjnn`Xf(zPg^2tfj#WVxfs*p4c-1jS#YJ z0=*C_9k8gt1d)wd3R({``$;wpcUn(>kGTX|#ja&|#uJG1XUpH@MrGLl0 zw0fx?KKcc8Gt(Jb3hjfz?JdY$g{;f$p1y&O##^ND(Rf@F9y{-v8e|4sg)i@zBZuD z*9ExzdBI-~k^MbG?ry8Z*5agQQGp(wK3;ys98*bC#ueQPk>TT7d)ye~#dN=-gKxUzbly zzMG5Q%olwM>{J!A$O~z{Ct&C2g~3Z%K9)0y3v5g;O`Qge8bZi=9}zMedWNdEgC%m- zPFEtVFN`_h=U2&gZe9_+e_TCe-0*9O_ec5ZAi=fnbUlD4XL7>U@qH)DWr<<; zL=vO}K12?wF+SWi23g?{*J%L<*Bxj-*22rj6kvW+fuvA}*4q~5k!ytI=Hq^}KuE&+ zp;XlLCDLyvG($%Hdqa!1vpsZ(zSdy|uZ9=@!hg1up_VVbUnF_{AZwF{C}Hew2U&}x zoPXu&wC(Q<{Z4MF`2NYEFSh^bs&d` zd*Y4u>Eyat*s`)jBF2kJRHIY{xI9gOMF<$^iLnJtU%jkB{6;?Fn^YnS9by--#C0l(?J00U@a>A(>SO#76|h0+ zyB5`lfH(%iqnTl?iakI#wJO>*$13GmAIOh&20A{m!$sixMbu~8sEgqqVJ~(v-iV8# z>wOquJ;h*=+NFWb#hLD30PFlBpi2SQ7Rtn50-1O#?%Ij(^HZ?cGy!9f34D&aoGUR= zGUg1aTaiz6-q0ns#}i|)_5#27k06gMYO`zYKxECKN5^O3In%@h&Gh~XYSFMUWTvMm z!zif+e@YnJ+-e~8%P_Auj)LuA-a@e|G|R#CVSfH0%Zh)WXY)eS*os+d;y~NYKpRS1c`^&X4fxH*q(Q{! zeie>H4&J9GjVNwy^qaWLy|>4JkzHX`y`gGbQ?o{%%@iKe&L6WNbKWY9ol7SkbA75& z3r(<|Z`-Eq=aJvxSMZ?2o2OPjuL|5&%>z}Gi2Zg0pXK}*8VxL{@RGfRtc^-ogNVns zMvV2>prsS3XN<`ekArz4k$xUgOM+YRa*L~Ku`4u-Jce;GpN6lfx<58YaujFF(W7#t zCLk^e5QbYrYptp-FM4s-5SS`tdjJ7WXEdk05SPCdS$CGE zuMnU|+^mP3c({T;(?Hk8;rG>{ODiDJ5v{T-*Y`H!MoNTyVcv8-MmoJU7we@o95VZU z2b(8&`i@}@z824^|m59Hw0TwPvFC=Dqv3U zQ4=MeF$cwq^*Ag)iBXdqY#WvpsQU)%m8gdf{02Nhv1VwG%fsqACB{6)Edu`?*U+@ZNQA!5@KT7x4Adh;+f%P1Ac_d>WZn1 zJus`&(q(9mYqNJ755%_@Bf5G9o;I@ztx<)i$5M@DE|%J=LV6<7C)w$}hL}u>0e->HoV*Wrs0jN@6)&8>F&eRKE-(C@s#($ zW*bSF!qPE34znqIAY*Y7m{oz>>PtiRnv@uZ#8D3@HE7GYV)vqfI0Z7$Q!8Q{^cG-+ zCQ~{%mG?wkY&^Yh%-pRIlKpm!TSO`lQ(sB)&%*r>37J9KvgKAG&v7plQbi;S8E`Hk zrfL?J->~>5EH8$01SP)v>A3$wO2eF`K=#Qo+xHPGQdX@~|A()v7qRIZ@cU=zN4KG@ zMscCkPW^7g@^+NFQSLxlGqrv%mOq}VYrvB2e-{cp#kVN)lg^xA-{+ds<{iGOeW#n8 zh~uh4rrxXp!k=zj{&m)XigzJfVX(2`>!a8+Jp&qAK#8oEo+?f7pt#bXb-iwL<@MGr z2R%RfS_wARLlrToxB9ZKcQiYxgTHnOdpulz-M!`NCFO8BwkHNnVxw5?vt5@Sw$OY- z`E~E+I?5B1CnDLfZjskVCFO7y_U3~-t;v?)7ULsvIDbBBZi3%Ic_VN0YV)0|JuQmj zWOHWD#w{a3o3+Zj-oxJ^911c`D20RyiTDmaySBYmI}RW7xY6=Sh|KZWNcW{dcha z>#)DcbI{{NyzDl1)D|4Yxo}hhYAvXJNV<7$M};cj#+y(Mm*ARngMz$%GtP(}odwSl zm_A7s4{d9izXW@u*1}mx4whDEG2D8eQCuoIum9o!AoWQdRdbD=1W!;br%I(;S}G=Z zY^ZO0NC z!t97(YJjdNM8MySSvw|hOf0_^Z^*pvU4oovN-K?5m@41!Eb|>@^$P2C@10~op)92F zM2Y(54~?fdK@IJYzfsbxm-!D_4hMzAm+*sq#Q5P~ACmo3ix~Rc>y3jSDp}Cp$ZIwZ z&rrUIcF^9K`|#7~$*GtX6gN87&6MW16rFrN#K~+umOzrMg$|9x4SwNEoLbiocKGfr zg0_tPH9`OItAgpAFVCPXfh^!g ziGPQlnpJ{3y&A&otcSI>VK!c z?U@#O;*TF75(>Bu9ASkO+svfusq9W=^!%8OjdM=Er+E>}Mc{zVy0s~aEj8hNaYu<| z17@0p(IdVJ`W|@jQ}Xx#vviOfFM5#e*l&5;zBuhyP70IhB2XxoPyUMvBVak>YAy1gFp^)2OmU4zID`rYd$Vt z(->s6q^RmzQu&eIx1dvCze2VK`PWhgoTme}W?qhmXZP^nX!yhUL7uF@b(&A1FY$Xs zCE`GGd@RbA+<5I?zEmaY<$FK0HeonM#rSDho@ushi4+5C%J3lBh+sMRAW!z8FquIm z?1v1lI>Ns}S`oW1YcgOdM7ESHEoL`wA^r0tZ_f^@Us1iR>AuhNOAp_r>r8C0dHw-h z71OYhPf`aA1}uk_@H_l^k^^$HL8%Tpt<1dp;O0h_4NT z2a*uPrId$Bw;kLS?|m~=9flXQOll2rEU($a&fyomFG*{2Re}3*bpavQNe_B;5|_!w z6yW+P?#SE&U)-r-2QS&mVW5VR&vTvJjl3P{gH943 zU}xonpW}*4V0BzLzEVg$hCJMpS+I8TFA0)bK5p-5WjY_=%Q*W!#7udWX<$2IM=FAT z9QpMnuJnmK)rH-8+H8Q6G&Etx8)H_| z=+&N>G~!MZVd=jJ#sGbw5#!(I6GnPxnCVuE;H$XC@k{KE@`N?%O`&W#25RT^g~xen zP~IXKz){eNePZyfO3=nlzUT34lE9H%jwFxuaUvo)qob^3>GCk8D( z8}`l-<7jq7(Mc>Um&_6%6{dGav&qbdUoeV5X5;ri%xbdcZRERLp(g8jLSB1-CkIem z_w!@{eviXHR2bpO+P8Qz8_Q%Y&%eo&iZD+~Q0_$;zQmKCZNQj^@)=HISO)H1EcgD4 zC-VcV4~x@%_u`omr#^8H`su+oHomp`&{H>z zyGS;Rh#Pgq3>#uJ1!aL8An|qd(TE0FNjc%g&|8^3=E@x=|4NMQv!tDQ{F&QvF63ud zXr#rKvDehB6!^1u+Dy&2 z+Lks~rjyLH=2bFYHhqFCjW75(IQ&?p`^01HE=|aKlu1j$B}E5_!DL*rnt zM%LLr{f&~%6Ii=`$N;G&M>r}VLqv?Ceaxk7jTuxambRER<)^2IRL##;=mM`oZk>yB zaR=C#`_FOG&2=e@AUj)B=+E!LKQSYuArAABeVl&@ta`VJoU^SWR%VofzXx`#Y5@^& zbSP}APB--(x~8a z$6)5dFf+gRxnMt^@9X#d zX{S)``Qy;Ck9z4l(a3V}6a-{^;tP8bAHMu1OTPUTON0PR>aqPcmNqOWqtsyizzvq< z;&?WS6=f#&{T%zgUW+ool7C`MHXXm=|Kau!F9&T4BxO6eS&%(wbSYTH$8ZXP_8+Zd z8ZZp(v;rWE172p&0U&gZdf4!c(PBDSAi>1vDS}^_q)~5h3G6|=;h|{eD9?Je%B%7{ z%}~z#8zFeUo0r5hQ^0@cq*38|&k0CgXyMd8J?>tN!m{?P(e(VYAr*4{(FoLYxHj`5 zJ@=p9B5`Jz!Az+LJV^>(k2)I>s758n#4H8&bAZ@k*Bx z8Q*_|S9qxYl>edcJ`_2}{4hNbqyrtvtF&{M#)A? zy`6P2^~&AKIv2q>9n`y)OF5*zBm2+|KX-e2$9T#HMkC@@Ydh27WfDqs&5#^G6sMri z9^}+wp@AY%bT2uo6+l>c!-^K_f0A_6rKZ zCCgB}viCEzZoSwSQod5&aTFZw%Dc{W@7{Gj0w%#e=Q_-g@tRFR7NlB6-z=f_B6^eID)L=}|B6EmUscML9jN1E!l3%AKvFgBT7%i?DEEPy@iAU8`(_R>##cXph4v;a2H$Qj%iiFpYOeL65!ij3|v`{`bTk`?sz z`fU7S7Bi9NOf8O|&IQd6C1i7-^sYkF0>k9zfr zLK&kx4M@JHE-Uw^!!u2@H=zFys#~Y%BBH+?m)e@fNpaVcYH< zji`6Zg?Sw@uv9A}xhFc6&CI1-jF>9-M0{g+P=#7oUShEoDgJ#x|B_u&wN`Q@H~x~w zt!;A7+t~?52VpFHtrXFII0&D7(^8IPM2pV^tem^t zK(JTwDdy#fnm~&ihuQT)Fu!Pl0Rsnf5JwQzLn8>7bnu@_Y$DZI=1E!;jl!!tCd3WO*>uDU!iVNer;tp9TX(D`h<~m0;^OjgA3x`%mDT7zZrD5P#$?FP(t{ zuVKt^kc^&qp?WF!E271o{wwk9w1x0S_Q5`^7gK{PQ9raUKZU(~=Px0{vHn|dQGlyq zVFaw-5zx0v4^B z56EK~7g45%rG0ukQ=bLas(31&fbmxeI+>S(&C`pIqDC!UiX>`vNZ@09CUVo?di?=h z=ihf&@+Atr-ZbcwMdHo?MWrzg<`B(@^Ur=2_R;x&Y`X@dqZ)IGC~-$vQJ>t-Vw)oG zP61mm2hX(&*V&089$&g}>7q>(mt4*ANxXrBon=#sqXZcC?crp8EqJg}9LvF!Q;OVH ztda6Xw1g+uzwWa{A|D9wkE*Eg=V=tjU#aaK%cJ2*^%jiOPY>JgHVC6JBeTk^Wb1`7 z@{zY?%iaURSb6KLymg;omA5{Zw|*u(J*ie8*oNo( zMM8WoP?vJnz*#~o$ z+xE!!#4LyIX&T@BjGUi=vBnCdB>^%Z5)7M(O}lM+uel|^sR?$&_~uD&*F6g*=0sBv ziT$N+=vyyBz1AJqFVv&GxT{#+n)03FKYS~H2>oR?aJ8*KnB4H6ye>En+U{JgJGD_e z^g9|;9aVP2@4UX*zTGy;bHm?!eY-8zV*uL+3pR8^N7(;W_*))hweTtr76-Cj_ANEq z{P2>}8Fbw#+kdas3?GdV_u;QoR?$4H(fInqIk<{dX=wNOhAYEbRH;a`huJ>o6zv)X3}v`!ae`&V8z z_g9|pj;G1hxjl{Naj8s|a&+2cGK zd5u(pV@O`>vg5j~>@Sj1$<^3+>1q1X&Z#zrMx_BM^t9!MbqmUdvSs z&vg^q@@Ss%qB(Mui>YHa`jQ!Vz=DONyx$=TVTcot_Lv(%BA%3Tz%!LFI@?i&J>Lb> zGgo;gEg)9fb3(zZRkQhQ_z)hUF(Sdj_Dp^&{1)qhZ=qN>CTf;vBUm%@y_w+YDuTUw zswdkq5=?X7NKXr}SQ3WU!%}alhkug=$5QHeVbpjvj`FgV(!!_kW5CHYa-q&ERMB%y zxX<-qjyMl~8?*3j)kGkzExZ+bM~3fSt>uUEx--x$!v6l?jjK7lc{p1)VQI9-5c3=9 zJg8Qa`L~B;Pa2ky3r)v2*@17xy(f1qgD$DSbH$I2mfxBW0(F+B6~g}B|9)@E=D14E z1^<%jUVD!&qx_4T?WP4P;DlH_eZuHu`3m!cDSS$1g!kU|+#q~VVQq(s!$>3V49aosd?u5`+yr=ne7>}_WJvN zMe1C%CkEPXDk<;VSx0jkDP0O!n4MiqA?wW!^4EK3kaDW!P@Xcm9VGC!cG~8u;lH95TRpfJ6sZa~tX4t=EZt^!Nq#TU znN{AYzp{w8#=LX|N;wK0Pp)CkN%@H4Wt||tOfP;6e>=P`>QQo37d-5U96*Ihfl9E^C7`(sfuq9df^1e%t=E(Ce#U&GXZIl9y?uig9Lx}DH8v6>Q zaNVi*alezwA^ZmV*8EXr9|D7@K|TnQJ_7P?3a8`|0jn=+Ts^QunhuB{6VZVudQrqehKd6Ktvj1dT1q939dlbWuqc3Pmfancj6YJ~Q#cDC+lv+-9@f@>4k>uaR2@ z2MHBQ!H?$tO(*{E!ZMSjqsx55@M(Ijh2U;kh3*&*(~kLt`n&PQu;`~hF; zF<40GI*t1zSSzesw#X#95!1_uO^&x#c2g^@9EO`n% z4n*cy)Gbtig8=#ozQY>#}6r3Ee&60cngY+R2@c`msu zoQ7PR!sw2qGG@wVcBi3EO7iy7m`4KRgYYuA~ zmy~OdY_V4?ULvEM=V0U{4Z6d6@k?n@nbNh{z6erRNi$HYfpM-Idu*RXU=5*jwI}PR zv=eKuKknvq_->J}d$5jox3}{;)XZc3Ks&>_PtUU1>-4qslxETw!|y_IH78<1i0S7j*l9Jrbh8W5dje5@+|*SaNNPNm4^E zA`C|Sq+?W*OQM-CnW-ep=Y4d{4l@}y5i!maIZg9icz(ZauiB&>u6u z^qy*OGcbVs}BN zqT7lmnI`6YPs-zUy z>1OcH;}_Tu%uPPYyl^=t5$!E$657rM@O>1DUn9m_CytQc{dF%Zzq@;oY9R06oi?CE z$nW;!{OrZs!0`#x3;aJ>@OS2jsqn^852q4Qvb4@N59R?~{73N0-}Wf$XXog=Q#urf zW8;}zrNpk9&}~9Qkx|fNZmk-Jua^eD+n=3@S@F<6Fi!_II`^yYmnD^p;vr^mjik6I z-jpNW4k~h^v0v>(oOApPZb6Tm!!|KZ_r zE(f0;vXFz1LJ7;xYCfX_ymUGpr_oQ_bj?X^I|ssz5gb}{9wMg-fFYv2<^UXHC2W+eQWOyqEaM-W?-`}J8YDI!}t z%-Y}U@40;lzHj4^dl+fPwGG;*vVq;F+WnjW&fv*WB0C6NgP!uiV(#@Ka#bZ651NvD z!Tyh2sj#72oa4d0(+UOvSR&HE_S#%&iQJPb^6;6^b{*k;M>2M;?kQWto}(OsWndp? z8Y7!Z#zeZ}gw|o5kUdXrpVrK7ZzA^T6m0f|^SVs7bD_*W%ot3bsFoI3Q@@Z3+Vr_9 z%;Pb(7)mTgmr^j~QcE>4L^Lmtf1BR%Met*!bzF^d8=AKvqQl@aG#L`W!oW>|)?{(2 z_Zu2@$hk{03c2?mMITVPya zEtJ@m`>PhfLIC~-u5xM`YCVn1LE1%6*w?|Df9WyGP@x0Q0?nyG zz+$RqjFgX{-HIOncrW-Sh~-onp6jvWNiqYjb#aocujE5tVGfTi(}^1q0iotb%i0Pw zmBQ2xia|ArPK@@*WQ44e6h%Ej{1&la%6daP<6?z;V5_NbmT@IPtJaEhaPE(YShJ#j zHuh(B&^VP`aVzjJEW8A{;^qD!d)nqxu79({0xpMWJX0#(i}qtb_T54G4rSc+@O;Se zboS3+LzT1-f&Ffw(nTd<@vtPM@j=QXI&sXPHYp!@PQ#BW-LsK>u&m=NhU&6B>chTmjolYtCyqPWt^`|W9qCWwCMNRI<`ju|P z1bj@}6XA7yumAg7N+3iN`AdkmE3}zTW#T;3aoRr+b&UDKQ>%8hBVM1z`1^EOL(%#* zGZ4LxIbwX&tqZGjZg|G!^mv9CnoY6|kI8{;rPIu1dK5X)UPEncpS3&*@$WR}z%@A! z2;o0evuEkJ-s`trcXt%tVT%lq`s;X_-T5KJ$z?jM+{3`k%@5B2Yf?UV)~3UAq!WK9dD^XfuK27p3N0lHISz|3Rx&OtuM>Al zlucre{C zk~z0n(&molmf)y)(gXY-ZGB(S?@~Da&CWI;R|>Uec2>p0tnS5z+Wyn{DhR zf*LSq%#$)L%cWGKCcyYK0kt1_$3uUFUuhopmBSxOl7aVoh?)Aq5_(owym^|U#{JL^ zTi>N9v>$r4+yb1heaRMe(VU#lDFUotEu5EDna;#hu5V_ldD?lYlF(nwlXA;w?Eq(* zuODJ%fg2UmnS@DJC(MxS@2X1NDGi#Ztrx884{wgA z*+H#0wC$>4H=JyQd<(WY^yrxc(y%hOl23DBxe9)c3Yu5OTEnC7Q-8<+`uO)K@1oEc zWOf;%w;c+fRc+*+as0z!f_}gxBlj}0ogh*IYtP{6>xOyg5wqlrQWM|YUHV#|N7GL7bXb2}{Z$Y+;~_6`Q84M~o(xULfR zWMRTk-=My~WZr%UEHHR3njux^*>h8Y*w;ci;uTkg&Y;5g1XE1?P;~r|ya@YW4ATs~ zhzOO>Jl@%kDAK`Oe_wwRv7RGux%4MHN8K{btimWT#3!smPmJOcREl$jXhjLZT;ASC z?$37g^U*#%TB>)DuYsgWBd|TvuOB1Ks$C|f;XT!8tyYXKlY5i+Xyg`4a?p6Ozt)oR zKIFmP$iIm8G}I^R!2itFlH>@^1dP=VfQ|~yhgJbAfjF*eTw&wwN<>+z1=eRlU_r0{ z*$N2JCm@*UccOiq#SE7EI5ZeF^S}>LgM2<#N3UOfTc4@8K*t@9wh-~oH3E%1 zDK82!`xD`1!}+*sum9T~&}-rDTN!PF6LuonuOx2`?mqK2?S-^w6{2T-%PYXV@SS7& zaJ)9XH-Y?C)kbmu^ZSAS_4|a|h!a(h0(YT>%)ry<_SVBLkR`r(?K}R%Vk_TdwvD;s zNQT~Zq;`^HuE-CvIM=M60*&|kVGd}TgKGrpFwL*5!r&Td8rj1r$&8lKw%mHVHDl@v< z0A!7^rSQ)B4ZCdm3rofvxO?ONqdp@sx~!aG_at#d2-qL!rLky(jpt-Nlv91P(owfuGjTOxZ2j1FybW*#{oXh^L+V8F{9sA@sat1u4fRelT4xS&oPn8U`1qN@ z>4>kTJr}XzyK;bWgO3%GMUVVWhr>g8ro~eVJd+Q)|9O6Cww_C&;3uUEfy6f-5-`@Xoz ztV1rgK`Z|M1^JgV#pc_HD}Knyu?Ll|G>putmYo<~TEmC9rx1bn%x#5Bg>1})@dSC- z!3m=4@mp>yTA;)9Dpks6>|y9^GVEVIsA{g}6v+9mXf{vn@#}9h?rrnFzNBg~fahn` z@{BT76P4So>xsCK=BpB3UH=?rvm^zx+=6Msx3w=KvWMahfOoswut6gnSobpg^K?%& z_MF@h_RkBZ2(Lc$-0*pagLWy-m;i6&O8HGsLBinq3k;<<6C4lSq`Jpl$eK^zoTs?V zOhH8ZiW4|v*^N=~!0Z6831kC!#;9KKj~q40MX7^4j==qxL1Y)MK@PBCIZbteiS35^ z6d+xoPr>sK>ohQhVgC=ZAJl(5N=zGoPC;3x$cJFLlKHGi8yKg&N8_^?Xs{~us@X{s z#a9E+@?hPZE4~hkWQKq-GDY#03YIS#-#s3!m0~cahSU;c1fqYcp`KdAuvIV=WwJ!F zgBc(BJ%W^5^JrMfBX;Rg1xB;E;-&#c&W(2iyaIK{ahB-zuOwhzg|8$hLsF8!Ov5A_S~A5CfE}IgjoRNW zO?Mu+Z=#@Teyu&41CNrLW}Ur^@0i!|DR9Vi>j`X`j-Bphv{f8zD(c-p>#e}K28Nk* z#*9eoH{S)qPV!WbdBeQRUT4-eAqQsQbT83zU}k|gX6k|a^f>`fZ2MyZWnqmdAf46GTtOmW98u-+PtZX@f|mc;GlLF)1cN z=Vo}XRMI+Ee4^iVlYl+p@0%)yYdk$nM-!5Km`kq2`Q0kyHQEMGV~flKrtm6}bty@R z0|PQiVmNV<(X6YG{7Ron=<_f&z&8goU%r?97wN1HRDJc{{9C=)TF8MF=V zM0S}7F4hzF|9l{aPlnzh6(u3Y&IY|A#c>XL4%KxsYfbG@;?okHn;>=qDBU`_J?(0X zgC7|)Dv`TcM9x^E#80Ix&g#$r^M+aT)*k=V+la~_B;`58?>{GH0t8VnQNfdIScxU69y>Voknw(En%bW+VVM(8N{36QGg87+zjn+rB?OEdLFr;D&nE8H{CGR~g zIrC0SJM#oQdjz;w%!cW=bi1q%f-etSqYU?$QM8vF_&qot1xvXFT%r$GjTY!{768-o z4dk{1zsQj&&h-6(u>Wgt7y}LGQ2m0y1Rw&g!GR&W{b=|ir@(a9235xDG^eouGPN&H4RUQIw8l7!zyS#=GTrWsIq2x6)U@2JFgxibmBQ%6PUa+W<~9 zAS2|61C{rZL<+y<5s(Xw{pkP9OtLYD$iU1*GpZw=TWIW5wfFHV#=9O~M`S_66lSC1*aO(+Q za#V(wnfA#-$_tmsQ@i>rj#%NV|7NjgrcoTm1`avvnCSK{Xj@qVl|_#Zpw}5S&9U{# zIaj@v7O>ImnO=wMSH@k57ul#HL{vY^xA6Ry3+N)VsNnZ zrMLeXS51M==%Ux0wbr89>xRebq;FMJEVLYhI54;qvTToBbE|;m##y^GEyobETT{*ceUJJa_Bxl z@`X6q)N?&q^+oft(C#R|-xm_wHCy~s7}$j_se@n0_9%(7{oVUs8)Dy-S?Xdh*oN3Q zmFIy6F$t8ZWJTs#SqS zPv+><-Q)5kA3(EGK(i_opLZ@BQ(dBIq#DLk4o%Ani>6^k{qQr$ztYlYp!yhd2G0O} zESvEr)Lp+ylH*0PC82J#x3pCAzvk4d>h(aT{=dzshnW5{fu%>SJ)rfhL{=cIJ+Abw zvS{|8tvsM4&Cw_NRsB`jDDHnhk0)on3& zn56h$Wym#@z^_`{yf&`P0vku&<1{9Y@ODSCe5{H;zcwE1`8sbzIqA`;Ms(0TX&Qn4 zKl8&7dmgo_le=r`KKQ}u3=<~_lNc?@Ph!n;$cU&E>|maS45&o;1&Ua}l7q==G7`%& zEW2j0WG{FiBC)h!`MFh1o<+$;85pZ3KcM^@WyK7ZRHBriP+hQj!7kud%f-?BXs-CQ}5j5(mp3 znCCwa`BQNODA=~UuGOLk=Pcg1=>5BKtEq*J?Ns`@5VfDl<2Qw5PsqO`NSYH+{~l!1 zrPtARf-%31sfqSyb+NsPmEaUNyFztFvh?iPaBy(-AjgS(@xnHhH0ktdt6k zmw>nr`JWDFwu9|=Ns^26@3n*pl`5p$$g#{n64egX_l zrXIC&Zr{LPwC;O4LmJwvPh*~=h*M^u-KNp@dj;DnVxE(W_Lq!eMA4%Vl=EZMq!k6c z3Apd`gY@plLMHGig#2FQ@h$Ij6k`4!Vi&d|TSX$jf^T4%bBxtoV>-3RLUq^Ql|cRv zs@Q?EAF!IU(KLT7mULd|3oC`qWehMxsr;{T*6Kmz+*y6gD+rG*B53Ke+kaESfXkWi zikkAit$AMxj}48+8!tJ{b1RSrSp+O@uc$^;n-dK>S-Pp zXB4h36puMI*i*8)$aCy&8Mco&lZ5J$kpCet*y7#72OVMmpThWtbs_(nAhnFDxoUoC z$#v|H#T6a4gFT#L4w?V zPdiBN6!bGXQ=KS;{C(iTTzp51JAVpv(ipl3NhB(6hiGfPVlKUz&C_AoKi5?a5 zzk@pJl2{kwKV4BmKEE42ltS!35=`QYY8E1Q$ksYKcaIHh)xZOW78)7Y#`K&;EV_%G zya4uenop)${!PwchG1SmdGZ78n9J$Q`zjo#B~xq2KL^ZmvG}by_z7k@4&=IG&(R|k z%cw-%IUON??%*ug=lR@E;J*Y*99k9ZHz75Cbq+pi=a#3beew4SLKL+B5)Wb0&PsF3 zP-oLorlL$n$w#5OwUaZKnB|^=@ADwO%I1(i0G70&c6nmJE|tM^Lfhz3tXCMr{@l<| z`?(f?e0Hj8@EeO3|0_{b6}iP=qwRIX*5G%WasGp{R*&zgj;H-QZP>qXz~@vi8}b<` zT;O}H;%RoMTrTyi(Q-RpyP;%s2=*4p$~%fkMNcH6h!x1!g4_xIRRbaaGl4a==Gr;p z$$kg^cOa`h18X*2Kh|&M%#%a@3j>oLuI8V$b$_KVz0W~MEayxjM6Zo~xCtn4_^OO6 z`8D%?^3b-|Y{podk617)#pCAW-y@p|N#eQd{=r)#`i5ZY8`7p zIjbmP_c2OEt>R7Q74{AG6!RTZt9Y9^&aPwbD6cb;au@SE24kR!fsWC3*S&hA7f&-* z<)tmcL%y&=f6)LJ4=KlMFN#3`pVz{r!2 zX|w^&nHanKTfX5KtXzmr7N=AXd(8?U5nc;y;}~A|-sbVqz!{t$Q3Y1`OmRX8@y5go zRNxsEjWGCih)MobinB%tza6jiz_K#p3Gm$^Hw2bdK=>RA)AOOTn__prgE49ixPWMm zNnjAB(6Q6KKIH%XU~E&C=ou&#-k=Obe=I{5S!zY;;0~jIbxUP!#=XDgl6cf$SrK;< zb!g~p<*gjvCpGN<5VLv(@6p7cGrG4ud{HtJbwkL1ACPo;oN9N-zixm@rgn05i=x5I z#rSSBs^*YC7%;ZDA69^gDCD0H2J0-*HBiugQL>Vdf3Cc}bKs+^1)OPbIi5+JOrN!C zUC2LCe%6fxdilF3q}V1kXL4nU8wT>Y+2Z+dtUF6glZd$W3qww~xPp03WUe%oRmE^KA0g@8gNWXtxM?C6pCvpj~ch}ebMgHzzOGO+#hCE53 zkpDL3_a+x@%`-8>5BUvf0Sivj?R+WZck~m{b`mTesju?1Z`t4jA>xdanVhL9dmKD4^!@cdH=-hl*bh6esVSDjnBpQ08RCxv-g!@P zkuC-DqNIq)!6X_*pU$Mym~w6B4$PQgv0wL(Z%uA`?~BlMI==fBQBcq_7QYW&UhVl( zp4UA5+j>jL|HA<7S+Dkg$7|c&JQ2?G)H=Q|_}$g-_+Ri-(bBC?0V{X+(Z_|+SFgtN zC6*w39Pe@FlyW>nEO^HY!J2!Z^l7e%%M@nuMI2@d(DZ35Jpsn$Fi$d64PSsEAnbn- zvAucVN(uR22!4$DbUt)wQjrJG`gNmus;c=4uLu}L1F!R$b#7ZXWfl06OgQU}1h%fQ z^$j5Wrt)7)F4q^*bl1m{tLtadRKo8Y=UszBf_w!kUOmd#%(V95mQjOxb;XFr_ z@CW(+Ka)xd5<5cvy&+C2F>a?d2}@atC3bhLTg~t7*e1`b_C7dUoE5rfd(M+>&msRc z__axL^}_CNzvELn>gDUTuaDeKztf=Hs!3*4H+@zb?RI8}-PUzMDnqZl9JnA=V0j+w z$}X@g|FG$uZ;j*0otUlPTvLl0<0$%s5)D>tWZ z+5z9gPhfnkx8J_9QojG*n`yA#&ENFg&B#sk&cMLp*YG(TO!%Dw{XA2giLbSXRLF1k zCDz7?CNF^V+;g8(o#hERpuE5Q&TN`M=RSW%XeNXf3dG6`n@v6 zJHb7;+Qh-#0_80x#F__CoV{ZQ@OWwe; z0mX^(GnA<)b=lxDF{#NLC{C1I6w`iuV{m)Q9LBC{`R(RQ+t40e?M1cm?er}_7{Ck< z%g+WQT{H$}HgW~fGpXErL5keJ78dmq*KAQ0yw}!BhTGcF0V1~(LH@FtU=WQ=dG!iK z$P@9}K;M5#uuKjzn6DfVF#fqpV38_w1^r9I72~O;^^5C~@UNN}qep#t-1rHeMdPDA zN#mz@#|RINAK|GRpXX&MSNZyBx73@o|6MZL;^?&R!p*;ot>!{UtJ;{9K zX4@uhC*=lb1d4W`=Tkl?`mE4Z2Iy0pQn)KrZUX0pr$VbvjD|lFtu^Z4(gjnqEF`9|O5Z}E9 zjt7Imr!dfwS`W+tm9W?ShkM?E^osWC+zP$|viTi}jyD_fRDY zuLC_gT0VjvzCKa7PnPf-e|y3b@t=EVslCw-dD(QYvzc9yTY=)7yb}q5SePa^|ee(i1~#Tgd$>{Zqg<3U}c!KL4~SunoRElqZ6TU7gWZhf;F3_JbiAbc}f%}Jaq z9(?ChuKAz6rD=N3w(OG1y^uQtw!gn|o$-sotYH_jUhY}WOj`x(Gc&0`NC&&+glv3i z#D7k4lT7$EbUhcM}XaA}9mzqdwP1eGitz{;~!Y{A%WVKwxRT9D4cF?G8 zHuj#;R!Q|>(0hE5&C}Bezt6H-l#-_FeJ;z*OfyN5rrqsxAZ>!k^#TTY z$^emp97=9O3)z=0MuxV+`!u)j(YL07Lo!{gyOnu(hB@nC(7zD(KNFvXR)7Ds$?mMC zpnq}LdYA>@0^>~)GvVROk^RW6_+Aae-wg43ZLHOZdwB+wE|LzLh4Ubva5&~j{9g0k zZprAH4=fAY5aFxRs~VF9CC@eu`E%W?^_?DAYf)PUCqGIwJ+gBN>sf%d(I}NlYBGya zom+ur&_6MRH(jzt%S>UXQZ22DQ;z#w{tEx|4M>*Pd%V}ZMfK$^*$S}DVaOXJXvHna z2NxYh?tBW3#Vp29rA zjyW6y2~#I^ORJn3WB}-v>M`D#2ZDYsz@!<3#oRqlauy=3!Cf?k%JFvYl+D*Y#ywlC z?T6;I@stqr%5;3I=9^A#6lD9m0V>&xZj3Zc#Rvw>&?d|mK0Q6}VCQL0F)p{~#&1;J zW}Np1a&?R{sDzJ^V*~ooGgN27Xl6JO4?U}Ae9x^75uzY5+!)LQDut2w#a;AkdIw*C zT1Io^eZ7Id730@4)8(!2htCiK+Y1xrJ;=W+|K?u->Nkj%_j!l+eG&MmP%G~_GrZ?? zz=^YPJ>YxhZ<2%z*e$EnVr@M$r-P>A0!AIM&8l6@0) zoH1ybOh^!7tM~{S#g_^kZbG1eGne6p%fiwm&G#5J-5-f)1J+ zbb|QRz!(?b{xNbMePq@PB&`l{SyUoS5V!T4+853H3Hg>#`*_YDHoYz|<8737rvnPe^~ zD~+$DGe0Z0R5GKL{VBK+wSe(z@F78cC=t=eGlMZrOmgHAk`5cr-gFw1+7a0twZFph zm<4k%A#yK8_C+<$T09F;8dLcv>_3CIAn4x~c==|e>=&mtQeL3jgBELD+hL{xK z4;r($_!hDUno)MxKQ?F<%q_sfHZlzfZp_dHl5B3F+<LW zEG5ZuMVpNHtR$8wz@;K;)MS-fO+qU0^?@hSgXIns9oEG^5BaQE?zuL`O41B32K~Dw zC!|?fyKJ$5&ECCwM5mQ&<#S=NC;}ce{zi|+G#lwcftP9*&4f=yx*M1;@Ce=UI zo|ZGc4l?*g%L^Zeg^aEQAfH7|=- zHN}pyzF>MLEV_n} zKQ=^vuSM(?W7x{k8Mf79Xi@g6^g;ire&|6|*P&QnhBD$CWL>AdpZ0W$+y!p%Q}mxZ zN?Ge|3@GX=(AuNngL(`(%!06gZbe`DO|QCnt6AgLHV6IXlA)=TD?#he5?}6*6bx>H zdr=K)NB>NY+Hop4RTEf)+k*bY!2Eb!%PHH5&e`0gx@p{;`bdm5_g$^E7=VX*CS-82 z?gB9qc`ri#w4kAB@p6MZVi>#Eg?S2aX|ilQF)`$SB^dO-0v^G$ilOoUg*IS#`r_(H z#xtB@pMKvZWS=+`+H5DVzN=sndH^%FRcBWv&z zzy=ZEQmMxcqv=XAE`WNv+;8aJX;g8aOK}9>wCz1#I7;U^#w89Tf2i&q^nVgy(b7pu z&_8+b7?)m85k%SJna=S%2ab#J4rcN%V2zEaC*wZ%9+72)SX+SK`3Kt81^s;ke?tE( zko)KB{eN7rrRt9hG>F`w`(W8^2>P4)!MCM+ZGm!lFWO`ODBnSa0?`t>x_`;fMWRwY z&A9exAOvP7jYoV8_$A>TAd!=R4?(1E@A-!Y{r?Wlz(F|1=Yjy34kHeK1}mcB2;wBNpj8D{qS7RzH zm!I#}zd1A$Rqi?DbLy3DlByM#!QNR$su34}5fWU%P7d65ODM{DMG)M*h~)}BS{Ppp z8^QC^I5XmOFXLT}g&ZrXx-yU}+yM(yL;w-q;-^79^t7)K`4A~YcCh04{+}4h=nV-`_w z!1oz8WB%f9XO#Ui8H(lphk|FJsi?H;0FCM~`8d3H(tl zmcPUPF(^u`4;&hbu^l98@-a#!$~5fDKuO1X9+oS>1yO-gib8!B3h0Z^!S-Fbb@{!_ zOJrH871*$43-Zyx(oJj8i8g@;DJn!s0!Uo>Kbo@^9hB0i+OeWeg`} zbTo?GKn0|WQM3(IaVl|ZkaS)?iM&4Gt@!t!SfU@zlD}e`#!mj>1(v*TLEbGCYKLmT z65pbjNz?47S0vhKf%FfY@t z4$&Jpf|MbwFt?VO2n^O{?PN_nJLO+eobz9ZRu<;n@qk^&(q#L#n`%1vMIL60PmxX~ zSIQUi&ICoLnK$rV33c-+*4cm=O{B+sNs&47vdo*$cm3#$(RSLP`K@cG4F76DD~~&$ zs#NFH*p3H+AXBUuG{J}W;Gl}^`6KW!SiXcM^=%d+J69aAtRB7rxdq1$CL_n8;81R8q?HF>koABZ|71F@lV_z*i%$0Rk6m#j2eZRenp4Brfw5W$`_G0IR@14z zz)-FwmMgJ1$w;7WjiLsA2+9z1rRu7g$=?E0T~eKP(qY?A-AoD#7O4~~hk_gnHmSQn zbOh+U*>t=ZSr%ANkpr@W&k$c2#&k2O&$a2ni>_%fG}4U8tUC!~<1;tcSV(-K)@{3c zo+)Ux-T7**Jg;AZ2u~Wx!JdWHWXp8Q23M!X7`)eE6mJZ$Eh_F6%LziY5~KM20LgeD z=_04xT`n4RPVN~&@2-$?AoGa$6tKG_Puu%@=tJP8HdaW<4$}LqktFMO@8zDbs2YA_ zTfu2}zX#O%O72Ha7ts9T->@w1u&wB(xM^L0sVL&xp;c&KioK+DlO((O0n@WKV|SI5 zD(C`{^lag;^Ugr0^IcY4OyX``WhSfKMV4p52~abp3N`kUO>-G%n{X}p+HJPnZY5$G z;=G0=CZHFY8475l6ajb5|G-V9OBWzMnlUkNfTH1`XSXPtbpgGPH@{^2y@PYCtH9Oj zN~F|Q8Zn`ixj|KX6hb4n+M*Z0!UInq+pTUg`dH(xc`ts|hy<2|fpASv8`_e?$ygf%qF(9Sg+A28Lu9hc;4oJasXc zCi}>*e`lWquW$x@bu^kk%5y)D_!8u>Ig!pz@ofy#Q?qJTeVxuz6)_C&1&s7%0mJ^hWX3 z{ux|}q#|3n-#YU6nXq`;Lcdz_3G!grgaw$T0WTij$^kvGMeQx`>8d!=>sj`<-p>-n zt2Nc7mL>D{q)K;)!53*5lNx4_XA^mpYxH= z(UR`3-T=Q^z6teHy$s6|3$}1>>6m5GM8q@Zn~D;cER`2X2#mU)aVM_czvTXE7y6*G z5puL&)l#*D02{7GzS|;t1yUp>6DGf=dbjQFMRtmIs&?EiZ?}{Q-&3wLnP0#a(U4ng5Wu zh1br~_I_ZvB(bI!Y_~k+Js%lA=Cp^6$Va&IRRO#_s8@p;qtJl8k5jj-1Sd|R{rr+| zt2Hf46915RVF{v8AZsV(F_U)L2D-I*+T>-hr5n50X*ptJKsy1Jm#%N|ym_q=uz*?H zW&!K9gwr((I16qIKNEb{QpoK_t+q*}oZ7Vn#}S_r)cX`{gI&<{Zr4G30>|uZ&$=-xH*7@iWypXY_CFh>`&I7J zF~vNx7t8y$(S3PI^gAM!VS4*r>)BPqe^PHw@VO?bV1t(IECf*~=IVG~ zSH-w1r%r_Su(BVv>bwN7TIs+Iktr@i#JOVc1R)bW9Q;^Rm+&TGe9A=p|0JQ7FSY10 z*EvQ2xj^z(s-n*+o9?fQ0Z+;b#Cuthxr1q7re=zH{Ub$96w`bcI)WPPY6q$)&VU|C z=~p19y27)%o~>37Gufe)XgZ`8Lu1v$N93>YMkb28b=7r#B&>~>do|;g?xF>^N~uIdbf+jz#o;`21Y(f z*|kcFY+Hq166s?jKkqdd*u3|E@-%lY08@mr=^5MgOX_BJQjAZ_XmieEZh>s-chpQi z`b>f}0}&^tWP*EN^*eeEEphH@%T~0ph~|0dAseqMchhGC^Q)lTy;`;#o>wZ*QA-sO zTb$Ku;@j(_v;P=xHSCac`3_#!p>2uhe}*=ZAxhzXy8X%%Jhe?^h+=rDyu1;{+m5VQ zpxI03HY8oWyPZmAeT1*Va1aqEYWKUf7I`LK->Z&X&fgcm z-F6Us<^Pb_3i>Q@ojFP4lKzMsl-bBN$HJfbUieL$#=~5K#Tzm&D^Z1g?O`qKv5d|% z{vTeNu{=W@3>R>7xOrUUTl!{=PpgEibb*f$T#Mrj>PAh|LhgBR{?c9pokAPaMD2Bq zH;*qKGo8w%*06tmi0+H^(ik1s%=pLnn5MA5Ae57$c9X`~rlb6i{~u#-0v<(`whfd;bKrD25Ki(=hYX#J|9=hJvE?t}h2oeI8^pHP zc(NVk95^vP{z*gLLCM$#tn^4}#_#Q~M*IEkb6>!B&$Qe&@Am5Y#kSf+;3Qm|Zd+ia z=;u~4pn?A`>N>Ia*?OGI&Ql!yZ4$M7C$y7UA$;h#1>|c{!{ygCcipTZJ*82SbrbmBWq5 zR14-v=h^N;`NB|C?s0TRd7S9@^Fcd!)HfoJ3zqr|8ZvYqV-t$LPeYE#Q8`4gz5>kp zv!ebTg6K|?xf?C<&id|9S?}6PrE<5}v^Y}+`-4SrPQyCp>n)J}I%4E01CnbyFzCkz zXjzYtE3D^31Ate zM**G85W8JaGBJFt^q7>cRB;1hgf{tR`U%2J200QX4NJ z=WrWo;kL5gWPBBKkW0X{GZJFMGzZpEg^nV-hv+EsyP?rLN$(T!cL29FUG5kfy@%`N z)0Y6_H79*8tVooJirI@c;OSe!JK}Cuk9>Xzzrj_)r-0)E$5!Il^Jk+Y(ex{k$bBdV z^krQoPiAf9$vc~o#|Wk467q7kVVv?t%W5oti;@Jf{Yr~EHi7Z)sZPA>cPbS}q|9=dlz+oVGAnzbxlg313dmaFVI)10Km3Ynaj zH%45lr9}%a)O%q`G$5L4l53YMfifUv=@2XVetH$;VSXFQ>kG0O-zjT8DiDV%^I;t& zWf=crZb#007wkzHuG=7;&qhJ!cyN&B0e4v2T;|sg>Mny*pF3q{CZ7$RKChFoMP-Ar zn9Z=`MEaR2{3N#EJJ@aPA2HUUO4KYo<+IWL0|Xg*OyG#}3=o}B9xN_M^BD2q=~IuW zz&?lCD}p#)?O`gXhCVLH?$ls(>K>jaVGp8^X|K381K})0D#894&8I?p4&ox|3}g*x z_dE&9MuCOveHw4xw1(z2cw$()ixZjNC)u0O!#Urb=~G1xekAQ~myPXxGL{?E^v%T{ zu-vfQ%|>}kKab z#=Bck-hYKBTzXcpa$HGr{Ye)>XQ+q|6h)8KGFHVyWBJT&H6f={h z*x3SbWfR8b$>LDfEgIl13oLnZ>5$1MrZY1_|8k(+w-0FGH<>O^f>)l}74+cDqxI1^ z;L&0d`T;LL8rF#iec70K4i3}#j0;kx7QI~9Un(*;Oqa(D+Gszqk$ilUHn5C>8|5_g zT3X*9UW(48tgs&zzl`s{m=msCRrwF}Pse7x=-B;P4cMbUSzS3)S=jpLd4+o(tNim^ zy!nM|DlJsMdWi?$vk8%VT#Lh-(v@e)wZv^Qzz&?yQs^}R%cX7M<MZr=|!X+%`ZJTjmF3$u>oT@KKwiRrQ*7}A6`BaT^uV@&>C zc(QgWW!KqIN3T}giJ6zS*)xb^s7A&j-pVxDVJ(Xk7T~LJ4`nqixbm-u0sh`H1#Jbc zYUF~mi-sfFq8IfT0> zkm5A07b(N%*-&*)wn#JKp|2V-hY!&E-#2_*e6r?AaK5dod~!CAxBGWQ=KNhrfft?8 z>ss}jV>Ttdl>G8m$pKkN*H$DJ>;VUO->0z!FXg{PH9vT94(Gqiyp$#XW9S>Kvv&R0 zf~d!l4ba!Jke{BhKmJYJYq|NlKtX%{R)@E+tzdJ0t7B7P3;)_9>HJHMZ7=u=z0JPQ zdo`L;=#)9oy3U4yTF1Te@;3uJD|g|Z8Dsvo08lPPTu#{8N9d*N8lUJYpvI_vNwZQ`TH+M^inx2A`0d7mRytKadXv z?b|A{0#AdRiXF$__ zN4nVRPN?QFgYoh$$j}nMDGpg99gx({|7hAe%}?igCQ#U(?5EM9+Z6|% zdOdJA)4_X5ujBiDyti1DO1G#ZrI4@|n2ddh&F|T%AuUhyNQY&E*dtzqA1F)zf z!<(2Rk(~IGODARqE62Z4VGTSreqY77V5}Mbv%h@^j`1-;v$V~>1X)3tNy*af$P7Wz z!uv3K&^0aa!tp*9y6UTlmqi>!rphQiJ?kcq({t7d57<@fsIF&{P^h*e`hmOKzE zZBZtWX?9&ua@#Q?oejNsNe_08rbFN}nxAsp!?DQGTmn#lvVQG!S8@L6y z?HtiyBdvE8Q*Ml=hyZNT1m&wt2kDPshs- z^v_DC$bm@cVfdsdH-04a&xqaGQ~|G_=CM?YhPoGwR`iPpMm|z9md?ZWR64Hva4#Wn zaxg7pz&jErUSl579s}duE`xQV{7%^JoFZj_d4!HH4e8lVrnNv?GGgH?z|thbo=xog z4gLbmD0injo0*rG*B(q~HX-gDqZi|)ckmSMKoAV_*VN;AxYRjR30uCYT;^Fi4sjTV zrh|u(X>Uy5X2$tmGB%9oy(m$eBL~(bVu8h~@U|uUz!z|S-x&Jl1hBzR+}IUmu_rl~ zg0*I##3ZI<+|nF6@>>lwJDvKKlAND{8^IG3qmBmuRz89pYRE$!m{(I%XQvwEoxnB6 z`IcDOTj_gyOO#`0r(T@;ymu%}i6gamDan01$avZ2X+HWU#zdI5bI?JI za;3s}r^##4#}1tvT6Y85{8RX4z-5W&Z&4;VW5pHuG$Y7wA~U3W)Lig+vJ-k>X<(V# z=-=rQd=2?*fZ{HvOE$#Oqg`SBU4oc(>gh0m@gYHqnf~p*F+k^I-cXtP`TUJtb(E){ ziNXHwyOCQ@ejD){=jv$xf2bFhMD$k&z5$Hm;PS|jUA-CRr={wV>kG=~J{LHRcDvGi zmAEp8{DqWxPUX`HzobksWtbn$ejs?xZIGK3gKcNsld#X-D@_|YpMbgX86V|^A0C(t zeTD}=Vi?g`DnR)t~1^i-smiEo-S5A1_Vwv29=A4PFRNlm8HA@os!!1KwpJ5CRkB9TCBARM$EALA*1S zUlW{tFXNr9NBI@XER-oIyI5>{5xGZE=-9Dn?mBTzO`jfYJCV>E!zTZAc!ng&VUCeg z2bg9Hxa{z4v@i}>#p3aGNHKEU0A+3&t@e@Q;U|>|j&ek{(AdQz%B#XUaTGM{R|)6( zRC(1weX=E>Ped${ z=Lwi*Ej)CPoGcSz@8QJ`A1CesR$k(Dq886V`*@$q*hadx;JnQqdfy3iDWCKaj~yDk0Cw|uI+1K!`;qSv1V4a{@h z0v^^6l1bYTGlhLD=Gs(vNILo)hWGno60FB4L&L9?X-;Z$G&@vDQ7beeljBLd*zX3{QH08W zb&b;-?=#=-&uO0HV+1;{WaG=Y9bf1pxX*(@GGXsh%JnrKOrE4b3Brz#-r9zDw$p)l zJ4dys8L=@wenLaM&x3;(OB4F(C165Xv`2?SEBC?Ue9v*(hkh#8i2@>fj{)ICIcM|1 zsa6g|ApKf7#PGpQ?gOLP)R{}JwE!LOqcQ-pJY}RKW7!NYRIVNJo%&`swWzR7dl^1 z3P@aEKK#y5c@ejPjKnD@usU2Rp}q#K7_*7`#z;Pq-RtR*hL^V~`AvwJM6R!!kcTQ} zo0hVI!OBbwz>#cO{s4|*zf(Re*#nfiely>id3p;*uP=Toi@mew*$1yXVsjJZpsRCF z^*dd5KQcS}M@h^#GpmxmF|;|s=1gSEdYWa0`q;>3o4gDhDp<3Z$)ncSyK?S@#uI}Y zktyfde)mu1@lRl#Y5>^*i@U*1vOn#D>Kuw(*GP}$aKYrhNHLLjt&2*^7u4@lJ9P4Yon0osvaZ3!`Eu_?4JKdT z4064lTz&!gX_I^-d7k<2-)-uzLT1VT*me}#sz#1t{>S$Jo<-N5BN}E4*{bf(WNu+z z{H5MMVyzZ|=i5mm8Bn+GBkP$N;0*g(+6nA<1^U&D;i^*xFCF#&1uUb}M|BnaF5ZRA zRR!RjdL?YIJ&P~02uGCwr9h871cVeKGS@N4^q2+iKLh6a4+acd`p!Zgg1xUD+;c=u zTSwpF99X~a?3v%BJ!zt17etCF1-XoFq>-fG**5IYv>cixegb^e*JS0i(=&=Ud zCl0LFda#I!$dS?dP&p0YZzKXjx`M<}wDi2rVTleGI3gRja;958aR#RI0 zcK1KJb6iFK|9JIh=Ynbk{k(mwrt* z$i0YDYyobR_NW&;^g5jSt4w~%Be`jNJ>`jn9MIPvlbVoS=sELdg^@Nwo7G5cQKG`C zIf%gST5M=zdb!xomk_%va0<+>ayM=N!G612gUrN~7u+B(={K}2R_|8ToP%r@MX=gr z;o{TjcDLSVlhZGLluBFa*ZpjPp@j*OEM1eX&ETCVA0EiYyO|oG>+cUtlI-qj^56RL z=3%3<*X4uL82M*nihX8e5VOh31w>W!u`vcOnCkIcroX}QNADsV8KBt&dmU=GvQ64H zyL+O%X~57{=c8*I2lSHRb@1Q$X+OFhcU(|s$f94=+AIHg7u+?Z6mRU>`=&i)5zTiu zNT2qJ{~b?R{Ry1s+CC z*|K}UEVBu5eNV)U?`oj_8~99U$b@+{^JcHc{G#1Cd(L|_lg1`Z z3%}V1Za&(JHGx^xv(#)Poct{AST`8Jy?r`VCn5WensdpB>^pP(s*ekKvR%lla1~5$ z`-iF|wk<}s40!O}()Tt)t&eJIX9lK7{>3zpeK;&RC&**_H>e&!KA2y9$_3n+{8~6h z{E7Y~T=arZG7_pADiduZ^2e5!G$iRO4XJp7 zCuOvtAJJtw%4h$I;sGx(g#7#NC>HQ^6R?^O^2C?TlXLfh7k53yY1144#}J==CiKKP z)1f~EsLY}O`?F4bPNYc0QBnrbZ6vE!(K+At6}uL~Ygr_EXBDsXz)Hc-H2R*vetydL zx(i47NsAQ?T9_pK5X4q;=$ryBSG~Ixk!DS0-jRH+6w8;qDi`zcP0t$LX(RbVO;TR2 z-hK14+920M$hBjkrEB*0Cf*sfPBhJGaT)LPj%1Ie^*n>RuN_N&fBt{`rkFuqY;jq{ zG_?F?l^51@fL=WY^32?2H@jc0FnygKj9HfK2D=09!HDg*xNDZdV)eBtnB+Dt+gcHO z9Fihpl4EhytKhkYAr4304QX z*RwD#a8Gn^nLe;wT@%WGcSL0Myh_I6i{d?LKIa$E~#5}C*& z7f9b4j%g*QX$~Mpc7$`sdBo)|y`BH&Q$+N~;)tgtI%`~7$JkB5@mmAw>&Q6o&FSNj z4d%Y^_%>o2*D?pXmerBo`t_-C$U@I1uwC1fH4gajI9%01m*+*r!YQ6*xP=n6lyIYz4JFqr}47)fAf|;P|pgr~-CC`?$}+ zAV#x>EORCMDa(NpFL2~+k(DbW9ugyK z!r0pKIqnvDv`XG2qruu0OO7dEghhULnp?}fn9jf~SoatMm4gax;h)HzJ?emXRZ4apdms6V6N69t#TtJ>M?8fHseWUJFAvcK|Ia?+<^6 z{c+&yq5ETnr_}u~;(n;TsW$us_QogJ)xDmPyImW$HnR`Gimv9v`>*B8-G| z2V7(cLv>GLQ49$J=B&eD!zhz?d77#%u=Y&rKG>H4UFN=Do{Q=-riAN)jU!v=2t6l^ zs~q--9(Yb{&3VwruFd4RSf4Gz7Q!&N618^O75X-tQA;B7J=3SD9l77EFuRLBPmKJ; z;OMPrUEyvVm6VXG9<^}fsFX0VcwpazeHeZt`VOYbbB7sVM(4wB#>fw=+p2M9a>8i! z%!-jSL&N_)^UIMl3x+vY>wbD(<=|;NYf3_fdd}q8X7!DKGi+`4i2wIijAr^Iv=!Un zFOv60hz0$be6FOJw9!6b;IPHBosf*8027c=6YBiG{`uJb>JcOlHQW z%+@m@dr#(yyH~_WY0Y_Hy0qjl0Xwv&+GfGWO!^fpnIsnyEHXCCp3O{JSt%-fDlqJv zwzYA5)$CV@4y;KlD=TXf``#g|D`x^37`tv&rS|oh7QR&jhQtMw7h2v8iNDmpMTt8+ zSFSKVp~Q7++9ya1vY}JV3H3FN2QzA&Q}6vNdPTv|hhR-M?9_?BQgV&q#l&Me*nXOk7moqzGcQ$w`BOk$ooh{&?ISBNu=%s-q$nnFMe4myh3G!3B`}BCY_LFAU8E z;2>oRU&346=|Zkej8!RC9yMJUxKAu7?*%qE*+qMcw<`bSLYJp1?`!jdLS*%{ ziU(bYHy?mLjwm)hFm-hzJh+*%chKerS_F6_&w`|&3umMRR=FBsY0yihV2QAq1lKdL zG}pOOeN1sHEQ!373f&0S7W51?BNc4dNB$hO6(_)+Y%dujXMV;gj zV&u{RM${o6fJW}a9u_`+ooY9> z!}wK=ThX_u?LAYTI>=bo)UT{lTy|elb$?@XWe%R{#DGaf?X@BnAVHn;=+=J@#Lcb% zLnFnFVj0VT?X>~<9%(C#QX@@Bml@ap<~QJ}X+*ADeBzPSd#Vb+?AE@ z&Usfw0>`xYk=2jlrTNX;R_>K?r;aFg53nY{jfr#yHXKBj70T{E2~4nywfdvrCU)h@ zvEauxcTwBRXsNext4>EVTru`>Kh|dhK^`N&JwUAXagFu6>ot8D9N9coWQwfv?}kk( zCQ%;%JDL9m)Xx}Zi3T9+7{hN|B>&6c4dM>hEOBcUk>B?4TgxwNV!=P#6U#h{H$4^n ze?0K!wL11F0khEcgU7KZHD)6JAFZJq8Q_`1G@jdpEX2rMM1J~{ryUsG*F9tWJKT%M z6KUo6H{2wrG+=9l{0wJrao`=~V*I$*7&8t&mlPm7s*#bHqAsY7`Aq2L^AvS)t71Xi zOkbcSV^^v7;5fW13Y9M6|oH z$-G!BPGw;y|0>M3)ANc0*weuXsUm4%ta`7m-75DFm3`oD+}&tQO-Wr=|4#i0cuE$F z({QH;!{b!zrVjmNG47qpr;*UR$imX$_V{R9*deVL`>l=5=@p9Ix!pY$Gu4Qy|M92P0#0^>Os^OmHP6RWE`Zk}2QSZ^FK@t`ofWD6|$ST=}gs5jmdT0eU0K zPzx$O()_80T*gvH`S>#p*@%+#G4NKfw~U2ud=Gy2d=%~HWWrm>>zuL2x*NHH?|WhH z3$xciAFw#N%^T-#RM+`FGvWK}TDGMKqb_1-*Ml4!{-Jao^9qaH6HlslbQ@#20;13<983_bYv|(McauuX3Av@5L%{s^^V(k=7?T!I&oyj`+au< z(~<_n`n|4Muv6DNuhRk(?W=}8XnSKNkftox;H-soGL~kv*17$_`7ey~6M5{AL*S?A z<&PqasBwZNP+q0XaEwQ86n^r})Lv1ROzu~aCrGsx!Kz-a&`q#;Y&edaNe)Toz*eon0R)7Xn+ zTK0(4sFB|tW&{E60eRQ(^*lbzx8<3^2O{rMrolh{Yc(8OY!Ismc=7iD9e*psB<&RTa^EmFA&MP+$8&rN{wvGr!H4gG`^(C11t{di4?P7`3 zCjUE3r7G7a8glke8uB$t(}6MgI>*e@BgXo%%F)2r?W!GBy|b{nG6VT|A^)pLfyv+) zWq}dQkPE}`J{42nk%98!2pp_D)cc97H1hAlD=7j*V1&iUP=Q=Er0LLE*qkP=gMSRq zbQ0?{UyU9*6R`d?XA`X4JPXD}MjjO93YOVzL1L7bbL%UN?%4&gT0bh!`m!r_RDna~hr$;pIf%FD;Af`2L_fxY= zfuW1t!^*~iC)BKf>$TibWUFoF{Ki%r+HWn;u#80iBWifltx61fwyt*rd$5<&gQ7IJ zsv7fz9+(xy26J>R>^L2>(!q*J@%KYTBug*n^!vs2nCmrLO)jhaeh(ep%hT7IKdQQV z^8G4%*I#-KI__U?v^FE(5Gh3~M22HqoTy9tN?BirCk}N%U#Woax?kJ!3M{#mGRw~q z+r@Zkk&Di%wvqgx86K}VDrkeo zN%5Y}}zHyZo35Phb?1N%F4mpByq?Ty8@uOEnhd$d2n zpLqD`&Y{W;BDdKKnFgA}gi2Vt-s#ANd^J$XgEKPaa0Qsiv&5gx87{e7)6Q@8)-szi z;5TO4IMq_Dh0F;5F(KK7fn0n|G5$)RIzI2^W4UebRB>OWsy(9+*?pMl-}|vW2AN|C zW#HG#Jwt5UVTEsDoIroI(VTl!^3V7&!M_J+k{QnVmE6{sD>TOnfa-$3dLhX>6sQ%i z<wuRrKfsd7IMHXKwv+3vJxe)s@CsUk&c%mKP57cdb z6;H-&@dERGshe-pZGEOTL(WsZ(Da!o_Ko(S^56>+nMi#`Y~IuWlcx!GR`6Z4p2@-0 zl7KIjqV;2-PtL>}d){xLThNo^u!Z*Ia(^t{VnvQ9Y@s-(G#{;ZRL~;PC4*cdABaor zcLcIV>avd1RqXq0ACoy-%7oMbZ7q}As%`rq?fDAst8BGRpB_e*4kMpe8vKYPS@nmax(^F|YSJLpLABWPMH<(O2w&wM zTcU>RO`vgk%hhe`%qGEwU1`W zW8|SBn_n+KKOngD@|ppvYd?q?bPfr-I$bAVwX( zlP-pkmKkWq$I!} zf@jS`nSqjlZEw^f&&FNqH&TwMXOYRE_(x=dg?(rMz5P3-)-zhQ5yPWKm|l@hsotmD zQ`}s6orayr^p5$p&KVap&31vS>4#8JPpLm%oqK)=P3+P8BBAGj973!punrlAvk_S# zh)a|SO$TRX$(M)XS7}Jc*BmHlG~^(3u>B~zAE9$J%^w~KO+uTnCoNd(jA&=uF{A0M zQ{+Dk34Q^5o23e3$A{>9tjBpx2WVT-ta-=6Ij%(Xn>1%)b6z$y*P=9MJfus(MdTxj z;QT&x?njKqYM&F(Zl6c!|4+iSmr$Fpj^;P+sz9A4+!sL+Q4IK<_hV=#Jb&ZLfSXtl zWOpsJ5}{n-^H{NDu3j!vSPN~h&pqEG|8^m2D_lT*_UhVv_+r8iY$KVG&Uh45YqskTfi^`4XdgZ@=i}7-S?oN!zVCj4bSaL>=R-hr%p)aDe#-uhcx;X=9jb zCvz*K_F~IRM#CeRoV)!vc zBG{dgP<6zP=bss-NY6;@SlA{)c^b$W>4FtEirU!G1Qlas-P@ z-{rTDM#l)#fdUIJ=D?mne3j|ZT+zVBA$KaG74Y`ILBr2ri*pviW|u907|9Vo8pE_xUduIyLilzm54ZXrA@8nCTbS?Oeojh_^aRH8Oun&p>d(rC3p z@%zv-m#&?m{pF0lkuzwYkB*mmKg}vn<9b+mC$K6^3C++o7%=&?m=_s|{?{Uoz=mF} zlanJ&hqhGlWDUxJSvax0?We8&OAec?Wod!jNMaQ+W}(76`4IBFeCy0UI13vJ$9!btT0 zV68(;-{qYJi~WgFvNNGf{?zlG!t)g4ybcjk?5^)a(|)8{S1IC`85f&PE&D{D8c=Zk z2TrlxbVT8sf?WH!Hi}kF^OoSZJ~+005`ObRSw%=&#Z9NECM0Y{oTeJ@Sq99ITgM*x z5w&Qf^qq`6FJktc#V@eHsyakmK--3RJ~diT-$h#N0cm6`c}JOistj#1p{GX&YiP?M z#Y1Yl4$dsQB0Wgk3R#;W1(afKbk7mgn0|_`n|h*8a|Cbtb+Q61My+Ed(wA(cHmpb}1-v9)-(uCz*b`>9ZV;>0?eim3dIX)lE0R@> zUb#I|i~p}h7NWigESBE}>DulgsuPvTDeFj^uoV{i9wz>}ffxI5f4CRVW&OH$s^3+S zCy1uUoDz}fn@A5V(=tbP)(~lDO$2YrA|AwB@?5sBqa#ivbTVAF4?fDDEbIQeFKyjx zc&;}k7wnXXnO(3_&FzpG+<#SAup$62qrMDY2d^5jXAw__UcN+YjCi6o?i;C5@s#3f zr$bMvdu7jasB@J>QJV~K0YH&ibn-oj5g_)5P71GMR=CnM+mEYZwz_h%`MQCpm5(eH zcSN z>($vU7Hvz=x~D_0U8L{zUbPoQvUvI1A$t6li-I>AH%t})o#=6@y~h}sf_&A9He`8s zQc13If}E4N!A1`v_}CM<-i*}6eb0_6Z7%h7QB(&L-ZS4F8!!; zAH~~ivu!;cszuw>BQigV7^3g(m7&`ZUwjy?K=l)}J~B*D4JF%;yiW^QX^ z{24>d`{<}NeFPiy6vhw%GI|Ee3)MVXhEk7l}eI;lux zBFek?y%DWgeEl#nOT84`8XslIoQk#CNZHmKMz4(D``f zbFho&Er`47S$KIdGcMU>bW%NT>PftVsp%@diofc)1yRL%lC=}a=s%!c|IlRxgMsI! zTIj|a88OD_P1XQ^BE5Q?`mAv(BFl7gA@*ZVlOI!df@^0?^%!+8FZ%`ur7=7U%`}Y1QKfxzA z^5ij&CvRbSGnUi~1+JPA43WWag1(7-yd%F;&^NC{I$+PHUkVqX{wm}Sf&ADD?#soP zS0IzuB+o-c6-M51qS;TbdYn4wVH9u7`;xVKONNi+F6f!bX;1JHq8Snv^xVvmz_PN$ zzDS`Qq=*@&2)?SdXK5^5m$2dBg+Gq_h&LU$UeL+ zarid+hrV|i{lJt-Y2sMOzJo!NlfZL)+X6fMV;IqaQ)Ko06spPfSyo8)=jn_*vCFmOmfgAB_dOmhl$$$7se|PJ|7Tv-xef8qG|wVVGW# zgoV23)pq@IHERMJp!pbkyPMKEDcMgohcn&aiM`R98wwVt>E!YuXB{V|HK+O6rZ>c< z^v3QbIf+3;pIn*-ln9Yhn>Q=$;f+;nFtM3w;-w^o-%I^1KLLfqI8Jv{f9Ai#9GOvv zcuptueUxn|(4k;oI^wBvDU~JFBn$D@eKU-vJ}VGbi-Bhy>+1oB829K+(sFm3I9{xl zGIOga7x-Sry9m-|6)?r2pbgxz$TLc}7vK$%kM_l6$06d7v?4xW7`YimZ!=TeiB|jD zzL<&1@g?cdk~(S;^_neb40i$vxdJ@2^DE8pE!_!=3+lPCVI=B|qSn-?GyfyGda&SV zr7wF)yuLR+_En|O@w1uARU~(R@JAOjsC_igMe=q8OR2{7+l9j%nS(;*q!m_V5)yuL zH96CoCb=PvP0DW0L_}TOf{EyVytKk?^xZc8p*p6dt~t?<_*6uAz+WgI#oQ|gf9{r+ z{Agy1tDC6zn94}ycSgsXujV|9m=wN+WXuOcN3c4n&&mLyvc=SA;k27{t+$-|x02FA zgfDBj7ESB*r)ZB}G58>|<1zjw=Ug?q(bk-%MmJ{u5`#>m8*}~KRnJ|223l*mGxO9G z_W~bUyau~zG)jJh6d4Fx;I{DO4aehFx8?#_V?gC8J5CmHWz z0%ES&7Ow(p4y>m1JGzz;_R4W=;qm<$={QA<_tLlHIS97ka95861lUGv;@!@s zD)!h5sO>-9lqKf*nnvg9${?(j<%pI@R*xTt)%q4*V_#UIoho^c|@F!5Ck2t~vPYbX!xJ#M{P* z%bX3k^HtqtmiijEGqKM`#)v}G>dFW4ES^X2sCfYQI7V#jrr9Yh_}VuPz5-k`u~v)q zO*&wD4~q7>r?G`mBZ<6N!)&BR!F&KN=xdf_l6xt5uxiwCa78$B-DY@-1o_Ctzkuh9 zXd?osiWhu5}XV#_S!2ue~)ObGBR;;z~d2^Wa3@KfeKE-CI|f!# z^rmQRD8_4`3@{jZ2Pu`xxaW@7&_$oXpOGF+c^M{Sd&D}IP0T9khca3u2%#Gj*J z{2@G+%2LP)H}m8OmOhkmC`OdX5^!o_c@9h9ZJV#lH5~iIwZfX#6h9}X8JbYvB97}_ z$0SH=p-Zi>eC$eWqAZ;{>G9l8T+Fcs#Jx1*=$K~Ww#lnhdqA_ok-^(}vi88(Ib+pG zy0P;+YB^-H<5~^Pm?I8vsbYc;rl&~oci%{IuLj@f6M$K~BY{8G<7yC0s4YfHnC*h> zbU%DknL}=|*R?`0H`#HG>H!X%MJb1G0dkLpzn{tguPJLWr&7#G%RL&BgX_P7>&pj( zdF`Eu|APjav!4iVNMFr8)gSQG&j|g8+(hG|skDe5WMyHs-t43DVM4&_ihDgcCbs>z z6)|5kz$IyqffTASw%y_kn1%X8=xh@YTU;u#-D;J;M-~?v54I^{by*q(=gnqY{f@e^ zoigqz3HL+&XBbCkjfIc2$@6&SSfGUz_^Ot-FqvyBZEmyc86TK@gmOsh+lR{hR<{Yv zM{^<;_gnS)aYEgN?lbi{@H(7s-0VM7Z$k#LsUnyb+zi<1sZ3*Yr@CT%Y2&PQHuT1S z!_rA-EYh|9ZVi#jdGh{kc(>|3(D|xl6A#b8tj3wkTK!yoDZYs|#o0iYe^xpgM9THC z?gnV=44Cs6qk=cRe%U&AMZ<=MW^+fKP=BGj!IkS1mJuKofy;?V{y$YL3;fRYsL#1< z`?4Ig@#DRSy!SH&&cGymMK<}9{xb1)seT!;EKDuJ{)&qhMDd-eyFsdVH7u)5rHljm zt|E~QybN|xSWem&D@+Gtxf$*8z@XFrKG0Wp_RMwiN3Cw~^~G}XhmbrRo$q%Oo2{Y2 zrABK7Qq$_3lhZPSZ@I2{blDM4rrl5PY#OfY=ymv*8B88?jI+MsbS^VVTpk+)Dj%^B zZ@VGQbRJ5*L42z&vz}x=-<@ZEwws_W!;mY(cSYah<_h3zP^i4TuI71Ul7y{L@XX;` zV3%lRHwUEb#-ot7G@Jec%oX3ny%yJ(Vf?G;m)>`Mr6YZQ54dwZVDFFFBdu}0DfPN< z_t_i075bBPE=0D@WqM+{WZ3wCTZX>M01e&X&h@2Hj{10h^9D#O4K5+KG7x)=$B4`y zV{*p?*xZMLVVS6W+xePy}R0-oHvf;Up;rnR%E?(@LX;B-lFXE**D z|Jk-%RI3bZ+Tlgg8!kSF4d`>`28~iJY&EAt|LWa#A!gMdFaBkf;HJ#lTEvOa?Vt4u z?r(n7+HCTAWfIO~bJBx_V0MH)*?Xuz!(@>Pn+5mwK7qR<_nEGIiv`yz6vs>OA-Knm zT=9!xvwEf`z~>+{H{`LxW({H@X)Q1J9#S$)f}8%P8t03+p0>><*C@0_IJAh-$9v69 z9j=_lWOHu)c2|b$H)a~&Q@dB+7b&HB{@N=G_ul9t1#7R&+zYQ-i>58RK8kiN*-PV! zSHhD?eTw$I%iLf2&LLVTw{gF(x9)!T!>%}ZlH<|NOfILknJx(bx%)>q1F6@75lE-d zXrhb3Yk8D^EaAxyD5HwiegS(~y!dBix6^?!CK5V7u+#Z8`n67^^3~Pgz4d1>e`KpR zj5ULFn*z;z0e2o9DrxMzB=uw&1A;@QVw*ZTA) zPfEIPGHeqX8|T!3tBNw%p~d8tVSXmHCH~$S{f5B9T*K2C&)K!Lw>T_vDza*8t97at z$jQf`O;3<#!_Tv71q1y$?RO#5s)im$9RcWnUQ z3uMUGd5U~B8eX@`e}EoZ`$4I61ic{IpTrBL`^&^S*XdB%g)*$oMq6Ef!MvaGn*3DD zH3zC8U7rd)bV=|Vw!RMxp|O33&*`GuT$if-Y@5FVkuF}rA0rv(Q)a=(VXI7+|MvE!@vJo?X50m z>aUzk$)6YU#r(AG6<5EG+C>w<97XzEBu<_h#0pN>8$HT%s+yBM^D|e zjN=)|8xC_g^yy$Wo-1(v8cvnI`KUctEAj%#(8_-w&V)z&x{)vPACYFi1TImh>&x(w`R!n4=*qT-@4z@xT_*9*wFY1Vkot;3Arp&RbDw07!Q(x zmdZ!Q!JNnD_zoy3h;YmYZj_Fx2hqdrcnS-0Wm4_)B5oe15p3O^3g5v zhobw=MdHz}@qfUREO__obN4|myp`SiSY>G)F#e-lwf|9;-^IBw5*Yph6`fHn9@8L0 z@Q>pvpT@X0 z)d7pFFsON2LVsX!x=_TF7{ydX`Fsn1z>+PvSA8_w25ng*w#|hff2i&r%)M0i6y(Np zAE$2`;p4aher|mdknqNLdyR3F6Zy0CCx^^LMGadP5Y82C4 z0Y{L-f-Ih!nSN@?X>*Mdo4&BQ26EMwbRZHB8~aQ~GiK3qh)|-fGEZbIr$j47kUM() z9Qq}2U9!Uz8LN z7ko`RRiz0CMLw=E1r*a9kd)aP30xo)O(wup&xLjqE*i8q#F^naJ!fm z$jdR~XuV_#u0l3+GnfmK#RO?nl{T2>`WD+Odg9qMr&fxG{`J~OYg`I4jtbZcNxaI= z7(Xp1mVN>8@!*i5PZbExOwXnE42-f=&dS=GC~JW}V}L9D4=gV2q77C8j@<^K(fT<80a>W-sSRbbx(6@ z4|Gn}m*#{nBa%%;;#Bvb8*^ENj&AS4PI6L7apd|CT`r_RGfl6s z1&p}YcD2{b!Gpk@@)fCp@02H`X7{a1Jg)swufedsD&gb#oBp%VwEQQd|~brtqzlFoEGvRro(jB^WpCn7vWYFLO;QVlb+87{TvV<1iL*kQ#+0 zQJZ-BHgH)X?&lw`BKIu{#ml9jRJ5u1X_ZTDG_o~Y{5REjE4*Dmy&pFSc=viTsJT3E z_M3yG>ekd9hP{TFJx?y7qtRXB3~-QK4Q{OZ>6igtq|;!?HCSl;3pDNXafl8j2}OvE zUG-oowxpe(fqB)kq_9cIW&+c(ewT%AkH0NlsPd;KFgiO#si7e2cq#l3s~$WZ`k^-qM`kXW)Fk9F zfy`g7bgY-2JMot*3BS~5Jzoku0p0tVdQ95+h9yZ-^e+C?I|j#HyYErIoTERVZ*wkb zYT6H0lS;fN+=uj(!bzzZDT^PB&S$Sb#gL;lJXr}D_D+;4lu0Pduq^@0s}9&=u>KL2 zdr&AYCk`mZg*_UE4NiqDyIf*&)_1XBE$tX&tLCNN?k`cT&XZ;r%6M%=4 z7VFbQr@5++FvOO>;B=_;BHGA9aT4@MI*U1^1wBtJ++kSI)ADQj{5}oPC$Ms#mLd2&{>G0(;C1thyFRSH?Pe z!JFo_l~ui*2D4X83bZGO%j_Q~XyxUK!-<%*7Snv#>`XxEZUUFBYpR$FnPA$W!$q+@ zq^oldPhLiOznde!#d0}H3)VBSOhx(dWes@~h008cDgqc8)qUdqy88>k@K<(uN)oZ1 z4jsM#etHrs&2)VL&-V@fb;ySB99Zre;5&(RaLATStU3)RV#%q{ zs*463V?ze;vddqWX`qh@PKp{F>$+LV5{jHNN3Qj81~@0dAMg;0=|GCOwUhNP7gK#y zQa1m{N_3e4tP~M+lErWUv-_0-2NxFtQl<}S?HR`J`#Q(Pj^UCp?A6lR@y#GAS}^*Z@a=XF;% zFSLrLJ_GX%m;|qr-#Z^|?^292hi{6GGsHG9pT@%VR~OYjBPO{nE#a=d>Ex~^)$!x_ zLaUO}bp5`$ezvz9QdgunOWdWf4)o;KGzr^c-@z}Y_y_oKOu?1u6h*c-!j$N)zF7ww zn!_;8>~bhchv#1LJSZqhCd9%{$w5}u?%=m`P2!Zr*CRh}>b|Tfrc0ITtnlbTqEqK` zZNT6+fF*VlFcicZFJTrOnZq(DURj;PQhhUlOvq5iI2Z@H`sTg-loG6y+^>RDq=n;d z+*g7~@?>~O!Nn!GgS?ic$v|GJt9IlA0aEHMf=FA-(T#c*>6>KV^ zn%E+yk71m49$F4_V-qLUUrL+qD>1*b@sUz`r94w0f)-)u-j9Z7hGZ-bY+69(47 z8)t_sL-D*H_N~TRB4xE?7WtBV6d4cQb;{y&xTul8n!X{XnD3p*?o+DMNcMMNYUF#% zNoRkxAzQ`zQjB-8|1lLGOl_=b(3&aQ54GIL6w+G$Noy%&3Yn`(^|<%g5Bm+c7vo7P zIUP}v$D{yD+|5lr9QkLEznXC`5aUy(i~%wOHSXgbA2 z$1pUbHKe3WDQTZD;?bmS`yBOXf`N@6*6Ri8jf3sw zdU)e#WJRt2hLJ66Mz)yz?6e86uSeTs7NP*aoiUa2(0m(Ix|!lB{p^`+!-YotP{p9e(E1ri6aK?CZpbYl+q3x|o(KmGra!T$~==7rmRu z(F)MuF_w{na{;3$b&rBfr&YMaOz|K3S!Dgd7wP23F};itKtEh4y4tj z0b|)-o9^1-_Ewa1Y2h8cVZV3m8COT$feO=C?~dj3&p5Tm^f>2+q0xPj$^Ec!#;fQI zi##iwC_OUv9+w?j^Qq9qOICMzy1x46H0>bsv#su-vCWmIoff$yOzkGC=0~sZp9v0L zl%@mYYsQaU`|idau>I8{uZiG@NPGaWv^Yo2Je@AC;8NBVxDkHOQu5joRMm#;;3 zxcC2ZCUczF;w0+H4(=Nh9a*BDo9vAvXi<{;eW2-3cwY2gnhqFijJOAHE$`Z~Y`Q;A zVrFb#cBWwwEGLuXis3WMsGYE5*(CY;;kO!^4y_tF5B`}sM$8BFypG06a^A3jV{(R_ z%XD-rQ!;X2v~5W49Rd2ZS$JBKTN^-}7>U?#IELI-)H^!TQuxZ^@m0h}{q_%v^D$D8 z?9;(d_EAqi<%5mAhTWhS7%S152f{nt4g0UXfvjUE_8}+tFX(^^$17wtpDSgH z#nn<1QjUG!9SOBX%>G36{1fzi*ap-)3%vl0^-n=wy3_tuptt+Z+`psEPtU#9=7}|l zzr1&P?GJJ8en|8-BG`WpQ2uc`GIqGj(H|_>rpLCsB6e8VBB8f&EJZdp9n$_%pQ+kJ zXY1N=uAPm7FMiJU+FJ?*#PDliTO#1~7Y^^KgO6(AMAzLer#l-xb?Ze~ee0a=Q=y)V zr<_fP==*uE<`@6af)_eAR%fp32!W-q6*8W>L*-)R#KTT&IK2Dv6$mLR(0j7PVVm74~1 z?Yvl1RVIJqNpB{|b1~>yoW69TZWEFJ>PbBI>xmBrbjLC#76q#QAHv=}AgXF_177K;UNY3`XnA@qv%t%F zr7|cxUGwM4JgLW?8`+a|GX0!LY?X}ll>$iTF=gExqB_ZFp z-lc&Oq^tJM!GB+P{~GvxrqQQ5z93WQbK^>bcR=6|naRFNobT~IPVL~j_>_+V_se?1 zZRXtZiwNeqfkJJ76Tj~mkyIt!OHNrI(7&eSbkAM{ zFP(LX;#GK)Q_nOauJoGV!!|`2Ee?k7#It_P%1yv8XFi3`$!~k_u%&b=)zbjw-s1yO z@!CZ3@4qsez@Yc=_(s0=;Uh7Dkx4)$1)BQe9)?PHNzYR(BW3<4=|w(=S-);t_zB#q z+7pN>40O))UQ1Q1b3sgUnN*wXN?jTn3v6B)(;aO>V)@i8h2b@ z`$hcw;2skM!+T)midDb)jlj!>NxFar?37%VW*y_p6k09_0=+XHK7B^(F!Aorh@D^V zrdq(eQ}pX~0cXC(zrTHs@`Q7=MdDnoS?Oba?JIJoJy9(Gb$|QZs1;6?5B+A0aL@Mi zHWpD)RpL4zqYYEWQ~_p&fn6FPCsWJEuOA}n7Q2=Oh$K(L9d#ExQ3EU(NFq_j z=5p%W-%rtA&%_v|W7Qtu$dhKCoVLRUZ46JYBKCvIbBqth5SVtfPHD%0{@|j}Z@bA~gwRHp#~MgIci5SMUU) z-AQh(XN-8D(<+RD@7dF4)!0zxeLxk@!j%j2GzM7dv0q821Q7B1Uyu6PVEg zb^ycO&8~F!8rQ{z4s)=aN}sgt?-zt+Pp^tFgL=qFY--3OE-t($Yl zxz~YV;6XQk%#3+9Ma%>*!Gn8}E2r+6059ZumBT5*OX`HAVPZa5N`YWvd$=+RI3_nP z>>$v_ibpyq+XIuL693YX=A!9FA)UP*nv!Lo39~EX>ht9k!i;XeFvbPB0}?xZ#=Von z@8~n^DXBKpD{OaT0^432lPgW)C>%K)6R0a z=ua=K&=D4+`<#i~81Q?rq=^MGk6mISc+UH|$U1)K1BK90!ULS5wskpc0{3CXDhfWY z8zRmLQNP`#{^#ML%C`?xC5kauC>k_kSH)atwIBCy=+n#h_hT<;f4U(N%#^x529l9c z5BXE>K}l8Eb$GnCxcV>rp#{Qg@E*aFby^-c2hw5E9MKJP;W}CeX0ay z7~|aRjRDV=!MlcfxCW#je+B=%_~T`jP=#muy2M!csZjJl)7yX#B_UIWJI^}*ryH-73JSglCP>bfl@slpKVPx2(MHqfw$ z$_Siz5?H@0VN>LV{QT>u*wK}4_@ZxsbqahKOd8wl6quoUSWoR(b(-41zo(pKT%x!~ zPl%i$d8(m{zlwca0ZD}iJz@y?nzX?FMH(=e>m!RX185OT$~UoVIdOYPwTa)NkK<}- zY$p?uB)-_uf_w9XJ^9*`+nnl6UxGmbY&(XRoR0kFQy(t^J}yZTzv*Dc{0078aisWN|V zX#oSr82Fqr?uhi3+Yy!(`=%tq>Nzc4&_aeXmGW-aLQXV><}I`Y0~N%YCtF}O3(Ha$ z^HlI@VFYFu_dbw6hU%uhA{$)K0_p9$-a3b_h2I%xQWdbWVR2Fk7_}e`T_E!F__J%hLwnTfA(k2DfGeqt^5Q0m z)($WwD{~__x;zEuS_S8tj+bhbop=ZJ-O*6bjizPJ@H|xQIq2E!V2%JgQL&|@ARSF# zv2VOGYmJ*irAR8}g{8XmE^yAc5_V17a1D+L*)FVs| z@<3v?{3fqKI@3j6qVgKeh1i|gjIqamfvk40)7W4@?vIfB9I%bm;oKx7{T0|=RNguZ zG(OtSw?gVY;WXwW;qpz#AyfBx+9^x{mVfsS%|krLiqJ0?9!{(GeG7T-1K&><=)3B5 z+sB5kb_)NUK8(I) zM4Rpiombj1;C4I4P92MQ%-B+cJK%ZSlb5&vNH8uubBfX$N8)-%DQyp=>pQ7*{V&gq znd@Jq>!+x64VmU_Sh`mHbafg39sx8`d0P@B*0Y|1#1)Rr+wZGSzNWbp@7uP2dtWh% zYz=?shJom(pO8P`p)E7qeq${i6fJ`ulsx*DvMX>g%MbNw?)|#7`;tS2zau z_4B}g+g<(pQ-${o{p+c0zvXtlrX!_hNa7f0^c_*og#T;LajRF(pgr%}Z?y;h+PB-Y z4Wm4X`06cbgCNx}>8NQ4NssitjjL7y`?$iw28myZZk~vHZanE_A7zBTuQ#B)%b31$ zX&kS*uUtBw2K9zVaK};OfzR#^*G*-jn5l#NQt{BoTNeKk+_Aut-N(Z<%c>JCH#;fAM#@lU0EHvK4CbV+}JgFEKIxX-s=o(O4G9{6NXI&}Qfw8bo({&(uCha>qfBtf(B1b|4@BCudjq1m0rmX<~ zWVL{up6%5s3GQtrz!R9+&z%NIuvBAj@Abm_2-+;W*yf#WR^9ma5qRWVY{EyL1{0l| zZID!|Tlx3c8XLTADu651i@3}ki%jrqpe#1AT{{+$vXv47k<^*8)>tI+ z5hDaY%&gWXGqgx6^BLcbnUJNjpUl5{6nK^orq!P- z?eAu+exUtazmQXj=pt}o(AeN?cw^WgDSp}AKVSkkYDh}&L_YyB0lUA8!%dLUKA>?0 ztj{uRD#ifH!BOrYiykjA4MMoE|8(Hi%XUF9Ub*A{j3>v*7{inX zhf(jYfrci7`oPe5mB;Wc!>^F~tkz*n(Xq8Ij{2;k&zpAPeylRGOjGE{+E$Y2hCDVu z(p|BTb8o31<^G48A2$Q2f1|~WZgv;#1O86xZMFsN8tdl87rO-9g`9@^O|*Vk2*dSj zyOemD$HW7)?)xX+`lcfasBVeQ2FcjN_`o@S!hHu;v%iLt-N)UIM8up2e zML_fkuOF68TY1riz3j{{HT0{r7+uA{p`A857e3~UW!XHrJpU?_TPzsg&k$oeiu2i1 z18X_WfMW&t@+Q&P{^&HJykr#Q_l_=#Bpn)4|8ts;6XLY~18N;UdGvl}Tm&+U*hS<{H8y zF1w<EhkJjR{=?KC74+@r zoUh39y@!e*`L9)N+(~_pI%0Q(q&qvA)N0`zTAx3EmSVqUd{abk{@&^P97KGu+S9Dd z0y?lar+E;pfJFR#bqvmQIQyVli?e*3Ra6gZcOueqN%dpr1_8U5h>um1Yx8hb6BQj` zk$-Nr4ry83$*OL;I;xthq-?>5f?+5R|W&?h|^s1Zn z`28Pm1nw4Ae;A0wfBjL$TV5ls*sDJcyj=JSTAGO(;&D%`T8_UPyn}IfRQ18Y%BgSS z?p80k_Pm#!_@=`y4y|4u@G4h_RZVCfjB7+3QWf8vp`7jXYMV96S&g?O;d!KwtbQf% zdnLWP+K@w2_g3uzm*i`>N2)KKeL}f6uu9$hRwC`QxGHijuF80Jp>qADDvgq-%e$vN z64(fK@qE?ZzkH`FGiCD*#V46fM4zgHa!lq%^zM#&Y` z#}jF*4pub>W-3=7tkU(B@;_B$PQ@kAcI~a2dUm>U_pZMB-$0wS>V3HPZq@$4T#TXU zZe}QZ4sucVG`?-p~Qv2(;EsYFNR9{VEXj-@q*#06)k$08!U{vKqLQSy3avQ9N4`R8d)MK>&V$iLhQg0wF95tUVt6U=M=5=o{o)YsRsIvj&(>`-uWl|z1*?pY_C+;wHkjXcE5l) zZK4g7s@w|$^s7XCI#!z@9TZvEE?)M|0+Yk}(lKuOBqd$J3qO}Wkd^5EQ8v{i`wY#F ztO-62eEiO>(gYS{seFIP;(X=!e^ymS;DM|NAKRRtHP9c4dpg{U zgf~2VmSsKkIKbcNP(#N3a|e}lBM}FGNZ#l9woOHPrG&1q20xZr&fiCL6cJB)e=g-VC%VVDFS?lox+`Ee(LJ~k zvwuhE=TfmO0T`Q6&yH}Xc}BVWi$+8?m7ymJJ3mDk)8q!Ue=(l$r>?#D|4>JL;9O~p zyUtUN|Jpm=54 z@jTNoS{xl4KDm!4XfhxCZ!=-B6B-r51_+15E3ULC_L(u&TOM!98*W7w>Pf2{hoOTVz2 z(}Wp`*dKMu@UZkMa!r)Gav{LVLo_AZl7@b~(anrd`(=+lDbJiflUTdTf-`%im7T^N zoEXt_MlNVFTj&~zdBUA2x_UWrcJF13JzM z4pDT{kO}UlG6elD!~P8LP6xx+8R`Bj#`^j2&ky5QV2|WB3&ZQp?%8hEWfF44b-)z5 zwaowOBVAx!uB=$mmE3pHN|-%Nr~dU&8Jt!qTjpUe?eA;x`=W3%G@PVMQ8zu%3|mgqkuNe{n2qd>C} z8tM-ZY&dVUkPS%>-E(@_BH23qv%3bfYk*VJ+paTiz+O+{tk!kGc- z{IcTF9f_KJy{tPiV>+&v;`&+Wd^N)U#*;$+sgtm5IB%+Qvk`SS7f)HdCr51PW!&oY zRQQ2j1n%$|Y5XO2lO33*j2PLYsx7)+n_E}rKtA=BYh~%+BUvGc@Y{CYaaEHm`;6&oz&_c7=oS(I*^_zO`Smg0Cm5o~z9@ zb8BC^@Px>y?6^Mq$~_IK?u3SiF+zhq7T3vkMg<(P)CHR%y$6^#pv?W@XHyh4)iOC zd>_msn>b)Vsi7r5EnU4l5u@MKWK*P8==qeoM)gdpqhpVb^X(&5#FZM>ld2Hs{bpU1 zFapdId6f|j3Bs~K(aq4)?2a8kZDU2A^36vuHPpi)%AXP#Ib82I$;_V{u#4*S(a1+S z8Z_t=uA~f({ z#zoYjOM?eisQ+oH6SxM0F%Ay(uZAcNhI|0+ta;aV_1$yySkZ?tAw%H@l8mkKKD6w}B+{ z@Bgjj2Sj_=fl@YSDpR}6N%4odHy#4!1opK$uHCNXZfyO-n-7-Csas310?u-N80!rh zRH^oS`|o2}kyA6-gJt#B@7gW;1)chvV`9~UF@y8Dgzd0yox6|$Z{d|{#9n}B8s**C zT3HfHo-LIvTknV8H$S%6xiZM=zmCgDS)PfOLfIyK^>g4bk( z^spV+5G<^g!%*s%DzMPOA{s6=E_R)4v6RZzt+Rms$d9?#$)mIlPGx$|+kPl=*1}_><3c z5|nu%ma$#Wi_TkYpA;Kzr(x?jfjPz2niL!6WP|XEhXD@oLUUoP7u*BOb^Y5DNEIySBj0 z<%#=-fGoZ&KRDw_u=SOVAHJdSE?B%CRFl*oIo8TE>Nb_`j8y$AGiJ3so@leK`9E{; zK41(Jy1(rKatr--WD0m=GBVS=RJLi`j} z#8PMcw0H#vdEVTj>)vMuR>a;zfWnofW!jAfAjuD7QV{pyU}fH$*a)1Viovs@glCNK z%o@$5Q%(}(nh~4J04IZke4Q?M%o=d){v)>IS$_qW%?)qyQ;j3lQf5A;BITcR#D!xD zj;|Jn^=4+_mAWskX`nA+*ABuw71Dr>26EXpZv!Flf&?OYO~lTniK^?~BpmSj8(pPd z4+e*|x*FL@l2n`7TG}({x7G@Gj<~byE7)p*RKJPe+%0YFRjiP{3ReVBA(@Fr=%GG^ z4=a$1WUgk=b&}1k;}LmMW=<71^i(@HEA!q_A7b_cZ{<@9Ako3%8S$NOBG{xLNp01D zgPieex6DDj6=^CKsBeLxu@t?WDn8a-4Ltv1A*mAW@8C993yyjqTqKm>-UC>NWk2PA zpml`H=i$rt68__T@%5;Q=w&8CwMnl9VN|Pp4Jtg_z1091(tiShv|(u!u$tSWU;sCa)vN z^H(l_efJ46;u7>O?6CgKAk|^RI1vz6tTm9+B1wKJD?HR064CE z#*s@ns&PDtBWf?Sa69jl`KiqM9PvsA>&~dp!FwfOIKv)~dLnFM!BKeNqFISRWx(e^ zc~V2tIYobdL;BA$4)vAsjZ#Ke=dCi*I>DpVOY<{I{$E1-kQeb@*xj5~%EG#A<0>QS zUv_l*>AD%YHwPnF^}ZX7t9(4OZiqM=aemmXoytJF$fj=TK}eINHb>miL098Rb{g$K zG34NdQCUf&nNtw=2H#9$3S))bUHNXiO{L3PiMMG{J#gn=9IB(n%zl0*0}($H^#Q(% znH9=X9S7=5cDlf3oIlYoP~M=O5(^xJ=*l&a_~CI&-(3;Oyy;)NlyiNvo62TOKMniA zsDxGEuSuMih&i@aaFrw!azGMw1I>7dc(CiqL^mwcL|oea1fF4F3$bR*WX7{chd&5( zQXfgqGFhyHl=*51BAtRWnTZD-H-CVnI3-P33Ou$vXe6KR($rFklxcdEs_0^P!yN`wY&2|jyMYAB zw?}Kv$WL$QUI)U$UK~%Sz`Lnp^m5E6s-Rxq+FTO16-+9sU!t$+&Ia3E6BpHxK!sMd7vDHcm(7Y9e0umLfL( zwB)*ChZihtU+`Xh6*#NuNw5>tq>4;u8scz>WqgGVz2jDcudu^t%{5a*x4FFym3qrc zdA@Ptl0Ar?V*|E{;N;0(wuBjH87}+zap%hQmZg=p2^_R(HZ|^*e^N>BNq+0RWoG@* zhb#X#oNv6ki)AT3kp-(AlT$uVKXkT|4+uIM+o-!tXokM$vfRMe{vj>K z|IXq~vD@aG0;G|IqR2GNYjjUO;yIqY47=TG97}L~1^=zB@MYpRXJxSdvx`^72If!f zD@%X5rXl(9H)B&Di42T`1vyZIgW8O?;;2)--hn8sPG^^MqyU`^EPC&@8&n)LZVBSv zUb@Cd0{Q+<{O9j!Q}z2Hvu`v!bjjk$7Kim>OduA76-NLgEwNA)WQc7~z@748wiw$> ztni5MOD|k9+=aCBMhT__*v&B?4`{*6I0iFgRlYe5GuYamQ9{6#f!W2^$_Ewz*^(6> z?g_YB5B z2<#@m-3v({E3!u#?tP7Wv|SWCJR0`sbh>+#)Ihz(nsqW8eZaZ-;a7cObOX{z)82~V zkAyCY#_&^F=C>GrFeCWJno^V~{wsY^{7SyODq#z>H_6kP`bc*H&^kymv67U-t%l@O z)R}U{u;q#1ddm|*ZyMFl)PaMd4!ah7uUK*4>vjlCtP1mgNIIZIp7Ow)$QDy!UyTK7 zfIUC*=nLRIeIht>(%85sf@`cS%GiIydv_YOT#oUfzP1ZM{UblXRazaX~JIZed1;q;3WKY2!e;*3)|xeK}rG za#ZYtr%KWwjNW4%=pP`V)4mGAQ-hWjElhxA=K&xvay}|uc1bTIf}!OaI0&IHRUsER zpzs!Kr_zKGm>JfA)1-J$40bA~rH9(m>Ie0GVI^&H154Q$fg5lv^rp<)h79NZZ^DoF zWpKtC0uJEl<3BPR$n!enRt2bkU6(YoM}z+?LQo3H7U3?mX#}2QD2{Jm>gfF4J~grt|yCJmvO z1zD}vfD;oX#0Za}U+G>xBz+DB&G1Oe=;quJz*@9Js_m|VMT0O&yJVi)5V8?=w}F5^ z{O1c8f3S%^Uxz3!`2LTs$4DXU&VJO|t7mGufc~E?s=C20v^A~L*1!NwEf=-Cin(M- z3p9Q%BUns%)WK}B0=*<~F@A)~msz34%8U{;i=cUD7_eg1?1J~g!$Nj|4BhJ(*i686 zl5HhoB>eZL`Le}hU5u61p#_o}9gz>A{LwAU=pC`2%&md9EhjE#H{@%5jj@pL$GzS` zTx3M&Np_q*5U*DM@JTF5O0QVo!MLQs*#Tzk;R_Ss2mG!7QS+79xWKKtj(6;@&lV{T z39X4f2{RTxBB)8zoGq^JQoAEYsC@|9s4xI4Ix_QI3*x6Tx#rA@_@QK&I`BMlRbHSn zCysH{vqq(8e@NrWdX6yQ0H%F8^`31CTG(pLNr^&>ykl#N{DD{BARy8;vOz#xE0z1A z8`)%a^1z@Dx^xF{fgMwWCEzOEl`hl(894G}tZ0v#kA4Am9B`T+##f(?@$ld!l2+yu6?Pot%dmJSWmiaA<>hV19-7Cxy>L!nGh{c-9_~7%68o@Oy1Kp;t?|z8| zCn)CfA8_2lt3^NNMPhCPatct+mOERd(`_WJA7;-c;M=np(k){j#(4$Khv2>uzkiG5$pP%cZTpN<{#j?7#_XaN46S=! zO&aP*yY!lzYg4u7l86SXf6oOT`{s^$uu~}bdwtB0Y2s;l0T6EJx_&N3MP{K)x;Fm% zI(qLVx{exwZu3neGbvl#4TWOmjc%>4H^A3GlD~WKibbQ>N%!O7x9!mqU~x~z3{E6DEKiq zIe#5;4Hfjjf@!^w_K~XndPHmhd}wRHD_5g!(*f6k)dIao#|2rnHpuIBZS9^ZLAACh zxLY62r)$$P_X+&Chx5<*Cw-*4@pk0^TEYj>_snwARJ&qVAg`*eeZdPsUZ+Rh~`Eci*Sxqwl}#>w5;4OnH^pDOTi@lqhUQ5>mIqmA;Q?8*w zPFL+*9n=zx0G#R2zf2J8cyPCFRgfUflQwT~cPaXw=-VQ+q)o4TS=cS8eRn~_JOol` z9-`g8zQEM-Z@%ZucVqRddEex4RlB2Ozi_W~%`koLVmu5GPIEnM+4rVu&*z?>VqcBT zD|@l*tFp;`{dxNRFm@UbeD8by=xZfAN$TO&0Xu!I?4yTU`9~q;uRh$WU(L4{>wK+h zreAxV_He6_Io7IAKGv#58ZCYe45U+Bi%dR@L)WH?IMqrZ)6DF}%EM{L9K?U#tgC+Q z4fB$MormFfxf>j#bKOTV#_vPv_qCcIjcL=Wi-OGsliPHfR&uzNJenJPu%ak_NDyY%z&=m#Wh~a94;PYkd+WX}B znJuj>^J-3 zQE=mwmexonx=qVZ3BEWnzfGq)ELYT};Ol&Se103FDhR#+4z$;E56jPP%?-YA7joDR z%TEXF!50e;%at{UTch(^S`*PH=KPgGqI({@yrSS&GmC;>&u|7G7@ixvf5c(gTXz`v zGA*r^{MA8T>kX>(;eIsa8{4!b1@lU7o1RGxYEhn<>etE`=nV>4DiqHpH5)tGu4p`+nkN(0w6Ypd|1>OUmZ{Y7%1|uV$59%U|g4Ivk zgIugLxL$i$t^v#1DsNG6#qV>2tSLXZPJdY5;5{s_+1k>Yf+w;vKu-6#?1jN2=nKdE z!(cad29L%amTR|q>@BTB^U($^+MtVX)6%Cw9wRdyGaSMDP%&|BJl;3UOvR{-c@u~f ze9Q(s0a|ImQy9_W$o!Z$_ua58kM?Od>E2ic);hix<9W4e6Gk`v3X;8;LGctg*RQ6s zPvQmB8+e}>QF`=91oI`{{xQ_yHRXcU=u4cz+LuiGXMicMjZv(0w9aEd#=Lb!O}`(c zVQ;6QUy?p~U2I;P208S&r+pOP*6k|>+>gXn!|fcA$^G!vVt@9h{X4)VJw-p2g`Jso z<+|Q!UzNSW^@R)G*N6~i%9>CY4-M^#M=B=YvN?-qj~u+OL)q8nk)(bK8ZUpt@(h0? z?dhjV9tA$YfHsXbuN`);QUAQiuC}CK1M&q)Zo)`zYBeU)ePP_YbpDWv48jUQw-~lj zmJyeON3~d&Y~tI$(XNn-EsTwCZ_+oldsQT<0M_~zX?j~!mia{aV#{Jb$qg3&u8B~; z?mN4`K|eAZA6>jGimX4k_?^Y{tNMwYCX<8r{lS)ZM_x!8-u)e}QE78KcC=AhM^9iC z5q_lk#=ytBTbp(MBFo(Lmtc;xTU(^(TEiHvR2HDEGr*RtTL_+4EhFBIcDgjlCdRe` z+}2I)cC^o~w68a)$ zu*#~nCYLay64c!F<&*P+10Tn)VR}%5^~ao?T+G|nI<6dDN2rCjMao92#41LneJ>ZS zqPsHPkyhi*XxMm7ZF*LZJ}d<9V?P1Crv4Iry$J~4{rolg5hsqJ_p$pztS`|G!0eva zro(6%kc>Xp>H~DQ*dnp57NIeA7yQio_jrdA3w$}9?MLpwzPd%a4x6$}*Uia;P}>oV z3xhBKa}kUFpzj*}p#EE{cC`w9bgR6R7t@5Dk2l6{kFT9?(22a zQ-R!~#t4e~d(_`H!f*L`98`PpC2HX?`rdhj?&*)e!;u-vvx~VZ>~onE#LERT9V+Nh1Gf|N0S{dPB=b=%lH5v})@lB+SLptq;t)1VmMcb_FGt!)0sC%5XSYb_ zkkW%(-uo5{?0T{hm=~et2W*JNVS(c}GCdhA0wdE?d?V5m{WB|Pm`74Zuv8|M#&hSx zZ{$G3h|K=}4VAxLk8aEqaEBjVzrvwA0o`)e$c!$;SplD}iIbUs^cSX>3xN>$5C01I zyqGFSrV$?`Vyj7rtDv$eESWRh9IEA?Je@hT2H&vxFfhkiR}5Y^Wz zu>enQhhb!2|EVNtnKKbFBoEFe*4N2c#E@)9)O#@Y-c1&(E!CT8VeQZFp@?z3pH=p{o$zNi9>{+yET&;-6+tMMwjt_j%B_iG=5wUu}i#E*NJv^$%5#K7?F z23@6+;$C5@Kwf7yLW6@8@AYtLsYnqW@uYHhHY9T7tpV>fQW%h;wueuPY+m$#++B^k zx|VX!+cz$i)x%H2Rc1jPV{#cAaG~d3gHP)a*rq2$+2Nb7+EiekgZ=93ff2x1=#>U` z*yGu>2>%0$B@?aY2DBR(YeItf5VX(M0P6MQDk+{yY7n2^u4M;eG^Gj2NO2FItbahA z*57YQC@ds3OPn;NdK5TM+YKzza#TM)p@&VozqvS|O&jRPHDaGafX8h~@SABmBTMrj zJ;!2Kn*fXyE-faYhfW{Y$XKORnhU+dD(N{(0$W4#a7y|JJiE0eAz(-wqU6Z<|IKl= z``>ztn^%_XDM_@H@d1hnkPhukd>4AmI3hg?n%iX2-Zi+8fkwef-zk?M9_dCDH+&=U z{*6dy8BkC6`M2VxuM(ad$MFr0PjEc{CieRH{XLFZIL6?Jz;Px7|8yJ=yup!~_#J{@ z=r9q1d?_I?Cb^Qb4JL@!J2j&}a7e&5$=pWm@k7#d$2Cc+sZ19^g!m@YmIov1wE`0$ z;^)1_11!>1U|!V&jkrU494suO#G}|}@2oc{F*}?!S=`r28o1Fq;Hv!*I#sZ=iM5?z z5FM)-V;OOieywA}{Dz`Ac0h!Zpctn7x>x+j9u=0nRpf8|VSI|Lf)^=I#m%k7`XRG6@9r`&~pX!q&d ztQBDMnYuhP;RGb5?D<5MK}%#(2L+D}x(N?}fxcgMN9Vp|(gjqNDzS<2rtAGG@op6Z zbJNP`8pk#N@=WH086Mh*-osoY;X96je;M-;)%=H~!_=xkqlIj`Ky*E`#VPX>fhP^L zd6IR-UlC7v0FC>e07o=*#}=v+I<08#SwV3f| z#q)vbPHsY0D@4Vj-F?9}R~aPDi=ix! zwjtmUiW9Jk0J+RA)_M2durF^CcY2F%c2%rlY>PfF4sovQZzpM z0JR}zGGLRFjcXiUajmx$^<6$fSMzPqwAsZ~C~4KhP2eqFdEJ`>ezhlJPuz3WIpV4O zLC15a>yoIX^6u{)rhB!jwrX0YYY)mS#uJQ@t;Uxfj~7q}KjRS52iTL5B$pSV?lq@rom4iH;9}DxGiwZ z;MxWa=GxY%KAS64ysP8IyZK#npRX{_{j!2bZ9g?roFFc+UbfqrZ0Aho4vO?f*L(WC zMBpn_3F8&bFUbJbPs3QuZ_JK#u&5`9j;~@=Hf>u3Uo8a8pT~lq$!PV`%7%I^ulFk zlQ!1am;1TPGo6u2`;ThWKY-V_hebJ7tPz(H6KNAC0R6xBPm@?!t&Vc!5O5sU;QSf< zM&tKcOo_&QL&ZPC-;g^=rI;RR9BgNIb||vMzv*D(#f^B+VY$O5%Dq(o+TLf)1mi&3 zVE80a%h}J$%w+Uo{t}mS+Qz198VfiYYy>+NCheO>?#9vzt{I~a7NU?X@&JwFBw}R` zBt~#n%|=TGp3?i11Pgk6Ot(!u2w(pvEX>+dQpIIvb4I-laq8$(7tKv&bvjSCAb$G* z=4y`0W!h8Vq@)%(CZNXOc-Z^WU|&-y3;`X|ACd0UW{%VY4e*bCj%Z)wh#kGaz|MOH z_rgAmM3m4E%aG>Q|G(n@3gip_Zx;Ut5%F_w-#3eY#{b2*Pi086Sc{k|%C_4hJrBvb z0`1gHHSVK0Yg!+purWJ;#Y2*a_zuPThctT++M!pF-Ih9y`)c6zOVg?Sj!J6-_3THi zJK+KtL#b?0^oF zuFvkI<7e!ZZoY?19XSy|zc(jq%y!7T6&2MNl~EHgQsmZG96%%SuXJP{*L11G?OmGu z{8$|#PPAI+&VgBa*00*!A3NJ&kO~PqD<6C|{%QFPwTj(+w!m$n`x$skZS9a2_i)P94(ZVz(m3rpN9N!dLf=<5eP`@iym$JZ zq3H@qb3>{+g1!&GyGzP@5cfq1JL_WZnJj8Kiuhb!s@m1x&8|;hn;{sJyveB_l8wyT zEb%O5QMN<`CTh4J=$iUH;ve;3Ca!d5@x+97Q9kC7 z^p#R?_ zBX#MbhTql3_j6;4ZW6zpX4<7W|JtLKe4aQKPh#_`G`14J}w(A#snfh z(1kN2<|}ym9*5^6y?#on`E~xs+joB~^FZTgG2gu}tL^(2YU_uK?{s%8JOhlyVxXTJ z`s|QH#m$|X_R$&z`5f2^v(dk_pO?aqBo+tWFXo2nN2sOfhJ!IH`=?#d{8il9bf4MlQ;|$77%!~+sS5xaLUqYl$-DR9b zJ@{=l9-jR+pouq2TQ4)?)PjEG8OZr`1|;8Yo_H_{Edi>2m_sAEJ}cSoVBp2ZOaNXI zS_e!8D~~ZpcL|?_kg9@4ERx2}XxqQuJM}O3p2IziS@7y09w&8~b3mYIE(80)U^6pj zAo#PUi53GdvxhX0xbT0)WYMBQE1yL?)QDC;X>&kq|NE<9nSpA};?N^;VlO;fz*Y-y z9i#P>R2@tcPDyVCd!-jb@Wl?DlJ*C|Kb-pL+#zCP_lrT-;74aMV~klh{X;S1lc7Vz zg3zxQ-dSQ@%85~t&^PDl5A_FRgkv|vqkTif=ekWmu)fi?3)d!J&3cgDTambV zcX|FwSoBQ>TyMfPW4fyu`B-CaL!^?gT*-F=`B<9oA>2d0A;2`fuH-C^#GL@HTC6Uc z@GSa13vKKYscfJUy!bLkb}q*bnCc7%i3#A$hCh0WO`H$kp9(5}Br(=Fu?*hT@HC^n zDbDHOlPuRsIo<8e`j_iPxNh&eUWn`3y@U6qir*<7MiD2~JDK%1F}ahtt>XP%@WdBX zwZObWEe9?p+8KDeYxicxoLUe$ZxqCrV-+_z%&95wd? zl@vRqvwI{K zZ;CWt`#yXxPAs|Y57rGnU3#zi*KnUfV#YI3Z!tPIc4M5=o+6E(;eNPWN9(O}yQLqM zymhzlrQEKwTlz-1_gCd!yqF+|b$8v;r^@vm%JoywSl_x{r(Ay>*C}@ve>AtDq?l(UIKR_beYtqvI*#}W^uaGU$jsDeuMhg6HC1KvEoBdpF!cO zN!r^Hi5d6nE-Gg;hywo(h`jNlgr1^4aD&i;k*)Ne&YudIHc9D?heC7)>IRMn?UT+c z9O=Pf+;>X4c>6h~DbI01xlaA%I;57aTmEt#(lxZA-&bMTRf`onR=oc*Vi=(L4M`VJ zD&`H;Y;3)iqZ`;`^!;pC%3B4k1P^4aOL!}%qz^CBaeGP%-mW`RNn4Awbo|qjMgxs8 z{4TACLh9|M?OvmlMaRgbe|eW8v__=y1tl;25{@Y`9Q?`f80wZj17c0ZfxYlqG42C% zIV7Vt)JFR=PW%jSh{vub+)Ll1q?i6B-DM>m*ig$L7xm?d7eDR1<&)Sg?N;h8QS#X9 zt>X5MG>ky5Zy!;LJ{$8ljx?>JbsMlkzAckUz=BP|{5BT$|7ZGir2heN-!7yF<}>!G#0tN(><>)fm^DB*G?Bog{!pCD47@eWb-bG zUW^p?hlo1{T23|gzHGoMo|l0Gq|6Q-(sN4tpF@50pmsgo(2$gXoY{&O+NW5Tic!W! zv^{2cmTx4uH>tN>nvV}qv~ab5r1%!bGHu7^P(pyfX42o6hUYod_H``vw+u;Yl-425 z>r6+>KfRnLjD$YKcL8y}IP)TJtoYZq$>y(dg|1Pw4d3r(hVjCm?Xam~y*I&^!|0FH z7eilQ5r943&WsC5r+UGuag~P*r0#-uoOI~YZ~4{2V6h#Nm`bRqCsyjcGe}$n#IKNa zymu6?PQ=%mfoo+w;n-q2CTW}%zGB!X=rv9T5PbVKyl;{dY zPAq_&xXfjRA0Lp0A;me(g#z?`R6aChiW=>%HZA1Ci`do9?xDKDXrCUDQFcL+Rw4Rj zqG|YH%QV2uu_QN{eve=&EK%c(?HHo6@gP(U*%4B9ds{pJzY;r0N)o%u%LuT zd%P&&5K4$c3A~rFXz;dD#aSU^{R*VNd4X7#xM}Iur6AX zrgf*eq5{+c#n>oott91jyItx4n9~}#3c7k@epcq(MN2}VQ8=((;|quvJ)y9D>aM=} zh`U#M0`Cs-X$@v*!+NEqooTM{xTe^fK)S6LF@&b>4^qWj9%%S=~{69!+Y$(U`|UNL6uzf$n>3?pj4^p$X{pCLq#M|mE=ox^?sgBy|3|t|Z}|Om;dgMv_$!*eH=*fE_Y`>SV1pHNdzdXd z9sPXqm2(icCif1&*Fk5W-ZpJR-Q@n~SA`So;kL#2t!f0DWy+5CI z#$2h1!!f&CO7G$-=ecqq!BBZlmj2SCx41BR3y}Zst2wf!fR6XLskBFyIp?_b@Vp;f zKv`tz*Y!wGN`RKC9ZpN*!CR~K_eTv(fZDmzAurA983+^_?021+!10)`WpaiL@9<|r zJ3q=|L&RuK*LBjMhQnv;>=uEe&?MoFO_yHa`%p^MAwRciv zn2H0n>2xne_khrA^nIzo`B%P&r*W?W-_AhbIa7cCs9q}=i?YSYD_Dad=|G=8`TnU7 z;4J`$u0-vg3IrJ&)}W$pXsTU$!R?l$;lM@N;SSVOd%8{kaOX?cb+8}hRmOu)^D@d+ z2MP*uftE|9z7?I$B^MEu2&)=q(MWJ5t`?X8f2RejS86wOc3TxIj!%-N$gOTf#26+N z5LoETDE8qD8jJf(*Hez)5$uFVk{Xf`-N-@z1|LMiBr`R|SnIVNRO00PS$N)VX;>$7 zSB86>{a|eNC&tW3AV6s|P4G9cWcKsfGY9&k0$%{nFHx|*XaYkzU%g5KUz84@ zUM!p{fO##M4bVNJ6@RxG={tS4J28N0TBWo>N@)g^W<=D*!=1qKkTu>&l(R~<;7k{= zbiIDp|*rSI8$`XQ^s5(94>)4y}Oi0g!J@Z+{_o1A!rWH;ylW ztmy4_?ht5%+5&K2@5{km+w$~b^pjorZ9p2~81tx8_H@U!yHa*{E% zh20YC_5-m$9+Au1j41#2?nU*kM99I1C~~yM7un9RFO|g8ez)wLQWB>Xx&s6igGRkn5;!gH} zYx{2YD6y887X^~sZ+ljmRyd3&j>$fP@nfrX@TVB;%|Gk4dYE;%YQ$Ai<+$V2yoC>U zzATgB!fWlk+KP2*AT)(+ZARl<1}I6mQBO!=?}7Erw{)q^#m zJ-R;M;n^6Y58)V#V-gN44#!XxvE%p*bFPfJ@)sPNaSY$jk!<{4Pg9X*9L9Z7N^iIp z+c39FjD zPD%=1uB&vOkzH%aN5K8J$YuTAv!*R6r_XW>y`^uD(x! z$BdyPMu%~w83Ww&{Pt6r8x)p+{q8uEF#)KbO-o%NNs^a%I02&}-Xtt_H+Yu0PD zv(eEt1#8Hej%9AUoNnWVS^1P@RdccvsCBWPR~jjKG>jRgkVNf+b07Jt@t+lKSL;0C>wMX$xnYUvjX= zDRz@OU<5-ntbc8KAslBHFHXd&y?kRW@#5Hxu~diSm>uzUIOw~cQTR$7atiE6h&Zk4 zaLs_;dHS>jH+|QCEdLZwVyimm!QX8IfTNj&*jc?S{5~-INktiU8k~00T)CaTMF0(wYba_ z*9K*V>S#fkc^S7!WNQn`MIAxbTPWPyq)op6xk2ZBzwi6?_w+7F&OP@m&w0+X{2vqY z&DUTTWZFZ7rA@&67gb6xnu(>h-3HE81C6o~n61;@YYA3=KV?1X)eIQ5 z1+q<^4Hb4LIZ99`vU+_Z!LI~YSaDJEXyG5&Ax{u;r6*)9cmUB3k;qI+c2pTcQs}=u zTJv+bKWCtQr*2eIlRy_gf_`ZhLv?}P1CjRL44<>p60@VOAoI32Ap2SRce`U93h>SpVF-xFOFb5Mhg+A@T&g%3#xa|21}5f66z^L7(<(Yg z)u(l&ttQ|8F{I?lE-*#-9+GEQI%ERmmNB7x9q0MH7J9Oyx==mwo3sV_nozG+= z`Qw<;lUAj8jEf1Dy@Dsl6yybA3O{teQhKG2*eL5h6;Z}?lpA-`Co_(N`QS&Z2I|)-nPtF%kV`bY>dcDuNDqrYBKD*jlVtdn+Rhx*MqjPDU z4ruKz1F3$my#Ia|<*flxRP1j2*hGh$UqWBA>x>4}Gp#oXcQGpm?MTT5^Bm8bq#8^@D&h4c$eUicf#q<_`W z&NHjXH_}!+Qg2J;YtvVdeYIc-%cUfnd4Gh#aecRs9^<6)$mc0e-ObOF-7RjqAR^^CWLTuX-)c-jIf-(+J%eYg233N>dWg|L z;WnfgopOY-B^lrR1{Q!2R#cN*AK=+P8iBo09+!*Hdi?LW$GguMftCors6#0k=YM{b z+&_zb&Y+o;X_V`51f#9|L-N}rkW`*Rp7_Npschx>$i0SfAMTrU^vz*B=XKB)Q28ySZ-U~2VO0gO29ec9 zdA;G`8ZJYag?PV8xlTmaeletVM94YNfJ5L`6r>2Z1gTs_zq1r}i6P?II4(r>+&!J4 z#^X1{mx4-zU74n~A(GmVSBY~a>6hGjP7e7Z>lGx<*~VOd^N;K8=V5tLlsLIkHbYeMSli|{ zu(a7y6%=nDw#>K8+XSuf2Ky}TN#y)xuv_{BZ3hT%Hp;4j$E_n(htaX$SuI;@Hy~2F zO3+56kqmKZ-2+HEHbI}DHL!xxm1E9QLn9YK>n z<40N8f7697Q&9Xiu!;TW*&Ab2)K!oHb%Uo9{61P_Sr_#zA^Yi&*d`IJ#v9OZE9>LC zNsn3h5$IQdkJz1ns}vq+_6_k>lD$`=8pyk7`Ch5eW@B%YGLQ=?S=bPy3t>OUEWO%i z!*zFnAT@==`w_dHFT@QKefB1_(F^Y?sZ}^mM1A&t3YyYS#j$B!v z(;X6@9X8{)gMmbzvGj@dOJe(!0ykgJlNT+qhxmv>C$(}nM z<*Gn`HjyzHE`OY)K>53Z4}kA7r&d@ay!Tp@eG&Xa));R+boF)CIG=_`EYL_a{(ltG z^F*6WI5Y!aEBM7gt3{4yhYg?pG?mnQy3A$CE<9i8K$Z-$qsLyn`jGTB=xBA02XY&g zAnY7EBuUj15M)S3WLQ^_B8(Z%Lwr9FpAl`4&@;lRb%ySD%GB%C*gD3QJIdyC-urnz06DF7{#%gRD4E}tR$lmNBK1sf^T2lr)IRH zFdBKEroayz$N3-@M8^8v<<9^o>+bn#*aYsH*HuIKypmhyP&FgZmy|GX4>%<_UqlML zaqg6D3Ms%<_>u)up_X`p9vJ~|wZ``*Nf9=9qTb9z6cMBA)kqN(*`ox-$AP z=j=~sy@-lYf1pd-51&h|lwi6ct{6h@t|A~DVE+s3@W8$N+}vqiT*YUAIqJBQSwBt%DX1F09lSh;@sgp*&q9f;cR}7dyR3tGbqjr z)u-xtt9yl|U+ld|1vFx(`xavkJ}E}5c}RS0IG#U-^=ZG6jPocy4(*-HSq9;&%@eL@ z=!rpPZ@%9NG4rpeUP`&7lo4IjC;m0^pue z!mfsyr!wIqy|p3bltIpo@H8?EAYXROO0NO=5jNnzKIRVIfOfhQZ)rd~0l&YYijT6+ z^O~(?{H@mez0s!-0|f79<*9M-f_|&vkNk98zt%7VSFbiK<>y!*_bN}#!qv+STlu-x zMc(;1Z)#Y}-*3I!YdCeUbsP}lms@S#71k-a3H|FArEB@!g4;In(|7cCX-N%3kJ(hpM%6QjUYk_GA2IWzQFaQKhTclxljV|qm^JX> z=M&|pVh)+BfnUBopyT6l=f6FBdW4kOHS*^F8uN-?V)iHck80qN3q_F8QOqsi>IZp4-VVE#?F&)ue$ji&L{1Mptt!m^h?*{&Y>OzC+09L2BR{T_J!!Gd}Ea7)}`BlZ;M&Z&( zwZ{eSD~jibu8YMZZ(wB(ihq)vEAEnc;2E{**wV6P<)mfT*tgbFmL>T168STukN|u- zf}}Gdeu_NV4SyurP^Po84D@)q@M19L-!cCrG@YC1JSy2@k4hQXU+a|S!H(s$<&b16 zI3#6QDpH@4Zi#(LnqC0BTACR!DxBPim=WaN@m59O8*W7o(`#ja5l0OX@8y=%Tgp0I zPuTMv3BVGDZ%Cl1jASq|3a-$f-H(|%si1g=WX6hdY-rMa`sGRUCRIIY-+&c*DnA1f zP6FbZOh9HeA|g_$H?J&XOH-X(+VWD^G0%_uUwB!fS~j_FGqvDJ7Kv&%)+R%K?ekI1LD3ha+R4>-kiAw7(QOGpkN-lB zDhr7f;P{r{;Mw_ulxF8KhI$75JQ4fn{)xb~!angG920QQ0Gf|D+0S5er*IyHnA^$c zL!pJh!iG-Gp0qzCycLDF5T8`?7IqSj)N9{M&c+dORnW~g;AvOk z|B>&oWAAwjPqlx7m^-=!-j10n-q>0ORNUk?g@?}cXrhiy*JnEZ2hUHg&;ZdFUYgPM zcErUhQiO-3i5mSeVjW)Sr&(>c3A57VNJE(^Lamf2=wsr2qq>v9BWT`;|HhkZ((SN1 z5ZUJ%Ji#sSg@0#+{vG3l;ICcZ2fvC@&_CK3YUPn|U%Y|yHc&R=0AIpUgJU{5LN7TE z$3MTJq>MNwfnLNp@yCf8Q^D!GucQ5quotM=UUB}FXG&GR5pj`Z@KEM4z{Know_kR0 z*|6S!JM85A;wvM>H(RK3R6GyuVic=;du|zGRcAh7x8gnb`|Xtv!lQSceRfqu%bCT| z9Boluct$%SibIM<+BPD_hSZIUmeN#a+wI7F67QJ~$wS3YpErH}di#@hh%=o=Atj%4!cmbtel`JnYTY}GKwY%EGPBqQFT4?@aPc(N*6 z7DH}q4ryA_YSb-p1B>Wn;RWRL)B>yLMQ96jW~zBad}xGfAH$NIpaj4DGmMTKq8NfE z@*XO$)2C_?MV+*90z>@~)aDEK(QKSw`GbW4@6-{$7&X2VH6{}Hki>^74?dB8$c#M+=d)qu?DeEJg;-tw=|1WHn}$vOh^Kp=CHuj$KF+P6YCV zdxP;6G`H5S$d2sUkoIJn!I9#GM9$q1r-x{Z!fX_%5gJIFN}L7ch+ATbeHW26Bho@ak5_yz zphhabp!4d2W&XWS&J`NyDTC9qqu*1o%m_~1zP+aYCFc93?e1}8gprGf3b?s_os zNY$Xr1q9h`WIs;MH$&IjFQ%Q-vNJ40_CE3Ol^O7OCijfzUg2k0U~Ry6|Bk!iZ$_W1 zX1Bnzw@=)Ag~*fYb3=ALbjXWgAxswhBZK^lj@>Kk?U(r%9F|q}_VawWhD|qXh`dU{ z-R@0tT@z5(r%_j*-C_S1?~>nSJrI&Npr60xH#l7Q{g?ci)fNvjjBQl3NcO++YvnQU z&yfTC8ixzd`Is-gYQR|N6TiL!-RnjL^wDRyVs_j=c9$mNViIa^Q;X|-as>Gt2-uTLDl zLfWrSwB9VcPaM1wZk2`XBWJ_UUHAKEzu*aW`MDj)wPSdwPki9Y0#=DuTz0m?aRzTy z1q9ID(9&jX42gpyl6^WqSN1cQ&9jc((45X9z1v87*MUBd+}I~xysSgNIZ&@(F0VjM zreBflI`rcL^vZ;hY<{}Kg5Ra1TnjYjd;{!IC^wp);y8m=PU0s!cHxxf+FXVz07Za)!u3he-#~AG+ClGv-T|!zy#%@)H1{S& z;rQ?I4D}Xh2j~Tq{WOlxg64r{f+mCVKx07AEMdJ%b3|d~-QHy>x0J1c^r3+CVXnL( z-VN={*s|K1&o!x#JfBf3j+!7XDtPigsc^GK1>7_4z_2~?deLL=0z=r1Ik$|&safua z1m=T3asj&%_qJn20RN&kSk>Oez=qv`>`lP6J7pjo%uIIdH$-YA0U1q@yn=dvkCM7S zo1rd#8D1MEa7rp01bk`e36xginV^6kfI(ch%A06~q{C}4{`K;It*rS`$^T8j$sH^F z1G<1utY}NnHP9Xq!QLpsZ@}xZv!!x5FOa}9Cs$-6bNgtn%{j(pV;4SkHx7|$CW#a9nn zFoOrbdpHR`pv2o~Y=53`5LWEi@hQF)8I@P7ZIHE~lP-W?;Dhk7jo}l3M0wSxbLcCH zmyrdvU5|GxzFJ}#5eI?%8IFHgr&CcKpx4J?PJsRZno44-XGgJ$JtdI9{9+z_YaAZB zHL9EV{}7z`Uh$WUXemglcBpFM3jasD_?i_0$IXU1IXIus-_5_eQA9S;z!V zHIeasS{iPcRW)lqu6Hx+E3WX!eiHIzZL+e}i0r=Qh&3a*e5v-$Y)3b;!?Go?V28wq zLYrAH5EA>~4c_9Z0UzxX-#%A|{ebL$5URm(y0nG$OfOg{EYS7 zNSqKN9&y-#{L1jr6?7Wu)qZFAJ$p4O%8WgZ;bkQ?8gbrNcOs4k@3k8Fk7k2 zKr`@NBKK<8M4|i=YpOF*nIqyZX(Idd?b9F&_lo@&ktK*Xqs^D2&1>a0|IK$_4L*uPlJae3CF# zGIW!YwYZZgoWD5R)FOLmP~$Hl+gP5kN22m05#_0eb!S0$WFe_j@?t96=c6VlP7)2D z4%%44C8?eRYFSS+n@YcXJ_979Dcp1HKd%+5@4fqG}+-1)s_&dOF4P0{w-}lR-k;nlt-m%@~_=OVdQ5lZVm(tU*&-fg?x(GF0 zBo*WT0%^89L+)~x0$FwzcZ<87#7$15Eo)r2I%dh3)yRso-7kJLycSt5nUmAF$Z?v0 zGKuH`paTwR*k`atR1Iof;qfBx-nq|#omwF8pNHVPIER0*JFIJKhWE(d2Uf()@aD>& z-oPGm3cnvMeIwX_zSp8u;+gXZyxtRq=@&~)ZyJ%)21sDV;ClX$`jb3QYMB)ye5|1N zAMVZ-`iYIynaviVj9W(0wn!t#(S93zqJ zo2i~(R4Qt2IzwfG#(*Bh^=i-^zygVZ`ox6uchVT@D5IiUaeNF^1|mFfRr!0@>GiAT z#b7k9tk_dS=7W~o(3o1k8aW5=lY2`uG%QXH?&UMg!@$HiExm9Mdp%hL7l}IyL+*UD zQ|Y~1{_ej=#&j;L>=i%ybwz%fZ)sT(-jYhYAs+Kv7c03trF5#OJ8Iwtqd=^5ugIMv z5#ht)MVV|*iDjfkkG%ICafe$=kFT#rUu0Ln-!}&+R z12h+&XXxz_$X}CiCTRZwekP@Yf+pF1Y2KZ$_x|^JwwupeH}Y`)t=`kpIrvwcLrgCN z?nJyR4DdUtX2YH*!{SRLG}b%BBWL6aV?$*UQ$@9#*glDYAIo{4J3rNDdY|mBZO#Jr zPAP}-iza^o7ulVKl_m{uxA4~k9^9|a70w4q56%q85kz>;>xkE)GD65TO22C3h}ZmG zL1YfY9!&I6<_(B(H6HkH9A=tud?X6Jgq86n;!838bA}pJ!cWWsTzvHDKXD|wvqLx* zApX4*pKStFqW{<7-U^&Qx($F+IJe^Xm09llxlaSNyb&$Ac8F+^G>~Mp$TFDkCGuC; znx6$r?IWg%Y`SY$%nEH{&5&=0MLGzc6;Z+>W__p}Rt#C^A87PgxIegnk_r(I_O4-~ zKcKjc8ud{t>%!ZAht=LBs3am^3D3?L%fRpl`HCiSmTcwA$jlhU&Vjy8$*DR=HJ=c# zUW{wkcP}x;ZHsIFUdrI<9NlYCuSU1%TO->HK&EM^{i`mnxkp!Z{?+uToe|9qy61H} zb-I_M8}-eRI}`YJof0wi%0P5b2@6Hk&bVe}fV%MwN>T=BLHDvUfEbRQ`o_qnRb0Af zOnqJ+?Hd$J{F#nSd9BDS&#YL3d?%UnGv|?Y3-QT2GN4&f>@*7R2X(JRv{@XtjfU<5 zZKr>g+ClG(d_}RtD0BqJ%!_V`YFlrQPoWw|%k$hQ>4NL?{@bLe4%jKH9Q&#H_|eA70Q2E1e~_8MdiF8>U8NU03<9muv%VW!gByJ+@= zSbc>^s1YaKIA3|0NW3S+{7X^YR13j$7!8E4u&(b+7dSsMmQ5>L^8Pf`k@WjLkevEL z(}9XOMXs4q@M4__h$rMMWJSLDy!vfr3$?9;W!fsxZf8SE>vSK}k|=EXRclrHCUNnC zHb%)Szc1npf+5C)oG+A3)ds(z9`!rp+0k6QPt7ktmIZ~ck*k>#>5YTG!3|%eS<#HR zIUu`hyA*9IXQ`9Iz7@JNKH`J2_el<%$_8d320g72qMQI64bH~8qAkqNBGcJ zjkEWM?~&&%@e%$lf;tU3&t0?mY?!=_f?~ z67@-3g|U@zVX93DJ)?&2M4ox2Z)rD&{6tzWB!;}}z9@bP_j;+$i*NChSQ7Q71t-31 z*zQ!L?m%LZb6mcP^1A>yW?J4wdvwy}fAQLSQ&Jr#)GD#e`bhMYjw zl|8UcCkZ+~kv7QLz9ENfy(jVxykXhMc_+jb7wIew){IEr$?ZqIN>KZhD`r^nUEGkk z&QE1!KV~>sgKe0|>!0F#WL+w${01CB z)dby<%oApTn~Y*BnggO2aaEMntWDRqgYUuQ7r@f^3mb&0&15 z?jw*?cLHl4?VNKBIh~hq3+L$NR?qpp)n5-BkeCkD%`v0rbswmaD``=K@?~ac)IhGD zjG72ok0Ie(%F&vS1J7kQu&y2G0Cm|auxG}IC97M&PB+gceXr6X z-yGUy$DlabuR@Qv1t_!{HNMbiL_a117k z=Xf*mtDEO^3t7bv-MosE*Yr<=L~x&r&%?tQB zG<=QM#kE-HDBbN+gaNzSfkz{>TojNtmv%0zyA+i{|&jnn0p0rv+8~BSc4FCU(|^LAnSYHRiGM$a$fg zp(;|sGJ$a~X)`ijqF@1IR@n$1njl=BVuUZ~u0N!%Lu}NO-xG9~wZ7W=)j2bL+a-nU z;a}vV^OfF?dADN5=JNq@t7K=VoJk|OjOfFABjD3OQ0vU#BJuE0$QA05k09Q&1HBu~ zYoN0VAYQ>J+#iU6G#n6Ll;DGERrmi1pIg}L;^Y9G5p#xc0d0Vp@)7ue&!>TQ+!Zs* z_fSr}?=ST)b)&vjB>I&0T@xP*k_?VvbQ;pLgfe_&??Y+n!tR09F$`)>!MpXr7^9cY z*LcnKk61B>>tnm=TS-Zz7UdGbvRCv!fLeTVmfWRpRmf$;j6;w8O3I-d@ARDzA3YZj z{U@<7pAg@_NM#fwc4gt5ncg>6(#U`eKlU7>Jj(KYlla>ut3i(zM88S|LFYmEa@>I@ zB=OIiw$@MVCLZtjj;z_Fe65&yx-{1LE_MVqvdE0$p)!)O%Op`Q$ubJ?b>xpv z;OVx;(nv3PcJ9Su;0=<`8H~oo5@V1M_skUHj3TRq1Ml&tA<~{y?svX49zB5=D>M9z z>B8_RxhD2Qe#{l_#oJmuB&+ImagtxlS7YrtAr4Rt z+M=Z5lc9q&GSo&;At(-X8o8kiIPS->7j%(a1Dg<>0c}BXCH41Z$ND1W{lqq4f$1E{ z;9~W#l7Bk{)Er!q^TR_*-pIzH79U?gY^eyj3Y37deu6Ab_>DDf2l5bVJ1Iy=FI=vh zSLaxdy$Hq4u3wcC?XTui$X-w4}wOob!9UE9-Pj%!miG8dlKq?D?UEs`<~5uSBir01I0 zJ3Ng`_MrA@!{U?3N2rFEpjt3cYIxm2n$f8Rty(u=R_3yutg?w|R5h!&X?EVmzrJ$G zoNDhcTw*uLcNfDif9|%_Yru01?|#R|?85jrM{dTfBuFdQzKd(8aug@|m77Z^`{Lzu z*Q)1BC-|mw{T?d48hWt;_~@(JM+tL>>$)|q$R%yl^M;n+G00uRV#KXaPp;AHY|vp5vnNN_8siei6{I`#8i|f|e z0wN3hURb}SyUtKI60mm!MSjRo=WrzN{V|T@z30gBKy&6PK3I-En6x@-aiZamSl|D^N=U&-H4L4M)o{qA;=Nkt|*`x8EFN2>mS3Px$9E* zySlDZ4+1}CkaF&Kk<2d%$jwuHwP2;Sa>9IV&m!mx_cyFV>5)34aJxi2@+Er?-?55F zE<>UhQBIqY*T?CegeTrM@~jlwxCA*ES15}yrfy?*uS^nt30+`6c4M3>V^dyV2`w>+ z&5wBRLPQi+><9;X=){NvYfYB)J$T9!oP_u+vQPQiHw5dH6&(Dx_<4(9{y(t`1?pnT zG{{i-d&6>=4sA6OkGym@=^GqL+r^A|y34_F9wpX+NMA|)1KANigQS?C>qa(@7_3$i z#_nrkT!6e&l~7#rpio>I5Z4V+S)15`@`>_J(>LbS7$Upb9FtkPNwHnBD;p~aFO}Cl zJ=U@^&v>-o80?G89`zFmk^)(8r+XFo5s=d@!h0bDG|u(*DBg>mOf>BFWPQFS&W3D~ zBXq*9pDuIWLGkfWD!-5=8n#$(j?j*Lc8ghs(*|wTJ`JKmuYnu|%ckBgSC=zyz#0MCX_wDP<|jODOhEj4xESr*cBu$DN9I_*tW``B)*`n#m6arX6`aBki7$Z1 zkZ(P6sS5V%U6Af~HI6IakND9cJH0KH&y;_4E5`b#fm9wAHQPz79Eiq(bbSYSKz0p1 zum~txi*cPM5!pfq`3{yD%3m<=i&u0#>tI1Ba0}Qn_7WPrl zpukX@aXf|Nb2x4RJq!9ft{=wnVH{Z;i4RICj>0~YzX}-##JbCJex})o=Byg;8!cO8 z5(G1ofl-twobjvKE~2?D%#wGgR*c;*hB>UQ8a6*$3EamC&=4!&2YEci%qBHmggPb? zd}Ku6lQXA30;@wn?83e_B*%pVNfkH&u!lgG^4BY5u3jsNpC>`~(6D585?2`z9}7Hy zaRmJn@}nVUJxI0EZA4mp3H^=O&QLMR7&}q~D=kx=gZ7<`J;blT*dNBeR-w>P6AbW? z0*wO^+n`BaFHDu!#U;`@`)JsK8w4ej!ktkkR{%Fxz1D7W>W)OzvWl#(=h7WIMu{zyc1%1&5b}mmY>xd ze%47&=_xL)oBKGvTeq)?U?d$$!OS=zzIi?$eyVHgC}`%0B=#H3bOfS zb9xk;UKib+%F?`T%8k7`%OC2c8RJz$>erWka zyC3@LA<{}m!g;i+6p#=L=RJ!(WbxHe1*(CIi2F_y-p0Osv3G}b(N>#tJ8;Pjh+H=+ zz<0JW17@6C6^ce=yGOaqK#>A+(zc8;f|ve;9k`B|QytJhO#dDkO^|Vfx-ag6T92G0 zI^;CDZ!|JMl_M(%GMT)Sd_kviT+pkL$K<&ruMY>NG@|4zy5?$=R5JjaR~`MQfouQ=THR9)sd~=z9`{`7-Xquh1F)e3qf^ ziXwAGtfDdrmJ-ouJGn#Bx#|OuOtJ%S!+NuaodEQpERN*Ky8}A@Yg`@YkW^HKbFXt6 zdsMQ^mb%g2G-PO2TsTO1p-XvnPJ~a%J&?!AP=U*qyt8;{<0aB0R2Iq<}Z`y^rlJ&Q=;uZLQZGui< z6yymCxr`!;iM2MJlkB6LwF8a_?Ldo`NLIa4G0+exbDvaPw;_dib8SqS&L($~Nd1ub zVQ@ODZ%pb$yoaq12#Wto35k1xz3?O01kJyeBHta=2|s+?Guk%ep3yL!{Z~pn?(M)m zvssCIX8C)uomyx#x1vN{V+=~PqC~4)VnZ;Zu}`w0E;chMF$%waJg9BgwIWLWfTCI1 z6w&TtnPyd^zCEVg#;!r0EUM!hSU;11KSJ~+2LsvM=r%{H)tN5G9b1G$Lt}30jq3M= zWtAU)VW@BP;r3ZRZy(0{X0(qB2$)LFiJqU-95rCo`o*N-u^-%3RtjD4EwElC3MYa@ z%c-zN4Ini&*34>48t$e9)Saq#FbA4T*@$-*%INf{m5dOYD0~`>cum{-v2Ke_(;l(y zHJ!Rm+t{R2wP;@6tkb=wZu(fKYSwMbB9rx_SikijYPYq4{ZcqCD}VJ!CMlqH=2JE|FhXAu?Maa zMro6T1^z0*Uu}U9@^Q{q`K=W>$Gt^6uOR#ACS^*O2 zZt&C#etRVG5UcFRjO~{i4gC^t-jcGp^r^i?Jzq-asK@{_s2)eMvd|fjZfDc{o0MYe zuF^o?$I=$_$5JnTb&m3-jP-8}Qi14!X&z!505%D$;NR3LX3;!qF=SC^LS*AAor|GAUXw^9KnF1~XjP)&8flYGlRo-3$G>TD}*>4E&) z7u~u|_XPTKN8lV6)yN@^Gh&-0HU=VE;gH!hszo(mR3_~qvoo=sX^h936W@~1u4+=t z=Q-t?CZGtl#MSO;EFKt2OC>fkH<6DR_4&^X?}(f=bu-G?KQ&vt=F5UiI3 zcDyhO@)tqhg$$KEBz6F)cu4$Un5`qSkOuL9WbAD!|FCOQ zcb=A{rsLx9rS%wZ#JkcDY>#zS>*uepU>bk(l2J9^4e6|mjYtb2ZcFP?H{OBk5>|`r zPjRhjoR8~i@-^a)J=#VV*9EKwpTCFeh{juaRV%TZ>u~2y+|e~o=Kml|Tcpf(+|f7Y z^2_BrYTVg|JCTj){5|p=@~h`?C#o@pU;6u<2Hc5mjOAnByHmbLp7uEI#Q>pgk$gvm zJNFYD@y6Kq8sNLev?U7Af>>K%Z5RctP&Mq7<&b@%Uy152gH}GKMceH_I}jbmTq6HB zDw^2x2Fn_IY$vrNNtouh<6C*08?&@jo~7jf0yg&TBw?duKxt%ut$i(~`&R4|B3_N| zCi{#?luC4bQ7H8mlp6aUcyZG-xm@g;keMb)i1bf!EC9C}4_>rP(xIeDC`pfBOq72? zHCfpPiw&a-ylQAXJ3;<7m6;^WkxpXA@Ixx>>rVCib;!avUU(~%n>XYuz?chXCyj*# zij29Jf|KMiM{HV=Z$jSJGE}(+d<@5ppe-O4Gz&BplncrPnLu$Mz$#PcKs=}y}g3)2$k~svx$5H$ojam*n$TLOjlc^7+dl^GenAO%IdrG=-cve_B3& zKGcEpE%N!(As*+?%jX+H&q$^w+XVIZs_TEMOCPhCO#^>%juc}aA$X%O5g4*`t0NU0 z%(}ln9FrXXzxc}35kK?;VOgs82VgU(8OjVkv2;X9wSjiw-V2~++1D@Ni)v6jI5hj}q*?>)xcWwI&lvWQrUvV~N*i%Z*PbkA z2>@16qprn|nDho#zbipdX!PEQcFad;ob!;IfnX*DK{3K2MHyrQRphAqZ!hz zi8_+3GcJ+8QDpuid5O!y9ZuE`te}my!EqX|&R& zoIMv$o_$qKuf?-#QGy?N!EHC6d@xx%hWzrl`1J+yOejMZkXlsYnGQT>i?IezBIjQv zx4FnCi||Rc{E2aSue1!$s4=H=8;vKEjVpD={@=f|Ed1-`~_ASdvIZpGxll{w! zVTly69ue)!hQS9vsKS1rkF|6Y8_PA(5d4L-S@dIbV!h7QMeu!lV`!FR6!vo=@$KOB zvsf2~=2e&xbK>H1)0BLLd~Qoi7M=)^h@HrmSj-2~>PC|Hp!nW7O0T{(B$h+#Lyr9; zA@P|YH9>hYX&^L}LbjcWT%3@gReBxJTO$_yEaFu2IVB@hQY!2Uy-KTwgYG7)j5>#e8X(Ptb7r79?GGFry3qW#<>iv4ENUR z`1=u;pH`kOdzGg-mec(U@R%e!chp!rXAap}Q^;rE@!`{h4Jrpu;_5me z3tW6HEMp!x1HZ+GmDIf|hWY~bjNVfWl1Wk2*{h*YALtX%IUf0}LI1${8=yT`LLnP? z=+uEw=r$1c@S!r$Js=mT4(NiGd1)2v;T>~t?Hjdba9|DpXb$p&qH6ECDRC))OzM^&oZPP%{x8=%iCtAetaJHi747U+>_%lw|FFMFO z7yLBl@U9_B_Ke9mun;m&Qd<~f$&9^f@=aO#AE@g)pf5mVJ;Hi`QDJ}`=E))2oGg4Z z0^E>ZqJt_bd%3Hql6gPuYXX}?^C)3cz{aKudSvudbsiHxKEH=s3BU0PC;`69!{f_T zEyu;fh*yAp2gthP!Pl{Gz<;uLNEF@~o?#*1*nfEjB9@MeA6+)$ol>t9!PYthXDL^7 zY@Wv~M_MEb+lQ5~1C!sqG^~C_^ICS~J9|evR%9X~DWJT1OJrQ6_SLceXM?Ihv^Xo0 zdUAQ`KrsG zkgMxcw4@4C{cjE=&`PYOoH4;NR`@VLI76avHsFUXg;hHH9dKjD1D8AUZ zdl@}3ieO%3&P3eXe>1PC%a+xQ!${eBDV?K{r%!od6NOlg7KSR8$1;`1a1orIhbN01 zF+fk8NwTnDzH2>3=mXzawq@Do(kotamr9?B*fh#)Od&Fmtl5KhkH*|I*4NE_zn{D( z!D%Acx<54)5lZ1ZAl>W8(-rWeNuvv9 zg7<{;#%%7My=>*O=2GFeXG1efr8NU74|ybE%|8Qg87H?%r8stmqs&|8)^hD?)zJ=a zrbQG#lnC}vIQ}7QuLZin2HK}LTd)VD<4872Dh`U`v1O*3R-DW-=(N8!$)vb_9;X(*U30R@Ai>)8dqV;AUe5su3CVHLSp=pmm~>Pc-f^83r9#@g7bP`;p@xpH4(bVlzu3hR;0p$-IP-q#lE@lcT>kwLKywEfh z##bjfHk|J9!gE6;zUQ*!LDR z81{L#g;frOCMO}|dnS(v^+tW$G&aujEM&vQu$@q82|~AotH#5gRjIm`Egs@sqC1w) zKAgI}RP|k)M4J-XjoG4?p85W0fq2*43fuOqG3;BVC%&T)FCF%IC(nz7Ki&6|6~4o{ z;B~TvOFOl`02(O@-XG6MRD%W4bL5E)($u;d8QELuwbpMW@uQQIJoIFG$}eYULbn|* z6S!n)YGA_{X_`M^{1E(t%JKWgSt8~g7uQ`_Z-2+Fys(i$?mpJd9TQ);V)W#)neYX? zaZ~?){y1spYbA6x-MEFdeP4Cnr6CCDn6-$h$m4)sImv&FN}tBYI~DK4-wAkgXG8x3 z4K&HR5faY;ABX1ikujFzTzJB=Dzc8r0N(+g6!IF+s+fgX+LjuIQ^6wvSgSUDH$jL>t*7!6dK6j8toyhVH@*63 z+zEU2(I3X-#RJxbBkQluM)HWtf@$xZomB&TL`E~Z%l^ADg;P4h}cxE69zTC%<0osUuC%&53ebg+hV$ky8t;cEb zwi`TFJn!%YgKY@7FnG_2HYdYwLM#J?Umrt$AEG^gk3Tq?_2#_Yg!)+Jx<|5PJa|Hz zfn%~*di4o2W=7TZnt^NWzc(0 zlu=s{2_Pc3)Fw6y9tjcVYb#@c@q3iAu%%;`II9L5me;wji)p~ULUtNoue1f2k9}Sp zW)j_Du2Yy3gefDs0a~Zw)&1E*7qSFW*#vKk(uL8tUTA{er7=9;9>=-)NSJ>v!?_08 zYE)%w5yMI~k5AL48wE+uzcyhw6k4>Fj58A9KO{~YzSmP|9)cY*ri}D9zMme&ZE~ud zTIXh$Ue;^9>+E!!yRniNlen2q7dTtR0vVGw#ntazEcfY~sK<8D8jxY%FXDYzV@TVb zmR2{6t|IZG1iPRK_HSaTrl%s#7#=-GMeU_j=#8_5JA-5SY~fb;G-z{DzymQCZEE;3 z27L5rivT|ajK^amlh`@Lm$Km(<3EfKbIhc-opjbrmiT;QG@ZpN^6clCO6mZ}u^mn;8zDzSIWiVt2DXw_XgO_`#21IQOHSKn&r!7es%|G|08c42lyy_UEdVwT z;&&5-$AG$xH4fJZSOH(lc!|6pL7XC?H{1p(Aes9TSj&f92K2)Akx8qJPGY701{&oI zS#Gd301>$Ou%xX%jJ#B2rF<7<4|>Dpe~x41N2jI21M&MJE0}lJ+80So4!u2Gvr}%m z@RW;gHzM|zU;@652&PZZnTi$2j70U2_pzg_x_z<8V@dia%ew({!N?v&H1a}^g5YFe zUPNJyBeSCPlMOjp$V#>WC}AbTi11?L%B|4%5KPE)wVF*nW;I5a8=w~@IFnP1vHY5D zl$4(1LB@0W?%N^6D&IVRGo(f@Q(56$#}W4^sTAaTiwB(oGCSdK6$6D1{8ht96zqU9TXmX{dFI~=6UW|uqVd}^ssjz{>%+}(&mwm6Vdb{*Q4>M4x zOs`F^{ZDNUxF0!BK`dSpc6>nj{*q}L4RQW+8xJv-6bZU>qluc!8%XHqN;WOM=!b{Dft?2Dq|TKG;w$1S*J2cB5Da4M z^LsIF`(4)-01%R@%nx-^rM@s;AYqy&3w=fZ&HdpT~lvDazPj^Wd}BOYV@0nat}64O=Jafym8o1;LDvV~^? z2)j|JOeD_ZAugCU{6JyZOB>_?`+Fy(9-)YfWcCNc1AM`A2YC$P;+ha(rI5 zuVj7+V!KKziTBTFIkU3f_a#^ES?Z2Q&S5h_!O2k|8v$)tiPkz6#GaW0?{=cKPA+j{ zzo1{@x(n9EK6gLX+8=yz1509JPqw)0J!9NdUfe07^9TMY^h=agf67|%ps<`K)`dQ2 z4SE$TdfgJ&OgvOYwO8BMx4Zk~p-*uo&dfPqz zjl(r{B>RE3uQ;rmq3-cF1V0;4#VC45VPE(kAJGM1TyZt-1*X!}KIambGEdW5(V4XRb3ekTPfD=gVhf3t!h}~xtONetMwkls45^q+2}n9$TL7j z$hz+_kIyWUu@HORb4{mRbIK8E8NJ3H?@ou`bt3#g6)|JHZCm>|YFu#lY`u)didqYJs83S4u}9eJs{9r4e7@FWJ7h-SkC5+(2v zIL8lC191Gll^UqA@I~(T46XlUeTiU*Y%YBkTs+?U@niIOgO7|;vaWpm|5{gwR#V~r z*rjp7z8biN=(*C#eu&Ca3bgu99>x1~s|~*2n16w4kKt`ydaMz0f>bnvmZs*~u!@Wi z#vl^P1Zywe{$}>kvBFXygOK%#e)d!(Ew`JiF`mO3GCn}| z8*82pKgV&CClwutmft+G*nD%<(c`*i6$36856ubDWRThu4s0v_Rw^t;ybiFH$-FV4 zteXEpd7wJ*cl!YqOQcF7Z;>^u(sam0oGhp5wBD3#44)os@aD zsl!!^8ut0?$pxopR|>`zTA|4GUr zk@8)V85zw0Z3X?>cQPL#?-f&Fz)F~m=+*EV7&V{xhVONcN={m=;jJind(i5978x8= z>;#UQaNWlg?#jK4GFZ9RZ*C6Png0j$ypVZqka_hL%$~J&WK_`qCh;yOI?$#hVFox> zNX!QI4v}~nNWA2It5HS;cR*v<=jhRMA7XwnzA!@a@sI|X+Y5nRG|8{HO7b3mgPJ$| zs-!l6Q2#2m`PnYT2Ug*JNUlY!vC@dO_o(>5ugeS9+nvxA-3d*U1H03f^D`_BIBv&r zGxSvIfU)J6=syoz<0D&Hf;3iuPoFxURZXdu-kRsOg2NKE3Wc@kFtUMZtEj^7N4YBmS`2iBJy?h|BCQ2?RRD!d({cr|N- zym1NbiSJT|fpyAVrSx}M>@`@^T7W<)Y~(hD+qUBnd=7C=`pZ^Pfc{dj#>KXIO61-F zvbllmomB-?dg;}eI@JIj9bG@F{(VFhC3a8G)A$&EdOjpcMBij~*O(|d4(GZjlVsD* zqO%guAAQ`^^EiA{)X=_@?Bw*68SK4ttUjQpExXS|f!Jm@+{lF|LIaRl2z6#J!NA$Gb@!%>)=mLZJ*P8RICTm&$(_2 zy!ojE%)1MqlU8zVZu_=fF67Q_BeRJ3a37MMq7F%042Pr_s+BFbarFPg*PFmaRj>c! zpEEl!!XT(DBM$qp$>54RA|62yFs;DsHdwa~<-Jnf3ioj-t-Lo7>#}%@tb4y`R!p{$ z7PwTlT$^zzT)LfX!K7?3?Hrh4=Kp@qSl{3B{r&az;hdQ{>t}tI_w#;Qnip)98yL-} z3^C-DJ<;(08`-*|PT7ujY%rbp#SyjC7B&w@*`hpJ|NK_gf~#2Qd5dsex{sA_ty!SN zi*G-I81oy?TaJB_-%@CcImp@rTy$_g{k<(hEr~o(<hQ z8rw$x`OZf4g1>CKeW6^WYp6mtaOv?W$8-p5@eP5PZPy24(XRni-~ z8gq@@?;Sf1%nAC|u#TH#gW1rXSlbiJuo91zkH(Hfgh)u+Ux6VA>q?wBS_GQ2$IzT5 z*b=#>W$?lIk+XPSLa3ODh~oVXDD5bn8xe0nvBY6}4UH55c2S`7o-RB(kQi?4&WF`| z{N*bTat(|5eS)r8wbRi0Z&(10lcPN6!GHNB_8%=g;?@CaKQ2Hz;tTLtXw0fC(psT8 zU}jq{j|1k&ELK4l2x5*BJm8vFJic%J>HM1vZ9%@?M_~h4hc-z$tYK5IjX^1^P_q-? zs@Z2KM^I?&>S0CUEVRx{f*d+{A*596(ddA}uMH7LJH_=!bec2yurFoe-jRV9YgzU$ zK=*q#J=3l9mj%g-Qpy~V;v)DJ)k!6z1$$M}A~w(wvc9Mo{>KMuqdb2OB%lwTlD8_E zO{U~&Z60O6S69CJIM~Oa4}$Ro1x@B@JoB(i(?JhILc5ZTChF{ReTjA4w5gtM0mMFh2bqsAN;^LE#xdyn6K$gyWx=)zn6yP_tq3%H586_GYlhTCVMWaO^x}M8foQH_WY zS$fH<0k1?RrMUL^luSm_9?l-toBR+>o*e)Efhrwkmm0qM_y zAWMN?iuc#OI~%r8s(vSNFb4V_FH2%YQvXXZ~2F~Xfz)E0s z#w#d*3Ao`f|2!{trgK&j zEWtNd0he=1+W+&>SY|1?=D0tmt^ik!5BQ}|faCIPW8GKRXjsqJ>KkhbjrNY;Wvc9Q zJ^XNf>1El$|Nr@So6x3f{s;fA&ecxrwgoI(g#SKQyc3)oD#p1uONN+yjol9pe{GFD z*U6!hY59>kI_V9aB+b6Arc{n zu29zIO1#gFI-hG(daA9Ma0$ag2Kdt`Unc1mQvyL-SqA!VgpgmWAFvq;=4)LYu#j1i z>*Pb(#HQh2=7>y{8ujJ)oP#24-dCsZA z3L#5dfslO^(hJ6}B4d+n!^R$k*V~HTJi^Q1L4zHZ&SRW#0(|S-uwKdOL{IpgVtr%X z4XcCi;}F&CyRU+C)YOG~ek$gW-BoGA0BXwv`>rg#I5eYP!&5}z`udx@BJj<9L%M-H zE+T0>`oO*`qP+;UHViwCme-*@JK?YYe~r=yZ?x$DIZ9QoDX^P=jmWQAiE*A6ybpI- zocUmb2}lFO8eBb(*WlT=fs4#yX@?}^6u!1UD7;{QKq&MWx%=%gIGX0xbHjJrgLbI@ z$j!`RKOr|4_@zw>Q*Th_f3qGO#qW?Fq$_3co1c=mSCSQKW8gP$a^1V5@w@4bxU%D5 z|KN6kQFo`hfonrsC}T5GP&IC^<$*U=wVtY7013r<33Hv31JAvxRoBr_qi)u;Xj=nP zE_4pQm4oDBLH@LGSd$=4w4SRuTN|rb-I3qOR}7ENzDIuVTNQ2mw$63sT8s~_v5{X} z0z|B(4zUtn$_4G(CYD+7%W21w1THhAe~STm0F_Z-JP(icI@CZ@q=&!4+K>1#fENrmwH41 zv2<{|iV(lpX?@7(4ygfgA#F50l+PYd1}PqwrVQDPE+Rivd>zYYUC|eS1pOCw5ZE9zL={4oe-K`Y~0UkAQAM}mCc@03mKMh}Ecr=|u zn!zb~HxMP!-I^pr(ownHQY@ID1$_a(MH6%s(uF#~2Y}pbr6YkoXsa44oRLj)cXSa? zq`LM#XVC7(MHt*heB+l+`&5uv-j_|0$j&TSaV=*+4=so^9t}8)%Z8^s7;L-0;JWuh zJ}br+{G$tXcpCC1LWd?#`9wmp(EX{6KYt*on~W_hhHe6`msAyI#;q7LabO!2diGSK z)oi1MSivTIR{JPCNi1~@{8={SsGS!-(GFJgwUO{Brz5AGW-3`be?2pymL(5YovGAJ zWI01r1$=AlTnF@kbt%ix37m}?ea^H5B}>3WAXzDU&ANi=mE#tNaC|tg1m>%$a4_s zsu7n6QC-IAPZSQF1cz~26g-I`@FMD5s;mTF)qQb2c@8f=)t*T^bsoWg7?~gf3R+$ ztwCEvd@kDIH~Sm;kX~4?%Cfjv+P@y^6J`suAO|cJ^LVm~YS5?Z19gQX6S3O<@V&6- z3Cg1wunoji2;jJZ1r^yt?Z%1ZGrQ&<0Ui}K5D0|P(BL`Lki4mG={d^r46~KzAnec> ze%YeiFq(Dz-YPfzguSw+0r8Fuo?8YRgZK3T7E1gwT&RlhCCQjR81|_ykELwko31fh4tl#>?j~~)$zLEc#P~-vptw+Z20_*R?SA& zs#)e2z(hMW>|>NSQB2^?18yWkb1u=t=AM)+S5%m*BR$FBc{83%hpj>_!~pfN3R1ns zrB*x~;9tUw!@65OCs|IeurAC{*j=AQ>qZD~Ba7L=8kSXf?kl;$0Y(kQPQjc1Qv*FJ zWJ7HypMurYRM3lYLRp;DV6bHoqmh@1ayyN5(I<_IaAgM93Z^@g;&Bue;Mu63bp-IK z;H0$fCyJIeU?qJ`Xq^AWd5S_b_pGVG*fZ4$80$4QKHc-~@Gv;uf_O6;>zDuhyX-TU zC4wtZL3EE=h*{EfRDRI}8-p;0=V}hy6QGBdX*dz<^56{N1$Ycu3fWUXkUI)+56kO! zjS}|P2(=bqGl^io85- z^1VuZ#v84&O&*r!28f@+_U?&41>g0rX99s+e+dMhIvogPp8*aSWeUn-6we#krA>G? z;D{DBL+;BgjzpF(m%QJm&f+d~+SFoFqC@U9Ic=#GsU;hst?T=@=+s%Cb|)pX{G z#rK+{JP!xBm&cWiD_>o-0sL&bflmE&$WHeKSa#C+oEUX>FLXl9mr2RG0VjJ*##OU} z=fh4WMwj?;)$snU$kbPv$W4gyR0K?Arjm8|HhQ2_MOZ67Frt`)ycUqg$gFz;-iu_H zx>u2xu?oH@*gwS6YBmXv#uainMer6M!+%ijV(IfV8Q%@nU(O0Uj;O!b~~-^$1Ksva(%3z?%k6w zEAxB>O9JoJrhjzGXvuKQ_Y=j;8!;1eZlI?N4&IhE*8QOQk@`f;;M_z+4`KaSPJC6g z4?kNjVFJ>*^g|eTziIJxT_khdZtVka{&M&#xG7pO7c%_9gAc)W%_VVDCPKPD?hZY; zOp!Z|v&R3vZXWh~G_tCPn-EqX=H&7`eOn8)F4f+X(y!p#>$$qiu?V&yH*(n_A9-Mh zxVJF$B+h|FNqMe3c!sl(%RTFAU(t=LZv~>5A_qr^bIm&-WkDuWo?PXom^I8>NjN@x zq-XLVA;#{6*7|Ly7o7OV>kfhUB-espjT3>T=F)L&I(YThX4QlFu4j1`Y!NJ`JBwEd zhVJ{!@DVytE1flF#OOE5MY&>w9EJKCPjv*m&q3_{?jJn}e!&om@{IJTy)LW;3os{? zpdDZPp;vjgxIly$i%5gSr9gpa47#~|Fu@qPRwiq(&X|xhZftqP`!%e70rcrvYSxZ@T66z^E!k?JJ#Nw= zkH;;=+d3iB0q?^+O^&5y&_vLyPsu%&MqO1mdXkMhQ-Qi2JGP=i{q)A7@{$T=ZVDZ% z9y^(zG*yGhu62S}m=w!3g>|XhbkK7wjaAS_Oad4v)Id5uuWF)MeW<7kc5c?AYCbfu z3AOYB&=MSFz_!IgQ;hX^z_)1XLdFA4k;t{o?b0^Kf`#=vZ|49DQP%yC{p3GQ4#B!l z`GAt0%lX?8QNe{|i^+8~4*ukyZ$F1#Z-L%(j4g*|4&RPLP0 z|IrM6vXk-;z2UVxHA*I;POr6#)?tlnrFj#7v2UeW>_e`0Aunb};hs}-;7fY~*vPo9 z@%+U4JDro2kv9qBJHKbXog{%{CWHM`+&8E{Evv=+@=|bqf6J(54`Y8Xw*Q4f?Jymm z|FBPKiv>Bw;~_t0RV6@fUB?a;s!wJq^Ne$NWA^8=!O`69m^4v{8{05{qFVQR5b|}7#Ig9MZniL0$mhS1S%V~fKz#5GsRpTNG42!MceNr`cwIXAS-Vu9BZ&r10TEQwh>Wzf{&4#U!UFMS^t zL-{u8U032h3G--;k>;@!E$j)}g7R{c=bfKmQL%k4yG%WJ(-nb*<)sTt66y2=G`&fgRj!oG+uS#c%QKg_Hf4@>&B|Qro-IBKUUW_G zmdsSw*32@@#oID-Tp6dfXY%fBk!)y*%HIUkB9}Fj{>F2j2z4kJ8z=Iddj{%$D|8GM zMpIY6dt9hHnoml~5WhjB>76`xCIeTv%Y@*dq;xSI`$J0p1*s3`Xp)km#TF-B4JDkz z74Kr|q)2cLtGwY`LR?cPXhqdaYGjXCj<_F|%W4~?n50A;7f-9!q#jir$>=VIh}#Jd;02yd?) zTG=7RR?a+52d&XwRt!$YBBLs{cjdK;Lp)h3q$X2`~3iCdGjCy`PTxN1#gi z^p#%(qhdS0*%er-eDk^gJ7Ec)AXfaRa1*wp#2{Pz$NoPGmH0eDtWb_SqFiTnU=cq3 zQz!#^unYcLy7Q{QIFUHMfHlC?iPLt0@@X&5;1ZdqP5!p8U6_Y6+Hpn*BA@8n23dqf zm3el^3&a;;v7RFm&ll_r{u=mjrj-Nl;-7|ZrY(Z5?%z;E^dFF4C;qkqPa;5V?B0pPqUd5N8JlMk9BbwpYY2 zt@x$V&xt9urW^9L1??Y?GP_XCZvGT~;zn75Z8=H_%0!eDlsFUnrMYT0 z9i<=p-=c^p=TT0gbffG?X-0Vh7q9u z2Im&!I)Azo9s<~xDDM=#|IdnN4K@#)KO2S4pQW%uheIoF<{P?Zpnguv4qFzix(xYh zmO=CS^}-a?vP*WD7Mgp2Rk}k|W#+mX;4!@8@{R}eXSO^smk)Cu5h9Uc%PqZmh0C?L zvr4i`1z5!N!iUIc6~w~^(Xcyf2mAKa#@SOay6O8u=S~G%#X+ASwCv8>>wSA_%=YJ> zxF{5xjp^;1^tzKy$rl#*1%B3E1iYq;ghiCMDa=xC zS=0;fh@+kQ$#`)b@a+d`msbZZCTEqIW6-UcygTO?_X~WoNcNCfi7}pKfrc(x{oo@K zD!Z1-p)8N@ux0Y4BoBp+^mNJwk+{pXB8OFy!y64FR{>&EpQD-fJos#B9sKqVO zJ%>U*{OCQwIaANi#wdP!a6^#;d_yzp>#&;VX6+XuAaz_)yjN7+VqR;eiOtHEcxls_VyRg}dkBZ>W0{@>dx| zZYCmCjk(D3y`RtuVwRJhDjrXTD?Q1StmSEtoWFMOFCycd{_Aigd056EqSlHVR|r*O2+>Y~oP8OSHJ9<06T&;yyZ*5%PJ z@1D=6^Et?gdc0qwH+eSyu+|(Clc$e5L%K}fLb8FZDKZKtA*=ioy*0`Ee!sz><=X{E zk)dC&(Ti7gsx!ZW|DSwOt7ODTb>;HN9|}ElE=I<$mp+XBWu6WhMbsV*3q`M6ZcG%n zL+|UE$4v_5;}unA5~k2jrW?h5x8ZEY1+>i~fp;gii~QmkfAj)l6uqGt=rHLzGN1|BpiM)HiWj z@)ND!lqygYFKr!^F(_={ zK-hXPzE+77OX{l-KhfSQPq3{$Xcwx%*gDZ)dElIEW@o_2KF|EIY_>%u+R=*FkrM(D zIG!Dsh+Xz=g4JALEc3@<7xV_sV4LQd=UXA{oUd|K@@bw~J|B3~d!gr*f`{&N zXfZ}RQ?7Qx{{eKV(XjNz+Rp+-uf}T3lx)iI(-}32Jg8X`avkR1{4}s%l<*KcX(;|jkw0tT6^uP%S>Hy`P74NTz9OR1T7CJ zS#_54c_EYkS!%-yp+-Nf9eiFWhID>zS+E`n&!y-ayl!DzRV<hT`;aWj57`Kf4eey%S@i#i^*07KwdZ!@=D7cbRy3jleuvO#l->DO=Dt#|23gN)?^W`;YYV- zD$a#2A2o1@d#do_DVoh-rNlR9iO&kh=lZEuITySoj3pBC3}?p^GAl}G5enk`(p^B- z$WQHqJ(bo=vSUMTou}s??Iev_y^r{u#wz1e-Kt&PihUc3X4KDuY&r(A zJtRoSEwE#ZE{_vP>$Mrih(JFHzet(#CZ4M=;1iu>$1le0%6Ta+ZyJ9D{GhP9HDsdy zAivz8x_N8ix2KpzOExg%{wjSh5cu{Mem|u#`P1<+!?Z_fkg3m{OW)|WxIEsi>vV9#wrel-4#*EJI?8f*(Mki`L!QdT*|3NZM^;F;JpnKgLV6>HK?ydDH8d1 z=qvG_ClwxX{kc)laeR`+M;?e_X`wIFZ7iA2*Hz8s3CVg?*32ago)$iLvNI*4g*V^u z4zg||?sMkd;5|qmBCGW%Ue%RULnr|o{}XH`daPd`%4#9Li{*B7_u0puv(@Jyzr};# zuC7k_+CECmafTHeOX}e%7?whPCW~LX%@={*Z0X??n_aJMi~WLp!E(fIxnYy9KBQ)L z+;`tIBv(+D$y4$UTbL7G_O4{q58;gy5!W=+MYe0oy)o5YYA!)0yNNE%q@0W+_?>fC z*Vi0~tv85>lf=8nijaPDrvm}VA-m%fg}=C$nG5QtTcd$LxeuPZ;2g1?A(La)r}B0d z*F|3SVae&Gn2Mvah)hx;_@+nRVKGp=r^WQ{Ry^OsC|B{k3D|yytp?knr-QO#CkB7a3b&=)_uwb0c_ z;(8v}eKUB?1!Kz-lvq+dnE7jv^};8;Nfx?LiZI7|hFliRI^d2LebRn!mGc%k1QN=2 zTZfG@DaC`?`;Xw+6C8*yvC(Y*832(Kd$>(Pr2-P)?q8MRXR$hn~YsP5s@v z1o3*XVVm(Bj~|3j3S}hrZ{UvSDy*eK1aGbnNU4Db5SOG%;Zo|X1+G-onhS`k@tF0d zxd<~E<2eKlG=p=2IUVRVuXMl{Pt5Q==vDs@P8TznPX1>kC&@mrEQ)i5#Cdb=8eDH0 zJT}A9T15G2RT?$6q+`2+Z8WNMG$f$W$gx^xXscprW?^H| zcY;QoJKx;>7@~x>E18B4AzL@IUUTzK@GKiGwRXf3T5%VZFSXWywI_1mEie-JkYgiw z2iD!YIJmA1y#vh1Rh6=S6qU^{T?cL|9sdMBw$|fh^{LiX?nlfI)*p51p?R&Tzo{#W zJVLOfrotlxJ1SS*m6OG}CL$xxsIDonKvauU%3iJo22GrdPb_DyyHZ@HpidA}=A$UH z$X;$@wUX6wfym{XQ_l-pFPr?df?5c_KjX9&=S>lxkvUlW=0s@S3!wWpI4~+vSzY?KGg3fTlS#zhIh5%qYlo#jlgKe zd+r=Y4ha3bG!C{TR0jQ;&*52iq0qb-yC|-FeG$a~X~mV$uZlb>O%bfJWN&&7R-$X} zsNfi|PZYK|BP$TYf@k^Ff4Le6&w-_k`fH*L?vrsW!vmWv&5g)NiuoTLtZZ2N0hSKx zx4SCv?zm@9<8R|ms+e3p1uOXe>Ldm686iw8|2x*!4X_2S7|yGhpm>9I;0(7R2J=|M zI|Fy$z;C#L3f2#p!dL^>G>FI>#)$D^KUNJ|lapODYM1dZ6slcnaE-UYF7-lfl%2Is ztey8e?nvzp{&v0Zg_>yauAGJJ5?T6uTz%0KCdy&RId2j%b~wT!Y|~ zsu0QKleR&lUX1tN2)&2d;+^n$;qBjn*5ZGPu=FI8#o&E!!n+ou@FhqWT3JY&%w9v-b-+FidfyRL_o;?MbdYYgnn%wrg%88gxtG3pFvbIs0h z@pDZrDj1e{qT&C1X-FgKJF)VR1aXTrV z(=8<194QORHW_a!V{6{6WshSf+Ropy=vIt!mQL|o`X*XauL402gl)QvoHj*=Z%EES zDE9(WQohI~ow%~T=w(^QT++u^ys(F3MYD_ohA`j#uB0ghq%>PSX))FlW-H&$i5eajN-Z} zYIv#DIp4S;KXydbMS5lp&l8ES&j&p3Y%x>GPKHQeME!{<2TY@UX)wk0Eb1tiuJ!vZSl*31!Z@qBX%}*9efE(ta?`sN-^whSj)Rrzy)$( z(c;ob4oN{g%TMl^n4eEi0*le47wQiddfnuafFxi$71Z_g6pJ7^!@H`H&xJA@N5RrU z`L#omQatgPHl3&&b%=(@6&laSL324Xm25ZG&(Iq}) z;Isz3!~=3jIX_aYg*{7cbV-*l=V1-^fj85}ha+~qmgj6Y@l#?*F8+ge53in7Hvf`4 zPMpnK>TCH+)SoXu;(SS8%NKWZ&s>7W&z`Z=yQDWSBSYUg%3#plNBuqt=g$U$4SZAE zV0oYNRbMmeDIE3n&JGP*jQvBMi1mT(^2N(4mVnPk50D)*wp0g8*a*a3{&x%{OSHji zI|H%Zl#6bkKJIj+f=lyB_xnSv;TJ;TZ}9tc7%B90YtN1^r2yiL3&^+9I` z1Hn17V&U_FV+VI4{a4|Ixr^+LkU4VT&A1cj4zm(xa$QOTpNH~91C~(eg$>nmCQJ1k z7%Gu73r0iF_e!&dywYBuX0jFQ^e1j*E!=jwIQV`kPioj`yx*6v1>do_yae*`?#{Aw zhJK37JB8-%M_~t`_XtS6gM`eTi+ZDeXcmgP=0KlNU4Q5P<7TfkS&6Mrug}Siz!Tor zMg7$a9eBP+rPc7+&=PtT%R4+L&{lJ^rn|;xh2hBY;A6L5#6QP!PrFAd^Qlj&9^R`DJ!2{+YhXRi;HI~1 zp@JLh?#F}7Vx}>_&49YIIn`_e_$}_eq+;*A64dejk^(;)zF&{h(5GUtrBmNP+${2O z5T}Dr${JQ%N0*Io$5opIjWA!}CaG%wSvc}bE~QA}qS}fmjIq^Rel|EGjjBIVM#&4D z#ZJH3+U>Lo1<|eQvEU4BC>9>aQ#}=!{q7+?_&hZKhrh0VLwzF>%qM;CBfH@=#Sb^F zIID`{AI1qR?Y)}SwTbY|M$;J26GH`PvDY0r3sq?& z1~g%E5!;yo{U8x>Zx|=uRL^~bIw4(*9SBT|KGQ3owmsREh?=Eeb@+8TG6JeH^sZFT zt%E8dI#Y$cn{Wne&Z-KoY$xNlDJxqQpNN?62I#`f`i1+ogs@ERtSU(>Mt~(<-@jRV zMqUSfcamd7i3}}xyWC*0fwjylr4EIbs4?HEElKDLn*)~3I5@Ugj-FSYx1w*h zUShe1^ZA$sw)x4o1a?Qfr~X_vu1EYxEa@?MvSo@G;n_A!5l752D$ym``!DrHW7TPZ z)buIxvv`qnXtc#E-71g5-=*?oAbB%z_3TU3mxrau!Led2W}j8?hg_ zGYLNDSJmu;$H313`(6@C74}VUL@tcP3`pF5V9i1nnZLWbp+-?MYEtGBsdiGccc2 z=8J_~YgBL^T9=6U#sO)%pR*lb0J(#i5Cf-Hj!Z$l?-79bwtS7h29t$P@%#v{MKfaS zy2(qvZ4#bu1KyFIk?f*2Wqd~PF<6TaIar!pWVn8@zDiERxm=!0+I)pZ;)_%Vuv|VH z`ALJjN43BFU(%WAd^`&Mj=vHf|!nq5WlpwN6&UA75UVDc-p zIc_asNt7eJ)xHZke_tEOQKXuzOjr^X9zsMGd72#>+wJD#uqx$bu7$lR%L$#{eQ$jz zq}K;U@&*@p9&;=~9hpduMNGUyo@R5%`L-B-ji|;Le%L)Ebs$rqax{l^A(5MWCuNVe zaIg_soUk*4S>$PZg}5p+3Ld2G@U#M3hAcn1;G&^8v|FI;gPycPGp4a+%;cEc5YmI zZpDwi)GLn>B1*7BGF-(wtYe5Z1aGWmsh?vQm|_wgzz} zG2FyQt7k^Vdxn!KM=04SBX52A96g?!ulkNrgEVjvBTqkiG`1NuiO?8UjApRxX5(7q~ z$*@GKpdB;-E#<%`mTVGY`6DqqQ70;(c{j^>CT?Ox)^&G6>1?M}xL6g1SQl8S#+7u9 z62HNk(g4QsOKm{eA#%xRhbWp0pGb;A$J~i90 zDY)*Kz)4&JKKkf|)4JNKEJ-nf&E}UrN9M&ivAK#9KCNAW$R1*+SO+@+dR2;13`l<% z4l?{fH%9xBT*rYmcd>6s`V2ZgVWdBv9c)JtTnW%Q5iw;zcDr}HG=@Sh+(2hT(=5F= z%Be*gNr>#R-#CZnze3ofjGNYh5zv6KG4IAv-wx5!{p_0+lwaY8dII-Ot_|yII&&@J+q_O{xq;0WmnT|>T_{7{?qicGu z4tCKk;91(9%OO*Ad>1?+8(Hp8z}6I-lj=(AXLOB$C5^lOPMsQ@^@T%fG0yYR@Fgd! z?RBc_KXInlkadn59J>% zaal`Y&ry4_!pAHBvc``eH$KZ|E4%TpynHeHr;v_$Aw)cl<3}PJ-ZA9Q6X2i!D3Aji zz%O`bQ3&_EeJO$Lg|f%81lWwjvWKbgeE_zXb|C@h8XaMnH-9um4j9-6cn(@AiCgeD zZ>0zE{^6cyE}fA*rc!fU%=@^KMzqv2$K`95I=s`z@bMz|jX>VVEAH8LuH||A zeZrmg0`U@ZX{7s9*b;Y{Xz#%GK)@_w1$JEdzpsdBuxpI2`27EQ#ny{B7aaV)c6+2~ z1+QB}z)};c>^+ISe&HLtTDi+s+-0xuyq#KPL%?pg3KqNKk=^nP_#%4GtJp2rYEY;j zYm!)61X>eqXgMZ(?0U?P-}%w9j?<`jLqEr^AvR6RYi!znYUyh%c||^sSsWN|4@MEP z?hWfSED9JR8?0O8(FtlIN5JHFq{hH=$qZ}dM*-Ld8Yqi^AI$xA!)DA~G+%x{jpW2l z3qR;wQv`eIPE{i^_#Fmw45GJp*UsOi;m_8p8%Z8G;?Q<9*SI9>4;(KzDL(x4*GuH^ zf@GojUM+s#>zLn6zfb>xwHSr)?2%|yjc0n;xJ8SWELl=-Foah|?qUL-?;er<=7{&; zZ;i-ys}wxQp}<{`Y<5Dbz5t9q7z0w)h^%G1z&tktxz8mwW3LBsu$5h^-Ka>+c!(#GP zA8Tz87DI*(NO6e%>4XgaH+rWOu62I%SBOQW7Ks(M*Q8-g6DCAcn9%K(+gX9f#13N{ z3Mrxjy;+HdMowenF;bIgGs###j>wO1@u%{3iZDpaa`RY}cc##Qsev#D~t3 z)5=iG6TsSpNT5*rllD^kCw69?=}N5ly4nCtNwlM|M&Lh_;$U}D!=^%ZgnNfchPi(@ zk5?t>VFAz#9`Eu>X#3{Rqz``JnmMc16;a}oE_pe8^WG0MM>E9M8e!chJ!1rW9uhV8Cd4RZ#ssvlif0LDLAIOZ!WN z{HhCJW$;OwVeMYBvp*cDgiL;qtZ&w}WH=`%IDmQhy)%HkiPq5bBL-4J97!eofOP9H zdE$;a)`T0bgfp0gFEHWIw$( z5E>!7xQUd_7MM0$T30omV**C}Q{Idgim<@D5xN34(m2mOa;9Q0A=~J_DZzFppZ~}8 z;KW5KMzNt_j;eUH^l{`qgl}&rYtnigDh}(Qb|-QOHr}h(DLD_JudEIk(1wf<@6+i{ zuO-{S^@|Vd2Gk)M%(UNbBCYA$)uWJ!eGDuODlK_+gBXNO(9C|;a%T|d1e7Ns72g}! z0N*dMae`9;=t^S3dT~>2`C{2%*-$h_5Q>G;dUzT&e^+0>biewUg=Vfnzf=93=GiZR zfH@$17{}7uV@r^uBrwSOb%to!U@vzL%mWf@uG)bRH0Dc2rQ0QIp)qfd z(7EkqaKI<2JmOH1`JujZKo#c`Mk|!1VTQBLx%S|z+)Qo?H}%hb+*B^@S|2z9d0nf@ za~yWc+xu8r9zPOo_l1mfVS);b9(8`~o5F$SmhFrBRL$JXVd*h%ai3yef9h|Ov5tMN zVpkz+Uqqq)a|?JK%268d`RYT#HEv?55xwWIFroap>QTrVp0{u|`tA{2*(of!6Hzm! zs5_H*hoEsL2^q+16OfMiHx@Aq+S4>F&GZ!}e2Dg8*>hY6gq}F~0KEEv9)phmP(J1u z1^ciO67KuHFMus%7K8l@xrfm&@V|LYq7}0rp?Lm2WU%<89bVEpc)Jo$Wicu7RG2pv zi^n9OFovYV{_s*}p_!ZFttd_{$!Q0(BE>weu#<$xx+^CJ=a3zEzm+KAD1PuLTtSf# zN6FIv#7Cyh6OkYAX$$y4O=^AC3`MHbDE~%`u+-MV`cHXHSnFb;rY0M5Rpo(NUXAbW z4zRW;B|CMjSS^tD13p|gHxQx@MSdJ^BC#?2<_{k@Tbyt-Ccb_ikc?c0+C_L8uk`*< zn*Ai&mP;Cz8kGo$F1H`+edRw8kAOnCBB(_|7FAb|fWLNSO(@1%W?-+N`z=b!a#P$- zQp8Z*yYJ-%-}UN)8ulRGP2f*R1;|sOK9{WA>#3n+#Ab)PMd2~b!6Q5y`c;T|>b&l_ zL)*(W=fS`6<6sszK$wMO_+cs5uj6A5vgQ-gg)1toN-rRW9eFQd85xxRfjIX;lI9%uLE3A3lyZ_it{zGdi zhZWX2U{Yx_$175$$uw3SmQ+;B5-sqM$nf2yoXZu9Y74Fw;+s*Jo$APPYcj$@HXU4H zMYR^(+YvA-$IQhs>fqj73!-$-KM?Nu9M@2tBc_N)!0?ppdDCw!VZdGw0+X*&^5ukx z$)1<|AveBl$G7DDOvEZ64}Nb8&b6HLGh9=7iZsX{m2VGafCME-SlN68@`@dERrp1%^&@x2iQt(7E%)R)J-5 zU;e!?+7%Crhva5C>s$*EF~1jWs1*$pPRa)HF>pk26Q3-U&Xa}Hg8GW`honv8b@o4^ zrl!M^9RS`$&u=XRx;qE4Kn^+^xioNoCD5A8v&9iSKOKDOET_b^SLncsL8B#jM1gXB z`TXO!_IF@op)s@ytXY|23m9?8zIsC1{Zq2%i{V6`Vi=2+-fSIw9q$s;O?f$W$Y~OM zmtBRcZoEs8$1!)Gpc5(TAC||S9rIVw6U?`B@zy4bAkKdf46Z?HpZ&K+^i z1FMwwT=1&MR_u;}7oN@aBCan=JX9FzqEGqg8S4W!%oLG|UqqE1(>)J9ktnb{odDir zst^fFA|YqEbdIusB*HSrsZv}^y;AWSl~F%wT|?tm21#?@%jy%a~rI* z*{~Fb!@|%bo7=-+;R;Q%V6;BqBlhC0?v;H7XrbMG3c~Rzvdvm<^waU!PC|M288w@a zLi~^QJs)(AEmb$df6~C3FnVD9<-ieD)S&6$z!5dS=`(3`zlOJU(dUL5RkIpn_HTaH zRs>l#Uxd~`{kkUG*?KPr-vgKUnPllF>6Eq3ZwcxiXKQ+EW4dDQH8=;QUx-%<@+rxt z>tM4ay$Re~h=Z|Is3{{2cuO}H8PR77hG%zuqt~8^U)Y5l&4^vH9mKoa3CoK+2Kk*y z%A74{Kr+%}K5~2Ox(207e!@wFJ5zv==ui+WQ~d&vRlrpZhC4BLfs@ON92KzV1SNAe zD4kF+_nz$Fcs>cP1=Aakbq+}%c%#aOq~sw&N*2RXMp9R#5Q%6O4Wim+4Gu}~gGDI9 zLi!qO@D&L>Aq3SsL$U3(ag8cyYj^py3ht*_(BZxRaN{0ZaSvK!ZQv#vS87pwB9C?+ zk$om)%5$l#5#Z&CU$ng1f;a!RfFh;sG`A@@hie6zN%YN9s(o-OBX(Lt&qumqyZ|&@ zL#x2;jIC8Q-Y%%026oaFQ~M{p^YgHCQBL1MaB>QeCDmSHc3|B;*eZEE5A_vl7kVyg zmocR*2^_fP@Pp4Cz33?3bVE@D>`@7@HTamxNm)CdLtf>k!4<+ch#lL5IX;NoV4hcH z6MP}>1oZYZsEIB3OUTI@;kcbp|Nl{<*gF4&T(v0AqL6)FpIlg`hs9cDec`TfH}iZF zn6rpWUJre`0~)hKbyBX3G}I%*a_W6}`)?bjf!XJhgQX4v0mg-GfQ6Rxd=2S`d0qj& zP>UQd$>2mbbl+(wtChxO#1q{gD6)e&!(y?I=t|}FB7JvHK%Y1tGwD{l7N{a^gbk}r zsK*?do2!N~eS3fdcHkrA{ zH%2u?wQ()ygvvOzRo$zB?8XMkexYs|l%A8rt?cTIO4z2-fb zwTBtU-GNkI)41C>E=9Xby{l7HC8`@=7S)h}nWuIWhgoQ5KE-fgHoC+$&>Q-Zudd9z z+z$Ss#F0ubE%Ogaz@+nszc#dnI<;+CPOb%!;zmTfeZn;^r+Jw2uHc%#VY*o+^E5v? z1b$f!FKP=0c0S6rEKmOSHJmYnYh<1$-W`(uiQga{Z47sF&A6HxPcb8E;Jk`!DKamF z-Esd^Zr9o($Hh=<7&Q9!K7|o!E=3i8=b*8}`9(3JIfd@7Xd{)ur&8e_StAF|Gp=o+ zxvCBsl3SJ&f4;I({NQ|jz^<$cDfFEZLDA+kw3-y%CJC!e0rVPNsSQtrOaWYcBt21c zwYjhk^AThq8Jr|WE7z^mfI9d-TpNxo3yO8qs*RPv2}uEQY2< z-w@*DrfC{idDele0;r@(Kj# z7J3c?2kVm>*05wo<56k58Th>&$G0oT4@v*_>03AByIp@od1wRT(C1(j?$EBMzoR~o zcU97LFZbzNxVBjIvFz_u&4#v0*v7#03mGlXJzL2w#--21b~+D^PGr}5{rYno$GDBK zSwuqvQM(y5kTB8Mb{IMc<&3yvXtRRJ^_(qCI0YSq7(TW*;6MJ3`YgLqBiOr9BgWm! zTDVrol#`LG^cdmJjdPF67fjJ{(E|ofwL1~X|7fioDeMyNirHn4uC0lStT`(8GPUK9 z(!b_h>wh^|lPc6cLk*5>1K)I)1}#1aERoj*&rR!2`0ehRuj;<-72QCEeloxDn(JjF zj=1Efai@0Qw)d}vI`{kEX=N@f)XKTuE%X4{cH7>pIz#i3n49X+n15(gzu;P2mQ z>oHGH8RZ=52?4q*2J1zIPs{(8lS|%WACyMJ zv+Zk(CW%!0S~r)t3C9l)MwR9Hv->)3Pa#OFCzd62HfaVi3n9XW2)H(aGMvsFaJ!y^s+BGv6_Lj8Is+ zIAJa{jW0_(x?jOls4Pe2=*6pAj>`KPR?QsT20tfHmnt=YUn2 zU)IuGsPxf!2kwA37CAv!C-SwTuK*nw8!`6mivx-3aao$)7fbSn)W4k7N1sm5hIX4W zVwXnbT2m|-eY{e{obTbf3M_8INR@o6@ ziTNmvzRH!g_av;U33+Da*W7cfJnIb<^9k;b*3f3|*{CXgKW7*#tj#_n8yfDfL!{m2 zL8%c4+VNg%gG}10O?{U0X-?r9o-PrxDi_uTgxun(sRY*6XkW zBLgSJgRwLn@ciWam}Q|S+v7#<`J7sJYW7r@>OyjMhI_J@o4wFAJv#+8c*cj=5O5iC z-~&s6zBnH``9 zMd`rlp+x*m&0cL(GeOX>ul}lLJFq_i`&-jA>@9rWh|e1A@3=?9PTY<2QxI#7?MiH` zP%i&b!+Mf6tQn>Mad1K4octu%l@gIp8f6a(mmc!>n2zXYHvl}IOgkFjoGJ=s~+e3Kjk+Xk1|UUNeF^N*^3K*G349Du*sv_p4SH;k|5 z+9nIH3K!xj3*%Mkm*MJ$>gK&d612|=msOav>yN~|0==wmmawbnl&d<=Lq~~Jq^jo!2c@Us&$3%@MfT88 z>wMR8YZ>&G_Un!f?+tJfeD8Slhpjjw)M^A~huLly1alRvdeELS&$&nj+Bo=mU+2Jb z1uJ5w8Ap+FHaSzQ=`L+E)=L%E%cP{77$q(=$+?(c4*4+#IUWN!qrd!0?s3*tc$HOh zRq;AuRmmsvt^!&itG}f<gDSB)1A zARbub>WTA8;drZ$eRVJ2ELZ&r(JMUpA-!$`=KUpuR(nXxt)&sLw;h!Yk+IHGvgUs1 zS2gq|&kpMNkY+2^?gEUDPw|URgoHX63VkjVXV=MD!XNA*kZ=a2eS<7@0qp;W<&H}9 z?lu=#6F3p~_GZ*RUpRF3Wudyc!&!|?-c~**_Jjnl`EI-`S^a@s2A9lajdIE9$Du>Q*gS2E%u%^7NSB zEtbkUAj@00rtn5JWOA^z98@H`QsTz{%Rw%c|1QQ8>${(P6HiUTSR>uiKMrwcC@sgrJ}Rm0zzACue*MZrR%GE=I}DlQ!2EbsPRy5s(tie#uh6ZTGEy{`rjeWnd6%wo z4ie0=+Ozh>2_&n6w+?StT{EG}vpUH2`6+5lC#I#4%RL#Y~z z_CYB``SB0H2AVZ&-ys$2z_t>fH(-AS_J6#c+T@o7h+|ol0sXtfK{6_sSg&`ikX4g%d-rPrR;A^PPKWGT$c2_?=?g!AxLZAZiu%lyDK zD4D%SF`~)pL?f@5k&oWDZ3mw936vE&#II}%1jb{ZDbMejOHpa3ArTQa23o0$bnzi@ zFJ!?2o==ii&1u<~7uFR!G0RTaXqVhuU_|uq_M8ycrW|k=PSV2iM%id)4;takM2@(e zpMln>uxh`w6elVx`yhCkGJw?eO0$6i=rv8YJME`s2K3)Cnbo9=afoyzhJ?}fL@~%x zr0ccvbR27NQFbNokk?7a9*!z6aHSX9kp9)Lc|c|`Frc~`7qBu*zk|Ik1C8t zpD#zdp+s(0vuKQ|(b)h0=z15psLHi(_+E!O4=^e!AmR)IIszJsc`i9FK~OBM(A+tA zs0C_aRu7^jsFj`e!@&awGcDV%niZqDx0980+Lc;+CT*vw?d73RP+OR~77WaM|9e3_ z@B4n=_v3f5)~s2x4)^i8uj_yPud+iCnk5H)2mOa-MLZrX5~F>7m^@4#XKZ$3VwbWH_$-~901+Juy4}cK6^ue3jKW)=K@8+@c#eM$ z-X-jG_t#3IE-1r7W6;iT4T?DbL!960C-%`e^XK3m9PtGExvuy=&_;~?_WnSX(yROM zOCFw!+wKy?Q}3}wCdOZ|;x47Iz3lmn7pOk7pTuDPF%35l$DQ3l%AqEhf@p=b|v{Y&t%@C zwlj0bFT4zqaD;HuFdZGwcLFKz18RK(q zC5?3)fF5sged4p&zxkCU-s6tP+wv&MMOZ)Rwf6Oo9&;kzPC_gKN`$VBOcIko(ZQOX zE}h8GDiBQqe(Rn+u%EfGHr@RmSTQ8d9?W*kLdlX9U}w?6RvI}b**z5X`#JJ(7Wc4N zT~HJVwfGUlxa}b$5wSSm;}m)LfN857*2BhUyIGVw0rshv0YaS*j%CPhNMa?p$u@Fi z5%$MHW*lb8sd>l;4S5i zJIGc@DTLad`+*Vet62MyYs<=G&y>8J)#+!{0}%do@%k z(9)~y&UWjOwc1$83m00);(CL6uUWWg#!Jm)xba>69{A;URb;#Ki}Ps4Zmf-J3|sYE zb5!dJYDp&59QBylLYFW`c^6U4I}PwgOrmy z3Ha}Cm28aRM)cA%7!NMFDO+_oq8t>omluKPr1<5JI_?3Mg4D+k<=v$AP%GFr(ou63 z9@!(_15(+iS)C&@QrwAXYp-?hZZ$NKl(q zTR~Co>S4T@TxI!549`MTXMOtCf{6BWlZPixAhAtSPP%9F3{N7}u*uZH{?}qyAR4we%>f z5OaCLR)l%_THs6IMb<)N{t{O@BE~hG#~BNvbfa}X>u9iMj!u_1S1y+*E6jY@3%1kq z(|^5Sczt2?M1eyN6GdGerxU`5a82<7ZS6+CNrDv%NSLY!Xbtxw$KKeNGjE?Pk2N#^ z>4RFG9AWbzbIG*-n^lA){qCQPxV2P)^_RzXDsiDhnao)*mk7@caSAVF9>zCjskcX= z#Co5S1>d~c^Bb{!Btjj?V4UiRYQnNK1rq9XedA)@A6VB3t_Ott1MCk0meKoA5; zh}a(YhOzNHSRJZGLz6E0i)irt%>F70oVqB(2%iahYd~p2me-w#*|j#ESM59F8h%oZ zSPPse%Z_5E85<2v!|E;DY;vV(n@GJ-dWWH%GgG|Qy3YToOFpAE*jJGM;Dr61jxeh) z<|C|7ZPn!Fe=0{GF=L&1pI|9J>$wZQ<#6vHc%NatnhK8pa1C`6zJT%_I5GEvX(~Uq zMyt66;GVSz^J1B?7h37r;oh*0LcO73%>s%pKP#C#LaF`U2(Q*PqzlLAt)9`0-0j1F zh9@R{En+J%jse$EJ5qr4TOeB%WlE3hh*#7%h1F1QTYGr``HRlOOUVe|p;bOk;}W%6 zH2Q%+il9iOfKu0`$BcM_91+9nH)O86_0apwIQk89cfNF_BRqn#%vlhtKbrpfk2W%n z8OPkcG4s|*nm=X^SRMvQ=hcK3l#T5}k*nhos`glysfl8z4vTyv*Hn!wC%sRv8v~{e z0-dW-IMNY@>?L;#-?a0*AnXy$uZKyrAN>e>K|q<_MSGH0yf0_nEt~esNbQ%`5pfs} z4xY-Baj$=b*s3Mb<21eMge{_T6Mxy^mqIZ)@W*e@9@@<~Z2%9{Go|bmA z*^byb)Xijz{9YU1Zf5App-3{8(Q)mB&5BsAf!dn&i~c;}G3HRa(bsc&*RMOC<;W&T zE#x`Ke?ykwyGJ3H@5fpLQg9zn?phrRH9)?Y-8*IhiM#8S=B{jAt)Zq;hyqvFAfWH` za)iNHi*dnem9omy!Jt8$2I=XU^Hm-E@J5lNULEK81K_Z#(Qlcrn$oGo18a!tK=v8c zXgiBCrpUH*u$2sumj?N9!dsQADxG#AI!o8sqqGP9OENVuBV$gJQIS6ZsnLj8u+}cbz*0Je zmTEJzHKa^NB;I0Qk)W4<(<|VU|Dsh7E7C0gJYYB?e}eDe)A^_^nxEnxTd@Z`pZcua zC)$jLEFk_aM6b!tM4Rta5IJ=h?@w&|1xU!p0(ZeL%KG(<^N$qcD&xWHb-9w*Rm9xT z_A#{6(DXIln3MZ4czgR4usabmTLWaJgR8zD_4dcJUF)9crR76wnQ1oz34VeUVWxW( zUY^YozDW&c7YX22v-@L=jf!$P$lT?ER<^cvXAKFL6P;c=@R0e0C|AV+>_g&ExsFIAf4r_3Rr<0@!-T1z5F2Zi_g*J)dd zLYttrkdoCLnE^=wf5hoo@a;m%A@ZSNGoNoBHj6UCu0m#{6p?I>E!Zd0yrLuF)nA4_ zN?AcZ6TiSLMdD%ITMQ0qTYpC-@)cPrtF*mcY(&1GfKsedzG=!t>S}>MOhTkBp%FTG z_w@KOaPUH}dm5{A5wm{)j2F6Q`D6Nwzgl>bfM+>3lRnS$z>G!}V6BT-n8Ag=&Px*? z7h>^L0}C4HQ`JP3u+{TLu9jjAj93@OVM@h7r}OScY?r#$~JYYQQRNAq!wS$e^2K4ztw7N*V>2_ef>3Vt*u20|d(E^GyiOu~C ztolH`r?PuuW-xUXi2waoSpZ~yIc$jwT1Y*-@rVK6Rm#IM2i*qx*AB$yGPRKskm~y> zt2{je82{pvYGwLV&*$LzrAQAa@E#6%Q9xDn@PT$K)4G`Y6Uv>dGjQLVrrvjr#Xi-k zvNiq+wwm9Ym5V5*T~2uKtu-{BDQgxPF;wJgx)AN6W@B6hKALOTC+cclCHm@RqM@z? zO#0dOOg!!77Ty6HCHP?Wz*cjiXM8@}AQiDRM-Ap4f}9A9od6@!>+fc2kv|D2UD_^O zezw8iXYCzx*VldaxrzRh@PJi&(Q8qD=g^@RQLbTJi-|D!)6t{f4FQXYnabwSA%-%| z*6GQ`(KkcPgfM&_ujTqN(yKtJnh@|Ecaw z1^(auhmKl~GNSeLw|t&_^fY+B%8(lY`;<$Hwv*v>{}AH{fX|Ay@Q0xie+>R!TAoJ> z-Uc#**=$9Ww+@{3rn&+0mOwdOw@+v`Jmxn3;1bMxPbixZQGfX82zSfP#Z|;P^@0i3 z|F1t|DE1%tZp7P`8Gyyk&C&Q7O<0|nXdI@|zZceHK{o0K$S-#r;U%%_VaatU$~#>K zVUMR$%tW3&=8O?2yPX(|xc2qoKdbVXG_VX%{i9Ie{FB#Ej6-}CT>1Ta-nC+ntacPBAXO@v_fQS_5PP|has?E zQ;nOgV;wKd;A&pTe^HANdLa)-Cj;qT%h&0u^)>q?romWmDWbe`(IsDlh2nFp)XY&a z#e6-qFtblRWsg5d(Sb~wPxIXV6_Jg|@34T3yzM_3<@C_CQM$aZ@ObDjd;Gk zb5FdQvlf|gd(ZVpk&#dP>Y??p4K&jl9S4~Bmvc^F3vGcl)V}O_IcLe)osvWTu#*$n zipgAiAOLYy&%^L7W5j ze@bD z<)LWXS1adX=GY{;ggeN|Y!Kh@JcBVM_tOV*>6Oc~!ES}CEbN(x@*9WjXRm<|-z%19 zFPA341ET=11YQpGDz18sh<1$YaC^a=08Ud=kZWR+CjwuV4PK1}eykUP-zO1=k0uF` zhzE%@!^c@Y5*(7Sp9D1)PFQ^#5Ql97r(#CbVfcfii*J1YoM*6S9QriH_4y>c8StIJ z^)X{mLn^RKlW@Gg#YRg)duOv0pFbKLGZ%|`pPrR26wMt&pS8Q&Deds^P0^yU{Bt1Y zoqbm=r&lE!<2o};yXrtS99PvcvD&28@t&C6Fshs3I*M|pd!5~kZxf_JD5LN{%jnx~ zV%O6e29G(#3tr@V$HUXV!CzViPKcH8b3#TyXkCAUI;CUfF>DV){sw7+G(g@uhjwu& zUrhE4DIbM(7wZK2Q(~NP0@J=hM{~i^2xB$KXCcPeLR<=BCg}VLd-hC{K>7b4gw2F9 zVR61^v^|D*p`0g$D7RpNM~}Cp{3%gll&3f@gz~4Od)dd`PasY{o6dW`Pp9kl>j@s5QqN|mNzay=r4$jPt7roc zEaHfR6xXPLe|>dnzmB!s>zTiuBniV|DIktJiWEx6DB$z}h3FqkG1X@k*wDe{VV^C` z8H#8=#0p&Qrd)=kA!?`x^C4F92{b1BM~Dv=Pl^FPjrXU1jbDFe$#X1E4&xnY9h6~z zJN73W3e)-vCpLLEh_86+!IhuU&6Y3n?ge@%w$FQrIfY~m-6WQvZ1;8Fi}F0c^j?RS z#{`Y_XTA8c0KA~Yr1rdA z7=NR``rrmbW5mugI1(AsjFyY>%AB;(_w>nC@?^aMfqIaSQ%1q0QtJuM49$3i%V?NC5*A&$Wa+Ys{EBMM$oD!Qz| zp864=ZacI&_iN~vq`L6d%Rm6iN=%SOVWodYBL}101n4i)QOSSiW{ZKH&nUd5E0YzY zc8y=*l$nJM1r{+#mVjLj@AytNg-_^s#JJhFXpQIvb_4C1WF zHjcetH5QO|t{>N7wSKC$q?2}Q95SaDFlpbZe7YeSYx(@|kd3y@zujI|Aj3YtHhX9B zTDz=#)8k&0Xm3-vptOkFL*l2`o={FfPnrZzU!Gc=i|kfKF=AaQldQumyy*g)&>LYn zeLLTmr;Gr>PjQeG$M|+7v`@s05_xCk{b_N`Qicr=bMOo9W zC|rn1!DyZ`6~0QUTg;b86Sp_JAPRXXb`>92HeI*7RpsB^greX2Vr!$stm+0ayC!RI zOi4~{ktkHpb2Ie;g$Xf@V7DkAH4^K{_=}66+2LxvnC(wX=Xvf%&tUL&)IUmj#aPF5 zc+m%iIQ#VK<4Wc=9&OxxZDVGX|F}}1eG>7hAKtmLcU1r`4ZIt;UuYk@qkP^K<>AX| z&EE?0cB~zw>D2_9q?Wx|tOd`&1jMcm$*1*3HMT}KT{{qp1k1k$k{`Wbq>=#{`o(XBk!X_QuABxv_95o0|+ zQvSe^mwY06#VY}Ww$7x_-5<}KG7Vgf5G#c095j#oZjBel1&+JjWW>y@SO#&9U#q)Q z*JgV#?z4_^Jk`w3)3~Z1c9@;1Y_bX7;>)S?u(Y?SGx-uc z|K>kR8D6z}blaW+3%wIo$Vs@n4fD@Vyg?4ijimhU*S(&C_E8TOuVA)OW{p4N?lg`$ zH`Y<`9ZH9PeQkE4B#R};PpvA0)n@ROb}L6!S}LDorqjyBK8LPZE)ylB{q&n@0!>hY_eow$l^iWC1UHckLb_L_6*cKdy?C)Dk> zJMcGh^;vOFH~$9XK;KF&cJFjg9vTmRM_m&K3tP7`PGuT~%-RH|E2U&@?5*OM0=Ayw z54LONvpw~W@=K?!FrX|5%xqxlzfkLKpUoSL%xrg*OPyi2|N7h~m{}seqUgCv?t=Q} z;ycRIJt$|pONf_w2IXffM9Zdq@$X&8S2?wJj@yszgAlqNT`$zZV^Xk0SMyx9aUXQw z&EQ-vn*zNc{i&hg5;ksO6Ss?|&4{(njs|b9xrV<@Ru+kt>iO>QJ>ZDhH>E7R&Q@pL z5>^vY-LDq5_teFjhOwTqyI~w6%?sP|S0e8Ke2dH}tTK%_XEsT&z3+f^IlH>ok`J_I zbCGacxgFX7F7!YAS{zu4CkcE!3(a~GA}70*Z@SI^F9r={TrWm~_UNkM^+D&;+V?BWK>J z*#*J{AyKj;dYF$tuTHH*j-4)`+-$jsI8Gv*%5ORI!g@E$zu&00{ppf2+_ z-#v&-APyrz?>&MiS~S5`Clr$HZ9{t$|P?*s(ENe%YK>< z(YE6VIDi!Ywmh{2@f-0sl($rpQtZ>+&F!$F)#ujM=5~VL!_*7G=?Vuv+$ zDYru5Si4(cCxFgFHhI8+s97PXenJswW^bhfSZUfG9ayJh4f;?I5Rkavx=`lv%+!Ze&nRD?TV1X!Em7{jvlt52xClM-@WL1b{?$yt;l7Nhc}!Q;2V=X19SVq zLrvlpC9%i2=MHik4(PLK*LL=f$H%6CE9P>qPS7^FS3hMgu;d#bOJ2Unk=I^h$xjoJ zs{&FA>7Kxo_ZIcW$^KHXi$*YQ)>T^tJ-qD~XK)RhijrRE#PjO@%9J-o?HE?KO9+?1 zWsiuv@Scg@v$+@eX2Gct=CjGxML4vk*5THQ|=Dwn}&Fs!G>ZR zs;?gCW#8yDr2P=qQDn@y$z)_A*TO(~NbpnO4aQl$80Ggvz7yzpPxmn5r=Eb!^h7r~ zF_VNweSoa8A!l^WYw8oJ>>D{Z*^Dj&+laPA2JK_3Q-#c<^h}Y9t{W%=htn{|b3?h% z4Lvjp`Y^KD&>q2zufEu8p0oiSFMYM91a*e98A%hq?XCb@w)e5S!1 zgLnP?WF_M;)?Zf^1Q}@5Cn^WaAuzJT$8@`L&oc>G61>O z_@h*VW`Qm9(X|eTUS^J1>R&3EkX?1bpDYYE&znMnun_)Aa|G*uQ@nCOYKl8lPVd_Kj560E-ZZvz1^^*=h;?<*zX!{4obF3eH zrAhqJHwC_Kly9*Jyo8z1+#PmYgIw_#8t^+}EXxq=qVA2u({WA9!md{WM>^;=X%6Ef zxL*BHMA8^2Qyk3~fEcF{{ARtxS2Gjd)J7R1y(tXr2;I#gOUV4zHw7l~C)68B9_3@E zMV&-B*miZ8`eG;k-_N?3J}c++=s8{q43EV0>~cJlZac0+c22j$-_8OVN}q5( zc(=iV39qhEHKY#7%|QRuHPufCt8rqwFib89u?@!!;owT3?IUd8K)J2kAoYipgO~c@ zKcoF0h80Y##BJB?Xs~oNW-`8kaz@b6+q-Y~axF7Udh@;Q+QyQ|&sj34m?L-G$e9T- zVxQ_3uL>_UAJ@1Q>xE-^V$mRQMH=d0Eor`#gD9)2cRFl_4B#N?TtVd1@M&XVn2Ka7RnbPzp}r&Oh;@P7E*^}u`&PrG2lH&3*g@XhF|-5vd@5AG(DRF9dA(Wl=` zz_GE+@dHdUJrWw9esf6G7{t~Mu6hi2omK_3e#)C2HuFDWJsF}Jr|SGPswoZkv@Yi) zIwFj!nkDSRv#}`@Ym?FUe4GA!zF}27o?r&fH&8EhZOb!ptT&=tz_Uq`E=A{m z5PN7*h+RG{ndrF=#u1P6GBBq1^XT#I3CXB=qL}zaI8Mj@{+<_byhYNdnEmJ-eR+$u zyhy__7w8X4W|YP(SpMmC_e)9m^!Ij?7Af+!l&^jFf%e@FDW&iEF8DF**z$Xa2BeE?;Unqy?1GG>4{*PGfkNo|K2C5-PoV$O^Je%))BD;PyA$`N z>wXtT?mXdy^70kE5FyR#d)BPJXHDz-w(Uwd*xqIdygZEKppCIkwlAwie|(~KXYvk6 z9_a6a?=P&wY8op<=H-G1*D5EdU|364#XO;Y`hXNX-@UAqhO0BehTAsRqml zu^RVWj7T#y43ulT|L`qM?C9-ZOO9*y?!sNOUTJ;~St7s~TY3X>;>ds+&oy9j> z%^kMziKS&ZyoQQiQxfIAC{Zmq$}?M-R6>ApswlC+=SRrDB|DAT$B1YK8xM`UC$O4) zRcV6F{fo*;C9jElrgxR-gzC(pzA2@j!N0dYitPxurT|CyZo4TAaf7~lOFK(s@wzfU z&{I6I6k~CCC0Hd2)7D&a>AG+!6{F85DDewNVbpRq6x5K;VUyy-Fz$?_B1Rs&&VMvc5 z@^%cMV?6p-LEH~f-NoLHG-%2Kdf)PL0drxbDM|uX3by9}^6>oF>g|XG8fid^)yJI< zLw%1)Frv+KK3ex<6IiKV0+ISBpgrlIjEkftgE6DG<%eSip`!*#9*4OwG9t-0yLDU& za3E7T|4Fa0BQ!Bt;^bjg4&}%W|EPn*a};8B{vapzq}k8XYhg@@z_+wr)_D2RHXnW+ zcArooP63166zFa1Zl%2+5VLZ=_ty*KQl{OqzmHaszf0&{+v;0Wg^E(x6eKS)qiHrF ztxe{FfhVOmYY6i2sn>hkWn(ogflB&3F-+%_SFD zeUB@b+icz^WN_DMwwGJ}3nH_JsWHvu_CA}PDY)Dd1s0f*mxFd70};C|+1)&yXR6*C z&65`(Ht^AKVzT#`^6z%L`-bwm>UJ*{jk(4=65wvy#W_)#WU-sLK02z)%}n>l#Jh9( zbgS*-ut%fG!rvdC3OcjOD;~ByQ?_%(Q_dcUPG-(5Op5fQ#;5f~^4&BgDKwIgEuQ@S zf#{@;GYgY{^Swgz#AD>pJOk6o(Fuo=@{=^rWfF8Y)(y_RebK@);ffLolth-n^n=k3 zO|)y(V2O<4F5#nt36TbKqVx zfE4>xzSOT;Clh;WnX&Oo%-EHwPwG32R)d+bzN#{1ui}nuxE>?zt14&z5*&#|v8k)* zw=dz_m$YwR!Z#D(otY-CS+)$?exPJhDHGs2^I$6-dmXVhPb3^IYriqhEk1H|PJ25gHSC(I2S>_TtOO7l3ughiYjq&m{YhIhx zM9+VA+0&lRl8L1xz}!y9n(nwl{=CQYF4}7+l>*zR%(xyovoMy%AB7I23;$R-64!6L zcD1Au-%Y)qF05R671zIbEiztSS!HAc{9K1TjWA9_)<0HmR3j(%`qNU9c@hQrXA-cm zkW>gQ-!R|@8U)JHK24lb+Eu~^I5k6{*5Sj~GSIiEFT{M^itP0Cz23W)>Yh|ekCE%l z7-ZhmY=*v(y>=ktq&7|@dZW2?DzQ$UYP@Y<(j@TX?uE`hX!V009UW_+_0qA1>bw!& z=STDYbhMBRm1}lMEc_d_h`B{(rk(#NpT-;7%_9u$Ci7O6tNxp4ZZ|!4G@9+O>c5&z z&)AAmENnC7ncB@GYgOw`Y+0PSlWjMbP>V!i_P=IF0*%P0frH1sCG(?`C<}~38}YmZ zz6}oj;WuSgC+GN0`CYYre10t*kCZIpOesj3u{JwF9RB$2uxHqjSa}>*^uJ}^j96t5 z>NAb!$W~@c06sDa6Bqp74H~Q;8{TkaVH>;e~x_UE8cr!|x*|u3VwY*i~sEFY& z(OzxOj56$H(P#Dhbnk3d_05m120l&-DL({xFhtR_cU8n!z)|0Bb}&Hs!GJg#D0%iqhKmyv%=*I1L&-?uWB`Y0^2r_%xSWxf!vecIRQ$Tc*SXX}Agw8(FDE-O8V z>&4@GuUMG|>n*TV*5|h|mJK;NKi9Yo_)fN|Ub`C2b!3rW?wp5gfLQ|NNwmltI{W4F zxEj~U;%aL&0N3~O?6S;kE|kEi<{bcspO4J z-O1?O3fvbcUpcMQS=yMRJK3B6W-N{*buKQg&(WXkpNqI~w)ZT1=b} zs|%%+Ru?CK+DSQd?v`TST{U!xBVmRMxMYj`*DjZEL-`a)hr<|GmpCTFuF;}y@(k7Z z)phZ4^4p!RgDxQ^kB?uS9VhST#9W}mT#y(Bj;|8TV)0k$b#?I1^p|U?UWKUi!Qj0z z$t|HYO&6wX&0f|4#F$~VDz`?;#?alcT~qGLotJv+VGo|a2~q>G9U6d@Z-RKKB-vvx zg&)7vrsW1B_(8grWM5uEiLIy)3`?fal=+U{WXjuztV*cWIPjsn1x1kuV2{>(CZX@hd3t(j$2WpUyEETeaJQIxM;my~e+j4Dq498Xymb4FcYudn!POdUo(makJSQk16s z^oQmXzNk5hG3%}Ko{V~u3E%PLnI~g%87D=({d2`jYWd`E)Uwh+n$CMr)FnrqpBIOc zw|WpE_E@Ynz`J2Fe4O02FAl$LUm81$YqE2K{++U(FU$L zc(QN<#n523n7Iopy-}j8Bpkii6_nhRckkcuC0`JeO0Fp#YH|sUaM$7Y{ZbKI6(kPF zQ^jtFyX@m;TxS@rL+79B{K(<-8J=%Gy;vV0QxTV3idgbes;5CKv_UJh+fW0Hb4&%a zLNXs^M;23S%0DXC$1QXP&&&C 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 literal 0 HcmV?d00001 diff --git a/release/aroma/config/compatibility.sh b/release/aroma/config/compatibility.sh new file mode 100644 index 00000000000..09039f25c57 --- /dev/null +++ b/release/aroma/config/compatibility.sh @@ -0,0 +1,13 @@ +#!/sbin/sh +# + +#remove the binaries as they are no longer needed. (kernel handled) +if [ -e /system/bin/mpdecision ] ; then + busybox mv /system/bin/mpdecision /system/bin/mpdecision_bck +fi +if [ -e /system/bin/thermald ] ; then + busybox mv /system/bin/thermald /system/bin/thermald_bck +fi + +return $? + diff --git a/release/aroma/config/settings.conf b/release/aroma/config/settings.conf new file mode 100755 index 00000000000..55b795e025e --- /dev/null +++ b/release/aroma/config/settings.conf @@ -0,0 +1,6 @@ +############################# + +#Glitch kernel Configuration + + +#For settings to take effect, you must execute /etc/init.d/99glitch as root. If you don't know how to do that, just reboot. diff --git a/release/aroma/config/systemcheck.sh b/release/aroma/config/systemcheck.sh new file mode 100755 index 00000000000..3972c2d486f --- /dev/null +++ b/release/aroma/config/systemcheck.sh @@ -0,0 +1,15 @@ +#!/sbin/sh + +if [ ! -f /system/xbin/busybox ]; then + + cp /tmp/busybox /system/xbin/busybox; + chmod 777 /system/xbin/busybox; +fi + + +if [ ! -d /system/etc/init.d ]; then + if [ -f /system/etc/init.d ]; then + mv /system/etc/init.d /system/etc/init.d.bak; + fi + mkdir /system/etc/init.d; +fi diff --git a/release/aroma/system/bin/fstrim b/release/aroma/system/bin/fstrim new file mode 100755 index 0000000000000000000000000000000000000000..4b0819ea239801e0afcc3c656308d75387b8041d GIT binary patch literal 11189 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 $KERNEL_LOGFILE + +#Set CPU_FREQ +MAXF="`cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq`" +echo $MAXF > /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq; +echo $MAXF > /sys/devices/system/cpu/cpu1/cpufreq/scaling_max_freq; +echo $MAXF > /sys/devices/system/cpu/cpu2/cpufreq/scaling_max_freq; +echo $MAXF > /sys/devices/system/cpu/cpu3/cpufreq/scaling_max_freq; +echo 384000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq; +echo 384000 > /sys/devices/system/cpu/cpu1/cpufreq/scaling_min_freq; +echo 384000 > /sys/devices/system/cpu/cpu2/cpufreq/scaling_min_freq; +echo 384000 > /sys/devices/system/cpu/cpu3/cpufreq/scaling_min_freq; +echo Max CPU Frequency: $MAXF >> $KERNEL_LOGFILE + +#Set SWEEP2WAKE +if [ "`grep SWEEP2WAKE=0 $KERNEL_CONF`" ]; then + echo 0 > /sys/android_touch/sweep2wake; + echo Sweep2wake disabled >> $KERNEL_LOGFILE; +elif [ "`grep SWEEP2WAKE=2 $KERNEL_CONF`" ]; then + echo 2 > /sys/android_touch/sweep2wake; + echo Sweep2sleep enabled >> $KERNEL_LOGFILE; +else + echo 1 > /sys/android_touch/sweep2wake; + echo Sweep2wake enabled >> $KERNEL_LOGFILE; +fi + +#Set S2S_ORIENTATION +if [ "`grep S2S_ORIENTATION=1 $KERNEL_CONF`" ]; then + echo 1 > /sys/android_touch/orientation; + echo orientation portrait >> $KERNEL_LOGFILE; +elif [ "`grep S2S_ORIENTATION=2 $KERNEL_CONF`" ]; then + echo 2 > /sys/android_touch/orientation; + echo orientation landscape >> $KERNEL_LOGFILE; +else + echo 0 > /sys/android_touch/orientation; + echo orientation both >> $KERNEL_LOGFILE; +fi + +#Set PWR_TOGGLE +if [ "`grep PWR_TOGGLE=1 $KERNEL_CONF`" ]; then + echo 1 > /sys/android_touch/pwrkey_suspend; +else + echo 0 > /sys/android_touch/pwrkey_suspend; +fi + +#Set SHORTSWEEP +if [ "`grep SHORTSWEEP=1 $KERNEL_CONF`" ]; then + echo 1 > /sys/android_touch/shortsweep; + echo Shortsweep enabled >> $KERNEL_LOGFILE; +else + echo 0 > /sys/android_touch/shortsweep; + echo Shortsweep disabled >> $KERNEL_LOGFILE; +fi + +#Set DOUBLETAP2WAKE +if [ "`grep DT2WAKE=1 $KERNEL_CONF`" ]; then + echo 1 > /sys/android_touch/doubletap2wake; + echo DoubleTap2Wake enabled >> $KERNEL_LOGFILE; +else + echo 0 > /sys/android_touch/doubletap2wake; + echo DoubleTap2Wake disabled >> $KERNEL_LOGFILE; +fi + +#Set Magnetic on/off +if [ "`grep LID=0 $KERNEL_CONF`" ]; then + echo 0 > /sys/module/lid/parameters/enable_lid; + echo Magnetic on/off disabled >> $KERNEL_LOGFILE; +else + echo 1 > /sys/module/lid/parameters/enable_lid; + echo Magnetic on/off enabled >> $KERNEL_LOGFILE; +fi + +#USB Host mode charging +if [ "`grep OTGCM=1 $KERNEL_CONF`" ]; then + echo Y > /sys/module/msm_otg/parameters/usbhost_charge_mode; + echo USB OTG+Charge mode enabled >> $KERNEL_LOGFILE; +fi + +#fstrim +fstrim -v /cache | tee -a $KERNEL_LOGFILE; +fstrim -v /data | tee -a $KERNEL_LOGFILE; + +#thermal settings +if [ "`grep THERM=1 $KERNEL_CONF`" ]; then + echo 80,82,90,100 > /sys/module/msm_thermal/parameters/limit_temp_degC; + echo run cool >> $KERNEL_LOGFILE; +elif [ "`grep THERM=2 $KERNEL_CONF`" ]; then + echo 85,90,97,105 > /sys/module/msm_thermal/parameters/limit_temp_degC; + echo run hot >> $KERNEL_LOGFILE; +fi + +#GPU Governor settings +if [ "`grep GPU_GOV=2 $KERNEL_CONF`" ]; then + echo simple > /sys/devices/platform/kgsl-3d0.0/kgsl/kgsl-3d0/pwrscale/trustzone/governor; + echo Simple GPU Governor >> $KERNEL_LOGFILE; +elif [ "`grep GPU_GOV=3 $KERNEL_CONF`" ]; then + echo performance > /sys/devices/platform/kgsl-3d0.0/kgsl/kgsl-3d0/pwrscale/trustzone/governor; + echo Performance GPU Governor >> $KERNEL_LOGFILE; +else + echo ondemand > /sys/devices/platform/kgsl-3d0.0/kgsl/kgsl-3d0/pwrscale/trustzone/governor; + echo Ondemand GPU Governor >> $KERNEL_LOGFILE; +fi + +#Battery life extender +if [ "`grep BLE=2 $KERNEL_CONF`" ]; then + echo 4200 > /sys/devices/i2c-0/0-006a/float_voltage +elif [ "`grep BLE=3 $KERNEL_CONF`" ]; then + echo 4100 > /sys/devices/i2c-0/0-006a/float_voltage +elif [ "`grep BLE=4 $KERNEL_CONF`" ]; then + echo 4000 > /sys/devices/i2c-0/0-006a/float_voltage +else + echo 4300 > /sys/devices/i2c-0/0-006a/float_voltage +fi + +#exFAT support + insmod /system/lib/modules/exfat.ko + +exit 0 diff --git a/release/zimage/META-INF/com/google/android/update-binary b/release/zimage/META-INF/com/google/android/update-binary new file mode 100755 index 0000000000000000000000000000000000000000..cb5fefe55b57ff337165a1f49c05bc4d42e45134 GIT binary patch literal 194596 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 literal 0 HcmV?d00001 diff --git a/release/zimage/kernel/compatibility.sh b/release/zimage/kernel/compatibility.sh new file mode 100644 index 00000000000..da1d32a2db9 --- /dev/null +++ b/release/zimage/kernel/compatibility.sh @@ -0,0 +1,9 @@ +#!/sbin/sh +# + +#remove the binaries as they are no longer needed. (kernel handled) +if [ -e /system/bin/mpdecision_bck ] ; then + busybox mv /system/bin/mpdecision_bck /system/bin/mpdecision +fi + +return $? diff --git a/release/zimage/kernel/edit_ramdisk.sh b/release/zimage/kernel/edit_ramdisk.sh new file mode 100644 index 00000000000..09fb2538403 --- /dev/null +++ b/release/zimage/kernel/edit_ramdisk.sh @@ -0,0 +1,61 @@ +#!/sbin/sh +#ramdisk_gov_sed.sh by show-p1984 +#Features: +#extracts ramdisk +#finds busbox in /system or sets default location if it cannot be found +#add init.d support if not already supported +#removes governor overrides +#repacks the ramdisk + +mkdir /tmp/ramdisk +cp /tmp/boot.img-ramdisk.gz /tmp/ramdisk/ +cd /tmp/ramdisk/ +gunzip -c /tmp/ramdisk/boot.img-ramdisk.gz | cpio -i +cd / + +#add init.d support if not already supported +found=$(find /tmp/ramdisk/init.rc -type f | xargs grep -oh "run-parts /system/etc/init.d"); +if [ "$found" != 'run-parts /system/etc/init.d' ]; then + #find busybox in /system + bblocation=$(find /system/ -name 'busybox') + if [ -n "$bblocation" ] && [ -e "$bblocation" ] ; then + echo "BUSYBOX FOUND!"; + #strip possible leading '.' + bblocation=${bblocation#.}; + else + echo "NO BUSYBOX NOT FOUND! init.d support will not work without busybox!"; + echo "Setting busybox location to /system/xbin/busybox! (install it and init.d will work)"; + #set default location since we couldn't find busybox + bblocation="/system/xbin/busybox"; + fi + #append the new lines for this option at the bottom + echo "" >> /tmp/ramdisk/init.rc + echo "service userinit $bblocation run-parts /system/etc/init.d" >> /tmp/ramdisk/init.rc + echo " oneshot" >> /tmp/ramdisk/init.rc + echo " class late_start" >> /tmp/ramdisk/init.rc + echo " user root" >> /tmp/ramdisk/init.rc + echo " group root" >> /tmp/ramdisk/init.rc +fi + +#remove governor overrides, use kernel default +sed -i '/\/sys\/devices\/system\/cpu\/cpu0\/cpufreq\/scaling_governor/d' /tmp/ramdisk/init.flo.rc +sed -i '/\/sys\/devices\/system\/cpu\/cpu1\/cpufreq\/scaling_governor/d' /tmp/ramdisk/init.flo.rc +sed -i '/\/sys\/devices\/system\/cpu\/cpu2\/cpufreq\/scaling_governor/d' /tmp/ramdisk/init.flo.rc +sed -i '/\/sys\/devices\/system\/cpu\/cpu3\/cpufreq\/scaling_governor/d' /tmp/ramdisk/init.flo.rc + +#add line for CIFs +tmpfs=$(find /tmp/ramdisk/init.rc -type f | xargs grep -oh "mount tmpfs /storage mode=050,uid=0,gid=1028"); +if [ "$tmpfs" != 'mount tmpfs /storage mode=050,uid=0,gid=1028' ]; then + echo "CIF hack found!"; +else +sed '/mkdir /storage 0050 root sdcard_r/a \ +> mount tmpfs /storage mode=0050,uid=0,gid=1028' /tmp/ramdisk/init.flo.rc; + echo "CIF hack added"; +fi + +rm /tmp/ramdisk/boot.img-ramdisk.gz +rm /tmp/boot.img-ramdisk.gz +cd /tmp/ramdisk/ +find . | cpio -o -H newc | gzip > ../boot.img-ramdisk.gz +cd / + diff --git a/release/zimage/kernel/mkbootimg b/release/zimage/kernel/mkbootimg new file mode 100644 index 0000000000000000000000000000000000000000..5b90622cf457c9c4594d15ffa08b4397b62b83ee GIT binary patch literal 64076 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 SPG$5OT=zV3Pq`lGrtu&DFs(5F literal 0 HcmV?d00001 diff --git a/release/zimage/kernel/mkbootimg.sh b/release/zimage/kernel/mkbootimg.sh new file mode 100644 index 00000000000..a09f6588371 --- /dev/null +++ b/release/zimage/kernel/mkbootimg.sh @@ -0,0 +1,6 @@ +#!/sbin/sh +echo \#!/sbin/sh > /tmp/createnewboot.sh +echo /tmp/mkbootimg --kernel /tmp/zImage --ramdisk /tmp/boot.img-ramdisk.gz --cmdline \"$(cat /tmp/boot.img-cmdline)\" --base 0x$(cat /tmp/boot.img-base) --pagesize 2048 --ramdiskaddr 0x82200000 --output /tmp/newboot.img >> /tmp/createnewboot.sh +chmod 777 /tmp/createnewboot.sh +/tmp/createnewboot.sh +return $? diff --git a/release/zimage/kernel/unpackbootimg b/release/zimage/kernel/unpackbootimg new file mode 100644 index 0000000000000000000000000000000000000000..25ac61d16cc34da290e0b2b385aafb0e1da720f2 GIT binary patch literal 58952 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 Y>Nt3A8jfflk^7+K33!in0jPOD0cv52rT_o{ literal 0 HcmV?d00001 diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 78b70d8af60..8d2d5e0f986 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -854,20 +854,18 @@ static void check_section(const char *modname, struct elf_info *elf, #define ALL_INIT_DATA_SECTIONS \ ".init.setup$", ".init.rodata$", \ - ".devinit.rodata$", ".cpuinit.rodata$", ".meminit.rodata$", \ - ".init.data$", ".devinit.data$", ".cpuinit.data$", ".meminit.data$" + ".devinit.rodata$", ".meminit.rodata$", \ + ".init.data$", ".devinit.data$", ".meminit.data$" #define ALL_EXIT_DATA_SECTIONS \ - ".exit.data$", ".devexit.data$", ".cpuexit.data$", ".memexit.data$" + ".exit.data$", ".devexit.data$", ".memexit.data$" #define ALL_INIT_TEXT_SECTIONS \ - ".init.text$", ".devinit.text$", ".cpuinit.text$", ".meminit.text$" + ".init.text$", ".devinit.text$", ".meminit.text$" #define ALL_EXIT_TEXT_SECTIONS \ - ".exit.text$", ".devexit.text$", ".cpuexit.text$", ".memexit.text$" + ".exit.text$", ".devexit.text$", ".memexit.text$" -#define ALL_XXXINIT_SECTIONS DEV_INIT_SECTIONS, CPU_INIT_SECTIONS, \ - MEM_INIT_SECTIONS -#define ALL_XXXEXIT_SECTIONS DEV_EXIT_SECTIONS, CPU_EXIT_SECTIONS, \ - MEM_EXIT_SECTIONS +#define ALL_XXXINIT_SECTIONS DEV_INIT_SECTIONS, MEM_INIT_SECTIONS +#define ALL_XXXEXIT_SECTIONS DEV_EXIT_SECTIONS, MEM_EXIT_SECTIONS #define ALL_INIT_SECTIONS INIT_SECTIONS, ALL_XXXINIT_SECTIONS #define ALL_EXIT_SECTIONS EXIT_SECTIONS, ALL_XXXEXIT_SECTIONS @@ -877,12 +875,10 @@ static void check_section(const char *modname, struct elf_info *elf, #define INIT_SECTIONS ".init.*" #define DEV_INIT_SECTIONS ".devinit.*" -#define CPU_INIT_SECTIONS ".cpuinit.*" #define MEM_INIT_SECTIONS ".meminit.*" #define EXIT_SECTIONS ".exit.*" #define DEV_EXIT_SECTIONS ".devexit.*" -#define CPU_EXIT_SECTIONS ".cpuexit.*" #define MEM_EXIT_SECTIONS ".memexit.*" /* init data sections */ @@ -970,48 +966,20 @@ const struct sectioncheck sectioncheck[] = { .mismatch = DATA_TO_ANY_EXIT, .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, }, -/* Do not reference init code/data from devinit/cpuinit/meminit code/data */ +/* Do not reference init code/data from devinit/meminit code/data */ { .fromsec = { ALL_XXXINIT_SECTIONS, NULL }, .tosec = { INIT_SECTIONS, NULL }, .mismatch = XXXINIT_TO_SOME_INIT, .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, }, -/* Do not reference cpuinit code/data from meminit code/data */ -{ - .fromsec = { MEM_INIT_SECTIONS, NULL }, - .tosec = { CPU_INIT_SECTIONS, NULL }, - .mismatch = XXXINIT_TO_SOME_INIT, - .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, -}, -/* Do not reference meminit code/data from cpuinit code/data */ -{ - .fromsec = { CPU_INIT_SECTIONS, NULL }, - .tosec = { MEM_INIT_SECTIONS, NULL }, - .mismatch = XXXINIT_TO_SOME_INIT, - .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, -}, -/* Do not reference exit code/data from devexit/cpuexit/memexit code/data */ +/* Do not reference exit code/data from devexit/memexit code/data */ { .fromsec = { ALL_XXXEXIT_SECTIONS, NULL }, .tosec = { EXIT_SECTIONS, NULL }, .mismatch = XXXEXIT_TO_SOME_EXIT, .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, }, -/* Do not reference cpuexit code/data from memexit code/data */ -{ - .fromsec = { MEM_EXIT_SECTIONS, NULL }, - .tosec = { CPU_EXIT_SECTIONS, NULL }, - .mismatch = XXXEXIT_TO_SOME_EXIT, - .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, -}, -/* Do not reference memexit code/data from cpuexit code/data */ -{ - .fromsec = { CPU_EXIT_SECTIONS, NULL }, - .tosec = { MEM_EXIT_SECTIONS, NULL }, - .mismatch = XXXEXIT_TO_SOME_EXIT, - .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, -}, /* Do not use exit code/data from init code */ { .fromsec = { ALL_INIT_SECTIONS, NULL }, @@ -1234,7 +1202,6 @@ static Elf_Sym *find_elf_symbol2(struct elf_info *elf, Elf_Addr addr, /* * Convert a section name to the function/data attribute * .init.text => __init - * .cpuinit.data => __cpudata * .memexitconst => __memconst * etc. * diff --git a/scripts/setlocalversion b/scripts/setlocalversion index 857ea4fccb8..5e5702533ab 100755 --- a/scripts/setlocalversion +++ b/scripts/setlocalversion @@ -184,7 +184,6 @@ else # LOCALVERSION= is not specified if test "${LOCALVERSION+set}" != "set"; then scm=$(scm_version --short) - res="$res${scm:++}" fi fi diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index d7018bfa1f0..3068d16cf12 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -1232,6 +1232,7 @@ static int sel_make_bools(void) kfree(bool_pending_names[i]); kfree(bool_pending_names); kfree(bool_pending_values); + bool_num = 0; bool_pending_names = NULL; bool_pending_values = NULL; diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 0e99137db86..aec054a739f 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -454,3 +454,16 @@ config SND_SOC_TPA2028D default n help Texas Instruments 3W Mono Class-D Audio Amplifier + +config SOUND_CONTROL_HAX_GPL + tristate "wcd93xx sound control hax" + default y + help + FauxSound WCD93xx chipset sound control hacks + +config SOUND_CONTROL_HAX_3_GPL + tristate "new wcd93xx sound control hax" + default y + help + FauxSound WCD93xx chipset sound control hacks 3.0 for deeper hax + diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index ec05d3c644d..7e105b53d47 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -213,3 +213,8 @@ obj-$(CONFIG_SND_SOC_MSM_STUB) += snd-soc-msm-stub.o obj-$(CONFIG_SND_SOC_MAX9877) += snd-soc-max9877.o obj-$(CONFIG_SND_SOC_TPA6130A2) += snd-soc-tpa6130a2.o obj-$(CONFIG_SND_SOC_TPA2028D) += tpa2028d.o + +# Hack +obj-$(CONFIG_SOUND_CONTROL_HAX_GPL) += sound_control_gpl.o +obj-$(CONFIG_SOUND_CONTROL_HAX_3_GPL) += sound_control_3_gpl.o + diff --git a/sound/soc/codecs/sound_control_3_gpl.c b/sound/soc/codecs/sound_control_3_gpl.c new file mode 100644 index 00000000000..b7c32860eb4 --- /dev/null +++ b/sound/soc/codecs/sound_control_3_gpl.c @@ -0,0 +1,276 @@ +/* + * Author: Paul Reioux aka Faux123 + * + * WCD93xx sound control module + * Copyright 2013 Paul Reioux + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include +#include + +#define SOUND_CONTROL_MAJOR_VERSION 3 +#define SOUND_CONTROL_MINOR_VERSION 0 + +extern struct snd_soc_codec *fauxsound_codec_ptr; + +unsigned int tabla_read(struct snd_soc_codec *codec, unsigned int reg); +int tabla_write(struct snd_soc_codec *codec, unsigned int reg, + unsigned int value); + +static bool calc_checksum(unsigned int a, unsigned int b, unsigned int c) +{ + unsigned char chksum = 0; + + chksum = ~((a & 0xff) + (b & 0xff)); + + if (chksum == (c & 0xff)) { + return true; + } else { + return false; + } +} + +static ssize_t cam_mic_gain_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + return sprintf(buf, "%u", + tabla_read(fauxsound_codec_ptr, + TABLA_A_CDC_TX6_VOL_CTL_GAIN)); + +} + +static ssize_t cam_mic_gain_store(struct kobject *kobj, + struct kobj_attribute *attr, const char *buf, size_t count) +{ + unsigned int lval, chksum; + + sscanf(buf, "%u %u", &lval, &chksum); + + if (calc_checksum(lval, 0, chksum)) { + tabla_write(fauxsound_codec_ptr, + TABLA_A_CDC_TX6_VOL_CTL_GAIN, lval); + } + return count; +} + +static ssize_t mic_gain_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + return sprintf(buf, "%u", + tabla_read(fauxsound_codec_ptr, + TABLA_A_CDC_TX7_VOL_CTL_GAIN)); +} + +static ssize_t mic_gain_store(struct kobject *kobj, + struct kobj_attribute *attr, const char *buf, size_t count) +{ + unsigned int lval, chksum; + + sscanf(buf, "%u %u", &lval, &chksum); + + if (calc_checksum(lval, 0, chksum)) { + tabla_write(fauxsound_codec_ptr, + TABLA_A_CDC_TX7_VOL_CTL_GAIN, lval); + } + return count; + +} + +static ssize_t speaker_gain_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + return sprintf(buf, "%u %u", + tabla_read(fauxsound_codec_ptr, + TABLA_A_CDC_RX3_VOL_CTL_B2_CTL), + tabla_read(fauxsound_codec_ptr, + TABLA_A_CDC_RX4_VOL_CTL_B2_CTL)); + +} + +static ssize_t speaker_gain_store(struct kobject *kobj, + struct kobj_attribute *attr, const char *buf, size_t count) +{ + unsigned int lval, rval, chksum; + + sscanf(buf, "%u %u %u", &lval, &rval, &chksum); + + if (calc_checksum(lval, rval, chksum)) { + tabla_write(fauxsound_codec_ptr, + TABLA_A_CDC_RX3_VOL_CTL_B2_CTL, lval); + tabla_write(fauxsound_codec_ptr, + TABLA_A_CDC_RX4_VOL_CTL_B2_CTL, rval); + } + return count; +} + +static ssize_t headphone_gain_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + return sprintf(buf, "%u %u", + tabla_read(fauxsound_codec_ptr, + TABLA_A_CDC_RX1_VOL_CTL_B2_CTL), + tabla_read(fauxsound_codec_ptr, + TABLA_A_CDC_RX2_VOL_CTL_B2_CTL)); +} + +static ssize_t headphone_gain_store(struct kobject *kobj, + struct kobj_attribute *attr, const char *buf, size_t count) +{ + unsigned int lval, rval, chksum; + + sscanf(buf, "%u %u %u", &lval, &rval, &chksum); + + if (calc_checksum(lval, rval, chksum)) { + tabla_write(fauxsound_codec_ptr, + TABLA_A_CDC_RX1_VOL_CTL_B2_CTL, lval); + tabla_write(fauxsound_codec_ptr, + TABLA_A_CDC_RX2_VOL_CTL_B2_CTL, rval); + } + return count; +} + +static ssize_t headphone_pa_gain_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + return sprintf(buf, "%u %u", + tabla_read(fauxsound_codec_ptr, TABLA_A_RX_HPH_L_GAIN), + tabla_read(fauxsound_codec_ptr, TABLA_A_RX_HPH_R_GAIN)); +} + +static ssize_t headphone_pa_gain_store(struct kobject *kobj, + struct kobj_attribute *attr, const char *buf, size_t count) +{ + unsigned int lval, rval, chksum; + unsigned int gain, status; + unsigned int out; + + sscanf(buf, "%u %u %u", &lval, &rval, &chksum); + + if (calc_checksum(lval, rval, chksum)) { + gain = tabla_read(fauxsound_codec_ptr, TABLA_A_RX_HPH_L_GAIN); + out = (gain & 0xf0) | lval; + tabla_write(fauxsound_codec_ptr, TABLA_A_RX_HPH_L_GAIN, out); + + status = tabla_read(fauxsound_codec_ptr, TABLA_A_RX_HPH_L_STATUS); + out = (status & 0x0f) | (lval << 4); + tabla_write(fauxsound_codec_ptr, TABLA_A_RX_HPH_L_STATUS, out); + + gain = tabla_read(fauxsound_codec_ptr, TABLA_A_RX_HPH_R_GAIN); + out = (gain & 0xf0) | rval; + tabla_write(fauxsound_codec_ptr, TABLA_A_RX_HPH_R_GAIN, out); + + status = tabla_read(fauxsound_codec_ptr, TABLA_A_RX_HPH_R_STATUS); + out = (status & 0x0f) | (rval << 4); + tabla_write(fauxsound_codec_ptr, TABLA_A_RX_HPH_R_STATUS, out); + } + return count; +} + +static ssize_t sound_control_version_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) +{ + return sprintf(buf, "version: %u.%u\n", + SOUND_CONTROL_MAJOR_VERSION, + SOUND_CONTROL_MINOR_VERSION); +} + +static struct kobj_attribute cam_mic_gain_attribute = + __ATTR(gpl_cam_mic_gain, + 0666, + cam_mic_gain_show, + cam_mic_gain_store); + +static struct kobj_attribute mic_gain_attribute = + __ATTR(gpl_mic_gain, + 0666, + mic_gain_show, + mic_gain_store); + +static struct kobj_attribute speaker_gain_attribute = + __ATTR(gpl_speaker_gain, + 0666, + speaker_gain_show, + speaker_gain_store); + +static struct kobj_attribute headphone_gain_attribute = + __ATTR(gpl_headphone_gain, + 0666, + headphone_gain_show, + headphone_gain_store); + +static struct kobj_attribute headphone_pa_gain_attribute = + __ATTR(gpl_headphone_pa_gain, + 0666, + headphone_pa_gain_show, + headphone_pa_gain_store); + +static struct kobj_attribute sound_control_version_attribute = + __ATTR(gpl_sound_control_version, + 0444, + sound_control_version_show, NULL); + +static struct attribute *sound_control_attrs[] = + { + &cam_mic_gain_attribute.attr, + &mic_gain_attribute.attr, + &speaker_gain_attribute.attr, + &headphone_gain_attribute.attr, + &headphone_pa_gain_attribute.attr, + &sound_control_version_attribute.attr, + NULL, + }; + +static struct attribute_group sound_control_attr_group = + { + .attrs = sound_control_attrs, + }; + +static struct kobject *sound_control_kobj; + +static int sound_control_init(void) +{ + int sysfs_result; + + sound_control_kobj = + kobject_create_and_add("sound_control_3", kernel_kobj); + + if (!sound_control_kobj) { + pr_err("%s sound_control_kobj create failed!\n", + __FUNCTION__); + return -ENOMEM; + } + + sysfs_result = sysfs_create_group(sound_control_kobj, + &sound_control_attr_group); + + if (sysfs_result) { + pr_info("%s sysfs create failed!\n", __FUNCTION__); + kobject_put(sound_control_kobj); + } + return sysfs_result; +} + +static void sound_control_exit(void) +{ + if (sound_control_kobj != NULL) + kobject_put(sound_control_kobj); +} + +module_init(sound_control_init); +module_exit(sound_control_exit); +MODULE_LICENSE("GPL and additional rights"); +MODULE_AUTHOR("Paul Reioux "); +MODULE_DESCRIPTION("Sound Control Module 3.x"); + diff --git a/sound/soc/codecs/sound_control_gpl.c b/sound/soc/codecs/sound_control_gpl.c new file mode 100644 index 00000000000..db50d0d752c --- /dev/null +++ b/sound/soc/codecs/sound_control_gpl.c @@ -0,0 +1,325 @@ +/* + * Author: Paul Reioux aka Faux123 + * + * WCD93xx sound control module + * Copyright 2013 Paul Reioux + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include + +#include +#include + +extern struct snd_kcontrol_new *gpl_faux_snd_controls_ptr; + +#define SOUND_CONTROL_MAJOR_VERSION 2 +#define SOUND_CONTROL_MINOR_VERSION 1 + +#define CAMCORDER_MIC_OFFSET 20 +#define HANDSET_MIC_OFFSET 21 +#define SPEAKER_OFFSET 10 +#define HEADPHONE_L_OFFSET 8 +#define HEADPHONE_R_OFFSET 9 + +#define HEADPHONE_PA_L_OFFSET 6 +#define HEADPHONE_PA_R_OFFSET 7 + +static ssize_t cam_mic_gain_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) +{ + struct soc_mixer_control *l_mixer_ptr; + + l_mixer_ptr = + (struct soc_mixer_control *)gpl_faux_snd_controls_ptr[CAMCORDER_MIC_OFFSET]. + private_value; + + return sprintf(buf, "%d", l_mixer_ptr->max); +} + +static ssize_t cam_mic_gain_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) +{ + int l_max; + int l_delta; + struct soc_mixer_control *l_mixer_ptr; + + l_mixer_ptr = + (struct soc_mixer_control *)gpl_faux_snd_controls_ptr[CAMCORDER_MIC_OFFSET]. + private_value; + + sscanf(buf, "%d", &l_max); + + // limit the max gain + l_delta = l_max - l_mixer_ptr->platform_max; + l_mixer_ptr->platform_max = l_max; + l_mixer_ptr->max = l_max; + l_mixer_ptr->min += l_delta; + + return (count); +} + +static ssize_t mic_gain_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) +{ + struct soc_mixer_control *l_mixer_ptr; + + l_mixer_ptr = + (struct soc_mixer_control *)gpl_faux_snd_controls_ptr[HANDSET_MIC_OFFSET]. + private_value; + + return sprintf(buf, "%d", l_mixer_ptr->max); +} + +static ssize_t mic_gain_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) +{ + int l_max; + int l_delta; + struct soc_mixer_control *l_mixer_ptr; + + l_mixer_ptr = + (struct soc_mixer_control *)gpl_faux_snd_controls_ptr[HANDSET_MIC_OFFSET]. + private_value; + + sscanf(buf, "%d", &l_max); + + l_delta = l_max - l_mixer_ptr->platform_max; + l_mixer_ptr->platform_max = l_max; + l_mixer_ptr->max = l_max; + l_mixer_ptr->min += l_delta; + + return (count); +} + +static ssize_t speaker_gain_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) +{ + struct soc_mixer_control *l_mixer_ptr; + + l_mixer_ptr = + (struct soc_mixer_control *)gpl_faux_snd_controls_ptr[SPEAKER_OFFSET]. + private_value; + + return sprintf(buf, "%d", l_mixer_ptr->max); +} + +static ssize_t speaker_gain_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) +{ + int l_max; + int l_delta; + struct soc_mixer_control *l_mixer_ptr; + + l_mixer_ptr = + (struct soc_mixer_control *)gpl_faux_snd_controls_ptr[SPEAKER_OFFSET]. + private_value; + + sscanf(buf, "%d", &l_max); + + l_delta = l_max - l_mixer_ptr->platform_max; + l_mixer_ptr->platform_max = l_max; + l_mixer_ptr->max = l_max; + l_mixer_ptr->min += l_delta; + + return (count); +} + +static ssize_t headphone_gain_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) +{ + struct soc_mixer_control *l_mixer_ptr, *r_mixer_ptr; + + l_mixer_ptr = + (struct soc_mixer_control *)gpl_faux_snd_controls_ptr[HEADPHONE_L_OFFSET]. + private_value; + r_mixer_ptr = + (struct soc_mixer_control *)gpl_faux_snd_controls_ptr[HEADPHONE_R_OFFSET]. + private_value; + + return sprintf(buf, "%d %d", + l_mixer_ptr->max, + r_mixer_ptr->max); +} + +static ssize_t headphone_gain_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) +{ + int l_max, r_max; + int l_delta, r_delta; + struct soc_mixer_control *l_mixer_ptr, *r_mixer_ptr; + + l_mixer_ptr = + (struct soc_mixer_control *)gpl_faux_snd_controls_ptr[HEADPHONE_L_OFFSET]. + private_value; + r_mixer_ptr = + (struct soc_mixer_control *)gpl_faux_snd_controls_ptr[HEADPHONE_R_OFFSET]. + private_value; + + sscanf(buf, "%d %d", &l_max, &r_max); + + l_delta = l_max - l_mixer_ptr->platform_max; + l_mixer_ptr->platform_max = l_max; + l_mixer_ptr->max = l_max; + l_mixer_ptr->min += l_delta; + + r_delta = r_max - r_mixer_ptr->platform_max; + r_mixer_ptr->platform_max = r_max; + r_mixer_ptr->max = r_max; + r_mixer_ptr->min += r_delta; + + return count; +} + +static ssize_t headphone_pa_gain_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) +{ + struct soc_mixer_control *l_mixer_ptr, *r_mixer_ptr; + + l_mixer_ptr = + (struct soc_mixer_control *) + gpl_faux_snd_controls_ptr[HEADPHONE_PA_L_OFFSET]. + private_value; + r_mixer_ptr = + (struct soc_mixer_control *) + gpl_faux_snd_controls_ptr[HEADPHONE_PA_R_OFFSET]. + private_value; + + return sprintf(buf, "%d %d", + l_mixer_ptr->max, + r_mixer_ptr->max); +} + +static ssize_t headphone_pa_gain_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) +{ + int l_max, r_max; + int l_delta, r_delta; + struct soc_mixer_control *l_mixer_ptr, *r_mixer_ptr; + + l_mixer_ptr = + (struct soc_mixer_control *) + gpl_faux_snd_controls_ptr[HEADPHONE_PA_L_OFFSET]. + private_value; + r_mixer_ptr = + (struct soc_mixer_control *) + gpl_faux_snd_controls_ptr[HEADPHONE_PA_R_OFFSET]. + private_value; + + sscanf(buf, "%d %d", &l_max, &r_max); + + l_delta = l_max - l_mixer_ptr->platform_max; + l_mixer_ptr->platform_max = l_max; + l_mixer_ptr->max = l_max; + l_mixer_ptr->min += l_delta; + + r_delta = r_max - r_mixer_ptr->platform_max; + r_mixer_ptr->platform_max = r_max; + r_mixer_ptr->max = r_max; + r_mixer_ptr->min += r_delta; + + return count; +} + +static ssize_t sound_control_version_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) +{ + return sprintf(buf, "version: %u.%u\n", + SOUND_CONTROL_MAJOR_VERSION, + SOUND_CONTROL_MINOR_VERSION); +} + +static struct kobj_attribute cam_mic_gain_attribute = + __ATTR(gpl_cam_mic_gain, + 0666, + cam_mic_gain_show, + cam_mic_gain_store); + +static struct kobj_attribute mic_gain_attribute = + __ATTR(gpl_mic_gain, + 0666, + mic_gain_show, + mic_gain_store); + +static struct kobj_attribute speaker_gain_attribute = + __ATTR(gpl_speaker_gain, + 0666, + speaker_gain_show, + speaker_gain_store); + +static struct kobj_attribute headphone_gain_attribute = + __ATTR(gpl_headphone_gain, + 0666, + headphone_gain_show, + headphone_gain_store); + +static struct kobj_attribute headphone_pa_gain_attribute = + __ATTR(gpl_headphone_pa_gain, + 0666, + headphone_pa_gain_show, + headphone_pa_gain_store); + +static struct kobj_attribute sound_control_version_attribute = + __ATTR(gpl_sound_control_version, + 0444, + sound_control_version_show, NULL); + +static struct attribute *sound_control_attrs[] = + { + &cam_mic_gain_attribute.attr, + &mic_gain_attribute.attr, + &speaker_gain_attribute.attr, + &headphone_gain_attribute.attr, + &headphone_pa_gain_attribute.attr, + &sound_control_version_attribute.attr, + NULL, + }; + +static struct attribute_group sound_control_attr_group = + { + .attrs = sound_control_attrs, + }; + +static struct kobject *sound_control_kobj; + +static int sound_control_init(void) +{ + int sysfs_result; + + if (gpl_faux_snd_controls_ptr == NULL) { + pr_err("%s sound_controls_ptr is NULL!\n", __FUNCTION__); + return -1; + } + + sound_control_kobj = + kobject_create_and_add("sound_control", kernel_kobj); + + if (!sound_control_kobj) { + pr_err("%s sound_control_kobj create failed!\n", + __FUNCTION__); + return -ENOMEM; + } + + sysfs_result = sysfs_create_group(sound_control_kobj, + &sound_control_attr_group); + + if (sysfs_result) { + pr_info("%s sysfs create failed!\n", __FUNCTION__); + kobject_put(sound_control_kobj); + } + return sysfs_result; +} + +static void sound_control_exit(void) +{ + if (sound_control_kobj != NULL) + kobject_put(sound_control_kobj); +} + +module_init(sound_control_init); +module_exit(sound_control_exit); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Paul Reioux "); +MODULE_DESCRIPTION("Sound Control Module GPL Edition"); + diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c index 3b9fa6de897..e84ff57933d 100644 --- a/sound/soc/codecs/wcd9310.c +++ b/sound/soc/codecs/wcd9310.c @@ -3852,6 +3852,7 @@ static int tabla_readable(struct snd_soc_codec *ssc, unsigned int reg) return tabla_reg_readable[reg]; } + static bool tabla_is_digital_gain_register(unsigned int reg) { bool rtn = false; @@ -3920,7 +3921,10 @@ static int tabla_volatile(struct snd_soc_codec *ssc, unsigned int reg) } #define TABLA_FORMATS (SNDRV_PCM_FMTBIT_S16_LE) -static int tabla_write(struct snd_soc_codec *codec, unsigned int reg, +#ifndef CONFIG_SOUND_CONTROL_HAX_GPL +static +#endif +int tabla_write(struct snd_soc_codec *codec, unsigned int reg, unsigned int value) { int ret; @@ -3935,7 +3939,14 @@ static int tabla_write(struct snd_soc_codec *codec, unsigned int reg, return wcd9xxx_reg_write(codec->control_data, reg, value); } -static unsigned int tabla_read(struct snd_soc_codec *codec, +#ifdef CONFIG_SOUND_CONTROL_HAX_GPL +EXPORT_SYMBOL(tabla_write); +#endif + +#ifndef CONFIG_SOUND_CONTROL_HAX_GPL +static +#endif +unsigned int tabla_read(struct snd_soc_codec *codec, unsigned int reg) { unsigned int val; @@ -3956,6 +3967,9 @@ static unsigned int tabla_read(struct snd_soc_codec *codec, val = wcd9xxx_reg_read(codec->control_data, reg); return val; } +#ifdef CONFIG_SOUND_CONTROL_HAX_GPL +EXPORT_SYMBOL(tabla_read); +#endif static s16 tabla_get_current_v_ins(struct tabla_priv *tabla, bool hu) { @@ -8391,6 +8405,13 @@ static const struct file_operations codec_mbhc_debug_ops = { }; #endif +#ifdef CONFIG_SOUND_CONTROL_HAX_GPL +struct snd_kcontrol_new *gpl_faux_snd_controls_ptr = + (struct snd_kcontrol_new *)tabla_snd_controls; +struct snd_soc_codec *fauxsound_codec_ptr; +EXPORT_SYMBOL(fauxsound_codec_ptr); +#endif + static int tabla_codec_probe(struct snd_soc_codec *codec) { struct wcd9xxx *control; @@ -8400,10 +8421,16 @@ static int tabla_codec_probe(struct snd_soc_codec *codec) int i; int ch_cnt; +#ifdef CONFIG_SOUND_CONTROL_HAX_GPL + pr_info("tabla codec probe...\n"); + fauxsound_codec_ptr = codec; +#endif + codec->control_data = dev_get_drvdata(codec->dev->parent); control = codec->control_data; tabla = kzalloc(sizeof(struct tabla_priv), GFP_KERNEL); + if (!tabla) { dev_err(codec->dev, "Failed to allocate private data\n"); return -ENOMEM; diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index ab23869c01b..04a09dbb4c4 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -1420,7 +1420,7 @@ static int parse_audio_mixer_unit(struct mixer_build *state, int unitid, void *r static int mixer_ctl_procunit_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct usb_mixer_elem_info *cval = kcontrol->private_data; - int err, val; + int err, val = 0; err = get_cur_ctl_value(cval, cval->control << 8, &val); if (err < 0 && cval->mixer->ignore_ctl_error) { @@ -1438,7 +1438,7 @@ static int mixer_ctl_procunit_get(struct snd_kcontrol *kcontrol, struct snd_ctl_ static int mixer_ctl_procunit_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct usb_mixer_elem_info *cval = kcontrol->private_data; - int val, oval, err; + int val, oval = 0, err; err = get_cur_ctl_value(cval, cval->control << 8, &oval); if (err < 0) { @@ -1701,7 +1701,7 @@ static int mixer_ctl_selector_info(struct snd_kcontrol *kcontrol, struct snd_ctl static int mixer_ctl_selector_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct usb_mixer_elem_info *cval = kcontrol->private_data; - int val, err; + int val = 0, err; err = get_cur_ctl_value(cval, cval->control << 8, &val); if (err < 0) { @@ -1720,7 +1720,7 @@ static int mixer_ctl_selector_get(struct snd_kcontrol *kcontrol, struct snd_ctl_ static int mixer_ctl_selector_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct usb_mixer_elem_info *cval = kcontrol->private_data; - int val, oval, err; + int val, oval = 0, err; err = get_cur_ctl_value(cval, cval->control << 8, &oval); if (err < 0) { diff --git a/tools/usb/ffs-test.c b/tools/usb/ffs-test.c index 4b107b5e623..8674b9ec14f 100644 --- a/tools/usb/ffs-test.c +++ b/tools/usb/ffs-test.c @@ -297,7 +297,7 @@ static void *start_thread_helper(void *arg) ret = t->in(t, t->buf, t->buf_size); if (ret > 0) { - ret = t->out(t, t->buf, t->buf_size); + ret = t->out(t, t->buf, ret); name = out_name; op = "write"; } else { From 8a5e6e364e9932d7140961008186145e0a655fac Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Fri, 15 Nov 2013 15:06:36 +0100 Subject: [PATCH 002/215] AOSP naming for aroma and localversion --- arch/arm/configs/flo_defconfig | 2 +- release/aroma/META-INF/com/google/android/aroma-config | 2 +- release/aroma/META-INF/com/google/android/aroma/changelog.txt | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/configs/flo_defconfig b/arch/arm/configs/flo_defconfig index 3506b40fda5..4743ff62d2e 100644 --- a/arch/arm/configs/flo_defconfig +++ b/arch/arm/configs/flo_defconfig @@ -40,7 +40,7 @@ CONFIG_IRQ_WORK=y CONFIG_EXPERIMENTAL=y CONFIG_INIT_ENV_ARG_LIMIT=32 CONFIG_CROSS_COMPILE="" -CONFIG_LOCALVERSION="-Glitch-Flo" +CONFIG_LOCALVERSION="-Glitch-Flo-AOSP" # CONFIG_LOCALVERSION_AUTO is not set CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_LZMA=y diff --git a/release/aroma/META-INF/com/google/android/aroma-config b/release/aroma/META-INF/com/google/android/aroma-config index 1f31527cc44..a47d537d06b 100755 --- a/release/aroma/META-INF/com/google/android/aroma-config +++ b/release/aroma/META-INF/com/google/android/aroma-config @@ -31,7 +31,7 @@ # * AROMA Temporary Dir = /tmp/aroma/ ini_set("rom_name", "Glitch kernel"); -ini_set("rom_version", "Flo-CAF"); +ini_set("rom_version", "Flo-AOSP"); ini_set("rom_author", "Tk-Glitch"); ini_set("rom_device", "Nexus 7 (2013)"); ini_set("rom_date", "November 2013"); diff --git a/release/aroma/META-INF/com/google/android/aroma/changelog.txt b/release/aroma/META-INF/com/google/android/aroma/changelog.txt index 400d9a746bb..8775e519ffa 100755 --- a/release/aroma/META-INF/com/google/android/aroma/changelog.txt +++ b/release/aroma/META-INF/com/google/android/aroma/changelog.txt @@ -1,6 +1,6 @@ -Glitch kernel "CAF" for flo +Glitch kernel "AOSP" for flo -- Based on CyanogenMod 3.4.0 kernel source for MSM devices updated to linux 3.4.1 +- Based on AOSP 3.4.0 kernel source for MSM devices updated to linux 3.4.1 - CPU OC up to 2.3Ghz with OV/UV support - L2/bus speed OC up to 1.49GHz / 4.96GBPS - GPU OC up to 627 MHz From db32737b489083781fc8ef9f91136f9497804cda Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Fri, 15 Nov 2013 16:52:57 +0100 Subject: [PATCH 003/215] block : Add updated ROW i/o scheduling algorithm Signed-off-by: Tk-Glitch --- Documentation/block/row-iosched.txt | 186 +++++ arch/arm/configs/flo_defconfig | 6 +- block/Kconfig.iosched | 22 + block/Makefile | 1 + block/blk-core.c | 95 ++- block/blk-settings.c | 12 + block/blk-sysfs.c | 2 + block/elevator.c | 40 + block/row-iosched.c | 1090 +++++++++++++++++++++++++++ include/linux/blk_types.h | 4 +- include/linux/blkdev.h | 6 + include/linux/elevator.h | 7 + 12 files changed, 1463 insertions(+), 8 deletions(-) create mode 100644 Documentation/block/row-iosched.txt create mode 100644 block/row-iosched.c diff --git a/Documentation/block/row-iosched.txt b/Documentation/block/row-iosched.txt new file mode 100644 index 00000000000..343c276129d --- /dev/null +++ b/Documentation/block/row-iosched.txt @@ -0,0 +1,186 @@ +Introduction +============ + +The ROW scheduling algorithm will be used in mobile devices as default +block layer IO scheduling algorithm. ROW stands for "READ Over WRITE" +which is the main requests dispatch policy of this algorithm. + +The ROW IO scheduler was developed with the mobile devices needs in +mind. In mobile devices we favor user experience upon everything else, +thus we want to give READ IO requests as much priority as possible. +The main idea of the ROW scheduling policy is just that: +- If there are READ requests in pipe - dispatch them, while write +starvation is considered. + +Software description +==================== +The elevator defines a registering mechanism for different IO scheduler +to implement. This makes implementing a new algorithm quite straight +forward and requires almost no changes to block/elevator framework. A +new IO scheduler just has to implement a set of callback functions +defined by the elevator. +These callbacks cover all the required IO operations such as +adding/removing request to/from the scheduler, merging two requests, +dispatching a request etc. + +Design +====== + +The requests are kept in queues according to their priority. The +dispatching of requests is done in a Round Robin manner with a +different slice for each queue. The dispatch quantum for a specific +queue is set according to the queues priority. READ queues are +given bigger dispatch quantum than the WRITE queues, within a dispatch +cycle. + +At the moment there are 6 types of queues the requests are +distributed to: +- High priority READ queue +- High priority Synchronous WRITE queue +- Regular priority READ queue +- Regular priority Synchronous WRITE queue +- Regular priority WRITE queue +- Low priority READ queue + +The marking of request as high/low priority will be done by the +application adding the request and not the scheduler. See TODO section. +If the request is not marked in any way (high/low) the scheduler +assigns it to one of the regular priority queues: +read/write/sync write. + +If in a certain dispatch cycle one of the queues was empty and didn't +use its quantum that queue will be marked as "un-served". If we're in +a middle of a dispatch cycle dispatching from queue Y and a request +arrives for queue X that was un-served in the previous cycle, if X's +priority is higher than Y's, queue X will be preempted in the favor of +queue Y. + +For READ request queues ROW IO scheduler allows idling within a +dispatch quantum in order to give the application a chance to insert +more requests. Idling means adding some extra time for serving a +certain queue even if the queue is empty. The idling is enabled if +the ROW IO scheduler identifies the application is inserting requests +in a high frequency. +Not all queues can idle. ROW scheduler exposes an enablement struct +for idling. +For idling on READ queues, the ROW IO scheduler uses timer mechanism. +When the timer expires we schedule a delayed work that will signal the +device driver to fetch another request for dispatch. + +ROW scheduler will support additional services for block devices that +supports Urgent Requests. That is, the scheduler may inform the +device driver upon urgent requests using a newly defined callback. +In addition it will support rescheduling of requests that were +interrupted. For example if the device driver issues a long write +request and a sudden urgent request is received by the scheduler. +The scheduler will inform the device driver about the urgent request, +so the device driver can stop the current write request and serve the +urgent request. In such a case the device driver may also insert back +to the scheduler the remainder of the interrupted write request, such +that the scheduler may continue sending urgent requests without the +need to interrupt the ongoing write again and again. The write +remainder will be sent later on according to the scheduler policy. + +SMP/multi-core +============== +At the moment the code is accessed from 2 contexts: +- Application context (from block/elevator layer): adding the requests. +- device driver thread: dispatching the requests and notifying on + completion. + +One lock is used to synchronize between the two. This lock is provided +by the block device driver along with the dispatch queue. + +Performance +=========== +Several performance tests were run in order to compare the ROW +scheduler to existing scheduling algorithms: + +1. Parallel sequential READ and sequential WRITE +The test was performed by running two parallel lmdd commands. + +IO scheduling| R Throughput| W Throughput| Worst case R | Worst case W + Algorithm | [MB/sec] | [MB/sec] | Latency [sec]| Latency [sec] +-------------|-------------|-------------|--------------|-------------- +no-op | 11.73 | 19.67 | 3830.00 | 4257.50 +deadline | 11.84 | 20.11 | 610.00 | 5267.50 +cfq | 20.39 | 12.32 | 353.33 | 8673.33 +ROW | 35.75 | 12.08 | 70.00 | 13695.00 + +R = READ, W = WRITE + +2. Parallel Random READ with sequential WRITE: +The test was performed by running lmdd WRITE command in parallel to +iozone. + +IO scheduling| R performance| W Throughput| Worst case R | Worst case W + Algorithm | [iops] | [MB/sec] | Latency [sec]| Latency [sec] +-------------|--------------|-------------|--------------|-------------- +no-op | 1909.25 | 20.82 | 3240.00 | 4175.00 +deadline | 1912.25 | 20.26 | 432.50 | 5372.50 +cfq | 1771.60 | 14.05 | 60.00 | 8786.00 +ROW | 1857.00 | 18.86 | 62.00 | 4718.00 + +R = READ, W = WRITE + +3. Parallel Random READ with sequential READ: +The test was performed by running lmdd WRITE command in parallel to +iozone. + +IO scheduling| R performance| W Throughput| Worst case R | Worst case W + Algorithm | [iops] | [MB/sec] | Latency [sec]| Latency [sec] +-------------|--------------|-------------|--------------|-------------- +no-op | 1919.50 | 35.59 | 32.50 | 300.00 +deadline | 1913.00 | 35.68 | 30.00 | 302.50 +cfq | 1789.20 | 23.19 | 264.00 | 864.00 +ROW | 1850.80 | 38.13 | 32.00 | 2206.00 + +R = READ, W = WRITE + +Note: the above measurements were collected on a particular system +configuration and may be different on other. We performed tests on +other system configurations as well. The numbers were different but +the main idea was the same - reduced latency and increased throughput. + + +Config options +============== +1. hp_read_quantum: dispatch quantum for the high priority READ queue + (default is 100 requests) +2. rp_read_quantum: dispatch quantum for the regular priority READ + queue (default is 100 requests) +3. hp_swrite_quantum: dispatch quantum for the high priority + Synchronous WRITE queue (default is 2 requests) +4. rp_swrite_quantum: dispatch quantum for the regular priority + Synchronous WRITE queue (default is 1 requests) +5. rp_write_quantum: dispatch quantum for the regular priority WRITE + queue (default is 1 requests) +6. lp_read_quantum: dispatch quantum for the low priority READ queue + (default is 1 requests) +7. lp_swrite_quantum: dispatch quantum for the low priority Synchronous + WRITE queue (default is 1 requests) +8. read_idle: how long to idle on read queue in Msec (in case idling + is enabled on that queue). (default is 1 requests) +9. read_idle_freq: frequency of inserting READ requests that will + trigger idling. This is the time in Msec between inserting two READ + requests. (default is 1 requests) + +Note: Dispatch quantum is number of requests that will be dispatched +from a certain queue in a dispatch cycle. + +To do +===== +The ROW algorithm takes the scheduling policy one step further, making +it a bit more "user-needs oriented", by allowing the application to +hint on the urgency of its requests. For example: even among the READ +requests several requests may be more urgent for completion than other. +The former will go to the High priority READ queue, that is given the +bigger dispatch quantum than any other queue. + +Still need to design the way applications will "hint" on the urgency of +their requests. May be done by ioctl(). We need to look into concrete +use-cases in order to determine the best solution for this. +This will be implemented as a second phase. + +Design and implement additional services for block devices that +supports High Priority Requests. \ No newline at end of file diff --git a/arch/arm/configs/flo_defconfig b/arch/arm/configs/flo_defconfig index 4743ff62d2e..c1498297ace 100644 --- a/arch/arm/configs/flo_defconfig +++ b/arch/arm/configs/flo_defconfig @@ -222,15 +222,17 @@ CONFIG_EFI_PARTITION=y CONFIG_IOSCHED_NOOP=y # CONFIG_IOSCHED_TEST is not set CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_ROW=y CONFIG_IOSCHED_CFQ=y CONFIG_IOSCHED_FIOPS=y CONFIG_IOSCHED_SIO=y # CONFIG_DEFAULT_DEADLINE is not set -CONFIG_DEFAULT_CFQ=y +CONFIG_DEFAULT_ROW=y +# CONFIG_DEFAULT_CFQ is not set # CONFIG_DEFAULT_FIOPS is not set # CONFIG_DEFAULT_SIO is not set # CONFIG_DEFAULT_NOOP is not set -CONFIG_DEFAULT_IOSCHED="cfq" +CONFIG_DEFAULT_IOSCHED="row" # CONFIG_INLINE_SPIN_TRYLOCK is not set # CONFIG_INLINE_SPIN_TRYLOCK_BH is not set # CONFIG_INLINE_SPIN_LOCK is not set diff --git a/block/Kconfig.iosched b/block/Kconfig.iosched index 4e7030d9c1d..58911655d25 100644 --- a/block/Kconfig.iosched +++ b/block/Kconfig.iosched @@ -32,6 +32,17 @@ config IOSCHED_DEADLINE a new point in the service tree and doing a batch of IO from there in case of expiry. +config IOSCHED_ROW + tristate "ROW I/O scheduler" + default y + ---help--- + The ROW I/O scheduler gives priority to READ requests over the + WRITE requests when dispatching, without starving WRITE requests. + Requests are kept in priority queues. Dispatching is done in a RR + manner when the dispatch quantum for each queue is calculated + according to queue priority. + Most suitable for mobile devices. + config IOSCHED_CFQ tristate "CFQ I/O scheduler" # If BLK_CGROUP is a module, CFQ has to be built as module. @@ -82,6 +93,16 @@ choice config DEFAULT_DEADLINE bool "Deadline" if IOSCHED_DEADLINE=y + config DEFAULT_ROW + bool "ROW" if IOSCHED_ROW=y + help + The ROW I/O scheduler gives priority to READ requests + over the WRITE requests when dispatching, without starving + WRITE requests. Requests are kept in priority queues. + Dispatching is done in a RR manner when the dispatch quantum + for each queue is defined according to queue priority. + Most suitable for mobile devices. + config DEFAULT_CFQ bool "CFQ" if IOSCHED_CFQ=y @@ -99,6 +120,7 @@ endchoice config DEFAULT_IOSCHED string default "deadline" if DEFAULT_DEADLINE + default "row" if DEFAULT_ROW default "cfq" if DEFAULT_CFQ default "fiops" if DEFAULT_FIOPS default "sio" if DEFAULT_SIO diff --git a/block/Makefile b/block/Makefile index 109892dd0bc..b962c7609b6 100644 --- a/block/Makefile +++ b/block/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_BLK_CGROUP) += blk-cgroup.o obj-$(CONFIG_BLK_DEV_THROTTLING) += blk-throttle.o obj-$(CONFIG_IOSCHED_NOOP) += noop-iosched.o obj-$(CONFIG_IOSCHED_DEADLINE) += deadline-iosched.o +obj-$(CONFIG_IOSCHED_ROW) += row-iosched.o obj-$(CONFIG_IOSCHED_CFQ) += cfq-iosched.o obj-$(CONFIG_IOSCHED_TEST) += test-iosched.o obj-$(CONFIG_IOSCHED_FIOPS) += fiops-iosched.o diff --git a/block/blk-core.c b/block/blk-core.c index 68d7158aeb6..69764dfbd80 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -29,6 +29,7 @@ #include #include #include +#include #define CREATE_TRACE_POINTS #include @@ -297,13 +298,26 @@ EXPORT_SYMBOL(blk_sync_queue); * Description: * See @blk_run_queue. This variant must be called with the queue lock * held and interrupts disabled. + * Device driver will be notified of an urgent request + * pending under the following conditions: + * 1. The driver and the current scheduler support urgent reques handling + * 2. There is an urgent request pending in the scheduler + * 3. There isn't already an urgent request in flight, meaning previously + * notified urgent request completed (!q->notified_urgent) */ void __blk_run_queue(struct request_queue *q) { if (unlikely(blk_queue_stopped(q))) return; - q->request_fn(q); + if (!q->notified_urgent && + q->elevator->type->ops.elevator_is_urgent_fn && + q->urgent_request_fn && + q->elevator->type->ops.elevator_is_urgent_fn(q)) { + q->notified_urgent = true; + q->urgent_request_fn(q); + } else + q->request_fn(q); } EXPORT_SYMBOL(__blk_run_queue); @@ -1066,10 +1080,74 @@ void blk_requeue_request(struct request_queue *q, struct request *rq) BUG_ON(blk_queued_rq(rq)); + if (rq->cmd_flags & REQ_URGENT) { + /* + * It's not compliant with the design to re-insert + * urgent requests. We want to be able to track this + * down. + */ + pr_err("%s(): requeueing an URGENT request", __func__); + WARN_ON(!q->dispatched_urgent); + q->dispatched_urgent = false; + } elv_requeue_request(q, rq); } EXPORT_SYMBOL(blk_requeue_request); +/** + * blk_reinsert_request() - Insert a request back to the scheduler + * @q: request queue + * @rq: request to be inserted + * + * This function inserts the request back to the scheduler as if + * it was never dispatched. + * + * Return: 0 on success, error code on fail + */ +int blk_reinsert_request(struct request_queue *q, struct request *rq) +{ + if (unlikely(!rq) || unlikely(!q)) + return -EIO; + + blk_delete_timer(rq); + blk_clear_rq_complete(rq); + trace_block_rq_requeue(q, rq); + + if (blk_rq_tagged(rq)) + blk_queue_end_tag(q, rq); + + BUG_ON(blk_queued_rq(rq)); + if (rq->cmd_flags & REQ_URGENT) { + /* + * It's not compliant with the design to re-insert + * urgent requests. We want to be able to track this + * down. + */ + pr_err("%s(): requeueing an URGENT request", __func__); + WARN_ON(!q->dispatched_urgent); + q->dispatched_urgent = false; + } + + return elv_reinsert_request(q, rq); +} +EXPORT_SYMBOL(blk_reinsert_request); + +/** + * blk_reinsert_req_sup() - check whether the scheduler supports + * reinsertion of requests + * @q: request queue + * + * Returns true if the current scheduler supports reinserting + * request. False otherwise + */ +bool blk_reinsert_req_sup(struct request_queue *q) +{ + if (unlikely(!q)) + return false; + return q->elevator->type->ops.elevator_reinsert_req_fn ? true : false; +} +EXPORT_SYMBOL(blk_reinsert_req_sup); + static void add_acct_request(struct request_queue *q, struct request *rq, int where) { @@ -2073,8 +2151,13 @@ struct request *blk_fetch_request(struct request_queue *q) struct request *rq; rq = blk_peek_request(q); - if (rq) + if (rq) { + if (rq->cmd_flags & REQ_URGENT) { + WARN_ON(q->dispatched_urgent); + q->dispatched_urgent = true; + } blk_start_request(rq); + } return rq; } EXPORT_SYMBOL(blk_fetch_request); @@ -2141,9 +2224,11 @@ bool blk_update_request(struct request *req, int error, unsigned int nr_bytes) error_type = "I/O"; break; } - printk(KERN_ERR "end_request: %s error, dev %s, sector %llu\n", - error_type, req->rq_disk ? req->rq_disk->disk_name : "?", - (unsigned long long)blk_rq_pos(req)); + printk_ratelimited( + KERN_ERR "end_request: %s error, dev %s, sector %llu\n", + error_type, + req->rq_disk ? req->rq_disk->disk_name : "?", + (unsigned long long)blk_rq_pos(req)); } blk_account_io_completion(req, nr_bytes); diff --git a/block/blk-settings.c b/block/blk-settings.c index d3234fc494a..579328cff6d 100644 --- a/block/blk-settings.c +++ b/block/blk-settings.c @@ -99,6 +99,18 @@ void blk_queue_lld_busy(struct request_queue *q, lld_busy_fn *fn) } EXPORT_SYMBOL_GPL(blk_queue_lld_busy); +/** + * blk_urgent_request() - Set an urgent_request handler function for queue + * @q: queue + * @fn: handler for urgent requests + * + */ +void blk_urgent_request(struct request_queue *q, request_fn_proc *fn) +{ + q->urgent_request_fn = fn; +} +EXPORT_SYMBOL(blk_urgent_request); + /** * blk_set_default_limits - reset limits to default values * @lim: the queue_limits structure to reset diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c index cf150011d80..262ed815e07 100644 --- a/block/blk-sysfs.c +++ b/block/blk-sysfs.c @@ -200,6 +200,8 @@ queue_store_##name(struct request_queue *q, const char *page, size_t count) \ unsigned long val; \ ssize_t ret; \ ret = queue_var_store(&val, page, count); \ + if (ret < 0) \ + return ret; \ if (neg) \ val = !val; \ \ diff --git a/block/elevator.c b/block/elevator.c index 74fd51b154f..27adf7c0372 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -585,6 +585,41 @@ void elv_requeue_request(struct request_queue *q, struct request *rq) __elv_add_request(q, rq, ELEVATOR_INSERT_REQUEUE); } +/** + * elv_reinsert_request() - Insert a request back to the scheduler + * @q: request queue where request should be inserted + * @rq: request to be inserted + * + * This function returns the request back to the scheduler to be + * inserted as if it was never dispatched + * + * Return: 0 on success, error code on failure + */ +int elv_reinsert_request(struct request_queue *q, struct request *rq) +{ + int res; + + if (!q->elevator->type->ops.elevator_reinsert_req_fn) + return -EPERM; + + res = q->elevator->type->ops.elevator_reinsert_req_fn(q, rq); + if (!res) { + /* + * it already went through dequeue, we need to decrement the + * in_flight count again + */ + if (blk_account_rq(rq)) { + q->in_flight[rq_is_sync(rq)]--; + if (rq->cmd_flags & REQ_SORTED) + elv_deactivate_rq(q, rq); + } + rq->cmd_flags &= ~REQ_STARTED; + q->nr_sorted++; + } + + return res; +} + void elv_drain_elevator(struct request_queue *q) { static int printed; @@ -779,6 +814,11 @@ void elv_completed_request(struct request_queue *q, struct request *rq) { struct elevator_queue *e = q->elevator; + if (rq->cmd_flags & REQ_URGENT) { + q->notified_urgent = false; + WARN_ON(!q->dispatched_urgent); + q->dispatched_urgent = false; + } /* * request is released from the driver, io must be done */ diff --git a/block/row-iosched.c b/block/row-iosched.c new file mode 100644 index 00000000000..ad30e81499a --- /dev/null +++ b/block/row-iosched.c @@ -0,0 +1,1090 @@ +/* + * ROW (Read Over Write) I/O scheduler. + * + * Copyright (c) 2012-2013, The Linux Foundation. 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 and + * only 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. + */ + +/* See Documentation/block/row-iosched.txt */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * enum row_queue_prio - Priorities of the ROW queues + * + * This enum defines the priorities (and the number of queues) + * the requests will be distributed to. The higher priority - + * the bigger is the "bus time" (or the dispatch quantum) given + * to that queue. + * ROWQ_PRIO_HIGH_READ - is the higher priority queue. + * + */ +enum row_queue_prio { + ROWQ_PRIO_HIGH_READ = 0, + ROWQ_PRIO_HIGH_SWRITE, + ROWQ_PRIO_REG_READ, + ROWQ_PRIO_REG_SWRITE, + ROWQ_PRIO_REG_WRITE, + ROWQ_PRIO_LOW_READ, + ROWQ_PRIO_LOW_SWRITE, + ROWQ_MAX_PRIO, +}; + +/* + * The following indexes define the distribution of ROW queues according to + * priorities. Each index defines the first queue in that priority group. + */ +#define ROWQ_HIGH_PRIO_IDX ROWQ_PRIO_HIGH_READ +#define ROWQ_REG_PRIO_IDX ROWQ_PRIO_REG_READ +#define ROWQ_LOW_PRIO_IDX ROWQ_PRIO_LOW_READ + +/** + * struct row_queue_params - ROW queue parameters + * @idling_enabled: Flag indicating whether idling is enable on + * the queue + * @quantum: Number of requests to be dispatched from this queue + * in a dispatch cycle + * @is_urgent: Flags indicating whether the queue can notify on + * urgent requests + * + */ +struct row_queue_params { + bool idling_enabled; + int quantum; + bool is_urgent; +}; + +/* + * This array holds the default values of the different configurables + * for each ROW queue. Each row of the array holds the following values: + * {idling_enabled, quantum, is_urgent} + * Each row corresponds to a queue with the same index (according to + * enum row_queue_prio) + * Note: The quantums are valid inside their priority type. For example: + * For every 10 high priority read requests, 1 high priority sync + * write will be dispatched. + * For every 100 regular read requests 1 regular write request will + * be dispatched. + */ +static const struct row_queue_params row_queues_def[] = { +/* idling_enabled, quantum, is_urgent */ + {true, 10, true}, /* ROWQ_PRIO_HIGH_READ */ + {false, 1, false}, /* ROWQ_PRIO_HIGH_SWRITE */ + {true, 100, true}, /* ROWQ_PRIO_REG_READ */ + {false, 1, false}, /* ROWQ_PRIO_REG_SWRITE */ + {false, 1, false}, /* ROWQ_PRIO_REG_WRITE */ + {false, 1, false}, /* ROWQ_PRIO_LOW_READ */ + {false, 1, false} /* ROWQ_PRIO_LOW_SWRITE */ +}; + +/* Default values for idling on read queues (in msec) */ +#define ROW_IDLE_TIME_MSEC 5 +#define ROW_READ_FREQ_MSEC 20 + +/** + * struct rowq_idling_data - parameters for idling on the queue + * @last_insert_time: time the last request was inserted + * to the queue + * @begin_idling: flag indicating wether we should idle + * + */ +struct rowq_idling_data { + ktime_t last_insert_time; + bool begin_idling; +}; + +/** + * struct row_queue - requests grouping structure + * @rdata: parent row_data structure + * @fifo: fifo of requests + * @prio: queue priority (enum row_queue_prio) + * @nr_dispatched: number of requests already dispatched in + * the current dispatch cycle + * @nr_req: number of requests in queue + * @dispatch quantum: number of requests this queue may + * dispatch in a dispatch cycle + * @idle_data: data for idling on queues + * + */ +struct row_queue { + struct row_data *rdata; + struct list_head fifo; + enum row_queue_prio prio; + + unsigned int nr_dispatched; + + unsigned int nr_req; + int disp_quantum; + + /* used only for READ queues */ + struct rowq_idling_data idle_data; +}; + +/** + * struct idling_data - data for idling on empty rqueue + * @idle_time_ms: idling duration (msec) + * @freq_ms: min time between two requests that + * triger idling (msec) + * @hr_timer: idling timer + * @idle_work: the work to be scheduled when idling timer expires + * @idling_queue_idx: index of the queues we're idling on + * + */ +struct idling_data { + s64 idle_time_ms; + s64 freq_ms; + + struct hrtimer hr_timer; + struct work_struct idle_work; + enum row_queue_prio idling_queue_idx; +}; + +/** + * struct starvation_data - data for starvation management + * @starvation_limit: number of times this priority class + * can tolerate being starved + * @starvation_counter: number of requests from higher + * priority classes that were dispatched while this + * priority request were pending + * + */ +struct starvation_data { + int starvation_limit; + int starvation_counter; +}; + +/** + * struct row_queue - Per block device rqueue structure + * @dispatch_queue: dispatch rqueue + * @row_queues: array of priority request queues + * @rd_idle_data: data for idling after READ request + * @nr_reqs: nr_reqs[0] holds the number of all READ requests in + * scheduler, nr_reqs[1] holds the number of all WRITE + * requests in scheduler + * @urgent_in_flight: flag indicating that there is an urgent + * request that was dispatched to driver and is yet to + * complete. + * @pending_urgent_rq: pointer to the pending urgent request + * @last_served_ioprio_class: I/O priority class that was last dispatched from + * @reg_prio_starvation: starvation data for REGULAR priority queues + * @low_prio_starvation: starvation data for LOW priority queues + * @cycle_flags: used for marking unserved queueus + * + */ +struct row_data { + struct request_queue *dispatch_queue; + + struct row_queue row_queues[ROWQ_MAX_PRIO]; + + struct idling_data rd_idle_data; + unsigned int nr_reqs[2]; + bool urgent_in_flight; + struct request *pending_urgent_rq; + int last_served_ioprio_class; + +#define ROW_REG_STARVATION_TOLLERANCE 5000 + struct starvation_data reg_prio_starvation; +#define ROW_LOW_STARVATION_TOLLERANCE 10000 + struct starvation_data low_prio_starvation; + + unsigned int cycle_flags; +}; + +#define RQ_ROWQ(rq) ((struct row_queue *) ((rq)->elv.priv[0])) + +#define row_log(q, fmt, args...) \ + blk_add_trace_msg(q, "%s():" fmt , __func__, ##args) +#define row_log_rowq(rdata, rowq_id, fmt, args...) \ + blk_add_trace_msg(rdata->dispatch_queue, "rowq%d " fmt, \ + rowq_id, ##args) + +static inline void row_mark_rowq_unserved(struct row_data *rd, + enum row_queue_prio qnum) +{ + rd->cycle_flags |= (1 << qnum); +} + +static inline void row_clear_rowq_unserved(struct row_data *rd, + enum row_queue_prio qnum) +{ + rd->cycle_flags &= ~(1 << qnum); +} + +static inline int row_rowq_unserved(struct row_data *rd, + enum row_queue_prio qnum) +{ + return rd->cycle_flags & (1 << qnum); +} + +static inline void __maybe_unused row_dump_queues_stat(struct row_data *rd) +{ + int i; + + row_log(rd->dispatch_queue, " Queues status:"); + for (i = 0; i < ROWQ_MAX_PRIO; i++) + row_log(rd->dispatch_queue, + "queue%d: dispatched= %d, nr_req=%d", i, + rd->row_queues[i].nr_dispatched, + rd->row_queues[i].nr_req); +} + +/******************** Static helper functions ***********************/ +static void kick_queue(struct work_struct *work) +{ + struct idling_data *read_data = + container_of(work, struct idling_data, idle_work); + struct row_data *rd = + container_of(read_data, struct row_data, rd_idle_data); + + blk_run_queue(rd->dispatch_queue); +} + + +static enum hrtimer_restart row_idle_hrtimer_fn(struct hrtimer *hr_timer) +{ + struct idling_data *read_data = + container_of(hr_timer, struct idling_data, hr_timer); + struct row_data *rd = + container_of(read_data, struct row_data, rd_idle_data); + + row_log_rowq(rd, rd->rd_idle_data.idling_queue_idx, + "Performing delayed work"); + /* Mark idling process as done */ + rd->row_queues[rd->rd_idle_data.idling_queue_idx]. + idle_data.begin_idling = false; + rd->rd_idle_data.idling_queue_idx = ROWQ_MAX_PRIO; + + if (!rd->nr_reqs[READ] && !rd->nr_reqs[WRITE]) + row_log(rd->dispatch_queue, "No requests in scheduler"); + else + kblockd_schedule_work(rd->dispatch_queue, + &read_data->idle_work); + return HRTIMER_NORESTART; +} + +/* + * row_regular_req_pending() - Check if there are REGULAR priority requests + * Pending in scheduler + * @rd: pointer to struct row_data + * + * Returns True if there are REGULAR priority requests in scheduler queues. + * False, otherwise. + */ +static inline bool row_regular_req_pending(struct row_data *rd) +{ + int i; + + for (i = ROWQ_REG_PRIO_IDX; i < ROWQ_LOW_PRIO_IDX; i++) + if (!list_empty(&rd->row_queues[i].fifo)) + return true; + return false; +} + +/* + * row_low_req_pending() - Check if there are LOW priority requests + * Pending in scheduler + * @rd: pointer to struct row_data + * + * Returns True if there are LOW priority requests in scheduler queues. + * False, otherwise. + */ +static inline bool row_low_req_pending(struct row_data *rd) +{ + int i; + + for (i = ROWQ_LOW_PRIO_IDX; i < ROWQ_MAX_PRIO; i++) + if (!list_empty(&rd->row_queues[i].fifo)) + return true; + return false; +} + +/******************* Elevator callback functions *********************/ + +/* + * row_add_request() - Add request to the scheduler + * @q: requests queue + * @rq: request to add + * + */ +static void row_add_request(struct request_queue *q, + struct request *rq) +{ + struct row_data *rd = (struct row_data *)q->elevator->elevator_data; + struct row_queue *rqueue = RQ_ROWQ(rq); + s64 diff_ms; + bool queue_was_empty = list_empty(&rqueue->fifo); + + list_add_tail(&rq->queuelist, &rqueue->fifo); + rd->nr_reqs[rq_data_dir(rq)]++; + rqueue->nr_req++; + rq_set_fifo_time(rq, jiffies); /* for statistics*/ + + if (rq->cmd_flags & REQ_URGENT) { + WARN_ON(1); + blk_dump_rq_flags(rq, ""); + rq->cmd_flags &= ~REQ_URGENT; + } + + if (row_queues_def[rqueue->prio].idling_enabled) { + if (rd->rd_idle_data.idling_queue_idx == rqueue->prio && + hrtimer_active(&rd->rd_idle_data.hr_timer)) { + (void)hrtimer_cancel(&rd->rd_idle_data.hr_timer); + row_log_rowq(rd, rqueue->prio, + "Canceled delayed work on %d", + rd->rd_idle_data.idling_queue_idx); + rd->rd_idle_data.idling_queue_idx = ROWQ_MAX_PRIO; + } + diff_ms = ktime_to_ms(ktime_sub(ktime_get(), + rqueue->idle_data.last_insert_time)); + if (unlikely(diff_ms < 0)) { + pr_err("%s(): time delta error: diff_ms < 0", + __func__); + rqueue->idle_data.begin_idling = false; + return; + } + if (diff_ms < rd->rd_idle_data.freq_ms) { + rqueue->idle_data.begin_idling = true; + row_log_rowq(rd, rqueue->prio, "Enable idling"); + } else { + rqueue->idle_data.begin_idling = false; + row_log_rowq(rd, rqueue->prio, "Disable idling (%ldms)", + (long)diff_ms); + } + + rqueue->idle_data.last_insert_time = ktime_get(); + } + if (row_queues_def[rqueue->prio].is_urgent && + !rd->pending_urgent_rq && !rd->urgent_in_flight) { + /* Handle High Priority queues */ + if (rqueue->prio < ROWQ_REG_PRIO_IDX && + rd->last_served_ioprio_class != IOPRIO_CLASS_RT && + queue_was_empty) { + row_log_rowq(rd, rqueue->prio, + "added (high prio) urgent request"); + rq->cmd_flags |= REQ_URGENT; + rd->pending_urgent_rq = rq; + } else if (row_rowq_unserved(rd, rqueue->prio)) { + /* Handle Regular priotity queues */ + row_log_rowq(rd, rqueue->prio, + "added urgent request (total on queue=%d)", + rqueue->nr_req); + rq->cmd_flags |= REQ_URGENT; + WARN_ON(rqueue->nr_req > 1); + rd->pending_urgent_rq = rq; + } + } else + row_log_rowq(rd, rqueue->prio, + "added request (total on queue=%d)", rqueue->nr_req); +} + +/** + * row_reinsert_req() - Reinsert request back to the scheduler + * @q: requests queue + * @rq: request to add + * + * Reinsert the given request back to the queue it was + * dispatched from as if it was never dispatched. + * + * Returns 0 on success, error code otherwise + */ +static int row_reinsert_req(struct request_queue *q, + struct request *rq) +{ + struct row_data *rd = q->elevator->elevator_data; + struct row_queue *rqueue = RQ_ROWQ(rq); + + if (!rqueue || rqueue->prio >= ROWQ_MAX_PRIO) + return -EIO; + + list_add(&rq->queuelist, &rqueue->fifo); + rd->nr_reqs[rq_data_dir(rq)]++; + rqueue->nr_req++; + + row_log_rowq(rd, rqueue->prio, + "%s request reinserted (total on queue=%d)", + (rq_data_dir(rq) == READ ? "READ" : "write"), rqueue->nr_req); + + if (rq->cmd_flags & REQ_URGENT) { + /* + * It's not compliant with the design to re-insert + * urgent requests. We want to be able to track this + * down. + */ + WARN_ON(1); + if (!rd->urgent_in_flight) { + pr_err("%s(): no urgent in flight", __func__); + } else { + rd->urgent_in_flight = false; + pr_err("%s(): reinserting URGENT %s req", + __func__, + (rq_data_dir(rq) == READ ? "READ" : "WRITE")); + if (rd->pending_urgent_rq) { + pr_err("%s(): urgent rq is pending", + __func__); + rd->pending_urgent_rq->cmd_flags &= ~REQ_URGENT; + } + rd->pending_urgent_rq = rq; + } + } + return 0; +} + +static void row_completed_req(struct request_queue *q, struct request *rq) +{ + struct row_data *rd = q->elevator->elevator_data; + + if (rq->cmd_flags & REQ_URGENT) { + if (!rd->urgent_in_flight) { + WARN_ON(1); + pr_err("%s(): URGENT req but urgent_in_flight = F", + __func__); + } + rd->urgent_in_flight = false; + rq->cmd_flags &= ~REQ_URGENT; + } + row_log(q, "completed %s %s req.", + (rq->cmd_flags & REQ_URGENT ? "URGENT" : "regular"), + (rq_data_dir(rq) == READ ? "READ" : "WRITE")); +} + +/** + * row_urgent_pending() - Return TRUE if there is an urgent + * request on scheduler + * @q: requests queue + */ +static bool row_urgent_pending(struct request_queue *q) +{ + struct row_data *rd = q->elevator->elevator_data; + + if (rd->urgent_in_flight) { + row_log(rd->dispatch_queue, "%d urgent requests in flight", + rd->urgent_in_flight); + return false; + } + + if (rd->pending_urgent_rq) { + row_log(rd->dispatch_queue, "Urgent request pending"); + return true; + } + + row_log(rd->dispatch_queue, "no urgent request pending/in flight"); + return false; +} + +/** + * row_remove_request() - Remove given request from scheduler + * @q: requests queue + * @rq: request to remove + * + */ +static void row_remove_request(struct row_data *rd, + struct request *rq) +{ + struct row_queue *rqueue = RQ_ROWQ(rq); + + list_del_init(&(rq)->queuelist); + if (rd->pending_urgent_rq == rq) + rd->pending_urgent_rq = NULL; + else + BUG_ON(rq->cmd_flags & REQ_URGENT); + rqueue->nr_req--; + rd->nr_reqs[rq_data_dir(rq)]--; +} + +/* + * row_dispatch_insert() - move request to dispatch queue + * @rd: pointer to struct row_data + * @rq: the request to dispatch + * + * This function moves the given request to the dispatch queue + * + */ +static void row_dispatch_insert(struct row_data *rd, struct request *rq) +{ + struct row_queue *rqueue = RQ_ROWQ(rq); + + row_remove_request(rd, rq); + elv_dispatch_sort(rd->dispatch_queue, rq); + if (rq->cmd_flags & REQ_URGENT) { + WARN_ON(rd->urgent_in_flight); + rd->urgent_in_flight = true; + } + rqueue->nr_dispatched++; + row_clear_rowq_unserved(rd, rqueue->prio); + row_log_rowq(rd, rqueue->prio, + " Dispatched request %p nr_disp = %d", rq, + rqueue->nr_dispatched); + if (rqueue->prio < ROWQ_REG_PRIO_IDX) { + rd->last_served_ioprio_class = IOPRIO_CLASS_RT; + if (row_regular_req_pending(rd)) + rd->reg_prio_starvation.starvation_counter++; + if (row_low_req_pending(rd)) + rd->low_prio_starvation.starvation_counter++; + } else if (rqueue->prio < ROWQ_LOW_PRIO_IDX) { + rd->last_served_ioprio_class = IOPRIO_CLASS_BE; + rd->reg_prio_starvation.starvation_counter = 0; + if (row_low_req_pending(rd)) + rd->low_prio_starvation.starvation_counter++; + } else { + rd->last_served_ioprio_class = IOPRIO_CLASS_IDLE; + rd->low_prio_starvation.starvation_counter = 0; + } +} + +/* + * row_get_ioprio_class_to_serve() - Return the next I/O priority + * class to dispatch requests from + * @rd: pointer to struct row_data + * @force: flag indicating if forced dispatch + * + * This function returns the next I/O priority class to serve + * {IOPRIO_CLASS_NONE, IOPRIO_CLASS_RT, IOPRIO_CLASS_BE, IOPRIO_CLASS_IDLE}. + * If there are no more requests in scheduler or if we're idling on some queue + * IOPRIO_CLASS_NONE will be returned. + * If idling is scheduled on a lower priority queue than the one that needs + * to be served, it will be canceled. + * + */ +static int row_get_ioprio_class_to_serve(struct row_data *rd, int force) +{ + int i; + int ret = IOPRIO_CLASS_NONE; + + if (!rd->nr_reqs[READ] && !rd->nr_reqs[WRITE]) { + row_log(rd->dispatch_queue, "No more requests in scheduler"); + goto check_idling; + } + + /* First, go over the high priority queues */ + for (i = 0; i < ROWQ_REG_PRIO_IDX; i++) { + if (!list_empty(&rd->row_queues[i].fifo)) { + if (hrtimer_active(&rd->rd_idle_data.hr_timer)) { + (void)hrtimer_cancel( + &rd->rd_idle_data.hr_timer); + row_log_rowq(rd, + rd->rd_idle_data.idling_queue_idx, + "Canceling delayed work on %d. RT pending", + rd->rd_idle_data.idling_queue_idx); + rd->rd_idle_data.idling_queue_idx = + ROWQ_MAX_PRIO; + } + + if (row_regular_req_pending(rd) && + (rd->reg_prio_starvation.starvation_counter >= + rd->reg_prio_starvation.starvation_limit)) + ret = IOPRIO_CLASS_BE; + else if (row_low_req_pending(rd) && + (rd->low_prio_starvation.starvation_counter >= + rd->low_prio_starvation.starvation_limit)) + ret = IOPRIO_CLASS_IDLE; + else + ret = IOPRIO_CLASS_RT; + + goto done; + } + } + + /* + * At the moment idling is implemented only for READ queues. + * If enabled on WRITE, this needs updating + */ + if (hrtimer_active(&rd->rd_idle_data.hr_timer)) { + row_log(rd->dispatch_queue, "Delayed work pending. Exiting"); + goto done; + } +check_idling: + /* Check for (high priority) idling and enable if needed */ + for (i = 0; i < ROWQ_REG_PRIO_IDX && !force; i++) { + if (rd->row_queues[i].idle_data.begin_idling && + row_queues_def[i].idling_enabled) + goto initiate_idling; + } + + /* Regular priority queues */ + for (i = ROWQ_REG_PRIO_IDX; i < ROWQ_LOW_PRIO_IDX; i++) { + if (list_empty(&rd->row_queues[i].fifo)) { + /* We can idle only if this is not a forced dispatch */ + if (rd->row_queues[i].idle_data.begin_idling && + !force && row_queues_def[i].idling_enabled) + goto initiate_idling; + } else { + if (row_low_req_pending(rd) && + (rd->low_prio_starvation.starvation_counter >= + rd->low_prio_starvation.starvation_limit)) + ret = IOPRIO_CLASS_IDLE; + else + ret = IOPRIO_CLASS_BE; + goto done; + } + } + + if (rd->nr_reqs[READ] || rd->nr_reqs[WRITE]) + ret = IOPRIO_CLASS_IDLE; + goto done; + +initiate_idling: + hrtimer_start(&rd->rd_idle_data.hr_timer, + ktime_set(0, rd->rd_idle_data.idle_time_ms * NSEC_PER_MSEC), + HRTIMER_MODE_REL); + + rd->rd_idle_data.idling_queue_idx = i; + row_log_rowq(rd, i, "Scheduled delayed work on %d. exiting", i); + +done: + return ret; +} + +static void row_restart_cycle(struct row_data *rd, + int start_idx, int end_idx) +{ + int i; + + row_dump_queues_stat(rd); + for (i = start_idx; i < end_idx; i++) { + if (rd->row_queues[i].nr_dispatched < + rd->row_queues[i].disp_quantum) + row_mark_rowq_unserved(rd, i); + rd->row_queues[i].nr_dispatched = 0; + } + row_log(rd->dispatch_queue, "Restarting cycle for class @ %d-%d", + start_idx, end_idx); +} + +/* + * row_get_next_queue() - selects the next queue to dispatch from + * @q: requests queue + * @rd: pointer to struct row_data + * @start_idx/end_idx: indexes in the row_queues array to select a queue + * from. + * + * Return index of the queues to dispatch from. Error code if fails. + * + */ +static int row_get_next_queue(struct request_queue *q, struct row_data *rd, + int start_idx, int end_idx) +{ + int i = start_idx; + bool restart = true; + int ret = -EIO; + + do { + if (list_empty(&rd->row_queues[i].fifo) || + rd->row_queues[i].nr_dispatched >= + rd->row_queues[i].disp_quantum) { + i++; + if (i == end_idx && restart) { + /* Restart cycle for this priority class */ + row_restart_cycle(rd, start_idx, end_idx); + i = start_idx; + restart = false; + } + } else { + ret = i; + break; + } + } while (i < end_idx); + + return ret; +} + +/* + * row_dispatch_requests() - selects the next request to dispatch + * @q: requests queue + * @force: flag indicating if forced dispatch + * + * Return 0 if no requests were moved to the dispatch queue. + * 1 otherwise + * + */ +static int row_dispatch_requests(struct request_queue *q, int force) +{ + struct row_data *rd = (struct row_data *)q->elevator->elevator_data; + int ret = 0, currq, ioprio_class_to_serve, start_idx, end_idx; + + if (force && hrtimer_active(&rd->rd_idle_data.hr_timer)) { + (void)hrtimer_cancel(&rd->rd_idle_data.hr_timer); + row_log_rowq(rd, rd->rd_idle_data.idling_queue_idx, + "Canceled delayed work on %d - forced dispatch", + rd->rd_idle_data.idling_queue_idx); + rd->rd_idle_data.idling_queue_idx = ROWQ_MAX_PRIO; + } + + if (rd->pending_urgent_rq) { + row_log(rd->dispatch_queue, "dispatching urgent request"); + row_dispatch_insert(rd, rd->pending_urgent_rq); + ret = 1; + goto done; + } + + ioprio_class_to_serve = row_get_ioprio_class_to_serve(rd, force); + row_log(rd->dispatch_queue, "Dispatching from %d priority class", + ioprio_class_to_serve); + + switch (ioprio_class_to_serve) { + case IOPRIO_CLASS_NONE: + rd->last_served_ioprio_class = IOPRIO_CLASS_NONE; + goto done; + case IOPRIO_CLASS_RT: + start_idx = ROWQ_HIGH_PRIO_IDX; + end_idx = ROWQ_REG_PRIO_IDX; + break; + case IOPRIO_CLASS_BE: + start_idx = ROWQ_REG_PRIO_IDX; + end_idx = ROWQ_LOW_PRIO_IDX; + break; + case IOPRIO_CLASS_IDLE: + start_idx = ROWQ_LOW_PRIO_IDX; + end_idx = ROWQ_MAX_PRIO; + break; + default: + pr_err("%s(): Invalid I/O priority class", __func__); + goto done; + } + + currq = row_get_next_queue(q, rd, start_idx, end_idx); + + /* Dispatch */ + if (currq >= 0) { + row_dispatch_insert(rd, + rq_entry_fifo(rd->row_queues[currq].fifo.next)); + ret = 1; + } +done: + return ret; +} + +/* + * row_init_queue() - Init scheduler data structures + * @q: requests queue + * + * Return pointer to struct row_data to be saved in elevator for + * this dispatch queue + * + */ +static void *row_init_queue(struct request_queue *q) +{ + + struct row_data *rdata; + int i; + + rdata = kmalloc_node(sizeof(*rdata), + GFP_KERNEL | __GFP_ZERO, q->node); + if (!rdata) + return NULL; + + memset(rdata, 0, sizeof(*rdata)); + for (i = 0; i < ROWQ_MAX_PRIO; i++) { + INIT_LIST_HEAD(&rdata->row_queues[i].fifo); + rdata->row_queues[i].disp_quantum = row_queues_def[i].quantum; + rdata->row_queues[i].rdata = rdata; + rdata->row_queues[i].prio = i; + rdata->row_queues[i].idle_data.begin_idling = false; + rdata->row_queues[i].idle_data.last_insert_time = + ktime_set(0, 0); + } + + rdata->reg_prio_starvation.starvation_limit = + ROW_REG_STARVATION_TOLLERANCE; + rdata->low_prio_starvation.starvation_limit = + ROW_LOW_STARVATION_TOLLERANCE; + /* + * Currently idling is enabled only for READ queues. If we want to + * enable it for write queues also, note that idling frequency will + * be the same in both cases + */ + rdata->rd_idle_data.idle_time_ms = ROW_IDLE_TIME_MSEC; + rdata->rd_idle_data.freq_ms = ROW_READ_FREQ_MSEC; + hrtimer_init(&rdata->rd_idle_data.hr_timer, + CLOCK_MONOTONIC, HRTIMER_MODE_REL); + rdata->rd_idle_data.hr_timer.function = &row_idle_hrtimer_fn; + + INIT_WORK(&rdata->rd_idle_data.idle_work, kick_queue); + rdata->last_served_ioprio_class = IOPRIO_CLASS_NONE; + rdata->rd_idle_data.idling_queue_idx = ROWQ_MAX_PRIO; + rdata->dispatch_queue = q; + + return rdata; +} + +/* + * row_exit_queue() - called on unloading the RAW scheduler + * @e: poiner to struct elevator_queue + * + */ +static void row_exit_queue(struct elevator_queue *e) +{ + struct row_data *rd = (struct row_data *)e->elevator_data; + int i; + + for (i = 0; i < ROWQ_MAX_PRIO; i++) + BUG_ON(!list_empty(&rd->row_queues[i].fifo)); + if (hrtimer_cancel(&rd->rd_idle_data.hr_timer)) + pr_err("%s(): idle timer was active!", __func__); + rd->rd_idle_data.idling_queue_idx = ROWQ_MAX_PRIO; + kfree(rd); +} + +/* + * row_merged_requests() - Called when 2 requests are merged + * @q: requests queue + * @rq: request the two requests were merged into + * @next: request that was merged + */ +static void row_merged_requests(struct request_queue *q, struct request *rq, + struct request *next) +{ + struct row_queue *rqueue = RQ_ROWQ(next); + + list_del_init(&next->queuelist); + rqueue->nr_req--; + if (rqueue->rdata->pending_urgent_rq == next) { + pr_err("\n\nROW_WARNING: merging pending urgent!"); + rqueue->rdata->pending_urgent_rq = rq; + rq->cmd_flags |= REQ_URGENT; + WARN_ON(!(next->cmd_flags & REQ_URGENT)); + next->cmd_flags &= ~REQ_URGENT; + } + rqueue->rdata->nr_reqs[rq_data_dir(rq)]--; +} + +/* + * row_get_queue_prio() - Get queue priority for a given request + * + * This is a helping function which purpose is to determine what + * ROW queue the given request should be added to (and + * dispatched from later on) + * + */ +static enum row_queue_prio row_get_queue_prio(struct request *rq, + struct row_data *rd) +{ + const int data_dir = rq_data_dir(rq); + const bool is_sync = rq_is_sync(rq); + enum row_queue_prio q_type = ROWQ_MAX_PRIO; + int ioprio_class = IOPRIO_PRIO_CLASS(rq->elv.icq->ioc->ioprio); + + switch (ioprio_class) { + case IOPRIO_CLASS_RT: + if (data_dir == READ) + q_type = ROWQ_PRIO_HIGH_READ; + else if (is_sync) + q_type = ROWQ_PRIO_HIGH_SWRITE; + else { + pr_err("%s:%s(): got a simple write from RT_CLASS. How???", + rq->rq_disk->disk_name, __func__); + q_type = ROWQ_PRIO_REG_WRITE; + } + break; + case IOPRIO_CLASS_IDLE: + if (data_dir == READ) + q_type = ROWQ_PRIO_LOW_READ; + else if (is_sync) + q_type = ROWQ_PRIO_LOW_SWRITE; + else { + pr_err("%s:%s(): got a simple write from IDLE_CLASS. How???", + rq->rq_disk->disk_name, __func__); + q_type = ROWQ_PRIO_REG_WRITE; + } + break; + case IOPRIO_CLASS_NONE: + case IOPRIO_CLASS_BE: + default: + if (data_dir == READ) + q_type = ROWQ_PRIO_REG_READ; + else if (is_sync) + q_type = ROWQ_PRIO_REG_SWRITE; + else + q_type = ROWQ_PRIO_REG_WRITE; + break; + } + + return q_type; +} + +/* + * row_set_request() - Set ROW data structures associated with this request. + * @q: requests queue + * @rq: pointer to the request + * @gfp_mask: ignored + * + */ +static int +row_set_request(struct request_queue *q, struct request *rq, gfp_t gfp_mask) +{ + struct row_data *rd = (struct row_data *)q->elevator->elevator_data; + unsigned long flags; + + spin_lock_irqsave(q->queue_lock, flags); + rq->elv.priv[0] = + (void *)(&rd->row_queues[row_get_queue_prio(rq, rd)]); + spin_unlock_irqrestore(q->queue_lock, flags); + + return 0; +} + +/********** Helping sysfs functions/defenitions for ROW attributes ******/ +static ssize_t row_var_show(int var, char *page) +{ + return snprintf(page, 100, "%d\n", var); +} + +static ssize_t row_var_store(int *var, const char *page, size_t count) +{ + int err; + err = kstrtoul(page, 10, (unsigned long *)var); + + return count; +} + +#define SHOW_FUNCTION(__FUNC, __VAR) \ +static ssize_t __FUNC(struct elevator_queue *e, char *page) \ +{ \ + struct row_data *rowd = e->elevator_data; \ + int __data = __VAR; \ + return row_var_show(__data, (page)); \ +} +SHOW_FUNCTION(row_hp_read_quantum_show, + rowd->row_queues[ROWQ_PRIO_HIGH_READ].disp_quantum); +SHOW_FUNCTION(row_rp_read_quantum_show, + rowd->row_queues[ROWQ_PRIO_REG_READ].disp_quantum); +SHOW_FUNCTION(row_hp_swrite_quantum_show, + rowd->row_queues[ROWQ_PRIO_HIGH_SWRITE].disp_quantum); +SHOW_FUNCTION(row_rp_swrite_quantum_show, + rowd->row_queues[ROWQ_PRIO_REG_SWRITE].disp_quantum); +SHOW_FUNCTION(row_rp_write_quantum_show, + rowd->row_queues[ROWQ_PRIO_REG_WRITE].disp_quantum); +SHOW_FUNCTION(row_lp_read_quantum_show, + rowd->row_queues[ROWQ_PRIO_LOW_READ].disp_quantum); +SHOW_FUNCTION(row_lp_swrite_quantum_show, + rowd->row_queues[ROWQ_PRIO_LOW_SWRITE].disp_quantum); +SHOW_FUNCTION(row_rd_idle_data_show, rowd->rd_idle_data.idle_time_ms); +SHOW_FUNCTION(row_rd_idle_data_freq_show, rowd->rd_idle_data.freq_ms); +SHOW_FUNCTION(row_reg_starv_limit_show, + rowd->reg_prio_starvation.starvation_limit); +SHOW_FUNCTION(row_low_starv_limit_show, + rowd->low_prio_starvation.starvation_limit); +#undef SHOW_FUNCTION + +#define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX) \ +static ssize_t __FUNC(struct elevator_queue *e, \ + const char *page, size_t count) \ +{ \ + struct row_data *rowd = e->elevator_data; \ + int __data; \ + int ret = row_var_store(&__data, (page), count); \ + if (__data < (MIN)) \ + __data = (MIN); \ + else if (__data > (MAX)) \ + __data = (MAX); \ + *(__PTR) = __data; \ + return ret; \ +} +STORE_FUNCTION(row_hp_read_quantum_store, +&rowd->row_queues[ROWQ_PRIO_HIGH_READ].disp_quantum, 1, INT_MAX); +STORE_FUNCTION(row_rp_read_quantum_store, + &rowd->row_queues[ROWQ_PRIO_REG_READ].disp_quantum, + 1, INT_MAX); +STORE_FUNCTION(row_hp_swrite_quantum_store, + &rowd->row_queues[ROWQ_PRIO_HIGH_SWRITE].disp_quantum, + 1, INT_MAX); +STORE_FUNCTION(row_rp_swrite_quantum_store, + &rowd->row_queues[ROWQ_PRIO_REG_SWRITE].disp_quantum, + 1, INT_MAX); +STORE_FUNCTION(row_rp_write_quantum_store, + &rowd->row_queues[ROWQ_PRIO_REG_WRITE].disp_quantum, + 1, INT_MAX); +STORE_FUNCTION(row_lp_read_quantum_store, + &rowd->row_queues[ROWQ_PRIO_LOW_READ].disp_quantum, + 1, INT_MAX); +STORE_FUNCTION(row_lp_swrite_quantum_store, + &rowd->row_queues[ROWQ_PRIO_LOW_SWRITE].disp_quantum, + 1, INT_MAX); +STORE_FUNCTION(row_rd_idle_data_store, &rowd->rd_idle_data.idle_time_ms, + 1, INT_MAX); +STORE_FUNCTION(row_rd_idle_data_freq_store, &rowd->rd_idle_data.freq_ms, + 1, INT_MAX); +STORE_FUNCTION(row_reg_starv_limit_store, + &rowd->reg_prio_starvation.starvation_limit, + 1, INT_MAX); +STORE_FUNCTION(row_low_starv_limit_store, + &rowd->low_prio_starvation.starvation_limit, + 1, INT_MAX); + +#undef STORE_FUNCTION + +#define ROW_ATTR(name) \ + __ATTR(name, S_IRUGO|S_IWUSR, row_##name##_show, \ + row_##name##_store) + +static struct elv_fs_entry row_attrs[] = { + ROW_ATTR(hp_read_quantum), + ROW_ATTR(rp_read_quantum), + ROW_ATTR(hp_swrite_quantum), + ROW_ATTR(rp_swrite_quantum), + ROW_ATTR(rp_write_quantum), + ROW_ATTR(lp_read_quantum), + ROW_ATTR(lp_swrite_quantum), + ROW_ATTR(rd_idle_data), + ROW_ATTR(rd_idle_data_freq), + ROW_ATTR(reg_starv_limit), + ROW_ATTR(low_starv_limit), + __ATTR_NULL +}; + +static struct elevator_type iosched_row = { + .ops = { + .elevator_merge_req_fn = row_merged_requests, + .elevator_dispatch_fn = row_dispatch_requests, + .elevator_add_req_fn = row_add_request, + .elevator_reinsert_req_fn = row_reinsert_req, + .elevator_is_urgent_fn = row_urgent_pending, + .elevator_completed_req_fn = row_completed_req, + .elevator_former_req_fn = elv_rb_former_request, + .elevator_latter_req_fn = elv_rb_latter_request, + .elevator_set_req_fn = row_set_request, + .elevator_init_fn = row_init_queue, + .elevator_exit_fn = row_exit_queue, + }, + .icq_size = sizeof(struct io_cq), + .icq_align = __alignof__(struct io_cq), + .elevator_attrs = row_attrs, + .elevator_name = "row", + .elevator_owner = THIS_MODULE, +}; + +static int __init row_init(void) +{ + elv_register(&iosched_row); + return 0; +} + +static void __exit row_exit(void) +{ + elv_unregister(&iosched_row); +} + +module_init(row_init); +module_exit(row_exit); + +MODULE_LICENSE("GPLv2"); +MODULE_DESCRIPTION("Read Over Write IO scheduler"); + + diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h index 9c49d17cbe1..2b4542a285b 100644 --- a/include/linux/blk_types.h +++ b/include/linux/blk_types.h @@ -135,7 +135,7 @@ enum rq_flag_bits { * throttling rules. Don't do it again. */ /* request only flags */ - __REQ_SORTED, /* elevator knows about this request */ + __REQ_SORTED = __REQ_RAHEAD, /* elevator knows about this request */ __REQ_SOFTBARRIER, /* may not be passed by ioscheduler */ __REQ_NOMERGE, /* don't touch this for merging */ __REQ_STARTED, /* drive already may have started this one */ @@ -151,6 +151,7 @@ enum rq_flag_bits { __REQ_IO_STAT, /* account I/O stat */ __REQ_MIXED_MERGE, /* merge of different types, fail separately */ __REQ_SANITIZE, /* sanitize */ + __REQ_URGENT, /* urgent request */ __REQ_NR_BITS, /* stops here */ }; @@ -163,6 +164,7 @@ enum rq_flag_bits { #define REQ_PRIO (1 << __REQ_PRIO) #define REQ_DISCARD (1 << __REQ_DISCARD) #define REQ_SANITIZE (1 << __REQ_SANITIZE) +#define REQ_URGENT (1 << __REQ_URGENT) #define REQ_NOIDLE (1 << __REQ_NOIDLE) #define REQ_FAILFAST_MASK \ diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index e76b0ae3368..65028417fbc 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -282,6 +282,7 @@ struct request_queue { struct request_list rq; request_fn_proc *request_fn; + request_fn_proc *urgent_request_fn; make_request_fn *make_request_fn; prep_rq_fn *prep_rq_fn; unprep_rq_fn *unprep_rq_fn; @@ -365,6 +366,8 @@ struct request_queue { struct list_head icq_list; struct queue_limits limits; + bool notified_urgent; + bool dispatched_urgent; /* * sg stuff @@ -673,6 +676,8 @@ extern struct request *blk_get_request(struct request_queue *, int, gfp_t); extern struct request *blk_make_request(struct request_queue *, struct bio *, gfp_t); extern void blk_requeue_request(struct request_queue *, struct request *); +extern int blk_reinsert_request(struct request_queue *q, struct request *rq); +extern bool blk_reinsert_req_sup(struct request_queue *q); extern void blk_add_request_payload(struct request *rq, struct page *page, unsigned int len); extern int blk_rq_check_limits(struct request_queue *q, struct request *rq); @@ -822,6 +827,7 @@ extern struct request_queue *blk_init_queue_node(request_fn_proc *rfn, extern struct request_queue *blk_init_queue(request_fn_proc *, spinlock_t *); extern struct request_queue *blk_init_allocated_queue(struct request_queue *, request_fn_proc *, spinlock_t *); +extern void blk_urgent_request(struct request_queue *q, request_fn_proc *fn); extern void blk_cleanup_queue(struct request_queue *); extern void blk_queue_make_request(struct request_queue *, make_request_fn *); extern void blk_queue_bounce_limit(struct request_queue *, u64); diff --git a/include/linux/elevator.h b/include/linux/elevator.h index 7d4e0356f32..b36b28ffd31 100644 --- a/include/linux/elevator.h +++ b/include/linux/elevator.h @@ -22,6 +22,9 @@ typedef void (elevator_bio_merged_fn) (struct request_queue *, typedef int (elevator_dispatch_fn) (struct request_queue *, int); typedef void (elevator_add_req_fn) (struct request_queue *, struct request *); +typedef int (elevator_reinsert_req_fn) (struct request_queue *, + struct request *); +typedef bool (elevator_is_urgent_fn) (struct request_queue *); typedef struct request *(elevator_request_list_fn) (struct request_queue *, struct request *); typedef void (elevator_completed_req_fn) (struct request_queue *, struct request *); typedef int (elevator_may_queue_fn) (struct request_queue *, int); @@ -46,6 +49,9 @@ struct elevator_ops elevator_dispatch_fn *elevator_dispatch_fn; elevator_add_req_fn *elevator_add_req_fn; + elevator_reinsert_req_fn *elevator_reinsert_req_fn; + elevator_is_urgent_fn *elevator_is_urgent_fn; + elevator_activate_req_fn *elevator_activate_req_fn; elevator_deactivate_req_fn *elevator_deactivate_req_fn; @@ -122,6 +128,7 @@ extern void elv_merged_request(struct request_queue *, struct request *, int); extern void elv_bio_merged(struct request_queue *q, struct request *, struct bio *); extern void elv_requeue_request(struct request_queue *, struct request *); +extern int elv_reinsert_request(struct request_queue *, struct request *); extern struct request *elv_former_request(struct request_queue *, struct request *); extern struct request *elv_latter_request(struct request_queue *, struct request *); extern int elv_register_queue(struct request_queue *q); From 779f59abb0a47b7ef9a44e833e9e1b4a9d2c5b5f Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Sun, 17 Nov 2013 07:12:37 +0100 Subject: [PATCH 004/215] Buildscript : prepare for CM compat --- glitch.sh | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/glitch.sh b/glitch.sh index e545e1d1fe5..8be6140a66b 100755 --- a/glitch.sh +++ b/glitch.sh @@ -81,6 +81,16 @@ cd release/aroma . $KERNEL_DIR/../rev +if [ "$cm" = "y" ] ; then + +mkdir -p $KERNEL_DIR/release/Flashable-flo-AOSP4CM +REL=Glitch-flo-r$counter-AOSP4CM.zip + + zip -q -r ${REL} boot config META-INF system + #sha256sum ${REL} > ${REL}.sha256sum + mv ${REL}* $KERNEL_DIR/release/Flashable-flo-AOSP4CM/ +else + counter=$((counter + 1)) mkdir -p $KERNEL_DIR/release/Flashable-flo-AOSP @@ -92,6 +102,8 @@ REL=Glitch-flo-r$counter.zip echo counter=$counter > $KERNEL_DIR/../rev; +fi + rm boot/glitch.zImage rm -r system/lib/modules/* cd $KERNEL_DIR @@ -114,10 +126,31 @@ else if [ "$1" = cleank ] ; then rm -fr "$KERNEL_DIR"/release/Flashable-flo-AOSP/* + rm -fr "$KERNEL_DIR"/release/Flashable-flo-AOSP4CM/* echo "Built kernels cleaned" else +if [ "$1" = cm ] ; then + +cm="y" + + git apply --reverse ../CMpatch + echo "--------------------------------------------------------" + echo "--------------Patched tree for CM compat----------------" + echo "--------------------------------------------------------" + +time { + build flo +} + + git apply ../CMpatch + echo "--------------------------------------------------------" + echo "---------------Patched tree back to AOSP----------------" + echo "--------------------------------------------------------" + +else + time { build flo @@ -125,3 +158,4 @@ time { } fi fi +fi From 70412704c64a73a634b03b03bf7f3bf6a0ac33b9 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Sun, 17 Nov 2013 08:16:16 +0100 Subject: [PATCH 005/215] Buildscript : Add CM compat patch Signed-off-by: Tk-Glitch --- glitch.sh | 4 ++-- release/Flashable-flo-AOSP4CM/.gitignore | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 release/Flashable-flo-AOSP4CM/.gitignore diff --git a/glitch.sh b/glitch.sh index 8be6140a66b..031044f4f52 100755 --- a/glitch.sh +++ b/glitch.sh @@ -135,7 +135,7 @@ if [ "$1" = cm ] ; then cm="y" - git apply --reverse ../CMpatch + git apply ../AOSPpatch echo "--------------------------------------------------------" echo "--------------Patched tree for CM compat----------------" echo "--------------------------------------------------------" @@ -144,7 +144,7 @@ time { build flo } - git apply ../CMpatch + git apply --reverse ../AOSPpatch echo "--------------------------------------------------------" echo "---------------Patched tree back to AOSP----------------" echo "--------------------------------------------------------" diff --git a/release/Flashable-flo-AOSP4CM/.gitignore b/release/Flashable-flo-AOSP4CM/.gitignore new file mode 100644 index 00000000000..c4c4ffc6aa4 --- /dev/null +++ b/release/Flashable-flo-AOSP4CM/.gitignore @@ -0,0 +1 @@ +*.zip From 10f1a1113ba4f04cdd50488cc733471ca453d94e Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Sun, 17 Nov 2013 11:15:59 +0100 Subject: [PATCH 006/215] Add 162 and 270 MHz CPU low frequencies Signed-off-by: Tk-Glitch --- arch/arm/configs/flo_defconfig | 2 +- arch/arm/mach-msm/acpuclock-8064.c | 14 ++++++++++++++ arch/arm/mach-msm/acpuclock-krait.c | 2 +- arch/arm/mach-msm/msm_dcvs.c | 2 +- release/aroma/system/etc/init.d/99glitch | 8 ++++---- 5 files changed, 21 insertions(+), 7 deletions(-) diff --git a/arch/arm/configs/flo_defconfig b/arch/arm/configs/flo_defconfig index c1498297ace..5123bb46cd3 100644 --- a/arch/arm/configs/flo_defconfig +++ b/arch/arm/configs/flo_defconfig @@ -462,7 +462,7 @@ CONFIG_MSM_MPDEC=y CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN=y CONFIG_MSM_CPU_FREQ_SET_MIN_MAX=y CONFIG_MSM_CPU_FREQ_MAX=2322000 -CONFIG_MSM_CPU_FREQ_MIN=384000 +CONFIG_MSM_CPU_FREQ_MIN=162000 CONFIG_INTELLI_PLUG=y CONFIG_CPU_VOLTAGE_TABLE=y CONFIG_MSM_AVS_HW=y diff --git a/arch/arm/mach-msm/acpuclock-8064.c b/arch/arm/mach-msm/acpuclock-8064.c index 60880dc8167..1b3770798ab 100644 --- a/arch/arm/mach-msm/acpuclock-8064.c +++ b/arch/arm/mach-msm/acpuclock-8064.c @@ -340,6 +340,8 @@ static struct acpu_level tbl_faster[] __initdata = { }; static struct acpu_level tbl_PVS0_1512MHz[] __initdata = { + { 1, { 162000, HFPLL, 2, 0x0C }, L2(0), 950000 }, + { 1, { 270000, HFPLL, 2, 0x14 }, L2(0), 950000 }, { 1, { 384000, PLL_8, 0, 0x00 }, L2(0), 950000 }, { 1, { 486000, HFPLL, 2, 0x24 }, L2(5), 950000 }, { 1, { 594000, HFPLL, 1, 0x16 }, L2(5), 950000 }, @@ -368,6 +370,8 @@ static struct acpu_level tbl_PVS0_1512MHz[] __initdata = { }; static struct acpu_level tbl_PVS1_1512MHz[] __initdata = { + { 1, { 162000, HFPLL, 2, 0x0C }, L2(0), 950000 }, + { 1, { 270000, HFPLL, 2, 0x14 }, L2(0), 950000 }, { 1, { 384000, PLL_8, 0, 0x00 }, L2(0), 950000 }, { 1, { 486000, HFPLL, 2, 0x24 }, L2(5), 950000 }, { 1, { 594000, HFPLL, 1, 0x16 }, L2(5), 950000 }, @@ -396,6 +400,8 @@ static struct acpu_level tbl_PVS1_1512MHz[] __initdata = { }; static struct acpu_level tbl_PVS2_1512MHz[] __initdata = { + { 1, { 162000, HFPLL, 2, 0x0C }, L2(0), 925000 }, + { 1, { 270000, HFPLL, 2, 0x14 }, L2(0), 925000 }, { 1, { 384000, PLL_8, 0, 0x00 }, L2(0), 925000 }, { 1, { 486000, HFPLL, 2, 0x24 }, L2(5), 925000 }, { 1, { 594000, HFPLL, 1, 0x16 }, L2(5), 925000 }, @@ -424,6 +430,8 @@ static struct acpu_level tbl_PVS2_1512MHz[] __initdata = { }; static struct acpu_level tbl_PVS3_1512MHz[] __initdata = { + { 1, { 162000, HFPLL, 2, 0x0C }, L2(0), 900000 }, + { 1, { 270000, HFPLL, 2, 0x14 }, L2(0), 900000 }, { 1, { 384000, PLL_8, 0, 0x00 }, L2(0), 900000 }, { 1, { 486000, HFPLL, 2, 0x24 }, L2(5), 900000 }, { 1, { 594000, HFPLL, 1, 0x16 }, L2(5), 900000 }, @@ -452,6 +460,8 @@ static struct acpu_level tbl_PVS3_1512MHz[] __initdata = { }; static struct acpu_level tbl_PVS4_1512MHz[] __initdata = { + { 1, { 162000, HFPLL, 2, 0x0C }, L2(0), 875000 }, + { 1, { 270000, HFPLL, 2, 0x14 }, L2(0), 875000 }, { 1, { 384000, PLL_8, 0, 0x00 }, L2(0), 875000 }, { 1, { 486000, HFPLL, 2, 0x24 }, L2(5), 875000 }, { 1, { 594000, HFPLL, 1, 0x16 }, L2(5), 875000 }, @@ -480,6 +490,8 @@ static struct acpu_level tbl_PVS4_1512MHz[] __initdata = { }; static struct acpu_level tbl_PVS5_1512MHz[] __initdata = { + { 1, { 162000, HFPLL, 2, 0x0C }, L2(0), 875000 }, + { 1, { 270000, HFPLL, 2, 0x14 }, L2(0), 875000 }, { 1, { 384000, PLL_8, 0, 0x00 }, L2(0), 875000 }, { 1, { 486000, HFPLL, 2, 0x24 }, L2(5), 875000 }, { 1, { 594000, HFPLL, 1, 0x16 }, L2(5), 875000 }, @@ -508,6 +520,8 @@ static struct acpu_level tbl_PVS5_1512MHz[] __initdata = { }; static struct acpu_level tbl_PVS6_1512MHz[] __initdata = { + { 1, { 162000, HFPLL, 2, 0x0C }, L2(0), 875000 }, + { 1, { 270000, HFPLL, 2, 0x14 }, L2(0), 875000 }, { 1, { 384000, PLL_8, 0, 0x00 }, L2(0), 875000 }, { 1, { 486000, HFPLL, 2, 0x24 }, L2(5), 875000 }, { 1, { 594000, HFPLL, 1, 0x16 }, L2(5), 875000 }, diff --git a/arch/arm/mach-msm/acpuclock-krait.c b/arch/arm/mach-msm/acpuclock-krait.c index 5bdd5439cb3..53d3e1fc0f0 100644 --- a/arch/arm/mach-msm/acpuclock-krait.c +++ b/arch/arm/mach-msm/acpuclock-krait.c @@ -47,7 +47,7 @@ #define SECCLKAGD BIT(4) -#define FREQ_TABLE_SIZE 44 +#define FREQ_TABLE_SIZE 46 /** elementalx defs **/ diff --git a/arch/arm/mach-msm/msm_dcvs.c b/arch/arm/mach-msm/msm_dcvs.c index 91e639e4730..c0b09be48bb 100644 --- a/arch/arm/mach-msm/msm_dcvs.c +++ b/arch/arm/mach-msm/msm_dcvs.c @@ -146,7 +146,7 @@ static struct dcvs_core core_list[CORES_MAX]; static struct kobject *cores_kobj; -#define DCVS_MAX_NUM_FREQS 24 +#define DCVS_MAX_NUM_FREQS 26 static struct msm_dcvs_freq_entry cpu_freq_tbl[DCVS_MAX_NUM_FREQS]; static unsigned num_cpu_freqs; static struct msm_dcvs_platform_data *dcvs_pdata; diff --git a/release/aroma/system/etc/init.d/99glitch b/release/aroma/system/etc/init.d/99glitch index d5b98e39ea8..2b03498daca 100755 --- a/release/aroma/system/etc/init.d/99glitch +++ b/release/aroma/system/etc/init.d/99glitch @@ -15,10 +15,10 @@ echo $MAXF > /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq; echo $MAXF > /sys/devices/system/cpu/cpu1/cpufreq/scaling_max_freq; echo $MAXF > /sys/devices/system/cpu/cpu2/cpufreq/scaling_max_freq; echo $MAXF > /sys/devices/system/cpu/cpu3/cpufreq/scaling_max_freq; -echo 384000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq; -echo 384000 > /sys/devices/system/cpu/cpu1/cpufreq/scaling_min_freq; -echo 384000 > /sys/devices/system/cpu/cpu2/cpufreq/scaling_min_freq; -echo 384000 > /sys/devices/system/cpu/cpu3/cpufreq/scaling_min_freq; +echo 162000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq; +echo 162000 > /sys/devices/system/cpu/cpu1/cpufreq/scaling_min_freq; +echo 162000 > /sys/devices/system/cpu/cpu2/cpufreq/scaling_min_freq; +echo 162000 > /sys/devices/system/cpu/cpu3/cpufreq/scaling_min_freq; echo Max CPU Frequency: $MAXF >> $KERNEL_LOGFILE #Set SWEEP2WAKE From 17b1a9f01dc69bb7b391982c0ee44b2a321e7c4f Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Sun, 17 Nov 2013 11:25:49 +0100 Subject: [PATCH 007/215] Print glitch kernel "name" on uV instead of eleX --- arch/arm/mach-msm/acpuclock-krait.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-msm/acpuclock-krait.c b/arch/arm/mach-msm/acpuclock-krait.c index 53d3e1fc0f0..0ff56fb251f 100644 --- a/arch/arm/mach-msm/acpuclock-krait.c +++ b/arch/arm/mach-msm/acpuclock-krait.c @@ -1193,32 +1193,32 @@ static void apply_undervolting(void) { if (uv_bin == 6) { drv.acpu_freq_tbl[0].vdd_core = 725000; - printk(KERN_INFO "[elementalx]: min_voltage='%i'\n", drv.acpu_freq_tbl[0].vdd_core ); + printk(KERN_INFO "[glitch]: min_voltage='%i'\n", drv.acpu_freq_tbl[0].vdd_core ); } if (uv_bin == 5) { drv.acpu_freq_tbl[0].vdd_core = 750000; - printk(KERN_INFO "[elementalx]: min_voltage='%i'\n", drv.acpu_freq_tbl[0].vdd_core ); + printk(KERN_INFO "[glitch]: min_voltage='%i'\n", drv.acpu_freq_tbl[0].vdd_core ); } if (uv_bin == 4) { drv.acpu_freq_tbl[0].vdd_core = 775000; - printk(KERN_INFO "[elementalx]: min_voltage='%i'\n", drv.acpu_freq_tbl[0].vdd_core ); + printk(KERN_INFO "[glitch]: min_voltage='%i'\n", drv.acpu_freq_tbl[0].vdd_core ); } if (uv_bin == 3) { drv.acpu_freq_tbl[0].vdd_core = 800000; - printk(KERN_INFO "[elementalx]: min_voltage='%i'\n", drv.acpu_freq_tbl[0].vdd_core ); + printk(KERN_INFO "[glitch]: min_voltage='%i'\n", drv.acpu_freq_tbl[0].vdd_core ); } if (uv_bin == 2) { drv.acpu_freq_tbl[0].vdd_core = 825000; - printk(KERN_INFO "[elementalx]: min_voltage='%i'\n", drv.acpu_freq_tbl[0].vdd_core ); + printk(KERN_INFO "[glitch]: min_voltage='%i'\n", drv.acpu_freq_tbl[0].vdd_core ); } if (uv_bin == 1) { drv.acpu_freq_tbl[0].vdd_core = 850000; - printk(KERN_INFO "[elementalx]: min_voltage='%i'\n", drv.acpu_freq_tbl[0].vdd_core ); + printk(KERN_INFO "[glitch]: min_voltage='%i'\n", drv.acpu_freq_tbl[0].vdd_core ); } } From 3fad3ae9095648c2f6b14fa19f1e3388faf3f36f Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Sun, 17 Nov 2013 11:31:08 +0100 Subject: [PATCH 008/215] ARM: 7670/1: fix the memset fix Commit 455bd4c430b0 ("ARM: 7668/1: fix memset-related crashes caused by recent GCC (4.7.2) optimizations") attempted to fix a compliance issue with the memset return value. However the memset itself became broken by that patch for misaligned pointers. This fixes the above by branching over the entry code from the misaligned fixup code to avoid reloading the original pointer. Also, because the function entry alignment is wrong in the Thumb mode compilation, that fixup code is moved to the end. While at it, the entry instructions are slightly reworked to help dual issue pipelines. Signed-off-by: Nicolas Pitre Tested-by: Alexander Holler Signed-off-by: Russell King Signed-off-by: Tk-Glitch --- arch/arm/lib/memset.S | 33 +++++++++++++-------------------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/arch/arm/lib/memset.S b/arch/arm/lib/memset.S index d912e7397ec..94b0650ea98 100644 --- a/arch/arm/lib/memset.S +++ b/arch/arm/lib/memset.S @@ -14,31 +14,15 @@ .text .align 5 - .word 0 - -1: subs r2, r2, #4 @ 1 do we have enough - blt 5f @ 1 bytes to align with? - cmp r3, #2 @ 1 - strltb r1, [ip], #1 @ 1 - strleb r1, [ip], #1 @ 1 - strb r1, [ip], #1 @ 1 - add r2, r2, r3 @ 1 (r2 = r2 - (4 - r3)) -/* - * The pointer is now aligned and the length is adjusted. Try doing the - * memset again. - */ ENTRY(memset) -/* - * Preserve the contents of r0 for the return value. - */ - mov ip, r0 - ands r3, ip, #3 @ 1 unaligned? - bne 1b @ 1 + ands r3, r0, #3 @ 1 unaligned? + mov ip, r0 @ preserve r0 as return value + bne 6f @ 1 /* * we know that the pointer in ip is aligned to a word boundary. */ - orr r1, r1, r1, lsl #8 +1: orr r1, r1, r1, lsl #8 orr r1, r1, r1, lsl #16 mov r3, r1 cmp r2, #16 @@ -127,4 +111,13 @@ ENTRY(memset) tst r2, #1 strneb r1, [ip], #1 mov pc, lr + +6: subs r2, r2, #4 @ 1 do we have enough + blt 5b @ 1 bytes to align with? + cmp r3, #2 @ 1 + strltb r1, [ip], #1 @ 1 + strleb r1, [ip], #1 @ 1 + strb r1, [ip], #1 @ 1 + add r2, r2, r3 @ 1 (r2 = r2 - (4 - r3)) + b 1b ENDPROC(memset) From 17616beca7bd7c868d6e2dd189e76c8c7faed05c Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Sun, 17 Nov 2013 11:35:59 +0100 Subject: [PATCH 009/215] arm: unwind: Remove logspam while in debug mode Signed-off-by: Tk-Glitch --- arch/arm/kernel/unwind.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/kernel/unwind.c b/arch/arm/kernel/unwind.c index 00df012c467..732dcc40275 100644 --- a/arch/arm/kernel/unwind.c +++ b/arch/arm/kernel/unwind.c @@ -345,7 +345,7 @@ int unwind_frame(struct stackframe *frame) idx = unwind_find_idx(frame->pc); if (!idx) { - pr_warning("unwind: Index not found %08lx\n", frame->pc); + pr_debug("unwind: Index not found %08lx\n", frame->pc); return -URC_FAILURE; } From f51e1f65a6754673c0ae74d947238eb50de2877b Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Sun, 17 Nov 2013 16:21:19 +0100 Subject: [PATCH 010/215] "N7" naming instead of "flo" --- arch/arm/configs/flo_defconfig | 2 +- glitch.sh | 8 ++++---- release/aroma/META-INF/com/google/android/aroma-config | 2 +- .../aroma/META-INF/com/google/android/aroma/changelog.txt | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/arm/configs/flo_defconfig b/arch/arm/configs/flo_defconfig index 5123bb46cd3..072afd1809c 100644 --- a/arch/arm/configs/flo_defconfig +++ b/arch/arm/configs/flo_defconfig @@ -40,7 +40,7 @@ CONFIG_IRQ_WORK=y CONFIG_EXPERIMENTAL=y CONFIG_INIT_ENV_ARG_LIMIT=32 CONFIG_CROSS_COMPILE="" -CONFIG_LOCALVERSION="-Glitch-Flo-AOSP" +CONFIG_LOCALVERSION="-Glitch-N7-AOSP" # CONFIG_LOCALVERSION_AUTO is not set CONFIG_HAVE_KERNEL_GZIP=y CONFIG_HAVE_KERNEL_LZMA=y diff --git a/glitch.sh b/glitch.sh index 031044f4f52..04e3c39a894 100755 --- a/glitch.sh +++ b/glitch.sh @@ -54,8 +54,8 @@ build () { local target=flo - echo "Building for flo" - local target_dir="$BUILD_DIR/flo" + echo "Building for N7" + local target_dir="$BUILD_DIR/N7" local module rm -fr "$target_dir" mkdir -p "$target_dir" @@ -84,7 +84,7 @@ cd release/aroma if [ "$cm" = "y" ] ; then mkdir -p $KERNEL_DIR/release/Flashable-flo-AOSP4CM -REL=Glitch-flo-r$counter-AOSP4CM.zip +REL=Glitch-N7-r$counter-AOSP4CM.zip zip -q -r ${REL} boot config META-INF system #sha256sum ${REL} > ${REL}.sha256sum @@ -94,7 +94,7 @@ else counter=$((counter + 1)) mkdir -p $KERNEL_DIR/release/Flashable-flo-AOSP -REL=Glitch-flo-r$counter.zip +REL=Glitch-N7-r$counter.zip zip -q -r ${REL} boot config META-INF system #sha256sum ${REL} > ${REL}.sha256sum diff --git a/release/aroma/META-INF/com/google/android/aroma-config b/release/aroma/META-INF/com/google/android/aroma-config index a47d537d06b..5bba8232b29 100755 --- a/release/aroma/META-INF/com/google/android/aroma-config +++ b/release/aroma/META-INF/com/google/android/aroma-config @@ -31,7 +31,7 @@ # * AROMA Temporary Dir = /tmp/aroma/ ini_set("rom_name", "Glitch kernel"); -ini_set("rom_version", "Flo-AOSP"); +ini_set("rom_version", "N7-AOSP"); ini_set("rom_author", "Tk-Glitch"); ini_set("rom_device", "Nexus 7 (2013)"); ini_set("rom_date", "November 2013"); diff --git a/release/aroma/META-INF/com/google/android/aroma/changelog.txt b/release/aroma/META-INF/com/google/android/aroma/changelog.txt index 8775e519ffa..5e27738a9ac 100755 --- a/release/aroma/META-INF/com/google/android/aroma/changelog.txt +++ b/release/aroma/META-INF/com/google/android/aroma/changelog.txt @@ -1,4 +1,4 @@ -Glitch kernel "AOSP" for flo +Glitch kernel "AOSP" for N7 2013 - Based on AOSP 3.4.0 kernel source for MSM devices updated to linux 3.4.1 - CPU OC up to 2.3Ghz with OV/UV support From d42fbdc5e0aca859959ecb925c256e0f13b41a77 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Sun, 17 Nov 2013 17:20:34 +0100 Subject: [PATCH 011/215] buildscript : fix comment --- glitch.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glitch.sh b/glitch.sh index 04e3c39a894..0477018e431 100755 --- a/glitch.sh +++ b/glitch.sh @@ -4,7 +4,7 @@ # # clean : clean the build directory. # cleank : clean the built kernel packages -# aosp : build an aosp compatible kernel +# cm : build a cm compatible kernel # CM repo path : repo=~/android/system From 166aa6226df6f71a4f540c274258f792ae8007d6 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Wed, 20 Nov 2013 21:51:27 +0100 Subject: [PATCH 012/215] Merge with kitkat-mr0 Signed-off-by: Tk-Glitch --- .../devicetree/bindings/gpu/adreno.txt | 30 +- Documentation/filesystems/proc.txt | 6 + arch/arm/boot/dts/msm8974-gpu.dtsi | 60 +- arch/arm/include/asm/assembler.h | 8 + arch/arm/include/asm/io.h | 25 +- arch/arm/include/asm/pgtable.h | 2 +- arch/arm/include/asm/uaccess.h | 40 +- arch/arm/kernel/perf_event.c | 3 + arch/arm/kernel/signal.c | 2 +- arch/arm/lib/getuser.S | 23 +- arch/arm/lib/putuser.S | 6 + arch/arm/mach-msm/asustek/flo/board-flo-gpu.c | 7 +- arch/arm/mach-msm/asustek/flo/board-flo.c | 8 +- arch/arm/mach-msm/board-8064-gpu.c | 7 +- arch/arm/mach-msm/board-8930-gpu.c | 7 +- arch/arm/mach-msm/board-8960.c | 10 + arch/arm/mach-msm/devices-8064.c | 4 - arch/arm/mach-msm/devices-8960.c | 32 +- arch/arm/mach-msm/devices-msm7x27a.c | 1 - arch/arm/mach-msm/devices-msm7x30.c | 2 - arch/arm/mach-msm/devices-msm8x60.c | 3 - arch/arm/mach-msm/devices.h | 3 + .../arm/mach-msm/include/mach/iommu_domains.h | 6 + arch/arm/mach-msm/include/mach/kgsl.h | 20 +- arch/arm/mach-msm/include/mach/scm.h | 9 +- arch/arm/mach-msm/iommu_domains.c | 103 +- arch/arm/mach-msm/lge/mako/board-mako-gpu.c | 7 +- arch/arm/mach-msm/scm-pas.c | 21 +- arch/arm/mach-msm/scm.c | 39 +- arch/ia64/kernel/irq_ia64.c | 1 - drivers/char/msm_rotator.c | 1 + drivers/char/random.c | 302 +- drivers/gpu/ion/ion.c | 17 +- drivers/gpu/msm/Makefile | 8 +- drivers/gpu/msm/a3xx_reg.h | 92 +- drivers/gpu/msm/a4xx_reg.h | 92 + drivers/gpu/msm/adreno.c | 1383 +++++--- drivers/gpu/msm/adreno.h | 418 ++- drivers/gpu/msm/adreno_a2xx.c | 380 ++- drivers/gpu/msm/adreno_a2xx_snapshot.c | 31 +- drivers/gpu/msm/adreno_a3xx.c | 1767 +++++++--- drivers/gpu/msm/adreno_a3xx.h | 25 + drivers/gpu/msm/adreno_a3xx_snapshot.c | 179 +- drivers/gpu/msm/adreno_a4xx.c | 305 ++ drivers/gpu/msm/adreno_coresight.c | 219 ++ drivers/gpu/msm/adreno_cp_parser.c | 823 +++++ drivers/gpu/msm/adreno_cp_parser.h | 68 + drivers/gpu/msm/adreno_debugfs.c | 19 +- drivers/gpu/msm/adreno_dispatch.c | 552 +++- drivers/gpu/msm/adreno_drawctxt.c | 90 +- drivers/gpu/msm/adreno_drawctxt.h | 1 + drivers/gpu/msm/adreno_pm4types.h | 4 +- drivers/gpu/msm/adreno_postmortem.c | 505 +-- drivers/gpu/msm/adreno_ringbuffer.c | 361 ++- drivers/gpu/msm/adreno_ringbuffer.h | 25 +- drivers/gpu/msm/adreno_snapshot.c | 729 ++--- drivers/gpu/msm/adreno_trace.h | 108 +- drivers/gpu/msm/kgsl.c | 813 +++-- drivers/gpu/msm/kgsl.h | 56 +- drivers/gpu/msm/kgsl_cffdump.c | 118 +- drivers/gpu/msm/kgsl_cffdump.h | 124 +- drivers/gpu/msm/kgsl_debugfs.c | 71 +- drivers/gpu/msm/kgsl_debugfs.h | 2 +- drivers/gpu/msm/kgsl_device.h | 123 +- drivers/gpu/msm/kgsl_drm.c | 745 +++-- drivers/gpu/msm/kgsl_events.c | 92 +- drivers/gpu/msm/kgsl_gpummu.c | 54 +- drivers/gpu/msm/kgsl_gpummu.h | 4 +- drivers/gpu/msm/kgsl_iommu.c | 687 ++-- drivers/gpu/msm/kgsl_iommu.h | 64 +- drivers/gpu/msm/kgsl_mmu.c | 227 +- drivers/gpu/msm/kgsl_mmu.h | 211 +- drivers/gpu/msm/kgsl_pwrctrl.c | 371 ++- drivers/gpu/msm/kgsl_pwrctrl.h | 25 +- drivers/gpu/msm/kgsl_pwrscale.c | 15 +- drivers/gpu/msm/kgsl_pwrscale_trustzone.c | 192 +- drivers/gpu/msm/kgsl_sharedmem.c | 265 +- drivers/gpu/msm/kgsl_sharedmem.h | 16 +- drivers/gpu/msm/kgsl_snapshot.c | 320 +- drivers/gpu/msm/kgsl_snapshot.h | 24 +- drivers/gpu/msm/kgsl_sync.c | 58 +- drivers/gpu/msm/kgsl_sync.h | 2 + drivers/gpu/msm/kgsl_trace.h | 75 +- drivers/gpu/msm/z180.c | 25 +- drivers/gpu/msm/z180_postmortem.c | 2 +- drivers/input/touchscreen/fw_data.b | 284 +- drivers/iommu/iommu.c | 5 +- .../platform/msm/camera_v2/sensor/mi1040.c | 1 + drivers/mfd/ab3100-core.c | 5 - drivers/misc/qseecom.c | 27 +- .../misc/slimport_anx7808/slimport_tx_drv.c | 7 +- drivers/mmc/card/block.c | 47 +- drivers/net/wireless/wcnss/wcnss_wlan.c | 13 + drivers/power/bq27541_battery.c | 17 +- drivers/power/pm8921-bms.c | 16 + drivers/power/pm8921-charger.c | 18 + drivers/power/smb345-charger.c | 27 +- drivers/remoteproc/remoteproc_core.c | 4 +- drivers/staging/prima/Android.mk | 6 +- .../staging/prima/CORE/BAP/src/bapApiHCBB.c | 32 +- .../staging/prima/CORE/BAP/src/bapApiInfo.c | 12 +- .../prima/CORE/BAP/src/bapApiLinkCntl.c | 22 +- .../CORE/BAP/src/bapApiLinkSupervision.c | 2 +- .../staging/prima/CORE/BAP/src/bapApiStatus.c | 12 +- .../staging/prima/CORE/BAP/src/bapModule.c | 4 +- .../CORE/BAP/src/bapRsn8021xSuppRsnFsm.c | 4 +- .../staging/prima/CORE/BAP/src/bapRsnTxRx.c | 4 +- drivers/staging/prima/CORE/BAP/src/btampFsm.c | 4 +- .../staging/prima/CORE/DXE/src/wlan_qct_dxe.c | 81 +- .../prima/CORE/DXE/src/wlan_qct_dxe_cfg_i.c | 14 +- .../prima/CORE/DXE/src/wlan_qct_dxe_i.h | 6 +- .../staging/prima/CORE/HDD/inc/qc_sap_ioctl.h | 1 + .../prima/CORE/HDD/inc/wlan_hdd_assoc.h | 11 +- .../staging/prima/CORE/HDD/inc/wlan_hdd_cfg.h | 172 +- .../prima/CORE/HDD/inc/wlan_hdd_cfg80211.h | 7 +- .../prima/CORE/HDD/inc/wlan_hdd_main.h | 117 +- .../staging/prima/CORE/HDD/inc/wlan_hdd_p2p.h | 4 - .../CORE/HDD/inc/wlan_hdd_packet_filtering.h | 14 +- .../prima/CORE/HDD/inc/wlan_hdd_power.h | 79 +- .../prima/CORE/HDD/inc/wlan_hdd_tdls.h | 17 +- .../prima/CORE/HDD/inc/wlan_hdd_tx_rx.h | 8 + .../prima/CORE/HDD/inc/wlan_hdd_wext.h | 3 + .../prima/CORE/HDD/inc/wlan_hdd_wowl.h | 7 + .../prima/CORE/HDD/src/wlan_hdd_assoc.c | 401 +-- .../staging/prima/CORE/HDD/src/wlan_hdd_cfg.c | 212 +- .../prima/CORE/HDD/src/wlan_hdd_cfg80211.c | 2843 ++++++++++------- .../prima/CORE/HDD/src/wlan_hdd_dev_pwr.c | 6 +- .../CORE/HDD/src/wlan_hdd_early_suspend.c | 762 +++-- .../staging/prima/CORE/HDD/src/wlan_hdd_ftm.c | 25 +- .../prima/CORE/HDD/src/wlan_hdd_hostapd.c | 114 +- .../prima/CORE/HDD/src/wlan_hdd_main.c | 1428 ++++++++- .../staging/prima/CORE/HDD/src/wlan_hdd_p2p.c | 86 +- .../CORE/HDD/src/wlan_hdd_softap_tx_rx.c | 163 +- .../prima/CORE/HDD/src/wlan_hdd_tdls.c | 390 ++- .../prima/CORE/HDD/src/wlan_hdd_tx_rx.c | 141 +- .../prima/CORE/HDD/src/wlan_hdd_wext.c | 489 ++- .../staging/prima/CORE/HDD/src/wlan_hdd_wmm.c | 8 +- .../prima/CORE/HDD/src/wlan_hdd_wowl.c | 10 +- .../staging/prima/CORE/MAC/inc/aniGlobal.h | 16 + .../prima/CORE/MAC/inc/qwlan_version.h | 8 +- drivers/staging/prima/CORE/MAC/inc/sirApi.h | 111 +- .../prima/CORE/MAC/inc/sirMacProtDef.h | 26 +- drivers/staging/prima/CORE/MAC/inc/wniApi.h | 5 +- drivers/staging/prima/CORE/MAC/inc/wniCfgAp.h | 153 +- .../staging/prima/CORE/MAC/inc/wniCfgSta.h | 147 +- .../staging/prima/CORE/MAC/src/cfg/cfgApi.c | 52 + .../prima/CORE/MAC/src/cfg/cfgUtil/cfg.txt | 13 + .../prima/CORE/MAC/src/include/dot11f.h | 111 +- .../prima/CORE/MAC/src/include/dphGlobal.h | 4 +- .../prima/CORE/MAC/src/include/sirParams.h | 13 +- .../prima/CORE/MAC/src/pe/include/limFTDefs.h | 35 +- .../prima/CORE/MAC/src/pe/include/limGlobal.h | 2 +- .../CORE/MAC/src/pe/include/limSession.h | 6 +- .../prima/CORE/MAC/src/pe/lim/limApi.c | 17 + .../prima/CORE/MAC/src/pe/lim/limAssocUtils.c | 164 +- .../prima/CORE/MAC/src/pe/lim/limAssocUtils.h | 4 - .../staging/prima/CORE/MAC/src/pe/lim/limFT.c | 227 +- .../CORE/MAC/src/pe/lim/limIbssPeerMgmt.c | 25 +- .../prima/CORE/MAC/src/pe/lim/limLogDump.c | 6 +- .../prima/CORE/MAC/src/pe/lim/limP2P.c | 2 +- .../MAC/src/pe/lim/limProcessActionFrame.c | 174 +- .../MAC/src/pe/lim/limProcessAssocReqFrame.c | 1 + .../MAC/src/pe/lim/limProcessAssocRspFrame.c | 12 +- .../CORE/MAC/src/pe/lim/limProcessAuthFrame.c | 14 +- .../MAC/src/pe/lim/limProcessBeaconFrame.c | 12 +- .../MAC/src/pe/lim/limProcessCfgUpdates.c | 142 +- .../MAC/src/pe/lim/limProcessDeauthFrame.c | 51 +- .../MAC/src/pe/lim/limProcessDisassocFrame.c | 57 +- .../MAC/src/pe/lim/limProcessMessageQueue.c | 136 +- .../MAC/src/pe/lim/limProcessMlmReqMessages.c | 362 ++- .../MAC/src/pe/lim/limProcessMlmRspMessages.c | 450 ++- .../MAC/src/pe/lim/limProcessProbeReqFrame.c | 18 +- .../MAC/src/pe/lim/limProcessProbeRspFrame.c | 83 +- .../MAC/src/pe/lim/limProcessSmeReqMessages.c | 626 ++-- .../CORE/MAC/src/pe/lim/limProcessTdls.c | 697 ++-- .../CORE/MAC/src/pe/lim/limPropExtsUtils.c | 10 +- .../CORE/MAC/src/pe/lim/limRoamingAlgo.c | 28 +- .../CORE/MAC/src/pe/lim/limScanResultUtils.c | 49 +- .../CORE/MAC/src/pe/lim/limScanResultUtils.h | 8 + .../CORE/MAC/src/pe/lim/limSecurityUtils.c | 64 +- .../MAC/src/pe/lim/limSendManagementFrames.c | 772 ++--- .../CORE/MAC/src/pe/lim/limSendMessages.c | 106 +- .../CORE/MAC/src/pe/lim/limSendMessages.h | 6 +- .../MAC/src/pe/lim/limSendSmeRspMessages.c | 306 +- .../MAC/src/pe/lim/limSendSmeRspMessages.h | 8 +- .../CORE/MAC/src/pe/lim/limSerDesUtils.c | 109 +- .../prima/CORE/MAC/src/pe/lim/limSession.c | 6 +- .../CORE/MAC/src/pe/lim/limSessionUtils.c | 60 +- .../CORE/MAC/src/pe/lim/limSmeReqUtils.c | 122 +- .../prima/CORE/MAC/src/pe/lim/limStaHashApi.c | 24 +- .../prima/CORE/MAC/src/pe/lim/limTimerUtils.c | 285 +- .../prima/CORE/MAC/src/pe/lim/limTrace.c | 36 +- .../prima/CORE/MAC/src/pe/lim/limTypes.h | 11 +- .../prima/CORE/MAC/src/pe/lim/limUtils.c | 1116 ++++--- .../prima/CORE/MAC/src/pe/lim/limUtils.h | 2 + .../prima/CORE/MAC/src/pe/pmm/pmmApi.c | 20 +- .../prima/CORE/MAC/src/pe/rrm/rrmApi.c | 31 +- .../CORE/MAC/src/pe/sch/schBeaconProcess.c | 6 +- drivers/staging/prima/CORE/SAP/inc/sapApi.h | 41 +- .../staging/prima/CORE/SAP/src/sapChSelect.c | 322 +- drivers/staging/prima/CORE/SAP/src/sapFsm.c | 6 +- .../staging/prima/CORE/SAP/src/sapInternal.h | 22 +- .../staging/prima/CORE/SAP/src/sapModule.c | 82 +- drivers/staging/prima/CORE/SME/inc/csrApi.h | 40 +- .../staging/prima/CORE/SME/inc/csrInternal.h | 70 +- .../prima/CORE/SME/inc/csrNeighborRoam.h | 22 + .../staging/prima/CORE/SME/inc/csrSupport.h | 12 +- .../staging/prima/CORE/SME/inc/smeInside.h | 9 +- .../staging/prima/CORE/SME/inc/smeInternal.h | 1 + drivers/staging/prima/CORE/SME/inc/sme_Api.h | 187 +- .../staging/prima/CORE/SME/inc/sme_FTApi.h | 9 + .../staging/prima/CORE/SME/src/QoS/sme_Qos.c | 19 +- .../staging/prima/CORE/SME/src/btc/btcApi.c | 56 +- .../staging/prima/CORE/SME/src/ccm/ccmApi.c | 302 +- .../prima/CORE/SME/src/csr/csrApiRoam.c | 673 +++- .../prima/CORE/SME/src/csr/csrApiScan.c | 505 ++- .../prima/CORE/SME/src/csr/csrInsideApi.h | 3 +- .../prima/CORE/SME/src/csr/csrNeighborRoam.c | 646 +++- .../prima/CORE/SME/src/csr/csrTdlsProcess.c | 119 +- .../staging/prima/CORE/SME/src/csr/csrUtil.c | 125 +- drivers/staging/prima/CORE/SME/src/pmc/pmc.c | 30 +- .../staging/prima/CORE/SME/src/pmc/pmcApi.c | 316 +- .../staging/prima/CORE/SME/src/rrm/sme_rrm.c | 34 +- .../prima/CORE/SME/src/sme_common/sme_Api.c | 536 +++- .../prima/CORE/SME/src/sme_common/sme_FTApi.c | 154 +- .../prima/CORE/SVC/src/btc/wlan_btc_svc.c | 1 + .../CORE/SVC/src/ptt/wlan_ptt_sock_svc.c | 4 +- .../CORE/SYS/legacy/src/pal/inc/palApi.h | 456 ++- .../CORE/SYS/legacy/src/pal/src/palApiComm.c | 9 - .../CORE/SYS/legacy/src/utils/src/dot11f.c | 958 +++--- .../CORE/SYS/legacy/src/utils/src/macTrace.c | 3 + .../staging/prima/CORE/TL/inc/wlan_qct_tl.h | 183 +- .../staging/prima/CORE/TL/src/wlan_qct_tl.c | 618 +++- .../prima/CORE/TL/src/wlan_qct_tl_ba.c | 10 +- .../prima/CORE/TL/src/wlan_qct_tl_hosupport.c | 39 +- .../staging/prima/CORE/TL/src/wlan_qct_tli.h | 9 +- .../prima/CORE/VOSS/inc/i_vos_packet.h | 4 + .../staging/prima/CORE/VOSS/inc/vos_packet.h | 16 + .../staging/prima/CORE/VOSS/inc/vos_trace.h | 24 +- .../staging/prima/CORE/VOSS/inc/vos_types.h | 1 + drivers/staging/prima/CORE/VOSS/src/vos_api.c | 4 +- .../staging/prima/CORE/VOSS/src/vos_nvitem.c | 168 +- .../staging/prima/CORE/VOSS/src/vos_packet.c | 39 +- .../staging/prima/CORE/VOSS/src/vos_sched.c | 2 +- .../staging/prima/CORE/VOSS/src/vos_timer.c | 16 +- .../staging/prima/CORE/VOSS/src/vos_trace.c | 77 +- .../staging/prima/CORE/VOSS/src/vos_utils.c | 9 +- .../prima/CORE/WDA/inc/legacy/halMsgApi.h | 2 +- .../prima/CORE/WDA/inc/legacy/halTypes.h | 4 +- .../staging/prima/CORE/WDA/inc/wlan_qct_wda.h | 67 +- .../staging/prima/CORE/WDA/src/wlan_qct_wda.c | 1625 ++++++++-- .../prima/CORE/WDI/CP/inc/wlan_qct_wdi.h | 197 +- .../prima/CORE/WDI/CP/inc/wlan_qct_wdi_bd.h | 41 +- .../prima/CORE/WDI/CP/inc/wlan_qct_wdi_dp.h | 9 +- .../prima/CORE/WDI/CP/inc/wlan_qct_wdi_i.h | 81 +- .../prima/CORE/WDI/CP/src/wlan_qct_wdi.c | 687 +++- .../prima/CORE/WDI/CP/src/wlan_qct_wdi_dp.c | 36 +- .../prima/CORE/WDI/DP/inc/wlan_qct_wdi_ds.h | 4 + .../CORE/WDI/TRP/DTS/src/wlan_qct_wdi_dts.c | 5 + .../CORE/WDI/WPAL/inc/wlan_qct_os_trace.h | 76 +- .../CORE/WDI/WPAL/inc/wlan_qct_pal_packet.h | 15 +- .../CORE/WDI/WPAL/src/wlan_qct_pal_packet.c | 31 +- .../CORE/WDI/WPAL/src/wlan_qct_pal_trace.c | 2 +- drivers/staging/prima/Kbuild | 16 +- drivers/staging/prima/Kconfig | 4 + .../staging/prima/firmware_bin/WCNSS_cfg.dat | Bin 10298 -> 10330 bytes .../prima/firmware_bin/WCNSS_qcom_cfg.ini | 27 +- drivers/staging/prima/riva/inc/wlan_hal_cfg.h | 3 +- drivers/staging/prima/riva/inc/wlan_hal_msg.h | 114 +- drivers/usb/core/hub.c | 11 +- drivers/video/msm/mdp4.h | 2 - drivers/video/msm/mdp4_overlay.c | 23 +- drivers/video/msm/mipi_JDI.c | 4 +- .../msm/vidc/1080p/ddl/vcd_ddl_properties.c | 39 +- fs/cifs/transport.c | 2 +- fs/proc/task_mmu.c | 62 + fs/select.c | 1 + include/drm/kgsl_drm.h | 43 + include/linux/console.h | 1 + include/linux/freezer.h | 71 +- include/linux/ieee80211.h | 87 + include/linux/iommu.h | 10 +- include/linux/irqdesc.h | 1 - include/linux/kref.h | 22 + include/linux/mfd/pm8xxx/pm8921-bms.h | 13 + include/linux/mm.h | 2 +- include/linux/mm_types.h | 15 + include/linux/msm_kgsl.h | 1 + include/linux/nl80211.h | 264 ++ include/linux/prctl.h | 3 + include/linux/random.h | 6 +- include/linux/wcnss_wlan.h | 7 + include/net/cfg80211.h | 111 +- include/net/inet6_hashtables.h | 8 +- include/net/inet_sock.h | 1 + include/net/ipv6.h | 32 + include/net/ping.h | 50 +- include/net/secure_seq.h | 1 + include/net/transp_v6.h | 3 + kernel/irq/handle.c | 7 +- kernel/irq/manage.c | 17 - kernel/panic.c | 5 + kernel/power/process.c | 42 +- kernel/printk.c | 6 + kernel/signal.c | 2 +- kernel/sys.c | 145 + mm/madvise.c | 3 +- mm/mempolicy.c | 2 +- mm/mlock.c | 3 +- mm/mmap.c | 44 +- mm/mprotect.c | 3 +- net/core/dev.c | 3 + net/core/rtnetlink.c | 1 + net/core/secure_seq.c | 4 +- net/core/sock_diag.c | 3 + net/ipv4/af_inet.c | 14 +- net/ipv4/icmp.c | 2 +- net/ipv4/ping.c | 560 +++- net/ipv6/Makefile | 2 +- net/ipv6/af_inet6.c | 12 + net/ipv6/icmp.c | 27 +- net/ipv6/ping.c | 222 ++ net/mac80211/cfg.c | 6 +- net/mac80211/ieee80211_i.h | 3 + net/mac80211/main.c | 8 +- net/mac80211/mlme.c | 46 +- net/mac80211/util.c | 24 + net/netfilter/xt_qtaguid.c | 14 +- net/wireless/core.c | 5 + net/wireless/nl80211.c | 344 +- sound/soc/msm/asustek_headset.c | 2 +- 331 files changed, 28724 insertions(+), 12929 deletions(-) create mode 100644 drivers/gpu/msm/a4xx_reg.h create mode 100644 drivers/gpu/msm/adreno_a3xx.h create mode 100644 drivers/gpu/msm/adreno_a4xx.c create mode 100644 drivers/gpu/msm/adreno_coresight.c create mode 100644 drivers/gpu/msm/adreno_cp_parser.c create mode 100644 drivers/gpu/msm/adreno_cp_parser.h mode change 100644 => 100755 drivers/media/platform/msm/camera_v2/sensor/mi1040.c mode change 100644 => 100755 drivers/staging/prima/CORE/HDD/inc/wlan_hdd_main.h mode change 100644 => 100755 drivers/staging/prima/CORE/HDD/src/wlan_hdd_assoc.c mode change 100644 => 100755 drivers/staging/prima/CORE/HDD/src/wlan_hdd_main.c mode change 100644 => 100755 drivers/staging/prima/CORE/SME/inc/csrInternal.h mode change 100644 => 100755 drivers/staging/prima/CORE/SME/inc/sme_Api.h mode change 100644 => 100755 drivers/staging/prima/CORE/SME/src/sme_common/sme_Api.c create mode 100644 net/ipv6/ping.c diff --git a/Documentation/devicetree/bindings/gpu/adreno.txt b/Documentation/devicetree/bindings/gpu/adreno.txt index 0433d98b51e..e2a4dcdd147 100644 --- a/Documentation/devicetree/bindings/gpu/adreno.txt +++ b/Documentation/devicetree/bindings/gpu/adreno.txt @@ -5,7 +5,12 @@ Qualcomm Adreno GPU Required properties: - label: A string used as a descriptive name for the device. - compatible: Must be "qcom,kgsl-3d0" and "qcom,kgsl-3d" -- reg: Specifies the base address and address size for this device. +- reg: Specifies the register base address and size. The second interval + specifies the shader memory base address and size. +- reg-names: Resource names used for the physical address of device registers + and shader memory. "kgsl_3d0_reg_memory" gives the physical address + and length of device registers while "kgsl_3d0_shader_memory" gives + physical address and length of device shader memory. - interrupts: Interrupt mapping for GPU IRQ. - interrupt-names: String property to describe the name of the interrupt. - qcom,id: An integer used as an identification number for the device. @@ -57,11 +62,26 @@ DCVS Core info Optional Properties: - qcom,initial-powerlevel: This value indicates which qcom,gpu-pwrlevel should be used at start time and when coming back out of resume +- qcom,step-pwrlevel: How many qcom,gpu-pwrlevel should be decremented at once - qcom,idle-timeout: This property represents the time in microseconds for idle timeout. -- qcom,nap-allowed: Boolean. <0> or <1> to disable/enable nap. - qcom,chipid: If it exists this property is used to replace the chip identification read from the GPU hardware. This is used to override faulty hardware readings. +- qcom,strtstp-sleepwake: Boolean. Enables use of GPU SLUMBER instead of SLEEP for power savings + +The following properties are optional as collecting data via coresight might +not be supported for every chipset. The documentation for coresight +properties can be found in: +Documentation/devicetree/bindings/coresight/coresight.txt + +- coresight-id Unique integer identifier for the bus. +- coresight-name Unique descriptive name of the bus. +- coresight-nr-inports Number of input ports on the bus. +- coresight-outports List of output port numbers on the bus. +- coresight-child-list List of phandles pointing to the children of this + component. +- coresight-child-ports List of input port numbers of the children. + Example of A330 GPU in MSM8974: @@ -69,8 +89,9 @@ Example of A330 GPU in MSM8974: qcom,kgsl-3d0@fdb00000 { label = "kgsl-3d0"; compatible = "qcom,kgsl-3d0", "qcom,kgsl-3d"; - reg = <0xfdb00000 0x20000>; - reg-names = "kgsl_3d0_reg_memory"; + reg = <0xfdb00000 0x10000 + 0xfdb20000 0x10000>; + reg-names = "kgsl_3d0_reg_memory", "kgsl_3d0_shader_memory"; interrupts = <0 33 0>; interrupt-names = "kgsl_3d0_irq"; qcom,id = <0>; @@ -81,7 +102,6 @@ Example of A330 GPU in MSM8974: qcom,initial-pwrlevel = <1>; qcom,idle-timeout = <83>; // - qcom,nap-allowed = <1>; qcom,clk-map = <0x00000016>; //KGSL_CLK_CORE | KGSL_CLK_IFACE | KGSL_CLK_MEM_IFACE /* Bus Scale Settings */ diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt index b7413cb46dc..87fb3e9ccd7 100644 --- a/Documentation/filesystems/proc.txt +++ b/Documentation/filesystems/proc.txt @@ -360,6 +360,8 @@ is not associated with a file: [stack:1001] = the stack of the thread with tid 1001 [vdso] = the "virtual dynamic shared object", the kernel system call handler + [anon:] = an anonymous mapping that has been + named by userspace or if empty, the mapping is anonymous. @@ -409,6 +411,7 @@ Swap: 0 kB KernelPageSize: 4 kB MMUPageSize: 4 kB Locked: 374 kB +Name: name from userspace The first of these lines shows the same information as is displayed for the mapping in /proc/PID/maps. The remaining lines show the size of the mapping @@ -424,6 +427,9 @@ and a page is modified, the file page is replaced by a private anonymous copy. "Swap" shows how much would-be-anonymous memory is also used, but out on swap. +The "Name" field will only be present on a mapping that has been named by +userspace, and will show the name passed in by userspace. + This file is only present if the CONFIG_MMU kernel configuration option is enabled. diff --git a/arch/arm/boot/dts/msm8974-gpu.dtsi b/arch/arm/boot/dts/msm8974-gpu.dtsi index 1ee1f4754be..48abdc5d28c 100644 --- a/arch/arm/boot/dts/msm8974-gpu.dtsi +++ b/arch/arm/boot/dts/msm8974-gpu.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2012, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2013, The Linux Foundation. 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 and @@ -13,29 +13,33 @@ qcom,kgsl-3d0@fdb00000 { label = "kgsl-3d0"; compatible = "qcom,kgsl-3d0", "qcom,kgsl-3d"; - reg = <0xfdb00000 0x20000>; - reg-names = "kgsl_3d0_reg_memory"; + reg = <0xfdb00000 0x10000 + 0xfdb20000 0x10000>; + reg-names = "kgsl_3d0_reg_memory" , "kgsl_3d0_shader_memory"; interrupts = <0 33 0>; interrupt-names = "kgsl_3d0_irq"; qcom,id = <0>; qcom,chipid = <0x03030000>; - qcom,initial-pwrlevel = <1>; + qcom,initial-pwrlevel = <2>; + qcom,step-pwrlevel = <2>; - qcom,idle-timeout = <83>; // - qcom,nap-allowed = <1>; + qcom,idle-timeout = <8>; // + qcom,strtstp-sleepwake; qcom,clk-map = <0x00000016>; //KGSL_CLK_CORE | KGSL_CLK_IFACE | KGSL_CLK_MEM_IFACE /* Bus Scale Settings */ qcom,msm-bus,name = "grp3d"; - qcom,msm-bus,num-cases = <4>; + qcom,msm-bus,num-cases = <6>; qcom,msm-bus,active-only = <0>; qcom,msm-bus,num-paths = <2>; qcom,msm-bus,vectors-KBps = <26 512 0 0>, <89 604 0 0>, - <26 512 0 2000000>, <89 604 0 3000000>, - <26 512 0 4000000>, <89 604 0 5000000>, + <26 512 0 2200000>, <89 604 0 3000000>, + <26 512 0 4000000>, <89 604 0 3000000>, + <26 512 0 4000000>, <89 604 0 4500000>, + <26 512 0 6400000>, <89 604 0 4500000>, <26 512 0 6400000>, <89 604 0 7600000>; /* GDSC oxili regulators */ @@ -47,6 +51,14 @@ /* IOMMU Data */ iommu = <&kgsl_iommu>; + /* Trace bus */ + coresight-id = <67>; + coresight-name = "coresight-gfx"; + coresight-nr-inports = <0>; + coresight-outports = <0>; + coresight-child-list = <&funnel_mmss>; + coresight-child-ports = <7>; + qcom,gpu-pwrlevels { #address-cells = <1>; #size-cells = <0>; @@ -55,27 +67,41 @@ qcom,gpu-pwrlevel@0 { reg = <0>; - qcom,gpu-freq = <500000000>; - qcom,bus-freq = <3>; - qcom,io-fraction = <0>; + qcom,gpu-freq = <450000000>; + qcom,bus-freq = <5>; + qcom,io-fraction = <33>; }; qcom,gpu-pwrlevel@1 { reg = <1>; - qcom,gpu-freq = <333000000>; - qcom,bus-freq = <2>; - qcom,io-fraction = <33>; + qcom,gpu-freq = <320000000>; + qcom,bus-freq = <4>; + qcom,io-fraction = <66>; }; qcom,gpu-pwrlevel@2 { reg = <2>; + qcom,gpu-freq = <320000000>; + qcom,bus-freq = <3>; + qcom,io-fraction = <66>; + }; + + qcom,gpu-pwrlevel@3 { + reg = <3>; + qcom,gpu-freq = <200000000>; + qcom,bus-freq = <2>; + qcom,io-fraction = <100>; + }; + + qcom,gpu-pwrlevel@4 { + reg = <4>; qcom,gpu-freq = <200000000>; qcom,bus-freq = <1>; qcom,io-fraction = <100>; }; - qcom,gpu-pwrlevel@3 { - reg = <3>; + qcom,gpu-pwrlevel@5 { + reg = <5>; qcom,gpu-freq = <27000000>; qcom,bus-freq = <0>; qcom,io-fraction = <0>; diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h index 03fb93621d0..5c8b3bf4d82 100644 --- a/arch/arm/include/asm/assembler.h +++ b/arch/arm/include/asm/assembler.h @@ -320,4 +320,12 @@ .size \name , . - \name .endm + .macro check_uaccess, addr:req, size:req, limit:req, tmp:req, bad:req +#ifndef CONFIG_CPU_USE_DOMAINS + adds \tmp, \addr, #\size - 1 + sbcccs \tmp, \tmp, \limit + bcs \bad +#endif + .endm + #endif /* __ASM_ASSEMBLER_H__ */ diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h index 42fef7cca6f..c1295c43453 100644 --- a/arch/arm/include/asm/io.h +++ b/arch/arm/include/asm/io.h @@ -68,15 +68,18 @@ extern void __raw_readsl(const void __iomem *addr, void *data, int longlen); #define __raw_writeb_no_log(v, a) (__chk_io_ptr(a), *(volatile unsigned char __force *)(a) = (v)) #define __raw_writew_no_log(v, a) (__chk_io_ptr(a), *(volatile unsigned short __force *)(a) = (v)) #define __raw_writel_no_log(v, a) (__chk_io_ptr(a), *(volatile unsigned int __force *)(a) = (v)) +#define __raw_writell_no_log(v, a) (__chk_io_ptr(a), *(volatile unsigned long long __force *)(a) = (v)) #define __raw_writeb(v, a) __raw_write_logged((v), (a), b) #define __raw_writew(v, a) __raw_write_logged((v), (a), w) #define __raw_writel(v, a) __raw_write_logged((v), (a), l) +#define __raw_writell(v, a) __raw_write_logged((v), (a), ll) #define __raw_readb_no_log(a) (__chk_io_ptr(a), *(volatile unsigned char __force *)(a)) #define __raw_readw_no_log(a) (__chk_io_ptr(a), *(volatile unsigned short __force *)(a)) #define __raw_readl_no_log(a) (__chk_io_ptr(a), *(volatile unsigned int __force *)(a)) +#define __raw_readll_no_log(a) (__chk_io_ptr(a), *(volatile unsigned long long __force *)(a)) #define __raw_read_logged(a, _l, _t) ({ \ unsigned _t __a; \ @@ -94,6 +97,7 @@ extern void __raw_readsl(const void __iomem *addr, void *data, int longlen); #define __raw_readb(a) __raw_read_logged((a), b, char) #define __raw_readw(a) __raw_read_logged((a), w, short) #define __raw_readl(a) __raw_read_logged((a), l, int) +#define __raw_readll(a) __raw_read_logged((a), ll, long long) /* * Architecture ioremap implementation. @@ -268,20 +272,35 @@ extern void _memset_io(volatile void __iomem *, int, size_t); __raw_readw(c)); __r; }) #define readl_relaxed(c) ({ u32 __r = le32_to_cpu((__force __le32) \ __raw_readl(c)); __r; }) +#define readll_relaxed(c) ({ u64 __r = le64_to_cpu((__force __le64) \ + __raw_readll(c)); __r; }) +#define readl_relaxed_no_log(c) ({ u32 __r = le32_to_cpu((__force __le32) \ + __raw_readl_no_log(c)); __r; }) +#define readll_relaxed_no_log(c) ({ u64 __r = le64_to_cpu((__force __le64) \ + __raw_readll_no_log(c)); __r; }) + #define writeb_relaxed(v,c) ((void)__raw_writeb(v,c)) #define writew_relaxed(v,c) ((void)__raw_writew((__force u16) \ cpu_to_le16(v),c)) #define writel_relaxed(v,c) ((void)__raw_writel((__force u32) \ cpu_to_le32(v),c)) +#define writell_relaxed(v, c) ((void)__raw_writell((__force u64) \ + cpu_to_le64(v), c)) +#define writel_relaxed_no_log(v, c) ((void)__raw_writel_no_log((__force u32) \ + cpu_to_le32(v), c)) +#define writell_relaxed_no_log(v, c) ((void)__raw_writell_no_log((__force u64) \ + cpu_to_le64(v), c)) #define readb(c) ({ u8 __v = readb_relaxed(c); __iormb(); __v; }) #define readw(c) ({ u16 __v = readw_relaxed(c); __iormb(); __v; }) #define readl(c) ({ u32 __v = readl_relaxed(c); __iormb(); __v; }) +#define readll(c) ({ u64 __v = readll_relaxed(c); __iormb(); __v; }) #define writeb(v,c) ({ __iowmb(); writeb_relaxed(v,c); }) #define writew(v,c) ({ __iowmb(); writew_relaxed(v,c); }) #define writel(v,c) ({ __iowmb(); writel_relaxed(v,c); }) +#define writell(v, c) ({ __iowmb(); writell_relaxed(v, c); }) #define readsb(p,d,l) __raw_readsb(p,d,l) #define readsw(p,d,l) __raw_readsw(p,d,l) @@ -311,22 +330,26 @@ extern void _memset_io(volatile void __iomem *, int, size_t); #define iounmap __arm_iounmap /* - * io{read,write}{8,16,32} macros + * io{read,write}{8,16,32,64} macros */ #ifndef ioread8 #define ioread8(p) ({ unsigned int __v = __raw_readb(p); __iormb(); __v; }) #define ioread16(p) ({ unsigned int __v = le16_to_cpu((__force __le16)__raw_readw(p)); __iormb(); __v; }) #define ioread32(p) ({ unsigned int __v = le32_to_cpu((__force __le32)__raw_readl(p)); __iormb(); __v; }) +#define ioread64(p) ({ unsigned int __v = le64_to_cpu((__force __le64)__raw_readll(p)); __iormb(); __v; }) #define ioread16be(p) ({ unsigned int __v = be16_to_cpu((__force __be16)__raw_readw(p)); __iormb(); __v; }) #define ioread32be(p) ({ unsigned int __v = be32_to_cpu((__force __be32)__raw_readl(p)); __iormb(); __v; }) +#define ioread64be(p) ({ unsigned int __v = be64_to_cpu((__force __be64)__raw_readll(p)); __iormb(); __v; }) #define iowrite8(v,p) ({ __iowmb(); (void)__raw_writeb(v, p); }) #define iowrite16(v,p) ({ __iowmb(); (void)__raw_writew((__force __u16)cpu_to_le16(v), p); }) #define iowrite32(v,p) ({ __iowmb(); (void)__raw_writel((__force __u32)cpu_to_le32(v), p); }) +#define iowrite64(v, p) ({ __iowmb(); (void)__raw_writell((__force __u64)cpu_to_le64(v), p); }) #define iowrite16be(v,p) ({ __iowmb(); (void)__raw_writew((__force __u16)cpu_to_be16(v), p); }) #define iowrite32be(v,p) ({ __iowmb(); (void)__raw_writel((__force __u32)cpu_to_be32(v), p); }) +#define iowrite64be(v, p) ({ __iowmb(); (void)__raw_writell((__force __u64)cpu_to_be64(v), p); }) #define ioread8_rep(p,d,c) __raw_readsb(p,d,c) #define ioread16_rep(p,d,c) __raw_readsw(p,d,c) diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h index 7b6f42a4b0b..2512e1b7145 100644 --- a/arch/arm/include/asm/pgtable.h +++ b/arch/arm/include/asm/pgtable.h @@ -101,7 +101,7 @@ extern pgprot_t pgprot_kernel; __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_BUFFERABLE) #define pgprot_stronglyordered(prot) \ - __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_UNCACHED) + __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_UNCACHED | L_PTE_XN) #define pgprot_device(prot) \ __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_DEV_NONSHARED) diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h index 71f6536d17a..0a070e98625 100644 --- a/arch/arm/include/asm/uaccess.h +++ b/arch/arm/include/asm/uaccess.h @@ -101,28 +101,39 @@ extern int __get_user_1(void *); extern int __get_user_2(void *); extern int __get_user_4(void *); -#define __get_user_x(__r2,__p,__e,__s,__i...) \ +#define __GUP_CLOBBER_1 "lr", "cc" +#ifdef CONFIG_CPU_USE_DOMAINS +#define __GUP_CLOBBER_2 "ip", "lr", "cc" +#else +#define __GUP_CLOBBER_2 "lr", "cc" +#endif +#define __GUP_CLOBBER_4 "lr", "cc" + +#define __get_user_x(__r2,__p,__e,__l,__s) \ __asm__ __volatile__ ( \ __asmeq("%0", "r0") __asmeq("%1", "r2") \ + __asmeq("%3", "r1") \ "bl __get_user_" #__s \ : "=&r" (__e), "=r" (__r2) \ - : "0" (__p) \ - : __i, "cc") + : "0" (__p), "r" (__l) \ + : __GUP_CLOBBER_##__s) #define get_user(x,p) \ ({ \ + unsigned long __limit = current_thread_info()->addr_limit - 1; \ register const typeof(*(p)) __user *__p asm("r0") = (p);\ register unsigned long __r2 asm("r2"); \ + register unsigned long __l asm("r1") = __limit; \ register int __e asm("r0"); \ switch (sizeof(*(__p))) { \ case 1: \ - __get_user_x(__r2, __p, __e, 1, "lr"); \ - break; \ + __get_user_x(__r2, __p, __e, __l, 1); \ + break; \ case 2: \ - __get_user_x(__r2, __p, __e, 2, "r3", "lr"); \ + __get_user_x(__r2, __p, __e, __l, 2); \ break; \ case 4: \ - __get_user_x(__r2, __p, __e, 4, "lr"); \ + __get_user_x(__r2, __p, __e, __l, 4); \ break; \ default: __e = __get_user_bad(); break; \ } \ @@ -135,31 +146,34 @@ extern int __put_user_2(void *, unsigned int); extern int __put_user_4(void *, unsigned int); extern int __put_user_8(void *, unsigned long long); -#define __put_user_x(__r2,__p,__e,__s) \ +#define __put_user_x(__r2,__p,__e,__l,__s) \ __asm__ __volatile__ ( \ __asmeq("%0", "r0") __asmeq("%2", "r2") \ + __asmeq("%3", "r1") \ "bl __put_user_" #__s \ : "=&r" (__e) \ - : "0" (__p), "r" (__r2) \ + : "0" (__p), "r" (__r2), "r" (__l) \ : "ip", "lr", "cc") #define put_user(x,p) \ ({ \ + unsigned long __limit = current_thread_info()->addr_limit - 1; \ register const typeof(*(p)) __r2 asm("r2") = (x); \ register const typeof(*(p)) __user *__p asm("r0") = (p);\ + register unsigned long __l asm("r1") = __limit; \ register int __e asm("r0"); \ switch (sizeof(*(__p))) { \ case 1: \ - __put_user_x(__r2, __p, __e, 1); \ + __put_user_x(__r2, __p, __e, __l, 1); \ break; \ case 2: \ - __put_user_x(__r2, __p, __e, 2); \ + __put_user_x(__r2, __p, __e, __l, 2); \ break; \ case 4: \ - __put_user_x(__r2, __p, __e, 4); \ + __put_user_x(__r2, __p, __e, __l, 4); \ break; \ case 8: \ - __put_user_x(__r2, __p, __e, 8); \ + __put_user_x(__r2, __p, __e, __l, 8); \ break; \ default: __e = __put_user_bad(); break; \ } \ diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c index 52aae9bd2fe..eeb9ffe39d4 100644 --- a/arch/arm/kernel/perf_event.c +++ b/arch/arm/kernel/perf_event.c @@ -338,6 +338,9 @@ validate_event(struct pmu_hw_events *hw_events, struct hw_perf_event fake_event = event->hw; struct pmu *leader_pmu = event->group_leader->pmu; + if (is_software_event(event)) + return 1; + if (event->pmu != leader_pmu || event->state <= PERF_EVENT_STATE_OFF) return 1; diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c index d68d1b69468..eb3a2912cb9 100644 --- a/arch/arm/kernel/signal.c +++ b/arch/arm/kernel/signal.c @@ -642,7 +642,7 @@ static void do_signal(struct pt_regs *regs, int syscall) } } - if (try_to_freeze()) + if (try_to_freeze_nowarn()) goto no_signal; /* diff --git a/arch/arm/lib/getuser.S b/arch/arm/lib/getuser.S index 11093a7c3e3..9b06bb41fca 100644 --- a/arch/arm/lib/getuser.S +++ b/arch/arm/lib/getuser.S @@ -16,8 +16,9 @@ * __get_user_X * * Inputs: r0 contains the address + * r1 contains the address limit, which must be preserved * Outputs: r0 is the error code - * r2, r3 contains the zero-extended value + * r2 contains the zero-extended value * lr corrupted * * No other registers must be altered. (see @@ -27,33 +28,39 @@ * Note also that it is intended that __get_user_bad is not global. */ #include +#include #include #include ENTRY(__get_user_1) + check_uaccess r0, 1, r1, r2, __get_user_bad 1: TUSER(ldrb) r2, [r0] mov r0, #0 mov pc, lr ENDPROC(__get_user_1) ENTRY(__get_user_2) -#ifdef CONFIG_THUMB2_KERNEL -2: TUSER(ldrb) r2, [r0] -3: TUSER(ldrb) r3, [r0, #1] + check_uaccess r0, 2, r1, r2, __get_user_bad +#ifdef CONFIG_CPU_USE_DOMAINS +rb .req ip +2: ldrbt r2, [r0], #1 +3: ldrbt rb, [r0], #0 #else -2: TUSER(ldrb) r2, [r0], #1 -3: TUSER(ldrb) r3, [r0] +rb .req r0 +2: ldrb r2, [r0] +3: ldrb rb, [r0, #1] #endif #ifndef __ARMEB__ - orr r2, r2, r3, lsl #8 + orr r2, r2, rb, lsl #8 #else - orr r2, r3, r2, lsl #8 + orr r2, rb, r2, lsl #8 #endif mov r0, #0 mov pc, lr ENDPROC(__get_user_2) ENTRY(__get_user_4) + check_uaccess r0, 4, r1, r2, __get_user_bad 4: TUSER(ldr) r2, [r0] mov r0, #0 mov pc, lr diff --git a/arch/arm/lib/putuser.S b/arch/arm/lib/putuser.S index 7db25990c58..3d73dcb959b 100644 --- a/arch/arm/lib/putuser.S +++ b/arch/arm/lib/putuser.S @@ -16,6 +16,7 @@ * __put_user_X * * Inputs: r0 contains the address + * r1 contains the address limit, which must be preserved * r2, r3 contains the value * Outputs: r0 is the error code * lr corrupted @@ -27,16 +28,19 @@ * Note also that it is intended that __put_user_bad is not global. */ #include +#include #include #include ENTRY(__put_user_1) + check_uaccess r0, 1, r1, ip, __put_user_bad 1: TUSER(strb) r2, [r0] mov r0, #0 mov pc, lr ENDPROC(__put_user_1) ENTRY(__put_user_2) + check_uaccess r0, 2, r1, ip, __put_user_bad mov ip, r2, lsr #8 #ifdef CONFIG_THUMB2_KERNEL #ifndef __ARMEB__ @@ -60,12 +64,14 @@ ENTRY(__put_user_2) ENDPROC(__put_user_2) ENTRY(__put_user_4) + check_uaccess r0, 4, r1, ip, __put_user_bad 4: TUSER(str) r2, [r0] mov r0, #0 mov pc, lr ENDPROC(__put_user_4) ENTRY(__put_user_8) + check_uaccess r0, 8, r1, ip, __put_user_bad #ifdef CONFIG_THUMB2_KERNEL 5: TUSER(str) r2, [r0] 6: TUSER(str) r3, [r0, #4] diff --git a/arch/arm/mach-msm/asustek/flo/board-flo-gpu.c b/arch/arm/mach-msm/asustek/flo/board-flo-gpu.c index 86138812611..925adea4a3b 100644 --- a/arch/arm/mach-msm/asustek/flo/board-flo-gpu.c +++ b/arch/arm/mach-msm/asustek/flo/board-flo-gpu.c @@ -182,6 +182,12 @@ static struct resource kgsl_3d0_resources[] = { { .name = KGSL_3D0_REG_MEMORY, .start = 0x04300000, /* GFX3D address */ + .end = 0x0430ffff, + .flags = IORESOURCE_MEM, + }, + { + .name = KGSL_3D0_SHADER_MEMORY, + .start = 0x04310000, /* Shader Mem Address */ .end = 0x0431ffff, .flags = IORESOURCE_MEM, }, @@ -249,7 +255,6 @@ static struct kgsl_device_platform_data kgsl_3d0_pdata = { .num_levels = 5, .set_grp_async = NULL, .idle_timeout = HZ/10, - .nap_allowed = true, .strtstp_sleepwake = true, .clk_map = KGSL_CLK_CORE | KGSL_CLK_IFACE | KGSL_CLK_MEM_IFACE, #ifdef CONFIG_MSM_BUS_SCALING diff --git a/arch/arm/mach-msm/asustek/flo/board-flo.c b/arch/arm/mach-msm/asustek/flo/board-flo.c index f56a1936237..78fb1b1f54b 100644 --- a/arch/arm/mach-msm/asustek/flo/board-flo.c +++ b/arch/arm/mach-msm/asustek/flo/board-flo.c @@ -247,7 +247,7 @@ static void enable_cap1106_regulator(void) { #define HOLE_SIZE 0x20000 #define MSM_CONTIG_MEM_SIZE 0x65000 #ifdef CONFIG_MSM_IOMMU -#define MSM_ION_MM_SIZE 0x4C00000 +#define MSM_ION_MM_SIZE 0x5C00000 #define MSM_ION_SF_SIZE 0 #define MSM_ION_QSECOM_SIZE 0x780000 /* (7.5MB) */ #define MSM_ION_HEAP_NUM 7 @@ -3277,10 +3277,10 @@ static struct i2c_registry i2c_anx7808_devices __initdata = { static void __init add_i2c_anx7808_device(void) { if (machine_is_apq8064_flo()) { - anx7808_pdata.phy_reg2 = 0x39; - anx7808_pdata.phy_reg12 = 0x09; + anx7808_pdata.phy_reg2 = 0x3f; + anx7808_pdata.phy_reg12 = 0x10; anx7808_pdata.phy_reg6 = 0x3f; - anx7808_pdata.phy_reg16 = 0x1d; + anx7808_pdata.phy_reg16 = 0x1f; } else if (machine_is_apq8064_deb()) { anx7808_pdata.phy_reg2 = 0x3a; anx7808_pdata.phy_reg12 = 0x09; diff --git a/arch/arm/mach-msm/board-8064-gpu.c b/arch/arm/mach-msm/board-8064-gpu.c index 4cca16794b8..27b5d292728 100644 --- a/arch/arm/mach-msm/board-8064-gpu.c +++ b/arch/arm/mach-msm/board-8064-gpu.c @@ -182,6 +182,12 @@ static struct resource kgsl_3d0_resources[] = { { .name = KGSL_3D0_REG_MEMORY, .start = 0x04300000, /* GFX3D address */ + .end = 0x0430ffff, + .flags = IORESOURCE_MEM, + }, + { + .name = KGSL_3D0_SHADER_MEMORY, + .start = 0x04310000, /* Shader Mem Address */ .end = 0x0431ffff, .flags = IORESOURCE_MEM, }, @@ -249,7 +255,6 @@ static struct kgsl_device_platform_data kgsl_3d0_pdata = { .num_levels = 5, .set_grp_async = NULL, .idle_timeout = HZ/10, - .nap_allowed = true, .strtstp_sleepwake = true, .clk_map = KGSL_CLK_CORE | KGSL_CLK_IFACE | KGSL_CLK_MEM_IFACE, #ifdef CONFIG_MSM_BUS_SCALING diff --git a/arch/arm/mach-msm/board-8930-gpu.c b/arch/arm/mach-msm/board-8930-gpu.c index cbf6803e023..12a6ab129a0 100644 --- a/arch/arm/mach-msm/board-8930-gpu.c +++ b/arch/arm/mach-msm/board-8930-gpu.c @@ -88,6 +88,12 @@ static struct resource kgsl_3d0_resources[] = { { .name = KGSL_3D0_REG_MEMORY, .start = 0x04300000, /* GFX3D address */ + .end = 0x0430ffff, + .flags = IORESOURCE_MEM, + }, + { + .name = KGSL_3D0_SHADER_MEMORY, + .start = 0x04310000, .end = 0x0431ffff, .flags = IORESOURCE_MEM, }, @@ -139,7 +145,6 @@ static struct kgsl_device_platform_data kgsl_3d0_pdata = { .num_levels = 4, .set_grp_async = NULL, .idle_timeout = HZ/12, - .nap_allowed = true, .strtstp_sleepwake = false, .clk_map = KGSL_CLK_CORE | KGSL_CLK_IFACE | KGSL_CLK_MEM_IFACE, #ifdef CONFIG_MSM_BUS_SCALING diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c index 4b4d653d23b..77f172a0dd7 100644 --- a/arch/arm/mach-msm/board-8960.c +++ b/arch/arm/mach-msm/board-8960.c @@ -3032,8 +3032,18 @@ static void __init msm8960_gfx_init(void) kgsl_3d0_pdata->chipid = ADRENO_CHIPID(3, 2, 1, 0); /* 8960PRO nominal clock rate is 320Mhz */ kgsl_3d0_pdata->pwrlevel[1].gpu_freq = 320000000; + + /* + * If this an A320 GPU device (MSM8960AB), then + * switch the resource table to 8960AB, to reflect the + * separate register and shader memory mapping used in A320. + */ + + msm_kgsl_3d0.num_resources = kgsl_num_resources_8960ab; + msm_kgsl_3d0.resource = kgsl_3d0_resources_8960ab; } else { kgsl_3d0_pdata->iommu_count = 1; + if (SOCINFO_VERSION_MAJOR(soc_platform_version) == 1) { kgsl_3d0_pdata->pwrlevel[0].gpu_freq = 320000000; kgsl_3d0_pdata->pwrlevel[1].gpu_freq = 266667000; diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c index 53d0ccfdf71..2175350da63 100644 --- a/arch/arm/mach-msm/devices-8064.c +++ b/arch/arm/mach-msm/devices-8064.c @@ -1451,11 +1451,7 @@ struct msm_vidc_platform_data apq8064_vidc_platform_data = { #endif .disable_dmx = 0, .disable_fullhd = 0, -#if (CONFIG_MACH_APQ8064_FLO || CONFIG_MACH_APQ8064_DEB) - .cont_mode_dpb_count = 14, -#else .cont_mode_dpb_count = 18, -#endif .fw_addr = 0x9fe00000, .enable_sec_metadata = 1, }; diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c index 3a949ff98e5..f5d4c5b84d8 100644 --- a/arch/arm/mach-msm/devices-8960.c +++ b/arch/arm/mach-msm/devices-8960.c @@ -3227,7 +3227,30 @@ struct msm_bus_scale_pdata grp2d1_bus_scale_pdata = { }; #endif -static struct resource kgsl_3d0_resources[] = { +struct resource kgsl_3d0_resources_8960ab[] = { + { + .name = KGSL_3D0_REG_MEMORY, + .start = 0x04300000, /* GFX3D address */ + .end = 0x0430ffff, + .flags = IORESOURCE_MEM, + }, + { + .name = KGSL_3D0_SHADER_MEMORY, + .start = 0x04310000, /* Shader Mem Address (8960AB) */ + .end = 0x0431ffff, + .flags = IORESOURCE_MEM, + }, + { + .name = KGSL_3D0_IRQ, + .start = GFX3D_IRQ, + .end = GFX3D_IRQ, + .flags = IORESOURCE_IRQ, + }, +}; + +int kgsl_num_resources_8960ab = ARRAY_SIZE(kgsl_3d0_resources_8960ab); + +static struct resource kgsl_3d0_resources_8960[] = { { .name = KGSL_3D0_REG_MEMORY, .start = 0x04300000, /* GFX3D address */ @@ -3298,7 +3321,6 @@ static struct kgsl_device_platform_data kgsl_3d0_pdata = { .num_levels = ARRAY_SIZE(grp3d_freq) + 1, .set_grp_async = NULL, .idle_timeout = HZ/12, - .nap_allowed = true, .clk_map = KGSL_CLK_CORE | KGSL_CLK_IFACE | KGSL_CLK_MEM_IFACE, #ifdef CONFIG_MSM_BUS_SCALING .bus_scale_table = &grp3d_bus_scale_pdata, @@ -3311,8 +3333,8 @@ static struct kgsl_device_platform_data kgsl_3d0_pdata = { struct platform_device msm_kgsl_3d0 = { .name = "kgsl-3d0", .id = 0, - .num_resources = ARRAY_SIZE(kgsl_3d0_resources), - .resource = kgsl_3d0_resources, + .num_resources = ARRAY_SIZE(kgsl_3d0_resources_8960), + .resource = kgsl_3d0_resources_8960, .dev = { .platform_data = &kgsl_3d0_pdata, }, @@ -3365,7 +3387,6 @@ static struct kgsl_device_platform_data kgsl_2d0_pdata = { .num_levels = ARRAY_SIZE(grp2d_freq) + 1, .set_grp_async = NULL, .idle_timeout = HZ/5, - .nap_allowed = true, .clk_map = KGSL_CLK_CORE | KGSL_CLK_IFACE, #ifdef CONFIG_MSM_BUS_SCALING .bus_scale_table = &grp2d0_bus_scale_pdata, @@ -3432,7 +3453,6 @@ static struct kgsl_device_platform_data kgsl_2d1_pdata = { .num_levels = ARRAY_SIZE(grp2d_freq) + 1, .set_grp_async = NULL, .idle_timeout = HZ/5, - .nap_allowed = true, .clk_map = KGSL_CLK_CORE | KGSL_CLK_IFACE, #ifdef CONFIG_MSM_BUS_SCALING .bus_scale_table = &grp2d1_bus_scale_pdata, diff --git a/arch/arm/mach-msm/devices-msm7x27a.c b/arch/arm/mach-msm/devices-msm7x27a.c index c08de763bf3..6c86743c33f 100644 --- a/arch/arm/mach-msm/devices-msm7x27a.c +++ b/arch/arm/mach-msm/devices-msm7x27a.c @@ -889,7 +889,6 @@ static struct kgsl_device_platform_data kgsl_3d0_pdata = { .set_grp_async = set_grp_xbar_async, .idle_timeout = HZ, .strtstp_sleepwake = true, - .nap_allowed = false, .clk_map = KGSL_CLK_CORE | KGSL_CLK_IFACE | KGSL_CLK_MEM, }; diff --git a/arch/arm/mach-msm/devices-msm7x30.c b/arch/arm/mach-msm/devices-msm7x30.c index fd4e56d8ef9..0a6a6793eb1 100644 --- a/arch/arm/mach-msm/devices-msm7x30.c +++ b/arch/arm/mach-msm/devices-msm7x30.c @@ -1295,7 +1295,6 @@ static struct kgsl_device_platform_data kgsl_3d0_pdata = { .num_levels = 3, .set_grp_async = set_grp3d_async, .idle_timeout = HZ/20, - .nap_allowed = true, .idle_needed = true, .clk_map = KGSL_CLK_SRC | KGSL_CLK_CORE | KGSL_CLK_IFACE | KGSL_CLK_MEM, @@ -1338,7 +1337,6 @@ static struct kgsl_device_platform_data kgsl_2d0_pdata = { /* HW workaround, run Z180 SYNC @ 192 MHZ */ .set_grp_async = NULL, .idle_timeout = HZ/10, - .nap_allowed = true, .idle_needed = true, .clk_map = KGSL_CLK_CORE | KGSL_CLK_IFACE, }; diff --git a/arch/arm/mach-msm/devices-msm8x60.c b/arch/arm/mach-msm/devices-msm8x60.c index c71ecb9cce0..39b2e8d5b32 100644 --- a/arch/arm/mach-msm/devices-msm8x60.c +++ b/arch/arm/mach-msm/devices-msm8x60.c @@ -738,7 +738,6 @@ static struct kgsl_device_platform_data kgsl_3d0_pdata = { .num_levels = 5, .set_grp_async = NULL, .idle_timeout = HZ/5, - .nap_allowed = true, .clk_map = KGSL_CLK_CORE | KGSL_CLK_IFACE | KGSL_CLK_MEM_IFACE, #ifdef CONFIG_MSM_BUS_SCALING .bus_scale_table = &grp3d_bus_scale_pdata, @@ -785,7 +784,6 @@ static struct kgsl_device_platform_data kgsl_2d0_pdata = { .num_levels = 2, .set_grp_async = NULL, .idle_timeout = HZ/10, - .nap_allowed = true, .clk_map = KGSL_CLK_CORE | KGSL_CLK_IFACE, #ifdef CONFIG_MSM_BUS_SCALING .bus_scale_table = &grp2d0_bus_scale_pdata, @@ -832,7 +830,6 @@ static struct kgsl_device_platform_data kgsl_2d1_pdata = { .num_levels = 2, .set_grp_async = NULL, .idle_timeout = HZ/10, - .nap_allowed = true, .clk_map = KGSL_CLK_CORE | KGSL_CLK_IFACE, #ifdef CONFIG_MSM_BUS_SCALING .bus_scale_table = &grp2d1_bus_scale_pdata, diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h index 5f3aa3a43f6..5e067eab7cc 100644 --- a/arch/arm/mach-msm/devices.h +++ b/arch/arm/mach-msm/devices.h @@ -319,6 +319,9 @@ extern struct platform_device msm_kgsl_3d0; extern struct platform_device msm_kgsl_2d0; extern struct platform_device msm_kgsl_2d1; +extern struct resource kgsl_3d0_resources_8960ab[]; +extern int kgsl_num_resources_8960ab; + extern struct platform_device msm_mipi_dsi1_device; extern struct platform_device mipi_dsi_device; extern struct platform_device msm_lvds_device; diff --git a/arch/arm/mach-msm/include/mach/iommu_domains.h b/arch/arm/mach-msm/include/mach/iommu_domains.h index 59d430f7bd0..7e98a0bfe60 100644 --- a/arch/arm/mach-msm/include/mach/iommu_domains.h +++ b/arch/arm/mach-msm/include/mach/iommu_domains.h @@ -114,6 +114,7 @@ extern void msm_iommu_unmap_contig_buffer(unsigned long iova, unsigned long size); extern int msm_register_domain(struct msm_iova_layout *layout); +extern int msm_unregister_domain(struct iommu_domain *domain); #else static inline struct iommu_domain @@ -177,6 +178,11 @@ static inline int msm_register_domain(struct msm_iova_layout *layout) { return -ENODEV; } + +static inline int msm_unregister_domain(struct iommu_domain *domain) +{ + return -ENODEV; +} #endif #endif diff --git a/arch/arm/mach-msm/include/mach/kgsl.h b/arch/arm/mach-msm/include/mach/kgsl.h index a22b628bb19..2d7e8df5d56 100644 --- a/arch/arm/mach-msm/include/mach/kgsl.h +++ b/arch/arm/mach-msm/include/mach/kgsl.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2013, The Linux Foundation. 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 and @@ -20,13 +20,15 @@ #define KGSL_CLK_MEM 0x00000008 #define KGSL_CLK_MEM_IFACE 0x00000010 #define KGSL_CLK_AXI 0x00000020 +#define KGSL_CLK_ALT_MEM_IFACE 0x00000040 -#define KGSL_MAX_PWRLEVELS 5 +#define KGSL_MAX_PWRLEVELS 10 #define KGSL_CONVERT_TO_MBPS(val) \ (val*1000*1000U) #define KGSL_3D0_REG_MEMORY "kgsl_3d0_reg_memory" +#define KGSL_3D0_SHADER_MEMORY "kgsl_3d0_shader_memory" #define KGSL_3D0_IRQ "kgsl_3d0_irq" #define KGSL_2D0_REG_MEMORY "kgsl_2d0_reg_memory" #define KGSL_2D0_IRQ "kgsl_2d0_irq" @@ -49,9 +51,19 @@ struct kgsl_iommu_ctx { enum kgsl_iommu_context_id ctx_id; }; +/* + * struct kgsl_device_iommu_data - Struct holding iommu context data obtained + * from dtsi file + * @iommu_ctxs: Pointer to array of struct hoding context name and id + * @iommu_ctx_count: Number of contexts defined in the dtsi file + * @iommu_halt_enable: Indicated if smmu halt h/w feature is supported + * @physstart: Start of iommu registers physical address + * @physend: End of iommu registers physical address + */ struct kgsl_device_iommu_data { const struct kgsl_iommu_ctx *iommu_ctxs; int iommu_ctx_count; + int iommu_halt_enable; unsigned int physstart; unsigned int physend; }; @@ -69,13 +81,15 @@ struct kgsl_device_platform_data { int (*set_grp_async)(void); unsigned int idle_timeout; bool strtstp_sleepwake; - unsigned int nap_allowed; unsigned int clk_map; unsigned int idle_needed; + unsigned int step_mul; struct msm_bus_scale_pdata *bus_scale_table; struct kgsl_device_iommu_data *iommu_data; int iommu_count; struct msm_dcvs_core_info *core_info; + struct coresight_device *csdev; + struct coresight_platform_data *coresight_pdata; unsigned int chipid; }; diff --git a/arch/arm/mach-msm/include/mach/scm.h b/arch/arm/mach-msm/include/mach/scm.h index 8a06fe3b8ac..56f2146a18a 100644 --- a/arch/arm/mach-msm/include/mach/scm.h +++ b/arch/arm/mach-msm/include/mach/scm.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. +/* Copyright (c) 2010-2013, The Linux Foundation. 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 and @@ -31,6 +31,7 @@ extern int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len, extern s32 scm_call_atomic1(u32 svc, u32 cmd, u32 arg1); extern s32 scm_call_atomic2(u32 svc, u32 cmd, u32 arg1, u32 arg2); +extern s32 scm_call_atomic3(u32 svc, u32 cmd, u32 arg1, u32 arg2, u32 arg3); extern s32 scm_call_atomic4_3(u32 svc, u32 cmd, u32 arg1, u32 arg2, u32 arg3, u32 arg4, u32 *ret1, u32 *ret2); @@ -58,6 +59,12 @@ static inline s32 scm_call_atomic2(u32 svc, u32 cmd, u32 arg1, u32 arg2) return 0; } +static inline s32 scm_call_atomic3(u32 svc, u32 cmd, u32 arg1, u32 arg2, + u32 arg3) +{ + return 0; +} + static inline s32 scm_call_atomic4_3(u32 svc, u32 cmd, u32 arg1, u32 arg2, u32 arg3, u32 arg4, u32 *ret1, u32 *ret2) { diff --git a/arch/arm/mach-msm/iommu_domains.c b/arch/arm/mach-msm/iommu_domains.c index 6053be31a7c..d87b4b4646d 100644 --- a/arch/arm/mach-msm/iommu_domains.c +++ b/arch/arm/mach-msm/iommu_domains.c @@ -17,6 +17,8 @@ #include #include #include +#include +#include #include #include #include @@ -35,9 +37,14 @@ struct msm_iova_data { int domain_num; }; +struct msm_iommu_data_entry { + struct list_head list; + void *data; +}; + static struct rb_root domain_root; DEFINE_MUTEX(domain_mutex); -static atomic_t domain_nums = ATOMIC_INIT(-1); +static DEFINE_IDA(domain_nums); int msm_use_iommu() { @@ -254,6 +261,27 @@ static int add_domain(struct msm_iova_data *node) return 0; } +static int remove_domain(struct iommu_domain *domain) +{ + struct rb_root *root = &domain_root; + struct rb_node *n; + struct msm_iova_data *node; + int ret = -EINVAL; + + mutex_lock(&domain_mutex); + + for (n = rb_first(root); n; n = rb_next(n)) { + node = rb_entry(n, struct msm_iova_data, node); + if (node->domain == domain) { + rb_erase(&node->node, &domain_root); + ret = 0; + break; + } + } + mutex_unlock(&domain_mutex); + return ret; +} + struct iommu_domain *msm_get_iommu_domain(int domain_num) { struct msm_iova_data *data; @@ -266,6 +294,27 @@ struct iommu_domain *msm_get_iommu_domain(int domain_num) return NULL; } +static struct msm_iova_data *msm_domain_to_iova_data(struct iommu_domain + const *domain) +{ + struct rb_root *root = &domain_root; + struct rb_node *n; + struct msm_iova_data *node; + struct msm_iova_data *iova_data = ERR_PTR(-EINVAL); + + mutex_lock(&domain_mutex); + + for (n = rb_first(root); n; n = rb_next(n)) { + node = rb_entry(n, struct msm_iova_data, node); + if (node->domain == domain) { + iova_data = node; + break; + } + } + mutex_unlock(&domain_mutex); + return iova_data; +} + int msm_allocate_iova_address(unsigned int iommu_domain, unsigned int partition_no, unsigned long size, @@ -351,11 +400,11 @@ int msm_register_domain(struct msm_iova_layout *layout) if (!data) return -ENOMEM; - pools = kmalloc(sizeof(struct mem_pool) * layout->npartitions, + pools = kzalloc(sizeof(struct mem_pool) * layout->npartitions, GFP_KERNEL); if (!pools) - goto out; + goto free_data; for (i = 0; i < layout->npartitions; i++) { if (layout->partitions[i].size == 0) @@ -389,22 +438,64 @@ int msm_register_domain(struct msm_iova_layout *layout) data->pools = pools; data->npools = layout->npartitions; - data->domain_num = atomic_inc_return(&domain_nums); + data->domain_num = ida_simple_get(&domain_nums, 0, 0, GFP_KERNEL); + if (data->domain_num < 0) + goto free_pools; + data->domain = iommu_domain_alloc(&platform_bus_type, layout->domain_flags); + if (!data->domain) + goto free_domain_num; add_domain(data); return data->domain_num; -out: +free_domain_num: + ida_simple_remove(&domain_nums, data->domain_num); + +free_pools: + for (i = 0; i < layout->npartitions; i++) { + if (pools[i].gpool) + gen_pool_destroy(pools[i].gpool); + } + kfree(pools); +free_data: kfree(data); return -EINVAL; } EXPORT_SYMBOL(msm_register_domain); -static int __init iommu_domain_probe(struct platform_device *pdev) +int msm_unregister_domain(struct iommu_domain *domain) +{ + unsigned int i; + struct msm_iova_data *data = msm_domain_to_iova_data(domain); + + if (IS_ERR_OR_NULL(data)) { + pr_err("%s: Could not find iova_data\n", __func__); + return -EINVAL; + } + + if (remove_domain(data->domain)) { + pr_err("%s: Domain not found. Failed to remove domain\n", + __func__); + } + + iommu_domain_free(domain); + + ida_simple_remove(&domain_nums, data->domain_num); + + for (i = 0; i < data->npools; ++i) + gen_pool_destroy(data->pools[i].gpool); + + kfree(data->pools); + kfree(data); + return 0; +} +EXPORT_SYMBOL(msm_unregister_domain); + +static int iommu_domain_probe(struct platform_device *pdev) { struct iommu_domains_pdata *p = pdev->dev.platform_data; int i, j; diff --git a/arch/arm/mach-msm/lge/mako/board-mako-gpu.c b/arch/arm/mach-msm/lge/mako/board-mako-gpu.c index 28c9515afe8..a2d6ac04781 100644 --- a/arch/arm/mach-msm/lge/mako/board-mako-gpu.c +++ b/arch/arm/mach-msm/lge/mako/board-mako-gpu.c @@ -183,6 +183,12 @@ static struct resource kgsl_3d0_resources[] = { { .name = KGSL_3D0_REG_MEMORY, .start = 0x04300000, /* GFX3D address */ + .end = 0x0430ffff, + .flags = IORESOURCE_MEM, + }, + { + .name = KGSL_3D0_SHADER_MEMORY, + .start = 0x04310000, .end = 0x0431ffff, .flags = IORESOURCE_MEM, }, @@ -250,7 +256,6 @@ static struct kgsl_device_platform_data kgsl_3d0_pdata = { .num_levels = 5, .set_grp_async = NULL, .idle_timeout = HZ/10, - .nap_allowed = true, .strtstp_sleepwake = true, .clk_map = KGSL_CLK_CORE | KGSL_CLK_IFACE | KGSL_CLK_MEM_IFACE, #ifdef CONFIG_MSM_BUS_SCALING diff --git a/arch/arm/mach-msm/scm-pas.c b/arch/arm/mach-msm/scm-pas.c index 9eb04e03338..6dcb78c1786 100644 --- a/arch/arm/mach-msm/scm-pas.c +++ b/arch/arm/mach-msm/scm-pas.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -36,18 +37,28 @@ int pas_init_image(enum pas_id id, const u8 *metadata, size_t size) u32 image_addr; } request; u32 scm_ret = 0; - /* Make memory physically contiguous */ - void *mdata_buf = kmemdup(metadata, size, GFP_KERNEL); + void *mdata_buf; + dma_addr_t mdata_phys; + DEFINE_DMA_ATTRS(attrs); - if (!mdata_buf) + dma_set_attr(DMA_ATTR_STRONGLY_ORDERED, &attrs); + mdata_buf = dma_alloc_attrs(NULL, size, &mdata_phys, GFP_KERNEL, + &attrs); + + if (!mdata_buf) { + pr_err("Allocation for metadata failed.\n"); return -ENOMEM; + } + + memcpy(mdata_buf, metadata, size); request.proc = id; - request.image_addr = virt_to_phys(mdata_buf); + request.image_addr = mdata_phys; ret = scm_call(SCM_SVC_PIL, PAS_INIT_IMAGE_CMD, &request, sizeof(request), &scm_ret, sizeof(scm_ret)); - kfree(mdata_buf); + + dma_free_attrs(NULL, size, mdata_buf, mdata_phys, &attrs); if (ret) return ret; diff --git a/arch/arm/mach-msm/scm.c b/arch/arm/mach-msm/scm.c index 468939ba75f..26320d2e090 100644 --- a/arch/arm/mach-msm/scm.c +++ b/arch/arm/mach-msm/scm.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. +/* Copyright (c) 2010-2013, The Linux Foundation. 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 and @@ -342,6 +342,43 @@ s32 scm_call_atomic2(u32 svc, u32 cmd, u32 arg1, u32 arg2) } EXPORT_SYMBOL(scm_call_atomic2); +/** + * scm_call_atomic3() - Send an atomic SCM command with three arguments + * @svc_id: service identifier + * @cmd_id: command identifier + * @arg1: first argument + * @arg2: second argument + * @arg3: third argument + * + * This shall only be used with commands that are guaranteed to be + * uninterruptable, atomic and SMP safe. + */ +s32 scm_call_atomic3(u32 svc, u32 cmd, u32 arg1, u32 arg2, u32 arg3) +{ + int context_id; + register u32 r0 asm("r0") = SCM_ATOMIC(svc, cmd, 3); + register u32 r1 asm("r1") = (u32)&context_id; + register u32 r2 asm("r2") = arg1; + register u32 r3 asm("r3") = arg2; + register u32 r4 asm("r4") = arg3; + + asm volatile( + __asmeq("%0", "r0") + __asmeq("%1", "r0") + __asmeq("%2", "r1") + __asmeq("%3", "r2") + __asmeq("%4", "r3") + __asmeq("%5", "r4") +#ifdef REQUIRES_SEC + ".arch_extension sec\n" +#endif + "smc #0 @ switch to secure world\n" + : "=r" (r0) + : "r" (r0), "r" (r1), "r" (r2), "r" (r3), "r" (r4)); + return r0; +} +EXPORT_SYMBOL(scm_call_atomic3); + s32 scm_call_atomic4_3(u32 svc, u32 cmd, u32 arg1, u32 arg2, u32 arg3, u32 arg4, u32 *ret1, u32 *ret2) { diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c index 5c3e0888265..1034884b77d 100644 --- a/arch/ia64/kernel/irq_ia64.c +++ b/arch/ia64/kernel/irq_ia64.c @@ -23,7 +23,6 @@ #include #include #include -#include /* for rand_initialize_irq() */ #include #include #include diff --git a/drivers/char/msm_rotator.c b/drivers/char/msm_rotator.c index 20e716efb21..684d283c707 100644 --- a/drivers/char/msm_rotator.c +++ b/drivers/char/msm_rotator.c @@ -1508,6 +1508,7 @@ static int msm_rotator_rotate_prepare( fput_light(srcp0_file, ps0_need); else put_img(srcp0_file, srcp0_ihdl, ROTATOR_SRC_DOMAIN, 0); + msm_rotator_signal_timeline_done(s); dev_dbg(msm_rotator_dev->device, "%s() returning rc = %d\n", __func__, rc); mutex_unlock(&msm_rotator_dev->rotator_lock); diff --git a/drivers/char/random.c b/drivers/char/random.c index 4ec04a75473..4d8458f1319 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -125,21 +125,26 @@ * The current exported interfaces for gathering environmental noise * from the devices are: * + * void add_device_randomness(const void *buf, unsigned int size); * void add_input_randomness(unsigned int type, unsigned int code, * unsigned int value); - * void add_interrupt_randomness(int irq); + * void add_interrupt_randomness(int irq, int irq_flags); * void add_disk_randomness(struct gendisk *disk); * + * add_device_randomness() is for adding data to the random pool that + * is likely to differ between two devices (or possibly even per boot). + * This would be things like MAC addresses or serial numbers, or the + * read-out of the RTC. This does *not* add any actual entropy to the + * pool, but it initializes the pool to different values for devices + * that might otherwise be identical and have very little entropy + * available to them (particularly common in the embedded world). + * * add_input_randomness() uses the input layer interrupt timing, as well as * the event type information from the hardware. * - * add_interrupt_randomness() uses the inter-interrupt timing as random - * inputs to the entropy pool. Note that not all interrupts are good - * sources of randomness! For example, the timer interrupts is not a - * good choice, because the periodicity of the interrupts is too - * regular, and hence predictable to an attacker. Network Interface - * Controller interrupts are a better measure, since the timing of the - * NIC interrupts are more unpredictable. + * add_interrupt_randomness() uses the interrupt timing as random + * inputs to the entropy pool. Using the cycle counters and the irq source + * as inputs, it feeds the randomness roughly once a second. * * add_disk_randomness() uses what amounts to the seek time of block * layer request events, on a per-disk_devt basis, as input to the @@ -248,6 +253,8 @@ #include #include #include +#include +#include #ifdef CONFIG_GENERIC_HARDIRQS # include @@ -256,6 +263,7 @@ #include #include #include +#include #include /* @@ -420,8 +428,10 @@ struct entropy_store { /* read-write data: */ spinlock_t lock; unsigned add_ptr; + unsigned input_rotate; int entropy_count; - int input_rotate; + int entropy_total; + unsigned int initialized:1; __u8 last_data[EXTRACT_SIZE]; }; @@ -454,6 +464,10 @@ static struct entropy_store nonblocking_pool = { .pool = nonblocking_pool_data }; +static __u32 const twist_table[8] = { + 0x00000000, 0x3b6e20c8, 0x76dc4190, 0x4db26158, + 0xedb88320, 0xd6d6a3e8, 0x9b64c2b0, 0xa00ae278 }; + /* * This function adds bytes into the entropy "pool". It does not * update the entropy estimate. The caller should call @@ -464,29 +478,24 @@ static struct entropy_store nonblocking_pool = { * it's cheap to do so and helps slightly in the expected case where * the entropy is concentrated in the low-order bits. */ -static void mix_pool_bytes_extract(struct entropy_store *r, const void *in, - int nbytes, __u8 out[64]) +static void __mix_pool_bytes(struct entropy_store *r, const void *in, + int nbytes, __u8 out[64]) { - static __u32 const twist_table[8] = { - 0x00000000, 0x3b6e20c8, 0x76dc4190, 0x4db26158, - 0xedb88320, 0xd6d6a3e8, 0x9b64c2b0, 0xa00ae278 }; unsigned long i, j, tap1, tap2, tap3, tap4, tap5; int input_rotate; int wordmask = r->poolinfo->poolwords - 1; const char *bytes = in; __u32 w; - unsigned long flags; - /* Taps are constant, so we can load them without holding r->lock. */ tap1 = r->poolinfo->tap1; tap2 = r->poolinfo->tap2; tap3 = r->poolinfo->tap3; tap4 = r->poolinfo->tap4; tap5 = r->poolinfo->tap5; - spin_lock_irqsave(&r->lock, flags); - input_rotate = r->input_rotate; - i = r->add_ptr; + smp_rmb(); + input_rotate = ACCESS_ONCE(r->input_rotate); + i = ACCESS_ONCE(r->add_ptr); /* mix one byte at a time to simplify size handling and churn faster */ while (nbytes--) { @@ -513,19 +522,53 @@ static void mix_pool_bytes_extract(struct entropy_store *r, const void *in, input_rotate += i ? 7 : 14; } - r->input_rotate = input_rotate; - r->add_ptr = i; + ACCESS_ONCE(r->input_rotate) = input_rotate; + ACCESS_ONCE(r->add_ptr) = i; + smp_wmb(); if (out) for (j = 0; j < 16; j++) ((__u32 *)out)[j] = r->pool[(i - j) & wordmask]; +} +static void mix_pool_bytes(struct entropy_store *r, const void *in, + int nbytes, __u8 out[64]) +{ + unsigned long flags; + + spin_lock_irqsave(&r->lock, flags); + __mix_pool_bytes(r, in, nbytes, out); spin_unlock_irqrestore(&r->lock, flags); } -static void mix_pool_bytes(struct entropy_store *r, const void *in, int bytes) +struct fast_pool { + __u32 pool[4]; + unsigned long last; + unsigned short count; + unsigned char rotate; + unsigned char last_timer_intr; +}; + +/* + * This is a fast mixing routine used by the interrupt randomness + * collector. It's hardcoded for an 128 bit pool and assumes that any + * locks that might be needed are taken by the caller. + */ +static void fast_mix(struct fast_pool *f, const void *in, int nbytes) { - mix_pool_bytes_extract(r, in, bytes, NULL); + const char *bytes = in; + __u32 w; + unsigned i = f->count; + unsigned input_rotate = f->rotate; + + while (nbytes--) { + w = rol32(*bytes++, input_rotate & 31) ^ f->pool[i & 3] ^ + f->pool[(i + 1) & 3]; + f->pool[i & 3] = (w >> 3) ^ twist_table[w & 7]; + input_rotate += (i++ & 3) ? 7 : 14; + } + f->count = i; + f->rotate = input_rotate; } /* @@ -533,30 +576,34 @@ static void mix_pool_bytes(struct entropy_store *r, const void *in, int bytes) */ static void credit_entropy_bits(struct entropy_store *r, int nbits) { - unsigned long flags; - int entropy_count; + int entropy_count, orig; if (!nbits) return; - spin_lock_irqsave(&r->lock, flags); - DEBUG_ENT("added %d entropy credits to %s\n", nbits, r->name); - entropy_count = r->entropy_count; +retry: + entropy_count = orig = ACCESS_ONCE(r->entropy_count); entropy_count += nbits; if (entropy_count < 0) { DEBUG_ENT("negative entropy/overflow\n"); entropy_count = 0; } else if (entropy_count > r->poolinfo->POOLBITS) entropy_count = r->poolinfo->POOLBITS; - r->entropy_count = entropy_count; + if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig) + goto retry; + + if (!r->initialized && nbits > 0) { + r->entropy_total += nbits; + if (r->entropy_total > 128) + r->initialized = 1; + } /* should we wake readers? */ if (r == &input_pool && entropy_count >= random_read_wakeup_thresh) { wake_up_interruptible(&random_read_wait); kill_fasync(&fasync, SIGIO, POLL_IN); } - spin_unlock_irqrestore(&r->lock, flags); } /********************************************************************* @@ -572,42 +619,24 @@ struct timer_rand_state { unsigned dont_count_entropy:1; }; -#ifndef CONFIG_GENERIC_HARDIRQS - -static struct timer_rand_state *irq_timer_state[NR_IRQS]; - -static struct timer_rand_state *get_timer_rand_state(unsigned int irq) -{ - return irq_timer_state[irq]; -} - -static void set_timer_rand_state(unsigned int irq, - struct timer_rand_state *state) -{ - irq_timer_state[irq] = state; -} - -#else - -static struct timer_rand_state *get_timer_rand_state(unsigned int irq) -{ - struct irq_desc *desc; - - desc = irq_to_desc(irq); - - return desc->timer_rand_state; -} - -static void set_timer_rand_state(unsigned int irq, - struct timer_rand_state *state) +/* + * Add device- or boot-specific data to the input and nonblocking + * pools to help initialize them to unique values. + * + * None of this adds any entropy, it is meant to avoid the + * problem of the nonblocking pool having similar initial state + * across largely identical devices. + */ +void add_device_randomness(const void *buf, unsigned int size) { - struct irq_desc *desc; + unsigned long time = get_cycles() ^ jiffies; - desc = irq_to_desc(irq); - - desc->timer_rand_state = state; + mix_pool_bytes(&input_pool, buf, size, NULL); + mix_pool_bytes(&input_pool, &time, sizeof(time), NULL); + mix_pool_bytes(&nonblocking_pool, buf, size, NULL); + mix_pool_bytes(&nonblocking_pool, &time, sizeof(time), NULL); } -#endif +EXPORT_SYMBOL(add_device_randomness); static struct timer_rand_state input_timer_state; @@ -637,13 +666,9 @@ static void add_timer_randomness(struct timer_rand_state *state, unsigned num) goto out; sample.jiffies = jiffies; - - /* Use arch random value, fall back to cycles */ - if (!arch_get_random_int(&sample.cycles)) - sample.cycles = get_cycles(); - + sample.cycles = get_cycles(); sample.num = num; - mix_pool_bytes(&input_pool, &sample, sizeof(sample)); + mix_pool_bytes(&input_pool, &sample, sizeof(sample), NULL); /* * Calculate number of bits of randomness we probably added. @@ -700,17 +725,48 @@ void add_input_randomness(unsigned int type, unsigned int code, } EXPORT_SYMBOL_GPL(add_input_randomness); -void add_interrupt_randomness(int irq) +static DEFINE_PER_CPU(struct fast_pool, irq_randomness); + +void add_interrupt_randomness(int irq, int irq_flags) { - struct timer_rand_state *state; + struct entropy_store *r; + struct fast_pool *fast_pool = &__get_cpu_var(irq_randomness); + struct pt_regs *regs = get_irq_regs(); + unsigned long now = jiffies; + __u32 input[4], cycles = get_cycles(); + + input[0] = cycles ^ jiffies; + input[1] = irq; + if (regs) { + __u64 ip = instruction_pointer(regs); + input[2] = ip; + input[3] = ip >> 32; + } - state = get_timer_rand_state(irq); + fast_mix(fast_pool, input, sizeof(input)); - if (state == NULL) + if ((fast_pool->count & 1023) && + !time_after(now, fast_pool->last + HZ)) return; - DEBUG_ENT("irq event %d\n", irq); - add_timer_randomness(state, 0x100 + irq); + fast_pool->last = now; + + r = nonblocking_pool.initialized ? &input_pool : &nonblocking_pool; + __mix_pool_bytes(r, &fast_pool->pool, sizeof(fast_pool->pool), NULL); + /* + * If we don't have a valid cycle counter, and we see + * back-to-back timer interrupts, then skip giving credit for + * any entropy. + */ + if (cycles == 0) { + if (irq_flags & __IRQF_TIMER) { + if (fast_pool->last_timer_intr) + return; + fast_pool->last_timer_intr = 1; + } else + fast_pool->last_timer_intr = 0; + } + credit_entropy_bits(r, 1); } #ifdef CONFIG_BLOCK @@ -742,7 +798,11 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf, */ static void xfer_secondary_pool(struct entropy_store *r, size_t nbytes) { - __u32 tmp[OUTPUT_POOL_WORDS]; + union { + __u32 tmp[OUTPUT_POOL_WORDS]; + long hwrand[4]; + } u; + int i; if (r->pull && r->entropy_count < nbytes * 8 && r->entropy_count < r->poolinfo->POOLBITS) { @@ -753,17 +813,23 @@ static void xfer_secondary_pool(struct entropy_store *r, size_t nbytes) /* pull at least as many as BYTES as wakeup BITS */ bytes = max_t(int, bytes, random_read_wakeup_thresh / 8); /* but never more than the buffer size */ - bytes = min_t(int, bytes, sizeof(tmp)); + bytes = min_t(int, bytes, sizeof(u.tmp)); DEBUG_ENT("going to reseed %s with %d bits " "(%d of %d requested)\n", r->name, bytes * 8, nbytes * 8, r->entropy_count); - bytes = extract_entropy(r->pull, tmp, bytes, + bytes = extract_entropy(r->pull, u.tmp, bytes, random_read_wakeup_thresh / 8, rsvd); - mix_pool_bytes(r, tmp, bytes); + mix_pool_bytes(r, u.tmp, bytes, NULL); credit_entropy_bits(r, bytes*8); } + kmemcheck_mark_initialized(&u.hwrand, sizeof(u.hwrand)); + for (i = 0; i < 4; i++) + if (arch_get_random_long(&u.hwrand[i])) + break; + if (i) + mix_pool_bytes(r, &u.hwrand, sizeof(u.hwrand), 0); } /* @@ -822,9 +888,11 @@ static void extract_buf(struct entropy_store *r, __u8 *out) int i; __u32 hash[5], workspace[SHA_WORKSPACE_WORDS]; __u8 extract[64]; + unsigned long flags; /* Generate a hash across the pool, 16 words (512 bits) at a time */ sha_init(hash); + spin_lock_irqsave(&r->lock, flags); for (i = 0; i < r->poolinfo->poolwords; i += 16) sha_transform(hash, (__u8 *)(r->pool + i), workspace); @@ -837,7 +905,8 @@ static void extract_buf(struct entropy_store *r, __u8 *out) * brute-forcing the feedback as hard as brute-forcing the * hash. */ - mix_pool_bytes_extract(r, hash, sizeof(hash), extract); + __mix_pool_bytes(r, hash, sizeof(hash), extract); + spin_unlock_irqrestore(&r->lock, flags); /* * To avoid duplicates, we atomically extract a portion of the @@ -860,11 +929,10 @@ static void extract_buf(struct entropy_store *r, __u8 *out) } static ssize_t extract_entropy(struct entropy_store *r, void *buf, - size_t nbytes, int min, int reserved) + size_t nbytes, int min, int reserved) { ssize_t ret = 0, i; __u8 tmp[EXTRACT_SIZE]; - unsigned long flags; xfer_secondary_pool(r, nbytes); nbytes = account(r, nbytes, min, reserved); @@ -873,6 +941,8 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf, extract_buf(r, tmp); if (fips_enabled) { + unsigned long flags; + spin_lock_irqsave(&r->lock, flags); if (!memcmp(tmp, r->last_data, EXTRACT_SIZE)) panic("Hardware RNG duplicated output!\n"); @@ -931,17 +1001,34 @@ static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf, /* * This function is the exported kernel interface. It returns some - * number of good random numbers, suitable for seeding TCP sequence - * numbers, etc. + * number of good random numbers, suitable for key generation, seeding + * TCP sequence numbers, etc. It does not use the hw random number + * generator, if available; use get_random_bytes_arch() for that. */ void get_random_bytes(void *buf, int nbytes) +{ + extract_entropy(&nonblocking_pool, buf, nbytes, 0, 0); +} +EXPORT_SYMBOL(get_random_bytes); + +/* + * This function will use the architecture-specific hardware random + * number generator if it is available. The arch-specific hw RNG will + * almost certainly be faster than what we can do in software, but it + * is impossible to verify that it is implemented securely (as + * opposed, to, say, the AES encryption of a sequence number using a + * key known by the NSA). So it's useful if we need the speed, but + * only if we're willing to trust the hardware manufacturer not to + * have put in a back door. + */ +void get_random_bytes_arch(void *buf, int nbytes) { char *p = buf; while (nbytes) { unsigned long v; int chunk = min(nbytes, (int)sizeof(unsigned long)); - + if (!arch_get_random_long(&v)) break; @@ -950,9 +1037,11 @@ void get_random_bytes(void *buf, int nbytes) nbytes -= chunk; } - extract_entropy(&nonblocking_pool, p, nbytes, 0, 0); + if (nbytes) + extract_entropy(&nonblocking_pool, p, nbytes, 0, 0); } -EXPORT_SYMBOL(get_random_bytes); +EXPORT_SYMBOL(get_random_bytes_arch); + /* * init_std_data - initialize pool with system data @@ -966,21 +1055,18 @@ EXPORT_SYMBOL(get_random_bytes); static void init_std_data(struct entropy_store *r) { int i; - ktime_t now; - unsigned long flags; + ktime_t now = ktime_get_real(); + unsigned long rv; - spin_lock_irqsave(&r->lock, flags); r->entropy_count = 0; - spin_unlock_irqrestore(&r->lock, flags); - - now = ktime_get_real(); - mix_pool_bytes(r, &now, sizeof(now)); - for (i = r->poolinfo->POOLBYTES; i > 0; i -= sizeof flags) { - if (!arch_get_random_long(&flags)) + r->entropy_total = 0; + mix_pool_bytes(r, &now, sizeof(now), NULL); + for (i = r->poolinfo->POOLBYTES; i > 0; i -= sizeof(rv)) { + if (!arch_get_random_long(&rv)) break; - mix_pool_bytes(r, &flags, sizeof(flags)); + mix_pool_bytes(r, &rv, sizeof(rv), NULL); } - mix_pool_bytes(r, utsname(), sizeof(*(utsname()))); + mix_pool_bytes(r, utsname(), sizeof(*(utsname())), NULL); } static int rand_initialize(void) @@ -992,24 +1078,6 @@ static int rand_initialize(void) } module_init(rand_initialize); -void rand_initialize_irq(int irq) -{ - struct timer_rand_state *state; - - state = get_timer_rand_state(irq); - - if (state) - return; - - /* - * If kzalloc returns null, we just won't use that entropy - * source. - */ - state = kzalloc(sizeof(struct timer_rand_state), GFP_KERNEL); - if (state) - set_timer_rand_state(irq, state); -} - #ifdef CONFIG_BLOCK void rand_initialize_disk(struct gendisk *disk) { @@ -1117,7 +1185,7 @@ write_pool(struct entropy_store *r, const char __user *buffer, size_t count) count -= bytes; p += bytes; - mix_pool_bytes(r, buf, bytes); + mix_pool_bytes(r, buf, bytes, NULL); cond_resched(); } diff --git a/drivers/gpu/ion/ion.c b/drivers/gpu/ion/ion.c index ffeea43dab6..26bc2511eec 100644 --- a/drivers/gpu/ion/ion.c +++ b/drivers/gpu/ion/ion.c @@ -489,6 +489,11 @@ void ion_free(struct ion_client *client, struct ion_handle *handle) { bool valid_handle; + if(IS_ERR_OR_NULL(handle)) { + pr_err("%s: handle pointer is invalid\n", __func__) ; + return; + } + BUG_ON(client != handle->client); mutex_lock(&client->lock); @@ -733,6 +738,15 @@ void ion_unmap_iommu(struct ion_client *client, struct ion_handle *handle, struct ion_iommu_map *iommu_map; struct ion_buffer *buffer; + if(IS_ERR_OR_NULL(client)) { + pr_err("%s: client pointer is invalid\n", __func__) ; + return; + } + if(IS_ERR_OR_NULL(handle)) { + pr_err("%s: handle pointer is invalid\n", __func__) ; + return; + } + mutex_lock(&client->lock); buffer = handle->buffer; @@ -749,12 +763,13 @@ void ion_unmap_iommu(struct ion_client *client, struct ion_handle *handle, kref_put(&iommu_map->ref, ion_iommu_release); buffer->iommu_map_cnt--; + out: mutex_unlock(&buffer->lock); mutex_unlock(&client->lock); - } + EXPORT_SYMBOL(ion_unmap_iommu); void *ion_map_kernel(struct ion_client *client, struct ion_handle *handle) diff --git a/drivers/gpu/msm/Makefile b/drivers/gpu/msm/Makefile index 55edac31741..9c26f44a040 100644 --- a/drivers/gpu/msm/Makefile +++ b/drivers/gpu/msm/Makefile @@ -1,4 +1,4 @@ -ccflags-y := -Iinclude/drm -Idrivers/gpu/msm -Wframe-larger-than=1040 +ccflags-y := -Iinclude/uapi/drm -Iinclude/drm -Idrivers/gpu/msm -Wframe-larger-than=1040 msm_kgsl_core-y = \ kgsl.o \ @@ -17,7 +17,6 @@ msm_kgsl_core-$(CONFIG_MSM_KGSL_CFF_DUMP) += kgsl_cffdump.o msm_kgsl_core-$(CONFIG_MSM_KGSL_DRM) += kgsl_drm.o msm_kgsl_core-$(CONFIG_MSM_SCM) += kgsl_pwrscale_trustzone.o msm_kgsl_core-$(CONFIG_MSM_SLEEP_STATS_DEVICE) += kgsl_pwrscale_idlestats.o -msm_kgsl_core-$(CONFIG_MSM_DCVS) += kgsl_pwrscale_msm.o msm_kgsl_core-$(CONFIG_SYNC) += kgsl_sync.o msm_adreno-y += \ @@ -27,13 +26,16 @@ msm_adreno-y += \ adreno_postmortem.o \ adreno_snapshot.o \ adreno_trace.o \ + adreno_coresight.o \ adreno_a2xx.o \ adreno_a2xx_trace.o \ adreno_a2xx_snapshot.o \ adreno_a3xx.o \ + adreno_a4xx.o \ adreno_a3xx_trace.o \ adreno_a3xx_snapshot.o \ - adreno.o + adreno.o \ + adreno_cp_parser.o msm_adreno-$(CONFIG_DEBUG_FS) += adreno_debugfs.o diff --git a/drivers/gpu/msm/a3xx_reg.h b/drivers/gpu/msm/a3xx_reg.h index 21d475954fb..676f46da39a 100644 --- a/drivers/gpu/msm/a3xx_reg.h +++ b/drivers/gpu/msm/a3xx_reg.h @@ -165,8 +165,16 @@ #define A3XX_RBBM_PERFCTR_PWR_0_HI 0x0EB #define A3XX_RBBM_PERFCTR_PWR_1_LO 0x0EC #define A3XX_RBBM_PERFCTR_PWR_1_HI 0x0ED -#define A3XX_RBBM_DEBUG_BUS_CTL 0x111 -#define A3XX_RBBM_DEBUG_BUS_DATA_STATUS 0x112 +#define A3XX_RBBM_DEBUG_BUS_CTL 0x111 +#define A3XX_RBBM_DEBUG_BUS_DATA_STATUS 0x112 +#define A3XX_RBBM_DEBUG_BUS_STB_CTL0 0x11B +#define A3XX_RBBM_DEBUG_BUS_STB_CTL1 0x11C +#define A3XX_RBBM_INT_TRACE_BUS_CTL 0x11D +#define A3XX_RBBM_EXT_TRACE_BUS_CTL 0x11E +#define A3XX_RBBM_EXT_TRACE_STOP_CNT 0x11F +#define A3XX_RBBM_EXT_TRACE_START_CNT 0x120 +#define A3XX_RBBM_EXT_TRACE_PERIOD_CNT 0x121 +#define A3XX_RBBM_EXT_TRACE_CMD 0x122 /* Following two are same as on A2XX, just in a different place */ #define A3XX_CP_PFP_UCODE_ADDR 0x1C9 @@ -179,6 +187,7 @@ #define A3XX_CP_MEQ_ADDR 0x1DA #define A3XX_CP_MEQ_DATA 0x1DB #define A3XX_CP_PERFCOUNTER_SELECT 0x445 +#define A3XX_CP_WFI_PEND_CTR 0x01F5 #define A3XX_CP_HW_FAULT 0x45C #define A3XX_CP_AHB_FAULT 0x54D #define A3XX_CP_PROTECT_CTRL 0x45E @@ -231,6 +240,7 @@ #define A3XX_PC_PERFCOUNTER1_SELECT 0xC49 #define A3XX_PC_PERFCOUNTER2_SELECT 0xC4A #define A3XX_PC_PERFCOUNTER3_SELECT 0xC4B +#define A3XX_GRAS_TSE_DEBUG_ECO 0xC81 #define A3XX_GRAS_PERFCOUNTER0_SELECT 0xC88 #define A3XX_GRAS_PERFCOUNTER1_SELECT 0xC89 #define A3XX_GRAS_PERFCOUNTER2_SELECT 0xC8A @@ -260,8 +270,10 @@ #define A3XX_GRAS_CL_USER_PLANE_Z5 0xCB6 #define A3XX_GRAS_CL_USER_PLANE_W5 0xCB7 #define A3XX_RB_GMEM_BASE_ADDR 0xCC0 +#define A3XX_RB_DEBUG_ECO_CONTROLS_ADDR 0xCC1 #define A3XX_RB_PERFCOUNTER0_SELECT 0xCC6 #define A3XX_RB_PERFCOUNTER1_SELECT 0xCC7 +#define A3XX_RB_FRAME_BUFFER_DIMENSION 0xCE0 #define A3XX_HLSQ_PERFCOUNTER0_SELECT 0xE00 #define A3XX_HLSQ_PERFCOUNTER1_SELECT 0xE01 #define A3XX_HLSQ_PERFCOUNTER2_SELECT 0xE02 @@ -299,6 +311,9 @@ #define A3XX_GRAS_CL_CLIP_CNTL 0x2040 #define A3XX_GRAS_CL_GB_CLIP_ADJ 0x2044 #define A3XX_GRAS_CL_VPORT_XOFFSET 0x2048 +#define A3XX_GRAS_CL_VPORT_XSCALE 0x2049 +#define A3XX_GRAS_CL_VPORT_YOFFSET 0x204A +#define A3XX_GRAS_CL_VPORT_YSCALE 0x204B #define A3XX_GRAS_CL_VPORT_ZOFFSET 0x204C #define A3XX_GRAS_CL_VPORT_ZSCALE 0x204D #define A3XX_GRAS_SU_POINT_MINMAX 0x2068 @@ -314,30 +329,75 @@ #define A3XX_RB_MODE_CONTROL 0x20C0 #define A3XX_RB_RENDER_CONTROL 0x20C1 #define A3XX_RB_MSAA_CONTROL 0x20C2 +#define A3XX_RB_ALPHA_REFERENCE 0x20C3 #define A3XX_RB_MRT_CONTROL0 0x20C4 #define A3XX_RB_MRT_BUF_INFO0 0x20C5 +#define A3XX_RB_MRT_BUF_BASE0 0x20C6 #define A3XX_RB_MRT_BLEND_CONTROL0 0x20C7 +#define A3XX_RB_MRT_CONTROL1 0x20C8 +#define A3XX_RB_MRT_BUF_INFO1 0x20C9 +#define A3XX_RB_MRT_BUF_BASE1 0x20CA #define A3XX_RB_MRT_BLEND_CONTROL1 0x20CB +#define A3XX_RB_MRT_CONTROL2 0x20CC +#define A3XX_RB_MRT_BUF_INFO2 0x20CD +#define A3XX_RB_MRT_BUF_BASE2 0x20CE #define A3XX_RB_MRT_BLEND_CONTROL2 0x20CF +#define A3XX_RB_MRT_CONTROL3 0x20D0 +#define A3XX_RB_MRT_BUF_INFO3 0x20D1 +#define A3XX_RB_MRT_BUF_BASE3 0x20D2 #define A3XX_RB_MRT_BLEND_CONTROL3 0x20D3 #define A3XX_RB_BLEND_RED 0x20E4 +#define A3XX_RB_BLEND_GREEN 0x20E5 +#define A3XX_RB_BLEND_BLUE 0x20E6 +#define A3XX_RB_BLEND_ALPHA 0x20E7 +#define A3XX_RB_CLEAR_COLOR_DW0 0x20E8 +#define A3XX_RB_CLEAR_COLOR_DW1 0x20E9 +#define A3XX_RB_CLEAR_COLOR_DW2 0x20EA +#define A3XX_RB_CLEAR_COLOR_DW3 0x20EB #define A3XX_RB_COPY_CONTROL 0x20EC +#define A3XX_RB_COPY_DEST_BASE 0x20ED +#define A3XX_RB_COPY_DEST_PITCH 0x20EE #define A3XX_RB_COPY_DEST_INFO 0x20EF #define A3XX_RB_DEPTH_CONTROL 0x2100 +#define A3XX_RB_DEPTH_CLEAR 0x2101 +#define A3XX_RB_DEPTH_BUF_INFO 0x2102 +#define A3XX_RB_DEPTH_BUF_PITCH 0x2103 #define A3XX_RB_STENCIL_CONTROL 0x2104 +#define A3XX_RB_STENCIL_CLEAR 0x2105 +#define A3XX_RB_STENCIL_BUF_INFO 0x2106 +#define A3XX_RB_STENCIL_BUF_PITCH 0x2107 +#define A3XX_RB_STENCIL_REF_MASK 0x2108 +#define A3XX_RB_STENCIL_REF_MASK_BF 0x2109 +#define A3XX_RB_LRZ_VSC_CONTROL 0x210C +#define A3XX_RB_WINDOW_OFFSET 0x210E +#define A3XX_RB_SAMPLE_COUNT_CONTROL 0x2110 +#define A3XX_RB_SAMPLE_COUNT_ADDR 0x2111 +#define A3XX_RB_Z_CLAMP_MIN 0x2114 +#define A3XX_RB_Z_CLAMP_MAX 0x2115 #define A3XX_PC_VSTREAM_CONTROL 0x21E4 #define A3XX_PC_VERTEX_REUSE_BLOCK_CNTL 0x21EA #define A3XX_PC_PRIM_VTX_CNTL 0x21EC #define A3XX_PC_RESTART_INDEX 0x21ED #define A3XX_HLSQ_CONTROL_0_REG 0x2200 +#define A3XX_HLSQ_CONTROL_1_REG 0x2201 +#define A3XX_HLSQ_CONTROL_2_REG 0x2202 +#define A3XX_HLSQ_CONTROL_3_REG 0x2203 #define A3XX_HLSQ_VS_CONTROL_REG 0x2204 +#define A3XX_HLSQ_FS_CONTROL_REG 0x2205 +#define A3XX_HLSQ_CONST_VSPRESV_RANGE_REG 0x2206 #define A3XX_HLSQ_CONST_FSPRESV_RANGE_REG 0x2207 #define A3XX_HLSQ_CL_NDRANGE_0_REG 0x220A +#define A3XX_HLSQ_CL_NDRANGE_1_REG 0x220B #define A3XX_HLSQ_CL_NDRANGE_2_REG 0x220C +#define A3XX_HLSQ_CL_NDRANGE_3_REG 0x220D +#define A3XX_HLSQ_CL_NDRANGE_4_REG 0x220E +#define A3XX_HLSQ_CL_NDRANGE_5_REG 0x220F +#define A3XX_HLSQ_CL_NDRANGE_6_REG 0x2210 #define A3XX_HLSQ_CL_CONTROL_0_REG 0x2211 #define A3XX_HLSQ_CL_CONTROL_1_REG 0x2212 #define A3XX_HLSQ_CL_KERNEL_CONST_REG 0x2214 #define A3XX_HLSQ_CL_KERNEL_GROUP_X_REG 0x2215 +#define A3XX_HLSQ_CL_KERNEL_GROUP_Y_REG 0x2216 #define A3XX_HLSQ_CL_KERNEL_GROUP_Z_REG 0x2217 #define A3XX_HLSQ_CL_WG_OFFSET_REG 0x221A #define A3XX_VFD_CONTROL_0 0x2240 @@ -354,10 +414,21 @@ #define A3XX_SP_VS_CTRL_REG0 0x22C4 #define A3XX_SP_VS_CTRL_REG1 0x22C5 #define A3XX_SP_VS_PARAM_REG 0x22C6 +#define A3XX_SP_VS_OUT_REG_0 0x22C7 +#define A3XX_SP_VS_OUT_REG_1 0x22C8 +#define A3XX_SP_VS_OUT_REG_2 0x22C9 +#define A3XX_SP_VS_OUT_REG_3 0x22CA +#define A3XX_SP_VS_OUT_REG_4 0x22CB +#define A3XX_SP_VS_OUT_REG_5 0x22CC +#define A3XX_SP_VS_OUT_REG_6 0x22CD #define A3XX_SP_VS_OUT_REG_7 0x22CE #define A3XX_SP_VS_VPC_DST_REG_0 0x22D0 +#define A3XX_SP_VS_VPC_DST_REG_1 0x22D1 +#define A3XX_SP_VS_VPC_DST_REG_2 0x22D2 +#define A3XX_SP_VS_VPC_DST_REG_3 0x22D3 #define A3XX_SP_VS_OBJ_OFFSET_REG 0x22D4 #define A3XX_SP_VS_OBJ_START_REG 0x22D5 +#define A3XX_SP_VS_PVT_MEM_PARAM_REG 0x22D6 #define A3XX_SP_VS_PVT_MEM_ADDR_REG 0x22D7 #define A3XX_SP_VS_PVT_MEM_SIZE_REG 0x22D8 #define A3XX_SP_VS_LENGTH_REG 0x22DF @@ -365,13 +436,19 @@ #define A3XX_SP_FS_CTRL_REG1 0x22E1 #define A3XX_SP_FS_OBJ_OFFSET_REG 0x22E2 #define A3XX_SP_FS_OBJ_START_REG 0x22E3 +#define A3XX_SP_FS_PVT_MEM_PARAM_REG 0x22E4 #define A3XX_SP_FS_PVT_MEM_ADDR_REG 0x22E5 #define A3XX_SP_FS_PVT_MEM_SIZE_REG 0x22E6 #define A3XX_SP_FS_FLAT_SHAD_MODE_REG_0 0x22E8 #define A3XX_SP_FS_FLAT_SHAD_MODE_REG_1 0x22E9 #define A3XX_SP_FS_OUTPUT_REG 0x22EC #define A3XX_SP_FS_MRT_REG_0 0x22F0 +#define A3XX_SP_FS_MRT_REG_1 0x22F1 +#define A3XX_SP_FS_MRT_REG_2 0x22F2 +#define A3XX_SP_FS_MRT_REG_3 0x22F3 #define A3XX_SP_FS_IMAGE_OUTPUT_REG_0 0x22F4 +#define A3XX_SP_FS_IMAGE_OUTPUT_REG_1 0x22F5 +#define A3XX_SP_FS_IMAGE_OUTPUT_REG_2 0x22F6 #define A3XX_SP_FS_IMAGE_OUTPUT_REG_3 0x22F7 #define A3XX_SP_FS_LENGTH_REG 0x22FF #define A3XX_TPL1_TP_VS_TEX_OFFSET 0x2340 @@ -416,6 +493,9 @@ #define RBBM_RBBM_CTL_ENABLE_PWR_CTR0 BIT(16) #define RBBM_RBBM_CTL_ENABLE_PWR_CTR1 BIT(17) +/* Bit flag for RBMM_PERFCTR_CTL */ +#define RBBM_PERFCTR_CTL_ENABLE BIT(0) + /* Various flags used by the context switch code */ #define SP_MULTI 0 @@ -680,12 +760,14 @@ /* RBBM_CLOCK_CTL default value */ #define A305_RBBM_CLOCK_CTL_DEFAULT 0xAAAAAAAA +#define A305C_RBBM_CLOCK_CTL_DEFAULT 0xAAAAAAAA #define A320_RBBM_CLOCK_CTL_DEFAULT 0xBFFFFFFF -#define A330_RBBM_CLOCK_CTL_DEFAULT 0xAAAAAAAE +#define A330_RBBM_CLOCK_CTL_DEFAULT 0xBFFCFFFF #define A330v2_RBBM_CLOCK_CTL_DEFAULT 0xAAAAAAAA +#define A305B_RBBM_CLOCK_CTL_DEFAULT 0xAAAAAAAA -#define A330_RBBM_GPR0_CTL_DEFAULT 0x0AE2B8AE -#define A330v2_RBBM_GPR0_CTL_DEFAULT 0x0AA2A8AA +#define A330_RBBM_GPR0_CTL_DEFAULT 0x00000000 +#define A330v2_RBBM_GPR0_CTL_DEFAULT 0x05515455 /* COUNTABLE FOR SP PERFCOUNTER */ #define SP_FS_FULL_ALU_INSTRUCTIONS 0x0E diff --git a/drivers/gpu/msm/a4xx_reg.h b/drivers/gpu/msm/a4xx_reg.h new file mode 100644 index 00000000000..56147f7c415 --- /dev/null +++ b/drivers/gpu/msm/a4xx_reg.h @@ -0,0 +1,92 @@ +/* Copyright (c) 2013, The Linux Foundation. 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 and + * only 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. + * + */ + +#ifndef _A4XX_REG_H +#define _A4XX_REG_H + +/* RB registers */ +#define A4XX_RB_GMEM_BASE_ADDR 0xcc0 + +/* RBBM registers */ +#define A4XX_RBBM_AHB_CMD 0x25 +#define A4XX_RBBM_SP_HYST_CNT 0x21 +#define A4XX_RBBM_AHB_CTL0 0x23 +#define A4XX_RBBM_AHB_CTL1 0x24 +#define A4XX_RBBM_WAIT_IDLE_CLOCKS_CTL 0x2b +#define A4XX_RBBM_INTERFACE_HANG_INT_CTL 0x2f +#define A4XX_RBBM_AHB_ERROR_STATUS 0x18f +#define A4XX_RBBM_STATUS 0x191 +#define A4XX_RBBM_INT_CLEAR_CMD 0x36 +#define A4XX_RBBM_INT_0_MASK 0x37 +#define A4XX_RBBM_INT_0_STATUS 0x17d +#define A4XX_RBBM_PERFCTR_CTL 0x170 +#define A4XX_RBBM_PERFCTR_LOAD_CMD0 0x171 +#define A4XX_RBBM_PERFCTR_LOAD_CMD1 0x172 +#define A4XX_RBBM_PERFCTR_LOAD_CMD2 0x173 +#define A4XX_RBBM_GPU_BUSY_MASKED 0x17a +#define A4XX_RBBM_PERFCTR_PWR_1_LO 0x168 + +/* CP registers */ +#define A4XX_CP_SCRATCH_REG0 0x578 +#define A4XX_CP_SCRATCH_UMASK 0x228 +#define A4XX_CP_SCRATCH_ADDR 0x229 +#define A4XX_CP_RB_BASE 0x200 +#define A4XX_CP_RB_CNTL 0x201 +#define A4XX_CP_RB_WPTR 0x205 +#define A4XX_CP_RB_RPTR_ADDR 0x203 +#define A4XX_CP_RB_RPTR 0x204 +#define A4XX_CP_IB1_BASE 0x206 +#define A4XX_CP_IB1_BUFSZ 0x207 +#define A4XX_CP_IB2_BASE 0x208 +#define A4XX_CP_IB2_BUFSZ 0x209 +#define A4XX_CP_WFI_PEND_CTR 0x4d2 +#define A4XX_CP_ME_CNTL 0x22d +#define A4XX_CP_ME_RAM_WADDR 0x225 +#define A4XX_CP_ME_RAM_RADDR 0x226 +#define A4XX_CP_ME_RAM_DATA 0x227 +#define A4XX_CP_PFP_UCODE_ADDR 0x223 +#define A4XX_CP_PFP_UCODE_DATA 0x224 +#define A4XX_CP_PROTECT_CTRL 0x250 +#define A4XX_CP_DEBUG 0x22e + +/* SP registers */ +#define A4XX_SP_VS_OBJ_START 0x22e1 +#define A4XX_SP_VS_PVT_MEM_ADDR 0x22e3 +#define A4XX_SP_FS_OBJ_START 0x22eb +#define A4XX_SP_FS_PVT_MEM_ADDR 0x22ed + +/* VPC registers */ +#define A4XX_VPC_DEBUG_RAM_SEL 0xe60 +#define A4XX_VPC_DEBUG_RAM_READ 0xe61 + +/* VSC registers */ +#define A4XX_VSC_SIZE_ADDRESS 0xc01 +#define A4XX_VSC_PIPE_DATA_ADDRESS_0 0xc10 +#define A4XX_VSC_PIPE_DATA_LENGTH_7 0xc1f + +/* VFD registers */ +#define A4XX_VFD_CONTROL_0 0x2200 +#define A4XX_VFD_FETCH_INSTR_0_0 0x220a +#define A4XX_VFD_FETCH_INSTR_1_31 0x2287 + +/* VBIF */ +#define A4XX_VBIF_ABIT_SORT 0x301c +#define A4XX_VBIF_ABIT_SORT_CONF 0x301d +#define A4XX_VBIF_GATE_OFF_WRREQ_EN 0x302a +#define A4XX_VBIF_IN_RD_LIM_CONF0 0x302c +#define A4XX_VBIF_IN_RD_LIM_CONF1 0x302d +#define A4XX_VBIF_IN_WR_LIM_CONF0 0x3030 +#define A4XX_VBIF_IN_WR_LIM_CONF1 0x3031 +#define A4XX_VBIF_ROUND_ROBIN_QOS_ARB 0x3049 + +#endif /* _A400_REG_H */ diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index 4eb982186e7..72d7410ae26 100644 --- a/drivers/gpu/msm/adreno.c +++ b/drivers/gpu/msm/adreno.c @@ -18,12 +18,12 @@ #include #include #include +#include +#include #include #include #include -#include -#include #include "kgsl.h" #include "kgsl_pwrscale.h" @@ -41,6 +41,9 @@ #define DRIVER_VERSION_MAJOR 3 #define DRIVER_VERSION_MINOR 1 +/* Number of times to try hard reset */ +#define NUM_TIMES_RESET_RETRY 5 + /* Adreno MH arbiter config*/ #define ADRENO_CFG_MHARB \ (0x10 \ @@ -73,6 +76,8 @@ | (MMU_CONFIG << MH_MMU_CONFIG__TC_R_CLNT_BEHAVIOR__SHIFT) \ | (MMU_CONFIG << MH_MMU_CONFIG__PA_W_CLNT_BEHAVIOR__SHIFT)) +#define KGSL_LOG_LEVEL_DEFAULT 3 + static const struct kgsl_functable adreno_functable; static struct adreno_device device_3d0 = { @@ -100,14 +105,14 @@ static struct adreno_device device_3d0 = { .irq_name = KGSL_3D0_IRQ, }, .iomemname = KGSL_3D0_REG_MEMORY, + .shadermemname = KGSL_3D0_SHADER_MEMORY, .ftbl = &adreno_functable, -#ifdef CONFIG_HAS_EARLYSUSPEND - .display_off = { - .level = EARLY_SUSPEND_LEVEL_STOP_DRAWING, - .suspend = kgsl_early_suspend_driver, - .resume = kgsl_late_resume_driver, - }, -#endif + .cmd_log = KGSL_LOG_LEVEL_DEFAULT, + .ctxt_log = KGSL_LOG_LEVEL_DEFAULT, + .drv_log = KGSL_LOG_LEVEL_DEFAULT, + .mem_log = KGSL_LOG_LEVEL_DEFAULT, + .pwr_log = KGSL_LOG_LEVEL_DEFAULT, + .pm_dump_enable = 0, }, .gmem_base = 0, .gmem_size = SZ_256K, @@ -115,25 +120,13 @@ static struct adreno_device device_3d0 = { .pm4_fw = NULL, .wait_timeout = 0, /* in milliseconds, 0 means disabled */ .ib_check_level = 0, + .ft_policy = KGSL_FT_DEFAULT_POLICY, + .ft_pf_policy = KGSL_FT_PAGEFAULT_DEFAULT_POLICY, + .fast_hang_detect = 1, + .long_ib_detect = 1, }; -#define LONG_IB_DETECT_REG_INDEX_START 1 -#define LONG_IB_DETECT_REG_INDEX_END 5 - -unsigned int ft_detect_regs[FT_DETECT_REGS_COUNT] = { - A3XX_RBBM_STATUS, - REG_CP_RB_RPTR, /* LONG_IB_DETECT_REG_INDEX_START */ - REG_CP_IB1_BASE, - REG_CP_IB1_BUFSZ, - REG_CP_IB2_BASE, - REG_CP_IB2_BUFSZ, /* LONG_IB_DETECT_REG_INDEX_END */ - 0, - 0, - 0, - 0, - 0, - 0 -}; +unsigned int ft_detect_regs[FT_DETECT_REGS_COUNT]; /* * This is the master list of all GPU cores that are supported by this @@ -156,11 +149,20 @@ static const struct { /* size of gmem for gpu*/ unsigned int gmem_size; /* version of pm4 microcode that supports sync_lock - between CPU and GPU for SMMU-v1 programming */ + between CPU and GPU for IOMMU-v0 programming */ unsigned int sync_lock_pm4_ver; /* version of pfp microcode that supports sync_lock - between CPU and GPU for SMMU-v1 programming */ + between CPU and GPU for IOMMU-v0 programming */ unsigned int sync_lock_pfp_ver; + /* PM4 jump table index */ + unsigned int pm4_jt_idx; + /* PM4 jump table load addr */ + unsigned int pm4_jt_addr; + /* PFP jump table index */ + unsigned int pfp_jt_idx; + /* PFP jump table load addr */ + unsigned int pfp_jt_addr; + } adreno_gpulist[] = { { ADRENO_REV_A200, 0, 2, ANY_ID, ANY_ID, "yamato_pm4.fw", "yamato_pfp.fw", &adreno_a2xx_gpudev, @@ -188,7 +190,7 @@ static const struct { "a225_pm4.fw", "a225_pfp.fw", &adreno_a2xx_gpudev, 1536, 768, 3, SZ_512K, 0x225011, 0x225002 }, /* A3XX doesn't use the pix_shader_start */ - { ADRENO_REV_A305, 3, 0, 5, ANY_ID, + { ADRENO_REV_A305, 3, 0, 5, 0, "a300_pm4.fw", "a300_pfp.fw", &adreno_a3xx_gpudev, 512, 0, 2, SZ_256K, 0x3FF037, 0x3FF016 }, /* A3XX doesn't use the pix_shader_start */ @@ -197,7 +199,22 @@ static const struct { 512, 0, 2, SZ_512K, 0x3FF037, 0x3FF016 }, { ADRENO_REV_A330, 3, 3, 0, ANY_ID, "a330_pm4.fw", "a330_pfp.fw", &adreno_a3xx_gpudev, - 512, 0, 2, SZ_1M, NO_VER, NO_VER }, + 512, 0, 2, SZ_1M, NO_VER, NO_VER, 0x8AD, 0x2E4, 0x201, 0x200 }, + { ADRENO_REV_A305B, 3, 0, 5, 0x10, + "a330_pm4.fw", "a330_pfp.fw", &adreno_a3xx_gpudev, + 512, 0, 2, SZ_128K, NO_VER, NO_VER, 0x8AD, 0x2E4, + 0x201, 0x200 }, + /* 8226v2 */ + { ADRENO_REV_A305B, 3, 0, 5, 0x12, + "a330_pm4.fw", "a330_pfp.fw", &adreno_a3xx_gpudev, + 512, 0, 2, SZ_128K, NO_VER, NO_VER, 0x8AD, 0x2E4, + 0x201, 0x200 }, + { ADRENO_REV_A305C, 3, 0, 5, 0x20, + "a300_pm4.fw", "a300_pfp.fw", &adreno_a3xx_gpudev, + 512, 0, 2, SZ_128K, 0x3FF037, 0x3FF016 }, + { ADRENO_REV_A420, 4, 2, 0, ANY_ID, + "a420_pm4.fw", "a420_pfp.fw", &adreno_a4xx_gpudev, + 512, 0, 2, (SZ_1M + SZ_512K), NO_VER, NO_VER }, }; /** @@ -211,14 +228,28 @@ static const struct { * performance counters will remain active as long as the device is alive. */ -static void adreno_perfcounter_init(struct kgsl_device *device) +static int adreno_perfcounter_init(struct kgsl_device *device) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); if (adreno_dev->gpudev->perfcounter_init) - adreno_dev->gpudev->perfcounter_init(adreno_dev); + return adreno_dev->gpudev->perfcounter_init(adreno_dev); + return 0; }; +/** + * adreno_perfcounter_close: Release counters initialized by + * adreno_perfcounter_init + * @device: device to realease counters for + * + */ +static void adreno_perfcounter_close(struct kgsl_device *device) +{ + struct adreno_device *adreno_dev = ADRENO_DEVICE(device); + if (adreno_dev->gpudev->perfcounter_close) + return adreno_dev->gpudev->perfcounter_close(adreno_dev); +} + /** * adreno_perfcounter_start: Enable performance counters * @adreno_dev: Adreno device to configure @@ -226,14 +257,18 @@ static void adreno_perfcounter_init(struct kgsl_device *device) * Ensure all performance counters are enabled that are allocated. Since * the device was most likely stopped, we can't trust that the counters * are still valid so make it so. + * Returns 0 on success else error code */ -static void adreno_perfcounter_start(struct adreno_device *adreno_dev) +static int adreno_perfcounter_start(struct adreno_device *adreno_dev) { struct adreno_perfcounters *counters = adreno_dev->gpudev->perfcounters; struct adreno_perfcount_group *group; unsigned int i, j; + int ret = 0; + if (NULL == counters) + return 0; /* group id iter */ for (i = 0; i < counters->group_count; i++) { group = &(counters->groups[i]); @@ -241,15 +276,21 @@ static void adreno_perfcounter_start(struct adreno_device *adreno_dev) /* countable iter */ for (j = 0; j < group->reg_count; j++) { if (group->regs[j].countable == - KGSL_PERFCOUNTER_NOT_USED) + KGSL_PERFCOUNTER_NOT_USED || + group->regs[j].countable == + KGSL_PERFCOUNTER_BROKEN) continue; if (adreno_dev->gpudev->perfcounter_enable) - adreno_dev->gpudev->perfcounter_enable( + ret = adreno_dev->gpudev->perfcounter_enable( adreno_dev, i, j, group->regs[j].countable); + if (ret) + goto done; } } +done: + return ret; } /** @@ -271,8 +312,7 @@ int adreno_perfcounter_read_group(struct adreno_device *adreno_dev, unsigned int i, j; int ret = 0; - /* perfcounter get/put/query/read not allowed on a2xx */ - if (adreno_is_a2xx(adreno_dev)) + if (NULL == counters) return -EINVAL; /* sanity check for later */ @@ -283,11 +323,6 @@ int adreno_perfcounter_read_group(struct adreno_device *adreno_dev, if (reads == NULL || count == 0 || count > 100) return -EINVAL; - /* verify valid inputs group ids and countables */ - for (i = 0; i < count; i++) { - if (reads[i].groupid >= counters->group_count) - return -EINVAL; - } list = kmalloc(sizeof(struct kgsl_perfcounter_read_group) * count, GFP_KERNEL); @@ -300,6 +335,12 @@ int adreno_perfcounter_read_group(struct adreno_device *adreno_dev, goto done; } + /* verify valid inputs group ids and countables */ + for (i = 0; i < count; i++) { + if (list[i].groupid >= counters->group_count) + return -EINVAL; + } + /* list iterator */ for (j = 0; j < count; j++) { list[j].value = 0; @@ -311,8 +352,7 @@ int adreno_perfcounter_read_group(struct adreno_device *adreno_dev, if (group->regs[i].countable == list[j].countable) { list[j].value = adreno_dev->gpudev->perfcounter_read( - adreno_dev, list[j].groupid, - i, group->regs[i].offset); + adreno_dev, list[j].groupid, i); break; } } @@ -350,8 +390,7 @@ int adreno_perfcounter_query_group(struct adreno_device *adreno_dev, *max_counters = 0; - /* perfcounter get/put/query not allowed on a2xx */ - if (adreno_is_a2xx(adreno_dev)) + if (NULL == counters) return -EINVAL; if (groupid >= counters->group_count) @@ -400,13 +439,13 @@ int adreno_perfcounter_get(struct adreno_device *adreno_dev, struct adreno_perfcounters *counters = adreno_dev->gpudev->perfcounters; struct adreno_perfcount_group *group; unsigned int i, empty = -1; + int ret = 0; /* always clear return variables */ if (offset) *offset = 0; - /* perfcounter get/put/query not allowed on a2xx */ - if (adreno_is_a2xx(adreno_dev)) + if (NULL == counters) return -EINVAL; if (groupid >= counters->group_count) @@ -422,8 +461,11 @@ int adreno_perfcounter_get(struct adreno_device *adreno_dev, for (i = 0; i < group->reg_count; i++) { if (group->regs[i].countable == countable) { /* Countable already associated with counter */ - group->regs[i].refcount++; - group->regs[i].flags |= flags; + if (flags & PERFCOUNTER_FLAG_KERNEL) + group->regs[i].kernelcount++; + else + group->regs[i].usercount++; + if (offset) *offset = group->regs[i].offset; return 0; @@ -438,20 +480,27 @@ int adreno_perfcounter_get(struct adreno_device *adreno_dev, if (empty == -1) return -EBUSY; - /* initialize the new counter */ - group->regs[empty].countable = countable; - group->regs[empty].refcount = 1; - /* enable the new counter */ - adreno_dev->gpudev->perfcounter_enable(adreno_dev, groupid, empty, + ret = adreno_dev->gpudev->perfcounter_enable(adreno_dev, groupid, empty, countable); + if (ret) + return ret; + /* initialize the new counter */ + group->regs[empty].countable = countable; - group->regs[empty].flags = flags; + /* set initial kernel and user count */ + if (flags & PERFCOUNTER_FLAG_KERNEL) { + group->regs[empty].kernelcount = 1; + group->regs[empty].usercount = 0; + } else { + group->regs[empty].kernelcount = 0; + group->regs[empty].usercount = 1; + } if (offset) *offset = group->regs[empty].offset; - return 0; + return ret; } @@ -460,20 +509,20 @@ int adreno_perfcounter_get(struct adreno_device *adreno_dev, * @adreno_dev: Adreno device to configure * @groupid: Desired performance counter group * @countable: Countable desired to be freed from a counter + * @flags: Flag to determine if kernel or user space request * * Put a performance counter/countable pair that was previously received. If * noone else is using the countable, free up the counter for others. */ int adreno_perfcounter_put(struct adreno_device *adreno_dev, - unsigned int groupid, unsigned int countable) + unsigned int groupid, unsigned int countable, unsigned int flags) { struct adreno_perfcounters *counters = adreno_dev->gpudev->perfcounters; struct adreno_perfcount_group *group; unsigned int i; - /* perfcounter get/put/query not allowed on a2xx */ - if (adreno_is_a2xx(adreno_dev)) + if (NULL == counters) return -EINVAL; if (groupid >= counters->group_count) @@ -481,24 +530,27 @@ int adreno_perfcounter_put(struct adreno_device *adreno_dev, group = &(counters->groups[groupid]); + /* + * Find if the counter/countable pair is used currently. + * Start cycling through registers in the bank. + */ for (i = 0; i < group->reg_count; i++) { + /* check if countable assigned is what we are looking for */ if (group->regs[i].countable == countable) { - if (group->regs[i].refcount > 0) { - group->regs[i].refcount--; + /* found pair, book keep count based on request type */ + if (flags & PERFCOUNTER_FLAG_KERNEL && + group->regs[i].kernelcount > 0) + group->regs[i].kernelcount--; + else if (group->regs[i].usercount > 0) + group->regs[i].usercount--; + else + break; - /* - * book keeping to ensure we never free a - * perf counter used by kernel - */ - if (group->regs[i].flags && - group->regs[i].refcount == 0) - group->regs[i].refcount++; - - /* make available if not used */ - if (group->regs[i].refcount == 0) - group->regs[i].countable = - KGSL_PERFCOUNTER_NOT_USED; - } + /* mark available if not used anymore */ + if (group->regs[i].kernelcount == 0 && + group->regs[i].usercount == 0) + group->regs[i].countable = + KGSL_PERFCOUNTER_NOT_USED; return 0; } @@ -526,31 +578,40 @@ static void adreno_cleanup_pt(struct kgsl_device *device, kgsl_mmu_unmap(pagetable, &device->memstore); + kgsl_mmu_unmap(pagetable, &adreno_dev->pwron_fixup); + kgsl_mmu_unmap(pagetable, &device->mmu.setstate_memory); } static int adreno_setup_pt(struct kgsl_device *device, struct kgsl_pagetable *pagetable) { - int result = 0; + int result; struct adreno_device *adreno_dev = ADRENO_DEVICE(device); struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer; result = kgsl_mmu_map_global(pagetable, &rb->buffer_desc); - if (result) - goto error; - result = kgsl_mmu_map_global(pagetable, &rb->memptrs_desc); - if (result) - goto unmap_buffer_desc; + if (!result) + result = kgsl_mmu_map_global(pagetable, &rb->memptrs_desc); - result = kgsl_mmu_map_global(pagetable, &device->memstore); - if (result) - goto unmap_memptrs_desc; + if (!result) + result = kgsl_mmu_map_global(pagetable, &device->memstore); + + if (!result) + result = kgsl_mmu_map_global(pagetable, + &adreno_dev->pwron_fixup); - result = kgsl_mmu_map_global(pagetable, &device->mmu.setstate_memory); - if (result) - goto unmap_memstore_desc; + + if (!result) + result = kgsl_mmu_map_global(pagetable, + &device->mmu.setstate_memory); + + if (result) { + /* On error clean up what we have wrought */ + adreno_cleanup_pt(device, pagetable); + return result; + } /* * Set the mpu end to the last "normal" global memory we use. @@ -559,61 +620,19 @@ static int adreno_setup_pt(struct kgsl_device *device, */ device->mh.mpu_range = device->mmu.setstate_memory.gpuaddr + device->mmu.setstate_memory.size; - return result; -unmap_memstore_desc: - kgsl_mmu_unmap(pagetable, &device->memstore); - -unmap_memptrs_desc: - kgsl_mmu_unmap(pagetable, &rb->memptrs_desc); - -unmap_buffer_desc: - kgsl_mmu_unmap(pagetable, &rb->buffer_desc); - -error: - return result; + return 0; } -static int adreno_iommu_setstate(struct kgsl_device *device, - unsigned int context_id, - uint32_t flags) +static unsigned int _adreno_iommu_setstate_v0(struct kgsl_device *device, + unsigned int *cmds_orig, + phys_addr_t pt_val, + int num_iommu_units, uint32_t flags) { - unsigned int pt_val, reg_pt_val; - unsigned int link[250]; - unsigned int *cmds = &link[0]; - int sizedwords = 0; + phys_addr_t reg_pt_val; + unsigned int *cmds = cmds_orig; struct adreno_device *adreno_dev = ADRENO_DEVICE(device); - int num_iommu_units, i; - struct kgsl_context *context; - struct adreno_context *adreno_ctx = NULL; - int result = 0; - - /* - * If we're idle and we don't need to use the GPU to save context - * state, use the CPU instead of the GPU to reprogram the - * iommu for simplicity's sake. - */ - if (!adreno_dev->drawctxt_active || device->ftbl->isidle(device) || - !atomic_read(&device->active_cnt)) - return kgsl_mmu_device_setstate(&device->mmu, flags); - - num_iommu_units = kgsl_mmu_get_num_iommu_units(&device->mmu); - - context = kgsl_context_get(device, context_id); - - if (context == NULL) - return 0; - - adreno_ctx = ADRENO_CONTEXT(context); - - result = kgsl_mmu_enable_clk(&device->mmu, KGSL_IOMMU_CONTEXT_USER); - - if (result) - goto done; - - cmds += __adreno_add_idle_indirect_cmds(cmds, - device->mmu.setstate_memory.gpuaddr + - KGSL_IOMMU_SETSTATE_NOP_OFFSET); + int i; if (cpu_is_msm8960()) cmds += adreno_add_change_mh_phys_limit_cmds(cmds, 0xFFFFF000, @@ -630,16 +649,16 @@ static int adreno_iommu_setstate(struct kgsl_device *device, /* Acquire GPU-CPU sync Lock here */ cmds += kgsl_mmu_sync_lock(&device->mmu, cmds); - pt_val = kgsl_mmu_get_pt_base_addr(&device->mmu, - device->mmu.hwpagetable); if (flags & KGSL_MMUFLAGS_PTUPDATE) { /* * We need to perfrom the following operations for all * IOMMU units */ for (i = 0; i < num_iommu_units; i++) { - reg_pt_val = (pt_val + kgsl_mmu_get_pt_lsb(&device->mmu, - i, KGSL_IOMMU_CONTEXT_USER)); + reg_pt_val = kgsl_mmu_get_default_ttbr0(&device->mmu, + i, KGSL_IOMMU_CONTEXT_USER); + reg_pt_val &= ~KGSL_IOMMU_CTX_TTBR0_ADDR_MASK; + reg_pt_val |= (pt_val & KGSL_IOMMU_CTX_TTBR0_ADDR_MASK); /* * Set address of the new pagetable by writng to IOMMU * TTBR0 register @@ -668,8 +687,11 @@ static int adreno_iommu_setstate(struct kgsl_device *device, * tlb flush */ for (i = 0; i < num_iommu_units; i++) { - reg_pt_val = (pt_val + kgsl_mmu_get_pt_lsb(&device->mmu, + reg_pt_val = (pt_val + kgsl_mmu_get_default_ttbr0( + &device->mmu, i, KGSL_IOMMU_CONTEXT_USER)); + reg_pt_val &= ~KGSL_IOMMU_CTX_TTBR0_ADDR_MASK; + reg_pt_val |= (pt_val & KGSL_IOMMU_CTX_TTBR0_ADDR_MASK); *cmds++ = cp_type3_packet(CP_MEM_WRITE, 2); *cmds++ = kgsl_mmu_get_reg_gpuaddr(&device->mmu, i, @@ -708,36 +730,206 @@ static int adreno_iommu_setstate(struct kgsl_device *device, cmds += adreno_add_idle_cmds(adreno_dev, cmds); - sizedwords += (cmds - &link[0]); - if (sizedwords) { - - /* invalidate all base pointers */ - *cmds++ = cp_type3_packet(CP_INVALIDATE_STATE, 1); - *cmds++ = 0x7fff; - sizedwords += 2; - /* This returns the per context timestamp but we need to - * use the global timestamp for iommu clock disablement */ - result = adreno_ringbuffer_issuecmds(device, adreno_ctx, - KGSL_CMD_FLAGS_PMODE, - &link[0], sizedwords); + return cmds - cmds_orig; +} - if (result) { - /* On error disable the IOMMU clock right away */ - kgsl_mmu_disable_clk(&device->mmu); - goto done; +static unsigned int _adreno_iommu_setstate_v1(struct kgsl_device *device, + unsigned int *cmds_orig, + phys_addr_t pt_val, + int num_iommu_units, uint32_t flags) +{ + struct adreno_device *adreno_dev = ADRENO_DEVICE(device); + phys_addr_t ttbr0_val; + unsigned int reg_pt_val; + unsigned int *cmds = cmds_orig; + int i; + unsigned int ttbr0, tlbiall, tlbstatus, tlbsync, mmu_ctrl; + + for (i = 0; i < num_iommu_units; i++) { + ttbr0_val = kgsl_mmu_get_default_ttbr0(&device->mmu, + i, KGSL_IOMMU_CONTEXT_USER); + ttbr0_val &= ~KGSL_IOMMU_CTX_TTBR0_ADDR_MASK; + ttbr0_val |= (pt_val & KGSL_IOMMU_CTX_TTBR0_ADDR_MASK); + if (flags & KGSL_MMUFLAGS_PTUPDATE) { + mmu_ctrl = kgsl_mmu_get_reg_ahbaddr( + &device->mmu, i, + KGSL_IOMMU_CONTEXT_USER, + KGSL_IOMMU_IMPLDEF_MICRO_MMU_CTRL) >> 2; + + ttbr0 = kgsl_mmu_get_reg_ahbaddr(&device->mmu, i, + KGSL_IOMMU_CONTEXT_USER, + KGSL_IOMMU_CTX_TTBR0) >> 2; + + if (kgsl_mmu_hw_halt_supported(&device->mmu, i)) { + *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1); + *cmds++ = 0; + /* + * glue commands together until next + * WAIT_FOR_ME + */ + cmds += adreno_wait_reg_eq(cmds, + adreno_getreg(adreno_dev, + ADRENO_REG_CP_WFI_PEND_CTR), + 1, 0xFFFFFFFF, 0xF); + + /* set the iommu lock bit */ + *cmds++ = cp_type3_packet(CP_REG_RMW, 3); + *cmds++ = mmu_ctrl; + /* AND to unmask the lock bit */ + *cmds++ = + ~(KGSL_IOMMU_IMPLDEF_MICRO_MMU_CTRL_HALT); + /* OR to set the IOMMU lock bit */ + *cmds++ = + KGSL_IOMMU_IMPLDEF_MICRO_MMU_CTRL_HALT; + /* wait for smmu to lock */ + cmds += adreno_wait_reg_eq(cmds, mmu_ctrl, + KGSL_IOMMU_IMPLDEF_MICRO_MMU_CTRL_IDLE, + KGSL_IOMMU_IMPLDEF_MICRO_MMU_CTRL_IDLE, 0xF); + } + /* set ttbr0 */ + if (sizeof(phys_addr_t) > sizeof(unsigned long)) { + reg_pt_val = ttbr0_val & 0xFFFFFFFF; + *cmds++ = cp_type0_packet(ttbr0, 1); + *cmds++ = reg_pt_val; + reg_pt_val = (unsigned int) + ((ttbr0_val & 0xFFFFFFFF00000000ULL) >> 32); + *cmds++ = cp_type0_packet(ttbr0 + 1, 1); + *cmds++ = reg_pt_val; + } else { + reg_pt_val = ttbr0_val; + *cmds++ = cp_type0_packet(ttbr0, 1); + *cmds++ = reg_pt_val; + } + if (kgsl_mmu_hw_halt_supported(&device->mmu, i)) { + /* unlock the IOMMU lock */ + *cmds++ = cp_type3_packet(CP_REG_RMW, 3); + *cmds++ = mmu_ctrl; + /* AND to unmask the lock bit */ + *cmds++ = + ~(KGSL_IOMMU_IMPLDEF_MICRO_MMU_CTRL_HALT); + /* OR with 0 so lock bit is unset */ + *cmds++ = 0; + /* release all commands with wait_for_me */ + *cmds++ = cp_type3_packet(CP_WAIT_FOR_ME, 1); + *cmds++ = 0; + } } + if (flags & KGSL_MMUFLAGS_TLBFLUSH) { + tlbiall = kgsl_mmu_get_reg_ahbaddr(&device->mmu, i, + KGSL_IOMMU_CONTEXT_USER, + KGSL_IOMMU_CTX_TLBIALL) >> 2; + *cmds++ = cp_type0_packet(tlbiall, 1); + *cmds++ = 1; - kgsl_mmu_disable_clk_on_ts(&device->mmu, - adreno_dev->ringbuffer.global_ts, true); + tlbsync = kgsl_mmu_get_reg_ahbaddr(&device->mmu, i, + KGSL_IOMMU_CONTEXT_USER, + KGSL_IOMMU_CTX_TLBSYNC) >> 2; + *cmds++ = cp_type0_packet(tlbsync, 1); + *cmds++ = 0; - if (result) - goto done; + tlbstatus = kgsl_mmu_get_reg_ahbaddr(&device->mmu, i, + KGSL_IOMMU_CONTEXT_USER, + KGSL_IOMMU_CTX_TLBSTATUS) >> 2; + cmds += adreno_wait_reg_eq(cmds, tlbstatus, 0, + KGSL_IOMMU_CTX_TLBSTATUS_SACTIVE, 0xF); + } } + return cmds - cmds_orig; +} + +/** + * adreno_use_default_setstate() - Use CPU instead of the GPU to manage the mmu? + * @adreno_dev: the device + * + * In many cases it is preferable to poke the iommu or gpummu directly rather + * than using the GPU command stream. If we are idle or trying to go to a low + * power state, using the command stream will be slower and asynchronous, which + * needlessly complicates the power state transitions. Additionally, + * the hardware simulators do not support command stream MMU operations so + * the command stream can never be used if we are capturing CFF data. + * + */ +static bool adreno_use_default_setstate(struct adreno_device *adreno_dev) +{ + return (adreno_isidle(&adreno_dev->dev) || + KGSL_STATE_ACTIVE != adreno_dev->dev.state || + atomic_read(&adreno_dev->dev.active_cnt) == 0 || + adreno_dev->dev.cff_dump_enable); +} + +static int adreno_iommu_setstate(struct kgsl_device *device, + unsigned int context_id, + uint32_t flags) +{ + phys_addr_t pt_val; + unsigned int link[230]; + unsigned int *cmds = &link[0]; + int sizedwords = 0; + struct adreno_device *adreno_dev = ADRENO_DEVICE(device); + int num_iommu_units; + struct kgsl_context *context; + struct adreno_context *adreno_ctx = NULL; + struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer; + unsigned int result; + + if (adreno_use_default_setstate(adreno_dev)) { + kgsl_mmu_device_setstate(&device->mmu, flags); + return 0; + } + num_iommu_units = kgsl_mmu_get_num_iommu_units(&device->mmu); + + context = kgsl_context_get(device, context_id); + if (context == NULL) { + kgsl_mmu_device_setstate(&device->mmu, KGSL_CONTEXT_INVALID); + return -EINVAL; + } + + adreno_ctx = ADRENO_CONTEXT(context); + + result = kgsl_mmu_enable_clk(&device->mmu, + KGSL_IOMMU_CONTEXT_USER); + if (result) + goto done; + + pt_val = kgsl_mmu_get_pt_base_addr(&device->mmu, + device->mmu.hwpagetable); + + cmds += __adreno_add_idle_indirect_cmds(cmds, + device->mmu.setstate_memory.gpuaddr + + KGSL_IOMMU_SETSTATE_NOP_OFFSET); + + /* naming mismatch */ + if (msm_soc_version_supports_iommu_v1()) + cmds += _adreno_iommu_setstate_v0(device, cmds, pt_val, + num_iommu_units, flags); + else + cmds += _adreno_iommu_setstate_v1(device, cmds, pt_val, + num_iommu_units, flags); + + sizedwords += (cmds - &link[0]); + if (sizedwords == 0) { + KGSL_DRV_ERR(device, "no commands generated\n"); + BUG(); + } + /* invalidate all base pointers */ + *cmds++ = cp_type3_packet(CP_INVALIDATE_STATE, 1); + *cmds++ = 0x7fff; + sizedwords += 2; if (sizedwords > (sizeof(link)/sizeof(unsigned int))) { KGSL_DRV_ERR(device, "Temp command buffer overflow\n"); BUG(); } + /* + * This returns the per context timestamp but we need to + * use the global timestamp for iommu clock disablement + */ + adreno_ringbuffer_issuecmds(device, adreno_ctx, KGSL_CMD_FLAGS_PMODE, + &link[0], sizedwords); + + kgsl_mmu_disable_clk_on_ts(&device->mmu, + rb->global_ts, true); + done: kgsl_context_put(context); return result; @@ -768,11 +960,10 @@ static int adreno_gpummu_setstate(struct kgsl_device *device, * writes For CFF dump we must idle and use the registers so that it is * easier to filter out the mmu accesses from the dump */ - if (!kgsl_cff_dump_enable && adreno_dev->drawctxt_active) { + if (!adreno_use_default_setstate(adreno_dev)) { context = kgsl_context_get(device, context_id); if (context == NULL) return -EINVAL; - adreno_ctx = ADRENO_CONTEXT(context); if (flags & KGSL_MMUFLAGS_PTUPDATE) { @@ -900,9 +1091,9 @@ a2xx_getchipid(struct kgsl_device *device) if (pdata->chipid != 0) return pdata->chipid; - adreno_regread(device, REG_RBBM_PERIPHID1, &coreid); - adreno_regread(device, REG_RBBM_PERIPHID2, &majorid); - adreno_regread(device, REG_RBBM_PATCH_RELEASE, &revid); + kgsl_regread(device, REG_RBBM_PERIPHID1, &coreid); + kgsl_regread(device, REG_RBBM_PERIPHID2, &majorid); + kgsl_regread(device, REG_RBBM_PATCH_RELEASE, &revid); /* * adreno 22x gpus are indicated by coreid 2, @@ -986,8 +1177,22 @@ adreno_identify_gpu(struct adreno_device *adreno_dev) adreno_dev->pix_shader_start = adreno_gpulist[i].pix_shader_start; adreno_dev->instruction_size = adreno_gpulist[i].instruction_size; adreno_dev->gmem_size = adreno_gpulist[i].gmem_size; + adreno_dev->pm4_jt_idx = adreno_gpulist[i].pm4_jt_idx; + adreno_dev->pm4_jt_addr = adreno_gpulist[i].pm4_jt_addr; + adreno_dev->pfp_jt_idx = adreno_gpulist[i].pfp_jt_idx; + adreno_dev->pfp_jt_addr = adreno_gpulist[i].pfp_jt_addr; adreno_dev->gpulist_index = i; - + /* + * Initialize uninitialzed gpu registers, only needs to be done once + * Make all offsets that are not initialized to ADRENO_REG_UNUSED + */ + for (i = 0; i < ADRENO_REG_REGISTER_MAX; i++) { + if (adreno_dev->gpudev->reg_offsets->offset_0 != i && + !adreno_dev->gpudev->reg_offsets->offsets[i]) { + adreno_dev->gpudev->reg_offsets->offsets[i] = + ADRENO_REG_UNUSED; + } + } } static struct platform_device_id adreno_id_table[] = { @@ -1074,6 +1279,10 @@ static int adreno_of_get_pwrlevels(struct device_node *parent, &pdata->init_level)) pdata->init_level = 1; + if (adreno_of_read_property(parent, "qcom,step-pwrlevel", + &pdata->step_mul)) + pdata->step_mul = 1; + if (pdata->init_level < 0 || pdata->init_level > pdata->num_levels) { KGSL_CORE_ERR("Initial power level out of range\n"); pdata->init_level = 1; @@ -1085,172 +1294,6 @@ static int adreno_of_get_pwrlevels(struct device_node *parent, } -static struct msm_dcvs_core_info *adreno_of_get_dcvs(struct device_node *parent) -{ - struct device_node *node, *child; - struct msm_dcvs_core_info *info = NULL; - int count = 0; - int ret = -EINVAL; - - node = adreno_of_find_subnode(parent, "qcom,dcvs-core-info"); - if (node == NULL) - return ERR_PTR(-EINVAL); - - info = kzalloc(sizeof(*info), GFP_KERNEL); - - if (info == NULL) { - KGSL_CORE_ERR("kzalloc(%d) failed\n", sizeof(*info)); - ret = -ENOMEM; - goto err; - } - - for_each_child_of_node(node, child) - count++; - - info->power_param.num_freq = count; - - info->freq_tbl = kzalloc(info->power_param.num_freq * - sizeof(struct msm_dcvs_freq_entry), - GFP_KERNEL); - - if (info->freq_tbl == NULL) { - KGSL_CORE_ERR("kzalloc(%d) failed\n", - info->power_param.num_freq * - sizeof(struct msm_dcvs_freq_entry)); - ret = -ENOMEM; - goto err; - } - - for_each_child_of_node(node, child) { - unsigned int index; - - if (adreno_of_read_property(child, "reg", &index)) - goto err; - - if (index >= info->power_param.num_freq) { - KGSL_CORE_ERR("DCVS freq entry %d is out of range\n", - index); - continue; - } - - if (adreno_of_read_property(child, "qcom,freq", - &info->freq_tbl[index].freq)) - goto err; - - if (adreno_of_read_property(child, "qcom,voltage", - &info->freq_tbl[index].voltage)) - info->freq_tbl[index].voltage = 0; - - if (adreno_of_read_property(child, "qcom,is_trans_level", - &info->freq_tbl[index].is_trans_level)) - info->freq_tbl[index].is_trans_level = 0; - - if (adreno_of_read_property(child, "qcom,active-energy-offset", - &info->freq_tbl[index].active_energy_offset)) - info->freq_tbl[index].active_energy_offset = 0; - - if (adreno_of_read_property(child, "qcom,leakage-energy-offset", - &info->freq_tbl[index].leakage_energy_offset)) - info->freq_tbl[index].leakage_energy_offset = 0; - } - - if (adreno_of_read_property(node, "qcom,num-cores", &info->num_cores)) - goto err; - - info->sensors = kzalloc(info->num_cores * - sizeof(int), - GFP_KERNEL); - - for (count = 0; count < info->num_cores; count++) { - if (adreno_of_read_property(node, "qcom,sensors", - &(info->sensors[count]))) - goto err; - } - - if (adreno_of_read_property(node, "qcom,core-core-type", - &info->core_param.core_type)) - goto err; - - if (adreno_of_read_property(node, "qcom,algo-disable-pc-threshold", - &info->algo_param.disable_pc_threshold)) - goto err; - if (adreno_of_read_property(node, "qcom,algo-em-win-size-min-us", - &info->algo_param.em_win_size_min_us)) - goto err; - if (adreno_of_read_property(node, "qcom,algo-em-win-size-max-us", - &info->algo_param.em_win_size_max_us)) - goto err; - if (adreno_of_read_property(node, "qcom,algo-em-max-util-pct", - &info->algo_param.em_max_util_pct)) - goto err; - if (adreno_of_read_property(node, "qcom,algo-group-id", - &info->algo_param.group_id)) - goto err; - if (adreno_of_read_property(node, "qcom,algo-max-freq-chg-time-us", - &info->algo_param.max_freq_chg_time_us)) - goto err; - if (adreno_of_read_property(node, "qcom,algo-slack-mode-dynamic", - &info->algo_param.slack_mode_dynamic)) - goto err; - if (adreno_of_read_property(node, "qcom,algo-slack-weight-thresh-pct", - &info->algo_param.slack_weight_thresh_pct)) - goto err; - if (adreno_of_read_property(node, "qcom,algo-slack-time-min-us", - &info->algo_param.slack_time_min_us)) - goto err; - if (adreno_of_read_property(node, "qcom,algo-slack-time-max-us", - &info->algo_param.slack_time_max_us)) - goto err; - if (adreno_of_read_property(node, "qcom,algo-ss-win-size-min-us", - &info->algo_param.ss_win_size_min_us)) - goto err; - if (adreno_of_read_property(node, "qcom,algo-ss-win-size-max-us", - &info->algo_param.ss_win_size_max_us)) - goto err; - if (adreno_of_read_property(node, "qcom,algo-ss-util-pct", - &info->algo_param.ss_util_pct)) - goto err; - if (adreno_of_read_property(node, "qcom,algo-ss-no-corr-below-freq", - &info->algo_param.ss_no_corr_below_freq)) - goto err; - - if (adreno_of_read_property(node, "qcom,energy-active-coeff-a", - &info->energy_coeffs.active_coeff_a)) - goto err; - if (adreno_of_read_property(node, "qcom,energy-active-coeff-b", - &info->energy_coeffs.active_coeff_b)) - goto err; - if (adreno_of_read_property(node, "qcom,energy-active-coeff-c", - &info->energy_coeffs.active_coeff_c)) - goto err; - if (adreno_of_read_property(node, "qcom,energy-leakage-coeff-a", - &info->energy_coeffs.leakage_coeff_a)) - goto err; - if (adreno_of_read_property(node, "qcom,energy-leakage-coeff-b", - &info->energy_coeffs.leakage_coeff_b)) - goto err; - if (adreno_of_read_property(node, "qcom,energy-leakage-coeff-c", - &info->energy_coeffs.leakage_coeff_c)) - goto err; - if (adreno_of_read_property(node, "qcom,energy-leakage-coeff-d", - &info->energy_coeffs.leakage_coeff_d)) - goto err; - - if (adreno_of_read_property(node, "qcom,power-current-temp", - &info->power_param.current_temp)) - goto err; - - return info; - -err: - if (info) - kfree(info->freq_tbl); - - kfree(info); - - return ERR_PTR(ret); -} - static int adreno_of_get_iommu(struct device_node *parent, struct kgsl_device_platform_data *pdata) { @@ -1275,6 +1318,8 @@ static int adreno_of_get_iommu(struct device_node *parent, data->physstart = reg_val[0]; data->physend = data->physstart + reg_val[1] - 1; + data->iommu_halt_enable = of_property_read_bool(node, + "qcom,iommu-enable-halt"); data->iommu_ctx_count = 0; @@ -1299,9 +1344,17 @@ static int adreno_of_get_iommu(struct device_node *parent, goto err; } - if (adreno_of_read_property(child, "qcom,iommu-ctx-sids", - &ctxs[ctx_index].ctx_id)) + ret = of_property_read_u32_array(child, "reg", reg_val, 2); + if (ret) { + KGSL_CORE_ERR("Unable to read KGSL IOMMU 'reg'\n"); goto err; + } + if (msm_soc_version_supports_iommu_v1()) + ctxs[ctx_index].ctx_id = (reg_val[0] - + data->physstart) >> KGSL_IOMMU_CTX_SHIFT; + else + ctxs[ctx_index].ctx_id = ((reg_val[0] - + data->physstart) >> KGSL_IOMMU_CTX_SHIFT) - 8; ctx_index++; } @@ -1356,14 +1409,12 @@ static int adreno_of_get_pdata(struct platform_device *pdev) if (ret) goto err; - /* Default value is 83, if not found in DT */ if (adreno_of_read_property(pdev->dev.of_node, "qcom,idle-timeout", &pdata->idle_timeout)) - pdata->idle_timeout = 83; + pdata->idle_timeout = HZ/12; - if (adreno_of_read_property(pdev->dev.of_node, "qcom,nap-allowed", - &pdata->nap_allowed)) - pdata->nap_allowed = 1; + pdata->strtstp_sleepwake = of_property_read_bool(pdev->dev.of_node, + "qcom,strtstp-sleepwake"); if (adreno_of_read_property(pdev->dev.of_node, "qcom,clk-map", &pdata->clk_map)) @@ -1379,12 +1430,8 @@ static int adreno_of_get_pdata(struct platform_device *pdev) pdata->bus_scale_table = msm_bus_cl_get_pdata(pdev); if (IS_ERR_OR_NULL(pdata->bus_scale_table)) { ret = PTR_ERR(pdata->bus_scale_table); - goto err; - } - - pdata->core_info = adreno_of_get_dcvs(pdev->dev.of_node); - if (IS_ERR_OR_NULL(pdata->core_info)) { - ret = PTR_ERR(pdata->core_info); + if (!ret) + ret = -EINVAL; goto err; } @@ -1392,15 +1439,14 @@ static int adreno_of_get_pdata(struct platform_device *pdev) if (ret) goto err; + pdata->coresight_pdata = of_get_coresight_platform_data(&pdev->dev, + pdev->dev.of_node); + pdev->dev.platform_data = pdata; return 0; err: if (pdata) { - if (pdata->core_info) - kfree(pdata->core_info->freq_tbl); - kfree(pdata->core_info); - if (pdata->iommu_data) kfree(pdata->iommu_data->iommu_ctxs); @@ -1416,7 +1462,8 @@ static int adreno_of_get_pdata(struct platform_device *pdev) static int adreno_ocmem_gmem_malloc(struct adreno_device *adreno_dev) { - if (!adreno_is_a330(adreno_dev)) + if (!(adreno_is_a330(adreno_dev) || + adreno_is_a305b(adreno_dev))) return 0; /* OCMEM is only needed once, do not support consective allocation */ @@ -1437,7 +1484,8 @@ adreno_ocmem_gmem_malloc(struct adreno_device *adreno_dev) static void adreno_ocmem_gmem_free(struct adreno_device *adreno_dev) { - if (!adreno_is_a330(adreno_dev)) + if (!(adreno_is_a330(adreno_dev) || + adreno_is_a305b(adreno_dev))) return; if (adreno_dev->ocmem_hdl == NULL) @@ -1463,6 +1511,7 @@ static int __devinit adreno_probe(struct platform_device *pdev) { struct kgsl_device *device; + struct kgsl_device_platform_data *pdata = NULL; struct adreno_device *adreno_dev; int status = -EINVAL; bool is_dt; @@ -1492,11 +1541,16 @@ adreno_probe(struct platform_device *pdev) goto error_close_device; adreno_debugfs_init(device); + adreno_ft_init_sysfs(device); kgsl_pwrscale_init(device); kgsl_pwrscale_attach_policy(device, ADRENO_DEFAULT_PWRSCALE_POLICY); device->flags &= ~KGSL_FLAGS_SOFT_RESET; + pdata = kgsl_device_get_drvdata(device); + + adreno_coresight_init(pdev); + return 0; error_close_device: @@ -1517,21 +1571,35 @@ static int __devexit adreno_remove(struct platform_device *pdev) device = (struct kgsl_device *)pdev->id_entry->driver_data; adreno_dev = ADRENO_DEVICE(device); + adreno_coresight_remove(pdev); + kgsl_pwrscale_detach_policy(device); kgsl_pwrscale_close(device); adreno_dispatcher_close(adreno_dev); adreno_ringbuffer_close(&adreno_dev->ringbuffer); + adreno_perfcounter_close(device); kgsl_device_platform_remove(device); + clear_bit(ADRENO_DEVICE_INITIALIZED, &adreno_dev->priv); + return 0; } static int adreno_init(struct kgsl_device *device) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); + struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer; + int i; + int ret; kgsl_pwrctrl_set_state(device, KGSL_STATE_INIT); + /* + * initialization only needs to be done once initially until + * device is shutdown + */ + if (test_bit(ADRENO_DEVICE_INITIALIZED, &adreno_dev->priv)) + return 0; /* Power up the device */ kgsl_pwrctrl_enable(device); @@ -1557,6 +1625,7 @@ static int adreno_init(struct kgsl_device *device) BUG_ON(1); } + kgsl_pwrctrl_set_state(device, KGSL_STATE_INIT); /* * Check if firmware supports the sync lock PM4 packets needed * for IOMMUv1 @@ -1568,16 +1637,39 @@ static int adreno_init(struct kgsl_device *device) adreno_gpulist[adreno_dev->gpulist_index].sync_lock_pfp_ver)) device->mmu.flags |= KGSL_MMU_FLAGS_IOMMU_SYNC; - /* Assign correct RBBM status register to hang detect regs - */ - ft_detect_regs[0] = adreno_dev->gpudev->reg_rbbm_status; - - adreno_perfcounter_init(device); + rb->global_ts = 0; + + /* Initialize ft detection register offsets */ + ft_detect_regs[0] = adreno_getreg(adreno_dev, + ADRENO_REG_RBBM_STATUS); + ft_detect_regs[1] = adreno_getreg(adreno_dev, + ADRENO_REG_CP_RB_RPTR); + ft_detect_regs[2] = adreno_getreg(adreno_dev, + ADRENO_REG_CP_IB1_BASE); + ft_detect_regs[3] = adreno_getreg(adreno_dev, + ADRENO_REG_CP_IB1_BUFSZ); + ft_detect_regs[4] = adreno_getreg(adreno_dev, + ADRENO_REG_CP_IB2_BASE); + ft_detect_regs[5] = adreno_getreg(adreno_dev, + ADRENO_REG_CP_IB2_BUFSZ); + for (i = 6; i < FT_DETECT_REGS_COUNT; i++) + ft_detect_regs[i] = 0; + + ret = adreno_perfcounter_init(device); /* Power down the device */ kgsl_pwrctrl_disable(device); - return 0; + if (ret) + goto done; + + /* Certain targets need the fixup. You know who you are */ + if (adreno_is_a330v2(adreno_dev)) + adreno_a3xx_pwron_fixup_init(adreno_dev); + + set_bit(ADRENO_DEVICE_INITIALIZED, &adreno_dev->priv); +done: + return ret; } static int adreno_start(struct kgsl_device *device) @@ -1585,14 +1677,25 @@ static int adreno_start(struct kgsl_device *device) int status = -EINVAL; struct adreno_device *adreno_dev = ADRENO_DEVICE(device); unsigned int state = device->state; + unsigned int regulator_left_on = 0; kgsl_cffdump_open(device); kgsl_pwrctrl_set_state(device, KGSL_STATE_INIT); + regulator_left_on = (regulator_is_enabled(device->pwrctrl.gpu_reg) || + (device->pwrctrl.gpu_cx && + regulator_is_enabled(device->pwrctrl.gpu_cx))); + + /* Clear any GPU faults that might have been left over */ + adreno_set_gpu_fault(adreno_dev, 0); + /* Power up the device */ kgsl_pwrctrl_enable(device); + /* Set the bit to indicate that we've just powered on */ + set_bit(ADRENO_DEVICE_PWRON, &adreno_dev->priv); + /* Set up a2xx special case */ if (adreno_is_a2xx(adreno_dev)) { /* @@ -1617,6 +1720,14 @@ static int adreno_start(struct kgsl_device *device) goto error_mmu_off; } + if (regulator_left_on && adreno_dev->gpudev->soft_reset) { + /* + * Reset the GPU for A3xx. A2xx does a soft reset in + * the start function. + */ + adreno_dev->gpudev->soft_reset(adreno_dev); + } + /* Start the GPU */ adreno_dev->gpudev->start(adreno_dev); @@ -1627,15 +1738,19 @@ static int adreno_start(struct kgsl_device *device) if (status) goto error_irq_off; + status = adreno_perfcounter_start(adreno_dev); + if (status) + goto error_rb_stop; + /* Start the dispatcher */ adreno_dispatcher_start(adreno_dev); - adreno_perfcounter_start(adreno_dev); - device->reset_counter++; return 0; +error_rb_stop: + adreno_ringbuffer_stop(&adreno_dev->ringbuffer); error_irq_off: kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF); @@ -1643,11 +1758,9 @@ static int adreno_start(struct kgsl_device *device) kgsl_mmu_stop(&device->mmu); error_clk_off: - if (KGSL_STATE_DUMP_AND_FT != device->state) { - kgsl_pwrctrl_disable(device); - /* set the state back to original state */ - kgsl_pwrctrl_set_state(device, state); - } + kgsl_pwrctrl_disable(device); + /* set the state back to original state */ + kgsl_pwrctrl_set_state(device, state); return status; } @@ -1675,7 +1788,7 @@ static int adreno_stop(struct kgsl_device *device) /* Power down the device */ kgsl_pwrctrl_disable(device); - kgsl_cffdump_close(device->id); + kgsl_cffdump_close(device); return 0; } @@ -1688,31 +1801,308 @@ static int adreno_stop(struct kgsl_device *device) */ int adreno_reset(struct kgsl_device *device) { - int ret; + int ret = -EINVAL; + struct kgsl_mmu *mmu = &device->mmu; + int i = 0; + + /* Try soft reset first, for non mmu fault case only */ + if (!atomic_read(&mmu->fault)) { + ret = adreno_soft_reset(device); + if (ret) + KGSL_DEV_ERR_ONCE(device, "Device soft reset failed\n"); + } + if (ret) { + /* If soft reset failed/skipped, then pull the power */ + adreno_stop(device); + + /* Keep trying to start the device until it works */ + for (i = 0; i < NUM_TIMES_RESET_RETRY; i++) { + ret = adreno_start(device); + if (!ret) + break; - ret = adreno_stop(device); + msleep(20); + } + } if (ret) return ret; - ret = adreno_init(device); - if (ret) - return ret; + if (0 != i) + KGSL_DRV_WARN(device, "Device hard reset tried %d tries\n", i); - ret = adreno_start(device); + /* + * If active_cnt is non-zero then the system was active before + * going into a reset - put it back in that state + */ - if (ret == 0) { - /* - * If active_cnt is non-zero then the system was active before - * going into a reset - put it back in that state - */ + if (atomic_read(&device->active_cnt)) + kgsl_pwrctrl_set_state(device, KGSL_STATE_ACTIVE); - if (atomic_read(&device->active_cnt)) - kgsl_pwrctrl_set_state(device, KGSL_STATE_ACTIVE); - } + /* Set the page table back to the default page table */ + kgsl_mmu_setstate(&device->mmu, device->mmu.defaultpagetable, + KGSL_MEMSTORE_GLOBAL); return ret; } +/** + * _ft_sysfs_store() - Common routine to write to FT sysfs files + * @buf: value to write + * @count: size of the value to write + * @sysfs_cfg: KGSL FT sysfs config to write + * + * This is a common routine to write to FT sysfs files. + */ +static int _ft_sysfs_store(const char *buf, size_t count, unsigned int *ptr) +{ + char temp[20]; + unsigned long val; + int rc; + + snprintf(temp, sizeof(temp), "%.*s", + (int)min(count, sizeof(temp) - 1), buf); + rc = kstrtoul(temp, 0, &val); + if (rc) + return rc; + + *ptr = val; + + return count; +} + +/** + * _get_adreno_dev() - Routine to get a pointer to adreno dev + * @dev: device ptr + * @attr: Device attribute + * @buf: value to write + * @count: size of the value to write + */ +struct adreno_device *_get_adreno_dev(struct device *dev) +{ + struct kgsl_device *device = kgsl_device_from_dev(dev); + return device ? ADRENO_DEVICE(device) : NULL; +} + +/** + * _ft_policy_store() - Routine to configure FT policy + * @dev: device ptr + * @attr: Device attribute + * @buf: value to write + * @count: size of the value to write + * + * FT policy can be set to any of the options below. + * KGSL_FT_DISABLE -> BIT(0) Set to disable FT + * KGSL_FT_REPLAY -> BIT(1) Set to enable replay + * KGSL_FT_SKIPIB -> BIT(2) Set to skip IB + * KGSL_FT_SKIPFRAME -> BIT(3) Set to skip frame + * by default set FT policy to KGSL_FT_DEFAULT_POLICY + */ +static int _ft_policy_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct adreno_device *adreno_dev = _get_adreno_dev(dev); + int ret; + if (adreno_dev == NULL) + return 0; + + mutex_lock(&adreno_dev->dev.mutex); + ret = _ft_sysfs_store(buf, count, &adreno_dev->ft_policy); + mutex_unlock(&adreno_dev->dev.mutex); + + return ret; +} + +/** + * _ft_policy_show() - Routine to read FT policy + * @dev: device ptr + * @attr: Device attribute + * @buf: value read + * + * This is a routine to read current FT policy + */ +static int _ft_policy_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct adreno_device *adreno_dev = _get_adreno_dev(dev); + if (adreno_dev == NULL) + return 0; + return snprintf(buf, PAGE_SIZE, "0x%X\n", adreno_dev->ft_policy); +} + +/** + * _ft_pagefault_policy_store() - Routine to configure FT + * pagefault policy + * @dev: device ptr + * @attr: Device attribute + * @buf: value to write + * @count: size of the value to write + * + * FT pagefault policy can be set to any of the options below. + * KGSL_FT_PAGEFAULT_INT_ENABLE -> BIT(0) set to enable pagefault INT + * KGSL_FT_PAGEFAULT_GPUHALT_ENABLE -> BIT(1) Set to enable GPU HALT on + * pagefaults. This stalls the GPU on a pagefault on IOMMU v1 HW. + * KGSL_FT_PAGEFAULT_LOG_ONE_PER_PAGE -> BIT(2) Set to log only one + * pagefault per page. + * KGSL_FT_PAGEFAULT_LOG_ONE_PER_INT -> BIT(3) Set to log only one + * pagefault per INT. + */ +static int _ft_pagefault_policy_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct adreno_device *adreno_dev = _get_adreno_dev(dev); + int ret; + if (adreno_dev == NULL) + return 0; + + mutex_lock(&adreno_dev->dev.mutex); + ret = _ft_sysfs_store(buf, count, &adreno_dev->ft_pf_policy); + mutex_unlock(&adreno_dev->dev.mutex); + + return ret; +} + +/** + * _ft_pagefault_policy_show() - Routine to read FT pagefault + * policy + * @dev: device ptr + * @attr: Device attribute + * @buf: value read + * + * This is a routine to read current FT pagefault policy + */ +static int _ft_pagefault_policy_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct adreno_device *adreno_dev = _get_adreno_dev(dev); + if (adreno_dev == NULL) + return 0; + return snprintf(buf, PAGE_SIZE, "0x%X\n", adreno_dev->ft_pf_policy); +} + +/** + * _ft_fast_hang_detect_store() - Routine to configure FT fast + * hang detect policy + * @dev: device ptr + * @attr: Device attribute + * @buf: value to write + * @count: size of the value to write + * + * 0x1 - Enable fast hang detection + * 0x0 - Disable fast hang detection + */ +static int _ft_fast_hang_detect_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct adreno_device *adreno_dev = _get_adreno_dev(dev); + int ret; + if (adreno_dev == NULL) + return 0; + + mutex_lock(&adreno_dev->dev.mutex); + ret = _ft_sysfs_store(buf, count, &adreno_dev->fast_hang_detect); + mutex_unlock(&adreno_dev->dev.mutex); + + return ret; + +} + +/** + * _ft_fast_hang_detect_show() - Routine to read FT fast + * hang detect policy + * @dev: device ptr + * @attr: Device attribute + * @buf: value read + */ +static int _ft_fast_hang_detect_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct adreno_device *adreno_dev = _get_adreno_dev(dev); + if (adreno_dev == NULL) + return 0; + return snprintf(buf, PAGE_SIZE, "%d\n", + (adreno_dev->fast_hang_detect ? 1 : 0)); +} + +/** + * _ft_long_ib_detect_store() - Routine to configure FT long IB + * detect policy + * @dev: device ptr + * @attr: Device attribute + * @buf: value to write + * @count: size of the value to write + * + * 0x0 - Enable long IB detection + * 0x1 - Disable long IB detection + */ +static int _ft_long_ib_detect_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct adreno_device *adreno_dev = _get_adreno_dev(dev); + int ret; + if (adreno_dev == NULL) + return 0; + + mutex_lock(&adreno_dev->dev.mutex); + ret = _ft_sysfs_store(buf, count, &adreno_dev->long_ib_detect); + mutex_unlock(&adreno_dev->dev.mutex); + + return ret; + +} + +/** + * _ft_long_ib_detect_show() - Routine to read FT long IB + * detect policy + * @dev: device ptr + * @attr: Device attribute + * @buf: value read + */ +static int _ft_long_ib_detect_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct adreno_device *adreno_dev = _get_adreno_dev(dev); + if (adreno_dev == NULL) + return 0; + return snprintf(buf, PAGE_SIZE, "%d\n", + (adreno_dev->long_ib_detect ? 1 : 0)); +} + + +#define FT_DEVICE_ATTR(name) \ + DEVICE_ATTR(name, 0644, _ ## name ## _show, _ ## name ## _store); + +FT_DEVICE_ATTR(ft_policy); +FT_DEVICE_ATTR(ft_pagefault_policy); +FT_DEVICE_ATTR(ft_fast_hang_detect); +FT_DEVICE_ATTR(ft_long_ib_detect); + + +const struct device_attribute *ft_attr_list[] = { + &dev_attr_ft_policy, + &dev_attr_ft_pagefault_policy, + &dev_attr_ft_fast_hang_detect, + &dev_attr_ft_long_ib_detect, + NULL, +}; + +int adreno_ft_init_sysfs(struct kgsl_device *device) +{ + return kgsl_create_device_sysfs_files(device->dev, ft_attr_list); +} + +void adreno_ft_uninit_sysfs(struct kgsl_device *device) +{ + kgsl_remove_device_sysfs_files(device->dev, ft_attr_list); +} + static int adreno_getproperty(struct kgsl_device *device, enum kgsl_property_type type, void *value, @@ -1822,8 +2212,6 @@ static int adreno_setproperty(struct kgsl_device *device, switch (type) { case KGSL_PROP_PWRCTRL: { unsigned int enable; - struct kgsl_device_platform_data *pdata = - kgsl_device_get_drvdata(device); if (sizebytes != sizeof(enable)) break; @@ -1835,12 +2223,11 @@ static int adreno_setproperty(struct kgsl_device *device, } if (enable) { - if (pdata->nap_allowed) - device->pwrctrl.nap_allowed = true; adreno_dev->fast_hang_detect = 1; kgsl_pwrscale_enable(device); } else { - device->pwrctrl.nap_allowed = false; + kgsl_pwrctrl_wake(device); + device->pwrctrl.ctrl_flags = KGSL_PWR_ON; adreno_dev->fast_hang_detect = 0; kgsl_pwrscale_disable(device); } @@ -1872,23 +2259,84 @@ static bool adreno_hw_isidle(struct kgsl_device *device) return false; /* Read the correct RBBM status for the GPU type */ - adreno_regread(device, - adreno_dev->gpudev->reg_rbbm_status, + adreno_readreg(adreno_dev, ADRENO_REG_RBBM_STATUS, ®_rbbm_status); if (adreno_is_a2xx(adreno_dev)) { if (reg_rbbm_status == 0x110) return true; - } else if (adreno_is_a3xx(adreno_dev)) { + } else if (adreno_is_a3xx(adreno_dev) || adreno_is_a4xx(adreno_dev)) { if (!(reg_rbbm_status & 0x80000000)) return true; - } else { - BUG(); } return false; } +/** + * adreno_soft_reset() - Do a soft reset of the GPU hardware + * @device: KGSL device to soft reset + * + * "soft reset" the GPU hardware - this is a fast path GPU reset + * The GPU hardware is reset but we never pull power so we can skip + * a lot of the standard adreno_stop/adreno_start sequence + */ +int adreno_soft_reset(struct kgsl_device *device) +{ + struct adreno_device *adreno_dev = ADRENO_DEVICE(device); + int ret; + + if (!adreno_dev->gpudev->soft_reset) { + dev_WARN_ONCE(device->dev, 1, "Soft reset not supported"); + return -EINVAL; + } + + adreno_dev->drawctxt_active = NULL; + + /* Stop the ringbuffer */ + adreno_ringbuffer_stop(&adreno_dev->ringbuffer); + + if (kgsl_pwrctrl_isenabled(device)) + device->ftbl->irqctrl(device, 0); + + kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF); + + adreno_set_gpu_fault(adreno_dev, 0); + + /* Delete the idle timer */ + del_timer_sync(&device->idle_timer); + + /* Make sure we are totally awake */ + kgsl_pwrctrl_enable(device); + + /* Reset the GPU */ + adreno_dev->gpudev->soft_reset(adreno_dev); + + /* Reinitialize the GPU */ + adreno_dev->gpudev->start(adreno_dev); + + /* Enable IRQ */ + kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_ON); + device->ftbl->irqctrl(device, 1); + + /* + * If we have offsets for the jump tables we can try to do a warm start, + * otherwise do a full ringbuffer restart + */ + + if (adreno_dev->pm4_jt_idx) + ret = adreno_ringbuffer_warm_start(&adreno_dev->ringbuffer); + else + ret = adreno_ringbuffer_start(&adreno_dev->ringbuffer); + + if (ret) + return ret; + + device->reset_counter++; + + return 0; +} + /** * adreno_isidle() - return true if the GPU hardware is idle * @device: Pointer to the KGSL device structure for the GPU @@ -1896,18 +2344,18 @@ static bool adreno_hw_isidle(struct kgsl_device *device) * Return true if the GPU hardware is idle and there are no commands pending in * the ringbuffer */ -static bool adreno_isidle(struct kgsl_device *device) +bool adreno_isidle(struct kgsl_device *device) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); - struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer; + unsigned int rptr; /* If the device isn't active, don't force it on. */ if (device->state != KGSL_STATE_ACTIVE) return true; - GSL_RB_GET_READPTR(rb, &rb->rptr); + rptr = adreno_get_rptr(&adreno_dev->ringbuffer); - if (rb->rptr == rb->wptr) + if (rptr == adreno_dev->ringbuffer.wptr) return adreno_hw_isidle(device); return false; @@ -1932,21 +2380,30 @@ int adreno_idle(struct kgsl_device *device) BUG_ON(!mutex_is_locked(&device->mutex)); - if (adreno_is_a2xx(adreno_dev)) + if (adreno_is_a3xx(adreno_dev) || adreno_is_a4xx(adreno_dev)) kgsl_cffdump_regpoll(device, - adreno_dev->gpudev->reg_rbbm_status << 2, 0x110, 0x110); + adreno_getreg(adreno_dev, ADRENO_REG_RBBM_STATUS) << 2, + 0x00000000, 0x80000000); else kgsl_cffdump_regpoll(device, - adreno_dev->gpudev->reg_rbbm_status << 2, 0, - 0x80000000); + adreno_getreg(adreno_dev, ADRENO_REG_RBBM_STATUS) << 2, + 0x110, 0x110); while (time_before(jiffies, wait)) { + /* + * If we fault, stop waiting and return an error. The dispatcher + * will clean up the fault from the work queue, but we need to + * make sure we don't block it by waiting for an idle that + * will never come. + */ + + if (adreno_gpu_fault(adreno_dev) != 0) + return -EDEADLK; + if (adreno_isidle(device)) return 0; } - kgsl_postmortem_dump(device, 0); - return -ETIMEDOUT; } @@ -1983,7 +2440,7 @@ static int adreno_suspend_context(struct kgsl_device *device) /* Find a memory structure attached to an adreno context */ struct kgsl_memdesc *adreno_find_ctxtmem(struct kgsl_device *device, - unsigned int pt_base, unsigned int gpuaddr, unsigned int size) + phys_addr_t pt_base, unsigned int gpuaddr, unsigned int size) { struct kgsl_context *context; int next = 0; @@ -1995,7 +2452,8 @@ struct kgsl_memdesc *adreno_find_ctxtmem(struct kgsl_device *device, if (context == NULL) break; - if (kgsl_mmu_pt_equal(&device->mmu, context->pagetable, + if (kgsl_mmu_pt_equal(&device->mmu, + context->proc_priv->pagetable, pt_base)) { struct adreno_context *adreno_context; @@ -2015,15 +2473,30 @@ struct kgsl_memdesc *adreno_find_ctxtmem(struct kgsl_device *device, return desc; } +/* + * adreno_find_region() - Find corresponding allocation for a given address + * @device: Device on which address operates + * @pt_base: The pagetable in which address is mapped + * @gpuaddr: The gpu address + * @size: Size in bytes of the address + * @entry: If the allocation is part of user space allocation then the mem + * entry is returned in this parameter. Caller is supposed to decrement + * refcount on this entry after its done using it. + * + * Finds an allocation descriptor for a given gpu address range + * + * Returns the descriptor on success else NULL + */ struct kgsl_memdesc *adreno_find_region(struct kgsl_device *device, - unsigned int pt_base, + phys_addr_t pt_base, unsigned int gpuaddr, - unsigned int size) + unsigned int size, + struct kgsl_mem_entry **entry) { - struct kgsl_mem_entry *entry; struct adreno_device *adreno_dev = ADRENO_DEVICE(device); struct adreno_ringbuffer *ringbuffer = &adreno_dev->ringbuffer; + *entry = NULL; if (kgsl_gpuaddr_in_memdesc(&ringbuffer->buffer_desc, gpuaddr, size)) return &ringbuffer->buffer_desc; @@ -2033,34 +2506,62 @@ struct kgsl_memdesc *adreno_find_region(struct kgsl_device *device, if (kgsl_gpuaddr_in_memdesc(&device->memstore, gpuaddr, size)) return &device->memstore; + if (kgsl_gpuaddr_in_memdesc(&adreno_dev->pwron_fixup, gpuaddr, size)) + return &adreno_dev->pwron_fixup; + if (kgsl_gpuaddr_in_memdesc(&device->mmu.setstate_memory, gpuaddr, size)) return &device->mmu.setstate_memory; - entry = kgsl_get_mem_entry(device, pt_base, gpuaddr, size); + *entry = kgsl_get_mem_entry(device, pt_base, gpuaddr, size); - if (entry) - return &entry->memdesc; + if (*entry) + return &((*entry)->memdesc); return adreno_find_ctxtmem(device, pt_base, gpuaddr, size); } -uint8_t *adreno_convertaddr(struct kgsl_device *device, unsigned int pt_base, - unsigned int gpuaddr, unsigned int size) +/* + * adreno_convertaddr() - Convert a gpu address to kernel mapped address + * @device: Device on which the address operates + * @pt_base: The pagetable in which address is mapped + * @gpuaddr: The start address + * @size: The length of address range + * @entry: If the allocation is part of user space allocation then the mem + * entry is returned in this parameter. Caller is supposed to decrement + * refcount on this entry after its done using it. + * + * Returns the converted host pointer on success else NULL + */ +uint8_t *adreno_convertaddr(struct kgsl_device *device, phys_addr_t pt_base, + unsigned int gpuaddr, unsigned int size, + struct kgsl_mem_entry **entry) { struct kgsl_memdesc *memdesc; - memdesc = adreno_find_region(device, pt_base, gpuaddr, size); + memdesc = adreno_find_region(device, pt_base, gpuaddr, size, entry); return memdesc ? kgsl_gpuaddr_to_vaddr(memdesc, gpuaddr) : NULL; } -void adreno_regread(struct kgsl_device *device, unsigned int offsetwords, - unsigned int *value) + +/** + * adreno_read - General read function to read adreno device memory + * @device - Pointer to the GPU device struct (for adreno device) + * @base - Base address (kernel virtual) where the device memory is mapped + * @offsetwords - Offset in words from the base address, of the memory that + * is to be read + * @value - Value read from the device memory + * @mem_len - Length of the device memory mapped to the kernel + */ +static void adreno_read(struct kgsl_device *device, void *base, + unsigned int offsetwords, unsigned int *value, + unsigned int mem_len) { + unsigned int *reg; - BUG_ON(offsetwords*sizeof(uint32_t) >= device->reg_len); - reg = (unsigned int *)(device->reg_virt + (offsetwords << 2)); + BUG_ON(offsetwords*sizeof(uint32_t) >= mem_len); + reg = (unsigned int *)(base + (offsetwords << 2)); if (!in_interrupt()) kgsl_pre_hwaccess(device); @@ -2071,7 +2572,33 @@ void adreno_regread(struct kgsl_device *device, unsigned int offsetwords, rmb(); } -void adreno_regwrite(struct kgsl_device *device, unsigned int offsetwords, +/** + * adreno_regread - Used to read adreno device registers + * @offsetwords - Word (4 Bytes) offset to the register to be read + * @value - Value read from device register + */ +static void adreno_regread(struct kgsl_device *device, unsigned int offsetwords, + unsigned int *value) +{ + adreno_read(device, device->reg_virt, offsetwords, value, + device->reg_len); +} + +/** + * adreno_shadermem_regread - Used to read GPU (adreno) shader memory + * @device - GPU device whose shader memory is to be read + * @offsetwords - Offset in words, of the shader memory address to be read + * @value - Pointer to where the read shader mem value is to be stored + */ +void adreno_shadermem_regread(struct kgsl_device *device, + unsigned int offsetwords, unsigned int *value) +{ + adreno_read(device, device->shader_mem_virt, offsetwords, value, + device->shader_mem_len); +} + +static void adreno_regwrite(struct kgsl_device *device, + unsigned int offsetwords, unsigned int value) { unsigned int *reg; @@ -2083,7 +2610,7 @@ void adreno_regwrite(struct kgsl_device *device, unsigned int offsetwords, kgsl_trace_regwrite(device, offsetwords, value); - kgsl_cffdump_regwrite(device->id, offsetwords << 2, value); + kgsl_cffdump_regwrite(device, offsetwords << 2, value); reg = (unsigned int *)(device->reg_virt + (offsetwords << 2)); /*ensure previous writes post before this one, @@ -2113,7 +2640,7 @@ static int adreno_waittimestamp(struct kgsl_device *device, /* If they are doing then complain once */ dev_WARN_ONCE(device->dev, 1, "IOCTL_KGSL_DEVICE_WAITTIMESTAMP is deprecated\n"); - return -EINVAL; + return -ENOTTY; } /* Return -EINVAL if the context has been detached */ @@ -2138,14 +2665,6 @@ static unsigned int adreno_readtimestamp(struct kgsl_device *device, unsigned int timestamp = 0; unsigned int id = context ? context->id : KGSL_MEMSTORE_GLOBAL; - /* - * If the context is detached we are in a race with - * the context being destroyed by userspace so bail. - */ - if (context && kgsl_context_detached(context)) { - KGSL_DRV_WARN(device, "context was detached"); - return timestamp; - } switch (type) { case KGSL_TIMESTAMP_QUEUED: { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); @@ -2208,7 +2727,7 @@ static long adreno_ioctl(struct kgsl_device_private *dev_priv, case IOCTL_KGSL_PERFCOUNTER_PUT: { struct kgsl_perfcounter_put *put = data; result = adreno_perfcounter_put(adreno_dev, put->groupid, - put->countable); + put->countable, PERFCOUNTER_FLAG_NONE); break; } case IOCTL_KGSL_PERFCOUNTER_QUERY: { @@ -2298,6 +2817,13 @@ static unsigned int adreno_gpuid(struct kgsl_device *device, return (0x0003 << 16) | ((int) adreno_dev->gpurev); } +static void adreno_resume(struct kgsl_device *device) +{ + struct adreno_device *adreno_dev = ADRENO_DEVICE(device); + + adreno_dispatcher_resume(adreno_dev); +} + static const struct kgsl_functable adreno_functable = { /* Mandatory functions */ .regread = adreno_regread, @@ -2329,6 +2855,7 @@ static const struct kgsl_functable adreno_functable = { .setproperty = adreno_setproperty, .postmortem_dump = adreno_dump, .drawctxt_sched = adreno_drawctxt_sched, + .resume = adreno_resume, }; static struct platform_driver adreno_platform_driver = { diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h index 25d1fdd3ad3..881e39c9707 100644 --- a/drivers/gpu/msm/adreno.h +++ b/drivers/gpu/msm/adreno.h @@ -37,8 +37,8 @@ #define KGSL_CMD_FLAGS_NONE 0 #define KGSL_CMD_FLAGS_PMODE BIT(0) #define KGSL_CMD_FLAGS_INTERNAL_ISSUE BIT(1) -#define KGSL_CMD_FLAGS_GET_INT BIT(2) -#define KGSL_CMD_FLAGS_WFI BIT(3) +#define KGSL_CMD_FLAGS_WFI BIT(2) +#define KGSL_CMD_FLAGS_PWRON_FIXUP BIT(3) /* Command identifiers */ #define KGSL_CONTEXT_TO_MEM_IDENTIFIER 0x2EADBEEF @@ -48,6 +48,7 @@ #define KGSL_END_OF_IB_IDENTIFIER 0x2ABEDEAD #define KGSL_END_OF_FRAME_IDENTIFIER 0x2E0F2E0F #define KGSL_NOP_IB_IDENTIFIER 0x20F20F20 +#define KGSL_PWRON_FIXUP_IDENTIFIER 0x2AFAFAFA #ifdef CONFIG_MSM_SCM #define ADRENO_DEFAULT_PWRSCALE_POLICY (&kgsl_pwrscale_policy_tz) @@ -77,10 +78,27 @@ enum adreno_gpurev { ADRENO_REV_A220 = 220, ADRENO_REV_A225 = 225, ADRENO_REV_A305 = 305, + ADRENO_REV_A305C = 306, ADRENO_REV_A320 = 320, ADRENO_REV_A330 = 330, + ADRENO_REV_A305B = 335, + ADRENO_REV_A420 = 420, }; +enum coresight_debug_reg { + DEBUG_BUS_CTL, + TRACE_STOP_CNT, + TRACE_START_CNT, + TRACE_PERIOD_CNT, + TRACE_CMD, + TRACE_BUS_CTL, +}; + +#define ADRENO_SOFT_FAULT BIT(0) +#define ADRENO_HARD_FAULT BIT(1) +#define ADRENO_TIMEOUT_FAULT BIT(2) +#define ADRENO_IOMMU_PAGE_FAULT BIT(3) + /* * Maximum size of the dispatcher ringbuffer - the actual inflight size will be * smaller then this but this size will allow for a larger range of inflight @@ -95,7 +113,7 @@ enum adreno_gpurev { * @state: Current state of the dispatcher (active or paused) * @timer: Timer to monitor the progress of the command batches * @inflight: Number of command batch operations pending in the ringbuffer - * @fault: True if a HW fault was detected + * @fault: Non-zero if a fault was detected. * @pending: Priority list of contexts waiting to submit command batches * @plist_lock: Spin lock to protect the pending queue * @cmdqueue: Queue of command batches currently flight @@ -112,7 +130,7 @@ struct adreno_dispatcher { struct timer_list timer; struct timer_list fault_timer; unsigned int inflight; - int fault; + atomic_t fault; struct plist_head pending; spinlock_t plist_lock; struct kgsl_cmdbatch *cmdqueue[ADRENO_DISPATCH_CMDQUEUE_SIZE]; @@ -126,6 +144,7 @@ struct adreno_gpudev; struct adreno_device { struct kgsl_device dev; /* Must be first field in this struct */ + unsigned long priv; unsigned int chip_id; enum adreno_gpurev gpurev; unsigned long gmem_base; @@ -143,6 +162,10 @@ struct adreno_device { unsigned int mharb; struct adreno_gpudev *gpudev; unsigned int wait_timeout; + unsigned int pm4_jt_idx; + unsigned int pm4_jt_addr; + unsigned int pfp_jt_idx; + unsigned int pfp_jt_addr; unsigned int istore_size; unsigned int pix_shader_start; unsigned int instruction_size; @@ -158,6 +181,20 @@ struct adreno_device { unsigned int ocmem_base; unsigned int gpu_cycles; struct adreno_dispatcher dispatcher; + struct kgsl_memdesc pwron_fixup; + unsigned int pwron_fixup_dwords; +}; + +/** + * enum adreno_device_flags - Private flags for the adreno_device + * @ADRENO_DEVICE_PWRON - Set during init after a power collapse + * @ADRENO_DEVICE_PWRON_FIXUP - Set if the target requires the shader fixup + * after power collapse + */ +enum adreno_device_flags { + ADRENO_DEVICE_PWRON = 0, + ADRENO_DEVICE_PWRON_FIXUP = 1, + ADRENO_DEVICE_INITIALIZED = 2, }; #define PERFCOUNTER_FLAG_NONE 0x0 @@ -168,14 +205,19 @@ struct adreno_device { /** * struct adreno_perfcount_register: register state * @countable: countable the register holds - * @refcount: number of users of the register + * @kernelcount: number of user space users of the register + * @usercount: number of kernel users of the register * @offset: register hardware offset + * @load_bit: The bit number in LOAD register which corresponds to this counter + * @select: The countable register offset */ struct adreno_perfcount_register { unsigned int countable; - unsigned int refcount; + unsigned int kernelcount; + unsigned int usercount; unsigned int offset; - unsigned int flags; + int load_bit; + unsigned int select; }; /** @@ -198,14 +240,114 @@ struct adreno_perfcounters { unsigned int group_count; }; +#define ADRENO_PERFCOUNTER_GROUP(core, name) { core##_perfcounters_##name, \ + ARRAY_SIZE(core##_perfcounters_##name) } + +/** + * adreno_regs: List of registers that are used in kgsl driver for all + * 3D devices. Each device type has different offset value for the same + * register, so an array of register offsets are declared for every device + * and are indexed by the enumeration values defined in this enum + */ +enum adreno_regs { + ADRENO_REG_CP_DEBUG, + ADRENO_REG_CP_ME_RAM_WADDR, + ADRENO_REG_CP_ME_RAM_DATA, + ADRENO_REG_CP_PFP_UCODE_DATA, + ADRENO_REG_CP_PFP_UCODE_ADDR, + ADRENO_REG_CP_WFI_PEND_CTR, + ADRENO_REG_CP_RB_BASE, + ADRENO_REG_CP_RB_RPTR_ADDR, + ADRENO_REG_CP_RB_RPTR, + ADRENO_REG_CP_RB_WPTR, + ADRENO_REG_CP_PROTECT_CTRL, + ADRENO_REG_CP_ME_CNTL, + ADRENO_REG_CP_RB_CNTL, + ADRENO_REG_CP_IB1_BASE, + ADRENO_REG_CP_IB1_BUFSZ, + ADRENO_REG_CP_IB2_BASE, + ADRENO_REG_CP_IB2_BUFSZ, + ADRENO_REG_CP_TIMESTAMP, + ADRENO_REG_CP_ME_RAM_RADDR, + ADRENO_REG_SCRATCH_ADDR, + ADRENO_REG_SCRATCH_UMSK, + ADRENO_REG_SCRATCH_REG2, + ADRENO_REG_RBBM_STATUS, + ADRENO_REG_RBBM_PERFCTR_CTL, + ADRENO_REG_RBBM_PERFCTR_LOAD_CMD0, + ADRENO_REG_RBBM_PERFCTR_LOAD_CMD1, + ADRENO_REG_RBBM_PERFCTR_LOAD_CMD2, + ADRENO_REG_RBBM_PERFCTR_PWR_1_LO, + ADRENO_REG_RBBM_INT_0_MASK, + ADRENO_REG_RBBM_INT_0_STATUS, + ADRENO_REG_RBBM_AHB_ERROR_STATUS, + ADRENO_REG_RBBM_PM_OVERRIDE2, + ADRENO_REG_RBBM_AHB_CMD, + ADRENO_REG_RBBM_INT_CLEAR_CMD, + ADRENO_REG_VPC_DEBUG_RAM_SEL, + ADRENO_REG_VPC_DEBUG_RAM_READ, + ADRENO_REG_VSC_PIPE_DATA_ADDRESS_0, + ADRENO_REG_VSC_PIPE_DATA_LENGTH_7, + ADRENO_REG_VSC_SIZE_ADDRESS, + ADRENO_REG_VFD_CONTROL_0, + ADRENO_REG_VFD_FETCH_INSTR_0_0, + ADRENO_REG_VFD_FETCH_INSTR_1_F, + ADRENO_REG_VFD_INDEX_MAX, + ADRENO_REG_SP_VS_PVT_MEM_ADDR_REG, + ADRENO_REG_SP_FS_PVT_MEM_ADDR_REG, + ADRENO_REG_SP_VS_OBJ_START_REG, + ADRENO_REG_SP_FS_OBJ_START_REG, + ADRENO_REG_PA_SC_AA_CONFIG, + ADRENO_REG_SQ_GPR_MANAGEMENT, + ADRENO_REG_SQ_INST_STORE_MANAGMENT, + ADRENO_REG_TC_CNTL_STATUS, + ADRENO_REG_TP0_CHICKEN, + ADRENO_REG_RBBM_RBBM_CTL, + ADRENO_REG_REGISTER_MAX, +}; + +/** + * adreno_reg_offsets: Holds array of register offsets + * @offsets: Offset array of size defined by enum adreno_regs + * @offset_0: This is the index of the register in offset array whose value + * is 0. 0 is a valid register offset and during initialization of the + * offset array we need to know if an offset value is correctly defined to 0 + */ +struct adreno_reg_offsets { + unsigned int *const offsets; + enum adreno_regs offset_0; +}; + +#define ADRENO_REG_UNUSED 0xFFFFFFFF +#define ADRENO_REG_DEFINE(_offset, _reg) [_offset] = _reg + +/* + * struct adreno_vbif_data - Describes vbif register value pair + * @reg: Offset to vbif register + * @val: The value that should be programmed in the register at reg + */ +struct adreno_vbif_data { + unsigned int reg; + unsigned int val; +}; + +/* + * struct adreno_vbif_platform - Holds an array of vbif reg value pairs + * for a particular core + * @devfunc: Pointer to platform/core identification function + * @vbif: Array of reg value pairs for vbif registers + */ +struct adreno_vbif_platform { + int(*devfunc)(struct adreno_device *); + const struct adreno_vbif_data *vbif; +}; + struct adreno_gpudev { /* - * These registers are in a different location on A3XX, so define - * them in the structure and use them as variables. + * These registers are in a different location on different devices, + * so define them in the structure and use them as variables. */ - unsigned int reg_rbbm_status; - unsigned int reg_cp_pfp_ucode_data; - unsigned int reg_cp_pfp_ucode_addr; + const struct adreno_reg_offsets *reg_offsets; /* keeps track of when we need to execute the draw workaround code */ int ctx_switches_since_last_draw; @@ -222,40 +364,59 @@ struct adreno_gpudev { unsigned int (*irq_pending)(struct adreno_device *); void * (*snapshot)(struct adreno_device *, void *, int *, int); int (*rb_init)(struct adreno_device *, struct adreno_ringbuffer *); - void (*perfcounter_init)(struct adreno_device *); + int (*perfcounter_init)(struct adreno_device *); + void (*perfcounter_close)(struct adreno_device *); void (*start)(struct adreno_device *); unsigned int (*busy_cycles)(struct adreno_device *); - void (*perfcounter_enable)(struct adreno_device *, unsigned int group, + int (*perfcounter_enable)(struct adreno_device *, unsigned int group, unsigned int counter, unsigned int countable); uint64_t (*perfcounter_read)(struct adreno_device *adreno_dev, - unsigned int group, unsigned int counter, - unsigned int offset); + unsigned int group, unsigned int counter); + int (*coresight_enable) (struct kgsl_device *device); + void (*coresight_disable) (struct kgsl_device *device); + void (*coresight_config_debug_reg) (struct kgsl_device *device, + int debug_reg, unsigned int val); + void (*postmortem_dump)(struct adreno_device *adreno_dev); + void (*soft_reset)(struct adreno_device *device); }; #define FT_DETECT_REGS_COUNT 12 +struct log_field { + bool show; + const char *display; +}; + /* Fault Tolerance policy flags */ -#define KGSL_FT_OFF BIT(0) -#define KGSL_FT_REPLAY BIT(1) -#define KGSL_FT_SKIPIB BIT(2) -#define KGSL_FT_SKIPFRAME BIT(3) -#define KGSL_FT_DISABLE BIT(4) -#define KGSL_FT_TEMP_DISABLE BIT(5) -#define KGSL_FT_DEFAULT_POLICY (KGSL_FT_REPLAY + KGSL_FT_SKIPIB) +#define KGSL_FT_OFF 0 +#define KGSL_FT_REPLAY 1 +#define KGSL_FT_SKIPIB 2 +#define KGSL_FT_SKIPFRAME 3 +#define KGSL_FT_DISABLE 4 +#define KGSL_FT_TEMP_DISABLE 5 +#define KGSL_FT_DEFAULT_POLICY (BIT(KGSL_FT_REPLAY) + BIT(KGSL_FT_SKIPIB)) /* This internal bit is used to skip the PM dump on replayed command batches */ -#define KGSL_FT_SKIP_PMDUMP BIT(31) +#define KGSL_FT_SKIP_PMDUMP 31 /* Pagefault policy flags */ #define KGSL_FT_PAGEFAULT_INT_ENABLE BIT(0) #define KGSL_FT_PAGEFAULT_GPUHALT_ENABLE BIT(1) #define KGSL_FT_PAGEFAULT_LOG_ONE_PER_PAGE BIT(2) #define KGSL_FT_PAGEFAULT_LOG_ONE_PER_INT BIT(3) -#define KGSL_FT_PAGEFAULT_DEFAULT_POLICY (KGSL_FT_PAGEFAULT_INT_ENABLE + \ - KGSL_FT_PAGEFAULT_GPUHALT_ENABLE) +#define KGSL_FT_PAGEFAULT_DEFAULT_POLICY KGSL_FT_PAGEFAULT_INT_ENABLE + +#define ADRENO_FT_TYPES \ + { BIT(KGSL_FT_OFF), "off" }, \ + { BIT(KGSL_FT_REPLAY), "replay" }, \ + { BIT(KGSL_FT_SKIPIB), "skipib" }, \ + { BIT(KGSL_FT_SKIPFRAME), "skipframe" }, \ + { BIT(KGSL_FT_DISABLE), "disable" }, \ + { BIT(KGSL_FT_TEMP_DISABLE), "temp" } extern struct adreno_gpudev adreno_a2xx_gpudev; extern struct adreno_gpudev adreno_a3xx_gpudev; +extern struct adreno_gpudev adreno_a4xx_gpudev; /* A2XX register sets defined in adreno_a2xx.c */ extern const unsigned int a200_registers[]; @@ -275,29 +436,43 @@ extern const unsigned int a3xx_hlsq_registers_count; extern const unsigned int a330_registers[]; extern const unsigned int a330_registers_count; +/* A4XX register set defined in adreno_a4xx.c */ +extern const unsigned int a4xx_registers[]; +extern const unsigned int a4xx_registers_count; + extern unsigned int ft_detect_regs[]; +int adreno_coresight_enable(struct coresight_device *csdev); +void adreno_coresight_disable(struct coresight_device *csdev); +void adreno_coresight_remove(struct platform_device *pdev); +int adreno_coresight_init(struct platform_device *pdev); int adreno_idle(struct kgsl_device *device); -void adreno_regread(struct kgsl_device *device, unsigned int offsetwords, - unsigned int *value); -void adreno_regwrite(struct kgsl_device *device, unsigned int offsetwords, - unsigned int value); +bool adreno_isidle(struct kgsl_device *device); + +void adreno_shadermem_regread(struct kgsl_device *device, + unsigned int offsetwords, + unsigned int *value); int adreno_dump(struct kgsl_device *device, int manual); +void adreno_dump_fields(struct kgsl_device *device, + const char *start, const struct log_field *lines, + int num); unsigned int adreno_a3xx_rbbm_clock_ctl_default(struct adreno_device *adreno_dev); struct kgsl_memdesc *adreno_find_region(struct kgsl_device *device, - unsigned int pt_base, + phys_addr_t pt_base, unsigned int gpuaddr, - unsigned int size); + unsigned int size, + struct kgsl_mem_entry **entry); uint8_t *adreno_convertaddr(struct kgsl_device *device, - unsigned int pt_base, unsigned int gpuaddr, unsigned int size); + phys_addr_t pt_base, unsigned int gpuaddr, unsigned int size, + struct kgsl_mem_entry **entry); struct kgsl_memdesc *adreno_find_ctxtmem(struct kgsl_device *device, - unsigned int pt_base, unsigned int gpuaddr, unsigned int size); + phys_addr_t pt_base, unsigned int gpuaddr, unsigned int size); void *adreno_snapshot(struct kgsl_device *device, void *snapshot, int *remain, int hang); @@ -310,22 +485,30 @@ int adreno_dispatcher_idle(struct adreno_device *adreno_dev, void adreno_dispatcher_irq_fault(struct kgsl_device *device); void adreno_dispatcher_stop(struct adreno_device *adreno_dev); -int adreno_context_queue_cmd(struct adreno_device *adreno_dev, +int adreno_dispatcher_queue_cmd(struct adreno_device *adreno_dev, struct adreno_context *drawctxt, struct kgsl_cmdbatch *cmdbatch, uint32_t *timestamp); void adreno_dispatcher_schedule(struct kgsl_device *device); void adreno_dispatcher_pause(struct adreno_device *adreno_dev); +void adreno_dispatcher_resume(struct adreno_device *adreno_dev); void adreno_dispatcher_queue_context(struct kgsl_device *device, struct adreno_context *drawctxt); int adreno_reset(struct kgsl_device *device); +int adreno_ft_init_sysfs(struct kgsl_device *device); +void adreno_ft_uninit_sysfs(struct kgsl_device *device); + int adreno_perfcounter_get(struct adreno_device *adreno_dev, unsigned int groupid, unsigned int countable, unsigned int *offset, unsigned int flags); int adreno_perfcounter_put(struct adreno_device *adreno_dev, - unsigned int groupid, unsigned int countable); + unsigned int groupid, unsigned int countable, unsigned int flags); + +int adreno_soft_reset(struct kgsl_device *device); + +int adreno_a3xx_pwron_fixup_init(struct adreno_device *adreno_dev); static inline int adreno_is_a200(struct adreno_device *adreno_dev) { @@ -370,7 +553,7 @@ static inline int adreno_is_a2xx(struct adreno_device *adreno_dev) static inline int adreno_is_a3xx(struct adreno_device *adreno_dev) { - return (adreno_dev->gpurev >= 300); + return ((adreno_dev->gpurev >= 300) && (adreno_dev->gpurev < 400)); } static inline int adreno_is_a305(struct adreno_device *adreno_dev) @@ -378,6 +561,16 @@ static inline int adreno_is_a305(struct adreno_device *adreno_dev) return (adreno_dev->gpurev == ADRENO_REV_A305); } +static inline int adreno_is_a305b(struct adreno_device *adreno_dev) +{ + return (adreno_dev->gpurev == ADRENO_REV_A305B); +} + +static inline int adreno_is_a305c(struct adreno_device *adreno_dev) +{ + return (adreno_dev->gpurev == ADRENO_REV_A305C); +} + static inline int adreno_is_a320(struct adreno_device *adreno_dev) { return (adreno_dev->gpurev == ADRENO_REV_A320); @@ -394,6 +587,17 @@ static inline int adreno_is_a330v2(struct adreno_device *adreno_dev) (ADRENO_CHIPID_PATCH(adreno_dev->chip_id) > 0)); } + +static inline int adreno_is_a4xx(struct adreno_device *adreno_dev) +{ + return (adreno_dev->gpurev >= 400); +} + +static inline int adreno_is_a420(struct adreno_device *adreno_dev) +{ + return (adreno_dev->gpurev == ADRENO_REV_A420); +} + static inline int adreno_rb_ctxtswitch(unsigned int *cmd) { return (cmd[0] == cp_nop_packet(1) && @@ -520,6 +724,7 @@ static inline int adreno_add_idle_cmds(struct adreno_device *adreno_dev, *cmds++ = 0x00000000; if ((adreno_dev->gpurev == ADRENO_REV_A305) || + (adreno_dev->gpurev == ADRENO_REV_A305C) || (adreno_dev->gpurev == ADRENO_REV_A320)) { *cmds++ = cp_type3_packet(CP_WAIT_FOR_ME, 1); *cmds++ = 0x00000000; @@ -528,4 +733,143 @@ static inline int adreno_add_idle_cmds(struct adreno_device *adreno_dev, return cmds - start; } +/* + * adreno_wait_reg_eq() - Add a CP_WAIT_REG_EQ command + * @cmds: Pointer to memory where commands are to be added + * @addr: Regiater address to poll for + * @val: Value to poll for + * @mask: The value against which register value is masked + * @interval: wait interval + */ +static inline int adreno_wait_reg_eq(unsigned int *cmds, unsigned int addr, + unsigned int val, unsigned int mask, + unsigned int interval) +{ + unsigned int *start = cmds; + *cmds++ = cp_type3_packet(CP_WAIT_REG_EQ, 4); + *cmds++ = addr; + *cmds++ = val; + *cmds++ = mask; + *cmds++ = interval; + return cmds - start; +} + +/* + * adreno_checkreg_off() - Checks the validity of a register enum + * @adreno_dev: Pointer to adreno device + * @offset_name: The register enum that is checked + */ +static inline bool adreno_checkreg_off(struct adreno_device *adreno_dev, + enum adreno_regs offset_name) +{ + if (offset_name >= ADRENO_REG_REGISTER_MAX || + ADRENO_REG_UNUSED == + adreno_dev->gpudev->reg_offsets->offsets[offset_name]) { + BUG_ON(1); + } + return true; +} + +/* + * adreno_readreg() - Read a register by getting its offset from the + * offset array defined in gpudev node + * @adreno_dev: Pointer to the the adreno device + * @offset_name: The register enum that is to be read + * @val: Register value read is placed here + */ +static inline void adreno_readreg(struct adreno_device *adreno_dev, + enum adreno_regs offset_name, unsigned int *val) +{ + struct kgsl_device *device = &adreno_dev->dev; + if (adreno_checkreg_off(adreno_dev, offset_name)) + kgsl_regread(device, + adreno_dev->gpudev->reg_offsets->offsets[offset_name], + val); +} + +/* + * adreno_writereg() - Write a register by getting its offset from the + * offset array defined in gpudev node + * @adreno_dev: Pointer to the the adreno device + * @offset_name: The register enum that is to be written + * @val: Value to write + */ +static inline void adreno_writereg(struct adreno_device *adreno_dev, + enum adreno_regs offset_name, unsigned int val) +{ + struct kgsl_device *device = &adreno_dev->dev; + if (adreno_checkreg_off(adreno_dev, offset_name)) + kgsl_regwrite(device, + adreno_dev->gpudev->reg_offsets->offsets[offset_name], val); +} + +/* + * adreno_getreg() - Returns the offset value of a register from the + * register offset array in the gpudev node + * @adreno_dev: Pointer to the the adreno device + * @offset_name: The register enum whore offset is returned + */ +static inline unsigned int adreno_getreg(struct adreno_device *adreno_dev, + enum adreno_regs offset_name) +{ + if (!adreno_checkreg_off(adreno_dev, offset_name)) + return ADRENO_REG_REGISTER_MAX; + return adreno_dev->gpudev->reg_offsets->offsets[offset_name]; +} + +/** + * adreno_gpu_fault() - Return the current state of the GPU + * @adreno_dev: A ponter to the adreno_device to query + * + * Return 0 if there is no fault or positive with the last type of fault that + * occurred + */ +static inline unsigned int adreno_gpu_fault(struct adreno_device *adreno_dev) +{ + smp_rmb(); + return atomic_read(&adreno_dev->dispatcher.fault); +} + +/** + * adreno_set_gpu_fault() - Set the current fault status of the GPU + * @adreno_dev: A pointer to the adreno_device to set + * @state: fault state to set + * + */ +static inline void adreno_set_gpu_fault(struct adreno_device *adreno_dev, + int state) +{ + /* only set the fault bit w/o overwriting other bits */ + atomic_add(state, &adreno_dev->dispatcher.fault); + smp_wmb(); +} + +/* + * adreno_vbif_start() - Program VBIF registers, called in device start + * @device: Pointer to device whose vbif data is to be programmed + * @vbif_platforms: list register value pair of vbif for a family + * of adreno cores + * @num_platforms: Number of platforms contained in vbif_platforms + */ +static inline void adreno_vbif_start(struct kgsl_device *device, + const struct adreno_vbif_platform *vbif_platforms, + int num_platforms) +{ + int i; + const struct adreno_vbif_data *vbif = NULL; + struct adreno_device *adreno_dev = ADRENO_DEVICE(device); + + for (i = 0; i < num_platforms; i++) { + if (vbif_platforms[i].devfunc(adreno_dev)) { + vbif = vbif_platforms[i].vbif; + break; + } + } + BUG_ON(vbif == NULL); + while (vbif->reg != 0) { + kgsl_regwrite(device, vbif->reg, vbif->val); + vbif++; + } +} + #endif /*__ADRENO_H */ diff --git a/drivers/gpu/msm/adreno_a2xx.c b/drivers/gpu/msm/adreno_a2xx.c index 93068c05c86..1f4544fbcdd 100644 --- a/drivers/gpu/msm/adreno_a2xx.c +++ b/drivers/gpu/msm/adreno_a2xx.c @@ -1355,7 +1355,8 @@ static int a2xx_create_gmem_shadow(struct adreno_device *adreno_dev, tmp_ctx.gmem_base = adreno_dev->gmem_base; result = kgsl_allocate(&drawctxt->context_gmem_shadow.gmemshadow, - drawctxt->base.pagetable, drawctxt->context_gmem_shadow.size); + drawctxt->base.proc_priv->pagetable, + drawctxt->context_gmem_shadow.size); if (result) return result; @@ -1364,7 +1365,8 @@ static int a2xx_create_gmem_shadow(struct adreno_device *adreno_dev, drawctxt->flags |= CTXT_FLAGS_GMEM_SHADOW; /* blank out gmem shadow. */ - kgsl_sharedmem_set(&drawctxt->context_gmem_shadow.gmemshadow, 0, 0, + kgsl_sharedmem_set(drawctxt->base.device, + &drawctxt->context_gmem_shadow.gmemshadow, 0, 0, drawctxt->context_gmem_shadow.size); /* build quad vertex buffer */ @@ -1388,7 +1390,7 @@ static int a2xx_create_gmem_shadow(struct adreno_device *adreno_dev, kgsl_cache_range_op(&drawctxt->context_gmem_shadow.gmemshadow, KGSL_CACHE_OP_FLUSH); - kgsl_cffdump_syncmem(NULL, + kgsl_cffdump_syncmem(drawctxt->base.device, &drawctxt->context_gmem_shadow.gmemshadow, drawctxt->context_gmem_shadow.gmemshadow.gpuaddr, drawctxt->context_gmem_shadow.gmemshadow.size, false); @@ -1409,12 +1411,12 @@ static int a2xx_drawctxt_create(struct adreno_device *adreno_dev, */ ret = kgsl_allocate(&drawctxt->gpustate, - drawctxt->base.pagetable, _context_size(adreno_dev)); + drawctxt->base.proc_priv->pagetable, _context_size(adreno_dev)); if (ret) return ret; - kgsl_sharedmem_set(&drawctxt->gpustate, + kgsl_sharedmem_set(drawctxt->base.device, &drawctxt->gpustate, 0, 0, _context_size(adreno_dev)); tmp_ctx.cmd = tmp_ctx.start @@ -1439,7 +1441,7 @@ static int a2xx_drawctxt_create(struct adreno_device *adreno_dev, kgsl_cache_range_op(&drawctxt->gpustate, KGSL_CACHE_OP_FLUSH); - kgsl_cffdump_syncmem(NULL, + kgsl_cffdump_syncmem(drawctxt->base.device, &drawctxt->gpustate, drawctxt->gpustate.gpuaddr, drawctxt->gpustate.size, false); @@ -1515,7 +1517,7 @@ static int a2xx_drawctxt_save(struct adreno_device *adreno_dev, return 0; if (!(context->flags & CTXT_FLAGS_PREAMBLE)) { - kgsl_cffdump_syncmem(NULL, &context->gpustate, + kgsl_cffdump_syncmem(context->base.device, &context->gpustate, context->reg_save[1], context->reg_save[2] << 2, true); /* save registers and constants. */ @@ -1527,7 +1529,7 @@ static int a2xx_drawctxt_save(struct adreno_device *adreno_dev, return ret; if (context->flags & CTXT_FLAGS_SHADER_SAVE) { - kgsl_cffdump_syncmem(NULL, + kgsl_cffdump_syncmem(context->base.device, &context->gpustate, context->shader_save[1], context->shader_save[2] << 2, true); @@ -1536,7 +1538,7 @@ static int a2xx_drawctxt_save(struct adreno_device *adreno_dev, KGSL_CMD_FLAGS_PMODE, context->shader_save, 3); - kgsl_cffdump_syncmem(NULL, + kgsl_cffdump_syncmem(context->base.device, &context->gpustate, context->shader_fixup[1], context->shader_fixup[2] << 2, true); @@ -1557,7 +1559,7 @@ static int a2xx_drawctxt_save(struct adreno_device *adreno_dev, if ((context->flags & CTXT_FLAGS_GMEM_SAVE) && (context->flags & CTXT_FLAGS_GMEM_SHADOW)) { - kgsl_cffdump_syncmem(NULL, &context->gpustate, + kgsl_cffdump_syncmem(context->base.device, &context->gpustate, context->context_gmem_shadow.gmem_save[1], context->context_gmem_shadow.gmem_save[2] << 2, true); /* save gmem. @@ -1569,8 +1571,7 @@ static int a2xx_drawctxt_save(struct adreno_device *adreno_dev, if (ret) return ret; - - kgsl_cffdump_syncmem(NULL, &context->gpustate, + kgsl_cffdump_syncmem(context->base.device, &context->gpustate, context->chicken_restore[1], context->chicken_restore[2] << 2, true); @@ -1626,14 +1627,14 @@ static int a2xx_drawctxt_restore(struct adreno_device *adreno_dev, if (ret) return ret; - kgsl_mmu_setstate(&device->mmu, context->base.pagetable, + kgsl_mmu_setstate(&device->mmu, context->base.proc_priv->pagetable, context->base.id); /* restore gmem. * (note: changes shader. shader must not already be restored.) */ if (context->flags & CTXT_FLAGS_GMEM_RESTORE) { - kgsl_cffdump_syncmem(NULL, &context->gpustate, + kgsl_cffdump_syncmem(context->base.device, &context->gpustate, context->context_gmem_shadow.gmem_restore[1], context->context_gmem_shadow.gmem_restore[2] << 2, true); @@ -1645,7 +1646,8 @@ static int a2xx_drawctxt_restore(struct adreno_device *adreno_dev, return ret; if (!(context->flags & CTXT_FLAGS_PREAMBLE)) { - kgsl_cffdump_syncmem(NULL, &context->gpustate, + kgsl_cffdump_syncmem(context->base.device, + &context->gpustate, context->chicken_restore[1], context->chicken_restore[2] << 2, true); @@ -1661,7 +1663,7 @@ static int a2xx_drawctxt_restore(struct adreno_device *adreno_dev, } if (!(context->flags & CTXT_FLAGS_PREAMBLE)) { - kgsl_cffdump_syncmem(NULL, &context->gpustate, + kgsl_cffdump_syncmem(context->base.device, &context->gpustate, context->reg_restore[1], context->reg_restore[2] << 2, true); @@ -1673,7 +1675,8 @@ static int a2xx_drawctxt_restore(struct adreno_device *adreno_dev, /* restore shader instructions & partitioning. */ if (context->flags & CTXT_FLAGS_SHADER_RESTORE) { - kgsl_cffdump_syncmem(NULL, &context->gpustate, + kgsl_cffdump_syncmem(context->base.device, + &context->gpustate, context->shader_restore[1], context->shader_restore[2] << 2, true); @@ -1742,11 +1745,11 @@ static void a2xx_cp_intrcallback(struct kgsl_device *device) struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer; int i; - adreno_regread(device, REG_MASTER_INT_SIGNAL, &master_status); + kgsl_regread(device, REG_MASTER_INT_SIGNAL, &master_status); while (!status && (num_reads < VALID_STATUS_COUNT_MAX) && (master_status & MASTER_INT_SIGNAL__CP_INT_STAT)) { - adreno_regread(device, REG_CP_INT_STATUS, &status); - adreno_regread(device, REG_MASTER_INT_SIGNAL, + kgsl_regread(device, REG_CP_INT_STATUS, &status); + kgsl_regread(device, REG_MASTER_INT_SIGNAL, &master_status); num_reads++; } @@ -1788,7 +1791,7 @@ static void a2xx_cp_intrcallback(struct kgsl_device *device) /* only ack bits we understand */ status &= CP_INT_MASK; - adreno_regwrite(device, REG_CP_INT_ACK, status); + kgsl_regwrite(device, REG_CP_INT_ACK, status); if (status & (CP_INT_CNTL__IB1_INT_MASK | CP_INT_CNTL__RB_INT_MASK)) { queue_work(device->work_queue, &device->ts_expired_ws); @@ -1803,10 +1806,10 @@ static void a2xx_rbbm_intrcallback(struct kgsl_device *device) unsigned int addr = 0; const char *source; - adreno_regread(device, REG_RBBM_INT_STATUS, &status); + kgsl_regread(device, REG_RBBM_INT_STATUS, &status); if (status & RBBM_INT_CNTL__RDERR_INT_MASK) { - adreno_regread(device, REG_RBBM_READ_ERROR, &rderr); + kgsl_regread(device, REG_RBBM_READ_ERROR, &rderr); source = (rderr & RBBM_READ_ERROR_REQUESTER) ? "host" : "cp"; /* convert to dword address */ @@ -1830,7 +1833,7 @@ static void a2xx_rbbm_intrcallback(struct kgsl_device *device) } status &= RBBM_INT_MASK; - adreno_regwrite(device, REG_RBBM_INT_ACK, status); + kgsl_regwrite(device, REG_RBBM_INT_ACK, status); } irqreturn_t a2xx_irq_handler(struct adreno_device *adreno_dev) @@ -1839,7 +1842,7 @@ irqreturn_t a2xx_irq_handler(struct adreno_device *adreno_dev) irqreturn_t result = IRQ_NONE; unsigned int status; - adreno_regread(device, REG_MASTER_INT_SIGNAL, &status); + kgsl_regread(device, REG_MASTER_INT_SIGNAL, &status); if (status & MASTER_INT_SIGNAL__MH_INT_STAT) { kgsl_mh_intrcallback(device); @@ -1864,14 +1867,14 @@ static void a2xx_irq_control(struct adreno_device *adreno_dev, int state) struct kgsl_device *device = &adreno_dev->dev; if (state) { - adreno_regwrite(device, REG_RBBM_INT_CNTL, RBBM_INT_MASK); - adreno_regwrite(device, REG_CP_INT_CNTL, CP_INT_MASK); - adreno_regwrite(device, MH_INTERRUPT_MASK, + kgsl_regwrite(device, REG_RBBM_INT_CNTL, RBBM_INT_MASK); + kgsl_regwrite(device, REG_CP_INT_CNTL, CP_INT_MASK); + kgsl_regwrite(device, MH_INTERRUPT_MASK, kgsl_mmu_get_int_mask()); } else { - adreno_regwrite(device, REG_RBBM_INT_CNTL, 0); - adreno_regwrite(device, REG_CP_INT_CNTL, 0); - adreno_regwrite(device, MH_INTERRUPT_MASK, 0); + kgsl_regwrite(device, REG_RBBM_INT_CNTL, 0); + kgsl_regwrite(device, REG_CP_INT_CNTL, 0); + kgsl_regwrite(device, MH_INTERRUPT_MASK, 0); } /* Force the writes to post before touching the IRQ line */ @@ -1881,14 +1884,14 @@ static void a2xx_irq_control(struct adreno_device *adreno_dev, int state) static unsigned int a2xx_irq_pending(struct adreno_device *adreno_dev) { struct kgsl_device *device = &adreno_dev->dev; - unsigned int rbbm, cp, mh; + unsigned int status; - adreno_regread(device, REG_RBBM_INT_CNTL, &rbbm); - adreno_regread(device, REG_CP_INT_CNTL, &cp); - adreno_regread(device, MH_INTERRUPT_MASK, &mh); + kgsl_regread(device, REG_MASTER_INT_SIGNAL, &status); - return ((rbbm & RBBM_INT_MASK) || (cp & CP_INT_MASK) || - (mh & kgsl_mmu_get_int_mask())) ? 1 : 0; + return (status & + (MASTER_INT_SIGNAL__MH_INT_STAT | + MASTER_INT_SIGNAL__CP_INT_STAT | + MASTER_INT_SIGNAL__RBBM_INT_STAT)) ? 1 : 0; } static int a2xx_rb_init(struct adreno_device *adreno_dev, @@ -1903,54 +1906,56 @@ static int a2xx_rb_init(struct adreno_device *adreno_dev, cmds_gpu = rb->buffer_desc.gpuaddr + sizeof(uint)*(rb->wptr-19); - GSL_RB_WRITE(cmds, cmds_gpu, cp_type3_packet(CP_ME_INIT, 18)); + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, cp_type3_packet(CP_ME_INIT, + 18)); /* All fields present (bits 9:0) */ - GSL_RB_WRITE(cmds, cmds_gpu, 0x000003ff); + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x000003ff); /* Disable/Enable Real-Time Stream processing (present but ignored) */ - GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000); + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000000); /* Enable (2D <-> 3D) implicit synchronization (present but ignored) */ - GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000); + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000000); - GSL_RB_WRITE(cmds, cmds_gpu, + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, SUBBLOCK_OFFSET(REG_RB_SURFACE_INFO)); - GSL_RB_WRITE(cmds, cmds_gpu, + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, SUBBLOCK_OFFSET(REG_PA_SC_WINDOW_OFFSET)); - GSL_RB_WRITE(cmds, cmds_gpu, + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, SUBBLOCK_OFFSET(REG_VGT_MAX_VTX_INDX)); - GSL_RB_WRITE(cmds, cmds_gpu, + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, SUBBLOCK_OFFSET(REG_SQ_PROGRAM_CNTL)); - GSL_RB_WRITE(cmds, cmds_gpu, + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, SUBBLOCK_OFFSET(REG_RB_DEPTHCONTROL)); - GSL_RB_WRITE(cmds, cmds_gpu, + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, SUBBLOCK_OFFSET(REG_PA_SU_POINT_SIZE)); - GSL_RB_WRITE(cmds, cmds_gpu, + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, SUBBLOCK_OFFSET(REG_PA_SC_LINE_CNTL)); - GSL_RB_WRITE(cmds, cmds_gpu, + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, SUBBLOCK_OFFSET(REG_PA_SU_POLY_OFFSET_FRONT_SCALE)); /* Instruction memory size: */ - GSL_RB_WRITE(cmds, cmds_gpu, + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, (adreno_encode_istore_size(adreno_dev) | adreno_dev->pix_shader_start)); /* Maximum Contexts */ - GSL_RB_WRITE(cmds, cmds_gpu, 0x00000001); + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000001); /* Write Confirm Interval and The CP will wait the * wait_interval * 16 clocks between polling */ - GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000); + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000000); /* NQ and External Memory Swap */ - GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000); + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000000); /* Protected mode error checking * If iommu is used then protection needs to be turned off * to enable context bank switching */ if (KGSL_MMU_TYPE_IOMMU == kgsl_mmu_get_mmutype()) - GSL_RB_WRITE(cmds, cmds_gpu, 0); + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0); else - GSL_RB_WRITE(cmds, cmds_gpu, GSL_RB_PROTECTED_MODE_CONTROL); + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, + GSL_RB_PROTECTED_MODE_CONTROL); /* Disable header dumping and Header dump address */ - GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000); + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000000); /* Header dump size */ - GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000); + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000000); adreno_ringbuffer_submit(rb); @@ -1963,21 +1968,21 @@ static unsigned int a2xx_busy_cycles(struct adreno_device *adreno_dev) unsigned int reg, val; /* Freeze the counter */ - adreno_regwrite(device, REG_CP_PERFMON_CNTL, + kgsl_regwrite(device, REG_CP_PERFMON_CNTL, REG_PERF_MODE_CNT | REG_PERF_STATE_FREEZE); /* Get the value */ - adreno_regread(device, REG_RBBM_PERFCOUNTER1_LO, &val); + kgsl_regread(device, REG_RBBM_PERFCOUNTER1_LO, &val); /* Reset the counter */ - adreno_regwrite(device, REG_CP_PERFMON_CNTL, + kgsl_regwrite(device, REG_CP_PERFMON_CNTL, REG_PERF_MODE_CNT | REG_PERF_STATE_RESET); /* Re-Enable the performance monitors */ - adreno_regread(device, REG_RBBM_PM_OVERRIDE2, ®); - adreno_regwrite(device, REG_RBBM_PM_OVERRIDE2, (reg | 0x40)); - adreno_regwrite(device, REG_RBBM_PERFCOUNTER1_SELECT, 0x1); - adreno_regwrite(device, REG_CP_PERFMON_CNTL, + kgsl_regread(device, REG_RBBM_PM_OVERRIDE2, ®); + kgsl_regwrite(device, REG_RBBM_PM_OVERRIDE2, (reg | 0x40)); + kgsl_regwrite(device, REG_RBBM_PERFCOUNTER1_SELECT, 0x1); + kgsl_regwrite(device, REG_CP_PERFMON_CNTL, REG_PERF_MODE_CNT | REG_PERF_STATE_ENABLE); return val; @@ -2003,7 +2008,7 @@ static void a2xx_gmeminit(struct adreno_device *adreno_dev) /* must be aligned to size */ rb_edram_info.f.edram_range = (adreno_dev->gmem_base >> 14); - adreno_regwrite(device, REG_RB_EDRAM_INFO, rb_edram_info.val); + kgsl_regwrite(device, REG_RB_EDRAM_INFO, rb_edram_info.val); } static void a2xx_start(struct adreno_device *adreno_dev) @@ -2015,8 +2020,8 @@ static void a2xx_start(struct adreno_device *adreno_dev) * before issuing a soft reset. The overrides will then be * turned off (set to 0) */ - adreno_regwrite(device, REG_RBBM_PM_OVERRIDE1, 0xfffffffe); - adreno_regwrite(device, REG_RBBM_PM_OVERRIDE2, 0xffffffff); + kgsl_regwrite(device, REG_RBBM_PM_OVERRIDE1, 0xfffffffe); + kgsl_regwrite(device, REG_RBBM_PM_OVERRIDE2, 0xffffffff); /* * Only reset CP block if all blocks have previously been @@ -2024,11 +2029,11 @@ static void a2xx_start(struct adreno_device *adreno_dev) */ if (!(device->flags & KGSL_FLAGS_SOFT_RESET) || !adreno_is_a22x(adreno_dev)) { - adreno_regwrite(device, REG_RBBM_SOFT_RESET, + kgsl_regwrite(device, REG_RBBM_SOFT_RESET, 0xFFFFFFFF); device->flags |= KGSL_FLAGS_SOFT_RESET; } else { - adreno_regwrite(device, REG_RBBM_SOFT_RESET, + kgsl_regwrite(device, REG_RBBM_SOFT_RESET, 0x00000001); } /* @@ -2037,11 +2042,11 @@ static void a2xx_start(struct adreno_device *adreno_dev) */ msleep(30); - adreno_regwrite(device, REG_RBBM_SOFT_RESET, 0x00000000); + kgsl_regwrite(device, REG_RBBM_SOFT_RESET, 0x00000000); if (adreno_is_a225(adreno_dev)) { /* Enable large instruction store for A225 */ - adreno_regwrite(device, REG_SQ_FLOW_CONTROL, + kgsl_regwrite(device, REG_SQ_FLOW_CONTROL, 0x18000000); } @@ -2049,41 +2054,243 @@ static void a2xx_start(struct adreno_device *adreno_dev) /* For A20X based targets increase number of clocks * that RBBM will wait before de-asserting Register * Clock Active signal */ - adreno_regwrite(device, REG_RBBM_CNTL, 0x0000FFFF); + kgsl_regwrite(device, REG_RBBM_CNTL, 0x0000FFFF); else - adreno_regwrite(device, REG_RBBM_CNTL, 0x00004442); + kgsl_regwrite(device, REG_RBBM_CNTL, 0x00004442); - adreno_regwrite(device, REG_SQ_VS_PROGRAM, 0x00000000); - adreno_regwrite(device, REG_SQ_PS_PROGRAM, 0x00000000); + kgsl_regwrite(device, REG_SQ_VS_PROGRAM, 0x00000000); + kgsl_regwrite(device, REG_SQ_PS_PROGRAM, 0x00000000); if (cpu_is_msm8960()) - adreno_regwrite(device, REG_RBBM_PM_OVERRIDE1, 0x200); + kgsl_regwrite(device, REG_RBBM_PM_OVERRIDE1, 0x200); else - adreno_regwrite(device, REG_RBBM_PM_OVERRIDE1, 0); + kgsl_regwrite(device, REG_RBBM_PM_OVERRIDE1, 0); if (!adreno_is_a22x(adreno_dev)) - adreno_regwrite(device, REG_RBBM_PM_OVERRIDE2, 0); + kgsl_regwrite(device, REG_RBBM_PM_OVERRIDE2, 0); else - adreno_regwrite(device, REG_RBBM_PM_OVERRIDE2, 0x80); + kgsl_regwrite(device, REG_RBBM_PM_OVERRIDE2, 0x80); - adreno_regwrite(device, REG_RBBM_DEBUG, 0x00080000); + kgsl_regwrite(device, REG_RBBM_DEBUG, 0x00080000); /* Make sure interrupts are disabled */ - adreno_regwrite(device, REG_RBBM_INT_CNTL, 0); - adreno_regwrite(device, REG_CP_INT_CNTL, 0); - adreno_regwrite(device, REG_SQ_INT_CNTL, 0); + kgsl_regwrite(device, REG_RBBM_INT_CNTL, 0); + kgsl_regwrite(device, REG_CP_INT_CNTL, 0); + kgsl_regwrite(device, REG_SQ_INT_CNTL, 0); a2xx_gmeminit(adreno_dev); } +static void a2xx_postmortem_dump(struct adreno_device *adreno_dev) +{ + unsigned int r1, r2, r3, rbbm_status; + unsigned int cp_stat, rb_count; + struct kgsl_device *device = &adreno_dev->dev; + + kgsl_regread(device, REG_RBBM_STATUS, &rbbm_status); + + kgsl_regread(device, REG_RBBM_PM_OVERRIDE1, &r2); + kgsl_regread(device, REG_RBBM_PM_OVERRIDE2, &r3); + KGSL_LOG_DUMP(device, + "RBBM: STATUS = %08X | PM_OVERRIDE1 = %08X | PM_OVERRIDE2 = %08X\n", + rbbm_status, r2, r3); + + kgsl_regread(device, REG_RBBM_INT_CNTL, &r1); + kgsl_regread(device, REG_RBBM_INT_STATUS, &r2); + kgsl_regread(device, REG_RBBM_READ_ERROR, &r3); + KGSL_LOG_DUMP(device, + "INT_CNTL = %08X | INT_STATUS = %08X | READ_ERROR = %08X\n", + r1, r2, r3); + + { + char cmdFifo[16]; + struct log_field lines[] = { + {rbbm_status & 0x001F, cmdFifo}, + {rbbm_status & BIT(5), "TC busy "}, + {rbbm_status & BIT(8), "HIRQ pending"}, + {rbbm_status & BIT(9), "CPRQ pending"}, + {rbbm_status & BIT(10), "CFRQ pending"}, + {rbbm_status & BIT(11), "PFRQ pending"}, + {rbbm_status & BIT(12), "VGT 0DMA bsy"}, + {rbbm_status & BIT(14), "RBBM WU busy"}, + {rbbm_status & BIT(16), "CP NRT busy "}, + {rbbm_status & BIT(18), "MH busy "}, + {rbbm_status & BIT(19), "MH chncy bsy"}, + {rbbm_status & BIT(21), "SX busy "}, + {rbbm_status & BIT(22), "TPC busy "}, + {rbbm_status & BIT(24), "SC CNTX busy"}, + {rbbm_status & BIT(25), "PA busy "}, + {rbbm_status & BIT(26), "VGT busy "}, + {rbbm_status & BIT(27), "SQ cntx1 bsy"}, + {rbbm_status & BIT(28), "SQ cntx0 bsy"}, + {rbbm_status & BIT(30), "RB busy "}, + {rbbm_status & BIT(31), "Grphs pp bsy"}, + }; + snprintf(cmdFifo, sizeof(cmdFifo), "CMD FIFO=%01X ", + rbbm_status & 0xf); + adreno_dump_fields(device, " STATUS=", lines, + ARRAY_SIZE(lines)); + } + + kgsl_regread(device, REG_CP_RB_BASE, &r1); + kgsl_regread(device, REG_CP_RB_CNTL, &r2); + rb_count = 2 << (r2 & (BIT(6)-1)); + kgsl_regread(device, REG_CP_RB_RPTR_ADDR, &r3); + KGSL_LOG_DUMP(device, + " RPTR = %08X | WPTR = %08X | RPTR_WR = %08X" + "\n", r1, r2, r3); + + kgsl_regread(device, REG_CP_IB1_BASE, &r1); + kgsl_regread(device, REG_CP_IB1_BUFSZ, &r2); + KGSL_LOG_DUMP(device, "CP_IB1: BASE = %08X | BUFSZ = %d\n", r1, r2); + + kgsl_regread(device, REG_CP_IB2_BASE, &r1); + kgsl_regread(device, REG_CP_IB2_BUFSZ, &r2); + KGSL_LOG_DUMP(device, "CP_IB2: BASE = %08X | BUFSZ = %d\n", r1, r2); + + kgsl_regread(device, REG_CP_INT_CNTL, &r1); + kgsl_regread(device, REG_CP_INT_STATUS, &r2); + KGSL_LOG_DUMP(device, "CP_INT: CNTL = %08X | STATUS = %08X\n", r1, r2); + + kgsl_regread(device, REG_CP_ME_CNTL, &r1); + kgsl_regread(device, REG_CP_ME_STATUS, &r2); + kgsl_regread(device, REG_MASTER_INT_SIGNAL, &r3); + KGSL_LOG_DUMP(device, + "CP_ME: CNTL = %08X | STATUS = %08X | MSTR_INT_SGNL = " + "%08X\n", r1, r2, r3); + + kgsl_regread(device, REG_CP_STAT, &cp_stat); + KGSL_LOG_DUMP(device, "CP_STAT = %08X\n", cp_stat); +#ifndef CONFIG_MSM_KGSL_PSTMRTMDMP_CP_STAT_NO_DETAIL + { + struct log_field lns[] = { + {cp_stat & BIT(0), "WR_BSY 0"}, + {cp_stat & BIT(1), "RD_RQ_BSY 1"}, + {cp_stat & BIT(2), "RD_RTN_BSY 2"}, + }; + adreno_dump_fields(device, " MIU=", lns, ARRAY_SIZE(lns)); + } + { + struct log_field lns[] = { + {cp_stat & BIT(5), "RING_BUSY 5"}, + {cp_stat & BIT(6), "NDRCTS_BSY 6"}, + {cp_stat & BIT(7), "NDRCT2_BSY 7"}, + {cp_stat & BIT(9), "ST_BUSY 9"}, + {cp_stat & BIT(10), "BUSY 10"}, + }; + adreno_dump_fields(device, " CSF=", lns, ARRAY_SIZE(lns)); + } + { + struct log_field lns[] = { + {cp_stat & BIT(11), "RNG_Q_BSY 11"}, + {cp_stat & BIT(12), "NDRCTS_Q_B12"}, + {cp_stat & BIT(13), "NDRCT2_Q_B13"}, + {cp_stat & BIT(16), "ST_QUEUE_B16"}, + {cp_stat & BIT(17), "PFP_BUSY 17"}, + }; + adreno_dump_fields(device, " RING=", lns, ARRAY_SIZE(lns)); + } + { + struct log_field lns[] = { + {cp_stat & BIT(3), "RBIU_BUSY 3"}, + {cp_stat & BIT(4), "RCIU_BUSY 4"}, + {cp_stat & BIT(18), "MQ_RG_BSY 18"}, + {cp_stat & BIT(19), "MQ_NDRS_BS19"}, + {cp_stat & BIT(20), "MQ_NDR2_BS20"}, + {cp_stat & BIT(21), "MIU_WC_STL21"}, + {cp_stat & BIT(22), "CP_NRT_BSY22"}, + {cp_stat & BIT(23), "3D_BUSY 23"}, + {cp_stat & BIT(26), "ME_BUSY 26"}, + {cp_stat & BIT(29), "ME_WC_BSY 29"}, + {cp_stat & BIT(30), "MIU_FF EM 30"}, + {cp_stat & BIT(31), "CP_BUSY 31"}, + }; + adreno_dump_fields(device, " CP_STT=", lns, ARRAY_SIZE(lns)); + } +#endif + + kgsl_regread(device, REG_SCRATCH_REG0, &r1); + KGSL_LOG_DUMP(device, "SCRATCH_REG0 = %08X\n", r1); + + kgsl_regread(device, REG_COHER_SIZE_PM4, &r1); + kgsl_regread(device, REG_COHER_BASE_PM4, &r2); + kgsl_regread(device, REG_COHER_STATUS_PM4, &r3); + KGSL_LOG_DUMP(device, + "COHER: SIZE_PM4 = %08X | BASE_PM4 = %08X | STATUS_PM4" + " = %08X\n", r1, r2, r3); + + kgsl_regread(device, MH_AXI_ERROR, &r1); + KGSL_LOG_DUMP(device, "MH: AXI_ERROR = %08X\n", r1); + + kgsl_regread(device, MH_MMU_PAGE_FAULT, &r1); + kgsl_regread(device, MH_MMU_CONFIG, &r2); + kgsl_regread(device, MH_MMU_MPU_BASE, &r3); + KGSL_LOG_DUMP(device, + "MH_MMU: PAGE_FAULT = %08X | CONFIG = %08X | MPU_BASE =" + " %08X\n", r1, r2, r3); + + kgsl_regread(device, MH_MMU_MPU_END, &r1); + kgsl_regread(device, MH_MMU_VA_RANGE, &r2); + r3 = kgsl_mmu_get_current_ptbase(&device->mmu); + KGSL_LOG_DUMP(device, + " MPU_END = %08X | VA_RANGE = %08X | PT_BASE =" + " %08X\n", r1, r2, r3); + + KGSL_LOG_DUMP(device, "PAGETABLE SIZE: %08X ", + kgsl_mmu_get_ptsize(&device->mmu)); + + kgsl_regread(device, MH_MMU_TRAN_ERROR, &r1); + KGSL_LOG_DUMP(device, " TRAN_ERROR = %08X\n", r1); + + kgsl_regread(device, MH_INTERRUPT_MASK, &r1); + kgsl_regread(device, MH_INTERRUPT_STATUS, &r2); + KGSL_LOG_DUMP(device, + "MH_INTERRUPT: MASK = %08X | STATUS = %08X\n", r1, r2); +} + +/* Register offset defines for A2XX */ +static unsigned int a2xx_register_offsets[ADRENO_REG_REGISTER_MAX] = { + ADRENO_REG_DEFINE(ADRENO_REG_CP_DEBUG, REG_CP_DEBUG), + ADRENO_REG_DEFINE(ADRENO_REG_CP_ME_RAM_WADDR, REG_CP_ME_RAM_WADDR), + ADRENO_REG_DEFINE(ADRENO_REG_CP_ME_RAM_DATA, REG_CP_ME_RAM_DATA), + ADRENO_REG_DEFINE(ADRENO_REG_CP_PFP_UCODE_DATA, REG_CP_PFP_UCODE_DATA), + ADRENO_REG_DEFINE(ADRENO_REG_CP_PFP_UCODE_ADDR, REG_CP_PFP_UCODE_ADDR), + ADRENO_REG_DEFINE(ADRENO_REG_CP_RB_BASE, REG_CP_RB_BASE), + ADRENO_REG_DEFINE(ADRENO_REG_CP_RB_RPTR_ADDR, REG_CP_RB_RPTR_ADDR), + ADRENO_REG_DEFINE(ADRENO_REG_CP_RB_RPTR, REG_CP_RB_RPTR), + ADRENO_REG_DEFINE(ADRENO_REG_CP_RB_WPTR, REG_CP_RB_WPTR), + ADRENO_REG_DEFINE(ADRENO_REG_CP_ME_CNTL, REG_CP_ME_CNTL), + ADRENO_REG_DEFINE(ADRENO_REG_CP_RB_CNTL, REG_CP_RB_CNTL), + ADRENO_REG_DEFINE(ADRENO_REG_CP_IB1_BASE, REG_CP_IB1_BASE), + ADRENO_REG_DEFINE(ADRENO_REG_CP_IB1_BUFSZ, REG_CP_IB1_BUFSZ), + ADRENO_REG_DEFINE(ADRENO_REG_CP_IB2_BASE, REG_CP_IB2_BASE), + ADRENO_REG_DEFINE(ADRENO_REG_CP_IB2_BUFSZ, REG_CP_IB2_BUFSZ), + ADRENO_REG_DEFINE(ADRENO_REG_CP_TIMESTAMP, REG_CP_TIMESTAMP), + ADRENO_REG_DEFINE(ADRENO_REG_CP_ME_RAM_RADDR, REG_CP_ME_RAM_RADDR), + ADRENO_REG_DEFINE(ADRENO_REG_SCRATCH_ADDR, REG_SCRATCH_ADDR), + ADRENO_REG_DEFINE(ADRENO_REG_SCRATCH_UMSK, REG_SCRATCH_UMSK), + ADRENO_REG_DEFINE(ADRENO_REG_RBBM_STATUS, REG_RBBM_STATUS), + ADRENO_REG_DEFINE(ADRENO_REG_PA_SC_AA_CONFIG, REG_PA_SC_AA_CONFIG), + ADRENO_REG_DEFINE(ADRENO_REG_RBBM_PM_OVERRIDE2, REG_RBBM_PM_OVERRIDE2), + ADRENO_REG_DEFINE(ADRENO_REG_SCRATCH_REG2, REG_SCRATCH_REG2), + ADRENO_REG_DEFINE(ADRENO_REG_SQ_GPR_MANAGEMENT, REG_SQ_GPR_MANAGEMENT), + ADRENO_REG_DEFINE(ADRENO_REG_SQ_INST_STORE_MANAGMENT, + REG_SQ_INST_STORE_MANAGMENT), + ADRENO_REG_DEFINE(ADRENO_REG_TC_CNTL_STATUS, REG_TC_CNTL_STATUS), + ADRENO_REG_DEFINE(ADRENO_REG_TP0_CHICKEN, REG_TP0_CHICKEN), +}; + +const struct adreno_reg_offsets a2xx_reg_offsets = { + .offsets = a2xx_register_offsets, + .offset_0 = ADRENO_REG_REGISTER_MAX, +}; + /* Defined in adreno_a2xx_snapshot.c */ void *a2xx_snapshot(struct adreno_device *adreno_dev, void *snapshot, int *remain, int hang); struct adreno_gpudev adreno_a2xx_gpudev = { - .reg_rbbm_status = REG_RBBM_STATUS, - .reg_cp_pfp_ucode_addr = REG_CP_PFP_UCODE_ADDR, - .reg_cp_pfp_ucode_data = REG_CP_PFP_UCODE_DATA, + .reg_offsets = &a2xx_reg_offsets, .ctxt_create = a2xx_drawctxt_create, .ctxt_save = a2xx_drawctxt_save, @@ -2096,4 +2303,5 @@ struct adreno_gpudev adreno_a2xx_gpudev = { .rb_init = a2xx_rb_init, .busy_cycles = a2xx_busy_cycles, .start = a2xx_start, + .postmortem_dump = a2xx_postmortem_dump, }; diff --git a/drivers/gpu/msm/adreno_a2xx_snapshot.c b/drivers/gpu/msm/adreno_a2xx_snapshot.c index 2c86f82d4df..5134ed6ff1a 100644 --- a/drivers/gpu/msm/adreno_a2xx_snapshot.c +++ b/drivers/gpu/msm/adreno_a2xx_snapshot.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2013, The Linux Foundation. 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 and @@ -38,11 +38,11 @@ static int a2xx_snapshot_sxdebug(struct kgsl_device *device, void *snapshot, header->size = SXDEBUG_COUNT; for (i = 0; i < SXDEBUG_COUNT; i++) { - adreno_regwrite(device, REG_RBBM_DEBUG_CNTL, 0x1B00 | i); - adreno_regread(device, REG_RBBM_DEBUG_OUT, &data[i]); + kgsl_regwrite(device, REG_RBBM_DEBUG_CNTL, 0x1B00 | i); + kgsl_regread(device, REG_RBBM_DEBUG_OUT, &data[i]); } - adreno_regwrite(device, REG_RBBM_DEBUG_CNTL, 0); + kgsl_regwrite(device, REG_RBBM_DEBUG_CNTL, 0); return DEBUG_SECTION_SZ(SXDEBUG_COUNT); } @@ -65,11 +65,11 @@ static int a2xx_snapshot_cpdebug(struct kgsl_device *device, void *snapshot, header->size = CPDEBUG_COUNT; for (i = 0; i < CPDEBUG_COUNT; i++) { - adreno_regwrite(device, REG_RBBM_DEBUG_CNTL, 0x1628); - adreno_regread(device, REG_RBBM_DEBUG_OUT, &data[i]); + kgsl_regwrite(device, REG_RBBM_DEBUG_CNTL, 0x1628); + kgsl_regread(device, REG_RBBM_DEBUG_OUT, &data[i]); } - adreno_regwrite(device, REG_RBBM_DEBUG_CNTL, 0); + kgsl_regwrite(device, REG_RBBM_DEBUG_CNTL, 0); return DEBUG_SECTION_SZ(CPDEBUG_COUNT); } @@ -82,7 +82,8 @@ static int a2xx_snapshot_cpdebug(struct kgsl_device *device, void *snapshot, #define SQ_DEBUG_WRITE(_device, _reg, _data, _offset) \ do { _data[(_offset)++] = (_reg); \ - adreno_regread(_device, (_reg), &_data[(_offset)++]); } while (0) + kgsl_regread(_device, (_reg), &_data[(_offset)++]); \ + } while (0) #define SQ_DEBUG_BANK_SIZE 23 @@ -175,7 +176,7 @@ static int a2xx_snapshot_sqthreaddebug(struct kgsl_device *device, header->size = size; for (i = 0; i < 16; i++) { - adreno_regwrite(device, REG_SQ_DEBUG_TB_STATUS_SEL, + kgsl_regwrite(device, REG_SQ_DEBUG_TB_STATUS_SEL, i | (6<<4) | (i<<7) | (1<<11) | (1<<12) | (i<<16) | (6<<20) | (i<<23)); SQ_DEBUG_WRITE(device, REG_SQ_DEBUG_VTX_TB_STATE_MEM, @@ -215,11 +216,11 @@ static int a2xx_snapshot_miudebug(struct kgsl_device *device, void *snapshot, header->size = MIUDEBUG_COUNT; for (i = 0; i < MIUDEBUG_COUNT; i++) { - adreno_regwrite(device, REG_RBBM_DEBUG_CNTL, 0x1600 | i); - adreno_regread(device, REG_RBBM_DEBUG_OUT, &data[i]); + kgsl_regwrite(device, REG_RBBM_DEBUG_CNTL, 0x1600 | i); + kgsl_regread(device, REG_RBBM_DEBUG_OUT, &data[i]); } - adreno_regwrite(device, REG_RBBM_DEBUG_CNTL, 0); + kgsl_regwrite(device, REG_RBBM_DEBUG_CNTL, 0); return DEBUG_SECTION_SZ(MIUDEBUG_COUNT); } @@ -297,8 +298,8 @@ void *a2xx_snapshot(struct adreno_device *adreno_dev, void *snapshot, * work */ - adreno_regread(device, REG_RBBM_PM_OVERRIDE2, &pmoverride); - adreno_regwrite(device, REG_RBBM_PM_OVERRIDE2, 0xFF); + kgsl_regread(device, REG_RBBM_PM_OVERRIDE2, &pmoverride); + kgsl_regwrite(device, REG_RBBM_PM_OVERRIDE2, 0xFF); /* SX debug registers */ snapshot = kgsl_snapshot_add_section(device, @@ -376,7 +377,7 @@ void *a2xx_snapshot(struct adreno_device *adreno_dev, void *snapshot, /* Reset the clock gating */ - adreno_regwrite(device, REG_RBBM_PM_OVERRIDE2, pmoverride); + kgsl_regwrite(device, REG_RBBM_PM_OVERRIDE2, pmoverride); return snapshot; } diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c index 1e61279e10f..b563c13fcd3 100644 --- a/drivers/gpu/msm/adreno_a3xx.c +++ b/drivers/gpu/msm/adreno_a3xx.c @@ -52,8 +52,8 @@ const unsigned int a3xx_registers[] = { 0x2240, 0x227e, 0x2280, 0x228b, 0x22c0, 0x22c0, 0x22c4, 0x22ce, 0x22d0, 0x22d8, 0x22df, 0x22e6, 0x22e8, 0x22e9, 0x22ec, 0x22ec, 0x22f0, 0x22f7, - 0x22ff, 0x22ff, 0x2340, 0x2343, 0x2348, 0x2349, 0x2350, 0x2356, - 0x2360, 0x2360, 0x2440, 0x2440, 0x2444, 0x2444, 0x2448, 0x244d, + 0x22ff, 0x22ff, 0x2340, 0x2343, + 0x2440, 0x2440, 0x2444, 0x2444, 0x2448, 0x244d, 0x2468, 0x2469, 0x246c, 0x246d, 0x2470, 0x2470, 0x2472, 0x2472, 0x2474, 0x2475, 0x2479, 0x247a, 0x24c0, 0x24d3, 0x24e4, 0x24ef, 0x2500, 0x2509, 0x250c, 0x250c, 0x250e, 0x250e, 0x2510, 0x2511, @@ -61,8 +61,8 @@ const unsigned int a3xx_registers[] = { 0x25f0, 0x25f0, 0x2640, 0x267e, 0x2680, 0x268b, 0x26c0, 0x26c0, 0x26c4, 0x26ce, 0x26d0, 0x26d8, 0x26df, 0x26e6, 0x26e8, 0x26e9, 0x26ec, 0x26ec, - 0x26f0, 0x26f7, 0x26ff, 0x26ff, 0x2740, 0x2743, 0x2748, 0x2749, - 0x2750, 0x2756, 0x2760, 0x2760, 0x300C, 0x300E, 0x301C, 0x301D, + 0x26f0, 0x26f7, 0x26ff, 0x26ff, 0x2740, 0x2743, + 0x300C, 0x300E, 0x301C, 0x301D, 0x302A, 0x302A, 0x302C, 0x302D, 0x3030, 0x3031, 0x3034, 0x3036, 0x303C, 0x303C, 0x305E, 0x305F, }; @@ -450,12 +450,16 @@ unsigned int adreno_a3xx_rbbm_clock_ctl_default(struct adreno_device { if (adreno_is_a305(adreno_dev)) return A305_RBBM_CLOCK_CTL_DEFAULT; + else if (adreno_is_a305c(adreno_dev)) + return A305C_RBBM_CLOCK_CTL_DEFAULT; else if (adreno_is_a320(adreno_dev)) return A320_RBBM_CLOCK_CTL_DEFAULT; else if (adreno_is_a330v2(adreno_dev)) return A330v2_RBBM_CLOCK_CTL_DEFAULT; else if (adreno_is_a330(adreno_dev)) return A330_RBBM_CLOCK_CTL_DEFAULT; + else if (adreno_is_a305b(adreno_dev)) + return A305B_RBBM_CLOCK_CTL_DEFAULT; BUG_ON(1); } @@ -2317,7 +2321,8 @@ static int a3xx_create_gmem_shadow(struct adreno_device *adreno_dev, tmp_ctx.gmem_base = adreno_dev->gmem_base; result = kgsl_allocate(&drawctxt->context_gmem_shadow.gmemshadow, - drawctxt->base.pagetable, drawctxt->context_gmem_shadow.size); + drawctxt->base.proc_priv->pagetable, + drawctxt->context_gmem_shadow.size); if (result) return result; @@ -2351,12 +2356,13 @@ static int a3xx_drawctxt_create(struct adreno_device *adreno_dev, */ ret = kgsl_allocate(&drawctxt->gpustate, - drawctxt->base.pagetable, CONTEXT_SIZE); + drawctxt->base.proc_priv->pagetable, CONTEXT_SIZE); if (ret) return ret; - kgsl_sharedmem_set(&drawctxt->gpustate, 0, 0, CONTEXT_SIZE); + kgsl_sharedmem_set(&adreno_dev->dev, &drawctxt->gpustate, 0, 0, + CONTEXT_SIZE); tmp_ctx.cmd = drawctxt->gpustate.hostptr + CMD_OFFSET; if (!(drawctxt->flags & CTXT_FLAGS_PREAMBLE)) { @@ -2473,7 +2479,7 @@ static int a3xx_drawctxt_restore(struct adreno_device *adreno_dev, if (ret) return ret; - kgsl_mmu_setstate(&device->mmu, context->base.pagetable, + kgsl_mmu_setstate(&device->mmu, context->base.proc_priv->pagetable, context->base.id); /* @@ -2482,7 +2488,7 @@ static int a3xx_drawctxt_restore(struct adreno_device *adreno_dev, */ if (context->flags & CTXT_FLAGS_GMEM_RESTORE) { - kgsl_cffdump_syncmem(NULL, + kgsl_cffdump_syncmem(context->base.device, &context->gpustate, context->context_gmem_shadow.gmem_restore[1], context->context_gmem_shadow.gmem_restore[2] << 2, @@ -2531,7 +2537,487 @@ static int a3xx_drawctxt_restore(struct adreno_device *adreno_dev, return ret; } -static int a3xx_rb_init(struct adreno_device *adreno_dev, +static const unsigned int _a3xx_pwron_fixup_fs_instructions[] = { + 0x00000000, 0x302CC300, 0x00000000, 0x302CC304, + 0x00000000, 0x302CC308, 0x00000000, 0x302CC30C, + 0x00000000, 0x302CC310, 0x00000000, 0x302CC314, + 0x00000000, 0x302CC318, 0x00000000, 0x302CC31C, + 0x00000000, 0x302CC320, 0x00000000, 0x302CC324, + 0x00000000, 0x302CC328, 0x00000000, 0x302CC32C, + 0x00000000, 0x302CC330, 0x00000000, 0x302CC334, + 0x00000000, 0x302CC338, 0x00000000, 0x302CC33C, + 0x00000000, 0x00000400, 0x00020000, 0x63808003, + 0x00060004, 0x63828007, 0x000A0008, 0x6384800B, + 0x000E000C, 0x6386800F, 0x00120010, 0x63888013, + 0x00160014, 0x638A8017, 0x001A0018, 0x638C801B, + 0x001E001C, 0x638E801F, 0x00220020, 0x63908023, + 0x00260024, 0x63928027, 0x002A0028, 0x6394802B, + 0x002E002C, 0x6396802F, 0x00320030, 0x63988033, + 0x00360034, 0x639A8037, 0x003A0038, 0x639C803B, + 0x003E003C, 0x639E803F, 0x00000000, 0x00000400, + 0x00000003, 0x80D60003, 0x00000007, 0x80D60007, + 0x0000000B, 0x80D6000B, 0x0000000F, 0x80D6000F, + 0x00000013, 0x80D60013, 0x00000017, 0x80D60017, + 0x0000001B, 0x80D6001B, 0x0000001F, 0x80D6001F, + 0x00000023, 0x80D60023, 0x00000027, 0x80D60027, + 0x0000002B, 0x80D6002B, 0x0000002F, 0x80D6002F, + 0x00000033, 0x80D60033, 0x00000037, 0x80D60037, + 0x0000003B, 0x80D6003B, 0x0000003F, 0x80D6003F, + 0x00000000, 0x03000000, 0x00000000, 0x00000000, +}; + +/** + * adreno_a3xx_pwron_fixup_init() - Initalize a special command buffer to run a + * post-power collapse shader workaround + * @adreno_dev: Pointer to a adreno_device struct + * + * Some targets require a special workaround shader to be executed after + * power-collapse. Construct the IB once at init time and keep it + * handy + * + * Returns: 0 on success or negative on error + */ +int adreno_a3xx_pwron_fixup_init(struct adreno_device *adreno_dev) +{ + unsigned int *cmds; + int count = ARRAY_SIZE(_a3xx_pwron_fixup_fs_instructions); + int ret; + + /* Return if the fixup is already in place */ + if (test_bit(ADRENO_DEVICE_PWRON_FIXUP, &adreno_dev->priv)) + return 0; + + ret = kgsl_allocate_contiguous(&adreno_dev->pwron_fixup, PAGE_SIZE); + + if (ret) + return ret; + + adreno_dev->pwron_fixup.flags |= KGSL_MEMFLAGS_GPUREADONLY; + + cmds = adreno_dev->pwron_fixup.hostptr; + + *cmds++ = cp_type0_packet(A3XX_UCHE_CACHE_INVALIDATE0_REG, 2); + *cmds++ = 0x00000000; + *cmds++ = 0x90000000; + *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type3_packet(CP_REG_RMW, 3); + *cmds++ = A3XX_RBBM_CLOCK_CTL; + *cmds++ = 0xFFFCFFFF; + *cmds++ = 0x00010000; + *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_HLSQ_CONTROL_0_REG, 1); + *cmds++ = 0x1E000150; + *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2); + *cmds++ = CP_REG(A3XX_HLSQ_CONTROL_0_REG); + *cmds++ = 0x1E000150; + *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_HLSQ_CONTROL_0_REG, 1); + *cmds++ = 0x1E000150; + *cmds++ = cp_type0_packet(A3XX_HLSQ_CONTROL_1_REG, 1); + *cmds++ = 0x00000040; + *cmds++ = cp_type0_packet(A3XX_HLSQ_CONTROL_2_REG, 1); + *cmds++ = 0x80000000; + *cmds++ = cp_type0_packet(A3XX_HLSQ_CONTROL_3_REG, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_HLSQ_VS_CONTROL_REG, 1); + *cmds++ = 0x00000001; + *cmds++ = cp_type0_packet(A3XX_HLSQ_FS_CONTROL_REG, 1); + *cmds++ = 0x0D001002; + *cmds++ = cp_type0_packet(A3XX_HLSQ_CONST_VSPRESV_RANGE_REG, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_HLSQ_CONST_FSPRESV_RANGE_REG, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_HLSQ_CL_NDRANGE_0_REG, 1); + *cmds++ = 0x00401101; + *cmds++ = cp_type0_packet(A3XX_HLSQ_CL_NDRANGE_1_REG, 1); + *cmds++ = 0x00000400; + *cmds++ = cp_type0_packet(A3XX_HLSQ_CL_NDRANGE_2_REG, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_HLSQ_CL_NDRANGE_3_REG, 1); + *cmds++ = 0x00000001; + *cmds++ = cp_type0_packet(A3XX_HLSQ_CL_NDRANGE_4_REG, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_HLSQ_CL_NDRANGE_5_REG, 1); + *cmds++ = 0x00000001; + *cmds++ = cp_type0_packet(A3XX_HLSQ_CL_NDRANGE_6_REG, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_HLSQ_CL_CONTROL_0_REG, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_HLSQ_CL_CONTROL_1_REG, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_HLSQ_CL_KERNEL_CONST_REG, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_HLSQ_CL_KERNEL_GROUP_X_REG, 1); + *cmds++ = 0x00000010; + *cmds++ = cp_type0_packet(A3XX_HLSQ_CL_KERNEL_GROUP_Y_REG, 1); + *cmds++ = 0x00000001; + *cmds++ = cp_type0_packet(A3XX_HLSQ_CL_KERNEL_GROUP_Z_REG, 1); + *cmds++ = 0x00000001; + *cmds++ = cp_type0_packet(A3XX_HLSQ_CL_WG_OFFSET_REG, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_SP_CTRL_REG, 1); + *cmds++ = 0x00040000; + *cmds++ = cp_type0_packet(A3XX_SP_VS_CTRL_REG0, 1); + *cmds++ = 0x0000000A; + *cmds++ = cp_type0_packet(A3XX_SP_VS_CTRL_REG1, 1); + *cmds++ = 0x00000001; + *cmds++ = cp_type0_packet(A3XX_SP_VS_PARAM_REG, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_VS_OUT_REG_0, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_VS_OUT_REG_1, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_VS_OUT_REG_2, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_VS_OUT_REG_3, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_VS_OUT_REG_4, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_VS_OUT_REG_5, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_VS_OUT_REG_6, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_VS_OUT_REG_7, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_VS_VPC_DST_REG_0, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_VS_VPC_DST_REG_1, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_VS_VPC_DST_REG_2, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_VS_VPC_DST_REG_3, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_VS_OBJ_OFFSET_REG, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_VS_OBJ_START_REG, 1); + *cmds++ = 0x00000004; + *cmds++ = cp_type0_packet(A3XX_SP_VS_PVT_MEM_PARAM_REG, 1); + *cmds++ = 0x04008001; + *cmds++ = cp_type0_packet(A3XX_SP_VS_PVT_MEM_ADDR_REG, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_VS_PVT_MEM_SIZE_REG, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_VS_LENGTH_REG, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_FS_CTRL_REG0, 1); + *cmds++ = 0x0DB0400A; + *cmds++ = cp_type0_packet(A3XX_SP_FS_CTRL_REG1, 1); + *cmds++ = 0x00300402; + *cmds++ = cp_type0_packet(A3XX_SP_FS_OBJ_OFFSET_REG, 1); + *cmds++ = 0x00010000; + *cmds++ = cp_type0_packet(A3XX_SP_FS_OBJ_START_REG, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_FS_PVT_MEM_PARAM_REG, 1); + *cmds++ = 0x04008001; + *cmds++ = cp_type0_packet(A3XX_SP_FS_PVT_MEM_ADDR_REG, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_FS_PVT_MEM_SIZE_REG, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_FS_FLAT_SHAD_MODE_REG_0, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_FS_FLAT_SHAD_MODE_REG_1, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_FS_OUTPUT_REG, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_FS_MRT_REG_0, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_FS_MRT_REG_1, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_FS_MRT_REG_2, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_FS_MRT_REG_3, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_FS_IMAGE_OUTPUT_REG_0, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_FS_IMAGE_OUTPUT_REG_1, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_FS_IMAGE_OUTPUT_REG_2, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_FS_IMAGE_OUTPUT_REG_3, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_FS_LENGTH_REG, 1); + *cmds++ = 0x0000000D; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_CLIP_CNTL, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_GB_CLIP_ADJ, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_VPORT_XOFFSET, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_VPORT_XSCALE, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_VPORT_YOFFSET, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_VPORT_YSCALE, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_VPORT_ZOFFSET, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_VPORT_ZSCALE, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_X0, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_Y0, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_Z0, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_W0, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_X1, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_Y1, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_Z1, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_W1, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_X2, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_Y2, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_Z2, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_W2, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_X3, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_Y3, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_Z3, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_W3, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_X4, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_Y4, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_Z4, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_W4, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_X5, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_Y5, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_Z5, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_W5, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_SU_POINT_MINMAX, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_SU_POINT_SIZE, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_SU_POLY_OFFSET_OFFSET, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_SU_POLY_OFFSET_SCALE, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_SU_MODE_CONTROL, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_SC_CONTROL, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_SC_SCREEN_SCISSOR_TL, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_SC_SCREEN_SCISSOR_BR, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_SC_WINDOW_SCISSOR_BR, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_SC_WINDOW_SCISSOR_TL, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_TSE_DEBUG_ECO, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_PERFCOUNTER0_SELECT, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_PERFCOUNTER1_SELECT, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_PERFCOUNTER2_SELECT, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_PERFCOUNTER3_SELECT, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_MODE_CONTROL, 1); + *cmds++ = 0x00008000; + *cmds++ = cp_type0_packet(A3XX_RB_RENDER_CONTROL, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_MSAA_CONTROL, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_ALPHA_REFERENCE, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_MRT_CONTROL0, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_MRT_CONTROL1, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_MRT_CONTROL2, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_MRT_CONTROL3, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_MRT_BUF_INFO0, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_MRT_BUF_INFO1, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_MRT_BUF_INFO2, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_MRT_BUF_INFO3, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_MRT_BUF_BASE0, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_MRT_BUF_BASE1, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_MRT_BUF_BASE2, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_MRT_BUF_BASE3, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_MRT_BLEND_CONTROL0, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_MRT_BLEND_CONTROL1, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_MRT_BLEND_CONTROL2, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_MRT_BLEND_CONTROL3, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_BLEND_RED, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_BLEND_GREEN, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_BLEND_BLUE, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_BLEND_ALPHA, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_CLEAR_COLOR_DW0, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_CLEAR_COLOR_DW1, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_CLEAR_COLOR_DW2, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_CLEAR_COLOR_DW3, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_COPY_CONTROL, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_COPY_DEST_BASE, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_COPY_DEST_PITCH, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_COPY_DEST_INFO, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_DEPTH_CONTROL, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_DEPTH_CLEAR, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_DEPTH_BUF_INFO, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_DEPTH_BUF_PITCH, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_STENCIL_CONTROL, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_STENCIL_CLEAR, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_STENCIL_BUF_INFO, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_STENCIL_BUF_PITCH, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_STENCIL_REF_MASK, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_STENCIL_REF_MASK_BF, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_LRZ_VSC_CONTROL, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_WINDOW_OFFSET, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_SAMPLE_COUNT_CONTROL, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_SAMPLE_COUNT_ADDR, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_Z_CLAMP_MIN, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_Z_CLAMP_MAX, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_GMEM_BASE_ADDR, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_DEBUG_ECO_CONTROLS_ADDR, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_PERFCOUNTER0_SELECT, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_PERFCOUNTER1_SELECT, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_FRAME_BUFFER_DIMENSION, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type3_packet(CP_LOAD_STATE, 4); + *cmds++ = (1 << CP_LOADSTATE_DSTOFFSET_SHIFT) | + (0 << CP_LOADSTATE_STATESRC_SHIFT) | + (6 << CP_LOADSTATE_STATEBLOCKID_SHIFT) | + (1 << CP_LOADSTATE_NUMOFUNITS_SHIFT); + *cmds++ = (1 << CP_LOADSTATE_STATETYPE_SHIFT) | + (0 << CP_LOADSTATE_EXTSRCADDR_SHIFT); + *cmds++ = 0x00400000; + *cmds++ = 0x00000000; + *cmds++ = cp_type3_packet(CP_LOAD_STATE, 4); + *cmds++ = (2 << CP_LOADSTATE_DSTOFFSET_SHIFT) | + (6 << CP_LOADSTATE_STATEBLOCKID_SHIFT) | + (1 << CP_LOADSTATE_NUMOFUNITS_SHIFT); + *cmds++ = (1 << CP_LOADSTATE_STATETYPE_SHIFT); + *cmds++ = 0x00400220; + *cmds++ = 0x00000000; + *cmds++ = cp_type3_packet(CP_LOAD_STATE, 4); + *cmds++ = (6 << CP_LOADSTATE_STATEBLOCKID_SHIFT) | + (1 << CP_LOADSTATE_NUMOFUNITS_SHIFT); + *cmds++ = (1 << CP_LOADSTATE_STATETYPE_SHIFT); + *cmds++ = 0x00000000; + *cmds++ = 0x00000000; + *cmds++ = cp_type3_packet(CP_LOAD_STATE, 2 + count); + *cmds++ = (6 << CP_LOADSTATE_STATEBLOCKID_SHIFT) | + (13 << CP_LOADSTATE_NUMOFUNITS_SHIFT); + *cmds++ = 0x00000000; + + memcpy(cmds, _a3xx_pwron_fixup_fs_instructions, count << 2); + + cmds += count; + + *cmds++ = cp_type3_packet(CP_EXEC_CL, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_HLSQ_CL_CONTROL_0_REG, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_HLSQ_CONTROL_0_REG, 1); + *cmds++ = 0x1E000150; + *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2); + *cmds++ = CP_REG(A3XX_HLSQ_CONTROL_0_REG); + *cmds++ = 0x1E000050; + *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type3_packet(CP_REG_RMW, 3); + *cmds++ = A3XX_RBBM_CLOCK_CTL; + *cmds++ = 0xFFFCFFFF; + *cmds++ = 0x00000000; + *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1); + *cmds++ = 0x00000000; + + /* + * Remember the number of dwords in the command buffer for when we + * program the indirect buffer call in the ringbuffer + */ + adreno_dev->pwron_fixup_dwords = + (cmds - (unsigned int *) adreno_dev->pwron_fixup.hostptr); + + /* Mark the flag in ->priv to show that we have the fix */ + set_bit(ADRENO_DEVICE_PWRON_FIXUP, &adreno_dev->priv); + return 0; +} + +/* + * a3xx_rb_init() - Initialize ringbuffer + * @adreno_dev: Pointer to adreno device + * @rb: Pointer to the ringbuffer of device + * + * Submit commands for ME initialization, common function shared between + * a3xx and a4xx devices + */ +int a3xx_rb_init(struct adreno_device *adreno_dev, struct adreno_ringbuffer *rb) { unsigned int *cmds, cmds_gpu; @@ -2541,25 +3027,26 @@ static int a3xx_rb_init(struct adreno_device *adreno_dev, cmds_gpu = rb->buffer_desc.gpuaddr + sizeof(uint) * (rb->wptr - 18); - GSL_RB_WRITE(cmds, cmds_gpu, cp_type3_packet(CP_ME_INIT, 17)); - GSL_RB_WRITE(cmds, cmds_gpu, 0x000003f7); - GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000); - GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000); - GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000); - GSL_RB_WRITE(cmds, cmds_gpu, 0x00000080); - GSL_RB_WRITE(cmds, cmds_gpu, 0x00000100); - GSL_RB_WRITE(cmds, cmds_gpu, 0x00000180); - GSL_RB_WRITE(cmds, cmds_gpu, 0x00006600); - GSL_RB_WRITE(cmds, cmds_gpu, 0x00000150); - GSL_RB_WRITE(cmds, cmds_gpu, 0x0000014e); - GSL_RB_WRITE(cmds, cmds_gpu, 0x00000154); - GSL_RB_WRITE(cmds, cmds_gpu, 0x00000001); - GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000); - GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000); - /* Protected mode control - turned off for A3XX */ - GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000); - GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000); - GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000); + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, + cp_type3_packet(CP_ME_INIT, 17)); + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x000003f7); + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000000); + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000000); + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000000); + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000080); + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000100); + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000180); + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00006600); + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000150); + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x0000014e); + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000154); + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000001); + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000000); + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000000); + /* Protected mode control - turned off for A3XX/A4XX */ + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000000); + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000000); + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000000); adreno_ringbuffer_submit(rb); @@ -2575,7 +3062,7 @@ static void a3xx_err_callback(struct adreno_device *adreno_dev, int bit) case A3XX_INT_RBBM_AHB_ERROR: { unsigned int reg; - adreno_regread(device, A3XX_RBBM_AHB_ERROR_STATUS, ®); + kgsl_regread(device, A3XX_RBBM_AHB_ERROR_STATUS, ®); /* * Return the word address of the erroring register so that it @@ -2589,11 +3076,8 @@ static void a3xx_err_callback(struct adreno_device *adreno_dev, int bit) (reg >> 24) & 0x3); /* Clear the error */ - adreno_regwrite(device, A3XX_RBBM_AHB_CMD, (1 << 3)); - - /* Trigger a fault in the interrupt handler */ - adreno_dispatcher_irq_fault(device); - return; + kgsl_regwrite(device, A3XX_RBBM_AHB_CMD, (1 << 3)); + goto done; } case A3XX_INT_RBBM_REG_TIMEOUT: err = "RBBM: AHB register timeout"; @@ -2637,171 +3121,71 @@ static void a3xx_err_callback(struct adreno_device *adreno_dev, int bit) default: return; } + KGSL_DRV_CRIT(device, "%s\n", err); + kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF); +done: /* Trigger a fault in the dispatcher - this will effect a restart */ adreno_dispatcher_irq_fault(device); - - KGSL_DRV_CRIT(device, "%s\n", err); - kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF); } +/* + * a3xx_cp_callback() - CP interrupt handler + * @adreno_dev: Adreno device pointer + * @irq: irq number + * + * Handle the cp interrupt generated by GPU, common function between a3xx and + * a4xx devices + */ static void a3xx_cp_callback(struct adreno_device *adreno_dev, int irq) { struct kgsl_device *device = &adreno_dev->dev; - /* Schedule the event queue */ + device->pwrctrl.irq_last = 1; queue_work(device->work_queue, &device->ts_expired_ws); adreno_dispatcher_schedule(device); } -/** - * struct a3xx_perfcounter_register - Define a performance counter register - * @load_bit: the bit to set in RBBM_LOAD_CMD0/RBBM_LOAD_CMD1 to force the RBBM - * to load the reset value into the appropriate counter - * @select: The dword offset of the register to write the selected - * countable into - */ -struct a3xx_perfcounter_register { - unsigned int load_bit; - unsigned int select; -}; - -static struct a3xx_perfcounter_register a3xx_perfcounter_reg_cp[] = { - { 0, A3XX_CP_PERFCOUNTER_SELECT }, -}; - -static struct a3xx_perfcounter_register a3xx_perfcounter_reg_rbbm[] = { - { 1, A3XX_RBBM_PERFCOUNTER0_SELECT }, - { 2, A3XX_RBBM_PERFCOUNTER1_SELECT }, -}; - -static struct a3xx_perfcounter_register a3xx_perfcounter_reg_pc[] = { - { 3, A3XX_PC_PERFCOUNTER0_SELECT }, - { 4, A3XX_PC_PERFCOUNTER1_SELECT }, - { 5, A3XX_PC_PERFCOUNTER2_SELECT }, - { 6, A3XX_PC_PERFCOUNTER3_SELECT }, -}; - -static struct a3xx_perfcounter_register a3xx_perfcounter_reg_vfd[] = { - { 7, A3XX_VFD_PERFCOUNTER0_SELECT }, - { 8, A3XX_VFD_PERFCOUNTER1_SELECT }, -}; - -static struct a3xx_perfcounter_register a3xx_perfcounter_reg_hlsq[] = { - { 9, A3XX_HLSQ_PERFCOUNTER0_SELECT }, - { 10, A3XX_HLSQ_PERFCOUNTER1_SELECT }, - { 11, A3XX_HLSQ_PERFCOUNTER2_SELECT }, - { 12, A3XX_HLSQ_PERFCOUNTER3_SELECT }, - { 13, A3XX_HLSQ_PERFCOUNTER4_SELECT }, - { 14, A3XX_HLSQ_PERFCOUNTER5_SELECT }, -}; - -static struct a3xx_perfcounter_register a3xx_perfcounter_reg_vpc[] = { - { 15, A3XX_VPC_PERFCOUNTER0_SELECT }, - { 16, A3XX_VPC_PERFCOUNTER1_SELECT }, -}; - -static struct a3xx_perfcounter_register a3xx_perfcounter_reg_tse[] = { - { 17, A3XX_GRAS_PERFCOUNTER0_SELECT }, - { 18, A3XX_GRAS_PERFCOUNTER1_SELECT }, -}; - -static struct a3xx_perfcounter_register a3xx_perfcounter_reg_ras[] = { - { 19, A3XX_GRAS_PERFCOUNTER2_SELECT }, - { 20, A3XX_GRAS_PERFCOUNTER3_SELECT }, -}; - -static struct a3xx_perfcounter_register a3xx_perfcounter_reg_uche[] = { - { 21, A3XX_UCHE_PERFCOUNTER0_SELECT }, - { 22, A3XX_UCHE_PERFCOUNTER1_SELECT }, - { 23, A3XX_UCHE_PERFCOUNTER2_SELECT }, - { 24, A3XX_UCHE_PERFCOUNTER3_SELECT }, - { 25, A3XX_UCHE_PERFCOUNTER4_SELECT }, - { 26, A3XX_UCHE_PERFCOUNTER5_SELECT }, -}; - -static struct a3xx_perfcounter_register a3xx_perfcounter_reg_tp[] = { - { 27, A3XX_TP_PERFCOUNTER0_SELECT }, - { 28, A3XX_TP_PERFCOUNTER1_SELECT }, - { 29, A3XX_TP_PERFCOUNTER2_SELECT }, - { 30, A3XX_TP_PERFCOUNTER3_SELECT }, - { 31, A3XX_TP_PERFCOUNTER4_SELECT }, - { 32, A3XX_TP_PERFCOUNTER5_SELECT }, -}; - -static struct a3xx_perfcounter_register a3xx_perfcounter_reg_sp[] = { - { 33, A3XX_SP_PERFCOUNTER0_SELECT }, - { 34, A3XX_SP_PERFCOUNTER1_SELECT }, - { 35, A3XX_SP_PERFCOUNTER2_SELECT }, - { 36, A3XX_SP_PERFCOUNTER3_SELECT }, - { 37, A3XX_SP_PERFCOUNTER4_SELECT }, - { 38, A3XX_SP_PERFCOUNTER5_SELECT }, - { 39, A3XX_SP_PERFCOUNTER6_SELECT }, - { 40, A3XX_SP_PERFCOUNTER7_SELECT }, -}; - -static struct a3xx_perfcounter_register a3xx_perfcounter_reg_rb[] = { - { 41, A3XX_RB_PERFCOUNTER0_SELECT }, - { 42, A3XX_RB_PERFCOUNTER1_SELECT }, -}; - -#define REGCOUNTER_GROUP(_x) { (_x), ARRAY_SIZE((_x)) } - -static struct { - struct a3xx_perfcounter_register *regs; - int count; -} a3xx_perfcounter_reglist[] = { - REGCOUNTER_GROUP(a3xx_perfcounter_reg_cp), - REGCOUNTER_GROUP(a3xx_perfcounter_reg_rbbm), - REGCOUNTER_GROUP(a3xx_perfcounter_reg_pc), - REGCOUNTER_GROUP(a3xx_perfcounter_reg_vfd), - REGCOUNTER_GROUP(a3xx_perfcounter_reg_hlsq), - REGCOUNTER_GROUP(a3xx_perfcounter_reg_vpc), - REGCOUNTER_GROUP(a3xx_perfcounter_reg_tse), - REGCOUNTER_GROUP(a3xx_perfcounter_reg_ras), - REGCOUNTER_GROUP(a3xx_perfcounter_reg_uche), - REGCOUNTER_GROUP(a3xx_perfcounter_reg_tp), - REGCOUNTER_GROUP(a3xx_perfcounter_reg_sp), - REGCOUNTER_GROUP(a3xx_perfcounter_reg_rb), -}; - -static void a3xx_perfcounter_enable_pwr(struct kgsl_device *device, - unsigned int countable) +static int a3xx_perfcounter_enable_pwr(struct kgsl_device *device, + unsigned int counter) { unsigned int in, out; - adreno_regread(device, A3XX_RBBM_RBBM_CTL, &in); + if (counter > 1) + return -EINVAL; + + kgsl_regread(device, A3XX_RBBM_RBBM_CTL, &in); - if (countable == 0) + if (counter == 0) out = in | RBBM_RBBM_CTL_RESET_PWR_CTR0; else out = in | RBBM_RBBM_CTL_RESET_PWR_CTR1; - adreno_regwrite(device, A3XX_RBBM_RBBM_CTL, out); + kgsl_regwrite(device, A3XX_RBBM_RBBM_CTL, out); - if (countable == 0) + if (counter == 0) out = in | RBBM_RBBM_CTL_ENABLE_PWR_CTR0; else out = in | RBBM_RBBM_CTL_ENABLE_PWR_CTR1; - adreno_regwrite(device, A3XX_RBBM_RBBM_CTL, out); + kgsl_regwrite(device, A3XX_RBBM_RBBM_CTL, out); - return; + return 0; } -static void a3xx_perfcounter_enable_vbif(struct kgsl_device *device, +static int a3xx_perfcounter_enable_vbif(struct kgsl_device *device, unsigned int counter, unsigned int countable) { unsigned int in, out, bit, sel; if (counter > 1 || countable > 0x7f) - return; + return -EINVAL; - adreno_regread(device, A3XX_VBIF_PERF_CNT_EN, &in); - adreno_regread(device, A3XX_VBIF_PERF_CNT_SEL, &sel); + kgsl_regread(device, A3XX_VBIF_PERF_CNT_EN, &in); + kgsl_regread(device, A3XX_VBIF_PERF_CNT_SEL, &sel); if (counter == 0) { bit = VBIF_PERF_CNT_0; @@ -2814,33 +3198,38 @@ static void a3xx_perfcounter_enable_vbif(struct kgsl_device *device, out = in | bit; - adreno_regwrite(device, A3XX_VBIF_PERF_CNT_SEL, sel); + kgsl_regwrite(device, A3XX_VBIF_PERF_CNT_SEL, sel); - adreno_regwrite(device, A3XX_VBIF_PERF_CNT_CLR, bit); - adreno_regwrite(device, A3XX_VBIF_PERF_CNT_CLR, 0); + kgsl_regwrite(device, A3XX_VBIF_PERF_CNT_CLR, bit); + kgsl_regwrite(device, A3XX_VBIF_PERF_CNT_CLR, 0); - adreno_regwrite(device, A3XX_VBIF_PERF_CNT_EN, out); + kgsl_regwrite(device, A3XX_VBIF_PERF_CNT_EN, out); + return 0; } -static void a3xx_perfcounter_enable_vbif_pwr(struct kgsl_device *device, - unsigned int countable) +static int a3xx_perfcounter_enable_vbif_pwr(struct kgsl_device *device, + unsigned int counter) { unsigned int in, out, bit; - adreno_regread(device, A3XX_VBIF_PERF_CNT_EN, &in); - if (countable == 0) + if (counter > 2) + return -EINVAL; + + kgsl_regread(device, A3XX_VBIF_PERF_CNT_EN, &in); + if (counter == 0) bit = VBIF_PERF_PWR_CNT_0; - else if (countable == 1) + else if (counter == 1) bit = VBIF_PERF_PWR_CNT_1; else bit = VBIF_PERF_PWR_CNT_2; out = in | bit; - adreno_regwrite(device, A3XX_VBIF_PERF_CNT_CLR, bit); - adreno_regwrite(device, A3XX_VBIF_PERF_CNT_CLR, 0); + kgsl_regwrite(device, A3XX_VBIF_PERF_CNT_CLR, bit); + kgsl_regwrite(device, A3XX_VBIF_PERF_CNT_CLR, 0); - adreno_regwrite(device, A3XX_VBIF_PERF_CNT_EN, out); + kgsl_regwrite(device, A3XX_VBIF_PERF_CNT_EN, out); + return 0; } /* @@ -2851,73 +3240,177 @@ static void a3xx_perfcounter_enable_vbif_pwr(struct kgsl_device *device, * @countable - Desired countable * * Physically set up a counter within a group with the desired countable + * Return 0 on success else error code */ -static void a3xx_perfcounter_enable(struct adreno_device *adreno_dev, +static int a3xx_perfcounter_enable(struct adreno_device *adreno_dev, unsigned int group, unsigned int counter, unsigned int countable) { struct kgsl_device *device = &adreno_dev->dev; unsigned int val = 0; - struct a3xx_perfcounter_register *reg; - - if (group >= ARRAY_SIZE(a3xx_perfcounter_reglist)) - return; - - if (counter >= a3xx_perfcounter_reglist[group].count) - return; + struct adreno_perfcount_register *reg; /* Special cases */ if (group == KGSL_PERFCOUNTER_GROUP_PWR) - return a3xx_perfcounter_enable_pwr(device, countable); + return a3xx_perfcounter_enable_pwr(device, counter); else if (group == KGSL_PERFCOUNTER_GROUP_VBIF) - return a3xx_perfcounter_enable_vbif(device, counter, countable); + return a3xx_perfcounter_enable_vbif(device, counter, + countable); else if (group == KGSL_PERFCOUNTER_GROUP_VBIF_PWR) - return a3xx_perfcounter_enable_vbif_pwr(device, countable); + return a3xx_perfcounter_enable_vbif_pwr(device, counter); - reg = &(a3xx_perfcounter_reglist[group].regs[counter]); + if (group >= adreno_dev->gpudev->perfcounters->group_count) + return -EINVAL; + + if ((0 == adreno_dev->gpudev->perfcounters->groups[group].reg_count) || + (counter >= + adreno_dev->gpudev->perfcounters->groups[group].reg_count)) + return -EINVAL; + + reg = &(adreno_dev->gpudev->perfcounters->groups[group].regs[counter]); /* Select the desired perfcounter */ - adreno_regwrite(device, reg->select, countable); + kgsl_regwrite(device, reg->select, countable); if (reg->load_bit < 32) { - val = 1 << reg->load_bit; - adreno_regwrite(device, A3XX_RBBM_PERFCTR_LOAD_CMD0, val); + kgsl_regread(device, A3XX_RBBM_PERFCTR_LOAD_CMD0, &val); + val |= (1 << reg->load_bit); + kgsl_regwrite(device, A3XX_RBBM_PERFCTR_LOAD_CMD0, val); } else { - val = 1 << (reg->load_bit - 32); - adreno_regwrite(device, A3XX_RBBM_PERFCTR_LOAD_CMD1, val); + kgsl_regread(device, A3XX_RBBM_PERFCTR_LOAD_CMD1, &val); + val |= (1 << (reg->load_bit - 32)); + kgsl_regwrite(device, A3XX_RBBM_PERFCTR_LOAD_CMD1, val); } + return 0; +} + +static uint64_t a3xx_perfcounter_read_pwr(struct adreno_device *adreno_dev, + unsigned int counter) +{ + struct kgsl_device *device = &adreno_dev->dev; + struct adreno_perfcounters *counters = adreno_dev->gpudev->perfcounters; + struct adreno_perfcount_register *reg; + unsigned int in, out, lo = 0, hi = 0; + unsigned int enable_bit; + + if (counter > 1) + return 0; + if (0 == counter) + enable_bit = RBBM_RBBM_CTL_ENABLE_PWR_CTR0; + else + enable_bit = RBBM_RBBM_CTL_ENABLE_PWR_CTR1; + /* freeze counter */ + adreno_readreg(adreno_dev, ADRENO_REG_RBBM_RBBM_CTL, &in); + out = (in & ~enable_bit); + adreno_writereg(adreno_dev, ADRENO_REG_RBBM_RBBM_CTL, out); + + reg = &counters->groups[KGSL_PERFCOUNTER_GROUP_PWR].regs[counter]; + kgsl_regread(device, reg->offset, &lo); + kgsl_regread(device, reg->offset + 1, &hi); + + /* restore the counter control value */ + adreno_writereg(adreno_dev, ADRENO_REG_RBBM_RBBM_CTL, in); + + return (((uint64_t) hi) << 32) | lo; +} + +static uint64_t a3xx_perfcounter_read_vbif(struct adreno_device *adreno_dev, + unsigned int counter) +{ + struct adreno_perfcounters *counters = adreno_dev->gpudev->perfcounters; + struct kgsl_device *device = &adreno_dev->dev; + struct adreno_perfcount_register *reg; + unsigned int in, out, lo = 0, hi = 0; + + if (counter > 1) + return 0; + + /* freeze counter */ + kgsl_regread(device, A3XX_VBIF_PERF_CNT_EN, &in); + if (counter == 0) + out = (in & ~VBIF_PERF_CNT_0); + else + out = (in & ~VBIF_PERF_CNT_1); + kgsl_regwrite(device, A3XX_VBIF_PERF_CNT_EN, out); + + reg = &counters->groups[KGSL_PERFCOUNTER_GROUP_VBIF].regs[counter]; + kgsl_regread(device, reg->offset, &lo); + kgsl_regread(device, reg->offset + 1, &hi); + + /* restore the perfcounter value */ + kgsl_regwrite(device, A3XX_VBIF_PERF_CNT_EN, in); + + return (((uint64_t) hi) << 32) | lo; +} + +static uint64_t a3xx_perfcounter_read_vbif_pwr(struct adreno_device *adreno_dev, + unsigned int counter) +{ + struct adreno_perfcounters *counters = adreno_dev->gpudev->perfcounters; + struct kgsl_device *device = &adreno_dev->dev; + struct adreno_perfcount_register *reg; + unsigned int in, out, lo = 0, hi = 0; + + if (counter > 2) + return 0; + + /* freeze counter */ + kgsl_regread(device, A3XX_VBIF_PERF_CNT_EN, &in); + if (0 == counter) + out = (in & ~VBIF_PERF_PWR_CNT_0); + else + out = (in & ~VBIF_PERF_PWR_CNT_2); + kgsl_regwrite(device, A3XX_VBIF_PERF_CNT_EN, out); + + reg = &counters->groups[KGSL_PERFCOUNTER_GROUP_VBIF_PWR].regs[counter]; + kgsl_regread(device, reg->offset, &lo); + kgsl_regread(device, reg->offset + 1, &hi); + /* restore the perfcounter value */ + kgsl_regwrite(device, A3XX_VBIF_PERF_CNT_EN, in); + + return (((uint64_t) hi) << 32) | lo; } static uint64_t a3xx_perfcounter_read(struct adreno_device *adreno_dev, - unsigned int group, unsigned int counter, - unsigned int offset) + unsigned int group, unsigned int counter) { struct kgsl_device *device = &adreno_dev->dev; - struct a3xx_perfcounter_register *reg = NULL; + struct adreno_perfcount_register *reg; unsigned int lo = 0, hi = 0; - unsigned int val; + unsigned int offset; + unsigned int in, out; + + if (group == KGSL_PERFCOUNTER_GROUP_VBIF_PWR) + return a3xx_perfcounter_read_vbif_pwr(adreno_dev, counter); - if (group >= ARRAY_SIZE(a3xx_perfcounter_reglist)) + if (group == KGSL_PERFCOUNTER_GROUP_VBIF) + return a3xx_perfcounter_read_vbif(adreno_dev, counter); + + if (group == KGSL_PERFCOUNTER_GROUP_PWR) + return a3xx_perfcounter_read_pwr(adreno_dev, counter); + + if (group >= adreno_dev->gpudev->perfcounters->group_count) return 0; - if (counter >= a3xx_perfcounter_reglist[group].count) + if ((0 == adreno_dev->gpudev->perfcounters->groups[group].reg_count) || + (counter >= + adreno_dev->gpudev->perfcounters->groups[group].reg_count)) return 0; - reg = &(a3xx_perfcounter_reglist[group].regs[counter]); + reg = &(adreno_dev->gpudev->perfcounters->groups[group].regs[counter]); /* Freeze the counter */ - adreno_regread(device, A3XX_RBBM_PERFCTR_CTL, &val); - val &= ~reg->load_bit; - adreno_regwrite(device, A3XX_RBBM_PERFCTR_CTL, val); + kgsl_regread(device, A3XX_RBBM_PERFCTR_CTL, &in); + out = in & ~RBBM_PERFCTR_CTL_ENABLE; + kgsl_regwrite(device, A3XX_RBBM_PERFCTR_CTL, out); + offset = reg->offset; /* Read the values */ - adreno_regread(device, offset, &lo); - adreno_regread(device, offset + 1, &hi); + kgsl_regread(device, offset, &lo); + kgsl_regread(device, offset + 1, &hi); /* Re-Enable the counter */ - val |= reg->load_bit; - adreno_regwrite(device, A3XX_RBBM_PERFCTR_CTL, val); - + kgsl_regwrite(device, A3XX_RBBM_PERFCTR_CTL, in); return (((uint64_t) hi) << 32) | lo; } @@ -2969,14 +3462,21 @@ static struct { /* 26 to 31 - Unused */ }; -static irqreturn_t a3xx_irq_handler(struct adreno_device *adreno_dev) +/* + * a3xx_irq_handler() - Interrupt handler function + * @adreno_dev: Pointer to adreno device + * + * Interrupt handler for adreno device, this function is common between + * a3xx and a4xx devices + */ +irqreturn_t a3xx_irq_handler(struct adreno_device *adreno_dev) { struct kgsl_device *device = &adreno_dev->dev; irqreturn_t ret = IRQ_NONE; unsigned int status, tmp; int i; - adreno_regread(&adreno_dev->dev, A3XX_RBBM_INT_0_STATUS, &status); + adreno_readreg(adreno_dev, ADRENO_REG_RBBM_INT_0_STATUS, &status); for (tmp = status, i = 0; tmp && i < ARRAY_SIZE(a3xx_irq_funcs); i++) { if (tmp & 1) { @@ -2995,38 +3495,57 @@ static irqreturn_t a3xx_irq_handler(struct adreno_device *adreno_dev) trace_kgsl_a3xx_irq_status(device, status); if (status) - adreno_regwrite(&adreno_dev->dev, A3XX_RBBM_INT_CLEAR_CMD, - status); + adreno_writereg(adreno_dev, ADRENO_REG_RBBM_INT_CLEAR_CMD, + status); return ret; } -static void a3xx_irq_control(struct adreno_device *adreno_dev, int state) +/* + * a3xx_irq_control() - Function called to enable/disable interrupts + * @adreno_dev: Pointer to device whose interrupts are enabled/disabled + * @state: When set interrupts are enabled else disabled + * + * This function is common for a3xx and a4xx adreno devices + */ +void a3xx_irq_control(struct adreno_device *adreno_dev, int state) { - struct kgsl_device *device = &adreno_dev->dev; - if (state) - adreno_regwrite(device, A3XX_RBBM_INT_0_MASK, A3XX_INT_MASK); + adreno_writereg(adreno_dev, ADRENO_REG_RBBM_INT_0_MASK, + A3XX_INT_MASK); else - adreno_regwrite(device, A3XX_RBBM_INT_0_MASK, 0); + adreno_writereg(adreno_dev, ADRENO_REG_RBBM_INT_0_MASK, 0); } -static unsigned int a3xx_irq_pending(struct adreno_device *adreno_dev) +/* + * a3xx_irq_pending() - Checks if interrupt is generated by h/w + * @adreno_dev: Pointer to device whose interrupts are checked + * + * Returns true if interrupts are pending from device else 0. This + * function is shared by both a3xx and a4xx devices. + */ +unsigned int a3xx_irq_pending(struct adreno_device *adreno_dev) { unsigned int status; - adreno_regread(&adreno_dev->dev, A3XX_RBBM_INT_0_STATUS, &status); + adreno_readreg(adreno_dev, ADRENO_REG_RBBM_INT_0_STATUS, &status); return (status & A3XX_INT_MASK) ? 1 : 0; } -static unsigned int a3xx_busy_cycles(struct adreno_device *adreno_dev) +/* + * a3xx_busy_cycles() - Returns number of gpu cycles + * @adreno_dev: Pointer to device ehose cycles are checked + * + * Returns number of busy clycles since the last time this function is called + * Function is common between a3xx and a4xx devices + */ +unsigned int a3xx_busy_cycles(struct adreno_device *adreno_dev) { - struct kgsl_device *device = &adreno_dev->dev; unsigned int val; unsigned int ret = 0; /* Read the value */ - adreno_regread(device, A3XX_RBBM_PERFCTR_PWR_1_LO, &val); + adreno_readreg(adreno_dev, ADRENO_REG_RBBM_PERFCTR_PWR_1_LO, &val); /* Return 0 for the first read */ if (adreno_dev->gpu_cycles != 0) { @@ -3040,13 +3559,8 @@ static unsigned int a3xx_busy_cycles(struct adreno_device *adreno_dev) return ret; } -struct a3xx_vbif_data { - unsigned int reg; - unsigned int val; -}; - /* VBIF registers start after 0x3000 so use 0x0 as end of list marker */ -static struct a3xx_vbif_data a305_vbif[] = { +static const struct adreno_vbif_data a305_vbif[] = { /* Set up 16 deep read/write request queues */ { A3XX_VBIF_IN_RD_LIM_CONF0, 0x10101010 }, { A3XX_VBIF_IN_RD_LIM_CONF1, 0x10101010 }, @@ -3065,7 +3579,30 @@ static struct a3xx_vbif_data a305_vbif[] = { {0, 0}, }; -static struct a3xx_vbif_data a320_vbif[] = { +static const struct adreno_vbif_data a305b_vbif[] = { + { A3XX_VBIF_IN_RD_LIM_CONF0, 0x00181818 }, + { A3XX_VBIF_IN_WR_LIM_CONF0, 0x00181818 }, + { A3XX_VBIF_OUT_RD_LIM_CONF0, 0x00000018 }, + { A3XX_VBIF_OUT_WR_LIM_CONF0, 0x00000018 }, + { A3XX_VBIF_DDR_OUT_MAX_BURST, 0x00000303 }, + { A3XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x0003 }, + {0, 0}, +}; + +static const struct adreno_vbif_data a305c_vbif[] = { + { A3XX_VBIF_IN_RD_LIM_CONF0, 0x00101010 }, + { A3XX_VBIF_IN_WR_LIM_CONF0, 0x00101010 }, + { A3XX_VBIF_OUT_RD_LIM_CONF0, 0x00000010 }, + { A3XX_VBIF_OUT_WR_LIM_CONF0, 0x00000010 }, + { A3XX_VBIF_DDR_OUT_MAX_BURST, 0x00000101 }, + { A3XX_VBIF_ARB_CTL, 0x00000010 }, + /* Set up AOOO */ + { A3XX_VBIF_OUT_AXI_AOOO_EN, 0x00000007 }, + { A3XX_VBIF_OUT_AXI_AOOO, 0x00070007 }, + {0, 0}, +}; + +static const struct adreno_vbif_data a320_vbif[] = { /* Set up 16 deep read/write request queues */ { A3XX_VBIF_IN_RD_LIM_CONF0, 0x10101010 }, { A3XX_VBIF_IN_RD_LIM_CONF1, 0x10101010 }, @@ -3087,7 +3624,7 @@ static struct a3xx_vbif_data a320_vbif[] = { {0, 0}, }; -static struct a3xx_vbif_data a330_vbif[] = { +static const struct adreno_vbif_data a330_vbif[] = { /* Set up 16 deep read/write request queues */ { A3XX_VBIF_IN_RD_LIM_CONF0, 0x18181818 }, { A3XX_VBIF_IN_RD_LIM_CONF1, 0x00001818 }, @@ -3119,7 +3656,7 @@ static struct a3xx_vbif_data a330_vbif[] = { * Most of the VBIF registers on 8974v2 have the correct values at power on, so * we won't modify those if we don't need to */ -static struct a3xx_vbif_data a330v2_vbif[] = { +static const struct adreno_vbif_data a330v2_vbif[] = { /* Enable 1k sort */ { A3XX_VBIF_ABIT_SORT, 0x0001003F }, { A3XX_VBIF_ABIT_SORT_CONF, 0x000000A4 }, @@ -3128,26 +3665,214 @@ static struct a3xx_vbif_data a330v2_vbif[] = { { A3XX_VBIF_DDR_OUT_MAX_BURST, 0x0000303 }, /* Set up VBIF_ROUND_ROBIN_QOS_ARB */ { A3XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x0003 }, - /* Disable VBIF clock gating. This is to enable AXI running - * higher frequency than GPU. - */ - { A3XX_VBIF_CLKON, 1 }, {0, 0}, }; -static struct { - int(*devfunc)(struct adreno_device *); - struct a3xx_vbif_data *vbif; -} a3xx_vbif_platforms[] = { +const struct adreno_vbif_platform a3xx_vbif_platforms[] = { { adreno_is_a305, a305_vbif }, + { adreno_is_a305c, a305c_vbif }, { adreno_is_a320, a320_vbif }, /* A330v2 needs to be ahead of A330 so the right device matches */ { adreno_is_a330v2, a330v2_vbif }, { adreno_is_a330, a330_vbif }, + { adreno_is_a305b, a305b_vbif }, +}; + +/* + * Define the available perfcounter groups - these get used by + * adreno_perfcounter_get and adreno_perfcounter_put + */ + +static struct adreno_perfcount_register a3xx_perfcounters_cp[] = { + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_CP_0_LO, + 0, A3XX_CP_PERFCOUNTER_SELECT }, +}; + +static struct adreno_perfcount_register a3xx_perfcounters_rbbm[] = { + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_RBBM_0_LO, + 1, A3XX_RBBM_PERFCOUNTER0_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_RBBM_1_LO, + 2, A3XX_RBBM_PERFCOUNTER1_SELECT }, +}; + +static struct adreno_perfcount_register a3xx_perfcounters_pc[] = { + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_PC_0_LO, + 3, A3XX_PC_PERFCOUNTER0_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_PC_1_LO, + 4, A3XX_PC_PERFCOUNTER1_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_PC_2_LO, + 5, A3XX_PC_PERFCOUNTER2_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_PC_3_LO, + 6, A3XX_PC_PERFCOUNTER3_SELECT }, +}; + +static struct adreno_perfcount_register a3xx_perfcounters_vfd[] = { + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_VFD_0_LO, + 7, A3XX_VFD_PERFCOUNTER0_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_VFD_1_LO, + 8, A3XX_VFD_PERFCOUNTER1_SELECT }, +}; + +static struct adreno_perfcount_register a3xx_perfcounters_hlsq[] = { + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_HLSQ_0_LO, + 9, A3XX_HLSQ_PERFCOUNTER0_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_HLSQ_1_LO, + 10, A3XX_HLSQ_PERFCOUNTER1_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_HLSQ_2_LO, + 11, A3XX_HLSQ_PERFCOUNTER2_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_HLSQ_3_LO, + 12, A3XX_HLSQ_PERFCOUNTER3_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_HLSQ_4_LO, + 13, A3XX_HLSQ_PERFCOUNTER4_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_HLSQ_5_LO, + 14, A3XX_HLSQ_PERFCOUNTER5_SELECT }, +}; + +static struct adreno_perfcount_register a3xx_perfcounters_vpc[] = { + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_VPC_0_LO, + 15, A3XX_VPC_PERFCOUNTER0_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_VPC_1_LO, + 16, A3XX_VPC_PERFCOUNTER1_SELECT }, +}; + +static struct adreno_perfcount_register a3xx_perfcounters_tse[] = { + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_TSE_0_LO, + 17, A3XX_GRAS_PERFCOUNTER0_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_TSE_1_LO, + 18, A3XX_GRAS_PERFCOUNTER1_SELECT }, +}; + +static struct adreno_perfcount_register a3xx_perfcounters_ras[] = { + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_RAS_0_LO, + 19, A3XX_GRAS_PERFCOUNTER2_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_RAS_1_LO, + 20, A3XX_GRAS_PERFCOUNTER3_SELECT }, +}; + +static struct adreno_perfcount_register a3xx_perfcounters_uche[] = { + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_UCHE_0_LO, + 21, A3XX_UCHE_PERFCOUNTER0_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_UCHE_1_LO, + 22, A3XX_UCHE_PERFCOUNTER1_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_UCHE_2_LO, + 23, A3XX_UCHE_PERFCOUNTER2_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_UCHE_3_LO, + 24, A3XX_UCHE_PERFCOUNTER3_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_UCHE_4_LO, + 25, A3XX_UCHE_PERFCOUNTER4_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_UCHE_5_LO, + 26, A3XX_UCHE_PERFCOUNTER5_SELECT }, +}; + +static struct adreno_perfcount_register a3xx_perfcounters_tp[] = { + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_TP_0_LO, + 27, A3XX_TP_PERFCOUNTER0_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_TP_1_LO, + 28, A3XX_TP_PERFCOUNTER1_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_TP_2_LO, + 29, A3XX_TP_PERFCOUNTER2_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_TP_3_LO, + 30, A3XX_TP_PERFCOUNTER3_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_TP_4_LO, + 31, A3XX_TP_PERFCOUNTER4_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_TP_5_LO, + 32, A3XX_TP_PERFCOUNTER5_SELECT }, +}; + +static struct adreno_perfcount_register a3xx_perfcounters_sp[] = { + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_SP_0_LO, + 33, A3XX_SP_PERFCOUNTER0_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_SP_1_LO, + 34, A3XX_SP_PERFCOUNTER1_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_SP_2_LO, + 35, A3XX_SP_PERFCOUNTER2_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_SP_3_LO, + 36, A3XX_SP_PERFCOUNTER3_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_SP_4_LO, + 37, A3XX_SP_PERFCOUNTER4_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_SP_5_LO, + 38, A3XX_SP_PERFCOUNTER5_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_SP_6_LO, + 39, A3XX_SP_PERFCOUNTER6_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_SP_7_LO, + 40, A3XX_SP_PERFCOUNTER7_SELECT }, +}; + +static struct adreno_perfcount_register a3xx_perfcounters_rb[] = { + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_RB_0_LO, + 41, A3XX_RB_PERFCOUNTER0_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_RB_1_LO, + 42, A3XX_RB_PERFCOUNTER1_SELECT }, +}; + +static struct adreno_perfcount_register a3xx_perfcounters_pwr[] = { + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_PWR_0_LO, + -1, 0 }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_PWR_1_LO, + -1, 0 }, }; -static void a3xx_perfcounter_init(struct adreno_device *adreno_dev) +static struct adreno_perfcount_register a3xx_perfcounters_vbif[] = { + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_VBIF_PERF_CNT0_LO, -1, 0 }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_VBIF_PERF_CNT1_LO, -1, 0 }, +}; +static struct adreno_perfcount_register a3xx_perfcounters_vbif_pwr[] = { + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_VBIF_PERF_PWR_CNT0_LO, -1, 0 }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_VBIF_PERF_PWR_CNT1_LO, -1, 0 }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_VBIF_PERF_PWR_CNT2_LO, -1, 0 }, +}; + +static struct adreno_perfcount_group a3xx_perfcounter_groups[] = { + ADRENO_PERFCOUNTER_GROUP(a3xx, cp), + ADRENO_PERFCOUNTER_GROUP(a3xx, rbbm), + ADRENO_PERFCOUNTER_GROUP(a3xx, pc), + ADRENO_PERFCOUNTER_GROUP(a3xx, vfd), + ADRENO_PERFCOUNTER_GROUP(a3xx, hlsq), + ADRENO_PERFCOUNTER_GROUP(a3xx, vpc), + ADRENO_PERFCOUNTER_GROUP(a3xx, tse), + ADRENO_PERFCOUNTER_GROUP(a3xx, ras), + ADRENO_PERFCOUNTER_GROUP(a3xx, uche), + ADRENO_PERFCOUNTER_GROUP(a3xx, tp), + ADRENO_PERFCOUNTER_GROUP(a3xx, sp), + ADRENO_PERFCOUNTER_GROUP(a3xx, rb), + ADRENO_PERFCOUNTER_GROUP(a3xx, pwr), + ADRENO_PERFCOUNTER_GROUP(a3xx, vbif), + ADRENO_PERFCOUNTER_GROUP(a3xx, vbif_pwr), +}; + +static struct adreno_perfcounters a3xx_perfcounters = { + a3xx_perfcounter_groups, + ARRAY_SIZE(a3xx_perfcounter_groups), +}; + +/* + * a3xx_perfcounter_close() - Return counters that were initialized in + * a3xx_perfcounter_init + * @adreno_dev: The device for which counters were initialized + */ +static void a3xx_perfcounter_close(struct adreno_device *adreno_dev) +{ + adreno_perfcounter_put(adreno_dev, KGSL_PERFCOUNTER_GROUP_SP, + SP_FS_FULL_ALU_INSTRUCTIONS, + PERFCOUNTER_FLAG_KERNEL); + adreno_perfcounter_put(adreno_dev, KGSL_PERFCOUNTER_GROUP_SP, + SP_FS_CFLOW_INSTRUCTIONS, + PERFCOUNTER_FLAG_KERNEL); + adreno_perfcounter_put(adreno_dev, KGSL_PERFCOUNTER_GROUP_SP, + SP0_ICL1_MISSES, + PERFCOUNTER_FLAG_KERNEL); + adreno_perfcounter_put(adreno_dev, KGSL_PERFCOUNTER_GROUP_SP, + SP_ALU_ACTIVE_CYCLES, + PERFCOUNTER_FLAG_KERNEL); +} + +static int a3xx_perfcounter_init(struct adreno_device *adreno_dev) { + int ret; + /* SP[3] counter is broken on a330 so disable it if a330 device */ + if (adreno_is_a330(adreno_dev)) + a3xx_perfcounters_sp[3].countable = KGSL_PERFCOUNTER_BROKEN; + /* * Set SP to count SP_ALU_ACTIVE_CYCLES, it includes * all ALU instruction execution regardless precision or shader ID. @@ -3158,230 +3883,504 @@ static void a3xx_perfcounter_init(struct adreno_device *adreno_dev) * we will use this to augment our hang detection */ if (adreno_dev->fast_hang_detect) { - adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_SP, + ret = adreno_perfcounter_get(adreno_dev, + KGSL_PERFCOUNTER_GROUP_SP, SP_ALU_ACTIVE_CYCLES, &ft_detect_regs[6], PERFCOUNTER_FLAG_KERNEL); + if (ret) + goto err; ft_detect_regs[7] = ft_detect_regs[6] + 1; - adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_SP, + ret = adreno_perfcounter_get(adreno_dev, + KGSL_PERFCOUNTER_GROUP_SP, SP0_ICL1_MISSES, &ft_detect_regs[8], PERFCOUNTER_FLAG_KERNEL); + if (ret) + goto err; ft_detect_regs[9] = ft_detect_regs[8] + 1; - adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_SP, + ret = adreno_perfcounter_get(adreno_dev, + KGSL_PERFCOUNTER_GROUP_SP, SP_FS_CFLOW_INSTRUCTIONS, &ft_detect_regs[10], PERFCOUNTER_FLAG_KERNEL); + if (ret) + goto err; ft_detect_regs[11] = ft_detect_regs[10] + 1; } - adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_SP, + ret = adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_SP, SP_FS_FULL_ALU_INSTRUCTIONS, NULL, PERFCOUNTER_FLAG_KERNEL); + if (ret) + goto err; /* Reserve and start countable 1 in the PWR perfcounter group */ - adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_PWR, 1, + ret = adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_PWR, 1, NULL, PERFCOUNTER_FLAG_KERNEL); + if (ret) + goto err; + + return ret; + +err: + a3xx_perfcounter_close(adreno_dev); + return ret; +} + +/** + * a3xx_protect_init() - Initializes register protection on a3xx + * @device: Pointer to the device structure + * Performs register writes to enable protected access to sensitive + * registers + */ +static void a3xx_protect_init(struct kgsl_device *device) +{ + /* enable access protection to privileged registers */ + kgsl_regwrite(device, A3XX_CP_PROTECT_CTRL, 0x00000007); + + /* RBBM registers */ + kgsl_regwrite(device, A3XX_CP_PROTECT_REG_0, 0x63000040); + kgsl_regwrite(device, A3XX_CP_PROTECT_REG_1, 0x62000080); + kgsl_regwrite(device, A3XX_CP_PROTECT_REG_2, 0x600000CC); + kgsl_regwrite(device, A3XX_CP_PROTECT_REG_3, 0x60000108); + kgsl_regwrite(device, A3XX_CP_PROTECT_REG_4, 0x64000140); + kgsl_regwrite(device, A3XX_CP_PROTECT_REG_5, 0x66000400); + + /* CP registers */ + kgsl_regwrite(device, A3XX_CP_PROTECT_REG_6, 0x65000700); + kgsl_regwrite(device, A3XX_CP_PROTECT_REG_7, 0x610007D8); + kgsl_regwrite(device, A3XX_CP_PROTECT_REG_8, 0x620007E0); + kgsl_regwrite(device, A3XX_CP_PROTECT_REG_9, 0x61001178); + kgsl_regwrite(device, A3XX_CP_PROTECT_REG_A, 0x64001180); + + /* RB registers */ + kgsl_regwrite(device, A3XX_CP_PROTECT_REG_B, 0x60003300); + + /* VBIF registers */ + kgsl_regwrite(device, A3XX_CP_PROTECT_REG_C, 0x6B00C000); } static void a3xx_start(struct adreno_device *adreno_dev) { struct kgsl_device *device = &adreno_dev->dev; - struct a3xx_vbif_data *vbif = NULL; - int i; - - for (i = 0; i < ARRAY_SIZE(a3xx_vbif_platforms); i++) { - if (a3xx_vbif_platforms[i].devfunc(adreno_dev)) { - vbif = a3xx_vbif_platforms[i].vbif; - break; - } - } - BUG_ON(vbif == NULL); - - while (vbif->reg != 0) { - adreno_regwrite(device, vbif->reg, vbif->val); - vbif++; - } + adreno_vbif_start(device, a3xx_vbif_platforms, + ARRAY_SIZE(a3xx_vbif_platforms)); /* Make all blocks contribute to the GPU BUSY perf counter */ - adreno_regwrite(device, A3XX_RBBM_GPU_BUSY_MASKED, 0xFFFFFFFF); + kgsl_regwrite(device, A3XX_RBBM_GPU_BUSY_MASKED, 0xFFFFFFFF); /* Tune the hystersis counters for SP and CP idle detection */ - adreno_regwrite(device, A3XX_RBBM_SP_HYST_CNT, 0x10); - adreno_regwrite(device, A3XX_RBBM_WAIT_IDLE_CLOCKS_CTL, 0x10); + kgsl_regwrite(device, A3XX_RBBM_SP_HYST_CNT, 0x10); + kgsl_regwrite(device, A3XX_RBBM_WAIT_IDLE_CLOCKS_CTL, 0x10); /* Enable the RBBM error reporting bits. This lets us get useful information on failure */ - adreno_regwrite(device, A3XX_RBBM_AHB_CTL0, 0x00000001); + kgsl_regwrite(device, A3XX_RBBM_AHB_CTL0, 0x00000001); /* Enable AHB error reporting */ - adreno_regwrite(device, A3XX_RBBM_AHB_CTL1, 0xA6FFFFFF); + kgsl_regwrite(device, A3XX_RBBM_AHB_CTL1, 0xA6FFFFFF); /* Turn on the power counters */ - adreno_regwrite(device, A3XX_RBBM_RBBM_CTL, 0x00030000); + kgsl_regwrite(device, A3XX_RBBM_RBBM_CTL, 0x00030000); /* Turn on hang detection - this spews a lot of useful information * into the RBBM registers on a hang */ - adreno_regwrite(device, A3XX_RBBM_INTERFACE_HANG_INT_CTL, + kgsl_regwrite(device, A3XX_RBBM_INTERFACE_HANG_INT_CTL, (1 << 16) | 0xFFF); /* Enable 64-byte cacheline size. HW Default is 32-byte (0x000000E0). */ - adreno_regwrite(device, A3XX_UCHE_CACHE_MODE_CONTROL_REG, 0x00000001); + kgsl_regwrite(device, A3XX_UCHE_CACHE_MODE_CONTROL_REG, 0x00000001); /* Enable Clock gating */ - adreno_regwrite(device, A3XX_RBBM_CLOCK_CTL, + kgsl_regwrite(device, A3XX_RBBM_CLOCK_CTL, adreno_a3xx_rbbm_clock_ctl_default(adreno_dev)); if (adreno_is_a330v2(adreno_dev)) - adreno_regwrite(device, A3XX_RBBM_GPR0_CTL, + kgsl_regwrite(device, A3XX_RBBM_GPR0_CTL, A330v2_RBBM_GPR0_CTL_DEFAULT); else if (adreno_is_a330(adreno_dev)) - adreno_regwrite(device, A3XX_RBBM_GPR0_CTL, + kgsl_regwrite(device, A3XX_RBBM_GPR0_CTL, A330_RBBM_GPR0_CTL_DEFAULT); /* Set the OCMEM base address for A330 */ - if (adreno_is_a330(adreno_dev)) { - adreno_regwrite(device, A3XX_RB_GMEM_BASE_ADDR, + if (adreno_is_a330(adreno_dev) || + adreno_is_a305b(adreno_dev)) { + kgsl_regwrite(device, A3XX_RB_GMEM_BASE_ADDR, (unsigned int)(adreno_dev->ocmem_base >> 14)); } + /* Turn on protection */ + a3xx_protect_init(device); /* Turn on performance counters */ - adreno_regwrite(device, A3XX_RBBM_PERFCTR_CTL, 0x01); + kgsl_regwrite(device, A3XX_RBBM_PERFCTR_CTL, 0x01); /* Turn on the GPU busy counter and let it run free */ adreno_dev->gpu_cycles = 0; } -/* - * Define the available perfcounter groups - these get used by - * adreno_perfcounter_get and adreno_perfcounter_put +/** + * a3xx_coresight_enable() - Enables debugging through coresight + * debug bus for adreno a3xx devices. + * @device: Pointer to GPU device structure */ +int a3xx_coresight_enable(struct kgsl_device *device) +{ + mutex_lock(&device->mutex); + if (!kgsl_active_count_get(device)) { + kgsl_regwrite(device, A3XX_RBBM_DEBUG_BUS_CTL, 0x0001093F); + kgsl_regwrite(device, A3XX_RBBM_DEBUG_BUS_STB_CTL0, + 0x00000000); + kgsl_regwrite(device, A3XX_RBBM_DEBUG_BUS_STB_CTL1, + 0xFFFFFFFE); + kgsl_regwrite(device, A3XX_RBBM_INT_TRACE_BUS_CTL, + 0x00201111); + kgsl_regwrite(device, A3XX_RBBM_EXT_TRACE_BUS_CTL, + 0x89100010); + kgsl_regwrite(device, A3XX_RBBM_EXT_TRACE_STOP_CNT, + 0x00017fff); + kgsl_regwrite(device, A3XX_RBBM_EXT_TRACE_START_CNT, + 0x0001000f); + kgsl_regwrite(device, A3XX_RBBM_EXT_TRACE_PERIOD_CNT , + 0x0001ffff); + kgsl_regwrite(device, A3XX_RBBM_EXT_TRACE_CMD, + 0x00000001); + kgsl_active_count_put(device); + } + mutex_unlock(&device->mutex); + return 0; +} -static struct adreno_perfcount_register a3xx_perfcounters_cp[] = { - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_CP_0_LO, 0 }, -}; +/** + * a3xx_coresight_disable() - Disables debugging through coresight + * debug bus for adreno a3xx devices. + * @device: Pointer to GPU device structure + */ +void a3xx_coresight_disable(struct kgsl_device *device) +{ + mutex_lock(&device->mutex); + if (!kgsl_active_count_get(device)) { + kgsl_regwrite(device, A3XX_RBBM_DEBUG_BUS_CTL, 0x0); + kgsl_regwrite(device, A3XX_RBBM_DEBUG_BUS_STB_CTL0, 0x0); + kgsl_regwrite(device, A3XX_RBBM_DEBUG_BUS_STB_CTL1, 0x0); + kgsl_regwrite(device, A3XX_RBBM_INT_TRACE_BUS_CTL, 0x0); + kgsl_regwrite(device, A3XX_RBBM_EXT_TRACE_BUS_CTL, 0x0); + kgsl_regwrite(device, A3XX_RBBM_EXT_TRACE_STOP_CNT, 0x0); + kgsl_regwrite(device, A3XX_RBBM_EXT_TRACE_START_CNT, 0x0); + kgsl_regwrite(device, A3XX_RBBM_EXT_TRACE_PERIOD_CNT , 0x0); + kgsl_regwrite(device, A3XX_RBBM_EXT_TRACE_CMD, 0x0); + kgsl_active_count_put(device); + } + mutex_unlock(&device->mutex); +} -static struct adreno_perfcount_register a3xx_perfcounters_rbbm[] = { - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_RBBM_0_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_RBBM_1_LO, 0 }, -}; +static void a3xx_coresight_write_reg(struct kgsl_device *device, + unsigned int wordoffset, unsigned int val) +{ + mutex_lock(&device->mutex); + if (!kgsl_active_count_get(device)) { + kgsl_regwrite(device, wordoffset, val); + kgsl_active_count_put(device); + } + mutex_unlock(&device->mutex); +} -static struct adreno_perfcount_register a3xx_perfcounters_pc[] = { - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_PC_0_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_PC_1_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_PC_2_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_PC_3_LO, 0 }, -}; +void a3xx_coresight_config_debug_reg(struct kgsl_device *device, + int debug_reg, unsigned int val) +{ + switch (debug_reg) { -static struct adreno_perfcount_register a3xx_perfcounters_vfd[] = { - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_VFD_0_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_VFD_1_LO, 0 }, -}; + case DEBUG_BUS_CTL: + a3xx_coresight_write_reg(device, A3XX_RBBM_DEBUG_BUS_CTL, val); + break; -static struct adreno_perfcount_register a3xx_perfcounters_hlsq[] = { - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_HLSQ_0_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_HLSQ_1_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_HLSQ_2_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_HLSQ_3_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_HLSQ_4_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_HLSQ_5_LO, 0 }, -}; + case TRACE_STOP_CNT: + a3xx_coresight_write_reg(device, A3XX_RBBM_EXT_TRACE_STOP_CNT, + val); + break; -static struct adreno_perfcount_register a3xx_perfcounters_vpc[] = { - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_VPC_0_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_VPC_1_LO, 0 }, -}; + case TRACE_START_CNT: + a3xx_coresight_write_reg(device, A3XX_RBBM_EXT_TRACE_START_CNT, + val); + break; -static struct adreno_perfcount_register a3xx_perfcounters_tse[] = { - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_TSE_0_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_TSE_1_LO, 0 }, -}; + case TRACE_PERIOD_CNT: + a3xx_coresight_write_reg(device, A3XX_RBBM_EXT_TRACE_PERIOD_CNT, + val); + break; -static struct adreno_perfcount_register a3xx_perfcounters_ras[] = { - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_RAS_0_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_RAS_1_LO, 0 }, -}; + case TRACE_CMD: + a3xx_coresight_write_reg(device, A3XX_RBBM_EXT_TRACE_CMD, val); + break; -static struct adreno_perfcount_register a3xx_perfcounters_uche[] = { - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_UCHE_0_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_UCHE_1_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_UCHE_2_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_UCHE_3_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_UCHE_4_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_UCHE_5_LO, 0 }, -}; + case TRACE_BUS_CTL: + a3xx_coresight_write_reg(device, A3XX_RBBM_EXT_TRACE_BUS_CTL, + val); + break; + } -static struct adreno_perfcount_register a3xx_perfcounters_tp[] = { - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_TP_0_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_TP_1_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_TP_2_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_TP_3_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_TP_4_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_TP_5_LO, 0 }, -}; +} -static struct adreno_perfcount_register a3xx_perfcounters_sp[] = { - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_SP_0_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_SP_1_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_SP_2_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_SP_3_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_SP_4_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_SP_5_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_SP_6_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_SP_7_LO, 0 }, -}; +/* + * a3xx_soft_reset() - Soft reset GPU + * @adreno_dev: Pointer to adreno device + * + * Soft reset the GPU by doing a AHB write of value 1 to RBBM_SW_RESET + * register. This is used when we want to reset the GPU without + * turning off GFX power rail. The reset when asserted resets + * all the HW logic, restores GPU registers to default state and + * flushes out pending VBIF transactions. + */ +static void a3xx_soft_reset(struct adreno_device *adreno_dev) +{ + struct kgsl_device *device = &adreno_dev->dev; + unsigned int reg; -static struct adreno_perfcount_register a3xx_perfcounters_rb[] = { - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_RB_0_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_RB_1_LO, 0 }, -}; + kgsl_regwrite(device, A3XX_RBBM_SW_RESET_CMD, 1); + /* + * Do a dummy read to get a brief read cycle delay for the reset to take + * effect + */ + kgsl_regread(device, A3XX_RBBM_SW_RESET_CMD, ®); + kgsl_regwrite(device, A3XX_RBBM_SW_RESET_CMD, 0); +} -static struct adreno_perfcount_register a3xx_perfcounters_pwr[] = { - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_PWR_0_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_PWR_1_LO, 0 }, -}; +/* Defined in adreno_a3xx_snapshot.c */ +void *a3xx_snapshot(struct adreno_device *adreno_dev, void *snapshot, + int *remain, int hang); -static struct adreno_perfcount_register a3xx_perfcounters_vbif[] = { - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_VBIF_PERF_CNT0_LO }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_VBIF_PERF_CNT1_LO }, -}; -static struct adreno_perfcount_register a3xx_perfcounters_vbif_pwr[] = { - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_VBIF_PERF_PWR_CNT0_LO }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_VBIF_PERF_PWR_CNT1_LO }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_VBIF_PERF_PWR_CNT2_LO }, -}; +static void a3xx_postmortem_dump(struct adreno_device *adreno_dev) +{ + struct kgsl_device *device = &adreno_dev->dev; + unsigned int r1, r2, r3, rbbm_status; + unsigned int cp_stat, rb_count; + + kgsl_regread(device, REG_RBBM_STATUS, &rbbm_status); + KGSL_LOG_DUMP(device, "RBBM: STATUS = %08X\n", rbbm_status); + + { + struct log_field lines[] = { + {rbbm_status & BIT(0), "HI busy "}, + {rbbm_status & BIT(1), "CP ME busy "}, + {rbbm_status & BIT(2), "CP PFP busy "}, + {rbbm_status & BIT(14), "CP NRT busy "}, + {rbbm_status & BIT(15), "VBIF busy "}, + {rbbm_status & BIT(16), "TSE busy "}, + {rbbm_status & BIT(17), "RAS busy "}, + {rbbm_status & BIT(18), "RB busy "}, + {rbbm_status & BIT(19), "PC DCALL bsy"}, + {rbbm_status & BIT(20), "PC VSD busy "}, + {rbbm_status & BIT(21), "VFD busy "}, + {rbbm_status & BIT(22), "VPC busy "}, + {rbbm_status & BIT(23), "UCHE busy "}, + {rbbm_status & BIT(24), "SP busy "}, + {rbbm_status & BIT(25), "TPL1 busy "}, + {rbbm_status & BIT(26), "MARB busy "}, + {rbbm_status & BIT(27), "VSC busy "}, + {rbbm_status & BIT(28), "ARB busy "}, + {rbbm_status & BIT(29), "HLSQ busy "}, + {rbbm_status & BIT(30), "GPU bsy noHC"}, + {rbbm_status & BIT(31), "GPU busy "}, + }; + adreno_dump_fields(device, " STATUS=", lines, + ARRAY_SIZE(lines)); + } -static struct adreno_perfcount_group a3xx_perfcounter_groups[] = { - { a3xx_perfcounters_cp, ARRAY_SIZE(a3xx_perfcounters_cp) }, - { a3xx_perfcounters_rbbm, ARRAY_SIZE(a3xx_perfcounters_rbbm) }, - { a3xx_perfcounters_pc, ARRAY_SIZE(a3xx_perfcounters_pc) }, - { a3xx_perfcounters_vfd, ARRAY_SIZE(a3xx_perfcounters_vfd) }, - { a3xx_perfcounters_hlsq, ARRAY_SIZE(a3xx_perfcounters_hlsq) }, - { a3xx_perfcounters_vpc, ARRAY_SIZE(a3xx_perfcounters_vpc) }, - { a3xx_perfcounters_tse, ARRAY_SIZE(a3xx_perfcounters_tse) }, - { a3xx_perfcounters_ras, ARRAY_SIZE(a3xx_perfcounters_ras) }, - { a3xx_perfcounters_uche, ARRAY_SIZE(a3xx_perfcounters_uche) }, - { a3xx_perfcounters_tp, ARRAY_SIZE(a3xx_perfcounters_tp) }, - { a3xx_perfcounters_sp, ARRAY_SIZE(a3xx_perfcounters_sp) }, - { a3xx_perfcounters_rb, ARRAY_SIZE(a3xx_perfcounters_rb) }, - { a3xx_perfcounters_pwr, ARRAY_SIZE(a3xx_perfcounters_pwr) }, - { a3xx_perfcounters_vbif, ARRAY_SIZE(a3xx_perfcounters_vbif) }, - { a3xx_perfcounters_vbif_pwr, ARRAY_SIZE(a3xx_perfcounters_vbif_pwr) }, -}; + kgsl_regread(device, REG_CP_RB_BASE, &r1); + kgsl_regread(device, REG_CP_RB_CNTL, &r2); + rb_count = 2 << (r2 & (BIT(6) - 1)); + kgsl_regread(device, REG_CP_RB_RPTR_ADDR, &r3); + KGSL_LOG_DUMP(device, + "CP_RB: BASE = %08X | CNTL = %08X | RPTR_ADDR = %08X" + "| rb_count = %08X\n", r1, r2, r3, rb_count); + + kgsl_regread(device, REG_CP_RB_RPTR, &r1); + kgsl_regread(device, REG_CP_RB_WPTR, &r2); + kgsl_regread(device, REG_CP_RB_RPTR_WR, &r3); + KGSL_LOG_DUMP(device, + "CP_RB: BASE = %08X | CNTL = %08X | RPTR_ADDR = %08X" + "| rb_count = %08X\n", r1, r2, r3, rb_count); + + kgsl_regread(device, REG_CP_RB_RPTR, &r1); + kgsl_regread(device, REG_CP_RB_WPTR, &r2); + kgsl_regread(device, REG_CP_RB_RPTR_WR, &r3); + KGSL_LOG_DUMP(device, + " RPTR = %08X | WPTR = %08X | RPTR_WR = %08X" + "\n", r1, r2, r3); + + kgsl_regread(device, REG_CP_IB1_BASE, &r1); + kgsl_regread(device, REG_CP_IB1_BUFSZ, &r2); + KGSL_LOG_DUMP(device, "CP_IB1: BASE = %08X | BUFSZ = %d\n", r1, r2); + + kgsl_regread(device, REG_CP_ME_CNTL, &r1); + kgsl_regread(device, REG_CP_ME_STATUS, &r2); + KGSL_LOG_DUMP(device, "CP_ME: CNTL = %08X | STATUS = %08X\n", r1, r2); + + kgsl_regread(device, REG_CP_STAT, &cp_stat); + KGSL_LOG_DUMP(device, "CP_STAT = %08X\n", cp_stat); +#ifndef CONFIG_MSM_KGSL_PSTMRTMDMP_CP_STAT_NO_DETAIL + { + struct log_field lns[] = { + {cp_stat & BIT(0), "WR_BSY 0"}, + {cp_stat & BIT(1), "RD_RQ_BSY 1"}, + {cp_stat & BIT(2), "RD_RTN_BSY 2"}, + }; + adreno_dump_fields(device, " MIU=", lns, ARRAY_SIZE(lns)); + } + { + struct log_field lns[] = { + {cp_stat & BIT(5), "RING_BUSY 5"}, + {cp_stat & BIT(6), "NDRCTS_BSY 6"}, + {cp_stat & BIT(7), "NDRCT2_BSY 7"}, + {cp_stat & BIT(9), "ST_BUSY 9"}, + {cp_stat & BIT(10), "BUSY 10"}, + }; + adreno_dump_fields(device, " CSF=", lns, ARRAY_SIZE(lns)); + } + { + struct log_field lns[] = { + {cp_stat & BIT(11), "RNG_Q_BSY 11"}, + {cp_stat & BIT(12), "NDRCTS_Q_B12"}, + {cp_stat & BIT(13), "NDRCT2_Q_B13"}, + {cp_stat & BIT(16), "ST_QUEUE_B16"}, + {cp_stat & BIT(17), "PFP_BUSY 17"}, + }; + adreno_dump_fields(device, " RING=", lns, ARRAY_SIZE(lns)); + } + { + struct log_field lns[] = { + {cp_stat & BIT(3), "RBIU_BUSY 3"}, + {cp_stat & BIT(4), "RCIU_BUSY 4"}, + {cp_stat & BIT(8), "EVENT_BUSY 8"}, + {cp_stat & BIT(18), "MQ_RG_BSY 18"}, + {cp_stat & BIT(19), "MQ_NDRS_BS19"}, + {cp_stat & BIT(20), "MQ_NDR2_BS20"}, + {cp_stat & BIT(21), "MIU_WC_STL21"}, + {cp_stat & BIT(22), "CP_NRT_BSY22"}, + {cp_stat & BIT(23), "3D_BUSY 23"}, + {cp_stat & BIT(26), "ME_BUSY 26"}, + {cp_stat & BIT(27), "RB_FFO_BSY27"}, + {cp_stat & BIT(28), "CF_FFO_BSY28"}, + {cp_stat & BIT(29), "PS_FFO_BSY29"}, + {cp_stat & BIT(30), "VS_FFO_BSY30"}, + {cp_stat & BIT(31), "CP_BUSY 31"}, + }; + adreno_dump_fields(device, " CP_STT=", lns, ARRAY_SIZE(lns)); + } +#endif -static struct adreno_perfcounters a3xx_perfcounters = { - a3xx_perfcounter_groups, - ARRAY_SIZE(a3xx_perfcounter_groups), + kgsl_regread(device, A3XX_RBBM_INT_0_STATUS, &r1); + KGSL_LOG_DUMP(device, "MSTR_INT_SGNL = %08X\n", r1); + { + struct log_field ints[] = { + {r1 & BIT(0), "RBBM_GPU_IDLE 0"}, + {r1 & BIT(1), "RBBM_AHB_ERROR 1"}, + {r1 & BIT(2), "RBBM_REG_TIMEOUT 2"}, + {r1 & BIT(3), "RBBM_ME_MS_TIMEOUT 3"}, + {r1 & BIT(4), "RBBM_PFP_MS_TIMEOUT 4"}, + {r1 & BIT(5), "RBBM_ATB_BUS_OVERFLOW 5"}, + {r1 & BIT(6), "VFD_ERROR 6"}, + {r1 & BIT(7), "CP_SW_INT 7"}, + {r1 & BIT(8), "CP_T0_PACKET_IN_IB 8"}, + {r1 & BIT(9), "CP_OPCODE_ERROR 9"}, + {r1 & BIT(10), "CP_RESERVED_BIT_ERROR 10"}, + {r1 & BIT(11), "CP_HW_FAULT 11"}, + {r1 & BIT(12), "CP_DMA 12"}, + {r1 & BIT(13), "CP_IB2_INT 13"}, + {r1 & BIT(14), "CP_IB1_INT 14"}, + {r1 & BIT(15), "CP_RB_INT 15"}, + {r1 & BIT(16), "CP_REG_PROTECT_FAULT 16"}, + {r1 & BIT(17), "CP_RB_DONE_TS 17"}, + {r1 & BIT(18), "CP_VS_DONE_TS 18"}, + {r1 & BIT(19), "CP_PS_DONE_TS 19"}, + {r1 & BIT(20), "CACHE_FLUSH_TS 20"}, + {r1 & BIT(21), "CP_AHB_ERROR_HALT 21"}, + {r1 & BIT(24), "MISC_HANG_DETECT 24"}, + {r1 & BIT(25), "UCHE_OOB_ACCESS 25"}, + }; + adreno_dump_fields(device, "INT_SGNL=", ints, ARRAY_SIZE(ints)); + } +} + +/* Register offset defines for A3XX */ +static unsigned int a3xx_register_offsets[ADRENO_REG_REGISTER_MAX] = { + ADRENO_REG_DEFINE(ADRENO_REG_CP_DEBUG, REG_CP_DEBUG), + ADRENO_REG_DEFINE(ADRENO_REG_CP_ME_RAM_WADDR, REG_CP_ME_RAM_WADDR), + ADRENO_REG_DEFINE(ADRENO_REG_CP_ME_RAM_DATA, REG_CP_ME_RAM_DATA), + ADRENO_REG_DEFINE(ADRENO_REG_CP_PFP_UCODE_DATA, A3XX_CP_PFP_UCODE_DATA), + ADRENO_REG_DEFINE(ADRENO_REG_CP_PFP_UCODE_ADDR, A3XX_CP_PFP_UCODE_ADDR), + ADRENO_REG_DEFINE(ADRENO_REG_CP_WFI_PEND_CTR, A3XX_CP_WFI_PEND_CTR), + ADRENO_REG_DEFINE(ADRENO_REG_CP_RB_BASE, REG_CP_RB_BASE), + ADRENO_REG_DEFINE(ADRENO_REG_CP_RB_RPTR_ADDR, REG_CP_RB_RPTR_ADDR), + ADRENO_REG_DEFINE(ADRENO_REG_CP_RB_RPTR, REG_CP_RB_RPTR), + ADRENO_REG_DEFINE(ADRENO_REG_CP_RB_WPTR, REG_CP_RB_WPTR), + ADRENO_REG_DEFINE(ADRENO_REG_CP_PROTECT_CTRL, A3XX_CP_PROTECT_CTRL), + ADRENO_REG_DEFINE(ADRENO_REG_CP_ME_CNTL, REG_CP_ME_CNTL), + ADRENO_REG_DEFINE(ADRENO_REG_CP_RB_CNTL, REG_CP_RB_CNTL), + ADRENO_REG_DEFINE(ADRENO_REG_CP_IB1_BASE, REG_CP_IB1_BASE), + ADRENO_REG_DEFINE(ADRENO_REG_CP_IB1_BUFSZ, REG_CP_IB1_BUFSZ), + ADRENO_REG_DEFINE(ADRENO_REG_CP_IB2_BASE, REG_CP_IB2_BASE), + ADRENO_REG_DEFINE(ADRENO_REG_CP_IB2_BUFSZ, REG_CP_IB2_BUFSZ), + ADRENO_REG_DEFINE(ADRENO_REG_CP_TIMESTAMP, REG_CP_TIMESTAMP), + ADRENO_REG_DEFINE(ADRENO_REG_CP_ME_RAM_RADDR, REG_CP_ME_RAM_RADDR), + ADRENO_REG_DEFINE(ADRENO_REG_SCRATCH_ADDR, REG_SCRATCH_ADDR), + ADRENO_REG_DEFINE(ADRENO_REG_SCRATCH_UMSK, REG_SCRATCH_UMSK), + ADRENO_REG_DEFINE(ADRENO_REG_RBBM_STATUS, A3XX_RBBM_STATUS), + ADRENO_REG_DEFINE(ADRENO_REG_RBBM_PERFCTR_CTL, A3XX_RBBM_PERFCTR_CTL), + ADRENO_REG_DEFINE(ADRENO_REG_RBBM_PERFCTR_LOAD_CMD0, + A3XX_RBBM_PERFCTR_LOAD_CMD0), + ADRENO_REG_DEFINE(ADRENO_REG_RBBM_PERFCTR_LOAD_CMD1, + A3XX_RBBM_PERFCTR_LOAD_CMD1), + ADRENO_REG_DEFINE(ADRENO_REG_RBBM_PERFCTR_PWR_1_LO, + A3XX_RBBM_PERFCTR_PWR_1_LO), + ADRENO_REG_DEFINE(ADRENO_REG_RBBM_INT_0_MASK, A3XX_RBBM_INT_0_MASK), + ADRENO_REG_DEFINE(ADRENO_REG_RBBM_INT_0_STATUS, A3XX_RBBM_INT_0_STATUS), + ADRENO_REG_DEFINE(ADRENO_REG_RBBM_AHB_ERROR_STATUS, + A3XX_RBBM_AHB_ERROR_STATUS), + ADRENO_REG_DEFINE(ADRENO_REG_RBBM_AHB_CMD, A3XX_RBBM_AHB_CMD), + ADRENO_REG_DEFINE(ADRENO_REG_RBBM_INT_CLEAR_CMD, + A3XX_RBBM_INT_CLEAR_CMD), + ADRENO_REG_DEFINE(ADRENO_REG_VPC_DEBUG_RAM_SEL, + A3XX_VPC_VPC_DEBUG_RAM_SEL), + ADRENO_REG_DEFINE(ADRENO_REG_VPC_DEBUG_RAM_READ, + A3XX_VPC_VPC_DEBUG_RAM_READ), + ADRENO_REG_DEFINE(ADRENO_REG_VSC_PIPE_DATA_ADDRESS_0, + A3XX_VSC_PIPE_DATA_ADDRESS_0), + ADRENO_REG_DEFINE(ADRENO_REG_VSC_PIPE_DATA_LENGTH_7, + A3XX_VSC_PIPE_DATA_LENGTH_7), + ADRENO_REG_DEFINE(ADRENO_REG_VSC_SIZE_ADDRESS, A3XX_VSC_SIZE_ADDRESS), + ADRENO_REG_DEFINE(ADRENO_REG_VFD_CONTROL_0, A3XX_VFD_CONTROL_0), + ADRENO_REG_DEFINE(ADRENO_REG_VFD_FETCH_INSTR_0_0, + A3XX_VFD_FETCH_INSTR_0_0), + ADRENO_REG_DEFINE(ADRENO_REG_VFD_FETCH_INSTR_1_F, + A3XX_VFD_FETCH_INSTR_1_F), + ADRENO_REG_DEFINE(ADRENO_REG_VFD_INDEX_MAX, A3XX_VFD_INDEX_MAX), + ADRENO_REG_DEFINE(ADRENO_REG_SP_VS_PVT_MEM_ADDR_REG, + A3XX_SP_VS_PVT_MEM_ADDR_REG), + ADRENO_REG_DEFINE(ADRENO_REG_SP_FS_PVT_MEM_ADDR_REG, + A3XX_SP_FS_PVT_MEM_ADDR_REG), + ADRENO_REG_DEFINE(ADRENO_REG_SP_VS_OBJ_START_REG, + A3XX_SP_VS_OBJ_START_REG), + ADRENO_REG_DEFINE(ADRENO_REG_SP_FS_OBJ_START_REG, + A3XX_SP_FS_OBJ_START_REG), + ADRENO_REG_DEFINE(ADRENO_REG_PA_SC_AA_CONFIG, REG_PA_SC_AA_CONFIG), + ADRENO_REG_DEFINE(ADRENO_REG_RBBM_PM_OVERRIDE2, REG_RBBM_PM_OVERRIDE2), + ADRENO_REG_DEFINE(ADRENO_REG_SCRATCH_REG2, REG_SCRATCH_REG2), + ADRENO_REG_DEFINE(ADRENO_REG_SQ_GPR_MANAGEMENT, REG_SQ_GPR_MANAGEMENT), + ADRENO_REG_DEFINE(ADRENO_REG_SQ_INST_STORE_MANAGMENT, + REG_SQ_INST_STORE_MANAGMENT), + ADRENO_REG_DEFINE(ADRENO_REG_TC_CNTL_STATUS, REG_TC_CNTL_STATUS), + ADRENO_REG_DEFINE(ADRENO_REG_TP0_CHICKEN, REG_TP0_CHICKEN), + ADRENO_REG_DEFINE(ADRENO_REG_RBBM_RBBM_CTL, A3XX_RBBM_RBBM_CTL), }; -/* Defined in adreno_a3xx_snapshot.c */ -void *a3xx_snapshot(struct adreno_device *adreno_dev, void *snapshot, - int *remain, int hang); +const struct adreno_reg_offsets a3xx_reg_offsets = { + .offsets = a3xx_register_offsets, + .offset_0 = ADRENO_REG_REGISTER_MAX, +}; struct adreno_gpudev adreno_a3xx_gpudev = { - .reg_rbbm_status = A3XX_RBBM_STATUS, - .reg_cp_pfp_ucode_addr = A3XX_CP_PFP_UCODE_ADDR, - .reg_cp_pfp_ucode_data = A3XX_CP_PFP_UCODE_DATA, + .reg_offsets = &a3xx_reg_offsets, .perfcounters = &a3xx_perfcounters, .ctxt_create = a3xx_drawctxt_create, @@ -3390,6 +4389,7 @@ struct adreno_gpudev adreno_a3xx_gpudev = { .ctxt_draw_workaround = NULL, .rb_init = a3xx_rb_init, .perfcounter_init = a3xx_perfcounter_init, + .perfcounter_close = a3xx_perfcounter_close, .irq_control = a3xx_irq_control, .irq_handler = a3xx_irq_handler, .irq_pending = a3xx_irq_pending, @@ -3398,4 +4398,9 @@ struct adreno_gpudev adreno_a3xx_gpudev = { .snapshot = a3xx_snapshot, .perfcounter_enable = a3xx_perfcounter_enable, .perfcounter_read = a3xx_perfcounter_read, + .coresight_enable = a3xx_coresight_enable, + .coresight_disable = a3xx_coresight_disable, + .coresight_config_debug_reg = a3xx_coresight_config_debug_reg, + .postmortem_dump = a3xx_postmortem_dump, + .soft_reset = a3xx_soft_reset, }; diff --git a/drivers/gpu/msm/adreno_a3xx.h b/drivers/gpu/msm/adreno_a3xx.h new file mode 100644 index 00000000000..fbd28e2bcdf --- /dev/null +++ b/drivers/gpu/msm/adreno_a3xx.h @@ -0,0 +1,25 @@ +/* Copyright (c) 2013, The Linux Foundation. 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 and + * only 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. + * + */ +#ifndef __A3XX_H +#define __A3XX_H + +void a3xx_err_callback(struct adreno_device *adreno_dev, int bit); +irqreturn_t a3xx_irq_handler(struct adreno_device *adreno_dev); +void a3xx_irq_control(struct adreno_device *adreno_dev, int state); +unsigned int a3xx_irq_pending(struct adreno_device *adreno_dev); +unsigned int a3xx_busy_cycles(struct adreno_device *adreno_dev); + +int a3xx_rb_init(struct adreno_device *adreno_dev, + struct adreno_ringbuffer *rb); + +#endif /*__A3XX_H */ diff --git a/drivers/gpu/msm/adreno_a3xx_snapshot.c b/drivers/gpu/msm/adreno_a3xx_snapshot.c index 34cac794447..ba0ef6a185b 100644 --- a/drivers/gpu/msm/adreno_a3xx_snapshot.c +++ b/drivers/gpu/msm/adreno_a3xx_snapshot.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2013, The Linux Foundation. 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 and @@ -11,6 +11,7 @@ * */ +#include #include "kgsl.h" #include "adreno.h" #include "kgsl_snapshot.h" @@ -19,6 +20,7 @@ #define DEBUG_SECTION_SZ(_dwords) (((_dwords) * sizeof(unsigned int)) \ + sizeof(struct kgsl_snapshot_debug)) +/* Shader memory size in words */ #define SHADER_MEMORY_SIZE 0x4000 /** @@ -33,16 +35,28 @@ static void _rbbm_debug_bus_read(struct kgsl_device *device, unsigned int block_id, unsigned int index, unsigned int *val) { unsigned int block = (block_id << 8) | 1 << 16; - adreno_regwrite(device, A3XX_RBBM_DEBUG_BUS_CTL, block | index); - adreno_regread(device, A3XX_RBBM_DEBUG_BUS_DATA_STATUS, val); + kgsl_regwrite(device, A3XX_RBBM_DEBUG_BUS_CTL, block | index); + kgsl_regread(device, A3XX_RBBM_DEBUG_BUS_DATA_STATUS, val); } +/** + * a3xx_snapshot_shader_memory - Helper function to dump the GPU shader + * memory to the snapshot buffer. + * @device - GPU device whose shader memory is to be dumped + * @snapshot - Pointer to binary snapshot data blob being made + * @remain - Number of remaining bytes in the snapshot blob + * @priv - Unused parameter + */ static int a3xx_snapshot_shader_memory(struct kgsl_device *device, void *snapshot, int remain, void *priv) { struct kgsl_snapshot_debug *header = snapshot; + unsigned int i; unsigned int *data = snapshot + sizeof(*header); - int i; + unsigned int shader_read_len = SHADER_MEMORY_SIZE; + + if (SHADER_MEMORY_SIZE > (device->shader_mem_len >> 2)) + shader_read_len = (device->shader_mem_len >> 2); if (remain < DEBUG_SECTION_SZ(SHADER_MEMORY_SIZE)) { SNAPSHOT_ERR_NOMEM(device, "SHADER MEMORY"); @@ -52,8 +66,22 @@ static int a3xx_snapshot_shader_memory(struct kgsl_device *device, header->type = SNAPSHOT_DEBUG_SHADER_MEMORY; header->size = SHADER_MEMORY_SIZE; - for (i = 0; i < SHADER_MEMORY_SIZE; i++) - adreno_regread(device, 0x4000 + i, &data[i]); + /* Map shader memory to kernel, for dumping */ + if (device->shader_mem_virt == NULL) + device->shader_mem_virt = devm_ioremap(device->dev, + device->shader_mem_phys, + device->shader_mem_len); + + if (device->shader_mem_virt == NULL) { + KGSL_DRV_ERR(device, + "Unable to map shader memory region\n"); + return 0; + } + + /* Now, dump shader memory to snapshot */ + for (i = 0; i < shader_read_len; i++) + adreno_shadermem_regread(device, i, &data[i]); + return DEBUG_SECTION_SZ(SHADER_MEMORY_SIZE); } @@ -80,9 +108,9 @@ static int a3xx_snapshot_vpc_memory(struct kgsl_device *device, void *snapshot, for (bank = 0; bank < VPC_MEMORY_BANKS; bank++) { for (addr = 0; addr < VPC_MEMORY_SIZE; addr++) { unsigned int val = bank | (addr << 4); - adreno_regwrite(device, + kgsl_regwrite(device, A3XX_VPC_VPC_DEBUG_RAM_SEL, val); - adreno_regread(device, + kgsl_regread(device, A3XX_VPC_VPC_DEBUG_RAM_READ, &data[i++]); } } @@ -106,9 +134,9 @@ static int a3xx_snapshot_cp_meq(struct kgsl_device *device, void *snapshot, header->type = SNAPSHOT_DEBUG_CP_MEQ; header->size = CP_MEQ_SIZE; - adreno_regwrite(device, A3XX_CP_MEQ_ADDR, 0x0); + kgsl_regwrite(device, A3XX_CP_MEQ_ADDR, 0x0); for (i = 0; i < CP_MEQ_SIZE; i++) - adreno_regread(device, A3XX_CP_MEQ_DATA, &data[i]); + kgsl_regread(device, A3XX_CP_MEQ_DATA, &data[i]); return DEBUG_SECTION_SZ(CP_MEQ_SIZE); } @@ -136,9 +164,9 @@ static int a3xx_snapshot_cp_pm4_ram(struct kgsl_device *device, void *snapshot, * maintain always changing hardcoded constants */ - adreno_regwrite(device, REG_CP_ME_RAM_RADDR, 0x0); + kgsl_regwrite(device, REG_CP_ME_RAM_RADDR, 0x0); for (i = 0; i < size; i++) - adreno_regread(device, REG_CP_ME_RAM_DATA, &data[i]); + kgsl_regread(device, REG_CP_ME_RAM_DATA, &data[i]); return DEBUG_SECTION_SZ(size); } @@ -167,7 +195,7 @@ static int a3xx_snapshot_cp_pfp_ram(struct kgsl_device *device, void *snapshot, */ kgsl_regwrite(device, A3XX_CP_PFP_UCODE_ADDR, 0x0); for (i = 0; i < size; i++) - adreno_regread(device, A3XX_CP_PFP_UCODE_DATA, &data[i]); + kgsl_regread(device, A3XX_CP_PFP_UCODE_DATA, &data[i]); return DEBUG_SECTION_SZ(size); } @@ -186,7 +214,8 @@ static int a3xx_snapshot_cp_roq(struct kgsl_device *device, void *snapshot, int i, size; /* The size of the ROQ buffer is core dependent */ - size = adreno_is_a330(adreno_dev) ? + size = (adreno_is_a330(adreno_dev) || + adreno_is_a305b(adreno_dev)) ? A330_CP_ROQ_SIZE : A320_CP_ROQ_SIZE; if (remain < DEBUG_SECTION_SZ(size)) { @@ -197,9 +226,9 @@ static int a3xx_snapshot_cp_roq(struct kgsl_device *device, void *snapshot, header->type = SNAPSHOT_DEBUG_CP_ROQ; header->size = size; - adreno_regwrite(device, A3XX_CP_ROQ_ADDR, 0x0); + kgsl_regwrite(device, A3XX_CP_ROQ_ADDR, 0x0); for (i = 0; i < size; i++) - adreno_regread(device, A3XX_CP_ROQ_DATA, &data[i]); + kgsl_regread(device, A3XX_CP_ROQ_DATA, &data[i]); return DEBUG_SECTION_SZ(size); } @@ -224,75 +253,92 @@ static int a330_snapshot_cp_merciu(struct kgsl_device *device, void *snapshot, header->type = SNAPSHOT_DEBUG_CP_MERCIU; header->size = size; - adreno_regwrite(device, A3XX_CP_MERCIU_ADDR, 0x0); + kgsl_regwrite(device, A3XX_CP_MERCIU_ADDR, 0x0); for (i = 0; i < A330_CP_MERCIU_QUEUE_SIZE; i++) { - adreno_regread(device, A3XX_CP_MERCIU_DATA, + kgsl_regread(device, A3XX_CP_MERCIU_DATA, &data[(i * 2)]); - adreno_regread(device, A3XX_CP_MERCIU_DATA2, + kgsl_regread(device, A3XX_CP_MERCIU_DATA2, &data[(i * 2) + 1]); } return DEBUG_SECTION_SZ(size); } -#define DEBUGFS_BLOCK_SIZE 0x40 +struct debugbus_block { + unsigned int block_id; + unsigned int dwords; +}; static int a3xx_snapshot_debugbus_block(struct kgsl_device *device, void *snapshot, int remain, void *priv) { + struct adreno_device *adreno_dev = ADRENO_DEVICE(device); + struct kgsl_snapshot_debugbus *header = snapshot; - unsigned int id = (unsigned int) priv; + struct debugbus_block *block = priv; unsigned int val; int i; unsigned int *data = snapshot + sizeof(*header); - int size = - (DEBUGFS_BLOCK_SIZE * sizeof(unsigned int)) + sizeof(*header); + unsigned int dwords; + int size; + + /* + * For A305 and A320 all debug bus regions are the same size (0x40). For + * A330, they can be different sizes - most are still 0x40, but some + * like CP are larger + */ + + dwords = (adreno_is_a330(adreno_dev) || + adreno_is_a305b(adreno_dev)) ? + block->dwords : 0x40; + + size = (dwords * sizeof(unsigned int)) + sizeof(*header); if (remain < size) { SNAPSHOT_ERR_NOMEM(device, "DEBUGBUS"); return 0; } - val = (id << 8) | (1 << 16); + val = (block->block_id << 8) | (1 << 16); - header->id = id; - header->count = DEBUGFS_BLOCK_SIZE; + header->id = block->block_id; + header->count = dwords; - for (i = 0; i < DEBUGFS_BLOCK_SIZE; i++) - _rbbm_debug_bus_read(device, id, i, &data[i]); + for (i = 0; i < dwords; i++) + _rbbm_debug_bus_read(device, block->block_id, i, &data[i]); return size; } -static unsigned int debugbus_blocks[] = { - RBBM_BLOCK_ID_CP, - RBBM_BLOCK_ID_RBBM, - RBBM_BLOCK_ID_VBIF, - RBBM_BLOCK_ID_HLSQ, - RBBM_BLOCK_ID_UCHE, - RBBM_BLOCK_ID_PC, - RBBM_BLOCK_ID_VFD, - RBBM_BLOCK_ID_VPC, - RBBM_BLOCK_ID_TSE, - RBBM_BLOCK_ID_RAS, - RBBM_BLOCK_ID_VSC, - RBBM_BLOCK_ID_SP_0, - RBBM_BLOCK_ID_SP_1, - RBBM_BLOCK_ID_SP_2, - RBBM_BLOCK_ID_SP_3, - RBBM_BLOCK_ID_TPL1_0, - RBBM_BLOCK_ID_TPL1_1, - RBBM_BLOCK_ID_TPL1_2, - RBBM_BLOCK_ID_TPL1_3, - RBBM_BLOCK_ID_RB_0, - RBBM_BLOCK_ID_RB_1, - RBBM_BLOCK_ID_RB_2, - RBBM_BLOCK_ID_RB_3, - RBBM_BLOCK_ID_MARB_0, - RBBM_BLOCK_ID_MARB_1, - RBBM_BLOCK_ID_MARB_2, - RBBM_BLOCK_ID_MARB_3, +static struct debugbus_block debugbus_blocks[] = { + { RBBM_BLOCK_ID_CP, 0x52, }, + { RBBM_BLOCK_ID_RBBM, 0x40, }, + { RBBM_BLOCK_ID_VBIF, 0x40, }, + { RBBM_BLOCK_ID_HLSQ, 0x40, }, + { RBBM_BLOCK_ID_UCHE, 0x40, }, + { RBBM_BLOCK_ID_PC, 0x40, }, + { RBBM_BLOCK_ID_VFD, 0x40, }, + { RBBM_BLOCK_ID_VPC, 0x40, }, + { RBBM_BLOCK_ID_TSE, 0x40, }, + { RBBM_BLOCK_ID_RAS, 0x40, }, + { RBBM_BLOCK_ID_VSC, 0x40, }, + { RBBM_BLOCK_ID_SP_0, 0x40, }, + { RBBM_BLOCK_ID_SP_1, 0x40, }, + { RBBM_BLOCK_ID_SP_2, 0x40, }, + { RBBM_BLOCK_ID_SP_3, 0x40, }, + { RBBM_BLOCK_ID_TPL1_0, 0x40, }, + { RBBM_BLOCK_ID_TPL1_1, 0x40, }, + { RBBM_BLOCK_ID_TPL1_2, 0x40, }, + { RBBM_BLOCK_ID_TPL1_3, 0x40, }, + { RBBM_BLOCK_ID_RB_0, 0x40, }, + { RBBM_BLOCK_ID_RB_1, 0x40, }, + { RBBM_BLOCK_ID_RB_2, 0x40, }, + { RBBM_BLOCK_ID_RB_3, 0x40, }, + { RBBM_BLOCK_ID_MARB_0, 0x40, }, + { RBBM_BLOCK_ID_MARB_1, 0x40, }, + { RBBM_BLOCK_ID_MARB_2, 0x40, }, + { RBBM_BLOCK_ID_MARB_3, 0x40, }, }; static void *a3xx_snapshot_debugbus(struct kgsl_device *device, @@ -304,7 +350,7 @@ static void *a3xx_snapshot_debugbus(struct kgsl_device *device, snapshot = kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_DEBUGBUS, snapshot, remain, a3xx_snapshot_debugbus_block, - (void *) debugbus_blocks[i]); + (void *) &debugbus_blocks[i]); } return snapshot; @@ -395,17 +441,18 @@ void *a3xx_snapshot(struct adreno_device *adreno_dev, void *snapshot, struct kgsl_device *device = &adreno_dev->dev; struct kgsl_snapshot_registers_list list; struct kgsl_snapshot_registers regs[5]; + int size; list.registers = regs; list.count = 0; /* Disable Clock gating temporarily for the debug bus to work */ - adreno_regwrite(device, A3XX_RBBM_CLOCK_CTL, 0x00); + kgsl_regwrite(device, A3XX_RBBM_CLOCK_CTL, 0x00); /* Store relevant registers in list to snapshot */ _snapshot_a3xx_regs(regs, &list); _snapshot_hlsq_regs(regs, &list, adreno_dev); - if (adreno_is_a330(adreno_dev)) + if (adreno_is_a330(adreno_dev) || adreno_is_a305b(adreno_dev)) _snapshot_a330_regs(regs, &list); /* Master set of (non debug) registers */ @@ -413,10 +460,15 @@ void *a3xx_snapshot(struct adreno_device *adreno_dev, void *snapshot, KGSL_SNAPSHOT_SECTION_REGS, snapshot, remain, kgsl_snapshot_dump_regs, &list); - /* CP_STATE_DEBUG indexed registers */ + /* + * CP_STATE_DEBUG indexed registers - 20 on 305 and 320 and 46 on A330 + */ + size = (adreno_is_a330(adreno_dev) || + adreno_is_a305b(adreno_dev)) ? 0x2E : 0x14; + snapshot = kgsl_snapshot_indexed_registers(device, snapshot, remain, REG_CP_STATE_DEBUG_INDEX, - REG_CP_STATE_DEBUG_DATA, 0x0, 0x14); + REG_CP_STATE_DEBUG_DATA, 0x0, size); /* CP_ME indexed registers */ snapshot = kgsl_snapshot_indexed_registers(device, snapshot, @@ -457,7 +509,8 @@ void *a3xx_snapshot(struct adreno_device *adreno_dev, void *snapshot, KGSL_SNAPSHOT_SECTION_DEBUG, snapshot, remain, a3xx_snapshot_cp_roq, NULL); - if (adreno_is_a330(adreno_dev)) { + if (adreno_is_a330(adreno_dev) || + adreno_is_a305b(adreno_dev)) { snapshot = kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_DEBUG, snapshot, remain, a330_snapshot_cp_merciu, NULL); @@ -466,7 +519,7 @@ void *a3xx_snapshot(struct adreno_device *adreno_dev, void *snapshot, snapshot = a3xx_snapshot_debugbus(device, snapshot, remain); /* Enable Clock gating */ - adreno_regwrite(device, A3XX_RBBM_CLOCK_CTL, + kgsl_regwrite(device, A3XX_RBBM_CLOCK_CTL, adreno_a3xx_rbbm_clock_ctl_default(adreno_dev)); return snapshot; diff --git a/drivers/gpu/msm/adreno_a4xx.c b/drivers/gpu/msm/adreno_a4xx.c new file mode 100644 index 00000000000..90d816b49d7 --- /dev/null +++ b/drivers/gpu/msm/adreno_a4xx.c @@ -0,0 +1,305 @@ +/* Copyright (c) 2013, The Linux Foundation. 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 and + * only 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. + * + */ + +#include "adreno.h" +#include "a4xx_reg.h" +#include "adreno_a3xx.h" + +/* + * Set of registers to dump for A4XX on postmortem and snapshot. + * Registers in pairs - first value is the start offset, second + * is the stop offset (inclusive) + */ + +const unsigned int a4xx_registers[] = { + 0x0000, 0x0002, /* RBBM_HW_VERSION - RBBM_HW_CONFIGURATION */ + 0x0020, 0x0020, /* RBBM_CLOCK_CTL */ + 0x0021, 0x0021, /* RBBM_SP_HYST_CNT */ + 0x0023, 0x0024, /* RBBM_AHB_CTL0 - RBBM_AHB_CTL1 */ + 0x0026, 0x0026, /* RBBM_RB_SUB_BLOCK_SEL_CTL */ + 0x0028, 0x0034, /* RBBM_RAM_ACC_63_32 - RBBM_INTERFACE_HANG_MASK_CTL4 */ + 0x0037, 0x003f, /* RBBM_INT_0_MASK - RBBM_AHB_DEBUG_CTL */ + 0x0041, 0x0045, /* RBBM_VBIF_DEBUG_CTL - BLOCK_SW_RESET_CMD */ + 0x0047, 0x0049, /* RBBM_RESET_CYCLES - RBBM_EXT_TRACE_BUS_CTL */ + 0x009c, 0x0170, /* RBBM_PERFCTR_CP_0_LO - RBBM_PERFCTR_CTL */ + 0x0174, 0x0182, /* RBBM_PERFCTR_LOAD_VALUE_LO - RBBM_CLOCK_STATUS */ + 0x0189, 0x019f, /* RBBM_AHB_STATUS - RBBM_INTERFACE_RRDY_STATUS5 */ + + 0x0206, 0x0217, /* CP_IB1_BASE - CP_ME_RB_DONE_DATA */ + 0x0219, 0x0219, /* CP_QUEUE_THRESH2 */ + 0x021b, 0x021b, /* CP_MERCIU_SIZE */ + 0x0228, 0x0229, /* CP_SCRATCH_UMASK - CP_SCRATCH_ADDR */ + 0x022a, 0x022c, /* CP_PREEMPT - CP_CNTL */ + 0x022e, 0x022e, /* CP_DEBUG */ + 0x0231, 0x0232, /* CP_DEBUG_ECO_CONTROL - CP_DRAW_STATE_ADDR */ + 0x0240, 0x0250, /* CP_PROTECT_REG_0 - CP_PROTECT_CTRL */ + 0x04c0, 0x04ce, /* CP_ST_BASE - CP_STQ_AVAIL */ + 0x04d0, 0x04d0, /* CP_MERCIU_STAT */ + 0x04d2, 0x04dd, /* CP_WFI_PEND_CTR - CP_EVENTS_IN_FLIGHT */ + 0x0500, 0x050b, /* CP_PERFCTR_CP_SEL_0 - CP_PERFCOMBINER_SELECT */ + 0x0578, 0x058f, /* CP_SCRATCH_REG0 - CP_SCRATCH_REG23 */ + + 0x0c00, 0x0c03, /* VSC_BIN_SIZE - VSC_DEBUG_ECO_CONTROL */ + 0x0c08, 0x0c41, /* VSC_PIPE_CONFIG_0 - VSC_PIPE_PARTIAL_POSN_1 */ + 0x0c50, 0x0c51, /* VSC_PERFCTR_VSC_SEL_0 - VSC_PERFCTR_VSC_SEL_1 */ + + 0x0e64, 0x0e68, /* VPC_DEBUG_ECO_CONTROL - VPC_PERFCTR_VPC_SEL_3 */ + 0x2140, 0x216e, /* VPC_ATTR - VPC_SO_FLUSH_WADDR_3 - ctx0 */ + 0x2540, 0x256e, /* VPC_ATTR - VPC_SO_FLUSH_WADDR_3 - ctx1 */ + + 0x0f00, 0x0f0b, /* TPL1_DEBUG_ECO_CONTROL - TPL1_PERFCTR_TP_SEL_7 */ + /* TPL1_TP_TEX_OFFSET - TPL1_TP_CS_TEXMEMOBJ_BASE_ADDR - ctx0 */ + 0x2380, 0x23a6, + /* TPL1_TP_TEX_OFFSET - TPL1_TP_CS_TEXMEMOBJ_BASE_ADDR - ctx1 */ + 0x2780, 0x27a6, + + 0x0ec0, 0x0ecf, /* SP_VS_STATUS - SP_PERFCTR_SP_SEL_11 */ + 0x22c0, 0x22c1, /* SP_SP_CTRL - SP_INSTR_CACHE_CTRL - ctx0 */ + 0x22c4, 0x2360, /* SP_VS_CTRL_0 - SP_GS_LENGTH - ctx0 */ + 0x26c0, 0x26c1, /* SP_SP_CTRL - SP_INSTR_CACHE_CTRL - ctx1 */ + 0x26c4, 0x2760, /* SP_VS_CTRL_0 - SP_GS_LENGTH - ctx1 */ + + 0x0cc0, 0x0cd2, /* RB_GMEM_BASE_ADDR - RB_PERFCTR_CCU_SEL_3 */ + 0x20a0, 0x213f, /* RB_MODE_CONTROL - RB_VPORT_Z_CLAMP_MAX_15 - ctx0 */ + 0x24a0, 0x253f, /* RB_MODE_CONTROL - RB_VPORT_Z_CLAMP_MAX_15 - ctx1 */ + + 0x0e40, 0x0e4a, /* VFD_DEBUG_CONTROL - VFD_PERFCTR_VFD_SEL_7 */ + 0x2200, 0x2204, /* VFD_CONTROL_0 - VFD_CONTROL_4 - ctx 0 */ + 0x2208, 0x22a9, /* VFD_INDEX_OFFSET - VFD_DECODE_INSTR_31 - ctx 0 */ + 0x2600, 0x2604, /* VFD_CONTROL_0 - VFD_CONTROL_4 - ctx 1 */ + 0x2608, 0x26a9, /* VFD_INDEX_OFFSET - VFD_DECODE_INSTR_31 - ctx 1 */ + + 0x0c80, 0x0c81, /* GRAS_TSE_STATUS - GRAS_DEBUG_ECO_CONTROL */ + 0x0c88, 0x0c8b, /* GRAS_PERFCTR_TSE_SEL_0 - GRAS_PERFCTR_TSE_SEL_3 */ + 0x2000, 0x2004, /* GRAS_CL_CLIP_CNTL - GRAS_CL_GB_CLIP_ADJ - ctx 0 */ + /* GRAS_CL_VPORT_XOFFSET_0 - GRAS_SC_EXTENT_WINDOW_TL - ctx 0 */ + 0x2008, 0x209f, + 0x2400, 0x2404, /* GRAS_CL_CLIP_CNTL - GRAS_CL_GB_CLIP_ADJ - ctx 1 */ + /* GRAS_CL_VPORT_XOFFSET_0 - GRAS_SC_EXTENT_WINDOW_TL - ctx 1 */ + 0x2408, 0x249f, + + 0x0e80, 0x0e84, /* UCHE_CACHE_MODE_CONTROL - UCHE_TRAP_BASE_HI */ + 0x0e88, 0x0e95, /* UCHE_CACHE_STATUS - UCHE_PERFCTR_UCHE_SEL_7 */ + + 0x0e00, 0x0e00, /* HLSQ_TIMEOUT_THRESHOLD - HLSQ_TIMEOUT_THRESHOLD */ + 0x0e04, 0x0e0e, /* HLSQ_DEBUG_ECO_CONTROL - HLSQ_PERF_PIPE_MASK */ + 0x23c0, 0x23db, /* HLSQ_CONTROL_0 - HLSQ_UPDATE_CONTROL - ctx 0 */ + 0x27c0, 0x27db, /* HLSQ_CONTROL_0 - HLSQ_UPDATE_CONTROL - ctx 1 */ + + 0x0d00, 0x0d0c, /* PC_BINNING_COMMAND - PC_DRAWCALL_SETUP_OVERRIDE */ + 0x0d10, 0x0d17, /* PC_PERFCTR_PC_SEL_0 - PC_PERFCTR_PC_SEL_7 */ + 0x21c0, 0x21c6, /* PC_BIN_BASE - PC_RESTART_INDEX - ctx 0 */ + 0x21e5, 0x21e7, /* PC_GS_PARAM - PC_HS_PARAM - ctx 0 */ + 0x25c0, 0x25c6, /* PC_BIN_BASE - PC_RESTART_INDEX - ctx 1 */ + 0x25e5, 0x25e7, /* PC_GS_PARAM - PC_HS_PARAM - ctx 1 */ +}; + +const unsigned int a4xx_registers_count = ARRAY_SIZE(a4xx_registers) / 2; + +static int a4xx_drawctxt_create(struct adreno_device *adreno_dev, + struct adreno_context *drawctxt) +{ + int ret = 0; + struct kgsl_device *device = &adreno_dev->dev; + + if (!(drawctxt->flags & CTXT_FLAGS_PREAMBLE)) { + /* This option is not supported on a4xx */ + KGSL_DRV_ERR(device, + "Preambles required for A4XX draw contexts\n"); + ret = -EPERM; + goto done; + } + + if (!(drawctxt->flags & CTXT_FLAGS_NOGMEMALLOC)) { + /* This option is not supported on a4xx */ + KGSL_DRV_ERR(device, + "Cannot create context with gmemalloc\n"); + ret = -EPERM; + } + +done: + return ret; +} + +static int a4xx_drawctxt_restore(struct adreno_device *adreno_dev, + struct adreno_context *context) +{ + struct kgsl_device *device = &adreno_dev->dev; + unsigned int cmds[5]; + int ret; + + if (context == NULL) { + /* No context - set the default pagetable and thats it */ + unsigned int id; + /* + * If there isn't a current context, the kgsl_mmu_setstate + * will use the CPU path so we don't need to give + * it a valid context id. + */ + id = (adreno_dev->drawctxt_active != NULL) + ? adreno_dev->drawctxt_active->base.id + : KGSL_CONTEXT_INVALID; + kgsl_mmu_setstate(&device->mmu, device->mmu.defaultpagetable, + id); + return 0; + } + + cmds[0] = cp_nop_packet(1); + cmds[1] = KGSL_CONTEXT_TO_MEM_IDENTIFIER; + cmds[2] = cp_type3_packet(CP_MEM_WRITE, 2); + cmds[3] = device->memstore.gpuaddr + + KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, current_context); + cmds[4] = context->base.id; + ret = adreno_ringbuffer_issuecmds(device, context, KGSL_CMD_FLAGS_NONE, + cmds, 5); + if (ret) + return ret; + ret = kgsl_mmu_setstate(&device->mmu, + context->base.proc_priv->pagetable, + context->base.id); + return ret; +} + +static const struct adreno_vbif_data a420_vbif[] = { + { A4XX_VBIF_ABIT_SORT, 0x0001001F }, + { A4XX_VBIF_ABIT_SORT_CONF, 0x000000A4 }, + { A4XX_VBIF_GATE_OFF_WRREQ_EN, 0x00000001 }, + { A4XX_VBIF_IN_RD_LIM_CONF0, 0x18181818 }, + { A4XX_VBIF_IN_RD_LIM_CONF1, 0x00000018 }, + { A4XX_VBIF_IN_WR_LIM_CONF0, 0x18181818 }, + { A4XX_VBIF_IN_WR_LIM_CONF1, 0x00000018 }, + { A4XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x00000003 }, + {0, 0}, +}; + +const struct adreno_vbif_platform a4xx_vbif_platforms[] = { + { adreno_is_a420, a420_vbif }, +}; + +static void a4xx_start(struct adreno_device *adreno_dev) +{ + struct kgsl_device *device = &adreno_dev->dev; + + adreno_vbif_start(device, a4xx_vbif_platforms, + ARRAY_SIZE(a4xx_vbif_platforms)); + /* Make all blocks contribute to the GPU BUSY perf counter */ + kgsl_regwrite(device, A4XX_RBBM_GPU_BUSY_MASKED, 0xFFFFFFFF); + + /* Tune the hystersis counters for SP and CP idle detection */ + kgsl_regwrite(device, A4XX_RBBM_SP_HYST_CNT, 0x10); + kgsl_regwrite(device, A4XX_RBBM_WAIT_IDLE_CLOCKS_CTL, 0x10); + + /* + * Enable the RBBM error reporting bits. This lets us get + * useful information on failure + */ + + kgsl_regwrite(device, A4XX_RBBM_AHB_CTL0, 0x00000001); + + /* Enable AHB error reporting */ + kgsl_regwrite(device, A4XX_RBBM_AHB_CTL1, 0xA6FFFFFF); + + /* + * Turn on hang detection - this spews a lot of useful information + * into the RBBM registers on a hang + */ + + kgsl_regwrite(device, A4XX_RBBM_INTERFACE_HANG_INT_CTL, + (1 << 16) | 0xFFF); + + /* Set the OCMEM base address for A4XX */ + kgsl_regwrite(device, A4XX_RB_GMEM_BASE_ADDR, + (unsigned int)(adreno_dev->ocmem_base >> 14)); +} + +/* Register offset defines for A4XX, in order of enum adreno_regs */ +static unsigned int a4xx_register_offsets[ADRENO_REG_REGISTER_MAX] = { + ADRENO_REG_DEFINE(ADRENO_REG_CP_DEBUG, A4XX_CP_DEBUG), + ADRENO_REG_DEFINE(ADRENO_REG_CP_ME_RAM_WADDR, A4XX_CP_ME_RAM_WADDR), + ADRENO_REG_DEFINE(ADRENO_REG_CP_ME_RAM_DATA, A4XX_CP_ME_RAM_DATA), + ADRENO_REG_DEFINE(ADRENO_REG_CP_PFP_UCODE_DATA, A4XX_CP_PFP_UCODE_DATA), + ADRENO_REG_DEFINE(ADRENO_REG_CP_PFP_UCODE_ADDR, A4XX_CP_PFP_UCODE_ADDR), + ADRENO_REG_DEFINE(ADRENO_REG_CP_WFI_PEND_CTR, A4XX_CP_WFI_PEND_CTR), + ADRENO_REG_DEFINE(ADRENO_REG_CP_RB_BASE, A4XX_CP_RB_BASE), + ADRENO_REG_DEFINE(ADRENO_REG_CP_RB_RPTR_ADDR, A4XX_CP_RB_RPTR_ADDR), + ADRENO_REG_DEFINE(ADRENO_REG_CP_RB_RPTR, A4XX_CP_RB_RPTR), + ADRENO_REG_DEFINE(ADRENO_REG_CP_RB_WPTR, A4XX_CP_RB_WPTR), + ADRENO_REG_DEFINE(ADRENO_REG_CP_PROTECT_CTRL, A4XX_CP_PROTECT_CTRL), + ADRENO_REG_DEFINE(ADRENO_REG_CP_ME_CNTL, A4XX_CP_ME_CNTL), + ADRENO_REG_DEFINE(ADRENO_REG_CP_RB_CNTL, A4XX_CP_RB_CNTL), + ADRENO_REG_DEFINE(ADRENO_REG_CP_IB1_BASE, A4XX_CP_IB1_BASE), + ADRENO_REG_DEFINE(ADRENO_REG_CP_IB1_BUFSZ, A4XX_CP_IB1_BUFSZ), + ADRENO_REG_DEFINE(ADRENO_REG_CP_IB2_BASE, A4XX_CP_IB2_BASE), + ADRENO_REG_DEFINE(ADRENO_REG_CP_IB2_BUFSZ, A4XX_CP_IB2_BUFSZ), + ADRENO_REG_DEFINE(ADRENO_REG_CP_TIMESTAMP, A4XX_CP_SCRATCH_REG0), + ADRENO_REG_DEFINE(ADRENO_REG_CP_ME_RAM_RADDR, A4XX_CP_ME_RAM_RADDR), + ADRENO_REG_DEFINE(ADRENO_REG_SCRATCH_ADDR, A4XX_CP_SCRATCH_ADDR), + ADRENO_REG_DEFINE(ADRENO_REG_SCRATCH_UMSK, A4XX_CP_SCRATCH_UMASK), + ADRENO_REG_DEFINE(ADRENO_REG_RBBM_STATUS, A4XX_RBBM_STATUS), + ADRENO_REG_DEFINE(ADRENO_REG_RBBM_PERFCTR_CTL, A4XX_RBBM_PERFCTR_CTL), + ADRENO_REG_DEFINE(ADRENO_REG_RBBM_PERFCTR_LOAD_CMD0, + A4XX_RBBM_PERFCTR_LOAD_CMD0), + ADRENO_REG_DEFINE(ADRENO_REG_RBBM_PERFCTR_LOAD_CMD1, + A4XX_RBBM_PERFCTR_LOAD_CMD1), + ADRENO_REG_DEFINE(ADRENO_REG_RBBM_PERFCTR_LOAD_CMD2, + A4XX_RBBM_PERFCTR_LOAD_CMD2), + ADRENO_REG_DEFINE(ADRENO_REG_RBBM_PERFCTR_PWR_1_LO, + A4XX_RBBM_PERFCTR_PWR_1_LO), + ADRENO_REG_DEFINE(ADRENO_REG_RBBM_INT_0_MASK, A4XX_RBBM_INT_0_MASK), + ADRENO_REG_DEFINE(ADRENO_REG_RBBM_INT_0_STATUS, A4XX_RBBM_INT_0_STATUS), + ADRENO_REG_DEFINE(ADRENO_REG_RBBM_AHB_ERROR_STATUS, + A4XX_RBBM_AHB_ERROR_STATUS), + ADRENO_REG_DEFINE(ADRENO_REG_RBBM_AHB_CMD, A4XX_RBBM_AHB_CMD), + ADRENO_REG_DEFINE(ADRENO_REG_VPC_DEBUG_RAM_SEL, + A4XX_VPC_DEBUG_RAM_SEL), + ADRENO_REG_DEFINE(ADRENO_REG_VPC_DEBUG_RAM_READ, + A4XX_VPC_DEBUG_RAM_READ), + ADRENO_REG_DEFINE(ADRENO_REG_RBBM_INT_CLEAR_CMD, + A4XX_RBBM_INT_CLEAR_CMD), + ADRENO_REG_DEFINE(ADRENO_REG_VSC_PIPE_DATA_ADDRESS_0, + A4XX_VSC_PIPE_DATA_ADDRESS_0), + ADRENO_REG_DEFINE(ADRENO_REG_VSC_PIPE_DATA_LENGTH_7, + A4XX_VSC_PIPE_DATA_LENGTH_7), + ADRENO_REG_DEFINE(ADRENO_REG_VSC_SIZE_ADDRESS, A4XX_VSC_SIZE_ADDRESS), + ADRENO_REG_DEFINE(ADRENO_REG_VFD_CONTROL_0, A4XX_VFD_CONTROL_0), + ADRENO_REG_DEFINE(ADRENO_REG_VFD_FETCH_INSTR_0_0, + A4XX_VFD_FETCH_INSTR_0_0), + ADRENO_REG_DEFINE(ADRENO_REG_VFD_FETCH_INSTR_1_F, + A4XX_VFD_FETCH_INSTR_1_31), + ADRENO_REG_DEFINE(ADRENO_REG_SP_VS_PVT_MEM_ADDR_REG, + A4XX_SP_VS_PVT_MEM_ADDR), + ADRENO_REG_DEFINE(ADRENO_REG_SP_FS_PVT_MEM_ADDR_REG, + A4XX_SP_FS_PVT_MEM_ADDR), + ADRENO_REG_DEFINE(ADRENO_REG_SP_VS_OBJ_START_REG, + A4XX_SP_VS_OBJ_START), + ADRENO_REG_DEFINE(ADRENO_REG_SP_FS_OBJ_START_REG, + A4XX_SP_FS_OBJ_START), +}; + +const struct adreno_reg_offsets a4xx_reg_offsets = { + .offsets = a4xx_register_offsets, + .offset_0 = ADRENO_REG_REGISTER_MAX, +}; + +struct adreno_gpudev adreno_a4xx_gpudev = { + .reg_offsets = &a4xx_reg_offsets, + + .ctxt_create = a4xx_drawctxt_create, + .ctxt_restore = a4xx_drawctxt_restore, + .rb_init = a3xx_rb_init, + .irq_control = a3xx_irq_control, + .irq_handler = a3xx_irq_handler, + .irq_pending = a3xx_irq_pending, + .busy_cycles = a3xx_busy_cycles, + .start = a4xx_start, +}; diff --git a/drivers/gpu/msm/adreno_coresight.c b/drivers/gpu/msm/adreno_coresight.c new file mode 100644 index 00000000000..1b827ffccd3 --- /dev/null +++ b/drivers/gpu/msm/adreno_coresight.c @@ -0,0 +1,219 @@ +/* Copyright (c) 2013, The Linux Foundation. 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 and + * only 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "kgsl.h" +#include "kgsl_device.h" +#include "adreno.h" + +struct coresight_attr { + struct device_attribute attr; + int regname; +}; + +#define CORESIGHT_CREATE_REG_ATTR(_attrname, _regname) \ + struct coresight_attr coresight_attr_##_attrname = \ + { __ATTR(_attrname, S_IRUGO | S_IWUSR, gfx_show_reg, gfx_store_reg),\ + _regname} + +/** + * adreno_coresight_enable() - Generic function to enable coresight debugging + * @csdev: Pointer to coresight's device struct + * + * This is a generic function to enable coresight debug bus on adreno + * devices. This should be used in all cases of enabling + * coresight debug bus for adreno devices. This function in turn calls + * the adreno device specific function through gpudev hook. + * This function is registered as the coresight enable function + * with coresight driver. It should only be called through coresight driver + * as that would ensure that the necessary setup required to be done + * on coresight driver's part is also done. + */ +int adreno_coresight_enable(struct coresight_device *csdev) +{ + struct kgsl_device *device = dev_get_drvdata(csdev->dev.parent); + struct adreno_device *adreno_dev = ADRENO_DEVICE(device); + + /* Check if coresight compatible device, return error otherwise */ + if (adreno_dev->gpudev->coresight_enable) + return adreno_dev->gpudev->coresight_enable(device); + else + return -ENODEV; +} + +/** + * adreno_coresight_disable() - Generic function to disable coresight debugging + * @csdev: Pointer to coresight's device struct + * + * This is a generic function to disable coresight debug bus on adreno + * devices. This should be used in all cases of disabling + * coresight debug bus for adreno devices. This function in turn calls + * the adreno device specific function through the gpudev hook. + * This function is registered as the coresight disable function + * with coresight driver. It should only be called through coresight driver + * as that would ensure that the necessary setup required to be done on + * coresight driver's part is also done. + */ +void adreno_coresight_disable(struct coresight_device *csdev) +{ + struct kgsl_device *device = dev_get_drvdata(csdev->dev.parent); + struct adreno_device *adreno_dev = ADRENO_DEVICE(device); + + /* Check if coresight compatible device, bail otherwise */ + if (adreno_dev->gpudev->coresight_disable) + return adreno_dev->gpudev->coresight_disable(device); +} + +static const struct coresight_ops_source adreno_coresight_ops_source = { + .enable = adreno_coresight_enable, + .disable = adreno_coresight_disable, +}; + +static const struct coresight_ops adreno_coresight_cs_ops = { + .source_ops = &adreno_coresight_ops_source, +}; + +void adreno_coresight_remove(struct platform_device *pdev) +{ + struct kgsl_device_platform_data *pdata = pdev->dev.platform_data; + coresight_unregister(pdata->csdev); +} + +static ssize_t coresight_read_reg(struct kgsl_device *device, + unsigned int offset, char *buf) +{ + unsigned int regval = 0; + + mutex_lock(&device->mutex); + if (!kgsl_active_count_get(device)) { + kgsl_regread(device, offset, ®val); + kgsl_active_count_put(device); + } + mutex_unlock(&device->mutex); + return snprintf(buf, PAGE_SIZE, "0x%X", regval); +} + +static inline unsigned int coresight_convert_reg(const char *buf) +{ + long regval = 0; + int rv = 0; + + rv = kstrtoul(buf, 16, ®val); + if (!rv) + return (unsigned int)regval; + else + return rv; +} + +static ssize_t gfx_show_reg(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct kgsl_device *device = dev_get_drvdata(dev->parent); + struct coresight_attr *csight_attr = container_of(attr, + struct coresight_attr, attr); + return coresight_read_reg(device, csight_attr->regname, buf); +} + +static ssize_t gfx_store_reg(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + struct kgsl_device *device = dev_get_drvdata(dev->parent); + struct adreno_device *adreno_dev = ADRENO_DEVICE(device); + struct coresight_attr *csight_attr = container_of(attr, + struct coresight_attr, attr); + unsigned int regval = 0; + + regval = coresight_convert_reg(buf); + + if (adreno_dev->gpudev->coresight_config_debug_reg) + adreno_dev->gpudev->coresight_config_debug_reg(device, + csight_attr->regname, regval); + return size; +} + +CORESIGHT_CREATE_REG_ATTR(config_debug_bus, DEBUG_BUS_CTL); +CORESIGHT_CREATE_REG_ATTR(config_trace_stop_cnt, TRACE_STOP_CNT); +CORESIGHT_CREATE_REG_ATTR(config_trace_start_cnt, TRACE_START_CNT); +CORESIGHT_CREATE_REG_ATTR(config_trace_period_cnt, TRACE_PERIOD_CNT); +CORESIGHT_CREATE_REG_ATTR(config_trace_cmd, TRACE_CMD); +CORESIGHT_CREATE_REG_ATTR(config_trace_bus_ctl, TRACE_BUS_CTL); + +static struct attribute *gfx_attrs[] = { + &coresight_attr_config_debug_bus.attr.attr, + &coresight_attr_config_trace_start_cnt.attr.attr, + &coresight_attr_config_trace_stop_cnt.attr.attr, + &coresight_attr_config_trace_period_cnt.attr.attr, + &coresight_attr_config_trace_cmd.attr.attr, + &coresight_attr_config_trace_bus_ctl.attr.attr, + NULL, +}; + +static struct attribute_group gfx_attr_grp = { + .attrs = gfx_attrs, +}; + +static const struct attribute_group *gfx_attr_grps[] = { + &gfx_attr_grp, + NULL, +}; + +int adreno_coresight_init(struct platform_device *pdev) +{ + int ret = 0; + struct kgsl_device_platform_data *pdata = pdev->dev.platform_data; + struct device *dev = &pdev->dev; + struct coresight_desc *desc; + + if (IS_ERR_OR_NULL(pdata->coresight_pdata)) + return -ENODATA; + + + desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL); + if (!desc) + return -ENOMEM; + + + desc->type = CORESIGHT_DEV_TYPE_SOURCE; + desc->subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_BUS; + desc->ops = &adreno_coresight_cs_ops; + desc->pdata = pdata->coresight_pdata; + desc->dev = &pdev->dev; + desc->owner = THIS_MODULE; + desc->groups = gfx_attr_grps; + pdata->csdev = coresight_register(desc); + if (IS_ERR(pdata->csdev)) { + ret = PTR_ERR(pdata->csdev); + goto err; + } + + return 0; + +err: + devm_kfree(dev, desc); + return ret; +} + diff --git a/drivers/gpu/msm/adreno_cp_parser.c b/drivers/gpu/msm/adreno_cp_parser.c new file mode 100644 index 00000000000..944c50f263a --- /dev/null +++ b/drivers/gpu/msm/adreno_cp_parser.c @@ -0,0 +1,823 @@ +/* Copyright (c) 2013, The Linux Foundation. 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 and + * only 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. + */ + +#include "kgsl.h" +#include "kgsl_sharedmem.h" +#include "kgsl_snapshot.h" + +#include "adreno.h" +#include "adreno_pm4types.h" +#include "a2xx_reg.h" +#include "a3xx_reg.h" +#include "adreno_cp_parser.h" + +#define MAX_IB_OBJS 1000 + +/* + * This structure keeps track of type0 writes to VSC_PIPE_DATA_ADDRESS_x and + * VSC_PIPE_DATA_LENGTH_x. When a draw initator is called these registers + * point to buffers that we need to freeze for a snapshot + */ + +struct ib_vsc_pipe { + unsigned int base; + unsigned int size; +}; + +/* + * This struct keeps track of type0 writes to VFD_FETCH_INSTR_0_X and + * VFD_FETCH_INSTR_1_X registers. When a draw initator is called the addresses + * and sizes in these registers point to VBOs that we need to freeze for a + * snapshot + */ + +struct ib_vbo { + unsigned int base; + unsigned int stride; +}; + +/* List of variables used when parsing an IB */ +struct ib_parser_variables { + struct ib_vsc_pipe vsc_pipe[8]; + /* + * This is the cached value of type0 writes to the VSC_SIZE_ADDRESS + * which contains the buffer address of the visiblity stream size + * buffer during a binning pass + */ + unsigned int vsc_size_address; + struct ib_vbo vbo[16]; + /* This is the cached value of type0 writes to VFD_INDEX_MAX. */ + unsigned int vfd_index_max; + /* + * This is the cached value of type0 writes to VFD_CONTROL_0 which + * tells us how many VBOs are active when the draw initator is called + */ + unsigned int vfd_control_0; + /* Cached value of type0 writes to SP_VS_PVT_MEM_ADDR and + * SP_FS_PVT_MEM_ADDR. This is a buffer that contains private + * stack information for the shader + */ + unsigned int sp_vs_pvt_mem_addr; + unsigned int sp_fs_pvt_mem_addr; + /* Cached value of SP_VS_OBJ_START_REG and SP_FS_OBJ_START_REG. */ + unsigned int sp_vs_obj_start_reg; + unsigned int sp_fs_obj_start_reg; +}; + +/* + * Used for locating shader objects. This array holds the unit size of shader + * objects based on type and block of shader. The type can be 0 or 1 hence there + * are 2 columns and block can be 0-7 hence 7 rows. + */ +static int load_state_unit_sizes[7][2] = { + { 2, 4 }, + { 0, 1 }, + { 2, 4 }, + { 0, 1 }, + { 8, 2 }, + { 8, 2 }, + { 8, 2 }, +}; + +/* + * adreno_ib_merge_range() - Increases the address range tracked by an ib + * object + * @ib_obj: The ib object + * @gpuaddr: The start address which is to be merged + * @size: Size of the merging address + */ +static void adreno_ib_merge_range(struct adreno_ib_object *ib_obj, + unsigned int gpuaddr, unsigned int size) +{ + unsigned int addr_end1 = ib_obj->gpuaddr + ib_obj->size; + unsigned int addr_end2 = gpuaddr + size; + if (gpuaddr < ib_obj->gpuaddr) + ib_obj->gpuaddr = gpuaddr; + if (addr_end2 > addr_end1) + ib_obj->size = addr_end2 - ib_obj->gpuaddr; + else + ib_obj->size = addr_end1 - ib_obj->gpuaddr; +} + +/* + * adreno_ib_check_overlap() - Checks if an address range overlap + * @gpuaddr: The start address range to check for overlap + * @size: Size of the address range + * @ib_obj_list: The list of address ranges to check for overlap + * + * Checks if an address range overlaps with a list of address ranges + * Returns the entry from list which overlaps else NULL + */ +static struct adreno_ib_object *adreno_ib_check_overlap(unsigned int gpuaddr, + unsigned int size, struct adreno_ib_object_list *ib_obj_list) +{ + struct adreno_ib_object *ib_obj; + int i; + + for (i = 0; i < ib_obj_list->num_objs; i++) { + ib_obj = &(ib_obj_list->obj_list[i]); + if (kgsl_addr_range_overlap(ib_obj->gpuaddr, ib_obj->size, + gpuaddr, size)) + /* regions overlap */ + return ib_obj; + } + return NULL; +} + +/* + * adreno_ib_add_range() - Add a gpuaddress range to list + * @device: Device on which the gpuaddress range is valid + * @ptbase: Pagtebale base on which the gpuaddress is mapped + * @size: Size of the address range in concern + * @type: The type of address range + * @ib_obj_list: List of the address ranges in which the given range is to be + * added + * + * Add a gpuaddress range as an ib object to a given list after checking if it + * overlaps with another entry on the list. If it conflicts then change the + * existing entry to incorporate this range + * + * Returns 0 on success else error code + */ +static int adreno_ib_add_range(struct kgsl_device *device, + phys_addr_t ptbase, + unsigned int gpuaddr, + unsigned int size, int type, + struct adreno_ib_object_list *ib_obj_list) +{ + struct adreno_ib_object *ib_obj; + struct kgsl_mem_entry *entry; + + entry = kgsl_get_mem_entry(device, ptbase, gpuaddr, size); + if (!entry) + /* + * Do not fail if gpuaddr not found, we can continue + * to search for other objects even if few objects are + * not found + */ + return 0; + + if (!size) { + size = entry->memdesc.size; + gpuaddr = entry->memdesc.gpuaddr; + } + + ib_obj = adreno_ib_check_overlap(gpuaddr, size, ib_obj_list); + if (ib_obj) { + adreno_ib_merge_range(ib_obj, gpuaddr, size); + } else { + if (MAX_IB_OBJS == ib_obj_list->num_objs) { + KGSL_DRV_ERR(device, + "Max objects reached %d\n", ib_obj_list->num_objs); + return -ENOMEM; + } + adreno_ib_init_ib_obj(gpuaddr, size, type, entry, + &(ib_obj_list->obj_list[ib_obj_list->num_objs])); + ib_obj_list->num_objs++; + } + return 0; +} + +/* + * ib_save_mip_addresses() - Find mip addresses + * @device: Device on which the IB is running + * @pkt: Pointer to the packet in IB + * @ptbase: The pagetable on which IB is mapped + * @ib_obj_list: List in which any objects found are added + * + * Returns 0 on success else error code + */ +static int ib_save_mip_addresses(struct kgsl_device *device, unsigned int *pkt, + phys_addr_t ptbase, struct adreno_ib_object_list *ib_obj_list) +{ + int ret = 0; + int num_levels = (pkt[1] >> 22) & 0x03FF; + int i; + unsigned int *hostptr; + struct kgsl_mem_entry *ent; + unsigned int block, type; + int unitsize = 0; + + block = (pkt[1] >> 19) & 0x07; + type = pkt[2] & 0x03; + + if (type == 0) + unitsize = load_state_unit_sizes[block][0]; + else + unitsize = load_state_unit_sizes[block][1]; + + if (3 == block && 1 == type) { + ent = kgsl_get_mem_entry(device, ptbase, pkt[2] & 0xFFFFFFFC, + (num_levels * unitsize) << 2); + if (!ent) + return -EINVAL; + + hostptr = (unsigned int *)kgsl_gpuaddr_to_vaddr(&ent->memdesc, + pkt[2] & 0xFFFFFFFC); + if (!hostptr) { + kgsl_mem_entry_put(ent); + return -EINVAL; + } + for (i = 0; i < num_levels; i++) { + ret = adreno_ib_add_range(device, ptbase, hostptr[i], + 0, SNAPSHOT_GPU_OBJECT_GENERIC, ib_obj_list); + if (ret < 0) + break; + } + kgsl_memdesc_unmap(&ent->memdesc); + kgsl_mem_entry_put(ent); + } + return ret; +} + +/* + * ib_parse_load_state() - Parse load state packet + * @device: Device on which the IB is running + * @pkt: Pointer to the packet in IB + * @ptbase: The pagetable on which IB is mapped + * @ib_obj_list: List in which any objects found are added + * @ib_parse_vars: VAriable list that store temporary addressses + * + * Parse load state packet found in an IB and add any memory object found to + * a list + * Returns 0 on success else error code + */ +static int ib_parse_load_state(struct kgsl_device *device, unsigned int *pkt, + phys_addr_t ptbase, struct adreno_ib_object_list *ib_obj_list, + struct ib_parser_variables *ib_parse_vars) +{ + unsigned int block, source, type; + int ret = 0; + int unitsize = 0; + + /* + * The object here is to find indirect shaders i.e - shaders loaded from + * GPU memory instead of directly in the command. These should be added + * to the list of memory objects to dump. So look at the load state + * if the block is indirect (source = 4). If so then add the memory + * address to the list. The size of the object differs depending on the + * type per the load_state_unit_sizes array above. + */ + + if (type3_pkt_size(pkt[0]) < 2) + return 0; + + /* + * pkt[1] 18:16 - source + * pkt[1] 21:19 - state block + * pkt[1] 31:22 - size in units + * pkt[2] 0:1 - type + * pkt[2] 31:2 - GPU memory address + */ + + block = (pkt[1] >> 19) & 0x07; + source = (pkt[1] >> 16) & 0x07; + type = pkt[2] & 0x03; + + if (source == 4) { + if (type == 0) + unitsize = load_state_unit_sizes[block][0]; + else + unitsize = load_state_unit_sizes[block][1]; + + /* Freeze the GPU buffer containing the shader */ + + ret = adreno_ib_add_range(device, ptbase, pkt[2] & 0xFFFFFFFC, + (((pkt[1] >> 22) & 0x03FF) * unitsize) << 2, + SNAPSHOT_GPU_OBJECT_SHADER, + ib_obj_list); + if (ret < 0) + return ret; + } + /* get the mip addresses */ + ret = ib_save_mip_addresses(device, pkt, ptbase, ib_obj_list); + return ret; +} + +/* + * This opcode sets the base addresses for the visibilty stream buffer and the + * visiblity stream size buffer. + */ + +static int ib_parse_set_bin_data(struct kgsl_device *device, unsigned int *pkt, + phys_addr_t ptbase, struct adreno_ib_object_list *ib_obj_list, + struct ib_parser_variables *ib_parse_vars) +{ + int ret = 0; + + if (type3_pkt_size(pkt[0]) < 2) + return 0; + + /* Visiblity stream buffer */ + ret = adreno_ib_add_range(device, ptbase, pkt[1], 0, + SNAPSHOT_GPU_OBJECT_GENERIC, ib_obj_list); + if (ret < 0) + return ret; + + /* visiblity stream size buffer (fixed size 8 dwords) */ + ret = adreno_ib_add_range(device, ptbase, pkt[2], 32, + SNAPSHOT_GPU_OBJECT_GENERIC, ib_obj_list); + + return ret; +} + +/* + * This opcode writes to GPU memory - if the buffer is written to, there is a + * good chance that it would be valuable to capture in the snapshot, so mark all + * buffers that are written to as frozen + */ + +static int ib_parse_mem_write(struct kgsl_device *device, unsigned int *pkt, + phys_addr_t ptbase, struct adreno_ib_object_list *ib_obj_list, + struct ib_parser_variables *ib_parse_vars) +{ + int ret = 0; + + if (type3_pkt_size(pkt[0]) < 1) + return 0; + + /* + * The address is where the data in the rest of this packet is written + * to, but since that might be an offset into the larger buffer we need + * to get the whole thing. Pass a size of 0 tocapture the entire buffer. + */ + + ret = adreno_ib_add_range(device, ptbase, pkt[1] & 0xFFFFFFFC, 0, + SNAPSHOT_GPU_OBJECT_GENERIC, ib_obj_list); + if (ret < 0) + return ret; + + return ret; +} + +/* + * ib_add_type0_entries() - Add memory objects to list + * @device: The device on which the IB will execute + * @ptbase: The ptbase on which IB is mapped + * @ib_obj_list: The list of gpu objects + * @ib_parse_vars: addresses ranges found in type0 packets + * + * Add memory objects to given list that are found in type0 packets + * Returns 0 on success else 0 + */ +static int ib_add_type0_entries(struct kgsl_device *device, + phys_addr_t ptbase, struct adreno_ib_object_list *ib_obj_list, + struct ib_parser_variables *ib_parse_vars) +{ + int ret = 0; + int i; + /* First up the visiblity stream buffer */ + + for (i = 0; i < ARRAY_SIZE(ib_parse_vars->vsc_pipe); i++) { + if (ib_parse_vars->vsc_pipe[i].base != 0 && + ib_parse_vars->vsc_pipe[i].size != 0) { + ret = adreno_ib_add_range(device, ptbase, + ib_parse_vars->vsc_pipe[i].base, + ib_parse_vars->vsc_pipe[i].size, + SNAPSHOT_GPU_OBJECT_GENERIC, + ib_obj_list); + if (ret < 0) + return ret; + ib_parse_vars->vsc_pipe[i].size = 0; + ib_parse_vars->vsc_pipe[i].base = 0; + } + } + + /* Next the visibility stream size buffer */ + + if (ib_parse_vars->vsc_size_address) { + ret = adreno_ib_add_range(device, ptbase, + ib_parse_vars->vsc_size_address, 32, + SNAPSHOT_GPU_OBJECT_GENERIC, ib_obj_list); + if (ret < 0) + return ret; + ib_parse_vars->vsc_size_address = 0; + } + + /* Next private shader buffer memory */ + if (ib_parse_vars->sp_vs_pvt_mem_addr) { + ret = adreno_ib_add_range(device, ptbase, + ib_parse_vars->sp_vs_pvt_mem_addr, 8192, + SNAPSHOT_GPU_OBJECT_GENERIC, ib_obj_list); + if (ret < 0) + return ret; + + ib_parse_vars->sp_vs_pvt_mem_addr = 0; + } + + if (ib_parse_vars->sp_fs_pvt_mem_addr) { + ret = adreno_ib_add_range(device, ptbase, + ib_parse_vars->sp_fs_pvt_mem_addr, 8192, + SNAPSHOT_GPU_OBJECT_GENERIC, + ib_obj_list); + if (ret < 0) + return ret; + + ib_parse_vars->sp_fs_pvt_mem_addr = 0; + } + + if (ib_parse_vars->sp_vs_obj_start_reg) { + ret = adreno_ib_add_range(device, ptbase, + ib_parse_vars->sp_vs_obj_start_reg & 0xFFFFFFE0, + 0, SNAPSHOT_GPU_OBJECT_GENERIC, ib_obj_list); + if (ret < 0) + return -ret; + ib_parse_vars->sp_vs_obj_start_reg = 0; + } + + if (ib_parse_vars->sp_fs_obj_start_reg) { + ret = adreno_ib_add_range(device, ptbase, + ib_parse_vars->sp_fs_obj_start_reg & 0xFFFFFFE0, + 0, SNAPSHOT_GPU_OBJECT_GENERIC, ib_obj_list); + if (ret < 0) + return ret; + ib_parse_vars->sp_fs_obj_start_reg = 0; + } + + /* Finally: VBOs */ + + /* The number of active VBOs is stored in VFD_CONTROL_O[31:27] */ + for (i = 0; i < (ib_parse_vars->vfd_control_0) >> 27; i++) { + int size; + + /* + * The size of the VBO is the stride stored in + * VFD_FETCH_INSTR_0_X.BUFSTRIDE * VFD_INDEX_MAX. The base + * is stored in VFD_FETCH_INSTR_1_X + */ + + if (ib_parse_vars->vbo[i].base != 0) { + size = ib_parse_vars->vbo[i].stride * + ib_parse_vars->vfd_index_max; + + ret = adreno_ib_add_range(device, ptbase, + ib_parse_vars->vbo[i].base, + 0, SNAPSHOT_GPU_OBJECT_GENERIC, ib_obj_list); + if (ret < 0) + return ret; + } + + ib_parse_vars->vbo[i].base = 0; + ib_parse_vars->vbo[i].stride = 0; + } + + ib_parse_vars->vfd_control_0 = 0; + ib_parse_vars->vfd_index_max = 0; + + return ret; +} + +/* + * The DRAW_INDX opcode sends a draw initator which starts a draw operation in + * the GPU, so this is the point where all the registers and buffers become + * "valid". The DRAW_INDX may also have an index buffer pointer that should be + * frozen with the others + */ + +static int ib_parse_draw_indx(struct kgsl_device *device, unsigned int *pkt, + phys_addr_t ptbase, struct adreno_ib_object_list *ib_obj_list, + struct ib_parser_variables *ib_parse_vars) +{ + int ret = 0; + + if (type3_pkt_size(pkt[0]) < 3) + return 0; + + /* DRAW_IDX may have a index buffer pointer */ + + if (type3_pkt_size(pkt[0]) > 3) { + ret = adreno_ib_add_range(device, ptbase, pkt[4], pkt[5], + SNAPSHOT_GPU_OBJECT_GENERIC, ib_obj_list); + if (ret < 0) + return ret; + } + + /* + * All of the type0 writes are valid at a draw initiator, so freeze + * the various buffers that we are tracking + */ + ret = ib_add_type0_entries(device, ptbase, ib_obj_list, + ib_parse_vars); + return ret; +} + +/* + * Parse all the type3 opcode packets that may contain important information, + * such as additional GPU buffers to grab or a draw initator + */ + +static int ib_parse_type3(struct kgsl_device *device, unsigned int *ptr, + phys_addr_t ptbase, struct adreno_ib_object_list *ib_obj_list, + struct ib_parser_variables *ib_parse_vars) +{ + int opcode = cp_type3_opcode(*ptr); + + if (opcode == CP_LOAD_STATE) + return ib_parse_load_state(device, ptr, ptbase, ib_obj_list, + ib_parse_vars); + else if (opcode == CP_SET_BIN_DATA) + return ib_parse_set_bin_data(device, ptr, ptbase, ib_obj_list, + ib_parse_vars); + else if (opcode == CP_MEM_WRITE) + return ib_parse_mem_write(device, ptr, ptbase, ib_obj_list, + ib_parse_vars); + else if (opcode == CP_DRAW_INDX) + return ib_parse_draw_indx(device, ptr, ptbase, ib_obj_list, + ib_parse_vars); + + return 0; +} + +/* + * Parse type0 packets found in the stream. Some of the registers that are + * written are clues for GPU buffers that we need to freeze. Register writes + * are considred valid when a draw initator is called, so just cache the values + * here and freeze them when a CP_DRAW_INDX is seen. This protects against + * needlessly caching buffers that won't be used during a draw call + */ + +static void ib_parse_type0(struct kgsl_device *device, unsigned int *ptr, + phys_addr_t ptbase, struct adreno_ib_object_list *ib_obj_list, + struct ib_parser_variables *ib_parse_vars) +{ + struct adreno_device *adreno_dev = ADRENO_DEVICE(device); + int size = type0_pkt_size(*ptr); + int offset = type0_pkt_offset(*ptr); + int i; + + for (i = 0; i < size; i++, offset++) { + + /* Visiblity stream buffer */ + + if (offset >= adreno_getreg(adreno_dev, + ADRENO_REG_VSC_PIPE_DATA_ADDRESS_0) && + offset <= adreno_getreg(adreno_dev, + ADRENO_REG_VSC_PIPE_DATA_LENGTH_7)) { + int index = offset - adreno_getreg(adreno_dev, + ADRENO_REG_VSC_PIPE_DATA_ADDRESS_0); + + /* Each bank of address and length registers are + * interleaved with an empty register: + * + * address 0 + * length 0 + * empty + * address 1 + * length 1 + * empty + * ... + */ + + if ((index % 3) == 0) + ib_parse_vars->vsc_pipe[index / 3].base = + ptr[i + 1]; + else if ((index % 3) == 1) + ib_parse_vars->vsc_pipe[index / 3].size = + ptr[i + 1]; + } else if ((offset >= adreno_getreg(adreno_dev, + ADRENO_REG_VFD_FETCH_INSTR_0_0)) && + (offset <= adreno_getreg(adreno_dev, + ADRENO_REG_VFD_FETCH_INSTR_1_F))) { + int index = offset - + adreno_getreg(adreno_dev, + ADRENO_REG_VFD_FETCH_INSTR_0_0); + + /* + * FETCH_INSTR_0_X and FETCH_INSTR_1_X banks are + * interleaved as above but without the empty register + * in between + */ + + if ((index % 2) == 0) + ib_parse_vars->vbo[index >> 1].stride = + (ptr[i + 1] >> 7) & 0x1FF; + else + ib_parse_vars->vbo[index >> 1].base = + ptr[i + 1]; + } else { + /* + * Cache various support registers for calculating + * buffer sizes + */ + + if (offset == + adreno_getreg(adreno_dev, + ADRENO_REG_VFD_CONTROL_0)) + ib_parse_vars->vfd_control_0 = ptr[i + 1]; + else if (offset == + adreno_getreg(adreno_dev, + ADRENO_REG_VFD_INDEX_MAX)) + ib_parse_vars->vfd_index_max = ptr[i + 1]; + else if (offset == + adreno_getreg(adreno_dev, + ADRENO_REG_VSC_SIZE_ADDRESS)) + ib_parse_vars->vsc_size_address = ptr[i + 1]; + else if (offset == adreno_getreg(adreno_dev, + ADRENO_REG_SP_VS_PVT_MEM_ADDR_REG)) + ib_parse_vars->sp_vs_pvt_mem_addr = ptr[i + 1]; + else if (offset == adreno_getreg(adreno_dev, + ADRENO_REG_SP_FS_PVT_MEM_ADDR_REG)) + ib_parse_vars->sp_fs_pvt_mem_addr = ptr[i + 1]; + else if (offset == adreno_getreg(adreno_dev, + ADRENO_REG_SP_VS_OBJ_START_REG)) + ib_parse_vars->sp_vs_obj_start_reg = ptr[i + 1]; + else if (offset == adreno_getreg(adreno_dev, + ADRENO_REG_SP_FS_OBJ_START_REG)) + ib_parse_vars->sp_fs_obj_start_reg = ptr[i + 1]; + } + } + ib_add_type0_entries(device, ptbase, ib_obj_list, + ib_parse_vars); +} + +/* + * adreno_ib_find_objs() - Find all IB objects in a given IB + * @device: The device pointer on which the IB executes + * @ptbase: The pagetable base in which in the IBis mapped and so are the + * objects in it + * @gpuaddr: The gpu address of the IB + * @dwords: Size of ib in dwords + * @ib_obj_list: The list in which the IB and the objects in it are added. + * + * Finds all IB objects in a given IB and puts then in a list. Can be called + * recursively for the IB2's in the IB1's + * Returns 0 on success else error code + */ +static int adreno_ib_find_objs(struct kgsl_device *device, + phys_addr_t ptbase, + unsigned int gpuaddr, unsigned int dwords, + struct adreno_ib_object_list *ib_obj_list) +{ + int ret = 0; + int rem = dwords; + int i; + struct ib_parser_variables ib_parse_vars; + unsigned int *src; + struct adreno_ib_object *ib_obj; + struct kgsl_mem_entry *entry; + + /* check that this IB is not already on list */ + for (i = 0; i < ib_obj_list->num_objs; i++) { + ib_obj = &(ib_obj_list->obj_list[i]); + if ((ib_obj->gpuaddr <= gpuaddr) && + ((ib_obj->gpuaddr + ib_obj->size) >= + (gpuaddr + (dwords << 2)))) + return 0; + } + + entry = kgsl_get_mem_entry(device, ptbase, gpuaddr, (dwords << 2)); + if (!entry) + return -EINVAL; + + src = (unsigned int *)kgsl_gpuaddr_to_vaddr(&entry->memdesc, gpuaddr); + if (!src) { + kgsl_mem_entry_put(entry); + return -EINVAL; + } + + memset(&ib_parse_vars, 0, sizeof(struct ib_parser_variables)); + + ret = adreno_ib_add_range(device, ptbase, gpuaddr, dwords << 2, + SNAPSHOT_GPU_OBJECT_IB, ib_obj_list); + if (ret) + goto done; + + for (i = 0; rem > 0; rem--, i++) { + int pktsize; + + /* + * If the packet isn't a type 1 or a type 3, then don't bother + * parsing it - it is likely corrupted + */ + if (!pkt_is_type0(src[i]) && !pkt_is_type3(src[i])) + break; + + pktsize = type3_pkt_size(src[i]); + + if (!pktsize || (pktsize + 1) > rem) + break; + + if (pkt_is_type3(src[i])) { + if (adreno_cmd_is_ib(src[i])) { + unsigned int gpuaddrib2 = src[i + 1]; + unsigned int size = src[i + 2]; + + ret = adreno_ib_find_objs( + device, ptbase, + gpuaddrib2, size, + ib_obj_list); + if (ret < 0) + goto done; + } else { + ret = ib_parse_type3(device, &src[i], ptbase, + ib_obj_list, + &ib_parse_vars); + /* + * If the parse function failed (probably + * because of a bad decode) then bail out and + * just capture the binary IB data + */ + + if (ret < 0) + goto done; + } + } else if (pkt_is_type0(src[i])) { + ib_parse_type0(device, &src[i], ptbase, ib_obj_list, + &ib_parse_vars); + } + + i += pktsize; + rem -= pktsize; + } + /* + * If any type objects got missed because we did not come across draw + * indx packets then catch them here. This works better for the replay + * tool and also if the draw indx packet is in an IB2 and these setups + * are in IB1 then these objects are definitely valid and should be + * dumped + */ + ret = ib_add_type0_entries(device, ptbase, ib_obj_list, + &ib_parse_vars); +done: + kgsl_memdesc_unmap(&entry->memdesc); + kgsl_mem_entry_put(entry); + return ret; +} + + +/* + * adreno_ib_create_object_list() - Find all the memory objects in IB + * @device: The device pointer on which the IB executes + * @ptbase: The pagetable base in which in the IBis mapped and so are the + * objects in it + * @gpuaddr: The gpu address of the IB + * @dwords: Size of ib in dwords + * @ib_obj_list: The list in which the IB and the objects in it are added. + * + * Find all the memory objects that an IB needs for execution and place + * them in a list including the IB. + * Returns the ib object list else error code in pointer. + */ +int adreno_ib_create_object_list(struct kgsl_device *device, + phys_addr_t ptbase, + unsigned int gpuaddr, unsigned int dwords, + struct adreno_ib_object_list **out_ib_obj_list) +{ + int ret = 0; + struct adreno_ib_object_list *ib_obj_list; + + if (!out_ib_obj_list) + return -EINVAL; + + ib_obj_list = kzalloc(sizeof(*ib_obj_list), GFP_KERNEL); + if (!ib_obj_list) + return -ENOMEM; + + ib_obj_list->obj_list = vmalloc(MAX_IB_OBJS * + sizeof(struct adreno_ib_object)); + + if (!ib_obj_list->obj_list) { + kfree(ib_obj_list); + return -ENOMEM; + } + + ret = adreno_ib_find_objs(device, ptbase, gpuaddr, dwords, + ib_obj_list); + + if (ret) + adreno_ib_destroy_obj_list(ib_obj_list); + else + *out_ib_obj_list = ib_obj_list; + + return ret; +} + +/* + * adreno_ib_destroy_obj_list() - Destroy an ib object list + * @ib_obj_list: List to destroy + * + * Free up all resources used by an ib_obj_list + */ +void adreno_ib_destroy_obj_list(struct adreno_ib_object_list *ib_obj_list) +{ + int i; + + if (!ib_obj_list) + return; + + for (i = 0; i < ib_obj_list->num_objs; i++) { + if (ib_obj_list->obj_list[i].entry) + kgsl_mem_entry_put(ib_obj_list->obj_list[i].entry); + } + vfree(ib_obj_list->obj_list); + kfree(ib_obj_list); +} diff --git a/drivers/gpu/msm/adreno_cp_parser.h b/drivers/gpu/msm/adreno_cp_parser.h new file mode 100644 index 00000000000..fb2886c5702 --- /dev/null +++ b/drivers/gpu/msm/adreno_cp_parser.h @@ -0,0 +1,68 @@ +/* Copyright (c) 2013, The Linux Foundation. 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 and + * only 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. + */ + +#ifndef __ADRENO_IB_PARSER__ +#define __ADRENO_IB_PARSER__ + +/* + * struct adreno_ib_object - Structure containing information about an + * address range found in an IB + * @gpuaddr: The starting gpuaddress of the range + * @size: Size of the range + * @snapshot_obj_type - Type of range used in snapshot + * @entry: The memory entry in which this range is found + */ +struct adreno_ib_object { + unsigned int gpuaddr; + unsigned int size; + int snapshot_obj_type; + struct kgsl_mem_entry *entry; +}; + +/* + * struct adreno_ib_object_list - List of address ranges found in IB + * @obj_list: The address range list + * @num_objs: Number of objects in list + */ +struct adreno_ib_object_list { + struct adreno_ib_object *obj_list; + int num_objs; +}; + +/* + * adreno_ib_init_ib_obj() - Create an ib object structure and initialize it + * with gpuaddress and size + * @gpuaddr: gpuaddr with which to initialize the object with + * @size: Size in bytes with which the object is initialized + * @ib_type: The IB type used by snapshot + * + * Returns the object pointer on success else error code in the pointer + */ +static inline void adreno_ib_init_ib_obj(unsigned int gpuaddr, + unsigned int size, int obj_type, + struct kgsl_mem_entry *entry, + struct adreno_ib_object *ib_obj) +{ + ib_obj->gpuaddr = gpuaddr; + ib_obj->size = size; + ib_obj->snapshot_obj_type = obj_type; + ib_obj->entry = entry; +} + +int adreno_ib_create_object_list( + struct kgsl_device *device, phys_addr_t ptbase, + unsigned int gpuaddr, unsigned int dwords, + struct adreno_ib_object_list **out_ib_obj_list); + +void adreno_ib_destroy_obj_list(struct adreno_ib_object_list *ib_obj_list); + +#endif diff --git a/drivers/gpu/msm/adreno_debugfs.c b/drivers/gpu/msm/adreno_debugfs.c index e6e4d769d79..12804a358f8 100644 --- a/drivers/gpu/msm/adreno_debugfs.c +++ b/drivers/gpu/msm/adreno_debugfs.c @@ -19,27 +19,12 @@ #include "kgsl.h" #include "adreno.h" +#include "kgsl_cffdump.h" #include "a2xx_reg.h" unsigned int kgsl_cff_dump_enable; -static int kgsl_cff_dump_enable_set(void *data, u64 val) -{ -#ifdef CONFIG_MSM_KGSL_CFF_DUMP - kgsl_cff_dump_enable = (val != 0); - return 0; -#else - return -EINVAL; -#endif -} - -static int kgsl_cff_dump_enable_get(void *data, u64 *val) -{ - *val = kgsl_cff_dump_enable; - return 0; -} - DEFINE_SIMPLE_ATTRIBUTE(kgsl_cff_dump_enable_fops, kgsl_cff_dump_enable_get, kgsl_cff_dump_enable_set, "%llu\n"); @@ -106,6 +91,6 @@ void adreno_debugfs_init(struct kgsl_device *device) debugfs_create_u32("ft_pagefault_policy", 0644, device->d_debugfs, &adreno_dev->ft_pf_policy); - debugfs_create_file("active_cnt", 0644, device->d_debugfs, device, + debugfs_create_file("active_cnt", 0444, device->d_debugfs, device, &_active_count_fops); } diff --git a/drivers/gpu/msm/adreno_dispatch.c b/drivers/gpu/msm/adreno_dispatch.c index f1c98db8a07..3bcc7a3bb8f 100644 --- a/drivers/gpu/msm/adreno_dispatch.c +++ b/drivers/gpu/msm/adreno_dispatch.c @@ -44,13 +44,16 @@ static unsigned int _context_cmdbatch_burst = 5; static unsigned int _dispatcher_inflight = 15; /* Command batch timeout (in milliseconds) */ -static unsigned int _cmdbatch_timeout = 10000; +static unsigned int _cmdbatch_timeout = 2000; /* Interval for reading and comparing fault detection registers */ -static unsigned int _fault_timer_interval = 100; +static unsigned int _fault_timer_interval = 50; /* Local array for the current set of fault detect registers */ -static unsigned int *fault_detect_regs; +static unsigned int fault_detect_regs[FT_DETECT_REGS_COUNT]; + +/* The last retired global timestamp read during fault detect */ +static unsigned int fault_detect_ts; /** * fault_detect_read() - Read the set of fault detect registers @@ -64,14 +67,35 @@ static void fault_detect_read(struct kgsl_device *device) { int i; + fault_detect_ts = kgsl_readtimestamp(device, NULL, + KGSL_TIMESTAMP_RETIRED); + for (i = 0; i < FT_DETECT_REGS_COUNT; i++) { if (ft_detect_regs[i] == 0) continue; - adreno_regread(device, ft_detect_regs[i], + kgsl_regread(device, ft_detect_regs[i], &fault_detect_regs[i]); } } +/* + * Check to see if the device is idle and that the global timestamp is up to + * date + */ +static inline bool _isidle(struct kgsl_device *device) +{ + struct adreno_device *adreno_dev = ADRENO_DEVICE(device); + unsigned int ts; + + ts = kgsl_readtimestamp(device, NULL, KGSL_TIMESTAMP_RETIRED); + + if (adreno_isidle(device) == true && + (ts >= adreno_dev->ringbuffer.global_ts)) + return true; + + return false; +} + /** * fault_detect_read_compare() - Read the fault detect registers and compare * them to the current value @@ -83,18 +107,29 @@ static void fault_detect_read(struct kgsl_device *device) static int fault_detect_read_compare(struct kgsl_device *device) { int i, ret = 0; + unsigned int ts; + + /* Check to see if the device is idle - if so report no hang */ + if (_isidle(device) == true) + ret = 1; for (i = 0; i < FT_DETECT_REGS_COUNT; i++) { unsigned int val; if (ft_detect_regs[i] == 0) continue; - adreno_regread(device, ft_detect_regs[i], &val); + kgsl_regread(device, ft_detect_regs[i], &val); if (val != fault_detect_regs[i]) ret = 1; fault_detect_regs[i] = val; } + ts = kgsl_readtimestamp(device, NULL, KGSL_TIMESTAMP_RETIRED); + if (ts != fault_detect_ts) + ret = 1; + + fault_detect_ts = ts; + return ret; } @@ -141,14 +176,22 @@ static inline struct kgsl_cmdbatch *adreno_context_get_cmdbatch( * * Failure to submit a command to the ringbuffer isn't the fault of the command * being submitted so if a failure happens, push it back on the head of the the - * context queue to be reconsidered again + * context queue to be reconsidered again unless the context got detached. */ -static inline void adreno_context_requeue_cmdbatch( +static inline int adreno_dispatcher_requeue_cmdbatch( struct adreno_context *drawctxt, struct kgsl_cmdbatch *cmdbatch) { unsigned int prev; mutex_lock(&drawctxt->mutex); + if (kgsl_context_detached(&drawctxt->base) || + drawctxt->state == ADRENO_CONTEXT_STATE_INVALID) { + mutex_unlock(&drawctxt->mutex); + /* get rid of this cmdbatch since the context is bad */ + kgsl_cmdbatch_destroy(cmdbatch); + return -EINVAL; + } + prev = drawctxt->cmdqueue_head - 1; if (prev < 0) @@ -167,6 +210,7 @@ static inline void adreno_context_requeue_cmdbatch( /* Reset the command queue head to reflect the newly requeued change */ drawctxt->cmdqueue_head = prev; mutex_unlock(&drawctxt->mutex); + return 0; } /** @@ -181,14 +225,19 @@ static void dispatcher_queue_context(struct adreno_device *adreno_dev, { struct adreno_dispatcher *dispatcher = &adreno_dev->dispatcher; + /* Refuse to queue a detached context */ + if (kgsl_context_detached(&drawctxt->base)) + return; + spin_lock(&dispatcher->plist_lock); if (plist_node_empty(&drawctxt->pending)) { /* Get a reference to the context while it sits on the list */ - _kgsl_context_get(&drawctxt->base); - trace_dispatch_queue_context(drawctxt); - plist_add(&drawctxt->pending, &dispatcher->pending); + if (_kgsl_context_get(&drawctxt->base)) { + trace_dispatch_queue_context(drawctxt); + plist_add(&drawctxt->pending, &dispatcher->pending); + } } spin_unlock(&dispatcher->plist_lock); @@ -208,10 +257,10 @@ static int sendcmd(struct adreno_device *adreno_dev, struct adreno_dispatcher *dispatcher = &adreno_dev->dispatcher; int ret; - dispatcher->inflight++; - mutex_lock(&device->mutex); + dispatcher->inflight++; + if (dispatcher->inflight == 1) { /* Time to make the donuts. Turn on the GPU */ ret = kgsl_active_count_get(device); @@ -241,7 +290,7 @@ static int sendcmd(struct adreno_device *adreno_dev, if (ret) { dispatcher->inflight--; KGSL_DRV_ERR(device, - "Unable to submit command to the ringbuffer\n"); + "Unable to submit command to the ringbuffer %d\n", ret); return ret; } @@ -278,12 +327,15 @@ static int sendcmd(struct adreno_device *adreno_dev, * @drawctxt: Pointer to the adreno context to dispatch commands from * * Dequeue and send a burst of commands from the specified context to the GPU + * Returns postive if the context needs to be put back on the pending queue + * 0 if the context is empty or detached and negative on error */ static int dispatcher_context_sendcmds(struct adreno_device *adreno_dev, struct adreno_context *drawctxt) { struct adreno_dispatcher *dispatcher = &adreno_dev->dispatcher; int count = 0; + int requeued = 0; /* * Each context can send a specific number of command batches per cycle @@ -304,8 +356,10 @@ static int dispatcher_context_sendcmds(struct adreno_device *adreno_dev, * reqeueued */ - if (IS_ERR(cmdbatch)) - return count; + if (IS_ERR(cmdbatch) && PTR_ERR(cmdbatch) == -EAGAIN) { + requeued = 1; + break; + } /* * If this is a synchronization submission then there are no @@ -330,31 +384,29 @@ static int dispatcher_context_sendcmds(struct adreno_device *adreno_dev, * conditions improve */ if (ret) { - adreno_context_requeue_cmdbatch(drawctxt, cmdbatch); + requeued = adreno_dispatcher_requeue_cmdbatch(drawctxt, + cmdbatch) ? 0 : 1; break; } + + count++; } /* - * If the context successfully submitted commands, then - * unconditionally put it back on the queue to be considered the - * next time around. This might seem a little wasteful but it is - * reasonable to think that a busy context will stay busy. + * If the context successfully submitted commands there will be room + * in the context queue so wake up any snoozing threads that want to + * submit commands */ - if (count) { - dispatcher_queue_context(adreno_dev, drawctxt); - - /* - * If we submitted something there will be room in the - * context queue so ping the context wait queue on the - * chance that the context is snoozing - */ - + if (count) wake_up_interruptible_all(&drawctxt->wq); - } - return count; + /* + * Return positive if the context submitted commands or if we figured + * out that we need to requeue due to a pending sync or error. + */ + + return (count || requeued) ? 1 : 0; } /** @@ -367,27 +419,39 @@ static int dispatcher_context_sendcmds(struct adreno_device *adreno_dev, static int _adreno_dispatcher_issuecmds(struct adreno_device *adreno_dev) { struct adreno_dispatcher *dispatcher = &adreno_dev->dispatcher; + struct adreno_context *drawctxt, *next; + struct plist_head requeue; + int ret; - /* Don't do anything if the dispatcher is paused */ - if (dispatcher->state != ADRENO_DISPATCHER_ACTIVE) - return 0; + /* Leave early if the dispatcher isn't in a happy state */ + if ((dispatcher->state != ADRENO_DISPATCHER_ACTIVE) || + adreno_gpu_fault(adreno_dev) != 0) + return 0; + plist_head_init(&requeue); + + /* Try to fill the ringbuffer as much as possible */ while (dispatcher->inflight < _dispatcher_inflight) { - struct adreno_context *drawctxt = NULL; - spin_lock(&dispatcher->plist_lock); + /* Stop doing things if the dispatcher is paused or faulted */ + if ((dispatcher->state != ADRENO_DISPATCHER_ACTIVE) || + adreno_gpu_fault(adreno_dev) != 0) + break; - if (!plist_head_empty(&dispatcher->pending)) { - drawctxt = plist_first_entry(&dispatcher->pending, - struct adreno_context, pending); + spin_lock(&dispatcher->plist_lock); - plist_del(&drawctxt->pending, &dispatcher->pending); + if (plist_head_empty(&dispatcher->pending)) { + spin_unlock(&dispatcher->plist_lock); + break; } - spin_unlock(&dispatcher->plist_lock); + /* Get the next entry on the list */ + drawctxt = plist_first_entry(&dispatcher->pending, + struct adreno_context, pending); - if (drawctxt == NULL) - break; + plist_del(&drawctxt->pending, &dispatcher->pending); + + spin_unlock(&dispatcher->plist_lock); if (kgsl_context_detached(&drawctxt->base) || drawctxt->state == ADRENO_CONTEXT_STATE_INVALID) { @@ -395,10 +459,49 @@ static int _adreno_dispatcher_issuecmds(struct adreno_device *adreno_dev) continue; } - dispatcher_context_sendcmds(adreno_dev, drawctxt); - kgsl_context_put(&drawctxt->base); + ret = dispatcher_context_sendcmds(adreno_dev, drawctxt); + + if (ret > 0) { + spin_lock(&dispatcher->plist_lock); + + /* + * Check to seen if the context had been requeued while + * we were processing it (probably by another thread + * pushing commands). If it has then we don't need to + * bother with it but do a put to make sure the + * reference counting stays accurate. If the node is + * empty then we will put it on the requeue list and not + * touch the refcount since we already hold it from the + * first time it went on the list. + */ + + if (plist_node_empty(&drawctxt->pending)) + plist_add(&drawctxt->pending, &requeue); + else + kgsl_context_put(&drawctxt->base); + + spin_unlock(&dispatcher->plist_lock); + } else { + /* + * If the context doesn't need be requeued put back the + * refcount + */ + + kgsl_context_put(&drawctxt->base); + } } + /* Put all the requeued contexts back on the master list */ + + spin_lock(&dispatcher->plist_lock); + + plist_for_each_entry_safe(drawctxt, next, &requeue, pending) { + plist_del(&drawctxt->pending, &requeue); + plist_add(&drawctxt->pending, &dispatcher->pending); + } + + spin_unlock(&dispatcher->plist_lock); + return 0; } @@ -476,7 +579,7 @@ static int get_timestamp(struct adreno_context *drawctxt, } /** - * adreno_context_queue_cmd() - Queue a new command in the context + * adreno_dispatcher_queue_cmd() - Queue a new command in the context * @adreno_dev: Pointer to the adreno device struct * @drawctxt: Pointer to the adreno draw context * @cmdbatch: Pointer to the command batch being submitted @@ -485,7 +588,7 @@ static int get_timestamp(struct adreno_context *drawctxt, * Queue a command in the context - if there isn't any room in the queue, then * block until there is */ -int adreno_context_queue_cmd(struct adreno_device *adreno_dev, +int adreno_dispatcher_queue_cmd(struct adreno_device *adreno_dev, struct adreno_context *drawctxt, struct kgsl_cmdbatch *cmdbatch, uint32_t *timestamp) { @@ -551,16 +654,19 @@ int adreno_context_queue_cmd(struct adreno_device *adreno_dev, mutex_unlock(&drawctxt->mutex); return (ret == 0) ? -ETIMEDOUT : (int) ret; } + } + /* + * Account for the possiblity that the context got invalidated + * while we were sleeping + */ - /* - * Account for the possiblity that the context got invalidated - * while we were sleeping - */ - - if (drawctxt->state == ADRENO_CONTEXT_STATE_INVALID) { - mutex_unlock(&drawctxt->mutex); - return -EDEADLK; - } + if (drawctxt->state == ADRENO_CONTEXT_STATE_INVALID) { + mutex_unlock(&drawctxt->mutex); + return -EDEADLK; + } + if (kgsl_context_detached(&drawctxt->base)) { + mutex_unlock(&drawctxt->mutex); + return -EINVAL; } ret = get_timestamp(drawctxt, cmdbatch, timestamp); @@ -574,6 +680,16 @@ int adreno_context_queue_cmd(struct adreno_device *adreno_dev, /* The batch fault policy is the current system fault policy */ cmdbatch->fault_policy = adreno_dev->ft_policy; + /* + * Set the fault tolerance policy for the command batch - assuming the + * context hsn't disabled FT use the current device policy + */ + + if (drawctxt->flags & CTXT_FLAGS_NO_FAULT_TOLERANCE) + set_bit(KGSL_FT_DISABLE, &cmdbatch->fault_policy); + else + cmdbatch->fault_policy = adreno_dev->ft_policy; + /* Put the command into the queue */ drawctxt->cmdqueue[drawctxt->cmdqueue_tail] = cmdbatch; drawctxt->cmdqueue_tail = (drawctxt->cmdqueue_tail + 1) % @@ -615,7 +731,8 @@ static void cmdbatch_skip_ib(struct kgsl_cmdbatch *cmdbatch, unsigned int base) for (i = 0; i < cmdbatch->ibcount; i++) { if (cmdbatch->ibdesc[i].gpuaddr == base) { cmdbatch->ibdesc[i].sizedwords = 0; - return; + if (base) + return; } } } @@ -644,12 +761,12 @@ static void cmdbatch_skip_frame(struct kgsl_cmdbatch *cmdbatch, */ if (skip) { - replay[i]->priv |= CMDBATCH_FLAG_SKIP; + set_bit(CMDBATCH_FLAG_SKIP, &replay[i]->priv); if (replay[i]->flags & KGSL_CONTEXT_END_OF_FRAME) skip = 0; } else { - replay[i]->priv |= CMDBATCH_FLAG_FORCE_PREAMBLE; + set_bit(CMDBATCH_FLAG_FORCE_PREAMBLE, &replay[i]->priv); return; } } @@ -699,7 +816,70 @@ static void remove_invalidated_cmdbatches(struct kgsl_device *device, } } -static void dispatcher_do_fault(struct kgsl_device *device) +static char _pidname[TASK_COMM_LEN]; + +static inline const char *_kgsl_context_comm(struct kgsl_context *context) +{ + struct task_struct *task = NULL; + + if (context) + task = find_task_by_vpid(context->pid); + + if (task) + get_task_comm(_pidname, task); + else + snprintf(_pidname, TASK_COMM_LEN, "unknown"); + + return _pidname; +} + +#define pr_fault(_d, _c, fmt, args...) \ + dev_err((_d)->dev, "%s[%d]: " fmt, \ + _kgsl_context_comm((_c)->context), \ + (_c)->context->pid, ##args) + + +static void adreno_fault_header(struct kgsl_device *device, + struct kgsl_cmdbatch *cmdbatch) +{ + struct adreno_device *adreno_dev = ADRENO_DEVICE(device); + unsigned int status, base, rptr, wptr, ib1base, ib2base, ib1sz, ib2sz; + + kgsl_regread(device, + adreno_getreg(adreno_dev, ADRENO_REG_RBBM_STATUS), + &status); + kgsl_regread(device, + adreno_getreg(adreno_dev, ADRENO_REG_CP_RB_BASE), + &base); + kgsl_regread(device, + adreno_getreg(adreno_dev, ADRENO_REG_CP_RB_RPTR), + &rptr); + kgsl_regread(device, + adreno_getreg(adreno_dev, ADRENO_REG_CP_RB_WPTR), + &wptr); + kgsl_regread(device, + adreno_getreg(adreno_dev, ADRENO_REG_CP_IB1_BASE), + &ib1base); + kgsl_regread(device, + adreno_getreg(adreno_dev, ADRENO_REG_CP_IB1_BUFSZ), + &ib1sz); + kgsl_regread(device, + adreno_getreg(adreno_dev, ADRENO_REG_CP_IB2_BASE), + &ib2base); + kgsl_regread(device, + adreno_getreg(adreno_dev, ADRENO_REG_CP_IB2_BUFSZ), + &ib2sz); + + trace_adreno_gpu_fault(cmdbatch->context->id, cmdbatch->timestamp, + status, rptr, wptr, ib1base, ib1sz, ib2base, ib2sz); + + pr_fault(device, cmdbatch, + "gpu fault ctx %d ts %d status %8.8X rb %4.4x/%4.4x ib1 %8.8x/%4.4x ib2 %8.8x/%4.4x\n", + cmdbatch->context->id, cmdbatch->timestamp, status, + rptr, wptr, ib1base, ib1sz, ib2base, ib2sz); +} + +static int dispatcher_do_fault(struct kgsl_device *device) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); struct adreno_dispatcher *dispatcher = &adreno_dev->dispatcher; @@ -708,8 +888,21 @@ static void dispatcher_do_fault(struct kgsl_device *device) struct kgsl_cmdbatch **replay = NULL; struct kgsl_cmdbatch *cmdbatch; int ret, i, count = 0; + int fault, first = 0; + bool pagefault = false; - BUG_ON(dispatcher->inflight == 0); + fault = atomic_xchg(&dispatcher->fault, 0); + if (fault == 0) + return 0; + /* + * Return early if no command inflight - can happen on + * false hang detects + */ + if (dispatcher->inflight == 0) { + KGSL_DRV_WARN(device, + "dispatcher_do_fault with 0 inflight commands\n"); + return 0; + } /* Turn off all the timers */ del_timer_sync(&dispatcher->timer); @@ -719,29 +912,35 @@ static void dispatcher_do_fault(struct kgsl_device *device) cmdbatch = dispatcher->cmdqueue[dispatcher->head]; + trace_adreno_cmdbatch_fault(cmdbatch, fault); + /* * If the fault was due to a timeout then stop the CP to ensure we don't * get activity while we are trying to dump the state of the system */ - if (dispatcher->fault == ADRENO_DISPATCHER_TIMEOUT_FAULT) { - kgsl_regread(device, REG_CP_ME_CNTL, ®); + if (fault & ADRENO_TIMEOUT_FAULT) { + adreno_readreg(adreno_dev, ADRENO_REG_CP_ME_CNTL, ®); reg |= (1 << 27) | (1 << 28); - kgsl_regwrite(device, REG_CP_ME_CNTL, reg); + adreno_writereg(adreno_dev, ADRENO_REG_CP_ME_CNTL, reg); /* Skip the PM dump for a timeout because it confuses people */ - cmdbatch->fault_policy |= KGSL_FT_SKIP_PMDUMP; + set_bit(KGSL_FT_SKIP_PMDUMP, &cmdbatch->fault_policy); } - kgsl_regread(device, REG_CP_IB1_BASE, &base); + adreno_readreg(adreno_dev, ADRENO_REG_CP_IB1_BASE, &base); /* * Dump the postmortem and snapshot information if this is the first * detected fault for the oldest active command batch */ - if (!(cmdbatch->fault_policy & KGSL_FT_SKIP_PMDUMP)) { - kgsl_postmortem_dump(device, 0); + if (!test_bit(KGSL_FT_SKIP_PMDUMP, &cmdbatch->fault_policy)) { + adreno_fault_header(device, cmdbatch); + + if (device->pm_dump_enable) + kgsl_postmortem_dump(device, 0); + kgsl_device_snapshot(device, 1); } @@ -787,12 +986,24 @@ static void dispatcher_do_fault(struct kgsl_device *device) cmdbatch = replay[0]; + /* + * If FT is disabled for this cmdbatch invalidate immediately + */ + + if (test_bit(KGSL_FT_DISABLE, &cmdbatch->fault_policy) || + test_bit(KGSL_FT_TEMP_DISABLE, &cmdbatch->fault_policy)) { + pr_fault(device, cmdbatch, "gpu skipped ctx %d ts %d\n", + cmdbatch->context->id, cmdbatch->timestamp); + + adreno_drawctxt_invalidate(device, cmdbatch->context); + } + /* * Set a flag so we don't print another PM dump if the cmdbatch fails * again on replay */ - cmdbatch->fault_policy |= KGSL_FT_SKIP_PMDUMP; + set_bit(KGSL_FT_SKIP_PMDUMP, &cmdbatch->fault_policy); /* * A hardware fault generally means something was deterministically @@ -800,16 +1011,29 @@ static void dispatcher_do_fault(struct kgsl_device *device) * Clear the replay bit and move on to the next policy level */ - if (dispatcher->fault == ADRENO_DISPATCHER_HARD_FAULT) - cmdbatch->fault_policy &= ~KGSL_FT_REPLAY; + if (fault & ADRENO_HARD_FAULT) + clear_bit(KGSL_FT_REPLAY, &(cmdbatch->fault_policy)); + + /* + * A timeout fault means the IB timed out - clear the policy and + * invalidate - this will clear the FT_SKIP_PMDUMP bit but that is okay + * because we won't see this cmdbatch again + */ + + if (fault & ADRENO_TIMEOUT_FAULT) + bitmap_zero(&cmdbatch->fault_policy, BITS_PER_LONG); /* - * A timeout fault means the IB timed out - don't be silly and replay - * it, because it will probably timeout again + * If the context had a GPU page fault then it is likely it would fault + * again if replayed */ - if (dispatcher->fault == ADRENO_DISPATCHER_TIMEOUT_FAULT) - cmdbatch->fault_policy &= ~KGSL_FT_REPLAY; + if (test_bit(KGSL_CONTEXT_PAGEFAULT, &cmdbatch->context->priv)) { + /* we'll need to resume the mmu later... */ + pagefault = true; + clear_bit(KGSL_FT_REPLAY, &cmdbatch->fault_policy); + clear_bit(KGSL_CONTEXT_PAGEFAULT, &cmdbatch->context->priv); + } /* * Execute the fault tolerance policy. Each command batch stores the @@ -821,8 +1045,9 @@ static void dispatcher_do_fault(struct kgsl_device *device) */ /* Replay the hanging command batch again */ - if (cmdbatch->fault_policy & KGSL_FT_REPLAY) { - cmdbatch->fault_policy &= ~KGSL_FT_REPLAY; + if (test_and_clear_bit(KGSL_FT_REPLAY, &cmdbatch->fault_policy)) { + trace_adreno_cmdbatch_recovery(cmdbatch, BIT(KGSL_FT_REPLAY)); + set_bit(KGSL_FT_REPLAY, &cmdbatch->fault_recovery); goto replay; } @@ -834,20 +1059,23 @@ static void dispatcher_do_fault(struct kgsl_device *device) * supposedly bad IB1 where ever it lurks. */ - if (cmdbatch->fault_policy & KGSL_FT_SKIPIB) { - cmdbatch->fault_policy &= ~KGSL_FT_SKIPIB; + if (test_and_clear_bit(KGSL_FT_SKIPIB, &cmdbatch->fault_policy)) { + trace_adreno_cmdbatch_recovery(cmdbatch, BIT(KGSL_FT_SKIPIB)); + set_bit(KGSL_FT_SKIPIB, &cmdbatch->fault_recovery); for (i = 0; i < count; i++) { - if (replay[i] != NULL) + if (replay[i] != NULL && + replay[i]->context->id == cmdbatch->context->id) cmdbatch_skip_ib(replay[i], base); } goto replay; } - if (cmdbatch->fault_policy & KGSL_FT_SKIPFRAME) { - - cmdbatch->fault_policy &= ~KGSL_FT_SKIPFRAME; + if (test_and_clear_bit(KGSL_FT_SKIPFRAME, &cmdbatch->fault_policy)) { + trace_adreno_cmdbatch_recovery(cmdbatch, + BIT(KGSL_FT_SKIPFRAME)); + set_bit(KGSL_FT_SKIPFRAME, &cmdbatch->fault_recovery); /* * Skip all the pending command batches for this context until @@ -857,13 +1085,14 @@ static void dispatcher_do_fault(struct kgsl_device *device) goto replay; } - /* If we get here then all the policies failed or FT is disabled */ + /* If we get here then all the policies failed */ + + pr_fault(device, cmdbatch, "gpu failed ctx %d ts %d\n", + cmdbatch->context->id, cmdbatch->timestamp); /* Invalidate the context */ adreno_drawctxt_invalidate(device, cmdbatch->context); - /* Remove any pending command batches that have been invalidated */ - remove_invalidated_cmdbatches(device, replay, count); replay: /* Reset the dispatcher queue */ @@ -872,19 +1101,17 @@ static void dispatcher_do_fault(struct kgsl_device *device) /* Reset the GPU */ mutex_lock(&device->mutex); + ret = adreno_reset(device); mutex_unlock(&device->mutex); + /* if any other fault got in until reset then ignore */ + fault = atomic_xchg(&dispatcher->fault, 0); /* If adreno_reset() fails then what hope do we have for the future? */ BUG_ON(ret); - /* - * Force the preamble on the first command (if applicable) to avoid any - * strange stage issues - */ - - if (replay[0]) - replay[0]->priv |= CMDBATCH_FLAG_FORCE_PREAMBLE; + /* Remove any pending command batches that have been invalidated */ + remove_invalidated_cmdbatches(device, replay, count); /* Replay the pending command buffers */ for (i = 0; i < count; i++) { @@ -895,11 +1122,21 @@ static void dispatcher_do_fault(struct kgsl_device *device) continue; /* - * Force each command batch to wait for idle - this avoids wierd + * Force the preamble on the first command (if applicable) to + * avoid any strange stage issues + */ + + if (first == 0) { + set_bit(CMDBATCH_FLAG_FORCE_PREAMBLE, &replay[i]->priv); + first = 1; + } + + /* + * Force each command batch to wait for idle - this avoids weird * CP parse issues */ - replay[i]->flags |= KGSL_CMD_FLAGS_WFI; + set_bit(CMDBATCH_FLAG_WFI, &replay[i]->priv); ret = sendcmd(adreno_dev, replay[i]); @@ -909,8 +1146,11 @@ static void dispatcher_do_fault(struct kgsl_device *device) */ if (ret) { - adreno_drawctxt_invalidate(device, cmdbatch->context); + pr_fault(device, replay[i], + "gpu reset failed ctx %d ts %d\n", + replay[i]->context->id, replay[i]->timestamp); + adreno_drawctxt_invalidate(device, replay[i]->context); remove_invalidated_cmdbatches(device, &replay[i], count - i); } @@ -921,6 +1161,8 @@ static void dispatcher_do_fault(struct kgsl_device *device) mutex_unlock(&device->mutex); kfree(replay); + + return 1; } static inline int cmdbatch_consumed(struct kgsl_cmdbatch *cmdbatch, @@ -930,6 +1172,30 @@ static inline int cmdbatch_consumed(struct kgsl_cmdbatch *cmdbatch, (timestamp_cmp(retired, cmdbatch->timestamp) < 0)); } +static void _print_recovery(struct kgsl_device *device, + struct kgsl_cmdbatch *cmdbatch) +{ + static struct { + unsigned int mask; + const char *str; + } flags[] = { ADRENO_FT_TYPES }; + + int i, nr = find_first_bit(&cmdbatch->fault_recovery, BITS_PER_LONG); + char *result = "unknown"; + + for (i = 0; i < ARRAY_SIZE(flags); i++) { + if (flags[i].mask == BIT(nr)) { + result = (char *) flags[i].str; + break; + } + } + + pr_fault(device, cmdbatch, + "gpu %s ctx %d ts %d policy %lX\n", + result, cmdbatch->context->id, cmdbatch->timestamp, + cmdbatch->fault_recovery); +} + /** * adreno_dispatcher_work() - Master work handler for the dispatcher * @work: Pointer to the work struct for the current work queue @@ -944,6 +1210,7 @@ static void adreno_dispatcher_work(struct work_struct *work) container_of(dispatcher, struct adreno_device, dispatcher); struct kgsl_device *device = &adreno_dev->dev; int count = 0; + int fault_handled = 0; mutex_lock(&dispatcher->mutex); @@ -964,12 +1231,18 @@ static void adreno_dispatcher_work(struct work_struct *work) * pointers and continue processing the queue */ - if (!kgsl_context_detached(cmdbatch->context)) - retired = kgsl_readtimestamp(device, cmdbatch->context, + retired = kgsl_readtimestamp(device, cmdbatch->context, KGSL_TIMESTAMP_RETIRED); - if (kgsl_context_detached(cmdbatch->context) || - (timestamp_cmp(cmdbatch->timestamp, retired) <= 0)) { + if ((timestamp_cmp(cmdbatch->timestamp, retired) <= 0)) { + + /* + * If the cmdbatch in question had faulted announce its + * successful completion to the world + */ + + if (cmdbatch->fault_recovery != 0) + _print_recovery(device, cmdbatch); trace_adreno_cmdbatch_retired(cmdbatch, dispatcher->inflight - 1); @@ -1005,19 +1278,17 @@ static void adreno_dispatcher_work(struct work_struct *work) * is to blame. Invalidate it, reset and replay */ - if (dispatcher->fault) { - dispatcher_do_fault(device); - dispatcher->fault = 0; + if (dispatcher_do_fault(device)) goto done; - } + fault_handled = 1; /* Get the last consumed timestamp */ consumed = kgsl_readtimestamp(device, cmdbatch->context, KGSL_TIMESTAMP_CONSUMED); /* - * Break here if fault detection is dsiabled for the context or - * if the long running IB detection is disabled device wide + * Break here if fault detection is disabled for the context or + * if the long running IB detection is disaled device wide * Long running command buffers will be allowed to run to * completion - but badly behaving command buffers (infinite * shaders etc) can end up running forever. @@ -1038,26 +1309,37 @@ static void adreno_dispatcher_work(struct work_struct *work) /* Boom goes the dynamite */ - KGSL_DRV_ERR(device, - "Context %d, timestamp %d ran too long\n", - drawctxt->base.id, drawctxt->timestamp); + pr_fault(device, cmdbatch, + "gpu timeout ctx %d ts %d\n", + cmdbatch->context->id, cmdbatch->timestamp); - dispatcher->fault = ADRENO_DISPATCHER_TIMEOUT_FAULT; + adreno_set_gpu_fault(adreno_dev, ADRENO_TIMEOUT_FAULT); dispatcher_do_fault(device); + fault_handled = 1; break; } + /* + * Call the dispatcher fault routine here so the fault bit gets cleared + * when no commands are in dispatcher but fault bit is set. This can + * happen on false hang detects + */ + if (!fault_handled && dispatcher_do_fault(device)) + goto done; /* * Decrement the active count to 0 - this will allow the system to go * into suspend even if there are queued command batches */ + mutex_lock(&device->mutex); if (count && dispatcher->inflight == 0) { - mutex_lock(&device->mutex); + del_timer_sync(&dispatcher->fault_timer); kgsl_active_count_put(device); - mutex_unlock(&device->mutex); + /* Queue back up the event processor to catch stragglers */ + queue_work(device->work_queue, &device->ts_expired_ws); } + mutex_unlock(&device->mutex); /* Dispatch new commands if we have the room */ if (dispatcher->inflight < _dispatcher_inflight) @@ -1071,9 +1353,6 @@ static void adreno_dispatcher_work(struct work_struct *work) /* Update the timeout timer for the next command batch */ mod_timer(&dispatcher->timer, cmdbatch->expires); - } else { - del_timer_sync(&dispatcher->timer); - del_timer_sync(&dispatcher->fault_timer); } /* Before leaving update the pwrscale information */ @@ -1123,17 +1402,16 @@ void adreno_dispatcher_fault_timer(unsigned long data) struct kgsl_device *device = &adreno_dev->dev; struct adreno_dispatcher *dispatcher = &adreno_dev->dispatcher; + BUG_ON(atomic_read(&device->active_cnt) == 0); + /* Leave if the user decided to turn off fast hang detection */ if (adreno_dev->fast_hang_detect == 0) return; - /* Don't do anything if the dispatcher is idle or faulted */ - if (dispatcher->inflight == 0 || dispatcher->fault) - return; - - /* Make sure the device is active before trying a read */ - if (device->state != KGSL_STATE_ACTIVE) + if (adreno_gpu_fault(adreno_dev)) { + adreno_dispatcher_schedule(device); return; + } /* * Read the fault registers - if it returns 0 then they haven't changed @@ -1141,7 +1419,7 @@ void adreno_dispatcher_fault_timer(unsigned long data) */ if (!fault_detect_read_compare(device)) { - dispatcher->fault = ADRENO_DISPATCHER_SOFT_FAULT; + adreno_set_gpu_fault(adreno_dev, ADRENO_SOFT_FAULT); adreno_dispatcher_schedule(device); } else { mod_timer(&dispatcher->fault_timer, @@ -1169,10 +1447,7 @@ void adreno_dispatcher_timer(unsigned long data) */ void adreno_dispatcher_irq_fault(struct kgsl_device *device) { - struct adreno_device *adreno_dev = ADRENO_DEVICE(device); - struct adreno_dispatcher *dispatcher = &adreno_dev->dispatcher; - - dispatcher->fault = ADRENO_DISPATCHER_HARD_FAULT; + adreno_set_gpu_fault(ADRENO_DEVICE(device), ADRENO_HARD_FAULT); adreno_dispatcher_schedule(device); } @@ -1197,6 +1472,20 @@ void adreno_dispatcher_pause(struct adreno_device *adreno_dev) dispatcher->state = ADRENO_DISPATCHER_PAUSE; } +/** + * adreno_dispatcher_resume() - resume the dispatcher + * @adreno_dev: pointer to the adreno device structure + * + * Set the dispatcher active so it can start accepting commands again + */ +void adreno_dispatcher_resume(struct adreno_device *adreno_dev) +{ + struct adreno_dispatcher *dispatcher = &adreno_dev->dispatcher; + + dispatcher->state = ADRENO_DISPATCHER_ACTIVE; + adreno_dispatcher_schedule(&adreno_dev->dev); +} + /** * adreno_dispatcher_start() - activate the dispatcher * @adreno_dev: pointer to the adreno device structure @@ -1225,6 +1514,8 @@ void adreno_dispatcher_stop(struct adreno_device *adreno_dev) del_timer_sync(&dispatcher->timer); del_timer_sync(&dispatcher->fault_timer); + + dispatcher->state = ADRENO_DISPATCHER_PAUSE; } /** @@ -1247,9 +1538,6 @@ void adreno_dispatcher_close(struct adreno_device *adreno_dev) % ADRENO_DISPATCH_CMDQUEUE_SIZE; } - kfree(fault_detect_regs); - fault_detect_regs = NULL; - mutex_unlock(&dispatcher->mutex); kobject_put(&dispatcher->kobj); @@ -1405,11 +1693,5 @@ int adreno_dispatcher_init(struct adreno_device *adreno_dev) ret = kobject_init_and_add(&dispatcher->kobj, &ktype_dispatcher, &device->dev->kobj, "dispatch"); - fault_detect_regs = kzalloc(FT_DETECT_REGS_COUNT * sizeof(unsigned int), - GFP_KERNEL); - - if (fault_detect_regs == NULL) - ret = -ENOMEM; - return ret; } diff --git a/drivers/gpu/msm/adreno_drawctxt.c b/drivers/gpu/msm/adreno_drawctxt.c index 55802c62fe0..b666c47b667 100644 --- a/drivers/gpu/msm/adreno_drawctxt.c +++ b/drivers/gpu/msm/adreno_drawctxt.c @@ -293,7 +293,10 @@ int adreno_drawctxt_wait_global(struct adreno_device *adreno_dev, /* Needs to hold the device mutex */ BUG_ON(!mutex_is_locked(&device->mutex)); - _kgsl_context_get(context); + if (!_kgsl_context_get(context)) { + ret = -EINVAL; + goto done; + } trace_adreno_drawctxt_wait_start(KGSL_MEMSTORE_GLOBAL, timestamp); @@ -307,7 +310,7 @@ int adreno_drawctxt_wait_global(struct adreno_device *adreno_dev, mutex_unlock(&device->mutex); if (timeout) { - ret = (int) wait_event_interruptible_timeout(drawctxt->waiting, + ret = (int) wait_event_timeout(drawctxt->waiting, _check_global_timestamp(device, timestamp), msecs_to_jiffies(timeout)); @@ -316,7 +319,7 @@ int adreno_drawctxt_wait_global(struct adreno_device *adreno_dev, else if (ret > 0) ret = 0; } else { - ret = (int) wait_event_interruptible(drawctxt->waiting, + wait_event(drawctxt->waiting, _check_global_timestamp(device, timestamp)); } @@ -348,6 +351,18 @@ void adreno_drawctxt_invalidate(struct kgsl_device *device, /* Clear the pending queue */ mutex_lock(&drawctxt->mutex); + /* + * set the timestamp to the last value since the context is invalidated + * and we want the pending events for this context to go away + */ + kgsl_sharedmem_writel(device, &device->memstore, + KGSL_MEMSTORE_OFFSET(context->id, soptimestamp), + drawctxt->timestamp); + + kgsl_sharedmem_writel(device, &device->memstore, + KGSL_MEMSTORE_OFFSET(context->id, eoptimestamp), + drawctxt->timestamp); + while (drawctxt->cmdqueue_head != drawctxt->cmdqueue_tail) { struct kgsl_cmdbatch *cmdbatch = drawctxt->cmdqueue[drawctxt->cmdqueue_head]; @@ -375,17 +390,14 @@ void adreno_drawctxt_invalidate(struct kgsl_device *device, /** * adreno_drawctxt_create - create a new adreno draw context - * @device - KGSL device to create the context on - * @pagetable - Pagetable for the context - * @context- Generic KGSL context structure - * @flags - flags for the context (passed from user space) + * @dev_priv: the owner of the context + * @flags: flags for the context (passed from user space) * - * Create a new draw context for the 3D core. Return 0 on success, - * or error code on failure. + * Create and return a new draw context for the 3D core. */ - struct kgsl_context * +struct kgsl_context * adreno_drawctxt_create(struct kgsl_device_private *dev_priv, - uint32_t *flags) + uint32_t *flags) { struct adreno_context *drawctxt; struct kgsl_device *device = dev_priv->device; @@ -393,7 +405,6 @@ adreno_drawctxt_create(struct kgsl_device_private *dev_priv, int ret; drawctxt = kzalloc(sizeof(struct adreno_context), GFP_KERNEL); - if (drawctxt == NULL) return ERR_PTR(-ENOMEM); @@ -448,16 +459,16 @@ adreno_drawctxt_create(struct kgsl_device_private *dev_priv, if (ret) goto err; - kgsl_sharedmem_writel(&device->memstore, + kgsl_sharedmem_writel(device, &device->memstore, KGSL_MEMSTORE_OFFSET(drawctxt->base.id, soptimestamp), 0); - kgsl_sharedmem_writel(&device->memstore, + kgsl_sharedmem_writel(device, &device->memstore, KGSL_MEMSTORE_OFFSET(drawctxt->base.id, eoptimestamp), 0); return &drawctxt->base; err: - kgsl_context_put(&drawctxt->base); + kgsl_context_detach(&drawctxt->base); return ERR_PTR(ret); } @@ -532,14 +543,33 @@ int adreno_drawctxt_detach(struct kgsl_context *context) } mutex_unlock(&drawctxt->mutex); + /* + * internal_timestamp is set in adreno_ringbuffer_addcmds, + * which holds the device mutex. The entire context destroy + * process requires the device mutex as well. But lets + * make sure we notice if the locking changes. + */ + BUG_ON(!mutex_is_locked(&device->mutex)); /* Wait for the last global timestamp to pass before continuing */ ret = adreno_drawctxt_wait_global(adreno_dev, context, drawctxt->internal_timestamp, 10 * 1000); + kgsl_sharedmem_writel(device, &device->memstore, + KGSL_MEMSTORE_OFFSET(context->id, soptimestamp), + drawctxt->timestamp); + + kgsl_sharedmem_writel(device, &device->memstore, + KGSL_MEMSTORE_OFFSET(context->id, eoptimestamp), + drawctxt->timestamp); + kgsl_sharedmem_free(&drawctxt->gpustate); kgsl_sharedmem_free(&drawctxt->context_gmem_shadow.gmemshadow); + /* wake threads waiting to submit commands from this context */ + wake_up_interruptible_all(&drawctxt->waiting); + wake_up_interruptible_all(&drawctxt->wq); + return ret; } @@ -610,20 +640,20 @@ int adreno_drawctxt_switch(struct adreno_device *adreno_dev, return ret; } - KGSL_CTXT_INFO(device, "from %d to %d flags %d\n", - adreno_dev->drawctxt_active ? - adreno_dev->drawctxt_active->base.id : 0, - drawctxt ? drawctxt->base.id : 0, flags); + trace_adreno_drawctxt_switch(adreno_dev->drawctxt_active, + drawctxt, flags); /* Save the old context */ - ret = adreno_dev->gpudev->ctxt_save(adreno_dev, - adreno_dev->drawctxt_active); - - if (ret) { - KGSL_DRV_ERR(device, - "Error in GPU context %d save: %d\n", - adreno_dev->drawctxt_active->base.id, ret); - return ret; + if (adreno_dev->gpudev->ctxt_save) { + ret = adreno_dev->gpudev->ctxt_save(adreno_dev, + adreno_dev->drawctxt_active); + + if (ret) { + KGSL_DRV_ERR(device, + "Error in GPU context %d save: %d\n", + adreno_dev->drawctxt_active->base.id, ret); + return ret; + } } /* Put the old instance of the active drawctxt */ @@ -631,8 +661,10 @@ int adreno_drawctxt_switch(struct adreno_device *adreno_dev, kgsl_context_put(&adreno_dev->drawctxt_active->base); /* Get a refcount to the new instance */ - if (drawctxt) - _kgsl_context_get(&drawctxt->base); + if (drawctxt) { + if (!_kgsl_context_get(&drawctxt->base)) + return -EINVAL; + } /* Set the new context */ ret = adreno_dev->gpudev->ctxt_restore(adreno_dev, drawctxt); diff --git a/drivers/gpu/msm/adreno_drawctxt.h b/drivers/gpu/msm/adreno_drawctxt.h index dddc20629b7..0f65d4b565b 100644 --- a/drivers/gpu/msm/adreno_drawctxt.h +++ b/drivers/gpu/msm/adreno_drawctxt.h @@ -107,6 +107,7 @@ struct gmem_shadow_t { * @id: Unique integer ID of the context * @timestamp: Last issued context-specific timestamp * @internal_timestamp: Global timestamp of the last issued command + * NOTE: guarded by device->mutex, not drawctxt->mutex! * @state: Current state of the context * @flags: Bitfield controlling behavior of the context * @type: Context type (GL, CL, RS) diff --git a/drivers/gpu/msm/adreno_pm4types.h b/drivers/gpu/msm/adreno_pm4types.h index a3fa3123265..e6ec91df079 100644 --- a/drivers/gpu/msm/adreno_pm4types.h +++ b/drivers/gpu/msm/adreno_pm4types.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2002,2007-2012, The Linux Foundation. All rights reserved. +/* Copyright (c) 2002,2007-2013, The Linux Foundation. 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 and @@ -177,6 +177,8 @@ /* Load a buffer with pre-fetch enabled */ #define CP_INDIRECT_BUFFER_PFE 0x3F +#define CP_EXEC_CL 0x31 + #define CP_LOADSTATE_DSTOFFSET_SHIFT 0x00000000 #define CP_LOADSTATE_STATESRC_SHIFT 0x00000010 #define CP_LOADSTATE_STATEBLOCKID_SHIFT 0x00000013 diff --git a/drivers/gpu/msm/adreno_postmortem.c b/drivers/gpu/msm/adreno_postmortem.c index 8a166fe92f7..33aa0954976 100644 --- a/drivers/gpu/msm/adreno_postmortem.c +++ b/drivers/gpu/msm/adreno_postmortem.c @@ -30,19 +30,19 @@ #define NUM_DWORDS_OF_RINGBUFFER_HISTORY 100 struct pm_id_name { - uint32_t id; + enum adreno_regs id; char name[9]; }; static const struct pm_id_name pm0_types[] = { - {REG_PA_SC_AA_CONFIG, "RPASCAAC"}, - {REG_RBBM_PM_OVERRIDE2, "RRBBPMO2"}, - {REG_SCRATCH_REG2, "RSCRTRG2"}, - {REG_SQ_GPR_MANAGEMENT, "RSQGPRMN"}, - {REG_SQ_INST_STORE_MANAGMENT, "RSQINSTS"}, - {REG_TC_CNTL_STATUS, "RTCCNTLS"}, - {REG_TP0_CHICKEN, "RTP0CHCK"}, - {REG_CP_TIMESTAMP, "CP_TM_ST"}, + {ADRENO_REG_PA_SC_AA_CONFIG, "RPASCAAC"}, + {ADRENO_REG_RBBM_PM_OVERRIDE2, "RRBBPMO2"}, + {ADRENO_REG_SCRATCH_REG2, "RSCRTRG2"}, + {ADRENO_REG_SQ_GPR_MANAGEMENT, "RSQGPRMN"}, + {ADRENO_REG_SQ_INST_STORE_MANAGMENT, "RSQINSTS"}, + {ADRENO_REG_TC_CNTL_STATUS, "RTCCNTLS"}, + {ADRENO_REG_TP0_CHICKEN, "RTP0CHCK"}, + {ADRENO_REG_CP_TIMESTAMP, "CP_TM_ST"}, }; static const struct pm_id_name pm3_types[] = { @@ -68,6 +68,16 @@ static const struct pm_id_name pm3_types[] = { {CP_SET_PROTECTED_MODE, "ST_PRT_M"}, {CP_SET_SHADER_BASES, "ST_SHD_B"}, {CP_WAIT_FOR_IDLE, "WAIT4IDL"}, + {CP_WAIT_FOR_ME, "WAIT4ME"}, + {CP_WAIT_REG_EQ, "WAITRGEQ"}, +}; + +static const struct pm_id_name pm3_nop_values[] = { + {KGSL_CONTEXT_TO_MEM_IDENTIFIER, "CTX_SWCH"}, + {KGSL_CMD_IDENTIFIER, "CMD__EXT"}, + {KGSL_CMD_INTERNAL_IDENTIFIER, "CMD__INT"}, + {KGSL_START_OF_IB_IDENTIFIER, "IB_START"}, + {KGSL_END_OF_IB_IDENTIFIER, "IB___END"}, }; static uint32_t adreno_is_pm4_len(uint32_t word) @@ -78,8 +88,9 @@ static uint32_t adreno_is_pm4_len(uint32_t word) return (word >> 16) & 0x3FFF; } -static bool adreno_is_pm4_type(uint32_t word) +static bool adreno_is_pm4_type(struct kgsl_device *device, uint32_t word) { + struct adreno_device *adreno_dev = ADRENO_DEVICE(device); int i; if (word == INVALID_RB_CMD) @@ -90,7 +101,8 @@ static bool adreno_is_pm4_type(uint32_t word) if ((word & (3<<30)) == CP_TYPE0_PKT) { for (i = 0; i < ARRAY_SIZE(pm0_types); ++i) { - if ((word & 0x7FFF) == pm0_types[i].id) + if ((word & 0x7FFF) == adreno_getreg(adreno_dev, + pm0_types[i].id)) return 1; } return 0; @@ -129,6 +141,28 @@ static const char *adreno_pm4_name(uint32_t word) return "????????"; } +static bool adreno_is_pm3_nop_value(uint32_t word) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(pm3_nop_values); ++i) { + if (word == pm3_nop_values[i].id) + return 1; + } + return 0; +} + +static const char *adreno_pm3_nop_name(uint32_t word) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(pm3_nop_values); ++i) { + if (word == pm3_nop_values[i].id) + return pm3_nop_values[i].name; + } + return "????????"; +} + static void adreno_dump_regs(struct kgsl_device *device, const int *registers, int size) { @@ -157,11 +191,13 @@ static void adreno_dump_regs(struct kgsl_device *device, } } -static void dump_ib(struct kgsl_device *device, char* buffId, uint32_t pt_base, - uint32_t base_offset, uint32_t ib_base, uint32_t ib_size, bool dump) +static void dump_ib(struct kgsl_device *device, char *buffId, + phys_addr_t pt_base, uint32_t base_offset, uint32_t ib_base, + uint32_t ib_size, bool dump) { + struct kgsl_mem_entry *ent = NULL; uint8_t *base_addr = adreno_convertaddr(device, pt_base, - ib_base, ib_size*sizeof(uint32_t)); + ib_base, ib_size*sizeof(uint32_t), &ent); if (base_addr && dump) print_hex_dump(KERN_ERR, buffId, DUMP_PREFIX_OFFSET, @@ -171,6 +207,10 @@ static void dump_ib(struct kgsl_device *device, char* buffId, uint32_t pt_base, "offset:%5.5X%s\n", buffId, ib_base, ib_size*4, base_offset, base_addr ? "" : " [Invalid]"); + if (ent) { + kgsl_memdesc_unmap(&ent->memdesc); + kgsl_mem_entry_put(ent); + } } #define IB_LIST_SIZE 64 @@ -181,7 +221,7 @@ struct ib_list { uint32_t offsets[IB_LIST_SIZE]; }; -static void dump_ib1(struct kgsl_device *device, uint32_t pt_base, +static void dump_ib1(struct kgsl_device *device, phys_addr_t pt_base, uint32_t base_offset, uint32_t ib1_base, uint32_t ib1_size, struct ib_list *ib_list, bool dump) @@ -189,13 +229,14 @@ static void dump_ib1(struct kgsl_device *device, uint32_t pt_base, int i, j; uint32_t value; uint32_t *ib1_addr; + struct kgsl_mem_entry *ent = NULL; dump_ib(device, "IB1:", pt_base, base_offset, ib1_base, ib1_size, dump); /* fetch virtual address for given IB base */ ib1_addr = (uint32_t *)adreno_convertaddr(device, pt_base, - ib1_base, ib1_size*sizeof(uint32_t)); + ib1_base, ib1_size*sizeof(uint32_t), &ent); if (!ib1_addr) return; @@ -222,10 +263,14 @@ static void dump_ib1(struct kgsl_device *device, uint32_t pt_base, ++ib_list->count; } } + if (ent) { + kgsl_memdesc_unmap(&ent->memdesc); + kgsl_mem_entry_put(ent); + } } -static void adreno_dump_rb_buffer(const void *buf, size_t len, - char *linebuf, size_t linebuflen, int *argp) +static void adreno_dump_rb_buffer(struct kgsl_device *device, const void *buf, + size_t len, char *linebuf, size_t linebuflen, int *argp) { const u32 *ptr4 = buf; const int ngroups = len; @@ -240,13 +285,18 @@ static void adreno_dump_rb_buffer(const void *buf, size_t len, lx += scnprintf(linebuf + lx, linebuflen - lx, " "); else nxsp = 1; - if (!*argp && adreno_is_pm4_type(ptr4[j])) { + if (!*argp && adreno_is_pm4_type(device, ptr4[j])) { lx += scnprintf(linebuf + lx, linebuflen - lx, "%s", adreno_pm4_name(ptr4[j])); *argp = -(adreno_is_pm4_len(ptr4[j])+1); } else { - lx += scnprintf(linebuf + lx, linebuflen - lx, - "%8.8X", ptr4[j]); + if (adreno_is_pm3_nop_value(ptr4[j])) + lx += scnprintf(linebuf + lx, linebuflen - lx, + "%s", adreno_pm3_nop_name(ptr4[j])); + else + lx += scnprintf(linebuf + lx, linebuflen - lx, + "%8.8X", ptr4[j]); + if (*argp > 1) --*argp; else if (*argp == 1) { @@ -287,18 +337,13 @@ void adreno_dump_rb(struct kgsl_device *device, const void *buf, hex_dump_to_buffer(ptr+i, linelen*4, rowsize*4, 4, linebuf, sizeof(linebuf), 0); else - adreno_dump_rb_buffer(ptr+i, linelen, linebuf, + adreno_dump_rb_buffer(device, ptr+i, linelen, linebuf, sizeof(linebuf), &args); KGSL_LOG_DUMP(device, "RB: %4.4X:%s\n", (start+i)%size, linebuf); } } -struct log_field { - bool show; - const char *display; -}; - static int adreno_dump_fields_line(struct kgsl_device *device, const char *start, char *str, int slen, const struct log_field **lines, @@ -333,7 +378,7 @@ static int adreno_dump_fields_line(struct kgsl_device *device, return num; } -static void adreno_dump_fields(struct kgsl_device *device, +void adreno_dump_fields(struct kgsl_device *device, const char *start, const struct log_field *lines, int num) { @@ -353,335 +398,13 @@ static void adreno_dump_fields(struct kgsl_device *device, sstr = " "; } } - -static void adreno_dump_a3xx(struct kgsl_device *device) -{ - unsigned int r1, r2, r3, rbbm_status; - unsigned int cp_stat, rb_count; - struct adreno_device *adreno_dev = ADRENO_DEVICE(device); - - kgsl_regread(device, adreno_dev->gpudev->reg_rbbm_status, &rbbm_status); - KGSL_LOG_DUMP(device, "RBBM: STATUS = %08X\n", rbbm_status); - - { - struct log_field lines[] = { - {rbbm_status & BIT(0), "HI busy "}, - {rbbm_status & BIT(1), "CP ME busy "}, - {rbbm_status & BIT(2), "CP PFP busy "}, - {rbbm_status & BIT(14), "CP NRT busy "}, - {rbbm_status & BIT(15), "VBIF busy "}, - {rbbm_status & BIT(16), "TSE busy "}, - {rbbm_status & BIT(17), "RAS busy "}, - {rbbm_status & BIT(18), "RB busy "}, - {rbbm_status & BIT(19), "PC DCALL bsy"}, - {rbbm_status & BIT(20), "PC VSD busy "}, - {rbbm_status & BIT(21), "VFD busy "}, - {rbbm_status & BIT(22), "VPC busy "}, - {rbbm_status & BIT(23), "UCHE busy "}, - {rbbm_status & BIT(24), "SP busy "}, - {rbbm_status & BIT(25), "TPL1 busy "}, - {rbbm_status & BIT(26), "MARB busy "}, - {rbbm_status & BIT(27), "VSC busy "}, - {rbbm_status & BIT(28), "ARB busy "}, - {rbbm_status & BIT(29), "HLSQ busy "}, - {rbbm_status & BIT(30), "GPU bsy noHC"}, - {rbbm_status & BIT(31), "GPU busy "}, - }; - adreno_dump_fields(device, " STATUS=", lines, - ARRAY_SIZE(lines)); - } - - kgsl_regread(device, REG_CP_RB_BASE, &r1); - kgsl_regread(device, REG_CP_RB_CNTL, &r2); - rb_count = 2 << (r2 & (BIT(6) - 1)); - kgsl_regread(device, REG_CP_RB_RPTR_ADDR, &r3); - KGSL_LOG_DUMP(device, - "CP_RB: BASE = %08X | CNTL = %08X | RPTR_ADDR = %08X" - "| rb_count = %08X\n", r1, r2, r3, rb_count); - - kgsl_regread(device, REG_CP_RB_RPTR, &r1); - kgsl_regread(device, REG_CP_RB_WPTR, &r2); - kgsl_regread(device, REG_CP_RB_RPTR_WR, &r3); - KGSL_LOG_DUMP(device, - " RPTR = %08X | WPTR = %08X | RPTR_WR = %08X" - "\n", r1, r2, r3); - - kgsl_regread(device, REG_CP_IB1_BASE, &r1); - kgsl_regread(device, REG_CP_IB1_BUFSZ, &r2); - KGSL_LOG_DUMP(device, "CP_IB1: BASE = %08X | BUFSZ = %d\n", r1, r2); - - kgsl_regread(device, REG_CP_ME_CNTL, &r1); - kgsl_regread(device, REG_CP_ME_STATUS, &r2); - KGSL_LOG_DUMP(device, "CP_ME: CNTL = %08X | STATUS = %08X\n", r1, r2); - - kgsl_regread(device, REG_CP_STAT, &cp_stat); - KGSL_LOG_DUMP(device, "CP_STAT = %08X\n", cp_stat); -#ifndef CONFIG_MSM_KGSL_PSTMRTMDMP_CP_STAT_NO_DETAIL - { - struct log_field lns[] = { - {cp_stat & BIT(0), "WR_BSY 0"}, - {cp_stat & BIT(1), "RD_RQ_BSY 1"}, - {cp_stat & BIT(2), "RD_RTN_BSY 2"}, - }; - adreno_dump_fields(device, " MIU=", lns, ARRAY_SIZE(lns)); - } - { - struct log_field lns[] = { - {cp_stat & BIT(5), "RING_BUSY 5"}, - {cp_stat & BIT(6), "NDRCTS_BSY 6"}, - {cp_stat & BIT(7), "NDRCT2_BSY 7"}, - {cp_stat & BIT(9), "ST_BUSY 9"}, - {cp_stat & BIT(10), "BUSY 10"}, - }; - adreno_dump_fields(device, " CSF=", lns, ARRAY_SIZE(lns)); - } - { - struct log_field lns[] = { - {cp_stat & BIT(11), "RNG_Q_BSY 11"}, - {cp_stat & BIT(12), "NDRCTS_Q_B12"}, - {cp_stat & BIT(13), "NDRCT2_Q_B13"}, - {cp_stat & BIT(16), "ST_QUEUE_B16"}, - {cp_stat & BIT(17), "PFP_BUSY 17"}, - }; - adreno_dump_fields(device, " RING=", lns, ARRAY_SIZE(lns)); - } - { - struct log_field lns[] = { - {cp_stat & BIT(3), "RBIU_BUSY 3"}, - {cp_stat & BIT(4), "RCIU_BUSY 4"}, - {cp_stat & BIT(8), "EVENT_BUSY 8"}, - {cp_stat & BIT(18), "MQ_RG_BSY 18"}, - {cp_stat & BIT(19), "MQ_NDRS_BS19"}, - {cp_stat & BIT(20), "MQ_NDR2_BS20"}, - {cp_stat & BIT(21), "MIU_WC_STL21"}, - {cp_stat & BIT(22), "CP_NRT_BSY22"}, - {cp_stat & BIT(23), "3D_BUSY 23"}, - {cp_stat & BIT(26), "ME_BUSY 26"}, - {cp_stat & BIT(27), "RB_FFO_BSY27"}, - {cp_stat & BIT(28), "CF_FFO_BSY28"}, - {cp_stat & BIT(29), "PS_FFO_BSY29"}, - {cp_stat & BIT(30), "VS_FFO_BSY30"}, - {cp_stat & BIT(31), "CP_BUSY 31"}, - }; - adreno_dump_fields(device, " CP_STT=", lns, ARRAY_SIZE(lns)); - } -#endif - - kgsl_regread(device, A3XX_RBBM_INT_0_STATUS, &r1); - KGSL_LOG_DUMP(device, "MSTR_INT_SGNL = %08X\n", r1); - { - struct log_field ints[] = { - {r1 & BIT(0), "RBBM_GPU_IDLE 0"}, - {r1 & BIT(1), "RBBM_AHB_ERROR 1"}, - {r1 & BIT(2), "RBBM_REG_TIMEOUT 2"}, - {r1 & BIT(3), "RBBM_ME_MS_TIMEOUT 3"}, - {r1 & BIT(4), "RBBM_PFP_MS_TIMEOUT 4"}, - {r1 & BIT(5), "RBBM_ATB_BUS_OVERFLOW 5"}, - {r1 & BIT(6), "VFD_ERROR 6"}, - {r1 & BIT(7), "CP_SW_INT 7"}, - {r1 & BIT(8), "CP_T0_PACKET_IN_IB 8"}, - {r1 & BIT(9), "CP_OPCODE_ERROR 9"}, - {r1 & BIT(10), "CP_RESERVED_BIT_ERROR 10"}, - {r1 & BIT(11), "CP_HW_FAULT 11"}, - {r1 & BIT(12), "CP_DMA 12"}, - {r1 & BIT(13), "CP_IB2_INT 13"}, - {r1 & BIT(14), "CP_IB1_INT 14"}, - {r1 & BIT(15), "CP_RB_INT 15"}, - {r1 & BIT(16), "CP_REG_PROTECT_FAULT 16"}, - {r1 & BIT(17), "CP_RB_DONE_TS 17"}, - {r1 & BIT(18), "CP_VS_DONE_TS 18"}, - {r1 & BIT(19), "CP_PS_DONE_TS 19"}, - {r1 & BIT(20), "CACHE_FLUSH_TS 20"}, - {r1 & BIT(21), "CP_AHB_ERROR_HALT 21"}, - {r1 & BIT(24), "MISC_HANG_DETECT 24"}, - {r1 & BIT(25), "UCHE_OOB_ACCESS 25"}, - }; - adreno_dump_fields(device, "INT_SGNL=", ints, ARRAY_SIZE(ints)); - } -} - -static void adreno_dump_a2xx(struct kgsl_device *device) -{ - unsigned int r1, r2, r3, rbbm_status; - unsigned int cp_stat, rb_count; - struct adreno_device *adreno_dev = ADRENO_DEVICE(device); - - kgsl_regread(device, adreno_dev->gpudev->reg_rbbm_status, &rbbm_status); - - kgsl_regread(device, REG_RBBM_PM_OVERRIDE1, &r2); - kgsl_regread(device, REG_RBBM_PM_OVERRIDE2, &r3); - KGSL_LOG_DUMP(device, "RBBM: STATUS = %08X | PM_OVERRIDE1 = %08X | " - "PM_OVERRIDE2 = %08X\n", rbbm_status, r2, r3); - - kgsl_regread(device, REG_RBBM_INT_CNTL, &r1); - kgsl_regread(device, REG_RBBM_INT_STATUS, &r2); - kgsl_regread(device, REG_RBBM_READ_ERROR, &r3); - KGSL_LOG_DUMP(device, " INT_CNTL = %08X | INT_STATUS = %08X | " - "READ_ERROR = %08X\n", r1, r2, r3); - - { - char cmdFifo[16]; - struct log_field lines[] = { - {rbbm_status & 0x001F, cmdFifo}, - {rbbm_status & BIT(5), "TC busy "}, - {rbbm_status & BIT(8), "HIRQ pending"}, - {rbbm_status & BIT(9), "CPRQ pending"}, - {rbbm_status & BIT(10), "CFRQ pending"}, - {rbbm_status & BIT(11), "PFRQ pending"}, - {rbbm_status & BIT(12), "VGT 0DMA bsy"}, - {rbbm_status & BIT(14), "RBBM WU busy"}, - {rbbm_status & BIT(16), "CP NRT busy "}, - {rbbm_status & BIT(18), "MH busy "}, - {rbbm_status & BIT(19), "MH chncy bsy"}, - {rbbm_status & BIT(21), "SX busy "}, - {rbbm_status & BIT(22), "TPC busy "}, - {rbbm_status & BIT(24), "SC CNTX busy"}, - {rbbm_status & BIT(25), "PA busy "}, - {rbbm_status & BIT(26), "VGT busy "}, - {rbbm_status & BIT(27), "SQ cntx1 bsy"}, - {rbbm_status & BIT(28), "SQ cntx0 bsy"}, - {rbbm_status & BIT(30), "RB busy "}, - {rbbm_status & BIT(31), "Grphs pp bsy"}, - }; - snprintf(cmdFifo, sizeof(cmdFifo), "CMD FIFO=%01X ", - rbbm_status & 0xf); - adreno_dump_fields(device, " STATUS=", lines, - ARRAY_SIZE(lines)); - } - - kgsl_regread(device, REG_CP_RB_BASE, &r1); - kgsl_regread(device, REG_CP_RB_CNTL, &r2); - rb_count = 2 << (r2 & (BIT(6)-1)); - kgsl_regread(device, REG_CP_RB_RPTR_ADDR, &r3); - KGSL_LOG_DUMP(device, - "CP_RB: BASE = %08X | CNTL = %08X | RPTR_ADDR = %08X" - "| rb_count = %08X\n", r1, r2, r3, rb_count); - { - struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer; - if (rb->sizedwords != rb_count) - rb_count = rb->sizedwords; - } - - kgsl_regread(device, REG_CP_RB_RPTR, &r1); - kgsl_regread(device, REG_CP_RB_WPTR, &r2); - kgsl_regread(device, REG_CP_RB_RPTR_WR, &r3); - KGSL_LOG_DUMP(device, - " RPTR = %08X | WPTR = %08X | RPTR_WR = %08X" - "\n", r1, r2, r3); - - kgsl_regread(device, REG_CP_IB1_BASE, &r1); - kgsl_regread(device, REG_CP_IB1_BUFSZ, &r2); - KGSL_LOG_DUMP(device, "CP_IB1: BASE = %08X | BUFSZ = %d\n", r1, r2); - - kgsl_regread(device, REG_CP_IB2_BASE, &r1); - kgsl_regread(device, REG_CP_IB2_BUFSZ, &r2); - KGSL_LOG_DUMP(device, "CP_IB2: BASE = %08X | BUFSZ = %d\n", r1, r2); - - kgsl_regread(device, REG_CP_INT_CNTL, &r1); - kgsl_regread(device, REG_CP_INT_STATUS, &r2); - KGSL_LOG_DUMP(device, "CP_INT: CNTL = %08X | STATUS = %08X\n", r1, r2); - - kgsl_regread(device, REG_CP_ME_CNTL, &r1); - kgsl_regread(device, REG_CP_ME_STATUS, &r2); - kgsl_regread(device, REG_MASTER_INT_SIGNAL, &r3); - KGSL_LOG_DUMP(device, - "CP_ME: CNTL = %08X | STATUS = %08X | MSTR_INT_SGNL = " - "%08X\n", r1, r2, r3); - - kgsl_regread(device, REG_CP_STAT, &cp_stat); - KGSL_LOG_DUMP(device, "CP_STAT = %08X\n", cp_stat); -#ifndef CONFIG_MSM_KGSL_PSTMRTMDMP_CP_STAT_NO_DETAIL - { - struct log_field lns[] = { - {cp_stat & BIT(0), "WR_BSY 0"}, - {cp_stat & BIT(1), "RD_RQ_BSY 1"}, - {cp_stat & BIT(2), "RD_RTN_BSY 2"}, - }; - adreno_dump_fields(device, " MIU=", lns, ARRAY_SIZE(lns)); - } - { - struct log_field lns[] = { - {cp_stat & BIT(5), "RING_BUSY 5"}, - {cp_stat & BIT(6), "NDRCTS_BSY 6"}, - {cp_stat & BIT(7), "NDRCT2_BSY 7"}, - {cp_stat & BIT(9), "ST_BUSY 9"}, - {cp_stat & BIT(10), "BUSY 10"}, - }; - adreno_dump_fields(device, " CSF=", lns, ARRAY_SIZE(lns)); - } - { - struct log_field lns[] = { - {cp_stat & BIT(11), "RNG_Q_BSY 11"}, - {cp_stat & BIT(12), "NDRCTS_Q_B12"}, - {cp_stat & BIT(13), "NDRCT2_Q_B13"}, - {cp_stat & BIT(16), "ST_QUEUE_B16"}, - {cp_stat & BIT(17), "PFP_BUSY 17"}, - }; - adreno_dump_fields(device, " RING=", lns, ARRAY_SIZE(lns)); - } - { - struct log_field lns[] = { - {cp_stat & BIT(3), "RBIU_BUSY 3"}, - {cp_stat & BIT(4), "RCIU_BUSY 4"}, - {cp_stat & BIT(18), "MQ_RG_BSY 18"}, - {cp_stat & BIT(19), "MQ_NDRS_BS19"}, - {cp_stat & BIT(20), "MQ_NDR2_BS20"}, - {cp_stat & BIT(21), "MIU_WC_STL21"}, - {cp_stat & BIT(22), "CP_NRT_BSY22"}, - {cp_stat & BIT(23), "3D_BUSY 23"}, - {cp_stat & BIT(26), "ME_BUSY 26"}, - {cp_stat & BIT(29), "ME_WC_BSY 29"}, - {cp_stat & BIT(30), "MIU_FF EM 30"}, - {cp_stat & BIT(31), "CP_BUSY 31"}, - }; - adreno_dump_fields(device, " CP_STT=", lns, ARRAY_SIZE(lns)); - } -#endif - - kgsl_regread(device, REG_SCRATCH_REG0, &r1); - KGSL_LOG_DUMP(device, "SCRATCH_REG0 = %08X\n", r1); - - kgsl_regread(device, REG_COHER_SIZE_PM4, &r1); - kgsl_regread(device, REG_COHER_BASE_PM4, &r2); - kgsl_regread(device, REG_COHER_STATUS_PM4, &r3); - KGSL_LOG_DUMP(device, - "COHER: SIZE_PM4 = %08X | BASE_PM4 = %08X | STATUS_PM4" - " = %08X\n", r1, r2, r3); - - kgsl_regread(device, MH_AXI_ERROR, &r1); - KGSL_LOG_DUMP(device, "MH: AXI_ERROR = %08X\n", r1); - - kgsl_regread(device, MH_MMU_PAGE_FAULT, &r1); - kgsl_regread(device, MH_MMU_CONFIG, &r2); - kgsl_regread(device, MH_MMU_MPU_BASE, &r3); - KGSL_LOG_DUMP(device, - "MH_MMU: PAGE_FAULT = %08X | CONFIG = %08X | MPU_BASE =" - " %08X\n", r1, r2, r3); - - kgsl_regread(device, MH_MMU_MPU_END, &r1); - kgsl_regread(device, MH_MMU_VA_RANGE, &r2); - r3 = kgsl_mmu_get_current_ptbase(&device->mmu); - KGSL_LOG_DUMP(device, - " MPU_END = %08X | VA_RANGE = %08X | PT_BASE =" - " %08X\n", r1, r2, r3); - - KGSL_LOG_DUMP(device, "PAGETABLE SIZE: %08X ", - kgsl_mmu_get_ptsize()); - - kgsl_regread(device, MH_MMU_TRAN_ERROR, &r1); - KGSL_LOG_DUMP(device, " TRAN_ERROR = %08X\n", r1); - - kgsl_regread(device, MH_INTERRUPT_MASK, &r1); - kgsl_regread(device, MH_INTERRUPT_STATUS, &r2); - KGSL_LOG_DUMP(device, - "MH_INTERRUPT: MASK = %08X | STATUS = %08X\n", r1, r2); -} +EXPORT_SYMBOL(adreno_dump_fields); int adreno_dump(struct kgsl_device *device, int manual) { - unsigned int cp_ib1_base, cp_ib1_bufsz; - unsigned int cp_ib2_base, cp_ib2_bufsz; - unsigned int pt_base, cur_pt_base; + unsigned int cp_ib1_base; + unsigned int cp_ib2_base; + phys_addr_t pt_base, cur_pt_base; unsigned int cp_rb_base, cp_rb_ctrl, rb_count; unsigned int cp_rb_wptr, cp_rb_rptr; unsigned int i; @@ -693,7 +416,6 @@ int adreno_dump(struct kgsl_device *device, int manual) unsigned int ts_processed = 0xdeaddead; struct kgsl_context *context; unsigned int context_id; - unsigned int rbbm_status; static struct ib_list ib_list; @@ -703,42 +425,31 @@ int adreno_dump(struct kgsl_device *device, int manual) mb(); - if (device->pm_dump_enable) { - if (adreno_is_a2xx(adreno_dev)) - adreno_dump_a2xx(device); - else if (adreno_is_a3xx(adreno_dev)) - adreno_dump_a3xx(device); - } - - kgsl_regread(device, adreno_dev->gpudev->reg_rbbm_status, &rbbm_status); + if (adreno_dev->gpudev->postmortem_dump) + adreno_dev->gpudev->postmortem_dump(adreno_dev); pt_base = kgsl_mmu_get_current_ptbase(&device->mmu); cur_pt_base = pt_base; - kgsl_regread(device, REG_CP_RB_BASE, &cp_rb_base); - kgsl_regread(device, REG_CP_RB_CNTL, &cp_rb_ctrl); + kgsl_regread(device, + adreno_getreg(adreno_dev, ADRENO_REG_CP_RB_BASE), + &cp_rb_base); + kgsl_regread(device, + adreno_getreg(adreno_dev, ADRENO_REG_CP_RB_CNTL), + &cp_rb_ctrl); rb_count = 2 << (cp_rb_ctrl & (BIT(6) - 1)); - kgsl_regread(device, REG_CP_RB_RPTR, &cp_rb_rptr); - kgsl_regread(device, REG_CP_RB_WPTR, &cp_rb_wptr); - kgsl_regread(device, REG_CP_IB1_BASE, &cp_ib1_base); - kgsl_regread(device, REG_CP_IB1_BUFSZ, &cp_ib1_bufsz); - kgsl_regread(device, REG_CP_IB2_BASE, &cp_ib2_base); - kgsl_regread(device, REG_CP_IB2_BUFSZ, &cp_ib2_bufsz); - - trace_adreno_gpu_fault(rbbm_status, cp_rb_rptr, cp_rb_wptr, - cp_ib1_base, cp_ib1_bufsz, cp_ib2_base, cp_ib2_bufsz); - - /* If postmortem dump is not enabled, dump minimal set and return */ - if (!device->pm_dump_enable) { - - KGSL_LOG_DUMP(device, - "RBBM STATUS %08X | IB1:%08X/%08X | IB2: %08X/%08X" - " | RPTR: %04X | WPTR: %04X\n", - rbbm_status, cp_ib1_base, cp_ib1_bufsz, cp_ib2_base, - cp_ib2_bufsz, cp_rb_rptr, cp_rb_wptr); - - return 0; - } + kgsl_regread(device, + adreno_getreg(adreno_dev, ADRENO_REG_CP_RB_RPTR), + &cp_rb_rptr); + kgsl_regread(device, + adreno_getreg(adreno_dev, ADRENO_REG_CP_RB_WPTR), + &cp_rb_wptr); + kgsl_regread(device, + adreno_getreg(adreno_dev, ADRENO_REG_CP_IB1_BASE), + &cp_ib1_base); + kgsl_regread(device, + adreno_getreg(adreno_dev, ADRENO_REG_CP_IB2_BASE), + &cp_ib2_base); kgsl_sharedmem_readl(&device->memstore, (unsigned int *) &context_id, @@ -823,21 +534,26 @@ int adreno_dump(struct kgsl_device *device, int manual) (num_iommu_units && this_cmd == kgsl_mmu_get_reg_gpuaddr(&device->mmu, 0, KGSL_IOMMU_CONTEXT_USER, - KGSL_IOMMU_CTX_TTBR0))) { - KGSL_LOG_DUMP(device, "Current pagetable: %x\t" - "pagetable base: %x\n", + KGSL_IOMMU_CTX_TTBR0)) || + (num_iommu_units && this_cmd == cp_type0_packet( + kgsl_mmu_get_reg_ahbaddr( + &device->mmu, 0, + KGSL_IOMMU_CONTEXT_USER, + KGSL_IOMMU_CTX_TTBR0), 1))) { + KGSL_LOG_DUMP(device, + "Current pagetable: %x\t pagetable base: %pa\n", kgsl_mmu_get_ptname_from_ptbase(&device->mmu, cur_pt_base), - cur_pt_base); + &cur_pt_base); /* Set cur_pt_base to the new pagetable base */ cur_pt_base = rb_copy[read_idx++]; - KGSL_LOG_DUMP(device, "New pagetable: %x\t" - "pagetable base: %x\n", + KGSL_LOG_DUMP(device, + "New pagetable: %x\t pagetable base: %pa\n", kgsl_mmu_get_ptname_from_ptbase(&device->mmu, cur_pt_base), - cur_pt_base); + &cur_pt_base); } } @@ -898,7 +614,8 @@ int adreno_dump(struct kgsl_device *device, int manual) adreno_dump_regs(device, a3xx_registers, a3xx_registers_count); - if (adreno_is_a330(adreno_dev)) + if (adreno_is_a330(adreno_dev) || + adreno_is_a305b(adreno_dev)) adreno_dump_regs(device, a330_registers, a330_registers_count); } diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c index ef696088eac..2fe2c4cb1c0 100644 --- a/drivers/gpu/msm/adreno_ringbuffer.c +++ b/drivers/gpu/msm/adreno_ringbuffer.c @@ -14,6 +14,8 @@ #include #include #include +#include +#include #include "kgsl.h" #include "kgsl_sharedmem.h" @@ -38,6 +40,7 @@ void adreno_ringbuffer_submit(struct adreno_ringbuffer *rb) { + struct adreno_device *adreno_dev = ADRENO_DEVICE(rb->device); BUG_ON(rb->wptr == 0); /* Let the pwrscale policy know that new commands have @@ -49,7 +52,7 @@ void adreno_ringbuffer_submit(struct adreno_ringbuffer *rb) */ mb(); - adreno_regwrite(rb->device, REG_CP_RB_WPTR, rb->wptr); + adreno_writereg(adreno_dev, ADRENO_REG_CP_RB_WPTR, rb->wptr); } static int @@ -64,6 +67,7 @@ adreno_ringbuffer_waitspace(struct adreno_ringbuffer *rb, unsigned long wait_time; unsigned long wait_timeout = msecs_to_jiffies(ADRENO_IDLE_TIMEOUT); unsigned long wait_time_part; + unsigned int rptr; /* if wptr ahead, fill the remaining with NOPs */ if (wptr_ahead) { @@ -73,19 +77,16 @@ adreno_ringbuffer_waitspace(struct adreno_ringbuffer *rb, cmds = (unsigned int *)rb->buffer_desc.hostptr + rb->wptr; cmds_gpu = rb->buffer_desc.gpuaddr + sizeof(uint)*rb->wptr; - GSL_RB_WRITE(cmds, cmds_gpu, cp_nop_packet(nopcount)); + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, + cp_nop_packet(nopcount)); /* Make sure that rptr is not 0 before submitting * commands at the end of ringbuffer. We do not * want the rptr and wptr to become equal when * the ringbuffer is not empty */ do { - GSL_RB_GET_READPTR(rb, &rb->rptr); - } while (!rb->rptr); - - rb->wptr++; - - adreno_ringbuffer_submit(rb); + rptr = adreno_get_rptr(rb); + } while (!rptr); rb->wptr = 0; } @@ -94,9 +95,9 @@ adreno_ringbuffer_waitspace(struct adreno_ringbuffer *rb, wait_time_part = jiffies + msecs_to_jiffies(KGSL_TIMEOUT_PART); /* wait for space in ringbuffer */ while (1) { - GSL_RB_GET_READPTR(rb, &rb->rptr); + rptr = adreno_get_rptr(rb); - freecmds = rb->rptr - rb->wptr; + freecmds = rptr - rb->wptr; if (freecmds == 0 || freecmds > numcmds) break; @@ -104,7 +105,7 @@ adreno_ringbuffer_waitspace(struct adreno_ringbuffer *rb, if (time_after(jiffies, wait_time)) { KGSL_DRV_ERR(rb->device, "Timed out while waiting for freespace in ringbuffer " - "rptr: 0x%x, wptr: 0x%x\n", rb->rptr, rb->wptr); + "rptr: 0x%x, wptr: 0x%x\n", rptr, rb->wptr); return -ETIMEDOUT; } @@ -118,11 +119,12 @@ unsigned int *adreno_ringbuffer_allocspace(struct adreno_ringbuffer *rb, { unsigned int *ptr = NULL; int ret = 0; + unsigned int rptr; BUG_ON(numcmds >= rb->sizedwords); - GSL_RB_GET_READPTR(rb, &rb->rptr); + rptr = adreno_get_rptr(rb); /* check for available space */ - if (rb->wptr >= rb->rptr) { + if (rb->wptr >= rptr) { /* wptr ahead or equal to rptr */ /* reserve dwords for nop packet */ if ((rb->wptr + numcmds) > (rb->sizedwords - @@ -131,7 +133,7 @@ unsigned int *adreno_ringbuffer_allocspace(struct adreno_ringbuffer *rb, numcmds, 1); } else { /* wptr behind rptr */ - if ((rb->wptr + numcmds) >= rb->rptr) + if ((rb->wptr + numcmds) >= rptr) ret = adreno_ringbuffer_waitspace(rb, context, numcmds, 0); /* check for remaining space */ @@ -209,8 +211,16 @@ int adreno_ringbuffer_read_pm4_ucode(struct kgsl_device *device) return ret; } - -int adreno_ringbuffer_load_pm4_ucode(struct kgsl_device *device) +/** + * adreno_ringbuffer_load_pm4_ucode() - Load pm4 ucode + * @device: Pointer to a KGSL device + * @start: Starting index in pm4 ucode to load + * @addr: Address to load the pm4 ucode + * + * Load the pm4 ucode from @start at @addr. + */ +int adreno_ringbuffer_load_pm4_ucode(struct kgsl_device *device, + unsigned int start, unsigned int addr) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); int i; @@ -224,11 +234,11 @@ int adreno_ringbuffer_load_pm4_ucode(struct kgsl_device *device) KGSL_DRV_INFO(device, "loading pm4 ucode version: %d\n", adreno_dev->pm4_fw_version); - adreno_regwrite(device, REG_CP_DEBUG, CP_DEBUG_DEFAULT); - adreno_regwrite(device, REG_CP_ME_RAM_WADDR, 0); + adreno_writereg(adreno_dev, ADRENO_REG_CP_DEBUG, CP_DEBUG_DEFAULT); + adreno_writereg(adreno_dev, ADRENO_REG_CP_ME_RAM_WADDR, addr); for (i = 1; i < adreno_dev->pm4_fw_size; i++) - adreno_regwrite(device, REG_CP_ME_RAM_DATA, - adreno_dev->pm4_fw[i]); + adreno_writereg(adreno_dev, ADRENO_REG_CP_ME_RAM_DATA, + adreno_dev->pm4_fw[i]); return 0; } @@ -264,7 +274,16 @@ int adreno_ringbuffer_read_pfp_ucode(struct kgsl_device *device) return ret; } -int adreno_ringbuffer_load_pfp_ucode(struct kgsl_device *device) +/** + * adreno_ringbuffer_load_pfp_ucode() - Load pfp ucode + * @device: Pointer to a KGSL device + * @start: Starting index in pfp ucode to load + * @addr: Address to load the pfp ucode + * + * Load the pfp ucode from @start at @addr. + */ +int adreno_ringbuffer_load_pfp_ucode(struct kgsl_device *device, + unsigned int start, unsigned int addr) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); int i; @@ -278,16 +297,21 @@ int adreno_ringbuffer_load_pfp_ucode(struct kgsl_device *device) KGSL_DRV_INFO(device, "loading pfp ucode version: %d\n", adreno_dev->pfp_fw_version); - adreno_regwrite(device, adreno_dev->gpudev->reg_cp_pfp_ucode_addr, 0); + adreno_writereg(adreno_dev, ADRENO_REG_CP_PFP_UCODE_ADDR, addr); for (i = 1; i < adreno_dev->pfp_fw_size; i++) - adreno_regwrite(device, - adreno_dev->gpudev->reg_cp_pfp_ucode_data, - adreno_dev->pfp_fw[i]); + adreno_writereg(adreno_dev, ADRENO_REG_CP_PFP_UCODE_DATA, + adreno_dev->pfp_fw[i]); return 0; } -int adreno_ringbuffer_start(struct adreno_ringbuffer *rb) +/** + * _ringbuffer_start_common() - Ringbuffer start + * @rb: Pointer to adreno ringbuffer + * + * Setup ringbuffer for GPU. + */ +int _ringbuffer_start_common(struct adreno_ringbuffer *rb) { int status; union reg_cp_rb_cntl cp_rb_cntl; @@ -298,24 +322,24 @@ int adreno_ringbuffer_start(struct adreno_ringbuffer *rb) if (rb->flags & KGSL_FLAGS_STARTED) return 0; - kgsl_sharedmem_set(&rb->memptrs_desc, 0, 0, + kgsl_sharedmem_set(rb->device, &rb->memptrs_desc, 0, 0, sizeof(struct kgsl_rbmemptrs)); - kgsl_sharedmem_set(&rb->buffer_desc, 0, 0xAA, + kgsl_sharedmem_set(rb->device, &rb->buffer_desc, 0, 0xAA, (rb->sizedwords << 2)); if (adreno_is_a2xx(adreno_dev)) { - adreno_regwrite(device, REG_CP_RB_WPTR_BASE, + kgsl_regwrite(device, REG_CP_RB_WPTR_BASE, (rb->memptrs_desc.gpuaddr + GSL_RB_MEMPTRS_WPTRPOLL_OFFSET)); /* setup WPTR delay */ - adreno_regwrite(device, REG_CP_RB_WPTR_DELAY, + kgsl_regwrite(device, REG_CP_RB_WPTR_DELAY, 0 /*0x70000010 */); } /*setup REG_CP_RB_CNTL */ - adreno_regread(device, REG_CP_RB_CNTL, &rb_cntl); + adreno_readreg(adreno_dev, ADRENO_REG_CP_RB_CNTL, &rb_cntl); cp_rb_cntl.val = rb_cntl; /* @@ -339,72 +363,40 @@ int adreno_ringbuffer_start(struct adreno_ringbuffer *rb) /* mem RPTR writebacks */ cp_rb_cntl.f.rb_no_update = GSL_RB_CNTL_NO_UPDATE; - adreno_regwrite(device, REG_CP_RB_CNTL, cp_rb_cntl.val); + adreno_writereg(adreno_dev, ADRENO_REG_CP_RB_CNTL, cp_rb_cntl.val); - adreno_regwrite(device, REG_CP_RB_BASE, rb->buffer_desc.gpuaddr); + adreno_writereg(adreno_dev, ADRENO_REG_CP_RB_BASE, + rb->buffer_desc.gpuaddr); - adreno_regwrite(device, REG_CP_RB_RPTR_ADDR, - rb->memptrs_desc.gpuaddr + - GSL_RB_MEMPTRS_RPTR_OFFSET); - - if (adreno_is_a3xx(adreno_dev)) { - /* enable access protection to privileged registers */ - adreno_regwrite(device, A3XX_CP_PROTECT_CTRL, 0x00000007); - - /* RBBM registers */ - adreno_regwrite(device, A3XX_CP_PROTECT_REG_0, 0x63000040); - adreno_regwrite(device, A3XX_CP_PROTECT_REG_1, 0x62000080); - adreno_regwrite(device, A3XX_CP_PROTECT_REG_2, 0x600000CC); - adreno_regwrite(device, A3XX_CP_PROTECT_REG_3, 0x60000108); - adreno_regwrite(device, A3XX_CP_PROTECT_REG_4, 0x64000140); - adreno_regwrite(device, A3XX_CP_PROTECT_REG_5, 0x66000400); - - /* CP registers */ - adreno_regwrite(device, A3XX_CP_PROTECT_REG_6, 0x65000700); - adreno_regwrite(device, A3XX_CP_PROTECT_REG_7, 0x610007D8); - adreno_regwrite(device, A3XX_CP_PROTECT_REG_8, 0x620007E0); - adreno_regwrite(device, A3XX_CP_PROTECT_REG_9, 0x61001178); - adreno_regwrite(device, A3XX_CP_PROTECT_REG_A, 0x64001180); - - /* RB registers */ - adreno_regwrite(device, A3XX_CP_PROTECT_REG_B, 0x60003300); - - /* VBIF registers */ - adreno_regwrite(device, A3XX_CP_PROTECT_REG_C, 0x6B00C000); - } + adreno_writereg(adreno_dev, ADRENO_REG_CP_RB_RPTR_ADDR, + rb->memptrs_desc.gpuaddr + + GSL_RB_MEMPTRS_RPTR_OFFSET); if (adreno_is_a2xx(adreno_dev)) { /* explicitly clear all cp interrupts */ - adreno_regwrite(device, REG_CP_INT_ACK, 0xFFFFFFFF); + kgsl_regwrite(device, REG_CP_INT_ACK, 0xFFFFFFFF); } /* setup scratch/timestamp */ - adreno_regwrite(device, REG_SCRATCH_ADDR, device->memstore.gpuaddr + - KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, - soptimestamp)); + adreno_writereg(adreno_dev, ADRENO_REG_SCRATCH_ADDR, + device->memstore.gpuaddr + + KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, + soptimestamp)); - adreno_regwrite(device, REG_SCRATCH_UMSK, + adreno_writereg(adreno_dev, ADRENO_REG_SCRATCH_UMSK, GSL_RB_MEMPTRS_SCRATCH_MASK); - /* load the CP ucode */ - status = adreno_ringbuffer_load_pm4_ucode(device); - if (status != 0) - return status; - - /* load the prefetch parser ucode */ - status = adreno_ringbuffer_load_pfp_ucode(device); - if (status != 0) - return status; - /* CP ROQ queue sizes (bytes) - RB:16, ST:16, IB1:32, IB2:64 */ - if (adreno_is_a305(adreno_dev) || adreno_is_a320(adreno_dev)) - adreno_regwrite(device, REG_CP_QUEUE_THRESHOLDS, 0x000E0602); + if (adreno_is_a305(adreno_dev) || adreno_is_a305c(adreno_dev) || + adreno_is_a320(adreno_dev)) + kgsl_regwrite(device, REG_CP_QUEUE_THRESHOLDS, 0x000E0602); + else if (adreno_is_a330(adreno_dev) || adreno_is_a305b(adreno_dev)) + kgsl_regwrite(device, REG_CP_QUEUE_THRESHOLDS, 0x003E2008); - rb->rptr = 0; rb->wptr = 0; /* clear ME_HALT to start micro engine */ - adreno_regwrite(device, REG_CP_ME_CNTL, 0); + adreno_writereg(adreno_dev, ADRENO_REG_CP_ME_CNTL, 0); /* ME init is GPU specific, so jump into the sub-function */ status = adreno_dev->gpudev->rb_init(adreno_dev, rb); @@ -420,6 +412,54 @@ int adreno_ringbuffer_start(struct adreno_ringbuffer *rb) return status; } +/** + * adreno_ringbuffer_warm_start() - Ringbuffer warm start + * @rb: Pointer to adreno ringbuffer + * + * Start the ringbuffer but load only jump tables part of the + * microcode. + */ +int adreno_ringbuffer_warm_start(struct adreno_ringbuffer *rb) +{ + int status; + struct kgsl_device *device = rb->device; + struct adreno_device *adreno_dev = ADRENO_DEVICE(device); + + /* load the CP ucode */ + status = adreno_ringbuffer_load_pm4_ucode(device, + adreno_dev->pm4_jt_idx, adreno_dev->pm4_jt_addr); + if (status != 0) + return status; + + /* load the prefetch parser ucode */ + status = adreno_ringbuffer_load_pfp_ucode(device, + adreno_dev->pfp_jt_idx, adreno_dev->pfp_jt_addr); + if (status != 0) + return status; + + return _ringbuffer_start_common(rb); +} + +int adreno_ringbuffer_start(struct adreno_ringbuffer *rb) +{ + int status; + + if (rb->flags & KGSL_FLAGS_STARTED) + return 0; + + /* load the CP ucode */ + status = adreno_ringbuffer_load_pm4_ucode(rb->device, 1, 0); + if (status != 0) + return status; + + /* load the prefetch parser ucode */ + status = adreno_ringbuffer_load_pfp_ucode(rb->device, 1, 0); + if (status != 0) + return status; + + return _ringbuffer_start_common(rb); +} + void adreno_ringbuffer_stop(struct adreno_ringbuffer *rb) { struct kgsl_device *device = rb->device; @@ -427,7 +467,7 @@ void adreno_ringbuffer_stop(struct adreno_ringbuffer *rb) if (rb->flags & KGSL_FLAGS_STARTED) { if (adreno_is_a200(adreno_dev)) - adreno_regwrite(rb->device, REG_CP_ME_CNTL, 0x10000000); + kgsl_regwrite(rb->device, REG_CP_ME_CNTL, 0x10000000); rb->flags &= ~KGSL_FLAGS_STARTED; } @@ -506,7 +546,9 @@ adreno_ringbuffer_addcmds(struct adreno_ringbuffer *rb, unsigned int context_id; unsigned int gpuaddr = rb->device->memstore.gpuaddr; - /* The global timestamp always needs to be incremented */ + if (drawctxt != NULL && kgsl_context_detached(&drawctxt->base)) + return -EINVAL; + rb->global_ts++; /* If this is a internal IB, use the global timestamp for it */ @@ -517,6 +559,12 @@ adreno_ringbuffer_addcmds(struct adreno_ringbuffer *rb, context_id = drawctxt->base.id; } + /* + * Note that we cannot safely take drawctxt->mutex here without + * potential mutex inversion with device->mutex which is held + * here. As a result, any other code that accesses this variable + * must also use device->mutex. + */ if (drawctxt) drawctxt->internal_timestamp = rb->global_ts; @@ -532,8 +580,13 @@ adreno_ringbuffer_addcmds(struct adreno_ringbuffer *rb, /* Add two dwords for the CP_INTERRUPT */ total_sizedwords += drawctxt ? 2 : 0; + /* context rollover */ if (adreno_is_a3xx(adreno_dev)) - total_sizedwords += 7; + total_sizedwords += 3; + + /* For HLSQ updates below */ + if (adreno_is_a4xx(adreno_dev) || adreno_is_a3xx(adreno_dev)) + total_sizedwords += 4; if (adreno_is_a2xx(adreno_dev)) total_sizedwords += 2; /* CP_WAIT_FOR_IDLE */ @@ -552,6 +605,10 @@ adreno_ringbuffer_addcmds(struct adreno_ringbuffer *rb, if (flags & KGSL_CMD_FLAGS_WFI) total_sizedwords += 2; /* WFI */ + /* Add space for the power on shader fixup if we need it */ + if (flags & KGSL_CMD_FLAGS_PWRON_FIXUP) + total_sizedwords += 5; + ringcmds = adreno_ringbuffer_allocspace(rb, drawctxt, total_sizedwords); if (IS_ERR(ringcmds)) @@ -562,37 +619,51 @@ adreno_ringbuffer_addcmds(struct adreno_ringbuffer *rb, rcmd_gpu = rb->buffer_desc.gpuaddr + sizeof(uint)*(rb->wptr-total_sizedwords); - GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_nop_packet(1)); - GSL_RB_WRITE(ringcmds, rcmd_gpu, KGSL_CMD_IDENTIFIER); + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, cp_nop_packet(1)); + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, KGSL_CMD_IDENTIFIER); if (flags & KGSL_CMD_FLAGS_INTERNAL_ISSUE) { - GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_nop_packet(1)); - GSL_RB_WRITE(ringcmds, rcmd_gpu, KGSL_CMD_INTERNAL_IDENTIFIER); + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, cp_nop_packet(1)); + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, + KGSL_CMD_INTERNAL_IDENTIFIER); + } + + if (flags & KGSL_CMD_FLAGS_PWRON_FIXUP) { + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, cp_nop_packet(1)); + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, + KGSL_PWRON_FIXUP_IDENTIFIER); + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, + CP_HDR_INDIRECT_BUFFER_PFD); + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, + adreno_dev->pwron_fixup.gpuaddr); + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, + adreno_dev->pwron_fixup_dwords); } /* start-of-pipeline timestamp */ - GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_type3_packet(CP_MEM_WRITE, 2)); - GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr + + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, + cp_type3_packet(CP_MEM_WRITE, 2)); + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, (gpuaddr + KGSL_MEMSTORE_OFFSET(context_id, soptimestamp))); - GSL_RB_WRITE(ringcmds, rcmd_gpu, timestamp); + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, timestamp); if (flags & KGSL_CMD_FLAGS_PMODE) { /* disable protected mode error checking */ - GSL_RB_WRITE(ringcmds, rcmd_gpu, + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, cp_type3_packet(CP_SET_PROTECTED_MODE, 1)); - GSL_RB_WRITE(ringcmds, rcmd_gpu, 0); + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, 0); } for (i = 0; i < sizedwords; i++) { - GSL_RB_WRITE(ringcmds, rcmd_gpu, *cmds); + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, *cmds); cmds++; } if (flags & KGSL_CMD_FLAGS_PMODE) { /* re-enable protected mode error checking */ - GSL_RB_WRITE(ringcmds, rcmd_gpu, + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, cp_type3_packet(CP_SET_PROTECTED_MODE, 1)); - GSL_RB_WRITE(ringcmds, rcmd_gpu, 1); + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, 1); } /* HW Workaround for MMU Page fault @@ -600,23 +671,24 @@ adreno_ringbuffer_addcmds(struct adreno_ringbuffer *rb, * GPU completes it. */ if (adreno_is_a2xx(adreno_dev)) { - GSL_RB_WRITE(ringcmds, rcmd_gpu, + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, cp_type3_packet(CP_WAIT_FOR_IDLE, 1)); - GSL_RB_WRITE(ringcmds, rcmd_gpu, 0x00); + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, 0x00); } - if (adreno_is_a3xx(adreno_dev)) { + if (adreno_is_a3xx(adreno_dev) || adreno_is_a4xx(adreno_dev)) { /* * Flush HLSQ lazy updates to make sure there are no * resources pending for indirect loads after the timestamp */ - GSL_RB_WRITE(ringcmds, rcmd_gpu, + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, cp_type3_packet(CP_EVENT_WRITE, 1)); - GSL_RB_WRITE(ringcmds, rcmd_gpu, 0x07); /* HLSQ_FLUSH */ - GSL_RB_WRITE(ringcmds, rcmd_gpu, + GSL_RB_WRITE(rb->device, ringcmds, + rcmd_gpu, 0x07); /* HLSQ_FLUSH */ + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, cp_type3_packet(CP_WAIT_FOR_IDLE, 1)); - GSL_RB_WRITE(ringcmds, rcmd_gpu, 0x00); + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, 0x00); } /* @@ -624,40 +696,48 @@ adreno_ringbuffer_addcmds(struct adreno_ringbuffer *rb, * enabled, then context_id will be KGSL_MEMSTORE_GLOBAL so all * eop timestamps will work out. */ - GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_type3_packet(CP_EVENT_WRITE, 3)); - GSL_RB_WRITE(ringcmds, rcmd_gpu, CACHE_FLUSH_TS); - GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr + + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, + cp_type3_packet(CP_EVENT_WRITE, 3)); + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, CACHE_FLUSH_TS); + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, (gpuaddr + KGSL_MEMSTORE_OFFSET(context_id, eoptimestamp))); - GSL_RB_WRITE(ringcmds, rcmd_gpu, timestamp); + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, timestamp); if (drawctxt) { - GSL_RB_WRITE(ringcmds, rcmd_gpu, + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, cp_type3_packet(CP_MEM_WRITE, 2)); - GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr + + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, (gpuaddr + KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, eoptimestamp))); - GSL_RB_WRITE(ringcmds, rcmd_gpu, rb->global_ts); + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, rb->global_ts); + } + + if (adreno_is_a20x(adreno_dev)) { + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, + cp_type3_packet(CP_EVENT_WRITE, 1)); + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, CACHE_FLUSH); } if (drawctxt || (flags & KGSL_CMD_FLAGS_INTERNAL_ISSUE)) { - GSL_RB_WRITE(ringcmds, rcmd_gpu, + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, cp_type3_packet(CP_INTERRUPT, 1)); - GSL_RB_WRITE(ringcmds, rcmd_gpu, CP_INT_CNTL__RB_INT_MASK); + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, + CP_INT_CNTL__RB_INT_MASK); } if (adreno_is_a3xx(adreno_dev)) { /* Dummy set-constant to trigger context rollover */ - GSL_RB_WRITE(ringcmds, rcmd_gpu, + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, cp_type3_packet(CP_SET_CONSTANT, 2)); - GSL_RB_WRITE(ringcmds, rcmd_gpu, + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, (0x4<<16)|(A3XX_HLSQ_CL_KERNEL_GROUP_X_REG - 0x2000)); - GSL_RB_WRITE(ringcmds, rcmd_gpu, 0); + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, 0); } if (flags & KGSL_CMD_FLAGS_WFI) { - GSL_RB_WRITE(ringcmds, rcmd_gpu, + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, cp_type3_packet(CP_WAIT_FOR_IDLE, 1)); - GSL_RB_WRITE(ringcmds, rcmd_gpu, 0x00000000); + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, 0x00000000); } adreno_ringbuffer_submit(rb); @@ -772,10 +852,8 @@ static bool _parse_ibs(struct kgsl_device_private *dev_priv, buffer */ struct kgsl_mem_entry *entry; - spin_lock(&dev_priv->process_priv->mem_lock); entry = kgsl_sharedmem_find_region(dev_priv->process_priv, gpuaddr, sizedwords * sizeof(uint)); - spin_unlock(&dev_priv->process_priv->mem_lock); if (entry == NULL) { KGSL_CMD_ERR(dev_priv->device, "no mapping for gpuaddr: 0x%08x\n", gpuaddr); @@ -925,13 +1003,32 @@ adreno_ringbuffer_issueibcmds(struct kgsl_device_private *dev_priv, return -EINVAL; } + /* For now everybody has the same priority */ + cmdbatch->priority = ADRENO_CONTEXT_DEFAULT_PRIORITY; + /* Queue the command in the ringbuffer */ - ret = adreno_context_queue_cmd(adreno_dev, drawctxt, cmdbatch, + ret = adreno_dispatcher_queue_cmd(adreno_dev, drawctxt, cmdbatch, timestamp); if (ret) - KGSL_DRV_ERR(device, "adreno_context_queue_cmd returned %d\n", + KGSL_DRV_ERR(device, "adreno_dispatcher_queue_cmd returned %d\n", ret); + else { + /* + * only call trace_gpu_job_enqueue for actual commands - dummy + * sync command batches won't get scheduled on the GPU + */ + + if (!(cmdbatch->flags & KGSL_CONTEXT_SYNC)) { + const char *str = "3D"; + if (drawctxt->type == KGSL_CONTEXT_TYPE_CL || + drawctxt->type == KGSL_CONTEXT_TYPE_RS) + str = "compute"; + + kgsl_trace_gpu_job_enqueue(drawctxt->base.id, + cmdbatch->timestamp, str); + } + } return ret; } @@ -949,6 +1046,7 @@ int adreno_ringbuffer_submitcmd(struct adreno_device *adreno_dev, struct kgsl_context *context; struct adreno_context *drawctxt; unsigned int start_index = 0; + int flags = KGSL_CMD_FLAGS_NONE; int ret; context = cmdbatch->context; @@ -962,7 +1060,7 @@ int adreno_ringbuffer_submitcmd(struct adreno_device *adreno_dev, if a context switch hasn't occured */ if ((drawctxt->flags & CTXT_FLAGS_PREAMBLE) && - !(cmdbatch->priv & CMDBATCH_FLAG_FORCE_PREAMBLE) && + !test_bit(CMDBATCH_FLAG_FORCE_PREAMBLE, &cmdbatch->priv) && (adreno_dev->drawctxt_active == drawctxt)) start_index = 1; @@ -973,7 +1071,7 @@ int adreno_ringbuffer_submitcmd(struct adreno_device *adreno_dev, * generate the start and end markers and skip everything else */ - if (cmdbatch->priv & CMDBATCH_FLAG_SKIP) { + if (test_bit(CMDBATCH_FLAG_SKIP, &cmdbatch->priv)) { start_index = 0; numibs = 0; } @@ -1030,9 +1128,21 @@ int adreno_ringbuffer_submitcmd(struct adreno_device *adreno_dev, if (ret) goto done; + if (test_bit(CMDBATCH_FLAG_WFI, &cmdbatch->priv)) + flags = KGSL_CMD_FLAGS_WFI; + + /* + * For some targets, we need to execute a dummy shader operation after a + * power collapse + */ + + if (test_and_clear_bit(ADRENO_DEVICE_PWRON, &adreno_dev->priv) && + test_bit(ADRENO_DEVICE_PWRON_FIXUP, &adreno_dev->priv)) + flags |= KGSL_CMD_FLAGS_PWRON_FIXUP; + ret = adreno_ringbuffer_addcmds(&adreno_dev->ringbuffer, drawctxt, - cmdbatch->flags, + flags, &link[0], (cmds - link), cmdbatch->timestamp); @@ -1046,9 +1156,10 @@ int adreno_ringbuffer_submitcmd(struct adreno_device *adreno_dev, #endif done: + device->pwrctrl.irq_last = 0; kgsl_trace_issueibcmds(device, context->id, cmdbatch, cmdbatch->timestamp, cmdbatch->flags, ret, - drawctxt->type); + drawctxt ? drawctxt->type : 0); kfree(link); return ret; diff --git a/drivers/gpu/msm/adreno_ringbuffer.h b/drivers/gpu/msm/adreno_ringbuffer.h index d7a77409335..3aa0101e534 100644 --- a/drivers/gpu/msm/adreno_ringbuffer.h +++ b/drivers/gpu/msm/adreno_ringbuffer.h @@ -53,17 +53,16 @@ struct adreno_ringbuffer { unsigned int sizedwords; unsigned int wptr; /* write pointer offset in dwords from baseaddr */ - unsigned int rptr; /* read pointer offset in dwords from baseaddr */ unsigned int global_ts; }; -#define GSL_RB_WRITE(ring, gpuaddr, data) \ +#define GSL_RB_WRITE(device, ring, gpuaddr, data) \ do { \ *ring = data; \ wmb(); \ - kgsl_cffdump_setmem(gpuaddr, data, 4); \ + kgsl_cffdump_setmem(device, gpuaddr, data, 4); \ ring++; \ gpuaddr += sizeof(uint); \ } while (0) @@ -73,10 +72,20 @@ struct adreno_ringbuffer { /* mem rptr */ #define GSL_RB_CNTL_NO_UPDATE 0x0 /* enable */ -#define GSL_RB_GET_READPTR(rb, data) \ - do { \ - *(data) = rb->memptrs->rptr; \ - } while (0) + +/** + * adreno_get_rptr - Get the current ringbuffer read pointer + * @rb - the ringbuffer + * + * Get the current read pointer, which is written by the GPU. + */ +static inline unsigned int +adreno_get_rptr(struct adreno_ringbuffer *rb) +{ + unsigned int result = rb->memptrs->rptr; + rmb(); + return result; +} #define GSL_RB_CNTL_POLL_EN 0x0 /* disable */ @@ -97,6 +106,8 @@ int adreno_ringbuffer_submitcmd(struct adreno_device *adreno_dev, int adreno_ringbuffer_init(struct kgsl_device *device); +int adreno_ringbuffer_warm_start(struct adreno_ringbuffer *rb); + int adreno_ringbuffer_start(struct adreno_ringbuffer *rb); void adreno_ringbuffer_stop(struct adreno_ringbuffer *rb); diff --git a/drivers/gpu/msm/adreno_snapshot.c b/drivers/gpu/msm/adreno_snapshot.c index 3bcbd580f36..fcb134938ed 100644 --- a/drivers/gpu/msm/adreno_snapshot.c +++ b/drivers/gpu/msm/adreno_snapshot.c @@ -18,6 +18,7 @@ #include "adreno_pm4types.h" #include "a2xx_reg.h" #include "a3xx_reg.h" +#include "adreno_cp_parser.h" /* Number of dwords of ringbuffer history to record */ #define NUM_DWORDS_OF_RINGBUFFER_HISTORY 100 @@ -34,20 +35,23 @@ static int snapshot_frozen_objsize; static struct kgsl_snapshot_obj { int type; uint32_t gpuaddr; - uint32_t ptbase; + phys_addr_t ptbase; void *ptr; int dwords; + struct kgsl_mem_entry *entry; } objbuf[SNAPSHOT_OBJ_BUFSIZE]; /* Pointer to the next open entry in the object list */ static int objbufptr; /* Push a new buffer object onto the list */ -static void push_object(struct kgsl_device *device, int type, uint32_t ptbase, +static void push_object(struct kgsl_device *device, int type, + phys_addr_t ptbase, uint32_t gpuaddr, int dwords) { int index; void *ptr; + struct kgsl_mem_entry *entry = NULL; /* * Sometimes IBs can be reused in the same dump. Because we parse from @@ -73,7 +77,7 @@ static void push_object(struct kgsl_device *device, int type, uint32_t ptbase, * adreno_convertaddr verifies that the IB size is valid - at least in * the context of it being smaller then the allocated memory space */ - ptr = adreno_convertaddr(device, ptbase, gpuaddr, dwords << 2); + ptr = adreno_convertaddr(device, ptbase, gpuaddr, dwords << 2, &entry); if (ptr == NULL) { KGSL_DRV_ERR(device, @@ -86,6 +90,7 @@ static void push_object(struct kgsl_device *device, int type, uint32_t ptbase, objbuf[objbufptr].gpuaddr = gpuaddr; objbuf[objbufptr].ptbase = ptbase; objbuf[objbufptr].dwords = dwords; + objbuf[objbufptr].entry = entry; objbuf[objbufptr++].ptr = ptr; } @@ -94,7 +99,7 @@ static void push_object(struct kgsl_device *device, int type, uint32_t ptbase, * to be dumped */ -static int find_object(int type, unsigned int gpuaddr, unsigned int ptbase) +static int find_object(int type, unsigned int gpuaddr, phys_addr_t ptbase) { int index; @@ -109,513 +114,61 @@ static int find_object(int type, unsigned int gpuaddr, unsigned int ptbase) } /* - * This structure keeps track of type0 writes to VSC_PIPE_DATA_ADDRESS_x and - * VSC_PIPE_DATA_LENGTH_x. When a draw initator is called these registers - * point to buffers that we need to freeze for a snapshot - */ - -static struct { - unsigned int base; - unsigned int size; -} vsc_pipe[8]; - -/* - * This is the cached value of type0 writes to the VSC_SIZE_ADDRESS which - * contains the buffer address of the visiblity stream size buffer during a - * binning pass - */ - -static unsigned int vsc_size_address; - -/* - * This struct keeps track of type0 writes to VFD_FETCH_INSTR_0_X and - * VFD_FETCH_INSTR_1_X registers. When a draw initator is called the addresses - * and sizes in these registers point to VBOs that we need to freeze for a - * snapshot - */ - -static struct { - unsigned int base; - unsigned int stride; -} vbo[16]; - -/* - * This is the cached value of type0 writes to VFD_INDEX_MAX. This will be used - * to calculate the size of the VBOs when the draw initator is called - */ - -static unsigned int vfd_index_max; - -/* - * This is the cached value of type0 writes to VFD_CONTROL_0 which tells us how - * many VBOs are active when the draw initator is called - */ - -static unsigned int vfd_control_0; - -/* - * Cached value of type0 writes to SP_VS_PVT_MEM_ADDR and SP_FS_PVT_MEM_ADDR. - * This is a buffer that contains private stack information for the shader - */ - -static unsigned int sp_vs_pvt_mem_addr; -static unsigned int sp_fs_pvt_mem_addr; - -/* - * Cached value of SP_VS_OBJ_START_REG and SP_FS_OBJ_START_REG. - */ -static unsigned int sp_vs_obj_start_reg; -static unsigned int sp_fs_obj_start_reg; - -/* - * Each load state block has two possible types. Each type has a different - * number of dwords per unit. Use this handy lookup table to make sure - * we dump the right amount of data from the indirect buffer + * snapshot_freeze_obj_list() - Take a list of ib objects and freeze their + * memory for snapshot + * @device: Device being snapshotted + * @ptbase: The pagetable base of the process to which IB belongs + * @ib_obj_list: List of the IB objects + * + * Returns 0 on success else error code */ - -static int load_state_unit_sizes[7][2] = { - { 2, 4 }, - { 0, 1 }, - { 2, 4 }, - { 0, 1 }, - { 8, 2 }, - { 8, 2 }, - { 8, 2 }, -}; - -static int ib_parse_load_state(struct kgsl_device *device, unsigned int *pkt, - unsigned int ptbase) +static int snapshot_freeze_obj_list(struct kgsl_device *device, + phys_addr_t ptbase, struct adreno_ib_object_list *ib_obj_list) { - unsigned int block, source, type; int ret = 0; - - /* - * The object here is to find indirect shaders i.e - shaders loaded from - * GPU memory instead of directly in the command. These should be added - * to the list of memory objects to dump. So look at the load state - * if the block is indirect (source = 4). If so then add the memory - * address to the list. The size of the object differs depending on the - * type per the load_state_unit_sizes array above. - */ - - if (type3_pkt_size(pkt[0]) < 2) - return 0; - - /* - * pkt[1] 18:16 - source - * pkt[1] 21:19 - state block - * pkt[1] 31:22 - size in units - * pkt[2] 0:1 - type - * pkt[2] 31:2 - GPU memory address - */ - - block = (pkt[1] >> 19) & 0x07; - source = (pkt[1] >> 16) & 0x07; - type = pkt[2] & 0x03; - - if (source == 4) { - int unitsize, ret; - - if (type == 0) - unitsize = load_state_unit_sizes[block][0]; - else - unitsize = load_state_unit_sizes[block][1]; - - /* Freeze the GPU buffer containing the shader */ - - ret = kgsl_snapshot_get_object(device, ptbase, - pkt[2] & 0xFFFFFFFC, - (((pkt[1] >> 22) & 0x03FF) * unitsize) << 2, - SNAPSHOT_GPU_OBJECT_SHADER); - - if (ret < 0) - return -EINVAL; - - snapshot_frozen_objsize += ret; - } - - return ret; -} - -/* - * This opcode sets the base addresses for the visibilty stream buffer and the - * visiblity stream size buffer. - */ - -static int ib_parse_set_bin_data(struct kgsl_device *device, unsigned int *pkt, - unsigned int ptbase) -{ - int ret; - - if (type3_pkt_size(pkt[0]) < 2) - return 0; - - /* Visiblity stream buffer */ - ret = kgsl_snapshot_get_object(device, ptbase, pkt[1], 0, - SNAPSHOT_GPU_OBJECT_GENERIC); - - if (ret < 0) - return -EINVAL; - - snapshot_frozen_objsize += ret; - - /* visiblity stream size buffer (fixed size 8 dwords) */ - ret = kgsl_snapshot_get_object(device, ptbase, pkt[2], 32, - SNAPSHOT_GPU_OBJECT_GENERIC); - - if (ret >= 0) - snapshot_frozen_objsize += ret; - - return ret; -} - -/* - * This opcode writes to GPU memory - if the buffer is written to, there is a - * good chance that it would be valuable to capture in the snapshot, so mark all - * buffers that are written to as frozen - */ - -static int ib_parse_mem_write(struct kgsl_device *device, unsigned int *pkt, - unsigned int ptbase) -{ - int ret; - - if (type3_pkt_size(pkt[0]) < 1) - return 0; - - /* - * The address is where the data in the rest of this packet is written - * to, but since that might be an offset into the larger buffer we need - * to get the whole thing. Pass a size of 0 kgsl_snapshot_get_object to - * capture the entire buffer. - */ - - ret = kgsl_snapshot_get_object(device, ptbase, pkt[1] & 0xFFFFFFFC, 0, - SNAPSHOT_GPU_OBJECT_GENERIC); - - if (ret >= 0) - snapshot_frozen_objsize += ret; - - return ret; -} - -/* - * The DRAW_INDX opcode sends a draw initator which starts a draw operation in - * the GPU, so this is the point where all the registers and buffers become - * "valid". The DRAW_INDX may also have an index buffer pointer that should be - * frozen with the others - */ - -static int ib_parse_draw_indx(struct kgsl_device *device, unsigned int *pkt, - unsigned int ptbase) -{ - int ret = 0, i; - - if (type3_pkt_size(pkt[0]) < 3) - return 0; - - /* DRAW_IDX may have a index buffer pointer */ - - if (type3_pkt_size(pkt[0]) > 3) { - ret = kgsl_snapshot_get_object(device, ptbase, pkt[4], pkt[5], - SNAPSHOT_GPU_OBJECT_GENERIC); - if (ret < 0) - return -EINVAL; - - snapshot_frozen_objsize += ret; - } - - /* - * All of the type0 writes are valid at a draw initiator, so freeze - * the various buffers that we are tracking - */ - - /* First up the visiblity stream buffer */ - - for (i = 0; i < ARRAY_SIZE(vsc_pipe); i++) { - if (vsc_pipe[i].base != 0 && vsc_pipe[i].size != 0) { - ret = kgsl_snapshot_get_object(device, ptbase, - vsc_pipe[i].base, vsc_pipe[i].size, - SNAPSHOT_GPU_OBJECT_GENERIC); - if (ret < 0) - return -EINVAL; - - snapshot_frozen_objsize += ret; - } - } - - /* Next the visibility stream size buffer */ - - if (vsc_size_address) { - ret = kgsl_snapshot_get_object(device, ptbase, - vsc_size_address, 32, - SNAPSHOT_GPU_OBJECT_GENERIC); - if (ret < 0) - return -EINVAL; - - snapshot_frozen_objsize += ret; - } - - /* Next private shader buffer memory */ - if (sp_vs_pvt_mem_addr) { - ret = kgsl_snapshot_get_object(device, ptbase, - sp_vs_pvt_mem_addr, 8192, - SNAPSHOT_GPU_OBJECT_GENERIC); - if (ret < 0) - return -EINVAL; - - snapshot_frozen_objsize += ret; - sp_vs_pvt_mem_addr = 0; - } - - if (sp_fs_pvt_mem_addr) { - ret = kgsl_snapshot_get_object(device, ptbase, - sp_fs_pvt_mem_addr, 8192, - SNAPSHOT_GPU_OBJECT_GENERIC); - if (ret < 0) - return -EINVAL; - - snapshot_frozen_objsize += ret; - sp_fs_pvt_mem_addr = 0; - } - - if (sp_vs_obj_start_reg) { - ret = kgsl_snapshot_get_object(device, ptbase, - sp_vs_obj_start_reg & 0xFFFFFFE0, 0, - SNAPSHOT_GPU_OBJECT_GENERIC); - if (ret < 0) - return -EINVAL; - snapshot_frozen_objsize += ret; - sp_vs_obj_start_reg = 0; - } - - if (sp_fs_obj_start_reg) { - ret = kgsl_snapshot_get_object(device, ptbase, - sp_fs_obj_start_reg & 0xFFFFFFE0, 0, - SNAPSHOT_GPU_OBJECT_GENERIC); - if (ret < 0) - return -EINVAL; - snapshot_frozen_objsize += ret; - sp_fs_obj_start_reg = 0; - } - - /* Finally: VBOs */ - - /* The number of active VBOs is stored in VFD_CONTROL_O[31:27] */ - for (i = 0; i < (vfd_control_0) >> 27; i++) { - int size; - - /* - * The size of the VBO is the stride stored in - * VFD_FETCH_INSTR_0_X.BUFSTRIDE * VFD_INDEX_MAX. The base - * is stored in VFD_FETCH_INSTR_1_X - */ - - if (vbo[i].base != 0) { - size = vbo[i].stride * vfd_index_max; - - ret = kgsl_snapshot_get_object(device, ptbase, - vbo[i].base, - 0, SNAPSHOT_GPU_OBJECT_GENERIC); - if (ret < 0) - return -EINVAL; - - snapshot_frozen_objsize += ret; - } - - vbo[i].base = 0; - vbo[i].stride = 0; - } - - vfd_control_0 = 0; - vfd_index_max = 0; - - return ret; -} - -/* - * Parse all the type3 opcode packets that may contain important information, - * such as additional GPU buffers to grab or a draw initator - */ - -static int ib_parse_type3(struct kgsl_device *device, unsigned int *ptr, - unsigned int ptbase) -{ - int opcode = cp_type3_opcode(*ptr); - - if (opcode == CP_LOAD_STATE) - return ib_parse_load_state(device, ptr, ptbase); - else if (opcode == CP_SET_BIN_DATA) - return ib_parse_set_bin_data(device, ptr, ptbase); - else if (opcode == CP_MEM_WRITE) - return ib_parse_mem_write(device, ptr, ptbase); - else if (opcode == CP_DRAW_INDX) - return ib_parse_draw_indx(device, ptr, ptbase); - - return 0; -} - -/* - * Parse type0 packets found in the stream. Some of the registers that are - * written are clues for GPU buffers that we need to freeze. Register writes - * are considred valid when a draw initator is called, so just cache the values - * here and freeze them when a CP_DRAW_INDX is seen. This protects against - * needlessly caching buffers that won't be used during a draw call - */ - -static void ib_parse_type0(struct kgsl_device *device, unsigned int *ptr, - unsigned int ptbase) -{ - int size = type0_pkt_size(*ptr); - int offset = type0_pkt_offset(*ptr); + struct adreno_ib_object *ib_objs; + unsigned int ib2base; + struct adreno_device *adreno_dev = ADRENO_DEVICE(device); int i; - for (i = 0; i < size - 1; i++, offset++) { - - /* Visiblity stream buffer */ - - if (offset >= A3XX_VSC_PIPE_DATA_ADDRESS_0 && - offset <= A3XX_VSC_PIPE_DATA_LENGTH_7) { - int index = offset - A3XX_VSC_PIPE_DATA_ADDRESS_0; - - /* Each bank of address and length registers are - * interleaved with an empty register: - * - * address 0 - * length 0 - * empty - * address 1 - * length 1 - * empty - * ... - */ - - if ((index % 3) == 0) - vsc_pipe[index / 3].base = ptr[i + 1]; - else if ((index % 3) == 1) - vsc_pipe[index / 3].size = ptr[i + 1]; - } else if ((offset >= A3XX_VFD_FETCH_INSTR_0_0) && - (offset <= A3XX_VFD_FETCH_INSTR_1_F)) { - int index = offset - A3XX_VFD_FETCH_INSTR_0_0; - - /* - * FETCH_INSTR_0_X and FETCH_INSTR_1_X banks are - * interleaved as above but without the empty register - * in between - */ - - if ((index % 2) == 0) - vbo[index >> 1].stride = - (ptr[i + 1] >> 7) & 0x1FF; - else - vbo[index >> 1].base = ptr[i + 1]; - } else { - /* - * Cache various support registers for calculating - * buffer sizes - */ - - switch (offset) { - case A3XX_VFD_CONTROL_0: - vfd_control_0 = ptr[i + 1]; - break; - case A3XX_VFD_INDEX_MAX: - vfd_index_max = ptr[i + 1]; - break; - case A3XX_VSC_SIZE_ADDRESS: - vsc_size_address = ptr[i + 1]; - break; - case A3XX_SP_VS_PVT_MEM_ADDR_REG: - sp_vs_pvt_mem_addr = ptr[i + 1]; - break; - case A3XX_SP_FS_PVT_MEM_ADDR_REG: - sp_fs_pvt_mem_addr = ptr[i + 1]; - break; - case A3XX_SP_VS_OBJ_START_REG: - sp_vs_obj_start_reg = ptr[i + 1]; - break; - case A3XX_SP_FS_OBJ_START_REG: - sp_fs_obj_start_reg = ptr[i + 1]; + adreno_readreg(adreno_dev, ADRENO_REG_CP_IB2_BASE, &ib2base); + + for (i = 0; i < ib_obj_list->num_objs; i++) { + int temp_ret; + int index; + int freeze = 1; + + ib_objs = &(ib_obj_list->obj_list[i]); + /* Make sure this object is not going to be saved statically */ + for (index = 0; index < objbufptr; index++) { + if ((objbuf[index].gpuaddr <= ib_objs->gpuaddr) && + ((objbuf[index].gpuaddr + + (objbuf[index].dwords << 2)) >= + (ib_objs->gpuaddr + ib_objs->size)) && + (objbuf[index].ptbase == ptbase)) { + freeze = 0; break; } } - } -} - -static inline int parse_ib(struct kgsl_device *device, unsigned int ptbase, - unsigned int gpuaddr, unsigned int dwords); - -/* Add an IB as a GPU object, but first, parse it to find more goodies within */ - -static int ib_add_gpu_object(struct kgsl_device *device, unsigned int ptbase, - unsigned int gpuaddr, unsigned int dwords) -{ - int i, ret, rem = dwords; - unsigned int *src; - - /* - * If the object is already in the list, we don't need to parse it again - */ - - if (kgsl_snapshot_have_object(device, ptbase, gpuaddr, dwords << 2)) - return 0; - - src = (unsigned int *) adreno_convertaddr(device, ptbase, gpuaddr, - dwords << 2); - - if (src == NULL) - return -EINVAL; - - for (i = 0; rem > 0; rem--, i++) { - int pktsize; - - /* If the packet isn't a type 1 or a type 3, then don't bother - * parsing it - it is likely corrupted */ - - if (!pkt_is_type0(src[i]) && !pkt_is_type3(src[i])) - break; - - pktsize = type3_pkt_size(src[i]); - if (!pktsize || (pktsize + 1) > rem) - break; - - if (pkt_is_type3(src[i])) { - if (adreno_cmd_is_ib(src[i])) { - unsigned int gpuaddr = src[i + 1]; - unsigned int size = src[i + 2]; - - ret = parse_ib(device, ptbase, gpuaddr, size); - - /* If adding the IB failed then stop parsing */ - if (ret < 0) - goto done; + if (freeze) { + /* Save current IB2 statically */ + if (ib2base == ib_objs->gpuaddr) { + push_object(device, SNAPSHOT_OBJ_TYPE_IB, + ptbase, ib_objs->gpuaddr, ib_objs->size >> 2); } else { - ret = ib_parse_type3(device, &src[i], ptbase); - /* - * If the parse function failed (probably - * because of a bad decode) then bail out and - * just capture the binary IB data - */ - - if (ret < 0) - goto done; + temp_ret = kgsl_snapshot_get_object(device, + ptbase, ib_objs->gpuaddr, ib_objs->size, + ib_objs->snapshot_obj_type); + if (temp_ret < 0) { + if (ret >= 0) + ret = temp_ret; + } else { + snapshot_frozen_objsize += temp_ret; + } } - } else if (pkt_is_type0(src[i])) { - ib_parse_type0(device, &src[i], ptbase); } - - i += pktsize; - rem -= pktsize; } - -done: - ret = kgsl_snapshot_get_object(device, ptbase, gpuaddr, dwords << 2, - SNAPSHOT_GPU_OBJECT_IB); - - if (ret >= 0) - snapshot_frozen_objsize += ret; - return ret; } @@ -625,27 +178,41 @@ static int ib_add_gpu_object(struct kgsl_device *device, unsigned int ptbase, * access the dynamic data from the sysfs file. Push all other IBs on the * dynamic list */ -static inline int parse_ib(struct kgsl_device *device, unsigned int ptbase, +static inline int parse_ib(struct kgsl_device *device, phys_addr_t ptbase, unsigned int gpuaddr, unsigned int dwords) { - unsigned int ib1base, ib2base; + struct adreno_device *adreno_dev = ADRENO_DEVICE(device); + unsigned int ib1base; int ret = 0; + struct adreno_ib_object_list *ib_obj_list; /* - * Check the IB address - if it is either the last executed IB1 or the - * last executed IB2 then push it into the static blob otherwise put - * it in the dynamic list + * Check the IB address - if it is either the last executed IB1 + * then push it into the static blob otherwise put it in the dynamic + * list */ - kgsl_regread(device, REG_CP_IB1_BASE, &ib1base); - kgsl_regread(device, REG_CP_IB2_BASE, &ib2base); + adreno_readreg(adreno_dev, ADRENO_REG_CP_IB1_BASE, &ib1base); - if (gpuaddr == ib1base || gpuaddr == ib2base) + if (gpuaddr == ib1base) { push_object(device, SNAPSHOT_OBJ_TYPE_IB, ptbase, gpuaddr, dwords); - else - ret = ib_add_gpu_object(device, ptbase, gpuaddr, dwords); + goto done; + } + + if (kgsl_snapshot_have_object(device, ptbase, gpuaddr, dwords << 2)) + goto done; + + ret = adreno_ib_create_object_list(device, ptbase, + gpuaddr, dwords, &ib_obj_list); + if (ret) + goto done; + ret = kgsl_snapshot_add_ib_obj_list(device, ptbase, ib_obj_list); + + if (ret) + adreno_ib_destroy_obj_list(ib_obj_list); +done: return ret; } @@ -657,7 +224,8 @@ static int snapshot_rb(struct kgsl_device *device, void *snapshot, unsigned int *data = snapshot + sizeof(*header); struct adreno_device *adreno_dev = ADRENO_DEVICE(device); struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer; - unsigned int ptbase, rptr, *rbptr, ibbase; + unsigned int rptr, *rbptr, ibbase; + phys_addr_t ptbase; int index, size, i; int parse_ibs = 0, ib_parse_start; @@ -665,10 +233,10 @@ static int snapshot_rb(struct kgsl_device *device, void *snapshot, ptbase = kgsl_mmu_get_current_ptbase(&device->mmu); /* Get the current read pointers for the RB */ - kgsl_regread(device, REG_CP_RB_RPTR, &rptr); + adreno_readreg(adreno_dev, ADRENO_REG_CP_RB_RPTR, &rptr); /* Address of the last processed IB */ - kgsl_regread(device, REG_CP_IB1_BASE, &ibbase); + adreno_readreg(adreno_dev, ADRENO_REG_CP_IB1_BASE, &ibbase); /* * Figure out the window of ringbuffer data to dump. First we need to @@ -818,15 +386,80 @@ static int snapshot_rb(struct kgsl_device *device, void *snapshot, return size + sizeof(*header); } +static int snapshot_capture_mem_list(struct kgsl_device *device, void *snapshot, + int remain, void *priv) +{ + struct kgsl_snapshot_replay_mem_list *header = snapshot; + struct kgsl_process_private *private = NULL; + struct kgsl_process_private *tmp_private; + phys_addr_t ptbase; + struct rb_node *node; + struct kgsl_mem_entry *entry = NULL; + int num_mem; + unsigned int *data = snapshot + sizeof(*header); + + ptbase = kgsl_mmu_get_current_ptbase(&device->mmu); + mutex_lock(&kgsl_driver.process_mutex); + list_for_each_entry(tmp_private, &kgsl_driver.process_list, list) { + if (kgsl_mmu_pt_equal(&device->mmu, tmp_private->pagetable, + ptbase)) { + private = tmp_private; + break; + } + } + mutex_unlock(&kgsl_driver.process_mutex); + if (!private) { + KGSL_DRV_ERR(device, + "Failed to get pointer to process private structure\n"); + return 0; + } + /* We need to know the number of memory objects that the process has */ + spin_lock(&private->mem_lock); + for (node = rb_first(&private->mem_rb), num_mem = 0; node; ) { + entry = rb_entry(node, struct kgsl_mem_entry, node); + node = rb_next(&entry->node); + num_mem++; + } + + if (remain < ((num_mem * 3 * sizeof(unsigned int)) + + sizeof(*header))) { + KGSL_DRV_ERR(device, + "snapshot: Not enough memory for the mem list section"); + spin_unlock(&private->mem_lock); + return 0; + } + header->num_entries = num_mem; + header->ptbase = (__u32)ptbase; + /* + * Walk throught the memory list and store the + * tuples(gpuaddr, size, memtype) in snapshot + */ + for (node = rb_first(&private->mem_rb); node; ) { + entry = rb_entry(node, struct kgsl_mem_entry, node); + node = rb_next(&entry->node); + + *data++ = entry->memdesc.gpuaddr; + *data++ = entry->memdesc.size; + *data++ = (entry->memdesc.priv & KGSL_MEMTYPE_MASK) >> + KGSL_MEMTYPE_SHIFT; + } + spin_unlock(&private->mem_lock); + return sizeof(*header) + (num_mem * 3 * sizeof(unsigned int)); +} + /* Snapshot the memory for an indirect buffer */ static int snapshot_ib(struct kgsl_device *device, void *snapshot, int remain, void *priv) { struct kgsl_snapshot_ib *header = snapshot; struct kgsl_snapshot_obj *obj = priv; + struct adreno_device *adreno_dev = ADRENO_DEVICE(device); unsigned int *src = obj->ptr; unsigned int *dst = snapshot + sizeof(*header); - int i, ret; + struct adreno_ib_object_list *ib_obj_list; + unsigned int ib1base; + + adreno_readreg(adreno_dev, ADRENO_REG_CP_IB1_BASE, &ib1base); if (remain < (obj->dwords << 2) + sizeof(*header)) { KGSL_DRV_ERR(device, @@ -834,30 +467,26 @@ static int snapshot_ib(struct kgsl_device *device, void *snapshot, return 0; } + /* only do this for IB1 because the IB2's are part of IB1 objects */ + if (ib1base == obj->gpuaddr) { + if (!adreno_ib_create_object_list(device, obj->ptbase, + obj->gpuaddr, obj->dwords, + &ib_obj_list)) { + /* freeze the IB objects in the IB */ + snapshot_freeze_obj_list(device, obj->ptbase, + ib_obj_list); + adreno_ib_destroy_obj_list(ib_obj_list); + } + } + /* Write the sub-header for the section */ header->gpuaddr = obj->gpuaddr; - header->ptbase = obj->ptbase; + header->ptbase = (__u32)obj->ptbase; header->size = obj->dwords; /* Write the contents of the ib */ - for (i = 0; i < obj->dwords; i++, src++, dst++) { - *dst = *src; - - if (pkt_is_type3(*src)) { - if ((obj->dwords - i) < type3_pkt_size(*src) + 1) - continue; - - if (adreno_cmd_is_ib(*src)) - ret = parse_ib(device, obj->ptbase, src[1], - src[2]); - else - ret = ib_parse_type3(device, src, obj->ptbase); - - /* Stop parsing if the type3 decode fails */ - if (ret < 0) - break; - } - } + memcpy((void *)dst, (void *)src, obj->dwords << 2); + /* Write the contents of the ib */ return (obj->dwords << 2) + sizeof(*header); } @@ -871,6 +500,10 @@ static void *dump_object(struct kgsl_device *device, int obj, void *snapshot, snapshot = kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_IB, snapshot, remain, snapshot_ib, &objbuf[obj]); + if (objbuf[obj].entry) { + kgsl_memdesc_unmap(&(objbuf[obj].entry->memdesc)); + kgsl_mem_entry_put(objbuf[obj].entry); + } break; default: KGSL_DRV_ERR(device, @@ -896,23 +529,15 @@ void *adreno_snapshot(struct kgsl_device *device, void *snapshot, int *remain, int hang) { int i; - uint32_t ptbase, ibbase, ibsize; + uint32_t ibbase, ibsize; struct adreno_device *adreno_dev = ADRENO_DEVICE(device); + phys_addr_t ptbase; /* Reset the list of objects */ objbufptr = 0; snapshot_frozen_objsize = 0; - /* Clear the caches for the visibilty stream and VBO parsing */ - - vfd_control_0 = 0; - vfd_index_max = 0; - vsc_size_address = 0; - - memset(vsc_pipe, 0, sizeof(vsc_pipe)); - memset(vbo, 0, sizeof(vbo)); - /* Get the physical address of the MMU pagetable */ ptbase = kgsl_mmu_get_current_ptbase(&device->mmu); @@ -920,6 +545,13 @@ void *adreno_snapshot(struct kgsl_device *device, void *snapshot, int *remain, snapshot = kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_RB, snapshot, remain, snapshot_rb, NULL); + /* + * Add a section that lists (gpuaddr, size, memtype) tuples of the + * hanging process + */ + snapshot = kgsl_snapshot_add_section(device, + KGSL_SNAPSHOT_SECTION_MEMLIST, snapshot, remain, + snapshot_capture_mem_list, NULL); /* * Make sure that the last IB1 that was being executed is dumped. * Since this was the last IB1 that was processed, we should have @@ -927,8 +559,8 @@ void *adreno_snapshot(struct kgsl_device *device, void *snapshot, int *remain, * want to be double plus sure. */ - kgsl_regread(device, REG_CP_IB1_BASE, &ibbase); - kgsl_regread(device, REG_CP_IB1_BUFSZ, &ibsize); + adreno_readreg(adreno_dev, ADRENO_REG_CP_IB1_BASE, &ibbase); + adreno_readreg(adreno_dev, ADRENO_REG_CP_IB1_BUFSZ, &ibsize); /* * The problem is that IB size from the register is the unprocessed size @@ -945,8 +577,8 @@ void *adreno_snapshot(struct kgsl_device *device, void *snapshot, int *remain, "Dumping %x dwords of the buffer.\n", ibsize); } - kgsl_regread(device, REG_CP_IB2_BASE, &ibbase); - kgsl_regread(device, REG_CP_IB2_BUFSZ, &ibsize); + adreno_readreg(adreno_dev, ADRENO_REG_CP_IB2_BASE, &ibbase); + adreno_readreg(adreno_dev, ADRENO_REG_CP_IB2_BUFSZ, &ibsize); /* * Add the last parsed IB2 to the list. The IB2 should be found as we @@ -977,5 +609,12 @@ void *adreno_snapshot(struct kgsl_device *device, void *snapshot, int *remain, KGSL_DRV_ERR(device, "GPU snapshot froze %dKb of GPU buffers\n", snapshot_frozen_objsize / 1024); + /* + * Queue a work item that will save the IB data in snapshot into + * static memory to prevent loss of data due to overwriting of + * memory + */ + queue_work(device->work_queue, &device->snapshot_obj_ws); + return snapshot; } diff --git a/drivers/gpu/msm/adreno_trace.h b/drivers/gpu/msm/adreno_trace.h index 8993afb3764..8a9046c4752 100644 --- a/drivers/gpu/msm/adreno_trace.h +++ b/drivers/gpu/msm/adreno_trace.h @@ -61,14 +61,78 @@ DECLARE_EVENT_CLASS(adreno_cmdbatch_template, ) ); -DEFINE_EVENT(adreno_cmdbatch_template, adreno_cmdbatch_retired, +DEFINE_EVENT(adreno_cmdbatch_template, adreno_cmdbatch_submitted, TP_PROTO(struct kgsl_cmdbatch *cmdbatch, int inflight), TP_ARGS(cmdbatch, inflight) ); -DEFINE_EVENT(adreno_cmdbatch_template, adreno_cmdbatch_submitted, +TRACE_EVENT(adreno_cmdbatch_retired, TP_PROTO(struct kgsl_cmdbatch *cmdbatch, int inflight), - TP_ARGS(cmdbatch, inflight) + TP_ARGS(cmdbatch, inflight), + TP_STRUCT__entry( + __field(unsigned int, id) + __field(unsigned int, timestamp) + __field(unsigned int, inflight) + __field(unsigned int, recovery) + ), + TP_fast_assign( + __entry->id = cmdbatch->context->id; + __entry->timestamp = cmdbatch->timestamp; + __entry->inflight = inflight; + __entry->recovery = cmdbatch->fault_recovery; + ), + TP_printk( + "ctx=%u ts=%u inflight=%u recovery=%s", + __entry->id, __entry->timestamp, + __entry->inflight, + __entry->recovery ? + __print_flags(__entry->recovery, "|", + ADRENO_FT_TYPES) : "none" + ) +); + +TRACE_EVENT(adreno_cmdbatch_fault, + TP_PROTO(struct kgsl_cmdbatch *cmdbatch, unsigned int fault), + TP_ARGS(cmdbatch, fault), + TP_STRUCT__entry( + __field(unsigned int, id) + __field(unsigned int, timestamp) + __field(unsigned int, fault) + ), + TP_fast_assign( + __entry->id = cmdbatch->context->id; + __entry->timestamp = cmdbatch->timestamp; + __entry->fault = fault; + ), + TP_printk( + "ctx=%u ts=%u type=%s", + __entry->id, __entry->timestamp, + __print_symbolic(__entry->fault, + { 0, "none" }, + { ADRENO_SOFT_FAULT, "soft" }, + { ADRENO_HARD_FAULT, "hard" }, + { ADRENO_TIMEOUT_FAULT, "timeout" }) + ) +); + +TRACE_EVENT(adreno_cmdbatch_recovery, + TP_PROTO(struct kgsl_cmdbatch *cmdbatch, unsigned int action), + TP_ARGS(cmdbatch, action), + TP_STRUCT__entry( + __field(unsigned int, id) + __field(unsigned int, timestamp) + __field(unsigned int, action) + ), + TP_fast_assign( + __entry->id = cmdbatch->context->id; + __entry->timestamp = cmdbatch->timestamp; + __entry->action = action; + ), + TP_printk( + "ctx=%u ts=%u action=%s", + __entry->id, __entry->timestamp, + __print_symbolic(__entry->action, ADRENO_FT_TYPES) + ) ); DECLARE_EVENT_CLASS(adreno_drawctxt_template, @@ -134,12 +198,36 @@ TRACE_EVENT(adreno_drawctxt_wait_done, ) ); +TRACE_EVENT(adreno_drawctxt_switch, + TP_PROTO(struct adreno_context *oldctx, + struct adreno_context *newctx, + unsigned int flags), + TP_ARGS(oldctx, newctx, flags), + TP_STRUCT__entry( + __field(unsigned int, oldctx) + __field(unsigned int, newctx) + __field(unsigned int, flags) + ), + TP_fast_assign( + __entry->oldctx = oldctx ? oldctx->base.id : 0; + __entry->newctx = newctx ? newctx->base.id : 0; + ), + TP_printk( + "oldctx=%u newctx=%u flags=%X", + __entry->oldctx, __entry->newctx, flags + ) +); + TRACE_EVENT(adreno_gpu_fault, - TP_PROTO(unsigned int status, unsigned int rptr, unsigned int wptr, + TP_PROTO(unsigned int ctx, unsigned int ts, + unsigned int status, unsigned int rptr, unsigned int wptr, unsigned int ib1base, unsigned int ib1size, unsigned int ib2base, unsigned int ib2size), - TP_ARGS(status, rptr, wptr, ib1base, ib1size, ib2base, ib2size), + TP_ARGS(ctx, ts, status, rptr, wptr, ib1base, ib1size, ib2base, + ib2size), TP_STRUCT__entry( + __field(unsigned int, ctx) + __field(unsigned int, ts) __field(unsigned int, status) __field(unsigned int, rptr) __field(unsigned int, wptr) @@ -149,6 +237,8 @@ TRACE_EVENT(adreno_gpu_fault, __field(unsigned int, ib2size) ), TP_fast_assign( + __entry->ctx = ctx; + __entry->ts = ts; __entry->status = status; __entry->rptr = rptr; __entry->wptr = wptr; @@ -157,10 +247,10 @@ TRACE_EVENT(adreno_gpu_fault, __entry->ib2base = ib2base; __entry->ib2size = ib2size; ), - TP_printk("status=%X RB=%X/%X IB1=%X/%X IB2=%X/%X", - __entry->status, __entry->wptr, __entry->rptr, - __entry->ib1base, __entry->ib1size, __entry->ib2base, - __entry->ib2size) + TP_printk("ctx=%d ts=%d status=%X RB=%X/%X IB1=%X/%X IB2=%X/%X", + __entry->ctx, __entry->ts, __entry->status, __entry->wptr, + __entry->rptr, __entry->ib1base, __entry->ib1size, + __entry->ib2base, __entry->ib2size) ); #endif /* _ADRENO_TRACE_H */ diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index bf7ec97a8b7..8ca70e14692 100644 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -19,14 +19,14 @@ #include #include #include -#include +#include + #include #include #include #include #include #include -#include #include #include #include @@ -54,8 +54,17 @@ module_param_named(mmutype, ksgl_mmu_type, charp, 0); MODULE_PARM_DESC(ksgl_mmu_type, "Type of MMU to be used for graphics. Valid values are 'iommu' or 'gpummu' or 'nommu'"); -static struct ion_client *kgsl_ion_client; +struct kgsl_dma_buf_meta { + struct dma_buf_attachment *attach; + struct dma_buf *dmabuf; + struct sg_table *table; +}; + +static void kgsl_mem_entry_detach_process(struct kgsl_mem_entry *entry); +static void +kgsl_put_process_private(struct kgsl_device *device, + struct kgsl_process_private *private); /** * kgsl_trace_issueibcmds() - Call trace_issueibcmds by proxy * device: KGSL device @@ -151,8 +160,8 @@ void kgsl_memfree_hist_set_event(unsigned int pid, unsigned int gpuaddr, */ struct kgsl_mem_entry * __must_check -kgsl_get_mem_entry(struct kgsl_device *device, unsigned int ptbase, - unsigned int gpuaddr, unsigned int size) +kgsl_get_mem_entry(struct kgsl_device *device, + phys_addr_t ptbase, unsigned int gpuaddr, unsigned int size) { struct kgsl_process_private *priv; struct kgsl_mem_entry *entry; @@ -188,6 +197,17 @@ kgsl_mem_entry_create(void) return entry; } +static void kgsl_destroy_ion(struct kgsl_dma_buf_meta *meta) +{ + if (meta != NULL) { + dma_buf_unmap_attachment(meta->attach, meta->table, + DMA_FROM_DEVICE); + dma_buf_detach(meta->dmabuf, meta->attach); + dma_buf_put(meta->dmabuf); + kfree(meta); + } +} + void kgsl_mem_entry_destroy(struct kref *kref) { @@ -195,6 +215,9 @@ kgsl_mem_entry_destroy(struct kref *kref) struct kgsl_mem_entry, refcount); + /* Detach from process list */ + kgsl_mem_entry_detach_process(entry); + if (entry->memtype != KGSL_MEM_ENTRY_KERNEL) kgsl_driver.stats.mapped -= entry->memdesc.size; @@ -217,7 +240,7 @@ kgsl_mem_entry_destroy(struct kref *kref) fput(entry->priv_data); break; case KGSL_MEM_ENTRY_ION: - ion_free(kgsl_ion_client, entry->priv_data); + kgsl_destroy_ion(entry->priv_data); break; } @@ -226,23 +249,46 @@ kgsl_mem_entry_destroy(struct kref *kref) EXPORT_SYMBOL(kgsl_mem_entry_destroy); /** - * kgsl_mem_entry_track_gpuaddr - Insert a mem_entry in the address tree + * kgsl_mem_entry_track_gpuaddr - Insert a mem_entry in the address tree and + * assign it with a gpu address space before insertion * @process: the process that owns the memory * @entry: the memory entry * - * Insert a kgsl_mem_entry in to the rb_tree for searching by GPU address. - * Not all mem_entries will have gpu addresses when first created, so this - * function may be called after creation when the GPU address is finally - * assigned. + * @returns - 0 on succcess else error code + * + * Insert the kgsl_mem_entry in to the rb_tree for searching by GPU address. + * The assignment of gpu address and insertion into list needs to + * happen with the memory lock held to avoid race conditions between + * gpu address being selected and some other thread looking through the + * rb list in search of memory based on gpuaddr + * This function should be called with processes memory spinlock held */ -static void +static int kgsl_mem_entry_track_gpuaddr(struct kgsl_process_private *process, struct kgsl_mem_entry *entry) { + int ret = 0; struct rb_node **node; struct rb_node *parent = NULL; - spin_lock(&process->mem_lock); + assert_spin_locked(&process->mem_lock); + /* + * If cpu=gpu map is used then caller needs to set the + * gpu address + */ + if (kgsl_memdesc_use_cpu_map(&entry->memdesc)) { + if (!entry->memdesc.gpuaddr) + goto done; + } else if (entry->memdesc.gpuaddr) { + WARN_ONCE(1, "gpuaddr assigned w/o holding memory lock\n"); + ret = -EINVAL; + goto done; + } + if (!kgsl_memdesc_use_cpu_map(&entry->memdesc)) { + ret = kgsl_mmu_get_gpuaddr(process->pagetable, &entry->memdesc); + if (ret) + goto done; + } node = &process->mem_rb.rb_node; @@ -261,7 +307,27 @@ kgsl_mem_entry_track_gpuaddr(struct kgsl_process_private *process, rb_link_node(&entry->node, parent, node); rb_insert_color(&entry->node, &process->mem_rb); - spin_unlock(&process->mem_lock); +done: + return ret; +} + +/** + * kgsl_mem_entry_untrack_gpuaddr() - Untrack memory that is previously tracked + * process - Pointer to process private to which memory belongs + * entry - Memory entry to untrack + * + * Function just does the opposite of kgsl_mem_entry_track_gpuaddr. Needs to be + * called with processes spin lock held + */ +static void +kgsl_mem_entry_untrack_gpuaddr(struct kgsl_process_private *process, + struct kgsl_mem_entry *entry) +{ + assert_spin_locked(&process->mem_lock); + if (entry->memdesc.gpuaddr) { + kgsl_mmu_put_gpuaddr(process->pagetable, &entry->memdesc); + rb_erase(&entry->node, &entry->priv->mem_rb); + } } /** @@ -300,8 +366,19 @@ kgsl_mem_entry_attach_process(struct kgsl_mem_entry *entry, } entry->priv = process; - if (entry->memdesc.gpuaddr != 0) - kgsl_mem_entry_track_gpuaddr(process, entry); + spin_lock(&process->mem_lock); + ret = kgsl_mem_entry_track_gpuaddr(process, entry); + if (ret) + idr_remove(&process->mem_idr, entry->id); + spin_unlock(&process->mem_lock); + if (ret) + goto err; + /* map the memory after unlocking if gpuaddr has been assigned */ + if (entry->memdesc.gpuaddr) { + ret = kgsl_mmu_map(process->pagetable, &entry->memdesc); + if (ret) + kgsl_mem_entry_detach_process(entry); + } err: return ret; } @@ -310,37 +387,23 @@ kgsl_mem_entry_attach_process(struct kgsl_mem_entry *entry, static void kgsl_mem_entry_detach_process(struct kgsl_mem_entry *entry) { - bool had_gpuaddr = false; - if (entry == NULL) return; - /* - * Unmap the entry first so that there isn't a period of - * time where kgsl doesn't know about the address range - * but it is still present in the pagetable. Unmapping will - * clear the gpuaddr field, so remember if we had a mapping, - * and an rbtree entry for later. - */ - had_gpuaddr = entry->memdesc.gpuaddr != 0; - kgsl_mmu_unmap(entry->memdesc.pagetable, &entry->memdesc); + /* Unmap here so that below we can call kgsl_mmu_put_gpuaddr */ + kgsl_mmu_unmap(entry->priv->pagetable, &entry->memdesc); spin_lock(&entry->priv->mem_lock); + kgsl_mem_entry_untrack_gpuaddr(entry->priv, entry); if (entry->id != 0) idr_remove(&entry->priv->mem_idr, entry->id); entry->id = 0; - if (had_gpuaddr) - rb_erase(&entry->node, &entry->priv->mem_rb); - + entry->priv->stats[entry->memtype].cur -= entry->memdesc.size; spin_unlock(&entry->priv->mem_lock); - entry->priv->stats[entry->memtype].cur -= entry->memdesc.size; entry->priv = NULL; - - - kgsl_mem_entry_put(entry); } /** @@ -353,7 +416,7 @@ static void kgsl_mem_entry_detach_process(struct kgsl_mem_entry *entry) * function to initialize the common members of its context struct. * If this function succeeds, reference counting is active in the context * struct and the caller should kgsl_context_put() it on error. - * If it fails, the caller should just free the context structer + * If it fails, the caller should just free the context structure * it passed in. */ int kgsl_context_init(struct kgsl_device_private *dev_priv, @@ -391,15 +454,21 @@ int kgsl_context_init(struct kgsl_device_private *dev_priv, } kref_init(&context->refcount); + /* + * Get a refernce to the process private so its not destroyed, until + * the context is destroyed. This will also prevent the pagetable + * from being destroyed + */ + if (!kref_get_unless_zero(&dev_priv->process_priv->refcount)) + goto fail_free_id; context->device = dev_priv->device; - context->pagetable = dev_priv->process_priv->pagetable; - - context->pid = dev_priv->process_priv->pid; + context->dev_priv = dev_priv; + context->proc_priv = dev_priv->process_priv; + context->pid = task_tgid_nr(current); ret = kgsl_sync_timeline_create(context); - if (ret) { + if (ret) goto fail_free_id; - } /* Initialize the pending event list */ INIT_LIST_HEAD(&context->events); @@ -457,11 +526,12 @@ int kgsl_context_detach(struct kgsl_context *context) /* * Cancel events after the device-specific context is - * destroyed, to avoid possibly freeing memory while + * detached, to avoid possibly freeing memory while * it is still in use by the GPU. */ kgsl_context_cancel_events(device, context); + kgsl_context_put(context); return ret; @@ -485,6 +555,8 @@ kgsl_context_destroy(struct kref *kref) } write_unlock(&device->context_lock); kgsl_sync_timeline_destroy(context); + kgsl_put_process_private(device, + context->proc_priv); device->ftbl->drawctxt_destroy(context); } @@ -537,7 +609,6 @@ EXPORT_SYMBOL(kgsl_check_timestamp); static int kgsl_suspend_device(struct kgsl_device *device, pm_message_t state) { int status = -EINVAL; - unsigned int nap_allowed_saved; struct kgsl_pwrscale_policy *policy_saved; if (!device) @@ -546,8 +617,6 @@ static int kgsl_suspend_device(struct kgsl_device *device, pm_message_t state) KGSL_PWR_WARN(device, "suspend start\n"); mutex_lock(&device->mutex); - nap_allowed_saved = device->pwrctrl.nap_allowed; - device->pwrctrl.nap_allowed = false; policy_saved = device->pwrscale.policy; device->pwrscale.policy = NULL; kgsl_pwrctrl_request_state(device, KGSL_STATE_SUSPEND); @@ -556,7 +625,15 @@ static int kgsl_suspend_device(struct kgsl_device *device, pm_message_t state) device->ftbl->drain(device); /* Wait for the active count to hit zero */ - kgsl_active_count_wait(device); + status = kgsl_active_count_wait(device, 0); + if (status) + goto end; + + /* + * An interrupt could have snuck in and requested NAP in + * the meantime, make sure we're on the SUSPEND path. + */ + kgsl_pwrctrl_request_state(device, KGSL_STATE_SUSPEND); /* Don't let the timer wake us during suspended sleep. */ del_timer_sync(&device->idle_timer); @@ -572,7 +649,7 @@ static int kgsl_suspend_device(struct kgsl_device *device, pm_message_t state) INIT_COMPLETION(device->hwaccess_gate); device->ftbl->suspend_context(device); device->ftbl->stop(device); - pm_qos_update_request(&device->pm_qos_req_dma, + pm_qos_update_request(&device->pwrctrl.pm_qos_req_dma, PM_QOS_DEFAULT_VALUE); kgsl_pwrctrl_set_state(device, KGSL_STATE_SUSPEND); break; @@ -586,20 +663,24 @@ static int kgsl_suspend_device(struct kgsl_device *device, pm_message_t state) goto end; } kgsl_pwrctrl_request_state(device, KGSL_STATE_NONE); - device->pwrctrl.nap_allowed = nap_allowed_saved; device->pwrscale.policy = policy_saved; status = 0; end: + if (status) { + /* On failure, re-resume normal activity */ + if (device->ftbl->resume) + device->ftbl->resume(device); + } + mutex_unlock(&device->mutex); KGSL_PWR_WARN(device, "suspend end\n"); + return status; } static int kgsl_resume_device(struct kgsl_device *device) { - int status = -EINVAL; - if (!device) return -EINVAL; @@ -607,14 +688,30 @@ static int kgsl_resume_device(struct kgsl_device *device) mutex_lock(&device->mutex); if (device->state == KGSL_STATE_SUSPEND) { kgsl_pwrctrl_set_state(device, KGSL_STATE_SLUMBER); - status = 0; complete_all(&device->hwaccess_gate); + } else if (device->state != KGSL_STATE_INIT) { + /* + * This is an error situation,so wait for the device + * to idle and then put the device to SLUMBER state. + * This will put the device to the right state when + * we resume. + */ + if (device->state == KGSL_STATE_ACTIVE) + device->ftbl->idle(device); + kgsl_pwrctrl_request_state(device, KGSL_STATE_SLUMBER); + kgsl_pwrctrl_sleep(device); + KGSL_PWR_ERR(device, + "resume invoked without a suspend\n"); } kgsl_pwrctrl_request_state(device, KGSL_STATE_NONE); + /* Call the GPU specific resume function */ + if (device->ftbl->resume) + device->ftbl->resume(device); + mutex_unlock(&device->mutex); KGSL_PWR_WARN(device, "resume end\n"); - return status; + return 0; } static int kgsl_suspend(struct device *dev) @@ -649,25 +746,6 @@ const struct dev_pm_ops kgsl_pm_ops = { }; EXPORT_SYMBOL(kgsl_pm_ops); -void kgsl_early_suspend_driver(struct early_suspend *h) -{ - struct kgsl_device *device = container_of(h, - struct kgsl_device, display_off); - KGSL_PWR_WARN(device, "early suspend start\n"); - mutex_lock(&device->mutex); - - /* Only go to slumber if active_cnt is 0 */ - if (atomic_read(&device->active_cnt) == 0) { - device->pwrctrl.restore_slumber = true; - kgsl_pwrctrl_request_state(device, KGSL_STATE_SLUMBER); - kgsl_pwrctrl_sleep(device); - } - - mutex_unlock(&device->mutex); - KGSL_PWR_WARN(device, "early suspend end\n"); -} -EXPORT_SYMBOL(kgsl_early_suspend_driver); - int kgsl_suspend_driver(struct platform_device *pdev, pm_message_t state) { @@ -683,38 +761,7 @@ int kgsl_resume_driver(struct platform_device *pdev) } EXPORT_SYMBOL(kgsl_resume_driver); -void kgsl_late_resume_driver(struct early_suspend *h) -{ - struct kgsl_device *device = container_of(h, - struct kgsl_device, display_off); - KGSL_PWR_WARN(device, "late resume start\n"); - mutex_lock(&device->mutex); - device->pwrctrl.restore_slumber = false; - if (device->pwrscale.policy == NULL) - kgsl_pwrctrl_pwrlevel_change(device, KGSL_PWRLEVEL_TURBO); - if (kgsl_pwrctrl_wake(device) != 0) - return; - /* - * We don't have a way to go directly from - * a deeper sleep state to NAP, which is - * the desired state here. - * - * Except if active_cnt is non zero which means that - * we probably went to early_suspend with it non zero - * and thus the system is still in an active state. - */ - - if (atomic_read(&device->active_cnt) == 0) { - kgsl_pwrctrl_request_state(device, KGSL_STATE_NAP); - kgsl_pwrctrl_sleep(device); - } - - mutex_unlock(&device->mutex); - KGSL_PWR_WARN(device, "late resume end\n"); -} -EXPORT_SYMBOL(kgsl_late_resume_driver); - -/* +/** * kgsl_destroy_process_private() - Cleanup function to free process private * @kref: - Pointer to object being destroyed's kref struct * Free struct object and all other resources attached to it. @@ -748,18 +795,18 @@ static void kgsl_destroy_process_private(struct kref *kref) list_del(&private->list); mutex_unlock(&kgsl_driver.process_mutex); - if (private->kobj.parent) + if (private->kobj.state_in_sysfs) kgsl_process_uninit_sysfs(private); if (private->debug_root) debugfs_remove_recursive(private->debug_root); while (1) { - rcu_read_lock(); + spin_lock(&private->mem_lock); entry = idr_get_next(&private->mem_idr, &next); - rcu_read_unlock(); + spin_unlock(&private->mem_lock); if (entry == NULL) break; - kgsl_mem_entry_detach_process(entry); + kgsl_mem_entry_put(entry); /* * Always start back at the beginning, to * ensure all entries are removed, @@ -767,8 +814,8 @@ static void kgsl_destroy_process_private(struct kref *kref) */ next = 0; } - kgsl_mmu_putpagetable(private->pagetable); idr_destroy(&private->mem_idr); + kgsl_mmu_putpagetable(private->pagetable); kfree(private); return; @@ -846,33 +893,67 @@ kgsl_get_process_private(struct kgsl_device_private *cur_dev_priv) mutex_lock(&private->process_private_mutex); - if (!private->mem_rb.rb_node) { - private->mem_rb = RB_ROOT; - idr_init(&private->mem_idr); - } + /* + * If debug root initialized then it means the rest of the fields + * are also initialized + */ + if (private->debug_root) + goto done; + + private->mem_rb = RB_ROOT; + idr_init(&private->mem_idr); if ((!private->pagetable) && kgsl_mmu_enabled()) { unsigned long pt_name; + struct kgsl_mmu *mmu = &cur_dev_priv->device->mmu; pt_name = task_tgid_nr(current); - private->pagetable = kgsl_mmu_getpagetable(pt_name); - if (private->pagetable == NULL) { - mutex_unlock(&private->process_private_mutex); - kgsl_put_process_private(cur_dev_priv->device, - private); - return NULL; - } + private->pagetable = kgsl_mmu_getpagetable(mmu, pt_name); + if (private->pagetable == NULL) + goto error; } - if (!private->kobj.parent) - kgsl_process_init_sysfs(private); - if (!private->debug_root) - kgsl_process_init_debugfs(private); + if (kgsl_process_init_sysfs(cur_dev_priv->device, private)) + goto error; + if (kgsl_process_init_debugfs(private)) + goto error; +done: mutex_unlock(&private->process_private_mutex); - return private; + +error: + mutex_unlock(&private->process_private_mutex); + kgsl_put_process_private(cur_dev_priv->device, private); + return NULL; +} + +int kgsl_close_device(struct kgsl_device *device) +{ + int result = 0; + device->open_count--; + if (device->open_count == 0) { + + /* Wait for the active count to go to 1 */ + kgsl_active_count_wait(device, 1); + + /* Fail if the wait times out */ + BUG_ON(atomic_read(&device->active_cnt) > 1); + + result = device->ftbl->stop(device); + kgsl_pwrctrl_set_state(device, KGSL_STATE_INIT); + /* + * active_cnt special case: we just stopped the device, + * so no need to use kgsl_active_count_put() + */ + atomic_dec(&device->active_cnt); + } else { + kgsl_active_count_put(device); + } + return result; + } +EXPORT_SYMBOL(kgsl_close_device); static int kgsl_release(struct inode *inodep, struct file *filep) { @@ -896,16 +977,16 @@ static int kgsl_release(struct inode *inodep, struct file *filep) if (context == NULL) break; - - if (context->pid == private->pid) { + if (context->dev_priv == dev_priv) { /* * Hold a reference to the context in case somebody * tries to put it while we are detaching */ - _kgsl_context_get(context); - kgsl_context_detach(context); - kgsl_context_put(context); + if (_kgsl_context_get(context)) { + kgsl_context_detach(context); + kgsl_context_put(context); + } } next = next + 1; @@ -918,19 +999,7 @@ static int kgsl_release(struct inode *inodep, struct file *filep) */ kgsl_cancel_events(device, dev_priv); - device->open_count--; - if (device->open_count == 0) { - BUG_ON(atomic_read(&device->active_cnt) > 1); - result = device->ftbl->stop(device); - kgsl_pwrctrl_set_state(device, KGSL_STATE_INIT); - /* - * active_cnt special case: we just stopped the device, - * so no need to use kgsl_active_count_put() - */ - atomic_dec(&device->active_cnt); - } else { - kgsl_active_count_put(device); - } + result = kgsl_close_device(device); mutex_unlock(&device->mutex); kfree(dev_priv); @@ -940,6 +1009,43 @@ static int kgsl_release(struct inode *inodep, struct file *filep) return result; } +int kgsl_open_device(struct kgsl_device *device) +{ + int result = 0; + if (device->open_count == 0) { + /* + * active_cnt special case: we are starting up for the first + * time, so use this sequence instead of the kgsl_pwrctrl_wake() + * which will be called by kgsl_active_count_get(). + */ + atomic_inc(&device->active_cnt); + kgsl_sharedmem_set(device, &device->memstore, 0, 0, + device->memstore.size); + + result = device->ftbl->init(device); + if (result) + goto err; + + result = device->ftbl->start(device); + if (result) + goto err; + /* + * Make sure the gates are open, so they don't block until + * we start suspend or FT. + */ + complete_all(&device->hwaccess_gate); + kgsl_pwrctrl_set_state(device, KGSL_STATE_ACTIVE); + kgsl_active_count_put(device); + } + device->open_count++; +err: + if (result) + atomic_dec(&device->active_cnt); + + return result; +} +EXPORT_SYMBOL(kgsl_open_device); + static int kgsl_open(struct inode *inodep, struct file *filep) { int result; @@ -977,28 +1083,9 @@ static int kgsl_open(struct inode *inodep, struct file *filep) mutex_lock(&device->mutex); - if (device->open_count == 0) { - /* - * active_cnt special case: we are starting up for the first - * time, so use this sequence instead of the kgsl_pwrctrl_wake() - * which will be called by kgsl_active_count_get(). - */ - atomic_inc(&device->active_cnt); - kgsl_sharedmem_set(&device->memstore, 0, 0, - device->memstore.size); - - result = device->ftbl->init(device); - if (result) - goto err_freedevpriv; - - result = device->ftbl->start(device); - if (result) - goto err_freedevpriv; - - kgsl_pwrctrl_set_state(device, KGSL_STATE_ACTIVE); - kgsl_active_count_put(device); - } - device->open_count++; + result = kgsl_open_device(device); + if (result) + goto err_freedevpriv; mutex_unlock(&device->mutex); /* @@ -1026,12 +1113,9 @@ static int kgsl_open(struct inode *inodep, struct file *filep) kgsl_pwrctrl_enable(device); result = device->ftbl->stop(device); kgsl_pwrctrl_set_state(device, KGSL_STATE_INIT); + atomic_dec(&device->active_cnt); } err_freedevpriv: - /* only the first open takes an active count */ - if (device->open_count == 0) - atomic_dec(&device->active_cnt); - mutex_unlock(&device->mutex); filep->private_data = NULL; kfree(dev_priv); @@ -1054,19 +1138,21 @@ struct kgsl_mem_entry * __must_check kgsl_sharedmem_find_region(struct kgsl_process_private *private, unsigned int gpuaddr, size_t size) { - struct rb_node *node = private->mem_rb.rb_node; + struct rb_node *node; - if (!kgsl_mmu_gpuaddr_in_range(gpuaddr)) + if (!kgsl_mmu_gpuaddr_in_range(private->pagetable, gpuaddr)) return NULL; spin_lock(&private->mem_lock); + node = private->mem_rb.rb_node; while (node != NULL) { struct kgsl_mem_entry *entry; entry = rb_entry(node, struct kgsl_mem_entry, node); if (kgsl_gpuaddr_in_memdesc(&entry->memdesc, gpuaddr, size)) { - kgsl_mem_entry_get(entry); + if (!kgsl_mem_entry_get(entry)) + break; spin_unlock(&private->mem_lock); return entry; } @@ -1109,25 +1195,27 @@ kgsl_sharedmem_find(struct kgsl_process_private *private, unsigned int gpuaddr) * @size: length of the region. * * Checks that there are no existing allocations within an address - * region. + * region. This function should be called with processes spin lock + * held. */ -int +static int kgsl_sharedmem_region_empty(struct kgsl_process_private *private, unsigned int gpuaddr, size_t size) { int result = 1; unsigned int gpuaddr_end = gpuaddr + size; - struct rb_node *node = private->mem_rb.rb_node; + struct rb_node *node; + + assert_spin_locked(&private->mem_lock); - if (!kgsl_mmu_gpuaddr_in_range(gpuaddr)) + if (!kgsl_mmu_gpuaddr_in_range(private->pagetable, gpuaddr)) return 0; /* don't overflow */ if (gpuaddr_end < gpuaddr) return 0; - spin_lock(&private->mem_lock); node = private->mem_rb.rb_node; while (node != NULL) { struct kgsl_mem_entry *entry; @@ -1148,7 +1236,6 @@ kgsl_sharedmem_region_empty(struct kgsl_process_private *private, break; } } - spin_unlock(&private->mem_lock); return result; } @@ -1165,17 +1252,44 @@ kgsl_sharedmem_region_empty(struct kgsl_process_private *private, static inline struct kgsl_mem_entry * __must_check kgsl_sharedmem_find_id(struct kgsl_process_private *process, unsigned int id) { + int result = 0; struct kgsl_mem_entry *entry; - rcu_read_lock(); + spin_lock(&process->mem_lock); entry = idr_find(&process->mem_idr, id); if (entry) - kgsl_mem_entry_get(entry); - rcu_read_unlock(); + result = kgsl_mem_entry_get(entry); + spin_unlock(&process->mem_lock); + if (!result) + return NULL; return entry; } +/** + * kgsl_mem_entry_set_pend() - Set the pending free flag of a memory entry + * @entry - The memory entry + * + * @returns - true if pending flag was 0 else false + * + * This function will set the pending free flag if it is previously unset. Used + * to prevent race condition between ioctls calling free/freememontimestamp + * on the same entry. Whichever thread set's the flag first will do the free. + */ +static inline bool kgsl_mem_entry_set_pend(struct kgsl_mem_entry *entry) +{ + bool ret = false; + spin_lock(&entry->priv->mem_lock); + if (entry && entry->pending_free) { + ret = false; + } else if (entry) { + entry->pending_free = 1; + ret = true; + } + spin_unlock(&entry->priv->mem_lock); + return ret; +} + /*call all ioctl sub functions with driver locked*/ static long kgsl_ioctl_device_getproperty(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data) @@ -1558,7 +1672,13 @@ static int kgsl_cmdbatch_add_sync_timestamp(struct kgsl_device *device, if (context == NULL) return -EINVAL; - /* Sanity check - you can't create a sync point on your own context */ + /* + * We allow somebody to create a sync point on their own context. + * This has the effect of delaying a command from submitting until the + * dependent command has cleared. That said we obviously can't let them + * create a sync point on a future timestamp. + */ + if (context == cmdbatch->context) { KGSL_DRV_ERR(device, "Cannot create a sync point on your own context\n"); @@ -1674,10 +1794,21 @@ static struct kgsl_cmdbatch *kgsl_cmdbatch_create(struct kgsl_device *device, if (cmdbatch == NULL) return ERR_PTR(-ENOMEM); + /* + * Increase the reference count on the context so it doesn't disappear + * during the lifetime of this command batch + */ + + if (!_kgsl_context_get(context)) { + kfree(cmdbatch); + return ERR_PTR(-EINVAL); + } + if (!(flags & KGSL_CONTEXT_SYNC)) { cmdbatch->ibdesc = kzalloc(sizeof(*cmdbatch->ibdesc) * numibs, GFP_KERNEL); if (cmdbatch->ibdesc == NULL) { + kgsl_context_put(context); kfree(cmdbatch); return ERR_PTR(-ENOMEM); } @@ -1692,12 +1823,6 @@ static struct kgsl_cmdbatch *kgsl_cmdbatch_create(struct kgsl_device *device, cmdbatch->context = context; cmdbatch->flags = flags; - /* - * Increase the reference count on the context so it doesn't disappear - * during the lifetime of this command batch - */ - _kgsl_context_get(context); - return cmdbatch; } @@ -1709,20 +1834,23 @@ static struct kgsl_cmdbatch *kgsl_cmdbatch_create(struct kgsl_device *device, * Do a quick sanity test on the list of indirect buffers in a command batch * verifying that the size and GPU address */ -static bool _kgsl_cmdbatch_verify(struct kgsl_device *device, +static bool _kgsl_cmdbatch_verify(struct kgsl_device_private *dev_priv, struct kgsl_cmdbatch *cmdbatch) { int i; + struct kgsl_process_private *private = dev_priv->process_priv; + for (i = 0; i < cmdbatch->ibcount; i++) { if (cmdbatch->ibdesc[i].sizedwords == 0) { - KGSL_DRV_ERR(device, + KGSL_DRV_ERR(dev_priv->device, "Invalid IB: size is 0\n"); return false; } - if (!kgsl_mmu_gpuaddr_in_range(cmdbatch->ibdesc[i].gpuaddr)) { - KGSL_DRV_ERR(device, + if (!kgsl_mmu_gpuaddr_in_range(private->pagetable, + cmdbatch->ibdesc[i].gpuaddr)) { + KGSL_DRV_ERR(dev_priv->device, "Invalid IB: address 0x%X is out of range\n", cmdbatch->ibdesc[i].gpuaddr); return false; @@ -1863,7 +1991,7 @@ static long kgsl_ioctl_rb_issueibcmds(struct kgsl_device_private *dev_priv, } /* Run basic sanity checking on the command */ - if (!_kgsl_cmdbatch_verify(device, cmdbatch)) { + if (!_kgsl_cmdbatch_verify(dev_priv, cmdbatch)) { KGSL_DRV_ERR(device, "Unable to verify the IBs\n"); goto free_cmdbatch; } @@ -1913,7 +2041,7 @@ static long kgsl_ioctl_submit_commands(struct kgsl_device_private *dev_priv, } /* Run basic sanity checking on the command */ - if (!_kgsl_cmdbatch_verify(device, cmdbatch)) { + if (!_kgsl_cmdbatch_verify(dev_priv, cmdbatch)) { KGSL_DRV_ERR(device, "Unable to verify the IBs\n"); goto free_cmdbatch; } @@ -1978,7 +2106,7 @@ static void kgsl_freemem_event_cb(struct kgsl_device *device, /* Free the memory for all event types */ trace_kgsl_mem_timestamp_free(device, entry, id, timestamp, 0); - kgsl_mem_entry_detach_process(entry); + kgsl_mem_entry_put(entry); } static long _cmdstream_freememontimestamp(struct kgsl_device_private *dev_priv, @@ -1997,6 +2125,13 @@ static long _cmdstream_freememontimestamp(struct kgsl_device_private *dev_priv, "invalid gpuaddr %08x\n", gpuaddr); return -EINVAL; } + if (!kgsl_mem_entry_set_pend(entry)) { + KGSL_DRV_WARN(dev_priv->device, + "Cannot set pending bit for gpuaddr %08x\n", gpuaddr); + kgsl_mem_entry_put(entry); + return -EBUSY; + } + trace_kgsl_mem_timestamp_queue(device, entry, context_id, kgsl_readtimestamp(device, context, KGSL_TIMESTAMP_RETIRED), @@ -2081,6 +2216,10 @@ static long kgsl_ioctl_sharedmem_free(struct kgsl_device_private *dev_priv, param->gpuaddr); return -EINVAL; } + if (!kgsl_mem_entry_set_pend(entry)) { + kgsl_mem_entry_put(entry); + return -EBUSY; + } trace_kgsl_mem_free(entry); @@ -2089,7 +2228,12 @@ static long kgsl_ioctl_sharedmem_free(struct kgsl_device_private *dev_priv, entry->memdesc.size, entry->memdesc.flags); - kgsl_mem_entry_detach_process(entry); + /* + * First kgsl_mem_entry_put is for the reference that we took in + * this function when calling kgsl_sharedmem_find, second one is + * to free the memory since this is a free ioctl + */ + kgsl_mem_entry_put(entry); kgsl_mem_entry_put(entry); return 0; } @@ -2107,9 +2251,20 @@ static long kgsl_ioctl_gpumem_free_id(struct kgsl_device_private *dev_priv, KGSL_MEM_INFO(dev_priv->device, "invalid id %d\n", param->id); return -EINVAL; } + + if (!kgsl_mem_entry_set_pend(entry)) { + kgsl_mem_entry_put(entry); + return -EBUSY; + } + trace_kgsl_mem_free(entry); - kgsl_mem_entry_detach_process(entry); + /* + * First kgsl_mem_entry_put is for the reference that we took in + * this function when calling kgsl_sharedmem_find_id, second one is + * to free the memory since this is a free ioctl + */ + kgsl_mem_entry_put(entry); kgsl_mem_entry_put(entry); return 0; } @@ -2142,11 +2297,10 @@ static int kgsl_get_phys_file(int fd, unsigned long *start, unsigned long *len, dev_t rdev; struct fb_info *info; + *start = 0; + *vstart = 0; + *len = 0; *filep = NULL; -#ifdef CONFIG_ANDROID_PMEM - if (!get_pmem_file(fd, start, vstart, len, filep)) - return 0; -#endif fbfile = fget(fd); if (fbfile == NULL) { @@ -2237,9 +2391,6 @@ static int kgsl_setup_phys_file(struct kgsl_mem_entry *entry, return 0; err: -#ifdef CONFIG_ANDROID_PMEM - put_pmem_file(filep); -#endif return ret; } @@ -2423,33 +2574,55 @@ static int kgsl_setup_ashmem(struct kgsl_mem_entry *entry, #endif static int kgsl_setup_ion(struct kgsl_mem_entry *entry, - struct kgsl_pagetable *pagetable, int fd) + struct kgsl_pagetable *pagetable, void *data, + struct kgsl_device *device) { - struct ion_handle *handle; struct scatterlist *s; struct sg_table *sg_table; + struct kgsl_map_user_mem *param = data; + int fd = param->fd; + struct dma_buf *dmabuf; + struct dma_buf_attachment *attach = NULL; + struct kgsl_dma_buf_meta *meta; + int ret = 0; - if (IS_ERR_OR_NULL(kgsl_ion_client)) - return -ENODEV; - - handle = ion_import_dma_buf(kgsl_ion_client, fd); - if (IS_ERR(handle)) - return PTR_ERR(handle); - else if (!handle) + if (!param->len) return -EINVAL; + meta = kzalloc(sizeof(*meta), GFP_KERNEL); + if (!meta) + return -ENOMEM; + + dmabuf = dma_buf_get(fd); + if (IS_ERR_OR_NULL(dmabuf)) { + ret = PTR_ERR(dmabuf); + goto out; + } + + attach = dma_buf_attach(dmabuf, device->dev); + if (IS_ERR_OR_NULL(attach)) { + ret = PTR_ERR(attach); + goto out; + } + + meta->dmabuf = dmabuf; + meta->attach = attach; + entry->memtype = KGSL_MEM_ENTRY_ION; - entry->priv_data = handle; entry->memdesc.pagetable = pagetable; entry->memdesc.size = 0; /* USE_CPU_MAP is not impemented for ION. */ entry->memdesc.flags &= ~KGSL_MEMFLAGS_USE_CPU_MAP; - sg_table = ion_sg_table(kgsl_ion_client, handle); + sg_table = dma_buf_map_attachment(attach, DMA_TO_DEVICE); - if (IS_ERR_OR_NULL(sg_table)) - goto err; + if (IS_ERR_OR_NULL(sg_table)) { + ret = PTR_ERR(sg_table); + goto out; + } + meta->table = sg_table; + entry->priv_data = meta; entry->memdesc.sg = sg_table->sgl; /* Calculate the size of the memdesc from the sglist */ @@ -2461,17 +2634,20 @@ static int kgsl_setup_ion(struct kgsl_mem_entry *entry, entry->memdesc.sglen++; } - return 0; -err: - ion_free(kgsl_ion_client, handle); - return -ENOMEM; -} + entry->memdesc.size = PAGE_ALIGN(entry->memdesc.size); -static inline int -can_use_cpu_map(void) -{ - return (kgsl_mmu_get_mmutype() == KGSL_MMU_TYPE_IOMMU - && kgsl_mmu_is_perprocess()); +out: + if (ret) { + if (!IS_ERR_OR_NULL(attach)) + dma_buf_detach(dmabuf, attach); + + if (!IS_ERR_OR_NULL(dmabuf)) + dma_buf_put(dmabuf); + + kfree(meta); + } + + return ret; } static long kgsl_ioctl_map_user_mem(struct kgsl_device_private *dev_priv, @@ -2505,7 +2681,7 @@ static long kgsl_ioctl_map_user_mem(struct kgsl_device_private *dev_priv, | KGSL_MEMFLAGS_USE_CPU_MAP; entry->memdesc.flags = param->flags; - if (!can_use_cpu_map()) + if (!kgsl_mmu_use_cpu_map(private->pagetable->mmu)) entry->memdesc.flags &= ~KGSL_MEMFLAGS_USE_CPU_MAP; if (kgsl_mmu_get_mmutype() == KGSL_MMU_TYPE_IOMMU) @@ -2559,8 +2735,8 @@ static long kgsl_ioctl_map_user_mem(struct kgsl_device_private *dev_priv, entry->memtype = KGSL_MEM_ENTRY_ASHMEM; break; case KGSL_USER_MEM_TYPE_ION: - result = kgsl_setup_ion(entry, private->pagetable, - param->fd); + result = kgsl_setup_ion(entry, private->pagetable, data, + dev_priv->device); break; default: KGSL_CORE_ERR("Invalid memory type: %x\n", memtype); @@ -2575,18 +2751,15 @@ static long kgsl_ioctl_map_user_mem(struct kgsl_device_private *dev_priv, else if (entry->memdesc.size >= SZ_64K) kgsl_memdesc_set_align(&entry->memdesc, ilog2(SZ_64)); - result = kgsl_mmu_map(private->pagetable, &entry->memdesc); - if (result) - goto error_put_file_ptr; - - /* Adjust the returned value for a non 4k aligned offset */ - param->gpuaddr = entry->memdesc.gpuaddr + (param->offset & ~PAGE_MASK); /* echo back flags */ param->flags = entry->memdesc.flags; result = kgsl_mem_entry_attach_process(entry, private); if (result) - goto error_unmap; + goto error_attach; + + /* Adjust the returned value for a non 4k aligned offset */ + param->gpuaddr = entry->memdesc.gpuaddr + (param->offset & ~PAGE_MASK); KGSL_STATS_ADD(param->len, kgsl_driver.stats.mapped, kgsl_driver.stats.mapped_max); @@ -2597,9 +2770,7 @@ static long kgsl_ioctl_map_user_mem(struct kgsl_device_private *dev_priv, return result; -error_unmap: - kgsl_mmu_unmap(private->pagetable, &entry->memdesc); -error_put_file_ptr: +error_attach: switch (entry->memtype) { case KGSL_MEM_ENTRY_PMEM: case KGSL_MEM_ENTRY_ASHMEM: @@ -2607,7 +2778,7 @@ static long kgsl_ioctl_map_user_mem(struct kgsl_device_private *dev_priv, fput(entry->priv_data); break; case KGSL_MEM_ENTRY_ION: - ion_free(kgsl_ion_client, entry->priv_data); + kgsl_destroy_ion(entry->priv_data); break; default: break; @@ -2753,7 +2924,8 @@ kgsl_ioctl_gpumem_sync_cache_bulk(struct kgsl_device_private *dev_priv, entries[actual_count++] = entry; /* If we exceed the breakeven point, flush the entire cache */ - if (op_size >= kgsl_driver.full_cache_threshold && + if (kgsl_driver.full_cache_threshold != 0 && + op_size >= kgsl_driver.full_cache_threshold && param->op == KGSL_GPUMEM_CACHE_FLUSH) { full_flush = true; break; @@ -2812,6 +2984,7 @@ _gpumem_alloc(struct kgsl_device_private *dev_priv, int result; struct kgsl_process_private *private = dev_priv->process_priv; struct kgsl_mem_entry *entry; + int align; /* * Mask off unknown flags from userspace. This way the caller can @@ -2823,6 +2996,15 @@ _gpumem_alloc(struct kgsl_device_private *dev_priv, | KGSL_MEMALIGN_MASK | KGSL_MEMFLAGS_USE_CPU_MAP; + /* Cap the alignment bits to the highest number we can handle */ + + align = (flags & KGSL_MEMALIGN_MASK) >> KGSL_MEMALIGN_SHIFT; + if (align >= 32) { + KGSL_CORE_ERR("Alignment too big, restricting to 2^32\n"); + flags &= ~KGSL_MEMALIGN_MASK; + flags |= (31 << KGSL_MEMALIGN_SHIFT) & KGSL_MEMALIGN_MASK; + } + entry = kgsl_mem_entry_create(); if (entry == NULL) return -ENOMEM; @@ -2859,10 +3041,6 @@ kgsl_ioctl_gpumem_alloc(struct kgsl_device_private *dev_priv, if (result) return result; - result = kgsl_mmu_map(private->pagetable, &entry->memdesc); - if (result) - goto err; - result = kgsl_mem_entry_attach_process(entry, private); if (result != 0) goto err; @@ -2889,19 +3067,13 @@ kgsl_ioctl_gpumem_alloc_id(struct kgsl_device_private *dev_priv, struct kgsl_mem_entry *entry = NULL; int result; - if (!can_use_cpu_map()) + if (!kgsl_mmu_use_cpu_map(private->pagetable->mmu)) param->flags &= ~KGSL_MEMFLAGS_USE_CPU_MAP; result = _gpumem_alloc(dev_priv, &entry, param->size, param->flags); if (result != 0) goto err; - if (!kgsl_memdesc_use_cpu_map(&entry->memdesc)) { - result = kgsl_mmu_map(private->pagetable, &entry->memdesc); - if (result) - goto err; - } - result = kgsl_mem_entry_attach_process(entry, private); if (result != 0) goto err; @@ -2985,7 +3157,8 @@ static long kgsl_ioctl_cff_user_event(struct kgsl_device_private *dev_priv, int result = 0; struct kgsl_cff_user_event *param = data; - kgsl_cffdump_user_event(param->cff_opcode, param->op1, param->op2, + kgsl_cffdump_user_event(dev_priv->device, param->cff_opcode, + param->op1, param->op2, param->op3, param->op4, param->op5); return result; @@ -3128,7 +3301,7 @@ static const struct { } kgsl_ioctl_funcs[] = { KGSL_IOCTL_FUNC(IOCTL_KGSL_DEVICE_GETPROPERTY, kgsl_ioctl_device_getproperty, - KGSL_IOCTL_LOCK | KGSL_IOCTL_WAKE), + KGSL_IOCTL_LOCK), KGSL_IOCTL_FUNC(IOCTL_KGSL_DEVICE_WAITTIMESTAMP, kgsl_ioctl_device_waittimestamp, KGSL_IOCTL_LOCK | KGSL_IOCTL_WAKE), @@ -3147,13 +3320,13 @@ static const struct { KGSL_IOCTL_LOCK), KGSL_IOCTL_FUNC(IOCTL_KGSL_CMDSTREAM_FREEMEMONTIMESTAMP, kgsl_ioctl_cmdstream_freememontimestamp, - KGSL_IOCTL_LOCK | KGSL_IOCTL_WAKE), + KGSL_IOCTL_LOCK), KGSL_IOCTL_FUNC(IOCTL_KGSL_CMDSTREAM_FREEMEMONTIMESTAMP_CTXTID, kgsl_ioctl_cmdstream_freememontimestamp_ctxtid, - KGSL_IOCTL_LOCK | KGSL_IOCTL_WAKE), + KGSL_IOCTL_LOCK), KGSL_IOCTL_FUNC(IOCTL_KGSL_DRAWCTXT_CREATE, kgsl_ioctl_drawctxt_create, - KGSL_IOCTL_LOCK | KGSL_IOCTL_WAKE), + KGSL_IOCTL_LOCK), KGSL_IOCTL_FUNC(IOCTL_KGSL_DRAWCTXT_DESTROY, kgsl_ioctl_drawctxt_destroy, KGSL_IOCTL_LOCK | KGSL_IOCTL_WAKE), @@ -3173,10 +3346,10 @@ static const struct { kgsl_ioctl_cff_user_event, 0), KGSL_IOCTL_FUNC(IOCTL_KGSL_TIMESTAMP_EVENT, kgsl_ioctl_timestamp_event, - KGSL_IOCTL_LOCK | KGSL_IOCTL_WAKE), + KGSL_IOCTL_LOCK), KGSL_IOCTL_FUNC(IOCTL_KGSL_SETPROPERTY, kgsl_ioctl_device_setproperty, - KGSL_IOCTL_LOCK | KGSL_IOCTL_WAKE), + KGSL_IOCTL_LOCK), KGSL_IOCTL_FUNC(IOCTL_KGSL_GPUMEM_ALLOC_ID, kgsl_ioctl_gpumem_alloc_id, 0), KGSL_IOCTL_FUNC(IOCTL_KGSL_GPUMEM_FREE_ID, @@ -3269,8 +3442,10 @@ static long kgsl_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) mutex_lock(&dev_priv->device->mutex); if (use_hw) { ret = kgsl_active_count_get(dev_priv->device); - if (ret < 0) + if (ret < 0) { + use_hw = 0; goto unlock; + } } } @@ -3283,7 +3458,11 @@ static long kgsl_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) mutex_unlock(&dev_priv->device->mutex); } - if (ret == 0 && (cmd & IOC_OUT)) { + /* + * Still copy back on failure, but assume function took + * all necessary precautions sanitizing the return values. + */ + if (cmd & IOC_OUT) { if (copy_to_user((void __user *) arg, uptr, _IOC_SIZE(cmd))) ret = -EFAULT; } @@ -3333,7 +3512,8 @@ kgsl_mmap_memstore(struct kgsl_device *device, struct vm_area_struct *vma) static void kgsl_gpumem_vm_open(struct vm_area_struct *vma) { struct kgsl_mem_entry *entry = vma->vm_private_data; - kgsl_mem_entry_get(entry); + if (!kgsl_mem_entry_get(entry)) + vma->vm_private_data = NULL; } static int @@ -3341,6 +3521,8 @@ kgsl_gpumem_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) { struct kgsl_mem_entry *entry = vma->vm_private_data; + if (!entry) + return VM_FAULT_SIGBUS; if (!entry->memdesc.ops || !entry->memdesc.ops->vmfault) return VM_FAULT_SIGBUS; @@ -3352,6 +3534,9 @@ kgsl_gpumem_vm_close(struct vm_area_struct *vma) { struct kgsl_mem_entry *entry = vma->vm_private_data; + if (!entry) + return; + entry->memdesc.useraddr = 0; kgsl_mem_entry_put(entry); } @@ -3429,7 +3614,7 @@ kgsl_get_unmapped_area(struct file *file, unsigned long addr, if (ret) return ret; - if (!kgsl_memdesc_use_cpu_map(&entry->memdesc) || (flags & MAP_FIXED)) { + if (!kgsl_memdesc_use_cpu_map(&entry->memdesc)) { /* * If we're not going to use the same mapping on the gpu, * any address is fine. @@ -3470,7 +3655,7 @@ kgsl_get_unmapped_area(struct file *file, unsigned long addr, */ if (!retry && (ret == (unsigned long)-ENOMEM) && (align > PAGE_SHIFT)) { - align = PAGE_SHIFT; + align = 0; addr = 0; len = orig_len; retry = 1; @@ -3482,16 +3667,39 @@ kgsl_get_unmapped_area(struct file *file, unsigned long addr, ret = ALIGN(ret, (1 << align)); /*make sure there isn't a GPU only mapping at this address */ - if (kgsl_sharedmem_region_empty(private, ret, len)) + spin_lock(&private->mem_lock); + if (kgsl_sharedmem_region_empty(private, ret, orig_len)) { + int ret_val; + /* + * We found a free memory map, claim it here with + * memory lock held + */ + entry->memdesc.gpuaddr = ret; + /* This should never fail */ + ret_val = kgsl_mem_entry_track_gpuaddr(private, entry); + spin_unlock(&private->mem_lock); + BUG_ON(ret_val); + /* map cannot be called with lock held */ + ret_val = kgsl_mmu_map(private->pagetable, + &entry->memdesc); + if (ret_val) { + spin_lock(&private->mem_lock); + kgsl_mem_entry_untrack_gpuaddr(private, entry); + spin_unlock(&private->mem_lock); + ret = ret_val; + } break; + } + spin_unlock(&private->mem_lock); - trace_kgsl_mem_unmapped_area_collision(entry, addr, len, ret); + trace_kgsl_mem_unmapped_area_collision(entry, addr, orig_len, + ret); /* * If we collided, bump the hint address so that * get_umapped_area knows to look somewhere else. */ - addr = (addr == 0) ? ret + len : addr + len; + addr = (addr == 0) ? ret + orig_len : addr + orig_len; /* * The addr hint can be set by userspace to be near @@ -3505,10 +3713,10 @@ kgsl_get_unmapped_area(struct file *file, unsigned long addr, } else { ret = -EBUSY; } - } while (mmap_range_valid(addr, len)); + } while (!(flags & MAP_FIXED) && mmap_range_valid(addr, len)); if (IS_ERR_VALUE(ret)) - KGSL_MEM_INFO(device, + KGSL_MEM_ERR(device, "pid %d pgoff %lx len %ld failed error %ld\n", private->pid, pgoff, len, ret); put: @@ -3539,17 +3747,6 @@ static int kgsl_mmap(struct file *file, struct vm_area_struct *vma) if (ret) return ret; - if (kgsl_memdesc_use_cpu_map(&entry->memdesc)) { - entry->memdesc.gpuaddr = vma->vm_start; - - ret = kgsl_mmu_map(private->pagetable, &entry->memdesc); - if (ret) { - kgsl_mem_entry_put(entry); - return ret; - } - kgsl_mem_entry_track_gpuaddr(private, entry); - } - vma->vm_flags |= entry->memdesc.ops->vmflags(&entry->memdesc); vma->vm_private_data = entry; @@ -3710,8 +3907,7 @@ int kgsl_device_platform_probe(struct kgsl_device *device) if (status) goto error; - kgsl_ion_client = msm_ion_client_create(UINT_MAX, KGSL_NAME); - + /* Get starting physical address of device registers */ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, device->iomemname); if (res == NULL) { @@ -3729,6 +3925,33 @@ int kgsl_device_platform_probe(struct kgsl_device *device) device->reg_phys = res->start; device->reg_len = resource_size(res); + /* + * Check if a shadermemname is defined, and then get shader memory + * details including shader memory starting physical address + * and shader memory length + */ + if (device->shadermemname != NULL) { + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + device->shadermemname); + + if (res == NULL) { + KGSL_DRV_ERR(device, + "Shader memory: platform_get_resource_byname failed\n"); + } + + else { + device->shader_mem_phys = res->start; + device->shader_mem_len = resource_size(res); + } + + if (!devm_request_mem_region(device->dev, + device->shader_mem_phys, + device->shader_mem_len, + device->name)) { + KGSL_DRV_ERR(device, "request_mem_region_failed\n"); + } + } + if (!devm_request_mem_region(device->dev, device->reg_phys, device->reg_len, device->name)) { KGSL_DRV_ERR(device, "request_mem_region failed\n"); @@ -3797,7 +4020,8 @@ int kgsl_device_platform_probe(struct kgsl_device *device) goto error_close_mmu; } - pm_qos_add_request(&device->pm_qos_req_dma, PM_QOS_CPU_DMA_LATENCY, + pm_qos_add_request(&device->pwrctrl.pm_qos_req_dma, + PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE); /* Initalize the snapshot engine */ @@ -3823,17 +4047,16 @@ EXPORT_SYMBOL(kgsl_device_platform_probe); int kgsl_postmortem_dump(struct kgsl_device *device, int manual) { - bool saved_nap; struct kgsl_pwrctrl *pwr = &device->pwrctrl; BUG_ON(device == NULL); - kgsl_cffdump_hang(device->id); + kgsl_cffdump_hang(device); /* For a manual dump, make sure that the system is idle */ if (manual) { - kgsl_active_count_wait(device); + kgsl_active_count_wait(device, 0); if (device->state == KGSL_STATE_ACTIVE) kgsl_idle(device); @@ -3843,22 +4066,21 @@ int kgsl_postmortem_dump(struct kgsl_device *device, int manual) if (device->pm_dump_enable) { KGSL_LOG_DUMP(device, - "POWER: FLAGS = %08lX | ACTIVE POWERLEVEL = %08X", - pwr->power_flags, pwr->active_pwrlevel); + "POWER: START_STOP_SLEEP_WAKE = %d\n", + pwr->strtstp_sleepwake); + + KGSL_LOG_DUMP(device, + "POWER: FLAGS = %08lX | ACTIVE POWERLEVEL = %08X", + pwr->power_flags, pwr->active_pwrlevel); KGSL_LOG_DUMP(device, "POWER: INTERVAL TIMEOUT = %08X ", - pwr->interval_timeout); + pwr->interval_timeout); } /* Disable the idle timer so we don't get interrupted */ del_timer_sync(&device->idle_timer); - /* Turn off napping to make sure we have the clocks full - attention through the following process */ - saved_nap = device->pwrctrl.nap_allowed; - device->pwrctrl.nap_allowed = false; - /* Force on the clocks */ kgsl_pwrctrl_wake(device); @@ -3868,9 +4090,6 @@ int kgsl_postmortem_dump(struct kgsl_device *device, int manual) /*Call the device specific postmortem dump function*/ device->ftbl->postmortem_dump(device, manual); - /* Restore nap mode */ - device->pwrctrl.nap_allowed = saved_nap; - /* On a manual trigger, turn on the interrupts and put the clocks to sleep. They will recover themselves on the next event. For a hang, leave things as they @@ -3894,7 +4113,7 @@ void kgsl_device_platform_remove(struct kgsl_device *device) kgsl_pwrctrl_uninit_sysfs(device); - pm_qos_remove_request(&device->pm_qos_req_dma); + pm_qos_remove_request(&device->pwrctrl.pm_qos_req_dma); idr_destroy(&device->context_idr); diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h index 458400d412f..651d5974f52 100644 --- a/drivers/gpu/msm/kgsl.h +++ b/drivers/gpu/msm/kgsl.h @@ -46,7 +46,11 @@ #define KGSL_PAGETABLE_ENTRY_SIZE 4 /* Pagetable Virtual Address base */ +#ifndef CONFIG_MSM_KGSL_CFF_DUMP #define KGSL_PAGETABLE_BASE 0x10000000 +#else +#define KGSL_PAGETABLE_BASE SZ_4M +#endif /* Extra accounting entries needed in the pagetable */ #define KGSL_PT_EXTRA_ENTRIES 16 @@ -144,7 +148,8 @@ struct kgsl_memdesc_ops { int (*vmfault)(struct kgsl_memdesc *, struct vm_area_struct *, struct vm_fault *); void (*free)(struct kgsl_memdesc *memdesc); - int (*map_kernel_mem)(struct kgsl_memdesc *); + int (*map_kernel)(struct kgsl_memdesc *); + void (*unmap_kernel)(struct kgsl_memdesc *); }; /* Internal definitions for memdesc->priv */ @@ -153,14 +158,17 @@ struct kgsl_memdesc_ops { #define KGSL_MEMDESC_GLOBAL BIT(1) /* The memdesc is frozen during a snapshot */ #define KGSL_MEMDESC_FROZEN BIT(2) +/* The memdesc is mapped into a pagetable */ +#define KGSL_MEMDESC_MAPPED BIT(3) /* shared memory allocation */ struct kgsl_memdesc { struct kgsl_pagetable *pagetable; void *hostptr; /* kernel virtual address */ + unsigned int hostptr_count; /* number of threads using hostptr */ unsigned long useraddr; /* userspace address */ unsigned int gpuaddr; - unsigned int physaddr; + phys_addr_t physaddr; unsigned int size; unsigned int priv; /* Internal flags and settings */ struct scatterlist *sg; @@ -190,6 +198,8 @@ struct kgsl_mem_entry { /* back pointer to private structure under whose context this * allocation is made */ struct kgsl_process_private *priv; + /* Initialized to 0, set to 1 when entry is marked for freeing */ + int pending_free; }; #ifdef CONFIG_MSM_KGSL_MMU_PAGE_FAULT @@ -202,7 +212,7 @@ void kgsl_mem_entry_destroy(struct kref *kref); int kgsl_postmortem_dump(struct kgsl_device *device, int manual); struct kgsl_mem_entry *kgsl_get_mem_entry(struct kgsl_device *device, - unsigned int ptbase, unsigned int gpuaddr, unsigned int size); + phys_addr_t ptbase, unsigned int gpuaddr, unsigned int size); struct kgsl_mem_entry *kgsl_sharedmem_find_region( struct kgsl_process_private *private, unsigned int gpuaddr, @@ -222,11 +232,8 @@ void kgsl_cancel_events(struct kgsl_device *device, extern const struct dev_pm_ops kgsl_pm_ops; -struct early_suspend; int kgsl_suspend_driver(struct platform_device *pdev, pm_message_t state); int kgsl_resume_driver(struct platform_device *pdev); -void kgsl_early_suspend_driver(struct early_suspend *h); -void kgsl_late_resume_driver(struct early_suspend *h); void kgsl_trace_regwrite(struct kgsl_device *device, unsigned int offset, unsigned int value); @@ -236,6 +243,10 @@ void kgsl_trace_issueibcmds(struct kgsl_device *device, int id, unsigned int timestamp, unsigned int flags, int result, unsigned int type); +int kgsl_open_device(struct kgsl_device *device); + +int kgsl_close_device(struct kgsl_device *device); + #ifdef CONFIG_MSM_KGSL_DRM extern int kgsl_drm_init(struct platform_device *dev); extern void kgsl_drm_exit(void); @@ -270,13 +281,18 @@ static inline int kgsl_gpuaddr_in_memdesc(const struct kgsl_memdesc *memdesc, static inline void *kgsl_memdesc_map(struct kgsl_memdesc *memdesc) { - if (memdesc->hostptr == NULL && memdesc->ops && - memdesc->ops->map_kernel_mem) - memdesc->ops->map_kernel_mem(memdesc); + if (memdesc->ops && memdesc->ops->map_kernel) + memdesc->ops->map_kernel(memdesc); return memdesc->hostptr; } +static inline void kgsl_memdesc_unmap(struct kgsl_memdesc *memdesc) +{ + if (memdesc->ops && memdesc->ops->unmap_kernel) + memdesc->ops->unmap_kernel(memdesc); +} + static inline uint8_t *kgsl_gpuaddr_to_vaddr(struct kgsl_memdesc *memdesc, unsigned int gpuaddr) { @@ -309,10 +325,10 @@ static inline int timestamp_cmp(unsigned int a, unsigned int b) return ((a > b) && (a - b <= KGSL_TIMESTAMP_WINDOW)) ? 1 : -1; } -static inline void +static inline int kgsl_mem_entry_get(struct kgsl_mem_entry *entry) { - kref_get(&entry->refcount); + return kref_get_unless_zero(&entry->refcount); } static inline void @@ -321,4 +337,22 @@ kgsl_mem_entry_put(struct kgsl_mem_entry *entry) kref_put(&entry->refcount, kgsl_mem_entry_destroy); } +/* + * kgsl_addr_range_overlap() - Checks if 2 ranges overlap + * @gpuaddr1: Start of first address range + * @size1: Size of first address range + * @gpuaddr2: Start of second address range + * @size2: Size of second address range + * + * Function returns true if the 2 given address ranges overlap + * else false + */ +static inline bool kgsl_addr_range_overlap(unsigned int gpuaddr1, + unsigned int size1, + unsigned int gpuaddr2, unsigned int size2) +{ + return !(((gpuaddr1 + size1) < gpuaddr2) || + (gpuaddr1 > (gpuaddr2 + size2))); +} + #endif /* __KGSL_H */ diff --git a/drivers/gpu/msm/kgsl_cffdump.c b/drivers/gpu/msm/kgsl_cffdump.c index 44f6e52fa23..ca2d1ee1e6d 100644 --- a/drivers/gpu/msm/kgsl_cffdump.c +++ b/drivers/gpu/msm/kgsl_cffdump.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. +/* Copyright (c) 2010-2012,2013, The Linux Foundation. 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 and @@ -335,8 +335,6 @@ void kgsl_cffdump_init() return; } - kgsl_cff_dump_enable = 0; - spin_lock_init(&cffdump_lock); dir = debugfs_create_dir("cff", debugfs_dir); @@ -360,51 +358,54 @@ void kgsl_cffdump_destroy() void kgsl_cffdump_open(struct kgsl_device *device) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); - if (!kgsl_cff_dump_enable) + if (!device->cff_dump_enable) return; if (KGSL_MMU_TYPE_IOMMU == kgsl_mmu_get_mmutype()) { - kgsl_cffdump_memory_base(device->id, - kgsl_mmu_get_base_addr(&device->mmu), - kgsl_mmu_get_ptsize(&device->mmu) + - KGSL_IOMMU_GLOBAL_MEM_SIZE, adreno_dev->gmem_size); + kgsl_cffdump_memory_base(device, + KGSL_PAGETABLE_BASE, + KGSL_IOMMU_GLOBAL_MEM_BASE + + KGSL_IOMMU_GLOBAL_MEM_SIZE - + KGSL_PAGETABLE_BASE, + adreno_dev->gmem_size); } else { - kgsl_cffdump_memory_base(device->id, + kgsl_cffdump_memory_base(device, kgsl_mmu_get_base_addr(&device->mmu), kgsl_mmu_get_ptsize(&device->mmu), adreno_dev->gmem_size); } } -void kgsl_cffdump_memory_base(enum kgsl_deviceid device_id, unsigned int base, +void kgsl_cffdump_memory_base(struct kgsl_device *device, unsigned int base, unsigned int range, unsigned gmemsize) { - if (!kgsl_cff_dump_enable) + if (!device->cff_dump_enable) return; - cffdump_printline(device_id, CFF_OP_MEMORY_BASE, base, + cffdump_printline(device->id, CFF_OP_MEMORY_BASE, base, range, gmemsize, 0, 0); } -void kgsl_cffdump_hang(enum kgsl_deviceid device_id) +void kgsl_cffdump_hang(struct kgsl_device *device) { - if (!kgsl_cff_dump_enable) + if (!device->cff_dump_enable) return; - cffdump_printline(device_id, CFF_OP_HANG, 0, 0, 0, 0, 0); + cffdump_printline(device->id, CFF_OP_HANG, 0, 0, 0, 0, 0); } -void kgsl_cffdump_close(enum kgsl_deviceid device_id) +void kgsl_cffdump_close(struct kgsl_device *device) { - if (!kgsl_cff_dump_enable) + if (!device->cff_dump_enable) return; - cffdump_printline(device_id, CFF_OP_EOF, 0, 0, 0, 0, 0); + cffdump_printline(device->id, CFF_OP_EOF, 0, 0, 0, 0, 0); } -void kgsl_cffdump_user_event(unsigned int cff_opcode, unsigned int op1, +void kgsl_cffdump_user_event(struct kgsl_device *device, + unsigned int cff_opcode, unsigned int op1, unsigned int op2, unsigned int op3, unsigned int op4, unsigned int op5) { - if (!kgsl_cff_dump_enable) + if (!device->cff_dump_enable) return; cffdump_printline(-1, cff_opcode, op1, op2, op3, op4, op5); } @@ -415,7 +416,7 @@ void kgsl_cffdump_syncmem(struct kgsl_device *device, { const void *src; - if (!kgsl_cff_dump_enable) + if (!device->cff_dump_enable) return; BUG_ON(memdesc == NULL); @@ -424,9 +425,9 @@ void kgsl_cffdump_syncmem(struct kgsl_device *device, src = (uint *)kgsl_gpuaddr_to_vaddr(memdesc, gpuaddr); if (memdesc->hostptr == NULL) { - KGSL_CORE_ERR("no kernel mapping for " - "gpuaddr: 0x%08x, m->host: 0x%p, phys: 0x%08x\n", - gpuaddr, memdesc->hostptr, memdesc->physaddr); + KGSL_CORE_ERR( + "no kernel map for gpuaddr: 0x%08x, m->host: 0x%p, phys: %pa\n", + gpuaddr, memdesc->hostptr, &memdesc->physaddr); return; } @@ -450,11 +451,14 @@ void kgsl_cffdump_syncmem(struct kgsl_device *device, if (sizebytes > 0) cffdump_printline(-1, CFF_OP_WRITE_MEM, gpuaddr, *(uint *)src, 0, 0, 0); + /* Unmap memory since kgsl_gpuaddr_to_vaddr was called */ + kgsl_memdesc_unmap(memdesc); } -void kgsl_cffdump_setmem(uint addr, uint value, uint sizebytes) +void kgsl_cffdump_setmem(struct kgsl_device *device, + uint addr, uint value, uint sizebytes) { - if (!kgsl_cff_dump_enable) + if (!device || !device->cff_dump_enable) return; while (sizebytes > 3) { @@ -470,37 +474,37 @@ void kgsl_cffdump_setmem(uint addr, uint value, uint sizebytes) 0, 0, 0); } -void kgsl_cffdump_regwrite(enum kgsl_deviceid device_id, uint addr, +void kgsl_cffdump_regwrite(struct kgsl_device *device, uint addr, uint value) { - if (!kgsl_cff_dump_enable) + if (!device->cff_dump_enable) return; - cffdump_printline(device_id, CFF_OP_WRITE_REG, addr, value, + cffdump_printline(device->id, CFF_OP_WRITE_REG, addr, value, 0, 0, 0); } -void kgsl_cffdump_regpoll(enum kgsl_deviceid device_id, uint addr, +void kgsl_cffdump_regpoll(struct kgsl_device *device, uint addr, uint value, uint mask) { - if (!kgsl_cff_dump_enable) + if (!device->cff_dump_enable) return; - cffdump_printline(device_id, CFF_OP_POLL_REG, addr, value, + cffdump_printline(device->id, CFF_OP_POLL_REG, addr, value, mask, 0, 0); } -void kgsl_cffdump_slavewrite(uint addr, uint value) +void kgsl_cffdump_slavewrite(struct kgsl_device *device, uint addr, uint value) { - if (!kgsl_cff_dump_enable) + if (!device->cff_dump_enable) return; cffdump_printline(-1, CFF_OP_WRITE_REG, addr, value, 0, 0, 0); } -int kgsl_cffdump_waitirq(void) +int kgsl_cffdump_waitirq(struct kgsl_device *device) { - if (!kgsl_cff_dump_enable) + if (!device->cff_dump_enable) return 0; cffdump_printline(-1, CFF_OP_WAIT_IRQ, 0, 0, 0, 0, 0); @@ -601,3 +605,45 @@ static void destroy_channel(void) } } +int kgsl_cff_dump_enable_set(void *data, u64 val) +{ + int ret = 0; + struct kgsl_device *device = (struct kgsl_device *)data; + int i; + + mutex_lock(&kgsl_driver.devlock); + if (val) { + /* Check if CFF is on for some other device already */ + for (i = 0; i < KGSL_DEVICE_MAX; i++) { + if (kgsl_driver.devp[i]) { + struct kgsl_device *device_temp = + kgsl_driver.devp[i]; + if (device_temp->cff_dump_enable && + device != device_temp) { + KGSL_CORE_ERR( + "CFF is on for another device %d\n", + device_temp->id); + ret = -EINVAL; + goto done; + } + } + } + if (!device->cff_dump_enable) { + device->cff_dump_enable = 1; + } + } else if (device->cff_dump_enable && !val) { + device->cff_dump_enable = 0; + } +done: + mutex_unlock(&kgsl_driver.devlock); + return ret; +} +EXPORT_SYMBOL(kgsl_cff_dump_enable_set); + +int kgsl_cff_dump_enable_get(void *data, u64 *val) +{ + struct kgsl_device *device = (struct kgsl_device *)data; + *val = device->cff_dump_enable; + return 0; +} +EXPORT_SYMBOL(kgsl_cff_dump_enable_get); diff --git a/drivers/gpu/msm/kgsl_cffdump.h b/drivers/gpu/msm/kgsl_cffdump.h index 83695f81c66..2852e0f6114 100644 --- a/drivers/gpu/msm/kgsl_cffdump.h +++ b/drivers/gpu/msm/kgsl_cffdump.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. +/* Copyright (c) 2010-2011,2013, The Linux Foundation. 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 and @@ -14,11 +14,15 @@ #ifndef __KGSL_CFFDUMP_H #define __KGSL_CFFDUMP_H -#ifdef CONFIG_MSM_KGSL_CFF_DUMP - #include -#include "kgsl_device.h" +extern unsigned int kgsl_cff_dump_enable; + +static inline bool kgsl_cffdump_flags_no_memzero(void) { return true; } + +struct kgsl_device_private; + +#ifdef CONFIG_MSM_KGSL_CFF_DUMP void kgsl_cffdump_init(void); void kgsl_cffdump_destroy(void); @@ -27,42 +31,108 @@ void kgsl_cffdump_close(struct kgsl_device *device); void kgsl_cffdump_syncmem(struct kgsl_device *, struct kgsl_memdesc *memdesc, uint physaddr, uint sizebytes, bool clean_cache); -void kgsl_cffdump_setmem(uint addr, uint value, uint sizebytes); -void kgsl_cffdump_regwrite(enum kgsl_deviceid device_id, uint addr, +void kgsl_cffdump_setmem(struct kgsl_device *device, uint addr, + uint value, uint sizebytes); +void kgsl_cffdump_regwrite(struct kgsl_device *device, uint addr, uint value); -void kgsl_cffdump_regpoll(enum kgsl_deviceid device_id, uint addr, +void kgsl_cffdump_regpoll(struct kgsl_device *device, uint addr, uint value, uint mask); bool kgsl_cffdump_parse_ibs(struct kgsl_device_private *dev_priv, const struct kgsl_memdesc *memdesc, uint gpuaddr, int sizedwords, bool check_only); -void kgsl_cffdump_user_event(unsigned int cff_opcode, unsigned int op1, +void kgsl_cffdump_user_event(struct kgsl_device *device, + unsigned int cff_opcode, unsigned int op1, unsigned int op2, unsigned int op3, unsigned int op4, unsigned int op5); -static inline bool kgsl_cffdump_flags_no_memzero(void) { return true; } -void kgsl_cffdump_memory_base(enum kgsl_deviceid device_id, unsigned int base, +void kgsl_cffdump_memory_base(struct kgsl_device *device, unsigned int base, unsigned int range, unsigned int gmemsize); -void kgsl_cffdump_hang(enum kgsl_deviceid device_id); +void kgsl_cffdump_hang(struct kgsl_device *device); +int kgsl_cff_dump_enable_set(void *data, u64 val); +int kgsl_cff_dump_enable_get(void *data, u64 *val); #else -#define kgsl_cffdump_init() (void)0 -#define kgsl_cffdump_destroy() (void)0 -#define kgsl_cffdump_open(device) (void)0 -#define kgsl_cffdump_close(device_id) (void)0 -#define kgsl_cffdump_syncmem(dev_priv, memdesc, addr, sizebytes, clean_cache) \ - (void) 0 -#define kgsl_cffdump_setmem(addr, value, sizebytes) (void)0 -#define kgsl_cffdump_regwrite(device_id, addr, value) (void)0 -#define kgsl_cffdump_regpoll(device_id, addr, value, mask) (void)0 -#define kgsl_cffdump_parse_ibs(dev_priv, memdesc, gpuaddr, \ - sizedwords, check_only) true -#define kgsl_cffdump_flags_no_memzero() true -#define kgsl_cffdump_memory_base(base, range, gmemsize) (void)0 -#define kgsl_cffdump_hang(device_id) (void)0 -#define kgsl_cffdump_user_event(cff_opcode, op1, op2, op3, op4, op5) \ - (void)param +static inline void kgsl_cffdump_init(void) +{ + return; +} + +static inline void kgsl_cffdump_destroy(void) +{ + return; +} + +static inline void kgsl_cffdump_open(struct kgsl_device *device) +{ + return; +} + +static inline void kgsl_cffdump_close(struct kgsl_device *device) +{ + return; +} + +static inline void kgsl_cffdump_syncmem(struct kgsl_device *device, + struct kgsl_memdesc *memdesc, uint physaddr, uint sizebytes, + bool clean_cache) +{ + return; +} + +static inline void kgsl_cffdump_setmem(struct kgsl_device *device, uint addr, + uint value, uint sizebytes) +{ + return; +} + +static inline void kgsl_cffdump_regwrite(struct kgsl_device *device, uint addr, + uint value) +{ + return; +} + +static inline void kgsl_cffdump_regpoll(struct kgsl_device *device, uint addr, + uint value, uint mask) +{ + return; +} + +static inline bool kgsl_cffdump_parse_ibs(struct kgsl_device_private *dev_priv, + const struct kgsl_memdesc *memdesc, uint gpuaddr, int sizedwords, + bool check_only) +{ + return false; +} + +static inline void kgsl_cffdump_memory_base(struct kgsl_device *device, + unsigned int base, unsigned int range, unsigned int gmemsize) +{ + return; +} + +static inline void kgsl_cffdump_hang(struct kgsl_device *device) +{ + return; +} + +static inline void kgsl_cffdump_user_event(struct kgsl_device *device, + unsigned int cff_opcode, unsigned int op1, + unsigned int op2, unsigned int op3, + unsigned int op4, unsigned int op5) +{ + return; +} +static inline int kgsl_cff_dump_enable_set(void *data, u64 val) +{ + return -EINVAL; +} + +static inline int kgsl_cff_dump_enable_get(void *data, u64 *val) +{ + return -EINVAL; +} #endif /* CONFIG_MSM_KGSL_CFF_DUMP */ diff --git a/drivers/gpu/msm/kgsl_debugfs.c b/drivers/gpu/msm/kgsl_debugfs.c index 09c9dfe6256..d62a222d9f4 100644 --- a/drivers/gpu/msm/kgsl_debugfs.c +++ b/drivers/gpu/msm/kgsl_debugfs.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2002,2008-2012, The Linux Foundation. All rights reserved. +/* Copyright (c) 2002,2008-2013, The Linux Foundation. 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 and @@ -19,7 +19,6 @@ #include "kgsl_sharedmem.h" /*default log levels is error for everything*/ -#define KGSL_LOG_LEVEL_DEFAULT 3 #define KGSL_LOG_LEVEL_MAX 7 struct dentry *kgsl_debugfs_dir; @@ -179,12 +178,6 @@ void kgsl_device_debugfs_init(struct kgsl_device *device) if (!device->d_debugfs || IS_ERR(device->d_debugfs)) return; - device->cmd_log = KGSL_LOG_LEVEL_DEFAULT; - device->ctxt_log = KGSL_LOG_LEVEL_DEFAULT; - device->drv_log = KGSL_LOG_LEVEL_DEFAULT; - device->mem_log = KGSL_LOG_LEVEL_DEFAULT; - device->pwr_log = KGSL_LOG_LEVEL_DEFAULT; - debugfs_create_file("log_level_cmd", 0644, device->d_debugfs, device, &cmd_log_fops); debugfs_create_file("log_level_ctxt", 0644, device->d_debugfs, device, @@ -211,7 +204,6 @@ void kgsl_device_debugfs_init(struct kgsl_device *device) &pm_regs_enabled_fops); debugfs_create_file("ib_enabled", 0644, pm_d_debugfs, device, &pm_ib_enabled_fops); - device->pm_dump_enable = 0; debugfs_create_file("enable", 0644, pm_d_debugfs, device, &pm_enabled_fops); @@ -268,8 +260,8 @@ static void print_mem_entry(struct seq_file *s, struct kgsl_mem_entry *entry) kgsl_get_memory_usage(usage, sizeof(usage), m->flags); - seq_printf(s, "%08x %8d %5d %5s %10s %16s %5d\n", - m->gpuaddr, m->size, entry->id, flags, + seq_printf(s, "%08x %08lx %8d %5d %5s %10s %16s %5d\n", + m->gpuaddr, m->useraddr, m->size, entry->id, flags, memtype_str(entry->memtype), usage, m->sglen); } @@ -280,8 +272,9 @@ static int process_mem_print(struct seq_file *s, void *unused) struct kgsl_process_private *private = s->private; int next = 0; - seq_printf(s, "%8s %8s %5s %5s %10s %16s %5s\n", - "gpuaddr", "size", "id", "flags", "type", "usage", "sglen"); + seq_printf(s, "%8s %8s %8s %5s %5s %10s %16s %5s\n", + "gpuaddr", "useraddr", "size", "id", "flags", "type", + "usage", "sglen"); /* print all entries with a GPU address */ spin_lock(&private->mem_lock); @@ -291,20 +284,17 @@ static int process_mem_print(struct seq_file *s, void *unused) print_mem_entry(s, entry); } - spin_unlock(&private->mem_lock); /* now print all the unbound entries */ while (1) { - rcu_read_lock(); entry = idr_get_next(&private->mem_idr, &next); - rcu_read_unlock(); - if (entry == NULL) break; if (entry->memdesc.gpuaddr == 0) print_mem_entry(s, entry); next++; } + spin_unlock(&private->mem_lock); return 0; } @@ -321,16 +311,59 @@ static const struct file_operations process_mem_fops = { .release = single_release, }; -void + +/** + * kgsl_process_init_debugfs() - Initialize debugfs for a process + * @private: Pointer to process private structure created for the process + * + * @returns: 0 on success, error code otherwise + * + * kgsl_process_init_debugfs() is called at the time of creating the + * process struct when a process opens kgsl device for the first time. + * The function creates the debugfs files for the process. If debugfs is + * disabled in the kernel, we ignore that error and return as successful. + */ +int kgsl_process_init_debugfs(struct kgsl_process_private *private) { unsigned char name[16]; + int ret = 0; + struct dentry *dentry; snprintf(name, sizeof(name), "%d", private->pid); private->debug_root = debugfs_create_dir(name, proc_d_debugfs); - debugfs_create_file("mem", 0400, private->debug_root, private, + + if (!private->debug_root) + return -EINVAL; + + private->debug_root->d_inode->i_uid = proc_d_debugfs->d_inode->i_uid; + private->debug_root->d_inode->i_gid = proc_d_debugfs->d_inode->i_gid; + + /* + * debugfs_create_dir() and debugfs_create_file() both + * return -ENODEV if debugfs is disabled in the kernel. + * We make a distinction between these two functions + * failing and debugfs being disabled in the kernel. + * In the first case, we abort process private struct + * creation, in the second we continue without any changes. + * So if debugfs is disabled in kernel, return as + * success. + */ + dentry = debugfs_create_file("mem", 0400, private->debug_root, private, &process_mem_fops); + + if (IS_ERR(dentry)) { + ret = PTR_ERR(dentry); + + if (ret == -ENODEV) + ret = 0; + } else if (dentry) { + dentry->d_inode->i_uid = proc_d_debugfs->d_inode->i_uid; + dentry->d_inode->i_gid = proc_d_debugfs->d_inode->i_gid; + } + + return ret; } void kgsl_core_debugfs_init(void) diff --git a/drivers/gpu/msm/kgsl_debugfs.h b/drivers/gpu/msm/kgsl_debugfs.h index ae5601fb40a..b2f137cd4b0 100644 --- a/drivers/gpu/msm/kgsl_debugfs.h +++ b/drivers/gpu/msm/kgsl_debugfs.h @@ -21,7 +21,7 @@ struct kgsl_process_private; void kgsl_core_debugfs_init(void); void kgsl_core_debugfs_close(void); -void kgsl_device_debugfs_init(struct kgsl_device *device); +int kgsl_device_debugfs_init(struct kgsl_device *device); extern struct dentry *kgsl_debugfs_dir; static inline struct dentry *kgsl_get_debugfs_dir(void) diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h index fb3fade51e4..c9be418d034 100644 --- a/drivers/gpu/msm/kgsl_device.h +++ b/drivers/gpu/msm/kgsl_device.h @@ -16,7 +16,6 @@ #include #include #include -#include #include #include "kgsl.h" @@ -49,7 +48,6 @@ #define KGSL_STATE_SLEEP 0x00000008 #define KGSL_STATE_SUSPEND 0x00000010 #define KGSL_STATE_HUNG 0x00000020 -#define KGSL_STATE_DUMP_AND_FT 0x00000040 #define KGSL_STATE_SLUMBER 0x00000080 #define KGSL_GRAPHICS_MEMORY_LOW_WATERMARK 0x1000000 @@ -133,10 +131,9 @@ struct kgsl_functable { enum kgsl_property_type type, void *value, unsigned int sizebytes); int (*postmortem_dump) (struct kgsl_device *device, int manual); - int (*next_event)(struct kgsl_device *device, - struct kgsl_event *event); void (*drawctxt_sched)(struct kgsl_device *device, struct kgsl_context *context); + void (*resume)(struct kgsl_device *device); }; /* MH register values */ @@ -169,6 +166,7 @@ struct kgsl_event { * @priv: Internal flags * @fault_policy: Internal policy describing how to handle this command in case * of a fault + * @fault_recovery: recovery actions actually tried for this batch * @ibcount: Number of IBs in the command list * @ibdesc: Pointer to the list of IBs * @expires: Point in time when the cmdbatch is considered to be hung @@ -176,6 +174,7 @@ struct kgsl_event { * context should be invalidated * @refcount: kref structure to maintain the reference count * @synclist: List of context/timestamp tuples to wait for before issuing + * @priority: Priority of the cmdbatch (inherited from the context) * * This struture defines an atomic batch of command buffers issued from * userspace. @@ -186,20 +185,30 @@ struct kgsl_cmdbatch { spinlock_t lock; uint32_t timestamp; uint32_t flags; - uint32_t priv; - uint32_t fault_policy; + unsigned long priv; + unsigned long fault_policy; + unsigned long fault_recovery; uint32_t ibcount; struct kgsl_ibdesc *ibdesc; unsigned long expires; int invalid; struct kref refcount; struct list_head synclist; + int priority; }; -/* Internal cmdbatch flags */ +/** + * enum kgsl_cmdbatch_priv - Internal cmdbatch flags + * @CMDBATCH_FLAG_SKIP - skip the entire command batch + * @CMDBATCH_FLAG_FORCE_PREAMBLE - Force the preamble on for the cmdbatch + * @CMDBATCH_FLAG_WFI - Force wait-for-idle for the submission + */ -#define CMDBATCH_FLAG_SKIP BIT(0) -#define CMDBATCH_FLAG_FORCE_PREAMBLE BIT(1) +enum kgsl_cmdbatch_priv { + CMDBATCH_FLAG_SKIP = 0, + CMDBATCH_FLAG_FORCE_PREAMBLE, + CMDBATCH_FLAG_WFI, +}; struct kgsl_device { struct device *dev; @@ -208,11 +217,27 @@ struct kgsl_device { unsigned int ver_minor; uint32_t flags; enum kgsl_deviceid id; + + /* Starting physical address for GPU registers */ unsigned long reg_phys; + + /* Starting Kernel virtual address for GPU registers */ void *reg_virt; + + /* Total memory size for all GPU registers */ unsigned int reg_len; + + /* Kernel virtual address for GPU shader memory */ + void *shader_mem_virt; + + /* Starting physical address for GPU shader memory */ + unsigned long shader_mem_phys; + + /* GPU shader memory size */ + unsigned int shader_mem_len; struct kgsl_memdesc memstore; const char *iomemname; + const char *shadermemname; struct kgsl_mh mh; struct kgsl_mmu mmu; @@ -228,20 +253,20 @@ struct kgsl_device { uint32_t requested_state; atomic_t active_cnt; - struct completion suspend_gate; wait_queue_head_t wait_queue; + wait_queue_head_t active_cnt_wq; struct workqueue_struct *work_queue; struct device *parentdev; struct dentry *d_debugfs; struct idr context_idr; - struct early_suspend display_off; rwlock_t context_lock; void *snapshot; /* Pointer to the snapshot memory region */ int snapshot_maxsize; /* Max size of the snapshot region */ int snapshot_size; /* Current size of the snapshot region */ u32 snapshot_timestamp; /* Timestamp of the last valid snapshot */ + u32 snapshot_faultcount; /* Total number of faults since boot */ int snapshot_frozen; /* 1 if the snapshot output is frozen until it gets read by the user. This avoids losing the output on multiple hangs */ @@ -252,6 +277,14 @@ struct kgsl_device { * dumped */ struct list_head snapshot_obj_list; + /* List of IB's to be dumped */ + struct list_head snapshot_cp_list; + /* Work item that saves snapshot's frozen object data */ + struct work_struct snapshot_obj_ws; + /* snapshot memory holding the hanging IB's objects in snapshot */ + void *snapshot_cur_ib_objs; + /* Size of snapshot_cur_ib_objs */ + int snapshot_cur_ib_objs_size; /* Logging levels */ int cmd_log; @@ -262,7 +295,6 @@ struct kgsl_device { int pm_dump_enable; struct kgsl_pwrscale pwrscale; struct kobject pwrscale_kobj; - struct pm_qos_request pm_qos_req_dma; struct work_struct ts_expired_ws; struct list_head events; struct list_head events_pending_list; @@ -274,6 +306,7 @@ struct kgsl_device { int pm_ib_enabled; int reset_counter; /* Track how many GPU core resets have occured */ + int cff_dump_enable; }; void kgsl_process_events(struct work_struct *work); @@ -281,15 +314,18 @@ void kgsl_check_fences(struct work_struct *work); #define KGSL_DEVICE_COMMON_INIT(_dev) \ .hwaccess_gate = COMPLETION_INITIALIZER((_dev).hwaccess_gate),\ - .suspend_gate = COMPLETION_INITIALIZER((_dev).suspend_gate),\ .idle_check_ws = __WORK_INITIALIZER((_dev).idle_check_ws,\ kgsl_idle_check),\ .ts_expired_ws = __WORK_INITIALIZER((_dev).ts_expired_ws,\ kgsl_process_events),\ + .snapshot_obj_ws = \ + __WORK_INITIALIZER((_dev).snapshot_obj_ws,\ + kgsl_snapshot_save_frozen_objs),\ .context_idr = IDR_INIT((_dev).context_idr),\ .events = LIST_HEAD_INIT((_dev).events),\ .events_pending_list = LIST_HEAD_INIT((_dev).events_pending_list), \ .wait_queue = __WAIT_QUEUE_HEAD_INITIALIZER((_dev).wait_queue),\ + .active_cnt_wq = __WAIT_QUEUE_HEAD_INITIALIZER((_dev).active_cnt_wq),\ .mutex = __MUTEX_INITIALIZER((_dev).mutex),\ .state = KGSL_STATE_INIT,\ .ver_major = DRIVER_VERSION_MAJOR,\ @@ -302,6 +338,7 @@ void kgsl_check_fences(struct work_struct *work); /* the context has caused a pagefault */ #define KGSL_CONTEXT_PAGEFAULT 1 +struct kgsl_process_private; /** * struct kgsl_context - Master structure for a KGSL context object * @refcount: kref object for reference counting the context @@ -325,9 +362,10 @@ struct kgsl_context { struct kref refcount; uint32_t id; pid_t pid; + struct kgsl_device_private *dev_priv; + struct kgsl_process_private *proc_priv; unsigned long priv; struct kgsl_device *device; - struct kgsl_pagetable *pagetable; unsigned int reset_status; bool wait_on_invalid_ts; struct sync_timeline *timeline; @@ -476,6 +514,7 @@ const char *kgsl_pwrstate_to_str(unsigned int state); int kgsl_device_snapshot_init(struct kgsl_device *device); int kgsl_device_snapshot(struct kgsl_device *device, int hang); void kgsl_device_snapshot_close(struct kgsl_device *device); +void kgsl_snapshot_save_frozen_objs(struct work_struct *work); static inline struct kgsl_device_platform_data * kgsl_device_get_drvdata(struct kgsl_device *dev) @@ -490,6 +529,7 @@ void kgsl_context_destroy(struct kref *kref); int kgsl_context_init(struct kgsl_device_private *, struct kgsl_context *context); +int kgsl_context_detach(struct kgsl_context *context); /** * kgsl_context_put() - Release context reference count @@ -511,7 +551,7 @@ kgsl_context_put(struct kgsl_context *context) * * Check if a context has been destroyed by userspace and is only waiting * for reference counts to go away. This check is used to weed out - * contexts that shouldn't use the gpu, so NULL is considered detached. + * contexts that shouldn't use the gpu so NULL is considered detached. */ static inline bool kgsl_context_detached(struct kgsl_context *context) { @@ -534,6 +574,7 @@ static inline bool kgsl_context_detached(struct kgsl_context *context) static inline struct kgsl_context *kgsl_context_get(struct kgsl_device *device, uint32_t id) { + int result = 0; struct kgsl_context *context = NULL; read_lock(&device->context_lock); @@ -544,10 +585,12 @@ static inline struct kgsl_context *kgsl_context_get(struct kgsl_device *device, if (kgsl_context_detached(context)) context = NULL; else - kref_get(&context->refcount); + result = kref_get_unless_zero(&context->refcount); read_unlock(&device->context_lock); + if (!result) + return NULL; return context; } @@ -559,10 +602,22 @@ static inline struct kgsl_context *kgsl_context_get(struct kgsl_device *device, * lightweight way to just increase the refcount on a known context rather than * walking through kgsl_context_get and searching the iterator */ -static inline void _kgsl_context_get(struct kgsl_context *context) +static inline int _kgsl_context_get(struct kgsl_context *context) { - if (context) - kref_get(&context->refcount); + int ret = 0; + + if (context) { + ret = kref_get_unless_zero(&context->refcount); + /* + * We shouldn't realistically fail kref_get_unless_zero unless + * we did something really dumb so make the failure both public + * and painful + */ + + WARN_ON(!ret); + } + + return ret; } /** @@ -645,4 +700,34 @@ static inline int kgsl_cmdbatch_sync_pending(struct kgsl_cmdbatch *cmdbatch) return list_empty(&cmdbatch->synclist) ? 0 : 1; } +#if defined(CONFIG_GPU_TRACEPOINTS) + +#include + +static inline void kgsl_trace_gpu_job_enqueue(unsigned int ctxt_id, + unsigned int timestamp, const char *type) +{ + trace_gpu_job_enqueue(ctxt_id, timestamp, type); +} + +static inline void kgsl_trace_gpu_sched_switch(const char *name, + u64 time, u32 ctxt_id, s32 prio, u32 timestamp) +{ + trace_gpu_sched_switch(name, time, ctxt_id, prio, timestamp); +} + +#else + +static inline void kgsl_trace_gpu_job_enqueue(unsigned int ctxt_id, + unsigned int timestamp, const char *type) +{ +} + +static inline void kgsl_trace_gpu_sched_switch(const char *name, + u64 time, u32 ctxt_id, s32 prio, u32 timestamp) +{ +} + +#endif + #endif /* __KGSL_DEVICE_H */ diff --git a/drivers/gpu/msm/kgsl_drm.c b/drivers/gpu/msm/kgsl_drm.c index 2a5a5fac296..6402bf4cb31 100644 --- a/drivers/gpu/msm/kgsl_drm.c +++ b/drivers/gpu/msm/kgsl_drm.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2009-2012, The Linux Foundation. All rights reserved. +/* Copyright (c) 2009-2013, The Linux Foundation. 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 and @@ -16,7 +16,9 @@ */ #include "drmP.h" #include "drm.h" -#include + +#include +#include #include "kgsl.h" #include "kgsl_device.h" @@ -27,7 +29,7 @@ #define DRIVER_AUTHOR "Qualcomm" #define DRIVER_NAME "kgsl" #define DRIVER_DESC "KGSL DRM" -#define DRIVER_DATE "20100127" +#define DRIVER_DATE "20121107" #define DRIVER_MAJOR 2 #define DRIVER_MINOR 1 @@ -106,6 +108,7 @@ struct drm_kgsl_gem_object { uint32_t type; struct kgsl_memdesc memdesc; struct kgsl_pagetable *pagetable; + struct ion_handle *ion_handle; uint64_t mmap_offset; int bufcount; int flags; @@ -117,6 +120,8 @@ struct drm_kgsl_gem_object { uint32_t gpuaddr; } bufs[DRM_KGSL_GEM_MAX_BUFFERS]; + struct genlock_handle *glock_handle[DRM_KGSL_GEM_MAX_BUFFERS]; + int bound; int lockpid; /* Put these here to avoid allocing all the time */ @@ -129,86 +134,18 @@ struct drm_kgsl_gem_object { struct list_head wait_list; }; +static struct ion_client *kgsl_drm_ion_client; + static int kgsl_drm_inited = DRM_KGSL_NOT_INITED; /* This is a global list of all the memory currently mapped in the MMU */ static struct list_head kgsl_mem_list; -static void kgsl_gem_mem_flush(struct kgsl_memdesc *memdesc, int type, int op) -{ - int cacheop = 0; - - switch (op) { - case DRM_KGSL_GEM_CACHE_OP_TO_DEV: - if (type & (DRM_KGSL_GEM_CACHE_WBACK | - DRM_KGSL_GEM_CACHE_WBACKWA)) - cacheop = KGSL_CACHE_OP_CLEAN; - - break; - - case DRM_KGSL_GEM_CACHE_OP_FROM_DEV: - if (type & (DRM_KGSL_GEM_CACHE_WBACK | - DRM_KGSL_GEM_CACHE_WBACKWA | - DRM_KGSL_GEM_CACHE_WTHROUGH)) - cacheop = KGSL_CACHE_OP_INV; - } - - kgsl_cache_range_op(memdesc, cacheop); -} - -/* TODO: - * Add vsync wait */ - -static int kgsl_drm_load(struct drm_device *dev, unsigned long flags) -{ - return 0; -} - -static int kgsl_drm_unload(struct drm_device *dev) -{ - return 0; -} - struct kgsl_drm_device_priv { struct kgsl_device *device[KGSL_DEVICE_MAX]; struct kgsl_device_private *devpriv[KGSL_DEVICE_MAX]; }; -void kgsl_drm_preclose(struct drm_device *dev, struct drm_file *file_priv) -{ -} - -static int kgsl_drm_suspend(struct drm_device *dev, pm_message_t state) -{ - return 0; -} - -static int kgsl_drm_resume(struct drm_device *dev) -{ - return 0; -} - -static void -kgsl_gem_free_mmap_offset(struct drm_gem_object *obj) -{ - struct drm_device *dev = obj->dev; - struct drm_gem_mm *mm = dev->mm_private; - struct drm_kgsl_gem_object *priv = obj->driver_private; - struct drm_map_list *list; - - list = &obj->map_list; - drm_ht_remove_item(&mm->offset_hash, &list->hash); - if (list->file_offset_node) { - drm_mm_put_block(list->file_offset_node); - list->file_offset_node = NULL; - } - - kfree(list->map); - list->map = NULL; - - priv->mmap_offset = 0; -} - static int kgsl_gem_memory_allocated(struct drm_gem_object *obj) { @@ -220,6 +157,9 @@ static int kgsl_gem_alloc_memory(struct drm_gem_object *obj) { struct drm_kgsl_gem_object *priv = obj->driver_private; + struct kgsl_mmu *mmu; + struct sg_table *sg_table; + struct scatterlist *s; int index; int result = 0; @@ -229,7 +169,17 @@ kgsl_gem_alloc_memory(struct drm_gem_object *obj) return 0; if (priv->pagetable == NULL) { - priv->pagetable = kgsl_mmu_getpagetable(KGSL_MMU_GLOBAL_PT); + /* Hard coded to use A2X device for MSM7X27 and MSM8625 + * Others to use A3X device + */ +#if defined(CONFIG_ARCH_MSM7X27) || defined(CONFIG_ARCH_MSM8625) + mmu = &kgsl_get_device(KGSL_DEVICE_2D0)->mmu; +#else + mmu = &kgsl_get_device(KGSL_DEVICE_3D0)->mmu; +#endif + + priv->pagetable = kgsl_mmu_getpagetable(mmu, + KGSL_MMU_GLOBAL_PT); if (priv->pagetable == NULL) { DRM_ERROR("Unable to get the GPU MMU pagetable\n"); @@ -237,21 +187,53 @@ kgsl_gem_alloc_memory(struct drm_gem_object *obj) } } - /* Set the flags for the memdesc (probably 0, unless it is cached) */ - priv->memdesc.priv = 0; - if (TYPE_IS_PMEM(priv->type)) { if (priv->type == DRM_KGSL_GEM_TYPE_EBI || priv->type & DRM_KGSL_GEM_PMEM_EBI) { - result = kgsl_sharedmem_ebimem_user( - &priv->memdesc, - priv->pagetable, - obj->size * priv->bufcount); - if (result) { - DRM_ERROR( - "Unable to allocate PMEM memory\n"); - return result; - } + priv->ion_handle = ion_alloc(kgsl_drm_ion_client, + obj->size * priv->bufcount, PAGE_SIZE, + ION_HEAP(ION_SF_HEAP_ID), 0); + if (IS_ERR_OR_NULL(priv->ion_handle)) { + DRM_ERROR( + "Unable to allocate ION Phys memory handle\n"); + return -ENOMEM; + } + + priv->memdesc.pagetable = priv->pagetable; + + result = ion_phys(kgsl_drm_ion_client, + priv->ion_handle, (ion_phys_addr_t *) + &priv->memdesc.physaddr, &priv->memdesc.size); + if (result) { + DRM_ERROR( + "Unable to get ION Physical memory address\n"); + ion_free(kgsl_drm_ion_client, + priv->ion_handle); + priv->ion_handle = NULL; + return result; + } + + result = memdesc_sg_phys(&priv->memdesc, + priv->memdesc.physaddr, priv->memdesc.size); + if (result) { + DRM_ERROR( + "Unable to get sg list\n"); + ion_free(kgsl_drm_ion_client, + priv->ion_handle); + priv->ion_handle = NULL; + return result; + } + + result = kgsl_mmu_map(priv->pagetable, &priv->memdesc, + GSL_PT_PAGE_RV | GSL_PT_PAGE_WV); + if (result) { + DRM_ERROR( + "kgsl_mmu_map failed. result = %d\n", result); + ion_free(kgsl_drm_ion_client, + priv->ion_handle); + priv->ion_handle = NULL; + return result; + } } else return -EINVAL; @@ -262,15 +244,43 @@ kgsl_gem_alloc_memory(struct drm_gem_object *obj) priv->type & DRM_KGSL_GEM_CACHE_MASK) list_add(&priv->list, &kgsl_mem_list); - result = kgsl_sharedmem_page_alloc_user(&priv->memdesc, - priv->pagetable, - obj->size * priv->bufcount); + priv->memdesc.pagetable = priv->pagetable; - if (result != 0) { - DRM_ERROR( - "Unable to allocate Vmalloc user memory\n"); - return result; + priv->ion_handle = ion_alloc(kgsl_drm_ion_client, + obj->size * priv->bufcount, PAGE_SIZE, + ION_HEAP(ION_IOMMU_HEAP_ID), 0); + if (IS_ERR_OR_NULL(priv->ion_handle)) { + DRM_ERROR( + "Unable to allocate ION IOMMU memory handle\n"); + return -ENOMEM; } + + sg_table = ion_sg_table(kgsl_drm_ion_client, + priv->ion_handle); + if (IS_ERR_OR_NULL(priv->ion_handle)) { + DRM_ERROR( + "Unable to get ION sg table\n"); + goto memerr; + } + + priv->memdesc.sg = sg_table->sgl; + + /* Calculate the size of the memdesc from the sglist */ + + priv->memdesc.sglen = 0; + + for (s = priv->memdesc.sg; s != NULL; s = sg_next(s)) { + priv->memdesc.size += s->length; + priv->memdesc.sglen++; + } + + result = kgsl_mmu_map(priv->pagetable, &priv->memdesc); + if (result) { + DRM_ERROR( + "kgsl_mmu_map failed. result = %d\n", result); + goto memerr; + } + } else return -EINVAL; @@ -282,21 +292,44 @@ kgsl_gem_alloc_memory(struct drm_gem_object *obj) } priv->flags |= DRM_KGSL_GEM_FLAG_MAPPED; + return 0; + +memerr: + ion_free(kgsl_drm_ion_client, + priv->ion_handle); + priv->ion_handle = NULL; + return -ENOMEM; + } static void kgsl_gem_free_memory(struct drm_gem_object *obj) { struct drm_kgsl_gem_object *priv = obj->driver_private; + int index; if (!kgsl_gem_memory_allocated(obj) || TYPE_IS_FD(priv->type)) return; - kgsl_gem_mem_flush(&priv->memdesc, priv->type, - DRM_KGSL_GEM_CACHE_OP_FROM_DEV); + if (priv->memdesc.gpuaddr) + kgsl_mmu_unmap(priv->memdesc.pagetable, &priv->memdesc); - kgsl_sharedmem_free(&priv->memdesc); + /* ION will take care of freeing the sg table. */ + priv->memdesc.sg = NULL; + priv->memdesc.sglen = 0; + + if (priv->ion_handle) + ion_free(kgsl_drm_ion_client, priv->ion_handle); + + priv->ion_handle = NULL; + + memset(&priv->memdesc, 0, sizeof(priv->memdesc)); + + for (index = 0; index < priv->bufcount; index++) { + if (priv->glock_handle[index]) + genlock_put_handle(priv->glock_handle[index]); + } kgsl_mmu_putpagetable(priv->pagetable); priv->pagetable = NULL; @@ -329,66 +362,10 @@ void kgsl_gem_free_object(struct drm_gem_object *obj) { kgsl_gem_free_memory(obj); - kgsl_gem_free_mmap_offset(obj); drm_gem_object_release(obj); kfree(obj->driver_private); } -static int -kgsl_gem_create_mmap_offset(struct drm_gem_object *obj) -{ - struct drm_device *dev = obj->dev; - struct drm_gem_mm *mm = dev->mm_private; - struct drm_kgsl_gem_object *priv = obj->driver_private; - struct drm_map_list *list; - int msize; - - list = &obj->map_list; - list->map = kzalloc(sizeof(struct drm_map_list), GFP_KERNEL); - if (list->map == NULL) { - DRM_ERROR("Unable to allocate drm_map_list\n"); - return -ENOMEM; - } - - msize = obj->size * priv->bufcount; - - list->map->type = _DRM_GEM; - list->map->size = msize; - list->map->handle = obj; - - /* Allocate a mmap offset */ - list->file_offset_node = drm_mm_search_free(&mm->offset_manager, - msize / PAGE_SIZE, - 0, 0); - - if (!list->file_offset_node) { - DRM_ERROR("Failed to allocate offset for %d\n", obj->name); - kfree(list->map); - return -ENOMEM; - } - - list->file_offset_node = drm_mm_get_block(list->file_offset_node, - msize / PAGE_SIZE, 0); - - if (!list->file_offset_node) { - DRM_ERROR("Unable to create the file_offset_node\n"); - kfree(list->map); - return -ENOMEM; - } - - list->hash.key = list->file_offset_node->start; - if (drm_ht_insert_item(&mm->offset_hash, &list->hash)) { - DRM_ERROR("Failed to add to map hash\n"); - drm_mm_put_block(list->file_offset_node); - kfree(list->map); - return -ENOMEM; - } - - priv->mmap_offset = ((uint64_t) list->hash.key) << PAGE_SHIFT; - - return 0; -} - int kgsl_gem_obj_addr(int drm_fd, int handle, unsigned long *start, unsigned long *len) @@ -435,9 +412,6 @@ kgsl_gem_obj_addr(int drm_fd, int handle, unsigned long *start, priv->bufs[priv->active].offset; *len = priv->memdesc.size; - - kgsl_gem_mem_flush(&priv->memdesc, - priv->type, DRM_KGSL_GEM_CACHE_OP_TO_DEV); } else { *start = 0; *len = 0; @@ -468,10 +442,7 @@ kgsl_gem_init_obj(struct drm_device *dev, priv->active = 0; priv->bound = 0; - /* To preserve backwards compatability, the default memory source - is EBI */ - - priv->type = DRM_KGSL_GEM_TYPE_PMEM | DRM_KGSL_GEM_PMEM_EBI; + priv->type = DRM_KGSL_GEM_TYPE_KMEM; ret = drm_gem_handle_create(file_priv, obj, handle); @@ -513,8 +484,11 @@ kgsl_gem_create_ioctl(struct drm_device *dev, void *data, } ret = kgsl_gem_init_obj(dev, file_priv, obj, &handle); - if (ret) + if (ret) { + drm_gem_object_release(obj); + DRM_ERROR("Unable to initialize GEM object ret = %d\n", ret); return ret; + } create->handle = handle; return 0; @@ -586,6 +560,155 @@ kgsl_gem_create_fd_ioctl(struct drm_device *dev, void *data, return ret; } +int +kgsl_gem_create_from_ion_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_kgsl_gem_create_from_ion *args = data; + struct drm_gem_object *obj; + struct ion_handle *ion_handle; + struct drm_kgsl_gem_object *priv; + struct sg_table *sg_table; + struct scatterlist *s; + int ret, handle; + unsigned long size; + struct kgsl_mmu *mmu; + + ion_handle = ion_import_dma_buf(kgsl_drm_ion_client, args->ion_fd); + if (IS_ERR_OR_NULL(ion_handle)) { + DRM_ERROR("Unable to import dmabuf. Error number = %d\n", + (int)PTR_ERR(ion_handle)); + return -EINVAL; + } + + ion_handle_get_size(kgsl_drm_ion_client, ion_handle, &size); + + if (size == 0) { + ion_free(kgsl_drm_ion_client, ion_handle); + DRM_ERROR( + "cannot create GEM object from zero size ION buffer\n"); + return -EINVAL; + } + + obj = drm_gem_object_alloc(dev, size); + + if (obj == NULL) { + ion_free(kgsl_drm_ion_client, ion_handle); + DRM_ERROR("Unable to allocate the GEM object\n"); + return -ENOMEM; + } + + ret = kgsl_gem_init_obj(dev, file_priv, obj, &handle); + if (ret) { + ion_free(kgsl_drm_ion_client, ion_handle); + drm_gem_object_release(obj); + DRM_ERROR("Unable to initialize GEM object ret = %d\n", ret); + return ret; + } + + priv = obj->driver_private; + priv->ion_handle = ion_handle; + + priv->type = DRM_KGSL_GEM_TYPE_KMEM; + list_add(&priv->list, &kgsl_mem_list); + +#if defined(CONFIG_ARCH_MSM7X27) || defined(CONFIG_ARCH_MSM8625) + mmu = &kgsl_get_device(KGSL_DEVICE_2D0)->mmu; +#else + mmu = &kgsl_get_device(KGSL_DEVICE_3D0)->mmu; +#endif + + priv->pagetable = kgsl_mmu_getpagetable(mmu, KGSL_MMU_GLOBAL_PT); + + priv->memdesc.pagetable = priv->pagetable; + + sg_table = ion_sg_table(kgsl_drm_ion_client, + priv->ion_handle); + if (IS_ERR_OR_NULL(priv->ion_handle)) { + DRM_ERROR("Unable to get ION sg table\n"); + ion_free(kgsl_drm_ion_client, + priv->ion_handle); + priv->ion_handle = NULL; + kgsl_mmu_putpagetable(priv->pagetable); + drm_gem_object_release(obj); + kfree(priv); + return -ENOMEM; + } + + priv->memdesc.sg = sg_table->sgl; + + /* Calculate the size of the memdesc from the sglist */ + + priv->memdesc.sglen = 0; + + for (s = priv->memdesc.sg; s != NULL; s = sg_next(s)) { + priv->memdesc.size += s->length; + priv->memdesc.sglen++; + } + + ret = kgsl_mmu_map(priv->pagetable, &priv->memdesc); + if (ret) { + DRM_ERROR("kgsl_mmu_map failed. ret = %d\n", ret); + ion_free(kgsl_drm_ion_client, + priv->ion_handle); + priv->ion_handle = NULL; + kgsl_mmu_putpagetable(priv->pagetable); + drm_gem_object_release(obj); + kfree(priv); + return -ENOMEM; + } + + priv->bufs[0].offset = 0; + priv->bufs[0].gpuaddr = priv->memdesc.gpuaddr; + priv->flags |= DRM_KGSL_GEM_FLAG_MAPPED; + + args->handle = handle; + return 0; +} + +int +kgsl_gem_get_ion_fd_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_kgsl_gem_get_ion_fd *args = data; + struct drm_gem_object *obj; + struct drm_kgsl_gem_object *priv; + int ret = 0; + + obj = drm_gem_object_lookup(dev, file_priv, args->handle); + + if (obj == NULL) { + DRM_ERROR("Invalid GEM handle %x\n", args->handle); + return -EBADF; + } + + mutex_lock(&dev->struct_mutex); + priv = obj->driver_private; + + if (TYPE_IS_FD(priv->type)) + ret = -EINVAL; + else if (TYPE_IS_PMEM(priv->type) || TYPE_IS_MEM(priv->type)) { + if (priv->ion_handle) { + args->ion_fd = ion_share_dma_buf_fd( + kgsl_drm_ion_client, priv->ion_handle); + if (args->ion_fd < 0) { + DRM_ERROR( + "Could not share ion buffer. Error = %d\n", + args->ion_fd); + ret = -EINVAL; + } + } else { + DRM_ERROR("GEM object has no ion memory allocated.\n"); + ret = -EINVAL; + } + } + + drm_gem_object_unreference(obj); + mutex_unlock(&dev->struct_mutex); + + return ret; +} + int kgsl_gem_setmemtype_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) @@ -685,13 +808,9 @@ kgsl_gem_alloc_ioctl(struct drm_device *dev, void *data, if (ret) { DRM_ERROR("Unable to allocate object memory\n"); - } else if (!priv->mmap_offset) { - ret = kgsl_gem_create_mmap_offset(obj); - if (ret) - DRM_ERROR("Unable to create a mmap offset\n"); } - args->offset = priv->mmap_offset; + args->offset = 0; drm_gem_object_unreference(obj); mutex_unlock(&dev->struct_mutex); @@ -703,33 +822,7 @@ int kgsl_gem_mmap_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { - struct drm_kgsl_gem_mmap *args = data; - struct drm_gem_object *obj; - unsigned long addr; - - obj = drm_gem_object_lookup(dev, file_priv, args->handle); - - if (obj == NULL) { - DRM_ERROR("Invalid GEM handle %x\n", args->handle); - return -EBADF; - } - - down_write(¤t->mm->mmap_sem); - - addr = do_mmap(obj->filp, 0, args->size, - PROT_READ | PROT_WRITE, MAP_SHARED, - args->offset); - - up_write(¤t->mm->mmap_sem); - - mutex_lock(&dev->struct_mutex); - drm_gem_object_unreference(obj); - mutex_unlock(&dev->struct_mutex); - - if (IS_ERR((void *) addr)) - return addr; - - args->hostptr = (uint32_t) addr; + /* Ion is used for mmap at this time */ return 0; } @@ -762,18 +855,6 @@ kgsl_gem_prep_ioctl(struct drm_device *dev, void *data, return ret; } - if (priv->mmap_offset == 0) { - ret = kgsl_gem_create_mmap_offset(obj); - if (ret) { - drm_gem_object_unreference(obj); - mutex_unlock(&dev->struct_mutex); - return ret; - } - } - - args->offset = priv->mmap_offset; - args->phys = priv->memdesc.physaddr; - drm_gem_object_unreference(obj); mutex_unlock(&dev->struct_mutex); @@ -822,6 +903,68 @@ kgsl_gem_get_bufinfo_ioctl(struct drm_device *dev, void *data, return ret; } +/* Get the genlock handles base off the GEM handle + */ + +int +kgsl_gem_get_glock_handles_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_kgsl_gem_glockinfo *args = data; + struct drm_gem_object *obj; + struct drm_kgsl_gem_object *priv; + int index; + + obj = drm_gem_object_lookup(dev, file_priv, args->handle); + + if (obj == NULL) { + DRM_ERROR("Invalid GEM handle %x\n", args->handle); + return -EBADF; + } + + mutex_lock(&dev->struct_mutex); + priv = obj->driver_private; + + for (index = 0; index < priv->bufcount; index++) { + args->glockhandle[index] = genlock_get_fd_handle( + priv->glock_handle[index]); + } + + drm_gem_object_unreference(obj); + mutex_unlock(&dev->struct_mutex); + return 0; +} + +int +kgsl_gem_set_glock_handles_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_kgsl_gem_glockinfo *args = data; + struct drm_gem_object *obj; + struct drm_kgsl_gem_object *priv; + int index; + + obj = drm_gem_object_lookup(dev, file_priv, args->handle); + + if (obj == NULL) { + DRM_ERROR("Invalid GEM handle %x\n", args->handle); + return -EBADF; + } + + mutex_lock(&dev->struct_mutex); + priv = obj->driver_private; + + for (index = 0; index < priv->bufcount; index++) { + priv->glock_handle[index] = genlock_get_handle_fd( + args->glockhandle[index]); + } + + drm_gem_object_unreference(obj); + mutex_unlock(&dev->struct_mutex); + + return 0; +} + int kgsl_gem_set_bufcount_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) @@ -863,6 +1006,32 @@ kgsl_gem_set_bufcount_ioctl(struct drm_device *dev, void *data, return ret; } +int +kgsl_gem_get_bufcount_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_kgsl_gem_bufcount *args = data; + struct drm_gem_object *obj; + struct drm_kgsl_gem_object *priv; + + obj = drm_gem_object_lookup(dev, file_priv, args->handle); + + if (obj == NULL) { + DRM_ERROR("Invalid GEM handle %x\n", args->handle); + return -EBADF; + } + + mutex_lock(&dev->struct_mutex); + priv = obj->driver_private; + + args->bufcount = priv->bufcount; + + drm_gem_object_unreference(obj); + mutex_unlock(&dev->struct_mutex); + + return 0; +} + int kgsl_gem_set_active_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) @@ -957,122 +1126,6 @@ int kgsl_gem_phys_fault(struct vm_area_struct *vma, struct vm_fault *vmf) } } -static struct vm_operations_struct kgsl_gem_kmem_vm_ops = { - .fault = kgsl_gem_kmem_fault, - .open = drm_gem_vm_open, - .close = drm_gem_vm_close, -}; - -static struct vm_operations_struct kgsl_gem_phys_vm_ops = { - .fault = kgsl_gem_phys_fault, - .open = drm_gem_vm_open, - .close = drm_gem_vm_close, -}; - -/* This is a clone of the standard drm_gem_mmap function modified to allow - us to properly map KMEM regions as well as the PMEM regions */ - -int msm_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma) -{ - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->minor->dev; - struct drm_gem_mm *mm = dev->mm_private; - struct drm_local_map *map = NULL; - struct drm_gem_object *obj; - struct drm_hash_item *hash; - struct drm_kgsl_gem_object *gpriv; - int ret = 0; - - mutex_lock(&dev->struct_mutex); - - if (drm_ht_find_item(&mm->offset_hash, vma->vm_pgoff, &hash)) { - mutex_unlock(&dev->struct_mutex); - return drm_mmap(filp, vma); - } - - map = drm_hash_entry(hash, struct drm_map_list, hash)->map; - if (!map || - ((map->flags & _DRM_RESTRICTED) && !capable(CAP_SYS_ADMIN))) { - ret = -EPERM; - goto out_unlock; - } - - /* Check for valid size. */ - if (map->size < vma->vm_end - vma->vm_start) { - ret = -EINVAL; - goto out_unlock; - } - - obj = map->handle; - - gpriv = obj->driver_private; - - /* VM_PFNMAP is only for memory that doesn't use struct page - * in other words, not "normal" memory. If you try to use it - * with "normal" memory then the mappings don't get flushed. */ - - if (TYPE_IS_MEM(gpriv->type)) { - vma->vm_flags |= VM_RESERVED | VM_DONTEXPAND; - vma->vm_ops = &kgsl_gem_kmem_vm_ops; - } else { - vma->vm_flags |= VM_RESERVED | VM_IO | VM_PFNMAP | - VM_DONTEXPAND; - vma->vm_ops = &kgsl_gem_phys_vm_ops; - } - - vma->vm_private_data = map->handle; - - - /* Take care of requested caching policy */ - if (gpriv->type == DRM_KGSL_GEM_TYPE_KMEM || - gpriv->type & DRM_KGSL_GEM_CACHE_MASK) { - if (gpriv->type & DRM_KGSL_GEM_CACHE_WBACKWA) - vma->vm_page_prot = - pgprot_writebackwacache(vma->vm_page_prot); - else if (gpriv->type & DRM_KGSL_GEM_CACHE_WBACK) - vma->vm_page_prot = - pgprot_writebackcache(vma->vm_page_prot); - else if (gpriv->type & DRM_KGSL_GEM_CACHE_WTHROUGH) - vma->vm_page_prot = - pgprot_writethroughcache(vma->vm_page_prot); - else - vma->vm_page_prot = - pgprot_writecombine(vma->vm_page_prot); - } else { - if (gpriv->type == DRM_KGSL_GEM_TYPE_KMEM_NOCACHE) - vma->vm_page_prot = - pgprot_noncached(vma->vm_page_prot); - else - /* default pmem is WC */ - vma->vm_page_prot = - pgprot_writecombine(vma->vm_page_prot); - } - - /* flush out existing KMEM cached mappings if new ones are - * of uncached type */ - if (IS_MEM_UNCACHED(gpriv->type)) - kgsl_cache_range_op(&gpriv->memdesc, - KGSL_CACHE_OP_FLUSH); - - /* Add the other memory types here */ - - /* Take a ref for this mapping of the object, so that the fault - * handler can dereference the mmap offset's pointer to the object. - * This reference is cleaned up by the corresponding vm_close - * (which should happen whether the vma was created by this call, or - * by a vm_open due to mremap or partial unmap or whatever). - */ - drm_gem_object_reference(obj); - - vma->vm_file = filp; /* Needed for drm_vm_open() */ - drm_vm_open_locked(vma); - -out_unlock: - mutex_unlock(&dev->struct_mutex); - - return ret; -} - void cleanup_fence(struct drm_kgsl_gem_object_fence *fence, int check_waiting) { @@ -1434,8 +1487,17 @@ struct drm_ioctl_desc kgsl_drm_ioctls[] = { DRM_IOCTL_DEF_DRV(KGSL_GEM_ALLOC, kgsl_gem_alloc_ioctl, 0), DRM_IOCTL_DEF_DRV(KGSL_GEM_MMAP, kgsl_gem_mmap_ioctl, 0), DRM_IOCTL_DEF_DRV(KGSL_GEM_GET_BUFINFO, kgsl_gem_get_bufinfo_ioctl, 0), + DRM_IOCTL_DEF_DRV(KGSL_GEM_GET_ION_FD, kgsl_gem_get_ion_fd_ioctl, 0), + DRM_IOCTL_DEF_DRV(KGSL_GEM_CREATE_FROM_ION, + kgsl_gem_create_from_ion_ioctl, 0), DRM_IOCTL_DEF_DRV(KGSL_GEM_SET_BUFCOUNT, - kgsl_gem_set_bufcount_ioctl, 0), + kgsl_gem_set_bufcount_ioctl, 0), + DRM_IOCTL_DEF_DRV(KGSL_GEM_GET_BUFCOUNT, + kgsl_gem_get_bufcount_ioctl, 0), + DRM_IOCTL_DEF_DRV(KGSL_GEM_SET_GLOCK_HANDLES_INFO, + kgsl_gem_set_glock_handles_ioctl, 0), + DRM_IOCTL_DEF_DRV(KGSL_GEM_GET_GLOCK_HANDLES_INFO, + kgsl_gem_get_glock_handles_ioctl, 0), DRM_IOCTL_DEF_DRV(KGSL_GEM_SET_ACTIVE, kgsl_gem_set_active_ioctl, 0), DRM_IOCTL_DEF_DRV(KGSL_GEM_LOCK_HANDLE, kgsl_gem_lock_handle_ioctl, 0), @@ -1447,28 +1509,22 @@ struct drm_ioctl_desc kgsl_drm_ioctls[] = { DRM_MASTER), }; +static const struct file_operations kgsl_drm_driver_fops = { + .owner = THIS_MODULE, + .open = drm_open, + .release = drm_release, + .unlocked_ioctl = drm_ioctl, + .mmap = drm_gem_mmap, + .poll = drm_poll, + .fasync = drm_fasync, +}; + static struct drm_driver driver = { .driver_features = DRIVER_GEM, - .load = kgsl_drm_load, - .unload = kgsl_drm_unload, - .preclose = kgsl_drm_preclose, - .suspend = kgsl_drm_suspend, - .resume = kgsl_drm_resume, - .reclaim_buffers = drm_core_reclaim_buffers, .gem_init_object = kgsl_gem_init_object, .gem_free_object = kgsl_gem_free_object, .ioctls = kgsl_drm_ioctls, - - .fops = { - .owner = THIS_MODULE, - .open = drm_open, - .release = drm_release, - .unlocked_ioctl = drm_ioctl, - .mmap = msm_drm_gem_mmap, - .poll = drm_poll, - .fasync = drm_fasync, - }, - + .fops = &kgsl_drm_driver_fops, .name = DRIVER_NAME, .desc = DRIVER_DESC, .date = DRIVER_DATE, @@ -1497,11 +1553,24 @@ int kgsl_drm_init(struct platform_device *dev) gem_buf_fence[i].fence_id = ENTRY_EMPTY; } + /* Create ION Client */ + kgsl_drm_ion_client = msm_ion_client_create( + 0xffffffff, "kgsl_drm"); + if (!kgsl_drm_ion_client) { + DRM_ERROR("Unable to create ION client\n"); + return -ENOMEM; + } + return drm_platform_init(&driver, dev); } void kgsl_drm_exit(void) { kgsl_drm_inited = DRM_KGSL_NOT_INITED; + + if (kgsl_drm_ion_client) + ion_client_destroy(kgsl_drm_ion_client); + kgsl_drm_ion_client = NULL; + drm_platform_exit(&driver, driver.kdriver.platform_device); } diff --git a/drivers/gpu/msm/kgsl_events.c b/drivers/gpu/msm/kgsl_events.c index e8c6c5d8a8e..277eae0127c 100644 --- a/drivers/gpu/msm/kgsl_events.c +++ b/drivers/gpu/msm/kgsl_events.c @@ -17,6 +17,7 @@ #include #include "kgsl_trace.h" +#include "adreno.h" static inline struct list_head *_get_list_head(struct kgsl_device *device, struct kgsl_context *context) @@ -48,7 +49,8 @@ static inline void _do_signal_event(struct kgsl_device *device, { int id = event->context ? event->context->id : KGSL_MEMSTORE_GLOBAL; - trace_kgsl_fire_event(id, timestamp, type, jiffies - event->created); + trace_kgsl_fire_event(id, timestamp, type, jiffies - event->created, + event->func); if (event->func) event->func(device, event->priv, id, timestamp, type); @@ -214,6 +216,8 @@ int kgsl_add_event(struct kgsl_device *device, u32 id, u32 ts, struct kgsl_event *event; unsigned int cur_ts; struct kgsl_context *context = NULL; + struct adreno_context *drawctxt; + struct adreno_device *adreno_dev = ADRENO_DEVICE(device); BUG_ON(!mutex_is_locked(&device->mutex)); @@ -224,6 +228,15 @@ int kgsl_add_event(struct kgsl_device *device, u32 id, u32 ts, context = kgsl_context_get(device, id); if (context == NULL) return -EINVAL; + /* Do not allow registering of event with invalid timestamp */ + drawctxt = ADRENO_CONTEXT(context); + if (timestamp_cmp(ts, drawctxt->timestamp) > 0) { + kgsl_context_put(context); + return -EINVAL; + } + } else { + if (timestamp_cmp(ts, adreno_dev->ringbuffer.global_ts) > 0) + return -EINVAL; } cur_ts = kgsl_readtimestamp(device, context, KGSL_TIMESTAMP_RETIRED); @@ -235,10 +248,11 @@ int kgsl_add_event(struct kgsl_device *device, u32 id, u32 ts, */ if (timestamp_cmp(cur_ts, ts) >= 0) { - trace_kgsl_fire_event(id, cur_ts, ts, 0); + trace_kgsl_fire_event(id, cur_ts, ts, 0, func); func(device, priv, id, ts, KGSL_EVENT_TIMESTAMP_RETIRED); kgsl_context_put(context); + queue_work(device->work_queue, &device->ts_expired_ws); return 0; } @@ -252,7 +266,7 @@ int kgsl_add_event(struct kgsl_device *device, u32 id, u32 ts, * Increase the active count on the device to avoid going into power * saving modes while events are pending */ - ret = kgsl_active_count_get_light(device); + ret = kgsl_active_count_get(device); if (ret < 0) { kgsl_context_put(context); kfree(event); @@ -266,7 +280,7 @@ int kgsl_add_event(struct kgsl_device *device, u32 id, u32 ts, event->owner = owner; event->created = jiffies; - trace_kgsl_register_event(id, ts); + trace_kgsl_register_event(id, ts, func); /* Add the event to either the owning context or the global list */ @@ -346,44 +360,13 @@ void kgsl_cancel_event(struct kgsl_device *device, struct kgsl_context *context, } EXPORT_SYMBOL(kgsl_cancel_event); -static inline int _mark_next_event(struct kgsl_device *device, - struct list_head *head) -{ - struct kgsl_event *event; - - if (!list_empty(head)) { - event = list_first_entry(head, struct kgsl_event, list); - - /* - * Next event will return 0 if the event was marked or 1 if the - * timestamp on the event has passed - return that up a layer - */ - - if (device->ftbl->next_event) - return device->ftbl->next_event(device, event); - } - - return 0; -} - static int kgsl_process_context_events(struct kgsl_device *device, struct kgsl_context *context) { - while (1) { - unsigned int timestamp = kgsl_readtimestamp(device, context, - KGSL_TIMESTAMP_RETIRED); - - _retire_events(device, &context->events, timestamp); + unsigned int timestamp = kgsl_readtimestamp(device, context, + KGSL_TIMESTAMP_RETIRED); - /* - * _mark_next event will return 1 as long as the next event - * timestamp has expired - this is to cope with an unavoidable - * race condition with the GPU that is still processing events. - */ - - if (!_mark_next_event(device, &context->events)) - break; - } + _retire_events(device, &context->events, timestamp); /* * Return 0 if the list is empty so the calling function can remove the @@ -400,21 +383,10 @@ void kgsl_process_events(struct work_struct *work) struct kgsl_context *context, *tmp; uint32_t timestamp; - /* - * Bail unless the global timestamp has advanced. We can safely do this - * outside of the mutex for speed - */ - - timestamp = kgsl_readtimestamp(device, NULL, KGSL_TIMESTAMP_RETIRED); - if (timestamp == device->events_last_timestamp) - return; - mutex_lock(&device->mutex); - device->events_last_timestamp = timestamp; - + timestamp = kgsl_readtimestamp(device, NULL, KGSL_TIMESTAMP_RETIRED); _retire_events(device, &device->events, timestamp); - _mark_next_event(device, &device->events); /* Now process all of the pending contexts */ list_for_each_entry_safe(context, tmp, &device->events_pending_list, @@ -424,15 +396,17 @@ void kgsl_process_events(struct work_struct *work) * Increment the refcount to make sure that the list_del_init * is called with a valid context's list */ - _kgsl_context_get(context); - /* - * If kgsl_timestamp_expired_context returns 0 then it no longer - * has any pending events and can be removed from the list - */ - - if (kgsl_process_context_events(device, context) == 0) - list_del_init(&context->events_list); - kgsl_context_put(context); + if (_kgsl_context_get(context)) { + /* + * If kgsl_timestamp_expired_context returns 0 then it + * no longer has any pending events and can be removed + * from the list + */ + + if (kgsl_process_context_events(device, context) == 0) + list_del_init(&context->events_list); + kgsl_context_put(context); + } } mutex_unlock(&device->mutex); diff --git a/drivers/gpu/msm/kgsl_gpummu.c b/drivers/gpu/msm/kgsl_gpummu.c index e52bb5dfd37..1a1e2e3549f 100644 --- a/drivers/gpu/msm/kgsl_gpummu.c +++ b/drivers/gpu/msm/kgsl_gpummu.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2013, The Linux Foundation. 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 and @@ -19,6 +19,7 @@ #include "kgsl.h" #include "kgsl_mmu.h" +#include "kgsl_gpummu.h" #include "kgsl_device.h" #include "kgsl_sharedmem.h" #include "kgsl_trace.h" @@ -161,7 +162,7 @@ _kgsl_ptpool_add_entries(struct kgsl_ptpool *pool, int count, int dynamic) } static void * -_kgsl_ptpool_get_entry(struct kgsl_ptpool *pool, unsigned int *physaddr) +_kgsl_ptpool_get_entry(struct kgsl_ptpool *pool, phys_addr_t *physaddr) { struct kgsl_ptpool_chunk *chunk; @@ -227,7 +228,7 @@ kgsl_ptpool_add(struct kgsl_ptpool *pool, int count) */ static void *kgsl_ptpool_alloc(struct kgsl_ptpool *pool, - unsigned int *physaddr) + phys_addr_t *physaddr) { void *addr = NULL; int ret; @@ -357,16 +358,15 @@ void *kgsl_gpummu_ptpool_init(int entries) int kgsl_gpummu_pt_equal(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt, - unsigned int pt_base) + phys_addr_t pt_base) { struct kgsl_gpummu_pt *gpummu_pt = pt ? pt->priv : NULL; return gpummu_pt && pt_base && (gpummu_pt->base.gpuaddr == pt_base); } -void kgsl_gpummu_destroy_pagetable(void *mmu_specific_pt) +void kgsl_gpummu_destroy_pagetable(struct kgsl_pagetable *pt) { - struct kgsl_gpummu_pt *gpummu_pt = (struct kgsl_gpummu_pt *) - mmu_specific_pt; + struct kgsl_gpummu_pt *gpummu_pt = pt->priv; kgsl_ptpool_free((struct kgsl_ptpool *)kgsl_driver.ptpool, gpummu_pt->base.hostptr); @@ -446,15 +446,20 @@ static void *kgsl_gpummu_create_pagetable(void) if (gpummu_pt->base.hostptr == NULL) goto err_flushfilter; + /* Do a check before truncating phys_addr_t to unsigned 32 */ + if (sizeof(phys_addr_t) > sizeof(unsigned int)) { + WARN_ONCE(1, "Cannot use LPAE with gpummu\n"); + goto err_flushfilter; + } + gpummu_pt->base.gpuaddr = gpummu_pt->base.physaddr; + gpummu_pt->base.size = KGSL_PAGETABLE_SIZE; + /* ptpool allocations are from coherent memory, so update the device statistics acordingly */ KGSL_STATS_ADD(KGSL_PAGETABLE_SIZE, kgsl_driver.stats.coherent, kgsl_driver.stats.coherent_max); - gpummu_pt->base.gpuaddr = gpummu_pt->base.physaddr; - gpummu_pt->base.size = KGSL_PAGETABLE_SIZE; - return (void *)gpummu_pt; err_flushfilter: @@ -473,7 +478,9 @@ static int kgsl_gpummu_default_setstate(struct kgsl_mmu *mmu, return 0; if (flags & KGSL_MMUFLAGS_PTUPDATE) { - kgsl_idle(mmu->device); + int ret = kgsl_idle(mmu->device); + if (ret) + return ret; gpummu_pt = mmu->hwpagetable->priv; kgsl_regwrite(mmu->device, MH_MMU_PT_BASE, gpummu_pt->base.gpuaddr); @@ -523,6 +530,11 @@ static int kgsl_gpummu_init(struct kgsl_mmu *mmu) */ int status = 0; + mmu->pt_base = KGSL_PAGETABLE_BASE; + mmu->pt_size = CONFIG_MSM_KGSL_PAGE_TABLE_SIZE; + mmu->pt_per_process = KGSL_MMU_USE_PER_PROCESS_PT; + mmu->use_cpu_map = false; + /* sub-client MMU lookups require address translation */ if ((mmu->config & ~0x1) > 0) { /*make sure virtual address range is a multiple of 64Kb */ @@ -564,7 +576,7 @@ static int kgsl_gpummu_start(struct kgsl_mmu *mmu) kgsl_regwrite(device, MH_INTERRUPT_MASK, GSL_MMU_INT_MASK | MH_INTERRUPT_MASK__MMU_PAGE_FAULT); - kgsl_sharedmem_set(&mmu->setstate_memory, 0, 0, + kgsl_sharedmem_set(device, &mmu->setstate_memory, 0, 0, mmu->setstate_memory.size); /* TRAN_ERROR needs a 32 byte (32 byte aligned) chunk of memory @@ -577,7 +589,7 @@ static int kgsl_gpummu_start(struct kgsl_mmu *mmu) if (mmu->defaultpagetable == NULL) mmu->defaultpagetable = - kgsl_mmu_getpagetable(KGSL_MMU_GLOBAL_PT); + kgsl_mmu_getpagetable(mmu, KGSL_MMU_GLOBAL_PT); /* Return error if the default pagetable doesn't exist */ if (mmu->defaultpagetable == NULL) @@ -599,14 +611,14 @@ static int kgsl_gpummu_start(struct kgsl_mmu *mmu) } static int -kgsl_gpummu_unmap(void *mmu_specific_pt, +kgsl_gpummu_unmap(struct kgsl_pagetable *pt, struct kgsl_memdesc *memdesc, unsigned int *tlb_flags) { unsigned int numpages; unsigned int pte, ptefirst, ptelast, superpte; unsigned int range = memdesc->size; - struct kgsl_gpummu_pt *gpummu_pt = mmu_specific_pt; + struct kgsl_gpummu_pt *gpummu_pt = pt->priv; /* All GPU addresses as assigned are page aligned, but some functions purturb the gpuaddr with an offset, so apply the @@ -648,13 +660,13 @@ kgsl_gpummu_unmap(void *mmu_specific_pt, GSL_TLBFLUSH_FILTER_ISDIRTY((_p) / GSL_PT_SUPER_PTE)) static int -kgsl_gpummu_map(void *mmu_specific_pt, +kgsl_gpummu_map(struct kgsl_pagetable *pt, struct kgsl_memdesc *memdesc, unsigned int protflags, unsigned int *tlb_flags) { unsigned int pte; - struct kgsl_gpummu_pt *gpummu_pt = mmu_specific_pt; + struct kgsl_gpummu_pt *gpummu_pt = pt->priv; struct scatterlist *s; int flushtlb = 0; int i; @@ -713,7 +725,7 @@ static int kgsl_gpummu_close(struct kgsl_mmu *mmu) return 0; } -static unsigned int +static phys_addr_t kgsl_gpummu_get_current_ptbase(struct kgsl_mmu *mmu) { unsigned int ptbase; @@ -721,7 +733,7 @@ kgsl_gpummu_get_current_ptbase(struct kgsl_mmu *mmu) return ptbase; } -static unsigned int +static phys_addr_t kgsl_gpummu_get_pt_base_addr(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt) { @@ -747,9 +759,11 @@ struct kgsl_mmu_ops gpummu_ops = { .mmu_get_pt_base_addr = kgsl_gpummu_get_pt_base_addr, .mmu_enable_clk = NULL, .mmu_disable_clk_on_ts = NULL, - .mmu_get_pt_lsb = NULL, + .mmu_get_default_ttbr0 = NULL, .mmu_get_reg_gpuaddr = NULL, + .mmu_get_reg_ahbaddr = NULL, .mmu_get_num_iommu_units = kgsl_gpummu_get_num_iommu_units, + .mmu_hw_halt_supported = NULL, }; struct kgsl_mmu_pt_ops gpummu_pt_ops = { diff --git a/drivers/gpu/msm/kgsl_gpummu.h b/drivers/gpu/msm/kgsl_gpummu.h index 99e7d5feb6e..1753afff442 100644 --- a/drivers/gpu/msm/kgsl_gpummu.h +++ b/drivers/gpu/msm/kgsl_gpummu.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2013, The Linux Foundation. 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 and @@ -57,7 +57,7 @@ struct kgsl_ptpool_chunk { int dynamic; void *data; - unsigned int phys; + phys_addr_t phys; unsigned long *bitmap; struct list_head list; diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c index 57ee5404adb..976d4a8b8cc 100644 --- a/drivers/gpu/msm/kgsl_iommu.c +++ b/drivers/gpu/msm/kgsl_iommu.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include "kgsl.h" @@ -35,32 +36,53 @@ #include "kgsl_cffdump.h" -static struct kgsl_iommu_register_list kgsl_iommuv1_reg[KGSL_IOMMU_REG_MAX] = { - { 0, 0, 0 }, /* GLOBAL_BASE */ - { 0x10, 0x0003FFFF, 14 }, /* TTBR0 */ - { 0x14, 0x0003FFFF, 14 }, /* TTBR1 */ - { 0x20, 0, 0 }, /* FSR */ - { 0x800, 0, 0 }, /* TLBIALL */ - { 0x820, 0, 0 }, /* RESUME */ - { 0x03C, 0, 0 }, /* TLBLKCR */ - { 0x818, 0, 0 }, /* V2PUR */ - { 0x2C, 0, 0 }, /* FSYNR0 */ - { 0x2C, 0, 0 }, /* FSYNR0 */ +static struct kgsl_iommu_register_list kgsl_iommuv0_reg[KGSL_IOMMU_REG_MAX] = { + { 0, 0 }, /* GLOBAL_BASE */ + { 0x0, 1 }, /* SCTLR */ + { 0x10, 1 }, /* TTBR0 */ + { 0x14, 1 }, /* TTBR1 */ + { 0x20, 1 }, /* FSR */ + { 0x800, 1 }, /* TLBIALL */ + { 0x820, 1 }, /* RESUME */ + { 0x03C, 1 }, /* TLBLKCR */ + { 0x818, 1 }, /* V2PUR */ + { 0x2C, 1 }, /* FSYNR0 */ + { 0x30, 1 }, /* FSYNR0 */ + { 0, 0 }, /* TLBSYNC, not in v0 */ + { 0, 0 }, /* TLBSTATUS, not in v0 */ + { 0, 0 } /* IMPLDEF_MICRO_MMU_CRTL, not in v0 */ }; -static struct kgsl_iommu_register_list kgsl_iommuv2_reg[KGSL_IOMMU_REG_MAX] = { - { 0, 0, 0 }, /* GLOBAL_BASE */ - { 0x20, 0x00FFFFFF, 14 }, /* TTBR0 */ - { 0x28, 0x00FFFFFF, 14 }, /* TTBR1 */ - { 0x58, 0, 0 }, /* FSR */ - { 0x618, 0, 0 }, /* TLBIALL */ - { 0x008, 0, 0 }, /* RESUME */ - { 0, 0, 0 }, /* TLBLKCR */ - { 0, 0, 0 }, /* V2PUR */ - { 0x68, 0, 0 }, /* FSYNR0 */ - { 0x6C, 0, 0 } /* FSYNR1 */ +static struct kgsl_iommu_register_list kgsl_iommuv1_reg[KGSL_IOMMU_REG_MAX] = { + { 0, 0 }, /* GLOBAL_BASE */ + { 0x0, 1 }, /* SCTLR */ + { 0x20, 1 }, /* TTBR0 */ + { 0x28, 1 }, /* TTBR1 */ + { 0x58, 1 }, /* FSR */ + { 0x618, 1 }, /* TLBIALL */ + { 0x008, 1 }, /* RESUME */ + { 0, 0 }, /* TLBLKCR not in V1 */ + { 0, 0 }, /* V2PUR not in V1 */ + { 0x68, 1 }, /* FSYNR0 */ + { 0x6C, 1 }, /* FSYNR1 */ + { 0x7F0, 1 }, /* TLBSYNC */ + { 0x7F4, 1 }, /* TLBSTATUS */ + { 0x2000, 0 } /* IMPLDEF_MICRO_MMU_CRTL */ }; +/* naming mismatch with iommu things */ +static void _iommu_lock(void) +{ + return; +} + +/* naming mismatch with iommu things */ +static void _iommu_unlock(void) +{ + return; +} + + struct remote_iommu_petersons_spinlock kgsl_iommu_sync_lock_vars; /* @@ -221,7 +243,7 @@ static void _find_mem_entries(struct kgsl_mmu *mmu, unsigned int faultaddr, list_for_each_entry(private, &kgsl_driver.process_list, list) { - if (private->pagetable->name != id) + if (private->pagetable && (private->pagetable->name != id)) continue; spin_lock(&private->mem_lock); @@ -254,6 +276,8 @@ static void _check_if_freed(struct kgsl_iommu_device *iommu_dev, void *base = kgsl_driver.memfree_hist.base_hist_rb; struct kgsl_memfree_hist_elem *wptr; struct kgsl_memfree_hist_elem *p; + char name[32]; + memset(name, 0, sizeof(name)); mutex_lock(&kgsl_driver.memfree_hist_mutex); wptr = kgsl_driver.memfree_hist.wptr; @@ -263,12 +287,15 @@ static void _check_if_freed(struct kgsl_iommu_device *iommu_dev, if (addr >= p->gpuaddr && addr < (p->gpuaddr + p->size)) { + kgsl_get_memory_usage(name, sizeof(name) - 1, + p->flags); KGSL_LOG_DUMP(iommu_dev->kgsldev, "---- premature free ----\n"); KGSL_LOG_DUMP(iommu_dev->kgsldev, - "[%8.8X-%8.8X] was already freed by pid %d\n", + "[%8.8X-%8.8X] (%s) was already freed by pid %d\n", p->gpuaddr, p->gpuaddr + p->size, + name, p->pid); } p++; @@ -282,7 +309,7 @@ static void _check_if_freed(struct kgsl_iommu_device *iommu_dev, } static int kgsl_iommu_fault_handler(struct iommu_domain *domain, - struct device *dev, unsigned long addr, int flags) + struct device *dev, unsigned long addr, int flags, void *token) { int ret = 0; struct kgsl_mmu *mmu; @@ -297,10 +324,22 @@ static int kgsl_iommu_fault_handler(struct iommu_domain *domain, unsigned int fsynr0, fsynr1; int write; struct _mem_entry prev, next; + unsigned int curr_context_id = 0; + unsigned int curr_global_ts = 0; + struct kgsl_context *context; ret = get_iommu_unit(dev, &mmu, &iommu_unit); if (ret) goto done; + + device = mmu->device; + adreno_dev = ADRENO_DEVICE(device); + if (atomic_read(&mmu->fault)) { + if (adreno_dev->ft_pf_policy & KGSL_FT_PAGEFAULT_GPUHALT_ENABLE) + ret = -EBUSY; + goto done; + } + iommu_dev = get_iommu_device(iommu_unit, dev); if (!iommu_dev) { KGSL_CORE_ERR("Invalid IOMMU device %p\n", dev); @@ -308,8 +347,38 @@ static int kgsl_iommu_fault_handler(struct iommu_domain *domain, goto done; } iommu = mmu->priv; - device = mmu->device; - adreno_dev = ADRENO_DEVICE(device); + + /* + * set the fault bits and stuff before any printks so that if fault + * handler runs then it will know it's dealing with a pagefault + */ + kgsl_sharedmem_readl(&device->memstore, &curr_context_id, + KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, current_context)); + + context = kgsl_context_get(device, curr_context_id); + + if (context != NULL) { + kgsl_sharedmem_readl(&device->memstore, &curr_global_ts, + KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, + eoptimestamp)); + + /* save pagefault timestamp for GFT */ + set_bit(KGSL_CONTEXT_PAGEFAULT, &context->priv); + context->pagefault_ts = curr_global_ts; + + kgsl_context_put(context); + context = NULL; + } + + atomic_set(&mmu->fault, 1); + iommu_dev->fault = 1; + + if (adreno_dev->ft_pf_policy & KGSL_FT_PAGEFAULT_GPUHALT_ENABLE) { + adreno_set_gpu_fault(adreno_dev, ADRENO_IOMMU_PAGE_FAULT); + /* turn off GPU IRQ so we don't get faults from it too */ + kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF); + adreno_dispatcher_schedule(device); + } ptbase = KGSL_IOMMU_GET_CTX_REG(iommu, iommu_unit, iommu_dev->ctx_id, TTBR0); @@ -328,41 +397,40 @@ static int kgsl_iommu_fault_handler(struct iommu_domain *domain, write = ((fsynr0 & (KGSL_IOMMU_V1_FSYNR0_WNR_MASK << KGSL_IOMMU_V1_FSYNR0_WNR_SHIFT)) ? 1 : 0); + pid = kgsl_mmu_get_ptname_from_ptbase(mmu, ptbase); + if (adreno_dev->ft_pf_policy & KGSL_FT_PAGEFAULT_LOG_ONE_PER_PAGE) no_page_fault_log = kgsl_mmu_log_fault_addr(mmu, ptbase, addr); - pid = kgsl_mmu_get_ptname_from_ptbase(mmu, ptbase); if (!no_page_fault_log) { KGSL_MEM_CRIT(iommu_dev->kgsldev, "GPU PAGE FAULT: addr = %lX pid = %d\n", addr, pid); KGSL_MEM_CRIT(iommu_dev->kgsldev, - "context = %d FSR = %X FSYNR0 = %X FSYNR1 = %X(%s fault)\n", + "context = %d FSR = %X FSYNR0 = %X FSYNR1 = %X(%s fault)\n", iommu_dev->ctx_id, fsr, fsynr0, fsynr1, write ? "write" : "read"); - } - - _check_if_freed(iommu_dev, addr, pid); - KGSL_LOG_DUMP(iommu_dev->kgsldev, "---- nearby memory ----\n"); + _check_if_freed(iommu_dev, addr, pid); - _find_mem_entries(mmu, addr, ptbase, &prev, &next); + KGSL_LOG_DUMP(iommu_dev->kgsldev, "---- nearby memory ----\n"); - if (prev.gpuaddr) - _print_entry(iommu_dev->kgsldev, &prev); - else - KGSL_LOG_DUMP(iommu_dev->kgsldev, "*EMPTY*\n"); + _find_mem_entries(mmu, addr, ptbase, &prev, &next); - KGSL_LOG_DUMP(iommu_dev->kgsldev, " <- fault @ %8.8lX\n", addr); + if (prev.gpuaddr) + _print_entry(iommu_dev->kgsldev, &prev); + else + KGSL_LOG_DUMP(iommu_dev->kgsldev, "*EMPTY*\n"); - if (next.gpuaddr != 0xFFFFFFFF) - _print_entry(iommu_dev->kgsldev, &next); - else - KGSL_LOG_DUMP(iommu_dev->kgsldev, "*EMPTY*\n"); + KGSL_LOG_DUMP(iommu_dev->kgsldev, " <- fault @ %8.8lX\n", addr); - mmu->fault = 1; - iommu_dev->fault = 1; + if (next.gpuaddr != 0xFFFFFFFF) + _print_entry(iommu_dev->kgsldev, &next); + else + KGSL_LOG_DUMP(iommu_dev->kgsldev, "*EMPTY*\n"); + } - trace_kgsl_mmu_pagefault(iommu_dev->kgsldev, addr, pid, + trace_kgsl_mmu_pagefault(iommu_dev->kgsldev, addr, + kgsl_mmu_get_ptname_from_ptbase(mmu, ptbase), write ? "write" : "read"); /* @@ -559,20 +627,16 @@ static int kgsl_iommu_enable_clk(struct kgsl_mmu *mmu, */ static int kgsl_iommu_pt_equal(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt, - unsigned int pt_base) + phys_addr_t pt_base) { - struct kgsl_iommu *iommu = mmu->priv; struct kgsl_iommu_pt *iommu_pt = pt ? pt->priv : NULL; - unsigned int domain_ptbase = iommu_pt ? + phys_addr_t domain_ptbase = iommu_pt ? iommu_get_pt_base_addr(iommu_pt->domain) : 0; + /* Only compare the valid address bits of the pt_base */ - domain_ptbase &= - (iommu->iommu_reg_list[KGSL_IOMMU_CTX_TTBR0].reg_mask << - iommu->iommu_reg_list[KGSL_IOMMU_CTX_TTBR0].reg_shift); + domain_ptbase &= KGSL_IOMMU_CTX_TTBR0_ADDR_MASK; - pt_base &= - (iommu->iommu_reg_list[KGSL_IOMMU_CTX_TTBR0].reg_mask << - iommu->iommu_reg_list[KGSL_IOMMU_CTX_TTBR0].reg_shift); + pt_base &= KGSL_IOMMU_CTX_TTBR0_ADDR_MASK; return domain_ptbase && pt_base && (domain_ptbase == pt_base); @@ -584,12 +648,14 @@ static int kgsl_iommu_pt_equal(struct kgsl_mmu *mmu, * * Return - void */ -static void kgsl_iommu_destroy_pagetable(void *mmu_specific_pt) +static void kgsl_iommu_destroy_pagetable(struct kgsl_pagetable *pt) { - struct kgsl_iommu_pt *iommu_pt = mmu_specific_pt; + struct kgsl_iommu_pt *iommu_pt = pt->priv; if (iommu_pt->domain) - iommu_domain_free(iommu_pt->domain); + msm_unregister_domain(iommu_pt->domain); + kfree(iommu_pt); + iommu_pt = NULL; } /* @@ -601,8 +667,20 @@ static void kgsl_iommu_destroy_pagetable(void *mmu_specific_pt) */ void *kgsl_iommu_create_pagetable(void) { + int domain_num; struct kgsl_iommu_pt *iommu_pt; + struct msm_iova_partition kgsl_partition = { + .start = 0, + .size = 0xFFFFFFFF, + }; + struct msm_iova_layout kgsl_layout = { + .partitions = &kgsl_partition, + .npartitions = 1, + .client_name = "kgsl", + .domain_flags = 0, + }; + iommu_pt = kzalloc(sizeof(struct kgsl_iommu_pt), GFP_KERNEL); if (!iommu_pt) { KGSL_CORE_ERR("kzalloc(%d) failed\n", @@ -611,21 +689,23 @@ void *kgsl_iommu_create_pagetable(void) } /* L2 redirect is not stable on IOMMU v2 */ if (msm_soc_version_supports_iommu_v1()) - iommu_pt->domain = iommu_domain_alloc(&platform_bus_type, - MSM_IOMMU_DOMAIN_PT_CACHEABLE); - else - iommu_pt->domain = iommu_domain_alloc(&platform_bus_type, - 0); - if (!iommu_pt->domain) { - KGSL_CORE_ERR("Failed to create iommu domain\n"); - kfree(iommu_pt); - return NULL; - } else { - iommu_set_fault_handler(iommu_pt->domain, - kgsl_iommu_fault_handler); + kgsl_layout.domain_flags = MSM_IOMMU_DOMAIN_PT_CACHEABLE; + + domain_num = msm_register_domain(&kgsl_layout); + if (domain_num >= 0) { + iommu_pt->domain = msm_get_iommu_domain(domain_num); + + if (iommu_pt->domain) { + iommu_set_fault_handler(iommu_pt->domain, + kgsl_iommu_fault_handler, NULL); + + return iommu_pt; + } } - return iommu_pt; + KGSL_CORE_ERR("Failed to create iommu domain\n"); + kfree(iommu_pt); + return NULL; } /* @@ -740,17 +820,23 @@ static int _get_iommu_ctxs(struct kgsl_mmu *mmu, { struct kgsl_iommu *iommu = mmu->priv; struct kgsl_iommu_unit *iommu_unit = &iommu->iommu_units[unit_id]; - int i; - - if (data->iommu_ctx_count > KGSL_IOMMU_MAX_DEVS_PER_UNIT) { - KGSL_CORE_ERR("Too many iommu devices defined for an " - "IOMMU unit\n"); - return -EINVAL; - } - - for (i = 0; i < data->iommu_ctx_count; i++) { - if (!data->iommu_ctxs[i].iommu_ctx_name) - continue; + int i, j; + int found_ctx; + + for (j = 0; j < KGSL_IOMMU_MAX_DEVS_PER_UNIT; j++) { + found_ctx = 0; + for (i = 0; i < data->iommu_ctx_count; i++) { + if (j == data->iommu_ctxs[i].ctx_id) { + found_ctx = 1; + break; + } + } + if (!found_ctx) + break; + if (!data->iommu_ctxs[i].iommu_ctx_name) { + KGSL_CORE_ERR("Context name invalid\n"); + return -EINVAL; + } iommu_unit->dev[iommu_unit->dev_count].dev = msm_iommu_get_ctx(data->iommu_ctxs[i].iommu_ctx_name); @@ -759,12 +845,6 @@ static int _get_iommu_ctxs(struct kgsl_mmu *mmu, "device %s\n", data->iommu_ctxs[i].iommu_ctx_name); return -EINVAL; } - if (KGSL_IOMMU_CONTEXT_USER != data->iommu_ctxs[i].ctx_id && - KGSL_IOMMU_CONTEXT_PRIV != data->iommu_ctxs[i].ctx_id) { - KGSL_CORE_ERR("Invalid context ID defined: %d\n", - data->iommu_ctxs[i].ctx_id); - return -EINVAL; - } iommu_unit->dev[iommu_unit->dev_count].ctx_id = data->iommu_ctxs[i].ctx_id; iommu_unit->dev[iommu_unit->dev_count].kgsldev = mmu->device; @@ -776,6 +856,52 @@ static int _get_iommu_ctxs(struct kgsl_mmu *mmu, iommu_unit->dev_count++; } + if (!j) { + KGSL_CORE_ERR("No ctxts initialized, user ctxt absent\n "); + return -EINVAL; + } + + return 0; +} + +/* + * kgsl_iommu_start_sync_lock - Initialize some variables during MMU start up + * for GPU CPU synchronization + * @mmu - Pointer to mmu device + * + * Return - 0 on success else error code + */ +static int kgsl_iommu_start_sync_lock(struct kgsl_mmu *mmu) +{ + struct kgsl_iommu *iommu = mmu->priv; + uint32_t lock_gpu_addr = 0; + + /* iommu v1 or v0 here, cp has v1 */ + if (KGSL_DEVICE_3D0 != mmu->device->id || + !msm_soc_version_supports_iommu_v1() || + !kgsl_mmu_is_perprocess(mmu) || + iommu->sync_lock_vars) + return 0; + + if (!(mmu->flags & KGSL_MMU_FLAGS_IOMMU_SYNC)) { + KGSL_DRV_ERR(mmu->device, + "The GPU microcode does not support IOMMUv1 sync opcodes\n"); + return -ENXIO; + } + /* Store Lock variables GPU address */ + lock_gpu_addr = (iommu->sync_lock_desc.gpuaddr + + iommu->sync_lock_offset); + + kgsl_iommu_sync_lock_vars.flag[PROC_APPS] = (lock_gpu_addr + + (offsetof(struct remote_iommu_petersons_spinlock, + flag[PROC_APPS]))); + kgsl_iommu_sync_lock_vars.flag[PROC_GPU] = (lock_gpu_addr + + (offsetof(struct remote_iommu_petersons_spinlock, + flag[PROC_GPU]))); + kgsl_iommu_sync_lock_vars.turn = (lock_gpu_addr + + (offsetof(struct remote_iommu_petersons_spinlock, turn))); + + iommu->sync_lock_vars = &kgsl_iommu_sync_lock_vars; return 0; } @@ -788,28 +914,16 @@ static int _get_iommu_ctxs(struct kgsl_mmu *mmu, */ static int kgsl_iommu_init_sync_lock(struct kgsl_mmu *mmu) { - struct kgsl_iommu *iommu = mmu->priv; + struct kgsl_iommu *iommu = mmu->device->mmu.priv; int status = 0; - struct kgsl_pagetable *pagetable = NULL; - uint32_t lock_gpu_addr = 0; uint32_t lock_phy_addr = 0; uint32_t page_offset = 0; - if (!msm_soc_version_supports_iommu_v1() || - !kgsl_mmu_is_perprocess()) + if (KGSL_DEVICE_3D0 != mmu->device->id || + !msm_soc_version_supports_iommu_v1() || + !kgsl_mmu_is_perprocess(mmu)) return status; - /* - * For 2D devices cpu side sync lock is required. For 3D device, - * since we only have a single 3D core and we always ensure that - * 3D core is idle while writing to IOMMU register using CPU this - * lock is not required - */ - if (KGSL_DEVICE_2D0 == mmu->device->id || - KGSL_DEVICE_2D1 == mmu->device->id) { - return status; - } - /* Return if already initialized */ if (iommu->sync_lock_initialized) return status; @@ -828,6 +942,7 @@ static int kgsl_iommu_init_sync_lock(struct kgsl_mmu *mmu) page_offset = (lock_phy_addr & (PAGE_SIZE - 1)); lock_phy_addr = (lock_phy_addr & ~(PAGE_SIZE - 1)); iommu->sync_lock_desc.physaddr = (unsigned int)lock_phy_addr; + iommu->sync_lock_offset = page_offset; iommu->sync_lock_desc.size = PAGE_ALIGN(sizeof(kgsl_iommu_sync_lock_vars)); @@ -838,32 +953,6 @@ static int kgsl_iommu_init_sync_lock(struct kgsl_mmu *mmu) if (status) return status; - /* Map Lock variables to GPU pagetable */ - pagetable = mmu->priv_bank_table ? mmu->priv_bank_table : - mmu->defaultpagetable; - - status = kgsl_mmu_map_global(pagetable, &iommu->sync_lock_desc); - - if (status) { - kgsl_mmu_unmap(pagetable, &iommu->sync_lock_desc); - iommu->sync_lock_desc.priv &= ~KGSL_MEMDESC_GLOBAL; - return status; - } - - /* Store Lock variables GPU address */ - lock_gpu_addr = (iommu->sync_lock_desc.gpuaddr + page_offset); - - kgsl_iommu_sync_lock_vars.flag[PROC_APPS] = (lock_gpu_addr + - (offsetof(struct remote_iommu_petersons_spinlock, - flag[PROC_APPS]))); - kgsl_iommu_sync_lock_vars.flag[PROC_GPU] = (lock_gpu_addr + - (offsetof(struct remote_iommu_petersons_spinlock, - flag[PROC_GPU]))); - kgsl_iommu_sync_lock_vars.turn = (lock_gpu_addr + - (offsetof(struct remote_iommu_petersons_spinlock, turn))); - - iommu->sync_lock_vars = &kgsl_iommu_sync_lock_vars; - /* Flag Sync Lock is Initialized */ iommu->sync_lock_initialized = 1; @@ -1042,6 +1131,9 @@ static int kgsl_set_register_map(struct kgsl_mmu *mmu) iommu_unit->reg_map.size); if (ret) goto err; + + iommu_unit->iommu_halt_enable = data.iommu_halt_enable; + iommu_unit->ahb_base = data.physstart - mmu->device->reg_phys; } iommu->unit_count = pdata_dev->iommu_count; return ret; @@ -1065,28 +1157,24 @@ static int kgsl_set_register_map(struct kgsl_mmu *mmu) * Return - actual pagetable address that the ttbr0 register is programmed * with */ -static unsigned int kgsl_iommu_get_pt_base_addr(struct kgsl_mmu *mmu, +static phys_addr_t kgsl_iommu_get_pt_base_addr(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt) { - struct kgsl_iommu *iommu = mmu->priv; struct kgsl_iommu_pt *iommu_pt = pt->priv; return iommu_get_pt_base_addr(iommu_pt->domain) & - (iommu->iommu_reg_list[KGSL_IOMMU_CTX_TTBR0].reg_mask << - iommu->iommu_reg_list[KGSL_IOMMU_CTX_TTBR0].reg_shift); + KGSL_IOMMU_CTX_TTBR0_ADDR_MASK; } /* - * kgsl_iommu_get_pt_lsb - Return the lsb of the ttbr0 IOMMU register + * kgsl_iommu_get_default_ttbr0 - Return the ttbr0 value programmed by + * iommu driver * @mmu - Pointer to mmu structure * @hostptr - Pointer to the IOMMU register map. This is used to match * the iommu device whose lsb value is to be returned * @ctx_id - The context bank whose lsb valus is to be returned - * Return - returns the lsb which is the last 14 bits of the ttbr0 IOMMU - * register. ttbr0 is the actual PTBR for of the IOMMU. The last 14 bits - * are only programmed once in the beginning when a domain is attached - * does not change. + * Return - returns the ttbr0 value programmed by iommu driver */ -static int kgsl_iommu_get_pt_lsb(struct kgsl_mmu *mmu, +static phys_addr_t kgsl_iommu_get_default_ttbr0(struct kgsl_mmu *mmu, unsigned int unit_id, enum kgsl_iommu_context_id ctx_id) { @@ -1097,7 +1185,7 @@ static int kgsl_iommu_get_pt_lsb(struct kgsl_mmu *mmu, for (j = 0; j < iommu_unit->dev_count; j++) if (unit_id == i && ctx_id == iommu_unit->dev[j].ctx_id) - return iommu_unit->dev[j].pt_lsb; + return iommu_unit->dev[j].default_ttbr0; } return 0; } @@ -1157,6 +1245,13 @@ static int kgsl_iommu_setup_regs(struct kgsl_mmu *mmu, goto err; } + /* Map Lock variables to GPU pagetable */ + if (iommu->sync_lock_initialized) { + status = kgsl_mmu_map_global(pt, &iommu->sync_lock_desc); + if (status) + goto err; + } + return 0; err: for (i--; i >= 0; i--) @@ -1182,9 +1277,36 @@ static void kgsl_iommu_cleanup_regs(struct kgsl_mmu *mmu, int i; for (i = 0; i < iommu->unit_count; i++) kgsl_mmu_unmap(pt, &(iommu->iommu_units[i].reg_map)); + + if (iommu->sync_lock_desc.gpuaddr) + kgsl_mmu_unmap(pt, &iommu->sync_lock_desc); } +/* + * kgsl_iommu_get_reg_ahbaddr - Returns the ahb address of the register + * @mmu - Pointer to mmu structure + * @iommu_unit - The iommu unit for which base address is requested + * @ctx_id - The context ID of the IOMMU ctx + * @reg - The register for which address is required + * + * Return - The address of register which can be used in type0 packet + */ +static unsigned int kgsl_iommu_get_reg_ahbaddr(struct kgsl_mmu *mmu, + int iommu_unit, int ctx_id, + enum kgsl_iommu_reg_map reg) +{ + struct kgsl_iommu *iommu = mmu->priv; + + if (iommu->iommu_reg_list[reg].ctx_reg) + return iommu->iommu_units[iommu_unit].ahb_base + + iommu->iommu_reg_list[reg].reg_offset + + (ctx_id << KGSL_IOMMU_CTX_SHIFT) + iommu->ctx_offset; + else + return iommu->iommu_units[iommu_unit].ahb_base + + iommu->iommu_reg_list[reg].reg_offset; +} + static int kgsl_iommu_init(struct kgsl_mmu *mmu) { /* @@ -1195,6 +1317,7 @@ static int kgsl_iommu_init(struct kgsl_mmu *mmu) int status = 0; struct kgsl_iommu *iommu; + atomic_set(&mmu->fault, 0); iommu = kzalloc(sizeof(struct kgsl_iommu), GFP_KERNEL); if (!iommu) { KGSL_CORE_ERR("kzalloc(%d) failed\n", @@ -1210,20 +1333,75 @@ static int kgsl_iommu_init(struct kgsl_mmu *mmu) if (status) goto done; - iommu->iommu_reg_list = kgsl_iommuv1_reg; - iommu->ctx_offset = KGSL_IOMMU_CTX_OFFSET_V1; + /* + * IOMMU-v1 requires hardware halt support to do in stream + * pagetable switching. This check assumes that if there are + * multiple units, they will be matching hardware. + */ + /* name mismatch fixup between v0 and v1 here */ + mmu->pt_per_process = KGSL_MMU_USE_PER_PROCESS_PT && + (msm_soc_version_supports_iommu_v1() || + iommu->iommu_units[0].iommu_halt_enable); + /* + * For IOMMU per-process pagetables, the allocatable range + * and the kernel global range must both be outside + * the userspace address range. There is a 1Mb gap + * between these address ranges to make overrun + * detection easier. + * For the shared pagetable case use 2GB and because + * mirroring the CPU address space is not possible and + * we're better off with extra room. + */ + if (mmu->pt_per_process) { +#ifndef CONFIG_MSM_KGSL_CFF_DUMP + mmu->pt_base = PAGE_OFFSET; + mmu->pt_size = KGSL_IOMMU_GLOBAL_MEM_BASE + - kgsl_mmu_get_base_addr(mmu) - SZ_1M; + mmu->use_cpu_map = true; +#else + mmu->pt_base = KGSL_PAGETABLE_BASE; + mmu->pt_size = KGSL_IOMMU_GLOBAL_MEM_BASE + + KGSL_IOMMU_GLOBAL_MEM_SIZE - + KGSL_PAGETABLE_BASE; + mmu->use_cpu_map = false; +#endif + } else { + mmu->pt_base = KGSL_PAGETABLE_BASE; +#ifndef CONFIG_MSM_KGSL_CFF_DUMP + mmu->pt_size = SZ_2G; +#else + mmu->pt_size = KGSL_IOMMU_GLOBAL_MEM_BASE + + KGSL_IOMMU_GLOBAL_MEM_SIZE - + KGSL_PAGETABLE_BASE; +#endif + mmu->use_cpu_map = false; + } + + status = kgsl_iommu_init_sync_lock(mmu); + if (status) + goto done; + + iommu->iommu_reg_list = kgsl_iommuv0_reg; + iommu->ctx_offset = KGSL_IOMMU_CTX_OFFSET_V0; + + /* + * Due to not bringing in the iommu rename, iommu_v1 is + * actually iommu_v0. Keep our internal representation + * constant, but our interface with iommu drive needs the + * correct vixes + */ if (msm_soc_version_supports_iommu_v1()) { + iommu->iommu_reg_list = kgsl_iommuv0_reg; + iommu->ctx_offset = KGSL_IOMMU_CTX_OFFSET_V0; + } else { iommu->iommu_reg_list = kgsl_iommuv1_reg; iommu->ctx_offset = KGSL_IOMMU_CTX_OFFSET_V1; - } else { - iommu->iommu_reg_list = kgsl_iommuv2_reg; - iommu->ctx_offset = KGSL_IOMMU_CTX_OFFSET_V2; } /* A nop is required in an indirect buffer when switching * pagetables in-stream */ - kgsl_sharedmem_writel(&mmu->setstate_memory, + kgsl_sharedmem_writel(mmu->device, &mmu->setstate_memory, KGSL_IOMMU_SETSTATE_NOP_OFFSET, cp_nop_packet(1)); @@ -1272,7 +1450,8 @@ static int kgsl_iommu_setup_defaultpagetable(struct kgsl_mmu *mmu) * switching on the 3D side for which a separate table is allocated */ if (!cpu_is_msm8960() && msm_soc_version_supports_iommu_v1()) { mmu->priv_bank_table = - kgsl_mmu_getpagetable(KGSL_MMU_PRIV_BANK_TABLE_NAME); + kgsl_mmu_getpagetable(mmu, + KGSL_MMU_PRIV_BANK_TABLE_NAME); if (mmu->priv_bank_table == NULL) { status = -ENOMEM; goto err; @@ -1281,7 +1460,7 @@ static int kgsl_iommu_setup_defaultpagetable(struct kgsl_mmu *mmu) if (status) goto err; } - mmu->defaultpagetable = kgsl_mmu_getpagetable(KGSL_MMU_GLOBAL_PT); + mmu->defaultpagetable = kgsl_mmu_getpagetable(mmu, KGSL_MMU_GLOBAL_PT); /* Return error if the default pagetable doesn't exist */ if (mmu->defaultpagetable == NULL) { status = -ENOMEM; @@ -1413,6 +1592,8 @@ static int kgsl_iommu_start(struct kgsl_mmu *mmu) int status; struct kgsl_iommu *iommu = mmu->priv; int i, j; + int sctlr_val = 0; + struct adreno_device *adreno_dev = ADRENO_DEVICE(mmu->device); if (mmu->flags & KGSL_FLAGS_STARTED) return 0; @@ -1427,6 +1608,9 @@ static int kgsl_iommu_start(struct kgsl_mmu *mmu) (device->id == KGSL_DEVICE_3D0)) kgsl_iommu_init_sync_lock(mmu); } + status = kgsl_iommu_start_sync_lock(mmu); + if (status) + return status; /* We use the GPU MMU to control access to IOMMU registers on 8960 with * a225, hence we still keep the MMU active on 8960 */ @@ -1466,18 +1650,45 @@ static int kgsl_iommu_start(struct kgsl_mmu *mmu) for (i = 0; i < iommu->unit_count; i++) { struct kgsl_iommu_unit *iommu_unit = &iommu->iommu_units[i]; for (j = 0; j < iommu_unit->dev_count; j++) { - iommu_unit->dev[j].pt_lsb = KGSL_IOMMMU_PT_LSB(iommu, + + /* + * For IOMMU V1 do not halt IOMMU on pagefault if + * FT pagefault policy is set accordingly + */ + if ((!msm_soc_version_supports_iommu_v1()) && + (!(adreno_dev->ft_pf_policy & + KGSL_FT_PAGEFAULT_GPUHALT_ENABLE))) { + sctlr_val = KGSL_IOMMU_GET_CTX_REG(iommu, + iommu_unit, + iommu_unit->dev[j].ctx_id, + SCTLR); + sctlr_val |= (0x1 << + KGSL_IOMMU_SCTLR_HUPCF_SHIFT); + KGSL_IOMMU_SET_CTX_REG(iommu, + iommu_unit, + iommu_unit->dev[j].ctx_id, + SCTLR, sctlr_val); + } + if (sizeof(phys_addr_t) > sizeof(unsigned long)) { + iommu_unit->dev[j].default_ttbr0 = + KGSL_IOMMU_GET_CTX_REG_LL(iommu, + iommu_unit, + iommu_unit->dev[j].ctx_id, + TTBR0); + } else { + iommu_unit->dev[j].default_ttbr0 = KGSL_IOMMU_GET_CTX_REG(iommu, iommu_unit, iommu_unit->dev[j].ctx_id, - TTBR0)); + TTBR0); + } } } kgsl_iommu_lock_rb_in_tlb(mmu); msm_iommu_unlock(); /* For complete CFF */ - kgsl_cffdump_setmem(mmu->setstate_memory.gpuaddr + + kgsl_cffdump_setmem(mmu->device, mmu->setstate_memory.gpuaddr + KGSL_IOMMU_SETSTATE_NOP_OFFSET, cp_nop_packet(1), sizeof(unsigned int)); @@ -1493,13 +1704,13 @@ static int kgsl_iommu_start(struct kgsl_mmu *mmu) } static int -kgsl_iommu_unmap(void *mmu_specific_pt, +kgsl_iommu_unmap(struct kgsl_pagetable *pt, struct kgsl_memdesc *memdesc, unsigned int *tlb_flags) { int ret; unsigned int range = memdesc->size; - struct kgsl_iommu_pt *iommu_pt = mmu_specific_pt; + struct kgsl_iommu_pt *iommu_pt = pt->priv; /* All GPU addresses as assigned are page aligned, but some functions purturb the gpuaddr with an offset, so apply the @@ -1523,20 +1734,20 @@ kgsl_iommu_unmap(void *mmu_specific_pt, * Flushing only required if per process pagetables are used. With * global case, flushing will happen inside iommu_map function */ - if (!ret && kgsl_mmu_is_perprocess()) + if (!ret && kgsl_mmu_is_perprocess(pt->mmu)) *tlb_flags = UINT_MAX; return 0; } static int -kgsl_iommu_map(void *mmu_specific_pt, +kgsl_iommu_map(struct kgsl_pagetable *pt, struct kgsl_memdesc *memdesc, unsigned int protflags, unsigned int *tlb_flags) { int ret; unsigned int iommu_virt_addr; - struct kgsl_iommu_pt *iommu_pt = mmu_specific_pt; + struct kgsl_iommu_pt *iommu_pt = pt->priv; int size = memdesc->size; BUG_ON(NULL == iommu_pt); @@ -1569,10 +1780,40 @@ kgsl_iommu_map(void *mmu_specific_pt, return ret; } -static void kgsl_iommu_stop(struct kgsl_mmu *mmu) +void kgsl_iommu_pagefault_resume(struct kgsl_mmu *mmu) { struct kgsl_iommu *iommu = mmu->priv; int i, j; + + if (atomic_read(&mmu->fault)) { + for (i = 0; i < iommu->unit_count; i++) { + struct kgsl_iommu_unit *iommu_unit = + &iommu->iommu_units[i]; + for (j = 0; j < iommu_unit->dev_count; j++) { + if (iommu_unit->dev[j].fault) { + kgsl_iommu_enable_clk(mmu, j); + _iommu_lock(); + KGSL_IOMMU_SET_CTX_REG(iommu, + iommu_unit, + iommu_unit->dev[j].ctx_id, + RESUME, 1); + KGSL_IOMMU_SET_CTX_REG(iommu, + iommu_unit, + iommu_unit->dev[j].ctx_id, + FSR, 0); + _iommu_unlock(); + iommu_unit->dev[j].fault = 0; + } + } + } + atomic_set(&mmu->fault, 0); + } +} + + +static void kgsl_iommu_stop(struct kgsl_mmu *mmu) +{ + struct kgsl_iommu *iommu = mmu->priv; /* * stop device mmu * @@ -1585,25 +1826,7 @@ static void kgsl_iommu_stop(struct kgsl_mmu *mmu) mmu->flags &= ~KGSL_FLAGS_STARTED; - if (mmu->fault) { - for (i = 0; i < iommu->unit_count; i++) { - struct kgsl_iommu_unit *iommu_unit = - &iommu->iommu_units[i]; - for (j = 0; j < iommu_unit->dev_count; j++) { - if (iommu_unit->dev[j].fault) { - kgsl_iommu_enable_clk(mmu, j); - msm_iommu_lock(); - KGSL_IOMMU_SET_CTX_REG(iommu, - iommu_unit, - iommu_unit->dev[j].ctx_id, - RESUME, 1); - msm_iommu_unlock(); - iommu_unit->dev[j].fault = 0; - } - } - } - mmu->fault = 0; - } + kgsl_iommu_pagefault_resume(mmu); } /* switch off MMU clocks and cancel any events it has queued */ iommu->clk_event_queued = false; @@ -1630,7 +1853,12 @@ static int kgsl_iommu_close(struct kgsl_mmu *mmu) if (reg_map->hostptr) iounmap(reg_map->hostptr); kgsl_sg_free(reg_map->sg, reg_map->sglen); + reg_map->priv &= ~KGSL_MEMDESC_GLOBAL; } + /* clear IOMMU GPU CPU sync structures */ + kgsl_sg_free(iommu->sync_lock_desc.sg, iommu->sync_lock_desc.sglen); + memset(&iommu->sync_lock_desc, 0, sizeof(iommu->sync_lock_desc)); + iommu->sync_lock_vars = NULL; kfree(iommu); @@ -1642,10 +1870,10 @@ static int kgsl_iommu_close(struct kgsl_mmu *mmu) return 0; } -static unsigned int +static phys_addr_t kgsl_iommu_get_current_ptbase(struct kgsl_mmu *mmu) { - unsigned int pt_base; + phys_addr_t pt_base; struct kgsl_iommu *iommu = mmu->priv; /* We cannot enable or disable the clocks in interrupt context, this function is called from interrupt context if there is an axi error */ @@ -1657,9 +1885,7 @@ kgsl_iommu_get_current_ptbase(struct kgsl_mmu *mmu) KGSL_IOMMU_CONTEXT_USER, TTBR0); kgsl_iommu_disable_clk_on_ts(mmu, 0, false); - return pt_base & - (iommu->iommu_reg_list[KGSL_IOMMU_CTX_TTBR0].reg_mask << - iommu->iommu_reg_list[KGSL_IOMMU_CTX_TTBR0].reg_shift); + return pt_base & KGSL_IOMMU_CTX_TTBR0_ADDR_MASK; } /* @@ -1683,7 +1909,7 @@ static int kgsl_iommu_default_setstate(struct kgsl_mmu *mmu, int ret = 0; unsigned int pt_base = kgsl_iommu_get_pt_base_addr(mmu, mmu->hwpagetable); - unsigned int pt_val; + phys_addr_t pt_val; ret = kgsl_iommu_enable_clk(mmu, KGSL_IOMMU_CONTEXT_USER); @@ -1691,26 +1917,43 @@ static int kgsl_iommu_default_setstate(struct kgsl_mmu *mmu, KGSL_DRV_ERR(mmu->device, "Failed to enable iommu clocks\n"); return ret; } - /* Mask off the lsb of the pt base address since lsb will not change */ - pt_base &= (iommu->iommu_reg_list[KGSL_IOMMU_CTX_TTBR0].reg_mask << - iommu->iommu_reg_list[KGSL_IOMMU_CTX_TTBR0].reg_shift); - //if (msm_soc_version_supports_iommu_v1()) + /* For v0 SMMU GPU needs to be idle for tlb invalidate as well */ + /* naming mismatch for iommu */ + if (msm_soc_version_supports_iommu_v1()) { + ret = kgsl_idle(mmu->device); + if (ret) + return ret; + } + /* Acquire GPU-CPU sync Lock here */ msm_iommu_lock(); if (flags & KGSL_MMUFLAGS_PTUPDATE) { - if (!msm_soc_version_supports_iommu_v1()) - kgsl_idle(mmu->device); + /* naming mismatch for iommu */ + if (!msm_soc_version_supports_iommu_v1()) { + ret = kgsl_idle(mmu->device); + if (ret) + goto unlock; + } for (i = 0; i < iommu->unit_count; i++) { /* get the lsb value which should not change when * changing ttbr0 */ - pt_val = kgsl_iommu_get_pt_lsb(mmu, i, + pt_val = kgsl_iommu_get_default_ttbr0(mmu, i, KGSL_IOMMU_CONTEXT_USER); - pt_val += pt_base; - KGSL_IOMMU_SET_CTX_REG(iommu, (&iommu->iommu_units[i]), - KGSL_IOMMU_CONTEXT_USER, TTBR0, pt_val); + pt_base &= KGSL_IOMMU_CTX_TTBR0_ADDR_MASK; + pt_val &= ~KGSL_IOMMU_CTX_TTBR0_ADDR_MASK; + pt_val |= pt_base; + if (sizeof(phys_addr_t) > sizeof(unsigned long)) { + KGSL_IOMMU_SET_CTX_REG_LL(iommu, + (&iommu->iommu_units[i]), + KGSL_IOMMU_CONTEXT_USER, TTBR0, pt_val); + } else { + KGSL_IOMMU_SET_CTX_REG(iommu, + (&iommu->iommu_units[i]), + KGSL_IOMMU_CONTEXT_USER, TTBR0, pt_val); + } mb(); temp = KGSL_IOMMU_GET_CTX_REG(iommu, @@ -1720,12 +1963,41 @@ static int kgsl_iommu_default_setstate(struct kgsl_mmu *mmu, } /* Flush tlb */ if (flags & KGSL_MMUFLAGS_TLBFLUSH) { + unsigned long wait_for_flush; for (i = 0; i < iommu->unit_count; i++) { KGSL_IOMMU_SET_CTX_REG(iommu, (&iommu->iommu_units[i]), KGSL_IOMMU_CONTEXT_USER, TLBIALL, 1); mb(); + /* + * Wait for flush to complete by polling the flush + * status bit of TLBSTATUS register for not more than + * 2 s. After 2s just exit, at that point the SMMU h/w + * may be stuck and will eventually cause GPU to hang + * or bring the system down. + */ + /* naming mismatch */ + if (!msm_soc_version_supports_iommu_v1()) { + wait_for_flush = jiffies + + msecs_to_jiffies(2000); + KGSL_IOMMU_SET_CTX_REG(iommu, + (&iommu->iommu_units[i]), + KGSL_IOMMU_CONTEXT_USER, TLBSYNC, 0); + while (KGSL_IOMMU_GET_CTX_REG(iommu, + (&iommu->iommu_units[i]), + KGSL_IOMMU_CONTEXT_USER, TLBSTATUS) & + (KGSL_IOMMU_CTX_TLBSTATUS_SACTIVE)) { + if (time_after(jiffies, + wait_for_flush)) { + KGSL_DRV_ERR(mmu->device, + "Wait limit reached for IOMMU tlb flush\n"); + break; + } + cpu_relax(); + } + } } } +unlock: /* Release GPU-CPU sync Lock here */ msm_iommu_unlock(); @@ -1742,8 +2014,7 @@ static int kgsl_iommu_default_setstate(struct kgsl_mmu *mmu, * @ctx_id - The context ID of the IOMMU ctx * @reg - The register for which address is required * - * Return - The number of iommu units which is also the number of register - * mapped descriptor arrays which the out parameter will have + * Return - The gpu address of register which can be used in type3 packet */ static unsigned int kgsl_iommu_get_reg_gpuaddr(struct kgsl_mmu *mmu, int iommu_unit, int ctx_id, int reg) @@ -1752,10 +2023,25 @@ static unsigned int kgsl_iommu_get_reg_gpuaddr(struct kgsl_mmu *mmu, if (KGSL_IOMMU_GLOBAL_BASE == reg) return iommu->iommu_units[iommu_unit].reg_map.gpuaddr; - else + + if (iommu->iommu_reg_list[reg].ctx_reg) return iommu->iommu_units[iommu_unit].reg_map.gpuaddr + iommu->iommu_reg_list[reg].reg_offset + (ctx_id << KGSL_IOMMU_CTX_SHIFT) + iommu->ctx_offset; + else + return iommu->iommu_units[iommu_unit].reg_map.gpuaddr + + iommu->iommu_reg_list[reg].reg_offset; +} +/* + * kgsl_iommu_hw_halt_supported - Returns whether IOMMU halt command is + * supported + * @mmu - Pointer to mmu structure + * @iommu_unit - The iommu unit for which the property is requested + */ +static int kgsl_iommu_hw_halt_supported(struct kgsl_mmu *mmu, int iommu_unit) +{ + struct kgsl_iommu *iommu = mmu->priv; + return iommu->iommu_units[iommu_unit].iommu_halt_enable; } static int kgsl_iommu_get_num_iommu_units(struct kgsl_mmu *mmu) @@ -1772,20 +2058,23 @@ struct kgsl_mmu_ops iommu_ops = { .mmu_setstate = kgsl_iommu_setstate, .mmu_device_setstate = kgsl_iommu_default_setstate, .mmu_pagefault = NULL, + .mmu_pagefault_resume = kgsl_iommu_pagefault_resume, .mmu_get_current_ptbase = kgsl_iommu_get_current_ptbase, .mmu_enable_clk = kgsl_iommu_enable_clk, .mmu_disable_clk = kgsl_iommu_disable_clk, .mmu_disable_clk_on_ts = kgsl_iommu_disable_clk_on_ts, - .mmu_get_pt_lsb = kgsl_iommu_get_pt_lsb, + .mmu_get_default_ttbr0 = kgsl_iommu_get_default_ttbr0, .mmu_get_reg_gpuaddr = kgsl_iommu_get_reg_gpuaddr, + .mmu_get_reg_ahbaddr = kgsl_iommu_get_reg_ahbaddr, .mmu_get_num_iommu_units = kgsl_iommu_get_num_iommu_units, .mmu_pt_equal = kgsl_iommu_pt_equal, .mmu_get_pt_base_addr = kgsl_iommu_get_pt_base_addr, - .mmu_sync_lock = kgsl_iommu_sync_lock, - .mmu_sync_unlock = kgsl_iommu_sync_unlock, + .mmu_hw_halt_supported = kgsl_iommu_hw_halt_supported, /* These callbacks will be set on some chipsets */ .mmu_setup_pt = NULL, .mmu_cleanup_pt = NULL, + .mmu_sync_lock = kgsl_iommu_sync_lock, + .mmu_sync_unlock = kgsl_iommu_sync_unlock, }; struct kgsl_mmu_pt_ops iommu_pt_ops = { diff --git a/drivers/gpu/msm/kgsl_iommu.h b/drivers/gpu/msm/kgsl_iommu.h index 2d681fcaacf..7dca40e2c98 100644 --- a/drivers/gpu/msm/kgsl_iommu.h +++ b/drivers/gpu/msm/kgsl_iommu.h @@ -15,8 +15,8 @@ #include -#define KGSL_IOMMU_CTX_OFFSET_V1 0 -#define KGSL_IOMMU_CTX_OFFSET_V2 0x8000 +#define KGSL_IOMMU_CTX_OFFSET_V0 0 +#define KGSL_IOMMU_CTX_OFFSET_V1 0x8000 #define KGSL_IOMMU_CTX_SHIFT 12 /* TLBLKCR fields */ @@ -46,8 +46,27 @@ #define KGSL_IOMMU_V1_FSYNR0_WNR_MASK 0x00000001 #define KGSL_IOMMU_V1_FSYNR0_WNR_SHIFT 4 +/* TTBR0 register fields */ +#ifdef CONFIG_ARM_LPAE +#define KGSL_IOMMU_CTX_TTBR0_ADDR_MASK_LPAE 0x000000FFFFFFFFE0ULL +#define KGSL_IOMMU_CTX_TTBR0_ADDR_MASK KGSL_IOMMU_CTX_TTBR0_ADDR_MASK_LPAE +#else +#define KGSL_IOMMU_CTX_TTBR0_ADDR_MASK 0xFFFFC000 +#endif + +/* TLBSTATUS register fields */ +#define KGSL_IOMMU_CTX_TLBSTATUS_SACTIVE BIT(0) + +/* IMPLDEF_MICRO_MMU_CTRL register fields */ +#define KGSL_IOMMU_IMPLDEF_MICRO_MMU_CTRL_HALT BIT(2) +#define KGSL_IOMMU_IMPLDEF_MICRO_MMU_CTRL_IDLE BIT(3) + +/* SCTLR fields */ +#define KGSL_IOMMU_SCTLR_HUPCF_SHIFT 8 + enum kgsl_iommu_reg_map { KGSL_IOMMU_GLOBAL_BASE = 0, + KGSL_IOMMU_CTX_SCTLR, KGSL_IOMMU_CTX_TTBR0, KGSL_IOMMU_CTX_TTBR1, KGSL_IOMMU_CTX_FSR, @@ -57,13 +76,15 @@ enum kgsl_iommu_reg_map { KGSL_IOMMU_CTX_V2PUR, KGSL_IOMMU_CTX_FSYNR0, KGSL_IOMMU_CTX_FSYNR1, + KGSL_IOMMU_CTX_TLBSYNC, + KGSL_IOMMU_CTX_TLBSTATUS, + KGSL_IOMMU_IMPLDEF_MICRO_MMU_CTRL, KGSL_IOMMU_REG_MAX }; struct kgsl_iommu_register_list { unsigned int reg_offset; - unsigned int reg_mask; - unsigned int reg_shift; + int ctx_reg; }; /* @@ -76,6 +97,20 @@ struct kgsl_iommu_register_list { #define KGSL_IOMMU_MAX_DEVS_PER_UNIT 2 /* Macros to read/write IOMMU registers */ +#define KGSL_IOMMU_SET_CTX_REG_LL(iommu, iommu_unit, ctx, REG, val) \ + writell_relaxed(val, \ + iommu_unit->reg_map.hostptr + \ + iommu->iommu_reg_list[KGSL_IOMMU_CTX_##REG].reg_offset +\ + (ctx << KGSL_IOMMU_CTX_SHIFT) + \ + iommu->ctx_offset) + +#define KGSL_IOMMU_GET_CTX_REG_LL(iommu, iommu_unit, ctx, REG) \ + readl_relaxed( \ + iommu_unit->reg_map.hostptr + \ + iommu->iommu_reg_list[KGSL_IOMMU_CTX_##REG].reg_offset +\ + (ctx << KGSL_IOMMU_CTX_SHIFT) + \ + iommu->ctx_offset) + #define KGSL_IOMMU_SET_CTX_REG(iommu, iommu_unit, ctx, REG, val) \ writel_relaxed(val, \ iommu_unit->reg_map.hostptr + \ @@ -91,10 +126,8 @@ struct kgsl_iommu_register_list { iommu->ctx_offset) /* Gets the lsb value of pagetable */ -#define KGSL_IOMMMU_PT_LSB(iommu, pt_val) \ - (pt_val & \ - ~(iommu->iommu_reg_list[KGSL_IOMMU_CTX_TTBR0].reg_mask << \ - iommu->iommu_reg_list[KGSL_IOMMU_CTX_TTBR0].reg_shift)) +#define KGSL_IOMMMU_PT_LSB(iommu, pt_val) \ + (pt_val & ~(KGSL_IOMMU_CTX_TTBR0_ADDR_MASK)) /* offset at which a nop command is placed in setstate_memory */ #define KGSL_IOMMU_SETSTATE_NOP_OFFSET 1024 @@ -104,8 +137,7 @@ struct kgsl_iommu_register_list { * @dev: Device pointer to iommu context * @attached: Indicates whether this iommu context is presently attached to * a pagetable/domain or not - * @pt_lsb: The LSB of IOMMU_TTBR0 register which is the pagetable - * register + * @default_ttbr0: The TTBR0 value set by iommu driver on start up * @ctx_id: This iommu units context id. It can be either 0 or 1 * @clk_enabled: If set indicates that iommu clocks of this iommu context * are on, else the clocks are off @@ -115,7 +147,7 @@ struct kgsl_iommu_register_list { struct kgsl_iommu_device { struct device *dev; bool attached; - unsigned int pt_lsb; + phys_addr_t default_ttbr0; enum kgsl_iommu_context_id ctx_id; bool clk_enabled; struct kgsl_device *kgsldev; @@ -130,11 +162,18 @@ struct kgsl_iommu_device { * @dev_count: Number of IOMMU contexts that are valid in the previous feild * @reg_map: Memory descriptor which holds the mapped address of this IOMMU * units register range + * @ahb_base - The base address from where IOMMU registers can be accesed from + * ahb bus + * @iommu_halt_enable: Valid only on IOMMU-v1, when set indicates that the iommu + * unit supports halting of the IOMMU, which can be enabled while programming + * the IOMMU registers for synchronization */ struct kgsl_iommu_unit { struct kgsl_iommu_device dev[KGSL_IOMMU_MAX_DEVS_PER_UNIT]; unsigned int dev_count; struct kgsl_memdesc reg_map; + unsigned int ahb_base; + int iommu_halt_enable; }; /* @@ -155,6 +194,8 @@ struct kgsl_iommu_unit { * IOMMU registers * @sync_lock_desc: GPU Memory descriptor for the memory containing the * spinlocks + * @sync_lock_offset - The page offset within a page at which the sync + * variables are located * @sync_lock_initialized: True if the sync_lock feature is enabled */ struct kgsl_iommu { @@ -167,6 +208,7 @@ struct kgsl_iommu { struct kgsl_iommu_register_list *iommu_reg_list; struct remote_iommu_petersons_spinlock *sync_lock_vars; struct kgsl_memdesc sync_lock_desc; + unsigned int sync_lock_offset; bool sync_lock_initialized; }; diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c index ea127d266e1..1910a46e995 100644 --- a/drivers/gpu/msm/kgsl_mmu.c +++ b/drivers/gpu/msm/kgsl_mmu.c @@ -23,6 +23,7 @@ #include "kgsl.h" #include "kgsl_mmu.h" +#include "kgsl_gpummu.h" #include "kgsl_device.h" #include "kgsl_sharedmem.h" #include "adreno.h" @@ -68,8 +69,10 @@ static int kgsl_setup_pt(struct kgsl_pagetable *pt) device = kgsl_driver.devp[KGSL_DEVICE_3D0]; if (device->mmu.mmu_ops->mmu_setup_pt != NULL) { status = device->mmu.mmu_ops->mmu_setup_pt(&device->mmu, pt); - if (status) + if (status) { + i = KGSL_DEVICE_MAX - 1; goto error_pt; + } } return status; error_pt: @@ -101,7 +104,7 @@ static void kgsl_destroy_pagetable(struct kref *kref) if (pagetable->pool) gen_pool_destroy(pagetable->pool); - pagetable->pt_ops->mmu_destroy_pagetable(pagetable->priv); + pagetable->pt_ops->mmu_destroy_pagetable(pagetable); kfree(pagetable); } @@ -120,10 +123,12 @@ kgsl_get_pagetable(unsigned long name) spin_lock_irqsave(&kgsl_driver.ptlock, flags); list_for_each_entry(pt, &kgsl_driver.pagetable_list, list) { - if (pt->name == name) { - ret = pt; - kref_get(&ret->refcount); - break; + if (kref_get_unless_zero(&pt->refcount)) { + if (pt->name == name) { + ret = pt; + break; + } + kref_put(&pt->refcount, kgsl_destroy_pagetable); } } @@ -191,7 +196,7 @@ sysfs_show_va_range(struct kobject *kobj, if (pt) { ret += snprintf(buf, PAGE_SIZE, "0x%x\n", - kgsl_mmu_get_ptsize()); + kgsl_mmu_get_ptsize(pt->mmu)); } kgsl_put_pagetable(pt); @@ -311,7 +316,7 @@ pagetable_add_sysfs_objects(struct kgsl_pagetable *pagetable) } int -kgsl_mmu_get_ptname_from_ptbase(struct kgsl_mmu *mmu, unsigned int pt_base) +kgsl_mmu_get_ptname_from_ptbase(struct kgsl_mmu *mmu, phys_addr_t pt_base) { struct kgsl_pagetable *pt; int ptid = -1; @@ -320,9 +325,13 @@ kgsl_mmu_get_ptname_from_ptbase(struct kgsl_mmu *mmu, unsigned int pt_base) return KGSL_MMU_GLOBAL_PT; spin_lock(&kgsl_driver.ptlock); list_for_each_entry(pt, &kgsl_driver.pagetable_list, list) { - if (mmu->mmu_ops->mmu_pt_equal(mmu, pt, pt_base)) { - ptid = (int) pt->name; - break; + if (kref_get_unless_zero(&pt->refcount)) { + if (mmu->mmu_ops->mmu_pt_equal(mmu, pt, pt_base)) { + ptid = (int) pt->name; + kref_put(&pt->refcount, kgsl_destroy_pagetable); + break; + } + kref_put(&pt->refcount, kgsl_destroy_pagetable); } } spin_unlock(&kgsl_driver.ptlock); @@ -332,7 +341,7 @@ kgsl_mmu_get_ptname_from_ptbase(struct kgsl_mmu *mmu, unsigned int pt_base) EXPORT_SYMBOL(kgsl_mmu_get_ptname_from_ptbase); unsigned int -kgsl_mmu_log_fault_addr(struct kgsl_mmu *mmu, unsigned int pt_base, +kgsl_mmu_log_fault_addr(struct kgsl_mmu *mmu, phys_addr_t pt_base, unsigned int addr) { struct kgsl_pagetable *pt; @@ -342,16 +351,23 @@ kgsl_mmu_log_fault_addr(struct kgsl_mmu *mmu, unsigned int pt_base, return KGSL_MMU_GLOBAL_PT; spin_lock(&kgsl_driver.ptlock); list_for_each_entry(pt, &kgsl_driver.pagetable_list, list) { - if (mmu->mmu_ops->mmu_pt_equal(mmu, pt, pt_base)) { - if ((addr & (PAGE_SIZE-1)) == pt->fault_addr) { - ret = 1; - break; - } else { - pt->fault_addr = (addr & (PAGE_SIZE-1)); - ret = 0; - break; + if (kref_get_unless_zero(&pt->refcount)) { + if (mmu->mmu_ops->mmu_pt_equal(mmu, pt, pt_base)) { + if ((addr & ~(PAGE_SIZE-1)) == pt->fault_addr) { + ret = 1; + kref_put(&pt->refcount, + kgsl_destroy_pagetable); + break; + } else { + pt->fault_addr = + (addr & ~(PAGE_SIZE-1)); + ret = 0; + kref_put(&pt->refcount, + kgsl_destroy_pagetable); + break; + } } - + kref_put(&pt->refcount, kgsl_destroy_pagetable); } } spin_unlock(&kgsl_driver.ptlock); @@ -369,7 +385,7 @@ int kgsl_mmu_init(struct kgsl_device *device) status = kgsl_allocate_contiguous(&mmu->setstate_memory, PAGE_SIZE); if (status) return status; - kgsl_sharedmem_set(&mmu->setstate_memory, 0, 0, + kgsl_sharedmem_set(device, &mmu->setstate_memory, 0, 0, mmu->setstate_memory.size); if (KGSL_MMU_TYPE_NONE == kgsl_mmu_type) { @@ -407,7 +423,8 @@ EXPORT_SYMBOL(kgsl_mmu_start); static void mh_axi_error(struct kgsl_device *device, const char* type) { - unsigned int reg, gpu_err, phys_err, pt_base; + unsigned int reg, gpu_err, phys_err; + phys_addr_t pt_base; kgsl_regread(device, MH_AXI_ERROR, ®); pt_base = kgsl_mmu_get_current_ptbase(&device->mmu); @@ -420,8 +437,8 @@ static void mh_axi_error(struct kgsl_device *device, const char* type) kgsl_regwrite(device, MH_DEBUG_CTRL, 45); kgsl_regread(device, MH_DEBUG_DATA, &phys_err); KGSL_MEM_CRIT(device, - "axi %s error: %08x pt %08x gpu %08x phys %08x\n", - type, reg, pt_base, gpu_err, phys_err); + "axi %s error: %08x pt %pa gpu %08x phys %08x\n", + type, reg, &pt_base, gpu_err, phys_err); } void kgsl_mh_intrcallback(struct kgsl_device *device) @@ -442,7 +459,8 @@ void kgsl_mh_intrcallback(struct kgsl_device *device) } EXPORT_SYMBOL(kgsl_mh_intrcallback); -static struct kgsl_pagetable *kgsl_mmu_createpagetableobject( +static struct kgsl_pagetable * +kgsl_mmu_createpagetableobject(struct kgsl_mmu *mmu, unsigned int name) { int status = 0; @@ -461,8 +479,8 @@ static struct kgsl_pagetable *kgsl_mmu_createpagetableobject( spin_lock_init(&pagetable->lock); - ptsize = kgsl_mmu_get_ptsize(); - + ptsize = kgsl_mmu_get_ptsize(mmu); + pagetable->mmu = mmu; pagetable->name = name; pagetable->max_entries = KGSL_PAGETABLE_ENTRIES(ptsize); pagetable->fault_addr = 0xFFFFFFFF; @@ -495,7 +513,7 @@ static struct kgsl_pagetable *kgsl_mmu_createpagetableobject( goto err_kgsl_pool; } - if (gen_pool_add(pagetable->pool, kgsl_mmu_get_base_addr(), + if (gen_pool_add(pagetable->pool, kgsl_mmu_get_base_addr(mmu), ptsize, -1)) { KGSL_CORE_ERR("gen_pool_add failed\n"); goto err_pool; @@ -524,7 +542,7 @@ static struct kgsl_pagetable *kgsl_mmu_createpagetableobject( return pagetable; err_mmu_create: - pagetable->pt_ops->mmu_destroy_pagetable(pagetable->priv); + pagetable->pt_ops->mmu_destroy_pagetable(pagetable); err_pool: gen_pool_destroy(pagetable->pool); err_kgsl_pool: @@ -536,20 +554,21 @@ static struct kgsl_pagetable *kgsl_mmu_createpagetableobject( return NULL; } -struct kgsl_pagetable *kgsl_mmu_getpagetable(unsigned long name) +struct kgsl_pagetable *kgsl_mmu_getpagetable(struct kgsl_mmu *mmu, + unsigned long name) { struct kgsl_pagetable *pt; if (KGSL_MMU_TYPE_NONE == kgsl_mmu_type) return (void *)(-1); - if (!kgsl_mmu_is_perprocess()) + if (!kgsl_mmu_is_perprocess(mmu)) name = KGSL_MMU_GLOBAL_PT; pt = kgsl_get_pagetable(name); if (pt == NULL) - pt = kgsl_mmu_createpagetableobject(name); + pt = kgsl_mmu_createpagetableobject(mmu, name); return pt; } @@ -608,15 +627,20 @@ void kgsl_mh_start(struct kgsl_device *device) } EXPORT_SYMBOL(kgsl_mh_start); +/** + * kgsl_mmu_get_gpuaddr - Assign a memdesc with a gpuadddr from the gen pool + * @pagetable - pagetable whose pool is to be used + * @memdesc - memdesc to which gpuaddr is assigned + * + * returns - 0 on success else error code + */ int -kgsl_mmu_map(struct kgsl_pagetable *pagetable, - struct kgsl_memdesc *memdesc) +kgsl_mmu_get_gpuaddr(struct kgsl_pagetable *pagetable, + struct kgsl_memdesc *memdesc) { - int ret; struct gen_pool *pool = NULL; int size; int page_align = ilog2(PAGE_SIZE); - unsigned int protflags = kgsl_memdesc_protflags(memdesc); if (kgsl_mmu_type == KGSL_MMU_TYPE_NONE) { if (memdesc->sglen == 1) { @@ -688,16 +712,38 @@ kgsl_mmu_map(struct kgsl_pagetable *pagetable, return -ENOMEM; } } + return 0; +} +EXPORT_SYMBOL(kgsl_mmu_get_gpuaddr); + +int +kgsl_mmu_map(struct kgsl_pagetable *pagetable, + struct kgsl_memdesc *memdesc) +{ + int ret = 0; + int size; + unsigned int protflags = kgsl_memdesc_protflags(memdesc); + + if (!memdesc->gpuaddr) + return -EINVAL; + /* Only global mappings should be mapped multiple times */ + if (!kgsl_memdesc_is_global(memdesc) && + (KGSL_MEMDESC_MAPPED & memdesc->priv)) + return -EINVAL; + /* Add space for the guard page when allocating the mmu VA. */ + size = memdesc->size; + if (kgsl_memdesc_has_guard_page(memdesc)) + size += PAGE_SIZE; if (KGSL_MMU_TYPE_IOMMU != kgsl_mmu_get_mmutype()) spin_lock(&pagetable->lock); - ret = pagetable->pt_ops->mmu_map(pagetable->priv, memdesc, protflags, + ret = pagetable->pt_ops->mmu_map(pagetable, memdesc, protflags, &pagetable->tlb_flags); if (KGSL_MMU_TYPE_IOMMU == kgsl_mmu_get_mmutype()) spin_lock(&pagetable->lock); if (ret) - goto err_free_gpuaddr; + goto done; /* Keep track of the statistics for the sysfs files */ @@ -708,34 +754,76 @@ kgsl_mmu_map(struct kgsl_pagetable *pagetable, pagetable->stats.max_mapped); spin_unlock(&pagetable->lock); + memdesc->priv |= KGSL_MEMDESC_MAPPED; return 0; -err_free_gpuaddr: +done: spin_unlock(&pagetable->lock); - if (pool) - gen_pool_free(pool, memdesc->gpuaddr, size); - memdesc->gpuaddr = 0; return ret; } EXPORT_SYMBOL(kgsl_mmu_map); +/** + * kgsl_mmu_put_gpuaddr - Free a gpuaddress from memory pool + * @pagetable - pagetable whose pool memory is freed from + * @memdesc - memdesc whose gpuaddress is freed + * + * returns - 0 on success else error code + */ int -kgsl_mmu_unmap(struct kgsl_pagetable *pagetable, - struct kgsl_memdesc *memdesc) +kgsl_mmu_put_gpuaddr(struct kgsl_pagetable *pagetable, + struct kgsl_memdesc *memdesc) { struct gen_pool *pool; int size; - unsigned int start_addr = 0; - unsigned int end_addr = 0; if (memdesc->size == 0 || memdesc->gpuaddr == 0) return 0; - if (kgsl_mmu_type == KGSL_MMU_TYPE_NONE) { + if (kgsl_mmu_type == KGSL_MMU_TYPE_NONE) + goto done; + + /* Add space for the guard page when freeing the mmu VA. */ + size = memdesc->size; + if (kgsl_memdesc_has_guard_page(memdesc)) + size += PAGE_SIZE; + + pool = pagetable->pool; + + if (KGSL_MMU_TYPE_IOMMU == kgsl_mmu_get_mmutype()) { + if (kgsl_memdesc_is_global(memdesc)) + pool = pagetable->kgsl_pool; + else if (kgsl_memdesc_use_cpu_map(memdesc)) + pool = NULL; + } + if (pool) + gen_pool_free(pool, memdesc->gpuaddr, size); + /* + * Don't clear the gpuaddr on global mappings because they + * may be in use by other pagetables + */ +done: + if (!kgsl_memdesc_is_global(memdesc)) memdesc->gpuaddr = 0; + return 0; +} +EXPORT_SYMBOL(kgsl_mmu_put_gpuaddr); + +int +kgsl_mmu_unmap(struct kgsl_pagetable *pagetable, + struct kgsl_memdesc *memdesc) +{ + int size; + unsigned int start_addr = 0; + unsigned int end_addr = 0; + + if (memdesc->size == 0 || memdesc->gpuaddr == 0 || + !(KGSL_MEMDESC_MAPPED & memdesc->priv)) + return -EINVAL; + + if (kgsl_mmu_type == KGSL_MMU_TYPE_NONE) return 0; - } /* Add space for the guard page when freeing the mmu VA. */ size = memdesc->size; @@ -747,7 +835,7 @@ kgsl_mmu_unmap(struct kgsl_pagetable *pagetable, if (KGSL_MMU_TYPE_IOMMU != kgsl_mmu_get_mmutype()) spin_lock(&pagetable->lock); - pagetable->pt_ops->mmu_unmap(pagetable->priv, memdesc, + pagetable->pt_ops->mmu_unmap(pagetable, memdesc, &pagetable->tlb_flags); /* If buffer is unmapped 0 fault addr */ @@ -762,24 +850,8 @@ kgsl_mmu_unmap(struct kgsl_pagetable *pagetable, pagetable->stats.mapped -= size; spin_unlock(&pagetable->lock); - - pool = pagetable->pool; - - if (KGSL_MMU_TYPE_IOMMU == kgsl_mmu_get_mmutype()) { - if (kgsl_memdesc_is_global(memdesc)) - pool = pagetable->kgsl_pool; - else if (kgsl_memdesc_use_cpu_map(memdesc)) - pool = NULL; - } - if (pool) - gen_pool_free(pool, memdesc->gpuaddr, size); - - /* - * Don't clear the gpuaddr on global mappings because they - * may be in use by other pagetables - */ if (!kgsl_memdesc_is_global(memdesc)) - memdesc->gpuaddr = 0; + memdesc->priv &= ~KGSL_MEMDESC_MAPPED; return 0; } EXPORT_SYMBOL(kgsl_mmu_unmap); @@ -800,20 +872,24 @@ int kgsl_mmu_map_global(struct kgsl_pagetable *pagetable, gpuaddr = memdesc->gpuaddr; memdesc->priv |= KGSL_MEMDESC_GLOBAL; - result = kgsl_mmu_map(pagetable, memdesc); + result = kgsl_mmu_get_gpuaddr(pagetable, memdesc); if (result) goto error; + result = kgsl_mmu_map(pagetable, memdesc); + if (result) + goto error_put_gpuaddr; /*global mappings must have the same gpu address in all pagetables*/ if (gpuaddr && gpuaddr != memdesc->gpuaddr) { - KGSL_CORE_ERR("pt %p addr mismatch phys 0x%08x" - "gpu 0x%0x 0x%08x", pagetable, memdesc->physaddr, - gpuaddr, memdesc->gpuaddr); + KGSL_CORE_ERR("pt %p addr mismatch phys %pa gpu 0x%0x 0x%08x", + pagetable, &memdesc->physaddr, gpuaddr, memdesc->gpuaddr); goto error_unmap; } return result; error_unmap: kgsl_mmu_unmap(pagetable, memdesc); +error_put_gpuaddr: + kgsl_mmu_put_gpuaddr(pagetable, memdesc); error: return result; } @@ -901,15 +977,16 @@ void kgsl_mmu_set_mmutype(char *mmutype) } EXPORT_SYMBOL(kgsl_mmu_set_mmutype); -int kgsl_mmu_gpuaddr_in_range(unsigned int gpuaddr) +int kgsl_mmu_gpuaddr_in_range(struct kgsl_pagetable *pt, unsigned int gpuaddr) { if (KGSL_MMU_TYPE_NONE == kgsl_mmu_type) return 1; - if (gpuaddr >= kgsl_mmu_get_base_addr() && - gpuaddr < kgsl_mmu_get_base_addr() + kgsl_mmu_get_ptsize()) + if (gpuaddr >= kgsl_mmu_get_base_addr(pt->mmu) && + gpuaddr < kgsl_mmu_get_base_addr(pt->mmu) + + kgsl_mmu_get_ptsize(pt->mmu)) return 1; if (kgsl_mmu_get_mmutype() == KGSL_MMU_TYPE_IOMMU - && kgsl_mmu_is_perprocess()) + && kgsl_mmu_is_perprocess(pt->mmu)) return (gpuaddr > 0 && gpuaddr < TASK_SIZE); return 0; } diff --git a/drivers/gpu/msm/kgsl_mmu.h b/drivers/gpu/msm/kgsl_mmu.h index fe1b2ee58ea..de6bafcf7ae 100644 --- a/drivers/gpu/msm/kgsl_mmu.h +++ b/drivers/gpu/msm/kgsl_mmu.h @@ -14,16 +14,27 @@ #define __KGSL_MMU_H #include - +#include "kgsl_iommu.h" /* * These defines control the address range for allocations that * are mapped into all pagetables. */ +#ifndef CONFIG_MSM_KGSL_CFF_DUMP #define KGSL_IOMMU_GLOBAL_MEM_BASE 0xf8000000 +#else +#define KGSL_IOMMU_GLOBAL_MEM_BASE (0x09F00000 - SZ_4M) +#endif #define KGSL_IOMMU_GLOBAL_MEM_SIZE SZ_4M #define KGSL_MMU_ALIGN_MASK (~((1 << PAGE_SHIFT) - 1)) +/* defconfig option for disabling per process pagetables */ +#ifdef CONFIG_KGSL_PER_PROCESS_PAGE_TABLE +#define KGSL_MMU_USE_PER_PROCESS_PT true +#else +#define KGSL_MMU_USE_PER_PROCESS_PT false +#endif + /* Identifier for the global page table */ /* Per process page tables will probably pass in the thread group as an identifier */ @@ -116,6 +127,7 @@ struct kgsl_pagetable { unsigned int tlb_flags; unsigned int fault_addr; void *priv; + struct kgsl_mmu *mmu; }; struct kgsl_mmu; @@ -131,7 +143,9 @@ struct kgsl_mmu_ops { int (*mmu_device_setstate) (struct kgsl_mmu *mmu, uint32_t flags); void (*mmu_pagefault) (struct kgsl_mmu *mmu); - unsigned int (*mmu_get_current_ptbase) + phys_addr_t (*mmu_get_current_ptbase) + (struct kgsl_mmu *mmu); + void (*mmu_pagefault_resume) (struct kgsl_mmu *mmu); void (*mmu_disable_clk_on_ts) (struct kgsl_mmu *mmu, uint32_t ts, bool ts_valid); @@ -139,40 +153,42 @@ struct kgsl_mmu_ops { (struct kgsl_mmu *mmu, int ctx_id); void (*mmu_disable_clk) (struct kgsl_mmu *mmu); - int (*mmu_get_pt_lsb)(struct kgsl_mmu *mmu, + phys_addr_t (*mmu_get_default_ttbr0)(struct kgsl_mmu *mmu, unsigned int unit_id, enum kgsl_iommu_context_id ctx_id); unsigned int (*mmu_get_reg_gpuaddr)(struct kgsl_mmu *mmu, int iommu_unit_num, int ctx_id, int reg); + unsigned int (*mmu_get_reg_ahbaddr)(struct kgsl_mmu *mmu, + int iommu_unit_num, int ctx_id, + enum kgsl_iommu_reg_map reg); int (*mmu_get_num_iommu_units)(struct kgsl_mmu *mmu); int (*mmu_pt_equal) (struct kgsl_mmu *mmu, struct kgsl_pagetable *pt, - unsigned int pt_base); - unsigned int (*mmu_get_pt_base_addr) + phys_addr_t pt_base); + phys_addr_t (*mmu_get_pt_base_addr) (struct kgsl_mmu *mmu, struct kgsl_pagetable *pt); - unsigned int (*mmu_sync_lock) - (struct kgsl_mmu *mmu, - unsigned int *cmds); - unsigned int (*mmu_sync_unlock) - (struct kgsl_mmu *mmu, - unsigned int *cmds); int (*mmu_setup_pt) (struct kgsl_mmu *mmu, struct kgsl_pagetable *pt); void (*mmu_cleanup_pt) (struct kgsl_mmu *mmu, struct kgsl_pagetable *pt); + unsigned int (*mmu_sync_lock) + (struct kgsl_mmu *mmu, unsigned int *cmds); + unsigned int (*mmu_sync_unlock) + (struct kgsl_mmu *mmu, unsigned int *cmds); + int (*mmu_hw_halt_supported)(struct kgsl_mmu *mmu, int iommu_unit_num); }; struct kgsl_mmu_pt_ops { - int (*mmu_map) (void *mmu_pt, + int (*mmu_map) (struct kgsl_pagetable *pt, struct kgsl_memdesc *memdesc, unsigned int protflags, unsigned int *tlb_flags); - int (*mmu_unmap) (void *mmu_pt, + int (*mmu_unmap) (struct kgsl_pagetable *pt, struct kgsl_memdesc *memdesc, unsigned int *tlb_flags); void *(*mmu_create_pagetable) (void); - void (*mmu_destroy_pagetable) (void *pt); + void (*mmu_destroy_pagetable) (struct kgsl_pagetable *); }; #define KGSL_MMU_FLAGS_IOMMU_SYNC BIT(31) @@ -190,15 +206,20 @@ struct kgsl_mmu { struct kgsl_pagetable *hwpagetable; const struct kgsl_mmu_ops *mmu_ops; void *priv; - int fault; + atomic_t fault; + unsigned long pt_base; + unsigned long pt_size; + bool pt_per_process; + bool use_cpu_map; }; -#include "kgsl_gpummu.h" - extern struct kgsl_mmu_ops iommu_ops; extern struct kgsl_mmu_pt_ops iommu_pt_ops; +extern struct kgsl_mmu_ops gpummu_ops; +extern struct kgsl_mmu_pt_ops gpummu_pt_ops; -struct kgsl_pagetable *kgsl_mmu_getpagetable(unsigned long name); +struct kgsl_pagetable *kgsl_mmu_getpagetable(struct kgsl_mmu *, + unsigned long name); void kgsl_mmu_putpagetable(struct kgsl_pagetable *pagetable); void kgsl_mh_start(struct kgsl_device *device); void kgsl_mh_intrcallback(struct kgsl_device *device); @@ -207,17 +228,21 @@ int kgsl_mmu_start(struct kgsl_device *device); int kgsl_mmu_close(struct kgsl_device *device); int kgsl_mmu_map(struct kgsl_pagetable *pagetable, struct kgsl_memdesc *memdesc); +int kgsl_mmu_get_gpuaddr(struct kgsl_pagetable *pagetable, + struct kgsl_memdesc *memdesc); int kgsl_mmu_map_global(struct kgsl_pagetable *pagetable, struct kgsl_memdesc *memdesc); int kgsl_mmu_unmap(struct kgsl_pagetable *pagetable, struct kgsl_memdesc *memdesc); +int kgsl_mmu_put_gpuaddr(struct kgsl_pagetable *pagetable, + struct kgsl_memdesc *memdesc); unsigned int kgsl_virtaddr_to_physaddr(void *virtaddr); int kgsl_setstate(struct kgsl_mmu *mmu, unsigned int context_id, uint32_t flags); int kgsl_mmu_get_ptname_from_ptbase(struct kgsl_mmu *mmu, - unsigned int pt_base); + phys_addr_t pt_base); unsigned int kgsl_mmu_log_fault_addr(struct kgsl_mmu *mmu, - unsigned int pt_base, unsigned int addr); + phys_addr_t pt_base, unsigned int addr); int kgsl_mmu_pt_get_flags(struct kgsl_pagetable *pt, enum kgsl_deviceid id); void kgsl_mmu_ptpool_destroy(void *ptpool); @@ -225,7 +250,7 @@ void *kgsl_mmu_ptpool_init(int entries); int kgsl_mmu_enabled(void); void kgsl_mmu_set_mmutype(char *mmutype); enum kgsl_mmutype kgsl_mmu_get_mmutype(void); -int kgsl_mmu_gpuaddr_in_range(unsigned int gpuaddr); +int kgsl_mmu_gpuaddr_in_range(struct kgsl_pagetable *pt, unsigned int gpuaddr); /* * Static inline functions of MMU that simply call the SMMU specific @@ -233,7 +258,7 @@ int kgsl_mmu_gpuaddr_in_range(unsigned int gpuaddr); * of as wrappers around the actual function */ -static inline unsigned int kgsl_mmu_get_current_ptbase(struct kgsl_mmu *mmu) +static inline phys_addr_t kgsl_mmu_get_current_ptbase(struct kgsl_mmu *mmu) { if (mmu->mmu_ops && mmu->mmu_ops->mmu_get_current_ptbase) return mmu->mmu_ops->mmu_get_current_ptbase(mmu); @@ -268,7 +293,7 @@ static inline void kgsl_mmu_stop(struct kgsl_mmu *mmu) static inline int kgsl_mmu_pt_equal(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt, - unsigned int pt_base) + phys_addr_t pt_base) { if (mmu->mmu_ops && mmu->mmu_ops->mmu_pt_equal) return mmu->mmu_ops->mmu_pt_equal(mmu, pt, pt_base); @@ -276,7 +301,7 @@ static inline int kgsl_mmu_pt_equal(struct kgsl_mmu *mmu, return 1; } -static inline unsigned int kgsl_mmu_get_pt_base_addr(struct kgsl_mmu *mmu, +static inline phys_addr_t kgsl_mmu_get_pt_base_addr(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt) { if (mmu->mmu_ops && mmu->mmu_ops->mmu_get_pt_base_addr) @@ -285,12 +310,13 @@ static inline unsigned int kgsl_mmu_get_pt_base_addr(struct kgsl_mmu *mmu, return 0; } -static inline int kgsl_mmu_get_pt_lsb(struct kgsl_mmu *mmu, +static inline phys_addr_t kgsl_mmu_get_default_ttbr0(struct kgsl_mmu *mmu, unsigned int unit_id, enum kgsl_iommu_context_id ctx_id) { - if (mmu->mmu_ops && mmu->mmu_ops->mmu_get_pt_lsb) - return mmu->mmu_ops->mmu_get_pt_lsb(mmu, unit_id, ctx_id); + if (mmu->mmu_ops && mmu->mmu_ops->mmu_get_default_ttbr0) + return mmu->mmu_ops->mmu_get_default_ttbr0(mmu, unit_id, + ctx_id); else return 0; } @@ -338,30 +364,49 @@ static inline unsigned int kgsl_mmu_get_reg_gpuaddr(struct kgsl_mmu *mmu, return 0; } -static inline int kgsl_mmu_get_num_iommu_units(struct kgsl_mmu *mmu) +/* + * kgsl_mmu_get_reg_ahbaddr() - Calls the mmu specific function pointer to + * return the address that GPU can use to access register + * @mmu: Pointer to the device mmu + * @iommu_unit_num: There can be multiple iommu units used for graphics. + * This parameter is an index to the iommu unit being used + * @ctx_id: The context id within the iommu unit + * @reg: Register whose address is to be returned + * + * Returns the ahb address of reg else 0 + */ +static inline unsigned int kgsl_mmu_get_reg_ahbaddr(struct kgsl_mmu *mmu, + int iommu_unit_num, + int ctx_id, + enum kgsl_iommu_reg_map reg) { - if (mmu->mmu_ops && mmu->mmu_ops->mmu_get_num_iommu_units) - return mmu->mmu_ops->mmu_get_num_iommu_units(mmu); + if (mmu->mmu_ops && mmu->mmu_ops->mmu_get_reg_ahbaddr) + return mmu->mmu_ops->mmu_get_reg_ahbaddr(mmu, iommu_unit_num, + ctx_id, reg); else return 0; } -static inline int kgsl_mmu_sync_lock(struct kgsl_mmu *mmu, - unsigned int *cmds) +static inline int kgsl_mmu_get_num_iommu_units(struct kgsl_mmu *mmu) { - if ((mmu->flags & KGSL_MMU_FLAGS_IOMMU_SYNC) && - mmu->mmu_ops && mmu->mmu_ops->mmu_sync_lock) - return mmu->mmu_ops->mmu_sync_lock(mmu, cmds); + if (mmu->mmu_ops && mmu->mmu_ops->mmu_get_num_iommu_units) + return mmu->mmu_ops->mmu_get_num_iommu_units(mmu); else return 0; } -static inline int kgsl_mmu_sync_unlock(struct kgsl_mmu *mmu, - unsigned int *cmds) +/* + * kgsl_mmu_hw_halt_supported() - Runtime check for iommu hw halt + * @mmu: the mmu + * + * Returns non-zero if the iommu supports hw halt, + * 0 if not. + */ +static inline int kgsl_mmu_hw_halt_supported(struct kgsl_mmu *mmu, + int iommu_unit_num) { - if ((mmu->flags & KGSL_MMU_FLAGS_IOMMU_SYNC) && - mmu->mmu_ops && mmu->mmu_ops->mmu_sync_unlock) - return mmu->mmu_ops->mmu_sync_unlock(mmu, cmds); + if (mmu->mmu_ops && mmu->mmu_ops->mmu_hw_halt_supported) + return mmu->mmu_ops->mmu_hw_halt_supported(mmu, iommu_unit_num); else return 0; } @@ -369,75 +414,71 @@ static inline int kgsl_mmu_sync_unlock(struct kgsl_mmu *mmu, /* * kgsl_mmu_is_perprocess() - Runtime check for per-process * pagetables. + * @mmu: the mmu * - * Returns non-zero if per-process pagetables are enabled, - * 0 if not. + * Returns true if per-process pagetables are enabled, + * false if not. */ -#ifdef CONFIG_KGSL_PER_PROCESS_PAGE_TABLE -static inline int kgsl_mmu_is_perprocess(void) +static inline int kgsl_mmu_is_perprocess(struct kgsl_mmu *mmu) { - - /* We presently do not support per-process for IOMMU-v2 */ - return (kgsl_mmu_get_mmutype() != KGSL_MMU_TYPE_IOMMU) - || msm_soc_version_supports_iommu_v1(); + return mmu->pt_per_process; } -#else -static inline int kgsl_mmu_is_perprocess(void) + +/* + * kgsl_mmu_use_cpu_map() - Runtime check for matching the CPU + * address space on the GPU. + * @mmu: the mmu + * + * Returns true if supported false if not. + */ +static inline int kgsl_mmu_use_cpu_map(struct kgsl_mmu *mmu) { - return 0; + return mmu->use_cpu_map; } -#endif /* * kgsl_mmu_base_addr() - Get gpu virtual address base. + * @mmu: the mmu * * Returns the start address of the allocatable gpu * virtual address space. Other mappings that mirror * the CPU address space are possible outside this range. */ -static inline unsigned int kgsl_mmu_get_base_addr(void) +static inline unsigned int kgsl_mmu_get_base_addr(struct kgsl_mmu *mmu) { - if (KGSL_MMU_TYPE_GPU == kgsl_mmu_get_mmutype() - || !kgsl_mmu_is_perprocess()) - return KGSL_PAGETABLE_BASE; - /* - * This is the start of the kernel address - * space, so allocations from this range will - * never conflict with userpace addresses - */ - return PAGE_OFFSET; + return mmu->pt_base; } /* * kgsl_mmu_get_ptsize() - Get gpu pagetable size + * @mmu: the mmu * * Returns the usable size of the gpu allocatable * address space. */ -static inline unsigned int kgsl_mmu_get_ptsize(void) +static inline unsigned int kgsl_mmu_get_ptsize(struct kgsl_mmu *mmu) { - /* - * For IOMMU per-process pagetables, the allocatable range - * and the kernel global range must both be outside - * the userspace address range. There is a 1Mb gap - * between these address ranges to make overrun - * detection easier. - * For the shared pagetable case use 2GB and because - * mirroring the CPU address space is not possible and - * we're better off with extra room. - */ - enum kgsl_mmutype mmu_type = kgsl_mmu_get_mmutype(); - - if (KGSL_MMU_TYPE_GPU == mmu_type) - return CONFIG_MSM_KGSL_PAGE_TABLE_SIZE; - else if (KGSL_MMU_TYPE_IOMMU == mmu_type) { - if (kgsl_mmu_is_perprocess()) - return KGSL_IOMMU_GLOBAL_MEM_BASE - - kgsl_mmu_get_base_addr() - SZ_1M; - else - return SZ_2G; - } - return 0; + return mmu->pt_size; +} + +static inline int kgsl_mmu_sync_lock(struct kgsl_mmu *mmu, + unsigned int *cmds) +{ + if ((mmu->flags & KGSL_MMU_FLAGS_IOMMU_SYNC) && + mmu->mmu_ops && mmu->mmu_ops->mmu_sync_lock) + return mmu->mmu_ops->mmu_sync_lock(mmu, cmds); + else + return 0; +} + +static inline int kgsl_mmu_sync_unlock(struct kgsl_mmu *mmu, + unsigned int *cmds) +{ + if ((mmu->flags & KGSL_MMU_FLAGS_IOMMU_SYNC) && + mmu->mmu_ops && mmu->mmu_ops->mmu_sync_unlock) + return mmu->mmu_ops->mmu_sync_unlock(mmu, cmds); + else + return 0; } #endif /* __KGSL_MMU_H */ diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c index 104379718dc..0e7740439f3 100644 --- a/drivers/gpu/msm/kgsl_pwrctrl.c +++ b/drivers/gpu/msm/kgsl_pwrctrl.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. +/* Copyright (c) 2010-2013, The Linux Foundation. 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 and @@ -18,6 +18,7 @@ #include #include #include +#include #include "kgsl.h" #include "kgsl_pwrscale.h" @@ -30,10 +31,19 @@ #define KGSL_PWRFLAGS_AXI_ON 2 #define KGSL_PWRFLAGS_IRQ_ON 3 -#define GPU_SWFI_LATENCY 3 #define UPDATE_BUSY_VAL 1000000 #define UPDATE_BUSY 50 +/* + * Expected delay for post-interrupt processing on A3xx. + * The delay may be longer, gradually increase the delay + * to compensate. If the GPU isn't done by max delay, + * it's working on something other than just the final + * command sequence so stop waiting for it to be idle. + */ +#define INIT_UDELAY 200 +#define MAX_UDELAY 2000 + unsigned long internal_max = 450000000; struct clk_pair { @@ -62,8 +72,17 @@ struct clk_pair clks[KGSL_MAX_CLKS] = { .name = "mem_iface_clk", .map = KGSL_CLK_MEM_IFACE, }, + { + .name = "alt_mem_iface_clk", + .map = KGSL_CLK_ALT_MEM_IFACE, + }, }; +static void kgsl_pwrctrl_clk(struct kgsl_device *device, int state, + int requested_state); +static void kgsl_pwrctrl_axi(struct kgsl_device *device, int state); +static void kgsl_pwrctrl_pwrrail(struct kgsl_device *device, int state); + /* Update the elapsed time at a particular clock level * if the device is active(on_time = true).Otherwise * store it as sleep time. @@ -133,6 +152,16 @@ void kgsl_pwrctrl_pwrlevel_change(struct kgsl_device *device, */ pwr->active_pwrlevel = new_level; + pwrlevel = &pwr->pwrlevels[pwr->active_pwrlevel]; + + if (test_bit(KGSL_PWRFLAGS_AXI_ON, &pwr->power_flags)) { + + if (pwr->pcl) + msm_bus_scale_client_update_request(pwr->pcl, + pwrlevel->bus_freq); + else if (pwr->ebi1_clk) + clk_set_rate(pwr->ebi1_clk, pwrlevel->bus_freq); + } if (test_bit(KGSL_PWRFLAGS_CLK_ON, &pwr->power_flags) || (device->state == KGSL_STATE_NAP)) { @@ -159,16 +188,6 @@ void kgsl_pwrctrl_pwrlevel_change(struct kgsl_device *device, } } - pwrlevel = &pwr->pwrlevels[pwr->active_pwrlevel]; - - if (test_bit(KGSL_PWRFLAGS_AXI_ON, &pwr->power_flags)) { - - if (pwr->pcl) - msm_bus_scale_client_update_request(pwr->pcl, - pwrlevel->bus_freq); - else if (pwr->ebi1_clk) - clk_set_rate(pwr->ebi1_clk, pwrlevel->bus_freq); - } trace_kgsl_pwrlevel(device, pwr->active_pwrlevel, pwrlevel->gpu_freq); } @@ -360,13 +379,13 @@ static int kgsl_pwrctrl_num_pwrlevels_show(struct device *dev, return snprintf(buf, PAGE_SIZE, "%d\n", pwr->num_pwrlevels - 1); } -/* Given a GPU clock value, return the nearest powerlevel */ +/* Given a GPU clock value, return the lowest matching powerlevel */ static int _get_nearest_pwrlevel(struct kgsl_pwrctrl *pwr, unsigned int clock) { int i; - for (i = 0; i < pwr->num_pwrlevels - 1; i++) { + for (i = pwr->num_pwrlevels - 1; i >= 0; i--) { if (abs(pwr->pwrlevels[i].gpu_freq - clock) < 5000000) return i; } @@ -496,14 +515,15 @@ static int kgsl_pwrctrl_gpuclk_show(struct device *dev, internal_max); } -static int kgsl_pwrctrl_pwrnap_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +static int kgsl_pwrctrl_idle_timer_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { char temp[20]; unsigned long val; struct kgsl_device *device = kgsl_device_from_dev(dev); struct kgsl_pwrctrl *pwr; + const long div = 1000/HZ; int rc; if (device == NULL) @@ -518,73 +538,62 @@ static int kgsl_pwrctrl_pwrnap_store(struct device *dev, mutex_lock(&device->mutex); - if (val == 1) - pwr->nap_allowed = true; - else if (val == 0) - pwr->nap_allowed = false; + /* Let the timeout be requested in ms, but convert to jiffies. */ + val /= div; + pwr->interval_timeout = val; mutex_unlock(&device->mutex); return count; } -static int kgsl_pwrctrl_pwrnap_show(struct device *dev, - struct device_attribute *attr, - char *buf) +static int kgsl_pwrctrl_idle_timer_show(struct device *dev, + struct device_attribute *attr, + char *buf) { struct kgsl_device *device = kgsl_device_from_dev(dev); + int mul = 1000/HZ; if (device == NULL) return 0; - return snprintf(buf, PAGE_SIZE, "%d\n", device->pwrctrl.nap_allowed); + /* Show the idle_timeout converted to msec */ + return snprintf(buf, PAGE_SIZE, "%d\n", + device->pwrctrl.interval_timeout * mul); } - -static int kgsl_pwrctrl_idle_timer_store(struct device *dev, +static int kgsl_pwrctrl_pmqos_latency_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { char temp[20]; unsigned long val; struct kgsl_device *device = kgsl_device_from_dev(dev); - struct kgsl_pwrctrl *pwr; - const long div = 1000/HZ; - static unsigned int org_interval_timeout = 1; int rc; if (device == NULL) return 0; - pwr = &device->pwrctrl; snprintf(temp, sizeof(temp), "%.*s", - (int)min(count, sizeof(temp) - 1), buf); - rc = strict_strtoul(temp, 0, &val); + (int)min(count, sizeof(temp) - 1), buf); + rc = kstrtoul(temp, 0, &val); if (rc) return rc; - if (org_interval_timeout == 1) - org_interval_timeout = pwr->interval_timeout; - mutex_lock(&device->mutex); - - /* Let the timeout be requested in ms, but convert to jiffies. */ - val /= div; - if (val >= org_interval_timeout) - pwr->interval_timeout = val; - + device->pwrctrl.pm_qos_latency = val; mutex_unlock(&device->mutex); return count; } -static int kgsl_pwrctrl_idle_timer_show(struct device *dev, - struct device_attribute *attr, - char *buf) +static int kgsl_pwrctrl_pmqos_latency_show(struct device *dev, + struct device_attribute *attr, + char *buf) { struct kgsl_device *device = kgsl_device_from_dev(dev); if (device == NULL) return 0; return snprintf(buf, PAGE_SIZE, "%d\n", - device->pwrctrl.interval_timeout); + device->pwrctrl.pm_qos_latency); } static int kgsl_pwrctrl_gpubusy_show(struct device *dev, @@ -593,7 +602,11 @@ static int kgsl_pwrctrl_gpubusy_show(struct device *dev, { int ret; struct kgsl_device *device = kgsl_device_from_dev(dev); - struct kgsl_clk_stats *clkstats = &device->pwrctrl.clk_stats; + struct kgsl_clk_stats *clkstats; + + if (device == NULL) + return 0; + clkstats = &device->pwrctrl.clk_stats; ret = snprintf(buf, PAGE_SIZE, "%7d %7d\n", clkstats->on_time_old, clkstats->elapsed_old); if (!test_bit(KGSL_PWRFLAGS_AXI_ON, &device->pwrctrl.power_flags)) { @@ -609,10 +622,13 @@ static int kgsl_pwrctrl_gputop_show(struct device *dev, { int ret; struct kgsl_device *device = kgsl_device_from_dev(dev); - struct kgsl_clk_stats *clkstats = &device->pwrctrl.clk_stats; + struct kgsl_clk_stats *clkstats; int i = 0; char *ptr = buf; + if (device == NULL) + return 0; + clkstats = &device->pwrctrl.clk_stats; ret = snprintf(buf, PAGE_SIZE, "%7d %7d ", clkstats->on_time_old, clkstats->elapsed_old); for (i = 0, ptr += ret; i < device->pwrctrl.num_pwrlevels; @@ -661,13 +677,114 @@ static int kgsl_pwrctrl_reset_count_show(struct device *dev, char *buf) { struct kgsl_device *device = kgsl_device_from_dev(dev); + if (device == NULL) + return 0; return snprintf(buf, PAGE_SIZE, "%d\n", device->reset_counter); } +static void __force_on(struct kgsl_device *device, int flag, int on) +{ + if (on) { + switch (flag) { + case KGSL_PWRFLAGS_CLK_ON: + kgsl_pwrctrl_clk(device, KGSL_PWRFLAGS_ON, + KGSL_STATE_ACTIVE); + break; + case KGSL_PWRFLAGS_AXI_ON: + kgsl_pwrctrl_axi(device, KGSL_PWRFLAGS_ON); + break; + case KGSL_PWRFLAGS_POWER_ON: + kgsl_pwrctrl_pwrrail(device, KGSL_PWRFLAGS_ON); + break; + } + set_bit(flag, &device->pwrctrl.ctrl_flags); + } else { + clear_bit(flag, &device->pwrctrl.ctrl_flags); + } +} + +static int __force_on_show(struct device *dev, + struct device_attribute *attr, + char *buf, int flag) +{ + struct kgsl_device *device = kgsl_device_from_dev(dev); + int i = test_bit(flag, &device->pwrctrl.ctrl_flags); + if (device == NULL) + return 0; + return snprintf(buf, PAGE_SIZE, "%d\n", i); +} + +static int __force_on_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count, + int flag) +{ + char temp[20]; + unsigned long val; + struct kgsl_device *device = kgsl_device_from_dev(dev); + int rc; + + if (device == NULL) + return 0; + + snprintf(temp, sizeof(temp), "%.*s", + (int)min(count, sizeof(temp) - 1), buf); + rc = kstrtoul(temp, 0, &val); + if (rc) + return rc; + + mutex_lock(&device->mutex); + __force_on(device, flag, val); + mutex_unlock(&device->mutex); + + return count; +} + +static int kgsl_pwrctrl_force_clk_on_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return __force_on_show(dev, attr, buf, KGSL_PWRFLAGS_CLK_ON); +} + +static int kgsl_pwrctrl_force_clk_on_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + return __force_on_store(dev, attr, buf, count, KGSL_PWRFLAGS_CLK_ON); +} + +static int kgsl_pwrctrl_force_bus_on_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return __force_on_show(dev, attr, buf, KGSL_PWRFLAGS_AXI_ON); +} + +static int kgsl_pwrctrl_force_bus_on_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + return __force_on_store(dev, attr, buf, count, KGSL_PWRFLAGS_AXI_ON); +} + +static int kgsl_pwrctrl_force_rail_on_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return __force_on_show(dev, attr, buf, KGSL_PWRFLAGS_POWER_ON); +} + +static int kgsl_pwrctrl_force_rail_on_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + return __force_on_store(dev, attr, buf, count, KGSL_PWRFLAGS_POWER_ON); +} + DEVICE_ATTR(gpuclk, 0644, kgsl_pwrctrl_gpuclk_show, kgsl_pwrctrl_gpuclk_store); DEVICE_ATTR(max_gpuclk, 0644, kgsl_pwrctrl_max_gpuclk_show, kgsl_pwrctrl_max_gpuclk_store); -DEVICE_ATTR(pwrnap, 0664, kgsl_pwrctrl_pwrnap_show, kgsl_pwrctrl_pwrnap_store); DEVICE_ATTR(idle_timer, 0644, kgsl_pwrctrl_idle_timer_show, kgsl_pwrctrl_idle_timer_store); DEVICE_ATTR(gpubusy, 0444, kgsl_pwrctrl_gpubusy_show, @@ -692,11 +809,22 @@ DEVICE_ATTR(num_pwrlevels, 0444, DEVICE_ATTR(reset_count, 0444, kgsl_pwrctrl_reset_count_show, NULL); +DEVICE_ATTR(pmqos_latency, 0644, + kgsl_pwrctrl_pmqos_latency_show, + kgsl_pwrctrl_pmqos_latency_store); +DEVICE_ATTR(force_clk_on, 0644, + kgsl_pwrctrl_force_clk_on_show, + kgsl_pwrctrl_force_clk_on_store); +DEVICE_ATTR(force_bus_on, 0644, + kgsl_pwrctrl_force_bus_on_show, + kgsl_pwrctrl_force_bus_on_store); +DEVICE_ATTR(force_rail_on, 0644, + kgsl_pwrctrl_force_rail_on_show, + kgsl_pwrctrl_force_rail_on_store); static const struct device_attribute *pwrctrl_attr_list[] = { &dev_attr_gpuclk, &dev_attr_max_gpuclk, - &dev_attr_pwrnap, &dev_attr_idle_timer, &dev_attr_gpubusy, &dev_attr_gputop, @@ -706,6 +834,10 @@ static const struct device_attribute *pwrctrl_attr_list[] = { &dev_attr_thermal_pwrlevel, &dev_attr_num_pwrlevels, &dev_attr_reset_count, + &dev_attr_pmqos_latency, + &dev_attr_force_clk_on, + &dev_attr_force_bus_on, + &dev_attr_force_rail_on, NULL }; @@ -737,6 +869,9 @@ static void update_statistics(struct kgsl_device *device) clkstats->on_time_old = on_time; clkstats->elapsed_old = clkstats->elapsed; clkstats->elapsed = 0; + + trace_kgsl_gpubusy(device, clkstats->on_time_old, + clkstats->elapsed_old); } /* Track the amount of time the gpu is on vs the total system time. * @@ -752,11 +887,15 @@ static void kgsl_pwrctrl_busy_time(struct kgsl_device *device, bool on_time) } } -void kgsl_pwrctrl_clk(struct kgsl_device *device, int state, +static void kgsl_pwrctrl_clk(struct kgsl_device *device, int state, int requested_state) { struct kgsl_pwrctrl *pwr = &device->pwrctrl; int i = 0; + + if (test_bit(KGSL_PWRFLAGS_CLK_ON, &pwr->ctrl_flags)) + return; + if (state == KGSL_PWRFLAGS_OFF) { if (test_and_clear_bit(KGSL_PWRFLAGS_CLK_ON, &pwr->power_flags)) { @@ -767,23 +906,23 @@ void kgsl_pwrctrl_clk(struct kgsl_device *device, int state, /* High latency clock maintenance. */ if ((pwr->pwrlevels[0].gpu_freq > 0) && (requested_state != KGSL_STATE_NAP)) { - clk_set_rate(pwr->grp_clks[0], - pwr->pwrlevels[pwr->num_pwrlevels - 1]. - gpu_freq); for (i = KGSL_MAX_CLKS - 1; i > 0; i--) if (pwr->grp_clks[i]) clk_unprepare(pwr->grp_clks[i]); + clk_set_rate(pwr->grp_clks[0], + pwr->pwrlevels[pwr->num_pwrlevels - 1]. + gpu_freq); } kgsl_pwrctrl_busy_time(device, true); } else if (requested_state == KGSL_STATE_SLEEP) { /* High latency clock maintenance. */ + for (i = KGSL_MAX_CLKS - 1; i > 0; i--) + if (pwr->grp_clks[i]) + clk_unprepare(pwr->grp_clks[i]); if ((pwr->pwrlevels[0].gpu_freq > 0)) clk_set_rate(pwr->grp_clks[0], pwr->pwrlevels[pwr->num_pwrlevels - 1]. gpu_freq); - for (i = KGSL_MAX_CLKS - 1; i > 0; i--) - if (pwr->grp_clks[i]) - clk_unprepare(pwr->grp_clks[i]); } } else if (state == KGSL_PWRFLAGS_ON) { if (!test_and_set_bit(KGSL_PWRFLAGS_CLK_ON, @@ -791,15 +930,14 @@ void kgsl_pwrctrl_clk(struct kgsl_device *device, int state, trace_kgsl_clk(device, state); /* High latency clock maintenance. */ if (device->state != KGSL_STATE_NAP) { - for (i = KGSL_MAX_CLKS - 1; i > 0; i--) - if (pwr->grp_clks[i]) - clk_prepare(pwr->grp_clks[i]); - if (pwr->pwrlevels[0].gpu_freq > 0) clk_set_rate(pwr->grp_clks[0], pwr->pwrlevels [pwr->active_pwrlevel]. gpu_freq); + for (i = KGSL_MAX_CLKS - 1; i > 0; i--) + if (pwr->grp_clks[i]) + clk_prepare(pwr->grp_clks[i]); } /* as last step, enable grp_clk this is to let GPU interrupt to come */ @@ -811,10 +949,13 @@ void kgsl_pwrctrl_clk(struct kgsl_device *device, int state, } } -void kgsl_pwrctrl_axi(struct kgsl_device *device, int state) +static void kgsl_pwrctrl_axi(struct kgsl_device *device, int state) { struct kgsl_pwrctrl *pwr = &device->pwrctrl; + if (test_bit(KGSL_PWRFLAGS_AXI_ON, &pwr->ctrl_flags)) + return; + if (state == KGSL_PWRFLAGS_OFF) { if (test_and_clear_bit(KGSL_PWRFLAGS_AXI_ON, &pwr->power_flags)) { @@ -845,10 +986,13 @@ void kgsl_pwrctrl_axi(struct kgsl_device *device, int state) } } -void kgsl_pwrctrl_pwrrail(struct kgsl_device *device, int state) +static void kgsl_pwrctrl_pwrrail(struct kgsl_device *device, int state) { struct kgsl_pwrctrl *pwr = &device->pwrctrl; + if (test_bit(KGSL_PWRFLAGS_POWER_ON, &pwr->ctrl_flags)) + return; + if (state == KGSL_PWRFLAGS_OFF) { if (test_and_clear_bit(KGSL_PWRFLAGS_POWER_ON, &pwr->power_flags)) { @@ -948,6 +1092,7 @@ int kgsl_pwrctrl_init(struct kgsl_device *device) pwr->active_pwrlevel = pdata->init_level; pwr->default_pwrlevel = pdata->init_level; + pwr->init_pwrlevel = pdata->init_level; for (i = 0; i < pdata->num_levels; i++) { pwr->pwrlevels[i].gpu_freq = (pdata->pwrlevel[i].gpu_freq > 0) ? @@ -977,7 +1122,6 @@ int kgsl_pwrctrl_init(struct kgsl_device *device) pwr->power_flags = 0; - pwr->nap_allowed = pdata->nap_allowed; pwr->idle_needed = pdata->idle_needed; pwr->interval_timeout = pdata->idle_timeout; pwr->strtstp_sleepwake = pdata->strtstp_sleepwake; @@ -1001,9 +1145,13 @@ int kgsl_pwrctrl_init(struct kgsl_device *device) } } + /* Set the power level step multiplier with 1 as the default */ + pwr->step_mul = pdata->step_mul ? pdata->step_mul : 1; + + /* Set the CPU latency to 501usec to allow low latency PC modes */ + pwr->pm_qos_latency = 501; pm_runtime_enable(device->parentdev); - register_early_suspend(&device->display_off); return result; clk_err: @@ -1023,7 +1171,6 @@ void kgsl_pwrctrl_close(struct kgsl_device *device) KGSL_PWR_INFO(device, "close device %d\n", device->id); pm_runtime_disable(device->parentdev); - unregister_early_suspend(&device->display_off); clk_put(pwr->ebi1_clk); @@ -1062,6 +1209,8 @@ void kgsl_pwrctrl_close(struct kgsl_device *device) */ void kgsl_idle_check(struct work_struct *work) { + int delay = INIT_UDELAY; + int requested_state; struct kgsl_device *device = container_of(work, struct kgsl_device, idle_check_ws); WARN_ON(device == NULL); @@ -1073,13 +1222,34 @@ void kgsl_idle_check(struct work_struct *work) kgsl_pwrscale_idle(device); if (device->state == KGSL_STATE_ACTIVE - || device->state == KGSL_STATE_NAP) { - - /* If we failed to sleep then reset the timer and try again */ - if (kgsl_pwrctrl_sleep(device) != 0) { + || device->state == KGSL_STATE_NAP) { + /* + * If no user is explicitly trying to use the GPU + * (active_cnt is zero), then loop with increasing delay, + * waiting for the GPU to become idle. + */ + while (!atomic_read(&device->active_cnt) && + (delay < MAX_UDELAY)) { + requested_state = device->requested_state; + if (!kgsl_pwrctrl_sleep(device)) + break; + /* + * If no new commands have been issued since the + * last interrupt, stay in this loop waiting for + * the GPU to become idle. + */ + if (!device->pwrctrl.irq_last) + break; + kgsl_pwrctrl_request_state(device, requested_state); + mutex_unlock(&device->mutex); + udelay(delay); + delay *= 2; + mutex_lock(&device->mutex); + } - kgsl_pwrctrl_request_state(device, KGSL_STATE_NONE); + kgsl_pwrctrl_request_state(device, KGSL_STATE_NONE); + if (device->state == KGSL_STATE_ACTIVE) { mod_timer(&device->idle_timer, jiffies + device->pwrctrl.interval_timeout); @@ -1093,6 +1263,8 @@ void kgsl_idle_check(struct work_struct *work) kgsl_pwrctrl_busy_time(device, true); device->pwrctrl.clk_stats.no_nap_cnt = 0; } + } else { + device->pwrctrl.irq_last = 0; } } @@ -1106,8 +1278,7 @@ void kgsl_timer(unsigned long data) KGSL_PWR_INFO(device, "idle timer expired device %d\n", device->id); if (device->requested_state != KGSL_STATE_SUSPEND) { - if (device->pwrctrl.restore_slumber || - device->pwrctrl.strtstp_sleepwake) + if (device->pwrctrl.strtstp_sleepwake) kgsl_pwrctrl_request_state(device, KGSL_STATE_SLUMBER); else kgsl_pwrctrl_request_state(device, KGSL_STATE_SLEEP); @@ -1116,6 +1287,11 @@ void kgsl_timer(unsigned long data) } } +bool kgsl_pwrctrl_isenabled(struct kgsl_device *device) +{ + struct kgsl_pwrctrl *pwr = &device->pwrctrl; + return (test_bit(KGSL_PWRFLAGS_CLK_ON, &pwr->power_flags) != 0); +} /** * kgsl_pre_hwaccess - Enforce preconditions for touching registers @@ -1132,7 +1308,7 @@ void kgsl_pre_hwaccess(struct kgsl_device *device) /* In order to touch a register you must hold the device mutex...*/ BUG_ON(!mutex_is_locked(&device->mutex)); /* and have the clock on! */ - BUG_ON(!test_bit(KGSL_PWRFLAGS_CLK_ON, &device->pwrctrl.power_flags)); + BUG_ON(!kgsl_pwrctrl_isenabled(device)); } EXPORT_SYMBOL(kgsl_pre_hwaccess); @@ -1184,7 +1360,7 @@ _sleep(struct kgsl_device *device) _sleep_accounting(device); kgsl_pwrctrl_clk(device, KGSL_PWRFLAGS_OFF, KGSL_STATE_SLEEP); kgsl_pwrctrl_set_state(device, KGSL_STATE_SLEEP); - pm_qos_update_request(&device->pm_qos_req_dma, + pm_qos_update_request(&device->pwrctrl.pm_qos_req_dma, PM_QOS_DEFAULT_VALUE); break; case KGSL_STATE_SLEEP: @@ -1220,7 +1396,7 @@ _slumber(struct kgsl_device *device) device->ftbl->stop(device); _sleep_accounting(device); kgsl_pwrctrl_set_state(device, KGSL_STATE_SLUMBER); - pm_qos_update_request(&device->pm_qos_req_dma, + pm_qos_update_request(&device->pwrctrl.pm_qos_req_dma, PM_QOS_DEFAULT_VALUE); break; case KGSL_STATE_SLUMBER: @@ -1305,8 +1481,8 @@ int kgsl_pwrctrl_wake(struct kgsl_device *device) /* Enable state before turning on irq */ kgsl_pwrctrl_set_state(device, KGSL_STATE_ACTIVE); kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_ON); - pm_qos_update_request(&device->pm_qos_req_dma, - GPU_SWFI_LATENCY); + pm_qos_update_request(&device->pwrctrl.pm_qos_req_dma, + device->pwrctrl.pm_qos_latency); case KGSL_STATE_ACTIVE: kgsl_pwrctrl_request_state(device, KGSL_STATE_NONE); break; @@ -1323,8 +1499,10 @@ EXPORT_SYMBOL(kgsl_pwrctrl_wake); void kgsl_pwrctrl_enable(struct kgsl_device *device) { + struct kgsl_pwrctrl *pwr = &device->pwrctrl; /* Order pwrrail/clk sequence based upon platform */ kgsl_pwrctrl_pwrrail(device, KGSL_PWRFLAGS_ON); + kgsl_pwrctrl_pwrlevel_change(device, pwr->default_pwrlevel); kgsl_pwrctrl_clk(device, KGSL_PWRFLAGS_ON, KGSL_STATE_ACTIVE); kgsl_pwrctrl_axi(device, KGSL_PWRFLAGS_ON); } @@ -1458,39 +1636,54 @@ void kgsl_active_count_put(struct kgsl_device *device) kgsl_pwrscale_idle(device); if (atomic_dec_and_test(&device->active_cnt)) { - INIT_COMPLETION(device->suspend_gate); - - if (device->pwrctrl.nap_allowed == true) { - /* Request nap */ + if (device->state == KGSL_STATE_ACTIVE && + device->requested_state == KGSL_STATE_NONE) { kgsl_pwrctrl_request_state(device, KGSL_STATE_NAP); - kgsl_pwrctrl_sleep(device); + if (kgsl_pwrctrl_sleep(device)) { + kgsl_pwrctrl_request_state(device, KGSL_STATE_NAP); + queue_work(device->work_queue, &device->idle_check_ws); + } } mod_timer(&device->idle_timer, jiffies + device->pwrctrl.interval_timeout); - - complete(&device->suspend_gate); } trace_kgsl_active_count(device, (unsigned long) __builtin_return_address(0)); + + wake_up(&device->active_cnt_wq); } EXPORT_SYMBOL(kgsl_active_count_put); +static int _check_active_count(struct kgsl_device *device, int count) +{ + /* Return 0 if the active count is greater than the desired value */ + return atomic_read(&device->active_cnt) > count ? 0 : 1; +} + /** * kgsl_active_count_wait() - Wait for activity to finish. * @device: Pointer to a KGSL device + * @count: Active count value to wait for * - * Block until all active_cnt users put() their reference. + * Block until the active_cnt value hits the desired value */ -void kgsl_active_count_wait(struct kgsl_device *device) +int kgsl_active_count_wait(struct kgsl_device *device, int count) { + int result = 0; + BUG_ON(!mutex_is_locked(&device->mutex)); - if (atomic_read(&device->active_cnt) != 0) { + if (atomic_read(&device->active_cnt) > count) { + int ret; mutex_unlock(&device->mutex); - wait_for_completion(&device->suspend_gate); + ret = wait_event_timeout(device->active_cnt_wq, + _check_active_count(device, count), HZ); mutex_lock(&device->mutex); + result = ret == 0 ? -ETIMEDOUT : 0; } + + return result; } EXPORT_SYMBOL(kgsl_active_count_wait); diff --git a/drivers/gpu/msm/kgsl_pwrctrl.h b/drivers/gpu/msm/kgsl_pwrctrl.h index 94cd8eb5b52..71a0fdd4b61 100644 --- a/drivers/gpu/msm/kgsl_pwrctrl.h +++ b/drivers/gpu/msm/kgsl_pwrctrl.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. +/* Copyright (c) 2010-2013, The Linux Foundation. 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 and @@ -23,7 +23,9 @@ #define KGSL_PWRLEVEL_NOMINAL 1 #define KGSL_PWRLEVEL_LAST_OFFSET 2 -#define KGSL_MAX_CLKS 5 +#define KGSL_PWR_ON 0xFFFF + +#define KGSL_MAX_CLKS 6 struct platform_device; @@ -47,6 +49,8 @@ struct kgsl_clk_stats { * @pwrlevels - List of supported power levels * @active_pwrlevel - The currently active power level * @thermal_pwrlevel - maximum powerlevel constraint from thermal + * @default_pwrlevel - device wake up power level + * @init_pwrlevel - device inital power level * @max_pwrlevel - maximum allowable powerlevel per the user * @min_pwrlevel - minimum allowable powerlevel per the user * @num_pwrlevels - number of available power levels @@ -55,11 +59,12 @@ struct kgsl_clk_stats { * @gpu_reg - pointer to the regulator structure for gpu_reg * @gpu_cx - pointer to the regulator structure for gpu_cx * @pcl - bus scale identifier - * @nap_allowed - true if the device supports naps * @idle_needed - true if the device needs a idle before clock change * @irq_name - resource name for the IRQ - * @restore_slumber - Flag to indicate that we are in a suspend/restore sequence * @clk_stats - structure of clock statistics + * @pm_qos_req_dma - the power management quality of service structure + * @pm_qos_latency - allowed CPU latency in microseconds + * @step_mul - multiplier for moving between power levels */ struct kgsl_pwrctrl { @@ -67,10 +72,12 @@ struct kgsl_pwrctrl { struct clk *ebi1_clk; struct clk *grp_clks[KGSL_MAX_CLKS]; unsigned long power_flags; + unsigned long ctrl_flags; struct kgsl_pwrlevel pwrlevels[KGSL_MAX_PWRLEVELS]; unsigned int active_pwrlevel; int thermal_pwrlevel; unsigned int default_pwrlevel; + unsigned int init_pwrlevel; unsigned int max_pwrlevel; unsigned int min_pwrlevel; unsigned int num_pwrlevels; @@ -79,12 +86,14 @@ struct kgsl_pwrctrl { struct regulator *gpu_reg; struct regulator *gpu_cx; uint32_t pcl; - unsigned int nap_allowed; unsigned int idle_needed; const char *irq_name; s64 time; - unsigned int restore_slumber; struct kgsl_clk_stats clk_stats; + struct pm_qos_request pm_qos_req_dma; + unsigned int pm_qos_latency; + unsigned int step_mul; + unsigned int irq_last; }; void kgsl_pwrctrl_irq(struct kgsl_device *device, int state); @@ -101,6 +110,8 @@ int kgsl_pwrctrl_init_sysfs(struct kgsl_device *device); void kgsl_pwrctrl_uninit_sysfs(struct kgsl_device *device); void kgsl_pwrctrl_enable(struct kgsl_device *device); void kgsl_pwrctrl_disable(struct kgsl_device *device); +bool kgsl_pwrctrl_isenabled(struct kgsl_device *device); + static inline unsigned long kgsl_get_clkrate(struct clk *clk) { return (clk != NULL) ? clk_get_rate(clk) : 0; @@ -112,6 +123,6 @@ void kgsl_pwrctrl_request_state(struct kgsl_device *device, unsigned int state); int kgsl_active_count_get(struct kgsl_device *device); int kgsl_active_count_get_light(struct kgsl_device *device); void kgsl_active_count_put(struct kgsl_device *device); -void kgsl_active_count_wait(struct kgsl_device *device); +int kgsl_active_count_wait(struct kgsl_device *device, int count); #endif /* __KGSL_PWRCTRL_H */ diff --git a/drivers/gpu/msm/kgsl_pwrscale.c b/drivers/gpu/msm/kgsl_pwrscale.c index 4f7dc5cc271..47554c4fad0 100644 --- a/drivers/gpu/msm/kgsl_pwrscale.c +++ b/drivers/gpu/msm/kgsl_pwrscale.c @@ -47,9 +47,6 @@ static struct kgsl_pwrscale_policy *kgsl_pwrscale_policies[] = { #endif #ifdef CONFIG_MSM_SLEEP_STATS_DEVICE &kgsl_pwrscale_policy_idlestats, -#endif -#ifdef CONFIG_MSM_DCVS - &kgsl_pwrscale_policy_msm, #endif NULL }; @@ -237,17 +234,15 @@ EXPORT_SYMBOL(kgsl_pwrscale_wake); void kgsl_pwrscale_busy(struct kgsl_device *device) { if (PWRSCALE_ACTIVE(device) && device->pwrscale.policy->busy) - if (device->requested_state != KGSL_STATE_SLUMBER) - device->pwrscale.policy->busy(device, - &device->pwrscale); + device->pwrscale.policy->busy(device, + &device->pwrscale); } EXPORT_SYMBOL(kgsl_pwrscale_busy); void kgsl_pwrscale_idle(struct kgsl_device *device) { if (PWRSCALE_ACTIVE(device) && device->pwrscale.policy->idle) - if (device->requested_state != KGSL_STATE_SLUMBER && - device->requested_state != KGSL_STATE_SLEEP) + if (device->state == KGSL_STATE_ACTIVE) device->pwrscale.policy->idle(device, &device->pwrscale); } @@ -308,6 +303,8 @@ static void _kgsl_pwrscale_detach_policy(struct kgsl_device *device) kgsl_pwrctrl_pwrlevel_change(device, device->pwrctrl.max_pwrlevel); + device->pwrctrl.default_pwrlevel = + device->pwrctrl.max_pwrlevel; } device->pwrscale.policy = NULL; } @@ -340,6 +337,8 @@ int kgsl_pwrscale_attach_policy(struct kgsl_device *device, device->pwrscale.policy = policy; + device->pwrctrl.default_pwrlevel = + device->pwrctrl.init_pwrlevel; /* Pwrscale is enabled by default at attach time */ kgsl_pwrscale_enable(device); diff --git a/drivers/gpu/msm/kgsl_pwrscale_trustzone.c b/drivers/gpu/msm/kgsl_pwrscale_trustzone.c index b3204330c75..5e4f6b1620b 100644 --- a/drivers/gpu/msm/kgsl_pwrscale_trustzone.c +++ b/drivers/gpu/msm/kgsl_pwrscale_trustzone.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. +/* Copyright (c) 2010-2013, The Linux Foundation. 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 and @@ -8,9 +8,6 @@ * 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. - * - * Modified by Paul Reioux (Faux123) - * 2013-06-20: Added KGSL Simple GPU Governor * */ @@ -38,9 +35,8 @@ struct tz_priv { int governor; - unsigned int no_switch_cnt; - unsigned int skip_cnt; struct kgsl_power_stats bin; + unsigned int idle_dcvs; }; spinlock_t tz_lock; @@ -48,29 +44,38 @@ spinlock_t tz_lock; * per frame for 60fps content. */ #define FLOOR 5000 -#define SWITCH_OFF 200 -#define SWITCH_OFF_RESET_TH 40 -#define SKIP_COUNTER 500 +/* CEILING is 50msec, larger than any standard + * frame length, but less than the idle timer. + */ +#define CEILING 50000 #define TZ_RESET_ID 0x3 #define TZ_UPDATE_ID 0x4 +#define TZ_INIT_ID 0x6 -#ifdef CONFIG_MSM_SCM /* Trap into the TrustZone, and call funcs there. */ -static int __secure_tz_entry(u32 cmd, u32 val, u32 id) +static int __secure_tz_entry2(u32 cmd, u32 val1, u32 val2) { int ret; spin_lock(&tz_lock); + /* sync memory before sending the commands to tz*/ __iowmb(); - ret = scm_call_atomic2(SCM_SVC_IO, cmd, val, id); + ret = scm_call_atomic2(SCM_SVC_IO, cmd, val1, val2); spin_unlock(&tz_lock); return ret; } -#else -static int __secure_tz_entry(u32 cmd, u32 val, u32 id) + +static int __secure_tz_entry3(u32 cmd, u32 val1, u32 val2, + u32 val3) { - return 0; + int ret; + spin_lock(&tz_lock); + /* sync memory before sending the commands to tz*/ + __iowmb(); + ret = scm_call_atomic3(SCM_SVC_IO, cmd, val1, val2, + val3); + spin_unlock(&tz_lock); + return ret; } -#endif /* CONFIG_MSM_SCM */ static ssize_t tz_governor_show(struct kgsl_device *device, struct kgsl_pwrscale *pwrscale, @@ -115,8 +120,12 @@ static ssize_t tz_governor_store(struct kgsl_device *device, else if (!strncmp(str, "performance", 11)) priv->governor = TZ_GOVERNOR_PERFORMANCE; - if (priv->governor == TZ_GOVERNOR_PERFORMANCE) + if (priv->governor == TZ_GOVERNOR_PERFORMANCE) { kgsl_pwrctrl_pwrlevel_change(device, pwr->max_pwrlevel); + pwr->default_pwrlevel = pwr->max_pwrlevel; + } else { + pwr->default_pwrlevel = pwr->init_pwrlevel; + } mutex_unlock(&device->mutex); return count; @@ -148,56 +157,45 @@ static void tz_wake(struct kgsl_device *device, struct kgsl_pwrscale *pwrscale) } #ifdef CONFIG_MSM_KGSL_SIMPLE_GOV -#define HISTORY_SIZE 10 - -static int laziness; - +/* KGSL Simple GPU Governor */ +/* Copyright (c) 2011-2013, Paul Reioux (Faux123). All rights reserved. */ static int default_laziness = 5; module_param_named(simple_laziness, default_laziness, int, 0664); -static int ramp_up_threshold = 5500; +static int ramp_up_threshold = 6000; module_param_named(simple_ramp_threshold, ramp_up_threshold, int, 0664); -static unsigned int history[HISTORY_SIZE] = {0}; -static unsigned int counter = 0; +static int laziness; static int simple_governor(struct kgsl_device *device, int idle_stat) { + int val = 0; struct kgsl_pwrctrl *pwr = &device->pwrctrl; - int i; - unsigned int total = 0; - - history[counter] = idle_stat; - - for (i = 0; i < HISTORY_SIZE; i++) - total += history[i]; - - total = total/HISTORY_SIZE; - - if (++counter == 10) - counter = 0; /* it's currently busy */ - if (total < ramp_up_threshold) { - if ((pwr->active_pwrlevel > 0) && + if (idle_stat < ramp_up_threshold) { + if (pwr->active_pwrlevel == 0) + val = 0; /* already maxed, so do nothing */ + else if ((pwr->active_pwrlevel > 0) && (pwr->active_pwrlevel <= (pwr->num_pwrlevels - 1))) - /* bump up to next pwrlevel */ - return -1; - + val = -1; /* bump up to next pwrlevel */ /* idle case */ - } else if ((pwr->active_pwrlevel >= 0) && - (pwr->active_pwrlevel < (pwr->num_pwrlevels - 1))) { - if (likely(--laziness > 0)) { - /* don't change anything yet hold off for a while */ - return 0; - } else { - /* above min, lower it */ - laziness = default_laziness; - return 1; - } + } else { + if ((pwr->active_pwrlevel >= 0) && + (pwr->active_pwrlevel < (pwr->num_pwrlevels - 1))) + if (laziness > 0) { + /* hold off for a while */ + laziness--; + val = 0; /* don't change anything yet */ + } else { + val = 1; /* above min, lower it */ + /* reset laziness count */ + laziness = default_laziness; + } + else if (pwr->active_pwrlevel == (pwr->num_pwrlevels - 1)) + val = 0; /* already @ min, so do nothing */ } - - return 0; + return val; } #endif @@ -224,40 +222,50 @@ static void tz_idle(struct kgsl_device *device, struct kgsl_pwrscale *pwrscale) (priv->bin.total_time < FLOOR)) return; - /* If the GPU has stayed in turbo mode for a while, * - * stop writing out values. */ - if (pwr->active_pwrlevel == 0) { - if (priv->no_switch_cnt > SWITCH_OFF) { - priv->skip_cnt++; - if (priv->skip_cnt > SKIP_COUNTER) { - priv->no_switch_cnt -= SWITCH_OFF_RESET_TH; - priv->skip_cnt = 0; - } - return; - } - priv->no_switch_cnt++; + /* If there is an extended block of busy processing, + * increase frequency. Otherwise run the normal algorithm. + */ + if (priv->bin.busy_time > CEILING) { + val = -1; + } else if (priv->idle_dcvs) { + idle = priv->bin.total_time - priv->bin.busy_time; + idle = (idle > 0) ? idle : 0; + val = __secure_tz_entry2(TZ_UPDATE_ID, idle, device->id); } else { - priv->no_switch_cnt = 0; + if (pwr->step_mul > 1) + val = __secure_tz_entry3(TZ_UPDATE_ID, + (pwr->active_pwrlevel + 1)/2, + priv->bin.total_time, priv->bin.busy_time); + else +#ifdef CONFIG_MSM_KGSL_SIMPLE_GOV + { + idle = priv->bin.total_time - priv->bin.busy_time; + idle = (idle > 0) ? idle : 0; + if (priv->governor == TZ_GOVERNOR_SIMPLE) + val = simple_governor(device, idle); + else + val = __secure_tz_entry3(TZ_UPDATE_ID, + pwr->active_pwrlevel, + priv->bin.total_time, priv->bin.busy_time); + } +#else + val = __secure_tz_entry3(TZ_UPDATE_ID, + pwr->active_pwrlevel, + priv->bin.total_time, priv->bin.busy_time); +#endif } - idle = priv->bin.total_time - priv->bin.busy_time; priv->bin.total_time = 0; priv->bin.busy_time = 0; - idle = (idle > 0) ? idle : 0; -#ifdef CONFIG_MSM_KGSL_SIMPLE_GOV - if (priv->governor == TZ_GOVERNOR_SIMPLE) - val = simple_governor(device, idle); - else - val = __secure_tz_entry(TZ_UPDATE_ID, idle, device->id); -#else - val = __secure_tz_entry(TZ_UPDATE_ID, idle, device->id); -#endif - if (val) { + + /* If the decision is to move to a lower level, make sure the GPU + * frequency drops. + */ + if (val > 0) + val *= pwr->step_mul; + if (val) kgsl_pwrctrl_pwrlevel_change(device, pwr->active_pwrlevel + val); - //pr_info("TZ idle stat: %d, TZ PL: %d, TZ out: %d\n", - // idle, pwr->active_pwrlevel, val); - } } static void tz_busy(struct kgsl_device *device, @@ -271,8 +279,7 @@ static void tz_sleep(struct kgsl_device *device, { struct tz_priv *priv = pwrscale->priv; - kgsl_pwrctrl_pwrlevel_change(device, 3); - priv->no_switch_cnt = 0; + __secure_tz_entry2(TZ_RESET_ID, 0, 0); priv->bin.total_time = 0; priv->bin.busy_time = 0; } @@ -280,16 +287,32 @@ static void tz_sleep(struct kgsl_device *device, #ifdef CONFIG_MSM_SCM static int tz_init(struct kgsl_device *device, struct kgsl_pwrscale *pwrscale) { + int i = 0, j = 1, ret = 0; struct tz_priv *priv; + struct kgsl_pwrctrl *pwr = &device->pwrctrl; + unsigned int tz_pwrlevels[KGSL_MAX_PWRLEVELS + 1]; priv = pwrscale->priv = kzalloc(sizeof(struct tz_priv), GFP_KERNEL); if (pwrscale->priv == NULL) return -ENOMEM; - + priv->idle_dcvs = 0; priv->governor = TZ_GOVERNOR_ONDEMAND; spin_lock_init(&tz_lock); kgsl_pwrscale_policy_add_files(device, pwrscale, &tz_attr_group); - + for (i = 0; i < pwr->num_pwrlevels - 1; i++) { + if (i == 0) + tz_pwrlevels[j] = pwr->pwrlevels[i].gpu_freq; + else if (pwr->pwrlevels[i].gpu_freq != + pwr->pwrlevels[i - 1].gpu_freq) { + j++; + tz_pwrlevels[j] = pwr->pwrlevels[i].gpu_freq; + } + } + tz_pwrlevels[0] = j; + ret = scm_call(SCM_SVC_DCVS, TZ_INIT_ID, tz_pwrlevels, + sizeof(tz_pwrlevels), NULL, 0); + if (ret) + priv->idle_dcvs = 1; return 0; } #else @@ -316,3 +339,4 @@ struct kgsl_pwrscale_policy kgsl_pwrscale_policy_tz = { .close = tz_close }; EXPORT_SYMBOL(kgsl_pwrscale_policy_tz); + diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c index ed80b198b82..0d6f2029802 100755 --- a/drivers/gpu/msm/kgsl_sharedmem.c +++ b/drivers/gpu/msm/kgsl_sharedmem.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2002,2007-2012, The Linux Foundation. All rights reserved. +/* Copyright (c) 2002,2007-2013, The Linux Foundation. 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 and @@ -24,6 +24,8 @@ #include "kgsl_cffdump.h" #include "kgsl_device.h" +DEFINE_MUTEX(kernel_map_global_lock); + /* An attribute for showing per-process memory statistics */ struct kgsl_mem_entry_attribute { struct attribute attr; @@ -146,9 +148,7 @@ static struct kobj_type ktype_mem_entry = { static struct mem_entry_stats mem_stats[] = { MEM_ENTRY_STAT(KGSL_MEM_ENTRY_KERNEL, kernel), -#ifdef CONFIG_ANDROID_PMEM MEM_ENTRY_STAT(KGSL_MEM_ENTRY_PMEM, pmem), -#endif #ifdef CONFIG_ASHMEM MEM_ENTRY_STAT(KGSL_MEM_ENTRY_ASHMEM, ashmem), #endif @@ -172,17 +172,32 @@ kgsl_process_uninit_sysfs(struct kgsl_process_private *private) kobject_put(&private->kobj); } -void -kgsl_process_init_sysfs(struct kgsl_process_private *private) +/** + * kgsl_process_init_sysfs() - Initialize and create sysfs files for a process + * + * @device: Pointer to kgsl device struct + * @private: Pointer to the structure for the process + * + * @returns: 0 on success, error code otherwise + * + * kgsl_process_init_sysfs() is called at the time of creating the + * process struct when a process opens the kgsl device for the first time. + * This function creates the sysfs files for the process. + */ +int +kgsl_process_init_sysfs(struct kgsl_device *device, + struct kgsl_process_private *private) { unsigned char name[16]; - int i, ret; + int i, ret = 0; snprintf(name, sizeof(name), "%d", private->pid); - if (kobject_init_and_add(&private->kobj, &ktype_mem_entry, - kgsl_driver.prockobj, name)) - return; + ret = kobject_init_and_add(&private->kobj, &ktype_mem_entry, + kgsl_driver.prockobj, name); + + if (ret) + return ret; for (i = 0; i < ARRAY_SIZE(mem_stats); i++) { /* We need to check the value of sysfs_create_file, but we @@ -193,6 +208,7 @@ kgsl_process_init_sysfs(struct kgsl_process_private *private) ret = sysfs_create_file(&private->kobj, &mem_stats[i].max_attr.attr); } + return ret; } static int kgsl_drv_memstat_show(struct device *dev, @@ -379,6 +395,35 @@ static int kgsl_page_alloc_vmflags(struct kgsl_memdesc *memdesc) return VM_RESERVED | VM_DONTEXPAND; } +static int kgsl_contiguous_vmflags(struct kgsl_memdesc *memdesc) +{ + return VM_RESERVED | VM_IO | VM_PFNMAP | VM_DONTEXPAND; +} + +/* + * kgsl_page_alloc_unmap_kernel() - Unmap the memory in memdesc + * + * @memdesc: The memory descriptor which contains information about the memory + * + * Unmaps the memory mapped into kernel address space + */ +static void kgsl_page_alloc_unmap_kernel(struct kgsl_memdesc *memdesc) +{ + mutex_lock(&kernel_map_global_lock); + if (!memdesc->hostptr) { + BUG_ON(memdesc->hostptr_count); + goto done; + } + memdesc->hostptr_count--; + if (memdesc->hostptr_count) + goto done; + vunmap(memdesc->hostptr); + kgsl_driver.stats.vmalloc -= memdesc->size; + memdesc->hostptr = NULL; +done: + mutex_unlock(&kernel_map_global_lock); +} + static void kgsl_page_alloc_free(struct kgsl_memdesc *memdesc) { int i = 0; @@ -387,21 +432,13 @@ static void kgsl_page_alloc_free(struct kgsl_memdesc *memdesc) kgsl_driver.stats.page_alloc -= memdesc->size; - if (memdesc->hostptr) { - vunmap(memdesc->hostptr); - kgsl_driver.stats.vmalloc -= memdesc->size; - } + kgsl_page_alloc_unmap_kernel(memdesc); + /* we certainly do not expect the hostptr to still be mapped */ + BUG_ON(memdesc->hostptr); + if (memdesc->sg) - for_each_sg(memdesc->sg, sg, sglen, i){ - if (sg->length == 0) - break; + for_each_sg(memdesc->sg, sg, sglen, i) __free_pages(sg_page(sg), get_order(sg->length)); - } -} - -static int kgsl_contiguous_vmflags(struct kgsl_memdesc *memdesc) -{ - return VM_RESERVED | VM_IO | VM_PFNMAP | VM_DONTEXPAND; } /* @@ -414,6 +451,9 @@ static int kgsl_contiguous_vmflags(struct kgsl_memdesc *memdesc) */ static int kgsl_page_alloc_map_kernel(struct kgsl_memdesc *memdesc) { + int ret = 0; + + mutex_lock(&kernel_map_global_lock); if (!memdesc->hostptr) { pgprot_t page_prot = pgprot_writecombine(PAGE_KERNEL); struct page **pages = NULL; @@ -427,7 +467,8 @@ static int kgsl_page_alloc_map_kernel(struct kgsl_memdesc *memdesc) if (!pages) { KGSL_CORE_ERR("vmalloc(%d) failed\n", npages * sizeof(struct page *)); - return -ENOMEM; + ret = -ENOMEM; + goto done; } for_each_sg(memdesc->sg, sg, sglen, i) { @@ -441,14 +482,19 @@ static int kgsl_page_alloc_map_kernel(struct kgsl_memdesc *memdesc) memdesc->hostptr = vmap(pages, count, VM_IOREMAP, page_prot); - KGSL_STATS_ADD(memdesc->size, kgsl_driver.stats.vmalloc, + if (memdesc->hostptr) + KGSL_STATS_ADD(memdesc->size, kgsl_driver.stats.vmalloc, kgsl_driver.stats.vmalloc_max); + else + ret = -ENOMEM; vfree(pages); } - if (!memdesc->hostptr) - return -ENOMEM; + if (memdesc->hostptr) + memdesc->hostptr_count++; +done: + mutex_unlock(&kernel_map_global_lock); - return 0; + return ret; } static int kgsl_contiguous_vmfault(struct kgsl_memdesc *memdesc, @@ -472,28 +518,51 @@ static int kgsl_contiguous_vmfault(struct kgsl_memdesc *memdesc, return VM_FAULT_NOPAGE; } +static void kgsl_ebimem_unmap_kernel(struct kgsl_memdesc *memdesc) +{ + mutex_lock(&kernel_map_global_lock); + if (!memdesc->hostptr) { + BUG_ON(memdesc->hostptr_count); + goto done; + } + memdesc->hostptr_count--; + if (memdesc->hostptr_count) + goto done; + + iounmap(memdesc->hostptr); + memdesc->hostptr = NULL; +done: + mutex_unlock(&kernel_map_global_lock); +} + static void kgsl_ebimem_free(struct kgsl_memdesc *memdesc) { kgsl_driver.stats.coherent -= memdesc->size; - if (memdesc->hostptr) - iounmap(memdesc->hostptr); + kgsl_ebimem_unmap_kernel(memdesc); + /* we certainly do not expect the hostptr to still be mapped */ + BUG_ON(memdesc->hostptr); free_contiguous_memory_by_paddr(memdesc->physaddr); } static int kgsl_ebimem_map_kernel(struct kgsl_memdesc *memdesc) { + int ret = 0; + mutex_lock(&kernel_map_global_lock); if (!memdesc->hostptr) { memdesc->hostptr = ioremap(memdesc->physaddr, memdesc->size); if (!memdesc->hostptr) { KGSL_CORE_ERR("ioremap failed, addr:0x%p, size:0x%x\n", memdesc->hostptr, memdesc->size); - return -ENOMEM; + ret = -ENOMEM; + goto done; } } - - return 0; + memdesc->hostptr_count++; +done: + mutex_unlock(&kernel_map_global_lock); + return ret; } static void kgsl_coherent_free(struct kgsl_memdesc *memdesc) @@ -508,7 +577,8 @@ struct kgsl_memdesc_ops kgsl_page_alloc_ops = { .free = kgsl_page_alloc_free, .vmflags = kgsl_page_alloc_vmflags, .vmfault = kgsl_page_alloc_vmfault, - .map_kernel_mem = kgsl_page_alloc_map_kernel, + .map_kernel = kgsl_page_alloc_map_kernel, + .unmap_kernel = kgsl_page_alloc_unmap_kernel, }; EXPORT_SYMBOL(kgsl_page_alloc_ops); @@ -516,7 +586,8 @@ static struct kgsl_memdesc_ops kgsl_ebimem_ops = { .free = kgsl_ebimem_free, .vmflags = kgsl_contiguous_vmflags, .vmfault = kgsl_contiguous_vmfault, - .map_kernel_mem = kgsl_ebimem_map_kernel, + .map_kernel = kgsl_ebimem_map_kernel, + .unmap_kernel = kgsl_ebimem_unmap_kernel, }; static struct kgsl_memdesc_ops kgsl_coherent_ops = { @@ -563,6 +634,7 @@ _kgsl_sharedmem_page_alloc(struct kgsl_memdesc *memdesc, pgprot_t page_prot = pgprot_writecombine(PAGE_KERNEL); void *ptr; unsigned int align; + int step = ((VMALLOC_END - VMALLOC_START)/8) >> PAGE_SHIFT; align = (memdesc->flags & KGSL_MEMALIGN_MASK) >> KGSL_MEMALIGN_SHIFT; @@ -583,35 +655,35 @@ _kgsl_sharedmem_page_alloc(struct kgsl_memdesc *memdesc, memdesc->pagetable = pagetable; memdesc->ops = &kgsl_page_alloc_ops; - memdesc->sg = kgsl_sg_alloc(sglen_alloc); + memdesc->sglen_alloc = sglen_alloc; + memdesc->sg = kgsl_sg_alloc(memdesc->sglen_alloc); if (memdesc->sg == NULL) { - KGSL_CORE_ERR("vmalloc(%d) failed\n", - sglen_alloc * sizeof(struct scatterlist)); ret = -ENOMEM; goto done; } /* * Allocate space to store the list of pages to send to vmap. - * This is an array of pointers so we can track 1024 pages per page of - * allocation which means we can handle up to a 8MB buffer request with - * two pages; well within the acceptable limits for using kmalloc. + * This is an array of pointers so we can t rack 1024 pages per page + * of allocation. Since allocations can be as large as the user dares, + * we have to use the kmalloc/vmalloc trick here to make sure we can + * get the memory we need. */ - pages = kmalloc(sglen_alloc * sizeof(struct page *), GFP_KERNEL); + if ((memdesc->sglen_alloc * sizeof(struct page *)) > PAGE_SIZE) + pages = vmalloc(memdesc->sglen_alloc * sizeof(struct page *)); + else + pages = kmalloc(PAGE_SIZE, GFP_KERNEL); if (pages == NULL) { - KGSL_CORE_ERR("kmalloc (%d) failed\n", - sglen_alloc * sizeof(struct page *)); ret = -ENOMEM; goto done; } kmemleak_not_leak(memdesc->sg); - memdesc->sglen_alloc = sglen_alloc; - sg_init_table(memdesc->sg, sglen_alloc); + sg_init_table(memdesc->sg, memdesc->sglen_alloc); len = size; @@ -632,7 +704,7 @@ _kgsl_sharedmem_page_alloc(struct kgsl_memdesc *memdesc, gfp_mask |= __GFP_COMP | __GFP_NORETRY | __GFP_NO_KSWAPD | __GFP_NOWARN; else - gfp_mask |= GFP_KERNEL | __GFP_NORETRY; + gfp_mask |= GFP_KERNEL; page = alloc_pages(gfp_mask, get_order(page_size)); @@ -668,30 +740,36 @@ _kgsl_sharedmem_page_alloc(struct kgsl_memdesc *memdesc, * zeroed and unmaped each individual page, and then we had to turn * around and call flush_dcache_page() on that page to clear the caches. * This was killing us for performance. Instead, we found it is much - * faster to allocate the pages without GFP_ZERO, map the entire range, - * memset it, flush the range and then unmap - this results in a factor - * of 4 improvement for speed for large buffers. There is a small - * increase in speed for small buffers, but only on the order of a few - * microseconds at best. The only downside is that there needs to be - * enough temporary space in vmalloc to accomodate the map. This - * shouldn't be a problem, but if it happens, fall back to a much slower - * path + * faster to allocate the pages without GFP_ZERO, map a chunk of the + * range ('step' pages), memset it, flush it and then unmap + * - this results in a factor of 4 improvement for speed for large + * buffers. There is a small decrease in speed for small buffers, + * but only on the order of a few microseconds at best. The 'step' + * size is based on a guess at the amount of free vmalloc space, but + * will scale down if there's not enough free space. */ - - ptr = vmap(pages, pcount, VM_IOREMAP, page_prot); - - if (ptr != NULL) { - memset(ptr, 0, memdesc->size); - dmac_flush_range(ptr, ptr + memdesc->size); - vunmap(ptr); - } else { - /* Very, very, very slow path */ - - for (j = 0; j < pcount; j++) { - ptr = kmap_atomic(pages[j]); - memset(ptr, 0, PAGE_SIZE); - dmac_flush_range(ptr, ptr + PAGE_SIZE); - kunmap_atomic(ptr); + for (j = 0; j < pcount; j += step) { + step = min(step, pcount - j); + + ptr = vmap(&pages[j], step, VM_IOREMAP, page_prot); + + if (ptr != NULL) { + memset(ptr, 0, step * PAGE_SIZE); + dmac_flush_range(ptr, ptr + step * PAGE_SIZE); + vunmap(ptr); + } else { + int k; + /* Very, very, very slow path */ + + for (k = j; k < j + step; k++) { + ptr = kmap_atomic(pages[k]); + memset(ptr, 0, PAGE_SIZE); + dmac_flush_range(ptr, ptr + PAGE_SIZE); + kunmap_atomic(ptr); + } + /* scale down the step size to avoid this path */ + if (step > 1) + step >>= 1; } } @@ -707,7 +785,10 @@ _kgsl_sharedmem_page_alloc(struct kgsl_memdesc *memdesc, kgsl_driver.stats.histogram[order]++; done: - kfree(pages); + if ((memdesc->sglen_alloc * sizeof(struct page *)) > PAGE_SIZE) + vfree(pages); + else + kfree(pages); if (ret) kgsl_sharedmem_free(memdesc); @@ -723,6 +804,8 @@ kgsl_sharedmem_page_alloc(struct kgsl_memdesc *memdesc, BUG_ON(size == 0); size = ALIGN(size, PAGE_SIZE * 2); + if (size == 0) + return -EINVAL; ret = _kgsl_sharedmem_page_alloc(memdesc, pagetable, size); if (!ret) @@ -738,7 +821,11 @@ kgsl_sharedmem_page_alloc_user(struct kgsl_memdesc *memdesc, struct kgsl_pagetable *pagetable, size_t size) { - return _kgsl_sharedmem_page_alloc(memdesc, pagetable, PAGE_ALIGN(size)); + size = PAGE_ALIGN(size); + if (size == 0) + return -EINVAL; + + return _kgsl_sharedmem_page_alloc(memdesc, pagetable, size); } EXPORT_SYMBOL(kgsl_sharedmem_page_alloc_user); @@ -748,6 +835,8 @@ kgsl_sharedmem_alloc_coherent(struct kgsl_memdesc *memdesc, size_t size) int result = 0; size = ALIGN(size, PAGE_SIZE); + if (size == 0) + return -EINVAL; memdesc->size = size; memdesc->ops = &kgsl_coherent_ops; @@ -782,8 +871,10 @@ void kgsl_sharedmem_free(struct kgsl_memdesc *memdesc) if (memdesc == NULL || memdesc->size == 0) return; - if (memdesc->gpuaddr) + if (memdesc->gpuaddr) { kgsl_mmu_unmap(memdesc->pagetable, memdesc); + kgsl_mmu_put_gpuaddr(memdesc->pagetable, memdesc); + } if (memdesc->ops && memdesc->ops->free) memdesc->ops->free(memdesc); @@ -832,6 +923,9 @@ kgsl_sharedmem_ebimem_user(struct kgsl_memdesc *memdesc, size_t size) { size = ALIGN(size, PAGE_SIZE); + if (size == 0) + return -EINVAL; + return _kgsl_sharedmem_ebimem(memdesc, pagetable, size); } EXPORT_SYMBOL(kgsl_sharedmem_ebimem_user); @@ -842,17 +936,20 @@ kgsl_sharedmem_ebimem(struct kgsl_memdesc *memdesc, { int result; size = ALIGN(size, 8192); + if (size == 0) + return -EINVAL; + result = _kgsl_sharedmem_ebimem(memdesc, pagetable, size); if (result) return result; - memdesc->hostptr = ioremap(memdesc->physaddr, size); + result = kgsl_ebimem_map_kernel(memdesc); - if (memdesc->hostptr == NULL) { - KGSL_CORE_ERR("ioremap failed\n"); + if (result) { + KGSL_CORE_ERR("hostptr mapping failed\n"); kgsl_sharedmem_free(memdesc); - return -ENOMEM; + return result; } return 0; @@ -880,7 +977,8 @@ kgsl_sharedmem_readl(const struct kgsl_memdesc *memdesc, EXPORT_SYMBOL(kgsl_sharedmem_readl); int -kgsl_sharedmem_writel(const struct kgsl_memdesc *memdesc, +kgsl_sharedmem_writel(struct kgsl_device *device, + const struct kgsl_memdesc *memdesc, unsigned int offsetbytes, uint32_t src) { @@ -893,7 +991,8 @@ kgsl_sharedmem_writel(const struct kgsl_memdesc *memdesc, WARN_ON(offsetbytes + sizeof(uint32_t) > memdesc->size); if (offsetbytes + sizeof(uint32_t) > memdesc->size) return -ERANGE; - kgsl_cffdump_setmem(memdesc->gpuaddr + offsetbytes, + kgsl_cffdump_setmem(device, + memdesc->gpuaddr + offsetbytes, src, sizeof(uint32_t)); dst = (uint32_t *)(memdesc->hostptr + offsetbytes); *dst = src; @@ -902,14 +1001,16 @@ kgsl_sharedmem_writel(const struct kgsl_memdesc *memdesc, EXPORT_SYMBOL(kgsl_sharedmem_writel); int -kgsl_sharedmem_set(const struct kgsl_memdesc *memdesc, unsigned int offsetbytes, - unsigned int value, unsigned int sizebytes) +kgsl_sharedmem_set(struct kgsl_device *device, + const struct kgsl_memdesc *memdesc, unsigned int offsetbytes, + unsigned int value, unsigned int sizebytes) { BUG_ON(memdesc == NULL || memdesc->hostptr == NULL); BUG_ON(offsetbytes + sizebytes > memdesc->size); - kgsl_cffdump_setmem(memdesc->gpuaddr + offsetbytes, value, - sizebytes); + kgsl_cffdump_setmem(device, + memdesc->gpuaddr + offsetbytes, value, + sizebytes); memset(memdesc->hostptr + offsetbytes, value, sizebytes); return 0; } diff --git a/drivers/gpu/msm/kgsl_sharedmem.h b/drivers/gpu/msm/kgsl_sharedmem.h index c000cbb6df6..339575f55e1 100644 --- a/drivers/gpu/msm/kgsl_sharedmem.h +++ b/drivers/gpu/msm/kgsl_sharedmem.h @@ -55,17 +55,20 @@ int kgsl_sharedmem_readl(const struct kgsl_memdesc *memdesc, uint32_t *dst, unsigned int offsetbytes); -int kgsl_sharedmem_writel(const struct kgsl_memdesc *memdesc, +int kgsl_sharedmem_writel(struct kgsl_device *device, + const struct kgsl_memdesc *memdesc, unsigned int offsetbytes, uint32_t src); -int kgsl_sharedmem_set(const struct kgsl_memdesc *memdesc, +int kgsl_sharedmem_set(struct kgsl_device *device, + const struct kgsl_memdesc *memdesc, unsigned int offsetbytes, unsigned int value, unsigned int sizebytes); void kgsl_cache_range_op(struct kgsl_memdesc *memdesc, int op); -void kgsl_process_init_sysfs(struct kgsl_process_private *private); +int kgsl_process_init_sysfs(struct kgsl_device *device, + struct kgsl_process_private *private); void kgsl_process_uninit_sysfs(struct kgsl_process_private *private); int kgsl_sharedmem_init_sysfs(void); @@ -159,7 +162,7 @@ static inline void kgsl_sg_free(void *ptr, unsigned int sglen) static inline int memdesc_sg_phys(struct kgsl_memdesc *memdesc, - unsigned int physaddr, unsigned int size) + phys_addr_t physaddr, unsigned int size) { memdesc->sg = kgsl_sg_alloc(1); if (!memdesc->sg) @@ -263,6 +266,11 @@ kgsl_allocate(struct kgsl_memdesc *memdesc, ret = kgsl_sharedmem_page_alloc(memdesc, pagetable, size); if (ret) return ret; + ret = kgsl_mmu_get_gpuaddr(pagetable, memdesc); + if (ret) { + kgsl_sharedmem_free(memdesc); + return ret; + } ret = kgsl_mmu_map(pagetable, memdesc); if (ret) kgsl_sharedmem_free(memdesc); diff --git a/drivers/gpu/msm/kgsl_snapshot.c b/drivers/gpu/msm/kgsl_snapshot.c index 50ac9c1bd34..a81e19c520a 100644 --- a/drivers/gpu/msm/kgsl_snapshot.c +++ b/drivers/gpu/msm/kgsl_snapshot.c @@ -22,12 +22,13 @@ #include "kgsl_device.h" #include "kgsl_sharedmem.h" #include "kgsl_snapshot.h" +#include "adreno_cp_parser.h" /* Placeholder for the list of memory objects frozen after a hang */ struct kgsl_snapshot_object { unsigned int gpuaddr; - unsigned int ptbase; + phys_addr_t ptbase; unsigned int size; unsigned int offset; int type; @@ -35,6 +36,14 @@ struct kgsl_snapshot_object { struct list_head node; }; +/* Placeholder for list of ib objects that contain all objects in that IB */ + +struct kgsl_snapshot_cp_obj { + struct adreno_ib_object_list *ib_obj_list; + unsigned int ptbase; + struct list_head node; +}; + struct snapshot_obj_itr { void *buf; /* Buffer pointer to write to */ int pos; /* Current position in the sequence */ @@ -140,6 +149,7 @@ static int snapshot_os(struct kgsl_device *device, int hang = (int) priv; int ctxtcount = 0; int size = sizeof(*header); + phys_addr_t temp_ptbase; /* Figure out how many active contexts there are - these will * be appended on the end of the structure */ @@ -183,11 +193,14 @@ static int snapshot_os(struct kgsl_device *device, kgsl_sharedmem_readl(&device->memstore, &header->current_context, KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, current_context)); + /* Get the current PT base */ - header->ptbase = kgsl_mmu_get_current_ptbase(&device->mmu); + temp_ptbase = kgsl_mmu_get_current_ptbase(&device->mmu); + /* Truncate to 32 bits in case LPAE is used */ + header->ptbase = (__u32)temp_ptbase; /* And the PID for the task leader */ pid = header->pid = kgsl_mmu_get_ptname_from_ptbase(&device->mmu, - header->ptbase); + temp_ptbase); task = find_task_by_vpid(pid); @@ -258,6 +271,12 @@ static int kgsl_snapshot_dump_object(struct kgsl_device *device, struct kgsl_snapshot_gpu_object header; int ret; + if (kgsl_memdesc_map(&obj->entry->memdesc) == NULL) { + KGSL_DRV_ERR(device, "Unable to map GPU buffer %X\n", + obj->gpuaddr); + return 0; + } + sect.magic = SNAPSHOT_SECTION_MAGIC; sect.id = KGSL_SNAPSHOT_SECTION_GPU_OBJECT; @@ -270,21 +289,21 @@ static int kgsl_snapshot_dump_object(struct kgsl_device *device, ret = obj_itr_out(itr, §, sizeof(sect)); if (ret == 0) - return 0; + goto done; header.size = ALIGN(obj->size, 4) >> 2; header.gpuaddr = obj->gpuaddr; - header.ptbase = obj->ptbase; + header.ptbase = (__u32)obj->ptbase; header.type = obj->type; ret = obj_itr_out(itr, &header, sizeof(header)); if (ret == 0) - return 0; + goto done; ret = obj_itr_out(itr, obj->entry->memdesc.hostptr + obj->offset, obj->size); if (ret == 0) - return 0; + goto done; /* Pad the end to a dword boundary if we need to */ @@ -292,7 +311,8 @@ static int kgsl_snapshot_dump_object(struct kgsl_device *device, unsigned int dummy = 0; ret = obj_itr_out(itr, &dummy, obj->size % 4); } - +done: + kgsl_memdesc_unmap(&obj->entry->memdesc); return ret; } @@ -307,6 +327,32 @@ static void kgsl_snapshot_put_object(struct kgsl_device *device, kfree(obj); } +/* + * ksgl_snapshot_find_object() - Return the snapshot object pointer + * for given address range + * @device: the device that is being snapshotted + * @ptbase: the pagetable base of the object to search + * @gpuaddr: The gpu address of the object to search + * @size: the size of the object (may not always be the size of the region) + * + * Return the object pointer if found else NULL + */ +struct kgsl_snapshot_object *kgsl_snapshot_find_object( + struct kgsl_device *device, + phys_addr_t ptbase, unsigned int gpuaddr, + unsigned int size) +{ + struct kgsl_snapshot_object *obj = NULL; + list_for_each_entry(obj, &device->snapshot_obj_list, node) { + if (obj->ptbase != ptbase) + continue; + if ((gpuaddr >= obj->gpuaddr) && + ((gpuaddr + size) <= (obj->gpuaddr + obj->size))) + return obj; + } + return NULL; +} + /* ksgl_snapshot_have_object - Return 1 if the object has been processed *@device - the device that is being snapshotted * @ptbase - the pagetable base of the object to freeze @@ -316,7 +362,7 @@ static void kgsl_snapshot_put_object(struct kgsl_device *device, * Return 1 if the object is already in the list - this can save us from * having to parse the sme thing over again. */ -int kgsl_snapshot_have_object(struct kgsl_device *device, unsigned int ptbase, +int kgsl_snapshot_have_object(struct kgsl_device *device, phys_addr_t ptbase, unsigned int gpuaddr, unsigned int size) { struct kgsl_snapshot_object *obj; @@ -346,13 +392,14 @@ EXPORT_SYMBOL(kgsl_snapshot_have_object); * size of the object being frozen */ -int kgsl_snapshot_get_object(struct kgsl_device *device, unsigned int ptbase, +int kgsl_snapshot_get_object(struct kgsl_device *device, phys_addr_t ptbase, unsigned int gpuaddr, unsigned int size, unsigned int type) { struct kgsl_mem_entry *entry; struct kgsl_snapshot_object *obj; int offset; int ret = -EINVAL; + unsigned int mem_type; if (!gpuaddr) return 0; @@ -371,6 +418,18 @@ int kgsl_snapshot_get_object(struct kgsl_device *device, unsigned int ptbase, "Only internal GPU buffers can be frozen\n"); goto err_put; } + /* + * Do not save texture and render targets in snapshot, + * they can be just too big + */ + mem_type = (entry->memdesc.flags & KGSL_MEMTYPE_MASK) >> + KGSL_MEMTYPE_SHIFT; + if (KGSL_MEMTYPE_TEXTURE == mem_type || + KGSL_MEMTYPE_EGL_SURFACE == mem_type || + KGSL_MEMTYPE_EGL_IMAGE == mem_type) { + ret = 0; + goto err_put; + } /* * size indicates the number of bytes in the region to save. This might @@ -397,21 +456,24 @@ int kgsl_snapshot_get_object(struct kgsl_device *device, unsigned int ptbase, /* If the buffer is already on the list, skip it */ list_for_each_entry(obj, &device->snapshot_obj_list, node) { - if (obj->gpuaddr == gpuaddr && obj->ptbase == ptbase) { - /* If the size is different, use the bigger size */ - if (obj->size < size) - obj->size = size; + /* combine the range with existing object if they overlap */ + if (obj->ptbase == ptbase && obj->type == type && + kgsl_addr_range_overlap(obj->gpuaddr, obj->size, + gpuaddr, size)) { + unsigned int end1 = obj->gpuaddr + obj->size; + unsigned int end2 = gpuaddr + size; + if (obj->gpuaddr > gpuaddr) + obj->gpuaddr = gpuaddr; + if (end1 > end2) + obj->size = end1 - obj->gpuaddr; + else + obj->size = end2 - obj->gpuaddr; + obj->offset = obj->gpuaddr - entry->memdesc.gpuaddr; ret = 0; goto err_put; } } - if (kgsl_memdesc_map(&entry->memdesc) == NULL) { - KGSL_DRV_ERR(device, "Unable to map GPU buffer %X\n", - gpuaddr); - goto err_put; - } - obj = kzalloc(sizeof(*obj), GFP_KERNEL); if (obj == NULL) { @@ -542,6 +604,20 @@ int kgsl_device_snapshot(struct kgsl_device *device, int hang) int remain = device->snapshot_maxsize - sizeof(*header); void *snapshot; struct timespec boot; + int ret = 0; + + /* + * Bail if failed to get active count for GPU, + * try again + */ + if (kgsl_active_count_get(device)) { + KGSL_DRV_ERR(device, "Failed to get GPU active count"); + return -EINVAL; + } + + /* increment the hang count (on hang) for good book keeping */ + if (hang) + device->snapshot_faultcount++; /* * The first hang is always the one we are interested in. To @@ -552,19 +628,23 @@ int kgsl_device_snapshot(struct kgsl_device *device, int hang) * of the state and never frozen. */ - if (hang && device->snapshot_frozen == 1) - return 0; + if (hang && device->snapshot_frozen == 1) { + ret = 0; + goto done; + } if (device->snapshot == NULL) { KGSL_DRV_ERR(device, "snapshot: No snapshot memory available\n"); - return -ENOMEM; + ret = -ENOMEM; + goto done; } if (remain < sizeof(*header)) { KGSL_DRV_ERR(device, "snapshot: Not enough memory for the header\n"); - return -ENOMEM; + ret = -ENOMEM; + goto done; } header->magic = SNAPSHOT_MAGIC; @@ -600,7 +680,10 @@ int kgsl_device_snapshot(struct kgsl_device *device, int hang) __pa(device->snapshot), device->snapshot_size); if (hang) sysfs_notify(&device->snapshot_kobj, NULL, "timestamp"); - return 0; + +done: + kgsl_active_count_put(device); + return ret; } EXPORT_SYMBOL(kgsl_device_snapshot); @@ -612,6 +695,32 @@ struct kgsl_snapshot_attribute { size_t count); }; +/* + * kgsl_snapshot_process_ib_obj_list() - Go through the list of IB's which need + * to be dumped for snapshot and move them to the global snapshot list so + * they will get dumped when the global list is dumped + * @device: device being snapshotted + */ +static void kgsl_snapshot_process_ib_obj_list(struct kgsl_device *device) +{ + struct kgsl_snapshot_cp_obj *obj, *obj_temp; + struct adreno_ib_object *ib_obj; + int i; + + list_for_each_entry_safe(obj, obj_temp, &device->snapshot_cp_list, + node) { + for (i = 0; i < obj->ib_obj_list->num_objs; i++) { + ib_obj = &(obj->ib_obj_list->obj_list[i]); + kgsl_snapshot_get_object(device, obj->ptbase, + ib_obj->gpuaddr, ib_obj->size, + ib_obj->snapshot_obj_type); + } + list_del(&obj->node); + adreno_ib_destroy_obj_list(obj->ib_obj_list); + kfree(obj); + } +} + #define to_snapshot_attr(a) \ container_of(a, struct kgsl_snapshot_attribute, attr) @@ -646,6 +755,13 @@ static ssize_t snapshot_show(struct file *filep, struct kobject *kobj, if (ret == 0) goto done; + kgsl_snapshot_process_ib_obj_list(device); + + if (device->snapshot_cur_ib_objs) { + obj_itr_out(&itr, device->snapshot_cur_ib_objs, + device->snapshot_cur_ib_objs_size); + } + list_for_each_entry(obj, &device->snapshot_obj_list, node) kgsl_snapshot_dump_object(device, obj, &itr); @@ -669,6 +785,12 @@ static ssize_t snapshot_show(struct file *filep, struct kobject *kobj, node) kgsl_snapshot_put_object(device, obj); + if (device->snapshot_cur_ib_objs) { + vfree(device->snapshot_cur_ib_objs); + device->snapshot_cur_ib_objs = NULL; + device->snapshot_cur_ib_objs_size = 0; + } + if (device->snapshot_frozen) KGSL_DRV_ERR(device, "Snapshot objects released\n"); @@ -681,6 +803,22 @@ static ssize_t snapshot_show(struct file *filep, struct kobject *kobj, return itr.write; } +/* Show the total number of hangs since device boot */ +static ssize_t faultcount_show(struct kgsl_device *device, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%d\n", device->snapshot_faultcount); +} + +/* Reset the total number of hangs since device boot */ +static ssize_t faultcount_store(struct kgsl_device *device, const char *buf, + size_t count) +{ + if (device && count > 0) + device->snapshot_faultcount = 0; + + return count; +} + /* Show the timestamp of the last collected snapshot */ static ssize_t timestamp_show(struct kgsl_device *device, char *buf) { @@ -693,7 +831,10 @@ static ssize_t trigger_store(struct kgsl_device *device, const char *buf, { if (device && count > 0) { mutex_lock(&device->mutex); - kgsl_device_snapshot(device, 0); + if (!kgsl_active_count_get(device)) { + kgsl_device_snapshot(device, 0); + kgsl_active_count_put(device); + } mutex_unlock(&device->mutex); } @@ -716,6 +857,7 @@ struct kgsl_snapshot_attribute attr_##_name = { \ SNAPSHOT_ATTR(trigger, 0600, NULL, trigger_store); SNAPSHOT_ATTR(timestamp, 0444, timestamp_show, NULL); +SNAPSHOT_ATTR(faultcount, 0644, faultcount_show, faultcount_store); static void snapshot_sysfs_release(struct kobject *kobj) { @@ -781,8 +923,12 @@ int kgsl_device_snapshot_init(struct kgsl_device *device) device->snapshot_maxsize = KGSL_SNAPSHOT_MEMSIZE; device->snapshot_timestamp = 0; + device->snapshot_faultcount = 0; INIT_LIST_HEAD(&device->snapshot_obj_list); + INIT_LIST_HEAD(&device->snapshot_cp_list); + device->snapshot_cur_ib_objs = NULL; + device->snapshot_cur_ib_objs_size = 0; ret = kobject_init_and_add(&device->snapshot_kobj, &ktype_snapshot, &device->dev->kobj, "snapshot"); @@ -798,6 +944,10 @@ int kgsl_device_snapshot_init(struct kgsl_device *device) goto done; ret = sysfs_create_file(&device->snapshot_kobj, &attr_timestamp.attr); + if (ret) + goto done; + + ret = sysfs_create_file(&device->snapshot_kobj, &attr_faultcount.attr); done: return ret; @@ -824,5 +974,123 @@ void kgsl_device_snapshot_close(struct kgsl_device *device) device->snapshot = NULL; device->snapshot_maxsize = 0; device->snapshot_timestamp = 0; + device->snapshot_faultcount = 0; } EXPORT_SYMBOL(kgsl_device_snapshot_close); + +/* + * kgsl_snapshot_add_ib_obj_list() - Add a IB object list to the snapshot + * object list + * @device: the device that is being snapshotted + * @ib_obj_list: The IB list that has objects required to execute an IB + * @num_objs: Number of IB objects + * @ptbase: The pagetable base in which the IB is mapped + * + * Adds a new IB to the list of IB objects maintained when getting snapshot + * Returns 0 on success else -ENOMEM on error + */ +int kgsl_snapshot_add_ib_obj_list(struct kgsl_device *device, + phys_addr_t ptbase, + struct adreno_ib_object_list *ib_obj_list) +{ + struct kgsl_snapshot_cp_obj *obj; + + obj = kzalloc(sizeof(*obj), GFP_KERNEL); + if (!obj) + return -ENOMEM; + obj->ib_obj_list = ib_obj_list; + obj->ptbase = ptbase; + list_add(&obj->node, &device->snapshot_cp_list); + return 0; +} + +/* + * snapshot_object() - Dump an IB object into memory + * @device - Device being snapshotted + * @snapshot - Snapshot memory + * @remain - Amount of bytes that the snapshot memory can take + * @priv - Pointer to the object being snapshotted + * + * Returns the amount of bytes written + */ +static int snapshot_object(struct kgsl_device *device, void *snapshot, + int remain, void *priv) +{ + int ret = 0; + struct kgsl_snapshot_object *obj = priv; + struct kgsl_snapshot_gpu_object *header = snapshot; + void *dest; + + if (remain < sizeof(*header) + obj->size) { + KGSL_DRV_ERR(device, "Not enough space in snapshot\n"); + return ret; + } + header->size = obj->size >> 2; + header->gpuaddr = obj->gpuaddr; + header->ptbase = (__u32)obj->ptbase; + header->type = obj->type; + dest = snapshot + sizeof(*header); + + if (!kgsl_memdesc_map(&obj->entry->memdesc)) { + KGSL_DRV_ERR(device, "Failed to map memdesc\n"); + return 0; + } + memcpy(dest, obj->entry->memdesc.hostptr + obj->offset, obj->size); + ret += sizeof(*header) + obj->size; + kgsl_memdesc_unmap(&obj->entry->memdesc); + return ret; +} + +/* + * kgsl_snapshot_save_frozen_objs - Save the objects frozen in snapshot into + * memory so that the data reported in these objects is correct when snapshot + * is taken + * @work - The work item that scheduled this work + */ +void kgsl_snapshot_save_frozen_objs(struct work_struct *work) +{ + struct kgsl_device *device = container_of(work, struct kgsl_device, + snapshot_obj_ws); + struct kgsl_snapshot_object *snapshot_obj, *snapshot_obj_temp; + unsigned int remain = 0; + void *snapshot_dest; + + mutex_lock(&device->mutex); + + kgsl_snapshot_process_ib_obj_list(device); + + /* If already exists then wait for it to be released */ + if (device->snapshot_cur_ib_objs) + goto done; + + list_for_each_entry_safe(snapshot_obj, snapshot_obj_temp, + &device->snapshot_obj_list, node) { + snapshot_obj->size = ALIGN(snapshot_obj->size, 4); + remain += (snapshot_obj->size + + sizeof(struct kgsl_snapshot_gpu_object) + + sizeof(struct kgsl_snapshot_section_header)); + } + if (!remain) + goto done; + + device->snapshot_cur_ib_objs = vmalloc(remain); + if (!device->snapshot_cur_ib_objs) + goto done; + + KGSL_DRV_ERR(device, + "Allocated memory for snapshot objects at address %p, size %x\n", + device->snapshot_cur_ib_objs, remain); + snapshot_dest = device->snapshot_cur_ib_objs; + device->snapshot_cur_ib_objs_size = remain; + + list_for_each_entry_safe(snapshot_obj, snapshot_obj_temp, + &device->snapshot_obj_list, node) { + snapshot_dest = kgsl_snapshot_add_section(device, + KGSL_SNAPSHOT_SECTION_GPU_OBJECT, + snapshot_dest, &remain, snapshot_object, + snapshot_obj); + kgsl_snapshot_put_object(device, snapshot_obj); + } +done: + mutex_unlock(&device->mutex); +} diff --git a/drivers/gpu/msm/kgsl_snapshot.h b/drivers/gpu/msm/kgsl_snapshot.h index 327d18a136b..00a83ac57e5 100644 --- a/drivers/gpu/msm/kgsl_snapshot.h +++ b/drivers/gpu/msm/kgsl_snapshot.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2013, The Linux Foundation. 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 and @@ -52,6 +52,7 @@ struct kgsl_snapshot_section_header { #define KGSL_SNAPSHOT_SECTION_DEBUG 0x0901 #define KGSL_SNAPSHOT_SECTION_DEBUGBUS 0x0A01 #define KGSL_SNAPSHOT_SECTION_GPU_OBJECT 0x0B01 +#define KGSL_SNAPSHOT_SECTION_MEMLIST 0x0E01 #define KGSL_SNAPSHOT_SECTION_END 0xFFFF @@ -103,6 +104,17 @@ struct kgsl_snapshot_rb { int count; /* Number of dwords in the dump */ } __packed; +/* Replay or Memory list section, both sections have same header */ +struct kgsl_snapshot_replay_mem_list { + /* + * Number of IBs to replay for replay section or + * number of memory list entries for mem list section + */ + int num_entries; + /* Pagetable base to which the replay IBs or memory entries belong */ + __u32 ptbase; +} __packed; + /* Indirect buffer sub-section header */ struct kgsl_snapshot_ib { __u32 gpuaddr; /* GPU address of the the IB */ @@ -308,11 +320,17 @@ void *kgsl_snapshot_indexed_registers(struct kgsl_device *device, unsigned int data, unsigned int start, unsigned int count); /* Freeze a GPU buffer so it can be dumped in the snapshot */ -int kgsl_snapshot_get_object(struct kgsl_device *device, unsigned int ptbase, +int kgsl_snapshot_get_object(struct kgsl_device *device, phys_addr_t ptbase, unsigned int gpuaddr, unsigned int size, unsigned int type); -int kgsl_snapshot_have_object(struct kgsl_device *device, unsigned int ptbase, +int kgsl_snapshot_have_object(struct kgsl_device *device, phys_addr_t ptbase, unsigned int gpuaddr, unsigned int size); +struct adreno_ib_object_list; + +int kgsl_snapshot_add_ib_obj_list(struct kgsl_device *device, + phys_addr_t ptbase, + struct adreno_ib_object_list *ib_obj_list); + #endif #endif diff --git a/drivers/gpu/msm/kgsl_sync.c b/drivers/gpu/msm/kgsl_sync.c index b74d4604d14..0e7606e842c 100644 --- a/drivers/gpu/msm/kgsl_sync.c +++ b/drivers/gpu/msm/kgsl_sync.c @@ -13,9 +13,12 @@ #include #include +#include #include #include +#include + #include "kgsl_sync.h" struct sync_pt *kgsl_sync_pt_create(struct sync_timeline *timeline, @@ -189,24 +192,77 @@ int kgsl_add_fence_event(struct kgsl_device *device, return ret; } +static unsigned int kgsl_sync_get_timestamp( + struct kgsl_sync_timeline *ktimeline, enum kgsl_timestamp_type type) +{ + struct kgsl_context *context = idr_find(&ktimeline->device->context_idr, + ktimeline->context_id); + if (context == NULL) + return 0; + + return kgsl_readtimestamp(ktimeline->device, context, type); +} + +static void kgsl_sync_timeline_value_str(struct sync_timeline *sync_timeline, + char *str, int size) +{ + struct kgsl_sync_timeline *ktimeline = + (struct kgsl_sync_timeline *) sync_timeline; + unsigned int timestamp_retired = kgsl_sync_get_timestamp(ktimeline, + KGSL_TIMESTAMP_RETIRED); + snprintf(str, size, "%u retired:%u", ktimeline->last_timestamp, + timestamp_retired); +} + +static void kgsl_sync_pt_value_str(struct sync_pt *sync_pt, + char *str, int size) +{ + struct kgsl_sync_pt *kpt = (struct kgsl_sync_pt *) sync_pt; + snprintf(str, size, "%u", kpt->timestamp); +} + +static void kgsl_sync_timeline_release_obj(struct sync_timeline *sync_timeline) +{ + /* + * Make sure to free the timeline only after destroy flag is set. + * This is to avoid further accessing to the timeline from KGSL and + * also to catch any unbalanced kref of timeline. + */ + BUG_ON(sync_timeline && (sync_timeline->destroyed != true)); +} static const struct sync_timeline_ops kgsl_sync_timeline_ops = { .driver_name = "kgsl-timeline", .dup = kgsl_sync_pt_dup, .has_signaled = kgsl_sync_pt_has_signaled, .compare = kgsl_sync_pt_compare, + .timeline_value_str = kgsl_sync_timeline_value_str, + .pt_value_str = kgsl_sync_pt_value_str, + .release_obj = kgsl_sync_timeline_release_obj, }; int kgsl_sync_timeline_create(struct kgsl_context *context) { struct kgsl_sync_timeline *ktimeline; + /* Generate a name which includes the thread name, thread id, process + * name, process id, and context id. This makes it possible to + * identify the context of a timeline in the sync dump. */ + char ktimeline_name[sizeof(context->timeline->name)] = {}; + snprintf(ktimeline_name, sizeof(ktimeline_name), + "%s_%.15s(%d)-%.15s(%d)-%d", + context->device->name, + current->group_leader->comm, current->group_leader->pid, + current->comm, current->pid, context->id); + context->timeline = sync_timeline_create(&kgsl_sync_timeline_ops, - (int) sizeof(struct kgsl_sync_timeline), "kgsl-timeline"); + (int) sizeof(struct kgsl_sync_timeline), ktimeline_name); if (context->timeline == NULL) return -EINVAL; ktimeline = (struct kgsl_sync_timeline *) context->timeline; ktimeline->last_timestamp = 0; + ktimeline->device = context->dev_priv->device; + ktimeline->context_id = context->id; return 0; } diff --git a/drivers/gpu/msm/kgsl_sync.h b/drivers/gpu/msm/kgsl_sync.h index 2f28b21fc6d..275eaf07dfb 100644 --- a/drivers/gpu/msm/kgsl_sync.h +++ b/drivers/gpu/msm/kgsl_sync.h @@ -19,6 +19,8 @@ struct kgsl_sync_timeline { struct sync_timeline timeline; unsigned int last_timestamp; + struct kgsl_device *device; + u32 context_id; }; struct kgsl_sync_pt { diff --git a/drivers/gpu/msm/kgsl_trace.h b/drivers/gpu/msm/kgsl_trace.h index b55075935db..5f39b8bb3ec 100644 --- a/drivers/gpu/msm/kgsl_trace.h +++ b/drivers/gpu/msm/kgsl_trace.h @@ -69,7 +69,7 @@ TRACE_EVENT(kgsl_issueibcmds, ), TP_printk( - "d_name=%s ctx=%u ib=0x%u numibs=%u timestamp=0x%x " + "d_name=%s ctx=%u ib=0x%u numibs=%u ts=%u " "flags=0x%x(%s) result=%d type=%s", __get_str(device_name), __entry->drawctxt_id, @@ -115,7 +115,7 @@ TRACE_EVENT(kgsl_readtimestamp, ), TP_printk( - "d_name=%s context_id=%u type=%u timestamp=0x%x", + "d_name=%s context_id=%u type=%u ts=%u", __get_str(device_name), __entry->context_id, __entry->type, @@ -153,7 +153,7 @@ TRACE_EVENT(kgsl_waittimestamp_entry, ), TP_printk( - "d_name=%s context_id=%u curr_ts=0x%x timestamp=0x%x timeout=%u", + "d_name=%s ctx=%u curr_ts=%u ts=%u timeout=%u", __get_str(device_name), __entry->context_id, __entry->curr_ts, @@ -185,7 +185,7 @@ TRACE_EVENT(kgsl_waittimestamp_exit, ), TP_printk( - "d_name=%s curr_ts=0x%x result=%d", + "d_name=%s curr_ts=%u result=%d", __get_str(device_name), __entry->curr_ts, __entry->result @@ -208,7 +208,7 @@ DECLARE_EVENT_CLASS(kgsl_pwr_template, ), TP_printk( - "d_name=%s %s", + "d_name=%s flag=%s", __get_str(device_name), __entry->on ? "on" : "off" ) @@ -261,26 +261,29 @@ TRACE_EVENT(kgsl_pwrlevel, ) ); -TRACE_EVENT(kgsl_mpdcvs, +TRACE_EVENT(kgsl_gpubusy, + TP_PROTO(struct kgsl_device *device, unsigned int busy, + unsigned int elapsed), - TP_PROTO(struct kgsl_device *device, unsigned int state), - - TP_ARGS(device, state), + TP_ARGS(device, busy, elapsed), TP_STRUCT__entry( __string(device_name, device->name) - __field(unsigned int, state) + __field(unsigned int, busy) + __field(unsigned int, elapsed) ), TP_fast_assign( __assign_str(device_name, device->name); - __entry->state = state; + __entry->busy = busy; + __entry->elapsed = elapsed; ), TP_printk( - "d_name=%s %s", + "d_name=%s busy=%u elapsed=%d", __get_str(device_name), - __entry->state ? "BUSY" : "IDLE" + __entry->busy, + __entry->elapsed ) ); @@ -300,7 +303,7 @@ DECLARE_EVENT_CLASS(kgsl_pwrstate_template, ), TP_printk( - "d_name=%s %s", + "d_name=%s state=%s", __get_str(device_name), kgsl_pwrstate_to_str(__entry->state) ) @@ -342,7 +345,7 @@ TRACE_EVENT(kgsl_mem_alloc, ), TP_printk( - "gpuaddr=0x%08x size=%d tgid=%d usage=%s id=%d flags=0x%08x", + "gpuaddr=0x%08x size=%u tgid=%u usage=%s id=%u flags=0x%08x", __entry->gpuaddr, __entry->size, __entry->tgid, __entry->usage, __entry->id, __entry->flags ) @@ -374,7 +377,7 @@ TRACE_EVENT(kgsl_mem_mmap, ), TP_printk( - "useraddr=%lx gpuaddr=0x%08x size=%d usage=%s id=%d" + "useraddr=0x%lx gpuaddr=0x%08x size=%u usage=%s id=%u" " flags=0x%08x", __entry->useraddr, __entry->gpuaddr, __entry->size, __entry->usage, __entry->id, __entry->flags @@ -405,7 +408,7 @@ TRACE_EVENT(kgsl_mem_unmapped_area_collision, ), TP_printk( - "id=%d hint=0x%lx len=%ld addr=0x%lx", + "id=%u hint=0x%lx len=%lu addr=0x%lx", __entry->id, __entry->hint, __entry->len, __entry->addr ) ); @@ -438,7 +441,7 @@ TRACE_EVENT(kgsl_mem_map, ), TP_printk( - "gpuaddr=0x%08x size=%d type=%d fd=%d tgid=%d usage=%s id=%d", + "gpuaddr=0x%08x size=%u type=%d fd=%d tgid=%u usage=%s id=%u", __entry->gpuaddr, __entry->size, __entry->type, __entry->fd, __entry->tgid, __entry->usage, __entry->id @@ -472,7 +475,7 @@ TRACE_EVENT(kgsl_mem_free, ), TP_printk( - "gpuaddr=0x%08x size=%d type=%d tgid=%d usage=%s id=%d", + "gpuaddr=0x%08x size=%u type=%d tgid=%u usage=%s id=%u", __entry->gpuaddr, __entry->size, __entry->type, __entry->tgid, __entry->usage, __entry->id ) @@ -504,7 +507,7 @@ TRACE_EVENT(kgsl_mem_sync_cache, ), TP_printk( - "gpuaddr=0x%08x size=%d tgid=%d usage=%s id=%d op=%c%c", + "gpuaddr=0x%08x size=%u tgid=%u usage=%s id=%u op=%c%c", __entry->gpuaddr, __entry->size, __entry->tgid, __entry->usage, __entry->id, (__entry->op & KGSL_GPUMEM_CACHE_CLEAN) ? 'c' : '.', @@ -572,8 +575,8 @@ DECLARE_EVENT_CLASS(kgsl_mem_timestamp_template, ), TP_printk( - "d_name=%s gpuaddr=0x%08x size=%d type=%d usage=%s id=%d ctx=%u" - " curr_ts=0x%x free_ts=0x%x", + "d_name=%s gpuaddr=0x%08x size=%u type=%d usage=%s id=%u ctx=%u" + " curr_ts=%u free_ts=%u", __get_str(device_name), __entry->gpuaddr, __entry->size, @@ -695,7 +698,7 @@ TRACE_EVENT(kgsl_mmu_pagefault, ), TP_printk( - "d_name=%s page=0x%08x pt=%d op=%s", + "d_name=%s page=0x%08x pt=%u op=%s", __get_str(device_name), __entry->page, __entry->pt, __get_str(op) ) @@ -721,46 +724,52 @@ TRACE_EVENT(kgsl_regwrite, ), TP_printk( - "d_name=%s reg=%x value=%x", + "d_name=%s reg=0x%x value=0x%x", __get_str(device_name), __entry->offset, __entry->value ) ); TRACE_EVENT(kgsl_register_event, - TP_PROTO(unsigned int id, unsigned int timestamp), - TP_ARGS(id, timestamp), + TP_PROTO(unsigned int id, unsigned int timestamp, void *func), + TP_ARGS(id, timestamp, func), TP_STRUCT__entry( __field(unsigned int, id) __field(unsigned int, timestamp) + __field(void *, func) ), TP_fast_assign( __entry->id = id; __entry->timestamp = timestamp; + __entry->func = func; ), TP_printk( - "ctx=%d ts=%d", - __entry->id, __entry->timestamp) + "ctx=%u ts=%u cb=%pF", + __entry->id, __entry->timestamp, __entry->func) ); TRACE_EVENT(kgsl_fire_event, TP_PROTO(unsigned int id, unsigned int ts, - unsigned int type, unsigned int age), - TP_ARGS(id, ts, type, age), + unsigned int type, unsigned int age, void *func), + TP_ARGS(id, ts, type, age, func), TP_STRUCT__entry( __field(unsigned int, id) __field(unsigned int, ts) __field(unsigned int, type) __field(unsigned int, age) + __field(void *, func) ), TP_fast_assign( __entry->id = id; __entry->ts = ts; __entry->type = type; __entry->age = age; + __entry->func = func; ), TP_printk( - "ctx=%d ts=%d type=%d age=%u", - __entry->id, __entry->ts, __entry->type, __entry->age) + "ctx=%u ts=%u type=%s age=%u cb=%pF", + __entry->id, __entry->ts, + __print_symbolic(__entry->type, KGSL_EVENT_TYPES), + __entry->age, __entry->func) ); TRACE_EVENT(kgsl_active_count, @@ -782,7 +791,7 @@ TRACE_EVENT(kgsl_active_count, ), TP_printk( - "d_name=%s active_cnt=%x func=%pf", + "d_name=%s active_cnt=%u func=%pf", __get_str(device_name), __entry->count, (void *) __entry->ip ) ); diff --git a/drivers/gpu/msm/z180.c b/drivers/gpu/msm/z180.c index 9cebacec048..ac50a91cdd8 100644 --- a/drivers/gpu/msm/z180.c +++ b/drivers/gpu/msm/z180.c @@ -124,6 +124,8 @@ static void z180_cmdwindow_write(struct kgsl_device *device, | (MMU_CONFIG << MH_MMU_CONFIG__TC_R_CLNT_BEHAVIOR__SHIFT) \ | (MMU_CONFIG << MH_MMU_CONFIG__PA_W_CLNT_BEHAVIOR__SHIFT)) +#define KGSL_LOG_LEVEL_DEFAULT 3 + static const struct kgsl_functable z180_functable; static struct z180_device device_2d0 = { @@ -149,6 +151,12 @@ static struct z180_device device_2d0 = { }, .iomemname = KGSL_2D0_REG_MEMORY, .ftbl = &z180_functable, + .cmd_log = KGSL_LOG_LEVEL_DEFAULT, + .ctxt_log = KGSL_LOG_LEVEL_DEFAULT, + .drv_log = KGSL_LOG_LEVEL_DEFAULT, + .mem_log = KGSL_LOG_LEVEL_DEFAULT, + .pwr_log = KGSL_LOG_LEVEL_DEFAULT, + .pm_dump_enable = 0, }, .cmdwin_lock = __SPIN_LOCK_INITIALIZER(device_2d1.cmdwin_lock), }; @@ -216,8 +224,7 @@ static irqreturn_t z180_irq_handler(struct kgsl_device *device) } } - if ((device->pwrctrl.nap_allowed == true) && - (device->requested_state == KGSL_STATE_NONE)) { + if (device->requested_state == KGSL_STATE_NONE) { kgsl_pwrctrl_request_state(device, KGSL_STATE_NAP); queue_work(device->work_queue, &device->idle_check_ws); } @@ -488,10 +495,10 @@ z180_cmdstream_issueibcmds(struct kgsl_device_private *dev_priv, addmarker(&z180_dev->ringbuffer, z180_dev->current_timestamp); /* monkey patch the IB so that it jumps back to the ringbuffer */ - kgsl_sharedmem_writel(&entry->memdesc, + kgsl_sharedmem_writel(device, &entry->memdesc, ((sizedwords + 1) * sizeof(unsigned int)), rb_gpuaddr(z180_dev, z180_dev->current_timestamp)); - kgsl_sharedmem_writel(&entry->memdesc, + kgsl_sharedmem_writel(device, &entry->memdesc, ((sizedwords + 2) * sizeof(unsigned int)), nextcnt); @@ -621,8 +628,12 @@ static int z180_start(struct kgsl_device *device) static int z180_stop(struct kgsl_device *device) { + int ret; + device->ftbl->irqctrl(device, 0); - z180_idle(device); + ret = z180_idle(device); + if (ret) + return ret; del_timer_sync(&device->idle_timer); @@ -734,7 +745,7 @@ static void _z180_regwrite_simple(struct kgsl_device *device, BUG_ON(offsetwords*sizeof(uint32_t) >= device->reg_len); reg = (unsigned int *)(device->reg_virt + (offsetwords << 2)); - kgsl_cffdump_regwrite(device->id, offsetwords << 2, value); + kgsl_cffdump_regwrite(device, offsetwords << 2, value); /*ensure previous writes post before this one, * i.e. act like normal writel() */ wmb(); @@ -915,6 +926,8 @@ z180_drawctxt_detach(struct kgsl_context *context) if (z180_dev->ringbuffer.prevctx == context->id) { z180_dev->ringbuffer.prevctx = Z180_INVALID_CONTEXT; device->mmu.hwpagetable = device->mmu.defaultpagetable; + + /* Ignore the result - we are going down anyway */ kgsl_setstate(&device->mmu, KGSL_MEMSTORE_GLOBAL, KGSL_MMUFLAGS_PTUPDATE); } diff --git a/drivers/gpu/msm/z180_postmortem.c b/drivers/gpu/msm/z180_postmortem.c index 03ebdb572d8..bc53c0e9801 100644 --- a/drivers/gpu/msm/z180_postmortem.c +++ b/drivers/gpu/msm/z180_postmortem.c @@ -120,7 +120,7 @@ static void z180_dump_ib(struct kgsl_device *device) int rb_slot_num = -1; struct z180_device *z180_dev = Z180_DEVICE(device); struct kgsl_mem_entry *entry = NULL; - unsigned int pt_base; + phys_addr_t pt_base; unsigned int i; unsigned int j; char linebuf[CHARS_PER_LINE]; diff --git a/drivers/input/touchscreen/fw_data.b b/drivers/input/touchscreen/fw_data.b index 714c55c4945..d4b4bd6b062 100755 --- a/drivers/input/touchscreen/fw_data.b +++ b/drivers/input/touchscreen/fw_data.b @@ -1,91 +1,91 @@ 0xc0, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x5f, 0x40, 0x02, 0x98, 0x3f, 0x5e, 0x52, 0x98, 0x3f, 0x5f, 0x52, 0x98, 0x3f, 0x60, 0x52, 0x98, 0x3f, 0xc2, 0x52, 0x98, 0x3f, 0xc3, 0x52, 0x98, 0x3f, 0xc4, 0x52, 0x98, 0x3f, 0xc9, 0x52, 0x98, 0x3f, 0xce, 0x52, 0x98, 0x3f, 0xcf, 0x52, 0x98, 0x3f, 0xd0, 0x52, 0x98, 0x3f, 0xd1, 0x52, 0x98, 0x3f, 0xd2, 0x52, 0x98, 0x3f, 0xd3, 0x52, 0x98, 0x3f, 0xd4, 0x52, 0x98, 0x3f, 0xd5, 0x52, 0x98, 0x3f, 0xd6, 0x52, 0x98, 0x3f, 0xd7, 0x52, 0x98, 0x3f, 0xd8, 0x52, 0x98, 0x3f, 0xd9, 0x52, 0x98, 0x3f, 0xda, 0x52, 0x98, 0x3f, 0xdb, 0x52, 0x98, 0x3f, 0xdc, 0x52, 0x98, 0x3f, 0xdd, 0x52, 0x98, 0x3f, 0xde, 0x52, 0x98, 0x3f, 0xdf, 0x52, 0x98, 0x3f, 0xe0, 0x52, 0x98, 0x3f, 0xf4, 0x52, 0x98, 0x3f, 0xf5, 0x52, 0x98, 0x3f, 0x04, 0x53, 0x98, 0x3f, 0x05, 0x53, 0x98, 0x3f, 0x9c, 0x50, 0x98, 0x3f, 0x06, 0x53, 0xf8, 0x4c, 0x80, 0x02, 0x98, 0x3f, 0xdc, 0x53, 0x98, 0x3f, 0xdd, 0x53, 0x1a, 0x38, 0x00, 0x60, 0xbe, 0x58, 0xbd, 0x1d, 0x00, 0x60, 0xbe, 0x58, 0xbe, 0x1d, 0x00, 0x60, 0xbe, 0x58, 0xbf, 0x1d, 0x00, 0x60, 0xbe, 0x58, 0xc1, 0x1d, 0x00, 0x60, 0xbe, 0x58, 0x1b, 0x1f, 0x00, 0x60, 0xbe, 0x58, 0x1c, 0x1f, 0x7a, 0xad, 0xfe, 0x93, 0x1a, 0x38, 0x02, 0xa9, 0x00, 0xbc, 0xb1, 0x00, 0x48, 0xaa, 0x40, 0xaa, 0x00, 0xbd, 0xb1, 0x00, 0xf2, 0x62, 0x72, 0x6a, 0x40, 0xbd, 0xb0, 0x00, 0x02, 0xab, 0x1a, 0x38, 0x02, 0x60, 0x80, 0x68, 0xb2, 0x61, 0x2f, 0x38, 0xae, 0x02, 0x0b, 0x5a, 0x8a, 0xb9, 0x19, 0x01, 0x7a, 0xad, 0xfe, 0x93, 0x04, 0x60, 0x80, 0x68, 0xb4, 0x61, 0x6f, 0x38, 0xb8, 0x02, 0x0b, 0x5a, 0x8a, 0xb9, 0x19, 0x01, 0x1a, 0x38, 0x7f, 0x60, 0x1f, 0x68, 0x91, 0xb0, 0x1f, 0x60, 0x1f, 0x68, 0x00, 0xbd, 0xe2, 0x36, -0xc0, 0x02, 0x16, 0x00, 0x41, 0xa9, 0xff, 0x60, 0x1f, 0x68, 0x00, 0xbd, 0x91, 0x00, 0x80, 0x60, 0x1f, 0x68, 0x00, 0xbd, 0x96, 0x00, 0x41, 0xab, 0x5a, 0xa9, 0x51, 0x60, 0x0b, 0x68, 0x1e, 0x58, 0x5a, 0xab, 0x00, 0x60, 0x82, 0xb0, 0xed, 0xc6, 0xe5, 0xc6, 0x19, 0x38, 0x20, 0x5a, 0xbe, 0xa8, 0xe0, 0xa8, 0xcf, 0xc6, 0xf4, 0xc6, 0x94, 0xef, 0x19, 0x38, 0x24, 0x5a, 0xb9, 0xfc, 0xfa, 0xc7, 0xaf, 0x61, 0x1a, 0x69, 0x78, 0xa9, 0x94, 0xa9, 0x92, 0xaa, 0x82, 0xaa, 0x53, 0xc7, 0x1a, 0xc7, 0x19, 0x38, 0x22, 0x5a, 0xff, 0xf0, 0xa7, 0xaa, 0xd7, 0xc8, 0x64, 0xee, 0x92, 0xac, 0xfe, 0x91, 0x18, 0xc5, 0xde, 0xc5, 0x8a, 0xc7, 0xe5, 0xaa, 0x00, 0x60, 0xbe, 0x58, 0xe7, 0x00, 0x00, 0x60, 0x05, 0x68, 0xbe, 0x58, 0xe9, 0x00, 0x18, 0x60, 0x08, 0x68, 0xbe, 0x58, 0xe8, 0x00, 0xf5, 0xac, 0x00, 0x92, 0x4f, 0x8e, -0x00, 0x03, 0x8f, 0xa8, 0x97, 0xaa, 0x58, 0xd9, 0xed, 0xac, 0x03, 0x92, 0x19, 0x38, 0x91, 0x4b, 0x02, 0x9e, 0x19, 0x38, 0xde, 0x53, 0x02, 0x60, 0x72, 0x68, 0xe3, 0xeb, 0x01, 0xc9, 0x19, 0x38, 0xd9, 0x54, 0x04, 0xc9, 0xf2, 0x60, 0x72, 0x68, 0xe3, 0xeb, 0x08, 0x60, 0x1e, 0x58, 0x9a, 0xea, 0x3e, 0x58, 0x19, 0x10, 0xfb, 0x89, 0x00, 0x60, 0xbe, 0x58, 0xdd, 0x00, 0x00, 0x60, 0x1e, 0x58, 0x78, 0xa9, 0x9a, 0xea, 0x3e, 0x58, 0x19, 0x00, 0x9c, 0xc7, 0x18, 0x10, 0xf8, 0x89, 0x19, 0x38, 0x32, 0x4e, 0x02, 0x60, 0x72, 0x68, 0xe3, 0xeb, 0x01, 0xc9, 0x19, 0x38, 0x1a, 0x55, 0x04, 0xc9, 0xf2, 0x60, 0x72, 0x68, 0xe3, 0xeb, 0xf5, 0xaa, 0x08, 0x60, 0x1e, 0x58, 0x0c, 0xf1, 0x3e, 0x58, 0x19, 0x10, 0xfb, 0x89, 0x00, 0x60, 0x1e, 0x58, 0x78, 0xa9, 0x0c, 0xf1, 0x3e, 0x58, 0x19, 0x00, 0xce, 0xc7, 0xe7, 0xc1, -0x40, 0x03, 0x18, 0x10, 0xf8, 0x89, 0xe5, 0xc8, 0xc5, 0xfc, 0xe5, 0xa8, 0x26, 0x60, 0x04, 0x68, 0x3e, 0x61, 0x04, 0x69, 0x9e, 0x5a, 0xbb, 0x00, 0x57, 0x38, 0x3d, 0x58, 0x1a, 0x38, 0x34, 0x60, 0x12, 0x68, 0xbe, 0x58, 0xbd, 0x1d, 0x78, 0x60, 0x56, 0x68, 0xbe, 0x58, 0xbe, 0x1d, 0xbc, 0x60, 0x9a, 0x68, 0xbe, 0x58, 0xbf, 0x1d, 0xaa, 0x60, 0x55, 0x68, 0xbe, 0x58, 0x1b, 0x1f, 0x55, 0x60, 0xaa, 0x68, 0xbe, 0x58, 0x1c, 0x1f, 0x1a, 0x38, 0x9e, 0x58, 0xe8, 0x00, 0x9e, 0x59, 0xe9, 0x00, 0x19, 0x48, 0x01, 0x88, 0x42, 0xa9, 0xf6, 0xeb, 0xf5, 0xac, 0x07, 0x90, 0x5d, 0xeb, 0x00, 0x60, 0xbe, 0x58, 0x40, 0x1b, 0xbe, 0x58, 0x3c, 0x02, 0x7e, 0x9f, 0xdd, 0xac, 0x5a, 0x90, 0xed, 0xac, 0x3c, 0x92, 0x8d, 0xac, 0x23, 0x92, 0x00, 0x9e, 0x9e, 0x58, 0x50, 0x01, 0xbe, 0x58, 0x00, 0xf8, 0x9e, 0x58, 0x83, 0xa6, +0xc0, 0x02, 0x16, 0x00, 0x41, 0xa9, 0xff, 0x60, 0x1f, 0x68, 0x00, 0xbd, 0x91, 0x00, 0x80, 0x60, 0x1f, 0x68, 0x00, 0xbd, 0x96, 0x00, 0x41, 0xab, 0x5a, 0xa9, 0x4f, 0x60, 0x0b, 0x68, 0x1e, 0x58, 0x5a, 0xab, 0x00, 0x60, 0x82, 0xb0, 0xeb, 0xc6, 0xe3, 0xc6, 0x19, 0x38, 0x20, 0x5a, 0xbe, 0xa8, 0xe0, 0xa8, 0xcd, 0xc6, 0xf2, 0xc6, 0x94, 0xef, 0x19, 0x38, 0x24, 0x5a, 0xb9, 0xfc, 0xf8, 0xc7, 0xaf, 0x61, 0x1a, 0x69, 0x78, 0xa9, 0x94, 0xa9, 0x92, 0xaa, 0x82, 0xaa, 0x51, 0xc7, 0x18, 0xc7, 0x19, 0x38, 0x22, 0x5a, 0xff, 0xf0, 0xa7, 0xaa, 0xd5, 0xc8, 0x77, 0xee, 0x92, 0xac, 0xfe, 0x91, 0x16, 0xc5, 0xdc, 0xc5, 0x88, 0xc7, 0xe5, 0xaa, 0x00, 0x60, 0xbe, 0x58, 0xe7, 0x00, 0x00, 0x60, 0x05, 0x68, 0xbe, 0x58, 0xe9, 0x00, 0x18, 0x60, 0x08, 0x68, 0xbe, 0x58, 0xe8, 0x00, 0xf5, 0xac, 0x00, 0x92, 0x4a, 0x8e, +0x00, 0x03, 0x8f, 0xa8, 0x97, 0xaa, 0x58, 0xd9, 0xed, 0xac, 0x03, 0x92, 0x19, 0x38, 0x91, 0x4b, 0x02, 0x9e, 0x19, 0x38, 0xde, 0x53, 0x02, 0x60, 0x72, 0x68, 0x05, 0xec, 0xff, 0xc8, 0x19, 0x38, 0xd9, 0x54, 0x02, 0xc9, 0xf2, 0x60, 0x72, 0x68, 0x05, 0xec, 0x08, 0x60, 0x1e, 0x58, 0xbc, 0xea, 0x3e, 0x58, 0x19, 0x10, 0xfb, 0x89, 0x00, 0x60, 0xbe, 0x58, 0xdd, 0x00, 0x00, 0x60, 0x1e, 0x58, 0x78, 0xa9, 0xbc, 0xea, 0x3e, 0x58, 0x19, 0x00, 0x9a, 0xc7, 0x18, 0x10, 0xf8, 0x89, 0x19, 0x38, 0x32, 0x4e, 0x02, 0x60, 0x72, 0x68, 0x05, 0xec, 0xff, 0xc8, 0x19, 0x38, 0x1a, 0x55, 0x02, 0xc9, 0xf2, 0x60, 0x72, 0x68, 0x05, 0xec, 0xf5, 0xaa, 0x08, 0x60, 0x1e, 0x58, 0x0c, 0xf1, 0x3e, 0x58, 0x19, 0x10, 0xfb, 0x89, 0x00, 0x60, 0x1e, 0x58, 0x78, 0xa9, 0x0c, 0xf1, 0x3e, 0x58, 0x19, 0x00, 0xcc, 0xc7, 0xa7, 0xc2, +0x40, 0x03, 0x18, 0x10, 0xf8, 0x89, 0xe3, 0xc8, 0xc5, 0xfc, 0xe5, 0xa8, 0x26, 0x60, 0x04, 0x68, 0x3e, 0x61, 0x04, 0x69, 0x9e, 0x5a, 0xbb, 0x00, 0x57, 0x38, 0x3d, 0x58, 0x1a, 0x38, 0x34, 0x60, 0x12, 0x68, 0xbe, 0x58, 0xbd, 0x1d, 0x78, 0x60, 0x56, 0x68, 0xbe, 0x58, 0xbe, 0x1d, 0xbc, 0x60, 0x9a, 0x68, 0xbe, 0x58, 0xbf, 0x1d, 0xaa, 0x60, 0x55, 0x68, 0xbe, 0x58, 0x1b, 0x1f, 0x55, 0x60, 0xaa, 0x68, 0xbe, 0x58, 0x1c, 0x1f, 0x1a, 0x38, 0x9e, 0x58, 0xe8, 0x00, 0x9e, 0x59, 0xe9, 0x00, 0x19, 0x48, 0x01, 0x88, 0x42, 0xa9, 0x18, 0xec, 0xf5, 0xac, 0x07, 0x90, 0x7f, 0xeb, 0x00, 0x60, 0xbe, 0x58, 0x40, 0x1b, 0xbe, 0x58, 0x3c, 0x02, 0x7e, 0x9f, 0xdd, 0xac, 0x5a, 0x90, 0xed, 0xac, 0x3c, 0x92, 0x8d, 0xac, 0x23, 0x92, 0x00, 0x9e, 0x9e, 0x58, 0x50, 0x01, 0xbe, 0x58, 0x00, 0xf8, 0x9e, 0x58, 0xc5, 0xa6, 0x80, 0x03, 0xd5, 0x1a, 0xbe, 0x58, 0x02, 0xf8, 0x9e, 0x58, 0xd6, 0x1a, 0xbe, 0x58, 0x04, 0xf8, 0x9e, 0x58, 0xd7, 0x1a, 0xbe, 0x58, 0x05, 0xf8, 0x9e, 0x58, 0xd8, 0x1a, 0xbe, 0x58, 0x0a, 0xf8, 0x9e, 0x58, 0x57, 0x01, 0xbe, 0x58, 0x0c, 0xf8, 0x9e, 0x58, 0x5b, 0x01, 0xbe, 0x58, 0x0b, 0xf8, 0x9e, 0x58, 0x07, 0xf8, 0x19, 0x28, 0xbe, 0x58, 0x07, 0xf8, 0x32, 0x9e, 0x9e, 0x58, 0x50, 0x01, 0xbe, 0x58, 0x00, 0xf8, 0x21, 0x60, 0xbe, 0x58, 0x02, 0xf8, 0x48, 0x60, 0xbe, 0x58, 0x04, 0xf8, 0x04, 0x60, 0xbe, 0x58, 0x05, 0xf8, 0x04, 0x60, 0xbe, 0x58, 0x0a, 0xf8, 0x64, 0x60, 0xbe, 0x58, 0x0c, 0xf8, 0x0b, 0x60, 0xbe, 0x58, 0x0b, 0xf8, 0x1b, 0x9e, 0x00, 0x60, 0xbe, 0x58, 0x00, 0xf8, 0x21, 0x60, 0xbe, 0x58, 0x02, 0xf8, 0x94, 0x60, 0xbe, 0x58, 0x04, 0xf8, 0x2d, 0x60, 0xbe, 0x58, 0x05, 0xf8, 0x23, 0xab, -0xc0, 0x03, 0x2d, 0x60, 0xbe, 0x58, 0x0a, 0xf8, 0x94, 0x60, 0xbe, 0x58, 0x0c, 0xf8, 0x0f, 0x60, 0xbe, 0x58, 0x0b, 0xf8, 0x9e, 0x58, 0x07, 0xf8, 0x04, 0x38, 0xfe, 0xff, 0xbe, 0x58, 0x07, 0xf8, 0xdd, 0xaa, 0xa5, 0xac, 0x01, 0x90, 0xf5, 0xc8, 0x77, 0xe9, 0x19, 0x38, 0xf2, 0x41, 0xed, 0xac, 0x7a, 0x92, 0xd5, 0xaa, 0xe5, 0xa8, 0x4b, 0xe5, 0x0c, 0xf1, 0x9e, 0x58, 0xe8, 0x00, 0x9e, 0x59, 0xe9, 0x00, 0x19, 0x48, 0x01, 0x88, 0x42, 0xa9, 0xf6, 0xeb, 0x9e, 0x58, 0x36, 0x1d, 0x1d, 0x10, 0x21, 0x8a, 0x9e, 0x58, 0x36, 0x1d, 0x1b, 0x10, 0x1d, 0x8a, 0xdb, 0xf1, 0x86, 0xf6, 0x00, 0x60, 0xbe, 0x58, 0x43, 0x1a, 0x9e, 0x58, 0xb8, 0x04, 0x18, 0x10, 0x14, 0x88, 0x9e, 0x58, 0xc6, 0x00, 0x19, 0x10, 0x10, 0x8a, 0x9e, 0x58, 0xea, 0x19, 0x00, 0x58, 0xbe, 0x58, 0xd3, 0x00, 0x9e, 0x58, 0xeb, 0x19, 0x59, 0xe2, -0x00, 0x04, 0x00, 0x58, 0xbe, 0x58, 0xd4, 0x00, 0x9e, 0x58, 0xec, 0x19, 0x00, 0x58, 0xbe, 0x58, 0xd5, 0x00, 0x0c, 0x9e, 0xff, 0x60, 0xff, 0x68, 0xbe, 0x58, 0xd3, 0x00, 0xff, 0x60, 0xff, 0x68, 0xbe, 0x58, 0xd4, 0x00, 0xff, 0x60, 0xff, 0x68, 0xbe, 0x58, 0xd5, 0x00, 0x9e, 0x58, 0xfc, 0x01, 0x78, 0xac, 0x08, 0x90, 0xff, 0x60, 0xff, 0x68, 0xbe, 0x58, 0xd5, 0x00, 0xbe, 0x58, 0xd4, 0x00, 0xbe, 0x58, 0xd3, 0x00, 0x7b, 0xeb, 0xb5, 0xea, 0x9e, 0x58, 0xe8, 0x00, 0x9e, 0x59, 0xe9, 0x00, 0x19, 0x48, 0x01, 0x88, 0x42, 0xa9, 0xf6, 0xeb, 0x26, 0x60, 0x04, 0x68, 0x3e, 0x61, 0x04, 0x69, 0x9e, 0x5a, 0xbb, 0x00, 0x57, 0x38, 0x3d, 0x58, 0x06, 0x70, 0x00, 0xac, 0x12, 0x90, 0x9e, 0x58, 0xfc, 0x1c, 0x18, 0x10, 0x0e, 0x88, 0x9e, 0x58, 0x47, 0x1e, 0x78, 0xac, 0x01, 0x90, 0x0d, 0x9e, 0x60, 0xed, 0xc4, 0xb6, -0x40, 0x04, 0x9e, 0x58, 0x1e, 0x1e, 0x18, 0x10, 0x0d, 0x8a, 0xdc, 0xec, 0x3c, 0xed, 0x4e, 0xed, 0x86, 0xed, 0x9e, 0x58, 0x47, 0x1e, 0x78, 0xac, 0x05, 0x90, 0x78, 0xaa, 0xbe, 0x58, 0x47, 0x1e, 0xbe, 0x58, 0x04, 0xf8, 0x02, 0x9e, 0x9d, 0xf7, 0x00, 0x9e, 0x4f, 0xf7, 0x19, 0x38, 0xd7, 0x41, 0xe6, 0xff, 0x5e, 0xca, 0x91, 0xca, 0xc4, 0xca, 0x19, 0x38, 0xa1, 0x51, 0xba, 0xac, 0x0f, 0x92, 0x9e, 0x58, 0xc1, 0x1d, 0x06, 0x39, 0x55, 0x00, 0x05, 0x8a, 0x06, 0x39, 0xa5, 0x00, 0x02, 0x8a, 0x42, 0xa9, 0x78, 0x9e, 0x9d, 0x60, 0x4e, 0x68, 0xef, 0xb0, 0xff, 0xa9, 0x34, 0xc8, 0xba, 0xac, 0x71, 0x92, 0x9e, 0x58, 0xc1, 0x1d, 0x06, 0x39, 0x55, 0x00, 0x05, 0x8a, 0x06, 0x39, 0xa5, 0x00, 0x02, 0x8a, 0x42, 0xa9, 0x67, 0x9e, 0x9d, 0x60, 0x4e, 0x68, 0xef, 0xb0, 0xff, 0xa9, 0x95, 0xac, 0x05, 0x90, 0x8e, 0xd2, -0x80, 0x04, 0x9e, 0x5f, 0xfb, 0x04, 0xbe, 0x5f, 0xfb, 0x04, 0x95, 0xaa, 0x9e, 0x58, 0xc1, 0x1d, 0x06, 0x39, 0x55, 0x00, 0x05, 0x8a, 0x06, 0x39, 0xa5, 0x00, 0x02, 0x8a, 0x42, 0xa9, 0x52, 0x9e, 0x9d, 0x60, 0x4e, 0x68, 0xef, 0xb0, 0xff, 0xa9, 0xb9, 0xac, 0xd9, 0x91, 0xfd, 0xac, 0x1a, 0x90, 0x9e, 0x58, 0xc1, 0x1d, 0x06, 0x39, 0x55, 0x00, 0x05, 0x8a, 0x06, 0x39, 0xa5, 0x00, 0x02, 0x8a, 0x42, 0xa9, 0x40, 0x9e, 0x9d, 0x60, 0x4e, 0x68, 0xef, 0xb0, 0xff, 0xa9, 0x80, 0x62, 0x57, 0x6a, 0x48, 0x63, 0x0e, 0x6b, 0x0c, 0x61, 0x24, 0x60, 0x01, 0x40, 0x19, 0x10, 0x07, 0x38, 0xb0, 0x04, 0x45, 0x5c, 0x9d, 0x5b, 0x85, 0xac, 0x1f, 0x90, 0x9e, 0x58, 0xc1, 0x1d, 0x06, 0x39, 0x55, 0x00, 0x05, 0x8a, 0x06, 0x39, 0xa5, 0x00, 0x02, 0x8a, 0x42, 0xa9, 0x24, 0x9e, 0x9d, 0x60, 0x4e, 0x68, 0xef, 0xb0, 0x10, 0x62, -0xc0, 0x04, 0xff, 0xa9, 0x48, 0x62, 0x0e, 0x6a, 0x7a, 0x63, 0x02, 0x6b, 0x9e, 0x5c, 0xbb, 0x00, 0x9e, 0x5d, 0xbc, 0x00, 0xa4, 0x05, 0x19, 0x15, 0xa7, 0x38, 0xd1, 0x04, 0x63, 0x5c, 0x83, 0x5d, 0xbb, 0x5a, 0x19, 0x02, 0x19, 0x03, 0x9e, 0x58, 0xc1, 0x1d, 0x06, 0x39, 0x55, 0x00, 0x05, 0x8a, 0x06, 0x39, 0xa5, 0x00, 0x02, 0x8a, 0x42, 0xa9, 0x05, 0x9e, 0x9d, 0x60, 0x4e, 0x68, 0xef, 0xb0, 0xff, 0xa9, 0x58, 0xeb, 0x34, 0x61, 0x12, 0x69, 0x9e, 0x58, 0xbd, 0x1d, 0x38, 0x48, 0x02, 0x8a, 0x42, 0xa9, 0x0f, 0x9e, 0x78, 0x61, 0x56, 0x69, 0x9e, 0x58, 0xbe, 0x1d, 0x38, 0x48, 0x02, 0x8a, 0x42, 0xa9, 0x07, 0x9e, 0xbc, 0x61, 0x9a, 0x69, 0x9e, 0x58, 0xbf, 0x1d, 0x38, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x9d, 0x60, 0x4e, 0x68, 0xef, 0xb0, 0xff, 0xa9, 0x1a, 0x38, 0x9e, 0x58, 0xe8, 0x00, 0x9e, 0x59, 0x4e, 0x4c, -0x00, 0x05, 0xe9, 0x00, 0x19, 0x48, 0x01, 0x88, 0x42, 0xa9, 0xf6, 0xeb, 0x9e, 0x58, 0xf8, 0x04, 0x19, 0x00, 0xbe, 0x58, 0xf8, 0x04, 0x9e, 0x58, 0xe8, 0x00, 0x9e, 0x59, 0xe9, 0x00, 0x19, 0x48, 0x06, 0x88, 0x9e, 0x58, 0x19, 0x1f, 0x19, 0x00, 0xbe, 0x58, 0x19, 0x1f, 0x42, 0xa9, 0x98, 0x3f, 0x62, 0x03, 0x9e, 0x5e, 0x50, 0x01, 0x00, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xbc, 0x01, 0x01, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xbd, 0x01, 0x1f, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xbe, 0x01, 0x20, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xbf, 0x01, 0x21, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xd5, 0x1a, 0x02, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0x51, 0x01, 0xc8, 0x58, 0xc0, 0x06, 0x08, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0x52, 0x01, 0x03, 0x60, 0x18, 0x4e, -0x40, 0x05, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xd6, 0x1a, 0x04, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xd7, 0x1a, 0x05, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0x55, 0x01, 0x06, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0x56, 0x01, 0x07, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0x57, 0x01, 0x0c, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0x58, 0x01, 0x0e, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0x59, 0x01, 0x12, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xba, 0x01, 0x09, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xd8, 0x1a, 0x0a, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0x5b, 0x01, 0x0b, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0xb4, 0x60, 0x01, 0x68, 0x22, 0x61, 0xf8, 0x69, 0xb9, 0x66, 0x01, 0x6e, 0xc2, 0x3e, 0xb4, 0x01, 0xc7, 0x38, 0x7f, 0x05, 0x05, 0x5a, 0x5d, 0x59, 0xd1, 0xc0, -0x80, 0x05, 0x9e, 0x5e, 0x5c, 0x01, 0x0f, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0x5d, 0x01, 0x10, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x5e, 0x60, 0x01, 0x68, 0x28, 0x61, 0xf8, 0x69, 0x63, 0x66, 0x01, 0x6e, 0xc2, 0x3e, 0x5e, 0x01, 0xc7, 0x38, 0x95, 0x05, 0x05, 0x5a, 0x5d, 0x59, 0x9e, 0x5e, 0xbb, 0x01, 0x2e, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x64, 0x60, 0x01, 0x68, 0x2f, 0x61, 0xf8, 0x69, 0x6f, 0x66, 0x01, 0x6e, 0xc2, 0x3e, 0x64, 0x01, 0xc7, 0x38, 0xa6, 0x05, 0x05, 0x5a, 0x5d, 0x59, 0x70, 0x60, 0x01, 0x68, 0x3b, 0x61, 0xf8, 0x69, 0x7b, 0x66, 0x01, 0x6e, 0xc2, 0x3e, 0x70, 0x01, 0xc7, 0x38, 0xb2, 0x05, 0x05, 0x5a, 0x5d, 0x59, 0x7c, 0x60, 0x01, 0x68, 0x47, 0x61, 0xf8, 0x69, 0x52, 0x66, 0xf8, 0x6e, 0xc2, 0x3e, 0x47, 0xf8, 0xc7, 0x38, 0xc1, 0x05, 0x03, 0x5a, 0x05, 0x5b, 0xfe, 0x5b, 0x10, 0x49, -0xc0, 0x05, 0x43, 0x2a, 0x5d, 0x59, 0x94, 0x60, 0x01, 0x68, 0x53, 0x61, 0xf8, 0x69, 0x5e, 0x66, 0xf8, 0x6e, 0xc2, 0x3e, 0x53, 0xf8, 0xc7, 0x38, 0xd0, 0x05, 0x03, 0x5a, 0x05, 0x5b, 0xfe, 0x5b, 0x43, 0x2a, 0x5d, 0x59, 0xac, 0x60, 0x01, 0x68, 0x13, 0x61, 0xf8, 0x69, 0xb2, 0x66, 0x01, 0x6e, 0xc2, 0x3e, 0xac, 0x01, 0xc7, 0x38, 0xdc, 0x05, 0x05, 0x5a, 0x5d, 0x59, 0x3a, 0x38, 0x9e, 0x5e, 0xc3, 0x01, 0xaa, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xc7, 0x01, 0xaf, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xc8, 0x01, 0xb0, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xd9, 0x1a, 0xb1, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xca, 0x01, 0xb2, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xcd, 0x01, 0xb5, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xce, 0x01, 0xb6, 0x60, 0xf8, 0x68, 0xa3, 0x24, -0x00, 0x06, 0xdb, 0x58, 0x9e, 0x5e, 0xcf, 0x01, 0xb7, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xd0, 0x01, 0xd8, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xd1, 0x01, 0xb8, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xd3, 0x01, 0xba, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xd4, 0x01, 0xbb, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xd5, 0x01, 0xbc, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xd6, 0x01, 0xbd, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xd7, 0x01, 0xbe, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xd8, 0x01, 0xbf, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xd9, 0x01, 0xc0, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xda, 0x01, 0xc1, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xdb, 0x01, 0xc2, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xdc, 0x01, 0xc3, 0x60, 0x58, 0x44, -0x40, 0x06, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xdd, 0x01, 0xc4, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xde, 0x01, 0xc5, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xdf, 0x01, 0xc6, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xe0, 0x01, 0xc7, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xe1, 0x01, 0xc8, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xe2, 0x01, 0xc9, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xe3, 0x01, 0xca, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xe4, 0x01, 0xcb, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xe5, 0x01, 0xcc, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xe6, 0x01, 0xcd, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xe7, 0x01, 0xce, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xe8, 0x01, 0xcf, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xe9, 0x01, 0xf6, 0x4d, -0x80, 0x06, 0xd0, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xea, 0x01, 0xd1, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xeb, 0x01, 0xd2, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xec, 0x01, 0xd3, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xed, 0x01, 0xd4, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xee, 0x01, 0xd5, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xef, 0x01, 0xd6, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xf0, 0x01, 0xd7, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xf1, 0x01, 0xea, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xf2, 0x01, 0xeb, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xf3, 0x01, 0xec, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xf4, 0x01, 0xed, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xf5, 0x01, 0xee, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xaf, 0xae, -0xc0, 0x06, 0xf6, 0x01, 0xef, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xf7, 0x01, 0xf0, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xf8, 0x01, 0xf1, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x3a, 0x38, 0x00, 0xbc, 0xb1, 0x00, 0x18, 0xaa, 0x10, 0xaa, 0x00, 0xbd, 0xb1, 0x00, 0x00, 0x60, 0x80, 0xb0, 0x00, 0x60, 0x81, 0xb0, 0x00, 0x60, 0x82, 0xb0, 0x00, 0x60, 0x83, 0xb0, 0x00, 0x60, 0x9c, 0xb0, 0xc0, 0x60, 0x13, 0x68, 0x9d, 0xb0, 0x00, 0x60, 0xcf, 0xb0, 0x3a, 0x38, 0x41, 0xab, 0x51, 0xb0, 0x78, 0xa8, 0x70, 0xa8, 0x68, 0xaa, 0x60, 0xaa, 0xd1, 0xb0, 0x3a, 0x38, 0x00, 0x60, 0x1f, 0x68, 0x00, 0x61, 0x00, 0x62, 0x17, 0x38, 0x5d, 0x59, 0x3a, 0x38, 0x3e, 0xb0, 0x08, 0xaa, 0x00, 0xaa, 0x18, 0xaa, 0x10, 0xaa, 0xbe, 0xb0, 0x10, 0x60, 0x9e, 0xb0, 0x30, 0xb0, 0x38, 0xa8, 0xb0, 0xb0, 0x3e, 0xb0, 0x53, 0x60, -0x00, 0x07, 0x38, 0xaa, 0xbe, 0xb0, 0x84, 0xb0, 0x3c, 0xa9, 0x3e, 0xb0, 0x78, 0xaa, 0xbe, 0xb0, 0x00, 0x60, 0x00, 0xbd, 0xaa, 0x00, 0x30, 0xb0, 0x08, 0xaa, 0x18, 0xaa, 0x00, 0xbd, 0x30, 0x00, 0x36, 0xb0, 0x08, 0xaa, 0x18, 0xaa, 0x00, 0xbd, 0x36, 0x00, 0x33, 0xb0, 0x08, 0xa8, 0x18, 0xa8, 0x00, 0xbd, 0x33, 0x00, 0x3a, 0x38, 0x04, 0x60, 0x69, 0x78, 0x55, 0x60, 0x6a, 0x78, 0x6b, 0x78, 0x6c, 0x78, 0x6d, 0x78, 0x82, 0xac, 0x28, 0x92, 0x00, 0x60, 0x88, 0x68, 0xae, 0xb0, 0x20, 0x60, 0xc4, 0x68, 0xd0, 0xb0, 0x1e, 0x59, 0x1e, 0x5a, 0x93, 0x60, 0x2f, 0x68, 0x09, 0x58, 0x04, 0x39, 0xff, 0x00, 0x04, 0x3a, 0x00, 0xff, 0xfe, 0x5a, 0x22, 0x32, 0xff, 0x61, 0x04, 0x38, 0xff, 0x00, 0x3a, 0x48, 0x01, 0x8a, 0x10, 0x60, 0xd2, 0xb0, 0x3e, 0x5a, 0x3e, 0x59, 0x00, 0x60, 0x5d, 0x78, 0x19, 0x38, 0xe3, 0xbf, -0x40, 0x07, 0x8c, 0x50, 0x92, 0xaa, 0xaa, 0xac, 0x01, 0x90, 0x92, 0xa8, 0xaa, 0xaa, 0xf9, 0xab, 0xf1, 0xab, 0xfd, 0xa9, 0xf5, 0xa9, 0x01, 0x9e, 0x1a, 0x38, 0xaa, 0xac, 0x04, 0x92, 0xa2, 0xa8, 0x92, 0xc7, 0x82, 0xac, 0x00, 0x90, 0x3a, 0x38, 0x90, 0xaa, 0xa2, 0xaa, 0x81, 0xaa, 0xb9, 0xaa, 0xba, 0xa8, 0xb0, 0xa8, 0xb8, 0xaa, 0x02, 0x60, 0xbe, 0x58, 0x12, 0x00, 0x01, 0x60, 0xbe, 0x58, 0x11, 0x00, 0x01, 0x60, 0xbe, 0x58, 0xfb, 0x1c, 0xff, 0xaa, 0x00, 0x60, 0xbe, 0x58, 0x1b, 0x00, 0xbe, 0x58, 0xc6, 0x00, 0x00, 0x60, 0xbe, 0x58, 0xa3, 0x1c, 0xbe, 0x58, 0xa4, 0x1c, 0xbe, 0x58, 0xa5, 0x1c, 0xbe, 0x58, 0xfc, 0x1c, 0xbe, 0x58, 0xfd, 0x1c, 0xe6, 0xa8, 0x88, 0xb0, 0x89, 0xb0, 0x78, 0xa9, 0x3a, 0x38, 0x30, 0x60, 0x80, 0x68, 0xcf, 0xb0, 0xcd, 0xa9, 0x00, 0x60, 0xbe, 0x58, 0xae, 0x00, 0x1c, 0x57, -0x80, 0x07, 0x00, 0x60, 0xbe, 0x58, 0xaf, 0x00, 0xbe, 0x58, 0xc2, 0x1d, 0xbe, 0x58, 0xc3, 0x1d, 0xbe, 0x58, 0xc4, 0x1d, 0x3a, 0x38, 0x36, 0x60, 0x80, 0x68, 0x8f, 0xb0, 0xdd, 0xa9, 0x9d, 0x60, 0x4e, 0x68, 0xef, 0xb0, 0x3a, 0x38, 0x39, 0xb0, 0x38, 0xaa, 0xb9, 0xb0, 0x30, 0xb0, 0x38, 0xa8, 0xb0, 0xb0, 0x3c, 0xab, 0x3a, 0x38, 0x3c, 0xa9, 0x3a, 0x38, 0x02, 0x3f, 0x01, 0x00, 0x0c, 0x98, 0x30, 0x66, 0x0b, 0x6e, 0x9e, 0x5d, 0xe8, 0x00, 0x9e, 0x5f, 0xda, 0x00, 0x19, 0x17, 0xe7, 0x38, 0xa9, 0x07, 0xa5, 0x59, 0x3d, 0x5e, 0x22, 0x9e, 0x12, 0x3f, 0x22, 0x00, 0x1f, 0x98, 0x30, 0x66, 0x0b, 0x6e, 0x9e, 0x5d, 0xe8, 0x00, 0x9e, 0x5f, 0xda, 0x00, 0x19, 0x17, 0xe7, 0x38, 0xb9, 0x07, 0xa5, 0x5f, 0xd7, 0x07, 0xfd, 0x5e, 0x12, 0x3f, 0x22, 0x00, 0x10, 0x88, 0x30, 0x66, 0x0b, 0x6e, 0x9e, 0x5d, 0xde, 0xa4, -0xc0, 0x07, 0x22, 0x00, 0x9e, 0x5f, 0xda, 0x00, 0x19, 0x17, 0xe7, 0x38, 0xcb, 0x07, 0x00, 0x61, 0xc3, 0x58, 0x1c, 0x5d, 0x1d, 0x5e, 0x1a, 0x38, 0x1a, 0x38, 0x00, 0x60, 0x3a, 0x38, 0x02, 0x3f, 0x01, 0x00, 0x0a, 0x98, 0x29, 0x66, 0x03, 0x6e, 0xb5, 0x65, 0x02, 0x6d, 0x39, 0x67, 0xe7, 0x38, 0xd9, 0x07, 0xa5, 0x59, 0x3d, 0x5e, 0x1e, 0x9e, 0x12, 0x3f, 0x22, 0x00, 0x1b, 0x98, 0x29, 0x66, 0x03, 0x6e, 0xb5, 0x65, 0x02, 0x6d, 0x39, 0x67, 0xe7, 0x38, 0xe7, 0x07, 0xa5, 0x5f, 0xd7, 0x07, 0xfd, 0x5e, 0x12, 0x3f, 0x22, 0x00, 0x0e, 0x88, 0x29, 0x66, 0x03, 0x6e, 0x9e, 0x5d, 0x22, 0x00, 0x39, 0x67, 0xe7, 0x38, 0xf7, 0x07, 0x00, 0x61, 0xc3, 0x58, 0x1c, 0x5d, 0x1d, 0x5e, 0x1a, 0x38, 0x1a, 0x38, 0x00, 0x60, 0x3a, 0x38, 0xaf, 0x61, 0x1a, 0x69, 0x19, 0x01, 0x00, 0x60, 0x2f, 0x68, 0x93, 0x62, 0x7d, 0xbb, -0x00, 0x08, 0x57, 0x38, 0x0f, 0x59, 0x1a, 0x38, 0x3a, 0x38, 0x1e, 0x58, 0x1e, 0x59, 0x1e, 0x5a, 0x1e, 0x5b, 0x1e, 0x5c, 0x1e, 0x5d, 0x1e, 0x5e, 0x1e, 0x5f, 0x08, 0x60, 0x1e, 0x58, 0x9a, 0xea, 0x3e, 0x58, 0x19, 0x10, 0xfb, 0x89, 0x00, 0x60, 0x1e, 0x58, 0x78, 0xa9, 0x9a, 0xea, 0x3e, 0x58, 0x19, 0x00, 0x9c, 0xc7, 0x18, 0x10, 0xf8, 0x89, 0x08, 0x60, 0x1e, 0x58, 0x0c, 0xf1, 0x3e, 0x58, 0x19, 0x10, 0xfb, 0x89, 0x00, 0x60, 0x1e, 0x58, 0x78, 0xa9, 0x0c, 0xf1, 0x3e, 0x58, 0x19, 0x00, 0xce, 0xc7, 0x18, 0x10, 0xf8, 0x89, 0xe5, 0xa8, 0x3e, 0x5f, 0x3e, 0x5e, 0x3e, 0x5d, 0x3e, 0x5c, 0x3e, 0x5b, 0x3e, 0x5a, 0x3e, 0x59, 0x3e, 0x58, 0x3a, 0x38, 0x1e, 0x58, 0x1e, 0x59, 0x1e, 0x5a, 0x1e, 0x5b, 0x1e, 0x5c, 0x1e, 0x5d, 0x1e, 0x5e, 0x1e, 0x5f, 0xa2, 0x72, 0x07, 0x61, 0x22, 0x23, 0x03, 0x61, 0x17, 0x1e, -0x40, 0x08, 0x23, 0x32, 0x0a, 0x8a, 0x04, 0x61, 0x23, 0x32, 0x0e, 0x8a, 0x00, 0x61, 0x23, 0x32, 0x24, 0x8a, 0x02, 0x61, 0x23, 0x32, 0x2a, 0x8a, 0x2f, 0x9e, 0x9e, 0x5b, 0xe8, 0x00, 0xb5, 0x66, 0x02, 0x6e, 0xbe, 0x5e, 0x28, 0x1d, 0x28, 0x9e, 0x48, 0x63, 0x0e, 0x6b, 0x48, 0x66, 0x1d, 0x6e, 0x9e, 0x59, 0xbe, 0x00, 0x00, 0x64, 0x3c, 0x48, 0x0d, 0x8a, 0xfa, 0x06, 0x48, 0x67, 0x1d, 0x6f, 0xfa, 0x07, 0x19, 0x11, 0x27, 0x38, 0x66, 0x08, 0xe3, 0x59, 0x3b, 0x5e, 0x19, 0x07, 0x19, 0x06, 0x48, 0x66, 0x1d, 0x6e, 0xbe, 0x5e, 0x28, 0x1d, 0x0f, 0x9e, 0x18, 0xca, 0x48, 0x63, 0x0e, 0x6b, 0x2c, 0xc9, 0x7a, 0x66, 0x02, 0x6e, 0xbe, 0x5e, 0x28, 0x1d, 0x06, 0x9e, 0x30, 0x63, 0x0b, 0x6b, 0x29, 0x66, 0x03, 0x6e, 0xbe, 0x5e, 0x28, 0x1d, 0x60, 0x62, 0x11, 0x6a, 0xc0, 0x61, 0x03, 0x69, 0x24, 0x64, 0x62, 0x8d, -0x80, 0x08, 0x16, 0x65, 0x9e, 0x58, 0x28, 0x1d, 0x05, 0x00, 0x19, 0x05, 0x00, 0x66, 0x00, 0x67, 0xbe, 0x5f, 0x29, 0x1d, 0x27, 0x38, 0xcd, 0x08, 0x19, 0x06, 0xbe, 0x48, 0x09, 0x8a, 0x1e, 0x58, 0x9e, 0x58, 0x29, 0x1d, 0x00, 0xac, 0x02, 0x92, 0x65, 0x58, 0x1d, 0x5a, 0x3e, 0x58, 0x36, 0x9e, 0x05, 0x5e, 0xdd, 0x5a, 0x00, 0x66, 0x19, 0x07, 0xfc, 0x48, 0x01, 0x8a, 0x2f, 0x9e, 0x13, 0xb8, 0x14, 0xb8, 0x15, 0xb8, 0x1e, 0x5e, 0x9e, 0x58, 0x28, 0x1d, 0x9e, 0x5c, 0xb8, 0x00, 0x87, 0x38, 0xa9, 0x08, 0x05, 0x5e, 0xdd, 0x5a, 0x3e, 0x5e, 0x95, 0xb8, 0x94, 0xb8, 0x93, 0xb8, 0x19, 0x12, 0x01, 0x76, 0xdd, 0x5a, 0x9e, 0x58, 0x28, 0x1d, 0xfa, 0x00, 0x05, 0x5e, 0xdd, 0x5a, 0x05, 0x5e, 0xdd, 0x5a, 0x05, 0x5e, 0xdd, 0x5a, 0x05, 0x5e, 0xdd, 0x5a, 0x05, 0x5e, 0xdd, 0x5a, 0x05, 0x5e, 0xdd, 0x5a, 0xbe, 0x22, -0xc0, 0x08, 0x05, 0x5e, 0xdd, 0x5a, 0x9e, 0x5e, 0xe3, 0x19, 0xdd, 0x5a, 0xbb, 0x66, 0xdd, 0x5a, 0xbb, 0x66, 0xdd, 0x5a, 0xff, 0x66, 0xbe, 0x5e, 0x29, 0x1d, 0x1a, 0x38, 0x1a, 0x38, 0x3e, 0x5f, 0x3e, 0x5e, 0x3e, 0x5d, 0x3e, 0x5c, 0x3e, 0x5b, 0x3e, 0x5a, 0x3e, 0x59, 0x3e, 0x58, 0x3a, 0x38, 0x00, 0x67, 0x03, 0x6f, 0xbe, 0x5f, 0xdb, 0x00, 0x7f, 0x67, 0xbe, 0x5f, 0xde, 0x00, 0x00, 0x67, 0xbe, 0x5f, 0xe1, 0x00, 0x40, 0x67, 0xbe, 0x5f, 0xe0, 0x00, 0x3a, 0x38, 0xad, 0xac, 0x0d, 0x90, 0x04, 0x60, 0x69, 0x78, 0x66, 0x60, 0x6a, 0x78, 0x6b, 0x78, 0x6c, 0x78, 0x6d, 0x78, 0xb2, 0xa8, 0x3c, 0xab, 0xad, 0xaa, 0x00, 0x60, 0xbe, 0x58, 0xc2, 0x1d, 0x3a, 0x38, 0x02, 0x60, 0x72, 0x68, 0xe3, 0xeb, 0x01, 0xc9, 0x19, 0x38, 0xd9, 0x54, 0x04, 0xc9, 0xf2, 0x60, 0x72, 0x68, 0xe3, 0xeb, 0xa5, 0xaa, 0xac, 0xdf, -0x00, 0x09, 0x3a, 0x38, 0x1e, 0x5c, 0x04, 0xaa, 0x02, 0x9e, 0x1e, 0x5c, 0x04, 0xa8, 0x46, 0x62, 0x31, 0x6a, 0x40, 0xbd, 0xbd, 0x00, 0x02, 0x62, 0x40, 0xbd, 0xbe, 0x00, 0x00, 0x61, 0x10, 0x69, 0x07, 0x60, 0xc0, 0x68, 0x3f, 0x38, 0x0f, 0x59, 0x00, 0x61, 0x10, 0x69, 0x23, 0x5a, 0x32, 0xa8, 0x04, 0xac, 0x01, 0x92, 0x32, 0xaa, 0x5b, 0x59, 0x01, 0x62, 0x40, 0xbd, 0xbe, 0x00, 0x07, 0x60, 0xc0, 0x68, 0x3f, 0x38, 0x7a, 0x38, 0x02, 0x62, 0x40, 0xbd, 0xbe, 0x00, 0x00, 0x62, 0x40, 0xbd, 0xbd, 0x00, 0x40, 0xbd, 0xbe, 0x00, 0x3e, 0x5c, 0x3a, 0x38, 0x1e, 0x58, 0x1e, 0x59, 0x1e, 0x5a, 0x1e, 0x5b, 0x1e, 0x5c, 0x1e, 0x5d, 0x1e, 0x5e, 0x1e, 0x5f, 0xe6, 0xac, 0x05, 0x92, 0xe0, 0x61, 0x1a, 0x69, 0x00, 0x62, 0x1b, 0x6a, 0x04, 0x9e, 0x40, 0x61, 0x57, 0x69, 0x60, 0x62, 0x57, 0x6a, 0x90, 0x63, 0xd4, 0xfd, -0x40, 0x09, 0x5e, 0x6b, 0xb6, 0x64, 0x5e, 0x6c, 0x39, 0x65, 0x00, 0x66, 0x00, 0x67, 0xa7, 0x38, 0x0e, 0x0a, 0x15, 0x65, 0xfd, 0x48, 0x21, 0x9c, 0xe6, 0xac, 0x05, 0x92, 0xec, 0x61, 0x1a, 0x69, 0x0c, 0x62, 0x1b, 0x6a, 0x04, 0x9e, 0x4c, 0x61, 0x57, 0x69, 0x6c, 0x62, 0x57, 0x6a, 0x16, 0x65, 0xa0, 0x38, 0x7a, 0x02, 0x5e, 0x17, 0x07, 0x00, 0x5e, 0x07, 0x6b, 0x5d, 0xbe, 0x5d, 0x2e, 0x1d, 0x48, 0x66, 0xbe, 0x48, 0xac, 0x8a, 0x09, 0x66, 0xbe, 0x48, 0x1b, 0x9c, 0x13, 0x66, 0xbe, 0x48, 0x35, 0x9c, 0x1d, 0x66, 0xbe, 0x48, 0x15, 0x9c, 0x31, 0x9e, 0x7a, 0x60, 0x02, 0x68, 0x8b, 0x5d, 0xbe, 0x5d, 0x2e, 0x1d, 0x48, 0x66, 0xdd, 0x48, 0x77, 0x8a, 0x05, 0x66, 0xfe, 0x48, 0x4b, 0x9c, 0x0b, 0x66, 0xfe, 0x48, 0x5d, 0x9c, 0x11, 0x66, 0xfe, 0x48, 0x45, 0x9c, 0x15, 0x66, 0xfe, 0x48, 0x57, 0x9c, 0x5b, 0x68, -0x80, 0x09, 0x9e, 0x5d, 0x2e, 0x1d, 0x0a, 0x66, 0xbe, 0x48, 0x01, 0x96, 0xa6, 0x15, 0x25, 0x01, 0x45, 0x02, 0xff, 0x65, 0xe6, 0xac, 0x02, 0x92, 0x35, 0x26, 0x04, 0x9e, 0x1e, 0x58, 0x29, 0x58, 0x05, 0x26, 0x3e, 0x58, 0xfe, 0x5e, 0xe6, 0xac, 0x02, 0x92, 0x55, 0x25, 0x04, 0x9e, 0x1e, 0x58, 0x49, 0x58, 0x05, 0x25, 0x3e, 0x58, 0xc5, 0x2e, 0xdb, 0x58, 0x71, 0x9e, 0xe6, 0xac, 0x05, 0x92, 0xec, 0x61, 0x1a, 0x69, 0x0c, 0x62, 0x1b, 0x6a, 0x04, 0x9e, 0x4c, 0x61, 0x57, 0x69, 0x6c, 0x62, 0x57, 0x6a, 0x9e, 0x5d, 0x2e, 0x1d, 0x0a, 0x66, 0xa6, 0x15, 0xbe, 0x48, 0x01, 0x96, 0xa6, 0x15, 0x25, 0x01, 0x45, 0x02, 0x00, 0x65, 0xff, 0x6d, 0xe6, 0xac, 0x03, 0x92, 0x35, 0x26, 0x55, 0x25, 0x06, 0x9e, 0x1e, 0x58, 0x29, 0x58, 0x05, 0x26, 0x49, 0x58, 0x05, 0x25, 0x3e, 0x58, 0xfe, 0x5d, 0xc5, 0x2e, 0xa9, 0x5c, -0xc0, 0x09, 0xdb, 0x58, 0x4c, 0x9e, 0xff, 0x65, 0xe6, 0xac, 0x04, 0x92, 0x35, 0x26, 0xfe, 0x5e, 0x55, 0x25, 0x07, 0x9e, 0x1e, 0x58, 0x29, 0x58, 0x05, 0x26, 0xfe, 0x5e, 0x49, 0x58, 0x05, 0x25, 0x3e, 0x58, 0xc5, 0x2e, 0x9e, 0x5d, 0x2e, 0x1d, 0x05, 0x00, 0xdb, 0x58, 0x05, 0x10, 0x14, 0x9e, 0x00, 0x65, 0xff, 0x6d, 0xe6, 0xac, 0x03, 0x92, 0x35, 0x26, 0x55, 0x25, 0x06, 0x9e, 0x1e, 0x58, 0x29, 0x58, 0x05, 0x26, 0x49, 0x58, 0x05, 0x25, 0x3e, 0x58, 0xfe, 0x5d, 0xc5, 0x2e, 0x9e, 0x5d, 0x2e, 0x1d, 0x05, 0x00, 0xdb, 0x58, 0x05, 0x10, 0x05, 0x66, 0xdf, 0x48, 0x09, 0x8a, 0x0b, 0x66, 0xdf, 0x48, 0x12, 0x8a, 0x11, 0x66, 0xdf, 0x48, 0x0f, 0x8a, 0x19, 0x01, 0x19, 0x02, 0x17, 0x9e, 0xe6, 0xac, 0x05, 0x92, 0xe0, 0x61, 0x1a, 0x69, 0x00, 0x62, 0x1b, 0x6a, 0x04, 0x9e, 0x40, 0x61, 0x57, 0x69, 0x4f, 0x4c, -0x00, 0x0a, 0x60, 0x62, 0x57, 0x6a, 0x0b, 0x9e, 0xe6, 0xac, 0x05, 0x92, 0xe6, 0x61, 0x1a, 0x69, 0x06, 0x62, 0x1b, 0x6a, 0x04, 0x9e, 0x46, 0x61, 0x57, 0x69, 0x66, 0x62, 0x57, 0x6a, 0x19, 0x07, 0x3e, 0x5f, 0x3e, 0x5e, 0x3e, 0x5d, 0x3e, 0x5c, 0x3e, 0x5b, 0x3e, 0x5a, 0x3e, 0x59, 0x3e, 0x58, 0x3a, 0x38, 0x90, 0x60, 0x5e, 0x68, 0x48, 0x64, 0x0e, 0x6c, 0x00, 0x65, 0x00, 0x66, 0x00, 0x67, 0xff, 0x63, 0xff, 0x6b, 0x6f, 0x3c, 0x5c, 0x0a, 0x09, 0x5a, 0x48, 0x65, 0x5d, 0x48, 0x34, 0x8a, 0x1e, 0x58, 0x19, 0x03, 0x0c, 0x65, 0x65, 0x40, 0xe6, 0xac, 0x03, 0x92, 0x00, 0x61, 0x05, 0x69, 0x02, 0x9e, 0x80, 0x61, 0x57, 0x69, 0x20, 0x01, 0xb6, 0x62, 0x5e, 0x6a, 0x13, 0xb8, 0x14, 0xb8, 0x15, 0xb8, 0x6f, 0x39, 0x54, 0x0a, 0xe6, 0xac, 0x02, 0x92, 0x23, 0x5e, 0x01, 0x9e, 0x29, 0x5e, 0xc4, 0x3f, 0xf9, 0x96, -0x40, 0x0a, 0x00, 0xff, 0xfe, 0x5f, 0xc4, 0x3e, 0xff, 0x00, 0x49, 0x5d, 0x48, 0x60, 0x1d, 0x48, 0x03, 0x8a, 0x85, 0x04, 0xdb, 0x5c, 0x85, 0x14, 0x19, 0x02, 0x49, 0x5d, 0x48, 0x60, 0x1d, 0x48, 0x03, 0x8a, 0x85, 0x04, 0xfb, 0x5c, 0x85, 0x14, 0x19, 0x02, 0x19, 0x01, 0x95, 0xb8, 0x94, 0xb8, 0x93, 0xb8, 0x16, 0x65, 0x85, 0x04, 0x3e, 0x58, 0x1a, 0x38, 0x19, 0x00, 0x3a, 0x38, 0x9e, 0x59, 0xf1, 0x1e, 0x1c, 0x11, 0x1e, 0x98, 0x9e, 0x59, 0xf2, 0x1e, 0x22, 0x39, 0x88, 0x00, 0x11, 0x8a, 0x9e, 0x59, 0x58, 0x1a, 0x1a, 0x11, 0x01, 0x94, 0x14, 0x9e, 0x88, 0x61, 0xbe, 0x59, 0xf2, 0x1e, 0x8d, 0x61, 0x9e, 0x58, 0xef, 0x1e, 0x1b, 0x59, 0x97, 0x61, 0x9e, 0x58, 0xee, 0x1e, 0x1b, 0x59, 0x18, 0x9e, 0x9e, 0x59, 0x58, 0x1a, 0x19, 0x11, 0xf0, 0x95, 0x9e, 0x59, 0xf1, 0x1e, 0x1c, 0x11, 0x00, 0x98, 0x40, 0x44, -0x80, 0x0a, 0x00, 0x61, 0xbe, 0x59, 0xf2, 0x1e, 0x9e, 0x59, 0xf0, 0x1e, 0x22, 0x39, 0x66, 0x00, 0x08, 0x88, 0x8d, 0x61, 0x23, 0x58, 0xbe, 0x58, 0xef, 0x1e, 0x97, 0x61, 0x23, 0x58, 0xbe, 0x58, 0xee, 0x1e, 0x3a, 0x38, 0x9e, 0x59, 0xf3, 0x1e, 0x1c, 0x11, 0x1e, 0x98, 0x9e, 0x59, 0xf7, 0x1e, 0x22, 0x39, 0x88, 0x00, 0x11, 0x8a, 0x9e, 0x59, 0x58, 0x1a, 0x1b, 0x11, 0x01, 0x94, 0x14, 0x9e, 0x88, 0x61, 0xbe, 0x59, 0xf7, 0x1e, 0x8e, 0x61, 0x9e, 0x58, 0xf5, 0x1e, 0x1b, 0x59, 0x98, 0x61, 0x9e, 0x58, 0xf6, 0x1e, 0x1b, 0x59, 0x18, 0x9e, 0x9e, 0x59, 0x58, 0x1a, 0x1a, 0x11, 0xf0, 0x95, 0x9e, 0x59, 0xf3, 0x1e, 0x1c, 0x11, 0x00, 0x98, 0x00, 0x61, 0xbe, 0x59, 0xf7, 0x1e, 0x9e, 0x59, 0xf4, 0x1e, 0x22, 0x39, 0x66, 0x00, 0x08, 0x88, 0x8e, 0x61, 0x23, 0x58, 0xbe, 0x58, 0xf5, 0x1e, 0x98, 0x61, 0xe4, 0x8e, -0xc0, 0x0a, 0x23, 0x58, 0xbe, 0x58, 0xf6, 0x1e, 0x3a, 0x38, 0x1e, 0x58, 0x1e, 0x59, 0x1e, 0x5a, 0x1e, 0x5b, 0x1e, 0x5c, 0x1e, 0x5d, 0x9e, 0x58, 0xea, 0x04, 0x18, 0x10, 0x0a, 0x88, 0x00, 0x60, 0x01, 0x61, 0x1f, 0x69, 0x06, 0x62, 0x1f, 0x6a, 0x8f, 0x38, 0xd7, 0x0a, 0x1d, 0x59, 0x1d, 0x5a, 0x1a, 0x38, 0x9e, 0x58, 0x00, 0x1f, 0x19, 0x10, 0x23, 0x8a, 0x00, 0x64, 0x7f, 0x6c, 0x8d, 0x61, 0x01, 0x62, 0x1f, 0x6a, 0x8f, 0x38, 0xed, 0x0a, 0x23, 0x58, 0x04, 0x15, 0x06, 0x8a, 0x43, 0x5b, 0x18, 0x13, 0x01, 0x88, 0x1b, 0x5a, 0x43, 0x58, 0x1b, 0x59, 0x19, 0x01, 0x19, 0x02, 0x30, 0x64, 0x97, 0x61, 0x06, 0x62, 0x1f, 0x6a, 0x8f, 0x38, 0xfe, 0x0a, 0x23, 0x58, 0x04, 0x15, 0x06, 0x8a, 0x43, 0x5b, 0x18, 0x13, 0x01, 0x88, 0x1b, 0x5a, 0x43, 0x58, 0x1b, 0x59, 0x19, 0x01, 0x19, 0x02, 0x3e, 0x5d, 0xcf, 0xcb, -0x00, 0x0b, 0x3e, 0x5c, 0x3e, 0x5b, 0x3e, 0x5a, 0x3e, 0x59, 0x3e, 0x58, 0x3a, 0x38, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x0e, 0x00, 0x0c, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x06, 0x00, 0x06, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x02, 0x00, 0xff, 0x01, 0xff, 0x00, 0x7f, 0x00, 0x3f, 0x00, 0x1f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x05, 0x00, 0x08, 0x0c, -0x40, 0x0b, 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x9e, 0x58, 0xe7, 0x00, 0x19, 0x10, 0x08, 0x98, 0x9e, 0x58, 0xe8, 0x00, 0x9e, 0x59, 0xe9, 0x00, 0x19, 0x48, 0x01, 0x88, 0x42, 0xa9, 0xfd, 0x38, 0x75, 0xcb, 0x01, 0x60, 0xbe, 0x58, 0xea, 0x00, 0xbe, 0x58, 0xe7, 0x00, 0xed, 0x9f, 0x9e, 0x58, 0xe7, 0x00, 0x19, 0x10, 0x08, 0x98, 0x9e, 0x58, 0xe8, 0x00, 0x9e, 0x59, 0xe9, 0x00, 0x19, 0x48, 0x01, 0x88, 0x42, 0xa9, 0xfd, 0x38, 0x94, 0xcc, 0x01, 0x60, 0xbe, 0x58, 0xe7, 0x00, 0xef, 0x9f, 0x1a, 0x38, 0x1a, 0x38, 0x9e, 0x58, 0x36, 0x1d, 0x1b, 0x10, 0xf4, 0x8a, 0xf6, 0xcd, 0x02, 0x60, 0xbe, 0x58, 0xdd, 0x1e, 0x79, 0xe4, 0xb7, 0x8b, -0x80, 0x0b, 0xc7, 0xdd, 0x8a, 0xde, 0xa1, 0xdd, 0xa8, 0xe5, 0x9c, 0xcc, 0xd2, 0xde, 0xd4, 0xdb, 0x37, 0xee, 0xb2, 0xcc, 0xcf, 0xcc, 0x48, 0x66, 0x0e, 0x6e, 0x91, 0xed, 0xf3, 0xcc, 0x7f, 0xe2, 0x80, 0x60, 0xbe, 0x58, 0xfd, 0x1e, 0x9e, 0x58, 0xf1, 0x04, 0x9e, 0x59, 0xf2, 0x04, 0x01, 0x00, 0x1a, 0x10, 0x13, 0x88, 0x9e, 0x58, 0x45, 0x04, 0x02, 0x38, 0x00, 0x01, 0x08, 0x98, 0x9e, 0x58, 0x4d, 0x04, 0x9e, 0x59, 0x4f, 0x04, 0x01, 0x00, 0x02, 0x39, 0x00, 0x02, 0x7d, 0x80, 0x88, 0x60, 0xbe, 0x58, 0xfd, 0x1e, 0x86, 0xe8, 0x0c, 0xe9, 0x77, 0x9e, 0x1a, 0x38, 0x9e, 0x58, 0xe9, 0x1e, 0x18, 0x10, 0x01, 0x8a, 0x71, 0x9e, 0x00, 0x60, 0xbe, 0x58, 0x20, 0x1d, 0x1b, 0x60, 0xbe, 0x58, 0x44, 0x1a, 0x06, 0x70, 0x50, 0xac, 0x18, 0x92, 0x9e, 0x58, 0x45, 0x04, 0x02, 0x38, 0x00, 0x01, 0x0a, 0x98, 0x09, 0x92, -0xc0, 0x0b, 0x9e, 0x58, 0x4d, 0x04, 0x02, 0x38, 0x40, 0x01, 0x0e, 0x80, 0x9e, 0x58, 0x4f, 0x04, 0x02, 0x38, 0x40, 0x01, 0x09, 0x80, 0xe7, 0xe5, 0x9e, 0x58, 0x20, 0x1d, 0x18, 0x10, 0x04, 0x8a, 0x05, 0x60, 0xbe, 0x58, 0x44, 0x1a, 0x50, 0x9e, 0x1a, 0x38, 0x06, 0x70, 0x08, 0xac, 0x2f, 0x92, 0x00, 0xac, 0x2d, 0x92, 0x50, 0xac, 0x2b, 0x92, 0x00, 0x60, 0xbe, 0x58, 0x43, 0x04, 0x9e, 0x58, 0xdb, 0x1e, 0x9e, 0x59, 0xdc, 0x1e, 0x01, 0x00, 0x1a, 0x10, 0x21, 0x8a, 0x9e, 0x58, 0xf1, 0x04, 0x9e, 0x59, 0xf2, 0x04, 0x01, 0x00, 0x1b, 0x10, 0x14, 0x9a, 0x9e, 0x58, 0x45, 0x04, 0x02, 0x38, 0x60, 0x00, 0x15, 0x80, 0x9e, 0x58, 0xf1, 0x04, 0x9e, 0x59, 0xf2, 0x04, 0x01, 0x00, 0x1b, 0x10, 0x08, 0x88, 0x9e, 0x58, 0xf1, 0x1e, 0x9e, 0x59, 0xf3, 0x1e, 0x01, 0x00, 0x08, 0x58, 0x1d, 0x10, 0x06, 0x98, 0xb2, 0x09, -0x00, 0x0c, 0x1f, 0xdf, 0x9e, 0x58, 0x43, 0x04, 0x01, 0x61, 0x19, 0x48, 0x1d, 0x8a, 0x9e, 0x58, 0x8a, 0x04, 0x1f, 0x10, 0x07, 0x80, 0x9e, 0x58, 0x8b, 0x04, 0x1f, 0x10, 0x03, 0x80, 0x05, 0x60, 0xbe, 0x58, 0x44, 0x1a, 0x9e, 0x58, 0x36, 0x1d, 0x1a, 0x10, 0x08, 0x8a, 0x9e, 0x58, 0x36, 0x1d, 0x1c, 0x10, 0x03, 0x8a, 0x98, 0xe2, 0x98, 0xe2, 0x01, 0x9e, 0x98, 0xe2, 0x9e, 0x58, 0x45, 0x04, 0x02, 0x38, 0x80, 0x01, 0x01, 0x80, 0x69, 0xe2, 0xc6, 0xce, 0x1a, 0xcd, 0x99, 0xce, 0xab, 0xce, 0x25, 0xcf, 0x72, 0xdc, 0x12, 0xd2, 0x9e, 0x58, 0x43, 0x04, 0x01, 0x61, 0x19, 0x48, 0x0a, 0x8a, 0x9e, 0x58, 0xb1, 0x04, 0x19, 0x10, 0x06, 0x8a, 0x9e, 0x58, 0xb8, 0x04, 0x18, 0x10, 0x02, 0x88, 0x28, 0xe4, 0xc3, 0xe1, 0xc1, 0xf8, 0x8a, 0xf8, 0x51, 0xd0, 0x19, 0x38, 0x92, 0x4a, 0x9e, 0x58, 0x43, 0x04, 0x1b, 0x22, -0x40, 0x0c, 0x01, 0x61, 0x19, 0x48, 0x0c, 0x8a, 0x9e, 0x58, 0x20, 0x1d, 0x18, 0x10, 0x08, 0x88, 0x19, 0x38, 0xc6, 0x4a, 0x19, 0x38, 0xc5, 0x48, 0x19, 0x38, 0x94, 0x49, 0x19, 0x38, 0xd6, 0x4a, 0x03, 0xda, 0x4d, 0xda, 0xe3, 0xed, 0x66, 0xd3, 0xdc, 0xd3, 0xec, 0xd6, 0x8a, 0xda, 0x9e, 0x58, 0x58, 0x1a, 0x19, 0x10, 0x12, 0x88, 0x9e, 0x58, 0x8a, 0x04, 0x9e, 0x59, 0x8b, 0x04, 0x01, 0x00, 0x02, 0x39, 0x05, 0x00, 0x0a, 0x98, 0xaa, 0x61, 0x15, 0x69, 0x23, 0x58, 0x02, 0x39, 0x0d, 0x00, 0x04, 0x80, 0xaa, 0x61, 0x15, 0x69, 0x0d, 0x60, 0x1b, 0x59, 0xbf, 0xdc, 0x7a, 0xdd, 0x3a, 0x38, 0xf6, 0xcd, 0x9c, 0xcc, 0xd4, 0xdb, 0xc3, 0xcc, 0xcf, 0xcc, 0xf3, 0xcc, 0x7f, 0xe2, 0xc6, 0xce, 0x1a, 0xcd, 0x99, 0xce, 0xab, 0xce, 0x25, 0xcf, 0x12, 0xd2, 0x51, 0xd0, 0x03, 0xda, 0x4d, 0xda, 0x66, 0xd3, 0x27, 0x2c, -0x80, 0x0c, 0xdc, 0xd3, 0xec, 0xd6, 0x8a, 0xda, 0xbf, 0xdc, 0x7a, 0xdd, 0x3a, 0x38, 0xf6, 0xcd, 0x9c, 0xcc, 0xcf, 0xcc, 0xf3, 0xcc, 0x75, 0xce, 0xc6, 0xce, 0x1a, 0xcd, 0x99, 0xce, 0xab, 0xce, 0x25, 0xcf, 0x12, 0xd2, 0x51, 0xd0, 0x03, 0xda, 0x3a, 0x38, 0x4d, 0xda, 0x66, 0xd3, 0xdc, 0xd3, 0xec, 0xd6, 0x8a, 0xda, 0xbf, 0xdc, 0x7a, 0xdd, 0x3a, 0x38, 0x30, 0x67, 0x0b, 0x6f, 0x9e, 0x5e, 0xe9, 0x00, 0x48, 0x65, 0x0e, 0x6d, 0x9e, 0x5c, 0xda, 0x00, 0x19, 0x14, 0x87, 0x38, 0xb0, 0x0c, 0xc5, 0x5c, 0xf4, 0x14, 0x7c, 0xac, 0x04, 0x92, 0x00, 0x61, 0x02, 0x62, 0x82, 0x40, 0x01, 0x5c, 0x9d, 0x5d, 0x19, 0x07, 0x3a, 0x38, 0x30, 0x60, 0x1c, 0x78, 0x06, 0x70, 0x50, 0xac, 0x08, 0x92, 0x08, 0xac, 0x04, 0x92, 0x00, 0xac, 0x02, 0x92, 0x10, 0x60, 0x03, 0x9e, 0x30, 0x60, 0x01, 0x9e, 0x68, 0x60, 0x61, 0x34, -0xc0, 0x0c, 0x25, 0x78, 0x26, 0x78, 0x3a, 0x38, 0x30, 0x60, 0x1c, 0x78, 0x30, 0x60, 0x25, 0x78, 0x26, 0x78, 0x3a, 0x38, 0x40, 0x60, 0x1c, 0x78, 0x30, 0x60, 0x25, 0x78, 0x26, 0x78, 0x3a, 0x38, 0x48, 0x67, 0x0e, 0x6f, 0x9e, 0x5d, 0xfd, 0x1b, 0x19, 0x15, 0x9e, 0x5e, 0xfe, 0x1b, 0xff, 0x64, 0x7f, 0x6c, 0xa7, 0x38, 0xdd, 0x0c, 0x9f, 0x49, 0x01, 0x9a, 0xe3, 0x5c, 0x19, 0x07, 0x18, 0x14, 0x01, 0x94, 0x00, 0x64, 0x90, 0x3c, 0x26, 0x00, 0x90, 0x3c, 0x05, 0x1c, 0xf2, 0x3f, 0xfd, 0x1b, 0x00, 0x62, 0xa7, 0x38, 0xef, 0x0c, 0xf2, 0x13, 0x03, 0x96, 0xf4, 0x13, 0x01, 0x94, 0x00, 0x63, 0x7d, 0x5f, 0x19, 0x16, 0xe4, 0x89, 0x3a, 0x38, 0x48, 0x67, 0x0e, 0x6f, 0x9e, 0x5d, 0xfd, 0x1b, 0x9e, 0x5e, 0xfe, 0x1b, 0x19, 0x16, 0xff, 0x64, 0x7f, 0x6c, 0xc7, 0x38, 0x03, 0x0d, 0x9f, 0x49, 0x01, 0x9a, 0xb0, 0xa2, -0x00, 0x0d, 0xe3, 0x5c, 0xf0, 0x3f, 0xfd, 0x1b, 0x1a, 0x38, 0x18, 0x14, 0x01, 0x94, 0x00, 0x64, 0x90, 0x3c, 0x25, 0x00, 0x90, 0x3c, 0x05, 0x1c, 0x00, 0x62, 0xc7, 0x38, 0x15, 0x0d, 0xf2, 0x3f, 0xfd, 0x1b, 0xf2, 0x13, 0x03, 0x96, 0xf4, 0x13, 0x01, 0x94, 0x00, 0x63, 0x7b, 0x5f, 0x19, 0x07, 0x19, 0x15, 0xe1, 0x89, 0x3a, 0x38, 0x05, 0x71, 0x49, 0xaa, 0x05, 0x79, 0x00, 0x66, 0x60, 0x65, 0x11, 0x6d, 0x48, 0x64, 0x0e, 0x6c, 0x9e, 0x5b, 0xfd, 0x1b, 0x1a, 0x05, 0xa3, 0x05, 0x00, 0x67, 0x9e, 0x58, 0xfd, 0x1b, 0x19, 0x10, 0x07, 0x38, 0xb6, 0x0d, 0x1d, 0x70, 0x1c, 0x49, 0x85, 0x94, 0x05, 0x71, 0x49, 0xa8, 0x05, 0x79, 0x00, 0x60, 0xa2, 0x3b, 0x01, 0x00, 0x63, 0x59, 0x24, 0x39, 0xff, 0x00, 0x19, 0x48, 0x29, 0x88, 0xb2, 0x3b, 0xfd, 0x1b, 0x19, 0x13, 0x63, 0x59, 0x24, 0x39, 0xff, 0x00, 0x77, 0xc4, -0x40, 0x0d, 0x19, 0x48, 0x21, 0x88, 0xa3, 0x59, 0x24, 0x39, 0xff, 0x00, 0x19, 0x48, 0x6d, 0x88, 0x9e, 0x5b, 0xf0, 0x04, 0x4b, 0x62, 0x1a, 0x6a, 0x7a, 0x49, 0x06, 0x98, 0xa3, 0x59, 0x24, 0x39, 0x00, 0x80, 0x23, 0x29, 0x3b, 0x5d, 0x08, 0x9e, 0x43, 0x5b, 0x19, 0x03, 0x7b, 0x5a, 0xa3, 0x59, 0x24, 0x39, 0x00, 0x80, 0x23, 0x29, 0x3b, 0x5d, 0x19, 0x13, 0x60, 0x3a, 0xaa, 0x15, 0x43, 0x59, 0x19, 0x01, 0x3b, 0x5a, 0xda, 0xce, 0x51, 0x9e, 0xa3, 0x59, 0x24, 0x39, 0xff, 0x00, 0x19, 0x48, 0x4c, 0x88, 0xa2, 0x3b, 0x01, 0x00, 0xb2, 0x3a, 0xfd, 0x1b, 0x19, 0x12, 0x63, 0x59, 0x24, 0x39, 0xff, 0x00, 0x19, 0x48, 0x1f, 0x8a, 0x43, 0x59, 0x24, 0x39, 0xff, 0x00, 0x19, 0x48, 0x1a, 0x8a, 0x63, 0x59, 0x24, 0x39, 0xff, 0x00, 0x43, 0x58, 0x04, 0x38, 0xff, 0x00, 0x38, 0x48, 0x12, 0x8a, 0x20, 0x39, 0x6a, 0x62, -0x80, 0x0d, 0xbd, 0x15, 0x43, 0x58, 0x00, 0x38, 0xbd, 0x15, 0x03, 0x58, 0x19, 0x49, 0x01, 0x94, 0x1b, 0x59, 0x00, 0x39, 0xbd, 0x15, 0x63, 0x58, 0x00, 0x38, 0xbd, 0x15, 0x03, 0x58, 0x19, 0x49, 0x01, 0x94, 0x1b, 0x59, 0x00, 0x60, 0x43, 0x59, 0x24, 0x39, 0xff, 0x00, 0x19, 0x48, 0x09, 0x8a, 0x43, 0x5b, 0x64, 0x3b, 0xff, 0x00, 0xa3, 0x59, 0x24, 0x39, 0x00, 0x80, 0x23, 0x29, 0x3b, 0x5d, 0x0d, 0x9e, 0x63, 0x59, 0x24, 0x39, 0xff, 0x00, 0x19, 0x48, 0x08, 0x8a, 0x63, 0x5b, 0x64, 0x3b, 0xff, 0x00, 0xa3, 0x59, 0x24, 0x39, 0x00, 0x80, 0x23, 0x29, 0x3b, 0x5d, 0x19, 0x13, 0x60, 0x3a, 0xaa, 0x15, 0x43, 0x59, 0x19, 0x01, 0x3b, 0x5a, 0xe7, 0xce, 0x19, 0x04, 0x19, 0x05, 0x19, 0x07, 0x19, 0x05, 0x19, 0x06, 0x9e, 0x5a, 0xfe, 0x1b, 0x5e, 0x48, 0x69, 0x99, 0x3a, 0x38, 0xe8, 0x67, 0x03, 0x6f, 0x22, 0x6f, -0xc0, 0x0d, 0xbe, 0x5f, 0x54, 0x1a, 0x9e, 0x5c, 0x58, 0x1a, 0x82, 0x39, 0x00, 0x00, 0x20, 0x8a, 0x00, 0x67, 0xbe, 0x5f, 0x54, 0x1a, 0x9e, 0x5a, 0xfd, 0x1b, 0x72, 0x65, 0x19, 0x6d, 0x86, 0x66, 0x19, 0x6e, 0x19, 0x14, 0xff, 0x61, 0x7f, 0x69, 0x00, 0x63, 0x87, 0x38, 0xe0, 0x0d, 0xa5, 0x58, 0x46, 0x4a, 0x00, 0x38, 0x48, 0x0e, 0x38, 0x49, 0x01, 0x9a, 0x03, 0x59, 0x78, 0x49, 0x01, 0x94, 0x03, 0x5b, 0x17, 0x07, 0x19, 0x04, 0xe1, 0x58, 0x00, 0x61, 0x1c, 0x5c, 0xbe, 0x58, 0x54, 0x1a, 0x3a, 0x38, 0x9e, 0x58, 0xe3, 0x19, 0x00, 0x67, 0x27, 0x76, 0x19, 0x16, 0xc7, 0x38, 0xf2, 0x0d, 0x04, 0x39, 0x01, 0x00, 0xe1, 0x07, 0x08, 0x58, 0xbe, 0x5f, 0xea, 0x04, 0x3a, 0x38, 0x9e, 0x58, 0x00, 0x1f, 0x9e, 0x5f, 0x20, 0x1d, 0x18, 0x17, 0x01, 0x8a, 0x1b, 0x00, 0xbe, 0x58, 0x11, 0x00, 0x7a, 0x67, 0xc6, 0xac, -0x00, 0x0e, 0x02, 0x6f, 0x00, 0x66, 0x9e, 0x58, 0x5d, 0x1a, 0x19, 0x10, 0x07, 0x38, 0x09, 0x0e, 0xdd, 0x5f, 0x1a, 0x38, 0x1a, 0x38, 0xe8, 0xcd, 0xbe, 0xcd, 0x9e, 0x5f, 0xea, 0x04, 0x0a, 0x67, 0xbe, 0x5f, 0xe4, 0x19, 0x9e, 0x58, 0x54, 0x1a, 0x9e, 0x59, 0x48, 0x1a, 0x24, 0x3a, 0x00, 0xe0, 0x07, 0x8a, 0x22, 0x39, 0x00, 0x20, 0xbe, 0x59, 0x48, 0x1a, 0x24, 0x38, 0xff, 0x1f, 0x17, 0x9e, 0x18, 0x10, 0x0b, 0x8a, 0x9e, 0x59, 0x48, 0x1a, 0x18, 0x11, 0x05, 0x8a, 0x26, 0x5a, 0x41, 0x02, 0x02, 0x00, 0x08, 0x58, 0x08, 0x58, 0xbe, 0x58, 0x48, 0x1a, 0x9e, 0x59, 0xe2, 0x19, 0x3f, 0x48, 0x07, 0x8a, 0x9e, 0x58, 0x48, 0x1a, 0x05, 0x39, 0x00, 0x80, 0xbe, 0x59, 0x48, 0x1a, 0x06, 0x58, 0x24, 0x3a, 0x00, 0xe0, 0x00, 0x8a, 0x32, 0x62, 0x0b, 0x6a, 0x50, 0x3a, 0x4b, 0x1a, 0x49, 0x5a, 0x02, 0x40, 0x1f, 0x71, -0x40, 0x0e, 0x00, 0x61, 0x02, 0x69, 0x01, 0x40, 0xbe, 0x59, 0x05, 0x1c, 0x9e, 0x59, 0x4b, 0x1a, 0xbe, 0x59, 0x03, 0x1c, 0x00, 0x9e, 0x00, 0x60, 0xbe, 0x58, 0x58, 0x1a, 0x60, 0x66, 0x11, 0x6e, 0x00, 0x61, 0x80, 0x69, 0x9e, 0x5f, 0xff, 0x1b, 0x19, 0x17, 0xe7, 0x38, 0x57, 0x0e, 0xd1, 0x22, 0x5d, 0x5e, 0xaa, 0x63, 0x15, 0x6b, 0xbe, 0x62, 0x15, 0x6a, 0x00, 0x61, 0x9e, 0x5f, 0xf0, 0x04, 0x19, 0x17, 0xe7, 0x38, 0x64, 0x0e, 0x1d, 0x5b, 0x19, 0x01, 0x3d, 0x5a, 0xbe, 0x58, 0x4b, 0x1a, 0xc8, 0x63, 0x1b, 0x6b, 0x00, 0x60, 0x13, 0x67, 0xe7, 0x38, 0x6f, 0x0e, 0x1d, 0x5b, 0x1a, 0x38, 0x1a, 0x38, 0x9e, 0x58, 0x06, 0x1c, 0xbe, 0x58, 0x1c, 0x00, 0x3a, 0x38, 0x60, 0x67, 0x11, 0x6f, 0x48, 0x66, 0x0e, 0x6e, 0x00, 0x64, 0x01, 0x63, 0x24, 0x72, 0x9e, 0x58, 0x05, 0x1c, 0x08, 0x58, 0x40, 0x02, 0x05, 0x2d, -0x80, 0x0e, 0x00, 0x61, 0x80, 0x69, 0x20, 0x58, 0x9e, 0x5d, 0xda, 0x00, 0x19, 0x15, 0xa7, 0x38, 0x97, 0x0e, 0xf1, 0x25, 0x08, 0x8a, 0xd3, 0x15, 0x0a, 0x98, 0xf0, 0x25, 0xbb, 0x5f, 0x9e, 0x49, 0x06, 0x98, 0x9b, 0x5e, 0x04, 0x9e, 0xd2, 0x15, 0xfa, 0x9b, 0xf1, 0x2d, 0xbb, 0x5f, 0x19, 0x07, 0x19, 0x06, 0x3a, 0x38, 0xbe, 0x63, 0x15, 0x6b, 0x00, 0x65, 0x9e, 0x5c, 0x4b, 0x1a, 0x18, 0x14, 0x0a, 0x8a, 0x19, 0x14, 0x87, 0x38, 0xa9, 0x0e, 0x65, 0x04, 0x83, 0x5e, 0x19, 0x16, 0x66, 0x07, 0xe3, 0x5e, 0xdb, 0x5c, 0x19, 0x05, 0x3a, 0x38, 0x9e, 0x5e, 0x4b, 0x1a, 0x0f, 0x9a, 0x0e, 0x8a, 0x19, 0x16, 0xc7, 0x38, 0xbc, 0x0e, 0xc0, 0x3d, 0xbe, 0x15, 0xa3, 0x5f, 0x19, 0x17, 0xdf, 0x48, 0x04, 0x8a, 0xaa, 0x62, 0x15, 0x6a, 0xbe, 0xce, 0xfc, 0xce, 0x19, 0x16, 0x3a, 0x38, 0xe2, 0x04, 0x83, 0x58, 0x26, 0xfe, -0xc0, 0x0e, 0xc2, 0x02, 0x50, 0x00, 0x1b, 0x5c, 0xde, 0x5a, 0x00, 0x00, 0x3a, 0x38, 0x00, 0x60, 0xff, 0x61, 0xde, 0x66, 0x15, 0x6e, 0xf2, 0x65, 0x15, 0x6d, 0x06, 0x64, 0x16, 0x6c, 0x1a, 0x63, 0x16, 0x6b, 0x9e, 0x5f, 0xf0, 0x04, 0x19, 0x17, 0xe7, 0x38, 0xd8, 0x0e, 0x3d, 0x5e, 0x1d, 0x5d, 0x1d, 0x5c, 0x3d, 0x5b, 0x3a, 0x38, 0x60, 0x38, 0xde, 0x15, 0xfb, 0x58, 0x60, 0x38, 0xf2, 0x15, 0xfb, 0x58, 0x60, 0x38, 0x06, 0x16, 0xdb, 0x58, 0x60, 0x38, 0x1a, 0x16, 0xdb, 0x58, 0x3a, 0x38, 0x60, 0x38, 0xde, 0x15, 0xf8, 0x49, 0x01, 0x94, 0xfb, 0x58, 0x60, 0x38, 0xf2, 0x15, 0xf8, 0x49, 0x01, 0x9a, 0xfb, 0x58, 0x60, 0x38, 0x06, 0x16, 0xd8, 0x49, 0x01, 0x9a, 0xdb, 0x58, 0x60, 0x38, 0x1a, 0x16, 0xd8, 0x49, 0x01, 0x94, 0xdb, 0x58, 0x3a, 0x38, 0xc0, 0x38, 0xde, 0x15, 0x03, 0x59, 0xe0, 0x3a, 0x6f, 0x88, -0x00, 0x0f, 0xde, 0x15, 0x3a, 0x49, 0x01, 0x94, 0x3b, 0x5a, 0xde, 0x58, 0xff, 0x00, 0xc0, 0x38, 0xf2, 0x15, 0x03, 0x59, 0xe0, 0x3a, 0xf2, 0x15, 0x3a, 0x49, 0x01, 0x9a, 0x3b, 0x5a, 0xde, 0x58, 0x00, 0x00, 0xc0, 0x38, 0x06, 0x16, 0x03, 0x59, 0xe0, 0x3a, 0x06, 0x16, 0x3a, 0x49, 0x01, 0x9a, 0x3b, 0x5a, 0xde, 0x58, 0x00, 0x00, 0xc0, 0x38, 0x1a, 0x16, 0x03, 0x59, 0xe0, 0x3a, 0x1a, 0x16, 0x3a, 0x49, 0x01, 0x94, 0x3b, 0x5a, 0xde, 0x58, 0xff, 0x00, 0x3a, 0x38, 0x00, 0x61, 0xbe, 0x59, 0x58, 0x1a, 0x00, 0x67, 0x23, 0x70, 0xe0, 0x39, 0xaa, 0x15, 0x19, 0x49, 0x32, 0x98, 0x02, 0xdc, 0x9e, 0x58, 0xe9, 0x1e, 0x18, 0x10, 0x0e, 0x8a, 0x06, 0x70, 0x08, 0xac, 0x08, 0x92, 0x00, 0xac, 0x06, 0x92, 0x50, 0xac, 0x04, 0x92, 0x20, 0x60, 0x01, 0x68, 0x1c, 0x78, 0x03, 0x9e, 0x00, 0x60, 0x02, 0x68, 0xe2, 0x31, -0x40, 0x0f, 0x1c, 0x78, 0x9e, 0x58, 0x20, 0x1d, 0x02, 0x38, 0x80, 0x01, 0x03, 0x88, 0x40, 0x60, 0xbe, 0x58, 0x1c, 0x00, 0xe0, 0x3b, 0x1a, 0x16, 0x63, 0x5e, 0xe0, 0x3b, 0xde, 0x15, 0x63, 0x5d, 0x14, 0x60, 0x58, 0x62, 0x1a, 0x6a, 0x1a, 0x49, 0x12, 0x9a, 0x68, 0xcf, 0x19, 0x05, 0xe0, 0x3b, 0xf2, 0x15, 0xbb, 0x49, 0xf5, 0x9b, 0x19, 0x06, 0xe0, 0x38, 0x06, 0x16, 0xd8, 0x49, 0xed, 0x9b, 0x66, 0xdc, 0x19, 0x07, 0x9e, 0x58, 0x4b, 0x1a, 0xf8, 0x48, 0xc4, 0x97, 0x01, 0x9e, 0x66, 0xdc, 0x3a, 0x38, 0x9e, 0x5a, 0xfd, 0x1b, 0xa0, 0x38, 0x48, 0x0e, 0x46, 0x48, 0x03, 0x5c, 0xe0, 0x3b, 0xc8, 0x1b, 0x63, 0x58, 0x04, 0x00, 0x1b, 0x5b, 0x1c, 0x73, 0x9b, 0x48, 0x31, 0x96, 0x1e, 0x5f, 0x01, 0x67, 0xe0, 0x39, 0x07, 0x10, 0x29, 0x59, 0x25, 0x03, 0x62, 0x39, 0x00, 0x00, 0x14, 0x96, 0x72, 0x39, 0x8f, 0x4b, -0x80, 0x0f, 0xfd, 0x1b, 0x11, 0x94, 0xe0, 0x39, 0x10, 0x10, 0x29, 0x59, 0x26, 0x02, 0x42, 0x39, 0x00, 0x00, 0x0a, 0x96, 0x52, 0x39, 0xfe, 0x1b, 0x07, 0x94, 0x9e, 0x59, 0xfd, 0x1b, 0x60, 0x38, 0x48, 0x0e, 0x22, 0x48, 0x98, 0x49, 0x13, 0x96, 0x19, 0x07, 0xe2, 0x38, 0x09, 0x00, 0xe1, 0x97, 0x3e, 0x5f, 0x58, 0x61, 0x1a, 0x69, 0x23, 0x58, 0x00, 0x3a, 0x72, 0x19, 0xfe, 0x5f, 0xaf, 0x2a, 0xfe, 0x5f, 0x00, 0x3a, 0x86, 0x19, 0xdb, 0x5a, 0x08, 0x39, 0x01, 0x00, 0x01, 0x9e, 0x3e, 0x5f, 0x3a, 0x38, 0x1e, 0x5f, 0x00, 0x67, 0xe0, 0x3c, 0x07, 0x10, 0x89, 0x5c, 0x85, 0x03, 0x62, 0x39, 0x00, 0x00, 0x50, 0x96, 0x72, 0x39, 0xfd, 0x1b, 0x4d, 0x94, 0xe0, 0x3c, 0x10, 0x10, 0x89, 0x5c, 0x86, 0x02, 0x42, 0x39, 0x00, 0x00, 0x46, 0x96, 0x52, 0x39, 0xfe, 0x1b, 0x43, 0x94, 0x9e, 0x59, 0xfd, 0x1b, 0x6e, 0xbd, -0xc0, 0x0f, 0x60, 0x38, 0x32, 0x16, 0x22, 0x48, 0x03, 0x5c, 0x82, 0x39, 0x00, 0x00, 0x3a, 0x9a, 0x1e, 0x5f, 0x1e, 0x5c, 0x19, 0xd0, 0x81, 0x58, 0x3e, 0x5c, 0x19, 0x17, 0x20, 0x98, 0x19, 0x11, 0x1e, 0x98, 0x1e, 0x5c, 0x00, 0x3f, 0x72, 0x19, 0xe3, 0x5f, 0x00, 0x39, 0x86, 0x19, 0x23, 0x59, 0x9e, 0x5c, 0xfd, 0x1b, 0xe0, 0x38, 0x32, 0x16, 0x81, 0x48, 0x03, 0x5f, 0xa0, 0x38, 0x32, 0x16, 0x86, 0x48, 0x3e, 0x5c, 0x17, 0x07, 0x80, 0x41, 0x1c, 0x5f, 0x01, 0x5c, 0x3e, 0x5f, 0xe2, 0x38, 0x05, 0x00, 0x04, 0x96, 0xfd, 0x61, 0xb4, 0x69, 0x81, 0x40, 0x21, 0x5c, 0x1e, 0x5f, 0x50, 0x67, 0x1a, 0x6f, 0xe5, 0x58, 0xe3, 0x59, 0x83, 0x48, 0x3f, 0x5f, 0x1b, 0x5f, 0x52, 0x67, 0x1a, 0x6f, 0xe5, 0x58, 0xe3, 0x59, 0x82, 0x48, 0x3f, 0x5f, 0x1b, 0x5f, 0x90, 0x38, 0x54, 0x1a, 0xbe, 0x58, 0x54, 0x1a, 0xfd, 0x70, -0x00, 0x10, 0x3e, 0x5f, 0x19, 0x07, 0xe2, 0x38, 0x09, 0x00, 0xa5, 0x97, 0x3e, 0x5f, 0x3a, 0x38, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0x01, 0x00, 0x01, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x01, 0x00, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x01, 0x00, 0x9e, 0x5c, 0x58, 0x1a, 0x18, 0x14, 0x29, 0x9a, 0x19, 0x14, 0xff, 0x67, 0x7f, 0x6f, 0x87, 0x38, 0x38, 0x10, 0x80, 0x38, 0x72, 0x19, 0x80, 0x39, 0x86, 0x19, 0xb8, 0x49, 0x02, 0x88, 0xd9, 0x49, 0x0e, 0x8a, 0x13, 0x10, 0x01, 0x8c, 0x02, 0x58, 0x32, 0x11, 0x01, 0x8c, 0x22, 0x59, 0x01, 0x00, 0xe4, 0x39, 0xff, 0x00, 0x19, 0x48, 0x03, 0x94, 0xfe, 0x5c, 0x04, 0x2f, 0xfe, 0x5c, 0x19, 0x14, 0xe4, 0x3c, 0x00, 0xff, 0xfe, 0x5c, 0x80, 0x38, 0x72, 0x19, 0x13, 0x11, 0x01, 0x8c, 0xf1, 0x08, -0x40, 0x10, 0x22, 0x59, 0x80, 0x38, 0x86, 0x19, 0x12, 0x17, 0x01, 0x8c, 0xe2, 0x5f, 0x3a, 0x38, 0x21, 0x72, 0x43, 0x43, 0x01, 0x5c, 0x43, 0x41, 0x24, 0x01, 0x9e, 0x5c, 0x54, 0x1a, 0x1c, 0x5c, 0x18, 0x00, 0x3a, 0x38, 0x1e, 0x58, 0x1e, 0x59, 0xd2, 0x60, 0x15, 0x68, 0x03, 0x59, 0x22, 0x38, 0x01, 0x00, 0x03, 0x8a, 0x22, 0x38, 0x02, 0x00, 0x06, 0x8a, 0x00, 0x60, 0xbe, 0x58, 0x0b, 0x1f, 0xbe, 0x58, 0x0c, 0x1f, 0x0a, 0x9e, 0xb2, 0x60, 0x19, 0x68, 0x03, 0x59, 0xbe, 0x59, 0x0c, 0x1f, 0xbe, 0x60, 0x19, 0x68, 0x03, 0x59, 0xbe, 0x59, 0x0b, 0x1f, 0x3e, 0x59, 0x3e, 0x58, 0x00, 0x60, 0xbe, 0x58, 0xe2, 0x19, 0x58, 0x60, 0x1a, 0x68, 0x00, 0x61, 0x38, 0x49, 0x58, 0x8a, 0x00, 0x67, 0xe0, 0x38, 0x72, 0x19, 0x03, 0x5d, 0xe0, 0x38, 0x86, 0x19, 0x03, 0x5e, 0xcf, 0xd0, 0xef, 0xd1, 0x9e, 0x58, 0x49, 0x13, -0x80, 0x10, 0x59, 0x1a, 0x19, 0x10, 0x05, 0x8a, 0xdb, 0xd0, 0x9e, 0x58, 0x59, 0x1a, 0x1a, 0x10, 0x01, 0x8a, 0xa8, 0xcf, 0x51, 0x63, 0x1a, 0x6b, 0x47, 0xd0, 0x9e, 0x5d, 0xe2, 0x19, 0xa0, 0x3b, 0xb2, 0x19, 0x1b, 0x5b, 0x53, 0x63, 0x1a, 0x6b, 0x47, 0xd0, 0xa0, 0x3b, 0xbe, 0x19, 0x1b, 0x5b, 0x1e, 0x58, 0x1e, 0x59, 0xa2, 0x38, 0x00, 0x00, 0x13, 0x88, 0x9e, 0x58, 0x0b, 0x1f, 0x18, 0x10, 0x05, 0x88, 0x9e, 0x58, 0x0c, 0x1f, 0x18, 0x10, 0x01, 0x88, 0x0a, 0x9e, 0x9e, 0x58, 0x0b, 0x1f, 0xb2, 0x61, 0x19, 0x69, 0x1b, 0x59, 0x9e, 0x58, 0x0c, 0x1f, 0xbe, 0x61, 0x19, 0x69, 0x1b, 0x59, 0x3e, 0x59, 0x3e, 0x58, 0xe2, 0x62, 0x19, 0x6a, 0xca, 0x63, 0x19, 0x6b, 0x53, 0x03, 0xde, 0x5b, 0xff, 0xff, 0xd6, 0x63, 0x19, 0x6b, 0x53, 0x03, 0xde, 0x5b, 0xff, 0x7f, 0x43, 0x5b, 0x68, 0x3a, 0x01, 0x00, 0x5c, 0xdf, -0xc0, 0x10, 0x59, 0x60, 0x1a, 0x68, 0xde, 0x58, 0x00, 0x00, 0x9e, 0x58, 0xe2, 0x19, 0x12, 0x38, 0x27, 0x00, 0x05, 0x94, 0x19, 0x07, 0x58, 0x60, 0x1a, 0x68, 0xf8, 0x49, 0xa9, 0x81, 0x3a, 0x38, 0x50, 0x60, 0x1a, 0x68, 0x00, 0x61, 0x04, 0x62, 0x47, 0x38, 0xd6, 0x10, 0x3d, 0x58, 0x1a, 0x38, 0x59, 0x60, 0x1a, 0x68, 0x3b, 0x58, 0x3a, 0x38, 0xbe, 0x5d, 0xe1, 0x1b, 0xbe, 0x5e, 0xe2, 0x1b, 0x1e, 0x5f, 0x00, 0x67, 0xe0, 0x39, 0xde, 0x15, 0x23, 0x59, 0xe0, 0x3a, 0xf2, 0x15, 0x43, 0x5a, 0xe0, 0x3b, 0x06, 0x16, 0x63, 0x5b, 0xe0, 0x3c, 0x1a, 0x16, 0x83, 0x5c, 0xb9, 0x48, 0x07, 0x96, 0xba, 0x48, 0x05, 0x98, 0xdb, 0x48, 0x03, 0x98, 0xdc, 0x48, 0x01, 0x96, 0x05, 0x9e, 0x19, 0x07, 0xf2, 0x39, 0x4b, 0x1a, 0xe7, 0x97, 0xa9, 0x9e, 0x1e, 0x5d, 0x1e, 0x5e, 0x1e, 0x5f, 0x00, 0x67, 0x00, 0x60, 0x97, 0xfd, -0x00, 0x11, 0xe0, 0x3d, 0x72, 0x19, 0xa3, 0x5d, 0xe0, 0x3e, 0x86, 0x19, 0xc3, 0x5e, 0xb9, 0x48, 0x0a, 0x96, 0xba, 0x48, 0x08, 0x98, 0xdb, 0x48, 0x06, 0x98, 0xdc, 0x48, 0x04, 0x96, 0x19, 0x00, 0xfe, 0x5f, 0x07, 0x28, 0xfe, 0x5f, 0x19, 0x07, 0xf2, 0x3d, 0x58, 0x1a, 0xea, 0x97, 0x3e, 0x5f, 0x04, 0x3d, 0xff, 0x00, 0x19, 0x15, 0x01, 0x8a, 0x86, 0x9e, 0x41, 0x16, 0xc1, 0x5f, 0x64, 0x15, 0xdd, 0x48, 0x01, 0x94, 0xa1, 0x5f, 0x1d, 0x17, 0x7b, 0x98, 0x04, 0x3f, 0x00, 0xff, 0xfe, 0x5f, 0x1a, 0x16, 0x0d, 0x94, 0xe0, 0x38, 0x72, 0x19, 0x03, 0x58, 0x18, 0x10, 0x02, 0x9a, 0x02, 0x39, 0x01, 0x00, 0x12, 0x3e, 0xfd, 0x1b, 0x19, 0x06, 0x02, 0x94, 0x00, 0x3a, 0x01, 0x00, 0x1a, 0x15, 0x0d, 0x94, 0xe0, 0x38, 0x86, 0x19, 0x03, 0x58, 0x18, 0x10, 0x02, 0x9a, 0x02, 0x3c, 0x01, 0x00, 0x12, 0x3e, 0xb0, 0xa9, -0x40, 0x11, 0xfe, 0x1b, 0x19, 0x06, 0x02, 0x94, 0x00, 0x3b, 0x01, 0x00, 0x1e, 0x59, 0x21, 0x5d, 0x9e, 0x5e, 0xfd, 0x1b, 0xa0, 0x38, 0x32, 0x16, 0xc4, 0x48, 0x03, 0x5e, 0x9e, 0x58, 0xe6, 0x1b, 0x00, 0x61, 0x01, 0x69, 0x19, 0x48, 0x12, 0x98, 0xb2, 0x38, 0xe1, 0x1b, 0x03, 0x88, 0x92, 0x38, 0xe2, 0x1b, 0x0c, 0x8a, 0x18, 0x16, 0x07, 0x9a, 0x08, 0x60, 0xc0, 0x40, 0x08, 0x5e, 0xc0, 0x06, 0xc8, 0x5e, 0xc8, 0x5e, 0xc8, 0x5e, 0x9e, 0x58, 0xe4, 0x1b, 0xc0, 0x06, 0x18, 0x16, 0x2b, 0x9a, 0x50, 0x67, 0x1a, 0x6f, 0xe5, 0x58, 0xe3, 0x59, 0xc5, 0x48, 0x3f, 0x5f, 0x1b, 0x5f, 0x52, 0x67, 0x1a, 0x6f, 0xe5, 0x58, 0xe3, 0x59, 0xc4, 0x48, 0x3f, 0x5f, 0x1b, 0x5f, 0xd0, 0x3f, 0x54, 0x1a, 0xbe, 0x5f, 0x54, 0x1a, 0x7f, 0xac, 0x17, 0x90, 0xe8, 0x5f, 0xbe, 0x5f, 0x54, 0x1a, 0x9e, 0x58, 0x50, 0x1a, 0x76, 0x7e, -0x80, 0x11, 0x9e, 0x59, 0x51, 0x1a, 0x28, 0x59, 0x0c, 0x58, 0xbe, 0x59, 0x51, 0x1a, 0xbe, 0x58, 0x50, 0x1a, 0x9e, 0x58, 0x52, 0x1a, 0x9e, 0x59, 0x53, 0x1a, 0x28, 0x59, 0x0c, 0x58, 0xbe, 0x59, 0x53, 0x1a, 0xbe, 0x58, 0x52, 0x1a, 0xa2, 0x37, 0x02, 0x8a, 0x19, 0x05, 0xb1, 0x9f, 0x3e, 0x59, 0x83, 0x37, 0x02, 0x8a, 0x19, 0x04, 0xaa, 0x9f, 0x02, 0x65, 0xbe, 0x5d, 0x59, 0x1a, 0x03, 0x9e, 0x03, 0x65, 0xbe, 0x5d, 0x59, 0x1a, 0x3e, 0x5e, 0x3e, 0x5d, 0x3e, 0x5f, 0x3a, 0x38, 0x1e, 0x5c, 0x9e, 0x5d, 0xe1, 0x1b, 0x9e, 0x5e, 0xe2, 0x1b, 0xa0, 0x38, 0x32, 0x16, 0x16, 0x67, 0x1e, 0x59, 0x00, 0x61, 0xc7, 0x48, 0x3e, 0x59, 0x03, 0x5f, 0x18, 0x17, 0x35, 0x9a, 0x1e, 0x59, 0x1e, 0x5a, 0x00, 0x61, 0xe1, 0x58, 0xbe, 0x5f, 0xe6, 0x1b, 0x06, 0x58, 0x2a, 0x59, 0x06, 0x58, 0x2a, 0x59, 0x0c, 0x62, 0xb9, 0x8c, -0xc0, 0x11, 0x1c, 0x5a, 0xbe, 0x58, 0xe3, 0x1b, 0x00, 0x61, 0xe1, 0x58, 0xa8, 0x62, 0x1c, 0x5a, 0xbe, 0x58, 0xe4, 0x1b, 0x3e, 0x5a, 0x3e, 0x59, 0x41, 0x10, 0x21, 0x5f, 0x07, 0x38, 0xe5, 0x11, 0xfd, 0x48, 0x02, 0x88, 0x9e, 0x48, 0x12, 0x8a, 0x20, 0x38, 0x32, 0x16, 0x1e, 0x59, 0x1e, 0x5a, 0x16, 0x62, 0x00, 0x61, 0x82, 0x48, 0x3e, 0x5a, 0x3e, 0x59, 0x03, 0x58, 0x18, 0x10, 0x06, 0x9a, 0x1e, 0x59, 0x9e, 0x59, 0xe3, 0x1b, 0x19, 0x48, 0x3e, 0x59, 0x05, 0x94, 0x19, 0x07, 0x19, 0x04, 0x9b, 0x48, 0xe2, 0x9b, 0x03, 0x9e, 0x00, 0x60, 0xbe, 0x58, 0xe4, 0x1b, 0x3e, 0x5c, 0x3a, 0x38, 0x9e, 0x58, 0x58, 0x1a, 0x02, 0x39, 0x01, 0x00, 0x1d, 0x9a, 0x00, 0x62, 0x5f, 0x48, 0x16, 0x8a, 0x40, 0x38, 0x72, 0x19, 0x03, 0x5b, 0x40, 0x38, 0x86, 0x19, 0x03, 0x5c, 0xa3, 0x10, 0x01, 0x8c, 0x02, 0x58, 0x76, 0x63, -0x00, 0x12, 0x02, 0x39, 0x01, 0x00, 0x0a, 0x88, 0xc4, 0x10, 0x01, 0x8c, 0x02, 0x58, 0x02, 0x39, 0x01, 0x00, 0x04, 0x88, 0x01, 0x61, 0xbe, 0x59, 0x59, 0x1a, 0x04, 0x9e, 0x19, 0x02, 0x52, 0x39, 0x58, 0x1a, 0xe4, 0x89, 0x3a, 0x38, 0x9e, 0x58, 0x58, 0x1a, 0x02, 0x39, 0x01, 0x00, 0x66, 0x9a, 0x00, 0x67, 0xe0, 0x3e, 0x86, 0x19, 0xe0, 0x3a, 0x01, 0x00, 0x40, 0x3b, 0x72, 0x19, 0x40, 0x3c, 0x86, 0x19, 0xe0, 0x3d, 0x72, 0x19, 0xa3, 0x5d, 0xa4, 0x38, 0x00, 0xff, 0x63, 0x5b, 0x64, 0x39, 0x00, 0xff, 0x19, 0x48, 0x4a, 0x88, 0xa4, 0x3d, 0xff, 0x00, 0x64, 0x3b, 0xff, 0x00, 0x1e, 0x5f, 0x1e, 0x5a, 0x9e, 0x5f, 0xfd, 0x1b, 0x60, 0x38, 0x48, 0x0e, 0xe4, 0x49, 0x03, 0x5a, 0xa0, 0x38, 0x48, 0x0e, 0xe6, 0x49, 0x00, 0x61, 0x58, 0x49, 0x02, 0x9a, 0x01, 0x61, 0x03, 0x5a, 0x1e, 0x59, 0x9e, 0x58, 0x0d, 0x2c, -0x40, 0x12, 0x44, 0x1a, 0x40, 0x40, 0x9f, 0x38, 0x08, 0x58, 0xbe, 0x58, 0x83, 0x1a, 0x8a, 0xd2, 0x19, 0x10, 0x28, 0x8a, 0x9e, 0x58, 0x58, 0x1a, 0x19, 0x10, 0xbe, 0x58, 0x58, 0x1a, 0x3e, 0x59, 0x3e, 0x5a, 0x3e, 0x5f, 0x40, 0x3b, 0x72, 0x19, 0xe0, 0x3d, 0x72, 0x19, 0x18, 0x11, 0x04, 0x8a, 0x63, 0x59, 0x3b, 0x5d, 0x83, 0x59, 0x3b, 0x5e, 0x72, 0x61, 0x19, 0x69, 0x30, 0x39, 0x58, 0x1a, 0x23, 0x59, 0x3b, 0x5b, 0x86, 0x61, 0x19, 0x69, 0x30, 0x39, 0x58, 0x1a, 0x23, 0x59, 0x3b, 0x5c, 0x19, 0x10, 0x14, 0x8a, 0x52, 0x38, 0x58, 0x1a, 0x0c, 0x94, 0xf2, 0x38, 0x58, 0x1a, 0x19, 0x00, 0x0d, 0x94, 0xab, 0x9f, 0x3e, 0x59, 0x3e, 0x5a, 0x3e, 0x5f, 0x19, 0x02, 0x52, 0x39, 0x58, 0x1a, 0xa4, 0x97, 0x19, 0x07, 0xf2, 0x39, 0x58, 0x1a, 0x19, 0x01, 0x9b, 0x97, 0x9e, 0x58, 0x58, 0x1a, 0x18, 0x10, 0x0c, 0xc1, -0x80, 0x12, 0x08, 0x8a, 0x72, 0x66, 0x19, 0x6e, 0xff, 0x61, 0x19, 0x10, 0x07, 0x38, 0x88, 0x12, 0xd1, 0x25, 0xbd, 0x5e, 0x3a, 0x38, 0x1e, 0x5d, 0x1e, 0x5e, 0x1e, 0x5b, 0x1e, 0x5c, 0x83, 0x5a, 0x7d, 0x48, 0x03, 0x9a, 0x5e, 0x49, 0x23, 0x9a, 0x32, 0x9e, 0x5e, 0x49, 0x10, 0x9a, 0x61, 0x5a, 0xbe, 0x5a, 0x2e, 0x16, 0xa1, 0x5a, 0xbe, 0x5a, 0x2f, 0x16, 0xc3, 0x5a, 0xbe, 0x5a, 0x30, 0x16, 0x83, 0x5a, 0xbe, 0x5a, 0x31, 0x16, 0x02, 0x62, 0xbe, 0x5a, 0x82, 0x1a, 0x2f, 0x9e, 0x61, 0x5a, 0xbe, 0x5a, 0x2e, 0x16, 0xa1, 0x5a, 0xbe, 0x5a, 0x2f, 0x16, 0x83, 0x5a, 0xbe, 0x5a, 0x30, 0x16, 0xc3, 0x5a, 0xbe, 0x5a, 0x31, 0x16, 0x00, 0x62, 0xbe, 0x5a, 0x82, 0x1a, 0x1f, 0x9e, 0xa1, 0x5a, 0xbe, 0x5a, 0x2e, 0x16, 0x61, 0x5a, 0xbe, 0x5a, 0x2f, 0x16, 0x83, 0x5a, 0xbe, 0x5a, 0x30, 0x16, 0xc3, 0x5a, 0xf9, 0x02, -0xc0, 0x12, 0xbe, 0x5a, 0x31, 0x16, 0x06, 0x62, 0xbe, 0x5a, 0x82, 0x1a, 0x0f, 0x9e, 0xa1, 0x5a, 0xbe, 0x5a, 0x2e, 0x16, 0x61, 0x5a, 0xbe, 0x5a, 0x2f, 0x16, 0xc3, 0x5a, 0xbe, 0x5a, 0x30, 0x16, 0x83, 0x5a, 0xbe, 0x5a, 0x31, 0x16, 0x04, 0x62, 0xbe, 0x5a, 0x82, 0x1a, 0xc3, 0x5e, 0xa1, 0x58, 0xc1, 0x59, 0x1e, 0x58, 0x1e, 0x59, 0x1e, 0x5b, 0x1e, 0x5c, 0x00, 0x67, 0x9e, 0x5a, 0x82, 0x1a, 0x40, 0x3c, 0x25, 0x13, 0x89, 0x5c, 0x85, 0x04, 0x92, 0x39, 0x2e, 0x16, 0x23, 0x96, 0x92, 0x39, 0x2f, 0x16, 0x20, 0x98, 0x40, 0x3b, 0x2d, 0x13, 0x69, 0x5b, 0x66, 0x03, 0x72, 0x39, 0x30, 0x16, 0x19, 0x96, 0x72, 0x39, 0x31, 0x16, 0x16, 0x98, 0x9e, 0x59, 0xfd, 0x1b, 0x80, 0x38, 0x48, 0x0e, 0x23, 0x48, 0x9e, 0x59, 0x83, 0x1a, 0x38, 0x49, 0x0d, 0x98, 0x81, 0x5d, 0x61, 0x5e, 0x9e, 0x59, 0x82, 0x1a, 0xd8, 0xd6, -0x00, 0x13, 0x01, 0xac, 0x02, 0x90, 0x1e, 0x01, 0x01, 0x9e, 0x1f, 0x01, 0x1f, 0x21, 0xbe, 0x59, 0x82, 0x1a, 0x08, 0x9e, 0x19, 0x02, 0x1f, 0x22, 0xbe, 0x5a, 0x82, 0x1a, 0x19, 0x07, 0xe2, 0x39, 0x08, 0x00, 0xce, 0x97, 0x3e, 0x5c, 0x3e, 0x5b, 0x3e, 0x59, 0x3e, 0x58, 0xd9, 0x48, 0x04, 0x88, 0xb8, 0x48, 0x02, 0x88, 0x01, 0x60, 0x05, 0x9e, 0xdc, 0x49, 0xbb, 0x89, 0xbb, 0x48, 0xb9, 0x89, 0x00, 0x60, 0x3e, 0x5c, 0x3e, 0x5b, 0x3e, 0x5e, 0x3e, 0x5d, 0x3a, 0x38, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0x02, 0x3f, 0x01, 0x00, 0x0c, 0x98, 0x30, 0x66, 0x0b, 0x6e, 0x9e, 0x5d, 0xe8, 0x00, 0x9e, 0x5f, 0xda, 0x00, 0x19, 0x17, 0xe7, 0x38, 0x0b, 0x09, -0x40, 0x13, 0x42, 0x13, 0xa5, 0x59, 0x3d, 0x5e, 0x21, 0x9e, 0x12, 0x3f, 0x22, 0x00, 0x1e, 0x98, 0x30, 0x66, 0x0b, 0x6e, 0x9e, 0x5d, 0xe8, 0x00, 0x9e, 0x5f, 0xda, 0x00, 0x19, 0x17, 0xe7, 0x38, 0x52, 0x13, 0xa5, 0x5f, 0xd7, 0x07, 0xfd, 0x5e, 0x12, 0x3f, 0x22, 0x00, 0x0f, 0x88, 0x30, 0x66, 0x0b, 0x6e, 0x22, 0x75, 0x9e, 0x5f, 0xda, 0x00, 0x19, 0x17, 0xe7, 0x38, 0x63, 0x13, 0x00, 0x61, 0xc3, 0x58, 0x1c, 0x5d, 0x1d, 0x5e, 0x1a, 0x38, 0x1a, 0x38, 0x00, 0x60, 0x3a, 0x38, 0x27, 0x76, 0x19, 0x16, 0x39, 0x60, 0x15, 0x68, 0x9a, 0x61, 0x19, 0x69, 0x45, 0x62, 0x15, 0x6a, 0xa6, 0x63, 0x19, 0x6b, 0x00, 0x64, 0x80, 0x6c, 0x00, 0x67, 0xc7, 0x38, 0x7e, 0x13, 0xf8, 0x49, 0x04, 0x98, 0x03, 0x5d, 0xbb, 0x59, 0x43, 0x5d, 0xbb, 0x5b, 0x19, 0x01, 0x19, 0x03, 0x9d, 0x58, 0x9d, 0x5a, 0x21, 0x60, 0x24, 0x0a, -0x80, 0x13, 0x15, 0x68, 0x2b, 0x61, 0x1c, 0x69, 0x2d, 0x62, 0x15, 0x6a, 0x37, 0x63, 0x1c, 0x6b, 0x00, 0x65, 0xc7, 0x38, 0x9d, 0x13, 0xa0, 0x3c, 0x63, 0x29, 0x89, 0x5c, 0x94, 0x3c, 0xe3, 0x19, 0x05, 0x8a, 0x03, 0x5c, 0x9b, 0x59, 0x43, 0x5c, 0x9b, 0x5b, 0x04, 0x9e, 0xde, 0x59, 0x00, 0x80, 0xde, 0x5b, 0x00, 0x80, 0x19, 0x01, 0x19, 0x03, 0x19, 0x00, 0x19, 0x02, 0x19, 0x05, 0x00, 0x67, 0x80, 0x6f, 0x51, 0x60, 0x15, 0x68, 0x21, 0x61, 0x15, 0x69, 0x5d, 0x62, 0x15, 0x6a, 0x2d, 0x63, 0x15, 0x6b, 0xc7, 0x38, 0xb3, 0x13, 0xf8, 0x49, 0x04, 0x8a, 0x03, 0x5c, 0x9b, 0x59, 0x43, 0x5c, 0x9b, 0x5b, 0x19, 0x01, 0x19, 0x03, 0x19, 0x00, 0x19, 0x02, 0xca, 0x60, 0x19, 0x68, 0xd6, 0x61, 0x19, 0x69, 0xc7, 0x38, 0xbf, 0x13, 0xde, 0x58, 0xff, 0xff, 0xde, 0x59, 0xff, 0x7f, 0x19, 0x00, 0x19, 0x01, 0x00, 0xae, -0xc0, 0x13, 0x9e, 0x58, 0xfa, 0x1b, 0x12, 0x38, 0xe2, 0x19, 0x16, 0x9a, 0x00, 0x67, 0x01, 0x65, 0xc7, 0x38, 0xda, 0x13, 0xb4, 0x38, 0x4c, 0x1a, 0x0d, 0x88, 0xe0, 0x38, 0x9a, 0x19, 0xde, 0x58, 0x00, 0x80, 0xe0, 0x38, 0xa6, 0x19, 0xde, 0x58, 0x00, 0x80, 0xa0, 0x5c, 0x94, 0x3c, 0x00, 0x1c, 0xbe, 0x5c, 0x00, 0x1c, 0xa6, 0x5d, 0x19, 0x07, 0x3a, 0x38, 0x9e, 0x5f, 0xe2, 0x19, 0x18, 0x17, 0x24, 0x8a, 0x21, 0x72, 0x23, 0x61, 0x22, 0x40, 0x00, 0x3b, 0x00, 0x00, 0x15, 0x61, 0x22, 0x40, 0x00, 0x3c, 0x00, 0x00, 0xe1, 0x5e, 0x00, 0x67, 0xe0, 0x39, 0xb2, 0x19, 0xe0, 0x3a, 0xbe, 0x19, 0x79, 0x49, 0x02, 0x80, 0x9a, 0x49, 0x0c, 0x82, 0x19, 0x16, 0xdf, 0x48, 0x0c, 0x8a, 0xc0, 0x38, 0xb2, 0x19, 0x03, 0x58, 0x1b, 0x59, 0xc0, 0x38, 0xbe, 0x19, 0x03, 0x58, 0x1b, 0x5a, 0xec, 0x9f, 0x19, 0x07, 0x78, 0x6b, -0x00, 0x14, 0xe6, 0x15, 0xe9, 0x97, 0xbe, 0x5e, 0xe2, 0x19, 0x01, 0x60, 0xbe, 0x58, 0x82, 0x1a, 0x00, 0x67, 0xe2, 0x60, 0x19, 0x68, 0xf8, 0x49, 0x31, 0x94, 0xe0, 0x38, 0xca, 0x19, 0x00, 0x61, 0x38, 0x49, 0x2a, 0x9a, 0x00, 0x66, 0x27, 0x70, 0x19, 0x10, 0x07, 0x38, 0x3a, 0x14, 0xc0, 0x38, 0x39, 0x15, 0x00, 0x61, 0x38, 0x49, 0x1f, 0x9a, 0xc0, 0x38, 0x9a, 0x19, 0x00, 0x61, 0x38, 0x49, 0x03, 0x9a, 0xfe, 0x65, 0x7f, 0x6d, 0x0f, 0x9e, 0xe0, 0x38, 0xb2, 0x19, 0xc0, 0x39, 0x9a, 0x19, 0x23, 0x59, 0x11, 0x12, 0xe0, 0x38, 0xbe, 0x19, 0xc0, 0x39, 0xa6, 0x19, 0x23, 0x59, 0x11, 0x13, 0x5a, 0x40, 0x63, 0x48, 0x46, 0xd9, 0xe0, 0x38, 0xd6, 0x19, 0xb8, 0x49, 0x04, 0x94, 0xbb, 0x58, 0xe0, 0x38, 0xca, 0x19, 0xdb, 0x58, 0x19, 0x06, 0x19, 0x07, 0xcb, 0x9f, 0x00, 0x60, 0xbe, 0x58, 0x82, 0x1a, 0x1c, 0xba, -0x40, 0x14, 0x00, 0x67, 0x9e, 0x5d, 0xe2, 0x19, 0xfd, 0x48, 0x25, 0x94, 0xe0, 0x3e, 0x01, 0x00, 0xa2, 0x38, 0x01, 0x00, 0x07, 0x38, 0x67, 0x14, 0xdd, 0x48, 0x1b, 0x94, 0xe0, 0x3c, 0xca, 0x19, 0x83, 0x58, 0xc0, 0x3b, 0xca, 0x19, 0x1b, 0x49, 0x13, 0x88, 0xe0, 0x3a, 0xd6, 0x19, 0x43, 0x58, 0xc0, 0x39, 0xd6, 0x19, 0x19, 0x49, 0x05, 0x9a, 0xde, 0x5c, 0xff, 0xff, 0xde, 0x5a, 0xff, 0x7f, 0x04, 0x9e, 0xde, 0x5b, 0xff, 0xff, 0xde, 0x59, 0xff, 0x7f, 0x01, 0x60, 0xbe, 0x58, 0x82, 0x1a, 0x19, 0x06, 0x19, 0x07, 0xd9, 0x9f, 0x00, 0x67, 0xe2, 0x60, 0x19, 0x68, 0xf8, 0x49, 0x15, 0x94, 0xe0, 0x38, 0xca, 0x19, 0x00, 0x61, 0x38, 0x49, 0x0e, 0x98, 0x39, 0x61, 0x15, 0x69, 0x11, 0x01, 0xe0, 0x3a, 0xb2, 0x19, 0x43, 0x5a, 0x5b, 0x59, 0x45, 0x61, 0x15, 0x69, 0x11, 0x01, 0xe0, 0x3a, 0xbe, 0x19, 0xb2, 0x4c, -0x80, 0x14, 0x43, 0x5a, 0x5b, 0x59, 0x19, 0x07, 0xe7, 0x9f, 0x82, 0x60, 0x1a, 0x68, 0x01, 0x61, 0x38, 0x49, 0x7e, 0x8b, 0x9e, 0x58, 0xe2, 0x19, 0x19, 0x10, 0x01, 0x9a, 0x25, 0xdb, 0x92, 0x60, 0x15, 0x68, 0xff, 0x61, 0xff, 0x69, 0x27, 0x76, 0x19, 0x16, 0xd7, 0x38, 0x3d, 0x58, 0x9e, 0x5f, 0xe2, 0x19, 0x18, 0x17, 0x10, 0x8a, 0x92, 0x66, 0x15, 0x6e, 0x19, 0x17, 0xe7, 0x38, 0xa9, 0x14, 0xe0, 0x3b, 0xca, 0x19, 0x76, 0x03, 0xe0, 0x3c, 0xd6, 0x19, 0x83, 0x5c, 0x18, 0x14, 0x01, 0x88, 0x21, 0x74, 0x9b, 0x5b, 0x19, 0x17, 0x01, 0x67, 0x27, 0x76, 0x19, 0x16, 0xc7, 0x38, 0xb0, 0x14, 0xe6, 0x5f, 0x1a, 0x38, 0x19, 0x17, 0xbe, 0x5f, 0x84, 0x1a, 0xf1, 0xd5, 0x9e, 0x58, 0xe2, 0x19, 0xbe, 0x58, 0xfa, 0x1b, 0x00, 0x67, 0x27, 0x70, 0x19, 0x10, 0x07, 0x38, 0x51, 0x15, 0x9e, 0x58, 0xea, 0x04, 0xc4, 0xb3, -0xc0, 0x14, 0x18, 0x10, 0x03, 0x8a, 0x02, 0x60, 0x20, 0x78, 0x02, 0x9e, 0x02, 0x60, 0x20, 0x78, 0xe0, 0x38, 0x39, 0x15, 0xe0, 0x3c, 0xd2, 0x15, 0x00, 0x61, 0x38, 0x49, 0x50, 0x98, 0xd0, 0x73, 0x7c, 0x49, 0x02, 0x9a, 0x7b, 0x5c, 0x7e, 0x9e, 0x70, 0x3b, 0x20, 0x00, 0x7c, 0x49, 0x14, 0x98, 0xe0, 0x38, 0x63, 0x29, 0x09, 0x58, 0xe3, 0x61, 0x19, 0x69, 0x30, 0x2a, 0x5b, 0x59, 0x4c, 0x61, 0x1a, 0x69, 0x30, 0x2a, 0x5b, 0x59, 0x70, 0x3b, 0xcf, 0x00, 0x7c, 0x49, 0x34, 0x98, 0x4d, 0x61, 0x1a, 0x69, 0x30, 0x2a, 0x5b, 0x59, 0x66, 0x9e, 0xe0, 0x38, 0x63, 0x29, 0x09, 0x58, 0x14, 0x3a, 0xe3, 0x19, 0x02, 0x8a, 0x7b, 0x5c, 0x27, 0x9e, 0xe0, 0x38, 0x92, 0x15, 0x0a, 0x61, 0x38, 0x49, 0x09, 0x9c, 0xe0, 0x38, 0x63, 0x29, 0x09, 0x58, 0x00, 0x61, 0x1c, 0x69, 0x00, 0x5a, 0x32, 0x22, 0x5b, 0x59, 0x7f, 0x32, -0x00, 0x15, 0x19, 0x9e, 0xd0, 0x70, 0x19, 0x00, 0x1c, 0x49, 0x15, 0x88, 0xe0, 0x38, 0x63, 0x29, 0x09, 0x58, 0x00, 0x61, 0x1c, 0x69, 0x30, 0x22, 0x0e, 0x88, 0x30, 0x2a, 0x5b, 0x59, 0xe0, 0x38, 0x39, 0x15, 0x03, 0x58, 0xe0, 0x39, 0x13, 0x1c, 0x1b, 0x59, 0xe0, 0x38, 0x45, 0x15, 0x03, 0x58, 0xe0, 0x39, 0x1f, 0x1c, 0x1b, 0x59, 0x83, 0x58, 0x08, 0x3c, 0x01, 0x00, 0x33, 0x9e, 0xe0, 0x38, 0x63, 0x29, 0x09, 0x58, 0xd0, 0x73, 0x14, 0x39, 0x4c, 0x1a, 0x04, 0x8a, 0x00, 0x61, 0x91, 0x11, 0x09, 0x98, 0x0b, 0x9e, 0x7c, 0x49, 0x09, 0x94, 0x7b, 0x5c, 0x00, 0x61, 0x1c, 0x69, 0x00, 0x5a, 0x32, 0x22, 0x5b, 0x59, 0x83, 0x59, 0x2a, 0x3c, 0x01, 0x00, 0x00, 0x58, 0x70, 0x3b, 0x1f, 0x00, 0x7c, 0x49, 0x10, 0x96, 0xe3, 0x61, 0x19, 0x69, 0x30, 0x22, 0x5b, 0x59, 0x4d, 0x61, 0x1a, 0x69, 0x30, 0x22, 0x44, 0x4e, -0x40, 0x15, 0x5b, 0x59, 0x83, 0x5b, 0x72, 0x3b, 0xd0, 0x00, 0x0c, 0x9a, 0xd0, 0x73, 0x19, 0x13, 0x7b, 0x5c, 0x08, 0x9e, 0x54, 0xd5, 0x19, 0x03, 0x7c, 0x49, 0x04, 0x96, 0x4d, 0x61, 0x1a, 0x69, 0x30, 0x22, 0x5b, 0x59, 0x19, 0x07, 0x99, 0xd6, 0x3a, 0x38, 0x1e, 0x58, 0x1e, 0x5b, 0x21, 0x72, 0x23, 0x65, 0xa2, 0x40, 0x00, 0x3d, 0x00, 0x00, 0xe0, 0x38, 0x5b, 0x1c, 0x03, 0x58, 0x18, 0x10, 0x02, 0x94, 0x00, 0x60, 0x0b, 0x9e, 0x1d, 0x48, 0x02, 0x9a, 0xa1, 0x58, 0x07, 0x9e, 0x40, 0x3b, 0x00, 0x00, 0x1b, 0x48, 0x03, 0x96, 0xa2, 0x13, 0x1b, 0x48, 0x03, 0x9a, 0xe0, 0x39, 0x9a, 0x19, 0x1b, 0x59, 0x15, 0x65, 0xa2, 0x40, 0x00, 0x3d, 0x00, 0x00, 0xe0, 0x38, 0x67, 0x1c, 0x03, 0x58, 0x18, 0x10, 0x02, 0x94, 0x00, 0x60, 0x0b, 0x9e, 0x1d, 0x48, 0x02, 0x9a, 0xa1, 0x58, 0x07, 0x9e, 0x40, 0x3b, 0xcf, 0x67, -0x80, 0x15, 0x00, 0x00, 0x1b, 0x48, 0x03, 0x96, 0xa2, 0x13, 0x1b, 0x48, 0x03, 0x9a, 0xe0, 0x39, 0xa6, 0x19, 0x1b, 0x59, 0x3e, 0x5b, 0x3e, 0x58, 0x3a, 0x38, 0x00, 0x60, 0xbe, 0x58, 0x04, 0x1c, 0x9e, 0x58, 0xe2, 0x19, 0x12, 0x38, 0xea, 0x04, 0x31, 0x94, 0x01, 0x60, 0xbe, 0x58, 0x04, 0x1c, 0x27, 0x76, 0x19, 0x16, 0x00, 0x65, 0x00, 0x67, 0xc7, 0x38, 0xc4, 0x15, 0xe0, 0x38, 0x9a, 0x19, 0xb8, 0x49, 0x23, 0x98, 0xe0, 0x3e, 0x63, 0x29, 0xc9, 0x5e, 0xd4, 0x3e, 0xe3, 0x19, 0x0b, 0x88, 0x03, 0x58, 0xe0, 0x39, 0x5b, 0x1c, 0x1b, 0x59, 0xe0, 0x38, 0xa6, 0x19, 0x03, 0x58, 0xe0, 0x39, 0x67, 0x1c, 0x1b, 0x59, 0x12, 0x9e, 0xe0, 0x39, 0x43, 0x1c, 0x23, 0x59, 0xe0, 0x3a, 0x4f, 0x1c, 0x43, 0x5a, 0xe0, 0x38, 0x9a, 0x19, 0x11, 0x00, 0xe0, 0x39, 0x5b, 0x1c, 0x1b, 0x59, 0xe0, 0x38, 0xa6, 0x19, 0x4a, 0xa6, -0xc0, 0x15, 0x12, 0x00, 0xe0, 0x39, 0x67, 0x1c, 0x1b, 0x59, 0x19, 0x07, 0x3a, 0x38, 0x27, 0x76, 0x19, 0x16, 0x00, 0x67, 0xc7, 0x38, 0xef, 0x15, 0x00, 0x62, 0xe0, 0x38, 0x39, 0x15, 0x58, 0x49, 0x1f, 0x98, 0xe0, 0x39, 0x9a, 0x19, 0x59, 0x49, 0x1b, 0x98, 0x23, 0x5a, 0x12, 0x12, 0xe0, 0x3c, 0x43, 0x1c, 0x5b, 0x5c, 0xe0, 0x38, 0x45, 0x15, 0xe0, 0x39, 0xa6, 0x19, 0x23, 0x5b, 0x13, 0x13, 0xe0, 0x3c, 0x4f, 0x1c, 0x7b, 0x5c, 0x9e, 0x58, 0x04, 0x1c, 0x18, 0x10, 0x09, 0x8a, 0x5a, 0x40, 0x63, 0x48, 0x46, 0xd9, 0x18, 0x15, 0x01, 0x88, 0x21, 0x75, 0xe0, 0x38, 0x92, 0x15, 0xbb, 0x58, 0x19, 0x07, 0x3a, 0x38, 0x27, 0x75, 0x19, 0x15, 0xa7, 0x38, 0x73, 0x16, 0xa0, 0x3f, 0x63, 0x29, 0xe9, 0x5f, 0x9e, 0x5c, 0x86, 0x1a, 0xe0, 0x5b, 0x83, 0x24, 0xa0, 0x3b, 0xa0, 0x1a, 0x63, 0x5b, 0xbd, 0x13, 0xe6, 0xbc, -0x00, 0x16, 0x01, 0x96, 0x87, 0x2c, 0xbe, 0x5c, 0x86, 0x1a, 0xa0, 0x3c, 0x92, 0x15, 0x83, 0x5c, 0x82, 0x38, 0xff, 0xff, 0x69, 0x8a, 0x21, 0x73, 0x66, 0x5b, 0x83, 0x11, 0x65, 0x9a, 0x81, 0x58, 0xa0, 0x3a, 0x9e, 0x15, 0x43, 0x5a, 0x21, 0x73, 0x68, 0x5b, 0x42, 0x39, 0xfe, 0x7f, 0x05, 0x88, 0xf4, 0x39, 0x87, 0x1a, 0x02, 0x8a, 0x61, 0x5a, 0x16, 0x9e, 0x5b, 0x48, 0x14, 0x98, 0xa0, 0x39, 0x88, 0x1a, 0x23, 0x59, 0x18, 0x11, 0x02, 0x8a, 0x04, 0x62, 0x0d, 0x9e, 0x02, 0xa8, 0xa0, 0x39, 0xa0, 0x1a, 0x23, 0x59, 0xbd, 0x11, 0x07, 0x96, 0xa0, 0x39, 0x94, 0x1a, 0x23, 0x59, 0x24, 0x39, 0xff, 0x00, 0x01, 0x8a, 0x61, 0x5a, 0x04, 0x61, 0x01, 0x40, 0x1c, 0x5a, 0x00, 0x39, 0x01, 0x00, 0x28, 0x59, 0x1a, 0x00, 0x08, 0x58, 0x08, 0x58, 0x1a, 0x11, 0x03, 0x88, 0xf4, 0x39, 0x4a, 0x1a, 0x28, 0x88, 0x7f, 0xca, -0x40, 0x16, 0x04, 0x62, 0xf4, 0x3e, 0x86, 0x1a, 0x01, 0x8a, 0x19, 0x62, 0x00, 0x61, 0xbe, 0x59, 0x17, 0x1f, 0x9e, 0x59, 0x20, 0x1d, 0x18, 0x11, 0x13, 0x8a, 0x22, 0x39, 0x68, 0x01, 0x14, 0x8a, 0x9e, 0x5e, 0xdb, 0x1e, 0x9e, 0x59, 0xdc, 0x1e, 0xc1, 0x06, 0x1b, 0x16, 0x09, 0x88, 0x9e, 0x5e, 0xf1, 0x04, 0x9e, 0x59, 0xf2, 0x04, 0xc1, 0x06, 0x1b, 0x16, 0x02, 0x88, 0x3a, 0x02, 0x05, 0x9e, 0x9e, 0x59, 0xb5, 0x00, 0x1a, 0x11, 0x01, 0x88, 0x3a, 0x02, 0xbe, 0x5a, 0x17, 0x1f, 0x02, 0x11, 0x0b, 0x96, 0xa0, 0x38, 0x63, 0x29, 0x09, 0x58, 0x14, 0x3a, 0x00, 0x1c, 0x05, 0x88, 0x00, 0x58, 0x84, 0x61, 0x1a, 0x69, 0x30, 0x22, 0x5b, 0x59, 0x19, 0x15, 0x21, 0x74, 0x88, 0x5c, 0x92, 0x60, 0x15, 0x68, 0x9e, 0x61, 0x15, 0x69, 0x00, 0x65, 0x27, 0x76, 0x19, 0x16, 0xc7, 0x38, 0x97, 0x16, 0xa0, 0x3f, 0x7a, 0x56, -0x80, 0x16, 0x63, 0x29, 0xe9, 0x5f, 0xff, 0x66, 0xff, 0x6e, 0xd8, 0x49, 0x03, 0x8a, 0x03, 0x5a, 0x5b, 0x59, 0x0c, 0x9e, 0xf4, 0x3b, 0xe3, 0x19, 0x09, 0x8a, 0xa0, 0x3b, 0xa0, 0x1a, 0x63, 0x5b, 0xbd, 0x13, 0x04, 0x82, 0x99, 0x49, 0x02, 0x82, 0x8a, 0x39, 0x01, 0x00, 0x19, 0x00, 0x19, 0x01, 0x19, 0x05, 0x3a, 0x38, 0x9e, 0x58, 0xe3, 0x19, 0x9e, 0x59, 0x84, 0x1a, 0x20, 0x59, 0x20, 0x21, 0xbe, 0x59, 0x4a, 0x1a, 0x14, 0x3a, 0x84, 0x1a, 0xbe, 0x5a, 0xe3, 0x19, 0x16, 0x39, 0x85, 0x1a, 0x20, 0x21, 0xbe, 0x59, 0x87, 0x1a, 0xbe, 0x58, 0x85, 0x1a, 0x01, 0x65, 0x00, 0x66, 0x27, 0x77, 0x19, 0x17, 0xe7, 0x38, 0xea, 0x16, 0x05, 0x27, 0x09, 0x8a, 0xc0, 0x39, 0x88, 0x1a, 0x23, 0x5b, 0x66, 0x5b, 0xb4, 0x3f, 0x4a, 0x1a, 0x01, 0x8a, 0x03, 0xa8, 0x7b, 0x59, 0xc0, 0x39, 0xa0, 0x1a, 0x23, 0x5b, 0x56, 0xfa, -0xc0, 0x16, 0xa2, 0x27, 0x0e, 0x8a, 0xd0, 0x77, 0xf0, 0x3f, 0x20, 0x00, 0xf0, 0x3f, 0xcf, 0x00, 0xc0, 0x3c, 0xd2, 0x15, 0xfc, 0x49, 0x05, 0x98, 0x62, 0x3f, 0x64, 0x00, 0x03, 0x82, 0x19, 0x03, 0x01, 0x9e, 0x00, 0x63, 0x7b, 0x59, 0x05, 0x27, 0x0f, 0x8a, 0xc0, 0x39, 0x94, 0x1a, 0x23, 0x5b, 0x66, 0x5b, 0xc0, 0x3c, 0x92, 0x15, 0x83, 0x5c, 0x92, 0x3f, 0x21, 0x00, 0x04, 0x80, 0x82, 0x3f, 0x00, 0x10, 0x01, 0x82, 0x03, 0xa8, 0x7b, 0x59, 0xa0, 0x27, 0x04, 0x88, 0xc0, 0x39, 0x9e, 0x15, 0xde, 0x59, 0xaa, 0x55, 0xa6, 0x5d, 0x19, 0x06, 0x3a, 0x38, 0x00, 0x67, 0xbe, 0x5f, 0xf1, 0x1e, 0xbe, 0x5f, 0xf3, 0x1e, 0x00, 0x67, 0x01, 0x66, 0xd0, 0x3e, 0xd0, 0x00, 0xd0, 0x3e, 0x1f, 0x00, 0xe3, 0x60, 0x19, 0x68, 0xe0, 0x39, 0x63, 0x29, 0x29, 0x5c, 0x14, 0x20, 0x87, 0x88, 0xe0, 0x38, 0x39, 0x15, 0x0d, 0x8c, -0x00, 0x17, 0x00, 0x61, 0x38, 0x49, 0x45, 0x98, 0x37, 0x9e, 0x95, 0x38, 0x4d, 0x1a, 0xbe, 0x58, 0x4d, 0x1a, 0xe0, 0x38, 0x63, 0x29, 0x09, 0x58, 0x00, 0x61, 0x1c, 0x69, 0x30, 0x22, 0x2c, 0x8a, 0x00, 0x58, 0x30, 0x22, 0x5b, 0x59, 0xe0, 0x3b, 0x13, 0x1c, 0xe0, 0x39, 0x43, 0x1c, 0x23, 0x59, 0x71, 0x13, 0x18, 0x13, 0x02, 0x94, 0x00, 0x63, 0x07, 0x9e, 0x21, 0x72, 0x23, 0x65, 0xa2, 0x40, 0x18, 0x00, 0x78, 0x48, 0x01, 0x9a, 0x01, 0x5b, 0xe0, 0x39, 0x51, 0x15, 0x7b, 0x59, 0xe0, 0x3b, 0x1f, 0x1c, 0xe0, 0x39, 0x4f, 0x1c, 0x23, 0x59, 0x71, 0x13, 0x18, 0x13, 0x02, 0x94, 0x00, 0x63, 0x07, 0x9e, 0x21, 0x72, 0x15, 0x65, 0xa2, 0x40, 0x18, 0x00, 0x78, 0x48, 0x01, 0x9a, 0x01, 0x5b, 0xe0, 0x39, 0x5d, 0x15, 0x7b, 0x59, 0xee, 0x9e, 0xe0, 0x38, 0x39, 0x15, 0x03, 0x58, 0xe0, 0x39, 0x51, 0x15, 0x1f, 0xd8, +0xc0, 0x03, 0x2d, 0x60, 0xbe, 0x58, 0x0a, 0xf8, 0x94, 0x60, 0xbe, 0x58, 0x0c, 0xf8, 0x0f, 0x60, 0xbe, 0x58, 0x0b, 0xf8, 0x9e, 0x58, 0x07, 0xf8, 0x04, 0x38, 0xfe, 0xff, 0xbe, 0x58, 0x07, 0xf8, 0xdd, 0xaa, 0xa5, 0xac, 0x01, 0x90, 0xf3, 0xc8, 0x99, 0xe9, 0x19, 0x38, 0xf2, 0x41, 0xed, 0xac, 0x7a, 0x92, 0xd5, 0xaa, 0xe5, 0xa8, 0x4f, 0xe5, 0x0c, 0xf1, 0x9e, 0x58, 0xe8, 0x00, 0x9e, 0x59, 0xe9, 0x00, 0x19, 0x48, 0x01, 0x88, 0x42, 0xa9, 0x18, 0xec, 0x9e, 0x58, 0x36, 0x1d, 0x1d, 0x10, 0x21, 0x8a, 0x9e, 0x58, 0x36, 0x1d, 0x1b, 0x10, 0x1d, 0x8a, 0xdb, 0xf1, 0x86, 0xf6, 0x00, 0x60, 0xbe, 0x58, 0x43, 0x1a, 0x9e, 0x58, 0xb8, 0x04, 0x18, 0x10, 0x14, 0x88, 0x9e, 0x58, 0xc6, 0x00, 0x19, 0x10, 0x10, 0x8a, 0x9e, 0x58, 0xea, 0x19, 0x00, 0x58, 0xbe, 0x58, 0xd3, 0x00, 0x9e, 0x58, 0xeb, 0x19, 0x9f, 0xe2, +0x00, 0x04, 0x00, 0x58, 0xbe, 0x58, 0xd4, 0x00, 0x9e, 0x58, 0xec, 0x19, 0x00, 0x58, 0xbe, 0x58, 0xd5, 0x00, 0x0c, 0x9e, 0xff, 0x60, 0xff, 0x68, 0xbe, 0x58, 0xd3, 0x00, 0xff, 0x60, 0xff, 0x68, 0xbe, 0x58, 0xd4, 0x00, 0xff, 0x60, 0xff, 0x68, 0xbe, 0x58, 0xd5, 0x00, 0x9e, 0x58, 0xfc, 0x01, 0x78, 0xac, 0x08, 0x90, 0xff, 0x60, 0xff, 0x68, 0xbe, 0x58, 0xd5, 0x00, 0xbe, 0x58, 0xd4, 0x00, 0xbe, 0x58, 0xd3, 0x00, 0x9d, 0xeb, 0xd7, 0xea, 0x9e, 0x58, 0xe8, 0x00, 0x9e, 0x59, 0xe9, 0x00, 0x19, 0x48, 0x01, 0x88, 0x42, 0xa9, 0x18, 0xec, 0x26, 0x60, 0x04, 0x68, 0x3e, 0x61, 0x04, 0x69, 0x9e, 0x5a, 0xbb, 0x00, 0x57, 0x38, 0x3d, 0x58, 0x06, 0x70, 0x00, 0xac, 0x12, 0x90, 0x9e, 0x58, 0xfc, 0x1c, 0x18, 0x10, 0x0e, 0x88, 0x9e, 0x58, 0x47, 0x1e, 0x78, 0xac, 0x01, 0x90, 0x0d, 0x9e, 0x73, 0xed, 0x3d, 0xb7, +0x40, 0x04, 0x9e, 0x58, 0x1e, 0x1e, 0x18, 0x10, 0x0d, 0x8a, 0xef, 0xec, 0x4f, 0xed, 0x61, 0xed, 0x99, 0xed, 0x9e, 0x58, 0x47, 0x1e, 0x78, 0xac, 0x05, 0x90, 0x78, 0xaa, 0xbe, 0x58, 0x47, 0x1e, 0xbe, 0x58, 0x04, 0xf8, 0x02, 0x9e, 0x9d, 0xf7, 0x00, 0x9e, 0x4f, 0xf7, 0x19, 0x38, 0xd7, 0x41, 0xe6, 0xff, 0x5c, 0xca, 0x8f, 0xca, 0xc2, 0xca, 0x19, 0x38, 0xa1, 0x51, 0xba, 0xac, 0x0f, 0x92, 0x9e, 0x58, 0xc1, 0x1d, 0x06, 0x39, 0x55, 0x00, 0x05, 0x8a, 0x06, 0x39, 0xa5, 0x00, 0x02, 0x8a, 0x42, 0xa9, 0x78, 0x9e, 0x9d, 0x60, 0x4e, 0x68, 0xef, 0xb0, 0xff, 0xa9, 0x32, 0xc8, 0xba, 0xac, 0x71, 0x92, 0x9e, 0x58, 0xc1, 0x1d, 0x06, 0x39, 0x55, 0x00, 0x05, 0x8a, 0x06, 0x39, 0xa5, 0x00, 0x02, 0x8a, 0x42, 0xa9, 0x67, 0x9e, 0x9d, 0x60, 0x4e, 0x68, 0xef, 0xb0, 0xff, 0xa9, 0x95, 0xac, 0x05, 0x90, 0xd2, 0xd2, +0x80, 0x04, 0x9e, 0x5f, 0xfb, 0x04, 0xbe, 0x5f, 0xfb, 0x04, 0x95, 0xaa, 0x9e, 0x58, 0xc1, 0x1d, 0x06, 0x39, 0x55, 0x00, 0x05, 0x8a, 0x06, 0x39, 0xa5, 0x00, 0x02, 0x8a, 0x42, 0xa9, 0x52, 0x9e, 0x9d, 0x60, 0x4e, 0x68, 0xef, 0xb0, 0xff, 0xa9, 0xb9, 0xac, 0xd9, 0x91, 0xfd, 0xac, 0x1a, 0x90, 0x9e, 0x58, 0xc1, 0x1d, 0x06, 0x39, 0x55, 0x00, 0x05, 0x8a, 0x06, 0x39, 0xa5, 0x00, 0x02, 0x8a, 0x42, 0xa9, 0x40, 0x9e, 0x9d, 0x60, 0x4e, 0x68, 0xef, 0xb0, 0xff, 0xa9, 0x80, 0x62, 0x57, 0x6a, 0x48, 0x63, 0x0e, 0x6b, 0x0c, 0x61, 0x24, 0x60, 0x01, 0x40, 0x19, 0x10, 0x07, 0x38, 0xb0, 0x04, 0x4b, 0x5c, 0x9d, 0x5b, 0x85, 0xac, 0x1f, 0x90, 0x9e, 0x58, 0xc1, 0x1d, 0x06, 0x39, 0x55, 0x00, 0x05, 0x8a, 0x06, 0x39, 0xa5, 0x00, 0x02, 0x8a, 0x42, 0xa9, 0x24, 0x9e, 0x9d, 0x60, 0x4e, 0x68, 0xef, 0xb0, 0x16, 0x62, +0xc0, 0x04, 0xff, 0xa9, 0x48, 0x62, 0x0e, 0x6a, 0x7a, 0x63, 0x02, 0x6b, 0x9e, 0x5c, 0xbb, 0x00, 0x9e, 0x5d, 0xbc, 0x00, 0xa4, 0x05, 0x19, 0x15, 0xa7, 0x38, 0xd1, 0x04, 0x63, 0x5c, 0x83, 0x5d, 0xbb, 0x5a, 0x19, 0x02, 0x19, 0x03, 0x9e, 0x58, 0xc1, 0x1d, 0x06, 0x39, 0x55, 0x00, 0x05, 0x8a, 0x06, 0x39, 0xa5, 0x00, 0x02, 0x8a, 0x42, 0xa9, 0x05, 0x9e, 0x9d, 0x60, 0x4e, 0x68, 0xef, 0xb0, 0xff, 0xa9, 0x7a, 0xeb, 0x34, 0x61, 0x12, 0x69, 0x9e, 0x58, 0xbd, 0x1d, 0x38, 0x48, 0x02, 0x8a, 0x42, 0xa9, 0x0f, 0x9e, 0x78, 0x61, 0x56, 0x69, 0x9e, 0x58, 0xbe, 0x1d, 0x38, 0x48, 0x02, 0x8a, 0x42, 0xa9, 0x07, 0x9e, 0xbc, 0x61, 0x9a, 0x69, 0x9e, 0x58, 0xbf, 0x1d, 0x38, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x9d, 0x60, 0x4e, 0x68, 0xef, 0xb0, 0xff, 0xa9, 0x1a, 0x38, 0x9e, 0x58, 0xe8, 0x00, 0x9e, 0x59, 0x70, 0x4c, +0x00, 0x05, 0xe9, 0x00, 0x19, 0x48, 0x01, 0x88, 0x42, 0xa9, 0x18, 0xec, 0x9e, 0x58, 0xf8, 0x04, 0x19, 0x00, 0xbe, 0x58, 0xf8, 0x04, 0x9e, 0x58, 0xe8, 0x00, 0x9e, 0x59, 0xe9, 0x00, 0x19, 0x48, 0x04, 0x88, 0x1a, 0x38, 0x1a, 0x38, 0x1a, 0x38, 0x42, 0xa9, 0x98, 0x3f, 0x62, 0x03, 0x9e, 0x5e, 0x50, 0x01, 0x00, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xbc, 0x01, 0x01, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xbd, 0x01, 0x1f, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xbe, 0x01, 0x20, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xbf, 0x01, 0x21, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xd5, 0x1a, 0x02, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0x51, 0x01, 0xc8, 0x58, 0xc0, 0x06, 0x08, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0x52, 0x01, 0x03, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0xb2, 0xc8, +0x40, 0x05, 0x9e, 0x5e, 0xd6, 0x1a, 0x04, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xd7, 0x1a, 0x05, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0x55, 0x01, 0x06, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0x56, 0x01, 0x07, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0x57, 0x01, 0x0c, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0x58, 0x01, 0x0e, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0x59, 0x01, 0x12, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xba, 0x01, 0x09, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xd8, 0x1a, 0x0a, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0x5b, 0x01, 0x0b, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0xb4, 0x60, 0x01, 0x68, 0x22, 0x61, 0xf8, 0x69, 0xb9, 0x66, 0x01, 0x6e, 0xc2, 0x3e, 0xb4, 0x01, 0xc7, 0x38, 0x7d, 0x05, 0x05, 0x5a, 0x5d, 0x59, 0x9e, 0x5e, 0x5c, 0x01, 0xf6, 0x5e, +0x80, 0x05, 0x0f, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0x5d, 0x01, 0x10, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x5e, 0x60, 0x01, 0x68, 0x28, 0x61, 0xf8, 0x69, 0x63, 0x66, 0x01, 0x6e, 0xc2, 0x3e, 0x5e, 0x01, 0xc7, 0x38, 0x93, 0x05, 0x05, 0x5a, 0x5d, 0x59, 0x9e, 0x5e, 0xbb, 0x01, 0x2e, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x64, 0x60, 0x01, 0x68, 0x2f, 0x61, 0xf8, 0x69, 0x6f, 0x66, 0x01, 0x6e, 0xc2, 0x3e, 0x64, 0x01, 0xc7, 0x38, 0xa4, 0x05, 0x05, 0x5a, 0x5d, 0x59, 0x70, 0x60, 0x01, 0x68, 0x3b, 0x61, 0xf8, 0x69, 0x7b, 0x66, 0x01, 0x6e, 0xc2, 0x3e, 0x70, 0x01, 0xc7, 0x38, 0xb0, 0x05, 0x05, 0x5a, 0x5d, 0x59, 0x7c, 0x60, 0x01, 0x68, 0x47, 0x61, 0xf8, 0x69, 0x52, 0x66, 0xf8, 0x6e, 0xc2, 0x3e, 0x47, 0xf8, 0xc7, 0x38, 0xbf, 0x05, 0x03, 0x5a, 0x05, 0x5b, 0xfe, 0x5b, 0x43, 0x2a, 0x5d, 0x59, 0xae, 0x6c, +0xc0, 0x05, 0x94, 0x60, 0x01, 0x68, 0x53, 0x61, 0xf8, 0x69, 0x5e, 0x66, 0xf8, 0x6e, 0xc2, 0x3e, 0x53, 0xf8, 0xc7, 0x38, 0xce, 0x05, 0x03, 0x5a, 0x05, 0x5b, 0xfe, 0x5b, 0x43, 0x2a, 0x5d, 0x59, 0xac, 0x60, 0x01, 0x68, 0x13, 0x61, 0xf8, 0x69, 0xb2, 0x66, 0x01, 0x6e, 0xc2, 0x3e, 0xac, 0x01, 0xc7, 0x38, 0xda, 0x05, 0x05, 0x5a, 0x5d, 0x59, 0x3a, 0x38, 0x9e, 0x5e, 0xc3, 0x01, 0xaa, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xc7, 0x01, 0xaf, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xc8, 0x01, 0xb0, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xd9, 0x1a, 0xb1, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xca, 0x01, 0xb2, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xcd, 0x01, 0xb5, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xce, 0x01, 0xb6, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0x78, 0x58, +0x00, 0x06, 0xcf, 0x01, 0xb7, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xd0, 0x01, 0xd8, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xd1, 0x01, 0xb8, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xd3, 0x01, 0xba, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xd4, 0x01, 0xbb, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xd5, 0x01, 0xbc, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xd6, 0x01, 0xbd, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xd7, 0x01, 0xbe, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xd8, 0x01, 0xbf, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xd9, 0x01, 0xc0, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xda, 0x01, 0xc1, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xdb, 0x01, 0xc2, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xdc, 0x01, 0xc3, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0xb2, 0x4e, +0x40, 0x06, 0x9e, 0x5e, 0xdd, 0x01, 0xc4, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xde, 0x01, 0xc5, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xdf, 0x01, 0xc6, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xe0, 0x01, 0xc7, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xe1, 0x01, 0xc8, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xe2, 0x01, 0xc9, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xe3, 0x01, 0xca, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xe4, 0x01, 0xcb, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xe5, 0x01, 0xcc, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xe6, 0x01, 0xcd, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xe7, 0x01, 0xce, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xe8, 0x01, 0xcf, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xe9, 0x01, 0xd0, 0x60, 0xf8, 0x68, 0xeb, 0x55, +0x80, 0x06, 0xdb, 0x58, 0x9e, 0x5e, 0xea, 0x01, 0xd1, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xeb, 0x01, 0xd2, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xec, 0x01, 0xd3, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xed, 0x01, 0xd4, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xee, 0x01, 0xd5, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xef, 0x01, 0xd6, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xf0, 0x01, 0xd7, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xf1, 0x01, 0xea, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xf2, 0x01, 0xeb, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xf3, 0x01, 0xec, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xf4, 0x01, 0xed, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xf5, 0x01, 0xee, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xf6, 0x01, 0xef, 0x60, 0xcc, 0x47, +0xc0, 0x06, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xf7, 0x01, 0xf0, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xf8, 0x01, 0xf1, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x3a, 0x38, 0x00, 0xbc, 0xb1, 0x00, 0x18, 0xaa, 0x10, 0xaa, 0x00, 0xbd, 0xb1, 0x00, 0x00, 0x60, 0x80, 0xb0, 0x00, 0x60, 0x81, 0xb0, 0x00, 0x60, 0x82, 0xb0, 0x00, 0x60, 0x83, 0xb0, 0x00, 0x60, 0x9c, 0xb0, 0xc0, 0x60, 0x13, 0x68, 0x9d, 0xb0, 0x00, 0x60, 0xcf, 0xb0, 0x3a, 0x38, 0x41, 0xab, 0x51, 0xb0, 0x78, 0xa8, 0x70, 0xa8, 0x68, 0xaa, 0x60, 0xaa, 0xd1, 0xb0, 0x3a, 0x38, 0x00, 0x60, 0x1f, 0x68, 0x00, 0x61, 0x00, 0x62, 0x17, 0x38, 0x5d, 0x59, 0x3a, 0x38, 0x3e, 0xb0, 0x08, 0xaa, 0x00, 0xaa, 0x18, 0xaa, 0x10, 0xaa, 0xbe, 0xb0, 0x10, 0x60, 0x9e, 0xb0, 0x30, 0xb0, 0x38, 0xa8, 0xb0, 0xb0, 0x3e, 0xb0, 0x38, 0xaa, 0xbe, 0xb0, 0x64, 0x58, +0x00, 0x07, 0x84, 0xb0, 0x3c, 0xa9, 0x3e, 0xb0, 0x78, 0xaa, 0xbe, 0xb0, 0x00, 0x60, 0x00, 0xbd, 0xaa, 0x00, 0x30, 0xb0, 0x08, 0xaa, 0x18, 0xaa, 0x00, 0xbd, 0x30, 0x00, 0x36, 0xb0, 0x08, 0xaa, 0x18, 0xaa, 0x00, 0xbd, 0x36, 0x00, 0x33, 0xb0, 0x08, 0xa8, 0x18, 0xa8, 0x00, 0xbd, 0x33, 0x00, 0x3a, 0x38, 0x04, 0x60, 0x69, 0x78, 0x55, 0x60, 0x6a, 0x78, 0x6b, 0x78, 0x6c, 0x78, 0x6d, 0x78, 0x82, 0xac, 0x28, 0x92, 0x00, 0x60, 0x88, 0x68, 0xae, 0xb0, 0x20, 0x60, 0xc4, 0x68, 0xd0, 0xb0, 0x1e, 0x59, 0x1e, 0x5a, 0x93, 0x60, 0x2f, 0x68, 0x09, 0x58, 0x04, 0x39, 0xff, 0x00, 0x04, 0x3a, 0x00, 0xff, 0xfe, 0x5a, 0x22, 0x32, 0xff, 0x61, 0x04, 0x38, 0xff, 0x00, 0x3a, 0x48, 0x01, 0x8a, 0x10, 0x60, 0xd2, 0xb0, 0x3e, 0x5a, 0x3e, 0x59, 0x00, 0x60, 0x5d, 0x78, 0x19, 0x38, 0x8c, 0x50, 0x92, 0xaa, 0x0b, 0x60, +0x40, 0x07, 0xaa, 0xac, 0x01, 0x90, 0x92, 0xa8, 0xaa, 0xaa, 0xf9, 0xab, 0xf1, 0xab, 0xfd, 0xa9, 0xf5, 0xa9, 0x01, 0x9e, 0x1a, 0x38, 0xaa, 0xac, 0x04, 0x92, 0xa2, 0xa8, 0x90, 0xc7, 0x82, 0xac, 0x00, 0x90, 0x3a, 0x38, 0x90, 0xaa, 0xa2, 0xaa, 0x81, 0xaa, 0xb9, 0xaa, 0xba, 0xa8, 0xb0, 0xa8, 0xb8, 0xaa, 0x02, 0x60, 0xbe, 0x58, 0x12, 0x00, 0x01, 0x60, 0xbe, 0x58, 0x11, 0x00, 0x01, 0x60, 0xbe, 0x58, 0xfb, 0x1c, 0xff, 0xaa, 0x00, 0x60, 0xbe, 0x58, 0x1b, 0x00, 0xbe, 0x58, 0xc6, 0x00, 0x00, 0x60, 0xbe, 0x58, 0xa3, 0x1c, 0xbe, 0x58, 0xa4, 0x1c, 0xbe, 0x58, 0xa5, 0x1c, 0xbe, 0x58, 0xfc, 0x1c, 0xbe, 0x58, 0xfd, 0x1c, 0xe6, 0xa8, 0x88, 0xb0, 0x89, 0xb0, 0x78, 0xa9, 0x3a, 0x38, 0x30, 0x60, 0x80, 0x68, 0xcf, 0xb0, 0xcd, 0xa9, 0x00, 0x60, 0xbe, 0x58, 0xae, 0x00, 0x00, 0x60, 0xbe, 0x58, 0xba, 0x14, +0x80, 0x07, 0xaf, 0x00, 0xbe, 0x58, 0xc2, 0x1d, 0xbe, 0x58, 0xc3, 0x1d, 0xbe, 0x58, 0xc4, 0x1d, 0x3a, 0x38, 0x36, 0x60, 0x80, 0x68, 0x8f, 0xb0, 0xdd, 0xa9, 0x9d, 0x60, 0x4e, 0x68, 0xef, 0xb0, 0x3a, 0x38, 0x39, 0xb0, 0x38, 0xaa, 0xb9, 0xb0, 0x30, 0xb0, 0x38, 0xa8, 0xb0, 0xb0, 0x3c, 0xab, 0x3a, 0x38, 0x3c, 0xa9, 0x3a, 0x38, 0x02, 0x3f, 0x01, 0x00, 0x0c, 0x98, 0x30, 0x66, 0x0b, 0x6e, 0x9e, 0x5d, 0xe8, 0x00, 0x9e, 0x5f, 0xda, 0x00, 0x19, 0x17, 0xe7, 0x38, 0xa7, 0x07, 0xa5, 0x59, 0x3d, 0x5e, 0x22, 0x9e, 0x12, 0x3f, 0x22, 0x00, 0x1f, 0x98, 0x30, 0x66, 0x0b, 0x6e, 0x9e, 0x5d, 0xe8, 0x00, 0x9e, 0x5f, 0xda, 0x00, 0x19, 0x17, 0xe7, 0x38, 0xb7, 0x07, 0xa5, 0x5f, 0xd7, 0x07, 0xfd, 0x5e, 0x12, 0x3f, 0x22, 0x00, 0x10, 0x88, 0x30, 0x66, 0x0b, 0x6e, 0x9e, 0x5d, 0x22, 0x00, 0x9e, 0x5f, 0xdc, 0x4b, +0xc0, 0x07, 0xda, 0x00, 0x19, 0x17, 0xe7, 0x38, 0xc9, 0x07, 0x00, 0x61, 0xc3, 0x58, 0x1c, 0x5d, 0x1d, 0x5e, 0x1a, 0x38, 0x1a, 0x38, 0x00, 0x60, 0x3a, 0x38, 0x02, 0x3f, 0x01, 0x00, 0x0a, 0x98, 0x29, 0x66, 0x03, 0x6e, 0xb5, 0x65, 0x02, 0x6d, 0x39, 0x67, 0xe7, 0x38, 0xd7, 0x07, 0xa5, 0x59, 0x3d, 0x5e, 0x1e, 0x9e, 0x12, 0x3f, 0x22, 0x00, 0x1b, 0x98, 0x29, 0x66, 0x03, 0x6e, 0xb5, 0x65, 0x02, 0x6d, 0x39, 0x67, 0xe7, 0x38, 0xe5, 0x07, 0xa5, 0x5f, 0xd7, 0x07, 0xfd, 0x5e, 0x12, 0x3f, 0x22, 0x00, 0x0e, 0x88, 0x29, 0x66, 0x03, 0x6e, 0x9e, 0x5d, 0x22, 0x00, 0x39, 0x67, 0xe7, 0x38, 0xf5, 0x07, 0x00, 0x61, 0xc3, 0x58, 0x1c, 0x5d, 0x1d, 0x5e, 0x1a, 0x38, 0x1a, 0x38, 0x00, 0x60, 0x3a, 0x38, 0xaf, 0x61, 0x1a, 0x69, 0x19, 0x01, 0x00, 0x60, 0x2f, 0x68, 0x93, 0x62, 0x57, 0x38, 0x0f, 0x59, 0x1b, 0xed, +0x00, 0x08, 0x1a, 0x38, 0x3a, 0x38, 0x1e, 0x58, 0x1e, 0x59, 0x1e, 0x5a, 0x1e, 0x5b, 0x1e, 0x5c, 0x1e, 0x5d, 0x1e, 0x5e, 0x1e, 0x5f, 0x08, 0x60, 0x1e, 0x58, 0xbc, 0xea, 0x3e, 0x58, 0x19, 0x10, 0xfb, 0x89, 0x00, 0x60, 0x1e, 0x58, 0x78, 0xa9, 0xbc, 0xea, 0x3e, 0x58, 0x19, 0x00, 0x9a, 0xc7, 0x18, 0x10, 0xf8, 0x89, 0x08, 0x60, 0x1e, 0x58, 0x0c, 0xf1, 0x3e, 0x58, 0x19, 0x10, 0xfb, 0x89, 0x00, 0x60, 0x1e, 0x58, 0x78, 0xa9, 0x0c, 0xf1, 0x3e, 0x58, 0x19, 0x00, 0xcc, 0xc7, 0x18, 0x10, 0xf8, 0x89, 0xe5, 0xa8, 0x3e, 0x5f, 0x3e, 0x5e, 0x3e, 0x5d, 0x3e, 0x5c, 0x3e, 0x5b, 0x3e, 0x5a, 0x3e, 0x59, 0x3e, 0x58, 0x3a, 0x38, 0x1e, 0x58, 0x1e, 0x59, 0x1e, 0x5a, 0x1e, 0x5b, 0x1e, 0x5c, 0x1e, 0x5d, 0x1e, 0x5e, 0x1e, 0x5f, 0xa2, 0x72, 0x07, 0x61, 0x22, 0x23, 0x03, 0x61, 0x23, 0x32, 0x0a, 0x8a, 0x1e, 0x49, +0x40, 0x08, 0x04, 0x61, 0x23, 0x32, 0x0e, 0x8a, 0x00, 0x61, 0x23, 0x32, 0x24, 0x8a, 0x02, 0x61, 0x23, 0x32, 0x2a, 0x8a, 0x2f, 0x9e, 0x9e, 0x5b, 0xe8, 0x00, 0xb5, 0x66, 0x02, 0x6e, 0xbe, 0x5e, 0x28, 0x1d, 0x28, 0x9e, 0x48, 0x63, 0x0e, 0x6b, 0x48, 0x66, 0x1d, 0x6e, 0x9e, 0x59, 0xbe, 0x00, 0x00, 0x64, 0x3c, 0x48, 0x0d, 0x8a, 0xfa, 0x06, 0x48, 0x67, 0x1d, 0x6f, 0xfa, 0x07, 0x19, 0x11, 0x27, 0x38, 0x64, 0x08, 0xe3, 0x59, 0x3b, 0x5e, 0x19, 0x07, 0x19, 0x06, 0x48, 0x66, 0x1d, 0x6e, 0xbe, 0x5e, 0x28, 0x1d, 0x0f, 0x9e, 0x16, 0xca, 0x48, 0x63, 0x0e, 0x6b, 0x2a, 0xc9, 0x7a, 0x66, 0x02, 0x6e, 0xbe, 0x5e, 0x28, 0x1d, 0x06, 0x9e, 0x30, 0x63, 0x0b, 0x6b, 0x29, 0x66, 0x03, 0x6e, 0xbe, 0x5e, 0x28, 0x1d, 0x60, 0x62, 0x11, 0x6a, 0xc0, 0x61, 0x03, 0x69, 0x24, 0x64, 0x16, 0x65, 0x9e, 0x58, 0xe3, 0x8e, +0x80, 0x08, 0x28, 0x1d, 0x05, 0x00, 0x19, 0x05, 0x00, 0x66, 0x00, 0x67, 0xbe, 0x5f, 0x29, 0x1d, 0x27, 0x38, 0xcb, 0x08, 0x19, 0x06, 0xbe, 0x48, 0x09, 0x8a, 0x1e, 0x58, 0x9e, 0x58, 0x29, 0x1d, 0x00, 0xac, 0x02, 0x92, 0x65, 0x58, 0x1d, 0x5a, 0x3e, 0x58, 0x36, 0x9e, 0x05, 0x5e, 0xdd, 0x5a, 0x00, 0x66, 0x19, 0x07, 0xfc, 0x48, 0x01, 0x8a, 0x2f, 0x9e, 0x13, 0xb8, 0x14, 0xb8, 0x15, 0xb8, 0x1e, 0x5e, 0x9e, 0x58, 0x28, 0x1d, 0x9e, 0x5c, 0xb8, 0x00, 0x87, 0x38, 0xa7, 0x08, 0x05, 0x5e, 0xdd, 0x5a, 0x3e, 0x5e, 0x95, 0xb8, 0x94, 0xb8, 0x93, 0xb8, 0x19, 0x12, 0x01, 0x76, 0xdd, 0x5a, 0x9e, 0x58, 0x28, 0x1d, 0xfa, 0x00, 0x05, 0x5e, 0xdd, 0x5a, 0x05, 0x5e, 0xdd, 0x5a, 0x05, 0x5e, 0xdd, 0x5a, 0x05, 0x5e, 0xdd, 0x5a, 0x05, 0x5e, 0xdd, 0x5a, 0x05, 0x5e, 0xdd, 0x5a, 0x05, 0x5e, 0xdd, 0x5a, 0xe8, 0x1d, +0xc0, 0x08, 0x9e, 0x5e, 0xe3, 0x19, 0xdd, 0x5a, 0xbb, 0x66, 0xdd, 0x5a, 0xbb, 0x66, 0xdd, 0x5a, 0xff, 0x66, 0xbe, 0x5e, 0x29, 0x1d, 0x1a, 0x38, 0x1a, 0x38, 0x3e, 0x5f, 0x3e, 0x5e, 0x3e, 0x5d, 0x3e, 0x5c, 0x3e, 0x5b, 0x3e, 0x5a, 0x3e, 0x59, 0x3e, 0x58, 0x3a, 0x38, 0x00, 0x67, 0x03, 0x6f, 0xbe, 0x5f, 0xdb, 0x00, 0x7f, 0x67, 0xbe, 0x5f, 0xde, 0x00, 0x00, 0x67, 0xbe, 0x5f, 0xe1, 0x00, 0x40, 0x67, 0xbe, 0x5f, 0xe0, 0x00, 0x3a, 0x38, 0xad, 0xac, 0x0d, 0x90, 0x04, 0x60, 0x69, 0x78, 0x66, 0x60, 0x6a, 0x78, 0x6b, 0x78, 0x6c, 0x78, 0x6d, 0x78, 0xb2, 0xa8, 0x3c, 0xab, 0xad, 0xaa, 0x00, 0x60, 0xbe, 0x58, 0xc2, 0x1d, 0x3a, 0x38, 0x02, 0x60, 0x72, 0x68, 0x05, 0xec, 0xff, 0xc8, 0x19, 0x38, 0xd9, 0x54, 0x02, 0xc9, 0xf2, 0x60, 0x72, 0x68, 0x05, 0xec, 0xa5, 0xaa, 0x3a, 0x38, 0x1e, 0x5c, 0x62, 0xbb, +0x00, 0x09, 0x04, 0xaa, 0x02, 0x9e, 0x1e, 0x5c, 0x04, 0xa8, 0x46, 0x62, 0x31, 0x6a, 0x40, 0xbd, 0xbd, 0x00, 0x02, 0x62, 0x40, 0xbd, 0xbe, 0x00, 0x00, 0x61, 0x10, 0x69, 0x07, 0x60, 0xc0, 0x68, 0x3f, 0x38, 0x0f, 0x59, 0x00, 0x61, 0x10, 0x69, 0x23, 0x5a, 0x32, 0xa8, 0x04, 0xac, 0x01, 0x92, 0x32, 0xaa, 0x5b, 0x59, 0x01, 0x62, 0x40, 0xbd, 0xbe, 0x00, 0x07, 0x60, 0xc0, 0x68, 0x3f, 0x38, 0x7a, 0x38, 0x02, 0x62, 0x40, 0xbd, 0xbe, 0x00, 0x00, 0x62, 0x40, 0xbd, 0xbd, 0x00, 0x40, 0xbd, 0xbe, 0x00, 0x3e, 0x5c, 0x3a, 0x38, 0x1e, 0x58, 0x1e, 0x59, 0x1e, 0x5a, 0x1e, 0x5b, 0x1e, 0x5c, 0x1e, 0x5d, 0x1e, 0x5e, 0x1e, 0x5f, 0xe6, 0xac, 0x05, 0x92, 0xe0, 0x61, 0x1a, 0x69, 0x00, 0x62, 0x1b, 0x6a, 0x04, 0x9e, 0x40, 0x61, 0x57, 0x69, 0x60, 0x62, 0x57, 0x6a, 0x90, 0x63, 0x5e, 0x6b, 0xb6, 0x64, 0x90, 0x39, +0x40, 0x09, 0x5e, 0x6c, 0x39, 0x65, 0x00, 0x66, 0x00, 0x67, 0xa7, 0x38, 0x0c, 0x0a, 0x15, 0x65, 0xfd, 0x48, 0x21, 0x9c, 0xe6, 0xac, 0x05, 0x92, 0xec, 0x61, 0x1a, 0x69, 0x0c, 0x62, 0x1b, 0x6a, 0x04, 0x9e, 0x4c, 0x61, 0x57, 0x69, 0x6c, 0x62, 0x57, 0x6a, 0x16, 0x65, 0xa0, 0x38, 0x7a, 0x02, 0x5e, 0x17, 0x07, 0x00, 0x5e, 0x07, 0x6b, 0x5d, 0xbe, 0x5d, 0x2e, 0x1d, 0x48, 0x66, 0xbe, 0x48, 0xac, 0x8a, 0x09, 0x66, 0xbe, 0x48, 0x1b, 0x9c, 0x13, 0x66, 0xbe, 0x48, 0x35, 0x9c, 0x1d, 0x66, 0xbe, 0x48, 0x15, 0x9c, 0x31, 0x9e, 0x7a, 0x60, 0x02, 0x68, 0x8b, 0x5d, 0xbe, 0x5d, 0x2e, 0x1d, 0x48, 0x66, 0xdd, 0x48, 0x77, 0x8a, 0x05, 0x66, 0xfe, 0x48, 0x4b, 0x9c, 0x0b, 0x66, 0xfe, 0x48, 0x5d, 0x9c, 0x11, 0x66, 0xfe, 0x48, 0x45, 0x9c, 0x15, 0x66, 0xfe, 0x48, 0x57, 0x9c, 0x9e, 0x5d, 0x2e, 0x1d, 0x11, 0x13, +0x80, 0x09, 0x0a, 0x66, 0xbe, 0x48, 0x01, 0x96, 0xa6, 0x15, 0x25, 0x01, 0x45, 0x02, 0xff, 0x65, 0xe6, 0xac, 0x02, 0x92, 0x35, 0x26, 0x04, 0x9e, 0x1e, 0x58, 0x29, 0x58, 0x05, 0x26, 0x3e, 0x58, 0xfe, 0x5e, 0xe6, 0xac, 0x02, 0x92, 0x55, 0x25, 0x04, 0x9e, 0x1e, 0x58, 0x49, 0x58, 0x05, 0x25, 0x3e, 0x58, 0xc5, 0x2e, 0xdb, 0x58, 0x71, 0x9e, 0xe6, 0xac, 0x05, 0x92, 0xec, 0x61, 0x1a, 0x69, 0x0c, 0x62, 0x1b, 0x6a, 0x04, 0x9e, 0x4c, 0x61, 0x57, 0x69, 0x6c, 0x62, 0x57, 0x6a, 0x9e, 0x5d, 0x2e, 0x1d, 0x0a, 0x66, 0xa6, 0x15, 0xbe, 0x48, 0x01, 0x96, 0xa6, 0x15, 0x25, 0x01, 0x45, 0x02, 0x00, 0x65, 0xff, 0x6d, 0xe6, 0xac, 0x03, 0x92, 0x35, 0x26, 0x55, 0x25, 0x06, 0x9e, 0x1e, 0x58, 0x29, 0x58, 0x05, 0x26, 0x49, 0x58, 0x05, 0x25, 0x3e, 0x58, 0xfe, 0x5d, 0xc5, 0x2e, 0xdb, 0x58, 0x4c, 0x9e, 0x04, 0xd9, +0xc0, 0x09, 0xff, 0x65, 0xe6, 0xac, 0x04, 0x92, 0x35, 0x26, 0xfe, 0x5e, 0x55, 0x25, 0x07, 0x9e, 0x1e, 0x58, 0x29, 0x58, 0x05, 0x26, 0xfe, 0x5e, 0x49, 0x58, 0x05, 0x25, 0x3e, 0x58, 0xc5, 0x2e, 0x9e, 0x5d, 0x2e, 0x1d, 0x05, 0x00, 0xdb, 0x58, 0x05, 0x10, 0x14, 0x9e, 0x00, 0x65, 0xff, 0x6d, 0xe6, 0xac, 0x03, 0x92, 0x35, 0x26, 0x55, 0x25, 0x06, 0x9e, 0x1e, 0x58, 0x29, 0x58, 0x05, 0x26, 0x49, 0x58, 0x05, 0x25, 0x3e, 0x58, 0xfe, 0x5d, 0xc5, 0x2e, 0x9e, 0x5d, 0x2e, 0x1d, 0x05, 0x00, 0xdb, 0x58, 0x05, 0x10, 0x05, 0x66, 0xdf, 0x48, 0x09, 0x8a, 0x0b, 0x66, 0xdf, 0x48, 0x12, 0x8a, 0x11, 0x66, 0xdf, 0x48, 0x0f, 0x8a, 0x19, 0x01, 0x19, 0x02, 0x17, 0x9e, 0xe6, 0xac, 0x05, 0x92, 0xe0, 0x61, 0x1a, 0x69, 0x00, 0x62, 0x1b, 0x6a, 0x04, 0x9e, 0x40, 0x61, 0x57, 0x69, 0x60, 0x62, 0x57, 0x6a, 0xdf, 0x21, +0x00, 0x0a, 0x0b, 0x9e, 0xe6, 0xac, 0x05, 0x92, 0xe6, 0x61, 0x1a, 0x69, 0x06, 0x62, 0x1b, 0x6a, 0x04, 0x9e, 0x46, 0x61, 0x57, 0x69, 0x66, 0x62, 0x57, 0x6a, 0x19, 0x07, 0x3e, 0x5f, 0x3e, 0x5e, 0x3e, 0x5d, 0x3e, 0x5c, 0x3e, 0x5b, 0x3e, 0x5a, 0x3e, 0x59, 0x3e, 0x58, 0x3a, 0x38, 0x90, 0x60, 0x5e, 0x68, 0x48, 0x64, 0x0e, 0x6c, 0x00, 0x65, 0x00, 0x66, 0x00, 0x67, 0xff, 0x63, 0xff, 0x6b, 0x6f, 0x3c, 0x5a, 0x0a, 0x09, 0x5a, 0x48, 0x65, 0x5d, 0x48, 0x34, 0x8a, 0x1e, 0x58, 0x19, 0x03, 0x0c, 0x65, 0x65, 0x40, 0xe6, 0xac, 0x03, 0x92, 0x00, 0x61, 0x05, 0x69, 0x02, 0x9e, 0x80, 0x61, 0x57, 0x69, 0x20, 0x01, 0xb6, 0x62, 0x5e, 0x6a, 0x13, 0xb8, 0x14, 0xb8, 0x15, 0xb8, 0x6f, 0x39, 0x52, 0x0a, 0xe6, 0xac, 0x02, 0x92, 0x23, 0x5e, 0x01, 0x9e, 0x29, 0x5e, 0xc4, 0x3f, 0x00, 0xff, 0xfe, 0x5f, 0x3c, 0x29, +0x40, 0x0a, 0xc4, 0x3e, 0xff, 0x00, 0x49, 0x5d, 0x48, 0x60, 0x1d, 0x48, 0x03, 0x8a, 0x85, 0x04, 0xdb, 0x5c, 0x85, 0x14, 0x19, 0x02, 0x49, 0x5d, 0x48, 0x60, 0x1d, 0x48, 0x03, 0x8a, 0x85, 0x04, 0xfb, 0x5c, 0x85, 0x14, 0x19, 0x02, 0x19, 0x01, 0x95, 0xb8, 0x94, 0xb8, 0x93, 0xb8, 0x16, 0x65, 0x85, 0x04, 0x3e, 0x58, 0x1a, 0x38, 0x19, 0x00, 0x3a, 0x38, 0x9e, 0x59, 0xf1, 0x1e, 0x1c, 0x11, 0x1e, 0x98, 0x9e, 0x59, 0xf2, 0x1e, 0x22, 0x39, 0x88, 0x00, 0x11, 0x8a, 0x9e, 0x59, 0x58, 0x1a, 0x1a, 0x11, 0x01, 0x94, 0x14, 0x9e, 0x88, 0x61, 0xbe, 0x59, 0xf2, 0x1e, 0x8d, 0x61, 0x9e, 0x58, 0xef, 0x1e, 0x1b, 0x59, 0x97, 0x61, 0x9e, 0x58, 0xee, 0x1e, 0x1b, 0x59, 0x18, 0x9e, 0x9e, 0x59, 0x58, 0x1a, 0x19, 0x11, 0xf0, 0x95, 0x9e, 0x59, 0xf1, 0x1e, 0x1c, 0x11, 0x00, 0x98, 0x00, 0x61, 0xbe, 0x59, 0x00, 0xa0, +0x80, 0x0a, 0xf2, 0x1e, 0x9e, 0x59, 0xf0, 0x1e, 0x22, 0x39, 0x66, 0x00, 0x08, 0x88, 0x8d, 0x61, 0x23, 0x58, 0xbe, 0x58, 0xef, 0x1e, 0x97, 0x61, 0x23, 0x58, 0xbe, 0x58, 0xee, 0x1e, 0x3a, 0x38, 0x9e, 0x59, 0xf3, 0x1e, 0x1c, 0x11, 0x1e, 0x98, 0x9e, 0x59, 0xf7, 0x1e, 0x22, 0x39, 0x88, 0x00, 0x11, 0x8a, 0x9e, 0x59, 0x58, 0x1a, 0x1b, 0x11, 0x01, 0x94, 0x14, 0x9e, 0x88, 0x61, 0xbe, 0x59, 0xf7, 0x1e, 0x8e, 0x61, 0x9e, 0x58, 0xf5, 0x1e, 0x1b, 0x59, 0x98, 0x61, 0x9e, 0x58, 0xf6, 0x1e, 0x1b, 0x59, 0x18, 0x9e, 0x9e, 0x59, 0x58, 0x1a, 0x1a, 0x11, 0xf0, 0x95, 0x9e, 0x59, 0xf3, 0x1e, 0x1c, 0x11, 0x00, 0x98, 0x00, 0x61, 0xbe, 0x59, 0xf7, 0x1e, 0x9e, 0x59, 0xf4, 0x1e, 0x22, 0x39, 0x66, 0x00, 0x08, 0x88, 0x8e, 0x61, 0x23, 0x58, 0xbe, 0x58, 0xf5, 0x1e, 0x98, 0x61, 0x23, 0x58, 0xbe, 0x58, 0x07, 0x85, +0xc0, 0x0a, 0xf6, 0x1e, 0x3a, 0x38, 0x1e, 0x58, 0x1e, 0x59, 0x1e, 0x5a, 0x1e, 0x5b, 0x1e, 0x5c, 0x1e, 0x5d, 0x9e, 0x58, 0xea, 0x04, 0x18, 0x10, 0x0a, 0x88, 0x00, 0x60, 0x01, 0x61, 0x1f, 0x69, 0x06, 0x62, 0x1f, 0x6a, 0x8f, 0x38, 0xd5, 0x0a, 0x1d, 0x59, 0x1d, 0x5a, 0x1a, 0x38, 0x9e, 0x58, 0x00, 0x1f, 0x19, 0x10, 0x23, 0x8a, 0x00, 0x64, 0x7f, 0x6c, 0x8d, 0x61, 0x01, 0x62, 0x1f, 0x6a, 0x8f, 0x38, 0xeb, 0x0a, 0x23, 0x58, 0x04, 0x15, 0x06, 0x8a, 0x43, 0x5b, 0x18, 0x13, 0x01, 0x88, 0x1b, 0x5a, 0x43, 0x58, 0x1b, 0x59, 0x19, 0x01, 0x19, 0x02, 0x30, 0x64, 0x97, 0x61, 0x06, 0x62, 0x1f, 0x6a, 0x8f, 0x38, 0xfc, 0x0a, 0x23, 0x58, 0x04, 0x15, 0x06, 0x8a, 0x43, 0x5b, 0x18, 0x13, 0x01, 0x88, 0x1b, 0x5a, 0x43, 0x58, 0x1b, 0x59, 0x19, 0x01, 0x19, 0x02, 0x3e, 0x5d, 0x3e, 0x5c, 0x3e, 0x5b, 0x64, 0xd2, +0x00, 0x0b, 0x3e, 0x5a, 0x3e, 0x59, 0x3e, 0x58, 0x3a, 0x38, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x0e, 0x00, 0x0c, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x06, 0x00, 0x06, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x02, 0x00, 0xff, 0x01, 0xff, 0x00, 0x7f, 0x00, 0x3f, 0x00, 0x1f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x96, 0x54, +0x40, 0x0b, 0x05, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x9e, 0x58, 0xe7, 0x00, 0x19, 0x10, 0x01, 0x98, 0xfd, 0x38, 0x6c, 0xcb, 0x9e, 0x58, 0xe8, 0x00, 0x9e, 0x59, 0xe9, 0x00, 0x19, 0x48, 0x01, 0x88, 0x42, 0xa9, 0x01, 0x60, 0xbe, 0x58, 0xea, 0x00, 0xbe, 0x58, 0xe7, 0x00, 0xed, 0x9f, 0x9e, 0x58, 0xe7, 0x00, 0x19, 0x10, 0x01, 0x98, 0xfd, 0x38, 0x99, 0xcc, 0x01, 0x60, 0xbe, 0x58, 0xe7, 0x00, 0xf6, 0x9f, 0x1a, 0x38, 0x1a, 0x38, 0x9e, 0x58, 0x36, 0x1d, 0x1b, 0x10, 0x98, 0x3a, 0x74, 0x0c, 0xfb, 0xcd, 0x02, 0x60, 0xbe, 0x58, 0xdd, 0x1e, 0x7d, 0xe4, 0xc7, 0xdd, 0x8a, 0xde, 0xa1, 0xdd, 0xac, 0xe5, 0xa1, 0xcc, 0xd4, 0xdb, 0x4a, 0xee, 0xb7, 0xcc, 0x6e, 0xfd, +0x80, 0x0b, 0xd4, 0xcc, 0x48, 0x66, 0x0e, 0x6e, 0xa4, 0xed, 0xf8, 0xcc, 0xd2, 0xde, 0x7f, 0xe2, 0x80, 0x60, 0xbe, 0x58, 0xfd, 0x1e, 0x9e, 0x58, 0xf1, 0x04, 0x9e, 0x59, 0xf2, 0x04, 0x01, 0x00, 0x1a, 0x10, 0x13, 0x88, 0x9e, 0x58, 0x45, 0x04, 0x02, 0x38, 0x00, 0x01, 0x08, 0x98, 0x9e, 0x58, 0x4d, 0x04, 0x9e, 0x59, 0x4f, 0x04, 0x01, 0x00, 0x02, 0x39, 0x00, 0x02, 0x8a, 0x80, 0x88, 0x60, 0xbe, 0x58, 0xfd, 0x1e, 0xa8, 0xe8, 0x2e, 0xe9, 0x84, 0x9e, 0x1a, 0x38, 0x9e, 0x58, 0xe9, 0x1e, 0x18, 0x10, 0x01, 0x8a, 0x7e, 0x9e, 0x00, 0x60, 0xbe, 0x58, 0x20, 0x1d, 0x1b, 0x60, 0xbe, 0x58, 0x44, 0x1a, 0x9e, 0x58, 0xcd, 0x04, 0xfc, 0x10, 0x1b, 0x98, 0x06, 0x70, 0x50, 0xac, 0x18, 0x92, 0x9e, 0x58, 0x45, 0x04, 0x02, 0x38, 0x00, 0x01, 0x0a, 0x98, 0x9e, 0x58, 0x4d, 0x04, 0x02, 0x38, 0x40, 0x01, 0x4d, 0x4c, +0xc0, 0x0b, 0x0e, 0x80, 0x9e, 0x58, 0x4f, 0x04, 0x02, 0x38, 0x40, 0x01, 0x09, 0x80, 0xeb, 0xe5, 0x9e, 0x58, 0x20, 0x1d, 0x18, 0x10, 0x04, 0x8a, 0x05, 0x60, 0xbe, 0x58, 0x44, 0x1a, 0x59, 0x9e, 0x1a, 0x38, 0x06, 0x70, 0x08, 0xac, 0x38, 0x92, 0x00, 0xac, 0x36, 0x92, 0x50, 0xac, 0x34, 0x92, 0x00, 0x60, 0xbe, 0x58, 0x43, 0x04, 0x9e, 0x58, 0xdb, 0x1e, 0x9e, 0x59, 0xdc, 0x1e, 0x01, 0x00, 0x1a, 0x10, 0x2a, 0x8a, 0x9e, 0x58, 0xf1, 0x04, 0x1a, 0x10, 0x01, 0x8a, 0x04, 0x9e, 0x9e, 0x58, 0xf2, 0x04, 0x1a, 0x10, 0x21, 0x8a, 0x9e, 0x58, 0xf1, 0x04, 0x9e, 0x59, 0xf2, 0x04, 0x01, 0x00, 0x1b, 0x10, 0x14, 0x9a, 0x9e, 0x58, 0x45, 0x04, 0x02, 0x38, 0x60, 0x00, 0x15, 0x80, 0x9e, 0x58, 0xf1, 0x04, 0x9e, 0x59, 0xf2, 0x04, 0x01, 0x00, 0x1b, 0x10, 0x08, 0x88, 0x9e, 0x58, 0xf1, 0x1e, 0x9e, 0x59, 0x10, 0xe2, +0x00, 0x0c, 0xf3, 0x1e, 0x01, 0x00, 0x08, 0x58, 0x1d, 0x10, 0x06, 0x98, 0x1f, 0xdf, 0x9e, 0x58, 0x43, 0x04, 0x01, 0x61, 0x19, 0x48, 0x1d, 0x8a, 0x9e, 0x58, 0x8a, 0x04, 0x1f, 0x10, 0x07, 0x80, 0x9e, 0x58, 0x8b, 0x04, 0x1f, 0x10, 0x03, 0x80, 0x05, 0x60, 0xbe, 0x58, 0x44, 0x1a, 0x9e, 0x58, 0x36, 0x1d, 0x1a, 0x10, 0x08, 0x8a, 0x9e, 0x58, 0x36, 0x1d, 0x1c, 0x10, 0x03, 0x8a, 0x98, 0xe2, 0x98, 0xe2, 0x01, 0x9e, 0x98, 0xe2, 0x9e, 0x58, 0x45, 0x04, 0x02, 0x38, 0x80, 0x01, 0x01, 0x80, 0x69, 0xe2, 0xcb, 0xce, 0x1f, 0xcd, 0x9e, 0xce, 0xb0, 0xce, 0x2a, 0xcf, 0x72, 0xdc, 0x17, 0xd2, 0x9e, 0x58, 0x43, 0x04, 0x01, 0x61, 0x19, 0x48, 0x0a, 0x8a, 0x9e, 0x58, 0xb1, 0x04, 0x19, 0x10, 0x06, 0x8a, 0x9e, 0x58, 0xb8, 0x04, 0x18, 0x10, 0x02, 0x88, 0x2c, 0xe4, 0xc3, 0xe1, 0xc1, 0xf8, 0x8a, 0xf8, 0x7f, 0x91, +0x40, 0x0c, 0x56, 0xd0, 0x19, 0x38, 0x92, 0x4a, 0x9e, 0x58, 0x43, 0x04, 0x01, 0x61, 0x19, 0x48, 0x0c, 0x8a, 0x9e, 0x58, 0x20, 0x1d, 0x18, 0x10, 0x08, 0x88, 0x19, 0x38, 0xc6, 0x4a, 0x19, 0x38, 0xc5, 0x48, 0x19, 0x38, 0x94, 0x49, 0x19, 0x38, 0xd6, 0x4a, 0x03, 0xda, 0x4d, 0xda, 0xf6, 0xed, 0x6b, 0xd3, 0xe1, 0xd3, 0xec, 0xd6, 0x8a, 0xda, 0x9e, 0x58, 0x58, 0x1a, 0x19, 0x10, 0x12, 0x88, 0x9e, 0x58, 0x8a, 0x04, 0x9e, 0x59, 0x8b, 0x04, 0x01, 0x00, 0x02, 0x39, 0x05, 0x00, 0x0a, 0x98, 0xaa, 0x61, 0x15, 0x69, 0x23, 0x58, 0x02, 0x39, 0x0d, 0x00, 0x04, 0x80, 0xaa, 0x61, 0x15, 0x69, 0x0d, 0x60, 0x1b, 0x59, 0xbf, 0xdc, 0x7a, 0xdd, 0x3a, 0x38, 0xfb, 0xcd, 0xa1, 0xcc, 0xd4, 0xdb, 0xc8, 0xcc, 0xd4, 0xcc, 0xf8, 0xcc, 0x7f, 0xe2, 0xcb, 0xce, 0x1f, 0xcd, 0x9e, 0xce, 0xb0, 0xce, 0x2a, 0xcf, 0x3f, 0xb2, +0x80, 0x0c, 0x17, 0xd2, 0x56, 0xd0, 0x03, 0xda, 0x4d, 0xda, 0x6b, 0xd3, 0xe1, 0xd3, 0xec, 0xd6, 0x8a, 0xda, 0xbf, 0xdc, 0x7a, 0xdd, 0x3a, 0x38, 0xfb, 0xcd, 0xa1, 0xcc, 0xd4, 0xcc, 0xf8, 0xcc, 0x7a, 0xce, 0xcb, 0xce, 0x1f, 0xcd, 0x9e, 0xce, 0xb0, 0xce, 0x2a, 0xcf, 0x17, 0xd2, 0x56, 0xd0, 0x03, 0xda, 0x3a, 0x38, 0x4d, 0xda, 0x6b, 0xd3, 0xe1, 0xd3, 0xec, 0xd6, 0x8a, 0xda, 0xbf, 0xdc, 0x7a, 0xdd, 0x3a, 0x38, 0x30, 0x67, 0x0b, 0x6f, 0x9e, 0x5e, 0xe9, 0x00, 0x48, 0x65, 0x0e, 0x6d, 0x9e, 0x5c, 0xda, 0x00, 0x19, 0x14, 0x87, 0x38, 0xb5, 0x0c, 0xc5, 0x5c, 0xf4, 0x14, 0x7c, 0xac, 0x04, 0x92, 0x00, 0x61, 0x02, 0x62, 0x82, 0x40, 0x01, 0x5c, 0x9d, 0x5d, 0x19, 0x07, 0x3a, 0x38, 0x30, 0x60, 0x1c, 0x78, 0x06, 0x70, 0x50, 0xac, 0x08, 0x92, 0x08, 0xac, 0x04, 0x92, 0x00, 0xac, 0x02, 0x92, 0x2d, 0x02, +0xc0, 0x0c, 0x10, 0x60, 0x03, 0x9e, 0x30, 0x60, 0x01, 0x9e, 0x68, 0x60, 0x25, 0x78, 0x26, 0x78, 0x3a, 0x38, 0x30, 0x60, 0x1c, 0x78, 0x30, 0x60, 0x25, 0x78, 0x26, 0x78, 0x3a, 0x38, 0x40, 0x60, 0x1c, 0x78, 0x30, 0x60, 0x25, 0x78, 0x26, 0x78, 0x3a, 0x38, 0x48, 0x67, 0x0e, 0x6f, 0x9e, 0x5d, 0xfd, 0x1b, 0x19, 0x15, 0x9e, 0x5e, 0xfe, 0x1b, 0xff, 0x64, 0x7f, 0x6c, 0xa7, 0x38, 0xe2, 0x0c, 0x9f, 0x49, 0x01, 0x9a, 0xe3, 0x5c, 0x19, 0x07, 0x18, 0x14, 0x01, 0x94, 0x00, 0x64, 0x90, 0x3c, 0x26, 0x00, 0x90, 0x3c, 0x05, 0x1c, 0xf2, 0x3f, 0xfd, 0x1b, 0x00, 0x62, 0xa7, 0x38, 0xf4, 0x0c, 0xf2, 0x13, 0x03, 0x96, 0xf4, 0x13, 0x01, 0x94, 0x00, 0x63, 0x7d, 0x5f, 0x19, 0x16, 0xe4, 0x89, 0x3a, 0x38, 0x48, 0x67, 0x0e, 0x6f, 0x9e, 0x5d, 0xfd, 0x1b, 0x9e, 0x5e, 0xfe, 0x1b, 0x19, 0x16, 0xff, 0x64, 0x7d, 0x69, +0x00, 0x0d, 0x7f, 0x6c, 0xc7, 0x38, 0x08, 0x0d, 0x9f, 0x49, 0x01, 0x9a, 0xe3, 0x5c, 0xf0, 0x3f, 0xfd, 0x1b, 0x1a, 0x38, 0x18, 0x14, 0x01, 0x94, 0x00, 0x64, 0x90, 0x3c, 0x25, 0x00, 0x90, 0x3c, 0x05, 0x1c, 0x00, 0x62, 0xc7, 0x38, 0x1a, 0x0d, 0xf2, 0x3f, 0xfd, 0x1b, 0xf2, 0x13, 0x03, 0x96, 0xf4, 0x13, 0x01, 0x94, 0x00, 0x63, 0x7b, 0x5f, 0x19, 0x07, 0x19, 0x15, 0xe1, 0x89, 0x3a, 0x38, 0x05, 0x71, 0x49, 0xaa, 0x05, 0x79, 0x00, 0x66, 0x60, 0x65, 0x11, 0x6d, 0x48, 0x64, 0x0e, 0x6c, 0x9e, 0x5b, 0xfd, 0x1b, 0x1a, 0x05, 0xa3, 0x05, 0x00, 0x67, 0x9e, 0x58, 0xfd, 0x1b, 0x19, 0x10, 0x07, 0x38, 0xbb, 0x0d, 0x1d, 0x70, 0x1c, 0x49, 0x85, 0x94, 0x05, 0x71, 0x49, 0xa8, 0x05, 0x79, 0x00, 0x60, 0xa2, 0x3b, 0x01, 0x00, 0x63, 0x59, 0x24, 0x39, 0xff, 0x00, 0x19, 0x48, 0x29, 0x88, 0xb2, 0x3b, 0xd3, 0x97, +0x40, 0x0d, 0xfd, 0x1b, 0x19, 0x13, 0x63, 0x59, 0x24, 0x39, 0xff, 0x00, 0x19, 0x48, 0x21, 0x88, 0xa3, 0x59, 0x24, 0x39, 0xff, 0x00, 0x19, 0x48, 0x6d, 0x88, 0x9e, 0x5b, 0xf0, 0x04, 0x4b, 0x62, 0x1a, 0x6a, 0x7a, 0x49, 0x06, 0x98, 0xa3, 0x59, 0x24, 0x39, 0x00, 0x80, 0x23, 0x29, 0x3b, 0x5d, 0x08, 0x9e, 0x43, 0x5b, 0x19, 0x03, 0x7b, 0x5a, 0xa3, 0x59, 0x24, 0x39, 0x00, 0x80, 0x23, 0x29, 0x3b, 0x5d, 0x19, 0x13, 0x60, 0x3a, 0xaa, 0x15, 0x43, 0x59, 0x19, 0x01, 0x3b, 0x5a, 0xdf, 0xce, 0x51, 0x9e, 0xa3, 0x59, 0x24, 0x39, 0xff, 0x00, 0x19, 0x48, 0x4c, 0x88, 0xa2, 0x3b, 0x01, 0x00, 0xb2, 0x3a, 0xfd, 0x1b, 0x19, 0x12, 0x63, 0x59, 0x24, 0x39, 0xff, 0x00, 0x19, 0x48, 0x1f, 0x8a, 0x43, 0x59, 0x24, 0x39, 0xff, 0x00, 0x19, 0x48, 0x1a, 0x8a, 0x63, 0x59, 0x24, 0x39, 0xff, 0x00, 0x43, 0x58, 0x9e, 0xe0, +0x80, 0x0d, 0x04, 0x38, 0xff, 0x00, 0x38, 0x48, 0x12, 0x8a, 0x20, 0x39, 0xbd, 0x15, 0x43, 0x58, 0x00, 0x38, 0xbd, 0x15, 0x03, 0x58, 0x19, 0x49, 0x01, 0x94, 0x1b, 0x59, 0x00, 0x39, 0xbd, 0x15, 0x63, 0x58, 0x00, 0x38, 0xbd, 0x15, 0x03, 0x58, 0x19, 0x49, 0x01, 0x94, 0x1b, 0x59, 0x00, 0x60, 0x43, 0x59, 0x24, 0x39, 0xff, 0x00, 0x19, 0x48, 0x09, 0x8a, 0x43, 0x5b, 0x64, 0x3b, 0xff, 0x00, 0xa3, 0x59, 0x24, 0x39, 0x00, 0x80, 0x23, 0x29, 0x3b, 0x5d, 0x0d, 0x9e, 0x63, 0x59, 0x24, 0x39, 0xff, 0x00, 0x19, 0x48, 0x08, 0x8a, 0x63, 0x5b, 0x64, 0x3b, 0xff, 0x00, 0xa3, 0x59, 0x24, 0x39, 0x00, 0x80, 0x23, 0x29, 0x3b, 0x5d, 0x19, 0x13, 0x60, 0x3a, 0xaa, 0x15, 0x43, 0x59, 0x19, 0x01, 0x3b, 0x5a, 0xec, 0xce, 0x19, 0x04, 0x19, 0x05, 0x19, 0x07, 0x19, 0x05, 0x19, 0x06, 0x9e, 0x5a, 0xfe, 0x1b, 0xa8, 0xc2, +0xc0, 0x0d, 0x5e, 0x48, 0x69, 0x99, 0x3a, 0x38, 0xe8, 0x67, 0x03, 0x6f, 0xbe, 0x5f, 0x54, 0x1a, 0x9e, 0x5c, 0x58, 0x1a, 0x82, 0x39, 0x00, 0x00, 0x20, 0x8a, 0x00, 0x67, 0xbe, 0x5f, 0x54, 0x1a, 0x9e, 0x5a, 0xfd, 0x1b, 0x72, 0x65, 0x19, 0x6d, 0x86, 0x66, 0x19, 0x6e, 0x19, 0x14, 0xff, 0x61, 0x7f, 0x69, 0x00, 0x63, 0x87, 0x38, 0xe5, 0x0d, 0xa5, 0x58, 0x46, 0x4a, 0x00, 0x38, 0x48, 0x0e, 0x38, 0x49, 0x01, 0x9a, 0x03, 0x59, 0x78, 0x49, 0x01, 0x94, 0x03, 0x5b, 0x17, 0x07, 0x19, 0x04, 0xe1, 0x58, 0x00, 0x61, 0x1c, 0x5c, 0xbe, 0x58, 0x54, 0x1a, 0x3a, 0x38, 0x9e, 0x58, 0xe3, 0x19, 0x00, 0x67, 0x27, 0x76, 0x19, 0x16, 0xc7, 0x38, 0xf7, 0x0d, 0x04, 0x39, 0x01, 0x00, 0xe1, 0x07, 0x08, 0x58, 0xbe, 0x5f, 0xea, 0x04, 0x3a, 0x38, 0x9e, 0x58, 0x00, 0x1f, 0x9e, 0x5f, 0x20, 0x1d, 0x18, 0x17, 0x57, 0x53, +0x00, 0x0e, 0x01, 0x8a, 0x1b, 0x00, 0xbe, 0x58, 0x11, 0x00, 0x7a, 0x67, 0x02, 0x6f, 0x00, 0x66, 0x9e, 0x58, 0x5d, 0x1a, 0x19, 0x10, 0x07, 0x38, 0x0e, 0x0e, 0xdd, 0x5f, 0x1a, 0x38, 0x1a, 0x38, 0xed, 0xcd, 0xc3, 0xcd, 0x9e, 0x5f, 0xea, 0x04, 0x0a, 0x67, 0xbe, 0x5f, 0xe4, 0x19, 0x9e, 0x58, 0x54, 0x1a, 0x9e, 0x59, 0x48, 0x1a, 0x24, 0x3a, 0x00, 0xe0, 0x07, 0x8a, 0x22, 0x39, 0x00, 0x20, 0xbe, 0x59, 0x48, 0x1a, 0x24, 0x38, 0xff, 0x1f, 0x17, 0x9e, 0x18, 0x10, 0x0b, 0x8a, 0x9e, 0x59, 0x48, 0x1a, 0x18, 0x11, 0x05, 0x8a, 0x26, 0x5a, 0x41, 0x02, 0x02, 0x00, 0x08, 0x58, 0x08, 0x58, 0xbe, 0x58, 0x48, 0x1a, 0x9e, 0x59, 0xe2, 0x19, 0x3f, 0x48, 0x07, 0x8a, 0x9e, 0x58, 0x48, 0x1a, 0x05, 0x39, 0x00, 0x80, 0xbe, 0x59, 0x48, 0x1a, 0x06, 0x58, 0x24, 0x3a, 0x00, 0xe0, 0x00, 0x8a, 0x30, 0x62, 0xa0, 0x62, +0x40, 0x0e, 0x0b, 0x6a, 0x50, 0x3a, 0x4b, 0x1a, 0x49, 0x5a, 0x02, 0x40, 0x00, 0x61, 0x02, 0x69, 0x01, 0x40, 0xbe, 0x59, 0x05, 0x1c, 0x9e, 0x59, 0x4b, 0x1a, 0xbe, 0x59, 0x03, 0x1c, 0x00, 0x9e, 0x00, 0x60, 0xbe, 0x58, 0x58, 0x1a, 0x60, 0x66, 0x11, 0x6e, 0x00, 0x61, 0x80, 0x69, 0x9e, 0x5f, 0xff, 0x1b, 0x19, 0x17, 0xe7, 0x38, 0x5c, 0x0e, 0xd1, 0x22, 0x5d, 0x5e, 0xaa, 0x63, 0x15, 0x6b, 0xbe, 0x62, 0x15, 0x6a, 0x00, 0x61, 0x9e, 0x5f, 0xf0, 0x04, 0x19, 0x17, 0xe7, 0x38, 0x69, 0x0e, 0x1d, 0x5b, 0x19, 0x01, 0x3d, 0x5a, 0xbe, 0x58, 0x4b, 0x1a, 0xc8, 0x63, 0x1b, 0x6b, 0x00, 0x60, 0x13, 0x67, 0xe7, 0x38, 0x74, 0x0e, 0x1d, 0x5b, 0x1a, 0x38, 0x1a, 0x38, 0x9e, 0x58, 0x06, 0x1c, 0xbe, 0x58, 0x1c, 0x00, 0x3a, 0x38, 0x60, 0x67, 0x11, 0x6f, 0x48, 0x66, 0x0e, 0x6e, 0x00, 0x64, 0x01, 0x63, 0xf6, 0x44, +0x80, 0x0e, 0x24, 0x72, 0x9e, 0x58, 0x05, 0x1c, 0x08, 0x58, 0x40, 0x02, 0x00, 0x61, 0x80, 0x69, 0x20, 0x58, 0x9e, 0x5d, 0xda, 0x00, 0x19, 0x15, 0xa7, 0x38, 0x9c, 0x0e, 0xf1, 0x25, 0x08, 0x8a, 0xd3, 0x15, 0x0a, 0x98, 0xf0, 0x25, 0xbb, 0x5f, 0x9e, 0x49, 0x06, 0x98, 0x9b, 0x5e, 0x04, 0x9e, 0xd2, 0x15, 0xfa, 0x9b, 0xf1, 0x2d, 0xbb, 0x5f, 0x19, 0x07, 0x19, 0x06, 0x3a, 0x38, 0xbe, 0x63, 0x15, 0x6b, 0x00, 0x65, 0x9e, 0x5c, 0x4b, 0x1a, 0x18, 0x14, 0x0a, 0x8a, 0x19, 0x14, 0x87, 0x38, 0xae, 0x0e, 0x65, 0x04, 0x83, 0x5e, 0x19, 0x16, 0x66, 0x07, 0xe3, 0x5e, 0xdb, 0x5c, 0x19, 0x05, 0x3a, 0x38, 0x9e, 0x5e, 0x4b, 0x1a, 0x0f, 0x9a, 0x0e, 0x8a, 0x19, 0x16, 0xc7, 0x38, 0xc1, 0x0e, 0xc0, 0x3d, 0xbe, 0x15, 0xa3, 0x5f, 0x19, 0x17, 0xdf, 0x48, 0x04, 0x8a, 0xaa, 0x62, 0x15, 0x6a, 0xc3, 0xce, 0x95, 0xc4, +0xc0, 0x0e, 0x01, 0xcf, 0x19, 0x16, 0x3a, 0x38, 0xe2, 0x04, 0x83, 0x58, 0xc2, 0x02, 0x50, 0x00, 0x1b, 0x5c, 0xde, 0x5a, 0x00, 0x00, 0x3a, 0x38, 0x00, 0x60, 0xff, 0x61, 0xde, 0x66, 0x15, 0x6e, 0xf2, 0x65, 0x15, 0x6d, 0x06, 0x64, 0x16, 0x6c, 0x1a, 0x63, 0x16, 0x6b, 0x9e, 0x5f, 0xf0, 0x04, 0x19, 0x17, 0xe7, 0x38, 0xdd, 0x0e, 0x3d, 0x5e, 0x1d, 0x5d, 0x1d, 0x5c, 0x3d, 0x5b, 0x3a, 0x38, 0x60, 0x38, 0xde, 0x15, 0xfb, 0x58, 0x60, 0x38, 0xf2, 0x15, 0xfb, 0x58, 0x60, 0x38, 0x06, 0x16, 0xdb, 0x58, 0x60, 0x38, 0x1a, 0x16, 0xdb, 0x58, 0x3a, 0x38, 0x60, 0x38, 0xde, 0x15, 0xf8, 0x49, 0x01, 0x94, 0xfb, 0x58, 0x60, 0x38, 0xf2, 0x15, 0xf8, 0x49, 0x01, 0x9a, 0xfb, 0x58, 0x60, 0x38, 0x06, 0x16, 0xd8, 0x49, 0x01, 0x9a, 0xdb, 0x58, 0x60, 0x38, 0x1a, 0x16, 0xd8, 0x49, 0x01, 0x94, 0xdb, 0x58, 0x72, 0xe8, +0x00, 0x0f, 0x3a, 0x38, 0xc0, 0x38, 0xde, 0x15, 0x03, 0x59, 0xe0, 0x3a, 0xde, 0x15, 0x3a, 0x49, 0x01, 0x94, 0x3b, 0x5a, 0xde, 0x58, 0xff, 0x00, 0xc0, 0x38, 0xf2, 0x15, 0x03, 0x59, 0xe0, 0x3a, 0xf2, 0x15, 0x3a, 0x49, 0x01, 0x9a, 0x3b, 0x5a, 0xde, 0x58, 0x00, 0x00, 0xc0, 0x38, 0x06, 0x16, 0x03, 0x59, 0xe0, 0x3a, 0x06, 0x16, 0x3a, 0x49, 0x01, 0x9a, 0x3b, 0x5a, 0xde, 0x58, 0x00, 0x00, 0xc0, 0x38, 0x1a, 0x16, 0x03, 0x59, 0xe0, 0x3a, 0x1a, 0x16, 0x3a, 0x49, 0x01, 0x94, 0x3b, 0x5a, 0xde, 0x58, 0xff, 0x00, 0x3a, 0x38, 0x00, 0x61, 0xbe, 0x59, 0x58, 0x1a, 0x00, 0x67, 0x23, 0x70, 0xe0, 0x39, 0xaa, 0x15, 0x19, 0x49, 0x32, 0x98, 0x02, 0xdc, 0x9e, 0x58, 0xe9, 0x1e, 0x18, 0x10, 0x0e, 0x8a, 0x06, 0x70, 0x08, 0xac, 0x08, 0x92, 0x00, 0xac, 0x06, 0x92, 0x50, 0xac, 0x04, 0x92, 0x20, 0x60, 0x7b, 0x06, +0x40, 0x0f, 0x01, 0x68, 0x1c, 0x78, 0x03, 0x9e, 0x00, 0x60, 0x02, 0x68, 0x1c, 0x78, 0x9e, 0x58, 0x20, 0x1d, 0x02, 0x38, 0x80, 0x01, 0x03, 0x88, 0x40, 0x60, 0xbe, 0x58, 0x1c, 0x00, 0xe0, 0x3b, 0x1a, 0x16, 0x63, 0x5e, 0xe0, 0x3b, 0xde, 0x15, 0x63, 0x5d, 0x14, 0x60, 0x58, 0x62, 0x1a, 0x6a, 0x1a, 0x49, 0x12, 0x9a, 0x6d, 0xcf, 0x19, 0x05, 0xe0, 0x3b, 0xf2, 0x15, 0xbb, 0x49, 0xf5, 0x9b, 0x19, 0x06, 0xe0, 0x38, 0x06, 0x16, 0xd8, 0x49, 0xed, 0x9b, 0x66, 0xdc, 0x19, 0x07, 0x9e, 0x58, 0x4b, 0x1a, 0xf8, 0x48, 0xc4, 0x97, 0x01, 0x9e, 0x66, 0xdc, 0x3a, 0x38, 0x9e, 0x5a, 0xfd, 0x1b, 0xa0, 0x38, 0x48, 0x0e, 0x46, 0x48, 0x03, 0x5c, 0xe0, 0x3b, 0xc8, 0x1b, 0x63, 0x58, 0x04, 0x00, 0x1b, 0x5b, 0x1c, 0x73, 0x9b, 0x48, 0x31, 0x96, 0x1e, 0x5f, 0x01, 0x67, 0xe0, 0x39, 0x0c, 0x10, 0x29, 0x59, 0xae, 0x85, +0x80, 0x0f, 0x25, 0x03, 0x62, 0x39, 0x00, 0x00, 0x14, 0x96, 0x72, 0x39, 0xfd, 0x1b, 0x11, 0x94, 0xe0, 0x39, 0x15, 0x10, 0x29, 0x59, 0x26, 0x02, 0x42, 0x39, 0x00, 0x00, 0x0a, 0x96, 0x52, 0x39, 0xfe, 0x1b, 0x07, 0x94, 0x9e, 0x59, 0xfd, 0x1b, 0x60, 0x38, 0x48, 0x0e, 0x22, 0x48, 0x98, 0x49, 0x13, 0x96, 0x19, 0x07, 0xe2, 0x38, 0x09, 0x00, 0xe1, 0x97, 0x3e, 0x5f, 0x58, 0x61, 0x1a, 0x69, 0x23, 0x58, 0x00, 0x3a, 0x72, 0x19, 0xfe, 0x5f, 0xaf, 0x2a, 0xfe, 0x5f, 0x00, 0x3a, 0x86, 0x19, 0xdb, 0x5a, 0x08, 0x39, 0x01, 0x00, 0x01, 0x9e, 0x3e, 0x5f, 0x3a, 0x38, 0x1e, 0x5f, 0x00, 0x67, 0xe0, 0x3c, 0x0c, 0x10, 0x89, 0x5c, 0x85, 0x03, 0x62, 0x39, 0x00, 0x00, 0x50, 0x96, 0x72, 0x39, 0xfd, 0x1b, 0x4d, 0x94, 0xe0, 0x3c, 0x15, 0x10, 0x89, 0x5c, 0x86, 0x02, 0x42, 0x39, 0x00, 0x00, 0x46, 0x96, 0x5c, 0x6a, +0xc0, 0x0f, 0x52, 0x39, 0xfe, 0x1b, 0x43, 0x94, 0x9e, 0x59, 0xfd, 0x1b, 0x60, 0x38, 0x32, 0x16, 0x22, 0x48, 0x03, 0x5c, 0x82, 0x39, 0x00, 0x00, 0x3a, 0x9a, 0x1e, 0x5f, 0x1e, 0x5c, 0x1e, 0xd0, 0x81, 0x58, 0x3e, 0x5c, 0x19, 0x17, 0x20, 0x98, 0x19, 0x11, 0x1e, 0x98, 0x1e, 0x5c, 0x00, 0x3f, 0x72, 0x19, 0xe3, 0x5f, 0x00, 0x39, 0x86, 0x19, 0x23, 0x59, 0x9e, 0x5c, 0xfd, 0x1b, 0xe0, 0x38, 0x32, 0x16, 0x81, 0x48, 0x03, 0x5f, 0xa0, 0x38, 0x32, 0x16, 0x86, 0x48, 0x3e, 0x5c, 0x17, 0x07, 0x80, 0x41, 0x1c, 0x5f, 0x01, 0x5c, 0x3e, 0x5f, 0xe2, 0x38, 0x05, 0x00, 0x04, 0x96, 0xfd, 0x61, 0xb4, 0x69, 0x81, 0x40, 0x21, 0x5c, 0x1e, 0x5f, 0x50, 0x67, 0x1a, 0x6f, 0xe5, 0x58, 0xe3, 0x59, 0x83, 0x48, 0x3f, 0x5f, 0x1b, 0x5f, 0x52, 0x67, 0x1a, 0x6f, 0xe5, 0x58, 0xe3, 0x59, 0x82, 0x48, 0x3f, 0x5f, 0x1f, 0xab, +0x00, 0x10, 0x1b, 0x5f, 0x90, 0x38, 0x54, 0x1a, 0xbe, 0x58, 0x54, 0x1a, 0x3e, 0x5f, 0x19, 0x07, 0xe2, 0x38, 0x09, 0x00, 0xa5, 0x97, 0x3e, 0x5f, 0x3a, 0x38, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0x01, 0x00, 0x01, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x01, 0x00, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x01, 0x00, 0x9e, 0x5c, 0x58, 0x1a, 0x18, 0x14, 0x29, 0x9a, 0x19, 0x14, 0xff, 0x67, 0x7f, 0x6f, 0x87, 0x38, 0x3d, 0x10, 0x80, 0x38, 0x72, 0x19, 0x80, 0x39, 0x86, 0x19, 0xb8, 0x49, 0x02, 0x88, 0xd9, 0x49, 0x0e, 0x8a, 0x13, 0x10, 0x01, 0x8c, 0x02, 0x58, 0x32, 0x11, 0x01, 0x8c, 0x22, 0x59, 0x01, 0x00, 0xe4, 0x39, 0xff, 0x00, 0x19, 0x48, 0x03, 0x94, 0xfe, 0x5c, 0x04, 0x2f, 0xfe, 0x5c, 0x19, 0x14, 0xe4, 0x3c, 0x00, 0xff, 0x03, 0xe2, +0x40, 0x10, 0xfe, 0x5c, 0x80, 0x38, 0x72, 0x19, 0x13, 0x11, 0x01, 0x8c, 0x22, 0x59, 0x80, 0x38, 0x86, 0x19, 0x12, 0x17, 0x01, 0x8c, 0xe2, 0x5f, 0x3a, 0x38, 0x21, 0x72, 0x43, 0x43, 0x01, 0x5c, 0x43, 0x41, 0x24, 0x01, 0x9e, 0x5c, 0x54, 0x1a, 0x1c, 0x5c, 0x18, 0x00, 0x3a, 0x38, 0x1e, 0x58, 0x1e, 0x59, 0xd2, 0x60, 0x15, 0x68, 0x03, 0x59, 0x22, 0x38, 0x01, 0x00, 0x03, 0x8a, 0x22, 0x38, 0x02, 0x00, 0x06, 0x8a, 0x00, 0x60, 0xbe, 0x58, 0x0b, 0x1f, 0xbe, 0x58, 0x0c, 0x1f, 0x0a, 0x9e, 0xb2, 0x60, 0x19, 0x68, 0x03, 0x59, 0xbe, 0x59, 0x0c, 0x1f, 0xbe, 0x60, 0x19, 0x68, 0x03, 0x59, 0xbe, 0x59, 0x0b, 0x1f, 0x3e, 0x59, 0x3e, 0x58, 0x00, 0x60, 0xbe, 0x58, 0xe2, 0x19, 0x58, 0x60, 0x1a, 0x68, 0x00, 0x61, 0x38, 0x49, 0x58, 0x8a, 0x00, 0x67, 0xe0, 0x38, 0x72, 0x19, 0x03, 0x5d, 0xe0, 0x38, 0x68, 0xec, +0x80, 0x10, 0x86, 0x19, 0x03, 0x5e, 0xd4, 0xd0, 0xf4, 0xd1, 0x9e, 0x58, 0x59, 0x1a, 0x19, 0x10, 0x05, 0x8a, 0xe0, 0xd0, 0x9e, 0x58, 0x59, 0x1a, 0x1a, 0x10, 0x01, 0x8a, 0xad, 0xcf, 0x51, 0x63, 0x1a, 0x6b, 0x4c, 0xd0, 0x9e, 0x5d, 0xe2, 0x19, 0xa0, 0x3b, 0xb2, 0x19, 0x1b, 0x5b, 0x53, 0x63, 0x1a, 0x6b, 0x4c, 0xd0, 0xa0, 0x3b, 0xbe, 0x19, 0x1b, 0x5b, 0x1e, 0x58, 0x1e, 0x59, 0xa2, 0x38, 0x00, 0x00, 0x13, 0x88, 0x9e, 0x58, 0x0b, 0x1f, 0x18, 0x10, 0x05, 0x88, 0x9e, 0x58, 0x0c, 0x1f, 0x18, 0x10, 0x01, 0x88, 0x0a, 0x9e, 0x9e, 0x58, 0x0b, 0x1f, 0xb2, 0x61, 0x19, 0x69, 0x1b, 0x59, 0x9e, 0x58, 0x0c, 0x1f, 0xbe, 0x61, 0x19, 0x69, 0x1b, 0x59, 0x3e, 0x59, 0x3e, 0x58, 0xe2, 0x62, 0x19, 0x6a, 0xca, 0x63, 0x19, 0x6b, 0x53, 0x03, 0xde, 0x5b, 0xff, 0xff, 0xd6, 0x63, 0x19, 0x6b, 0x53, 0x03, 0xd6, 0xe0, +0xc0, 0x10, 0xde, 0x5b, 0xff, 0x7f, 0x43, 0x5b, 0x68, 0x3a, 0x01, 0x00, 0x59, 0x60, 0x1a, 0x68, 0xde, 0x58, 0x00, 0x00, 0x9e, 0x58, 0xe2, 0x19, 0x12, 0x38, 0x27, 0x00, 0x05, 0x94, 0x19, 0x07, 0x58, 0x60, 0x1a, 0x68, 0xf8, 0x49, 0xa9, 0x81, 0x3a, 0x38, 0x50, 0x60, 0x1a, 0x68, 0x00, 0x61, 0x04, 0x62, 0x47, 0x38, 0xdb, 0x10, 0x3d, 0x58, 0x1a, 0x38, 0x59, 0x60, 0x1a, 0x68, 0x3b, 0x58, 0x3a, 0x38, 0xbe, 0x5d, 0xe1, 0x1b, 0xbe, 0x5e, 0xe2, 0x1b, 0x1e, 0x5f, 0x00, 0x67, 0xe0, 0x39, 0xde, 0x15, 0x23, 0x59, 0xe0, 0x3a, 0xf2, 0x15, 0x43, 0x5a, 0xe0, 0x3b, 0x06, 0x16, 0x63, 0x5b, 0xe0, 0x3c, 0x1a, 0x16, 0x83, 0x5c, 0xb9, 0x48, 0x07, 0x96, 0xba, 0x48, 0x05, 0x98, 0xdb, 0x48, 0x03, 0x98, 0xdc, 0x48, 0x01, 0x96, 0x05, 0x9e, 0x19, 0x07, 0xf2, 0x39, 0x4b, 0x1a, 0xe7, 0x97, 0xa9, 0x9e, 0xcb, 0x8d, +0x00, 0x11, 0x1e, 0x5d, 0x1e, 0x5e, 0x1e, 0x5f, 0x00, 0x67, 0x00, 0x60, 0xe0, 0x3d, 0x72, 0x19, 0xa3, 0x5d, 0xe0, 0x3e, 0x86, 0x19, 0xc3, 0x5e, 0xb9, 0x48, 0x0a, 0x96, 0xba, 0x48, 0x08, 0x98, 0xdb, 0x48, 0x06, 0x98, 0xdc, 0x48, 0x04, 0x96, 0x19, 0x00, 0xfe, 0x5f, 0x07, 0x28, 0xfe, 0x5f, 0x19, 0x07, 0xf2, 0x3d, 0x58, 0x1a, 0xea, 0x97, 0x3e, 0x5f, 0x04, 0x3d, 0xff, 0x00, 0x19, 0x15, 0x01, 0x8a, 0x86, 0x9e, 0x41, 0x16, 0xc1, 0x5f, 0x64, 0x15, 0xdd, 0x48, 0x01, 0x94, 0xa1, 0x5f, 0x1d, 0x17, 0x7b, 0x98, 0x04, 0x3f, 0x00, 0xff, 0xfe, 0x5f, 0x1a, 0x16, 0x0d, 0x94, 0xe0, 0x38, 0x72, 0x19, 0x03, 0x58, 0x18, 0x10, 0x02, 0x9a, 0x02, 0x39, 0x01, 0x00, 0x12, 0x3e, 0xfd, 0x1b, 0x19, 0x06, 0x02, 0x94, 0x00, 0x3a, 0x01, 0x00, 0x1a, 0x15, 0x0d, 0x94, 0xe0, 0x38, 0x86, 0x19, 0x03, 0x58, 0xdb, 0x66, +0x40, 0x11, 0x18, 0x10, 0x02, 0x9a, 0x02, 0x3c, 0x01, 0x00, 0x12, 0x3e, 0xfe, 0x1b, 0x19, 0x06, 0x02, 0x94, 0x00, 0x3b, 0x01, 0x00, 0x1e, 0x59, 0x21, 0x5d, 0x9e, 0x5e, 0xfd, 0x1b, 0xa0, 0x38, 0x32, 0x16, 0xc4, 0x48, 0x03, 0x5e, 0x9e, 0x58, 0xe6, 0x1b, 0x00, 0x61, 0x01, 0x69, 0x19, 0x48, 0x12, 0x98, 0xb2, 0x38, 0xe1, 0x1b, 0x03, 0x88, 0x92, 0x38, 0xe2, 0x1b, 0x0c, 0x8a, 0x18, 0x16, 0x07, 0x9a, 0x08, 0x60, 0xc0, 0x40, 0x08, 0x5e, 0xc0, 0x06, 0xc8, 0x5e, 0xc8, 0x5e, 0xc8, 0x5e, 0x9e, 0x58, 0xe4, 0x1b, 0xc0, 0x06, 0x18, 0x16, 0x2b, 0x9a, 0x50, 0x67, 0x1a, 0x6f, 0xe5, 0x58, 0xe3, 0x59, 0xc5, 0x48, 0x3f, 0x5f, 0x1b, 0x5f, 0x52, 0x67, 0x1a, 0x6f, 0xe5, 0x58, 0xe3, 0x59, 0xc4, 0x48, 0x3f, 0x5f, 0x1b, 0x5f, 0xd0, 0x3f, 0x54, 0x1a, 0xbe, 0x5f, 0x54, 0x1a, 0x7f, 0xac, 0x17, 0x90, 0xbd, 0x55, +0x80, 0x11, 0xe8, 0x5f, 0xbe, 0x5f, 0x54, 0x1a, 0x9e, 0x58, 0x50, 0x1a, 0x9e, 0x59, 0x51, 0x1a, 0x28, 0x59, 0x0c, 0x58, 0xbe, 0x59, 0x51, 0x1a, 0xbe, 0x58, 0x50, 0x1a, 0x9e, 0x58, 0x52, 0x1a, 0x9e, 0x59, 0x53, 0x1a, 0x28, 0x59, 0x0c, 0x58, 0xbe, 0x59, 0x53, 0x1a, 0xbe, 0x58, 0x52, 0x1a, 0xa2, 0x37, 0x02, 0x8a, 0x19, 0x05, 0xb1, 0x9f, 0x3e, 0x59, 0x83, 0x37, 0x02, 0x8a, 0x19, 0x04, 0xaa, 0x9f, 0x02, 0x65, 0xbe, 0x5d, 0x59, 0x1a, 0x03, 0x9e, 0x03, 0x65, 0xbe, 0x5d, 0x59, 0x1a, 0x3e, 0x5e, 0x3e, 0x5d, 0x3e, 0x5f, 0x3a, 0x38, 0x1e, 0x5c, 0x9e, 0x5d, 0xe1, 0x1b, 0x9e, 0x5e, 0xe2, 0x1b, 0xa0, 0x38, 0x32, 0x16, 0x16, 0x67, 0x1e, 0x59, 0x00, 0x61, 0xc7, 0x48, 0x3e, 0x59, 0x03, 0x5f, 0x18, 0x17, 0x35, 0x9a, 0x1e, 0x59, 0x1e, 0x5a, 0x00, 0x61, 0xe1, 0x58, 0xbe, 0x5f, 0xe6, 0x1b, 0x35, 0x15, +0xc0, 0x11, 0x06, 0x58, 0x2a, 0x59, 0x06, 0x58, 0x2a, 0x59, 0x0c, 0x62, 0x1c, 0x5a, 0xbe, 0x58, 0xe3, 0x1b, 0x00, 0x61, 0xe1, 0x58, 0xa8, 0x62, 0x1c, 0x5a, 0xbe, 0x58, 0xe4, 0x1b, 0x3e, 0x5a, 0x3e, 0x59, 0x41, 0x10, 0x21, 0x5f, 0x07, 0x38, 0xea, 0x11, 0xfd, 0x48, 0x02, 0x88, 0x9e, 0x48, 0x12, 0x8a, 0x20, 0x38, 0x32, 0x16, 0x1e, 0x59, 0x1e, 0x5a, 0x16, 0x62, 0x00, 0x61, 0x82, 0x48, 0x3e, 0x5a, 0x3e, 0x59, 0x03, 0x58, 0x18, 0x10, 0x06, 0x9a, 0x1e, 0x59, 0x9e, 0x59, 0xe3, 0x1b, 0x19, 0x48, 0x3e, 0x59, 0x05, 0x94, 0x19, 0x07, 0x19, 0x04, 0x9b, 0x48, 0xe2, 0x9b, 0x03, 0x9e, 0x00, 0x60, 0xbe, 0x58, 0xe4, 0x1b, 0x3e, 0x5c, 0x3a, 0x38, 0x9e, 0x58, 0x58, 0x1a, 0x02, 0x39, 0x01, 0x00, 0x1d, 0x9a, 0x00, 0x62, 0x5f, 0x48, 0x16, 0x8a, 0x40, 0x38, 0x72, 0x19, 0x03, 0x5b, 0x40, 0x38, 0xb8, 0xbd, +0x00, 0x12, 0x86, 0x19, 0x03, 0x5c, 0xa3, 0x10, 0x01, 0x8c, 0x02, 0x58, 0x02, 0x39, 0x01, 0x00, 0x0a, 0x88, 0xc4, 0x10, 0x01, 0x8c, 0x02, 0x58, 0x02, 0x39, 0x01, 0x00, 0x04, 0x88, 0x01, 0x61, 0xbe, 0x59, 0x59, 0x1a, 0x04, 0x9e, 0x19, 0x02, 0x52, 0x39, 0x58, 0x1a, 0xe4, 0x89, 0x3a, 0x38, 0x9e, 0x58, 0x58, 0x1a, 0x02, 0x39, 0x01, 0x00, 0x66, 0x9a, 0x00, 0x67, 0xe0, 0x3e, 0x86, 0x19, 0xe0, 0x3a, 0x01, 0x00, 0x40, 0x3b, 0x72, 0x19, 0x40, 0x3c, 0x86, 0x19, 0xe0, 0x3d, 0x72, 0x19, 0xa3, 0x5d, 0xa4, 0x38, 0x00, 0xff, 0x63, 0x5b, 0x64, 0x39, 0x00, 0xff, 0x19, 0x48, 0x4a, 0x88, 0xa4, 0x3d, 0xff, 0x00, 0x64, 0x3b, 0xff, 0x00, 0x1e, 0x5f, 0x1e, 0x5a, 0x9e, 0x5f, 0xfd, 0x1b, 0x60, 0x38, 0x48, 0x0e, 0xe4, 0x49, 0x03, 0x5a, 0xa0, 0x38, 0x48, 0x0e, 0xe6, 0x49, 0x00, 0x61, 0x58, 0x49, 0x7a, 0x8f, +0x40, 0x12, 0x02, 0x9a, 0x01, 0x61, 0x03, 0x5a, 0x1e, 0x59, 0x9e, 0x58, 0x44, 0x1a, 0x40, 0x40, 0x9f, 0x38, 0x08, 0x58, 0xbe, 0x58, 0x83, 0x1a, 0x8f, 0xd2, 0x19, 0x10, 0x28, 0x8a, 0x9e, 0x58, 0x58, 0x1a, 0x19, 0x10, 0xbe, 0x58, 0x58, 0x1a, 0x3e, 0x59, 0x3e, 0x5a, 0x3e, 0x5f, 0x40, 0x3b, 0x72, 0x19, 0xe0, 0x3d, 0x72, 0x19, 0x18, 0x11, 0x04, 0x8a, 0x63, 0x59, 0x3b, 0x5d, 0x83, 0x59, 0x3b, 0x5e, 0x72, 0x61, 0x19, 0x69, 0x30, 0x39, 0x58, 0x1a, 0x23, 0x59, 0x3b, 0x5b, 0x86, 0x61, 0x19, 0x69, 0x30, 0x39, 0x58, 0x1a, 0x23, 0x59, 0x3b, 0x5c, 0x19, 0x10, 0x14, 0x8a, 0x52, 0x38, 0x58, 0x1a, 0x0c, 0x94, 0xf2, 0x38, 0x58, 0x1a, 0x19, 0x00, 0x0d, 0x94, 0xab, 0x9f, 0x3e, 0x59, 0x3e, 0x5a, 0x3e, 0x5f, 0x19, 0x02, 0x52, 0x39, 0x58, 0x1a, 0xa4, 0x97, 0x19, 0x07, 0xf2, 0x39, 0x58, 0x1a, 0x11, 0xac, +0x80, 0x12, 0x19, 0x01, 0x9b, 0x97, 0x9e, 0x58, 0x58, 0x1a, 0x18, 0x10, 0x08, 0x8a, 0x72, 0x66, 0x19, 0x6e, 0xff, 0x61, 0x19, 0x10, 0x07, 0x38, 0x8d, 0x12, 0xd1, 0x25, 0xbd, 0x5e, 0x3a, 0x38, 0x1e, 0x5d, 0x1e, 0x5e, 0x1e, 0x5b, 0x1e, 0x5c, 0x83, 0x5a, 0x7d, 0x48, 0x03, 0x9a, 0x5e, 0x49, 0x23, 0x9a, 0x32, 0x9e, 0x5e, 0x49, 0x10, 0x9a, 0x61, 0x5a, 0xbe, 0x5a, 0x2e, 0x16, 0xa1, 0x5a, 0xbe, 0x5a, 0x2f, 0x16, 0xc3, 0x5a, 0xbe, 0x5a, 0x30, 0x16, 0x83, 0x5a, 0xbe, 0x5a, 0x31, 0x16, 0x02, 0x62, 0xbe, 0x5a, 0x82, 0x1a, 0x2f, 0x9e, 0x61, 0x5a, 0xbe, 0x5a, 0x2e, 0x16, 0xa1, 0x5a, 0xbe, 0x5a, 0x2f, 0x16, 0x83, 0x5a, 0xbe, 0x5a, 0x30, 0x16, 0xc3, 0x5a, 0xbe, 0x5a, 0x31, 0x16, 0x00, 0x62, 0xbe, 0x5a, 0x82, 0x1a, 0x1f, 0x9e, 0xa1, 0x5a, 0xbe, 0x5a, 0x2e, 0x16, 0x61, 0x5a, 0xbe, 0x5a, 0x5d, 0xe2, +0xc0, 0x12, 0x2f, 0x16, 0x83, 0x5a, 0xbe, 0x5a, 0x30, 0x16, 0xc3, 0x5a, 0xbe, 0x5a, 0x31, 0x16, 0x06, 0x62, 0xbe, 0x5a, 0x82, 0x1a, 0x0f, 0x9e, 0xa1, 0x5a, 0xbe, 0x5a, 0x2e, 0x16, 0x61, 0x5a, 0xbe, 0x5a, 0x2f, 0x16, 0xc3, 0x5a, 0xbe, 0x5a, 0x30, 0x16, 0x83, 0x5a, 0xbe, 0x5a, 0x31, 0x16, 0x04, 0x62, 0xbe, 0x5a, 0x82, 0x1a, 0xc3, 0x5e, 0xa1, 0x58, 0xc1, 0x59, 0x1e, 0x58, 0x1e, 0x59, 0x1e, 0x5b, 0x1e, 0x5c, 0x00, 0x67, 0x9e, 0x5a, 0x82, 0x1a, 0x40, 0x3c, 0x2a, 0x13, 0x89, 0x5c, 0x85, 0x04, 0x92, 0x39, 0x2e, 0x16, 0x23, 0x96, 0x92, 0x39, 0x2f, 0x16, 0x20, 0x98, 0x40, 0x3b, 0x32, 0x13, 0x69, 0x5b, 0x66, 0x03, 0x72, 0x39, 0x30, 0x16, 0x19, 0x96, 0x72, 0x39, 0x31, 0x16, 0x16, 0x98, 0x9e, 0x59, 0xfd, 0x1b, 0x80, 0x38, 0x48, 0x0e, 0x23, 0x48, 0x9e, 0x59, 0x83, 0x1a, 0x38, 0x49, 0x36, 0x4b, +0x00, 0x13, 0x0d, 0x98, 0x81, 0x5d, 0x61, 0x5e, 0x9e, 0x59, 0x82, 0x1a, 0x01, 0xac, 0x02, 0x90, 0x1e, 0x01, 0x01, 0x9e, 0x1f, 0x01, 0x1f, 0x21, 0xbe, 0x59, 0x82, 0x1a, 0x08, 0x9e, 0x19, 0x02, 0x1f, 0x22, 0xbe, 0x5a, 0x82, 0x1a, 0x19, 0x07, 0xe2, 0x39, 0x08, 0x00, 0xce, 0x97, 0x3e, 0x5c, 0x3e, 0x5b, 0x3e, 0x59, 0x3e, 0x58, 0xd9, 0x48, 0x04, 0x88, 0xb8, 0x48, 0x02, 0x88, 0x01, 0x60, 0x05, 0x9e, 0xdc, 0x49, 0xbb, 0x89, 0xbb, 0x48, 0xb9, 0x89, 0x00, 0x60, 0x3e, 0x5c, 0x3e, 0x5b, 0x3e, 0x5e, 0x3e, 0x5d, 0x3a, 0x38, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0x02, 0x3f, 0x01, 0x00, 0x0c, 0x98, 0x30, 0x66, 0x0b, 0x6e, 0x9e, 0x5d, 0xba, 0x1f, +0x40, 0x13, 0xe8, 0x00, 0x9e, 0x5f, 0xda, 0x00, 0x19, 0x17, 0xe7, 0x38, 0x47, 0x13, 0xa5, 0x59, 0x3d, 0x5e, 0x21, 0x9e, 0x12, 0x3f, 0x22, 0x00, 0x1e, 0x98, 0x30, 0x66, 0x0b, 0x6e, 0x9e, 0x5d, 0xe8, 0x00, 0x9e, 0x5f, 0xda, 0x00, 0x19, 0x17, 0xe7, 0x38, 0x57, 0x13, 0xa5, 0x5f, 0xd7, 0x07, 0xfd, 0x5e, 0x12, 0x3f, 0x22, 0x00, 0x0f, 0x88, 0x30, 0x66, 0x0b, 0x6e, 0x22, 0x75, 0x9e, 0x5f, 0xda, 0x00, 0x19, 0x17, 0xe7, 0x38, 0x68, 0x13, 0x00, 0x61, 0xc3, 0x58, 0x1c, 0x5d, 0x1d, 0x5e, 0x1a, 0x38, 0x1a, 0x38, 0x00, 0x60, 0x3a, 0x38, 0x27, 0x76, 0x19, 0x16, 0x39, 0x60, 0x15, 0x68, 0x9a, 0x61, 0x19, 0x69, 0x45, 0x62, 0x15, 0x6a, 0xa6, 0x63, 0x19, 0x6b, 0x00, 0x64, 0x80, 0x6c, 0x00, 0x67, 0xc7, 0x38, 0x83, 0x13, 0xf8, 0x49, 0x04, 0x98, 0x03, 0x5d, 0xbb, 0x59, 0x43, 0x5d, 0xbb, 0x5b, 0x0b, 0xa4, +0x80, 0x13, 0x19, 0x01, 0x19, 0x03, 0x9d, 0x58, 0x9d, 0x5a, 0x21, 0x60, 0x15, 0x68, 0x2b, 0x61, 0x1c, 0x69, 0x2d, 0x62, 0x15, 0x6a, 0x37, 0x63, 0x1c, 0x6b, 0x00, 0x65, 0xc7, 0x38, 0xa2, 0x13, 0xa0, 0x3c, 0x85, 0x29, 0x89, 0x5c, 0x94, 0x3c, 0xe3, 0x19, 0x05, 0x8a, 0x03, 0x5c, 0x9b, 0x59, 0x43, 0x5c, 0x9b, 0x5b, 0x04, 0x9e, 0xde, 0x59, 0x00, 0x80, 0xde, 0x5b, 0x00, 0x80, 0x19, 0x01, 0x19, 0x03, 0x19, 0x00, 0x19, 0x02, 0x19, 0x05, 0x00, 0x67, 0x80, 0x6f, 0x51, 0x60, 0x15, 0x68, 0x21, 0x61, 0x15, 0x69, 0x5d, 0x62, 0x15, 0x6a, 0x2d, 0x63, 0x15, 0x6b, 0xc7, 0x38, 0xb8, 0x13, 0xf8, 0x49, 0x04, 0x8a, 0x03, 0x5c, 0x9b, 0x59, 0x43, 0x5c, 0x9b, 0x5b, 0x19, 0x01, 0x19, 0x03, 0x19, 0x00, 0x19, 0x02, 0xca, 0x60, 0x19, 0x68, 0xd6, 0x61, 0x19, 0x69, 0xc7, 0x38, 0xc4, 0x13, 0xde, 0x58, 0xb0, 0xea, +0xc0, 0x13, 0xff, 0xff, 0xde, 0x59, 0xff, 0x7f, 0x19, 0x00, 0x19, 0x01, 0x9e, 0x58, 0xfa, 0x1b, 0x12, 0x38, 0xe2, 0x19, 0x16, 0x9a, 0x00, 0x67, 0x01, 0x65, 0xc7, 0x38, 0xdf, 0x13, 0xb4, 0x38, 0x4c, 0x1a, 0x0d, 0x88, 0xe0, 0x38, 0x9a, 0x19, 0xde, 0x58, 0x00, 0x80, 0xe0, 0x38, 0xa6, 0x19, 0xde, 0x58, 0x00, 0x80, 0xa0, 0x5c, 0x94, 0x3c, 0x00, 0x1c, 0xbe, 0x5c, 0x00, 0x1c, 0xa6, 0x5d, 0x19, 0x07, 0x3a, 0x38, 0x9e, 0x5f, 0xe2, 0x19, 0x18, 0x17, 0x24, 0x8a, 0x21, 0x72, 0x23, 0x61, 0x22, 0x40, 0x00, 0x3b, 0x00, 0x00, 0x15, 0x61, 0x22, 0x40, 0x00, 0x3c, 0x00, 0x00, 0xe1, 0x5e, 0x00, 0x67, 0xe0, 0x39, 0xb2, 0x19, 0xe0, 0x3a, 0xbe, 0x19, 0x79, 0x49, 0x02, 0x80, 0x9a, 0x49, 0x0c, 0x82, 0x19, 0x16, 0xdf, 0x48, 0x0c, 0x8a, 0xc0, 0x38, 0xb2, 0x19, 0x03, 0x58, 0x1b, 0x59, 0xc0, 0x38, 0xaa, 0xd3, +0x00, 0x14, 0xbe, 0x19, 0x03, 0x58, 0x1b, 0x5a, 0xec, 0x9f, 0x19, 0x07, 0xe6, 0x15, 0xe9, 0x97, 0xbe, 0x5e, 0xe2, 0x19, 0x01, 0x60, 0xbe, 0x58, 0x82, 0x1a, 0x00, 0x67, 0xe2, 0x60, 0x19, 0x68, 0xf8, 0x49, 0x31, 0x94, 0xe0, 0x38, 0xca, 0x19, 0x00, 0x61, 0x38, 0x49, 0x2a, 0x9a, 0x00, 0x66, 0x27, 0x70, 0x19, 0x10, 0x07, 0x38, 0x3f, 0x14, 0xc0, 0x38, 0x39, 0x15, 0x00, 0x61, 0x38, 0x49, 0x1f, 0x9a, 0xc0, 0x38, 0x9a, 0x19, 0x00, 0x61, 0x38, 0x49, 0x03, 0x9a, 0xfe, 0x65, 0x7f, 0x6d, 0x0f, 0x9e, 0xe0, 0x38, 0xb2, 0x19, 0xc0, 0x39, 0x9a, 0x19, 0x23, 0x59, 0x11, 0x12, 0xe0, 0x38, 0xbe, 0x19, 0xc0, 0x39, 0xa6, 0x19, 0x23, 0x59, 0x11, 0x13, 0x5a, 0x40, 0x63, 0x48, 0x46, 0xd9, 0xe0, 0x38, 0xd6, 0x19, 0xb8, 0x49, 0x04, 0x94, 0xbb, 0x58, 0xe0, 0x38, 0xca, 0x19, 0xdb, 0x58, 0x19, 0x06, 0xde, 0xb2, +0x40, 0x14, 0x19, 0x07, 0xcb, 0x9f, 0x00, 0x60, 0xbe, 0x58, 0x82, 0x1a, 0x00, 0x67, 0x9e, 0x5d, 0xe2, 0x19, 0xfd, 0x48, 0x25, 0x94, 0xe0, 0x3e, 0x01, 0x00, 0xa2, 0x38, 0x01, 0x00, 0x07, 0x38, 0x6c, 0x14, 0xdd, 0x48, 0x1b, 0x94, 0xe0, 0x3c, 0xca, 0x19, 0x83, 0x58, 0xc0, 0x3b, 0xca, 0x19, 0x1b, 0x49, 0x13, 0x88, 0xe0, 0x3a, 0xd6, 0x19, 0x43, 0x58, 0xc0, 0x39, 0xd6, 0x19, 0x19, 0x49, 0x05, 0x9a, 0xde, 0x5c, 0xff, 0xff, 0xde, 0x5a, 0xff, 0x7f, 0x04, 0x9e, 0xde, 0x5b, 0xff, 0xff, 0xde, 0x59, 0xff, 0x7f, 0x01, 0x60, 0xbe, 0x58, 0x82, 0x1a, 0x19, 0x06, 0x19, 0x07, 0xd9, 0x9f, 0x00, 0x67, 0xe2, 0x60, 0x19, 0x68, 0xf8, 0x49, 0x15, 0x94, 0xe0, 0x38, 0xca, 0x19, 0x00, 0x61, 0x38, 0x49, 0x0e, 0x98, 0x39, 0x61, 0x15, 0x69, 0x11, 0x01, 0xe0, 0x3a, 0xb2, 0x19, 0x43, 0x5a, 0x5b, 0x59, 0xd2, 0xa6, +0x80, 0x14, 0x45, 0x61, 0x15, 0x69, 0x11, 0x01, 0xe0, 0x3a, 0xbe, 0x19, 0x43, 0x5a, 0x5b, 0x59, 0x19, 0x07, 0xe7, 0x9f, 0x82, 0x60, 0x1a, 0x68, 0x01, 0x61, 0x38, 0x49, 0x7e, 0x8b, 0x9e, 0x58, 0xe2, 0x19, 0x19, 0x10, 0x01, 0x9a, 0x25, 0xdb, 0x92, 0x60, 0x15, 0x68, 0xff, 0x61, 0xff, 0x69, 0x27, 0x76, 0x19, 0x16, 0xd7, 0x38, 0x3d, 0x58, 0x9e, 0x5f, 0xe2, 0x19, 0x18, 0x17, 0x10, 0x8a, 0x92, 0x66, 0x15, 0x6e, 0x19, 0x17, 0xe7, 0x38, 0xae, 0x14, 0xe0, 0x3b, 0xca, 0x19, 0x76, 0x03, 0xe0, 0x3c, 0xd6, 0x19, 0x83, 0x5c, 0x18, 0x14, 0x01, 0x88, 0x21, 0x74, 0x9b, 0x5b, 0x19, 0x17, 0x01, 0x67, 0x27, 0x76, 0x19, 0x16, 0xc7, 0x38, 0xb5, 0x14, 0xe6, 0x5f, 0x1a, 0x38, 0x19, 0x17, 0xbe, 0x5f, 0x84, 0x1a, 0xf6, 0xd5, 0x9e, 0x58, 0xe2, 0x19, 0xbe, 0x58, 0xfa, 0x1b, 0x00, 0x67, 0x27, 0x70, 0xe3, 0x18, +0xc0, 0x14, 0x19, 0x10, 0x07, 0x38, 0x56, 0x15, 0x9e, 0x58, 0xea, 0x04, 0x18, 0x10, 0x03, 0x8a, 0x02, 0x60, 0x20, 0x78, 0x02, 0x9e, 0x02, 0x60, 0x20, 0x78, 0xe0, 0x38, 0x39, 0x15, 0xe0, 0x3c, 0xd2, 0x15, 0x00, 0x61, 0x38, 0x49, 0x50, 0x98, 0xd0, 0x73, 0x7c, 0x49, 0x02, 0x9a, 0x7b, 0x5c, 0x7e, 0x9e, 0x70, 0x3b, 0x20, 0x00, 0x7c, 0x49, 0x14, 0x98, 0xe0, 0x38, 0x85, 0x29, 0x09, 0x58, 0xe3, 0x61, 0x19, 0x69, 0x30, 0x2a, 0x5b, 0x59, 0x4c, 0x61, 0x1a, 0x69, 0x30, 0x2a, 0x5b, 0x59, 0x70, 0x3b, 0xcf, 0x00, 0x7c, 0x49, 0x34, 0x98, 0x4d, 0x61, 0x1a, 0x69, 0x30, 0x2a, 0x5b, 0x59, 0x66, 0x9e, 0xe0, 0x38, 0x85, 0x29, 0x09, 0x58, 0x14, 0x3a, 0xe3, 0x19, 0x02, 0x8a, 0x7b, 0x5c, 0x27, 0x9e, 0xe0, 0x38, 0x92, 0x15, 0x0a, 0x61, 0x38, 0x49, 0x09, 0x9c, 0xe0, 0x38, 0x85, 0x29, 0x09, 0x58, 0x3a, 0x4e, +0x00, 0x15, 0x00, 0x61, 0x1c, 0x69, 0x00, 0x5a, 0x32, 0x22, 0x5b, 0x59, 0x19, 0x9e, 0xd0, 0x70, 0x19, 0x00, 0x1c, 0x49, 0x15, 0x88, 0xe0, 0x38, 0x85, 0x29, 0x09, 0x58, 0x00, 0x61, 0x1c, 0x69, 0x30, 0x22, 0x0e, 0x88, 0x30, 0x2a, 0x5b, 0x59, 0xe0, 0x38, 0x39, 0x15, 0x03, 0x58, 0xe0, 0x39, 0x13, 0x1c, 0x1b, 0x59, 0xe0, 0x38, 0x45, 0x15, 0x03, 0x58, 0xe0, 0x39, 0x1f, 0x1c, 0x1b, 0x59, 0x83, 0x58, 0x08, 0x3c, 0x01, 0x00, 0x33, 0x9e, 0xe0, 0x38, 0x85, 0x29, 0x09, 0x58, 0xd0, 0x73, 0x14, 0x39, 0x4c, 0x1a, 0x04, 0x8a, 0x00, 0x61, 0x91, 0x11, 0x09, 0x98, 0x0b, 0x9e, 0x7c, 0x49, 0x09, 0x94, 0x7b, 0x5c, 0x00, 0x61, 0x1c, 0x69, 0x00, 0x5a, 0x32, 0x22, 0x5b, 0x59, 0x83, 0x59, 0x2a, 0x3c, 0x01, 0x00, 0x00, 0x58, 0x70, 0x3b, 0x1f, 0x00, 0x7c, 0x49, 0x10, 0x96, 0xe3, 0x61, 0x19, 0x69, 0x0f, 0x86, +0x40, 0x15, 0x30, 0x22, 0x5b, 0x59, 0x4d, 0x61, 0x1a, 0x69, 0x30, 0x22, 0x5b, 0x59, 0x83, 0x5b, 0x72, 0x3b, 0xd0, 0x00, 0x0c, 0x9a, 0xd0, 0x73, 0x19, 0x13, 0x7b, 0x5c, 0x08, 0x9e, 0x59, 0xd5, 0x19, 0x03, 0x7c, 0x49, 0x04, 0x96, 0x4d, 0x61, 0x1a, 0x69, 0x30, 0x22, 0x5b, 0x59, 0x19, 0x07, 0x99, 0xd6, 0x3a, 0x38, 0x1e, 0x58, 0x1e, 0x5b, 0x21, 0x72, 0x23, 0x65, 0xa2, 0x40, 0x00, 0x3d, 0x00, 0x00, 0xe0, 0x38, 0x5b, 0x1c, 0x03, 0x58, 0x18, 0x10, 0x02, 0x94, 0x00, 0x60, 0x0b, 0x9e, 0x1d, 0x48, 0x02, 0x9a, 0xa1, 0x58, 0x07, 0x9e, 0x40, 0x3b, 0x00, 0x00, 0x1b, 0x48, 0x03, 0x96, 0xa2, 0x13, 0x1b, 0x48, 0x03, 0x9a, 0xe0, 0x39, 0x9a, 0x19, 0x1b, 0x59, 0x15, 0x65, 0xa2, 0x40, 0x00, 0x3d, 0x00, 0x00, 0xe0, 0x38, 0x67, 0x1c, 0x03, 0x58, 0x18, 0x10, 0x02, 0x94, 0x00, 0x60, 0x0b, 0x9e, 0xef, 0xbb, +0x80, 0x15, 0x1d, 0x48, 0x02, 0x9a, 0xa1, 0x58, 0x07, 0x9e, 0x40, 0x3b, 0x00, 0x00, 0x1b, 0x48, 0x03, 0x96, 0xa2, 0x13, 0x1b, 0x48, 0x03, 0x9a, 0xe0, 0x39, 0xa6, 0x19, 0x1b, 0x59, 0x3e, 0x5b, 0x3e, 0x58, 0x3a, 0x38, 0x00, 0x60, 0xbe, 0x58, 0x04, 0x1c, 0x9e, 0x58, 0xe2, 0x19, 0x12, 0x38, 0xea, 0x04, 0x31, 0x94, 0x01, 0x60, 0xbe, 0x58, 0x04, 0x1c, 0x27, 0x76, 0x19, 0x16, 0x00, 0x65, 0x00, 0x67, 0xc7, 0x38, 0xc9, 0x15, 0xe0, 0x38, 0x9a, 0x19, 0xb8, 0x49, 0x23, 0x98, 0xe0, 0x3e, 0x85, 0x29, 0xc9, 0x5e, 0xd4, 0x3e, 0xe3, 0x19, 0x0b, 0x88, 0x03, 0x58, 0xe0, 0x39, 0x5b, 0x1c, 0x1b, 0x59, 0xe0, 0x38, 0xa6, 0x19, 0x03, 0x58, 0xe0, 0x39, 0x67, 0x1c, 0x1b, 0x59, 0x12, 0x9e, 0xe0, 0x39, 0x43, 0x1c, 0x23, 0x59, 0xe0, 0x3a, 0x4f, 0x1c, 0x43, 0x5a, 0xe0, 0x38, 0x9a, 0x19, 0x11, 0x00, 0x9c, 0xb8, +0xc0, 0x15, 0xe0, 0x39, 0x5b, 0x1c, 0x1b, 0x59, 0xe0, 0x38, 0xa6, 0x19, 0x12, 0x00, 0xe0, 0x39, 0x67, 0x1c, 0x1b, 0x59, 0x19, 0x07, 0x3a, 0x38, 0x27, 0x76, 0x19, 0x16, 0x00, 0x67, 0xc7, 0x38, 0xf4, 0x15, 0x00, 0x62, 0xe0, 0x38, 0x39, 0x15, 0x58, 0x49, 0x1f, 0x98, 0xe0, 0x39, 0x9a, 0x19, 0x59, 0x49, 0x1b, 0x98, 0x23, 0x5a, 0x12, 0x12, 0xe0, 0x3c, 0x43, 0x1c, 0x5b, 0x5c, 0xe0, 0x38, 0x45, 0x15, 0xe0, 0x39, 0xa6, 0x19, 0x23, 0x5b, 0x13, 0x13, 0xe0, 0x3c, 0x4f, 0x1c, 0x7b, 0x5c, 0x9e, 0x58, 0x04, 0x1c, 0x18, 0x10, 0x09, 0x8a, 0x5a, 0x40, 0x63, 0x48, 0x46, 0xd9, 0x18, 0x15, 0x01, 0x88, 0x21, 0x75, 0xe0, 0x38, 0x92, 0x15, 0xbb, 0x58, 0x19, 0x07, 0x3a, 0x38, 0x27, 0x75, 0x19, 0x15, 0xa7, 0x38, 0x73, 0x16, 0xa0, 0x3f, 0x85, 0x29, 0xe9, 0x5f, 0x9e, 0x5c, 0x86, 0x1a, 0xe0, 0x5b, 0x06, 0xd5, +0x00, 0x16, 0x83, 0x24, 0xa0, 0x3b, 0xa0, 0x1a, 0x63, 0x5b, 0xbd, 0x13, 0x01, 0x96, 0x87, 0x2c, 0xbe, 0x5c, 0x86, 0x1a, 0xa0, 0x3c, 0x92, 0x15, 0x83, 0x5c, 0x82, 0x38, 0xff, 0xff, 0x64, 0x8a, 0x21, 0x73, 0x66, 0x5b, 0x83, 0x11, 0x60, 0x9a, 0x81, 0x58, 0xa0, 0x3a, 0x9e, 0x15, 0x43, 0x5a, 0x21, 0x73, 0x68, 0x5b, 0x42, 0x39, 0xfe, 0x7f, 0x05, 0x88, 0xf4, 0x39, 0x87, 0x1a, 0x02, 0x8a, 0x61, 0x5a, 0x16, 0x9e, 0x5b, 0x48, 0x14, 0x98, 0xa0, 0x39, 0x88, 0x1a, 0x23, 0x59, 0x18, 0x11, 0x02, 0x8a, 0x04, 0x62, 0x0d, 0x9e, 0x02, 0xa8, 0xa0, 0x39, 0xa0, 0x1a, 0x23, 0x59, 0xbd, 0x11, 0x07, 0x96, 0xa0, 0x39, 0x94, 0x1a, 0x23, 0x59, 0x24, 0x39, 0xff, 0x00, 0x01, 0x8a, 0x61, 0x5a, 0x04, 0x61, 0x01, 0x40, 0x1c, 0x5a, 0x00, 0x39, 0x01, 0x00, 0x28, 0x59, 0x1a, 0x00, 0x08, 0x58, 0x08, 0x58, 0xd5, 0x3e, +0x40, 0x16, 0x1a, 0x11, 0x03, 0x88, 0xf4, 0x39, 0x4a, 0x1a, 0x23, 0x88, 0x04, 0x62, 0xf4, 0x3e, 0x86, 0x1a, 0x01, 0x8a, 0x19, 0x62, 0x9e, 0x59, 0x20, 0x1d, 0x18, 0x11, 0x13, 0x8a, 0x22, 0x39, 0x68, 0x01, 0x14, 0x8a, 0x9e, 0x5e, 0xdb, 0x1e, 0x9e, 0x59, 0xdc, 0x1e, 0xc1, 0x06, 0x1b, 0x16, 0x09, 0x88, 0x9e, 0x5e, 0xf1, 0x04, 0x9e, 0x59, 0xf2, 0x04, 0xc1, 0x06, 0x1b, 0x16, 0x02, 0x88, 0x3a, 0x02, 0x05, 0x9e, 0x9e, 0x59, 0xb5, 0x00, 0x1a, 0x11, 0x01, 0x88, 0x3a, 0x02, 0x02, 0x11, 0x0b, 0x96, 0xa0, 0x38, 0x85, 0x29, 0x09, 0x58, 0x14, 0x3a, 0x00, 0x1c, 0x05, 0x88, 0x00, 0x58, 0x84, 0x61, 0x1a, 0x69, 0x30, 0x22, 0x5b, 0x59, 0x19, 0x15, 0x21, 0x74, 0x88, 0x5c, 0x92, 0x60, 0x15, 0x68, 0x9e, 0x61, 0x15, 0x69, 0x00, 0x65, 0x27, 0x76, 0x19, 0x16, 0xc7, 0x38, 0x97, 0x16, 0xa0, 0x3f, 0x70, 0x78, +0x80, 0x16, 0x85, 0x29, 0xe9, 0x5f, 0xff, 0x66, 0xff, 0x6e, 0xd8, 0x49, 0x03, 0x8a, 0x03, 0x5a, 0x5b, 0x59, 0x0c, 0x9e, 0xf4, 0x3b, 0xe3, 0x19, 0x09, 0x8a, 0xa0, 0x3b, 0xa0, 0x1a, 0x63, 0x5b, 0xbd, 0x13, 0x04, 0x82, 0x99, 0x49, 0x02, 0x82, 0x8a, 0x39, 0x01, 0x00, 0x19, 0x00, 0x19, 0x01, 0x19, 0x05, 0x3a, 0x38, 0x9e, 0x58, 0xe3, 0x19, 0x9e, 0x59, 0x84, 0x1a, 0x20, 0x59, 0x20, 0x21, 0xbe, 0x59, 0x4a, 0x1a, 0x14, 0x3a, 0x84, 0x1a, 0xbe, 0x5a, 0xe3, 0x19, 0x16, 0x39, 0x85, 0x1a, 0x20, 0x21, 0xbe, 0x59, 0x87, 0x1a, 0xbe, 0x58, 0x85, 0x1a, 0x01, 0x65, 0x00, 0x66, 0x27, 0x77, 0x19, 0x17, 0xe7, 0x38, 0xea, 0x16, 0x05, 0x27, 0x09, 0x8a, 0xc0, 0x39, 0x88, 0x1a, 0x23, 0x5b, 0x66, 0x5b, 0xb4, 0x3f, 0x4a, 0x1a, 0x01, 0x8a, 0x03, 0xa8, 0x7b, 0x59, 0xc0, 0x39, 0xa0, 0x1a, 0x23, 0x5b, 0x78, 0xfa, +0xc0, 0x16, 0xa2, 0x27, 0x0e, 0x8a, 0xd0, 0x77, 0xf0, 0x3f, 0x20, 0x00, 0xf0, 0x3f, 0xcf, 0x00, 0xc0, 0x3c, 0xd2, 0x15, 0xfc, 0x49, 0x05, 0x98, 0x62, 0x3f, 0x64, 0x00, 0x03, 0x82, 0x19, 0x03, 0x01, 0x9e, 0x00, 0x63, 0x7b, 0x59, 0x05, 0x27, 0x0f, 0x8a, 0xc0, 0x39, 0x94, 0x1a, 0x23, 0x5b, 0x66, 0x5b, 0xc0, 0x3c, 0x92, 0x15, 0x83, 0x5c, 0x92, 0x3f, 0x21, 0x00, 0x04, 0x80, 0x82, 0x3f, 0x00, 0x10, 0x01, 0x82, 0x03, 0xa8, 0x7b, 0x59, 0xa0, 0x27, 0x04, 0x88, 0xc0, 0x39, 0x9e, 0x15, 0xde, 0x59, 0xaa, 0x55, 0xa6, 0x5d, 0x19, 0x06, 0x3a, 0x38, 0x00, 0x67, 0xbe, 0x5f, 0xf1, 0x1e, 0xbe, 0x5f, 0xf3, 0x1e, 0x00, 0x67, 0x01, 0x66, 0xd0, 0x3e, 0xd0, 0x00, 0xd0, 0x3e, 0x1f, 0x00, 0xe3, 0x60, 0x19, 0x68, 0xe0, 0x39, 0x85, 0x29, 0x29, 0x5c, 0x14, 0x20, 0x87, 0x88, 0xe0, 0x38, 0x39, 0x15, 0x2f, 0x8c, +0x00, 0x17, 0x00, 0x61, 0x38, 0x49, 0x45, 0x98, 0x37, 0x9e, 0x95, 0x38, 0x4d, 0x1a, 0xbe, 0x58, 0x4d, 0x1a, 0xe0, 0x38, 0x85, 0x29, 0x09, 0x58, 0x00, 0x61, 0x1c, 0x69, 0x30, 0x22, 0x2c, 0x8a, 0x00, 0x58, 0x30, 0x22, 0x5b, 0x59, 0xe0, 0x3b, 0x13, 0x1c, 0xe0, 0x39, 0x43, 0x1c, 0x23, 0x59, 0x71, 0x13, 0x18, 0x13, 0x02, 0x94, 0x00, 0x63, 0x07, 0x9e, 0x21, 0x72, 0x23, 0x65, 0xa2, 0x40, 0x18, 0x00, 0x78, 0x48, 0x01, 0x9a, 0x01, 0x5b, 0xe0, 0x39, 0x51, 0x15, 0x7b, 0x59, 0xe0, 0x3b, 0x1f, 0x1c, 0xe0, 0x39, 0x4f, 0x1c, 0x23, 0x59, 0x71, 0x13, 0x18, 0x13, 0x02, 0x94, 0x00, 0x63, 0x07, 0x9e, 0x21, 0x72, 0x15, 0x65, 0xa2, 0x40, 0x18, 0x00, 0x78, 0x48, 0x01, 0x9a, 0x01, 0x5b, 0xe0, 0x39, 0x5d, 0x15, 0x7b, 0x59, 0xee, 0x9e, 0xe0, 0x38, 0x39, 0x15, 0x03, 0x58, 0xe0, 0x39, 0x51, 0x15, 0x41, 0xd8, 0x40, 0x17, 0x1b, 0x59, 0xe0, 0x38, 0x45, 0x15, 0x03, 0x58, 0xe0, 0x39, 0x5d, 0x15, 0x1b, 0x59, 0xe1, 0x9e, 0xe0, 0x38, 0xd2, 0x15, 0x38, 0x49, 0x22, 0x88, 0xd0, 0x71, 0x3b, 0x58, 0x80, 0x5c, 0x4c, 0x61, 0x1a, 0x69, 0x34, 0x20, 0x1b, 0x59, 0x00, 0x62, 0x80, 0x6a, 0xe0, 0x38, 0x51, 0x15, 0xe0, 0x39, 0x5d, 0x15, 0x5b, 0x58, 0x5b, 0x59, 0xe0, 0x38, 0x21, 0x15, 0xe0, 0x39, 0x2d, 0x15, 0xe0, 0x3b, 0x9a, 0x19, 0xe0, 0x3c, 0xa6, 0x19, 0x5b, 0x58, 0x5b, 0x59, 0x5b, 0x5b, 0x5b, 0x5c, 0xe0, 0x38, 0x2b, 0x1c, 0xe0, 0x39, 0x37, 0x1c, 0x5b, 0x58, 0x5b, 0x59, 0xbb, 0x9e, 0xe0, 0x38, 0x73, 0x1c, 0x03, 0x58, 0x39, 0x10, 0x05, 0x94, 0xe0, 0x38, 0x7f, 0x1c, 0x03, 0x58, 0x39, 0x10, 0x19, 0x96, 0xe0, 0x38, 0x9a, 0x19, 0x03, 0x58, 0xe0, 0x3b, 0xa6, 0x19, 0x63, 0x5b, 0xe0, 0x39, 0x51, 0x15, 0x98, 0x01, 0x80, 0x17, 0x1b, 0x59, 0xe0, 0x3d, 0x5d, 0x15, 0x7b, 0x5d, 0xa4, 0x9e, 0x94, 0x38, 0x4d, 0x1a, 0x16, 0x88, 0xe0, 0x38, 0x39, 0x15, 0x00, 0x61, 0x38, 0x49, 0x77, 0x9b, 0xe0, 0x38, 0xd2, 0x15, 0xd8, 0x49, 0xdd, 0x9b, 0xe0, 0x38, 0x21, 0x15, 0x03, 0x58, 0xe0, 0x39, 0x51, 0x15, 0x1b, 0x59, 0xe0, 0x38, 0x2d, 0x15, 0x03, 0x58, 0xe0, 0x39, 0x5d, 0x15, 0x1b, 0x59, 0x8b, 0x9e, 0x94, 0x3d, 0x84, 0x1a, 0x01, 0x88, 0x99, 0x9f, 0x00, 0x60, 0xe0, 0x39, 0x39, 0x15, 0x19, 0x49, 0x36, 0x9a, 0xe0, 0x38, 0x2b, 0x1c, 0x03, 0x58, 0xe0, 0x39, 0x21, 0x15, 0x30, 0x12, 0x01, 0x8c, 0x42, 0x5a, 0xe0, 0x38, 0x37, 0x1c, 0x03, 0x58, 0xe0, 0x39, 0x2d, 0x15, 0x30, 0x13, 0x01, 0x8c, 0x62, 0x5b, 0xd0, 0x75, 0xb0, 0x3d, 0x20, 0x00, 0xb0, 0x3d, 0xcf, 0x00, 0x19, 0x15, 0xe0, 0x38, 0xd2, 0x15, 0xb8, 0x49, 0x58, 0x3b, -0xc0, 0x17, 0x06, 0x88, 0xe0, 0x38, 0x73, 0x1c, 0x5b, 0x58, 0xe0, 0x38, 0x7f, 0x1c, 0x7b, 0x58, 0xe0, 0x38, 0x73, 0x1c, 0x03, 0x5a, 0xe0, 0x38, 0x7f, 0x1c, 0x03, 0x5b, 0x39, 0x12, 0x02, 0x94, 0x39, 0x13, 0xc0, 0x97, 0xe0, 0x39, 0x39, 0x15, 0xe0, 0x38, 0x9a, 0x19, 0x03, 0x58, 0x1b, 0x59, 0xe0, 0x3b, 0xa6, 0x19, 0x63, 0x5b, 0xe0, 0x39, 0x45, 0x15, 0x7b, 0x59, 0x32, 0xd9, 0x19, 0x00, 0x00, 0x61, 0x21, 0x75, 0x5f, 0x38, 0xa8, 0x5d, 0x1c, 0x5d, 0xe2, 0x39, 0x00, 0x00, 0x02, 0x88, 0xbe, 0x58, 0xf1, 0x1e, 0xe2, 0x39, 0x01, 0x00, 0x02, 0x88, 0xbe, 0x58, 0xf3, 0x1e, 0x16, 0x61, 0x01, 0x11, 0x0c, 0x94, 0x01, 0x61, 0x19, 0x48, 0x05, 0x9a, 0x01, 0x11, 0x20, 0x39, 0x07, 0x0b, 0x29, 0x5d, 0x07, 0x9e, 0x07, 0x65, 0x0b, 0x6d, 0xa9, 0x5d, 0x03, 0x9e, 0x1c, 0x65, 0x0b, 0x6d, 0xa9, 0x5d, 0x54, 0x05, +0xc0, 0x17, 0x06, 0x88, 0xe0, 0x38, 0x73, 0x1c, 0x5b, 0x58, 0xe0, 0x38, 0x7f, 0x1c, 0x7b, 0x58, 0xe0, 0x38, 0x73, 0x1c, 0x03, 0x5a, 0xe0, 0x38, 0x7f, 0x1c, 0x03, 0x5b, 0x39, 0x12, 0x02, 0x94, 0x39, 0x13, 0xc0, 0x97, 0xe0, 0x39, 0x39, 0x15, 0xe0, 0x38, 0x9a, 0x19, 0x03, 0x58, 0x1b, 0x59, 0xe0, 0x3b, 0xa6, 0x19, 0x63, 0x5b, 0xe0, 0x39, 0x45, 0x15, 0x7b, 0x59, 0x32, 0xd9, 0x19, 0x00, 0x00, 0x61, 0x21, 0x75, 0x5f, 0x38, 0xa8, 0x5d, 0x1c, 0x5d, 0xe2, 0x39, 0x00, 0x00, 0x02, 0x88, 0xbe, 0x58, 0xf1, 0x1e, 0xe2, 0x39, 0x01, 0x00, 0x02, 0x88, 0xbe, 0x58, 0xf3, 0x1e, 0x16, 0x61, 0x01, 0x11, 0x0c, 0x94, 0x01, 0x61, 0x19, 0x48, 0x05, 0x9a, 0x01, 0x11, 0x20, 0x39, 0x05, 0x0b, 0x29, 0x5d, 0x07, 0x9e, 0x05, 0x65, 0x0b, 0x6d, 0xa9, 0x5d, 0x03, 0x9e, 0x1a, 0x65, 0x0b, 0x6d, 0xa9, 0x5d, 0x4e, 0x05, 0x00, 0x18, 0x9e, 0x5a, 0xcd, 0x04, 0x42, 0x3a, 0x50, 0x00, 0x01, 0x96, 0x1a, 0x05, 0x9e, 0x5a, 0x20, 0x1d, 0x18, 0x12, 0x01, 0x8a, 0x1b, 0x05, 0xa2, 0x3a, 0x01, 0x00, 0x0d, 0x8a, 0xe0, 0x3a, 0x21, 0x15, 0xe0, 0x38, 0x39, 0x15, 0x03, 0x58, 0x2f, 0xd8, 0xe0, 0x3a, 0x2d, 0x15, 0xe0, 0x38, 0x45, 0x15, 0x03, 0x58, 0x58, 0xd8, 0x0e, 0x9e, 0x00, 0x61, 0x1e, 0x5e, 0x81, 0xd8, 0x3e, 0x5e, 0xe0, 0x39, 0x51, 0x15, 0x1b, 0x59, 0x01, 0x61, 0x1e, 0x5e, 0x81, 0xd8, 0x3e, 0x5e, 0xe0, 0x39, 0x5d, 0x15, 0x1b, 0x59, 0x19, 0x07, 0xf2, 0x39, 0x27, 0x00, 0x98, 0x3d, 0xf7, 0x16, 0x3a, 0x38, 0x1e, 0x5e, 0x1e, 0x58, 0x21, 0x71, 0x23, 0x63, 0x23, 0x40, 0x00, 0x3e, 0x00, 0x00, 0x3e, 0x58, 0xa2, 0x3b, 0x01, 0x00, 0x00, 0x61, 0x62, 0x49, 0x01, 0x5b, 0x1c, 0x5d, 0x01, 0x5c, 0x05, 0x40, 0x60, 0x10, 0x64, 0x1b, 0x40, 0x18, 0x0a, 0x8a, 0xd2, 0x39, 0x21, 0x00, 0xe0, 0x38, 0x39, 0x15, 0x03, 0x58, 0x19, 0x48, 0x03, 0x9a, 0x80, 0x10, 0x01, 0x98, 0x19, 0x04, 0x81, 0x58, 0x18, 0x10, 0x02, 0x94, 0x00, 0x60, 0x03, 0x9e, 0x1e, 0x48, 0x01, 0x9a, 0xc1, 0x58, 0xe0, 0x39, 0x51, 0x15, 0x1b, 0x59, 0x3e, 0x5e, 0x3a, 0x38, 0x1e, 0x5e, 0x1e, 0x58, 0x21, 0x71, 0x15, 0x63, 0x23, 0x40, 0x00, 0x3e, 0x00, 0x00, 0x3e, 0x58, 0xa2, 0x3b, 0x01, 0x00, 0x00, 0x61, 0x62, 0x49, 0x01, 0x5b, 0x1c, 0x5d, 0x01, 0x5c, 0x05, 0x40, 0x60, 0x10, 0x0a, 0x8a, 0xd2, 0x39, 0x21, 0x00, 0xe0, 0x38, 0x45, 0x15, 0x03, 0x58, 0x19, 0x48, 0x03, 0x9a, 0x80, 0x10, 0x01, 0x98, 0x19, 0x04, 0x81, 0x58, 0x18, 0x10, 0x02, 0x94, 0x00, 0x60, 0x03, 0x9e, 0x1e, 0x48, 0x01, 0x9a, 0xc1, 0x58, 0xe0, 0x39, 0x5d, 0x15, 0x1b, 0x59, 0x3e, 0x5e, 0x9b, 0x65, 0x80, 0x18, 0x3a, 0x38, 0x1e, 0x59, 0x14, 0x60, 0x1e, 0x58, 0xb0, 0xd8, 0x3e, 0x5b, 0xa3, 0x14, 0x10, 0x9a, 0x3e, 0x59, 0x01, 0xac, 0x05, 0x92, 0xe0, 0x3a, 0x21, 0x15, 0xe0, 0x38, 0x39, 0x15, 0x04, 0x9e, 0xe0, 0x3a, 0x2d, 0x15, 0xe0, 0x38, 0x45, 0x15, 0x80, 0x41, 0x62, 0x49, 0x1c, 0x5d, 0x17, 0x9e, 0x1e, 0x75, 0x3e, 0x59, 0x01, 0xac, 0x05, 0x92, 0xe0, 0x3a, 0x21, 0x15, 0xe0, 0x38, 0x39, 0x15, 0x04, 0x9e, 0xe0, 0x3a, 0x2d, 0x15, 0xe0, 0x38, 0x45, 0x15, 0xa2, 0x3b, 0x01, 0x00, 0x00, 0x61, 0x03, 0x58, 0x62, 0x49, 0x06, 0x58, 0x2a, 0x59, 0x1c, 0x5d, 0x19, 0x00, 0x08, 0x58, 0x3a, 0x38, 0xe0, 0x39, 0x21, 0x15, 0x00, 0x65, 0xb9, 0x49, 0x0d, 0x98, 0xe0, 0x38, 0x39, 0x15, 0x23, 0x59, 0x11, 0x12, 0xe0, 0x38, 0x45, 0x15, 0xe0, 0x39, 0x2d, 0x15, 0x23, 0x59, 0x11, 0x13, 0x5a, 0x40, 0x89, 0x98, @@ -96,7 +96,7 @@ 0xc0, 0x19, 0xff, 0x3a, 0x9d, 0x5b, 0x00, 0x64, 0x80, 0x6c, 0x8b, 0x63, 0x1c, 0x6b, 0xff, 0x3a, 0x9d, 0x5b, 0x00, 0x64, 0x80, 0x6c, 0x21, 0x63, 0x15, 0x6b, 0xff, 0x3a, 0x9d, 0x5b, 0x2b, 0x63, 0x1c, 0x6b, 0xff, 0x3a, 0x9d, 0x5b, 0x9e, 0x60, 0x15, 0x68, 0xff, 0x61, 0x7f, 0x69, 0x7f, 0x39, 0x3d, 0x58, 0xbe, 0x58, 0x85, 0x1a, 0x88, 0x61, 0x1a, 0x69, 0x7f, 0x39, 0x1d, 0x59, 0x94, 0x61, 0x1a, 0x69, 0x7f, 0x39, 0x1d, 0x59, 0x13, 0x67, 0x1c, 0x6f, 0x1f, 0x66, 0x1c, 0x6e, 0x00, 0x60, 0x80, 0x68, 0x6f, 0x39, 0xeb, 0x19, 0x1d, 0x5f, 0x1d, 0x5e, 0x00, 0x61, 0xbe, 0x59, 0x00, 0x1c, 0x00, 0x61, 0x7f, 0x69, 0xe6, 0x66, 0x1b, 0x6e, 0x3f, 0x39, 0x3d, 0x5e, 0x00, 0x61, 0xf0, 0x66, 0x1b, 0x6e, 0x3f, 0x39, 0x3d, 0x5e, 0x00, 0x61, 0x30, 0x60, 0x1d, 0x68, 0x04, 0x62, 0x57, 0x38, 0x3d, 0x58, 0xb0, 0x4e, 0x00, 0x1a, 0xa2, 0xf8, 0xf2, 0xdb, 0x3a, 0x38, 0x9e, 0x5f, 0xe2, 0x19, 0x19, 0x17, 0x45, 0x9a, 0x00, 0x67, 0xe0, 0x3d, 0xb2, 0x19, 0xa3, 0x5d, 0xe0, 0x3c, 0xbe, 0x19, 0x83, 0x5c, 0xe0, 0x3e, 0x01, 0x00, 0xc0, 0x3b, 0xb2, 0x19, 0x63, 0x5b, 0xa3, 0x13, 0x01, 0x8c, 0x62, 0x5b, 0x62, 0x3b, 0x40, 0x00, 0x2a, 0x98, 0xc0, 0x3b, 0xbe, 0x19, 0x63, 0x5b, 0x83, 0x13, 0x01, 0x8c, 0x62, 0x5b, 0x62, 0x3b, 0x40, 0x00, 0x21, 0x98, 0xe0, 0x3c, 0xbe, 0x19, 0xc0, 0x3d, 0xbe, 0x19, 0xa3, 0x59, 0x91, 0x01, 0x28, 0x5b, 0x7b, 0x5c, 0xe0, 0x3c, 0xb2, 0x19, 0xc0, 0x3a, 0xb2, 0x19, 0x43, 0x59, 0x91, 0x01, 0x28, 0x5b, 0x7b, 0x5c, 0x9e, 0x59, 0xe2, 0x19, 0x19, 0x11, 0x20, 0x3c, 0xbe, 0x19, 0x83, 0x5c, 0x9b, 0x5d, 0x20, 0x3c, 0xb2, 0x19, 0x83, 0x5c, 0x9b, 0x5a, 0xbe, 0x59, 0xe2, 0x19, 0x22, 0x38, 0xc9, 0x2a, 0x40, 0x1a, 0x01, 0x00, 0x0a, 0x9a, 0xcd, 0x9f, 0x19, 0x06, 0xd2, 0x39, 0xe2, 0x19, 0xc9, 0x97, 0x19, 0x07, 0xf2, 0x38, 0xe2, 0x19, 0x19, 0x00, 0xbc, 0x97, 0x3a, 0x38, 0x9e, 0x5f, 0xe2, 0x19, 0x18, 0x17, 0x19, 0x8a, 0x23, 0x66, 0x21, 0x75, 0xa6, 0x40, 0x00, 0x3e, 0x00, 0x00, 0x15, 0x64, 0xa4, 0x40, 0x00, 0x3d, 0x00, 0x00, 0x19, 0x17, 0xe7, 0x38, 0x69, 0x1a, 0xe0, 0x38, 0xbe, 0x19, 0x03, 0x5a, 0xe0, 0x39, 0xb2, 0x19, 0x23, 0x5b, 0xe0, 0x38, 0xb2, 0x19, 0x5b, 0x58, 0xe0, 0x39, 0xbe, 0x19, 0x7b, 0x59, 0x19, 0x17, 0x3a, 0x38, 0xe0, 0x3b, 0x1a, 0x16, 0x63, 0x5e, 0xe0, 0x3b, 0xde, 0x15, 0x63, 0x5d, 0x00, 0x64, 0x1e, 0x5d, 0xa0, 0x38, 0x48, 0x0e, 0x9e, 0x5b, 0xfd, 0x1b, 0x66, 0x48, 0x98, 0x49, 0x01, 0x94, 0x03, 0x5c, 0xe0, 0x3b, 0xf2, 0x15, 0x75, 0x33, 0x03, 0x8a, 0x19, 0x00, 0x9a, 0xa3, -0x80, 0x1a, 0x19, 0x05, 0xf6, 0x9f, 0x3e, 0x5d, 0xe0, 0x3b, 0x06, 0x16, 0x76, 0x33, 0x02, 0x8a, 0x19, 0x06, 0xe9, 0x9f, 0x3a, 0x38, 0x9e, 0x5f, 0xe4, 0x19, 0xf2, 0x38, 0x27, 0x00, 0x90, 0x94, 0x00, 0x65, 0xe0, 0x3e, 0x63, 0x29, 0xc9, 0x5e, 0xd4, 0x3b, 0xe3, 0x19, 0x85, 0x8a, 0xc0, 0x5e, 0xd4, 0x3b, 0xe3, 0x19, 0xbe, 0x5b, 0xe3, 0x19, 0xb2, 0x38, 0xe4, 0x19, 0x7d, 0x94, 0xa0, 0x3e, 0x63, 0x29, 0xc9, 0x5e, 0xd4, 0x3e, 0xe3, 0x19, 0x75, 0x88, 0xe0, 0x3e, 0x39, 0x15, 0xa0, 0x3c, 0x39, 0x15, 0x20, 0xdb, 0xe0, 0x3e, 0x45, 0x15, 0xa0, 0x3c, 0x45, 0x15, 0x20, 0xdb, 0xe0, 0x3e, 0x9a, 0x19, 0xa0, 0x3c, 0x9a, 0x19, 0x20, 0xdb, 0xe0, 0x3e, 0xa6, 0x19, 0xa0, 0x3c, 0xa6, 0x19, 0x20, 0xdb, 0xe0, 0x3e, 0x51, 0x15, 0xa0, 0x3c, 0x51, 0x15, 0x20, 0xdb, 0xe0, 0x3e, 0x5d, 0x15, 0xa0, 0x3c, 0x18, 0x3f, +0x80, 0x1a, 0x19, 0x05, 0xf6, 0x9f, 0x3e, 0x5d, 0xe0, 0x3b, 0x06, 0x16, 0x76, 0x33, 0x02, 0x8a, 0x19, 0x06, 0xe9, 0x9f, 0x3a, 0x38, 0x9e, 0x5f, 0xe4, 0x19, 0xf2, 0x38, 0x27, 0x00, 0x90, 0x94, 0x00, 0x65, 0xe0, 0x3e, 0x85, 0x29, 0xc9, 0x5e, 0xd4, 0x3b, 0xe3, 0x19, 0x85, 0x8a, 0xc0, 0x5e, 0xd4, 0x3b, 0xe3, 0x19, 0xbe, 0x5b, 0xe3, 0x19, 0xb2, 0x38, 0xe4, 0x19, 0x7d, 0x94, 0xa0, 0x3e, 0x85, 0x29, 0xc9, 0x5e, 0xd4, 0x3e, 0xe3, 0x19, 0x75, 0x88, 0xe0, 0x3e, 0x39, 0x15, 0xa0, 0x3c, 0x39, 0x15, 0x20, 0xdb, 0xe0, 0x3e, 0x45, 0x15, 0xa0, 0x3c, 0x45, 0x15, 0x20, 0xdb, 0xe0, 0x3e, 0x9a, 0x19, 0xa0, 0x3c, 0x9a, 0x19, 0x20, 0xdb, 0xe0, 0x3e, 0xa6, 0x19, 0xa0, 0x3c, 0xa6, 0x19, 0x20, 0xdb, 0xe0, 0x3e, 0x51, 0x15, 0xa0, 0x3c, 0x51, 0x15, 0x20, 0xdb, 0xe0, 0x3e, 0x5d, 0x15, 0xa0, 0x3c, 0x5c, 0x3f, 0xc0, 0x1a, 0x5d, 0x15, 0x20, 0xdb, 0xe0, 0x3e, 0x21, 0x15, 0xa0, 0x3c, 0x21, 0x15, 0x20, 0xdb, 0xe0, 0x3e, 0x2d, 0x15, 0xa0, 0x3c, 0x2d, 0x15, 0x20, 0xdb, 0xe0, 0x3e, 0xd2, 0x15, 0xa0, 0x3c, 0xd2, 0x15, 0x20, 0xdb, 0xe0, 0x3e, 0x2b, 0x1c, 0xa0, 0x3c, 0x2b, 0x1c, 0x20, 0xdb, 0xe0, 0x3e, 0x37, 0x1c, 0xa0, 0x3c, 0x37, 0x1c, 0x20, 0xdb, 0xe0, 0x3e, 0x43, 0x1c, 0xa0, 0x3c, 0x43, 0x1c, 0x20, 0xdb, 0xe0, 0x3e, 0x4f, 0x1c, 0xa0, 0x3c, 0x4f, 0x1c, 0x20, 0xdb, 0xe0, 0x3e, 0x5b, 0x1c, 0xa0, 0x3c, 0x5b, 0x1c, 0x20, 0xdb, 0xe0, 0x3e, 0x67, 0x1c, 0xa0, 0x3c, 0x67, 0x1c, 0x20, 0xdb, 0xe0, 0x3e, 0x07, 0x1c, 0xa0, 0x3c, 0x07, 0x1c, 0x20, 0xdb, 0xe0, 0x3e, 0x73, 0x1c, 0xa0, 0x3c, 0x73, 0x1c, 0x20, 0xdb, 0xe0, 0x3e, 0x7f, 0x1c, 0xa0, 0x3c, 0x7f, 0x1c, 0x20, 0xdb, 0xe0, 0x3e, 0x88, 0x1a, 0xc3, 0xf1, 0x00, 0x1b, 0xa0, 0x3c, 0x88, 0x1a, 0x20, 0xdb, 0xe0, 0x3e, 0x94, 0x1a, 0xa0, 0x3c, 0x94, 0x1a, 0x20, 0xdb, 0xe0, 0x3e, 0xa0, 0x1a, 0xa0, 0x3c, 0xa0, 0x1a, 0x20, 0xdb, 0xe0, 0x3e, 0x92, 0x15, 0xa0, 0x3c, 0x92, 0x15, 0x20, 0xdb, 0xe0, 0x3e, 0x9e, 0x15, 0xa0, 0x3c, 0x9e, 0x15, 0x20, 0xdb, 0x19, 0x05, 0x02, 0x9e, 0x19, 0x05, 0x80, 0x9f, 0x19, 0x07, 0xf2, 0x38, 0x27, 0x00, 0x71, 0x97, 0x3a, 0x38, 0xc3, 0x5b, 0x83, 0x5a, 0x7b, 0x5c, 0x5b, 0x5e, 0x3a, 0x38, 0x00, 0x67, 0x00, 0x61, 0xe0, 0x38, 0x9a, 0x19, 0x38, 0x49, 0xa4, 0x98, 0xe0, 0x38, 0x39, 0x15, 0x38, 0x49, 0xa0, 0x98, 0x27, 0x76, 0x19, 0x16, 0xdf, 0x48, 0x9a, 0x8a, 0x00, 0x61, 0xc0, 0x38, 0x9a, 0x19, 0x38, 0x49, 0x95, 0x98, 0xc0, 0x38, 0x39, 0x15, 0x38, 0x49, 0x91, 0x98, 0xe0, 0x3a, 0x9a, 0x19, 0xe0, 0x3b, 0x39, 0x15, 0xf3, 0x5f, 0x40, 0x1b, 0x63, 0x5b, 0x53, 0x12, 0xe0, 0x3b, 0xa6, 0x19, 0xe0, 0x3c, 0x45, 0x15, 0x83, 0x5c, 0x74, 0x13, 0xc0, 0x3c, 0x9a, 0x19, 0xe0, 0x3d, 0x39, 0x15, 0xa3, 0x5d, 0x95, 0x14, 0xc0, 0x3d, 0xa6, 0x19, 0xe0, 0x38, 0x45, 0x15, 0x03, 0x58, 0xb0, 0x15, 0x5d, 0x40, 0x6c, 0x48, 0x21, 0x5c, 0xc0, 0x3d, 0x39, 0x15, 0xe0, 0x39, 0x39, 0x15, 0x23, 0x59, 0xb1, 0x15, 0xc0, 0x38, 0x45, 0x15, 0xe0, 0x39, 0x45, 0x15, 0x23, 0x59, 0x11, 0x10, 0x58, 0x40, 0x6d, 0x48, 0x81, 0x31, 0x79, 0xac, 0x65, 0x90, 0xc0, 0x3a, 0x9a, 0x19, 0xc0, 0x3b, 0x39, 0x15, 0x63, 0x5b, 0x53, 0x12, 0xc0, 0x3b, 0xa6, 0x19, 0xc0, 0x3c, 0x45, 0x15, 0x83, 0x5c, 0x74, 0x13, 0xe0, 0x3c, 0x9a, 0x19, 0xc0, 0x3d, 0x39, 0x15, 0xa3, 0x5d, 0x95, 0x14, 0xe0, 0x3d, 0xa6, 0x19, 0xc0, 0x38, 0x45, 0x15, 0x03, 0x58, 0xb0, 0x15, 0x27, 0x1c, @@ -134,50 +134,50 @@ 0x40, 0x23, 0x60, 0x11, 0x83, 0x5a, 0xff, 0x63, 0xff, 0x6b, 0xbe, 0x5b, 0x60, 0x1a, 0x00, 0x63, 0x5b, 0x48, 0x14, 0x88, 0x9e, 0x5d, 0x60, 0x1a, 0xa4, 0x3d, 0xff, 0x7f, 0xbe, 0x5d, 0x60, 0x1a, 0x41, 0x59, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x00, 0x62, 0x10, 0x6a, 0x3a, 0x48, 0x02, 0x9c, 0x00, 0x61, 0x10, 0x69, 0x5e, 0x14, 0x19, 0x14, 0x83, 0x5a, 0x22, 0x01, 0x5b, 0x48, 0x06, 0x88, 0x9e, 0x5d, 0x60, 0x1a, 0xa4, 0x3d, 0x7f, 0xff, 0xbe, 0x5d, 0x60, 0x1a, 0x19, 0x04, 0x83, 0x5a, 0x22, 0x01, 0x22, 0x01, 0x5b, 0x48, 0x06, 0x88, 0x9e, 0x5d, 0x60, 0x1a, 0xa4, 0x3d, 0xbf, 0xff, 0xbe, 0x5d, 0x60, 0x1a, 0x5e, 0x14, 0x83, 0x5a, 0x5b, 0x48, 0x06, 0x88, 0x9e, 0x5d, 0x60, 0x1a, 0xa4, 0x3d, 0xff, 0xfe, 0xbe, 0x5d, 0x60, 0x1a, 0x5e, 0x04, 0xd3, 0xe2, 0x80, 0x23, 0x19, 0x04, 0x83, 0x5a, 0x22, 0x01, 0x5b, 0x48, 0x06, 0x88, 0x9e, 0x5d, 0x60, 0x1a, 0xa4, 0x3d, 0xdf, 0xff, 0xbe, 0x5d, 0x60, 0x1a, 0x5e, 0x04, 0x83, 0x5a, 0x22, 0x01, 0x22, 0x01, 0x5b, 0x48, 0x06, 0x88, 0x9e, 0x5d, 0x60, 0x1a, 0xa4, 0x3d, 0xf7, 0xff, 0xbe, 0x5d, 0x60, 0x1a, 0x19, 0x04, 0x83, 0x5a, 0x5b, 0x48, 0x06, 0x88, 0x9e, 0x5d, 0x60, 0x1a, 0xa4, 0x3d, 0xff, 0xf7, 0xbe, 0x5d, 0x60, 0x1a, 0x19, 0x14, 0x1a, 0x14, 0x83, 0x5a, 0x22, 0x01, 0x22, 0x01, 0x5b, 0x48, 0x06, 0x88, 0x9e, 0x5d, 0x60, 0x1a, 0xa4, 0x3d, 0xef, 0xff, 0xbe, 0x5d, 0x60, 0x1a, 0x19, 0x14, 0x83, 0x5a, 0x5b, 0x48, 0x06, 0x88, 0x9e, 0x5d, 0x60, 0x1a, 0xa4, 0x3d, 0xff, 0xfb, 0xbe, 0x5d, 0x60, 0x1a, 0x19, 0x04, 0x5e, 0x04, 0x83, 0x5a, 0x22, 0x01, 0x5b, 0x48, 0x06, 0x88, 0x9e, 0x5d, 0x60, 0x1a, 0x78, 0xcd, 0xc0, 0x23, 0xa4, 0x3d, 0xfb, 0xff, 0xbe, 0x5d, 0x60, 0x1a, 0x19, 0x04, 0x83, 0x5a, 0x22, 0x01, 0x22, 0x01, 0x5b, 0x48, 0x06, 0x88, 0x9e, 0x5d, 0x60, 0x1a, 0xa4, 0x3d, 0xfd, 0xff, 0xbe, 0x5d, 0x60, 0x1a, 0x5e, 0x04, 0x83, 0x5a, 0x5b, 0x48, 0x06, 0x88, 0x9e, 0x5d, 0x60, 0x1a, 0xa4, 0x3d, 0xff, 0xfd, 0xbe, 0x5d, 0x60, 0x1a, 0x5e, 0x14, 0x19, 0x04, 0x83, 0x5a, 0x22, 0x01, 0x5b, 0x48, 0x06, 0x88, 0x9e, 0x5d, 0x60, 0x1a, 0xa4, 0x3d, 0xfe, 0xff, 0xbe, 0x5d, 0x60, 0x1a, 0x1e, 0x58, 0x08, 0x65, 0x21, 0x58, 0x00, 0x61, 0x1c, 0x5d, 0x01, 0x59, 0x3e, 0x58, 0x00, 0x65, 0xbe, 0x5d, 0x61, 0x1a, 0x9e, 0x5d, 0x60, 0x1a, 0x35, 0xac, 0x02, 0x92, 0x45, 0xac, 0x0d, 0x90, 0x0d, 0xac, 0x02, 0x92, 0x4d, 0xac, 0x09, 0x90, 0x25, 0xac, 0x02, 0x92, 0x55, 0xac, 0x05, 0x90, 0x1d, 0xac, 0x06, 0x92, 0x08, 0x8d, -0x00, 0x24, 0x5d, 0xac, 0x01, 0x90, 0x03, 0x9e, 0x01, 0x65, 0xbe, 0x5d, 0x61, 0x1a, 0x9e, 0x5c, 0x02, 0x1d, 0x19, 0x04, 0xbe, 0x5c, 0x02, 0x1d, 0x00, 0x3c, 0x48, 0x0e, 0x83, 0x5b, 0x9e, 0x5d, 0x61, 0x1a, 0x05, 0xac, 0x0c, 0x92, 0x61, 0x12, 0x7a, 0xac, 0x09, 0x90, 0x3b, 0x5c, 0x01, 0x62, 0xbe, 0x5a, 0x62, 0x1a, 0x9e, 0x5a, 0x03, 0x1d, 0x19, 0x02, 0xbe, 0x5a, 0x03, 0x1d, 0x3e, 0x5b, 0x19, 0x13, 0x00, 0x62, 0x62, 0x14, 0x0e, 0x89, 0x3e, 0x5f, 0x3e, 0x5e, 0x3e, 0x5d, 0x3e, 0x5c, 0x3a, 0x38, 0x1e, 0x58, 0x1e, 0x59, 0x1e, 0x5a, 0x1e, 0x5b, 0x1e, 0x5c, 0x1e, 0x5d, 0x1e, 0x5e, 0x1e, 0x5f, 0x72, 0x62, 0x19, 0x6a, 0x86, 0x63, 0x19, 0x6b, 0x00, 0x60, 0xbe, 0x58, 0x71, 0x1a, 0x00, 0x67, 0x00, 0x60, 0x9e, 0x59, 0x58, 0x1a, 0x38, 0x48, 0x33, 0x8a, 0x19, 0x11, 0x27, 0x38, 0x6f, 0x24, 0xe2, 0x85, -0x40, 0x24, 0x40, 0x04, 0x83, 0x5d, 0x48, 0x64, 0x1d, 0x6c, 0x85, 0x04, 0x83, 0x5d, 0x15, 0x66, 0xbe, 0x48, 0x09, 0x82, 0x19, 0x04, 0x83, 0x5d, 0xbe, 0x48, 0x05, 0x82, 0x1a, 0x14, 0x83, 0x5d, 0xbe, 0x48, 0x01, 0x82, 0x13, 0x9e, 0x60, 0x04, 0x83, 0x5d, 0x48, 0x64, 0x1d, 0x6c, 0x85, 0x04, 0x90, 0x3c, 0xb8, 0x00, 0x83, 0x5d, 0x15, 0x66, 0xbe, 0x48, 0x10, 0x82, 0x19, 0x04, 0x83, 0x5d, 0xbe, 0x48, 0x0c, 0x82, 0x1a, 0x14, 0x83, 0x5d, 0xbe, 0x48, 0x08, 0x82, 0x19, 0x07, 0xbe, 0x5f, 0x71, 0x1a, 0x72, 0x65, 0x1a, 0x6d, 0xa7, 0x06, 0x19, 0x16, 0x1b, 0x5e, 0x1a, 0x38, 0x1a, 0x38, 0x19, 0x00, 0x3e, 0x5f, 0x3e, 0x5e, 0x3e, 0x5d, 0x3e, 0x5c, 0x3e, 0x5b, 0x3e, 0x5a, 0x3e, 0x59, 0x3e, 0x58, 0x3a, 0x38, 0x00, 0x67, 0xdf, 0x60, 0x1e, 0x68, 0x2f, 0x39, 0x80, 0x24, 0xfd, 0x58, 0x1a, 0x38, 0x47, 0xcf, -0x80, 0x24, 0x1a, 0x38, 0x00, 0x67, 0x50, 0x65, 0x04, 0x6d, 0x9e, 0x5c, 0xb8, 0x00, 0x9e, 0x5e, 0xb9, 0x00, 0x86, 0x04, 0x19, 0x14, 0x87, 0x38, 0x8e, 0x24, 0xfd, 0x5d, 0x1a, 0x38, 0x1a, 0x38, 0xbe, 0x5f, 0xdb, 0x1e, 0xbe, 0x5f, 0xdc, 0x1e, 0x9e, 0x58, 0x4d, 0x04, 0x9e, 0x59, 0x4f, 0x04, 0x01, 0x00, 0x02, 0x3a, 0xb0, 0x00, 0x01, 0x98, 0x3a, 0x38, 0x00, 0x61, 0x9e, 0x58, 0x4d, 0x04, 0x9e, 0x5a, 0xdd, 0x1e, 0x1c, 0x5a, 0x02, 0x39, 0x20, 0x00, 0x01, 0x98, 0x20, 0x60, 0x00, 0x61, 0x01, 0x62, 0x00, 0x67, 0x50, 0x65, 0x04, 0x6d, 0x48, 0x63, 0x1d, 0x6b, 0x9e, 0x5c, 0xb8, 0x00, 0x19, 0x14, 0x87, 0x38, 0xc9, 0x24, 0x65, 0x5c, 0x98, 0x48, 0x06, 0x80, 0x5b, 0x5d, 0xbe, 0x5a, 0xdb, 0x1e, 0x19, 0x01, 0x01, 0x67, 0x0e, 0x9e, 0x07, 0xac, 0x0c, 0x90, 0x1e, 0x5d, 0x40, 0x3d, 0xdf, 0x1e, 0x26, 0xad, -0xc0, 0x24, 0x19, 0x15, 0x50, 0x48, 0x08, 0x00, 0x01, 0x8a, 0x3b, 0x5d, 0x3e, 0x5d, 0x00, 0x61, 0x00, 0x67, 0x19, 0x02, 0x19, 0x05, 0x1e, 0x5d, 0x40, 0x3d, 0xdf, 0x1e, 0x19, 0x15, 0x50, 0x48, 0x08, 0x00, 0x01, 0x8a, 0x3b, 0x5d, 0x3e, 0x5d, 0x00, 0x61, 0x9e, 0x58, 0x4f, 0x04, 0x9e, 0x5a, 0xdd, 0x1e, 0x1c, 0x5a, 0x02, 0x39, 0x20, 0x00, 0x01, 0x98, 0x20, 0x60, 0x00, 0x61, 0x01, 0x62, 0x00, 0x67, 0x50, 0x65, 0x04, 0x6d, 0x48, 0x63, 0x1d, 0x6b, 0x9e, 0x5c, 0xb8, 0x00, 0xa4, 0x05, 0x64, 0x03, 0x9e, 0x5c, 0xb9, 0x00, 0x19, 0x14, 0x87, 0x38, 0x09, 0x25, 0x65, 0x5c, 0x98, 0x48, 0x06, 0x80, 0x5b, 0x5d, 0xbe, 0x5a, 0xdc, 0x1e, 0x19, 0x01, 0x01, 0x67, 0x13, 0x9e, 0x07, 0xac, 0x11, 0x90, 0x1e, 0x5d, 0x1e, 0x5e, 0x40, 0x3d, 0xdf, 0x1e, 0x19, 0x15, 0x50, 0x48, 0x08, 0x00, 0x04, 0x8a, 0xf1, 0xf0, -0x00, 0x25, 0xa3, 0x5e, 0xfe, 0x59, 0xc1, 0x06, 0xdb, 0x5d, 0x3e, 0x5e, 0x3e, 0x5d, 0x00, 0x61, 0x00, 0x67, 0x19, 0x02, 0x19, 0x05, 0x1e, 0x5d, 0x1e, 0x5e, 0x40, 0x3d, 0xdf, 0x1e, 0x19, 0x15, 0x50, 0x48, 0x08, 0x00, 0x04, 0x8a, 0xa3, 0x5e, 0xfe, 0x59, 0xc1, 0x06, 0xdb, 0x5d, 0x3e, 0x5e, 0x3e, 0x5d, 0x00, 0x60, 0xbe, 0x58, 0xe8, 0x1e, 0xbe, 0x58, 0xe7, 0x1e, 0xdf, 0x62, 0x1e, 0x6a, 0x01, 0x67, 0xef, 0x38, 0x2a, 0x25, 0x45, 0x5b, 0x64, 0x3b, 0xff, 0x00, 0x78, 0x48, 0x02, 0x96, 0x61, 0x58, 0xe1, 0x5c, 0x19, 0x07, 0x1a, 0x38, 0xbe, 0x5c, 0xe7, 0x1e, 0xdf, 0x62, 0x1e, 0x6a, 0x01, 0x67, 0x00, 0x60, 0xef, 0x38, 0x3c, 0x25, 0x45, 0x5b, 0xfe, 0x5b, 0x64, 0x3b, 0xff, 0x00, 0x78, 0x48, 0x02, 0x96, 0x61, 0x58, 0xe1, 0x5d, 0x19, 0x07, 0x1a, 0x38, 0xbe, 0x5d, 0xe8, 0x1e, 0x7a, 0x60, 0xf0, 0x02, -0x40, 0x25, 0x02, 0x68, 0x50, 0x61, 0x04, 0x69, 0x39, 0x62, 0x47, 0x38, 0x49, 0x25, 0x23, 0x5b, 0x7b, 0x58, 0x19, 0x01, 0x19, 0x00, 0x3a, 0x38, 0x92, 0x62, 0xf8, 0x6a, 0x00, 0x64, 0x17, 0x63, 0x67, 0x38, 0x53, 0x25, 0x45, 0x5b, 0x83, 0x04, 0x1a, 0x38, 0xfe, 0x5c, 0x84, 0x3c, 0x00, 0xff, 0x9e, 0x5f, 0x34, 0x1d, 0xe0, 0x3b, 0x30, 0x1d, 0x9e, 0x59, 0xb5, 0x00, 0x24, 0x29, 0x3b, 0x5b, 0x30, 0x63, 0x1d, 0x6b, 0x00, 0x60, 0xbe, 0x58, 0x36, 0x1d, 0x04, 0x65, 0x19, 0x15, 0xa7, 0x38, 0x6c, 0x25, 0x63, 0x5e, 0xc4, 0x3e, 0xff, 0x00, 0x06, 0x00, 0x19, 0x03, 0x19, 0x05, 0x00, 0x61, 0x1c, 0x5d, 0xbe, 0x58, 0x35, 0x1d, 0x30, 0x63, 0x1d, 0x6b, 0x04, 0x65, 0x19, 0x15, 0xa7, 0x38, 0x7d, 0x25, 0x63, 0x5e, 0xc4, 0x3e, 0x00, 0xff, 0xfe, 0x5e, 0x06, 0x00, 0x19, 0x03, 0x19, 0x05, 0x00, 0x61, 0x85, 0x3d, -0x80, 0x25, 0x1c, 0x5d, 0x01, 0x5b, 0xbe, 0x58, 0xbc, 0x1d, 0x9e, 0x58, 0x35, 0x1d, 0x19, 0x07, 0xe2, 0x3a, 0x04, 0x00, 0x01, 0x88, 0x00, 0x67, 0xbe, 0x5f, 0x34, 0x1d, 0x01, 0x61, 0x9e, 0x5a, 0xb1, 0x04, 0x42, 0x3f, 0x01, 0x00, 0x11, 0x8a, 0x01, 0x61, 0x02, 0x3f, 0x04, 0x00, 0x0d, 0x9a, 0x04, 0x61, 0x02, 0x3f, 0x06, 0x00, 0x09, 0x9a, 0x02, 0x61, 0x02, 0x3f, 0x08, 0x00, 0x05, 0x9a, 0x03, 0x61, 0x02, 0x3f, 0x0a, 0x00, 0x01, 0x9a, 0x01, 0x61, 0xbe, 0x59, 0x36, 0x1d, 0x1a, 0x38, 0x3a, 0x38, 0x1e, 0x58, 0x1e, 0x59, 0x1e, 0x5a, 0x1e, 0x5b, 0x1e, 0x5d, 0x1e, 0x5e, 0x1e, 0x5f, 0x00, 0x63, 0x00, 0x65, 0x9c, 0x60, 0x1e, 0x68, 0x9e, 0x59, 0xb8, 0x00, 0x19, 0x11, 0x27, 0x38, 0xbd, 0x25, 0x03, 0x5a, 0x5b, 0x48, 0x01, 0x96, 0x41, 0x5b, 0x19, 0x00, 0x1a, 0x38, 0xbe, 0x5b, 0x60, 0x1e, 0xe3, 0x52, -0xc0, 0x25, 0x9e, 0x59, 0xb9, 0x00, 0x19, 0x11, 0x27, 0x38, 0xca, 0x25, 0x03, 0x5a, 0x5d, 0x48, 0x01, 0x96, 0x41, 0x5d, 0x19, 0x00, 0x1a, 0x38, 0xbe, 0x5d, 0x5f, 0x1e, 0x10, 0x64, 0x65, 0x02, 0x50, 0x48, 0x00, 0x01, 0x0b, 0x80, 0x61, 0x58, 0x7d, 0x48, 0x01, 0x98, 0xa1, 0x58, 0x01, 0x5c, 0x00, 0x61, 0x07, 0x62, 0x82, 0x40, 0x0a, 0x62, 0x1c, 0x5a, 0x01, 0x5c, 0xbe, 0x5c, 0x61, 0x1e, 0x3e, 0x5f, 0x3e, 0x5e, 0x3e, 0x5d, 0x3e, 0x5b, 0x3e, 0x5a, 0x3e, 0x59, 0x3e, 0x58, 0x3a, 0x38, 0x9e, 0x58, 0xf1, 0x04, 0x9e, 0x59, 0xf2, 0x04, 0x01, 0x00, 0x10, 0x48, 0x05, 0x00, 0x18, 0x3e, 0x34, 0x27, 0x9e, 0x58, 0xdb, 0x1e, 0x10, 0x48, 0x02, 0x00, 0x18, 0x3e, 0x34, 0x27, 0x9e, 0x59, 0xdc, 0x1e, 0x30, 0x48, 0x02, 0x00, 0x18, 0x3e, 0x34, 0x27, 0x9e, 0x58, 0x45, 0x04, 0x02, 0x38, 0x50, 0x01, 0xa4, 0xf1, -0x00, 0x26, 0x3d, 0x98, 0xdf, 0x60, 0x1e, 0x68, 0x05, 0x59, 0x24, 0x3a, 0xff, 0x00, 0xfe, 0x59, 0x24, 0x3b, 0xff, 0x00, 0x43, 0x06, 0x03, 0x59, 0x24, 0x3c, 0xff, 0x00, 0xfe, 0x59, 0x24, 0x3d, 0xff, 0x00, 0x85, 0x07, 0xc7, 0x00, 0x38, 0x10, 0x2a, 0x98, 0xd0, 0x48, 0x06, 0x00, 0x27, 0x98, 0xf0, 0x48, 0x06, 0x00, 0x24, 0x98, 0x45, 0x00, 0x10, 0x48, 0x06, 0x00, 0x20, 0x98, 0x64, 0x00, 0x10, 0x48, 0x06, 0x00, 0x1c, 0x98, 0x9e, 0x58, 0x4d, 0x04, 0x9e, 0x59, 0x4f, 0x04, 0x19, 0x48, 0x01, 0x98, 0x21, 0x58, 0x9e, 0x59, 0x44, 0x04, 0x19, 0x48, 0x10, 0x80, 0x9e, 0x58, 0xf1, 0x04, 0x19, 0x10, 0x04, 0x88, 0x9e, 0x58, 0x8a, 0x04, 0x1a, 0x10, 0x09, 0x98, 0x9e, 0x58, 0xf2, 0x04, 0x19, 0x10, 0x04, 0x88, 0x9e, 0x58, 0x8b, 0x04, 0x1a, 0x10, 0x01, 0x98, 0xf5, 0x9e, 0x9e, 0x59, 0x4e, 0x04, 0xca, 0x25, -0x40, 0x26, 0x30, 0x48, 0x00, 0x00, 0x84, 0x8a, 0x9e, 0x59, 0x4e, 0x04, 0x30, 0x48, 0x23, 0x00, 0x7f, 0x8a, 0x9e, 0x59, 0x4c, 0x04, 0x30, 0x48, 0x00, 0x00, 0x7a, 0x8a, 0x9e, 0x59, 0x4c, 0x04, 0x30, 0x48, 0x15, 0x00, 0x75, 0x8a, 0x9e, 0x58, 0x46, 0x04, 0x9e, 0x59, 0x47, 0x04, 0x01, 0x00, 0x02, 0x38, 0x40, 0x00, 0x08, 0x98, 0x9e, 0x58, 0xdb, 0x1e, 0x9e, 0x59, 0xdc, 0x1e, 0x01, 0x00, 0x02, 0x39, 0x02, 0x00, 0x12, 0x8a, 0x9e, 0x58, 0x46, 0x04, 0x38, 0x10, 0x61, 0x98, 0x9e, 0x58, 0xdb, 0x1e, 0x9e, 0x59, 0xdc, 0x1e, 0x01, 0x00, 0x1b, 0x10, 0x5a, 0x88, 0x9e, 0x58, 0xf1, 0x04, 0x9e, 0x59, 0xf2, 0x04, 0x01, 0x10, 0x54, 0x8a, 0x22, 0x9e, 0x80, 0x60, 0x01, 0x68, 0xbe, 0x58, 0x20, 0x1d, 0x9e, 0x58, 0x4d, 0x04, 0x9e, 0x59, 0x4f, 0x04, 0x19, 0x48, 0x01, 0x9a, 0x21, 0x58, 0xbe, 0x58, 0xb4, 0xd7, -0x80, 0x26, 0x14, 0x1f, 0x36, 0xe7, 0x00, 0x63, 0xbe, 0x5b, 0x0e, 0x1f, 0xbe, 0x5b, 0x10, 0x1f, 0x9e, 0x5b, 0xb8, 0x00, 0x19, 0x13, 0xbe, 0x5b, 0x0f, 0x1f, 0x9e, 0x5b, 0xb9, 0x00, 0x19, 0x13, 0xbe, 0x5b, 0x11, 0x1f, 0x01, 0x60, 0x01, 0x61, 0x5c, 0xe7, 0x98, 0xe2, 0x9d, 0x9e, 0x9e, 0x58, 0x46, 0x04, 0x9e, 0x59, 0x47, 0x04, 0x19, 0x48, 0x97, 0x98, 0x68, 0x60, 0x01, 0x68, 0xbe, 0x58, 0x20, 0x1d, 0x76, 0xde, 0x9e, 0x58, 0x4d, 0x04, 0x9e, 0x59, 0x4f, 0x04, 0x19, 0x48, 0x01, 0x9a, 0x21, 0x58, 0x08, 0x58, 0xbe, 0x58, 0x14, 0x1f, 0x00, 0x63, 0xbe, 0x5b, 0x0e, 0x1f, 0xbe, 0x5b, 0x10, 0x1f, 0x9e, 0x5b, 0xb8, 0x00, 0x19, 0x13, 0xbe, 0x5b, 0x0f, 0x1f, 0x9e, 0x5b, 0xb9, 0x00, 0x19, 0x13, 0xbe, 0x5b, 0x11, 0x1f, 0x01, 0x60, 0x01, 0x61, 0x5c, 0xe7, 0x01, 0x60, 0x02, 0x61, 0x5c, 0xe7, 0x67, 0x7e, -0xc0, 0x26, 0x02, 0x60, 0x01, 0x61, 0x5c, 0xe7, 0x02, 0x60, 0x02, 0x61, 0x5c, 0xe7, 0x6c, 0x9e, 0x0c, 0x60, 0xbe, 0x58, 0xdd, 0x1e, 0x79, 0xe4, 0xdf, 0x60, 0x1e, 0x68, 0x05, 0x59, 0x24, 0x3a, 0xff, 0x00, 0xfe, 0x59, 0x24, 0x3b, 0xff, 0x00, 0x43, 0x06, 0x03, 0x59, 0x24, 0x3c, 0xff, 0x00, 0xfe, 0x59, 0x24, 0x3d, 0xff, 0x00, 0x85, 0x07, 0xd0, 0x48, 0x0f, 0x00, 0x04, 0x98, 0xf0, 0x48, 0x0f, 0x00, 0x01, 0x98, 0x04, 0x9e, 0x04, 0x60, 0xbe, 0x58, 0xdd, 0x1e, 0x79, 0xe4, 0x9e, 0x58, 0xdb, 0x1e, 0x9e, 0x59, 0xdc, 0x1e, 0x01, 0x00, 0x1a, 0x10, 0x0b, 0x88, 0x60, 0x60, 0xbe, 0x58, 0x20, 0x1d, 0x9e, 0x58, 0xf1, 0x04, 0x9e, 0x59, 0xf2, 0x04, 0x01, 0x00, 0x1c, 0x10, 0x3d, 0x88, 0x3b, 0x9e, 0x66, 0x60, 0xbe, 0x58, 0x20, 0x1d, 0x4e, 0xe8, 0x01, 0x60, 0x01, 0x61, 0x9d, 0xe7, 0x9e, 0x58, 0x39, 0x2e, -0x00, 0x27, 0x0d, 0x1f, 0x1e, 0x10, 0x03, 0x80, 0x01, 0x60, 0x01, 0x61, 0x5c, 0xe7, 0x01, 0x60, 0x02, 0x61, 0x9d, 0xe7, 0x9e, 0x58, 0x0d, 0x1f, 0x1e, 0x10, 0x03, 0x80, 0x01, 0x60, 0x02, 0x61, 0x5c, 0xe7, 0x02, 0x60, 0x01, 0x61, 0x9d, 0xe7, 0x9e, 0x58, 0x0d, 0x1f, 0x1e, 0x10, 0x03, 0x80, 0x02, 0x60, 0x01, 0x61, 0x5c, 0xe7, 0x02, 0x60, 0x02, 0x61, 0x9d, 0xe7, 0x9e, 0x58, 0x0d, 0x1f, 0x1e, 0x10, 0x03, 0x80, 0x02, 0x60, 0x02, 0x61, 0x5c, 0xe7, 0x06, 0x71, 0x09, 0xac, 0x0c, 0x92, 0x01, 0xac, 0x0a, 0x92, 0x51, 0xac, 0x08, 0x92, 0x9e, 0x58, 0x20, 0x1d, 0x00, 0x61, 0x19, 0x48, 0x03, 0x8a, 0x01, 0x60, 0xbe, 0x58, 0x44, 0x1a, 0x98, 0xe2, 0x1a, 0x38, 0x3a, 0x38, 0x9e, 0x58, 0xb8, 0x00, 0x1b, 0x10, 0x7a, 0x61, 0x02, 0x69, 0x45, 0xe7, 0x9e, 0x58, 0xb9, 0x00, 0x1b, 0x10, 0x7a, 0x61, 0x55, 0x69, -0x40, 0x27, 0x02, 0x69, 0x30, 0x39, 0xb8, 0x00, 0x45, 0xe7, 0x3a, 0x38, 0x19, 0x01, 0x00, 0x66, 0x07, 0x38, 0x5a, 0x27, 0x23, 0x5a, 0x18, 0x12, 0x08, 0x8a, 0x18, 0x16, 0x04, 0x88, 0x21, 0x5b, 0x19, 0x13, 0x01, 0x64, 0x9b, 0x5b, 0x01, 0x66, 0x06, 0x9e, 0x18, 0x16, 0x04, 0x8a, 0x21, 0x5b, 0x01, 0x64, 0x9b, 0x5b, 0x00, 0x66, 0x19, 0x01, 0x3a, 0x38, 0xbe, 0x58, 0x82, 0x1d, 0xbe, 0x59, 0x83, 0x1d, 0x9e, 0x5e, 0x10, 0x1f, 0x9e, 0x5f, 0x0e, 0x1f, 0x7a, 0x63, 0x02, 0x6b, 0x67, 0x03, 0x63, 0x5b, 0x9e, 0x59, 0x82, 0x1d, 0x79, 0x48, 0x26, 0x88, 0x48, 0x63, 0x1d, 0x6b, 0x67, 0x03, 0x63, 0x5b, 0x18, 0x13, 0x20, 0x8a, 0x7a, 0x62, 0x02, 0x6a, 0x50, 0x3a, 0xb8, 0x00, 0x46, 0x02, 0x43, 0x5a, 0x9e, 0x59, 0x83, 0x1d, 0x59, 0x48, 0x16, 0x88, 0x48, 0x62, 0x1d, 0x6a, 0x50, 0x3a, 0xb8, 0x00, 0xdc, 0xac, -0x80, 0x27, 0x46, 0x02, 0x43, 0x5a, 0x00, 0x61, 0x61, 0x58, 0x43, 0x40, 0x9e, 0x5d, 0x14, 0x1f, 0x1c, 0x5d, 0x01, 0x5d, 0x9e, 0x5c, 0xb8, 0x00, 0x00, 0x61, 0xe1, 0x58, 0x86, 0x48, 0x48, 0x64, 0x0e, 0x6c, 0x80, 0x04, 0xbb, 0x5c, 0x19, 0x07, 0x9e, 0x5a, 0x0f, 0x1f, 0xfa, 0x48, 0xcd, 0x9d, 0x19, 0x06, 0x9e, 0x5a, 0x11, 0x1f, 0xda, 0x48, 0xc6, 0x9d, 0x3a, 0x38, 0x9e, 0x5b, 0xb8, 0x00, 0xbe, 0x5b, 0x0e, 0x1f, 0x00, 0x63, 0xbe, 0x5b, 0x0f, 0x1f, 0x9e, 0x5b, 0xb9, 0x00, 0xbe, 0x5b, 0x10, 0x1f, 0x00, 0x63, 0xbe, 0x5b, 0x11, 0x1f, 0x00, 0x63, 0xbe, 0x5b, 0x0d, 0x1f, 0x01, 0x63, 0xbe, 0x5b, 0x12, 0x1f, 0xbe, 0x5b, 0x13, 0x1f, 0x00, 0x63, 0x00, 0x65, 0xbe, 0x58, 0x00, 0x1d, 0xbe, 0x59, 0x04, 0x1d, 0x00, 0x66, 0x00, 0x67, 0x7a, 0x62, 0x02, 0x6a, 0x47, 0x02, 0x43, 0x5a, 0x9e, 0x59, 0x6d, 0xf0, -0xc0, 0x27, 0x00, 0x1d, 0x59, 0x48, 0x5a, 0x88, 0x7a, 0x62, 0x02, 0x6a, 0x50, 0x3a, 0xb8, 0x00, 0x46, 0x02, 0x43, 0x5a, 0x9e, 0x59, 0x04, 0x1d, 0x59, 0x48, 0x50, 0x88, 0x48, 0x62, 0x1d, 0x6a, 0x47, 0x02, 0x43, 0x5a, 0x9e, 0x59, 0x12, 0x1f, 0x59, 0x48, 0x02, 0x9a, 0xbe, 0x5a, 0x12, 0x1f, 0x48, 0x62, 0x1d, 0x6a, 0x50, 0x3a, 0xb8, 0x00, 0x46, 0x02, 0x43, 0x5a, 0x9e, 0x59, 0x13, 0x1f, 0x59, 0x48, 0x02, 0x9a, 0xbe, 0x5a, 0x13, 0x1f, 0x9e, 0x5c, 0xb8, 0x00, 0x00, 0x61, 0xe1, 0x58, 0x86, 0x48, 0x48, 0x64, 0x0e, 0x6c, 0x80, 0x04, 0x83, 0x59, 0x79, 0xac, 0x2f, 0x92, 0x10, 0x60, 0x38, 0x48, 0x2c, 0x9a, 0x9e, 0x58, 0x0e, 0x1f, 0xf8, 0x48, 0x07, 0x98, 0xbe, 0x5f, 0x0e, 0x1f, 0x9e, 0x58, 0x0d, 0x1f, 0x19, 0x00, 0xbe, 0x58, 0x0d, 0x1f, 0x9e, 0x58, 0x0f, 0x1f, 0xf8, 0x48, 0x07, 0x80, 0x4c, 0x0e, -0x00, 0x28, 0xbe, 0x5f, 0x0f, 0x1f, 0x9e, 0x58, 0x0d, 0x1f, 0x19, 0x00, 0xbe, 0x58, 0x0d, 0x1f, 0x9e, 0x58, 0x10, 0x1f, 0xd8, 0x48, 0x07, 0x98, 0xbe, 0x5e, 0x10, 0x1f, 0x9e, 0x58, 0x0d, 0x1f, 0x19, 0x00, 0xbe, 0x58, 0x0d, 0x1f, 0x9e, 0x58, 0x11, 0x1f, 0xd8, 0x48, 0x07, 0x80, 0xbe, 0x5e, 0x11, 0x1f, 0x9e, 0x58, 0x0d, 0x1f, 0x19, 0x00, 0xbe, 0x58, 0x0d, 0x1f, 0x19, 0x07, 0x9e, 0x5a, 0xb8, 0x00, 0x19, 0x12, 0xfa, 0x48, 0x98, 0x9d, 0x19, 0x06, 0x9e, 0x5a, 0xb9, 0x00, 0x19, 0x12, 0xda, 0x48, 0x91, 0x9d, 0x9e, 0x58, 0x12, 0x1f, 0x9e, 0x59, 0x13, 0x1f, 0x38, 0x48, 0x01, 0x98, 0x21, 0x58, 0x9e, 0x5e, 0x4d, 0x04, 0x9e, 0x5f, 0x4f, 0x04, 0xc7, 0x06, 0xc2, 0x3e, 0x00, 0x06, 0x04, 0x80, 0x02, 0x39, 0x40, 0x01, 0x01, 0x98, 0x10, 0x60, 0x02, 0x39, 0x80, 0x03, 0x02, 0x80, 0x08, 0x59, 0x3f, 0xc2, -0x40, 0x28, 0x01, 0x00, 0x9e, 0x5e, 0x12, 0x1f, 0x9e, 0x5f, 0x13, 0x1f, 0xc7, 0x06, 0xc2, 0x3e, 0x00, 0x02, 0x02, 0x98, 0x08, 0x58, 0x08, 0x58, 0xbe, 0x58, 0x14, 0x1f, 0x3a, 0x38, 0x00, 0x62, 0x7a, 0x67, 0x02, 0x6f, 0x16, 0x60, 0xe5, 0x5c, 0x18, 0x14, 0x01, 0x88, 0x69, 0xe8, 0x19, 0x02, 0x19, 0x10, 0x18, 0x10, 0xf8, 0x89, 0x00, 0x62, 0x7a, 0x67, 0x02, 0x6f, 0x16, 0x66, 0xe6, 0x07, 0x24, 0x66, 0xe5, 0x5c, 0x18, 0x14, 0x01, 0x88, 0x76, 0xe8, 0x19, 0x02, 0x19, 0x16, 0x18, 0x16, 0xf8, 0x89, 0x3a, 0x38, 0x00, 0x64, 0x48, 0x63, 0x0e, 0x6b, 0x62, 0x03, 0x16, 0x65, 0x24, 0x66, 0x19, 0x16, 0xc7, 0x38, 0x74, 0x28, 0x9b, 0x5b, 0x65, 0x03, 0x1a, 0x38, 0x3a, 0x38, 0x00, 0x64, 0x16, 0x65, 0x48, 0x63, 0x0e, 0x6b, 0x00, 0x61, 0x00, 0x60, 0x45, 0x40, 0x03, 0x03, 0x16, 0x65, 0x19, 0x15, 0x8d, 0xc6, -0x80, 0x28, 0xa7, 0x38, 0x84, 0x28, 0x9d, 0x5b, 0x1a, 0x38, 0x1a, 0x38, 0x3a, 0x38, 0x48, 0x60, 0x1d, 0x68, 0x9c, 0x61, 0x1e, 0x69, 0x9e, 0x5b, 0x4c, 0x04, 0x70, 0x48, 0x00, 0x00, 0x0c, 0x8a, 0x9e, 0x5b, 0x4c, 0x04, 0x70, 0x48, 0x01, 0x00, 0x0f, 0x8a, 0x70, 0x48, 0x14, 0x00, 0x15, 0x8a, 0x70, 0x48, 0x15, 0x00, 0x1b, 0x8a, 0x23, 0x9e, 0x03, 0x00, 0x23, 0x01, 0x4f, 0x38, 0xa1, 0x28, 0x05, 0x5a, 0x5d, 0x59, 0x1a, 0x38, 0x23, 0x9e, 0x19, 0x13, 0x03, 0x00, 0x23, 0x01, 0x6f, 0x38, 0xaa, 0x28, 0x05, 0x5a, 0x5d, 0x59, 0x1a, 0x38, 0x1a, 0x9e, 0x19, 0x13, 0x03, 0x00, 0x23, 0x01, 0x6f, 0x38, 0xb3, 0x28, 0x05, 0x5a, 0x5d, 0x59, 0x1a, 0x38, 0x11, 0x9e, 0x1a, 0x13, 0x03, 0x00, 0x23, 0x01, 0x4f, 0x38, 0xbc, 0x28, 0x05, 0x5a, 0x5d, 0x59, 0x1a, 0x38, 0x08, 0x9e, 0x1a, 0x13, 0x03, 0x00, 0x7e, 0xc4, -0xc0, 0x28, 0x23, 0x01, 0x8f, 0x38, 0xc5, 0x28, 0x05, 0x5a, 0x5d, 0x59, 0x1a, 0x38, 0x48, 0x60, 0x1d, 0x68, 0x10, 0x38, 0xb8, 0x00, 0x9c, 0x61, 0x1e, 0x69, 0x30, 0x39, 0xb8, 0x00, 0x9e, 0x5b, 0x4e, 0x04, 0x70, 0x48, 0x00, 0x00, 0x0c, 0x8a, 0x9e, 0x5b, 0x4e, 0x04, 0x70, 0x48, 0x01, 0x00, 0x0f, 0x8a, 0x70, 0x48, 0x22, 0x00, 0x15, 0x8a, 0x70, 0x48, 0x23, 0x00, 0x1b, 0x8a, 0x23, 0x9e, 0x03, 0x00, 0x23, 0x01, 0x4f, 0x38, 0xe5, 0x28, 0x05, 0x5a, 0x5d, 0x59, 0x1a, 0x38, 0x23, 0x9e, 0x19, 0x13, 0x03, 0x00, 0x23, 0x01, 0x6f, 0x38, 0xee, 0x28, 0x05, 0x5a, 0x5d, 0x59, 0x1a, 0x38, 0x1a, 0x9e, 0x19, 0x13, 0x03, 0x00, 0x23, 0x01, 0x6f, 0x38, 0xf7, 0x28, 0x05, 0x5a, 0x5d, 0x59, 0x1a, 0x38, 0x11, 0x9e, 0x1a, 0x13, 0x03, 0x00, 0x23, 0x01, 0x4f, 0x38, 0x00, 0x29, 0x05, 0x5a, 0x5d, 0x59, 0x1c, 0x38, -0x00, 0x29, 0x1a, 0x38, 0x08, 0x9e, 0x1a, 0x13, 0x03, 0x00, 0x23, 0x01, 0x8f, 0x38, 0x09, 0x29, 0x05, 0x5a, 0x5d, 0x59, 0x1a, 0x38, 0x1a, 0x38, 0x3a, 0x38, 0x1e, 0x58, 0x1e, 0x59, 0x1e, 0x5a, 0x1e, 0x5b, 0x1e, 0x5c, 0x1e, 0x5d, 0x1e, 0x5e, 0x1e, 0x5f, 0x00, 0x66, 0x00, 0x67, 0x9c, 0x63, 0x1e, 0x6b, 0x67, 0x03, 0x63, 0x5b, 0x18, 0x13, 0x24, 0x8a, 0x48, 0x62, 0x1d, 0x6a, 0x50, 0x3a, 0xb8, 0x00, 0x46, 0x02, 0x43, 0x5a, 0x00, 0x61, 0x59, 0x48, 0x1b, 0x8a, 0x9c, 0x62, 0x1e, 0x6a, 0x50, 0x3a, 0xb8, 0x00, 0x46, 0x02, 0x43, 0x5a, 0x00, 0x61, 0x61, 0x58, 0x43, 0x40, 0x9e, 0x5d, 0x61, 0x1e, 0x1c, 0x5d, 0x01, 0x5d, 0x9e, 0x5c, 0xb8, 0x00, 0x00, 0x61, 0xe1, 0x58, 0x86, 0x48, 0x32, 0x64, 0x16, 0x6c, 0x80, 0x04, 0x48, 0x63, 0x0e, 0x6b, 0x60, 0x03, 0xbb, 0x5c, 0xbb, 0x5b, 0x0e, 0x9e, 0xae, 0xcd, -0x40, 0x29, 0x9e, 0x5c, 0xb8, 0x00, 0x00, 0x61, 0xe1, 0x58, 0x86, 0x48, 0x32, 0x64, 0x16, 0x6c, 0x80, 0x04, 0x48, 0x63, 0x0e, 0x6b, 0x60, 0x03, 0x00, 0x65, 0xbb, 0x5c, 0xbb, 0x5b, 0x19, 0x07, 0x9e, 0x5a, 0xb8, 0x00, 0x19, 0x12, 0xfa, 0x48, 0xc2, 0x9d, 0x19, 0x06, 0x9e, 0x5a, 0xb9, 0x00, 0x19, 0x12, 0xda, 0x48, 0xbb, 0x9d, 0x3e, 0x5f, 0x3e, 0x5e, 0x3e, 0x5d, 0x3e, 0x5c, 0x3e, 0x5b, 0x3e, 0x5a, 0x3e, 0x59, 0x3e, 0x58, 0x3a, 0x38, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0x40, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0x40, 0x00, 0x80, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x08, 0x00, 0xe0, 0xac, 0x98, 0x3c, 0x99, 0x2a, 0x9d, 0x60, 0x4e, 0x68, 0xef, 0xb0, 0x52, 0xb1, 0x39, 0xac, 0xfd, 0x93, 0xfe, 0x97, -0x80, 0x29, 0x00, 0xbc, 0xbc, 0x00, 0x78, 0xa8, 0x70, 0xa8, 0x00, 0xbd, 0xbc, 0x00, 0x00, 0xbc, 0xb1, 0x00, 0x38, 0xa8, 0x70, 0xa8, 0x00, 0xbd, 0xb1, 0x00, 0x00, 0xbc, 0x1c, 0x00, 0x78, 0xaa, 0x00, 0xbd, 0x1c, 0x00, 0x9e, 0x58, 0x00, 0xf8, 0x00, 0xa8, 0xbe, 0x58, 0x00, 0xf8, 0x00, 0x60, 0xbe, 0x58, 0x0f, 0xf8, 0xbe, 0x58, 0x10, 0xf8, 0x00, 0xbc, 0xb1, 0x00, 0x30, 0xaa, 0x00, 0xaa, 0x00, 0xbd, 0xb1, 0x00, 0x1d, 0xb0, 0x38, 0xa8, 0x40, 0xa8, 0x48, 0xa8, 0x9d, 0xb0, 0x9a, 0xaa, 0x00, 0x60, 0xbe, 0x58, 0x5e, 0x00, 0xbe, 0x58, 0x5f, 0x00, 0xbe, 0x58, 0x60, 0x00, 0xbe, 0x58, 0x61, 0x00, 0x3e, 0xb0, 0x70, 0xaa, 0x78, 0xaa, 0xbe, 0xb0, 0x30, 0xb0, 0xbe, 0x58, 0x2a, 0x1d, 0x31, 0xb0, 0xbe, 0x58, 0x2b, 0x1d, 0x33, 0xb0, 0xbe, 0x58, 0x2c, 0x1d, 0x34, 0xb0, 0xbe, 0x58, 0x2d, 0x1d, 0xff, 0x13, -0xc0, 0x29, 0x00, 0x60, 0x00, 0xbd, 0x31, 0x00, 0x00, 0x60, 0x00, 0xbd, 0x05, 0x00, 0x00, 0xbc, 0x34, 0x00, 0x00, 0x60, 0x00, 0xbd, 0x34, 0x00, 0x00, 0xbc, 0x30, 0x00, 0x00, 0xaa, 0x08, 0xaa, 0x10, 0xaa, 0x18, 0xaa, 0x20, 0xaa, 0x28, 0xaa, 0x30, 0xaa, 0x38, 0xaa, 0x40, 0xaa, 0x48, 0xaa, 0x50, 0xaa, 0x58, 0xaa, 0x60, 0xaa, 0x68, 0xaa, 0x70, 0xaa, 0x78, 0xaa, 0x00, 0xbd, 0x30, 0x00, 0x00, 0xbc, 0x04, 0x00, 0x00, 0xaa, 0x08, 0xaa, 0x10, 0xaa, 0x18, 0xaa, 0x20, 0xaa, 0x28, 0xaa, 0x30, 0xaa, 0x38, 0xaa, 0x40, 0xaa, 0x48, 0xaa, 0x50, 0xaa, 0x58, 0xaa, 0x60, 0xaa, 0x68, 0xaa, 0x70, 0xaa, 0x78, 0xaa, 0x00, 0xbd, 0x04, 0x00, 0x00, 0xbc, 0x33, 0x00, 0x00, 0xaa, 0x08, 0xaa, 0x10, 0xaa, 0x18, 0xaa, 0x20, 0xaa, 0x28, 0xaa, 0x30, 0xaa, 0x38, 0xaa, 0x40, 0xaa, 0x48, 0xaa, 0x50, 0xaa, 0x31, 0x83, -0x00, 0x2a, 0x58, 0xaa, 0x60, 0xaa, 0x68, 0xaa, 0x70, 0xaa, 0x78, 0xaa, 0x00, 0xbd, 0x33, 0x00, 0x9e, 0x58, 0xc3, 0x1d, 0x06, 0x38, 0xaa, 0x55, 0x02, 0x8a, 0x42, 0xa9, 0x8b, 0x9e, 0x9d, 0x60, 0x4e, 0x68, 0xef, 0xb0, 0xff, 0xab, 0x62, 0x60, 0xb1, 0x68, 0xef, 0xb0, 0x12, 0xa9, 0x1a, 0x38, 0x1a, 0x38, 0x00, 0xbc, 0x04, 0x00, 0x38, 0xa8, 0x00, 0xbd, 0x04, 0x00, 0x9e, 0x58, 0x2a, 0x1d, 0xb0, 0xb0, 0x9e, 0x58, 0x2b, 0x1d, 0xb1, 0xb0, 0x9e, 0x58, 0x2c, 0x1d, 0xb3, 0xb0, 0x9e, 0x58, 0x2d, 0x1d, 0xb4, 0xb0, 0x9a, 0xac, 0xfe, 0x91, 0x9e, 0x58, 0x5e, 0x00, 0x02, 0x38, 0x54, 0x00, 0x03, 0x8a, 0xb2, 0xac, 0xfe, 0x93, 0x81, 0x9f, 0xe0, 0xac, 0x7f, 0x91, 0x9a, 0xaa, 0x00, 0x60, 0xbe, 0x58, 0xae, 0x00, 0x00, 0xbc, 0xb1, 0x00, 0x30, 0xa8, 0x00, 0xbd, 0xb1, 0x00, 0x9e, 0x58, 0x00, 0xf8, 0x1d, 0xd5, -0x40, 0x2a, 0x00, 0xaa, 0xbe, 0x58, 0x00, 0xf8, 0x00, 0xbc, 0xbc, 0x00, 0x78, 0xaa, 0x70, 0xaa, 0x00, 0xbd, 0xbc, 0x00, 0x00, 0xbc, 0xb1, 0x00, 0x38, 0xaa, 0x70, 0xaa, 0x00, 0xbd, 0xb1, 0x00, 0x00, 0xbc, 0x1c, 0x00, 0x78, 0xa8, 0x00, 0xbd, 0x1c, 0x00, 0x3e, 0xb0, 0x70, 0xa8, 0x78, 0xa8, 0xbe, 0xb0, 0x19, 0x38, 0x8c, 0x50, 0x00, 0x60, 0xbe, 0x58, 0xe7, 0x00, 0x00, 0x60, 0x05, 0x68, 0xbe, 0x58, 0xe9, 0x00, 0x18, 0x60, 0x08, 0x68, 0xbe, 0x58, 0xe8, 0x00, 0xea, 0x60, 0x2f, 0x68, 0x07, 0x38, 0x6b, 0x2a, 0x1a, 0x38, 0x1a, 0x38, 0x1a, 0x38, 0x1a, 0x38, 0xe5, 0xaa, 0x00, 0x61, 0xff, 0x65, 0xff, 0x6d, 0x0c, 0x62, 0x47, 0x63, 0xf8, 0x6b, 0x53, 0x64, 0xf8, 0x6c, 0x19, 0x12, 0x47, 0x38, 0x7b, 0x2a, 0x3d, 0x5b, 0xbd, 0x5c, 0x1a, 0x38, 0xc5, 0xfc, 0x1e, 0x59, 0x96, 0x61, 0xbe, 0x59, 0x4a, 0x81, -0x80, 0x2a, 0xfc, 0x1c, 0x3e, 0x59, 0x04, 0xc8, 0x9e, 0x58, 0xc4, 0x1d, 0x06, 0x38, 0x55, 0xaa, 0x02, 0x8a, 0x42, 0xa9, 0x0f, 0x9e, 0x9d, 0x60, 0x4e, 0x68, 0xef, 0xb0, 0xff, 0xa9, 0x9e, 0x58, 0xd6, 0x1a, 0xbe, 0x58, 0x47, 0x1e, 0xbe, 0x58, 0x04, 0xf8, 0x9e, 0x58, 0xda, 0x1a, 0xbe, 0x58, 0xb3, 0xf8, 0x79, 0xed, 0x3a, 0x38, 0x00, 0x60, 0xbe, 0x58, 0xb1, 0x00, 0xb5, 0xef, 0x9e, 0x59, 0xbc, 0x00, 0x9e, 0x58, 0xb1, 0x00, 0x19, 0x00, 0xbe, 0x58, 0xb1, 0x00, 0x19, 0x48, 0xf6, 0x81, 0xd5, 0xf0, 0x9e, 0x58, 0xe7, 0x00, 0x1a, 0x10, 0x08, 0x88, 0x9e, 0x58, 0xe8, 0x00, 0x9e, 0x59, 0xe9, 0x00, 0x19, 0x48, 0x01, 0x88, 0x42, 0xa9, 0x1d, 0x39, 0x3a, 0x38, 0x00, 0x60, 0xbe, 0x58, 0xb1, 0x00, 0xbe, 0x58, 0xb0, 0x00, 0x9e, 0x58, 0x36, 0x1d, 0x1d, 0x10, 0x04, 0x8a, 0x9e, 0x58, 0x36, 0x1d, 0xc4, 0x76, -0xc0, 0x2a, 0x1b, 0x10, 0x20, 0x88, 0xe5, 0xac, 0x1e, 0x90, 0x9e, 0x58, 0xe8, 0x00, 0x02, 0x38, 0x00, 0x05, 0x09, 0x8a, 0x00, 0x60, 0x05, 0x68, 0xbe, 0x58, 0xe8, 0x00, 0x18, 0x60, 0x08, 0x68, 0xbe, 0x58, 0xe9, 0x00, 0x08, 0x9e, 0x18, 0x60, 0x08, 0x68, 0xbe, 0x58, 0xe8, 0x00, 0x00, 0x60, 0x05, 0x68, 0xbe, 0x58, 0xe9, 0x00, 0x9e, 0x58, 0xe7, 0x00, 0x02, 0x39, 0x01, 0x00, 0x03, 0x98, 0x19, 0x00, 0xbe, 0x58, 0xe7, 0x00, 0x9e, 0x5d, 0xd5, 0x00, 0x9e, 0x5b, 0xd4, 0x00, 0x9e, 0x5c, 0xd3, 0x00, 0x04, 0xac, 0x07, 0x90, 0x1e, 0x5b, 0x1e, 0x5c, 0x1e, 0x5d, 0xb5, 0xef, 0x3e, 0x5d, 0x3e, 0x5c, 0x3e, 0x5b, 0x9e, 0x59, 0xbc, 0x00, 0x9e, 0x58, 0xb1, 0x00, 0x19, 0x00, 0x01, 0x31, 0x06, 0x8a, 0xbe, 0x58, 0xb1, 0x00, 0xa8, 0x5d, 0x6c, 0x5b, 0x8c, 0x5c, 0xea, 0x9f, 0xd5, 0xf0, 0x9e, 0x58, 0x23, 0xfe, -0x00, 0x2b, 0xe7, 0x00, 0x1a, 0x10, 0x08, 0x88, 0x9e, 0x58, 0xe8, 0x00, 0x9e, 0x59, 0xe9, 0x00, 0x19, 0x48, 0x01, 0x88, 0x42, 0xa9, 0x1d, 0x39, 0x3a, 0x38, 0x3a, 0x38, 0x9e, 0x58, 0xe2, 0x19, 0x00, 0x61, 0x01, 0x30, 0x01, 0x88, 0x05, 0x9e, 0x00, 0x60, 0xbe, 0x58, 0xae, 0x00, 0xd0, 0xaa, 0x3f, 0x9e, 0x9e, 0x58, 0xae, 0x00, 0x9e, 0x59, 0xc0, 0x00, 0x19, 0x48, 0x01, 0x82, 0x38, 0x9e, 0x52, 0xb1, 0x39, 0xac, 0xfd, 0x93, 0xd0, 0xa8, 0x74, 0xb0, 0x78, 0xaa, 0xf4, 0xb0, 0x00, 0xbc, 0xb1, 0x00, 0x00, 0xa8, 0x00, 0xbd, 0xb1, 0x00, 0x9e, 0x58, 0x00, 0xf8, 0x00, 0xa8, 0xbe, 0x58, 0x00, 0xf8, 0x00, 0x60, 0xbe, 0x58, 0x0f, 0xf8, 0xbe, 0x58, 0x10, 0xf8, 0x4f, 0xb0, 0x50, 0xa8, 0xcf, 0xb0, 0x9e, 0x58, 0xaf, 0x00, 0x9e, 0x59, 0xc5, 0x00, 0x19, 0x48, 0x03, 0x82, 0x74, 0x60, 0x82, 0xb0, 0xc2, 0x8e, -0x40, 0x2b, 0xf7, 0x9f, 0x00, 0x60, 0xbe, 0x58, 0xaf, 0x00, 0x4f, 0xb0, 0x50, 0xaa, 0xcf, 0xb0, 0x00, 0xbc, 0xb1, 0x00, 0x00, 0xaa, 0x00, 0xbd, 0xb1, 0x00, 0x9e, 0x58, 0x00, 0xf8, 0x00, 0xaa, 0xbe, 0x58, 0x00, 0xf8, 0x20, 0x60, 0x07, 0x38, 0x56, 0x2b, 0x1a, 0x38, 0x1a, 0x38, 0x1a, 0x38, 0x3a, 0x38, 0x19, 0x38, 0x02, 0x48, 0xb9, 0xaa, 0x00, 0x9e, 0x3a, 0x38, 0x3a, 0x38, 0x52, 0xb2, 0x3a, 0xac, 0xfd, 0x93, 0x78, 0xab, 0x5a, 0x62, 0xe1, 0x6a, 0xac, 0xb2, 0x00, 0x62, 0xff, 0x3f, 0x7a, 0x38, 0xac, 0xb2, 0x78, 0xa9, 0x3a, 0x38, 0x00, 0x62, 0xac, 0xb2, 0xff, 0x3f, 0x0f, 0x59, 0x3a, 0x38, 0x01, 0x62, 0xef, 0x3f, 0x77, 0x2b, 0x05, 0x5d, 0x25, 0x5c, 0xbc, 0x48, 0x02, 0x88, 0x1a, 0x38, 0x3a, 0x38, 0x00, 0x62, 0x3a, 0x38, 0x9e, 0x58, 0xbf, 0x00, 0x19, 0x10, 0x0f, 0x61, 0x27, 0x69, 0x59, 0xe5, -0x80, 0x2b, 0x9e, 0x5b, 0xe8, 0x00, 0x9e, 0x58, 0xd5, 0x00, 0x9e, 0x5a, 0xd4, 0x00, 0x9e, 0x5c, 0xd3, 0x00, 0xbe, 0x58, 0xed, 0x19, 0xbe, 0x5a, 0xee, 0x19, 0xbe, 0x5c, 0xef, 0x19, 0x00, 0x65, 0x9e, 0x5e, 0xe9, 0x19, 0xa0, 0xac, 0x26, 0x90, 0x9e, 0x5b, 0xe8, 0x00, 0x30, 0x67, 0x0b, 0x6f, 0xa6, 0x40, 0x60, 0x03, 0xe0, 0x07, 0x00, 0xa9, 0x9e, 0x58, 0xed, 0x19, 0x9e, 0x5a, 0xee, 0x19, 0x9e, 0x5c, 0xef, 0x19, 0x0c, 0x58, 0x4c, 0x5a, 0x8c, 0x5c, 0xbe, 0x58, 0xed, 0x19, 0xbe, 0x5a, 0xee, 0x19, 0xbe, 0x5c, 0xef, 0x19, 0x00, 0xad, 0x07, 0x92, 0xc2, 0x38, 0x01, 0x00, 0x07, 0x38, 0xb2, 0x2b, 0xe5, 0x59, 0x3d, 0x5b, 0x1a, 0x38, 0x19, 0x05, 0x9e, 0x58, 0xe8, 0x19, 0xb8, 0x48, 0xdb, 0x81, 0x29, 0x9e, 0x9e, 0x5b, 0xe8, 0x00, 0x30, 0x67, 0x0b, 0x6f, 0x65, 0x03, 0xe5, 0x07, 0x00, 0xa9, 0x05, 0x95, -0xc0, 0x2b, 0x9e, 0x58, 0xed, 0x19, 0x9e, 0x5a, 0xee, 0x19, 0x9e, 0x5c, 0xef, 0x19, 0x0c, 0x58, 0x4c, 0x5a, 0x8c, 0x5c, 0xbe, 0x58, 0xed, 0x19, 0xbe, 0x5a, 0xee, 0x19, 0xbe, 0x5c, 0xef, 0x19, 0x00, 0xad, 0x0b, 0x92, 0xc2, 0x38, 0x01, 0x00, 0x07, 0x38, 0xdb, 0x2b, 0xe3, 0x59, 0x3b, 0x5b, 0x70, 0x3b, 0xe8, 0x19, 0xf0, 0x3f, 0xe8, 0x19, 0x1a, 0x38, 0x19, 0x05, 0x9e, 0x58, 0xe8, 0x19, 0xb8, 0x48, 0xd8, 0x81, 0x00, 0x9e, 0x3a, 0x38, 0x52, 0xb1, 0x39, 0xac, 0xfd, 0x93, 0xfd, 0xab, 0xf5, 0xab, 0x1a, 0x38, 0x1a, 0x38, 0x02, 0xa9, 0x00, 0xbd, 0xb0, 0x00, 0x1a, 0x38, 0x1a, 0x38, 0x02, 0xab, 0x1a, 0x38, 0x7a, 0xad, 0xfe, 0x93, 0xfd, 0xa9, 0xf5, 0xa9, 0x3a, 0x38, 0x00, 0xbc, 0xaa, 0x00, 0x10, 0x48, 0x00, 0x00, 0x01, 0x8a, 0x42, 0xa9, 0x40, 0x60, 0x21, 0x71, 0x19, 0x48, 0x01, 0x8a, 0x99, 0xa3, -0x00, 0x2c, 0x42, 0xa9, 0x0c, 0x60, 0x27, 0x71, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x0a, 0x60, 0x9e, 0x59, 0xe4, 0x19, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x14, 0x60, 0x9e, 0x59, 0xf0, 0x04, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x16, 0x60, 0x9e, 0x59, 0xba, 0x00, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x18, 0x60, 0x03, 0x68, 0x9e, 0x59, 0xbf, 0x00, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x16, 0x60, 0x9e, 0x59, 0xbb, 0x00, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x24, 0x60, 0x9e, 0x59, 0xbc, 0x00, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x9e, 0x58, 0xe7, 0x00, 0x10, 0x48, 0x02, 0x00, 0x01, 0x9a, 0x42, 0xa9, 0x9e, 0x58, 0x1b, 0x1f, 0x10, 0x48, 0xaa, 0x55, 0x01, 0x8a, 0x42, 0xa9, 0x9e, 0x58, 0x1c, 0x1f, 0x10, 0x48, 0x55, 0xaa, 0x01, 0x8a, 0x42, 0xa9, 0x9e, 0x58, 0x1b, 0x1f, 0x9e, 0x59, 0x43, 0x86, -0x40, 0x2c, 0x1c, 0x1f, 0x19, 0x48, 0x01, 0x88, 0x42, 0xa9, 0x1a, 0x60, 0xf8, 0x68, 0x03, 0x58, 0x00, 0x61, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x1b, 0x60, 0xf8, 0x68, 0x03, 0x58, 0x00, 0x61, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x1c, 0x60, 0xf8, 0x68, 0x03, 0x58, 0x00, 0x61, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x9e, 0x58, 0x17, 0x1f, 0x9e, 0x59, 0x1a, 0x1f, 0x19, 0x48, 0x09, 0x88, 0xcc, 0x60, 0x33, 0x68, 0xbe, 0x58, 0x17, 0x1f, 0x33, 0x60, 0xcc, 0x68, 0xbe, 0x58, 0x1a, 0x1f, 0x42, 0xa9, 0xff, 0xad, 0x01, 0x92, 0x42, 0xa9, 0x9e, 0x58, 0xe8, 0x00, 0x9e, 0x59, 0xe9, 0x00, 0x19, 0x48, 0x01, 0x88, 0x42, 0xa9, 0x9e, 0x58, 0x1f, 0x00, 0x10, 0x48, 0x01, 0x00, 0x01, 0x8a, 0x42, 0xa9, 0xed, 0xac, 0x5f, 0x92, 0x2c, 0x60, 0x1b, 0x68, 0x1f, 0x61, 0x1f, 0x69, 0x14, 0x62, 0x19, 0x12, 0x44, 0xd9, -0x80, 0x2c, 0x47, 0x38, 0x87, 0x2c, 0x05, 0x5b, 0x70, 0x48, 0x1f, 0x1f, 0x01, 0x8a, 0x42, 0xa9, 0x1a, 0x38, 0x02, 0x60, 0xf8, 0x68, 0x03, 0x58, 0x9e, 0x59, 0xd5, 0x1a, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x0a, 0x60, 0xf8, 0x68, 0x03, 0x58, 0x9e, 0x59, 0xd8, 0x1a, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x05, 0x60, 0xf8, 0x68, 0x03, 0x58, 0x9e, 0x59, 0xd7, 0x1a, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x0e, 0x60, 0xf8, 0x68, 0x03, 0x58, 0x9e, 0x59, 0x58, 0x01, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x0c, 0x60, 0xf8, 0x68, 0x03, 0x58, 0x9e, 0x59, 0x57, 0x01, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x09, 0x60, 0xf8, 0x68, 0x03, 0x58, 0x9e, 0x59, 0xba, 0x01, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0xaf, 0x60, 0xf8, 0x68, 0x03, 0x58, 0x9e, 0x59, 0xc7, 0x01, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x89, 0xd0, -0xc0, 0x2c, 0xb0, 0x60, 0xf8, 0x68, 0x03, 0x58, 0x9e, 0x59, 0xc8, 0x01, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0xb7, 0x60, 0xf8, 0x68, 0x03, 0x58, 0x9e, 0x59, 0xcf, 0x01, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0xb8, 0x60, 0xf8, 0x68, 0x03, 0x58, 0x9e, 0x59, 0xd1, 0x01, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x1a, 0x38, 0x1a, 0x38, 0x1a, 0x38, 0x3a, 0x38, 0xe0, 0xec, 0xf0, 0xec, 0x1a, 0xed, 0x3a, 0x38, 0x00, 0x60, 0xbe, 0x58, 0x1f, 0x1e, 0xbe, 0x58, 0x20, 0x1e, 0xbe, 0x58, 0x21, 0x1e, 0x22, 0x61, 0x1e, 0x69, 0x23, 0x62, 0x47, 0x38, 0xee, 0x2c, 0x1d, 0x59, 0x1a, 0x38, 0x1a, 0x38, 0x3a, 0x38, 0x30, 0x60, 0x0b, 0x68, 0x9e, 0x59, 0xe8, 0x00, 0x9e, 0x5a, 0xe9, 0x00, 0x9e, 0x5f, 0xfe, 0x1b, 0x9e, 0x5e, 0xfd, 0x1b, 0x19, 0x16, 0x00, 0x63, 0x00, 0x64, 0x00, 0x65, 0xc7, 0x38, 0x0a, 0x2d, 0xf8, 0x69, -0x00, 0x2d, 0x68, 0x5b, 0x8c, 0x5c, 0xac, 0x5d, 0x25, 0x5e, 0x16, 0x16, 0xdd, 0x5a, 0xd2, 0x3e, 0x19, 0x1e, 0x01, 0x96, 0x7b, 0xa8, 0x19, 0x00, 0x75, 0x3b, 0x1f, 0x1e, 0x95, 0x3c, 0x20, 0x1e, 0xb5, 0x3d, 0x21, 0x1e, 0xbe, 0x5b, 0x1f, 0x1e, 0xbe, 0x5c, 0x20, 0x1e, 0xbe, 0x5d, 0x21, 0x1e, 0x19, 0x17, 0xdf, 0x99, 0x3a, 0x38, 0x9e, 0x5b, 0x1f, 0x1e, 0x9e, 0x5c, 0x20, 0x1e, 0x9e, 0x5a, 0x21, 0x1e, 0x00, 0x65, 0x9e, 0x5f, 0xfd, 0x1b, 0x19, 0x17, 0x7b, 0xac, 0x0e, 0x92, 0xf0, 0x38, 0xe9, 0x00, 0x22, 0x61, 0x1e, 0x69, 0x23, 0x66, 0xc7, 0x38, 0x32, 0x2d, 0x03, 0x5e, 0x36, 0x06, 0xdd, 0x59, 0x10, 0x38, 0xfd, 0x1b, 0x1a, 0x38, 0x19, 0x05, 0x46, 0x5a, 0x8a, 0x5c, 0x6a, 0x5b, 0x19, 0x17, 0xeb, 0x95, 0xbe, 0x5d, 0x46, 0x1e, 0x3a, 0x38, 0x9e, 0x5b, 0x46, 0x1e, 0x18, 0x13, 0x0d, 0x8a, 0xaa, 0x64, -0x40, 0x2d, 0x24, 0x62, 0x22, 0x64, 0x1e, 0x6c, 0x47, 0x38, 0x4c, 0x2d, 0x00, 0x61, 0x83, 0x58, 0x78, 0xac, 0x02, 0x90, 0xff, 0x61, 0xff, 0x69, 0x3c, 0x5b, 0x1d, 0x5c, 0x3a, 0x38, 0x9e, 0x5b, 0xe9, 0x00, 0x22, 0x64, 0x1e, 0x6c, 0x85, 0x5d, 0x24, 0x67, 0x9e, 0x5e, 0xfd, 0x1b, 0x19, 0x16, 0xc7, 0x38, 0x5b, 0x2d, 0x75, 0x16, 0xdd, 0x5b, 0x1a, 0x38, 0x85, 0x5d, 0x19, 0x17, 0xf5, 0x99, 0x3a, 0x38, 0x9e, 0x58, 0x15, 0x1e, 0x00, 0xac, 0x21, 0x90, 0xff, 0x61, 0x07, 0x69, 0x34, 0x38, 0xe3, 0x19, 0x18, 0x10, 0x1b, 0x88, 0x9e, 0x58, 0x1a, 0x1e, 0x02, 0x61, 0x19, 0x48, 0x16, 0x88, 0x9e, 0x58, 0xd6, 0x1a, 0xbe, 0x58, 0x47, 0x1e, 0xbe, 0x58, 0x04, 0xf8, 0x9e, 0x58, 0xda, 0x1a, 0xbe, 0x58, 0xb3, 0xf8, 0xff, 0x60, 0xff, 0x68, 0xbe, 0x58, 0x1a, 0x1e, 0x00, 0x60, 0xbe, 0x58, 0x1b, 0x1e, 0x24, 0x78, -0x80, 0x2d, 0xbe, 0x58, 0x1c, 0x1e, 0xff, 0x60, 0xbe, 0x58, 0x1d, 0x1e, 0x3a, 0x38, 0x9e, 0x58, 0x1a, 0x1e, 0x1a, 0x10, 0x04, 0x8a, 0x8f, 0xed, 0xc5, 0xed, 0xf5, 0xed, 0x1c, 0xee, 0x3a, 0x38, 0x9e, 0x5e, 0xe9, 0x00, 0x00, 0x65, 0xbe, 0x5d, 0x48, 0x1e, 0x9e, 0x5f, 0xfd, 0x1b, 0xbe, 0x5f, 0x49, 0x1e, 0x19, 0x17, 0xe6, 0x00, 0x03, 0x5b, 0x10, 0x38, 0xfd, 0x1b, 0x9e, 0x59, 0xfe, 0x1b, 0x1a, 0x11, 0x27, 0x38, 0xb4, 0x2d, 0x03, 0x5a, 0x10, 0x39, 0xfd, 0x1b, 0x23, 0x5c, 0x43, 0x13, 0x09, 0x9a, 0x44, 0x14, 0x07, 0x9a, 0x72, 0x39, 0x16, 0x1e, 0x03, 0x98, 0x92, 0x39, 0x16, 0x1e, 0x01, 0x9a, 0x19, 0x05, 0x41, 0x5b, 0x10, 0x38, 0xfd, 0x1b, 0x1a, 0x38, 0x9e, 0x5b, 0x48, 0x1e, 0x7d, 0x48, 0x02, 0x94, 0xbe, 0x5d, 0x48, 0x1e, 0x9e, 0x5b, 0x49, 0x1e, 0x7d, 0x48, 0x02, 0x9a, 0xbe, 0x5d, 0xc0, 0x63, -0xc0, 0x2d, 0x49, 0x1e, 0x00, 0x65, 0x19, 0x17, 0xd5, 0x95, 0x3a, 0x38, 0x9e, 0x5f, 0x1a, 0x1e, 0x19, 0x07, 0x18, 0x17, 0x01, 0x9a, 0x00, 0x67, 0xbe, 0x5f, 0x1a, 0x1e, 0x9e, 0x58, 0x48, 0x1e, 0x12, 0x39, 0x49, 0x1e, 0x06, 0x62, 0xd6, 0xac, 0x01, 0x90, 0x02, 0x62, 0xbe, 0x5a, 0x17, 0x1e, 0x12, 0x3a, 0x17, 0x1e, 0x08, 0x9a, 0x01, 0x67, 0xbe, 0x5f, 0x1a, 0x1e, 0x9e, 0x5f, 0x1b, 0x1e, 0x19, 0x07, 0xbe, 0x5f, 0x1b, 0x1e, 0x3a, 0x38, 0x00, 0x63, 0x9e, 0x58, 0x48, 0x1e, 0x12, 0x39, 0x49, 0x1e, 0x06, 0x62, 0xd6, 0xac, 0x01, 0x90, 0x02, 0x62, 0xbe, 0x5a, 0x17, 0x1e, 0x12, 0x3a, 0x17, 0x1e, 0x01, 0x9a, 0x01, 0x63, 0xbe, 0x5b, 0x1e, 0x1e, 0x3a, 0x38, 0x9e, 0x58, 0x1a, 0x1e, 0x18, 0x10, 0x1f, 0x8a, 0x9e, 0x58, 0x1b, 0x1e, 0x02, 0x39, 0x05, 0x00, 0x0a, 0x8a, 0x9e, 0x59, 0x48, 0x1e, 0xac, 0x7f, -0x00, 0x2e, 0x32, 0x3a, 0x1d, 0x1e, 0x18, 0x98, 0xbe, 0x59, 0x1d, 0x1e, 0xbe, 0x58, 0x1c, 0x1e, 0x13, 0x9e, 0x9e, 0x59, 0x15, 0x1e, 0x09, 0xac, 0x08, 0x92, 0x02, 0x67, 0xbe, 0x5f, 0x1a, 0x1e, 0x9e, 0x5f, 0x1c, 0x1e, 0xbe, 0x5f, 0x1b, 0x1e, 0x07, 0x9e, 0x00, 0x67, 0xbe, 0x5f, 0x1b, 0x1e, 0x03, 0x9e, 0x00, 0x63, 0xbe, 0x5b, 0x1e, 0x1e, 0x3a, 0x38, 0x9e, 0x58, 0x1a, 0x1e, 0x18, 0x10, 0x16, 0x8a, 0x9e, 0x58, 0x1b, 0x1e, 0x9e, 0x59, 0x15, 0x1e, 0x11, 0xac, 0x02, 0x90, 0x08, 0x58, 0x08, 0x58, 0xd6, 0xac, 0x03, 0x90, 0x00, 0x38, 0x77, 0x2e, 0x02, 0x9e, 0x00, 0x38, 0x7c, 0x2e, 0x09, 0x58, 0x9e, 0x59, 0xd6, 0x1a, 0x01, 0x00, 0x78, 0xa8, 0xbe, 0x58, 0x47, 0x1e, 0x3a, 0x38, 0x48, 0x62, 0x0e, 0x6a, 0x9e, 0x5b, 0xfd, 0x1b, 0x9e, 0x5c, 0xfd, 0x1b, 0x41, 0x5d, 0x00, 0x61, 0x00, 0x67, 0x9e, 0x10, -0x40, 0x2e, 0x9e, 0x5e, 0xfe, 0x1b, 0x19, 0x16, 0xc7, 0x38, 0x4a, 0x2e, 0xa3, 0x58, 0x18, 0x10, 0x02, 0x94, 0x19, 0x07, 0x20, 0x01, 0xa3, 0x05, 0x21, 0x58, 0x00, 0x61, 0x02, 0x58, 0x1c, 0x5f, 0x01, 0x59, 0x32, 0x39, 0x18, 0x1e, 0x0d, 0x9a, 0x41, 0x5d, 0x9e, 0x5e, 0xfe, 0x1b, 0x19, 0x16, 0x08, 0x58, 0xc7, 0x38, 0x5f, 0x2e, 0xa3, 0x5e, 0x18, 0x06, 0x02, 0x9a, 0xc0, 0x06, 0xdb, 0x5d, 0xa3, 0x05, 0x19, 0x02, 0x19, 0x14, 0xda, 0x89, 0x3a, 0x38, 0x01, 0x60, 0xbe, 0x58, 0x15, 0x1e, 0x40, 0x60, 0xbe, 0x58, 0x16, 0x1e, 0xff, 0x60, 0x1f, 0x68, 0xbe, 0x58, 0x18, 0x1e, 0x80, 0x60, 0xbe, 0x58, 0x19, 0x1e, 0x9e, 0x58, 0xd6, 0x1a, 0xbe, 0x58, 0x47, 0x1e, 0x79, 0xed, 0x3a, 0x38, 0x1d, 0x00, 0x1d, 0x00, 0x1d, 0x00, 0x1d, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8b, 0xaf, -0x80, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x00, 0x00, 0x08, 0x00, 0x18, 0x00, 0x30, 0x00, 0x38, 0x00, 0x3c, 0xab, 0x3a, 0x38, 0xfa, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x01, 0xd6, 0x1a, 0xd7, 0x1a, 0xd8, 0x1a, 0x57, 0x01, 0x5b, 0x01, 0x2d, 0x62, 0x01, 0x6a, 0x26, 0x63, 0x04, 0x6b, 0xeb, 0x64, 0x00, 0x67, 0x10, 0x6f, 0xef, 0x3a, 0xa3, 0x2e, 0x45, 0x5d, 0x65, 0x5e, 0x85, 0x58, 0xbb, 0x5e, 0x3a, 0x38, 0x9e, 0x5e, 0x20, 0x04, 0xc6, 0x5e, 0x7c, 0x62, 0x01, 0x6a, 0x94, 0x63, 0x01, 0x6b, 0x17, 0x64, 0x01, 0x6c, 0x01, 0x65, 0x01, 0x6d, 0xef, 0x3a, 0xb7, 0x2e, 0x45, 0x58, 0xc0, 0x40, 0x1d, 0x5c, 0x65, 0x58, 0xc0, 0x40, 0x1d, 0x5d, 0x3a, 0x38, 0xef, 0xa8, 0x9e, 0x58, 0x17, 0x04, 0x9e, 0x59, 0x1f, 0x04, 0x01, 0x10, 0x19, 0x48, 0x3d, 0x9e, -0xc0, 0x2e, 0x03, 0x9a, 0xbe, 0x58, 0x18, 0x04, 0x02, 0x9e, 0xbe, 0x59, 0x18, 0x04, 0x9e, 0x58, 0xb5, 0x00, 0x18, 0x10, 0x03, 0x8a, 0x19, 0x10, 0x01, 0x8a, 0x09, 0x9e, 0x9e, 0x58, 0x1d, 0x04, 0x18, 0x10, 0x04, 0x8a, 0x19, 0x10, 0xbe, 0x58, 0x1d, 0x04, 0x01, 0x9e, 0xef, 0xaa, 0x3a, 0x38, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xce, 0x31, +0x00, 0x24, 0x5d, 0xac, 0x01, 0x90, 0x03, 0x9e, 0x01, 0x65, 0xbe, 0x5d, 0x61, 0x1a, 0x9e, 0x5c, 0x02, 0x1d, 0x19, 0x04, 0xbe, 0x5c, 0x02, 0x1d, 0x00, 0x3c, 0x48, 0x0e, 0x83, 0x5b, 0x9e, 0x5a, 0x1d, 0x1f, 0x18, 0x12, 0x07, 0x88, 0x9e, 0x5d, 0x61, 0x1a, 0x05, 0xac, 0x0c, 0x92, 0x61, 0x12, 0x7a, 0xac, 0x09, 0x90, 0x3b, 0x5c, 0x01, 0x62, 0xbe, 0x5a, 0x62, 0x1a, 0x9e, 0x5a, 0x03, 0x1d, 0x19, 0x02, 0xbe, 0x5a, 0x03, 0x1d, 0x3e, 0x5b, 0x19, 0x13, 0x00, 0x62, 0x62, 0x14, 0x0a, 0x89, 0x3e, 0x5f, 0x3e, 0x5e, 0x3e, 0x5d, 0x3e, 0x5c, 0x3a, 0x38, 0x1e, 0x58, 0x1e, 0x59, 0x1e, 0x5a, 0x1e, 0x5b, 0x1e, 0x5c, 0x1e, 0x5d, 0x1e, 0x5e, 0x1e, 0x5f, 0x72, 0x62, 0x19, 0x6a, 0x86, 0x63, 0x19, 0x6b, 0x00, 0x60, 0xbe, 0x58, 0x71, 0x1a, 0x00, 0x67, 0x00, 0x60, 0x9e, 0x59, 0x58, 0x1a, 0x38, 0x48, 0xd6, 0xa1, +0x40, 0x24, 0x33, 0x8a, 0x19, 0x11, 0x27, 0x38, 0x73, 0x24, 0x40, 0x04, 0x83, 0x5d, 0x48, 0x64, 0x1d, 0x6c, 0x85, 0x04, 0x83, 0x5d, 0x15, 0x66, 0xbe, 0x48, 0x09, 0x82, 0x19, 0x04, 0x83, 0x5d, 0xbe, 0x48, 0x05, 0x82, 0x1a, 0x14, 0x83, 0x5d, 0xbe, 0x48, 0x01, 0x82, 0x13, 0x9e, 0x60, 0x04, 0x83, 0x5d, 0x48, 0x64, 0x1d, 0x6c, 0x85, 0x04, 0x90, 0x3c, 0xb8, 0x00, 0x83, 0x5d, 0x15, 0x66, 0xbe, 0x48, 0x10, 0x82, 0x19, 0x04, 0x83, 0x5d, 0xbe, 0x48, 0x0c, 0x82, 0x1a, 0x14, 0x83, 0x5d, 0xbe, 0x48, 0x08, 0x82, 0x19, 0x07, 0xbe, 0x5f, 0x71, 0x1a, 0x72, 0x65, 0x1a, 0x6d, 0xa7, 0x06, 0x19, 0x16, 0x1b, 0x5e, 0x1a, 0x38, 0x1a, 0x38, 0x19, 0x00, 0x3e, 0x5f, 0x3e, 0x5e, 0x3e, 0x5d, 0x3e, 0x5c, 0x3e, 0x5b, 0x3e, 0x5a, 0x3e, 0x59, 0x3e, 0x58, 0x3a, 0x38, 0x00, 0x67, 0xdf, 0x60, 0x1e, 0x68, 0x67, 0xd8, +0x80, 0x24, 0x2f, 0x39, 0x84, 0x24, 0xfd, 0x58, 0x1a, 0x38, 0x1a, 0x38, 0x00, 0x67, 0x50, 0x65, 0x04, 0x6d, 0x9e, 0x5c, 0xb8, 0x00, 0x9e, 0x5e, 0xb9, 0x00, 0x86, 0x04, 0x19, 0x14, 0x87, 0x38, 0x92, 0x24, 0xfd, 0x5d, 0x1a, 0x38, 0x1a, 0x38, 0xbe, 0x5f, 0xdb, 0x1e, 0xbe, 0x5f, 0xdc, 0x1e, 0x9e, 0x58, 0x4d, 0x04, 0x9e, 0x59, 0x4f, 0x04, 0x01, 0x00, 0x02, 0x3a, 0xb0, 0x00, 0x01, 0x98, 0x3a, 0x38, 0x00, 0x61, 0x9e, 0x58, 0x4d, 0x04, 0x9e, 0x5a, 0xdd, 0x1e, 0x1c, 0x5a, 0x02, 0x39, 0x20, 0x00, 0x01, 0x98, 0x20, 0x60, 0x00, 0x61, 0x01, 0x62, 0x00, 0x67, 0x50, 0x65, 0x04, 0x6d, 0x48, 0x63, 0x1d, 0x6b, 0x9e, 0x5c, 0xb8, 0x00, 0x19, 0x14, 0x87, 0x38, 0xcd, 0x24, 0x65, 0x5c, 0x98, 0x48, 0x06, 0x80, 0x5b, 0x5d, 0xbe, 0x5a, 0xdb, 0x1e, 0x19, 0x01, 0x01, 0x67, 0x0e, 0x9e, 0x07, 0xac, 0xaf, 0x52, +0xc0, 0x24, 0x0c, 0x90, 0x1e, 0x5d, 0x40, 0x3d, 0xdf, 0x1e, 0x19, 0x15, 0x50, 0x48, 0x08, 0x00, 0x01, 0x8a, 0x3b, 0x5d, 0x3e, 0x5d, 0x00, 0x61, 0x00, 0x67, 0x19, 0x02, 0x19, 0x05, 0x1e, 0x5d, 0x40, 0x3d, 0xdf, 0x1e, 0x19, 0x15, 0x50, 0x48, 0x08, 0x00, 0x01, 0x8a, 0x3b, 0x5d, 0x3e, 0x5d, 0x00, 0x61, 0x9e, 0x58, 0x4f, 0x04, 0x9e, 0x5a, 0xdd, 0x1e, 0x1c, 0x5a, 0x02, 0x39, 0x20, 0x00, 0x01, 0x98, 0x20, 0x60, 0x00, 0x61, 0x01, 0x62, 0x00, 0x67, 0x50, 0x65, 0x04, 0x6d, 0x48, 0x63, 0x1d, 0x6b, 0x9e, 0x5c, 0xb8, 0x00, 0xa4, 0x05, 0x64, 0x03, 0x9e, 0x5c, 0xb9, 0x00, 0x19, 0x14, 0x87, 0x38, 0x0d, 0x25, 0x65, 0x5c, 0x98, 0x48, 0x06, 0x80, 0x5b, 0x5d, 0xbe, 0x5a, 0xdc, 0x1e, 0x19, 0x01, 0x01, 0x67, 0x13, 0x9e, 0x07, 0xac, 0x11, 0x90, 0x1e, 0x5d, 0x1e, 0x5e, 0x40, 0x3d, 0xdf, 0x1e, 0xc9, 0x52, +0x00, 0x25, 0x19, 0x15, 0x50, 0x48, 0x08, 0x00, 0x04, 0x8a, 0xa3, 0x5e, 0xfe, 0x59, 0xc1, 0x06, 0xdb, 0x5d, 0x3e, 0x5e, 0x3e, 0x5d, 0x00, 0x61, 0x00, 0x67, 0x19, 0x02, 0x19, 0x05, 0x1e, 0x5d, 0x1e, 0x5e, 0x40, 0x3d, 0xdf, 0x1e, 0x19, 0x15, 0x50, 0x48, 0x08, 0x00, 0x04, 0x8a, 0xa3, 0x5e, 0xfe, 0x59, 0xc1, 0x06, 0xdb, 0x5d, 0x3e, 0x5e, 0x3e, 0x5d, 0x00, 0x60, 0xbe, 0x58, 0xe8, 0x1e, 0xbe, 0x58, 0xe7, 0x1e, 0xdf, 0x62, 0x1e, 0x6a, 0x01, 0x67, 0xef, 0x38, 0x2e, 0x25, 0x45, 0x5b, 0x64, 0x3b, 0xff, 0x00, 0x78, 0x48, 0x02, 0x96, 0x61, 0x58, 0xe1, 0x5c, 0x19, 0x07, 0x1a, 0x38, 0xbe, 0x5c, 0xe7, 0x1e, 0xdf, 0x62, 0x1e, 0x6a, 0x01, 0x67, 0x00, 0x60, 0xef, 0x38, 0x40, 0x25, 0x45, 0x5b, 0xfe, 0x5b, 0x64, 0x3b, 0xff, 0x00, 0x78, 0x48, 0x02, 0x96, 0x61, 0x58, 0xe1, 0x5d, 0x19, 0x07, 0x33, 0xd5, +0x40, 0x25, 0x1a, 0x38, 0xbe, 0x5d, 0xe8, 0x1e, 0x7a, 0x60, 0x02, 0x68, 0x50, 0x61, 0x04, 0x69, 0x39, 0x62, 0x47, 0x38, 0x4d, 0x25, 0x23, 0x5b, 0x7b, 0x58, 0x19, 0x01, 0x19, 0x00, 0x3a, 0x38, 0x92, 0x62, 0xf8, 0x6a, 0x00, 0x64, 0x17, 0x63, 0x67, 0x38, 0x57, 0x25, 0x45, 0x5b, 0x83, 0x04, 0x1a, 0x38, 0xfe, 0x5c, 0x84, 0x3c, 0x00, 0xff, 0x9e, 0x5f, 0x34, 0x1d, 0xe0, 0x3b, 0x30, 0x1d, 0x9e, 0x59, 0xb5, 0x00, 0x24, 0x29, 0x3b, 0x5b, 0x30, 0x63, 0x1d, 0x6b, 0x00, 0x60, 0xbe, 0x58, 0x36, 0x1d, 0x04, 0x65, 0x19, 0x15, 0xa7, 0x38, 0x70, 0x25, 0x63, 0x5e, 0xc4, 0x3e, 0xff, 0x00, 0x06, 0x00, 0x19, 0x03, 0x19, 0x05, 0x00, 0x61, 0x1c, 0x5d, 0xbe, 0x58, 0x35, 0x1d, 0x30, 0x63, 0x1d, 0x6b, 0x04, 0x65, 0x19, 0x15, 0xa7, 0x38, 0x81, 0x25, 0x63, 0x5e, 0xc4, 0x3e, 0x00, 0xff, 0xfe, 0x5e, 0x97, 0xe9, +0x80, 0x25, 0x06, 0x00, 0x19, 0x03, 0x19, 0x05, 0x00, 0x61, 0x1c, 0x5d, 0x01, 0x5b, 0xbe, 0x58, 0xbc, 0x1d, 0x9e, 0x58, 0x35, 0x1d, 0x19, 0x07, 0xe2, 0x3a, 0x04, 0x00, 0x01, 0x88, 0x00, 0x67, 0xbe, 0x5f, 0x34, 0x1d, 0x01, 0x61, 0x9e, 0x5a, 0xb1, 0x04, 0x42, 0x3f, 0x01, 0x00, 0x11, 0x8a, 0x01, 0x61, 0x02, 0x3f, 0x04, 0x00, 0x0d, 0x9a, 0x04, 0x61, 0x02, 0x3f, 0x06, 0x00, 0x09, 0x9a, 0x02, 0x61, 0x02, 0x3f, 0x08, 0x00, 0x05, 0x9a, 0x03, 0x61, 0x02, 0x3f, 0x0a, 0x00, 0x01, 0x9a, 0x01, 0x61, 0xbe, 0x59, 0x36, 0x1d, 0x1a, 0x38, 0x3a, 0x38, 0x1e, 0x58, 0x1e, 0x59, 0x1e, 0x5a, 0x1e, 0x5b, 0x1e, 0x5d, 0x1e, 0x5e, 0x1e, 0x5f, 0x00, 0x63, 0x00, 0x65, 0x9c, 0x60, 0x1e, 0x68, 0x9e, 0x59, 0xb8, 0x00, 0x19, 0x11, 0x27, 0x38, 0xc1, 0x25, 0x03, 0x5a, 0x5b, 0x48, 0x01, 0x96, 0x41, 0x5b, 0xce, 0x09, +0xc0, 0x25, 0x19, 0x00, 0x1a, 0x38, 0xbe, 0x5b, 0x60, 0x1e, 0x9e, 0x59, 0xb9, 0x00, 0x19, 0x11, 0x27, 0x38, 0xce, 0x25, 0x03, 0x5a, 0x5d, 0x48, 0x01, 0x96, 0x41, 0x5d, 0x19, 0x00, 0x1a, 0x38, 0xbe, 0x5d, 0x5f, 0x1e, 0x10, 0x64, 0x65, 0x02, 0x50, 0x48, 0x00, 0x01, 0x0b, 0x80, 0x61, 0x58, 0x7d, 0x48, 0x01, 0x98, 0xa1, 0x58, 0x01, 0x5c, 0x00, 0x61, 0x07, 0x62, 0x82, 0x40, 0x0a, 0x62, 0x1c, 0x5a, 0x01, 0x5c, 0xbe, 0x5c, 0x61, 0x1e, 0x3e, 0x5f, 0x3e, 0x5e, 0x3e, 0x5d, 0x3e, 0x5b, 0x3e, 0x5a, 0x3e, 0x59, 0x3e, 0x58, 0x3a, 0x38, 0x9e, 0x58, 0xf1, 0x04, 0x9e, 0x59, 0xf2, 0x04, 0x01, 0x00, 0x10, 0x48, 0x05, 0x00, 0x18, 0x3e, 0x4f, 0x27, 0x9e, 0x58, 0xdb, 0x1e, 0x10, 0x48, 0x02, 0x00, 0x18, 0x3e, 0x4f, 0x27, 0x9e, 0x59, 0xdc, 0x1e, 0x30, 0x48, 0x02, 0x00, 0x18, 0x3e, 0x4f, 0x27, 0x15, 0x0e, +0x00, 0x26, 0x9e, 0x58, 0x45, 0x04, 0x02, 0x38, 0x50, 0x01, 0x3d, 0x98, 0xdf, 0x60, 0x1e, 0x68, 0x05, 0x59, 0x24, 0x3a, 0xff, 0x00, 0xfe, 0x59, 0x24, 0x3b, 0xff, 0x00, 0x43, 0x06, 0x03, 0x59, 0x24, 0x3c, 0xff, 0x00, 0xfe, 0x59, 0x24, 0x3d, 0xff, 0x00, 0x85, 0x07, 0xc7, 0x00, 0x38, 0x10, 0x2a, 0x98, 0xd0, 0x48, 0x06, 0x00, 0x27, 0x98, 0xf0, 0x48, 0x06, 0x00, 0x24, 0x98, 0x45, 0x00, 0x10, 0x48, 0x06, 0x00, 0x20, 0x98, 0x64, 0x00, 0x10, 0x48, 0x06, 0x00, 0x1c, 0x98, 0x9e, 0x58, 0x4d, 0x04, 0x9e, 0x59, 0x4f, 0x04, 0x19, 0x48, 0x01, 0x98, 0x21, 0x58, 0x9e, 0x59, 0x44, 0x04, 0x19, 0x48, 0x10, 0x80, 0x9e, 0x58, 0xf1, 0x04, 0x19, 0x10, 0x04, 0x88, 0x9e, 0x58, 0x8a, 0x04, 0x1a, 0x10, 0x09, 0x98, 0x9e, 0x58, 0xf2, 0x04, 0x19, 0x10, 0x04, 0x88, 0x9e, 0x58, 0x8b, 0x04, 0x1a, 0x10, 0x1d, 0x27, +0x40, 0x26, 0x01, 0x98, 0xfc, 0x9e, 0x9e, 0x59, 0x4e, 0x04, 0x30, 0x48, 0x00, 0x00, 0x8a, 0x8a, 0x9e, 0x59, 0x4e, 0x04, 0x30, 0x48, 0x23, 0x00, 0x85, 0x8a, 0x9e, 0x59, 0x4c, 0x04, 0x30, 0x48, 0x00, 0x00, 0x80, 0x8a, 0x9e, 0x59, 0x4c, 0x04, 0x30, 0x48, 0x15, 0x00, 0x7b, 0x8a, 0x9e, 0x58, 0x46, 0x04, 0x9e, 0x59, 0x47, 0x04, 0x01, 0x00, 0x02, 0x38, 0x40, 0x00, 0x08, 0x98, 0x9e, 0x58, 0xdb, 0x1e, 0x9e, 0x59, 0xdc, 0x1e, 0x01, 0x00, 0x02, 0x39, 0x02, 0x00, 0x12, 0x8a, 0x9e, 0x58, 0x46, 0x04, 0x38, 0x10, 0x67, 0x98, 0x9e, 0x58, 0xdb, 0x1e, 0x9e, 0x59, 0xdc, 0x1e, 0x01, 0x00, 0x1b, 0x10, 0x60, 0x88, 0x9e, 0x58, 0xf1, 0x04, 0x9e, 0x59, 0xf2, 0x04, 0x01, 0x10, 0x5a, 0x8a, 0x28, 0x9e, 0x80, 0x60, 0x01, 0x68, 0xbe, 0x58, 0x20, 0x1d, 0x9e, 0x58, 0x4d, 0x04, 0x9e, 0x59, 0x4f, 0x04, 0xd4, 0xd9, +0x80, 0x26, 0x19, 0x48, 0x01, 0x9a, 0x21, 0x58, 0xbe, 0x58, 0x14, 0x1f, 0x51, 0xe7, 0x01, 0x60, 0x01, 0x61, 0xb8, 0xe7, 0x9e, 0x58, 0x0d, 0x1f, 0x18, 0x10, 0xb1, 0x8a, 0x00, 0x63, 0xbe, 0x5b, 0x0e, 0x1f, 0xbe, 0x5b, 0x10, 0x1f, 0x9e, 0x5b, 0xb8, 0x00, 0x19, 0x13, 0xbe, 0x5b, 0x0f, 0x1f, 0x9e, 0x5b, 0xb9, 0x00, 0x19, 0x13, 0xbe, 0x5b, 0x11, 0x1f, 0x01, 0x60, 0x01, 0x61, 0x77, 0xe7, 0x9e, 0x9e, 0x9e, 0x58, 0x46, 0x04, 0x9e, 0x59, 0x47, 0x04, 0x19, 0x48, 0x98, 0x98, 0x68, 0x60, 0x01, 0x68, 0xbe, 0x58, 0x20, 0x1d, 0x76, 0xde, 0x9e, 0x58, 0x4d, 0x04, 0x9e, 0x59, 0x4f, 0x04, 0x19, 0x48, 0x01, 0x9a, 0x21, 0x58, 0x08, 0x58, 0xbe, 0x58, 0x14, 0x1f, 0x00, 0x63, 0xbe, 0x5b, 0x0e, 0x1f, 0xbe, 0x5b, 0x10, 0x1f, 0x9e, 0x5b, 0xb8, 0x00, 0x19, 0x13, 0xbe, 0x5b, 0x0f, 0x1f, 0x9e, 0x5b, 0xd0, 0x0a, +0xc0, 0x26, 0xb9, 0x00, 0x19, 0x13, 0xbe, 0x5b, 0x11, 0x1f, 0x01, 0x60, 0x01, 0x61, 0x77, 0xe7, 0x01, 0x60, 0x02, 0x61, 0x77, 0xe7, 0x02, 0x60, 0x01, 0x61, 0x77, 0xe7, 0x02, 0x60, 0x02, 0x61, 0x77, 0xe7, 0x6d, 0x9e, 0x0c, 0x60, 0xbe, 0x58, 0xdd, 0x1e, 0x7d, 0xe4, 0xdf, 0x60, 0x1e, 0x68, 0x05, 0x59, 0x24, 0x3a, 0xff, 0x00, 0xfe, 0x59, 0x24, 0x3b, 0xff, 0x00, 0x43, 0x06, 0x03, 0x59, 0x24, 0x3c, 0xff, 0x00, 0xfe, 0x59, 0x24, 0x3d, 0xff, 0x00, 0x85, 0x07, 0xd0, 0x48, 0x0f, 0x00, 0x04, 0x98, 0xf0, 0x48, 0x0f, 0x00, 0x01, 0x98, 0x04, 0x9e, 0x04, 0x60, 0xbe, 0x58, 0xdd, 0x1e, 0x7d, 0xe4, 0x9e, 0x58, 0xdb, 0x1e, 0x9e, 0x59, 0xdc, 0x1e, 0x01, 0x00, 0x1a, 0x10, 0x0b, 0x88, 0x60, 0x60, 0xbe, 0x58, 0x20, 0x1d, 0x9e, 0x58, 0xf1, 0x04, 0x9e, 0x59, 0xf2, 0x04, 0x01, 0x00, 0x1c, 0x10, 0xc5, 0x27, +0x00, 0x27, 0x4e, 0x88, 0x3c, 0x9e, 0x66, 0x60, 0xbe, 0x58, 0x20, 0x1d, 0x70, 0xe8, 0x01, 0x60, 0x01, 0x61, 0xb8, 0xe7, 0x9e, 0x58, 0x0d, 0x1f, 0x1e, 0x10, 0x03, 0x80, 0x01, 0x60, 0x01, 0x61, 0x77, 0xe7, 0x01, 0x60, 0x02, 0x61, 0xb8, 0xe7, 0x9e, 0x58, 0x0d, 0x1f, 0x1e, 0x10, 0x03, 0x80, 0x01, 0x60, 0x02, 0x61, 0x77, 0xe7, 0x02, 0x60, 0x01, 0x61, 0xb8, 0xe7, 0x9e, 0x58, 0x0d, 0x1f, 0x1e, 0x10, 0x03, 0x80, 0x02, 0x60, 0x01, 0x61, 0x77, 0xe7, 0x02, 0x60, 0x02, 0x61, 0xb8, 0xe7, 0x9e, 0x58, 0x0d, 0x1f, 0x1e, 0x10, 0x03, 0x80, 0x02, 0x60, 0x02, 0x61, 0x77, 0xe7, 0x98, 0xe2, 0x06, 0x71, 0x09, 0xac, 0x0c, 0x92, 0x01, 0xac, 0x0a, 0x92, 0x51, 0xac, 0x08, 0x92, 0x9e, 0x58, 0x20, 0x1d, 0x00, 0x61, 0x19, 0x48, 0x03, 0x8a, 0x01, 0x60, 0xbe, 0x58, 0x44, 0x1a, 0x9e, 0x58, 0x8a, 0x04, 0x5e, 0x57, +0x40, 0x27, 0x10, 0x48, 0x0a, 0x00, 0x05, 0x98, 0x9e, 0x58, 0x8b, 0x04, 0x10, 0x48, 0x0a, 0x00, 0x03, 0x9c, 0x01, 0x60, 0xbe, 0x58, 0x1d, 0x1f, 0x98, 0xe2, 0x00, 0x60, 0xbe, 0x58, 0x1d, 0x1f, 0x1a, 0x38, 0x3a, 0x38, 0x9e, 0x58, 0xb8, 0x00, 0x1b, 0x10, 0x7a, 0x61, 0x02, 0x69, 0x60, 0xe7, 0x9e, 0x58, 0xb9, 0x00, 0x1b, 0x10, 0x7a, 0x61, 0x02, 0x69, 0x30, 0x39, 0xb8, 0x00, 0x60, 0xe7, 0x3a, 0x38, 0x19, 0x01, 0x00, 0x66, 0x07, 0x38, 0x75, 0x27, 0x23, 0x5a, 0x18, 0x12, 0x08, 0x8a, 0x18, 0x16, 0x04, 0x88, 0x21, 0x5b, 0x19, 0x13, 0x01, 0x64, 0x9b, 0x5b, 0x01, 0x66, 0x06, 0x9e, 0x18, 0x16, 0x04, 0x8a, 0x21, 0x5b, 0x01, 0x64, 0x9b, 0x5b, 0x00, 0x66, 0x19, 0x01, 0x3a, 0x38, 0xbe, 0x58, 0x82, 0x1d, 0xbe, 0x59, 0x83, 0x1d, 0x9e, 0x5e, 0x10, 0x1f, 0x9e, 0x5f, 0x0e, 0x1f, 0x7a, 0x63, 0x57, 0x28, +0x80, 0x27, 0x02, 0x6b, 0x67, 0x03, 0x63, 0x5b, 0x9e, 0x59, 0x82, 0x1d, 0x79, 0x48, 0x26, 0x88, 0x48, 0x63, 0x1d, 0x6b, 0x67, 0x03, 0x63, 0x5b, 0x18, 0x13, 0x20, 0x8a, 0x7a, 0x62, 0x02, 0x6a, 0x50, 0x3a, 0xb8, 0x00, 0x46, 0x02, 0x43, 0x5a, 0x9e, 0x59, 0x83, 0x1d, 0x59, 0x48, 0x16, 0x88, 0x48, 0x62, 0x1d, 0x6a, 0x50, 0x3a, 0xb8, 0x00, 0x46, 0x02, 0x43, 0x5a, 0x00, 0x61, 0x61, 0x58, 0x43, 0x40, 0x9e, 0x5d, 0x14, 0x1f, 0x1c, 0x5d, 0x01, 0x5d, 0x9e, 0x5c, 0xb8, 0x00, 0x00, 0x61, 0xe1, 0x58, 0x86, 0x48, 0x48, 0x64, 0x0e, 0x6c, 0x80, 0x04, 0xbb, 0x5c, 0x19, 0x07, 0x9e, 0x5a, 0x0f, 0x1f, 0xfa, 0x48, 0xcd, 0x9d, 0x19, 0x06, 0x9e, 0x5a, 0x11, 0x1f, 0xda, 0x48, 0xc6, 0x9d, 0x3a, 0x38, 0x9e, 0x5b, 0xb8, 0x00, 0xbe, 0x5b, 0x0e, 0x1f, 0x00, 0x63, 0xbe, 0x5b, 0x0f, 0x1f, 0x9e, 0x5b, 0x82, 0xeb, +0xc0, 0x27, 0xb9, 0x00, 0xbe, 0x5b, 0x10, 0x1f, 0x00, 0x63, 0xbe, 0x5b, 0x11, 0x1f, 0x00, 0x63, 0xbe, 0x5b, 0x0d, 0x1f, 0x01, 0x63, 0xbe, 0x5b, 0x12, 0x1f, 0xbe, 0x5b, 0x13, 0x1f, 0x00, 0x63, 0x00, 0x65, 0xbe, 0x58, 0x00, 0x1d, 0xbe, 0x59, 0x04, 0x1d, 0x00, 0x66, 0x00, 0x67, 0x7a, 0x62, 0x02, 0x6a, 0x47, 0x02, 0x43, 0x5a, 0x9e, 0x59, 0x00, 0x1d, 0x59, 0x48, 0x61, 0x88, 0x7a, 0x62, 0x02, 0x6a, 0x50, 0x3a, 0xb8, 0x00, 0x46, 0x02, 0x43, 0x5a, 0x9e, 0x59, 0x04, 0x1d, 0x59, 0x48, 0x57, 0x88, 0x48, 0x62, 0x1d, 0x6a, 0x47, 0x02, 0x43, 0x5a, 0x9e, 0x59, 0x12, 0x1f, 0x59, 0x48, 0x02, 0x9a, 0xbe, 0x5a, 0x12, 0x1f, 0x48, 0x62, 0x1d, 0x6a, 0x50, 0x3a, 0xb8, 0x00, 0x46, 0x02, 0x43, 0x5a, 0x9e, 0x59, 0x13, 0x1f, 0x59, 0x48, 0x02, 0x9a, 0xbe, 0x5a, 0x13, 0x1f, 0x9e, 0x5c, 0xb8, 0x00, 0xb3, 0xe8, +0x00, 0x28, 0x00, 0x61, 0xe1, 0x58, 0x86, 0x48, 0x32, 0x64, 0x16, 0x6c, 0x9e, 0x5d, 0x20, 0x1d, 0xb0, 0x48, 0x66, 0x00, 0x02, 0x88, 0x48, 0x64, 0x0e, 0x6c, 0x80, 0x04, 0x83, 0x59, 0x79, 0xac, 0x2f, 0x92, 0x10, 0x60, 0x38, 0x48, 0x2c, 0x9a, 0x9e, 0x58, 0x0e, 0x1f, 0xf8, 0x48, 0x07, 0x98, 0xbe, 0x5f, 0x0e, 0x1f, 0x9e, 0x58, 0x0d, 0x1f, 0x19, 0x00, 0xbe, 0x58, 0x0d, 0x1f, 0x9e, 0x58, 0x0f, 0x1f, 0xf8, 0x48, 0x07, 0x80, 0xbe, 0x5f, 0x0f, 0x1f, 0x9e, 0x58, 0x0d, 0x1f, 0x19, 0x00, 0xbe, 0x58, 0x0d, 0x1f, 0x9e, 0x58, 0x10, 0x1f, 0xd8, 0x48, 0x07, 0x98, 0xbe, 0x5e, 0x10, 0x1f, 0x9e, 0x58, 0x0d, 0x1f, 0x19, 0x00, 0xbe, 0x58, 0x0d, 0x1f, 0x9e, 0x58, 0x11, 0x1f, 0xd8, 0x48, 0x07, 0x80, 0xbe, 0x5e, 0x11, 0x1f, 0x9e, 0x58, 0x0d, 0x1f, 0x19, 0x00, 0xbe, 0x58, 0x0d, 0x1f, 0x19, 0x07, 0xf7, 0xe6, +0x40, 0x28, 0x9e, 0x5a, 0xb8, 0x00, 0x19, 0x12, 0xfa, 0x48, 0x91, 0x9d, 0x19, 0x06, 0x9e, 0x5a, 0xb9, 0x00, 0x19, 0x12, 0xda, 0x48, 0x8a, 0x9d, 0x9e, 0x58, 0x12, 0x1f, 0x9e, 0x59, 0x13, 0x1f, 0x38, 0x48, 0x01, 0x98, 0x21, 0x58, 0x9e, 0x5e, 0x4d, 0x04, 0x9e, 0x5f, 0x4f, 0x04, 0xc7, 0x06, 0xc2, 0x3e, 0x00, 0x06, 0x04, 0x80, 0x02, 0x39, 0x40, 0x01, 0x01, 0x98, 0x10, 0x60, 0x02, 0x39, 0x80, 0x03, 0x02, 0x80, 0x08, 0x59, 0x01, 0x00, 0x9e, 0x5e, 0x12, 0x1f, 0x9e, 0x5f, 0x13, 0x1f, 0xc7, 0x06, 0xc2, 0x3e, 0x00, 0x02, 0x02, 0x98, 0x08, 0x58, 0x08, 0x58, 0xbe, 0x58, 0x14, 0x1f, 0x3a, 0x38, 0x00, 0x62, 0x7a, 0x67, 0x02, 0x6f, 0x16, 0x60, 0xe5, 0x5c, 0x18, 0x14, 0x01, 0x88, 0x8b, 0xe8, 0x19, 0x02, 0x19, 0x10, 0x18, 0x10, 0xf8, 0x89, 0x00, 0x62, 0x7a, 0x67, 0x02, 0x6f, 0x16, 0x66, 0x1e, 0xda, +0x80, 0x28, 0xe6, 0x07, 0x24, 0x66, 0xe5, 0x5c, 0x18, 0x14, 0x01, 0x88, 0x98, 0xe8, 0x19, 0x02, 0x19, 0x16, 0x18, 0x16, 0xf8, 0x89, 0x3a, 0x38, 0x00, 0x64, 0x48, 0x63, 0x0e, 0x6b, 0x62, 0x03, 0x16, 0x65, 0x24, 0x66, 0x19, 0x16, 0xc7, 0x38, 0x96, 0x28, 0x9b, 0x5b, 0x65, 0x03, 0x1a, 0x38, 0x3a, 0x38, 0x00, 0x64, 0x16, 0x65, 0x48, 0x63, 0x0e, 0x6b, 0x00, 0x61, 0x00, 0x60, 0x45, 0x40, 0x03, 0x03, 0x16, 0x65, 0x19, 0x15, 0xa7, 0x38, 0xa6, 0x28, 0x9d, 0x5b, 0x1a, 0x38, 0x1a, 0x38, 0x3a, 0x38, 0x48, 0x60, 0x1d, 0x68, 0x9c, 0x61, 0x1e, 0x69, 0x9e, 0x5b, 0x4c, 0x04, 0x70, 0x48, 0x00, 0x00, 0x0c, 0x8a, 0x9e, 0x5b, 0x4c, 0x04, 0x70, 0x48, 0x01, 0x00, 0x0f, 0x8a, 0x70, 0x48, 0x14, 0x00, 0x15, 0x8a, 0x70, 0x48, 0x15, 0x00, 0x1b, 0x8a, 0x23, 0x9e, 0x03, 0x00, 0x23, 0x01, 0x4f, 0x38, 0x53, 0xa0, +0xc0, 0x28, 0xc3, 0x28, 0x05, 0x5a, 0x5d, 0x59, 0x1a, 0x38, 0x23, 0x9e, 0x19, 0x13, 0x03, 0x00, 0x23, 0x01, 0x6f, 0x38, 0xcc, 0x28, 0x05, 0x5a, 0x5d, 0x59, 0x1a, 0x38, 0x1a, 0x9e, 0x19, 0x13, 0x03, 0x00, 0x23, 0x01, 0x4f, 0x38, 0xd5, 0x28, 0x05, 0x5a, 0x5d, 0x59, 0x1a, 0x38, 0x11, 0x9e, 0x1a, 0x13, 0x03, 0x00, 0x23, 0x01, 0x4f, 0x38, 0xde, 0x28, 0x05, 0x5a, 0x5d, 0x59, 0x1a, 0x38, 0x08, 0x9e, 0x1a, 0x13, 0x03, 0x00, 0x23, 0x01, 0x8f, 0x38, 0xe7, 0x28, 0x05, 0x5a, 0x5d, 0x59, 0x1a, 0x38, 0x48, 0x60, 0x1d, 0x68, 0x10, 0x38, 0xb8, 0x00, 0x9c, 0x61, 0x1e, 0x69, 0x30, 0x39, 0xb8, 0x00, 0x9e, 0x5b, 0x4e, 0x04, 0x70, 0x48, 0x00, 0x00, 0x0c, 0x8a, 0x9e, 0x5b, 0x4e, 0x04, 0x70, 0x48, 0x01, 0x00, 0x0f, 0x8a, 0x70, 0x48, 0x22, 0x00, 0x15, 0x8a, 0x70, 0x48, 0x23, 0x00, 0x1b, 0x8a, 0x3d, 0x49, +0x00, 0x29, 0x23, 0x9e, 0x03, 0x00, 0x23, 0x01, 0x4f, 0x38, 0x07, 0x29, 0x05, 0x5a, 0x5d, 0x59, 0x1a, 0x38, 0x23, 0x9e, 0x19, 0x13, 0x03, 0x00, 0x23, 0x01, 0x6f, 0x38, 0x10, 0x29, 0x05, 0x5a, 0x5d, 0x59, 0x1a, 0x38, 0x1a, 0x9e, 0x19, 0x13, 0x03, 0x00, 0x23, 0x01, 0x4f, 0x38, 0x19, 0x29, 0x05, 0x5a, 0x5d, 0x59, 0x1a, 0x38, 0x11, 0x9e, 0x1a, 0x13, 0x03, 0x00, 0x23, 0x01, 0x4f, 0x38, 0x22, 0x29, 0x05, 0x5a, 0x5d, 0x59, 0x1a, 0x38, 0x08, 0x9e, 0x1a, 0x13, 0x03, 0x00, 0x23, 0x01, 0x8f, 0x38, 0x2b, 0x29, 0x05, 0x5a, 0x5d, 0x59, 0x1a, 0x38, 0x1a, 0x38, 0x3a, 0x38, 0x1e, 0x58, 0x1e, 0x59, 0x1e, 0x5a, 0x1e, 0x5b, 0x1e, 0x5c, 0x1e, 0x5d, 0x1e, 0x5e, 0x1e, 0x5f, 0x00, 0x66, 0x00, 0x67, 0x9c, 0x63, 0x1e, 0x6b, 0x67, 0x03, 0x63, 0x5b, 0x18, 0x13, 0x24, 0x8a, 0x48, 0x62, 0x1d, 0x6a, 0xda, 0xc3, +0x40, 0x29, 0x50, 0x3a, 0xb8, 0x00, 0x46, 0x02, 0x43, 0x5a, 0x00, 0x61, 0x59, 0x48, 0x1b, 0x8a, 0x9c, 0x62, 0x1e, 0x6a, 0x50, 0x3a, 0xb8, 0x00, 0x46, 0x02, 0x43, 0x5a, 0x00, 0x61, 0x61, 0x58, 0x43, 0x40, 0x9e, 0x5d, 0x61, 0x1e, 0x1c, 0x5d, 0x01, 0x5d, 0x9e, 0x5c, 0xb8, 0x00, 0x00, 0x61, 0xe1, 0x58, 0x86, 0x48, 0x32, 0x64, 0x16, 0x6c, 0x80, 0x04, 0x48, 0x63, 0x0e, 0x6b, 0x60, 0x03, 0xbb, 0x5c, 0xbb, 0x5b, 0x0e, 0x9e, 0x9e, 0x5c, 0xb8, 0x00, 0x00, 0x61, 0xe1, 0x58, 0x86, 0x48, 0x32, 0x64, 0x16, 0x6c, 0x80, 0x04, 0x48, 0x63, 0x0e, 0x6b, 0x60, 0x03, 0x00, 0x65, 0xbb, 0x5c, 0xbb, 0x5b, 0x19, 0x07, 0x9e, 0x5a, 0xb8, 0x00, 0x19, 0x12, 0xfa, 0x48, 0xc2, 0x9d, 0x19, 0x06, 0x9e, 0x5a, 0xb9, 0x00, 0x19, 0x12, 0xda, 0x48, 0xbb, 0x9d, 0x3e, 0x5f, 0x3e, 0x5e, 0x3e, 0x5d, 0x3e, 0x5c, 0x1a, 0x35, +0x80, 0x29, 0x3e, 0x5b, 0x3e, 0x5a, 0x3e, 0x59, 0x3e, 0x58, 0x3a, 0x38, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0x40, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0x40, 0x00, 0x80, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x08, 0x00, 0xe0, 0xac, 0x98, 0x3c, 0xbb, 0x2a, 0x9d, 0x60, 0x4e, 0x68, 0xef, 0xb0, 0x52, 0xb1, 0x39, 0xac, 0xfd, 0x93, 0x00, 0xbc, 0xbc, 0x00, 0x78, 0xa8, 0x70, 0xa8, 0x00, 0xbd, 0xbc, 0x00, 0x00, 0xbc, 0xb1, 0x00, 0x38, 0xa8, 0x70, 0xa8, 0x00, 0xbd, 0xb1, 0x00, 0x00, 0xbc, 0x1c, 0x00, 0x78, 0xaa, 0x00, 0xbd, 0x1c, 0x00, 0x9e, 0x58, 0x00, 0xf8, 0x00, 0xa8, 0xbe, 0x58, 0x00, 0xf8, 0x00, 0x60, 0xbe, 0x58, 0x0f, 0xf8, 0xbe, 0x58, 0x10, 0xf8, 0x00, 0xbc, 0xb1, 0x00, 0x30, 0xaa, 0x47, 0xb4, +0xc0, 0x29, 0x00, 0xaa, 0x00, 0xbd, 0xb1, 0x00, 0x1d, 0xb0, 0x38, 0xa8, 0x40, 0xa8, 0x48, 0xa8, 0x9d, 0xb0, 0x9a, 0xaa, 0x00, 0x60, 0xbe, 0x58, 0x5e, 0x00, 0xbe, 0x58, 0x5f, 0x00, 0xbe, 0x58, 0x60, 0x00, 0xbe, 0x58, 0x61, 0x00, 0x3e, 0xb0, 0x70, 0xaa, 0x78, 0xaa, 0xbe, 0xb0, 0x30, 0xb0, 0xbe, 0x58, 0x2a, 0x1d, 0x31, 0xb0, 0xbe, 0x58, 0x2b, 0x1d, 0x33, 0xb0, 0xbe, 0x58, 0x2c, 0x1d, 0x34, 0xb0, 0xbe, 0x58, 0x2d, 0x1d, 0x00, 0x60, 0x00, 0xbd, 0x31, 0x00, 0x00, 0x60, 0x00, 0xbd, 0x05, 0x00, 0x00, 0xbc, 0x34, 0x00, 0x00, 0x60, 0x00, 0xbd, 0x34, 0x00, 0x00, 0xbc, 0x30, 0x00, 0x00, 0xaa, 0x08, 0xaa, 0x10, 0xaa, 0x18, 0xaa, 0x20, 0xaa, 0x28, 0xaa, 0x30, 0xaa, 0x38, 0xaa, 0x40, 0xaa, 0x48, 0xaa, 0x50, 0xaa, 0x58, 0xaa, 0x60, 0xaa, 0x68, 0xaa, 0x70, 0xaa, 0x78, 0xaa, 0x00, 0xbd, 0xdb, 0xd8, +0x00, 0x2a, 0x30, 0x00, 0x00, 0xbc, 0x04, 0x00, 0x00, 0xaa, 0x08, 0xaa, 0x10, 0xaa, 0x18, 0xaa, 0x20, 0xaa, 0x28, 0xaa, 0x30, 0xaa, 0x38, 0xaa, 0x40, 0xaa, 0x48, 0xaa, 0x50, 0xaa, 0x58, 0xaa, 0x60, 0xaa, 0x68, 0xaa, 0x70, 0xaa, 0x78, 0xaa, 0x00, 0xbd, 0x04, 0x00, 0x00, 0xbc, 0x33, 0x00, 0x00, 0xaa, 0x08, 0xaa, 0x10, 0xaa, 0x18, 0xaa, 0x20, 0xaa, 0x28, 0xaa, 0x30, 0xaa, 0x38, 0xaa, 0x40, 0xaa, 0x48, 0xaa, 0x50, 0xaa, 0x58, 0xaa, 0x60, 0xaa, 0x68, 0xaa, 0x70, 0xaa, 0x78, 0xaa, 0x00, 0xbd, 0x33, 0x00, 0x9e, 0x58, 0xc3, 0x1d, 0x06, 0x38, 0xaa, 0x55, 0x02, 0x8a, 0x42, 0xa9, 0x8b, 0x9e, 0x9d, 0x60, 0x4e, 0x68, 0xef, 0xb0, 0xff, 0xab, 0x62, 0x60, 0xb1, 0x68, 0xef, 0xb0, 0x12, 0xa9, 0x1a, 0x38, 0x1a, 0x38, 0x00, 0xbc, 0x04, 0x00, 0x38, 0xa8, 0x00, 0xbd, 0x04, 0x00, 0x9e, 0x58, 0xfd, 0x6c, +0x40, 0x2a, 0x2a, 0x1d, 0xb0, 0xb0, 0x9e, 0x58, 0x2b, 0x1d, 0xb1, 0xb0, 0x9e, 0x58, 0x2c, 0x1d, 0xb3, 0xb0, 0x9e, 0x58, 0x2d, 0x1d, 0xb4, 0xb0, 0x9a, 0xac, 0xfe, 0x91, 0x9e, 0x58, 0x5e, 0x00, 0x02, 0x38, 0x54, 0x00, 0x03, 0x8a, 0xb2, 0xac, 0xfe, 0x93, 0x81, 0x9f, 0xe0, 0xac, 0x7f, 0x91, 0x9a, 0xaa, 0x00, 0x60, 0xbe, 0x58, 0xae, 0x00, 0x00, 0xbc, 0xb1, 0x00, 0x30, 0xa8, 0x00, 0xbd, 0xb1, 0x00, 0x9e, 0x58, 0x00, 0xf8, 0x00, 0xaa, 0xbe, 0x58, 0x00, 0xf8, 0x00, 0xbc, 0xbc, 0x00, 0x78, 0xaa, 0x70, 0xaa, 0x00, 0xbd, 0xbc, 0x00, 0x00, 0xbc, 0xb1, 0x00, 0x38, 0xaa, 0x70, 0xaa, 0x00, 0xbd, 0xb1, 0x00, 0x00, 0xbc, 0x1c, 0x00, 0x78, 0xa8, 0x00, 0xbd, 0x1c, 0x00, 0x3e, 0xb0, 0x70, 0xa8, 0x78, 0xa8, 0xbe, 0xb0, 0x19, 0x38, 0x8c, 0x50, 0x00, 0x60, 0xbe, 0x58, 0xe7, 0x00, 0x00, 0x60, 0x49, 0xca, +0x80, 0x2a, 0x05, 0x68, 0xbe, 0x58, 0xe9, 0x00, 0x18, 0x60, 0x08, 0x68, 0xbe, 0x58, 0xe8, 0x00, 0xea, 0x60, 0x2f, 0x68, 0x07, 0x38, 0x8d, 0x2a, 0x1a, 0x38, 0x1a, 0x38, 0x1a, 0x38, 0x1a, 0x38, 0xe5, 0xaa, 0x00, 0x61, 0xff, 0x65, 0xff, 0x6d, 0x0c, 0x62, 0x47, 0x63, 0xf8, 0x6b, 0x53, 0x64, 0xf8, 0x6c, 0x19, 0x12, 0x47, 0x38, 0x9d, 0x2a, 0x3d, 0x5b, 0xbd, 0x5c, 0x1a, 0x38, 0xc5, 0xfc, 0x1e, 0x59, 0x96, 0x61, 0xbe, 0x59, 0xfc, 0x1c, 0x3e, 0x59, 0x02, 0xc8, 0x9e, 0x58, 0xc4, 0x1d, 0x06, 0x38, 0x55, 0xaa, 0x02, 0x8a, 0x42, 0xa9, 0x0f, 0x9e, 0x9d, 0x60, 0x4e, 0x68, 0xef, 0xb0, 0xff, 0xa9, 0x9e, 0x58, 0xd6, 0x1a, 0xbe, 0x58, 0x47, 0x1e, 0xbe, 0x58, 0x04, 0xf8, 0x9e, 0x58, 0xda, 0x1a, 0xbe, 0x58, 0xb3, 0xf8, 0x8c, 0xed, 0x3a, 0x38, 0x00, 0x60, 0xbe, 0x58, 0xb1, 0x00, 0xb5, 0xef, 0xfb, 0xcd, +0xc0, 0x2a, 0x9e, 0x59, 0xbc, 0x00, 0x9e, 0x58, 0xb1, 0x00, 0x19, 0x00, 0xbe, 0x58, 0xb1, 0x00, 0x19, 0x48, 0xf6, 0x81, 0xd5, 0xf0, 0x9e, 0x58, 0xe7, 0x00, 0x1a, 0x10, 0x08, 0x88, 0x9e, 0x58, 0xe8, 0x00, 0x9e, 0x59, 0xe9, 0x00, 0x19, 0x48, 0x01, 0x88, 0x42, 0xa9, 0x1d, 0x39, 0x3a, 0x38, 0x00, 0x60, 0xbe, 0x58, 0xb1, 0x00, 0xbe, 0x58, 0xb0, 0x00, 0x9e, 0x58, 0x36, 0x1d, 0x1d, 0x10, 0x04, 0x8a, 0x9e, 0x58, 0x36, 0x1d, 0x1b, 0x10, 0x20, 0x88, 0xe5, 0xac, 0x1e, 0x90, 0x9e, 0x58, 0xe8, 0x00, 0x02, 0x38, 0x00, 0x05, 0x09, 0x8a, 0x00, 0x60, 0x05, 0x68, 0xbe, 0x58, 0xe8, 0x00, 0x18, 0x60, 0x08, 0x68, 0xbe, 0x58, 0xe9, 0x00, 0x08, 0x9e, 0x18, 0x60, 0x08, 0x68, 0xbe, 0x58, 0xe8, 0x00, 0x00, 0x60, 0x05, 0x68, 0xbe, 0x58, 0xe9, 0x00, 0x9e, 0x58, 0xe7, 0x00, 0x02, 0x39, 0x01, 0x00, 0x25, 0xc9, +0x00, 0x2b, 0x03, 0x98, 0x19, 0x00, 0xbe, 0x58, 0xe7, 0x00, 0x9e, 0x5d, 0xd5, 0x00, 0x9e, 0x5b, 0xd4, 0x00, 0x9e, 0x5c, 0xd3, 0x00, 0x04, 0xac, 0x07, 0x90, 0x1e, 0x5b, 0x1e, 0x5c, 0x1e, 0x5d, 0xb5, 0xef, 0x3e, 0x5d, 0x3e, 0x5c, 0x3e, 0x5b, 0x9e, 0x59, 0xbc, 0x00, 0x9e, 0x58, 0xb1, 0x00, 0x19, 0x00, 0x01, 0x31, 0x06, 0x8a, 0xbe, 0x58, 0xb1, 0x00, 0xa8, 0x5d, 0x6c, 0x5b, 0x8c, 0x5c, 0xea, 0x9f, 0xd5, 0xf0, 0x9e, 0x58, 0xe7, 0x00, 0x1a, 0x10, 0x08, 0x88, 0x9e, 0x58, 0xe8, 0x00, 0x9e, 0x59, 0xe9, 0x00, 0x19, 0x48, 0x01, 0x88, 0x42, 0xa9, 0x1d, 0x39, 0x3a, 0x38, 0x3a, 0x38, 0x9e, 0x58, 0xe2, 0x19, 0x00, 0x61, 0x01, 0x30, 0x01, 0x88, 0x05, 0x9e, 0x00, 0x60, 0xbe, 0x58, 0xae, 0x00, 0xd0, 0xaa, 0x3f, 0x9e, 0x9e, 0x58, 0xae, 0x00, 0x9e, 0x59, 0xc0, 0x00, 0x19, 0x48, 0x01, 0x82, 0xe9, 0x6a, +0x40, 0x2b, 0x38, 0x9e, 0x52, 0xb1, 0x39, 0xac, 0xfd, 0x93, 0xd0, 0xa8, 0x74, 0xb0, 0x78, 0xaa, 0xf4, 0xb0, 0x00, 0xbc, 0xb1, 0x00, 0x00, 0xa8, 0x00, 0xbd, 0xb1, 0x00, 0x9e, 0x58, 0x00, 0xf8, 0x00, 0xa8, 0xbe, 0x58, 0x00, 0xf8, 0x00, 0x60, 0xbe, 0x58, 0x0f, 0xf8, 0xbe, 0x58, 0x10, 0xf8, 0x4f, 0xb0, 0x50, 0xa8, 0xcf, 0xb0, 0x9e, 0x58, 0xaf, 0x00, 0x9e, 0x59, 0xc5, 0x00, 0x19, 0x48, 0x03, 0x82, 0x74, 0x60, 0x82, 0xb0, 0xf7, 0x9f, 0x00, 0x60, 0xbe, 0x58, 0xaf, 0x00, 0x4f, 0xb0, 0x50, 0xaa, 0xcf, 0xb0, 0x00, 0xbc, 0xb1, 0x00, 0x00, 0xaa, 0x00, 0xbd, 0xb1, 0x00, 0x9e, 0x58, 0x00, 0xf8, 0x00, 0xaa, 0xbe, 0x58, 0x00, 0xf8, 0x20, 0x60, 0x07, 0x38, 0x78, 0x2b, 0x1a, 0x38, 0x1a, 0x38, 0x1a, 0x38, 0x3a, 0x38, 0x19, 0x38, 0x02, 0x48, 0xb9, 0xaa, 0x00, 0x9e, 0x3a, 0x38, 0x3a, 0x38, 0x38, 0x27, +0x80, 0x2b, 0x52, 0xb2, 0x3a, 0xac, 0xfd, 0x93, 0x78, 0xab, 0x5a, 0x62, 0xe1, 0x6a, 0xac, 0xb2, 0x00, 0x62, 0xff, 0x3f, 0x7a, 0x38, 0xac, 0xb2, 0x78, 0xa9, 0x3a, 0x38, 0x00, 0x62, 0xac, 0xb2, 0xff, 0x3f, 0x0f, 0x59, 0x3a, 0x38, 0x01, 0x62, 0xef, 0x3f, 0x99, 0x2b, 0x05, 0x5d, 0x25, 0x5c, 0xbc, 0x48, 0x02, 0x88, 0x1a, 0x38, 0x3a, 0x38, 0x00, 0x62, 0x3a, 0x38, 0x9e, 0x58, 0xbf, 0x00, 0x19, 0x10, 0x0f, 0x61, 0x27, 0x69, 0x9e, 0x5b, 0xe8, 0x00, 0x9e, 0x58, 0xd5, 0x00, 0x9e, 0x5a, 0xd4, 0x00, 0x9e, 0x5c, 0xd3, 0x00, 0xbe, 0x58, 0xed, 0x19, 0xbe, 0x5a, 0xee, 0x19, 0xbe, 0x5c, 0xef, 0x19, 0x00, 0x65, 0x9e, 0x5e, 0xe9, 0x19, 0xa0, 0xac, 0x26, 0x90, 0x9e, 0x5b, 0xe8, 0x00, 0x30, 0x67, 0x0b, 0x6f, 0xa6, 0x40, 0x60, 0x03, 0xe0, 0x07, 0x00, 0xa9, 0x9e, 0x58, 0xed, 0x19, 0x9e, 0x5a, 0xdb, 0x0f, +0xc0, 0x2b, 0xee, 0x19, 0x9e, 0x5c, 0xef, 0x19, 0x0c, 0x58, 0x4c, 0x5a, 0x8c, 0x5c, 0xbe, 0x58, 0xed, 0x19, 0xbe, 0x5a, 0xee, 0x19, 0xbe, 0x5c, 0xef, 0x19, 0x00, 0xad, 0x07, 0x92, 0xc2, 0x38, 0x01, 0x00, 0x07, 0x38, 0xd4, 0x2b, 0xe5, 0x59, 0x3d, 0x5b, 0x1a, 0x38, 0x19, 0x05, 0x9e, 0x58, 0xe8, 0x19, 0xb8, 0x48, 0xdb, 0x81, 0x29, 0x9e, 0x9e, 0x5b, 0xe8, 0x00, 0x30, 0x67, 0x0b, 0x6f, 0x65, 0x03, 0xe5, 0x07, 0x00, 0xa9, 0x9e, 0x58, 0xed, 0x19, 0x9e, 0x5a, 0xee, 0x19, 0x9e, 0x5c, 0xef, 0x19, 0x0c, 0x58, 0x4c, 0x5a, 0x8c, 0x5c, 0xbe, 0x58, 0xed, 0x19, 0xbe, 0x5a, 0xee, 0x19, 0xbe, 0x5c, 0xef, 0x19, 0x00, 0xad, 0x0b, 0x92, 0xc2, 0x38, 0x01, 0x00, 0x07, 0x38, 0xfd, 0x2b, 0xe3, 0x59, 0x3b, 0x5b, 0x70, 0x3b, 0xe8, 0x19, 0xf0, 0x3f, 0xe8, 0x19, 0x1a, 0x38, 0x19, 0x05, 0x9e, 0x58, 0xe7, 0x59, +0x00, 0x2c, 0xe8, 0x19, 0xb8, 0x48, 0xd8, 0x81, 0x00, 0x9e, 0x3a, 0x38, 0x52, 0xb1, 0x39, 0xac, 0xfd, 0x93, 0xfd, 0xab, 0xf5, 0xab, 0x1a, 0x38, 0x1a, 0x38, 0x02, 0xa9, 0x00, 0xbd, 0xb0, 0x00, 0x1a, 0x38, 0x1a, 0x38, 0x02, 0xab, 0x1a, 0x38, 0x7a, 0xad, 0xfe, 0x93, 0xfd, 0xa9, 0xf5, 0xa9, 0x3a, 0x38, 0x00, 0xbc, 0xaa, 0x00, 0x10, 0x48, 0x00, 0x00, 0x01, 0x8a, 0x42, 0xa9, 0x40, 0x60, 0x21, 0x71, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x0c, 0x60, 0x27, 0x71, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x0a, 0x60, 0x9e, 0x59, 0xe4, 0x19, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x14, 0x60, 0x9e, 0x59, 0xf0, 0x04, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x16, 0x60, 0x9e, 0x59, 0xba, 0x00, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x18, 0x60, 0x03, 0x68, 0x9e, 0x59, 0xbf, 0x00, 0x19, 0x48, 0x01, 0x8a, 0x91, 0xac, +0x40, 0x2c, 0x42, 0xa9, 0x16, 0x60, 0x9e, 0x59, 0xbb, 0x00, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x24, 0x60, 0x9e, 0x59, 0xbc, 0x00, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x9e, 0x58, 0xe7, 0x00, 0x10, 0x48, 0x02, 0x00, 0x01, 0x9a, 0x42, 0xa9, 0x9e, 0x58, 0x1b, 0x1f, 0x10, 0x48, 0xaa, 0x55, 0x01, 0x8a, 0x42, 0xa9, 0x9e, 0x58, 0x1c, 0x1f, 0x10, 0x48, 0x55, 0xaa, 0x01, 0x8a, 0x42, 0xa9, 0x9e, 0x58, 0x1b, 0x1f, 0x9e, 0x59, 0x1c, 0x1f, 0x19, 0x48, 0x01, 0x88, 0x42, 0xa9, 0x1a, 0x60, 0xf8, 0x68, 0x03, 0x58, 0x00, 0x61, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x1b, 0x60, 0xf8, 0x68, 0x03, 0x58, 0x00, 0x61, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x1c, 0x60, 0xf8, 0x68, 0x03, 0x58, 0x00, 0x61, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0xff, 0xad, 0x01, 0x92, 0x42, 0xa9, 0x9e, 0x58, 0xe8, 0x00, 0x06, 0xb1, +0x80, 0x2c, 0x9e, 0x59, 0xe9, 0x00, 0x19, 0x48, 0x01, 0x88, 0x42, 0xa9, 0x9e, 0x58, 0x1f, 0x00, 0x10, 0x48, 0x01, 0x00, 0x01, 0x8a, 0x42, 0xa9, 0xed, 0xac, 0x5f, 0x92, 0x2c, 0x60, 0x1b, 0x68, 0x1f, 0x61, 0x1f, 0x69, 0x14, 0x62, 0x19, 0x12, 0x47, 0x38, 0x9a, 0x2c, 0x05, 0x5b, 0x70, 0x48, 0x1f, 0x1f, 0x01, 0x8a, 0x42, 0xa9, 0x1a, 0x38, 0x02, 0x60, 0xf8, 0x68, 0x03, 0x58, 0x9e, 0x59, 0xd5, 0x1a, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x0a, 0x60, 0xf8, 0x68, 0x03, 0x58, 0x9e, 0x59, 0xd8, 0x1a, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x05, 0x60, 0xf8, 0x68, 0x03, 0x58, 0x9e, 0x59, 0xd7, 0x1a, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x0e, 0x60, 0xf8, 0x68, 0x03, 0x58, 0x9e, 0x59, 0x58, 0x01, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x0c, 0x60, 0xf8, 0x68, 0x03, 0x58, 0x9e, 0x59, 0x57, 0x01, 0x0f, 0x53, +0xc0, 0x2c, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x09, 0x60, 0xf8, 0x68, 0x03, 0x58, 0x9e, 0x59, 0xba, 0x01, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0xaf, 0x60, 0xf8, 0x68, 0x03, 0x58, 0x9e, 0x59, 0xc7, 0x01, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0xb0, 0x60, 0xf8, 0x68, 0x03, 0x58, 0x9e, 0x59, 0xc8, 0x01, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0xb7, 0x60, 0xf8, 0x68, 0x03, 0x58, 0x9e, 0x59, 0xcf, 0x01, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0xb8, 0x60, 0xf8, 0x68, 0x03, 0x58, 0x9e, 0x59, 0xd1, 0x01, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x1a, 0x38, 0x1a, 0x38, 0x1a, 0x38, 0x3a, 0x38, 0xf3, 0xec, 0x03, 0xed, 0x2d, 0xed, 0x3a, 0x38, 0x00, 0x60, 0xbe, 0x58, 0x1f, 0x1e, 0xbe, 0x58, 0x20, 0x1e, 0xbe, 0x58, 0x21, 0x1e, 0x22, 0x61, 0x1e, 0x69, 0x23, 0x62, 0x47, 0x38, 0x01, 0x2d, 0x1d, 0x59, 0xec, 0x10, +0x00, 0x2d, 0x1a, 0x38, 0x1a, 0x38, 0x3a, 0x38, 0x30, 0x60, 0x0b, 0x68, 0x9e, 0x59, 0xe8, 0x00, 0x9e, 0x5a, 0xe9, 0x00, 0x9e, 0x5f, 0xfe, 0x1b, 0x9e, 0x5e, 0xfd, 0x1b, 0x19, 0x16, 0x00, 0x63, 0x00, 0x64, 0x00, 0x65, 0xc7, 0x38, 0x1d, 0x2d, 0x68, 0x5b, 0x8c, 0x5c, 0xac, 0x5d, 0x25, 0x5e, 0x16, 0x16, 0xdd, 0x5a, 0xd2, 0x3e, 0x19, 0x1e, 0x01, 0x96, 0x7b, 0xa8, 0x19, 0x00, 0x75, 0x3b, 0x1f, 0x1e, 0x95, 0x3c, 0x20, 0x1e, 0xb5, 0x3d, 0x21, 0x1e, 0xbe, 0x5b, 0x1f, 0x1e, 0xbe, 0x5c, 0x20, 0x1e, 0xbe, 0x5d, 0x21, 0x1e, 0x19, 0x17, 0xdf, 0x99, 0x3a, 0x38, 0x9e, 0x5b, 0x1f, 0x1e, 0x9e, 0x5c, 0x20, 0x1e, 0x9e, 0x5a, 0x21, 0x1e, 0x00, 0x65, 0x9e, 0x5f, 0xfd, 0x1b, 0x19, 0x17, 0x7b, 0xac, 0x0e, 0x92, 0xf0, 0x38, 0xe9, 0x00, 0x22, 0x61, 0x1e, 0x69, 0x23, 0x66, 0xc7, 0x38, 0x45, 0x2d, 0xcc, 0x4f, +0x40, 0x2d, 0x03, 0x5e, 0x36, 0x06, 0xdd, 0x59, 0x10, 0x38, 0xfd, 0x1b, 0x1a, 0x38, 0x19, 0x05, 0x46, 0x5a, 0x8a, 0x5c, 0x6a, 0x5b, 0x19, 0x17, 0xeb, 0x95, 0xbe, 0x5d, 0x46, 0x1e, 0x3a, 0x38, 0x9e, 0x5b, 0x46, 0x1e, 0x18, 0x13, 0x0d, 0x8a, 0x24, 0x62, 0x22, 0x64, 0x1e, 0x6c, 0x47, 0x38, 0x5f, 0x2d, 0x00, 0x61, 0x83, 0x58, 0x78, 0xac, 0x02, 0x90, 0xff, 0x61, 0xff, 0x69, 0x3c, 0x5b, 0x1d, 0x5c, 0x3a, 0x38, 0x9e, 0x5b, 0xe9, 0x00, 0x22, 0x64, 0x1e, 0x6c, 0x85, 0x5d, 0x24, 0x67, 0x9e, 0x5e, 0xfd, 0x1b, 0x19, 0x16, 0xc7, 0x38, 0x6e, 0x2d, 0x75, 0x16, 0xdd, 0x5b, 0x1a, 0x38, 0x85, 0x5d, 0x19, 0x17, 0xf5, 0x99, 0x3a, 0x38, 0x9e, 0x58, 0x15, 0x1e, 0x00, 0xac, 0x21, 0x90, 0xff, 0x61, 0x07, 0x69, 0x34, 0x38, 0xe3, 0x19, 0x18, 0x10, 0x1b, 0x88, 0x9e, 0x58, 0x1a, 0x1e, 0x02, 0x61, 0x23, 0x6a, +0x80, 0x2d, 0x19, 0x48, 0x16, 0x88, 0x9e, 0x58, 0xd6, 0x1a, 0xbe, 0x58, 0x47, 0x1e, 0xbe, 0x58, 0x04, 0xf8, 0x9e, 0x58, 0xda, 0x1a, 0xbe, 0x58, 0xb3, 0xf8, 0xff, 0x60, 0xff, 0x68, 0xbe, 0x58, 0x1a, 0x1e, 0x00, 0x60, 0xbe, 0x58, 0x1b, 0x1e, 0xbe, 0x58, 0x1c, 0x1e, 0xff, 0x60, 0xbe, 0x58, 0x1d, 0x1e, 0x3a, 0x38, 0x9e, 0x58, 0x1a, 0x1e, 0x1a, 0x10, 0x04, 0x8a, 0xa2, 0xed, 0xd8, 0xed, 0x08, 0xee, 0x2f, 0xee, 0x3a, 0x38, 0x9e, 0x5e, 0xe9, 0x00, 0x00, 0x65, 0xbe, 0x5d, 0x48, 0x1e, 0x9e, 0x5f, 0xfd, 0x1b, 0xbe, 0x5f, 0x49, 0x1e, 0x19, 0x17, 0xe6, 0x00, 0x03, 0x5b, 0x10, 0x38, 0xfd, 0x1b, 0x9e, 0x59, 0xfe, 0x1b, 0x1a, 0x11, 0x27, 0x38, 0xc7, 0x2d, 0x03, 0x5a, 0x10, 0x39, 0xfd, 0x1b, 0x23, 0x5c, 0x43, 0x13, 0x09, 0x9a, 0x44, 0x14, 0x07, 0x9a, 0x72, 0x39, 0x16, 0x1e, 0x03, 0x98, 0x68, 0xe1, +0xc0, 0x2d, 0x92, 0x39, 0x16, 0x1e, 0x01, 0x9a, 0x19, 0x05, 0x41, 0x5b, 0x10, 0x38, 0xfd, 0x1b, 0x1a, 0x38, 0x9e, 0x5b, 0x48, 0x1e, 0x7d, 0x48, 0x02, 0x94, 0xbe, 0x5d, 0x48, 0x1e, 0x9e, 0x5b, 0x49, 0x1e, 0x7d, 0x48, 0x02, 0x9a, 0xbe, 0x5d, 0x49, 0x1e, 0x00, 0x65, 0x19, 0x17, 0xd5, 0x95, 0x3a, 0x38, 0x9e, 0x5f, 0x1a, 0x1e, 0x19, 0x07, 0x18, 0x17, 0x01, 0x9a, 0x00, 0x67, 0xbe, 0x5f, 0x1a, 0x1e, 0x9e, 0x58, 0x48, 0x1e, 0x12, 0x39, 0x49, 0x1e, 0x06, 0x62, 0xd6, 0xac, 0x01, 0x90, 0x02, 0x62, 0xbe, 0x5a, 0x17, 0x1e, 0x12, 0x3a, 0x17, 0x1e, 0x08, 0x9a, 0x01, 0x67, 0xbe, 0x5f, 0x1a, 0x1e, 0x9e, 0x5f, 0x1b, 0x1e, 0x19, 0x07, 0xbe, 0x5f, 0x1b, 0x1e, 0x3a, 0x38, 0x00, 0x63, 0x9e, 0x58, 0x48, 0x1e, 0x12, 0x39, 0x49, 0x1e, 0x06, 0x62, 0xd6, 0xac, 0x01, 0x90, 0x02, 0x62, 0xbe, 0x5a, 0x6e, 0x02, +0x00, 0x2e, 0x17, 0x1e, 0x12, 0x3a, 0x17, 0x1e, 0x01, 0x9a, 0x01, 0x63, 0xbe, 0x5b, 0x1e, 0x1e, 0x3a, 0x38, 0x9e, 0x58, 0x1a, 0x1e, 0x18, 0x10, 0x1f, 0x8a, 0x9e, 0x58, 0x1b, 0x1e, 0x02, 0x39, 0x05, 0x00, 0x0a, 0x8a, 0x9e, 0x59, 0x48, 0x1e, 0x32, 0x3a, 0x1d, 0x1e, 0x18, 0x98, 0xbe, 0x59, 0x1d, 0x1e, 0xbe, 0x58, 0x1c, 0x1e, 0x13, 0x9e, 0x9e, 0x59, 0x15, 0x1e, 0x09, 0xac, 0x08, 0x92, 0x02, 0x67, 0xbe, 0x5f, 0x1a, 0x1e, 0x9e, 0x5f, 0x1c, 0x1e, 0xbe, 0x5f, 0x1b, 0x1e, 0x07, 0x9e, 0x00, 0x67, 0xbe, 0x5f, 0x1b, 0x1e, 0x03, 0x9e, 0x00, 0x63, 0xbe, 0x5b, 0x1e, 0x1e, 0x3a, 0x38, 0x9e, 0x58, 0x1a, 0x1e, 0x18, 0x10, 0x16, 0x8a, 0x9e, 0x58, 0x1b, 0x1e, 0x9e, 0x59, 0x15, 0x1e, 0x11, 0xac, 0x02, 0x90, 0x08, 0x58, 0x08, 0x58, 0xd6, 0xac, 0x03, 0x90, 0x00, 0x38, 0x8a, 0x2e, 0x02, 0x9e, 0x2a, 0x8c, +0x40, 0x2e, 0x00, 0x38, 0x8f, 0x2e, 0x09, 0x58, 0x9e, 0x59, 0xd6, 0x1a, 0x01, 0x00, 0x78, 0xa8, 0xbe, 0x58, 0x47, 0x1e, 0x3a, 0x38, 0x48, 0x62, 0x0e, 0x6a, 0x9e, 0x5b, 0xfd, 0x1b, 0x9e, 0x5c, 0xfd, 0x1b, 0x41, 0x5d, 0x00, 0x61, 0x00, 0x67, 0x9e, 0x5e, 0xfe, 0x1b, 0x19, 0x16, 0xc7, 0x38, 0x5d, 0x2e, 0xa3, 0x58, 0x18, 0x10, 0x02, 0x94, 0x19, 0x07, 0x20, 0x01, 0xa3, 0x05, 0x21, 0x58, 0x00, 0x61, 0x02, 0x58, 0x1c, 0x5f, 0x01, 0x59, 0x32, 0x39, 0x18, 0x1e, 0x0d, 0x9a, 0x41, 0x5d, 0x9e, 0x5e, 0xfe, 0x1b, 0x19, 0x16, 0x08, 0x58, 0xc7, 0x38, 0x72, 0x2e, 0xa3, 0x5e, 0x18, 0x06, 0x02, 0x9a, 0xc0, 0x06, 0xdb, 0x5d, 0xa3, 0x05, 0x19, 0x02, 0x19, 0x14, 0xda, 0x89, 0x3a, 0x38, 0x01, 0x60, 0xbe, 0x58, 0x15, 0x1e, 0x40, 0x60, 0xbe, 0x58, 0x16, 0x1e, 0xff, 0x60, 0x1f, 0x68, 0xbe, 0x58, 0x16, 0x16, +0x80, 0x2e, 0x18, 0x1e, 0x80, 0x60, 0xbe, 0x58, 0x19, 0x1e, 0x9e, 0x58, 0xd6, 0x1a, 0xbe, 0x58, 0x47, 0x1e, 0x8c, 0xed, 0x3a, 0x38, 0x1d, 0x00, 0x1d, 0x00, 0x1d, 0x00, 0x1d, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x00, 0x00, 0x08, 0x00, 0x18, 0x00, 0x30, 0x00, 0x38, 0x00, 0x3c, 0xab, 0x3a, 0x38, 0xfa, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x01, 0xd6, 0x1a, 0xd7, 0x1a, 0xd8, 0x1a, 0x57, 0x01, 0x5b, 0x01, 0x2d, 0x62, 0x01, 0x6a, 0x26, 0x63, 0x04, 0x6b, 0xeb, 0x64, 0x00, 0x67, 0x10, 0x6f, 0xef, 0x3a, 0xb6, 0x2e, 0x45, 0x5d, 0x65, 0x5e, 0x85, 0x58, 0xbb, 0x5e, 0x3a, 0x38, 0x9e, 0x5e, 0x20, 0x04, 0xc6, 0x5e, 0x7c, 0x62, 0x01, 0x6a, 0x94, 0x63, 0x01, 0x6b, 0x17, 0x64, 0xcd, 0x1d, +0xc0, 0x2e, 0x01, 0x6c, 0x01, 0x65, 0x01, 0x6d, 0xef, 0x3a, 0xca, 0x2e, 0x45, 0x58, 0xc0, 0x40, 0x1d, 0x5c, 0x65, 0x58, 0xc0, 0x40, 0x1d, 0x5d, 0x3a, 0x38, 0xef, 0xa8, 0x9e, 0x58, 0x17, 0x04, 0x9e, 0x59, 0x1f, 0x04, 0x01, 0x10, 0x19, 0x48, 0x03, 0x9a, 0xbe, 0x58, 0x18, 0x04, 0x02, 0x9e, 0xbe, 0x59, 0x18, 0x04, 0x9e, 0x58, 0xb5, 0x00, 0x18, 0x10, 0x03, 0x8a, 0x19, 0x10, 0x01, 0x8a, 0x09, 0x9e, 0x9e, 0x58, 0x1d, 0x04, 0x18, 0x10, 0x04, 0x8a, 0x19, 0x10, 0xbe, 0x58, 0x1d, 0x04, 0x01, 0x9e, 0xef, 0xaa, 0x3a, 0x38, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb6, 0xb8, 0x00, 0x2f, 0x25, 0x00, 0x25, 0x00, 0x04, 0x00, 0x08, 0x00, 0x30, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x05, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, 0x02, 0x00, 0x10, 0x00, 0x0a, 0x00, 0x03, 0x00, 0x12, 0x00, 0x0e, 0x00, 0x08, 0x00, 0x08, 0x00, 0x40, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x04, 0x00, 0x01, 0x00, 0x05, 0x00, 0x05, 0x00, 0x13, 0x00, 0x50, 0x00, 0x38, 0x00, 0x18, 0x00, 0x1a, 0x00, 0x24, 0x00, 0x30, 0x00, 0x20, 0x00, 0x24, 0x00, 0x30, 0x00, 0x14, 0x00, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x55, 0x2a, 0x40, 0x2f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x27, 0x80, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x10, 0xef, 0x00, 0xbc, 0xb1, 0x00, 0x30, 0xa8, 0x28, 0xa8, 0x20, 0xa8, 0x68, 0xa8, 0x60, 0xaa, 0x00, 0xbd, 0xb1, 0x00, 0x9e, 0x58, 0x01, 0xf8, 0x08, 0xaa, 0xbe, 0x58, 0x01, 0xf8, 0x3e, 0xb0, 0x60, 0xaa, 0xbe, 0xb0, 0x9e, 0x58, 0x00, 0xf8, 0x00, 0xa8, 0xbe, 0x58, 0x00, 0xf8, 0x1f, 0x60, 0x4e, 0x68, 0x07, 0x38, 0xb0, 0x2f, 0x1a, 0x38, 0x1a, 0x38, 0x1a, 0x38, 0x00, 0x60, 0xbe, 0x58, 0x01, 0x00, 0x3a, 0x38, 0x00, 0x60, 0xbe, 0x58, 0xb0, 0x00, 0xdb, 0xef, 0x9e, 0x58, 0x00, 0xf8, 0x00, 0xaa, 0xbe, 0x58, 0x00, 0xf8, 0xff, 0x60, 0xff, 0x68, 0x62, 0x0c, @@ -190,9 +190,9 @@ 0x40, 0x31, 0x7d, 0x5a, 0x1a, 0x38, 0x8e, 0x61, 0x1b, 0x69, 0x62, 0x62, 0x1e, 0x6a, 0x9e, 0x58, 0x5d, 0x1a, 0x19, 0x10, 0x07, 0x38, 0x4d, 0x31, 0x25, 0x5b, 0x7d, 0x5a, 0x1a, 0x38, 0x09, 0x61, 0x1a, 0x69, 0x9c, 0x62, 0x1e, 0x6a, 0x9e, 0x58, 0x5d, 0x1a, 0x19, 0x10, 0x07, 0x38, 0x59, 0x31, 0x25, 0x5b, 0x7d, 0x5a, 0x1a, 0x38, 0x9e, 0x5a, 0xec, 0x19, 0x9e, 0x59, 0xeb, 0x19, 0x9e, 0x58, 0xea, 0x19, 0xbe, 0x5a, 0x5b, 0x1a, 0xbe, 0x59, 0xaf, 0x1a, 0xbe, 0x58, 0x5a, 0x1a, 0x9e, 0x58, 0xea, 0x1e, 0xbe, 0x58, 0x4c, 0x04, 0x9e, 0x58, 0xeb, 0x1e, 0xbe, 0x58, 0x4d, 0x04, 0x9e, 0x58, 0xec, 0x1e, 0xbe, 0x58, 0x4e, 0x04, 0x9e, 0x58, 0xed, 0x1e, 0xbe, 0x58, 0x4f, 0x04, 0x00, 0x60, 0xbe, 0x58, 0x43, 0x1a, 0x2c, 0xf2, 0x1a, 0x38, 0x9e, 0x58, 0x00, 0xf8, 0x00, 0xaa, 0xbe, 0x58, 0x00, 0xf8, 0x61, 0xf8, 0x80, 0x31, 0xff, 0x60, 0xff, 0x68, 0xbe, 0x58, 0x0f, 0xf8, 0xbe, 0x58, 0x10, 0xf8, 0x9e, 0x58, 0x00, 0xf8, 0x10, 0xa8, 0xbe, 0x58, 0x00, 0xf8, 0x9f, 0xf0, 0x1a, 0x38, 0x9e, 0x58, 0x00, 0xf8, 0x00, 0xa8, 0xbe, 0x58, 0x00, 0xf8, 0x00, 0x60, 0xbe, 0x58, 0x0f, 0xf8, 0xbe, 0x58, 0x10, 0xf8, 0x3d, 0xf3, 0x1a, 0x38, 0xf9, 0x60, 0x01, 0x68, 0x03, 0x59, 0x05, 0x62, 0x0f, 0x63, 0x1a, 0x38, 0x3a, 0x48, 0x98, 0x3a, 0x31, 0x33, 0x1a, 0x38, 0x3b, 0x48, 0x18, 0x3a, 0x2a, 0x33, 0x1a, 0x38, 0xf9, 0x60, 0x01, 0x68, 0xfa, 0x61, 0x01, 0x69, 0x00, 0x62, 0x5b, 0x58, 0x5b, 0x59, 0x1a, 0x38, 0xe1, 0xf1, 0x65, 0xf3, 0x9e, 0x58, 0xe7, 0x00, 0x1a, 0x10, 0x08, 0x88, 0x9e, 0x58, 0xe8, 0x00, 0x9e, 0x59, 0xe9, 0x00, 0x19, 0x48, 0x01, 0x88, 0x42, 0xa9, 0x1d, 0x39, 0x1a, 0x38, 0x1a, 0x38, 0x3a, 0x38, 0x11, 0x46, 0xc0, 0x31, 0x1e, 0x58, 0x1e, 0x59, 0x1e, 0x5a, 0xb5, 0x61, 0x02, 0x69, 0x29, 0x62, 0x03, 0x6a, 0x2f, 0x3f, 0xcc, 0x31, 0x23, 0x58, 0x1b, 0x5a, 0x19, 0x01, 0x19, 0x02, 0x02, 0x61, 0x02, 0x69, 0x3d, 0x62, 0x02, 0x6a, 0x0f, 0x3f, 0xd6, 0x31, 0x23, 0x58, 0x1b, 0x5a, 0x19, 0x01, 0x19, 0x02, 0x3e, 0x5a, 0x3e, 0x59, 0x3e, 0x58, 0x3a, 0x38, 0x34, 0xf8, 0x82, 0xf3, 0xbe, 0xf3, 0x02, 0xf4, 0x9d, 0xf4, 0x3a, 0x38, 0x02, 0x62, 0x02, 0x6a, 0xb5, 0x64, 0x02, 0x6c, 0xf1, 0x61, 0x31, 0x69, 0x2f, 0x3f, 0xee, 0x31, 0x29, 0x5b, 0x43, 0x03, 0x63, 0x5d, 0xbb, 0x5c, 0x19, 0x01, 0x19, 0x04, 0x1a, 0x38, 0x3a, 0x38, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x14, 0x00, 0x01, 0x00, 0x05, 0x00, 0x09, 0x00, 0x0d, 0x00, 0x11, 0x00, 0x15, 0x00, 0x02, 0x00, 0x06, 0x00, 0x0a, 0x00, 0xdb, 0x62, -0x00, 0x32, 0x0e, 0x00, 0x12, 0x00, 0x16, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x18, 0x00, 0x1c, 0x00, 0x20, 0x00, 0x24, 0x00, 0x28, 0x00, 0x2c, 0x00, 0x30, 0x00, 0x34, 0x00, 0x38, 0x00, 0x3c, 0x00, 0x19, 0x00, 0x1d, 0x00, 0x21, 0x00, 0x25, 0x00, 0x29, 0x00, 0x2d, 0x00, 0x31, 0x00, 0x35, 0x00, 0x39, 0x00, 0x3d, 0x00, 0x1a, 0x00, 0x1e, 0x00, 0x22, 0x00, 0x26, 0x00, 0x2a, 0x00, 0x2e, 0x00, 0x32, 0x00, 0x36, 0x00, 0x3a, 0x00, 0x3e, 0x00, 0x1b, 0x00, 0x1f, 0x00, 0x23, 0x00, 0x27, 0x00, 0x2b, 0x00, 0x2f, 0x00, 0x3a, 0x38, 0xfa, 0x60, 0x01, 0x68, 0x03, 0x58, 0x00, 0xac, 0x02, 0x90, 0x77, 0x9e, 0x3a, 0x38, 0x9e, 0x58, 0x1b, 0x1e, 0xd6, 0xac, 0x03, 0x92, 0x00, 0x38, 0x86, 0x2e, 0x02, 0x9e, 0x00, 0x38, 0x81, 0x2e, 0x09, 0x58, 0x9e, 0x59, 0xda, 0x1a, 0x20, 0x01, 0x69, 0x92, +0x00, 0x32, 0x0e, 0x00, 0x12, 0x00, 0x16, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x18, 0x00, 0x1c, 0x00, 0x20, 0x00, 0x24, 0x00, 0x28, 0x00, 0x2c, 0x00, 0x30, 0x00, 0x34, 0x00, 0x38, 0x00, 0x3c, 0x00, 0x19, 0x00, 0x1d, 0x00, 0x21, 0x00, 0x25, 0x00, 0x29, 0x00, 0x2d, 0x00, 0x31, 0x00, 0x35, 0x00, 0x39, 0x00, 0x3d, 0x00, 0x1a, 0x00, 0x1e, 0x00, 0x22, 0x00, 0x26, 0x00, 0x2a, 0x00, 0x2e, 0x00, 0x32, 0x00, 0x36, 0x00, 0x3a, 0x00, 0x3e, 0x00, 0x1b, 0x00, 0x1f, 0x00, 0x23, 0x00, 0x27, 0x00, 0x2b, 0x00, 0x2f, 0x00, 0x3a, 0x38, 0xfa, 0x60, 0x01, 0x68, 0x03, 0x58, 0x00, 0xac, 0x02, 0x90, 0x77, 0x9e, 0x3a, 0x38, 0x9e, 0x58, 0x1b, 0x1e, 0xd6, 0xac, 0x03, 0x92, 0x00, 0x38, 0x99, 0x2e, 0x02, 0x9e, 0x00, 0x38, 0x94, 0x2e, 0x09, 0x58, 0x9e, 0x59, 0xda, 0x1a, 0x20, 0x01, 0x8f, 0x92, 0x40, 0x32, 0xb3, 0x60, 0xf8, 0x68, 0x3b, 0x58, 0x9e, 0x59, 0xdb, 0x1a, 0xb4, 0x60, 0xf8, 0x68, 0x3b, 0x58, 0x9e, 0x59, 0xdc, 0x1a, 0xb9, 0x60, 0xf8, 0x68, 0x3b, 0x58, 0x20, 0x61, 0xb1, 0x60, 0xf8, 0x68, 0x9e, 0x5a, 0xc9, 0x00, 0x18, 0x12, 0x01, 0x8a, 0x20, 0x61, 0x3b, 0x58, 0xaa, 0x60, 0xf8, 0x68, 0x03, 0x59, 0x01, 0xa8, 0x21, 0xa8, 0x29, 0xa8, 0x31, 0xa8, 0x39, 0xa8, 0x41, 0xaa, 0x49, 0xaa, 0x51, 0xaa, 0x59, 0xaa, 0x79, 0xa8, 0x3b, 0x58, 0xab, 0x60, 0xf8, 0x68, 0x03, 0x59, 0x01, 0xa8, 0x09, 0xa8, 0x11, 0xa8, 0x19, 0xa8, 0x21, 0xa8, 0x29, 0xaa, 0x31, 0xaa, 0x39, 0xaa, 0x41, 0xaa, 0x3b, 0x58, 0xe0, 0x61, 0x1a, 0x69, 0x30, 0x39, 0xf9, 0x01, 0xac, 0x60, 0xf8, 0x68, 0x23, 0x5a, 0x5b, 0x58, 0xe6, 0x61, 0x1a, 0x69, 0x30, 0x39, 0xf9, 0x01, 0xad, 0x60, 0xf8, 0x68, 0x23, 0x5a, 0x12, 0x8a, -0x80, 0x32, 0x5b, 0x58, 0x20, 0x61, 0x1b, 0x69, 0x30, 0x39, 0xf9, 0x01, 0xd4, 0x60, 0xf8, 0x68, 0x23, 0x5a, 0x5b, 0x58, 0x26, 0x61, 0x1b, 0x69, 0x30, 0x39, 0xf9, 0x01, 0xd5, 0x60, 0xf8, 0x68, 0x23, 0x5a, 0x5b, 0x58, 0x00, 0x61, 0x1b, 0x69, 0x30, 0x39, 0xf9, 0x01, 0xd0, 0x60, 0xf8, 0x68, 0x23, 0x5a, 0x5b, 0x58, 0x06, 0x61, 0x1b, 0x69, 0x30, 0x39, 0xf9, 0x01, 0xd1, 0x60, 0xf8, 0x68, 0x23, 0x5a, 0x5b, 0x58, 0xf9, 0x62, 0x01, 0x6a, 0x43, 0x5a, 0xae, 0x64, 0xf8, 0x6c, 0x5b, 0x5c, 0x1a, 0x38, 0x89, 0x9f, 0x9e, 0x58, 0x1b, 0x1e, 0xd6, 0xac, 0x03, 0x92, 0x00, 0x38, 0x86, 0x2e, 0x02, 0x9e, 0x00, 0x38, 0x81, 0x2e, 0x09, 0x58, 0x9e, 0x59, 0xdd, 0x1a, 0x20, 0x01, 0xb3, 0x60, 0xf8, 0x68, 0x3b, 0x58, 0x9e, 0x59, 0xde, 0x1a, 0xb4, 0x60, 0xf8, 0x68, 0x3b, 0x58, 0x9e, 0x59, 0xdf, 0x1a, 0x3f, 0xd9, +0x80, 0x32, 0x5b, 0x58, 0x20, 0x61, 0x1b, 0x69, 0x30, 0x39, 0xf9, 0x01, 0xd4, 0x60, 0xf8, 0x68, 0x23, 0x5a, 0x5b, 0x58, 0x26, 0x61, 0x1b, 0x69, 0x30, 0x39, 0xf9, 0x01, 0xd5, 0x60, 0xf8, 0x68, 0x23, 0x5a, 0x5b, 0x58, 0x00, 0x61, 0x1b, 0x69, 0x30, 0x39, 0xf9, 0x01, 0xd0, 0x60, 0xf8, 0x68, 0x23, 0x5a, 0x5b, 0x58, 0x06, 0x61, 0x1b, 0x69, 0x30, 0x39, 0xf9, 0x01, 0xd1, 0x60, 0xf8, 0x68, 0x23, 0x5a, 0x5b, 0x58, 0xf9, 0x62, 0x01, 0x6a, 0x43, 0x5a, 0xae, 0x64, 0xf8, 0x6c, 0x5b, 0x5c, 0x1a, 0x38, 0x89, 0x9f, 0x9e, 0x58, 0x1b, 0x1e, 0xd6, 0xac, 0x03, 0x92, 0x00, 0x38, 0x99, 0x2e, 0x02, 0x9e, 0x00, 0x38, 0x94, 0x2e, 0x09, 0x58, 0x9e, 0x59, 0xdd, 0x1a, 0x20, 0x01, 0xb3, 0x60, 0xf8, 0x68, 0x3b, 0x58, 0x9e, 0x59, 0xde, 0x1a, 0xb4, 0x60, 0xf8, 0x68, 0x3b, 0x58, 0x9e, 0x59, 0xdf, 0x1a, 0x65, 0xd9, 0xc0, 0x32, 0xb9, 0x60, 0xf8, 0x68, 0x3b, 0x58, 0x20, 0x61, 0xb1, 0x60, 0xf8, 0x68, 0x9e, 0x5a, 0xc9, 0x00, 0x18, 0x12, 0x01, 0x8a, 0x20, 0x61, 0x3b, 0x58, 0xaa, 0x60, 0xf8, 0x68, 0x03, 0x59, 0x01, 0xa8, 0x21, 0xaa, 0x29, 0xaa, 0x31, 0xaa, 0x39, 0xaa, 0x41, 0xa8, 0x49, 0xa8, 0x51, 0xa8, 0x59, 0xa8, 0x79, 0xa8, 0x3b, 0x58, 0xab, 0x60, 0xf8, 0x68, 0x03, 0x59, 0x01, 0xa8, 0x09, 0xaa, 0x11, 0xaa, 0x19, 0xaa, 0x21, 0xaa, 0x29, 0xa8, 0x31, 0xa8, 0x39, 0xa8, 0x41, 0xa8, 0x3b, 0x58, 0xec, 0x61, 0x1a, 0x69, 0x30, 0x39, 0xf9, 0x01, 0x1e, 0x11, 0xac, 0x60, 0xf8, 0x68, 0x23, 0x5a, 0x5b, 0x58, 0xf6, 0x61, 0x1a, 0x69, 0x30, 0x39, 0xf9, 0x01, 0x1e, 0x11, 0xad, 0x60, 0xf8, 0x68, 0x23, 0x5a, 0x5b, 0x58, 0x2c, 0x61, 0x1b, 0x69, 0x30, 0x39, 0xf9, 0x01, 0x1e, 0x11, 0xd6, 0x60, 0xf8, 0x68, 0xe1, 0xb8, 0x00, 0x33, 0x23, 0x5a, 0x5b, 0x58, 0x36, 0x61, 0x1b, 0x69, 0x30, 0x39, 0xf9, 0x01, 0x1e, 0x11, 0xd7, 0x60, 0xf8, 0x68, 0x23, 0x5a, 0x5b, 0x58, 0x0c, 0x61, 0x1b, 0x69, 0x30, 0x39, 0xf9, 0x01, 0x1e, 0x11, 0xd2, 0x60, 0xf8, 0x68, 0x23, 0x5a, 0x5b, 0x58, 0x16, 0x61, 0x1b, 0x69, 0x30, 0x39, 0xf9, 0x01, 0x1e, 0x11, 0xd3, 0x60, 0xf8, 0x68, 0x23, 0x5a, 0x5b, 0x58, 0xf9, 0x62, 0x01, 0x6a, 0x43, 0x5a, 0x06, 0x63, 0x43, 0x12, 0x44, 0x3a, 0xff, 0x00, 0xfe, 0x5a, 0xae, 0x64, 0xf8, 0x6c, 0x5b, 0x5c, 0x1a, 0x38, 0x08, 0x9f, 0xf9, 0x60, 0x01, 0x68, 0x03, 0x59, 0x19, 0x01, 0x3b, 0x58, 0x98, 0x3f, 0x79, 0x31, 0xf9, 0x60, 0x01, 0x68, 0x03, 0x59, 0x19, 0x01, 0x3b, 0x58, 0xfa, 0x61, 0x01, 0x69, 0x23, 0x58, 0x00, 0xa8, 0x1b, 0x59, 0x98, 0x3f, 0x79, 0x31, 0xfa, 0x60, 0x01, 0x68, 0x03, 0x59, 0xbf, 0xf4, 0x40, 0x33, 0x01, 0xac, 0x01, 0x90, 0x11, 0x9e, 0xda, 0x65, 0xf8, 0x6d, 0xf9, 0x63, 0x01, 0x6b, 0x63, 0x5b, 0x04, 0x60, 0x03, 0x40, 0x02, 0x63, 0x02, 0x6b, 0x03, 0x04, 0x6f, 0x38, 0x51, 0x33, 0xa5, 0x5e, 0xdd, 0x5c, 0x1a, 0x38, 0xdb, 0x5c, 0x10, 0x9e, 0xde, 0x65, 0xf8, 0x6d, 0xf9, 0x63, 0x01, 0x6b, 0x63, 0x5b, 0x04, 0x60, 0x03, 0x40, 0x02, 0x63, 0x02, 0x6b, 0x03, 0x04, 0x6f, 0x38, 0x62, 0x33, 0xa5, 0x5e, 0xdd, 0x5c, 0x1a, 0x38, 0x00, 0x9e, 0x3a, 0x38, 0xaa, 0x60, 0xf8, 0x68, 0x03, 0x59, 0x21, 0xaa, 0x29, 0xaa, 0x31, 0xaa, 0x39, 0xaa, 0x41, 0xaa, 0x49, 0xaa, 0x51, 0xaa, 0x59, 0xaa, 0x3b, 0x58, 0xab, 0x60, 0xf8, 0x68, 0x03, 0x59, 0x01, 0xaa, 0x09, 0xaa, 0x11, 0xaa, 0x19, 0xaa, 0x21, 0xaa, 0x29, 0xaa, 0x31, 0xaa, 0x39, 0xaa, 0x41, 0xaa, 0xae, 0x60, 0xf8, 0x68, 0x00, 0x61, 0xfc, 0x92, @@ -217,21 +217,21 @@ 0x00, 0x38, 0x00, 0x61, 0x9e, 0x5b, 0xbb, 0x00, 0xb1, 0x70, 0x03, 0x40, 0x04, 0x04, 0x40, 0x3e, 0xb6, 0x5e, 0xc9, 0x5e, 0xd0, 0x48, 0x48, 0x00, 0x03, 0x8a, 0x86, 0x04, 0xbb, 0x5c, 0x03, 0x9e, 0x0f, 0x77, 0x19, 0x07, 0x0f, 0x7f, 0xb0, 0x72, 0x19, 0x02, 0xb0, 0x7a, 0x19, 0x07, 0x9d, 0x9f, 0xb1, 0x70, 0x19, 0x00, 0xb1, 0x78, 0x8b, 0x9f, 0x00, 0x60, 0xbe, 0x58, 0x0f, 0xf8, 0x00, 0x60, 0xbe, 0x58, 0x10, 0xf8, 0x44, 0xab, 0x9e, 0x58, 0x00, 0xf8, 0x00, 0xa8, 0xbe, 0x58, 0x00, 0xf8, 0x3a, 0x38, 0x40, 0x60, 0x57, 0x68, 0xe0, 0x63, 0x1a, 0x6b, 0x40, 0x61, 0x19, 0x11, 0x27, 0x38, 0x32, 0x38, 0x0b, 0x5a, 0x5d, 0x5b, 0x1a, 0x38, 0x3a, 0x38, 0x06, 0x71, 0x51, 0xac, 0x1c, 0x92, 0x09, 0xac, 0x36, 0x92, 0x01, 0xac, 0x34, 0x92, 0x0a, 0x60, 0xbe, 0x58, 0xc1, 0x1a, 0x03, 0x60, 0xbe, 0x58, 0x40, 0x7b, 0x40, 0x38, 0xc2, 0x1a, 0x12, 0x60, 0xbe, 0x58, 0xc3, 0x1a, 0x0e, 0x60, 0xbe, 0x58, 0xc4, 0x1a, 0x9e, 0x58, 0xd6, 0x1a, 0xbe, 0x58, 0x47, 0x1e, 0xbe, 0x58, 0x04, 0xf8, 0x01, 0x60, 0x23, 0x78, 0x00, 0x60, 0xbe, 0x58, 0x1b, 0x1e, 0x36, 0x9e, 0x48, 0x60, 0xbe, 0x58, 0xc1, 0x1a, 0x48, 0x60, 0xbe, 0x58, 0xc2, 0x1a, 0x60, 0x60, 0xbe, 0x58, 0xc3, 0x1a, 0x60, 0x60, 0xbe, 0x58, 0xc4, 0x1a, 0x50, 0x60, 0x02, 0x68, 0x1c, 0x78, 0x02, 0x60, 0x23, 0x78, 0x9e, 0x59, 0x47, 0x1e, 0x9e, 0x58, 0xd6, 0x1a, 0x19, 0x48, 0x1f, 0x88, 0x9e, 0x59, 0xd6, 0x1a, 0xbe, 0x59, 0x04, 0xf8, 0x1a, 0x9e, 0x20, 0x60, 0xbe, 0x58, 0xc1, 0x1a, 0x20, 0x60, 0xbe, 0x58, 0xc2, 0x1a, 0x30, 0x60, 0xbe, 0x58, 0xc3, 0x1a, 0x30, 0x60, 0xbe, 0x58, 0xc4, 0x1a, 0x80, 0x60, 0x1c, 0x78, 0x01, 0x60, 0x23, 0x78, 0x9e, 0x59, 0x59, 0x63, 0x80, 0x38, 0x47, 0x1e, 0x9e, 0x58, 0xd6, 0x1a, 0x19, 0x48, 0x04, 0x88, 0x9e, 0x59, 0xd6, 0x1a, 0xbe, 0x59, 0x04, 0xf8, 0x3a, 0x38, 0xaa, 0x66, 0x15, 0x6e, 0xc3, 0x5d, 0xa4, 0x3d, 0xff, 0x0f, 0xbb, 0x5e, 0x9e, 0x5f, 0x4b, 0x1a, 0xe2, 0x38, 0x01, 0x00, 0x0b, 0x9a, 0xe2, 0x3e, 0x01, 0x00, 0xc7, 0x38, 0x9f, 0x38, 0xe0, 0x3e, 0xaa, 0x15, 0xc3, 0x5d, 0xa4, 0x3d, 0xff, 0x00, 0xbb, 0x5e, 0x19, 0x17, 0x1a, 0x38, 0x3a, 0x38, 0x3c, 0x60, 0xbe, 0x58, 0xce, 0x04, 0x0f, 0x60, 0xbe, 0x58, 0xd0, 0x04, 0x06, 0x60, 0xbe, 0x58, 0xd1, 0x04, 0x04, 0x60, 0xbe, 0x58, 0xd2, 0x04, 0x07, 0x60, 0xbe, 0x58, 0xd3, 0x04, 0x01, 0x60, 0xbe, 0x58, 0xd4, 0x04, 0x14, 0x60, 0xbe, 0x58, 0xd5, 0x04, 0x05, 0x60, 0xbe, 0x58, 0xd6, 0x04, 0x3c, 0x60, 0xbe, 0x58, 0xcd, 0x04, 0x00, 0x60, 0xbe, 0x58, 0xc7, 0x04, 0x25, 0xb4, -0xc0, 0x38, 0x3a, 0x38, 0x8a, 0xf8, 0xce, 0x60, 0x04, 0x68, 0xd0, 0x61, 0x04, 0x69, 0xd1, 0x62, 0x04, 0x6a, 0xd2, 0x63, 0x04, 0x6b, 0xd3, 0x64, 0x04, 0x6c, 0xd4, 0x65, 0x04, 0x6d, 0xd5, 0x66, 0x04, 0x6e, 0xd6, 0x67, 0x04, 0x6f, 0x9e, 0x58, 0xe2, 0x19, 0x1a, 0x10, 0x04, 0x8a, 0x9e, 0x58, 0xea, 0x04, 0x1a, 0x10, 0x61, 0x88, 0x9e, 0x58, 0x58, 0x1a, 0x18, 0x10, 0x5d, 0x9a, 0x1a, 0x10, 0x5b, 0x98, 0x9e, 0x58, 0x58, 0x1a, 0x1a, 0x10, 0x19, 0x8a, 0x9e, 0x58, 0xcd, 0x04, 0x9e, 0x59, 0xce, 0x04, 0x30, 0x39, 0xd5, 0x04, 0x01, 0x10, 0x05, 0x98, 0x9e, 0x58, 0xc7, 0x04, 0x12, 0x38, 0xd4, 0x04, 0x3e, 0x96, 0xc7, 0x60, 0x04, 0x68, 0x9e, 0x59, 0xd4, 0x04, 0x3b, 0x58, 0xae, 0xfc, 0x46, 0xf9, 0x00, 0xfc, 0x8a, 0xf8, 0x3e, 0x58, 0x98, 0x3f, 0x3c, 0x0c, 0x9e, 0x58, 0x72, 0x19, 0x73, 0x61, 0xd7, 0x71, +0xc0, 0x38, 0x3a, 0x38, 0x8a, 0xf8, 0xce, 0x60, 0x04, 0x68, 0xd0, 0x61, 0x04, 0x69, 0xd1, 0x62, 0x04, 0x6a, 0xd2, 0x63, 0x04, 0x6b, 0xd3, 0x64, 0x04, 0x6c, 0xd4, 0x65, 0x04, 0x6d, 0xd5, 0x66, 0x04, 0x6e, 0xd6, 0x67, 0x04, 0x6f, 0x9e, 0x58, 0xe2, 0x19, 0x1a, 0x10, 0x04, 0x8a, 0x9e, 0x58, 0xea, 0x04, 0x1a, 0x10, 0x61, 0x88, 0x9e, 0x58, 0x58, 0x1a, 0x18, 0x10, 0x5d, 0x9a, 0x1a, 0x10, 0x5b, 0x98, 0x9e, 0x58, 0x58, 0x1a, 0x1a, 0x10, 0x19, 0x8a, 0x9e, 0x58, 0xcd, 0x04, 0x9e, 0x59, 0xce, 0x04, 0x30, 0x39, 0xd5, 0x04, 0x01, 0x10, 0x05, 0x98, 0x9e, 0x58, 0xc7, 0x04, 0x12, 0x38, 0xd4, 0x04, 0x3e, 0x96, 0xc7, 0x60, 0x04, 0x68, 0x9e, 0x59, 0xd4, 0x04, 0x3b, 0x58, 0xae, 0xfc, 0x46, 0xf9, 0x00, 0xfc, 0x8a, 0xf8, 0x3e, 0x58, 0x98, 0x3f, 0x41, 0x0c, 0x9e, 0x58, 0x72, 0x19, 0x73, 0x61, 0xdc, 0x71, 0x00, 0x39, 0x19, 0x69, 0x23, 0x59, 0x20, 0x10, 0x04, 0x58, 0x9e, 0x59, 0x86, 0x19, 0x87, 0x62, 0x19, 0x6a, 0x43, 0x5a, 0x41, 0x11, 0x04, 0x59, 0x01, 0x00, 0xbe, 0x58, 0xee, 0x04, 0x9e, 0x59, 0xd3, 0x04, 0x01, 0x11, 0x22, 0x98, 0xc7, 0x60, 0x04, 0x68, 0x03, 0x59, 0x19, 0x01, 0x32, 0x3a, 0xd4, 0x04, 0x02, 0x94, 0x3b, 0x58, 0x2a, 0x9e, 0x9e, 0x59, 0xd4, 0x04, 0x3b, 0x58, 0xcd, 0x60, 0x04, 0x68, 0x5a, 0x61, 0x03, 0x5a, 0x19, 0x02, 0x41, 0x13, 0x02, 0x94, 0x3b, 0x58, 0x1e, 0x9e, 0x9e, 0x59, 0xce, 0x04, 0x26, 0x59, 0x41, 0x13, 0x01, 0x9a, 0x21, 0x5a, 0x5b, 0x58, 0x16, 0x9e, 0x0b, 0x9e, 0x3c, 0x60, 0xbe, 0x58, 0xcd, 0x04, 0x11, 0x9e, 0xc7, 0x60, 0x04, 0x68, 0x03, 0x59, 0x19, 0x11, 0x22, 0x3a, 0x00, 0x00, 0x09, 0x98, 0xc7, 0x60, 0x04, 0x68, 0xde, 0x58, 0x00, 0x00, 0x9e, 0x58, 0x73, 0xc2, 0x40, 0x39, 0xce, 0x04, 0xbe, 0x58, 0xcd, 0x04, 0x01, 0x9e, 0x3b, 0x58, 0x3a, 0x38, 0xc8, 0x67, 0x04, 0x6f, 0x00, 0x65, 0xbd, 0x5f, 0xbb, 0x5f, 0xbe, 0x5d, 0xcb, 0x04, 0xbe, 0x5d, 0xcc, 0x04, 0x9e, 0x5f, 0x4b, 0x1a, 0x18, 0x17, 0xa5, 0x8a, 0xe2, 0x38, 0x14, 0x00, 0x1a, 0x00, 0xa5, 0x94, 0x00, 0x67, 0xe0, 0x38, 0xaa, 0x15, 0x03, 0x58, 0x12, 0x38, 0x23, 0x00, 0x93, 0x96, 0xe0, 0x3e, 0xde, 0x15, 0xc3, 0x5e, 0xe0, 0x3d, 0xf2, 0x15, 0xa3, 0x5d, 0xa6, 0x16, 0x19, 0x06, 0xe0, 0x3d, 0x1a, 0x16, 0xa3, 0x5d, 0xe0, 0x3c, 0x06, 0x16, 0x83, 0x5c, 0x85, 0x15, 0x19, 0x05, 0xe0, 0x3c, 0xaa, 0x15, 0x83, 0x5c, 0xc5, 0x00, 0xbe, 0x58, 0xec, 0x04, 0x12, 0x38, 0xd1, 0x04, 0x7a, 0x96, 0xc5, 0x00, 0x12, 0x38, 0xd0, 0x04, 0x76, 0x98, 0xe0, 0x38, 0xaa, 0x15, 0x7c, 0xa8, 0x9b, 0x58, 0x06, 0xac, 0x0c, 0x00, 0x80, 0x39, 0x3b, 0x92, 0x05, 0xac, 0x20, 0x92, 0xe0, 0x3c, 0xde, 0x15, 0x83, 0x5c, 0xc8, 0x5a, 0x19, 0x12, 0x82, 0x04, 0xe0, 0x3b, 0x1a, 0x16, 0x63, 0x5b, 0xa8, 0x59, 0x19, 0x11, 0x61, 0x03, 0x80, 0x38, 0x48, 0x0e, 0x9e, 0x5a, 0xb8, 0x00, 0x43, 0x48, 0x03, 0x59, 0x01, 0xa8, 0x3d, 0x58, 0x03, 0x59, 0x01, 0xa8, 0x3f, 0x58, 0x10, 0x38, 0xb8, 0x00, 0x03, 0x59, 0x01, 0xa8, 0x3d, 0x58, 0x03, 0x59, 0x01, 0xa8, 0x3b, 0x58, 0x4c, 0x9e, 0xe0, 0x3c, 0xde, 0x15, 0x83, 0x5c, 0xc8, 0x5a, 0x19, 0x12, 0x82, 0x04, 0xe0, 0x3b, 0x1a, 0x16, 0x63, 0x5b, 0xa2, 0x39, 0x01, 0x00, 0x28, 0x59, 0x61, 0x03, 0x80, 0x38, 0x48, 0x0e, 0x9e, 0x5a, 0xb8, 0x00, 0x43, 0x48, 0x03, 0x59, 0x01, 0xa8, 0x3d, 0x58, 0x03, 0x59, 0x01, 0xa8, 0x3b, 0x58, 0x33, 0x9e, 0x05, 0xac, 0x1b, 0x92, 0xe0, 0x3c, 0xde, 0x15, 0x9b, 0x9c, 0xc0, 0x39, 0x83, 0x5c, 0xc2, 0x3a, 0x01, 0x00, 0x48, 0x5a, 0x82, 0x04, 0xe0, 0x3b, 0x1a, 0x16, 0x63, 0x5b, 0xa8, 0x59, 0x19, 0x11, 0x61, 0x03, 0x80, 0x38, 0x48, 0x0e, 0x9e, 0x5a, 0xb8, 0x00, 0x43, 0x48, 0x03, 0x59, 0x01, 0xa8, 0x3b, 0x58, 0x10, 0x38, 0xb8, 0x00, 0x03, 0x59, 0x01, 0xa8, 0x3b, 0x58, 0x16, 0x9e, 0xe0, 0x3c, 0xde, 0x15, 0x83, 0x5c, 0xc2, 0x3a, 0x01, 0x00, 0x48, 0x5a, 0x82, 0x04, 0xe0, 0x3b, 0x1a, 0x16, 0x63, 0x5b, 0xa2, 0x39, 0x01, 0x00, 0x28, 0x59, 0x61, 0x03, 0x80, 0x38, 0x48, 0x0e, 0x9e, 0x5a, 0xb8, 0x00, 0x43, 0x48, 0x03, 0x59, 0x01, 0xa8, 0x3b, 0x58, 0x3e, 0xfa, 0xfd, 0xf9, 0x19, 0x07, 0xf2, 0x38, 0x4b, 0x1a, 0x63, 0x97, 0xa0, 0xfa, 0xcb, 0xfa, 0x04, 0x9e, 0x9e, 0x58, 0xce, 0x04, 0xbe, 0x58, 0xcd, 0x04, 0x3a, 0x38, 0x9e, 0x5e, 0xca, 0x04, 0xc2, 0x38, 0xc1, 0x97, -0x00, 0x3a, 0x01, 0x00, 0x23, 0x9a, 0x00, 0x66, 0xc0, 0x3d, 0x01, 0x00, 0xc0, 0x3c, 0xe0, 0x04, 0x83, 0x5c, 0xa0, 0x3b, 0xe0, 0x04, 0x74, 0x10, 0x04, 0x58, 0xc0, 0x3c, 0xe5, 0x04, 0x83, 0x5c, 0xa0, 0x3b, 0xe5, 0x04, 0x74, 0x11, 0x04, 0x59, 0x01, 0x00, 0x19, 0x10, 0x0f, 0x9a, 0x01, 0x61, 0xbe, 0x59, 0xcb, 0x04, 0xc8, 0x60, 0x04, 0x68, 0xe2, 0x39, 0x10, 0x00, 0x01, 0x96, 0x19, 0x00, 0xe0, 0x39, 0x63, 0x29, 0x29, 0x59, 0x11, 0x29, 0x3b, 0x58, 0x0b, 0x9e, 0x9e, 0x58, 0xcd, 0x04, 0x9e, 0x59, 0xce, 0x04, 0x30, 0x39, 0xd5, 0x04, 0x01, 0x10, 0xec, 0x99, 0x02, 0x60, 0xbe, 0x58, 0xcc, 0x04, 0x19, 0x05, 0xb2, 0x38, 0xca, 0x04, 0xd1, 0x97, 0x19, 0x06, 0xd2, 0x38, 0xca, 0x04, 0x19, 0x00, 0xca, 0x97, 0x03, 0x9e, 0x02, 0x60, 0xbe, 0x58, 0xcc, 0x04, 0x3a, 0x38, 0xe0, 0x3b, 0x1a, 0x16, 0x89, 0xe3, +0x00, 0x3a, 0x01, 0x00, 0x23, 0x9a, 0x00, 0x66, 0xc0, 0x3d, 0x01, 0x00, 0xc0, 0x3c, 0xe0, 0x04, 0x83, 0x5c, 0xa0, 0x3b, 0xe0, 0x04, 0x74, 0x10, 0x04, 0x58, 0xc0, 0x3c, 0xe5, 0x04, 0x83, 0x5c, 0xa0, 0x3b, 0xe5, 0x04, 0x74, 0x11, 0x04, 0x59, 0x01, 0x00, 0x19, 0x10, 0x0f, 0x9a, 0x01, 0x61, 0xbe, 0x59, 0xcb, 0x04, 0xc8, 0x60, 0x04, 0x68, 0xe2, 0x39, 0x10, 0x00, 0x01, 0x96, 0x19, 0x00, 0xe0, 0x39, 0x85, 0x29, 0x29, 0x59, 0x11, 0x29, 0x3b, 0x58, 0x0b, 0x9e, 0x9e, 0x58, 0xcd, 0x04, 0x9e, 0x59, 0xce, 0x04, 0x30, 0x39, 0xd5, 0x04, 0x01, 0x10, 0xec, 0x99, 0x02, 0x60, 0xbe, 0x58, 0xcc, 0x04, 0x19, 0x05, 0xb2, 0x38, 0xca, 0x04, 0xd1, 0x97, 0x19, 0x06, 0xd2, 0x38, 0xca, 0x04, 0x19, 0x00, 0xca, 0x97, 0x03, 0x9e, 0x02, 0x60, 0xbe, 0x58, 0xcc, 0x04, 0x3a, 0x38, 0xe0, 0x3b, 0x1a, 0x16, 0xab, 0xe3, 0x40, 0x3a, 0x63, 0x5e, 0xe0, 0x3b, 0xde, 0x15, 0x63, 0x5d, 0x00, 0x60, 0xbe, 0x58, 0xca, 0x04, 0x1e, 0x5d, 0x6d, 0xfa, 0x9c, 0xfc, 0x59, 0x48, 0x15, 0x96, 0x5b, 0x48, 0x13, 0x96, 0x88, 0xfc, 0x59, 0x48, 0x10, 0x96, 0x5b, 0x48, 0x0e, 0x96, 0x9e, 0x58, 0xca, 0x04, 0x02, 0x3c, 0x05, 0x00, 0x09, 0x94, 0x00, 0x3c, 0xe0, 0x04, 0xbb, 0x5c, 0x00, 0x3c, 0xe5, 0x04, 0xdb, 0x5c, 0x19, 0x00, 0xbe, 0x58, 0xca, 0x04, 0x19, 0x05, 0xe0, 0x3b, 0xf2, 0x15, 0xbb, 0x49, 0xe2, 0x9b, 0x3e, 0x5d, 0x19, 0x06, 0xe0, 0x3b, 0x06, 0x16, 0xdb, 0x49, 0xdb, 0x9b, 0x3a, 0x38, 0x1e, 0x5e, 0xc0, 0x3c, 0x01, 0x00, 0xa0, 0x3b, 0x01, 0x00, 0x19, 0x16, 0x19, 0x15, 0xd7, 0x62, 0x04, 0x6a, 0x1e, 0x5d, 0xc2, 0x39, 0x00, 0x00, 0x1b, 0x96, 0xd2, 0x39, 0xb9, 0x00, 0x18, 0x94, 0xa0, 0x38, 0x48, 0x0e, 0x9e, 0x59, 0x83, 0x10, 0x80, 0x3a, 0xb8, 0x00, 0x26, 0x48, 0xa2, 0x39, 0x00, 0x00, 0x09, 0x96, 0xb2, 0x39, 0xb8, 0x00, 0x06, 0x94, 0x03, 0x59, 0x01, 0xac, 0x01, 0x90, 0x28, 0x59, 0x3d, 0x5a, 0x02, 0x9e, 0x00, 0x61, 0x3d, 0x5a, 0x19, 0x00, 0x19, 0x05, 0xbb, 0x48, 0xee, 0x9b, 0x04, 0x9e, 0x00, 0x61, 0x3d, 0x5a, 0x3d, 0x5a, 0x3d, 0x5a, 0x3e, 0x5d, 0x19, 0x06, 0xdc, 0x48, 0xd9, 0x9b, 0x19, 0x05, 0x3e, 0x5e, 0x3a, 0x38, 0x9e, 0x5f, 0xcb, 0x04, 0xf0, 0x3f, 0xcc, 0x04, 0xe2, 0x38, 0x01, 0x00, 0x17, 0x8a, 0xe2, 0x38, 0x02, 0x00, 0x08, 0x8a, 0xe2, 0x38, 0x03, 0x00, 0x1b, 0x8a, 0x9e, 0x58, 0xce, 0x04, 0xbe, 0x58, 0xcd, 0x04, 0x16, 0x9e, 0x9e, 0x58, 0xcd, 0x04, 0x12, 0x38, 0xd6, 0x04, 0x9e, 0x59, 0xce, 0x04, 0xb8, 0x11, 0x01, 0x11, 0x0d, 0x96, 0xbe, 0x58, 0xcd, 0x04, 0x0a, 0x9e, 0x9e, 0x58, 0xcd, 0x04, 0xf2, 0xf3, -0xc0, 0x3a, 0x19, 0x00, 0x9e, 0x59, 0xce, 0x04, 0xb8, 0x01, 0x01, 0x11, 0x02, 0x98, 0xbe, 0x58, 0xcd, 0x04, 0x9e, 0x58, 0xcd, 0x04, 0x3a, 0x38, 0x9e, 0x5f, 0x4b, 0x1a, 0xbe, 0x5f, 0x82, 0x1a, 0x00, 0x67, 0x9e, 0x5e, 0xcd, 0x04, 0x9e, 0x5a, 0xce, 0x04, 0x9e, 0x59, 0xd5, 0x04, 0x41, 0x10, 0xc0, 0x10, 0x19, 0x96, 0x41, 0x00, 0xc0, 0x10, 0x23, 0x9a, 0xe0, 0x38, 0xaa, 0x15, 0x03, 0x58, 0x04, 0x38, 0xff, 0x00, 0xbe, 0x58, 0xed, 0x04, 0x12, 0x39, 0xd2, 0x04, 0x19, 0x9a, 0xc8, 0x60, 0x04, 0x68, 0xe2, 0x39, 0x10, 0x00, 0x01, 0x96, 0x19, 0x00, 0xe0, 0x39, 0x63, 0x29, 0x29, 0x59, 0x11, 0x29, 0x3b, 0x58, 0x18, 0x9e, 0xc8, 0x60, 0x04, 0x68, 0xe2, 0x39, 0x10, 0x00, 0x01, 0x96, 0x19, 0x00, 0xe0, 0x39, 0x63, 0x29, 0x29, 0x59, 0x20, 0x59, 0x11, 0x21, 0x3b, 0x58, 0xe2, 0x9e, 0xc8, 0x60, 0x1b, 0xc7, -0x00, 0x3b, 0x04, 0x68, 0xe2, 0x39, 0x10, 0x00, 0x01, 0x96, 0x19, 0x00, 0xe0, 0x39, 0x63, 0x29, 0x29, 0x59, 0x11, 0x21, 0xd7, 0x8a, 0xe0, 0x3e, 0xde, 0x15, 0xc3, 0x5e, 0xe0, 0x3d, 0xf2, 0x15, 0xb6, 0x16, 0x19, 0x06, 0xe0, 0x3d, 0x1a, 0x16, 0xa3, 0x5d, 0xe0, 0x3c, 0x06, 0x16, 0x95, 0x15, 0x19, 0x05, 0xdd, 0x48, 0x04, 0x98, 0x62, 0x96, 0x06, 0xac, 0x32, 0x92, 0x02, 0x9e, 0x06, 0xac, 0x2f, 0x92, 0xe0, 0x3c, 0xde, 0x15, 0x83, 0x5c, 0xc8, 0x5e, 0x19, 0x16, 0xc4, 0x06, 0xe0, 0x38, 0xf2, 0x15, 0x03, 0x59, 0x1e, 0x59, 0xdb, 0x58, 0xe0, 0x3b, 0x1a, 0x16, 0x63, 0x5b, 0xa3, 0x05, 0x19, 0x15, 0xe7, 0xfb, 0xe0, 0x38, 0xaa, 0x15, 0x5b, 0x58, 0xc0, 0x3c, 0x01, 0x00, 0x3e, 0x5e, 0x9e, 0x58, 0x4b, 0x1a, 0x00, 0x39, 0xde, 0x15, 0x9b, 0x59, 0x00, 0x39, 0xf2, 0x15, 0xdb, 0x59, 0x00, 0x39, 0x30, 0x38, +0xc0, 0x3a, 0x19, 0x00, 0x9e, 0x59, 0xce, 0x04, 0xb8, 0x01, 0x01, 0x11, 0x02, 0x98, 0xbe, 0x58, 0xcd, 0x04, 0x9e, 0x58, 0xcd, 0x04, 0x3a, 0x38, 0x9e, 0x5f, 0x4b, 0x1a, 0xbe, 0x5f, 0x82, 0x1a, 0x00, 0x67, 0x9e, 0x5e, 0xcd, 0x04, 0x9e, 0x5a, 0xce, 0x04, 0x9e, 0x59, 0xd5, 0x04, 0x41, 0x10, 0xc0, 0x10, 0x19, 0x96, 0x41, 0x00, 0xc0, 0x10, 0x23, 0x9a, 0xe0, 0x38, 0xaa, 0x15, 0x03, 0x58, 0x04, 0x38, 0xff, 0x00, 0xbe, 0x58, 0xed, 0x04, 0x12, 0x39, 0xd2, 0x04, 0x19, 0x9a, 0xc8, 0x60, 0x04, 0x68, 0xe2, 0x39, 0x10, 0x00, 0x01, 0x96, 0x19, 0x00, 0xe0, 0x39, 0x85, 0x29, 0x29, 0x59, 0x11, 0x29, 0x3b, 0x58, 0x18, 0x9e, 0xc8, 0x60, 0x04, 0x68, 0xe2, 0x39, 0x10, 0x00, 0x01, 0x96, 0x19, 0x00, 0xe0, 0x39, 0x85, 0x29, 0x29, 0x59, 0x20, 0x59, 0x11, 0x21, 0x3b, 0x58, 0xe2, 0x9e, 0xc8, 0x60, 0x5f, 0xc7, +0x00, 0x3b, 0x04, 0x68, 0xe2, 0x39, 0x10, 0x00, 0x01, 0x96, 0x19, 0x00, 0xe0, 0x39, 0x85, 0x29, 0x29, 0x59, 0x11, 0x21, 0xd7, 0x8a, 0xe0, 0x3e, 0xde, 0x15, 0xc3, 0x5e, 0xe0, 0x3d, 0xf2, 0x15, 0xb6, 0x16, 0x19, 0x06, 0xe0, 0x3d, 0x1a, 0x16, 0xa3, 0x5d, 0xe0, 0x3c, 0x06, 0x16, 0x95, 0x15, 0x19, 0x05, 0xdd, 0x48, 0x04, 0x98, 0x62, 0x96, 0x06, 0xac, 0x32, 0x92, 0x02, 0x9e, 0x06, 0xac, 0x2f, 0x92, 0xe0, 0x3c, 0xde, 0x15, 0x83, 0x5c, 0xc8, 0x5e, 0x19, 0x16, 0xc4, 0x06, 0xe0, 0x38, 0xf2, 0x15, 0x03, 0x59, 0x1e, 0x59, 0xdb, 0x58, 0xe0, 0x3b, 0x1a, 0x16, 0x63, 0x5b, 0xa3, 0x05, 0x19, 0x15, 0xe7, 0xfb, 0xe0, 0x38, 0xaa, 0x15, 0x5b, 0x58, 0xc0, 0x3c, 0x01, 0x00, 0x3e, 0x5e, 0x9e, 0x58, 0x4b, 0x1a, 0x00, 0x39, 0xde, 0x15, 0x9b, 0x59, 0x00, 0x39, 0xf2, 0x15, 0xdb, 0x59, 0x00, 0x39, 0x52, 0x38, 0x40, 0x3b, 0x06, 0x16, 0xbb, 0x59, 0x00, 0x39, 0x1a, 0x16, 0x7b, 0x59, 0xe7, 0xfb, 0x9e, 0x5c, 0x4b, 0x1a, 0x80, 0x39, 0xaa, 0x15, 0xe1, 0x58, 0xfe, 0x58, 0x68, 0xa8, 0x48, 0x29, 0x8c, 0x9e, 0xe0, 0x3c, 0xde, 0x15, 0x83, 0x5c, 0x19, 0x16, 0xc8, 0x5e, 0xc4, 0x06, 0xe0, 0x38, 0xf2, 0x15, 0x03, 0x59, 0x1e, 0x59, 0xdb, 0x58, 0xe0, 0x3b, 0x1a, 0x16, 0x63, 0x5b, 0xa3, 0x05, 0x19, 0x15, 0xe7, 0xfb, 0xe0, 0x38, 0xaa, 0x15, 0x5b, 0x58, 0xc1, 0x5c, 0x3e, 0x5e, 0x9e, 0x58, 0x4b, 0x1a, 0x00, 0x39, 0xde, 0x15, 0x9b, 0x59, 0x00, 0x39, 0xf2, 0x15, 0xdb, 0x59, 0x00, 0x39, 0x06, 0x16, 0xbb, 0x59, 0x00, 0x39, 0x1a, 0x16, 0x7b, 0x59, 0xe7, 0xfb, 0x9e, 0x5c, 0x4b, 0x1a, 0x80, 0x39, 0xaa, 0x15, 0xe1, 0x58, 0xfe, 0x58, 0x68, 0xa8, 0x48, 0x29, 0x5e, 0x9e, 0x05, 0xac, 0x2f, 0x92, 0xe0, 0x3c, 0xc3, 0x56, 0x80, 0x3b, 0xde, 0x15, 0x83, 0x5c, 0x86, 0x06, 0x19, 0x16, 0xe0, 0x3b, 0x1a, 0x16, 0x63, 0x5b, 0xa8, 0x5d, 0x19, 0x15, 0xa3, 0x05, 0xe0, 0x38, 0x06, 0x16, 0x03, 0x59, 0x1e, 0x59, 0xbb, 0x58, 0xe7, 0xfb, 0xe0, 0x38, 0xaa, 0x15, 0x5b, 0x58, 0xa0, 0x3b, 0x01, 0x00, 0x3e, 0x5d, 0x9e, 0x58, 0x4b, 0x1a, 0x00, 0x39, 0xde, 0x15, 0x9b, 0x59, 0x00, 0x39, 0xf2, 0x15, 0xdb, 0x59, 0x00, 0x39, 0x06, 0x16, 0xbb, 0x59, 0x00, 0x39, 0x1a, 0x16, 0x7b, 0x59, 0xe7, 0xfb, 0x9e, 0x5c, 0x4b, 0x1a, 0x80, 0x39, 0xaa, 0x15, 0xe1, 0x58, 0xfe, 0x58, 0x70, 0xa8, 0x48, 0x29, 0x2d, 0x9e, 0xe0, 0x3c, 0xde, 0x15, 0x83, 0x5c, 0x86, 0x06, 0x19, 0x16, 0xe0, 0x3b, 0x1a, 0x16, 0x63, 0x5b, 0x19, 0x15, 0xa8, 0x5d, 0xa3, 0x05, 0xe0, 0x38, 0x06, 0x16, 0x03, 0x59, 0x1e, 0x59, 0xbb, 0x58, 0xe7, 0xfb, 0xe0, 0x38, 0x1b, 0xff, 0xc0, 0x3b, 0xaa, 0x15, 0x5b, 0x58, 0xa1, 0x5b, 0x3e, 0x5d, 0x9e, 0x58, 0x4b, 0x1a, 0x00, 0x39, 0xde, 0x15, 0x9b, 0x59, 0x00, 0x39, 0xf2, 0x15, 0xdb, 0x59, 0x00, 0x39, 0x06, 0x16, 0xbb, 0x59, 0x00, 0x39, 0x1a, 0x16, 0x7b, 0x59, 0xe7, 0xfb, 0x9e, 0x5c, 0x4b, 0x1a, 0x80, 0x39, 0xaa, 0x15, 0xe1, 0x58, 0xfe, 0x58, 0x70, 0xa8, 0x48, 0x29, 0x19, 0x04, 0xbe, 0x5c, 0x4b, 0x1a, 0x82, 0x38, 0x14, 0x00, 0x05, 0x94, 0x19, 0x07, 0xf2, 0x38, 0x82, 0x1a, 0x98, 0x3d, 0xd0, 0x3a, 0x3a, 0x38, 0x1e, 0x5e, 0x1e, 0x5b, 0x00, 0x62, 0xc4, 0x16, 0x80, 0x38, 0x48, 0x0e, 0x9e, 0x59, 0xb8, 0x00, 0x23, 0x48, 0xc7, 0x38, 0xf9, 0x3b, 0x05, 0x59, 0x01, 0xac, 0x01, 0x90, 0x28, 0x59, 0x32, 0x39, 0x1d, 0x00, 0x00, 0x9a, 0x19, 0x02, 0x19, 0x03, 0x7d, 0x48, 0xee, 0x9b, 0x3e, 0x5b, 0x3e, 0x5e, 0x3a, 0x38, 0x78, 0x3d, -0x00, 0x3c, 0x00, 0x60, 0xbe, 0x58, 0xe2, 0x19, 0x9e, 0x5f, 0x4b, 0x1a, 0x18, 0x17, 0x5f, 0x9a, 0x00, 0x67, 0xe0, 0x3e, 0xaa, 0x15, 0xc3, 0x5e, 0xc4, 0x3e, 0xff, 0x00, 0xd2, 0x38, 0x23, 0x00, 0x52, 0x96, 0xff, 0x62, 0xe0, 0x3e, 0x1a, 0x16, 0xd2, 0x26, 0xe0, 0x3d, 0xde, 0x15, 0xb2, 0x25, 0xe0, 0x3c, 0x06, 0x16, 0x92, 0x24, 0xe0, 0x3b, 0xf2, 0x15, 0x72, 0x23, 0x1e, 0x5f, 0xcf, 0xd0, 0x1e, 0x5d, 0x9e, 0x5a, 0xb8, 0x00, 0xa0, 0x38, 0x48, 0x0e, 0x46, 0x48, 0x03, 0x5a, 0x42, 0x38, 0x01, 0x00, 0x2b, 0x9a, 0x50, 0x67, 0x1a, 0x6f, 0xe5, 0x58, 0xe3, 0x59, 0x45, 0x48, 0x3f, 0x5f, 0x1b, 0x5f, 0x52, 0x67, 0x1a, 0x6f, 0xe5, 0x58, 0xe3, 0x59, 0x46, 0x48, 0x3f, 0x5f, 0x1b, 0x5f, 0x50, 0x3f, 0x54, 0x1a, 0xbe, 0x5f, 0x54, 0x1a, 0x7f, 0xac, 0x17, 0x90, 0xe8, 0x5f, 0xbe, 0x5f, 0x54, 0x1a, 0x39, 0x56, -0x40, 0x3c, 0x9e, 0x58, 0x50, 0x1a, 0x9e, 0x59, 0x51, 0x1a, 0x28, 0x59, 0x0c, 0x58, 0xbe, 0x59, 0x51, 0x1a, 0xbe, 0x58, 0x50, 0x1a, 0x9e, 0x58, 0x52, 0x1a, 0x9e, 0x59, 0x53, 0x1a, 0x28, 0x59, 0x0c, 0x58, 0xbe, 0x59, 0x53, 0x1a, 0xbe, 0x58, 0x52, 0x1a, 0x19, 0x05, 0xbb, 0x48, 0xc9, 0x9b, 0x3e, 0x5d, 0x19, 0x06, 0xdc, 0x48, 0xc4, 0x9b, 0x3e, 0x5f, 0x67, 0xfc, 0x9e, 0x58, 0xe2, 0x19, 0x12, 0x38, 0x27, 0x00, 0x04, 0x94, 0x19, 0x07, 0xf2, 0x38, 0x4b, 0x1a, 0xa2, 0x97, 0x3a, 0x38, 0x9e, 0x58, 0x54, 0x1a, 0xbe, 0x58, 0x55, 0x1a, 0x00, 0x60, 0xbe, 0x58, 0x56, 0x1a, 0x9e, 0x5d, 0xe2, 0x19, 0x51, 0x63, 0x1a, 0x6b, 0x47, 0xd0, 0xa0, 0x3b, 0xb2, 0x19, 0x1b, 0x5b, 0x53, 0x63, 0x1a, 0x6b, 0x47, 0xd0, 0xa0, 0x3b, 0xbe, 0x19, 0x1b, 0x5b, 0xa0, 0x3b, 0xca, 0x19, 0xde, 0x5b, 0xff, 0xff, 0xf8, 0xb0, +0x00, 0x3c, 0x00, 0x60, 0xbe, 0x58, 0xe2, 0x19, 0x9e, 0x5f, 0x4b, 0x1a, 0x18, 0x17, 0x5f, 0x9a, 0x00, 0x67, 0xe0, 0x3e, 0xaa, 0x15, 0xc3, 0x5e, 0xc4, 0x3e, 0xff, 0x00, 0xd2, 0x38, 0x23, 0x00, 0x52, 0x96, 0xff, 0x62, 0xe0, 0x3e, 0x1a, 0x16, 0xd2, 0x26, 0xe0, 0x3d, 0xde, 0x15, 0xb2, 0x25, 0xe0, 0x3c, 0x06, 0x16, 0x92, 0x24, 0xe0, 0x3b, 0xf2, 0x15, 0x72, 0x23, 0x1e, 0x5f, 0xd4, 0xd0, 0x1e, 0x5d, 0x9e, 0x5a, 0xb8, 0x00, 0xa0, 0x38, 0x48, 0x0e, 0x46, 0x48, 0x03, 0x5a, 0x42, 0x38, 0x01, 0x00, 0x2b, 0x9a, 0x50, 0x67, 0x1a, 0x6f, 0xe5, 0x58, 0xe3, 0x59, 0x45, 0x48, 0x3f, 0x5f, 0x1b, 0x5f, 0x52, 0x67, 0x1a, 0x6f, 0xe5, 0x58, 0xe3, 0x59, 0x46, 0x48, 0x3f, 0x5f, 0x1b, 0x5f, 0x50, 0x3f, 0x54, 0x1a, 0xbe, 0x5f, 0x54, 0x1a, 0x7f, 0xac, 0x17, 0x90, 0xe8, 0x5f, 0xbe, 0x5f, 0x54, 0x1a, 0x3e, 0x56, +0x40, 0x3c, 0x9e, 0x58, 0x50, 0x1a, 0x9e, 0x59, 0x51, 0x1a, 0x28, 0x59, 0x0c, 0x58, 0xbe, 0x59, 0x51, 0x1a, 0xbe, 0x58, 0x50, 0x1a, 0x9e, 0x58, 0x52, 0x1a, 0x9e, 0x59, 0x53, 0x1a, 0x28, 0x59, 0x0c, 0x58, 0xbe, 0x59, 0x53, 0x1a, 0xbe, 0x58, 0x52, 0x1a, 0x19, 0x05, 0xbb, 0x48, 0xc9, 0x9b, 0x3e, 0x5d, 0x19, 0x06, 0xdc, 0x48, 0xc4, 0x9b, 0x3e, 0x5f, 0x67, 0xfc, 0x9e, 0x58, 0xe2, 0x19, 0x12, 0x38, 0x27, 0x00, 0x04, 0x94, 0x19, 0x07, 0xf2, 0x38, 0x4b, 0x1a, 0xa2, 0x97, 0x3a, 0x38, 0x9e, 0x58, 0x54, 0x1a, 0xbe, 0x58, 0x55, 0x1a, 0x00, 0x60, 0xbe, 0x58, 0x56, 0x1a, 0x9e, 0x5d, 0xe2, 0x19, 0x51, 0x63, 0x1a, 0x6b, 0x4c, 0xd0, 0xa0, 0x3b, 0xb2, 0x19, 0x1b, 0x5b, 0x53, 0x63, 0x1a, 0x6b, 0x4c, 0xd0, 0xa0, 0x3b, 0xbe, 0x19, 0x1b, 0x5b, 0xa0, 0x3b, 0xca, 0x19, 0xde, 0x5b, 0xff, 0xff, 0x02, 0xb1, 0x80, 0x3c, 0xa0, 0x3b, 0xd6, 0x19, 0xde, 0x5b, 0xff, 0x7f, 0x19, 0x05, 0xbe, 0x5d, 0xe2, 0x19, 0x3a, 0x38, 0xd7, 0x64, 0x04, 0x6c, 0x00, 0x63, 0x4f, 0x38, 0x8e, 0x3c, 0x93, 0x03, 0x1b, 0x04, 0x38, 0x14, 0x00, 0x62, 0x4f, 0x38, 0x94, 0x3c, 0x92, 0x02, 0x1b, 0x04, 0x38, 0x14, 0x00, 0x61, 0x4f, 0x38, 0x9a, 0x3c, 0x91, 0x01, 0x1b, 0x04, 0x3a, 0x38, 0xd7, 0x64, 0x04, 0x6c, 0x00, 0x63, 0x4f, 0x38, 0xa2, 0x3c, 0x93, 0x03, 0x19, 0x04, 0x00, 0x62, 0x4f, 0x38, 0xa7, 0x3c, 0x92, 0x02, 0x19, 0x04, 0x00, 0x61, 0x4f, 0x38, 0xac, 0x3c, 0x91, 0x01, 0x19, 0x04, 0x3a, 0x38, 0x48, 0x60, 0x0e, 0x68, 0x9e, 0x5f, 0xbf, 0x00, 0x19, 0x17, 0xe7, 0x38, 0xb7, 0x3c, 0x03, 0x59, 0x01, 0xaa, 0x3d, 0x58, 0x3a, 0x38, 0x00, 0x60, 0xbe, 0x58, 0xdd, 0x00, 0xbe, 0x58, 0xe3, 0x00, 0xbe, 0x58, 0xe2, 0x00, 0xb4, 0x44, 0xc0, 0x3c, 0xbe, 0x58, 0xe5, 0x00, 0xbe, 0x58, 0x16, 0x1f, 0x3a, 0x38, 0x00, 0x60, 0xbe, 0x58, 0xe3, 0x00, 0xbe, 0x58, 0xe2, 0x00, 0xbe, 0x58, 0xe5, 0x00, 0xbe, 0x58, 0x1e, 0x1d, 0xbe, 0x58, 0x16, 0x1f, 0x4d, 0xfe, 0xbe, 0x58, 0xdc, 0x00, 0xbe, 0x58, 0xe6, 0x00, 0x00, 0x60, 0x79, 0xfe, 0xbe, 0x58, 0x45, 0x01, 0x00, 0x60, 0x98, 0xfe, 0xbe, 0x58, 0x46, 0x01, 0x3a, 0x38, 0x9e, 0x5f, 0xe2, 0x00, 0x27, 0xaa, 0xbe, 0x5f, 0xe2, 0x00, 0x1f, 0xac, 0x0e, 0x92, 0x9e, 0x5f, 0xe5, 0x00, 0x19, 0x07, 0xbe, 0x5f, 0xe5, 0x00, 0xb8, 0x66, 0x0b, 0x6e, 0xfe, 0x48, 0x05, 0x9c, 0x9e, 0x5f, 0xe2, 0x00, 0x1f, 0xa8, 0xbe, 0x5f, 0xe2, 0x00, 0x9e, 0x5f, 0xdf, 0x00, 0x19, 0x07, 0xbe, 0x5f, 0xdf, 0x00, 0x9e, 0x5e, 0xe1, 0x00, 0xdf, 0x48, 0x98, 0x38, 0x4b, 0x3e, 0x00, 0x67, 0xbe, 0x5f, 0xdf, 0x00, 0xab, 0x3f, 0x00, 0x3d, 0x4d, 0xfe, 0xbe, 0x58, 0xdb, 0x00, 0x9e, 0x59, 0xdc, 0x00, 0x19, 0x48, 0x2c, 0x82, 0x20, 0x10, 0x1e, 0x61, 0x38, 0x48, 0x20, 0x82, 0x9e, 0x5f, 0xe2, 0x00, 0x47, 0xa8, 0xbe, 0x5f, 0xe2, 0x00, 0x9e, 0x5a, 0x1e, 0x1d, 0x19, 0x02, 0xbe, 0x5a, 0x1e, 0x1d, 0x03, 0x63, 0x5b, 0x48, 0x1b, 0x96, 0x00, 0x62, 0xbe, 0x5a, 0x1e, 0x1d, 0x9e, 0x5f, 0xe2, 0x00, 0x47, 0xaa, 0xbe, 0x5f, 0xe2, 0x00, 0x9e, 0x58, 0xdb, 0x00, 0x9e, 0x59, 0xdc, 0x00, 0x20, 0x11, 0xbe, 0x58, 0xdc, 0x00, 0x10, 0x60, 0x19, 0x48, 0xd4, 0x82, 0xec, 0x9e, 0x00, 0x62, 0xbe, 0x5a, 0x1e, 0x1d, 0x9e, 0x5f, 0xe2, 0x00, 0x47, 0xaa, 0xbe, 0x5f, 0xe2, 0x00, 0x9e, 0x5f, 0xea, 0x04, 0x18, 0x17, 0x06, 0x8a, 0x00, 0x67, 0xbe, 0x5f, 0xdf, 0x00, 0xbe, 0x5f, 0xe3, 0x00, 0x09, 0x9e, 0x9e, 0x5f, 0xe2, 0x19, 0x18, 0x17, 0x6d, 0x61, @@ -260,12 +260,12 @@ 0xc0, 0x42, 0xff, 0x00, 0x7f, 0x38, 0x06, 0x58, 0x64, 0x3b, 0xff, 0x00, 0x7f, 0x38, 0x66, 0x5b, 0x60, 0x33, 0x0b, 0x8a, 0xd1, 0xa8, 0x09, 0x9e, 0x04, 0x38, 0x00, 0xff, 0xfe, 0x58, 0x64, 0x3b, 0x00, 0xff, 0xfe, 0x5b, 0x60, 0x33, 0x01, 0x8a, 0xd1, 0xa8, 0xe1, 0x01, 0x30, 0x28, 0x1b, 0x59, 0xc8, 0x5e, 0x19, 0x05, 0x19, 0x14, 0xd9, 0x89, 0x9e, 0x5a, 0x90, 0x19, 0xbe, 0x5a, 0xc0, 0x01, 0x9e, 0x5a, 0x91, 0x19, 0xbe, 0x5a, 0xc1, 0x01, 0x9e, 0x5a, 0x92, 0x19, 0xbe, 0x5a, 0xc2, 0x01, 0x3a, 0x38, 0x53, 0x60, 0x16, 0x39, 0x5e, 0x00, 0x82, 0x8a, 0x54, 0x60, 0x16, 0x39, 0x5e, 0x00, 0x98, 0x3a, 0x11, 0x45, 0x57, 0x60, 0x16, 0x39, 0x5e, 0x00, 0x98, 0x3a, 0x00, 0x48, 0x58, 0x60, 0x16, 0x39, 0x5e, 0x00, 0x98, 0x3a, 0x5f, 0x48, 0x19, 0x38, 0x66, 0x43, 0x26, 0x38, 0x66, 0x00, 0x98, 0x3a, 0x2d, 0xca, 0x00, 0x43, 0x5b, 0x48, 0x9f, 0x60, 0x16, 0x39, 0x5e, 0x00, 0x0d, 0x88, 0x00, 0x60, 0x16, 0x39, 0x5f, 0x00, 0x36, 0x38, 0x60, 0x00, 0x06, 0x88, 0x01, 0x60, 0x16, 0x39, 0x61, 0x00, 0x02, 0x88, 0xb9, 0xaa, 0xf7, 0xaa, 0x3a, 0x38, 0x96, 0x60, 0x16, 0x39, 0x5e, 0x00, 0x02, 0x88, 0x98, 0x3f, 0x8a, 0x47, 0x97, 0x60, 0x16, 0x39, 0x5e, 0x00, 0x02, 0x88, 0x98, 0x3f, 0xf6, 0x47, 0x98, 0x60, 0x16, 0x39, 0x5e, 0x00, 0x02, 0x88, 0x98, 0x3f, 0xaf, 0x47, 0x5b, 0x60, 0x16, 0x39, 0x5e, 0x00, 0x02, 0x88, 0x98, 0x3f, 0xcf, 0x47, 0x19, 0x38, 0x66, 0x43, 0x26, 0x38, 0x56, 0x00, 0x02, 0x88, 0x84, 0xaa, 0x3a, 0x38, 0x19, 0x38, 0x66, 0x43, 0x26, 0x38, 0xa6, 0x00, 0x02, 0x88, 0x84, 0xa8, 0x3a, 0x38, 0x19, 0x38, 0x66, 0x43, 0x26, 0x38, 0x57, 0x00, 0x02, 0x88, 0xa8, 0xa8, 0x3a, 0x38, 0x19, 0x38, 0x05, 0xed, 0x40, 0x43, 0x66, 0x43, 0x26, 0x38, 0xa7, 0x00, 0x02, 0x88, 0xa8, 0xaa, 0x3a, 0x38, 0x19, 0x38, 0x66, 0x43, 0x26, 0x38, 0x55, 0x00, 0x05, 0x88, 0xba, 0xaa, 0x5e, 0x71, 0xbe, 0x59, 0xc1, 0x1d, 0x3a, 0x38, 0x19, 0x38, 0x66, 0x43, 0x26, 0x38, 0xa5, 0x00, 0x09, 0x88, 0xba, 0xa8, 0x81, 0xaa, 0x5e, 0x71, 0xbe, 0x59, 0xc1, 0x1d, 0x00, 0x60, 0xbe, 0x58, 0x27, 0x1d, 0x3a, 0x38, 0x19, 0x38, 0x66, 0x43, 0x26, 0x38, 0x77, 0x00, 0x02, 0x88, 0x42, 0xa9, 0x3a, 0x38, 0x3a, 0x38, 0x5e, 0x70, 0x14, 0x39, 0x5f, 0x00, 0x34, 0x38, 0x60, 0x00, 0x14, 0x39, 0x61, 0x00, 0x3a, 0x38, 0xa2, 0xa8, 0x04, 0x60, 0x69, 0x78, 0x52, 0x60, 0x6a, 0x78, 0x5f, 0x70, 0x6b, 0x78, 0x00, 0x60, 0x6c, 0x78, 0x01, 0x60, 0x6d, 0x78, 0x5f, 0x70, 0x7f, 0x38, 0x08, 0x58, 0x3f, 0x20, 0x00, 0x39, 0x81, 0x43, 0x29, 0x58, 0xd7, 0x4b, -0x80, 0x43, 0x5e, 0x58, 0x91, 0x43, 0x95, 0x43, 0x9a, 0x43, 0xbb, 0x43, 0xc5, 0x43, 0xe7, 0x43, 0x02, 0x44, 0x56, 0x44, 0x57, 0x44, 0x9c, 0x44, 0xa4, 0x44, 0xb0, 0x44, 0xdf, 0x44, 0xf3, 0x44, 0xf5, 0x44, 0xf7, 0x44, 0x42, 0x60, 0xa0, 0x68, 0x98, 0x3f, 0xfc, 0x44, 0x1c, 0x61, 0x02, 0x69, 0x29, 0x58, 0x98, 0x3f, 0xfc, 0x44, 0x5f, 0x70, 0x06, 0x39, 0x20, 0x00, 0x0a, 0x8a, 0x06, 0x39, 0x27, 0x00, 0x0e, 0x8a, 0x06, 0x39, 0x28, 0x00, 0x0e, 0x8a, 0x06, 0x39, 0x29, 0x00, 0x0c, 0x8a, 0x3a, 0x38, 0xf5, 0xac, 0x01, 0x90, 0x01, 0x61, 0x6c, 0x79, 0x01, 0x61, 0x6d, 0x79, 0x3a, 0x38, 0xfd, 0xac, 0x09, 0x90, 0x06, 0x9e, 0x02, 0x9e, 0xfa, 0x60, 0x5f, 0x68, 0x09, 0x58, 0x18, 0x10, 0x02, 0x88, 0x01, 0x60, 0x6c, 0x78, 0x3a, 0x38, 0x6b, 0x71, 0x24, 0x39, 0xf0, 0x00, 0x00, 0x60, 0xd8, 0xac, 0xc1, 0xaf, +0x80, 0x43, 0x5e, 0x58, 0x91, 0x43, 0x95, 0x43, 0x9a, 0x43, 0xbb, 0x43, 0xc5, 0x43, 0xe7, 0x43, 0x02, 0x44, 0x56, 0x44, 0x57, 0x44, 0x9c, 0x44, 0xa4, 0x44, 0xb0, 0x44, 0xdf, 0x44, 0xf3, 0x44, 0xf5, 0x44, 0xf7, 0x44, 0x44, 0x60, 0xa0, 0x68, 0x98, 0x3f, 0xfc, 0x44, 0x1c, 0x61, 0x02, 0x69, 0x29, 0x58, 0x98, 0x3f, 0xfc, 0x44, 0x5f, 0x70, 0x06, 0x39, 0x20, 0x00, 0x0a, 0x8a, 0x06, 0x39, 0x27, 0x00, 0x0e, 0x8a, 0x06, 0x39, 0x28, 0x00, 0x0e, 0x8a, 0x06, 0x39, 0x29, 0x00, 0x0c, 0x8a, 0x3a, 0x38, 0xf5, 0xac, 0x01, 0x90, 0x01, 0x61, 0x6c, 0x79, 0x01, 0x61, 0x6d, 0x79, 0x3a, 0x38, 0xfd, 0xac, 0x09, 0x90, 0x06, 0x9e, 0x02, 0x9e, 0xfa, 0x60, 0x5f, 0x68, 0x09, 0x58, 0x18, 0x10, 0x02, 0x88, 0x01, 0x60, 0x6c, 0x78, 0x3a, 0x38, 0x6b, 0x71, 0x24, 0x39, 0xf0, 0x00, 0x00, 0x60, 0xd8, 0xac, 0xc3, 0xaf, 0xc0, 0x43, 0x01, 0x90, 0x18, 0xa8, 0x20, 0x29, 0x6b, 0x79, 0x3a, 0x38, 0x6b, 0x71, 0x24, 0x39, 0xf3, 0x00, 0x03, 0x60, 0x01, 0x20, 0x00, 0x62, 0x1a, 0x48, 0x04, 0x8a, 0x00, 0x60, 0x24, 0x39, 0xf0, 0x00, 0x13, 0x9e, 0x03, 0x60, 0xd6, 0xac, 0x10, 0x92, 0x00, 0x60, 0x86, 0xac, 0x02, 0x90, 0x00, 0xa8, 0x04, 0x9e, 0x00, 0xaa, 0x8e, 0xac, 0x04, 0x90, 0x05, 0x9e, 0x8e, 0xac, 0x01, 0x90, 0x02, 0x9e, 0x08, 0xaa, 0x02, 0x9e, 0x08, 0xa8, 0x00, 0x9e, 0x20, 0x29, 0x6b, 0x79, 0x3a, 0x38, 0x6b, 0x71, 0x26, 0x38, 0x5a, 0x00, 0x0d, 0x8a, 0x24, 0x39, 0xf0, 0x00, 0x00, 0x60, 0xe0, 0xac, 0x05, 0x90, 0xd0, 0xac, 0x02, 0x90, 0x00, 0xa8, 0x01, 0x9e, 0x18, 0xa8, 0x20, 0x29, 0x6b, 0x79, 0x3a, 0x38, 0x9e, 0x59, 0xbd, 0x1d, 0x6b, 0x79, 0x9e, 0x59, 0xbe, 0x1d, 0x6c, 0x79, 0x9e, 0x59, 0xbf, 0x1d, 0x69, 0xa1, 0x00, 0x44, 0x6d, 0x79, 0x3a, 0x38, 0xb0, 0xac, 0x06, 0x90, 0xb8, 0xac, 0x02, 0x92, 0x06, 0x60, 0x03, 0x9e, 0x07, 0x60, 0x01, 0x9e, 0x08, 0x60, 0xb3, 0x78, 0x5f, 0x70, 0x3f, 0x20, 0x00, 0x38, 0x12, 0x44, 0x09, 0x59, 0x5e, 0x59, 0x22, 0x44, 0x35, 0x44, 0x36, 0x44, 0x37, 0x44, 0x4a, 0x44, 0x4b, 0x44, 0x4c, 0x44, 0x4d, 0x44, 0x4e, 0x44, 0x4f, 0x44, 0x50, 0x44, 0x51, 0x44, 0x52, 0x44, 0x53, 0x44, 0x54, 0x44, 0x55, 0x44, 0x00, 0x60, 0x00, 0x61, 0x9e, 0x5a, 0xb8, 0x00, 0xb3, 0x73, 0x19, 0x12, 0x43, 0x48, 0x04, 0x3a, 0xff, 0x00, 0x6c, 0x7a, 0x04, 0x3a, 0x00, 0x0f, 0xfe, 0x5a, 0x7f, 0x38, 0x46, 0x5a, 0x55, 0x3a, 0x6d, 0x00, 0x6d, 0x7a, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x00, 0x60, 0x00, 0x61, 0x9e, 0x5a, 0xb9, 0x00, 0xb3, 0x73, 0x19, 0x12, 0x43, 0x48, 0x04, 0x3a, 0xff, 0x00, 0x59, 0xa3, 0x40, 0x44, 0x6c, 0x7a, 0x04, 0x3a, 0x00, 0x0f, 0xfe, 0x5a, 0x7f, 0x38, 0x46, 0x5a, 0x55, 0x3a, 0x6d, 0x00, 0x6d, 0x7a, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x5f, 0x70, 0x3f, 0x20, 0x00, 0x38, 0x5e, 0x44, 0x09, 0x59, 0x01, 0x60, 0x5e, 0x59, 0x6e, 0x44, 0x72, 0x44, 0x74, 0x44, 0x75, 0x44, 0x79, 0x44, 0x7d, 0x44, 0x7e, 0x44, 0x7f, 0x44, 0x83, 0x44, 0x87, 0x44, 0x88, 0x44, 0x89, 0x44, 0x8a, 0x44, 0x8c, 0x44, 0x8d, 0x44, 0x8e, 0x44, 0xa1, 0xac, 0x01, 0x92, 0x00, 0xaa, 0x28, 0x9e, 0x12, 0x70, 0x26, 0x9e, 0x25, 0x9e, 0xf8, 0xac, 0x01, 0x92, 0x00, 0xaa, 0x21, 0x9e, 0xca, 0xac, 0x01, 0x92, 0x00, 0xaa, 0x1d, 0x9e, 0x1c, 0x9e, 0x1b, 0x9e, 0xf2, 0xac, 0x8c, 0x4f, 0x80, 0x44, 0x01, 0x92, 0x00, 0xaa, 0x17, 0x9e, 0xf0, 0xac, 0x01, 0x92, 0x00, 0xaa, 0x13, 0x9e, 0x12, 0x9e, 0x11, 0x9e, 0x10, 0x9e, 0x11, 0x70, 0x0e, 0x9e, 0x3a, 0x38, 0x3a, 0x38, 0x5f, 0x70, 0x06, 0x38, 0x8f, 0x00, 0x02, 0x8a, 0x1a, 0x38, 0x3a, 0x38, 0x01, 0x60, 0xe6, 0xac, 0x01, 0x92, 0x00, 0x60, 0x6c, 0x78, 0x3a, 0x38, 0x6c, 0x78, 0x3a, 0x38, 0x9e, 0x58, 0xfb, 0x04, 0x04, 0x38, 0x00, 0x0f, 0xfe, 0x58, 0x19, 0x00, 0x6c, 0x78, 0x3a, 0x38, 0x5f, 0x70, 0x06, 0x38, 0xa0, 0x00, 0x02, 0x8a, 0xa2, 0xaa, 0x3a, 0x38, 0x01, 0x60, 0xe8, 0xac, 0x01, 0x92, 0x00, 0xaa, 0x6c, 0x78, 0x3a, 0x38, 0x5f, 0x70, 0x3f, 0x20, 0x00, 0x38, 0xb6, 0x44, 0x09, 0x59, 0x5e, 0x59, 0xc6, 0x44, 0xcc, 0x44, 0xd1, 0x44, 0xd2, 0x44, 0xd3, 0x44, 0xd4, 0x44, 0xd5, 0x44, 0xd6, 0x44, 0xd7, 0x44, 0xd8, 0x44, 0x9e, 0x2f, -0xc0, 0x44, 0xd9, 0x44, 0xda, 0x44, 0xdb, 0x44, 0xdc, 0x44, 0xdd, 0x44, 0xde, 0x44, 0x01, 0x60, 0x90, 0xac, 0x01, 0x8a, 0x00, 0xaa, 0x6c, 0x78, 0x3a, 0x38, 0x03, 0x60, 0x14, 0x38, 0x00, 0x00, 0x6c, 0x78, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x5f, 0x71, 0x24, 0x38, 0x0f, 0x00, 0x00, 0x38, 0x8d, 0x2e, 0x09, 0x58, 0x02, 0x39, 0x00, 0x00, 0x02, 0x88, 0x6c, 0x78, 0x3a, 0x38, 0x03, 0x58, 0x04, 0x39, 0xff, 0x00, 0x6d, 0x79, 0xfe, 0x58, 0x04, 0x39, 0xff, 0x00, 0x6c, 0x79, 0x3a, 0x38, 0x00, 0x60, 0x07, 0x9e, 0x88, 0x60, 0x05, 0x9e, 0xfc, 0x61, 0x3f, 0x69, 0x29, 0x58, 0x29, 0x60, 0x30, 0x68, 0x04, 0x39, 0x00, 0xf0, 0xfe, 0x59, 0x7f, 0x38, 0xc4, 0xfc, +0xc0, 0x44, 0xd9, 0x44, 0xda, 0x44, 0xdb, 0x44, 0xdc, 0x44, 0xdd, 0x44, 0xde, 0x44, 0x01, 0x60, 0x90, 0xac, 0x01, 0x8a, 0x00, 0xaa, 0x6c, 0x78, 0x3a, 0x38, 0x03, 0x60, 0x14, 0x38, 0x00, 0x00, 0x6c, 0x78, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x5f, 0x71, 0x24, 0x38, 0x0f, 0x00, 0x00, 0x38, 0xa0, 0x2e, 0x09, 0x58, 0x02, 0x39, 0x00, 0x00, 0x02, 0x88, 0x6c, 0x78, 0x3a, 0x38, 0x03, 0x58, 0x04, 0x39, 0xff, 0x00, 0x6d, 0x79, 0xfe, 0x58, 0x04, 0x39, 0xff, 0x00, 0x6c, 0x79, 0x3a, 0x38, 0x00, 0x60, 0x07, 0x9e, 0x88, 0x60, 0x05, 0x9e, 0xfc, 0x61, 0x3f, 0x69, 0x29, 0x58, 0x29, 0x60, 0x30, 0x68, 0x04, 0x39, 0x00, 0xf0, 0xfe, 0x59, 0x7f, 0x38, 0xd7, 0xfc, 0x00, 0x45, 0x28, 0x59, 0x35, 0x39, 0x6b, 0x00, 0x6b, 0x79, 0x04, 0x39, 0xf0, 0x0f, 0x7f, 0x38, 0x28, 0x59, 0x6c, 0x79, 0x04, 0x39, 0x0f, 0x00, 0x7f, 0x38, 0x26, 0x59, 0x35, 0x39, 0x6d, 0x00, 0x6d, 0x79, 0x3a, 0x38, 0x5f, 0x70, 0x7f, 0x38, 0x08, 0x58, 0x3f, 0x20, 0x00, 0x39, 0x19, 0x45, 0x29, 0x58, 0x5e, 0x58, 0x29, 0x45, 0x35, 0x45, 0x36, 0x45, 0x0c, 0x46, 0x18, 0x46, 0x34, 0x46, 0x54, 0x46, 0x68, 0x46, 0x69, 0x46, 0xfc, 0x46, 0x45, 0x47, 0x56, 0x47, 0x78, 0x47, 0x87, 0x47, 0x88, 0x47, 0x89, 0x47, 0x60, 0x70, 0x12, 0x61, 0x19, 0x48, 0x07, 0x88, 0x61, 0x70, 0x34, 0x61, 0x19, 0x48, 0x03, 0x88, 0xff, 0x60, 0xff, 0x68, 0x60, 0xc0, 0x3a, 0x38, 0x3a, 0x38, 0x5f, 0x70, 0x06, 0x39, 0x25, 0x00, 0x38, 0x8a, 0x06, 0x39, 0x26, 0x00, 0x37, 0x8a, 0x06, 0x39, 0x27, 0x00, 0x1c, 0x8a, 0x3b, 0x0c, 0x40, 0x45, 0x06, 0x39, 0x28, 0x00, 0x10, 0x8a, 0x06, 0x39, 0x29, 0x00, 0x0f, 0x8a, 0x06, 0x39, 0x2a, 0x00, 0x1e, 0x8a, 0x06, 0x39, 0x2d, 0x00, 0x37, 0x8a, 0x06, 0x39, 0x2e, 0x00, 0x36, 0x8a, 0x06, 0x39, 0x2f, 0x00, 0x3d, 0x8a, 0x3a, 0x38, 0x97, 0xa8, 0x3a, 0x38, 0x5a, 0x60, 0x5a, 0x68, 0xbe, 0x58, 0xc2, 0x1d, 0xad, 0xa8, 0xf5, 0xa8, 0x3a, 0x38, 0x60, 0x70, 0x00, 0x61, 0x20, 0x31, 0x03, 0x8a, 0x01, 0x61, 0x20, 0x31, 0x02, 0x8a, 0xfd, 0xaa, 0x3a, 0x38, 0xfd, 0xa8, 0x3a, 0x38, 0x60, 0x70, 0x00, 0x61, 0x20, 0x31, 0x03, 0x8a, 0x01, 0x61, 0x20, 0x31, 0x02, 0x8a, 0xb6, 0xaa, 0x3a, 0x38, 0xb6, 0xa8, 0x3a, 0x38, 0x42, 0xa9, 0x3a, 0x38, 0x60, 0x70, 0x00, 0x61, 0x20, 0x31, 0x03, 0x8a, 0x01, 0x61, 0x20, 0x31, 0x04, 0x8a, 0x00, 0x60, 0xbe, 0x58, 0xc6, 0x00, 0x3a, 0x38, 0x01, 0x60, 0xe8, 0x70, 0x80, 0x45, 0xbe, 0x58, 0xc6, 0x00, 0x3a, 0x38, 0xdd, 0xa8, 0x3a, 0x38, 0x60, 0x70, 0x1f, 0x61, 0x20, 0x21, 0x21, 0x5a, 0xfe, 0x5a, 0x41, 0x2a, 0xbe, 0x5a, 0xf9, 0x04, 0xa5, 0xa8, 0x3a, 0x38, 0x60, 0x70, 0x06, 0x39, 0x00, 0x00, 0x10, 0x8a, 0x06, 0x39, 0x01, 0x00, 0x1c, 0x8a, 0x06, 0x39, 0x02, 0x00, 0x2b, 0x8a, 0x06, 0x39, 0x03, 0x00, 0x3a, 0x8a, 0x06, 0x39, 0x04, 0x00, 0x49, 0x8a, 0x06, 0x39, 0x05, 0x00, 0x58, 0x8a, 0x3a, 0x38, 0x85, 0xaa, 0x80, 0x62, 0x57, 0x6a, 0x48, 0x63, 0x0e, 0x6b, 0x0c, 0x61, 0x24, 0x60, 0x01, 0x40, 0x19, 0x10, 0x07, 0x38, 0xaf, 0x45, 0x4b, 0x5c, 0x9d, 0x5b, 0x1a, 0x38, 0x3a, 0x38, 0x7a, 0x62, 0x02, 0x6a, 0xb5, 0x63, 0x02, 0x6b, 0x9e, 0x5c, 0xbb, 0x00, 0x9e, 0x5d, 0xbc, 0x00, 0xa4, 0x05, 0x19, 0x15, 0xa7, 0x38, 0xc0, 0x45, 0x7d, 0x5a, 0x19, 0x03, 0x77, 0x51, @@ -275,11 +275,11 @@ 0x80, 0x46, 0xa1, 0xa8, 0x00, 0xac, 0x01, 0x92, 0xa1, 0xaa, 0xa1, 0xac, 0x01, 0x92, 0xf9, 0xaa, 0x3a, 0x38, 0x1b, 0x20, 0x12, 0x78, 0x3a, 0x38, 0x06, 0x39, 0x01, 0x00, 0x04, 0x8a, 0x06, 0x39, 0x00, 0x00, 0x02, 0x8a, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x06, 0x39, 0x01, 0x00, 0x04, 0x8a, 0x06, 0x39, 0x00, 0x00, 0x03, 0x8a, 0x3a, 0x38, 0xf8, 0xa8, 0x3a, 0x38, 0xf8, 0xaa, 0x3a, 0x38, 0x06, 0x39, 0x01, 0x00, 0x04, 0x8a, 0x06, 0x39, 0x00, 0x00, 0x03, 0x8a, 0x3a, 0x38, 0xca, 0xa8, 0x3a, 0x38, 0xca, 0xaa, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x06, 0x39, 0x01, 0x00, 0x07, 0x8a, 0x06, 0x39, 0x00, 0x00, 0x01, 0x8a, 0x3a, 0x38, 0xf2, 0xaa, 0x64, 0x61, 0x3a, 0x38, 0xf2, 0xa8, 0x69, 0x61, 0x3a, 0x38, 0x06, 0x39, 0x01, 0x00, 0x04, 0x8a, 0x06, 0x39, 0x00, 0x00, 0x03, 0x8a, 0x3a, 0x38, 0xfe, 0x71, 0xc0, 0x46, 0xf0, 0xa8, 0x3a, 0x38, 0xf0, 0xaa, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x11, 0x78, 0xee, 0xa8, 0x3a, 0x38, 0x61, 0x71, 0x01, 0x60, 0x19, 0x48, 0x0b, 0x88, 0x60, 0x71, 0x00, 0x60, 0x19, 0x48, 0x05, 0x8a, 0x01, 0x60, 0x19, 0x48, 0x04, 0x88, 0xed, 0xa8, 0x02, 0x9e, 0xed, 0xaa, 0x00, 0x9e, 0xdd, 0xa8, 0x3a, 0x38, 0x61, 0x71, 0x01, 0x60, 0x19, 0x48, 0x0b, 0x88, 0x60, 0x71, 0x00, 0x60, 0x19, 0x48, 0x05, 0x8a, 0x01, 0x60, 0x19, 0x48, 0x04, 0x88, 0x8d, 0xa8, 0x02, 0x9e, 0x8d, 0xaa, 0x00, 0x9e, 0xdd, 0xa8, 0x3a, 0x38, 0x61, 0x71, 0x01, 0x60, 0x19, 0x48, 0x0b, 0x88, 0x60, 0x71, 0x00, 0x60, 0x19, 0x48, 0x05, 0x8a, 0x01, 0x60, 0x19, 0x48, 0x04, 0x88, 0xe6, 0xa8, 0x02, 0x9e, 0xe6, 0xaa, 0xef, 0x9f, 0x3a, 0x38, 0x5f, 0x70, 0x06, 0x39, 0x90, 0x00, 0x01, 0x8a, 0x74, 0x4b, 0x00, 0x47, 0x3a, 0x38, 0x60, 0x70, 0x95, 0xa8, 0x06, 0x39, 0x01, 0x00, 0x17, 0x8a, 0x06, 0x39, 0x02, 0x00, 0x18, 0x8a, 0x06, 0x39, 0x03, 0x00, 0x1a, 0x8a, 0x06, 0x39, 0x04, 0x00, 0x1c, 0x8a, 0x06, 0x39, 0x05, 0x00, 0x1e, 0x8a, 0x06, 0x39, 0x06, 0x00, 0x20, 0x8a, 0x06, 0x39, 0x07, 0x00, 0x22, 0x8a, 0x06, 0x39, 0x08, 0x00, 0x24, 0x8a, 0x95, 0xaa, 0x3a, 0x38, 0x52, 0x60, 0xbe, 0x58, 0xfb, 0x04, 0x3a, 0x38, 0x52, 0x60, 0x01, 0x68, 0xbe, 0x58, 0xfb, 0x04, 0x3a, 0x38, 0x52, 0x60, 0x02, 0x68, 0xbe, 0x58, 0xfb, 0x04, 0x3a, 0x38, 0x52, 0x60, 0x03, 0x68, 0xbe, 0x58, 0xfb, 0x04, 0x3a, 0x38, 0x52, 0x60, 0x04, 0x68, 0xbe, 0x58, 0xfb, 0x04, 0x3a, 0x38, 0x52, 0x60, 0x06, 0x68, 0xbe, 0x58, 0xfb, 0x04, 0x3a, 0x38, 0x52, 0x60, 0x07, 0x68, 0xbe, 0x58, 0xfb, 0x04, 0x3a, 0x38, 0x52, 0x60, 0x87, 0x20, -0x40, 0x47, 0x08, 0x68, 0xbe, 0x58, 0xfb, 0x04, 0x3a, 0x38, 0x3a, 0x38, 0x5f, 0x70, 0x06, 0x39, 0xa0, 0x00, 0x01, 0x8a, 0x3a, 0x38, 0x60, 0x70, 0x06, 0x39, 0x01, 0x00, 0x04, 0x8a, 0x06, 0x39, 0x00, 0x00, 0x03, 0x8a, 0x3a, 0x38, 0xe8, 0xa8, 0x3a, 0x38, 0xe8, 0xa8, 0x3a, 0x38, 0x5f, 0x70, 0x06, 0x39, 0xb0, 0x00, 0x04, 0x8a, 0x06, 0x39, 0xb1, 0x00, 0x0d, 0x8a, 0x3a, 0x38, 0x60, 0x70, 0x06, 0x39, 0x01, 0x00, 0x04, 0x8a, 0x06, 0x39, 0x00, 0x00, 0x03, 0x8a, 0x3a, 0x38, 0x93, 0xa8, 0x3a, 0x38, 0x93, 0xa8, 0x3a, 0x38, 0x83, 0xaa, 0x8b, 0xaa, 0x60, 0x70, 0x1b, 0x20, 0x15, 0x38, 0x03, 0x00, 0x83, 0xac, 0x03, 0x90, 0x83, 0xaa, 0xc8, 0xa8, 0x3a, 0x38, 0x83, 0xa8, 0xc8, 0xa8, 0x3a, 0x38, 0x5f, 0x71, 0x24, 0x38, 0x0f, 0x00, 0x00, 0x38, 0x8d, 0x2e, 0x09, 0x58, 0x02, 0x39, 0x00, 0x00, 0x61, 0x0b, +0x40, 0x47, 0x08, 0x68, 0xbe, 0x58, 0xfb, 0x04, 0x3a, 0x38, 0x3a, 0x38, 0x5f, 0x70, 0x06, 0x39, 0xa0, 0x00, 0x01, 0x8a, 0x3a, 0x38, 0x60, 0x70, 0x06, 0x39, 0x01, 0x00, 0x04, 0x8a, 0x06, 0x39, 0x00, 0x00, 0x03, 0x8a, 0x3a, 0x38, 0xe8, 0xa8, 0x3a, 0x38, 0xe8, 0xa8, 0x3a, 0x38, 0x5f, 0x70, 0x06, 0x39, 0xb0, 0x00, 0x04, 0x8a, 0x06, 0x39, 0xb1, 0x00, 0x0d, 0x8a, 0x3a, 0x38, 0x60, 0x70, 0x06, 0x39, 0x01, 0x00, 0x04, 0x8a, 0x06, 0x39, 0x00, 0x00, 0x03, 0x8a, 0x3a, 0x38, 0x93, 0xa8, 0x3a, 0x38, 0x93, 0xa8, 0x3a, 0x38, 0x83, 0xaa, 0x8b, 0xaa, 0x60, 0x70, 0x1b, 0x20, 0x15, 0x38, 0x03, 0x00, 0x83, 0xac, 0x03, 0x90, 0x83, 0xaa, 0xc8, 0xa8, 0x3a, 0x38, 0x83, 0xa8, 0xc8, 0xa8, 0x3a, 0x38, 0x5f, 0x71, 0x24, 0x38, 0x0f, 0x00, 0x00, 0x38, 0xa0, 0x2e, 0x09, 0x58, 0x02, 0x39, 0x00, 0x00, 0x74, 0x0b, 0x80, 0x47, 0x05, 0x8a, 0x60, 0x71, 0xfe, 0x59, 0x35, 0x39, 0x61, 0x00, 0x3b, 0x58, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0xa2, 0xa8, 0x06, 0x60, 0x69, 0x78, 0x95, 0x60, 0x6a, 0x78, 0x60, 0x70, 0x6c, 0x78, 0x5f, 0x70, 0x6b, 0x78, 0xfe, 0x58, 0x15, 0x38, 0x60, 0x00, 0x03, 0x59, 0x24, 0x38, 0x00, 0xff, 0xfe, 0x58, 0x6d, 0x78, 0x24, 0x38, 0xff, 0x00, 0x6e, 0x78, 0xf1, 0x60, 0x6f, 0x78, 0xbe, 0xac, 0x0c, 0x90, 0x6b, 0x71, 0x24, 0x39, 0xff, 0x00, 0x18, 0x31, 0x07, 0x88, 0x6c, 0x71, 0x24, 0x39, 0xff, 0x00, 0x26, 0x39, 0x4e, 0x00, 0x01, 0x88, 0x82, 0xa8, 0x3a, 0x38, 0xa2, 0xa8, 0x12, 0x60, 0x69, 0x78, 0x94, 0x60, 0x6a, 0x78, 0x60, 0x70, 0x5f, 0x71, 0xfe, 0x59, 0x01, 0x28, 0x80, 0x61, 0x59, 0x69, 0x01, 0x00, 0x60, 0x71, 0x6c, 0x79, 0x5f, 0x71, 0x6b, 0x79, 0x01, 0x5b, 0xb9, 0x61, 0xc0, 0x47, 0x6d, 0x64, 0xef, 0x38, 0xcb, 0x47, 0x69, 0x59, 0x24, 0x38, 0x00, 0xff, 0xfe, 0x58, 0x1d, 0x5c, 0x24, 0x38, 0xff, 0x00, 0x1d, 0x5c, 0x19, 0x03, 0xf1, 0x60, 0x7b, 0x78, 0x3a, 0x38, 0xa2, 0xa8, 0x11, 0x60, 0x69, 0x78, 0x9b, 0x60, 0x6a, 0x78, 0x10, 0x60, 0x06, 0x58, 0x6b, 0x78, 0x9e, 0x58, 0xba, 0x00, 0xe2, 0xac, 0x01, 0x90, 0x19, 0x00, 0x6c, 0x78, 0x24, 0x60, 0xe2, 0xac, 0x01, 0x90, 0x19, 0x00, 0x6d, 0x78, 0x00, 0x60, 0x6e, 0x78, 0x00, 0x60, 0x6f, 0x78, 0x00, 0x60, 0x70, 0x78, 0x00, 0x60, 0x71, 0x78, 0x00, 0x60, 0x72, 0x78, 0x73, 0x78, 0x74, 0x78, 0x75, 0x78, 0x76, 0x78, 0x77, 0x78, 0x78, 0x78, 0x79, 0x78, 0x7a, 0x78, 0xe2, 0xaa, 0x3a, 0x38, 0x5f, 0x70, 0xfe, 0x58, 0x15, 0x38, 0x60, 0x00, 0x61, 0x71, 0xfe, 0x59, 0x35, 0x39, 0x62, 0x00, 0x3b, 0x58, 0x3a, 0x38, 0xba, 0x43, -0x00, 0x48, 0x98, 0x3f, 0x65, 0x43, 0x00, 0x62, 0xa9, 0x7a, 0xad, 0x72, 0x57, 0x7a, 0xa9, 0x70, 0xa8, 0x71, 0x19, 0x48, 0x28, 0x82, 0x19, 0x11, 0x19, 0x48, 0x03, 0x88, 0xaa, 0x72, 0x46, 0x5a, 0x01, 0x9e, 0x3c, 0x62, 0x1b, 0x02, 0x69, 0x7a, 0x1b, 0x12, 0x4e, 0x5a, 0x6c, 0x7a, 0x98, 0x62, 0x6a, 0x7a, 0xa9, 0x72, 0xbe, 0xac, 0x02, 0x92, 0x45, 0x3a, 0x40, 0x00, 0x6b, 0x7a, 0x81, 0xa8, 0xa2, 0xa8, 0x8b, 0xee, 0xb9, 0xac, 0x17, 0x90, 0xa2, 0xac, 0xfc, 0x93, 0x9d, 0x60, 0x4e, 0x68, 0xef, 0xb0, 0xbe, 0xac, 0x01, 0x92, 0x24, 0xa9, 0xa9, 0x70, 0x19, 0x00, 0xa9, 0x78, 0x57, 0x70, 0x7e, 0x00, 0x57, 0x78, 0xd4, 0x9f, 0x81, 0xaa, 0xa2, 0xaa, 0xbe, 0xac, 0x02, 0x90, 0x3c, 0xa9, 0x01, 0x9e, 0x24, 0xa9, 0x3a, 0x38, 0x81, 0xaa, 0xa2, 0xaa, 0xbe, 0xac, 0x02, 0x90, 0x3c, 0xa9, 0x01, 0x9e, 0x34, 0xbb, -0x40, 0x48, 0x24, 0xa9, 0x3a, 0x38, 0xb2, 0xa8, 0xa2, 0xa8, 0xaa, 0xaa, 0x00, 0x60, 0x5d, 0x78, 0x50, 0xb2, 0x3a, 0xaa, 0xd0, 0xb2, 0xf9, 0xab, 0x5e, 0x70, 0x06, 0x39, 0x83, 0x00, 0x01, 0x8a, 0x8b, 0xee, 0x3e, 0x5f, 0x3e, 0x5e, 0x3e, 0x5d, 0x3e, 0x5c, 0x3e, 0x5b, 0x3e, 0x5a, 0x3e, 0x59, 0x3e, 0x58, 0x80, 0xb8, 0x81, 0xb8, 0x5a, 0x38, 0xe2, 0xa8, 0x66, 0x61, 0xbe, 0x59, 0x27, 0x1d, 0xba, 0xac, 0x98, 0x3c, 0x65, 0x43, 0x81, 0xaa, 0xb9, 0xaa, 0x5f, 0x70, 0xa2, 0x78, 0x60, 0x70, 0xa4, 0x78, 0x61, 0x70, 0xa5, 0x78, 0x62, 0x70, 0x01, 0x59, 0xa6, 0x78, 0x63, 0x70, 0xa7, 0x78, 0x24, 0x39, 0xff, 0x00, 0xfe, 0x59, 0x04, 0x38, 0xff, 0x00, 0x20, 0x28, 0x08, 0x58, 0x01, 0x5b, 0x00, 0x61, 0x1e, 0x62, 0x1c, 0x5a, 0x01, 0x5c, 0x02, 0x40, 0x78, 0x48, 0x06, 0x8a, 0x19, 0x04, 0xa8, 0x7c, 0x0f, 0x01, +0x00, 0x48, 0x98, 0x3f, 0x65, 0x43, 0x00, 0x62, 0xa9, 0x7a, 0xad, 0x72, 0x57, 0x7a, 0xa9, 0x70, 0xa8, 0x71, 0x19, 0x48, 0x28, 0x82, 0x19, 0x11, 0x19, 0x48, 0x03, 0x88, 0xaa, 0x72, 0x46, 0x5a, 0x01, 0x9e, 0x3c, 0x62, 0x1b, 0x02, 0x69, 0x7a, 0x1b, 0x12, 0x4e, 0x5a, 0x6c, 0x7a, 0x98, 0x62, 0x6a, 0x7a, 0xa9, 0x72, 0xbe, 0xac, 0x02, 0x92, 0x45, 0x3a, 0x40, 0x00, 0x6b, 0x7a, 0x81, 0xa8, 0xa2, 0xa8, 0x9e, 0xee, 0xb9, 0xac, 0x17, 0x90, 0xa2, 0xac, 0xfc, 0x93, 0x9d, 0x60, 0x4e, 0x68, 0xef, 0xb0, 0xbe, 0xac, 0x01, 0x92, 0x24, 0xa9, 0xa9, 0x70, 0x19, 0x00, 0xa9, 0x78, 0x57, 0x70, 0x7e, 0x00, 0x57, 0x78, 0xd4, 0x9f, 0x81, 0xaa, 0xa2, 0xaa, 0xbe, 0xac, 0x02, 0x90, 0x3c, 0xa9, 0x01, 0x9e, 0x24, 0xa9, 0x3a, 0x38, 0x81, 0xaa, 0xa2, 0xaa, 0xbe, 0xac, 0x02, 0x90, 0x3c, 0xa9, 0x01, 0x9e, 0x47, 0xbb, +0x40, 0x48, 0x24, 0xa9, 0x3a, 0x38, 0xb2, 0xa8, 0xa2, 0xa8, 0xaa, 0xaa, 0x00, 0x60, 0x5d, 0x78, 0x50, 0xb2, 0x3a, 0xaa, 0xd0, 0xb2, 0xf9, 0xab, 0x5e, 0x70, 0x06, 0x39, 0x83, 0x00, 0x01, 0x8a, 0x9e, 0xee, 0x3e, 0x5f, 0x3e, 0x5e, 0x3e, 0x5d, 0x3e, 0x5c, 0x3e, 0x5b, 0x3e, 0x5a, 0x3e, 0x59, 0x3e, 0x58, 0x80, 0xb8, 0x81, 0xb8, 0x5a, 0x38, 0xe2, 0xa8, 0x66, 0x61, 0xbe, 0x59, 0x27, 0x1d, 0xba, 0xac, 0x98, 0x3c, 0x65, 0x43, 0x81, 0xaa, 0xb9, 0xaa, 0x5f, 0x70, 0xa2, 0x78, 0x60, 0x70, 0xa4, 0x78, 0x61, 0x70, 0xa5, 0x78, 0x62, 0x70, 0x01, 0x59, 0xa6, 0x78, 0x63, 0x70, 0xa7, 0x78, 0x24, 0x39, 0xff, 0x00, 0xfe, 0x59, 0x04, 0x38, 0xff, 0x00, 0x20, 0x28, 0x08, 0x58, 0x01, 0x5b, 0x00, 0x61, 0x1e, 0x62, 0x1c, 0x5a, 0x01, 0x5c, 0x02, 0x40, 0x78, 0x48, 0x06, 0x8a, 0x19, 0x04, 0xa8, 0x7c, 0x22, 0x01, 0x80, 0x48, 0xa3, 0x7c, 0x60, 0x13, 0xaa, 0x7b, 0x04, 0x9e, 0xa8, 0x7c, 0xa3, 0x7c, 0x1e, 0x63, 0xaa, 0x7b, 0x60, 0x71, 0x24, 0x39, 0xff, 0x00, 0xfe, 0x59, 0x61, 0x70, 0x04, 0x38, 0xff, 0x00, 0x20, 0x28, 0xab, 0x78, 0xa2, 0x70, 0x04, 0x38, 0xc0, 0x00, 0xbf, 0x38, 0x08, 0x58, 0x00, 0x61, 0x20, 0x31, 0x01, 0x8a, 0x2a, 0x9e, 0xa2, 0x70, 0x04, 0x39, 0x07, 0x00, 0x20, 0x3a, 0xa1, 0x48, 0x49, 0x5b, 0x5e, 0x5b, 0xa9, 0x48, 0xa6, 0x48, 0xa9, 0x48, 0xb0, 0x48, 0xb0, 0x48, 0x60, 0x63, 0x11, 0x6b, 0x0d, 0x9e, 0x00, 0x63, 0x05, 0x6b, 0x08, 0xac, 0x09, 0x90, 0x30, 0x63, 0x0b, 0x6b, 0x06, 0x9e, 0x9e, 0x5b, 0xe8, 0x00, 0x10, 0xac, 0x02, 0x90, 0x48, 0x63, 0x0e, 0x6b, 0x1e, 0x59, 0x1e, 0x58, 0x9e, 0x59, 0x27, 0x1d, 0x26, 0x38, 0x66, 0x00, 0x02, 0x88, 0x60, 0x63, 0x11, 0x6b, 0x3e, 0x58, 0xda, 0xb5, 0xc0, 0x48, 0x3e, 0x59, 0xad, 0x7b, 0xf7, 0xa8, 0xb9, 0xa8, 0x3a, 0x38, 0x9e, 0x58, 0xc6, 0x04, 0x18, 0x10, 0x2f, 0x8a, 0xff, 0x60, 0xff, 0x68, 0x8c, 0x61, 0x04, 0x69, 0x14, 0x62, 0x19, 0x12, 0x57, 0x38, 0x1d, 0x59, 0x00, 0x60, 0xbe, 0x58, 0xa0, 0x04, 0xbe, 0x58, 0xa1, 0x04, 0x19, 0x38, 0xf9, 0x48, 0x18, 0x60, 0x58, 0x48, 0x1d, 0x9c, 0x60, 0x38, 0x06, 0x16, 0x03, 0x59, 0x24, 0x3a, 0xff, 0x00, 0x4d, 0x38, 0x00, 0x71, 0x01, 0x60, 0xbe, 0x58, 0xa0, 0x04, 0xbe, 0x58, 0xa1, 0x04, 0x00, 0x39, 0x8c, 0x04, 0x7b, 0x59, 0x19, 0x38, 0x18, 0x49, 0x9e, 0x58, 0xa0, 0x04, 0x19, 0x00, 0xbe, 0x58, 0xa0, 0x04, 0x00, 0x39, 0x8c, 0x04, 0x23, 0x5b, 0xff, 0x62, 0xff, 0x6a, 0x59, 0x49, 0xf2, 0x89, 0x3a, 0x38, 0x00, 0x67, 0x9e, 0x58, 0xc6, 0x04, 0x00, 0x62, 0x00, 0x63, 0x23, 0x74, 0xe0, 0x39, 0xe8, 0x3c, 0x00, 0x49, 0xaa, 0x15, 0x23, 0x5e, 0xc4, 0x3e, 0xff, 0x00, 0x9e, 0x48, 0x04, 0x98, 0x5e, 0x48, 0x02, 0x94, 0xc1, 0x5a, 0xe1, 0x5b, 0x19, 0x07, 0xf8, 0x48, 0xf2, 0x97, 0xbe, 0x5a, 0xbc, 0x04, 0x00, 0x60, 0x9e, 0x59, 0xad, 0x04, 0x59, 0x48, 0x01, 0x9a, 0x01, 0x60, 0xbe, 0x58, 0xb2, 0x04, 0x3a, 0x38, 0x61, 0x5e, 0x00, 0x67, 0x19, 0x38, 0x44, 0x49, 0xe0, 0x39, 0xaa, 0x15, 0x23, 0x74, 0x99, 0x49, 0x1d, 0x98, 0xfe, 0x48, 0x1b, 0x8a, 0xe0, 0x38, 0x06, 0x16, 0x03, 0x59, 0x24, 0x39, 0x00, 0xff, 0x22, 0x39, 0x00, 0x71, 0x13, 0x8a, 0x19, 0x38, 0x5a, 0x49, 0x18, 0x10, 0x0f, 0x8a, 0xe0, 0x38, 0x06, 0x16, 0x03, 0x59, 0x24, 0x3a, 0xff, 0x00, 0x4d, 0x38, 0x00, 0x71, 0x9e, 0x58, 0xa1, 0x04, 0x19, 0x00, 0xbe, 0x58, 0xa1, 0x04, 0x00, 0x39, 0x8c, 0x04, 0xfb, 0x59, 0x19, 0x07, 0x9e, 0x58, 0x65, 0x7b, @@ -330,7 +330,7 @@ 0x40, 0x54, 0xbe, 0x58, 0x07, 0xf8, 0x5b, 0x38, 0x3e, 0x5b, 0x3a, 0x38, 0x3b, 0x61, 0xf8, 0x69, 0x81, 0x5a, 0xff, 0x38, 0x86, 0x5c, 0x44, 0x2a, 0x6f, 0x39, 0x4e, 0x54, 0x5b, 0x59, 0x19, 0x01, 0x3a, 0x38, 0x9d, 0x60, 0x4e, 0x68, 0xef, 0xb0, 0x9e, 0x58, 0x00, 0xf8, 0x10, 0xa8, 0xbe, 0x58, 0x00, 0xf8, 0x19, 0x38, 0x64, 0x54, 0x1a, 0x38, 0x1a, 0x38, 0x9e, 0x5e, 0xb2, 0x00, 0x1e, 0xac, 0xfa, 0x91, 0x00, 0x66, 0xbe, 0x5e, 0xb2, 0x00, 0x3a, 0x38, 0x94, 0xab, 0x26, 0x66, 0x04, 0x6e, 0xef, 0x3a, 0x6a, 0x54, 0xdd, 0x5e, 0x1a, 0x38, 0x94, 0xa9, 0x3a, 0x38, 0x30, 0x65, 0xa4, 0x15, 0x18, 0x61, 0x25, 0x40, 0x00, 0x3d, 0x18, 0x08, 0x26, 0x66, 0x04, 0x6e, 0x42, 0x38, 0x10, 0x00, 0x05, 0x88, 0xef, 0x3a, 0x7b, 0x54, 0xc5, 0x58, 0x1d, 0x5d, 0x3a, 0x38, 0xef, 0x3a, 0x82, 0x54, 0xc5, 0x58, 0x0b, 0xb5, 0x80, 0x54, 0xa3, 0x59, 0x20, 0x00, 0x1d, 0x5d, 0x3a, 0x38, 0x9e, 0x58, 0x04, 0xf8, 0x9e, 0x5a, 0x05, 0xf8, 0x9e, 0x5c, 0x00, 0xf8, 0x02, 0x00, 0x24, 0xac, 0x01, 0x90, 0x06, 0x58, 0x55, 0x61, 0x01, 0x40, 0x64, 0x62, 0x1c, 0x5a, 0xbe, 0x58, 0x08, 0x00, 0x3a, 0x38, 0x1e, 0x5b, 0x18, 0x61, 0x21, 0x5c, 0x00, 0x66, 0x0b, 0x7e, 0xc0, 0x3d, 0x18, 0x08, 0x30, 0x67, 0x00, 0x73, 0xff, 0x61, 0x7f, 0x69, 0xa3, 0x5a, 0x6f, 0x38, 0xa4, 0x54, 0x48, 0x5a, 0x1a, 0x38, 0x52, 0x3a, 0x08, 0x00, 0x04, 0x5a, 0x59, 0x48, 0x02, 0x98, 0x41, 0x59, 0xe1, 0x5b, 0xa4, 0x05, 0x19, 0x17, 0x10, 0x60, 0xf8, 0x48, 0xef, 0x95, 0x9e, 0x58, 0xb1, 0x00, 0x0c, 0x61, 0x01, 0x40, 0x00, 0x3a, 0x00, 0x05, 0x0a, 0x7a, 0x02, 0x62, 0x00, 0x61, 0xc1, 0x58, 0x1c, 0x5a, 0x0a, 0x72, 0x02, 0x02, 0x0b, 0x70, 0x00, 0xab, 0x6b, 0x5e, 0xc0, 0x54, 0x06, 0x39, 0x00, 0x00, 0x04, 0x8a, 0x06, 0x39, 0x01, 0x00, 0x06, 0x8a, 0x0d, 0x9e, 0x7b, 0x5a, 0x0b, 0x71, 0x19, 0x01, 0x0b, 0x79, 0x08, 0x9e, 0x43, 0x58, 0x10, 0x58, 0x60, 0x83, 0x03, 0x28, 0x1b, 0x5a, 0x00, 0x61, 0x0b, 0x79, 0x00, 0x9e, 0x19, 0x06, 0xdc, 0x48, 0xc3, 0x89, 0x3e, 0x5b, 0x3a, 0x38, 0xa5, 0xac, 0x0a, 0x90, 0x00, 0x61, 0x05, 0x69, 0xff, 0x60, 0x01, 0x68, 0x07, 0x38, 0xe4, 0x54, 0x9e, 0x58, 0xf9, 0x04, 0x1b, 0x59, 0x19, 0x01, 0x00, 0x60, 0xac, 0xb0, 0xfa, 0x61, 0x5f, 0x69, 0x29, 0x58, 0x02, 0x38, 0xff, 0xff, 0x02, 0x8a, 0xf5, 0xac, 0x47, 0x90, 0x40, 0x66, 0x9e, 0x5f, 0xbc, 0x00, 0x0c, 0x61, 0x9e, 0x58, 0xbd, 0x00, 0x01, 0x40, 0x07, 0x40, 0x00, 0x61, 0x05, 0x69, 0x20, 0x01, 0xff, 0x62, 0x01, 0x6a, 0x40, 0x12, 0xff, 0x60, 0xff, 0x68, 0x57, 0x38, 0x3c, 0xec, -0x00, 0x55, 0x1d, 0x59, 0x00, 0x67, 0xe6, 0x40, 0x00, 0x3d, 0x80, 0x57, 0x00, 0x3c, 0x00, 0x05, 0x00, 0x3b, 0x18, 0x08, 0xe2, 0x38, 0x08, 0x00, 0x01, 0x96, 0x3d, 0x94, 0xa1, 0x58, 0x81, 0x59, 0x5e, 0xeb, 0xa1, 0x58, 0x61, 0x59, 0x6b, 0xeb, 0x61, 0x58, 0x81, 0x59, 0x70, 0xeb, 0x18, 0x12, 0xf5, 0x8b, 0x19, 0x07, 0xe8, 0x9f, 0x00, 0x60, 0xac, 0xb0, 0xfa, 0x61, 0x5f, 0x69, 0x29, 0x58, 0x02, 0x38, 0xff, 0xff, 0x03, 0x8a, 0xf5, 0xac, 0x12, 0x90, 0x00, 0x60, 0x00, 0x3d, 0x40, 0x57, 0x00, 0x3c, 0xe0, 0x1a, 0x00, 0x3b, 0x18, 0x08, 0xa1, 0x58, 0x81, 0x59, 0x5e, 0xeb, 0xa1, 0x58, 0x61, 0x59, 0x6b, 0xeb, 0x61, 0x58, 0x81, 0x59, 0x70, 0xeb, 0x18, 0x12, 0xf5, 0x8b, 0x00, 0x63, 0xbe, 0x5b, 0x0b, 0x00, 0x0b, 0x61, 0x78, 0xab, 0x5a, 0x62, 0xe1, 0x6a, 0xac, 0xb2, 0xfa, 0x60, 0x5f, 0x68, 0x59, 0x3b, +0x00, 0x55, 0x1d, 0x59, 0x00, 0x67, 0xe6, 0x40, 0x00, 0x3d, 0x80, 0x57, 0x00, 0x3c, 0x00, 0x05, 0x00, 0x3b, 0x18, 0x08, 0xe2, 0x38, 0x08, 0x00, 0x01, 0x96, 0x3d, 0x94, 0xa1, 0x58, 0x81, 0x59, 0x80, 0xeb, 0xa1, 0x58, 0x61, 0x59, 0x8d, 0xeb, 0x61, 0x58, 0x81, 0x59, 0x92, 0xeb, 0x18, 0x12, 0xf5, 0x8b, 0x19, 0x07, 0xe8, 0x9f, 0x00, 0x60, 0xac, 0xb0, 0xfa, 0x61, 0x5f, 0x69, 0x29, 0x58, 0x02, 0x38, 0xff, 0xff, 0x03, 0x8a, 0xf5, 0xac, 0x12, 0x90, 0x00, 0x60, 0x00, 0x3d, 0x40, 0x57, 0x00, 0x3c, 0xe0, 0x1a, 0x00, 0x3b, 0x18, 0x08, 0xa1, 0x58, 0x81, 0x59, 0x80, 0xeb, 0xa1, 0x58, 0x61, 0x59, 0x8d, 0xeb, 0x61, 0x58, 0x81, 0x59, 0x92, 0xeb, 0x18, 0x12, 0xf5, 0x8b, 0x00, 0x63, 0xbe, 0x5b, 0x0b, 0x00, 0x0b, 0x61, 0x78, 0xab, 0x5a, 0x62, 0xe1, 0x6a, 0xac, 0xb2, 0xfa, 0x60, 0x5f, 0x68, 0x25, 0x3c, 0x40, 0x55, 0x00, 0x62, 0x57, 0x38, 0x7a, 0x38, 0x19, 0x10, 0x19, 0x11, 0xac, 0xb2, 0x09, 0x5a, 0x5b, 0x48, 0xf2, 0x89, 0x78, 0xa9, 0x1a, 0x38, 0x3a, 0x38, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdd, 0x41, 0x80, 0x55, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x40, 0x55, 0xc0, 0x55, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x55, @@ -363,6 +363,6 @@ 0x00, 0x5f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x5e, 0x40, 0x5f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x5f, 0x80, 0x5f, 0xff, 0xff, 0x00, 0x80, 0x55, 0x55, 0x00, 0x40, 0x33, 0x33, 0xaa, 0x2a, 0x92, 0x24, 0x00, 0x20, 0x71, 0x1c, 0x99, 0x19, 0x45, 0x17, 0x55, 0x15, 0xb1, 0x13, 0x49, 0x12, 0x11, 0x11, 0x00, 0x10, 0x0f, 0x0f, 0x38, 0x0e, 0x79, 0x0d, 0xcc, 0x0c, 0x30, 0x0c, 0xa2, 0x0b, 0x21, 0x0b, 0xaa, 0x0a, 0x3d, 0x0a, 0xd8, 0x09, 0x7b, 0x09, 0x24, 0x09, 0xd3, 0x08, 0x88, 0x08, 0x42, 0x08, 0x00, 0x08, 0xc1, 0x07, 0x87, 0x07, 0x50, 0x07, 0x1c, 0x07, 0xeb, 0x06, 0xbc, 0x06, 0x90, 0x06, 0x66, 0x06, 0x3e, 0x06, 0x18, 0x06, 0xf4, 0x05, 0xd1, 0x05, 0xb0, 0x05, 0x90, 0x05, 0x72, 0x05, 0x55, 0x05, 0x39, 0x05, 0x1e, 0x05, 0x05, 0x05, 0xec, 0x04, 0xd4, 0x04, 0xbd, 0x04, 0xa7, 0x04, 0x92, 0x04, 0x7d, 0x04, 0x69, 0x04, 0x56, 0x04, 0x44, 0x04, 0x32, 0x04, 0x21, 0x04, 0x10, 0x04, 0x00, 0x04, 0xd4, 0x1d, -0xc0, 0x5f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x88, 0x00, 0xff, 0xff, 0x00, 0x00, 0x42, 0xa0, 0x29, 0x30, 0xaa, 0x55, 0xcc, 0x33, 0xff, 0xff, 0xef, 0xb9, +0xc0, 0x5f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x88, 0x00, 0xff, 0xff, 0x00, 0x00, 0x44, 0xa0, 0x29, 0x30, 0xaa, 0x55, 0xcc, 0x33, 0xff, 0xff, 0xf1, 0xb9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index ef69d91516d..88e44ddf525 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -120,6 +120,7 @@ EXPORT_SYMBOL_GPL(iommu_present); * iommu_set_fault_handler() - set a fault handler for an iommu domain * @domain: iommu domain * @handler: fault handler + * @token: user data, will be passed back to the fault handler * * This function should be used by IOMMU users which want to be notified * whenever an IOMMU fault happens. @@ -128,11 +129,13 @@ EXPORT_SYMBOL_GPL(iommu_present); * error code otherwise. */ void iommu_set_fault_handler(struct iommu_domain *domain, - iommu_fault_handler_t handler) + iommu_fault_handler_t handler, + void *token) { BUG_ON(!domain); domain->handler = handler; + domain->handler_token = token; } EXPORT_SYMBOL_GPL(iommu_set_fault_handler); diff --git a/drivers/media/platform/msm/camera_v2/sensor/mi1040.c b/drivers/media/platform/msm/camera_v2/sensor/mi1040.c old mode 100644 new mode 100755 index 806c650dd71..9e357ee8890 --- a/drivers/media/platform/msm/camera_v2/sensor/mi1040.c +++ b/drivers/media/platform/msm/camera_v2/sensor/mi1040.c @@ -779,6 +779,7 @@ int32_t mi1040_sensor_set_fps(struct msm_sensor_ctrl_t *s_ctrl, int fps) CDBG("--CAMERA--CAMERA_FPS_FIX_15\n"); rc = sensor_write_table(s_ctrl, Fix_15_fps, ARRAY_SIZE(Fix_15_fps)); + break; case CAMERA_FPS_AUTO_30: CDBG("--CAMERA--ERROR CAMERA_FPS_AUTO_30\n"); rc = sensor_write_table(s_ctrl, auto_30_fps, diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c index 1efad20fb17..1287645b984 100644 --- a/drivers/mfd/ab3100-core.c +++ b/drivers/mfd/ab3100-core.c @@ -409,8 +409,6 @@ static irqreturn_t ab3100_irq_handler(int irq, void *data) u32 fatevent; int err; - add_interrupt_randomness(irq); - err = ab3100_get_register_page_interruptible(ab3100, AB3100_EVENTA1, event_regs, 3); if (err) @@ -933,9 +931,6 @@ static int __devinit ab3100_probe(struct i2c_client *client, err = request_threaded_irq(client->irq, NULL, ab3100_irq_handler, IRQF_ONESHOT, "ab3100-core", ab3100); - /* This real unpredictable IRQ is of course sampled for entropy */ - rand_initialize_irq(client->irq); - if (err) goto exit_no_irq; diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c index 83453cfaa54..65d43f244b5 100644 --- a/drivers/misc/qseecom.c +++ b/drivers/misc/qseecom.c @@ -551,6 +551,8 @@ static int __qseecom_process_incomplete_cmd(struct qseecom_dev_handle *data, unsigned long flags; struct qseecom_client_listener_data_irsp send_data_rsp; struct qseecom_registered_listener_list *ptr_svc = NULL; + sigset_t new_sigset; + sigset_t old_sigset; while (resp->result == QSEOS_RESULT_INCOMPLETE) { @@ -576,17 +578,28 @@ static int __qseecom_process_incomplete_cmd(struct qseecom_dev_handle *data, } pr_debug("waking up rcv_req_wq and " "waiting for send_resp_wq\n"); - if (wait_event_freezable(qseecom.send_resp_wq, - __qseecom_listener_has_sent_rsp(data))) { - pr_warning("Interrupted: exiting send_cmd loop\n"); - return -ERESTARTSYS; - } + /* initialize the new signal mask with all signals*/ + sigfillset(&new_sigset); + /* block all signals */ + sigprocmask(SIG_SETMASK, &new_sigset, &old_sigset); + + do { + if (!wait_event_freezable(qseecom.send_resp_wq, + __qseecom_listener_has_sent_rsp(data))) + break; + } while (1); + + /* restore signal mask */ + sigprocmask(SIG_SETMASK, &old_sigset, NULL); if (data->abort) { - pr_err("Aborting listener service %d\n", - data->listener.id); + pr_err("Abort clnt %d waiting on lstnr svc %d, ret %d", + data->client.app_id, lstnr, ret); return -ENODEV; + } + + qseecom.send_resp_flag = 0; send_data_rsp.qsee_cmd_id = QSEOS_LISTENER_DATA_RSP_COMMAND; send_data_rsp.listener_id = lstnr ; diff --git a/drivers/misc/slimport_anx7808/slimport_tx_drv.c b/drivers/misc/slimport_anx7808/slimport_tx_drv.c index 06cac2b7d5f..14879094b8b 100644 --- a/drivers/misc/slimport_anx7808/slimport_tx_drv.c +++ b/drivers/misc/slimport_anx7808/slimport_tx_drv.c @@ -1187,7 +1187,6 @@ static void sp_tx_enable_audio_output(unchar benable) sp_read_reg(TX_P0, SP_TX_AUD_CTRL, &c); if (benable) { - sp_read_reg(TX_P0, SP_TX_AUD_CTRL, &c); if (c&AUD_EN) { c &= ~AUD_EN; sp_write_reg(TX_P0, SP_TX_AUD_CTRL, c); @@ -2307,7 +2306,7 @@ void sp_tx_edid_read(void) bedid_break = 0; sp_tx_addronly_set(1); sp_write_reg(TX_P0, SP_TX_AUX_CTRL_REG, 0x04); - sp_write_reg(TX_P0, SP_TX_AUX_CTRL_REG2, 0x01); + sp_write_reg(TX_P0, SP_TX_AUX_CTRL_REG2, 0x03); sp_tx_wait_aux_finished(); edid_block = sp_tx_get_edid_block(); @@ -3189,7 +3188,7 @@ static void hdmi_rx_restart_audio_chk(void) SP_DEV_DBG("WAIT_AUDIO: hdmi_rx_restart_audio_chk.\n"); g_cts_got = 0; g_audio_got = 0; - if (hdmi_system_state == HDMI_AUDIO_CONFIG) + if (hdmi_system_state > HDMI_AUDIO_CONFIG) hdmi_rx_set_sys_state(HDMI_AUDIO_CONFIG); } @@ -3670,7 +3669,7 @@ static void hdmi_rx_hdmi_dvi_int(void) SP_DEV_NOTICE("hdmi_rx_hdmi_dvi_int: HDMI MODE."); if (hdmi_system_state == HDMI_PLAYBACK) - hdmi_rx_set_sys_state(HDMI_AUDIO_CONFIG); + hdmi_rx_restart_audio_chk(); } else { hdmi_rx_unmute_audio(); } diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 27a127c9e8d..15bebc861ac 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -796,7 +796,7 @@ static int mmc_blk_cmd_error(struct request *req, const char *name, int error, * Otherwise we don't understand what happened, so abort. */ static int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req, - struct mmc_blk_request *brq, int *ecc_err) + struct mmc_blk_request *brq, int *ecc_err, int *gen_err) { bool prev_cmd_status_valid = true; u32 status, stop_status = 0; @@ -834,6 +834,16 @@ static int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req, (brq->cmd.resp[0] & R1_CARD_ECC_FAILED)) *ecc_err = 1; + /* Flag General errors */ + if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ) + if ((status & R1_ERROR) || + (brq->stop.resp[0] & R1_ERROR)) { + pr_err("%s: %s: general error sending stop or status command, stop cmd response %#x, card status %#x\n", + req->rq_disk->disk_name, __func__, + brq->stop.resp[0], status); + *gen_err = 1; + } + /* * Check the current card state. If it is in some data transfer * mode, tell it to stop (and hopefully transition back to TRAN.) @@ -853,6 +863,13 @@ static int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req, return ERR_ABORT; if (stop_status & R1_CARD_ECC_FAILED) *ecc_err = 1; + if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ) + if (stop_status & R1_ERROR) { + pr_err("%s: %s: general error sending stop command, stop cmd response %#x\n", + req->rq_disk->disk_name, __func__, + stop_status); + *gen_err = 1; + } } /* Check for set block count errors */ @@ -1123,7 +1140,7 @@ static int mmc_blk_err_check(struct mmc_card *card, mmc_active); struct mmc_blk_request *brq = &mq_mrq->brq; struct request *req = mq_mrq->req; - int ecc_err = 0; + int ecc_err = 0, gen_err = 0; /* * sbc.error indicates a problem with the set block count @@ -1137,7 +1154,7 @@ static int mmc_blk_err_check(struct mmc_card *card, */ if (brq->sbc.error || brq->cmd.error || brq->stop.error || brq->data.error) { - switch (mmc_blk_cmd_recovery(card, req, brq, &ecc_err)) { + switch (mmc_blk_cmd_recovery(card, req, brq, &ecc_err, &gen_err)) { case ERR_RETRY: return MMC_BLK_RETRY; case ERR_ABORT: @@ -1167,6 +1184,15 @@ static int mmc_blk_err_check(struct mmc_card *card, */ if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ) { u32 status; + + /* Check stop command response */ + if (brq->stop.resp[0] & R1_ERROR) { + pr_err("%s: %s: general error sending stop command, stop cmd response %#x\n", + req->rq_disk->disk_name, __func__, + brq->stop.resp[0]); + gen_err = 1; + } + do { int err = get_card_status(card, &status, 5); if (err) { @@ -1174,6 +1200,14 @@ static int mmc_blk_err_check(struct mmc_card *card, req->rq_disk->disk_name, err); return MMC_BLK_CMD_ERR; } + + if (status & R1_ERROR) { + pr_err("%s: %s: general error sending status command, card status %#x\n", + req->rq_disk->disk_name, __func__, + status); + gen_err = 1; + } + /* * Some cards mishandle the status bits, * so make sure to check both the busy @@ -1183,6 +1217,13 @@ static int mmc_blk_err_check(struct mmc_card *card, (R1_CURRENT_STATE(status) == R1_STATE_PRG)); } + /* if general error occurs, retry the write operation. */ + if (gen_err) { + pr_warn("%s: retrying write for general error\n", + req->rq_disk->disk_name); + return MMC_BLK_RETRY; + } + if (brq->data.error) { pr_err("%s: error %d transferring data, sector %u, nr %u, cmd response %#x, card status %#x\n", req->rq_disk->disk_name, brq->data.error, diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c index 65984011ab9..e5d5b4b282f 100644 --- a/drivers/net/wireless/wcnss/wcnss_wlan.c +++ b/drivers/net/wireless/wcnss/wcnss_wlan.c @@ -548,6 +548,19 @@ static int enable_wcnss_suspend_notify_set(const char *val, module_param_call(enable_wcnss_suspend_notify, enable_wcnss_suspend_notify_set, param_get_int, &enable_wcnss_suspend_notify, S_IRUGO | S_IWUSR); +int wcnss_wlan_iris_xo_mode(void) +{ + if (!penv || !penv->pdev || !penv->smd_channel_ready) + return -ENODEV; + + if (penv->wlan_config.use_48mhz_xo) + return WCNSS_XO_48MHZ; + else + return WCNSS_XO_19MHZ; +} +EXPORT_SYMBOL(wcnss_wlan_iris_xo_mode); + + static void wcnss_suspend_notify(void) { void __iomem *pmu_spare_reg; diff --git a/drivers/power/bq27541_battery.c b/drivers/power/bq27541_battery.c index e8a216bd43d..5ddb20cb705 100644 --- a/drivers/power/bq27541_battery.c +++ b/drivers/power/bq27541_battery.c @@ -86,6 +86,7 @@ static int bq27541_get_property(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val); extern unsigned get_usb_cable_status(void); extern int smb345_config_thermal_charging(int temp, int volt, int rule); +extern void reconfig_AICL(void); module_param(battery_current, uint, 0644); module_param(battery_remaining_capacity, uint, 0644); @@ -387,6 +388,7 @@ static void battery_status_poll(struct work_struct *work) if(!bq27541_battery_driver_ready) BAT_NOTICE("battery driver not ready\n"); + reconfig_AICL(); power_supply_changed(&bq27541_supply[Charger_Type_Battery]); if (!bq27541_device->temp_err) { @@ -621,10 +623,14 @@ static int bq27541_get_capacity(union power_supply_propval *val) bool check_cap = false; int smb_retry_max = (SMBUS_RETRY + 2); + bq27541_device->bat_capacity = 0; do { bq27541_device->smbus_status = bq27541_smbus_read_data(REG_CAPACITY, 0 ,&bq27541_device->bat_capacity); - if ((bq27541_device->bat_capacity <= 0) || (bq27541_device->bat_capacity > 100)) + if ((bq27541_device->bat_capacity <= 0) || (bq27541_device->bat_capacity > 100)) { check_cap = true; + BAT_NOTICE("check capacity, cap = %d, smb_retry = %d\n", bq27541_device->bat_capacity, smb_retry); + } else + check_cap = false; } while(((bq27541_device->smbus_status < 0) || check_cap) && ( ++smb_retry <= smb_retry_max)); if (bq27541_device->smbus_status < 0) { @@ -641,9 +647,14 @@ static int bq27541_get_capacity(union power_supply_propval *val) } } - ret = bq27541_device->bat_capacity; + temp_capacity = ret = bq27541_device->bat_capacity; - temp_capacity = ((ret >= 100) ? 100 : ret); + if (!(bq27541_device->bat_capacity >= bq27541_data[REG_CAPACITY].min_value && + bq27541_device->bat_capacity <= bq27541_data[REG_CAPACITY].max_value)) { + val->intval = bq27541_device->old_capacity; + BAT_NOTICE("use old capacity=%u\n", bq27541_device->old_capacity); + return 0; + } /* start: for mapping %99 to 100%. Lose 84%*/ if(temp_capacity==99) diff --git a/drivers/power/pm8921-bms.c b/drivers/power/pm8921-bms.c index d1b0ba0fee8..d25306edf0f 100644 --- a/drivers/power/pm8921-bms.c +++ b/drivers/power/pm8921-bms.c @@ -1223,6 +1223,22 @@ static void calculate_cc_uah(struct pm8921_bms_chip *chip, int cc, int *val) *val = cc_uah; } +int pm8921_bms_cc_uah(int *cc_uah) +{ + int cc; + + *cc_uah = 0; + + if (!the_chip) + return -EINVAL; + + read_cc(the_chip, &cc); + calculate_cc_uah(the_chip, cc, cc_uah); + + return 0; +} +EXPORT_SYMBOL(pm8921_bms_cc_uah); + static int calculate_termination_uuc(struct pm8921_bms_chip *chip, int batt_temp, int chargecycles, int fcc_uah, int i_ma, diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c index 16142861142..d550bacafff 100644 --- a/drivers/power/pm8921-charger.c +++ b/drivers/power/pm8921-charger.c @@ -1401,6 +1401,7 @@ static enum power_supply_property msm_batt_power_props[] = { POWER_SUPPLY_PROP_CURRENT_NOW, POWER_SUPPLY_PROP_TEMP, POWER_SUPPLY_PROP_ENERGY_FULL, + POWER_SUPPLY_PROP_CHARGE_NOW, }; static int get_prop_battery_uvolts(struct pm8921_chg_chip *chip) @@ -1486,6 +1487,20 @@ static int get_prop_batt_fcc(struct pm8921_chg_chip *chip) return rc; } +static int get_prop_batt_charge_now(struct pm8921_chg_chip *chip) +{ + int rc; + int cc_uah; + + rc = pm8921_bms_cc_uah(&cc_uah); + + if (rc == 0) + return cc_uah; + + pr_err("unable to get batt fcc rc = %d\n", rc); + return rc; +} + static int get_prop_batt_health(struct pm8921_chg_chip *chip) { int temp; @@ -1643,6 +1658,9 @@ static int pm_batt_power_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_ENERGY_FULL: val->intval = get_prop_batt_fcc(chip) * 1000; break; + case POWER_SUPPLY_PROP_CHARGE_NOW: + val->intval = get_prop_batt_charge_now(chip); + break; default: return -EINVAL; } diff --git a/drivers/power/smb345-charger.c b/drivers/power/smb345-charger.c index 1f193052533..d4bb9cdd460 100644 --- a/drivers/power/smb345-charger.c +++ b/drivers/power/smb345-charger.c @@ -104,8 +104,8 @@ #define WPC_INIT_DET_INTERVAL (22 * HZ) #define WPC_SET_CURT_LIMIT_CNT 6 #define BAT_Cold_Limit 0 -#define BAT_Hot_Limit 55 -#define BAT_Mid_Temp_Wired 50 +#define BAT_Hot_Limit 45 +#define BAT_Mid_Temp_Wired 45 #define BAT_Mid_Temp_Wireless 40 #define FLOAT_VOLT 0x2A #define FLOAT_VOLT_LOW 0x1E @@ -460,17 +460,7 @@ smb345_set_InputCurrentlimit(struct i2c_client *client, u32 current_setting) static irqreturn_t smb345_inok_isr(int irq, void *dev_id) { - struct smb345_charger *smb = dev_id; - int status = gpio_get_value(GPIO_AC_OK); - - SMB_NOTICE("VBUS_DET = %s\n", status ? "H" : "L"); - - if (ac_on && !status) - queue_delayed_work(smb345_wq, &smb->cable_det_work, 0); - else { - if (delayed_work_pending(&charger->cable_det_work)) - cancel_delayed_work(&charger->cable_det_work); - } + SMB_NOTICE("VBUS_DET = %s\n", gpio_get_value(GPIO_AC_OK) ? "H" : "L"); return IRQ_HANDLED; } @@ -661,13 +651,10 @@ static void wireless_set_current_function(struct work_struct *dat) queue_delayed_work(smb345_wq, &charger->wireless_set_current_work, WPC_SET_CURT_INTERVAL); } -static void cable_det_work_function(struct work_struct *dat) +void reconfig_AICL(void) { struct i2c_client *client = charger->client; - if (delayed_work_pending(&charger->cable_det_work)) - cancel_delayed_work(&charger->cable_det_work); - if (ac_on && !gpio_get_value(GPIO_AC_OK)) { int retval; retval = smb345_read(client, smb345_STS_REG_E); @@ -675,7 +662,7 @@ static void cable_det_work_function(struct work_struct *dat) dev_err(&client->dev, "%s(): Failed in reading 0x%02x", __func__, smb345_STS_REG_E); else { - SMB_NOTICE("Status Reg E=0x02%x\n", retval); + SMB_NOTICE("Status Reg E=0x%02x\n", retval); if ((retval & 0xF) <= 0x1) { SMB_NOTICE("reconfig input current limit\n"); @@ -684,6 +671,7 @@ static void cable_det_work_function(struct work_struct *dat) } } } +EXPORT_SYMBOL(reconfig_AICL); static int smb345_inok_irq(struct smb345_charger *smb) { @@ -1150,6 +1138,7 @@ int smb345_config_thermal_charging(int temp, int volt, int rule) else if (rule == THERMAL_RULE2) BAT_Mid_Temp = BAT_Mid_Temp_Wireless; + mdelay(100); smb345_config_thermal_limit(); SMB_NOTICE("temp=%d, volt=%d\n", temp, volt); @@ -1285,8 +1274,6 @@ static int __devinit smb345_probe(struct i2c_client *client, wireless_det_work_function); INIT_DELAYED_WORK_DEFERRABLE(&charger->wireless_set_current_work, wireless_set_current_function); - INIT_DELAYED_WORK_DEFERRABLE(&charger->cable_det_work, - cable_det_work_function); wake_lock_init(&charger_wakelock, WAKE_LOCK_SUSPEND, "charger_configuration"); diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index e756a0df366..289293a5cbb 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c @@ -78,7 +78,7 @@ typedef int (*rproc_handle_resource_t)(struct rproc *rproc, void *, int avail); * the recovery of the remote processor. */ static int rproc_iommu_fault(struct iommu_domain *domain, struct device *dev, - unsigned long iova, int flags) + unsigned long iova, int flags, void *token) { dev_err(dev, "iommu fault: da 0x%lx flags 0x%x\n", iova, flags); @@ -117,7 +117,7 @@ static int rproc_enable_iommu(struct rproc *rproc) return -ENOMEM; } - iommu_set_fault_handler(domain, rproc_iommu_fault); + iommu_set_fault_handler(domain, rproc_iommu_fault, rproc); ret = iommu_attach_device(domain, dev); if (ret) { diff --git a/drivers/staging/prima/Android.mk b/drivers/staging/prima/Android.mk index beefec4efd0..e046954a2eb 100644 --- a/drivers/staging/prima/Android.mk +++ b/drivers/staging/prima/Android.mk @@ -80,10 +80,14 @@ KBUILD_OPTIONS += MODNAME=wlan KBUILD_OPTIONS += BOARD_PLATFORM=$(TARGET_BOARD_PLATFORM) KBUILD_OPTIONS += $(WLAN_SELECT) + +VERSION=$(shell grep -w "VERSION =" $(TOP)/kernel/Makefile | sed 's/^VERSION = //' ) +PATCHLEVEL=$(shell grep -w "PATCHLEVEL =" $(TOP)/kernel/Makefile | sed 's/^PATCHLEVEL = //' ) + include $(CLEAR_VARS) LOCAL_MODULE := $(WLAN_CHIPSET)_wlan.ko LOCAL_MODULE_KBUILD_NAME := wlan.ko -LOCAL_MODULE_TAGS := debug +LOCAL_MODULE_TAGS := optional LOCAL_MODULE_DEBUG_ENABLE := true LOCAL_MODULE_PATH := $(TARGET_OUT)/lib/modules/$(WLAN_CHIPSET) include $(DLKM_DIR)/AndroidKernelModule.mk diff --git a/drivers/staging/prima/CORE/BAP/src/bapApiHCBB.c b/drivers/staging/prima/CORE/BAP/src/bapApiHCBB.c index fbe7cf43839..1f3b1275834 100644 --- a/drivers/staging/prima/CORE/BAP/src/bapApiHCBB.c +++ b/drivers/staging/prima/CORE/BAP/src/bapApiHCBB.c @@ -161,7 +161,7 @@ WLAN_BAPReset tHalHandle hHal = NULL; /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ - VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %x", __func__, btampHandle); + VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %p", __func__, btampHandle); /* Validate params */ if (btampHandle == NULL) @@ -308,7 +308,7 @@ WLAN_BAPFlush ptBtampContext btampContext = (ptBtampContext) btampHandle; /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ - VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %x", __func__, btampHandle); + VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %p", __func__, btampHandle); /* Validate params */ if (btampHandle == NULL) { @@ -381,7 +381,7 @@ WLAN_EnhancedBAPFlush ptBtampContext btampContext; /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ - VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %x", __func__, btampHandle); + VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %p", __func__, btampHandle); /* Validate params */ /* Validate params */ @@ -461,7 +461,7 @@ WLAN_BAPReadConnectionAcceptTimeout /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, - "%s: btampHandle value: %x", __func__, btampHandle); + "%s: btampHandle value: %p", __func__, btampHandle); /* Validate params */ if ((NULL == btampHandle) || (NULL == pBapHCIEvent)) @@ -530,7 +530,7 @@ WLAN_BAPWriteConnectionAcceptTimeout /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, - "%s: btampHandle value: %x", __func__, btampHandle); + "%s: btampHandle value: %p", __func__, btampHandle); /* Validate params */ if ((NULL == btampHandle) || (NULL == pBapHCIWriteConnectionAcceptTimeout) @@ -621,7 +621,7 @@ WLAN_BAPReadLinkSupervisionTimeout /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, - "%s: btampHandle value: %x", __func__, btampHandle); + "%s: btampHandle value: %p", __func__, btampHandle); /* Validate params */ if ((NULL == btampHandle) || (NULL == pBapHCIReadLinkSupervisionTimeout) || @@ -713,7 +713,7 @@ WLAN_BAPWriteLinkSupervisionTimeout /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, - "%s: btampHandle value: %x", __func__, btampHandle); + "%s: btampHandle value: %p", __func__, btampHandle); /* Validate params */ if ((NULL == btampHandle) || (NULL == pBapHCIWriteLinkSupervisionTimeout) || @@ -805,7 +805,7 @@ WLAN_BAPReadLogicalLinkAcceptTimeout /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, - "%s: btampHandle value: %x", __func__, btampHandle); + "%s: btampHandle value: %p", __func__, btampHandle); /* Validate params */ if ((NULL == btampHandle) || (NULL == pBapHCIEvent)) @@ -874,7 +874,7 @@ WLAN_BAPWriteLogicalLinkAcceptTimeout /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, - "%s: btampHandle value: %x", __func__, btampHandle); + "%s: btampHandle value: %p", __func__, btampHandle); /* Validate params */ if ((NULL == btampHandle) || (NULL == pBapHCIWriteLogicalLinkAcceptTimeout) @@ -962,7 +962,7 @@ WLAN_BAPSetEventMaskPage2 /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, - "%s: btampHandle value: %x", __func__, btampHandle); + "%s: btampHandle value: %p", __func__, btampHandle); /* Validate params */ if ((NULL == btampHandle) || (NULL == pBapHCISetEventMaskPage2) @@ -1037,7 +1037,7 @@ WLAN_BAPReadLocationData /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, - "%s: btampHandle value: %x", __func__, btampHandle); + "%s: btampHandle value: %p", __func__, btampHandle); /* Validate params */ if ((NULL == btampHandle) || (NULL == pBapHCIEvent)) @@ -1119,7 +1119,7 @@ WLAN_BAPWriteLocationData /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, - "%s: btampHandle value: %x", __func__, btampHandle); + "%s: btampHandle value: %p", __func__, btampHandle); /* Validate params */ if ((NULL == btampHandle) || (NULL == pBapHCIWriteLocationData) @@ -1200,7 +1200,7 @@ WLAN_BAPReadFlowControlMode /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, - "%s: btampHandle value: %x", __func__, btampHandle); + "%s: btampHandle value: %p", __func__, btampHandle); /* Validate params */ if ((NULL == btampHandle) || (NULL == pBapHCIEvent)) @@ -1405,7 +1405,7 @@ WLAN_BAPSetShortRangeMode /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, - "%s: btampHandle value: %x", __func__, btampHandle); + "%s: btampHandle value: %p", __func__, btampHandle); /* Validate params */ if ((NULL == btampHandle) || (NULL == pBapHCIEvent)) @@ -1546,7 +1546,7 @@ WLAN_BAPVendorSpecificCmd0 /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, - "%s: btampHandle value: %x", __func__, btampHandle); + "%s: btampHandle value: %p", __func__, btampHandle); /* Validate params */ if ((NULL == btampHandle) || (NULL == pBapHCIEvent)) @@ -1646,7 +1646,7 @@ WLAN_BAPVendorSpecificCmd1 /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, - "%s: btampHandle value: %x", __func__, btampHandle); + "%s: btampHandle value: %p", __func__, btampHandle); /* Validate params */ if ((NULL == btampHandle) || (NULL == pBapHCIEvent)) diff --git a/drivers/staging/prima/CORE/BAP/src/bapApiInfo.c b/drivers/staging/prima/CORE/BAP/src/bapApiInfo.c index 63356f9eab0..df2583e04fe 100644 --- a/drivers/staging/prima/CORE/BAP/src/bapApiInfo.c +++ b/drivers/staging/prima/CORE/BAP/src/bapApiInfo.c @@ -170,7 +170,7 @@ WLAN_BAPReadLocalVersionInfo } - VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %x", __func__, btampHandle); + VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %p", __func__, btampHandle); /* Format the command complete event to return... */ @@ -246,7 +246,7 @@ WLAN_BAPReadLocalSupportedCmds } - VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %x", __func__, btampHandle); + VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %p", __func__, btampHandle); /* Format the command complete event to return... */ @@ -312,7 +312,7 @@ WLAN_BAPReadBufferSize } - VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %x", __func__, btampHandle); + VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %p", __func__, btampHandle); /* Format the command complete event to return... */ @@ -382,7 +382,7 @@ WLAN_BAPReadDataBlockSize } - VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %x", __func__, btampHandle); + VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %p", __func__, btampHandle); /* Format the command complete event to return... */ @@ -543,7 +543,7 @@ WLAN_BAPDisconnect VOS_STATUS vosStatus; /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ - VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_FATAL, "%s: btampHandle value: %x", __func__, btampHandle); + VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_FATAL, "%s: btampHandle value: %p", __func__, btampHandle); /* Validate params */ if (btampHandle == NULL) @@ -609,7 +609,7 @@ v_BOOL_t WLAN_BAPSessionOn ptBtampContext btampContext = (ptBtampContext) btampHandle; /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ - VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %x", __func__, btampHandle); + VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %p", __func__, btampHandle); /* Validate params */ if (btampHandle == NULL) diff --git a/drivers/staging/prima/CORE/BAP/src/bapApiLinkCntl.c b/drivers/staging/prima/CORE/BAP/src/bapApiLinkCntl.c index 5a484c8aebf..b8ae3c5120f 100644 --- a/drivers/staging/prima/CORE/BAP/src/bapApiLinkCntl.c +++ b/drivers/staging/prima/CORE/BAP/src/bapApiLinkCntl.c @@ -882,12 +882,12 @@ WLAN_BAPPhysicalLinkCreate /* Validate params */ if ((pBapHCIPhysLinkCreate == NULL) || (NULL == btampContext)) { - VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "%s: btampHandle value: %x, pBapHCIPhysLinkCreate is %x", + VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "%s: btampHandle value: %p, pBapHCIPhysLinkCreate is %p", __func__, btampHandle, pBapHCIPhysLinkCreate); return VOS_STATUS_E_FAULT; } - VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %x", __func__, btampHandle); + VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %p", __func__, btampHandle); if(DISCONNECTED != instanceVar->stateVar) { @@ -913,7 +913,7 @@ WLAN_BAPPhysicalLinkCreate &btampContext, /* Handle to return per assoc btampContext value in */ BT_INITIATOR); /* BT_INITIATOR */ - VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampContext value: %x", __func__, btampContext); + VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampContext value: %p", __func__, btampContext); /* Handle event */ vosStatus = btampFsm(btampContext, &bapEvent, &status); @@ -985,12 +985,12 @@ WLAN_BAPPhysicalLinkAccept /* Validate params */ if ((pBapHCIPhysLinkAccept == NULL) || (NULL == btampContext)) { - VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "%s: btampHandle value: %x, pBapHCIPhysLinkAccept is %x", + VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "%s: btampHandle value: %p, pBapHCIPhysLinkAccept is %p", __func__, btampHandle, pBapHCIPhysLinkAccept); return VOS_STATUS_E_FAULT; } - VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %x", __func__, btampHandle); + VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %p", __func__, btampHandle); instanceVar = &(btampContext->bapPhysLinkMachine); if(DISCONNECTED != instanceVar->stateVar) @@ -1017,7 +1017,7 @@ WLAN_BAPPhysicalLinkAccept &btampContext, /* Handle to return per assoc btampContext value in */ BT_RESPONDER); /* BT_RESPONDER */ - VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampContext value: %x", __func__, btampContext); + VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampContext value: %p", __func__, btampContext); /* Handle event */ vosStatus = btampFsm(btampContext, &bapEvent, &status); @@ -1087,7 +1087,7 @@ WLAN_BAPPhysicalLinkDisconnect return VOS_STATUS_E_FAULT; } - VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %x", __func__, btampHandle); + VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %p", __func__, btampHandle); /* Validate the Physical link handle */ if (pBapHCIPhysLinkDisconnect->phy_link_handle != btampContext->phy_link_handle) @@ -1106,7 +1106,7 @@ WLAN_BAPPhysicalLinkDisconnect bapEvent.event = eWLAN_BAP_HCI_PHYSICAL_LINK_DISCONNECT; bapEvent.params = pBapHCIPhysLinkDisconnect; - VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampContext value: %x", __func__, btampContext); + VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampContext value: %p", __func__, btampContext); /* Handle event */ vosStatus = btampFsm(btampContext, &bapEvent, &status); @@ -1192,7 +1192,7 @@ WLAN_BAPLogicalLinkCreate } - VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %x", __func__, btampHandle); + VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %p", __func__, btampHandle); /* Validate the BAP state to accept the logical link request Logical Link create/accept requests are allowed only in @@ -1382,7 +1382,7 @@ WLAN_BAPLogicalLinkAccept } - VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %x", __func__, btampHandle); + VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %p", __func__, btampHandle); /* Validate the BAP state to accept the logical link request Logical Link create/accept requests are allowed only in @@ -1590,7 +1590,7 @@ WLAN_BAPLogicalLinkDisconnect #ifdef BAP_DEBUG /* Trace the tBtampCtx being passed in. */ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, - "WLAN BAP Context Monitor: btampContext value = %x in %s:%d", btampContext, __func__, __LINE__ ); + "WLAN BAP Context Monitor: btampContext value = %p in %s:%d", btampContext, __func__, __LINE__ ); #endif //BAP_DEBUG bapHCIEvent.bapHCIEventCode = BTAMP_TLV_HCI_COMMAND_STATUS_EVENT; diff --git a/drivers/staging/prima/CORE/BAP/src/bapApiLinkSupervision.c b/drivers/staging/prima/CORE/BAP/src/bapApiLinkSupervision.c index 426f00e6ad3..62a1d4e2752 100644 --- a/drivers/staging/prima/CORE/BAP/src/bapApiLinkSupervision.c +++ b/drivers/staging/prima/CORE/BAP/src/bapApiLinkSupervision.c @@ -537,7 +537,7 @@ static VOS_STATUS WLANBAP_TxLinkSupervisionCB } } VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO, - "%s:Returned Vos Packet:%x\n",__func__, pPacket ); + "%s:Returned Vos Packet:%p\n", __func__, pPacket ); vos_pkt_return_packet( pPacket ); diff --git a/drivers/staging/prima/CORE/BAP/src/bapApiStatus.c b/drivers/staging/prima/CORE/BAP/src/bapApiStatus.c index b1c26b4087c..00b11e662ba 100644 --- a/drivers/staging/prima/CORE/BAP/src/bapApiStatus.c +++ b/drivers/staging/prima/CORE/BAP/src/bapApiStatus.c @@ -263,7 +263,7 @@ WLAN_BAPReadLinkQuality /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, - "%s: btampHandle value: %x", __func__, btampHandle); + "%s: btampHandle value: %p", __func__, btampHandle); /* Validate params */ if ((NULL == btampHandle) || (NULL == pBapHCIReadLinkQuality) || @@ -360,7 +360,7 @@ WLAN_BAPReadRSSI /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, - "%s: btampHandle value: %x", __func__, btampHandle); + "%s: btampHandle value: %p", __func__, btampHandle); /* Validate params */ if ((NULL == btampHandle) || (NULL == pBapHCIReadRSSI) || @@ -469,7 +469,7 @@ WLAN_BAPReadLocalAMPInfo return VOS_STATUS_E_FAULT; } - VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %x", __func__, btampHandle); + VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %p", __func__, btampHandle); /* Format the command complete event to return... */ @@ -581,7 +581,7 @@ WLAN_BAPReadLocalAMPAssoc return VOS_STATUS_E_FAULT; } - VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %x", __func__, btampHandle); + VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %p", __func__, btampHandle); VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "In %s, phy_link_handle = %d", __func__, @@ -818,13 +818,13 @@ WLAN_BAPWriteRemoteAMPAssoc return VOS_STATUS_E_FAULT; } - VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %x", __func__, btampHandle); + VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %p", __func__, btampHandle); /* Fill in the event structure */ bapEvent.event = eWLAN_BAP_HCI_WRITE_REMOTE_AMP_ASSOC; bapEvent.params = pBapHCIWriteRemoteAMPAssoc; - VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampContext value: %x", __func__, btampContext); + VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampContext value: %p", __func__, btampContext); /* Handle event */ vosStatus = btampFsm(btampContext, &bapEvent, &status); diff --git a/drivers/staging/prima/CORE/BAP/src/bapModule.c b/drivers/staging/prima/CORE/BAP/src/bapModule.c index a0eab5cc696..504ae9b7501 100644 --- a/drivers/staging/prima/CORE/BAP/src/bapModule.c +++ b/drivers/staging/prima/CORE/BAP/src/bapModule.c @@ -977,7 +977,7 @@ WLANBAP_CreateNewPhyLinkCtx *hBtampContext = pBtampCtx; VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, - "Btamp Ctxt = %x", pBtampCtx); + "Btamp Ctxt = %p", pBtampCtx); return VOS_STATUS_SUCCESS; #else // defined(BTAMP_MULTIPLE_PHY_LINKS) @@ -1112,7 +1112,7 @@ WLANBAP_CreateNewLogLinkCtx #ifdef BAP_DEBUG /* Trace the tBtampCtx being passed in. */ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, - "WLAN BAP Context Monitor: pBtampContext value = %x in %s:%d", pBtampContext, __func__, __LINE__ ); + "WLAN BAP Context Monitor: pBtampContext value = %p in %s:%d", pBtampContext, __func__, __LINE__ ); #endif //BAP_DEBUG /*------------------------------------------------------------------------ diff --git a/drivers/staging/prima/CORE/BAP/src/bapRsn8021xSuppRsnFsm.c b/drivers/staging/prima/CORE/BAP/src/bapRsn8021xSuppRsnFsm.c index abaa50a7ba4..4e4724597ab 100644 --- a/drivers/staging/prima/CORE/BAP/src/bapRsn8021xSuppRsnFsm.c +++ b/drivers/staging/prima/CORE/BAP/src/bapRsn8021xSuppRsnFsm.c @@ -797,7 +797,7 @@ int checkPeerReplayCounter(tSuppRsnFsm *fsm, if (cmp > 0) { VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, - "BP radio %d got old EAPOL replay counter from AP\n" ); + "BP got old EAPOL replay counter from AP" ); retVal = ANI_E_REPLAY_CHECK_FAILED; } @@ -875,7 +875,7 @@ int checkTransition(tSuppRsnFsm *fsm, void *arg) VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "Resending EAPOL-Key Msg2 from " - "supplicant radio %d to AP\n" ); + "supplicant to AP" ); retVal = gotoStateStaKeyStart(fsm, data, eANI_BOOLEAN_TRUE); } diff --git a/drivers/staging/prima/CORE/BAP/src/bapRsnTxRx.c b/drivers/staging/prima/CORE/BAP/src/bapRsnTxRx.c index efe8ec3c55b..390d61abac7 100644 --- a/drivers/staging/prima/CORE/BAP/src/bapRsnTxRx.c +++ b/drivers/staging/prima/CORE/BAP/src/bapRsnTxRx.c @@ -223,7 +223,7 @@ static VOS_STATUS bapRsnTxFrame( v_PVOID_t pvosGCtx, vos_pkt_t *pPacket ) VOS_STATUS bapRsnSendEapolFrame( v_PVOID_t pvosGCtx, tAniPacket *pAniPkt ) { VOS_STATUS status; - vos_pkt_t *pPacket; + vos_pkt_t *pPacket = NULL; v_U8_t *pData, *pSrc; int pktLen = aniAsfPacketGetBytes( pAniPkt, &pSrc ); @@ -232,7 +232,7 @@ VOS_STATUS bapRsnSendEapolFrame( v_PVOID_t pvosGCtx, tAniPacket *pAniPkt ) return VOS_STATUS_E_EMPTY; } status = bapRsnAcquirePacket( &pPacket, &pData, pktLen ); - if( VOS_IS_STATUS_SUCCESS( status ) ) + if( VOS_IS_STATUS_SUCCESS( status ) && ( NULL != pPacket )) { vos_mem_copy( pData, pSrc, pktLen ); //Send the packet, need to check whether we have an outstanding packet first. diff --git a/drivers/staging/prima/CORE/BAP/src/btampFsm.c b/drivers/staging/prima/CORE/BAP/src/btampFsm.c index 0b4b97b1e93..d049067f7aa 100644 --- a/drivers/staging/prima/CORE/BAP/src/btampFsm.c +++ b/drivers/staging/prima/CORE/BAP/src/btampFsm.c @@ -208,7 +208,7 @@ bapSetKey( v_PVOID_t pvosGCtx, tCsrRoamSetKey *pSetKeyInfo ) return VOS_STATUS_E_FAULT; } - VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampContext value: %x", __func__, btampContext); + VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampContext value: %p", __func__, btampContext); /* Fill in the event structure */ bapEvent.event = eWLAN_BAP_RSN_SUCCESS; @@ -1415,7 +1415,7 @@ signalHCIPhysLinkDiscEvent #ifdef BAP_DEBUG /* Trace the tBtampCtx being passed in. */ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, - "WLAN BAP Context Monitor: btampContext value = %x in %s:%d", btampContext, __func__, __LINE__ ); + "WLAN BAP Context Monitor: btampContext value = %p in %s:%d", btampContext, __func__, __LINE__ ); #endif //BAP_DEBUG /* Loop disconnecting all Logical Links on this Physical Link */ diff --git a/drivers/staging/prima/CORE/DXE/src/wlan_qct_dxe.c b/drivers/staging/prima/CORE/DXE/src/wlan_qct_dxe.c index cdeed3540b3..d62d460e6c0 100644 --- a/drivers/staging/prima/CORE/DXE/src/wlan_qct_dxe.c +++ b/drivers/staging/prima/CORE/DXE/src/wlan_qct_dxe.c @@ -39,6 +39,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ + /**========================================================================= @file wlan_qct_dxe.c @@ -46,9 +47,8 @@ @brief This file contains the external API exposed by the wlan data transfer abstraction layer module. - Copyright (c) 2010-2011 QUALCOMM Incorporated. + Copyright (c) 2010-2011 Qualcomm Technologies, Inc. All Rights Reserved. - Qualcomm Confidential and Proprietary ========================================================================*/ /*=========================================================================== @@ -97,7 +97,7 @@ when who what, where, why #define T_WLANDXE_TX_INT_ENABLE_FCOUNT 1 #define T_WLANDXE_MEMDUMP_BYTE_PER_LINE 16 #define T_WLANDXE_MAX_RX_PACKET_WAIT 6000 -#define T_WLANDXE_PERIODIC_HEALTH_M_TIME 1500 +#define T_WLANDXE_PERIODIC_HEALTH_M_TIME 2500 #define T_WLANDXE_MAX_HW_ACCESS_WAIT 2000 #define WLANDXE_MAX_REAPED_RX_FRAMES 512 @@ -585,6 +585,7 @@ void dxeRXHealthMonitor /* Make wake up HW */ dxeNotifySmsm(eWLAN_PAL_FALSE, eWLAN_PAL_TRUE); dxeNotifySmsm(eWLAN_PAL_TRUE, eWLAN_PAL_FALSE); + dxeNotifySmsm(eWLAN_PAL_FALSE, eWLAN_PAL_TRUE); for(hwWakeLoop = 0; hwWakeLoop < T_WLANDXE_MAX_HW_ACCESS_WAIT; hwWakeLoop++) { @@ -711,6 +712,7 @@ void dxeTXHealthMonitor * This will fix if there is any problem with SMSM state */ dxeNotifySmsm(eWLAN_PAL_FALSE, eWLAN_PAL_TRUE); dxeNotifySmsm(eWLAN_PAL_TRUE, eWLAN_PAL_FALSE); + dxeNotifySmsm(eWLAN_PAL_FALSE, eWLAN_PAL_TRUE); /* Wait till RIVA up */ for(hwWakeLoop = 0; hwWakeLoop < T_WLANDXE_MAX_HW_ACCESS_WAIT; hwWakeLoop++) @@ -2214,10 +2216,13 @@ static wpt_status dxeRXFrameReady * Do not try reload driver at here*/ if(!(chStat & WLANDXE_CH_CTRL_EN_MASK)) { - HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR, + HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_WARN, "dxeRXFrameReady %s RING Wrapped, RX Free Low 0x%x", channelType[channelEntry->channelType], chStat); - channelEntry->numFragmentCurrentChain = 0; + /* This is not empty interrupt case + * If handle this as empty interrupt, false SSR might be issued + * Frame count '1' is dummy frame count to avoid SSR */ + channelEntry->numFragmentCurrentChain = 1; return eWLAN_PAL_STATUS_SUCCESS; } @@ -2248,11 +2253,11 @@ static wpt_status dxeRXFrameReady { if(!(WLANDXE_U32_SWAP_ENDIAN(descCtrl) & WLANDXE_DESC_CTRL_VALID)) { - HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR, + HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_WARN, "Found Invalidated Descriptor %d", (int)descLoop); if(eWLAN_PAL_STATUS_SUCCESS == wpalIsPacketLocked(currentCtrlBlk->xfrFrame)) { - HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR, + HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_WARN, "Packet locked, Resync Host and HW"); channelEntry->headCtrlBlk = currentCtrlBlk; invalidatedFound = 1; @@ -2260,7 +2265,7 @@ static wpt_status dxeRXFrameReady } else { - HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR, + HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_WARN, "Packet Not Locked, cannot transfer frame"); } } @@ -2675,16 +2680,6 @@ void dxeRXEventHandler return; } - /* Enable system level ISR */ - /* Enable RX ready Interrupt at here */ - status = wpalEnableInterrupt(DXE_INTERRUPT_RX_READY); - if(eWLAN_PAL_STATUS_SUCCESS != status) - { - HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR, - "dxeRXEventHandler Enable RX Ready interrupt fail"); - return; - } - /* Prepare Control Register EN Channel */ if(!(dxeCtxt->dxeChannel[WDTS_CHANNEL_RX_HIGH_PRI].extraConfig.chan_mask & WLANDXE_CH_CTRL_EN_MASK)) { @@ -2708,6 +2703,16 @@ void dxeRXEventHandler regValue &= WLANDXE_RX_INTERRUPT_PRO_UNMASK; wpalWriteRegister(WLANDXE_INT_MASK_REG_ADDRESS, regValue); + /* Enable system level ISR */ + /* Enable RX ready Interrupt at here */ + status = wpalEnableInterrupt(DXE_INTERRUPT_RX_READY); + if(eWLAN_PAL_STATUS_SUCCESS != status) + { + HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR, + "dxeRXEventHandler Enable RX Ready interrupt fail"); + return; + } + HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW, "%s Exit", __func__); return; @@ -2899,14 +2904,16 @@ static wpt_status dxeTXPushFrame #else wpt_iterator iterator; #endif /* FEATURE_R33D */ + wpt_uint32 isEmpty = 0; HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW, "%s Enter", __func__); - if(WLANDXE_POWER_STATE_BMPS == tempDxeCtrlBlk->hostPowerState) + tempDxeCtrlBlk->smsmToggled = eWLAN_PAL_FALSE; + if((0 == tempDxeCtrlBlk->dxeChannel[WDTS_CHANNEL_TX_LOW_PRI].numRsvdDesc) && + (0 == tempDxeCtrlBlk->dxeChannel[WDTS_CHANNEL_TX_HIGH_PRI].numRsvdDesc)) { - tempDxeCtrlBlk->rivaPowerState = WLANDXE_RIVA_POWER_STATE_BMPS_UNKNOWN; - dxeNotifySmsm(eWLAN_PAL_FALSE, eWLAN_PAL_TRUE); + isEmpty = 1; } channelEntry->numFragmentCurrentChain = 0; @@ -3049,10 +3056,16 @@ static wpt_status dxeTXPushFrame { /* Update channel head as next avaliable linked slot */ channelEntry->headCtrlBlk = currentCtrlBlk; - tempDxeCtrlBlk->ringNotEmpty = eWLAN_PAL_TRUE; - HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW, "SMSM_ret LO=%d HI=%d", tempDxeCtrlBlk->dxeChannel[WDTS_CHANNEL_TX_LOW_PRI].numRsvdDesc, - tempDxeCtrlBlk->dxeChannel[WDTS_CHANNEL_TX_HIGH_PRI].numRsvdDesc ); - dxeNotifySmsm(eWLAN_PAL_TRUE, eWLAN_PAL_FALSE); + if(isEmpty) + { + tempDxeCtrlBlk->ringNotEmpty = eWLAN_PAL_TRUE; + HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW, + "SMSM_ret LO=%d HI=%d", + tempDxeCtrlBlk->dxeChannel[WDTS_CHANNEL_TX_LOW_PRI].numRsvdDesc, + tempDxeCtrlBlk->dxeChannel[WDTS_CHANNEL_TX_HIGH_PRI].numRsvdDesc ); + dxeNotifySmsm(eWLAN_PAL_TRUE, eWLAN_PAL_FALSE); + tempDxeCtrlBlk->smsmToggled = eWLAN_PAL_TRUE; + } return status; } @@ -3732,6 +3745,18 @@ void dxeTXCompleteProcessing dxeCtxt->dxeChannel[WDTS_CHANNEL_TX_HIGH_PRI].numRsvdDesc, channelType[dxeCtxt->dxeChannel[WDTS_CHANNEL_TX_LOW_PRI].channelType], dxeCtxt->dxeChannel[WDTS_CHANNEL_TX_LOW_PRI].numRsvdDesc); + + if((WLANDXE_POWER_STATE_FULL != dxeCtxt->hostPowerState) && + (eWLAN_PAL_FALSE == tempDxeCtrlBlk->smsmToggled)) + { + /* After TX Comp processing, still remaining frame on the DXE TX ring + * And when push frame, RING was not empty marked + * Then when push frame, no SMSM toggle happen + * To avoid permanent TX stall, SMSM toggle is needed at here + * With this toggle, host should gaurantee SMSM state should be changed */ + dxeNotifySmsm(eWLAN_PAL_FALSE, eWLAN_PAL_TRUE); + dxeNotifySmsm(eWLAN_PAL_TRUE, eWLAN_PAL_FALSE); + } } /*Kicking the DXE after the TX Complete interrupt was enabled - to avoid @@ -4184,6 +4209,7 @@ void *WLANDXE_Open tempDxeCtrlBlk->rxIntDisabledByIMPS = eWLAN_PAL_FALSE; tempDxeCtrlBlk->txIntDisabledByIMPS = eWLAN_PAL_FALSE; tempDxeCtrlBlk->driverReloadInProcessing = eWLAN_PAL_FALSE; + tempDxeCtrlBlk->smsmToggled = eWLAN_PAL_FALSE; /* Initialize SMSM state * Init State is @@ -4697,6 +4723,11 @@ wpt_status WLANDXE_Stop dxeCtxt = (WLANDXE_CtrlBlkType *)pDXEContext; for(idx = 0; idx < WDTS_CHANNEL_MAX; idx++) { + if(VOS_TIMER_STATE_RUNNING == wpalTimerGetCurStatus(&dxeCtxt->dxeChannel[idx].healthMonitorTimer)) + { + wpalTimerStop(&dxeCtxt->dxeChannel[idx].healthMonitorTimer); + } + status = dxeChannelStop(dxeCtxt, &dxeCtxt->dxeChannel[idx]); if(eWLAN_PAL_STATUS_SUCCESS != status) { diff --git a/drivers/staging/prima/CORE/DXE/src/wlan_qct_dxe_cfg_i.c b/drivers/staging/prima/CORE/DXE/src/wlan_qct_dxe_cfg_i.c index 24bd93ccba9..6c782f30e52 100644 --- a/drivers/staging/prima/CORE/DXE/src/wlan_qct_dxe_cfg_i.c +++ b/drivers/staging/prima/CORE/DXE/src/wlan_qct_dxe_cfg_i.c @@ -386,7 +386,7 @@ wpt_status dxeCommonDefaultConfig All the channels must have it's own configurations @ Parameters - WLANDXE_CtrlBlkType *dxeCtrlBlk, + WLANDXE_CtrlBlkType: *dxeCtrlBlk, DXE host driver main control block WLANDXE_ChannelCBType *channelEntry Channel specific control block @@ -409,6 +409,7 @@ wpt_status dxeChannelDefaultConfig wpt_uint32 dxeControlWriteEop = 0; wpt_uint32 dxeControlWriteEopInt = 0; wpt_uint32 idx; + wpt_uint32 rxResourceCount = 0; WLANDXE_ChannelMappingType *mappedChannel = NULL; /* Sanity Check */ @@ -621,7 +622,16 @@ wpt_status dxeChannelDefaultConfig channelEntry->extraConfig.intMask = channelInterruptMask[mappedChannel->DMAChannel]; - channelEntry->numDesc = mappedChannel->channelConfig->nDescs; + wpalGetNumRxRawPacket(&rxResourceCount); + if((WDTS_CHANNEL_TX_LOW_PRI == channelEntry->channelType) || + (0 == rxResourceCount)) + { + channelEntry->numDesc = mappedChannel->channelConfig->nDescs; + } + else + { + channelEntry->numDesc = rxResourceCount / 4; + } channelEntry->assignedDMAChannel = mappedChannel->DMAChannel; channelEntry->numFreeDesc = 0; channelEntry->numRsvdDesc = 0; diff --git a/drivers/staging/prima/CORE/DXE/src/wlan_qct_dxe_i.h b/drivers/staging/prima/CORE/DXE/src/wlan_qct_dxe_i.h index 77d3987d95d..5f95b33dc82 100644 --- a/drivers/staging/prima/CORE/DXE/src/wlan_qct_dxe_i.h +++ b/drivers/staging/prima/CORE/DXE/src/wlan_qct_dxe_i.h @@ -39,6 +39,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ + #ifndef WLAN_QCT_DXE_I_H #define WLAN_QCT_DXE_I_H @@ -49,9 +50,9 @@ @brief This file contains the external API exposed by the wlan data transfer abstraction layer module. - Copyright (c) 2011 QUALCOMM Incorporated. + Copyright (c) 2011 Qualcomm Technologies, Inc. All Rights Reserved. - Qualcomm Confidential and Proprietary + Qualcomm Technologies Confidential and Proprietary ========================================================================*/ /*=========================================================================== @@ -642,6 +643,7 @@ typedef struct wpt_packet *freeRXPacket; wpt_boolean rxPalPacketUnavailable; wpt_boolean driverReloadInProcessing; + wpt_boolean smsmToggled; } WLANDXE_CtrlBlkType; /*========================================================================== diff --git a/drivers/staging/prima/CORE/HDD/inc/qc_sap_ioctl.h b/drivers/staging/prima/CORE/HDD/inc/qc_sap_ioctl.h index b4b27ef73f4..15520ae2e02 100644 --- a/drivers/staging/prima/CORE/HDD/inc/qc_sap_ioctl.h +++ b/drivers/staging/prima/CORE/HDD/inc/qc_sap_ioctl.h @@ -256,6 +256,7 @@ typedef struct #define QCSAP_IOCTL_SET_TX_POWER (SIOCIWFIRSTPRIV+20) #define QCSAP_IOCTL_GET_STA_INFO (SIOCIWFIRSTPRIV+21) #define QCSAP_IOCTL_SET_MAX_TX_POWER (SIOCIWFIRSTPRIV+22) +#define QCSAP_IOCTL_DATAPATH_SNAP_SHOT (SIOCIWFIRSTPRIV+23) #define MAX_VAR_ARGS 7 #define QCSAP_IOCTL_PRIV_GET_SOFTAP_LINK_SPEED (SIOCIWFIRSTPRIV + 31) diff --git a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_assoc.h b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_assoc.h index c1d1b6d58c9..55d8caeefb5 100644 --- a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_assoc.h +++ b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_assoc.h @@ -44,13 +44,15 @@ #include #define HDD_MAX_NUM_IBSS_STA ( 9 ) #ifdef FEATURE_WLAN_TDLS -#define HDD_MAX_NUM_TDLS_STA ( HDD_MAX_NUM_IBSS_STA - 1 ) // up to 3 as 1 is assigned to AP +#define HDD_MAX_NUM_TDLS_STA ( 8 ) +#define TDLS_STA_INDEX_VALID(staId) \ + (((staId) >= 4) && ((staId) < 0xFF)) #endif #define TKIP_COUNTER_MEASURE_STARTED 1 #define TKIP_COUNTER_MEASURE_STOPED 0 /* Timeout (in ms) for Link to Up before Registering Station */ #define ASSOC_LINKUP_TIMEOUT 60 -typedef enum +typedef enum { /** Not associated in Infra or participating in an IBSS / Ad-hoc network.*/ eConnectionState_NotConnected, @@ -110,6 +112,9 @@ typedef struct connection_info_s /** Remembers authenticated state */ v_U8_t uIsAuthenticated; + + /** Dot11Mode */ + tANI_U32 dot11Mode; }connection_info_t; /*Forward declaration of Adapter*/ @@ -134,5 +139,5 @@ int hdd_SetGENIEToCsr( hdd_adapter_t *pAdapter, eCsrAuthType *RSNAuthType ); int hdd_set_csr_auth_type( hdd_adapter_t *pAdapter, eCsrAuthType RSNAuthType ); VOS_STATUS hdd_roamRegisterTDLSSTA( hdd_adapter_t *pAdapter, tANI_U8 *peerMac, tANI_U16 staId, tANI_U8 ucastSig); - +void hdd_PerformRoamSetKeyComplete(hdd_adapter_t *pAdapter); #endif diff --git a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_cfg.h b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_cfg.h index 2e900906f83..09e60085142 100644 --- a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_cfg.h +++ b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_cfg.h @@ -591,6 +591,11 @@ typedef enum #define CFG_RETRY_LIMIT_TWO_MAX ( 15 ) #define CFG_RETRY_LIMIT_TWO_DEFAULT ( 15 ) +#define CFG_DISABLE_AGG_WITH_BTC_NAME "gDisableAggWithBTC" +#define CFG_DISABLE_AGG_WITH_BTC_MIN ( 0 ) +#define CFG_DISABLE_AGG_WITH_BTC_MAX ( 1 ) +#define CFG_DISABLE_AGG_WITH_BTC_DEFAULT ( 1 ) + #ifdef WLAN_AP_STA_CONCURRENCY #define CFG_PASSIVE_MAX_CHANNEL_TIME_CONC_NAME "gPassiveMaxChannelTimeConc" @@ -618,10 +623,15 @@ typedef enum #define CFG_REST_TIME_CONC_MAX ( 10000 ) #define CFG_REST_TIME_CONC_DEFAULT ( 100 ) -#define CFG_NUM_CHAN_COMBINED_CONC_NAME "gNumChanCombinedConc" -#define CFG_NUM_CHAN_COMBINED_CONC_MIN ( 1 ) -#define CFG_NUM_CHAN_COMBINED_CONC_MAX ( 255 ) -#define CFG_NUM_CHAN_COMBINED_CONC_DEFAULT ( 1 ) +#define CFG_NUM_STA_CHAN_COMBINED_CONC_NAME "gNumStaChanCombinedConc" +#define CFG_NUM_STA_CHAN_COMBINED_CONC_MIN ( 1 ) +#define CFG_NUM_STA_CHAN_COMBINED_CONC_MAX ( 255 ) +#define CFG_NUM_STA_CHAN_COMBINED_CONC_DEFAULT ( 3 ) + +#define CFG_NUM_P2P_CHAN_COMBINED_CONC_NAME "gNumP2PChanCombinedConc" +#define CFG_NUM_P2P_CHAN_COMBINED_CONC_MIN ( 1 ) +#define CFG_NUM_P2P_CHAN_COMBINED_CONC_MAX ( 255 ) +#define CFG_NUM_P2P_CHAN_COMBINED_CONC_DEFAULT ( 1 ) #endif @@ -655,6 +665,11 @@ typedef enum #define CFG_IGNORE_DTIM_MAX WNI_CFG_IGNORE_DTIM_STAMAX #define CFG_IGNORE_DTIM_DEFAULT WNI_CFG_IGNORE_DTIM_STADEF +#define CFG_MAX_LI_MODULATED_DTIM_NAME "gMaxLIModulatedDTIM" +#define CFG_MAX_LI_MODULATED_DTIM_MIN ( 1 ) +#define CFG_MAX_LI_MODULATED_DTIM_MAX ( 10 ) +#define CFG_MAX_LI_MODULATED_DTIM_DEFAULT ( 10 ) + #define CFG_RX_ANT_CONFIGURATION_NAME "gNumRxAnt" #define CFG_RX_ANT_CONFIGURATION_NAME_MIN ( 1 ) #define CFG_RX_ANT_CONFIGURATION_NAME_MAX ( 2 ) @@ -811,6 +826,21 @@ typedef enum #define CFG_IMMEDIATE_ROAM_RSSI_DIFF_MAX (125) #define CFG_IMMEDIATE_ROAM_RSSI_DIFF_DEFAULT (3) +/*This parameter is used to set Wireless Extended Security Mode.*/ +#define CFG_ENABLE_WES_MODE_NAME "gWESModeEnabled" +#define CFG_ENABLE_WES_MODE_NAME_MIN (0) +#define CFG_ENABLE_WES_MODE_NAME_MAX (1) +#define CFG_ENABLE_WES_MODE_NAME_DEFAULT (0) + +#define CFG_ROAM_SCAN_N_PROBES "gRoamScanNProbes" +#define CFG_ROAM_SCAN_N_PROBES_MIN (1) +#define CFG_ROAM_SCAN_N_PROBES_MAX (10) +#define CFG_ROAM_SCAN_N_PROBES_DEFAULT (2) + +#define CFG_ROAM_SCAN_HOME_AWAY_TIME "gRoamScanHomeAwayTime" +#define CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN (3) +#define CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX (300) +#define CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT (CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT) #endif /* (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR) */ #ifdef FEATURE_WLAN_OKC @@ -820,6 +850,13 @@ typedef enum #define CFG_OKC_FEATURE_ENABLED_DEFAULT (1) #endif +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +#define CFG_ROAM_SCAN_OFFLOAD_ENABLED "gRoamScanOffloadEnabled" +#define CFG_ROAM_SCAN_OFFLOAD_ENABLED_MIN (0) +#define CFG_ROAM_SCAN_OFFLOAD_ENABLED_MAX (1) +#define CFG_ROAM_SCAN_OFFLOAD_ENABLED_DEFAULT (1) +#endif + #define CFG_QOS_WMM_PKT_CLASSIFY_BASIS_NAME "PktClassificationBasis" // DSCP or 802.1Q #define CFG_QOS_WMM_PKT_CLASSIFY_BASIS_MIN (0) #define CFG_QOS_WMM_PKT_CLASSIFY_BASIS_MAX (1) @@ -1148,9 +1185,8 @@ typedef enum #define CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN (1000) #define CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX (60000) #define CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT (20000) - #define CFG_EMPTY_SCAN_REFRESH_PERIOD_NAME "gEmptyScanRefreshPeriod" -#define CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN (0) +#define CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN (1000) #define CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX (60000) #define CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT (0) #endif /* WLAN_FEATURE_NEIGHBOR_ROAMING */ @@ -1210,6 +1246,12 @@ typedef enum #define CFG_ENABLE_HOST_ARPOFFLOAD_MAX ( 1 ) #define CFG_ENABLE_HOST_ARPOFFLOAD_DEFAULT ( 0 ) +#define CFG_ENABLE_HOST_NSOFFLOAD_NAME "hostNSOffload" +#define CFG_ENABLE_HOST_NSOFFLOAD_MIN ( 0 ) +#define CFG_ENABLE_HOST_NSOFFLOAD_MAX ( 1 ) +#define CFG_ENABLE_HOST_NSOFFLOAD_DEFAULT ( 0 ) + + #define CFG_ENABLE_BTAMP_NAME "gEnableBtAmp" #define CFG_ENABLE_BTAMP_MIN ( 0 ) #define CFG_ENABLE_BTAMP_MAX ( 1 ) @@ -1247,11 +1289,6 @@ typedef enum #define CFG_ENABLE_DFS_CHNL_SCAN_MAX ( 1 ) #define CFG_ENABLE_DFS_CHNL_SCAN_DEFAULT ( 1 ) -#define CFG_ENABLE_IGNORE_CHAN165 "gIgnore_Chan165" -#define CFG_ENABLE_IGNORE_CHAN165_MIN ( 0 ) -#define CFG_ENABLE_IGNORE_CHAN165_MAX ( 1 ) -#define CFG_ENABLE_IGNORE_CHAN165_DEFAULT ( 0 ) - typedef enum { eHDD_LINK_SPEED_REPORT_ACTUAL = 0, @@ -1312,6 +1349,11 @@ typedef enum #define CFG_MC_ADDR_LIST_FILTER_DEFAULT ( 0 ) #endif +#define CFG_ENABLE_SSR "gEnableSSR" +#define CFG_ENABLE_SSR_MIN ( 0 ) +#define CFG_ENABLE_SSR_MAX ( 1 ) +#define CFG_ENABLE_SSR_DEFAULT ( 1 ) + /* * VOS Trace Enable Control * Notes: @@ -1470,27 +1512,32 @@ typedef enum * Enable / Disable MCC feature * Default: Enable */ -#define CFG_ENABLE_MCC_ENABLED_NAME "gEnableMCCMode" +#define CFG_ENABLE_MCC_ENABLED_NAME "gEnableMCCMode" #define CFG_ENABLE_MCC_ENABLED_MIN ( 0 ) #define CFG_ENABLE_MCC_ENABLED_MAX ( 1 ) -#define CFG_ENABLE_MCC_ENABLED_DEFAULT ( 1 ) +#define CFG_ENABLE_MCC_ENABLED_DEFAULT ( 1 ) /* * Allow GO in MCC mode to accept different beacon interval than STA's. * Added for Wi-Fi Cert. 5.1.12 - * Default: Disable - * If gAllowMCCGODiffBI = 1 // Set to 1 for WFA certification. GO Beacon interval is not changed. MCC GO -* doesn't work well in optimized way. In worst scenario, it may invite STA -* disconnection. - * gAllowMCCGODiffBI = 2 //If set to 2 workaround 1 disassoc all the clients + * Default: gAllowMCCGODiffBI = 2 + * If gAllowMCCGODiffBI = 1 // Set to 1 for WFA certification. GO Beacon + * interval is not changed. MCC GO + * doesn't work well in optimized way. + * In worst scenario, it may invite STA + * disconnection. + * gAllowMCCGODiffBI = 2 //If set to 2 workaround 1 disassoc all the clients * and update beacon Interval * gAllowMCCGODiffBI = 3 //If set to 3 tear down the P2P link in auto/ * Non-autonomous -GO case + * gAllowMCCGODiffBI = 4 //If set to 4 don't disconnect the P2P client + * in autonomous/Non-autonomous -GO case update + * the BI dynamically */ #define CFG_ALLOW_MCC_GO_DIFF_BI_NAME "gAllowMCCGODiffBI" #define CFG_ALLOW_MCC_GO_DIFF_BI_MIN ( 0 ) -#define CFG_ALLOW_MCC_GO_DIFF_BI_MAX ( 3 ) -#define CFG_ALLOW_MCC_GO_DIFF_BI_DEFAULT ( 2 ) +#define CFG_ALLOW_MCC_GO_DIFF_BI_MAX ( 4 ) +#define CFG_ALLOW_MCC_GO_DIFF_BI_DEFAULT ( 4 ) /* * Enable/Disable Thermal Mitigation feature @@ -1674,8 +1721,63 @@ typedef enum #define CFG_DISABLE_LDPC_WITH_TXBF_AP "gDisableLDPCWithTxbfAP" #define CFG_DISABLE_LDPC_WITH_TXBF_AP_MIN ( 0 ) #define CFG_DISABLE_LDPC_WITH_TXBF_AP_MAX ( 1 ) -#define CFG_DISABLE_LDPC_WITH_TXBF_AP_DEFAULT ( 1 ) +#define CFG_DISABLE_LDPC_WITH_TXBF_AP_DEFAULT ( 0 ) #endif + +#define CFG_LIST_OF_NON_DFS_COUNTRY_CODE "gListOfNonDfsCountryCode" +#define CFG_LIST_OF_NON_DFS_COUNTRY_CODE_DEFAULT "JO,MA" + +/* + * IBSS Operating Channels for 2.4G and 5GHz channels + */ +#define CFG_IBSS_ADHOC_CHANNEL_5GHZ_NAME "gAdHocChannel5G" +#define CFG_IBSS_ADHOC_CHANNEL_5GHZ_MIN ( 36 ) +#define CFG_IBSS_ADHOC_CHANNEL_5GHZ_MAX ( 165 ) +#define CFG_IBSS_ADHOC_CHANNEL_5GHZ_DEFAULT ( 44 ) + +#define CFG_IBSS_ADHOC_CHANNEL_24GHZ_NAME "gAdHocChannel24G" +#define CFG_IBSS_ADHOC_CHANNEL_24GHZ_MIN ( 1 ) +#define CFG_IBSS_ADHOC_CHANNEL_24GHZ_MAX ( 14 ) +#define CFG_IBSS_ADHOC_CHANNEL_24GHZ_DEFAULT ( 6 ) + +#define CFG_LIST_OF_NON_11AC_COUNTRY_CODE "gListOfNon11acCountryCode" +#define CFG_LIST_OF_NON_11AC_COUNTRY_CODE_DEFAULT "RU,UA,ZA" + +#define CFG_MAX_MEDIUM_TIME "gMaxMediumTime" +#define CFG_MAX_MEDIUM_TIME_STAMIN WNI_CFG_MAX_MEDIUM_TIME_STAMIN +#define CFG_MAX_MEDIUM_TIME_STAMAX WNI_CFG_MAX_MEDIUM_TIME_STAMAX +#define CFG_MAX_MEDIUM_TIME_STADEFAULT WNI_CFG_MAX_MEDIUM_TIME_STADEF + +/* + * SAP/P2P-GO mode traffic monitor + */ +#define CFG_ENABLE_TRAFFIC_MONITOR "gEnableTrafficMonitor" +#define CFG_ENABLE_TRAFFIC_MONITOR_MIN ( 0 ) +#define CFG_ENABLE_TRAFFIC_MONITOR_MAX ( 1 ) +#define CFG_ENABLE_TRAFFIC_MONITOR_DEFAULT ( 0 ) + +#define CFG_TRAFFIC_IDLE_TIMEOUT "gTrafficIdleTimeout" +#define CFG_TRAFFIC_IDLE_TIMEOUT_MIN ( 3000 ) +#define CFG_TRAFFIC_IDLE_TIMEOUT_MAX ( 10000 ) +#define CFG_TRAFFIC_IDLE_TIMEOUT_DEFAULT ( 5000 ) + +//Macro to enable/disable dynamic timer +#define CFG_DYNAMIC_SPLIT_SCAN_NAME "gEnableDynSplitScan" +#define CFG_DYNAMIC_SPLIT_SCAN_MIN ( 0 ) +#define CFG_DYNAMIC_SPLIT_SCAN_MAX ( 1 ) +#define CFG_DYNAMIC_SPLIT_SCAN_DEFAULT ( 1 ) + +//Macro to monitor the packet count +#define CFG_SPLIT_SCAN_TRAFFIC_MONITOR_THRSHLD_NAME "gSplitScanTxRxThreshold" +#define CFG_SPLIT_SCAN_TRAFFIC_MONITOR_THRSHLD_MIN ( 10 ) +#define CFG_SPLIT_SCAN_TRAFFIC_MONITOR_THRSHLD_MAX ( 100 ) +#define CFG_SPLIT_SCAN_TRAFFIC_MONITOR_THRSHLD_DEFAULT ( 50 ) +//Macro to handle the monitor timer value in milliseconds +#define CFG_SPLIT_SCAN_TRAFFIC_MONITOR_TIMER_NAME "gSplitScanTxRxTimer" +#define CFG_SPLIT_SCAN_TRAFFIC_MONITOR_TIMER_MIN ( 1000 ) +#define CFG_SPLIT_SCAN_TRAFFIC_MONITOR_TIMER_MAX ( 10000 ) +#define CFG_SPLIT_SCAN_TRAFFIC_MONITOR_TIMER_DEFAULT ( 5000 ) + /*--------------------------------------------------------------------------- Type declarations -------------------------------------------------------------------------*/ @@ -1833,14 +1935,17 @@ typedef struct v_U32_t nActiveMinChnTimeConc; //in units of milliseconds v_U32_t nActiveMaxChnTimeConc; //in units of milliseconds v_U32_t nRestTimeConc; //in units of milliseconds - v_U8_t nNumChanCombinedConc; //number of channels combined - //in each split scan operation + v_U8_t nNumStaChanCombinedConc; //number of channels combined for + //STA in each split scan operation + v_U8_t nNumP2PChanCombinedConc; //number of channels combined for + //P2P in each split scan operation #endif v_U8_t nMaxPsPoll; v_U8_t nRssiFilterPeriod; v_BOOL_t fIgnoreDtim; + v_U8_t fMaxLIModulatedDTIM; v_U8_t nRxAnt; v_U8_t fEnableFwHeartBeatMonitoring; @@ -1873,10 +1978,20 @@ typedef struct v_BOOL_t isFastTransitionEnabled; v_U8_t RoamRssiDiff; v_U8_t nImmediateRoamRssiDiff; + v_BOOL_t isWESModeEnabled; #endif #ifdef FEATURE_WLAN_OKC v_BOOL_t isOkcIniFeatureEnabled; #endif +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + v_BOOL_t isRoamOffloadScanEnabled; +#endif + //TX and RX traffic threshold for split scan + v_U8_t txRxThresholdForSplitScan; + v_U8_t dynSplitscan; //Enable/Disable dynamic + //splitscan + //Traffic monitor timer for split scan + v_U32_t trafficMntrTmrForSplitScan; hdd_wmm_classification_t PktClassificationBasis; // DSCP or 802.1Q v_BOOL_t bImplicitQosEnabled; @@ -1924,6 +2039,7 @@ typedef struct v_BOOL_t bSingleTidRc; v_U8_t mcastBcastFilterSetting; v_BOOL_t fhostArpOffload; + v_BOOL_t fhostNSOffload; v_BOOL_t burstSizeDefinition; v_U8_t tsInfoAckPolicy; @@ -1980,6 +2096,8 @@ typedef struct #if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR) v_BOOL_t nRoamPrefer5GHz; v_BOOL_t nRoamIntraBand; + v_U8_t nProbes; + v_U16_t nRoamScanHomeAwayTime; #endif v_S31_t linkSpeedRssiMid; v_S31_t linkSpeedRssiLow; @@ -2004,7 +2122,6 @@ typedef struct v_BOOL_t ignoreDynamicDtimInP2pMode; v_U16_t configMccParam; v_U32_t numBuffAdvert; - v_U8_t ignore_chan165; v_BOOL_t enableRxSTBC; #ifdef FEATURE_WLAN_TDLS v_BOOL_t fEnableTDLSSupport; @@ -2035,6 +2152,13 @@ typedef struct v_U8_t retryLimitZero; v_U8_t retryLimitOne; v_U8_t retryLimitTwo; + v_U8_t disableAggWithBtc; + char listOfNonDfsCountryCode[128]; + v_BOOL_t enableSSR; + char listOfNon11acCountryCode[128]; + v_U32_t cfgMaxMediumTime; + v_U8_t enableTrafficMonitor; + v_U32_t trafficIdleTimeout; } hdd_config_t; /*--------------------------------------------------------------------------- Function declarations and documenation diff --git a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_cfg80211.h b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_cfg80211.h index 2468a5bb28b..638ef073ca5 100644 --- a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_cfg80211.h +++ b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_cfg80211.h @@ -77,12 +77,6 @@ #define P2P_ACTION_FRAME "\x7f\x50\x6f\x9a\x09" #define P2P_ACTION_FRAME_SIZE 5 -#define SA_QUERY_FRAME_REQ "\x08\x00" -#define SA_QUERY_FRAME_REQ_SIZE 2 - -#define SA_QUERY_FRAME_RSP "\x08\x01" -#define SA_QUERY_FRAME_RSP_SIZE 2 - #define HDD_P2P_WILDCARD_SSID "DIRECT-" //TODO Put it in proper place; #define HDD_P2P_WILDCARD_SSID_LEN 7 @@ -156,6 +150,7 @@ int wlan_hdd_crda_reg_notifier(struct wiphy *wiphy, struct regulatory_request *r int wlan_hdd_get_crda_regd_entry(struct wiphy *wiphy, hdd_config_t *pCfg); extern v_VOID_t hdd_connSetConnectionState( hdd_station_ctx_t *pHddStaCtx, eConnectionState connState ); +VOS_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,int channel); #ifdef FEATURE_WLAN_TDLS int wlan_hdd_cfg80211_send_tdls_discover_req(struct wiphy *wiphy, struct net_device *dev, u8 *peer); diff --git a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_main.h b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_main.h old mode 100644 new mode 100755 index afdf2638d3c..8ed33322645 --- a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_main.h +++ b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_main.h @@ -101,14 +101,15 @@ #endif /** Hdd Default MTU */ #define HDD_DEFAULT_MTU (1500) + /**event flags registered net device*/ -#define NET_DEVICE_REGISTERED (1<<0) -#define SME_SESSION_OPENED (1<<1) -#define INIT_TX_RX_SUCCESS (1<<2) -#define WMM_INIT_DONE (1<<3) -#define SOFTAP_BSS_STARTED (1<<4) -#define DEVICE_IFACE_OPENED (1<<5) -#define TDLS_INIT_DONE (1<<6) +#define NET_DEVICE_REGISTERED (0) +#define SME_SESSION_OPENED (1) +#define INIT_TX_RX_SUCCESS (2) +#define WMM_INIT_DONE (3) +#define SOFTAP_BSS_STARTED (4) +#define DEVICE_IFACE_OPENED (5) +#define TDLS_INIT_DONE (6) /** Maximum time(ms)to wait for disconnect to complete **/ #define WLAN_WAIT_TIME_DISCONNECT 500 @@ -129,6 +130,8 @@ /** Maximum time(ms) to wait for tdls mgmt to complete **/ #define WAIT_TIME_TDLS_MGMT 11000 +/** Maximum time(ms) to wait for tdls initiator to start direct communication **/ +#define WAIT_TIME_TDLS_INITIATOR 600 /* Maximum time to get crda entry settings */ #define CRDA_WAIT_TIME 300 @@ -162,17 +165,22 @@ #define WLAN_HDD_P2P_SOCIAL_CHANNELS 3 #define WLAN_HDD_P2P_SINGLE_CHANNEL_SCAN 1 -#ifdef WLAN_FEATURE_11W -#define WLAN_HDD_SA_QUERY_ACTION_FRAME 8 -#endif +#define WLAN_HDD_IS_SOCIAL_CHANNEL(center_freq) \ +(((center_freq) == 2412) || ((center_freq) == 2437) || ((center_freq) == 2462)) + +#define WLAN_HDD_CHANNEL_IN_UNII_1_BAND(center_freq) \ +(((center_freq) == 5180 ) || ((center_freq) == 5200) \ +|| ((center_freq) == 5220) || ((center_freq) == 5240)) #define WLAN_HDD_PUBLIC_ACTION_TDLS_DISC_RESP 14 #define WLAN_HDD_TDLS_ACTION_FRAME 12 #ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK -#define HDD_WAKE_LOCK_DURATION msecs_to_jiffies(50) +#define HDD_WAKE_LOCK_DURATION 50 //in msecs #endif -#define HDD_SAP_WAKE_LOCK_DURATION 10000 //10 sec +#define HDD_SAP_WAKE_LOCK_DURATION 10000 //in msecs + +#define HDD_MOD_EXIT_SSR_MAX_RETRIES 30 /* Maximum number of interfaces allowed(STA, P2P Device, P2P Interface) */ #define WLAN_MAX_INTERFACES 3 @@ -182,6 +190,9 @@ #define GTK_OFFLOAD_DISABLE 1 #endif +#define HDD_MAC_ADDR_LEN 6 +typedef v_U8_t tWlanHddMacAddr[HDD_MAC_ADDR_LEN]; + typedef struct hdd_tx_rx_stats_s { // start_xmit stats @@ -214,6 +225,8 @@ typedef struct hdd_tx_rx_stats_s __u32 rxDropped; __u32 rxDelivered; __u32 rxRefused; + __u32 pkt_tx_count; //TX pkt Counter used for dynamic splitscan + __u32 pkt_rx_count; //RX pkt Counter used for dynamic splitscan } hdd_tx_rx_stats_t; typedef struct hdd_chip_reset_stats_s @@ -226,14 +239,6 @@ typedef struct hdd_chip_reset_stats_s __u32 totalUnknownExceptions; } hdd_chip_reset_stats_t; -#ifdef WLAN_FEATURE_11W -typedef struct hdd_pmf_stats_s -{ - uint8 numUnprotDeauthRx; - uint8 numUnprotDisassocRx; -} hdd_pmf_stats_t; -#endif - typedef struct hdd_stats_s { tCsrSummaryStatsInfo summary_stat; @@ -244,9 +249,6 @@ typedef struct hdd_stats_s tCsrPerStaStatsInfo perStaStats; hdd_tx_rx_stats_t hddTxRxStats; hdd_chip_reset_stats_t hddChipResetStats; -#ifdef WLAN_FEATURE_11W - hdd_pmf_stats_t hddPmfStats; -#endif } hdd_stats_t; typedef enum @@ -273,6 +275,12 @@ typedef struct roaming_info_s { HDD_ROAM_STATE roamingState; vos_event_t roamingEvent; + + tWlanHddMacAddr bssid; + tWlanHddMacAddr peerMac; + tANI_U32 roamId; + eRoamCmdStatus roamStatus; + v_BOOL_t deferKeyComplete; } roaming_info_t; @@ -522,8 +530,6 @@ struct hdd_station_ctx roaming_info_t roam_info; - v_BOOL_t bSendDisconnect; - #if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR) int ft_carrier_on; #endif @@ -800,14 +806,6 @@ struct hdd_adapter_s v_BOOL_t higherDtimTransition; }; -typedef struct hdd_dynamic_mcbcfilter_s -{ - v_BOOL_t enableCfg; - v_U8_t mcastBcastFilterSetting; - v_BOOL_t enableSuspend; - v_U8_t mcBcFilterSuspend; -}hdd_dynamic_mcbcfilter_t; - #define WLAN_HDD_GET_STATION_CTX_PTR(pAdapter) (&(pAdapter)->sessionCtx.station) #define WLAN_HDD_GET_AP_CTX_PTR(pAdapter) (&(pAdapter)->sessionCtx.ap) #define WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter) (&(pAdapter)->sessionCtx.station.WextState) @@ -816,7 +814,12 @@ typedef struct hdd_dynamic_mcbcfilter_s #define WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter) (&(pAdapter)->sessionCtx.ap.HostapdState) #define WLAN_HDD_GET_CFG_STATE_PTR(pAdapter) (&(pAdapter)->cfg80211State) #ifdef FEATURE_WLAN_TDLS -#define WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter) ((tdlsCtx_t*)(pAdapter)->sessionCtx.station.pHddTdlsCtx) +#define WLAN_HDD_IS_TDLS_SUPPORTED_ADAPTER(pAdapter) \ + (((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) && \ + (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode)) ? 0 : 1) +#define WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter) \ + ((WLAN_HDD_IS_TDLS_SUPPORTED_ADAPTER(pAdapter)) ? \ + (tdlsCtx_t*)(pAdapter)->sessionCtx.station.pHddTdlsCtx : NULL) #endif typedef struct hdd_adapter_list_node @@ -832,6 +835,15 @@ typedef struct hdd_priv_data_s int total_len; }hdd_priv_data_t; +typedef struct +{ + vos_timer_t trafficTimer; + atomic_t isActiveMode; + v_U8_t isInitialized; + vos_lock_t trafficLock; + v_TIME_t lastFrameTs; +}hdd_traffic_monitor_t; + /** Adapter stucture definition */ struct hdd_context_s @@ -932,8 +944,6 @@ struct hdd_context_s /* Number of times riva restarted */ v_U32_t hddRivaResetStats; - hdd_dynamic_mcbcfilter_t dynamic_mcbc_filter; - /* Can we allow AMP connection right now*/ v_BOOL_t isAmpAllowed; @@ -978,6 +988,33 @@ struct hdd_context_s tANI_U16 connected_peer_count; tdls_scan_context_t tdls_scan_ctxt; #endif + + hdd_traffic_monitor_t traffic_monitor; + + /* MC/BC Filter state variable + * This always contains the value that is currently + * configured + * */ + v_U8_t configuredMcastBcastFilter; + + /* Use below lock to protect access to isSchedScanUpdatePending + * since it will be accessed in two different contexts. + */ + spinlock_t schedScan_lock; + + v_U8_t sus_res_mcastbcast_filter; + + // Flag keeps track of wiphy suspend/resume + v_BOOL_t isWiphySuspended; + + // Indicates about pending sched_scan results + v_BOOL_t isSchedScanUpdatePending; + /* + * TX_rx_pkt_count_timer + */ + vos_timer_t tx_rx_trafficTmr; + v_U8_t drvr_miracast; + v_U8_t issplitscan_enabled; }; @@ -1036,6 +1073,7 @@ void hdd_abort_mac_scan(hdd_context_t *pHddCtx); void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter ); void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter ); v_BOOL_t is_crda_regulatory_entry_valid(void); +void crda_regulatory_entry_default(v_U8_t *countryCode, int domain_id); void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode); void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode); void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter); @@ -1048,10 +1086,15 @@ void hdd_set_ssr_required(e_hdd_ssr_required value); VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx); VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type); -eHalStatus hdd_smeCloseSessionCallback(void *pContext); void wlan_hdd_cfg80211_update_reg_info(struct wiphy *wiphy); VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx); void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx); void hdd_set_pwrparams(hdd_context_t *pHddCtx); void hdd_reset_pwrparams(hdd_context_t *pHddCtx); +int wlan_hdd_validate_context(hdd_context_t *pHddCtx); +#ifdef WLAN_FEATURE_PACKET_FILTERING +int wlan_hdd_setIPv6Filter(hdd_context_t *pHddCtx, tANI_U8 filterType, tANI_U8 sessionId); +#endif +VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx); + #endif // end #if !defined( WLAN_HDD_MAIN_H ) diff --git a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_p2p.h b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_p2p.h index 8bc873de978..ff4463a4b5d 100644 --- a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_p2p.h +++ b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_p2p.h @@ -64,10 +64,6 @@ #define P2P_WILDCARD_SSID_LEN 7 #define P2P_WILDCARD_SSID "DIRECT-" -#ifdef WLAN_FEATURE_11W -#define WLAN_HDD_SET_WEP_FRM_FC(__fc__) ( (__fc__) = ((__fc__) | 0x40)) -#endif //WLAN_FEATURE_11W - enum hdd_rx_flags { HDD_RX_FLAG_DECRYPTED = 1 << 0, HDD_RX_FLAG_MMIC_STRIPPED = 1 << 1, diff --git a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_packet_filtering.h b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_packet_filtering.h index 70896530929..c2b36b66838 100644 --- a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_packet_filtering.h +++ b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_packet_filtering.h @@ -36,10 +36,20 @@ #ifdef WLAN_FEATURE_PACKET_FILTERING + #define HDD_MAX_CMP_PER_PACKET_FILTER 5 +#define HDD_FILTER_IPV6_MC_UC 1 +#define HDD_FILTER_IPV6_MC 0 +#define HDD_FILTER_ID_IPV6_MC 10 +#define HDD_FILTER_ID_IPV6_UC 11 + +#define HDD_IPV6_MC_CMP_DATA 0x33 +#define HDD_IPV6_UC_CMP_DATA 0x01 +#define HDD_IPV6_CMP_DATA_0 0x86 +#define HDD_IPV6_CMP_DATA_1 0xDD -#define HDD_WLAN_MAC_ADDR_LEN 6 -#define HDD_MAX_NUM_MULTICAST_ADDRESS 10 +#define HDD_WLAN_MAC_ADDR_LEN 6 +#define HDD_MAX_NUM_MULTICAST_ADDRESS 10 typedef enum { diff --git a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_power.h b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_power.h index 5b24ae8dd66..a1498a12ebc 100644 --- a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_power.h +++ b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_power.h @@ -1,43 +1,28 @@ /* - * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. - * - * Previously licensed under the ISC license by Qualcomm Atheros, Inc. - * - * - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all - * copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ + * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. +*/ /* - * Copyright (c) 2012, The Linux Foundation. All rights reserved. - * - * Previously licensed under the ISC license by Qualcomm Atheros, Inc. - * - * - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all - * copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ +* Copyright (c) 2012 Qualcomm Atheros, Inc. +* All Rights Reserved. +* Qualcomm Atheros Confidential and Proprietary. +*/ #ifndef __WLAN_HDD_POWER_H #define __WLAN_HDD_POWER_H @@ -47,9 +32,9 @@ \file wlan_hdd_power.h \brief Linux HDD Power - Copyright 2008 (c) Qualcomm, Incorporated. + Copyright 2008 (c) Qualcomm Technologies, Inc. All Rights Reserved. - Qualcomm Confidential and Proprietary. + Qualcomm Technologies Confidential and Proprietary. ==========================================================================*/ @@ -106,5 +91,17 @@ VOS_STATUS hdd_wlan_re_init(void); void hdd_conf_mcastbcast_filter(hdd_context_t* pHddCtx, v_BOOL_t setfilter); -VOS_STATUS hdd_conf_hostarpoffload(hdd_adapter_t* pAdapter, v_BOOL_t fenable); +VOS_STATUS hdd_conf_arp_offload(hdd_adapter_t* pAdapter, v_BOOL_t fenable); +/* + * Function: hdd_conf_hostoffload + * Central function to configure the supported offloads, + * either enable or disable them. + */ +void hdd_conf_hostoffload(hdd_adapter_t * pAdapter, v_BOOL_t fenable); +#ifdef WLAN_FEATURE_GTK_OFFLOAD +void hdd_conf_gtk_offload(hdd_adapter_t *pAdapter, v_BOOL_t fenable); +#endif +#ifdef WLAN_NS_OFFLOAD +void hdd_conf_ns_offload(hdd_adapter_t *pAdapter, v_BOOL_t fenable); +#endif #endif // if !defined __WLAN_QCT_DRIVER_H diff --git a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_tdls.h b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_tdls.h index ac3ca9611cb..c0e8bdadae8 100644 --- a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_tdls.h +++ b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_tdls.h @@ -51,6 +51,7 @@ should not be more than 2000 */ #define TDLS_CTX_MAGIC 0x54444c53 // "TDLS" #define TDLS_MAX_SCAN_SCHEDULE 10 +#define TDLS_MAX_SCAN_REJECT 5 #define TDLS_DELAY_SCAN_PER_CONNECTION 100 #define TDLS_IS_CONNECTED(peer) \ @@ -79,6 +80,7 @@ typedef struct struct cfg80211_scan_request *scan_request; int magic; int attempt; + int reject; struct delayed_work tdls_scan_work; } tdls_scan_context_t; @@ -122,19 +124,25 @@ typedef struct { tANI_U16 rssi_thres; } tdls_rssi_config_t; +struct _hddTdlsPeer_t; typedef struct { struct list_head peer_list[256]; hdd_adapter_t *pAdapter; +#ifdef TDLS_USE_SEPARATE_DISCOVERY_TIMER vos_timer_t peerDiscoverTimer; +#endif vos_timer_t peerUpdateTimer; vos_timer_t peerDiscoveryTimeoutTimer; tdls_config_params_t threshold_config; tANI_S32 discovery_peer_cnt; tANI_U32 discovery_sent_cnt; tANI_S8 ap_rssi; + struct _hddTdlsPeer_t *curr_candidate; + struct work_struct implicit_setup; + v_U32_t magic; } tdlsCtx_t; -typedef struct { +typedef struct _hddTdlsPeer_t { struct list_head node; tdlsCtx_t *pHddTdlsCtx; tSirMacAddr peerMac; @@ -149,6 +157,7 @@ typedef struct { tANI_U16 tx_pkt; tANI_U16 rx_pkt; vos_timer_t peerIdleTimer; + vos_timer_t initiatorWaitTimeoutTimer; } hddTdlsPeer_t; typedef struct { @@ -174,6 +183,8 @@ int wlan_hdd_tdls_set_sta_id(hdd_adapter_t *pAdapter, u8 *mac, u8 staId); hddTdlsPeer_t *wlan_hdd_tdls_find_peer(hdd_adapter_t *pAdapter, u8 *mac); +hddTdlsPeer_t *wlan_hdd_tdls_find_all_peer(hdd_context_t *pHddCtx, u8 *mac); + hddTdlsPeer_t *wlan_hdd_tdls_get_peer(hdd_adapter_t *pAdapter, u8 *mac); int wlan_hdd_tdls_set_cap(hdd_adapter_t *pAdapter, u8* mac, tTDLSCapType cap); @@ -214,14 +225,12 @@ void wlan_hdd_tdls_check_bmps(hdd_adapter_t *pAdapter); u8 wlan_hdd_tdls_is_peer_progress(hdd_adapter_t *pAdapter, u8 *mac); -u8 wlan_hdd_tdls_is_progress(hdd_adapter_t *pAdapter, u8* mac, u8 skip_self); +hddTdlsPeer_t *wlan_hdd_tdls_is_progress(hdd_context_t *pHddCtx, u8* mac, u8 skip_self, tANI_BOOLEAN mutexLock); void wlan_hdd_tdls_set_mode(hdd_context_t *pHddCtx, eTDLSSupportMode tdls_mode, v_BOOL_t bUpdateLast); -void wlan_hdd_tdls_pre_setup(tdlsCtx_t *pHddTdlsCtx, hddTdlsPeer_t *curr_peer); - tANI_U32 wlan_hdd_tdls_discovery_sent_cnt(hdd_context_t *pHddCtx); void wlan_hdd_tdls_check_power_save_prohibited(hdd_adapter_t *pAdapter); diff --git a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_tx_rx.h b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_tx_rx.h index efd8e22e983..13d17f17886 100644 --- a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_tx_rx.h +++ b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_tx_rx.h @@ -254,4 +254,12 @@ void hdd_mon_tx_mgmt_pkt(hdd_adapter_t* pAdapter); ===========================================================================*/ void hdd_mon_tx_work_queue(struct work_struct *work); +/**============================================================================ + @brief hdd_tx_rx_pkt_cnt_stat_timer_handler() - + Timer handler to check enable/disable split scan + @param pHddStaCtx : Hdd adapter + @return : VOS_STATUS_SUCCESS/VOS_STATUS_E_FAILURE + ===========================================================================*/ +void hdd_tx_rx_pkt_cnt_stat_timer_handler( void *pAdapter); + #endif // end #if !defined( WLAN_HDD_TX_RX_H ) diff --git a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_wext.h b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_wext.h index fbd2c145387..07135f8454b 100644 --- a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_wext.h +++ b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_wext.h @@ -412,6 +412,9 @@ VOS_STATUS wlan_hdd_get_classAstats(hdd_adapter_t *pAdapter); VOS_STATUS wlan_hdd_get_station_stats(hdd_adapter_t *pAdapter); VOS_STATUS wlan_hdd_get_rssi(hdd_adapter_t *pAdapter, v_S7_t *rssi_value); + +void hdd_wmm_tx_snapshot(hdd_adapter_t *pAdapter); + #ifdef FEATURE_WLAN_TDLS VOS_STATUS iw_set_tdls_params(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra, int nOffset); #endif diff --git a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_wowl.h b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_wowl.h index 1725c59642f..d2d672d3ecb 100644 --- a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_wowl.h +++ b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_wowl.h @@ -180,4 +180,11 @@ v_BOOL_t hdd_exit_wowl (hdd_adapter_t*pAdapter); ===========================================================================*/ v_BOOL_t hdd_init_wowl (hdd_adapter_t* pAdapter); +/**============================================================================ + @brief hdd_parse_hex() - function returns integer equivalent of hexa decimal + + @return : integer equivalent of hexa decimal + ===========================================================================*/ +int hdd_parse_hex(unsigned char c); + #endif /* #ifndef _WLAN_HDD_WOWL_H */ diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_assoc.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_assoc.c old mode 100644 new mode 100755 index 6f5798738fa..c68522e4113 --- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_assoc.c +++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_assoc.c @@ -109,9 +109,6 @@ v_U8_t ccpRSNOui05[ HDD_RSN_OUI_SIZE ] = { 0x00, 0x0F, 0xAC, 0x05 }; // WEP-104 #ifdef FEATURE_WLAN_CCX v_U8_t ccpRSNOui06[ HDD_RSN_OUI_SIZE ] = { 0x00, 0x40, 0x96, 0x00 }; // CCKM #endif /* FEATURE_WLAN_CCX */ -#ifdef WLAN_FEATURE_11W -v_U8_t ccpRSNOui07[ HDD_RSN_OUI_SIZE ] = { 0x00, 0x0F, 0xAC, 0x06 }; // RSN-PSK-SHA256 -#endif #if defined(WLAN_FEATURE_VOWIFI_11R) // Offset where the EID-Len-IE, start. @@ -121,12 +118,11 @@ v_U8_t ccpRSNOui07[ HDD_RSN_OUI_SIZE ] = { 0x00, 0x0F, 0xAC, 0x06 }; // RSN-PSK- #define BEACON_FRAME_IES_OFFSET 12 -#ifdef WLAN_FEATURE_11W -void hdd_indicateUnprotMgmtFrame(hdd_adapter_t *pAdapter, - tANI_U32 nFrameLength, - tANI_U8* pbFrames, - tANI_U8 frameType ); -#endif +static eHalStatus hdd_RoamSetKeyCompleteHandler( hdd_adapter_t *pAdapter, + tCsrRoamInfo *pRoamInfo, + tANI_U32 roamId, + eRoamCmdStatus roamStatus, + eCsrRoamResult roamResult ); v_VOID_t hdd_connSetConnectionState( hdd_station_ctx_t *pHddStaCtx, eConnectionState connState ) @@ -299,6 +295,9 @@ void hdd_connSaveConnectInfo( hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo, // Save the ssid for the connection vos_mem_copy( &pHddStaCtx->conn_info.SSID.SSID, &pRoamInfo->u.pConnectedProfile->SSID, sizeof( tSirMacSSid ) ); + + // Save dot11mode in which STA associated to AP + pHddStaCtx->conn_info.dot11Mode = pRoamInfo->u.pConnectedProfile->dot11Mode; } } @@ -392,7 +391,6 @@ void hdd_SendFTEvent(hdd_adapter_t *pAdapter) struct cfg80211_ft_event_params ftEvent; v_U8_t ftIe[DOT11F_IE_FTINFO_MAX_LEN]; v_U8_t ricIe[DOT11F_IE_RICDESCRIPTOR_MAX_LEN]; - v_U8_t target_ap[SIR_MAC_ADDR_LENGTH]; struct net_device *dev = pAdapter->dev; #else char *buff; @@ -426,9 +424,9 @@ void hdd_SendFTEvent(hdd_adapter_t *pAdapter) return; } - vos_mem_copy(target_ap, ftIe, SIR_MAC_ADDR_LENGTH); + sme_SetFTPreAuthState(pHddCtx->hHal, TRUE); - ftEvent.target_ap = target_ap; + ftEvent.target_ap = ftIe; ftEvent.ies = (u8 *)(ftIe + SIR_MAC_ADDR_LENGTH); ftEvent.ies_len = auth_resp_len - SIR_MAC_ADDR_LENGTH; @@ -807,10 +805,8 @@ static eHalStatus hdd_DisConnectHandler( hdd_adapter_t *pAdapter, tCsrRoamInfo * //Enable BMPS // In case of JB, as Change-Iface may or maynot be called for p2p0 - // Enable BMPS/IMPS in case P2P_CLIENT disconnected - if(((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) || - (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)) && - (vos_concurrent_sessions_running())) + // Enable BMPS/IMPS in case P2P_CLIENT disconnected + if(VOS_STATUS_SUCCESS == hdd_issta_p2p_clientconnected(pHddCtx)) { //Enable BMPS only of other Session is P2P Client hdd_context_t *pHddCtx = NULL; @@ -826,20 +822,12 @@ static eHalStatus hdd_DisConnectHandler( hdd_adapter_t *pAdapter, tCsrRoamInfo * if((0 == pHddCtx->no_of_sessions[VOS_STA_SAP_MODE]) && (0 == pHddCtx->no_of_sessions[VOS_P2P_GO_MODE])) { - if (pHddCtx->hdd_wlan_suspended) - { - if(WLAN_HDD_INFRA_STATION == pAdapter->device_mode) - { - hdd_reset_pwrparams(pHddCtx); - } - else - { - hdd_set_pwrparams(pHddCtx); - } - } - + if (pHddCtx->hdd_wlan_suspended) + { + hdd_set_pwrparams(pHddCtx); + } hdd_enable_bmps_imps(pHddCtx); - } + } } } } @@ -892,7 +880,8 @@ static VOS_STATUS hdd_roamRegisterSTA( hdd_adapter_t *pAdapter, v_BOOL_t fConnected; hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); - + hdd_config_t *cfg_param = pHddCtx->cfg_ini; + // Get the Station ID from the one saved during the assocation. staDesc.ucSTAId = staId; @@ -1008,35 +997,39 @@ static VOS_STATUS hdd_roamRegisterSTA( hdd_adapter_t *pAdapter, return vosStatus; } - // if ( WPA ), tell TL to go to 'connected' and after keys come to the driver, - // then go to 'authenticated'. For all other authentication types (those that do - // not require upper layer authentication) we can put TL directly into 'authenticated' - // state. - + if ( cfg_param->dynSplitscan && + ( VOS_TIMER_STATE_RUNNING != + vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))) + { + vos_timer_start(&pHddCtx->tx_rx_trafficTmr, + cfg_param->trafficMntrTmrForSplitScan); + } + // if (WPA), tell TL to go to 'connected' and after keys come to the driver, + // then go to 'authenticated'. For all other authentication types + // (those that donot require upper layer authentication) we can put + // TL directly into 'authenticated' state. + VOS_ASSERT( fConnected ); - + if ( !pRoamInfo->fAuthRequired ) { - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED, - "open/shared auth StaId= %d. Changing TL state to AUTHENTICATED at Join time", pHddStaCtx->conn_info.staId[ 0 ] ); - // Connections that do not need Upper layer auth, transition TL directly - // to 'Authenticated' state. - vosStatus = WLANTL_ChangeSTAState( pHddCtx->pvosContext, staDesc.ucSTAId, + // to 'Authenticated' state. + vosStatus = WLANTL_ChangeSTAState( pHddCtx->pvosContext, staDesc.ucSTAId, WLANTL_STA_AUTHENTICATED ); - + pHddStaCtx->conn_info.uIsAuthenticated = VOS_TRUE; - } + } else { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED, - "ULA auth StaId= %d. Changing TL state to CONNECTED at Join time", pHddStaCtx->conn_info.staId[ 0 ] ); - - vosStatus = WLANTL_ChangeSTAState( pHddCtx->pvosContext, staDesc.ucSTAId, + "ULA auth StaId= %d. Changing TL state to CONNECTED at Join time", + pHddStaCtx->conn_info.staId[0] ); + vosStatus = WLANTL_ChangeSTAState( pHddCtx->pvosContext, staDesc.ucSTAId, WLANTL_STA_CONNECTED ); - pHddStaCtx->conn_info.uIsAuthenticated = VOS_FALSE; - } + } + return( vosStatus ); } @@ -1093,8 +1086,33 @@ static void hdd_SendReAssocEvent(struct net_device *dev, hdd_adapter_t *pAdapter kfree(rspRsnIe); } -static eHalStatus hdd_AssociationCompletionHandler( hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo, - tANI_U32 roamId, eRoamCmdStatus roamStatus, +void hdd_PerformRoamSetKeyComplete(hdd_adapter_t *pAdapter) +{ + eHalStatus halStatus = eHAL_STATUS_SUCCESS; + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + tCsrRoamInfo roamInfo; + roamInfo.fAuthRequired = FALSE; + vos_mem_copy(roamInfo.bssid, + pHddStaCtx->roam_info.bssid, + WNI_CFG_BSSID_LEN); + vos_mem_copy(roamInfo.peerMac, + pHddStaCtx->roam_info.peerMac, + WNI_CFG_BSSID_LEN); + + halStatus = hdd_RoamSetKeyCompleteHandler(pAdapter, + &roamInfo, + pHddStaCtx->roam_info.roamId, + pHddStaCtx->roam_info.roamStatus, + eCSR_ROAM_RESULT_AUTHENTICATED); + if (halStatus != eHAL_STATUS_SUCCESS) + { + hddLog(LOGE, "%s: Set Key complete failure", __func__); + } + pHddStaCtx->roam_info.deferKeyComplete = FALSE; +} + +static eHalStatus hdd_AssociationCompletionHandler( hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo, + tANI_U32 roamId, eRoamCmdStatus roamStatus, eCsrRoamResult roamResult ) { struct net_device *dev = pAdapter->dev; @@ -1257,6 +1275,21 @@ static eHalStatus hdd_AssociationCompletionHandler( hdd_adapter_t *pAdapter, tCs cfg80211_roamed(dev,chan, pRoamInfo->bssid, pFTAssocReq, assocReqlen, pFTAssocRsp, assocRsplen, GFP_KERNEL); + if (sme_GetFTPTKState(WLAN_HDD_GET_HAL_CTX(pAdapter))) + { + sme_SetFTPTKState(WLAN_HDD_GET_HAL_CTX(pAdapter), FALSE); + pRoamInfo->fAuthRequired = FALSE; + + vos_mem_copy(pHddStaCtx->roam_info.bssid, + pRoamInfo->bssid, + HDD_MAC_ADDR_LEN); + vos_mem_copy(pHddStaCtx->roam_info.peerMac, + pRoamInfo->peerMac, + HDD_MAC_ADDR_LEN); + pHddStaCtx->roam_info.roamId = roamId; + pHddStaCtx->roam_info.roamStatus = roamStatus; + pHddStaCtx->roam_info.deferKeyComplete = TRUE; + } } else { @@ -1267,7 +1300,6 @@ static eHalStatus hdd_AssociationCompletionHandler( hdd_adapter_t *pAdapter, tCs pFTAssocRsp, assocRsplen, WLAN_STATUS_SUCCESS, GFP_KERNEL); - cfg80211_put_bss(bss); } } else @@ -1297,9 +1329,9 @@ static eHalStatus hdd_AssociationCompletionHandler( hdd_adapter_t *pAdapter, tCs WLAN_STATUS_SUCCESS, GFP_KERNEL); - cfg80211_put_bss(bss); } } + cfg80211_put_bss(bss); // Register the Station with TL after associated... vosStatus = hdd_roamRegisterSTA( pAdapter, pRoamInfo, @@ -1320,8 +1352,12 @@ static eHalStatus hdd_AssociationCompletionHandler( hdd_adapter_t *pAdapter, tCs //Reassoc successfully if( pRoamInfo->fAuthRequired ) { - vosStatus = WLANTL_ChangeSTAState( pHddCtx->pvosContext, pHddStaCtx->conn_info.staId[ 0 ], - WLANTL_STA_CONNECTED ); + vosStatus = WLANTL_ChangeSTAState( pHddCtx->pvosContext, + pHddStaCtx->conn_info.staId[ 0 ], + WLANTL_STA_CONNECTED ); + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: staId: %d Changing TL state to CONNECTED", + __func__, pHddStaCtx->conn_info.staId[0]); pHddStaCtx->conn_info.uIsAuthenticated = VOS_FALSE; } else @@ -1329,8 +1365,9 @@ static eHalStatus hdd_AssociationCompletionHandler( hdd_adapter_t *pAdapter, tCs VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "%s: staId: %d Changing TL state to AUTHENTICATED", __func__, pHddStaCtx->conn_info.staId[ 0 ] ); - vosStatus = WLANTL_ChangeSTAState( pHddCtx->pvosContext, pHddStaCtx->conn_info.staId[ 0 ], - WLANTL_STA_AUTHENTICATED ); + vosStatus = WLANTL_ChangeSTAState( pHddCtx->pvosContext, + pHddStaCtx->conn_info.staId[ 0 ], + WLANTL_STA_AUTHENTICATED ); pHddStaCtx->conn_info.uIsAuthenticated = VOS_TRUE; } } @@ -1346,10 +1383,7 @@ static eHalStatus hdd_AssociationCompletionHandler( hdd_adapter_t *pAdapter, tCs "Cannot register STA with TL. Failed with vosStatus = %d [%08lX]", vosStatus, vosStatus ); } -#ifdef WLAN_FEATURE_11W - vos_mem_zero( &pAdapter->hdd_stats.hddPmfStats, - sizeof(pAdapter->hdd_stats.hddPmfStats) ); -#endif + // Start the Queue netif_tx_wake_all_queues(dev); } @@ -1398,24 +1432,16 @@ static eHalStatus hdd_AssociationCompletionHandler( hdd_adapter_t *pAdapter, tCs if(NULL != pHddCtx) { - //Only P2P Client is there Enable Bmps back - if((0 == pHddCtx->no_of_sessions[VOS_STA_SAP_MODE]) && - (0 == pHddCtx->no_of_sessions[VOS_P2P_GO_MODE])) - { - if (pHddCtx->hdd_wlan_suspended) - { - if(WLAN_HDD_INFRA_STATION == pAdapter->device_mode) - { - hdd_reset_pwrparams(pHddCtx); - } - else + //Only P2P Client is there Enable Bmps back + if((0 == pHddCtx->no_of_sessions[VOS_STA_SAP_MODE]) && + (0 == pHddCtx->no_of_sessions[VOS_P2P_GO_MODE])) + { + if (pHddCtx->hdd_wlan_suspended) { - hdd_set_pwrparams(pHddCtx); + hdd_set_pwrparams(pHddCtx); } - } - - hdd_enable_bmps_imps(pHddCtx); - } + hdd_enable_bmps_imps(pHddCtx); + } } } } @@ -1458,7 +1484,6 @@ static eHalStatus hdd_AssociationCompletionHandler( hdd_adapter_t *pAdapter, tCs netif_tx_disable(dev); netif_carrier_off(dev); - } return eHAL_STATUS_SUCCESS; @@ -1627,6 +1652,12 @@ static eHalStatus hdd_RoamSetKeyCompleteHandler( hdd_adapter_t *pAdapter, tCsrRo hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); ENTER(); + + if (NULL == pRoamInfo) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "pRoamInfo is NULL"); + return eHAL_STATUS_FAILURE; + } // if ( WPA ), tell TL to go to 'authenticated' after the keys are set. // then go to 'authenticated'. For all other authentication types (those that do // not require upper layer authentication) we can put TL directly into 'authenticated' @@ -1636,27 +1667,32 @@ static eHalStatus hdd_RoamSetKeyCompleteHandler( hdd_adapter_t *pAdapter, tCsrRo if( fConnected ) { // TODO: Considering getting a state machine in HDD later. - // This routuine is invoked twice. 1)set PTK 2)set GTK. The folloing if statement will be - // TRUE when setting GTK. At this time we don't handle the state in detail. + // This routuine is invoked twice. 1)set PTK 2)set GTK. + // The folloing if statement will be TRUE when setting GTK. + // At this time we don't handle the state in detail. // Related CR: 174048 - TL not in authenticated state - if(( eCSR_ROAM_RESULT_AUTHENTICATED == roamResult ) && (pRoamInfo != NULL) && !pRoamInfo->fAuthRequired) + + if ( ( eCSR_ROAM_RESULT_AUTHENTICATED == roamResult ) && + (pRoamInfo != NULL) && !pRoamInfo->fAuthRequired ) { - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED, - "Key set for StaId= %d. Changing TL state to AUTHENTICATED", pHddStaCtx->conn_info.staId[ 0 ] ); - - // Connections that do not need Upper layer authentication, transition TL - // to 'Authenticated' state after the keys are set. - vosStatus = WLANTL_ChangeSTAState( pHddCtx->pvosContext, pHddStaCtx->conn_info.staId[ 0 ], + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED, "Key set " + "for StaId= %d. Changing TL state to AUTHENTICATED", + pHddStaCtx->conn_info.staId[ 0 ] ); + + // Connections that do not need Upper layer authentication, + // transition TL to 'Authenticated' state after the keys are set. + vosStatus = WLANTL_ChangeSTAState( pHddCtx->pvosContext, + pHddStaCtx->conn_info.staId[ 0 ], WLANTL_STA_AUTHENTICATED ); - + pHddStaCtx->conn_info.uIsAuthenticated = VOS_TRUE; } else { vosStatus = WLANTL_STAPtkInstalled( pHddCtx->pvosContext, - pHddStaCtx->conn_info.staId[ 0 ]); + pHddStaCtx->conn_info.staId[ 0 ]); } - + pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE; } else @@ -1826,6 +1862,8 @@ VOS_STATUS hdd_roamRegisterTDLSSTA( hdd_adapter_t *pAdapter, WLAN_STADescType staDesc = {0}; eCsrEncryptionType connectedCipherAlgo = eCSR_ENCRYPT_TYPE_UNKNOWN; v_BOOL_t fConnected = FALSE; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + hdd_config_t *cfg_param = pHddCtx->cfg_ini; fConnected = hdd_connGetConnectedCipherAlgo( pHddStaCtx, &connectedCipherAlgo ); if (!fConnected) { @@ -1880,7 +1918,7 @@ VOS_STATUS hdd_roamRegisterTDLSSTA( hdd_adapter_t *pAdapter, staDesc.ucIsReplayCheckValid = VOS_FALSE; #endif - staDesc.ucInitState = WLANTL_STA_AUTHENTICATED ; + staDesc.ucInitState = WLANTL_STA_CONNECTED ; /* Register the Station with TL... */ vosStatus = WLANTL_RegisterSTAClient( pVosContext, @@ -1891,11 +1929,19 @@ VOS_STATUS hdd_roamRegisterTDLSSTA( hdd_adapter_t *pAdapter, if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) ) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "WLANTL_RegisterSTAClient() failed to register. \ - Status= %d [0x%08lX]", vosStatus, vosStatus ); - return vosStatus; - } - + "%s: WLANTL_RegisterSTAClient() failed to register. \ + Status= %d [0x%08lX]", __func__, vosStatus, vosStatus ); + return vosStatus; + } + + if ( cfg_param->dynSplitscan && + ( VOS_TIMER_STATE_RUNNING != + vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr)) ) + { + vos_timer_start(&pHddCtx->tx_rx_trafficTmr, + cfg_param->trafficMntrTmrForSplitScan); + } + return( vosStatus ); } @@ -1993,16 +2039,20 @@ eHalStatus hdd_RoamTdlsStatusUpdateHandler(hdd_adapter_t *pAdapter, } (WLAN_HDD_GET_CTX(pAdapter))->sta_to_adapter[pRoamInfo->staId] = pAdapter; - /* store the ucast signature which will be used later when - registering to TL - */ + /* store the ucast signature , if required for further reference. */ + wlan_hdd_tdls_set_signature( pAdapter, pRoamInfo->peerMac, pRoamInfo->ucastSig ); + /* start TDLS client registration with TL */ + status = hdd_roamRegisterTDLSSTA( pAdapter, + pRoamInfo->peerMac, + pRoamInfo->staId, + pRoamInfo->ucastSig); } else { status = eHAL_STATUS_FAILURE; VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "no availalbe slot in conn_info. staId %d cannot be stored", pRoamInfo->staId); + "%s: no available slot in conn_info. staId %d cannot be stored", __func__, pRoamInfo->staId); } pAdapter->tdlsAddStaStatus = status; } @@ -2098,8 +2148,8 @@ eHalStatus hdd_RoamTdlsStatusUpdateHandler(hdd_adapter_t *pAdapter, status = eHAL_STATUS_SUCCESS ; } - wlan_hdd_tdls_check_bmps(pAdapter); } + wlan_hdd_tdls_check_bmps(pAdapter); break ; } default: @@ -2120,6 +2170,7 @@ eHalStatus hdd_smeRoamCallback( void *pContext, tCsrRoamInfo *pRoamInfo, tANI_U3 hdd_wext_state_t *pWextState = NULL; hdd_station_ctx_t *pHddStaCtx = NULL; VOS_STATUS status = VOS_STATUS_SUCCESS; + hdd_context_t *pHddCtx = NULL; VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "CSR Callback: status= %d result= %d roamID=%ld", @@ -2135,8 +2186,9 @@ eHalStatus hdd_smeRoamCallback( void *pContext, tCsrRoamInfo *pRoamInfo, tANI_U3 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); - if ((NULL == pWextState) || (NULL == pHddStaCtx)) + if ((NULL == pWextState) || (NULL == pHddStaCtx) || (NULL == pHddCtx)) { VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "invalid WEXT state or HDD station context"); @@ -2240,13 +2292,16 @@ eHalStatus hdd_smeRoamCallback( void *pContext, tCsrRoamInfo *pRoamInfo, tANI_U3 case eCSR_ROAM_LOSTLINK: case eCSR_ROAM_DISASSOCIATED: { - hdd_context_t* pHddCtx = (hdd_context_t*)pAdapter->pHddCtx; VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "****eCSR_ROAM_DISASSOCIATED****"); halStatus = hdd_DisConnectHandler( pAdapter, pRoamInfo, roamId, roamStatus, roamResult ); /* Check if Mcast/Bcast Filters are set, if yes clear the filters here */ - if ((WLAN_HDD_GET_CTX(pAdapter))->hdd_mcastbcast_filter_set == TRUE) { - hdd_conf_mcastbcast_filter((WLAN_HDD_GET_CTX(pAdapter)), FALSE); + if (pHddCtx->hdd_mcastbcast_filter_set == TRUE) + { + hdd_conf_mcastbcast_filter(pHddCtx, FALSE); + pHddCtx->configuredMcastBcastFilter = + pHddCtx->sus_res_mcastbcast_filter; + (WLAN_HDD_GET_CTX(pAdapter))->hdd_mcastbcast_filter_set = FALSE; } #ifdef WLAN_FEATURE_PACKET_FILTERING @@ -2272,11 +2327,13 @@ eHalStatus hdd_smeRoamCallback( void *pContext, tCsrRoamInfo *pRoamInfo, tANI_U3 case eCSR_ROAM_ASSOCIATION_COMPLETION: VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "****eCSR_ROAM_ASSOCIATION_COMPLETION****"); - if ( (roamResult != eCSR_ROAM_RESULT_ASSOCIATED) - && ( (pWextState->roamProfile.EncryptionType.encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP40_STATICKEY) - || (pWextState->roamProfile.EncryptionType.encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104_STATICKEY) - ) - && (eCSR_AUTH_TYPE_SHARED_KEY != pWextState->roamProfile.AuthType.authType[0]) + if ( (roamResult != eCSR_ROAM_RESULT_ASSOCIATED) && + ( (pWextState->roamProfile.EncryptionType.encryptionType[0] == + eCSR_ENCRYPT_TYPE_WEP40) || + (pWextState->roamProfile.EncryptionType.encryptionType[0] == + eCSR_ENCRYPT_TYPE_WEP104) + ) && + (eCSR_AUTH_TYPE_SHARED_KEY != pWextState->roamProfile.AuthType.authType[0]) ) { v_U32_t roamId = 0; @@ -2303,7 +2360,7 @@ eHalStatus hdd_smeRoamCallback( void *pContext, tCsrRoamInfo *pRoamInfo, tANI_U3 case eCSR_ROAM_CONNECT_STATUS_UPDATE: halStatus = roamRoamConnectStatusUpdateHandler( pAdapter, pRoamInfo, roamId, roamStatus, roamResult ); - break; + break; case eCSR_ROAM_MIC_ERROR_IND: halStatus = hdd_RoamMicErrorIndicationHandler( pAdapter, pRoamInfo, roamId, roamStatus, roamResult ); @@ -2314,11 +2371,6 @@ eHalStatus hdd_smeRoamCallback( void *pContext, tCsrRoamInfo *pRoamInfo, tANI_U3 hdd_context_t* pHddCtx = (hdd_context_t*)pAdapter->pHddCtx; if((pHddCtx) && - (pHddCtx->cfg_ini->enableDynamicDTIM || - pHddCtx->cfg_ini->enableModulatedDTIM) && - (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) && - (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) && - (pHddCtx->cfg_ini->fIsBmpsEnabled) && (VOS_TRUE == pHddStaCtx->hdd_ReassocScenario) && (TRUE == pHddCtx->hdd_wlan_suspended) && (eCSR_ROAM_RESULT_NONE == roamResult)) @@ -2355,7 +2407,7 @@ eHalStatus hdd_smeRoamCallback( void *pContext, tCsrRoamInfo *pRoamInfo, tANI_U3 #endif #if defined(FEATURE_WLAN_LFR) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)) case eCSR_ROAM_PMK_NOTIFY: - if (eCSR_AUTH_TYPE_RSN == pHddStaCtx->conn_info.authType) + if (eCSR_AUTH_TYPE_RSN == pHddStaCtx->conn_info.authType) { /* Notify the supplicant of a new candidate */ halStatus = wlan_hdd_cfg80211_pmksa_candidate_notify(pAdapter, pRoamInfo, 1, false); @@ -2386,13 +2438,6 @@ eHalStatus hdd_smeRoamCallback( void *pContext, tCsrRoamInfo *pRoamInfo, tANI_U3 case eCSR_ROAM_RESULT_MGMT_TX_COMPLETE_IND: wlan_hdd_tdls_mgmt_completion_callback(pAdapter, pRoamInfo->reasonCode); break; -#endif -#ifdef WLAN_FEATURE_11W - case eCSR_ROAM_UNPROT_MGMT_FRAME_IND: - hdd_indicateUnprotMgmtFrame(pAdapter, pRoamInfo->nFrameLength, - pRoamInfo->pbFrames, - pRoamInfo->frameType); - break; #endif default: break; @@ -2429,12 +2474,6 @@ eCsrAuthType hdd_TranslateRSNToCsrAuthType( u_int8_t auth_suite[4]) auth_type = eCSR_AUTH_TYPE_CCKM_RSN; } else #endif /* FEATURE_WLAN_CCX */ -#ifdef WLAN_FEATURE_11W - if (memcmp(auth_suite , ccpRSNOui07, 4) == 0) - { - auth_type = eCSR_AUTH_TYPE_RSN_PSK_SHA256; - } else -#endif { auth_type = eCSR_AUTH_TYPE_UNKNOWN; } @@ -2550,10 +2589,6 @@ static tANI_S32 hdd_ProcessGENIE(hdd_adapter_t *pAdapter, eCsrEncryptionType *pEncryptType, eCsrEncryptionType *mcEncryptType, eCsrAuthType *pAuthType, -#ifdef WLAN_FEATURE_11W - u_int8_t *pMfpRequired, - u_int8_t *pMfpCapable, -#endif u_int16_t gen_ie_len, u_int8_t *gen_ie) { @@ -2606,10 +2641,6 @@ static tANI_S32 hdd_ProcessGENIE(hdd_adapter_t *pAdapter, *pEncryptType = hdd_TranslateRSNToCsrEncryptionType(dot11RSNIE.pwise_cipher_suites[0]); //dot11RSNIE.gp_cipher_suite_count *mcEncryptType = hdd_TranslateRSNToCsrEncryptionType(dot11RSNIE.gp_cipher_suite); -#ifdef WLAN_FEATURE_11W - *pMfpRequired = (dot11RSNIE.RSN_Cap[0] >> 6) & 0x1 ; - *pMfpCapable = (dot11RSNIE.RSN_Cap[0] >> 7) & 0x1 ; -#endif // Set the PMKSA ID Cache for this interface for (i=0; iWPARSNIE[1]+2, pWextState->WPARSNIE); if (status == 0) @@ -2717,11 +2740,6 @@ int hdd_SetGENIEToCsr( hdd_adapter_t *pAdapter, eCsrAuthType *RSNAuthType) pWextState->roamProfile.EncryptionType.encryptionType[0] = RSNEncryptType; // Use the cipher type in the RSN IE pWextState->roamProfile.mcEncryptionType.encryptionType[0] = mcRSNEncryptType; - -#ifdef WLAN_FEATURE_11W - pWextState->roamProfile.MFPRequired = RSNMfpRequired; - pWextState->roamProfile.MFPCapable = RSNMfpCapable; -#endif hddLog( LOG1, "%s: CSR AuthType = %d, EncryptionType = %d mcEncryptionType = %d", __func__, *RSNAuthType, RSNEncryptType, mcRSNEncryptType); } return 0; @@ -2799,12 +2817,6 @@ int hdd_set_csr_auth_type ( hdd_adapter_t *pAdapter, eCsrAuthType RSNAuthType) } else #endif -#ifdef WLAN_FEATURE_11W - if (RSNAuthType == eCSR_AUTH_TYPE_RSN_PSK_SHA256) { - pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_RSN_PSK_SHA256; - } else -#endif - if( (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X) == IW_AUTH_KEY_MGMT_802_1X) { pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_RSN; @@ -3329,9 +3341,6 @@ int iw_get_auth(struct net_device *dev,struct iw_request_info *info, case eCSR_AUTH_TYPE_FT_RSN_PSK: #endif case eCSR_AUTH_TYPE_RSN_PSK: -#ifdef WLAN_FEATURE_11W - case eCSR_AUTH_TYPE_RSN_PSK_SHA256: -#endif hddLog(LOG1,"%s called with unknown auth type", __func__); wrqu->param.value = IW_AUTH_ALG_OPEN_SYSTEM; return -EIO; @@ -3460,77 +3469,3 @@ int iw_get_ap_address(struct net_device *dev, return 0; } -#ifdef WLAN_FEATURE_11W -/**--------------------------------------------------------------------------- - - \brief hdd_indicateUnprotMgmtFrame - - This function forwards the unprotected management frame to the supplicant - \param - pAdapter - Pointer to HDD adapter - - nFrameLength - Length of the unprotected frame being passed - - pbFrames - Pointer to the frame buffer - - frameType - 802.11 frame type - \return - nothing - - --------------------------------------------------------------------------*/ -void hdd_indicateUnprotMgmtFrame( hdd_adapter_t *pAdapter, - tANI_U32 nFrameLength, - tANI_U8* pbFrames, - tANI_U8 frameType ) -{ - tANI_U8 type = 0; - tANI_U8 subType = 0; - - hddLog(VOS_TRACE_LEVEL_INFO, "%s: Frame Type = %d Frame Length = %d", - __func__, frameType, nFrameLength); - - /* Sanity Checks */ - if (NULL == pAdapter) - { - hddLog( LOGE, FL("pAdapter is NULL")); - return; - } - - if (NULL == pAdapter->dev) - { - hddLog( LOGE, FL("pAdapter->dev is NULL")); - return; - } - - if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic) - { - hddLog( LOGE, FL("pAdapter has invalid magic")); - return; - } - - if( !nFrameLength ) - { - hddLog( LOGE, FL("Frame Length is Invalid ZERO")); - return; - } - - if (NULL == pbFrames) { - hddLog( LOGE, FL("pbFrames is NULL")); - return; - } - - type = WLAN_HDD_GET_TYPE_FRM_FC(pbFrames[0]); - subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(pbFrames[0]); - - /* Get pAdapter from Destination mac address of the frame */ - if (type == SIR_MAC_MGMT_FRAME && subType == SIR_MAC_MGMT_DISASSOC) - { - cfg80211_send_unprot_disassoc(pAdapter->dev, pbFrames, nFrameLength); - pAdapter->hdd_stats.hddPmfStats.numUnprotDisassocRx++; - } - else if (type == SIR_MAC_MGMT_FRAME && subType == SIR_MAC_MGMT_DEAUTH) - { - cfg80211_send_unprot_deauth(pAdapter->dev, pbFrames, nFrameLength); - pAdapter->hdd_stats.hddPmfStats.numUnprotDeauthRx++; - } - else - { - hddLog( LOGE, FL("Frame type %d and subtype %d are not valid"), type, subType); - return; - } -} -#endif diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_cfg.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_cfg.c index cf18291155f..8c951e9a9dd 100644 --- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_cfg.c +++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_cfg.c @@ -97,10 +97,25 @@ static void cbNotifySetFastTransitionEnabled(hdd_context_t *pHddCtx, unsigned lo sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), pHddCtx->cfg_ini->isFastTransitionEnabled); } +static void cbNotifySetWESMode(hdd_context_t *pHddCtx, unsigned long NotifyId) +{ + // at the point this routine is called, the value in the cfg_ini table has already been updated + sme_UpdateWESMode((tHalHandle)(pHddCtx->hHal), pHddCtx->cfg_ini->isWESModeEnabled); +} + static void cbNotifySetRoamIntraBand(hdd_context_t *pHddCtx, unsigned long NotifyId) { sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), pHddCtx->cfg_ini->nRoamIntraBand); } +static void cbNotifySetRoamScanNProbes(hdd_context_t *pHddCtx, unsigned long NotifyId) +{ + sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), pHddCtx->cfg_ini->nProbes); +} + +static void cbNotifySetRoamScanHomeAwayTime(hdd_context_t *pHddCtx, unsigned long NotifyId) +{ + sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), pHddCtx->cfg_ini->nRoamScanHomeAwayTime); +} #endif #ifdef FEATURE_WLAN_OKC @@ -170,6 +185,18 @@ static void cbNotifySetNeighborScanMaxChanTime(hdd_context_t *pHddCtx, unsigned } #endif +static void cbNotifySetEnableSSR(hdd_context_t *pHddCtx, unsigned long NotifyId) +{ + sme_UpdateEnableSSR((tHalHandle)(pHddCtx->hHal), pHddCtx->cfg_ini->enableSSR); +} + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +static void cbNotifyUpdateRoamScanOffloadEnabled(hdd_context_t *pHddCtx, unsigned long NotifyId) +{ + sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal), pHddCtx->cfg_ini->isRoamOffloadScanEnabled); +} +#endif + REG_TABLE_ENTRY g_registry_table[] = { REG_VARIABLE( CFG_RTS_THRESHOLD_NAME, WLAN_PARAM_Integer, @@ -794,6 +821,13 @@ REG_TABLE_ENTRY g_registry_table[] = CFG_RETRY_LIMIT_TWO_MIN, CFG_RETRY_LIMIT_TWO_MAX ), + REG_VARIABLE( CFG_DISABLE_AGG_WITH_BTC_NAME, WLAN_PARAM_Integer, + hdd_config_t, disableAggWithBtc, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_DISABLE_AGG_WITH_BTC_DEFAULT, + CFG_DISABLE_AGG_WITH_BTC_MIN, + CFG_DISABLE_AGG_WITH_BTC_MAX ), + #ifdef WLAN_AP_STA_CONCURRENCY REG_VARIABLE( CFG_PASSIVE_MAX_CHANNEL_TIME_CONC_NAME, WLAN_PARAM_Integer, hdd_config_t, nPassiveMaxChnTimeConc, @@ -830,12 +864,19 @@ REG_TABLE_ENTRY g_registry_table[] = CFG_REST_TIME_CONC_MIN, CFG_REST_TIME_CONC_MAX ), - REG_VARIABLE( CFG_NUM_CHAN_COMBINED_CONC_NAME, WLAN_PARAM_Integer, - hdd_config_t, nNumChanCombinedConc, + REG_VARIABLE( CFG_NUM_STA_CHAN_COMBINED_CONC_NAME, WLAN_PARAM_Integer, + hdd_config_t, nNumStaChanCombinedConc, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_NUM_STA_CHAN_COMBINED_CONC_DEFAULT, + CFG_NUM_STA_CHAN_COMBINED_CONC_MIN, + CFG_NUM_STA_CHAN_COMBINED_CONC_MAX ), + + REG_VARIABLE( CFG_NUM_P2P_CHAN_COMBINED_CONC_NAME, WLAN_PARAM_Integer, + hdd_config_t, nNumP2PChanCombinedConc, VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, - CFG_NUM_CHAN_COMBINED_CONC_DEFAULT, - CFG_NUM_CHAN_COMBINED_CONC_MIN, - CFG_NUM_CHAN_COMBINED_CONC_MAX ), + CFG_NUM_P2P_CHAN_COMBINED_CONC_DEFAULT, + CFG_NUM_P2P_CHAN_COMBINED_CONC_MIN, + CFG_NUM_P2P_CHAN_COMBINED_CONC_MAX ), #endif REG_VARIABLE( CFG_MAX_PS_POLL_NAME, WLAN_PARAM_Integer, @@ -873,6 +914,13 @@ REG_TABLE_ENTRY g_registry_table[] = CFG_IGNORE_DTIM_MIN, CFG_IGNORE_DTIM_MAX ), + REG_VARIABLE( CFG_MAX_LI_MODULATED_DTIM_NAME, WLAN_PARAM_Integer, + hdd_config_t, fMaxLIModulatedDTIM, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_MAX_LI_MODULATED_DTIM_DEFAULT, + CFG_MAX_LI_MODULATED_DTIM_MIN, + CFG_MAX_LI_MODULATED_DTIM_MAX ), + REG_VARIABLE( CFG_RX_ANT_CONFIGURATION_NAME, WLAN_PARAM_Integer, hdd_config_t, nRxAnt, VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, @@ -1023,8 +1071,8 @@ REG_TABLE_ENTRY g_registry_table[] = VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, CFG_LFR_FEATURE_ENABLED_DEFAULT, CFG_LFR_FEATURE_ENABLED_MIN, - CFG_LFR_FEATURE_ENABLED_MAX, - NotifyIsFastRoamIniFeatureEnabled, 0 ), + CFG_LFR_FEATURE_ENABLED_MAX, + NotifyIsFastRoamIniFeatureEnabled, 0 ), #endif // FEATURE_WLAN_LFR #if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR) @@ -1054,6 +1102,14 @@ REG_TABLE_ENTRY g_registry_table[] = CFG_IMMEDIATE_ROAM_RSSI_DIFF_MIN, CFG_IMMEDIATE_ROAM_RSSI_DIFF_MAX, cbNotifySetImmediateRoamRssiDiff, 0), + + REG_DYNAMIC_VARIABLE( CFG_ENABLE_WES_MODE_NAME, WLAN_PARAM_Integer, + hdd_config_t, isWESModeEnabled, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_WES_MODE_NAME_DEFAULT, + CFG_ENABLE_WES_MODE_NAME_MIN, + CFG_ENABLE_WES_MODE_NAME_MAX, + cbNotifySetWESMode, 0), #endif #ifdef FEATURE_WLAN_OKC REG_DYNAMIC_VARIABLE( CFG_OKC_FEATURE_ENABLED_NAME, WLAN_PARAM_Integer, @@ -1064,7 +1120,15 @@ REG_TABLE_ENTRY g_registry_table[] = CFG_OKC_FEATURE_ENABLED_MAX, cbNotifySetOkcFeatureEnabled, 0 ), #endif - +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + REG_DYNAMIC_VARIABLE( CFG_ROAM_SCAN_OFFLOAD_ENABLED, WLAN_PARAM_Integer, + hdd_config_t, isRoamOffloadScanEnabled, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ROAM_SCAN_OFFLOAD_ENABLED_DEFAULT, + CFG_ROAM_SCAN_OFFLOAD_ENABLED_MIN, + CFG_ROAM_SCAN_OFFLOAD_ENABLED_MAX, + cbNotifyUpdateRoamScanOffloadEnabled, 0), +#endif REG_VARIABLE( CFG_QOS_WMM_PKT_CLASSIFY_BASIS_NAME , WLAN_PARAM_Integer, hdd_config_t, PktClassificationBasis, VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, @@ -1072,6 +1136,27 @@ REG_TABLE_ENTRY g_registry_table[] = CFG_QOS_WMM_PKT_CLASSIFY_BASIS_MIN, CFG_QOS_WMM_PKT_CLASSIFY_BASIS_MAX ), + REG_VARIABLE( CFG_DYNAMIC_SPLIT_SCAN_NAME, WLAN_PARAM_Integer, + hdd_config_t, dynSplitscan, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_DYNAMIC_SPLIT_SCAN_DEFAULT, + CFG_DYNAMIC_SPLIT_SCAN_MIN, + CFG_DYNAMIC_SPLIT_SCAN_MAX ), + + REG_VARIABLE( CFG_SPLIT_SCAN_TRAFFIC_MONITOR_THRSHLD_NAME, WLAN_PARAM_Integer, + hdd_config_t, txRxThresholdForSplitScan, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_SPLIT_SCAN_TRAFFIC_MONITOR_THRSHLD_DEFAULT, + CFG_SPLIT_SCAN_TRAFFIC_MONITOR_THRSHLD_MIN, + CFG_SPLIT_SCAN_TRAFFIC_MONITOR_THRSHLD_MAX ), + + REG_VARIABLE( CFG_SPLIT_SCAN_TRAFFIC_MONITOR_TIMER_NAME, WLAN_PARAM_Integer, + hdd_config_t, trafficMntrTmrForSplitScan, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_SPLIT_SCAN_TRAFFIC_MONITOR_TIMER_DEFAULT, + CFG_SPLIT_SCAN_TRAFFIC_MONITOR_TIMER_MIN, + CFG_SPLIT_SCAN_TRAFFIC_MONITOR_TIMER_MAX ), + REG_VARIABLE( CFG_QOS_WMM_INFRA_DIR_AC_VO_NAME , WLAN_PARAM_Integer, hdd_config_t, InfraDirAcVo, VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, @@ -1528,6 +1613,13 @@ REG_TABLE_ENTRY g_registry_table[] = CFG_ENABLE_HOST_ARPOFFLOAD_MIN, CFG_ENABLE_HOST_ARPOFFLOAD_MAX ), + REG_VARIABLE( CFG_ENABLE_HOST_NSOFFLOAD_NAME, WLAN_PARAM_Integer, + hdd_config_t, fhostNSOffload, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_HOST_NSOFFLOAD_DEFAULT, + CFG_ENABLE_HOST_NSOFFLOAD_MIN, + CFG_ENABLE_HOST_NSOFFLOAD_MAX ), + REG_VARIABLE( CFG_QOS_WMM_TS_INFO_ACK_POLICY_NAME , WLAN_PARAM_HexInteger, hdd_config_t, tsInfoAckPolicy, VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, @@ -1861,6 +1953,22 @@ REG_TABLE_ENTRY g_registry_table[] = CFG_ROAM_INTRA_BAND_MAX, cbNotifySetRoamIntraBand, 0 ), + REG_DYNAMIC_VARIABLE( CFG_ROAM_SCAN_N_PROBES, WLAN_PARAM_Integer, + hdd_config_t, nProbes, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ROAM_SCAN_N_PROBES_DEFAULT, + CFG_ROAM_SCAN_N_PROBES_MIN, + CFG_ROAM_SCAN_N_PROBES_MAX, + cbNotifySetRoamScanNProbes, 0 ), + + REG_DYNAMIC_VARIABLE( CFG_ROAM_SCAN_HOME_AWAY_TIME, WLAN_PARAM_Integer, + hdd_config_t, nRoamScanHomeAwayTime, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT, + CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN, + CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX, + cbNotifySetRoamScanHomeAwayTime, 0 ), + #endif REG_VARIABLE( CFG_P2P_DEVICE_ADDRESS_ADMINISTRATED_NAME, WLAN_PARAM_Integer, @@ -1964,13 +2072,6 @@ REG_VARIABLE( CFG_NUM_BUFF_ADVERT_NAME, WLAN_PARAM_Integer, CFG_NUM_BUFF_ADVERT_MIN, CFG_NUM_BUFF_ADVERT_MAX ), - REG_VARIABLE( CFG_ENABLE_IGNORE_CHAN165, WLAN_PARAM_Integer, - hdd_config_t, ignore_chan165, - VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, - CFG_ENABLE_IGNORE_CHAN165_DEFAULT, - CFG_ENABLE_IGNORE_CHAN165_MIN, - CFG_ENABLE_IGNORE_CHAN165_MAX ), - REG_VARIABLE( CFG_MCC_CONFIG_PARAM_NAME, WLAN_PARAM_Integer, hdd_config_t, configMccParam, VAR_FLAGS_OPTIONAL, @@ -2152,6 +2253,45 @@ REG_VARIABLE( CFG_DISABLE_LDPC_WITH_TXBF_AP, WLAN_PARAM_Integer, CFG_DISABLE_LDPC_WITH_TXBF_AP_MIN, CFG_DISABLE_LDPC_WITH_TXBF_AP_MAX ), #endif + +REG_VARIABLE_STRING( CFG_LIST_OF_NON_DFS_COUNTRY_CODE, WLAN_PARAM_String, + hdd_config_t, listOfNonDfsCountryCode, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + (void *)CFG_LIST_OF_NON_DFS_COUNTRY_CODE_DEFAULT), + + REG_DYNAMIC_VARIABLE( CFG_ENABLE_SSR, WLAN_PARAM_Integer, + hdd_config_t, enableSSR, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_SSR_DEFAULT, + CFG_ENABLE_SSR_MIN, + CFG_ENABLE_SSR_MAX, + cbNotifySetEnableSSR, 0 ), + +REG_VARIABLE_STRING( CFG_LIST_OF_NON_11AC_COUNTRY_CODE, WLAN_PARAM_String, + hdd_config_t, listOfNon11acCountryCode, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + (void *)CFG_LIST_OF_NON_11AC_COUNTRY_CODE_DEFAULT), + +REG_VARIABLE(CFG_MAX_MEDIUM_TIME, WLAN_PARAM_Integer, + hdd_config_t, cfgMaxMediumTime, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_MAX_MEDIUM_TIME_STADEFAULT, + CFG_MAX_MEDIUM_TIME_STAMIN, + CFG_MAX_MEDIUM_TIME_STAMAX ), + + REG_VARIABLE( CFG_ENABLE_TRAFFIC_MONITOR, WLAN_PARAM_Integer, + hdd_config_t, enableTrafficMonitor, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_TRAFFIC_MONITOR_DEFAULT, + CFG_ENABLE_TRAFFIC_MONITOR_MIN, + CFG_ENABLE_TRAFFIC_MONITOR_MAX), + + REG_VARIABLE( CFG_TRAFFIC_IDLE_TIMEOUT, WLAN_PARAM_Integer, + hdd_config_t, trafficIdleTimeout, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_TRAFFIC_IDLE_TIMEOUT_DEFAULT, + CFG_TRAFFIC_IDLE_TIMEOUT_MIN, + CFG_TRAFFIC_IDLE_TIMEOUT_MAX), }; /* @@ -2444,6 +2584,7 @@ static void print_hdd_cfg(hdd_context_t *pHddCtx) #if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR) VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [RoamRssiDiff] Value = [%lu] ",pHddCtx->cfg_ini->RoamRssiDiff); VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [ImmediateRoamRssiDiff] Value = [%lu] ",pHddCtx->cfg_ini->nImmediateRoamRssiDiff); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [isWESModeEnabled] Value = [%lu] ",pHddCtx->cfg_ini->isWESModeEnabled); #endif #ifdef FEATURE_WLAN_OKC VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [OkcEnabled] Value = [%lu] ",pHddCtx->cfg_ini->isOkcIniFeatureEnabled); @@ -2527,12 +2668,16 @@ static void print_hdd_cfg(hdd_context_t *pHddCtx) VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [enableFirstScan2GOnly] Value = [%u] ",pHddCtx->cfg_ini->enableFirstScan2GOnly); VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [skipDfsChnlInP2pSearch] Value = [%u] ",pHddCtx->cfg_ini->skipDfsChnlInP2pSearch); VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [ignoreDynamicDtimInP2pMode] Value = [%u] ",pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode); - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gIgnore_Chan165] Value = [%u] ",pHddCtx->cfg_ini->ignore_chan165); VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [enableRxSTBC] Value = [%u] ",pHddCtx->cfg_ini->enableRxSTBC); VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gEnableLpwrImgTransition] Value = [%u] ",pHddCtx->cfg_ini->enableLpwrImgTransition); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gEnableSSR] Value = [%u] ",pHddCtx->cfg_ini->enableSSR); + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gEnableTrafficMonitor] Value = [%u] ", pHddCtx->cfg_ini->enableTrafficMonitor); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gTrafficIdleTimeout] Value = [%u] ", pHddCtx->cfg_ini->trafficIdleTimeout); } + #define CFG_VALUE_MAX_LEN 256 #define CFG_ENTRY_MAX_LEN (32+CFG_VALUE_MAX_LEN) VOS_STATUS hdd_cfg_get_config(hdd_context_t *pHddCtx, char *pBuf, int buflen) @@ -3031,14 +3176,11 @@ static void hdd_set_power_save_config(hdd_context_t *pHddCtx, tSmeConfigParams * { sme_StartAutoBmpsTimer(pHddCtx->hHal); } - } - #ifdef WLAN_FEATURE_NEIGHBOR_ROAMING static VOS_STATUS hdd_string_to_u8_array( char *str, tANI_U8 *intArray, tANI_U8 *len, tANI_U8 intArrayMaxLen ) { char *s = str; - if( str == NULL || intArray == NULL || len == NULL ) { return VOS_STATUS_E_INVAL; @@ -3059,13 +3201,9 @@ static VOS_STATUS hdd_string_to_u8_array( char *str, tANI_U8 *intArray, tANI_U8 if( s ) s++; } - return VOS_STATUS_SUCCESS; - } #endif - - v_BOOL_t hdd_update_config_dat( hdd_context_t *pHddCtx ) { v_BOOL_t fStatus = TRUE; @@ -3637,6 +3775,13 @@ v_BOOL_t hdd_update_config_dat( hdd_context_t *pHddCtx ) hddLog(LOGE, "Could not pass on WNI_CFG_DYNAMIC_THRESHOLD_TWO to CCM"); } + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_MAX_MEDIUM_TIME, pConfig->cfgMaxMediumTime, + NULL, eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Could not pass on WNI_CFG_MAX_MEDIUM_TIME to CCM"); + } + return fStatus; } @@ -3702,13 +3847,16 @@ VOS_STATUS hdd_set_sme_config( hdd_context_t *pHddCtx ) smeConfig.csrConfig.nPassiveMinChnTime = pConfig->nPassiveMinChnTime; smeConfig.csrConfig.nActiveMaxChnTimeBtc = pConfig->nActiveMaxChnTimeBtc; smeConfig.csrConfig.nActiveMinChnTimeBtc = pConfig->nActiveMinChnTimeBtc; + smeConfig.csrConfig.disableAggWithBtc = pConfig->disableAggWithBtc; #ifdef WLAN_AP_STA_CONCURRENCY smeConfig.csrConfig.nActiveMaxChnTimeConc = pConfig->nActiveMaxChnTimeConc; smeConfig.csrConfig.nActiveMinChnTimeConc = pConfig->nActiveMinChnTimeConc; smeConfig.csrConfig.nPassiveMaxChnTimeConc = pConfig->nPassiveMaxChnTimeConc; smeConfig.csrConfig.nPassiveMinChnTimeConc = pConfig->nPassiveMinChnTimeConc; smeConfig.csrConfig.nRestTimeConc = pConfig->nRestTimeConc; - smeConfig.csrConfig.nNumChanCombinedConc = pConfig->nNumChanCombinedConc; + smeConfig.csrConfig.nNumStaChanCombinedConc = pConfig->nNumStaChanCombinedConc; + smeConfig.csrConfig.nNumP2PChanCombinedConc = pConfig->nNumP2PChanCombinedConc; + #endif smeConfig.csrConfig.Is11eSupportEnabled = pConfig->b80211eIsEnabled; smeConfig.csrConfig.WMMSupportMode = pConfig->WmmMode; @@ -3740,10 +3888,11 @@ VOS_STATUS hdd_set_sme_config( hdd_context_t *pHddCtx ) smeConfig.csrConfig.nTxPowerCap = pConfig->nTxPowerCap; smeConfig.csrConfig.fEnableBypass11d = pConfig->enableBypass11d; smeConfig.csrConfig.fEnableDFSChnlScan = pConfig->enableDFSChnlScan; - smeConfig.csrConfig.fIgnore_chan165 = pConfig->ignore_chan165; #if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR) smeConfig.csrConfig.nRoamPrefer5GHz = pConfig->nRoamPrefer5GHz; smeConfig.csrConfig.nRoamIntraBand = pConfig->nRoamIntraBand; + smeConfig.csrConfig.nProbes = pConfig->nProbes; + smeConfig.csrConfig.nRoamScanHomeAwayTime = pConfig->nRoamScanHomeAwayTime; #endif smeConfig.csrConfig.fFirstScanOnly2GChnl = pConfig->enableFirstScan2GOnly; @@ -3790,8 +3939,11 @@ VOS_STATUS hdd_set_sme_config( hdd_context_t *pHddCtx ) smeConfig.csrConfig.isFastTransitionEnabled = pConfig->isFastTransitionEnabled; smeConfig.csrConfig.RoamRssiDiff = pConfig->RoamRssiDiff; smeConfig.csrConfig.nImmediateRoamRssiDiff = pConfig->nImmediateRoamRssiDiff; + smeConfig.csrConfig.isWESModeEnabled = pConfig->isWESModeEnabled; +#endif +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + smeConfig.csrConfig.isRoamOffloadScanEnabled = pConfig->isRoamOffloadScanEnabled; #endif - #ifdef WLAN_FEATURE_NEIGHBOR_ROAMING smeConfig.csrConfig.neighborRoamConfig.nNeighborReassocRssiThreshold = pConfig->nNeighborReassocRssiThreshold; smeConfig.csrConfig.neighborRoamConfig.nNeighborLookupRssiThreshold = pConfig->nNeighborLookupRssiThreshold; @@ -3806,7 +3958,6 @@ VOS_STATUS hdd_set_sme_config( hdd_context_t *pHddCtx ) &smeConfig.csrConfig.neighborRoamConfig.neighborScanChanList.numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN ); #endif - smeConfig.csrConfig.addTSWhenACMIsOff = pConfig->AddTSWhenACMIsOff; smeConfig.csrConfig.fValidateList = pConfig->fValidateScanList; @@ -3819,17 +3970,16 @@ VOS_STATUS hdd_set_sme_config( hdd_context_t *pHddCtx ) smeConfig.csrConfig.enableTxLdpc = pConfig->enableTxLdpc; + /* update SSR config */ + sme_UpdateEnableSSR((tHalHandle)(pHddCtx->hHal), pHddCtx->cfg_ini->enableSSR); + halStatus = sme_UpdateConfig( pHddCtx->hHal, &smeConfig); if ( !HAL_STATUS_SUCCESS( halStatus ) ) { status = VOS_STATUS_E_FAILURE; } - - return status; } - - /**--------------------------------------------------------------------------- \brief hdd_execute_config_command() - diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_cfg80211.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_cfg80211.c index 3c81079b015..aa9598061ce 100755 --- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_cfg80211.c +++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_cfg80211.c @@ -1,43 +1,23 @@ /* - * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. - * - * Previously licensed under the ISC license by Qualcomm Atheros, Inc. - * - * - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all - * copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ -/* - * Copyright (c) 2012, The Linux Foundation. All rights reserved. - * - * Previously licensed under the ISC license by Qualcomm Atheros, Inc. - * - * - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all - * copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ + * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. +*/ /**======================================================================== @@ -45,9 +25,9 @@ \brief WLAN Host Device Driver implementation - Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved. + Copyright 2008 (c) Qualcomm Technologies, Inc. All Rights Reserved. - Qualcomm Confidential and Proprietary. + Qualcomm Technologies Confidential and Proprietary. ========================================================================*/ @@ -150,7 +130,7 @@ #define WLAN_AKM_SUITE_FT_PSK 0x000FAC04 #endif -static const u32 hdd_cipher_suites[] = +static const u32 hdd_cipher_suites[] = { WLAN_CIPHER_SUITE_WEP40, WLAN_CIPHER_SUITE_WEP104, @@ -165,9 +145,6 @@ static const u32 hdd_cipher_suites[] = #ifdef FEATURE_WLAN_WAPI WLAN_CIPHER_SUITE_SMS4, #endif -#ifdef WLAN_FEATURE_11W - WLAN_CIPHER_SUITE_AES_CMAC, -#endif }; static inline int is_broadcast_ether_addr(const u8 *addr) @@ -177,7 +154,7 @@ static inline int is_broadcast_ether_addr(const u8 *addr) } static struct ieee80211_channel hdd_channels_2_4_GHZ[] = -{ +{ HDD2GHZCHAN(2412, 1, 0) , HDD2GHZCHAN(2417, 2, 0) , HDD2GHZCHAN(2422, 3, 0) , @@ -236,66 +213,31 @@ static struct ieee80211_channel hdd_channels_5_GHZ[] = HDD5GHZCHAN(5825,165, 0) , }; -static struct ieee80211_channel hdd_channels_5_GHZ_FCC[] = -{ - HDD5GHZCHAN(4920, 240, 0) , - HDD5GHZCHAN(4940, 244, 0) , - HDD5GHZCHAN(4960, 248, 0) , - HDD5GHZCHAN(4980, 252, 0) , - HDD5GHZCHAN(5040, 208, 0) , - HDD5GHZCHAN(5060, 212, 0) , - HDD5GHZCHAN(5080, 216, 0) , - HDD5GHZCHAN(5180, 36, IEEE80211_CHAN_PASSIVE_SCAN) , - HDD5GHZCHAN(5200, 40, IEEE80211_CHAN_PASSIVE_SCAN) , - HDD5GHZCHAN(5220, 44, IEEE80211_CHAN_PASSIVE_SCAN) , - HDD5GHZCHAN(5240, 48, IEEE80211_CHAN_PASSIVE_SCAN) , - HDD5GHZCHAN(5260, 52, 0) , - HDD5GHZCHAN(5280, 56, 0) , - HDD5GHZCHAN(5300, 60, 0) , - HDD5GHZCHAN(5320, 64, 0) , - HDD5GHZCHAN(5500,100, 0) , - HDD5GHZCHAN(5520,104, 0) , - HDD5GHZCHAN(5540,108, 0) , - HDD5GHZCHAN(5560,112, 0) , - HDD5GHZCHAN(5580,116, 0) , - HDD5GHZCHAN(5600,120, 0) , - HDD5GHZCHAN(5620,124, 0) , - HDD5GHZCHAN(5640,128, 0) , - HDD5GHZCHAN(5660,132, 0) , - HDD5GHZCHAN(5680,136, 0) , - HDD5GHZCHAN(5700,140, 0) , - HDD5GHZCHAN(5745,149, 0) , - HDD5GHZCHAN(5765,153, 0) , - HDD5GHZCHAN(5785,157, 0) , - HDD5GHZCHAN(5805,161, 0) , - HDD5GHZCHAN(5825,165, 0) , -}; - static struct ieee80211_rate g_mode_rates[] = { - HDD_G_MODE_RATETAB(10, 0x1, 0), - HDD_G_MODE_RATETAB(20, 0x2, 0), - HDD_G_MODE_RATETAB(55, 0x4, 0), - HDD_G_MODE_RATETAB(110, 0x8, 0), - HDD_G_MODE_RATETAB(60, 0x10, 0), - HDD_G_MODE_RATETAB(90, 0x20, 0), - HDD_G_MODE_RATETAB(120, 0x40, 0), - HDD_G_MODE_RATETAB(180, 0x80, 0), - HDD_G_MODE_RATETAB(240, 0x100, 0), - HDD_G_MODE_RATETAB(360, 0x200, 0), - HDD_G_MODE_RATETAB(480, 0x400, 0), + HDD_G_MODE_RATETAB(10, 0x1, 0), + HDD_G_MODE_RATETAB(20, 0x2, 0), + HDD_G_MODE_RATETAB(55, 0x4, 0), + HDD_G_MODE_RATETAB(110, 0x8, 0), + HDD_G_MODE_RATETAB(60, 0x10, 0), + HDD_G_MODE_RATETAB(90, 0x20, 0), + HDD_G_MODE_RATETAB(120, 0x40, 0), + HDD_G_MODE_RATETAB(180, 0x80, 0), + HDD_G_MODE_RATETAB(240, 0x100, 0), + HDD_G_MODE_RATETAB(360, 0x200, 0), + HDD_G_MODE_RATETAB(480, 0x400, 0), HDD_G_MODE_RATETAB(540, 0x800, 0), -}; +}; static struct ieee80211_rate a_mode_rates[] = { - HDD_G_MODE_RATETAB(60, 0x10, 0), - HDD_G_MODE_RATETAB(90, 0x20, 0), - HDD_G_MODE_RATETAB(120, 0x40, 0), - HDD_G_MODE_RATETAB(180, 0x80, 0), - HDD_G_MODE_RATETAB(240, 0x100, 0), - HDD_G_MODE_RATETAB(360, 0x200, 0), - HDD_G_MODE_RATETAB(480, 0x400, 0), + HDD_G_MODE_RATETAB(60, 0x10, 0), + HDD_G_MODE_RATETAB(90, 0x20, 0), + HDD_G_MODE_RATETAB(120, 0x40, 0), + HDD_G_MODE_RATETAB(180, 0x80, 0), + HDD_G_MODE_RATETAB(240, 0x100, 0), + HDD_G_MODE_RATETAB(360, 0x200, 0), + HDD_G_MODE_RATETAB(480, 0x400, 0), HDD_G_MODE_RATETAB(540, 0x800, 0), }; @@ -358,7 +300,7 @@ static struct ieee80211_supported_band wlan_hdd_band_5_GHZ = .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED, }; -/* This structure contain information what kind of frame are expected in +/* This structure contain information what kind of frame are expected in TX/RX direction for each kind of interface */ static const struct ieee80211_txrx_stypes wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = { @@ -509,12 +451,14 @@ static struct index_data_rate_type supported_mcs_rate[] = #ifdef WLAN_FEATURE_11AC -#define DATA_RATE_11AC_MCS_MASK 0x0F +#define DATA_RATE_11AC_MCS_MASK 0x03 struct index_vht_data_rate_type { v_U8_t beacon_rate_index; - v_U16_t supported_rate[2]; + v_U16_t supported_VHT80_rate[2]; + v_U16_t supported_VHT40_rate[2]; + v_U16_t supported_VHT20_rate[2]; }; typedef enum @@ -528,17 +472,17 @@ typedef enum /* MCS Based VHT rate table */ static struct index_vht_data_rate_type supported_vht_mcs_rate[] = { -/* MCS L80 S80 */ - {0, {293, 325}}, - {1, {585, 650}}, - {2, {878, 975}}, - {3, {1170, 1300}}, - {4, {1755, 1950}}, - {5, {2340, 2600}}, - {6, {2633, 2925}}, - {7, {2925, 3250}}, - {8, {3510, 3900}}, - {9, {3900, 4333}} +/* MCS L80 S80 L40 S40 L20 S40*/ + {0, {293, 325}, {135, 150}, {65, 72}}, + {1, {585, 650}, {270, 300}, {130, 144}}, + {2, {878, 975}, {405, 450}, {195, 217}}, + {3, {1170, 1300}, {540, 600}, {260, 289}}, + {4, {1755, 1950}, {810, 900}, {390, 433}}, + {5, {2340, 2600}, {1080, 1200}, {520, 578}}, + {6, {2633, 2925}, {1215, 1350}, {585, 650}}, + {7, {2925, 3250}, {1350, 1500}, {650, 722}}, + {8, {3510, 3900}, {1620, 1800}, {780, 867}}, + {9, {3900, 4333}, {1800, 2000}, {780, 867}} }; #endif /* WLAN_FEATURE_11AC */ @@ -546,8 +490,8 @@ extern struct net_device_ops net_ops_struct; /* * FUNCTION: wlan_hdd_cfg80211_wiphy_alloc - * This function is called by hdd_wlan_startup() - * during initialization. + * This function is called by hdd_wlan_startup() + * during initialization. * This function is used to allocate wiphy structure. */ struct wiphy *wlan_hdd_cfg80211_wiphy_alloc(int priv_size) @@ -555,8 +499,8 @@ struct wiphy *wlan_hdd_cfg80211_wiphy_alloc(int priv_size) struct wiphy *wiphy; ENTER(); - /* - * Create wiphy device + /* + * Create wiphy device */ wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size); @@ -572,33 +516,71 @@ struct wiphy *wlan_hdd_cfg80211_wiphy_alloc(int priv_size) /* * FUNCTION: wlan_hdd_cfg80211_update_band - * This function is called from the supplicant through a + * This function is called from the supplicant through a * private ioctl to change the band value */ int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand) { + int i, j; + eNVChannelEnabledType channelEnabledState; + ENTER(); - switch(eBand) + for (i = 0; i < IEEE80211_NUM_BANDS; i++) { - case eCSR_BAND_24: - wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ; - wiphy->bands[IEEE80211_BAND_5GHZ] = NULL; - break; - case eCSR_BAND_5G: - wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_p2p_2_4_GHZ; - wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ; - break; - case eCSR_BAND_ALL: - default: - wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ; - wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ; + + if (NULL == wiphy->bands[i]) + { + hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy->bands[i] is NULL, i = %d", + __func__, i); + continue; + } + + for (j = 0; j < wiphy->bands[i]->n_channels; j++) + { + struct ieee80211_supported_band *band = wiphy->bands[i]; + + channelEnabledState = vos_nv_getChannelEnabledState( + band->channels[j].hw_value); + + if (IEEE80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) // 5G only + { + // Enable Social channels for P2P + if (WLAN_HDD_IS_SOCIAL_CHANNEL(band->channels[j].center_freq) && + NV_CHANNEL_ENABLE == channelEnabledState) + band->channels[j].flags &= ~IEEE80211_CHAN_DISABLED; + else + band->channels[j].flags |= IEEE80211_CHAN_DISABLED; + continue; + } + else if (IEEE80211_BAND_5GHZ == i && eCSR_BAND_24 == eBand) // 2G only + { + band->channels[j].flags |= IEEE80211_CHAN_DISABLED; + continue; + } + + if (NV_CHANNEL_DISABLE == channelEnabledState || + NV_CHANNEL_INVALID == channelEnabledState) + { + band->channels[j].flags |= IEEE80211_CHAN_DISABLED; + } + else if (NV_CHANNEL_DFS == channelEnabledState) + { + band->channels[j].flags &= ~IEEE80211_CHAN_DISABLED; + band->channels[j].flags |= IEEE80211_CHAN_RADAR; + } + else + { + band->channels[j].flags &= ~(IEEE80211_CHAN_DISABLED + |IEEE80211_CHAN_RADAR); + } + } } return 0; } /* * FUNCTION: wlan_hdd_cfg80211_init - * This function is called by hdd_wlan_startup() - * during initialization. + * This function is called by hdd_wlan_startup() + * during initialization. * This function is used to initialize and register wiphy structure. */ int wlan_hdd_cfg80211_init(struct device *dev, @@ -606,6 +588,7 @@ int wlan_hdd_cfg80211_init(struct device *dev, hdd_config_t *pCfg ) { + int i, j; hdd_context_t *pHddCtx = wiphy_priv(wiphy); ENTER(); @@ -613,7 +596,6 @@ int wlan_hdd_cfg80211_init(struct device *dev, set_wiphy_dev(wiphy, dev); wiphy->mgmt_stypes = wlan_hdd_txrx_stypes; - if (memcmp(pHddCtx->cfg_ini->crdaDefaultCountryCode, CFG_CRDA_DEFAULT_COUNTRY_CODE_DEFAULT , 2) != 0) { @@ -621,13 +603,11 @@ int wlan_hdd_cfg80211_init(struct device *dev, } else { - /* This will disable updating of NL channels from passive to - * active if a beacon is received on passive channel. - */ + /* This will disable updating of NL channels from passive to + * active if a beacon is received on passive channel. */ wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS; wiphy->flags |= WIPHY_FLAG_STRICT_REGULATORY; } - #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)) wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD @@ -651,6 +631,11 @@ int wlan_hdd_cfg80211_init(struct device *dev, wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS | WIPHY_FLAG_TDLS_EXTERNAL_SETUP; #endif +#ifdef FEATURE_WLAN_SCAN_PNO + wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; + wiphy->max_sched_scan_ssids = SIR_PNO_MAX_SUPP_NETWORKS; + wiphy->max_match_sets = SIR_PNO_MAX_SUPP_NETWORKS; +#endif/*FEATURE_WLAN_SCAN_PNO*/ /* even with WIPHY_FLAG_CUSTOM_REGULATORY, driver can still register regulatory callback and @@ -659,12 +644,14 @@ int wlan_hdd_cfg80211_init(struct device *dev, regulatory settings */ wiphy->reg_notifier = wlan_hdd_crda_reg_notifier; - wiphy->max_scan_ssids = MAX_SCAN_SSID; - - wiphy->max_scan_ie_len = 200 ; //TODO: define a macro + wiphy->max_scan_ssids = MAX_SCAN_SSID; + + wiphy->max_scan_ie_len = SIR_MAC_MAX_IE_LENGTH; + + wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS; /* Supports STATION & AD-HOC modes right now */ - wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) + wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO) @@ -703,20 +690,38 @@ int wlan_hdd_cfg80211_init(struct device *dev, wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; } - /*Initialize band capability*/ - switch(pCfg->nBandCapability) - { - case eCSR_BAND_24: - wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ; - break; - case eCSR_BAND_5G: - wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_p2p_2_4_GHZ; - wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ; - break; - case eCSR_BAND_ALL: - default: - wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ; - wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ; + wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ; + wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ; + + for (i = 0; i < IEEE80211_NUM_BANDS; i++) + { + + if (NULL == wiphy->bands[i]) + { + hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy->bands[i] is NULL, i = %d", + __func__, i); + continue; + } + + for (j = 0; j < wiphy->bands[i]->n_channels; j++) + { + struct ieee80211_supported_band *band = wiphy->bands[i]; + + if (IEEE80211_BAND_2GHZ == i && eCSR_BAND_5G == pCfg->nBandCapability) // 5G only + { + // Enable social channels for P2P + if (WLAN_HDD_IS_SOCIAL_CHANNEL(band->channels[j].center_freq)) + band->channels[j].flags &= ~IEEE80211_CHAN_DISABLED; + else + band->channels[j].flags |= IEEE80211_CHAN_DISABLED; + continue; + } + else if (IEEE80211_BAND_5GHZ == i && eCSR_BAND_24 == pCfg->nBandCapability) // 2G only + { + band->channels[j].flags |= IEEE80211_CHAN_DISABLED; + continue; + } + } } /*Initialise the supported cipher suite details*/ wiphy->cipher_suites = hdd_cipher_suites; @@ -747,7 +752,7 @@ int wlan_hdd_cfg80211_register(struct wiphy *wiphy) EXIT(); return 0; -} +} /* In this function we will try to get default country code from crda. If the gCrdaDefaultCountryCode is configured in ini file, @@ -765,6 +770,10 @@ int wlan_hdd_get_crda_regd_entry(struct wiphy *wiphy, hdd_config_t *pCfg) regulatory_hint(wiphy, pCfg->crdaDefaultCountryCode); wait_for_completion_interruptible_timeout(&pHddCtx->driver_crda_req, CRDA_WAIT_TIME); + /* if the country is not found from current regulatory.bin, + fall back to world domain */ + if (is_crda_regulatory_entry_valid() == VOS_FALSE) + crda_regulatory_entry_default(pCfg->crdaDefaultCountryCode, NUM_REG_DOMAINS-1); } return 0; } @@ -776,25 +785,35 @@ int wlan_hdd_get_crda_regd_entry(struct wiphy *wiphy, hdd_config_t *pCfg) GO should not opeate on indoor channels */ void wlan_hdd_cfg80211_update_reg_info(struct wiphy *wiphy) { + int j; hdd_context_t *pHddCtx = wiphy_priv(wiphy); tANI_U8 defaultCountryCode[3] = SME_INVALID_COUNTRY_CODE; //Default counrtycode from NV at the time of wiphy initialization. if (eHAL_STATUS_SUCCESS != sme_GetDefaultCountryCodeFrmNv(pHddCtx->hHal, &defaultCountryCode[0])) { - hddLog(LOGE, FL("%s Failed to get default country code from NV")); + hddLog(LOGE, FL("%s Failed to get default country code from NV")); } if ((defaultCountryCode[0]== 'U') && (defaultCountryCode[1]=='S')) { - wlan_hdd_band_5_GHZ.channels = hdd_channels_5_GHZ_FCC; - wlan_hdd_band_5_GHZ.n_channels = ARRAY_SIZE(hdd_channels_5_GHZ_FCC); - + if (NULL == wiphy->bands[IEEE80211_BAND_5GHZ]) + { + hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy->bands[IEEE80211_BAND_5GHZ] is NULL",__func__ ); + return; + } + for (j = 0; j < wiphy->bands[IEEE80211_BAND_5GHZ]->n_channels; j++) + { + struct ieee80211_supported_band *band = wiphy->bands[IEEE80211_BAND_5GHZ]; + // Mark UNII -1 band channel as passive + if (WLAN_HDD_CHANNEL_IN_UNII_1_BAND(band->channels[j].center_freq)) + band->channels[j].flags |= IEEE80211_CHAN_PASSIVE_SCAN; + } } } /* In this function we will do all post VOS start initialization. In this function we will register for all frame in which supplicant - is interested. + is interested. */ void wlan_hdd_cfg80211_post_voss_start(hdd_adapter_t* pAdapter) { @@ -808,13 +827,13 @@ void wlan_hdd_cfg80211_post_voss_start(hdd_adapter_t* pAdapter) initialized. Once we will move to 2.6.37 kernel, in which we have frame register ops, we will move this code as a part of that */ /* GAS Initial Request */ - sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type, + sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type, (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE ); /* GAS Initial Response */ sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type, (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE ); - + /* GAS Comeback Request */ sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type, (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE ); @@ -825,20 +844,13 @@ void wlan_hdd_cfg80211_post_voss_start(hdd_adapter_t* pAdapter) /* P2P Public Action */ sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type, - (v_U8_t*)P2P_PUBLIC_ACTION_FRAME, + (v_U8_t*)P2P_PUBLIC_ACTION_FRAME, P2P_PUBLIC_ACTION_FRAME_SIZE ); /* P2P Action */ sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type, (v_U8_t*)P2P_ACTION_FRAME, P2P_ACTION_FRAME_SIZE ); - -#ifdef WLAN_FEATURE_11W - /* SA Query Response Action Frame */ - sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type, - (v_U8_t*)SA_QUERY_FRAME_RSP, - SA_QUERY_FRAME_RSP_SIZE ); -#endif /* WLAN_FEATURE_11W */ } void wlan_hdd_cfg80211_pre_voss_stop(hdd_adapter_t* pAdapter) @@ -860,7 +872,7 @@ void wlan_hdd_cfg80211_pre_voss_stop(hdd_adapter_t* pAdapter) /* GAS Initial Response */ sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type, (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE ); - + /* GAS Comeback Request */ sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type, (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE ); @@ -871,20 +883,13 @@ void wlan_hdd_cfg80211_pre_voss_stop(hdd_adapter_t* pAdapter) /* P2P Public Action */ sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type, - (v_U8_t*)P2P_PUBLIC_ACTION_FRAME, + (v_U8_t*)P2P_PUBLIC_ACTION_FRAME, P2P_PUBLIC_ACTION_FRAME_SIZE ); /* P2P Action */ sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type, (v_U8_t*)P2P_ACTION_FRAME, P2P_ACTION_FRAME_SIZE ); - -#ifdef WLAN_FEATURE_11W - /* SA Query Response Action Frame */ - sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type, - (v_U8_t*)SA_QUERY_FRAME_RSP, - SA_QUERY_FRAME_RSP_SIZE ); -#endif /* WLAN_FEATURE_11W */ } #ifdef FEATURE_WLAN_WAPI @@ -943,16 +948,16 @@ void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t* pAdapter, u8 key_index, #endif /* FEATURE_WLAN_WAPI*/ #if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0)) -int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter, +int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter, beacon_data_t **ppBeacon, struct beacon_parameters *params) #else -int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter, +int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter, beacon_data_t **ppBeacon, struct cfg80211_beacon_data *params, int dtim_period) #endif -{ +{ int size; beacon_data_t *beacon = NULL; beacon_data_t *old = NULL; @@ -1004,7 +1009,7 @@ int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter, else beacon->dtim_period = old->dtim_period; #endif - + beacon->head = ((u8 *) beacon) + sizeof(beacon_data_t); beacon->tail = beacon->head + head_len; beacon->head_len = head_len; @@ -1013,16 +1018,16 @@ int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter, if(params->head) { memcpy (beacon->head,params->head,beacon->head_len); } - else { + else { if(old) memcpy (beacon->head,old->head,beacon->head_len); } - + if(params->tail) { memcpy (beacon->tail,params->tail,beacon->tail_len); } else { - if(old) + if(old) memcpy (beacon->tail,old->tail,beacon->tail_len); } @@ -1039,9 +1044,9 @@ v_U8_t* wlan_hdd_cfg80211_get_ie_ptr(v_U8_t *pIes, int length, v_U8_t eid) int left = length; v_U8_t *ptr = pIes; v_U8_t elem_id,elem_len; - + while(left >= 2) - { + { elem_id = ptr[0]; elem_len = ptr[1]; left -= 2; @@ -1052,11 +1057,11 @@ v_U8_t* wlan_hdd_cfg80211_get_ie_ptr(v_U8_t *pIes, int length, v_U8_t eid) eid,elem_len,left); return NULL; } - if (elem_id == eid) + if (elem_id == eid) { return ptr; } - + left -= elem_len; ptr += (elem_len + 2); } @@ -1066,7 +1071,7 @@ v_U8_t* wlan_hdd_cfg80211_get_ie_ptr(v_U8_t *pIes, int length, v_U8_t eid) /* Check if rate is 11g rate or not */ static int wlan_hdd_rate_is_11g(u8 rate) { - u8 gRateArray[8] = {12, 18, 24, 36, 48, 72, 96, 104}; /* actual rate * 2 */ + static const u8 gRateArray[8] = {12, 18, 24, 36, 48, 72, 96, 108}; /* actual rate * 2 */ u8 i; for (i = 0; i < 8; i++) { @@ -1144,7 +1149,7 @@ static void wlan_hdd_set_sapHwmode(hdd_adapter_t *pHostapdAdapter) pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len, WLAN_EID_HT_CAPABILITY); - if(pIe) + if(pIe) { pConfig->SapHw_mode= eSAP_DOT11_MODE_11n; if(require_ht) @@ -1419,23 +1424,23 @@ static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter, return ret; } -/* +/* * FUNCTION: wlan_hdd_validate_operation_channel * called by wlan_hdd_cfg80211_start_bss() and * wlan_hdd_cfg80211_set_channel() * This function validates whether given channel is part of valid - * channel list. - */ -static VOS_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,int channel) + * channel list. + */ +VOS_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,int channel) { - + v_U32_t num_ch = 0; u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN]; u32 indx = 0; tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); v_U8_t fValidChannel = FALSE, count = 0; hdd_config_t *hdd_pConfig_ini= (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini; - + num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN; if ( hdd_pConfig_ini->sapAllowAllChannel) @@ -1481,7 +1486,7 @@ static VOS_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,in } } return VOS_STATUS_SUCCESS; - + } /** @@ -1497,6 +1502,8 @@ static int wlan_hdd_cfg80211_set_channel( struct wiphy *wiphy, struct net_device int channel = 0; hdd_adapter_t *pAdapter = NULL; int freq = chan->center_freq; /* freq is in MHZ */ + hdd_context_t *pHddCtx; + int status; ENTER(); @@ -1511,10 +1518,15 @@ static int wlan_hdd_cfg80211_set_channel( struct wiphy *wiphy, struct net_device hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d freq = %d \n",__func__, pAdapter->device_mode, chan->center_freq); - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__); - return -EAGAIN; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return status; } /* @@ -1621,27 +1633,27 @@ static int wlan_hdd_cfg80211_set_channel( struct wiphy *wiphy, struct net_device return -EINVAL; } EXIT(); - return 0; + return status; } -/* +/* * FUNCTION: wlan_hdd_select_cbmode * called by wlan_hdd_cfg80211_start_bss() and * This function selects the cbmode based on primary channel - */ + */ VOS_STATUS wlan_sap_select_cbmode(void *pAdapter,eSapPhyMode SapHw_mode, v_U8_t channel) { tSmeConfigParams smeConfig; hdd_context_t *pHddCtx = ( hdd_context_t *) pAdapter; hdd_config_t *pConfigIni = ((hdd_context_t *)(pAdapter))->cfg_ini; - + if( #ifdef WLAN_FEATURE_11AC SapHw_mode != eSAP_DOT11_MODE_11ac && SapHw_mode != eSAP_DOT11_MODE_11ac_ONLY && #endif SapHw_mode != eSAP_DOT11_MODE_11n && - SapHw_mode != eSAP_DOT11_MODE_11n_ONLY + SapHw_mode != eSAP_DOT11_MODE_11n_ONLY ) { return VOS_STATUS_SUCCESS; @@ -1658,31 +1670,31 @@ VOS_STATUS wlan_sap_select_cbmode(void *pAdapter,eSapPhyMode SapHw_mode, v_U8_t #ifdef WLAN_FEATURE_11AC - if ( SapHw_mode == eSAP_DOT11_MODE_11ac || + if ( SapHw_mode == eSAP_DOT11_MODE_11ac || SapHw_mode == eSAP_DOT11_MODE_11ac_ONLY ) { if ( channel== 36 || channel == 52 || channel == 100 || channel == 116 || channel == 149 ) { - smeConfig.csrConfig.channelBondingMode5GHz = + smeConfig.csrConfig.channelBondingMode5GHz = PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW - 1; } else if ( channel == 40 || channel == 56 || channel == 104 || channel == 120 || channel == 153 ) { - smeConfig.csrConfig.channelBondingMode5GHz = + smeConfig.csrConfig.channelBondingMode5GHz = PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW - 1; } else if ( channel == 44 || channel == 60 || channel == 108 || channel == 124 || channel == 157 ) { - smeConfig.csrConfig.channelBondingMode5GHz = + smeConfig.csrConfig.channelBondingMode5GHz = PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH -1; } else if ( channel == 48 || channel == 64 || channel == 112 || channel == 128 || channel == 161 ) { - smeConfig.csrConfig.channelBondingMode5GHz = + smeConfig.csrConfig.channelBondingMode5GHz = PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH - 1; } else if ( channel == 165 ) @@ -1763,7 +1775,7 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, //pConfig->channel = pCommitConfig->channel; /*Protection parameter to enable or disable*/ - pConfig->protEnabled = + pConfig->protEnabled = (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtEnabled; pConfig->dtim_period = pBeacon->dtim_period; @@ -1819,8 +1831,8 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, pConfig->authType = eSAP_AUTO_SWITCH; capab_info = pMgmt_frame->u.beacon.capab_info; - - pConfig->privacy = (pMgmt_frame->u.beacon.capab_info & + + pConfig->privacy = (pMgmt_frame->u.beacon.capab_info & WLAN_CAPABILITY_PRIVACY) ? VOS_TRUE : VOS_FALSE; (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->uPrivacy = pConfig->privacy; @@ -1854,22 +1866,22 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, { pConfig->wps_state = SAP_WPS_DISABLED; } - pConfig->fwdWPSPBCProbeReq = 1; // Forward WPS PBC probe request frame up + pConfig->fwdWPSPBCProbeReq = 1; // Forward WPS PBC probe request frame up pConfig->RSNWPAReqIELength = 0; pConfig->pRSNWPAReqIE = NULL; - pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len, + pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len, WLAN_EID_RSN); if(pIe && pIe[1]) - { + { pConfig->RSNWPAReqIELength = pIe[1] + 2; memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength); pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0]; - /* The actual processing may eventually be more extensive than - * this. Right now, just consume any PMKIDs that are sent in + /* The actual processing may eventually be more extensive than + * this. Right now, just consume any PMKIDs that are sent in * by the app. * */ - status = hdd_softap_unpackIE( + status = hdd_softap_unpackIE( vos_get_context( VOS_MODULE_ID_SME, pVosContext), &RSNEncryptType, &mcRSNEncryptType, @@ -1879,19 +1891,19 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, if( VOS_STATUS_SUCCESS == status ) { - /* Now copy over all the security attributes you have - * parsed out + /* Now copy over all the security attributes you have + * parsed out * */ pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE pConfig->mcRSNEncryptType = mcRSNEncryptType; (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType = RSNEncryptType; - hddLog( LOG1, FL("%s: CSR AuthType = %d, " + hddLog( LOG1, FL("CSR AuthType = %d, " "EncryptionType = %d mcEncryptionType = %d\n"), RSNAuthType, RSNEncryptType, mcRSNEncryptType); } } - + pIe = wlan_hdd_get_vendor_oui_ie_ptr(WPA_OUI_TYPE, WPA_OUI_TYPE_SIZE, pBeacon->tail, pBeacon->tail_len); @@ -1908,7 +1920,7 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, pConfig->RSNWPAReqIELength = pIe[1] + 2; memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength); pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0]; - status = hdd_softap_unpackIE( + status = hdd_softap_unpackIE( vos_get_context( VOS_MODULE_ID_SME, pVosContext), &RSNEncryptType, &mcRSNEncryptType, @@ -1918,14 +1930,14 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, if( VOS_STATUS_SUCCESS == status ) { - /* Now copy over all the security attributes you have - * parsed out + /* Now copy over all the security attributes you have + * parsed out * */ pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE pConfig->mcRSNEncryptType = mcRSNEncryptType; (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType = RSNEncryptType; - hddLog( LOG1, FL("%s: CSR AuthType = %d, " + hddLog( LOG1, FL("CSR AuthType = %d, " "EncryptionType = %d mcEncryptionType = %d\n"), RSNAuthType, RSNEncryptType, mcRSNEncryptType); } @@ -1957,9 +1969,9 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, } #endif - vos_mem_copy(pConfig->self_macaddr.bytes, + vos_mem_copy(pConfig->self_macaddr.bytes, pHostapdAdapter->macAddressCurrent.bytes, sizeof(v_MACADDR_t)); - + /* default value */ pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED; pConfig->num_accept_mac = 0; @@ -1975,21 +1987,21 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, acl type : 1 byte no of mac addr in black list: 1 byte list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id - */ - if ((pIe != NULL) && (pIe[1] != 0)) + */ + if ((pIe != NULL) && (pIe[1] != 0)) { pConfig->SapMacaddr_acl = pIe[6]; pConfig->num_deny_mac = pIe[7]; hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no deny mac = %d\n", pIe[6], pIe[7]); - if (pConfig->num_deny_mac > MAX_MAC_ADDRESS_DENIED) - pConfig->num_deny_mac = MAX_MAC_ADDRESS_DENIED; + if (pConfig->num_deny_mac > MAX_ACL_MAC_ADDRESS) + pConfig->num_deny_mac = MAX_ACL_MAC_ADDRESS; acl_entry = (struct qc_mac_acl_entry *)(pIe + 8); for (i = 0; i < pConfig->num_deny_mac; i++) { vos_mem_copy(&pConfig->deny_mac[i], acl_entry->addr, sizeof(qcmacaddr)); acl_entry++; - } + } } pIe = wlan_hdd_get_vendor_oui_ie_ptr(WHITELIST_OUI_TYPE, WPA_OUI_TYPE_SIZE, pBeacon->tail, pBeacon->tail_len); @@ -2001,15 +2013,15 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, acl type : 1 byte no of mac addr in white list: 1 byte list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id - */ - if ((pIe != NULL) && (pIe[1] != 0)) + */ + if ((pIe != NULL) && (pIe[1] != 0)) { pConfig->SapMacaddr_acl = pIe[6]; pConfig->num_accept_mac = pIe[7]; hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no accept mac = %d\n", pIe[6], pIe[7]); - if (pConfig->num_accept_mac > MAX_MAC_ADDRESS_ACCEPTED) - pConfig->num_accept_mac = MAX_MAC_ADDRESS_ACCEPTED; + if (pConfig->num_accept_mac > MAX_ACL_MAC_ADDRESS) + pConfig->num_accept_mac = MAX_ACL_MAC_ADDRESS; acl_entry = (struct qc_mac_acl_entry *)(pIe + 8); for (i = 0; i < pConfig->num_accept_mac; i++) { @@ -2017,17 +2029,23 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, acl_entry++; } } + wlan_hdd_set_sapHwmode(pHostapdAdapter); #ifdef WLAN_FEATURE_11AC - if(((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_AUTO) || - ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac) || - ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) ) + /* Overwrite the hostapd setting for HW mode only for 11ac. + * This is valid only if mode is set to 11n in hostapd and either AUTO or 11ac in .ini . + * Otherwise, leave whatever is set in hostapd (a OR b OR g OR n mode) */ + if( ((pConfig->SapHw_mode == eSAP_DOT11_MODE_11n) || + (pConfig->SapHw_mode == eSAP_DOT11_MODE_11n_ONLY)) && + (((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_AUTO) || + ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac) || + ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY)) ) { pConfig->SapHw_mode = eSAP_DOT11_MODE_11ac; } #endif - + if( AUTO_CHANNEL_SELECT != pConfig->channel) wlan_sap_select_cbmode((WLAN_HDD_GET_CTX(pHostapdAdapter)),pConfig->SapHw_mode,pConfig->channel); // ht_capab is not what the name conveys,this is used for protection bitmap @@ -2041,26 +2059,26 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, } //Uapsd Enabled Bit - pConfig->UapsdEnable = + pConfig->UapsdEnable = (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apUapsdEnabled; //Enable OBSS protection - pConfig->obssProtEnabled = - (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apOBSSProtEnabled; + pConfig->obssProtEnabled = + (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apOBSSProtEnabled; - hddLog(LOGW, FL("SOftAP macaddress : "MAC_ADDRESS_STR"\n"), + hddLog(LOGW, FL("SOftAP macaddress : "MAC_ADDRESS_STR"\n"), MAC_ADDR_ARRAY(pHostapdAdapter->macAddressCurrent.bytes)); - hddLog(LOGW,FL("ssid =%s\n"), pConfig->SSIDinfo.ssid.ssId); + hddLog(LOGW,FL("ssid =%s\n"), pConfig->SSIDinfo.ssid.ssId); hddLog(LOGW,FL("beaconint=%d, channel=%d\n"), (int)pConfig->beacon_int, (int)pConfig->channel); hddLog(LOGW,FL("hw_mode=%x\n"), pConfig->SapHw_mode); - hddLog(LOGW,FL("privacy=%d, authType=%d\n"), pConfig->privacy, - pConfig->authType); + hddLog(LOGW,FL("privacy=%d, authType=%d\n"), pConfig->privacy, + pConfig->authType); hddLog(LOGW,FL("RSN/WPALen=%d, \n"),(int)pConfig->RSNWPAReqIELength); - hddLog(LOGW,FL("Uapsd = %d\n"),pConfig->UapsdEnable); + hddLog(LOGW,FL("Uapsd = %d\n"),pConfig->UapsdEnable); hddLog(LOGW,FL("ProtEnabled = %d, OBSSProtEnabled = %d\n"), pConfig->protEnabled, pConfig->obssProtEnabled); - if(test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags)) + if(test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags)) { //Bss already started. just return. //TODO Probably it should update some beacon params. @@ -2068,7 +2086,7 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, EXIT(); return 0; } - + pConfig->persona = pHostapdAdapter->device_mode; pSapEventCallback = hdd_hostapd_SAPEventCB; @@ -2079,18 +2097,18 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, return -EINVAL; } - hddLog(LOG1, + hddLog(LOG1, FL("Waiting for Scan to complete(auto mode) and BSS to start")); status = vos_wait_single_event(&pHostapdState->vosEvent, 10000); - + if (!VOS_IS_STATUS_SUCCESS(status)) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, ("ERROR: HDD vos wait for single_event failed!!\n")); VOS_ASSERT(0); } - + //Succesfully started Bss update the state bit. set_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags); @@ -2119,38 +2137,42 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, } #if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0)) -static int wlan_hdd_cfg80211_add_beacon(struct wiphy *wiphy, - struct net_device *dev, +static int wlan_hdd_cfg80211_add_beacon(struct wiphy *wiphy, + struct net_device *dev, struct beacon_parameters *params) { hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - int status=VOS_STATUS_SUCCESS; + hdd_context_t *pHddCtx; + int status; ENTER(); hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "device mode=%d\n",pAdapter->device_mode); - if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress ) + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EAGAIN; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return status; } - if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP) + if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP) || (pAdapter->device_mode == WLAN_HDD_P2P_GO) ) { beacon_data_t *old,*new; old = pAdapter->sessionCtx.ap.beacon; - + if (old) return -EALREADY; status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params); - if(status != VOS_STATUS_SUCCESS) + if(status != VOS_STATUS_SUCCESS) { hddLog(VOS_TRACE_LEVEL_FATAL, "%s:Error!!! Allocating the new beacon\n",__func__); @@ -2165,41 +2187,45 @@ static int wlan_hdd_cfg80211_add_beacon(struct wiphy *wiphy, EXIT(); return status; } - -static int wlan_hdd_cfg80211_set_beacon(struct wiphy *wiphy, + +static int wlan_hdd_cfg80211_set_beacon(struct wiphy *wiphy, struct net_device *dev, struct beacon_parameters *params) { - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - int status=VOS_STATUS_SUCCESS; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx; + int status; ENTER(); hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n", __func__,pAdapter->device_mode); - if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress ) + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EAGAIN; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return status; } - if ((pAdapter->device_mode == WLAN_HDD_SOFTAP) + if ((pAdapter->device_mode == WLAN_HDD_SOFTAP) || (pAdapter->device_mode == WLAN_HDD_P2P_GO) - ) + ) { beacon_data_t *old,*new; - + old = pAdapter->sessionCtx.ap.beacon; - + if (!old) return -ENOENT; status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params); if(status != VOS_STATUS_SUCCESS) { - hddLog(VOS_TRACE_LEVEL_FATAL, + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Error!!! Allocating the new beacon\n",__func__); return -EINVAL; } @@ -2227,7 +2253,7 @@ static int wlan_hdd_cfg80211_stop_ap (struct wiphy *wiphy, hdd_context_t *pHddCtx = NULL; hdd_scaninfo_t *pScanInfo = NULL; hdd_adapter_t *staAdapter = NULL; - VOS_STATUS status = 0; + VOS_STATUS status; ENTER(); @@ -2238,18 +2264,14 @@ static int wlan_hdd_cfg80211_stop_ap (struct wiphy *wiphy, return -ENODEV; } - pHddCtx = WLAN_HDD_GET_CTX(pAdapter); - if (NULL == pHddCtx) - { - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, - "%s: HDD context is Null", __func__); - return -ENODEV; - } - if (pHddCtx->isLogpInProgress) + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EAGAIN; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return status; } staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_INFRA_STATION); @@ -2258,7 +2280,7 @@ static int wlan_hdd_cfg80211_stop_ap (struct wiphy *wiphy, staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_CLIENT); if (NULL == staAdapter) { - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: HDD adapter context is Null", __func__); return -ENODEV; } @@ -2266,14 +2288,6 @@ static int wlan_hdd_cfg80211_stop_ap (struct wiphy *wiphy, pScanInfo = &pHddCtx->scan_info; - if (pHddCtx->isLogpInProgress) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__); - return -EAGAIN; - } - - pHddCtx = (hdd_context_t*)pAdapter->pHddCtx; - hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n", __func__,pAdapter->device_mode); @@ -2377,13 +2391,13 @@ static int wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy, { hdd_adapter_t *pAdapter; hdd_context_t *pHddCtx; - int status = 0; + int status; ENTER(); if (NULL == dev) { - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: Device is Null", __func__); return -ENODEV; } @@ -2391,38 +2405,26 @@ static int wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy, pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); if (NULL == pAdapter) { - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: HDD adapter is Null", __func__); return -ENODEV; } if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic) { - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: HDD adapter magic is invalid", __func__); return -ENODEV; } pHddCtx = WLAN_HDD_GET_CTX(pAdapter); - if (NULL == pHddCtx) - { - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, - "%s: HDD context is Null", __func__); - return -ENODEV; - } - - if (pHddCtx->isLogpInProgress) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, - "%s: LOGP in Progress. Ignore!!!", __func__); - return -EAGAIN; - } + status = wlan_hdd_validate_context(pHddCtx); - if (pHddCtx->isLoadUnloadInProgress) + if (0 != status) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, - "%s: Unloading/Loading in Progress. Ignore!!!", __func__); - return -EAGAIN; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return status; } hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device mode = %d", @@ -2460,38 +2462,44 @@ static int wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy, } -static int wlan_hdd_cfg80211_change_beacon(struct wiphy *wiphy, +static int wlan_hdd_cfg80211_change_beacon(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_beacon_data *params) { - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - int status=VOS_STATUS_SUCCESS; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx; + int status; ENTER(); hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n", __func__, pAdapter->device_mode); - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__); - return -EAGAIN; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return status; } - if ((pAdapter->device_mode == WLAN_HDD_SOFTAP) + if ((pAdapter->device_mode == WLAN_HDD_SOFTAP) || (pAdapter->device_mode == WLAN_HDD_P2P_GO) - ) + ) { beacon_data_t *old,*new; - + old = pAdapter->sessionCtx.ap.beacon; - + if (!old) return -ENOENT; status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, params, 0); if(status != VOS_STATUS_SUCCESS) { - hddLog(VOS_TRACE_LEVEL_FATAL, + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Error!!! Allocating the new beacon\n",__func__); return -EINVAL; } @@ -2515,20 +2523,20 @@ static int wlan_hdd_cfg80211_change_bss (struct wiphy *wiphy, hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); ENTER(); - + hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n", __func__,pAdapter->device_mode); if((pAdapter->device_mode == WLAN_HDD_SOFTAP) || (pAdapter->device_mode == WLAN_HDD_P2P_GO) - ) + ) { /* ap_isolate == -1 means that in change bss, upper layer doesn't * want to update this parameter */ - if (-1 != params->ap_isolate) + if (-1 != params->ap_isolate) { pAdapter->sessionCtx.ap.apDisableIntraBssFwd = !!params->ap_isolate; - } + } } EXIT(); @@ -2552,21 +2560,25 @@ int wlan_hdd_cfg80211_change_iface( struct wiphy *wiphy, hdd_adapter_t *pP2pAdapter = NULL; tCsrRoamProfile *pRoamProfile = NULL; eCsrRoamBssType LastBSSType; - hdd_config_t *pConfig = pHddCtx->cfg_ini; + hdd_config_t *pConfig = NULL; eMib_dot11DesiredBssType connectedBssType; VOS_STATUS status; ENTER(); - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__); - return -EAGAIN; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return status; } hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d", __func__, pAdapter->device_mode); + pConfig = pHddCtx->cfg_ini; wdev = ndev->ieee80211_ptr; #ifdef WLAN_BTAMP_FEATURE @@ -2612,12 +2624,12 @@ int wlan_hdd_cfg80211_change_iface( struct wiphy *wiphy, pConfig->dot11Mode = eHDD_DOT11_MODE_11ac; } #endif - pRoamProfile->phyMode = + pRoamProfile->phyMode = hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode); wdev->iftype = type; //Check for sub-string p2p to confirm its a p2p interface if (NULL != strstr(ndev->name,"p2p")) - { + { pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ? WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT; } @@ -2626,14 +2638,31 @@ int wlan_hdd_cfg80211_change_iface( struct wiphy *wiphy, pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ? WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT; } - break; - case NL80211_IFTYPE_ADHOC: - hddLog(VOS_TRACE_LEVEL_INFO, - "%s: setting interface Type to ADHOC", __func__); - pRoamProfile->BSSType = eCSR_BSS_TYPE_START_IBSS; - pRoamProfile->phyMode = - hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode); - wdev->iftype = type; +#ifdef FEATURE_WLAN_TDLS + /* The open adapter for the p2p shall skip initializations in + * tdls_init if the device mode is WLAN_HDD_P2P_DEVICE, for + * TDLS is supported only on WLAN_HDD_P2P_CLIENT. Hence invoke + * tdls_init when the change_iface sets the device mode to + * WLAN_HDD_P2P_CLIENT. + */ + + if ( pAdapter->device_mode == WLAN_HDD_P2P_CLIENT) + { + if (0 != wlan_hdd_tdls_init (pAdapter)) + { + return -EINVAL; + } + } +#endif + + break; + case NL80211_IFTYPE_ADHOC: + hddLog(VOS_TRACE_LEVEL_INFO, + "%s: setting interface Type to ADHOC", __func__); + pRoamProfile->BSSType = eCSR_BSS_TYPE_START_IBSS; + pRoamProfile->phyMode = + hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode); + wdev->iftype = type; break; case NL80211_IFTYPE_AP: @@ -2679,7 +2708,7 @@ int wlan_hdd_cfg80211_change_iface( struct wiphy *wiphy, //before starting Go if(WLAN_HDD_P2P_GO == pAdapter->device_mode) { - if(VOS_STATUS_E_FAILURE == + if(VOS_STATUS_E_FAILURE == hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_P2P_GO)) { //Fail to Exit BMPS @@ -2774,6 +2803,10 @@ int wlan_hdd_cfg80211_change_iface( struct wiphy *wiphy, /* In case of JB, for P2P-GO, only change interface will be called, * This is the right place to enable back bmps_imps() */ + if (pHddCtx->hdd_wlan_suspended) + { + hdd_set_pwrparams(pHddCtx); + } hdd_enable_bmps_imps(pHddCtx); goto done; case NL80211_IFTYPE_AP: @@ -2828,7 +2861,7 @@ int wlan_hdd_cfg80211_change_iface( struct wiphy *wiphy, /*set bitmask based on updated value*/ wlan_hdd_set_concurrency_mode(pHddCtx, pAdapter->device_mode); #ifdef WLAN_BTAMP_FEATURE - if((NL80211_IFTYPE_STATION == type) && (pHddCtx->concurrency_mode <= 1) && + if((NL80211_IFTYPE_STATION == type) && (pHddCtx->concurrency_mode <= 1) && (pHddCtx->no_of_sessions[WLAN_HDD_INFRA_STATION] <=1)) { //we are ok to do AMP @@ -2894,7 +2927,7 @@ static int wlan_hdd_tdls_add_station(struct wiphy *wiphy, } /* when others are on-going, we want to change link_status to idle */ - if (wlan_hdd_tdls_is_progress(pAdapter, mac, TRUE)) + if (NULL != wlan_hdd_tdls_is_progress(pHddCtx, mac, TRUE, TRUE)) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: " MAC_ADDRESS_STR @@ -2929,23 +2962,30 @@ static int wlan_hdd_tdls_add_station(struct wiphy *wiphy, if (0 == update) wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_CONNECTING); + /* debug code */ if (NULL != StaParams) { VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "%s: TDLS Peer Parameters.", __func__); - VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, - "ht_capa->cap_info: %0x", StaParams->HTCap.capInfo); - VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, - "ht_capa->extended_capabilities: %0x", - StaParams->HTCap.extendedHtCapInfo); + if(StaParams->htcap_present) + { + VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, + "ht_capa->cap_info: %0x", StaParams->HTCap.capInfo); + VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, + "ht_capa->extended_capabilities: %0x", + StaParams->HTCap.extendedHtCapInfo); + } VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "params->capability: %0x",StaParams->capability); VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "params->ext_capab_len: %0x",StaParams->extn_capability); - VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, - "rxMcsMap %x rxHighest %x txMcsMap %x txHighest %x", - StaParams->VHTCap.suppMcs.rxMcsMap, StaParams->VHTCap.suppMcs.rxHighest, - StaParams->VHTCap.suppMcs.txMcsMap, StaParams->VHTCap.suppMcs.txHighest); + if(StaParams->vhtcap_present) + { + VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, + "rxMcsMap %x rxHighest %x txMcsMap %x txHighest %x", + StaParams->VHTCap.suppMcs.rxMcsMap, StaParams->VHTCap.suppMcs.rxHighest, + StaParams->VHTCap.suppMcs.txMcsMap, StaParams->VHTCap.suppMcs.txHighest); + } { int i = 0; VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "Supported rates:"); @@ -2953,6 +2993,12 @@ static int wlan_hdd_tdls_add_station(struct wiphy *wiphy, VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "[%d]: %x ", i, StaParams->supported_rates[i]); } + } /* end debug code */ + else if ((1 == update) && (NULL == StaParams)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s : update is true, but staParams is NULL. Error!", __func__); + return -EPERM; } INIT_COMPLETION(pAdapter->tdls_add_station_comp); @@ -3001,6 +3047,8 @@ static int wlan_hdd_change_station(struct wiphy *wiphy, { VOS_STATUS status = VOS_STATUS_SUCCESS; hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev ); + hdd_context_t *pHddCtx; + hdd_station_ctx_t *pHddStaCtx; v_MACADDR_t STAMacAddress; #ifdef FEATURE_WLAN_TDLS tCsrStaParams StaParams = {0}; @@ -3008,7 +3056,24 @@ static int wlan_hdd_change_station(struct wiphy *wiphy, #endif ENTER(); - if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress ) + if ((NULL == pAdapter)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "invalid adapter "); + return -EINVAL; + } + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + + if ((NULL == pHddCtx) || (NULL == pHddStaCtx)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "invalid HDD state or HDD station context"); + return -EINVAL; + } + + if (pHddCtx->isLogpInProgress) { VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:LOGP in Progress. Ignore!!!", __func__); @@ -3022,16 +3087,20 @@ static int wlan_hdd_change_station(struct wiphy *wiphy, { if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) { - status = hdd_softap_change_STA_state( pAdapter, &STAMacAddress, + status = hdd_softap_change_STA_state( pAdapter, &STAMacAddress, WLANTL_STA_AUTHENTICATED); - VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR, - "%s: Station MAC address does not matching", __func__); - return -EINVAL; + if (status != VOS_STATUS_SUCCESS) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Not able to change TL state to AUTHENTICATED", __func__); + return -EINVAL; + } } } + else if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION) + || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)) { #ifdef FEATURE_WLAN_TDLS - else if (pAdapter->device_mode == WLAN_HDD_INFRA_STATION ) { if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) { StaParams.capability = params->capability; StaParams.uapsd_queues = params->uapsd_queues; @@ -3042,7 +3111,10 @@ static int wlan_hdd_change_station(struct wiphy *wiphy, sizeof(StaParams.extn_capability)); if (NULL != params->ht_capa) + { + StaParams.htcap_present = 1; vos_mem_copy(&StaParams.HTCap, params->ht_capa, sizeof(tSirHTCap)); + } StaParams.supported_rates_len = params->supported_rates_len; @@ -3069,7 +3141,10 @@ static int wlan_hdd_change_station(struct wiphy *wiphy, } if (NULL != params->vht_capa) + { + StaParams.vhtcap_present = 1; vos_mem_copy(&StaParams.VHTCap, params->vht_capa, sizeof(tSirVHTCap)); + } if (0 != params->ext_capab_len ) { /*Define A Macro : TODO Sunil*/ @@ -3092,38 +3167,12 @@ static int wlan_hdd_change_station(struct wiphy *wiphy, return -EINVAL; } } - } #endif - + } EXIT(); return status; } -/* - * FUNCTION: wlan_hdd_cfg80211_get_ibss_peer_staidx - * This function is used to get peer station index in IBSS mode - */ -static u8 wlan_hdd_cfg80211_get_ibss_peer_staidx(hdd_adapter_t* pAdapter) -{ - u8 idx = 0; - u8 temp[VOS_MAC_ADDR_SIZE] = {0}; - ENTER(); - memset(temp, 0, VOS_MAC_ADDR_SIZE); - for ( idx = 0; idx < HDD_MAX_NUM_IBSS_STA; idx++ ) - { - if ( (0 != - (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[idx]) - && memcmp((u8*)&(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.peerMacAddress[idx], - temp, VOS_MAC_ADDR_SIZE) - ) - { - return idx; - } - } - return idx; -} - - /* * FUNCTION: wlan_hdd_cfg80211_add_key * This function is used to initialize the key information @@ -3146,20 +3195,24 @@ static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy, hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev ); tCsrRoamSetKey setKey; u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; - int status = 0; + int status; v_U32_t roamId= 0xFF; v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext; hdd_hostapd_state_t *pHostapdState; VOS_STATUS vos_status; eHalStatus halStatus; + hdd_context_t *pHddCtx; ENTER(); - if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress ) + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EAGAIN; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return status; } hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d", @@ -3249,19 +3302,11 @@ static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy, return 0; } #endif - #ifdef FEATURE_WLAN_CCX case WLAN_CIPHER_SUITE_KRK: setKey.encType = eCSR_ENCRYPT_TYPE_KRK; break; #endif - -#ifdef WLAN_FEATURE_11W - case WLAN_CIPHER_SUITE_AES_CMAC: - setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC; - break; -#endif - default: hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unsupported cipher type %lu", __func__, params->cipher); @@ -3272,13 +3317,6 @@ static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy, __func__, setKey.encType); - - if ((pAdapter->device_mode == WLAN_HDD_SOFTAP) - || (pAdapter->device_mode == WLAN_HDD_P2P_GO) - ) - { - - if ( #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)) (!pairwise) @@ -3304,6 +3342,9 @@ static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy, vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN); } + if ((pAdapter->device_mode == WLAN_HDD_SOFTAP) || + (pAdapter->device_mode == WLAN_HDD_P2P_GO)) + { pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter); if( pHostapdState->bssState == BSS_START ) { @@ -3338,6 +3379,22 @@ static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy, hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)) + if (!pairwise) +#else + if (!mac_addr || is_broadcast_ether_addr(mac_addr)) +#endif + { + /* set group key*/ + if (pHddStaCtx->roam_info.deferKeyComplete) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s- %d: Perform Set key Complete", + __func__, __LINE__); + hdd_PerformRoamSetKeyComplete(pAdapter); + } + } + pWextState->roamProfile.Keys.KeyLength[key_index] = (u8)params->key_len; pWextState->roamProfile.Keys.defaultIndex = key_index; @@ -3346,119 +3403,14 @@ static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy, vos_mem_copy(&pWextState->roamProfile.Keys.KeyMaterial[key_index][0], params->key, params->key_len); - pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY; - - if (!( ( IW_AUTH_KEY_MGMT_802_1X - == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) - && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType) - ) - && - ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher) - || (WLAN_CIPHER_SUITE_WEP104 == params->cipher) - ) - ) - { - /* in case of static WEP, macaddr/bssid is not coming from nl80211 - * interface, copy bssid for pairwise key and group macaddr for - * group key initialization*/ - - tCsrRoamProfile *pRoamProfile = &pWextState->roamProfile; - - pWextState->roamProfile.negotiatedUCEncryptionType = - pHddStaCtx->conn_info.ucEncryptionType = - ((WLAN_CIPHER_SUITE_WEP40 == params->cipher) ? - eCSR_ENCRYPT_TYPE_WEP40_STATICKEY : - eCSR_ENCRYPT_TYPE_WEP104_STATICKEY); - - - hddLog(VOS_TRACE_LEVEL_INFO_MED, - "%s: Negotiated encryption type %d", __func__, - pWextState->roamProfile.negotiatedUCEncryptionType); - sme_SetCfgPrivacy((tpAniSirGlobal)WLAN_HDD_GET_HAL_CTX(pAdapter), - &pWextState->roamProfile, true); - setKey.keyLength = 0; - setKey.keyDirection = eSIR_TX_RX; - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)) - if (pairwise) - { -#endif - if (mac_addr) - { - vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN); - } - else - { - /* macaddr is NULL, set the peerMac to bssId in case of BSS, - * and peerMacAddress in case of IBSS*/ - if (eCSR_BSS_TYPE_START_IBSS == pRoamProfile->BSSType) - { - u8 staidx = wlan_hdd_cfg80211_get_ibss_peer_staidx(pAdapter); - if (HDD_MAX_NUM_IBSS_STA != staidx) - { - vos_mem_copy(setKey.peerMac, - &pHddStaCtx->conn_info.peerMacAddress[staidx], - WNI_CFG_BSSID_LEN); - - } - else - { - hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No peerMac found", - __func__); - return -EOPNOTSUPP; - } - } - else - { - vos_mem_copy(setKey.peerMac, - &pHddStaCtx->conn_info.bssId[0], - WNI_CFG_BSSID_LEN); - } - } -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)) - } - else - { - /* set group key*/ - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - "%s- %d: setting Group key", - __func__, __LINE__); - setKey.keyDirection = eSIR_RX_ONLY; - vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN); - } -#endif - } - else if ( -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)) - (!pairwise) -#else - (!mac_addr || is_broadcast_ether_addr(mac_addr)) -#endif - ) - { - /* set group key*/ - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - "%s- %d: setting Group key", - __func__, __LINE__); - setKey.keyDirection = eSIR_RX_ONLY; - vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN); - } - else - { - /* set pairwise key*/ - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - "%s- %d: setting pairwise key", - __func__, __LINE__); - setKey.keyDirection = eSIR_TX_RX; - vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN); - } + pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY; - hddLog(VOS_TRACE_LEVEL_INFO_MED, + hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set key for peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d", - __func__, setKey.peerMac[0], setKey.peerMac[1], - setKey.peerMac[2], setKey.peerMac[3], - setKey.peerMac[4], setKey.peerMac[5], + __func__, setKey.peerMac[0], setKey.peerMac[1], + setKey.peerMac[2], setKey.peerMac[3], + setKey.peerMac[4], setKey.peerMac[5], setKey.keyDirection); vos_status = wlan_hdd_check_ula_done(pAdapter); @@ -3476,11 +3428,20 @@ static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy, } #ifdef WLAN_FEATURE_VOWIFI_11R - /* The supplicant may attempt to set the PTK once pre-authentication is done. - Save the key in the UMAC and include it in the ADD BSS request */ + /* The supplicant may attempt to set the PTK once pre-authentication + is done. Save the key in the UMAC and include it in the ADD BSS + request */ halStatus = sme_FTUpdateKey( WLAN_HDD_GET_HAL_CTX(pAdapter), &setKey); - if( halStatus == eHAL_STATUS_FT_PREAUTH_KEY_WAIT ) + if ( halStatus == eHAL_STATUS_FT_PREAUTH_KEY_SUCCESS ) + { + hddLog(VOS_TRACE_LEVEL_INFO_MED, + "%s: Update PreAuth Key success", __func__); + return 0; + } + else if ( halStatus == eHAL_STATUS_FT_PREAUTH_KEY_FAILED ) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Update PreAuth Key failed", __func__); return -EINVAL; } #endif /* WLAN_FEATURE_VOWIFI_11R */ @@ -3491,19 +3452,19 @@ static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy, if ( 0 != status ) { - hddLog(VOS_TRACE_LEVEL_ERROR, + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_RoamSetKey failed, returned %d", __func__, status); pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE; return -EINVAL; } - /* in case of IBSS as there was no information available about WEP keys during - * IBSS join, group key intialized with NULL key, so re-initialize group key + /* in case of IBSS as there was no information available about WEP keys during + * IBSS join, group key intialized with NULL key, so re-initialize group key * with correct value*/ - if ( (eCSR_BSS_TYPE_START_IBSS == pWextState->roamProfile.BSSType) && - !( ( IW_AUTH_KEY_MGMT_802_1X - == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) + if ( (eCSR_BSS_TYPE_START_IBSS == pWextState->roamProfile.BSSType) && + !( ( IW_AUTH_KEY_MGMT_802_1X + == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType) ) && @@ -3515,20 +3476,20 @@ static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy, setKey.keyDirection = eSIR_RX_ONLY; vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN); - hddLog(VOS_TRACE_LEVEL_INFO_MED, + hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set key peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d", - __func__, setKey.peerMac[0], setKey.peerMac[1], - setKey.peerMac[2], setKey.peerMac[3], - setKey.peerMac[4], setKey.peerMac[5], + __func__, setKey.peerMac[0], setKey.peerMac[1], + setKey.peerMac[2], setKey.peerMac[3], + setKey.peerMac[4], setKey.peerMac[5], setKey.keyDirection); - status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter), + status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, &setKey, &roamId ); if ( 0 != status ) { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: sme_RoamSetKey failed for group key (IBSS), returned %d", + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: sme_RoamSetKey failed for group key (IBSS), returned %d", __func__, status); pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE; return -EINVAL; @@ -3544,38 +3505,38 @@ static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy, * This function is used to get the key information */ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)) -static int wlan_hdd_cfg80211_get_key( - struct wiphy *wiphy, +static int wlan_hdd_cfg80211_get_key( + struct wiphy *wiphy, struct net_device *ndev, - u8 key_index, bool pairwise, + u8 key_index, bool pairwise, const u8 *mac_addr, void *cookie, void (*callback)(void *cookie, struct key_params*) ) #else -static int wlan_hdd_cfg80211_get_key( - struct wiphy *wiphy, +static int wlan_hdd_cfg80211_get_key( + struct wiphy *wiphy, struct net_device *ndev, u8 key_index, const u8 *mac_addr, void *cookie, void (*callback)(void *cookie, struct key_params*) ) #endif { - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev ); + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev ); hdd_wext_state_t *pWextState= WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile); struct key_params params; ENTER(); - + hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n", __func__,pAdapter->device_mode); - + memset(¶ms, 0, sizeof(params)); if (CSR_MAX_NUM_KEY <= key_index) { return -EINVAL; - } + } switch(pRoamProfile->EncryptionType.encryptionType[0]) { @@ -3619,14 +3580,14 @@ static int wlan_hdd_cfg80211_get_key( * This function is used to delete the key information */ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)) -static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy, +static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy, struct net_device *ndev, - u8 key_index, - bool pairwise, + u8 key_index, + bool pairwise, const u8 *mac_addr ) #else -static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy, +static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy, struct net_device *ndev, u8 key_index, const u8 *mac_addr @@ -3636,17 +3597,17 @@ static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy, int status = 0; //This code needs to be revisited. There is sme_removeKey API, we should - //plan to use that. After the change to use correct index in setkey, + //plan to use that. After the change to use correct index in setkey, //it is observed that this is invalidating peer //key index whenever re-key is done. This is affecting data link. //It should be ok to ignore del_key. #if 0 - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev ); - v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev ); + v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext; u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; tCsrRoamSetKey setKey; v_U32_t roamId= 0xFF; - + ENTER(); hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device_mode = %d\n", @@ -3654,7 +3615,7 @@ static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy, if (CSR_MAX_NUM_KEY <= key_index) { - hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__, + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__, key_index); return -EINVAL; @@ -3672,15 +3633,15 @@ static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy, if ((pAdapter->device_mode == WLAN_HDD_SOFTAP) || (pAdapter->device_mode == WLAN_HDD_P2P_GO) - ) - { - - hdd_hostapd_state_t *pHostapdState = + ) + { + + hdd_hostapd_state_t *pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter); if( pHostapdState->bssState == BSS_START) { status = WLANSAP_SetKeySta( pVosContext, &setKey); - + if ( status != eHAL_STATUS_SUCCESS ) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, @@ -3690,27 +3651,27 @@ static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy, } } else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION) - || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT) + || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT) ) { hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); - pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY; - - hddLog(VOS_TRACE_LEVEL_INFO_MED, + pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY; + + hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: delete key for peerMac %2x:%2x:%2x:%2x:%2x:%2x", - __func__, setKey.peerMac[0], setKey.peerMac[1], - setKey.peerMac[2], setKey.peerMac[3], + __func__, setKey.peerMac[0], setKey.peerMac[1], + setKey.peerMac[2], setKey.peerMac[3], setKey.peerMac[4], setKey.peerMac[5]); - if(pAdapter->sessionCtx.station.conn_info.connState == - eConnectionState_Associated) + if(pAdapter->sessionCtx.station.conn_info.connState == + eConnectionState_Associated) { - status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter), + status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, &setKey, &roamId ); - + if ( 0 != status ) { - hddLog(VOS_TRACE_LEVEL_ERROR, + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_RoamSetKey failure, returned %d", __func__, status); pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE; @@ -3738,78 +3699,109 @@ static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy, u8 key_index) #endif { - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev ); - hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); - int status = 0; - hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev ); + int status; + hdd_wext_state_t *pWextState; + hdd_station_ctx_t *pHddStaCtx; + hdd_context_t *pHddCtx; ENTER(); + if ((NULL == pAdapter)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "invalid adapter"); + return -EINVAL; + } + + pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + + if ((NULL == pWextState) || (NULL == pHddStaCtx)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "invalid Wext state or HDD context"); + return -EINVAL; + } + hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d key_index = %d \n", __func__,pAdapter->device_mode, key_index); - + if (CSR_MAX_NUM_KEY <= key_index) { - hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__, + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__, key_index); return -EINVAL; } - if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress ) + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EAGAIN; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return status; } - + if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION) || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT) - ) + ) { - if ( (key_index != pWextState->roamProfile.Keys.defaultIndex) && - (eCSR_ENCRYPT_TYPE_TKIP != + if ( (eCSR_ENCRYPT_TYPE_TKIP != pWextState->roamProfile.EncryptionType.encryptionType[0]) && - (eCSR_ENCRYPT_TYPE_AES != + (eCSR_ENCRYPT_TYPE_AES != pWextState->roamProfile.EncryptionType.encryptionType[0]) ) - { - /* if default key index is not same as previous one, + { + /* if default key index is not same as previous one, * then update the default key index */ - + tCsrRoamSetKey setKey; v_U32_t roamId= 0xFF; tCsrKeys *Keys = &pWextState->roamProfile.Keys; - - hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: default tx key index %d", + + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: default tx key index %d", __func__, key_index); - + Keys->defaultIndex = (u8)key_index; vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey)); setKey.keyId = key_index; setKey.keyLength = Keys->KeyLength[key_index]; - - vos_mem_copy(&setKey.Key[0], - &Keys->KeyMaterial[key_index][0], + + vos_mem_copy(&setKey.Key[0], + &Keys->KeyMaterial[key_index][0], Keys->KeyLength[key_index]); - - setKey.keyDirection = eSIR_TX_ONLY; - - vos_mem_copy(setKey.peerMac, + setKey.keyDirection = eSIR_TX_RX; + vos_mem_copy(setKey.peerMac, &pHddStaCtx->conn_info.bssId[0], WNI_CFG_BSSID_LEN); - - setKey.encType = + if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN && + pWextState->roamProfile.EncryptionType.encryptionType[0] == + eCSR_ENCRYPT_TYPE_WEP104) + { + /*In the case of dynamic wep supplicant hardcodes DWEP type to eCSR_ENCRYPT_TYPE_WEP104 + even though ap is configured for WEP-40 encryption. In this canse the key length + is 5 but the encryption type is 104 hence checking the key langht(5) and encryption + type(104) and switching encryption type to 40*/ + pWextState->roamProfile.EncryptionType.encryptionType[0] = + eCSR_ENCRYPT_TYPE_WEP40; + pWextState->roamProfile.mcEncryptionType.encryptionType[0] = + eCSR_ENCRYPT_TYPE_WEP40; + } + + setKey.encType = pWextState->roamProfile.EncryptionType.encryptionType[0]; - + /* issue set key request */ - status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter), + status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, &setKey, &roamId ); - + if ( 0 != status ) { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: sme_RoamSetKey failed, returned %d", __func__, + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: sme_RoamSetKey failed, returned %d", __func__, status); return -EINVAL; } @@ -3830,7 +3822,7 @@ static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy, pAPCtx->wepKey[key_index].keyDirection = eSIR_TX_DEFAULT; } } - + return status; } @@ -3893,8 +3885,8 @@ static struct cfg80211_bss* wlan_hdd_cfg80211_inform_bss( { rssi = (VOS_MIN ((pBssDesc->rssi + pBssDesc->sinr), 0))*100; - return (cfg80211_inform_bss(wiphy, chan, pBssDesc->bssId, - le64_to_cpu(*(__le64 *)pBssDesc->timeStamp), + return (cfg80211_inform_bss(wiphy, chan, pBssDesc->bssId, + le64_to_cpu(*(__le64 *)pBssDesc->timeStamp), pBssDesc->capabilityInfo, pBssDesc->beaconInterval, ie, ie_length, rssi, GFP_KERNEL )); @@ -3944,6 +3936,8 @@ wlan_hdd_cfg80211_inform_bss_frame( hdd_adapter_t *pAdapter, struct cfg80211_bss *bss_status = NULL; size_t frame_len = sizeof (struct ieee80211_mgmt) + ie_length; int rssi = 0; + hdd_context_t *pHddCtx; + int status; #ifdef WLAN_OPEN_SOURCE struct timespec ts; #endif @@ -3953,6 +3947,16 @@ wlan_hdd_cfg80211_inform_bss_frame( hdd_adapter_t *pAdapter, if (!mgmt) return NULL; + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return NULL; + } + memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN); #ifdef WLAN_OPEN_SOURCE @@ -3997,14 +4001,13 @@ wlan_hdd_cfg80211_inform_bss_frame( hdd_adapter_t *pAdapter, (u16)(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON); } - #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38)) - if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ) && + if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ) && (wiphy->bands[IEEE80211_BAND_2GHZ] != NULL)) { freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ); } - else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_GHZ)) && + else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_GHZ)) && (wiphy->bands[IEEE80211_BAND_5GHZ] != NULL)) { @@ -4038,13 +4041,14 @@ wlan_hdd_cfg80211_inform_bss_frame( hdd_adapter_t *pAdapter, return NULL; } /*To keep the rssi icon of the connected AP in the scan window - *and the rssi icon of the wireless networks in sync + *and the rssi icon of the wireless networks in sync * */ if (( eConnectionState_Associated == pAdapter->sessionCtx.station.conn_info.connState ) && ( VOS_TRUE == vos_mem_compare(bss_desc->bssId, pAdapter->sessionCtx.station.conn_info.bssId, - WNI_CFG_BSSID_LEN))) + WNI_CFG_BSSID_LEN)) && + (pHddCtx->hdd_wlan_suspended == FALSE)) { /* supplicant takes the signal strength in terms of mBm(100*dBm) */ rssi = (pAdapter->rssi * 100); @@ -4064,7 +4068,7 @@ wlan_hdd_cfg80211_inform_bss_frame( hdd_adapter_t *pAdapter, * FUNCTION: wlan_hdd_cfg80211_update_bss_db * This function is used to update the BSS data base of CFG8011 */ -struct cfg80211_bss* wlan_hdd_cfg80211_update_bss_db( hdd_adapter_t *pAdapter, +struct cfg80211_bss* wlan_hdd_cfg80211_update_bss_db( hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo ) { @@ -4079,7 +4083,7 @@ struct cfg80211_bss* wlan_hdd_cfg80211_update_bss_db( hdd_adapter_t *pAdapter, if (NULL != roamProfile.pBssDesc) { - bss = wlan_hdd_cfg80211_inform_bss(pAdapter, + bss = wlan_hdd_cfg80211_inform_bss(pAdapter, &roamProfile); if (NULL == bss) @@ -4101,10 +4105,10 @@ struct cfg80211_bss* wlan_hdd_cfg80211_update_bss_db( hdd_adapter_t *pAdapter, /* * FUNCTION: wlan_hdd_cfg80211_update_bss */ -static int wlan_hdd_cfg80211_update_bss( struct wiphy *wiphy, - hdd_adapter_t *pAdapter +static int wlan_hdd_cfg80211_update_bss( struct wiphy *wiphy, + hdd_adapter_t *pAdapter ) -{ +{ tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); tCsrScanResultInfo *pScanResult; eHalStatus status = 0; @@ -4135,20 +4139,20 @@ static int wlan_hdd_cfg80211_update_bss( struct wiphy *wiphy, while (pScanResult) { - /* - * cfg80211_inform_bss() is not updating ie field of bss entry, if - * entry already exists in bss data base of cfg80211 for that - * particular BSS ID. Using cfg80211_inform_bss_frame to update the - * bss entry instead of cfg80211_inform_bss, But this call expects - * mgmt packet as input. As of now there is no possibility to get - * the mgmt(probe response) frame from PE, converting bss_desc to + /* + * cfg80211_inform_bss() is not updating ie field of bss entry, if + * entry already exists in bss data base of cfg80211 for that + * particular BSS ID. Using cfg80211_inform_bss_frame to update the + * bss entry instead of cfg80211_inform_bss, But this call expects + * mgmt packet as input. As of now there is no possibility to get + * the mgmt(probe response) frame from PE, converting bss_desc to * ieee80211_mgmt(probe response) and passing to c * fg80211_inform_bss_frame. * */ bss_status = wlan_hdd_cfg80211_inform_bss_frame(pAdapter, &pScanResult->BssDescriptor); - + if (NULL == bss_status) { @@ -4163,15 +4167,15 @@ static int wlan_hdd_cfg80211_update_bss( struct wiphy *wiphy, pScanResult = sme_ScanResultGetNext(hHal, pResult); } - sme_ScanResultPurge(hHal, pResult); + sme_ScanResultPurge(hHal, pResult); - return 0; + return 0; } void hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel) { - VOS_TRACE(VOS_MODULE_ID_HDD, logLevel, + VOS_TRACE(VOS_MODULE_ID_HDD, logLevel, "%02X:%02X:%02X:%02X:%02X:%02X\n", macAddr[0], macAddr[1], macAddr[2], macAddr[3], macAddr[4], macAddr[5]); @@ -4180,7 +4184,7 @@ hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel) void hddPrintPmkId(tANI_U8 *pmkId, tANI_U8 logLevel) { - VOS_TRACE(VOS_MODULE_ID_HDD, logLevel, + VOS_TRACE(VOS_MODULE_ID_HDD, logLevel, "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", pmkId[0], pmkId[1], pmkId[2], pmkId[3], pmkId[4], pmkId[5], pmkId[6], pmkId[7], pmkId[8], pmkId[9], pmkId[10], @@ -4213,7 +4217,7 @@ hddPrintPmkId(tANI_U8 *pmkId, tANI_U8 logLevel) * This function is used to notify the supplicant of a new PMKSA candidate. */ int wlan_hdd_cfg80211_pmksa_candidate_notify( - hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo, + hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo, int index, bool preauth ) { #ifdef FEATURE_WLAN_OKC @@ -4236,7 +4240,7 @@ int wlan_hdd_cfg80211_pmksa_candidate_notify( pRoamInfo->bssid, preauth, GFP_KERNEL); } #endif /* FEATURE_WLAN_OKC */ - return 0; + return 0; } #endif //FEATURE_WLAN_LFR @@ -4245,11 +4249,11 @@ int wlan_hdd_cfg80211_pmksa_candidate_notify( * scanning callback function, called after finishing scan * */ -static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle, +static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle, void *pContext, tANI_U32 scanId, eCsrScanStatus status) { struct net_device *dev = (struct net_device *) pContext; - //struct wireless_dev *wdev = dev->ieee80211_ptr; + //struct wireless_dev *wdev = dev->ieee80211_ptr; hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev ); hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info; @@ -4260,7 +4264,7 @@ static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle, hddLog(VOS_TRACE_LEVEL_INFO, "%s called with halHandle = %p, pContext = %p," - "scanID = %d, returned status = %d\n", + "scanID = %d, returned status = %d\n", __func__, halHandle, pContext, (int) scanId, (int) status); //Block on scan req completion variable. Can't wait forever though. @@ -4280,19 +4284,19 @@ static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle, } /* Check the scanId */ - if (pScanInfo->scanId != scanId) + if (pScanInfo->scanId != scanId) { hddLog(VOS_TRACE_LEVEL_INFO, "%s called with mismatched scanId pScanInfo->scanId = %d " - "scanId = %d \n", __func__, (int) pScanInfo->scanId, + "scanId = %d \n", __func__, (int) pScanInfo->scanId, (int) scanId); } - ret = wlan_hdd_cfg80211_update_bss((WLAN_HDD_GET_CTX(pAdapter))->wiphy, + ret = wlan_hdd_cfg80211_update_bss((WLAN_HDD_GET_CTX(pAdapter))->wiphy, pAdapter); if (0 > ret) - hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__); + hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__); /* If any client wait scan result through WEXT @@ -4333,7 +4337,7 @@ static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle, /* * setting up 0, just in case. - */ + */ req->n_ssids = 0; req->n_channels = 0; req->ie = 0; @@ -4357,7 +4361,7 @@ static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle, * immediatly after the driver gets connect request(i.e after scan) * from supplicant, this result in app's is suspending and not able * to process the connect request to AP */ - hdd_allow_suspend_timeout(100); + hdd_allow_suspend_timeout(1000); #ifdef FEATURE_WLAN_TDLS wlan_hdd_tdls_scan_done_callback(pAdapter); @@ -4390,7 +4394,7 @@ v_BOOL_t hdd_isScanAllowed( hdd_context_t *pHddCtx ) if( pAdapter ) { hddLog(VOS_TRACE_LEVEL_INFO, - "%s: Adapter with device mode %d exists", + "%s: Adapter with device mode %d exists", __func__, pAdapter->device_mode); if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) || @@ -4403,7 +4407,7 @@ v_BOOL_t hdd_isScanAllowed( hdd_context_t *pHddCtx ) staMac = (v_U8_t *) &(pAdapter->macAddressCurrent.bytes[0]); hddLog(VOS_TRACE_LEVEL_ERROR, "%s: client %02x:%02x:%02x:%02x:%02x:%02x is in the " - "middle of WPS/EAPOL exchange.", __func__, + "middle of WPS/EAPOL exchange.", __func__, staMac[0], staMac[1], staMac[2], staMac[3], staMac[4], staMac[5]); return VOS_FALSE; @@ -4414,14 +4418,14 @@ v_BOOL_t hdd_isScanAllowed( hdd_context_t *pHddCtx ) { for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++) { - if ((pAdapter->aStaInfo[staId].isUsed) && + if ((pAdapter->aStaInfo[staId].isUsed) && (WLANTL_STA_CONNECTED == pAdapter->aStaInfo[staId].tlSTAState)) { staMac = (v_U8_t *) &(pAdapter->aStaInfo[staId].macAddrSTA.bytes[0]); hddLog(VOS_TRACE_LEVEL_ERROR, "%s: client %02x:%02x:%02x:%02x:%02x:%02x of SoftAP/P2P-GO is in the " - "middle of WPS/EAPOL exchange.", __func__, + "middle of WPS/EAPOL exchange.", __func__, staMac[0], staMac[1], staMac[2], staMac[3], staMac[4], staMac[5]); return VOS_FALSE; @@ -4435,7 +4439,7 @@ v_BOOL_t hdd_isScanAllowed( hdd_context_t *pHddCtx ) hddLog(VOS_TRACE_LEVEL_INFO, "%s: Scan allowed", __func__); return VOS_TRUE; -} +} /* * FUNCTION: wlan_hdd_cfg80211_scan @@ -4451,15 +4455,15 @@ int wlan_hdd_cfg80211_scan( struct wiphy *wiphy, #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) struct net_device *dev = request->wdev->netdev; #endif - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev ); + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev ); hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter ); hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); - hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini; + hdd_config_t *cfg_param = NULL; tCsrScanRequest scanRequest; tANI_U8 *channelList = NULL, i; v_U32_t scanId = 0; - int status = 0; - hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info; + int status; + hdd_scaninfo_t *pScanInfo = NULL; v_U8_t* pP2pIe = NULL; ENTER(); @@ -4467,6 +4471,18 @@ int wlan_hdd_cfg80211_scan( struct wiphy *wiphy, hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n", __func__,pAdapter->device_mode); + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return status; + } + + cfg_param = pHddCtx->cfg_ini; + pScanInfo = &pHddCtx->scan_info; + if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) && (eConnectionState_Connecting == (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState)) @@ -4501,20 +4517,7 @@ int wlan_hdd_cfg80211_scan( struct wiphy *wiphy, return -EBUSY; } - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EAGAIN; - } - - if ((WLAN_HDD_GET_CTX(pAdapter))->isLoadUnloadInProgress) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, - "%s:Unloading/Loading in Progress. Ignore!!!", __func__); - return -EAGAIN; - } - //Don't Allow Scan and return busy if Remain On + //Don't Allow Scan and return busy if Remain On //Channel and action frame is pending //Otherwise Cancel Remain On Channel and allow Scan //If no action frame pending @@ -4546,13 +4549,13 @@ int wlan_hdd_cfg80211_scan( struct wiphy *wiphy, VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR, "%s: Acquire lock fail", __func__); return -EAGAIN; - } + } if (TRUE == pHddCtx->tmInfo.tmAction.enterImps) { hddLog(VOS_TRACE_LEVEL_WARN, "%s: MAX TM Level Scan not allowed", __func__); mutex_unlock(&pHddCtx->tmInfo.tmOperationLock); - return -EBUSY; + return -EBUSY; } mutex_unlock(&pHddCtx->tmInfo.tmOperationLock); @@ -4563,13 +4566,13 @@ int wlan_hdd_cfg80211_scan( struct wiphy *wiphy, hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Scan not allowed", __func__); return -EBUSY; } - + vos_mem_zero( &scanRequest, sizeof(scanRequest)); if (NULL != request) { hddLog(VOS_TRACE_LEVEL_INFO, "scan request for ssid = %d", - (int)request->n_ssids); + (int)request->n_ssids); /* Even though supplicant doesn't provide any SSIDs, n_ssids is set to 1. * Becasue of this, driver is assuming that this is not wildcard scan and so @@ -4621,7 +4624,7 @@ int wlan_hdd_cfg80211_scan( struct wiphy *wiphy, /*Set the scan type to default type, in this case it is ACTIVE*/ scanRequest.scanType = pScanInfo->scan_mode; } - scanRequest.minChnTime = cfg_param->nActiveMinChnTime; + scanRequest.minChnTime = cfg_param->nActiveMinChnTime; scanRequest.maxChnTime = cfg_param->nActiveMaxChnTime; } else @@ -4661,16 +4664,16 @@ int wlan_hdd_cfg80211_scan( struct wiphy *wiphy, /* set requestType to full scan */ scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN; - - /* Flush the scan results(only p2p beacons) for STA scan and P2P + + /* Flush the scan results(only p2p beacons) for STA scan and P2P * search (Flush on both full scan and social scan but not on single - * channel scan).P2P search happens on 3 social channels (1, 6, 11) + * channel scan).P2P search happens on 3 social channels (1, 6, 11) */ /* Supplicant does single channel scan after 8-way handshake - * and in that case driver shoudnt flush scan results. If - * driver flushes the scan results here and unfortunately if - * the AP doesnt respond to our probe req then association + * and in that case driver shoudnt flush scan results. If + * driver flushes the scan results here and unfortunately if + * the AP doesnt respond to our probe req then association * fails which is not desired */ @@ -4810,9 +4813,9 @@ int wlan_hdd_cfg80211_scan( struct wiphy *wiphy, /* * FUNCTION: wlan_hdd_cfg80211_connect_start - * This function is used to start the association process + * This function is used to start the association process */ -int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter, +int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter, const u8 *ssid, size_t ssid_len, const u8 *bssid, u8 operatingChannel) { int status = 0; @@ -4825,7 +4828,7 @@ int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter, ENTER(); pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); - + if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) { hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wrong SSID len", __func__); @@ -4834,7 +4837,7 @@ int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter, pRoamProfile = &pWextState->roamProfile; - if (pRoamProfile) + if (pRoamProfile) { int ret = 0; hdd_station_ctx_t *pHddStaCtx; @@ -4847,7 +4850,7 @@ int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter, { /* Issue disconnect to CSR */ INIT_COMPLETION(pAdapter->disconnect_comp_var); - if( eHAL_STATUS_SUCCESS == + if( eHAL_STATUS_SUCCESS == sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, eCSR_DISCONNECT_REASON_UNSPECIFIED ) ) @@ -4872,7 +4875,7 @@ int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter, } } - if (HDD_WMM_USER_MODE_NO_QOS == + if (HDD_WMM_USER_MODE_NO_QOS == (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->WmmMode) { /*QoS not enabled in cfg file*/ @@ -4881,14 +4884,14 @@ int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter, else { /*QoS enabled, update uapsd mask from cfg file*/ - pRoamProfile->uapsd_mask = + pRoamProfile->uapsd_mask = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask; } pRoamProfile->SSIDs.numOfSSIDs = 1; pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len; vos_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId, - sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId)); + sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId)); vos_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId), ssid, ssid_len); @@ -4897,8 +4900,8 @@ int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter, pRoamProfile->BSSIDs.numOfBSSIDs = 1; vos_mem_copy((void *)(pRoamProfile->BSSIDs.bssid), bssid, WNI_CFG_BSSID_LEN); - /* Save BSSID in seperate variable as well, as RoamProfile - BSSID is getting zeroed out in the association process. And in + /* Save BSSID in seperate variable as well, as RoamProfile + BSSID is getting zeroed out in the association process. And in case of join failure we should send valid BSSID to supplicant */ vos_mem_copy((void *)(pWextState->req_bssId), bssid, @@ -4907,28 +4910,12 @@ int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter, if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) || (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) - { + { /*set gen ie*/ hdd_SetGENIEToCsr(pAdapter, &RSNAuthType); /*set auth*/ hdd_set_csr_auth_type(pAdapter, RSNAuthType); } - else if ( (pWextState->roamProfile.AuthType.authType[0] == - eCSR_AUTH_TYPE_OPEN_SYSTEM) - && ((pWextState->roamProfile.EncryptionType.encryptionType[0] == - eCSR_ENCRYPT_TYPE_WEP40_STATICKEY) - || (pWextState->roamProfile.EncryptionType.encryptionType[0] == - eCSR_ENCRYPT_TYPE_WEP104_STATICKEY)) - ) - { - /*Android UI not having any option to configure the Authentication type to OPEN/SHARED; - * The authentication type will be always eCSR_AUTH_TYPE_OPEN_SYSTEM when WEP is used - * Use eCSR_AUTH_TYPE_AUTOSWITCH when WEP encryption used*/ - (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType = - eCSR_AUTH_TYPE_AUTOSWITCH; - pWextState->roamProfile.AuthType.authType[0] = - (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType; - } #ifdef FEATURE_WLAN_WAPI if (pAdapter->wapi_info.nWapiMode) { @@ -4979,27 +4966,24 @@ int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter, pRoamProfile->ChannelInfo.ChannelList = &operatingChannel; pRoamProfile->ChannelInfo.numOfChannels = 1; } - else - { - pRoamProfile->ChannelInfo.ChannelList = NULL; - pRoamProfile->ChannelInfo.numOfChannels = 0; - } /* change conn_state to connecting before sme_RoamConnect(), because sme_RoamConnect() * has a direct path to call hdd_smeRoamCallback(), which will change the conn_state - * If direct path, conn_state will be accordingly changed to NotConnected or Associated + * If direct path, conn_state will be accordingly changed to NotConnected or Associated * by either hdd_AssociationCompletionHandler() or hdd_DisConnectHandler() in sme_RoamCallback() * if sme_RomConnect is to be queued, Connecting state will remain until it is completed. */ - if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) + if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode || + WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), eConnectionState_Connecting); - - status = sme_RoamConnect( WLAN_HDD_GET_HAL_CTX(pAdapter), + + status = sme_RoamConnect( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, pRoamProfile, &roamId); - if( (eHAL_STATUS_SUCCESS != status) && - (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ) + if ((eHAL_STATUS_SUCCESS != status) && + (WLAN_HDD_INFRA_STATION == pAdapter->device_mode || + WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)) { hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_RoamConnect (session %d) failed with " @@ -5030,32 +5014,37 @@ int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter, static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter, enum nl80211_auth_type auth_type) { - hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); ENTER(); /*set authentication type*/ - switch (auth_type) + switch (auth_type) { - case NL80211_AUTHTYPE_OPEN_SYSTEM: case NL80211_AUTHTYPE_AUTOMATIC: + hddLog(VOS_TRACE_LEVEL_INFO, + "%s: set authentication type to AUTOSWITCH", __func__); + pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH; + break; + + case NL80211_AUTHTYPE_OPEN_SYSTEM: #ifdef WLAN_FEATURE_VOWIFI_11R case NL80211_AUTHTYPE_FT: #endif /* WLAN_FEATURE_VOWIFI_11R */ - hddLog(VOS_TRACE_LEVEL_INFO, + hddLog(VOS_TRACE_LEVEL_INFO, "%s: set authentication type to OPEN", __func__); pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM; break; case NL80211_AUTHTYPE_SHARED_KEY: - hddLog(VOS_TRACE_LEVEL_INFO, + hddLog(VOS_TRACE_LEVEL_INFO, "%s: set authentication type to SHARED", __func__); pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY; break; #ifdef FEATURE_WLAN_CCX case NL80211_AUTHTYPE_NETWORK_EAP: - hddLog(VOS_TRACE_LEVEL_INFO, + hddLog(VOS_TRACE_LEVEL_INFO, "%s: set authentication type to CCKM WPA", __func__); pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;//eCSR_AUTH_TYPE_CCKM_RSN needs to be handled as well if required. break; @@ -5063,14 +5052,14 @@ static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter, default: - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: Unsupported authentication type %d", __func__, + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Unsupported authentication type %d", __func__, auth_type); pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN; return -EINVAL; } - pWextState->roamProfile.AuthType.authType[0] = + pWextState->roamProfile.AuthType.authType[0] = pHddStaCtx->conn_info.authType; return 0; } @@ -5080,13 +5069,13 @@ static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter, * This function is used to set the key mgmt type(PSK/8021x). * */ -static int wlan_hdd_set_akm_suite( hdd_adapter_t *pAdapter, +static int wlan_hdd_set_akm_suite( hdd_adapter_t *pAdapter, u32 key_mgmt ) { hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); ENTER(); - + /*set key mgmt type*/ switch(key_mgmt) { @@ -5118,7 +5107,7 @@ static int wlan_hdd_set_akm_suite( hdd_adapter_t *pAdapter, #endif default: - hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported key mgmt type %d", + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported key mgmt type %d", __func__, key_mgmt); return -EINVAL; @@ -5128,56 +5117,48 @@ static int wlan_hdd_set_akm_suite( hdd_adapter_t *pAdapter, /* * FUNCTION: wlan_hdd_cfg80211_set_cipher - * This function is used to set the encryption type + * This function is used to set the encryption type * (NONE/WEP40/WEP104/TKIP/CCMP). */ -static int wlan_hdd_cfg80211_set_cipher( hdd_adapter_t *pAdapter, - u32 cipher, +static int wlan_hdd_cfg80211_set_cipher( hdd_adapter_t *pAdapter, + u32 cipher, bool ucast ) { eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE; - hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); ENTER(); - if (!cipher) + if (!cipher) { - hddLog(VOS_TRACE_LEVEL_ERROR, "%s: received cipher %d - considering none", + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: received cipher %d - considering none", __func__, cipher); encryptionType = eCSR_ENCRYPT_TYPE_NONE; } else { - + /*set encryption method*/ - switch (cipher) + switch (cipher) { case IW_AUTH_CIPHER_NONE: encryptionType = eCSR_ENCRYPT_TYPE_NONE; break; - + case WLAN_CIPHER_SUITE_WEP40: - if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) && - (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)) - encryptionType = eCSR_ENCRYPT_TYPE_WEP40; - else - encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY; + encryptionType = eCSR_ENCRYPT_TYPE_WEP40; break; - + case WLAN_CIPHER_SUITE_WEP104: - if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) && - (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)) - encryptionType = eCSR_ENCRYPT_TYPE_WEP104; - else - encryptionType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY; + encryptionType = eCSR_ENCRYPT_TYPE_WEP104; break; - + case WLAN_CIPHER_SUITE_TKIP: encryptionType = eCSR_ENCRYPT_TYPE_TKIP; break; - + case WLAN_CIPHER_SUITE_CCMP: encryptionType = eCSR_ENCRYPT_TYPE_AES; break; @@ -5193,7 +5174,7 @@ static int wlan_hdd_cfg80211_set_cipher( hdd_adapter_t *pAdapter, break; #endif default: - hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported cipher type %d", + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported cipher type %d", __func__, cipher); return -EOPNOTSUPP; } @@ -5201,16 +5182,16 @@ static int wlan_hdd_cfg80211_set_cipher( hdd_adapter_t *pAdapter, if (ucast) { - hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting unicast cipher type to %d", + hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting unicast cipher type to %d", __func__, encryptionType); pHddStaCtx->conn_info.ucEncryptionType = encryptionType; pWextState->roamProfile.EncryptionType.numEntries = 1; - pWextState->roamProfile.EncryptionType.encryptionType[0] = + pWextState->roamProfile.EncryptionType.encryptionType[0] = encryptionType; } else { - hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting mcast cipher type to %d", + hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting mcast cipher type to %d", __func__, encryptionType); pHddStaCtx->conn_info.mcEncryptionType = encryptionType; pWextState->roamProfile.mcEncryptionType.numEntries = 1; @@ -5225,8 +5206,8 @@ static int wlan_hdd_cfg80211_set_cipher( hdd_adapter_t *pAdapter, * FUNCTION: wlan_hdd_cfg80211_set_ie * This function is used to parse WPA/RSN IE's. */ -int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter, - u8 *ie, +int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter, + u8 *ie, size_t ie_len ) { @@ -5252,25 +5233,25 @@ int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter, elementId = *genie++; eLen = *genie++; remLen -= 2; - - hddLog(VOS_TRACE_LEVEL_INFO, "%s: IE[0x%X], LEN[%d]\n", + + hddLog(VOS_TRACE_LEVEL_INFO, "%s: IE[0x%X], LEN[%d]\n", __func__, elementId, eLen); - - switch ( elementId ) + + switch ( elementId ) { - case DOT11F_EID_WPA: + case DOT11F_EID_WPA: if (4 > eLen) /* should have at least OUI which is 4 bytes so extra 2 bytes not needed */ { - hddLog(VOS_TRACE_LEVEL_ERROR, + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid WPA IE", __func__); return -EINVAL; } - else if (0 == memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) + else if (0 == memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) { v_U16_t curAddIELen = pWextState->assocAddIE.length; - hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPS IE(len %d)", + hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPS IE(len %d)", __func__, eLen + 2); - + if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) ) { hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE. " @@ -5281,28 +5262,28 @@ int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter, // WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2); pWextState->assocAddIE.length += eLen + 2; - + pWextState->roamProfile.bWPSAssociation = VOS_TRUE; pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata; pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length; } - else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) - { + else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) + { hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPA IE (len %d)",__func__, eLen + 2); memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN ); memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2) /*ie_len*/); pWextState->roamProfile.pWPAReqIE = pWextState->WPARSNIE; pWextState->roamProfile.nWPAReqIELength = eLen + 2;//ie_len; } - else if ( (0 == memcmp(&genie[0], P2P_OUI_TYPE, - P2P_OUI_TYPE_SIZE)) + else if ( (0 == memcmp(&genie[0], P2P_OUI_TYPE, + P2P_OUI_TYPE_SIZE)) /*Consider P2P IE, only for P2P Client */ && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ) { v_U16_t curAddIELen = pWextState->assocAddIE.length; - hddLog (VOS_TRACE_LEVEL_INFO, "%s Set P2P IE(len %d)", + hddLog (VOS_TRACE_LEVEL_INFO, "%s Set P2P IE(len %d)", __func__, eLen + 2); - + if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) ) { hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE " @@ -5313,20 +5294,20 @@ int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter, // P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2); pWextState->assocAddIE.length += eLen + 2; - + pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata; pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length; } #ifdef WLAN_FEATURE_WFD - else if ( (0 == memcmp(&genie[0], WFD_OUI_TYPE, - WFD_OUI_TYPE_SIZE)) + else if ( (0 == memcmp(&genie[0], WFD_OUI_TYPE, + WFD_OUI_TYPE_SIZE)) /*Consider WFD IE, only for P2P Client */ && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ) { v_U16_t curAddIELen = pWextState->assocAddIE.length; - hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WFD IE(len %d)", + hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WFD IE(len %d)", __func__, eLen + 2); - + if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) ) { hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE " @@ -5338,17 +5319,17 @@ int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter, // WPS IE + P2P IE + WFD IE memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2); pWextState->assocAddIE.length += eLen + 2; - + pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata; pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length; } #endif /* Appending HS 2.0 Indication Element in Assiciation Request */ - else if ( (0 == memcmp(&genie[0], HS20_OUI_TYPE, + else if ( (0 == memcmp(&genie[0], HS20_OUI_TYPE, HS20_OUI_TYPE_SIZE)) ) { v_U16_t curAddIELen = pWextState->assocAddIE.length; - hddLog (VOS_TRACE_LEVEL_INFO, "%s Set HS20 IE(len %d)", + hddLog (VOS_TRACE_LEVEL_INFO, "%s Set HS20 IE(len %d)", __func__, eLen + 2); if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) ) @@ -5375,11 +5356,11 @@ int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter, break; /* Appending Extended Capabilities with Interworking bit set in Assoc Req */ case DOT11F_EID_EXTCAP: - { + { v_U16_t curAddIELen = pWextState->assocAddIE.length; - hddLog (VOS_TRACE_LEVEL_INFO, "%s Set Extended CAPS IE(len %d)", + hddLog (VOS_TRACE_LEVEL_INFO, "%s Set Extended CAPS IE(len %d)", __func__, eLen + 2); - + if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) ) { hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE " @@ -5389,7 +5370,7 @@ int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter, } memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2); pWextState->assocAddIE.length += eLen + 2; - + pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata; pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length; break; @@ -5400,7 +5381,7 @@ int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter, hddLog(VOS_TRACE_LEVEL_INFO,"WAPI MODE IS %lu \n", pAdapter->wapi_info.nWapiMode); tmp = (u16 *)ie; - tmp = tmp + 2; // Skip element Id and Len, Version + tmp = tmp + 2; // Skip element Id and Len, Version akmsuiteCount = WPA_GET_LE16(tmp); tmp = tmp + 1; akmlist = (int *)(tmp); @@ -5420,9 +5401,9 @@ int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter, hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO PSK", __func__); pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_PSK; - } + } if (WAPI_CERT_AKM_SUITE == akmsuite[0]) - { + { hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO CERTIFICATE", __func__); pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_CERT; @@ -5430,7 +5411,7 @@ int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter, break; #endif default: - hddLog (VOS_TRACE_LEVEL_ERROR, + hddLog (VOS_TRACE_LEVEL_ERROR, "%s Set UNKNOWN IE %X", __func__, elementId); /* when Unknown IE is received we should break and continue * to the next IE in the buffer instead we were returning @@ -5444,29 +5425,65 @@ int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter, return 0; } +/* + * FUNCTION: hdd_isWPAIEPresent + * Parse the received IE to find the WPA IE + * + */ +static bool hdd_isWPAIEPresent(u8 *ie, u8 ie_len) +{ + v_U8_t eLen = 0; + v_U16_t remLen = ie_len; + v_U8_t elementId = 0; + + while (remLen >= 2) + { + elementId = *ie++; + eLen = *ie++; + remLen -= 2; + if (eLen > remLen) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: IE length is wrong %d", __func__, eLen); + return FALSE; + } + if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) + { + /* OUI - 0x00 0X50 0XF2 + WPA Information Element - 0x01 + WPA version - 0x01*/ + if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5)) + return TRUE; + } + ie += eLen; + remLen -= eLen; + } + return FALSE; +} + /* * FUNCTION: wlan_hdd_cfg80211_set_privacy - * This function is used to initialize the security + * This function is used to initialize the security * parameters during connect operation. */ -int wlan_hdd_cfg80211_set_privacy( hdd_adapter_t *pAdapter, +int wlan_hdd_cfg80211_set_privacy( hdd_adapter_t *pAdapter, struct cfg80211_connect_params *req ) { int status = 0; - hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); ENTER(); /*set wpa version*/ pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED; - if (req->crypto.wpa_versions) + if (req->crypto.wpa_versions) { if ( (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) - && ( (req->ie_len) - && (0 == memcmp( &req->ie[2], "\x00\x50\xf2",3) ) ) ) + && ( (req->ie_len) + && (hdd_isWPAIEPresent(req->ie, req->ie_len) ) ) ) // Make sure that it is including a WPA IE. - /* Currently NL is putting WPA version 1 even for open, + /* Currently NL is putting WPA version 1 even for open, * since p2p ie is also put in same buffer. * */ { @@ -5477,8 +5494,8 @@ int wlan_hdd_cfg80211_set_privacy( hdd_adapter_t *pAdapter, pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2; } } - - hddLog(VOS_TRACE_LEVEL_INFO, "%s: set wpa version to %d", __func__, + + hddLog(VOS_TRACE_LEVEL_INFO, "%s: set wpa version to %d", __func__, pWextState->wpaVersion); /*set authentication type*/ @@ -5486,7 +5503,7 @@ int wlan_hdd_cfg80211_set_privacy( hdd_adapter_t *pAdapter, if (0 > status) { - hddLog(VOS_TRACE_LEVEL_ERROR, + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set authentication type ", __func__); return status; } @@ -5497,7 +5514,7 @@ int wlan_hdd_cfg80211_set_privacy( hdd_adapter_t *pAdapter, status = wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]); if (0 > status) { - hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set akm suite", + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set akm suite", __func__); return status; } @@ -5510,7 +5527,7 @@ int wlan_hdd_cfg80211_set_privacy( hdd_adapter_t *pAdapter, req->crypto.ciphers_pairwise[0], true); if (0 > status) { - hddLog(VOS_TRACE_LEVEL_ERROR, + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set unicast cipher type", __func__); return status; } @@ -5521,7 +5538,7 @@ int wlan_hdd_cfg80211_set_privacy( hdd_adapter_t *pAdapter, status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true); if (0 > status) { - hddLog(VOS_TRACE_LEVEL_ERROR, + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set unicast cipher type", __func__); return status; } @@ -5533,38 +5550,34 @@ int wlan_hdd_cfg80211_set_privacy( hdd_adapter_t *pAdapter, if (0 > status) { - hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set mcast cipher type", + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set mcast cipher type", __func__); return status; } -#ifdef WLAN_FEATURE_11W - pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED); -#endif - /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile*/ if (req->ie_len) { status = wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len); if ( 0 > status) { - hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse the WPA/RSN IE", + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse the WPA/RSN IE", __func__); return status; } } /*incase of WEP set default key information*/ - if (req->key && req->key_len) + if (req->key && req->key_len) { if ( (WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0]) || (WLAN_CIPHER_SUITE_WEP104 == req->crypto.ciphers_pairwise[0]) ) { - if ( IW_AUTH_KEY_MGMT_802_1X + if ( IW_AUTH_KEY_MGMT_802_1X == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X )) { - hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Dynamic WEP not supported", + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Dynamic WEP not supported", __func__); return -EOPNOTSUPP; } @@ -5573,17 +5586,17 @@ int wlan_hdd_cfg80211_set_privacy( hdd_adapter_t *pAdapter, u8 key_len = req->key_len; u8 key_idx = req->key_idx; - if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len) + if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len) && (CSR_MAX_NUM_KEY > key_idx) ) { - hddLog(VOS_TRACE_LEVEL_INFO, - "%s: setting default wep key, key_idx = %hu key_len %hu", + hddLog(VOS_TRACE_LEVEL_INFO, + "%s: setting default wep key, key_idx = %hu key_len %hu", __func__, key_idx, key_len); vos_mem_copy( - &pWextState->roamProfile.Keys.KeyMaterial[key_idx][0], + &pWextState->roamProfile.Keys.KeyMaterial[key_idx][0], req->key, key_len); - pWextState->roamProfile.Keys.KeyLength[key_idx] = + pWextState->roamProfile.Keys.KeyLength[key_idx] = (u8)key_len; pWextState->roamProfile.Keys.defaultIndex = (u8)key_idx; } @@ -5596,46 +5609,49 @@ int wlan_hdd_cfg80211_set_privacy( hdd_adapter_t *pAdapter, /* * FUNCTION: wlan_hdd_cfg80211_set_privacy - * This function is used to initialize the security + * This function is used to initialize the security * parameters during connect operation. */ -static int wlan_hdd_cfg80211_connect( struct wiphy *wiphy, +static int wlan_hdd_cfg80211_connect( struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_connect_params *req ) { - int status = 0; - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev ); + int status; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev ); VOS_STATUS exitbmpsStatus = VOS_STATUS_E_INVAL; hdd_context_t *pHddCtx = NULL; ENTER(); - hddLog(VOS_TRACE_LEVEL_INFO, + hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",__func__,pAdapter->device_mode); - if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress ) + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EAGAIN; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return status; } #ifdef WLAN_BTAMP_FEATURE //Infra connect not supported when AMP traffic is on. - if( VOS_TRUE == WLANBAP_AmpSessionOn() ) + if( VOS_TRUE == WLANBAP_AmpSessionOn() ) { - hddLog(VOS_TRACE_LEVEL_ERROR, + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No connection when AMP is on", __func__); return -ECONNREFUSED; } #endif /*initialise security parameters*/ - status = wlan_hdd_cfg80211_set_privacy(pAdapter, req); + status = wlan_hdd_cfg80211_set_privacy(pAdapter, req); if ( 0 > status) { - hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security params", + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security params", __func__); return status; } @@ -5645,16 +5661,7 @@ static int wlan_hdd_cfg80211_connect( struct wiphy *wiphy, if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) && (vos_concurrent_sessions_running())) { - v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL ); - - if (NULL != pVosContext) - { - pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext); - if(NULL != pHddCtx) - { - exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION); - } - } + exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION); } if ( req->channel ) @@ -5666,8 +5673,7 @@ static int wlan_hdd_cfg80211_connect( struct wiphy *wiphy, else { status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid, - req->ssid_len, req->bssid, - 0); + req->ssid_len, req->bssid, 0); } if (0 > status) @@ -5676,6 +5682,10 @@ static int wlan_hdd_cfg80211_connect( struct wiphy *wiphy, if((VOS_STATUS_SUCCESS == exitbmpsStatus) && (NULL != pHddCtx)) { + if (pHddCtx->hdd_wlan_suspended) + { + hdd_set_pwrparams(pHddCtx); + } //ReEnable Bmps and Imps back hdd_enable_bmps_imps(pHddCtx); } @@ -5683,7 +5693,7 @@ static int wlan_hdd_cfg80211_connect( struct wiphy *wiphy, hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__); return status; } - (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_FALSE; + pHddCtx->isAmpAllowed = VOS_FALSE; EXIT(); return status; } @@ -5693,43 +5703,44 @@ static int wlan_hdd_cfg80211_connect( struct wiphy *wiphy, * FUNCTION: wlan_hdd_cfg80211_disconnect * This function is used to issue a disconnect request to SME */ -static int wlan_hdd_cfg80211_disconnect( struct wiphy *wiphy, +static int wlan_hdd_cfg80211_disconnect( struct wiphy *wiphy, struct net_device *dev, u16 reason ) { - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev ); - tCsrRoamProfile *pRoamProfile = + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev ); + tCsrRoamProfile *pRoamProfile = &(WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter))->roamProfile; - int status = 0; + int status; hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); - hdd_scaninfo_t *pScanInfo = NULL; #ifdef FEATURE_WLAN_TDLS tANI_U8 staIdx; #endif - + ENTER(); - - pScanInfo = &pHddCtx->scan_info; - hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n", + + hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n", __func__,pAdapter->device_mode); - hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disconnect called with reason code %d", - __func__, reason); + hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disconnect called with reason code %d", + __func__, reason); - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s:LOGP in Progress. Ignore!!!",__func__); - return -EAGAIN; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return status; } + if (NULL != pRoamProfile) { /*issue disconnect request to SME, if station is in connected state*/ if (pHddStaCtx->conn_info.connState == eConnectionState_Associated) { - eCsrRoamDisconnectReason reasonCode = + eCsrRoamDisconnectReason reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED; switch(reason) { @@ -5754,12 +5765,6 @@ static int wlan_hdd_cfg80211_disconnect( struct wiphy *wiphy, break; } pHddStaCtx->conn_info.connState = eConnectionState_NotConnected; - if ((pScanInfo != NULL) && pScanInfo->mScanPending) - { - hddLog(VOS_TRACE_LEVEL_INFO," Disconnect is in progress," - " Aborting Scan"); - hdd_abort_mac_scan(pHddCtx); - } (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_TRUE; INIT_COMPLETION(pAdapter->disconnect_comp_var); @@ -5783,13 +5788,13 @@ static int wlan_hdd_cfg80211_disconnect( struct wiphy *wiphy, } #endif /*issue disconnect*/ - status = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), + status = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, reasonCode); if ( 0 != status) { hddLog(VOS_TRACE_LEVEL_ERROR, - "%s csrRoamDisconnect failure, returned %d \n", + "%s csrRoamDisconnect failure, returned %d \n", __func__, (int)status ); return -EINVAL; } @@ -5814,26 +5819,26 @@ static int wlan_hdd_cfg80211_disconnect( struct wiphy *wiphy, /* * FUNCTION: wlan_hdd_cfg80211_set_privacy_ibss - * This function is used to initialize the security + * This function is used to initialize the security * settings in IBSS mode. */ static int wlan_hdd_cfg80211_set_privacy_ibss( - hdd_adapter_t *pAdapter, + hdd_adapter_t *pAdapter, struct cfg80211_ibss_params *params ) { int status = 0; - hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE; hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); - + ENTER(); pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED; if (params->ie_len && ( NULL != params->ie) ) { - if (WLAN_EID_RSN == params->ie[0]) + if (WLAN_EID_RSN == params->ie[0]) { pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2; encryptionType = eCSR_ENCRYPT_TYPE_AES; @@ -5847,24 +5852,24 @@ static int wlan_hdd_cfg80211_set_privacy_ibss( if (0 > status) { - hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse WPA/RSN IE", + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse WPA/RSN IE", __func__); return status; } } - pWextState->roamProfile.AuthType.authType[0] = - pHddStaCtx->conn_info.authType = + pWextState->roamProfile.AuthType.authType[0] = + pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM; if (params->privacy) { - /* Security enabled IBSS, At this time there is no information available - * about the security paramters, so initialise the encryption type to + /* Security enabled IBSS, At this time there is no information available + * about the security paramters, so initialise the encryption type to * eCSR_ENCRYPT_TYPE_WEP40_STATICKEY. - * The correct security parameters will be updated later in + * The correct security parameters will be updated later in * wlan_hdd_cfg80211_add_key */ - /* Hal expects encryption type to be set inorder + /* Hal expects encryption type to be set inorder *enable privacy bit in beacons */ encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY; @@ -5879,34 +5884,37 @@ static int wlan_hdd_cfg80211_set_privacy_ibss( /* * FUNCTION: wlan_hdd_cfg80211_join_ibss - * This function is used to create/join an IBSS + * This function is used to create/join an IBSS */ -static int wlan_hdd_cfg80211_join_ibss( struct wiphy *wiphy, +static int wlan_hdd_cfg80211_join_ibss( struct wiphy *wiphy, struct net_device *dev, struct cfg80211_ibss_params *params ) { - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev ); + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev ); hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); tCsrRoamProfile *pRoamProfile; int status; hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); ENTER(); - - hddLog(VOS_TRACE_LEVEL_INFO, + + hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",__func__,pAdapter->device_mode); - if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress ) + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EAGAIN; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return status; } if (NULL == pWextState) { - hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n", + hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n", __func__); return -EIO; } @@ -5915,7 +5923,7 @@ static int wlan_hdd_cfg80211_join_ibss( struct wiphy *wiphy, if ( eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType ) { - hddLog (VOS_TRACE_LEVEL_ERROR, + hddLog (VOS_TRACE_LEVEL_ERROR, "%s Interface type is not set to IBSS \n", __func__); return -EINVAL; } @@ -5926,14 +5934,14 @@ static int wlan_hdd_cfg80211_join_ibss( struct wiphy *wiphy, u8 channelNum; if (IEEE80211_BAND_5GHZ == params->channel->band) { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: IBSS join is called with unsupported band %d", + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: IBSS join is called with unsupported band %d", __func__, params->channel->band); return -EOPNOTSUPP; } /* Get channel number */ - channelNum = + channelNum = ieee80211_frequency_to_channel(params->channel->center_freq); /*TODO: use macro*/ @@ -5947,7 +5955,7 @@ static int wlan_hdd_cfg80211_join_ibss( struct wiphy *wiphy, if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST, validChan, &numChans)) { - hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid channel list", + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid channel list", __func__); return -EOPNOTSUPP; } @@ -5961,37 +5969,37 @@ static int wlan_hdd_cfg80211_join_ibss( struct wiphy *wiphy, } if (indx >= numChans) { - hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %d", + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %d", __func__, channelNum); return -EINVAL; } /* Set the Operational Channel */ - hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: set channel %d", __func__, + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: set channel %d", __func__, channelNum); pRoamProfile->ChannelInfo.numOfChannels = 1; pHddStaCtx->conn_info.operationChannel = channelNum; - pRoamProfile->ChannelInfo.ChannelList = + pRoamProfile->ChannelInfo.ChannelList = &pHddStaCtx->conn_info.operationChannel; } else { - hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %hu", + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %hu", __func__, channelNum); return -EINVAL; } } /* Initialize security parameters */ - status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params); + status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params); if (status < 0) { - hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security parameters", + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security parameters", __func__); return status; } /* Issue connect start */ - status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid, + status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid, params->ssid_len, params->bssid, 0); if (0 > status) @@ -6005,29 +6013,33 @@ static int wlan_hdd_cfg80211_join_ibss( struct wiphy *wiphy, /* * FUNCTION: wlan_hdd_cfg80211_leave_ibss - * This function is used to leave an IBSS + * This function is used to leave an IBSS */ -static int wlan_hdd_cfg80211_leave_ibss( struct wiphy *wiphy, +static int wlan_hdd_cfg80211_leave_ibss( struct wiphy *wiphy, struct net_device *dev ) { - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev ); + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev ); hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); tCsrRoamProfile *pRoamProfile; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + int status; ENTER(); - if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress ) + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EAGAIN; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return status; } hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",__func__,pAdapter->device_mode); if (NULL == pWextState) { - hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n", + hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n", __func__); return -EIO; } @@ -6037,7 +6049,7 @@ static int wlan_hdd_cfg80211_leave_ibss( struct wiphy *wiphy, /* Issue disconnect only if interface type is set to IBSS */ if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) { - hddLog (VOS_TRACE_LEVEL_ERROR, "%s: BSS Type is not set to IBSS", + hddLog (VOS_TRACE_LEVEL_ERROR, "%s: BSS Type is not set to IBSS", __func__); return -EINVAL; } @@ -6055,19 +6067,22 @@ static int wlan_hdd_cfg80211_leave_ibss( struct wiphy *wiphy, * This function is used to set the phy parameters * (RTS Threshold/FRAG Threshold/Retry Count etc ...) */ -static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, +static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) { hdd_context_t *pHddCtx = wiphy_priv(wiphy); tHalHandle hHal = pHddCtx->hHal; + int status; ENTER(); - if ( pHddCtx->isLogpInProgress ) + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EAGAIN; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return status; } if (changed & WIPHY_PARAM_RTS_THRESHOLD) @@ -6077,25 +6092,25 @@ static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, wiphy->rts_threshold; if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) || - (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) + (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: Invalid RTS Threshold value %hu", + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Invalid RTS Threshold value %hu", __func__, rts_threshold); return -EINVAL; } if (0 != ccmCfgSetInt(hHal, WNI_CFG_RTS_THRESHOLD, rts_threshold, ccmCfgSetCallback, - eANI_BOOLEAN_TRUE)) + eANI_BOOLEAN_TRUE)) { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: ccmCfgSetInt failed for rts_threshold value %hu", + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: ccmCfgSetInt failed for rts_threshold value %hu", __func__, rts_threshold); return -EIO; } - hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set rts threshold %hu", __func__, + hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set rts threshold %hu", __func__, rts_threshold); } @@ -6106,20 +6121,20 @@ static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, wiphy->frag_threshold; if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold)|| - (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold) ) + (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold) ) { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: Invalid frag_threshold value %hu", __func__, + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Invalid frag_threshold value %hu", __func__, frag_threshold); return -EINVAL; } if (0 != ccmCfgSetInt(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD, frag_threshold, ccmCfgSetCallback, - eANI_BOOLEAN_TRUE)) + eANI_BOOLEAN_TRUE)) { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: ccmCfgSetInt failed for frag_threshold value %hu", + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: ccmCfgSetInt failed for frag_threshold value %hu", __func__, frag_threshold); return -EIO; } @@ -6138,7 +6153,7 @@ static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) || (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) { - hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Retry count %hu", + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Retry count %hu", __func__, retry_value); return -EINVAL; } @@ -6147,28 +6162,28 @@ static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, { if (0 != ccmCfgSetInt(hHal, WNI_CFG_LONG_RETRY_LIMIT, retry_value, ccmCfgSetCallback, - eANI_BOOLEAN_TRUE)) + eANI_BOOLEAN_TRUE)) { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: ccmCfgSetInt failed for long retry count %hu", + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: ccmCfgSetInt failed for long retry count %hu", __func__, retry_value); return -EIO; } - hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set long retry count %hu", + hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set long retry count %hu", __func__, retry_value); } else if (changed & WIPHY_PARAM_RETRY_SHORT) { if (0 != ccmCfgSetInt(hHal, WNI_CFG_SHORT_RETRY_LIMIT, retry_value, ccmCfgSetCallback, - eANI_BOOLEAN_TRUE)) + eANI_BOOLEAN_TRUE)) { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: ccmCfgSetInt failed for short retry count %hu", + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: ccmCfgSetInt failed for short retry count %hu", __func__, retry_value); return -EIO; } - hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set short retry count %hu", + hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set short retry count %hu", __func__, retry_value); } } @@ -6182,33 +6197,38 @@ static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, */ static int wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy, #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,35) - enum tx_power_setting type, + enum tx_power_setting type, #else - enum nl80211_tx_power_setting type, + enum nl80211_tx_power_setting type, #endif int dbm) { hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy); - tHalHandle hHal = pHddCtx->hHal; + tHalHandle hHal = NULL; tSirMacAddr bssid = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; tSirMacAddr selfMac = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; + int status; ENTER(); - if (0 != ccmCfgSetInt(hHal, WNI_CFG_CURRENT_TX_POWER_LEVEL, - dbm, ccmCfgSetCallback, - eANI_BOOLEAN_TRUE)) + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: ccmCfgSetInt failed for tx power %hu", __func__, dbm); - return -EIO; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return status; } - if ( pHddCtx->isLogpInProgress ) + hHal = pHddCtx->hHal; + + if (0 != ccmCfgSetInt(hHal, WNI_CFG_CURRENT_TX_POWER_LEVEL, + dbm, ccmCfgSetCallback, + eANI_BOOLEAN_TRUE)) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EAGAIN; + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: ccmCfgSetInt failed for tx power %hu", __func__, dbm); + return -EIO; } hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set tx power level %d dbm", __func__, @@ -6221,19 +6241,19 @@ static int wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy, case NL80211_TX_POWER_LIMITED: /*limit TX power by the mBm parameter*/ if( sme_SetMaxTxPower(hHal, bssid, selfMac, dbm) != eHAL_STATUS_SUCCESS ) { - hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Setting maximum tx power failed", - __func__); - return -EIO; + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Setting maximum tx power failed", + __func__); + return -EIO; } break; case NL80211_TX_POWER_FIXED: /*fix TX power to the mBm parameter*/ - hddLog(VOS_TRACE_LEVEL_ERROR, "%s: NL80211_TX_POWER_FIXED not supported", + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: NL80211_TX_POWER_FIXED not supported", __func__); return -EOPNOTSUPP; break; default: - hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid power setting type %d", - __func__, type); + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid power setting type %d", + __func__, type); return -EIO; } @@ -6249,21 +6269,18 @@ static int wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm) hdd_adapter_t *pAdapter; hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy); + int status; ENTER(); - if (NULL == pHddCtx) - { - hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__); - *dbm = 0; - return -ENOENT; - } + status = wlan_hdd_validate_context(pHddCtx); - if ( pHddCtx->isLogpInProgress ) + if (0 != status) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EAGAIN; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + *dbm = 0; + return status; } pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION); @@ -6305,6 +6322,7 @@ static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device tANI_U8 rateFlag = 1; tANI_U8 i, j, rssidx; tANI_U16 temp; + int status; #ifdef WLAN_FEATURE_11AC tANI_U32 vht_mcs_map; @@ -6322,11 +6340,13 @@ static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device return 0; } - if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress ) + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EAGAIN; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return status; } wlan_hdd_get_rssi(pAdapter, &sinfo->signal); @@ -6439,7 +6459,6 @@ static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device /* Update MAX rate */ maxRate = (currentRate > maxRate)?currentRate:maxRate; } - /* Get MCS Rate Set -- but only if we are connected at MCS rates or if we are always reporting max speed or if we have good rssi */ @@ -6455,15 +6474,14 @@ static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device rateFlag = 0; #ifdef WLAN_FEATURE_11AC /* VHT80 rate has seperate rate table */ - if (rate_flags & eHAL_TX_RATE_VHT80) + if (rate_flags & (eHAL_TX_RATE_VHT20|eHAL_TX_RATE_VHT40|eHAL_TX_RATE_VHT80)) { - currentRate = supported_vht_mcs_rate[pAdapter->hdd_stats.ClassA_stat.mcs_index].supported_rate[rateFlag]; ccmCfgGetInt(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_VHT_TX_MCS_MAP, &vht_mcs_map); + vhtMaxMcs = (eDataRate11ACMaxMcs)(vht_mcs_map & DATA_RATE_11AC_MCS_MASK ); if (rate_flags & eHAL_TX_RATE_SGI) { rateFlag |= 1; } - vhtMaxMcs = (eDataRate11ACMaxMcs)(vht_mcs_map & DATA_RATE_11AC_MCS_MASK); if (DATA_RATE_11AC_MAX_MCS_7 == vhtMaxMcs) { maxMCSIdx = 7; @@ -6474,14 +6492,35 @@ static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device } else if (DATA_RATE_11AC_MAX_MCS_9 == vhtMaxMcs) { - maxMCSIdx = 9; + //VHT20 is supporting 0~8 + if (rate_flags & eHAL_TX_RATE_VHT20) + maxMCSIdx = 8; + else + maxMCSIdx = 9; + } + + if (rate_flags & eHAL_TX_RATE_VHT80) + { + currentRate = supported_vht_mcs_rate[pAdapter->hdd_stats.ClassA_stat.mcs_index].supported_VHT80_rate[rateFlag]; + maxRate = supported_vht_mcs_rate[maxMCSIdx].supported_VHT80_rate[rateFlag]; } - maxRate = supported_vht_mcs_rate[maxMCSIdx].supported_rate[rateFlag]; + else if (rate_flags & eHAL_TX_RATE_VHT40) + { + currentRate = supported_vht_mcs_rate[pAdapter->hdd_stats.ClassA_stat.mcs_index].supported_VHT40_rate[rateFlag]; + maxRate = supported_vht_mcs_rate[maxMCSIdx].supported_VHT40_rate[rateFlag]; + } + else if (rate_flags & eHAL_TX_RATE_VHT20) + { + currentRate = supported_vht_mcs_rate[pAdapter->hdd_stats.ClassA_stat.mcs_index].supported_VHT20_rate[rateFlag]; + maxRate = supported_vht_mcs_rate[maxMCSIdx].supported_VHT20_rate[rateFlag]; + } + maxSpeedMCS = 1; if (currentRate > maxRate) { maxRate = currentRate; } + } else #endif /* WLAN_FEATURE_11AC */ @@ -6516,6 +6555,13 @@ static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device } } + else if (!(rate_flags & eHAL_TX_RATE_LEGACY)) + { + maxRate = myRate; + maxSpeedMCS = 1; + maxMCSIdx = pAdapter->hdd_stats.ClassA_stat.mcs_index; + } + // make sure we report a value at least as big as our current rate if (((maxRate < myRate) && (0 == rssidx)) || (0 == maxRate)) @@ -6532,7 +6578,7 @@ static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device } } - if ((!maxSpeedMCS) || (0 != rssidx)) + if (rate_flags & eHAL_TX_RATE_LEGACY) { sinfo->txrate.legacy = maxRate; #ifdef LINKSPEED_DEBUG_ENABLED @@ -6547,26 +6593,31 @@ static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device if (rate_flags & eHAL_TX_RATE_VHT80) { sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS; + sinfo->txrate.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH; } - else -#endif /* WLAN_FEATURE_11AC */ + else if (rate_flags & eHAL_TX_RATE_VHT40) { - sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS; + sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS; + sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; } - if (rate_flags & eHAL_TX_RATE_SGI) + else if (rate_flags & eHAL_TX_RATE_VHT20) { - sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; + sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS; } - if (rate_flags & eHAL_TX_RATE_HT40) +#endif /* WLAN_FEATURE_11AC */ + if (rate_flags & (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) { - sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; + sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS; + if (rate_flags & eHAL_TX_RATE_HT40) + { + sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; + } } -#ifdef WLAN_FEATURE_11AC - else if (rate_flags & eHAL_TX_RATE_VHT80) + if (rate_flags & eHAL_TX_RATE_SGI) { - sinfo->txrate.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH; + sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; } -#endif /* WLAN_FEATURE_11AC */ + #ifdef LINKSPEED_DEBUG_ENABLED pr_info("Reporting MCS rate %d flags %x\n", sinfo->txrate.mcs, @@ -6652,11 +6703,12 @@ static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device } static int wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy, - struct net_device *dev, bool mode, v_SINT_t timeout) + struct net_device *dev, bool mode, int timeout) { hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); hdd_context_t *pHddCtx; VOS_STATUS vos_status; + int status; ENTER(); @@ -6665,18 +6717,15 @@ static int wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy, hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__); return -ENODEV; } - if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress ) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EAGAIN; - } pHddCtx = WLAN_HDD_GET_CTX(pAdapter); - if (NULL == pHddCtx) + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) { - hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HDD context is NULL\n", __func__); - return -ENODEV; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return status; } if ((DRIVER_POWER_MODE_AUTO == !mode) && @@ -6685,7 +6734,7 @@ static int wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy, (eConnectionState_Associated == (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState)) { - vos_status = hdd_conf_hostarpoffload(pAdapter, TRUE); + vos_status = hdd_conf_arp_offload(pAdapter, TRUE); if (!VOS_IS_STATUS_SUCCESS(vos_status)) { hddLog(VOS_TRACE_LEVEL_INFO, @@ -6717,7 +6766,7 @@ static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy, ENTER(); return 0; } -#endif //LINUX_VERSION_CODE +#endif //LINUX_VERSION_CODE #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)) static int wlan_hdd_set_txq_params(struct wiphy *wiphy, @@ -6740,28 +6789,26 @@ static int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev, u8 *mac) { hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx; VOS_STATUS vos_status; + int status; v_U8_t staId; ENTER(); - if ( NULL == pAdapter || NULL == pAdapter->pHddCtx) + if ( NULL == pAdapter ) { - hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__); + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Adapter" ,__func__); return -EINVAL; } - if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress) - { - hddLog( LOGE, - "%s: Wlan Load/Unload is in progress", __func__); - return -EBUSY; - } + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + status = wlan_hdd_validate_context(pHddCtx); - if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress ) + if (0 != status) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EAGAIN; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return status; } if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode) @@ -6875,52 +6922,50 @@ static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *d { #define MAX_PMKSAIDS_IN_CACHE 8 static tPmkidCacheInfo PMKIDCache[MAX_PMKSAIDS_IN_CACHE]; // HDD Local cache - static tANI_U32 i; // HDD Local Cache index - tANI_U32 j=0; + static tANI_U32 i; // HDD Local Cache index + tANI_U32 j=0; hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); tHalHandle halHandle; - eHalStatus result; + eHalStatus result; + int status; tANI_U8 BSSIDMatched = 0; - + hdd_context_t *pHddCtx; + ENTER(); - // Validate pAdapter - if ( NULL == pAdapter || NULL == pAdapter->pHddCtx) + // Validate pAdapter + if ( NULL == pAdapter ) { - hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__); + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Adapter" ,__func__); return -EINVAL; } - if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress) + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) { - hddLog( LOGE, - "%s: Wlan Load/Unload is in progress", __func__); - return -EBUSY; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return status; } - if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress ) + // Retrieve halHandle + halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter); + + for (j = 0; j < i; j++) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EAGAIN; - } - - // Retrieve halHandle - halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter); - - for (j = 0; j < i; j++) - { - if(vos_mem_compare(PMKIDCache[j].BSSID, + if(vos_mem_compare(PMKIDCache[j].BSSID, pmksa->bssid, WNI_CFG_BSSID_LEN)) { /* BSSID matched previous entry. Overwrite it. */ BSSIDMatched = 1; - vos_mem_copy(PMKIDCache[j].BSSID, + vos_mem_copy(PMKIDCache[j].BSSID, pmksa->bssid, WNI_CFG_BSSID_LEN); - vos_mem_copy(PMKIDCache[j].PMKID, - pmksa->pmkid, + vos_mem_copy(PMKIDCache[j].PMKID, + pmksa->pmkid, CSR_RSN_PMKID_SIZE); - hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Reusing cache entry %d.", + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Reusing cache entry %d.", __func__, j ); dump_bssid(pmksa->bssid); dump_pmkid(halHandle, pmksa->pmkid); @@ -6932,31 +6977,31 @@ static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *d if(j == MAX_PMKSAIDS_IN_CACHE) i=0; if (!BSSIDMatched) - { - // Now, we DON'T have a BSSID match, so take a new entry in the cache. - vos_mem_copy(PMKIDCache[i].BSSID, - pmksa->bssid, ETHER_ADDR_LEN); - vos_mem_copy(PMKIDCache[i].PMKID, - pmksa->pmkid, + { + // Now, we DON'T have a BSSID match, so take a new entry in the cache. + vos_mem_copy(PMKIDCache[i].BSSID, + pmksa->bssid, ETHER_ADDR_LEN); + vos_mem_copy(PMKIDCache[i].PMKID, + pmksa->pmkid, CSR_RSN_PMKID_SIZE); - hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Adding a new cache entry %d.", + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Adding a new cache entry %d.", __func__, i ); dump_bssid(pmksa->bssid); dump_pmkid(halHandle, pmksa->pmkid); - // Increment the HDD Local Cache index + // Increment the HDD Local Cache index // The "i=0" doesn't work for the call to sme_RoamSetPMKIDCache() - LFR FIXME - if (i<=(MAX_PMKSAIDS_IN_CACHE-1)) i++; else i=0; + if (i<=(MAX_PMKSAIDS_IN_CACHE-1)) i++; else i=0; } // Calling csrRoamSetPMKIDCache to configure the PMKIDs into the cache - //hddLog(LOG1, FL("%s: Calling csrRoamSetPMKIDCache with %d cache entries."), + //hddLog(LOG1, FL("%s: Calling csrRoamSetPMKIDCache with %d cache entries."), // __func__, i ); - hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Calling csrRoamSetPMKIDCache with %d cache entries.", + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Calling csrRoamSetPMKIDCache with %d cache entries.", __func__, i ); // Finally set the PMKSA ID Cache in CSR - result = sme_RoamSetPMKIDCache(halHandle,pAdapter->sessionId, - PMKIDCache, + result = sme_RoamSetPMKIDCache(halHandle,pAdapter->sessionId, + PMKIDCache, i ); return 0; } @@ -6979,7 +7024,7 @@ static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device #endif #if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211) -static int wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy, +static int wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_update_ft_ies_params *ftie) { hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); @@ -6996,13 +7041,13 @@ static int wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy, // Added for debug on reception of Re-assoc Req. if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) { - hddLog(LOGE, FL("Called with Ie of length = %d when not associated\n"), + hddLog(LOGE, FL("Called with Ie of length = %d when not associated\n"), ftie->ie_len); hddLog(LOGE, FL("Should be Re-assoc Req IEs\n")); } #ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG - hddLog(LOGE, FL("%s called with Ie of length = %d\n"), __func__, + hddLog(LOGE, FL("%s called with Ie of length = %d\n"), __func__, ftie->ie_len); #endif @@ -7014,6 +7059,299 @@ static int wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy, } #endif +#ifdef FEATURE_WLAN_SCAN_PNO + +void hdd_cfg80211_sched_scan_done_callback(void *callbackContext, + tSirPrefNetworkFoundInd *pPrefNetworkFoundInd) +{ + int ret; + hdd_adapter_t* pAdapter = (hdd_adapter_t*)callbackContext; + hdd_context_t *pHddCtx; + + if (NULL == pAdapter) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s: HDD adapter is Null", __func__); + return ; + } + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + if (NULL == pHddCtx) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is Null!!!", __func__); + return ; + } + + spin_lock(&pHddCtx->schedScan_lock); + if (TRUE == pHddCtx->isWiphySuspended) + { + pHddCtx->isSchedScanUpdatePending = TRUE; + spin_unlock(&pHddCtx->schedScan_lock); + hddLog(VOS_TRACE_LEVEL_INFO, + "%s: Update cfg80211 scan database after it resume", __func__); + return ; + } + spin_unlock(&pHddCtx->schedScan_lock); + + ret = wlan_hdd_cfg80211_update_bss(pHddCtx->wiphy, pAdapter); + + if (0 > ret) + hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__); + + cfg80211_sched_scan_results(pHddCtx->wiphy); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: cfg80211 scan result database updated", __func__); +} + +/* + * FUNCTION: wlan_hdd_cfg80211_sched_scan_start + * NL interface to enable PNO + */ +static int wlan_hdd_cfg80211_sched_scan_start(struct wiphy *wiphy, + struct net_device *dev, struct cfg80211_sched_scan_request *request) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + tpSirPNOScanReq pPnoRequest = NULL; + hdd_context_t *pHddCtx; + tHalHandle hHal; + v_U32_t i, indx, num_ch; + u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN]; + u8 channels_allowed[WNI_CFG_VALID_CHANNEL_LIST_LEN]; + v_U32_t num_channels_allowed = WNI_CFG_VALID_CHANNEL_LIST_LEN; + eHalStatus status = eHAL_STATUS_FAILURE; + int ret = 0; + + if (NULL == pAdapter) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s: HDD adapter is Null", __func__); + return -ENODEV; + } + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(pHddCtx); + + if (0 != ret) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return -EINVAL; + } + + hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + if (NULL == hHal) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HAL context is Null!!!", __func__); + return -EINVAL; + } + + pPnoRequest = (tpSirPNOScanReq) vos_mem_malloc(sizeof (tSirPNOScanReq)); + if (NULL == pPnoRequest) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s: vos_mem_malloc failed", __func__); + return -ENOMEM; + } + + pPnoRequest->enable = 1; /*Enable PNO */ + pPnoRequest->ucNetworksCount = request->n_match_sets; + + if (( !pPnoRequest->ucNetworksCount ) || + ( pPnoRequest->ucNetworksCount > SIR_PNO_MAX_SUPP_NETWORKS )) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Network input is not correct"); + ret = -EINVAL; + goto error; + } + + if ( SIR_PNO_MAX_NETW_CHANNELS_EX < request->n_channels ) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Incorrect number of channels"); + ret = -EINVAL; + goto error; + } + + /* Framework provides one set of channels(all) + * common for all saved profile */ + if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST, + channels_allowed, &num_channels_allowed)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: failed to get valid channel list", __func__); + ret = -EINVAL; + goto error; + } + /* Checking each channel against allowed channel list */ + num_ch = 0; + for (i = 0; i < request->n_channels; i++) + { + for (indx = 0; indx < num_channels_allowed; indx++) + { + if (request->channels[i]->hw_value == channels_allowed[indx]) + { + valid_ch[num_ch++] = request->channels[i]->hw_value; + break ; + } + } + } + + /* Filling per profile params */ + for (i = 0; i < pPnoRequest->ucNetworksCount; i++) + { + pPnoRequest->aNetworks[i].ssId.length = + request->match_sets[i].ssid.ssid_len; + + if (( 0 == pPnoRequest->aNetworks[i].ssId.length ) || + ( pPnoRequest->aNetworks[i].ssId.length > 32 ) ) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "SSID Len %d is not correct for network %d", + pPnoRequest->aNetworks[i].ssId.length, i); + ret = -EINVAL; + goto error; + } + + memcpy(pPnoRequest->aNetworks[i].ssId.ssId, + request->match_sets[i].ssid.ssid, + request->match_sets[i].ssid.ssid_len); + pPnoRequest->aNetworks[i].authentication = 0; /*eAUTH_TYPE_ANY*/ + pPnoRequest->aNetworks[i].encryption = 0; /*eED_ANY*/ + pPnoRequest->aNetworks[i].bcastNetwType = 0; /*eBCAST_UNKNOWN*/ + + /*Copying list of valid channel into request */ + memcpy(pPnoRequest->aNetworks[i].aChannels, valid_ch, num_ch); + pPnoRequest->aNetworks[i].ucChannelCount = num_ch; + + pPnoRequest->aNetworks[i].rssiThreshold = 0; //Default value + } + + /* framework provides interval in ms */ + pPnoRequest->scanTimers.ucScanTimersCount = 1; + pPnoRequest->scanTimers.aTimerValues[0].uTimerValue = + (request->interval)/1000; + pPnoRequest->scanTimers.aTimerValues[0].uTimerRepeat = 0; + pPnoRequest->modePNO = SIR_PNO_MODE_ON_SUSPEND; + + status = sme_SetPreferredNetworkList(WLAN_HDD_GET_HAL_CTX(pAdapter), + pPnoRequest, pAdapter->sessionId, + hdd_cfg80211_sched_scan_done_callback, pAdapter); + if (eHAL_STATUS_SUCCESS != status) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Failed to enable PNO"); + ret = -EINVAL; + goto error; + } + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "PNO scanRequest offloaded"); + +error: + vos_mem_free(pPnoRequest); + return ret; +} + +/* + * FUNCTION: wlan_hdd_cfg80211_sched_scan_stop + * NL interface to disable PNO + */ +static int wlan_hdd_cfg80211_sched_scan_stop(struct wiphy *wiphy, + struct net_device *dev) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx; + tHalHandle hHal; + tpSirPNOScanReq pPnoRequest = NULL; + int ret = 0; + + ENTER(); + + if (NULL == pAdapter) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s: HDD adapter is Null", __func__); + return -ENODEV; + } + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + if (NULL == pHddCtx) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is Null", __func__); + return -ENODEV; + } + + /* The return 0 is intentional when isLogpInProgress and + * isLoadUnloadInProgress. We did observe a crash due to a return of + * failure in sched_scan_stop , especially for a case where the unload + * of the happens at the same time. The function __cfg80211_stop_sched_scan + * was clearing rdev->sched_scan_req only when the sched_scan_stop returns + * success. If it returns a failure , then its next invocation due to the + * clean up of the second interface will have the dev pointer corresponding + * to the first one leading to a crash. + */ + if (pHddCtx->isLogpInProgress) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: LOGP in Progress. Ignore!!!", __func__); + return ret; + } + + if (pHddCtx->isLoadUnloadInProgress) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Unloading/Loading in Progress. Ignore!!!", __func__); + return ret; + } + + hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + if (NULL == hHal) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HAL context is Null!!!", __func__); + return -EINVAL; + } + + pPnoRequest = (tpSirPNOScanReq) vos_mem_malloc(sizeof (tSirPNOScanReq)); + if (NULL == pPnoRequest) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s: vos_mem_malloc failed", __func__); + return -ENOMEM; + } + + memset(pPnoRequest, 0, sizeof (tSirPNOScanReq)); + pPnoRequest->enable = 0; /* Disable PNO */ + pPnoRequest->ucNetworksCount = 0; + + status = sme_SetPreferredNetworkList(hHal, pPnoRequest, + pAdapter->sessionId, + NULL, pAdapter); + if (eHAL_STATUS_SUCCESS != status) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Failed to disabled PNO"); + ret = -EINVAL; + } + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: PNO scan disabled", __func__); + + vos_mem_free(pPnoRequest); + + EXIT(); + return ret; +} + +#endif /*FEATURE_WLAN_SCAN_PNO*/ + + #ifdef FEATURE_WLAN_TDLS static int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev, u8 *peer, u8 action_code, u8 dialog_token, @@ -7026,10 +7364,11 @@ static int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *d VOS_STATUS status; int max_sta_failed = 0; int responder; + long rc; if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini) { - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "Invalid arguments"); return -EINVAL; } @@ -7051,12 +7390,6 @@ static int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *d return -ENOTSUPP; } - if ((SIR_MAC_TDLS_SETUP_RSP == action_code) || - (SIR_MAC_TDLS_DIS_RSP == action_code)) - { - wlan_hdd_tdls_set_cap (pAdapter, peer, eTDLS_CAP_SUPPORTED); - } - /* other than teardown frame, other mgmt frames are not sent if disabled */ if (SIR_MAC_TDLS_TEARDOWN != action_code) { @@ -7074,7 +7407,7 @@ static int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *d if (WLAN_IS_TDLS_SETUP_ACTION(action_code)) { - if (wlan_hdd_tdls_is_progress(pAdapter, peer, TRUE)) + if (NULL != wlan_hdd_tdls_is_progress(pHddCtx, peer, TRUE, TRUE)) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: " MAC_ADDRESS_STR @@ -7141,17 +7474,38 @@ static int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *d responder = 0; if (SIR_MAC_TDLS_TEARDOWN == action_code) { - responder = wlan_hdd_tdls_get_responder(pAdapter, peerMac); - if(-1 == responder) + + hddTdlsPeer_t *pTdlsPeer; + pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peerMac); + + if(pTdlsPeer && TDLS_IS_CONNECTED(pTdlsPeer)) + responder = pTdlsPeer->is_responder; + else { - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s: " MAC_ADDRESS_STR " peer doesn't exist dialog_token %d status %d, len = %d", - "tdls_mgmt", MAC_ADDR_ARRAY(peer), - dialog_token, status_code, len); - return -EPERM; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: " MAC_ADDRESS_STR " peer doesn't exist or not connected %d dialog_token %d status %d, len = %d", + __func__, MAC_ADDR_ARRAY(peer), (NULL == pTdlsPeer) ? -1 : pTdlsPeer->link_status, + dialog_token, status_code, len); + return -EPERM; } } + /* For explicit trigger of DIS_REQ come out of BMPS for + successfully receiving DIS_RSP from peer. */ + if ((SIR_MAC_TDLS_SETUP_RSP == action_code) || + (SIR_MAC_TDLS_DIS_RSP == action_code) || + (SIR_MAC_TDLS_DIS_REQ == action_code)) + { + if (TRUE == sme_IsPmcBmps(WLAN_HDD_GET_HAL_CTX(pAdapter))) + { + VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, + "%s: Sending frame action_code %u.Disable BMPS", __func__, action_code); + hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION); + } + if (SIR_MAC_TDLS_DIS_REQ != action_code) + wlan_hdd_tdls_set_cap(pAdapter, peerMac, eTDLS_CAP_SUPPORTED); + } + INIT_COMPLETION(pAdapter->tdls_mgmt_comp); status = sme_SendTdlsMgmtFrame(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, @@ -7161,28 +7515,27 @@ static int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *d { VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: sme_SendTdlsMgmtFrame failed!", __func__); - return -EPERM; + wlan_hdd_tdls_check_bmps(pAdapter); + goto error; } - /* not block discovery request, as it is called from timer callback */ - if (SIR_MAC_TDLS_DIS_REQ != action_code) - { - long rc; - - rc = wait_for_completion_interruptible_timeout(&pAdapter->tdls_mgmt_comp, - msecs_to_jiffies(WAIT_TIME_TDLS_MGMT)); + rc = wait_for_completion_interruptible_timeout(&pAdapter->tdls_mgmt_comp, + msecs_to_jiffies(WAIT_TIME_TDLS_MGMT)); - if ((rc <= 0) || (TRUE != pAdapter->mgmtTxCompletionStatus)) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s: Mgmt Tx Completion failed status %ld TxCompletion %lu", - __func__, rc, pAdapter->mgmtTxCompletionStatus); - return -EPERM; - } + if ((rc <= 0) || (TRUE != pAdapter->mgmtTxCompletionStatus)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Mgmt Tx Completion failed status %ld TxCompletion %lu", + __func__, rc, pAdapter->mgmtTxCompletionStatus); + wlan_hdd_tdls_check_bmps(pAdapter); + goto error; } if (max_sta_failed) + { + wlan_hdd_tdls_check_bmps(pAdapter); return max_sta_failed; + } if (SIR_MAC_TDLS_SETUP_RSP == action_code) { @@ -7211,6 +7564,7 @@ static int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *d { hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); hdd_context_t *pHddCtx = wiphy_priv(wiphy); + int status; #ifdef WLAN_FEATURE_TDLS_DEBUG const char *tdls_oper_str[]= { "NL80211_TDLS_DISCOVERY_REQ", @@ -7218,21 +7572,23 @@ static int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *d "NL80211_TDLS_TEARDOWN", "NL80211_TDLS_ENABLE_LINK", "NL80211_TDLS_DISABLE_LINK", - "NL80211_TDLS_UNKONW_OPER"}; + "NL80211_TDLS_UNKNOWN_OPER"}; #endif - if ( NULL == pHddCtx || NULL == pHddCtx->cfg_ini || NULL == peer ) + if ( NULL == peer ) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: Invalid arguments", __func__); return -EINVAL; } - if (pHddCtx->isLogpInProgress) + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EBUSY; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return status; } #ifdef WLAN_FEATURE_TDLS_DEBUG @@ -7273,13 +7629,35 @@ static int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *d return -EINVAL; } + if (!TDLS_STA_INDEX_VALID(pTdlsPeer->staId)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Staion Index %u " + MAC_ADDRESS_STR " failed", + __func__, pTdlsPeer->staId, MAC_ADDR_ARRAY(peer)); + return -EINVAL; + } + if (eTDLS_LINK_CONNECTING == pTdlsPeer->link_status) { wlan_hdd_tdls_set_peer_link_status(pTdlsPeer, eTDLS_LINK_CONNECTED); - /* start TDLS client registration with TL */ - status = hdd_roamRegisterTDLSSTA( pAdapter, peer, pTdlsPeer->staId, pTdlsPeer->signature); + /* Mark TDLS client Authenticated .*/ + status = WLANTL_ChangeSTAState( pHddCtx->pvosContext, + pTdlsPeer->staId, + WLANTL_STA_AUTHENTICATED); if (VOS_STATUS_SUCCESS == status) { + if (pTdlsPeer->is_responder == 0) + { + v_U8_t staId = (v_U8_t)pTdlsPeer->staId; + + wlan_hdd_tdls_timer_restart(pAdapter, + &pTdlsPeer->initiatorWaitTimeoutTimer, + WAIT_TIME_TDLS_INITIATOR); + /* suspend initiator TX until it receives direct packet from the + reponder or WAIT_TIME_TDLS_INITIATOR timer expires */ + WLANTL_SuspendDataTx( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, + &staId, NULL); + } wlan_hdd_tdls_increment_peer_count(pAdapter); } wlan_hdd_tdls_check_bmps(pAdapter); @@ -7291,7 +7669,7 @@ static int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *d { hddTdlsPeer_t *curr_peer = wlan_hdd_tdls_find_peer(pAdapter, peer); - if(NULL != curr_peer) + if((NULL != curr_peer) && TDLS_STA_INDEX_VALID(curr_peer->staId)) { long status; @@ -7393,6 +7771,7 @@ int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy, struct net_device *dev hdd_context_t *pHddCtx = wiphy_priv(wiphy); hdd_station_ctx_t *pHddStaCtx; tHalHandle hHal; + int result; tpSirGtkOffloadParams pGtkOffloadReqParams; eHalStatus status = eHAL_STATUS_FAILURE; @@ -7405,25 +7784,13 @@ int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy, struct net_device *dev return -ENODEV; } - if (NULL == pHddCtx) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s: HDD context is Null!!!", __func__); - return -ENODEV; - } - - if (pHddCtx->isLogpInProgress) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, - "%s: LOGP in Progress. Ignore!!!", __func__); - return -EAGAIN; - } + result = wlan_hdd_validate_context(pHddCtx); - if (pHddCtx->isLoadUnloadInProgress) + if (0 != result) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, - "%s: Unloading/Loading in Progress. Ignore!!!", __func__); - return -EAGAIN; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return result; } pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); @@ -7475,8 +7842,241 @@ int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy, struct net_device *dev } #endif /*WLAN_FEATURE_GTK_OFFLOAD*/ +/* + * FUNCTION: wlan_hdd_cfg80211_set_mac_acl + * This function is used to set access control policy + */ +static int wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy, + struct net_device *dev, const struct cfg80211_acl_data *params) +{ + int i; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_hostapd_state_t *pHostapdState; + tsap_Config_t *pConfig; + v_CONTEXT_t pVosContext = NULL; + hdd_context_t *pHddCtx; + int status; + + ENTER(); + + if (NULL == pAdapter) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s: HDD adapter is Null", __func__); + return -ENODEV; + } + + if (NULL == params) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s: params is Null", __func__); + return -EINVAL; + } + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return status; + } + + pVosContext = pHddCtx->pvosContext; + pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter); + + if (NULL == pHostapdState) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s: pHostapdState is Null", __func__); + return -EINVAL; + } + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"acl policy: = %d" + "no acl entries = %d", params->acl_policy, params->n_acl_entries); + + if (WLAN_HDD_SOFTAP == pAdapter->device_mode) + { + pConfig = &pAdapter->sessionCtx.ap.sapConfig; + + /* default value */ + pConfig->num_accept_mac = 0; + pConfig->num_deny_mac = 0; + + /** + * access control policy + * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are + * listed in hostapd.deny file. + * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are + * listed in hostapd.accept file. + */ + if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) + { + pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED; + } + else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED == params->acl_policy) + { + pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED; + } + else + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s:Acl Policy : %d is not supported", + __func__, params->acl_policy); + return -ENOTSUPP; + } + + if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) + { + pConfig->num_accept_mac = params->n_acl_entries; + for (i = 0; i < params->n_acl_entries; i++) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "** Add ACL MAC entry %i in WhiletList :" + MAC_ADDRESS_STR, i, + MAC_ADDR_ARRAY(params->mac_addrs[i].addr)); + + vos_mem_copy(&pConfig->accept_mac[i], params->mac_addrs[i].addr, + sizeof(qcmacaddr)); + } + } + else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) + { + pConfig->num_deny_mac = params->n_acl_entries; + for (i = 0; i < params->n_acl_entries; i++) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "** Add ACL MAC entry %i in BlackList :" + MAC_ADDRESS_STR, i, + MAC_ADDR_ARRAY(params->mac_addrs[i].addr)); + + vos_mem_copy(&pConfig->deny_mac[i], params->mac_addrs[i].addr, + sizeof(qcmacaddr)); + } + } + + if (VOS_STATUS_SUCCESS != WLANSAP_SetMacACL(pVosContext, pConfig)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: SAP Set Mac Acl fail", __func__); + return -EINVAL; + } + } + else + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid device_mode = %d", + __func__, pAdapter->device_mode); + return -EINVAL; + } + + return 0; +} + +/* + * FUNCTION: wlan_hdd_cfg80211_resume_wlan + * this is called when cfg80211 driver resume + * driver updates latest sched_scan scan result(if any) to cfg80211 database + */ +int wlan_hdd_cfg80211_resume_wlan(struct wiphy *wiphy) +{ + hdd_context_t *pHddCtx = wiphy_priv(wiphy); + hdd_adapter_t *pAdapter; + hdd_adapter_list_node_t *pAdapterNode, *pNext; + VOS_STATUS status = VOS_STATUS_SUCCESS; + + ENTER(); + + if ( NULL == pHddCtx ) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s: HddCtx validation failed", __func__); + return 0; + } + + if (pHddCtx->isLogpInProgress) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: LOGP in Progress. Ignore!!!", __func__); + return 0; + } + + if (pHddCtx->isLoadUnloadInProgress) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Unloading/Loading in Progress. Ignore!!!", __func__); + return 0; + } + + spin_lock(&pHddCtx->schedScan_lock); + pHddCtx->isWiphySuspended = FALSE; + if (TRUE != pHddCtx->isSchedScanUpdatePending) + { + spin_unlock(&pHddCtx->schedScan_lock); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Return resume is not due to PNO indication", __func__); + return 0; + } + // Reset flag to avoid updatating cfg80211 data old results again + pHddCtx->isSchedScanUpdatePending = FALSE; + spin_unlock(&pHddCtx->schedScan_lock); + + status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode ); + + while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status ) + { + pAdapter = pAdapterNode->pAdapter; + if ( (NULL != pAdapter) && + (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ) + { + if (0 != wlan_hdd_cfg80211_update_bss(pHddCtx->wiphy, pAdapter)) + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, + "%s: NO SCAN result", __func__); + else + cfg80211_sched_scan_results(pHddCtx->wiphy); + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s : cfg80211 scan result database updated", __func__); + + return 0; + + } + status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); + pAdapterNode = pNext; + } + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Failed to find Adapter", __func__); + return 0; +} + +/* + * FUNCTION: wlan_hdd_cfg80211_suspend_wlan + * this is called when cfg80211 driver suspends + */ +int wlan_hdd_cfg80211_suspend_wlan(struct wiphy *wiphy, + struct cfg80211_wowlan *wow) +{ + hdd_context_t *pHddCtx = wiphy_priv(wiphy); + + ENTER(); + if (NULL == pHddCtx) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s: HddCtx validation failed", __func__); + return 0; + } + + pHddCtx->isWiphySuspended = TRUE; + + EXIT(); + + return 0; +} + /* cfg80211_ops */ -static struct cfg80211_ops wlan_hdd_cfg80211_ops = +static struct cfg80211_ops wlan_hdd_cfg80211_ops = { .add_virtual_intf = wlan_hdd_add_virtual_intf, .del_virtual_intf = wlan_hdd_del_virtual_intf, @@ -7534,5 +8134,12 @@ static struct cfg80211_ops wlan_hdd_cfg80211_ops = #ifdef WLAN_FEATURE_GTK_OFFLOAD .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data, #endif /* WLAN_FEATURE_GTK_OFFLOAD */ +#ifdef FEATURE_WLAN_SCAN_PNO + .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start, + .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop, +#endif /*FEATURE_WLAN_SCAN_PNO */ + .resume = wlan_hdd_cfg80211_resume_wlan, + .suspend = wlan_hdd_cfg80211_suspend_wlan, + .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl, }; diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_dev_pwr.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_dev_pwr.c index 9b7a34476a2..f522f227e04 100644 --- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_dev_pwr.c +++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_dev_pwr.c @@ -143,7 +143,7 @@ static int wlan_suspend(hdd_context_t* pHddCtx) */ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: Suspending Mc, Rx and Tx Threads",__func__); - init_completion(&pHddCtx->tx_sus_event_var); + INIT_COMPLETION(pHddCtx->tx_sus_event_var); /* Indicate Tx Thread to Suspend */ set_bit(TX_SUSPEND_EVENT_MASK, &vosSchedContext->txEventFlag); @@ -163,7 +163,7 @@ static int wlan_suspend(hdd_context_t* pHddCtx) /* Set the Tx Thread as Suspended */ pHddCtx->isTxThreadSuspended = TRUE; - init_completion(&pHddCtx->rx_sus_event_var); + INIT_COMPLETION(pHddCtx->rx_sus_event_var); /* Indicate Rx Thread to Suspend */ set_bit(RX_SUSPEND_EVENT_MASK, &vosSchedContext->rxEventFlag); @@ -191,7 +191,7 @@ static int wlan_suspend(hdd_context_t* pHddCtx) /* Set the Rx Thread as Suspended */ pHddCtx->isRxThreadSuspended = TRUE; - init_completion(&pHddCtx->mc_sus_event_var); + INIT_COMPLETION(pHddCtx->mc_sus_event_var); /* Indicate MC Thread to Suspend */ set_bit(MC_SUSPEND_EVENT_MASK, &vosSchedContext->mcEventFlag); diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_early_suspend.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_early_suspend.c index 7984a354144..0a974d02126 100644 --- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_early_suspend.c +++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_early_suspend.c @@ -91,6 +91,7 @@ #include #include #include +#include /**----------------------------------------------------------------------------- * Preprocessor definitions and constants * ----------------------------------------------------------------------------*/ @@ -105,7 +106,7 @@ #include "wlan_hdd_power.h" #include "wlan_hdd_packet_filtering.h" -#define HDD_SSR_BRING_UP_TIME 10000 +#define HDD_SSR_BRING_UP_TIME 180000 static eHalStatus g_full_pwr_status; static eHalStatus g_standby_status; @@ -128,7 +129,7 @@ void hdd_suspend_standby_cbk (void *callbackContext, eHalStatus status) { hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext; hddLog(VOS_TRACE_LEVEL_INFO, "%s: Standby status = %d", __func__, status); - g_standby_status = status; + g_standby_status = status; if(eHAL_STATUS_SUCCESS == status) { @@ -162,7 +163,7 @@ void hdd_suspend_full_pwr_callback(void *callbackContext, eHalStatus status) } eHalStatus hdd_exit_standby(hdd_context_t *pHddCtx) -{ +{ eHalStatus status = VOS_STATUS_SUCCESS; hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed from standby",__func__); @@ -175,7 +176,7 @@ eHalStatus hdd_exit_standby(hdd_context_t *pHddCtx) if(status == eHAL_STATUS_PMC_PENDING) { //Block on a completion variable. Can't wait forever though - wait_for_completion_interruptible_timeout(&pHddCtx->full_pwr_comp_var, + wait_for_completion_interruptible_timeout(&pHddCtx->full_pwr_comp_var, msecs_to_jiffies(WLAN_WAIT_TIME_FULL_PWR)); status = g_full_pwr_status; if(g_full_pwr_status != eHAL_STATUS_SUCCESS) @@ -216,20 +217,19 @@ VOS_STATUS hdd_enter_standby(hdd_context_t *pHddCtx) //Note we do not disable queues unnecessarily. Queues should already be disabled //if STA is disconnected or the queue will be disabled as and when disconnect //happens because of standby procedure. - //Ensure that device is in full power first. There is scope for optimization //here especially in scenarios where PMC is already in IMPS or REQUEST_IMPS. //Core s/w needs to be optimized to handle this. Until then we request full //power before issuing request for standby. INIT_COMPLETION(pHddCtx->full_pwr_comp_var); g_full_pwr_status = eHAL_STATUS_FAILURE; - halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_suspend_full_pwr_callback, + halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_suspend_full_pwr_callback, pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD); if(halStatus == eHAL_STATUS_PMC_PENDING) { //Block on a completion variable. Can't wait forever though - wait_for_completion_interruptible_timeout(&pHddCtx->full_pwr_comp_var, + wait_for_completion_interruptible_timeout(&pHddCtx->full_pwr_comp_var, msecs_to_jiffies(WLAN_WAIT_TIME_FULL_PWR)); if(g_full_pwr_status != eHAL_STATUS_SUCCESS) { @@ -262,10 +262,10 @@ VOS_STATUS hdd_enter_standby(hdd_context_t *pHddCtx) g_standby_status = eHAL_STATUS_FAILURE; halStatus = sme_RequestStandby(pHddCtx->hHal, hdd_suspend_standby_cbk, pHddCtx); - if (halStatus == eHAL_STATUS_PMC_PENDING) + if (halStatus == eHAL_STATUS_PMC_PENDING) { //Wait till WLAN device enters standby mode - wait_for_completion_timeout(&pHddCtx->standby_comp_var, + wait_for_completion_timeout(&pHddCtx->standby_comp_var, msecs_to_jiffies(WLAN_WAIT_TIME_STANDBY)); if (g_standby_status != eHAL_STATUS_SUCCESS && g_standby_status != eHAL_STATUS_PMC_NOT_NOW) { @@ -317,13 +317,13 @@ VOS_STATUS hdd_enter_deep_sleep(hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter) //Ensure that device is in full power as we will touch H/W during vos_Stop INIT_COMPLETION(pHddCtx->full_pwr_comp_var); g_full_pwr_status = eHAL_STATUS_FAILURE; - halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_suspend_full_pwr_callback, + halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_suspend_full_pwr_callback, pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD); if(halStatus == eHAL_STATUS_PMC_PENDING) { //Block on a completion variable. Can't wait forever though - wait_for_completion_interruptible_timeout(&pHddCtx->full_pwr_comp_var, + wait_for_completion_interruptible_timeout(&pHddCtx->full_pwr_comp_var, msecs_to_jiffies(WLAN_WAIT_TIME_FULL_PWR)); if(g_full_pwr_status != eHAL_STATUS_SUCCESS){ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower failed",__func__); @@ -345,7 +345,7 @@ VOS_STATUS hdd_enter_deep_sleep(hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter) if(halStatus == eHAL_STATUS_SUCCESS) { //Block on a completion variable. Can't wait forever though. - wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var, + wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var, msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT)); } @@ -398,7 +398,7 @@ VOS_STATUS hdd_exit_deep_sleep(hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter) goto err_deep_sleep; } - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: calling vos_start",__func__); vosStatus = vos_start( pHddCtx->pvosContext ); VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); @@ -409,7 +409,7 @@ VOS_STATUS hdd_exit_deep_sleep(hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter) goto err_deep_sleep; } - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: calling hdd_post_voss_start_config",__func__); vosStatus = hdd_post_voss_start_config( pHddCtx ); VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); @@ -423,7 +423,8 @@ VOS_STATUS hdd_exit_deep_sleep(hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter) //Open a SME session for future operation halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pHddCtx, - (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId ); + (tANI_U8 *)&pAdapter->macAddressCurrent, + &pAdapter->sessionId); if ( !HAL_STATUS_SUCCESS( halStatus ) ) { hddLog(VOS_TRACE_LEVEL_FATAL,"sme_OpenSession() failed with status code %08d [x%08lx]", @@ -446,7 +447,265 @@ VOS_STATUS hdd_exit_deep_sleep(hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter) } -VOS_STATUS hdd_conf_hostarpoffload(hdd_adapter_t *pAdapter, v_BOOL_t fenable) +/* + * Function: hdd_conf_hostoffload + * Central function to configure the supported offloads, + * either enable or disable them. + */ +void hdd_conf_hostoffload(hdd_adapter_t *pAdapter, v_BOOL_t fenable) +{ + hdd_context_t *pHddCtx = NULL; + v_CONTEXT_t *pVosContext = NULL; + VOS_STATUS vstatus = VOS_STATUS_E_FAILURE; + + hddLog(VOS_TRACE_LEVEL_INFO, FL("Configuring offloads with flag: %d"), + fenable); + + pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); + + if (NULL == pVosContext) + { + hddLog(VOS_TRACE_LEVEL_ERROR, FL(" Global VOS context is Null")); + return; + } + + //Get the HDD context. + pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext ); + + if (NULL == pHddCtx) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: HDD context is Null", __func__); + return; + } + + if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) || + (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)) + { + if (fenable) + { + if (eConnectionState_Associated == + (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) + { + if ((pHddCtx->cfg_ini->fhostArpOffload)) + { + /* + * Configure the ARP Offload. + * Even if it fails we have to reconfigure the MC/BC + * filter flag as we want RIVA not to drop BroadCast + * Packets + */ + hddLog(VOS_TRACE_LEVEL_INFO, + FL("Calling ARP Offload with flag: %d"), fenable); + vstatus = hdd_conf_arp_offload(pAdapter, fenable); + pHddCtx->configuredMcastBcastFilter &= + ~(HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST); + + if (!VOS_IS_STATUS_SUCCESS(vstatus)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "Failed to enable ARPOFfloadFeature %d", + vstatus); + } + } + //Configure GTK_OFFLOAD +#ifdef WLAN_FEATURE_GTK_OFFLOAD + hdd_conf_gtk_offload(pAdapter, fenable); +#endif + +#ifdef WLAN_NS_OFFLOAD + if (pHddCtx->cfg_ini->fhostNSOffload) + { + /* + * Configure the NS Offload. + * Even if it fails we have to reconfigure the MC/BC filter flag + * as we want RIVA not to drop Multicast Packets + */ + + hddLog(VOS_TRACE_LEVEL_INFO, + FL("Calling NS Offload with flag: %d"), fenable); + hdd_conf_ns_offload(pAdapter, fenable); + pHddCtx->configuredMcastBcastFilter &= + ~(HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST); + } +#endif + } + } + else + { + //Disable ARPOFFLOAD + if (pHddCtx->cfg_ini->fhostArpOffload) + { + vstatus = hdd_conf_arp_offload(pAdapter, fenable); + if (!VOS_IS_STATUS_SUCCESS(vstatus)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "Failed to disable ARPOffload Feature %d", vstatus); + } + } + //Disable GTK_OFFLOAD +#ifdef WLAN_FEATURE_GTK_OFFLOAD + hdd_conf_gtk_offload(pAdapter, fenable); +#endif + +#ifdef WLAN_NS_OFFLOAD + //Disable NSOFFLOAD + if (pHddCtx->cfg_ini->fhostNSOffload) + { + hdd_conf_ns_offload(pAdapter, fenable); + } +#endif + } + } + return; +} + +#ifdef WLAN_NS_OFFLOAD +void hdd_conf_ns_offload(hdd_adapter_t *pAdapter, v_BOOL_t fenable) +{ + struct inet6_dev *in6_dev; + struct inet6_ifaddr *ifp; + struct list_head *p; + tANI_U8 selfIPv6Addr[SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA][SIR_MAC_IPV6_ADDR_LEN] = {{0,}}; + tANI_BOOLEAN selfIPv6AddrValid[SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA] = {0}; + tSirHostOffloadReq offLoadRequest; + hdd_context_t *pHddCtx; + + int i =0; + eHalStatus returnStatus; + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + ENTER(); + if (fenable) + { + in6_dev = __in6_dev_get(pAdapter->dev); + if (NULL != in6_dev) + { + //read_lock_bh(&in6_dev->lock); + list_for_each(p, &in6_dev->addr_list) + { + ifp = list_entry(p, struct inet6_ifaddr, if_list); + switch(ipv6_addr_src_scope(&ifp->addr)) + { + case IPV6_ADDR_SCOPE_LINKLOCAL: + vos_mem_copy(&selfIPv6Addr[0], &ifp->addr.s6_addr, + sizeof(ifp->addr.s6_addr)); + selfIPv6AddrValid[0] = SIR_IPV6_ADDR_VALID; + hddLog (VOS_TRACE_LEVEL_INFO, + "Found IPV6_ADDR_SCOPE_LINKLOCAL Address : %pI6", + selfIPv6Addr[0]); + break; + case IPV6_ADDR_SCOPE_GLOBAL: + vos_mem_copy(&selfIPv6Addr[1], &ifp->addr.s6_addr, + sizeof(ifp->addr.s6_addr)); + selfIPv6AddrValid[1] = SIR_IPV6_ADDR_VALID; + hddLog (VOS_TRACE_LEVEL_INFO, + "Found IPV6_ADDR_SCOPE_GLOBAL Address : %pI6", + selfIPv6Addr[1]); + break; + default: + hddLog(LOGE, "The Scope %d is not supported", + ipv6_addr_src_scope(&ifp->addr)); + } + + } + //read_unlock_bh(&in6_dev->lock); + vos_mem_zero(&offLoadRequest, sizeof(offLoadRequest)); + for (i =0; imacAddressCurrent.bytes, + sizeof(tANI_U8)*SIR_MAC_ADDR_LEN); + + offLoadRequest.nsOffloadInfo.targetIPv6AddrValid[0] = SIR_IPV6_ADDR_VALID; + offLoadRequest.offloadType = SIR_IPV6_NS_OFFLOAD; + offLoadRequest.enableOrDisable = SIR_OFFLOAD_ENABLE; + + hddLog (VOS_TRACE_LEVEL_INFO, + "configuredMcastBcastFilter: %d",pHddCtx->configuredMcastBcastFilter); + + if((HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST == + pHddCtx->configuredMcastBcastFilter) || + (HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST_BROADCAST == + pHddCtx->configuredMcastBcastFilter)) + { + hddLog (VOS_TRACE_LEVEL_INFO, + "Set offLoadRequest with SIR_OFFLOAD_NS_AND_MCAST_FILTER_ENABLE \n", __func__); + offLoadRequest.enableOrDisable = + SIR_OFFLOAD_NS_AND_MCAST_FILTER_ENABLE; + } + + vos_mem_copy(&offLoadRequest.params.hostIpv6Addr, + &offLoadRequest.nsOffloadInfo.targetIPv6Addr[0], + sizeof(tANI_U8)*SIR_MAC_IPV6_ADDR_LEN); + + hddLog (VOS_TRACE_LEVEL_INFO, + "Setting NSOffload with solicitedIp: %pI6, targetIp: %pI6", + offLoadRequest.nsOffloadInfo.selfIPv6Addr, + offLoadRequest.nsOffloadInfo.targetIPv6Addr[0]); + + //Configure the Firmware with this + returnStatus = sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, &offLoadRequest); + if(eHAL_STATUS_SUCCESS != returnStatus) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("Failed to enable HostOffload feature with status: %d"), + returnStatus); + } + vos_mem_zero(&offLoadRequest, sizeof(offLoadRequest)); + } + } + } + else + { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("IPv6 dev does not exist. Failed to request NSOffload")); + return; + } + } + else + { + //Disable NSOffload + vos_mem_zero((void *)&offLoadRequest, sizeof(tSirHostOffloadReq)); + offLoadRequest.enableOrDisable = SIR_OFFLOAD_DISABLE; + offLoadRequest.offloadType = SIR_IPV6_NS_OFFLOAD; + + if (eHAL_STATUS_SUCCESS != + sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, &offLoadRequest)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Failure to disable" + "NSOffload feature")); + } + } + return; +} +#endif +VOS_STATUS hdd_conf_arp_offload(hdd_adapter_t *pAdapter, v_BOOL_t fenable) { struct in_ifaddr **ifap = NULL; struct in_ifaddr *ifa = NULL; @@ -461,7 +720,7 @@ VOS_STATUS hdd_conf_hostarpoffload(hdd_adapter_t *pAdapter, v_BOOL_t fenable) { if ((in_dev = __in_dev_get_rtnl(pAdapter->dev)) != NULL) { - for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL; + for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL; ifap = &ifa->ifa_next) { if (!strcmp(pAdapter->dev->name, ifa->ifa_label)) @@ -470,49 +729,37 @@ VOS_STATUS hdd_conf_hostarpoffload(hdd_adapter_t *pAdapter, v_BOOL_t fenable) } } } - if(ifa && ifa->ifa_local) { offLoadRequest.offloadType = SIR_IPV4_ARP_REPLY_OFFLOAD; offLoadRequest.enableOrDisable = SIR_OFFLOAD_ENABLE; - hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Enabled \n", __func__); + hddLog(VOS_TRACE_LEVEL_INFO, "%s: Enabled \n", __func__); - if(pHddCtx->dynamic_mcbc_filter.enableCfg) - { - if((HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST == - pHddCtx->dynamic_mcbc_filter.mcastBcastFilterSetting) || - (HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST_BROADCAST == - pHddCtx->dynamic_mcbc_filter.mcastBcastFilterSetting)) - { - offLoadRequest.enableOrDisable = - SIR_OFFLOAD_ARP_AND_BCAST_FILTER_ENABLE; - } - } - else if((HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST == - pHddCtx->cfg_ini->mcastBcastFilterSetting ) || + if((HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST == + pHddCtx->configuredMcastBcastFilter) || (HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST_BROADCAST == - pHddCtx->cfg_ini->mcastBcastFilterSetting)) + pHddCtx->configuredMcastBcastFilter)) { - offLoadRequest.enableOrDisable = - SIR_OFFLOAD_ARP_AND_BCAST_FILTER_ENABLE; + offLoadRequest.enableOrDisable = + SIR_OFFLOAD_ARP_AND_BCAST_FILTER_ENABLE; } - + //converting u32 to IPV4 address for(i = 0 ; i < 4; i++) { - offLoadRequest.params.hostIpv4Addr[i] = + offLoadRequest.params.hostIpv4Addr[i] = (ifa->ifa_local >> (i*8) ) & 0xFF ; } - hddLog(VOS_TRACE_LEVEL_WARN, " Enable SME HostOffload: %d.%d.%d.%d", + hddLog(VOS_TRACE_LEVEL_INFO, " Enable SME HostOffload: %d.%d.%d.%d", offLoadRequest.params.hostIpv4Addr[0], offLoadRequest.params.hostIpv4Addr[1], offLoadRequest.params.hostIpv4Addr[2], offLoadRequest.params.hostIpv4Addr[3]); - if (eHAL_STATUS_SUCCESS != - sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter), - pAdapter->sessionId, &offLoadRequest)) + if (eHAL_STATUS_SUCCESS != + sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, &offLoadRequest)) { hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to enable HostOffload " "feature\n", __func__); @@ -532,8 +779,9 @@ VOS_STATUS hdd_conf_hostarpoffload(hdd_adapter_t *pAdapter, v_BOOL_t fenable) offLoadRequest.enableOrDisable = SIR_OFFLOAD_DISABLE; offLoadRequest.offloadType = SIR_IPV4_ARP_REPLY_OFFLOAD; - if (eHAL_STATUS_SUCCESS != sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, - &offLoadRequest)) + if (eHAL_STATUS_SUCCESS != + sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, &offLoadRequest)) { hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failure to disable host " "offload feature\n", __func__); @@ -545,67 +793,41 @@ VOS_STATUS hdd_conf_hostarpoffload(hdd_adapter_t *pAdapter, v_BOOL_t fenable) /* * This function is called before setting mcbc filters - * to modify filter value considering ARP + * to modify filter value considering Different Offloads */ -void hdd_mcbc_filter_modification(hdd_context_t* pHddCtx, v_BOOL_t arpFlag, +void hdd_mcbc_filter_modification(hdd_context_t* pHddCtx, tANI_U8 *pMcBcFilter) { - if (TRUE == arpFlag) + if (NULL == pHddCtx) { - /*ARP offload is enabled, do not block bcast packets at RXP*/ - if (pHddCtx->dynamic_mcbc_filter.enableCfg) - { - if ((HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST_BROADCAST == - pHddCtx->dynamic_mcbc_filter.mcastBcastFilterSetting)) - { - *pMcBcFilter = HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST; - } - else if ((HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST == - pHddCtx->dynamic_mcbc_filter.mcastBcastFilterSetting)) - { - *pMcBcFilter = HDD_MCASTBCASTFILTER_FILTER_NONE; - } - else - { - *pMcBcFilter = pHddCtx->dynamic_mcbc_filter.mcastBcastFilterSetting; - } - - pHddCtx->dynamic_mcbc_filter.enableSuspend = TRUE; - pHddCtx->dynamic_mcbc_filter.mcBcFilterSuspend = *pMcBcFilter; - } - else - { - if (HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST_BROADCAST == - pHddCtx->cfg_ini->mcastBcastFilterSetting) - { - *pMcBcFilter = HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST; - } - else if (HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST == - pHddCtx->cfg_ini->mcastBcastFilterSetting) - { - *pMcBcFilter = HDD_MCASTBCASTFILTER_FILTER_NONE; - } - else - { - *pMcBcFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting; - } + hddLog(VOS_TRACE_LEVEL_ERROR, FL("NULL HDD context passed")); + return; + } - pHddCtx->dynamic_mcbc_filter.enableSuspend = FALSE; - } + *pMcBcFilter = pHddCtx->configuredMcastBcastFilter; + if (pHddCtx->cfg_ini->fhostArpOffload) + { + /* ARP offload is enabled, do not block bcast packets at RXP + * Will be using Bitmasking to reset the filter. As we have + * disable Broadcast filtering, Anding with the negation + * of Broadcast BIT + */ + *pMcBcFilter &= ~(HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST); } - else + +#ifdef WLAN_NS_OFFLOAD + if (pHddCtx->cfg_ini->fhostNSOffload) { - if (pHddCtx->dynamic_mcbc_filter.enableCfg) - { - *pMcBcFilter = pHddCtx->dynamic_mcbc_filter.mcastBcastFilterSetting; - pHddCtx->dynamic_mcbc_filter.enableSuspend = TRUE; - } - else - { - pHddCtx->dynamic_mcbc_filter.enableSuspend = FALSE; - *pMcBcFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting; - } + /* NS offload is enabled, do not block mcast packets at RXP + * Will be using Bitmasking to reset the filter. As we have + * disable Multicast filtering, Anding with the negation + * of Multicast BIT + */ + *pMcBcFilter &= ~(HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST); } +#endif + + pHddCtx->configuredMcastBcastFilter = *pMcBcFilter; } void hdd_conf_mcastbcast_filter(hdd_context_t* pHddCtx, v_BOOL_t setfilter) @@ -623,20 +845,15 @@ void hdd_conf_mcastbcast_filter(hdd_context_t* pHddCtx, v_BOOL_t setfilter) "%s: Configuring Mcast/Bcast Filter Setting. setfilter %d", __func__, setfilter); if (TRUE == setfilter) { - if (pHddCtx->cfg_ini->fhostArpOffload) - { - hdd_mcbc_filter_modification(pHddCtx, TRUE, + hdd_mcbc_filter_modification(pHddCtx, &wlanRxpFilterParam->configuredMcstBcstFilterSetting); - } - else - { - hdd_mcbc_filter_modification(pHddCtx, FALSE, - &wlanRxpFilterParam->configuredMcstBcstFilterSetting); - } } else + { + /*Use the current configured value to clear*/ wlanRxpFilterParam->configuredMcstBcstFilterSetting = - pHddCtx->cfg_ini->mcastBcastFilterSetting; + pHddCtx->configuredMcastBcastFilter; + } wlanRxpFilterParam->setMcstBcstFilter = setfilter; halStatus = sme_ConfigureRxpFilter(pHddCtx->hHal, wlanRxpFilterParam); @@ -650,10 +867,12 @@ static void hdd_conf_suspend_ind(hdd_context_t* pHddCtx, hdd_adapter_t *pAdapter) { eHalStatus halStatus = eHAL_STATUS_FAILURE; - VOS_STATUS vstatus = VOS_STATUS_E_FAILURE; tpSirWlanSuspendParam wlanSuspendParam = vos_mem_malloc(sizeof(tSirWlanSuspendParam)); + pHddCtx->sus_res_mcastbcast_filter = + pHddCtx->configuredMcastBcastFilter; + if(NULL == wlanSuspendParam) { hddLog(VOS_TRACE_LEVEL_FATAL, @@ -661,49 +880,23 @@ static void hdd_conf_suspend_ind(hdd_context_t* pHddCtx, return; } - hddLog(VOS_TRACE_LEVEL_INFO, + hddLog(VOS_TRACE_LEVEL_INFO, "%s: send wlan suspend indication", __func__); if((pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER)) { - if((pHddCtx->cfg_ini->fhostArpOffload) && - (eConnectionState_Associated == - (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState)) - { - vstatus = hdd_conf_hostarpoffload(pAdapter, TRUE); - if (!VOS_IS_STATUS_SUCCESS(vstatus)) - { - hdd_mcbc_filter_modification(pHddCtx, FALSE, - &wlanSuspendParam->configuredMcstBcstFilterSetting); - hddLog(VOS_TRACE_LEVEL_INFO, - "%s:Failed to enable ARPOFFLOAD Feature %d\n", - __func__, vstatus); - } - else - { - hdd_mcbc_filter_modification(pHddCtx, TRUE, - &wlanSuspendParam->configuredMcstBcstFilterSetting); - } - } - else - { - hdd_mcbc_filter_modification(pHddCtx, FALSE, - &wlanSuspendParam->configuredMcstBcstFilterSetting); - if(pHddCtx->dynamic_mcbc_filter.enableCfg) - { - pHddCtx->dynamic_mcbc_filter.mcBcFilterSuspend = - wlanSuspendParam->configuredMcstBcstFilterSetting; - } - } + //Configure supported OffLoads + hdd_conf_hostoffload(pAdapter, TRUE); + wlanSuspendParam->configuredMcstBcstFilterSetting = pHddCtx->configuredMcastBcastFilter; #ifdef WLAN_FEATURE_PACKET_FILTERING if (pHddCtx->cfg_ini->isMcAddrListFilter) { /*Multicast addr list filter is enabled during suspend*/ - if (((pAdapter->device_mode == WLAN_HDD_INFRA_STATION) || + if (((pAdapter->device_mode == WLAN_HDD_INFRA_STATION) || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)) && pAdapter->mc_addr_list.mc_cnt - && (eConnectionState_Associated == + && (eConnectionState_Associated == (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState)) { /*set the filter*/ @@ -725,7 +918,6 @@ static void hdd_conf_suspend_ind(hdd_context_t* pHddCtx, static void hdd_conf_resume_ind(hdd_adapter_t *pAdapter) { eHalStatus halStatus = eHAL_STATUS_FAILURE; - VOS_STATUS vstatus; hdd_context_t* pHddCtx = WLAN_HDD_GET_CTX(pAdapter); tpSirWlanResumeParam wlanResumeParam; @@ -743,33 +935,22 @@ static void hdd_conf_resume_ind(hdd_adapter_t *pAdapter) return; } - if (pHddCtx->cfg_ini->fhostArpOffload) - { - vstatus = hdd_conf_hostarpoffload(pAdapter, FALSE); - if (!VOS_IS_STATUS_SUCCESS(vstatus)) - { - hddLog(VOS_TRACE_LEVEL_INFO, "%s:Failed to disable ARPOFFLOAD " - "Feature %d\n", __func__, vstatus); - } - } - if (pHddCtx->dynamic_mcbc_filter.enableSuspend) - { - wlanResumeParam->configuredMcstBcstFilterSetting = - pHddCtx->dynamic_mcbc_filter.mcBcFilterSuspend; - } - else - { - wlanResumeParam->configuredMcstBcstFilterSetting = - pHddCtx->cfg_ini->mcastBcastFilterSetting; - } + //Disable supported OffLoads + hdd_conf_hostoffload(pAdapter, FALSE); + + wlanResumeParam->configuredMcstBcstFilterSetting = + pHddCtx->configuredMcastBcastFilter; halStatus = sme_ConfigureResumeReq(pHddCtx->hHal, wlanResumeParam); if (eHAL_STATUS_SUCCESS != halStatus) vos_mem_free(wlanResumeParam); pHddCtx->hdd_mcastbcast_filter_set = FALSE; } + pHddCtx->configuredMcastBcastFilter = + pHddCtx->sus_res_mcastbcast_filter; + -#ifdef WLAN_FEATURE_PACKET_FILTERING +#ifdef WLAN_FEATURE_PACKET_FILTERING if (pHddCtx->cfg_ini->isMcAddrListFilter) { /*Multicast addr filtering is enabled*/ @@ -789,9 +970,10 @@ void hdd_suspend_wlan(void) hdd_context_t *pHddCtx = NULL; v_CONTEXT_t pVosContext = NULL; - hdd_adapter_t *pAdapter = NULL; - hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; VOS_STATUS status; + hdd_adapter_t *pAdapter = NULL; + hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; + bool hdd_enter_bmps = FALSE; hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being suspended by Android OS",__func__); @@ -816,7 +998,7 @@ void hdd_suspend_wlan(void) return; } - /*loop through all adapters. TBD fix for Concurrency */ + hdd_set_pwrparams(pHddCtx); status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode ); while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status ) { @@ -830,7 +1012,22 @@ void hdd_suspend_wlan(void) pAdapterNode = pNext; continue; } + /* Avoid multiple enter/exit BMPS in this while loop using + * hdd_enter_bmps flag + */ + if (FALSE == hdd_enter_bmps && (BMPS == pmcGetPmcState(pHddCtx->hHal))) + { + hdd_enter_bmps = TRUE; + + /* If device was already in BMPS, and dynamic DTIM is set, + * exit(set the device to full power) and enter BMPS again + * to reflect new DTIM value */ + wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_ACTIVE); + wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_AUTO); + + pHddCtx->hdd_ignore_dtim_enabled = TRUE; + } #ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP if (pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_STANDBY) { @@ -838,7 +1035,7 @@ void hdd_suspend_wlan(void) netif_tx_disable(pAdapter->dev); netif_carrier_off(pAdapter->dev); } - else if (pHddCtx->cfg_ini->nEnableSuspend == + else if (pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_DEEP_SLEEP) { //Execute deep sleep procedure @@ -846,96 +1043,14 @@ void hdd_suspend_wlan(void) } #endif - //Apply Dynamic Dtim For P2P - //Only if ignoreDynamicDtimInP2pMode is not set in ini - if((pHddCtx->cfg_ini->enableDynamicDTIM || - pHddCtx->cfg_ini->enableModulatedDTIM) && - ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) || - ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) && - !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) && - (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) && - (eConnectionState_Associated == - (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) && - (pHddCtx->cfg_ini->fIsBmpsEnabled)) - { - tSirSetPowerParamsReq powerRequest = { 0 }; - - powerRequest.uIgnoreDTIM = 1; - - /*Back up the actual values from CFG */ - wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, - &pHddCtx->hdd_actual_ignore_DTIM_value); - wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, - &pHddCtx->hdd_actual_LI_value); - - if(pHddCtx->cfg_ini->enableModulatedDTIM) - { - powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM; - powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value; - } - else - { - powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM; - } - - /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM - *specified during Enter/Exit BMPS when LCD off*/ - ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM, - NULL, eANI_BOOLEAN_FALSE); - ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval, - NULL, eANI_BOOLEAN_FALSE); - - /* switch to the DTIM specified in cfg.ini */ - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - "Switch to DTIM%d \n", powerRequest.uListenInterval); - sme_SetPowerParams( WLAN_HDD_GET_HAL_CTX(pAdapter), &powerRequest, FALSE); - - if (BMPS == pmcGetPmcState(pHddCtx->hHal)) - { - /* put the device into full power */ - wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_ACTIVE); - - /* put the device back into BMPS */ - wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_AUTO); + /*Suspend notification sent down to driver*/ + hdd_conf_suspend_ind(pHddCtx, pAdapter); - pHddCtx->hdd_ignore_dtim_enabled = TRUE; - } + status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); + pAdapterNode = pNext; } - /*Suspend notification sent down to driver*/ - hdd_conf_suspend_ind(pHddCtx, pAdapter); - -#ifdef WLAN_FEATURE_GTK_OFFLOAD - if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) || - (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)) - { - eHalStatus ret; - hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); - if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) && - (TRUE == pHddStaCtx->gtkOffloadRequestParams.requested)) - { - ret = sme_SetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter), - &pHddStaCtx->gtkOffloadRequestParams.gtkOffloadReqParams, - pAdapter->sessionId); - if (eHAL_STATUS_SUCCESS != ret) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s: sme_SetGTKOffload failed, returned %d", - __func__, ret); - } - pHddStaCtx->gtkOffloadRequestParams.requested = FALSE; - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - "%s: sme_SetGTKOffload successfull", - __func__); - } - } -#endif - - status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); - pAdapterNode = pNext; - } - pHddCtx->hdd_wlan_suspended = TRUE; - + pHddCtx->hdd_wlan_suspended = TRUE; #ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP if(pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_STANDBY) { @@ -953,7 +1068,7 @@ static void hdd_PowerStateChangedCB ) { hdd_context_t *pHddCtx = callbackContext; - + /* if the driver was not in BMPS during early suspend, * the dynamic DTIM is now updated at Riva */ if ((newState == BMPS) && pHddCtx->hdd_wlan_suspended @@ -965,11 +1080,12 @@ static void hdd_PowerStateChangedCB spin_lock(&pHddCtx->filter_lock); if((newState == BMPS) && pHddCtx->hdd_wlan_suspended) { spin_unlock(&pHddCtx->filter_lock); + pHddCtx->sus_res_mcastbcast_filter = pHddCtx->configuredMcastBcastFilter; hdd_conf_mcastbcast_filter(pHddCtx, TRUE); if(pHddCtx->hdd_mcastbcast_filter_set != TRUE) hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not able to set mcast/bcast filter ", __func__); } - else + else spin_unlock(&pHddCtx->filter_lock); } @@ -1026,50 +1142,83 @@ void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx) pmcDeregisterDeviceStateUpdateInd(smeContext, hdd_PowerStateChangedCB); } } + #ifdef WLAN_FEATURE_GTK_OFFLOAD -void wlan_hdd_update_and_dissable_gtk_offload(hdd_adapter_t *pAdapter) +void hdd_conf_gtk_offload(hdd_adapter_t *pAdapter, v_BOOL_t fenable) { eHalStatus ret; tpSirGtkOffloadParams pGtkOffloadReqParams; hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); - pGtkOffloadReqParams = - &pHddStaCtx->gtkOffloadRequestParams.gtkOffloadReqParams; + if(fenable) + { + if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) && + (GTK_OFFLOAD_ENABLE == pHddStaCtx->gtkOffloadReqParams.ulFlags )) + { + vos_mem_copy(&hddGtkOffloadReqParams, + &pHddStaCtx->gtkOffloadReqParams, + sizeof (tSirGtkOffloadParams)); - if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) && - (0 != memcmp(&pGtkOffloadReqParams->bssId, - &pHddStaCtx->conn_info.bssId, WNI_CFG_BSSID_LEN)) && - (FALSE == pHddStaCtx->gtkOffloadRequestParams.requested)) + ret = sme_SetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter), + &hddGtkOffloadReqParams, pAdapter->sessionId); + if (eHAL_STATUS_SUCCESS != ret) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: sme_SetGTKOffload failed, returned %d", + __func__, ret); + return; + } + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: sme_SetGTKOffload successfull", __func__); + } + } + else { - /* Host driver has previously offloaded GTK rekey */ - ret = sme_GetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter), + if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) && + (0 == memcmp(&pHddStaCtx->gtkOffloadReqParams.bssId, + &pHddStaCtx->conn_info.bssId, WNI_CFG_BSSID_LEN)) && + (GTK_OFFLOAD_ENABLE == pHddStaCtx->gtkOffloadReqParams.ulFlags)) + { + + /* Host driver has previously offloaded GTK rekey */ + ret = sme_GetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter), wlan_hdd_cfg80211_update_replayCounterCallback, pAdapter, pAdapter->sessionId); - if (eHAL_STATUS_SUCCESS != ret) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s: sme_GetGTKOffload failed, returned %d", - __func__, ret); - } - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - "%s: sme_GetGTKOffload successfull", __func__); + if (eHAL_STATUS_SUCCESS != ret) - /* Sending GTK offload dissable */ - pGtkOffloadReqParams->ulFlags = GTK_OFFLOAD_DISABLE; - ret = sme_SetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter), - pGtkOffloadReqParams, pAdapter->sessionId); + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: sme_GetGTKOffload failed, returned %d", + __func__, ret); + return; + } + else + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: sme_GetGTKOffload successful", + __func__); - if (eHAL_STATUS_SUCCESS != ret) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s: failed to dissable GTK offload, returned %d", - __func__, ret); + /* Sending GTK offload dissable */ + memcpy(&hddGtkOffloadReqParams, &pHddStaCtx->gtkOffloadReqParams, + sizeof (tSirGtkOffloadParams)); + hddGtkOffloadReqParams.ulFlags = GTK_OFFLOAD_DISABLE; + ret = sme_SetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter), + &hddGtkOffloadReqParams, pAdapter->sessionId); + if (eHAL_STATUS_SUCCESS != ret) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: failed to dissable GTK offload, returned %d", + __func__, ret); + return; + } + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: successfully dissabled GTK offload request to HAL", + __func__); + } } - pHddStaCtx->gtkOffloadRequestParams.requested = FALSE; - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - "%s: successfully dissabled GTK offload request to HAL", - __func__); } + return; } #endif /*WLAN_FEATURE_GTK_OFFLOAD*/ @@ -1097,7 +1246,7 @@ void hdd_resume_wlan(void) hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__); return; } - + if (pHddCtx->isLogpInProgress) { hddLog(VOS_TRACE_LEVEL_INFO, "%s: Ignore resume wlan, LOGP in progress!", __func__); @@ -1120,16 +1269,9 @@ void hdd_resume_wlan(void) continue; } -#ifdef WLAN_FEATURE_GTK_OFFLOAD - if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) || - (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)) - { - wlan_hdd_update_and_dissable_gtk_offload(pAdapter); - } -#endif -#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP - if(pHddCtx->hdd_ps_state == eHDD_SUSPEND_DEEP_SLEEP) +#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP + if(pHddCtx->hdd_ps_state == eHDD_SUSPEND_DEEP_SLEEP) { hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed from deep sleep",__func__); hdd_exit_deep_sleep(pAdapter); @@ -1139,10 +1281,11 @@ void hdd_resume_wlan(void) if(pHddCtx->hdd_ignore_dtim_enabled == TRUE) { /*Switch back to DTIM 1*/ - tSirSetPowerParamsReq powerRequest = { 0 }; + tSirSetPowerParamsReq powerRequest = { 0 }; powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value; powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value; + powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM; /*Disabled ModulatedDTIM if enabled on suspend*/ if(pHddCtx->cfg_ini->enableModulatedDTIM) @@ -1151,10 +1294,10 @@ void hdd_resume_wlan(void) /* Update ignoreDTIM and ListedInterval in CFG with default values */ ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM, NULL, eANI_BOOLEAN_FALSE); - ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval, + ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval, NULL, eANI_BOOLEAN_FALSE); - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "Switch to DTIM%d \n",powerRequest.uListenInterval); sme_SetPowerParams( WLAN_HDD_GET_HAL_CTX(pAdapter), &powerRequest, FALSE); @@ -1175,25 +1318,25 @@ void hdd_resume_wlan(void) pAdapterNode = pNext; } -#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP - if(pHddCtx->hdd_ps_state == eHDD_SUSPEND_STANDBY) +#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP + if(pHddCtx->hdd_ps_state == eHDD_SUSPEND_STANDBY) { hdd_exit_standby(pHddCtx); - } + } #endif return; } -VOS_STATUS hdd_wlan_reset_initialization(void) +VOS_STATUS hdd_wlan_reset_initialization(void) { v_CONTEXT_t pVosContext = NULL; - hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN being reset",__func__); + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN being reset",__func__); //Get the global VOSS context. pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); - if(!pVosContext) + if(!pVosContext) { hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__); return VOS_STATUS_E_FAILURE; @@ -1410,6 +1553,9 @@ VOS_STATUS hdd_wlan_re_init(void) v_CONTEXT_t pVosContext = NULL; hdd_context_t *pHddCtx = NULL; eHalStatus halStatus; +#ifdef HAVE_WCNSS_CAL_DOWNLOAD + int max_retries = 0; +#endif #ifdef WLAN_BTAMP_FEATURE hdd_config_t *pConfig = NULL; WLANBAP_ConfigType btAmpConfig; @@ -1418,6 +1564,17 @@ VOS_STATUS hdd_wlan_re_init(void) hdd_ssr_timer_del(); hdd_prevent_suspend(); +#ifdef HAVE_WCNSS_CAL_DOWNLOAD + /* wait until WCNSS driver downloads NV */ + while (!wcnss_device_ready() && 5 >= ++max_retries) { + msleep(1000); + } + if (max_retries >= 5) { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__); + goto err_re_init; + } +#endif + /* The driver should always be initialized in STA mode after SSR */ hdd_set_conparam(0); @@ -1607,6 +1764,7 @@ VOS_STATUS hdd_wlan_re_init(void) err_re_init: /* Allow the phone to go to sleep */ hdd_allow_suspend(); + VOS_BUG(0); return -EPERM; success: diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_ftm.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_ftm.c index e56780556b1..35401d0232e 100644 --- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_ftm.c +++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_ftm.c @@ -169,6 +169,7 @@ typedef struct { extern const sHalNv nvDefaults; static int wlan_ftm_register_wext(hdd_adapter_t *pAdapter); +static int wlan_ftm_stop(hdd_context_t *pHddCtx); /* for PRIMA: all the available frequency, channal pair i the table are defined for channel frequency @ RF center frequency Since it is associated to agc.channel_freq register for mapping. @@ -1009,7 +1010,7 @@ int wlan_hdd_ftm_open(hdd_context_t *pHddCtx) if (NULL == pVosContext) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s: Trying to open VOSS without a PreOpen",__func__); + "%s: Trying to open VOSS without a PreOpen", __func__); VOS_ASSERT(0); goto err_vos_status_failure; } @@ -1019,7 +1020,7 @@ int wlan_hdd_ftm_open(hdd_context_t *pHddCtx) if ( !VOS_IS_STATUS_SUCCESS( vStatus )) { - hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_open failed",__func__); + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_open failed", __func__); goto err_vos_status_failure; } @@ -1031,7 +1032,7 @@ int wlan_hdd_ftm_open(hdd_context_t *pHddCtx) if ( NULL == pHddCtx->hHal ) { - hddLog(VOS_TRACE_LEVEL_ERROR,"%s: HAL context is null",__func__); + hddLog(VOS_TRACE_LEVEL_ERROR,"%s: HAL context is null", __func__); goto err_sal_close; } @@ -1039,20 +1040,20 @@ int wlan_hdd_ftm_open(hdd_context_t *pHddCtx) wlan_hdd_get_intf_addr(pHddCtx), FALSE); if( NULL == pAdapter ) { - hddLog(VOS_TRACE_LEVEL_ERROR,"%s: hdd_open_adapter failed",__func__); + hddLog(VOS_TRACE_LEVEL_ERROR,"%s: hdd_open_adapter failed", __func__); goto err_adapter_open_failure; } if( wlan_ftm_register_wext(pAdapter)!= 0 ) { - hddLog(VOS_TRACE_LEVEL_ERROR,"%S: hdd_register_wext failed",__func__); + hddLog(VOS_TRACE_LEVEL_ERROR,"%s: hdd_register_wext failed", __func__); goto err_sal_close; } //Initialize the nlink service if(nl_srv_init() != 0) { - hddLog(VOS_TRACE_LEVEL_ERROR,"%S: nl_srv_init failed",__func__); + hddLog(VOS_TRACE_LEVEL_ERROR,"%s: nl_srv_init failed", __func__); goto err_ftm_register_wext_close; } @@ -1060,7 +1061,7 @@ int wlan_hdd_ftm_open(hdd_context_t *pHddCtx) //Initialize the PTT service if(ptt_sock_activate_svc(pHddCtx) != 0) { - hddLog(VOS_TRACE_LEVEL_ERROR,"%s: ptt_sock_activate_svc failed",__func__); + hddLog(VOS_TRACE_LEVEL_ERROR,"%s: ptt_sock_activate_svc failed", __func__); goto err_nl_srv_init; } #endif @@ -1085,7 +1086,7 @@ int wlan_hdd_ftm_open(hdd_context_t *pHddCtx) if(NULL == pHddCtx->ftm.tempNVTableBuffer) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s: NV Table Buffer Alloc Fail",__func__); + "%s: NV Table Buffer Alloc Fail", __func__); VOS_ASSERT(0); goto err_nl_srv_init; } @@ -1096,7 +1097,7 @@ int wlan_hdd_ftm_open(hdd_context_t *pHddCtx) if (vos_event_init(&pHddCtx->ftm.ftm_vos_event) != VOS_STATUS_SUCCESS) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s: Unable to init probeEvent",__func__); + "%s: Unable to init probeEvent", __func__); VOS_ASSERT(0); vos_mem_free(pHddCtx->ftm.tempNVTableBuffer); goto err_nl_srv_init; @@ -1137,6 +1138,12 @@ int wlan_hdd_ftm_close(hdd_context_t *pHddCtx) return VOS_STATUS_E_NOMEM; } + if(WLAN_FTM_STARTED == pHddCtx->ftm.ftm_state) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s: Ftm has been started. stopping ftm", __func__); + wlan_ftm_stop(pHddCtx); + } //Assert Deep sleep signal now to put Libra HW in lowest power state vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL ); diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_hostapd.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_hostapd.c index db76996f677..45c6f788b2a 100644 --- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_hostapd.c +++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_hostapd.c @@ -456,6 +456,7 @@ VOS_STATUS hdd_hostapd_SAPEventCB( tpSap_Event pSapEvent, v_PVOID_t usrDataForCa char *startBssEvent; hdd_context_t *pHddCtx; hdd_scaninfo_t *pScanInfo = NULL; + struct iw_michaelmicfailure msg; dev = (struct net_device *)usrDataForCallback; pHostapdAdapter = netdev_priv(dev); @@ -565,7 +566,6 @@ VOS_STATUS hdd_hostapd_SAPEventCB( tpSap_Event pSapEvent, v_PVOID_t usrDataForCa return VOS_STATUS_SUCCESS; case eSAP_STA_MIC_FAILURE_EVENT: { - struct iw_michaelmicfailure msg; memset(&msg, '\0', sizeof(msg)); msg.src_addr.sa_family = ARPHRD_ETHER; memcpy(msg.src_addr.sa_data, &pSapEvent->sapevt.sapStationMICFailureEvent.staMac, sizeof(v_MACADDR_t)); @@ -629,8 +629,8 @@ VOS_STATUS hdd_hostapd_SAPEventCB( tpSap_Event pSapEvent, v_PVOID_t usrDataForCa 0, (v_MACADDR_t *)wrqu.addr.sa_data, pSapEvent->sapevt.sapStationAssocReassocCompleteEvent.wmmEnabled); - } - + } + // Stop AP inactivity timer if (pHddApCtx->hdd_ap_inactivity_timer.state == VOS_TIMER_STATE_RUNNING) { @@ -643,7 +643,7 @@ VOS_STATUS hdd_hostapd_SAPEventCB( tpSap_Event pSapEvent, v_PVOID_t usrDataForCa { wake_unlock(&pHddCtx->sap_wake_lock); } - wake_lock_timeout(&pHddCtx->sap_wake_lock, HDD_SAP_WAKE_LOCK_DURATION); + wake_lock_timeout(&pHddCtx->sap_wake_lock, msecs_to_jiffies(HDD_SAP_WAKE_LOCK_DURATION)); #endif #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)) { @@ -844,6 +844,20 @@ stopbss : * we don't want interfaces to become re-enabled */ pHostapdState->bssState = BSS_STOP; + if (0 != (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->nAPAutoShutOff) + { + if (VOS_TIMER_STATE_RUNNING == pHddApCtx->hdd_ap_inactivity_timer.state) + { + vos_status = vos_timer_stop(&pHddApCtx->hdd_ap_inactivity_timer); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) + hddLog(LOGE, FL("Failed to stop AP inactivity timer")); + } + + vos_status = vos_timer_destroy(&pHddApCtx->hdd_ap_inactivity_timer); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) + hddLog(LOGE, FL("Failed to Destroy AP inactivity timer")); + } + /* Stop the pkts from n/w stack as we are going to free all of * the TX WMM queues for all STAID's */ hdd_hostapd_stop(dev); @@ -1213,6 +1227,24 @@ static iw_softap_set_max_tx_power(struct net_device *dev, return 0; } +int +static iw_display_data_path_snapshot(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + + /* Function intitiating dumping states of + * HDD(WMM Tx Queues) + * TL State (with Per Client infor) + * DXE Snapshot (Called at the end of TL Snapshot) + */ + hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev)); + hddLog(LOGE, "%s: called for SAP",__func__); + hdd_wmm_tx_snapshot(pHostapdAdapter); + WLANTL_TLDebugMessage(VOS_TRUE); + return 0; +} + int static iw_softap_set_tx_power(struct net_device *dev, struct iw_request_info *info, @@ -1442,7 +1474,7 @@ static iw_softap_commit(struct net_device *dev, //TODO: Need to handle mixed mode pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE pConfig->mcRSNEncryptType = mcRSNEncryptType; - hddLog( LOG1, FL("%s: CSR AuthType = %d, EncryptionType = %d mcEncryptionType = %d\n"), + hddLog( LOG1, FL("CSR AuthType = %d, EncryptionType = %d mcEncryptionType = %d\n"), RSNAuthType, RSNEncryptType, mcRSNEncryptType); } } @@ -1472,8 +1504,8 @@ static iw_softap_commit(struct net_device *dev, // ht_capab is not what the name conveys,this is used for protection bitmap pConfig->ht_capab = (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtection; - if (pCommitConfig->num_accept_mac > MAX_MAC_ADDRESS_ACCEPTED) - num_mac = pConfig->num_accept_mac = MAX_MAC_ADDRESS_ACCEPTED; + if (pCommitConfig->num_accept_mac > MAX_ACL_MAC_ADDRESS) + num_mac = pConfig->num_accept_mac = MAX_ACL_MAC_ADDRESS; else num_mac = pConfig->num_accept_mac = pCommitConfig->num_accept_mac; acl_entry = pCommitConfig->accept_mac; @@ -1482,8 +1514,8 @@ static iw_softap_commit(struct net_device *dev, vos_mem_copy(&pConfig->accept_mac[i], acl_entry->addr, sizeof(v_MACADDR_t)); acl_entry++; } - if (pCommitConfig->num_deny_mac > MAX_MAC_ADDRESS_DENIED) - num_mac = pConfig->num_deny_mac = MAX_MAC_ADDRESS_DENIED; + if (pCommitConfig->num_deny_mac > MAX_ACL_MAC_ADDRESS) + num_mac = pConfig->num_deny_mac = MAX_ACL_MAC_ADDRESS; else num_mac = pConfig->num_deny_mac = pCommitConfig->num_deny_mac; acl_entry = pCommitConfig->deny_mac; @@ -1614,7 +1646,6 @@ int iw_softap_get_channel_list(struct net_device *dev, v_U8_t bandEndChannel = RF_CHAN_165; v_U32_t temp_num_channels = 0; hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev)); - hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter); tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter); v_REGDOMAIN_t domainIdCurrentSoftap; tpChannelListInfo channel_list = (tpChannelListInfo) extra; @@ -1639,8 +1670,8 @@ int iw_softap_get_channel_list(struct net_device *dev, bandEndChannel = RF_CHAN_165; } - hddLog(LOG1, FL("\n nBandCapability = %d, bandStartChannel = %hu, " - "bandEndChannel = %hu \n"), pHddCtx->cfg_ini->nBandCapability, + hddLog(LOG1, FL("\n curBand = %d, bandStartChannel = %hu, " + "bandEndChannel = %hu "), curBand, bandStartChannel, bandEndChannel ); for( i = bandStartChannel; i <= bandEndChannel; i++ ) @@ -1952,7 +1983,7 @@ static int iw_set_ap_encodeext(struct net_device *dev, } VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - ("%s:EncryptionType:%d key_len:%d, :%d, KeyId:%d \n"),__func__, setKey.encType, setKey.keyLength, + ("%s:EncryptionType:%d key_len:%d, KeyId:%d"), __func__, setKey.encType, setKey.keyLength, setKey.keyId); for(i=0; i< ext->key_len; i++) VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, @@ -2593,46 +2624,71 @@ int iw_get_softap_linkspeed(struct net_device *dev, { hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev)); + hdd_context_t *pHddCtx; char *pLinkSpeed = (char*)extra; - v_U16_t link_speed; + v_U32_t link_speed; unsigned short staId; - int len = sizeof(v_U16_t)+1; + int len = sizeof(v_U32_t)+1; v_BYTE_t macAddress[VOS_MAC_ADDR_SIZE]; VOS_STATUS status; - int rc; + int rc, valid; + + pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter); + + valid = wlan_hdd_validate_context(pHddCtx); + + if (0 != valid) + { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("HDD context not valid")); + return valid; + } if ( hdd_string_to_hex ((char *)wrqu->data.pointer, wrqu->data.length, macAddress ) ) { - hddLog(VOS_TRACE_LEVEL_FATAL, "ERROR: Command not found"); + hddLog(VOS_TRACE_LEVEL_FATAL, FL("ERROR: Command not found")); return -EINVAL; } status = hdd_softap_GetStaId(pHostapdAdapter, (v_MACADDR_t *)macAddress, (void *)(&staId)); - if (!VOS_IS_STATUS_SUCCESS(status )) + if (!VOS_IS_STATUS_SUCCESS(status)) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, FL("ERROR: HDD Failed to find sta id!!")); + hddLog(VOS_TRACE_LEVEL_ERROR, FL("ERROR: HDD Failed to find sta id!!")); link_speed = 0; } else { status = wlan_hdd_get_classAstats_for_station(pHostapdAdapter , staId); + if (!VOS_IS_STATUS_SUCCESS(status )) { - hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unable to retrieve SME statistics", __func__); + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Unable to retrieve SME statistics")); return -EINVAL; } - link_speed =(int)pHostapdAdapter->hdd_stats.ClassA_stat.tx_rate/2; + + WLANTL_GetSTALinkCapacity(pHddCtx->pvosContext, + staId, &link_speed); + + link_speed = link_speed / 10; + + if (0 == link_speed) + { + /* The linkspeed returned by HAL is in units of 500kbps. + * converting it to mbps. + * This is required to support legacy firmware which does + * not return link capacity. + */ + link_speed =(int)pHostapdAdapter->hdd_stats.ClassA_stat.tx_rate/2; + } } wrqu->data.length = len; - rc = snprintf(pLinkSpeed, len, "%u", link_speed); + rc = snprintf(pLinkSpeed, len, "%lu", link_speed); + if ((rc < 0) || (rc >= len)) { // encoding or length error? - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: Unable to encode link speed, got [%s]", - __func__, pLinkSpeed); + hddLog(VOS_TRACE_LEVEL_ERROR,FL( "Unable to encode link speed")); return -EIO; } @@ -2754,7 +2810,7 @@ static const struct iw_priv_args hostapd_private_args[] = { IW_PRIV_TYPE_BYTE | QCSAP_MAX_WSC_IE, 0, "ap_stats" }, { QCSAP_IOCTL_PRIV_GET_SOFTAP_LINK_SPEED, IW_PRIV_TYPE_CHAR | 18, - IW_PRIV_TYPE_CHAR | 3, "getLinkSpeed" }, + IW_PRIV_TYPE_CHAR | 5, "getLinkSpeed" }, { QCSAP_IOCTL_PRIV_SET_THREE_INT_GET_NONE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, 0, "" }, @@ -2816,6 +2872,8 @@ static const struct iw_priv_args hostapd_private_args[] = { IW_PRIV_TYPE_INT| IW_PRIV_SIZE_FIXED | 1, 0, "setTxMaxPower" }, + { QCSAP_IOCTL_DATAPATH_SNAP_SHOT, + IW_PRIV_TYPE_NONE | IW_PRIV_TYPE_NONE, 0, "dataSnapshot" }, }; static const iw_handler hostapd_private[] = { @@ -2841,6 +2899,7 @@ static const iw_handler hostapd_private[] = { [QCSAP_IOCTL_PRIV_GET_SOFTAP_LINK_SPEED - SIOCIWFIRSTPRIV] = iw_get_softap_linkspeed, [QCSAP_IOCTL_SET_TX_POWER - SIOCIWFIRSTPRIV] = iw_softap_set_tx_power, [QCSAP_IOCTL_SET_MAX_TX_POWER - SIOCIWFIRSTPRIV] = iw_softap_set_max_tx_power, + [QCSAP_IOCTL_DATAPATH_SNAP_SHOT - SIOCIWFIRSTPRIV] = iw_display_data_path_snapshot, }; const struct iw_handler_def hostapd_handler_def = { .num_standard = sizeof(hostapd_handler) / sizeof(hostapd_handler[0]), @@ -2891,10 +2950,13 @@ VOS_STATUS hdd_init_ap_mode( hdd_adapter_t *pAdapter ) { hdd_hostapd_state_t * phostapdBuf; struct net_device *dev = pAdapter->dev; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); VOS_STATUS status; ENTER(); // Allocate the Wireless Extensions state structure phostapdBuf = WLAN_HDD_GET_HOSTAP_STATE_PTR( pAdapter ); + + sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode); // Zero the memory. This zeros the profile structure. memset(phostapdBuf, 0,sizeof(hdd_hostapd_state_t)); diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_main.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_main.c old mode 100644 new mode 100755 index 837c45eb88f..5a53219454d --- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_main.c +++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_main.c @@ -160,6 +160,20 @@ static int wlan_hdd_inited; */ #define WLAN_HDD_RESTART_RETRY_DELAY_MS 5000 /* 5 second */ #define WLAN_HDD_RESTART_RETRY_MAX_CNT 5 /* 5 retries */ + +/* + * Size of Driver command strings from upper layer + */ +#define SIZE_OF_SETROAMMODE 11 /* size of SETROAMMODE */ +#define SIZE_OF_GETROAMMODE 11 /* size of GETROAMMODE */ + +/* + * Driver miracast parameters 0-Disabled + * 1-Source, 2-Sink + */ +#define WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL 0 +#define WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL 2 + #ifdef WLAN_OPEN_SOURCE static struct wake_lock wlan_wake_lock; #endif @@ -188,6 +202,12 @@ extern int hdd_setBand_helper(struct net_device *dev, tANI_U8* ptr); void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand); static VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels); static VOS_STATUS hdd_parse_countryrev(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels); +static VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, + tANI_U8 *pChannel, tANI_U8 *pDwellTime, + tANI_U8 **pBuf, tANI_U8 *pBufLen); +static VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue, + tANI_U8 *pTargetApBssid, + tANI_U8 *pChannel); #endif static int hdd_netdev_notifier_call(struct notifier_block * nb, unsigned long state, @@ -328,7 +348,7 @@ static int curr_con_mode; the desired trace levels. \param - moduleId - module whose trace level is being configured - \param - bitmask - bitmask of log levels to be enabled + \param - bitmask - bitmask of log levels to be enabled. \return - void @@ -403,6 +423,134 @@ static void hdd_wdi_trace_enable(wpt_moduleid moduleId, v_U32_t bitmask) } } +/* + * FUNCTION: wlan_hdd_validate_context + * This function is used to check the HDD context + */ +int wlan_hdd_validate_context(hdd_context_t *pHddCtx) +{ + ENTER(); + + if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is Null", __func__); + return -ENODEV; + } + + if (pHddCtx->isLogpInProgress) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: LOGP in Progress. Ignore!!!", __func__); + return -EAGAIN; + } + + if (pHddCtx->isLoadUnloadInProgress) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Unloading/Loading in Progress. Ignore!!!", __func__); + return -EAGAIN; + } + return 0; +} + +void hdd_checkandupdate_phymode( hdd_adapter_t *pAdapter, char *country_code) +{ + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + hdd_config_t *cfg_param; + eCsrPhyMode phyMode; + + if (NULL == pHddCtx) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "HDD Context is null !!"); + return ; + } + + cfg_param = pHddCtx->cfg_ini; + + if (NULL == cfg_param) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "cfg_params not available !!"); + return ; + } + + phyMode = sme_GetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter)); + + if (NULL != strstr(cfg_param->listOfNon11acCountryCode, country_code)) + { + if ((eCSR_DOT11_MODE_AUTO == phyMode) || + (eCSR_DOT11_MODE_11ac == phyMode) || + (eCSR_DOT11_MODE_11ac_ONLY == phyMode)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "Setting phymode to 11n!!"); + sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_DOT11_MODE_11n); + } + } + else + { + /*New country Supports 11ac as well resetting value back from .ini*/ + sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), + hdd_cfg_xlate_to_csr_phy_mode(cfg_param->dot11Mode)); + return ; + } + + if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) && + ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode) || + (eCSR_CFG_DOT11_MODE_11AC == pHddStaCtx->conn_info.dot11Mode))) + { + VOS_STATUS vosStatus; + + // need to issue a disconnect to CSR. + INIT_COMPLETION(pAdapter->disconnect_comp_var); + vosStatus = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, + eCSR_DISCONNECT_REASON_UNSPECIFIED ); + + if (VOS_STATUS_SUCCESS == vosStatus) + wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var, + msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT)); + + } +} + +void hdd_checkandupdate_dfssetting( hdd_adapter_t *pAdapter, char *country_code) +{ + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + hdd_config_t *cfg_param; + + if (NULL == pHddCtx) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "HDD Context is null !!"); + return ; + } + + cfg_param = pHddCtx->cfg_ini; + + if (NULL == cfg_param) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "cfg_params not available !!"); + return ; + } + + if (NULL != strstr(cfg_param->listOfNonDfsCountryCode, country_code)) + { + /*New country doesn't support DFS */ + sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), 0); + } + else + { + /*New country Supports DFS as well resetting value back from .ini*/ + sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), cfg_param->enableDFSChnlScan); + } + +} + int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); @@ -456,6 +604,7 @@ int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) if ((SIOCDEVPRIVATE + 1) == cmd) { hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx; + struct wiphy *wiphy = pHddCtx->wiphy; VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: Received %s cmd from Wi-Fi GUI***", __func__, command); @@ -489,6 +638,9 @@ int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) char *country_code; country_code = command + 8; + + hdd_checkandupdate_dfssetting(pAdapter, country_code); + hdd_checkandupdate_phymode(pAdapter, country_code); ret = (int)sme_ChangeCountryCode(pHddCtx->hHal, NULL, country_code, pAdapter, pHddCtx->pvosContext); if( 0 != ret ) @@ -497,6 +649,14 @@ int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) "%s: SME Change Country code fail ret=%d\n",__func__, ret); } + /* If you get a 00 country code it means you are world roaming. + In case of world roaming, country code should be updated by + DRIVER COUNTRY */ + if (memcmp(pHddCtx->cfg_ini->crdaDefaultCountryCode, + CFG_CRDA_DEFAULT_COUNTRY_CODE_DEFAULT , 2) == 0) + { + regulatory_hint(wiphy, "00"); + } } #if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR) else if ( strncasecmp(command, "SETCOUNTRYREV", 13) == 0 ) @@ -535,6 +695,8 @@ int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) goto exit; } + hdd_checkandupdate_dfssetting(pAdapter, countryCode); + hdd_checkandupdate_phymode(pAdapter, countryCode); ret = (int)sme_ChangeCountryCode(pHddCtx->hHal, NULL, countryCode, pAdapter, pHddCtx->pvosContext); if (0 != ret) @@ -584,15 +746,29 @@ int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) else if (strncmp(command, "SETROAMTRIGGER", 14) == 0) { tANI_U8 *value = command; - int rssi = 0; + tANI_S8 rssi = 0; tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT; eHalStatus status = eHAL_STATUS_SUCCESS; /* Move pointer to ahead of SETROAMTRIGGER */ value = value + 15; - sscanf(value, "%d", &rssi); + /* Convert the value from ascii to integer */ + ret = kstrtos8(value, 10, &rssi); + if (ret < 0) + { + /* If the input value is greater than max value of datatype, then also + kstrtou8 fails */ + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: kstrtou8 failed Input value may be out of range[%d - %d]", + CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN, + CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX); + ret = -EINVAL; + goto exit; + } + lookUpThreshold = abs(rssi); + if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) || (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX)) { @@ -641,19 +817,20 @@ int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0) { tANI_U8 *value = command; + tANI_U8 roamScanPeriod = 0; tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT; + /* input refresh period is in terms of seconds */ /* Move pointer to ahead of SETROAMSCANPERIOD */ value = value + 18; /* Convert the value from ascii to integer */ - ret = kstrtou16(value, 10, &neighborEmptyScanRefreshPeriod); + ret = kstrtou8(value, 10, &roamScanPeriod); if (ret < 0) { /* If the input value is greater than max value of datatype, then also - kstrtou16 fails */ + kstrtou8 fails */ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s: kstrtou16 failed ", - "Input value may be out of range[%d - %d]", + "%s: kstrtou8 failed Input value may be out of range[%d - %d]", __func__, (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000), (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000)); @@ -661,22 +838,22 @@ int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) goto exit; } - neighborEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod * 1000; - if ((neighborEmptyScanRefreshPeriod < CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN) || - (neighborEmptyScanRefreshPeriod > CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX)) + if ((roamScanPeriod < (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000)) || + (roamScanPeriod > (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000))) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "Neighbor empty scan results refresh period value %d is out of range" - " (Min: %d Max: %d)", neighborEmptyScanRefreshPeriod/1000, + "Roam scan period value %d is out of range" + " (Min: %d Max: %d)", roamScanPeriod, (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000), (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000)); ret = -EINVAL; goto exit; } + neighborEmptyScanRefreshPeriod = roamScanPeriod * 1000; VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: Received Command to Set roam scan period" - " (Empty Scan refresh period) = %d", __func__, neighborEmptyScanRefreshPeriod/1000); + " (Empty Scan refresh period) = %d", __func__, roamScanPeriod); pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod; sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod); @@ -700,19 +877,21 @@ int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0) { tANI_U8 *value = command; + tANI_U8 roamScanRefreshPeriod = 0; tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT; + /* input refresh period is in terms of seconds */ /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD */ value = value + 25; + /* Convert the value from ascii to integer */ - ret = kstrtou16(value, 10, &neighborScanRefreshPeriod); + ret = kstrtou8(value, 10, &roamScanRefreshPeriod); if (ret < 0) { /* If the input value is greater than max value of datatype, then also - kstrtou16 fails */ + kstrtou8 fails */ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s: kstrtou16 failed ", - "Input value may be out of range[%d - %d]", + "%s: kstrtou8 failed Input value may be out of range[%d - %d]", __func__, (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000), (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000)); @@ -720,22 +899,22 @@ int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) goto exit; } - neighborScanRefreshPeriod = neighborScanRefreshPeriod * 1000; - if ((neighborScanRefreshPeriod < CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN) || - (neighborScanRefreshPeriod > CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX)) + if ((roamScanRefreshPeriod < (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000)) || + (roamScanRefreshPeriod > (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000))) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "Neighbor scan results refresh period value %d is out of range" - " (Min: %d Max: %d)", neighborScanRefreshPeriod/1000, + " (Min: %d Max: %d)", roamScanRefreshPeriod, (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000), (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000)); ret = -EINVAL; goto exit; } + neighborScanRefreshPeriod = roamScanRefreshPeriod * 1000; VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: Received Command to Set roam scan refresh period" - " (Scan refresh period) = %d", __func__, neighborScanRefreshPeriod/1000); + " (Scan refresh period) = %d", __func__, roamScanRefreshPeriod); pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod; sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod); @@ -756,6 +935,83 @@ int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) goto exit; } } +#ifdef FEATURE_WLAN_LFR + /* SETROAMMODE */ + else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0) + { + tANI_U8 *value = command; + tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT; + + /* Move pointer to ahead of SETROAMMODE */ + value = value + SIZE_OF_SETROAMMODE + 1; + + /* Convert the value from ascii to integer */ + ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode); + if (ret < 0) + { + /* If the input value is greater than max value of datatype, then also + kstrtou8 fails */ + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: kstrtou8 failed range [%d - %d]", __func__, + CFG_LFR_FEATURE_ENABLED_MIN, + CFG_LFR_FEATURE_ENABLED_MAX); + ret = -EINVAL; + goto exit; + } + if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) || + (roamMode > CFG_LFR_FEATURE_ENABLED_MAX)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Roam Mode value %d is out of range" + " (Min: %d Max: %d)", roamMode, + CFG_LFR_FEATURE_ENABLED_MIN, + CFG_LFR_FEATURE_ENABLED_MAX); + ret = -EINVAL; + goto exit; + } + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Received Command to Set Roam Mode = %d", __func__, roamMode); + /* + * Note that + * SETROAMMODE 0 is to enable LFR while + * SETROAMMODE 1 is to disable LFR, but + * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable. + * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled. + */ + if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode) + roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */ + else + roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */ + + pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode; + sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode); + } + /* GETROAMMODE */ + else if (strncmp(priv_data.buf, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0) + { + tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal)); + char extra[32]; + tANI_U8 len = 0; + + /* + * roamMode value shall be inverted because the sementics is different. + */ + if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode) + roamMode = CFG_LFR_FEATURE_ENABLED_MAX; + else + roamMode = CFG_LFR_FEATURE_ENABLED_MIN; + + len = snprintf(extra, sizeof(extra), "%s %d", command, roamMode); + if (copy_to_user(priv_data.buf, &extra, len + 1)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", __func__); + ret = -EFAULT; + goto exit; + } + } +#endif #endif #if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR) else if (strncmp(command, "SETROAMDELTA", 12) == 0) @@ -929,6 +1185,137 @@ int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) goto exit; } } + else if (strncmp(command, "SENDACTIONFRAME", 15) == 0) + { + tANI_U8 *value = command; + tANI_U8 channel = 0; + tANI_U8 dwellTime = 0; + tANI_U8 bufLen = 0; + tANI_U8 *buf = NULL; + tSirMacAddr targetApBssid; + eHalStatus status = eHAL_STATUS_SUCCESS; + struct ieee80211_channel chan; + tANI_U8 finalLen = 0; + tANI_U8 *finalBuf = NULL; + tANI_U8 temp = 0; + u64 cookie; + hdd_station_ctx_t *pHddStaCtx = NULL; + pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + + /* if not associated, no need to send action frame */ + if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__); + ret = -EINVAL; + goto exit; + } + + status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel, + &dwellTime, &buf, &bufLen); + if (eHAL_STATUS_SUCCESS != status) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to parse send action frame data", __func__); + ret = -EINVAL; + goto exit; + } + + /* if the target bssid is different from currently associated AP, + then no need to send action frame */ + if (VOS_TRUE != vos_mem_compare(targetApBssid, + pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr))) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__); + ret = -EINVAL; + goto exit; + } + + /* if the channel number is different from operating channel then + no need to send action frame */ + if (channel != pHddStaCtx->conn_info.operationChannel) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: channel(%d) is different from operating channel(%d)", + __func__, channel, pHddStaCtx->conn_info.operationChannel); + ret = -EINVAL; + goto exit; + } + chan.center_freq = sme_ChnToFreq(channel); + + finalLen = bufLen + 24; + finalBuf = vos_mem_malloc(finalLen); + if (NULL == finalBuf) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__); + ret = -ENOMEM; + goto exit; + } + vos_mem_zero(finalBuf, finalLen); + + /* Fill subtype */ + temp = SIR_MAC_MGMT_ACTION << 4; + vos_mem_copy(finalBuf + 0, &temp, sizeof(temp)); + + /* Fill type */ + temp = SIR_MAC_MGMT_FRAME; + vos_mem_copy(finalBuf + 2, &temp, sizeof(temp)); + + /* Fill destination address (bssid of the AP) */ + vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid)); + + /* Fill source address (STA mac address) */ + vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes)); + + /* Fill BSSID (AP mac address) */ + vos_mem_copy(finalBuf + 16, targetApBssid, sizeof(targetApBssid)); + + /* Fill received buffer from 24th address */ + vos_mem_copy(finalBuf + 24, buf, bufLen); + + wlan_hdd_action( NULL, dev, &chan, 0, NL80211_CHAN_HT20, + 1, dwellTime, finalBuf, finalLen, 1, + 1, &cookie ); + vos_mem_free(finalBuf); + } + else if (strncmp(command, "SETWESMODE", 10) == 0) + { + tANI_U8 *value = command; + tANI_BOOLEAN wesMode = CFG_ENABLE_WES_MODE_NAME_DEFAULT; + + /* Move pointer to ahead of SETWESMODE */ + value = value + 11; + /* Convert the value from ascii to integer */ + ret = kstrtou8(value, 10, &wesMode); + + if (ret < 0) + { + /* If the input value is greater than max value of datatype, then also + kstrtou8 fails */ + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: kstrtou8 failed range [%d - %d]", __func__, + CFG_ENABLE_WES_MODE_NAME_MIN, + CFG_ENABLE_WES_MODE_NAME_MAX); + ret = -EINVAL; + goto exit; + } + + if ((wesMode < CFG_ENABLE_WES_MODE_NAME_MIN) || + (wesMode > CFG_ENABLE_WES_MODE_NAME_MAX)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "WES Mode value %d is out of range" + " (Min: %d Max: %d)", wesMode, + CFG_ENABLE_WES_MODE_NAME_MIN, + CFG_ENABLE_WES_MODE_NAME_MAX); + ret = -EINVAL; + goto exit; + } + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Received Command to Set WES Mode rssi diff = %d", __func__, wesMode); + + pHddCtx->cfg_ini->isWESModeEnabled = wesMode; + sme_UpdateWESMode((tHalHandle)(pHddCtx->hHal), wesMode); + } else if (strncmp(command, "GETCCXMODE", 10) == 0) { tANI_BOOLEAN ccxMode = sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)); @@ -959,7 +1346,7 @@ int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) goto exit; } } - else if (strncmp(command, "GETFASTROAM", 10) == 0) + else if (strncmp(command, "GETFASTROAM", 11) == 0) { tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal)); char extra[32]; @@ -1210,6 +1597,179 @@ int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) } } + else if (strncmp(command, "SETSCANNPROBES", 14) == 0) + { + tANI_U8 *value = command; + tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT; + + /* Move pointer to ahead of SETSCANNPROBES */ + value = value + 15; + /* Convert the value from ascii to integer */ + ret = kstrtou8(value, 10, &nProbes); + if (ret < 0) + { + /* If the input value is greater than max value of datatype, then also + kstrtou8 fails */ + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: kstrtou8 failed range [%d - %d]", __func__, + CFG_ROAM_SCAN_N_PROBES_MIN, + CFG_ROAM_SCAN_N_PROBES_MAX); + ret = -EINVAL; + goto exit; + } + + if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) || + (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "NProbes value %d is out of range" + " (Min: %d Max: %d)", nProbes, + CFG_ROAM_SCAN_N_PROBES_MIN, + CFG_ROAM_SCAN_N_PROBES_MAX); + ret = -EINVAL; + goto exit; + } + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Received Command to Set nProbes = %d", __func__, nProbes); + + pHddCtx->cfg_ini->nProbes = nProbes; + sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes); + } + else if (strncmp(priv_data.buf, "GETSCANNPROBES", 14) == 0) + { + tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal)); + char extra[32]; + tANI_U8 len = 0; + + len = snprintf(extra, sizeof(extra), "%s %d", command, val); + if (copy_to_user(priv_data.buf, &extra, len + 1)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", __func__); + ret = -EFAULT; + goto exit; + } + } + else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0) + { + tANI_U8 *value = command; + tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT; + + /* Move pointer to ahead of SETSCANHOMEAWAYTIME */ + /* input value is in units of msec */ + value = value + 20; + /* Convert the value from ascii to integer */ + ret = kstrtou16(value, 10, &homeAwayTime); + if (ret < 0) + { + /* If the input value is greater than max value of datatype, then also + kstrtou8 fails */ + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: kstrtou8 failed range [%d - %d]", __func__, + CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN, + CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX); + ret = -EINVAL; + goto exit; + } + + /*Currently Home Away Time has a MIN value of 3. + * But, we sould allow the user to input Zero, + * since we are using the value of Zero to disable + * this and fallback to LFR1.5 behaviour.*/ + if (0 != homeAwayTime) + if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) || + (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "homeAwayTime value %d is out of range" + " (Min: %d Max: %d)", homeAwayTime, + CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN, + CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX); + ret = -EINVAL; + goto exit; + } + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime); + + pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime; + sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime); + } + else if (strncmp(priv_data.buf, "GETSCANHOMEAWAYTIME", 19) == 0) + { + tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal)); + char extra[32]; + tANI_U8 len = 0; + + len = snprintf(extra, sizeof(extra), "%s %d", command, val); + if (copy_to_user(priv_data.buf, &extra, len + 1)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", __func__); + ret = -EFAULT; + goto exit; + } + } + else if (strncmp(command, "REASSOC", 7) == 0) + { + tANI_U8 *value = command; + tANI_U8 channel = 0; + tSirMacAddr targetApBssid; + eHalStatus status = eHAL_STATUS_SUCCESS; + + hdd_station_ctx_t *pHddStaCtx = NULL; + tANI_BOOLEAN wesMode = eANI_BOOLEAN_FALSE; + pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + + wesMode = sme_GetWESMode((tHalHandle)(pHddCtx->hHal)); + + /* Reassoc command is allowed only if WES mode is enabled */ + if (!wesMode) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:WES Mode is not enabled(%d)",__func__, wesMode); + ret = -EINVAL; + goto exit; + } + + /* if not associated, no need to proceed with reassoc */ + if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__); + ret = -EINVAL; + goto exit; + } + + status = hdd_parse_reassoc_command_data(value, targetApBssid, &channel); + if (eHAL_STATUS_SUCCESS != status) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to parse reassoc command data", __func__); + ret = -EINVAL; + goto exit; + } + + /* if the target bssid is same as currently associated AP, + then no need to proceed with reassoc */ + if (VOS_TRUE == vos_mem_compare(targetApBssid, + pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr))) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Reassoc BSSID is same as currently associated AP bssid",__func__); + ret = -EINVAL; + goto exit; + } + + /* Check channel number is a valid channel number */ + if(VOS_STATUS_SUCCESS != + wlan_hdd_validate_operation_channel(pAdapter, channel)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Invalid Channel [%d] \n", __func__, channel); + return -EINVAL; + } + + /* Proceed with reassoc */ + } #endif #ifdef FEATURE_WLAN_LFR else if (strncmp(command, "SETFASTROAM", 11) == 0) @@ -1374,6 +1934,152 @@ int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode; } #endif + else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0) + { + tANI_U8 *value = command; + tANI_BOOLEAN roamScanControl = 0; + + /* Move pointer to ahead of SETROAMSCANCONTROL */ + value = value + 19; + /* Convert the value from ascii to integer */ + ret = kstrtou8(value, 10, &roamScanControl); + if (ret < 0) + { + /* If the input value is greater than max value of datatype, then also + kstrtou8 fails */ + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: kstrtou8 failed ", __func__); + ret = -EINVAL; + goto exit; + } + + if (0 != roamScanControl) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "roam scan control invalid value = %d", + roamScanControl); + ret = -EINVAL; + goto exit; + } + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl); + + sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl); + } + else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0) + { + tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal)); + char extra[32]; + tANI_U8 len = 0; + + len = snprintf(extra, sizeof(extra), "%s %d", command, roamScanControl); + if (copy_to_user(priv_data.buf, &extra, len + 1)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", __func__); + ret = -EFAULT; + goto exit; + } + } +#ifdef WLAN_FEATURE_PACKET_FILTERING + else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0) + { + tANI_U8 filterType = 0; + tANI_U8 *value = command; + + /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6 */ + value = value + 22; + + /* Convert the value from ascii to integer */ + ret = kstrtou8(value, 10, &filterType); + if (ret < 0) + { + /* If the input value is greater than max value of datatype, + * then also kstrtou8 fails + */ + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: kstrtou8 failed range ", __func__); + ret = -EINVAL; + goto exit; + } + + if (filterType != 0 && filterType != 1) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Accepted Values are 0 and 1 ", __func__); + ret = -EINVAL; + goto exit; + } + wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType, + pAdapter->sessionId); + } +#endif + else if (strncmp(command, "GETDWELLTIME", 12) == 0) + { + hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini; + char extra[32]; + tANI_U8 len = 0; + + len = snprintf(extra, sizeof(extra), "GETDWELLTIME %u\n", + (int)pCfg->nActiveMaxChnTime); + if (copy_to_user(priv_data.buf, &extra, len + 1)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", __func__); + ret = -EFAULT; + goto exit; + } + ret = len; + } + else if (strncmp(command, "SETDWELLTIME", 12) == 0) + { + tANI_U8 *value = command; + hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini; + int val = 0, temp; + + value = value + 13; + temp = kstrtou32(value, 10, &val); + if ( temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN || + val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX ) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: argument passed for SETDWELLTIME is incorrect", __func__); + ret = -EFAULT; + goto exit; + } + pCfg->nActiveMaxChnTime = val; + } + else if ( strncasecmp(command, "MIRACAST", 8) == 0 ) + { + tANI_U8 filterType = 0; + tANI_U8 *value; + value = command + 9; + + /* Convert the value from ascii to integer */ + ret = kstrtou8(value, 10, &filterType); + if (ret < 0) + { + /* If the input value is greater than max value of datatype, 1993 + * then also kstrtou8 fails 1994 + */ + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: kstrtou8 failed range ", __func__); + ret = -EINVAL; + goto exit; + } + if ((filterType < WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL ) || + (filterType > WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Accepted Values are 0 to 2. 0-Disabled, 1-Source," + " 2-Sink ", __func__); + ret = -EINVAL; + goto exit; + } + //Filtertype value should be either 0-Disabled, 1-Source, 2-sink + pHddCtx->drvr_miracast = filterType; + hdd_tx_rx_pkt_cnt_stat_timer_handler(pHddCtx); + } else { hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s", __func__, command); @@ -1388,30 +2094,181 @@ int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) return ret; } -#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR) -void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand) -{ - eCsrBand band = -1; - sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band); - switch (band) +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR) +void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand) +{ + eCsrBand band = -1; + sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band); + switch (band) + { + case eCSR_BAND_ALL: + *pBand = WLAN_HDD_UI_BAND_AUTO; + break; + + case eCSR_BAND_24: + *pBand = WLAN_HDD_UI_BAND_2_4_GHZ; + break; + + case eCSR_BAND_5G: + *pBand = WLAN_HDD_UI_BAND_5_GHZ; + break; + + default: + hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band); + *pBand = -1; + break; + } +} + +/**--------------------------------------------------------------------------- + + \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data + + This function parses the send action frame data passed in the format + SENDACTIONFRAME + + \param - pValue Pointer to input country code revision + \param - pTargetApBssid Pointer to target Ap bssid + \param - pChannel Pointer to the Target AP channel + \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame + \param - pBuf Pointer to data + \param - pBufLen Pointer to data length + + \return - 0 for success non-zero for failure + + --------------------------------------------------------------------------*/ +VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel, + tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen) +{ + tANI_U8 *inPtr = pValue; + tANI_U8 *dataEnd; + int tempInt; + int j = 0; + int i = 0; + int v = 0; + tANI_U8 tempBuf[32]; + tANI_U8 tempByte = 0; + + inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE); + /*no argument after the command*/ + if (NULL == inPtr) + { + return -EINVAL; + } + + /*no space after the command*/ + else if (SPACE_ASCII_VALUE != *inPtr) + { + return -EINVAL; + } + + /*removing empty spaces*/ + while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++; + + /*no argument followed by spaces*/ + if ('\0' == *inPtr) + { + return -EINVAL; + } + + /*getting the first argument ie the target AP bssid */ + if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':') + { + return -EINVAL; + } + j = sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1], + (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3], + (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]); + + /* point to the next argument */ + inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE); + /*no argument after the command*/ + if (NULL == inPtr) return -EINVAL; + + /*removing empty spaces*/ + while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++; + + /*no argument followed by spaces*/ + if ('\0' == *inPtr) + { + return -EINVAL; + } + + /*getting the next argument ie the channel number */ + j = sscanf(inPtr, "%s ", tempBuf); + v = kstrtos32(tempBuf, 10, &tempInt); + if ( v < 0) return -EINVAL; + + *pChannel = tempInt; + + /* point to the next argument */ + inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE); + /*no argument after the command*/ + if (NULL == inPtr) return -EINVAL; + /*removing empty spaces*/ + while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++; + + /*no argument followed by spaces*/ + if ('\0' == *inPtr) { - case eCSR_BAND_ALL: - *pBand = WLAN_HDD_UI_BAND_AUTO; - break; + return -EINVAL; + } - case eCSR_BAND_24: - *pBand = WLAN_HDD_UI_BAND_2_4_GHZ; - break; + /*getting the next argument ie the dwell time */ + j = sscanf(inPtr, "%s ", tempBuf); + v = kstrtos32(tempBuf, 10, &tempInt); + if ( v < 0) return -EINVAL; - case eCSR_BAND_5G: - *pBand = WLAN_HDD_UI_BAND_5_GHZ; - break; + *pDwellTime = tempInt; - default: - hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band); - *pBand = -1; - break; + /* point to the next argument */ + inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE); + /*no argument after the command*/ + if (NULL == inPtr) return -EINVAL; + /*removing empty spaces*/ + while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++; + + /*no argument followed by spaces*/ + if ('\0' == *inPtr) + { + return -EINVAL; + } + + /* find the length of data */ + dataEnd = inPtr; + while(('\0' != *dataEnd) ) + { + dataEnd++; + ++(*pBufLen); + } + if ( *pBufLen <= 0) return -EINVAL; + + /* Allocate the number of bytes based on the number of input characters + whether it is even or odd. + if the number of input characters are even, then we need N/2 byte. + if the number of input characters are odd, then we need do (N+1)/2 to + compensate rounding off. + For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough. + If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */ + *pBuf = vos_mem_malloc((*pBufLen + 1)/2); + if (NULL == *pBuf) + { + hddLog(VOS_TRACE_LEVEL_FATAL, + "%s: vos_mem_alloc failed ", __func__); + return -EINVAL; + } + + /* the buffer received from the upper layer is character buffer, + we need to prepare the buffer taking 2 characters in to a U8 hex decimal number + for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st + and f0 in 3rd location */ + for (i = 0, j = 0; j < *pBufLen; j += 2) + { + tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1])); + (*pBuf)[i++] = tempByte; } + *pBufLen = i; + return VOS_STATUS_SUCCESS; } /**--------------------------------------------------------------------------- @@ -1500,11 +2357,6 @@ VOS_STATUS hdd_parse_countryrev(tANI_U8 *pValue, tANI_U8 *pCountryCode, tANI_U8 This function parses the channel list passed in the format SETROAMSCANCHANNELSChannel 1Channel 2Channel N - if the Number of channels (N) does not match with the actual number of channels passed - then take the minimum of N and count of (Ch1, Ch2, ...Ch M) - For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken. - If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48. - This function does not take care of removing duplicate channels from the list \param - pValue Pointer to input channel list \param - ChannelList Pointer to local output array to record channel list @@ -1535,7 +2387,7 @@ VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 } /*removing empty spaces*/ - while ((SPACE_ASCII_VALUE == *inPtr)&& ('\0' != *inPtr) ) inPtr++; + while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++; /*no argument followed by spaces*/ if ('\0' == *inPtr) @@ -1546,7 +2398,12 @@ VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 /*getting the first argument ie the number of channels*/ sscanf(inPtr, "%32s ", buf); v = kstrtos32(buf, 10, &tempInt); - if ((v < 0) || (tempInt <= 0)) return -EINVAL; + if ((v < 0) || + (tempInt <= 0) || + (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN)) + { + return -EINVAL; + } *pNumChannels = tempInt; @@ -1572,7 +2429,7 @@ VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 } /*removing empty space*/ - while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++; + while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++; /*no channel list after the number of channels argument and spaces*/ if ( '\0' == *inPtr ) @@ -1588,9 +2445,14 @@ VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 } } - sscanf(inPtr, "%s ", buf); + sscanf(inPtr, "%32s ", buf); v = kstrtos32(buf, 10, &tempInt); - if ((v < 0) || (tempInt <= 0)) return -EINVAL; + if ((v < 0) || + (tempInt <= 0) || + (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX)) + { + return -EINVAL; + } pChannelList[j] = tempInt; VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, @@ -1601,7 +2463,84 @@ VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 return VOS_STATUS_SUCCESS; } + +/**--------------------------------------------------------------------------- + + \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data + + This function parses the reasoc command data passed in the format + REASSOC + + \param - pValue Pointer to input country code revision + \param - pTargetApBssid Pointer to target Ap bssid + \param - pChannel Pointer to the Target AP channel + + \return - 0 for success non-zero for failure + + --------------------------------------------------------------------------*/ +VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel) +{ + tANI_U8 *inPtr = pValue; + int tempInt; + int v = 0; + tANI_U8 tempBuf[32]; + + inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE); + /*no argument after the command*/ + if (NULL == inPtr) + { + return -EINVAL; + } + + /*no space after the command*/ + else if (SPACE_ASCII_VALUE != *inPtr) + { + return -EINVAL; + } + + /*removing empty spaces*/ + while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++; + + /*no argument followed by spaces*/ + if ('\0' == *inPtr) + { + return -EINVAL; + } + + /*getting the first argument ie the target AP bssid */ + if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':') + { + return -EINVAL; + } + sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1], + (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3], + (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]); + + /* point to the next argument */ + inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE); + /*no argument after the command*/ + if (NULL == inPtr) return -EINVAL; + + /*removing empty spaces*/ + while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++; + + /*no argument followed by spaces*/ + if ('\0' == *inPtr) + { + return -EINVAL; + } + + /*getting the next argument ie the channel number */ + sscanf(inPtr, "%s ", tempBuf); + v = kstrtos32(tempBuf, 10, &tempInt); + if ( v < 0) return -EINVAL; + + *pChannel = tempInt; + return VOS_STATUS_SUCCESS; +} + #endif + /**--------------------------------------------------------------------------- \brief hdd_open() - HDD Open function @@ -1639,18 +2578,18 @@ int hdd_open (struct net_device *dev) status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode ); while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) ) { - if( pAdapterNode->pAdapter->event_flags & DEVICE_IFACE_OPENED) - { - hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of " - "standby", __func__, pAdapter->device_mode); - in_standby = FALSE; - break; - } - else - { - status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); - pAdapterNode = pNext; - } + if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags)) + { + hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby", + __func__); + in_standby = FALSE; + break; + } + else + { + status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); + pAdapterNode = pNext; + } } if (TRUE == in_standby) @@ -1663,7 +2602,7 @@ int hdd_open (struct net_device *dev) } } - pAdapter->event_flags |= DEVICE_IFACE_OPENED; + set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags); if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, @@ -1726,7 +2665,7 @@ int hdd_stop (struct net_device *dev) return -ENODEV; } - pAdapter->event_flags &= ~(DEVICE_IFACE_OPENED); + clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags); hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__); netif_tx_disable(pAdapter->dev); netif_carrier_off(pAdapter->dev); @@ -1749,18 +2688,18 @@ int hdd_stop (struct net_device *dev) status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode ); while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) ) { - if ( pAdapterNode->pAdapter->event_flags & DEVICE_IFACE_OPENED) - { - hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot " - "put device to sleep", __func__, pAdapter->device_mode); - enter_standby = FALSE; - break; - } - else - { - status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); - pAdapterNode = pNext; - } + if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags)) + { + hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot " + "put device to sleep", __func__); + enter_standby = FALSE; + break; + } + else + { + status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); + pAdapterNode = pNext; + } } if (TRUE == enter_standby) @@ -2239,6 +3178,7 @@ static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMac #endif init_completion(&pHddCtx->mc_sus_event_var); init_completion(&pHddCtx->tx_sus_event_var); + init_completion(&pHddCtx->rx_sus_event_var); init_completion(&pAdapter->ula_complete); pAdapter->isLinkUpSvcNeeded = FALSE; @@ -2299,19 +3239,40 @@ VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_he return VOS_STATUS_SUCCESS; } -eHalStatus hdd_smeCloseSessionCallback(void *pContext) +static eHalStatus hdd_smeCloseSessionCallback(void *pContext) { - if(pContext != NULL) + hdd_adapter_t *pAdapter = pContext; + + if (NULL == pAdapter) { - clear_bit(SME_SESSION_OPENED, &((hdd_adapter_t*)pContext)->event_flags); + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__); + return eHAL_STATUS_INVALID_PARAMETER; + } - /* need to make sure all of our scheduled work has completed. - * This callback is called from MC thread context, so it is safe to - * to call below flush workqueue API from here. - */ - flush_scheduled_work(); - complete(&((hdd_adapter_t*)pContext)->session_close_comp_var); + if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic) + { + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__); + return eHAL_STATUS_NOT_INITIALIZED; + } + + clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags); + + /* need to make sure all of our scheduled work has completed. + * This callback is called from MC thread context, so it is safe to + * to call below flush workqueue API from here. + */ + flush_scheduled_work(); + + /* We can be blocked while waiting for scheduled work to be + * flushed, and the adapter structure can potentially be freed, in + * which case the magic will have been reset. So make sure the + * magic is still good, and hence the adapter structure is still + * valid, before signaling completion */ + if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic) + { + complete(&pAdapter->session_close_comp_var); } + return eHAL_STATUS_SUCCESS; } @@ -2325,6 +3286,7 @@ VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter ) int rc = 0; INIT_COMPLETION(pAdapter->session_open_comp_var); + sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode); //Open a SME session for future operation halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter, (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId ); @@ -2417,17 +3379,17 @@ VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter ) error_init_txrx: hdd_UnregisterWext(pWlanDev); error_register_wext: - if(test_bit(SME_SESSION_OPENED, &pAdapter->event_flags)) + if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags)) { INIT_COMPLETION(pAdapter->session_close_comp_var); - if( eHAL_STATUS_SUCCESS == sme_CloseSession( pHddCtx->hHal, + if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId, - hdd_smeCloseSessionCallback, pAdapter ) ) + hdd_smeCloseSessionCallback, pAdapter)) { //Block on a completion variable. Can't wait forever though. - wait_for_completion_interruptible_timeout( + wait_for_completion_timeout( &pAdapter->session_close_comp_var, - msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE)); + msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE)); } } error_sme_open: @@ -2544,32 +3506,70 @@ void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_ void hdd_set_pwrparams(hdd_context_t *pHddCtx) { - tSirSetPowerParamsReq powerRequest = { 0 }; + VOS_STATUS status; + hdd_adapter_t *pAdapter = NULL; + hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; - powerRequest.uIgnoreDTIM = 1; + status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode ); - if (pHddCtx->cfg_ini->enableModulatedDTIM) - { - powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM; - powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value; - } - else + /*loop through all adapters.*/ + while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status ) { - powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM; - } + pAdapter = pAdapterNode->pAdapter; + if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode) + && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) ) - /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM - *specified during Enter/Exit BMPS when LCD off*/ - ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM, - NULL, eANI_BOOLEAN_FALSE); - ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval, - NULL, eANI_BOOLEAN_FALSE); + { // we skip this registration for modes other than STA and P2P client modes. + status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); + pAdapterNode = pNext; + continue; + } - /* switch to the DTIM specified in cfg.ini */ - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - "Switch to DTIM%d", powerRequest.uListenInterval); - sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE); + //Apply Dynamic DTIM For P2P + //Only if ignoreDynamicDtimInP2pMode is not set in ini + if ((pHddCtx->cfg_ini->enableDynamicDTIM || + pHddCtx->cfg_ini->enableModulatedDTIM) && + ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) || + ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) && + !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) && + (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) && + (eConnectionState_Associated == + (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) && + (pHddCtx->cfg_ini->fIsBmpsEnabled)) + { + tSirSetPowerParamsReq powerRequest = { 0 }; + powerRequest.uIgnoreDTIM = 1; + powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM; + + if (pHddCtx->cfg_ini->enableModulatedDTIM) + { + powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM; + powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value; + } + else + { + powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM; + } + + /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM + * specified during Enter/Exit BMPS when LCD off*/ + ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM, + NULL, eANI_BOOLEAN_FALSE); + ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval, + NULL, eANI_BOOLEAN_FALSE); + + /* switch to the DTIM specified in cfg.ini */ + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "Switch to DTIM %d", powerRequest.uListenInterval); + sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE); + break; + + } + + status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); + pAdapterNode = pNext; + } } void hdd_reset_pwrparams(hdd_context_t *pHddCtx) @@ -2579,6 +3579,7 @@ void hdd_reset_pwrparams(hdd_context_t *pHddCtx) powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value; powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value; + powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM; /* Update ignoreDTIM and ListedInterval in CFG with default values */ ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM, @@ -2916,7 +3917,11 @@ hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type, //If bmps disabled enable it if(VOS_STATUS_SUCCESS == exitbmpsStatus) { - hdd_enable_bmps_imps(pHddCtx); + if (pHddCtx->hdd_wlan_suspended) + { + hdd_set_pwrparams(pHddCtx); + } + hdd_enable_bmps_imps(pHddCtx); } return NULL; } @@ -2953,7 +3958,11 @@ VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) || (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1))) { - hdd_enable_bmps_imps(pHddCtx); + if (pHddCtx->hdd_wlan_suspended) + { + hdd_set_pwrparams(pHddCtx); + } + hdd_enable_bmps_imps(pHddCtx); } return VOS_STATUS_SUCCESS; @@ -3060,7 +4069,7 @@ VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter ) hdd_smeCloseSessionCallback, pAdapter)) { //Block on a completion variable. Can't wait forever though. - wait_for_completion_interruptible_timeout( + wait_for_completion_timeout( &pAdapter->session_close_comp_var, msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE)); } @@ -3175,12 +4184,7 @@ VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx ) netif_tx_disable(pAdapter->dev); netif_carrier_off(pAdapter->dev); - //Record whether STA is associated - pAdapter->sessionCtx.station.bSendDisconnect = - hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) ? - VOS_TRUE : VOS_FALSE; pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE; - hdd_deinit_tx_rx(pAdapter); hdd_wmm_adapter_close(pAdapter); @@ -3199,6 +4203,7 @@ VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx ) VOS_STATUS status; hdd_adapter_t *pAdapter; v_MACADDR_t bcastMac = VOS_MAC_ADDR_BROADCAST_INITIALIZER; + eConnectionState connState; ENTER(); @@ -3213,9 +4218,12 @@ VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx ) case WLAN_HDD_INFRA_STATION: case WLAN_HDD_P2P_CLIENT: case WLAN_HDD_P2P_DEVICE: + + connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState; + hdd_init_station_mode(pAdapter); /* Open the gates for HDD to receive Wext commands */ - pAdapter->isLinkUpSvcNeeded = FALSE; + pAdapter->isLinkUpSvcNeeded = FALSE; pHddCtx->scan_info.mScanPending = FALSE; pHddCtx->scan_info.waitScanResult = FALSE; @@ -3223,20 +4231,31 @@ VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx ) hdd_wlan_initial_scan(pAdapter); //Indicate disconnect event to supplicant if associated previously - if(pAdapter->sessionCtx.station.bSendDisconnect) + if (eConnectionState_Associated == connState || + eConnectionState_IbssConnected == connState ) { union iwreq_data wrqu; memset(&wrqu, '\0', sizeof(wrqu)); wrqu.ap_addr.sa_family = ARPHRD_ETHER; memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN); wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL); - pAdapter->sessionCtx.station.bSendDisconnect = VOS_FALSE; pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE; /* indicate disconnected event to nl80211 */ cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED, NULL, 0, GFP_KERNEL); } + else if (eConnectionState_Connecting == connState) + { + /* + * Indicate connect failure to supplicant if we were in the + * process of connecting + */ + cfg80211_connect_result(pAdapter->dev, NULL, + NULL, 0, NULL, 0, + WLAN_STATUS_ASSOC_DENIED_UNSPEC, + GFP_KERNEL); + } break; case WLAN_HDD_SOFTAP: @@ -3817,7 +4836,7 @@ static void hdd_full_power_callback(void *callbackContext, eHalStatus status) struct fullPowerContext *pContext = callbackContext; hddLog(VOS_TRACE_LEVEL_INFO, - "%s: context = %p, status = %d", pContext, status); + "%s: context = %p, status = %d", __func__, pContext, status); if (NULL == callbackContext) { @@ -3944,6 +4963,21 @@ void hdd_wlan_exit(hdd_context_t *pHddCtx) // all scans will be cancelled. hdd_abort_mac_scan( pHddCtx ); + //Stop the traffic monitor timer + if ( VOS_TIMER_STATE_RUNNING == + vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr)) + { + vos_timer_stop(&pHddCtx->tx_rx_trafficTmr); + } + + // Destroy the traffic monitor timer + if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy( + &pHddCtx->tx_rx_trafficTmr))) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Cannot deallocate Traffic monitor timer", __func__); + } + //Disable IMPS/BMPS as we do not want the device to enter any power //save mode during shutdown sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE); @@ -4024,10 +5058,6 @@ void hdd_wlan_exit(hdd_context_t *pHddCtx) vos_chipVoteOffXOBuffer(NULL, NULL, NULL); - //Clean up HDD Nlink Service - send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0); - nl_srv_exit(); - //This requires pMac access, Call this before vos_close(). hdd_unregister_mcast_bcast_filter(pHddCtx); @@ -4057,6 +5087,10 @@ void hdd_wlan_exit(hdd_context_t *pHddCtx) if(pHddCtx->cfg_ini->fIsLogpEnabled) vos_watchdog_close(pVosContext); + //Clean up HDD Nlink Service + send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0); + nl_srv_exit(); + /* Cancel the vote for XO Core ON. * This is done here to ensure there is no race condition since MC, TX and WD threads have * exited at this point @@ -4184,6 +5218,7 @@ VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx) { eHalStatus halStatus; v_U32_t listenInterval; + tANI_U32 ignoreDtim; // Send ready indication to the HDD. This will kick off the MAC @@ -4191,17 +5226,20 @@ VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx) halStatus = sme_HDDReadyInd( pHddCtx->hHal ); if ( !HAL_STATUS_SUCCESS( halStatus ) ) { - hddLog(VOS_TRACE_LEVEL_ERROR,"%S: sme_HDDReadyInd() failed with status " + hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status " "code %08d [x%08x]",__func__, halStatus, halStatus ); return VOS_STATUS_E_FAILURE; } - // Set default LI into HDD context, + // Set default LI and ignoreDtim into HDD context, // otherwise under some race condition, HDD will set 0 LI value into RIVA, // And RIVA will crash wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval); pHddCtx->hdd_actual_LI_value = listenInterval; - + wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim); + pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim; + + return VOS_STATUS_SUCCESS; } @@ -4227,7 +5265,7 @@ void hdd_allow_suspend(void) void hdd_allow_suspend_timeout(v_U32_t timeout) { #ifdef WLAN_OPEN_SOURCE - wake_lock_timeout(&wlan_wake_lock, timeout); + wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout)); #else /* Do nothing as there is no API in wcnss for timeout*/ #endif @@ -4364,6 +5402,34 @@ void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx) } +/**--------------------------------------------------------------------------- + + \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz + + \param - pHddCtx - Pointer to the hdd context + + \return - true if hardware supports 5GHz + + --------------------------------------------------------------------------*/ +static boolean hdd_is_5g_supported(hdd_context_t * pHddCtx) +{ + /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1); + * then hardware support 5Ghz. + */ + if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode()) + { + hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware supports 5Ghz", __func__); + return true; + } + else + { + hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware doesn't supports 5Ghz", + __func__); + return false; + } +} + + /**--------------------------------------------------------------------------- \brief hdd_wlan_startup() - HDD init function @@ -4437,6 +5503,8 @@ int hdd_wlan_startup(struct device *dev ) init_completion(&pHddCtx->scan_info.scan_req_completion_event); init_completion(&pHddCtx->scan_info.abortscan_event_var); + spin_lock_init(&pHddCtx->schedScan_lock); + hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS ); // Load all config first as TL config is needed during vos_open @@ -4458,6 +5526,24 @@ int hdd_wlan_startup(struct device *dev ) goto err_config; } + if (false == hdd_is_5g_supported(pHddCtx)) + { + //5Ghz is not supported. + if (1 != pHddCtx->cfg_ini->nBandCapability) + { + hddLog(VOS_TRACE_LEVEL_INFO, + "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__); + pHddCtx->cfg_ini->nBandCapability = 1; + } + } + + /* INI has been read, initialise the configuredMcastBcastFilter with + * INI value as this will serve as the default value + */ + pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting; + hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d", + pHddCtx->cfg_ini->mcastBcastFilterSetting); + /* * cfg80211: Initialization ... */ @@ -4777,6 +5863,15 @@ int hdd_wlan_startup(struct device *dev ) #endif //WLAN_BTAMP_FEATURE +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE)) + { + hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__); + pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0; + sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal), + pHddCtx->cfg_ini->isRoamOffloadScanEnabled); + } +#endif #ifdef FEATURE_WLAN_SCAN_PNO /*SME must send channel update configuration to RIVA*/ sme_UpdateChannelConfig(pHddCtx->hHal); @@ -4822,7 +5917,7 @@ int hdd_wlan_startup(struct device *dev ) //Initialize the nlink service if(nl_srv_init() != 0) { - hddLog(VOS_TRACE_LEVEL_FATAL,"%S: nl_srv_init failed",__func__); + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__); goto err_reg_netdev; } @@ -4877,6 +5972,14 @@ int hdd_wlan_startup(struct device *dev ) // Initialize the restart logic wlan_hdd_restart_init(pHddCtx); + //Register the traffic monitor timer now + if ( pHddCtx->cfg_ini->dynSplitscan) + { + vos_timer_init(&pHddCtx->tx_rx_trafficTmr, + VOS_TIMER_TYPE_SW, + hdd_tx_rx_pkt_cnt_stat_timer_handler, + (void *)pHddCtx); + } goto success; err_nl_srv: @@ -4968,6 +6071,13 @@ static int hdd_driver_init( void) v_CONTEXT_t pVosContext = NULL; struct device *dev = NULL; int ret_status = 0; +#ifdef HAVE_WCNSS_CAL_DOWNLOAD + int max_retries = 0; +#endif + +#ifdef WCONN_TRACE_KMSG_LOG_BUFF + vos_wconn_trace_init(); +#endif ENTER(); @@ -4984,6 +6094,9 @@ static int hdd_driver_init( void) { hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. " "exiting", __func__); +#ifdef WLAN_OPEN_SOURCE + wake_lock_destroy(&wlan_wake_lock); +#endif return -EIO; } @@ -4994,6 +6107,21 @@ static int hdd_driver_init( void) #endif // ANI_BUS_TYPE_PCI #ifdef ANI_BUS_TYPE_PLATFORM + +#ifdef HAVE_WCNSS_CAL_DOWNLOAD + /* wait until WCNSS driver downloads NV */ + while (!wcnss_device_ready() && 5 >= ++max_retries) { + msleep(1000); + } + if (max_retries >= 5) { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__); +#ifdef WLAN_OPEN_SOURCE + wake_lock_destroy(&wlan_wake_lock); +#endif + return -ENODEV; + } +#endif + dev = wcnss_wlan_get_device(); #endif // ANI_BUS_TYPE_PLATFORM @@ -5079,7 +6207,6 @@ static int hdd_driver_init( void) send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0); pr_info("%s: driver loaded\n", WLAN_MODULE_NAME); - } EXIT(); @@ -5128,6 +6255,7 @@ static void hdd_driver_exit(void) { hdd_context_t *pHddCtx = NULL; v_CONTEXT_t pVosContext = NULL; + int retry = 0; pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR); @@ -5149,11 +6277,18 @@ static void hdd_driver_exit(void) } else { - /* module exit should never proceed if SSR is not completed */ - while(isWDresetInProgress()){ - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:SSR in Progress; block rmmod for 1 second!!!",__func__); + while(isWDresetInProgress()) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s:SSR in Progress; block rmmod for 1 second!!!", __func__); msleep(1000); - } + + if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s:SSR never completed, fatal error", __func__); + VOS_BUG(0); + } + } + pHddCtx->isLoadUnloadInProgress = TRUE; vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE); @@ -5171,6 +6306,10 @@ static void hdd_driver_exit(void) vos_mem_exit(); #endif +#ifdef WCONN_TRACE_KMSG_LOG_BUFF + vos_wconn_trace_exit(); +#endif + done: #ifdef WLAN_OPEN_SOURCE wake_lock_destroy(&wlan_wake_lock); @@ -5330,7 +6469,7 @@ VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddres ENTER(); - hddLog( LOGE, "hdd_softap_sta_deauth:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext); + hddLog( LOGE, "hdd_softap_sta_deauth:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext); //Ignore request to deauth bcmc station if( pDestMacAddress[0] & 0x1 ) @@ -5362,7 +6501,7 @@ void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress) ENTER(); - hddLog( LOGE, "hdd_softap_sta_disassoc:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext); + hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext); //Ignore request to disassoc bcmc station if( pDestMacAddress[0] & 0x1 ) @@ -5377,7 +6516,7 @@ void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t e ENTER(); - hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext); + hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext); WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable); } @@ -5699,6 +6838,13 @@ VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx) return status; } +/* + * API to find if there is any STA or P2P-Client is connected + */ +VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx) +{ + return sme_isSta_p2p_clientConnected(pHddCtx->hHal); +} //Register the module init/exit functions module_init(hdd_module_init); diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_p2p.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_p2p.c index 72cc77dae32..4a902851539 100644 --- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_p2p.c +++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_p2p.c @@ -57,6 +57,7 @@ #include "sme_Api.h" #include "wlan_hdd_p2p.h" #include "sapApi.h" +#include "wlan_hdd_main.h" #include #include @@ -452,15 +453,18 @@ int wlan_hdd_cfg80211_cancel_remain_on_channel( struct wiphy *wiphy, #endif hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter ); - int status = 0; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter ); + int status; hddLog( LOG1, "Cancel remain on channel req"); - if (((hdd_context_t*)pAdapter->pHddCtx)->isLogpInProgress) + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EAGAIN; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return status; } /* FIXME cancel currently running remain on chan. * Need to check cookie and cancel accordingly @@ -473,8 +477,8 @@ int wlan_hdd_cfg80211_cancel_remain_on_channel( struct wiphy *wiphy, __func__); return -EINVAL; } - - /* wait until remain on channel ready event received + + /* wait until remain on channel ready event received * for already issued remain on channel request */ status = wait_for_completion_interruptible_timeout(&pAdapter->rem_on_chan_ready_event, msecs_to_jiffies(WAIT_REM_CHAN_READY)); @@ -549,25 +553,27 @@ int wlan_hdd_action( struct wiphy *wiphy, struct net_device *dev, #endif hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev ); hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter ); + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter ); tANI_U16 extendedWait = 0; tANI_U8 type = WLAN_HDD_GET_TYPE_FRM_FC(buf[0]); tANI_U8 subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(buf[0]); tActionFrmType actionFrmType; bool noack = 0; -#ifdef WLAN_FEATURE_11W - tANI_U8 *pTxFrmBuf = (tANI_U8 *) buf; // For SA Query, we have to set protect bit -#endif + int status; #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)) hdd_adapter_t *goAdapter; #endif - if (((hdd_context_t*)pAdapter->pHddCtx)->isLogpInProgress) + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EBUSY; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return status; } + #ifdef WLAN_FEATURE_P2P_DEBUG if ((type == SIR_MAC_MGMT_FRAME) && (subType == SIR_MAC_MGMT_ACTION) && @@ -788,17 +794,7 @@ int wlan_hdd_action( struct wiphy *wiphy, struct net_device *dev, hddLog(LOG1, "%s: HDD_GO_NEG_REQ_ACK_PENDING \n", __func__); } } -#ifdef WLAN_FEATURE_11W - if ((type == SIR_MAC_MGMT_FRAME) && - (subType == SIR_MAC_MGMT_ACTION) && - (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_SA_QUERY_ACTION_FRAME)) - { - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s: Calling sme_sendAction. For Category %s", __func__, "SA Query"); - // Since this is an SA Query Action Frame, we have to protect it - WLAN_HDD_SET_WEP_FRM_FC(pTxFrmBuf[1]); - } -#endif + if (eHAL_STATUS_SUCCESS != sme_sendAction( WLAN_HDD_GET_HAL_CTX(pAdapter), sessionId, buf, len, extendedWait, noack)) @@ -1246,26 +1242,30 @@ int wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct net_device *dev ) #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) struct net_device *dev = wdev->netdev; #endif - hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy); - hdd_adapter_t *pVirtAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - ENTER(); + hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy); + hdd_adapter_t *pVirtAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + int status; + ENTER(); - hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d", - __func__,pVirtAdapter->device_mode); - if (pHddCtx->isLogpInProgress) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EAGAIN; - } + hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d", + __func__,pVirtAdapter->device_mode); + + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return status; + } - wlan_hdd_release_intf_addr( pHddCtx, + wlan_hdd_release_intf_addr( pHddCtx, pVirtAdapter->macAddressCurrent.bytes ); - hdd_stop_adapter( pHddCtx, pVirtAdapter ); - hdd_close_adapter( pHddCtx, pVirtAdapter, TRUE ); - EXIT(); - return 0; + hdd_stop_adapter( pHddCtx, pVirtAdapter ); + hdd_close_adapter( pHddCtx, pVirtAdapter, TRUE ); + EXIT(); + return 0; } void hdd_sendMgmtFrameOverMonitorIface( hdd_adapter_t *pMonAdapter, @@ -1332,7 +1332,7 @@ void hdd_sendMgmtFrameOverMonitorIface( hdd_adapter_t *pMonAdapter, skb->ip_summed = CHECKSUM_NONE; #ifdef WLAN_OPEN_SOURCE #ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK - wake_lock_timeout(&pHddCtx->rx_wake_lock, HDD_WAKE_LOCK_DURATION); + wake_lock_timeout(&pHddCtx->rx_wake_lock, msecs_to_jiffies(HDD_WAKE_LOCK_DURATION)); #endif #endif rxstat = netif_rx_ni(skb); @@ -1663,7 +1663,7 @@ static void hdd_wlan_tx_complete( hdd_adapter_t* pAdapter, memset( skb->cb, 0, sizeof( skb->cb ) ); #ifdef WLAN_OPEN_SOURCE #ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK - wake_lock_timeout(&pHddCtx->rx_wake_lock, HDD_WAKE_LOCK_DURATION); + wake_lock_timeout(&pHddCtx->rx_wake_lock, msecs_to_jiffies(HDD_WAKE_LOCK_DURATION)); #endif #endif if (in_interrupt()) diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_softap_tx_rx.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_softap_tx_rx.c index 98b5a005d03..05349f470f6 100644 --- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_softap_tx_rx.c +++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_softap_tx_rx.c @@ -98,6 +98,45 @@ static void hdd_softap_dump_sk_buff(struct sk_buff * skb) skb->data[13], skb->data[14], skb->data[15]); } #endif + +extern void hdd_set_wlan_suspend_mode(bool suspend); + +/**============================================================================ + @brief hdd_softap_traffic_monitor_timeout_handler() - + SAP/P2P GO traffin monitor timeout handler function + If no traffic during programmed time, trigger suspand mode + + @param pUsrData : [in] pointer to hdd context + @return : NONE + ===========================================================================*/ +void hdd_softap_traffic_monitor_timeout_handler( void *pUsrData ) +{ + hdd_context_t *pHddCtx = (hdd_context_t *)pUsrData; + v_TIME_t currentTS; + + if (NULL == pHddCtx) + { + VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid user data, context", __func__); + return; + } + + currentTS = vos_timer_get_system_time(); + if (pHddCtx->cfg_ini->trafficIdleTimeout < + (currentTS - pHddCtx->traffic_monitor.lastFrameTs)) + { + hdd_set_wlan_suspend_mode(1); + atomic_set(&pHddCtx->traffic_monitor.isActiveMode, 0); + } + else + { + vos_timer_start(&pHddCtx->traffic_monitor.trafficTimer, + pHddCtx->cfg_ini->trafficIdleTimeout); + } + + return; +} + /**============================================================================ @brief hdd_softap_flush_tx_queues() - Utility function to flush the TX queues @@ -217,7 +256,7 @@ int hdd_softap_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) } else if (FALSE == pAdapter->aStaInfo[STAId].isUsed ) { - VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_WARN,"%s: STA is unregistered", __func__, STAId); + VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_WARN,"%s: STA %d is unregistered", __func__, STAId); ++pAdapter->stats.tx_dropped; ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped; kfree_skb(skb); @@ -372,7 +411,7 @@ VOS_STATUS hdd_softap_sta_2_sta_xmit(struct sk_buff *skb, if ( FALSE == pAdapter->aStaInfo[STAId].isUsed ) { VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_WARN, - "%s: STA is unregistered", __func__, STAId ); + "%s: STA %d is unregistered", __func__, STAId ); kfree_skb(skb); status = VOS_STATUS_E_FAILURE; goto xmit_end; @@ -521,6 +560,9 @@ VOS_STATUS hdd_softap_init_tx_rx( hdd_adapter_t *pAdapter ) HDD_SOFTAP_VI_WEIGHT_DEFAULT, HDD_SOFTAP_VO_WEIGHT_DEFAULT }; + + hdd_context_t *pHddCtx = NULL; + pAdapter->isVosOutOfResource = VOS_FALSE; vos_mem_zero(&pAdapter->stats, sizeof(struct net_device_stats)); @@ -550,6 +592,31 @@ VOS_STATUS hdd_softap_init_tx_rx( hdd_adapter_t *pAdapter ) /* Update the AC weights suitable for SoftAP mode of operation */ WLANTL_SetACWeights((WLAN_HDD_GET_CTX(pAdapter))->pvosContext, pACWeights); + /* Initialize SAP/P2P-GO traffin monitor */ + pHddCtx = (hdd_context_t *)pAdapter->pHddCtx; + if (NULL == pHddCtx) + { + VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid HDD cntxt", __func__ ); + return VOS_STATUS_E_INVAL; + } + if ((pHddCtx->cfg_ini->enableTrafficMonitor) && + (!pHddCtx->traffic_monitor.isInitialized)) + { + atomic_set(&pHddCtx->traffic_monitor.isActiveMode, 1); + vos_timer_init(&pHddCtx->traffic_monitor.trafficTimer, + VOS_TIMER_TYPE_SW, + hdd_softap_traffic_monitor_timeout_handler, + pHddCtx); + vos_lock_init(&pHddCtx->traffic_monitor.trafficLock); + pHddCtx->traffic_monitor.isInitialized = 1; + pHddCtx->traffic_monitor.lastFrameTs = 0; + /* Start traffic monitor timer here + * If no AP assoc, immediatly go into suspend */ + vos_timer_start(&pHddCtx->traffic_monitor.trafficTimer, + pHddCtx->cfg_ini->trafficIdleTimeout); + } + return status; } @@ -564,6 +631,26 @@ VOS_STATUS hdd_softap_init_tx_rx( hdd_adapter_t *pAdapter ) VOS_STATUS hdd_softap_deinit_tx_rx( hdd_adapter_t *pAdapter ) { VOS_STATUS status = VOS_STATUS_SUCCESS; + hdd_context_t *pHddCtx = NULL; + + pHddCtx = (hdd_context_t *)pAdapter->pHddCtx; + if (NULL == pHddCtx) + { + VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid HDD cntxt", __func__ ); + return VOS_STATUS_E_INVAL; + } + if (pHddCtx->traffic_monitor.isInitialized) + { + if (VOS_TIMER_STATE_STOPPED != + vos_timer_getCurrentState(&pHddCtx->traffic_monitor.trafficTimer)) + { + vos_timer_stop(&pHddCtx->traffic_monitor.trafficTimer); + } + vos_timer_destroy(&pHddCtx->traffic_monitor.trafficTimer); + vos_lock_destroy(&pHddCtx->traffic_monitor.trafficLock); + pHddCtx->traffic_monitor.isInitialized = 0; + } status = hdd_softap_flush_tx_queues(pAdapter); @@ -853,6 +940,26 @@ VOS_STATUS hdd_softap_tx_fetch_packet_cbk( v_VOID_t *vosContext, return VOS_STATUS_E_FAILURE; } + /* Monitor traffic */ + if ( pHddCtx->cfg_ini->enableTrafficMonitor ) + { + pHddCtx->traffic_monitor.lastFrameTs = vos_timer_get_system_time(); + if ( !atomic_read(&pHddCtx->traffic_monitor.isActiveMode) ) + { + vos_lock_acquire(&pHddCtx->traffic_monitor.trafficLock); + /* It was IDLE mode, + * this is new state, then switch mode from suspend to resume */ + if ( !atomic_read(&pHddCtx->traffic_monitor.isActiveMode) ) + { + hdd_set_wlan_suspend_mode(0); + vos_timer_start(&pHddCtx->traffic_monitor.trafficTimer, + pHddCtx->cfg_ini->trafficIdleTimeout); + atomic_set(&pHddCtx->traffic_monitor.isActiveMode, 1); + } + vos_lock_release(&pHddCtx->traffic_monitor.trafficLock); + } + } + ++pAdapter->hdd_stats.hddTxRxStats.txFetched; STAId = *pStaId; @@ -1148,7 +1255,27 @@ VOS_STATUS hdd_softap_rx_packet_cbk( v_VOID_t *vosContext, VOS_ASSERT(0); return VOS_STATUS_E_FAILURE; } - + + /* Monitor traffic */ + if ( pHddCtx->cfg_ini->enableTrafficMonitor ) + { + pHddCtx->traffic_monitor.lastFrameTs = vos_timer_get_system_time(); + if ( !atomic_read(&pHddCtx->traffic_monitor.isActiveMode) ) + { + vos_lock_acquire(&pHddCtx->traffic_monitor.trafficLock); + /* It was IDLE mode, + * this is new state, then switch mode from suspend to resume */ + if ( !atomic_read(&pHddCtx->traffic_monitor.isActiveMode) ) + { + hdd_set_wlan_suspend_mode(0); + vos_timer_start(&pHddCtx->traffic_monitor.trafficTimer, + pHddCtx->cfg_ini->trafficIdleTimeout); + atomic_set(&pHddCtx->traffic_monitor.isActiveMode, 1); + } + vos_lock_release(&pHddCtx->traffic_monitor.trafficLock); + } + } + ++pAdapter->hdd_stats.hddTxRxStats.rxChains; // walk the chain until all are processed @@ -1225,13 +1352,14 @@ VOS_STATUS hdd_softap_rx_packet_cbk( v_VOID_t *vosContext, skb->ip_summed = CHECKSUM_NONE; #ifdef WLAN_OPEN_SOURCE #ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK - wake_lock_timeout(&pHddCtx->rx_wake_lock, HDD_WAKE_LOCK_DURATION); + wake_lock_timeout(&pHddCtx->rx_wake_lock, msecs_to_jiffies(HDD_WAKE_LOCK_DURATION)); #endif #endif rxstat = netif_rx_ni(skb); if (NET_RX_SUCCESS == rxstat) { ++pAdapter->hdd_stats.hddTxRxStats.rxDelivered; + ++pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count; } else { @@ -1269,11 +1397,25 @@ VOS_STATUS hdd_softap_rx_packet_cbk( v_VOID_t *vosContext, VOS_STATUS hdd_softap_DeregisterSTA( hdd_adapter_t *pAdapter, tANI_U8 staId ) { VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; - hdd_context_t *pHddCtx = pAdapter->pHddCtx; + hdd_context_t *pHddCtx; + if (NULL == pAdapter) + { + VOS_TRACE(VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR, + "%s: pAdapter is NULL", __func__); + return VOS_STATUS_E_INVAL; + } + + if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic) + { + VOS_TRACE(VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid pAdapter magic", __func__); + return VOS_STATUS_E_INVAL; + } + pHddCtx = (hdd_context_t*)(pAdapter->pHddCtx); //Clear station in TL and then update HDD data structures. This helps //to block RX frames from other station to this station. - vosStatus = WLANTL_ClearSTAClient( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, staId ); + vosStatus = WLANTL_ClearSTAClient( pHddCtx->pvosContext, staId ); if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) ) { VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR, @@ -1402,6 +1544,15 @@ VOS_STATUS hdd_softap_RegisterSTA( hdd_adapter_t *pAdapter, return vosStatus; } + //Timer value should be in milliseconds + if ( pHddCtx->cfg_ini->dynSplitscan && + ( VOS_TIMER_STATE_RUNNING != + vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))) + { + vos_timer_start(&pHddCtx->tx_rx_trafficTmr, + pHddCtx->cfg_ini->trafficMntrTmrForSplitScan); + } + // if ( WPA ), tell TL to go to 'connected' and after keys come to the driver, // then go to 'authenticated'. For all other authentication types (those that do // not require upper layer authentication) we can put TL directly into 'authenticated' diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_tdls.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_tdls.c index 676666abd16..4242081bced 100644 --- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_tdls.c +++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_tdls.c @@ -25,6 +25,8 @@ \brief WLAN Host Device Driver implementation for TDLS + Copyright (c) 2013 Qualcomm Atheros, Inc. All Rights Reserved. + Qualcomm Atheros Confidential and Proprietary. ========================================================================*/ #include @@ -44,6 +46,10 @@ static tANI_S32 wlan_hdd_get_tdls_discovery_peer_cnt(tdlsCtx_t *pHddTdlsCtx); static tANI_S32 wlan_hdd_tdls_peer_reset_discovery_processed(tdlsCtx_t *pHddTdlsCtx); static void wlan_hdd_tdls_timers_destroy(tdlsCtx_t *pHddTdlsCtx); +#ifdef CONFIG_TDLS_IMPLICIT +static void wlan_hdd_tdls_pre_setup(struct work_struct *work); +#endif + #ifndef WLAN_FEATURE_TDLS_DEBUG #define TDLS_LOG_LEVEL VOS_TRACE_LEVEL_INFO #else @@ -61,6 +67,21 @@ static u8 wlan_hdd_tdls_hash_key (u8 *mac) return key; } +#ifdef CONFIG_TDLS_IMPLICIT +static void wlan_hdd_tdls_pre_setup_init_work(tdlsCtx_t * pHddTdlsCtx, + hddTdlsPeer_t *curr_candidate) +{ + if (TDLS_CTX_MAGIC != pHddTdlsCtx->magic) + { + pHddTdlsCtx->curr_candidate = curr_candidate; + pHddTdlsCtx->magic = TDLS_CTX_MAGIC; + + INIT_WORK(&pHddTdlsCtx->implicit_setup, wlan_hdd_tdls_pre_setup); + schedule_work(&pHddTdlsCtx->implicit_setup); + } +} +#endif + static v_VOID_t wlan_hdd_tdls_start_peer_discover_timer(tdlsCtx_t *pHddTdlsCtx, tANI_BOOLEAN mutexLock, v_U32_t discoveryExpiry) @@ -105,6 +126,7 @@ static v_VOID_t wlan_hdd_tdls_start_peer_discover_timer(tdlsCtx_t *pHddTdlsCtx, return; } +#ifdef TDLS_USE_SEPARATE_DISCOVERY_TIMER static v_VOID_t wlan_hdd_tdls_discover_peer_cb( v_PVOID_t userData ) { int i; @@ -227,6 +249,7 @@ static v_VOID_t wlan_hdd_tdls_discover_peer_cb( v_PVOID_t userData ) mutex_unlock(&tdls_lock); return; } +#endif static v_VOID_t wlan_hdd_tdls_update_peer_cb( v_PVOID_t userData ) { @@ -262,16 +285,20 @@ static v_VOID_t wlan_hdd_tdls_update_peer_cb( v_PVOID_t userData ) curr_peer = list_entry (pos, hddTdlsPeer_t, node); VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, - "hdd update cb " MAC_ADDRESS_STR " link_status %d" - " tdls_support %d", MAC_ADDR_ARRAY(curr_peer->peerMac), + "%s: " MAC_ADDRESS_STR " link_status %d" + " tdls_support %d", __func__, MAC_ADDR_ARRAY(curr_peer->peerMac), curr_peer->link_status, curr_peer->tdls_support); if (eTDLS_CAP_SUPPORTED == curr_peer->tdls_support) { VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, - "%s: (tx %d, rx %d, config %d) " MAC_ADDRESS_STR " (%d) ", - __func__, curr_peer->tx_pkt, curr_peer->rx_pkt, + "tx %d, rx %d (thr.pkt %d/idle %d), rssi %d (thr.trig %d/hys %d/tear %d)", + curr_peer->tx_pkt, curr_peer->rx_pkt, pHddTdlsCtx->threshold_config.tx_packet_n, - MAC_ADDR_ARRAY(curr_peer->peerMac), curr_peer->link_status); + pHddTdlsCtx->threshold_config.idle_packet_n, + curr_peer->rssi, + pHddTdlsCtx->threshold_config.rssi_trigger_threshold, + pHddTdlsCtx->threshold_config.rssi_hysteresis, + pHddTdlsCtx->threshold_config.rssi_teardown_threshold); if ((eTDLS_LINK_IDLE == curr_peer->link_status) || (eTDLS_LINK_DISCOVERING == curr_peer->link_status)){ @@ -283,7 +310,7 @@ static v_VOID_t wlan_hdd_tdls_update_peer_cb( v_PVOID_t userData ) VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "Tput trigger TDLS pre-setup"); #ifdef CONFIG_TDLS_IMPLICIT - wlan_hdd_tdls_pre_setup(pHddTdlsCtx, curr_peer); + wlan_hdd_tdls_pre_setup_init_work(pHddTdlsCtx, curr_peer); #endif } else @@ -294,7 +321,8 @@ static v_VOID_t wlan_hdd_tdls_update_peer_cb( v_PVOID_t userData ) } goto next_peer; } - } else { + } + else if (eTDLS_LINK_CONNECTED == curr_peer->link_status) { if ((tANI_S32)curr_peer->rssi < (tANI_S32)pHddTdlsCtx->threshold_config.rssi_teardown_threshold) { @@ -353,7 +381,9 @@ static v_VOID_t wlan_hdd_tdls_update_peer_cb( v_PVOID_t userData ) if (curr_peer->discovery_attempt++ < pHddTdlsCtx->threshold_config.discovery_tries_n) { VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "TDLS UNKNOWN discover "); - wlan_hdd_tdls_pre_setup(pHddTdlsCtx, curr_peer); +#ifdef CONFIG_TDLS_IMPLICIT + wlan_hdd_tdls_pre_setup_init_work(pHddTdlsCtx, curr_peer); +#endif } else { @@ -381,10 +411,20 @@ static v_VOID_t wlan_hdd_tdls_idle_cb( v_PVOID_t userData ) #ifdef CONFIG_TDLS_IMPLICIT hddTdlsPeer_t *curr_peer = (hddTdlsPeer_t *)userData; - VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, - "%s: Tx/Rx Idle " MAC_ADDRESS_STR " trigger teardown", - __func__, - MAC_ADDR_ARRAY(curr_peer->peerMac)); + if (NULL == curr_peer) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid tdls idle timer expired", __func__); + return; + } + + VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, + "%s: Tx/Rx Idle " MAC_ADDRESS_STR " tx_pkt: %d, rx_pkt: %d, idle_packet_n: %d\n", + __func__, MAC_ADDR_ARRAY(curr_peer->peerMac), + curr_peer->tx_pkt, + curr_peer->rx_pkt, + curr_peer->pHddTdlsCtx->threshold_config.idle_packet_n); + if (mutex_lock_interruptible(&tdls_lock)) { VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, @@ -392,9 +432,27 @@ static v_VOID_t wlan_hdd_tdls_idle_cb( v_PVOID_t userData ) return; } - wlan_hdd_tdls_indicate_teardown(curr_peer->pHddTdlsCtx->pAdapter, - curr_peer, - eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON); + /* Check tx/rx statistics on this tdls link for recent activities and + * then decide whether to tear down the link or keep it. + */ + if ((curr_peer->tx_pkt >= curr_peer->pHddTdlsCtx->threshold_config.idle_packet_n) || (curr_peer->rx_pkt >= curr_peer->pHddTdlsCtx->threshold_config.idle_packet_n)) + { + /* this tdls link got back to normal, so keep it */ + VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, + "%s: tdls link to " MAC_ADDRESS_STR " back to normal, will stay", + __func__, MAC_ADDR_ARRAY(curr_peer->peerMac)); + } + else + { + /* this tdls link needs to get torn down */ + VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, + "%s: trigger tdls link to " MAC_ADDRESS_STR " down", + __func__, MAC_ADDR_ARRAY(curr_peer->peerMac)); + + wlan_hdd_tdls_indicate_teardown(curr_peer->pHddTdlsCtx->pAdapter, + curr_peer, + eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON); + } mutex_unlock(&tdls_lock); #endif } @@ -445,6 +503,23 @@ static v_VOID_t wlan_hdd_tdls_discovery_timeout_peer_cb(v_PVOID_t userData) return; } +static v_VOID_t wlan_hdd_tdls_initiator_wait_cb( v_PVOID_t userData ) +{ + hddTdlsPeer_t *curr_peer = (hddTdlsPeer_t *)userData; + tdlsCtx_t *pHddTdlsCtx; + + if ( NULL == curr_peer ) + return; + + pHddTdlsCtx = curr_peer->pHddTdlsCtx; + + if ( NULL == pHddTdlsCtx ) + return; + + WLANTL_ResumeDataTx( (WLAN_HDD_GET_CTX(pHddTdlsCtx->pAdapter))->pvosContext, + (v_U8_t *)&curr_peer->staId); +} + static void wlan_hdd_tdls_free_list(tdlsCtx_t *pHddTdlsCtx) { int i; @@ -484,22 +559,65 @@ int wlan_hdd_tdls_init(hdd_adapter_t *pAdapter) sme_IsFeatureSupportedByFW(TDLS)); return 0; } + /* TDLS is supported only in STA / P2P Client modes, + * hence the check for TDLS support in a specific Device mode. + * Do not return a failure rather do not continue further + * with the initialization as tdls_init would be called + * during the open adapter for a p2p interface at which point + * the device mode would be a P2P_DEVICE. The point here is to + * continue initialization for STA / P2P Client modes. + * TDLS exit also check for the device mode for clean up hence + * there is no issue even if success is returned. + */ + if (0 == WLAN_HDD_IS_TDLS_SUPPORTED_ADAPTER(pAdapter)) + { + return 0; + } + /* Check for the valid pHddTdlsCtx. If valid do not further + * allocate the memory, rather continue with the initialization. + * If tdls_initialization would get reinvoked without tdls_exit + * getting invoked (SSR) there is no point to further proceed + * with the memory allocations. + */ + if (NULL == pAdapter->sessionCtx.station.pHddTdlsCtx) + { + pHddTdlsCtx = vos_mem_malloc(sizeof(tdlsCtx_t)); - pHddTdlsCtx = vos_mem_malloc(sizeof(tdlsCtx_t)); + if (NULL == pHddTdlsCtx) { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s malloc failed!", __func__); + pAdapter->sessionCtx.station.pHddTdlsCtx = NULL; + return -1; + } + /* initialize TDLS pAdater context */ + vos_mem_zero(pHddTdlsCtx, sizeof(tdlsCtx_t)); +#ifdef TDLS_USE_SEPARATE_DISCOVERY_TIMER + vos_timer_init(&pHddTdlsCtx->peerDiscoverTimer, + VOS_TIMER_TYPE_SW, + wlan_hdd_tdls_discover_peer_cb, + pHddTdlsCtx); +#endif - if (NULL == pHddTdlsCtx) { - hddLog(VOS_TRACE_LEVEL_ERROR, "%s malloc failed!", __func__); - pAdapter->sessionCtx.station.pHddTdlsCtx = NULL; - return -1; + vos_timer_init(&pHddTdlsCtx->peerUpdateTimer, + VOS_TIMER_TYPE_SW, + wlan_hdd_tdls_update_peer_cb, + pHddTdlsCtx); + vos_timer_init(&pHddTdlsCtx->peerDiscoveryTimeoutTimer, + VOS_TIMER_TYPE_SW, + wlan_hdd_tdls_discovery_timeout_peer_cb, + pHddTdlsCtx); + + pAdapter->sessionCtx.station.pHddTdlsCtx = pHddTdlsCtx; } - pAdapter->sessionCtx.station.pHddTdlsCtx = pHddTdlsCtx; + pHddTdlsCtx = pAdapter->sessionCtx.station.pHddTdlsCtx; /* initialize TDLS global context */ pHddCtx->connected_peer_count = 0; sme_SetTdlsPowerSaveProhibited(WLAN_HDD_GET_HAL_CTX(pAdapter), 0); pHddCtx->tdls_scan_ctxt.magic = 0; + pHddCtx->tdls_scan_ctxt.attempt = 0; + pHddCtx->tdls_scan_ctxt.reject = 0; pHddCtx->tdls_scan_ctxt.scan_request = NULL; for (staIdx = 0; staIdx < HDD_MAX_NUM_TDLS_STA; staIdx++) @@ -510,9 +628,6 @@ int wlan_hdd_tdls_init(hdd_adapter_t *pAdapter) sizeof(v_MACADDR_t)) ; } - /* initialize TDLS pAdater context */ - vos_mem_zero(pHddTdlsCtx, sizeof(tdlsCtx_t)); - pHddTdlsCtx->pAdapter = pAdapter; for (i = 0; i < 256; i++) @@ -520,19 +635,8 @@ int wlan_hdd_tdls_init(hdd_adapter_t *pAdapter) INIT_LIST_HEAD(&pHddTdlsCtx->peer_list[i]); } - vos_timer_init(&pHddTdlsCtx->peerDiscoverTimer, - VOS_TIMER_TYPE_SW, - wlan_hdd_tdls_discover_peer_cb, - pHddTdlsCtx); - - vos_timer_init(&pHddTdlsCtx->peerUpdateTimer, - VOS_TIMER_TYPE_SW, - wlan_hdd_tdls_update_peer_cb, - pHddTdlsCtx); - vos_timer_init(&pHddTdlsCtx->peerDiscoveryTimeoutTimer, - VOS_TIMER_TYPE_SW, - wlan_hdd_tdls_discovery_timeout_peer_cb, - pHddTdlsCtx); + pHddTdlsCtx->curr_candidate = NULL; + pHddTdlsCtx->magic = 0; /* remember configuration even if it is not used right now. it could be used later */ pHddTdlsCtx->threshold_config.tx_period_t = pHddCtx->cfg_ini->fTDLSTxStatsPeriod; @@ -605,7 +709,9 @@ static void wlan_hdd_tdls_timers_stop(tdlsCtx_t *pHddTdlsCtx) struct list_head *pos; hddTdlsPeer_t *curr_peer; +#ifdef TDLS_USE_SEPARATE_DISCOVERY_TIMER vos_timer_stop(&pHddTdlsCtx->peerDiscoverTimer); +#endif vos_timer_stop(&pHddTdlsCtx->peerUpdateTimer); vos_timer_stop(&pHddTdlsCtx->peerDiscoveryTimeoutTimer); @@ -621,6 +727,7 @@ static void wlan_hdd_tdls_timers_stop(tdlsCtx_t *pHddTdlsCtx) __func__, MAC_ADDR_ARRAY(curr_peer->peerMac)); vos_timer_stop ( &curr_peer->peerIdleTimer ); + vos_timer_stop( &curr_peer->initiatorWaitTimeoutTimer ); } } } @@ -633,8 +740,10 @@ static void wlan_hdd_tdls_timers_destroy(tdlsCtx_t *pHddTdlsCtx) struct list_head *pos; hddTdlsPeer_t *curr_peer; +#ifdef TDLS_USE_SEPARATE_DISCOVERY_TIMER vos_timer_stop(&pHddTdlsCtx->peerDiscoverTimer); vos_timer_destroy(&pHddTdlsCtx->peerDiscoverTimer); +#endif vos_timer_stop(&pHddTdlsCtx->peerUpdateTimer); vos_timer_destroy(&pHddTdlsCtx->peerUpdateTimer); vos_timer_stop(&pHddTdlsCtx->peerDiscoveryTimeoutTimer); @@ -653,6 +762,8 @@ static void wlan_hdd_tdls_timers_destroy(tdlsCtx_t *pHddTdlsCtx) MAC_ADDR_ARRAY(curr_peer->peerMac)); vos_timer_stop ( &curr_peer->peerIdleTimer ); vos_timer_destroy ( &curr_peer->peerIdleTimer ); + vos_timer_stop(&curr_peer->initiatorWaitTimeoutTimer); + vos_timer_destroy(&curr_peer->initiatorWaitTimeoutTimer); } } } @@ -710,6 +821,11 @@ hddTdlsPeer_t *wlan_hdd_tdls_get_peer(hdd_adapter_t *pAdapter, u8 *mac) wlan_hdd_tdls_idle_cb, peer); + vos_timer_init(&peer->initiatorWaitTimeoutTimer, + VOS_TIMER_TYPE_SW, + wlan_hdd_tdls_initiator_wait_cb, + peer); + list_add_tail(&peer->node, head); mutex_unlock(&tdls_lock); @@ -797,7 +913,7 @@ int wlan_hdd_tdls_recv_discovery_resp(hdd_adapter_t *pAdapter, u8 *mac) } else { - VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, + VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "Rssi Threshold not met: "MAC_ADDRESS_STR" rssi = %d threshold = %d ", MAC_ADDR_ARRAY(curr_peer->peerMac), curr_peer->rssi, pHddTdlsCtx->threshold_config.rssi_trigger_threshold); @@ -1073,6 +1189,33 @@ hddTdlsPeer_t *wlan_hdd_tdls_find_peer(hdd_adapter_t *pAdapter, u8 *mac) return NULL; } +hddTdlsPeer_t *wlan_hdd_tdls_find_all_peer(hdd_context_t *pHddCtx, u8 *mac) +{ + hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; + hdd_adapter_t *pAdapter = NULL; + tdlsCtx_t *pHddTdlsCtx = NULL; + hddTdlsPeer_t *curr_peer= NULL; + VOS_STATUS status = 0; + + status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode ); + while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status ) + { + pAdapter = pAdapterNode->pAdapter; + + pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter); + if (NULL != pHddTdlsCtx) + { + curr_peer = wlan_hdd_tdls_find_peer(pAdapter, mac); + if (curr_peer) + return curr_peer; + } + status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); + pAdapterNode = pNext; + } + return curr_peer; +} + + int wlan_hdd_tdls_reset_peer(hdd_adapter_t *pAdapter, u8 *mac) { hdd_context_t *pHddCtx; @@ -1331,9 +1474,19 @@ void wlan_hdd_tdls_check_bmps(hdd_adapter_t *pAdapter) { hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); tdlsCtx_t *pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter); + hddTdlsPeer_t *curr_peer; if ((NULL == pHddCtx) || (NULL == pHddTdlsCtx)) return; + curr_peer = wlan_hdd_tdls_is_progress(pHddCtx, NULL, 0, TRUE); + if (NULL != curr_peer) + { + VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, + "%s: tdls in progress. Dont check for BMPS " MAC_ADDRESS_STR, + __func__, MAC_ADDR_ARRAY (curr_peer->peerMac)); + return; + } + if ((TDLS_CTX_MAGIC != pHddCtx->tdls_scan_ctxt.magic) && (0 == pHddCtx->connected_peer_count) && (0 == pHddTdlsCtx->discovery_sent_cnt)) @@ -1369,12 +1522,12 @@ u8 wlan_hdd_tdls_is_peer_progress(hdd_adapter_t *pAdapter, u8 *mac) return (eTDLS_LINK_CONNECTING == curr_peer->link_status); } -/* return TRUE if TDLS is ongoing +/* return pointer to hddTdlsPeer_t if TDLS is ongoing. Otherwise return NULL. * mac - if NULL check for all the peer list, otherwise, skip this mac when skip_self is TRUE * skip_self - if TRUE, skip this mac. otherwise, check all the peer list. if mac is NULL, this argument is ignored, and check for all the peer list. */ -u8 wlan_hdd_tdls_is_progress(hdd_adapter_t *pAdapter, u8 *mac, u8 skip_self) +static hddTdlsPeer_t *wlan_hdd_tdls_find_progress_peer(hdd_adapter_t *pAdapter, u8 *mac, u8 skip_self, tANI_BOOLEAN mutexLock) { int i; struct list_head *head; @@ -1382,17 +1535,21 @@ u8 wlan_hdd_tdls_is_progress(hdd_adapter_t *pAdapter, u8 *mac, u8 skip_self) struct list_head *pos; tdlsCtx_t *pHddTdlsCtx; - if (mutex_lock_interruptible(&tdls_lock)) + if (mutexLock) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + if (mutex_lock_interruptible(&tdls_lock)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: unable to lock list", __func__); - return FALSE; + return NULL; + } } pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter); if (NULL == pHddTdlsCtx) { - mutex_unlock(&tdls_lock); - return FALSE; + if (mutexLock) + mutex_unlock(&tdls_lock); + return NULL; } for (i = 0; i < 256; i++) { @@ -1409,15 +1566,43 @@ u8 wlan_hdd_tdls_is_progress(hdd_adapter_t *pAdapter, u8 *mac, u8 skip_self) VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "%s:" MAC_ADDRESS_STR " eTDLS_LINK_CONNECTING", __func__, MAC_ADDR_ARRAY(curr_peer->peerMac)); - mutex_unlock(&tdls_lock); - return TRUE; + if (mutexLock) + mutex_unlock(&tdls_lock); + return curr_peer; } } } } - mutex_unlock(&tdls_lock); - return FALSE; + if (mutexLock) + mutex_unlock(&tdls_lock); + return NULL; +} + +hddTdlsPeer_t *wlan_hdd_tdls_is_progress(hdd_context_t *pHddCtx, u8 *mac, u8 skip_self, tANI_BOOLEAN mutexLock) +{ + hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; + hdd_adapter_t *pAdapter = NULL; + tdlsCtx_t *pHddTdlsCtx = NULL; + hddTdlsPeer_t *curr_peer= NULL; + VOS_STATUS status = 0; + + status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode ); + while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status ) + { + pAdapter = pAdapterNode->pAdapter; + + pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter); + if (NULL != pHddTdlsCtx) + { + curr_peer = wlan_hdd_tdls_find_progress_peer(pAdapter, mac, skip_self, mutexLock); + if (curr_peer) + return curr_peer; + } + status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); + pAdapterNode = pNext; + } + return NULL; } static void wlan_hdd_tdls_implicit_disable(tdlsCtx_t *pHddTdlsCtx) @@ -1479,18 +1664,14 @@ void wlan_hdd_tdls_set_mode(hdd_context_t *pHddCtx, while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status ) { pAdapter = pAdapterNode->pAdapter; - if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) || - (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)) + pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter); + if (NULL != pHddTdlsCtx) { - pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter); - if (NULL != pHddTdlsCtx) - { - if(eTDLS_SUPPORT_ENABLED == tdls_mode) - wlan_hdd_tdls_implicit_enable(pHddTdlsCtx); - else if((eTDLS_SUPPORT_DISABLED == tdls_mode) || - (eTDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY == tdls_mode)) - wlan_hdd_tdls_implicit_disable(pHddTdlsCtx); - } + if(eTDLS_SUPPORT_ENABLED == tdls_mode) + wlan_hdd_tdls_implicit_enable(pHddTdlsCtx); + else if((eTDLS_SUPPORT_DISABLED == tdls_mode) || + (eTDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY == tdls_mode)) + wlan_hdd_tdls_implicit_disable(pHddTdlsCtx); } status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); pAdapterNode = pNext; @@ -1508,10 +1689,30 @@ void wlan_hdd_tdls_set_mode(hdd_context_t *pHddCtx, mutex_unlock(&tdls_lock); } -void wlan_hdd_tdls_pre_setup(tdlsCtx_t *pHddTdlsCtx, - hddTdlsPeer_t *curr_peer) +static void wlan_hdd_tdls_pre_setup(struct work_struct *work) { - hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHddTdlsCtx->pAdapter); + tdlsCtx_t *pHddTdlsCtx = + container_of(work, tdlsCtx_t, implicit_setup); + hdd_context_t *pHddCtx; + hddTdlsPeer_t *curr_peer; + hddTdlsPeer_t *temp_peer; + int status; + + if (NULL == pHddTdlsCtx) + return; + + if (unlikely(TDLS_CTX_MAGIC != pHddTdlsCtx->magic)) + return; + + pHddCtx = WLAN_HDD_GET_CTX(pHddTdlsCtx->pAdapter); + + if (NULL == pHddCtx) + return; + + curr_peer = pHddTdlsCtx->curr_candidate; + + if (NULL == curr_peer) + return; if (TRUE == sme_IsPmcBmps(WLAN_HDD_GET_HAL_CTX(pHddTdlsCtx->pAdapter))) { @@ -1519,14 +1720,30 @@ void wlan_hdd_tdls_pre_setup(tdlsCtx_t *pHddTdlsCtx, hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION); } + temp_peer = wlan_hdd_tdls_is_progress(pHddCtx, NULL, 0, FALSE); + if (NULL != temp_peer) + { + VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "%s: " MAC_ADDRESS_STR " ongoing. pre_setup ignored\n", + __func__, MAC_ADDR_ARRAY(temp_peer->peerMac)); + goto done; + } + if (eTDLS_CAP_UNKNOWN != curr_peer->tdls_support) curr_peer->link_status = eTDLS_LINK_DISCOVERING; - sme_SendTdlsMgmtFrame(WLAN_HDD_GET_HAL_CTX(pHddTdlsCtx->pAdapter), - pHddTdlsCtx->pAdapter->sessionId, - curr_peer->peerMac, - WLAN_TDLS_DISCOVERY_REQUEST, - 1, 0, NULL, 0, 0); + status = wlan_hdd_cfg80211_send_tdls_discover_req(pHddTdlsCtx->pAdapter->wdev.wiphy, + pHddTdlsCtx->pAdapter->dev, + curr_peer->peerMac); + + if (0 != status) + { + VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "%s: " MAC_ADDRESS_STR " discovery could not sent\n", + __func__, MAC_ADDR_ARRAY(curr_peer->peerMac)); + if (eTDLS_CAP_UNKNOWN != curr_peer->tdls_support) + curr_peer->link_status = eTDLS_LINK_IDLE; + goto done; + } + pHddTdlsCtx->discovery_sent_cnt++; wlan_hdd_tdls_check_power_save_prohibited(pHddTdlsCtx->pAdapter); VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "%s: discovery count %lu timeout %lu msec", @@ -1537,6 +1754,9 @@ void wlan_hdd_tdls_pre_setup(tdlsCtx_t *pHddTdlsCtx, &pHddTdlsCtx->peerDiscoveryTimeoutTimer, pHddTdlsCtx->threshold_config.tx_period_t - TDLS_DISCOVERY_TIMEOUT_BEFORE_UPDATE); +done: + pHddTdlsCtx->curr_candidate = NULL; + pHddTdlsCtx->magic = 0; return; } @@ -1553,14 +1773,10 @@ tANI_U32 wlan_hdd_tdls_discovery_sent_cnt(hdd_context_t *pHddCtx) { pAdapter = pAdapterNode->pAdapter; - if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) || - (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)) + pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter); + if (NULL != pHddTdlsCtx) { - pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter); - if (NULL != pHddTdlsCtx) - { - count = count + pHddTdlsCtx->discovery_sent_cnt; - } + count = count + pHddTdlsCtx->discovery_sent_cnt; } status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); pAdapterNode = pNext; @@ -1592,6 +1808,7 @@ void wlan_hdd_tdls_free_scan_request (tdls_scan_context_t *tdls_scan_ctx) return; tdls_scan_ctx->attempt = 0; + tdls_scan_ctx->reject = 0; tdls_scan_ctx->magic = 0; tdls_scan_ctx->scan_request = NULL; return; @@ -1679,6 +1896,7 @@ int wlan_hdd_tdls_scan_callback (hdd_adapter_t *pAdapter, #endif hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); u16 connectedTdlsPeers; + hddTdlsPeer_t *curr_peer; unsigned long delay; if (NULL == pHddCtx) @@ -1688,11 +1906,22 @@ int wlan_hdd_tdls_scan_callback (hdd_adapter_t *pAdapter, if (eTDLS_SUPPORT_NOT_ENABLED == pHddCtx->tdls_mode) return 1; - if (wlan_hdd_tdls_is_progress(pAdapter, NULL, 0)) + curr_peer = wlan_hdd_tdls_is_progress(pHddCtx, NULL, 0, TRUE); + if (NULL != curr_peer) { + if (pHddCtx->tdls_scan_ctxt.reject++ >= TDLS_MAX_SCAN_REJECT) + { + pHddCtx->tdls_scan_ctxt.reject = 0; + VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, + "%s: " MAC_ADDRESS_STR ". scan rejected %d. force it to idle", + __func__, MAC_ADDR_ARRAY (curr_peer->peerMac), pHddCtx->tdls_scan_ctxt.reject); + + wlan_hdd_tdls_set_peer_link_status (curr_peer, eTDLS_LINK_IDLE); + return 1; + } VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, - "%s: tdls in progress. scan rejected", - __func__); + "%s: tdls in progress. scan rejected %d", + __func__, pHddCtx->tdls_scan_ctxt.reject); return -EBUSY; } @@ -1743,8 +1972,9 @@ int wlan_hdd_tdls_scan_callback (hdd_adapter_t *pAdapter, ("%s: indicate TDLS teadown (staId %d)"), __func__, pHddCtx->tdlsConnInfo[staIdx].staId) ; #ifdef CONFIG_TDLS_IMPLICIT - curr_peer = wlan_hdd_tdls_find_peer(pAdapter,pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes); - wlan_hdd_tdls_indicate_teardown(pAdapter, curr_peer, eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON); + curr_peer = wlan_hdd_tdls_find_all_peer(pHddCtx, pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes); + if(curr_peer) + wlan_hdd_tdls_indicate_teardown(curr_peer->pHddTdlsCtx->pAdapter, curr_peer, eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON); #endif } } diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_tx_rx.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_tx_rx.c index 5fc2ab5c719..997f37ec08e 100644 --- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_tx_rx.c +++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_tx_rx.c @@ -621,6 +621,7 @@ int hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueued; ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueuedAC[ac]; + ++pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count; //Make sure we have access to this access category if (likely(pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessAllowed) || @@ -671,27 +672,12 @@ int hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) ===========================================================================*/ void hdd_tx_timeout(struct net_device *dev) { - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: Transmission timeout occurred", __func__); //Getting here implies we disabled the TX queues for too long. Queues are //disabled either because of disassociation or low resource scenarios. In //case of disassociation it is ok to ignore this. But if associated, we have //do possible recovery here - - //testing underlying data path stall - //FTM mode, data path is not initiated - if (VOS_FTM_MODE == hdd_get_conparam()) - { - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s: FTM mode, how initiated TX?", __func__); - } - else - { - sme_transportDebug(hHal, 0, 1); - } } @@ -1353,7 +1339,8 @@ VOS_STATUS hdd_rx_packet_cbk( v_VOID_t *vosContext, pAdapter = pHddCtx->sta_to_adapter[staId]; if( NULL == pAdapter ) { - VOS_ASSERT(0); + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: pAdapter is Null for staId %u", + __func__, staId); return VOS_STATUS_E_FAILURE; } @@ -1411,7 +1398,8 @@ VOS_STATUS hdd_rx_packet_cbk( v_VOID_t *vosContext, "rx extract mac:" MAC_ADDRESS_STR, MAC_ADDR_ARRAY(mac) ); curr_peer = wlan_hdd_tdls_find_peer(pAdapter, mac); - if ((NULL != curr_peer) && (eTDLS_LINK_CONNECTED == curr_peer->link_status)) + if ((NULL != curr_peer) && (eTDLS_LINK_CONNECTED == curr_peer->link_status) + && (TRUE == pRxMetaInfo->isStaTdls)) { wlan_hdd_tdls_increment_pkt_count(pAdapter, mac, 0); VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"rssi is %d", pRxMetaInfo->rssiAvg); @@ -1432,13 +1420,14 @@ VOS_STATUS hdd_rx_packet_cbk( v_VOID_t *vosContext, pAdapter->stats.rx_bytes += skb->len; #ifdef WLAN_OPEN_SOURCE #ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK - wake_lock_timeout(&pHddCtx->rx_wake_lock, HDD_WAKE_LOCK_DURATION); + wake_lock_timeout(&pHddCtx->rx_wake_lock, msecs_to_jiffies(HDD_WAKE_LOCK_DURATION)); #endif #endif rxstat = netif_rx_ni(skb); if (NET_RX_SUCCESS == rxstat) { ++pAdapter->hdd_stats.hddTxRxStats.rxDelivered; + ++pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count; } else { @@ -1461,3 +1450,119 @@ VOS_STATUS hdd_rx_packet_cbk( v_VOID_t *vosContext, return status; } +/**=========================================================================== + @brief hdd_tx_rx_pkt_cnt_stat_timer_handler() - + Enable/Disable split scan based on TX and RX traffic. + @param HddContext : [in] pointer to Hdd context + @return : None + ===========================================================================*/ +void hdd_tx_rx_pkt_cnt_stat_timer_handler( void *phddctx) +{ + hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; + hdd_adapter_t *pAdapter = NULL; + hdd_station_ctx_t *pHddStaCtx = NULL; + hdd_context_t *pHddCtx = (hdd_context_t *)phddctx; + hdd_config_t *cfg_param = pHddCtx->cfg_ini; + VOS_STATUS status; + v_U8_t staId = 0; + v_U8_t fconnected = 0; + + if (!cfg_param->dynSplitscan) + { + hddLog(VOS_TRACE_LEVEL_INFO, + "%s: Error : Dynamic split scan is not Enabled : %d", + __func__, pHddCtx->cfg_ini->dynSplitscan); + return; + } + + status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode ); + while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status ) + { + pAdapter = pAdapterNode->pAdapter; + + if ( pAdapter ) + { + hddLog(VOS_TRACE_LEVEL_INFO, + "%s: Adapter with device mode %d exists", + __func__, pAdapter->device_mode); + + if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) || + (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)) + { + pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + if ((eConnectionState_Associated == + pHddStaCtx->conn_info.connState) && + (VOS_TRUE == pHddStaCtx->conn_info.uIsAuthenticated)) + { + fconnected = TRUE; + } + } + else if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) || + (WLAN_HDD_P2P_GO == pAdapter->device_mode)) + { + for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++) + { + if ((pAdapter->aStaInfo[staId].isUsed) && + (WLANTL_STA_AUTHENTICATED == + pAdapter->aStaInfo[staId].tlSTAState)) + { + fconnected = TRUE; + } + } + } + if ( fconnected ) + { + hddLog(VOS_TRACE_LEVEL_INFO, + "%s: One of the interface is connected check for scan", + __func__); + hddLog(VOS_TRACE_LEVEL_INFO, + "%s: pkt_tx_count: %d, pkt_rx_count: %d", __func__, + pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count, + pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count); + + vos_timer_start(&pHddCtx->tx_rx_trafficTmr, + cfg_param->trafficMntrTmrForSplitScan); + //Check for the previous statistics count + if ((pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count > + cfg_param->txRxThresholdForSplitScan) || + (pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count > + cfg_param->txRxThresholdForSplitScan) || + pHddCtx->drvr_miracast) + { + pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count = 0; + pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count = 0; + + if (!pHddCtx->issplitscan_enabled) + { + pHddCtx->issplitscan_enabled = TRUE; + sme_enable_disable_split_scan( + WLAN_HDD_GET_HAL_CTX(pAdapter), + cfg_param->nNumStaChanCombinedConc, + cfg_param->nNumP2PChanCombinedConc); + } + return; + } + else + { + pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count = 0; + pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count = 0; + } + fconnected = FALSE; + } + } + status = hdd_get_next_adapter( pHddCtx, pAdapterNode, &pNext); + pAdapterNode = pNext; + } + + if (pHddCtx->issplitscan_enabled) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Disable split scan", __func__); + pHddCtx->issplitscan_enabled = FALSE; + sme_enable_disable_split_scan( + pHddCtx->hHal, + SME_DISABLE_SPLIT_SCAN, + SME_DISABLE_SPLIT_SCAN); + } + return; +} diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_wext.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_wext.c index 48f0571b755..543a3273171 100644 --- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_wext.c +++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_wext.c @@ -104,12 +104,14 @@ #include #include #include "wlan_qct_pal_trace.h" +#include "wlan_qct_tl.h" #include "wlan_hdd_misc.h" #include "bap_hdd_misc.h" #include "wlan_hdd_dev_pwr.h" #include "qc_sap_ioctl.h" +#include "sme_Api.h" #ifdef CONFIG_HAS_EARLYSUSPEND extern void hdd_suspend_wlan(struct early_suspend *wlan_suspend); @@ -208,9 +210,6 @@ static const hdd_freq_chan_map_t freq_chan_map[] = { {2412, 1}, {2417, 2}, #ifdef FEATURE_WLAN_TDLS #define WE_GET_TDLS_PEERS 8 #endif -#ifdef WLAN_FEATURE_11W -#define WE_GET_11W_INFO 9 -#endif /* Private ioctls and their sub-ioctls */ #define WLAN_PRIV_SET_NONE_GET_NONE (SIOCIWFIRSTPRIV + 6) @@ -221,6 +220,7 @@ static const hdd_freq_chan_map_t freq_chan_map[] = { {2412, 1}, {2417, 2}, #define WE_DISABLE_AMP 5 #define WE_ENABLE_DXE_STALL_DETECT 6 #define WE_DISPLAY_DXE_SNAP_SHOT 7 +#define WE_DISPLAY_DATAPATH_SNAP_SHOT 9 #define WE_SET_REASSOC_TRIGGER 8 /* Private ioctls and their sub-ioctls */ @@ -536,9 +536,6 @@ hdd_IsAuthTypeRSN( tHalHandle halHandle, eCsrAuthType authType) case eCSR_AUTH_TYPE_FT_RSN_PSK: #endif case eCSR_AUTH_TYPE_RSN_PSK: -#ifdef WLAN_FEATURE_11W - case eCSR_AUTH_TYPE_RSN_PSK_SHA256: -#endif rsnType = eANI_BOOLEAN_TRUE; break; //case eCSR_AUTH_TYPE_FAILED: @@ -910,11 +907,6 @@ void hdd_clearRoamProfileIe( hdd_adapter_t *pAdapter) pWextState->roamProfile.nRSNReqIELength = 0; pWextState->roamProfile.pRSNReqIE = (tANI_U8 *)NULL; -#ifdef FEATURE_WLAN_WAPI - pWextState->roamProfile.nWAPIReqIELength = 0; - pWextState->roamProfile.pWAPIReqIE = (tANI_U8 *)NULL; -#endif - pWextState->roamProfile.bWPSAssociation = VOS_FALSE; pWextState->roamProfile.pAddIEScan = (tANI_U8 *)NULL; pWextState->roamProfile.nAddIEScanLength = 0; @@ -932,12 +924,6 @@ void hdd_clearRoamProfileIe( hdd_adapter_t *pAdapter) pWextState->roamProfile.AuthType.numEntries = 1; pWextState->roamProfile.AuthType.authType[0] = eCSR_AUTH_TYPE_OPEN_SYSTEM; -#ifdef WLAN_FEATURE_11W - pWextState->roamProfile.MFPEnabled = eANI_BOOLEAN_FALSE; - pWextState->roamProfile.MFPRequired = 0; - pWextState->roamProfile.MFPCapable = 0; -#endif - pWextState->authKeyMgmt = 0; for (i=0; i < CSR_MAX_NUM_KEY; i++) @@ -1917,6 +1903,7 @@ static int iw_get_range(struct net_device *dev, struct iw_request_info *info, if (active_phy_mode == WNI_CFG_DOT11_MODE_11A || active_phy_mode == WNI_CFG_DOT11_MODE_11G) { /*Get the supported rates for 11G band*/ + a_len = WNI_CFG_SUPPORTED_RATES_11A_LEN; if (ccmCfgGetStr(hHal, WNI_CFG_SUPPORTED_RATES_11A, supp_rates, &a_len) == eHAL_STATUS_SUCCESS) @@ -1939,6 +1926,7 @@ static int iw_get_range(struct net_device *dev, struct iw_request_info *info, else if (active_phy_mode == WNI_CFG_DOT11_MODE_11B) { /*Get the supported rates for 11B band*/ + b_len = WNI_CFG_SUPPORTED_RATES_11B_LEN; if (ccmCfgGetStr(hHal, WNI_CFG_SUPPORTED_RATES_11B, supp_rates, &b_len) == eHAL_STATUS_SUCCESS) @@ -2326,17 +2314,22 @@ static int iw_get_linkspeed(struct net_device *dev, union iwreq_data *wrqu, char *extra) { hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx; char *pLinkSpeed = (char*)extra; - int len = sizeof(v_U16_t) + 1; - v_U16_t link_speed; + int len = sizeof(v_U32_t) + 1; + v_U32_t link_speed; hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); - int rc; + VOS_STATUS status; + int rc, valid; - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + valid = wlan_hdd_validate_context(pHddCtx); + + if (0 != valid) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EBUSY; + hddLog(VOS_TRACE_LEVEL_ERROR, FL("HDD context is not valid")); + return valid; } if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) @@ -2346,21 +2339,40 @@ static int iw_get_linkspeed(struct net_device *dev, } else { - wlan_hdd_get_classAstats(pAdapter); - //The linkspeed returned by HAL is in units of 500kbps. - //converting it to mbps - link_speed = pAdapter->hdd_stats.ClassA_stat.tx_rate/2; + status = wlan_hdd_get_classAstats(pAdapter); + + if (!VOS_IS_STATUS_SUCCESS(status )) + { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Unable to retrieve SME statistics")); + return -EINVAL; + } + + /* Unit of link capacity is obtained from the TL API is MbpsX10 */ + WLANTL_GetSTALinkCapacity(WLAN_HDD_GET_CTX(pAdapter)->pvosContext, + (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0], + &link_speed); + + link_speed = link_speed / 10; + + if (0 == link_speed) + { + /* The linkspeed returned by HAL is in units of 500kbps. + * converting it to mbps. + * This is required to support legacy firmware which does + * not return link capacity. + */ + link_speed = pAdapter->hdd_stats.ClassA_stat.tx_rate/2; + } + } wrqu->data.length = len; // return the linkspeed in the format required by the WiFi Framework - rc = snprintf(pLinkSpeed, len, "%u", link_speed); + rc = snprintf(pLinkSpeed, len, "%lu", link_speed); if ((rc < 0) || (rc >= len)) { // encoding or length error? - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: Unable to encode link speed, got [%s]", - __func__,pLinkSpeed); + hddLog(VOS_TRACE_LEVEL_ERROR,FL("Unable to encode link speed")); return -EIO; } @@ -3314,12 +3326,21 @@ static int iw_set_encodeext(struct net_device *dev, ("%s:cipher_alg:%d key_len[%d] *pEncryptionType :%d \n"),__func__,(int)ext->alg,(int)ext->key_len,setKey.encType); #ifdef WLAN_FEATURE_VOWIFI_11R -/* The supplicant may attempt to set the PTK once pre-authentication is done. - Save the key in the UMAC and include it in the ADD BSS request */ + /* The supplicant may attempt to set the PTK once pre-authentication + is done. Save the key in the UMAC and include it in the ADD + BSS request */ halStatus = sme_FTUpdateKey( WLAN_HDD_GET_HAL_CTX(pAdapter), &setKey); - if( halStatus == eHAL_STATUS_FT_PREAUTH_KEY_WAIT ) + if ( halStatus == eHAL_STATUS_FT_PREAUTH_KEY_SUCCESS ) { - return -EINVAL; + hddLog(VOS_TRACE_LEVEL_INFO_MED, + "%s: Update PreAuth Key success", __func__); + return 0; + } + else if ( halStatus == eHAL_STATUS_FT_PREAUTH_KEY_FAILED ) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Update PreAuth Key failed", __func__); + return -EINVAL; } #endif /* WLAN_FEATURE_VOWIFI_11R */ @@ -4060,9 +4081,6 @@ static int iw_get_char_setnone(struct net_device *dev, struct iw_request_info *i { hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); int sub_cmd = wrqu->data.flags; -#ifdef WLAN_FEATURE_11W - hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); -#endif if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) { @@ -4274,25 +4292,6 @@ static int iw_get_char_setnone(struct net_device *dev, struct iw_request_info *i wrqu->data.length = wlan_hdd_tdls_get_all_peers(pAdapter, extra, WE_MAX_STR_LEN)+1; break; } -#endif -#ifdef WLAN_FEATURE_11W - case WE_GET_11W_INFO: - { - hddLog(LOGE, "WE_GET_11W_ENABLED = %d", pWextState->roamProfile.MFPEnabled ); - - snprintf(extra, WE_MAX_STR_LEN, - "\n BSSID %02X:%02X:%02X:%02X:%02X:%02X, Is PMF Assoc? %d" - "\n Number of Unprotected Disassocs %d" - "\n Number of Unprotected Deauths %d", - (*pWextState->roamProfile.BSSIDs.bssid)[0], (*pWextState->roamProfile.BSSIDs.bssid)[1], - (*pWextState->roamProfile.BSSIDs.bssid)[2], (*pWextState->roamProfile.BSSIDs.bssid)[3], - (*pWextState->roamProfile.BSSIDs.bssid)[4], (*pWextState->roamProfile.BSSIDs.bssid)[5], - pWextState->roamProfile.MFPEnabled, pAdapter->hdd_stats.hddPmfStats.numUnprotDisassocRx, - pAdapter->hdd_stats.hddPmfStats.numUnprotDeauthRx); - - wrqu->data.length = strlen(extra)+1; - break; - } #endif default: { @@ -4348,6 +4347,12 @@ static int iw_setnone_getnone(struct net_device *dev, struct iw_request_info *in pr_info("Stopping AP mode\n"); + if (TRUE == sme_IsPmcBmps(WLAN_HDD_GET_HAL_CTX(pAdapter))) + { + /* EXIT BMPS as fw cannot handle DEL_STA when its in BMPS */ + wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_ACTIVE); + } + /*Make sure that pAdapter cleaned properly*/ hdd_stop_adapter( pHddCtx, pAdapter_to_stop ); hdd_deinit_adapter( pHddCtx, pAdapter_to_stop ); @@ -4357,6 +4362,12 @@ static int iw_setnone_getnone(struct net_device *dev, struct iw_request_info *in pAdapter_to_stop->macAddressCurrent.bytes); hdd_close_adapter(WLAN_HDD_GET_CTX(pAdapter), pAdapter_to_stop, TRUE); + + if (FALSE == sme_IsPmcBmps(WLAN_HDD_GET_HAL_CTX(pAdapter))) + { + /* put the device back into BMPS */ + wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_AUTO); + } } else { @@ -4411,6 +4422,13 @@ static int iw_setnone_getnone(struct net_device *dev, struct iw_request_info *in sme_transportDebug(hHal, VOS_TRUE, VOS_FALSE); break; } + case WE_DISPLAY_DATAPATH_SNAP_SHOT: + { + hddLog(LOGE, "%s: called %d",__func__, sub_cmd); + hdd_wmm_tx_snapshot(pAdapter); + WLANTL_TLDebugMessage(VOS_TRUE); + break; + } case WE_SET_REASSOC_TRIGGER: { hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); @@ -4433,6 +4451,42 @@ static int iw_setnone_getnone(struct net_device *dev, struct iw_request_info *in return ret; } +void hdd_wmm_tx_snapshot(hdd_adapter_t *pAdapter) +{ + /* + * Function to display HDD WMM information + * for Tx Queues. + * Prints globala as well as per client depending + * whether the clients are registered or not. + */ + int i = 0, j = 0; + for ( i=0; i< NUM_TX_QUEUES; i++) + { + spin_lock_bh(&pAdapter->wmm_tx_queue[i].lock); + hddLog(LOGE, "HDD WMM TxQueue Info For AC: %d Count: %d PrevAdress:0x%x, NextAddress:0x%x", + i, pAdapter->wmm_tx_queue[i].count, + pAdapter->wmm_tx_queue[i].anchor.prev, pAdapter->wmm_tx_queue[i].anchor.next); + spin_unlock_bh(&pAdapter->wmm_tx_queue[i].lock); + } + + for(i =0; iaStaInfo[i].isUsed) + { + hddLog(LOGE, "******STAIndex: %d*********", i); + for ( j=0; j< NUM_TX_QUEUES; j++) + { + spin_lock_bh(&pAdapter->aStaInfo[i].wmm_tx_queue[j].lock); + hddLog(LOGE, "HDD TxQueue Info For AC: %d Count: %d PrevAdress:0x%x, NextAddress:0x%x", + j, pAdapter->aStaInfo[i].wmm_tx_queue[j].count, + pAdapter->aStaInfo[i].wmm_tx_queue[j].anchor.prev, + pAdapter->aStaInfo[i].wmm_tx_queue[j].anchor.next); + spin_unlock_bh(&pAdapter->aStaInfo[i].wmm_tx_queue[j].lock); + } + } + } + +} int iw_set_var_ints_getnone(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { @@ -4530,7 +4584,7 @@ int iw_set_var_ints_getnone(struct net_device *dev, struct iw_request_info *info } else { - hddLog(LOGE, "%s : Enter valid MccCredential value between MIN :40 and MAX:160\n"); + hddLog(LOGE, "%s : Enter valid MccCredential value between MIN :40 and MAX:160\n", __func__); return 0; } } @@ -4925,7 +4979,7 @@ static int iw_qcom_set_wapi_key(struct net_device *dev, struct iw_request_info * hddLog(LOG1, "%s: Received data %s", __func__, (char*)wrqu->data.pointer); hddLog(LOG1, "%s: Received data %s", __func__, (char*)extra); - hddLog(LOG1,":s: INPUT DATA:\nKey Type:0x%02x Key Direction:0x%02x KEY ID:0x%02x\n", __func__,pWapiKey->keyType,pWapiKey->keyDirection,pWapiKey->keyId); + hddLog(LOG1,":%s: INPUT DATA:\nKey Type:0x%02x Key Direction:0x%02x KEY ID:0x%02x\n", __func__, pWapiKey->keyType, pWapiKey->keyDirection, pWapiKey->keyId); hddLog(LOG1,"Add Index:0x"); for(i =0 ; i < 12 ; i++) hddLog(LOG1,"%02x",pWapiKey->addrIndex[i]); @@ -5083,12 +5137,12 @@ static int iw_set_fties(struct net_device *dev, struct iw_request_info *info, } if (!wrqu->data.length) { - hddLog(LOGE, FL("%s called with 0 length IEs\n")); + hddLog(LOGE, FL("called with 0 length IEs\n")); return -EINVAL; } if (wrqu->data.pointer == NULL) { - hddLog(LOGE, FL("%s called with NULL IE\n")); + hddLog(LOGE, FL("called with NULL IE\n")); return -EINVAL; } @@ -5121,11 +5175,9 @@ static int iw_set_dynamic_mcbc_filter(struct net_device *dev, hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); tpSirWlanSetRxpFilters wlanRxpFilterParam; tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); - VOS_STATUS vstatus = VOS_STATUS_E_FAILURE; tpSirRcvFltMcAddrList mc_addr_list_ptr; int idx; eHalStatus ret_val; - tANI_U8 mcastBcastFilterSetting; if (pHddCtx->isLogpInProgress) { @@ -5134,7 +5186,9 @@ static int iw_set_dynamic_mcbc_filter(struct net_device *dev, return -EBUSY; } - if (HDD_MULTICAST_FILTER_LIST == pRequest->mcastBcastFilterSetting) { + if (HDD_MULTICAST_FILTER_LIST == pRequest->mcastBcastFilterSetting) + { +#ifdef WLAN_FEATURE_PACKET_FILTERING mc_addr_list_ptr = vos_mem_malloc(sizeof(tSirRcvFltMcAddrList)); if (NULL == mc_addr_list_ptr) @@ -5169,69 +5223,45 @@ static int iw_set_dynamic_mcbc_filter(struct net_device *dev, __func__); return -EINVAL; } - } else { +#endif //WLAN_FEATURE_PACKET_FILTERING + } + else + { hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: Set MC BC Filter Config request: %d suspend %d", __func__, pRequest->mcastBcastFilterSetting, pHddCtx->hdd_wlan_suspended); - wlanRxpFilterParam = vos_mem_malloc(sizeof(tSirWlanSetRxpFilters)); - if (NULL == wlanRxpFilterParam) - { - hddLog(VOS_TRACE_LEVEL_FATAL, - "%s: vos_mem_alloc failed", __func__); - return -EINVAL; - } - - pHddCtx->dynamic_mcbc_filter.mcastBcastFilterSetting = - pRequest->mcastBcastFilterSetting; - pHddCtx->dynamic_mcbc_filter.enableCfg = TRUE; + pHddCtx->configuredMcastBcastFilter = pRequest->mcastBcastFilterSetting; if (pHddCtx->hdd_wlan_suspended) { + wlanRxpFilterParam = vos_mem_malloc(sizeof(tSirWlanSetRxpFilters)); + if (NULL == wlanRxpFilterParam) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: vos_mem_alloc failed", __func__); + return -EINVAL; + } + wlanRxpFilterParam->configuredMcstBcstFilterSetting = pRequest->mcastBcastFilterSetting; wlanRxpFilterParam->setMcstBcstFilter = TRUE; - if ((pHddCtx->cfg_ini->fhostArpOffload) && - (eConnectionState_Associated == - (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState)) - { - vstatus = hdd_conf_hostarpoffload(pAdapter, TRUE); - if (!VOS_IS_STATUS_SUCCESS(vstatus)) - { - hddLog(VOS_TRACE_LEVEL_INFO, - "%s:Failed to enable ARPOFFLOAD Feature %d", - __func__, vstatus); - } - else - { - if (HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST_BROADCAST == - pHddCtx->dynamic_mcbc_filter.mcastBcastFilterSetting) - { - wlanRxpFilterParam->configuredMcstBcstFilterSetting = - HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST; - } - else if (HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST == - pHddCtx->dynamic_mcbc_filter.mcastBcastFilterSetting) - { - wlanRxpFilterParam->configuredMcstBcstFilterSetting = - HDD_MCASTBCASTFILTER_FILTER_NONE; - } - } - } + hdd_conf_hostoffload(pAdapter, TRUE); + wlanRxpFilterParam->configuredMcstBcstFilterSetting = + pHddCtx->configuredMcastBcastFilter; hddLog(VOS_TRACE_LEVEL_INFO, "%s:MC/BC changed Req %d Set %d En %d", __func__, - pHddCtx->dynamic_mcbc_filter.mcastBcastFilterSetting, + pHddCtx->configuredMcastBcastFilter, wlanRxpFilterParam->configuredMcstBcstFilterSetting, wlanRxpFilterParam->setMcstBcstFilter); - mcastBcastFilterSetting = wlanRxpFilterParam->configuredMcstBcstFilterSetting; - - if (eHAL_STATUS_SUCCESS != sme_ConfigureRxpFilter(WLAN_HDD_GET_HAL_CTX(pAdapter), - wlanRxpFilterParam)) + if (eHAL_STATUS_SUCCESS != + sme_ConfigureRxpFilter(WLAN_HDD_GET_HAL_CTX(pAdapter), + wlanRxpFilterParam)) { hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failure to execute set HW MC/BC Filter request", @@ -5240,8 +5270,6 @@ static int iw_set_dynamic_mcbc_filter(struct net_device *dev, return -EINVAL; } - pHddCtx->dynamic_mcbc_filter.mcBcFilterSuspend = - mcastBcastFilterSetting; } } @@ -5254,11 +5282,42 @@ static int iw_clear_dynamic_mcbc_filter(struct net_device *dev, { hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); - + tpSirWlanSetRxpFilters wlanRxpFilterParam; hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: ", __func__); - pHddCtx->dynamic_mcbc_filter.enableCfg = FALSE; + //Reset the filter to INI value as we have to clear the dynamic filter + pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting; + + //Configure FW with new setting + if (pHddCtx->hdd_wlan_suspended) + { + wlanRxpFilterParam = vos_mem_malloc(sizeof(tSirWlanSetRxpFilters)); + if (NULL == wlanRxpFilterParam) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: vos_mem_alloc failed", __func__); + return -EINVAL; + } + + wlanRxpFilterParam->configuredMcstBcstFilterSetting = + pHddCtx->configuredMcastBcastFilter; + wlanRxpFilterParam->setMcstBcstFilter = TRUE; + hdd_conf_hostoffload(pAdapter, TRUE); + wlanRxpFilterParam->configuredMcstBcstFilterSetting = + pHddCtx->configuredMcastBcastFilter; + + if (eHAL_STATUS_SUCCESS != + sme_ConfigureRxpFilter(WLAN_HDD_GET_HAL_CTX(pAdapter), + wlanRxpFilterParam)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Failure to execute set HW MC/BC Filter request", + __func__); + vos_mem_free(wlanRxpFilterParam); + return -EINVAL; + } + } return 0; } @@ -5446,7 +5505,7 @@ int wlan_hdd_set_filter(hdd_context_t *pHddCtx, tpPacketFilterCfg pRequest, packetFilterSetReq.paramsData[i].dataLength = pRequest->paramsData[i].dataLength; packetFilterSetReq.paramsData[i].reserved = 0; - hddLog(VOS_TRACE_LEVEL_INFO, "Proto %d Comp Flag %d Filter Type\n", + hddLog(VOS_TRACE_LEVEL_INFO, "Proto %d Comp Flag %d Filter Type %d\n", pRequest->paramsData[i].protocolLayer, pRequest->paramsData[i].cmpFlag, packetFilterSetReq.filterType); @@ -5499,6 +5558,189 @@ int wlan_hdd_set_filter(hdd_context_t *pHddCtx, tpPacketFilterCfg pRequest, return 0; } +int wlan_hdd_setIPv6Filter(hdd_context_t *pHddCtx, tANI_U8 filterType, + tANI_U8 sessionId) +{ + tSirRcvPktFilterCfgType packetFilterSetReq = {0}; + tSirRcvFltPktClearParam packetFilterClrReq = {0}; + + if (NULL == pHddCtx) + { + hddLog(VOS_TRACE_LEVEL_ERROR, FL(" NULL HDD Context Passed")); + return -EINVAL; + } + + if (pHddCtx->isLogpInProgress) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s:LOGP in Progress. Ignore!!!", __func__); + return -EBUSY; + } + + if (pHddCtx->cfg_ini->disablePacketFilter) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Packet Filtering Disabled. Returning ", + __func__ ); + return -EINVAL; + } + + switch (filterType) + { + /* For setting IPV6 MC and UC Filter we need to configure + * 2 filters, one for MC and one for UC. + * The Filter ID shouldn't be swapped, which results in making + * UC Filter ineffective. + * We have Hardcode all the values + * + * Reason for a seperate UC filter is because, driver need to + * specify the FW that the specific filter is for unicast + * otherwise FW will not pass the unicast frames by default + * through the filter. This is required to avoid any performance + * hits when no unicast filter is set and only MC/BC are set. + * The way driver informs host is by using the MAC protocol + * layer, CMP flag set to MAX, CMP Data set to 1. + */ + + case HDD_FILTER_IPV6_MC_UC: + /* Setting IPV6 MC Filter below + */ + packetFilterSetReq.filterType = HDD_RCV_FILTER_SET; + packetFilterSetReq.filterId = HDD_FILTER_ID_IPV6_MC; + packetFilterSetReq.numFieldParams = 2; + packetFilterSetReq.paramsData[0].protocolLayer = + HDD_FILTER_PROTO_TYPE_MAC; + packetFilterSetReq.paramsData[0].cmpFlag = + HDD_FILTER_CMP_TYPE_NOT_EQUAL; + packetFilterSetReq.paramsData[0].dataOffset = + WLAN_HDD_80211_FRM_DA_OFFSET; + packetFilterSetReq.paramsData[0].dataLength = 1; + packetFilterSetReq.paramsData[0].compareData[0] = + HDD_IPV6_MC_CMP_DATA; + + packetFilterSetReq.paramsData[1].protocolLayer = + HDD_FILTER_PROTO_TYPE_ARP; + packetFilterSetReq.paramsData[1].cmpFlag = + HDD_FILTER_CMP_TYPE_NOT_EQUAL; + packetFilterSetReq.paramsData[1].dataOffset = ETH_ALEN; + packetFilterSetReq.paramsData[1].dataLength = 2; + packetFilterSetReq.paramsData[1].compareData[0] = + HDD_IPV6_CMP_DATA_0; + packetFilterSetReq.paramsData[1].compareData[1] = + HDD_IPV6_CMP_DATA_1; + + + if (eHAL_STATUS_SUCCESS != sme_ReceiveFilterSetFilter(pHddCtx->hHal, + &packetFilterSetReq, sessionId)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Failure to execute Set IPv6 Mulicast Filter", + __func__); + return -EINVAL; + } + + memset( &packetFilterSetReq, 0, sizeof(tSirRcvPktFilterCfgType)); + + /* + * Setting IPV6 UC Filter below + */ + packetFilterSetReq.filterType = HDD_RCV_FILTER_SET; + packetFilterSetReq.filterId = HDD_FILTER_ID_IPV6_UC; + packetFilterSetReq.numFieldParams = 2; + packetFilterSetReq.paramsData[0].protocolLayer = + HDD_FILTER_PROTO_TYPE_MAC; + packetFilterSetReq.paramsData[0].cmpFlag = + HDD_FILTER_CMP_TYPE_MAX; + packetFilterSetReq.paramsData[0].dataOffset = 0; + packetFilterSetReq.paramsData[0].dataLength = 1; + packetFilterSetReq.paramsData[0].compareData[0] = + HDD_IPV6_UC_CMP_DATA; + + packetFilterSetReq.paramsData[1].protocolLayer = + HDD_FILTER_PROTO_TYPE_ARP; + packetFilterSetReq.paramsData[1].cmpFlag = + HDD_FILTER_CMP_TYPE_NOT_EQUAL; + packetFilterSetReq.paramsData[1].dataOffset = ETH_ALEN; + packetFilterSetReq.paramsData[1].dataLength = 2; + packetFilterSetReq.paramsData[1].compareData[0] = + HDD_IPV6_CMP_DATA_0; + packetFilterSetReq.paramsData[1].compareData[1] = + HDD_IPV6_CMP_DATA_1; + + if (eHAL_STATUS_SUCCESS != sme_ReceiveFilterSetFilter(pHddCtx->hHal, + &packetFilterSetReq, sessionId)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Failure to execute Set IPv6 Unicast Filter", + __func__); + return -EINVAL; + } + + break; + + case HDD_FILTER_IPV6_MC: + /* + * IPV6 UC Filter might be already set, + * clear the UC Filter. As the Filter + * IDs are static, we can directly clear it. + */ + packetFilterSetReq.filterType = HDD_RCV_FILTER_SET; + packetFilterClrReq.filterId = HDD_FILTER_ID_IPV6_UC; + if (eHAL_STATUS_SUCCESS != sme_ReceiveFilterClearFilter(pHddCtx->hHal, + &packetFilterClrReq, sessionId)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Failure to execute Clear IPv6 Unicast Filter", + __func__); + return -EINVAL; + } + + /* + * Setting IPV6 MC Filter below + */ + packetFilterSetReq.filterId = HDD_FILTER_ID_IPV6_MC; + packetFilterSetReq.numFieldParams = 2; + packetFilterSetReq.paramsData[0].protocolLayer = + HDD_FILTER_PROTO_TYPE_MAC; + packetFilterSetReq.paramsData[0].cmpFlag = + HDD_FILTER_CMP_TYPE_NOT_EQUAL; + packetFilterSetReq.paramsData[0].dataOffset = + WLAN_HDD_80211_FRM_DA_OFFSET; + packetFilterSetReq.paramsData[0].dataLength = 1; + packetFilterSetReq.paramsData[0].compareData[0] = + HDD_IPV6_MC_CMP_DATA; + + packetFilterSetReq.paramsData[1].protocolLayer = + HDD_FILTER_PROTO_TYPE_ARP; + packetFilterSetReq.paramsData[1].cmpFlag = + HDD_FILTER_CMP_TYPE_NOT_EQUAL; + packetFilterSetReq.paramsData[1].dataOffset = ETH_ALEN; + packetFilterSetReq.paramsData[1].dataLength = 2; + packetFilterSetReq.paramsData[1].compareData[0] = + HDD_IPV6_CMP_DATA_0; + packetFilterSetReq.paramsData[1].compareData[1] = + HDD_IPV6_CMP_DATA_1; + + + if (eHAL_STATUS_SUCCESS != sme_ReceiveFilterSetFilter(pHddCtx->hHal, + &packetFilterSetReq, sessionId)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Failure to execute Set IPv6 Multicast Filter", + __func__); + return -EINVAL; + } + break; + + default : + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, + "%s: Packet Filter Request: Invalid", + __func__); + return -EINVAL; + } + return 0; +} + void wlan_hdd_set_mc_addr_list(hdd_adapter_t *pAdapter, v_U8_t set) { v_U8_t filterAction; @@ -5772,7 +6014,7 @@ VOS_STATUS iw_set_pno(struct net_device *dev, struct iw_request_info *info, VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "PNO data len %d data %s", wrqu->data.length, - wrqu->data.pointer); + (char *)wrqu->data.pointer); if (wrqu->data.length <= nOffset ) { @@ -6153,7 +6395,7 @@ int hdd_setBand_helper(struct net_device *dev, tANI_U8* ptr) if (lrc <= 0) { - hddLog(VOS_TRACE_LEVEL_ERROR,"%s: %s while while waiting for csrRoamDisconnect ", + hddLog(VOS_TRACE_LEVEL_ERROR,"%s: %s while waiting for csrRoamDisconnect ", __func__, (0 == lrc) ? "Timeout" : "Interrupt"); return (0 == lrc) ? -ETIMEDOUT : -EINTR; @@ -6229,7 +6471,7 @@ VOS_STATUS iw_set_power_params(struct net_device *dev, struct iw_request_info *i VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "Power Params data len %d data %s", wrqu->data.length, - wrqu->data.pointer); + (char *)wrqu->data.pointer); if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) { @@ -6665,13 +6907,6 @@ static const struct iw_priv_args we_private_args[] = { 0, IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN, "getTdlsPeers" }, -#endif -#ifdef WLAN_FEATURE_11W - { - WE_GET_11W_INFO, - 0, - IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN, - "getPMFInfo" }, #endif /* handlers for main ioctl */ { WLAN_PRIV_SET_NONE_GET_NONE, @@ -6708,6 +6943,10 @@ static const struct iw_priv_args we_private_args[] = { 0, 0, "dxeSnapshot" }, + { WE_DISPLAY_DATAPATH_SNAP_SHOT, + 0, + 0, + "dataSnapshot"}, { WE_SET_REASSOC_TRIGGER, 0, @@ -6877,7 +7116,7 @@ static const struct iw_priv_args we_private_args[] = { { WLAN_GET_LINK_SPEED, IW_PRIV_TYPE_CHAR | 18, - IW_PRIV_TYPE_CHAR | 3, "getLinkSpeed" }, + IW_PRIV_TYPE_CHAR | 5, "getLinkSpeed" }, }; diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_wmm.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_wmm.c index 23dc9c5afec..5992c6ead7c 100644 --- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_wmm.c +++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_wmm.c @@ -689,7 +689,7 @@ static eHalStatus hdd_wmm_sme_callback (tHalHandle hHal, #ifdef FEATURE_WLAN_CCX // Check if the inactivity interval is specified - if (pCurrentQosInfo->inactivity_interval) { + if (pCurrentQosInfo && pCurrentQosInfo->inactivity_interval) { VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, "%s: Inactivity timer value = %d for AC=%d\n", __func__, pCurrentQosInfo->inactivity_interval, acType); @@ -2268,7 +2268,7 @@ hdd_wlan_wmm_status_e hdd_wmm_addts( hdd_adapter_t* pAdapter, default: // we didn't get back one of the SME_QOS_STATUS_MODIFY_* status codes VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR, - "%s: unexpected SME Status=%d\n", smeStatus ); + "%s: unexpected SME Status=%d\n", __func__, smeStatus ); VOS_ASSERT(0); return HDD_WLAN_WMM_STATUS_MODIFY_FAILED; } @@ -2346,7 +2346,7 @@ hdd_wlan_wmm_status_e hdd_wmm_addts( hdd_adapter_t* pAdapter, // we didn't get back one of the SME_QOS_STATUS_SETUP_* status codes hdd_wmm_free_context(pQosContext); VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR, - "%s: unexpected SME Status=%d\n", smeStatus ); + "%s: unexpected SME Status=%d\n", __func__, smeStatus ); VOS_ASSERT(0); return HDD_WLAN_WMM_STATUS_SETUP_FAILED; } @@ -2457,7 +2457,7 @@ hdd_wlan_wmm_status_e hdd_wmm_delts( hdd_adapter_t* pAdapter, default: // we didn't get back one of the SME_QOS_STATUS_RELEASE_* status codes VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR, - "%s: unexpected SME Status=%d\n", smeStatus ); + "%s: unexpected SME Status=%d\n", __func__, smeStatus ); VOS_ASSERT(0); status = HDD_WLAN_WMM_STATUS_RELEASE_FAILED; } diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_wowl.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_wowl.c index 101bd18a9b7..e783033a3c6 100644 --- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_wowl.c +++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_wowl.c @@ -71,7 +71,7 @@ char *g_hdd_wowl_ptrns[WOWL_MAX_PTRNS_ALLOWED]; //Patterns 0-7 -static int parse_hex(unsigned char c) +int hdd_parse_hex(unsigned char c) { if (c >= '0' && c <= '9') return c-'0'; @@ -190,11 +190,11 @@ v_BOOL_t hdd_add_wowl_ptrn (hdd_adapter_t *pAdapter, const char * ptrn) // Extract the pattern size localPattern.ucPatternSize = - ( parse_hex( ptrn[0] ) * 0x10 ) + parse_hex( ptrn[1] ); + ( hdd_parse_hex( ptrn[0] ) * 0x10 ) + hdd_parse_hex( ptrn[1] ); // Extract the pattern mask size localPattern.ucPatternMaskSize = - ( parse_hex( ptrn[3] ) * 0x10 ) + parse_hex( ptrn[4] ); + ( hdd_parse_hex( ptrn[3] ) * 0x10 ) + hdd_parse_hex( ptrn[4] ); if(localPattern.ucPatternSize > WOWL_PTRN_MAX_SIZE || localPattern.ucPatternMaskSize > WOWL_PTRN_MASK_MAX_SIZE) @@ -234,7 +234,7 @@ v_BOOL_t hdd_add_wowl_ptrn (hdd_adapter_t *pAdapter, const char * ptrn) for(i=0; i < localPattern.ucPatternSize; i++) { localPattern.ucPattern[i] = - (parse_hex( ptrn[0] ) * 0x10 ) + parse_hex( ptrn[1] ); + (hdd_parse_hex( ptrn[0] ) * 0x10 ) + hdd_parse_hex( ptrn[1] ); ptrn += 2; //skip to next byte } @@ -244,7 +244,7 @@ v_BOOL_t hdd_add_wowl_ptrn (hdd_adapter_t *pAdapter, const char * ptrn) for(i=0; i < localPattern.ucPatternMaskSize; i++) { localPattern.ucPatternMask[i] = - (parse_hex( ptrn[0] ) * 0x10 ) + parse_hex( ptrn[1] ); + (hdd_parse_hex( ptrn[0] ) * 0x10 ) + hdd_parse_hex( ptrn[1] ); ptrn += 2; //skip to next byte } diff --git a/drivers/staging/prima/CORE/MAC/inc/aniGlobal.h b/drivers/staging/prima/CORE/MAC/inc/aniGlobal.h index f1b6318687a..e55dca65e5b 100644 --- a/drivers/staging/prima/CORE/MAC/inc/aniGlobal.h +++ b/drivers/staging/prima/CORE/MAC/inc/aniGlobal.h @@ -150,6 +150,8 @@ typedef struct sAniSirGlobal *tpAniSirGlobal; #define SPACE_ASCII_VALUE 32 +#define SPACE_ASCII_VALUE 32 + // ------------------------------------------------------------------- // Change channel generic scheme typedef void (*CHANGE_CHANNEL_CALLBACK)(tpAniSirGlobal pMac, eHalStatus status, tANI_U32 *data, @@ -336,6 +338,20 @@ typedef struct sAniSirLim tLimScanResultNode *gLimCachedScanHashTable[LIM_MAX_NUM_OF_SCAN_RESULTS]; + /// This indicates total length of 'matched' scan results + tANI_U16 gLimMlmLfrScanResultLength; + + /// This indicates total length of 'cached' scan results + tANI_U16 gLimSmeLfrScanResultLength; + + /** + * Hash table definition for storing LFR SCAN results + * This is the placed holder for roaming candidates as forwarded + * by FW + */ + tLimScanResultNode + *gLimCachedLfrScanHashTable[LIM_MAX_NUM_OF_SCAN_RESULTS]; + /// Place holder for current channel ID /// being scanned during background scanning tANI_U32 gLimBackgroundScanChannelId; diff --git a/drivers/staging/prima/CORE/MAC/inc/qwlan_version.h b/drivers/staging/prima/CORE/MAC/inc/qwlan_version.h index aaf39184931..707407aca66 100644 --- a/drivers/staging/prima/CORE/MAC/inc/qwlan_version.h +++ b/drivers/staging/prima/CORE/MAC/inc/qwlan_version.h @@ -58,11 +58,11 @@ BRIEF DESCRIPTION: #define QWLAN_VERSION_MAJOR 3 #define QWLAN_VERSION_MINOR 2 -#define QWLAN_VERSION_PATCH 2 -#define QWLAN_VERSION_EXTRA "B" -#define QWLAN_VERSION_BUILD 17 +#define QWLAN_VERSION_PATCH 3 +#define QWLAN_VERSION_EXTRA "" +#define QWLAN_VERSION_BUILD 10 -#define QWLAN_VERSIONSTR "3.2.2.17B" +#define QWLAN_VERSIONSTR "3.2.3.10" #endif /* QWLAN_VERSION_H */ diff --git a/drivers/staging/prima/CORE/MAC/inc/sirApi.h b/drivers/staging/prima/CORE/MAC/inc/sirApi.h index 71d4366b65a..36fab78cbb0 100644 --- a/drivers/staging/prima/CORE/MAC/inc/sirApi.h +++ b/drivers/staging/prima/CORE/MAC/inc/sirApi.h @@ -1,9 +1,43 @@ /* -* Copyright (c) 2012-2013 Qualcomm Atheros, Inc. -* All Rights Reserved. -* Qualcomm Atheros Confidential and Proprietary. -*/ - + * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ +/* + * Copyright (c) 2012, The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ /* * Airgo Networks, Inc proprietary. All rights reserved. @@ -986,15 +1020,11 @@ typedef struct sSirSmeJoinReq tAniEdType UCEncryptionType; tAniEdType MCEncryptionType; - -#ifdef WLAN_FEATURE_11W - tAniEdType MgmtEncryptionType; -#endif - #ifdef WLAN_FEATURE_VOWIFI_11R tAniBool is11Rconnection; #endif #ifdef FEATURE_WLAN_CCX + tAniBool isCCXFeatureIniEnabled; tAniBool isCCXconnection; tCCXTspecInfo ccxTspecInfo; #endif @@ -3219,7 +3249,9 @@ typedef struct sSirUpdateAPWPARSNIEsReq #define SIR_OFFLOAD_DISABLE 0 #define SIR_OFFLOAD_ENABLE 1 #define SIR_OFFLOAD_BCAST_FILTER_ENABLE 0x2 +#define SIR_OFFLOAD_MCAST_FILTER_ENABLE 0x4 #define SIR_OFFLOAD_ARP_AND_BCAST_FILTER_ENABLE (SIR_OFFLOAD_ENABLE|SIR_OFFLOAD_BCAST_FILTER_ENABLE) +#define SIR_OFFLOAD_NS_AND_MCAST_FILTER_ENABLE (SIR_OFFLOAD_ENABLE|SIR_OFFLOAD_MCAST_FILTER_ENABLE) #ifdef WLAN_NS_OFFLOAD typedef struct sSirNsOffloadReq @@ -3231,6 +3263,7 @@ typedef struct sSirNsOffloadReq tANI_U8 selfMacAddr[6]; tANI_U8 srcIPv6AddrValid; tANI_U8 targetIPv6AddrValid[SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA]; + tANI_U8 slotIdx; } tSirNsOffloadReq, *tpSirNsOffloadReq; #endif //WLAN_NS_OFFLOAD @@ -3273,6 +3306,7 @@ typedef struct sSirSmeAddStaSelfReq tANI_U16 mesgType; tANI_U16 mesgLen; tSirMacAddr selfMacAddr; + tVOS_CON_MODE currDeviceMode; }tSirSmeAddStaSelfReq, *tpSirSmeAddStaSelfReq; typedef struct sSirSmeDelStaSelfReq @@ -3307,6 +3341,8 @@ typedef struct sSirSmeDelStaSelfRsp #define SIR_COEX_IND_TYPE_ENABLE_HB_MONITOR (1) #define SIR_COEX_IND_TYPE_SCAN_COMPROMISED (2) #define SIR_COEX_IND_TYPE_SCAN_NOT_COMPROMISED (3) +#define SIR_COEX_IND_TYPE_DISABLE_AGGREGATION_IN_2p4 (4) +#define SIR_COEX_IND_TYPE_ENABLE_AGGREGATION_IN_2p4 (5) typedef struct sSirSmeCoexInd { @@ -3327,16 +3363,6 @@ typedef struct sSirSmeMgmtFrameInd tANI_U8 frameBuf[1]; //variable }tSirSmeMgmtFrameInd, *tpSirSmeMgmtFrameInd; -#ifdef WLAN_FEATURE_11W -typedef struct sSirSmeUnprotMgmtFrameInd -{ - tANI_U8 sessionId; - tANI_U8 frameType; - tANI_U8 frameLen; - tANI_U8 frameBuf[1]; //variable -}tSirSmeUnprotMgmtFrameInd, *tpSirSmeUnprotMgmtFrameInd; -#endif - #define SIR_IS_FULL_POWER_REASON_DISCONNECTED(eReason) \ ( ( eSME_LINK_DISCONNECTED_BY_HDD == (eReason) ) || \ ( eSME_LINK_DISCONNECTED_BY_OTHER == (eReason) ) || \ @@ -3399,7 +3425,8 @@ typedef struct sSirWlanSetRxpFilters #define CHANNEL_LIST_DYNAMIC_UPDATE 4 /* Occupied channel list can be learnt after update */ #define SIR_ROAM_SCAN_24G_DEFAULT_CH 1 #define SIR_ROAM_SCAN_5G_DEFAULT_CH 36 -#define SIR_ROAM_SCAN_RESERVED_BYTES 64 +#define SIR_ROAM_SCAN_CHANNEL_SWITCH_TIME 3 +#define SIR_ROAM_SCAN_RESERVED_BYTES 61 #endif typedef enum @@ -3417,7 +3444,7 @@ typedef struct tANI_U32 encryption; tANI_U32 bcastNetwType; tANI_U8 ucChannelCount; - tANI_U8 aChannels[SIR_PNO_MAX_NETW_CHANNELS]; + tANI_U8 aChannels[SIR_PNO_MAX_NETW_CHANNELS_EX]; tANI_U8 rssiThreshold; } tSirNetworkType; @@ -3487,9 +3514,18 @@ typedef struct sSirRoamOffloadScanReq tANI_U8 p24GProbeTemplate[SIR_ROAM_SCAN_MAX_PB_REQ_SIZE]; tANI_U16 us5GProbeTemplateLen; tANI_U8 p5GProbeTemplate[SIR_ROAM_SCAN_MAX_PB_REQ_SIZE]; - tANI_U8 ReservedBytes[SIR_ROAM_SCAN_RESERVED_BYTES]; /*This is to add any additional data in future - without changing the interface params on Host - and firmware.*/ + tANI_U8 ReservedBytes[SIR_ROAM_SCAN_RESERVED_BYTES]; + /*ReservedBytes is to add any further params in future + without changing the interface params on Host + and firmware.The firmware right now checks + if the size of this structure matches and then + proceeds with the processing of the command. + So, in future, if there is any need to add + more params, pick the memory from reserved + bytes and keep deducting the reserved bytes + by the amount of bytes picked.*/ + tANI_U8 nProbes; + tANI_U16 HomeAwayTime; tSirRoamNetworkType ConnectedNetwork; tSirMobilityDomainInfo MDID; } tSirRoamOffloadScanReq, *tpSirRoamOffloadScanReq; @@ -3517,12 +3553,18 @@ typedef struct { // Preferred Network Found Indication typedef struct { - tANI_U16 mesgType; - tANI_U16 mesgLen; + tANI_U16 mesgType; + tANI_U16 mesgLen; /* Network that was found with the highest RSSI*/ - tSirMacSSid ssId; + tSirMacSSid ssId; /* Indicates the RSSI */ - tANI_U8 rssi; + tANI_U8 rssi; + /* Length of the beacon or probe response + * corresponding to the candidate found by PNO */ + tANI_U32 frameLength; + /* Index to memory location where the contents of + * beacon or probe response frame will be copied */ + tANI_U8 data[1]; } tSirPrefNetworkFoundInd, *tpSirPrefNetworkFoundInd; #endif // FEATURE_WLAN_SCAN_PNO @@ -3559,6 +3601,9 @@ typedef struct /* Beacon Early Termination Interval */ tANI_U32 uBETInterval; + /* MAX LI for modulated DTIM */ + tANI_U32 uMaxLIModulatedDTIM; + }tSirSetPowerParamsReq, *tpSirSetPowerParamsReq; typedef struct sSirTxPerTrackingParam @@ -4049,12 +4094,4 @@ typedef struct sSirSmeCandidateFoundInd tANI_U8 sessionId; // Session Identifier } tSirSmeCandidateFoundInd, *tpSirSmeCandidateFoundInd; -#ifdef WLAN_FEATURE_11W -typedef struct sSirWlanExcludeUnencryptParam -{ - tANI_BOOLEAN excludeUnencrypt; - tSirMacAddr bssId; -}tSirWlanExcludeUnencryptParam,*tpSirWlanExcludeUnencryptParam; -#endif - #endif /* __SIR_API_H */ diff --git a/drivers/staging/prima/CORE/MAC/inc/sirMacProtDef.h b/drivers/staging/prima/CORE/MAC/inc/sirMacProtDef.h index 68121e595f7..cd548457338 100644 --- a/drivers/staging/prima/CORE/MAC/inc/sirMacProtDef.h +++ b/drivers/staging/prima/CORE/MAC/inc/sirMacProtDef.h @@ -38,8 +38,9 @@ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ + + /* - * Airgo Networks, Inc proprietary. All rights reserved. * This file sirMacProtDef.h contains the MAC/PHY protocol * definitions used across various projects. * Author: Chandra Modumudi @@ -261,9 +262,7 @@ #ifdef WLAN_FEATURE_11W //11w SA query request/response action frame category code -#define SIR_MAC_ACTION_SA_QUERY 8 -#define SIR_MAC_SA_QUERY_REQ 0 -#define SIR_MAC_SA_QUERY_RSP 1 +#define SIR_MAC_ACTION_SA_QUERY 8 #endif #ifdef FEATURE_WLAN_TDLS @@ -499,8 +498,10 @@ #define SIR_MAC_OUI_WSM_SCHEDULE_MAX 20 #ifdef WLAN_NS_OFFLOAD -#define SIR_MAC_NS_OFFLOAD_SIZE 1 //support only one IPv6 offload +#define SIR_MAC_NS_OFFLOAD_SIZE 1 //support only one IPv6 offload #define SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA 2 //Number of target IP in NA frames. It must be at least 2 +#define SIR_MAC_IPV6_ADDR_LEN 16 +#define SIR_IPV6_ADDR_VALID 1 #endif //WLAN_NS_OFFLOAD #define SIR_MAC_ARP_OFFLOAD_SIZE 1 @@ -629,6 +630,13 @@ #define SIR_MAC_CLEAR_CAPABILITY(u16value, bitname) \ ((u16value) &= (~(SIR_MAC_SET_##bitname(0)))) +#define IS_WES_MODE_ENABLED(x) \ + ((x)->roam.configParam.isWESModeEnabled) + +#define BA_RECIPIENT 1 +#define BA_INITIATOR 2 +#define BA_BOTH_DIRECTIONS 3 + /// Status Code (present in Management response frames) enum typedef enum eSirMacStatusCodes @@ -2328,6 +2336,14 @@ typedef __ani_attr_pre_packed struct sSirMacActionFrameHdr tANI_U8 actionID; } __ani_attr_packed tSirMacActionFrameHdr, *tpSirMacActionFrameHdr; +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR) +typedef __ani_attr_pre_packed struct sSirMacVendorSpecificFrameHdr +{ + tANI_U8 category; + tANI_U8 Oui[4]; +} __ani_attr_packed tSirMacVendorSpecificFrameHdr, *tpSirMacVendorSpecificFrameHdr; +#endif + typedef __ani_attr_pre_packed struct sSirMacVendorSpecificPublicActionFrameHdr { tANI_U8 category; diff --git a/drivers/staging/prima/CORE/MAC/inc/wniApi.h b/drivers/staging/prima/CORE/MAC/inc/wniApi.h index e3fd1b6258f..1388052e7b4 100644 --- a/drivers/staging/prima/CORE/MAC/inc/wniApi.h +++ b/drivers/staging/prima/CORE/MAC/inc/wniApi.h @@ -366,13 +366,10 @@ enum eWniMsgTypes #endif eWNI_SME_SET_BCN_FILTER_REQ, eWNI_SME_RESET_AP_CAPS_CHANGED, -#ifdef WLAN_FEATURE_11W - eWNI_SME_UNPROT_MGMT_FRM_IND, -#endif #ifdef WLAN_FEATURE_GTK_OFFLOAD eWNI_PMC_GTK_OFFLOAD_GETINFO_RSP, #endif // WLAN_FEATURE_GTK_OFFLOAD - + eWNI_SME_CANDIDATE_FOUND_IND, //ROAM candidate indication from FW eWNI_SME_MSG_TYPES_END }; diff --git a/drivers/staging/prima/CORE/MAC/inc/wniCfgAp.h b/drivers/staging/prima/CORE/MAC/inc/wniCfgAp.h index 96187e29524..615ff731050 100644 --- a/drivers/staging/prima/CORE/MAC/inc/wniCfgAp.h +++ b/drivers/staging/prima/CORE/MAC/inc/wniCfgAp.h @@ -290,75 +290,76 @@ #define WNI_CFG_MAX_BA_SESSIONS 225 #define WNI_CFG_BA_AUTO_SETUP 226 #define WNI_CFG_ADDBA_REQ_DECLINE 227 -#define WNI_CFG_BG_SCAN_CHANNEL_LIST 228 -#define WNI_CFG_MAX_MEDIUM_TIME 229 -#define WNI_CFG_MAX_MPDUS_IN_AMPDU 230 -#define WNI_CFG_IBSS_AUTO_BSSID 231 -#define WNI_CFG_PROBE_REQ_ADDNIE_FLAG 232 -#define WNI_CFG_PROBE_REQ_ADDNIE_DATA 233 -#define WNI_CFG_PROBE_RSP_ADDNIE_FLAG 234 -#define WNI_CFG_PROBE_RSP_ADDNIE_DATA1 235 -#define WNI_CFG_PROBE_RSP_ADDNIE_DATA2 236 -#define WNI_CFG_PROBE_RSP_ADDNIE_DATA3 237 -#define WNI_CFG_ASSOC_RSP_ADDNIE_FLAG 238 -#define WNI_CFG_ASSOC_RSP_ADDNIE_DATA 239 -#define WNI_CFG_PROBE_REQ_ADDNP2PIE_FLAG 240 -#define WNI_CFG_PROBE_REQ_ADDNP2PIE_DATA 241 -#define WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG 242 -#define WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA 243 -#define WNI_CFG_WPS_ENABLE 244 -#define WNI_CFG_WPS_STATE 245 -#define WNI_CFG_WPS_PROBE_REQ_FLAG 246 -#define WNI_CFG_WPS_VERSION 247 -#define WNI_CFG_WPS_REQUEST_TYPE 248 -#define WNI_CFG_WPS_CFG_METHOD 249 -#define WNI_CFG_WPS_UUID 250 -#define WNI_CFG_WPS_PRIMARY_DEVICE_CATEGORY 251 -#define WNI_CFG_WPS_PIMARY_DEVICE_OUI 252 -#define WNI_CFG_WPS_DEVICE_SUB_CATEGORY 253 -#define WNI_CFG_WPS_ASSOCIATION_STATE 254 -#define WNI_CFG_WPS_CONFIGURATION_ERROR 255 -#define WNI_CFG_WPS_DEVICE_PASSWORD_ID 256 -#define WNI_CFG_WPS_ASSOC_METHOD 257 -#define WNI_CFG_LOW_GAIN_OVERRIDE 258 -#define WNI_CFG_ENABLE_PHY_AGC_LISTEN_MODE 259 -#define WNI_CFG_RPE_POLLING_THRESHOLD 260 -#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC0_REG 261 -#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC1_REG 262 -#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC2_REG 263 -#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC3_REG 264 -#define WNI_CFG_NO_OF_ONCHIP_REORDER_SESSIONS 265 -#define WNI_CFG_SINGLE_TID_RC 266 -#define WNI_CFG_RRM_ENABLED 267 -#define WNI_CFG_RRM_OPERATING_CHAN_MAX 268 -#define WNI_CFG_RRM_NON_OPERATING_CHAN_MAX 269 -#define WNI_CFG_TX_PWR_CTRL_ENABLE 270 -#define WNI_CFG_MCAST_BCAST_FILTER_SETTING 271 -#define WNI_CFG_BTC_DHCP_BT_SLOTS_TO_BLOCK 272 -#define WNI_CFG_DYNAMIC_PS_POLL_VALUE 273 -#define WNI_CFG_PS_NULLDATA_AP_RESP_TIMEOUT 274 -#define WNI_CFG_TELE_BCN_WAKEUP_EN 275 -#define WNI_CFG_TELE_BCN_TRANS_LI 276 -#define WNI_CFG_TELE_BCN_TRANS_LI_IDLE_BCNS 277 -#define WNI_CFG_TELE_BCN_MAX_LI 278 -#define WNI_CFG_TELE_BCN_MAX_LI_IDLE_BCNS 279 -#define WNI_CFG_BTC_A2DP_DHCP_BT_SUB_INTERVALS 280 -#define WNI_CFG_INFRA_STA_KEEP_ALIVE_PERIOD 281 -#define WNI_CFG_ASSOC_STA_LIMIT 282 -#define WNI_CFG_SAP_CHANNEL_SELECT_START_CHANNEL 283 -#define WNI_CFG_SAP_CHANNEL_SELECT_END_CHANNEL 284 -#define WNI_CFG_SAP_CHANNEL_SELECT_OPERATING_BAND 285 -#define WNI_CFG_AP_DATA_AVAIL_POLL_PERIOD 286 -#define WNI_CFG_ENABLE_CLOSE_LOOP 287 -#define WNI_CFG_ENABLE_LTE_COEX 288 -#define WNI_CFG_AP_KEEP_ALIVE_TIMEOUT 289 -#define WNI_CFG_GO_KEEP_ALIVE_TIMEOUT 290 -#define WNI_CFG_ENABLE_MC_ADDR_LIST 291 -#define WNI_CFG_ENABLE_UC_FILTER 292 -#define WNI_CFG_ENABLE_LPWR_IMG_TRANSITION 293 -#define WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED 294 -#define WNI_CFG_DISABLE_LDPC_WITH_TXBF_AP 295 -#define WNI_CFG_AP_LINK_MONITOR_TIMEOUT 296 +#define WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC 228 +#define WNI_CFG_BG_SCAN_CHANNEL_LIST 229 +#define WNI_CFG_MAX_MEDIUM_TIME 230 +#define WNI_CFG_MAX_MPDUS_IN_AMPDU 231 +#define WNI_CFG_IBSS_AUTO_BSSID 232 +#define WNI_CFG_PROBE_REQ_ADDNIE_FLAG 233 +#define WNI_CFG_PROBE_REQ_ADDNIE_DATA 234 +#define WNI_CFG_PROBE_RSP_ADDNIE_FLAG 235 +#define WNI_CFG_PROBE_RSP_ADDNIE_DATA1 236 +#define WNI_CFG_PROBE_RSP_ADDNIE_DATA2 237 +#define WNI_CFG_PROBE_RSP_ADDNIE_DATA3 238 +#define WNI_CFG_ASSOC_RSP_ADDNIE_FLAG 239 +#define WNI_CFG_ASSOC_RSP_ADDNIE_DATA 240 +#define WNI_CFG_PROBE_REQ_ADDNP2PIE_FLAG 241 +#define WNI_CFG_PROBE_REQ_ADDNP2PIE_DATA 242 +#define WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG 243 +#define WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA 244 +#define WNI_CFG_WPS_ENABLE 245 +#define WNI_CFG_WPS_STATE 246 +#define WNI_CFG_WPS_PROBE_REQ_FLAG 247 +#define WNI_CFG_WPS_VERSION 248 +#define WNI_CFG_WPS_REQUEST_TYPE 249 +#define WNI_CFG_WPS_CFG_METHOD 250 +#define WNI_CFG_WPS_UUID 251 +#define WNI_CFG_WPS_PRIMARY_DEVICE_CATEGORY 252 +#define WNI_CFG_WPS_PIMARY_DEVICE_OUI 253 +#define WNI_CFG_WPS_DEVICE_SUB_CATEGORY 254 +#define WNI_CFG_WPS_ASSOCIATION_STATE 255 +#define WNI_CFG_WPS_CONFIGURATION_ERROR 256 +#define WNI_CFG_WPS_DEVICE_PASSWORD_ID 257 +#define WNI_CFG_WPS_ASSOC_METHOD 258 +#define WNI_CFG_LOW_GAIN_OVERRIDE 259 +#define WNI_CFG_ENABLE_PHY_AGC_LISTEN_MODE 260 +#define WNI_CFG_RPE_POLLING_THRESHOLD 261 +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC0_REG 262 +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC1_REG 263 +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC2_REG 264 +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC3_REG 265 +#define WNI_CFG_NO_OF_ONCHIP_REORDER_SESSIONS 266 +#define WNI_CFG_SINGLE_TID_RC 267 +#define WNI_CFG_RRM_ENABLED 268 +#define WNI_CFG_RRM_OPERATING_CHAN_MAX 269 +#define WNI_CFG_RRM_NON_OPERATING_CHAN_MAX 270 +#define WNI_CFG_TX_PWR_CTRL_ENABLE 271 +#define WNI_CFG_MCAST_BCAST_FILTER_SETTING 272 +#define WNI_CFG_BTC_DHCP_BT_SLOTS_TO_BLOCK 273 +#define WNI_CFG_DYNAMIC_PS_POLL_VALUE 274 +#define WNI_CFG_PS_NULLDATA_AP_RESP_TIMEOUT 275 +#define WNI_CFG_TELE_BCN_WAKEUP_EN 276 +#define WNI_CFG_TELE_BCN_TRANS_LI 277 +#define WNI_CFG_TELE_BCN_TRANS_LI_IDLE_BCNS 278 +#define WNI_CFG_TELE_BCN_MAX_LI 279 +#define WNI_CFG_TELE_BCN_MAX_LI_IDLE_BCNS 280 +#define WNI_CFG_BTC_A2DP_DHCP_BT_SUB_INTERVALS 281 +#define WNI_CFG_INFRA_STA_KEEP_ALIVE_PERIOD 282 +#define WNI_CFG_ASSOC_STA_LIMIT 283 +#define WNI_CFG_SAP_CHANNEL_SELECT_START_CHANNEL 284 +#define WNI_CFG_SAP_CHANNEL_SELECT_END_CHANNEL 285 +#define WNI_CFG_SAP_CHANNEL_SELECT_OPERATING_BAND 286 +#define WNI_CFG_AP_DATA_AVAIL_POLL_PERIOD 287 +#define WNI_CFG_ENABLE_CLOSE_LOOP 288 +#define WNI_CFG_ENABLE_LTE_COEX 289 +#define WNI_CFG_AP_KEEP_ALIVE_TIMEOUT 290 +#define WNI_CFG_GO_KEEP_ALIVE_TIMEOUT 291 +#define WNI_CFG_ENABLE_MC_ADDR_LIST 292 +#define WNI_CFG_ENABLE_UC_FILTER 293 +#define WNI_CFG_ENABLE_LPWR_IMG_TRANSITION 294 +#define WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED 295 +#define WNI_CFG_DISABLE_LDPC_WITH_TXBF_AP 296 +#define WNI_CFG_AP_LINK_MONITOR_TIMEOUT 297 /* * String parameter lengths @@ -2002,6 +2003,14 @@ #define WNI_CFG_ADDBA_REQ_DECLINE_APMAX 255 #define WNI_CFG_ADDBA_REQ_DECLINE_APDEF 0 +#define WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC_STAMIN 0 +#define WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC_STAMAX 1 +#define WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC_STADEF 0 + +#define WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC_APMIN 0 +#define WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC_APMAX 1 +#define WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC_APDEF 0 + #define WNI_CFG_MAX_MEDIUM_TIME_STAMIN 0 #define WNI_CFG_MAX_MEDIUM_TIME_STAMAX 65535 #define WNI_CFG_MAX_MEDIUM_TIME_STADEF 2048 @@ -2477,10 +2486,10 @@ #define WNI_CFG_AP_LINK_MONITOR_TIMEOUT_APMAX 255 #define WNI_CFG_AP_LINK_MONITOR_TIMEOUT_APDEF 3 -#define CFG_PARAM_MAX_NUM 297 -#define CFG_AP_IBUF_MAX_SIZE 236 +#define CFG_PARAM_MAX_NUM 298 +#define CFG_AP_IBUF_MAX_SIZE 237 #define CFG_AP_SBUF_MAX_SIZE 3422 -#define CFG_STA_IBUF_MAX_SIZE 231 +#define CFG_STA_IBUF_MAX_SIZE 232 #define CFG_STA_SBUF_MAX_SIZE 3388 #define CFG_SEM_MAX_NUM 19 diff --git a/drivers/staging/prima/CORE/MAC/inc/wniCfgSta.h b/drivers/staging/prima/CORE/MAC/inc/wniCfgSta.h index 571d55977e3..4d1e31a012d 100644 --- a/drivers/staging/prima/CORE/MAC/inc/wniCfgSta.h +++ b/drivers/staging/prima/CORE/MAC/inc/wniCfgSta.h @@ -284,75 +284,76 @@ #define WNI_CFG_MAX_BA_SESSIONS 225 #define WNI_CFG_BA_AUTO_SETUP 226 #define WNI_CFG_ADDBA_REQ_DECLINE 227 -#define WNI_CFG_BG_SCAN_CHANNEL_LIST 228 -#define WNI_CFG_MAX_MEDIUM_TIME 229 -#define WNI_CFG_MAX_MPDUS_IN_AMPDU 230 -#define WNI_CFG_IBSS_AUTO_BSSID 231 -#define WNI_CFG_PROBE_REQ_ADDNIE_FLAG 232 -#define WNI_CFG_PROBE_REQ_ADDNIE_DATA 233 -#define WNI_CFG_PROBE_RSP_ADDNIE_FLAG 234 -#define WNI_CFG_PROBE_RSP_ADDNIE_DATA1 235 -#define WNI_CFG_PROBE_RSP_ADDNIE_DATA2 236 -#define WNI_CFG_PROBE_RSP_ADDNIE_DATA3 237 -#define WNI_CFG_ASSOC_RSP_ADDNIE_FLAG 238 -#define WNI_CFG_ASSOC_RSP_ADDNIE_DATA 239 -#define WNI_CFG_PROBE_REQ_ADDNP2PIE_FLAG 240 -#define WNI_CFG_PROBE_REQ_ADDNP2PIE_DATA 241 -#define WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG 242 -#define WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA 243 -#define WNI_CFG_WPS_ENABLE 244 -#define WNI_CFG_WPS_STATE 245 -#define WNI_CFG_WPS_PROBE_REQ_FLAG 246 -#define WNI_CFG_WPS_VERSION 247 -#define WNI_CFG_WPS_REQUEST_TYPE 248 -#define WNI_CFG_WPS_CFG_METHOD 249 -#define WNI_CFG_WPS_UUID 250 -#define WNI_CFG_WPS_PRIMARY_DEVICE_CATEGORY 251 -#define WNI_CFG_WPS_PIMARY_DEVICE_OUI 252 -#define WNI_CFG_WPS_DEVICE_SUB_CATEGORY 253 -#define WNI_CFG_WPS_ASSOCIATION_STATE 254 -#define WNI_CFG_WPS_CONFIGURATION_ERROR 255 -#define WNI_CFG_WPS_DEVICE_PASSWORD_ID 256 -#define WNI_CFG_WPS_ASSOC_METHOD 257 -#define WNI_CFG_LOW_GAIN_OVERRIDE 258 -#define WNI_CFG_ENABLE_PHY_AGC_LISTEN_MODE 259 -#define WNI_CFG_RPE_POLLING_THRESHOLD 260 -#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC0_REG 261 -#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC1_REG 262 -#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC2_REG 263 -#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC3_REG 264 -#define WNI_CFG_NO_OF_ONCHIP_REORDER_SESSIONS 265 -#define WNI_CFG_SINGLE_TID_RC 266 -#define WNI_CFG_RRM_ENABLED 267 -#define WNI_CFG_RRM_OPERATING_CHAN_MAX 268 -#define WNI_CFG_RRM_NON_OPERATING_CHAN_MAX 269 -#define WNI_CFG_TX_PWR_CTRL_ENABLE 270 -#define WNI_CFG_MCAST_BCAST_FILTER_SETTING 271 -#define WNI_CFG_BTC_DHCP_BT_SLOTS_TO_BLOCK 272 -#define WNI_CFG_DYNAMIC_PS_POLL_VALUE 273 -#define WNI_CFG_PS_NULLDATA_AP_RESP_TIMEOUT 274 -#define WNI_CFG_TELE_BCN_WAKEUP_EN 275 -#define WNI_CFG_TELE_BCN_TRANS_LI 276 -#define WNI_CFG_TELE_BCN_TRANS_LI_IDLE_BCNS 277 -#define WNI_CFG_TELE_BCN_MAX_LI 278 -#define WNI_CFG_TELE_BCN_MAX_LI_IDLE_BCNS 279 -#define WNI_CFG_BTC_A2DP_DHCP_BT_SUB_INTERVALS 280 -#define WNI_CFG_INFRA_STA_KEEP_ALIVE_PERIOD 281 -#define WNI_CFG_ASSOC_STA_LIMIT 282 -#define WNI_CFG_SAP_CHANNEL_SELECT_START_CHANNEL 283 -#define WNI_CFG_SAP_CHANNEL_SELECT_END_CHANNEL 284 -#define WNI_CFG_SAP_CHANNEL_SELECT_OPERATING_BAND 285 -#define WNI_CFG_AP_DATA_AVAIL_POLL_PERIOD 286 -#define WNI_CFG_ENABLE_CLOSE_LOOP 287 -#define WNI_CFG_ENABLE_LTE_COEX 288 -#define WNI_CFG_AP_KEEP_ALIVE_TIMEOUT 289 -#define WNI_CFG_GO_KEEP_ALIVE_TIMEOUT 290 -#define WNI_CFG_ENABLE_MC_ADDR_LIST 291 -#define WNI_CFG_ENABLE_UC_FILTER 292 -#define WNI_CFG_ENABLE_LPWR_IMG_TRANSITION 293 -#define WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED 294 -#define WNI_CFG_DISABLE_LDPC_WITH_TXBF_AP 295 -#define WNI_CFG_AP_LINK_MONITOR_TIMEOUT 296 +#define WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC 228 +#define WNI_CFG_BG_SCAN_CHANNEL_LIST 229 +#define WNI_CFG_MAX_MEDIUM_TIME 230 +#define WNI_CFG_MAX_MPDUS_IN_AMPDU 231 +#define WNI_CFG_IBSS_AUTO_BSSID 232 +#define WNI_CFG_PROBE_REQ_ADDNIE_FLAG 233 +#define WNI_CFG_PROBE_REQ_ADDNIE_DATA 234 +#define WNI_CFG_PROBE_RSP_ADDNIE_FLAG 235 +#define WNI_CFG_PROBE_RSP_ADDNIE_DATA1 236 +#define WNI_CFG_PROBE_RSP_ADDNIE_DATA2 237 +#define WNI_CFG_PROBE_RSP_ADDNIE_DATA3 238 +#define WNI_CFG_ASSOC_RSP_ADDNIE_FLAG 239 +#define WNI_CFG_ASSOC_RSP_ADDNIE_DATA 240 +#define WNI_CFG_PROBE_REQ_ADDNP2PIE_FLAG 241 +#define WNI_CFG_PROBE_REQ_ADDNP2PIE_DATA 242 +#define WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG 243 +#define WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA 244 +#define WNI_CFG_WPS_ENABLE 245 +#define WNI_CFG_WPS_STATE 246 +#define WNI_CFG_WPS_PROBE_REQ_FLAG 247 +#define WNI_CFG_WPS_VERSION 248 +#define WNI_CFG_WPS_REQUEST_TYPE 249 +#define WNI_CFG_WPS_CFG_METHOD 250 +#define WNI_CFG_WPS_UUID 251 +#define WNI_CFG_WPS_PRIMARY_DEVICE_CATEGORY 252 +#define WNI_CFG_WPS_PIMARY_DEVICE_OUI 253 +#define WNI_CFG_WPS_DEVICE_SUB_CATEGORY 254 +#define WNI_CFG_WPS_ASSOCIATION_STATE 255 +#define WNI_CFG_WPS_CONFIGURATION_ERROR 256 +#define WNI_CFG_WPS_DEVICE_PASSWORD_ID 257 +#define WNI_CFG_WPS_ASSOC_METHOD 258 +#define WNI_CFG_LOW_GAIN_OVERRIDE 259 +#define WNI_CFG_ENABLE_PHY_AGC_LISTEN_MODE 260 +#define WNI_CFG_RPE_POLLING_THRESHOLD 261 +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC0_REG 262 +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC1_REG 263 +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC2_REG 264 +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC3_REG 265 +#define WNI_CFG_NO_OF_ONCHIP_REORDER_SESSIONS 266 +#define WNI_CFG_SINGLE_TID_RC 267 +#define WNI_CFG_RRM_ENABLED 268 +#define WNI_CFG_RRM_OPERATING_CHAN_MAX 269 +#define WNI_CFG_RRM_NON_OPERATING_CHAN_MAX 270 +#define WNI_CFG_TX_PWR_CTRL_ENABLE 271 +#define WNI_CFG_MCAST_BCAST_FILTER_SETTING 272 +#define WNI_CFG_BTC_DHCP_BT_SLOTS_TO_BLOCK 273 +#define WNI_CFG_DYNAMIC_PS_POLL_VALUE 274 +#define WNI_CFG_PS_NULLDATA_AP_RESP_TIMEOUT 275 +#define WNI_CFG_TELE_BCN_WAKEUP_EN 276 +#define WNI_CFG_TELE_BCN_TRANS_LI 277 +#define WNI_CFG_TELE_BCN_TRANS_LI_IDLE_BCNS 278 +#define WNI_CFG_TELE_BCN_MAX_LI 279 +#define WNI_CFG_TELE_BCN_MAX_LI_IDLE_BCNS 280 +#define WNI_CFG_BTC_A2DP_DHCP_BT_SUB_INTERVALS 281 +#define WNI_CFG_INFRA_STA_KEEP_ALIVE_PERIOD 282 +#define WNI_CFG_ASSOC_STA_LIMIT 283 +#define WNI_CFG_SAP_CHANNEL_SELECT_START_CHANNEL 284 +#define WNI_CFG_SAP_CHANNEL_SELECT_END_CHANNEL 285 +#define WNI_CFG_SAP_CHANNEL_SELECT_OPERATING_BAND 286 +#define WNI_CFG_AP_DATA_AVAIL_POLL_PERIOD 287 +#define WNI_CFG_ENABLE_CLOSE_LOOP 288 +#define WNI_CFG_ENABLE_LTE_COEX 289 +#define WNI_CFG_AP_KEEP_ALIVE_TIMEOUT 290 +#define WNI_CFG_GO_KEEP_ALIVE_TIMEOUT 291 +#define WNI_CFG_ENABLE_MC_ADDR_LIST 292 +#define WNI_CFG_ENABLE_UC_FILTER 293 +#define WNI_CFG_ENABLE_LPWR_IMG_TRANSITION 294 +#define WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED 295 +#define WNI_CFG_DISABLE_LDPC_WITH_TXBF_AP 296 +#define WNI_CFG_AP_LINK_MONITOR_TIMEOUT 297 /* * String parameter lengths @@ -1367,6 +1368,10 @@ #define WNI_CFG_ADDBA_REQ_DECLINE_STAMAX 255 #define WNI_CFG_ADDBA_REQ_DECLINE_STADEF 0 +#define WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC_STAMIN 0 +#define WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC_STAMAX 1 +#define WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC_STADEF 0 + #define WNI_CFG_MAX_MEDIUM_TIME_STAMIN 0 #define WNI_CFG_MAX_MEDIUM_TIME_STAMAX 65535 #define WNI_CFG_MAX_MEDIUM_TIME_STADEF 2048 @@ -1610,8 +1615,8 @@ #define WNI_CFG_AP_LINK_MONITOR_TIMEOUT_STAMAX 255 #define WNI_CFG_AP_LINK_MONITOR_TIMEOUT_STADEF 3 -#define CFG_PARAM_MAX_NUM 297 -#define CFG_STA_IBUF_MAX_SIZE 231 +#define CFG_PARAM_MAX_NUM 298 +#define CFG_STA_IBUF_MAX_SIZE 232 #define CFG_STA_SBUF_MAX_SIZE 3388 #define CFG_SEM_MAX_NUM 19 diff --git a/drivers/staging/prima/CORE/MAC/src/cfg/cfgApi.c b/drivers/staging/prima/CORE/MAC/src/cfg/cfgApi.c index 14b78a4c02f..86fe42c46a3 100644 --- a/drivers/staging/prima/CORE/MAC/src/cfg/cfgApi.c +++ b/drivers/staging/prima/CORE/MAC/src/cfg/cfgApi.c @@ -74,12 +74,22 @@ static void Notify(tpAniSirGlobal, tANI_U16, tANI_U32); // --------------------------------------------------------------------- tANI_U32 cfgNeedRestart(tpAniSirGlobal pMac, tANI_U16 cfgId) { + if (!pMac->cfg.gCfgEntry) + { + PELOGE(cfgLog(pMac, LOGE, FL("gCfgEntry is NULL"));) + return 0; + } return !!(pMac->cfg.gCfgEntry[cfgId].control & CFG_CTL_RESTART) ; } // --------------------------------------------------------------------- tANI_U32 cfgNeedReload(tpAniSirGlobal pMac, tANI_U16 cfgId) { + if (!pMac->cfg.gCfgEntry) + { + PELOGE(cfgLog(pMac, LOGE, FL("gCfgEntry is NULL"));) + return 0; + } return !!(pMac->cfg.gCfgEntry[cfgId].control & CFG_CTL_RELOAD) ; } @@ -184,6 +194,12 @@ cfgSetInt(tpAniSirGlobal pMac, tANI_U16 cfgId, tANI_U32 value) return eSIR_CFG_INVALID_ID; } + if (!pMac->cfg.gCfgEntry) + { + PELOGE(cfgLog(pMac, LOGE, FL("gCfgEntry is NULL"));) + return eSIR_CFG_INVALID_ID; + } + control = pMac->cfg.gCfgEntry[cfgId].control; index = control & CFG_BUF_INDX_MASK; retVal = eSIR_SUCCESS; @@ -259,6 +275,12 @@ cfgCheckValid(tpAniSirGlobal pMac, tANI_U16 cfgId) return(eSIR_CFG_INVALID_ID); } + if (!pMac->cfg.gCfgEntry) + { + PELOGE(cfgLog(pMac, LOGE, FL("gCfgEntry is NULL"));) + return eSIR_CFG_INVALID_ID; + } + control = pMac->cfg.gCfgEntry[cfgId].control; // Check if parameter is valid @@ -306,6 +328,12 @@ wlan_cfgGetInt(tpAniSirGlobal pMac, tANI_U16 cfgId, tANI_U32 *pValue) return retVal; } + if (!pMac->cfg.gCfgEntry) + { + PELOGE(cfgLog(pMac, LOGE, FL("gCfgEntry is NULL"));) + return eSIR_CFG_INVALID_ID; + } + control = pMac->cfg.gCfgEntry[cfgId].control; index = control & CFG_BUF_INDX_MASK; retVal = eSIR_SUCCESS; @@ -370,6 +398,12 @@ cfgIncrementInt(tpAniSirGlobal pMac, tANI_U16 cfgId, tANI_U32 value) retVal = eSIR_CFG_INVALID_ID; } + if (!pMac->cfg.gCfgEntry) + { + PELOGE(cfgLog(pMac, LOGE, FL("gCfgEntry is NULL"));) + return eSIR_CFG_INVALID_ID; + } + control = pMac->cfg.gCfgEntry[cfgId].control; index = control & CFG_BUF_INDX_MASK; retVal = eSIR_SUCCESS; @@ -468,6 +502,12 @@ cfgSetStrNotify(tpAniSirGlobal pMac, tANI_U16 cfgId, tANI_U8 *pStr, return eSIR_CFG_INVALID_ID; } + if (!pMac->cfg.gCfgEntry) + { + PELOGE(cfgLog(pMac, LOGE, FL("gCfgEntry is NULL"));) + return eSIR_CFG_INVALID_ID; + } + control = pMac->cfg.gCfgEntry[cfgId].control; index = control & CFG_BUF_INDX_MASK; retVal = eSIR_SUCCESS; @@ -648,6 +688,12 @@ wlan_cfgGetStrMaxLen(tpAniSirGlobal pMac, tANI_U16 cfgId, tANI_U32 *pLength) retVal = eSIR_CFG_INVALID_ID; } + if (!pMac->cfg.gCfgEntry) + { + PELOGE(cfgLog(pMac, LOGE, FL("gCfgEntry is NULL"));) + return eSIR_CFG_INVALID_ID; + } + control = pMac->cfg.gCfgEntry[cfgId].control; index = control & CFG_BUF_INDX_MASK; retVal = eSIR_SUCCESS; @@ -709,6 +755,12 @@ wlan_cfgGetStrLen(tpAniSirGlobal pMac, tANI_U16 cfgId, tANI_U32 *pLength) retVal = eSIR_CFG_INVALID_ID; } + if (!pMac->cfg.gCfgEntry) + { + PELOGE(cfgLog(pMac, LOGE, FL("gCfgEntry is NULL"));) + return eSIR_CFG_INVALID_ID; + } + control = pMac->cfg.gCfgEntry[cfgId].control; index = control & CFG_BUF_INDX_MASK; retVal = eSIR_SUCCESS; diff --git a/drivers/staging/prima/CORE/MAC/src/cfg/cfgUtil/cfg.txt b/drivers/staging/prima/CORE/MAC/src/cfg/cfgUtil/cfg.txt index 463bdd08b44..7240b7db62f 100644 --- a/drivers/staging/prima/CORE/MAC/src/cfg/cfgUtil/cfg.txt +++ b/drivers/staging/prima/CORE/MAC/src/cfg/cfgUtil/cfg.txt @@ -3459,6 +3459,19 @@ V RW NP RESTART LIM 0 0xff 0 +* +* Delete all Rx BA sessions in 2.4 GHz +* when BTC requests to disable agg. +* +WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC I 4 7 +V RW NP +LIM +0 1 0 +V RW NP +LIM +0 1 0 + + * * Valid Channel List * diff --git a/drivers/staging/prima/CORE/MAC/src/include/dot11f.h b/drivers/staging/prima/CORE/MAC/src/include/dot11f.h index 7bedcd4d5a0..c367f5290c2 100644 --- a/drivers/staging/prima/CORE/MAC/src/include/dot11f.h +++ b/drivers/staging/prima/CORE/MAC/src/include/dot11f.h @@ -52,7 +52,7 @@ * * * This file was automatically generated by 'framesc' - * Tue Mar 19 13:37:40 2013 from the following file(s): + * Fri Jun 7 17:41:21 2013 from the following file(s): * * dot11f.frms * @@ -549,16 +549,6 @@ void dot11fUnpackFfTimeStamp(tpAniSirGlobal, tANI_U8*, tDot11fFfTimeStamp*); void dot11fPackFfTimeStamp(tpAniSirGlobal, tDot11fFfTimeStamp*, tANI_U8*); -typedef struct sDot11fFfTransactionId { - tANI_U8 transId[2]; -} tDot11fFfTransactionId; - -#define DOT11F_FF_TRANSACTIONID_LEN ( 2 ) - -void dot11fUnpackFfTransactionId(tpAniSirGlobal, tANI_U8*, tDot11fFfTransactionId*); - -void dot11fPackFfTransactionId(tpAniSirGlobal, tDot11fFfTransactionId*, tANI_U8*); - typedef struct sDot11fFfTxAntennaId { tANI_U8 antennaId; } tDot11fFfTxAntennaId; @@ -1848,6 +1838,34 @@ tANI_U32 dot11fPackIeHCF(tpAniSirGlobal, tDot11fIEHCF*, tANI_U8*, tANI_U32, tANI tANI_U32 dot11fGetPackedIEHCF(tpAniSirGlobal, tDot11fIEHCF*, tANI_U32*); +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 4 (0x04) +typedef struct sDot11fIEIGTK { + tANI_U8 present; + tANI_U8 keyID[2]; + tANI_U8 IPN[6]; + tANI_U8 keyLength; + tANI_U8 key[24]; +} tDot11fIEIGTK; + +#define DOT11F_EID_IGTK ( 4 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_IGTK_MIN_LEN ( 33 ) + +#define DOT11F_IE_IGTK_MAX_LEN ( 33 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeIGTK(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEIGTK*); + +tANI_U32 dot11fPackIeIGTK(tpAniSirGlobal, tDot11fIEIGTK*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEIGTK(tpAniSirGlobal, tDot11fIEIGTK*, tANI_U32*); + #ifdef __cplusplus }; /* End extern "C". */ #endif /* C++ */ @@ -3702,6 +3720,7 @@ typedef struct sDot11fIEFTInfo { tDot11fIER1KH_ID R1KH_ID; tDot11fIEGTK GTK; tDot11fIER0KH_ID R0KH_ID; + tDot11fIEIGTK IGTK; } tDot11fIEFTInfo; #define DOT11F_EID_FTINFO ( 55 ) @@ -3709,7 +3728,7 @@ typedef struct sDot11fIEFTInfo { // N.B. These #defines do *not* include the EID & length #define DOT11F_IE_FTINFO_MIN_LEN ( 82 ) -#define DOT11F_IE_FTINFO_MAX_LEN ( 185 ) +#define DOT11F_IE_FTINFO_MAX_LEN ( 220 ) #ifdef __cplusplus extern "C" { @@ -4884,11 +4903,11 @@ tANI_U32 dot11fGetPackedIEQBSSLoad(tpAniSirGlobal, tDot11fIEQBSSLoad*, tANI_U32* // EID 46 (0x2e) typedef struct sDot11fIEQOSCapsAp { tANI_U8 present; - tANI_U8 reserved: 1; - tANI_U8 txopreq: 1; - tANI_U8 qreq: 1; - tANI_U8 qack: 1; tANI_U8 count: 4; + tANI_U8 qack: 1; + tANI_U8 qreq: 1; + tANI_U8 txopreq: 1; + tANI_U8 reserved: 1; } tDot11fIEQOSCapsAp; #define DOT11F_EID_QOSCAPSAP ( 46 ) @@ -4913,13 +4932,13 @@ tANI_U32 dot11fGetPackedIEQOSCapsAp(tpAniSirGlobal, tDot11fIEQOSCapsAp*, tANI_U3 // EID 46 (0x2e) typedef struct sDot11fIEQOSCapsStation { tANI_U8 present; - tANI_U8 more_data_ack: 1; - tANI_U8 max_sp_length: 2; - tANI_U8 qack: 1; - tANI_U8 acbe_uapsd: 1; - tANI_U8 acbk_uapsd: 1; - tANI_U8 acvi_uapsd: 1; tANI_U8 acvo_uapsd: 1; + tANI_U8 acvi_uapsd: 1; + tANI_U8 acbk_uapsd: 1; + tANI_U8 acbe_uapsd: 1; + tANI_U8 qack: 1; + tANI_U8 max_sp_length: 2; + tANI_U8 more_data_ack: 1; } tDot11fIEQOSCapsStation; #define DOT11F_EID_QOSCAPSSTATION ( 46 ) @@ -7243,26 +7262,6 @@ tANI_U32 dot11fGetPackedSMPowerSaveSize(tpAniSirGlobal pCtx, tDot11fSMPowerSave } /* End extern "C". */ #endif /* C++ */ -typedef struct sDot11fSaQueryRsp{ - tDot11fFfCategory Category; - tDot11fFfAction Action; - tDot11fFfTransactionId TransactionId; -} tDot11fSaQueryRsp; - -#define DOT11F_SAQUERYRSP ( 44 ) - -#ifdef __cplusplus -extern "C" { -#endif /* C++ */ - -tANI_U32 dot11fUnpackSaQueryRsp(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fSaQueryRsp *pFrm); -tANI_U32 dot11fPackSaQueryRsp(tpAniSirGlobal pCtx, tDot11fSaQueryRsp *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); -tANI_U32 dot11fGetPackedSaQueryRspSize(tpAniSirGlobal pCtx, tDot11fSaQueryRsp *pFrm, tANI_U32 *pnNeeded); - -#ifdef __cplusplus -} /* End extern "C". */ -#endif /* C++ */ - typedef struct sDot11fTDLSDisReq{ tDot11fFfCategory Category; tDot11fFfAction Action; @@ -7270,7 +7269,7 @@ typedef struct sDot11fTDLSDisReq{ tDot11fIELinkIdentifier LinkIdentifier; } tDot11fTDLSDisReq; -#define DOT11F_TDLSDISREQ ( 45 ) +#define DOT11F_TDLSDISREQ ( 44 ) #ifdef __cplusplus extern "C" { @@ -7302,7 +7301,7 @@ typedef struct sDot11fTDLSDisRsp{ tDot11fIEVHTCaps VHTCaps; } tDot11fTDLSDisRsp; -#define DOT11F_TDLSDISRSP ( 46 ) +#define DOT11F_TDLSDISRSP ( 45 ) #ifdef __cplusplus extern "C" { @@ -7325,7 +7324,7 @@ typedef struct sDot11fTDLSPeerTrafficInd{ tDot11fIEPUBufferStatus PUBufferStatus; } tDot11fTDLSPeerTrafficInd; -#define DOT11F_TDLSPEERTRAFFICIND ( 47 ) +#define DOT11F_TDLSPEERTRAFFICIND ( 46 ) #ifdef __cplusplus extern "C" { @@ -7346,7 +7345,7 @@ typedef struct sDot11fTDLSPeerTrafficRsp{ tDot11fIELinkIdentifier LinkIdentifier; } tDot11fTDLSPeerTrafficRsp; -#define DOT11F_TDLSPEERTRAFFICRSP ( 48 ) +#define DOT11F_TDLSPEERTRAFFICRSP ( 47 ) #ifdef __cplusplus extern "C" { @@ -7373,9 +7372,10 @@ typedef struct sDot11fTDLSSetupCnf{ tDot11fIELinkIdentifier LinkIdentifier; tDot11fIEWMMInfoStation WMMInfoStation; tDot11fIEVHTOperation VHTOperation; + tDot11fIEOperatingMode OperatingMode; } tDot11fTDLSSetupCnf; -#define DOT11F_TDLSSETUPCNF ( 49 ) +#define DOT11F_TDLSSETUPCNF ( 48 ) #ifdef __cplusplus extern "C" { @@ -7411,7 +7411,7 @@ typedef struct sDot11fTDLSSetupReq{ tDot11fIEVHTCaps VHTCaps; } tDot11fTDLSSetupReq; -#define DOT11F_TDLSSETUPREQ ( 50 ) +#define DOT11F_TDLSSETUPREQ ( 49 ) #ifdef __cplusplus extern "C" { @@ -7446,9 +7446,10 @@ typedef struct sDot11fTDLSSetupRsp{ tDot11fIEWMMInfoStation WMMInfoStation; tDot11fIEAID AID; tDot11fIEVHTCaps VHTCaps; + tDot11fIEOperatingMode OperatingMode; } tDot11fTDLSSetupRsp; -#define DOT11F_TDLSSETUPRSP ( 51 ) +#define DOT11F_TDLSSETUPRSP ( 50 ) #ifdef __cplusplus extern "C" { @@ -7470,7 +7471,7 @@ typedef struct sDot11fTDLSTeardown{ tDot11fIELinkIdentifier LinkIdentifier; } tDot11fTDLSTeardown; -#define DOT11F_TDLSTEARDOWN ( 52 ) +#define DOT11F_TDLSTEARDOWN ( 51 ) #ifdef __cplusplus extern "C" { @@ -7491,7 +7492,7 @@ typedef struct sDot11fTPCReport{ tDot11fIETPCReport TPCReport; } tDot11fTPCReport; -#define DOT11F_TPCREPORT ( 53 ) +#define DOT11F_TPCREPORT ( 52 ) #ifdef __cplusplus extern "C" { @@ -7512,7 +7513,7 @@ typedef struct sDot11fTPCRequest{ tDot11fIETPCRequest TPCRequest; } tDot11fTPCRequest; -#define DOT11F_TPCREQUEST ( 54 ) +#define DOT11F_TPCREQUEST ( 53 ) #ifdef __cplusplus extern "C" { @@ -7535,7 +7536,7 @@ typedef struct sDot11fWMMAddTSRequest{ tDot11fIECCXTrafStrmRateSet CCXTrafStrmRateSet; } tDot11fWMMAddTSRequest; -#define DOT11F_WMMADDTSREQUEST ( 55 ) +#define DOT11F_WMMADDTSREQUEST ( 54 ) #ifdef __cplusplus extern "C" { @@ -7558,7 +7559,7 @@ typedef struct sDot11fWMMAddTSResponse{ tDot11fIECCXTrafStrmMet CCXTrafStrmMet; } tDot11fWMMAddTSResponse; -#define DOT11F_WMMADDTSRESPONSE ( 56 ) +#define DOT11F_WMMADDTSRESPONSE ( 55 ) #ifdef __cplusplus extern "C" { @@ -7580,7 +7581,7 @@ typedef struct sDot11fWMMDelTS{ tDot11fIEWMMTSPEC WMMTSPEC; } tDot11fWMMDelTS; -#define DOT11F_WMMDELTS ( 57 ) +#define DOT11F_WMMDELTS ( 56 ) #ifdef __cplusplus extern "C" { diff --git a/drivers/staging/prima/CORE/MAC/src/include/dphGlobal.h b/drivers/staging/prima/CORE/MAC/src/include/dphGlobal.h index d1e01073d44..91bb281d2dc 100644 --- a/drivers/staging/prima/CORE/MAC/src/include/dphGlobal.h +++ b/drivers/staging/prima/CORE/MAC/src/include/dphGlobal.h @@ -387,7 +387,9 @@ typedef struct sDphHashNode tANI_U8 fAniCount:1; - tANI_U8 rmfEnabled:1; + + tANI_U8 rsvd:1; + /// Fragmentation size diff --git a/drivers/staging/prima/CORE/MAC/src/include/sirParams.h b/drivers/staging/prima/CORE/MAC/src/include/sirParams.h index 287fbb51fdf..f539fb274f5 100644 --- a/drivers/staging/prima/CORE/MAC/src/include/sirParams.h +++ b/drivers/staging/prima/CORE/MAC/src/include/sirParams.h @@ -93,7 +93,10 @@ typedef enum { SAP32STA = 5, TDLS = 6, P2P_GO_NOA_DECOUPLE_INIT_SCAN = 7, - WLANACTIVE_OFFLOAD = 8 + WLANACTIVE_OFFLOAD = 8, +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + WLAN_ROAM_SCAN_OFFLOAD = 23, +#endif //MAX_FEATURE_SUPPORTED = 128 } placeHolderInCapBitmap; @@ -553,16 +556,14 @@ typedef struct sSirMbMsgP2p #define SIR_HAL_TDLS_LINK_ESTABLISH (SIR_HAL_ITC_MSG_TYPES_BEGIN + 189) #define SIR_HAL_TDLS_LINK_TEARDOWN (SIR_HAL_ITC_MSG_TYPES_BEGIN + 190) #endif - +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +#define SIR_HAL_ROAM_SCAN_OFFLOAD_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 191) +#endif #define SIR_HAL_GET_ROAM_RSSI_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 193) #define SIR_HAL_GET_ROAM_RSSI_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 194) #define SIR_HAL_TRAFFIC_STATS_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 195) -#ifdef WLAN_FEATURE_11W -#define SIR_HAL_EXCLUDE_UNENCRYPTED_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 196) -#endif - #define SIR_HAL_MSG_TYPES_END (SIR_HAL_ITC_MSG_TYPES_BEGIN + 0xFF) // CFG message types #define SIR_CFG_MSG_TYPES_BEGIN (SIR_CFG_MODULE_ID << 8) diff --git a/drivers/staging/prima/CORE/MAC/src/pe/include/limFTDefs.h b/drivers/staging/prima/CORE/MAC/src/pe/include/limFTDefs.h index 2b34866075e..4912087f328 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/include/limFTDefs.h +++ b/drivers/staging/prima/CORE/MAC/src/pe/include/limFTDefs.h @@ -54,6 +54,7 @@ #include +#include "halMsgApi.h" /*-------------------------------------------------------------------------- Preprocessor definitions and constants @@ -66,8 +67,8 @@ /*-------------------------------------------------------------------------- Type declarations ------------------------------------------------------------------------*/ -/*-------------------------------------------------------------------------- - FT Pre Auth Req SME<->PE +/*-------------------------------------------------------------------------- + FT Pre Auth Req SME<->PE ------------------------------------------------------------------------*/ typedef struct sSirFTPreAuthReq { @@ -84,7 +85,7 @@ typedef struct sSirFTPreAuthReq } tSirFTPreAuthReq, *tpSirFTPreAuthReq; /*------------------------------------------------------------------------- - FT Pre Auth Rsp PE<->SME + FT Pre Auth Rsp PE<->SME ------------------------------------------------------------------------*/ typedef struct sSirFTPreAuthRsp { @@ -99,29 +100,39 @@ typedef struct sSirFTPreAuthRsp tANI_U8 ric_ies[MAX_FTIE_SIZE]; } tSirFTPreAuthRsp, *tpSirFTPreAuthRsp; -/*-------------------------------------------------------------------------- - FT Pre Auth Req SME<->PE +/*-------------------------------------------------------------------------- + FT Pre Auth Rsp Key SME<->PE ------------------------------------------------------------------------*/ typedef struct sSirFTUpdateKeyInfo { - tANI_U16 messageType; - tANI_U16 length; - tSirKeyMaterial keyMaterial; + tANI_U16 messageType; + tANI_U16 length; + tSirMacAddr bssId; + tSirKeyMaterial keyMaterial; } tSirFTUpdateKeyInfo, *tpSirFTUpdateKeyInfo; +/*-------------------------------------------------------------------------- + FT Pre Auth Rsp Key SME<->PE + ------------------------------------------------------------------------*/ +typedef struct sSirFTPreAuthKeyInfo +{ + tANI_U8 extSetStaKeyParamValid; //Ext Bss Config Msg if set + tSetStaKeyParams extSetStaKeyParam; //SetStaKeyParams for ext bss msg +} tSirFTPreAuthKeyInfo, *tpSirFTPreAuthKeyInfo; + /*------------------------------------------------------------------------- - Global FT Information + Global FT Information ------------------------------------------------------------------------*/ typedef struct sFTPEContext { tpSirFTPreAuthReq pFTPreAuthReq; // Saved FT Pre Auth Req - void *psavedsessionEntry; + void *psavedsessionEntry; tSirRetStatus ftPreAuthStatus; tANI_U16 saved_auth_rsp_length; tANI_U8 saved_auth_rsp[MAX_FTIE_SIZE]; - + tSirFTPreAuthKeyInfo *pPreAuthKeyInfo; // Items created for the new FT, session - void *pftSessionEntry; // Saved session created for pre-auth + void *pftSessionEntry; // Saved session created for pre-auth void *pAddBssReq; // Save add bss req. void *pAddStaReq; // Save add sta req. diff --git a/drivers/staging/prima/CORE/MAC/src/pe/include/limGlobal.h b/drivers/staging/prima/CORE/MAC/src/pe/include/limGlobal.h index 4a608f55f6e..7c2b6d9d455 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/include/limGlobal.h +++ b/drivers/staging/prima/CORE/MAC/src/pe/include/limGlobal.h @@ -115,7 +115,7 @@ typedef enum eLimSystemRole eLIM_BT_AMP_AP_ROLE, eLIM_P2P_DEVICE_ROLE, eLIM_P2P_DEVICE_GO, - eLIM_P2P_DEVICE_CLINET + eLIM_P2P_DEVICE_CLIENT } tLimSystemRole; /** diff --git a/drivers/staging/prima/CORE/MAC/src/pe/include/limSession.h b/drivers/staging/prima/CORE/MAC/src/pe/include/limSession.h index 570c35bbc57..81f240d9fe5 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/include/limSession.h +++ b/drivers/staging/prima/CORE/MAC/src/pe/include/limSession.h @@ -266,9 +266,7 @@ typedef struct sPESession // Added to Support BT-AMP tANI_U8 limWsmEnabled:1; //WSM tANI_U8 limHcfEnabled:1; tANI_U8 lim11dEnabled:1; -#ifdef WLAN_FEATURE_11W - tANI_U8 limRmfEnabled:1; //11W -#endif + tANI_U32 lim11hEnable; tPowerdBm maxTxPower; //MIN (Regulatory and local power constraint) @@ -337,7 +335,7 @@ typedef struct sPESession // Added to Support BT-AMP /*Flag to Track Status/Indicate HBFailure on this session */ tANI_BOOLEAN LimHBFailureStatus; tANI_U32 gLimPhyMode; - + tANI_U8 amsduSupportedInBA; tANI_U8 txLdpcIniFeatureEnabled; /** * Following is the place holder for free peer index pool. diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limApi.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limApi.c index 1bf6733ac04..e458129b581 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limApi.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limApi.c @@ -119,6 +119,14 @@ static void __limInitScanVars(tpAniSirGlobal pMac) palZeroMemory(pMac->hHdd, pMac->lim.gLimCachedScanHashTable, sizeof(pMac->lim.gLimCachedScanHashTable)); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + + pMac->lim.gLimMlmLfrScanResultLength = 0; + pMac->lim.gLimSmeLfrScanResultLength = 0; + + palZeroMemory(pMac->hHdd, pMac->lim.gLimCachedLfrScanHashTable, + sizeof(pMac->lim.gLimCachedLfrScanHashTable)); +#endif pMac->lim.gLimBackgroundScanChannelId = 0; pMac->lim.gLimBackgroundScanStarted = 0; pMac->lim.gLimRestoreCBNumScanInterval = LIM_RESTORE_CB_NUM_SCAN_INTERVAL_DEFAULT; @@ -643,6 +651,9 @@ tSirRetStatus limStart(tpAniSirGlobal pMac) // By default return unique scan results pMac->lim.gLimReturnUniqueResults = true; pMac->lim.gLimSmeScanResultLength = 0; +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + pMac->lim.gLimSmeLfrScanResultLength = 0; +#endif } else { @@ -2155,6 +2166,12 @@ tMgmtFrmDropReason limIsPktCandidateForDrop(tpAniSirGlobal pMac, tANI_U8 *pRxPac { return eMGMT_DROP_NO_DROP; } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + else if (WDA_GET_OFFLOADSCANLEARN(pRxPacketInfo) || WDA_GET_ROAMCANDIDATEIND(pRxPacketInfo)) + { + return eMGMT_DROP_NO_DROP; + } +#endif else if (WDA_IS_RX_IN_SCAN(pRxPacketInfo)) { return eMGMT_DROP_SCAN_MODE_FRAME; diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limAssocUtils.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limAssocUtils.c index e92533fc981..51ffb2a8a02 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limAssocUtils.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limAssocUtils.c @@ -307,7 +307,7 @@ limCheckRxBasicRates(tpAniSirGlobal pMac, tSirMacRateSet rxRateSet,tpPESession p pRateSet->numRates = psessionEntry->rateSet.numRates; // Extract BSS basic rateset from operational rateset - for (i = 0, j = 0; i < pRateSet->numRates; i++) + for (i = 0, j = 0; ((i < pRateSet->numRates) && (i < SIR_MAC_RATESET_EID_MAX)) ; i++) { if ((pRateSet->rate[i] & 0x80) == 0x80) { @@ -323,7 +323,7 @@ limCheckRxBasicRates(tpAniSirGlobal pMac, tSirMacRateSet rxRateSet,tpPESession p for (k = 0; k < j; k++) { match = 0; - for (i = 0; i < rxRateSet.numRates; i++) + for (i = 0; ((i < rxRateSet.numRates) && (i < SIR_MAC_RATESET_EID_MAX)); i++) { if ((rxRateSet.rate[i] | 0x80) == basicRate.rate[k]) match = 1; @@ -1627,68 +1627,40 @@ limPopulateOwnRateSet(tpAniSirGlobal pMac, { tSirMacRateSet tempRateSet; tSirMacRateSet tempRateSet2; - tANI_U32 i,j,val,min,isArate; + tANI_U32 i,j,val,min,isArate; tANI_U32 phyMode = 0; - tANI_U32 selfStaDot11Mode=0; + isArate = 0; wlan_cfgGetInt(pMac, WNI_CFG_DOT11_MODE, &selfStaDot11Mode); limGetPhyMode(pMac, &phyMode, psessionEntry); - // Get own rate set - #if 0 - val = WNI_CFG_OPERATIONAL_RATE_SET_LEN; - if (wlan_cfgGetStr(pMac, WNI_CFG_OPERATIONAL_RATE_SET, - (tANI_U8 *) &tempRateSet.rate, - &val) != eSIR_SUCCESS) - { - /// Could not get rateset from CFG. Log error. - limLog(pMac, LOGP, FL("could not retrieve rateset")); - } - #endif // TO SUPPORT BT-AMP - - /* copy operational rate set from psessionEntry */ - if ( psessionEntry->rateSet.numRates < SIR_MAC_RATESET_EID_MAX ) + /* Include 11b rates only when the device configured in + auto, 11a/b/g or 11b_only */ + if ( (selfStaDot11Mode == WNI_CFG_DOT11_MODE_ALL) || + (selfStaDot11Mode == WNI_CFG_DOT11_MODE_11A) || + (selfStaDot11Mode == WNI_CFG_DOT11_MODE_11AC) || + (selfStaDot11Mode == WNI_CFG_DOT11_MODE_11B) ) { - palCopyMemory(pMac->hHdd,(tANI_U8 *)tempRateSet.rate,(tANI_U8*)(psessionEntry->rateSet.rate), psessionEntry->rateSet.numRates); - tempRateSet.numRates = psessionEntry->rateSet.numRates; + val = WNI_CFG_SUPPORTED_RATES_11B_LEN; + wlan_cfgGetStr( pMac, WNI_CFG_SUPPORTED_RATES_11B, + (tANI_U8 *)&tempRateSet.rate, &val ); + tempRateSet.numRates = (tANI_U8) val; } else - { - limLog(pMac, LOGE, FL("more than SIR_MAC_RATESET_EID_MAX rates\n")); - goto error; - } + tempRateSet.numRates = 0; - if (phyMode == WNI_CFG_PHY_MODE_11G) + /* Include 11a rates when the device configured in non-11b mode */ + if (!IS_DOT11_MODE_11B(selfStaDot11Mode)) { - - // get own extended rate set - #if 0 - val = WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET_LEN; - if (wlan_cfgGetStr(pMac, WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET, - (tANI_U8 *) &tempRateSet2.rate, - &val) != eSIR_SUCCESS) - { - /// Could not get extended rateset from CFG. Log error. - limLog(pMac, LOGP, FL("could not retrieve extended rateset")); - } + val = WNI_CFG_SUPPORTED_RATES_11A_LEN; + wlan_cfgGetStr( pMac, WNI_CFG_SUPPORTED_RATES_11A, + (tANI_U8 *)&tempRateSet2.rate, &val ); tempRateSet2.numRates = (tANI_U8) val; - #endif - if (psessionEntry->extRateSet.numRates < SIR_MAC_RATESET_EID_MAX) - { - palCopyMemory(pMac->hHdd,(tANI_U8 *)tempRateSet2.rate, (tANI_U8*)(psessionEntry->extRateSet.rate), psessionEntry->extRateSet.numRates); - tempRateSet2.numRates = psessionEntry->extRateSet.numRates; - } - else { - limLog(pMac, LOGE, FL("psessionEntry->extRateSet.numRates more than SIR_MAC_RATESET_EID_MAX rates\n")); - goto error; - } - } else - tempRateSet2.numRates = 0; - + tempRateSet2.numRates = 0; if ((tempRateSet.numRates + tempRateSet2.numRates) > 12) { @@ -1698,7 +1670,6 @@ limPopulateOwnRateSet(tpAniSirGlobal pMac, goto error; } - //copy all rates in tempRateSet, there are 12 rates max for (i = 0;i < tempRateSet2.numRates; i++) tempRateSet.rate[i + tempRateSet.numRates] = tempRateSet2.rate[i]; @@ -1990,8 +1961,11 @@ limPopulateMatchingRateSet(tpAniSirGlobal pMac, } else { - for(j = 0; ((j < pExtRateSet->numRates) && (j < SIR_MAC_RATESET_EID_MAX) && ((i+j) < SIR_MAC_RATESET_EID_MAX)); j++) + for(j = 0; ((j < pExtRateSet->numRates) && (j < SIR_MAC_RATESET_EID_MAX) + && ((i+j) < SIR_MAC_RATESET_EID_MAX)); j++) + { tempRateSet.rate[i+j] = pExtRateSet->rate[j]; + } tempRateSet.numRates += pExtRateSet->numRates; } @@ -2002,9 +1976,9 @@ limPopulateMatchingRateSet(tpAniSirGlobal pMac, tANI_U8 aRateIndex = 0; tANI_U8 bRateIndex = 0; palZeroMemory( pMac->hHdd, (tANI_U8 *) rates, sizeof(tSirSupportedRates)); - for(i = 0;(i < tempRateSet2.numRates && i < SIR_MAC_RATESET_EID_MAX ); i++) + for(i = 0; (i < tempRateSet2.numRates && i < SIR_MAC_RATESET_EID_MAX ); i++) { - for(j = 0;(j < tempRateSet.numRates && j < SIR_MAC_RATESET_EID_MAX); j++) + for(j = 0; (j < tempRateSet.numRates && j < SIR_MAC_RATESET_EID_MAX); j++) { if ((tempRateSet2.rate[i] & 0x7F) == (tempRateSet.rate[j] & 0x7F)) @@ -2012,10 +1986,14 @@ limPopulateMatchingRateSet(tpAniSirGlobal pMac, if (sirIsArate(tempRateSet2.rate[i] & 0x7f)) { isArate=1; - rates->llaRates[aRateIndex++] = tempRateSet2.rate[i]; + if (aRateIndex < SIR_NUM_11A_RATES) + rates->llaRates[aRateIndex++] = tempRateSet2.rate[i]; } else - rates->llbRates[bRateIndex++] = tempRateSet2.rate[i]; + { + if (bRateIndex < SIR_NUM_11B_RATES) + rates->llbRates[bRateIndex++] = tempRateSet2.rate[i]; + } break; } } @@ -3397,24 +3375,14 @@ tSirRetStatus limStaSendAddBss( tpAniSirGlobal pMac, tpSirAssocRsp pAssocRsp, if (VOS_P2P_CLIENT_MODE == psessionEntry->pePersona) { - pAddBssParams->staContext.p2pCapableSta = 1; + pAddBssParams->staContext.p2pCapableSta = 1; } - - pAddBssParams->bSpectrumMgtEnabled = psessionEntry->spectrumMgtEnabled || - limIsconnectedOnDFSChannel(bssDescription->channelId); + pAddBssParams->bSpectrumMgtEnabled = psessionEntry->spectrumMgtEnabled; #if defined WLAN_FEATURE_VOWIFI_11R pAddBssParams->extSetStaKeyParamValid = 0; #endif -#ifdef WLAN_FEATURE_11W - if (psessionEntry->limRmfEnabled) - { - pAddBssParams->rmfEnabled = 1; - pAddBssParams->staContext.rmfEnabled = 1; - } -#endif - // Set a new state for MLME if( eLIM_MLM_WT_ASSOC_RSP_STATE == psessionEntry->limMlmState ) psessionEntry->limMlmState = eLIM_MLM_WT_ADD_BSS_RSP_ASSOC_STATE; @@ -3689,29 +3657,19 @@ tSirRetStatus limStaSendAddBssPreAssoc( tpAniSirGlobal pMac, tANI_U8 updateEntry pAddBssParams->staContext.sessionId = psessionEntry->peSessionId; pAddBssParams->sessionId = psessionEntry->peSessionId; - - pAddBssParams->halPersona = (tANI_U8)psessionEntry->pePersona; //update persona - pAddBssParams->bSpectrumMgtEnabled = psessionEntry->spectrumMgtEnabled || - limIsconnectedOnDFSChannel(bssDescription->channelId); + pAddBssParams->halPersona = (tANI_U8)psessionEntry->pePersona; //update persona + pAddBssParams->bSpectrumMgtEnabled = psessionEntry->spectrumMgtEnabled; #if defined WLAN_FEATURE_VOWIFI_11R pAddBssParams->extSetStaKeyParamValid = 0; #endif -#ifdef WLAN_FEATURE_11W - if (psessionEntry->limRmfEnabled) - { - pAddBssParams->rmfEnabled = 1; - pAddBssParams->staContext.rmfEnabled = 1; - } -#endif - // Set a new state for MLME //pMac->lim.gLimMlmState = eLIM_MLM_WT_ADD_BSS_RSP_PREASSOC_STATE; psessionEntry->limMlmState = eLIM_MLM_WT_ADD_BSS_RSP_PREASSOC_STATE; - + MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, psessionEntry->limMlmState)); //we need to defer the message until we get the response back from HAL. @@ -3987,49 +3945,3 @@ void limFillRxHighestSupportedRate(tpAniSirGlobal pMac, tANI_U16 *rxHighestRate, return; } - -#ifdef WLAN_FEATURE_11W -/** ------------------------------------------------------------- -\fn limSendSmeUnprotectedMgmtFrameInd -\brief Forwards the unprotected management frame to SME. -\param tpAniSirGlobal pMac -\param frameType - 802.11 frame type -\param frame - frame buffer -\param sessionId - id for the current session -\param psessionEntry - PE session context -\return none - -------------------------------------------------------------*/ -void limSendSmeUnprotectedMgmtFrameInd( - tpAniSirGlobal pMac, tANI_U8 frameType, - tANI_U8 *frame, tANI_U32 frameLen, tANI_U16 sessionId, - tpPESession psessionEntry) -{ - tSirMsgQ mmhMsg; - tSirSmeUnprotMgmtFrameInd * pSirSmeMgmtFrame = NULL; - tANI_U16 length; - - length = sizeof(tSirSmeUnprotMgmtFrameInd) + frameLen; - - if (eHAL_STATUS_SUCCESS != - palAllocateMemory(pMac->hHdd, (void **)&pSirSmeMgmtFrame, length)) - { - limLog(pMac, LOGP, - FL("palAllocateMemory failed for tSirSmeUnprotectedMgmtFrameInd")); - return; - } - palZeroMemory(pMac->hHdd, (void*)pSirSmeMgmtFrame, length); - - pSirSmeMgmtFrame->sessionId = sessionId; - pSirSmeMgmtFrame->frameType = frameType; - - vos_mem_copy(pSirSmeMgmtFrame->frameBuf, frame, frameLen); - pSirSmeMgmtFrame->frameLen = frameLen; - - mmhMsg.type = eWNI_SME_UNPROT_MGMT_FRM_IND; - mmhMsg.bodyptr = pSirSmeMgmtFrame; - mmhMsg.bodyval = 0; - - limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); - return; -} -#endif diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limAssocUtils.h b/drivers/staging/prima/CORE/MAC/src/pe/lim/limAssocUtils.h index 915d9c3affe..9a7ba3b5c5f 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limAssocUtils.h +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limAssocUtils.h @@ -177,10 +177,6 @@ void limFillRxHighestSupportedRate(tpAniSirGlobal pMac, tANI_U16 *rxHighestRate, #if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR) void limSendRetryReassocReqFrame(tpAniSirGlobal pMac, tLimMlmReassocReq *pMlmReassocReq, tpPESession psessionEntry); #endif -#ifdef WLAN_FEATURE_11W -void limSendSmeUnprotectedMgmtFrameInd(tpAniSirGlobal pMac, tANI_U8 frameType, - tANI_U8 *frame, tANI_U32 frameLen, tANI_U16 sessionId, tpPESession psessionEntry); -#endif #endif /* __LIM_ASSOC_UTILS_H */ diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limFT.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limFT.c index 58eed714a2d..f349d66adad 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limFT.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limFT.c @@ -1,52 +1,31 @@ /* - * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. - * - * Previously licensed under the ISC license by Qualcomm Atheros, Inc. - * - * - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all - * copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ -/* - * Copyright (c) 2012, The Linux Foundation. All rights reserved. - * - * Previously licensed under the ISC license by Qualcomm Atheros, Inc. - * - * - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all - * copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - + * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. +*/ #ifdef WLAN_FEATURE_VOWIFI_11R /**========================================================================= \brief implementation for PE 11r VoWiFi FT Protocol - Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved. + Copyright 2008 (c) Qualcomm Technologies, Inc. All Rights Reserved. - Qualcomm Confidential and Proprietary. + Qualcomm Technologies Confidential and Proprietary. ========================================================================*/ @@ -70,6 +49,7 @@ #define LIM_FT_RIC_BA_SSN 1 #define LIM_FT_RIC_BA_DIALOG_TOKEN_TID_0 248 #define LIM_FT_RIC_DESCRIPTOR_RESOURCE_TYPE_BA 1 +#define LIM_FT_RIC_DESCRIPTOR_MAX_VAR_DATA_LEN 255 /*-------------------------------------------------------------------------- Initialize the FT variables. @@ -268,7 +248,16 @@ int limProcessFTPreAuthReq(tpAniSirGlobal pMac, tpSirMsgQ pMsg) // Now we are starting fresh make sure all's cleanup. limFTInit(pMac); - pMac->ft.ftPEContext.ftPreAuthStatus = eSIR_FAILURE; // Can set it only after sending auth + // Can set it only after sending auth + pMac->ft.ftPEContext.ftPreAuthStatus = eSIR_FAILURE; + + if( pMac->ft.ftPEContext.pFTPreAuthReq && + pMac->ft.ftPEContext.pFTPreAuthReq->pbssDescription) + { + palFreeMemory(pMac->hHdd, + pMac->ft.ftPEContext.pFTPreAuthReq->pbssDescription); + pMac->ft.ftPEContext.pFTPreAuthReq->pbssDescription = NULL; + } // We need information from the Pre-Auth Req. Lets save that pMac->ft.ftPEContext.pFTPreAuthReq = (tpSirFTPreAuthReq)pMsg->bodyptr; @@ -290,7 +279,13 @@ int limProcessFTPreAuthReq(tpAniSirGlobal pMac, tpSirMsgQ pMsg) limPrintMacAddr( pMac, pMac->ft.ftPEContext.pFTPreAuthReq->currbssId, LOGE ); // Post the FT Pre Auth Response to SME limPostFTPreAuthRsp(pMac, eSIR_FAILURE, NULL, 0, NULL); - pMac->ft.ftPEContext.pFTPreAuthReq = NULL; + if (pMac->ft.ftPEContext.pFTPreAuthReq->pbssDescription) + { + palFreeMemory(pMac->hHdd, + pMac->ft.ftPEContext.pFTPreAuthReq->pbssDescription); + pMac->ft.ftPEContext.pFTPreAuthReq->pbssDescription = NULL; + } + pMac->ft.ftPEContext.pFTPreAuthReq = NULL; return TRUE; } @@ -805,6 +800,8 @@ void limPerformPostFTPreAuthAndChannelChange(tpAniSirGlobal pMac, eHalStatus sta tSirRetStatus limCreateRICBlockAckIE(tpAniSirGlobal pMac, tANI_U8 tid, tCfgTrafficClass *pTrafficClass, tANI_U8 *ric_ies, tANI_U32 *ieLength) { + /* BlockACK + RIC is not supported now, TODO later to support this */ +#if 0 tDot11fIERICDataDesc ricIe; tDot11fFfBAStartingSequenceControl baSsnControl; tDot11fFfAddBAParameterSet baParamSet; @@ -827,23 +824,25 @@ tSirRetStatus limCreateRICBlockAckIE(tpAniSirGlobal pMac, tANI_U8 tid, tCfgTraff vos_mem_copy((v_VOID_t *)&baTimeout, (v_VOID_t *)&pTrafficClass->tuTxBAWaitTimeout, sizeof(baTimeout)); baSsnControl.fragNumber = 0; baSsnControl.ssn = LIM_FT_RIC_BA_SSN; - if ( ricIe.RICDescriptor.num_variableData < sizeof (ricIe.RICDescriptor.variableData)) { + if (ricIe.RICDescriptor.num_variableData < sizeof (ricIe.RICDescriptor.variableData)) { dot11fPackFfAddBAParameterSet(pMac, &baParamSet, &ricIe.RICDescriptor.variableData[ricIe.RICDescriptor.num_variableData]); //vos_mem_copy(&ricIe.RICDescriptor.variableData[ricIe.RICDescriptor.num_variableData], &baParamSet, sizeof(tDot11fFfAddBAParameterSet)); ricIe.RICDescriptor.num_variableData += sizeof(tDot11fFfAddBAParameterSet); } - - if ( ricIe.RICDescriptor.num_variableData < sizeof (ricIe.RICDescriptor.variableData)) { + if (ricIe.RICDescriptor.num_variableData < sizeof (ricIe.RICDescriptor.variableData)) { dot11fPackFfBATimeout(pMac, &baTimeout, &ricIe.RICDescriptor.variableData[ricIe.RICDescriptor.num_variableData]); //vos_mem_copy(&ricIe.RICDescriptor.variableData[ricIe.RICDescriptor.num_variableData], &baTimeout, sizeof(tDot11fFfBATimeout)); ricIe.RICDescriptor.num_variableData += sizeof(tDot11fFfBATimeout); } - if ( ricIe.RICDescriptor.num_variableData < sizeof (ricIe.RICDescriptor.variableData)) { + if (ricIe.RICDescriptor.num_variableData < sizeof (ricIe.RICDescriptor.variableData)) { dot11fPackFfBAStartingSequenceControl(pMac, &baSsnControl, &ricIe.RICDescriptor.variableData[ricIe.RICDescriptor.num_variableData]); //vos_mem_copy(&ricIe.RICDescriptor.variableData[ricIe.RICDescriptor.num_variableData], &baSsnControl, sizeof(tDot11fFfBAStartingSequenceControl)); ricIe.RICDescriptor.num_variableData += sizeof(tDot11fFfBAStartingSequenceControl); } return (tSirRetStatus) dot11fPackIeRICDataDesc(pMac, &ricIe, ric_ies, sizeof(tDot11fIERICDataDesc), ieLength); +#endif + + return eSIR_FAILURE; } tSirRetStatus limFTFillRICBlockAckInfo(tpAniSirGlobal pMac, tANI_U8 *ric_ies, tANI_U32 *ric_ies_length) @@ -1067,7 +1066,7 @@ void limProcessMlmFTReassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf, { tANI_U8 smeSessionId = 0; tANI_U16 transactionId = 0; - tANI_U8 chanNum = 0; + tANI_U8 chanNum = 0; tLimMlmReassocReq *pMlmReassocReq; tANI_U16 caps; tANI_U32 val; @@ -1075,14 +1074,18 @@ void limProcessMlmFTReassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf, tSirRetStatus retCode; tANI_U32 teleBcnEn = 0; - chanNum = psessionEntry->currentOperChannel; + chanNum = psessionEntry->currentOperChannel; limGetSessionInfo(pMac,(tANI_U8*)pMsgBuf, &smeSessionId, &transactionId); psessionEntry->smeSessionId = smeSessionId; psessionEntry->transactionId = transactionId; - - if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pMlmReassocReq, + if (NULL == pMac->ft.ftPEContext.pAddBssReq) + { + limLog(pMac, LOGE, FL("pAddBssReq is NULL")); + return; + } + if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pMlmReassocReq, sizeof(tLimMlmReassocReq))) { // Log error @@ -1103,6 +1106,7 @@ void limProcessMlmFTReassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf, * from CFG. Log error. */ limLog(pMac, LOGE, FL("could not retrieve ReassocFailureTimeout value")); + palFreeMemory(pMac->hHdd, pMlmReassocReq); return; } @@ -1113,52 +1117,54 @@ void limProcessMlmFTReassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf, * from CFG. Log error. */ limLog(pMac, LOGE, FL("could not retrieve Capabilities value")); + palFreeMemory(pMac->hHdd, pMlmReassocReq); return; } pMlmReassocReq->capabilityInfo = caps; - + /* Update PE sessionId*/ pMlmReassocReq->sessionId = psessionEntry->peSessionId; /* If telescopic beaconing is enabled, set listen interval to WNI_CFG_TELE_BCN_MAX_LI */ - if(wlan_cfgGetInt(pMac, WNI_CFG_TELE_BCN_WAKEUP_EN, &teleBcnEn) != - eSIR_SUCCESS) + if (wlan_cfgGetInt(pMac, WNI_CFG_TELE_BCN_WAKEUP_EN, &teleBcnEn) != + eSIR_SUCCESS) + { limLog(pMac, LOGP, FL("Couldn't get WNI_CFG_TELE_BCN_WAKEUP_EN")); + palFreeMemory(pMac->hHdd, pMlmReassocReq); + return; + } - if(teleBcnEn) + if (teleBcnEn) { - if(wlan_cfgGetInt(pMac, WNI_CFG_TELE_BCN_MAX_LI, &val) != eSIR_SUCCESS) + if (wlan_cfgGetInt(pMac, WNI_CFG_TELE_BCN_MAX_LI, &val) != eSIR_SUCCESS) { /** * Could not get ListenInterval value * from CFG. Log error. */ limLog(pMac, LOGE, FL("could not retrieve ListenInterval")); + palFreeMemory(pMac->hHdd, pMlmReassocReq); return; } } else { - if (wlan_cfgGetInt(pMac, WNI_CFG_LISTEN_INTERVAL, &val) != eSIR_SUCCESS) + if (wlan_cfgGetInt(pMac, WNI_CFG_LISTEN_INTERVAL, &val) != eSIR_SUCCESS) { /** * Could not get ListenInterval value * from CFG. Log error. */ limLog(pMac, LOGE, FL("could not retrieve ListenInterval")); + palFreeMemory(pMac->hHdd, pMlmReassocReq); return; } } - if (limSetLinkState(pMac, eSIR_LINK_PREASSOC_STATE, psessionEntry->bssId, - psessionEntry->selfMacAddr, NULL, NULL) != eSIR_SUCCESS) - { - return; - } - if (limSetLinkState(pMac, eSIR_LINK_PREASSOC_STATE, psessionEntry->bssId, psessionEntry->selfMacAddr, NULL, NULL) != eSIR_SUCCESS) { - return; + palFreeMemory(pMac->hHdd, pMlmReassocReq); + return; } pMlmReassocReq->listenInterval = (tANI_U16) val; @@ -1168,7 +1174,7 @@ void limProcessMlmFTReassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf, //we need to defer the message until we get the response back from HAL. SET_LIM_PROCESS_DEFD_MESGS(pMac, false); - + msgQ.type = SIR_HAL_ADD_BSS_REQ; msgQ.reserved = 0; msgQ.bodyptr = pMac->ft.ftPEContext.pAddBssReq; @@ -1181,7 +1187,7 @@ void limProcessMlmFTReassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf, MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, msgQ.type)); retCode = wdaPostCtrlMsg( pMac, &msgQ ); - if( eSIR_SUCCESS != retCode) + if( eSIR_SUCCESS != retCode) { vos_mem_free(pMac->ft.ftPEContext.pAddBssReq); limLog( pMac, LOGE, FL("Posting ADD_BSS_REQ to HAL failed, reason=%X"), @@ -1204,6 +1210,7 @@ void limProcessFTPreauthRspTimeout(tpAniSirGlobal pMac) // We have failed pre auth. We need to resume link and get back on // home channel. + limLog(pMac, LOG1, FL("FT Pre-Auth Time Out!!!!")); if((psessionEntry = peFindSessionBySessionId(pMac, pMac->lim.limTimers.gLimFTPreAuthRspTimer.sessionId))== NULL) { @@ -1224,32 +1231,72 @@ void limProcessFTPreauthRspTimeout(tpAniSirGlobal pMac) *------------------------------------------------------------------*/ tANI_BOOLEAN limProcessFTUpdateKey(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf ) { - tAddBssParams * pAddBssParams; - tSirFTUpdateKeyInfo * pKeyInfo; - tANI_U32 val = 0; - - /* Sanity Check */ - if( pMac == NULL || pMsgBuf == NULL ) - { - return TRUE; - } - - pAddBssParams = pMac->ft.ftPEContext.pAddBssReq; - pKeyInfo = (tSirFTUpdateKeyInfo *)pMsgBuf; - - /* Store the key information in the ADD BSS parameters */ - pAddBssParams->extSetStaKeyParamValid = 1; - pAddBssParams->extSetStaKeyParam.encType = pKeyInfo->keyMaterial.edType; - palCopyMemory( pMac->hHdd, (tANI_U8 *) &pAddBssParams->extSetStaKeyParam.key, + tAddBssParams * pAddBssParams; + tSirFTUpdateKeyInfo * pKeyInfo; + tANI_U32 val = 0; + + /* Sanity Check */ + if( pMac == NULL || pMsgBuf == NULL ) + { + return TRUE; + } + if(pMac->ft.ftPEContext.pAddBssReq == NULL) + { + limLog( pMac, LOGE, + FL( "pAddBssReq is NULL" )); + return TRUE; + } + + pAddBssParams = pMac->ft.ftPEContext.pAddBssReq; + pKeyInfo = (tSirFTUpdateKeyInfo *)pMsgBuf; + + /* Store the key information in the ADD BSS parameters */ + pAddBssParams->extSetStaKeyParamValid = 1; + pAddBssParams->extSetStaKeyParam.encType = pKeyInfo->keyMaterial.edType; + palCopyMemory( pMac->hHdd, (tANI_U8 *) &pAddBssParams->extSetStaKeyParam.key, (tANI_U8 *) &pKeyInfo->keyMaterial.key, sizeof( tSirKeys )); - if(eSIR_SUCCESS != wlan_cfgGetInt(pMac, WNI_CFG_SINGLE_TID_RC, &val)) - { - limLog( pMac, LOGP, FL( "Unable to read WNI_CFG_SINGLE_TID_RC" )); - } + if(eSIR_SUCCESS != wlan_cfgGetInt(pMac, WNI_CFG_SINGLE_TID_RC, &val)) + { + limLog( pMac, LOGP, FL( "Unable to read WNI_CFG_SINGLE_TID_RC" )); + } - pAddBssParams->extSetStaKeyParam.singleTidRc = val; + pAddBssParams->extSetStaKeyParam.singleTidRc = val; + PELOG1(limLog(pMac, LOG1, FL("Key valid %d"), + pAddBssParams->extSetStaKeyParamValid, + pAddBssParams->extSetStaKeyParam.key[0].keyLength);) - return TRUE; + pAddBssParams->extSetStaKeyParam.staIdx = 0; + + PELOG1(limLog(pMac, LOG1, + FL("BSSID = %02X-%02X-%02X-%02X-%02X-%02X"), + pKeyInfo->bssId[0], pKeyInfo->bssId[1], + pKeyInfo->bssId[2], pKeyInfo->bssId[3], + pKeyInfo->bssId[4], pKeyInfo->bssId[5]);) + + if(pAddBssParams->extSetStaKeyParam.key[0].keyLength == 16) + { + PELOG1(limLog(pMac, LOG1, + FL("BSS key = %02X-%02X-%02X-%02X-%02X-%02X-%02X- " + "%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X"), + pAddBssParams->extSetStaKeyParam.key[0].key[0], + pAddBssParams->extSetStaKeyParam.key[0].key[1], + pAddBssParams->extSetStaKeyParam.key[0].key[2], + pAddBssParams->extSetStaKeyParam.key[0].key[3], + pAddBssParams->extSetStaKeyParam.key[0].key[4], + pAddBssParams->extSetStaKeyParam.key[0].key[5], + pAddBssParams->extSetStaKeyParam.key[0].key[6], + pAddBssParams->extSetStaKeyParam.key[0].key[7], + pAddBssParams->extSetStaKeyParam.key[0].key[8], + pAddBssParams->extSetStaKeyParam.key[0].key[9], + pAddBssParams->extSetStaKeyParam.key[0].key[10], + pAddBssParams->extSetStaKeyParam.key[0].key[11], + pAddBssParams->extSetStaKeyParam.key[0].key[12], + pAddBssParams->extSetStaKeyParam.key[0].key[13], + pAddBssParams->extSetStaKeyParam.key[0].key[14], + pAddBssParams->extSetStaKeyParam.key[0].key[15]);) + } + + return TRUE; } tSirRetStatus diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limIbssPeerMgmt.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limIbssPeerMgmt.c index a903e22fa2b..9272b387a02 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limIbssPeerMgmt.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limIbssPeerMgmt.c @@ -1085,26 +1085,25 @@ limIbssStaAdd( limPrintMacAddr(pMac, *pPeerAddr, LOGE); pPeerNode = ibss_peer_find(pMac, *pPeerAddr); - if(NULL != pPeerNode) + if (NULL != pPeerNode) { - retCode = ibss_dph_entry_add(pMac, *pPeerAddr, &pStaDs,psessionEntry); + retCode = ibss_dph_entry_add(pMac, *pPeerAddr, &pStaDs, psessionEntry); if (eSIR_SUCCESS == retCode) { prevState = pStaDs->mlmStaContext.mlmState; pStaDs->erpEnabled = pPeerNode->erpIePresent; - ibss_sta_info_update(pMac, pStaDs, pPeerNode,psessionEntry); + ibss_sta_info_update(pMac, pStaDs, pPeerNode, psessionEntry); PELOGW(limLog(pMac, LOGW, FL("initiating ADD STA for the IBSS peer."));) retCode = limAddSta(pMac, pStaDs, false, psessionEntry); - if(retCode != eSIR_SUCCESS) + if (retCode != eSIR_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("ibss-sta-add failed (reason %x)"), retCode);) + PELOGE(limLog(pMac, LOGE, FL("ibss-sta-add failed (reason %x)"), + retCode);) limPrintMacAddr(pMac, *pPeerAddr, LOGE); - if(NULL != pStaDs) - { - pStaDs->mlmStaContext.mlmState = prevState; - dphDeleteHashEntry(pMac, pStaDs->staAddr, pStaDs->assocId, &psessionEntry->dph.dphHashTable); - } + pStaDs->mlmStaContext.mlmState = prevState; + dphDeleteHashEntry(pMac, pStaDs->staAddr, pStaDs->assocId, + &psessionEntry->dph.dphHashTable); } else { @@ -1114,7 +1113,8 @@ limIbssStaAdd( if(beaconParams.paramChangeBitmap) { PELOGE(limLog(pMac, LOGE, FL("---> Update Beacon Params "));) - schSetFixedBeaconFields(pMac, psessionEntry); + schSetFixedBeaconFields(pMac, psessionEntry); + beaconParams.bssIdx = psessionEntry->bssIdx; limSendBeaconParams(pMac, &beaconParams, psessionEntry ); } } @@ -1466,7 +1466,8 @@ limIbssCoalesce( if(beaconParams.paramChangeBitmap) { PELOGE(limLog(pMac, LOGE, FL("beaconParams.paramChangeBitmap=1 ---> Update Beacon Params "));) - schSetFixedBeaconFields(pMac, psessionEntry); + schSetFixedBeaconFields(pMac, psessionEntry); + beaconParams.bssIdx = psessionEntry->bssIdx; limSendBeaconParams(pMac, &beaconParams, psessionEntry ); } } diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limLogDump.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limLogDump.c index 076f10bfec1..6dcda170fd7 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limLogDump.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limLogDump.c @@ -2339,9 +2339,9 @@ dump_lim_mcc_policy_maker(tpAniSirGlobal pMac, tANI_U32 arg1,tANI_U32 arg2,tANI_ v_VOID_t * pVosContext = vos_get_global_context(VOS_MODULE_ID_WDA, NULL); tWDA_CbContext *pWDA = vos_get_context(VOS_MODULE_ID_WDA, pVosContext); ccmCfgSetInt(pMac, WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED, TRUE, NULL, eANI_BOOLEAN_FALSE); - if(pWDA != NULL) + if(NULL != pWDA) { - WDA_TimerTrafficStatsInd(pWDA); + WDA_TimerTrafficStatsInd(pWDA); } WDA_TrafficStatsTimerActivate(FALSE); ccmCfgSetInt(pMac, WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED, FALSE,NULL, eANI_BOOLEAN_FALSE); @@ -2350,7 +2350,7 @@ dump_lim_mcc_policy_maker(tpAniSirGlobal pMac, tANI_U32 arg1,tANI_U32 arg2,tANI_ { v_VOID_t * pVosContext = vos_get_global_context(VOS_MODULE_ID_WDA, NULL); tWDA_CbContext *pWDA = vos_get_context(VOS_MODULE_ID_WDA, pVosContext); - if (pWDA != NULL && tx_timer_change(&pWDA->wdaTimers.trafficStatsTimer, arg2/10, arg2/10) != TX_SUCCESS) + if (tx_timer_change(&pWDA->wdaTimers.trafficStatsTimer, arg2/10, arg2/10) != TX_SUCCESS) { limLog(pMac, LOGP, FL("Disable timer before changing timeout value")); } diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limP2P.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limP2P.c index 3080cb3a456..68013717bb4 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limP2P.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limP2P.c @@ -809,7 +809,7 @@ void limSendP2PActionFrame(tpAniSirGlobal pMac, tpSirMsgQ pMsg) tANI_U8 txFlag = 0; tpSirMacFrameCtl pFc = (tpSirMacFrameCtl ) pMbMsg->data; tANI_U8 noaLen = 0; - tANI_U8 noaStream[SIR_MAX_NOA_ATTR_LEN + SIR_P2P_IE_HEADER_LEN]; + tANI_U8 noaStream[SIR_MAX_NOA_ATTR_LEN + (2*SIR_P2P_IE_HEADER_LEN)]; tANI_U8 origLen = 0; tANI_U8 sessionId = 0; v_U8_t *pP2PIe = NULL; diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessActionFrame.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessActionFrame.c index da02800fc8e..424be1dc076 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessActionFrame.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessActionFrame.c @@ -1198,6 +1198,7 @@ __limProcessAddBAReq( tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession ps pHdr = WDA_GET_RX_MAC_HEADER( pRxPacketInfo ); pBody = WDA_GET_RX_MPDU_DATA( pRxPacketInfo ); frameLen = WDA_GET_RX_PAYLOAD_LEN( pRxPacketInfo ); + val = 0; // Unpack the received frame nStatus = dot11fUnpackAddBAReq( pMac, pBody, frameLen, &frmAddBAReq ); @@ -1223,12 +1224,14 @@ __limProcessAddBAReq( tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession ps PELOG2(sirDumpBuf( pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frameLen );) } + psessionEntry->amsduSupportedInBA = frmAddBAReq.AddBAParameterSet.amsduSupported; + pSta = dphLookupHashEntry( pMac, pHdr->sa, &aid, &psessionEntry->dph.dphHashTable ); if( pSta == NULL ) { limLog( pMac, LOGE, FL( "STA context not found - ignoring ADDBA from " )); - limPrintMacAddr( pMac, pHdr->sa, LOGW ); + limPrintMacAddr( pMac, pHdr->sa, LOGE ); // FIXME - Should we do this? status = eSIR_MAC_INABLITY_TO_CONFIRM_ASSOC_STATUS; @@ -1248,6 +1251,23 @@ __limProcessAddBAReq( tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession ps } #endif //WLAN_SOFTAP_VSTA_FEATURE + if (wlan_cfgGetInt(pMac, WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC, &val) != + eSIR_SUCCESS) + { + limLog(pMac, LOGE, + FL("Unable to get WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC")); + val = 0; + } + if ((SIR_BAND_2_4_GHZ == limGetRFBand(psessionEntry->currentOperChannel)) && + val) + { + limLog( pMac, LOGW, + FL( "BTC disabled aggregation - ignoring ADDBA from " )); + limPrintMacAddr( pMac, pHdr->sa, LOGW ); + + status = eSIR_MAC_REQ_DECLINED_STATUS; + goto returnAfterError; + } // Now, validate the ADDBA Req if( eSIR_MAC_SUCCESS_STATUS != @@ -1304,7 +1324,7 @@ __limProcessAddBAReq( tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession ps { frmAddBAReq.AddBAParameterSet.bufferSize = val; } - limLog( pMac, LOGE, FL( "ADDBAREQ NUMBUFF %d" ), + limLog( pMac, LOG1, FL( "ADDBAREQ NUMBUFF %d" ), frmAddBAReq.AddBAParameterSet.bufferSize); if( eSIR_SUCCESS != limPostMsgAddBAReq( pMac, @@ -1773,7 +1793,7 @@ __limProcessNeighborReport( tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo ,tpPESes #ifdef WLAN_FEATURE_11W /** - * limProcessSAQueryRequestActionFrame + * limProcessActionFrame * *FUNCTION: * This function is called by limProcessActionFrame() upon @@ -1786,16 +1806,14 @@ __limProcessNeighborReport( tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo ,tpPESes *NOTE: * * @param pMac - Pointer to Global MAC structure - * @param *pRxPacketInfo - Handle to the Rx packet info - * @param psessionEntry - PE session entry - * + * @param *pBd - A pointer to Buffer descriptor + associated PDUs * @return None */ -static void __limProcessSAQueryRequestActionFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession psessionEntry) +static void __limProcessSAQueryRequestActionFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession psessionEntry) { tpSirMacMgmtHdr pHdr; tANI_U8 *pBody; - tANI_U8 transId[2]; + tANI_U16 transId = 0; /* Prima --- Below Macro not available in prima pHdr = SIR_MAC_BD_TO_MPDUHEADER(pBd); @@ -1804,62 +1822,27 @@ static void __limProcessSAQueryRequestActionFrame(tpAniSirGlobal pMac, tANI_U8 * pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo); pBody = WDA_GET_RX_MPDU_DATA(pRxPacketInfo); - /* If this is an unprotected SA Query Request, then ignore it. */ - if (pHdr->fc.wep == 0) - return; - /*Extract 11w trsansId from SA query request action frame In SA query response action frame we will send same transId In SA query request action frame: Category : 1 byte Action : 1 byte - Transaction ID : 2 bytes */ - vos_mem_copy( &transId[0], &pBody[2], 2 ); + Transaction ID : 2 bbytes */ + transId = pBody[2]; + transId = transId << 8; + transId |= pBody[3]; + //Send 11w SA query response action frame if (limSendSaQueryResponseFrame(pMac, transId, pHdr->sa,psessionEntry) != eSIR_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("fail to send SA query response action frame."));) + PELOGE(limLog(pMac, LOGE, FL("fail to send SA query response action frame. \n"));) return; } } -/** - * __limProcessSAQueryResponseActionFrame - * - *FUNCTION: - * This function is called by limProcessActionFrame() upon - * SA query response Action frame reception. - * - *LOGIC: - * - *ASSUMPTIONS: - * - *NOTE: - * - * @param pMac - Pointer to Global MAC structure - * @param *pRxPacketInfo - Handle to the Rx packet info - * @param psessionEntry - PE session entry - * @return None - */ -static void __limProcessSAQueryResponseActionFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession psessionEntry) -{ - tpSirMacMgmtHdr pHdr; - tANI_U32 frameLen; - - pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo); - frameLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); - VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("SA Query Response received...")) ; - /* Forward to the SME to HDD to wpa_supplicant */ - // type is ACTION - limSendSmeMgmtFrameInd(pMac, pHdr->fc.subType, - (tANI_U8*)pHdr, frameLen + sizeof(tSirMacMgmtHdr), 0, - WDA_GET_RX_CH( pRxPacketInfo ), psessionEntry, 0); -} - #endif /** @@ -1885,21 +1868,11 @@ limProcessActionFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession ps { tANI_U8 *pBody = WDA_GET_RX_MPDU_DATA(pRxPacketInfo); tpSirMacActionFrameHdr pActionHdr = (tpSirMacActionFrameHdr) pBody; -#ifdef WLAN_FEATURE_11W - tpSirMacMgmtHdr pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo); -#endif + switch (pActionHdr->category) { case SIR_MAC_ACTION_QOS_MGMT: -#ifdef WLAN_FEATURE_11W - if ((psessionEntry->limRmfEnabled) && (pHdr->fc.wep == 0)) - { - PELOGE(limLog(pMac, LOGE, FL("Dropping unprotected Action category %d frame " - "since RMF is enabled."), pActionHdr->category);) - break; - } -#endif if (psessionEntry->limQosEnabled) { switch (pActionHdr->actionID) @@ -1926,14 +1899,6 @@ limProcessActionFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession ps break; case SIR_MAC_ACTION_SPECTRUM_MGMT: -#ifdef WLAN_FEATURE_11W - if ((psessionEntry->limRmfEnabled) && (pHdr->fc.wep == 0)) - { - PELOGE(limLog(pMac, LOGE, FL("Dropping unprotected Action category %d frame " - "since RMF is enabled."), pActionHdr->category);) - break; - } -#endif switch (pActionHdr->actionID) { #ifdef ANI_SUPPORT_11H @@ -1997,14 +1962,6 @@ limProcessActionFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession ps case SIR_MAC_ACTION_BLKACK: // Determine the "type" of BA Action Frame -#ifdef WLAN_FEATURE_11W - if ((psessionEntry->limRmfEnabled) && (pHdr->fc.wep == 0)) - { - PELOGE(limLog(pMac, LOGE, FL("Dropping unprotected Action category %d frame " - "since RMF is enabled."), pActionHdr->category);) - break; - } -#endif switch(pActionHdr->actionID) { case SIR_MAC_BLKACK_ADD_REQ: @@ -2038,14 +1995,6 @@ limProcessActionFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession ps #if defined WLAN_FEATURE_VOWIFI case SIR_MAC_ACTION_RRM: -#ifdef WLAN_FEATURE_11W - if ((psessionEntry->limRmfEnabled) && (pHdr->fc.wep == 0)) - { - PELOGE(limLog(pMac, LOGE, FL("Dropping unprotected Action category %d frame " - "since RMF is enabled."), pActionHdr->category);) - break; - } -#endif if( pMac->rrm.rrmPEContext.rrmEnable ) { switch(pActionHdr->actionID) { @@ -2070,6 +2019,44 @@ limProcessActionFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession ps PELOGE( limLog( pMac, LOGE, FL("RRM Action frame ignored as RRM is disabled in cfg"));) } break; +#endif +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR) + case SIR_MAC_ACTION_VENDOR_SPECIFIC_CATEGORY: + { + tpSirMacVendorSpecificFrameHdr pVendorSpecific = (tpSirMacVendorSpecificFrameHdr) pActionHdr; + tpSirMacMgmtHdr pHdr; + tANI_U32 frameLen; + tANI_U8 Oui[] = { 0x00, 0x00, 0xf0 }; + + pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo); + frameLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); + + //Check if it is a vendor specific action frame. + if ((eLIM_STA_ROLE == psessionEntry->limSystemRole) && + (VOS_TRUE == palEqualMemory(pMac->hHdd, psessionEntry->selfMacAddr, + &pHdr->da[0], sizeof(tSirMacAddr))) && + IS_WES_MODE_ENABLED(pMac) && palEqualMemory( pMac->hHdd, pVendorSpecific->Oui, Oui, 3)) + { + PELOGE( limLog( pMac, LOGW, FL("Received Vendor specific action frame, OUI %x %x %x"), + pVendorSpecific->Oui[0], pVendorSpecific->Oui[1], pVendorSpecific->Oui[2]);) + /* Forward to the SME to HDD to wpa_supplicant */ + // type is ACTION + limSendSmeMgmtFrameInd(pMac, pHdr->fc.subType, + (tANI_U8*)pHdr, frameLen + sizeof(tSirMacMgmtHdr), 0, + WDA_GET_RX_CH( pRxPacketInfo ), psessionEntry, 0); + } + else + { + limLog( pMac, LOGE, FL("Dropping the vendor specific action frame because of( " + "WES Mode not enabled (WESMODE = %d) or OUI mismatch (%02x %02x %02x) or " + "not received with SelfSta Mac address) system role = %d"), + IS_WES_MODE_ENABLED(pMac), + pVendorSpecific->Oui[0], pVendorSpecific->Oui[1], + pVendorSpecific->Oui[2], + psessionEntry->limSystemRole ); + } + } + break; #endif case SIR_MAC_ACTION_PUBLIC_USAGE: switch(pActionHdr->actionID) { @@ -2132,22 +2119,8 @@ limProcessActionFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession ps #ifdef WLAN_FEATURE_11W case SIR_MAC_ACTION_SA_QUERY: { - PELOGE(limLog(pMac, LOG1, FL("SA Query Action category %d action %d."), pActionHdr->category, pActionHdr->actionID);) - switch (pActionHdr->actionID) - { - case SIR_MAC_SA_QUERY_REQ: - /**11w SA query request action frame received**/ - /* Respond directly to the incoming request in LIM */ - __limProcessSAQueryRequestActionFrame(pMac,(tANI_U8*) pRxPacketInfo, psessionEntry ); - break; - case SIR_MAC_SA_QUERY_RSP: - /**11w SA query response action frame received**/ - /* Forward to the SME to HDD to wpa_supplicant */ - __limProcessSAQueryResponseActionFrame(pMac,(tANI_U8*) pRxPacketInfo, psessionEntry ); - break; - default: - break; - } + /**11w SA query request action frame received**/ + __limProcessSAQueryRequestActionFrame(pMac,(tANI_U8*) pRxPacketInfo, psessionEntry ); break; } #endif @@ -2165,7 +2138,6 @@ limProcessActionFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession ps break; } } - break; } #endif default: diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessAssocReqFrame.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessAssocReqFrame.c index 55ba8f02ab7..27413d48112 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessAssocReqFrame.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessAssocReqFrame.c @@ -1403,6 +1403,7 @@ void limSendMlmAssocInd(tpAniSirGlobal pMac, tpDphHashNode pStaDs, tpPESession p if((pMlmAssocInd->rsnIE.length + pAssocReq->wpa.length) >= SIR_MAC_MAX_IE_LENGTH) { PELOGE(limLog(pMac, LOGE, FL("rsnIEdata index out of bounds %d"), pMlmAssocInd->rsnIE.length);) + palFreeMemory(pMac->hHdd, pMlmAssocInd); return; } pMlmAssocInd->rsnIE.rsnIEdata[pMlmAssocInd->rsnIE.length] = SIR_MAC_WPA_EID; diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessAssocRspFrame.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessAssocRspFrame.c index 41c787f556d..8cd7009fa0f 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessAssocRspFrame.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessAssocRspFrame.c @@ -235,12 +235,7 @@ void limUpdateAssocStaDatas(tpAniSirGlobal pMac, tpDphHashNode pStaDs, tpSirAsso pStaDs->wmeEnabled = 1; } -#ifdef WLAN_FEATURE_11W - if(psessionEntry->limRmfEnabled) - { - pStaDs->rmfEnabled = 1; - } -#endif + } /** @@ -441,9 +436,8 @@ limProcessAssocRspFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tANI_U8 sub } VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, - FL("Assoc Resp Frame Received: BSSID %02x:%02x:%02x:%02x:%02x:%02x (Rssi %d)"), - pHdr->bssId[0], pHdr->bssId[1], pHdr->bssId[2], - pHdr->bssId[3], pHdr->bssId[4], pHdr->bssId[5], + FL("Re/Assoc Resp Frame Received: BSSID " MAC_ADDRESS_STR " (RSSI %d)"), + MAC_ADDR_ARRAY(pHdr->bssId), (uint)abs((tANI_S8)WDA_GET_RX_RSSI_DB(pRxPacketInfo))); // Get pointer to Re/Association Response frame body diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessAuthFrame.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessAuthFrame.c index 7f9b288e42a..01b581c4ac8 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessAuthFrame.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessAuthFrame.c @@ -9,6 +9,7 @@ * above copyright notice and this permission notice appear in all * copies. * + * Airgo Networks, Inc proprietary. All rights reserved. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE @@ -39,9 +40,8 @@ * PERFORMANCE OF THIS SOFTWARE. */ + /* - * - * Airgo Networks, Inc proprietary. All rights reserved. * This file limProcessAuthFrame.cc contains the code * for processing received Authentication Frame. * Author: Chandra Modumudi @@ -202,9 +202,8 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse } VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, - FL("Auth Frame Received: BSSID %02x:%02x:%02x:%02x:%02x:%02x (Rssi %d)"), - pHdr->bssId[0], pHdr->bssId[1], pHdr->bssId[2], - pHdr->bssId[3], pHdr->bssId[4], pHdr->bssId[5], + FL("Auth Frame Received: BSSID " MAC_ADDRESS_STR " (RSSI %d)"), + MAC_ADDR_ARRAY(pHdr->bssId), (uint)abs((tANI_S8)WDA_GET_RX_RSSI_DB(pRxPacketInfo))); pBody = WDA_GET_RX_MPDU_DATA(pRxPacketInfo); @@ -1685,9 +1684,8 @@ tSirRetStatus limProcessAuthFrameNoSession(tpAniSirGlobal pMac, tANI_U8 *pBd, vo frameLen = WDA_GET_RX_PAYLOAD_LEN(pBd); VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, - FL("Auth Frame Received: BSSID %02x:%02x:%02x:%02x:%02x:%02x (Rssi %d)"), - pHdr->bssId[0], pHdr->bssId[1], pHdr->bssId[2], - pHdr->bssId[3], pHdr->bssId[4], pHdr->bssId[5], + FL("Auth Frame Received: BSSID " MAC_ADDRESS_STR " (RSSI %d)"), + MAC_ADDR_ARRAY(pHdr->bssId), (uint)abs((tANI_S8)WDA_GET_RX_RSSI_DB(pBd))); // Check for the operating channel and see what needs to be done next. diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessBeaconFrame.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessBeaconFrame.c index 4a3dd869561..bebfa11b842 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessBeaconFrame.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessBeaconFrame.c @@ -121,7 +121,7 @@ limProcessBeaconFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession ps if(eHAL_STATUS_SUCCESS != palAllocateMemory(pMac->hHdd, (void **)&pBeacon, sizeof(tSchBeaconStruct))) { - limLog(pMac, LOGE, FL("Unable to PAL allocate memory in limProcessBeaconFrame\n") ); + limLog(pMac, LOGE, FL("Unable to PAL allocate memory in limProcessBeaconFrame") ); return; } @@ -132,7 +132,7 @@ limProcessBeaconFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession ps // Received wrongly formatted/invalid Beacon. // Ignore it and move on. limLog(pMac, LOGW, - FL("Received invalid Beacon in state %X\n"), + FL("Received invalid Beacon in state %X"), psessionEntry->limMlmState); limPrintMlmState(pMac, LOGW, psessionEntry->limMlmState); palFreeMemory(pMac->hHdd, pBeacon); @@ -214,7 +214,7 @@ limProcessBeaconFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession ps } else { - PELOG1(limLog(pMac, LOG1, FL("Received Beacon in unexpected state %d\n"), + PELOG1(limLog(pMac, LOG1, FL("Received Beacon in unexpected state %d"), psessionEntry->limMlmState); limPrintMlmState(pMac, LOG1, psessionEntry->limMlmState);) #ifdef WLAN_DEBUG @@ -265,14 +265,14 @@ limProcessBeaconFrameNoSession(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo) if(eHAL_STATUS_SUCCESS != palAllocateMemory(pMac->hHdd, (void **)&pBeacon, sizeof(tSchBeaconStruct))) { - limLog(pMac, LOGE, FL("Unable to PAL allocate memory in limProcessBeaconFrameNoSession\n") ); + limLog(pMac, LOGE, FL("Unable to PAL allocate memory in limProcessBeaconFrameNoSession") ); return; } if (sirConvertBeaconFrame2Struct(pMac, (tANI_U8 *) pRxPacketInfo, pBeacon) != eSIR_SUCCESS) { // Received wrongly formatted/invalid Beacon. Ignore and move on. - limLog(pMac, LOGW, FL("Received invalid Beacon in global MLM state %X\n"), pMac->lim.gLimMlmState); + limLog(pMac, LOGW, FL("Received invalid Beacon in global MLM state %X"), pMac->lim.gLimMlmState); limPrintMlmState(pMac, LOGW, pMac->lim.gLimMlmState); palFreeMemory(pMac->hHdd, pBeacon); return; @@ -295,7 +295,7 @@ limProcessBeaconFrameNoSession(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo) } // end of (eLIM_MLM_WT_PROBE_RESP_STATE) || (eLIM_MLM_PASSIVE_SCAN_STATE) else { - limLog(pMac, LOG1, FL("Rcvd Beacon in unexpected MLM state %d\n"), pMac->lim.gLimMlmState); + limLog(pMac, LOG1, FL("Rcvd Beacon in unexpected MLM state %d"), pMac->lim.gLimMlmState); limPrintMlmState(pMac, LOG1, pMac->lim.gLimMlmState); #ifdef WLAN_DEBUG pMac->lim.gLimUnexpBcnCnt++; diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessCfgUpdates.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessCfgUpdates.c index 3be5f67c0ab..6ae8ee53b82 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessCfgUpdates.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessCfgUpdates.c @@ -129,13 +129,13 @@ limSetDefaultKeyIdAndKeys(tpAniSirGlobal pMac) tANI_U32 val; tANI_U32 dkCfgId; - PELOG1(limLog(pMac, LOG1, FL("Setting default keys at SP\n"));) + PELOG1(limLog(pMac, LOG1, FL("Setting default keys at SP"));) if (wlan_cfgGetInt(pMac, WNI_CFG_WEP_DEFAULT_KEYID, &val) != eSIR_SUCCESS) { limLog(pMac, LOGP, - FL("Unable to retrieve defaultKeyId from CFG\n")); + FL("Unable to retrieve defaultKeyId from CFG")); } dkCfgId = limGetCfgIdOfDefaultKeyid(val); #endif @@ -158,7 +158,7 @@ void limSetCfgProtection(tpAniSirGlobal pMac, tpPESession pesessionEntry) else{ limLog(pMac, LOG1, FL(" frm11a = %d, from11b = %d, frm11g = %d, " "ht20 = %d, nongf = %d, lsigTxop = %d, " - "rifs = %d, obss = %d\n"), + "rifs = %d, obss = %d"), pesessionEntry->cfgProtection.fromlla, pesessionEntry->cfgProtection.fromllb, pesessionEntry->cfgProtection.fromllg, @@ -172,7 +172,7 @@ void limSetCfgProtection(tpAniSirGlobal pMac, tpPESession pesessionEntry) else{ if (wlan_cfgGetInt(pMac, WNI_CFG_FORCE_POLICY_PROTECTION, &val) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("reading WNI_CFG_FORCE_POLICY_PROTECTION cfg failed\n")); + limLog(pMac, LOGP, FL("reading WNI_CFG_FORCE_POLICY_PROTECTION cfg failed")); return; } else @@ -180,7 +180,7 @@ void limSetCfgProtection(tpAniSirGlobal pMac, tpPESession pesessionEntry) if (wlan_cfgGetInt(pMac, WNI_CFG_PROTECTION_ENABLED, &val) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("reading protection cfg failed\n")); + limLog(pMac, LOGP, FL("reading protection cfg failed")); return; } @@ -221,7 +221,7 @@ static tSirRetStatus limUpdateTriggerStaBkScanFlag(tpAniSirGlobal pMac) if(wlan_cfgGetInt(pMac, WNI_CFG_TRIG_STA_BK_SCAN, &val) != eSIR_SUCCESS) { - PELOG1(limLog(pMac, LOG1, FL("Failed to get WNI_CFG_TRIG_STA_BK_SCAN from cfg\n"));) + PELOG1(limLog(pMac, LOG1, FL("Failed to get WNI_CFG_TRIG_STA_BK_SCAN from cfg"));) return eSIR_FAILURE; } @@ -271,7 +271,7 @@ limHandleCFGparamUpdate(tpAniSirGlobal pMac, tANI_U32 cfgId) tSirMacHTCapabilityInfo *pHTCapabilityInfo; tSirMacHTParametersInfo *pAmpduParamInfo; - PELOG3(limLog(pMac, LOG3, FL("Handling CFG parameter id %X update\n"), cfgId);) + PELOG3(limLog(pMac, LOG3, FL("Handling CFG parameter id %X update"), cfgId);) switch (cfgId) { case WNI_CFG_WEP_DEFAULT_KEYID: @@ -289,13 +289,13 @@ limHandleCFGparamUpdate(tpAniSirGlobal pMac, tANI_U32 cfgId) &val1) != eSIR_SUCCESS) { limLog(pMac, LOGP, - FL("Unable to retrieve excludeUnencr from CFG\n")); + FL("Unable to retrieve excludeUnencr from CFG")); } #if 0 halSetSpExclUndecrypted(pMac, (tHalBitVal) val); #else limLog(pMac, LOGE, - FL("Unsupported CFG: WNI_CFG_EXCLUDE_UNENCRYPTED\n")); + FL("Unsupported CFG: WNI_CFG_EXCLUDE_UNENCRYPTED")); #endif break; @@ -317,7 +317,7 @@ limHandleCFGparamUpdate(tpAniSirGlobal pMac, tANI_U32 cfgId) if (wlan_cfgGetInt(pMac, WNI_CFG_BACKGROUND_SCAN_PERIOD, &val1) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("could not retrieve Background scan period value\n")); + limLog(pMac, LOGP, FL("could not retrieve Background scan period value")); break; } if (val1 == 0) @@ -337,7 +337,7 @@ limHandleCFGparamUpdate(tpAniSirGlobal pMac, tANI_U32 cfgId) /// Could not activate background scan timer. // Log error limLog(pMac, LOGP, - FL("could not activate background scan timer\n")); + FL("could not activate background scan timer")); pMac->lim.gLimBackgroundScanStarted = FALSE; pMac->lim.gLimBackgroundScanTerminate = TRUE; } @@ -348,14 +348,14 @@ limHandleCFGparamUpdate(tpAniSirGlobal pMac, tANI_U32 cfgId) } PELOG3(limLog(pMac, LOG3, - FL("Updated Background scan period\n"));) + FL("Updated Background scan period"));) } break; case WNI_CFG_BG_SCAN_CHANNEL_LIST: PELOG1(limLog(pMac, LOG1, - FL("VALID_CHANNEL_LIST has changed, reset next bg scan channel\n"));) + FL("VALID_CHANNEL_LIST has changed, reset next bg scan channel"));) pMac->lim.gLimBackgroundScanChannelId = 0; break; @@ -364,7 +364,7 @@ limHandleCFGparamUpdate(tpAniSirGlobal pMac, tANI_U32 cfgId) if(limUpdateTriggerStaBkScanFlag(pMac) != eSIR_SUCCESS) { PELOG2(limLog(pMac, LOG2, - FL("Updating lim trigger sta bk scan global flag failed!\n"));) + FL("Updating lim trigger sta bk scan global flag failed!"));) } break; @@ -381,150 +381,148 @@ limHandleCFGparamUpdate(tpAniSirGlobal pMac, tANI_U32 cfgId) status = limPostMsgApi(pMac, &msg); if (status != TX_SUCCESS) - PELOGE(limLog(pMac, LOGE, FL("Failed limPostMsgApi\n"), status);) + PELOGE(limLog(pMac, LOGE, FL("Failed limPostMsgApi"), status);) break; } case WNI_CFG_GREENFIELD_CAPABILITY: if (wlan_cfgGetInt(pMac, WNI_CFG_HT_CAP_INFO, &val1) != eSIR_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("could not retrieve HT Cap Info CFG\n"));) + PELOGE(limLog(pMac, LOGE, FL("could not retrieve HT Cap Info CFG"));) break; } if (wlan_cfgGetInt(pMac, WNI_CFG_GREENFIELD_CAPABILITY, &val2) != eSIR_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("could not retrieve GreenField CFG\n"));) + PELOGE(limLog(pMac, LOGE, FL("could not retrieve GreenField CFG"));) break; } val16 = ( tANI_U16 ) val1; pHTCapabilityInfo = ( tSirMacHTCapabilityInfo* ) &val16; pHTCapabilityInfo->greenField = (tANI_U16)val2; if(cfgSetInt(pMac, WNI_CFG_HT_CAP_INFO, *(tANI_U16*)pHTCapabilityInfo) != eSIR_SUCCESS) - PELOGE(limLog(pMac, LOGE, FL("could not update HT Cap Info CFG\n"));) + PELOGE(limLog(pMac, LOGE, FL("could not update HT Cap Info CFG"));) break; case WNI_CFG_HT_RX_STBC: if (wlan_cfgGetInt(pMac, WNI_CFG_HT_CAP_INFO, &val1) != eSIR_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("could not retrieve WNI_CFG_HT_CAP_INFO \n"));) + PELOGE(limLog(pMac, LOGE, FL("could not retrieve WNI_CFG_HT_CAP_INFO "));) break; } if (wlan_cfgGetInt(pMac, WNI_CFG_HT_RX_STBC, &val2) != eSIR_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("could not retrieve WNI_CFG_HT_RX_STBC\n"));) + PELOGE(limLog(pMac, LOGE, FL("could not retrieve WNI_CFG_HT_RX_STBC"));) break; } val16 = ( tANI_U16 ) val1; pHTCapabilityInfo = ( tSirMacHTCapabilityInfo* ) &val16; pHTCapabilityInfo->rxSTBC = (tANI_U16)val2; if(cfgSetInt(pMac, WNI_CFG_HT_CAP_INFO, *(tANI_U16*)pHTCapabilityInfo) != eSIR_SUCCESS) - PELOGE(limLog(pMac, LOGE, FL("could not update HT Cap Info CFG\n"));) + PELOGE(limLog(pMac, LOGE, FL("could not update HT Cap Info CFG"));) break; case WNI_CFG_MAX_AMSDU_LENGTH: if (wlan_cfgGetInt(pMac, WNI_CFG_HT_CAP_INFO, &val1) != eSIR_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("could not retrieve HT Cap Info CFG\n"));) + PELOGE(limLog(pMac, LOGE, FL("could not retrieve HT Cap Info CFG"));) break; } if (wlan_cfgGetInt(pMac, WNI_CFG_MAX_AMSDU_LENGTH, &val2) != eSIR_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("could not retrieve Max AMSDU Length CFG\n"));) + PELOGE(limLog(pMac, LOGE, FL("could not retrieve Max AMSDU Length CFG"));) break; } val16 = ( tANI_U16 ) val1; pHTCapabilityInfo = ( tSirMacHTCapabilityInfo* ) &val16; pHTCapabilityInfo->maximalAMSDUsize = (tANI_U16)val2; if(cfgSetInt(pMac, WNI_CFG_HT_CAP_INFO, *(tANI_U16*)pHTCapabilityInfo) != eSIR_SUCCESS) - PELOGE(limLog(pMac, LOGE, FL("could not update HT Cap Info CFG\n"));) + PELOGE(limLog(pMac, LOGE, FL("could not update HT Cap Info CFG"));) break; case WNI_CFG_SHORT_GI_20MHZ: if (wlan_cfgGetInt(pMac, WNI_CFG_HT_CAP_INFO, &val1) != eSIR_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("could not retrieve HT Cap CFG\n"));) + PELOGE(limLog(pMac, LOGE, FL("could not retrieve HT Cap CFG"));) break; } if (wlan_cfgGetInt(pMac, WNI_CFG_SHORT_GI_20MHZ, &val2) != eSIR_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("could not retrieve shortGI 20Mhz CFG\n"));) + PELOGE(limLog(pMac, LOGE, FL("could not retrieve shortGI 20Mhz CFG"));) break; } val16 = ( tANI_U16 ) val1; pHTCapabilityInfo = ( tSirMacHTCapabilityInfo* ) &val16; pHTCapabilityInfo->shortGI20MHz = (tANI_U16)val2; if(cfgSetInt(pMac, WNI_CFG_HT_CAP_INFO, *(tANI_U16*)pHTCapabilityInfo) != eSIR_SUCCESS) - PELOGE(limLog(pMac, LOGE, FL("could not update HT Cap Info CFG\n"));) + PELOGE(limLog(pMac, LOGE, FL("could not update HT Cap Info CFG"));) break; case WNI_CFG_SHORT_GI_40MHZ: if (wlan_cfgGetInt(pMac, WNI_CFG_HT_CAP_INFO, &val1) != eSIR_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("could not retrieve HT Cap CFG\n"));) + PELOGE(limLog(pMac, LOGE, FL("could not retrieve HT Cap CFG"));) break; } if (wlan_cfgGetInt(pMac, WNI_CFG_SHORT_GI_40MHZ, &val2) != eSIR_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("could not retrieve shortGI 40Mhz CFG\n"));) + PELOGE(limLog(pMac, LOGE, FL("could not retrieve shortGI 40Mhz CFG"));) break; } val16 = ( tANI_U16 ) val1; pHTCapabilityInfo = ( tSirMacHTCapabilityInfo* ) &val16; pHTCapabilityInfo->shortGI40MHz = (tANI_U16)val2; if(cfgSetInt(pMac, WNI_CFG_HT_CAP_INFO, *(tANI_U16*)pHTCapabilityInfo) != eSIR_SUCCESS) - PELOGE(limLog(pMac, LOGE, FL("could not update HT Cap Info CFG\n"));) + PELOGE(limLog(pMac, LOGE, FL("could not update HT Cap Info CFG"));) break; case WNI_CFG_MPDU_DENSITY: if (wlan_cfgGetInt(pMac, WNI_CFG_HT_AMPDU_PARAMS, &val1) != eSIR_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("could not retrieve HT AMPDU Param CFG\n"));) + PELOGE(limLog(pMac, LOGE, FL("could not retrieve HT AMPDU Param CFG"));) break; } if (wlan_cfgGetInt(pMac, WNI_CFG_MPDU_DENSITY, &val2) != eSIR_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("could not retrieve MPDU Density CFG\n"));) + PELOGE(limLog(pMac, LOGE, FL("could not retrieve MPDU Density CFG"));) break; } val16 = ( tANI_U16 ) val1; pAmpduParamInfo = ( tSirMacHTParametersInfo* ) &val16; pAmpduParamInfo->mpduDensity = (tANI_U8)val2; if(cfgSetInt(pMac, WNI_CFG_HT_AMPDU_PARAMS, *(tANI_U8*)pAmpduParamInfo) != eSIR_SUCCESS) - PELOGE(limLog(pMac, LOGE, FL("could not update HT AMPDU Param CFG\n"));) + PELOGE(limLog(pMac, LOGE, FL("could not update HT AMPDU Param CFG"));) break; case WNI_CFG_MAX_RX_AMPDU_FACTOR: if (wlan_cfgGetInt(pMac, WNI_CFG_HT_AMPDU_PARAMS, &val1) != eSIR_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("could not retrieve HT AMPDU Param CFG\n"));) + PELOGE(limLog(pMac, LOGE, FL("could not retrieve HT AMPDU Param CFG"));) break; } if (wlan_cfgGetInt(pMac, WNI_CFG_MAX_RX_AMPDU_FACTOR, &val2) != eSIR_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("could not retrieve AMPDU Factor CFG\n"));) + PELOGE(limLog(pMac, LOGE, FL("could not retrieve AMPDU Factor CFG"));) break; } val16 = ( tANI_U16 ) val1; pAmpduParamInfo = ( tSirMacHTParametersInfo* ) &val16; pAmpduParamInfo->maxRxAMPDUFactor = (tANI_U8)val2; if(cfgSetInt(pMac, WNI_CFG_HT_AMPDU_PARAMS, *(tANI_U8*)pAmpduParamInfo) != eSIR_SUCCESS) - PELOGE(limLog(pMac, LOGE, FL("could not update HT AMPDU Param CFG\n"));) + PELOGE(limLog(pMac, LOGE, FL("could not update HT AMPDU Param CFG"));) break; case WNI_CFG_HEART_BEAT_THRESHOLD: if (wlan_cfgGetInt(pMac, WNI_CFG_HEART_BEAT_THRESHOLD, &val1) != eSIR_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("could not retrieve WNI_CFG_HEART_BEAT_THRESHOLD CFG\n"));) + PELOGE(limLog(pMac, LOGE, FL("could not retrieve WNI_CFG_HEART_BEAT_THRESHOLD CFG"));) break; } if(!val1) { limDeactivateAndChangeTimer(pMac, eLIM_HEART_BEAT_TIMER); pMac->sys.gSysEnableLinkMonitorMode = 0; - PELOGE(limLog(pMac, LOGE, "Deactivating heartbeat link monitoring\n");) } else { tANI_U16 sessionId; pMac->sys.gSysEnableLinkMonitorMode = 1; - PELOGE(limLog(pMac, LOGE, "Reactivating heartbeat link monitoring\n");) for(sessionId = 0; sessionId < pMac->lim.maxBssId; sessionId++) { if( (pMac->lim.gpSession[sessionId].valid )&& @@ -534,11 +532,15 @@ limHandleCFGparamUpdate(tpAniSirGlobal pMac, tANI_U32 cfgId) { PELOG2(limLog(pMac, LOG2, "HB link monitoring reactivated" " for session=%d", sessionId);) + PELOGW(limLog(pMac, LOGW, "Before reactivating HB timer; parameters are" + " session=%d limMlmState=%d pmmState=%d", sessionId, + pMac->lim.gpSession[sessionId].limMlmState, + pMac->pmm.gPmmState);) limReactivateHeartBeatTimer(pMac, &pMac->lim.gpSession[sessionId]); } else if ( pMac->lim.gpSession[sessionId].valid ) { - PELOG2(limLog(pMac, LOG2, "HB link monitoring not reactivated-" + PELOGW(limLog(pMac, LOGW, "HB link monitoring not reactivated-" "session=%d, limMlmState=%d, gPmmState=%d", sessionId, pMac->lim.gpSession[sessionId].limMlmState, pMac->pmm.gPmmState);) @@ -557,7 +559,7 @@ limHandleCFGparamUpdate(tpAniSirGlobal pMac, tANI_U32 cfgId) if (palAllocateMemory(pMac->hHdd, (void **)&pPowerSaveConfig, sizeof(tSirPowerSaveCfg)) != eHAL_STATUS_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("LIM: Cannot allocate memory for power save configuration\n"));) + PELOGE(limLog(pMac, LOGE, FL("LIM: Cannot allocate memory for power save configuration"));) break; } @@ -568,7 +570,7 @@ limHandleCFGparamUpdate(tpAniSirGlobal pMac, tANI_U32 cfgId) if ( (pmmSendPowerSaveCfg(pMac, pPowerSaveConfig)) != eSIR_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("LIM: pmmSendPowerSaveCfg() failed \n"));) + PELOGE(limLog(pMac, LOGE, FL("LIM: pmmSendPowerSaveCfg() failed "));) } } break; @@ -577,7 +579,7 @@ limHandleCFGparamUpdate(tpAniSirGlobal pMac, tANI_U32 cfgId) case WNI_CFG_DOT11_MODE: if (wlan_cfgGetInt(pMac, WNI_CFG_DOT11_MODE, &val1) != eSIR_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("could not retrieve Dot11 Mode CFG\n"));) + PELOGE(limLog(pMac, LOGE, FL("could not retrieve Dot11 Mode CFG"));) break; } /* TODO */ @@ -585,7 +587,7 @@ limHandleCFGparamUpdate(tpAniSirGlobal pMac, tANI_U32 cfgId) break; case WNI_CFG_ADDBA_REQ_DECLINE: if(wlan_cfgGetInt(pMac, WNI_CFG_ADDBA_REQ_DECLINE, &val1) != eSIR_SUCCESS) { - limLog( pMac, LOGE, FL( "Unable to get ADDBA_REQ_DECLINE cfg\n" )); + limLog( pMac, LOGE, FL( "Unable to get ADDBA_REQ_DECLINE cfg" )); break; } pMac->lim.gAddBA_Declined = (tANI_U8)val1; @@ -593,7 +595,7 @@ limHandleCFGparamUpdate(tpAniSirGlobal pMac, tANI_U32 cfgId) case WNI_CFG_SCAN_IN_POWERSAVE: if(wlan_cfgGetInt(pMac, WNI_CFG_SCAN_IN_POWERSAVE, &val1) != eSIR_SUCCESS) { - limLog( pMac, LOGE, FL( "Unable to get WNI_CFG_SCAN_IN_POWERSAVE \n" )); + limLog( pMac, LOGE, FL( "Unable to get WNI_CFG_SCAN_IN_POWERSAVE " )); break; } pMac->lim.gScanInPowersave = (tANI_U8)val1; @@ -608,6 +610,28 @@ limHandleCFGparamUpdate(tpAniSirGlobal pMac, tANI_U32 cfgId) pMac->lim.gLimAssocStaLimit = (tANI_U16)val1; break; + case WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC: + if (wlan_cfgGetInt + (pMac, WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC, &val1) != + eSIR_SUCCESS) + { + limLog(pMac, LOGE, + FL( "Unable to get WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC")); + break; + } + if (val1) + { + limLog(pMac, LOGW, + FL("BTC requested to disable all RX BA sessions")); + limDelAllBASessionsBtc(pMac); + } + else + { + limLog(pMac, LOGW, + FL("Resetting the WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC")); + } + break; + default: break; } @@ -640,7 +664,7 @@ limApplyConfiguration(tpAniSirGlobal pMac,tpPESession psessionEntry) { tANI_U32 val=0, phyMode; - PELOG2(limLog(pMac, LOG2, FL("Applying config\n"));) + PELOG2(limLog(pMac, LOG2, FL("Applying config"));) limInitWdsInfoParams(pMac); @@ -669,7 +693,7 @@ limApplyConfiguration(tpAniSirGlobal pMac,tpPESession psessionEntry) if(psessionEntry->statypeForBss == STA_ENTRY_SELF) { - PELOG1(limLog(pMac, LOG1, FL("Initializing BT-AMP beacon generation\n"));) + PELOG1(limLog(pMac, LOG1, FL("Initializing BT-AMP beacon generation"));) schSetBeaconInterval(pMac,psessionEntry); schSetFixedBeaconFields(pMac,psessionEntry); } @@ -677,7 +701,7 @@ limApplyConfiguration(tpAniSirGlobal pMac,tpPESession psessionEntry) if (wlan_cfgGetInt(pMac, WNI_CFG_SCAN_IN_POWERSAVE, &val) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("could not retrieve WNI_CFG_SCAN_IN_POWERSAVE\n")); + limLog(pMac, LOGP, FL("could not retrieve WNI_CFG_SCAN_IN_POWERSAVE")); return; } pMac->lim.gScanInPowersave = (tANI_U8) val; @@ -709,39 +733,39 @@ limUpdateConfig(tpAniSirGlobal pMac,tpPESession psessionEntry) #if 0 if (wlan_cfgGetStr(pMac, WNI_CFG_STA_ID, pMac->lim.gLimMyMacAddr, &len) != eSIR_SUCCESS) - limLog(pMac, LOGP, FL("cfg get sta id failed\n")); + limLog(pMac, LOGP, FL("cfg get sta id failed")); #endif //To SUPPORT BT-AMP sirCopyMacAddr(pMac->lim.gLimMyMacAddr,psessionEntry->selfMacAddr); if (wlan_cfgGetInt(pMac, WNI_CFG_SHORT_PREAMBLE, &val) != eSIR_SUCCESS) - limLog(pMac, LOGP, FL("cfg get short preamble failed\n")); + limLog(pMac, LOGP, FL("cfg get short preamble failed")); psessionEntry->beaconParams.fShortPreamble = (val) ? 1 : 0; if (wlan_cfgGetInt(pMac, WNI_CFG_WME_ENABLED, &val) != eSIR_SUCCESS) - limLog(pMac, LOGP, FL("cfg get wme enabled failed\n")); + limLog(pMac, LOGP, FL("cfg get wme enabled failed")); psessionEntry->limWmeEnabled = (val) ? 1 : 0; if (wlan_cfgGetInt(pMac, WNI_CFG_WSM_ENABLED, &val) != eSIR_SUCCESS) - limLog(pMac, LOGP, FL("cfg get wsm enabled failed\n")); + limLog(pMac, LOGP, FL("cfg get wsm enabled failed")); psessionEntry->limWsmEnabled = (val) ? 1 : 0; if ((! psessionEntry->limWmeEnabled) && (psessionEntry->limWsmEnabled)) { - PELOGE(limLog(pMac, LOGE, FL("Can't enable WSM without WME\n"));) + PELOGE(limLog(pMac, LOGE, FL("Can't enable WSM without WME"));) psessionEntry->limWsmEnabled = 0; } if (wlan_cfgGetInt(pMac, WNI_CFG_QOS_ENABLED, &val) != eSIR_SUCCESS) - limLog(pMac, LOGP, FL("cfg get qos enabled failed\n")); + limLog(pMac, LOGP, FL("cfg get qos enabled failed")); psessionEntry->limQosEnabled = (val) ? 1 : 0; if (wlan_cfgGetInt(pMac, WNI_CFG_HCF_ENABLED, &val) != eSIR_SUCCESS) - limLog(pMac, LOGP, FL("cfg get hcf enabled failed\n")); + limLog(pMac, LOGP, FL("cfg get hcf enabled failed")); psessionEntry->limHcfEnabled = (val) ? 1 : 0; // Update the ADD BA Declined configuration if(wlan_cfgGetInt(pMac, WNI_CFG_ADDBA_REQ_DECLINE, &val) != eSIR_SUCCESS) - limLog( pMac, LOGP, FL( "Unable to get ADDBA_REQ_DECLINE cfg\n" )); + limLog( pMac, LOGP, FL( "Unable to get ADDBA_REQ_DECLINE cfg" )); pMac->lim.gAddBA_Declined = (val) ? 0xff : 0x0; // AP: WSM should enable HCF as well, for STA enable WSM only after @@ -750,7 +774,7 @@ limUpdateConfig(tpAniSirGlobal pMac,tpPESession psessionEntry) psessionEntry->limHcfEnabled = 1; if (wlan_cfgGetInt(pMac, WNI_CFG_11D_ENABLED, &val) != eSIR_SUCCESS) - limLog(pMac, LOGP, FL("cfg get 11d enabled failed\n")); + limLog(pMac, LOGP, FL("cfg get 11d enabled failed")); psessionEntry->lim11dEnabled = (val) ? 1 : 0; if(wlan_cfgGetInt(pMac, WNI_CFG_ASSOC_STA_LIMIT, &val) != eSIR_SUCCESS) { @@ -761,7 +785,7 @@ limUpdateConfig(tpAniSirGlobal pMac,tpPESession psessionEntry) if(ccmCfgSetInt(pMac, WNI_CFG_ASSOC_STA_LIMIT, WNI_CFG_ASSOC_STA_LIMIT_STADEF, NULL, eANI_BOOLEAN_FALSE) != eHAL_STATUS_SUCCESS) { - limLog( pMac, LOGP, FL( "cfg get assoc sta limit failed" )); + limLog( pMac, LOGP, FL( "cfg get assoc sta limit failed" )); } val = WNI_CFG_ASSOC_STA_LIMIT_STADEF; } @@ -770,7 +794,7 @@ limUpdateConfig(tpAniSirGlobal pMac,tpPESession psessionEntry) #if defined WLAN_FEATURE_VOWIFI rrmUpdateConfig( pMac, psessionEntry ); #endif - PELOG1(limLog(pMac, LOG1, FL("Updated Lim shadow state based on CFG\n"));) + PELOG1(limLog(pMac, LOG1, FL("Updated Lim shadow state based on CFG"));) } diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessDeauthFrame.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessDeauthFrame.c index ea155f73957..776b36ee831 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessDeauthFrame.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessDeauthFrame.c @@ -94,9 +94,6 @@ limProcessDeauthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession p tpDphHashNode pStaDs; tpPESession pRoamSessionEntry=NULL; tANI_U8 roamSessionId; -#ifdef WLAN_FEATURE_11W - tANI_U32 frameLen; -#endif pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo); @@ -115,7 +112,7 @@ limProcessDeauthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession p // Received Deauth frame from a BC/MC address // Log error and ignore it PELOG1(limLog(pMac, LOG1, - FL("received Deauth frame from a BC/MC address\n"));) + FL("received Deauth frame from a BC/MC address"));) return; } @@ -125,28 +122,10 @@ limProcessDeauthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession p // Received Deauth frame for a MC address // Log error and ignore it PELOG1(limLog(pMac, LOG1, - FL("received Deauth frame for a MC address\n"));) + FL("received Deauth frame for a MC address"));) return; } - -#ifdef WLAN_FEATURE_11W - /* PMF: If this session is a PMF session, then ensure that this frame was protected */ - if(psessionEntry->limRmfEnabled && (WDA_GET_RX_DPU_FEEDBACK(pRxPacketInfo) & DPU_FEEDBACK_UNPROTECTED_ERROR)) - { - PELOGE(limLog(pMac, LOGE, FL("received an unprotected deauth from AP"));) - // If the frame received is unprotected, forward it to the supplicant to initiate - // an SA query - frameLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); - - //send the unprotected frame indication to SME - limSendSmeUnprotectedMgmtFrameInd( pMac, pHdr->fc.subType, - (tANI_U8*)pHdr, (frameLen + sizeof(tSirMacMgmtHdr)), - psessionEntry->smeSessionId, psessionEntry); - return; - } -#endif - // Get reasonCode from Deauthentication frame body reasonCode = sirReadU16(pBody); @@ -157,8 +136,8 @@ limProcessDeauthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession p if (limCheckDisassocDeauthAckPending(pMac, (tANI_U8*)pHdr->sa)) { - PELOGW(limLog(pMac, LOGE, - FL("Ignore the Deauth received, while waiting for ack of disassoc/deauth\n"));) + PELOGW(limLog(pMac, LOGW, + FL("Ignore the Deauth received, while waiting for ack of disassoc/deauth"));) limCleanUpDisassocDeauthReq(pMac,(tANI_U8*)pHdr->sa, 1); return; } @@ -177,7 +156,7 @@ limProcessDeauthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession p // Invalid reasonCode in received Deauthentication frame // Log error and ignore the frame PELOG1(limLog(pMac, LOG1, - FL("received Deauth frame with invalid reasonCode %d from \n"), + FL("received Deauth frame with invalid reasonCode %d from "), reasonCode); limPrintMacAddr(pMac, pHdr->sa, LOG1);) @@ -201,7 +180,7 @@ limProcessDeauthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession p // Invalid reasonCode in received Deauth frame // Log error and ignore the frame PELOG1(limLog(pMac, LOG1, - FL("received Deauth frame with invalid reasonCode %d from \n"), + FL("received Deauth frame with invalid reasonCode %d from "), reasonCode); limPrintMacAddr(pMac, pHdr->sa, LOG1);) @@ -211,11 +190,11 @@ limProcessDeauthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession p else { // Received Deauth frame in either IBSS - // or un-known role. Log error and ignore it - limLog(pMac, LOGE, - FL("received Deauth frame with reasonCode %d in role %d from \n"), + // or un-known role. Log and ignore it + limLog(pMac, LOG1, + FL("received Deauth frame with reasonCode %d in role %d from "), reasonCode, psessionEntry->limSystemRole); - limPrintMacAddr(pMac, pHdr->sa, LOGE); + limPrintMacAddr(pMac, pHdr->sa, LOG1); return; } @@ -244,7 +223,7 @@ limProcessDeauthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession p } if (limIsReassocInProgress(pMac,psessionEntry) || limIsReassocInProgress(pMac,pRoamSessionEntry)) { if (!IS_REASSOC_BSSID(pMac,pHdr->sa,psessionEntry)) { - PELOGE(limLog(pMac, LOGE, FL("Rcv Deauth from unknown/different AP while ReAssoc. Ignore \n"));) + PELOGE(limLog(pMac, LOGE, FL("Rcv Deauth from unknown/different AP while ReAssoc. Ignore "));) limPrintMacAddr(pMac, pHdr->sa, LOGE); limPrintMacAddr(pMac, psessionEntry->limReAssocbssId, LOGE); return; @@ -254,7 +233,7 @@ limProcessDeauthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession p * Drop ReAssoc and Restore the Previous context( current connected AP). */ if (!IS_CURRENT_BSSID(pMac, pHdr->sa,psessionEntry)) { - PELOGE(limLog(pMac, LOGE, FL("received DeAuth from the New AP to which ReAssoc is sent \n"));) + PELOGE(limLog(pMac, LOGE, FL("received DeAuth from the New AP to which ReAssoc is sent "));) limPrintMacAddr(pMac, pHdr->sa, LOGE); limPrintMacAddr(pMac, psessionEntry->bssId, LOGE); limRestorePreReassocState(pMac, @@ -270,10 +249,10 @@ limProcessDeauthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession p if(psessionEntry->limSystemRole != eLIM_AP_ROLE ){ if (!IS_CURRENT_BSSID(pMac, pHdr->bssId, psessionEntry)) { - PELOGE(limLog(pMac, LOGE, FL("received DeAuth from an AP other than we're trying to join. Ignore. \n"));) + PELOGE(limLog(pMac, LOGE, FL("received DeAuth from an AP other than we're trying to join. Ignore. "));) if (limSearchPreAuthList(pMac, pHdr->sa)) { - PELOGE(limLog(pMac, LOGE, FL("Preauth entry exist. Deleting... \n"));) + PELOG1(limLog(pMac, LOG1, FL("Preauth entry exist. Deleting... "));) limDeletePreAuthNode(pMac, pHdr->sa); } return; @@ -475,7 +454,7 @@ limProcessDeauthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession p psessionEntry->limAssocResponseData = NULL; } - PELOGE(limLog(pMac, LOGE, FL("Rcv Deauth from ReAssoc AP. Issue REASSOC_CNF. \n"));) + PELOGE(limLog(pMac, LOGE, FL("Rcv Deauth from ReAssoc AP. Issue REASSOC_CNF. "));) /* * TODO: Instead of overloading eSIR_SME_FT_REASSOC_TIMEOUT_FAILURE * it would have been good to define/use a different failure type. diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessDisassocFrame.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessDisassocFrame.c index 6666e7b7197..7c9f6d40d3f 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessDisassocFrame.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessDisassocFrame.c @@ -39,8 +39,9 @@ * PERFORMANCE OF THIS SOFTWARE. */ + + /* - * * Airgo Networks, Inc proprietary. All rights reserved. * This file limProcessDisassocFrame.cc contains the code * for processing Disassocation Frame. @@ -93,9 +94,7 @@ limProcessDisassocFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession tpSirMacMgmtHdr pHdr; tpDphHashNode pStaDs; tLimMlmDisassocInd mlmDisassocInd; -#ifdef WLAN_FEATURE_11W - tANI_U32 frameLen; -#endif + pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo); pBody = WDA_GET_RX_MPDU_DATA(pRxPacketInfo); @@ -106,7 +105,7 @@ limProcessDisassocFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession // Received Disassoc frame from a BC/MC address // Log error and ignore it PELOG1(limLog(pMac, LOG1, - FL("received Disassoc frame from a BC/MC address\n"));) + FL("received Disassoc frame from a BC/MC address"));) return; } @@ -116,32 +115,16 @@ limProcessDisassocFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession // Received Disassoc frame for a MC address // Log error and ignore it PELOG1(limLog(pMac, LOG1, - FL("received Disassoc frame for a MC address\n"));) + FL("received Disassoc frame for a MC address"));) return; } -#ifdef WLAN_FEATURE_11W - /* PMF: If this session is a PMF session, then ensure that this frame was protected */ - if(psessionEntry->limRmfEnabled && (WDA_GET_RX_DPU_FEEDBACK(pRxPacketInfo) & DPU_FEEDBACK_UNPROTECTED_ERROR)) - { - PELOGE(limLog(pMac, LOGE, FL("received an unprotected disassoc from AP"));) - // If the frame received is unprotected, forward it to the supplicant to initiate - // an SA query - frameLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); - //send the unprotected frame indication to SME - limSendSmeUnprotectedMgmtFrameInd( pMac, pHdr->fc.subType, - (tANI_U8*)pHdr, (frameLen + sizeof(tSirMacMgmtHdr)), - psessionEntry->smeSessionId, psessionEntry); - return; - } -#endif - // Get reasonCode from Disassociation frame body reasonCode = sirReadU16(pBody); PELOG2(limLog(pMac, LOG2, - FL("Received Disassoc frame (mlm state %d sme state %d), with reason code %d from "MAC_ADDRESS_STR), + FL("Received Disassoc frame (mlm state %d sme state %d), with reason code %d from "MAC_ADDRESS_STR), psessionEntry->limMlmState, psessionEntry->limSmeState, reasonCode, MAC_ADDR_ARRAY(pHdr->sa));) /** @@ -166,8 +149,8 @@ limProcessDisassocFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession if (limCheckDisassocDeauthAckPending(pMac, (tANI_U8*)pHdr->sa)) { - PELOGW(limLog(pMac, LOGE, - FL("Ignore the DisAssoc received, while waiting for ack of disassoc/deauth\n"));) + PELOGW(limLog(pMac, LOGW, + FL("Ignore the DisAssoc received, while waiting for ack of disassoc/deauth"));) limCleanUpDisassocDeauthReq(pMac,(tANI_U8*)pHdr->sa, 1); return; } @@ -180,14 +163,14 @@ limProcessDisassocFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession * drop/ignore the DisAssoc received */ if (!IS_REASSOC_BSSID(pMac,pHdr->sa,psessionEntry)) { - PELOGW(limLog(pMac, LOGW, FL("Ignore the DisAssoc received, while Processing ReAssoc with different/unknown AP\n"));) + PELOGW(limLog(pMac, LOGW, FL("Ignore the DisAssoc received, while Processing ReAssoc with different/unknown AP"));) return; } /** If the Disassoc is received from the new AP to which we tried to ReAssociate * Drop ReAssoc and Restore the Previous context( current connected AP). */ if (!IS_CURRENT_BSSID(pMac, pHdr->sa,psessionEntry)) { - PELOGW(limLog(pMac, LOGW, FL("received Disassoc from the New AP to which ReAssoc is sent \n"));) + PELOGW(limLog(pMac, LOGW, FL("received Disassoc from the New AP to which ReAssoc is sent "));) limRestorePreReassocState(pMac, eSIR_SME_REASSOC_REFUSED, reasonCode,psessionEntry); return; @@ -213,7 +196,7 @@ limProcessDisassocFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession default: // Invalid reasonCode in received Disassociation frame PELOG1(limLog(pMac, LOG1, - FL("received Disassoc frame with invalid reasonCode %d from \n"), + FL("received Disassoc frame with invalid reasonCode %d from "), reasonCode); limPrintMacAddr(pMac, pHdr->sa, LOG1);) break; @@ -238,10 +221,10 @@ limProcessDisassocFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession case eSIR_MAC_GR_KEY_UPDATE_TIMEOUT_REASON: case eSIR_MAC_RSN_IE_MISMATCH_REASON: case eSIR_MAC_1X_AUTH_FAILURE_REASON: - case eSIR_MAC_PREV_AUTH_NOT_VALID_REASON: // Valid reasonCode in received Disassociation frame break; + case eSIR_MAC_DEAUTH_LEAVING_BSS_REASON: case eSIR_MAC_DISASSOC_LEAVING_BSS_REASON: // Valid reasonCode in received Disassociation frame // as long as we're not about to channel switch @@ -249,7 +232,7 @@ limProcessDisassocFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession { limLog(pMac, LOGW, FL("Ignoring disassoc frame due to upcoming " - "channel switch, from\n"), + "channel switch, from"), reasonCode); limPrintMacAddr(pMac, pHdr->sa, LOGW); return; @@ -260,7 +243,7 @@ limProcessDisassocFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession // Invalid reasonCode in received Disassociation frame // Log error and ignore the frame PELOG1(limLog(pMac, LOG1, - FL("received Disassoc frame with invalid reasonCode %d from \n"), + FL("received Disassoc frame with invalid reasonCode %d from "), reasonCode); limPrintMacAddr(pMac, pHdr->sa, LOG1);) return; @@ -269,18 +252,18 @@ limProcessDisassocFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession else { // Received Disassociation frame in either IBSS - // or un-known role. Log error and ignore it - limLog(pMac, LOGE, - FL("received Disassoc frame with invalid reasonCode %d in role %d in sme state %d from \n"), + // or un-known role. Log and ignore it + limLog(pMac, LOG1, + FL("received Disassoc frame with invalid reasonCode %d in role %d in sme state %d from "), reasonCode, psessionEntry->limSystemRole, psessionEntry->limSmeState); - limPrintMacAddr(pMac, pHdr->sa, LOGE); + limPrintMacAddr(pMac, pHdr->sa, LOG1); return; } // Disassociation from peer MAC entity - PELOGE(limLog(pMac, LOGE, + PELOG1(limLog(pMac, LOG1, FL("Received Disassoc frame from sta with assocId=%d with reasonCode=%d. Peer MAC is "MAC_ADDRESS_STR), pStaDs->assocId, reasonCode, MAC_ADDR_ARRAY(pHdr->sa));) @@ -332,7 +315,7 @@ limProcessDisassocFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession * failure result code. By design, SME will then issue "Disassoc" * and cleanup will happen at that time. */ - PELOGE(limLog(pMac, LOGE, FL("received Disassoc from AP while waiting for Reassoc Rsp\n"));) + PELOGE(limLog(pMac, LOGE, FL("received Disassoc from AP while waiting for Reassoc Rsp"));) if (psessionEntry->limAssocResponseData) { palFreeMemory(pMac->hHdd, psessionEntry->limAssocResponseData); diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessMessageQueue.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessMessageQueue.c index 8b3e25daf24..050cf8c7def 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessMessageQueue.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessMessageQueue.c @@ -156,7 +156,7 @@ defMsgDecision(tpAniSirGlobal pMac, tpSirMsgQ limMsg) #endif (limMsg->type != WDA_ADD_TS_RSP)) { - PELOG1(limLog(pMac, LOG1, FL("Defer the current message %s , gLimProcessDefdMsgs is false and system is not in scan/learn mode\n"), + PELOG1(limLog(pMac, LOG1, FL("Defer the current message %s , gLimProcessDefdMsgs is false and system is not in scan/learn mode"), limMsgStr(limMsg->type));) // Defer processsing this message @@ -290,7 +290,7 @@ limHandleFramesInScanState(tpAniSirGlobal pMac, tpSirMsgQ limMsg, tANI_U8 *pRxPa *deferMsg = false; pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo); fc = pHdr->fc; - limLog( pMac, LOG2, FL("ProtVersion %d, Type %d, Subtype %d\n"), + limLog( pMac, LOG2, FL("ProtVersion %d, Type %d, Subtype %d"), fc.protVer, fc.type, fc.subType ); // defer all message in scan state except for Beacons and Probe Response @@ -355,7 +355,7 @@ static void limHandleUnknownA2IndexFrames(tpAniSirGlobal pMac, void *pRxPacketIn if (limIsGroupAddr(pMacHdr->addr2)) { - PELOG2(limLog(pMac, LOG2, FL("Ignoring A2 Invalid Packet received for MC/BC:\n")); + PELOG2(limLog(pMac, LOG2, FL("Ignoring A2 Invalid Packet received for MC/BC:")); limPrintMacAddr(pMac, pMacHdr->addr2, LOG2);) return; @@ -366,7 +366,7 @@ static void limHandleUnknownA2IndexFrames(tpAniSirGlobal pMac, void *pRxPacketIn { /* ADD handling of Public Action Frame */ LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, \ - ("limHandleUnknownA2IndexFrames: type=0x%x, subtype=0x%x\n"),pMacHdr->fc.type, pMacHdr->fc.subType)); + ("limHandleUnknownA2IndexFrames: type=0x%x, subtype=0x%x"),pMacHdr->fc.type, pMacHdr->fc.subType)); switch (pMacHdr->fc.type) { case SIR_MAC_MGMT_FRAME: @@ -446,7 +446,7 @@ limCheckMgmtRegisteredFrames(tpAniSirGlobal pMac, tANI_U8 *pBd, && (subType == SIR_MAC_MGMT_RESERVED15) ) { limLog( pMac, LOG3, - FL("rcvd frame match with SIR_MAC_MGMT_RESERVED15\n")); + FL("rcvd frame match with SIR_MAC_MGMT_RESERVED15")); match = VOS_TRUE; break; } @@ -485,7 +485,7 @@ limCheckMgmtRegisteredFrames(tpAniSirGlobal pMac, tANI_U8 *pBd, if (match) { limLog( pMac, LOG1, - FL("rcvd frame match with registered frame params\n")); + FL("rcvd frame match with registered frame params")); /* Indicate this to SME */ limSendSmeMgmtFrameInd( pMac, pHdr->fc.subType, (tANI_U8*)pHdr, @@ -546,10 +546,37 @@ limHandle80211Frames(tpAniSirGlobal pMac, tpSirMsgQ limMsg, tANI_U8 *pDeferMsg) fcOffset = (v_U8_t)WDA_GET_RX_MPDU_HEADER_OFFSET(pRxPacketInfo); fc = pHdr->fc; - limLog( pMac, LOG4, FL("ProtVersion %d, Type %d, Subtype %d rateIndex=%d\n"), + limLog( pMac, LOG4, FL("ProtVersion %d, Type %d, Subtype %d rateIndex=%d"), fc.protVer, fc.type, fc.subType, WDA_GET_RX_MAC_RATE_IDX(pRxPacketInfo)); - +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if ( WDA_GET_ROAMCANDIDATEIND(pRxPacketInfo)) + { + limLog( pMac, LOG2, FL("Notify SME with candidate ind")); + //send a session 0 for now - TBD + limSendSmeCandidateFoundInd(pMac, 0); + goto end; + } + if (WDA_GET_OFFLOADSCANLEARN(pRxPacketInfo)) + { + if (fc.subType == SIR_MAC_MGMT_BEACON) + { + limLog( pMac, LOG2, FL("Save this beacon in LFR cache")); + __limHandleBeacon(pMac, limMsg, NULL); + } + else if (fc.subType == SIR_MAC_MGMT_PROBE_RSP) + { + limLog( pMac, LOG2, FL("Save this probe rsp in LFR cache")); + limProcessProbeRspFrameNoSession(pMac, pRxPacketInfo); + } + else + { + limLog( pMac, LOGE, FL("Wrong frame Type %d, Subtype %d for LFR"), + fc.type, fc.subType); + } + goto end; + } +#endif //WLAN_FEATURE_ROAM_SCAN_OFFLOAD #ifdef FEATURE_WLAN_CCX if (fc.type == SIR_MAC_DATA_FRAME && isFrmFt) { @@ -567,7 +594,7 @@ limHandle80211Frames(tpAniSirGlobal pMac, tpSirMsgQ limMsg, tANI_U8 *pDeferMsg) if (!psessionEntry->isCCXconnection) { - limLog( pMac, LOGE, FL("LIM received Type %d, Subtype %d in Non CCX connection\n"), + limLog( pMac, LOGE, FL("LIM received Type %d, Subtype %d in Non CCX connection"), fc.type, fc.subType); limPktFree(pMac, HAL_TXRX_FRM_802_11_MGMT, pBD, limMsg->bodyptr); return; @@ -575,7 +602,7 @@ limHandle80211Frames(tpAniSirGlobal pMac, tpSirMsgQ limMsg, tANI_U8 *pDeferMsg) limLog( pMac, LOGE, FL("Processing IAPP Frm from SA:")); limPrintMacAddr(pMac, pDataFrmHdr->sa, LOGE); #else - printk("%s: Need to port handling of IAPP frames to PRIMA for CCX\n", __func__); + printk("%s: Need to port handling of IAPP frames to PRIMA for CCX", __func__); #endif @@ -608,7 +635,7 @@ limHandle80211Frames(tpAniSirGlobal pMac, tpSirMsgQ limMsg, tANI_U8 *pDeferMsg) if((psessionEntry = peFindSessionByPeerSta(pMac,pHdr->sa,&sessionId))== NULL) { - limLog(pMac, LOG1, FL("session does not exist for given bssId\n")); + limLog(pMac, LOG1, FL("session does not exist for given bssId")); limPktFree(pMac, HAL_TXRX_FRM_802_11_MGMT, pRxPacketInfo, limMsg->bodyptr); return; } @@ -625,7 +652,7 @@ limHandle80211Frames(tpAniSirGlobal pMac, tpSirMsgQ limMsg, tANI_U8 *pDeferMsg) /* Check if frame is registered by HDD */ if(limCheckMgmtRegisteredFrames(pMac, pRxPacketInfo, psessionEntry)) { - limLog( pMac, LOG1, FL("Received frame is passed to SME\n")); + limLog( pMac, LOG1, FL("Received frame is passed to SME")); limPktFree(pMac, HAL_TXRX_FRM_802_11_MGMT, pRxPacketInfo, limMsg->bodyptr); return; } @@ -634,7 +661,7 @@ limHandle80211Frames(tpAniSirGlobal pMac, tpSirMsgQ limMsg, tANI_U8 *pDeferMsg) if (fc.protVer != SIR_MAC_PROTOCOL_VERSION) { // Received Frame with non-zero Protocol Version - limLog(pMac, LOGE, FL("Unexpected frame with protVersion %d received\n"), + limLog(pMac, LOGE, FL("Unexpected frame with protVersion %d received"), fc.protVer); limPktFree(pMac, HAL_TXRX_FRM_802_11_MGMT, pRxPacketInfo, (void *) limMsg->bodyptr); #ifdef WLAN_DEBUG @@ -654,7 +681,7 @@ limHandle80211Frames(tpAniSirGlobal pMac, tpSirMsgQ limMsg, tANI_U8 *pDeferMsg) #if 0 if (psessionEntry->limSystemRole == eLIM_UNKNOWN_ROLE) { - limLog( pMac, LOGW, FL( "gLimSystemRole is %d. Exiting...\n" ),psessionEntry->limSystemRole ); + limLog( pMac, LOGW, FL( "gLimSystemRole is %d. Exiting..." ),psessionEntry->limSystemRole ); limPktFree(pMac, HAL_TXRX_FRM_802_11_MGMT, pRxPacketInfo, (void *) limMsg->bodyptr); #ifdef WLAN_DEBUG @@ -677,7 +704,7 @@ limHandle80211Frames(tpAniSirGlobal pMac, tpSirMsgQ limMsg, tANI_U8 *pDeferMsg) if (limIsReassocInProgress( pMac,psessionEntry) && (fc.subType != SIR_MAC_MGMT_DISASSOC) && (fc.subType != SIR_MAC_MGMT_DEAUTH) && (fc.subType != SIR_MAC_MGMT_REASSOC_RSP)) { - limLog(pMac, LOGE, FL("Frame with Type - %d, Subtype - %d received in ReAssoc Wait state, dropping...\n"), + limLog(pMac, LOGE, FL("Frame with Type - %d, Subtype - %d received in ReAssoc Wait state, dropping..."), fc.type, fc.subType); return; } @@ -695,7 +722,7 @@ limHandle80211Frames(tpAniSirGlobal pMac, tpSirMsgQ limMsg, tANI_U8 *pDeferMsg) else { // Unwanted messages - Log error - limLog(pMac, LOGE, FL("unexpected message received %X\n"),limMsg->type); + limLog(pMac, LOGE, FL("unexpected message received %X"),limMsg->type); limPrintMsgName(pMac, LOGE, limMsg->type); } break; @@ -714,7 +741,7 @@ limHandle80211Frames(tpAniSirGlobal pMac, tpSirMsgQ limMsg, tANI_U8 *pDeferMsg) else { // Unwanted messages - Log error - limLog(pMac, LOGE, FL("unexpected message received %X\n"),limMsg->type); + limLog(pMac, LOGE, FL("unexpected message received %X"),limMsg->type); limPrintMsgName(pMac, LOGE, limMsg->type); } break; @@ -781,7 +808,7 @@ limHandle80211Frames(tpAniSirGlobal pMac, tpSirMsgQ limMsg, tANI_U8 *pDeferMsg) tANI_U8 *rfc1042Hdr = (tANI_U8 *)(dataOffset + RFC1042_HDR_LENGTH) ; tANI_U16 ethType = GET_BE16(rfc1042Hdr) ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("TDLS frame with 80211 Header\n")) ; + ("TDLS frame with 80211 Header")) ; if(ETH_TYPE_89_0d == ethType) { tANI_U8 payloadType = (rfc1042Hdr + ETH_TYPE_LEN)[0] ; @@ -808,6 +835,9 @@ limHandle80211Frames(tpAniSirGlobal pMac, tpSirMsgQ limMsg, tANI_U8 *pDeferMsg) } // switch (fc.type) +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +end: +#endif limPktFree(pMac, HAL_TXRX_FRM_802_11_MGMT, pRxPacketInfo, (void *) limMsg->bodyptr) ; return; } /*** end limHandle80211Frames() ***/ @@ -850,13 +880,13 @@ limProcessAbortScanInd(tpAniSirGlobal pMac) (eLIM_HAL_FINISH_SCAN_WAIT_STATE == pMac->lim.gLimHalScanState) ) { //Simply signal we need to abort - limLog( pMac, LOGW, FL(" waiting for HAL, simply signal abort gLimHalScanState = %d\n"), pMac->lim.gLimHalScanState ); + limLog( pMac, LOGW, FL(" waiting for HAL, simply signal abort gLimHalScanState = %d"), pMac->lim.gLimHalScanState ); pMac->lim.abortScan = 1; } else { //Force abort - limLog( pMac, LOGW, FL(" Force aborting scan\n") ); + limLog( pMac, LOGW, FL(" Force aborting scan") ); pMac->lim.abortScan = 0; limDeactivateAndChangeTimer(pMac, eLIM_MIN_CHANNEL_TIMER); limDeactivateAndChangeTimer(pMac, eLIM_MAX_CHANNEL_TIMER); @@ -911,7 +941,7 @@ void limOemDataRspHandleResumeLinkRsp(tpAniSirGlobal pMac, eHalStatus status, tA { if(status != eHAL_STATUS_SUCCESS) { - limLog(pMac, LOGE, FL("OEM Data Rsp failed to get the response for resume link\n")); + limLog(pMac, LOGE, FL("OEM Data Rsp failed to get the response for resume link")); } if(NULL != pMac->lim.gpLimMlmOemDataReq) @@ -943,7 +973,7 @@ void limProcessOemDataRsp(tpAniSirGlobal pMac, tANI_U32* body) status = palAllocateMemory(pMac->hHdd, (void**)(&mlmOemDataRsp), sizeof(tLimMlmOemDataRsp)); if(status != eHAL_STATUS_SUCCESS) { - limLog(pMac, LOGP, FL("could not allocate memory for mlmOemDataRsp\n")); + limLog(pMac, LOGP, FL("could not allocate memory for mlmOemDataRsp")); return; } @@ -1007,7 +1037,7 @@ limProcessMessages(tpAniSirGlobal pMac, tpSirMsgQ limMsg) #endif - PELOG3(limLog(pMac, LOG3, FL("rcvd msgType = %s, sme state = %s, mlm state = %s\n"), + PELOG3(limLog(pMac, LOG3, FL("rcvd msgType = %s, sme state = %s, mlm state = %s"), limMsgStr(limMsg->type), limSmeStateStr(pMac->lim.gLimSmeState), limMlmStateStr(pMac->lim.gLimMlmState));) @@ -1030,7 +1060,7 @@ limProcessMessages(tpAniSirGlobal pMac, tpSirMsgQ limMsg) { if(!(pMac->lim.deferredMsgCnt & 0xF)) { - PELOGE(limLog(pMac, LOGE, FL("Unable to Defer message(0x%X) limSmeState %d (prev sme state %d) sysRole %d mlm state %d (prev mlm state %d)\n"), + PELOGE(limLog(pMac, LOGE, FL("Unable to Defer message(0x%X) limSmeState %d (prev sme state %d) sysRole %d mlm state %d (prev mlm state %d)"), limMsg->type, pMac->lim.gLimSmeState, pMac->lim.gLimPrevSmeState, pMac->lim.gLimSystemRole, pMac->lim.gLimMlmState, pMac->lim.gLimPrevMlmState);) } @@ -1130,10 +1160,10 @@ limProcessMessages(tpAniSirGlobal pMac, tpSirMsgQ limMsg) if ( deferMsg == true ) { - PELOG1(limLog(pMac, LOG1, FL("Defer message type=%X \n"), limMsg->type);) + PELOG1(limLog(pMac, LOG1, FL("Defer message type=%X "), limMsg->type);) if (limDeferMsg(pMac, limMsg) != TX_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("Unable to Defer message(0x%X) limSmeState %d (prev sme state %d) sysRole %d mlm state %d (prev mlm state %d)\n"), + PELOGE(limLog(pMac, LOGE, FL("Unable to Defer message(0x%X) limSmeState %d (prev sme state %d) sysRole %d mlm state %d (prev mlm state %d)"), limMsg->type, pMac->lim.gLimSmeState, pMac->lim.gLimPrevSmeState, pMac->lim.gLimSystemRole, pMac->lim.gLimMlmState, pMac->lim.gLimPrevMlmState);) limLogSessionStates(pMac); @@ -1284,7 +1314,7 @@ limProcessMessages(tpAniSirGlobal pMac, tpSirMsgQ limMsg) tANI_U8 i; tANI_U8 p2pGOExists = 0; - limLog(pMac, LOG1, "LIM received NOA start %x\n", limMsg->type); + limLog(pMac, LOG1, "LIM received NOA start %x", limMsg->type); /* Since insert NOA is done and NOA start msg received, we should deactivate the Insert NOA timer */ limDeactivateAndChangeTimer(pMac, eLIM_INSERT_SINGLESHOT_NOA_TIMER); @@ -1300,7 +1330,7 @@ limProcessMessages(tpAniSirGlobal pMac, tpSirMsgQ limMsg) if (psessionEntry->p2pGoPsNoaStartInd.status != eHAL_STATUS_SUCCESS) { limLog(pMac, LOGW, FL("GO NOA start failure status %d reported by FW." - " - still go ahead with deferred sme req. This is just info\n"), + " - still go ahead with deferred sme req. This is just info"), psessionEntry->p2pGoPsNoaStartInd.status); } break; @@ -1310,7 +1340,7 @@ limProcessMessages(tpAniSirGlobal pMac, tpSirMsgQ limMsg) if (p2pGOExists == 0) { limLog(pMac, LOGW, FL("By the time, we received NOA start, GO is already removed." - " - still go ahead with deferred sme req. This is just info\n")); + " - still go ahead with deferred sme req. This is just info")); } /* We received the NOA start indication. Now we can send down the SME request which requires off-channel operation */ @@ -1325,7 +1355,7 @@ limProcessMessages(tpAniSirGlobal pMac, tpSirMsgQ limMsg) tpPESession psessionEntry = &pMac->lim.gpSession[0]; tANI_U8 i; - limLog(pMac, LOGW, FL("Received message Noa_ATTR %x\n"), limMsg->type); + limLog(pMac, LOGW, FL("Received message Noa_ATTR %x"), limMsg->type); for(i=0; i < pMac->lim.maxBssId; i++) { psessionEntry = &pMac->lim.gpSession[i]; @@ -1336,7 +1366,7 @@ limProcessMessages(tpAniSirGlobal pMac, tpSirMsgQ limMsg) palCopyMemory(pMac->hHdd,&psessionEntry->p2pGoPsUpdate, limMsg->bodyptr,sizeof(tSirP2PNoaAttr)); - limLog(pMac, LOG2, FL(" &psessionEntry->bssId%02x:%02x:%02x:%02x:%02x:%02x ctWin=%d oppPsFlag=%d\n"), + limLog(pMac, LOG2, FL(" &psessionEntry->bssId%02x:%02x:%02x:%02x:%02x:%02x ctWin=%d oppPsFlag=%d"), psessionEntry->bssId[0], psessionEntry->bssId[1], psessionEntry->bssId[2], @@ -1346,7 +1376,7 @@ limProcessMessages(tpAniSirGlobal pMac, tpSirMsgQ limMsg) psessionEntry->p2pGoPsUpdate.ctWin, psessionEntry->p2pGoPsUpdate.oppPsFlag); - limLog(pMac, LOG2, FL(" uNoa1IntervalCnt=%d uNoa1Duration=%d uNoa1Interval=%d uNoa1StartTime=%d\n"), + limLog(pMac, LOG2, FL(" uNoa1IntervalCnt=%d uNoa1Duration=%d uNoa1Interval=%d uNoa1StartTime=%d"), psessionEntry->p2pGoPsUpdate.uNoa1IntervalCnt, psessionEntry->p2pGoPsUpdate.uNoa1Duration, psessionEntry->p2pGoPsUpdate.uNoa1Interval, @@ -1434,7 +1464,7 @@ limProcessMessages(tpAniSirGlobal pMac, tpSirMsgQ limMsg) limProcessAddBaInd(pMac, limMsg); break; case SIR_LIM_DEL_BA_ALL_IND: - limDelAllBASessions(pMac); // refer notes and change + limDelAllBASessions(pMac); break; case SIR_LIM_DEL_BA_IND: limProcessMlmHalBADeleteInd( pMac, limMsg ); @@ -1483,7 +1513,7 @@ limProcessMessages(tpAniSirGlobal pMac, tpSirMsgQ limMsg) */ #if 0 - PELOG1(limLog(pMac, LOG1, FL("Heartbeat timeout, SME %d, MLME %d, #bcn %d\n"), + PELOG1(limLog(pMac, LOG1, FL("Heartbeat timeout, SME %d, MLME %d, #bcn %d"), pMac->lim.gLimSmeState, pMac->lim.gLimMlmState, pMac->lim.gLimRxedBeaconCntDuringHB);) @@ -1504,7 +1534,7 @@ limProcessMessages(tpAniSirGlobal pMac, tpSirMsgQ limMsg) // Defer processsing this message if (limDeferMsg(pMac, limMsg) != TX_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("Unable to Defer message(0x%X) limSmeState %d (prev sme state %d) sysRole %d mlm state %d (prev mlm state %d)\n"), + PELOGE(limLog(pMac, LOGE, FL("Unable to Defer message(0x%X) limSmeState %d (prev sme state %d) sysRole %d mlm state %d (prev mlm state %d)"), limMsg->type, pMac->lim.gLimSmeState, pMac->lim.gLimPrevSmeState, pMac->lim.gLimSystemRole, pMac->lim.gLimMlmState, pMac->lim.gLimPrevMlmState);) limLogSessionStates(pMac); @@ -1619,12 +1649,12 @@ limProcessMessages(tpAniSirGlobal pMac, tpSirMsgQ limMsg) pMac->lim.limTimers.gLimTdlsDisRspWaitTimer.sessionId) ; if(NULL == psessionEntry) { - limLog(pMac, LOGP,FL("Session Does not exist for given sessionID %d\n"), pMac->lim.limTimers.gLimTdlsDisRspWaitTimer.sessionId); + limLog(pMac, LOGP,FL("Session Does not exist for given sessionID %d"), pMac->lim.limTimers.gLimTdlsDisRspWaitTimer.sessionId); return; } VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - ("Discovery Rsp timer expires \n")) ; + ("Discovery Rsp timer expires ")) ; #if 0 // TDLS_hklee: D13 no need to open Addr2 unknown data packet /* restore RXP filters */ limSetLinkState(pMac, eSIR_LINK_FINISH_TDLS_DISCOVERY_STATE, @@ -1645,11 +1675,11 @@ limProcessMessages(tpAniSirGlobal pMac, tpSirMsgQ limMsg) tLimTdlsLinkSetupPeer *setupPeer = NULL ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("TDLS setup rsp timer expires \n")) ; + ("TDLS setup rsp timer expires ")) ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("TDLS setup rsp timer expires for peer:\n")) ; + ("TDLS setup rsp timer expires for peer:")) ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("%02X, %02X, %02X,%02X, %02X, %02X\n"), + ("%02X, %02X, %02X,%02X, %02X, %02X"), peerMac[0], peerMac[1], peerMac[2], @@ -1673,11 +1703,11 @@ limProcessMessages(tpAniSirGlobal pMac, tpSirMsgQ limMsg) tLimTdlsLinkSetupPeer *setupPeer = NULL ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("TDLS setup CNF timer expires \n")) ; + ("TDLS setup CNF timer expires ")) ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("TDLS setup CNF timer expires for peer:\n")) ; + ("TDLS setup CNF timer expires for peer:")) ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("%02X, %02X, %02X,%02X, %02X, %02X\n"), + ("%02X, %02X, %02X,%02X, %02X, %02X"), peerMac[0], peerMac[1], peerMac[2], @@ -1772,7 +1802,7 @@ limProcessMessages(tpAniSirGlobal pMac, tpSirMsgQ limMsg) case SIR_LIM_ADDR2_MISS_IND: { limLog(pMac, LOGE, - FL("Addr2 mismatch interrupt received %X\n"), + FL("Addr2 mismatch interrupt received %X"), limMsg->type); /*a message from HAL indicating addr2 mismatch interrupt occurred limMsg->bodyptr contains only pointer to 48-bit addr2 field*/ @@ -1830,7 +1860,7 @@ limProcessMessages(tpAniSirGlobal pMac, tpSirMsgQ limMsg) // sending beacon filtering information down to HAL if (limSendBeaconFilterInfo(pMac, psessionEntry) != eSIR_SUCCESS) { - limLog(pMac, LOGE, FL("Fail to send Beacon Filter Info \n")); + limLog(pMac, LOGE, FL("Fail to send Beacon Filter Info ")); } } vos_mem_free((v_VOID_t *)(limMsg->bodyptr)); @@ -1844,14 +1874,14 @@ limProcessMessages(tpAniSirGlobal pMac, tpSirMsgQ limMsg) // Unwanted messages // Log error limLog(pMac, LOGE, - FL("Discarding unexpected message received %X\n"), + FL("Discarding unexpected message received %X"), limMsg->type); limPrintMsgName(pMac, LOGE, limMsg->type); break; } // switch (limMsg->type) - PELOG2(limLog(pMac, LOG2, FL("Done Processing msgType = %d, sme state = %s, mlm state = %s\n"), + PELOG2(limLog(pMac, LOG2, FL("Done Processing msgType = %d, sme state = %s, mlm state = %s"), limMsg->type, limSmeStateStr(pMac->lim.gLimSmeState), limMlmStateStr(pMac->lim.gLimMlmState));) @@ -1958,7 +1988,7 @@ void limProcessNormalHddMsg(tpAniSirGlobal pMac, tSirMsgQ *pLimMsg, tANI_U8 fRsp #ifdef WLAN_DEBUG pMac->lim.numSme++; #endif - PELOGE(limLog(pMac, LOGE, FL("Unable to Defer message(0x%X) limSmeState %d (prev sme state %d) sysRole %d mlm state %d (prev mlm state %d)\n"), + PELOGE(limLog(pMac, LOGE, FL("Unable to Defer message(0x%X) limSmeState %d (prev sme state %d) sysRole %d mlm state %d (prev mlm state %d)"), pLimMsg->type, pMac->lim.gLimSmeState, pMac->lim.gLimPrevSmeState, pMac->lim.gLimSystemRole, pMac->lim.gLimMlmState, pMac->lim.gLimPrevMlmState);) limLogSessionStates(pMac); @@ -2002,7 +2032,7 @@ handleHTCapabilityandHTInfo(struct sAniSirGlobal *pMac, tpPESession psessionEntr if (wlan_cfgGetInt(pMac, WNI_CFG_HT_CAP_INFO, &cfgValue) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("Fail to retrieve WNI_CFG_HT_CAP_INFO value\n")); + limLog(pMac, LOGP, FL("Fail to retrieve WNI_CFG_HT_CAP_INFO value")); return ; } ptr = (tANI_U8 *) &macHTCapabilityInfo; @@ -2018,7 +2048,7 @@ handleHTCapabilityandHTInfo(struct sAniSirGlobal *pMac, tpPESession psessionEntr if (wlan_cfgGetInt(pMac, WNI_CFG_HT_AMPDU_PARAMS, &cfgValue) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("Fail to retrieve WNI_CFG_HT_PARAM_INFO value\n")); + limLog(pMac, LOGP, FL("Fail to retrieve WNI_CFG_HT_PARAM_INFO value")); return ; } ptr = (tANI_U8 *) &macHTParametersInfo; @@ -2029,7 +2059,7 @@ handleHTCapabilityandHTInfo(struct sAniSirGlobal *pMac, tpPESession psessionEntr // Get HT IE Info if (wlan_cfgGetInt(pMac, WNI_CFG_HT_INFO_FIELD1, &cfgValue) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("Fail to retrieve WNI_CFG_HT_INFO_FIELD1 value\n")); + limLog(pMac, LOGP, FL("Fail to retrieve WNI_CFG_HT_INFO_FIELD1 value")); return ; } ptr = (tANI_U8 *) &macHTInfoField1; @@ -2040,7 +2070,7 @@ handleHTCapabilityandHTInfo(struct sAniSirGlobal *pMac, tpPESession psessionEntr if (wlan_cfgGetInt(pMac, WNI_CFG_HT_INFO_FIELD2, &cfgValue) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("Fail to retrieve WNI_CFG_HT_INFO_FIELD2 value\n")); + limLog(pMac, LOGP, FL("Fail to retrieve WNI_CFG_HT_INFO_FIELD2 value")); return ; } ptr = (tANI_U8 *) &macHTInfoField2; @@ -2049,7 +2079,7 @@ handleHTCapabilityandHTInfo(struct sAniSirGlobal *pMac, tpPESession psessionEntr if (wlan_cfgGetInt(pMac, WNI_CFG_HT_INFO_FIELD3, &cfgValue) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("Fail to retrieve WNI_CFG_HT_INFO_FIELD3 value\n")); + limLog(pMac, LOGP, FL("Fail to retrieve WNI_CFG_HT_INFO_FIELD3 value")); return ; } ptr = (tANI_U8 *) &macHTInfoField3; diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessMlmReqMessages.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessMlmReqMessages.c index 36edb28c641..f015dd271a0 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessMlmReqMessages.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessMlmReqMessages.c @@ -220,7 +220,7 @@ limSetScanMode(tpAniSirGlobal pMac) else checkTraffic = eSIR_CHECK_ROAMING_SCAN; - PELOG1(limLog(pMac, LOG1, FL("Calling limSendHalInitScanReq\n"));) + PELOG1(limLog(pMac, LOG1, FL("Calling limSendHalInitScanReq"));) limSendHalInitScanReq(pMac, eLIM_HAL_INIT_SCAN_WAIT_STATE, checkTraffic); return ; @@ -275,13 +275,13 @@ limSuspendLink(tpAniSirGlobal pMac, tSirLinkTrafficCheck trafficCheck, SUSPEND_ { if( NULL == callback ) { - limLog( pMac, LOGE, "%s:%d: Invalid parameters\n", __func__, __LINE__ ); + limLog( pMac, LOGE, "%s:%d: Invalid parameters", __func__, __LINE__ ); return; } if( pMac->lim.gpLimSuspendCallback ) { - limLog( pMac, LOGE, "%s:%d: gLimSuspendLink callback is not NULL...something is wrong\n", __func__, __LINE__ ); + limLog( pMac, LOGE, "%s:%d: gLimSuspendLink callback is not NULL...something is wrong", __func__, __LINE__ ); callback( pMac, eHAL_STATUS_FAILURE, data ); return; } @@ -318,13 +318,13 @@ limResumeLink(tpAniSirGlobal pMac, SUSPEND_RESUME_LINK_CALLBACK callback, tANI_U { if( NULL == callback ) { - limLog( pMac, LOGE, "%s:%d: Invalid parameters\n", __func__, __LINE__ ); + limLog( pMac, LOGE, "%s:%d: Invalid parameters", __func__, __LINE__ ); return; } if( pMac->lim.gpLimResumeCallback ) { - limLog( pMac, LOGE, "%s:%d: gLimResumeLink callback is not NULL...something is wrong\n", __func__, __LINE__ ); + limLog( pMac, LOGE, "%s:%d: gLimResumeLink callback is not NULL...something is wrong", __func__, __LINE__ ); callback( pMac, eHAL_STATUS_FAILURE, data ); return; } @@ -358,7 +358,7 @@ limChangeChannelWithCallback(tpAniSirGlobal pMac, tANI_U8 newChannel, { // Sanity checks for the current and new channel #if defined WLAN_VOWIFI_DEBUG - PELOGE(limLog( pMac, LOGE, "Switching channel to %d\n", newChannel);) + PELOGE(limLog( pMac, LOGE, "Switching channel to %d", newChannel);) #endif psessionEntry->channelChangeReasonCode=LIM_SWITCH_CHANNEL_OPERATION; @@ -419,14 +419,14 @@ void limContinuePostChannelScan(tpAniSirGlobal pMac) (limActiveScanAllowed(pMac, channelNum))) { TX_TIMER *periodicScanTimer; - PELOG2(limLog(pMac, LOG2, FL("ACTIVE Scan chan %d, sending probe\n"), channelNum);) + PELOG2(limLog(pMac, LOG2, FL("ACTIVE Scan chan %d, sending probe"), channelNum);) do { /* Prepare and send Probe Request frame for all the SSIDs present in the saved MLM */ - PELOGE(limLog(pMac, LOG1, FL("sending ProbeReq number %d, for SSID %s on channel: %d\n"), + PELOGE(limLog(pMac, LOG1, FL("sending ProbeReq number %d, for SSID %s on channel: %d"), i, pMac->lim.gpLimMlmScanReq->ssId[i].ssId, channelNum);) // include additional IE if there is status = limSendProbeReqMgmtFrame( pMac, &pMac->lim.gpLimMlmScanReq->ssId[i], @@ -437,7 +437,7 @@ void limContinuePostChannelScan(tpAniSirGlobal pMac) if ( status != eSIR_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("send ProbeReq failed for SSID %s on channel: %d\n"), + PELOGE(limLog(pMac, LOGE, FL("send ProbeReq failed for SSID %s on channel: %d"), pMac->lim.gpLimMlmScanReq->ssId[i].ssId, channelNum);) limDeactivateAndChangeTimer(pMac, eLIM_MIN_CHANNEL_TIMER); limSendHalEndScanReq(pMac, channelNum, eLIM_HAL_END_SCAN_WAIT_STATE); @@ -469,7 +469,7 @@ void limContinuePostChannelScan(tpAniSirGlobal pMac) if (tx_timer_activate(&pMac->lim.limTimers.gLimMinChannelTimer) != TX_SUCCESS) { - limLog(pMac, LOGP, FL("could not start min channel timer\n")); + limLog(pMac, LOGP, FL("could not start min channel timer")); return; } @@ -480,7 +480,7 @@ void limContinuePostChannelScan(tpAniSirGlobal pMac) else { #if defined WLAN_VOWIFI_DEBUG - PELOGE(limLog( pMac, LOGE, "Min channel time == 0, Use only max chan timer\n" );) + PELOGE(limLog( pMac, LOGE, "Min channel time == 0, Use only max chan timer" );) #endif //No Need to start Min channel timer. Start Max Channel timer. limDeactivateAndChangeTimer(pMac, eLIM_MAX_CHANNEL_TIMER); @@ -490,7 +490,7 @@ void limContinuePostChannelScan(tpAniSirGlobal pMac) { /// Could not activate max channel timer. // Log error - limLog(pMac,LOGP, FL("could not start max channel timer\n")); + limLog(pMac,LOGP, FL("could not start max channel timer")); return; } @@ -503,7 +503,7 @@ void limContinuePostChannelScan(tpAniSirGlobal pMac) if (tx_timer_activate(periodicScanTimer) != TX_SUCCESS) { limLog(pMac, LOGP, FL("could not start periodic probe req " - "timer\n")); + "timer")); return; } periodicScanTimer->sessionId = channelNum; @@ -512,7 +512,7 @@ void limContinuePostChannelScan(tpAniSirGlobal pMac) else { tANI_U32 val; - PELOG2(limLog(pMac, LOG2, FL("START PASSIVE Scan chan %d\n"), channelNum);) + PELOG2(limLog(pMac, LOG2, FL("START PASSIVE Scan chan %d"), channelNum);) /// Passive Scanning. Activate maxChannelTimer MTRACE(macTrace(pMac, TRACE_CODE_TIMER_DEACTIVATE, NO_SESSION, eLIM_MAX_CHANNEL_TIMER)); @@ -521,7 +521,7 @@ void limContinuePostChannelScan(tpAniSirGlobal pMac) { // Could not deactivate max channel timer. // Log error - limLog(pMac, LOGP, FL("Unable to deactivate max channel timer\n")); + limLog(pMac, LOGP, FL("Unable to deactivate max channel timer")); return; } else @@ -533,7 +533,7 @@ void limContinuePostChannelScan(tpAniSirGlobal pMac) * Could not get max channel value * from CFG. Log error. */ - limLog(pMac, LOGP, FL("could not retrieve passive max channel value\n")); + limLog(pMac, LOGP, FL("could not retrieve passive max channel value")); return; } else @@ -567,12 +567,12 @@ void limContinuePostChannelScan(tpAniSirGlobal pMac) { // Could not change max channel timer. // Log error - limLog(pMac, LOGP, FL("Unable to change max channel timer\n")); + limLog(pMac, LOGP, FL("Unable to change max channel timer")); return; } else if (tx_timer_activate(&pMac->lim.limTimers.gLimMaxChannelTimer) != TX_SUCCESS) { - limLog(pMac, LOGP, FL("could not start max channel timer\n")); + limLog(pMac, LOGP, FL("could not start max channel timer")); return; } @@ -701,27 +701,35 @@ void limSetDFSChannelList(tpAniSirGlobal pMac,tANI_U8 channelNum, tSirDFSChannel { tANI_BOOLEAN passiveToActive = TRUE; - if (eANI_BOOLEAN_TRUE == limIsconnectedOnDFSChannel(channelNum)) + if ((1 <= channelNum) && (165 >= channelNum)) { - if (dfsChannelList->timeStamp[channelNum] == 0) - { - //Received first beacon; Convert DFS channel to Active channel. - PELOG1(limLog(pMac, LOG1, FL("Received first beacon on DFS channel: %d"), channelNum);) - limCovertChannelScanType(pMac,channelNum, passiveToActive); - } - dfsChannelList->timeStamp[channelNum] = vos_timer_get_system_time(); + if (eANI_BOOLEAN_TRUE == limIsconnectedOnDFSChannel(channelNum)) + { + if (dfsChannelList->timeStamp[channelNum] == 0) + { + //Received first beacon; Convert DFS channel to Active channel. + PELOG1(limLog(pMac, LOG1, FL("Received first beacon on DFS channel: %d"), channelNum);) + limCovertChannelScanType(pMac,channelNum, passiveToActive); + } + dfsChannelList->timeStamp[channelNum] = vos_timer_get_system_time(); + } + else + { + PELOG1(limLog(pMac, LOG1, FL("Channel %d is Active"), channelNum);) + return; + } + if (!tx_timer_running(&pMac->lim.limTimers.gLimActiveToPassiveChannelTimer)) + { + tx_timer_activate(&pMac->lim.limTimers.gLimActiveToPassiveChannelTimer); + } } else { - PELOG1(limLog(pMac, LOG1, FL("Channel %d is Active"), channelNum);) - return; - } - if (!tx_timer_running(&pMac->lim.limTimers.gLimActiveToPassiveChannelTimer)) - { - tx_timer_activate(&pMac->lim.limTimers.gLimActiveToPassiveChannelTimer); + PELOGE(limLog(pMac, LOGE, FL("Invalid Channel: %d"), channelNum);) + return; } - return ; + return; } @@ -832,7 +840,7 @@ limSendHalInitScanReq(tpAniSirGlobal pMac, tLimLimHalScanState nextState, tSirLi if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pInitScanParam, sizeof(*pInitScanParam))) { - PELOGW(limLog(pMac, LOGW, FL("palAllocateMemory() failed\n"));) + PELOGW(limLog(pMac, LOGW, FL("palAllocateMemory() failed"));) goto error; } @@ -903,14 +911,14 @@ limSendHalInitScanReq(tpAniSirGlobal pMac, tLimLimHalScanState nextState, tSirLi rc = wdaPostCtrlMsg(pMac, &msg); if (rc == eSIR_SUCCESS) { - PELOG3(limLog(pMac, LOG3, FL("wdaPostCtrlMsg() return eSIR_SUCCESS pMac=%x nextState=%d\n"), + PELOG3(limLog(pMac, LOG3, FL("wdaPostCtrlMsg() return eSIR_SUCCESS pMac=%x nextState=%d"), pMac, pMac->lim.gLimHalScanState);) return; } SET_LIM_PROCESS_DEFD_MESGS(pMac, true); palFreeMemory(pMac->hHdd, (void *)pInitScanParam); - PELOGW(limLog(pMac, LOGW, FL("wdaPostCtrlMsg failed, error code %d\n"), rc);) + PELOGW(limLog(pMac, LOGW, FL("wdaPostCtrlMsg failed, error code %d"), rc);) error: switch(nextState) @@ -957,7 +965,7 @@ limSendHalStartScanReq(tpAniSirGlobal pMac, tANI_U8 channelNum, tLimLimHalScanSt (void **)&pStartScanParam, sizeof(*pStartScanParam))) { - PELOGW(limLog(pMac, LOGW, FL("palAllocateMemory() failed\n"));) + PELOGW(limLog(pMac, LOGW, FL("palAllocateMemory() failed"));) goto error; } @@ -971,7 +979,7 @@ limSendHalStartScanReq(tpAniSirGlobal pMac, tANI_U8 channelNum, tLimLimHalScanSt SET_LIM_PROCESS_DEFD_MESGS(pMac, false); MTRACE(macTraceMsgTx(pMac, NO_SESSION, msg.type)); - limLog(pMac, LOG1, FL("Channel %d\n"), channelNum); + limLog(pMac, LOG1, FL("Channel %d"), channelNum); rc = wdaPostCtrlMsg(pMac, &msg); if (rc == eSIR_SUCCESS) { @@ -980,7 +988,7 @@ limSendHalStartScanReq(tpAniSirGlobal pMac, tANI_U8 channelNum, tLimLimHalScanSt SET_LIM_PROCESS_DEFD_MESGS(pMac, true); palFreeMemory(pMac->hHdd, (void *)pStartScanParam); - PELOGW(limLog(pMac, LOGW, FL("wdaPostCtrlMsg failed, error code %d\n"), rc);) + PELOGW(limLog(pMac, LOGW, FL("wdaPostCtrlMsg failed, error code %d"), rc);) error: switch(nextState) @@ -998,7 +1006,7 @@ limSendHalStartScanReq(tpAniSirGlobal pMac, tANI_U8 channelNum, tLimLimHalScanSt } else { - PELOGW(limLog(pMac, LOGW, FL("Invalid state for START_SCAN_REQ message=%d\n"), pMac->lim.gLimHalScanState);) + PELOGW(limLog(pMac, LOGW, FL("Invalid state for START_SCAN_REQ message=%d"), pMac->lim.gLimHalScanState);) } return; @@ -1021,7 +1029,7 @@ void limSendHalEndScanReq(tpAniSirGlobal pMac, tANI_U8 channelNum, tLimLimHalSca if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pEndScanParam, sizeof(*pEndScanParam))) { - PELOGW(limLog(pMac, LOGW, FL("palAllocateMemory() failed\n"));) + PELOGW(limLog(pMac, LOGW, FL("palAllocateMemory() failed"));) goto error; } @@ -1042,7 +1050,7 @@ void limSendHalEndScanReq(tpAniSirGlobal pMac, tANI_U8 channelNum, tLimLimHalSca SET_LIM_PROCESS_DEFD_MESGS(pMac, true); palFreeMemory(pMac->hHdd, (void *)pEndScanParam); - PELOGW(limLog(pMac, LOGW, FL("wdaPostCtrlMsg failed, error code %d\n"), rc);) + PELOGW(limLog(pMac, LOGW, FL("wdaPostCtrlMsg failed, error code %d"), rc);) error: switch(nextState) @@ -1053,15 +1061,15 @@ void limSendHalEndScanReq(tpAniSirGlobal pMac, tANI_U8 channelNum, tLimLimHalSca default: - PELOGW(limLog(pMac, LOGW, FL("wdaPostCtrlMsg Rcvd invalid nextState %d\n"), nextState);) + PELOGW(limLog(pMac, LOGW, FL("wdaPostCtrlMsg Rcvd invalid nextState %d"), nextState);) break; } pMac->lim.gLimHalScanState = eLIM_HAL_IDLE_SCAN_STATE; - PELOGW(limLog(pMac, LOGW, FL("wdaPostCtrlMsg failed, error code %d\n"), rc);) + PELOGW(limLog(pMac, LOGW, FL("wdaPostCtrlMsg failed, error code %d"), rc);) } else { - PELOGW(limLog(pMac, LOGW, FL("Invalid state for END_SCAN_REQ message=%d\n"), pMac->lim.gLimHalScanState);) + PELOGW(limLog(pMac, LOGW, FL("Invalid state for END_SCAN_REQ message=%d"), pMac->lim.gLimHalScanState);) } @@ -1102,7 +1110,7 @@ void limSendHalFinishScanReq(tpAniSirGlobal pMac, tLimLimHalScanState nextState) * this check will avoid that. * If PE is already waiting for the 'finish_scan_rsp' message from HAL, it will ignore this request. */ - PELOGW(limLog(pMac, LOGW, FL("Next Scan State is same as the current state: %d \n"), nextState);) + PELOGW(limLog(pMac, LOGW, FL("Next Scan State is same as the current state: %d "), nextState);) return; } @@ -1110,7 +1118,7 @@ void limSendHalFinishScanReq(tpAniSirGlobal pMac, tLimLimHalScanState nextState) if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pFinishScanParam, sizeof(*pFinishScanParam))) { - PELOGW(limLog(pMac, LOGW, FL("palAllocateMemory() failed\n"));) + PELOGW(limLog(pMac, LOGW, FL("palAllocateMemory() failed"));) goto error; } @@ -1163,7 +1171,7 @@ void limSendHalFinishScanReq(tpAniSirGlobal pMac, tLimLimHalScanState nextState) } SET_LIM_PROCESS_DEFD_MESGS(pMac, true); palFreeMemory(pMac->hHdd, (void *)pFinishScanParam); - PELOGW(limLog(pMac, LOGW, FL("wdaPostCtrlMsg failed, error code %d\n"), rc);) + PELOGW(limLog(pMac, LOGW, FL("wdaPostCtrlMsg failed, error code %d"), rc);) error: if(nextState == eLIM_HAL_FINISH_SCAN_WAIT_STATE) @@ -1217,7 +1225,7 @@ limContinueChannelScan(tpAniSirGlobal pMac) { tANI_U8 channelNum; - PELOG1(limLog(pMac, LOG1, FL("Continue SCAN : chan %d tot %d\n"), + PELOG1(limLog(pMac, LOG1, FL("Continue SCAN : chan %d tot %d"), pMac->lim.gLimCurrentScanChannelId, pMac->lim.gpLimMlmScanReq->channelList.numChannels);) @@ -1251,7 +1259,7 @@ limContinueChannelScan(tpAniSirGlobal pMac) ((limGetCurrentScanChannel(pMac) > 14) && pMac->lim.gLim50Band11dScanDone)) { - limLog(pMac, LOGW, FL("skipping chan %d\n"), + limLog(pMac, LOGW, FL("skipping chan %d"), limGetCurrentScanChannel(pMac)); pMac->lim.gLimCurrentScanChannelId++; } @@ -1275,7 +1283,7 @@ limContinueChannelScan(tpAniSirGlobal pMac) } channelNum = limGetCurrentScanChannel(pMac); - PELOG2(limLog(pMac, LOG2, FL("Current Channel to be scanned is %d\n"), + PELOG2(limLog(pMac, LOG2, FL("Current Channel to be scanned is %d"), channelNum);) limSendHalStartScanReq(pMac, channelNum, eLIM_HAL_START_SCAN_WAIT_STATE); @@ -1337,7 +1345,7 @@ limRestorePreScanState(tpAniSirGlobal pMac) //limCleanupMsgQ(pMac); pMac->lim.gLimSystemInScanLearnMode = 0; - PELOG1(limLog(pMac, LOG1, FL("Scan ended, took %d tu\n"), (tx_time_get() - pMac->lim.scanStartTime));) + PELOG1(limLog(pMac, LOG1, FL("Scan ended, took %d tu"), (tx_time_get() - pMac->lim.scanStartTime));) } /*** limRestorePreScanState() ***/ #ifdef FEATURE_OEM_DATA_SUPPORT @@ -1351,7 +1359,7 @@ void limSendHalOemDataReq(tpAniSirGlobal pMac) tANI_U32 reqLen = 0; if(NULL == pMac->lim.gpLimMlmOemDataReq) { - PELOGE(limLog(pMac, LOGE, FL("Null pointer\n"));) + PELOGE(limLog(pMac, LOGE, FL("Null pointer"));) goto error; } @@ -1359,7 +1367,7 @@ void limSendHalOemDataReq(tpAniSirGlobal pMac) if(eHAL_STATUS_SUCCESS != palAllocateMemory(pMac->hHdd, (void**)&pStartOemDataReq, reqLen)) { - PELOGE(limLog(pMac, LOGE, FL("OEM_DATA: Could not allocate memory for pStartOemDataReq\n"));) + PELOGE(limLog(pMac, LOGE, FL("OEM_DATA: Could not allocate memory for pStartOemDataReq"));) goto error; } @@ -1386,7 +1394,7 @@ void limSendHalOemDataReq(tpAniSirGlobal pMac) SET_LIM_PROCESS_DEFD_MESGS(pMac, true); palFreeMemory(pMac->hHdd, (void*)pStartOemDataReq); - PELOGE(limLog(pMac, LOGE, FL("OEM_DATA: posting WDA_START_OEM_DATA_REQ to HAL failed\n"));) + PELOGE(limLog(pMac, LOGE, FL("OEM_DATA: posting WDA_START_OEM_DATA_REQ to HAL failed"));) error: pMac->lim.gLimMlmState = pMac->lim.gLimPrevMlmState; @@ -1394,7 +1402,7 @@ void limSendHalOemDataReq(tpAniSirGlobal pMac) if(eHAL_STATUS_SUCCESS != palAllocateMemory(pMac->hHdd, (void**)(&pMlmOemDataRsp), sizeof(tLimMlmOemDataRsp))) { - limLog(pMac->hHdd, LOGP, FL("OEM_DATA: memory allocation for pMlmOemDataRsp failed under suspend link failure\n")); + limLog(pMac->hHdd, LOGP, FL("OEM_DATA: memory allocation for pMlmOemDataRsp failed under suspend link failure")); return; } @@ -1435,7 +1443,7 @@ void limSetOemDataReqModeFailed(tpAniSirGlobal pMac, eHalStatus status, tANI_U32 if(eHAL_STATUS_SUCCESS != palAllocateMemory(pMac->hHdd, (void**)(&pMlmOemDataRsp), sizeof(tLimMlmOemDataRsp))) { - limLog(pMac->hHdd, LOGP, FL("OEM_DATA: memory allocation for pMlmOemDataRsp failed under suspend link failure\n")); + limLog(pMac->hHdd, LOGP, FL("OEM_DATA: memory allocation for pMlmOemDataRsp failed under suspend link failure")); return; } @@ -1474,12 +1482,12 @@ void limSetOemDataReqMode(tpAniSirGlobal pMac, eHalStatus status, tANI_U32* data { if(status != eHAL_STATUS_SUCCESS) { - limLog(pMac, LOGE, FL("OEM_DATA: failed in suspend link\n")); + limLog(pMac, LOGE, FL("OEM_DATA: failed in suspend link")); goto error; } else { - PELOGE(limLog(pMac, LOGE, FL("OEM_DATA: Calling limSendHalOemDataReq\n"));) + PELOGE(limLog(pMac, LOGE, FL("OEM_DATA: Calling limSendHalOemDataReq"));) limSendHalOemDataReq(pMac); return; } @@ -1511,12 +1519,12 @@ mlm_add_sta( /* Configuration related parameters to be changed to support BT-AMP */ if( eSIR_SUCCESS != wlan_cfgGetInt( pMac, WNI_CFG_LISTEN_INTERVAL, &val )) - limLog(pMac, LOGP, FL("Couldn't get LISTEN_INTERVAL\n")); + limLog(pMac, LOGP, FL("Couldn't get LISTEN_INTERVAL")); pSta->listenInterval = (tANI_U16) val; if (eSIR_SUCCESS != wlan_cfgGetInt(pMac, WNI_CFG_SHORT_PREAMBLE, &val) ) - limLog(pMac, LOGP, FL("Couldn't get SHORT_PREAMBLE\n")); + limLog(pMac, LOGP, FL("Couldn't get SHORT_PREAMBLE")); pSta->shortPreambleSupported = (tANI_U8)val; pSta->assocId = 0; // Is SMAC OK with this? @@ -1562,7 +1570,7 @@ mlm_add_sta( #endif limFillSupportedRatesInfo(pMac, NULL, &pSta->supportedRates,psessionEntry); - limLog( pMac, LOGE, FL( "GF: %d, ChnlWidth: %d, MimoPS: %d, lsigTXOP: %d, dsssCCK: %d, SGI20: %d, SGI40%d\n") , + limLog( pMac, LOGE, FL( "GF: %d, ChnlWidth: %d, MimoPS: %d, lsigTXOP: %d, dsssCCK: %d, SGI20: %d, SGI40%d") , pSta->greenFieldCapable, pSta->txChannelWidthSet, pSta->mimoPS, pSta->lsigTxopProtection, pSta->fDsssCckMode40Mhz,pSta->fShortGI20Mhz, pSta->fShortGI40Mhz); @@ -1599,7 +1607,7 @@ limMlmAddBss ( if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **) &pAddBssParams, sizeof( tAddBssParams ))) { - limLog( pMac, LOGE, FL( "Unable to PAL allocate memory during ADD_BSS\n" )); + limLog( pMac, LOGE, FL( "Unable to PAL allocate memory during ADD_BSS" )); // Respond to SME with LIM_MLM_START_CNF return eSIR_SME_HAL_SEND_MESSAGE_FAIL; } @@ -1661,7 +1669,7 @@ limMlmAddBss ( pMlmStartReq->ssId.length); pAddBssParams->ssId.length = pMlmStartReq->ssId.length; pAddBssParams->bHiddenSSIDEn = pMlmStartReq->ssidHidden; - limLog( pMac, LOGE, FL( "TRYING TO HIDE SSID %d\n" ),pAddBssParams->bHiddenSSIDEn); + limLog( pMac, LOGE, FL( "TRYING TO HIDE SSID %d" ),pAddBssParams->bHiddenSSIDEn); // CR309183. Disable Proxy Probe Rsp. Host handles Probe Requests. Until FW fixed. pAddBssParams->bProxyProbeRespEn = 0; pAddBssParams->obssProtEnabled = pMlmStartReq->obssProtEnabled; @@ -1698,10 +1706,10 @@ limMlmAddBss ( msgQ.bodyval = 0; MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, msgQ.type)); - limLog( pMac, LOGW, FL( "Sending WDA_ADD_BSS_REQ...\n" )); + limLog( pMac, LOGW, FL( "Sending WDA_ADD_BSS_REQ..." )); if( eSIR_SUCCESS != (retCode = wdaPostCtrlMsg( pMac, &msgQ ))) { - limLog( pMac, LOGE, FL("Posting ADD_BSS_REQ to HAL failed, reason=%X\n"), retCode ); + limLog( pMac, LOGE, FL("Posting ADD_BSS_REQ to HAL failed, reason=%X"), retCode ); palFreeMemory(pMac->hHdd,(void *)pAddBssParams); return eSIR_SME_HAL_SEND_MESSAGE_FAIL; } @@ -1741,14 +1749,14 @@ limProcessMlmStartReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if(pMsgBuf == NULL) { - PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n"));) + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) return; } pMlmStartReq = (tLimMlmStartReq *) pMsgBuf; if((psessionEntry = peFindSessionBySessionId(pMac,pMlmStartReq->sessionId))==NULL) { - limLog(pMac, LOGP,FL("Session Does not exist for given sessionID\n")); + limLog(pMac, LOGP,FL("Session Does not exist for given sessionID")); mlmStartCnf.resultCode = eSIR_SME_REFUSED; goto end; } @@ -1759,7 +1767,7 @@ limProcessMlmStartReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * Should not have received Start req in states other than idle. * Return Start confirm with failure code. */ - PELOGE(limLog(pMac, LOGE, FL("received unexpected MLM_START_REQ in state %X\n"),psessionEntry->limMlmState);) + PELOGE(limLog(pMac, LOGE, FL("received unexpected MLM_START_REQ in state %X"),psessionEntry->limMlmState);) limPrintMlmState(pMac, LOGE, psessionEntry->limMlmState); mlmStartCnf.resultCode = eSIR_SME_BSS_ALREADY_STARTED_OR_JOINED; goto end; @@ -1767,7 +1775,7 @@ limProcessMlmStartReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) #if 0 if (cfgSetInt(pMac, WNI_CFG_CURRENT_CHANNEL, pMlmStartReq->channelNumber)!= eSIR_SUCCESS) - limLog(pMac, LOGP, FL("could not set CURRENT_CHANNEL at CFG\n")); + limLog(pMac, LOGP, FL("could not set CURRENT_CHANNEL at CFG")); pMac->lim.gLimCurrentChannelId = pMlmStartReq->channelNumber; #endif //TO SUPPORT BT-AMP @@ -1777,7 +1785,7 @@ limProcessMlmStartReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) #if 0 //We are not using the BSSID and SSID from the config file, instead we are reading form the session table if (cfgSetStr(pMac, WNI_CFG_BSSID, (tANI_U8 *) pMlmStartReq->bssId, sizeof(tSirMacAddr)) != eSIR_SUCCESS) - limLog(pMac, LOGP, FL("could not update BSSID at CFG\n")); + limLog(pMac, LOGP, FL("could not update BSSID at CFG")); @@ -1789,7 +1797,7 @@ limProcessMlmStartReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) #if 0 if (cfgSetStr(pMac, WNI_CFG_SSID, (tANI_U8 *) &pMlmStartReq->ssId.ssId, pMlmStartReq->ssId.length) != eSIR_SUCCESS) - limLog(pMac, LOGP, FL("could not update SSID at CFG\n")); + limLog(pMac, LOGP, FL("could not update SSID at CFG")); #endif //To SUPPORT BT-AMP @@ -1800,7 +1808,7 @@ limProcessMlmStartReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) (tANI_U8 *) &pMac->lim.gpLimStartBssReq->operationalRateSet.rate, pMac->lim.gpLimStartBssReq->operationalRateSet.numRates) != eSIR_SUCCESS) - limLog(pMac, LOGP, FL("could not update Operational Rateset at CFG\n")); + limLog(pMac, LOGP, FL("could not update Operational Rateset at CFG")); #endif //TO SUPPORT BT-AMP @@ -1818,16 +1826,16 @@ limProcessMlmStartReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) SYS_MS_TO_TICKS(LIM_WPS_OVERLAP_TIMER_MS), // reschedule_ticks TX_AUTO_ACTIVATE /* TX_NO_ACTIVATE*/) != TX_SUCCESS) { - limLog(pMac, LOGP, FL("failed to create WPS overlap Timer\n")); + limLog(pMac, LOGP, FL("failed to create WPS overlap Timer")); } pMac->lim.limTimers.gLimWPSOverlapTimerObj.sessionId = pMlmStartReq->sessionId; pMac->lim.limTimers.gLimWPSOverlapTimerObj.isTimerCreated = eANI_BOOLEAN_TRUE; - limLog(pMac, LOGE, FL("Create WPS overlap Timer, session=%d\n"), pMlmStartReq->sessionId); + limLog(pMac, LOGE, FL("Create WPS overlap Timer, session=%d"), pMlmStartReq->sessionId); if (tx_timer_activate(&pMac->lim.limTimers.gLimWPSOverlapTimerObj.gLimWPSOverlapTimer) != TX_SUCCESS) { - limLog(pMac, LOGP, FL("tx_timer_activate failed\n")); + limLog(pMac, LOGP, FL("tx_timer_activate failed")); } } } @@ -1928,7 +1936,7 @@ limProcessMlmScanReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if (pMac->lim.gLimSystemInScanLearnMode) { PELOGE(limLog(pMac, LOGE, - FL("Sending START_SCAN from LIM while one req is pending\n"));) + FL("Sending START_SCAN from LIM while one req is pending"));) palFreeMemory( pMac->hHdd, (tANI_U8 *) pMsgBuf); /*Send back a failure*/ mlmScanCnf.resultCode = eSIR_SME_SCAN_FAILED; @@ -1946,7 +1954,7 @@ limProcessMlmScanReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) /// Hold onto SCAN REQ criteria pMac->lim.gpLimMlmScanReq = (tLimMlmScanReq *) pMsgBuf; - PELOG3(limLog(pMac, LOG3, FL("Number of channels to scan are %d \n"), + PELOG3(limLog(pMac, LOG3, FL("Number of channels to scan are %d "), pMac->lim.gpLimMlmScanReq->channelList.numChannels);) pMac->lim.gLimPrevMlmState = pMac->lim.gLimMlmState; @@ -1970,7 +1978,7 @@ limProcessMlmScanReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * Could not get max channel value * from CFG. Log error. */ - limLog(pMac, LOGP, FL("could not retrieve passive max channel value\n")); + limLog(pMac, LOGP, FL("could not retrieve passive max channel value")); /* use a default value of 110ms */ val = 110; @@ -2003,7 +2011,7 @@ limProcessMlmScanReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * Log error */ limLog(pMac, LOGW, - FL("received unexpected MLM_SCAN_REQ in state %X OR zero number of channels: %X\n"), + FL("received unexpected MLM_SCAN_REQ in state %X OR zero number of channels: %X"), pMac->lim.gLimMlmState, ((tLimMlmScanReq *) pMsgBuf)->channelList.numChannels); limPrintMlmState(pMac, LOGW, pMac->lim.gLimMlmState); @@ -2049,7 +2057,7 @@ static void limProcessMlmOemDataReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * Log error */ - PELOGW(limLog(pMac, LOGW, FL("OEM_DATA: unexpected LIM_MLM_OEM_DATA_REQ in invalid state %X\n"),pMac->lim.gLimMlmState);) + PELOGW(limLog(pMac, LOGW, FL("OEM_DATA: unexpected LIM_MLM_OEM_DATA_REQ in invalid state %X"),pMac->lim.gLimMlmState);) limPrintMlmState(pMac, LOGW, pMac->lim.gLimMlmState); @@ -2064,7 +2072,7 @@ static void limProcessMlmOemDataReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) } else { - limLog(pMac, LOGP, FL("Could not allocate memory for pMlmOemDataRsp\n")); + limLog(pMac, LOGP, FL("Could not allocate memory for pMlmOemDataRsp")); return; } } @@ -2107,7 +2115,7 @@ limProcessMlmPostJoinSuspendLink(tpAniSirGlobal pMac, eHalStatus status, tANI_U3 if( eHAL_STATUS_SUCCESS != status ) { - limLog(pMac, LOGE, FL("Suspend link(NOTIFY_BSS) failed. still proceeding with join\n")); + limLog(pMac, LOGE, FL("Suspend link(NOTIFY_BSS) failed. still proceeding with join")); } psessionEntry->limPrevMlmState = psessionEntry->limMlmState; psessionEntry->limMlmState = eLIM_MLM_WT_JOIN_BEACON_STATE; @@ -2119,13 +2127,13 @@ limProcessMlmPostJoinSuspendLink(tpAniSirGlobal pMac, eHalStatus status, tANI_U3 pMac->lim.limTimers.gLimJoinFailureTimer.sessionId = psessionEntry->peSessionId; linkState = ((psessionEntry->limSystemRole == eLIM_BT_AMP_STA_ROLE) ? eSIR_LINK_BTAMP_PREASSOC_STATE : eSIR_LINK_PREASSOC_STATE); - limLog(pMac, LOG1, FL("[limProcessMlmJoinReq]: linkState:%d\n"),linkState); + limLog(pMac, LOG1, FL("[limProcessMlmJoinReq]: linkState:%d"),linkState); if (limSetLinkState(pMac, linkState, psessionEntry->pLimMlmJoinReq->bssDescription.bssId, psessionEntry->selfMacAddr, NULL, NULL) != eSIR_SUCCESS ) { - limLog(pMac, LOGE, FL("limSetLinkState to eSIR_LINK_PREASSOC_STATE Failed!!\n")); + limLog(pMac, LOGE, FL("limSetLinkState to eSIR_LINK_PREASSOC_STATE Failed!!")); mlmJoinCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE; psessionEntry->limMlmState = eLIM_MLM_IDLE_STATE; MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, psessionEntry->limMlmState)); @@ -2200,7 +2208,7 @@ limProcessMlmJoinReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if((psessionEntry = peFindSessionBySessionId(pMac,sessionId))== NULL) { - limLog(pMac, LOGP, FL("session does not exist for given sessionId\n")); + limLog(pMac, LOGP, FL("session does not exist for given sessionId")); goto error; } @@ -2243,12 +2251,12 @@ limProcessMlmJoinReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * Return join confirm with invalid parameters code. */ PELOGE(limLog(pMac, LOGE, - FL("Unexpected Join request for role %d state %X\n"), + FL("Unexpected Join request for role %d state %X"), psessionEntry->limSystemRole, psessionEntry->limMlmState);) limPrintMlmState(pMac, LOGE, psessionEntry->limMlmState); - limLog(pMac, LOGE, FL("Unexpected Join request for role %d state %X\n"), + limLog(pMac, LOGE, FL("Unexpected Join request for role %d state %X"), psessionEntry->limSystemRole, psessionEntry->limMlmState); } @@ -2297,7 +2305,7 @@ limProcessMlmAuthReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if(pMsgBuf == NULL) { - PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n"));) + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) return; } @@ -2305,7 +2313,7 @@ limProcessMlmAuthReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) sessionId = pMac->lim.gpLimMlmAuthReq->sessionId; if((psessionEntry= peFindSessionBySessionId(pMac,sessionId) )== NULL) { - limLog(pMac, LOGP, FL("Session Does not exist for given sessionId\n")); + limLog(pMac, LOGP, FL("Session Does not exist for given sessionId")); return; } @@ -2322,7 +2330,7 @@ limProcessMlmAuthReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) eSIR_SUCCESS) { /// Could not get BSSID from CFG. Log error. - limLog(pMac, LOGP, FL("could not retrieve BSSID\n")); + limLog(pMac, LOGP, FL("could not retrieve BSSID")); } #endif //To SuppoRT BT-AMP @@ -2368,7 +2376,7 @@ limProcessMlmAuthReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) pMac->lim.gpLimMlmAuthReq->authType))) { PELOG2(limLog(pMac, LOG2, - FL("Already have pre-auth context with peer\n")); + FL("Already have pre-auth context with peer")); limPrintMacAddr(pMac, pMac->lim.gpLimMlmAuthReq->peerMacAddr, LOG2);) @@ -2384,13 +2392,13 @@ limProcessMlmAuthReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) (tANI_U32 *) &numPreAuthContexts) != eSIR_SUCCESS) { limLog(pMac, LOGP, - FL("Could not retrieve NumPreAuthLimit from CFG\n")); + FL("Could not retrieve NumPreAuthLimit from CFG")); } if (pMac->lim.gLimNumPreAuthContexts == numPreAuthContexts) { PELOGW(limLog(pMac, LOGW, - FL("Number of pre-auth reached max limit\n"));) + FL("Number of pre-auth reached max limit"));) /// Return Auth confirm with reject code mlmAuthCnf.resultCode = @@ -2430,7 +2438,7 @@ limProcessMlmAuthReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) /// Could not start Auth failure timer. // Log error limLog(pMac, LOGP, - FL("could not start Auth failure timer\n")); + FL("could not start Auth failure timer")); // Cleanup as if auth timer expired limProcessAuthFailureTimeout(pMac); } @@ -2494,14 +2502,14 @@ limProcessMlmAssocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if(pMsgBuf == NULL) { - PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n"));) + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) return; } pMlmAssocReq = (tLimMlmAssocReq *) pMsgBuf; if( (psessionEntry = peFindSessionBySessionId(pMac,pMlmAssocReq->sessionId) )== NULL) { - limLog(pMac, LOGP,FL("Session Does not exist for given sessionID\n")); + limLog(pMac, LOGP,FL("Session Does not exist for given sessionID")); palFreeMemory( pMac->hHdd, (tANI_U8 *) pMlmAssocReq); return; } @@ -2511,7 +2519,7 @@ limProcessMlmAssocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) eSIR_SUCCESS) { /// Could not get BSSID from CFG. Log error. - limLog(pMac, LOGP, FL("could not retrieve BSSID\n")); + limLog(pMac, LOGP, FL("could not retrieve BSSID")); } #endif //TO SUPPORT BT-AMP sirCopyMacAddr(currentBssId,psessionEntry->bssId); @@ -2537,7 +2545,7 @@ limProcessMlmAssocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) { if(limSetLinkState(pMac, eSIR_LINK_BTAMP_POSTASSOC_STATE, currentBssId, psessionEntry->selfMacAddr, NULL, NULL) != eSIR_SUCCESS) - PELOGE(limLog(pMac, LOGE, FL("Failed to set the LinkState\n"));) + PELOGE(limLog(pMac, LOGE, FL("Failed to set the LinkState"));) } /// Start association failure timer MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, psessionEntry->peSessionId, eLIM_ASSOC_FAIL_TIMER)); @@ -2547,7 +2555,7 @@ limProcessMlmAssocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) /// Could not start Assoc failure timer. // Log error limLog(pMac, LOGP, - FL("could not start Association failure timer\n")); + FL("could not start Association failure timer")); // Cleanup as if assoc timer expired limProcessAssocFailureTimeout(pMac,LIM_ASSOC ); @@ -2619,7 +2627,7 @@ limProcessMlmReassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if(pMsgBuf == NULL) { - PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n"));) + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) return; } @@ -2627,7 +2635,7 @@ limProcessMlmReassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if((psessionEntry = peFindSessionBySessionId(pMac,pMlmReassocReq->sessionId)) == NULL) { - PELOGE(limLog(pMac, LOGE,FL("Session Does not exist for given sessionId\n"));) + PELOGE(limLog(pMac, LOGE,FL("Session Does not exist for given sessionId"));) palFreeMemory( pMac->hHdd, (tANI_U8 *) pMlmReassocReq); return; } @@ -2674,7 +2682,7 @@ limProcessMlmReassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) sizeof(tSirMacAddr)) != eSIR_SUCCESS) { /// Could not update BSSID at CFG. Log error. - limLog(pMac, LOGP, FL("could not update BSSID at CFG\n")); + limLog(pMac, LOGP, FL("could not update BSSID at CFG")); } #endif //TO SUPPORT BT-AMP @@ -2753,7 +2761,7 @@ limProcessMlmDisassocReqNtf(tpAniSirGlobal pMac, eHalStatus suspendStatus, tANI_ if(eHAL_STATUS_SUCCESS != suspendStatus) { - PELOGE(limLog(pMac, LOGE,FL("Suspend Status is not success %X\n"), suspendStatus);) + PELOGE(limLog(pMac, LOGE,FL("Suspend Status is not success %X"), suspendStatus);) #if 0 //It can ignore the status and proceed with the disassoc processing. mlmDisassocCnf.resultCode = eSIR_SME_REFUSED; @@ -2768,7 +2776,7 @@ limProcessMlmDisassocReqNtf(tpAniSirGlobal pMac, eHalStatus suspendStatus, tANI_ { PELOGE(limLog(pMac, LOGE, - FL("session does not exist for given sessionId\n"));) + FL("session does not exist for given sessionId"));) mlmDisassocCnf.resultCode = eSIR_SME_INVALID_PARAMETERS; goto end; } @@ -2777,7 +2785,7 @@ limProcessMlmDisassocReqNtf(tpAniSirGlobal pMac, eHalStatus suspendStatus, tANI_ eSIR_SUCCESS) { /// Could not get BSSID from CFG. Log error. - limLog(pMac, LOGP, FL("could not retrieve BSSID\n")); + limLog(pMac, LOGP, FL("could not retrieve BSSID")); } #endif //BT-AMP Support sirCopyMacAddr(currentBssId,psessionEntry->bssId); @@ -2919,12 +2927,12 @@ tANI_BOOLEAN limCheckDisassocDeauthAckPending(tpAniSirGlobal pMac, sizeof(tSirMacAddr)))) ) { - PELOGE(limLog(pMac, LOGE,FL("Disassoc/Deauth ack pending\n"));) + PELOG1(limLog(pMac, LOG1, FL("Disassoc/Deauth ack pending"));) return eANI_BOOLEAN_TRUE; } else { - PELOGE(limLog(pMac, LOGE,FL("Disassoc/Deauth Ack not pending\n"));) + PELOG1(limLog(pMac, LOG1, FL("Disassoc/Deauth Ack not pending"));) return eANI_BOOLEAN_FALSE; } } @@ -3014,7 +3022,7 @@ limProcessMlmDisassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if(pMsgBuf == NULL) { - PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n"));) + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) return; } @@ -3024,7 +3032,7 @@ limProcessMlmDisassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) { PELOGE(limLog(pMac, LOGE, - FL("session does not exist for given sessionId\n"));) + FL("session does not exist for given sessionId"));) return; } @@ -3046,7 +3054,7 @@ limProcessMlmDeauthReqNtf(tpAniSirGlobal pMac, eHalStatus suspendStatus, tANI_U3 if(eHAL_STATUS_SUCCESS != suspendStatus) { - PELOGE(limLog(pMac, LOGE,FL("Suspend Status is not success %X\n"), suspendStatus);) + PELOGE(limLog(pMac, LOGE,FL("Suspend Status is not success %X"), suspendStatus);) #if 0 //It can ignore the status and proceed with the disassoc processing. mlmDisassocCnf.resultCode = eSIR_SME_REFUSED; @@ -3059,7 +3067,7 @@ limProcessMlmDeauthReqNtf(tpAniSirGlobal pMac, eHalStatus suspendStatus, tANI_U3 if((psessionEntry = peFindSessionBySessionId(pMac,pMlmDeauthReq->sessionId))== NULL) { - PELOGE(limLog(pMac, LOGE, FL("session does not exist for given sessionId\n"));) + PELOGE(limLog(pMac, LOGE, FL("session does not exist for given sessionId"));) palFreeMemory( pMac->hHdd, (tANI_U8 *) pMlmDeauthReq); return; } @@ -3068,7 +3076,7 @@ limProcessMlmDeauthReqNtf(tpAniSirGlobal pMac, eHalStatus suspendStatus, tANI_U3 eSIR_SUCCESS) { /// Could not get BSSID from CFG. Log error. - limLog(pMac, LOGP, FL("could not retrieve BSSID\n")); + limLog(pMac, LOGP, FL("could not retrieve BSSID")); } #endif //SUPPORT BT-AMP sirCopyMacAddr(currentBssId,psessionEntry->bssId); @@ -3293,7 +3301,7 @@ limProcessMlmDeauthReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if(pMsgBuf == NULL) { - PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n"));) + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) return; } @@ -3302,7 +3310,7 @@ limProcessMlmDeauthReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if((psessionEntry = peFindSessionBySessionId(pMac,pMlmDeauthReq->sessionId))== NULL) { - PELOGE(limLog(pMac, LOGE, FL("session does not exist for given sessionId\n"));) + PELOGE(limLog(pMac, LOGE, FL("session does not exist for given sessionId"));) return; } @@ -3343,7 +3351,7 @@ tpPESession psessionEntry; if(pMsgBuf == NULL) { - PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n"));) + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) return; } @@ -3354,12 +3362,12 @@ tpPESession psessionEntry; if((psessionEntry = peFindSessionBySessionId(pMac,pMlmSetKeysReq->sessionId))== NULL) { - PELOGE(limLog(pMac, LOGE,FL("session does not exist for given sessionId\n"));) + PELOGE(limLog(pMac, LOGE,FL("session does not exist for given sessionId"));) return; } limLog( pMac, LOGW, - FL( "Received MLM_SETKEYS_REQ with parameters:\n" + FL( "Received MLM_SETKEYS_REQ with parameters:" "AID [%d], ED Type [%d], # Keys [%d] & Peer MAC Addr - "), pMlmSetKeysReq->aid, pMlmSetKeysReq->edType, @@ -3368,7 +3376,7 @@ tpPESession psessionEntry; #if 0 if( eSIR_SUCCESS != wlan_cfgGetStr( pMac, WNI_CFG_BSSID, currentBssId, &cfg )) { - limLog( pMac, LOGP, FL("Could not retrieve BSSID\n")); + limLog( pMac, LOGP, FL("Could not retrieve BSSID")); return; } #endif //TO SUPPORT BT-AMP @@ -3383,7 +3391,7 @@ tpPESession psessionEntry; if((!limIsAddrBC( pMlmSetKeysReq->peerMacAddr ) ) && (!palEqualMemory( pMac->hHdd,pMlmSetKeysReq->peerMacAddr, currentBssId, sizeof(tSirMacAddr))) ){ - limLog( pMac, LOGW, FL("Received MLM_SETKEYS_REQ with invalid BSSID\n")); + limLog( pMac, LOGW, FL("Received MLM_SETKEYS_REQ with invalid BSSID")); limPrintMacAddr( pMac, pMlmSetKeysReq->peerMacAddr, LOGW ); // Prepare and Send LIM_MLM_SETKEYS_CNF with error code @@ -3406,7 +3414,7 @@ tpPESession psessionEntry; * pMlmSetKeysReq->key.unicast - 1 -> Unicast keys are being set */ if( limIsAddrBC( pMlmSetKeysReq->peerMacAddr )) { - limLog( pMac, LOG1, FL("Trying to set Group Keys...%d \n"), pMlmSetKeysReq->sessionId); + limLog( pMac, LOG1, FL("Trying to set Group Keys...%d "), pMlmSetKeysReq->sessionId); /** When trying to set Group Keys for any * security mode other than WEP, use the * STA Index corresponding to the AP... @@ -3424,7 +3432,7 @@ tpPESession psessionEntry; break; } }else { - limLog( pMac, LOG1, FL("Trying to set Unicast Keys...\n")); + limLog( pMac, LOG1, FL("Trying to set Unicast Keys...")); /** * Check if there exists a context for the * peer entity for which keys need to be set. @@ -3471,7 +3479,7 @@ tpPESession psessionEntry; defaultKeyId = 0; limLog( pMac, LOG1, - FL( "Trying to set keys for STA Index [%d], using defaultKeyId [%d]\n" ), + FL( "Trying to set keys for STA Index [%d], using defaultKeyId [%d]" ), staIdx, defaultKeyId ); @@ -3479,7 +3487,7 @@ tpPESession psessionEntry; psessionEntry->limPrevMlmState = psessionEntry->limMlmState; psessionEntry->limMlmState = eLIM_MLM_WT_SET_BSS_KEY_STATE; MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, psessionEntry->limMlmState)); - limLog( pMac, LOG1, FL("Trying to set Group Keys...%d \n"), + limLog( pMac, LOG1, FL("Trying to set Group Keys...%d "), psessionEntry->peSessionId); // Package WDA_SET_BSSKEY_REQ message parameters @@ -3528,7 +3536,7 @@ tLimMlmRemoveKeyCnf mlmRemoveKeyCnf; if(pMsgBuf == NULL) { - PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n"));) + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) return; } @@ -3538,7 +3546,7 @@ tLimMlmRemoveKeyCnf mlmRemoveKeyCnf; if((psessionEntry = peFindSessionBySessionId(pMac,pMlmRemoveKeyReq->sessionId))== NULL) { PELOGE(limLog(pMac, LOGE, - FL("session does not exist for given sessionId\n"));) + FL("session does not exist for given sessionId"));) palFreeMemory( pMac->hHdd, (tANI_U8 *) pMsgBuf ); return; } @@ -3558,7 +3566,7 @@ tLimMlmRemoveKeyCnf mlmRemoveKeyCnf; WNI_CFG_BSSID, currentBssId, &cfg )) - limLog( pMac, LOGP, FL("Could not retrieve BSSID\n")); + limLog( pMac, LOGP, FL("Could not retrieve BSSID")); #endif //TO-SUPPORT BT-AMP sirCopyMacAddr(currentBssId,psessionEntry->bssId); @@ -3572,7 +3580,7 @@ tLimMlmRemoveKeyCnf mlmRemoveKeyCnf; sizeof(tSirMacAddr)))) { limLog( pMac, LOGW, - FL("Received MLM_REMOVEKEY_REQ with invalid BSSID\n")); + FL("Received MLM_REMOVEKEY_REQ with invalid BSSID")); limPrintMacAddr( pMac, pMlmRemoveKeyReq->peerMacAddr, LOGW ); // Prepare and Send LIM_MLM_REMOVEKEY_CNF with error code @@ -3676,7 +3684,7 @@ limProcessMinChannelTimeout(tpAniSirGlobal pMac) if((psessionEntry = peFindSessionBySessionId(pMac, pMac->lim.limTimers.gLimMinChannelTimer.sessionId))== NULL) { - limLog(pMac, LOGP,FL("Session Does not exist for given sessionID\n")); + limLog(pMac, LOGP,FL("Session Does not exist for given sessionID")); return; } #endif @@ -3684,7 +3692,7 @@ limProcessMinChannelTimeout(tpAniSirGlobal pMac) if (pMac->lim.gLimMlmState == eLIM_MLM_WT_PROBE_RESP_STATE) { - PELOG1(limLog(pMac, LOG1, FL("Scanning : min channel timeout occurred\n"));) + PELOG1(limLog(pMac, LOG1, FL("Scanning : min channel timeout occurred"));) /// Min channel timer timed out pMac->lim.limTimers.gLimPeriodicProbeReqTimer.sessionId = 0xff; @@ -3719,7 +3727,7 @@ limProcessMinChannelTimeout(tpAniSirGlobal pMac) * Log error. */ limLog(pMac, LOGW, - FL("received unexpected MIN channel timeout in state %X\n"), + FL("received unexpected MIN channel timeout in state %X"), pMac->lim.gLimMlmState); limPrintMlmState(pMac, LOGE, pMac->lim.gLimMlmState); } @@ -3753,7 +3761,7 @@ limProcessMaxChannelTimeout(tpAniSirGlobal pMac) if (pMac->lim.gLimMlmState == eLIM_MLM_WT_PROBE_RESP_STATE || pMac->lim.gLimMlmState == eLIM_MLM_PASSIVE_SCAN_STATE) { - PELOG1(limLog(pMac, LOG1, FL("Scanning : Max channel timed out\n"));) + PELOG1(limLog(pMac, LOG1, FL("Scanning : Max channel timed out"));) /** * MAX channel timer timed out * Continue channel scan. @@ -3787,7 +3795,7 @@ limProcessMaxChannelTimeout(tpAniSirGlobal pMac) * Log error. */ limLog(pMac, LOGW, - FL("received unexpected MAX channel timeout in state %X\n"), + FL("received unexpected MAX channel timeout in state %X"), pMac->lim.gLimMlmState); limPrintMlmState(pMac, LOGW, pMac->lim.gLimMlmState); } @@ -3822,7 +3830,7 @@ limProcessPeriodicProbeReqTimer(tpAniSirGlobal pMac) if(vos_timer_getCurrentState(&pPeriodicProbeReqTimer->vosTimer) != VOS_TIMER_STATE_STOPPED) { - PELOG1(limLog(pMac, LOG1, FL("Invalid state of timer\n"));) + PELOG1(limLog(pMac, LOG1, FL("Invalid state of timer"));) return; } @@ -3830,7 +3838,7 @@ limProcessPeriodicProbeReqTimer(tpAniSirGlobal pMac) (pPeriodicProbeReqTimer->sessionId != 0xff)) { tLimMlmScanReq *pLimMlmScanReq = pMac->lim.gpLimMlmScanReq; - PELOG1(limLog(pMac, LOG1, FL("Scanning : Periodic scanning\n"));) + PELOG1(limLog(pMac, LOG1, FL("Scanning : Periodic scanning"));) /** * Periodic channel timer timed out * to send probe request. @@ -3844,7 +3852,7 @@ limProcessPeriodicProbeReqTimer(tpAniSirGlobal pMac) /* * PELOGE(limLog(pMac, LOGW, FL("sending ProbeReq number %d," - * " for SSID %s on channel: %d\n"), + * " for SSID %s on channel: %d"), * i, pLimMlmScanReq->ssId[i].ssId, * channelNum);) */ @@ -3857,7 +3865,7 @@ limProcessPeriodicProbeReqTimer(tpAniSirGlobal pMac) if ( status != eSIR_SUCCESS) { PELOGE(limLog(pMac, LOGE, FL("send ProbeReq failed for SSID " - "%s on channel: %d\n"), + "%s on channel: %d"), pLimMlmScanReq->ssId[i].ssId, channelNum);) return; @@ -3870,7 +3878,7 @@ limProcessPeriodicProbeReqTimer(tpAniSirGlobal pMac) if (tx_timer_activate(pPeriodicProbeReqTimer) != TX_SUCCESS) { limLog(pMac, LOGP, FL("could not start periodic probe" - " req timer\n")); + " req timer")); return; } } @@ -3882,7 +3890,7 @@ limProcessPeriodicProbeReqTimer(tpAniSirGlobal pMac) * Log error. */ limLog(pMac, LOG1, - FL("received unexpected Periodic scan timeout in state %X\n"), + FL("received unexpected Periodic scan timeout in state %X"), pMac->lim.gLimMlmState); } } /*** limProcessPeriodicProbeReqTimer() ***/ @@ -3915,7 +3923,7 @@ limProcessJoinFailureTimeout(tpAniSirGlobal pMac) if((psessionEntry = peFindSessionBySessionId(pMac, pMac->lim.limTimers.gLimJoinFailureTimer.sessionId))== NULL) { - limLog(pMac, LOGP,FL("Session Does not exist for given sessionID\n")); + limLog(pMac, LOGP,FL("Session Does not exist for given sessionID")); return; } @@ -3927,7 +3935,7 @@ limProcessJoinFailureTimeout(tpAniSirGlobal pMac) eSIR_SUCCESS) { /// Could not get BSSID from CFG. Log error. - limLog(pMac, LOGP, FL("could not retrieve BSSID\n")); + limLog(pMac, LOGP, FL("could not retrieve BSSID")); return; } @@ -3938,7 +3946,7 @@ limProcessJoinFailureTimeout(tpAniSirGlobal pMac) /** * Issue MLM join confirm with timeout reason code */ - PELOGE(limLog(pMac, LOGE, FL(" Join Failure Timeout occurred.\n"));) + PELOGE(limLog(pMac, LOGE, FL(" Join Failure Timeout occurred."));) mlmJoinCnf.resultCode = eSIR_SME_JOIN_TIMEOUT_RESULT_CODE; mlmJoinCnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS; @@ -3947,7 +3955,7 @@ limProcessJoinFailureTimeout(tpAniSirGlobal pMac) MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, psessionEntry->limMlmState)); if(limSetLinkState(pMac, eSIR_LINK_IDLE_STATE, psessionEntry->bssId, psessionEntry->selfMacAddr, NULL, NULL) != eSIR_SUCCESS) - PELOGE(limLog(pMac, LOGE, FL("Failed to set the LinkState\n"));) + PELOGE(limLog(pMac, LOGE, FL("Failed to set the LinkState"));) /* Update PE session Id */ mlmJoinCnf.sessionId = psessionEntry->peSessionId; @@ -3973,7 +3981,7 @@ limProcessJoinFailureTimeout(tpAniSirGlobal pMac) * Log error. */ limLog(pMac, LOGW, - FL("received unexpected JOIN failure timeout in state %X\n"),psessionEntry->limMlmState); + FL("received unexpected JOIN failure timeout in state %X"),psessionEntry->limMlmState); limPrintMlmState(pMac, LOGW, psessionEntry->limMlmState); } } /*** limProcessJoinFailureTimeout() ***/ @@ -4003,7 +4011,7 @@ static void limProcessPeriodicJoinProbeReqTimer(tpAniSirGlobal pMac) if((psessionEntry = peFindSessionBySessionId(pMac, pMac->lim.limTimers.gLimPeriodicJoinProbeReqTimer.sessionId))== NULL) { - limLog(pMac, LOGE,FL("session does not exist for given SessionId\n")); + limLog(pMac, LOGE,FL("session does not exist for given SessionId")); return; } @@ -4025,7 +4033,7 @@ static void limProcessPeriodicJoinProbeReqTimer(tpAniSirGlobal pMac) // Activate Join Periodic Probe Req timer if (tx_timer_activate(&pMac->lim.limTimers.gLimPeriodicJoinProbeReqTimer) != TX_SUCCESS) { - limLog(pMac, LOGP, FL("could not activate Periodic Join req failure timer\n")); + limLog(pMac, LOGP, FL("could not activate Periodic Join req failure timer")); return; } } @@ -4058,7 +4066,7 @@ limProcessAuthFailureTimeout(tpAniSirGlobal pMac) if((psessionEntry = peFindSessionBySessionId(pMac, pMac->lim.limTimers.gLimAuthFailureTimer.sessionId))== NULL) { - limLog(pMac, LOGP,FL("Session Does not exist for given sessionID\n")); + limLog(pMac, LOGP,FL("Session Does not exist for given sessionID")); return; } @@ -4086,7 +4094,7 @@ limProcessAuthFailureTimeout(tpAniSirGlobal pMac) * in states other than wt_auth_frame2/4 * Log error. */ - PELOGE(limLog(pMac, LOGE, FL("received unexpected AUTH failure timeout in state %X\n"), psessionEntry->limMlmState);) + PELOGE(limLog(pMac, LOGE, FL("received unexpected AUTH failure timeout in state %X"), psessionEntry->limMlmState);) limPrintMlmState(pMac, LOGE, psessionEntry->limMlmState); break; @@ -4123,13 +4131,13 @@ limProcessAuthRspTimeout(tpAniSirGlobal pMac, tANI_U32 authIndex) if (NULL == pAuthNode) { - limLog(pMac, LOGW, FL("Invalid auth node\n")); + limLog(pMac, LOGW, FL("Invalid auth node")); return; } if ((psessionEntry = peFindSessionByBssid(pMac, pAuthNode->peerMacAddr, &sessionId)) == NULL) { - limLog(pMac, LOGW, FL("session does not exist for given BSSID \n")); + limLog(pMac, LOGW, FL("session does not exist for given BSSID ")); return; } @@ -4205,7 +4213,7 @@ limProcessAssocFailureTimeout(tpAniSirGlobal pMac, tANI_U32 MsgType) if((psessionEntry = peFindSessionBySessionId(pMac, sessionId))== NULL) { - limLog(pMac, LOGP,FL("Session Does not exist for given sessionID\n")); + limLog(pMac, LOGP,FL("Session Does not exist for given sessionID")); return; } @@ -4223,7 +4231,7 @@ limProcessAssocFailureTimeout(tpAniSirGlobal pMac, tANI_U32 MsgType) // Log error PELOG1(limLog(pMac, LOG1, - FL("Re/Association Response not received before timeout \n"));) + FL("Re/Association Response not received before timeout "));) if (( (psessionEntry->limSystemRole == eLIM_AP_ROLE) || (psessionEntry->limSystemRole == eLIM_BT_AMP_AP_ROLE) )|| ( (psessionEntry->limMlmState != eLIM_MLM_WT_ASSOC_RSP_STATE) && @@ -4237,7 +4245,7 @@ limProcessAssocFailureTimeout(tpAniSirGlobal pMac, tANI_U32 MsgType) // Log error limLog(pMac, LOGW, - FL("received unexpected REASSOC failure timeout in state %X for role %d\n"), + FL("received unexpected REASSOC failure timeout in state %X for role %d"), psessionEntry->limMlmState, psessionEntry->limSystemRole); limPrintMlmState(pMac, LOGW, psessionEntry->limMlmState); } @@ -4247,7 +4255,7 @@ limProcessAssocFailureTimeout(tpAniSirGlobal pMac, tANI_U32 MsgType) if ((MsgType == LIM_ASSOC) || ((MsgType == LIM_REASSOC) && (psessionEntry->limMlmState == eLIM_MLM_WT_FT_REASSOC_RSP_STATE))) { - PELOGE(limLog(pMac, LOGE, FL("(Re)Assoc Failure Timeout occurred.\n"));) + PELOGE(limLog(pMac, LOGE, FL("(Re)Assoc Failure Timeout occurred."));) psessionEntry->limMlmState = eLIM_MLM_IDLE_STATE; MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, psessionEntry->limMlmState)); @@ -4266,7 +4274,7 @@ limProcessAssocFailureTimeout(tpAniSirGlobal pMac, tANI_U32 MsgType) //To remove the preauth node in case of fail to associate if (limSearchPreAuthList(pMac, psessionEntry->bssId)) { - PELOG1(limLog(pMac, LOG1, FL(" delete pre auth node for %02X-%02X-%02X-%02X-%02X-%02X\n"), + PELOG1(limLog(pMac, LOG1, FL(" delete pre auth node for %02X-%02X-%02X-%02X-%02X-%02X"), psessionEntry->bssId[0], psessionEntry->bssId[1], psessionEntry->bssId[2], psessionEntry->bssId[3], psessionEntry->bssId[4], psessionEntry->bssId[5]);) limDeletePreAuthNode(pMac, psessionEntry->bssId); @@ -4369,7 +4377,7 @@ tpLimMlmAddBACnf pMlmAddBACnf; if(pMsgBuf == NULL) { - PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n"));) + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) return; } @@ -4377,7 +4385,7 @@ tpLimMlmAddBACnf pMlmAddBACnf; if((psessionEntry = peFindSessionBySessionId(pMac,pMlmAddBAReq->sessionId))== NULL) { PELOGE(limLog(pMac, LOGE, - FL("session does not exist for given sessionId\n"));) + FL("session does not exist for given sessionId"));) palFreeMemory( pMac->hHdd, (tANI_U8 *) pMsgBuf ); return; } @@ -4400,7 +4408,7 @@ tpLimMlmAddBACnf pMlmAddBACnf; sizeof( tLimMlmAddBACnf ))) { limLog( pMac, LOGP, - FL("palAllocateMemory failed with error code %d\n")); + FL("palAllocateMemory failed with error code %d")); palFreeMemory( pMac->hHdd, (tANI_U8 *) pMsgBuf ); return; } @@ -4461,7 +4469,7 @@ tpLimMlmAddBARsp pMlmAddBARsp; if(pMsgBuf == NULL) { - PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n"));) + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) return; } @@ -4470,7 +4478,7 @@ tpLimMlmAddBARsp pMlmAddBARsp; if(( psessionEntry = peFindSessionBySessionId(pMac,pMlmAddBARsp->sessionId))== NULL) { PELOGE(limLog(pMac, LOGE, - FL("session does not exist for given session ID\n"));) + FL("session does not exist for given session ID"));) palFreeMemory( pMac->hHdd, (tANI_U8 *) pMsgBuf ); return; } @@ -4480,7 +4488,7 @@ tpLimMlmAddBARsp pMlmAddBARsp; if( eSIR_SUCCESS != limSendAddBARsp( pMac,pMlmAddBARsp,psessionEntry)) { limLog( pMac, LOGE, - FL("Failed to send ADDBA Rsp to peer \n")); + FL("Failed to send ADDBA Rsp to peer ")); limPrintMacAddr( pMac, pMlmAddBARsp->peerMacAddr, LOGE ); /* Clean the BA context maintained by HAL and TL on failure */ pSta = dphLookupHashEntry( pMac, pMlmAddBARsp->peerMacAddr, &aid, @@ -4523,7 +4531,7 @@ void limProcessMlmDelBAReq( tpAniSirGlobal pMac, if(pMsgBuf == NULL) { - PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n"));) + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) return; } @@ -4532,7 +4540,7 @@ void limProcessMlmDelBAReq( tpAniSirGlobal pMac, if((psessionEntry = peFindSessionBySessionId(pMac,pMlmDelBAReq->sessionId))== NULL) { - PELOGE(limLog(pMac, LOGE,FL("session does not exist for given bssId\n"));) + PELOGE(limLog(pMac, LOGE,FL("session does not exist for given bssId"));) palFreeMemory( pMac->hHdd, (tANI_U8 *) pMsgBuf ); return; } @@ -4569,7 +4577,7 @@ void limProcessMlmDelBAReq( tpAniSirGlobal pMac, (void **) &pMlmDelBACnf, sizeof( tLimMlmDelBACnf ))) { - limLog( pMac, LOGP, FL("palAllocateMemory failed\n")); + limLog( pMac, LOGP, FL("palAllocateMemory failed")); palFreeMemory( pMac->hHdd, (tANI_U8 *) pMsgBuf ); return; } @@ -4630,23 +4638,23 @@ limSMPowerSaveStateInd(tpAniSirGlobal pMac, tSirMacHTMIMOPowerSaveState state) tpPESession psessionEntry = &pMac->lim.gpSession[0]; //TBD-RAJESH HOW TO GET sessionEntry????? /** Verify the Mode of operation */ if (pMac->lim.gLimSystemRole != eSYSTEM_STA_ROLE) { - PELOGE(limLog(pMac, LOGE, FL("Got PMC indication when System not in the STA Role\n"));) + PELOGE(limLog(pMac, LOGE, FL("Got PMC indication when System not in the STA Role"));) return eSIR_FAILURE; } if ((pMac->lim.gHTMIMOPSState == state) || (state == eSIR_HT_MIMO_PS_NA )) { - PELOGE(limLog(pMac, LOGE, FL("Got Indication when already in the same mode or State passed is NA:%d \n"), state);) + PELOGE(limLog(pMac, LOGE, FL("Got Indication when already in the same mode or State passed is NA:%d "), state);) return eSIR_FAILURE; } if (!pMac->lim.htCapability){ - PELOGW(limLog(pMac, LOGW, FL(" Not in 11n or HT capable mode\n"));) + PELOGW(limLog(pMac, LOGW, FL(" Not in 11n or HT capable mode"));) return eSIR_FAILURE; } /** Update the CFG about the default MimoPS State */ if (wlan_cfgGetInt(pMac, WNI_CFG_HT_CAP_INFO, &cfgVal1) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("could not retrieve HT Cap CFG \n")); + limLog(pMac, LOGP, FL("could not retrieve HT Cap CFG ")); return eSIR_FAILURE; } @@ -4655,13 +4663,13 @@ limSMPowerSaveStateInd(tpAniSirGlobal pMac, tSirMacHTMIMOPowerSaveState state) pHTCapabilityInfo->mimoPowerSave = state; if(cfgSetInt(pMac, WNI_CFG_HT_CAP_INFO, *(tANI_U16*)pHTCapabilityInfo) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("could not update HT Cap Info CFG\n")); + limLog(pMac, LOGP, FL("could not update HT Cap Info CFG")); return eSIR_FAILURE; } - PELOG2(limLog(pMac, LOG2, FL(" The HT Capability for Mimo Pwr is updated to State: %u \n"),state);) + PELOG2(limLog(pMac, LOG2, FL(" The HT Capability for Mimo Pwr is updated to State: %u "),state);) if (pMac->lim.gLimSmeState != eLIM_SME_LINK_EST_STATE) { - PELOG2(limLog(pMac, LOG2,FL(" The STA is not in the Connected/Link Est Sme_State: %d \n"), pMac->lim.gLimSmeState);) + PELOG2(limLog(pMac, LOG2,FL(" The STA is not in the Connected/Link Est Sme_State: %d "), pMac->lim.gLimSmeState);) /** Update in the LIM the MIMO PS state of the SELF */ pMac->lim.gHTMIMOPSState = state; return eSIR_SUCCESS; @@ -4669,7 +4677,7 @@ limSMPowerSaveStateInd(tpAniSirGlobal pMac, tSirMacHTMIMOPowerSaveState state) pSta = dphGetHashEntry(pMac, DPH_STA_HASH_INDEX_PEER, &psessionEntry->dph.dphHashTable); if (!pSta->mlmStaContext.htCapability) { - limLog( pMac, LOGE,FL( "limSendSMPowerState: Peer is not HT Capable \n" )); + limLog( pMac, LOGE,FL( "limSendSMPowerState: Peer is not HT Capable " )); return eSIR_FAILURE; } @@ -4680,7 +4688,7 @@ limSMPowerSaveStateInd(tpAniSirGlobal pMac, tSirMacHTMIMOPowerSaveState state) /** Send Action Frame with the corresponding mode */ retStatus = limSendSMPowerStateFrame(pMac, macAddr, state); if (retStatus != eSIR_SUCCESS) { - PELOGE(limLog(pMac, LOGE, "Update SM POWER: Sending Action Frame has failed\n");) + PELOGE(limLog(pMac, LOGE, "Update SM POWER: Sending Action Frame has failed");) return retStatus; } } @@ -4724,7 +4732,7 @@ ePhyChanBondState limGet11ACPhyCBState(tpAniSirGlobal pMac, tANI_U8 channel, tAN cbState = PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH; else limLog (pMac, LOGP, - FL("Invalid Channel Number = %d Center Chan = %d \n"), + FL("Invalid Channel Number = %d Center Chan = %d "), channel, peerCenterChan); } if ( (htSecondaryChannelOffset @@ -4739,7 +4747,7 @@ ePhyChanBondState limGet11ACPhyCBState(tpAniSirGlobal pMac, tANI_U8 channel, tAN cbState = PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH; else limLog (pMac, LOGP, - FL("Invalid Channel Number = %d Center Chan = %d \n"), + FL("Invalid Channel Number = %d Center Chan = %d "), channel, peerCenterChan); } return cbState; @@ -4759,7 +4767,7 @@ limSetChannel(tpAniSirGlobal pMac, tANI_U8 channel, tANI_U8 secChannelOffset, tP if ( NULL == peSession) { - limLog (pMac, LOGP, FL("Invalid PE session = %d\n"), peSessionId); + limLog (pMac, LOGP, FL("Invalid PE session = %d"), peSessionId); return; } #if defined WLAN_FEATURE_VOWIFI @@ -4775,7 +4783,7 @@ limSetChannel(tpAniSirGlobal pMac, tANI_U8 channel, tANI_U8 secChannelOffset, tP } #else if (wlan_cfgGetInt(pMac, WNI_CFG_LOCAL_POWER_CONSTRAINT, &localPwrConstraint) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("could not read WNI_CFG_LOCAL_POWER_CONSTRAINT from CFG\n")); + limLog(pMac, LOGP, FL("could not read WNI_CFG_LOCAL_POWER_CONSTRAINT from CFG")); return; } // Send WDA_CHNL_SWITCH_IND to HAL diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessMlmRspMessages.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessMlmRspMessages.c index 23b3984305d..6399b0c02be 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessMlmRspMessages.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessMlmRspMessages.c @@ -127,7 +127,7 @@ limProcessMlmRspMessages(tpAniSirGlobal pMac, tANI_U32 msgType, tANI_U32 *pMsgBu if(pMsgBuf == NULL) { - PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n"));) + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) return; } switch (msgType) @@ -238,7 +238,7 @@ limProcessMlmScanCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * Log error */ PELOGE(limLog(pMac, LOGE, - FL("received unexpected MLM_SCAN_CNF in state %X\n"), + FL("received unexpected MLM_SCAN_CNF in state %X"), pMac->lim.gLimSmeState);) return; } @@ -287,7 +287,7 @@ limProcessMlmScanCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) /// Could not activate background scan timer. // Log error limLog(pMac, LOGP, - FL("could not activate background scan timer\n")); + FL("could not activate background scan timer")); pMac->lim.gLimBackgroundScanStarted = FALSE; } else @@ -363,13 +363,13 @@ limProcessMlmStartCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if(pMsgBuf == NULL) { - PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n"));) + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) return; } pLimMlmStartCnf = (tLimMlmStartCnf*)pMsgBuf; if((psessionEntry = peFindSessionBySessionId(pMac,pLimMlmStartCnf->sessionId))==NULL) { - PELOGE(limLog(pMac, LOGE,FL("Session does Not exist with given sessionId \n"));) + PELOGE(limLog(pMac, LOGE,FL("Session does Not exist with given sessionId "));) return; } smesessionId = psessionEntry->smeSessionId; @@ -383,7 +383,7 @@ limProcessMlmStartCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * Log error */ PELOGE(limLog(pMac, LOGE, - FL("received unexpected MLM_START_CNF in state %X\n"), + FL("received unexpected MLM_START_CNF in state %X"), psessionEntry->limSmeState);) return; } @@ -400,18 +400,18 @@ limProcessMlmStartCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId, psessionEntry->limSmeState)); if(psessionEntry->bssType == eSIR_BTAMP_STA_MODE) { - limLog(pMac, LOG1, FL("*** Started BSS in BT_AMP STA SIDE***\n")); + limLog(pMac, LOG1, FL("*** Started BSS in BT_AMP STA SIDE***")); } else if(psessionEntry->bssType == eSIR_BTAMP_AP_MODE) { - limLog(pMac, LOG1, FL("*** Started BSS in BT_AMP AP SIDE***\n")); + limLog(pMac, LOG1, FL("*** Started BSS in BT_AMP AP SIDE***")); } else if(psessionEntry->bssType == eSIR_INFRA_AP_MODE) { - limLog(pMac, LOG1, FL("*** Started BSS in INFRA AP SIDE***\n")); + limLog(pMac, LOG1, FL("*** Started BSS in INFRA AP SIDE***")); } else - PELOG1(limLog(pMac, LOG1, FL("*** Started BSS ***\n"));) + PELOG1(limLog(pMac, LOG1, FL("*** Started BSS ***"));) } else { @@ -459,14 +459,14 @@ limProcessMlmJoinCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) pLimMlmJoinCnf = (tLimMlmJoinCnf*)pMsgBuf; if( (psessionEntry = peFindSessionBySessionId(pMac,pLimMlmJoinCnf->sessionId))== NULL) { - PELOGE(limLog(pMac, LOGE,FL("Session does not exist for given sessionId\n"));) + PELOGE(limLog(pMac, LOGE,FL("Session does not exist for given sessionId"));) return; } if (psessionEntry->limSmeState!= eLIM_SME_WT_JOIN_STATE) { PELOGE(limLog(pMac, LOGE, - FL("received unexpected MLM_JOIN_CNF in state %X\n"), + FL("received unexpected MLM_JOIN_CNF in state %X"), psessionEntry->limSmeState);) return; } @@ -525,13 +525,13 @@ limProcessMlmAuthCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if(pMsgBuf == NULL) { - PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n"));) + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) return; } pMlmAuthCnf = (tLimMlmAuthCnf*)pMsgBuf; if((psessionEntry = peFindSessionBySessionId(pMac,pMlmAuthCnf->sessionId))== NULL) { - PELOGE(limLog(pMac, LOGE, FL("session does not exist for given sessionId\n"));) + PELOGE(limLog(pMac, LOGE, FL("session does not exist for given sessionId"));) return; } @@ -545,7 +545,7 @@ limProcessMlmAuthCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * Log error */ PELOGE(limLog(pMac, LOGE, - FL("received unexpected MLM_AUTH_CNF in state %X\n"), + FL("received unexpected MLM_AUTH_CNF in state %X"), psessionEntry->limSmeState);) return; } @@ -562,7 +562,7 @@ limProcessMlmAuthCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * Log error. */ limLog(pMac, LOGP, - FL("could not retrieve AuthType value\n")); + FL("could not retrieve AuthType value")); } } else @@ -582,7 +582,7 @@ limProcessMlmAuthCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) { // Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for mlmAuthReq\n")); + FL("call to palAllocateMemory failed for mlmAuthReq")); return; } palZeroMemory( pMac->hHdd, (tANI_U8 *) pMlmAuthReq, sizeof(tLimMlmAuthReq)); @@ -607,7 +607,7 @@ limProcessMlmAuthCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * Log error. */ limLog(pMac, LOGP, - FL("could not retrieve AuthFailureTimeout value\n")); + FL("could not retrieve AuthFailureTimeout value")); } limPostMlmMessage(pMac, LIM_MLM_AUTH_REQ, @@ -619,7 +619,7 @@ limProcessMlmAuthCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) // MAC based authentication failure if (psessionEntry->limSmeState == eLIM_SME_WT_AUTH_STATE) { - PELOGE(limLog(pMac, LOGE, FL("Auth Failure occurred.\n"));) + PELOGE(limLog(pMac, LOGE, FL("Auth Failure occurred."));) psessionEntry->limSmeState = eLIM_SME_JOIN_FAILURE_STATE; MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId, psessionEntry->limSmeState)); psessionEntry->limMlmState = eLIM_MLM_IDLE_STATE; @@ -658,12 +658,12 @@ limProcessMlmAuthCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * Trigger Association with BSS */ PELOG1(limLog(pMac, LOG1, - FL("*** Authenticated with BSS ***\n"));) + FL("*** Authenticated with BSS ***"));) if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pMlmAssocReq, sizeof(tLimMlmAssocReq))) { // Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for mlmAssocReq\n")); + FL("call to palAllocateMemory failed for mlmAssocReq")); return; } val = sizeof(tSirMacAddr); @@ -673,7 +673,7 @@ limProcessMlmAuthCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) &val) != eSIR_SUCCESS) { /// Could not get BSSID from CFG. Log error. - limLog(pMac, LOGP, FL("could not retrieve BSSID\n")); + limLog(pMac, LOGP, FL("could not retrieve BSSID")); } #endif //SUPPORT BT-AMP sirCopyMacAddr(pMlmAssocReq->peerMacAddr,psessionEntry->bssId); @@ -686,7 +686,7 @@ limProcessMlmAuthCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve AssocFailureTimeout value\n")); + FL("could not retrieve AssocFailureTimeout value")); } if (cfgGetCapabilityInfo(pMac, &caps,psessionEntry) != eSIR_SUCCESS) { @@ -695,7 +695,7 @@ limProcessMlmAuthCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve Capabilities value\n")); + FL("could not retrieve Capabilities value")); } /*Clear spectrum management bit if AP doesn't support it*/ if(!(psessionEntry->pLimJoinReq->bssDescription.capabilityInfo & LIM_SPECTRUM_MANAGEMENT_BIT_MASK)) @@ -706,7 +706,7 @@ limProcessMlmAuthCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) pMlmAssocReq->capabilityInfo = caps; PELOG3(limLog(pMac, LOG3, - FL("Capabilities to be used in AssocReq=0x%X, privacy bit=%x shortSlotTime %x\n"), + FL("Capabilities to be used in AssocReq=0x%X, privacy bit=%x shortSlotTime %x"), caps, ((tpSirMacCapabilityInfo) &pMlmAssocReq->capabilityInfo)->privacy, ((tpSirMacCapabilityInfo) &pMlmAssocReq->capabilityInfo)->shortSlotTime);) @@ -715,7 +715,7 @@ limProcessMlmAuthCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) WNI_CFG_TELE_BCN_MAX_LI */ if(wlan_cfgGetInt(pMac, WNI_CFG_TELE_BCN_WAKEUP_EN, &teleBcnEn) != eSIR_SUCCESS) - limLog(pMac, LOGP, FL("Couldn't get WNI_CFG_TELE_BCN_WAKEUP_EN\n")); + limLog(pMac, LOGP, FL("Couldn't get WNI_CFG_TELE_BCN_WAKEUP_EN")); val = WNI_CFG_LISTEN_INTERVAL_STADEF; @@ -728,7 +728,7 @@ limProcessMlmAuthCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * Could not get ListenInterval value * from CFG. Log error. */ - limLog(pMac, LOGP, FL("could not retrieve ListenInterval\n")); + limLog(pMac, LOGP, FL("could not retrieve ListenInterval")); } } else @@ -739,7 +739,7 @@ limProcessMlmAuthCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * Could not get ListenInterval value * from CFG. Log error. */ - limLog(pMac, LOGP, FL("could not retrieve ListenInterval\n")); + limLog(pMac, LOGP, FL("could not retrieve ListenInterval")); } } @@ -797,13 +797,13 @@ limProcessMlmAssocCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if(pMsgBuf == NULL) { - limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n")); + limLog(pMac, LOGE,FL("Buffer is Pointing to NULL")); return; } pLimMlmAssocCnf = (tLimMlmAssocCnf*)pMsgBuf; if((psessionEntry = peFindSessionBySessionId(pMac,pLimMlmAssocCnf->sessionId)) == NULL) { - PELOGE(limLog(pMac, LOGE,FL("Session does not exist for given sessionId\n"));) + PELOGE(limLog(pMac, LOGE,FL("Session does not exist for given sessionId"));) return; } if (psessionEntry->limSmeState != eLIM_SME_WT_ASSOC_STATE || @@ -815,14 +815,14 @@ limProcessMlmAssocCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * Log error */ PELOGE(limLog(pMac, LOGE, - FL("received unexpected MLM_ASSOC_CNF in state %X\n"), + FL("received unexpected MLM_ASSOC_CNF in state %X"), psessionEntry->limSmeState);) return; } if (((tLimMlmAssocCnf *) pMsgBuf)->resultCode != eSIR_SME_SUCCESS) { // Association failure - PELOG1(limLog(pMac, LOG1, FL("*** Association failure ***\n"));) + PELOG1(limLog(pMac, LOG1, FL("*** Association failure ***"));) psessionEntry->limSmeState = eLIM_SME_JOIN_FAILURE_STATE; MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId, pMac->lim.gLimSmeState)); /** @@ -836,7 +836,7 @@ limProcessMlmAssocCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) else { // Successful Association - PELOG1(limLog(pMac, LOG1, FL("*** Associated with BSS ***\n"));) + PELOG1(limLog(pMac, LOG1, FL("*** Associated with BSS ***"));) psessionEntry->limSmeState = eLIM_SME_LINK_EST_STATE; MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId, psessionEntry->limSmeState)); /** @@ -875,13 +875,13 @@ limProcessMlmReassocCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if(pMsgBuf == NULL) { - PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n"));) + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) return; } pLimMlmReassocCnf = (tLimMlmReassocCnf*) pMsgBuf; if((psessionEntry = peFindSessionBySessionId(pMac,pLimMlmReassocCnf->sessionId))==NULL) { - PELOGE(limLog(pMac, LOGE, FL("session Does not exist for given session Id\n"));) + PELOGE(limLog(pMac, LOGE, FL("session Does not exist for given session Id"));) return; } if ((psessionEntry->limSmeState != eLIM_SME_WT_REASSOC_STATE) || @@ -893,7 +893,7 @@ limProcessMlmReassocCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * Log error */ PELOGE(limLog(pMac, LOGE, - FL("Rcv unexpected MLM_REASSOC_CNF in role %d, sme state 0x%X\n"), + FL("Rcv unexpected MLM_REASSOC_CNF in role %d, sme state 0x%X"), psessionEntry->limSystemRole, psessionEntry->limSmeState);) return; } @@ -902,10 +902,10 @@ limProcessMlmReassocCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) psessionEntry->pLimReAssocReq = NULL; } - PELOGE(limLog(pMac, LOGE, FL("Rcv MLM_REASSOC_CNF with result code %d\n"), pLimMlmReassocCnf->resultCode);) + PELOGE(limLog(pMac, LOGE, FL("Rcv MLM_REASSOC_CNF with result code %d"), pLimMlmReassocCnf->resultCode);) if (pLimMlmReassocCnf->resultCode == eSIR_SME_SUCCESS) { // Successful Reassociation - PELOG1(limLog(pMac, LOG1, FL("*** Reassociated with new BSS ***\n"));) + PELOG1(limLog(pMac, LOG1, FL("*** Reassociated with new BSS ***"));) psessionEntry->limSmeState = eLIM_SME_LINK_EST_STATE; MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId, psessionEntry->limSmeState)); @@ -973,12 +973,12 @@ limProcessMlmReassocInd(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) tANI_U8 sessionId; if(pMsgBuf == NULL) { - PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n"));) + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) return; } if((psessionEntry = peFindSessionByBssid(pMac,((tpLimMlmReassocInd)pMsgBuf)->peerMacAddr, &sessionId))== NULL) { - PELOGE(limLog(pMac, LOGE,FL("session does not exist for given BSSId\n"));) + PELOGE(limLog(pMac, LOGE,FL("session does not exist for given BSSId"));) return; } /// Inform Host of STA reassociation @@ -987,7 +987,7 @@ limProcessMlmReassocInd(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) { // Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for eWNI_SME_REASSOC_IND\n")); + FL("call to palAllocateMemory failed for eWNI_SME_REASSOC_IND")); return; } @@ -1012,7 +1012,7 @@ limProcessMlmReassocInd(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) pStaDs = dphGetHashEntry(pMac, ((tpLimMlmReassocInd) pMsgBuf)->aid, &psessionEntry->dph.dphHashTable); if (! pStaDs) { - limLog( pMac, LOGP, FL("MLM ReAssocInd: Station context no longer valid (aid %d)\n"), + limLog( pMac, LOGP, FL("MLM ReAssocInd: Station context no longer valid (aid %d)"), ((tpLimMlmReassocInd) pMsgBuf)->aid); palFreeMemory(pMac->hHdd, pSirSmeReassocInd); return; @@ -1020,7 +1020,7 @@ limProcessMlmReassocInd(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) limSysProcessMmhMsgApi(pMac, &msgQ, ePROT); PELOG1(limLog(pMac, LOG1, - FL("Create CNF_WAIT_TIMER after received LIM_MLM_REASSOC_IND\n"));) + FL("Create CNF_WAIT_TIMER after received LIM_MLM_REASSOC_IND"));) /* ** turn on a timer to detect the loss of REASSOC CNF **/ @@ -1054,14 +1054,14 @@ limProcessMlmAuthInd(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if(pMsgBuf == NULL) { - PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n"));) + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) return; } if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pSirSmeAuthInd, sizeof(tSirSmeAuthInd))) { // Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for eWNI_SME_AUTH_IND\n")); + FL("call to palAllocateMemory failed for eWNI_SME_AUTH_IND")); } limCopyU16((tANI_U8 *) &pSirSmeAuthInd->messageType, eWNI_SME_AUTH_IND); limAuthIndSerDes(pMac, (tpLimMlmAuthInd) pMsgBuf, @@ -1162,12 +1162,12 @@ limProcessMlmAssocInd(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) tpPESession psessionEntry; if(pMsgBuf == NULL) { - PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n"));) + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) return; } if((psessionEntry = peFindSessionBySessionId(pMac,((tpLimMlmAssocInd) pMsgBuf)->sessionId))== NULL) { - limLog( pMac, LOGE, FL( "Session Does not exist for given sessionId\n" )); + limLog( pMac, LOGE, FL( "Session Does not exist for given sessionId" )); return; } /// Inform Host of STA association @@ -1176,7 +1176,7 @@ limProcessMlmAssocInd(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) { // Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for eWNI_SME_ASSOC_IND\n")); + FL("call to palAllocateMemory failed for eWNI_SME_ASSOC_IND")); return; } @@ -1189,7 +1189,7 @@ limProcessMlmAssocInd(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) ((tpLimMlmAssocInd) pMsgBuf)->aid, &psessionEntry->dph.dphHashTable); if (! pStaDs) { // good time to panic... - limLog(pMac, LOGE, FL("MLM AssocInd: Station context no longer valid (aid %d)\n"), + limLog(pMac, LOGE, FL("MLM AssocInd: Station context no longer valid (aid %d)"), ((tpLimMlmAssocInd) pMsgBuf)->aid); palFreeMemory(pMac->hHdd, pSirSmeAssocInd); @@ -1204,7 +1204,7 @@ limProcessMlmAssocInd(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) limSysProcessMmhMsgApi(pMac, &msgQ, ePROT); PELOG1(limLog(pMac, LOG1, - FL("Create CNF_WAIT_TIMER after received LIM_MLM_ASSOC_IND\n"));) + FL("Create CNF_WAIT_TIMER after received LIM_MLM_ASSOC_IND"));) /* ** turn on a timer to detect the loss of ASSOC CNF **/ @@ -1216,7 +1216,7 @@ limProcessMlmAssocInd(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) { tpSirSmeAssocCnf pSmeAssoccnf; if(!palAllocateMemory(pMac->hHdd,(void **)&pSmeAssoccnf,sizeof(tSirSmeAssocCnf))) - PELOGE(limLog(pMac, LOGE, FL("palAllocateMemory failed for pSmeAssoccnf \n"));) + PELOGE(limLog(pMac, LOGE, FL("palAllocateMemory failed for pSmeAssoccnf "));) pSmeAssoccnf->messageType = eWNI_SME_ASSOC_CNF; pSmeAssoccnf->length = sizeof(tSirSmeAssocCnf); palCopyMemory( pMac->hHdd,pSmeAssoccnf->peerMacAddr,((tpLimMlmAssocInd)pMsgBuf)->peerMacAddr,6); @@ -1263,7 +1263,7 @@ limProcessMlmDisassocInd(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) pMlmDisassocInd = (tLimMlmDisassocInd *) pMsgBuf; if( (psessionEntry = peFindSessionBySessionId(pMac,pMlmDisassocInd->sessionId) )== NULL) { - limLog(pMac, LOGP,FL("Session Does not exist for given sessionID\n")); + limLog(pMac, LOGP,FL("Session Does not exist for given sessionID")); return; } switch (psessionEntry->limSystemRole) @@ -1277,7 +1277,7 @@ limProcessMlmDisassocInd(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) break; default: // eLIM_AP_ROLE //eLIM_BT_AMP_AP_ROLE PELOG1(limLog(pMac, LOG1, - FL("*** Peer staId=%d Disassociated ***\n"), + FL("*** Peer staId=%d Disassociated ***"), pMlmDisassocInd->aid);) // Send SME_DISASOC_IND after Polaris cleanup // (after receiving LIM_MLM_PURGE_STA_IND) @@ -1312,7 +1312,7 @@ limProcessMlmDisassocCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) pMlmDisassocCnf = (tLimMlmDisassocCnf *) pMsgBuf; if((psessionEntry = peFindSessionBySessionId(pMac,pMlmDisassocCnf->sessionId))== NULL) { - PELOGE(limLog(pMac, LOGE,FL("session Does not exist for given session Id\n"));) + PELOGE(limLog(pMac, LOGE,FL("session Does not exist for given session Id"));) return; } resultCode = (tSirResultCodes) @@ -1333,7 +1333,7 @@ limProcessMlmDisassocCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * Log error */ PELOGE(limLog(pMac, LOGE, - FL("received unexpected MLM_DISASSOC_CNF in state %X\n"),psessionEntry->limSmeState);) + FL("received unexpected MLM_DISASSOC_CNF in state %X"),psessionEntry->limSmeState);) return; } if (pMac->lim.gLimRspReqd) @@ -1398,7 +1398,7 @@ limProcessMlmDeauthInd(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) pMlmDeauthInd = (tLimMlmDeauthInd *) pMsgBuf; if((psessionEntry = peFindSessionByBssid(pMac,pMlmDeauthInd->peerMacAddr,&sessionId))== NULL) { - PELOGE(limLog(pMac, LOGE,FL("session does not exist for given BSSId\n"));) + PELOGE(limLog(pMac, LOGE,FL("session does not exist for given BSSId"));) return; } switch (psessionEntry->limSystemRole) @@ -1413,7 +1413,7 @@ limProcessMlmDeauthInd(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) default: // eLIM_AP_ROLE { PELOG1(limLog(pMac, LOG1, - FL("*** Received Deauthentication from staId=%d ***\n"), + FL("*** Received Deauthentication from staId=%d ***"), pMlmDeauthInd->aid);) } // Send SME_DEAUTH_IND after Polaris cleanup @@ -1450,13 +1450,13 @@ limProcessMlmDeauthCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if(pMsgBuf == NULL) { - PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n"));) + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) return; } pMlmDeauthCnf = (tLimMlmDeauthCnf *) pMsgBuf; if((psessionEntry = peFindSessionBySessionId(pMac,pMlmDeauthCnf->sessionId))==NULL) { - PELOGE(limLog(pMac, LOGE,FL("session does not exist for given session Id \n"));) + PELOGE(limLog(pMac, LOGE,FL("session does not exist for given session Id "));) return; } @@ -1478,7 +1478,7 @@ limProcessMlmDeauthCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * Log error */ PELOGE(limLog(pMac, LOGE, - FL("received unexpected MLM_DEAUTH_CNF in state %X\n"), + FL("received unexpected MLM_DEAUTH_CNF in state %X"), psessionEntry->limSmeState);) return; } @@ -1486,7 +1486,7 @@ limProcessMlmDeauthCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) { psessionEntry->limSmeState = eLIM_SME_IDLE_STATE; PELOG1(limLog(pMac, LOG1, - FL("*** Deauthenticated with BSS ***\n"));) + FL("*** Deauthenticated with BSS ***"));) } else psessionEntry->limSmeState = psessionEntry->limPrevSmeState; @@ -1528,13 +1528,13 @@ limProcessMlmPurgeStaInd(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) tpPESession psessionEntry; if(pMsgBuf == NULL) { - PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n"));) + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) return; } pMlmPurgeStaInd = (tpLimMlmPurgeStaInd) pMsgBuf; if((psessionEntry = peFindSessionBySessionId(pMac,pMlmPurgeStaInd->sessionId))==NULL) { - PELOGE(limLog(pMac, LOGE,FL("session does not exist for given bssId\n"));) + PELOGE(limLog(pMac, LOGE,FL("session does not exist for given bssId"));) return; } // Purge STA indication from MLM @@ -1558,12 +1558,12 @@ limProcessMlmPurgeStaInd(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * Log error */ PELOGE(limLog(pMac, LOGE, - FL("received unexpected MLM_PURGE_STA_IND in state %X\n"), + FL("received unexpected MLM_PURGE_STA_IND in state %X"), psessionEntry->limSmeState);) break; } PELOG1(limLog(pMac, LOG1, - FL("*** Polaris cleanup completed for staId=%d ***\n"), + FL("*** Polaris cleanup completed for staId=%d ***"), pMlmPurgeStaInd->aid);) if ((psessionEntry->limSystemRole == eLIM_STA_ROLE)||(psessionEntry->limSystemRole == eLIM_BT_AMP_STA_ROLE)) { @@ -1615,17 +1615,17 @@ limProcessMlmSetKeysCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if(pMsgBuf == NULL) { - PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n"));) + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) return; } pMlmSetKeysCnf = (tLimMlmSetKeysCnf *) pMsgBuf; if ((psessionEntry = peFindSessionBySessionId(pMac, pMlmSetKeysCnf->sessionId))== NULL) { - PELOGE(limLog(pMac, LOGE,FL("session does not exist for given sessionId \n"));) + PELOGE(limLog(pMac, LOGE,FL("session does not exist for given sessionId "));) return; } limLog( pMac, LOG1, - FL("Received MLM_SETKEYS_CNF with resultCode = %d\n"), + FL("Received MLM_SETKEYS_CNF with resultCode = %d"), pMlmSetKeysCnf->resultCode ); limSendSmeSetContextRsp(pMac, pMlmSetKeysCnf->peerMacAddr, @@ -1660,17 +1660,17 @@ limProcessMlmRemoveKeyCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if(pMsgBuf == NULL) { - PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n"));) + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) return; } pMlmRemoveKeyCnf = (tLimMlmRemoveKeyCnf *) pMsgBuf; if((psessionEntry = peFindSessionBySessionId(pMac,pMlmRemoveKeyCnf->sessionId))== NULL) { - PELOGE(limLog(pMac, LOGE,FL("session Does not exist for given session Id\n"));) + PELOGE(limLog(pMac, LOGE,FL("session Does not exist for given session Id"));) return; } limLog( pMac, LOG1, - FL("Received MLM_REMOVEKEYS_CNF with resultCode = %d\n"), + FL("Received MLM_REMOVEKEYS_CNF with resultCode = %d"), pMlmRemoveKeyCnf->resultCode ); limSendSmeRemoveKeyRsp(pMac, pMlmRemoveKeyCnf->peerMacAddr, @@ -1710,7 +1710,7 @@ limHandleSmeJoinResult(tpAniSirGlobal pMac, tSirResultCodes resultCode, tANI_U16 /* Newly Added on oct 11 th*/ if(psessionEntry == NULL) { - PELOGE(limLog(pMac, LOGE,FL("psessionEntry is NULL \n"));) + PELOGE(limLog(pMac, LOGE,FL("psessionEntry is NULL "));) return; } smesessionId = psessionEntry->smeSessionId; @@ -1742,7 +1742,7 @@ limHandleSmeJoinResult(tpAniSirGlobal pMac, tSirResultCodes resultCode, tANI_U16 { if(limSetLinkState(pMac, eSIR_LINK_IDLE_STATE,psessionEntry->bssId, psessionEntry->selfMacAddr, NULL, NULL) != eSIR_SUCCESS) - PELOGE(limLog(pMac, LOGE, FL("Failed to set the LinkState.\n"));) + PELOGE(limLog(pMac, LOGE, FL("Failed to set the LinkState."));) peDeleteSession(pMac,psessionEntry); psessionEntry = NULL; } @@ -1780,7 +1780,7 @@ limHandleSmeReaasocResult(tpAniSirGlobal pMac, tSirResultCodes resultCode, tANI_ if(psessionEntry == NULL) { - PELOGE(limLog(pMac, LOGE,FL("psessionEntry is NULL \n"));) + PELOGE(limLog(pMac, LOGE,FL("psessionEntry is NULL "));) return; } smesessionId = psessionEntry->smeSessionId; @@ -1855,7 +1855,7 @@ void limProcessStaMlmAddStaRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ,tpPESess if(NULL == pAddStaParams ) { - limLog( pMac, LOGE, FL( "Encountered NULL Pointer\n" )); + limLog( pMac, LOGE, FL( "Encountered NULL Pointer" )); return; } if( eHAL_STATUS_SUCCESS == pAddStaParams->status ) @@ -1864,7 +1864,7 @@ void limProcessStaMlmAddStaRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ,tpPESess { //TODO: any response to be sent out here ? limLog( pMac, LOGE, - FL( "Received unexpected WDA_ADD_STA_RSP in state %X\n" ), + FL( "Received unexpected WDA_ADD_STA_RSP in state %X" ), psessionEntry->limMlmState); mlmAssocCnf.resultCode = (tSirResultCodes) eSIR_SME_REFUSED; goto end; @@ -1880,7 +1880,7 @@ void limProcessStaMlmAddStaRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ,tpPESess pStaDs->mlmStaContext.mlmState = eLIM_MLM_LINK_ESTABLISHED_STATE; else limLog( pMac, LOGW, - FL( "Unable to get the DPH Hash Entry for AID - %d\n" ), + FL( "Unable to get the DPH Hash Entry for AID - %d" ), DPH_STA_HASH_INDEX_PEER); psessionEntry->limMlmState = eLIM_MLM_LINK_ESTABLISHED_STATE; MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, psessionEntry->limMlmState)); @@ -1903,9 +1903,13 @@ void limProcessStaMlmAddStaRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ,tpPESess //assign the sessionId to the timer Object pMac->lim.limTimers.gLimKeepaliveTimer.sessionId = psessionEntry->peSessionId; if (tx_timer_activate(&pMac->lim.limTimers.gLimKeepaliveTimer) != TX_SUCCESS) - limLog(pMac, LOGP, FL("Cannot activate keepalive timer.\n")); + limLog(pMac, LOGP, FL("Cannot activate keepalive timer.")); #ifdef WLAN_DEBUG pMac->lim.gLimNumLinkEsts++; +#endif +#ifdef FEATURE_WLAN_TDLS + /* initialize TDLS peer related data */ + limInitTdlsData(pMac,psessionEntry); #endif // Return Assoc confirm to SME with success // FIXME_GEN4 - Need the correct ASSOC RSP code to @@ -1937,7 +1941,7 @@ void limProcessMlmDelBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,tpPESession // tpDeleteBssParams pDeleteBssParams =( tpDeleteBssParams)limMsgQ->bodyptr; // if((psessionEntry = peFindSessionBySessionId(pMac,pDeleteBssParams->sessionId)) == NULL) // { - // limLog( pMac, LOGE, FL( "Session deos not exist with given sessionId\n" )); + // limLog( pMac, LOGE, FL( "Session deos not exist with given sessionId" )); // return; // } SET_LIM_PROCESS_DEFD_MESGS(pMac, true); @@ -1957,18 +1961,6 @@ void limProcessMlmDelBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,tpPESession { WDA_TrafficStatsTimerActivate(FALSE); } - -#ifdef WLAN_FEATURE_11W - if (psessionEntry->limRmfEnabled) - { - if ( eSIR_SUCCESS != limSendExcludeUnencryptInd(pMac, TRUE, psessionEntry) ) - { - limLog( pMac, LOGE, - FL( "Could not send down Exclude Unencrypted Indication!" ), - psessionEntry->limMlmState ); - } - } -#endif } void limProcessStaMlmDelBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,tpPESession psessionEntry) @@ -1979,30 +1971,30 @@ void limProcessStaMlmDelBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,tpPESessi if (NULL == pDelBssParams) { - limLog( pMac, LOGE, FL( "Invalid body pointer in message\n")); + limLog( pMac, LOGE, FL( "Invalid body pointer in message")); goto end; } if( eHAL_STATUS_SUCCESS == pDelBssParams->status ) { PELOGW(limLog( pMac, LOGW, - FL( "STA received the DEL_BSS_RSP for BSSID: %X.\n"),pDelBssParams->bssIdx);) + FL( "STA received the DEL_BSS_RSP for BSSID: %X."),pDelBssParams->bssIdx);) if (limSetLinkState(pMac, eSIR_LINK_IDLE_STATE, psessionEntry->bssId, psessionEntry->selfMacAddr, NULL, NULL) != eSIR_SUCCESS) { - PELOGE(limLog( pMac, LOGE, FL( "Failure in setting link state to IDLE\n"));) + PELOGE(limLog( pMac, LOGE, FL( "Failure in setting link state to IDLE"));) statusCode = eSIR_SME_REFUSED; goto end; } if(pStaDs == NULL) { - limLog( pMac, LOGE, FL( "DPH Entry for STA 1 missing.\n")); + limLog( pMac, LOGE, FL( "DPH Entry for STA 1 missing.")); statusCode = eSIR_SME_REFUSED; goto end; } if( eLIM_MLM_WT_DEL_BSS_RSP_STATE != pStaDs->mlmStaContext.mlmState) { - PELOGE(limLog( pMac, LOGE, FL( "Received unexpected WDA_DEL_BSS_RSP in state %X\n" ), + PELOGE(limLog( pMac, LOGE, FL( "Received unexpected WDA_DEL_BSS_RSP in state %X" ), pStaDs->mlmStaContext.mlmState);) statusCode = eSIR_SME_REFUSED; goto end; @@ -2048,7 +2040,7 @@ void limProcessBtAmpApMlmDelBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,tpPES if(psessionEntry == NULL) { - limLog(pMac, LOGE,FL("Session entry passed is NULL\n")); + limLog(pMac, LOGE,FL("Session entry passed is NULL")); if(pDelBss != NULL) palFreeMemory( pMac->hHdd, (void *) pDelBss ); return; @@ -2056,7 +2048,7 @@ void limProcessBtAmpApMlmDelBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,tpPES if (pDelBss == NULL) { - PELOGE(limLog(pMac, LOGE, FL("BSS: DEL_BSS_RSP with no body!\n"));) + PELOGE(limLog(pMac, LOGE, FL("BSS: DEL_BSS_RSP with no body!"));) rc = eSIR_SME_REFUSED; goto end; } @@ -2122,7 +2114,7 @@ void limProcessMlmDelStaRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ) if(NULL == pDeleteStaParams || NULL == (psessionEntry = peFindSessionBySessionId(pMac, pDeleteStaParams->sessionId))) { - limLog(pMac, LOGP,FL("Session Does not exist or invalid body pointer in message\n")); + limLog(pMac, LOGP,FL("Session Does not exist or invalid body pointer in message")); if(pDeleteStaParams != NULL) palFreeMemory( pMac->hHdd, (void *) pDeleteStaParams ); return; @@ -2152,7 +2144,7 @@ void limProcessBtAmpApMlmDelStaRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,tpPES if(pStaDs == NULL) { limLog( pMac, LOGE, - FL( "DPH Entry for STA %X missing.\n"), pDelStaParams->assocId); + FL( "DPH Entry for STA %X missing."), pDelStaParams->assocId); statusCode = eSIR_SME_REFUSED; palFreeMemory( pMac->hHdd, (void *) pDelStaParams ); @@ -2161,13 +2153,13 @@ void limProcessBtAmpApMlmDelStaRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,tpPES if( eHAL_STATUS_SUCCESS == pDelStaParams->status ) { limLog( pMac, LOGW, - FL( "AP received the DEL_STA_RSP for assocID: %X.\n"), pDelStaParams->assocId); + FL( "AP received the DEL_STA_RSP for assocID: %X."), pDelStaParams->assocId); if(( eLIM_MLM_WT_DEL_STA_RSP_STATE != pStaDs->mlmStaContext.mlmState) && ( eLIM_MLM_WT_ASSOC_DEL_STA_RSP_STATE != pStaDs->mlmStaContext.mlmState)) { limLog( pMac, LOGE, - FL( "Received unexpected WDA_DEL_STA_RSP in state %s for staId %d assocId %d \n" ), + FL( "Received unexpected WDA_DEL_STA_RSP in state %s for staId %d assocId %d " ), limMlmStateStr(pStaDs->mlmStaContext.mlmState), pStaDs->staIndex, pStaDs->assocId); statusCode = eSIR_SME_REFUSED; goto end; @@ -2183,7 +2175,7 @@ void limProcessBtAmpApMlmDelStaRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,tpPES if (limAddSta(pMac, pStaDs, false, psessionEntry) != eSIR_SUCCESS) { PELOGE(limLog(pMac, LOGE, - FL("could not Add STA with assocId=%d\n"), + FL("could not Add STA with assocId=%d"), pStaDs->assocId);) // delete the TS if it has already been added. // send the response with error status. @@ -2211,7 +2203,7 @@ void limProcessBtAmpApMlmDelStaRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,tpPES else { limLog( pMac, LOGW, - FL( "DEL STA failed!\n" )); + FL( "DEL STA failed!" )); statusCode = eSIR_SME_REFUSED; } end: @@ -2230,7 +2222,7 @@ void limProcessStaMlmDelStaRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,tpPESessi tpDphHashNode pStaDs = NULL; if(NULL == pDelStaParams ) { - limLog( pMac, LOGE, FL( "Encountered NULL Pointer\n" )); + limLog( pMac, LOGE, FL( "Encountered NULL Pointer" )); goto end; } if( eHAL_STATUS_SUCCESS == pDelStaParams->status ) @@ -2239,7 +2231,7 @@ void limProcessStaMlmDelStaRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,tpPESessi if (pStaDs == NULL) { //TODO: any response to be sent out here ? - limLog( pMac, LOGE, FL( "DPH Entry for STA %X missing.\n"), + limLog( pMac, LOGE, FL( "DPH Entry for STA %X missing."), pDelStaParams->assocId); statusCode = eSIR_SME_REFUSED; goto end; @@ -2247,14 +2239,14 @@ void limProcessStaMlmDelStaRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,tpPESessi if( eLIM_MLM_WT_DEL_STA_RSP_STATE != psessionEntry->limMlmState) { //TODO: any response to be sent out here ? - limLog( pMac, LOGE, FL( "Received unexpected WDA_DELETE_STA_RSP in state %s\n" ), + limLog( pMac, LOGE, FL( "Received unexpected WDA_DELETE_STA_RSP in state %s" ), limMlmStateStr(psessionEntry->limMlmState)); statusCode = eSIR_SME_REFUSED; goto end; } PELOG1(limLog( pMac, LOG1, FL("STA AssocID %d MAC "), pStaDs->assocId ); limPrintMacAddr(pMac, pStaDs->staAddr, LOG1);) - limLog( pMac, LOGW, FL( "DEL_STA_RSP received for assocID: %X\n"), pDelStaParams->assocId); + limLog( pMac, LOGW, FL( "DEL_STA_RSP received for assocID: %X"), pDelStaParams->assocId); //we must complete all cleanup related to delSta before calling limDelBSS. if( 0 != limMsgQ->bodyptr ) { @@ -2265,7 +2257,7 @@ void limProcessStaMlmDelStaRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,tpPESessi } else { - limLog( pMac, LOGE, FL( "DEL_STA failed for sta Id %d\n" ), pStaDs->staIndex); + limLog( pMac, LOGE, FL( "DEL_STA failed for sta Id %d" ), pDelStaParams->staIdx); statusCode = eSIR_SME_REFUSED; } end: @@ -2283,7 +2275,7 @@ void limProcessBtAmpApMlmAddStaRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,tpPES if (NULL == pAddStaParams) { - limLog( pMac, LOGE, FL( "Invalid body pointer in message\n")); + limLog( pMac, LOGE, FL( "Invalid body pointer in message")); goto end; } @@ -2291,7 +2283,7 @@ void limProcessBtAmpApMlmAddStaRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,tpPES if(pStaDs == NULL) { //TODO: any response to be sent out here ? - limLog( pMac, LOGE, FL( "DPH Entry for STA %X missing.\n"), pAddStaParams->assocId); + limLog( pMac, LOGE, FL( "DPH Entry for STA %X missing."), pAddStaParams->assocId); goto end; } // @@ -2303,13 +2295,13 @@ void limProcessBtAmpApMlmAddStaRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,tpPES { //TODO: any response to be sent out here ? limLog( pMac, LOGE, - FL( "Received unexpected WDA_ADD_STA_RSP in state %X\n" ), + FL( "Received unexpected WDA_ADD_STA_RSP in state %X" ), pStaDs->mlmStaContext.mlmState); goto end; } if(eHAL_STATUS_SUCCESS != pAddStaParams->status) { - PELOGE(limLog(pMac, LOGE, FL("Error! rcvd delSta rsp from HAL with status %d\n"),pAddStaParams->status);) + PELOGE(limLog(pMac, LOGE, FL("Error! rcvd delSta rsp from HAL with status %d"),pAddStaParams->status);) limRejectAssociation(pMac, pStaDs->staAddr, pStaDs->mlmStaContext.subType, true, pStaDs->mlmStaContext.authType, @@ -2387,13 +2379,13 @@ limProcessApMlmAddBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ) tpAddBssParams pAddBssParams = (tpAddBssParams) limMsgQ->bodyptr; if(NULL == pAddBssParams ) { - limLog( pMac, LOGE, FL( "Encountered NULL Pointer\n" )); + limLog( pMac, LOGE, FL( "Encountered NULL Pointer" )); goto end; } //TBD: free the memory before returning, do it for all places where lookup fails. if((psessionEntry = peFindSessionBySessionId(pMac,pAddBssParams->sessionId))== NULL) { - PELOGE(limLog(pMac, LOGE,FL("session does not exist for given sessionId\n"));) + PELOGE(limLog(pMac, LOGE,FL("session does not exist for given sessionId"));) if( NULL != pAddBssParams ) palFreeMemory( pMac->hHdd, (void *) pAddBssParams ); return; @@ -2402,7 +2394,7 @@ limProcessApMlmAddBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ) mlmStartCnf.sessionId = pAddBssParams->sessionId; if( eHAL_STATUS_SUCCESS == pAddBssParams->status ) { - PELOG2(limLog(pMac, LOG2, FL("WDA_ADD_BSS_RSP returned with eHAL_STATUS_SUCCESS\n"));) + PELOG2(limLog(pMac, LOG2, FL("WDA_ADD_BSS_RSP returned with eHAL_STATUS_SUCCESS"));) if (limSetLinkState(pMac, eSIR_LINK_AP_STATE,psessionEntry->bssId, psessionEntry->selfMacAddr, NULL, NULL) != eSIR_SUCCESS ) goto end; @@ -2421,7 +2413,7 @@ limProcessApMlmAddBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ) limHeartBeatDeactivateAndChangeTimer(pMac, psessionEntry); MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, psessionEntry->peSessionId, eLIM_HEART_BEAT_TIMER)); if (limActivateHearBeatTimer(pMac) != TX_SUCCESS) - limLog(pMac, LOGP, FL("could not activate Heartbeat timer\n")); + limLog(pMac, LOGP, FL("could not activate Heartbeat timer")); } psessionEntry->bssIdx = (tANI_U8) pAddBssParams->bssIdx; @@ -2441,12 +2433,12 @@ limProcessApMlmAddBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ) // Start OLBC timer if (tx_timer_activate(&pMac->lim.limTimers.gLimUpdateOlbcCacheTimer) != TX_SUCCESS) { - limLog(pMac, LOGE, FL("tx_timer_activate failed\n")); + limLog(pMac, LOGE, FL("tx_timer_activate failed")); } /* Update the lim global gLimTriggerBackgroundScanDuringQuietBss */ if( eSIR_SUCCESS != wlan_cfgGetInt( pMac, WNI_CFG_TRIG_STA_BK_SCAN, &val )) - limLog( pMac, LOGP, FL("Failed to get WNI_CFG_TRIG_STA_BK_SCAN!\n")); + limLog( pMac, LOGP, FL("Failed to get WNI_CFG_TRIG_STA_BK_SCAN!")); pMac->lim.gLimTriggerBackgroundScanDuringQuietBss = (val) ? 1 : 0; // Apply previously set configuration at HW limApplyConfiguration(pMac,psessionEntry); @@ -2455,7 +2447,7 @@ limProcessApMlmAddBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ) } else { - limLog( pMac, LOGE, FL( "WDA_ADD_BSS_REQ failed with status %d\n" ),pAddBssParams->status ); + limLog( pMac, LOGE, FL( "WDA_ADD_BSS_REQ failed with status %d" ),pAddBssParams->status ); mlmStartCnf.resultCode = eSIR_SME_HAL_SEND_MESSAGE_FAIL; } limPostSmeMessage( pMac, LIM_MLM_START_CNF, (tANI_U32 *) &mlmStartCnf ); @@ -2507,12 +2499,12 @@ limProcessIbssMlmAddBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ,tpPESession if (NULL == pAddBssParams) { - limLog( pMac, LOGE, FL( "Invalid body pointer in message\n")); + limLog( pMac, LOGE, FL( "Invalid body pointer in message")); goto end; } if( eHAL_STATUS_SUCCESS == pAddBssParams->status ) { - PELOG1(limLog(pMac, LOG1, FL("WDA_ADD_BSS_RSP returned with eHAL_STATUS_SUCCESS\n"));) + PELOG1(limLog(pMac, LOG1, FL("WDA_ADD_BSS_RSP returned with eHAL_STATUS_SUCCESS"));) if (limSetLinkState(pMac, eSIR_LINK_IBSS_STATE,psessionEntry->bssId, psessionEntry->selfMacAddr, NULL, NULL) != eSIR_SUCCESS ) goto end; @@ -2529,7 +2521,7 @@ limProcessIbssMlmAddBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ,tpPESession limHeartBeatDeactivateAndChangeTimer(pMac, psessionEntry); MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, psessionEntry->peSessionId, eLIM_HEART_BEAT_TIMER)); if (limActivateHearBeatTimer(pMac) != TX_SUCCESS) - limLog(pMac, LOGP, FL("could not activate Heartbeat timer\n")); + limLog(pMac, LOGP, FL("could not activate Heartbeat timer")); psessionEntry->bssIdx = (tANI_U8) pAddBssParams->bssIdx; psessionEntry->limSystemRole = eLIM_STA_IN_IBSS_ROLE; psessionEntry->statypeForBss = STA_ENTRY_SELF; @@ -2544,7 +2536,7 @@ limProcessIbssMlmAddBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ,tpPESession #endif /* Update the lim global gLimTriggerBackgroundScanDuringQuietBss */ if( eSIR_SUCCESS != wlan_cfgGetInt( pMac, WNI_CFG_TRIG_STA_BK_SCAN, &val )) - limLog( pMac, LOGP, FL("Failed to get WNI_CFG_TRIG_STA_BK_SCAN!\n")); + limLog( pMac, LOGP, FL("Failed to get WNI_CFG_TRIG_STA_BK_SCAN!")); pMac->lim.gLimTriggerBackgroundScanDuringQuietBss = (val) ? 1 : 0; // Apply previously set configuration at HW limApplyConfiguration(pMac,psessionEntry); @@ -2559,7 +2551,7 @@ limProcessIbssMlmAddBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ,tpPESession } else { - limLog( pMac, LOGE, FL( "WDA_ADD_BSS_REQ failed with status %d\n" ), + limLog( pMac, LOGE, FL( "WDA_ADD_BSS_REQ failed with status %d" ), pAddBssParams->status ); mlmStartCnf.resultCode = eSIR_SME_HAL_SEND_MESSAGE_FAIL; } @@ -2583,7 +2575,7 @@ limProcessStaMlmAddBssRspPreAssoc( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ, tpPES if (NULL == pAddBssParams) { - limLog( pMac, LOGE, FL( "Invalid body pointer in message\n")); + limLog( pMac, LOGE, FL( "Invalid body pointer in message")); goto joinFailure; } if( eHAL_STATUS_SUCCESS == pAddBssParams->status ) @@ -2591,7 +2583,7 @@ limProcessStaMlmAddBssRspPreAssoc( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ, tpPES if ((pStaDs = dphAddHashEntry(pMac, pAddBssParams->staContext.staMac, DPH_STA_HASH_INDEX_PEER, &psessionEntry->dph.dphHashTable)) == NULL) { // Could not add hash table entry - PELOGE(limLog(pMac, LOGE, FL("could not add hash entry at DPH for \n"));) + PELOGE(limLog(pMac, LOGE, FL("could not add hash entry at DPH for "));) limPrintMacAddr(pMac, pAddBssParams->staContext.staMac, LOGE); goto joinFailure; } @@ -2609,7 +2601,7 @@ limProcessStaMlmAddBssRspPreAssoc( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ, tpPES * Log error. */ limLog(pMac, LOGP, - FL("could not retrieve AuthType\n")); + FL("could not retrieve AuthType")); } if (cfgAuthType == eSIR_AUTO_SWITCH) authMode = eSIR_OPEN_SYSTEM; // Try Open Authentication first @@ -2621,7 +2613,7 @@ limProcessStaMlmAddBssRspPreAssoc( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ, tpPES { // Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for mlmAuthReq\n")); + FL("call to palAllocateMemory failed for mlmAuthReq")); return; } #if 0 @@ -2631,7 +2623,7 @@ limProcessStaMlmAddBssRspPreAssoc( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ, tpPES &val) != eSIR_SUCCESS) { /// Could not get BSSID from CFG. Log error. - limLog(pMac, LOGP, FL("could not retrieve BSSID\n")); + limLog(pMac, LOGP, FL("could not retrieve BSSID")); } #endif //TO SUPPORT BT-AMP sirCopyMacAddr(pMlmAuthReq->peerMacAddr,psessionEntry->bssId); @@ -2646,7 +2638,7 @@ limProcessStaMlmAddBssRspPreAssoc( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ, tpPES * value from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve AuthFailureTimeout value\n")); + FL("could not retrieve AuthFailureTimeout value")); } // SUNIT_FIX_ME: Set BOTH? Assume not. Please verify here and below. //pMac->lim.gLimMlmState = eLIM_MLM_JOINED_STATE; @@ -2699,7 +2691,7 @@ void limSetLinkStateForPostAssocCallback(tpAniSirGlobal pMac, void *msgParam ) /* Sanity Checks */ if (pCbackParams == NULL) { - PELOGE(limLog(pMac, LOGE, FL("Invalid parameters\n"));) + PELOGE(limLog(pMac, LOGE, FL("Invalid parameters"));) goto end; } @@ -2707,15 +2699,13 @@ void limSetLinkStateForPostAssocCallback(tpAniSirGlobal pMac, void *msgParam ) if (pAddBssParams == NULL) { - PELOGE(limLog(pMac, LOGE, FL("Invalid parameters\n"));) + PELOGE(limLog(pMac, LOGE, FL("Invalid parameters"));) goto end; } if((psessionEntry = peFindSessionBySessionId(pMac,pAddBssParams->sessionId))== NULL) { - limLog( pMac, LOGE, FL( "Session Does not exist for given sessionId\n" )); - if( NULL != pAddBssParams ) - palFreeMemory( pMac->hHdd, (void *) pAddBssParams ); + limLog( pMac, LOGE, FL( "Session Does not exist for given sessionId" )); goto end; } @@ -2727,7 +2717,7 @@ void limSetLinkStateForPostAssocCallback(tpAniSirGlobal pMac, void *msgParam ) &psessionEntry->dph.dphHashTable)) == NULL) { // Could not add hash table entry - PELOGE(limLog(pMac, LOGE, FL("could not add hash entry at DPH for \n"));) + PELOGE(limLog(pMac, LOGE, FL("could not add hash entry at DPH for "));) limPrintMacAddr(pMac, pAddBssParams->staContext.staMac, LOGE); goto end; } @@ -2742,7 +2732,7 @@ void limSetLinkStateForPostAssocCallback(tpAniSirGlobal pMac, void *msgParam ) /// Could not start reassoc failure timer. // Log error limLog(pMac, LOGP, - FL("could not start Reassociation failure timer\n")); + FL("could not start Reassociation failure timer")); // Return Reassoc confirm with // Resources Unavailable mlmReassocCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE; @@ -2784,8 +2774,8 @@ void limSetLinkStateForPostAssocCallback(tpAniSirGlobal pMac, void *msgParam ) if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **) &pAddStaParams, sizeof( tAddStaParams ))) { - limLog( pMac, LOGP, FL( "Unable to PAL allocate memory during ADD_STA\n" )); - return; + limLog( pMac, LOGP, FL( "Unable to PAL allocate memory during ADD_STA" )); + goto end; } palZeroMemory( pMac->hHdd, (tANI_U8 *) pAddStaParams, sizeof(tAddStaParams)); @@ -2850,7 +2840,7 @@ void limSetLinkStateForPostAssocCallback(tpAniSirGlobal pMac, void *msgParam ) } if (wlan_cfgGetInt(pMac, WNI_CFG_LISTEN_INTERVAL, &listenInterval) != eSIR_SUCCESS) - limLog(pMac, LOGP, FL("Couldn't get LISTEN_INTERVAL\n")); + limLog(pMac, LOGP, FL("Couldn't get LISTEN_INTERVAL")); pAddStaParams->listenInterval = (tANI_U16)listenInterval; limFillSupportedRatesInfo(pMac, NULL, &pAddStaParams->supportedRates,psessionEntry); @@ -2889,6 +2879,8 @@ void limSetLinkStateForPostAssocCallback(tpAniSirGlobal pMac, void *msgParam ) /* Update PE session Id*/ if (psessionEntry != NULL) mlmReassocCnf.sessionId = psessionEntry->peSessionId; + else + mlmReassocCnf.sessionId = 0; limPostSmeMessage(pMac, LIM_MLM_REASSOC_CNF, (tANI_U32 *) &mlmReassocCnf); } @@ -2914,13 +2906,13 @@ limProcessStaMlmAddBssRspFT(tpAniSirGlobal pMac, tpSirMsgQ limMsgQ, tpPESession if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **) &pCbackParam, sizeof( tSetLinkCbackParams ))) { - PELOGE(limLog(pMac, LOGE, FL("Could not allocate memory for LinkState callback params\n"));) + PELOGE(limLog(pMac, LOGE, FL("Could not allocate memory for LinkState callback params"));) goto end; } if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **) &pAddBssCbackInfo, sizeof( tAddBssParams ))) { - PELOGE(limLog(pMac, LOGE, FL("Could not allocate memory for Add BSS info callback param\n"));) + PELOGE(limLog(pMac, LOGE, FL("Could not allocate memory for Add BSS info callback param"));) goto end; } @@ -2934,7 +2926,7 @@ limProcessStaMlmAddBssRspFT(tpAniSirGlobal pMac, tpSirMsgQ limMsgQ, tpPESession (tpSetLinkStateCallback)limSetLinkStateForPostAssocCallback, (void *)pCbackParam) != eSIR_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("Failed to set the LinkState\n"));) + PELOGE(limLog(pMac, LOGE, FL("Failed to set the LinkState"));) goto end; } @@ -3042,11 +3034,11 @@ limProcessStaMlmAddBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,tpPESession ps MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, psessionEntry->limMlmState)); psessionEntry->statypeForBss = STA_ENTRY_PEER; //to know the session started for self or for peer oct6th // Now, send WDA_ADD_STA_REQ - limLog( pMac, LOGW, FL( "On STA: ADD_BSS was successful\n" )); + limLog( pMac, LOGW, FL( "On STA: ADD_BSS was successful" )); pStaDs = dphGetHashEntry(pMac, DPH_STA_HASH_INDEX_PEER, &psessionEntry->dph.dphHashTable); if (pStaDs == NULL) { - PELOGE(limLog(pMac, LOGE, FL("could not Add Self Entry for the station\n"));) + PELOGE(limLog(pMac, LOGE, FL("could not Add Self Entry for the station"));) mlmAssocCnf.resultCode = (tSirResultCodes) eSIR_SME_REFUSED; } else @@ -3075,20 +3067,14 @@ limProcessStaMlmAddBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,tpPESession ps if (limAddStaSelf(pMac,staIdx, updateSta, psessionEntry) != eSIR_SUCCESS) { // Add STA context at HW - PELOGE(limLog(pMac, LOGE, FL("could not Add Self Entry for the station\n"));) + PELOGE(limLog(pMac, LOGE, FL("could not Add Self Entry for the station"));) mlmAssocCnf.resultCode = (tSirResultCodes) eSIR_SME_REFUSED; } -#ifdef FEATURE_WLAN_TDLS - else { - /* initialize TDLS peer related data */ - limInitTdlsData(pMac,psessionEntry); - } -#endif } } else { - limLog( pMac, LOGP, FL( "ADD_BSS failed!\n" )); + limLog( pMac, LOGP, FL( "ADD_BSS failed!" )); // Return Assoc confirm to SME with failure mlmAssocCnf.resultCode = (tSirResultCodes) eSIR_SME_REFUSED; } @@ -3140,7 +3126,7 @@ void limProcessMlmAddBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ) if(NULL == pAddBssParams ) { - limLog( pMac, LOGE, FL( "Encountered NULL Pointer\n" )); + limLog( pMac, LOGE, FL( "Encountered NULL Pointer" )); return; } @@ -3156,7 +3142,7 @@ void limProcessMlmAddBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ) // Validate MLME state if((psessionEntry = peFindSessionBySessionId(pMac,pAddBssParams->sessionId))== NULL) { - limLog( pMac, LOGE, FL( "Session Does not exist for given sessionId\n" )); + limLog( pMac, LOGE, FL( "Session Does not exist for given sessionId" )); if( NULL != pAddBssParams ) palFreeMemory( pMac->hHdd, (void *) pAddBssParams ); return; @@ -3173,7 +3159,7 @@ void limProcessMlmAddBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ) { // Mesg received from HAL in Invalid state! limLog( pMac, LOGE, - FL( "Received unexpected WDA_ADD_BSS_RSP in state %X\n" ), + FL( "Received unexpected WDA_ADD_BSS_RSP in state %X" ), psessionEntry->limMlmState ); mlmStartCnf.resultCode = eSIR_SME_BSS_ALREADY_STARTED_OR_JOINED; if( 0 != limMsgQ->bodyptr ) @@ -3196,18 +3182,6 @@ void limProcessMlmAddBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ) { WDA_TrafficStatsTimerActivate(TRUE); } - -#ifdef WLAN_FEATURE_11W - if (psessionEntry->limRmfEnabled) - { - if ( eSIR_SUCCESS != limSendExcludeUnencryptInd(pMac, FALSE, psessionEntry) ) - { - limLog( pMac, LOGE, - FL( "Could not send down Exclude Unencrypted Indication!" ), - psessionEntry->limMlmState ); - } - } -#endif } /** * limProcessMlmSetKeyRsp() @@ -3255,20 +3229,20 @@ void limProcessMlmSetStaKeyRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ) //BTAMP if( NULL == limMsgQ->bodyptr ) { - PELOGE(limLog(pMac, LOGE,FL("limMsgQ bodyptr is NULL\n"));) + PELOGE(limLog(pMac, LOGE,FL("limMsgQ bodyptr is NULL"));) return; } sessionId = ((tpSetStaKeyParams) limMsgQ->bodyptr)->sessionId; if((psessionEntry = peFindSessionBySessionId(pMac, sessionId))== NULL) { - PELOGE(limLog(pMac, LOGE,FL("session does not exist for given sessionId\n"));) + PELOGE(limLog(pMac, LOGE,FL("session does not exist for given sessionId"));) palFreeMemory( pMac->hHdd, (void *) limMsgQ->bodyptr ); return; } if( eLIM_MLM_WT_SET_STA_KEY_STATE != psessionEntry->limMlmState ) { // Mesg received from HAL in Invalid state! - limLog( pMac, LOGW, FL( "Received unexpected [Mesg Id - %d] in state %X\n" ), limMsgQ->type, psessionEntry->limMlmState ); + limLog( pMac, LOGW, FL( "Received unexpected [Mesg Id - %d] in state %X" ), limMsgQ->type, psessionEntry->limMlmState ); // There's not much that MLME can do at this stage... respReqd = 0; } @@ -3306,13 +3280,13 @@ void limProcessMlmSetBssKeyRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ) //BTAMP if( NULL == limMsgQ->bodyptr ) { - PELOGE(limLog(pMac, LOGE,FL("limMsgQ bodyptr is null\n"));) + PELOGE(limLog(pMac, LOGE,FL("limMsgQ bodyptr is null"));) return; } sessionId = ((tpSetBssKeyParams) limMsgQ->bodyptr)->sessionId; if((psessionEntry = peFindSessionBySessionId(pMac, sessionId))== NULL) { - PELOGE(limLog(pMac, LOGE,FL("session does not exist for given sessionId\n"));) + PELOGE(limLog(pMac, LOGE,FL("session does not exist for given sessionId"));) palFreeMemory( pMac->hHdd, (void *) limMsgQ->bodyptr ); return; } @@ -3333,7 +3307,7 @@ void limProcessMlmSetBssKeyRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ) eLIM_MLM_WT_SET_STA_BCASTKEY_STATE != psessionEntry->limMlmState ) { // Mesg received from HAL in Invalid state! - limLog( pMac, LOGW, FL( "Received unexpected [Mesg Id - %d] in state %X\n" ), limMsgQ->type, psessionEntry->limMlmState ); + limLog( pMac, LOGW, FL( "Received unexpected [Mesg Id - %d] in state %X" ), limMsgQ->type, psessionEntry->limMlmState ); // There's not much that MLME can do at this stage... respReqd = 0; } @@ -3389,7 +3363,7 @@ void limProcessMlmRemoveKeyRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ) if( NULL == limMsgQ->bodyptr ) { - PELOGE(limLog(pMac, LOGE,FL("limMsgQ bodyptr is NULL\n"));) + PELOGE(limLog(pMac, LOGE,FL("limMsgQ bodyptr is NULL"));) return; } @@ -3400,7 +3374,7 @@ void limProcessMlmRemoveKeyRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ) if((psessionEntry = peFindSessionBySessionId(pMac, sessionId))== NULL) { - PELOGE(limLog(pMac, LOGE,FL("session does not exist for given sessionId\n"));) + PELOGE(limLog(pMac, LOGE,FL("session does not exist for given sessionId"));) return; } @@ -3415,7 +3389,7 @@ void limProcessMlmRemoveKeyRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ) { // Mesg received from HAL in Invalid state! limLog(pMac, LOGW, - FL("Received unexpected [Mesg Id - %d] in state %X\n"), + FL("Received unexpected [Mesg Id - %d] in state %X"), limMsgQ->type, psessionEntry->limMlmState ); respReqd = 0; @@ -3475,7 +3449,7 @@ void limProcessInitScanRsp(tpAniSirGlobal pMac, void *body) if( pMac->lim.abortScan && (eLIM_HAL_INIT_SCAN_WAIT_STATE == pMac->lim.gLimHalScanState) ) { - limLog( pMac, LOGW, FL(" finish scan\n") ); + limLog( pMac, LOGW, FL(" finish scan") ); pMac->lim.abortScan = 0; limDeactivateAndChangeTimer(pMac, eLIM_MIN_CHANNEL_TIMER); limDeactivateAndChangeTimer(pMac, eLIM_MAX_CHANNEL_TIMER); @@ -3489,7 +3463,7 @@ void limProcessInitScanRsp(tpAniSirGlobal pMac, void *body) case eLIM_HAL_INIT_SCAN_WAIT_STATE: if (status != (tANI_U32) eHAL_STATUS_SUCCESS) { - PELOGW(limLog(pMac, LOGW, FL("InitScanRsp with failed status= %d\n"), status);) + PELOGW(limLog(pMac, LOGW, FL("InitScanRsp with failed status= %d"), status);) pMac->lim.gLimHalScanState = eLIM_HAL_IDLE_SCAN_STATE; pMac->lim.gLimNumOfConsecutiveBkgndScanFailure += 1; /* @@ -3527,13 +3501,13 @@ void limProcessInitScanRsp(tpAniSirGlobal pMac, void *body) } else { - limLog( pMac, LOGP, "No suspend link callback set but station is in suspend state\n"); + limLog( pMac, LOGP, "No suspend link callback set but station is in suspend state"); return; } break; //end WLAN_SUSPEND_LINK Related default: - limLog(pMac, LOGW, FL("limProcessInitScanRsp: Rcvd InitScanRsp not in WAIT State, state %d\n"), + limLog(pMac, LOGW, FL("limProcessInitScanRsp: Rcvd InitScanRsp not in WAIT State, state %d"), pMac->lim.gLimHalScanState); break; } @@ -3567,14 +3541,14 @@ static void limProcessSwitchChannelReAssocReq(tpAniSirGlobal pMac, tpPESession p pMlmReassocReq = (tLimMlmReassocReq *)(psessionEntry->pLimMlmReassocReq); if(pMlmReassocReq == NULL) { - limLog(pMac, LOGP, FL("pLimMlmReassocReq does not exist for given switchChanSession\n")); + limLog(pMac, LOGP, FL("pLimMlmReassocReq does not exist for given switchChanSession")); mlmReassocCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE; goto end; } if(status != eHAL_STATUS_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("Change channel failed!!\n"));) + PELOGE(limLog(pMac, LOGE, FL("Change channel failed!!"));) mlmReassocCnf.resultCode = eSIR_SME_CHANNEL_SWITCH_FAIL; goto end; } @@ -3586,7 +3560,7 @@ static void limProcessSwitchChannelReAssocReq(tpAniSirGlobal pMac, tpPESession p /// Could not start reassoc failure timer. // Log error limLog(pMac, LOGP, - FL("could not start Reassociation failure timer\n")); + FL("could not start Reassociation failure timer")); // Return Reassoc confirm with // Resources Unavailable mlmReassocCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE; @@ -3642,13 +3616,13 @@ static void limProcessSwitchChannelJoinReq(tpAniSirGlobal pMac, tpPESession pses tLimMlmJoinCnf mlmJoinCnf; if(status != eHAL_STATUS_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("Change channel failed!!\n"));) + PELOGE(limLog(pMac, LOGE, FL("Change channel failed!!"));) goto error; } if ( (NULL == psessionEntry ) || (NULL == psessionEntry->pLimMlmJoinReq) ) { - PELOGE(limLog(pMac, LOGE, FL("invalid pointer!!\n"));) + PELOGE(limLog(pMac, LOGE, FL("invalid pointer!!"));) goto error; } @@ -3663,7 +3637,7 @@ static void limProcessSwitchChannelJoinReq(tpAniSirGlobal pMac, tpPESession pses /* Update the lim global gLimTriggerBackgroundScanDuringQuietBss */ if(wlan_cfgGetInt(pMac, WNI_CFG_TRIG_STA_BK_SCAN, &val) != eSIR_SUCCESS) - limLog(pMac, LOGP, FL("failed to get WNI_CFG_TRIG_STA_BK_SCAN cfg value!\n")); + limLog(pMac, LOGP, FL("failed to get WNI_CFG_TRIG_STA_BK_SCAN cfg value!")); pMac->lim.gLimTriggerBackgroundScanDuringQuietBss = (val) ? 1 : 0; // Apply previously set configuration at HW limApplyConfiguration(pMac, psessionEntry); @@ -3687,7 +3661,7 @@ static void limProcessSwitchChannelJoinReq(tpAniSirGlobal pMac, tpPESession pses MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, psessionEntry->peSessionId, eLIM_JOIN_FAIL_TIMER)); if (tx_timer_activate(&pMac->lim.limTimers.gLimJoinFailureTimer) != TX_SUCCESS) { - limLog(pMac, LOGP, FL("could not activate Join failure timer\n")); + limLog(pMac, LOGP, FL("could not activate Join failure timer")); psessionEntry->limMlmState = psessionEntry->limPrevMlmState; MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, pMac->lim.gLimMlmState)); //memory is freed up below. @@ -3700,7 +3674,7 @@ static void limProcessSwitchChannelJoinReq(tpAniSirGlobal pMac, tpPESession pses // Activate Join Periodic Probe Req timer if (tx_timer_activate(&pMac->lim.limTimers.gLimPeriodicJoinProbeReqTimer) != TX_SUCCESS) { - limLog(pMac, LOGP, FL("could not activate Periodic Join req failure timer\n")); + limLog(pMac, LOGP, FL("could not activate Periodic Join req failure timer")); goto error; } } @@ -3758,7 +3732,7 @@ void limProcessSwitchChannelRsp(tpAniSirGlobal pMac, void *body) if((psessionEntry = peFindSessionBySessionId(pMac, peSessionId))== NULL) { palFreeMemory( pMac->hHdd, (tANI_U8 *)body); - limLog(pMac, LOGP, FL("session does not exist for given sessionId\n")); + limLog(pMac, LOGP, FL("session does not exist for given sessionId")); return; } #if defined WLAN_FEATURE_VOWIFI @@ -3788,7 +3762,7 @@ void limProcessSwitchChannelRsp(tpAniSirGlobal pMac, void *body) */ if (pMac->lim.gpchangeChannelCallback) { - PELOG1(limLog( pMac, LOG1, "Channel changed hence invoke registered call back\n");) + PELOG1(limLog( pMac, LOG1, "Channel changed hence invoke registered call back");) pMac->lim.gpchangeChannelCallback(pMac, status, pMac->lim.gpchangeChannelData, psessionEntry); } break; @@ -3834,7 +3808,7 @@ void limProcessStartScanRsp(tpAniSirGlobal pMac, void *body) palFreeMemory( pMac->hHdd, (tANI_U8 *)body); if( pMac->lim.abortScan ) { - limLog( pMac, LOGW, FL(" finish scan\n") ); + limLog( pMac, LOGW, FL(" finish scan") ); pMac->lim.abortScan = 0; limDeactivateAndChangeTimer(pMac, eLIM_MIN_CHANNEL_TIMER); limDeactivateAndChangeTimer(pMac, eLIM_MAX_CHANNEL_TIMER); @@ -3848,7 +3822,7 @@ void limProcessStartScanRsp(tpAniSirGlobal pMac, void *body) case eLIM_HAL_START_SCAN_WAIT_STATE: if (status != (tANI_U32) eHAL_STATUS_SUCCESS) { - PELOGW(limLog(pMac, LOGW, FL("StartScanRsp with failed status= %d\n"), status);) + PELOGW(limLog(pMac, LOGW, FL("StartScanRsp with failed status= %d"), status);) // // FIXME - With this, LIM will try and recover state, but // eWNI_SME_SCAN_CNF maybe reporting an incorrect @@ -3867,7 +3841,7 @@ void limProcessStartScanRsp(tpAniSirGlobal pMac, void *body) } break; default: - limLog(pMac, LOGW, FL("Rcvd StartScanRsp not in WAIT State, state %d\n"), + limLog(pMac, LOGW, FL("Rcvd StartScanRsp not in WAIT State, state %d"), pMac->lim.gLimHalScanState); break; } @@ -3886,7 +3860,7 @@ void limProcessEndScanRsp(tpAniSirGlobal pMac, void *body) case eLIM_HAL_END_SCAN_WAIT_STATE: if (status != (tANI_U32) eHAL_STATUS_SUCCESS) { - PELOGW(limLog(pMac, LOGW, FL("EndScanRsp with failed status= %d\n"), status);) + PELOGW(limLog(pMac, LOGW, FL("EndScanRsp with failed status= %d"), status);) pMac->lim.gLimHalScanState = eLIM_HAL_IDLE_SCAN_STATE; limCompleteMlmScan(pMac, eSIR_SME_HAL_SCAN_INIT_FAILED); } @@ -3897,7 +3871,7 @@ void limProcessEndScanRsp(tpAniSirGlobal pMac, void *body) } break; default: - limLog(pMac, LOGW, FL("Rcvd endScanRsp not in WAIT State, state %d\n"), + limLog(pMac, LOGW, FL("Rcvd endScanRsp not in WAIT State, state %d"), pMac->lim.gLimHalScanState); break; } @@ -3994,7 +3968,7 @@ void limProcessFinishScanRsp(tpAniSirGlobal pMac, void *body) } if (status != (tANI_U32) eHAL_STATUS_SUCCESS) { - PELOGW(limLog(pMac, LOGW, FL("EndScanRsp with failed status= %d\n"), status);) + PELOGW(limLog(pMac, LOGW, FL("EndScanRsp with failed status= %d"), status);) } break; //WLAN_SUSPEND_LINK Related @@ -4009,14 +3983,14 @@ void limProcessFinishScanRsp(tpAniSirGlobal pMac, void *body) } else { - limLog( pMac, LOGP, "No Resume link callback set but station is in suspend state\n"); + limLog( pMac, LOGP, "No Resume link callback set but station is in suspend state"); return; } break; //end WLAN_SUSPEND_LINK Related default: - limLog(pMac, LOGW, FL("Rcvd FinishScanRsp not in WAIT State, state %d\n"), + limLog(pMac, LOGW, FL("Rcvd FinishScanRsp not in WAIT State, state %d"), pMac->lim.gLimHalScanState); break; } @@ -4047,12 +4021,12 @@ void limProcessMlmHalAddBARsp( tpAniSirGlobal pMac, //now LIM can process any defer message. SET_LIM_PROCESS_DEFD_MESGS(pMac, true); if (pAddBAParams == NULL) { - PELOGE(limLog(pMac, LOGE,FL("NULL ADD BA Response from HAL\n"));) + PELOGE(limLog(pMac, LOGE,FL("NULL ADD BA Response from HAL"));) return; } if((psessionEntry = peFindSessionBySessionId(pMac, pAddBAParams->sessionId))==NULL) { - PELOGE(limLog(pMac, LOGE,FL("session does not exist for given sessionID: %d\n"),pAddBAParams->sessionId );) + PELOGE(limLog(pMac, LOGE,FL("session does not exist for given sessionID: %d"),pAddBAParams->sessionId );) palFreeMemory(pMac->hHdd, (void*)limMsgQ->bodyptr); return; } @@ -4063,7 +4037,7 @@ void limProcessMlmHalAddBARsp( tpAniSirGlobal pMac, // Allocate for LIM_MLM_ADDBA_CNF if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **) &pMlmAddBACnf, sizeof( tLimMlmAddBACnf ))) { - limLog( pMac, LOGP, FL(" palAllocateMemory failed with error code %d\n")); + limLog( pMac, LOGP, FL(" palAllocateMemory failed with error code %d")); palFreeMemory(pMac->hHdd, (void*)limMsgQ->bodyptr); return; } @@ -4108,13 +4082,13 @@ tLimBAState curBaState; tpPESession psessionEntry = NULL; if(pMsgBuf == NULL) { - PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n"));) + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) return; } pMlmAddBACnf = (tpLimMlmAddBACnf) pMsgBuf; if((psessionEntry = peFindSessionBySessionId(pMac,pMlmAddBACnf->sessionId))== NULL) { - PELOGE(limLog(pMac, LOGE,FL("session does not exist for given BSSId\n"));) + PELOGE(limLog(pMac, LOGE,FL("session does not exist for given BSSId"));) palFreeMemory( pMac->hHdd, (void *) pMsgBuf ); return; } @@ -4123,7 +4097,7 @@ pMlmAddBACnf = (tpLimMlmAddBACnf) pMsgBuf; if( NULL == pSta ) { PELOGE(limLog( pMac, LOGE, - FL( "STA context not found - ignoring ADDBA CNF from HAL\n" ));) + FL( "STA context not found - ignoring ADDBA CNF from HAL" ));) palFreeMemory( pMac->hHdd, (void *) pMsgBuf ); return; } @@ -4132,7 +4106,7 @@ pMlmAddBACnf = (tpLimMlmAddBACnf) pMsgBuf; if( eLIM_BA_STATE_WT_ADD_RSP != curBaState) { PELOGE(limLog( pMac, LOGE, - FL( "Received unexpected ADDBA CNF when STA BA state is %d\n" ), + FL( "Received unexpected ADDBA CNF when STA BA state is %d" ), curBaState );) palFreeMemory( pMac->hHdd, (void *) pMsgBuf ); return; @@ -4201,13 +4175,13 @@ void limProcessMlmDelBACnf( tpAniSirGlobal pMac, if(pMsgBuf == NULL) { - PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n"));) + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) return; } pMlmDelBACnf = (tpLimMlmDelBACnf) pMsgBuf; if((psessionEntry = peFindSessionBySessionId(pMac, pMlmDelBACnf->sessionId))== NULL) { - limLog(pMac, LOGP,FL("Session Does not exist for given sessionID\n")); + limLog(pMac, LOGP,FL("Session Does not exist for given sessionID")); palFreeMemory( pMac->hHdd, (void *) pMsgBuf ); return; } @@ -4216,14 +4190,14 @@ void limProcessMlmDelBACnf( tpAniSirGlobal pMac, if( NULL == pSta ) { limLog( pMac, LOGE, - FL( "STA context not found - ignoring DELBA CNF from HAL\n" )); + FL( "STA context not found - ignoring DELBA CNF from HAL" )); palFreeMemory( pMac->hHdd, (void *) pMsgBuf ); return; } if(NULL == pMlmDelBACnf) { limLog( pMac, LOGE, - FL( "pMlmDelBACnf is NULL - ignoring DELBA CNF from HAL\n" )); + FL( "pMlmDelBACnf is NULL - ignoring DELBA CNF from HAL" )); return; } // Need to validate baState @@ -4231,7 +4205,7 @@ void limProcessMlmDelBACnf( tpAniSirGlobal pMac, if( eLIM_BA_STATE_WT_DEL_RSP != curBaState ) { limLog( pMac, LOGE, - FL( "Received unexpected DELBA CNF when STA BA state is %d\n" ), + FL( "Received unexpected DELBA CNF when STA BA state is %d" ), curBaState ); palFreeMemory( pMac->hHdd, (void *) pMsgBuf ); return; @@ -4267,7 +4241,7 @@ void limProcessMlmHalBADeleteInd( tpAniSirGlobal pMac, if((psessionEntry = peFindSessionByBssid(pMac,pBADeleteParams->bssId,&sessionId))== NULL) { - PELOGE(limLog(pMac, LOGE,FL("session does not exist for given BSSId\n"));) + PELOGE(limLog(pMac, LOGE,FL("session does not exist for given BSSId"));) palFreeMemory( pMac->hHdd, (void *) limMsgQ->bodyptr ); return; } @@ -4276,7 +4250,7 @@ void limProcessMlmHalBADeleteInd( tpAniSirGlobal pMac, if( NULL == pSta ) { limLog( pMac, LOGE, - FL( "STA context not found - ignoring BA Delete IND from HAL\n" )); + FL( "STA context not found - ignoring BA Delete IND from HAL" )); goto returnAfterCleanup; } @@ -4285,7 +4259,7 @@ void limProcessMlmHalBADeleteInd( tpAniSirGlobal pMac, if( eLIM_BA_STATE_IDLE != curBaState ) { limLog( pMac, LOGE, - FL( "Received unexpected BA Delete IND when STA BA state is %d\n" ), + FL( "Received unexpected BA Delete IND when STA BA state is %d" ), curBaState ); goto returnAfterCleanup; } @@ -4305,7 +4279,7 @@ void limProcessMlmHalBADeleteInd( tpAniSirGlobal pMac, if( eSIR_FAILURE == status ) { limLog( pMac, LOGW, - FL("Received an INVALID DELBA Delete Ind for TID %d...\n"), + FL("Received an INVALID DELBA Delete Ind for TID %d..."), pBADeleteParams->baTID ); } else @@ -4319,7 +4293,7 @@ void limProcessMlmHalBADeleteInd( tpAniSirGlobal pMac, eSIR_MAC_UNSPEC_FAILURE_REASON,psessionEntry ))) { limLog( pMac, LOGE, - FL( "Attempt to post LIM_MLM_DELBA_REQ failed with status %d\n" ), status); + FL( "Attempt to post LIM_MLM_DELBA_REQ failed with status %d" ), status); } else { @@ -4370,7 +4344,7 @@ limProcessSetMimoRsp(tpAniSirGlobal pMac, tpSirMsgQ limMsg) /** If Updation of the HAL Fail's*/ if (pMIMO_PSParams->status != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("Update HAL / SW Mac for MIMO State has Failed\n")); + limLog(pMac, LOGP, FL("Update HAL / SW Mac for MIMO State has Failed")); break; } @@ -4394,7 +4368,7 @@ limProcessSetMimoRsp(tpAniSirGlobal pMac, tpSirMsgQ limMsg) /** Send Action Frame with the corresponding mode */ retStatus = limSendSMPowerStateFrame(pMac, macAddr, pMIMO_PSParams->htMIMOPSState); if (retStatus != eSIR_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("Sending Action Frame has failed\n"));) + PELOGE(limLog(pMac, LOGE, FL("Sending Action Frame has failed"));) break; } } @@ -4445,7 +4419,7 @@ limHandleDelBssInReAssocContext(tpAniSirGlobal pMac, tpDphHashNode pStaDs,tpPESe if ((pStaDs = dphAddHashEntry(pMac, psessionEntry->limReAssocbssId, DPH_STA_HASH_INDEX_PEER, &psessionEntry->dph.dphHashTable)) == NULL) { // Could not add hash table entry - PELOGE(limLog(pMac, LOGE, FL("could not add hash entry at DPH for \n"));) + PELOGE(limLog(pMac, LOGE, FL("could not add hash entry at DPH for "));) limPrintMacAddr(pMac, psessionEntry->limReAssocbssId, LOGE); mlmReassocCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE; mlmReassocCnf.protStatusCode = eSIR_SME_SUCCESS; @@ -4472,7 +4446,7 @@ limHandleDelBssInReAssocContext(tpAniSirGlobal pMac, tpDphHashNode pStaDs,tpPESe //updateBss flag is false, as in this case, PE is first deleting the existing BSS and then adding a new one. if (eSIR_SUCCESS != limStaSendAddBss( pMac, assocRsp, &beaconStruct, &psessionEntry->pLimReAssocReq->bssDescription, false, psessionEntry)) { - limLog( pMac, LOGE, FL( "Posting ADDBSS in the ReAssocContext has Failed \n")); + limLog( pMac, LOGE, FL( "Posting ADDBSS in the ReAssocContext has Failed ")); retStatus = eSIR_FAILURE; } if (retStatus != eSIR_SUCCESS) @@ -4506,7 +4480,7 @@ limHandleDelBssInReAssocContext(tpAniSirGlobal pMac, tpDphHashNode pStaDs,tpPESe } break; default: - PELOGE(limLog(pMac, LOGE, FL("DelBss is being invoked in the wrong system Role /unhandled SME State\n"));) + PELOGE(limLog(pMac, LOGE, FL("DelBss is being invoked in the wrong system Role /unhandled SME State"));) mlmReassocCnf.resultCode = eSIR_SME_REFUSED; mlmReassocCnf.protStatusCode = eSIR_SME_UNEXPECTED_REQ_RESULT_CODE; goto Error; @@ -4526,12 +4500,12 @@ limProcessBtampAddBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ,tpPESession ps if (NULL == pAddBssParams) { - limLog( pMac, LOGE, FL( "Invalid body pointer in message\n")); + limLog( pMac, LOGE, FL( "Invalid body pointer in message")); goto end; } if( eHAL_STATUS_SUCCESS == pAddBssParams->status ) { - limLog(pMac, LOG2, FL("WDA_ADD_BSS_RSP returned with eHAL_STATUS_SUCCESS\n")); + limLog(pMac, LOG2, FL("WDA_ADD_BSS_RSP returned with eHAL_STATUS_SUCCESS")); if (psessionEntry->bssType == eSIR_BTAMP_AP_MODE) { if (limSetLinkState(pMac, eSIR_LINK_BTAMP_AP_STATE, psessionEntry->bssId, @@ -4554,7 +4528,7 @@ limProcessBtampAddBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ,tpPESession ps limCreateTimers(pMac); /* Update the lim global gLimTriggerBackgroundScanDuringQuietBss */ if( eSIR_SUCCESS != wlan_cfgGetInt( pMac, WNI_CFG_TRIG_STA_BK_SCAN, &val )) - limLog( pMac, LOGP, FL("Failed to get WNI_CFG_TRIG_STA_BK_SCAN!\n")); + limLog( pMac, LOGP, FL("Failed to get WNI_CFG_TRIG_STA_BK_SCAN!")); pMac->lim.gLimTriggerBackgroundScanDuringQuietBss = (val) ? 1 : 0; // Apply previously set configuration at HW limApplyConfiguration(pMac,psessionEntry); @@ -4563,7 +4537,7 @@ limProcessBtampAddBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ,tpPESession ps } else { - limLog( pMac, LOGE, FL( "WDA_ADD_BSS_REQ failed with status %d\n" ),pAddBssParams->status ); + limLog( pMac, LOGE, FL( "WDA_ADD_BSS_REQ failed with status %d" ),pAddBssParams->status ); mlmStartCnf.resultCode = eSIR_SME_HAL_SEND_MESSAGE_FAIL; } mlmStartCnf.sessionId = psessionEntry->peSessionId; @@ -4606,7 +4580,7 @@ limHandleAddBssInReAssocContext(tpAniSirGlobal pMac, tpDphHashNode pStaDs, tpPES if(eHAL_STATUS_SUCCESS != palAllocateMemory(pMac->hHdd, (void **)&pBeaconStruct, sizeof(tSchBeaconStruct))) { - limLog(pMac, LOGE, FL("Unable to PAL allocate memory in limHandleAddBssInReAssocContext\n") ); + limLog(pMac, LOGE, FL("Unable to PAL allocate memory in limHandleAddBssInReAssocContext") ); mlmReassocCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE; mlmReassocCnf.protStatusCode = eSIR_SME_RESOURCES_UNAVAILABLE; goto Error; @@ -4616,7 +4590,7 @@ limHandleAddBssInReAssocContext(tpAniSirGlobal pMac, tpDphHashNode pStaDs, tpPES pStaDs = dphGetHashEntry(pMac, DPH_STA_HASH_INDEX_PEER, &psessionEntry->dph.dphHashTable); if (pStaDs == NULL ) { - PELOGE(limLog(pMac, LOGE, FL("Fail to get STA PEER entry from hash\n"));) + PELOGE(limLog(pMac, LOGE, FL("Fail to get STA PEER entry from hash"));) mlmReassocCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE; mlmReassocCnf.protStatusCode = eSIR_SME_SUCCESS; palFreeMemory(pMac->hHdd, pBeaconStruct); @@ -4645,7 +4619,7 @@ limHandleAddBssInReAssocContext(tpAniSirGlobal pMac, tpDphHashNode pStaDs, tpPES if (eSIR_SUCCESS != limStaSendAddBss( pMac, assocRsp, pBeaconStruct, &psessionEntry->pLimReAssocReq->bssDescription, true, psessionEntry)) { - limLog( pMac, LOGE, FL( "Posting ADDBSS in the ReAssocContext has Failed \n")); + limLog( pMac, LOGE, FL( "Posting ADDBSS in the ReAssocContext has Failed ")); retStatus = eSIR_FAILURE; } if (retStatus != eSIR_SUCCESS) @@ -4680,7 +4654,7 @@ limHandleAddBssInReAssocContext(tpAniSirGlobal pMac, tpDphHashNode pStaDs, tpPES } break; default: - PELOGE(limLog(pMac, LOGE, FL("DelBss is being invoked in the wrong system Role /unhandled SME State\n"));) + PELOGE(limLog(pMac, LOGE, FL("DelBss is being invoked in the wrong system Role /unhandled SME State"));) mlmReassocCnf.resultCode = eSIR_SME_REFUSED; mlmReassocCnf.protStatusCode = eSIR_SME_UNEXPECTED_REQ_RESULT_CODE; goto Error; @@ -4701,24 +4675,24 @@ limProcessSmeAssocCnfNew(tpAniSirGlobal pMac, tANI_U32 msgType, tANI_U32 *pMsgBu if(pMsgBuf == NULL) { - limLog(pMac, LOGE, FL("pMsgBuf is NULL \n")); + limLog(pMac, LOGE, FL("pMsgBuf is NULL ")); goto end; } if ((limAssocCnfSerDes(pMac, &assocCnf, (tANI_U8 *) pMsgBuf) == eSIR_FAILURE) || !__limIsSmeAssocCnfValid(&assocCnf)) { - limLog(pMac, LOGE, FL("Received invalid SME_RE(ASSOC)_CNF message \n")); + limLog(pMac, LOGE, FL("Received invalid SME_RE(ASSOC)_CNF message ")); goto end; } if((psessionEntry = peFindSessionByBssid(pMac, assocCnf.bssId, &sessionId))== NULL) { - limLog(pMac, LOGE, FL("session does not exist for given bssId\n")); + limLog(pMac, LOGE, FL("session does not exist for given bssId")); goto end; } if ( ((psessionEntry->limSystemRole != eLIM_AP_ROLE) && (psessionEntry->limSystemRole != eLIM_BT_AMP_AP_ROLE)) || ((psessionEntry->limSmeState != eLIM_SME_NORMAL_STATE) && (psessionEntry->limSmeState != eLIM_SME_NORMAL_CHANNEL_SCAN_STATE))) { - limLog(pMac, LOGE, FL("Received unexpected message %X in state %X, in role %X\n"), + limLog(pMac, LOGE, FL("Received unexpected message %X in state %X, in role %X"), msgType, psessionEntry->limSmeState , psessionEntry->limSystemRole); goto end; } @@ -4757,7 +4731,7 @@ limProcessSmeAssocCnfNew(tpAniSirGlobal pMac, tANI_U32 msgType, tANI_U32 *pMsgBu ** Deactivate/delet CNF_WAIT timer since ASSOC_CNF ** has been received **/ - limLog(pMac, LOG1, FL("Received SME_ASSOC_CNF. Delete Timer\n")); + limLog(pMac, LOG1, FL("Received SME_ASSOC_CNF. Delete Timer")); limDeactivateAndChangePerStaIdTimer(pMac, eLIM_CNF_WAIT_TIMER, pStaDs->assocId); if (assocCnf.statusCode == eSIR_SME_SUCCESS) { @@ -4766,7 +4740,7 @@ limProcessSmeAssocCnfNew(tpAniSirGlobal pMac, tANI_U32 msgType, tANI_U32 *pMsgBu * Association Response frame to the requesting BTAMP-STA. */ pStaDs->mlmStaContext.mlmState = eLIM_MLM_LINK_ESTABLISHED_STATE; - limLog(pMac, LOG1, FL("sending Assoc Rsp frame to STA (assoc id=%d) \n"), pStaDs->assocId); + limLog(pMac, LOG1, FL("sending Assoc Rsp frame to STA (assoc id=%d) "), pStaDs->assocId); limSendAssocRspMgmtFrame( pMac, eSIR_SUCCESS, pStaDs->assocId, pStaDs->staAddr, pStaDs->mlmStaContext.subType, pStaDs, psessionEntry); goto end; @@ -4803,14 +4777,14 @@ limSendBeaconInd(tpAniSirGlobal pMac, tpPESession psessionEntry){ /** Allocate the Memory for Beacon Pre Message and for Stations in PoweSave*/ if(psessionEntry == NULL ){ PELOGE( limLog( pMac, LOGE, - FL( "Error:Unable to get the PESessionEntry\n" ));) + FL( "Error:Unable to get the PESessionEntry" ));) return; } if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **) &pBeaconGenParams, (sizeof(*pBeaconGenParams)))) { PELOGE( limLog( pMac, LOGP, - FL( "Unable to PAL allocate memory during sending beaconPreMessage\n" ));) + FL( "Unable to PAL allocate memory during sending beaconPreMessage" ));) return; } palZeroMemory( pMac->hHdd, pBeaconGenParams, sizeof(*pBeaconGenParams)); diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessProbeReqFrame.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessProbeReqFrame.c index a3075030fc2..4f9c623a00b 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessProbeReqFrame.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessProbeReqFrame.c @@ -135,7 +135,7 @@ void limGetWPSPBCSessions(tpAniSirGlobal pMac, tANI_U8 *addr, *overlap = eSAP_WPSPBC_ONE_WPSPBC_PROBE_REQ_IN120S; // One WPS probe request in 120 second } - PELOGE(limLog(pMac, LOGE, FL("overlap = %d\n"), *overlap);) + PELOGE(limLog(pMac, LOGE, FL("overlap = %d"), *overlap);) PELOGE(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOGE, addr, sizeof(tSirMacAddr));) PELOGE(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOGE, uuid_e, SIR_WPS_UUID_LEN);) @@ -169,7 +169,7 @@ static void limRemoveTimeoutPBCsessions(tpAniSirGlobal pMac, tSirWPSPBCSession * prev = pbc; pbc = pbc->next; - PELOG4(limLog(pMac, LOG4, FL("WPS PBC sessions remove\n"));) + PELOG4(limLog(pMac, LOG4, FL("WPS PBC sessions remove"));) PELOG4(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG4, prev->addr, sizeof(tSirMacAddr));) PELOG4(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG4, prev->uuid_e, SIR_WPS_UUID_LEN);) @@ -231,7 +231,7 @@ static void limUpdatePBCSessionEntry(tpAniSirGlobal pMac, curTime = (tANI_TIMESTAMP)(palGetTickCount(pMac->hHdd) / PAL_TICKS_PER_SECOND); - PELOG4(limLog(pMac, LOG4, FL("Receive WPS probe reques curTime=%d\n"), curTime);) + PELOG4(limLog(pMac, LOG4, FL("Receive WPS probe reques curTime=%d"), curTime);) PELOG4(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG4, addr, sizeof(tSirMacAddr));) PELOG4(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG4, uuid_e, SIR_WPS_UUID_LEN);) @@ -254,7 +254,7 @@ static void limUpdatePBCSessionEntry(tpAniSirGlobal pMac, if (eHAL_STATUS_SUCCESS != palAllocateMemory(pMac->hHdd, (void **) &pbc, sizeof(tSirWPSPBCSession))) { - PELOGE(limLog(pMac, LOGE, FL("memory allocate failed!\n"));) + PELOGE(limLog(pMac, LOGE, FL("memory allocate failed!"));) return; } palCopyMemory(pMac->hHdd, (tANI_U8 *)pbc->addr, (tANI_U8 *)addr, sizeof(tSirMacAddr)); @@ -309,7 +309,7 @@ void limWPSPBCTimeout(tpAniSirGlobal pMac, tpPESession psessionEntry) curTime = (tANI_TIMESTAMP)(palGetTickCount(pMac->hHdd) / PAL_TICKS_PER_SECOND); - PELOG3(limLog(pMac, LOG3, FL("WPS PBC cleanup timeout curTime=%d\n"), curTime);) + PELOG3(limLog(pMac, LOG3, FL("WPS PBC cleanup timeout curTime=%d"), curTime);) prev = psessionEntry->pAPWPSPBCSession; if(prev) @@ -443,7 +443,7 @@ limProcessProbeReqFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession || (pMac->lim.gLimHalScanState != eLIM_HAL_IDLE_SCAN_STATE))) { limLog(pMac, LOG3, - FL("While GO is scanning, don't send probe response on diff channel\n")); + FL("While GO is scanning, don't send probe response on diff channel")); break; } @@ -538,7 +538,7 @@ limProcessProbeReqFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession else { if (wlan_cfgGetInt(pMac, (tANI_U16) WNI_CFG_WPS_ENABLE, &tmp) != eSIR_SUCCESS) - limLog(pMac, LOGP,"Failed to cfg get id %d\n", WNI_CFG_WPS_ENABLE ); + limLog(pMac, LOGP,"Failed to cfg get id %d", WNI_CFG_WPS_ENABLE ); wpsApEnable = tmp & WNI_CFG_WPS_ENABLE_AP; if ((wpsApEnable) && @@ -551,7 +551,7 @@ limProcessProbeReqFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession { // Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for eWNI_SME_PROBE_REQ\n")); + FL("call to palAllocateMemory failed for eWNI_SME_PROBE_REQ")); return; } msgQ.type = eWNI_SME_PROBE_REQ; @@ -796,7 +796,7 @@ limSendSmeProbeReqInd(tpAniSirGlobal pMac, { // Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for eWNI_SME_PROBE_REQ\n")); + FL("call to palAllocateMemory failed for eWNI_SME_PROBE_REQ")); return; } diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessProbeRspFrame.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessProbeRspFrame.c index 0e695980943..58c49f94580 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessProbeRspFrame.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessProbeRspFrame.c @@ -118,7 +118,7 @@ limProcessProbeRspFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession if(eHAL_STATUS_SUCCESS != palAllocateMemory(pMac->hHdd, (void **)&pProbeRsp, sizeof(tSirProbeRespBeacon))) { - limLog(pMac, LOGE, FL("Unable to PAL allocate memory in limProcessProbeRspFrame\n") ); + limLog(pMac, LOGE, FL("Unable to PAL allocate memory in limProcessProbeRspFrame") ); return; } @@ -176,6 +176,14 @@ limProcessProbeRspFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession { frameLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); + if (pMac->lim.gLimBackgroundScanMode == eSIR_ROAMING_SCAN) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + FL("Probe Resp Frame Received: BSSID " MAC_ADDRESS_STR " (RSSI %d)"), + MAC_ADDR_ARRAY(pHdr->bssId), + (uint)abs((tANI_S8)WDA_GET_RX_RSSI_DB(pRxPacketInfo))); + } + // Get pointer to Probe Response frame body pBody = WDA_GET_RX_MPDU_DATA(pRxPacketInfo); @@ -238,7 +246,7 @@ limProcessProbeRspFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession &cfg) != eSIR_SUCCESS) { /// Could not get BSSID from CFG. Log error. - limLog(pMac, LOGP, FL("could not retrieve BSSID\n")); + limLog(pMac, LOGP, FL("could not retrieve BSSID")); } #endif //TO SUPPORT BT-AMP sirCopyMacAddr(currentBssId,psessionEntry->bssId); @@ -252,7 +260,7 @@ limProcessProbeRspFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession if (!LIM_IS_CONNECTION_ACTIVE(psessionEntry)) { limLog(pMac, LOGW, - FL("Received Probe Resp from AP. So it is alive!!\n")); + FL("Received Probe Resp from AP. So it is alive!!")); if (pProbeRsp->HTInfo.present) limReceivedHBHandler(pMac, (tANI_U8)pProbeRsp->HTInfo.primaryChannel, psessionEntry); @@ -288,7 +296,7 @@ limProcessProbeRspFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession limGetQosMode(psessionEntry, &qosEnabled); limGetWmeMode(psessionEntry, &wmeEnabled); PELOG2(limLog(pMac, LOG2, - FL("wmeEdcaPresent: %d wmeEnabled: %d, edcaPresent: %d, qosEnabled: %d, edcaParams.qosInfo.count: %d schObject.gLimEdcaParamSetCount: %d\n"), + FL("wmeEdcaPresent: %d wmeEnabled: %d, edcaPresent: %d, qosEnabled: %d, edcaParams.qosInfo.count: %d schObject.gLimEdcaParamSetCount: %d"), pProbeRsp->wmeEdcaPresent, wmeEnabled, pProbeRsp->edcaPresent, qosEnabled, pProbeRsp->edcaParams.qosInfo.count, psessionEntry->gLimEdcaParamSetCount);) if (((pProbeRsp->wmeEdcaPresent && wmeEnabled) || @@ -296,7 +304,7 @@ limProcessProbeRspFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession (pProbeRsp->edcaParams.qosInfo.count != psessionEntry->gLimEdcaParamSetCount)) { if (schBeaconEdcaProcess(pMac, &pProbeRsp->edcaParams, psessionEntry) != eSIR_SUCCESS) - PELOGE(limLog(pMac, LOGE, FL("EDCA parameter processing error\n"));) + PELOGE(limLog(pMac, LOGE, FL("EDCA parameter processing error"));) else if (pStaDs != NULL) { // If needed, downgrade the EDCA parameters @@ -308,7 +316,7 @@ limProcessProbeRspFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession limSendEdcaParams(pMac, psessionEntry->gLimEdcaParamsActive, pStaDs->bssId, eANI_BOOLEAN_FALSE); } else - PELOGE(limLog(pMac, LOGE, FL("Self Entry missing in Hash Table\n"));) + PELOGE(limLog(pMac, LOGE, FL("Self Entry missing in Hash Table"));) } @@ -340,7 +348,7 @@ limProcessProbeRspFrameNoSession(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo) if(eHAL_STATUS_SUCCESS != palAllocateMemory(pMac->hHdd, (void **)&pProbeRsp, sizeof(tSirProbeRespBeacon))) { - limLog(pMac, LOGE, FL("Unable to PAL allocate memory in limProcessProbeRspFrameNoSession\n") ); + limLog(pMac, LOGE, FL("Unable to PAL allocate memory in limProcessProbeRspFrameNoSession") ); return; } @@ -357,10 +365,26 @@ limProcessProbeRspFrameNoSession(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo) WDA_GET_RX_MPDU_LEN(pRxPacketInfo)); limPrintMacAddr(pMac, pHdr->sa, LOG2); - if (limDeactivateMinChannelTimerDuringScan(pMac) != eSIR_SUCCESS) +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (!(WDA_GET_OFFLOADSCANLEARN(pRxPacketInfo) || + WDA_GET_ROAMCANDIDATEIND(pRxPacketInfo))) { - palFreeMemory(pMac->hHdd, pProbeRsp); - return; +#endif + if (limDeactivateMinChannelTimerDuringScan(pMac) != eSIR_SUCCESS) + { + palFreeMemory(pMac->hHdd, pProbeRsp); + return; + } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + } +#endif + // Validate IE information before processing Probe Response Frame + if (limValidateIEInformationInProbeRspFrame(pRxPacketInfo) != eSIR_SUCCESS) + { + PELOG1(limLog(pMac, LOG1,FL("Parse error ProbeResponse, length=%d"), + frameLen);) + palFreeMemory(pMac->hHdd, pProbeRsp); + return; } // Validate IE information before processing Probe Response Frame if (limValidateIEInformationInProbeRspFrame(pRxPacketInfo) != eSIR_SUCCESS) @@ -376,21 +400,58 @@ limProcessProbeRspFrameNoSession(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo) * - eLIM_MLM_BSS_STARTED_STATE * Hence, expect Probe Response only when * 1. STA is in scan mode waiting for Beacon/Probe response + * 2. LFR logic in FW sends up candidate frames * * Ignore Probe Response frame in all other states */ +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (WDA_GET_OFFLOADSCANLEARN(pRxPacketInfo)) + { + frameLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); + + if (pMac->lim.gLimBackgroundScanMode == eSIR_ROAMING_SCAN) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + FL("Probe Resp Frame Received: BSSID " MAC_ADDRESS_STR " (RSSI %d)"), + MAC_ADDR_ARRAY(pHdr->bssId), + (uint)abs((tANI_S8)WDA_GET_RX_RSSI_DB(pRxPacketInfo))); + } + + // Get pointer to Probe Response frame body + pBody = WDA_GET_RX_MPDU_DATA(pRxPacketInfo); + + if (sirConvertProbeFrame2Struct(pMac, pBody, frameLen, pProbeRsp) == eSIR_FAILURE) + { + limLog(pMac, LOG1, FL("Parse error ProbeResponse, length=%d\n"), frameLen); + palFreeMemory(pMac->hHdd, pProbeRsp); + return; + } + limLog( pMac, LOG2, FL("Save this probe rsp in LFR cache")); + limCheckAndAddBssDescription(pMac, pProbeRsp, pRxPacketInfo, + eANI_BOOLEAN_FALSE, eANI_BOOLEAN_TRUE); + } + else +#endif if( (pMac->lim.gLimMlmState == eLIM_MLM_WT_PROBE_RESP_STATE) || (pMac->lim.gLimMlmState == eLIM_MLM_PASSIVE_SCAN_STATE) || //mlm state check should be global - 18th oct (pMac->lim.gLimMlmState == eLIM_MLM_LEARN_STATE) ) { frameLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); + if (pMac->lim.gLimBackgroundScanMode == eSIR_ROAMING_SCAN) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + FL("Probe Resp Frame Received: BSSID " MAC_ADDRESS_STR " (RSSI %d)"), + MAC_ADDR_ARRAY(pHdr->bssId), + (uint)abs((tANI_S8)WDA_GET_RX_RSSI_DB(pRxPacketInfo))); + } + // Get pointer to Probe Response frame body pBody = WDA_GET_RX_MPDU_DATA(pRxPacketInfo); if (sirConvertProbeFrame2Struct(pMac, pBody, frameLen, pProbeRsp) == eSIR_FAILURE) { - limLog(pMac, LOG1, FL("Parse error ProbeResponse, length=%d\n"), frameLen); + limLog(pMac, LOG1, FL("Parse error ProbeResponse, length=%d"), frameLen); palFreeMemory(pMac->hHdd, pProbeRsp); return; } diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c index d08c060a37e..f2852b351b6 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c @@ -121,7 +121,6 @@ void __limProcessSmeAssocCnfNew(tpAniSirGlobal, tANI_U32, tANI_U32 *); extern void peRegisterTLHandle(tpAniSirGlobal pMac); -extern int limProcessRemainOnChnlReq(tpAniSirGlobal pMac, tANI_U32 *pMsg); #ifdef BACKGROUND_SCAN_ENABLED @@ -138,7 +137,7 @@ __limBackgroundScanInitiate(tpAniSirGlobal pMac) limDeactivateAndChangeTimer(pMac, eLIM_BACKGROUND_SCAN_TIMER); MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, NO_SESSION, eLIM_BACKGROUND_SCAN_TIMER)); if (tx_timer_activate(&pMac->lim.limTimers.gLimBackgroundScanTimer) != TX_SUCCESS) - limLog(pMac, LOGP, FL("could not activate background scan timer\n")); + limLog(pMac, LOGP, FL("could not activate background scan timer")); pMac->lim.gLimBackgroundScanStarted = true; pMac->lim.gLimBackgroundScanChannelId = 0; } @@ -189,7 +188,7 @@ __limFreshScanReqd(tpAniSirGlobal pMac, tANI_U8 returnFreshResults) } } - PELOG1(limLog(pMac, LOG1, FL("FreshScanReqd: %d \n"), validState);) + PELOG1(limLog(pMac, LOG1, FL("FreshScanReqd: %d "), validState);) if( (validState) && (returnFreshResults & SIR_BG_SCAN_RETURN_FRESH_RESULTS)) return TRUE; @@ -284,10 +283,10 @@ __limIsDeferedMsgForLearn(tpAniSirGlobal pMac, tpSirMsgQ pMsg) { if (limDeferMsg(pMac, pMsg) != TX_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("Could not defer Msg = %d\n"), pMsg->type);) + PELOGE(limLog(pMac, LOGE, FL("Could not defer Msg = %d"), pMsg->type);) return eANI_BOOLEAN_FALSE; } - PELOG1(limLog(pMac, LOG1, FL("Defer the message, in learn mode type = %d\n"), + PELOG1(limLog(pMac, LOG1, FL("Defer the message, in learn mode type = %d"), pMsg->type);) /** Send finish scan req to HAL only if LIM is not waiting for any response @@ -328,10 +327,10 @@ __limIsDeferedMsgForRadar(tpAniSirGlobal pMac, tpSirMsgQ pMsg) { if (limDeferMsg(pMac, pMsg) != TX_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("Could not defer Msg = %d\n"), pMsg->type);) + PELOGE(limLog(pMac, LOGE, FL("Could not defer Msg = %d"), pMsg->type);) return eANI_BOOLEAN_FALSE; } - PELOG1(limLog(pMac, LOG1, FL("Defer the message, in learn mode type = %d\n"), + PELOG1(limLog(pMac, LOG1, FL("Defer the message, in learn mode type = %d"), pMsg->type);) return eANI_BOOLEAN_TRUE; } @@ -365,7 +364,7 @@ __limProcessSmeStartReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) tANI_U16 smetransactionId; - PELOG1(limLog(pMac, LOG1, FL("Received START_REQ\n"));) + PELOG1(limLog(pMac, LOG1, FL("Received START_REQ"));) limGetSessionInfo(pMac,(tANI_U8 *)pMsgBuf,&smesessionId,&smetransactionId); @@ -384,6 +383,9 @@ __limProcessSmeStartReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) /// By default return unique scan results pMac->lim.gLimReturnUniqueResults = true; pMac->lim.gLimSmeScanResultLength = 0; +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + pMac->lim.gLimSmeLfrScanResultLength = 0; +#endif if (((tSirSmeStartReq *) pMsgBuf)->sendNewBssInd) { @@ -394,7 +396,7 @@ __limProcessSmeStartReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if (cfgSetInt(pMac, WNI_CFG_NEW_BSS_FOUND_IND, ((tSirSmeStartReq *) pMsgBuf)->sendNewBssInd) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("could not set NEIGHBOR_BSS_IND at CFG\n")); + limLog(pMac, LOGP, FL("could not set NEIGHBOR_BSS_IND at CFG")); retCode = eSIR_SME_UNEXPECTED_REQ_RESULT_CODE; } } @@ -406,7 +408,7 @@ __limProcessSmeStartReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * other than OFFLINE. Return response to host and * log error */ - limLog(pMac, LOGE, FL("Invalid SME_START_REQ received in SME state %X\n"),pMac->lim.gLimSmeState ); + limLog(pMac, LOGE, FL("Invalid SME_START_REQ received in SME state %X"),pMac->lim.gLimSmeState ); limPrintSmeState(pMac, LOGE, pMac->lim.gLimSmeState); retCode = eSIR_SME_UNEXPECTED_REQ_RESULT_CODE; } @@ -436,12 +438,12 @@ __limProcessSmeSysReadyInd(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) { peRegisterTLHandle(pMac); } - PELOGW(limLog(pMac, LOGW, FL("sending WDA_SYS_READY_IND msg to HAL\n"));) + PELOGW(limLog(pMac, LOGW, FL("sending WDA_SYS_READY_IND msg to HAL"));) MTRACE(macTraceMsgTx(pMac, NO_SESSION, msg.type)); if (eSIR_SUCCESS != wdaPostCtrlMsg(pMac, &msg)) { - limLog(pMac, LOGP, FL("wdaPostCtrlMsg failed\n")); + limLog(pMac, LOGP, FL("wdaPostCtrlMsg failed")); return eANI_BOOLEAN_TRUE; } return eANI_BOOLEAN_FALSE; @@ -528,8 +530,8 @@ __limHandleSmeStartBssRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) tANI_U32 val = 0; tSirRetStatus retStatus; tSirMacChanNum channelNumber; - tLimMlmStartReq *pMlmStartReq; - tpSirSmeStartBssReq pSmeStartBssReq; //Local variable for Start BSS Req.. Added For BT-AMP Support + tLimMlmStartReq *pMlmStartReq = NULL; + tpSirSmeStartBssReq pSmeStartBssReq = NULL; tSirResultCodes retCode = eSIR_SME_SUCCESS; tANI_U32 autoGenBssId = FALSE; //Flag Used in case of IBSS to Auto generate BSSID. tANI_U8 sessionId; @@ -542,7 +544,7 @@ __limHandleSmeStartBssRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) limDiagEventReport(pMac, WLAN_PE_DIAG_START_BSS_REQ_EVENT, NULL, 0, 0); #endif //FEATURE_WLAN_DIAG_SUPPORT - PELOG1(limLog(pMac, LOG1, FL("Received START_BSS_REQ\n"));) + PELOG1(limLog(pMac, LOG1, FL("Received START_BSS_REQ"));) /* Global Sme state and mlm states are not defined yet , for BT-AMP Suppoprt . TO BE DONE */ if ( (pMac->lim.gLimSmeState == eLIM_SME_OFFLINE_STATE) || @@ -553,7 +555,7 @@ __limHandleSmeStartBssRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pSmeStartBssReq, size)) { - PELOGE(limLog(pMac, LOGE, FL("palAllocateMemory failed for pMac->lim.gpLimStartBssReq\n"));) + PELOGE(limLog(pMac, LOGE, FL("palAllocateMemory failed for pMac->lim.gpLimStartBssReq"));) /// Send failure response to host retCode = eSIR_SME_RESOURCES_UNAVAILABLE; goto end; @@ -564,13 +566,13 @@ __limHandleSmeStartBssRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if ((limStartBssReqSerDes(pMac, pSmeStartBssReq, (tANI_U8 *) pMsgBuf) == eSIR_FAILURE) || (!limIsSmeStartBssReqValid(pMac, pSmeStartBssReq))) { - PELOGW(limLog(pMac, LOGW, FL("Received invalid eWNI_SME_START_BSS_REQ\n"));) + PELOGW(limLog(pMac, LOGW, FL("Received invalid eWNI_SME_START_BSS_REQ"));) retCode = eSIR_SME_INVALID_PARAMETERS; goto free; } #if 0 PELOG3(limLog(pMac, LOG3, - FL("Parsed START_BSS_REQ fields are bssType=%d, channelId=%d\n"), + FL("Parsed START_BSS_REQ fields are bssType=%d, channelId=%d"), pMac->lim.gpLimStartBssReq->bssType, pMac->lim.gpLimStartBssReq->channelId);) #endif @@ -578,7 +580,7 @@ __limHandleSmeStartBssRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * If session is not existed , then create a new session */ if((psessionEntry = peFindSessionByBssid(pMac,pSmeStartBssReq->bssId,&sessionId)) != NULL) { - limLog(pMac, LOGW, FL("Session Already exists for given BSSID\n")); + limLog(pMac, LOGW, FL("Session Already exists for given BSSID")); retCode = eSIR_SME_BSS_ALREADY_STARTED_OR_JOINED; psessionEntry = NULL; goto free; @@ -587,7 +589,7 @@ __limHandleSmeStartBssRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) { if((psessionEntry = peCreateSession(pMac,pSmeStartBssReq->bssId,&sessionId, pMac->lim.maxStation)) == NULL) { - limLog(pMac, LOGW, FL("Session Can not be created \n")); + limLog(pMac, LOGW, FL("Session Can not be created ")); retCode = eSIR_SME_RESOURCES_UNAVAILABLE; goto free; } @@ -716,7 +718,7 @@ __limHandleSmeStartBssRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&psessionEntry->parsedAssocReq, (psessionEntry->dph.dphHashTable.size * sizeof(tpSirAssocReq)) )) { - limLog(pMac, LOGW, FL("palAllocateMemory() failed\n")); + limLog(pMac, LOGW, FL("palAllocateMemory() failed")); retCode = eSIR_SME_RESOURCES_UNAVAILABLE; goto free; } @@ -742,7 +744,7 @@ __limHandleSmeStartBssRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) &chanWidth) != eSIR_SUCCESS) { limLog(pMac, LOGP, - FL("Unable to retrieve Channel Width from CFG\n")); + FL("Unable to retrieve Channel Width from CFG")); } if(chanWidth == eHT_CHANNEL_WIDTH_20MHZ || chanWidth == eHT_CHANNEL_WIDTH_40MHZ) @@ -750,7 +752,7 @@ __limHandleSmeStartBssRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if (cfgSetInt(pMac, WNI_CFG_VHT_CHANNEL_WIDTH, WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("could not set WNI_CFG_CHANNEL_BONDING_MODE at CFG\n")); + limLog(pMac, LOGP, FL("could not set WNI_CFG_CHANNEL_BONDING_MODE at CFG")); retCode = eSIR_LOGP_EXCEPTION; goto free; } @@ -760,7 +762,7 @@ __limHandleSmeStartBssRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if (cfgSetInt(pMac, WNI_CFG_VHT_CHANNEL_WIDTH, WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("could not set WNI_CFG_CHANNEL_BONDING_MODE at CFG\n")); + limLog(pMac, LOGP, FL("could not set WNI_CFG_CHANNEL_BONDING_MODE at CFG")); retCode = eSIR_LOGP_EXCEPTION; goto free; } @@ -768,12 +770,12 @@ __limHandleSmeStartBssRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) centerChan = limGetCenterChannel(pMac,channelNumber,pSmeStartBssReq->cbMode,WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ); if(centerChan != eSIR_CFG_INVALID_ID) { - limLog(pMac, LOGW, FL("***Center Channel for 80MHZ channel width = %ld\n"),centerChan); + limLog(pMac, LOGW, FL("***Center Channel for 80MHZ channel width = %ld"),centerChan); psessionEntry->apCenterChan = centerChan; if (cfgSetInt(pMac, WNI_CFG_VHT_CHANNEL_CENTER_FREQ_SEGMENT1, centerChan) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("could not set WNI_CFG_CHANNEL_BONDING_MODE at CFG\n")); + limLog(pMac, LOGP, FL("could not set WNI_CFG_CHANNEL_BONDING_MODE at CFG")); retCode = eSIR_LOGP_EXCEPTION; goto free; } @@ -787,7 +789,7 @@ __limHandleSmeStartBssRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) &chanWidth) != eSIR_SUCCESS) { limLog(pMac, LOGP, - FL("Unable to retrieve Channel Width from CFG\n")); + FL("Unable to retrieve Channel Width from CFG")); } /*For Sta+p2p-Go concurrency vhtTxChannelWidthSet is used for storing p2p-GO channel width @@ -802,7 +804,7 @@ __limHandleSmeStartBssRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) } else { - PELOGW(limLog(pMac, LOGW, FL("Received invalid eWNI_SME_START_BSS_REQ\n"));) + PELOGW(limLog(pMac, LOGW, FL("Received invalid eWNI_SME_START_BSS_REQ"));) retCode = eSIR_SME_INVALID_PARAMETERS; goto free; } @@ -836,14 +838,14 @@ __limHandleSmeStartBssRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) *reserved reserved RIFS Lsig n-GF ht20 11g 11b*/ palCopyMemory( pMac->hHdd, (void *) &psessionEntry->cfgProtection, (void *) &pSmeStartBssReq->ht_capab, - sizeof( tANI_U16 )); + sizeof( tCfgProtection )); psessionEntry->pAPWPSPBCSession = NULL; // Initialize WPS PBC session link list } // Prepare and Issue LIM_MLM_START_REQ to MLM if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pMlmStartReq, sizeof(tLimMlmStartReq))) { - limLog(pMac, LOGP, FL("call to palAllocateMemory failed for mlmStartReq\n")); + limLog(pMac, LOGP, FL("call to palAllocateMemory failed for mlmStartReq")); retCode = eSIR_SME_RESOURCES_UNAVAILABLE; goto free; } @@ -870,7 +872,7 @@ __limHandleSmeStartBssRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) //len = sizeof(tSirMacAddr); //retStatus = wlan_cfgGetStr(pMac, WNI_CFG_STA_ID, (tANI_U8 *) pMlmStartReq->bssId, &len); //if (retStatus != eSIR_SUCCESS) - //limLog(pMac, LOGP, FL("could not retrive BSSID, retStatus=%d\n"), retStatus); + //limLog(pMac, LOGP, FL("could not retrive BSSID, retStatus=%d"), retStatus); /* Copy the BSSId from sessionTable to mlmStartReq struct */ sirCopyMacAddr(pMlmStartReq->bssId,psessionEntry->bssId); @@ -882,7 +884,7 @@ __limHandleSmeStartBssRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if((retStatus = wlan_cfgGetInt(pMac, WNI_CFG_IBSS_AUTO_BSSID, &autoGenBssId)) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("Could not retrieve Auto Gen BSSID, retStatus=%d\n"), retStatus); + limLog(pMac, LOGP, FL("Could not retrieve Auto Gen BSSID, retStatus=%d"), retStatus); retCode = eSIR_LOGP_EXCEPTION; goto free; } @@ -894,7 +896,7 @@ __limHandleSmeStartBssRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if(pMlmStartReq->bssId[0] & 0x01) { - PELOGE(limLog(pMac, LOGE, FL("Request to start IBSS with group BSSID\n Autogenerating the BSSID\n"));) + PELOGE(limLog(pMac, LOGE, FL("Request to start IBSS with group BSSID\n Autogenerating the BSSID"));) autoGenBssId = TRUE; } } @@ -921,16 +923,16 @@ __limHandleSmeStartBssRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) }else { if (wlan_cfgGetInt(pMac, WNI_CFG_DTIM_PERIOD, &val) != eSIR_SUCCESS) - limLog(pMac, LOGP, FL("could not retrieve DTIM Period\n")); + limLog(pMac, LOGP, FL("could not retrieve DTIM Period")); pMlmStartReq->dtimPeriod = (tANI_U8)val; } if (wlan_cfgGetInt(pMac, WNI_CFG_CFP_PERIOD, &val) != eSIR_SUCCESS) - limLog(pMac, LOGP, FL("could not retrieve Beacon interval\n")); + limLog(pMac, LOGP, FL("could not retrieve Beacon interval")); pMlmStartReq->cfParamSet.cfpPeriod = (tANI_U8)val; if (wlan_cfgGetInt(pMac, WNI_CFG_CFP_MAX_DURATION, &val) != eSIR_SUCCESS) - limLog(pMac, LOGP, FL("could not retrieve CFPMaxDuration\n")); + limLog(pMac, LOGP, FL("could not retrieve CFPMaxDuration")); pMlmStartReq->cfParamSet.cfpMaxDuration = (tANI_U16) val; //this may not be needed anymore now, as rateSet is now included in the session entry and MLM has session context. @@ -957,14 +959,14 @@ __limHandleSmeStartBssRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) (SIR_BAND_5_GHZ == psessionEntry->limRFBand) ) { if (wlan_cfgGetInt(pMac, WNI_CFG_11H_ENABLED, &val) != eSIR_SUCCESS) - limLog(pMac, LOGP, FL("Fail to get WNI_CFG_11H_ENABLED \n")); + limLog(pMac, LOGP, FL("Fail to get WNI_CFG_11H_ENABLED ")); psessionEntry->lim11hEnable = val; } if (!psessionEntry->lim11hEnable) { if (cfgSetInt(pMac, WNI_CFG_LOCAL_POWER_CONSTRAINT, 0) != eSIR_SUCCESS) - limLog(pMac, LOGP, FL("Fail to get WNI_CFG_11H_ENABLED \n")); + limLog(pMac, LOGP, FL("Fail to get WNI_CFG_11H_ENABLED ")); } psessionEntry ->limPrevSmeState = psessionEntry->limSmeState; @@ -977,14 +979,19 @@ __limHandleSmeStartBssRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) else { - limLog(pMac, LOGE, FL("Received unexpected START_BSS_REQ, in state %X\n"),pMac->lim.gLimSmeState); + limLog(pMac, LOGE, FL("Received unexpected START_BSS_REQ, in state %X"),pMac->lim.gLimSmeState); retCode = eSIR_SME_BSS_ALREADY_STARTED_OR_JOINED; goto end; } // if (pMac->lim.gLimSmeState == eLIM_SME_OFFLINE_STATE) free: - palFreeMemory( pMac->hHdd, pSmeStartBssReq); - pSmeStartBssReq = NULL; + if ((psessionEntry != NULL) && + (psessionEntry->pLimStartBssReq == pSmeStartBssReq)) + { + psessionEntry->pLimStartBssReq = NULL; + } + palFreeMemory(pMac->hHdd, pSmeStartBssReq); + palFreeMemory(pMac->hHdd, pMlmStartReq); end: @@ -1092,7 +1099,7 @@ __limProcessSmeScanReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) #endif //FEATURE_WLAN_DIAG_SUPPORT pScanReq = (tpSirSmeScanReq) pMsgBuf; - PELOG1(limLog(pMac, LOG1, FL("SME SCAN REQ numChan %d min %d max %d IELen %d first %d fresh %d unique %d type %d mode %d rsp %d\n"), + PELOG1(limLog(pMac, LOG1, FL("SME SCAN REQ numChan %d min %d max %d IELen %d first %d fresh %d unique %d type %d mode %d rsp %d"), pScanReq->channelList.numChannels, pScanReq->minChannelTime, pScanReq->maxChannelTime, @@ -1123,7 +1130,7 @@ __limProcessSmeScanReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if (!limIsSmeScanReqValid(pMac, pScanReq)) { - PELOGW(limLog(pMac, LOGW, FL("Received SME_SCAN_REQ with invalid parameters\n"));) + PELOGW(limLog(pMac, LOGW, FL("Received SME_SCAN_REQ with invalid parameters"));) if (pMac->lim.gLimRspReqd) { @@ -1221,7 +1228,7 @@ __limProcessSmeScanReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) { // Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for mlmScanReq (%d)\n"), len); + FL("call to palAllocateMemory failed for mlmScanReq (%d)"), len); return; } @@ -1239,7 +1246,7 @@ __limProcessSmeScanReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * Log error. */ limLog(pMac, LOGP, - FL("could not retrieve Valid channel list\n")); + FL("could not retrieve Valid channel list")); } pMlmScanReq->channelList.numChannels = (tANI_U8) cfg_len; } @@ -1253,7 +1260,7 @@ __limProcessSmeScanReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) { // Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for mlmScanReq(%d)\n"), len); + FL("call to palAllocateMemory failed for mlmScanReq(%d)"), len); return; } @@ -1321,24 +1328,58 @@ __limProcessSmeScanReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) tANI_U16 scanRspLen = sizeof(tSirSmeScanRsp); pMac->lim.gLimRspReqd = false; - - if (pMac->lim.gLimSmeScanResultLength == 0) +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pScanReq->returnFreshResults & SIR_BG_SCAN_RETURN_LFR_CACHED_RESULTS) { - limSendSmeScanRsp(pMac, scanRspLen, eSIR_SME_SUCCESS, pScanReq->sessionId, pScanReq->transactionId); + pMac->lim.gLimSmeLfrScanResultLength = pMac->lim.gLimMlmLfrScanResultLength; + if (pMac->lim.gLimSmeLfrScanResultLength == 0) + { + limSendSmeLfrScanRsp(pMac, scanRspLen, + eSIR_SME_SUCCESS, + pScanReq->sessionId, + pScanReq->transactionId); + } + else + { + scanRspLen = sizeof(tSirSmeScanRsp) + + pMac->lim.gLimSmeLfrScanResultLength - + sizeof(tSirBssDescription); + limSendSmeLfrScanRsp(pMac, scanRspLen, eSIR_SME_SUCCESS, + pScanReq->sessionId, pScanReq->transactionId); + } } else { - scanRspLen = sizeof(tSirSmeScanRsp) + - pMac->lim.gLimSmeScanResultLength - - sizeof(tSirBssDescription); - limSendSmeScanRsp(pMac, scanRspLen, eSIR_SME_SUCCESS, pScanReq->sessionId, pScanReq->transactionId); +#endif + if (pMac->lim.gLimSmeScanResultLength == 0) + { + limSendSmeScanRsp(pMac, scanRspLen, eSIR_SME_SUCCESS, + pScanReq->sessionId, pScanReq->transactionId); + } + else + { + scanRspLen = sizeof(tSirSmeScanRsp) + + pMac->lim.gLimSmeScanResultLength - + sizeof(tSirBssDescription); + limSendSmeScanRsp(pMac, scanRspLen, eSIR_SME_SUCCESS, + pScanReq->sessionId, pScanReq->transactionId); + } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD } +#endif if (pScanReq->returnFreshResults & SIR_BG_SCAN_PURGE_RESUTLS) { // Discard previously cached scan results limReInitScanResults(pMac); } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pScanReq->returnFreshResults & SIR_BG_SCAN_PURGE_LFR_RESULTS) + { + // Discard previously cached scan results + limReInitLfrScanResults(pMac); + } +#endif } // if (pMac->lim.gLimRspReqd) } // else ((pMac->lim.gLimSmeState == eLIM_SME_IDLE_STATE) || ... @@ -1363,7 +1404,7 @@ static void __limProcessSmeOemDataReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) //post the lim mlm message now if(eHAL_STATUS_SUCCESS != palAllocateMemory(pMac->hHdd, (void**)&pMlmOemDataReq, (sizeof(tLimMlmOemDataReq)))) { - limLog(pMac, LOGP, FL("palAllocateMemory failed for mlmOemDataReq\n")); + limLog(pMac, LOGP, FL("palAllocateMemory failed for mlmOemDataReq")); return; } @@ -1445,7 +1486,7 @@ __limProcessSmeJoinReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) limDiagEventReport(pMac, WLAN_PE_DIAG_JOIN_REQ_EVENT, NULL, 0, 0); #endif //FEATURE_WLAN_DIAG_SUPPORT - PELOG1(limLog(pMac, LOG1, FL("Received SME_JOIN_REQ\n"));) + PELOG1(limLog(pMac, LOG1, FL("Received SME_JOIN_REQ"));) #ifdef WLAN_FEATURE_VOWIFI /* Need to read the CFG here itself as this is used in limExtractAPCapability() below. @@ -1453,7 +1494,7 @@ __limProcessSmeJoinReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * read, RRM related path before calling rrmUpdateConfig() is not getting executed causing issues * like not honoring power constraint on 1st association after driver loading. */ if (wlan_cfgGetInt(pMac, WNI_CFG_RRM_ENABLED, &val) != eSIR_SUCCESS) - limLog(pMac, LOGP, FL("cfg get rrm enabled failed\n")); + limLog(pMac, LOGP, FL("cfg get rrm enabled failed")); pMac->rrm.rrmPEContext.rrmEnable = (val) ? 1 : 0; val = 0; #endif /* WLAN_FEATURE_VOWIFI */ @@ -1469,7 +1510,7 @@ __limProcessSmeJoinReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) nSize = __limGetSmeJoinReqSizeForAlloc((tANI_U8*) pMsgBuf); if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pSmeJoinReq, nSize)) { - limLog(pMac, LOGP, FL("call to palAllocateMemory failed for pSmeJoinReq\n")); + limLog(pMac, LOGP, FL("call to palAllocateMemory failed for pSmeJoinReq")); retCode = eSIR_SME_RESOURCES_UNAVAILABLE; goto end; } @@ -1480,7 +1521,7 @@ __limProcessSmeJoinReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) { /// Received invalid eWNI_SME_JOIN_REQ // Log the event - limLog(pMac, LOGW, FL("received SME_JOIN_REQ with invalid data\n")); + limLog(pMac, LOGW, FL("received SME_JOIN_REQ with invalid data")); retCode = eSIR_SME_INVALID_PARAMETERS; goto end; } @@ -1493,7 +1534,7 @@ __limProcessSmeJoinReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) { if(peValidateBtJoinRequest(pMac)!= TRUE) { - limLog(pMac, LOGW, FL("Start Bss session not present::SME_JOIN_REQ in unexpected state\n")); + limLog(pMac, LOGW, FL("Start Bss session not present::SME_JOIN_REQ in unexpected state")); retCode = eSIR_SME_UNEXPECTED_REQ_RESULT_CODE; psessionEntry = NULL; goto end; @@ -1505,14 +1546,14 @@ __limProcessSmeJoinReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if((psessionEntry = peFindSessionByBssid(pMac,pSmeJoinReq->bssDescription.bssId,&sessionId)) != NULL) { - limLog(pMac, LOGE, FL("Session Already exists for given BSSID\n")); + limLog(pMac, LOGE, FL("Session Already exists for given BSSID")); if(psessionEntry->limSmeState == eLIM_SME_LINK_EST_STATE) { // Received eWNI_SME_JOIN_REQ for same // BSS as currently associated. // Log the event and send success - PELOGW(limLog(pMac, LOGW, FL("Received SME_JOIN_REQ for currently joined BSS\n"));) + PELOGW(limLog(pMac, LOGW, FL("Received SME_JOIN_REQ for currently joined BSS"));) /// Send Join success response to host retCode = eSIR_SME_SUCCESS; goto end; @@ -1529,7 +1570,7 @@ __limProcessSmeJoinReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) /* Try to Create a new session */ if((psessionEntry = peCreateSession(pMac,pSmeJoinReq->bssDescription.bssId,&sessionId, pMac->lim.maxStation)) == NULL) { - limLog(pMac, LOGE, FL("Session Can not be created \n")); + limLog(pMac, LOGE, FL("Session Can not be created ")); retCode = eSIR_SME_RESOURCES_UNAVAILABLE; goto end; } @@ -1566,13 +1607,13 @@ __limProcessSmeJoinReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) #ifdef WLAN_FEATURE_11AC psessionEntry->vhtCapability = IS_DOT11_MODE_VHT(psessionEntry->dot11mode); VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO_MED, - "***__limProcessSmeJoinReq: vhtCapability=%d****\n",psessionEntry->vhtCapability); + "***__limProcessSmeJoinReq: vhtCapability=%d****",psessionEntry->vhtCapability); if (psessionEntry->vhtCapability ) { psessionEntry->txBFIniFeatureEnabled = pSmeJoinReq->txBFIniFeatureEnabled; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO_MED, - "***__limProcessSmeJoinReq: txBFIniFeatureEnabled=%d****\n", + "***__limProcessSmeJoinReq: txBFIniFeatureEnabled=%d****", psessionEntry->txBFIniFeatureEnabled); if( psessionEntry->txBFIniFeatureEnabled ) @@ -1580,7 +1621,7 @@ __limProcessSmeJoinReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if (cfgSetInt(pMac, WNI_CFG_VHT_SU_BEAMFORMEE_CAP, psessionEntry->txBFIniFeatureEnabled) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("could not set WNI_CFG_VHT_SU_BEAMFORMEE_CAP at CFG\n")); + limLog(pMac, LOGP, FL("could not set WNI_CFG_VHT_SU_BEAMFORMEE_CAP at CFG")); retCode = eSIR_LOGP_EXCEPTION; goto end; } @@ -1590,7 +1631,7 @@ __limProcessSmeJoinReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if (cfgSetInt(pMac, WNI_CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED, pSmeJoinReq->txBFCsnValue) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("could not set WNI_CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED at CFG\n")); + limLog(pMac, LOGP, FL("could not set WNI_CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED at CFG")); retCode = eSIR_LOGP_EXCEPTION; goto end; } @@ -1608,18 +1649,6 @@ __limProcessSmeJoinReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) psessionEntry->htRecommendedTxWidthSet = psessionEntry->htSupportedChannelWidthSet; psessionEntry->htSecondaryChannelOffset = pSmeJoinReq->cbMode; - /* Record if management frames need to be protected */ -#ifdef WLAN_FEATURE_11W - if(eSIR_ED_AES_128_CMAC == pSmeJoinReq->MgmtEncryptionType) - { - psessionEntry->limRmfEnabled = 1; - } - else - { - psessionEntry->limRmfEnabled = 0; - } -#endif - /*Store Persona */ psessionEntry->pePersona = pSmeJoinReq->staPersona; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, @@ -1662,7 +1691,7 @@ __limProcessSmeJoinReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) else { /* Throw an error and return and make sure to delete the session.*/ - limLog(pMac, LOGW, FL("received SME_JOIN_REQ with invalid bss type\n")); + limLog(pMac, LOGW, FL("received SME_JOIN_REQ with invalid bss type")); retCode = eSIR_SME_INVALID_PARAMETERS; goto end; } @@ -1682,7 +1711,7 @@ __limProcessSmeJoinReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) val = sizeof(tLimMlmJoinReq) + psessionEntry->pLimJoinReq->bssDescription.length + 2; if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pMlmJoinReq, val)) { - limLog(pMac, LOGP, FL("call to palAllocateMemory failed for mlmJoinReq\n")); + limLog(pMac, LOGP, FL("call to palAllocateMemory failed for mlmJoinReq")); return; } (void) palZeroMemory(pMac->hHdd, (void *) pMlmJoinReq, val); @@ -1692,7 +1721,7 @@ __limProcessSmeJoinReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if (wlan_cfgGetInt(pMac, WNI_CFG_JOIN_FAILURE_TIMEOUT, (tANI_U32 *) &pMlmJoinReq->joinFailureTimeout) != eSIR_SUCCESS) - limLog(pMac, LOGP, FL("could not retrieve JoinFailureTimer value\n")); + limLog(pMac, LOGP, FL("could not retrieve JoinFailureTimer value")); /* copy operational rate from psessionEntry*/ palCopyMemory(pMac->hHdd, (void*)&psessionEntry->rateSet, (void*)&pSmeJoinReq->operationalRateSet, @@ -1738,7 +1767,7 @@ __limProcessSmeJoinReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if (pMac->lim.gLimCurrentBssUapsd) { pMac->lim.gUapsdPerAcBitmask = psessionEntry->pLimJoinReq->uapsdPerAcBitmask; - limLog( pMac, LOG1, FL("UAPSD flag for all AC - 0x%2x\n"), pMac->lim.gUapsdPerAcBitmask); + limLog( pMac, LOG1, FL("UAPSD flag for all AC - 0x%2x"), pMac->lim.gUapsdPerAcBitmask); // resetting the dynamic uapsd mask pMac->lim.gUapsdPerAcDeliveryEnableMask = 0; @@ -1751,7 +1780,7 @@ __limProcessSmeJoinReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if(SIR_BAND_5_GHZ == psessionEntry->limRFBand) { if (wlan_cfgGetInt(pMac, WNI_CFG_11H_ENABLED, &val) != eSIR_SUCCESS) - limLog(pMac, LOGP, FL("Fail to get WNI_CFG_11H_ENABLED \n")); + limLog(pMac, LOGP, FL("Fail to get WNI_CFG_11H_ENABLED ")); psessionEntry->lim11hEnable = val; } else @@ -1764,7 +1793,7 @@ __limProcessSmeJoinReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) psessionEntry->limSmeState = eLIM_SME_WT_JOIN_STATE; MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId, psessionEntry->limSmeState)); - PELOG1(limLog(pMac, LOG1, FL("SME JoinReq: SSID %d.%c%c%c%c%c%c\n"), + PELOG1(limLog(pMac, LOG1, FL("SME JoinReq: SSID %d.%c%c%c%c%c%c"), psessionEntry->ssId.length, psessionEntry->ssId.ssId[0], psessionEntry->ssId.ssId[1], @@ -1772,7 +1801,7 @@ __limProcessSmeJoinReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) psessionEntry->ssId.ssId[3], psessionEntry->ssId.ssId[4], psessionEntry->ssId.ssId[5]); - limLog(pMac, LOG1, FL("Channel %d, BSSID %x:%x:%x:%x:%x:%x\n"), + limLog(pMac, LOG1, FL("Channel %d, BSSID %x:%x:%x:%x:%x:%x"), psessionEntry->currentOperChannel, psessionEntry->bssId[0], psessionEntry->bssId[1], @@ -1792,7 +1821,7 @@ __limProcessSmeJoinReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) else { /* Received eWNI_SME_JOIN_REQ un expected state */ - limLog(pMac, LOGE, FL("received unexpected SME_JOIN_REQ in state %X\n"), pMac->lim.gLimSmeState); + limLog(pMac, LOGE, FL("received unexpected SME_JOIN_REQ in state %X"), pMac->lim.gLimSmeState); limPrintSmeState(pMac, LOGE, pMac->lim.gLimSmeState); retCode = eSIR_SME_UNEXPECTED_REQ_RESULT_CODE; psessionEntry = NULL; @@ -1878,14 +1907,14 @@ __limProcessSmeReassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) tANI_U16 nSize; - PELOG3(limLog(pMac, LOG3, FL("Received REASSOC_REQ\n"));) + PELOG3(limLog(pMac, LOG3, FL("Received REASSOC_REQ"));) nSize = __limGetSmeJoinReqSizeForAlloc((tANI_U8 *) pMsgBuf); if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pReassocReq, nSize )) { // Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for pReassocReq\n")); + FL("call to palAllocateMemory failed for pReassocReq")); retCode = eSIR_SME_RESOURCES_UNAVAILABLE; goto end; @@ -1899,7 +1928,7 @@ __limProcessSmeReassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) /// Received invalid eWNI_SME_REASSOC_REQ // Log the event limLog(pMac, LOGW, - FL("received SME_REASSOC_REQ with invalid data\n")); + FL("received SME_REASSOC_REQ with invalid data")); retCode = eSIR_SME_INVALID_PARAMETERS; goto end; @@ -1908,7 +1937,7 @@ __limProcessSmeReassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if((psessionEntry = peFindSessionByBssid(pMac,pReassocReq->bssDescription.bssId,&sessionId))==NULL) { limPrintMacAddr(pMac, pReassocReq->bssDescription.bssId, LOGE); - limLog(pMac, LOGP, FL("Session does not exist for given bssId\n")); + limLog(pMac, LOGP, FL("Session does not exist for given bssId")); retCode = eSIR_SME_INVALID_PARAMETERS; goto end; } @@ -1941,7 +1970,7 @@ __limProcessSmeReassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) { limPrintMacAddr(pMac, pReassocReq->bssDescription.bssId, LOGE); limPrintMacAddr(pMac, pMac->ft.ftPEContext.pFTPreAuthReq->preAuthbssId, LOGE); - limLog(pMac, LOGP, FL("Unknown bssId in reassoc state\n")); + limLog(pMac, LOGP, FL("Unknown bssId in reassoc state")); retCode = eSIR_SME_INVALID_PARAMETERS; goto end; } @@ -1953,7 +1982,7 @@ __limProcessSmeReassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) /// Should not have received eWNI_SME_REASSOC_REQ // Log the event limLog(pMac, LOGE, - FL("received unexpected SME_REASSOC_REQ in state %X\n"), + FL("received unexpected SME_REASSOC_REQ in state %X"), psessionEntry->limSmeState); limPrintSmeState(pMac, LOGE, psessionEntry->limSmeState); @@ -2001,7 +2030,7 @@ __limProcessSmeReassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) &cfgLen) != eSIR_SUCCESS) { /// Could not get SSID from CFG. Log error. - limLog(pMac, LOGP, FL("could not retrive SSID\n")); + limLog(pMac, LOGP, FL("could not retrive SSID")); } #endif//TO SUPPORT BT-AMP @@ -2020,14 +2049,14 @@ __limProcessSmeReassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if (pMac->lim.gLimCurrentBssUapsd) { pMac->lim.gUapsdPerAcBitmask = psessionEntry->pLimReAssocReq->uapsdPerAcBitmask; - limLog( pMac, LOG1, FL("UAPSD flag for all AC - 0x%2x\n"), pMac->lim.gUapsdPerAcBitmask); + limLog( pMac, LOG1, FL("UAPSD flag for all AC - 0x%2x"), pMac->lim.gUapsdPerAcBitmask); } if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pMlmReassocReq, sizeof(tLimMlmReassocReq))) { // Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for mlmReassocReq\n")); + FL("call to palAllocateMemory failed for mlmReassocReq")); retCode = eSIR_SME_RESOURCES_UNAVAILABLE; goto end; @@ -2046,7 +2075,7 @@ __limProcessSmeReassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve ReassocFailureTimeout value\n")); + FL("could not retrieve ReassocFailureTimeout value")); } if (cfgGetCapabilityInfo(pMac, &caps,psessionEntry) != eSIR_SUCCESS) @@ -2056,7 +2085,7 @@ __limProcessSmeReassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve Capabilities value\n")); + FL("could not retrieve Capabilities value")); } pMlmReassocReq->capabilityInfo = caps; @@ -2067,7 +2096,7 @@ __limProcessSmeReassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) WNI_CFG_TELE_BCN_MAX_LI */ if(wlan_cfgGetInt(pMac, WNI_CFG_TELE_BCN_WAKEUP_EN, &teleBcnEn) != eSIR_SUCCESS) - limLog(pMac, LOGP, FL("Couldn't get WNI_CFG_TELE_BCN_WAKEUP_EN\n")); + limLog(pMac, LOGP, FL("Couldn't get WNI_CFG_TELE_BCN_WAKEUP_EN")); val = WNI_CFG_LISTEN_INTERVAL_STADEF; @@ -2080,7 +2109,7 @@ __limProcessSmeReassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * Could not get ListenInterval value * from CFG. Log error. */ - limLog(pMac, LOGP, FL("could not retrieve ListenInterval\n")); + limLog(pMac, LOGP, FL("could not retrieve ListenInterval")); } } else @@ -2091,7 +2120,7 @@ __limProcessSmeReassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * Could not get ListenInterval value * from CFG. Log error. */ - limLog(pMac, LOGP, FL("could not retrieve ListenInterval\n")); + limLog(pMac, LOGP, FL("could not retrieve ListenInterval")); } } @@ -2100,7 +2129,7 @@ __limProcessSmeReassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * is lost upon disassociation and reassociation. */ - limDelAllBASessions(pMac); + limDeleteBASessions(pMac, psessionEntry, BA_BOTH_DIRECTIONS); pMlmReassocReq->listenInterval = (tANI_U16) val; @@ -2176,11 +2205,11 @@ __limProcessSmeDisassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) tANI_U8 smesessionId; tANI_U16 smetransactionId; - PELOG1(limLog(pMac, LOG1,FL("received DISASSOC_REQ message\n"));) + PELOG1(limLog(pMac, LOG1,FL("received DISASSOC_REQ message"));) if (pMsgBuf == NULL) { - limLog(pMac, LOGE, FL("Buffer is Pointing to NULL\n")); + limLog(pMac, LOGE, FL("Buffer is Pointing to NULL")); return; } @@ -2192,7 +2221,7 @@ __limProcessSmeDisassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) (!limIsSmeDisassocReqValid(pMac, &smeDisassocReq, psessionEntry)) ) { PELOGE(limLog(pMac, LOGE, - FL("received invalid SME_DISASSOC_REQ message\n"));) + FL("received invalid SME_DISASSOC_REQ message"));) if (pMac->lim.gLimRspReqd) { @@ -2207,13 +2236,13 @@ __limProcessSmeDisassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) } - PELOG1(limLog(pMac, LOG1, FL("received DISASSOC_REQ message. Reason: %d global SmeState: %d"), + PELOG1(limLog(pMac, LOG1, FL("received DISASSOC_REQ message. Reason: %d global SmeState: %d"), smeDisassocReq.reasonCode, pMac->lim.gLimSmeState);) if((psessionEntry = peFindSessionByBssid(pMac,smeDisassocReq.bssId,&sessionId))== NULL) { - limLog(pMac, LOGE,FL("session does not exist for given bssId\n")); + limLog(pMac, LOGE,FL("session does not exist for given bssId")); retCode = eSIR_SME_INVALID_PARAMETERS; disassocTrigger = eLIM_HOST_DISASSOC; goto sendDisassoc; @@ -2239,6 +2268,10 @@ __limProcessSmeDisassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) case eLIM_SME_LINK_EST_STATE: psessionEntry->limPrevSmeState = psessionEntry->limSmeState; psessionEntry->limSmeState= eLIM_SME_WT_DISASSOC_STATE; +#ifdef FEATURE_WLAN_TDLS + /* Delete all TDLS peers connected before leaving BSS*/ + limDeleteTDLSPeers(pMac, psessionEntry); +#endif MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId, psessionEntry->limSmeState)); break; @@ -2250,7 +2283,7 @@ __limProcessSmeDisassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) */ psessionEntry->limSmeState= eLIM_SME_WT_DISASSOC_STATE; MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId, psessionEntry->limSmeState)); - limLog(pMac, LOG1, FL("Rcvd SME_DISASSOC_REQ while in SME_WT_DEAUTH_STATE. \n")); + limLog(pMac, LOG1, FL("Rcvd SME_DISASSOC_REQ while in SME_WT_DEAUTH_STATE. ")); break; case eLIM_SME_WT_DISASSOC_STATE: @@ -2263,7 +2296,7 @@ __limProcessSmeDisassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * It will send a disassoc, which is ok. However, we can use the global flag * sendDisassoc to not send disassoc frame. */ - limLog(pMac, LOG1, FL("Rcvd SME_DISASSOC_REQ while in SME_WT_DISASSOC_STATE. \n")); + limLog(pMac, LOG1, FL("Rcvd SME_DISASSOC_REQ while in SME_WT_DISASSOC_STATE. ")); break; case eLIM_SME_JOIN_FAILURE_STATE: { @@ -2280,7 +2313,7 @@ __limProcessSmeDisassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * Log error and send response to host */ limLog(pMac, LOGE, - FL("received unexpected SME_DISASSOC_REQ in state %X\n"), + FL("received unexpected SME_DISASSOC_REQ in state %X"), psessionEntry->limSmeState); limPrintSmeState(pMac, LOGE, psessionEntry->limSmeState); @@ -2308,7 +2341,7 @@ __limProcessSmeDisassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) case eLIM_STA_IN_IBSS_ROLE: default: // eLIM_UNKNOWN_ROLE limLog(pMac, LOGE, - FL("received unexpected SME_DISASSOC_REQ for role %d\n"), + FL("received unexpected SME_DISASSOC_REQ for role %d"), psessionEntry->limSystemRole); retCode = eSIR_SME_UNEXPECTED_REQ_RESULT_CODE; @@ -2337,7 +2370,7 @@ __limProcessSmeDisassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) { // Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for mlmDisassocReq\n")); + FL("call to palAllocateMemory failed for mlmDisassocReq")); return; } @@ -2395,25 +2428,25 @@ __limProcessSmeDisassocCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) tANI_U8 sessionId; - PELOG1(limLog(pMac, LOG1, FL("received DISASSOC_CNF message\n"));) + PELOG1(limLog(pMac, LOG1, FL("received DISASSOC_CNF message"));) status = limDisassocCnfSerDes(pMac, &smeDisassocCnf,(tANI_U8 *) pMsgBuf); if (status == eSIR_FAILURE) { - PELOGE(limLog(pMac, LOGE, FL("invalid SME_DISASSOC_CNF message\n"));) + PELOGE(limLog(pMac, LOGE, FL("invalid SME_DISASSOC_CNF message"));) return; } if((psessionEntry = peFindSessionByBssid(pMac, smeDisassocCnf.bssId, &sessionId))== NULL) { - limLog(pMac, LOGE,FL("session does not exist for given bssId\n")); + limLog(pMac, LOGE,FL("session does not exist for given bssId")); return; } if (!limIsSmeDisassocCnfValid(pMac, &smeDisassocCnf, psessionEntry)) { - limLog(pMac, LOGW, FL("received invalid SME_DISASSOC_CNF message\n")); + limLog(pMac, LOGW, FL("received invalid SME_DISASSOC_CNF message")); return; } @@ -2433,7 +2466,7 @@ __limProcessSmeDisassocCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) (psessionEntry->limSmeState != eLIM_SME_WT_DEAUTH_STATE)) { limLog(pMac, LOGE, - FL("received unexp SME_DISASSOC_CNF in state %X\n"), + FL("received unexp SME_DISASSOC_CNF in state %X"), psessionEntry->limSmeState); limPrintSmeState(pMac, LOGE, psessionEntry->limSmeState); return; @@ -2447,7 +2480,7 @@ __limProcessSmeDisassocCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) case eLIM_STA_IN_IBSS_ROLE: default: // eLIM_UNKNOWN_ROLE limLog(pMac, LOGE, - FL("received unexpected SME_DISASSOC_CNF role %d\n"), + FL("received unexpected SME_DISASSOC_CNF role %d"), psessionEntry->limSystemRole); return; @@ -2508,7 +2541,7 @@ __limProcessSmeDeauthReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) tANI_U8 smesessionId; tANI_U16 smetransactionId; - PELOG1(limLog(pMac, LOG1,FL("received DEAUTH_REQ message\n"));) + PELOG1(limLog(pMac, LOG1,FL("received DEAUTH_REQ message"));) status = limDeauthReqSerDes(pMac, &smeDeauthReq,(tANI_U8 *) pMsgBuf); @@ -2517,7 +2550,7 @@ __limProcessSmeDeauthReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) //We need to get a session first but we don't even know if the message is correct. if((psessionEntry = peFindSessionByBssid(pMac, smeDeauthReq.bssId, &sessionId)) == NULL) { - limLog(pMac, LOGE,FL("session does not exist for given bssId\n")); + limLog(pMac, LOGE,FL("session does not exist for given bssId")); retCode = eSIR_SME_INVALID_PARAMETERS; deauthTrigger = eLIM_HOST_DEAUTH; goto sendDeauth; @@ -2526,7 +2559,7 @@ __limProcessSmeDeauthReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if ((status == eSIR_FAILURE) || (!limIsSmeDeauthReqValid(pMac, &smeDeauthReq, psessionEntry))) { - PELOGE(limLog(pMac, LOGW,FL("received invalid SME_DEAUTH_REQ message\n"));) + PELOGE(limLog(pMac, LOGW,FL("received invalid SME_DEAUTH_REQ message"));) if (pMac->lim.gLimRspReqd) { pMac->lim.gLimRspReqd = false; @@ -2574,7 +2607,7 @@ __limProcessSmeDeauthReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * peer. Log error and send response to host. */ limLog(pMac, LOGE, - FL("received unexp SME_DEAUTH_REQ in state %X\n"),psessionEntry->limSmeState); + FL("received unexp SME_DEAUTH_REQ in state %X"),psessionEntry->limSmeState); limPrintSmeState(pMac, LOGE, psessionEntry->limSmeState); if (pMac->lim.gLimRspReqd) @@ -2602,7 +2635,7 @@ __limProcessSmeDeauthReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) default: limLog(pMac, LOGE, - FL("received unexpected SME_DEAUTH_REQ for role %X\n"),psessionEntry->limSystemRole); + FL("received unexpected SME_DEAUTH_REQ for role %X"),psessionEntry->limSystemRole); return; } // end switch (pMac->lim.gLimSystemRole) @@ -2610,7 +2643,7 @@ __limProcessSmeDeauthReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if (smeDeauthReq.reasonCode == eLIM_LINK_MONITORING_DEAUTH) { /// Deauthentication is triggered by Link Monitoring - PELOG1(limLog(pMac, LOG1, FL("**** Lost link with AP ****\n"));) + PELOG1(limLog(pMac, LOG1, FL("**** Lost link with AP ****"));) deauthTrigger = eLIM_LINK_MONITORING_DEAUTH; reasonCode = eSIR_MAC_UNSPEC_FAILURE_REASON; } @@ -2625,7 +2658,7 @@ __limProcessSmeDeauthReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) { // Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for mlmDeauthReq\n")); + FL("call to palAllocateMemory failed for mlmDeauthReq")); return; } @@ -2685,12 +2718,12 @@ __limProcessSmeSetContextReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) PELOG1(limLog(pMac, LOG1, - FL("received SETCONTEXT_REQ message\n"));); + FL("received SETCONTEXT_REQ message"));); if(pMsgBuf == NULL) { - limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n")); + limLog(pMac, LOGE,FL("Buffer is Pointing to NULL")); return; } @@ -2699,20 +2732,20 @@ __limProcessSmeSetContextReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pSetContextReq, (sizeof(tSirKeys) * SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS))) { - limLog(pMac, LOGP, FL("call to palAllocateMemory failed for pSetContextReq\n")); + limLog(pMac, LOGP, FL("call to palAllocateMemory failed for pSetContextReq")); return; } if ((limSetContextReqSerDes(pMac, pSetContextReq, (tANI_U8 *) pMsgBuf) == eSIR_FAILURE) || (!limIsSmeSetContextReqValid(pMac, pSetContextReq))) { - limLog(pMac, LOGW, FL("received invalid SME_SETCONTEXT_REQ message\n")); + limLog(pMac, LOGW, FL("received invalid SME_SETCONTEXT_REQ message")); goto end; } if(pSetContextReq->keyMaterial.numKeys > SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS) { - PELOGE(limLog(pMac, LOGE, FL("numKeys:%d is more than SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS\n"), pSetContextReq->keyMaterial.numKeys);) + PELOGE(limLog(pMac, LOGE, FL("numKeys:%d is more than SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS"), pSetContextReq->keyMaterial.numKeys);) limSendSmeSetContextRsp(pMac, pSetContextReq->peerMacAddr, 1, @@ -2725,7 +2758,7 @@ __limProcessSmeSetContextReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if((psessionEntry = peFindSessionByBssid(pMac, pSetContextReq->bssId, &sessionId)) == NULL) { - limLog(pMac, LOGW, FL("Session does not exist for given BSSID\n")); + limLog(pMac, LOGW, FL("Session does not exist for given BSSID")); limSendSmeSetContextRsp(pMac, pSetContextReq->peerMacAddr, 1, @@ -2750,7 +2783,7 @@ __limProcessSmeSetContextReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pMlmSetKeysReq, sizeof(tLimMlmSetKeysReq))) { // Log error - limLog(pMac, LOGP, FL("call to palAllocateMemory failed for mlmSetKeysReq\n")); + limLog(pMac, LOGP, FL("call to palAllocateMemory failed for mlmSetKeysReq")); goto end; } @@ -2758,7 +2791,7 @@ __limProcessSmeSetContextReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) pMlmSetKeysReq->numKeys = pSetContextReq->keyMaterial.numKeys; if(pMlmSetKeysReq->numKeys > SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS) { - limLog(pMac, LOGP, FL("Num of keys exceeded max num of default keys limit\n")); + limLog(pMac, LOGP, FL("Num of keys exceeded max num of default keys limit")); goto end; } palCopyMemory( pMac->hHdd, (tANI_U8 *) &pMlmSetKeysReq->peerMacAddr, @@ -2773,7 +2806,7 @@ __limProcessSmeSetContextReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) pMlmSetKeysReq->sessionId = sessionId; #ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG PELOG1(limLog(pMac, LOG1, - FL("received SETCONTEXT_REQ message sessionId=%d\n"), pMlmSetKeysReq->sessionId);); + FL("received SETCONTEXT_REQ message sessionId=%d"), pMlmSetKeysReq->sessionId);); #endif if(((pSetContextReq->keyMaterial.edType == eSIR_ED_WEP40) || (pSetContextReq->keyMaterial.edType == eSIR_ED_WEP104)) @@ -2801,7 +2834,7 @@ __limProcessSmeSetContextReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) else { limLog(pMac, LOGE, - FL("received unexpected SME_SETCONTEXT_REQ for role %d, state=%X\n"), + FL("received unexpected SME_SETCONTEXT_REQ for role %d, state=%X"), psessionEntry->limSystemRole, psessionEntry->limSmeState); limPrintSmeState(pMac, LOGE, psessionEntry->limSmeState); @@ -2847,11 +2880,11 @@ __limProcessSmeRemoveKeyReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) tANI_U16 smetransactionId; PELOG1(limLog(pMac, LOG1, - FL("received REMOVEKEY_REQ message\n"));) + FL("received REMOVEKEY_REQ message"));) if(pMsgBuf == NULL) { - limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n")); + limLog(pMac, LOGE,FL("Buffer is Pointing to NULL")); return; } @@ -2863,7 +2896,7 @@ __limProcessSmeRemoveKeyReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) { //Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for pRemoveKeyReq\n")); + FL("call to palAllocateMemory failed for pRemoveKeyReq")); return; } @@ -2873,13 +2906,13 @@ __limProcessSmeRemoveKeyReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) (tANI_U8 *) pMsgBuf) == eSIR_FAILURE)) { limLog(pMac, LOGW, - FL("received invalid SME_REMOVECONTEXT_REQ message\n")); + FL("received invalid SME_REMOVECONTEXT_REQ message")); /* extra look up is needed since, session entry to be passed il limsendremovekey response */ if((psessionEntry = peFindSessionByBssid(pMac,pRemoveKeyReq->bssId,&sessionId))== NULL) { - limLog(pMac, LOGE,FL("session does not exist for given bssId\n")); + limLog(pMac, LOGE,FL("session does not exist for given bssId")); //goto end; } @@ -2894,7 +2927,7 @@ __limProcessSmeRemoveKeyReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if((psessionEntry = peFindSessionByBssid(pMac,pRemoveKeyReq->bssId, &sessionId))== NULL) { limLog(pMac, LOGE, - FL("session does not exist for given bssId\n")); + FL("session does not exist for given bssId")); limSendSmeRemoveKeyRsp(pMac, pRemoveKeyReq->peerMacAddr, eSIR_SME_UNEXPECTED_REQ_RESULT_CODE, NULL, @@ -2914,7 +2947,7 @@ __limProcessSmeRemoveKeyReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) { // Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for mlmRemoveKeysReq\n")); + FL("call to palAllocateMemory failed for mlmRemoveKeysReq")); goto end; } @@ -2939,7 +2972,7 @@ __limProcessSmeRemoveKeyReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) else { limLog(pMac, LOGE, - FL("received unexpected SME_REMOVEKEY_REQ for role %d, state=%X\n"), + FL("received unexpected SME_REMOVEKEY_REQ for role %d, state=%X"), psessionEntry->limSystemRole, psessionEntry->limSmeState); limPrintSmeState(pMac, LOGE, psessionEntry->limSmeState); @@ -2962,13 +2995,13 @@ void limProcessSmeGetScanChannelInfo(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if(pMac->lim.scanChnInfo.numChnInfo > SIR_MAX_SUPPORTED_CHANNEL_LIST) { - limLog(pMac, LOGW, FL("numChn is out of bounds %d\n"), + limLog(pMac, LOGW, FL("numChn is out of bounds %d"), pMac->lim.scanChnInfo.numChnInfo); pMac->lim.scanChnInfo.numChnInfo = SIR_MAX_SUPPORTED_CHANNEL_LIST; } PELOG2(limLog(pMac, LOG2, - FL("Sending message %s with number of channels %d\n"), + FL("Sending message %s with number of channels %d"), limMsgStr(eWNI_SME_GET_SCANNED_CHANNEL_RSP), pMac->lim.scanChnInfo.numChnInfo);) len = sizeof(tSmeGetScanChnRsp) + (pMac->lim.scanChnInfo.numChnInfo - 1) * sizeof(tLimScanChn); @@ -2976,7 +3009,7 @@ void limProcessSmeGetScanChannelInfo(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) { /// Buffer not available. Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for JOIN/REASSOC_RSP\n")); + FL("call to palAllocateMemory failed for JOIN/REASSOC_RSP")); return; } @@ -3019,7 +3052,7 @@ void limProcessSmeGetAssocSTAsInfo(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if (!limIsSmeGetAssocSTAsReqValid(pMac, &getAssocSTAsReq, (tANI_U8 *) pMsgBuf)) { limLog(pMac, LOGE, - FL("received invalid eWNI_SME_GET_ASSOC_STAS_REQ message\n")); + FL("received invalid eWNI_SME_GET_ASSOC_STAS_REQ message")); goto limAssocStaEnd; } @@ -3044,14 +3077,14 @@ void limProcessSmeGetAssocSTAsInfo(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if ((psessionEntry = peFindSessionByBssid(pMac, getAssocSTAsReq.bssId, &sessionId)) == NULL) { limLog(pMac, LOGE, - FL("session does not exist for given bssId\n")); + FL("session does not exist for given bssId")); goto limAssocStaEnd; } if (psessionEntry->limSystemRole != eLIM_AP_ROLE) { limLog(pMac, LOGE, - FL("Received unexpected message in state %X, in role %X\n"), + FL("Received unexpected message in state %X, in role %X"), psessionEntry->limSmeState , psessionEntry->limSystemRole); goto limAssocStaEnd; } @@ -3137,7 +3170,7 @@ void limProcessSmeGetWPSPBCSessions(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if (limIsSmeGetWPSPBCSessionsReqValid(pMac, &GetWPSPBCSessionsReq, (tANI_U8 *) pMsgBuf) != eSIR_SUCCESS) { limLog(pMac, LOGE, - FL("received invalid eWNI_SME_GET_ASSOC_STAS_REQ message\n")); + FL("received invalid eWNI_SME_GET_ASSOC_STAS_REQ message")); goto limGetWPSPBCSessionsEnd; } @@ -3146,14 +3179,14 @@ void limProcessSmeGetWPSPBCSessions(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if ((psessionEntry = peFindSessionByBssid(pMac, GetWPSPBCSessionsReq.bssId, &sessionId)) == NULL) { limLog(pMac, LOGE, - FL("session does not exist for given bssId\n")); + FL("session does not exist for given bssId")); goto limGetWPSPBCSessionsEnd; } if (psessionEntry->limSystemRole != eLIM_AP_ROLE) { limLog(pMac, LOGE, - FL("Received unexpected message in role %X\n"), + FL("Received unexpected message in role %X"), psessionEntry->limSystemRole); goto limGetWPSPBCSessionsEnd; } @@ -3176,7 +3209,7 @@ void limProcessSmeGetWPSPBCSessions(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) return; } - PELOG4(limLog(pMac, LOGE, FL("wpsPBCOverlap %d\n"), sapEvent.sapevt.sapGetWPSPBCSessionEvent.wpsPBCOverlap);) + PELOG4(limLog(pMac, LOGE, FL("wpsPBCOverlap %d"), sapEvent.sapevt.sapGetWPSPBCSessionEvent.wpsPBCOverlap);) PELOG4(limPrintMacAddr(pMac, sapEvent.sapevt.sapGetWPSPBCSessionEvent.addr.bytes, LOG4);) sapEvent.sapevt.sapGetWPSPBCSessionEvent.status = VOS_STATUS_SUCCESS; @@ -3229,13 +3262,13 @@ limProcessTkipCounterMeasures(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if ( limTkipCntrMeasReqSerDes( pMac, &tkipCntrMeasReq, (tANI_U8 *) pMsgBuf ) != eSIR_SUCCESS ) { limLog(pMac, LOGE, - FL("received invalid eWNI_SME_TKIP_CNTR_MEAS_REQ message\n")); + FL("received invalid eWNI_SME_TKIP_CNTR_MEAS_REQ message")); return; } if ( NULL == (psessionEntry = peFindSessionByBssid( pMac, tkipCntrMeasReq.bssId, &sessionId )) ) { - limLog(pMac, LOGE, FL("session does not exist for given BSSID \n")); + limLog(pMac, LOGE, FL("session does not exist for given BSSID ")); return; } @@ -3266,7 +3299,7 @@ __limHandleSmeStopBssRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if ((limStopBssReqSerDes(pMac, &stopBssReq, (tANI_U8 *) pMsgBuf) != eSIR_SUCCESS) || !limIsSmeStopBssReqValid(pMsgBuf)) { - PELOGW(limLog(pMac, LOGW, FL("received invalid SME_STOP_BSS_REQ message\n"));) + PELOGW(limLog(pMac, LOGW, FL("received invalid SME_STOP_BSS_REQ message"));) /// Send Stop BSS response to host limSendSmeRsp(pMac, eWNI_SME_STOP_BSS_RSP, eSIR_SME_INVALID_PARAMETERS,smesessionId,smetransactionId); return; @@ -3275,7 +3308,7 @@ __limHandleSmeStopBssRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if((psessionEntry = peFindSessionByBssid(pMac,stopBssReq.bssId,&sessionId)) == NULL) { - limLog(pMac, LOGW, FL("session does not exist for given BSSID \n")); + limLog(pMac, LOGW, FL("session does not exist for given BSSID ")); limSendSmeRsp(pMac, eWNI_SME_STOP_BSS_RSP, eSIR_SME_INVALID_PARAMETERS,smesessionId,smetransactionId); return; } @@ -3294,7 +3327,7 @@ __limHandleSmeStopBssRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * mode. Log error and return response to host. */ limLog(pMac, LOGE, - FL("received unexpected SME_STOP_BSS_REQ in state %X, for role %d\n"), + FL("received unexpected SME_STOP_BSS_REQ in state %X, for role %d"), psessionEntry->limSmeState, psessionEntry->limSystemRole); limPrintSmeState(pMac, LOGE, psessionEntry->limSmeState); /// Send Stop BSS response to host @@ -3306,7 +3339,7 @@ __limHandleSmeStopBssRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) { limWPSPBCClose(pMac, psessionEntry); } - PELOGW(limLog(pMac, LOGW, FL("RECEIVED STOP_BSS_REQ with reason code=%d\n"), stopBssReq.reasonCode);) + PELOGW(limLog(pMac, LOGW, FL("RECEIVED STOP_BSS_REQ with reason code=%d"), stopBssReq.reasonCode);) prevState = psessionEntry->limSmeState; @@ -3336,7 +3369,7 @@ __limHandleSmeStopBssRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if (status != eSIR_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("delBss failed for bss %d\n"), psessionEntry->bssIdx);) + PELOGE(limLog(pMac, LOGE, FL("delBss failed for bss %d"), psessionEntry->bssIdx);) psessionEntry->limSmeState= prevState; MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId, psessionEntry->limSmeState)); @@ -3413,27 +3446,27 @@ __limProcessSmeAssocCnfNew(tpAniSirGlobal pMac, tANI_U32 msgType, tANI_U32 *pMsg if(pMsgBuf == NULL) { - limLog(pMac, LOGE, FL("pMsgBuf is NULL \n")); + limLog(pMac, LOGE, FL("pMsgBuf is NULL ")); goto end; } if ((limAssocCnfSerDes(pMac, &assocCnf, (tANI_U8 *) pMsgBuf) == eSIR_FAILURE) || !__limIsSmeAssocCnfValid(&assocCnf)) { - limLog(pMac, LOGE, FL("Received invalid SME_RE(ASSOC)_CNF message \n")); + limLog(pMac, LOGE, FL("Received invalid SME_RE(ASSOC)_CNF message ")); goto end; } if((psessionEntry = peFindSessionByBssid(pMac, assocCnf.bssId, &sessionId))== NULL) { - limLog(pMac, LOGE, FL("session does not exist for given bssId\n")); + limLog(pMac, LOGE, FL("session does not exist for given bssId")); goto end; } if ( ((psessionEntry->limSystemRole != eLIM_AP_ROLE) && (psessionEntry->limSystemRole != eLIM_BT_AMP_AP_ROLE)) || ((psessionEntry->limSmeState != eLIM_SME_NORMAL_STATE) && (psessionEntry->limSmeState != eLIM_SME_NORMAL_CHANNEL_SCAN_STATE))) { - limLog(pMac, LOGE, FL("Received unexpected message %X in state %X, in role %X\n"), + limLog(pMac, LOGE, FL("Received unexpected message %X in state %X, in role %X"), msgType, psessionEntry->limSmeState , psessionEntry->limSystemRole); goto end; } @@ -3476,7 +3509,7 @@ __limProcessSmeAssocCnfNew(tpAniSirGlobal pMac, tANI_U32 msgType, tANI_U32 *pMsg ** Deactivate/delet CNF_WAIT timer since ASSOC_CNF ** has been received **/ - limLog(pMac, LOG1, FL("Received SME_ASSOC_CNF. Delete Timer\n")); + limLog(pMac, LOG1, FL("Received SME_ASSOC_CNF. Delete Timer")); limDeactivateAndChangePerStaIdTimer(pMac, eLIM_CNF_WAIT_TIMER, pStaDs->assocId); if (assocCnf.statusCode == eSIR_SME_SUCCESS) @@ -3486,7 +3519,7 @@ __limProcessSmeAssocCnfNew(tpAniSirGlobal pMac, tANI_U32 msgType, tANI_U32 *pMsg * Association Response frame to the requesting BTAMP-STA. */ pStaDs->mlmStaContext.mlmState = eLIM_MLM_LINK_ESTABLISHED_STATE; - limLog(pMac, LOG1, FL("sending Assoc Rsp frame to STA (assoc id=%d) \n"), pStaDs->assocId); + limLog(pMac, LOG1, FL("sending Assoc Rsp frame to STA (assoc id=%d) "), pStaDs->assocId); limSendAssocRspMgmtFrame( pMac, eSIR_SUCCESS, pStaDs->assocId, pStaDs->staAddr, pStaDs->mlmStaContext.subType, pStaDs, psessionEntry); goto end; @@ -3541,7 +3574,7 @@ __limProcessSmeAddtsReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if(pMsgBuf == NULL) { - limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n")); + limLog(pMac, LOGE,FL("Buffer is Pointing to NULL")); return; } @@ -3551,7 +3584,7 @@ __limProcessSmeAddtsReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if((psessionEntry = peFindSessionByBssid(pMac, pSirAddts->bssId,&sessionId))== NULL) { - limLog(pMac, LOGE, "Session Does not exist for given bssId\n"); + limLog(pMac, LOGE, "Session Does not exist for given bssId"); return; } #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT @@ -3567,13 +3600,13 @@ __limProcessSmeAddtsReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * if ap, just ignore with error log */ PELOG1(limLog(pMac, LOG1, - FL("Received SME_ADDTS_REQ (TSid %d, UP %d)\n"), + FL("Received SME_ADDTS_REQ (TSid %d, UP %d)"), pSirAddts->req.tspec.tsinfo.traffic.tsid, pSirAddts->req.tspec.tsinfo.traffic.userPrio);) if ((psessionEntry->limSystemRole != eLIM_STA_ROLE)&&(psessionEntry->limSystemRole != eLIM_BT_AMP_STA_ROLE)) { - PELOGE(limLog(pMac, LOGE, "AddTs received on AP - ignoring\n");) + PELOGE(limLog(pMac, LOGE, "AddTs received on AP - ignoring");) limSendSmeAddtsRsp(pMac, pSirAddts->rspReqd, eSIR_FAILURE, psessionEntry, pSirAddts->req.tspec, smesessionId,smetransactionId); return; @@ -3582,7 +3615,7 @@ __limProcessSmeAddtsReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) //Ignore the request if STA is in 11B mode. if(psessionEntry->dot11mode == WNI_CFG_DOT11_MODE_11B) { - PELOGE(limLog(pMac, LOGE, "AddTS received while Dot11Mode is 11B - ignoring\n");) + PELOGE(limLog(pMac, LOGE, "AddTS received while Dot11Mode is 11B - ignoring");) limSendSmeAddtsRsp(pMac, pSirAddts->rspReqd, eSIR_FAILURE, psessionEntry, pSirAddts->req.tspec, smesessionId,smetransactionId); return; @@ -3593,7 +3626,7 @@ __limProcessSmeAddtsReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if(pStaDs == NULL) { - PELOGE(limLog(pMac, LOGE, "Cannot find AP context for addts req\n");) + PELOGE(limLog(pMac, LOGE, "Cannot find AP context for addts req");) limSendSmeAddtsRsp(pMac, pSirAddts->rspReqd, eSIR_FAILURE, psessionEntry, pSirAddts->req.tspec, smesessionId,smetransactionId); return; @@ -3602,7 +3635,7 @@ __limProcessSmeAddtsReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if ((! pStaDs->valid) || (pStaDs->mlmStaContext.mlmState != eLIM_MLM_LINK_ESTABLISHED_STATE)) { - PELOGE(limLog(pMac, LOGE, "AddTs received in invalid MLM state\n");) + PELOGE(limLog(pMac, LOGE, "AddTs received in invalid MLM state");) limSendSmeAddtsRsp(pMac, pSirAddts->rspReqd, eSIR_FAILURE, psessionEntry, pSirAddts->req.tspec, smesessionId,smetransactionId); return; @@ -3621,7 +3654,7 @@ __limProcessSmeAddtsReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) pSirAddts->req.lleTspecPresent = 1; else { - PELOGW(limLog(pMac, LOGW, FL("ADDTS_REQ ignore - qos is disabled\n"));) + PELOGW(limLog(pMac, LOGW, FL("ADDTS_REQ ignore - qos is disabled"));) limSendSmeAddtsRsp(pMac, pSirAddts->rspReqd, eSIR_FAILURE, psessionEntry, pSirAddts->req.tspec, smesessionId,smetransactionId); return; @@ -3630,7 +3663,7 @@ __limProcessSmeAddtsReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if ((psessionEntry->limSmeState != eLIM_SME_ASSOCIATED_STATE) && (psessionEntry->limSmeState != eLIM_SME_LINK_EST_STATE)) { - limLog(pMac, LOGE, "AddTs received in invalid LIMsme state (%d)\n", + limLog(pMac, LOGE, "AddTs received in invalid LIMsme state (%d)", psessionEntry->limSmeState); limSendSmeAddtsRsp(pMac, pSirAddts->rspReqd, eSIR_FAILURE, psessionEntry, pSirAddts->req.tspec, smesessionId,smetransactionId); @@ -3639,7 +3672,7 @@ __limProcessSmeAddtsReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if (pMac->lim.gLimAddtsSent) { - limLog(pMac, LOGE, "Addts (token %d, tsid %d, up %d) is still pending\n", + limLog(pMac, LOGE, "Addts (token %d, tsid %d, up %d) is still pending", pMac->lim.gLimAddtsReq.req.dialogToken, pMac->lim.gLimAddtsReq.req.tspec.tsinfo.traffic.tsid, pMac->lim.gLimAddtsReq.req.tspec.tsinfo.traffic.userPrio); @@ -3653,7 +3686,7 @@ __limProcessSmeAddtsReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if (wlan_cfgGetStr(pMac, WNI_CFG_BSSID, peerMac, &val) != eSIR_SUCCESS) { /// Could not get BSSID from CFG. Log error. - limLog(pMac, LOGP, FL("could not retrieve BSSID\n")); + limLog(pMac, LOGP, FL("could not retrieve BSSID")); return; } #endif @@ -3666,14 +3699,14 @@ __limProcessSmeAddtsReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) // ship out the message now limSendAddtsReqActionFrame(pMac, peerMac, &pSirAddts->req, psessionEntry); - PELOG1(limLog(pMac, LOG1, "Sent ADDTS request\n");) + PELOG1(limLog(pMac, LOG1, "Sent ADDTS request");) // start a timer to wait for the response if (pSirAddts->timeout) timeout = pSirAddts->timeout; else if (wlan_cfgGetInt(pMac, WNI_CFG_ADDTS_RSP_TIMEOUT, &timeout) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("Unable to get Cfg param %d (Addts Rsp Timeout)\n"), + limLog(pMac, LOGP, FL("Unable to get Cfg param %d (Addts Rsp Timeout)"), WNI_CFG_ADDTS_RSP_TIMEOUT); return; } @@ -3681,14 +3714,14 @@ __limProcessSmeAddtsReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) timeout = SYS_MS_TO_TICKS(timeout); if (tx_timer_change(&pMac->lim.limTimers.gLimAddtsRspTimer, timeout, 0) != TX_SUCCESS) { - limLog(pMac, LOGP, FL("AddtsRsp timer change failed!\n")); + limLog(pMac, LOGP, FL("AddtsRsp timer change failed!")); return; } pMac->lim.gLimAddtsRspTimerCount++; if (tx_timer_change_context(&pMac->lim.limTimers.gLimAddtsRspTimer, pMac->lim.gLimAddtsRspTimerCount) != TX_SUCCESS) { - limLog(pMac, LOGP, FL("AddtsRsp timer change failed!\n")); + limLog(pMac, LOGP, FL("AddtsRsp timer change failed!")); return; } MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, psessionEntry->peSessionId, eLIM_ADDTS_RSP_TIMER)); @@ -3697,7 +3730,7 @@ __limProcessSmeAddtsReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) pMac->lim.limTimers.gLimAddtsRspTimer.sessionId = sessionId; if (tx_timer_activate(&pMac->lim.limTimers.gLimAddtsRspTimer) != TX_SUCCESS) { - limLog(pMac, LOGP, FL("AddtsRsp timer activation failed!\n")); + limLog(pMac, LOGP, FL("AddtsRsp timer activation failed!")); return; } return; @@ -3722,7 +3755,7 @@ __limProcessSmeDeltsReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if((psessionEntry = peFindSessionByBssid(pMac, pDeltsReq->bssId, &sessionId))== NULL) { - limLog(pMac, LOGE, "Session Does not exist for given bssId\n"); + limLog(pMac, LOGE, "Session Does not exist for given bssId"); status = eSIR_FAILURE; goto end; } @@ -3733,13 +3766,13 @@ __limProcessSmeDeltsReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if (eSIR_SUCCESS != limValidateDeltsReq(pMac, pDeltsReq, peerMacAddr,psessionEntry)) { - PELOGE(limLog(pMac, LOGE, FL("limValidateDeltsReq failed\n"));) + PELOGE(limLog(pMac, LOGE, FL("limValidateDeltsReq failed"));) status = eSIR_FAILURE; limSendSmeDeltsRsp(pMac, pDeltsReq, eSIR_FAILURE,psessionEntry,smesessionId,smetransactionId); return; } - PELOG1(limLog(pMac, LOG1, FL("Sent DELTS request to station with assocId = %d MacAddr = %x:%x:%x:%x:%x:%x\n"), + PELOG1(limLog(pMac, LOG1, FL("Sent DELTS request to station with assocId = %d MacAddr = %x:%x:%x:%x:%x:%x"), pDeltsReq->aid, peerMacAddr[0], peerMacAddr[1], peerMacAddr[2], peerMacAddr[3], peerMacAddr[4], peerMacAddr[5]);) @@ -3789,7 +3822,7 @@ __limProcessSmeDeltsReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) } else { - limLog(pMac, LOGE, FL("Self entry missing in Hash Table \n")); + limLog(pMac, LOGE, FL("Self entry missing in Hash Table ")); status = eSIR_FAILURE; } #ifdef FEATURE_WLAN_CCX @@ -3809,26 +3842,26 @@ limProcessSmeAddtsRspTimeout(tpAniSirGlobal pMac, tANI_U32 param) tpPESession psessionEntry; if((psessionEntry = peFindSessionBySessionId(pMac, pMac->lim.limTimers.gLimAddtsRspTimer.sessionId))== NULL) { - limLog(pMac, LOGP,FL("Session Does not exist for given sessionID\n")); + limLog(pMac, LOGP,FL("Session Does not exist for given sessionID")); return; } if ( (psessionEntry->limSystemRole != eLIM_STA_ROLE) && (psessionEntry->limSystemRole != eLIM_BT_AMP_STA_ROLE) ) { - limLog(pMac, LOGW, "AddtsRspTimeout in non-Sta role (%d)\n", psessionEntry->limSystemRole); + limLog(pMac, LOGW, "AddtsRspTimeout in non-Sta role (%d)", psessionEntry->limSystemRole); pMac->lim.gLimAddtsSent = false; return; } if (! pMac->lim.gLimAddtsSent) { - PELOGW(limLog(pMac, LOGW, "AddtsRspTimeout but no AddtsSent\n");) + PELOGW(limLog(pMac, LOGW, "AddtsRspTimeout but no AddtsSent");) return; } if (param != pMac->lim.gLimAddtsRspTimerCount) { - limLog(pMac, LOGE, FL("Invalid AddtsRsp Timer count %d (exp %d)\n"), + limLog(pMac, LOGE, FL("Invalid AddtsRsp Timer count %d (exp %d)"), param, pMac->lim.gLimAddtsRspTimerCount); return; } @@ -3865,7 +3898,7 @@ __limProcessSmeStatsRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if(pMsgBuf == NULL) { - limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n")); + limLog(pMac, LOGE,FL("Buffer is Pointing to NULL")); return; } @@ -3873,7 +3906,7 @@ __limProcessSmeStatsRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if((psessionEntry = peFindSessionByBssid(pMac,pStatsReq->bssId,&sessionId))== NULL) { - limLog(pMac, LOGE, FL("session does not exist for given bssId\n")); + limLog(pMac, LOGE, FL("session does not exist for given bssId")); palFreeMemory( pMac, pMsgBuf ); return; } @@ -3898,7 +3931,7 @@ __limProcessSmeStatsRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) msgQ.type = WDA_STAT_SUMM_REQ; break; default: //Unknown request. - PELOGE(limLog(pMac, LOGE, "Unknown Statistics request\n");) + PELOGE(limLog(pMac, LOGE, "Unknown Statistics request");) palFreeMemory( pMac, pMsgBuf ); return; } @@ -3925,7 +3958,7 @@ __limProcessSmeStatsRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, msgQ.type)); } if( eSIR_SUCCESS != (wdaPostCtrlMsg( pMac, &msgQ ))){ - limLog(pMac, LOGP, "Unable to forward request\n"); + limLog(pMac, LOGP, "Unable to forward request"); palFreeMemory( pMac, pMsgBuf ); return; } @@ -3975,7 +4008,7 @@ __limProcessSmeGetStatisticsRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if( eSIR_SUCCESS != (wdaPostCtrlMsg( pMac, &msgQ ))){ palFreeMemory( pMac, pMsgBuf ); - limLog(pMac, LOGP, "Unable to forward request\n"); + limLog(pMac, LOGP, "Unable to forward request"); return; } @@ -4022,7 +4055,7 @@ __limProcessSmeGetRoamRssiRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if( eSIR_SUCCESS != (wdaPostCtrlMsg( pMac, &msgQ ))){ palFreeMemory( pMac, pMsgBuf ); - limLog(pMac, LOGP, "Unable to forward request\n"); + limLog(pMac, LOGP, "Unable to forward request"); return; } @@ -4039,29 +4072,29 @@ __limProcessSmeUpdateAPWPSIEs(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) tANI_U8 sessionId; //PE sessionID PELOG1(limLog(pMac, LOG1, - FL("received UPDATE_APWPSIEs_REQ message\n"));); + FL("received UPDATE_APWPSIEs_REQ message"));); if(pMsgBuf == NULL) { - limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n")); + limLog(pMac, LOGE,FL("Buffer is Pointing to NULL")); return; } if( palAllocateMemory( pMac->hHdd, (void **)&pUpdateAPWPSIEsReq, sizeof(tSirUpdateAPWPSIEsReq))) { - limLog(pMac, LOGP, FL("call to palAllocateMemory failed for pUpdateAPWPSIEsReq\n")); + limLog(pMac, LOGP, FL("call to palAllocateMemory failed for pUpdateAPWPSIEsReq")); return; } if ((limUpdateAPWPSIEsReqSerDes(pMac, pUpdateAPWPSIEsReq, (tANI_U8 *) pMsgBuf) == eSIR_FAILURE)) { - limLog(pMac, LOGW, FL("received invalid SME_SETCONTEXT_REQ message\n")); + limLog(pMac, LOGW, FL("received invalid SME_SETCONTEXT_REQ message")); goto end; } if((psessionEntry = peFindSessionByBssid(pMac, pUpdateAPWPSIEsReq->bssId, &sessionId)) == NULL) { - limLog(pMac, LOGW, FL("Session does not exist for given BSSID\n")); + limLog(pMac, LOGW, FL("Session does not exist for given BSSID")); goto end; } @@ -4082,11 +4115,11 @@ __limProcessSmeHideSSID(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) tpPESession psessionEntry; PELOG1(limLog(pMac, LOG1, - FL("received HIDE_SSID message\n"));); + FL("received HIDE_SSID message"));); if(pMsgBuf == NULL) { - limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n")); + limLog(pMac, LOGE,FL("Buffer is Pointing to NULL")); return; } @@ -4094,7 +4127,7 @@ __limProcessSmeHideSSID(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if((psessionEntry = peFindSessionBySessionId(pMac, pUpdateParams->sessionId)) == NULL) { - limLog(pMac, LOGW, "Session does not exist for given sessionId %d\n", + limLog(pMac, LOGW, "Session does not exist for given sessionId %d", pUpdateParams->sessionId); return; } @@ -4118,25 +4151,25 @@ __limProcessSmeSetWPARSNIEs(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if(pMsgBuf == NULL) { - limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n")); + limLog(pMac, LOGE,FL("Buffer is Pointing to NULL")); return; } if( palAllocateMemory( pMac->hHdd, (void **)&pUpdateAPWPARSNIEsReq, sizeof(tSirUpdateAPWPSIEsReq))) { - limLog(pMac, LOGP, FL("call to palAllocateMemory failed for pUpdateAPWPARSNIEsReq\n")); + limLog(pMac, LOGP, FL("call to palAllocateMemory failed for pUpdateAPWPARSNIEsReq")); return; } if ((limUpdateAPWPARSNIEsReqSerDes(pMac, pUpdateAPWPARSNIEsReq, (tANI_U8 *) pMsgBuf) == eSIR_FAILURE)) { - limLog(pMac, LOGW, FL("received invalid SME_SETCONTEXT_REQ message\n")); + limLog(pMac, LOGW, FL("received invalid SME_SETCONTEXT_REQ message")); goto end; } if((psessionEntry = peFindSessionByBssid(pMac, pUpdateAPWPARSNIEsReq->bssId, &sessionId)) == NULL) { - limLog(pMac, LOGW, FL("Session does not exist for given BSSID\n")); + limLog(pMac, LOGW, FL("Session does not exist for given BSSID")); goto end; } @@ -4167,11 +4200,11 @@ __limProcessSmeChangeBI(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) tUpdateBeaconParams beaconParams; PELOG1(limLog(pMac, LOG1, - FL("received Update Beacon Interval message\n"));); + FL("received Update Beacon Interval message"));); if(pMsgBuf == NULL) { - limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n")); + limLog(pMac, LOGE,FL("Buffer is Pointing to NULL")); return; } @@ -4179,7 +4212,7 @@ __limProcessSmeChangeBI(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if((psessionEntry = peFindSessionByBssid(pMac, pChangeBIParams->bssId, &sessionId)) == NULL) { - limLog(pMac, LOGE, FL("Session does not exist for given BSSID\n")); + limLog(pMac, LOGE, FL("Session does not exist for given BSSID")); return; } @@ -4202,9 +4235,10 @@ __limProcessSmeChangeBI(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) /* Update beacon */ schSetFixedBeaconFields(pMac, psessionEntry); + beaconParams.bssIdx = psessionEntry->bssIdx; //Set change in beacon Interval beaconParams.beaconInterval = pChangeBIParams->beaconInterval; - beaconParams.paramChangeBitmap |= PARAM_BCN_INTERVAL_CHANGED; + beaconParams.paramChangeBitmap = PARAM_BCN_INTERVAL_CHANGED; limSendBeaconParams(pMac, &beaconParams, psessionEntry); } @@ -4236,10 +4270,10 @@ limProcessSmeDelBaPeerInd(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if ((psessionEntry = peFindSessionByBssid(pMac,pSmeDelBAPeerInd->bssId,&sessionId))==NULL) { - limLog(pMac, LOGE,FL("session does not exist for given bssId\n")); + limLog(pMac, LOGE,FL("session does not exist for given bssId")); return; } - limLog(pMac, LOGW, FL("called with staId = %d, tid = %d, baDirection = %d\n"), + limLog(pMac, LOGW, FL("called with staId = %d, tid = %d, baDirection = %d"), pSmeDelBAPeerInd->staIdx, pSmeDelBAPeerInd->baTID, pSmeDelBAPeerInd->baDirection); pSta = dphLookupAssocId(pMac, pSmeDelBAPeerInd->staIdx, &assocId, &psessionEntry->dph.dphHashTable); @@ -4289,13 +4323,13 @@ void __limProcessReportMessage(tpAniSirGlobal pMac, tpSirMsgQ pMsg) if(pMsg->bodyptr == NULL) { - limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n")); + limLog(pMac, LOGE,FL("Buffer is Pointing to NULL")); return; } pBcnReport = (tpSirBeaconReportXmitInd )pMsg->bodyptr; if((psessionEntry = peFindSessionByBssid(pMac, pBcnReport->bssId,&sessionId))== NULL) { - limLog(pMac, LOGE, "Session Does not exist for given bssId\n"); + limLog(pMac, LOGE, "Session Does not exist for given bssId"); return; } if (psessionEntry->isCCXconnection) @@ -4335,43 +4369,35 @@ limSendSetMaxTxPowerReq ( tpAniSirGlobal pMac, tPowerdBm txPower, tpPESession pS if( pSessionEntry == NULL ) { - PELOGE(limLog(pMac, LOGE, "%s:%d: Inavalid parameters\n", __func__, __LINE__ );) + PELOGE(limLog(pMac, LOGE, "%s:%d: Inavalid parameters", __func__, __LINE__ );) return eSIR_FAILURE; } if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **) &pMaxTxParams, sizeof(tMaxTxPowerParams) ) ) { - limLog( pMac, LOGP, "%s:%d:Unable to allocate memory for pMaxTxParams \n", __func__, __LINE__); + limLog( pMac, LOGP, "%s:%d:Unable to allocate memory for pMaxTxParams ", __func__, __LINE__); return eSIR_MEM_ALLOC_FAILED; } #if defined(WLAN_VOWIFI_DEBUG) || defined(FEATURE_WLAN_CCX) - PELOG1(limLog( pMac, LOG1, "%s:%d: Allocated memory for pMaxTxParams...will be freed in other module\n", __func__, __LINE__ );) + PELOG1(limLog( pMac, LOG1, "%s:%d: Allocated memory for pMaxTxParams...will be freed in other module", __func__, __LINE__ );) #endif - if( pMaxTxParams == NULL ) - { - limLog( pMac, LOGE, "%s:%d: pMaxTxParams is NULL\n", __func__, __LINE__); - return eSIR_FAILURE; - } pMaxTxParams->power = txPower; palCopyMemory( pMac->hHdd, pMaxTxParams->bssId, pSessionEntry->bssId, sizeof(tSirMacAddr) ); palCopyMemory( pMac->hHdd, pMaxTxParams->selfStaMacAddr, pSessionEntry->selfMacAddr, sizeof(tSirMacAddr) ); - msgQ.type = WDA_SET_MAX_TX_POWER_REQ; - msgQ.bodyptr = pMaxTxParams; - msgQ.bodyval = 0; - PELOGW(limLog(pMac, LOG1, FL("Posting WDA_SET_MAX_TX_POWER_REQ to WDA\n"));) - MTRACE(macTraceMsgTx(pMac, pSessionEntry->peSessionId, msgQ.type)); - if(eSIR_SUCCESS != (retCode = wdaPostCtrlMsg(pMac, &msgQ))) - { - PELOGW(limLog(pMac, LOGW, FL("wdaPostCtrlMsg() failed\n"));) - if (NULL != pMaxTxParams) - { - palFreeMemory(pMac->hHdd, (tANI_U8*)pMaxTxParams); - } - return retCode; - } - return retCode; + msgQ.type = WDA_SET_MAX_TX_POWER_REQ; + msgQ.bodyptr = pMaxTxParams; + msgQ.bodyval = 0; + PELOG1(limLog(pMac, LOG1, FL("Posting WDA_SET_MAX_TX_POWER_REQ to WDA"));) + MTRACE(macTraceMsgTx(pMac, pSessionEntry->peSessionId, msgQ.type)); + retCode = wdaPostCtrlMsg(pMac, &msgQ); + if (eSIR_SUCCESS != retCode) + { + PELOGE(limLog(pMac, LOGE, FL("wdaPostCtrlMsg() failed"));) + palFreeMemory(pMac->hHdd, pMaxTxParams); + } + return retCode; } #endif @@ -4409,17 +4435,18 @@ __limProcessSmeAddStaSelfReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) palCopyMemory( pMac->hHdd, pAddStaSelfParams->selfMacAddr, pSmeReq->selfMacAddr, sizeof(tSirMacAddr) ); + pAddStaSelfParams->currDeviceMode = pSmeReq->currDeviceMode; msg.type = SIR_HAL_ADD_STA_SELF_REQ; msg.reserved = 0; msg.bodyptr = pAddStaSelfParams; msg.bodyval = 0; - PELOGW(limLog(pMac, LOG1, FL("sending SIR_HAL_ADD_STA_SELF_REQ msg to HAL\n"));) + PELOGW(limLog(pMac, LOG1, FL("sending SIR_HAL_ADD_STA_SELF_REQ msg to HAL"));) MTRACE(macTraceMsgTx(pMac, NO_SESSION, msg.type)); if(eSIR_SUCCESS != wdaPostCtrlMsg(pMac, &msg)) { - limLog(pMac, LOGP, FL("wdaPostCtrlMsg failed\n")); + limLog(pMac, LOGP, FL("wdaPostCtrlMsg failed")); } return; } /*** end __limProcessAddStaSelfReq() ***/ @@ -4464,12 +4491,12 @@ __limProcessSmeDelStaSelfReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) msg.bodyptr = pDelStaSelfParams; msg.bodyval = 0; - PELOGW(limLog(pMac, LOG1, FL("sending SIR_HAL_ADD_STA_SELF_REQ msg to HAL\n"));) + PELOGW(limLog(pMac, LOG1, FL("sending SIR_HAL_ADD_STA_SELF_REQ msg to HAL"));) MTRACE(macTraceMsgTx(pMac, NO_SESSION, msg.type)); if(eSIR_SUCCESS != wdaPostCtrlMsg(pMac, &msg)) { - limLog(pMac, LOGP, FL("wdaPostCtrlMsg failed\n")); + limLog(pMac, LOGP, FL("wdaPostCtrlMsg failed")); } return; } /*** end __limProcessSmeDelStaSelfReq() ***/ @@ -4500,7 +4527,7 @@ __limProcessSmeRegisterMgmtFrameReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) tpLimMgmtFrameRegistration pLimMgmtRegistration = NULL, pNext = NULL; tANI_BOOLEAN match = VOS_FALSE; PELOG1(limLog(pMac, LOG1, - FL("registerFrame %d, frameType %d, matchLen %d\n"), + FL("registerFrame %d, frameType %d, matchLen %d"), pSmeReq->registerFrame, pSmeReq->frameType, pSmeReq->matchLen);) /* First check whether entry exists already*/ @@ -4583,7 +4610,7 @@ __limInsertSingleShotNOAForScan(tpAniSirGlobal pMac, tANI_U32 noaDuration) pMac->hHdd, (void **) &pMsgNoA, sizeof( tP2pPsConfig ))) { limLog( pMac, LOGP, - FL( "Unable to allocate memory during NoA Update\n" )); + FL( "Unable to allocate memory during NoA Update" )); goto error; } @@ -4609,11 +4636,11 @@ __limInsertSingleShotNOAForScan(tpAniSirGlobal pMac, tANI_U32 noaDuration) { /// Could not activate Insert NOA timer. // Log error - limLog(pMac, LOGP, FL("could not activate Insert Single Shot NOA during scan timer\n")); + limLog(pMac, LOGP, FL("could not activate Insert Single Shot NOA during scan timer")); // send the scan response back with status failure and do not even call insert NOA limSendSmeScanRsp(pMac, sizeof(tSirSmeScanRsp), eSIR_SME_SCAN_FAILED, pMac->lim.gSmeSessionId, pMac->lim.gTransactionId); - palFreeMemory( pMac->hHdd, (void **) &pMsgNoA); + palFreeMemory( pMac->hHdd, pMsgNoA); goto error; } @@ -4627,7 +4654,7 @@ __limInsertSingleShotNOAForScan(tpAniSirGlobal pMac, tANI_U32 noaDuration) if(eSIR_SUCCESS != wdaPostCtrlMsg(pMac, &msg)) { /* In this failure case, timer is already started, so its expiration will take care of sending scan response */ - limLog(pMac, LOGP, FL("wdaPost Msg failed\n")); + limLog(pMac, LOGP, FL("wdaPost Msg failed")); /* Deactivate the NOA timer in failure case */ limDeactivateAndChangeTimer(pMac, eLIM_INSERT_SINGLESHOT_NOA_TIMER); goto error; @@ -4646,14 +4673,14 @@ __limInsertSingleShotNOAForScan(tpAniSirGlobal pMac, tANI_U32 noaDuration) static void __limRegisterDeferredSmeReqForNOAStart(tpAniSirGlobal pMac, tANI_U16 msgType, tANI_U32 *pMsgBuf) { - limLog(pMac, LOG1, FL("Reg msgType %d\n"), msgType) ; + limLog(pMac, LOG1, FL("Reg msgType %d"), msgType) ; pMac->lim.gDeferMsgTypeForNOA = msgType; pMac->lim.gpDefdSmeMsgForNOA = pMsgBuf; } static void __limDeregisterDeferredSmeReqAfterNOAStart(tpAniSirGlobal pMac) { - limLog(pMac, LOG1, FL("Dereg msgType %d\n"), pMac->lim.gDeferMsgTypeForNOA) ; + limLog(pMac, LOG1, FL("Dereg msgType %d"), pMac->lim.gDeferMsgTypeForNOA) ; pMac->lim.gDeferMsgTypeForNOA = 0; if (pMac->lim.gpDefdSmeMsgForNOA != NULL) { @@ -4681,7 +4708,7 @@ tANI_U32 limCalculateNOADuration(tpAniSirGlobal pMac, tANI_U16 msgType, tANI_U32 * Could not get max channel value * from CFG. Log error. */ - limLog(pMac, LOGP, FL("could not retrieve passive max channel value\n")); + limLog(pMac, LOGP, FL("could not retrieve passive max channel value")); /* use a default value of 110ms */ val = DEFAULT_PASSIVE_MAX_CHANNEL_TIME; @@ -4728,7 +4755,7 @@ tANI_U32 limCalculateNOADuration(tpAniSirGlobal pMac, tANI_U16 msgType, tANI_U32 break; } - limLog(pMac, LOGW, FL("msgType %d noa %d\n"), msgType, noaDuration); + limLog(pMac, LOGW, FL("msgType %d noa %d"), msgType, noaDuration); return noaDuration; } @@ -4736,7 +4763,7 @@ void limProcessRegdDefdSmeReqAfterNOAStart(tpAniSirGlobal pMac) { tANI_BOOLEAN bufConsumed = TRUE; - limLog(pMac, LOG1, FL("Process defd sme req %d\n"), pMac->lim.gDeferMsgTypeForNOA); + limLog(pMac, LOG1, FL("Process defd sme req %d"), pMac->lim.gDeferMsgTypeForNOA); if ( (pMac->lim.gDeferMsgTypeForNOA != 0) && (pMac->lim.gpDefdSmeMsgForNOA != NULL) ) { @@ -4762,7 +4789,7 @@ void limProcessRegdDefdSmeReqAfterNOAStart(tpAniSirGlobal pMac) __limProcessSmeJoinReq(pMac, pMac->lim.gpDefdSmeMsgForNOA); break; default: - limLog(pMac, LOGE, FL("Unknown deferred msg type %d\n"), pMac->lim.gDeferMsgTypeForNOA); + limLog(pMac, LOGE, FL("Unknown deferred msg type %d"), pMac->lim.gDeferMsgTypeForNOA); break; } __limDeregisterDeferredSmeReqAfterNOAStart(pMac); @@ -4770,7 +4797,7 @@ void limProcessRegdDefdSmeReqAfterNOAStart(tpAniSirGlobal pMac) else { limLog( pMac, LOGW, FL("start received from FW when no sme deferred msg pending. Do nothing." - "It might happen sometime when NOA start ind and timeout happen at the same time\n")); + "It might happen sometime when NOA start ind and timeout happen at the same time")); } } @@ -4787,13 +4814,13 @@ static tSirRetStatus limProcessSmeDisStartReq(tpAniSirGlobal pMac, tANI_U8 sessionId; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("Discovery Req Recieved\n")) ; + ("Discovery Req Recieved")) ; if((psessionEntry = peFindSessionByBssid(pMac, disReq->bssid, &sessionId)) == NULL) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - "PE Session does not exist for given sme sessionId %d\n", + "PE Session does not exist for given sme sessionId %d", disReq->sessionId); goto lim_tdls_dis_start_error; } @@ -4802,7 +4829,7 @@ static tSirRetStatus limProcessSmeDisStartReq(tpAniSirGlobal pMac, if (psessionEntry->limSystemRole != eLIM_STA_ROLE) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - "dis req received in wrong system Role %d\n", + "dis req received in wrong system Role %d", psessionEntry->limSystemRole); goto lim_tdls_dis_start_error; } @@ -4816,7 +4843,7 @@ static tSirRetStatus limProcessSmeDisStartReq(tpAniSirGlobal pMac, { limLog(pMac, LOGE, "dis req received in invalid LIMsme \ - state (%d)\n", psessionEntry->limSmeState); + state (%d)", psessionEntry->limSmeState); goto lim_tdls_dis_start_error; } @@ -4839,7 +4866,7 @@ static tSirRetStatus limProcessSmeDisStartReq(tpAniSirGlobal pMac, (tANI_U8 *) disReq, sizeof(tSirTdlsDisReq)); VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - "Transmit Discovery Request Frame\n") ; + "Transmit Discovery Request Frame") ; /* format TDLS discovery request frame and transmit it */ limSendTdlsDisReqFrame(pMac, disReq->peerMac, disReq->dialog, psessionEntry) ; @@ -4854,7 +4881,7 @@ static tSirRetStatus limProcessSmeDisStartReq(tpAniSirGlobal pMac, */ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("Start Discovery request Timeout Timer\n")) ; + ("Start Discovery request Timeout Timer")) ; MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, 0, eLIM_TDLS_DISCOVERY_RSP_WAIT)); @@ -4866,7 +4893,7 @@ static tSirRetStatus limProcessSmeDisStartReq(tpAniSirGlobal pMac, != TX_SUCCESS) { limLog(pMac, LOGP, FL("TDLS discovery response timer \ - activation failed!\n")); + activation failed!")); goto lim_tdls_dis_start_error; } /* @@ -4897,7 +4924,7 @@ eHalStatus limProcessSmeLinkStartReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) setupReq->bssid, &sessionId)) == NULL) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - "PE Session does not exist for given sme sessionId %d\n", + "PE Session does not exist for given sme sessionId %d", setupReq->sessionId); goto lim_tdls_link_start_error; } @@ -4906,7 +4933,7 @@ eHalStatus limProcessSmeLinkStartReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if (psessionEntry->limSystemRole != eLIM_STA_ROLE) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - "TDLS link setup req received in wrong system Role %d\n", + "TDLS link setup req received in wrong system Role %d", psessionEntry->limSystemRole); goto lim_tdls_link_start_error; } @@ -4919,7 +4946,7 @@ eHalStatus limProcessSmeLinkStartReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) (psessionEntry->limSmeState != eLIM_SME_LINK_EST_STATE)) { limLog(pMac, LOGE, "Setup request in invalid LIMsme \ - state (%d)\n", pMac->lim.gLimSmeState); + state (%d)", pMac->lim.gLimSmeState); goto lim_tdls_link_start_error; } @@ -4948,7 +4975,7 @@ eHalStatus limProcessSmeLinkStartReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) (void **) &setupPeer, sizeof( tLimTdlsLinkSetupPeer ))) { limLog( pMac, LOGP, - FL( "Unable to allocate memory during ADD_STA\n" )); + FL( "Unable to allocate memory during ADD_STA" )); VOS_ASSERT(0) ; return eSIR_MEM_ALLOC_FAILED; } @@ -5001,7 +5028,7 @@ eHalStatus limProcessSmeTeardownReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if((psessionEntry = peFindSessionByBssid(pMac, teardownReq->bssid, &sessionId)) == NULL) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - "PE Session does not exist for given sme sessionId %d\n", teardownReq->sessionId); + "PE Session does not exist for given sme sessionId %d", teardownReq->sessionId); goto lim_tdls_teardown_req_error; } @@ -5009,7 +5036,7 @@ eHalStatus limProcessSmeTeardownReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if (psessionEntry->limSystemRole != eLIM_STA_ROLE) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - "TDLS teardown req received in wrong system Role %d\n", psessionEntry->limSystemRole); + "TDLS teardown req received in wrong system Role %d", psessionEntry->limSystemRole); goto lim_tdls_teardown_req_error; } @@ -5021,12 +5048,12 @@ eHalStatus limProcessSmeTeardownReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) (psessionEntry->limSmeState != eLIM_SME_LINK_EST_STATE)) { limLog(pMac, LOGE, "TDLS teardwon req received in invalid LIMsme \ - state (%d)\n", psessionEntry->limSmeState); + state (%d)", psessionEntry->limSmeState); goto lim_tdls_teardown_req_error; } VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - "Teardown for peer = %02x,%02x,%02x,%02x,%02x,%02x\n", + "Teardown for peer = %02x,%02x,%02x,%02x,%02x,%02x", teardownReq->peerMac[0], teardownReq->peerMac[1], teardownReq->peerMac[2], @@ -5043,7 +5070,7 @@ eHalStatus limProcessSmeTeardownReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if(NULL == setupPeer) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("invalid Peer on teardown \n")) ; + ("invalid Peer on teardown ")) ; goto lim_tdls_teardown_req_error; } @@ -5053,7 +5080,7 @@ eHalStatus limProcessSmeTeardownReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) /* TDLS_sessionize: check sessionId in case */ if((setupPeer)->tdls_sessionId != psessionEntry->peSessionId) { - limLog(pMac, LOGE, "TDLS teardown req; stored sessionId (%d) not matched from peSessionId (%d)\n", \ + limLog(pMac, LOGE, "TDLS teardown req; stored sessionId (%d) not matched from peSessionId (%d)", \ (setupPeer)->tdls_sessionId, psessionEntry->limSmeState); (setupPeer)->tdls_sessionId = psessionEntry->peSessionId; } @@ -5063,7 +5090,7 @@ eHalStatus limProcessSmeTeardownReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON, psessionEntry, NULL, 0 )) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("couldn't send teardown frame \n")) ; + ("couldn't send teardown frame ")) ; goto lim_tdls_teardown_req_error; } /* in case of success, eWNI_SME_TDLS_TEARDOWN_RSP is sent back to SME later when @@ -5087,7 +5114,7 @@ __limProcessSmeResetApCapsChange(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) tANI_U8 sessionId = 0; if (pMsgBuf == NULL) { - limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n")); + limLog(pMac, LOGE,FL("Buffer is Pointing to NULL")); return; } @@ -5095,7 +5122,7 @@ __limProcessSmeResetApCapsChange(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) psessionEntry = peFindSessionByBssid(pMac, pResetCapsChange->bssId, &sessionId); if (psessionEntry == NULL) { - limLog(pMac, LOGE, FL("Session does not exist for given BSSID\n")); + limLog(pMac, LOGE, FL("Session does not exist for given BSSID")); return; } @@ -5129,12 +5156,13 @@ limProcessSmeReqMessages(tpAniSirGlobal pMac, tpSirMsgQ pMsg) { tANI_BOOLEAN bufConsumed = TRUE; //Set this flag to false within case block of any following message, that doesnt want pMsgBuf to be freed. tANI_U32 *pMsgBuf = pMsg->bodyptr; - - PELOG1(limLog(pMac, LOG1, FL("LIM Received SME Message %s(%d) Global LimSmeState:%s(%d) Global LimMlmState: %s(%d)\n"), + tpSirSmeScanReq pScanReq; + PELOG1(limLog(pMac, LOG1, FL("LIM Received SME Message %s(%d) Global LimSmeState:%s(%d) Global LimMlmState: %s(%d)"), limMsgStr(pMsg->type), pMsg->type, limSmeStateStr(pMac->lim.gLimSmeState), pMac->lim.gLimSmeState, limMlmStateStr(pMac->lim.gLimMlmState), pMac->lim.gLimMlmState );) + pScanReq = (tpSirSmeScanReq) pMsgBuf; /* Special handling of some SME Req msgs where we have an existing GO session and * want to insert NOA before processing those msgs. These msgs will be processed later when * start event happens @@ -5142,8 +5170,42 @@ limProcessSmeReqMessages(tpAniSirGlobal pMac, tpSirMsgQ pMsg) switch (pMsg->type) { case eWNI_SME_SCAN_REQ: - case eWNI_SME_OEM_DATA_REQ: case eWNI_SME_REMAIN_ON_CHANNEL_REQ: + + /* If scan is disabled return from here + */ + if (pMac->lim.fScanDisabled) + { + PELOGE(limLog(pMac, LOGE, FL("Error: Scan Disabled"));) + if (pMsg->type == eWNI_SME_SCAN_REQ) + { + limSendSmeScanRsp(pMac, + offsetof(tSirSmeScanRsp,bssDescription[0]), + eSIR_SME_INVALID_PARAMETERS, + pScanReq->sessionId, + pScanReq->transactionId); + + bufConsumed = TRUE; + } + else if (pMsg->type == eWNI_SME_REMAIN_ON_CHANNEL_REQ) + { + pMac->lim.gpDefdSmeMsgForNOA = NULL; + pMac->lim.gpLimRemainOnChanReq = (tpSirRemainOnChnReq )pMsgBuf; + limRemainOnChnRsp(pMac,eHAL_STATUS_FAILURE, NULL); + + /* + * limRemainOnChnRsp will free the buffer this change is to + * avoid "double free" + */ + bufConsumed = FALSE; + } + + return bufConsumed; + } + /* + * Do not add BREAK here + */ + case eWNI_SME_OEM_DATA_REQ: case eWNI_SME_JOIN_REQ: /* If we have an existing P2P GO session we need to insert NOA before actually process this SME Req */ if ((limIsNOAInsertReqd(pMac) == TRUE) && IS_FEATURE_SUPPORTED_BY_FW(P2P_GO_NOA_DECOUPLE_INIT_SCAN)) @@ -5244,24 +5306,24 @@ limProcessSmeReqMessages(tpAniSirGlobal pMac, tpSirMsgQ pMsg) case eWNI_SME_ASSOC_CNF: case eWNI_SME_REASSOC_CNF: if (pMsg->type == eWNI_SME_ASSOC_CNF) - PELOG1(limLog(pMac, LOG1, FL("Received ASSOC_CNF message\n"));) + PELOG1(limLog(pMac, LOG1, FL("Received ASSOC_CNF message"));) else - PELOG1(limLog(pMac, LOG1, FL("Received REASSOC_CNF message\n"));) + PELOG1(limLog(pMac, LOG1, FL("Received REASSOC_CNF message"));) __limProcessSmeAssocCnfNew(pMac, pMsg->type, pMsgBuf); break; case eWNI_SME_ADDTS_REQ: - PELOG1(limLog(pMac, LOG1, FL("Received ADDTS_REQ message\n"));) + PELOG1(limLog(pMac, LOG1, FL("Received ADDTS_REQ message"));) __limProcessSmeAddtsReq(pMac, pMsgBuf); break; case eWNI_SME_DELTS_REQ: - PELOG1(limLog(pMac, LOG1, FL("Received DELTS_REQ message\n"));) + PELOG1(limLog(pMac, LOG1, FL("Received DELTS_REQ message"));) __limProcessSmeDeltsReq(pMac, pMsgBuf); break; case SIR_LIM_ADDTS_RSP_TIMEOUT: - PELOG1(limLog(pMac, LOG1, FL("Received SIR_LIM_ADDTS_RSP_TIMEOUT message \n"));) + PELOG1(limLog(pMac, LOG1, FL("Received SIR_LIM_ADDTS_RSP_TIMEOUT message "));) limProcessSmeAddtsRspTimeout(pMac, pMsg->bodyval); break; diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessTdls.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessTdls.c index 4936b289bb2..ba906e233b0 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessTdls.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessTdls.c @@ -49,10 +49,12 @@ Are listed for each API below. +Copyright (c) 2013 Qualcomm Atheros, Inc.All Rights Reserved. +Qualcomm Atheros Confidential and Proprietary. + +Copyright (c) 2010 Qualcomm Technologies, Inc.All Rights Reserved. +Qualcomm Technologies Confidential and Proprietary - Copyright (c) 2010 QUALCOMM Incorporated. - All Rights Reserved. - Qualcomm Confidential and Proprietary ===========================================================================*/ /*=========================================================================== @@ -239,6 +241,14 @@ typedef enum tdlsLinkSetupStatus #define WNI_CFG_TDLS_LINK_SETUP_CNF_TIMEOUT (200) #endif +#define IS_QOS_ENABLED(psessionEntry) ((((psessionEntry)->limQosEnabled) && \ + SIR_MAC_GET_QOS((psessionEntry)->limCurrentBssCaps)) || \ + (((psessionEntry)->limWmeEnabled ) && \ + LIM_BSS_CAPS_GET(WME, (psessionEntry)->limCurrentBssQosCaps))) + +#define TID_AC_VI 4 +#define TID_AC_BK 1 + const tANI_U8* limTraceTdlsActionString( tANI_U8 tdlsActionCode ) { switch( tdlsActionCode ) @@ -268,7 +278,7 @@ static void printMacAddr(tSirMacAddr macAddr) VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, (" %02x "), macAddr[i]); } - VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, ("\n")); + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, ("")); return ; } #endif @@ -311,7 +321,7 @@ void limTdlsSetNegativeBehavior(tpAniSirGlobal pMac, tANI_U8 value, tANI_BOOLEAN else pMac->lim.gLimTdlsNegativeBehavior &= ~(1 << (value-1)); } - LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,("%d %d -> gLimTdlsNegativeBehavior= 0x%lx\n"), \ + LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,("%d %d -> gLimTdlsNegativeBehavior= 0x%lx"), \ value, on, pMac->lim.gLimTdlsNegativeBehavior)); } #endif @@ -359,7 +369,7 @@ static void limPreparesActionFrameHdr(tpAniSirGlobal pMac, tANI_U8 *pFrame, palCopyMemory( pMac->hHdd, (tANI_U8 *) pMacHdr->bssId, bssid, sizeof( tSirMacAddr )); - LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_WARN, ("Preparing TDLS action frame\n%02x:%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x:%02x\n"), \ + LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_WARN, ("Preparing TDLS action frame\n%02x:%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x:%02x"), \ pMacHdr->da[0], pMacHdr->da[1], pMacHdr->da[2], pMacHdr->da[3], pMacHdr->da[4], pMacHdr->da[5], \ pMacHdr->sa[0], pMacHdr->sa[1], pMacHdr->sa[2], pMacHdr->sa[3], pMacHdr->sa[4], pMacHdr->sa[5], \ pMacHdr->bssId[0], pMacHdr->bssId[1], pMacHdr->bssId[2], \ @@ -375,9 +385,10 @@ static void limPreparesActionFrameHdr(tpAniSirGlobal pMac, tANI_U8 *pFrame, * | | | | */ static tANI_U32 limPrepareTdlsFrameHeader(tpAniSirGlobal pMac, tANI_U8* pFrame, - tDot11fIELinkIdentifier *link_iden, tANI_U8 tdlsLinkType, tANI_U8 reqType, tpPESession psessionEntry ) + tDot11fIELinkIdentifier *link_iden, tANI_U8 tdlsLinkType, tANI_U8 reqType, + tANI_U8 tid, tpPESession psessionEntry) { - tpSirMacMgmtHdr pMacHdr ; + tpSirMacDataHdr3a pMacHdr ; tANI_U32 header_offset = 0 ; tANI_U8 *addr1 = NULL ; tANI_U8 *addr3 = NULL ; @@ -388,7 +399,7 @@ static tANI_U32 limPrepareTdlsFrameHeader(tpAniSirGlobal pMac, tANI_U8* pFrame, tANI_U8 *staMac = (reqType == TDLS_INITIATOR) ? link_iden->InitStaAddr : link_iden->RespStaAddr; - pMacHdr = (tpSirMacMgmtHdr) (pFrame); + pMacHdr = (tpSirMacDataHdr3a) (pFrame); /* * if TDLS frame goes through the AP link, it follows normal address @@ -404,7 +415,8 @@ static tANI_U32 limPrepareTdlsFrameHeader(tpAniSirGlobal pMac, tANI_U8* pFrame, */ pMacHdr->fc.protVer = SIR_MAC_PROTOCOL_VERSION; pMacHdr->fc.type = SIR_MAC_DATA_FRAME ; - pMacHdr->fc.subType = SIR_MAC_DATA_DATA ; + pMacHdr->fc.subType = IS_QOS_ENABLED(psessionEntry) ? SIR_MAC_DATA_QOS_DATA : SIR_MAC_DATA_DATA; + /* * TL is not setting up below fields, so we are doing it here */ @@ -413,28 +425,34 @@ static tANI_U32 limPrepareTdlsFrameHeader(tpAniSirGlobal pMac, tANI_U8* pFrame, pMacHdr->fc.wep = (psessionEntry->encryptType == eSIR_ED_NONE)? 0 : 1; - palCopyMemory( pMac->hHdd, (tANI_U8 *) pMacHdr->da, (tANI_U8 *)addr1, + palCopyMemory( pMac->hHdd, (tANI_U8 *) pMacHdr->addr1, (tANI_U8 *)addr1, sizeof( tSirMacAddr )); palCopyMemory( pMac->hHdd, - (tANI_U8 *) pMacHdr->sa, + (tANI_U8 *) pMacHdr->addr2, (tANI_U8 *) staMac, sizeof( tSirMacAddr )); - palCopyMemory( pMac->hHdd, (tANI_U8 *) pMacHdr->bssId, + palCopyMemory( pMac->hHdd, (tANI_U8 *) pMacHdr->addr3, (tANI_U8 *) (addr3), sizeof( tSirMacAddr )); - - LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_WARN, ("Preparing TDLS frame header to %s\n%02x:%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x:%02x\n"), \ + + LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_WARN, ("Preparing TDLS frame header to %s\n%02x:%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x:%02x"), \ (tdlsLinkType == TDLS_LINK_AP) ? "AP" : "TD", \ - pMacHdr->da[0], pMacHdr->da[1], pMacHdr->da[2], pMacHdr->da[3], pMacHdr->da[4], pMacHdr->da[5], \ - pMacHdr->sa[0], pMacHdr->sa[1], pMacHdr->sa[2], pMacHdr->sa[3], pMacHdr->sa[4], pMacHdr->sa[5], \ - pMacHdr->bssId[0], pMacHdr->bssId[1], pMacHdr->bssId[2], \ - pMacHdr->bssId[3], pMacHdr->bssId[4], pMacHdr->bssId[5])); + pMacHdr->addr1[0], pMacHdr->addr1[1], pMacHdr->addr1[2], pMacHdr->addr1[3], pMacHdr->addr1[4], pMacHdr->addr1[5], \ + pMacHdr->addr2[0], pMacHdr->addr2[1], pMacHdr->addr2[2], pMacHdr->addr2[3], pMacHdr->addr2[4], pMacHdr->addr2[5], \ + pMacHdr->addr3[0], pMacHdr->addr3[1], pMacHdr->addr3[2], pMacHdr->addr3[3], pMacHdr->addr3[4], pMacHdr->addr3[5])); //printMacAddr(pMacHdr->bssId) ; //printMacAddr(pMacHdr->sa) ; //printMacAddr(pMacHdr->da) ; - - header_offset += sizeof(tSirMacMgmtHdr) ; + + if (IS_QOS_ENABLED(psessionEntry)) + { + pMacHdr->qosControl.tid = tid; + header_offset += sizeof(tSirMacDataHdr3a); + } + else + header_offset += sizeof(tSirMacMgmtHdr); + /* * Now form RFC1042 header */ @@ -520,7 +538,7 @@ tSirRetStatus limSendTdlsDisReqFrame(tpAniSirGlobal pMac, tSirMacAddr peer_mac, if ( DOT11F_FAILED( status ) ) { limLog( pMac, LOGP, FL("Failed to calculate the packed size f" - "or a discovery Request (0x%08x).\n"), status ); + "or a discovery Request (0x%08x)."), status ); /* We'll fall back on the worst case scenario: */ nPayload = sizeof( tDot11fTDLSDisReq ); } @@ -528,7 +546,7 @@ tSirRetStatus limSendTdlsDisReqFrame(tpAniSirGlobal pMac, tSirMacAddr peer_mac, { limLog( pMac, LOGW, FL("There were warnings while calculating" "the packed size for a discovery Request (" - "0x%08x).\n"), status ); + "0x%08x)."), status ); } /* @@ -538,9 +556,10 @@ tSirRetStatus limSendTdlsDisReqFrame(tpAniSirGlobal pMac, tSirMacAddr peer_mac, */ - nBytes = nPayload + sizeof( tSirMacMgmtHdr ) - + sizeof( eth_890d_header ) - + PAYLOAD_TYPE_TDLS_SIZE ; + nBytes = nPayload + ((IS_QOS_ENABLED(psessionEntry)) + ? sizeof(tSirMacDataHdr3a) : sizeof(tSirMacMgmtHdr)) + + sizeof( eth_890d_header ) + + PAYLOAD_TYPE_TDLS_SIZE ; #ifndef NO_PAD_TDLS_MIN_8023_SIZE /* IOT issue with some AP : some AP doesn't like the data packet size < minimum 802.3 frame length (64) @@ -567,7 +586,7 @@ tSirRetStatus limSendTdlsDisReqFrame(tpAniSirGlobal pMac, tSirMacAddr peer_mac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a TDLS" - "Discovery Request.\n"), nBytes ); + "Discovery Request."), nBytes ); return eSIR_MEM_ALLOC_FAILED; } @@ -582,7 +601,7 @@ tSirRetStatus limSendTdlsDisReqFrame(tpAniSirGlobal pMac, tSirMacAddr peer_mac, /* fill out the buffer descriptor */ header_offset = limPrepareTdlsFrameHeader(pMac, pFrame, - LINK_IDEN_ADDR_OFFSET(tdlsDisReq), TDLS_LINK_AP, TDLS_INITIATOR, psessionEntry) ; + LINK_IDEN_ADDR_OFFSET(tdlsDisReq), TDLS_LINK_AP, TDLS_INITIATOR, TID_AC_VI, psessionEntry) ; #ifdef FEATURE_WLAN_TDLS_NEGATIVE if(pMac->lim.gLimTdlsNegativeBehavior & LIM_TDLS_NEGATIVE_WRONG_BSSID_IN_DSCV_REQ) @@ -590,7 +609,7 @@ tSirRetStatus limSendTdlsDisReqFrame(tpAniSirGlobal pMac, tSirMacAddr peer_mac, tdlsDisReq.LinkIdentifier.bssid[4] = 0xde; tdlsDisReq.LinkIdentifier.bssid[5] = 0xad; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("TDLS negative running: wrong BSSID %02x:%02x:%02x:%02x:%02x:%02x in TDLS Discovery Req\n"), \ + ("TDLS negative running: wrong BSSID %02x:%02x:%02x:%02x:%02x:%02x in TDLS Discovery Req"), \ tdlsDisReq.LinkIdentifier.bssid[0], tdlsDisReq.LinkIdentifier.bssid[1], tdlsDisReq.LinkIdentifier.bssid[2], @@ -605,7 +624,7 @@ tSirRetStatus limSendTdlsDisReqFrame(tpAniSirGlobal pMac, tSirMacAddr peer_mac, if ( DOT11F_FAILED( status ) ) { limLog( pMac, LOGE, FL("Failed to pack a TDLS discovery req \ - (0x%08x).\n"), status ); + (0x%08x)."), status ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return eSIR_FAILURE; @@ -613,7 +632,7 @@ tSirRetStatus limSendTdlsDisReqFrame(tpAniSirGlobal pMac, tSirMacAddr peer_mac, else if ( DOT11F_WARNED( status ) ) { limLog( pMac, LOGW, FL("There were warnings while packing TDLS" - "Discovery Request (0x%08x).\n") ); + "Discovery Request (0x%08x).") ); } #ifndef NO_PAD_TDLS_MIN_8023_SIZE @@ -643,14 +662,14 @@ tSirRetStatus limSendTdlsDisReqFrame(tpAniSirGlobal pMac, tSirMacAddr peer_mac, halstatus = halTxFrameWithTxComplete( pMac, pPacket, ( tANI_U16 ) nBytes, HAL_TXRX_FRM_802_11_DATA, ANI_TXDIR_TODS, - 7, + TID_AC_VI, limTxComplete, pFrame, limMgmtTXComplete, HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME); if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { pMac->lim.mgmtFrameSessionId = 0xff; - limLog( pMac, LOGE, FL("could not send TDLS Dis Request frame!\n" )); + limLog( pMac, LOGE, FL("could not send TDLS Dis Request frame!" )); return eSIR_FAILURE; } pMac->lim.mgmtFrameSessionId = psessionEntry->peSessionId; @@ -677,7 +696,7 @@ eHalStatus limTdlsDisRspTxComplete(tpAniSirGlobal pMac, if(NULL == peerInfo) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("DisRspTxComplete: No TDLS state machine waits for this event\n")); + ("DisRspTxComplete: No TDLS state machine waits for this event")); VOS_ASSERT(0) ; return eHAL_STATUS_FAILURE; } @@ -694,7 +713,7 @@ eHalStatus limTdlsDisRspTxComplete(tpAniSirGlobal pMac, if(NULL == psessionEntry) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("DisRspTxComplete: sessionID %d is not found\n"), peerInfo->sessionId); + ("DisRspTxComplete: sessionID %d is not found"), peerInfo->sessionId); return eHAL_STATUS_FAILURE; } /* send del STA to remove context for this TDLS STA */ @@ -709,7 +728,7 @@ eHalStatus limTdlsDisRspTxComplete(tpAniSirGlobal pMac, else { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("DisRspTxComplete: staDs not found for %02x:%02x:%02x:%02x:%02x:%02x\n"), + ("DisRspTxComplete: staDs not found for %02x:%02x:%02x:%02x:%02x:%02x"), (peerInfo)->peerMac[0], (peerInfo)->peerMac[1], (peerInfo)->peerMac[2], @@ -760,7 +779,7 @@ eHalStatus limTdlsSetupCnfTxComplete(tpAniSirGlobal pMac, if(NULL == peerInfo) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("limTdlsSetupCnfTxComplete: No TDLS state machine waits for this event\n")); + ("limTdlsSetupCnfTxComplete: No TDLS state machine waits for this event")); VOS_ASSERT(0) ; return eHAL_STATUS_FAILURE; } @@ -779,7 +798,7 @@ eHalStatus limTdlsSetupCnfTxComplete(tpAniSirGlobal pMac, else { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("RSP-->SME peer MAC = %02x,%02x,%02x,%02x,%02x,%02x\n"), + ("RSP-->SME peer MAC = %02x,%02x,%02x,%02x,%02x,%02x"), (peerInfo)->peerMac[0], (peerInfo)->peerMac[1], (peerInfo)->peerMac[2], @@ -823,13 +842,13 @@ eHalStatus limTdlsTeardownTxComplete(tpAniSirGlobal pMac, if(NULL == peerInfo) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("limTdlsTeardownTxComplete: No TDLS state machine waits for this event\n")); + ("limTdlsTeardownTxComplete: No TDLS state machine waits for this event")); VOS_ASSERT(0) ; return eHAL_STATUS_FAILURE; } VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("teardown peer Mac = %02x,%02x,%02x,%02x,%02x,%02x\n"), + ("teardown peer Mac = %02x,%02x,%02x,%02x,%02x,%02x"), (peerInfo)->peerMac[0] , (peerInfo)->peerMac[1] , (peerInfo)->peerMac[2] , @@ -845,7 +864,7 @@ eHalStatus limTdlsTeardownTxComplete(tpAniSirGlobal pMac, if(NULL == psessionEntry) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("limTdlsTeardownTxComplete: sessionID %d is not found\n"), (peerInfo)->tdls_sessionId); + ("limTdlsTeardownTxComplete: sessionID %d is not found"), (peerInfo)->tdls_sessionId); VOS_ASSERT(0) ; return eHAL_STATUS_FAILURE; } @@ -853,7 +872,7 @@ eHalStatus limTdlsTeardownTxComplete(tpAniSirGlobal pMac, if(!txCompleteSuccess) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("TX complete failure for Teardown \n")) ; + ("TX complete failure for Teardown ")) ; /* * we should be sending Teradown to AP with status code @@ -891,9 +910,9 @@ eHalStatus limTdlsTeardownTxComplete(tpAniSirGlobal pMac, pStaDs, eSIR_SUCCESS) ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("TX complete SUCCESS for Teardown\n")) ; + ("TX complete SUCCESS for Teardown")) ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("Prev State = %d\n"), (peerInfo)->tdls_prev_link_state) ; + ("Prev State = %d"), (peerInfo)->tdls_prev_link_state) ; limSendSmeTdlsTeardownRsp(pMac, eSIR_SUCCESS, (peerInfo)->peerMac, eWNI_SME_TDLS_TEARDOWN_RSP) ; /* Delete Peer for Link Peer List */ @@ -937,6 +956,12 @@ static tSirRetStatus limSendTdlsDisRspFrame(tpAniSirGlobal pMac, tANI_U8 *pFrame; void *pPacket; eHalStatus halstatus; + uint32 selfDot11Mode; +// Placeholder to support different channel bonding mode of TDLS than AP. +// Today, WNI_CFG_CHANNEL_BONDING_MODE will be overwritten when connecting to AP +// To support this feature, we need to introduce WNI_CFG_TDLS_CHANNEL_BONDING_MODE +// As of now, we hardcoded to max channel bonding of dot11Mode (i.e HT80 for 11ac/HT40 for 11n) +// uint32 tdlsChannelBondingMode; /* * The scheme here is to fill out a 'tDot11fProbeRequest' structure @@ -963,7 +988,7 @@ static tSirRetStatus limSendTdlsDisRspFrame(tpAniSirGlobal pMac, * from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve Capabilities value\n")); + FL("could not retrieve Capabilities value")); } swapBitField16(caps, ( tANI_U16* )&tdlsDisRsp.Capabilities ); @@ -978,9 +1003,57 @@ static tSirRetStatus limSendTdlsDisRspFrame(tpAniSirGlobal pMac, /* Populate extended supported rates */ PopulateDot11fTdlsExtCapability( pMac, &tdlsDisRsp.ExtCap ); - /* Include HT Capability IE */ - //This does not depend on peer capabilities. If it is supported then it should be included - PopulateDot11fHTCaps( pMac, psessionEntry, &tdlsDisRsp.HTCaps ); + wlan_cfgGetInt(pMac,WNI_CFG_DOT11_MODE,&selfDot11Mode); + + if (psessionEntry->currentOperChannel <= SIR_11B_CHANNEL_END) + { + if (IS_DOT11_MODE_HT(selfDot11Mode)) + { + /* Include HT Capability IE */ + PopulateDot11fHTCaps( pMac, NULL, &tdlsDisRsp.HTCaps ); + tdlsDisRsp.HTCaps.present = 1; + /* hardcode NO channel bonding in 2.4Ghz */ + tdlsDisRsp.HTCaps.supportedChannelWidthSet = 0; + } + else + { + tdlsDisRsp.HTCaps.present = 0; + } +#ifdef WLAN_FEATURE_11AC + /* in 2.4Ghz, hardcode NO 11ac */ + tdlsDisRsp.VHTCaps.present = 0; +#endif + } + else + { + if (IS_DOT11_MODE_HT(selfDot11Mode)) + { + /* Include HT Capability IE */ + PopulateDot11fHTCaps( pMac, NULL, &tdlsDisRsp.HTCaps ); + + tdlsDisRsp.HTCaps.present = 1; + //Placeholder to support different channel bonding mode of TDLS than AP. + //wlan_cfgGetInt(pMac,WNI_CFG_TDLS_CHANNEL_BONDING_MODE,&tdlsChannelBondingMode); + //tdlsDisRsp.HTCaps.supportedChannelWidthSet = tdlsChannelBondingMode ? 1 : 0; + tdlsDisRsp.HTCaps.supportedChannelWidthSet = 1; // hardcode it to max + } + else + { + tdlsDisRsp.HTCaps.present = 0; + } +#ifdef WLAN_FEATURE_11AC + if (IS_DOT11_MODE_VHT(selfDot11Mode) && + IS_FEATURE_SUPPORTED_BY_FW(DOT11AC)) + { + /* Include VHT Capability IE */ + PopulateDot11fVHTCaps( pMac, &tdlsDisRsp.VHTCaps ); + } + else + { + tdlsDisRsp.VHTCaps.present = 0; + } +#endif + } /* * now we pack it. First, how much space are we going to need? @@ -989,7 +1062,7 @@ static tSirRetStatus limSendTdlsDisRspFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( status ) ) { limLog( pMac, LOGP, FL("Failed to calculate the packed size f" - "or a discovery Request (0x%08x).\n"), status ); + "or a discovery Request (0x%08x)."), status ); /* We'll fall back on the worst case scenario: */ nPayload = sizeof( tDot11fProbeRequest ); } @@ -997,7 +1070,7 @@ static tSirRetStatus limSendTdlsDisRspFrame(tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL("There were warnings while calculating" "the packed size for a discovery Request (" - "0x%08x).\n"), status ); + "0x%08x)."), status ); } /* @@ -1017,7 +1090,7 @@ static tSirRetStatus limSendTdlsDisRspFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a TDLS" - "Discovery Request.\n"), nBytes ); + "Discovery Request."), nBytes ); return eSIR_MEM_ALLOC_FAILED; } @@ -1053,7 +1126,7 @@ static tSirRetStatus limSendTdlsDisRspFrame(tpAniSirGlobal pMac, tdlsDisRsp.LinkIdentifier.bssid[4] = 0xde; tdlsDisRsp.LinkIdentifier.bssid[5] = 0xad; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("TDLS negative running: wrong BSSID %02x:%02x:%02x:%02x:%02x:%02x in TDLS Discovery Rsp\n"), \ + ("TDLS negative running: wrong BSSID %02x:%02x:%02x:%02x:%02x:%02x in TDLS Discovery Rsp"), \ tdlsDisRsp.LinkIdentifier.bssid[0], tdlsDisRsp.LinkIdentifier.bssid[1], tdlsDisRsp.LinkIdentifier.bssid[2], @@ -1069,7 +1142,7 @@ static tSirRetStatus limSendTdlsDisRspFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( status ) ) { limLog( pMac, LOGE, FL("Failed to pack a TDLS discovery req \ - (0x%08x).\n"), status ); + (0x%08x)."), status ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return eSIR_FAILURE; @@ -1077,7 +1150,7 @@ static tSirRetStatus limSendTdlsDisRspFrame(tpAniSirGlobal pMac, else if ( DOT11F_WARNED( status ) ) { limLog( pMac, LOGW, FL("There were warnings while packing TDLS" - "Discovery Request (0x%08x).\n") ); + "Discovery Request (0x%08x).") ); } #if 0 @@ -1094,7 +1167,7 @@ static tSirRetStatus limSendTdlsDisRspFrame(tpAniSirGlobal pMac, } #endif VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("transmitting Discovery response on direct link\n")) ; + ("transmitting Discovery response on direct link")) ; LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, TDLS_DEBUG_LOG_LEVEL, ("[TDLS] action %d (%s) -DIRECT-> OTA"), SIR_MAC_TDLS_DIS_RSP, limTraceTdlsActionString(SIR_MAC_TDLS_DIS_RSP) )); @@ -1114,7 +1187,7 @@ static tSirRetStatus limSendTdlsDisRspFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { pMac->lim.mgmtFrameSessionId = 0xff; - limLog( pMac, LOGE, FL("could not send TDLS Dis Request frame!\n" )); + limLog( pMac, LOGE, FL("could not send TDLS Dis Request frame!" )); return eSIR_FAILURE; } pMac->lim.mgmtFrameSessionId = psessionEntry->peSessionId; @@ -1140,6 +1213,12 @@ tSirRetStatus limSendTdlsLinkSetupReqFrame(tpAniSirGlobal pMac, tANI_U8 *pFrame; void *pPacket; eHalStatus halstatus; + uint32 selfDot11Mode; +// Placeholder to support different channel bonding mode of TDLS than AP. +// Today, WNI_CFG_CHANNEL_BONDING_MODE will be overwritten when connecting to AP +// To support this feature, we need to introduce WNI_CFG_TDLS_CHANNEL_BONDING_MODE +// As of now, we hardcoded to max channel bonding of dot11Mode (i.e HT80 for 11ac/HT40 for 11n) +// uint32 tdlsChannelBondingMode; /* * The scheme here is to fill out a 'tDot11fProbeRequest' structure @@ -1163,7 +1242,7 @@ tSirRetStatus limSendTdlsLinkSetupReqFrame(tpAniSirGlobal pMac, * from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve Capabilities value\n")); + FL("could not retrieve Capabilities value")); } swapBitField16(caps, ( tANI_U16* )&tdlsSetupReq.Capabilities ); @@ -1202,37 +1281,67 @@ tSirRetStatus limSendTdlsLinkSetupReqFrame(tpAniSirGlobal pMac, * of peer caps */ - /* Include HT Capability IE */ - PopulateDot11fHTCaps( pMac, NULL, &tdlsSetupReq.HTCaps ); + wlan_cfgGetInt(pMac,WNI_CFG_DOT11_MODE,&selfDot11Mode); + if (psessionEntry->currentOperChannel <= SIR_11B_CHANNEL_END) { - tdlsSetupReq.HTCaps.present = 1; - tdlsSetupReq.HTCaps.supportedChannelWidthSet = 0; - } - else - { - if (tdlsSetupReq.HTCaps.present) + if (IS_DOT11_MODE_HT(selfDot11Mode)) { - tdlsSetupReq.HTCaps.supportedChannelWidthSet = 1; // pVhtCaps->supportedChannelWidthSet; + /* Include HT Capability IE */ + PopulateDot11fHTCaps( pMac, NULL, &tdlsSetupReq.HTCaps ); + + tdlsSetupReq.HTCaps.present = 1; + /* hardcode NO channel bonding in 2.4Ghz */ + tdlsSetupReq.HTCaps.supportedChannelWidthSet = 0; } - } - /* Include VHT Capability IE */ - PopulateDot11fVHTCaps( pMac, &tdlsSetupReq.VHTCaps ); - if (psessionEntry->currentOperChannel <= SIR_11B_CHANNEL_END) - { + else + { + tdlsSetupReq.HTCaps.present = 0; + } +#ifdef WLAN_FEATURE_11AC + /* in 2.4Ghz, hardcode NO 11ac */ tdlsSetupReq.VHTCaps.present = 0; - tdlsSetupReq.VHTCaps.supportedChannelWidthSet = 0; - tdlsSetupReq.VHTCaps.ldpcCodingCap = 0; - tdlsSetupReq.VHTCaps.suBeamFormerCap = 0; +#endif } else { - if (tdlsSetupReq.VHTCaps.present) + if (IS_DOT11_MODE_HT(selfDot11Mode)) + { + /* Include HT Capability IE */ + PopulateDot11fHTCaps( pMac, NULL, &tdlsSetupReq.HTCaps ); + + tdlsSetupReq.HTCaps.present = 1; + //Placeholder to support different channel bonding mode of TDLS than AP. + //wlan_cfgGetInt(pMac,WNI_CFG_TDLS_CHANNEL_BONDING_MODE,&tdlsChannelBondingMode); + //tdlsSetupReq.HTCaps.supportedChannelWidthSet = tdlsChannelBondingMode ? 1 : 0; + tdlsSetupReq.HTCaps.supportedChannelWidthSet = 1; // hardcode it to max + } + else + { + tdlsSetupReq.HTCaps.present = 0; + } +#ifdef WLAN_FEATURE_11AC + if (IS_DOT11_MODE_VHT(selfDot11Mode) && + IS_FEATURE_SUPPORTED_BY_FW(DOT11AC)) + { + tANI_U16 aid; + tpDphHashNode pStaDs; + + pStaDs = dphLookupHashEntry(pMac, peerMac, &aid , &psessionEntry->dph.dphHashTable); + if (NULL != pStaDs) + { + tdlsSetupReq.AID.present = 1; + tdlsSetupReq.AID.assocId = aid | LIM_AID_MASK; // set bit 14 and 15 1's + } + + /* Include VHT Capability IE */ + PopulateDot11fVHTCaps( pMac, &tdlsSetupReq.VHTCaps ); + } + else { - tdlsSetupReq.VHTCaps.supportedChannelWidthSet = 1; // pVhtCaps->supportedChannelWidthSet; - tdlsSetupReq.VHTCaps.ldpcCodingCap = 1; // pVhtCaps->ldpcCodingCap - tdlsSetupReq.VHTCaps.suBeamFormerCap = 1; // pVhtCaps->suBeamFormerCap + tdlsSetupReq.VHTCaps.present = 0; } +#endif } /* * now we pack it. First, how much space are we going to need? @@ -1242,7 +1351,7 @@ tSirRetStatus limSendTdlsLinkSetupReqFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( status ) ) { limLog( pMac, LOGP, FL("Failed to calculate the packed size f" - "or a discovery Request (0x%08x).\n"), status ); + "or a discovery Request (0x%08x)."), status ); /* We'll fall back on the worst case scenario: */ nPayload = sizeof( tDot11fProbeRequest ); } @@ -1250,7 +1359,7 @@ tSirRetStatus limSendTdlsLinkSetupReqFrame(tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL("There were warnings while calculating" "the packed size for a discovery Request (" - "0x%08x).\n"), status ); + "0x%08x)."), status ); } @@ -1261,10 +1370,11 @@ tSirRetStatus limSendTdlsLinkSetupReqFrame(tpAniSirGlobal pMac, */ - nBytes = nPayload + sizeof( tSirMacMgmtHdr ) - + sizeof( eth_890d_header ) - + PAYLOAD_TYPE_TDLS_SIZE - + addIeLen; + nBytes = nPayload + ((IS_QOS_ENABLED(psessionEntry)) + ? sizeof(tSirMacDataHdr3a) : sizeof(tSirMacMgmtHdr)) + + sizeof( eth_890d_header ) + + PAYLOAD_TYPE_TDLS_SIZE + + addIeLen; /* Ok-- try to allocate memory from MGMT PKT pool */ @@ -1274,7 +1384,7 @@ tSirRetStatus limSendTdlsLinkSetupReqFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a TDLS" - "Discovery Request.\n"), nBytes ); + "Discovery Request."), nBytes ); return eSIR_MEM_ALLOC_FAILED; } @@ -1289,7 +1399,7 @@ tSirRetStatus limSendTdlsLinkSetupReqFrame(tpAniSirGlobal pMac, /* fill out the buffer descriptor */ header_offset = limPrepareTdlsFrameHeader(pMac, pFrame, - LINK_IDEN_ADDR_OFFSET(tdlsSetupReq), TDLS_LINK_AP, TDLS_INITIATOR, psessionEntry) ; + LINK_IDEN_ADDR_OFFSET(tdlsSetupReq), TDLS_LINK_AP, TDLS_INITIATOR, TID_AC_BK, psessionEntry) ; #ifdef FEATURE_WLAN_TDLS_NEGATIVE if(pMac->lim.gLimTdlsNegativeBehavior & LIM_TDLS_NEGATIVE_WRONG_BSSID_IN_SETUP_REQ) @@ -1297,7 +1407,7 @@ tSirRetStatus limSendTdlsLinkSetupReqFrame(tpAniSirGlobal pMac, tdlsSetupReq.LinkIdentifier.bssid[4] = 0xde; tdlsSetupReq.LinkIdentifier.bssid[5] = 0xad; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("TDLS negative running: wrong BSSID %02x:%02x:%02x:%02x:%02x:%02x in TDLS Setup Req\n"), \ + ("TDLS negative running: wrong BSSID %02x:%02x:%02x:%02x:%02x:%02x in TDLS Setup Req"), \ tdlsSetupReq.LinkIdentifier.bssid[0], tdlsSetupReq.LinkIdentifier.bssid[1], tdlsSetupReq.LinkIdentifier.bssid[2], @@ -1316,7 +1426,7 @@ tSirRetStatus limSendTdlsLinkSetupReqFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( status ) ) { limLog( pMac, LOGE, FL("Failed to pack a TDLS discovery req \ - (0x%08x).\n"), status ); + (0x%08x)."), status ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return eSIR_FAILURE; @@ -1324,7 +1434,7 @@ tSirRetStatus limSendTdlsLinkSetupReqFrame(tpAniSirGlobal pMac, else if ( DOT11F_WARNED( status ) ) { limLog( pMac, LOGW, FL("There were warnings while packing TDLS" - "Discovery Request (0x%08x).\n") ); + "Discovery Request (0x%08x).") ); } //Copy the additional IE. @@ -1333,7 +1443,7 @@ tSirRetStatus limSendTdlsLinkSetupReqFrame(tpAniSirGlobal pMac, //if there is any IOT issue. if( addIeLen != 0 ) { - LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, ("Copy Additional Ie Len = %d"), + LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, ("Copy Additional Ie Len = %d"), addIeLen )); palCopyMemory( pMac->hHdd, pFrame + header_offset + nPayload, addIe, addIeLen ); } @@ -1344,7 +1454,7 @@ tSirRetStatus limSendTdlsLinkSetupReqFrame(tpAniSirGlobal pMac, halstatus = halTxFrameWithTxComplete( pMac, pPacket, ( tANI_U16 ) nBytes, HAL_TXRX_FRM_802_11_DATA, ANI_TXDIR_TODS, - 7,//SMAC_SWBD_TX_TID_MGMT_HIGH, + TID_AC_BK, limTxComplete, pFrame, limMgmtTXComplete, HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME ); @@ -1352,7 +1462,7 @@ tSirRetStatus limSendTdlsLinkSetupReqFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { pMac->lim.mgmtFrameSessionId = 0xff; - limLog( pMac, LOGE, FL("could not send TDLS Dis Request frame!\n" )); + limLog( pMac, LOGE, FL("could not send TDLS Dis Request frame!" )); return eSIR_FAILURE; } pMac->lim.mgmtFrameSessionId = psessionEntry->peSessionId; @@ -1401,7 +1511,7 @@ tSirRetStatus limSendTdlsTeardownFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( status ) ) { limLog( pMac, LOGP, FL("Failed to calculate the packed size f" - "or a discovery Request (0x%08x).\n"), status ); + "or a discovery Request (0x%08x)."), status ); /* We'll fall back on the worst case scenario: */ nPayload = sizeof( tDot11fProbeRequest ); } @@ -1409,7 +1519,7 @@ tSirRetStatus limSendTdlsTeardownFrame(tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL("There were warnings while calculating" "the packed size for a discovery Request (" - "0x%08x).\n"), status ); + "0x%08x)."), status ); } @@ -1420,10 +1530,11 @@ tSirRetStatus limSendTdlsTeardownFrame(tpAniSirGlobal pMac, */ - nBytes = nPayload + sizeof( tSirMacMgmtHdr ) - + sizeof( eth_890d_header ) - + PAYLOAD_TYPE_TDLS_SIZE - + addIeLen; + nBytes = nPayload + ((IS_QOS_ENABLED(psessionEntry)) + ? sizeof(tSirMacDataHdr3a) : sizeof(tSirMacMgmtHdr)) + + sizeof( eth_890d_header ) + + PAYLOAD_TYPE_TDLS_SIZE + + addIeLen; #ifndef NO_PAD_TDLS_MIN_8023_SIZE /* IOT issue with some AP : some AP doesn't like the data packet size < minimum 802.3 frame length (64) @@ -1450,7 +1561,7 @@ tSirRetStatus limSendTdlsTeardownFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a TDLS" - "Discovery Request.\n"), nBytes ); + "Discovery Request."), nBytes ); return eSIR_MEM_ALLOC_FAILED; } @@ -1469,7 +1580,7 @@ tSirRetStatus limSendTdlsTeardownFrame(tpAniSirGlobal pMac, (reason == eSIR_MAC_TDLS_TEARDOWN_PEER_UNREACHABLE) ? TDLS_LINK_AP : TDLS_LINK_DIRECT, (responder == TRUE) ? TDLS_RESPONDER : TDLS_INITIATOR, - psessionEntry) ; + TID_AC_VI, psessionEntry) ; status = dot11fPackTDLSTeardown( pMac, &teardown, pFrame + header_offset, nPayload, &nPayload ); @@ -1477,7 +1588,7 @@ tSirRetStatus limSendTdlsTeardownFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( status ) ) { limLog( pMac, LOGE, FL("Failed to pack a TDLS Teardown req \ - (0x%08x).\n"), status ); + (0x%08x)."), status ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return eSIR_FAILURE; @@ -1485,7 +1596,7 @@ tSirRetStatus limSendTdlsTeardownFrame(tpAniSirGlobal pMac, else if ( DOT11F_WARNED( status ) ) { limLog( pMac, LOGW, FL("There were warnings while packing TDLS" - "Teardown Request (0x%08x).\n") ); + "Teardown Request (0x%08x).") ); } #if 0 if(pMac->hal.pCBackFnTxComp == NULL) @@ -1507,7 +1618,7 @@ tSirRetStatus limSendTdlsTeardownFrame(tpAniSirGlobal pMac, if( addIeLen != 0 ) { - LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, ("Copy Additional Ie Len = %d"), + LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, ("Copy Additional Ie Len = %d"), addIeLen )); palCopyMemory( pMac->hHdd, pFrame + header_offset + nPayload, addIe, addIeLen ); } @@ -1539,14 +1650,14 @@ tSirRetStatus limSendTdlsTeardownFrame(tpAniSirGlobal pMac, halstatus = halTxFrameWithTxComplete( pMac, pPacket, ( tANI_U16 ) nBytes, HAL_TXRX_FRM_802_11_DATA, ANI_TXDIR_TODS, - 7, + TID_AC_VI, limTxComplete, pFrame, limMgmtTXComplete, HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME ); if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { pMac->lim.mgmtFrameSessionId = 0xff; - limLog( pMac, LOGE, FL("could not send TDLS Dis Request frame!\n" )); + limLog( pMac, LOGE, FL("could not send TDLS Dis Request frame!" )); return eSIR_FAILURE; } @@ -1571,6 +1682,12 @@ static tSirRetStatus limSendTdlsSetupRspFrame(tpAniSirGlobal pMac, tANI_U8 *pFrame; void *pPacket; eHalStatus halstatus; + uint32 selfDot11Mode; +// Placeholder to support different channel bonding mode of TDLS than AP. +// Today, WNI_CFG_CHANNEL_BONDING_MODE will be overwritten when connecting to AP +// To support this feature, we need to introduce WNI_CFG_TDLS_CHANNEL_BONDING_MODE +// As of now, we hardcoded to max channel bonding of dot11Mode (i.e HT80 for 11ac/HT40 for 11n) +// uint32 tdlsChannelBondingMode; /* * The scheme here is to fill out a 'tDot11fProbeRequest' structure @@ -1597,7 +1714,7 @@ static tSirRetStatus limSendTdlsSetupRspFrame(tpAniSirGlobal pMac, * from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve Capabilities value\n")); + FL("could not retrieve Capabilities value")); } swapBitField16(caps, ( tANI_U16* )&tdlsSetupRsp.Capabilities ); @@ -1629,37 +1746,69 @@ static tSirRetStatus limSendTdlsSetupRspFrame(tpAniSirGlobal pMac, tdlsSetupRsp.QOSCapsStation.acvi_uapsd = 1; tdlsSetupRsp.QOSCapsStation.acvo_uapsd = 1; - PopulateDot11fHTCaps( pMac, NULL, &tdlsSetupRsp.HTCaps ); + wlan_cfgGetInt(pMac,WNI_CFG_DOT11_MODE,&selfDot11Mode); + if (psessionEntry->currentOperChannel <= SIR_11B_CHANNEL_END) { - tdlsSetupRsp.HTCaps.present = 1; - tdlsSetupRsp.HTCaps.supportedChannelWidthSet = 0; - } - else - { - if (tdlsSetupRsp.HTCaps.present) + if (IS_DOT11_MODE_HT(selfDot11Mode)) { - tdlsSetupRsp.HTCaps.supportedChannelWidthSet = 1; // pVhtCaps->supportedChannelWidthSet; + /* Include HT Capability IE */ + PopulateDot11fHTCaps( pMac, NULL, &tdlsSetupRsp.HTCaps ); + + tdlsSetupRsp.HTCaps.present = 1; + /* hardcode NO channel bonding in 2.4Ghz */ + tdlsSetupRsp.HTCaps.supportedChannelWidthSet = 0; } - } - /* Include VHT Capability IE */ - PopulateDot11fVHTCaps( pMac, &tdlsSetupRsp.VHTCaps ); - if (psessionEntry->currentOperChannel <= SIR_11B_CHANNEL_END) - { + else + { + tdlsSetupRsp.HTCaps.present = 0; + } +#ifdef WLAN_FEATURE_11AC + /* in 2.4Ghz, hardcode NO 11ac */ tdlsSetupRsp.VHTCaps.present = 0; - tdlsSetupRsp.VHTCaps.supportedChannelWidthSet = 0; - tdlsSetupRsp.VHTCaps.ldpcCodingCap = 0; - tdlsSetupRsp.VHTCaps.suBeamFormerCap = 0; +#endif } else { - if (tdlsSetupRsp.VHTCaps.present) + if (IS_DOT11_MODE_HT(selfDot11Mode)) + { + /* Include HT Capability IE */ + PopulateDot11fHTCaps( pMac, NULL, &tdlsSetupRsp.HTCaps ); + + tdlsSetupRsp.HTCaps.present = 1; + //Placeholder to support different channel bonding mode of TDLS than AP. + //wlan_cfgGetInt(pMac,WNI_CFG_TDLS_CHANNEL_BONDING_MODE,&tdlsChannelBondingMode); + //tdlsSetupRsp.HTCaps.supportedChannelWidthSet = tdlsChannelBondingMode ? 1 : 0; + tdlsSetupRsp.HTCaps.supportedChannelWidthSet = 1; // hardcode it to max + } + else { - tdlsSetupRsp.VHTCaps.supportedChannelWidthSet = 1; // pVhtCaps->supportedChannelWidthSet; - tdlsSetupRsp.VHTCaps.ldpcCodingCap = 1; // pVhtCaps->ldpcCodingCap - tdlsSetupRsp.VHTCaps.suBeamFormerCap = 1; // pVhtCaps->suBeamFormerCap + tdlsSetupRsp.HTCaps.present = 0; } +#ifdef WLAN_FEATURE_11AC + if (IS_DOT11_MODE_VHT(selfDot11Mode) && + IS_FEATURE_SUPPORTED_BY_FW(DOT11AC)) + { + tANI_U16 aid; + tpDphHashNode pStaDs; + + pStaDs = dphLookupHashEntry(pMac, peerMac, &aid , &psessionEntry->dph.dphHashTable); + if (NULL != pStaDs) + { + tdlsSetupRsp.AID.present = 1; + tdlsSetupRsp.AID.assocId = aid | LIM_AID_MASK; // set bit 14 and 15 1's + } + + /* Include VHT Capability IE */ + PopulateDot11fVHTCaps( pMac, &tdlsSetupRsp.VHTCaps ); + } + else + { + tdlsSetupRsp.VHTCaps.present = 0; + } +#endif } + tdlsSetupRsp.Status.status = setupStatus ; /* @@ -1670,7 +1819,7 @@ static tSirRetStatus limSendTdlsSetupRspFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( status ) ) { limLog( pMac, LOGP, FL("Failed to calculate the packed size f" - "or a discovery Request (0x%08x).\n"), status ); + "or a discovery Request (0x%08x)."), status ); /* We'll fall back on the worst case scenario: */ nPayload = sizeof( tDot11fProbeRequest ); } @@ -1678,7 +1827,7 @@ static tSirRetStatus limSendTdlsSetupRspFrame(tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL("There were warnings while calculating" "the packed size for a discovery Request (" - "0x%08x).\n"), status ); + "0x%08x)."), status ); } /* @@ -1688,10 +1837,11 @@ static tSirRetStatus limSendTdlsSetupRspFrame(tpAniSirGlobal pMac, */ - nBytes = nPayload + sizeof( tSirMacMgmtHdr ) - + sizeof( eth_890d_header ) - + PAYLOAD_TYPE_TDLS_SIZE - + addIeLen; + nBytes = nPayload + ((IS_QOS_ENABLED(psessionEntry)) + ? sizeof(tSirMacDataHdr3a) : sizeof(tSirMacMgmtHdr)) + + sizeof( eth_890d_header ) + + PAYLOAD_TYPE_TDLS_SIZE + + addIeLen; /* Ok-- try to allocate memory from MGMT PKT pool */ @@ -1701,7 +1851,7 @@ static tSirRetStatus limSendTdlsSetupRspFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a TDLS" - "Discovery Request.\n"), nBytes ); + "Discovery Request."), nBytes ); return eSIR_MEM_ALLOC_FAILED; } @@ -1718,7 +1868,7 @@ static tSirRetStatus limSendTdlsSetupRspFrame(tpAniSirGlobal pMac, header_offset = limPrepareTdlsFrameHeader(pMac, pFrame, LINK_IDEN_ADDR_OFFSET(tdlsSetupRsp), TDLS_LINK_AP, TDLS_RESPONDER, - psessionEntry) ; + TID_AC_BK, psessionEntry) ; #ifdef FEATURE_WLAN_TDLS_NEGATIVE if(pMac->lim.gLimTdlsNegativeBehavior & LIM_TDLS_NEGATIVE_WRONG_BSSID_IN_SETUP_RSP) @@ -1726,7 +1876,7 @@ static tSirRetStatus limSendTdlsSetupRspFrame(tpAniSirGlobal pMac, tdlsSetupRsp.LinkIdentifier.bssid[4] = 0xde; tdlsSetupRsp.LinkIdentifier.bssid[5] = 0xad; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("TDLS negative running: wrong BSSID %02x:%02x:%02x:%02x:%02x:%02x in TDLS Setup Rsp\n"), \ + ("TDLS negative running: wrong BSSID %02x:%02x:%02x:%02x:%02x:%02x in TDLS Setup Rsp"), \ tdlsSetupRsp.LinkIdentifier.bssid[0], tdlsSetupRsp.LinkIdentifier.bssid[1], tdlsSetupRsp.LinkIdentifier.bssid[2], @@ -1744,7 +1894,7 @@ static tSirRetStatus limSendTdlsSetupRspFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( status ) ) { limLog( pMac, LOGE, FL("Failed to pack a TDLS discovery req \ - (0x%08x).\n"), status ); + (0x%08x)."), status ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return eSIR_FAILURE; @@ -1752,7 +1902,7 @@ static tSirRetStatus limSendTdlsSetupRspFrame(tpAniSirGlobal pMac, else if ( DOT11F_WARNED( status ) ) { limLog( pMac, LOGW, FL("There were warnings while packing TDLS" - "Discovery Request (0x%08x).\n") ); + "Discovery Request (0x%08x).") ); } //Copy the additional IE. @@ -1771,14 +1921,14 @@ static tSirRetStatus limSendTdlsSetupRspFrame(tpAniSirGlobal pMac, HAL_TXRX_FRM_802_11_DATA, ANI_TXDIR_TODS, //ANI_TXDIR_IBSS, - 7, + TID_AC_BK, limTxComplete, pFrame, limMgmtTXComplete, HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME ); if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { pMac->lim.mgmtFrameSessionId = 0xff; - limLog( pMac, LOGE, FL("could not send TDLS Dis Request frame!\n" )); + limLog( pMac, LOGE, FL("could not send TDLS Dis Request frame!" )); return eSIR_FAILURE; } pMac->lim.mgmtFrameSessionId = psessionEntry->peSessionId; @@ -1855,7 +2005,7 @@ tSirRetStatus limSendTdlsLinkSetupCnfFrame(tpAniSirGlobal pMac, tSirMacAddr peer if ( DOT11F_FAILED( status ) ) { limLog( pMac, LOGP, FL("Failed to calculate the packed size f" - "or a discovery Request (0x%08x).\n"), status ); + "or a discovery Request (0x%08x)."), status ); /* We'll fall back on the worst case scenario: */ nPayload = sizeof( tDot11fProbeRequest ); } @@ -1863,7 +2013,7 @@ tSirRetStatus limSendTdlsLinkSetupCnfFrame(tpAniSirGlobal pMac, tSirMacAddr peer { limLog( pMac, LOGW, FL("There were warnings while calculating" "the packed size for a discovery Request (" - "0x%08x).\n"), status ); + "0x%08x)."), status ); } /* @@ -1873,10 +2023,11 @@ tSirRetStatus limSendTdlsLinkSetupCnfFrame(tpAniSirGlobal pMac, tSirMacAddr peer */ - nBytes = nPayload + sizeof( tSirMacMgmtHdr ) - + sizeof( eth_890d_header ) - + PAYLOAD_TYPE_TDLS_SIZE - + addIeLen; + nBytes = nPayload + ((IS_QOS_ENABLED(psessionEntry)) + ? sizeof(tSirMacDataHdr3a) : sizeof(tSirMacMgmtHdr)) + + sizeof( eth_890d_header ) + + PAYLOAD_TYPE_TDLS_SIZE + + addIeLen; #ifndef NO_PAD_TDLS_MIN_8023_SIZE /* IOT issue with some AP : some AP doesn't like the data packet size < minimum 802.3 frame length (64) @@ -1904,7 +2055,7 @@ tSirRetStatus limSendTdlsLinkSetupCnfFrame(tpAniSirGlobal pMac, tSirMacAddr peer if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a TDLS" - "Discovery Request.\n"), nBytes ); + "Discovery Request."), nBytes ); return eSIR_MEM_ALLOC_FAILED; } @@ -1920,13 +2071,13 @@ tSirRetStatus limSendTdlsLinkSetupCnfFrame(tpAniSirGlobal pMac, tSirMacAddr peer header_offset = limPrepareTdlsFrameHeader(pMac, pFrame, LINK_IDEN_ADDR_OFFSET(tdlsSetupCnf), TDLS_LINK_AP, TDLS_INITIATOR, - psessionEntry) ; + TID_AC_VI, psessionEntry) ; #ifdef FEATURE_WLAN_TDLS_NEGATIVE if(pMac->lim.gLimTdlsNegativeBehavior & LIM_TDLS_NEGATIVE_STATUS_37_IN_SETUP_CNF) { tdlsSetupCnf.StatusCode.statusCode = 37; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("TDLS negative running: StatusCode = 37 in TDLS Setup Cnf\n")); + ("TDLS negative running: StatusCode = 37 in TDLS Setup Cnf")); } #endif status = dot11fPackTDLSSetupCnf( pMac, &tdlsSetupCnf, pFrame @@ -1935,7 +2086,7 @@ tSirRetStatus limSendTdlsLinkSetupCnfFrame(tpAniSirGlobal pMac, tSirMacAddr peer if ( DOT11F_FAILED( status ) ) { limLog( pMac, LOGE, FL("Failed to pack a TDLS discovery req \ - (0x%08x).\n"), status ); + (0x%08x)."), status ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return eSIR_FAILURE; @@ -1943,7 +2094,7 @@ tSirRetStatus limSendTdlsLinkSetupCnfFrame(tpAniSirGlobal pMac, tSirMacAddr peer else if ( DOT11F_WARNED( status ) ) { limLog( pMac, LOGW, FL("There were warnings while packing TDLS" - "Discovery Request (0x%08x).\n") ); + "Discovery Request (0x%08x).") ); } #if 0 if(pMac->hal.pCBackFnTxComp == NULL) @@ -1999,7 +2150,7 @@ tSirRetStatus limSendTdlsLinkSetupCnfFrame(tpAniSirGlobal pMac, tSirMacAddr peer halstatus = halTxFrameWithTxComplete( pMac, pPacket, ( tANI_U16 ) nBytes, HAL_TXRX_FRM_802_11_DATA, ANI_TXDIR_TODS, - 7, + TID_AC_VI, limTxComplete, pFrame, limMgmtTXComplete, HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME ); @@ -2008,7 +2159,7 @@ tSirRetStatus limSendTdlsLinkSetupCnfFrame(tpAniSirGlobal pMac, tSirMacAddr peer if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { pMac->lim.mgmtFrameSessionId = 0xff; - limLog( pMac, LOGE, FL("could not send TDLS Dis Request frame!\n" )); + limLog( pMac, LOGE, FL("could not send TDLS Dis Request frame!" )); return eSIR_FAILURE; } @@ -2108,7 +2259,7 @@ void limTdlsUpdateLinkReqPeerInfo(tpAniSirGlobal pMac, { ConvertQOSCapsStation(pMac->hHdd, &setupPeer->qosCaps, &setupReq->QOSCapsStation) ; - LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,("setupReq->SPLen=%d (be %d %d %d %d vo) more %d qack %d.\n"), \ + LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,("setupReq->SPLen=%d (be %d %d %d %d vo) more %d qack %d."), \ setupReq->QOSCapsStation.max_sp_length, setupReq->QOSCapsStation.acbe_uapsd, \ setupReq->QOSCapsStation.acbk_uapsd, setupReq->QOSCapsStation.acvi_uapsd, \ setupReq->QOSCapsStation.acvo_uapsd, setupReq->QOSCapsStation.more_data_ack, \ @@ -2159,7 +2310,7 @@ void limTdlsUpdateLinkRspPeerInfo(tpAniSirGlobal pMac, { ConvertQOSCapsStation(pMac->hHdd, &setupPeer->qosCaps, &setupRsp->QOSCapsStation) ; - LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, ("setupRsp->SPLen=%d (be %d %d %d %d vo) more %d qack %d.\n"), \ + LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, ("setupRsp->SPLen=%d (be %d %d %d %d vo) more %d qack %d."), \ setupRsp->QOSCapsStation.max_sp_length, setupRsp->QOSCapsStation.acbe_uapsd, \ setupRsp->QOSCapsStation.acbk_uapsd, setupRsp->QOSCapsStation.acvi_uapsd, \ setupRsp->QOSCapsStation.acvo_uapsd, setupRsp->QOSCapsStation.more_data_ack, \ @@ -2300,7 +2451,7 @@ static tSirRetStatus limTdlsPopulateDot11fHTCaps(tpAniSirGlobal pMac, tpPESessio pDot11f->rxAS = pASCapabilityInfo->rxAS; pDot11f->txSoundingPPDUs = pASCapabilityInfo->txSoundingPPDUs; - pDot11f->present = 1; + pDot11f->present = pTdlsAddStaReq->htcap_present; return eSIR_SUCCESS; @@ -2322,7 +2473,7 @@ limTdlsPopulateDot11fVHTCaps(tpAniSirGlobal pMac, tSirMacVHTRxSupDataRateInfo vhtRxsupDataRateInfo; } uVHTSupDataRateInfo; - pDot11f->present = 1; + pDot11f->present = pTdlsAddStaReq->vhtcap_present; nCfgValue = pTdlsAddStaReq->vhtCap.vhtCapInfo; uVHTCapabilityInfo.nCfgValue32 = nCfgValue; @@ -2396,7 +2547,7 @@ limTdlsPopulateMatchingRateSet(tpAniSirGlobal pMac, &val) != eSIR_SUCCESS) { /// Could not get rateset from CFG. Log error. - limLog(pMac, LOGP, FL("could not retrieve rateset\n")); + limLog(pMac, LOGP, FL("could not retrieve rateset")); } tempRateSet.numRates = val; @@ -2415,7 +2566,7 @@ limTdlsPopulateMatchingRateSet(tpAniSirGlobal pMac, if ((tempRateSet.numRates + tempRateSet2.numRates) > 12) { - PELOGE(limLog(pMac, LOGE, FL("more than 12 rates in CFG\n"));) + PELOGE(limLog(pMac, LOGE, FL("more than 12 rates in CFG"));) goto error; } @@ -2481,7 +2632,7 @@ limTdlsPopulateMatchingRateSet(tpAniSirGlobal pMac, #ifdef FEATURE_WLAN_NON_INTEGRATED_SOC if ((bRateIndex > HAL_NUM_11B_RATES) || (aRateIndex > HAL_NUM_11A_RATES)) { - limLog(pMac, LOGE, FL("Invalid number of rates (11b->%d, 11a->%d)\n"), + limLog(pMac, LOGE, FL("Invalid number of rates (11b->%d, 11a->%d)"), bRateIndex, aRateIndex); return eSIR_FAILURE; } @@ -2514,7 +2665,7 @@ limTdlsPopulateMatchingRateSet(tpAniSirGlobal pMac, &val) != eSIR_SUCCESS) { /// Could not get rateset from CFG. Log error. - limLog(pMac, LOGP, FL("could not retrieve supportedMCSSet\n")); + limLog(pMac, LOGP, FL("could not retrieve supportedMCSSet")); goto error; } @@ -2655,7 +2806,8 @@ static void limTdlsUpdateHashNodeInfo(tpAniSirGlobal pMac, tDphHashNode *pStaDs, if (pVhtCaps->present) { pStaDs->mlmStaContext.vhtCapability = 1 ; - pStaDs->vhtSupportedChannelWidthSet= pVhtCaps->supportedChannelWidthSet; + pStaDs->vhtSupportedChannelWidthSet = WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ; + pStaDs->htSupportedChannelWidthSet = eHT_CHANNEL_WIDTH_40MHZ ; pStaDs->vhtLdpcCapable = pVhtCaps->ldpcCodingCap; pStaDs->vhtBeamFormerCapable= pVhtCaps->suBeamFormerCap; // TODO , is it necessary , Sunil??? @@ -2664,6 +2816,7 @@ static void limTdlsUpdateHashNodeInfo(tpAniSirGlobal pMac, tDphHashNode *pStaDs, else { pStaDs->mlmStaContext.vhtCapability = 0 ; + pStaDs->vhtSupportedChannelWidthSet = WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ; } #endif /*Calculate the Secondary Coannel Offset */ @@ -2748,7 +2901,7 @@ tSirTdlsPeerInfo *limTdlsFindDisPeer(tpAniSirGlobal pMac, tSirMacAddr peerMac) { peerInfo = &discoveryList->tdlsDisPeerInfo ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("Peer in discovery list = %02x, %02x, %02x, %02x, %02x, %02x \n"), + ("Peer in discovery list = %02x, %02x, %02x, %02x, %02x, %02x "), peerInfo->peerMac[0], peerInfo->peerMac[1], peerInfo->peerMac[2], @@ -2816,7 +2969,7 @@ static tANI_U8 limTdlsFindSetupPeerByState(tpAniSirGlobal pMac, tANI_U8 state, while (linkSetupList != NULL) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("peer state = %02x\n"), (linkSetupList)->tdls_link_state) ; + ("peer state = %02x"), (linkSetupList)->tdls_link_state) ; if((linkSetupList)->tdls_link_state == state) { checkNode = TDLS_NODE_FOUND ; @@ -2848,7 +3001,7 @@ void limTdlsDelLinkPeer(tpAniSirGlobal pMac, tSirMacAddr peerMac) sizeof(tSirMacAddr)) ) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("Del Node for Peer = %02x,%02x,%02x,%02x,%02x,%02x\n"), + ("Del Node for Peer = %02x,%02x,%02x,%02x,%02x,%02x"), currentNode->peerMac[0], currentNode->peerMac[1], currentNode->peerMac[2], @@ -2893,19 +3046,19 @@ static tSirRetStatus limProcessTdlsDisReqFrame(tpAniSirGlobal pMac, status = dot11fUnpackTDLSDisReq(pMac, pBody, frmLen, &tdlsDisReq) ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_WARN, - ("TDLS dis request dialog = %d\n"), tdlsDisReq.DialogToken.token); + ("TDLS dis request dialog = %d"), tdlsDisReq.DialogToken.token); if ( DOT11F_FAILED( status ) ) { limLog(pMac, LOGE, FL("Failed to parse TDLS discovery Request \ - frame (0x%08x, %d bytes):\n"),status, frmLen); + frame (0x%08x, %d bytes):"),status, frmLen); PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frmLen);) return eSIR_FAILURE; } else if ( DOT11F_WARNED( status ) ) { limLog( pMac, LOGW, FL("There were warnings while unpacking an\ - TDLS discovery Request frame (0x%08x," "%d bytes):\n"), + TDLS discovery Request frame (0x%08x," "%d bytes):"), status, frmLen ); PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frmLen);) } @@ -2920,7 +3073,7 @@ static tSirRetStatus limProcessTdlsDisReqFrame(tpAniSirGlobal pMac, if(NULL == psessionEntry) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, \ - ("no Seesion entry for TDLS session (bssid %02x:%02x:%02x:%02x:%02x:%02x)\n"), \ + ("no Seesion entry for TDLS session (bssid %02x:%02x:%02x:%02x:%02x:%02x)"), \ tdlsDisReq.LinkIdentifier.bssid[0], tdlsDisReq.LinkIdentifier.bssid[1], tdlsDisReq.LinkIdentifier.bssid[2], @@ -2936,7 +3089,7 @@ static tSirRetStatus limProcessTdlsDisReqFrame(tpAniSirGlobal pMac, status = palEqualMemory(pMac->hHdd, &psessionEntry->bssId[0], &tdlsDisReq.LinkIdentifier.bssid[0], sizeof(tSirMacAddr)) ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("lim BSSID %02x, %02x, %02x, %02x, %02x, %02x\n"), + ("lim BSSID %02x, %02x, %02x, %02x, %02x, %02x"), psessionEntry->bssId[0], psessionEntry->bssId[1], psessionEntry->bssId[2], @@ -2945,7 +3098,7 @@ static tSirRetStatus limProcessTdlsDisReqFrame(tpAniSirGlobal pMac, psessionEntry->bssId[5]) ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("Dis req from BSSID %02x, %02x, %02x, %02x, %02x, %02x\n"), + ("Dis req from BSSID %02x, %02x, %02x, %02x, %02x, %02x"), tdlsDisReq.LinkIdentifier.bssid[0], tdlsDisReq.LinkIdentifier.bssid[1], tdlsDisReq.LinkIdentifier.bssid[2], @@ -2955,7 +3108,7 @@ static tSirRetStatus limProcessTdlsDisReqFrame(tpAniSirGlobal pMac, ) ; if(!status) { - limLog( pMac, LOGE, FL("TDLS discovery request frame from other BSS -> something wrong. Check RXP filter\n")) ; + limLog( pMac, LOGE, FL("TDLS discovery request frame from other BSS -> something wrong. Check RXP filter")) ; return eSIR_FAILURE ; } @@ -2969,7 +3122,7 @@ static tSirRetStatus limProcessTdlsDisReqFrame(tpAniSirGlobal pMac, sizeof(tSirMacAddr)) ; if(status) { - limLog( pMac, LOGE, FL("Echo of our TDLS discovery request frame\n")) ; + limLog( pMac, LOGE, FL("Echo of our TDLS discovery request frame")) ; return eSIR_FAILURE ; } @@ -3000,7 +3153,7 @@ static tSirRetStatus limProcessTdlsDisReqFrame(tpAniSirGlobal pMac, if(status != eHAL_STATUS_SUCCESS) { limLog(pMac, LOGP, FL("alloc fail for TDLS discovery \ - reponse info\n")) ; + reponse info")) ; return eSIR_FAILURE ; } @@ -3047,7 +3200,7 @@ static tSirRetStatus limProcessTdlsDisReqFrame(tpAniSirGlobal pMac, * from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve Capabilities value\n")); + FL("could not retrieve Capabilities value")); } swapBitField16(caps, ( tANI_U16* )&capsInfo ); /* update Caps Info */ @@ -3080,7 +3233,7 @@ static tSirRetStatus limProcessTdlsDisReqFrame(tpAniSirGlobal pMac, peerInfo, psessionEntry)) { VOS_ASSERT(0) ; - limLog(pMac, LOGE, "Add STA for dis response is failed \n") ; + limLog(pMac, LOGE, "Add STA for dis response is failed ") ; return eSIR_FAILURE ; } } /* use setup link sta ID for discovery rsp */ @@ -3095,7 +3248,7 @@ static tSirRetStatus limProcessTdlsDisReqFrame(tpAniSirGlobal pMac, else { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("discovery procedure in progress for this peer\n")) ; + ("discovery procedure in progress for this peer")) ; } return eSIR_SUCCESS ; @@ -3123,14 +3276,14 @@ static tSirRetStatus limProcessTdlsSetupReqFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( status ) ) { limLog(pMac, LOGE, FL("Failed to parse TDLS discovery Request \ - frame (0x%08x, %d bytes):\n"),status, frmLen); + frame (0x%08x, %d bytes):"),status, frmLen); PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frmLen);) return eSIR_FAILURE; } else if ( DOT11F_WARNED( status ) ) { limLog( pMac, LOGW, FL("There were warnings while unpacking an\ - TDLS setup Request frame (0x%08x," "%d bytes):\n"), + TDLS setup Request frame (0x%08x," "%d bytes):"), status, pBody ); PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frmLen);) } @@ -3144,7 +3297,7 @@ static tSirRetStatus limProcessTdlsSetupReqFrame(tpAniSirGlobal pMac, if(NULL == psessionEntry) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, \ - ("no Seesion entry for TDLS session (bssid %02x:%02x:%02x:%02x:%02x:%02x)\n"), \ + ("no Seesion entry for TDLS session (bssid %02x:%02x:%02x:%02x:%02x:%02x)"), \ tdlsSetupReq.LinkIdentifier.bssid[0], tdlsSetupReq.LinkIdentifier.bssid[1], tdlsSetupReq.LinkIdentifier.bssid[2], @@ -3162,7 +3315,7 @@ static tSirRetStatus limProcessTdlsSetupReqFrame(tpAniSirGlobal pMac, if(!status) { - limLog( pMac, LOGE, FL("TDLS setup request frame from other BSS -> something wrong. Check RXP filter\n")) ; + limLog( pMac, LOGE, FL("TDLS setup request frame from other BSS -> something wrong. Check RXP filter")) ; limSendTdlsSetupRspFrame(pMac, tdlsSetupReq.LinkIdentifier.InitStaAddr, tdlsSetupReq.DialogToken.token , psessionEntry, TDLS_SETUP_STATUS_FAILURE, NULL, 0 ) ; @@ -3174,13 +3327,13 @@ static tSirRetStatus limProcessTdlsSetupReqFrame(tpAniSirGlobal pMac, { /* simply ignore this setup request packet */ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("TDLS negative running: ignore TDLS Setup Req packet\n")); + ("TDLS negative running: ignore TDLS Setup Req packet")); return eSIR_SUCCESS ; } if(pMac->lim.gLimTdlsNegativeBehavior & LIM_TDLS_NEGATIVE_SEND_REQ_TO_SETUP_REQ) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("TDLS negative running: send TDLS Setup Req to peer TDLS Setup Req\n")); + ("TDLS negative running: send TDLS Setup Req to peer TDLS Setup Req")); /* format TDLS discovery request frame and transmit it */ limSendTdlsLinkSetupReqFrame(pMac, tdlsSetupReq.LinkIdentifier.InitStaAddr, tdlsSetupReq.DialogToken.token, psessionEntry, NULL, 0) ; @@ -3195,9 +3348,9 @@ static tSirRetStatus limProcessTdlsSetupReqFrame(tpAniSirGlobal pMac, tANI_U32 tdlsStateStatus = TDLS_LINK_SETUP_START_STATE ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("Link is already setup with this peer\n" )) ; + ("Link is already setup with this peer" )) ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("state = %d\n"), tmpSetupPeer->tdls_link_state) ; + ("state = %d"), tmpSetupPeer->tdls_link_state) ; //return eSIR_FAILURE ; if(tmpSetupPeer == NULL) @@ -3215,7 +3368,7 @@ static tSirRetStatus limProcessTdlsSetupReqFrame(tpAniSirGlobal pMac, macCompare= vos_mem_compare2(tmpSetupPeer->peerMac, psessionEntry->selfMacAddr, sizeof(tSirMacAddr)) ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("MAC comparison Rslt = %d\n"), macCompare ) ; + ("MAC comparison Rslt = %d"), macCompare ) ; if(0 > macCompare) { /* @@ -3298,7 +3451,7 @@ static tSirRetStatus limProcessTdlsSetupReqFrame(tpAniSirGlobal pMac, { VOS_ASSERT(0) ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("link Setup is Recieved in unknown state\n" )) ; + ("link Setup is Recieved in unknown state" )) ; break ; } #endif @@ -3318,7 +3471,7 @@ static tSirRetStatus limProcessTdlsSetupReqFrame(tpAniSirGlobal pMac, (void **) &setupPeer, sizeof( tLimTdlsLinkSetupPeer ))) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ( "Unable to allocate memory during ADD_STA\n" )); + ( "Unable to allocate memory during ADD_STA" )); return eSIR_MEM_ALLOC_FAILED; } @@ -3336,7 +3489,7 @@ static tSirRetStatus limProcessTdlsSetupReqFrame(tpAniSirGlobal pMac, sizeof(tSirMacAddr)) ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("Setup REQ MAC = %02x,%02x, %02x, %02x, %02x, %02x\n"), + ("Setup REQ MAC = %02x,%02x, %02x, %02x, %02x, %02x"), setupPeer->peerMac[0], setupPeer->peerMac[1], setupPeer->peerMac[2], @@ -3386,7 +3539,7 @@ static tSirRetStatus limProcessTdlsSetupReqFrame(tpAniSirGlobal pMac, sizeof(tSirMacAddr)) ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("Setup REQ MAC = %02x,%02x, %02x, %02x, %02x, %02x\n"), + ("Setup REQ MAC = %02x,%02x, %02x, %02x, %02x, %02x"), setupPeer->peerMac[0], setupPeer->peerMac[1], setupPeer->peerMac[2], @@ -3429,14 +3582,14 @@ static tSirRetStatus limProcessTdlsSetupRspFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( status ) ) { limLog(pMac, LOGE, FL("Failed to parse TDLS discovery Request \ - frame (0x%08x, %d bytes):\n"),status, frmLen); + frame (0x%08x, %d bytes):"),status, frmLen); PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frmLen);) return eSIR_FAILURE; } else if ( DOT11F_WARNED( status ) ) { limLog( pMac, LOGW, FL("There were warnings while unpacking an\ - TDLS discovery Request frame (0x%08x," "%d bytes):\n"), + TDLS discovery Request frame (0x%08x," "%d bytes):"), status, frmLen ); PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frmLen);) } @@ -3451,7 +3604,7 @@ static tSirRetStatus limProcessTdlsSetupRspFrame(tpAniSirGlobal pMac, if(NULL == psessionEntry) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, \ - ("no Seesion entry for TDLS session (bssid %02x:%02x:%02x:%02x:%02x:%02x)\n"), \ + ("no Seesion entry for TDLS session (bssid %02x:%02x:%02x:%02x:%02x:%02x)"), \ tdlsSetupRsp.LinkIdentifier.bssid[0], tdlsSetupRsp.LinkIdentifier.bssid[1], tdlsSetupRsp.LinkIdentifier.bssid[2], @@ -3470,7 +3623,7 @@ static tSirRetStatus limProcessTdlsSetupRspFrame(tpAniSirGlobal pMac, if(!status) { - limLog( pMac, LOGE, FL("TDLS discovery request frame from other BSS -> something wrong. Check RXP filter\n")) ; + limLog( pMac, LOGE, FL("TDLS discovery request frame from other BSS -> something wrong. Check RXP filter")) ; VOS_ASSERT(0) ; return eSIR_FAILURE ; @@ -3480,7 +3633,7 @@ static tSirRetStatus limProcessTdlsSetupRspFrame(tpAniSirGlobal pMac, sizeof(tSirMacAddr)) ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("TDLS setup RSP peer = %02x,%02x,%02x,%02x,%02x,%02x\n"), + ("TDLS setup RSP peer = %02x,%02x,%02x,%02x,%02x,%02x"), peerMac[0], peerMac[1], peerMac[2], @@ -3492,12 +3645,12 @@ static tSirRetStatus limProcessTdlsSetupRspFrame(tpAniSirGlobal pMac, if(NULL == setupPeer) { limLog( pMac, LOGE, FL(" unknown setup Response frame \ - other BSS\n")) ; + other BSS")) ; return eSIR_FAILURE ; } VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("deactivating Setup RSP timer\n")) ; + ("deactivating Setup RSP timer")) ; /* Deactivate the timer */ tx_timer_deactivate(&(setupPeer)->gLimTdlsLinkSetupRspTimeoutTimer) ; @@ -3510,7 +3663,7 @@ static tSirRetStatus limProcessTdlsSetupRspFrame(tpAniSirGlobal pMac, { limTdlsDelLinkPeer(pMac, (setupPeer)->peerMac) ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("setup RSP with Failure Code\n")) ; + ("setup RSP with Failure Code")) ; return eSIR_FAILURE ; } @@ -3568,14 +3721,14 @@ static tSirRetStatus limProcessTdlsSetupCnfFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( status ) ) { limLog(pMac, LOGE, FL("Failed to parse an TDLS discovery Response \ - frame (0x%08x, %d bytes):\n"),status, frmLen); + frame (0x%08x, %d bytes):"),status, frmLen); PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frmLen);) return eSIR_FAILURE; } else if ( DOT11F_WARNED( status ) ) { limLog( pMac, LOGW, FL("There were warnings while unpacking an\ - TDLS discovery Response frame (0x%08x," "%d bytes):\n"), + TDLS discovery Response frame (0x%08x," "%d bytes):"), status, frmLen ); PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frmLen);) } @@ -3589,7 +3742,7 @@ static tSirRetStatus limProcessTdlsSetupCnfFrame(tpAniSirGlobal pMac, if(NULL == psessionEntry) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, \ - ("no Seesion entry for TDLS session (bssid %02x:%02x:%02x:%02x:%02x:%02x)\n"), \ + ("no Seesion entry for TDLS session (bssid %02x:%02x:%02x:%02x:%02x:%02x)"), \ tdlsSetupCnf.LinkIdentifier.bssid[0], tdlsSetupCnf.LinkIdentifier.bssid[1], tdlsSetupCnf.LinkIdentifier.bssid[2], @@ -3608,14 +3761,14 @@ static tSirRetStatus limProcessTdlsSetupCnfFrame(tpAniSirGlobal pMac, if(!status) { - limLog( pMac, LOGE, FL("TDLS setup CNF frame other BSS -> something wrong. Check RXP filter\n")) ; + limLog( pMac, LOGE, FL("TDLS setup CNF frame other BSS -> something wrong. Check RXP filter")) ; VOS_ASSERT(0) ; return eSIR_FAILURE ; } /* TODO, do more validation */ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("setup Cnf peer MAc = %02x,%02x,%02x,%02x,%02x,%02x\n"), + ("setup Cnf peer MAc = %02x,%02x,%02x,%02x,%02x,%02x"), tdlsSetupCnf.LinkIdentifier.InitStaAddr[0], tdlsSetupCnf.LinkIdentifier.InitStaAddr[1], tdlsSetupCnf.LinkIdentifier.InitStaAddr[2], @@ -3631,12 +3784,12 @@ static tSirRetStatus limProcessTdlsSetupCnfFrame(tpAniSirGlobal pMac, if(NULL == setupPeer) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - (" unknown setup CNF frame\n")) ; + (" unknown setup CNF frame")) ; VOS_ASSERT(0) ; return eSIR_FAILURE ; } VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("setup CNF peer MAC = %02x,%02x,%02x,%02x,%02x,%02x\n"), + ("setup CNF peer MAC = %02x,%02x,%02x,%02x,%02x,%02x"), (setupPeer)->peerMac[0], (setupPeer)->peerMac[1], (setupPeer)->peerMac[2], @@ -3647,7 +3800,7 @@ static tSirRetStatus limProcessTdlsSetupCnfFrame(tpAniSirGlobal pMac, if((setupPeer)->dialog != tdlsSetupCnf.DialogToken.token) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("setup CNF frame not matching with setup RSP\n")) ; + ("setup CNF frame not matching with setup RSP")) ; VOS_ASSERT(0) ; return eSIR_FAILURE ; } @@ -3691,14 +3844,14 @@ static tSirRetStatus limProcessTdlsDisRspFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( status ) ) { limLog(pMac, LOGE, FL("Failed to parse an TDLS discovery Response \ - frame (0x%08x, %d bytes):\n"),status, frmLen); + frame (0x%08x, %d bytes):"),status, frmLen); PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frmLen);) return eSIR_FAILURE; } else if ( DOT11F_WARNED( status ) ) { limLog( pMac, LOGW, FL("There were warnings while unpacking an\ - TDLS discovery Response frame (0x%08x," "%d bytes):\n"), + TDLS discovery Response frame (0x%08x," "%d bytes):"), status, frmLen ); PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pFrame, nFrame);) } @@ -3711,14 +3864,14 @@ static tSirRetStatus limProcessTdlsDisRspFrame(tpAniSirGlobal pMac, if(!status) { - limLog( pMac, LOGW, FL(" TDLS discovery Response frame other BSS\n")) ; + limLog( pMac, LOGW, FL(" TDLS discovery Response frame other BSS")) ; return eSIR_FAILURE ; } /* TODO, do more validation */ if(tdlsDisRsp.DialogToken.token != prevDisReq->dialog) { - limLog( pMac, LOGW, FL(" wrong TDLS discovery Response frame\n")) ; + limLog( pMac, LOGW, FL(" wrong TDLS discovery Response frame")) ; return eSIR_FAILURE ; } @@ -3735,7 +3888,7 @@ static tSirRetStatus limProcessTdlsDisRspFrame(tpAniSirGlobal pMac, if(status != eHAL_STATUS_SUCCESS) { - limLog(pMac, LOGP, FL("alloc fail for TDLS discovery reponse info\n")) ; + limLog(pMac, LOGP, FL("alloc fail for TDLS discovery reponse info")) ; return eSIR_FAILURE ; } @@ -3814,14 +3967,14 @@ static tSirRetStatus limProcessTdlsTeardownFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( status ) ) { limLog(pMac, LOGE, FL("Failed to parse an TDLS discovery Response \ - frame (0x%08x, %d bytes):\n"),status, frmLen); + frame (0x%08x, %d bytes):"),status, frmLen); PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frmLen);) return eSIR_FAILURE; } else if ( DOT11F_WARNED( status ) ) { limLog( pMac, LOGW, FL("There were warnings while unpacking an\ - TDLS discovery Response frame (0x%08x," "%d bytes):\n"), + TDLS discovery Response frame (0x%08x," "%d bytes):"), status, frmLen ); PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frmLen);) } @@ -3836,7 +3989,7 @@ static tSirRetStatus limProcessTdlsTeardownFrame(tpAniSirGlobal pMac, if(NULL == psessionEntry) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, \ - ("no Seesion entry for TDLS session (bssid %02x:%02x:%02x:%02x:%02x:%02x)\n"), \ + ("no Seesion entry for TDLS session (bssid %02x:%02x:%02x:%02x:%02x:%02x)"), \ tdlsTeardown.LinkIdentifier.bssid[0], tdlsTeardown.LinkIdentifier.bssid[1], tdlsTeardown.LinkIdentifier.bssid[2], @@ -3856,7 +4009,7 @@ static tSirRetStatus limProcessTdlsTeardownFrame(tpAniSirGlobal pMac, if(!status) { - limLog( pMac, LOGE, FL("Teardown from other BSS -> something wrong. Check RXP filter\n")) ; + limLog( pMac, LOGE, FL("Teardown from other BSS -> something wrong. Check RXP filter")) ; VOS_ASSERT(0) ; return eSIR_FAILURE ; } @@ -3869,12 +4022,12 @@ static tSirRetStatus limProcessTdlsTeardownFrame(tpAniSirGlobal pMac, { //ignore //VOS_ASSERT(0) ; - limLog( pMac, LOGE, FL("Teardown from unknown peer. --> ignored\n") ); + limLog( pMac, LOGE, FL("Teardown from unknown peer. --> ignored") ); return eSIR_FAILURE ; } VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("teardown for peer %02x,%02x,%02x,%02x,%02x,%02x\n"), + ("teardown for peer %02x,%02x,%02x,%02x,%02x,%02x"), (setupPeer)->peerMac[0], (setupPeer)->peerMac[1], (setupPeer)->peerMac[2], @@ -3887,19 +4040,19 @@ static tSirRetStatus limProcessTdlsTeardownFrame(tpAniSirGlobal pMac, case eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON: { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("teardown with unspecified reason\n")) ; + ("teardown with unspecified reason")) ; break ; } case eSIR_MAC_TDLS_TEARDOWN_PEER_UNREACHABLE: { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - (" Teardown from AP, TDLS peer unreachable\n")) ; + (" Teardown from AP, TDLS peer unreachable")) ; break ; } default: { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - (" unknown teardown\n")) ; + (" unknown teardown")) ; break ; } } @@ -3954,7 +4107,7 @@ void limProcessTdlsFrame(tpAniSirGlobal pMac, tANI_U32 *pBd) if(category != SIR_MAC_ACTION_TDLS) { - limLog( pMac, LOGE, FL("Invalid TDLS action frame=(%d). Ignored\n"), category ); + limLog( pMac, LOGE, FL("Invalid TDLS action frame=(%d). Ignored"), category ); return ; } @@ -4020,7 +4173,7 @@ static tSirRetStatus limTdlsDisAddSta(tpAniSirGlobal pMac, tSirMacAddr peerMac, } VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("ADD STA peer MAC: %02x, %02x, %02x, %02x, %02x, %02x\n"), + ("ADD STA peer MAC: %02x, %02x, %02x, %02x, %02x, %02x"), peerMac[0], peerMac[1], peerMac[2], @@ -4033,7 +4186,7 @@ static tSirRetStatus limTdlsDisAddSta(tpAniSirGlobal pMac, tSirMacAddr peerMac, &aid, &psessionEntry->dph.dphHashTable)) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - (" there is hash entry for this client\n")) ; + (" there is hash entry for this client")) ; status = eSIR_FAILURE ; VOS_ASSERT(0) ; return status ; @@ -4057,7 +4210,7 @@ static tSirRetStatus limTdlsDisAddSta(tpAniSirGlobal pMac, tSirMacAddr peerMac, if(NULL == pStaDs) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - (" add hash entry failed\n")) ; + (" add hash entry failed")) ; status = eSIR_FAILURE ; VOS_ASSERT(0) ; return status; @@ -4068,23 +4221,23 @@ static tSirRetStatus limTdlsDisAddSta(tpAniSirGlobal pMac, tSirMacAddr peerMac, tSirMacRateSet *suppRates = &peerInfo->tdlsPeerSuppRates ; tSirMacRateSet *extRates = &peerInfo->tdlsPeerExtRates ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("pSta DS [%p] \n"), pStaDs) ; + ("pSta DS [%p] "), pStaDs) ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("peerInfo->tdlsPeerSuppRates = [%p]\n"), + ("peerInfo->tdlsPeerSuppRates = [%p]"), (tANI_U8 *)&peerInfo->tdlsPeerSuppRates) ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("peerInfo->tdlsPeerExtRates = [%p]\n"), + ("peerInfo->tdlsPeerExtRates = [%p]"), (tANI_U8 *)&peerInfo->tdlsPeerExtRates) ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("peerInfo->tdlsPeerPropRates = [%p]\n"), + ("peerInfo->tdlsPeerPropRates = [%p]"), (tANI_U8 *)&pStaDs->mlmStaContext.propRateSet) ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("peerInfo->mcs = [%p]\n"), + ("peerInfo->mcs = [%p]"), (tANI_U8 *)peerInfo->supportedMCSSet) ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("num of supp rates = %02x\n"), suppRates->numRates) ; + ("num of supp rates = %02x"), suppRates->numRates) ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("num of ext rates = %01x\n"), extRates->numRates) ; + ("num of ext rates = %01x"), extRates->numRates) ; #endif /* Populate matching rate set */ @@ -4112,7 +4265,7 @@ static tSirRetStatus limTdlsDisAddSta(tpAniSirGlobal pMac, tSirMacAddr peerMac, palCopyMemory(pMac->hHdd, pStaDs->staAddr, peerMac, sizeof(tSirMacAddr)) ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("Add STA for Peer: %02x, %02x, %02x, %02x, %02x, %02x\n"), + ("Add STA for Peer: %02x, %02x, %02x, %02x, %02x, %02x"), pStaDs->staAddr[0], pStaDs->staAddr[1], pStaDs->staAddr[2], @@ -4180,7 +4333,7 @@ static tSirRetStatus limTdlsSetupAddSta(tpAniSirGlobal pMac, if(NULL == pStaDs) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - (" add hash entry failed\n")) ; + (" add hash entry failed")) ; VOS_ASSERT(0) ; return eSIR_FAILURE; } @@ -4217,7 +4370,7 @@ static tpDphHashNode limTdlsDelSta(tpAniSirGlobal pMac, tSirMacAddr peerMac, { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("DEL STA peer MAC: %02x, %02x, %02x, %02x, %02x, %02x \n"), + ("DEL STA peer MAC: %02x, %02x, %02x, %02x, %02x, %02x "), pStaDs->staAddr[0], pStaDs->staAddr[1], pStaDs->staAddr[2], @@ -4227,7 +4380,7 @@ static tpDphHashNode limTdlsDelSta(tpAniSirGlobal pMac, tSirMacAddr peerMac, ) ; VOS_TRACE(VOS_MODULE_ID_PE, TDLS_DEBUG_LOG_LEVEL, - ("limTdlsDelSta: STA type = %x, sta idx = %x\n"),pStaDs->staType, + ("limTdlsDelSta: STA type = %x, sta idx = %x"),pStaDs->staType, pStaDs->staIndex) ; status = limDelSta(pMac, pStaDs, false, psessionEntry) ; @@ -4269,7 +4422,7 @@ static tSirRetStatus limTdlsLinkEstablish(tpAniSirGlobal pMac, tSirMacAddr peerM limTdlsFindLinkPeer(pMac, peerMac, &setupPeer) ; if(NULL == setupPeer) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("limTdlsLinkEstablish: cannot find peer mac in tdls linksetup list: %02X %02X %02X %02X %02X %02X\n"), \ + ("limTdlsLinkEstablish: cannot find peer mac in tdls linksetup list: %02X %02X %02X %02X %02X %02X"), \ peerMac[0], peerMac[1], peerMac[2], \ peerMac[3], peerMac[4], peerMac[5]); return eSIR_FAILURE; @@ -4281,7 +4434,7 @@ static tSirRetStatus limTdlsLinkEstablish(tpAniSirGlobal pMac, tSirMacAddr peerM if(NULL == psessionEntry) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("limTdlsLinkEstablish: sessionID %d is not found\n"), setupPeer->tdls_sessionId); + ("limTdlsLinkEstablish: sessionID %d is not found"), setupPeer->tdls_sessionId); VOS_ASSERT(0) ; return eHAL_STATUS_FAILURE; } @@ -4290,7 +4443,7 @@ static tSirRetStatus limTdlsLinkEstablish(tpAniSirGlobal pMac, tSirMacAddr peerM pStaDs = dphLookupHashEntry(pMac, peerMac, &aid, &psessionEntry->dph.dphHashTable) ; if(pStaDs == NULL) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("limTdlsLinkEstablish: cannot find peer mac in hash table: %02X %02X %02X %02X %02X %02X\n"), \ + ("limTdlsLinkEstablish: cannot find peer mac in hash table: %02X %02X %02X %02X %02X %02X"), \ peerMac[0], peerMac[1], peerMac[2], \ peerMac[3], peerMac[4], peerMac[5]); return eSIR_FAILURE; @@ -4327,13 +4480,13 @@ static tSirRetStatus limTdlsLinkEstablish(tpAniSirGlobal pMac, tSirMacAddr peerM status = dot11fGetPackedTDLSPeerTrafficIndSize ( pMac, &tdlsPtiTemplate, &nPayload); if ( DOT11F_FAILED( status ) ) { - limLog( pMac, LOGP, FL("Failed to calculate the packed size for a PTI template (0x%08x).\n"), status ); + limLog( pMac, LOGP, FL("Failed to calculate the packed size for a PTI template (0x%08x)."), status ); /* We'll fall back on the worst case scenario: */ nPayload = sizeof( tdlsPtiTemplate ); } else if ( DOT11F_WARNED( status ) ) { - limLog( pMac, LOGW, FL("There were warnings while calculating the packed size for a PTI template (0x%08x).\n"), status ); + limLog( pMac, LOGW, FL("There were warnings while calculating the packed size for a PTI template (0x%08x)."), status ); } /* @@ -4347,7 +4500,7 @@ static tSirRetStatus limTdlsLinkEstablish(tpAniSirGlobal pMac, tSirMacAddr peerM + PAYLOAD_TYPE_TDLS_SIZE ; if(nBytes > 64) { - limLog( pMac, LOGE, FL("required memory for PTI frame is %ld, but reserved only 64.\n"), nBytes); + limLog( pMac, LOGE, FL("required memory for PTI frame is %ld, but reserved only 64."), nBytes); nBytes = 64; } /* zero out the memory */ @@ -4364,16 +4517,16 @@ static tSirRetStatus limTdlsLinkEstablish(tpAniSirGlobal pMac, tSirMacAddr peerM if ( DOT11F_FAILED( status ) ) { limLog( pMac, LOGE, FL("Failed to pack a PTI template \ - (0x%08x).\n"), status ); + (0x%08x)."), status ); return eSIR_FAILURE; } else if ( DOT11F_WARNED( status ) ) { limLog( pMac, LOGW, FL("There were warnings while packing TDLS" - "Peer Traffic Indication (0x%08x).\n") ); + "Peer Traffic Indication (0x%08x).") ); } - LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, ("bIsResponder=%d, header_offset=%ld, linkIdenOffset=%d, ptiBufStatusOffset=%d \n"), \ + LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, ("bIsResponder=%d, header_offset=%ld, linkIdenOffset=%d, ptiBufStatusOffset=%d "), \ setupPeer->tdls_bIsResponder, header_offset, PTI_LINK_IDEN_OFFSET, PTI_BUF_STATUS_OFFSET)); limSendTdlsLinkEstablish(pMac, setupPeer->tdls_bIsResponder, @@ -4398,7 +4551,7 @@ static tSirRetStatus limTdlsLinkTeardown(tpAniSirGlobal pMac, tSirMacAddr peerMa limTdlsFindLinkPeer(pMac, peerMac, &setupPeer) ; if(NULL == setupPeer) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("limTdlsLinkTeardown: cannot find peer mac in tdls linksetup list: %02X %02X %02X %02X %02X %02X\n"), \ + ("limTdlsLinkTeardown: cannot find peer mac in tdls linksetup list: %02X %02X %02X %02X %02X %02X"), \ peerMac[0], peerMac[1], peerMac[2], \ peerMac[3], peerMac[4], peerMac[5]); return eSIR_FAILURE; @@ -4410,7 +4563,7 @@ static tSirRetStatus limTdlsLinkTeardown(tpAniSirGlobal pMac, tSirMacAddr peerMa if(NULL == psessionEntry) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("limTdlsLinkTeardown: sessionID %d is not found\n"), setupPeer->tdls_sessionId); + ("limTdlsLinkTeardown: sessionID %d is not found"), setupPeer->tdls_sessionId); VOS_ASSERT(0) ; return eHAL_STATUS_FAILURE; } @@ -4421,7 +4574,7 @@ static tSirRetStatus limTdlsLinkTeardown(tpAniSirGlobal pMac, tSirMacAddr peerMa if(pStaDs == NULL) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("limTdlsLinkTeardown: cannot find peer mac in hash table: %02X %02X %02X %02X %02X %02X\n"), \ + ("limTdlsLinkTeardown: cannot find peer mac in hash table: %02X %02X %02X %02X %02X %02X"), \ peerMac[0], peerMac[1], peerMac[2], \ peerMac[3], peerMac[4], peerMac[5]); return eSIR_FAILURE; @@ -4473,7 +4626,7 @@ static tSirTdlsDisRsp *tdlsPrepareTdlsDisRsp(tpAniSirGlobal pMac, sizeof(tSirTdlsPeerInfo)); VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("Msg Sent to PE, peer MAC: %02x, %02x, %02x, %02x, %02x, %02x\n"), + ("Msg Sent to PE, peer MAC: %02x, %02x, %02x, %02x, %02x, %02x"), peerInfo->peerMac[0] , peerInfo->peerMac[1] , peerInfo->peerMac[2] , @@ -4490,7 +4643,7 @@ static tSirTdlsDisRsp *tdlsPrepareTdlsDisRsp(tpAniSirGlobal pMac, || ((!tdlsDisRspList) && disStaCount)) { limLog(pMac, LOG1, FL("mismatch in dis sta count and\ - and number of nodes in list\n")) ; + and number of nodes in list")) ; VOS_ASSERT(0) ; return NULL ; } @@ -4581,7 +4734,7 @@ void limSendSmeTdlsDisRsp(tpAniSirGlobal pMac, tSirResultCodes statusCode, tANI_U8 tdlsStaCount = pMac->lim.gLimTdlsDisStaCount ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("no of TDLS STA discovered: %d\n"), tdlsStaCount) ; + ("no of TDLS STA discovered: %d"), tdlsStaCount) ; tdlsDisRsp = tdlsPrepareTdlsDisRsp(pMac, tdlsDisRsp, tdlsStaCount) ; if(tdlsDisRsp) @@ -4590,7 +4743,7 @@ void limSendSmeTdlsDisRsp(tpAniSirGlobal pMac, tSirResultCodes statusCode, } else { - limLog(pMac, LOGP, FL("fatal failure for TDLS DIS RSP\n")); + limLog(pMac, LOGP, FL("fatal failure for TDLS DIS RSP")); VOS_ASSERT(0) ; return ; } @@ -4723,7 +4876,7 @@ void limTdlsLinkSetupRspTimerHandler(void *pMacGlobal, tANI_U32 timerId) if ((statusCode = limPostMsgApi(pMac, &msg)) != eSIR_SUCCESS) limLog(pMac, LOGE, - FL("posting message %X to LIM failed, reason=%d\n"), + FL("posting message %X to LIM failed, reason=%d"), msg.type, statusCode); return ; } @@ -4746,7 +4899,7 @@ void limTdlsLinkSetupCnfTimerHandler(void *pMacGlobal, tANI_U32 timerId) if ((statusCode = limPostMsgApi(pMac, &msg)) != eSIR_SUCCESS) limLog(pMac, LOGE, - FL("posting message %X to LIM failed, reason=%d\n"), + FL("posting message %X to LIM failed, reason=%d"), msg.type, statusCode); return ; } @@ -4775,7 +4928,7 @@ void limStartTdlsTimer(tpAniSirGlobal pMac, tANI_U8 sessionId, TX_TIMER *timer, timerId, cfgValue, 0, TX_NO_ACTIVATE) != TX_SUCCESS) { limLog(pMac, LOGP, - FL("could not create TDLS discovery response wait timer\n")); + FL("could not create TDLS discovery response wait timer")); return; } @@ -4786,7 +4939,7 @@ void limStartTdlsTimer(tpAniSirGlobal pMac, tANI_U8 sessionId, TX_TIMER *timer, eLIM_TDLS_DISCOVERY_RSP_WAIT)); if (tx_timer_activate(timer) != TX_SUCCESS) { - limLog(pMac, LOGP, FL("TDLS link setup timer activation failed!\n")); + limLog(pMac, LOGP, FL("TDLS link setup timer activation failed!")); return ; } @@ -4865,7 +5018,7 @@ eHalStatus limProcessTdlsAddStaRsp(tpAniSirGlobal pMac, void *msg, { VOS_ASSERT(0) ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("Add sta failed \n")) ; + ("Add sta failed ")) ; status = eSIR_FAILURE; goto add_sta_error; } @@ -4875,7 +5028,7 @@ eHalStatus limProcessTdlsAddStaRsp(tpAniSirGlobal pMac, void *msg, if(NULL == pStaDs) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("pStaDs is NULL \n")) ; + ("pStaDs is NULL ")) ; status = eSIR_FAILURE; goto add_sta_error; } @@ -4892,7 +5045,7 @@ eHalStatus limProcessTdlsAddStaRsp(tpAniSirGlobal pMac, void *msg, if(eSIR_FAILURE == status) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("Peer IND msg to SME failed\n")) ; + ("Peer IND msg to SME failed")) ; palFreeMemory( pMac->hHdd, (void *) pAddStaParams ); return eSIR_FAILURE ; } @@ -5007,7 +5160,7 @@ eHalStatus limTdlsPrepareSetupReqFrame(tpAniSirGlobal pMac, (void **) &setupPeer, sizeof( tLimTdlsLinkSetupPeer ))) { limLog( pMac, LOGP, - FL( "Unable to allocate memory during ADD_STA\n" )); + FL( "Unable to allocate memory during ADD_STA" )); VOS_ASSERT(0) ; return eSIR_MEM_ALLOC_FAILED; } @@ -5058,13 +5211,13 @@ tSirRetStatus limProcessSmeTdlsMgmtSendReq(tpAniSirGlobal pMac, tSirResultCodes resultCode = eSIR_SME_INVALID_PARAMETERS; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("Send Mgmt Recieved\n")) ; + ("Send Mgmt Recieved")) ; if((psessionEntry = peFindSessionByBssid(pMac, pSendMgmtReq->bssid, &sessionId)) == NULL) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - "PE Session does not exist for given sme sessionId %d\n", + "PE Session does not exist for given sme sessionId %d", pSendMgmtReq->sessionId); goto lim_tdls_send_mgmt_error; } @@ -5073,7 +5226,7 @@ tSirRetStatus limProcessSmeTdlsMgmtSendReq(tpAniSirGlobal pMac, if (psessionEntry->limSystemRole != eLIM_STA_ROLE) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - "send mgmt received in wrong system Role %d\n", + "send mgmt received in wrong system Role %d", psessionEntry->limSystemRole); goto lim_tdls_send_mgmt_error; } @@ -5087,7 +5240,7 @@ tSirRetStatus limProcessSmeTdlsMgmtSendReq(tpAniSirGlobal pMac, { limLog(pMac, LOGE, "send mgmt received in invalid LIMsme \ - state (%d)\n", psessionEntry->limSmeState); + state (%d)", psessionEntry->limSmeState); goto lim_tdls_send_mgmt_error; } @@ -5095,7 +5248,7 @@ tSirRetStatus limProcessSmeTdlsMgmtSendReq(tpAniSirGlobal pMac, { case SIR_MAC_TDLS_DIS_REQ: VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - "Transmit Discovery Request Frame\n") ; + "Transmit Discovery Request Frame") ; /* format TDLS discovery request frame and transmit it */ limSendTdlsDisReqFrame(pMac, pSendMgmtReq->peerMac, pSendMgmtReq->dialog, psessionEntry) ; @@ -5222,13 +5375,13 @@ tSirRetStatus limProcessSmeTdlsAddStaReq(tpAniSirGlobal pMac, tANI_U8 sessionId; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("Send Mgmt Recieved\n")) ; + ("Send Mgmt Recieved")) ; if((psessionEntry = peFindSessionByBssid(pMac, pAddStaReq->bssid, &sessionId)) == NULL) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - "PE Session does not exist for given sme sessionId %d\n", + "PE Session does not exist for given sme sessionId %d", pAddStaReq->sessionId); goto lim_tdls_add_sta_error; } @@ -5237,7 +5390,7 @@ tSirRetStatus limProcessSmeTdlsAddStaReq(tpAniSirGlobal pMac, if (psessionEntry->limSystemRole != eLIM_STA_ROLE) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - "send mgmt received in wrong system Role %d\n", + "send mgmt received in wrong system Role %d", psessionEntry->limSystemRole); goto lim_tdls_add_sta_error; } @@ -5251,7 +5404,7 @@ tSirRetStatus limProcessSmeTdlsAddStaReq(tpAniSirGlobal pMac, { limLog(pMac, LOGE, "send mgmt received in invalid LIMsme \ - state (%d)\n", psessionEntry->limSmeState); + state (%d)", psessionEntry->limSmeState); goto lim_tdls_add_sta_error; } @@ -5260,7 +5413,7 @@ tSirRetStatus limProcessSmeTdlsAddStaReq(tpAniSirGlobal pMac, /* To start with, send add STA request to HAL */ if (eSIR_FAILURE == limTdlsSetupAddSta(pMac, pAddStaReq, psessionEntry)) { - limLog(pMac, LOGE, "%s: Add TDLS Station request failed \n", __func__); + limLog(pMac, LOGE, "%s: Add TDLS Station request failed ", __func__); goto lim_tdls_add_sta_error; } return eSIR_SUCCESS; @@ -5284,13 +5437,13 @@ tSirRetStatus limProcessSmeTdlsDelStaReq(tpAniSirGlobal pMac, tpDphHashNode pStaDs = NULL ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("Send Mgmt Recieved\n")) ; + ("Send Mgmt Recieved")) ; if((psessionEntry = peFindSessionByBssid(pMac, pDelStaReq->bssid, &sessionId)) == NULL) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - "PE Session does not exist for given sme sessionId %d\n", + "PE Session does not exist for given sme sessionId %d", pDelStaReq->sessionId); limSendSmeTdlsDelStaRsp(pMac, pDelStaReq->sessionId, pDelStaReq->peerMac, NULL, eSIR_FAILURE) ; @@ -5301,7 +5454,7 @@ tSirRetStatus limProcessSmeTdlsDelStaReq(tpAniSirGlobal pMac, if (psessionEntry->limSystemRole != eLIM_STA_ROLE) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - "Del sta received in wrong system Role %d\n", + "Del sta received in wrong system Role %d", psessionEntry->limSystemRole); goto lim_tdls_del_sta_error; } @@ -5315,7 +5468,7 @@ tSirRetStatus limProcessSmeTdlsDelStaReq(tpAniSirGlobal pMac, { limLog(pMac, LOGE, "Del Sta received in invalid LIMsme \ - state (%d)\n", psessionEntry->limSmeState); + state (%d)", psessionEntry->limSmeState); goto lim_tdls_del_sta_error; } diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limPropExtsUtils.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limPropExtsUtils.c index 4ab03e05b65..44a28160c51 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limPropExtsUtils.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limPropExtsUtils.c @@ -102,7 +102,7 @@ limExtractApCapability(tpAniSirGlobal pMac, tANI_U8 *pIE, tANI_U16 ieLen, if(eHAL_STATUS_SUCCESS != palAllocateMemory(pMac->hHdd, (void **)&pBeaconStruct, sizeof(tSirProbeRespBeacon))) { - limLog(pMac, LOGE, FL("Unable to PAL allocate memory in limExtractApCapability\n") ); + limLog(pMac, LOGE, FL("Unable to PAL allocate memory in limExtractApCapability") ); return; } @@ -111,7 +111,7 @@ limExtractApCapability(tpAniSirGlobal pMac, tANI_U8 *pIE, tANI_U16 ieLen, *propCap = 0; *uapsd = 0; PELOG3(limLog( pMac, LOG3, - FL("In limExtractApCapability: The IE's being received are:\n")); + FL("In limExtractApCapability: The IE's being received are:")); sirDumpBuf( pMac, SIR_LIM_MODULE_ID, LOG3, pIE, ieLen );) if (sirParseBeaconIE(pMac, pBeaconStruct, pIE, (tANI_U32)ieLen) == eSIR_SUCCESS) { @@ -129,9 +129,9 @@ limExtractApCapability(tpAniSirGlobal pMac, tANI_U8 *pIE, tANI_U16 ieLen, #ifdef WLAN_FEATURE_11AC VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO_MED, - "***beacon.VHTCaps.present*****=%d\n",pBeaconStruct->VHTCaps.present); + "***beacon.VHTCaps.present*****=%d",pBeaconStruct->VHTCaps.present); VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO_MED, - "***beacon.SU Beamformer Capable*****=%d\n",pBeaconStruct->VHTCaps.suBeamFormerCap); + "***beacon.SU Beamformer Capable*****=%d",pBeaconStruct->VHTCaps.suBeamFormerCap); if ( pBeaconStruct->VHTCaps.present && pBeaconStruct->VHTOperation.present) { @@ -176,7 +176,7 @@ limExtractApCapability(tpAniSirGlobal pMac, tANI_U8 *pIE, tANI_U16 ieLen, #if !defined WLAN_FEATURE_VOWIFI if (cfgSetInt(pMac, WNI_CFG_LOCAL_POWER_CONSTRAINT, localPowerConstraints) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("Could not update local power constraint to cfg.\n")); + limLog(pMac, LOGP, FL("Could not update local power constraint to cfg.")); } #endif } diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limRoamingAlgo.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limRoamingAlgo.c index 09c78cd614b..7beea7fe5c5 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limRoamingAlgo.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limRoamingAlgo.c @@ -79,7 +79,7 @@ tSirBackgroundScanMode limSelectsBackgroundScanMode(tpAniSirGlobal pMac) if (wlan_cfgGetInt(pMac, WNI_CFG_MAX_CONSECUTIVE_BACKGROUND_SCAN_FAILURE, &cfgVal) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("Fail to get WNI_CFG_MAX_CONSECUTIVE_BACKGROUND_SCAN_FAILURE value\n")); + limLog(pMac, LOGP, FL("Fail to get WNI_CFG_MAX_CONSECUTIVE_BACKGROUND_SCAN_FAILURE value")); return eSIR_NORMAL_BACKGROUND_SCAN; } @@ -94,7 +94,7 @@ tSirBackgroundScanMode limSelectsBackgroundScanMode(tpAniSirGlobal pMac) { pMac->lim.gLimNumOfForcedBkgndScan += 1; limLog(pMac, LOGE, - FL("Had %d consec scan fail(when expect < %d). Trigger AGGRESSIVE bkgnd scan.\n"), + FL("Had %d consec scan fail(when expect < %d). Trigger AGGRESSIVE bkgnd scan."), pMac->lim.gLimNumOfConsecutiveBkgndScanFailure, cfgVal); return eSIR_AGGRESSIVE_BACKGROUND_SCAN; } @@ -167,12 +167,12 @@ void limTriggerBackgroundScan(tpAniSirGlobal pMac) tSirMacAddr bcAddr = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; tSirBackgroundScanMode backgroundScan; - PELOG1(limLog(pMac, LOG1, FL("Background Scan: %d success, %d consec fail \n"), + PELOG1(limLog(pMac, LOG1, FL("Background Scan: %d success, %d consec fail "), pMac->lim.gLimNumOfBackgroundScanSuccess, pMac->lim.gLimNumOfConsecutiveBkgndScanFailure);) if (! limIsBackgroundScanAllowed(pMac)) { - PELOG1(limLog(pMac, LOG1, FL("Skipping Background Scan \n"));) + PELOG1(limLog(pMac, LOG1, FL("Skipping Background Scan "));) return; } @@ -185,7 +185,7 @@ void limTriggerBackgroundScan(tpAniSirGlobal pMac) * Could not get Valid channel list from CFG. * Log error. */ - PELOGE(limLog(pMac, LOGE, FL("could not retrieve valid channel list\n"));) + PELOGE(limLog(pMac, LOGE, FL("could not retrieve valid channel list"));) return; } @@ -203,7 +203,7 @@ void limTriggerBackgroundScan(tpAniSirGlobal pMac) (tANI_U32 *) &ssidLen) != eSIR_SUCCESS) { /// Could not get SSID from CFG. Log error. - limLog(pMac, LOGP, FL("could not retrieve SSID\n")); + limLog(pMac, LOGP, FL("could not retrieve SSID")); } smeScanReq.ssId[0].length = (tANI_U8) ssidLen; smeScanReq.numSsid = 1; @@ -215,7 +215,7 @@ void limTriggerBackgroundScan(tpAniSirGlobal pMac) &smeScanReq.minChannelTime) != eSIR_SUCCESS) { /// Could not get minChlTime value from CFG. Log error. - PELOGE(limLog(pMac, LOGE, FL("could not retrieve minChlTime value\n"));) + PELOGE(limLog(pMac, LOGE, FL("could not retrieve minChlTime value"));) return; } @@ -224,7 +224,7 @@ void limTriggerBackgroundScan(tpAniSirGlobal pMac) &smeScanReq.maxChannelTime) != eSIR_SUCCESS) { /// Could not get maxChlTime value from CFG. Log error. - PELOGE(limLog(pMac, LOGE, FL("could not retrieve maxChlTime value\n"));) + PELOGE(limLog(pMac, LOGE, FL("could not retrieve maxChlTime value"));) return; } @@ -248,8 +248,8 @@ void limTriggerBackgroundScan(tpAniSirGlobal pMac) { pMac->lim.gLimBackgroundScanChannelId = 0; - PELOGE(limLog(pMac, LOGE, FL("Skipping Background Scan since the channel list is exhausted.\n"));) - PELOGE(limLog(pMac, LOGE, FL("SME should send WNI_CFG_BACKGROUND_SCAN_PERIOD indication to start the background scan again.\n"));) + PELOGE(limLog(pMac, LOGE, FL("Skipping Background Scan since the channel list is exhausted."));) + PELOGE(limLog(pMac, LOGE, FL("SME should send WNI_CFG_BACKGROUND_SCAN_PERIOD indication to start the background scan again."));) /* Stop the BG scan timer here. SME should send WNI_CFG_BACKGROUND_SCAN_PERIOD * indication to start the background scan again. @@ -263,13 +263,13 @@ void limTriggerBackgroundScan(tpAniSirGlobal pMac) // Could not deactivate BackgroundScanTimer timer. // Log error limLog(pMac, LOGP, - FL("unable to deactivate BackgroundScanTimer timer\n")); + FL("unable to deactivate BackgroundScanTimer timer")); } } pMac->lim.gLimBackgroundScanTerminate = TRUE; - PELOGE(limLog(pMac, LOGE, FL("Send dummy scan with returnFreshResults as 0 to report BG scan results to SME.\n"));) + PELOGE(limLog(pMac, LOGE, FL("Send dummy scan with returnFreshResults as 0 to report BG scan results to SME."));) return; } smeScanReq.channelList.channelNumber[0] = @@ -279,7 +279,7 @@ void limTriggerBackgroundScan(tpAniSirGlobal pMac) smeScanReq.uIEFieldOffset = sizeof(tSirSmeScanReq); backgroundScan = limSelectsBackgroundScanMode(pMac); - PELOG1(limLog(pMac, LOG1, FL("Performing (mode %d) Background Scan \n"), backgroundScan);) + PELOG1(limLog(pMac, LOG1, FL("Performing (mode %d) Background Scan "), backgroundScan);) smeScanReq.backgroundScanMode = backgroundScan; //determine whether to send the results or not, If so, notify the BG scan results to SME @@ -307,7 +307,7 @@ void limAbortBackgroundScan(tpAniSirGlobal pMac) if(pMac->lim.gLimBackgroundScanTerminate == FALSE) { - limLog(pMac, LOGE, FL("Abort Background Scan \n")); + limLog(pMac, LOGE, FL("Abort Background Scan ")); if (TX_TIMER_VALID(pMac->lim.limTimers.gLimBackgroundScanTimer)) { limDeactivateAndChangeTimer(pMac, eLIM_BACKGROUND_SCAN_TIMER); diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limScanResultUtils.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limScanResultUtils.c index 4c8f81e4ae2..abd96363fb0 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limScanResultUtils.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limScanResultUtils.c @@ -1,8 +1,43 @@ /* -* Copyright (c) 2011-2013 Qualcomm Atheros, Inc. -* All Rights Reserved. -* Qualcomm Atheros Confidential and Proprietary. -*/ + * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ +/* + * Copyright (c) 2012, The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ /* * Airgo Networks, Inc proprietary. All rights reserved. @@ -442,9 +477,9 @@ limCheckAndAddBssDescription(tpAniSirGlobal pMac, ieLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); if (ieLen <= SIR_MAC_B_PR_SSID_OFFSET) { - limLog(pMac, LOGP, - FL("RX packet has invalid length %d"), ieLen); - return; + limLog(pMac, LOGP, + FL("RX packet has invalid length %d\n"), ieLen); + return; } ieLen -= SIR_MAC_B_PR_SSID_OFFSET; diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limScanResultUtils.h b/drivers/staging/prima/CORE/MAC/src/pe/lim/limScanResultUtils.h index 9ad88bfdc7c..b16147dd9a3 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limScanResultUtils.h +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limScanResultUtils.h @@ -65,6 +65,14 @@ void limDeleteCachedScanResults(tpAniSirGlobal); void limRestorePreScanState(tpAniSirGlobal); void limCopyScanResult(tpAniSirGlobal, tANI_U8 *); void limReInitScanResults(tpAniSirGlobal); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +void limInitLfrHashTable(tpAniSirGlobal); +eHalStatus + limLookupNaddLfrHashEntry(tpAniSirGlobal, tLimScanResultNode *, tANI_U8, tANI_U8); +void limDeleteLfrHashEntry(tLimScanResultNode *); +void limDeleteCachedLfrScanResults(tpAniSirGlobal); +void limReInitLfrScanResults(tpAniSirGlobal); +#endif tANI_U32 limDeactivateMinChannelTimerDuringScan(tpAniSirGlobal); void limCheckAndAddBssDescription(tpAniSirGlobal, tpSirProbeRespBeacon, tANI_U8 *, tANI_BOOLEAN, tANI_U8); #if defined WLAN_FEATURE_VOWIFI diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limSecurityUtils.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limSecurityUtils.c index 70abc3a6a2f..85f12dfb876 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limSecurityUtils.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limSecurityUtils.c @@ -114,7 +114,7 @@ limIsAuthAlgoSupported(tpAniSirGlobal pMac, tAniAuthType authType, tpPESession p * from CFG. Log error. */ limLog(pMac, LOGE, - FL("could not retrieve AuthAlgo1 Enable value\n")); + FL("could not retrieve AuthAlgo1 Enable value")); return false; } @@ -142,7 +142,7 @@ limIsAuthAlgoSupported(tpAniSirGlobal pMac, tAniAuthType authType, tpPESession p * from CFG. Log error. */ limLog(pMac, LOGE, - FL("could not retrieve AuthAlgo2 Enable value\n")); + FL("could not retrieve AuthAlgo2 Enable value")); return false; } @@ -161,7 +161,7 @@ limIsAuthAlgoSupported(tpAniSirGlobal pMac, tAniAuthType authType, tpPESession p * from CFG. Log error. */ limLog(pMac, LOGE, - FL("could not retrieve PrivacyOptImplemented value\n")); + FL("could not retrieve PrivacyOptImplemented value")); return false; } @@ -226,7 +226,7 @@ limDeletePreAuthList(tpAniSirGlobal pMac) { pTempNode = pCurrNode->next; - PELOG1(limLog(pMac, LOG1, FL("=====> limDeletePreAuthList \n"));) + PELOG1(limLog(pMac, LOG1, FL("=====> limDeletePreAuthList "));) limReleasePreAuthNode(pMac, pCurrNode); pCurrNode = pTempNode; @@ -380,8 +380,8 @@ limDeletePreAuthNode(tpAniSirGlobal pMac, tSirMacAddr macAddr) pMac->lim.pLimPreAuthList = pTempNode->next; - PELOG1(limLog(pMac, LOG1, FL("=====> limDeletePreAuthNode : first node to delete\n"));) - PELOG1(limLog(pMac, LOG1, FL("Release data entry: %x id %d peer \n"), + PELOG1(limLog(pMac, LOG1, FL("=====> limDeletePreAuthNode : first node to delete"));) + PELOG1(limLog(pMac, LOG1, FL("Release data entry: %x id %d peer "), pTempNode, pTempNode->authNodeIdx); limPrintMacAddr(pMac, macAddr, LOG1);) limReleasePreAuthNode(pMac, pTempNode); @@ -401,8 +401,8 @@ limDeletePreAuthNode(tpAniSirGlobal pMac, tSirMacAddr macAddr) pPrevNode->next = pTempNode->next; - PELOG1(limLog(pMac, LOG1, FL("=====> limDeletePreAuthNode : subsequent node to delete\n")); - limLog(pMac, LOG1, FL("Release data entry: %x id %d peer \n"), + PELOG1(limLog(pMac, LOG1, FL("=====> limDeletePreAuthNode : subsequent node to delete")); + limLog(pMac, LOG1, FL("Release data entry: %x id %d peer "), pTempNode, pTempNode->authNodeIdx); limPrintMacAddr(pMac, macAddr, LOG1);) limReleasePreAuthNode(pMac, pTempNode); @@ -481,7 +481,7 @@ limRestoreFromAuthState(tpAniSirGlobal pMac, tSirResultCodes resultCode, tANI_U1 if (wlan_cfgGetStr(pMac, WNI_CFG_BSSID, currentBssId, &cfg) != eSIR_SUCCESS) { /// Could not get BSSID from CFG. Log error. - limLog(pMac, LOGP, FL("could not retrieve BSSID\n")); + limLog(pMac, LOGP, FL("could not retrieve BSSID")); } #endif //TO SUPPORT BT-AMP sirCopyMacAddr(currentBssId,sessionEntry->bssId); @@ -772,7 +772,7 @@ limDecryptAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pKey, tANI_U8 *pEncrBody, keyLength, frameLen); - PELOG4(limLog(pMac, LOG4, FL("plainbody is \n")); + PELOG4(limLog(pMac, LOG4, FL("plainbody is ")); sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG4, pPlainBody, frameLen);) // Compute CRC-32 and place them in last 4 bytes of encrypted body @@ -783,7 +783,7 @@ limDecryptAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pKey, tANI_U8 *pEncrBody, // Compare RX_ICV with computed ICV for (i = 0; i < SIR_MAC_WEP_ICV_LENGTH; i++) { - PELOG4(limLog(pMac, LOG4, FL(" computed ICV%d[%x], rxed ICV%d[%x]\n"), + PELOG4(limLog(pMac, LOG4, FL(" computed ICV%d[%x], rxed ICV%d[%x]"), i, icv[i], i, pPlainBody[frameLen - SIR_MAC_WEP_ICV_LENGTH + i]);) if (icv[i] != pPlainBody[frameLen - SIR_MAC_WEP_ICV_LENGTH + i]) return LIM_DECRYPT_ICV_FAIL; @@ -880,7 +880,7 @@ tANI_U32 val = 0; if(pMlmSetKeysReq->numKeys > SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS) { limLog( pMac, LOG1, - FL( "numKeys = %d is more than SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS\n" ), pMlmSetKeysReq->numKeys); + FL( "numKeys = %d is more than SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS" ), pMlmSetKeysReq->numKeys); // Respond to SME with error code mlmSetKeysCnf.resultCode = eSIR_SME_INVALID_PARAMETERS; @@ -894,7 +894,7 @@ tANI_U32 val = 0; sizeof( tSetBssKeyParams ))) { limLog( pMac, LOGE, - FL( "Unable to PAL allocate memory during SET_BSSKEY\n" )); + FL( "Unable to PAL allocate memory during SET_BSSKEY" )); // Respond to SME with error code mlmSetKeysCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE; @@ -912,7 +912,7 @@ tANI_U32 val = 0; if(eSIR_SUCCESS != wlan_cfgGetInt(pMac, WNI_CFG_SINGLE_TID_RC, &val)) { - limLog( pMac, LOGP, FL( "Unable to read WNI_CFG_SINGLE_TID_RC\n" )); + limLog( pMac, LOGP, FL( "Unable to read WNI_CFG_SINGLE_TID_RC" )); } pSetBssKeyParams->singleTidRc = (tANI_U8)val; @@ -954,12 +954,12 @@ tANI_U32 val = 0; msgQ.bodyval = 0; limLog( pMac, LOGW, - FL( "Sending WDA_SET_BSSKEY_REQ...\n" )); + FL( "Sending WDA_SET_BSSKEY_REQ..." )); MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, msgQ.type)); if( eSIR_SUCCESS != (retCode = wdaPostCtrlMsg( pMac, &msgQ ))) { limLog( pMac, LOGE, - FL("Posting SET_BSSKEY to HAL failed, reason=%X\n"), + FL("Posting SET_BSSKEY to HAL failed, reason=%X"), retCode ); // Respond to SME with LIM_MLM_SETKEYS_CNF @@ -1011,7 +1011,7 @@ tANI_U32 val = 0; // Package WDA_SET_STAKEY_REQ message parameters if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **) &pSetStaKeyParams, sizeof( tSetStaKeyParams ))) { - limLog( pMac, LOGP, FL( "Unable to PAL allocate memory during SET_BSSKEY\n" )); + limLog( pMac, LOGP, FL( "Unable to PAL allocate memory during SET_BSSKEY" )); return; }else palZeroMemory( pMac->hHdd, (void *) pSetStaKeyParams, sizeof( tSetStaKeyParams )); @@ -1023,7 +1023,7 @@ tANI_U32 val = 0; if(eSIR_SUCCESS != wlan_cfgGetInt(pMac, WNI_CFG_SINGLE_TID_RC, &val)) { - limLog( pMac, LOGP, FL( "Unable to read WNI_CFG_SINGLE_TID_RC\n" )); + limLog( pMac, LOGP, FL( "Unable to read WNI_CFG_SINGLE_TID_RC" )); } pSetStaKeyParams->singleTidRc = (tANI_U8)val; @@ -1108,10 +1108,10 @@ tANI_U32 val = 0; msgQ.bodyptr = pSetStaKeyParams; msgQ.bodyval = 0; - limLog( pMac, LOG1, FL( "Sending WDA_SET_STAKEY_REQ...\n" )); + limLog( pMac, LOG1, FL( "Sending WDA_SET_STAKEY_REQ..." )); MTRACE(macTraceMsgTx(pMac, sessionEntry->peSessionId, msgQ.type)); if( eSIR_SUCCESS != (retCode = wdaPostCtrlMsg( pMac, &msgQ ))) { - limLog( pMac, LOGE, FL("Posting SET_STAKEY to HAL failed, reason=%X\n"), retCode ); + limLog( pMac, LOGE, FL("Posting SET_STAKEY to HAL failed, reason=%X"), retCode ); // Respond to SME with LIM_MLM_SETKEYS_CNF mlmSetKeysCnf.resultCode = eSIR_SME_HAL_SEND_MESSAGE_FAIL; }else @@ -1156,7 +1156,7 @@ tSirRetStatus retCode; sizeof( tRemoveBssKeyParams ))) { limLog( pMac, LOGE, - FL( "Unable to PAL allocate memory during REMOVE_BSSKEY\n" )); + FL( "Unable to PAL allocate memory during REMOVE_BSSKEY" )); // Respond to SME with error code mlmRemoveKeysCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE; @@ -1188,13 +1188,13 @@ tSirRetStatus retCode; msgQ.bodyval = 0; limLog( pMac, LOGW, - FL( "Sending WDA_REMOVE_BSSKEY_REQ...\n" )); + FL( "Sending WDA_REMOVE_BSSKEY_REQ..." )); MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, msgQ.type)); if( eSIR_SUCCESS != (retCode = wdaPostCtrlMsg( pMac, &msgQ ))) { limLog( pMac, LOGE, - FL("Posting REMOVE_BSSKEY to HAL failed, reason=%X\n"), + FL("Posting REMOVE_BSSKEY to HAL failed, reason=%X"), retCode ); // Respond to SME with LIM_MLM_REMOVEKEYS_CNF @@ -1249,7 +1249,7 @@ tSirRetStatus retCode; sizeof( tRemoveStaKeyParams ))) { limLog( pMac, LOGE, - FL( "Unable to PAL allocate memory during REMOVE_STAKEY\n" )); + FL( "Unable to PAL allocate memory during REMOVE_STAKEY" )); // Respond to SME with error code mlmRemoveKeyCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE; @@ -1263,11 +1263,11 @@ tSirRetStatus retCode; if( (pMlmRemoveKeyReq->edType == eSIR_ED_WEP104 || pMlmRemoveKeyReq->edType == eSIR_ED_WEP40) && pMlmRemoveKeyReq->wepType == eSIR_WEP_STATIC ) { - PELOGE(limLog(pMac, LOGE, FL("Request to remove static WEP keys through station interface\n Should use BSS interface\n"));) + PELOGE(limLog(pMac, LOGE, FL("Request to remove static WEP keys through station interface\n Should use BSS interface"));) mlmRemoveKeyCnf.resultCode = eSIR_SME_INVALID_PARAMETERS; goto end; } - + // Update the WDA_REMOVEKEY_REQ parameters pRemoveStaKeyParams->staIdx = staIdx; pRemoveStaKeyParams->encType = pMlmRemoveKeyReq->edType; @@ -1278,7 +1278,7 @@ tSirRetStatus retCode; pRemoveStaKeyParams->sessionId = psessionEntry->peSessionId; SET_LIM_PROCESS_DEFD_MESGS(pMac, false); - + msgQ.type = WDA_REMOVE_STAKEY_REQ; // // FIXME_GEN4 @@ -1290,19 +1290,21 @@ tSirRetStatus retCode; msgQ.bodyval = 0; limLog( pMac, LOGW, - FL( "Sending WDA_REMOVE_STAKEY_REQ...\n" )); + FL( "Sending WDA_REMOVE_STAKEY_REQ..." )); MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, msgQ.type)); - if( eSIR_SUCCESS != (retCode = wdaPostCtrlMsg( pMac, &msgQ ))) + retCode = wdaPostCtrlMsg( pMac, &msgQ ); + if (eSIR_SUCCESS != retCode) { limLog( pMac, LOGE, - FL("Posting REMOVE_STAKEY to HAL failed, reason=%X\n"), + FL("Posting REMOVE_STAKEY to HAL failed, reason=%X"), retCode ); + palFreeMemory(pMac->hHdd, pRemoveStaKeyParams); // Respond to SME with LIM_MLM_REMOVEKEY_CNF mlmRemoveKeyCnf.resultCode = eSIR_SME_HAL_SEND_MESSAGE_FAIL; } else - return; + return; end: limPostSmeRemoveKeyCnf( pMac, diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limSendManagementFrames.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limSendManagementFrames.c index 0a2325b748b..d54b6b7905d 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limSendManagementFrames.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limSendManagementFrames.c @@ -128,16 +128,6 @@ tSirRetStatus limPopulateMacHeader( tpAniSirGlobal pMac, sizeof( tSirMacAddr )); // Prepare Address 2 - #if 0 - if ((statusCode = wlan_cfgGetStr(pMac, WNI_CFG_STA_ID, (tANI_U8 *) pMacHdr->sa, - &cfgLen)) != eSIR_SUCCESS) - { - // Could not get STA_ID from CFG. Log error. - limLog( pMac, LOGP, - FL("Failed to retrive STA_ID\n")); - return statusCode; - } - #endif// TO SUPPORT BT-AMP sirCopyMacAddr(pMacHdr->sa,selfMacAddr); // Prepare Address 3 @@ -315,7 +305,7 @@ limSendProbeReqMgmtFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGP, FL("Failed to calculate the packed size f" - "or a Probe Request (0x%08x).\n"), nStatus ); + "or a Probe Request (0x%08x)."), nStatus ); // We'll fall back on the worst case scenario: nPayload = sizeof( tDot11fProbeRequest ); } @@ -323,7 +313,7 @@ limSendProbeReqMgmtFrame(tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL("There were warnings while calculating" "the packed size for a Probe Request (" - "0x%08x).\n"), nStatus ); + "0x%08x)."), nStatus ); } nBytes = nPayload + sizeof( tSirMacMgmtHdr ) + nAdditionalIELen; @@ -335,7 +325,7 @@ limSendProbeReqMgmtFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a Pro" - "be Request.\n"), nBytes ); + "be Request."), nBytes ); return eSIR_MEM_ALLOC_FAILED; } @@ -348,7 +338,7 @@ limSendProbeReqMgmtFrame(tpAniSirGlobal pMac, if ( eSIR_SUCCESS != nSirStatus ) { limLog( pMac, LOGE, FL("Failed to populate the buffer descrip" - "tor for a Probe Request (%d).\n"), + "tor for a Probe Request (%d)."), nSirStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); @@ -361,7 +351,7 @@ limSendProbeReqMgmtFrame(tpAniSirGlobal pMac, nPayload, &nPayload ); if ( DOT11F_FAILED( nStatus ) ) { - limLog( pMac, LOGE, FL("Failed to pack a Probe Request (0x%08x).\n"), + limLog( pMac, LOGE, FL("Failed to pack a Probe Request (0x%08x)."), nStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return eSIR_FAILURE; // allocated! @@ -369,7 +359,7 @@ limSendProbeReqMgmtFrame(tpAniSirGlobal pMac, else if ( DOT11F_WARNED( nStatus ) ) { limLog( pMac, LOGW, FL("There were warnings while packing a P" - "robe Request (0x%08x).\n") ); + "robe Request (0x%08x).") ); } // Append any AddIE if present. @@ -404,7 +394,7 @@ limSendProbeReqMgmtFrame(tpAniSirGlobal pMac, limTxComplete, pFrame, txFlag ); if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { - limLog( pMac, LOGE, FL("could not send Probe Request frame!\n" )); + limLog( pMac, LOGE, FL("could not send Probe Request frame!" )); //Pkt will be freed up by the callback return eSIR_FAILURE; } @@ -449,7 +439,7 @@ tSirRetStatus limGetAddnIeForProbeResp(tpAniSirGlobal pMac, if(elem_len > left) { limLog( pMac, LOGE, - FL("****Invalid IEs eid = %d elem_len=%d left=%d*****\n"), + FL("****Invalid IEs eid = %d elem_len=%d left=%d*****"), elem_id,elem_len,left); palFreeMemory(pMac->hHdd, tempbuf); return eSIR_FAILURE; @@ -514,7 +504,7 @@ limSendProbeRspMgmtFrame(tpAniSirGlobal pMac, if(eHAL_STATUS_SUCCESS != palAllocateMemory(pMac->hHdd, (void **)&pFrm, sizeof(tDot11fProbeResponse))) { - limLog(pMac, LOGE, FL("Unable to PAL allocate memory in limSendProbeRspMgmtFrame\n") ); + limLog(pMac, LOGE, FL("Unable to PAL allocate memory in limSendProbeRspMgmtFrame") ); return; } @@ -534,7 +524,7 @@ limSendProbeRspMgmtFrame(tpAniSirGlobal pMac, nSirStatus = wlan_cfgGetInt( pMac, WNI_CFG_BEACON_INTERVAL, &cfg); if (eSIR_SUCCESS != nSirStatus) { - limLog( pMac, LOGP, FL("Failed to retrieve WNI_CFG_BEACON_INTERVAL from CFG (%d).\n"), + limLog( pMac, LOGP, FL("Failed to retrieve WNI_CFG_BEACON_INTERVAL from CFG (%d)."), nSirStatus ); palFreeMemory(pMac->hHdd, pFrm); return; @@ -561,7 +551,7 @@ limSendProbeRspMgmtFrame(tpAniSirGlobal pMac, else { if (wlan_cfgGetInt(pMac, (tANI_U16) WNI_CFG_WPS_ENABLE, &tmp) != eSIR_SUCCESS) - limLog(pMac, LOGP,"Failed to cfg get id %d\n", WNI_CFG_WPS_ENABLE ); + limLog(pMac, LOGP,"Failed to cfg get id %d", WNI_CFG_WPS_ENABLE ); wpsApEnable = tmp & WNI_CFG_WPS_ENABLE_AP; @@ -605,7 +595,7 @@ limSendProbeRspMgmtFrame(tpAniSirGlobal pMac, #ifdef WLAN_FEATURE_11AC if(psessionEntry->vhtCapability) { - limLog( pMac, LOGW, FL("Populate VHT IE in Probe Response\n")); + limLog( pMac, LOGW, FL("Populate VHT IE in Probe Response")); PopulateDot11fVHTCaps( pMac, &pFrm->VHTCaps ); PopulateDot11fVHTOperation( pMac, &pFrm->VHTOperation ); // we do not support multi users yet @@ -638,7 +628,7 @@ limSendProbeRspMgmtFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGP, FL("Failed to calculate the packed size f" - "or a Probe Response (0x%08x).\n"), + "or a Probe Response (0x%08x)."), nStatus ); // We'll fall back on the worst case scenario: nPayload = sizeof( tDot11fProbeResponse ); @@ -647,7 +637,7 @@ limSendProbeRspMgmtFrame(tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL("There were warnings while calculating" "the packed size for a Probe Response " - "(0x%08x).\n"), nStatus ); + "(0x%08x)."), nStatus ); } nBytes = nPayload + sizeof( tSirMacMgmtHdr ); @@ -790,7 +780,7 @@ limSendProbeRspMgmtFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a Pro" - "be Response.\n"), nBytes ); + "be Response."), nBytes ); if ( addIE != NULL ) { palFreeMemory(pMac->hHdd, addIE); @@ -808,7 +798,7 @@ limSendProbeRspMgmtFrame(tpAniSirGlobal pMac, if ( eSIR_SUCCESS != nSirStatus ) { limLog( pMac, LOGE, FL("Failed to populate the buffer descrip" - "tor for a Probe Response (%d).\n"), + "tor for a Probe Response (%d)."), nSirStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); @@ -829,7 +819,7 @@ limSendProbeRspMgmtFrame(tpAniSirGlobal pMac, nPayload, &nPayload ); if ( DOT11F_FAILED( nStatus ) ) { - limLog( pMac, LOGE, FL("Failed to pack a Probe Response (0x%08x).\n"), + limLog( pMac, LOGE, FL("Failed to pack a Probe Response (0x%08x)."), nStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); if ( addIE != NULL ) @@ -842,7 +832,7 @@ limSendProbeRspMgmtFrame(tpAniSirGlobal pMac, else if ( DOT11F_WARNED( nStatus ) ) { limLog( pMac, LOGW, FL("There were warnings while packing a P" - "robe Response (0x%08x).\n") ); + "robe Response (0x%08x).") ); } PELOG3(limLog( pMac, LOG3, FL("Sending Probe Response frame to ") ); @@ -899,7 +889,7 @@ limSendProbeRspMgmtFrame(tpAniSirGlobal pMac, limTxComplete, pFrame, txFlag ); if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { - limLog( pMac, LOGE, FL("Could not send Probe Response.\n") ); + limLog( pMac, LOGE, FL("Could not send Probe Response.") ); //Pkt will be freed up by the callback } @@ -995,7 +985,7 @@ limSendAddtsReqActionFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGP, FL("Failed to calculate the packed size f" - "or an Add TS Request (0x%08x).\n"), + "or an Add TS Request (0x%08x)."), nStatus ); // We'll fall back on the worst case scenario: nPayload = sizeof( tDot11fAddTSRequest ); @@ -1004,7 +994,7 @@ limSendAddtsReqActionFrame(tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL("There were warnings while calculating" "the packed size for an Add TS Request" - " (0x%08x).\n"), nStatus ); + " (0x%08x)."), nStatus ); } } else @@ -1038,7 +1028,7 @@ limSendAddtsReqActionFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGP, FL("Failed to calculate the packed size f" - "or a WMM Add TS Request (0x%08x).\n"), + "or a WMM Add TS Request (0x%08x)."), nStatus ); // We'll fall back on the worst case scenario: nPayload = sizeof( tDot11fAddTSRequest ); @@ -1047,7 +1037,7 @@ limSendAddtsReqActionFrame(tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL("There were warnings while calculating" "the packed size for a WMM Add TS Requ" - "est (0x%08x).\n"), nStatus ); + "est (0x%08x)."), nStatus ); } } @@ -1059,7 +1049,7 @@ limSendAddtsReqActionFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGP, FL("Failed to allocate %d bytes for an Ad" - "d TS Request.\n"), nBytes ); + "d TS Request."), nBytes ); return; } @@ -1072,7 +1062,7 @@ limSendAddtsReqActionFrame(tpAniSirGlobal pMac, if ( eSIR_SUCCESS != nSirStatus ) { limLog( pMac, LOGE, FL("Failed to populate the buffer descrip" - "tor for an Add TS Request (%d).\n"), + "tor for an Add TS Request (%d)."), nSirStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); @@ -1087,7 +1077,7 @@ limSendAddtsReqActionFrame(tpAniSirGlobal pMac, ( tANI_U8* )pMacHdr->bssId, &cfgLen ) ) { limLog( pMac, LOGP, FL("Failed to retrieve WNI_CFG_BSSID whil" - "e sending an Add TS Request.\n") ); + "e sending an Add TS Request.") ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return; @@ -1096,13 +1086,6 @@ limSendAddtsReqActionFrame(tpAniSirGlobal pMac, sirCopyMacAddr(pMacHdr->bssId,psessionEntry->bssId); -#ifdef WLAN_FEATURE_11W - if ( psessionEntry->limRmfEnabled ) - { - pMacHdr->fc.wep = 1; - } -#endif - // That done, pack the struct: if ( ! pAddTS->wmeTspecPresent ) { @@ -1112,7 +1095,7 @@ limSendAddtsReqActionFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGE, FL("Failed to pack an Add TS Request " - "(0x%08x).\n"), + "(0x%08x)."), nStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return; // allocated! @@ -1120,7 +1103,7 @@ limSendAddtsReqActionFrame(tpAniSirGlobal pMac, else if ( DOT11F_WARNED( nStatus ) ) { limLog( pMac, LOGW, FL("There were warnings while packing" - "an Add TS Request (0x%08x).\n") ); + "an Add TS Request (0x%08x).") ); } } else @@ -1131,7 +1114,7 @@ limSendAddtsReqActionFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGE, FL("Failed to pack a WMM Add TS Reque" - "st (0x%08x).\n"), + "st (0x%08x)."), nStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return; // allocated! @@ -1139,7 +1122,7 @@ limSendAddtsReqActionFrame(tpAniSirGlobal pMac, else if ( DOT11F_WARNED( nStatus ) ) { limLog( pMac, LOGW, FL("There were warnings while packing" - "a WMM Add TS Request (0x%08x).\n") ); + "a WMM Add TS Request (0x%08x).") ); } } @@ -1163,7 +1146,7 @@ limSendAddtsReqActionFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGE, FL( "*** Could not send an Add TS Request" - " (%X) ***\n" ), halstatus ); + " (%X) ***" ), halstatus ); //Pkt will be freed up by the callback } @@ -1298,7 +1281,7 @@ limSendAssocRspMgmtFrame(tpAniSirGlobal pMac, if( pSta->mlmStaContext.vhtCapability && psessionEntry->vhtCapability ) { - limLog( pMac, LOGW, FL("Populate VHT IEs in Assoc Response\n")); + limLog( pMac, LOGW, FL("Populate VHT IEs in Assoc Response")); PopulateDot11fVHTCaps( pMac, &frm.VHTCaps ); PopulateDot11fVHTOperation( pMac, &frm.VHTOperation); PopulateDot11fExtCap( pMac, &frm.ExtCap); @@ -1332,7 +1315,7 @@ limSendAssocRspMgmtFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGE, FL("Failed to calculate the packed size f" - "or an Association Response (0x%08x).\n"), + "or an Association Response (0x%08x)."), nStatus ); return; } @@ -1340,7 +1323,7 @@ limSendAssocRspMgmtFrame(tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL("There were warnings while calculating" "the packed size for an Association Re" - "sponse (0x%08x).\n"), nStatus ); + "sponse (0x%08x)."), nStatus ); } nBytes = sizeof( tSirMacMgmtHdr ) + nPayload; @@ -1381,7 +1364,7 @@ limSendAssocRspMgmtFrame(tpAniSirGlobal pMac, ( void** ) &pPacket ); if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { - limLog(pMac, LOGP, FL("Call to bufAlloc failed for RE/ASSOC RSP.\n")); + limLog(pMac, LOGP, FL("Call to bufAlloc failed for RE/ASSOC RSP.")); return; } @@ -1399,7 +1382,7 @@ limSendAssocRspMgmtFrame(tpAniSirGlobal pMac, if ( eSIR_SUCCESS != nSirStatus ) { limLog( pMac, LOGE, FL("Failed to populate the buffer descrip" - "tor for an Association Response (%d).\n"), + "tor for an Association Response (%d)."), nSirStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); @@ -1408,17 +1391,6 @@ limSendAssocRspMgmtFrame(tpAniSirGlobal pMac, pMacHdr = ( tpSirMacMgmtHdr ) pFrame; - #if 0 - cfgLen = SIR_MAC_ADDR_LENGTH; - if ( eSIR_SUCCESS != cfgGetStr( pMac, WNI_CFG_BSSID, - ( tANI_U8* )pMacHdr->bssId, &cfgLen ) ) - { - limLog( pMac, LOGP, FL("Failed to retrieve WNI_CFG_BSSID whil" - "e sending an Association Response.\n") ); - palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); - return; // allocated! - } - #endif //TO SUPPORT BT-AMP sirCopyMacAddr(pMacHdr->bssId,psessionEntry->bssId); nStatus = dot11fPackAssocResponse( pMac, &frm, @@ -1426,7 +1398,7 @@ limSendAssocRspMgmtFrame(tpAniSirGlobal pMac, nPayload, &nPayload ); if ( DOT11F_FAILED( nStatus ) ) { - limLog( pMac, LOGE, FL("Failed to pack an Association Response (0x%08x).\n"), + limLog( pMac, LOGE, FL("Failed to pack an Association Response (0x%08x)."), nStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); @@ -1435,7 +1407,7 @@ limSendAssocRspMgmtFrame(tpAniSirGlobal pMac, else if ( DOT11F_WARNED( nStatus ) ) { limLog( pMac, LOGW, FL("There were warnings while packing an " - "Association Response (0x%08x).\n") ); + "Association Response (0x%08x).") ); } macAddr = pMacHdr->da; @@ -1458,7 +1430,7 @@ limSendAssocRspMgmtFrame(tpAniSirGlobal pMac, if (palCopyMemory ( pMac->hHdd, pFrame+sizeof(tSirMacMgmtHdr)+nPayload, &addIE[0], addnIELen ) != eHAL_STATUS_SUCCESS) { - limLog(pMac, LOGP, FL("Additional Assoc IEs request failed while Appending: %x\n"),halstatus); + limLog(pMac, LOGP, FL("Additional Assoc IEs request failed while Appending: %x"),halstatus); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return; @@ -1482,7 +1454,7 @@ limSendAssocRspMgmtFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog(pMac, LOGE, - FL("*** Could not Send Re/AssocRsp, retCode=%X ***\n"), + FL("*** Could not Send Re/AssocRsp, retCode=%X ***"), nSirStatus); //Pkt will be freed up by the callback @@ -1615,7 +1587,7 @@ limSendAddtsRspActionFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGP, FL("Failed to calculate the packed si" - "ze for an Add TS Response (0x%08x).\n"), + "ze for an Add TS Response (0x%08x)."), nStatus ); // We'll fall back on the worst case scenario: nPayload = sizeof( tDot11fAddTSResponse ); @@ -1624,7 +1596,7 @@ limSendAddtsRspActionFrame(tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL("There were warnings while calcula" "tingthe packed size for an Add TS" - " Response (0x%08x).\n"), nStatus ); + " Response (0x%08x)."), nStatus ); } } else @@ -1642,7 +1614,7 @@ limSendAddtsRspActionFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGP, FL("Failed to calculate the packed si" - "ze for a WMM Add TS Response (0x%08x).\n"), + "ze for a WMM Add TS Response (0x%08x)."), nStatus ); // We'll fall back on the worst case scenario: nPayload = sizeof( tDot11fWMMAddTSResponse ); @@ -1651,7 +1623,7 @@ limSendAddtsRspActionFrame(tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL("There were warnings while calcula" "tingthe packed size for a WMM Add" - "TS Response (0x%08x).\n"), nStatus ); + "TS Response (0x%08x)."), nStatus ); } } @@ -1661,7 +1633,7 @@ limSendAddtsRspActionFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGP, FL("Failed to allocate %d bytes for an Ad" - "d TS Response.\n"), nBytes ); + "d TS Response."), nBytes ); return; } @@ -1674,7 +1646,7 @@ limSendAddtsRspActionFrame(tpAniSirGlobal pMac, if ( eSIR_SUCCESS != nSirStatus ) { limLog( pMac, LOGE, FL("Failed to populate the buffer descrip" - "tor for an Add TS Response (%d).\n"), + "tor for an Add TS Response (%d)."), nSirStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return; // allocated! @@ -1688,20 +1660,13 @@ limSendAddtsRspActionFrame(tpAniSirGlobal pMac, ( tANI_U8* )pMacHdr->bssId, &cfgLen ) ) { limLog( pMac, LOGP, FL("Failed to retrieve WNI_CFG_BSSID whil" - "e sending an Add TS Response.\n") ); + "e sending an Add TS Response.") ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return; // allocated! } #endif //TO SUPPORT BT-AMP sirCopyMacAddr(pMacHdr->bssId,psessionEntry->bssId); -#ifdef WLAN_FEATURE_11W - if ( psessionEntry->limRmfEnabled ) - { - pMacHdr->fc.wep = 1; - } -#endif - // That done, pack the struct: if ( ! pAddTS->wmeTspecPresent ) { @@ -1711,7 +1676,7 @@ limSendAddtsRspActionFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGE, FL("Failed to pack an Add TS Response " - "(0x%08x).\n"), + "(0x%08x)."), nStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return; @@ -1719,7 +1684,7 @@ limSendAddtsRspActionFrame(tpAniSirGlobal pMac, else if ( DOT11F_WARNED( nStatus ) ) { limLog( pMac, LOGW, FL("There were warnings while packing" - "an Add TS Response (0x%08x).\n") ); + "an Add TS Response (0x%08x).") ); } } else @@ -1730,7 +1695,7 @@ limSendAddtsRspActionFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGE, FL("Failed to pack a WMM Add TS Response " - "(0x%08x).\n"), + "(0x%08x)."), nStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return; @@ -1738,7 +1703,7 @@ limSendAddtsRspActionFrame(tpAniSirGlobal pMac, else if ( DOT11F_WARNED( nStatus ) ) { limLog( pMac, LOGW, FL("There were warnings while packing" - "a WMM Add TS Response (0x%08x).\n") ); + "a WMM Add TS Response (0x%08x).") ); } } @@ -1762,7 +1727,7 @@ limSendAddtsRspActionFrame(tpAniSirGlobal pMac, limTxComplete, pFrame, txFlag ); if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { - limLog( pMac, LOGE, FL("Failed to send Add TS Response (%X)!\n"), + limLog( pMac, LOGE, FL("Failed to send Add TS Response (%X)!"), nSirStatus ); //Pkt will be freed up by the callback } @@ -1804,7 +1769,7 @@ limSendDeltsReqActionFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGP, FL("Failed to calculate the packed si" - "ze for a Del TS (0x%08x).\n"), + "ze for a Del TS (0x%08x)."), nStatus ); // We'll fall back on the worst case scenario: nPayload = sizeof( tDot11fDelTS ); @@ -1813,7 +1778,7 @@ limSendDeltsReqActionFrame(tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL("There were warnings while calcula" "ting the packed size for a Del TS" - " (0x%08x).\n"), nStatus ); + " (0x%08x)."), nStatus ); } } else @@ -1829,7 +1794,7 @@ limSendDeltsReqActionFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGP, FL("Failed to calculate the packed si" - "ze for a WMM Del TS (0x%08x).\n"), + "ze for a WMM Del TS (0x%08x)."), nStatus ); // We'll fall back on the worst case scenario: nPayload = sizeof( tDot11fDelTS ); @@ -1838,7 +1803,7 @@ limSendDeltsReqActionFrame(tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL("There were warnings while calcula" "ting the packed size for a WMM De" - "l TS (0x%08x).\n"), nStatus ); + "l TS (0x%08x)."), nStatus ); } } @@ -1848,7 +1813,7 @@ limSendDeltsReqActionFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGP, FL("Failed to allocate %d bytes for an Ad" - "d TS Response.\n"), nBytes ); + "d TS Response."), nBytes ); return; } @@ -1862,7 +1827,7 @@ limSendDeltsReqActionFrame(tpAniSirGlobal pMac, if ( eSIR_SUCCESS != nSirStatus ) { limLog( pMac, LOGE, FL("Failed to populate the buffer descrip" - "tor for an Add TS Response (%d).\n"), + "tor for an Add TS Response (%d)."), nSirStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return; // allocated! @@ -1877,20 +1842,13 @@ limSendDeltsReqActionFrame(tpAniSirGlobal pMac, ( tANI_U8* )pMacHdr->bssId, &cfgLen ) ) { limLog( pMac, LOGP, FL("Failed to retrieve WNI_CFG_BSSID whil" - "e sending an Add TS Response.\n") ); + "e sending an Add TS Response.") ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return; // allocated! } #endif //TO SUPPORT BT-AMP sirCopyMacAddr(pMacHdr->bssId, psessionEntry->bssId); -#ifdef WLAN_FEATURE_11W - if ( psessionEntry->limRmfEnabled ) - { - pMacHdr->fc.wep = 1; - } -#endif - // That done, pack the struct: if ( !wmmTspecPresent ) { @@ -1899,7 +1857,7 @@ limSendDeltsReqActionFrame(tpAniSirGlobal pMac, nPayload, &nPayload ); if ( DOT11F_FAILED( nStatus ) ) { - limLog( pMac, LOGE, FL("Failed to pack a Del TS frame (0x%08x).\n"), + limLog( pMac, LOGE, FL("Failed to pack a Del TS frame (0x%08x)."), nStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return; // allocated! @@ -1907,7 +1865,7 @@ limSendDeltsReqActionFrame(tpAniSirGlobal pMac, else if ( DOT11F_WARNED( nStatus ) ) { limLog( pMac, LOGW, FL("There were warnings while packing" - "a Del TS frame (0x%08x).\n") ); + "a Del TS frame (0x%08x).") ); } } else @@ -1917,7 +1875,7 @@ limSendDeltsReqActionFrame(tpAniSirGlobal pMac, nPayload, &nPayload ); if ( DOT11F_FAILED( nStatus ) ) { - limLog( pMac, LOGE, FL("Failed to pack a WMM Del TS frame (0x%08x).\n"), + limLog( pMac, LOGE, FL("Failed to pack a WMM Del TS frame (0x%08x)."), nStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return; // allocated! @@ -1925,7 +1883,7 @@ limSendDeltsReqActionFrame(tpAniSirGlobal pMac, else if ( DOT11F_WARNED( nStatus ) ) { limLog( pMac, LOGW, FL("There were warnings while packing" - "a WMM Del TS frame (0x%08x).\n") ); + "a WMM Del TS frame (0x%08x).") ); } } @@ -1947,7 +1905,7 @@ limSendDeltsReqActionFrame(tpAniSirGlobal pMac, limTxComplete, pFrame, txFlag ); if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { - limLog( pMac, LOGE, FL("Failed to send Del TS (%X)!\n"), + limLog( pMac, LOGE, FL("Failed to send Del TS (%X)!"), nSirStatus ); //Pkt will be freed up by the callback } @@ -1997,7 +1955,7 @@ limSendAssocReqMgmtFrame(tpAniSirGlobal pMac, if(eHAL_STATUS_SUCCESS != palAllocateMemory(pMac->hHdd, (void **)&pFrm, sizeof(tDot11fAssocRequest))) { - limLog(pMac, LOGE, FL("Unable to PAL allocate memory in limSendAssocReqMgmtFrame\n") ); + limLog(pMac, LOGE, FL("Unable to PAL allocate memory in limSendAssocReqMgmtFrame") ); return; } @@ -2163,34 +2121,43 @@ limSendAssocReqMgmtFrame(tpAniSirGlobal pMac, if (psessionEntry->pLimJoinReq->is11Rconnection) { #if defined WLAN_FEATURE_VOWIFI_11R_DEBUG - limLog( pMac, LOG1, FL("mdie = %02x %02x %02x"), + limLog( pMac, LOG1, FL("mdie = %02x %02x %02x"), (unsigned int)psessionEntry->pLimJoinReq->bssDescription.mdie[0], (unsigned int)psessionEntry->pLimJoinReq->bssDescription.mdie[1], (unsigned int)psessionEntry->pLimJoinReq->bssDescription.mdie[2]); #endif - PopulateMDIE( pMac, &pFrm->MobilityDomain, psessionEntry->pLimJoinReq->bssDescription.mdie); + PopulateMDIE( pMac, &pFrm->MobilityDomain, + psessionEntry->pLimJoinReq->bssDescription.mdie); } - else + else { // No 11r IEs dont send any MDIE - limLog( pMac, LOG1, FL("mdie not present")); + limLog( pMac, LOG1, FL("MDIE not present")); } #endif #ifdef FEATURE_WLAN_CCX - // For CCX Associations fill the CCX IEs - if (psessionEntry->isCCXconnection) + /* CCX Version IE will be included in association request + when CCX is enabled on DUT through ini */ + if (psessionEntry->pLimJoinReq->isCCXFeatureIniEnabled) { - PopulateDot11fCCXRadMgmtCap(&pFrm->CCXRadMgmtCap); PopulateDot11fCCXVersion(&pFrm->CCXVersion); } + /* For CCX Associations fill the CCX IEs */ + if (psessionEntry->isCCXconnection && + psessionEntry->pLimJoinReq->isCCXFeatureIniEnabled) + { +#ifndef FEATURE_DISABLE_RM + PopulateDot11fCCXRadMgmtCap(&pFrm->CCXRadMgmtCap); +#endif + } #endif nStatus = dot11fGetPackedAssocRequestSize( pMac, pFrm, &nPayload ); if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGP, FL("Failed to calculate the packed size f" - "or an Association Request (0x%08x).\n"), + "or an Association Request (0x%08x)."), nStatus ); // We'll fall back on the worst case scenario: nPayload = sizeof( tDot11fAssocRequest ); @@ -2199,7 +2166,7 @@ limSendAssocReqMgmtFrame(tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL("There were warnings while calculating" "the packed size for an Association Re " - "quest(0x%08x).\n"), nStatus ); + "quest(0x%08x)."), nStatus ); } nBytes = nPayload + sizeof( tSirMacMgmtHdr ) + nAddIELen; @@ -2210,7 +2177,7 @@ limSendAssocReqMgmtFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGP, FL("Failed to allocate %d bytes for an As" - "sociation Request.\n"), nBytes ); + "sociation Request."), nBytes ); psessionEntry->limMlmState = psessionEntry->limPrevMlmState; MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, psessionEntry->limMlmState)); @@ -2240,7 +2207,7 @@ limSendAssocReqMgmtFrame(tpAniSirGlobal pMac, if ( eSIR_SUCCESS != nSirStatus ) { limLog( pMac, LOGE, FL("Failed to populate the buffer descrip" - "tor for an Association Request (%d).\n"), + "tor for an Association Request (%d)."), nSirStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); palFreeMemory(pMac->hHdd, pFrm); @@ -2255,7 +2222,7 @@ limSendAssocReqMgmtFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGE, FL("Failed to pack a Probe Response (0x%0" - "8x).\n"), + "8x)."), nStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); @@ -2265,11 +2232,11 @@ limSendAssocReqMgmtFrame(tpAniSirGlobal pMac, else if ( DOT11F_WARNED( nStatus ) ) { limLog( pMac, LOGW, FL("There were warnings while packing a P" - "robe Response (0x%08x).\n") ); + "robe Response (0x%08x).") ); } PELOG1(limLog( pMac, LOG1, FL("*** Sending Association Request length %d" - "to \n"), + "to "), nBytes );) // limPrintMacAddr( pMac, bssid, LOG1 ); @@ -2319,7 +2286,7 @@ limSendAssocReqMgmtFrame(tpAniSirGlobal pMac, limTxComplete, pFrame, txFlag ); if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { - limLog( pMac, LOGE, FL("Failed to send Association Request (%X)!\n"), + limLog( pMac, LOGE, FL("Failed to send Association Request (%X)!"), halstatus ); //Pkt will be freed up by the callback palFreeMemory(pMac->hHdd, pFrm); @@ -2497,7 +2464,7 @@ limSendReassocReqWithFTIEsMgmtFrame(tpAniSirGlobal pMac, } #ifdef FEATURE_WLAN_CCX - if(psessionEntry->pLimReAssocReq->cckmIE.length) + if (psessionEntry->pLimReAssocReq->cckmIE.length) { PopulateDot11fCCXCckmOpaque( pMac, &( psessionEntry->pLimReAssocReq->cckmIE ), &frm.CCXCckmOpaque ); @@ -2506,13 +2473,21 @@ limSendReassocReqWithFTIEsMgmtFrame(tpAniSirGlobal pMac, } #ifdef FEATURE_WLAN_CCX + /* CCX Version IE will be included in reassociation request + when CCX is enabled on DUT through ini */ + if (psessionEntry->pLimReAssocReq->isCCXFeatureIniEnabled) + { + PopulateDot11fCCXVersion(&frm.CCXVersion); + } // For CCX Associations fill the CCX IEs - if (psessionEntry->isCCXconnection) + if (psessionEntry->isCCXconnection && + psessionEntry->pLimReAssocReq->isCCXFeatureIniEnabled) { +#ifndef FEATURE_DISABLE_RM PopulateDot11fCCXRadMgmtCap(&frm.CCXRadMgmtCap); - PopulateDot11fCCXVersion(&frm.CCXVersion); +#endif } -#endif //FEATURE_WLAN_CCX +#endif //FEATURE_WLAN_CCX #endif //FEATURE_WLAN_CCX || FEATURE_WLAN_LFR // include WME EDCA IE as well @@ -2545,14 +2520,14 @@ limSendReassocReqWithFTIEsMgmtFrame(tpAniSirGlobal pMac, { tsrsIE.rates[0] = TSRS_11AG_RATE_6MBPS; } - else + else { tsrsIE.rates[0] = TSRS_11B_RATE_5_5MBPS; } PopulateDot11TSRSIE(pMac,&tsrsIE, &frm.CCXTrafStrmRateSet, sizeof(tANI_U8)); } } -#endif +#endif } if ( psessionEntry->htCapability && @@ -2562,7 +2537,11 @@ limSendReassocReqWithFTIEsMgmtFrame(tpAniSirGlobal pMac, } #if defined WLAN_FEATURE_VOWIFI_11R - if ( psessionEntry->pLimReAssocReq->bssDescription.mdiePresent && (0 == pMac->ft.ftSmeContext.reassoc_ft_ies_length) ) + if ( psessionEntry->pLimReAssocReq->bssDescription.mdiePresent && (0 == pMac->ft.ftSmeContext.reassoc_ft_ies_length) +#if defined FEATURE_WLAN_CCX + && !psessionEntry->isCCXconnection +#endif + ) { PopulateMDIE( pMac, &frm.MobilityDomain, psessionEntry->pLimReAssocReq->bssDescription.mdie); } @@ -2572,7 +2551,7 @@ limSendReassocReqWithFTIEsMgmtFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGP, FL("Failed to calculate the packed size f" - "or a Re-Association Request (0x%08x).\n"), + "or a Re-Association Request (0x%08x)."), nStatus ); // We'll fall back on the worst case scenario: nPayload = sizeof( tDot11fReAssocRequest ); @@ -2581,7 +2560,7 @@ limSendReassocReqWithFTIEsMgmtFrame(tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL("There were warnings while calculating" "the packed size for a Re-Association Re " - "quest(0x%08x).\n"), nStatus ); + "quest(0x%08x)."), nStatus ); } nBytes = nPayload + sizeof( tSirMacMgmtHdr ) + nAddIELen; @@ -2606,7 +2585,7 @@ limSendReassocReqWithFTIEsMgmtFrame(tpAniSirGlobal pMac, psessionEntry->limMlmState = psessionEntry->limPrevMlmState; MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, psessionEntry->limMlmState)); limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a Re-As" - "sociation Request.\n"), nBytes ); + "sociation Request."), nBytes ); goto end; } @@ -2623,7 +2602,7 @@ limSendReassocReqWithFTIEsMgmtFrame(tpAniSirGlobal pMac, if ( eSIR_SUCCESS != nSirStatus ) { limLog( pMac, LOGE, FL("Failed to populate the buffer descrip" - "tor for an Association Request (%d).\n"), + "tor for an Association Request (%d)."), nSirStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); goto end; @@ -2637,7 +2616,7 @@ limSendReassocReqWithFTIEsMgmtFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGE, FL("Failed to pack a Re-Association Reque" - "st (0x%08x).\n"), + "st (0x%08x)."), nStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); goto end; @@ -2645,11 +2624,11 @@ limSendReassocReqWithFTIEsMgmtFrame(tpAniSirGlobal pMac, else if ( DOT11F_WARNED( nStatus ) ) { limLog( pMac, LOGW, FL("There were warnings while packing a R" - "e-Association Request (0x%08x).\n") ); + "e-Association Request (0x%08x).") ); } PELOG3(limLog( pMac, LOG3, - FL("*** Sending Re-Association Request length %d %d to \n"), + FL("*** Sending Re-Association Request length %d %d to "), nBytes, nPayload );) if( psessionEntry->assocReq != NULL ) { @@ -2736,7 +2715,7 @@ limSendReassocReqWithFTIEsMgmtFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGE, FL("Failed to send Re-Association Request" - "(%X)!\n"), + "(%X)!"), nSirStatus ); //Pkt will be freed up by the callback goto end; @@ -2773,7 +2752,7 @@ void limSendRetryReassocReqFrame(tpAniSirGlobal pMac, // Could not start reassoc failure timer. // Log error limLog(pMac, LOGP, - FL("could not start Reassociation failure timer\n")); + FL("could not start Reassociation failure timer")); // Return Reassoc confirm with // Resources Unavailable mlmReassocCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE; @@ -2974,7 +2953,7 @@ limSendReassocReqMgmtFrame(tpAniSirGlobal pMac, if ( psessionEntry->vhtCapability && psessionEntry->vhtCapabilityPresentInBeacon) { - limLog( pMac, LOGW, FL("Populate VHT IEs in Re-Assoc Request\n")); + limLog( pMac, LOGW, FL("Populate VHT IEs in Re-Assoc Request")); PopulateDot11fVHTCaps( pMac, &frm.VHTCaps ); PopulateDot11fExtCap( pMac, &frm.ExtCap); } @@ -2984,7 +2963,7 @@ limSendReassocReqMgmtFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGP, FL("Failed to calculate the packed size f" - "or a Re-Association Request (0x%08x).\n"), + "or a Re-Association Request (0x%08x)."), nStatus ); // We'll fall back on the worst case scenario: nPayload = sizeof( tDot11fReAssocRequest ); @@ -2993,7 +2972,7 @@ limSendReassocReqMgmtFrame(tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL("There were warnings while calculating" "the packed size for a Re-Association Re " - "quest(0x%08x).\n"), nStatus ); + "quest(0x%08x)."), nStatus ); } nBytes = nPayload + sizeof( tSirMacMgmtHdr ) + nAddIELen; @@ -3006,7 +2985,7 @@ limSendReassocReqMgmtFrame(tpAniSirGlobal pMac, psessionEntry->limMlmState = psessionEntry->limPrevMlmState; MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, psessionEntry->limMlmState)); limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a Re-As" - "sociation Request.\n"), nBytes ); + "sociation Request."), nBytes ); goto end; } @@ -3020,7 +2999,7 @@ limSendReassocReqMgmtFrame(tpAniSirGlobal pMac, if ( eSIR_SUCCESS != nSirStatus ) { limLog( pMac, LOGE, FL("Failed to populate the buffer descrip" - "tor for an Association Request (%d).\n"), + "tor for an Association Request (%d)."), nSirStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); goto end; @@ -3034,7 +3013,7 @@ limSendReassocReqMgmtFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGE, FL("Failed to pack a Re-Association Reque" - "st (0x%08x).\n"), + "st (0x%08x)."), nStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); goto end; @@ -3042,11 +3021,11 @@ limSendReassocReqMgmtFrame(tpAniSirGlobal pMac, else if ( DOT11F_WARNED( nStatus ) ) { limLog( pMac, LOGW, FL("There were warnings while packing a R" - "e-Association Request (0x%08x).\n") ); + "e-Association Request (0x%08x).") ); } PELOG1(limLog( pMac, LOG1, FL("*** Sending Re-Association Request length %d" - "to \n"), + "to "), nBytes );) if( psessionEntry->assocReq != NULL ) @@ -3096,7 +3075,7 @@ limSendReassocReqMgmtFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGE, FL("Failed to send Re-Association Request" - "(%X)!\n"), + "(%X)!"), nSirStatus ); //Pkt will be freed up by the callback goto end; @@ -3189,12 +3168,12 @@ limSendAuthMgmtFrame(tpAniSirGlobal pMac, if (0 != pMac->ft.ftPEContext.pFTPreAuthReq->ft_ies_length) { frameLen += pMac->ft.ftPEContext.pFTPreAuthReq->ft_ies_length; - limLog(pMac, LOG3, FL("Auth frame, FTIES length added=%d\n"), + limLog(pMac, LOG3, FL("Auth frame, FTIES length added=%d"), pMac->ft.ftPEContext.pFTPreAuthReq->ft_ies_length); } else { - limLog(pMac, LOG3, FL("Auth frame, Does not contain FTIES!!!\n")); + limLog(pMac, LOG3, FL("Auth frame, Does not contain FTIES!!!")); frameLen += (2+SIR_MDIE_SIZE); } } @@ -3273,7 +3252,7 @@ limSendAuthMgmtFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { // Log error - limLog(pMac, LOGP, FL("call to bufAlloc failed for AUTH frame\n")); + limLog(pMac, LOGP, FL("call to bufAlloc failed for AUTH frame")); return; } @@ -3308,7 +3287,7 @@ limSendAuthMgmtFrame(tpAniSirGlobal pMac, palCopyMemory( pMac->hHdd, pBody, (tANI_U8 *) pAuthFrameBody, bodyLen); PELOG1(limLog(pMac, LOG1, - FL("*** Sending Auth seq# 3 status %d (%d) to\n"), + FL("*** Sending Auth seq# 3 status %d (%d) to"), pAuthFrameBody->authStatusCode, (pAuthFrameBody->authStatusCode == eSIR_MAC_SUCCESS_STATUS)); @@ -3327,8 +3306,8 @@ limSendAuthMgmtFrame(tpAniSirGlobal pMac, *((tANI_U16 *)(pBody)) = sirSwapU16ifNeeded(pAuthFrameBody->authStatusCode); pBody += sizeof(tANI_U16); bodyLen -= sizeof(tANI_U16); - if ( bodyLen < sizeof (pAuthFrameBody->type) + sizeof (pAuthFrameBody->length) + sizeof (pAuthFrameBody->challengeText)) - palCopyMemory( pMac->hHdd, pBody, (tANI_U8 *) &pAuthFrameBody->type, bodyLen); + + palCopyMemory( pMac->hHdd, pBody, (tANI_U8 *) &pAuthFrameBody->type, bodyLen); #if defined WLAN_FEATURE_VOWIFI_11R if ((pAuthFrameBody->authAlgoNumber == eSIR_FT_AUTH) && @@ -3382,7 +3361,7 @@ limSendAuthMgmtFrame(tpAniSirGlobal pMac, || ( psessionEntry->pePersona == VOS_P2P_CLIENT_MODE ) || ( psessionEntry->pePersona == VOS_P2P_GO_MODE) #if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR) - || ((NULL != pMac->ft.ftPEContext.pFTPreAuthReq) + || ((NULL != pMac->ft.ftPEContext.pFTPreAuthReq) && ( SIR_BAND_5_GHZ == limGetRFBand(pMac->ft.ftPEContext.pFTPreAuthReq->preAuthchannelNum))) #endif ) @@ -3404,7 +3383,7 @@ limSendAuthMgmtFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog(pMac, LOGE, - FL("*** Could not send Auth frame, retCode=%X ***\n"), + FL("*** Could not send Auth frame, retCode=%X ***"), halstatus); //Pkt will be freed up by the callback @@ -3433,7 +3412,7 @@ eHalStatus limSendDeauthCnf(tpAniSirGlobal pMac) { PELOGE(limLog(pMac, LOGE, - FL("session does not exist for given sessionId\n"));) + FL("session does not exist for given sessionId"));) mlmDeauthCnf.resultCode = eSIR_SME_INVALID_PARAMETERS; goto end; } @@ -3491,7 +3470,7 @@ eHalStatus limSendDisassocCnf(tpAniSirGlobal pMac) { PELOGE(limLog(pMac, LOGE, - FL("session does not exist for given sessionId\n"));) + FL("session does not exist for given sessionId"));) mlmDisassocCnf.resultCode = eSIR_SME_INVALID_PARAMETERS; goto end; } @@ -3512,19 +3491,19 @@ eHalStatus limSendDisassocCnf(tpAniSirGlobal pMac) #ifdef WLAN_FEATURE_VOWIFI_11R if ( (psessionEntry->limSystemRole == eLIM_STA_ROLE ) && - ( + ( #ifdef FEATURE_WLAN_CCX - (psessionEntry->isCCXconnection ) || + (psessionEntry->isCCXconnection ) || #endif #ifdef FEATURE_WLAN_LFR (psessionEntry->isFastRoamIniFeatureEnabled ) || #endif (psessionEntry->is11Rconnection )) && - (pMlmDisassocReq->reasonCode != + (pMlmDisassocReq->reasonCode != eSIR_MAC_DISASSOC_DUE_TO_FTHANDOFF_REASON)) { - PELOGE(limLog(pMac, LOGE, - FL("FT Preauth Session (%p,%d) Cleanup\n"), + PELOGE(limLog(pMac, LOGE, + FL("FT Preauth Session (%p,%d) Cleanup"), psessionEntry, psessionEntry->peSessionId);); limFTCleanup(pMac); } @@ -3538,7 +3517,7 @@ eHalStatus limSendDisassocCnf(tpAniSirGlobal pMac) #ifdef FEATURE_WLAN_LFR " isLFR %d" #endif - " is11r %d reason %d\n"), + " is11r %d reason %d"), psessionEntry->limSystemRole, #ifdef FEATURE_WLAN_CCX psessionEntry->isCCXconnection, @@ -3637,7 +3616,7 @@ limSendDisassocMgmtFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGP, FL("Failed to calculate the packed size f" - "or a Disassociation (0x%08x).\n"), + "or a Disassociation (0x%08x)."), nStatus ); // We'll fall back on the worst case scenario: nPayload = sizeof( tDot11fDisassociation ); @@ -3646,7 +3625,7 @@ limSendDisassocMgmtFrame(tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL("There were warnings while calculating" "the packed size for a Disassociation " - "(0x%08x).\n"), nStatus ); + "(0x%08x)."), nStatus ); } nBytes = nPayload + sizeof( tSirMacMgmtHdr ); @@ -3657,7 +3636,7 @@ limSendDisassocMgmtFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a Dis" - "association.\n"), nBytes ); + "association."), nBytes ); return; } @@ -3670,7 +3649,7 @@ limSendDisassocMgmtFrame(tpAniSirGlobal pMac, if ( eSIR_SUCCESS != nSirStatus ) { limLog( pMac, LOGE, FL("Failed to populate the buffer descrip" - "tor for a Disassociation (%d).\n"), + "tor for a Disassociation (%d)."), nSirStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); @@ -3682,19 +3661,12 @@ limSendDisassocMgmtFrame(tpAniSirGlobal pMac, // Prepare the BSSID sirCopyMacAddr(pMacHdr->bssId,psessionEntry->bssId); -#ifdef WLAN_FEATURE_11W - if ( psessionEntry->limRmfEnabled ) - { - pMacHdr->fc.wep = 1; - } -#endif - nStatus = dot11fPackDisassociation( pMac, &frm, pFrame + sizeof(tSirMacMgmtHdr), nPayload, &nPayload ); if ( DOT11F_FAILED( nStatus ) ) { - limLog( pMac, LOGE, FL("Failed to pack a Disassociation (0x%08x).\n"), + limLog( pMac, LOGE, FL("Failed to pack a Disassociation (0x%08x)."), nStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); @@ -3703,11 +3675,11 @@ limSendDisassocMgmtFrame(tpAniSirGlobal pMac, else if ( DOT11F_WARNED( nStatus ) ) { limLog( pMac, LOGW, FL("There were warnings while packing a D" - "isassociation (0x%08x).\n") ); + "isassociation (0x%08x).") ); } PELOG1(limLog( pMac, LOG1, FL("*** Sending Disassociation frame with rea" - "son %d to\n"), nReason ); + "son %d to"), nReason ); limPrintMacAddr( pMac, pMacHdr->da, LOG1 );) if( ( SIR_BAND_5_GHZ == limGetRFBand(psessionEntry->currentOperChannel)) @@ -3741,14 +3713,14 @@ limSendDisassocMgmtFrame(tpAniSirGlobal pMac, != TX_SUCCESS) { limLog(pMac, LOGP, - FL("Unable to change Disassoc ack Timer val\n")); + FL("Unable to change Disassoc ack Timer val")); return; } else if(TX_SUCCESS != tx_timer_activate( &pMac->lim.limTimers.gLimDisassocAckTimer)) { limLog(pMac, LOGP, - FL("Unable to activate Disassoc ack Timer\n")); + FL("Unable to activate Disassoc ack Timer")); limDeactivateAndChangeTimer(pMac, eLIM_DISASSOC_ACK_TIMER); return; } @@ -3764,7 +3736,7 @@ limSendDisassocMgmtFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGE, FL("Failed to send Disassociation " - "(%X)!\n"), + "(%X)!"), nSirStatus ); //Pkt will be freed up by the callback return; @@ -3820,7 +3792,7 @@ limSendDeauthMgmtFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGP, FL("Failed to calculate the packed size f" - "or a De-Authentication (0x%08x).\n"), + "or a De-Authentication (0x%08x)."), nStatus ); // We'll fall back on the worst case scenario: nPayload = sizeof( tDot11fDeAuth ); @@ -3829,7 +3801,7 @@ limSendDeauthMgmtFrame(tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL("There were warnings while calculating" "the packed size for a De-Authentication " - "(0x%08x).\n"), nStatus ); + "(0x%08x)."), nStatus ); } nBytes = nPayload + sizeof( tSirMacMgmtHdr ); @@ -3840,7 +3812,7 @@ limSendDeauthMgmtFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a De-" - "Authentication.\n"), nBytes ); + "Authentication."), nBytes ); return; } @@ -3853,7 +3825,7 @@ limSendDeauthMgmtFrame(tpAniSirGlobal pMac, if ( eSIR_SUCCESS != nSirStatus ) { limLog( pMac, LOGE, FL("Failed to populate the buffer descrip" - "tor for a De-Authentication (%d).\n"), + "tor for a De-Authentication (%d)."), nSirStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); @@ -3865,19 +3837,12 @@ limSendDeauthMgmtFrame(tpAniSirGlobal pMac, // Prepare the BSSID sirCopyMacAddr(pMacHdr->bssId,psessionEntry->bssId); -#ifdef WLAN_FEATURE_11W - if ( psessionEntry->limRmfEnabled ) - { - pMacHdr->fc.wep = 1; - } -#endif - nStatus = dot11fPackDeAuth( pMac, &frm, pFrame + sizeof(tSirMacMgmtHdr), nPayload, &nPayload ); if ( DOT11F_FAILED( nStatus ) ) { - limLog( pMac, LOGE, FL("Failed to pack a DeAuthentication (0x%08x).\n"), + limLog( pMac, LOGE, FL("Failed to pack a DeAuthentication (0x%08x)."), nStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); @@ -3886,11 +3851,11 @@ limSendDeauthMgmtFrame(tpAniSirGlobal pMac, else if ( DOT11F_WARNED( nStatus ) ) { limLog( pMac, LOGW, FL("There were warnings while packing a D" - "e-Authentication (0x%08x).\n") ); + "e-Authentication (0x%08x).") ); } PELOG1(limLog( pMac, LOG1, FL("*** Sending De-Authentication frame with rea" - "son %d to\n"), nReason ); + "son %d to"), nReason ); limPrintMacAddr( pMac, pMacHdr->da, LOG1 );) if( ( SIR_BAND_5_GHZ == limGetRFBand(psessionEntry->currentOperChannel)) @@ -3922,7 +3887,7 @@ limSendDeauthMgmtFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGE, FL("Failed to send De-Authentication " - "(%X)!\n"), + "(%X)!"), nSirStatus ); //Pkt will be freed up by the callback limTxComplete @@ -3940,14 +3905,14 @@ limSendDeauthMgmtFrame(tpAniSirGlobal pMac, != TX_SUCCESS) { limLog(pMac, LOGP, - FL("Unable to change Deauth ack Timer val\n")); + FL("Unable to change Deauth ack Timer val")); return; } else if(TX_SUCCESS != tx_timer_activate( &pMac->lim.limTimers.gLimDeauthAckTimer)) { limLog(pMac, LOGP, - FL("Unable to activate Deauth ack Timer\n")); + FL("Unable to activate Deauth ack Timer")); limDeactivateAndChangeTimer(pMac, eLIM_DEAUTH_ACK_TIMER); return; } @@ -3979,7 +3944,7 @@ limSendDeauthMgmtFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGE, FL("Failed to send De-Authentication " - "(%X)!\n"), + "(%X)!"), nSirStatus ); //Pkt will be freed up by the callback return; @@ -4041,7 +4006,7 @@ limSendMeasReportFrame(tpAniSirGlobal pMac, break; default: limLog( pMac, LOGE, FL("Unknown measurement type %d in limSen" - "dMeasReportFrame.\n"), + "dMeasReportFrame."), pMeasReqFrame->measReqIE.measType ); return eSIR_FAILURE; } @@ -4052,7 +4017,7 @@ limSendMeasReportFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGP, FL("Failed to calculate the packed size f" - "or a Measurement Report (0x%08x).\n"), + "or a Measurement Report (0x%08x)."), nStatus ); // We'll fall back on the worst case scenario: nPayload = sizeof( tDot11fMeasurementReport ); @@ -4061,7 +4026,7 @@ limSendMeasReportFrame(tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL("There were warnings while calculating" "the packed size for a Measurement Rep" - "ort (0x%08x).\n"), nStatus ); + "ort (0x%08x)."), nStatus ); } nBytes = nPayload + sizeof( tSirMacMgmtHdr ); @@ -4070,7 +4035,7 @@ limSendMeasReportFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a De-" - "Authentication.\n"), nBytes ); + "Authentication."), nBytes ); return eSIR_FAILURE; } @@ -4083,7 +4048,7 @@ limSendMeasReportFrame(tpAniSirGlobal pMac, if ( eSIR_SUCCESS != nSirStatus ) { limLog( pMac, LOGE, FL("Failed to populate the buffer descrip" - "tor for a Measurement Report (%d).\n"), + "tor for a Measurement Report (%d)."), nSirStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return eSIR_FAILURE; // just allocated... @@ -4096,25 +4061,18 @@ limSendMeasReportFrame(tpAniSirGlobal pMac, if ( eSIR_SUCCESS != nSirStatus ) { limLog( pMac, LOGE, FL("Failed to retrieve WNI_CFG_BSSID from" - " CFG (%d).\n"), + " CFG (%d)."), nSirStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return eSIR_FAILURE; // just allocated... } -#ifdef WLAN_FEATURE_11W - if ( psessionEntry->limRmfEnabled ) - { - pMacHdr->fc.wep = 1; - } -#endif - nStatus = dot11fPackMeasurementReport( pMac, &frm, pFrame + sizeof(tSirMacMgmtHdr), nPayload, &nPayload ); if ( DOT11F_FAILED( nStatus ) ) { - limLog( pMac, LOGE, FL("Failed to pack a Measurement Report (0x%08x).\n"), + limLog( pMac, LOGE, FL("Failed to pack a Measurement Report (0x%08x)."), nStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return eSIR_FAILURE; // allocated! @@ -4122,7 +4080,7 @@ limSendMeasReportFrame(tpAniSirGlobal pMac, else if ( DOT11F_WARNED( nStatus ) ) { limLog( pMac, LOGW, FL("There were warnings while packing a M" - "easurement Report (0x%08x).\n") ); + "easurement Report (0x%08x).") ); } halstatus = halTxFrame( pMac, pPacket, ( tANI_U16 ) nBytes, @@ -4133,7 +4091,7 @@ limSendMeasReportFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGE, FL("Failed to send a Measurement Report " - "(%X)!\n"), + "(%X)!"), nSirStatus ); //Pkt will be freed up by the callback return eSIR_FAILURE; // just allocated... @@ -4178,7 +4136,7 @@ limSendTpcRequestFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGP, FL("Failed to calculate the packed size f" - "or a TPC Request (0x%08x).\n"), + "or a TPC Request (0x%08x)."), nStatus ); // We'll fall back on the worst case scenario: nPayload = sizeof( tDot11fTPCRequest ); @@ -4187,7 +4145,7 @@ limSendTpcRequestFrame(tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL("There were warnings while calculating" "the packed size for a TPC Request (0x" - "%08x).\n"), nStatus ); + "%08x)."), nStatus ); } nBytes = nPayload + sizeof( tSirMacMgmtHdr ); @@ -4196,7 +4154,7 @@ limSendTpcRequestFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a TPC" - " Request.\n"), nBytes ); + " Request."), nBytes ); return; } @@ -4209,7 +4167,7 @@ limSendTpcRequestFrame(tpAniSirGlobal pMac, if ( eSIR_SUCCESS != nSirStatus ) { limLog( pMac, LOGE, FL("Failed to populate the buffer descrip" - "tor for a TPC Request (%d).\n"), + "tor for a TPC Request (%d)."), nSirStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return; // just allocated... @@ -4222,25 +4180,18 @@ limSendTpcRequestFrame(tpAniSirGlobal pMac, if ( eSIR_SUCCESS != nSirStatus ) { limLog( pMac, LOGE, FL("Failed to retrieve WNI_CFG_BSSID from" - " CFG (%d).\n"), + " CFG (%d)."), nSirStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return; // just allocated... } -#ifdef WLAN_FEATURE_11W - if ( psessionEntry->limRmfEnabled ) - { - pMacHdr->fc.wep = 1; - } -#endif - nStatus = dot11fPackTPCRequest( pMac, &frm, pFrame + sizeof(tSirMacMgmtHdr), nPayload, &nPayload ); if ( DOT11F_FAILED( nStatus ) ) { - limLog( pMac, LOGE, FL("Failed to pack a TPC Request (0x%08x).\n"), + limLog( pMac, LOGE, FL("Failed to pack a TPC Request (0x%08x)."), nStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return; // allocated! @@ -4248,7 +4199,7 @@ limSendTpcRequestFrame(tpAniSirGlobal pMac, else if ( DOT11F_WARNED( nStatus ) ) { limLog( pMac, LOGW, FL("There were warnings while packing a T" - "PC Request (0x%08x).\n") ); + "PC Request (0x%08x).") ); } halstatus = halTxFrame( pMac, pPacket, ( tANI_U16 ) nBytes, @@ -4259,7 +4210,7 @@ limSendTpcRequestFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGE, FL("Failed to send a TPC Request " - "(%X)!\n"), + "(%X)!"), nSirStatus ); //Pkt will be freed up by the callback return; @@ -4312,7 +4263,7 @@ limSendTpcReportFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGP, FL("Failed to calculate the packed size f" - "or a TPC Report (0x%08x).\n"), + "or a TPC Report (0x%08x)."), nStatus ); // We'll fall back on the worst case scenario: nPayload = sizeof( tDot11fTPCReport ); @@ -4321,7 +4272,7 @@ limSendTpcReportFrame(tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL("There were warnings while calculating" "the packed size for a TPC Report (0x" - "%08x).\n"), nStatus ); + "%08x)."), nStatus ); } nBytes = nPayload + sizeof( tSirMacMgmtHdr ); @@ -4330,7 +4281,7 @@ limSendTpcReportFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a TPC" - " Report.\n"), nBytes ); + " Report."), nBytes ); return eSIR_FAILURE; } @@ -4343,7 +4294,7 @@ limSendTpcReportFrame(tpAniSirGlobal pMac, if ( eSIR_SUCCESS != nSirStatus ) { limLog( pMac, LOGE, FL("Failed to populate the buffer descrip" - "tor for a TPC Report (%d).\n"), + "tor for a TPC Report (%d)."), nSirStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return eSIR_FAILURE; // just allocated... @@ -4356,25 +4307,18 @@ limSendTpcReportFrame(tpAniSirGlobal pMac, if ( eSIR_SUCCESS != nSirStatus ) { limLog( pMac, LOGE, FL("Failed to retrieve WNI_CFG_BSSID from" - " CFG (%d).\n"), + " CFG (%d)."), nSirStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return eSIR_FAILURE; // just allocated... } -#ifdef WLAN_FEATURE_11W - if ( psessionEntry->limRmfEnabled ) - { - pMacHdr->fc.wep = 1; - } -#endif - nStatus = dot11fPackTPCReport( pMac, &frm, pFrame + sizeof(tSirMacMgmtHdr), nPayload, &nPayload ); if ( DOT11F_FAILED( nStatus ) ) { - limLog( pMac, LOGE, FL("Failed to pack a TPC Report (0x%08x).\n"), + limLog( pMac, LOGE, FL("Failed to pack a TPC Report (0x%08x)."), nStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return eSIR_FAILURE; // allocated! @@ -4382,7 +4326,7 @@ limSendTpcReportFrame(tpAniSirGlobal pMac, else if ( DOT11F_WARNED( nStatus ) ) { limLog( pMac, LOGW, FL("There were warnings while packing a T" - "PC Report (0x%08x).\n") ); + "PC Report (0x%08x).") ); } @@ -4394,7 +4338,7 @@ limSendTpcReportFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGE, FL("Failed to send a TPC Report " - "(%X)!\n"), + "(%X)!"), nSirStatus ); //Pkt will be freed up by the callback return eSIR_FAILURE; // just allocated... @@ -4455,7 +4399,7 @@ limSendChannelSwitchMgmtFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGP, FL("Failed to calculate the packed size f" - "or a Channel Switch (0x%08x).\n"), + "or a Channel Switch (0x%08x)."), nStatus ); // We'll fall back on the worst case scenario: nPayload = sizeof( tDot11fChannelSwitch ); @@ -4464,7 +4408,7 @@ limSendChannelSwitchMgmtFrame(tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL("There were warnings while calculating" "the packed size for a Channel Switch (0x" - "%08x).\n"), nStatus ); + "%08x)."), nStatus ); } nBytes = nPayload + sizeof( tSirMacMgmtHdr ); @@ -4473,7 +4417,7 @@ limSendChannelSwitchMgmtFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a TPC" - " Report.\n"), nBytes ); + " Report."), nBytes ); return eSIR_FAILURE; } @@ -4491,7 +4435,7 @@ limSendChannelSwitchMgmtFrame(tpAniSirGlobal pMac, if ( eSIR_SUCCESS != nSirStatus ) { limLog( pMac, LOGE, FL("Failed to populate the buffer descrip" - "tor for a Channel Switch (%d).\n"), + "tor for a Channel Switch (%d)."), nSirStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return eSIR_FAILURE; // just allocated... @@ -4505,26 +4449,18 @@ limSendChannelSwitchMgmtFrame(tpAniSirGlobal pMac, if ( eSIR_SUCCESS != nSirStatus ) { limLog( pMac, LOGE, FL("Failed to retrieve WNI_CFG_BSSID from" - " CFG (%d).\n"), + " CFG (%d)."), nSirStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return eSIR_FAILURE; // just allocated... } #endif - -#ifdef WLAN_FEATURE_11W - if ( psessionEntry->limRmfEnabled ) - { - pMacHdr->fc.wep = 1; - } -#endif - nStatus = dot11fPackChannelSwitch( pMac, &frm, pFrame + sizeof(tSirMacMgmtHdr), nPayload, &nPayload ); if ( DOT11F_FAILED( nStatus ) ) { - limLog( pMac, LOGE, FL("Failed to pack a Channel Switch (0x%08x).\n"), + limLog( pMac, LOGE, FL("Failed to pack a Channel Switch (0x%08x)."), nStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return eSIR_FAILURE; // allocated! @@ -4532,7 +4468,7 @@ limSendChannelSwitchMgmtFrame(tpAniSirGlobal pMac, else if ( DOT11F_WARNED( nStatus ) ) { limLog( pMac, LOGW, FL("There were warnings while packing a C" - "hannel Switch (0x%08x).\n") ); + "hannel Switch (0x%08x).") ); } if( ( SIR_BAND_5_GHZ == limGetRFBand(psessionEntry->currentOperChannel)) @@ -4550,7 +4486,7 @@ limSendChannelSwitchMgmtFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGE, FL("Failed to send a Channel Switch " - "(%X)!\n"), + "(%X)!"), nSirStatus ); //Pkt will be freed up by the callback return eSIR_FAILURE; @@ -4590,7 +4526,7 @@ limSendVHTOpmodeNotificationFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGP, FL("Failed to calculate the packed size f" - "or a Operating Mode (0x%08x).\n"), + "or a Operating Mode (0x%08x)."), nStatus ); // We'll fall back on the worst case scenario: nPayload = sizeof( tDot11fOperatingMode); @@ -4599,7 +4535,7 @@ limSendVHTOpmodeNotificationFrame(tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL("There were warnings while calculating" "the packed size for a Operating Mode (0x" - "%08x).\n"), nStatus ); + "%08x)."), nStatus ); } nBytes = nPayload + sizeof( tSirMacMgmtHdr ); @@ -4608,7 +4544,7 @@ limSendVHTOpmodeNotificationFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a Operating Mode" - " Report.\n"), nBytes ); + " Report."), nBytes ); return eSIR_FAILURE; } @@ -4631,7 +4567,7 @@ limSendVHTOpmodeNotificationFrame(tpAniSirGlobal pMac, if ( eSIR_SUCCESS != nSirStatus ) { limLog( pMac, LOGE, FL("Failed to populate the buffer descrip" - "tor for a Operating Mode (%d).\n"), + "tor for a Operating Mode (%d)."), nSirStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return eSIR_FAILURE; // just allocated... @@ -4641,7 +4577,7 @@ limSendVHTOpmodeNotificationFrame(tpAniSirGlobal pMac, nPayload, &nPayload ); if ( DOT11F_FAILED( nStatus ) ) { - limLog( pMac, LOGE, FL("Failed to pack a Operating Mode (0x%08x).\n"), + limLog( pMac, LOGE, FL("Failed to pack a Operating Mode (0x%08x)."), nStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return eSIR_FAILURE; // allocated! @@ -4649,7 +4585,7 @@ limSendVHTOpmodeNotificationFrame(tpAniSirGlobal pMac, else if ( DOT11F_WARNED( nStatus ) ) { limLog( pMac, LOGW, FL("There were warnings while packing a Operating Mode" - " (0x%08x).\n") ); + " (0x%08x).") ); } if( ( SIR_BAND_5_GHZ == limGetRFBand(psessionEntry->currentOperChannel)) || ( psessionEntry->pePersona == VOS_P2P_CLIENT_MODE ) || @@ -4666,7 +4602,7 @@ limSendVHTOpmodeNotificationFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGE, FL("Failed to send a Channel Switch " - "(%X)!\n"), + "(%X)!"), nSirStatus ); //Pkt will be freed up by the callback return eSIR_FAILURE; @@ -4730,7 +4666,7 @@ limSendVHTChannelSwitchMgmtFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGP, FL("Failed to calculate the packed size f" - "or a Channel Switch (0x%08x).\n"), + "or a Channel Switch (0x%08x)."), nStatus ); // We'll fall back on the worst case scenario: nPayload = sizeof( tDot11fChannelSwitch ); @@ -4739,7 +4675,7 @@ limSendVHTChannelSwitchMgmtFrame(tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL("There were warnings while calculating" "the packed size for a Channel Switch (0x" - "%08x).\n"), nStatus ); + "%08x)."), nStatus ); } nBytes = nPayload + sizeof( tSirMacMgmtHdr ); @@ -4748,7 +4684,7 @@ limSendVHTChannelSwitchMgmtFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a TPC" - " Report.\n"), nBytes ); + " Report."), nBytes ); return eSIR_FAILURE; } // Paranoia: @@ -4765,7 +4701,7 @@ limSendVHTChannelSwitchMgmtFrame(tpAniSirGlobal pMac, if ( eSIR_SUCCESS != nSirStatus ) { limLog( pMac, LOGE, FL("Failed to populate the buffer descrip" - "tor for a Channel Switch (%d).\n"), + "tor for a Channel Switch (%d)."), nSirStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return eSIR_FAILURE; // just allocated... @@ -4775,7 +4711,7 @@ limSendVHTChannelSwitchMgmtFrame(tpAniSirGlobal pMac, nPayload, &nPayload ); if ( DOT11F_FAILED( nStatus ) ) { - limLog( pMac, LOGE, FL("Failed to pack a Channel Switch (0x%08x).\n"), + limLog( pMac, LOGE, FL("Failed to pack a Channel Switch (0x%08x)."), nStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return eSIR_FAILURE; // allocated! @@ -4783,7 +4719,7 @@ limSendVHTChannelSwitchMgmtFrame(tpAniSirGlobal pMac, else if ( DOT11F_WARNED( nStatus ) ) { limLog( pMac, LOGW, FL("There were warnings while packing a C" - "hannel Switch (0x%08x).\n") ); + "hannel Switch (0x%08x).") ); } if( ( SIR_BAND_5_GHZ == limGetRFBand(psessionEntry->currentOperChannel)) @@ -4801,7 +4737,7 @@ limSendVHTChannelSwitchMgmtFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGE, FL("Failed to send a Channel Switch " - "(%X)!\n"), + "(%X)!"), nSirStatus ); //Pkt will be freed up by the callback return eSIR_FAILURE; @@ -4881,7 +4817,7 @@ tSirRetStatus limSendAddBAReq( tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL( "Failed to calculate the packed size for " - "an ADDBA Request (0x%08x).\n"), + "an ADDBA Request (0x%08x)."), nStatus ); // We'll fall back on the worst case scenario: @@ -4891,7 +4827,7 @@ tSirRetStatus limSendAddBAReq( tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL( "There were warnings while calculating" - "the packed size for an ADDBA Req (0x%08x).\n"), + "the packed size for an ADDBA Req (0x%08x)."), nStatus ); } @@ -4908,7 +4844,7 @@ tSirRetStatus limSendAddBAReq( tpAniSirGlobal pMac, { // Log error limLog( pMac, LOGP, - FL("palPktAlloc FAILED! Length [%d], Status [%d]\n"), + FL("palPktAlloc FAILED! Length [%d], Status [%d]"), frameLen, halStatus ); @@ -4939,7 +4875,7 @@ tSirRetStatus limSendAddBAReq( tpAniSirGlobal pMac, { limLog( pMac, LOGP, FL( "Failed to retrieve WNI_CFG_BSSID while" - "sending an ACTION Frame\n" )); + "sending an ACTION Frame" )); // FIXME - Need to convert to tSirRetStatus statusCode = eSIR_FAILURE; @@ -4948,13 +4884,6 @@ tSirRetStatus limSendAddBAReq( tpAniSirGlobal pMac, #endif//TO SUPPORT BT-AMP sirCopyMacAddr(pMacHdr->bssId,psessionEntry->bssId); -#ifdef WLAN_FEATURE_11W - if ( psessionEntry->limRmfEnabled ) - { - pMacHdr->fc.wep = 1; - } -#endif - // Now, we're ready to "pack" the frames nStatus = dot11fPackAddBAReq( pMac, &frmAddBAReq, @@ -4965,7 +4894,7 @@ tSirRetStatus limSendAddBAReq( tpAniSirGlobal pMac, if( DOT11F_FAILED( nStatus )) { limLog( pMac, LOGE, - FL( "Failed to pack an ADDBA Req (0x%08x).\n" ), + FL( "Failed to pack an ADDBA Req (0x%08x)." ), nStatus ); // FIXME - Need to convert to tSirRetStatus @@ -4975,11 +4904,11 @@ tSirRetStatus limSendAddBAReq( tpAniSirGlobal pMac, else if( DOT11F_WARNED( nStatus )) { limLog( pMac, LOGW, - FL( "There were warnings while packing an ADDBA Req (0x%08x).\n" )); + FL( "There were warnings while packing an ADDBA Req (0x%08x)." )); } limLog( pMac, LOGW, - FL( "Sending an ADDBA REQ to \n" )); + FL( "Sending an ADDBA REQ to " )); limPrintMacAddr( pMac, pMlmAddBAReq->peerMacAddr, LOGW ); if( ( SIR_BAND_5_GHZ == limGetRFBand(psessionEntry->currentOperChannel)) @@ -5001,7 +4930,7 @@ tSirRetStatus limSendAddBAReq( tpAniSirGlobal pMac, pAddBAReqBuffer, txFlag ))) { limLog( pMac, LOGE, - FL( "halTxFrame FAILED! Status [%d]\n"), + FL( "halTxFrame FAILED! Status [%d]"), halStatus ); // FIXME - Need to convert eHalStatus to tSirRetStatus @@ -5053,7 +4982,7 @@ tSirRetStatus limSendAddBARsp( tpAniSirGlobal pMac, if(NULL == psessionEntry) { - PELOGE(limLog(pMac, LOGE, FL("Session entry is NULL!!!\n"));) + PELOGE(limLog(pMac, LOGE, FL("Session entry is NULL!!!"));) return eSIR_FAILURE; } @@ -5074,6 +5003,7 @@ tSirRetStatus limSendAddBARsp( tpAniSirGlobal pMac, frmAddBARsp.AddBAParameterSet.tid = pMlmAddBARsp->baTID; frmAddBARsp.AddBAParameterSet.policy = pMlmAddBARsp->baPolicy; frmAddBARsp.AddBAParameterSet.bufferSize = pMlmAddBARsp->baBufferSize; + frmAddBARsp.AddBAParameterSet.amsduSupported = psessionEntry->amsduSupportedInBA; // BA timeout // 0 - indicates no BA timeout @@ -5085,7 +5015,7 @@ tSirRetStatus limSendAddBARsp( tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL( "Failed to calculate the packed size for " - "an ADDBA Response (0x%08x).\n"), + "an ADDBA Response (0x%08x)."), nStatus ); // We'll fall back on the worst case scenario: @@ -5095,7 +5025,7 @@ tSirRetStatus limSendAddBARsp( tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL( "There were warnings while calculating" - "the packed size for an ADDBA Rsp (0x%08x).\n"), + "the packed size for an ADDBA Rsp (0x%08x)."), nStatus ); } @@ -5112,7 +5042,7 @@ tSirRetStatus limSendAddBARsp( tpAniSirGlobal pMac, { // Log error limLog( pMac, LOGP, - FL("palPktAlloc FAILED! Length [%d], Status [%d]\n"), + FL("palPktAlloc FAILED! Length [%d], Status [%d]"), frameLen, halStatus ); @@ -5144,7 +5074,7 @@ tSirRetStatus limSendAddBARsp( tpAniSirGlobal pMac, { limLog( pMac, LOGP, FL( "Failed to retrieve WNI_CFG_BSSID while" - "sending an ACTION Frame\n" )); + "sending an ACTION Frame" )); // FIXME - Need to convert to tSirRetStatus statusCode = eSIR_FAILURE; @@ -5153,13 +5083,6 @@ tSirRetStatus limSendAddBARsp( tpAniSirGlobal pMac, #endif // TO SUPPORT BT-AMP sirCopyMacAddr(pMacHdr->bssId,psessionEntry->bssId); -#ifdef WLAN_FEATURE_11W - if ( psessionEntry->limRmfEnabled ) - { - pMacHdr->fc.wep = 1; - } -#endif - // Now, we're ready to "pack" the frames nStatus = dot11fPackAddBARsp( pMac, &frmAddBARsp, @@ -5170,7 +5093,7 @@ tSirRetStatus limSendAddBARsp( tpAniSirGlobal pMac, if( DOT11F_FAILED( nStatus )) { limLog( pMac, LOGE, - FL( "Failed to pack an ADDBA Rsp (0x%08x).\n" ), + FL( "Failed to pack an ADDBA Rsp (0x%08x)." ), nStatus ); // FIXME - Need to convert to tSirRetStatus @@ -5180,11 +5103,11 @@ tSirRetStatus limSendAddBARsp( tpAniSirGlobal pMac, else if( DOT11F_WARNED( nStatus )) { limLog( pMac, LOGW, - FL( "There were warnings while packing an ADDBA Rsp (0x%08x).\n" )); + FL( "There were warnings while packing an ADDBA Rsp (0x%08x)." )); } limLog( pMac, LOGW, - FL( "Sending an ADDBA RSP to \n" )); + FL( "Sending an ADDBA RSP to " )); limPrintMacAddr( pMac, pMlmAddBARsp->peerMacAddr, LOGW ); if( ( SIR_BAND_5_GHZ == limGetRFBand(psessionEntry->currentOperChannel)) @@ -5206,7 +5129,7 @@ tSirRetStatus limSendAddBARsp( tpAniSirGlobal pMac, pAddBARspBuffer, txFlag ))) { limLog( pMac, LOGE, - FL( "halTxFrame FAILED! Status [%d]\n" ), + FL( "halTxFrame FAILED! Status [%d]" ), halStatus ); // FIXME - HAL error codes are different from PE error @@ -5287,7 +5210,7 @@ tSirRetStatus limSendDelBAInd( tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL( "Failed to calculate the packed size for " - "an DELBA Indication (0x%08x).\n"), + "an DELBA Indication (0x%08x)."), nStatus ); // We'll fall back on the worst case scenario: @@ -5297,7 +5220,7 @@ tSirRetStatus limSendDelBAInd( tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL( "There were warnings while calculating" - "the packed size for an DELBA Ind (0x%08x).\n"), + "the packed size for an DELBA Ind (0x%08x)."), nStatus ); } @@ -5314,7 +5237,7 @@ tSirRetStatus limSendDelBAInd( tpAniSirGlobal pMac, { // Log error limLog( pMac, LOGP, - FL("palPktAlloc FAILED! Length [%d], Status [%d]\n"), + FL("palPktAlloc FAILED! Length [%d], Status [%d]"), frameLen, halStatus ); @@ -5345,7 +5268,7 @@ tSirRetStatus limSendDelBAInd( tpAniSirGlobal pMac, { limLog( pMac, LOGP, FL( "Failed to retrieve WNI_CFG_BSSID while" - "sending an ACTION Frame\n" )); + "sending an ACTION Frame" )); // FIXME - Need to convert to tSirRetStatus statusCode = eSIR_FAILURE; @@ -5354,13 +5277,6 @@ tSirRetStatus limSendDelBAInd( tpAniSirGlobal pMac, #endif //TO SUPPORT BT-AMP sirCopyMacAddr(pMacHdr->bssId,psessionEntry->bssId); -#ifdef WLAN_FEATURE_11W - if ( psessionEntry->limRmfEnabled ) - { - pMacHdr->fc.wep = 1; - } -#endif - // Now, we're ready to "pack" the frames nStatus = dot11fPackDelBAInd( pMac, &frmDelBAInd, @@ -5371,7 +5287,7 @@ tSirRetStatus limSendDelBAInd( tpAniSirGlobal pMac, if( DOT11F_FAILED( nStatus )) { limLog( pMac, LOGE, - FL( "Failed to pack an DELBA Ind (0x%08x).\n" ), + FL( "Failed to pack an DELBA Ind (0x%08x)." ), nStatus ); // FIXME - Need to convert to tSirRetStatus @@ -5381,11 +5297,11 @@ tSirRetStatus limSendDelBAInd( tpAniSirGlobal pMac, else if( DOT11F_WARNED( nStatus )) { limLog( pMac, LOGW, - FL( "There were warnings while packing an DELBA Ind (0x%08x).\n" )); + FL( "There were warnings while packing an DELBA Ind (0x%08x)." )); } limLog( pMac, LOGW, - FL( "Sending a DELBA IND to \n" )); + FL( "Sending a DELBA IND to " )); limPrintMacAddr( pMac, pMlmDelBAReq->peerMacAddr, LOGW ); if( ( SIR_BAND_5_GHZ == limGetRFBand(psessionEntry->currentOperChannel)) @@ -5406,7 +5322,7 @@ tSirRetStatus limSendDelBAInd( tpAniSirGlobal pMac, limTxComplete, pDelBAIndBuffer, txFlag ))) { - PELOGE(limLog( pMac, LOGE, FL( "halTxFrame FAILED! Status [%d]\n" ), halStatus );) + PELOGE(limLog( pMac, LOGE, FL( "halTxFrame FAILED! Status [%d]" ), halStatus );) statusCode = eSIR_FAILURE; //Pkt will be freed up by the callback return statusCode; @@ -5463,7 +5379,7 @@ limSendNeighborReportRequestFrame(tpAniSirGlobal pMac, if ( psessionEntry == NULL ) { - limLog( pMac, LOGE, FL("(psession == NULL) in Request to send Neighbor Report request action frame\n") ); + limLog( pMac, LOGE, FL("(psession == NULL) in Request to send Neighbor Report request action frame") ); return eSIR_FAILURE; } palZeroMemory( pMac->hHdd, ( tANI_U8* )&frm, sizeof( frm ) ); @@ -5482,7 +5398,7 @@ limSendNeighborReportRequestFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGP, FL("Failed to calculate the packed size f" - "or a Neighbor Report Request(0x%08x).\n"), + "or a Neighbor Report Request(0x%08x)."), nStatus ); // We'll fall back on the worst case scenario: nPayload = sizeof( tDot11fNeighborReportRequest ); @@ -5491,7 +5407,7 @@ limSendNeighborReportRequestFrame(tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL("There were warnings while calculating" "the packed size for a Neighbor Rep" - "ort Request(0x%08x).\n"), nStatus ); + "ort Request(0x%08x)."), nStatus ); } nBytes = nPayload + sizeof( tSirMacMgmtHdr ); @@ -5500,7 +5416,7 @@ limSendNeighborReportRequestFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a Neighbor " - "Report Request.\n"), nBytes ); + "Report Request."), nBytes ); return eSIR_FAILURE; } @@ -5521,13 +5437,6 @@ limSendNeighborReportRequestFrame(tpAniSirGlobal pMac, sirCopyMacAddr( pMacHdr->bssId, psessionEntry->bssId ); -#ifdef WLAN_FEATURE_11W - if ( psessionEntry->limRmfEnabled ) - { - pMacHdr->fc.wep = 1; - } -#endif - // Now, we're ready to "pack" the frames nStatus = dot11fPackNeighborReportRequest( pMac, &frm, @@ -5538,7 +5447,7 @@ limSendNeighborReportRequestFrame(tpAniSirGlobal pMac, if( DOT11F_FAILED( nStatus )) { limLog( pMac, LOGE, - FL( "Failed to pack an Neighbor Report Request (0x%08x).\n" ), + FL( "Failed to pack an Neighbor Report Request (0x%08x)." ), nStatus ); // FIXME - Need to convert to tSirRetStatus @@ -5548,11 +5457,11 @@ limSendNeighborReportRequestFrame(tpAniSirGlobal pMac, else if( DOT11F_WARNED( nStatus )) { limLog( pMac, LOGW, - FL( "There were warnings while packing Neighbor Report Request (0x%08x).\n" )); + FL( "There were warnings while packing Neighbor Report Request (0x%08x)." )); } limLog( pMac, LOGW, - FL( "Sending a Neighbor Report Request to \n" )); + FL( "Sending a Neighbor Report Request to " )); limPrintMacAddr( pMac, peer, LOGW ); if( ( SIR_BAND_5_GHZ == limGetRFBand(psessionEntry->currentOperChannel)) @@ -5573,7 +5482,7 @@ limSendNeighborReportRequestFrame(tpAniSirGlobal pMac, limTxComplete, pFrame, txFlag ))) { - PELOGE(limLog( pMac, LOGE, FL( "halTxFrame FAILED! Status [%d]\n" ), halstatus );) + PELOGE(limLog( pMac, LOGE, FL( "halTxFrame FAILED! Status [%d]" ), halstatus );) statusCode = eSIR_FAILURE; //Pkt will be freed up by the callback return statusCode; @@ -5623,7 +5532,7 @@ limSendLinkReportActionFrame(tpAniSirGlobal pMac, if ( psessionEntry == NULL ) { - limLog( pMac, LOGE, FL("(psession == NULL) in Request to send Link Report action frame\n") ); + limLog( pMac, LOGE, FL("(psession == NULL) in Request to send Link Report action frame") ); return eSIR_FAILURE; } @@ -5653,7 +5562,7 @@ limSendLinkReportActionFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGP, FL("Failed to calculate the packed size f" - "or a Link Report (0x%08x).\n"), + "or a Link Report (0x%08x)."), nStatus ); // We'll fall back on the worst case scenario: nPayload = sizeof( tDot11fLinkMeasurementReport ); @@ -5662,7 +5571,7 @@ limSendLinkReportActionFrame(tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL("There were warnings while calculating" "the packed size for a Link Rep" - "ort (0x%08x).\n"), nStatus ); + "ort (0x%08x)."), nStatus ); } nBytes = nPayload + sizeof( tSirMacMgmtHdr ); @@ -5671,7 +5580,7 @@ limSendLinkReportActionFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a Link " - "Report.\n"), nBytes ); + "Report."), nBytes ); return eSIR_FAILURE; } @@ -5692,13 +5601,6 @@ limSendLinkReportActionFrame(tpAniSirGlobal pMac, sirCopyMacAddr( pMacHdr->bssId, psessionEntry->bssId ); -#ifdef WLAN_FEATURE_11W - if ( psessionEntry->limRmfEnabled ) - { - pMacHdr->fc.wep = 1; - } -#endif - // Now, we're ready to "pack" the frames nStatus = dot11fPackLinkMeasurementReport( pMac, &frm, @@ -5709,7 +5611,7 @@ limSendLinkReportActionFrame(tpAniSirGlobal pMac, if( DOT11F_FAILED( nStatus )) { limLog( pMac, LOGE, - FL( "Failed to pack an Link Report (0x%08x).\n" ), + FL( "Failed to pack an Link Report (0x%08x)." ), nStatus ); // FIXME - Need to convert to tSirRetStatus @@ -5719,11 +5621,11 @@ limSendLinkReportActionFrame(tpAniSirGlobal pMac, else if( DOT11F_WARNED( nStatus )) { limLog( pMac, LOGW, - FL( "There were warnings while packing Link Report (0x%08x).\n" )); + FL( "There were warnings while packing Link Report (0x%08x)." )); } limLog( pMac, LOGW, - FL( "Sending a Link Report to \n" )); + FL( "Sending a Link Report to " )); limPrintMacAddr( pMac, peer, LOGW ); if( ( SIR_BAND_5_GHZ == limGetRFBand(psessionEntry->currentOperChannel)) @@ -5744,7 +5646,7 @@ limSendLinkReportActionFrame(tpAniSirGlobal pMac, limTxComplete, pFrame, txFlag ))) { - PELOGE(limLog( pMac, LOGE, FL( "halTxFrame FAILED! Status [%d]\n" ), halstatus );) + PELOGE(limLog( pMac, LOGE, FL( "halTxFrame FAILED! Status [%d]" ), halstatus );) statusCode = eSIR_FAILURE; //Pkt will be freed up by the callback return statusCode; @@ -5800,13 +5702,13 @@ limSendRadioMeasureReportActionFrame(tpAniSirGlobal pMac, tDot11fRadioMeasurementReport *frm = vos_mem_malloc(sizeof(tDot11fRadioMeasurementReport)); if (!frm) { - limLog( pMac, LOGE, FL("Not enough memory to allocate tDot11fRadioMeasurementReport\n") ); + limLog( pMac, LOGE, FL("Not enough memory to allocate tDot11fRadioMeasurementReport") ); return eSIR_FAILURE; } if ( psessionEntry == NULL ) { - limLog( pMac, LOGE, FL("(psession == NULL) in Request to send Beacon Report action frame\n") ); + limLog( pMac, LOGE, FL("(psession == NULL) in Request to send Beacon Report action frame") ); vos_mem_free(frm); return eSIR_FAILURE; } @@ -5843,7 +5745,7 @@ limSendRadioMeasureReportActionFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGP, FL("Failed to calculate the packed size f" - "or a Radio Measure Report (0x%08x).\n"), + "or a Radio Measure Report (0x%08x)."), nStatus ); // We'll fall back on the worst case scenario: nPayload = sizeof( tDot11fLinkMeasurementReport ); @@ -5854,7 +5756,7 @@ limSendRadioMeasureReportActionFrame(tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL("There were warnings while calculating" "the packed size for a Radio Measure Rep" - "ort (0x%08x).\n"), nStatus ); + "ort (0x%08x)."), nStatus ); } nBytes = nPayload + sizeof( tSirMacMgmtHdr ); @@ -5863,7 +5765,7 @@ limSendRadioMeasureReportActionFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a Radio Measure " - "Report.\n"), nBytes ); + "Report."), nBytes ); vos_mem_free(frm); return eSIR_FAILURE; } @@ -5885,13 +5787,6 @@ limSendRadioMeasureReportActionFrame(tpAniSirGlobal pMac, sirCopyMacAddr( pMacHdr->bssId, psessionEntry->bssId ); -#ifdef WLAN_FEATURE_11W - if ( psessionEntry->limRmfEnabled ) - { - pMacHdr->fc.wep = 1; - } -#endif - // Now, we're ready to "pack" the frames nStatus = dot11fPackRadioMeasurementReport( pMac, frm, @@ -5902,7 +5797,7 @@ limSendRadioMeasureReportActionFrame(tpAniSirGlobal pMac, if( DOT11F_FAILED( nStatus )) { limLog( pMac, LOGE, - FL( "Failed to pack an Radio Measure Report (0x%08x).\n" ), + FL( "Failed to pack an Radio Measure Report (0x%08x)." ), nStatus ); // FIXME - Need to convert to tSirRetStatus @@ -5912,11 +5807,11 @@ limSendRadioMeasureReportActionFrame(tpAniSirGlobal pMac, else if( DOT11F_WARNED( nStatus )) { limLog( pMac, LOGW, - FL( "There were warnings while packing Radio Measure Report (0x%08x).\n" )); + FL( "There were warnings while packing Radio Measure Report (0x%08x)." )); } limLog( pMac, LOGW, - FL( "Sending a Radio Measure Report to \n" )); + FL( "Sending a Radio Measure Report to " )); limPrintMacAddr( pMac, peer, LOGW ); if( ( SIR_BAND_5_GHZ == limGetRFBand(psessionEntry->currentOperChannel)) @@ -5937,7 +5832,7 @@ limSendRadioMeasureReportActionFrame(tpAniSirGlobal pMac, limTxComplete, pFrame, txFlag ))) { - PELOGE(limLog( pMac, LOGE, FL( "halTxFrame FAILED! Status [%d]\n" ), halstatus );) + PELOGE(limLog( pMac, LOGE, FL( "halTxFrame FAILED! Status [%d]" ), halstatus );) statusCode = eSIR_FAILURE; //Pkt will be freed up by the callback vos_mem_free(frm); @@ -5965,146 +5860,87 @@ limSendRadioMeasureReportActionFrame(tpAniSirGlobal pMac, * * \param pMac The global tpAniSirGlobal object * - * \param transId Transaction identifier received in SA query request action frame - * - * \param peer The Mac address of the AP to which this action frame is addressed + * \param peer The Mac address of the AP to which this action frame is +addressed * - * \param psessionEntry The PE session entry + * \param transId Transaction identifier received in SA query request action +frame * * \return eSIR_SUCCESS if setup completes successfully * eSIR_FAILURE is some problem is encountered */ -tSirRetStatus limSendSaQueryResponseFrame( tpAniSirGlobal pMac, tANI_U8 *transId, +tSirRetStatus limSendSaQueryResponseFrame( tpAniSirGlobal pMac, tANI_U16 transId, tSirMacAddr peer,tpPESession psessionEntry) { - tDot11fSaQueryRsp frm; // SA query reponse action frame + tDot11wSaQueryRsp frm; // SA query reponse action frame tANI_U8 *pFrame; tSirRetStatus nSirStatus; tpSirMacMgmtHdr pMacHdr; - tANI_U32 nBytes, nPayload, nStatus; + tANI_U32 nBytes, nPayload; void *pPacket; eHalStatus halstatus; - tANI_U8 txFlag = 0; + // Local variables used to dump prepared SA query response frame + tANI_U8 *pDump; + tANI_U16 dumpCount; + tANI_U8 txFlag = 0; + //tANI_U16 nBytes palZeroMemory( pMac->hHdd, ( tANI_U8* )&frm, sizeof( frm ) ); - frm.Category.category = SIR_MAC_ACTION_SA_QUERY; - /*11w action field is : + frm.category = SIR_MAC_ACTION_SA_QUERY; + /*11w action fiedl is : action: 0 --> SA query request action frame action: 1 --> SA query response action frame */ - frm.Action.action = SIR_MAC_SA_QUERY_RSP; - /*11w SA query response transId is same as + frm.action = 1; + /*11w Draft9.0 SA query response transId is same as SA query request transId*/ - vos_mem_copy( &frm.TransactionId.transId[0], &transId[0], 2 ); - - nStatus = dot11fGetPackedSaQueryRspSize(pMac, &frm, &nPayload); - if ( DOT11F_FAILED( nStatus ) ) - { - limLog( pMac, LOGP, FL("Failed to calculate the packed size f" - "or a SA Query Response (0x%08x)."), - nStatus ); - // We'll fall back on the worst case scenario: - nPayload = sizeof( tDot11fSaQueryRsp ); - } - else if ( DOT11F_WARNED( nStatus ) ) - { - limLog( pMac, LOGW, FL("There were warnings while calculating" - "the packed size for an SA Query Response" - " (0x%08x)."), nStatus ); - } + frm.transId = transId; + nPayload = sizeof(tDot11wSaQueryRsp); nBytes = nPayload + sizeof( tSirMacMgmtHdr ); halstatus = palPktAlloc( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, nBytes, ( void** ) &pFrame, ( void** ) &pPacket ); if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a SA query response" - " action frame\n"), nBytes ); + " action frame"), nBytes ); return eSIR_FAILURE; } // Paranoia: palZeroMemory( pMac->hHdd, pFrame, nBytes ); - // Copy necessary info to BD - nSirStatus = limPopulateMacHeader( pMac, - pFrame, - SIR_MAC_MGMT_FRAME, - SIR_MAC_MGMT_ACTION, - peer, psessionEntry->selfMacAddr ); + // Next, we fill out the buffer descriptor: + nSirStatus = limPopulateMacHeader( pMac, pFrame, SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_ACTION, peer,psessionEntry->selfMacAddr ); if ( eSIR_SUCCESS != nSirStatus ) - goto returnAfterError; - - // Update A3 with the BSSID - pMacHdr = ( tpSirMacMgmtHdr ) pFrame; - - sirCopyMacAddr( pMacHdr->bssId, psessionEntry->bssId ); - - // Since this is a SA Query Response, set the "protect" (aka WEP) bit - // in the FC - if ( psessionEntry->limRmfEnabled ) { - pMacHdr->fc.wep = 1; + limLog( pMac, LOGE, FL("Failed to populate the buffer descrip" + "tor for a TPC Report (%d).\n"), + nSirStatus ); + palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); + return eSIR_FAILURE; // just allocated... } - // Pack 11w SA query response frame - nStatus = dot11fPackSaQueryRsp( pMac, - &frm, - pFrame + sizeof( tSirMacMgmtHdr ), - nPayload, - &nPayload ); - - if ( DOT11F_FAILED( nStatus )) - { - limLog( pMac, LOGE, - FL( "Failed to pack an SA Query Response (0x%08x)." ), - nStatus ); - // FIXME - Need to convert to tSirRetStatus - nSirStatus = eSIR_FAILURE; - goto returnAfterError; - } - else if ( DOT11F_WARNED( nStatus )) - { - limLog( pMac, LOGW, - FL( "There were warnings while packing SA Query Response (0x%08x)." ), - nStatus); - } - - limLog( pMac, LOG1, - FL( "Sending a SA Query Response to " )); - limPrintMacAddr( pMac, peer, LOGW ); + pMacHdr = ( tpSirMacMgmtHdr ) pFrame; - if ( ( SIR_BAND_5_GHZ == limGetRFBand( psessionEntry->currentOperChannel ) ) -#ifdef WLAN_FEATURE_P2P - || ( psessionEntry->pePersona == VOS_P2P_CLIENT_MODE ) || - ( psessionEntry->pePersona == VOS_P2P_GO_MODE ) -#endif - ) - { - txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME; - } + // Pack 11w SA query response frame + DOT11F_MEMCPY(pMac, (tANI_U8 *)(pFrame + sizeof(tSirMacMgmtHdr)),(tANI_U8 *)&frm, nPayload); + pDump = (tANI_U8 *) pFrame; - halstatus = halTxFrame( pMac, - pPacket, - (tANI_U16) nBytes, - HAL_TXRX_FRM_802_11_MGMT, - ANI_TXDIR_TODS, - 7,//SMAC_SWBD_TX_TID_MGMT_HIGH, - limTxComplete, - pFrame, txFlag ); - if ( eHAL_STATUS_SUCCESS != halstatus ) + halstatus = halTxFrame( pMac, pPacket, ( tANI_U16 ) nBytes, + HAL_TXRX_FRM_802_11_MGMT, + ANI_TXDIR_TODS, + 7,//SMAC_SWBD_TX_TID_MGMT_HIGH, + limTxComplete, pFrame,txFlag); + if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { - PELOGE(limLog( pMac, LOGE, FL( "halTxFrame FAILED! Status [%d]" ), halstatus );) - nSirStatus = eSIR_FAILURE; - //Pkt will be freed up by the callback - return nSirStatus; - } - else { - return eSIR_SUCCESS; + limLog( pMac, LOGE, FL("Failed to send a SA Query resp frame " + "(%X)!\n"),halstatus ); + //Pkt will be freed up by the callback + return eSIR_FAILURE; // just allocated... } -returnAfterError: - palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); - return nSirStatus; -} // End limSendSaQueryResponseFrame + return eSIR_SUCCESS; +} #endif diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limSendMessages.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limSendMessages.c index 4d99aad5792..f224661513f 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limSendMessages.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limSendMessages.c @@ -74,7 +74,6 @@ static tBeaconFilterIe beaconFilterTable[] = { {SIR_MAC_EDCA_PARAM_SET_EID, 0, {0, 0, EDCA_FILTER_MASK, 0}}, {SIR_MAC_QOS_CAPABILITY_EID, 0, {0, 0, QOS_FILTER_MASK, 0}}, {SIR_MAC_CHNL_SWITCH_ANN_EID, 1, {0, 0, 0, 0}}, - {SIR_MAC_QUIET_EID, 1, {0, 0, 0, 0}}, {SIR_MAC_HT_INFO_EID, 0, {0, 0, HT_BYTE0_FILTER_MASK, 0}}, {SIR_MAC_HT_INFO_EID, 0, {2, 0, HT_BYTE2_FILTER_MASK, 0}}, {SIR_MAC_HT_INFO_EID, 0, {5, 0, HT_BYTE5_FILTER_MASK, 0}} @@ -118,7 +117,7 @@ tSirRetStatus limSendCFParams(tpAniSirGlobal pMac, tANI_U8 bssIdx, tANI_U8 cfpCo sizeof( tUpdateCFParams ))) { limLog( pMac, LOGP, - FL( "Unable to PAL allocate memory during Update CF Params\n" )); + FL( "Unable to PAL allocate memory during Update CF Params" )); retCode = eSIR_MEM_ALLOC_FAILED; goto returnFailure; } @@ -138,7 +137,7 @@ tSirRetStatus limSendCFParams(tpAniSirGlobal pMac, tANI_U8 bssIdx, tANI_U8 cfpCo { palFreeMemory(pMac->hHdd, pCFParams); limLog( pMac, LOGP, - FL("Posting WDA_UPDATE_CF_IND to WDA failed, reason=%X\n"), + FL("Posting WDA_UPDATE_CF_IND to WDA failed, reason=%X"), retCode ); } returnFailure: @@ -178,7 +177,7 @@ tSirRetStatus limSendBeaconParams(tpAniSirGlobal pMac, (void **) &pBcnParams, sizeof(*pBcnParams))) { limLog( pMac, LOGP, - FL( "Unable to PAL allocate memory during Update Beacon Params\n" )); + FL( "Unable to PAL allocate memory during Update Beacon Params" )); return eSIR_MEM_ALLOC_FAILED; } palCopyMemory( pMac->hHdd, (tANI_U8 *) pBcnParams, pUpdatedBcnParams, sizeof(*pBcnParams)); @@ -201,7 +200,7 @@ tSirRetStatus limSendBeaconParams(tpAniSirGlobal pMac, { palFreeMemory(pMac->hHdd, pBcnParams); limLog( pMac, LOGP, - FL("Posting WDA_UPDATE_BEACON_IND to WDA failed, reason=%X\n"), + FL("Posting WDA_UPDATE_BEACON_IND to WDA failed, reason=%X"), retCode ); } limSendBeaconInd(pMac, psessionEntry); @@ -248,7 +247,7 @@ tSirRetStatus limSendSwitchChnlParams(tpAniSirGlobal pMac, if((pSessionEntry = peFindSessionBySessionId(pMac , peSessionId)) == NULL) { limLog( pMac, LOGP, - FL( "Unable to get Session for session Id %d\n" ), peSessionId); + FL( "Unable to get Session for session Id %d" ), peSessionId); return eSIR_FAILURE; } if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, @@ -256,7 +255,7 @@ tSirRetStatus limSendSwitchChnlParams(tpAniSirGlobal pMac, sizeof( tSwitchChannelParams ))) { limLog( pMac, LOGP, - FL( "Unable to PAL allocate memory during Switch Channel Params\n" )); + FL( "Unable to PAL allocate memory during Switch Channel Params" )); retCode = eSIR_MEM_ALLOC_FAILED; goto returnFailure; } @@ -292,7 +291,7 @@ tSirRetStatus limSendSwitchChnlParams(tpAniSirGlobal pMac, { palFreeMemory(pMac->hHdd, pChnlParams); limLog( pMac, LOGP, - FL("Posting WDA_CHNL_SWITCH_REQ to WDA failed, reason=%X\n"), + FL("Posting WDA_CHNL_SWITCH_REQ to WDA failed, reason=%X"), retCode ); } returnFailure: @@ -330,7 +329,7 @@ tSirRetStatus limSendEdcaParams(tpAniSirGlobal pMac, tSirMacEdcaParamRecord *pUp sizeof(tEdcaParams))) { limLog( pMac, LOGP, - FL( "Unable to PAL allocate memory during Update EDCA Params\n" )); + FL( "Unable to PAL allocate memory during Update EDCA Params" )); retCode = eSIR_MEM_ALLOC_FAILED; return retCode; } @@ -349,7 +348,7 @@ tSirRetStatus limSendEdcaParams(tpAniSirGlobal pMac, tSirMacEdcaParamRecord *pUp PELOG1(limLog( pMac, LOG1,FL("Sending WDA_UPDATE_EDCA_PROFILE_IND with EDCA Parameters:" ));) for(i=0; ihHdd, pEdcaParams); limLog( pMac, LOGP, - FL("Posting WDA_UPDATE_EDCA_PROFILE_IND to WDA failed, reason=%X\n"), + FL("Posting WDA_UPDATE_EDCA_PROFILE_IND to WDA failed, reason=%X"), retCode ); } return retCode; @@ -407,12 +406,12 @@ tSirRetStatus limSendEdcaParams(tpAniSirGlobal pMac, tSirMacEdcaParamRecord *pUp * such that: BE_ACM=1, BK_ACM=1, VI_ACM=1, VO_ACM=0 * then all AC will be downgraded to AC_BE. */ - limLog(pMac, LOG1, FL("adAdmitMask[UPLINK] = 0x%x \n"), pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] ); - limLog(pMac, LOG1, FL("adAdmitMask[DOWNLINK] = 0x%x \n"), pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] ); + limLog(pMac, LOG1, FL("adAdmitMask[UPLINK] = 0x%x "), pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] ); + limLog(pMac, LOG1, FL("adAdmitMask[DOWNLINK] = 0x%x "), pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] ); for (ac = EDCA_AC_BK; ac <= EDCA_AC_VO; ac++) { acAdmitted = ( (pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] & (1 << ac)) >> ac ); - limLog(pMac, LOG1, FL("For AC[%d]: acm=%d, acAdmit=%d \n"), ac, plocalEdcaParams[ac].aci.acm, acAdmitted); + limLog(pMac, LOG1, FL("For AC[%d]: acm=%d, acAdmit=%d "), ac, plocalEdcaParams[ac].aci.acm, acAdmitted); if ( (plocalEdcaParams[ac].aci.acm == 1) && (acAdmitted == 0) ) { limLog(pMac, LOG1, FL("We need to downgrade AC %d!! "), ac); @@ -476,7 +475,7 @@ tSirRetStatus limSetLinkState(tpAniSirGlobal pMac, tSirLinkState state,tSirMacAd MTRACE(macTraceMsgTx(pMac, 0, msg.type)); retCode = wdaPostCtrlMsg(pMac, &msg); if (retCode != eSIR_SUCCESS) - limLog(pMac, LOGP, FL("Posting link state %d failed, reason = %x \n"), retCode); + limLog(pMac, LOGP, FL("Posting link state %d failed, reason = %x "), retCode); return retCode; } #endif //0 @@ -493,7 +492,7 @@ tSirRetStatus limSetLinkState(tpAniSirGlobal pMac, tSirLinkState state,tSirMacAd sizeof(tLinkStateParams))) { limLog( pMac, LOGP, - FL( "Unable to PAL allocate memory while sending Set Link State\n" )); + FL( "Unable to PAL allocate memory while sending Set Link State" )); retCode = eSIR_SME_RESOURCES_UNAVAILABLE; return retCode; } @@ -517,7 +516,7 @@ tSirRetStatus limSetLinkState(tpAniSirGlobal pMac, tSirLinkState state,tSirMacAd if (retCode != eSIR_SUCCESS) { palFreeMemory(pMac, (void*)pLinkStateParams); - limLog(pMac, LOGP, FL("Posting link state %d failed, reason = %x \n"), retCode); + limLog(pMac, LOGP, FL("Posting link state %d failed, reason = %x "), retCode); } return retCode; } @@ -534,7 +533,7 @@ state,tSirMacAddr bssId, tSirMacAddr selfMacAddr, int ft, tpPESession psessionEn sizeof(tLinkStateParams))) { limLog( pMac, LOGP, - FL( "Unable to PAL allocate memory while sending Set Link State\n" )); + FL( "Unable to PAL allocate memory while sending Set Link State" )); retCode = eSIR_SME_RESOURCES_UNAVAILABLE; return retCode; } @@ -563,7 +562,7 @@ state,tSirMacAddr bssId, tSirMacAddr selfMacAddr, int ft, tpPESession psessionEn if (retCode != eSIR_SUCCESS) { palFreeMemory(pMac, (void*)pLinkStateParams); - limLog(pMac, LOGP, FL("Posting link state %d failed, reason = %x \n"), retCode); + limLog(pMac, LOGP, FL("Posting link state %d failed, reason = %x "), retCode); } return retCode; } @@ -670,7 +669,7 @@ tSirRetStatus limSendBeaconFilterInfo(tpAniSirGlobal pMac,tpPESession psessionEn if( psessionEntry == NULL ) { - limLog( pMac, LOGE, FL("Fail to find the right session \n")); + limLog( pMac, LOGE, FL("Fail to find the right session ")); retCode = eSIR_FAILURE; return retCode; } @@ -678,7 +677,7 @@ tSirRetStatus limSendBeaconFilterInfo(tpAniSirGlobal pMac,tpPESession psessionEn if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **) &pBeaconFilterMsg, msgSize) ) { - limLog( pMac, LOGP, FL("Fail to allocate memory for beaconFiilterMsg \n")); + limLog( pMac, LOGP, FL("Fail to allocate memory for beaconFiilterMsg ")); retCode = eSIR_MEM_ALLOC_FAILED; return retCode; } @@ -717,7 +716,7 @@ tSirRetStatus limSendBeaconFilterInfo(tpAniSirGlobal pMac,tpPESession psessionEn { palFreeMemory(pMac->hHdd, pBeaconFilterMsg); limLog( pMac, LOGP, - FL("Posting WDA_BEACON_FILTER_IND to WDA failed, reason=%X\n"), + FL("Posting WDA_BEACON_FILTER_IND to WDA failed, reason=%X"), retCode ); return retCode; } @@ -737,7 +736,7 @@ tSirRetStatus limSendModeUpdate(tpAniSirGlobal pMac, (void **) &pVhtOpMode, sizeof(tUpdateVHTOpMode))) { limLog( pMac, LOGP, - FL( "Unable to PAL allocate memory during Update Op Mode\n" )); + FL( "Unable to PAL allocate memory during Update Op Mode" )); return eSIR_MEM_ALLOC_FAILED; } palCopyMemory( pMac->hHdd, (tANI_U8 *)pVhtOpMode, pTempParam, sizeof(tUpdateVHTOpMode)); @@ -759,7 +758,7 @@ tSirRetStatus limSendModeUpdate(tpAniSirGlobal pMac, { palFreeMemory(pMac->hHdd, pVhtOpMode); limLog( pMac, LOGP, - FL("Posting WDA_UPDATE_OP_MODE to WDA failed, reason=%X\n"), + FL("Posting WDA_UPDATE_OP_MODE to WDA failed, reason=%X"), retCode ); } @@ -788,7 +787,7 @@ tSirRetStatus limSendTdlsLinkEstablish(tpAniSirGlobal pMac, tANI_U8 bIsPeerRespo sizeof(tSirTdlsLinkEstablishInd))) { limLog( pMac, LOGP, - FL( "Unable to PAL allocate memory while sending Tdls Link Establish \n" )); + FL( "Unable to PAL allocate memory while sending Tdls Link Establish " )); retCode = eSIR_SME_RESOURCES_UNAVAILABLE; return retCode; @@ -816,7 +815,7 @@ tSirRetStatus limSendTdlsLinkEstablish(tpAniSirGlobal pMac, tANI_U8 bIsPeerRespo if (retCode != eSIR_SUCCESS) { palFreeMemory(pMac, (void*)pTdlsLinkEstablish); - limLog(pMac, LOGP, FL("Posting tdls link establish %d failed, reason = %x \n"), retCode); + limLog(pMac, LOGP, FL("Posting tdls link establish %d failed, reason = %x "), retCode); } return retCode; @@ -841,7 +840,7 @@ tSirRetStatus limSendTdlsLinkTeardown(tpAniSirGlobal pMac, tANI_U16 staId) sizeof(tSirTdlsLinkTeardownInd))) { limLog( pMac, LOGP, - FL( "Unable to PAL allocate memory while sending Tdls Link Teardown \n" )); + FL( "Unable to PAL allocate memory while sending Tdls Link Teardown " )); retCode = eSIR_SME_RESOURCES_UNAVAILABLE; return retCode; @@ -862,7 +861,7 @@ tSirRetStatus limSendTdlsLinkTeardown(tpAniSirGlobal pMac, tANI_U16 staId) if (retCode != eSIR_SUCCESS) { palFreeMemory(pMac, (void*)pTdlsLinkTeardown); - limLog(pMac, LOGP, FL("Posting tdls link teardown %d failed, reason = %x \n"), retCode); + limLog(pMac, LOGP, FL("Posting tdls link teardown %d failed, reason = %x "), retCode); } return retCode; @@ -870,54 +869,3 @@ tSirRetStatus limSendTdlsLinkTeardown(tpAniSirGlobal pMac, tANI_U16 staId) #endif -#ifdef WLAN_FEATURE_11W -/** --------------------------------------------------------- -\fn limSendExcludeUnencryptInd -\brief LIM sends a message to HAL to indicate whether to - ignore or indicate the unprotected packet error -\param tpAniSirGlobal pMac -\param tANI_BOOLEAN excludeUnenc - true: ignore, false: - indicate -\param tpPESession psessionEntry - session context -\return status - -----------------------------------------------------------*/ -tSirRetStatus limSendExcludeUnencryptInd(tpAniSirGlobal pMac, - tANI_BOOLEAN excludeUnenc, - tpPESession psessionEntry) -{ - tSirRetStatus retCode = eSIR_SUCCESS; - tSirMsgQ msgQ; - tSirWlanExcludeUnencryptParam * pExcludeUnencryptParam; - - if (eHAL_STATUS_SUCCESS != palAllocateMemory(pMac->hHdd, - (void **) &pExcludeUnencryptParam, - sizeof(tSirWlanExcludeUnencryptParam))) - { - limLog(pMac, LOGP, - FL( "Unable to PAL allocate memory during limSendExcludeUnencryptInd")); - return eSIR_MEM_ALLOC_FAILED; - } - - pExcludeUnencryptParam->excludeUnencrypt = excludeUnenc; - sirCopyMacAddr(pExcludeUnencryptParam->bssId, psessionEntry->bssId); - - msgQ.type = WDA_EXCLUDE_UNENCRYPTED_IND; - msgQ.reserved = 0; - msgQ.bodyptr = pExcludeUnencryptParam; - msgQ.bodyval = 0; - PELOG3(limLog(pMac, LOG3, - FL("Sending WDA_EXCLUDE_UNENCRYPTED_IND"));) - MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, msgQ.type)); - retCode = wdaPostCtrlMsg(pMac, &msgQ); - if (eSIR_SUCCESS != retCode) - { - palFreeMemory(pMac->hHdd, pExcludeUnencryptParam); - limLog(pMac, LOGP, - FL("Posting WDA_EXCLUDE_UNENCRYPTED_IND to WDA failed, reason=%X"), - retCode); - } - - return retCode; -} -#endif - diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limSendMessages.h b/drivers/staging/prima/CORE/MAC/src/pe/lim/limSendMessages.h index d2d12fac83e..7f7b0735d98 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limSendMessages.h +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limSendMessages.h @@ -109,9 +109,5 @@ tSirRetStatus limSendTdlsLinkEstablish(tpAniSirGlobal pMac, tANI_U8 bIsPeerRespo tANI_U8 ptiBufStatusOffset, tANI_U8 ptiFrameLen, tANI_U8 *ptiFrame, tANI_U8 *extCapability); tSirRetStatus limSendTdlsLinkTeardown(tpAniSirGlobal pMac, tANI_U16 staId); #endif -#ifdef WLAN_FEATURE_11W -tSirRetStatus limSendExcludeUnencryptInd(tpAniSirGlobal pMac, - tANI_BOOLEAN excludeUnenc, - tpPESession psessionEntry ); -#endif + #endif diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limSendSmeRspMessages.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limSendSmeRspMessages.c index 299375468b7..d91c595680b 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limSendSmeRspMessages.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limSendSmeRspMessages.c @@ -106,14 +106,14 @@ limSendSmeRsp(tpAniSirGlobal pMac, tANI_U16 msgType, tSirSmeRsp *pSirSmeRsp; PELOG1(limLog(pMac, LOG1, - FL("Sending message %s with reasonCode %s\n"), + FL("Sending message %s with reasonCode %s"), limMsgStr(msgType), limResultCodeStr(resultCode));) if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pSirSmeRsp, sizeof(tSirSmeRsp))) { /// Buffer not available. Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for eWNI_SME_*_RSP\n")); + FL("call to palAllocateMemory failed for eWNI_SME_*_RSP")); return; } @@ -256,7 +256,7 @@ limSendSmeJoinReassocRsp(tpAniSirGlobal pMac, tANI_U16 msgType, #endif //FEATURE_WLAN_DIAG_SUPPORT PELOG1(limLog(pMac, LOG1, - FL("Sending message %s with reasonCode %s\n"), + FL("Sending message %s with reasonCode %s"), limMsgStr(msgType), limResultCodeStr(resultCode));) if(psessionEntry == NULL) @@ -267,7 +267,7 @@ limSendSmeJoinReassocRsp(tpAniSirGlobal pMac, tANI_U16 msgType, if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pSirSmeJoinRsp, rspLen)) { /// Buffer not available. Log error - limLog(pMac, LOGP, FL("call to palAllocateMemory failed for JOIN/REASSOC_RSP\n")); + limLog(pMac, LOGP, FL("call to palAllocateMemory failed for JOIN/REASSOC_RSP")); return; } @@ -295,7 +295,7 @@ limSendSmeJoinReassocRsp(tpAniSirGlobal pMac, tANI_U16 msgType, { /// Buffer not available. Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for JOIN/REASSOC_RSP\n")); + FL("call to palAllocateMemory failed for JOIN/REASSOC_RSP")); return; } @@ -307,7 +307,7 @@ limSendSmeJoinReassocRsp(tpAniSirGlobal pMac, tANI_U16 msgType, pStaDs = dphGetHashEntry(pMac, DPH_STA_HASH_INDEX_PEER, &psessionEntry->dph.dphHashTable); if (pStaDs == NULL) { - PELOGE(limLog(pMac, LOGE, FL("could not Get Self Entry for the station\n"));) + PELOGE(limLog(pMac, LOGE, FL("could not Get Self Entry for the station"));) } else { @@ -338,7 +338,7 @@ limSendSmeJoinReassocRsp(tpAniSirGlobal pMac, tANI_U16 msgType, palFreeMemory(pMac->hHdd, psessionEntry->beacon); psessionEntry->beacon = NULL; #ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG - PELOG1(limLog(pMac, LOG1, FL("Beacon=%d\n"), psessionEntry->bcnLen);) + PELOG1(limLog(pMac, LOG1, FL("Beacon=%d"), psessionEntry->bcnLen);) #endif } @@ -349,7 +349,7 @@ limSendSmeJoinReassocRsp(tpAniSirGlobal pMac, tANI_U16 msgType, palFreeMemory(pMac->hHdd, psessionEntry->assocReq); psessionEntry->assocReq = NULL; #ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG - PELOG1(limLog(pMac, LOG1, FL("AssocReq=%d\n"), psessionEntry->assocReqLen);) + PELOG1(limLog(pMac, LOG1, FL("AssocReq=%d"), psessionEntry->assocReqLen);) #endif } if(psessionEntry->assocRsp != NULL) @@ -366,7 +366,7 @@ limSendSmeJoinReassocRsp(tpAniSirGlobal pMac, tANI_U16 msgType, palCopyMemory(pMac->hHdd, pSirSmeJoinRsp->frames + psessionEntry->bcnLen + psessionEntry->assocReqLen + psessionEntry->assocRspLen, psessionEntry->ricData, pSirSmeJoinRsp->parsedRicRspLen); palFreeMemory(pMac->hHdd, psessionEntry->ricData); psessionEntry->ricData = NULL; - PELOG1(limLog(pMac, LOG1, FL("RicLength=%d\n"), pSirSmeJoinRsp->parsedRicRspLen);) + PELOG1(limLog(pMac, LOG1, FL("RicLength=%d"), pSirSmeJoinRsp->parsedRicRspLen);) } #endif #ifdef FEATURE_WLAN_CCX @@ -376,12 +376,12 @@ limSendSmeJoinReassocRsp(tpAniSirGlobal pMac, tANI_U16 msgType, palCopyMemory(pMac->hHdd, pSirSmeJoinRsp->frames + psessionEntry->bcnLen + psessionEntry->assocReqLen + psessionEntry->assocRspLen + psessionEntry->RICDataLen, psessionEntry->tspecIes, pSirSmeJoinRsp->tspecIeLen); palFreeMemory(pMac->hHdd, psessionEntry->tspecIes); psessionEntry->tspecIes = NULL; - PELOG1(limLog(pMac, LOG1, FL("CCX-TspecLen=%d\n"), psessionEntry->tspecLen);) + PELOG1(limLog(pMac, LOG1, FL("CCX-TspecLen=%d"), psessionEntry->tspecLen);) } #endif pSirSmeJoinRsp->aid = psessionEntry->limAID; #ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG - PELOG1(limLog(pMac, LOG1, FL("AssocRsp=%d\n"), psessionEntry->assocRspLen);) + PELOG1(limLog(pMac, LOG1, FL("AssocRsp=%d"), psessionEntry->assocRspLen);) #endif } else @@ -493,7 +493,7 @@ limSendSmeStartBssRsp(tpAniSirGlobal pMac, tANI_U16 ieLen; tANI_U16 ieOffset, curLen; - PELOG1(limLog(pMac, LOG1, FL("Sending message %s with reasonCode %s\n"), + PELOG1(limLog(pMac, LOG1, FL("Sending message %s with reasonCode %s"), limMsgStr(msgType), limResultCodeStr(resultCode));) size = sizeof(tSirSmeStartBssRsp); @@ -504,7 +504,7 @@ limSendSmeStartBssRsp(tpAniSirGlobal pMac, if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pSirSmeRsp, size)) { /// Buffer not available. Log error - limLog(pMac, LOGP,FL("call to palAllocateMemory failed for eWNI_SME_START_BSS_RSP\n")); + limLog(pMac, LOGP,FL("call to palAllocateMemory failed for eWNI_SME_START_BSS_RSP")); return; } palZeroMemory(pMac, (tANI_U8*)pSirSmeRsp, size); @@ -522,7 +522,7 @@ limSendSmeStartBssRsp(tpAniSirGlobal pMac, { /// Buffer not available. Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for eWNI_SME_START_BSS_RSP\n")); + FL("call to palAllocateMemory failed for eWNI_SME_START_BSS_RSP")); return; } @@ -539,13 +539,13 @@ limSendSmeStartBssRsp(tpAniSirGlobal pMac, if (cfgGetCapabilityInfo( pMac, &pSirSmeRsp->bssDescription.capabilityInfo,psessionEntry) != eSIR_SUCCESS) - limLog(pMac, LOGP, FL("could not retrieve Capabilities value\n")); + limLog(pMac, LOGP, FL("could not retrieve Capabilities value")); limGetPhyMode(pMac, (tANI_U32 *)&pSirSmeRsp->bssDescription.nwType, psessionEntry); #if 0 if (wlan_cfgGetInt(pMac, WNI_CFG_CURRENT_CHANNEL, &len) != eSIR_SUCCESS) - limLog(pMac, LOGP, FL("could not retrieve CURRENT_CHANNEL from CFG\n")); + limLog(pMac, LOGP, FL("could not retrieve CURRENT_CHANNEL from CFG")); #endif// TO SUPPORT BT-AMP @@ -652,7 +652,7 @@ limSendSmeScanRsp(tpAniSirGlobal pMac, tANI_U16 length, tSirBssDescription *pDesc; PELOG1(limLog(pMac, LOG1, - FL("Sending message SME_SCAN_RSP with length=%d reasonCode %s\n"), + FL("Sending message SME_SCAN_RSP with length=%d reasonCode %s"), length, limResultCodeStr(resultCode));) if (resultCode != eSIR_SME_SUCCESS) @@ -670,7 +670,7 @@ limSendSmeScanRsp(tpAniSirGlobal pMac, tANI_U16 length, { // Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for eWNI_SME_SCAN_RSP\n")); + FL("call to palAllocateMemory failed for eWNI_SME_SCAN_RSP")); return; } @@ -710,7 +710,7 @@ limSendSmeScanRsp(tpAniSirGlobal pMac, tANI_U16 length, { // Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for eWNI_SME_SCAN_RSP\n")); + FL("call to palAllocateMemory failed for eWNI_SME_SCAN_RSP")); return; } msgLen = sizeof(tSirSmeScanRsp) - @@ -722,7 +722,7 @@ limSendSmeScanRsp(tpAniSirGlobal pMac, tANI_U16 length, } curMsgLen = msgLen; - PELOG2(limLog(pMac, LOG2, FL("ScanRsp : msgLen %d, bssDescr Len=%d\n"), + PELOG2(limLog(pMac, LOG2, FL("ScanRsp : msgLen %d, bssDescr Len=%d"), msgLen, ptemp->bssDescription.length);) pDesc->length = ptemp->bssDescription.length; @@ -765,13 +765,176 @@ limSendSmeScanRsp(tpAniSirGlobal pMac, tANI_U16 length, mmhMsg.bodyval = 0; MTRACE(macTraceMsgTx(pMac, NO_SESSION, mmhMsg.type)); limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); - PELOG2(limLog(pMac, LOG2, FL("statusCode : eSIR_SME_SUCCESS\n"));) + PELOG2(limLog(pMac, LOG2, FL("statusCode : eSIR_SME_SUCCESS"));) } return; } /*** end limSendSmeScanRsp() ***/ +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +/** + * limSendSmeLfrScanRsp() + * + *FUNCTION: + * This function is called by limProcessSmeReqMessages() to send + * eWNI_SME_SCAN_RSP message to applications above MAC Software + * only for sending up the roam candidates. + * + *PARAMS: + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac Pointer to Global MAC structure + * @param length Indicates length of message + * @param resultCode Indicates the result of previously issued + * eWNI_SME_SCAN_REQ message + * + * @return None + */ + +void +limSendSmeLfrScanRsp(tpAniSirGlobal pMac, tANI_U16 length, + tSirResultCodes resultCode,tANI_U8 smesessionId,tANI_U16 smetranscationId) +{ + tSirMsgQ mmhMsg; + tpSirSmeScanRsp pSirSmeScanRsp=NULL; + tLimScanResultNode *ptemp = NULL; + tANI_U16 msgLen, allocLength, curMsgLen = 0; + tANI_U16 i, bssCount; + tANI_U8 *pbBuf; + tSirBssDescription *pDesc; + + PELOG1(limLog(pMac, LOG1, + FL("Sending message SME_SCAN_RSP with length=%d reasonCode %s\n"), + length, limResultCodeStr(resultCode));) + + if (resultCode != eSIR_SME_SUCCESS) + { + limPostSmeScanRspMessage(pMac, length, resultCode,smesessionId,smetranscationId); + return; + } + + mmhMsg.type = eWNI_SME_SCAN_RSP; + i = 0; + bssCount = 0; + msgLen = 0; + allocLength = LIM_MAX_NUM_OF_SCAN_RESULTS_REPORTED * LIM_SIZE_OF_EACH_BSS; + if ( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, + (void **)&pSirSmeScanRsp, allocLength)) + { + // Log error + limLog(pMac, LOGP, + FL("call to palAllocateMemory failed for eWNI_SME_SCAN_RSP\n")); + + return; + } + for (i = 0; i < LIM_MAX_NUM_OF_SCAN_RESULTS; i++) + { + //when ptemp is not NULL it is a left over + ptemp = pMac->lim.gLimCachedLfrScanHashTable[i]; + while(ptemp) + { + pbBuf = ((tANI_U8 *)pSirSmeScanRsp) + msgLen; + if(0 == bssCount) + { + msgLen = sizeof(tSirSmeScanRsp) - + sizeof(tSirBssDescription) + + ptemp->bssDescription.length + + sizeof(ptemp->bssDescription.length); + pDesc = pSirSmeScanRsp->bssDescription; + } + else + { + msgLen += ptemp->bssDescription.length + + sizeof(ptemp->bssDescription.length); + pDesc = (tSirBssDescription *)pbBuf; + } + if ( (allocLength < msgLen) || + (LIM_MAX_NUM_OF_SCAN_RESULTS_REPORTED <= bssCount++) ) + { + pSirSmeScanRsp->statusCode = + eSIR_SME_MORE_SCAN_RESULTS_FOLLOW; + pSirSmeScanRsp->messageType = eWNI_SME_SCAN_RSP; + pSirSmeScanRsp->length = curMsgLen; + mmhMsg.bodyptr = pSirSmeScanRsp; + mmhMsg.bodyval = 0; + MTRACE(macTraceMsgTx(pMac, NO_SESSION, mmhMsg.type)); + limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); + if (eHAL_STATUS_SUCCESS != palAllocateMemory(pMac->hHdd, + (void **)&pSirSmeScanRsp, + allocLength)) + { + // Log error + limLog(pMac, LOGP, + FL("call to palAllocateMemory failed for eWNI_SME_SCAN_RSP\n")); + return; + } + msgLen = sizeof(tSirSmeScanRsp) - + sizeof(tSirBssDescription) + + ptemp->bssDescription.length + + sizeof(ptemp->bssDescription.length); + pDesc = pSirSmeScanRsp->bssDescription; + bssCount = 1; + } + curMsgLen = msgLen; + + PELOG2(limLog(pMac, LOG2, FL("ScanRsp : msgLen %d, bssDescr Len=%d\n"), + msgLen, ptemp->bssDescription.length);) + pDesc->length + = ptemp->bssDescription.length; + palCopyMemory( pMac->hHdd, (tANI_U8 *) &pDesc->bssId, + (tANI_U8 *) &ptemp->bssDescription.bssId, + ptemp->bssDescription.length); + + PELOG2(limLog(pMac, LOG2, FL("BssId ")); + limPrintMacAddr(pMac, ptemp->bssDescription.bssId, LOG2);) + + pSirSmeScanRsp->sessionId = smesessionId; + pSirSmeScanRsp->transcationId = smetranscationId; + + ptemp = ptemp->next; + } //while(ptemp) + } //for (i = 0; i < LIM_MAX_NUM_OF_SCAN_RESULTS; i++) + + if (0 == bssCount) + { + limPostSmeScanRspMessage(pMac, length, resultCode, smesessionId, smetranscationId); + if (NULL != pSirSmeScanRsp) + { + palFreeMemory( pMac->hHdd, pSirSmeScanRsp); + pSirSmeScanRsp = NULL; + } + } + else + { + // send last message + pSirSmeScanRsp->statusCode = eSIR_SME_SUCCESS; + pSirSmeScanRsp->messageType = eWNI_SME_SCAN_RSP; + pSirSmeScanRsp->length = curMsgLen; + + /* Update SME session Id and SME transcation Id */ + pSirSmeScanRsp->sessionId = smesessionId; + pSirSmeScanRsp->transcationId = smetranscationId; + + mmhMsg.type = eWNI_SME_SCAN_RSP; + mmhMsg.bodyptr = pSirSmeScanRsp; + mmhMsg.bodyval = 0; + MTRACE(macTraceMsgTx(pMac, NO_SESSION, mmhMsg.type)); + limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); + PELOG2(limLog(pMac, LOG2, FL("statusCode : eSIR_SME_SUCCESS\n"));) + } + + return; + +} /*** end limSendSmeLfrScanRsp() ***/ +#endif //WLAN_FEATURE_ROAM_SCAN_OFFLOAD /** * limPostSmeScanRspMessage() @@ -799,12 +962,12 @@ limPostSmeScanRspMessage(tpAniSirGlobal pMac, tSirMsgQ mmhMsg; PELOG1(limLog(pMac, LOG1, - FL("limPostSmeScanRspMessage: send SME_SCAN_RSP (len %d, reasonCode %s). \n"), + FL("limPostSmeScanRspMessage: send SME_SCAN_RSP (len %d, reasonCode %s). "), length, limResultCodeStr(resultCode));) if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pSirSmeScanRsp, length)) { - limLog(pMac, LOGP, FL("palAllocateMemory failed for eWNI_SME_SCAN_RSP\n")); + limLog(pMac, LOGP, FL("palAllocateMemory failed for eWNI_SME_SCAN_RSP")); return; } palZeroMemory(pMac->hHdd, (void*)pSirSmeScanRsp, length); @@ -881,7 +1044,7 @@ void limSendSmeOemDataRsp(tpAniSirGlobal pMac, tANI_U32* pMsgBuf, tSirResultCode //now allocate memory for the char buffer if(eHAL_STATUS_SUCCESS != palAllocateMemory(pMac->hHdd, (void**)&pSirSmeOemDataRsp, msgLength)) { - limLog(pMac, LOGP, FL("call to palAllocateMemory failed for pSirSmeOemDataRsp\n")); + limLog(pMac, LOGP, FL("call to palAllocateMemory failed for pSirSmeOemDataRsp")); return; } @@ -951,7 +1114,7 @@ limSendSmeAuthRsp(tpAniSirGlobal pMac, { // Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for eWNI_SME_AUTH_RSP\n")); + FL("call to palAllocateMemory failed for eWNI_SME_AUTH_RSP")); return; } @@ -1057,7 +1220,7 @@ limSendSmeDisassocNtf(tpAniSirGlobal pMac, { // Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for eWNI_SME_DISASSOC_RSP\n")); + FL("call to palAllocateMemory failed for eWNI_SME_DISASSOC_RSP")); return; } @@ -1103,7 +1266,7 @@ limSendSmeDisassocNtf(tpAniSirGlobal pMac, { // Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for eWNI_SME_DISASSOC_IND\n")); + FL("call to palAllocateMemory failed for eWNI_SME_DISASSOC_IND")); return; } @@ -1167,7 +1330,7 @@ limSendSmeDisassocInd(tpAniSirGlobal pMac, tpDphHashNode pStaDs,tpPESession pses if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pSirSmeDisassocInd, sizeof(tSirSmeDisassocInd))) { - limLog(pMac, LOGP, FL("palAllocateMemory failed for eWNI_SME_DISASSOC_IND\n")); + limLog(pMac, LOGP, FL("palAllocateMemory failed for eWNI_SME_DISASSOC_IND")); return; } @@ -1219,7 +1382,7 @@ limSendSmeDeauthInd(tpAniSirGlobal pMac, tpDphHashNode pStaDs, tpPESession psess if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pSirSmeDeauthInd, sizeof(tSirSmeDeauthInd))) { - limLog(pMac, LOGP, FL("palAllocateMemory failed for eWNI_SME_DEAUTH_IND \n")); + limLog(pMac, LOGP, FL("palAllocateMemory failed for eWNI_SME_DEAUTH_IND ")); return; } @@ -1287,7 +1450,7 @@ limSendSmeTDLSDelStaInd(tpAniSirGlobal pMac, tpDphHashNode pStaDs, tpPESession p if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pSirTdlsDelStaInd, sizeof(tSirTdlsDelStaInd))) { - limLog(pMac, LOGP, FL("palAllocateMemory failed for eWNI_SME_TDLS_DEL_STA_IND \n")); + limLog(pMac, LOGP, FL("palAllocateMemory failed for eWNI_SME_TDLS_DEL_STA_IND ")); return; } @@ -1468,7 +1631,7 @@ limSendSmeDeauthNtf(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr, tSirResultCode { // Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for eWNI_SME_DEAUTH_RSP\n")); + FL("call to palAllocateMemory failed for eWNI_SME_DEAUTH_RSP")); return; } @@ -1500,7 +1663,7 @@ limSendSmeDeauthNtf(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr, tSirResultCode { // Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for eWNI_SME_DEAUTH_Ind\n")); + FL("call to palAllocateMemory failed for eWNI_SME_DEAUTH_Ind")); return; } @@ -1588,7 +1751,7 @@ limSendSmeWmStatusChangeNtf(tpAniSirGlobal pMac, tSirSmeStatusChangeCode statusC if (status != eHAL_STATUS_SUCCESS) { limLog(pMac, LOGE, - FL("call to palAllocateMemory failed for eWNI_SME_WM_STATUS_CHANGE_NTF, status = %d\n"), + FL("call to palAllocateMemory failed for eWNI_SME_WM_STATUS_CHANGE_NTF, status = %d"), status); return; } @@ -1623,7 +1786,7 @@ limSendSmeWmStatusChangeNtf(tpAniSirGlobal pMac, tSirSmeStatusChangeCode statusC { palCopyMemory( pMac->hHdd, (tANI_U8 *)&pSirSmeWmStatusChangeNtf->statusChangeInfo, (tANI_U8 *)pStatusChangeInfo, infoLen); } - limLog(pMac, LOGE, FL("***---*** StatusChg: code 0x%x, length %d ***---***\n"), + limLog(pMac, LOGE, FL("***---*** StatusChg: code 0x%x, length %d ***---***"), statusChangeCode, infoLen); break; } @@ -1633,7 +1796,7 @@ limSendSmeWmStatusChangeNtf(tpAniSirGlobal pMac, tSirSmeStatusChangeCode statusC if (eSIR_SUCCESS != limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT)) { palFreeMemory(pMac->hHdd, (void *) pSirSmeWmStatusChangeNtf); - limLog( pMac, LOGP, FL("limSysProcessMmhMsgApi failed\n")); + limLog( pMac, LOGP, FL("limSysProcessMmhMsgApi failed")); } } /*** end limSendSmeWmStatusChangeNtf() ***/ @@ -1680,7 +1843,7 @@ limSendSmeSetContextRsp(tpAniSirGlobal pMac, { // Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for SmeSetContextRsp\n")); + FL("call to palAllocateMemory failed for SmeSetContextRsp")); return; } @@ -1759,7 +1922,7 @@ limSendSmeRemoveKeyRsp(tpAniSirGlobal pMac, { // Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for SmeRemoveKeyRsp\n")); + FL("call to palAllocateMemory failed for SmeRemoveKeyRsp")); return; } @@ -1828,7 +1991,7 @@ limSendSmePromiscuousModeRsp(tpAniSirGlobal pMac) if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pMbMsg, sizeof(tSirMbMsg))) { // Log error - limLog(pMac, LOGP, FL("call to palAllocateMemory failed\n")); + limLog(pMac, LOGP, FL("call to palAllocateMemory failed")); return; } @@ -1889,7 +2052,7 @@ limSendSmeNeighborBssInd(tpAniSirGlobal pMac, if (wlan_cfgGetInt(pMac, WNI_CFG_NEW_BSS_FOUND_IND, &val) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("could not get NEIGHBOR_BSS_IND from CFG\n")); + limLog(pMac, LOGP, FL("could not get NEIGHBOR_BSS_IND from CFG")); return; } @@ -1909,7 +2072,7 @@ limSendSmeNeighborBssInd(tpAniSirGlobal pMac, { // Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for eWNI_SME_NEIGHBOR_BSS_IND\n")); + FL("call to palAllocateMemory failed for eWNI_SME_NEIGHBOR_BSS_IND")); return; } @@ -1991,7 +2154,7 @@ limSendSmeAddtsInd(tpAniSirGlobal pMac, tpSirAddtsReqInfo addts) tpSirAddtsRsp rsp; tSirMsgQ mmhMsg; - limLog(pMac, LOGW, "SendSmeAddtsInd (token %d, tsid %d, up %d)\n", + limLog(pMac, LOGW, "SendSmeAddtsInd (token %d, tsid %d, up %d)", addts->dialogToken, addts->tspec.tsinfo.traffic.tsid, addts->tspec.tsinfo.traffic.userPrio); @@ -1999,7 +2162,7 @@ limSendSmeAddtsInd(tpAniSirGlobal pMac, tpSirAddtsReqInfo addts) if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&rsp, sizeof(tSirAddtsRsp))) { // Log error - limLog(pMac, LOGP, FL("palAllocateMemory failed for ADDTS_IND\n")); + limLog(pMac, LOGP, FL("palAllocateMemory failed for ADDTS_IND")); return; } palZeroMemory( pMac->hHdd, (tANI_U8 *) rsp, sizeof(*rsp)); @@ -2021,7 +2184,7 @@ limSendSmeDeltsRsp(tpAniSirGlobal pMac, tpSirDeltsReq delts, tANI_U32 status,tpP tpSirDeltsRsp rsp; tSirMsgQ mmhMsg; - limLog(pMac, LOGW, "SendSmeDeltsRsp (aid %d, tsid %d, up %d) status %d\n", + limLog(pMac, LOGW, "SendSmeDeltsRsp (aid %d, tsid %d, up %d) status %d", delts->aid, delts->req.tsinfo.traffic.tsid, delts->req.tsinfo.traffic.userPrio, @@ -2032,7 +2195,7 @@ limSendSmeDeltsRsp(tpAniSirGlobal pMac, tpSirDeltsReq delts, tANI_U32 status,tpP if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&rsp, sizeof(tSirDeltsRsp))) { // Log error - limLog(pMac, LOGP, FL("palAllocateMemory failed for DELTS_RSP\n")); + limLog(pMac, LOGP, FL("palAllocateMemory failed for DELTS_RSP")); return; } palZeroMemory( pMac->hHdd, (tANI_U8 *) rsp, sizeof(*rsp)); @@ -2077,7 +2240,7 @@ limSendSmeDeltsInd(tpAniSirGlobal pMac, tpSirDeltsReqInfo delts, tANI_U16 aid,tp tpSirDeltsRsp rsp; tSirMsgQ mmhMsg; - limLog(pMac, LOGW, "SendSmeDeltsInd (aid %d, tsid %d, up %d)\n", + limLog(pMac, LOGW, "SendSmeDeltsInd (aid %d, tsid %d, up %d)", aid, delts->tsinfo.traffic.tsid, delts->tsinfo.traffic.userPrio); @@ -2085,7 +2248,7 @@ limSendSmeDeltsInd(tpAniSirGlobal pMac, tpSirDeltsReqInfo delts, tANI_U16 aid,tp if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&rsp, sizeof(tSirDeltsRsp))) { // Log error - limLog(pMac, LOGP, FL("palAllocateMemory failed for DELTS_IND\n")); + limLog(pMac, LOGP, FL("palAllocateMemory failed for DELTS_IND")); return; } palZeroMemory( pMac->hHdd, (tANI_U8 *) rsp, sizeof(*rsp)); @@ -2361,7 +2524,7 @@ void limSendExitBmpsInd(tpAniSirGlobal pMac, tExitBmpsReason reasonCode) msgLen = sizeof(tSirSmeExitBmpsInd); if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pExitBmpsInd, msgLen )) { - limLog(pMac, LOGP, FL("palAllocateMemory failed for PMC_EXIT_BMPS_IND \n")); + limLog(pMac, LOGP, FL("palAllocateMemory failed for PMC_EXIT_BMPS_IND ")); return; } palZeroMemory(pMac->hHdd, pExitBmpsInd, msgLen); @@ -2375,7 +2538,7 @@ void limSendExitBmpsInd(tpAniSirGlobal pMac, tExitBmpsReason reasonCode) mmhMsg.bodyptr = pExitBmpsInd; mmhMsg.bodyval = 0; - PELOG1(limLog(pMac, LOG1, FL("Sending eWNI_PMC_EXIT_BMPS_IND to SME. \n"));) + PELOG1(limLog(pMac, LOG1, FL("Sending eWNI_PMC_EXIT_BMPS_IND to SME. "));) MTRACE(macTraceMsgTx(pMac, NO_SESSION, mmhMsg.type)); #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT limDiagEventReport(pMac, WLAN_PE_DIAG_EXIT_BMPS_IND_EVENT, peGetValidPowerSaveSession(pMac), 0, (tANI_U16)reasonCode); @@ -2405,7 +2568,7 @@ void limHandleDeleteBssRsp(tpAniSirGlobal pMac,tpSirMsgQ MsgQ) tpDeleteBssParams pDelBss = (tpDeleteBssParams)(MsgQ->bodyptr); if((psessionEntry = peFindSessionBySessionId(pMac,pDelBss->sessionId))==NULL) { - limLog(pMac, LOGP,FL("Session Does not exist for given sessionID\n")); + limLog(pMac, LOGP,FL("Session Does not exist for given sessionID")); return; } if (psessionEntry->limSystemRole == eLIM_STA_IN_IBSS_ROLE) @@ -2518,10 +2681,53 @@ void limSendSmeMaxAssocExceededNtf(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr, mmhMsg.type = pSmeMaxAssocInd->mesgType; mmhMsg.bodyptr = pSmeMaxAssocInd; PELOG1(limLog(pMac, LOG1, FL("msgType %s peerMacAddr %02x-%02x-%02x-%02x-%02x-%02x" - "sme session id %d\n"),"eWNI_SME_MAX_ASSOC_EXCEEDED", peerMacAddr[0], peerMacAddr[1], + "sme session id %d"),"eWNI_SME_MAX_ASSOC_EXCEEDED", peerMacAddr[0], peerMacAddr[1], peerMacAddr[2], peerMacAddr[3], peerMacAddr[4], peerMacAddr[5], smesessionId);) MTRACE(macTraceMsgTx(pMac, smesessionId, mmhMsg.type)); limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); return; } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +/** ----------------------------------------------------------------- + \brief limSendSmeCandidateFoundInd() - sends + eWNI_SME_CANDIDATE_FOUND_IND + + After receiving candidate found indication frame from FW, this + function sends a eWNI_SME_CANDIDATE_FOUND_IND to SME to notify + roam candidate(s) are available. + + \param pMac - global mac structure + \param psessionEntry - session info + \return none + \sa + ----------------------------------------------------------------- */ +void +limSendSmeCandidateFoundInd(tpAniSirGlobal pMac, tANI_U8 sessionId) +{ + tSirMsgQ mmhMsg; + tSirSmeCandidateFoundInd *pSirSmeCandidateFoundInd; + + if ( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, + (void **)&pSirSmeCandidateFoundInd, + sizeof(tSirSmeCandidateFoundInd))) + { + limLog(pMac, LOGP, FL("palAllocateMemory failed for eWNI_SME_CANDIDATE_FOUND_IND\n")); + return; + } + + pSirSmeCandidateFoundInd->messageType = eWNI_SME_CANDIDATE_FOUND_IND; + pSirSmeCandidateFoundInd->length = sizeof(tSirSmeDisassocInd); + + pSirSmeCandidateFoundInd->sessionId = sessionId; + + + limLog( pMac, LOGE, FL("posting candidate ind to SME")); + mmhMsg.type = eWNI_SME_CANDIDATE_FOUND_IND; + mmhMsg.bodyptr = pSirSmeCandidateFoundInd; + mmhMsg.bodyval = 0; + + limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); + +} /*** end limSendSmeCandidateFoundInd() ***/ +#endif //WLAN_FEATURE_ROAM_SCAN_OFFLOAD diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limSendSmeRspMessages.h b/drivers/staging/prima/CORE/MAC/src/pe/lim/limSendSmeRspMessages.h index a2e5c47e767..3ef5351f1d7 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limSendSmeRspMessages.h +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limSendSmeRspMessages.h @@ -63,6 +63,9 @@ void limSendSmeRsp(tpAniSirGlobal, tANI_U16, tSirResultCodes, tANI_U8 , tANI_U16); void limSendSmeStartBssRsp(tpAniSirGlobal, tANI_U16, tSirResultCodes,tpPESession,tANI_U8,tANI_U16); void limSendSmeScanRsp(tpAniSirGlobal, tANI_U16, tSirResultCodes,tANI_U8, tANI_U16); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +void limSendSmeLfrScanRsp(tpAniSirGlobal, tANI_U16, tSirResultCodes,tANI_U8, tANI_U16); +#endif void limPostSmeScanRspMessage(tpAniSirGlobal, tANI_U16, tSirResultCodes,tANI_U8,tANI_U16); void limSendSmeAuthRsp(tpAniSirGlobal, tSirResultCodes, tSirMacAddr, tAniAuthType, tANI_U16,tpPESession,tANI_U8,tANI_U16); @@ -72,8 +75,9 @@ void limSendSmeDisassocNtf(tpAniSirGlobal, tSirMacAddr, tSirResultCodes, tANI_U1 void limSendSmeDeauthNtf(tpAniSirGlobal, tSirMacAddr, tSirResultCodes, tANI_U16, tANI_U16, tANI_U8, tANI_U16); void limSendSmeDisassocInd(tpAniSirGlobal, tpDphHashNode,tpPESession); void limSendSmeDeauthInd(tpAniSirGlobal, tpDphHashNode, tpPESession psessionEntry); - - +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +void limSendSmeCandidateFoundInd(tpAniSirGlobal, tANI_U8); +#endif void limSendSmeWmStatusChangeNtf(tpAniSirGlobal, tSirSmeStatusChangeCode, tANI_U32 *, tANI_U16, tANI_U8); void limSendSmeSetContextRsp(tpAniSirGlobal, diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limSerDesUtils.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limSerDesUtils.c index 152024d3582..9969899dd8b 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limSerDesUtils.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limSerDesUtils.c @@ -88,7 +88,7 @@ limCheckRemainingLength(tpAniSirGlobal pMac, tANI_S16 len) else { limLog(pMac, LOGW, - FL("Received SME message with invalid rem length=%d\n"), + FL("Received SME message with invalid rem length=%d"), len); return eSIR_FAILURE; } @@ -237,7 +237,7 @@ limGetBssDescription( tpAniSirGlobal pMac, tSirBssDescription *pBssDescription, pBssDescription->mdie[2] = *pBuf++; len --; #ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG - PELOGE(limLog(pMac, LOG1, FL("mdie=%02x %02x %02x\n"), + PELOGE(limLog(pMac, LOG1, FL("mdie=%02x %02x %02x"), pBssDescription->mdie[0], pBssDescription->mdie[1], pBssDescription->mdie[2]);) @@ -287,7 +287,7 @@ limGetBssDescription( tpAniSirGlobal pMac, tSirBssDescription *pBssDescription, else { limLog(pMac, LOGE, - FL("remaining bytes len %d is less than WSCIE_PROBE_RSP_LEN\n"), + FL("remaining bytes len %d is less than WSCIE_PROBE_RSP_LEN"), pBssDescription->WscIeLen); return eSIR_FAILURE; } @@ -305,7 +305,7 @@ limGetBssDescription( tpAniSirGlobal pMac, tSirBssDescription *pBssDescription, else if (len < 0) { limLog(pMac, LOGE, - FL("remaining length is negative. len = %d, actual length = %d\n"), + FL("remaining length is negative. len = %d, actual length = %d"), len, pBssDescription->length); return eSIR_FAILURE; } @@ -452,7 +452,7 @@ limGetKeysInfo(tpAniSirGlobal pMac, tpSirKeys pKeyInfo, tANI_U8 *pBuf) len += pKeyInfo->keyLength; PELOG3(limLog(pMac, LOG3, - FL("Extracted keyId=%d, keyLength=%d, Key is :\n"), + FL("Extracted keyId=%d, keyLength=%d, Key is :"), pKeyInfo->keyId, pKeyInfo->keyLength); sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG3, pKeyInfo->key, pKeyInfo->keyLength);) @@ -504,7 +504,7 @@ limStartBssReqSerDes(tpAniSirGlobal pMac, tpSirSmeStartBssReq pStartBssReq, tANI len = pStartBssReq->length = limGetU16(pBuf); pBuf += sizeof(tANI_U16); - PELOG1(limLog(pMac, LOG1, FL("SME_START_BSS_REQ length %d bytes is:\n"), len);) + PELOG1(limLog(pMac, LOG1, FL("SME_START_BSS_REQ length %d bytes is:"), len);) PELOG1(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG1, pTemp, len);) if (len < (tANI_S16) sizeof(tANI_U32)) @@ -565,7 +565,7 @@ limStartBssReqSerDes(tpAniSirGlobal pMac, tpSirSmeStartBssReq pStartBssReq, tANI if (*pBuf > SIR_MAC_MAX_SSID_LENGTH) { // SSID length is more than max allowed 32 bytes - PELOGW(limLog(pMac, LOGW, FL("Invalid SSID length, len=%d\n"), *pBuf);) + PELOGW(limLog(pMac, LOGW, FL("Invalid SSID length, len=%d"), *pBuf);) return eSIR_FAILURE; } @@ -574,7 +574,7 @@ limStartBssReqSerDes(tpAniSirGlobal pMac, tpSirSmeStartBssReq pStartBssReq, tANI if (len < pStartBssReq->ssId.length) { limLog(pMac, LOGW, - FL("SSID length is longer that the remaining length. SSID len=%d, remaining len=%d\n"), + FL("SSID length is longer that the remaining length. SSID len=%d, remaining len=%d"), pStartBssReq->ssId.length, len); return eSIR_FAILURE; } @@ -683,7 +683,7 @@ limStartBssReqSerDes(tpAniSirGlobal pMac, tpSirSmeStartBssReq pStartBssReq, tANI if (pStartBssReq->rsnIE.length > SIR_MAC_MAX_IE_LENGTH + 2) { limLog(pMac, LOGW, - FL("Invalid RSN IE length %d in SME_START_BSS_REQ\n"), + FL("Invalid RSN IE length %d in SME_START_BSS_REQ"), pStartBssReq->rsnIE.length); return eSIR_FAILURE; } @@ -710,7 +710,7 @@ limStartBssReqSerDes(tpAniSirGlobal pMac, tpSirSmeStartBssReq pStartBssReq, tANI if (pStartBssReq->operationalRateSet.numRates > SIR_MAC_MAX_NUMBER_OF_RATES) { - limLog(pMac, LOGW, FL("Invalid numRates %d in SME_START_BSS_REQ\n"), + limLog(pMac, LOGW, FL("Invalid numRates %d in SME_START_BSS_REQ"), pStartBssReq->operationalRateSet.numRates); return eSIR_FAILURE; } @@ -740,7 +740,7 @@ limStartBssReqSerDes(tpAniSirGlobal pMac, tpSirSmeStartBssReq pStartBssReq, tANI if (len) { - limLog(pMac, LOGW, FL("Extra bytes left in SME_START_BSS_REQ, len=%d\n"), len); + limLog(pMac, LOGW, FL("Extra bytes left in SME_START_BSS_REQ, len=%d"), len); } return eSIR_SUCCESS; @@ -787,7 +787,7 @@ limStopBssReqSerDes(tpAniSirGlobal pMac, tpSirSmeStopBssReq pStopBssReq, tANI_U8 len = pStopBssReq->length = limGetU16(pBuf); pBuf += sizeof(tANI_U16); - PELOG1(limLog(pMac, LOG1, FL("SME_STOP_BSS_REQ length %d bytes is:\n"), len);) + PELOG1(limLog(pMac, LOG1, FL("SME_STOP_BSS_REQ length %d bytes is:"), len);) PELOG1(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG1, pTemp, len);) if (len < (tANI_S16) sizeof(tANI_U32)) @@ -862,7 +862,7 @@ limJoinReqSerDes(tpAniSirGlobal pMac, tpSirSmeJoinReq pJoinReq, tANI_U8 *pBuf) if (!pJoinReq || !pBuf) { - PELOGE(limLog(pMac, LOGE, FL("NULL ptr received\n"));) + PELOGE(limLog(pMac, LOGE, FL("NULL ptr received"));) return eSIR_FAILURE; } @@ -875,15 +875,15 @@ limJoinReqSerDes(tpAniSirGlobal pMac, tpSirSmeJoinReq pJoinReq, tANI_U8 *pBuf) pBuf += sizeof(tANI_U16); if (pJoinReq->messageType == eWNI_SME_JOIN_REQ) - PELOG1(limLog(pMac, LOG3, FL("SME_JOIN_REQ length %d bytes is:\n"), len);) + PELOG1(limLog(pMac, LOG3, FL("SME_JOIN_REQ length %d bytes is:"), len);) else - PELOG1(limLog(pMac, LOG3, FL("SME_REASSOC_REQ length %d bytes is:\n"), len);) + PELOG1(limLog(pMac, LOG3, FL("SME_REASSOC_REQ length %d bytes is:"), len);) PELOG1(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG3, pTemp, len);) if (len < (tANI_S16) sizeof(tANI_U32)) { - PELOGE(limLog(pMac, LOGE, FL("len too short %d\n"), len);) + PELOGE(limLog(pMac, LOGE, FL("len too short %d"), len);) return eSIR_FAILURE; } @@ -988,7 +988,7 @@ limJoinReqSerDes(tpAniSirGlobal pMac, tpSirSmeJoinReq pJoinReq, tANI_U8 *pBuf) (pJoinReq->rsnIE.length != 2 + *(pBuf + 1))) { limLog(pMac, LOGW, - FL("Invalid RSN IE length %d in SME_JOIN_REQ\n"), + FL("Invalid RSN IE length %d in SME_JOIN_REQ"), pJoinReq->rsnIE.length); return eSIR_FAILURE; } @@ -1012,7 +1012,7 @@ limJoinReqSerDes(tpAniSirGlobal pMac, tpSirSmeJoinReq pJoinReq, tANI_U8 *pBuf) (pJoinReq->cckmIE.length != (2 + *(pBuf + 1)))) { limLog(pMac, LOGW, - FL("Invalid CCKM IE length %d/%d in SME_JOIN/REASSOC_REQ\n"), + FL("Invalid CCKM IE length %d/%d in SME_JOIN/REASSOC_REQ"), pJoinReq->cckmIE.length, 2 + *(pBuf + 1)); return eSIR_FAILURE; } @@ -1036,7 +1036,7 @@ limJoinReqSerDes(tpAniSirGlobal pMac, tpSirSmeJoinReq pJoinReq, tANI_U8 *pBuf) if (pJoinReq->addIEScan.length > SIR_MAC_MAX_IE_LENGTH + 2) { limLog(pMac, LOGE, - FL("Invalid addIE Scan length %d in SME_JOIN_REQ\n"), + FL("Invalid addIE Scan length %d in SME_JOIN_REQ"), pJoinReq->addIEScan.length); return eSIR_FAILURE; } @@ -1060,7 +1060,7 @@ limJoinReqSerDes(tpAniSirGlobal pMac, tpSirSmeJoinReq pJoinReq, tANI_U8 *pBuf) if (pJoinReq->addIEAssoc.length > SIR_MAC_MAX_IE_LENGTH + 2) { limLog(pMac, LOGE, - FL("Invalid addIE Assoc length %d in SME_JOIN_REQ\n"), + FL("Invalid addIE Assoc length %d in SME_JOIN_REQ"), pJoinReq->addIEAssoc.length); return eSIR_FAILURE; } @@ -1073,26 +1073,18 @@ limJoinReqSerDes(tpAniSirGlobal pMac, tpSirSmeJoinReq pJoinReq, tANI_U8 *pBuf) return eSIR_FAILURE; } - pJoinReq->MCEncryptionType = limGetU32(pBuf); + pJoinReq->UCEncryptionType = limGetU32(pBuf); pBuf += sizeof(tANI_U32); len -= sizeof(tANI_U32); if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) return eSIR_FAILURE; - pJoinReq->UCEncryptionType = limGetU32(pBuf); + pJoinReq->MCEncryptionType = limGetU32(pBuf); pBuf += sizeof(tANI_U32); len -= sizeof(tANI_U32); if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) return eSIR_FAILURE; -#ifdef WLAN_FEATURE_11W - pJoinReq->MgmtEncryptionType = limGetU32(pBuf); - pBuf += sizeof(tANI_U32); - len -= sizeof(tANI_U32); - if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) - return eSIR_FAILURE; -#endif - #ifdef WLAN_FEATURE_VOWIFI_11R //is11Rconnection; pJoinReq->is11Rconnection = (tAniBool)limGetU32(pBuf); @@ -1103,6 +1095,13 @@ limJoinReqSerDes(tpAniSirGlobal pMac, tpSirSmeJoinReq pJoinReq, tANI_U8 *pBuf) #endif #ifdef FEATURE_WLAN_CCX + //CCX version IE + pJoinReq->isCCXFeatureIniEnabled = (tAniBool)limGetU32(pBuf); + pBuf += sizeof(tAniBool); + len -= sizeof(tAniBool); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + //isCCXconnection; pJoinReq->isCCXconnection = (tAniBool)limGetU32(pBuf); pBuf += sizeof(tAniBool); @@ -1174,7 +1173,7 @@ limJoinReqSerDes(tpAniSirGlobal pMac, tpSirSmeJoinReq pJoinReq, tANI_U8 *pBuf) pJoinReq->powerCap.minTxPower = *pBuf++; pJoinReq->powerCap.maxTxPower = *pBuf++; len -=2; - limLog(pMac, LOG1, FL("Power Caps: Min power = %d, Max power = %d\n"), pJoinReq->powerCap.minTxPower, pJoinReq->powerCap.maxTxPower); + limLog(pMac, LOG1, FL("Power Caps: Min power = %d, Max power = %d"), pJoinReq->powerCap.minTxPower, pJoinReq->powerCap.maxTxPower); pJoinReq->supportedChannels.numChnl = *pBuf++; len--; @@ -1184,7 +1183,7 @@ limJoinReqSerDes(tpAniSirGlobal pMac, tpSirSmeJoinReq pJoinReq, tANI_U8 *pBuf) len-= pJoinReq->supportedChannels.numChnl; PELOG2(limLog(pMac, LOG2, - FL("spectrumInd ON: minPower %d, maxPower %d , numChnls %d\n"), + FL("spectrumInd ON: minPower %d, maxPower %d , numChnls %d"), pJoinReq->powerCap.minTxPower, pJoinReq->powerCap.maxTxPower, pJoinReq->supportedChannels.numChnl);) @@ -1203,7 +1202,7 @@ limJoinReqSerDes(tpAniSirGlobal pMac, tpSirSmeJoinReq pJoinReq, tANI_U8 *pBuf) if (limGetBssDescription( pMac, &pJoinReq->bssDescription, len, &lenUsed, pBuf) == eSIR_FAILURE) { - PELOGE(limLog(pMac, LOGE, FL("get bss description failed\n"));) + PELOGE(limLog(pMac, LOGE, FL("get bss description failed"));) return eSIR_FAILURE; } PELOG3(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG3, (tANI_U8 *) &(pJoinReq->bssDescription), pJoinReq->bssDescription.length + 2);) @@ -1314,7 +1313,7 @@ limAssocIndSerDes(tpAniSirGlobal pMac, tpLimMlmAssocInd pAssocInd, tANI_U8 *pBuf // Fill in length of SME_ASSOC_IND message limCopyU16(pLen, mLen); - PELOG1(limLog(pMac, LOG1, FL("Sending SME_ASSOC_IND length %d bytes:\n"), mLen);) + PELOG1(limLog(pMac, LOG1, FL("Sending SME_ASSOC_IND length %d bytes:"), mLen);) PELOG1(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG1, pTemp, mLen);) } /*** end limAssocIndSerDes() ***/ @@ -1363,11 +1362,11 @@ limAssocCnfSerDes(tpAniSirGlobal pMac, tpSirSmeAssocCnf pAssocCnf, tANI_U8 *pBuf if (pAssocCnf->messageType == eWNI_SME_ASSOC_CNF) { - PELOG1(limLog(pMac, LOG1, FL("SME_ASSOC_CNF length %d bytes is:\n"), pAssocCnf->length);) + PELOG1(limLog(pMac, LOG1, FL("SME_ASSOC_CNF length %d bytes is:"), pAssocCnf->length);) } else { - PELOG1(limLog(pMac, LOG1, FL("SME_REASSOC_CNF length %d bytes is:\n"), pAssocCnf->length);) + PELOG1(limLog(pMac, LOG1, FL("SME_REASSOC_CNF length %d bytes is:"), pAssocCnf->length);) } PELOG1(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG1, pTemp, pAssocCnf->length);) @@ -1440,7 +1439,7 @@ limDisassocCnfSerDes(tpAniSirGlobal pMac, tpSirSmeDisassocCnf pDisassocCnf, tANI pDisassocCnf->length = limGetU16(pBuf); pBuf += sizeof(tANI_U16); - PELOG1(limLog(pMac, LOG1, FL("SME_DISASSOC_CNF length %d bytes is:\n"), pDisassocCnf->length);) + PELOG1(limLog(pMac, LOG1, FL("SME_DISASSOC_CNF length %d bytes is:"), pDisassocCnf->length);) PELOG1(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG1, pTemp, pDisassocCnf->length);) pDisassocCnf->statusCode = (tSirResultCodes) limGetU32(pBuf); @@ -1573,7 +1572,7 @@ limReassocIndSerDes(tpAniSirGlobal pMac, tpLimMlmReassocInd pReassocInd, tANI_U8 // Fill in length of SME_REASSOC_IND message limCopyU16(pLen, mLen); - PELOG1(limLog(pMac, LOG1, FL("Sending SME_REASSOC_IND length %d bytes:\n"), mLen);) + PELOG1(limLog(pMac, LOG1, FL("Sending SME_REASSOC_IND length %d bytes:"), mLen);) PELOG1(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG1, pTemp, mLen);) } /*** end limReassocIndSerDes() ***/ @@ -1631,7 +1630,7 @@ limAuthIndSerDes(tpAniSirGlobal pMac, tpLimMlmAuthInd pAuthInd, tANI_U8 *pBuf) limCopyU16(pLen, mLen); - PELOG1(limLog(pMac, LOG1, FL("Sending SME_AUTH_IND length %d bytes:\n"), mLen);) + PELOG1(limLog(pMac, LOG1, FL("Sending SME_AUTH_IND length %d bytes:"), mLen);) PELOG1(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG1, pTemp, mLen);) } /*** end limAuthIndSerDes() ***/ @@ -1683,7 +1682,7 @@ limSetContextReqSerDes(tpAniSirGlobal pMac, tpSirSmeSetContextReq pSetContextReq len = pSetContextReq->length = limGetU16(pBuf); pBuf += sizeof(tANI_U16); - PELOG1(limLog(pMac, LOG1, FL("SME_SETCONTEXT_REQ length %d bytes is:\n"), len);) + PELOG1(limLog(pMac, LOG1, FL("SME_SETCONTEXT_REQ length %d bytes is:"), len);) PELOG1(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG3, pTemp, len);) if (len < (tANI_S16) sizeof(tANI_U32)) @@ -1816,7 +1815,7 @@ limRemoveKeyReqSerDes(tpAniSirGlobal pMac, tpSirSmeRemoveKeyReq pRemoveKeyReq, t len = pRemoveKeyReq->length = limGetU16(pBuf); pBuf += sizeof(tANI_U16); - PELOG1(limLog(pMac, LOG1, FL("SME_REMOVEKEY_REQ length %d bytes is:\n"), len);) + PELOG1(limLog(pMac, LOG1, FL("SME_REMOVEKEY_REQ length %d bytes is:"), len);) PELOG1(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG1, pTemp, len);) if (len < (tANI_S16) sizeof(tANI_U32)) @@ -1926,7 +1925,7 @@ limDisassocReqSerDes(tpAniSirGlobal pMac, tSirSmeDisassocReq *pDisassocReq, tANI len = pDisassocReq->length = limGetU16(pBuf); pBuf += sizeof(tANI_U16); - PELOG1(limLog(pMac, LOG1, FL("SME_DISASSOC_REQ length %d bytes is:\n"), len);) + PELOG1(limLog(pMac, LOG1, FL("SME_DISASSOC_REQ length %d bytes is:"), len);) PELOG1(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG1, pTemp, len);) if (len < (tANI_S16) sizeof(tANI_U32)) @@ -2023,7 +2022,7 @@ limDeauthReqSerDes(tpAniSirGlobal pMac, tSirSmeDeauthReq *pDeauthReq, tANI_U8 *p len = pDeauthReq->length = limGetU16(pBuf); pBuf += sizeof(tANI_U16); - PELOG1(limLog(pMac, LOG1, FL("SME_DEAUTH_REQ length %d bytes is:\n"), len);) + PELOG1(limLog(pMac, LOG1, FL("SME_DEAUTH_REQ length %d bytes is:"), len);) PELOG1(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG1, pTemp, len);) if (len < (tANI_S16) sizeof(tANI_U32)) @@ -2179,7 +2178,7 @@ limStatSerDes(tpAniSirGlobal pMac, tpAniStaStatStruct pStat, tANI_U8 *pBuf) limCopyU32(pBuf, pStat->nXmitBytes); pBuf += sizeof(tANI_U32); - PELOG1(limLog(pMac, LOG1, FL("STAT: length %d bytes is:\n"), sizeof(tAniStaStatStruct));) + PELOG1(limLog(pMac, LOG1, FL("STAT: length %d bytes is:"), sizeof(tAniStaStatStruct));) PELOG1(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG1, pTemp, sizeof(tAniStaStatStruct));) } /*** end limStatSerDes() ***/ @@ -2287,11 +2286,11 @@ limIsSmeGetAssocSTAsReqValid(tpAniSirGlobal pMac, tpSirSmeGetAssocSTAsReq pGetAs pBuf += sizeof(tANI_U32); len -= sizeof(tANI_U32); - PELOG1(limLog(pMac, LOG1, FL("SME_GET_ASSOC_STAS_REQ length consumed %d bytes \n"), len);) + PELOG1(limLog(pMac, LOG1, FL("SME_GET_ASSOC_STAS_REQ length consumed %d bytes "), len);) if (len < 0) { - PELOGE(limLog(pMac, LOGE, FL("SME_GET_ASSOC_STAS_REQ invalid length\n"));) + PELOGE(limLog(pMac, LOGE, FL("SME_GET_ASSOC_STAS_REQ invalid length"));) return eANI_BOOLEAN_FALSE; } @@ -2336,7 +2335,7 @@ limTkipCntrMeasReqSerDes(tpAniSirGlobal pMac, tpSirSmeTkipCntrMeasReq pTkipCntr len = pTkipCntrMeasReq->length = limGetU16(pBuf); pBuf += sizeof(tANI_U16); - PELOG1(limLog(pMac, LOG1, FL("SME_TKIP_CNTR_MEAS_REQ length %d bytes is:\n"), len);) + PELOG1(limLog(pMac, LOG1, FL("SME_TKIP_CNTR_MEAS_REQ length %d bytes is:"), len);) PELOG1(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG1, pTemp, len);) if (len < (tANI_S16) sizeof(tANI_U32)) @@ -2370,11 +2369,11 @@ limTkipCntrMeasReqSerDes(tpAniSirGlobal pMac, tpSirSmeTkipCntrMeasReq pTkipCntr pTkipCntrMeasReq->bEnable = *pBuf++; len --; - PELOG1(limLog(pMac, LOG1, FL("SME_TKIP_CNTR_MEAS_REQ length consumed %d bytes \n"), len);) + PELOG1(limLog(pMac, LOG1, FL("SME_TKIP_CNTR_MEAS_REQ length consumed %d bytes "), len);) if (len) { - PELOGE(limLog(pMac, LOGE, FL("SME_TKIP_CNTR_MEAS_REQ invalid \n"));) + PELOGE(limLog(pMac, LOGE, FL("SME_TKIP_CNTR_MEAS_REQ invalid "));) return eSIR_FAILURE; } else @@ -2445,11 +2444,11 @@ limIsSmeGetWPSPBCSessionsReqValid(tpAniSirGlobal pMac, tSirSmeGetWPSPBCSessionsR pBuf += sizeof(tSirMacAddr); len -= sizeof(tSirMacAddr); - PELOG1(limLog(pMac, LOG1, FL("SME_GET_ASSOC_STAS_REQ length consumed %d bytes \n"), len);) + PELOG1(limLog(pMac, LOG1, FL("SME_GET_ASSOC_STAS_REQ length consumed %d bytes "), len);) if (len < 0) { - PELOGE(limLog(pMac, LOGE, FL("SME_GET_WPSPBC_SESSION_REQ invalid length\n"));) + PELOGE(limLog(pMac, LOGE, FL("SME_GET_WPSPBC_SESSION_REQ invalid length"));) return eSIR_FAILURE; } @@ -2477,7 +2476,7 @@ limGetSessionInfo(tpAniSirGlobal pMac, tANI_U8 *pBuf, tANI_U8 *sessionId, tANI_U { if (!pBuf) { - limLog(pMac, LOGE, FL("NULL ptr received. \n")); + limLog(pMac, LOGE, FL("NULL ptr received. ")); return; } @@ -2565,11 +2564,11 @@ limUpdateAPWPSIEsReqSerDes(tpAniSirGlobal pMac, tpSirUpdateAPWPSIEsReq pUpdateAP pBuf += sizeof(tSirAPWPSIEs); len -= sizeof(tSirAPWPSIEs); - PELOG1(limLog(pMac, LOG1, FL("SME_UPDATE_APWPSIE_REQ length consumed %d bytes \n"), len);) + PELOG1(limLog(pMac, LOG1, FL("SME_UPDATE_APWPSIE_REQ length consumed %d bytes "), len);) if (len < 0) { - PELOGE(limLog(pMac, LOGE, FL("SME_UPDATE_APWPSIE_REQ invalid length\n"));) + PELOGE(limLog(pMac, LOGE, FL("SME_UPDATE_APWPSIE_REQ invalid length"));) return eSIR_FAILURE; } @@ -2651,7 +2650,7 @@ limUpdateAPWPARSNIEsReqSerDes(tpAniSirGlobal pMac, tpSirUpdateAPWPARSNIEsReq pUp if (len < 0) { - PELOGE(limLog(pMac, LOGE, FL("SME_GET_WPSPBC_SESSION_REQ invalid length\n"));) + PELOGE(limLog(pMac, LOGE, FL("SME_GET_WPSPBC_SESSION_REQ invalid length"));) return eSIR_FAILURE; } diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limSession.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limSession.c index 97a76e7a12c..805856c3949 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limSession.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limSession.c @@ -129,14 +129,14 @@ tpPESession peCreateSession(tpAniSirGlobal pMac, tANI_U8 *bssid , tANI_U8* sessi if (eHAL_STATUS_SUCCESS != palAllocateMemory(pMac->hHdd, (void **) &pMac->lim.gpSession[i].dph.dphHashTable.pHashTable, sizeof(tpDphHashNode)*numSta)) { - limLog(pMac, LOGE, FL("memory allocate failed!\n")); + limLog(pMac, LOGE, FL("memory allocate failed!")); return NULL; } if (eHAL_STATUS_SUCCESS != palAllocateMemory(pMac->hHdd, (void **) &pMac->lim.gpSession[i].dph.dphHashTable.pDphNodeArray, sizeof(tDphHashNode)*numSta)) { - limLog(pMac, LOGE, FL("memory allocate failed!\n")); + limLog(pMac, LOGE, FL("memory allocate failed!")); palFreeMemory(pMac->hHdd,pMac->lim.gpSession[i].dph.dphHashTable.pHashTable); return NULL; } @@ -149,7 +149,7 @@ tpPESession peCreateSession(tpAniSirGlobal pMac, tANI_U8 *bssid , tANI_U8* sessi (void **) &pMac->lim.gpSession[i].gpLimPeerIdxpool, sizeof(*pMac->lim.gpSession[i].gpLimPeerIdxpool) * (numSta+1))) { - PELOGE(limLog(pMac, LOGE, FL("memory allocate failed!\n"));) + PELOGE(limLog(pMac, LOGE, FL("memory allocate failed!"));) palFreeMemory(pMac->hHdd,pMac->lim.gpSession[i].dph.dphHashTable.pHashTable); palFreeMemory(pMac->hHdd,pMac->lim.gpSession[i].dph.dphHashTable.pDphNodeArray); return NULL; diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limSessionUtils.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limSessionUtils.c index d6b0ef1d701..fe5b6a20d5b 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limSessionUtils.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limSessionUtils.c @@ -1,50 +1,30 @@ /* - * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. - * - * Previously licensed under the ISC license by Qualcomm Atheros, Inc. - * - * - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all - * copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ -/* - * Copyright (c) 2012, The Linux Foundation. All rights reserved. - * - * Previously licensed under the ISC license by Qualcomm Atheros, Inc. - * - * - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all - * copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - + * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. +*/ /**========================================================================= \file limSessionUtils.c \brief implementation for lim Session Utility APIs \author Sunit Bhatia + Copyright 2008 (c) Qualcomm Technologies, Inc. All Rights Reserved. ========================================================================*/ diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limSmeReqUtils.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limSmeReqUtils.c index 5ee773781da..f7f8f5ac591 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limSmeReqUtils.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limSmeReqUtils.c @@ -97,14 +97,14 @@ limIsRSNieValidInSmeReqMessage(tpAniSirGlobal pMac, tpSirRSNie pRSNie) &privacy) != eSIR_SUCCESS) { limLog(pMac, LOGP, - FL("Unable to retrieve POI from CFG\n")); + FL("Unable to retrieve POI from CFG")); } if (wlan_cfgGetInt(pMac, WNI_CFG_RSN_ENABLED, &val) != eSIR_SUCCESS) { limLog(pMac, LOGP, - FL("Unable to retrieve RSN_ENABLED from CFG\n")); + FL("Unable to retrieve RSN_ENABLED from CFG")); } if (pRSNie->length && (!privacy || !val)) @@ -115,7 +115,7 @@ limIsRSNieValidInSmeReqMessage(tpAniSirGlobal pMac, tpSirRSNie pRSNie) * allow BSS creation/join with no Privacy capability * yet advertising WPA IE */ - PELOG1(limLog(pMac, LOG1, FL("RSN ie len %d but PRIVACY %d RSN %d\n"), + PELOG1(limLog(pMac, LOG1, FL("RSN ie len %d but PRIVACY %d RSN %d"), pRSNie->length, privacy, val);) } @@ -128,7 +128,7 @@ limIsRSNieValidInSmeReqMessage(tpAniSirGlobal pMac, tpSirRSNie pRSNie) #endif ) { - limLog(pMac, LOGE, FL("RSN/WPA/WAPI EID %d not [%d || %d]\n"), + limLog(pMac, LOGE, FL("RSN/WPA/WAPI EID %d not [%d || %d]"), pRSNie->rsnIEdata[0], DOT11F_EID_RSN, DOT11F_EID_WPA); return false; @@ -143,49 +143,53 @@ limIsRSNieValidInSmeReqMessage(tpAniSirGlobal pMac, tpSirRSNie pRSNie) { if((pRSNie->rsnIEdata[startPos+1] > DOT11F_IE_RSN_MAX_LEN) || (pRSNie->rsnIEdata[startPos+1] < DOT11F_IE_RSN_MIN_LEN)) - { - limLog(pMac, LOGE, FL("RSN IE len %d not [%d,%d]\n"), - pRSNie->rsnIEdata[startPos+1], DOT11F_IE_RSN_MIN_LEN, - DOT11F_IE_RSN_MAX_LEN); - return false; - } + { + limLog(pMac, LOGE, FL("RSN IE len %d not [%d,%d]"), + pRSNie->rsnIEdata[startPos+1], DOT11F_IE_RSN_MIN_LEN, + DOT11F_IE_RSN_MAX_LEN); + return false; + } } else if(pRSNie->rsnIEdata[startPos] == DOT11F_EID_WPA) - { - // Check validity of WPA IE - val = sirReadU32((tANI_U8 *) &pRSNie->rsnIEdata[startPos + 2]); - if((pRSNie->rsnIEdata[startPos + 1] < DOT11F_IE_WPA_MIN_LEN) || - (pRSNie->rsnIEdata[startPos + 1] > DOT11F_IE_WPA_MAX_LEN) || - (SIR_MAC_WPA_OUI != val)) { - limLog(pMac, LOGE, - FL("WPA IE len %d not [%d,%d] OR data 0x%x not 0x%x\n"), - pRSNie->rsnIEdata[startPos+1], DOT11F_IE_WPA_MIN_LEN, - DOT11F_IE_WPA_MAX_LEN, val, SIR_MAC_WPA_OUI); - - return false; + // Check validity of WPA IE + if (SIR_MAC_MAX_IE_LENGTH > startPos) + { + if (startPos <= (SIR_MAC_MAX_IE_LENGTH - sizeof(tANI_U32))) + val = sirReadU32((tANI_U8 *) &pRSNie->rsnIEdata[startPos + 2]); + if((pRSNie->rsnIEdata[startPos + 1] < DOT11F_IE_WPA_MIN_LEN) || + (pRSNie->rsnIEdata[startPos + 1] > DOT11F_IE_WPA_MAX_LEN) || + (SIR_MAC_WPA_OUI != val)) + { + limLog(pMac, LOGE, + FL("WPA IE len %d not [%d,%d] OR data 0x%x not 0x%x"), + pRSNie->rsnIEdata[startPos+1], DOT11F_IE_WPA_MIN_LEN, + DOT11F_IE_WPA_MAX_LEN, val, SIR_MAC_WPA_OUI); + + return false; + } + } } - } #ifdef FEATURE_WLAN_WAPI else if(pRSNie->rsnIEdata[startPos] == DOT11F_EID_WAPI) { if((pRSNie->rsnIEdata[startPos+1] > DOT11F_IE_WAPI_MAX_LEN) || (pRSNie->rsnIEdata[startPos+1] < DOT11F_IE_WAPI_MIN_LEN)) - { + { limLog(pMac, LOGE, - FL("WAPI IE len %d not [%d,%d]\n"), + FL("WAPI IE len %d not [%d,%d]"), pRSNie->rsnIEdata[startPos+1], DOT11F_IE_WAPI_MIN_LEN, DOT11F_IE_WAPI_MAX_LEN); return false; } - } + } #endif else - { + { //we will never be here, simply for completeness - return false; - } + return false; + } startPos += 2 + pRSNie->rsnIEdata[startPos+1]; //EID + length field + length len -= startPos; }//while @@ -232,7 +236,7 @@ limIsAddieValidInSmeReqMessage(tpAniSirGlobal pMac, tpSirAddie pAddie) if(elem_len > left) { limLog( pMac, LOGE, - FL("****Invalid Add IEs eid = %d elem_len=%d left=%d*****\n"), + FL("****Invalid Add IEs eid = %d elem_len=%d left=%d*****"), elem_id,elem_len,left); return false; } @@ -277,14 +281,14 @@ limSetRSNieWPAiefromSmeStartBSSReqMessage(tpAniSirGlobal pMac, &privacy) != eSIR_SUCCESS) { limLog(pMac, LOGP, - FL("Unable to retrieve POI from CFG\n")); + FL("Unable to retrieve POI from CFG")); } if (wlan_cfgGetInt(pMac, WNI_CFG_RSN_ENABLED, &val) != eSIR_SUCCESS) { limLog(pMac, LOGP, - FL("Unable to retrieve RSN_ENABLED from CFG\n")); + FL("Unable to retrieve RSN_ENABLED from CFG")); } if (pRSNie->length && (!privacy || !val)) @@ -295,7 +299,7 @@ limSetRSNieWPAiefromSmeStartBSSReqMessage(tpAniSirGlobal pMac, * allow BSS creation/join with no Privacy capability * yet advertising WPA IE */ - PELOG1(limLog(pMac, LOG1, FL("RSN ie len %d but PRIVACY %d RSN %d\n"), + PELOG1(limLog(pMac, LOG1, FL("RSN ie len %d but PRIVACY %d RSN %d"), pRSNie->length, privacy, val);) } @@ -304,7 +308,7 @@ limSetRSNieWPAiefromSmeStartBSSReqMessage(tpAniSirGlobal pMac, if ((pRSNie->rsnIEdata[0] != SIR_MAC_RSN_EID) && (pRSNie->rsnIEdata[0] != SIR_MAC_WPA_EID)) { - limLog(pMac, LOGE, FL("RSN/WPA EID %d not [%d || %d]\n"), + limLog(pMac, LOGE, FL("RSN/WPA EID %d not [%d || %d]"), pRSNie->rsnIEdata[0], SIR_MAC_RSN_EID, SIR_MAC_WPA_EID); return false; @@ -317,7 +321,7 @@ limSetRSNieWPAiefromSmeStartBSSReqMessage(tpAniSirGlobal pMac, #endif (pRSNie->rsnIEdata[1] < SIR_MAC_RSN_IE_MIN_LENGTH)) { - limLog(pMac, LOGE, FL("RSN IE len %d not [%d,%d]\n"), + limLog(pMac, LOGE, FL("RSN IE len %d not [%d,%d]"), pRSNie->rsnIEdata[1], SIR_MAC_RSN_IE_MIN_LENGTH, SIR_MAC_RSN_IE_MAX_LENGTH); return false; @@ -329,14 +333,14 @@ limSetRSNieWPAiefromSmeStartBSSReqMessage(tpAniSirGlobal pMac, { limLog(pMac, LOGE, - FL("First byte[%d] in rsnIEdata is not RSN_EID\n"), + FL("First byte[%d] in rsnIEdata is not RSN_EID"), pRSNie->rsnIEdata[1]); return false; } limLog(pMac, LOG1, - FL("WPA IE is present along with WPA2 IE\n")); + FL("WPA IE is present along with WPA2 IE")); wpaIndex = 2 + pRSNie->rsnIEdata[1]; } else if ((pRSNie->length == pRSNie->rsnIEdata[1] + 2) && @@ -344,7 +348,7 @@ limSetRSNieWPAiefromSmeStartBSSReqMessage(tpAniSirGlobal pMac, { limLog(pMac, LOG1, - FL("Only RSN IE is present\n")); + FL("Only RSN IE is present")); dot11fUnpackIeRSN(pMac,&pRSNie->rsnIEdata[2], (tANI_U8)pRSNie->length,&pSessionEntry->gStartBssRSNIe); } @@ -353,7 +357,7 @@ limSetRSNieWPAiefromSmeStartBSSReqMessage(tpAniSirGlobal pMac, { limLog(pMac, LOG1, - FL("Only WPA IE is present\n")); + FL("Only WPA IE is present")); dot11fUnpackIeWPA(pMac,&pRSNie->rsnIEdata[6],(tANI_U8)pRSNie->length-4, &pSessionEntry->gStartBssWPAIe); @@ -372,7 +376,7 @@ limSetRSNieWPAiefromSmeStartBSSReqMessage(tpAniSirGlobal pMac, (SIR_MAC_WPA_OUI != val))) { limLog(pMac, LOGE, - FL("WPA IE len %d not [%d,%d] OR data 0x%x not 0x%x\n"), + FL("WPA IE len %d not [%d,%d] OR data 0x%x not 0x%x"), pRSNie->rsnIEdata[1], SIR_MAC_RSN_IE_MIN_LENGTH, SIR_MAC_RSN_IE_MAX_LENGTH, val, SIR_MAC_WPA_OUI); @@ -471,7 +475,7 @@ limIsSmeStartReqValid(tpAniSirGlobal pMac, tANI_U32 *pMsg) * Log error. */ limLog(pMac, LOGW, - FL("Invalid length %d in eWNI_SME_START_REQ\n"), + FL("Invalid length %d in eWNI_SME_START_REQ"), ((tpSirSmeStartReq) pMsg)->length); valid = false; @@ -512,7 +516,7 @@ limIsSmeStartBssReqValid(tpAniSirGlobal pMac, tANI_U8 valid = true; PELOG1(limLog(pMac, LOG1, - FL("Parsed START_BSS_REQ fields are bssType=%d, channelId=%d, SSID len=%d, rsnIE len=%d, nwType=%d, rateset len=%d\n"), + FL("Parsed START_BSS_REQ fields are bssType=%d, channelId=%d, SSID len=%d, rsnIE len=%d, nwType=%d, rateset len=%d"), pStartBssReq->bssType, pStartBssReq->channelId, pStartBssReq->ssId.length, @@ -557,7 +561,7 @@ limIsSmeStartBssReqValid(tpAniSirGlobal pMac, * Log error */ limLog(pMac, LOGW, - FL("Invalid bssType %d in eWNI_SME_START_BSS_REQ\n"), + FL("Invalid bssType %d in eWNI_SME_START_BSS_REQ"), pStartBssReq->bssType); valid = false; @@ -573,7 +577,7 @@ limIsSmeStartBssReqValid(tpAniSirGlobal pMac, // Invalid length for SSID. // Reject START_BSS_REQ limLog(pMac, LOGW, - FL("Invalid SSID length in eWNI_SME_START_BSS_REQ\n")); + FL("Invalid SSID length in eWNI_SME_START_BSS_REQ")); valid = false; goto end; @@ -603,7 +607,7 @@ limIsSmeStartBssReqValid(tpAniSirGlobal pMac, // Invalid Operational rates // Reject START_BSS_REQ limLog(pMac, LOGW, - FL("Invalid operational rates in eWNI_SME_START_BSS_REQ\n")); + FL("Invalid operational rates in eWNI_SME_START_BSS_REQ")); sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG2, pStartBssReq->operationalRateSet.rate, pStartBssReq->operationalRateSet.numRates); @@ -621,7 +625,7 @@ limIsSmeStartBssReqValid(tpAniSirGlobal pMac, // Invalid Operational rates // Reject START_BSS_REQ limLog(pMac, LOGW, - FL("Invalid operational rates in eWNI_SME_START_BSS_REQ\n")); + FL("Invalid operational rates in eWNI_SME_START_BSS_REQ")); sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG2, pStartBssReq->operationalRateSet.rate, pStartBssReq->operationalRateSet.numRates); @@ -638,7 +642,7 @@ limIsSmeStartBssReqValid(tpAniSirGlobal pMac, // Invalid Operational rates // Reject START_BSS_REQ limLog(pMac, LOGW, - FL("Invalid operational rates in eWNI_SME_START_BSS_REQ\n")); + FL("Invalid operational rates in eWNI_SME_START_BSS_REQ")); sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG2, pStartBssReq->operationalRateSet.rate, pStartBssReq->operationalRateSet.numRates); @@ -683,7 +687,7 @@ limIsSmeJoinReqValid(tpAniSirGlobal pMac, tpSirSmeJoinReq pJoinReq) if (!limIsRSNieValidInSmeReqMessage(pMac, &pJoinReq->rsnIE)) { limLog(pMac, LOGE, - FL("received SME_JOIN_REQ with invalid RSNIE\n")); + FL("received SME_JOIN_REQ with invalid RSNIE")); valid = false; goto end; } @@ -691,7 +695,7 @@ limIsSmeJoinReqValid(tpAniSirGlobal pMac, tpSirSmeJoinReq pJoinReq) if (!limIsAddieValidInSmeReqMessage(pMac, &pJoinReq->addIEScan)) { limLog(pMac, LOGE, - FL("received SME_JOIN_REQ with invalid additional IE for scan\n")); + FL("received SME_JOIN_REQ with invalid additional IE for scan")); valid = false; goto end; } @@ -699,7 +703,7 @@ limIsSmeJoinReqValid(tpAniSirGlobal pMac, tpSirSmeJoinReq pJoinReq) if (!limIsAddieValidInSmeReqMessage(pMac, &pJoinReq->addIEAssoc)) { limLog(pMac, LOGE, - FL("received SME_JOIN_REQ with invalid additional IE for assoc\n")); + FL("received SME_JOIN_REQ with invalid additional IE for assoc")); valid = false; goto end; } @@ -711,7 +715,7 @@ limIsSmeJoinReqValid(tpAniSirGlobal pMac, tpSirSmeJoinReq pJoinReq) /// Received eWNI_SME_JOIN_REQ with invalid BSS Info // Log the event limLog(pMac, LOGE, - FL("received SME_JOIN_REQ with invalid bssInfo\n")); + FL("received SME_JOIN_REQ with invalid bssInfo")); valid = false; goto end; @@ -727,7 +731,7 @@ limIsSmeJoinReqValid(tpAniSirGlobal pMac, tpSirSmeJoinReq pJoinReq) { // Log the event limLog(pMac, LOGE, - FL("received SME_JOIN_REQ with Self Mac and BSSID Same\n")); + FL("received SME_JOIN_REQ with Self Mac and BSSID Same")); valid = false; goto end; @@ -888,7 +892,7 @@ limIsSmeScanReqValid(tpAniSirGlobal pMac, tpSirSmeScanReq pScanReq) if ((pScanReq->scanType == eSIR_ACTIVE_SCAN) && (pScanReq->maxChannelTime < pScanReq->minChannelTime)) { - PELOGW(limLog(pMac, LOGW, FL("Max Channel Time < Min Channel Time\n"));) + PELOGW(limLog(pMac, LOGW, FL("Max Channel Time < Min Channel Time"));) valid = false; goto end; } @@ -976,7 +980,7 @@ limIsSmeSetContextReqValid(tpAniSirGlobal pMac, tpSirSmeSetContextReq pSetConte * Log error. */ limLog(pMac, LOGW, - FL("No keys present in SME_SETCONTEXT_REQ for edType=%d\n"), + FL("No keys present in SME_SETCONTEXT_REQ for edType=%d"), pSetContextReq->keyMaterial.edType); valid = false; @@ -991,7 +995,7 @@ limIsSmeSetContextReqValid(tpAniSirGlobal pMac, tpSirSmeSetContextReq pSetConte * Log error. */ limLog(pMac, LOGW, - FL("Keys present in SME_SETCONTEXT_REQ for edType=%d\n"), + FL("Keys present in SME_SETCONTEXT_REQ for edType=%d"), pSetContextReq->keyMaterial.edType); valid = false; @@ -1005,7 +1009,7 @@ limIsSmeSetContextReqValid(tpAniSirGlobal pMac, tpSirSmeSetContextReq pSetConte * Log error. */ limLog(pMac, LOGW, - FL("Invalid edType=%d in SME_SETCONTEXT_REQ\n"), + FL("Invalid edType=%d in SME_SETCONTEXT_REQ"), pSetContextReq->keyMaterial.edType); valid = false; @@ -1019,7 +1023,7 @@ limIsSmeSetContextReqValid(tpAniSirGlobal pMac, tpSirSmeSetContextReq pSetConte &poi) != eSIR_SUCCESS) { limLog(pMac, LOGP, - FL("Unable to retrieve POI from CFG\n")); + FL("Unable to retrieve POI from CFG")); } if (!poi) @@ -1031,7 +1035,7 @@ limIsSmeSetContextReqValid(tpAniSirGlobal pMac, tpSirSmeSetContextReq pSetConte * yet advertising WPA IE */ PELOG1(limLog(pMac, LOG1, - FL("Privacy is not enabled, yet non-None EDtype=%d in SME_SETCONTEXT_REQ\n"), + FL("Privacy is not enabled, yet non-None EDtype=%d in SME_SETCONTEXT_REQ"), pSetContextReq->keyMaterial.edType);) } } @@ -1056,7 +1060,7 @@ limIsSmeSetContextReqValid(tpAniSirGlobal pMac, tpSirSmeSetContextReq pSetConte * Log error. */ limLog(pMac, LOGW, - FL("Invalid keyLength =%d for edType=%d in SME_SETCONTEXT_REQ\n"), + FL("Invalid keyLength =%d for edType=%d in SME_SETCONTEXT_REQ"), pKey->keyLength, pSetContextReq->keyMaterial.edType); valid = false; diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limStaHashApi.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limStaHashApi.c index 3027cb74fa8..7e1920894cb 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limStaHashApi.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limStaHashApi.c @@ -19,28 +19,6 @@ * PERFORMANCE OF THIS SOFTWARE. */ /* - * Copyright (c) 2012, The Linux Foundation. All rights reserved. - * - * Previously licensed under the ISC license by Qualcomm Atheros, Inc. - * - * - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all - * copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * * Airgo Networks, Inc proprietary. All rights reserved. * limStaHashApi.c: Provides access functions to get/set values of station hash entry fields. * Author: Sunit Bhatia @@ -82,7 +60,7 @@ tSirRetStatus limGetStaHashBssidx(tpAniSirGlobal pMac, tANI_U16 assocId, tANI_U8 if (pSta == NULL) { - PELOGE(limLog(pMac, LOGE, FL("invalid STA %d\n"), assocId);) + PELOGE(limLog(pMac, LOGE, FL("invalid STA %d"), assocId);) return eSIR_LIM_INVALID_STA; } diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limTimerUtils.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limTimerUtils.c index f5b630bc227..08dffa04000 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limTimerUtils.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limTimerUtils.c @@ -102,7 +102,7 @@ limCreateTimers(tpAniSirGlobal pMac) { tANI_U32 cfgValue, i=0; - PELOG1(limLog(pMac, LOG1, FL("Creating Timers used by LIM module in Role %d\n"), pMac->lim.gLimSystemRole);) + PELOG1(limLog(pMac, LOG1, FL("Creating Timers used by LIM module in Role %d"), pMac->lim.gLimSystemRole);) if (wlan_cfgGetInt(pMac, WNI_CFG_ACTIVE_MINIMUM_CHANNEL_TIME, &cfgValue) != eSIR_SUCCESS) @@ -111,7 +111,7 @@ limCreateTimers(tpAniSirGlobal pMac) * Could not get MinChannelTimeout value * from CFG. Log error. */ - limLog(pMac, LOGP, FL("could not retrieve MinChannelTimeout value\n")); + limLog(pMac, LOGP, FL("could not retrieve MinChannelTimeout value")); } cfgValue = SYS_MS_TO_TICKS(cfgValue); @@ -124,10 +124,10 @@ limCreateTimers(tpAniSirGlobal pMac) { /// Could not start min channel timer. // Log error - limLog(pMac, LOGP, FL("could not create MIN channel timer\n")); + limLog(pMac, LOGP, FL("could not create MIN channel timer")); return TX_TIMER_ERROR; } - PELOG2(limLog(pMac, LOG2, FL("Created MinChannelTimer\n"));) + PELOG2(limLog(pMac, LOG2, FL("Created MinChannelTimer"));) /* Periodic probe request timer value is half of the Min channel * timer. Probe request sends periodically till min/max channel @@ -146,7 +146,7 @@ limCreateTimers(tpAniSirGlobal pMac) { /// Could not start Periodic Probe Req timer. // Log error - limLog(pMac, LOGP, FL("could not create periodic probe timer\n")); + limLog(pMac, LOGP, FL("could not create periodic probe timer")); goto err_timer; } } @@ -160,7 +160,7 @@ limCreateTimers(tpAniSirGlobal pMac) * from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve MAXChannelTimeout value\n")); + FL("could not retrieve MAXChannelTimeout value")); } cfgValue = SYS_MS_TO_TICKS(cfgValue); @@ -172,11 +172,11 @@ limCreateTimers(tpAniSirGlobal pMac) { /// Could not start max channel timer. // Log error - limLog(pMac, LOGP, FL("could not create MAX channel timer\n")); + limLog(pMac, LOGP, FL("could not create MAX channel timer")); goto err_timer; } - PELOG2(limLog(pMac, LOG2, FL("Created MaxChannelTimer\n"));) + PELOG2(limLog(pMac, LOG2, FL("Created MaxChannelTimer"));) if (pMac->lim.gLimSystemRole != eLIM_AP_ROLE) { @@ -189,7 +189,7 @@ limCreateTimers(tpAniSirGlobal pMac) 0, // reschedule_ticks TX_NO_ACTIVATE) != TX_SUCCESS) { - limLog(pMac, LOGP, FL("failed to create Channel Switch timer\n")); + limLog(pMac, LOGP, FL("failed to create Channel Switch timer")); goto err_timer; } @@ -206,7 +206,7 @@ limCreateTimers(tpAniSirGlobal pMac) 0, // reschedule_ticks TX_NO_ACTIVATE) != TX_SUCCESS) { - limLog(pMac, LOGP, FL("failed to create Quiet Begin Timer\n")); + limLog(pMac, LOGP, FL("failed to create Quiet Begin Timer")); goto err_timer; } @@ -225,7 +225,7 @@ limCreateTimers(tpAniSirGlobal pMac) 0, // reschedule_ticks TX_NO_ACTIVATE) != TX_SUCCESS) { - limLog(pMac, LOGP, FL("failed to create Quiet Begin Timer\n")); + limLog(pMac, LOGP, FL("failed to create Quiet Begin Timer")); goto err_timer; } @@ -237,7 +237,7 @@ limCreateTimers(tpAniSirGlobal pMac) * from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve JoinFailureTimeout value\n")); + FL("could not retrieve JoinFailureTimeout value")); } cfgValue = SYS_MS_TO_TICKS(cfgValue); @@ -250,7 +250,7 @@ limCreateTimers(tpAniSirGlobal pMac) { /// Could not create Join failure timer. // Log error - limLog(pMac, LOGP, FL("could not create Join failure timer\n")); + limLog(pMac, LOGP, FL("could not create Join failure timer")); goto err_timer; } @@ -264,7 +264,7 @@ limCreateTimers(tpAniSirGlobal pMac) { /// Could not create Periodic Join Probe Request timer. // Log error - limLog(pMac, LOGP, FL("could not create Periodic Join Probe Request timer\n")); + limLog(pMac, LOGP, FL("could not create Periodic Join Probe Request timer")); goto err_timer; } @@ -276,7 +276,7 @@ limCreateTimers(tpAniSirGlobal pMac) * from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve AssocFailureTimeout value\n")); + FL("could not retrieve AssocFailureTimeout value")); } cfgValue = SYS_MS_TO_TICKS(cfgValue); @@ -290,7 +290,7 @@ limCreateTimers(tpAniSirGlobal pMac) /// Could not create Assoc failure timer. // Log error limLog(pMac, LOGP, - FL("could not create Association failure timer\n")); + FL("could not create Association failure timer")); goto err_timer; } @@ -302,7 +302,7 @@ limCreateTimers(tpAniSirGlobal pMac) * from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve ReassocFailureTimeout value\n")); + FL("could not retrieve ReassocFailureTimeout value")); } cfgValue = SYS_MS_TO_TICKS(cfgValue); @@ -316,13 +316,13 @@ limCreateTimers(tpAniSirGlobal pMac) /// Could not create Reassoc failure timer. // Log error limLog(pMac, LOGP, - FL("could not create Reassociation failure timer\n")); + FL("could not create Reassociation failure timer")); goto err_timer; } if (wlan_cfgGetInt(pMac, WNI_CFG_ADDTS_RSP_TIMEOUT, &cfgValue) != eSIR_SUCCESS) - limLog(pMac, LOGP, FL("Fail to get WNI_CFG_ADDTS_RSP_TIMEOUT \n")); + limLog(pMac, LOGP, FL("Fail to get WNI_CFG_ADDTS_RSP_TIMEOUT ")); cfgValue = SYS_MS_TO_TICKS(cfgValue); @@ -336,7 +336,7 @@ limCreateTimers(tpAniSirGlobal pMac) { /// Could not create Auth failure timer. // Log error - limLog(pMac, LOGP, FL("could not create Addts response timer\n")); + limLog(pMac, LOGP, FL("could not create Addts response timer")); goto err_timer; } @@ -349,7 +349,7 @@ limCreateTimers(tpAniSirGlobal pMac) * from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve AuthFailureTimeout value\n")); + FL("could not retrieve AuthFailureTimeout value")); } cfgValue = SYS_MS_TO_TICKS(cfgValue); @@ -363,7 +363,7 @@ limCreateTimers(tpAniSirGlobal pMac) { /// Could not create Auth failure timer. // Log error - limLog(pMac, LOGP, FL("could not create Auth failure timer\n")); + limLog(pMac, LOGP, FL("could not create Auth failure timer")); goto err_timer; } @@ -376,7 +376,7 @@ limCreateTimers(tpAniSirGlobal pMac) * from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve BEACON_INTERVAL value\n")); + FL("could not retrieve BEACON_INTERVAL value")); } cfgValue = SYS_MS_TO_TICKS(cfgValue); @@ -391,7 +391,7 @@ limCreateTimers(tpAniSirGlobal pMac) /// Could not start Heartbeat timer. // Log error limLog(pMac, LOGP, - FL("call to create heartbeat timer failed\n")); + FL("call to create heartbeat timer failed")); goto err_timer; } @@ -403,7 +403,7 @@ limCreateTimers(tpAniSirGlobal pMac) * value from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve PROBE_AFTER_HB_FAIL_TIMEOUT value\n")); + FL("could not retrieve PROBE_AFTER_HB_FAIL_TIMEOUT value")); } // Change timer to reactivate it in future @@ -420,7 +420,7 @@ limCreateTimers(tpAniSirGlobal pMac) // Could not creat wt-probe-after-HeartBeat-failure timer. // Log error limLog(pMac, LOGP, - FL("unable to create ProbeAfterHBTimer\n")); + FL("unable to create ProbeAfterHBTimer")); goto err_timer; } @@ -432,7 +432,7 @@ limCreateTimers(tpAniSirGlobal pMac) * from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve Background scan period value\n")); + FL("could not retrieve Background scan period value")); } /* @@ -462,7 +462,7 @@ limCreateTimers(tpAniSirGlobal pMac) /// Could not start background scan timer. // Log error limLog(pMac, LOGP, - FL("call to create background scan timer failed\n")); + FL("call to create background scan timer failed")); goto err_timer; } #ifdef FEATURE_WLAN_TDLS_INTERNAL @@ -479,7 +479,7 @@ limCreateTimers(tpAniSirGlobal pMac) * from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve ReassocFailureTimeout value\n")); + FL("could not retrieve ReassocFailureTimeout value")); } cfgValue = SYS_MS_TO_TICKS(cfgValue); @@ -494,7 +494,7 @@ limCreateTimers(tpAniSirGlobal pMac) TX_NO_ACTIVATE) != TX_SUCCESS) { limLog(pMac, LOGP, - FL("could not create TDLS discovery response wait timer\n")); + FL("could not create TDLS discovery response wait timer")); goto err_timer; } #endif @@ -515,11 +515,11 @@ limCreateTimers(tpAniSirGlobal pMac) /// Could not start Send Disassociate Frame Threshold timer. // Log error limLog(pMac, LOGP, - FL("create Disassociate throttle timer failed\n")); + FL("create Disassociate throttle timer failed")); goto err_timer; } PELOG1(limLog(pMac, LOG1, - FL("Created Disassociate throttle timer \n"));) + FL("Created Disassociate throttle timer "));) /** * Create keepalive timer and activate it right away for AP role @@ -533,7 +533,7 @@ limCreateTimers(tpAniSirGlobal pMac) * from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve keepalive timeout value\n")); + FL("could not retrieve keepalive timeout value")); } // A value of zero implies keep alive should be disabled @@ -558,7 +558,7 @@ limCreateTimers(tpAniSirGlobal pMac) != TX_SUCCESS) { // Cannot create keepalive timer. Log error. - limLog(pMac, LOGP, FL("Cannot create keepalive timer.\n")); + limLog(pMac, LOGP, FL("Cannot create keepalive timer.")); goto err_timer; } @@ -574,7 +574,7 @@ limCreateTimers(tpAniSirGlobal pMac) * from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve CNF timeout value\n")); + FL("could not retrieve CNF timeout value")); } cfgValue = SYS_MS_TO_TICKS(cfgValue); @@ -589,7 +589,7 @@ limCreateTimers(tpAniSirGlobal pMac) TX_NO_ACTIVATE) != TX_SUCCESS) { // Cannot create timer. Log error. - limLog(pMac, LOGP, FL("Cannot create CNF wait timer.\n")); + limLog(pMac, LOGP, FL("Cannot create CNF wait timer.")); goto err_timer; } } @@ -608,18 +608,18 @@ limCreateTimers(tpAniSirGlobal pMac) ** from CFG. Log error. **/ limLog(pMac, LOGP, - FL("could not retrieve mac preauth value\n")); + FL("could not retrieve mac preauth value")); } pMac->lim.gLimPreAuthTimerTable.numEntry = cfgValue; if (palAllocateMemory(pMac->hHdd, (void **) &pMac->lim.gLimPreAuthTimerTable.pTable, cfgValue*sizeof(tLimPreAuthNode)) != eHAL_STATUS_SUCCESS) { - limLog(pMac, LOGP, FL("palAllocateMemory failed!\n")); + limLog(pMac, LOGP, FL("palAllocateMemory failed!")); goto err_timer; } limInitPreAuthTimerTable(pMac, &pMac->lim.gLimPreAuthTimerTable); - PELOG1(limLog(pMac, LOG1, FL("alloc and init table for preAuth timers\n"));) + PELOG1(limLog(pMac, LOG1, FL("alloc and init table for preAuth timers"));) { @@ -634,7 +634,7 @@ limCreateTimers(tpAniSirGlobal pMac) * from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve OLBD detect timeout value\n")); + FL("could not retrieve OLBD detect timeout value")); } cfgValue = SYS_MS_TO_TICKS(cfgValue); @@ -650,7 +650,7 @@ limCreateTimers(tpAniSirGlobal pMac) { // Cannot create update OLBC cache timer // Log error - limLog(pMac, LOGP, FL("Cannot create update OLBC cache timer\n")); + limLog(pMac, LOGP, FL("Cannot create update OLBC cache timer")); goto err_timer; } } @@ -670,7 +670,7 @@ limCreateTimers(tpAniSirGlobal pMac) { // Could not create Join failure timer. // Log error - limLog(pMac, LOGP, FL("could not create Join failure timer\n")); + limLog(pMac, LOGP, FL("could not create Join failure timer")); goto err_timer; } #endif @@ -687,7 +687,7 @@ limCreateTimers(tpAniSirGlobal pMac) { // Could not create Join failure timer. // Log error - limLog(pMac, LOGP, FL("could not create Join failure timer\n")); + limLog(pMac, LOGP, FL("could not create Join failure timer")); goto err_timer; } #endif @@ -702,7 +702,7 @@ limCreateTimers(tpAniSirGlobal pMac) { // Could not create Join failure timer. // Log error - limLog(pMac, LOGP, FL("could not create Join failure timer\n")); + limLog(pMac, LOGP, FL("could not create Join failure timer")); goto err_timer; } @@ -715,7 +715,7 @@ limCreateTimers(tpAniSirGlobal pMac) cfgValue, 0, TX_NO_ACTIVATE) != TX_SUCCESS) { - limLog(pMac, LOGP, FL("could not DISASSOC ACK TIMEOUT timer\n")); + limLog(pMac, LOGP, FL("could not DISASSOC ACK TIMEOUT timer")); goto err_timer; } @@ -727,7 +727,7 @@ limCreateTimers(tpAniSirGlobal pMac) cfgValue, 0, TX_NO_ACTIVATE) != TX_SUCCESS) { - limLog(pMac, LOGP, FL("could not create DEAUTH ACK TIMEOUT timer\n")); + limLog(pMac, LOGP, FL("could not create DEAUTH ACK TIMEOUT timer")); goto err_timer; } @@ -739,7 +739,7 @@ limCreateTimers(tpAniSirGlobal pMac) cfgValue, 0, TX_NO_ACTIVATE) != TX_SUCCESS) { - limLog(pMac, LOGP, FL("could not create Single Shot NOA Insert Timeout timer\n")); + limLog(pMac, LOGP, FL("could not create Single Shot NOA Insert Timeout timer")); goto err_timer; } @@ -840,7 +840,7 @@ limTimerHandler(void *pMacGlobal, tANI_U32 param) if ((statusCode = limPostMsgApi(pMac, &msg)) != eSIR_SUCCESS) limLog(pMac, LOGE, - FL("posting message %X to LIM failed, reason=%d\n"), + FL("posting message %X to LIM failed, reason=%d"), msg.type, statusCode); } /****** end limTimerHandler() ******/ @@ -952,17 +952,17 @@ limAssocFailureTimerHandler(void *pMacGlobal, tANI_U32 param) if((LIM_REASSOC == param) && (NULL != pMac->lim.pSessionEntry)) { - limLog(pMac, LOGE, FL("Reassoc timeout happened\n")); + limLog(pMac, LOGE, FL("Reassoc timeout happened")); if(pMac->lim.reAssocRetryAttempt < LIM_MAX_REASSOC_RETRY_LIMIT) { limSendRetryReassocReqFrame(pMac, pMac->lim.pSessionEntry->pLimMlmReassocRetryReq, pMac->lim.pSessionEntry); pMac->lim.reAssocRetryAttempt++; - limLog(pMac, LOGW, FL("Reassoc request retry is sent %d times\n"), pMac->lim.reAssocRetryAttempt); + limLog(pMac, LOGW, FL("Reassoc request retry is sent %d times"), pMac->lim.reAssocRetryAttempt); return; } else { - limLog(pMac, LOGW, FL("Reassoc request retry MAX(%d) reached\n"), LIM_MAX_REASSOC_RETRY_LIMIT); + limLog(pMac, LOGW, FL("Reassoc request retry MAX(%d) reached"), LIM_MAX_REASSOC_RETRY_LIMIT); if(NULL != pMac->lim.pSessionEntry->pLimMlmReassocRetryReq) { palFreeMemory( pMac->hHdd, pMac->lim.pSessionEntry->pLimMlmReassocRetryReq); @@ -1055,7 +1055,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) // Could not deactivate AddtsRsp Timer // Log error limLog(pMac, LOGP, - FL("Unable to deactivate AddtsRsp timer\n")); + FL("Unable to deactivate AddtsRsp timer")); } break; @@ -1066,7 +1066,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) // Could not deactivate min channel timer. // Log error limLog(pMac, LOGP, - FL("Unable to deactivate min channel timer\n")); + FL("Unable to deactivate min channel timer")); } #if 0 @@ -1115,7 +1115,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) { // Could not change min channel timer. // Log error - limLog(pMac, LOGP, FL("Unable to change min channel timer\n")); + limLog(pMac, LOGP, FL("Unable to change min channel timer")); } break; @@ -1127,7 +1127,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) // Could not deactivate min channel timer. // Log error limLog(pMac, LOGP, - FL("Unable to deactivate periodic timer\n")); + FL("Unable to deactivate periodic timer")); } val = SYS_MS_TO_TICKS(pMac->lim.gpLimMlmScanReq->minChannelTime)/2; @@ -1147,7 +1147,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) { // Could not change min channel timer. // Log error - limLog(pMac, LOGP, FL("Unable to change periodic timer\n")); + limLog(pMac, LOGP, FL("Unable to change periodic timer")); } break; @@ -1159,7 +1159,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) // Could not deactivate max channel timer. // Log error limLog(pMac, LOGP, - FL("Unable to deactivate max channel timer\n")); + FL("Unable to deactivate max channel timer")); } // If a background was triggered via Quiet BSS, @@ -1213,7 +1213,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) // Could not change max channel timer. // Log error limLog(pMac, LOGP, - FL("Unable to change max channel timer\n")); + FL("Unable to change max channel timer")); } break; @@ -1227,7 +1227,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) * timer. Log error. */ limLog(pMac, LOGP, - FL("Unable to deactivate Join Failure timer\n")); + FL("Unable to deactivate Join Failure timer")); } if (wlan_cfgGetInt(pMac, WNI_CFG_JOIN_FAILURE_TIMEOUT, @@ -1238,7 +1238,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) * from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve JoinFailureTimeout value\n")); + FL("could not retrieve JoinFailureTimeout value")); } val = SYS_MS_TO_TICKS(val); @@ -1250,7 +1250,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) * timer. Log error. */ limLog(pMac, LOGP, - FL("Unable to change Join Failure timer\n")); + FL("Unable to change Join Failure timer")); } break; @@ -1261,7 +1261,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) { // Could not deactivate periodic join req Times. limLog(pMac, LOGP, - FL("Unable to deactivate periodic join request timer\n")); + FL("Unable to deactivate periodic join request timer")); } val = SYS_MS_TO_TICKS(LIM_JOIN_PROBE_REQ_TIMER_MS); @@ -1270,7 +1270,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) { // Could not change periodic join req times. // Log error - limLog(pMac, LOGP, FL("Unable to change periodic join request timer\n")); + limLog(pMac, LOGP, FL("Unable to change periodic join request timer")); } break; @@ -1282,7 +1282,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) // Could not deactivate Auth failure timer. // Log error limLog(pMac, LOGP, - FL("Unable to deactivate auth failure timer\n")); + FL("Unable to deactivate auth failure timer")); } // Change timer to reactivate it in future @@ -1294,7 +1294,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) * from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve AuthFailureTimeout value\n")); + FL("could not retrieve AuthFailureTimeout value")); } val = SYS_MS_TO_TICKS(val); @@ -1304,7 +1304,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) // Could not change Authentication failure timer. // Log error limLog(pMac, LOGP, - FL("unable to change Auth failure timer\n")); + FL("unable to change Auth failure timer")); } break; @@ -1316,7 +1316,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) // Could not deactivate Association failure timer. // Log error limLog(pMac, LOGP, - FL("unable to deactivate Association failure timer\n")); + FL("unable to deactivate Association failure timer")); } // Change timer to reactivate it in future @@ -1328,7 +1328,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) * from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve AssocFailureTimeout value\n")); + FL("could not retrieve AssocFailureTimeout value")); } val = SYS_MS_TO_TICKS(val); @@ -1338,7 +1338,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) // Could not change Association failure timer. // Log error limLog(pMac, LOGP, - FL("unable to change Assoc failure timer\n")); + FL("unable to change Assoc failure timer")); } break; @@ -1350,7 +1350,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) // Could not deactivate Reassociation failure timer. // Log error limLog(pMac, LOGP, - FL("unable to deactivate Reassoc failure timer\n")); + FL("unable to deactivate Reassoc failure timer")); } // Change timer to reactivate it in future @@ -1362,7 +1362,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) * from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve ReassocFailureTimeout value\n")); + FL("could not retrieve ReassocFailureTimeout value")); } val = SYS_MS_TO_TICKS(val); @@ -1372,7 +1372,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) // Could not change Reassociation failure timer. // Log error limLog(pMac, LOGP, - FL("unable to change Reassociation failure timer\n")); + FL("unable to change Reassociation failure timer")); } break; @@ -1384,7 +1384,11 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) // Could not deactivate Heartbeat timer. // Log error limLog(pMac, LOGP, - FL("unable to deactivate Heartbeat timer\n")); + FL("unable to deactivate Heartbeat timer")); + } + else + { + limLog(pMac, LOGW, FL("Deactivated heartbeat link monitoring")); } if (wlan_cfgGetInt(pMac, WNI_CFG_BEACON_INTERVAL, @@ -1395,13 +1399,13 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) * from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve BEACON_INTERVAL value\n")); + FL("could not retrieve BEACON_INTERVAL value")); } if (wlan_cfgGetInt(pMac, WNI_CFG_HEART_BEAT_THRESHOLD, &val1) != eSIR_SUCCESS) limLog(pMac, LOGP, - FL("could not retrieve heartbeat failure value\n")); + FL("could not retrieve heartbeat failure value")); // Change timer to reactivate it in future val = SYS_MS_TO_TICKS(val * val1); @@ -1412,9 +1416,12 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) // Could not change HeartBeat timer. // Log error limLog(pMac, LOGP, - FL("unable to change HeartBeat timer\n")); + FL("unable to change HeartBeat timer")); + } + else + { + limLog(pMac, LOGW, FL("HeartBeat timer value is changed = %lu"), val); } - break; case eLIM_PROBE_AFTER_HB_TIMER: @@ -1424,7 +1431,11 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) // Could not deactivate Heartbeat timer. // Log error limLog(pMac, LOGP, - FL("unable to deactivate probeAfterHBTimer\n")); + FL("unable to deactivate probeAfterHBTimer")); + } + else + { + limLog(pMac, LOGE, FL("Deactivated probe after hb timer")); } if (wlan_cfgGetInt(pMac, WNI_CFG_PROBE_AFTER_HB_FAIL_TIMEOUT, @@ -1435,7 +1446,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) * value from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve PROBE_AFTER_HB_FAIL_TIMEOUT value\n")); + FL("could not retrieve PROBE_AFTER_HB_FAIL_TIMEOUT value")); } // Change timer to reactivate it in future @@ -1447,7 +1458,11 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) // Could not change HeartBeat timer. // Log error limLog(pMac, LOGP, - FL("unable to change ProbeAfterHBTimer\n")); + FL("unable to change ProbeAfterHBTimer")); + } + else + { + limLog(pMac, LOGW, FL("Probe after HB timer value is changed = %lu"), val); } break; @@ -1459,7 +1474,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) // Could not deactivate Keepalive timer. // Log error limLog(pMac, LOGP, - FL("unable to deactivate KeepaliveTimer timer\n")); + FL("unable to deactivate KeepaliveTimer timer")); } // Change timer to reactivate it in future @@ -1472,7 +1487,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) * from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve keepalive timeout value\n")); + FL("could not retrieve keepalive timeout value")); } if (val == 0) { @@ -1491,7 +1506,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) // Could not change KeepaliveTimer timer. // Log error limLog(pMac, LOGP, - FL("unable to change KeepaliveTimer timer\n")); + FL("unable to change KeepaliveTimer timer")); } break; @@ -1503,7 +1518,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) // Could not deactivate BackgroundScanTimer timer. // Log error limLog(pMac, LOGP, - FL("unable to deactivate BackgroundScanTimer timer\n")); + FL("unable to deactivate BackgroundScanTimer timer")); } // Change timer to reactivate it in future @@ -1515,7 +1530,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) * from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve Background scan period value\n")); + FL("could not retrieve Background scan period value")); } if (val == 0) { @@ -1533,7 +1548,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) // Could not change BackgroundScanTimer timer. // Log error limLog(pMac, LOGP, - FL("unable to change BackgroundScanTimer timer\n")); + FL("unable to change BackgroundScanTimer timer")); } break; @@ -1542,7 +1557,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) case eLIM_CHANNEL_SWITCH_TIMER: if (tx_timer_deactivate(&pMac->lim.limTimers.gLimChannelSwitchTimer) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("tx_timer_deactivate failed!\n")); + limLog(pMac, LOGP, FL("tx_timer_deactivate failed!")); return; } @@ -1550,7 +1565,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) pMac->lim.gLimChannelSwitch.switchTimeoutValue, 0) != TX_SUCCESS) { - limLog(pMac, LOGP, FL("tx_timer_change failed \n")); + limLog(pMac, LOGP, FL("tx_timer_change failed ")); return; } break; @@ -1565,7 +1580,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) tx_timer_deactivate(&pMac->lim.limTimers.gLimQuietBssTimer)) { limLog( pMac, LOGE, - FL("Unable to de-activate gLimQuietBssTimer! Will attempt to activate anyway...\n")); + FL("Unable to de-activate gLimQuietBssTimer! Will attempt to activate anyway...")); } // gLimQuietDuration appears to be in units of ticks @@ -1576,7 +1591,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) 0)) { limLog( pMac, LOGE, - FL("Unable to change gLimQuietBssTimer! Will still attempt to activate anyway...\n")); + FL("Unable to change gLimQuietBssTimer! Will still attempt to activate anyway...")); } break; @@ -1584,7 +1599,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) if( TX_SUCCESS != tx_timer_deactivate(&pMac->lim.limTimers.gLimQuietTimer)) { limLog( pMac, LOGE, - FL( "Unable to deactivate gLimQuietTimer! Will still attempt to re-activate anyway...\n" )); + FL( "Unable to deactivate gLimQuietTimer! Will still attempt to re-activate anyway..." )); } // Set the NEW timeout value, in ticks @@ -1592,7 +1607,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) SYS_MS_TO_TICKS(pMac->lim.gLimSpecMgmt.quietTimeoutValue), 0)) { limLog( pMac, LOGE, - FL( "Unable to change gLimQuietTimer! Will still attempt to re-activate anyway...\n" )); + FL( "Unable to change gLimQuietTimer! Will still attempt to re-activate anyway..." )); } break; #endif @@ -1610,7 +1625,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) // Could not deactivate Learn Interval timer. // Log error limLog(pMac, LOGP, - FL("Unable to deactivate WPS overlap timer\n")); + FL("Unable to deactivate WPS overlap timer")); } if (tx_timer_change( @@ -1619,13 +1634,13 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) { // Could not change Learn Interval timer. // Log error - limLog(pMac, LOGP, FL("Unable to change WPS overlap timer\n")); + limLog(pMac, LOGP, FL("Unable to change WPS overlap timer")); return; } limLog( pMac, LOGE, - FL("Setting WPS overlap TIMER to %d ticks\n"), + FL("Setting WPS overlap TIMER to %d ticks"), WPSOverlapTimer); } break; @@ -1639,7 +1654,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) ** Could not deactivate Join Failure ** timer. Log error. **/ - limLog(pMac, LOGP, FL("Unable to deactivate Preauth response Failure timer\n")); + limLog(pMac, LOGP, FL("Unable to deactivate Preauth response Failure timer")); return; } val = 1000; @@ -1651,7 +1666,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) * Could not change Join Failure * timer. Log error. */ - limLog(pMac, LOGP, FL("Unable to change Join Failure timer\n")); + limLog(pMac, LOGP, FL("Unable to change Join Failure timer")); return; } break; @@ -1661,7 +1676,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) if (tx_timer_deactivate(&pMac->lim.limTimers.gLimCcxTsmTimer) != TX_SUCCESS) { - limLog(pMac, LOGE, FL("Unable to deactivate TSM timer\n")); + limLog(pMac, LOGE, FL("Unable to deactivate TSM timer")); } break; #endif @@ -1672,7 +1687,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) ** Could not deactivate Join Failure ** timer. Log error. **/ - limLog(pMac, LOGP, FL("Unable to deactivate Remain on Chn timer\n")); + limLog(pMac, LOGP, FL("Unable to deactivate Remain on Chn timer")); return; } val = 1000; @@ -1684,7 +1699,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) * Could not change Join Failure * timer. Log error. */ - limLog(pMac, LOGP, FL("Unable to change timer\n")); + limLog(pMac, LOGP, FL("Unable to change timer")); return; } break; @@ -1721,7 +1736,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) ** Could not deactivate Join Failure ** timer. Log error. **/ - limLog(pMac, LOGP, FL("Unable to deactivate Disassoc ack timer\n")); + limLog(pMac, LOGP, FL("Unable to deactivate Disassoc ack timer")); return; } val = 1000; @@ -1733,7 +1748,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) * Could not change Join Failure * timer. Log error. */ - limLog(pMac, LOGP, FL("Unable to change timer\n")); + limLog(pMac, LOGP, FL("Unable to change timer")); return; } break; @@ -1745,7 +1760,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) ** Could not deactivate Join Failure ** timer. Log error. **/ - limLog(pMac, LOGP, FL("Unable to deactivate Deauth ack timer\n")); + limLog(pMac, LOGP, FL("Unable to deactivate Deauth ack timer")); return; } val = 1000; @@ -1757,7 +1772,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) * Could not change Join Failure * timer. Log error. */ - limLog(pMac, LOGP, FL("Unable to change timer\n")); + limLog(pMac, LOGP, FL("Unable to change timer")); return; } break; @@ -1769,7 +1784,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) ** Could not deactivate SingleShot NOA Insert ** timer. Log error. **/ - limLog(pMac, LOGP, FL("Unable to deactivate SingleShot NOA Insert timer\n")); + limLog(pMac, LOGP, FL("Unable to deactivate SingleShot NOA Insert timer")); return; } val = LIM_INSERT_SINGLESHOTNOA_TIMEOUT_VALUE; @@ -1781,7 +1796,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) * Could not change Single Shot NOA Insert * timer. Log error. */ - limLog(pMac, LOGP, FL("Unable to change timer\n")); + limLog(pMac, LOGP, FL("Unable to change timer")); return; } break; @@ -1808,6 +1823,10 @@ limHeartBeatDeactivateAndChangeTimer(tpAniSirGlobal pMac, tpPESession psessionEn { tANI_U32 val, val1; + if (NULL == psessionEntry) + { + return; + } MTRACE(macTrace(pMac, TRACE_CODE_TIMER_DEACTIVATE, psessionEntry->peSessionId, eLIM_HEART_BEAT_TIMER)); #ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE if(IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE) @@ -1815,7 +1834,7 @@ limHeartBeatDeactivateAndChangeTimer(tpAniSirGlobal pMac, tpPESession psessionEn #endif if (tx_timer_deactivate(&pMac->lim.limTimers.gLimHeartBeatTimer) != TX_SUCCESS) - limLog(pMac, LOGP, FL("Fail to deactivate HeartBeatTimer \n")); + limLog(pMac, LOGP, FL("Fail to deactivate HeartBeatTimer ")); /* HB Timer sessionisation: In case of 2 or more sessions, the HB interval keeps changing. to avoid this problem, HeartBeat interval is made constant, by @@ -1825,10 +1844,10 @@ limHeartBeatDeactivateAndChangeTimer(tpAniSirGlobal pMac, tpPESession psessionEn val = LIM_HB_TIMER_BEACON_INTERVAL; if (wlan_cfgGetInt(pMac, WNI_CFG_HEART_BEAT_THRESHOLD, &val1) != eSIR_SUCCESS) - limLog(pMac, LOGP, FL("Fail to get WNI_CFG_HEART_BEAT_THRESHOLD \n")); + limLog(pMac, LOGP, FL("Fail to get WNI_CFG_HEART_BEAT_THRESHOLD ")); PELOGW(limLog(pMac,LOGW, - FL("HB Timer Int.=100ms * %d, Beacon Int.=%dms,Session Id=%d \n"), + FL("HB Timer Int.=100ms * %d, Beacon Int.=%dms,Session Id=%d "), val1, psessionEntry->beaconParams.beaconInterval, psessionEntry->peSessionId);) @@ -1836,7 +1855,7 @@ limHeartBeatDeactivateAndChangeTimer(tpAniSirGlobal pMac, tpPESession psessionEn val = SYS_MS_TO_TICKS(val * val1); if (tx_timer_change(&pMac->lim.limTimers.gLimHeartBeatTimer, val, 0) != TX_SUCCESS) - limLog(pMac, LOGP, FL("Fail to change HeartBeatTimer\n")); + limLog(pMac, LOGP, FL("Fail to change HeartBeatTimer")); } /****** end limHeartBeatDeactivateAndChangeTimer() ******/ @@ -1853,11 +1872,14 @@ limHeartBeatDeactivateAndChangeTimer(tpAniSirGlobal pMac, tpPESession psessionEn void limReactivateHeartBeatTimer(tpAniSirGlobal pMac, tpPESession psessionEntry) { - PELOG3(limLog(pMac, LOG3, FL("Rxed Heartbeat. Count=%d\n"), psessionEntry->LimRxedBeaconCntDuringHB);) + PELOG3(limLog(pMac, LOG3, FL("Rxed Heartbeat. Count=%d"), psessionEntry->LimRxedBeaconCntDuringHB);) #ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE if(IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE) + { + limLog(pMac, LOGW, FL("Active offload feature is enabled, FW takes care of HB monitoring")); return; + } #endif limHeartBeatDeactivateAndChangeTimer(pMac, psessionEntry); @@ -1867,8 +1889,9 @@ limReactivateHeartBeatTimer(tpAniSirGlobal pMac, tpPESession psessionEntry) if(pMac->lim.limTimers.gLimHeartBeatTimer.initScheduleTimeInMsecs > 0) { if (tx_timer_activate(&pMac->lim.limTimers.gLimHeartBeatTimer)!= TX_SUCCESS) { - limLog(pMac, LOGP,FL("could not activate Heartbeat timer\n")); + limLog(pMac, LOGP,FL("could not activate Heartbeat timer")); } + limLog(pMac, LOGW, FL("Reactivated heartbeat link monitoring")); limResetHBPktCount(psessionEntry); } @@ -1911,7 +1934,7 @@ v_UINT_t limActivateHearBeatTimer(tpAniSirGlobal pMac) if( TX_SUCCESS != status ) { PELOGE(limLog(pMac, LOGE, - FL("could not activate Heartbeat timer status(%d)\n"), status);) + FL("could not activate Heartbeat timer status(%d)"), status);) } } else @@ -1961,7 +1984,7 @@ limDeactivateAndChangePerStaIdTimer(tpAniSirGlobal pMac, tANI_U32 timerId, tANI_ != TX_SUCCESS) { limLog(pMac, LOGP, - FL("unable to deactivate CNF wait timer\n")); + FL("unable to deactivate CNF wait timer")); } @@ -1975,7 +1998,7 @@ limDeactivateAndChangePerStaIdTimer(tpAniSirGlobal pMac, tANI_U32 timerId, tANI_ * from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve cnf timeout value\n")); + FL("could not retrieve cnf timeout value")); } val = SYS_MS_TO_TICKS(val); @@ -1984,7 +2007,7 @@ limDeactivateAndChangePerStaIdTimer(tpAniSirGlobal pMac, tANI_U32 timerId, tANI_ { // Could not change cnf timer. // Log error - limLog(pMac, LOGP, FL("unable to change cnf wait timer\n")); + limLog(pMac, LOGP, FL("unable to change cnf wait timer")); } break; @@ -1997,7 +2020,7 @@ limDeactivateAndChangePerStaIdTimer(tpAniSirGlobal pMac, tANI_U32 timerId, tANI_ if (pAuthNode == NULL) { - limLog(pMac, LOGP, FL("Invalid Pre Auth Index passed :%d\n"), staId); + limLog(pMac, LOGP, FL("Invalid Pre Auth Index passed :%d"), staId); break; } @@ -2005,7 +2028,7 @@ limDeactivateAndChangePerStaIdTimer(tpAniSirGlobal pMac, tANI_U32 timerId, tANI_ { // Could not deactivate auth response timer. // Log error - limLog(pMac, LOGP, FL("unable to deactivate auth response timer\n")); + limLog(pMac, LOGP, FL("unable to deactivate auth response timer")); } // Change timer to reactivate it in future @@ -2017,7 +2040,7 @@ limDeactivateAndChangePerStaIdTimer(tpAniSirGlobal pMac, tANI_U32 timerId, tANI_ * from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve auth response timeout value\n")); + FL("could not retrieve auth response timeout value")); } val = SYS_MS_TO_TICKS(val); @@ -2026,7 +2049,7 @@ limDeactivateAndChangePerStaIdTimer(tpAniSirGlobal pMac, tANI_U32 timerId, tANI_ { // Could not change auth rsp timer. // Log error - limLog(pMac, LOGP, FL("unable to change auth rsp timer\n")); + limLog(pMac, LOGP, FL("unable to change auth rsp timer")); } } break; @@ -2068,7 +2091,7 @@ void limActivateCnfTimer(tpAniSirGlobal pMac, tANI_U16 staId, tpPESession psessi != TX_SUCCESS) { limLog(pMac, LOGP, - FL("could not activate cnf wait timer\n")); + FL("could not activate cnf wait timer")); } } @@ -2100,7 +2123,7 @@ void limActivateAuthRspTimer(tpAniSirGlobal pMac, tLimPreAuthNode *pAuthNode) /// Could not activate auth rsp timer. // Log error limLog(pMac, LOGP, - FL("could not activate auth rsp timer\n")); + FL("could not activate auth rsp timer")); } } @@ -2136,7 +2159,7 @@ limSendDisassocFrameThresholdHandler(void *pMacGlobal, tANI_U32 param) if ((statusCode = limPostMsgApi(pMac, &msg)) != eSIR_SUCCESS) limLog(pMac, LOGE, - FL("posting to LIM failed, reason=%d\n"), statusCode); + FL("posting to LIM failed, reason=%d"), statusCode); } @@ -2171,7 +2194,7 @@ limCnfWaitTmerHandler(void *pMacGlobal, tANI_U32 param) if ((statusCode = limPostMsgApi(pMac, &msg)) != eSIR_SUCCESS) limLog(pMac, LOGE, - FL("posting to LIM failed, reason=%d\n"), statusCode); + FL("posting to LIM failed, reason=%d"), statusCode); } @@ -2206,7 +2229,7 @@ limKeepaliveTmerHandler(void *pMacGlobal, tANI_U32 param) if ((statusCode = limPostMsgApi(pMac, &msg)) != eSIR_SUCCESS) limLog(pMac, LOGE, - FL("posting to LIM failed, reason=%d\n"), statusCode); + FL("posting to LIM failed, reason=%d"), statusCode); } @@ -2217,7 +2240,7 @@ limChannelSwitchTimerHandler(void *pMacGlobal, tANI_U32 param) tpAniSirGlobal pMac = (tpAniSirGlobal)pMacGlobal; PELOG1(limLog(pMac, LOG1, - FL("ChannelSwitch Timer expired. Posting msg to LIM \n"));) + FL("ChannelSwitch Timer expired. Posting msg to LIM "));) msg.type = SIR_LIM_CHANNEL_SWITCH_TIMEOUT; msg.bodyval = (tANI_U32)param; @@ -2237,7 +2260,7 @@ limQuietTimerHandler(void *pMacGlobal, tANI_U32 param) msg.bodyptr = NULL; PELOG1(limLog(pMac, LOG1, - FL("Post SIR_LIM_QUIET_TIMEOUT msg. \n"));) + FL("Post SIR_LIM_QUIET_TIMEOUT msg. "));) limPostMsgApi(pMac, &msg); } @@ -2251,7 +2274,7 @@ limQuietBssTimerHandler(void *pMacGlobal, tANI_U32 param) msg.bodyval = (tANI_U32)param; msg.bodyptr = NULL; PELOG1(limLog(pMac, LOG1, - FL("Post SIR_LIM_QUIET_BSS_TIMEOUT msg. \n"));) + FL("Post SIR_LIM_QUIET_BSS_TIMEOUT msg. "));) limPostMsgApi(pMac, &msg); } #if 0 @@ -2265,7 +2288,7 @@ limWPSOverlapTimerHandler(void *pMacGlobal, tANI_U32 param) msg.bodyval = (tANI_U32)param; msg.bodyptr = NULL; PELOG1(limLog(pMac, LOG1, - FL("Post SIR_LIM_WPS_OVERLAP_TIMEOUT msg. \n"));) + FL("Post SIR_LIM_WPS_OVERLAP_TIMEOUT msg. "));) limPostMsgApi(pMac, &msg); } #endif @@ -2305,10 +2328,10 @@ limMissedBeaconInActiveMode(void *pMacGlobal, tpPESession psessionEntry) msg.bodyptr = psessionEntry; msg.bodyval = 0; limLog(pMac, LOGE, - FL("Heartbeat failure from Riva\n")); + FL("Heartbeat failure from Riva")); if ((statusCode = limPostMsgApi(pMac, &msg)) != eSIR_SUCCESS) limLog(pMac, LOGE, - FL("posting message %X to LIM failed, reason=%d\n"), + FL("posting message %X to LIM failed, reason=%d"), msg.type, statusCode); } } diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limTrace.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limTrace.c index fce789c14d9..95744c8cfcf 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limTrace.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limTrace.c @@ -169,15 +169,15 @@ void limTraceDump(tpAniSirGlobal pMac, tpTraceRecord pRecord, tANI_U16 recIndex) switch (pRecord->code) { case TRACE_CODE_MLM_STATE: - limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(0x%x) \n", recIndex, pRecord->time, pRecord->session, + limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(0x%x) ", recIndex, pRecord->time, pRecord->session, "MLM State:", limTraceGetMlmStateString((tANI_U16)pRecord->data), pRecord->data ); break; case TRACE_CODE_SME_STATE: - limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(0x%x) \n", recIndex, pRecord->time, pRecord->session, + limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(0x%x) ", recIndex, pRecord->time, pRecord->session, "SME State:", limTraceGetSmeStateString((tANI_U16)pRecord->data), pRecord->data ); break; case TRACE_CODE_TX_MGMT: - limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(0x%x) \n", recIndex, pRecord->time, pRecord->session, + limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(0x%x) ", recIndex, pRecord->time, pRecord->session, "TX Mgmt:", frameSubtypeStr[pRecord->data], pRecord->data ); break; @@ -188,75 +188,75 @@ void limTraceDump(tpAniSirGlobal pMac, tpTraceRecord pRecord, tANI_U16 recIndex) } else { - limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(%d) SN: %d \n", recIndex, pRecord->time, pRecord->session, + limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(%d) SN: %d ", recIndex, pRecord->time, pRecord->session, "RX Mgmt:", frameSubtypeStr[LIM_TRACE_GET_SUBTYPE(pRecord->data)], LIM_TRACE_GET_SUBTYPE(pRecord->data), LIM_TRACE_GET_SSN(pRecord->data) ); } break; case TRACE_CODE_RX_MGMT_DROP: - limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(%d) \n", recIndex, pRecord->time, pRecord->session, + limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(%d) ", recIndex, pRecord->time, pRecord->session, "Drop RX Mgmt:", __limTraceGetMgmtDropReasonString((tANI_U16)pRecord->data), pRecord->data); break; case TRACE_CODE_RX_MGMT_TSF: - limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s0x%x(%d) \n", recIndex, pRecord->time, pRecord->session, + limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s0x%x(%d) ", recIndex, pRecord->time, pRecord->session, "RX Mgmt TSF:", " ", pRecord->data, pRecord->data ); break; case TRACE_CODE_TX_COMPLETE: - limLog(pMac, LOGE, "%04d %012u S%d %-14s \n", recIndex, pRecord->time, pRecord->session, + limLog(pMac, LOGE, "%04d %012u S%d %-14s ", recIndex, pRecord->time, pRecord->session, "TX Complete" ); break; case TRACE_CODE_TX_SME_MSG: - limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(0x%x) \n", recIndex, pRecord->time, pRecord->session, + limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(0x%x) ", recIndex, pRecord->time, pRecord->session, "TX SME Msg:", macTraceGetSmeMsgString((tANI_U16)pRecord->data), pRecord->data ); break; case TRACE_CODE_RX_SME_MSG: - limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(0x%x) \n", recIndex, pRecord->time, pRecord->session, + limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(0x%x) ", recIndex, pRecord->time, pRecord->session, LIM_TRACE_GET_DEFRD_OR_DROPPED(pRecord->data) ? "Def/Drp LIM Msg:": "RX Sme Msg:", macTraceGetSmeMsgString((tANI_U16)pRecord->data), pRecord->data ); break; case TRACE_CODE_TX_WDA_MSG: - limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(0x%x) \n", recIndex, pRecord->time, pRecord->session, + limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(0x%x) ", recIndex, pRecord->time, pRecord->session, "TX WDA Msg:", macTraceGetWdaMsgString((tANI_U16)pRecord->data), pRecord->data ); break; case TRACE_CODE_RX_WDA_MSG: - limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(0x%x) \n", recIndex, pRecord->time, pRecord->session, + limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(0x%x) ", recIndex, pRecord->time, pRecord->session, LIM_TRACE_GET_DEFRD_OR_DROPPED(pRecord->data) ? "Def/Drp LIM Msg:": "RX WDA Msg:", macTraceGetWdaMsgString((tANI_U16)pRecord->data), pRecord->data ); break; case TRACE_CODE_TX_LIM_MSG: - limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(0x%x) \n", recIndex, pRecord->time, pRecord->session, + limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(0x%x) ", recIndex, pRecord->time, pRecord->session, "TX LIM Msg:", macTraceGetLimMsgString((tANI_U16)pRecord->data), pRecord->data ); break; case TRACE_CODE_RX_LIM_MSG: - limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(0x%x) \n", recIndex, pRecord->time, pRecord->session, + limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(0x%x) ", recIndex, pRecord->time, pRecord->session, LIM_TRACE_GET_DEFRD_OR_DROPPED(pRecord->data) ? "Def/Drp LIM Msg:": "RX LIM Msg", macTraceGetLimMsgString((tANI_U16)pRecord->data), pRecord->data ); break; case TRACE_CODE_TX_CFG_MSG: - limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(0x%x) \n", recIndex, pRecord->time, pRecord->session, + limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(0x%x) ", recIndex, pRecord->time, pRecord->session, "TX CFG Msg:", macTraceGetCfgMsgString((tANI_U16)pRecord->data), pRecord->data ); break; case TRACE_CODE_RX_CFG_MSG: - limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(0x%x) \n", recIndex, pRecord->time, pRecord->session, + limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(0x%x) ", recIndex, pRecord->time, pRecord->session, LIM_TRACE_GET_DEFRD_OR_DROPPED(pRecord->data) ? "Def/Drp LIM Msg:": "RX CFG Msg:", macTraceGetCfgMsgString((tANI_U16)MAC_TRACE_GET_MSG_ID(pRecord->data)), pRecord->data ); break; case TRACE_CODE_TIMER_ACTIVATE: - limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(0x%x) \n", recIndex, pRecord->time, pRecord->session, + limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(0x%x) ", recIndex, pRecord->time, pRecord->session, "Timer Actvtd", __limTraceGetTimerString((tANI_U16)pRecord->data), pRecord->data ); break; case TRACE_CODE_TIMER_DEACTIVATE: - limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(0x%x) \n", recIndex, pRecord->time, pRecord->session, + limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(0x%x) ", recIndex, pRecord->time, pRecord->session, "Timer DeActvtd", __limTraceGetTimerString((tANI_U16)pRecord->data), pRecord->data ); break; @@ -265,7 +265,7 @@ void limTraceDump(tpAniSirGlobal pMac, tpTraceRecord pRecord, tANI_U16 recIndex) "INFORMATION_LOG", macTraceGetInfoLogString((tANI_U16)pRecord->data), pRecord->data ); break; default : - limLog(pMac, LOGE, "%04d %012u S%d %-14s(%d) (0x%x) \n", recIndex, pRecord->time, pRecord->session, + limLog(pMac, LOGE, "%04d %012u S%d %-14s(%d) (0x%x) ", recIndex, pRecord->time, pRecord->session, "Unknown Code", pRecord->code, pRecord->data ); break; } diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limTypes.h b/drivers/staging/prima/CORE/MAC/src/pe/lim/limTypes.h index a8fd0c6af08..1f915e628e8 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limTypes.h +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limTypes.h @@ -871,7 +871,7 @@ void limProcessLearnIntervalTimeout(tpAniSirGlobal pMac); #ifdef WLAN_FEATURE_11W //11w SA query request action frame handler tSirRetStatus limSendSaQueryResponseFrame( tpAniSirGlobal pMac, - tANI_U8 *transId, tSirMacAddr peer,tpPESession psessionEntry); + tANI_U16 transId, tSirMacAddr peer,tpPESession psessionEntry); #endif // Inline functions @@ -905,7 +905,7 @@ limPostSmeMessage(tpAniSirGlobal pMac, tANI_U32 msgType, tANI_U32 *pMsgBuf) if(pMsgBuf == NULL) { - limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n")); + limLog(pMac, LOGE,FL("Buffer is Pointing to NULL")); return; } @@ -950,7 +950,7 @@ limPostMlmMessage(tpAniSirGlobal pMac, tANI_U32 msgType, tANI_U32 *pMsgBuf) tSirMsgQ msg; if(pMsgBuf == NULL) { - limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n")); + limLog(pMac, LOGE,FL("Buffer is Pointing to NULL")); return; } msg.type = (tANI_U16) msgType; @@ -1103,5 +1103,10 @@ typedef struct sSetLinkCbackParams void * cbackDataPtr; } tSetLinkCbackParams; #endif + +void limProcessRxScanEvent(tpAniSirGlobal mac, void *buf); + +int limProcessRemainOnChnlReq(tpAniSirGlobal pMac, tANI_U32 *pMsg); +void limRemainOnChnRsp(tpAniSirGlobal pMac, eHalStatus status, tANI_U32 *data); #endif /* __LIM_TYPES_H */ diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limUtils.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limUtils.c index 59500f992fd..e534aebe94d 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limUtils.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limUtils.c @@ -80,6 +80,11 @@ static tAniBool glimTriggerBackgroundScanDuringQuietBss_Status = eSIR_TRUE; static const tANI_U8 abChannel[]= {36,40,44,48,52,56,60,64,100,104,108,112,116, 120,124,128,132,136,140,149,153,157,161,165}; +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +static const tANI_U8 aUnsortedChannelList[]= {52,56,60,64,100,104,108,112,116, + 120,124,128,132,136,140,36,40,44,48,149,153,157,161,165}; +#endif + //#define LIM_MAX_ACTIVE_SESSIONS 3 //defined temporarily for BT-AMP SUPPORT #define SUCCESS 1 //defined temporarily for BT-AMP @@ -98,7 +103,7 @@ limAssignDialogueToken(tpAniSirGlobal pMac) if(eHAL_STATUS_SUCCESS != palAllocateMemory(pMac->hHdd, (void **) &pCurrNode, sizeof(tDialogueToken))) { - PELOGE(limLog(pMac, LOGE, FL("palAllocateMemory failed\n"));) + PELOGE(limLog(pMac, LOGE, FL("palAllocateMemory failed"));) return NULL; } @@ -116,7 +121,7 @@ limAssignDialogueToken(tpAniSirGlobal pMac) //assocId and tid of the node will be filled in by caller. pCurrNode->next = NULL; pCurrNode->token = token++; - PELOG4(limLog(pMac, LOG4, FL("token assigned = %d\n"), token);) + PELOG4(limLog(pMac, LOG4, FL("token assigned = %d"), token);) return pCurrNode; } @@ -178,7 +183,7 @@ limSearchAndDeleteDialogueToken(tpAniSirGlobal pMac, tANI_U8 token, tANI_U16 ass return eSIR_SUCCESS; } - PELOGW(limLog(pMac, LOGW, FL("LIM does not have matching dialogue token node\n"));) + PELOGW(limLog(pMac, LOGW, FL("LIM does not have matching dialogue token node"));) return eSIR_FAILURE; } @@ -239,63 +244,63 @@ limMlmStateStr(tLimMlmStates state) switch (state) { case eLIM_MLM_OFFLINE_STATE: - return "eLIM_MLM_OFFLINE_STATE\n"; + return "eLIM_MLM_OFFLINE_STATE"; case eLIM_MLM_IDLE_STATE: - return "eLIM_MLM_IDLE_STATE\n"; + return "eLIM_MLM_IDLE_STATE"; case eLIM_MLM_WT_PROBE_RESP_STATE: - return "eLIM_MLM_WT_PROBE_RESP_STATE\n"; + return "eLIM_MLM_WT_PROBE_RESP_STATE"; case eLIM_MLM_PASSIVE_SCAN_STATE: - return "eLIM_MLM_PASSIVE_SCAN_STATE\n"; + return "eLIM_MLM_PASSIVE_SCAN_STATE"; case eLIM_MLM_WT_JOIN_BEACON_STATE: - return "eLIM_MLM_WT_JOIN_BEACON_STATE\n"; + return "eLIM_MLM_WT_JOIN_BEACON_STATE"; case eLIM_MLM_JOINED_STATE: - return "eLIM_MLM_JOINED_STATE\n"; + return "eLIM_MLM_JOINED_STATE"; case eLIM_MLM_BSS_STARTED_STATE: - return "eLIM_MLM_BSS_STARTED_STATE\n"; + return "eLIM_MLM_BSS_STARTED_STATE"; case eLIM_MLM_WT_AUTH_FRAME2_STATE: - return "eLIM_MLM_WT_AUTH_FRAME2_STATE\n"; + return "eLIM_MLM_WT_AUTH_FRAME2_STATE"; case eLIM_MLM_WT_AUTH_FRAME3_STATE: - return "eLIM_MLM_WT_AUTH_FRAME3_STATE\n"; + return "eLIM_MLM_WT_AUTH_FRAME3_STATE"; case eLIM_MLM_WT_AUTH_FRAME4_STATE: - return "eLIM_MLM_WT_AUTH_FRAME4_STATE\n"; + return "eLIM_MLM_WT_AUTH_FRAME4_STATE"; case eLIM_MLM_AUTH_RSP_TIMEOUT_STATE: - return "eLIM_MLM_AUTH_RSP_TIMEOUT_STATE\n"; + return "eLIM_MLM_AUTH_RSP_TIMEOUT_STATE"; case eLIM_MLM_AUTHENTICATED_STATE: - return "eLIM_MLM_AUTHENTICATED_STATE\n"; + return "eLIM_MLM_AUTHENTICATED_STATE"; case eLIM_MLM_WT_ASSOC_RSP_STATE: - return "eLIM_MLM_WT_ASSOC_RSP_STATE\n"; + return "eLIM_MLM_WT_ASSOC_RSP_STATE"; case eLIM_MLM_WT_REASSOC_RSP_STATE: - return "eLIM_MLM_WT_REASSOC_RSP_STATE\n"; + return "eLIM_MLM_WT_REASSOC_RSP_STATE"; case eLIM_MLM_WT_FT_REASSOC_RSP_STATE: return "eLIM_MLM_WT_FT_REASSOC_RSP_STATE"; case eLIM_MLM_WT_DEL_STA_RSP_STATE: - return "eLIM_MLM_WT_DEL_STA_RSP_STATE\n"; + return "eLIM_MLM_WT_DEL_STA_RSP_STATE"; case eLIM_MLM_WT_DEL_BSS_RSP_STATE: - return "eLIM_MLM_WT_DEL_BSS_RSP_STATE\n"; + return "eLIM_MLM_WT_DEL_BSS_RSP_STATE"; case eLIM_MLM_WT_ADD_STA_RSP_STATE: - return "eLIM_MLM_WT_ADD_STA_RSP_STATE\n"; + return "eLIM_MLM_WT_ADD_STA_RSP_STATE"; case eLIM_MLM_WT_ADD_BSS_RSP_STATE: - return "eLIM_MLM_WT_ADD_BSS_RSP_STATE\n"; + return "eLIM_MLM_WT_ADD_BSS_RSP_STATE"; case eLIM_MLM_REASSOCIATED_STATE: - return "eLIM_MLM_REASSOCIATED_STATE\n"; + return "eLIM_MLM_REASSOCIATED_STATE"; case eLIM_MLM_LINK_ESTABLISHED_STATE: - return "eLIM_MLM_LINK_ESTABLISHED_STATE\n"; + return "eLIM_MLM_LINK_ESTABLISHED_STATE"; case eLIM_MLM_WT_ASSOC_CNF_STATE: - return "eLIM_MLM_WT_ASSOC_CNF_STATE\n"; + return "eLIM_MLM_WT_ASSOC_CNF_STATE"; case eLIM_MLM_WT_ADD_BSS_RSP_ASSOC_STATE: - return "eLIM_MLM_WT_ADD_BSS_RSP_ASSOC_STATE\n"; + return "eLIM_MLM_WT_ADD_BSS_RSP_ASSOC_STATE"; case eLIM_MLM_WT_ADD_BSS_RSP_REASSOC_STATE: - return "eLIM_MLM_WT_ADD_BSS_RSP_REASSOC_STATE\n"; + return "eLIM_MLM_WT_ADD_BSS_RSP_REASSOC_STATE"; case eLIM_MLM_WT_ADD_BSS_RSP_FT_REASSOC_STATE: return "eLIM_MLM_WT_ADD_BSS_RSP_FT_REASSOC_STATE"; case eLIM_MLM_WT_ASSOC_DEL_STA_RSP_STATE: - return "eLIM_MLM_WT_ASSOC_DEL_STA_RSP_STATE\n"; + return "eLIM_MLM_WT_ASSOC_DEL_STA_RSP_STATE"; case eLIM_MLM_WT_SET_BSS_KEY_STATE: - return "eLIM_MLM_WT_SET_BSS_KEY_STATE\n"; + return "eLIM_MLM_WT_SET_BSS_KEY_STATE"; case eLIM_MLM_WT_SET_STA_KEY_STATE: - return "eLIM_MLM_WT_SET_STA_KEY_STATE\n"; + return "eLIM_MLM_WT_SET_STA_KEY_STATE"; default: - return "INVALID MLM state\n"; + return "INVALID MLM state"; } } @@ -312,51 +317,51 @@ limSmeStateStr(tLimSmeStates state) switch (state) { case eLIM_SME_OFFLINE_STATE: - return "eLIM_SME_OFFLINE_STATE\n"; + return "eLIM_SME_OFFLINE_STATE"; case eLIM_SME_IDLE_STATE: - return "eLIM_SME_IDLE_STATE\n"; + return "eLIM_SME_IDLE_STATE"; case eLIM_SME_SUSPEND_STATE: - return "eLIM_SME_SUSPEND_STATE\n"; + return "eLIM_SME_SUSPEND_STATE"; case eLIM_SME_WT_SCAN_STATE: - return "eLIM_SME_WT_SCAN_STATE\n"; + return "eLIM_SME_WT_SCAN_STATE"; case eLIM_SME_WT_JOIN_STATE: - return "eLIM_SME_WT_JOIN_STATE\n"; + return "eLIM_SME_WT_JOIN_STATE"; case eLIM_SME_WT_AUTH_STATE: - return "eLIM_SME_WT_AUTH_STATE\n"; + return "eLIM_SME_WT_AUTH_STATE"; case eLIM_SME_WT_ASSOC_STATE: - return "eLIM_SME_WT_ASSOC_STATE\n"; + return "eLIM_SME_WT_ASSOC_STATE"; case eLIM_SME_WT_REASSOC_STATE: - return "eLIM_SME_WT_REASSOC_STATE\n"; + return "eLIM_SME_WT_REASSOC_STATE"; case eLIM_SME_WT_REASSOC_LINK_FAIL_STATE: - return "eLIM_SME_WT_REASSOC_LINK_FAIL_STATE\n"; + return "eLIM_SME_WT_REASSOC_LINK_FAIL_STATE"; case eLIM_SME_JOIN_FAILURE_STATE: - return "eLIM_SME_JOIN_FAILURE_STATE\n"; + return "eLIM_SME_JOIN_FAILURE_STATE"; case eLIM_SME_ASSOCIATED_STATE: - return "eLIM_SME_ASSOCIATED_STATE\n"; + return "eLIM_SME_ASSOCIATED_STATE"; case eLIM_SME_REASSOCIATED_STATE: - return "eLIM_SME_REASSOCIATED_STATE\n"; + return "eLIM_SME_REASSOCIATED_STATE"; case eLIM_SME_LINK_EST_STATE: - return "eLIM_SME_LINK_EST_STATE\n"; + return "eLIM_SME_LINK_EST_STATE"; case eLIM_SME_LINK_EST_WT_SCAN_STATE: - return "eLIM_SME_LINK_EST_WT_SCAN_STATE\n"; + return "eLIM_SME_LINK_EST_WT_SCAN_STATE"; case eLIM_SME_WT_PRE_AUTH_STATE: - return "eLIM_SME_WT_PRE_AUTH_STATE\n"; + return "eLIM_SME_WT_PRE_AUTH_STATE"; case eLIM_SME_WT_DISASSOC_STATE: - return "eLIM_SME_WT_DISASSOC_STATE\n"; + return "eLIM_SME_WT_DISASSOC_STATE"; case eLIM_SME_WT_DEAUTH_STATE: - return "eLIM_SME_WT_DEAUTH_STATE\n"; + return "eLIM_SME_WT_DEAUTH_STATE"; case eLIM_SME_WT_START_BSS_STATE: - return "eLIM_SME_WT_START_BSS_STATE\n"; + return "eLIM_SME_WT_START_BSS_STATE"; case eLIM_SME_WT_STOP_BSS_STATE: - return "eLIM_SME_WT_STOP_BSS_STATE\n"; + return "eLIM_SME_WT_STOP_BSS_STATE"; case eLIM_SME_NORMAL_STATE: - return "eLIM_SME_NORMAL_STATE\n"; + return "eLIM_SME_NORMAL_STATE"; case eLIM_SME_CHANNEL_SCAN_STATE: - return "eLIM_SME_CHANNEL_SCAN_STATE\n"; + return "eLIM_SME_CHANNEL_SCAN_STATE"; case eLIM_SME_NORMAL_CHANNEL_SCAN_STATE: - return "eLIM_SME_NORMAL_CHANNEL_SCAN_STATE\n"; + return "eLIM_SME_NORMAL_CHANNEL_SCAN_STATE"; default: - return "INVALID SME state\n"; + return "INVALID SME state"; } #endif return ""; @@ -370,23 +375,23 @@ char* limDot11ModeStr(tpAniSirGlobal pMac, tANI_U8 dot11Mode) switch(dot11Mode) { case WNI_CFG_DOT11_MODE_ALL: - return "ALL\n"; + return "ALL"; case WNI_CFG_DOT11_MODE_11A: - return "11A\n"; - case WNI_CFG_DOT11_MODE_11B: - return "11B\n"; - case WNI_CFG_DOT11_MODE_11G: - return "11G\n"; - case WNI_CFG_DOT11_MODE_11N: - return "11N\n"; - case WNI_CFG_DOT11_MODE_POLARIS: - return "Polaris\n"; - case WNI_CFG_DOT11_MODE_TITAN: - return "Titan\n"; + return "11A"; + case WNI_CFG_DOT11_MODE_11B: + return "11B"; + case WNI_CFG_DOT11_MODE_11G: + return "11G"; + case WNI_CFG_DOT11_MODE_11N: + return "11N"; + case WNI_CFG_DOT11_MODE_POLARIS: + return "Polaris"; + case WNI_CFG_DOT11_MODE_TITAN: + return "Titan"; case WNI_CFG_DOT11_MODE_TAURUS: - return "Taurus\n"; + return "Taurus"; default: - return "Invalid Dot11 Mode\n"; + return "Invalid Dot11 Mode"; } #endif return ""; @@ -400,21 +405,21 @@ char* limStaOpRateModeStr(tStaRateMode opRateMode) switch(opRateMode) { case eSTA_TAURUS: - return "Taurus\n"; + return "Taurus"; case eSTA_11a: - return "11A\n"; - case eSTA_11b: - return "11B\n"; - case eSTA_11bg: - return "11G\n"; - case eSTA_11n: - return "11N\n"; - case eSTA_POLARIS: - return "Polaris\n"; + return "11A"; + case eSTA_11b: + return "11B"; + case eSTA_11bg: + return "11G"; + case eSTA_11n: + return "11N"; + case eSTA_POLARIS: + return "Polaris"; case eSTA_TITAN: - return "Titan\n"; + return "Titan"; default: - return "Invalid Dot11 Mode\n"; + return "Invalid Dot11 Mode"; } #endif return ""; @@ -428,11 +433,11 @@ char* limBssTypeStr(tSirBssType bssType) return "eSIR_INFRASTRUCTURE_MODE"; case eSIR_IBSS_MODE: return "eSIR_IBSS_MODE"; - case eSIR_BTAMP_STA_MODE: + case eSIR_BTAMP_STA_MODE: return "eSIR_BTAMP_STA_MODE"; - case eSIR_BTAMP_AP_MODE: + case eSIR_BTAMP_AP_MODE: return "eSIR_BTAMP_AP_MODE"; - case eSIR_AUTO_MODE: + case eSIR_AUTO_MODE: return "eSIR_AUTO_MODE"; default: return "Invalid BSS Type"; @@ -451,236 +456,236 @@ char *limMsgStr(tANI_U32 msgType) switch (msgType) { case eWNI_SME_START_REQ: - return "eWNI_SME_START_REQ\n"; + return "eWNI_SME_START_REQ"; case eWNI_SME_START_RSP: - return "eWNI_SME_START_RSP\n"; + return "eWNI_SME_START_RSP"; case eWNI_SME_SYS_READY_IND: - return "eWNI_SME_SYS_READY_IND\n"; + return "eWNI_SME_SYS_READY_IND"; case eWNI_SME_SCAN_REQ: - return "eWNI_SME_SCAN_REQ\n"; + return "eWNI_SME_SCAN_REQ"; #ifdef FEATURE_OEM_DATA_SUPPORT case eWNI_SME_OEM_DATA_REQ: - return "eWNI_SME_OEM_DATA_REQ\n"; + return "eWNI_SME_OEM_DATA_REQ"; case eWNI_SME_OEM_DATA_RSP: - return "eWNI_SME_OEM_DATA_RSP\n"; + return "eWNI_SME_OEM_DATA_RSP"; #endif case eWNI_SME_SCAN_RSP: - return "eWNI_SME_SCAN_RSP\n"; + return "eWNI_SME_SCAN_RSP"; case eWNI_SME_JOIN_REQ: - return "eWNI_SME_JOIN_REQ\n"; + return "eWNI_SME_JOIN_REQ"; case eWNI_SME_JOIN_RSP: - return "eWNI_SME_JOIN_RSP\n"; + return "eWNI_SME_JOIN_RSP"; case eWNI_SME_SETCONTEXT_REQ: - return "eWNI_SME_SETCONTEXT_REQ\n"; + return "eWNI_SME_SETCONTEXT_REQ"; case eWNI_SME_SETCONTEXT_RSP: - return "eWNI_SME_SETCONTEXT_RSP\n"; + return "eWNI_SME_SETCONTEXT_RSP"; case eWNI_SME_REASSOC_REQ: - return "eWNI_SME_REASSOC_REQ\n"; + return "eWNI_SME_REASSOC_REQ"; case eWNI_SME_REASSOC_RSP: - return "eWNI_SME_REASSOC_RSP\n"; + return "eWNI_SME_REASSOC_RSP"; case eWNI_SME_AUTH_REQ: - return "eWNI_SME_AUTH_REQ\n"; + return "eWNI_SME_AUTH_REQ"; case eWNI_SME_AUTH_RSP: - return "eWNI_SME_AUTH_RSP\n"; + return "eWNI_SME_AUTH_RSP"; case eWNI_SME_DISASSOC_REQ: - return "eWNI_SME_DISASSOC_REQ\n"; + return "eWNI_SME_DISASSOC_REQ"; case eWNI_SME_DISASSOC_RSP: - return "eWNI_SME_DISASSOC_RSP\n"; + return "eWNI_SME_DISASSOC_RSP"; case eWNI_SME_DISASSOC_IND: - return "eWNI_SME_DISASSOC_IND\n"; + return "eWNI_SME_DISASSOC_IND"; case eWNI_SME_DISASSOC_CNF: - return "eWNI_SME_DISASSOC_CNF\n"; + return "eWNI_SME_DISASSOC_CNF"; case eWNI_SME_DEAUTH_REQ: - return "eWNI_SME_DEAUTH_REQ\n"; + return "eWNI_SME_DEAUTH_REQ"; case eWNI_SME_DEAUTH_RSP: - return "eWNI_SME_DEAUTH_RSP\n"; + return "eWNI_SME_DEAUTH_RSP"; case eWNI_SME_DEAUTH_IND: - return "eWNI_SME_DEAUTH_IND\n"; + return "eWNI_SME_DEAUTH_IND"; case eWNI_SME_WM_STATUS_CHANGE_NTF: - return "eWNI_SME_WM_STATUS_CHANGE_NTF\n"; + return "eWNI_SME_WM_STATUS_CHANGE_NTF"; case eWNI_SME_START_BSS_REQ: - return "eWNI_SME_START_BSS_REQ\n"; + return "eWNI_SME_START_BSS_REQ"; case eWNI_SME_START_BSS_RSP: - return "eWNI_SME_START_BSS_RSP\n"; + return "eWNI_SME_START_BSS_RSP"; case eWNI_SME_AUTH_IND: - return "eWNI_SME_AUTH_IND\n"; + return "eWNI_SME_AUTH_IND"; case eWNI_SME_ASSOC_IND: - return "eWNI_SME_ASSOC_IND\n"; + return "eWNI_SME_ASSOC_IND"; case eWNI_SME_ASSOC_CNF: - return "eWNI_SME_ASSOC_CNF\n"; + return "eWNI_SME_ASSOC_CNF"; case eWNI_SME_REASSOC_IND: - return "eWNI_SME_REASSOC_IND\n"; + return "eWNI_SME_REASSOC_IND"; case eWNI_SME_REASSOC_CNF: - return "eWNI_SME_REASSOC_CNF\n"; + return "eWNI_SME_REASSOC_CNF"; case eWNI_SME_SWITCH_CHL_REQ: - return "eWNI_SME_SWITCH_CHL_REQ\n"; + return "eWNI_SME_SWITCH_CHL_REQ"; case eWNI_SME_SWITCH_CHL_RSP: - return "eWNI_SME_SWITCH_CHL_RSP\n"; + return "eWNI_SME_SWITCH_CHL_RSP"; case eWNI_SME_SWITCH_CHL_CB_PRIMARY_REQ: - return "eWNI_SME_SWITCH_CHL_CB_PRIMARY_REQ\n"; + return "eWNI_SME_SWITCH_CHL_CB_PRIMARY_REQ"; case eWNI_SME_SWITCH_CHL_CB_SECONDARY_REQ: - return "eWNI_SME_SWITCH_CHL_CB_SECONDARY_REQ\n"; + return "eWNI_SME_SWITCH_CHL_CB_SECONDARY_REQ"; case eWNI_SME_STOP_BSS_REQ: - return "eWNI_SME_STOP_BSS_REQ\n"; + return "eWNI_SME_STOP_BSS_REQ"; case eWNI_SME_STOP_BSS_RSP: - return "eWNI_SME_STOP_BSS_RSP\n"; + return "eWNI_SME_STOP_BSS_RSP"; case eWNI_SME_PROMISCUOUS_MODE_REQ: - return "eWNI_SME_PROMISCUOUS_MODE_REQ\n"; + return "eWNI_SME_PROMISCUOUS_MODE_REQ"; case eWNI_SME_PROMISCUOUS_MODE_RSP: - return "eWNI_SME_PROMISCUOUS_MODE_RSP\n"; + return "eWNI_SME_PROMISCUOUS_MODE_RSP"; case eWNI_SME_NEIGHBOR_BSS_IND: - return "eWNI_SME_NEIGHBOR_BSS_IND\n"; + return "eWNI_SME_NEIGHBOR_BSS_IND"; case eWNI_SME_MEASUREMENT_REQ: - return "eWNI_SME_MEASUREMENT_REQ\n"; + return "eWNI_SME_MEASUREMENT_REQ"; case eWNI_SME_MEASUREMENT_RSP: - return "eWNI_SME_MEASUREMENT_RSP\n"; + return "eWNI_SME_MEASUREMENT_RSP"; case eWNI_SME_MEASUREMENT_IND: - return "eWNI_SME_MEASUREMENT_IND\n"; + return "eWNI_SME_MEASUREMENT_IND"; case eWNI_SME_SET_WDS_INFO_REQ: - return "eWNI_SME_SET_WDS_INFO_REQ\n"; + return "eWNI_SME_SET_WDS_INFO_REQ"; case eWNI_SME_SET_WDS_INFO_RSP: - return "eWNI_SME_SET_WDS_INFO_RSP\n"; + return "eWNI_SME_SET_WDS_INFO_RSP"; case eWNI_SME_WDS_INFO_IND: - return "eWNI_SME_WDS_INFO_IND\n"; + return "eWNI_SME_WDS_INFO_IND"; case eWNI_SME_DEAUTH_CNF: - return "eWNI_SME_DEAUTH_CNF\n"; + return "eWNI_SME_DEAUTH_CNF"; case eWNI_SME_MIC_FAILURE_IND: - return "eWNI_SME_MIC_FAILURE_IND\n"; + return "eWNI_SME_MIC_FAILURE_IND"; case eWNI_SME_ADDTS_REQ: - return "eWNI_SME_ADDTS_REQ\n"; + return "eWNI_SME_ADDTS_REQ"; case eWNI_SME_ADDTS_RSP: - return "eWNI_SME_ADDTS_RSP\n"; + return "eWNI_SME_ADDTS_RSP"; case eWNI_SME_ADDTS_CNF: - return "eWNI_SME_ADDTS_CNF\n"; + return "eWNI_SME_ADDTS_CNF"; case eWNI_SME_ADDTS_IND: - return "eWNI_SME_ADDTS_IND\n"; + return "eWNI_SME_ADDTS_IND"; case eWNI_SME_DELTS_REQ: - return "eWNI_SME_DELTS_REQ\n"; + return "eWNI_SME_DELTS_REQ"; case eWNI_SME_DELTS_RSP: - return "eWNI_SME_DELTS_RSP\n"; + return "eWNI_SME_DELTS_RSP"; case eWNI_SME_DELTS_IND: - return "eWNI_SME_DELTS_IND\n"; + return "eWNI_SME_DELTS_IND"; #if defined WLAN_FEATURE_VOWIFI_11R || defined FEATURE_WLAN_CCX || defined(FEATURE_WLAN_LFR) case eWNI_SME_GET_ROAM_RSSI_REQ: - return "eWNI_SME_GET_ROAM_RSSI_REQ\n"; + return "eWNI_SME_GET_ROAM_RSSI_REQ"; case eWNI_SME_GET_ROAM_RSSI_RSP: - return "eWNI_SME_GET_ROAM_RSSI_RSP\n"; + return "eWNI_SME_GET_ROAM_RSSI_RSP"; #endif case WDA_SUSPEND_ACTIVITY_RSP: - return "WDA_SUSPEND_ACTIVITY_RSP\n"; + return "WDA_SUSPEND_ACTIVITY_RSP"; case SIR_LIM_RETRY_INTERRUPT_MSG: - return "SIR_LIM_RETRY_INTERRUPT_MSG\n"; + return "SIR_LIM_RETRY_INTERRUPT_MSG"; case SIR_BB_XPORT_MGMT_MSG: - return "SIR_BB_XPORT_MGMT_MSG\n"; + return "SIR_BB_XPORT_MGMT_MSG"; case SIR_LIM_INV_KEY_INTERRUPT_MSG: - return "SIR_LIM_INV_KEY_INTERRUPT_MSG\n"; + return "SIR_LIM_INV_KEY_INTERRUPT_MSG"; case SIR_LIM_KEY_ID_INTERRUPT_MSG: - return "SIR_LIM_KEY_ID_INTERRUPT_MSG\n"; + return "SIR_LIM_KEY_ID_INTERRUPT_MSG"; case SIR_LIM_REPLAY_THRES_INTERRUPT_MSG: - return "SIR_LIM_REPLAY_THRES_INTERRUPT_MSG\n"; + return "SIR_LIM_REPLAY_THRES_INTERRUPT_MSG"; case SIR_LIM_MIN_CHANNEL_TIMEOUT: - return "SIR_LIM_MIN_CHANNEL_TIMEOUT\n"; + return "SIR_LIM_MIN_CHANNEL_TIMEOUT"; case SIR_LIM_MAX_CHANNEL_TIMEOUT: - return "SIR_LIM_MAX_CHANNEL_TIMEOUT\n"; + return "SIR_LIM_MAX_CHANNEL_TIMEOUT"; case SIR_LIM_JOIN_FAIL_TIMEOUT: - return "SIR_LIM_JOIN_FAIL_TIMEOUT\n"; + return "SIR_LIM_JOIN_FAIL_TIMEOUT"; case SIR_LIM_AUTH_FAIL_TIMEOUT: - return "SIR_LIM_AUTH_FAIL_TIMEOUT\n"; + return "SIR_LIM_AUTH_FAIL_TIMEOUT"; case SIR_LIM_AUTH_RSP_TIMEOUT: - return "SIR_LIM_AUTH_RSP_TIMEOUT\n"; + return "SIR_LIM_AUTH_RSP_TIMEOUT"; case SIR_LIM_ASSOC_FAIL_TIMEOUT: - return "SIR_LIM_ASSOC_FAIL_TIMEOUT\n"; + return "SIR_LIM_ASSOC_FAIL_TIMEOUT"; case SIR_LIM_REASSOC_FAIL_TIMEOUT: - return "SIR_LIM_REASSOC_FAIL_TIMEOUT\n"; + return "SIR_LIM_REASSOC_FAIL_TIMEOUT"; case SIR_LIM_HEART_BEAT_TIMEOUT: - return "SIR_LIM_HEART_BEAT_TIMEOUT\n"; + return "SIR_LIM_HEART_BEAT_TIMEOUT"; case SIR_LIM_ADDTS_RSP_TIMEOUT: - return "SIR_LIM_ADDTS_RSP_TIMEOUT\n"; + return "SIR_LIM_ADDTS_RSP_TIMEOUT"; case SIR_LIM_CHANNEL_SCAN_TIMEOUT: - return "SIR_LIM_CHANNEL_SCAN_TIMEOUT\n"; + return "SIR_LIM_CHANNEL_SCAN_TIMEOUT"; case SIR_LIM_LINK_TEST_DURATION_TIMEOUT: - return "SIR_LIM_LINK_TEST_DURATION_TIMEOUT\n"; + return "SIR_LIM_LINK_TEST_DURATION_TIMEOUT"; case SIR_LIM_HASH_MISS_THRES_TIMEOUT: - return "SIR_LIM_HASH_MISS_THRES_TIMEOUT\n"; + return "SIR_LIM_HASH_MISS_THRES_TIMEOUT"; case SIR_LIM_KEEPALIVE_TIMEOUT: - return "SIR_LIM_KEEPALIVE_TIMEOUT\n"; + return "SIR_LIM_KEEPALIVE_TIMEOUT"; case SIR_LIM_UPDATE_OLBC_CACHEL_TIMEOUT: - return "SIR_LIM_UPDATE_OLBC_CACHEL_TIMEOUT\n"; + return "SIR_LIM_UPDATE_OLBC_CACHEL_TIMEOUT"; case SIR_LIM_CNF_WAIT_TIMEOUT: - return "SIR_LIM_CNF_WAIT_TIMEOUT\n"; + return "SIR_LIM_CNF_WAIT_TIMEOUT"; case SIR_LIM_RADAR_DETECT_IND: - return "SIR_LIM_RADAR_DETECT_IND\n"; + return "SIR_LIM_RADAR_DETECT_IND"; #ifdef WLAN_FEATURE_VOWIFI_11R case SIR_LIM_FT_PREAUTH_RSP_TIMEOUT: - return "SIR_LIM_FT_PREAUTH_RSP_TIMEOUT\n"; + return "SIR_LIM_FT_PREAUTH_RSP_TIMEOUT"; #endif case SIR_HAL_APP_SETUP_NTF: - return "SIR_HAL_APP_SETUP_NTF\n"; + return "SIR_HAL_APP_SETUP_NTF"; case SIR_HAL_INITIAL_CAL_FAILED_NTF: - return "SIR_HAL_INITIAL_CAL_FAILED_NTF\n"; + return "SIR_HAL_INITIAL_CAL_FAILED_NTF"; case SIR_HAL_NIC_OPER_NTF: - return "SIR_HAL_NIC_OPER_NTF\n"; + return "SIR_HAL_NIC_OPER_NTF"; case SIR_HAL_INIT_START_REQ: - return "SIR_HAL_INIT_START_REQ\n"; + return "SIR_HAL_INIT_START_REQ"; case SIR_HAL_SHUTDOWN_REQ: - return "SIR_HAL_SHUTDOWN_REQ\n"; + return "SIR_HAL_SHUTDOWN_REQ"; case SIR_HAL_SHUTDOWN_CNF: - return "SIR_HAL_SHUTDOWN_CNF\n"; + return "SIR_HAL_SHUTDOWN_CNF"; case SIR_HAL_RESET_REQ: - return "SIR_HAL_RESET_REQ\n"; + return "SIR_HAL_RESET_REQ"; case SIR_HAL_RESET_CNF: - return "SIR_HAL_RESET_CNF\n"; + return "SIR_HAL_RESET_CNF"; case SIR_WRITE_TO_TD: - return "SIR_WRITE_TO_TD\n"; + return "SIR_WRITE_TO_TD"; case WNI_CFG_PARAM_UPDATE_IND: - return "WNI_CFG_PARAM_UPDATE_IND\n"; + return "WNI_CFG_PARAM_UPDATE_IND"; case WNI_CFG_DNLD_REQ: - return "WNI_CFG_DNLD_REQ\n"; + return "WNI_CFG_DNLD_REQ"; case WNI_CFG_DNLD_CNF: - return "WNI_CFG_DNLD_CNF\n"; + return "WNI_CFG_DNLD_CNF"; case WNI_CFG_GET_RSP: - return "WNI_CFG_GET_RSP\n"; + return "WNI_CFG_GET_RSP"; case WNI_CFG_SET_CNF: - return "WNI_CFG_SET_CNF\n"; + return "WNI_CFG_SET_CNF"; case WNI_CFG_GET_ATTRIB_RSP: - return "WNI_CFG_GET_ATTRIB_RSP\n"; + return "WNI_CFG_GET_ATTRIB_RSP"; case WNI_CFG_ADD_GRP_ADDR_CNF: - return "WNI_CFG_ADD_GRP_ADDR_CNF\n"; + return "WNI_CFG_ADD_GRP_ADDR_CNF"; case WNI_CFG_DEL_GRP_ADDR_CNF: - return "WNI_CFG_DEL_GRP_ADDR_CNF\n"; + return "WNI_CFG_DEL_GRP_ADDR_CNF"; case ANI_CFG_GET_RADIO_STAT_RSP: - return "ANI_CFG_GET_RADIO_STAT_RSP\n"; + return "ANI_CFG_GET_RADIO_STAT_RSP"; case ANI_CFG_GET_PER_STA_STAT_RSP: - return "ANI_CFG_GET_PER_STA_STAT_RSP\n"; + return "ANI_CFG_GET_PER_STA_STAT_RSP"; case ANI_CFG_GET_AGG_STA_STAT_RSP: - return "ANI_CFG_GET_AGG_STA_STAT_RSP\n"; + return "ANI_CFG_GET_AGG_STA_STAT_RSP"; case ANI_CFG_CLEAR_STAT_RSP: - return "ANI_CFG_CLEAR_STAT_RSP\n"; + return "ANI_CFG_CLEAR_STAT_RSP"; case WNI_CFG_DNLD_RSP: - return "WNI_CFG_DNLD_RSP\n"; + return "WNI_CFG_DNLD_RSP"; case WNI_CFG_GET_REQ: - return "WNI_CFG_GET_REQ\n"; + return "WNI_CFG_GET_REQ"; case WNI_CFG_SET_REQ: - return "WNI_CFG_SET_REQ\n"; + return "WNI_CFG_SET_REQ"; case WNI_CFG_SET_REQ_NO_RSP: - return "WNI_CFG_SET_REQ_NO_RSP\n"; + return "WNI_CFG_SET_REQ_NO_RSP"; case eWNI_PMC_ENTER_IMPS_RSP: - return "eWNI_PMC_ENTER_IMPS_RSP\n"; + return "eWNI_PMC_ENTER_IMPS_RSP"; case eWNI_PMC_EXIT_IMPS_RSP: - return "eWNI_PMC_EXIT_IMPS_RSP\n"; + return "eWNI_PMC_EXIT_IMPS_RSP"; case eWNI_PMC_ENTER_BMPS_RSP: - return "eWNI_PMC_ENTER_BMPS_RSP\n"; + return "eWNI_PMC_ENTER_BMPS_RSP"; case eWNI_PMC_EXIT_BMPS_RSP: - return "eWNI_PMC_EXIT_BMPS_RSP\n"; + return "eWNI_PMC_EXIT_BMPS_RSP"; case eWNI_PMC_EXIT_BMPS_IND: - return "eWNI_PMC_EXIT_BMPS_IND\n"; + return "eWNI_PMC_EXIT_BMPS_IND"; case eWNI_SME_SET_BCN_FILTER_REQ: - return "eWNI_SME_SET_BCN_FILTER_REQ\n"; + return "eWNI_SME_SET_BCN_FILTER_REQ"; default: - return "INVALID SME message\n"; + return "INVALID SME message"; } #endif return ""; @@ -693,153 +698,153 @@ char *limResultCodeStr(tSirResultCodes resultCode) switch (resultCode) { case eSIR_SME_SUCCESS: - return "eSIR_SME_SUCCESS\n"; + return "eSIR_SME_SUCCESS"; case eSIR_EOF_SOF_EXCEPTION: - return "eSIR_EOF_SOF_EXCEPTION\n"; + return "eSIR_EOF_SOF_EXCEPTION"; case eSIR_BMU_EXCEPTION: - return "eSIR_BMU_EXCEPTION\n"; + return "eSIR_BMU_EXCEPTION"; case eSIR_LOW_PDU_EXCEPTION: - return "eSIR_LOW_PDU_EXCEPTION\n"; + return "eSIR_LOW_PDU_EXCEPTION"; case eSIR_USER_TRIG_RESET: - return"eSIR_USER_TRIG_RESET\n"; + return"eSIR_USER_TRIG_RESET"; case eSIR_LOGP_EXCEPTION: - return "eSIR_LOGP_EXCEPTION\n"; + return "eSIR_LOGP_EXCEPTION"; case eSIR_CP_EXCEPTION: - return "eSIR_CP_EXCEPTION\n"; + return "eSIR_CP_EXCEPTION"; case eSIR_STOP_BSS: - return "eSIR_STOP_BSS\n"; + return "eSIR_STOP_BSS"; case eSIR_AHB_HANG_EXCEPTION: - return "eSIR_AHB_HANG_EXCEPTION\n"; + return "eSIR_AHB_HANG_EXCEPTION"; case eSIR_DPU_EXCEPTION: - return "eSIR_DPU_EXCEPTION\n"; + return "eSIR_DPU_EXCEPTION"; case eSIR_RXP_EXCEPTION: - return "eSIR_RXP_EXCEPTION\n"; + return "eSIR_RXP_EXCEPTION"; case eSIR_MCPU_EXCEPTION: - return "eSIR_MCPU_EXCEPTION\n"; + return "eSIR_MCPU_EXCEPTION"; case eSIR_MCU_EXCEPTION: - return "eSIR_MCU_EXCEPTION\n"; + return "eSIR_MCU_EXCEPTION"; case eSIR_MTU_EXCEPTION: - return "eSIR_MTU_EXCEPTION\n"; + return "eSIR_MTU_EXCEPTION"; case eSIR_MIF_EXCEPTION: - return "eSIR_MIF_EXCEPTION\n"; + return "eSIR_MIF_EXCEPTION"; case eSIR_FW_EXCEPTION: - return "eSIR_FW_EXCEPTION\n"; + return "eSIR_FW_EXCEPTION"; case eSIR_MAILBOX_SANITY_CHK_FAILED: - return "eSIR_MAILBOX_SANITY_CHK_FAILED\n"; + return "eSIR_MAILBOX_SANITY_CHK_FAILED"; case eSIR_RADIO_HW_SWITCH_STATUS_IS_OFF: - return "eSIR_RADIO_HW_SWITCH_STATUS_IS_OFF\n"; + return "eSIR_RADIO_HW_SWITCH_STATUS_IS_OFF"; case eSIR_CFB_FLAG_STUCK_EXCEPTION: - return "eSIR_CFB_FLAG_STUCK_EXCEPTION\n"; + return "eSIR_CFB_FLAG_STUCK_EXCEPTION"; case eSIR_SME_BASIC_RATES_NOT_SUPPORTED_STATUS: - return "eSIR_SME_BASIC_RATES_NOT_SUPPORTED_STATUS\n"; + return "eSIR_SME_BASIC_RATES_NOT_SUPPORTED_STATUS"; case eSIR_SME_INVALID_PARAMETERS: - return "eSIR_SME_INVALID_PARAMETERS\n"; + return "eSIR_SME_INVALID_PARAMETERS"; case eSIR_SME_UNEXPECTED_REQ_RESULT_CODE: - return "eSIR_SME_UNEXPECTED_REQ_RESULT_CODE\n"; + return "eSIR_SME_UNEXPECTED_REQ_RESULT_CODE"; case eSIR_SME_RESOURCES_UNAVAILABLE: - return "eSIR_SME_RESOURCES_UNAVAILABLE\n"; + return "eSIR_SME_RESOURCES_UNAVAILABLE"; case eSIR_SME_SCAN_FAILED: - return "eSIR_SME_SCAN_FAILED\n"; + return "eSIR_SME_SCAN_FAILED"; case eSIR_SME_BSS_ALREADY_STARTED_OR_JOINED: - return "eSIR_SME_BSS_ALREADY_STARTED_OR_JOINED\n"; + return "eSIR_SME_BSS_ALREADY_STARTED_OR_JOINED"; case eSIR_SME_LOST_LINK_WITH_PEER_RESULT_CODE: - return "eSIR_SME_LOST_LINK_WITH_PEER_RESULT_CODE\n"; + return "eSIR_SME_LOST_LINK_WITH_PEER_RESULT_CODE"; case eSIR_SME_REFUSED: - return "eSIR_SME_REFUSED\n"; + return "eSIR_SME_REFUSED"; case eSIR_SME_JOIN_TIMEOUT_RESULT_CODE: - return "eSIR_SME_JOIN_TIMEOUT_RESULT_CODE\n"; + return "eSIR_SME_JOIN_TIMEOUT_RESULT_CODE"; case eSIR_SME_AUTH_TIMEOUT_RESULT_CODE: - return "eSIR_SME_AUTH_TIMEOUT_RESULT_CODE\n"; + return "eSIR_SME_AUTH_TIMEOUT_RESULT_CODE"; case eSIR_SME_ASSOC_TIMEOUT_RESULT_CODE: - return "eSIR_SME_ASSOC_TIMEOUT_RESULT_CODE\n"; + return "eSIR_SME_ASSOC_TIMEOUT_RESULT_CODE"; case eSIR_SME_REASSOC_TIMEOUT_RESULT_CODE: - return "eSIR_SME_REASSOC_TIMEOUT_RESULT_CODE\n"; + return "eSIR_SME_REASSOC_TIMEOUT_RESULT_CODE"; case eSIR_SME_MAX_NUM_OF_PRE_AUTH_REACHED: - return "eSIR_SME_MAX_NUM_OF_PRE_AUTH_REACHED\n"; + return "eSIR_SME_MAX_NUM_OF_PRE_AUTH_REACHED"; case eSIR_SME_AUTH_REFUSED: - return "eSIR_SME_AUTH_REFUSED\n"; + return "eSIR_SME_AUTH_REFUSED"; case eSIR_SME_INVALID_WEP_DEFAULT_KEY: - return "eSIR_SME_INVALID_WEP_DEFAULT_KEY\n"; + return "eSIR_SME_INVALID_WEP_DEFAULT_KEY"; case eSIR_SME_ASSOC_REFUSED: - return "eSIR_SME_ASSOC_REFUSED\n"; + return "eSIR_SME_ASSOC_REFUSED"; case eSIR_SME_REASSOC_REFUSED: - return "eSIR_SME_REASSOC_REFUSED\n"; + return "eSIR_SME_REASSOC_REFUSED"; case eSIR_SME_STA_NOT_AUTHENTICATED: - return "eSIR_SME_STA_NOT_AUTHENTICATED\n"; + return "eSIR_SME_STA_NOT_AUTHENTICATED"; case eSIR_SME_STA_NOT_ASSOCIATED: - return "eSIR_SME_STA_NOT_ASSOCIATED\n"; + return "eSIR_SME_STA_NOT_ASSOCIATED"; case eSIR_SME_STA_DISASSOCIATED: - return "eSIR_SME_STA_DISASSOCIATED\n"; + return "eSIR_SME_STA_DISASSOCIATED"; case eSIR_SME_ALREADY_JOINED_A_BSS: - return "eSIR_SME_ALREADY_JOINED_A_BSS\n"; + return "eSIR_SME_ALREADY_JOINED_A_BSS"; case eSIR_ULA_COMPLETED: - return "eSIR_ULA_COMPLETED\n"; + return "eSIR_ULA_COMPLETED"; case eSIR_ULA_FAILURE: - return "eSIR_ULA_FAILURE\n"; + return "eSIR_ULA_FAILURE"; case eSIR_SME_LINK_ESTABLISHED: - return "eSIR_SME_LINK_ESTABLISHED\n"; + return "eSIR_SME_LINK_ESTABLISHED"; case eSIR_SME_UNABLE_TO_PERFORM_MEASUREMENTS: - return "eSIR_SME_UNABLE_TO_PERFORM_MEASUREMENTS\n"; + return "eSIR_SME_UNABLE_TO_PERFORM_MEASUREMENTS"; case eSIR_SME_UNABLE_TO_PERFORM_DFS: - return "eSIR_SME_UNABLE_TO_PERFORM_DFS\n"; + return "eSIR_SME_UNABLE_TO_PERFORM_DFS"; case eSIR_SME_DFS_FAILED: - return "eSIR_SME_DFS_FAILED\n"; + return "eSIR_SME_DFS_FAILED"; case eSIR_SME_TRANSFER_STA: - return "eSIR_SME_TRANSFER_STA\n"; + return "eSIR_SME_TRANSFER_STA"; case eSIR_SME_INVALID_LINK_TEST_PARAMETERS: - return "eSIR_SME_INVALID_LINK_TEST_PARAMETERS\n"; + return "eSIR_SME_INVALID_LINK_TEST_PARAMETERS"; case eSIR_SME_LINK_TEST_MAX_EXCEEDED: - return "eSIR_SME_LINK_TEST_MAX_EXCEEDED\n"; + return "eSIR_SME_LINK_TEST_MAX_EXCEEDED"; case eSIR_SME_UNSUPPORTED_RATE: - return "eSIR_SME_UNSUPPORTED_RATE\n"; + return "eSIR_SME_UNSUPPORTED_RATE"; case eSIR_SME_LINK_TEST_TIMEOUT: - return "eSIR_SME_LINK_TEST_TIMEOUT\n"; + return "eSIR_SME_LINK_TEST_TIMEOUT"; case eSIR_SME_LINK_TEST_COMPLETE: - return "eSIR_SME_LINK_TEST_COMPLETE\n"; + return "eSIR_SME_LINK_TEST_COMPLETE"; case eSIR_SME_LINK_TEST_INVALID_STATE: - return "eSIR_SME_LINK_TEST_INVALID_STATE\n"; + return "eSIR_SME_LINK_TEST_INVALID_STATE"; case eSIR_SME_LINK_TEST_INVALID_ADDRESS: - return "eSIR_SME_LINK_TEST_INVALID_ADDRESS\n"; + return "eSIR_SME_LINK_TEST_INVALID_ADDRESS"; case eSIR_SME_POLARIS_RESET: - return "eSIR_SME_POLARIS_RESET\n"; + return "eSIR_SME_POLARIS_RESET"; case eSIR_SME_SETCONTEXT_FAILED: - return "eSIR_SME_SETCONTEXT_FAILED\n"; + return "eSIR_SME_SETCONTEXT_FAILED"; case eSIR_SME_BSS_RESTART: - return "eSIR_SME_BSS_RESTART\n"; + return "eSIR_SME_BSS_RESTART"; case eSIR_SME_MORE_SCAN_RESULTS_FOLLOW: - return "eSIR_SME_MORE_SCAN_RESULTS_FOLLOW\n"; + return "eSIR_SME_MORE_SCAN_RESULTS_FOLLOW"; case eSIR_SME_INVALID_ASSOC_RSP_RXED: - return "eSIR_SME_INVALID_ASSOC_RSP_RXED\n"; + return "eSIR_SME_INVALID_ASSOC_RSP_RXED"; case eSIR_SME_MIC_COUNTER_MEASURES: - return "eSIR_SME_MIC_COUNTER_MEASURES\n"; + return "eSIR_SME_MIC_COUNTER_MEASURES"; case eSIR_SME_ADDTS_RSP_TIMEOUT: - return "eSIR_SME_ADDTS_RSP_TIMEOUT\n"; + return "eSIR_SME_ADDTS_RSP_TIMEOUT"; case eSIR_SME_RECEIVED: - return "eSIR_SME_RECEIVED\n"; + return "eSIR_SME_RECEIVED"; case eSIR_SME_CHANNEL_SWITCH_FAIL: - return "eSIR_SME_CHANNEL_SWITCH_FAIL\n"; + return "eSIR_SME_CHANNEL_SWITCH_FAIL"; #ifdef GEN4_SCAN case eSIR_SME_CHANNEL_SWITCH_DISABLED: - return "eSIR_SME_CHANNEL_SWITCH_DISABLED\n"; + return "eSIR_SME_CHANNEL_SWITCH_DISABLED"; case eSIR_SME_HAL_SCAN_INIT_FAILED: - return "eSIR_SME_HAL_SCAN_INIT_FAILED\n"; + return "eSIR_SME_HAL_SCAN_INIT_FAILED"; case eSIR_SME_HAL_SCAN_START_FAILED: - return "eSIR_SME_HAL_SCAN_START_FAILED\n"; + return "eSIR_SME_HAL_SCAN_START_FAILED"; case eSIR_SME_HAL_SCAN_END_FAILED: - return "eSIR_SME_HAL_SCAN_END_FAILED\n"; + return "eSIR_SME_HAL_SCAN_END_FAILED"; case eSIR_SME_HAL_SCAN_FINISH_FAILED: - return "eSIR_SME_HAL_SCAN_FINISH_FAILED\n"; + return "eSIR_SME_HAL_SCAN_FINISH_FAILED"; case eSIR_SME_HAL_SEND_MESSAGE_FAIL: - return "eSIR_SME_HAL_SEND_MESSAGE_FAIL\n"; + return "eSIR_SME_HAL_SEND_MESSAGE_FAIL"; #else // GEN4_SCAN case eSIR_SME_CHANNEL_SWITCH_DISABLED: - return "eSIR_SME_CHANNEL_SWITCH_DISABLED\n"; + return "eSIR_SME_CHANNEL_SWITCH_DISABLED"; case eSIR_SME_HAL_SEND_MESSAGE_FAIL: - return "eSIR_SME_HAL_SEND_MESSAGE_FAIL\n"; + return "eSIR_SME_HAL_SEND_MESSAGE_FAIL"; #endif // GEN4_SCAN default: - return "INVALID resultCode\n"; + return "INVALID resultCode"; } } @@ -849,13 +854,6 @@ limPrintMsgName(tpAniSirGlobal pMac, tANI_U16 logLevel, tANI_U32 msgType) limLog(pMac, logLevel, limMsgStr(msgType)); } - -#if defined(ANI_MIPS) || defined(ANI_ARM) -#define LINK 0 -#else -#define LINK 1 -#endif - void limPrintMsgInfo(tpAniSirGlobal pMac, tANI_U16 logLevel, tSirMsgQ *msg) { @@ -905,6 +903,13 @@ limInitMlm(tpAniSirGlobal pMac) /// Initialize scan result hash table limReInitScanResults(pMac); //sep26th review +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + /// Initialize lfr scan result hash table + // Could there be a problem in multisession with SAP/P2P GO, when in the + // middle of FW bg scan, SAP started; Again that could be a problem even on + // infra + SAP/P2P GO too - TBD + limReInitLfrScanResults(pMac); +#endif /// Initialize number of pre-auth contexts pMac->lim.gLimNumPreAuthContexts = 0; @@ -925,7 +930,7 @@ limInitMlm(tpAniSirGlobal pMac) } else { - limLog(pMac, LOGP, FL(" limCreateTimers Failed to create lim timers \n")); + limLog(pMac, LOGP, FL(" limCreateTimers Failed to create lim timers ")); } } /*** end limInitMlm() ***/ @@ -1098,6 +1103,10 @@ limCleanupMlm(tpAniSirGlobal pMac) /// Cleanup cached scan list limReInitScanResults(pMac); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + /// Cleanup cached scan list + limReInitLfrScanResults(pMac); +#endif } /*** end limCleanupMlm() ***/ @@ -1252,7 +1261,7 @@ void limPrintMacAddr(tpAniSirGlobal pMac, tSirMacAddr macAddr, tANI_U8 logLevel) { limLog(pMac, logLevel, - FL("%X:%X:%X:%X:%X:%X\n"), + FL("%X:%X:%X:%X:%X:%X"), macAddr[0], macAddr[1], macAddr[2], macAddr[3], macAddr[4], macAddr[5]); } /****** end limPrintMacAddr() ******/ @@ -1321,7 +1330,7 @@ void limResetDeferredMsgQ(tpAniSirGlobal pMac) tANI_U8 limWriteDeferredMsgQ(tpAniSirGlobal pMac, tpSirMsgQ limMsg) { PELOG1(limLog(pMac, LOG1, - FL("** Queue a deferred message (size %d, write %d) - type 0x%x **\n"), + FL("** Queue a deferred message (size %d, write %d) - type 0x%x **"), pMac->lim.gLimDeferredMsgQ.size, pMac->lim.gLimDeferredMsgQ.write, limMsg->type);) @@ -1332,7 +1341,7 @@ tANI_U8 limWriteDeferredMsgQ(tpAniSirGlobal pMac, tpSirMsgQ limMsg) { if(!(pMac->lim.deferredMsgCnt & 0xF)) { - PELOGE(limLog(pMac, LOGE, FL("Deferred Message Queue is full. Msg:%d Messages Failed:%d\n"), limMsg->type, ++pMac->lim.deferredMsgCnt);) + PELOGE(limLog(pMac, LOGE, FL("Deferred Message Queue is full. Msg:%d Messages Failed:%d"), limMsg->type, ++pMac->lim.deferredMsgCnt);) } else { @@ -1348,7 +1357,7 @@ tANI_U8 limWriteDeferredMsgQ(tpAniSirGlobal pMac, tpSirMsgQ limMsg) **/ if (pMac->lim.gLimDeferredMsgQ.size > 0) { - PELOGW(limLog(pMac, LOGW, FL("%d Deferred messages (type 0x%x, scan %d, global sme %d, global mlme %d, addts %d)\n"), + PELOGW(limLog(pMac, LOGW, FL("%d Deferred messages (type 0x%x, scan %d, global sme %d, global mlme %d, addts %d)"), pMac->lim.gLimDeferredMsgQ.size, limMsg->type, limIsSystemInScanState(pMac), pMac->lim.gLimSmeState, pMac->lim.gLimMlmState, @@ -1459,11 +1468,11 @@ tSirMsgQ* limReadDeferredMsgQ(tpAniSirGlobal pMac) pMac->lim.gLimDeferredMsgQ.read = 0; PELOG1(limLog(pMac, LOG1, - FL("** DeQueue a deferred message (size %d read %d) - type 0x%x **\n"), + FL("** DeQueue a deferred message (size %d read %d) - type 0x%x **"), pMac->lim.gLimDeferredMsgQ.size, pMac->lim.gLimDeferredMsgQ.read, msg->type);) - PELOG1(limLog(pMac, LOG1, FL("DQ msg -- scan %d, global sme %d, global mlme %d, addts %d\n"), + PELOG1(limLog(pMac, LOG1, FL("DQ msg -- scan %d, global sme %d, global mlme %d, addts %d"), limIsSystemInScanState(pMac), pMac->lim.gLimSmeState, pMac->lim.gLimMlmState, pMac->lim.gLimAddtsSent);) @@ -1603,7 +1612,7 @@ void limHandleUpdateOlbcCache(tpAniSirGlobal pMac) if (psessionEntry == NULL) { - PELOGE(limLog(pMac, LOGE, FL(" Session not found\n"));) + PELOGE(limLog(pMac, LOGE, FL(" Session not found"));) return; } @@ -1619,7 +1628,7 @@ void limHandleUpdateOlbcCache(tpAniSirGlobal pMac) if (!enable) { - PELOG2(limLog(pMac, LOG2, FL("Resetting OLBC cache\n"));) + PELOG2(limLog(pMac, LOG2, FL("Resetting OLBC cache"));) psessionEntry->gLimOlbcParams.numSta = 0; psessionEntry->gLimOverlap11gParams.numSta = 0; psessionEntry->gLimOverlapHt20Params.numSta = 0; @@ -1640,7 +1649,7 @@ void limHandleUpdateOlbcCache(tpAniSirGlobal pMac) { if (!psessionEntry->gLim11bParams.protectionEnabled) { - PELOG1(limLog(pMac, LOG1, FL("Overlap cache all clear and no 11B STA detected\n"));) + PELOG1(limLog(pMac, LOG1, FL("Overlap cache all clear and no 11B STA detected"));) limEnable11gProtection(pMac, false, true, &beaconParams, psessionEntry); } } @@ -1652,7 +1661,7 @@ void limHandleUpdateOlbcCache(tpAniSirGlobal pMac) { if (!psessionEntry->gLim11gParams.protectionEnabled) { - PELOG1(limLog(pMac, LOG1, FL("Overlap cache all clear and no 11G STA detected\n"));) + PELOG1(limLog(pMac, LOG1, FL("Overlap cache all clear and no 11G STA detected"));) limEnableHtProtectionFrom11g(pMac, false, true, &beaconParams,psessionEntry); } } @@ -1664,7 +1673,7 @@ void limHandleUpdateOlbcCache(tpAniSirGlobal pMac) { if (!psessionEntry->gLimHt20Params.protectionEnabled) { - PELOG1(limLog(pMac, LOG1, FL("Overlap cache all clear and no HT20 STA detected\n"));) + PELOG1(limLog(pMac, LOG1, FL("Overlap cache all clear and no HT20 STA detected"));) limEnable11gProtection(pMac, false, true, &beaconParams,psessionEntry); } } @@ -1682,7 +1691,7 @@ void limHandleUpdateOlbcCache(tpAniSirGlobal pMac) // Start OLBC timer if (tx_timer_activate(&pMac->lim.limTimers.gLimUpdateOlbcCacheTimer) != TX_SUCCESS) { - limLog(pMac, LOGE, FL("tx_timer_activate failed\n")); + limLog(pMac, LOGE, FL("tx_timer_activate failed")); } } @@ -1808,7 +1817,7 @@ tpPESession psessionEntry) psessionEntry->protStaCache[i].addr, peerMacAddr, sizeof(tSirMacAddr))) { - PELOG1(limLog(pMac, LOG1, FL("matching cache entry at %d already active.\n"), i);) + PELOG1(limLog(pMac, LOG1, FL("matching cache entry at %d already active."), i);) return; } } @@ -1822,7 +1831,7 @@ tpPESession psessionEntry) if (i >= LIM_PROT_STA_CACHE_SIZE) { - PELOGE(limLog(pMac, LOGE, FL("No space in ProtStaCache\n"));) + PELOGE(limLog(pMac, LOGE, FL("No space in ProtStaCache"));) return; } @@ -1856,7 +1865,7 @@ tpPESession psessionEntry) if(!lsigTxopSupported) { psessionEntry->gLimLsigTxopParams.numSta++; - limLog(pMac,LOG1, FL("!lsigTxopSupported\n")); + limLog(pMac,LOG1, FL("!lsigTxopSupported")); } }// --------------------------------------------------------------------- @@ -1884,7 +1893,7 @@ limDecideApProtection(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr, tpUpdateBeac pStaDs = dphLookupHashEntry(pMac, peerMacAddr, &tmpAid, &psessionEntry->dph.dphHashTable); if(NULL == pStaDs) { - PELOG1(limLog(pMac, LOG1, FL("pStaDs is NULL\n"));) + PELOG1(limLog(pMac, LOG1, FL("pStaDs is NULL"));) return; } limGetRfBand(pMac, &rfBand, psessionEntry); @@ -1917,7 +1926,7 @@ limDecideApProtection(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr, tpUpdateBeac { protStaCacheType = eLIM_PROT_STA_CACHE_TYPE_llB; // enable protection - PELOG3(limLog(pMac, LOG3, FL("Enabling protection from 11B\n"));) + PELOG3(limLog(pMac, LOG3, FL("Enabling protection from 11B"));) limEnable11gProtection(pMac, true, false, pBeaconParams,psessionEntry); } } @@ -1931,7 +1940,7 @@ limDecideApProtection(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr, tpUpdateBeac { protStaCacheType = eLIM_PROT_STA_CACHE_TYPE_llB; // enable protection - PELOG3(limLog(pMac, LOG3, FL("Enabling protection from 11B\n"));) + PELOG3(limLog(pMac, LOG3, FL("Enabling protection from 11B"));) limEnable11gProtection(pMac, true, false, pBeaconParams, psessionEntry); } //station being joined is non-11b and non-ht ==> 11g device @@ -1995,7 +2004,7 @@ tpUpdateBeaconParams pBeaconParams, tpSirMacMgmtHdr pMh,tpPESession psessionEntr !psessionEntry->gLimOlbcParams.protectionEnabled) { // enable protection - PELOG1(limLog(pMac, LOG1, FL("OLBC happens!!!\n"));) + PELOG1(limLog(pMac, LOG1, FL("OLBC happens!!!"));) limEnable11gProtection(pMac, true, true, pBeaconParams,psessionEntry); } } @@ -2099,10 +2108,10 @@ limUpdateShortPreamble(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr, // enable long preamble - PELOG1(limLog(pMac, LOG1, FL("Disabling short preamble\n"));) + PELOG1(limLog(pMac, LOG1, FL("Disabling short preamble"));) if (limEnableShortPreamble(pMac, false, pBeaconParams, psessionEntry) != eSIR_SUCCESS) - PELOGE(limLog(pMac, LOGE, FL("Cannot enable long preamble\n"));) + PELOGE(limLog(pMac, LOGE, FL("Cannot enable long preamble"));) } } } @@ -2217,7 +2226,7 @@ limUpdateShortSlotTime(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr, // enable long slot time pBeaconParams->fShortSlotTime = false; pBeaconParams->paramChangeBitmap |= PARAM_SHORT_SLOT_TIME_CHANGED; - PELOG1(limLog(pMac, LOG1, FL("Disable short slot time. Enable long slot time.\n"));) + PELOG1(limLog(pMac, LOG1, FL("Disable short slot time. Enable long slot time."));) psessionEntry->shortSlotTimeSupported = false; } else if ( psessionEntry->limSystemRole != eLIM_AP_ROLE) @@ -2227,7 +2236,7 @@ limUpdateShortSlotTime(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr, // enable long slot time pBeaconParams->fShortSlotTime = false; pBeaconParams->paramChangeBitmap |= PARAM_SHORT_SLOT_TIME_CHANGED; - PELOG1(limLog(pMac, LOG1, FL("Disable short slot time. Enable long slot time.\n"));) + PELOG1(limLog(pMac, LOG1, FL("Disable short slot time. Enable long slot time."));) psessionEntry->shortSlotTimeSupported = false; } } @@ -2533,13 +2542,13 @@ void limProcessChannelSwitchTimeout(tpAniSirGlobal pMac) if((psessionEntry = peFindSessionBySessionId(pMac, pMac->lim.limTimers.gLimChannelSwitchTimer.sessionId))== NULL) { - limLog(pMac, LOGP,FL("Session Does not exist for given sessionID\n")); + limLog(pMac, LOGP,FL("Session Does not exist for given sessionID")); return; } if (psessionEntry->limSystemRole != eLIM_STA_ROLE) { - PELOGW(limLog(pMac, LOGW, "Channel switch can be done only in STA role, Current Role = %d\n", psessionEntry->limSystemRole);) + PELOGW(limLog(pMac, LOGW, "Channel switch can be done only in STA role, Current Role = %d", psessionEntry->limSystemRole);) return; } channel = psessionEntry->gLimChannelSwitch.primaryChannel; @@ -2550,7 +2559,7 @@ void limProcessChannelSwitchTimeout(tpAniSirGlobal pMac) */ if(!limIsSystemInActiveState(pMac)) { - PELOGW(limLog(pMac, LOGW, FL("Device is not in active state, cannot switch channel\n"));) + PELOGW(limLog(pMac, LOGW, FL("Device is not in active state, cannot switch channel"));) return; } @@ -2569,7 +2578,7 @@ void limProcessChannelSwitchTimeout(tpAniSirGlobal pMac) /* We need to restore pre-channelSwitch state on the STA */ if(limRestorePreChannelSwitchState(pMac, psessionEntry) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("Could not restore pre-channelSwitch (11h) state, resetting the system\n")); + limLog(pMac, LOGP, FL("Could not restore pre-channelSwitch (11h) state, resetting the system")); return; } @@ -2585,13 +2594,13 @@ void limProcessChannelSwitchTimeout(tpAniSirGlobal pMac) switch(psessionEntry->gLimChannelSwitch.state) { case eLIM_CHANNEL_SWITCH_PRIMARY_ONLY: - PELOGW(limLog(pMac, LOGW, FL("CHANNEL_SWITCH_PRIMARY_ONLY \n"));) + PELOGW(limLog(pMac, LOGW, FL("CHANNEL_SWITCH_PRIMARY_ONLY "));) limSwitchPrimaryChannel(pMac, psessionEntry->gLimChannelSwitch.primaryChannel,psessionEntry); psessionEntry->gLimChannelSwitch.state = eLIM_CHANNEL_SWITCH_IDLE; break; case eLIM_CHANNEL_SWITCH_SECONDARY_ONLY: - PELOGW(limLog(pMac, LOGW, FL("CHANNEL_SWITCH_SECONDARY_ONLY \n"));) + PELOGW(limLog(pMac, LOGW, FL("CHANNEL_SWITCH_SECONDARY_ONLY "));) limSwitchPrimarySecondaryChannel(pMac, psessionEntry, psessionEntry->currentOperChannel, psessionEntry->gLimChannelSwitch.secondarySubBand); @@ -2599,7 +2608,7 @@ void limProcessChannelSwitchTimeout(tpAniSirGlobal pMac) break; case eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY: - PELOGW(limLog(pMac, LOGW, FL("CHANNEL_SWITCH_PRIMARY_AND_SECONDARY\n"));) + PELOGW(limLog(pMac, LOGW, FL("CHANNEL_SWITCH_PRIMARY_AND_SECONDARY"));) limSwitchPrimarySecondaryChannel(pMac, psessionEntry, psessionEntry->gLimChannelSwitch.primaryChannel, psessionEntry->gLimChannelSwitch.secondarySubBand); @@ -2608,10 +2617,10 @@ void limProcessChannelSwitchTimeout(tpAniSirGlobal pMac) case eLIM_CHANNEL_SWITCH_IDLE: default: - PELOGE(limLog(pMac, LOGE, FL("incorrect state \n"));) + PELOGE(limLog(pMac, LOGE, FL("incorrect state "));) if(limRestorePreChannelSwitchState(pMac, psessionEntry) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("Could not restore pre-channelSwitch (11h) state, resetting the system\n")); + limLog(pMac, LOGP, FL("Could not restore pre-channelSwitch (11h) state, resetting the system")); } return; /* Please note, this is 'return' and not 'break' */ } @@ -2721,11 +2730,11 @@ limUpdateChannelSwitch(struct sAniSirGlobal *pMac, tpSirProbeRespBeacon pBeacon } if (eSIR_SUCCESS != limStartChannelSwitch(pMac, psessionEntry)) { - PELOGW(limLog(pMac, LOGW, FL("Could not start Channel Switch\n"));) + PELOGW(limLog(pMac, LOGW, FL("Could not start Channel Switch"));) } limLog(pMac, LOGW, - FL("session %d primary chl %d, subband %d, count %d (%d ticks) \n"), + FL("session %d primary chl %d, subband %d, count %d (%d ticks) "), psessionEntry->peSessionId, psessionEntry->gLimChannelSwitch.primaryChannel, psessionEntry->gLimChannelSwitch.secondarySubBand, @@ -2757,18 +2766,18 @@ void limCancelDot11hChannelSwitch(tpAniSirGlobal pMac, tpPESession psessionEntry if (psessionEntry->limSystemRole != eLIM_STA_ROLE) return; - PELOGW(limLog(pMac, LOGW, FL("Received a beacon without channel switch IE\n"));) + PELOGW(limLog(pMac, LOGW, FL("Received a beacon without channel switch IE"));) MTRACE(macTrace(pMac, TRACE_CODE_TIMER_DEACTIVATE, psessionEntry->peSessionId, eLIM_CHANNEL_SWITCH_TIMER)); if (tx_timer_deactivate(&pMac->lim.limTimers.gLimChannelSwitchTimer) != eSIR_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("tx_timer_deactivate failed!\n"));) + PELOGE(limLog(pMac, LOGE, FL("tx_timer_deactivate failed!"));) } /* We need to restore pre-channelSwitch state on the STA */ if (limRestorePreChannelSwitchState(pMac, psessionEntry) != eSIR_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("LIM: Could not restore pre-channelSwitch (11h) state, resetting the system\n"));) + PELOGE(limLog(pMac, LOGE, FL("LIM: Could not restore pre-channelSwitch (11h) state, resetting the system"));) } } @@ -2791,7 +2800,7 @@ void limCancelDot11hQuiet(tpAniSirGlobal pMac, tpPESession psessionEntry) MTRACE(macTrace(pMac, TRACE_CODE_TIMER_DEACTIVATE, psessionEntry->peSessionId, eLIM_QUIET_TIMER)); if (tx_timer_deactivate(&pMac->lim.limTimers.gLimQuietTimer) != TX_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("tx_timer_deactivate failed\n"));) + PELOGE(limLog(pMac, LOGE, FL("tx_timer_deactivate failed"));) } } else if (psessionEntry->gLimSpecMgmt.quietState == eLIM_QUIET_RUNNING) @@ -2799,7 +2808,7 @@ void limCancelDot11hQuiet(tpAniSirGlobal pMac, tpPESession psessionEntry) MTRACE(macTrace(pMac, TRACE_CODE_TIMER_DEACTIVATE, psessionEntry->peSessionId, eLIM_QUIET_BSS_TIMER)); if (tx_timer_deactivate(&pMac->lim.limTimers.gLimQuietBssTimer) != TX_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("tx_timer_deactivate failed\n"));) + PELOGE(limLog(pMac, LOGE, FL("tx_timer_deactivate failed"));) } /** * If the channel switch is already running in silent mode, dont resume the @@ -2852,11 +2861,11 @@ void limProcessQuietTimeout(tpAniSirGlobal pMac) if((psessionEntry = peFindSessionBySessionId(pMac, pMac->lim.limTimers.gLimQuietTimer.sessionId))== NULL) { - limLog(pMac, LOGE,FL("Session Does not exist for given sessionID\n")); + limLog(pMac, LOGE,FL("Session Does not exist for given sessionID")); return; } - PELOG1(limLog(pMac, LOG1, FL("quietState = %d\n"), psessionEntry->gLimSpecMgmt.quietState);) + PELOG1(limLog(pMac, LOG1, FL("quietState = %d"), psessionEntry->gLimSpecMgmt.quietState);) switch( psessionEntry->gLimSpecMgmt.quietState ) { case eLIM_QUIET_BEGIN: @@ -2866,7 +2875,7 @@ void limProcessQuietTimeout(tpAniSirGlobal pMac) tx_timer_deactivate(&pMac->lim.limTimers.gLimQuietBssTimer)) { limLog( pMac, LOGE, - FL("Unable to de-activate gLimQuietBssTimer! Will attempt to activate anyway...\n")); + FL("Unable to de-activate gLimQuietBssTimer! Will attempt to activate anyway...")); } // gLimQuietDuration appears to be in units of ticks @@ -2877,7 +2886,7 @@ void limProcessQuietTimeout(tpAniSirGlobal pMac) 0)) { limLog( pMac, LOGE, - FL("Unable to change gLimQuietBssTimer! Will still attempt to activate anyway...\n")); + FL("Unable to change gLimQuietBssTimer! Will still attempt to activate anyway...")); } MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, pMac->lim.limTimers.gLimQuietTimer.sessionId, eLIM_QUIET_BSS_TIMER)); #ifdef GEN6_TODO @@ -2890,7 +2899,7 @@ void limProcessQuietTimeout(tpAniSirGlobal pMac) tx_timer_activate( &pMac->lim.limTimers.gLimQuietBssTimer )) { limLog( pMac, LOGW, - FL("Unable to activate gLimQuietBssTimer! The STA will be unable to honor Quiet BSS...\n")); + FL("Unable to activate gLimQuietBssTimer! The STA will be unable to honor Quiet BSS...")); } else { @@ -2903,7 +2912,7 @@ void limProcessQuietTimeout(tpAniSirGlobal pMac) (eSIR_TRUE == (glimTriggerBackgroundScanDuringQuietBss_Status = limTriggerBackgroundScanDuringQuietBss( pMac ))) ) { limLog( pMac, LOG2, - FL("Attempting to trigger a background scan...\n")); + FL("Attempting to trigger a background scan...")); } else { @@ -2912,7 +2921,7 @@ void limProcessQuietTimeout(tpAniSirGlobal pMac) limFrameTransmissionControl(pMac, eLIM_TX_ALL, eLIM_STOP_TX); limLog( pMac, LOG2, - FL("Quiet BSS: STA shutting down for %d ticks\n"), + FL("Quiet BSS: STA shutting down for %d ticks"), psessionEntry->gLimSpecMgmt.quietDuration ); } } @@ -2973,11 +2982,11 @@ void limProcessQuietBssTimeout( tpAniSirGlobal pMac ) if((psessionEntry = peFindSessionBySessionId(pMac, pMac->lim.limTimers.gLimQuietBssTimer.sessionId))== NULL) { - limLog(pMac, LOGP,FL("Session Does not exist for given sessionID\n")); + limLog(pMac, LOGP,FL("Session Does not exist for given sessionID")); return; } - PELOG1(limLog(pMac, LOG1, FL("quietState = %d\n"), psessionEntry->gLimSpecMgmt.quietState);) + PELOG1(limLog(pMac, LOG1, FL("quietState = %d"), psessionEntry->gLimSpecMgmt.quietState);) if (eLIM_AP_ROLE == psessionEntry->limSystemRole) { } @@ -3005,7 +3014,7 @@ void limProcessQuietBssTimeout( tpAniSirGlobal pMac ) glimTriggerBackgroundScanDuringQuietBss_Status = eSIR_TRUE; limLog( pMac, LOG2, - FL("Quiet BSS: Resuming traffic...\n")); + FL("Quiet BSS: Resuming traffic...")); } else { @@ -3015,14 +3024,14 @@ void limProcessQuietBssTimeout( tpAniSirGlobal pMac ) // SIR_LIM_QUIET_TIMEOUT will complete on its own // limLog( pMac, LOG2, - FL("Background scan should be complete now...\n")); + FL("Background scan should be complete now...")); } break; case eLIM_QUIET_INIT: case eLIM_QUIET_BEGIN: case eLIM_QUIET_END: - PELOG2(limLog(pMac, LOG2, FL("Quiet state not in RUNNING\n"));) + PELOG2(limLog(pMac, LOG2, FL("Quiet state not in RUNNING"));) /* If the quiet period has ended, then resume the frame transmission */ limFrameTransmissionControl(pMac, eLIM_TX_ALL, eLIM_RESUME_TX); limRestorePreQuietState(pMac, psessionEntry); @@ -3061,16 +3070,16 @@ void limProcessWPSOverlapTimeout(tpAniSirGlobal pMac) if (tx_timer_activate(&pMac->lim.limTimers.gLimWPSOverlapTimerObj.gLimWPSOverlapTimer) != TX_SUCCESS) { - limLog(pMac, LOGP, FL("tx_timer_activate failed\n")); + limLog(pMac, LOGP, FL("tx_timer_activate failed")); } sessionId = pMac->lim.limTimers.gLimWPSOverlapTimerObj.sessionId; - PELOGE(limLog(pMac, LOGE, FL("WPS overlap timeout, sessionId=%d\n"), sessionId);) + PELOGE(limLog(pMac, LOGE, FL("WPS overlap timeout, sessionId=%d"), sessionId);) if((psessionEntry = peFindSessionBySessionId(pMac, sessionId)) == NULL) { - PELOGE(limLog(pMac, LOGP,FL("Session Does not exist for given sessionID\n"));) + PELOGE(limLog(pMac, LOGP,FL("Session Does not exist for given sessionID"));) return; } @@ -3091,7 +3100,7 @@ void limStartQuietTimer(tpAniSirGlobal pMac, tANI_U8 sessionId) psessionEntry = peFindSessionBySessionId(pMac , sessionId); if(psessionEntry == NULL) { - limLog(pMac, LOGP,FL("Session Does not exist for given sessionID\n")); + limLog(pMac, LOGP,FL("Session Does not exist for given sessionID")); return; } @@ -3105,7 +3114,7 @@ void limStartQuietTimer(tpAniSirGlobal pMac, tANI_U8 sessionId) if( TX_SUCCESS != tx_timer_deactivate(&pMac->lim.limTimers.gLimQuietTimer)) { limLog( pMac, LOGE, - FL( "Unable to deactivate gLimQuietTimer! Will still attempt to re-activate anyway...\n" )); + FL( "Unable to deactivate gLimQuietTimer! Will still attempt to re-activate anyway..." )); } // Set the NEW timeout value, in ticks @@ -3113,14 +3122,14 @@ void limStartQuietTimer(tpAniSirGlobal pMac, tANI_U8 sessionId) SYS_MS_TO_TICKS(psessionEntry->gLimSpecMgmt.quietTimeoutValue), 0)) { limLog( pMac, LOGE, - FL( "Unable to change gLimQuietTimer! Will still attempt to re-activate anyway...\n" )); + FL( "Unable to change gLimQuietTimer! Will still attempt to re-activate anyway..." )); } pMac->lim.limTimers.gLimQuietTimer.sessionId = sessionId; if( TX_SUCCESS != tx_timer_activate(&pMac->lim.limTimers.gLimQuietTimer)) { limLog( pMac, LOGE, - FL("Unable to activate gLimQuietTimer! STA cannot honor Quiet BSS!\n")); + FL("Unable to activate gLimQuietTimer! STA cannot honor Quiet BSS!")); limRestorePreQuietState(pMac, psessionEntry); psessionEntry->gLimSpecMgmt.quietState = eLIM_QUIET_INIT; @@ -3177,7 +3186,7 @@ limUtilCountStaDel( if (pMac->lim.gLimNumOfAniSTAs <= 0) { - limLog(pMac, LOGE, FL("CountStaDel: ignoring Delete Req when AniPeer count is %d\n"), + limLog(pMac, LOGE, FL("CountStaDel: ignoring Delete Req when AniPeer count is %d"), pMac->lim.gLimNumOfAniSTAs); return; } @@ -3216,14 +3225,14 @@ void limSwitchChannelCback(tpAniSirGlobal pMac, eHalStatus status, /* We need to restore pre-channelSwitch state on the STA */ if (limRestorePreChannelSwitchState(pMac, psessionEntry) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("Could not restore pre-channelSwitch (11h) state, resetting the system\n")); + limLog(pMac, LOGP, FL("Could not restore pre-channelSwitch (11h) state, resetting the system")); return; } mmhMsg.type = eWNI_SME_SWITCH_CHL_REQ; if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pSirSmeSwitchChInd, sizeof(tSirSmeSwitchChannelInd))) { - limLog(pMac, LOGP, FL("Failed to allocate buffer for buffer descriptor\n")); + limLog(pMac, LOGP, FL("Failed to allocate buffer for buffer descriptor")); return; } @@ -3259,7 +3268,7 @@ void limSwitchPrimaryChannel(tpAniSirGlobal pMac, tANI_U8 newChannel,tpPESession tANI_U32 localPwrConstraint; #endif - PELOG3(limLog(pMac, LOG3, FL("limSwitchPrimaryChannel: old chnl %d --> new chnl %d \n"), + PELOG3(limLog(pMac, LOG3, FL("limSwitchPrimaryChannel: old chnl %d --> new chnl %d "), psessionEntry->currentOperChannel, newChannel);) psessionEntry->currentReqChannel = newChannel; psessionEntry->limRFBand = limGetRFBand(newChannel); @@ -3275,7 +3284,7 @@ void limSwitchPrimaryChannel(tpAniSirGlobal pMac, tANI_U8 newChannel,tpPESession #else if(wlan_cfgGetInt(pMac, WNI_CFG_LOCAL_POWER_CONSTRAINT, &localPwrConstraint) != eSIR_SUCCESS) { - limLog( pMac, LOGP, FL( "Unable to read Local Power Constraint from cfg\n" )); + limLog( pMac, LOGP, FL( "Unable to read Local Power Constraint from cfg" )); return; } limSendSwitchChnlParams(pMac, newChannel, PHY_SINGLE_CHANNEL_CENTERED, @@ -3311,7 +3320,7 @@ void limSwitchPrimarySecondaryChannel(tpAniSirGlobal pMac, tpPESession psessionE #if !defined WLAN_FEATURE_VOWIFI if(wlan_cfgGetInt(pMac, WNI_CFG_LOCAL_POWER_CONSTRAINT, &localPwrConstraint) != eSIR_SUCCESS) { - limLog( pMac, LOGP, FL( "Unable to get Local Power Constraint from cfg\n" )); + limLog( pMac, LOGP, FL( "Unable to get Local Power Constraint from cfg" )); return; } #endif @@ -3326,14 +3335,14 @@ void limSwitchPrimarySecondaryChannel(tpAniSirGlobal pMac, tpPESession psessionE if (psessionEntry->currentOperChannel != newChannel) { limLog(pMac, LOGW, - FL("switch old chnl %d --> new chnl %d \n"), + FL("switch old chnl %d --> new chnl %d "), psessionEntry->currentOperChannel, newChannel); psessionEntry->currentOperChannel = newChannel; } if (psessionEntry->htSecondaryChannelOffset != subband) { limLog(pMac, LOGW, - FL("switch old sec chnl %d --> new sec chnl %d \n"), + FL("switch old sec chnl %d --> new sec chnl %d "), psessionEntry->htSecondaryChannelOffset, subband); psessionEntry->htSecondaryChannelOffset = subband; if (psessionEntry->htSecondaryChannelOffset == PHY_SINGLE_CHANNEL_CENTERED) @@ -3381,13 +3390,13 @@ tANI_U8 limActiveScanAllowed( if (wlan_cfgGetStr(pMac, WNI_CFG_SCAN_CONTROL_LIST, channelPair, &len) != eSIR_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("Unable to get scan control list\n"));) + PELOGE(limLog(pMac, LOGE, FL("Unable to get scan control list"));) return false; } if (len > WNI_CFG_SCAN_CONTROL_LIST_LEN) { - limLog(pMac, LOGE, FL("Invalid scan control list length:%d\n"), + limLog(pMac, LOGE, FL("Invalid scan control list length:%d"), len); return false; } @@ -3473,13 +3482,13 @@ tAniBool limTriggerBackgroundScanDuringQuietBss( tpAniSirGlobal pMac ) else { limLog( pMac, LOGW, - FL("The next SCAN channel is the current operating channel on which a Quiet BSS is requested.! A background scan will not be triggered during this Quiet BSS period...\n")); + FL("The next SCAN channel is the current operating channel on which a Quiet BSS is requested.! A background scan will not be triggered during this Quiet BSS period...")); } } else { limLog( pMac, LOGW, - FL("Unable to retrieve WNI_CFG_VALID_CHANNEL_LIST from CFG! A background scan will not be triggered during this Quiet BSS period...\n")); + FL("Unable to retrieve WNI_CFG_VALID_CHANNEL_LIST from CFG! A background scan will not be triggered during this Quiet BSS period...")); } } return bScanTriggered; @@ -3739,7 +3748,7 @@ limEnable11aProtection(tpAniSirGlobal pMac, tANI_U8 enable, { if(NULL == psessionEntry) { - PELOG3(limLog(pMac, LOG3, FL("psessionEntry is NULL\n"));) + PELOG3(limLog(pMac, LOG3, FL("psessionEntry is NULL"));) return eSIR_FAILURE; } //overlapping protection configuration check. @@ -3753,7 +3762,7 @@ limEnable11aProtection(tpAniSirGlobal pMac, tANI_U8 enable, (!psessionEntry->cfgProtection.fromlla)) { // protection disabled. - PELOG3(limLog(pMac, LOG3, FL("protection from 11a is disabled\n"));) + PELOG3(limLog(pMac, LOG3, FL("protection from 11a is disabled"));) return eSIR_SUCCESS; } } @@ -3794,7 +3803,7 @@ limEnable11aProtection(tpAniSirGlobal pMac, tANI_U8 enable, //This part is common for staiton as well. if(false == psessionEntry->beaconParams.llaCoexist) { - PELOG1(limLog(pMac, LOG1, FL(" => protection from 11A Enabled\n"));) + PELOG1(limLog(pMac, LOG1, FL(" => protection from 11A Enabled"));) pBeaconParams->llaCoexist = psessionEntry->beaconParams.llaCoexist = true; pBeaconParams->paramChangeBitmap |= PARAM_llACOEXIST_CHANGED; } @@ -3870,7 +3879,7 @@ limEnable11aProtection(tpAniSirGlobal pMac, tANI_U8 enable, if(!pMac->lim.gLimOverlap11aParams.protectionEnabled && !psessionEntry->gLim11aParams.protectionEnabled) { - PELOG1(limLog(pMac, LOG1, FL("===> Protection from 11A Disabled\n"));) + PELOG1(limLog(pMac, LOG1, FL("===> Protection from 11A Disabled"));) pBeaconParams->llaCoexist = psessionEntry->beaconParams.llaCoexist = false; pBeaconParams->paramChangeBitmap |= PARAM_llACOEXIST_CHANGED; } @@ -3878,7 +3887,7 @@ limEnable11aProtection(tpAniSirGlobal pMac, tANI_U8 enable, //for station role else { - PELOG1(limLog(pMac, LOG1, FL("===> Protection from 11A Disabled\n"));) + PELOG1(limLog(pMac, LOG1, FL("===> Protection from 11A Disabled"));) pBeaconParams->llaCoexist = psessionEntry->beaconParams.llaCoexist = false; pBeaconParams->paramChangeBitmap |= PARAM_llACOEXIST_CHANGED; } @@ -3912,14 +3921,14 @@ limEnable11gProtection(tpAniSirGlobal pMac, tANI_U8 enable, !psessionEntry->cfgProtection.fromllb) { // protection disabled. - PELOG1(limLog(pMac, LOG1, FL("protection from 11b is disabled\n"));) + PELOG1(limLog(pMac, LOG1, FL("protection from 11b is disabled"));) return eSIR_SUCCESS; }else if(psessionEntry->limSystemRole != eLIM_AP_ROLE) { if(!pMac->lim.cfgProtection.fromllb) { // protection disabled. - PELOG1(limLog(pMac, LOG1, FL("protection from 11b is disabled\n"));) + PELOG1(limLog(pMac, LOG1, FL("protection from 11b is disabled"));) return eSIR_SUCCESS; } } @@ -3934,7 +3943,7 @@ limEnable11gProtection(tpAniSirGlobal pMac, tANI_U8 enable, if(overlap) { psessionEntry->gLimOlbcParams.protectionEnabled = true; - PELOGE(limLog(pMac, LOGE, FL("protection from olbc is enabled\n"));) + PELOGE(limLog(pMac, LOGE, FL("protection from olbc is enabled"));) if(true == psessionEntry->htCapability) { if((eSIR_HT_OP_MODE_OVERLAP_LEGACY != psessionEntry->htOperMode) && @@ -3953,7 +3962,7 @@ limEnable11gProtection(tpAniSirGlobal pMac, tANI_U8 enable, else { psessionEntry->gLim11bParams.protectionEnabled = true; - PELOGE(limLog(pMac, LOGE, FL("protection from 11b is enabled\n"));) + PELOGE(limLog(pMac, LOGE, FL("protection from 11b is enabled"));) if(true == psessionEntry->htCapability) { if(eSIR_HT_OP_MODE_MIXED != psessionEntry->htOperMode) @@ -3997,7 +4006,7 @@ limEnable11gProtection(tpAniSirGlobal pMac, tANI_U8 enable, //This part is common for staiton as well. if(false == psessionEntry->beaconParams.llbCoexist) { - PELOG1(limLog(pMac, LOG1, FL("=> 11G Protection Enabled\n"));) + PELOG1(limLog(pMac, LOG1, FL("=> 11G Protection Enabled"));) pBeaconParams->llbCoexist = psessionEntry->beaconParams.llbCoexist = true; pBeaconParams->paramChangeBitmap |= PARAM_llBCOEXIST_CHANGED; } @@ -4042,7 +4051,7 @@ limEnable11gProtection(tpAniSirGlobal pMac, tANI_U8 enable, { //Disable protection from 11B stations. psessionEntry->gLim11bParams.protectionEnabled = false; - PELOGE(limLog(pMac, LOGE, FL("===> 11B Protection Disabled\n"));) + PELOGE(limLog(pMac, LOGE, FL("===> 11B Protection Disabled"));) //Check if any other non-HT protection enabled. if(!psessionEntry->gLim11gParams.protectionEnabled) { @@ -4057,7 +4066,7 @@ limEnable11gProtection(tpAniSirGlobal pMac, tANI_U8 enable, psessionEntry->gLimOverlapNonGfParams.protectionEnabled) { psessionEntry->htOperMode = eSIR_HT_OP_MODE_OVERLAP_LEGACY; - PELOGE(limLog(pMac, LOGE, FL("===> 11G Protection Disabled\n"));) + PELOGE(limLog(pMac, LOGE, FL("===> 11G Protection Disabled"));) limEnableHtRifsProtection(pMac, true, overlap, pBeaconParams,psessionEntry); } else if(psessionEntry->gLimHt20Params.protectionEnabled) @@ -4065,7 +4074,7 @@ limEnable11gProtection(tpAniSirGlobal pMac, tANI_U8 enable, //Commenting because of CR 258588 WFA cert //psessionEntry->htOperMode = eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT; psessionEntry->htOperMode = eSIR_HT_OP_MODE_PURE; - PELOGE(limLog(pMac, LOGE, FL("===> 11G Protection Disabled\n"));) + PELOGE(limLog(pMac, LOGE, FL("===> 11G Protection Disabled"));) limEnableHtRifsProtection(pMac, false, overlap, pBeaconParams,psessionEntry); } else @@ -4078,7 +4087,7 @@ limEnable11gProtection(tpAniSirGlobal pMac, tANI_U8 enable, if(!psessionEntry->gLimOlbcParams.protectionEnabled && !psessionEntry->gLim11bParams.protectionEnabled) { - PELOGE(limLog(pMac, LOGE, FL("===> 11G Protection Disabled\n"));) + PELOGE(limLog(pMac, LOGE, FL("===> 11G Protection Disabled"));) pBeaconParams->llbCoexist = psessionEntry->beaconParams.llbCoexist = false; pBeaconParams->paramChangeBitmap |= PARAM_llBCOEXIST_CHANGED; } @@ -4147,7 +4156,7 @@ limEnable11gProtection(tpAniSirGlobal pMac, tANI_U8 enable, if(!psessionEntry->gLimOlbcParams.protectionEnabled && !psessionEntry->gLim11bParams.protectionEnabled) { - PELOG1(limLog(pMac, LOG1, FL("===> 11G Protection Disabled\n"));) + PELOG1(limLog(pMac, LOG1, FL("===> 11G Protection Disabled"));) pBeaconParams->llbCoexist = psessionEntry->beaconParams.llbCoexist = false; pBeaconParams->paramChangeBitmap |= PARAM_llBCOEXIST_CHANGED; } @@ -4155,7 +4164,7 @@ limEnable11gProtection(tpAniSirGlobal pMac, tANI_U8 enable, //for station role else { - PELOG1(limLog(pMac, LOG1, FL("===> 11G Protection Disabled\n"));) + PELOG1(limLog(pMac, LOG1, FL("===> 11G Protection Disabled"));) pBeaconParams->llbCoexist = psessionEntry->beaconParams.llbCoexist = false; pBeaconParams->paramChangeBitmap |= PARAM_llBCOEXIST_CHANGED; } @@ -4184,12 +4193,12 @@ limEnableHtProtectionFrom11g(tpAniSirGlobal pMac, tANI_U8 enable, if((psessionEntry->limSystemRole == eLIM_AP_ROLE ) && (!psessionEntry->cfgProtection.overlapFromllg)) { // protection disabled. - PELOG3(limLog(pMac, LOG3, FL("overlap protection from 11g is disabled\n"));); + PELOG3(limLog(pMac, LOG3, FL("overlap protection from 11g is disabled"));); return eSIR_SUCCESS; }else if ((psessionEntry->limSystemRole == eLIM_BT_AMP_AP_ROLE) && (!pMac->lim.cfgProtection.overlapFromllg)) { // protection disabled. - PELOG3(limLog(pMac, LOG3, FL("overlap protection from 11g is disabled\n"));); + PELOG3(limLog(pMac, LOG3, FL("overlap protection from 11g is disabled"));); return eSIR_SUCCESS; } } @@ -4199,14 +4208,14 @@ limEnableHtProtectionFrom11g(tpAniSirGlobal pMac, tANI_U8 enable, if((psessionEntry->limSystemRole == eLIM_AP_ROLE ) && !psessionEntry->cfgProtection.fromllg){ // protection disabled. - PELOG3(limLog(pMac, LOG3, FL("protection from 11g is disabled\n"));) + PELOG3(limLog(pMac, LOG3, FL("protection from 11g is disabled"));) return eSIR_SUCCESS; }else if(psessionEntry->limSystemRole != eLIM_AP_ROLE ) { if(!pMac->lim.cfgProtection.fromllg) { // protection disabled. - PELOG3(limLog(pMac, LOG3, FL("protection from 11g is disabled\n"));) + PELOG3(limLog(pMac, LOG3, FL("protection from 11g is disabled"));) return eSIR_SUCCESS; } } @@ -4361,7 +4370,7 @@ limEnableHtProtectionFrom11g(tpAniSirGlobal pMac, tANI_U8 enable, if(!psessionEntry->gLimOverlap11gParams.protectionEnabled && !psessionEntry->gLim11gParams.protectionEnabled) { - PELOG1(limLog(pMac, LOG1, FL("===> Protection from 11G Disabled\n"));) + PELOG1(limLog(pMac, LOG1, FL("===> Protection from 11G Disabled"));) pBeaconParams->llgCoexist = psessionEntry->beaconParams.llgCoexist = false; pBeaconParams->paramChangeBitmap |= PARAM_llGCOEXIST_CHANGED; } @@ -4427,7 +4436,7 @@ limEnableHtProtectionFrom11g(tpAniSirGlobal pMac, tANI_U8 enable, if(!pMac->lim.gLimOverlap11gParams.protectionEnabled && !psessionEntry->gLim11gParams.protectionEnabled) { - PELOG1(limLog(pMac, LOG1, FL("===> Protection from 11G Disabled\n"));) + PELOG1(limLog(pMac, LOG1, FL("===> Protection from 11G Disabled"));) pBeaconParams->llgCoexist = psessionEntry->beaconParams.llgCoexist = false; pBeaconParams->paramChangeBitmap |= PARAM_llGCOEXIST_CHANGED; } @@ -4435,7 +4444,7 @@ limEnableHtProtectionFrom11g(tpAniSirGlobal pMac, tANI_U8 enable, //for station role else { - PELOG1(limLog(pMac, LOG1, FL("===> Protection from 11G Disabled\n"));) + PELOG1(limLog(pMac, LOG1, FL("===> Protection from 11G Disabled"));) pBeaconParams->llgCoexist = psessionEntry->beaconParams.llgCoexist = false; pBeaconParams->paramChangeBitmap |= PARAM_llGCOEXIST_CHANGED; } @@ -4473,14 +4482,14 @@ limEnableHtOBSSProtection(tpAniSirGlobal pMac, tANI_U8 enable, if((psessionEntry->limSystemRole == eLIM_AP_ROLE) && !psessionEntry->cfgProtection.obss) { //ToDo Update this field // protection disabled. - PELOG1(limLog(pMac, LOG1, FL("protection from Obss is disabled\n"));) + PELOG1(limLog(pMac, LOG1, FL("protection from Obss is disabled"));) return eSIR_SUCCESS; }else if(psessionEntry->limSystemRole != eLIM_AP_ROLE) { if(!pMac->lim.cfgProtection.obss) { //ToDo Update this field // protection disabled. - PELOG1(limLog(pMac, LOG1, FL("protection from Obss is disabled\n"));) + PELOG1(limLog(pMac, LOG1, FL("protection from Obss is disabled"));) return eSIR_SUCCESS; } } @@ -4490,14 +4499,14 @@ limEnableHtOBSSProtection(tpAniSirGlobal pMac, tANI_U8 enable, if (eLIM_AP_ROLE == psessionEntry->limSystemRole){ if ((enable) && (false == psessionEntry->beaconParams.gHTObssMode) ) { - PELOG1(limLog(pMac, LOG1, FL("=>obss protection enabled\n"));) + PELOG1(limLog(pMac, LOG1, FL("=>obss protection enabled"));) psessionEntry->beaconParams.gHTObssMode = true; pBeaconParams->paramChangeBitmap |= PARAM_OBSS_MODE_CHANGED; // UPDATE AN ENUM FOR OBSS MODE } else if (!enable && (true == psessionEntry->beaconParams.gHTObssMode)) { - PELOG1(limLog(pMac, LOG1, FL("===> obss Protection disabled\n"));) + PELOG1(limLog(pMac, LOG1, FL("===> obss Protection disabled"));) psessionEntry->beaconParams.gHTObssMode = false; pBeaconParams->paramChangeBitmap |= PARAM_OBSS_MODE_CHANGED; @@ -4511,7 +4520,7 @@ limEnableHtOBSSProtection(tpAniSirGlobal pMac, tANI_U8 enable, { if ((enable) && (false == psessionEntry->beaconParams.gHTObssMode) ) { - PELOG1(limLog(pMac, LOG1, FL("=>obss protection enabled\n"));) + PELOG1(limLog(pMac, LOG1, FL("=>obss protection enabled"));) psessionEntry->beaconParams.gHTObssMode = true; pBeaconParams->paramChangeBitmap |= PARAM_OBSS_MODE_CHANGED; // UPDATE AN ENUM FOR OBSS MODE @@ -4519,7 +4528,7 @@ limEnableHtOBSSProtection(tpAniSirGlobal pMac, tANI_U8 enable, else if (!enable && (true == psessionEntry->beaconParams.gHTObssMode)) { - PELOG1(limLog(pMac, LOG1, FL("===> obss Protection disabled\n"));) + PELOG1(limLog(pMac, LOG1, FL("===> obss Protection disabled"));) psessionEntry->beaconParams.gHTObssMode = false; pBeaconParams->paramChangeBitmap |= PARAM_OBSS_MODE_CHANGED; @@ -4553,14 +4562,14 @@ limEnableHT20Protection(tpAniSirGlobal pMac, tANI_U8 enable, !psessionEntry->cfgProtection.ht20) { // protection disabled. - PELOG3(limLog(pMac, LOG3, FL("protection from HT20 is disabled\n"));) + PELOG3(limLog(pMac, LOG3, FL("protection from HT20 is disabled"));) return eSIR_SUCCESS; }else if(psessionEntry->limSystemRole != eLIM_AP_ROLE ) { if(!pMac->lim.cfgProtection.ht20) { // protection disabled. - PELOG3(limLog(pMac, LOG3, FL("protection from HT20 is disabled\n"));) + PELOG3(limLog(pMac, LOG3, FL("protection from HT20 is disabled"));) return eSIR_SUCCESS; } } @@ -4621,7 +4630,7 @@ limEnableHT20Protection(tpAniSirGlobal pMac, tANI_U8 enable, //This part is common for staiton as well. if(false == psessionEntry->beaconParams.ht20Coexist) { - PELOG1(limLog(pMac, LOG1, FL("=> Prtection from HT20 Enabled\n"));) + PELOG1(limLog(pMac, LOG1, FL("=> Prtection from HT20 Enabled"));) pBeaconParams->ht20MhzCoexist = psessionEntry->beaconParams.ht20Coexist = true; pBeaconParams->paramChangeBitmap |= PARAM_HT20MHZCOEXIST_CHANGED; } @@ -4675,7 +4684,7 @@ limEnableHT20Protection(tpAniSirGlobal pMac, tANI_U8 enable, limEnableHtOBSSProtection(pMac, false, overlap, pBeaconParams,psessionEntry); } } - PELOG1(limLog(pMac, LOG1, FL("===> Protection from HT 20 Disabled\n"));) + PELOG1(limLog(pMac, LOG1, FL("===> Protection from HT 20 Disabled"));) pBeaconParams->ht20MhzCoexist = psessionEntry->beaconParams.ht20Coexist = false; pBeaconParams->paramChangeBitmap |= PARAM_HT20MHZCOEXIST_CHANGED; }else if(eLIM_BT_AMP_AP_ROLE == psessionEntry->limSystemRole) @@ -4721,14 +4730,14 @@ limEnableHT20Protection(tpAniSirGlobal pMac, tANI_U8 enable, limEnableHtOBSSProtection(pMac, false, overlap, pBeaconParams,psessionEntry); } } - PELOG1(limLog(pMac, LOG1, FL("===> Protection from HT 20 Disabled\n"));) + PELOG1(limLog(pMac, LOG1, FL("===> Protection from HT 20 Disabled"));) pBeaconParams->ht20MhzCoexist = psessionEntry->beaconParams.ht20Coexist = false; pBeaconParams->paramChangeBitmap |= PARAM_HT20MHZCOEXIST_CHANGED; } //for station role else { - PELOG1(limLog(pMac, LOG1, FL("===> Protection from HT20 Disabled\n"));) + PELOG1(limLog(pMac, LOG1, FL("===> Protection from HT20 Disabled"));) pBeaconParams->ht20MhzCoexist = psessionEntry->beaconParams.ht20Coexist = false; pBeaconParams->paramChangeBitmap |= PARAM_HT20MHZCOEXIST_CHANGED; } @@ -4763,7 +4772,7 @@ limEnableHTNonGfProtection(tpAniSirGlobal pMac, tANI_U8 enable, !psessionEntry->cfgProtection.nonGf) { // protection disabled. - PELOG3(limLog(pMac, LOG3, FL("protection from NonGf is disabled\n"));) + PELOG3(limLog(pMac, LOG3, FL("protection from NonGf is disabled"));) return eSIR_SUCCESS; }else if(psessionEntry->limSystemRole != eLIM_AP_ROLE) { @@ -4771,7 +4780,7 @@ limEnableHTNonGfProtection(tpAniSirGlobal pMac, tANI_U8 enable, if(!pMac->lim.cfgProtection.nonGf) { // protection disabled. - PELOG3(limLog(pMac, LOG3, FL("protection from NonGf is disabled\n"));) + PELOG3(limLog(pMac, LOG3, FL("protection from NonGf is disabled"));) return eSIR_SUCCESS; } } @@ -4779,13 +4788,13 @@ limEnableHTNonGfProtection(tpAniSirGlobal pMac, tANI_U8 enable, if(psessionEntry->limSystemRole == eLIM_AP_ROLE){ if ((enable) && (false == psessionEntry->beaconParams.llnNonGFCoexist)) { - PELOG1(limLog(pMac, LOG1, FL(" => Prtection from non GF Enabled\n"));) + PELOG1(limLog(pMac, LOG1, FL(" => Prtection from non GF Enabled"));) pBeaconParams->llnNonGFCoexist = psessionEntry->beaconParams.llnNonGFCoexist = true; pBeaconParams->paramChangeBitmap |= PARAM_NON_GF_DEVICES_PRESENT_CHANGED; } else if (!enable && (true == psessionEntry->beaconParams.llnNonGFCoexist)) { - PELOG1(limLog(pMac, LOG1, FL("===> Protection from Non GF Disabled\n"));) + PELOG1(limLog(pMac, LOG1, FL("===> Protection from Non GF Disabled"));) pBeaconParams->llnNonGFCoexist = psessionEntry->beaconParams.llnNonGFCoexist = false; pBeaconParams->paramChangeBitmap |= PARAM_NON_GF_DEVICES_PRESENT_CHANGED; } @@ -4793,13 +4802,13 @@ limEnableHTNonGfProtection(tpAniSirGlobal pMac, tANI_U8 enable, { if ((enable) && (false == psessionEntry->beaconParams.llnNonGFCoexist)) { - PELOG1(limLog(pMac, LOG1, FL(" => Prtection from non GF Enabled\n"));) + PELOG1(limLog(pMac, LOG1, FL(" => Prtection from non GF Enabled"));) pBeaconParams->llnNonGFCoexist = psessionEntry->beaconParams.llnNonGFCoexist = true; pBeaconParams->paramChangeBitmap |= PARAM_NON_GF_DEVICES_PRESENT_CHANGED; } else if (!enable && (true == psessionEntry->beaconParams.llnNonGFCoexist)) { - PELOG1(limLog(pMac, LOG1, FL("===> Protection from Non GF Disabled\n"));) + PELOG1(limLog(pMac, LOG1, FL("===> Protection from Non GF Disabled"));) pBeaconParams->llnNonGFCoexist = psessionEntry->beaconParams.llnNonGFCoexist = false; pBeaconParams->paramChangeBitmap |= PARAM_NON_GF_DEVICES_PRESENT_CHANGED; } @@ -4834,7 +4843,7 @@ limEnableHTLsigTxopProtection(tpAniSirGlobal pMac, tANI_U8 enable, !psessionEntry->cfgProtection.lsigTxop) { // protection disabled. - PELOG3(limLog(pMac, LOG3, FL(" protection from LsigTxop not supported is disabled\n"));) + PELOG3(limLog(pMac, LOG3, FL(" protection from LsigTxop not supported is disabled"));) return eSIR_SUCCESS; }else if(psessionEntry->limSystemRole != eLIM_AP_ROLE) { @@ -4842,7 +4851,7 @@ limEnableHTLsigTxopProtection(tpAniSirGlobal pMac, tANI_U8 enable, if(!pMac->lim.cfgProtection.lsigTxop) { // protection disabled. - PELOG3(limLog(pMac, LOG3, FL(" protection from LsigTxop not supported is disabled\n"));) + PELOG3(limLog(pMac, LOG3, FL(" protection from LsigTxop not supported is disabled"));) return eSIR_SUCCESS; } } @@ -4852,13 +4861,13 @@ limEnableHTLsigTxopProtection(tpAniSirGlobal pMac, tANI_U8 enable, if(psessionEntry->limSystemRole == eLIM_AP_ROLE){ if ((enable) && (false == psessionEntry->beaconParams.fLsigTXOPProtectionFullSupport)) { - PELOG1(limLog(pMac, LOG1, FL(" => Prtection from LsigTxop Enabled\n"));) + PELOG1(limLog(pMac, LOG1, FL(" => Prtection from LsigTxop Enabled"));) pBeaconParams->fLsigTXOPProtectionFullSupport = psessionEntry->beaconParams.fLsigTXOPProtectionFullSupport = true; pBeaconParams->paramChangeBitmap |= PARAM_LSIG_TXOP_FULL_SUPPORT_CHANGED; } else if (!enable && (true == psessionEntry->beaconParams.fLsigTXOPProtectionFullSupport)) { - PELOG1(limLog(pMac, LOG1, FL("===> Protection from LsigTxop Disabled\n"));) + PELOG1(limLog(pMac, LOG1, FL("===> Protection from LsigTxop Disabled"));) pBeaconParams->fLsigTXOPProtectionFullSupport= psessionEntry->beaconParams.fLsigTXOPProtectionFullSupport = false; pBeaconParams->paramChangeBitmap |= PARAM_LSIG_TXOP_FULL_SUPPORT_CHANGED; } @@ -4866,13 +4875,13 @@ limEnableHTLsigTxopProtection(tpAniSirGlobal pMac, tANI_U8 enable, { if ((enable) && (false == psessionEntry->beaconParams.fLsigTXOPProtectionFullSupport)) { - PELOG1(limLog(pMac, LOG1, FL(" => Prtection from LsigTxop Enabled\n"));) + PELOG1(limLog(pMac, LOG1, FL(" => Prtection from LsigTxop Enabled"));) pBeaconParams->fLsigTXOPProtectionFullSupport = psessionEntry->beaconParams.fLsigTXOPProtectionFullSupport = true; pBeaconParams->paramChangeBitmap |= PARAM_LSIG_TXOP_FULL_SUPPORT_CHANGED; } else if (!enable && (true == psessionEntry->beaconParams.fLsigTXOPProtectionFullSupport)) { - PELOG1(limLog(pMac, LOG1, FL("===> Protection from LsigTxop Disabled\n"));) + PELOG1(limLog(pMac, LOG1, FL("===> Protection from LsigTxop Disabled"));) pBeaconParams->fLsigTXOPProtectionFullSupport= psessionEntry->beaconParams.fLsigTXOPProtectionFullSupport = false; pBeaconParams->paramChangeBitmap |= PARAM_LSIG_TXOP_FULL_SUPPORT_CHANGED; } @@ -4908,7 +4917,7 @@ limEnableHtRifsProtection(tpAniSirGlobal pMac, tANI_U8 enable, !psessionEntry->cfgProtection.rifs) { // protection disabled. - PELOG3(limLog(pMac, LOG3, FL(" protection from Rifs is disabled\n"));) + PELOG3(limLog(pMac, LOG3, FL(" protection from Rifs is disabled"));) return eSIR_SUCCESS; }else if(psessionEntry->limSystemRole != eLIM_AP_ROLE ) { @@ -4916,7 +4925,7 @@ limEnableHtRifsProtection(tpAniSirGlobal pMac, tANI_U8 enable, if(!pMac->lim.cfgProtection.rifs) { // protection disabled. - PELOG3(limLog(pMac, LOG3, FL(" protection from Rifs is disabled\n"));) + PELOG3(limLog(pMac, LOG3, FL(" protection from Rifs is disabled"));) return eSIR_SUCCESS; } } @@ -4926,14 +4935,14 @@ limEnableHtRifsProtection(tpAniSirGlobal pMac, tANI_U8 enable, // Disabling the RIFS Protection means Enable the RIFS mode of operation in the BSS if ((!enable) && (false == psessionEntry->beaconParams.fRIFSMode)) { - PELOG1(limLog(pMac, LOG1, FL(" => Rifs protection Disabled\n"));) + PELOG1(limLog(pMac, LOG1, FL(" => Rifs protection Disabled"));) pBeaconParams->fRIFSMode = psessionEntry->beaconParams.fRIFSMode = true; pBeaconParams->paramChangeBitmap |= PARAM_RIFS_MODE_CHANGED; } // Enabling the RIFS Protection means Disable the RIFS mode of operation in the BSS else if (enable && (true == psessionEntry->beaconParams.fRIFSMode)) { - PELOG1(limLog(pMac, LOG1, FL("===> Rifs Protection Enabled\n"));) + PELOG1(limLog(pMac, LOG1, FL("===> Rifs Protection Enabled"));) pBeaconParams->fRIFSMode = psessionEntry->beaconParams.fRIFSMode = false; pBeaconParams->paramChangeBitmap |= PARAM_RIFS_MODE_CHANGED; } @@ -4942,14 +4951,14 @@ limEnableHtRifsProtection(tpAniSirGlobal pMac, tANI_U8 enable, // Disabling the RIFS Protection means Enable the RIFS mode of operation in the BSS if ((!enable) && (false == psessionEntry->beaconParams.fRIFSMode)) { - PELOG1(limLog(pMac, LOG1, FL(" => Rifs protection Disabled\n"));) + PELOG1(limLog(pMac, LOG1, FL(" => Rifs protection Disabled"));) pBeaconParams->fRIFSMode = psessionEntry->beaconParams.fRIFSMode = true; pBeaconParams->paramChangeBitmap |= PARAM_RIFS_MODE_CHANGED; } // Enabling the RIFS Protection means Disable the RIFS mode of operation in the BSS else if (enable && (true == psessionEntry->beaconParams.fRIFSMode)) { - PELOG1(limLog(pMac, LOG1, FL("===> Rifs Protection Enabled\n"));) + PELOG1(limLog(pMac, LOG1, FL("===> Rifs Protection Enabled"));) pBeaconParams->fRIFSMode = psessionEntry->beaconParams.fRIFSMode = false; pBeaconParams->paramChangeBitmap |= PARAM_RIFS_MODE_CHANGED; } @@ -4982,7 +4991,7 @@ limEnableShortPreamble(tpAniSirGlobal pMac, tANI_U8 enable, tpUpdateBeaconParams if (wlan_cfgGetInt(pMac, WNI_CFG_SHORT_PREAMBLE, &val) != eSIR_SUCCESS) { /* Could not get short preamble enabled flag from CFG. Log error. */ - limLog(pMac, LOGP, FL("could not retrieve short preamble flag\n")); + limLog(pMac, LOGP, FL("could not retrieve short preamble flag")); return eSIR_FAILURE; } @@ -4991,7 +5000,7 @@ limEnableShortPreamble(tpAniSirGlobal pMac, tANI_U8 enable, tpUpdateBeaconParams if (wlan_cfgGetInt(pMac, WNI_CFG_11G_SHORT_PREAMBLE_ENABLED, &val) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("could not retrieve 11G short preamble switching enabled flag\n")); + limLog(pMac, LOGP, FL("could not retrieve 11G short preamble switching enabled flag")); return eSIR_FAILURE; } @@ -5002,14 +5011,14 @@ limEnableShortPreamble(tpAniSirGlobal pMac, tANI_U8 enable, tpUpdateBeaconParams { if (enable && (psessionEntry->beaconParams.fShortPreamble == 0)) { - PELOG1(limLog(pMac, LOG1, FL("===> Short Preamble Enabled\n"));) + PELOG1(limLog(pMac, LOG1, FL("===> Short Preamble Enabled"));) psessionEntry->beaconParams.fShortPreamble = true; pBeaconParams->fShortPreamble = (tANI_U8) psessionEntry->beaconParams.fShortPreamble; pBeaconParams->paramChangeBitmap |= PARAM_SHORT_PREAMBLE_CHANGED; } else if (!enable && (psessionEntry->beaconParams.fShortPreamble == 1)) { - PELOG1(limLog(pMac, LOG1, FL("===> Short Preamble Disabled\n"));) + PELOG1(limLog(pMac, LOG1, FL("===> Short Preamble Disabled"));) psessionEntry->beaconParams.fShortPreamble = false; pBeaconParams->fShortPreamble = (tANI_U8) psessionEntry->beaconParams.fShortPreamble; pBeaconParams->paramChangeBitmap |= PARAM_SHORT_PREAMBLE_CHANGED; @@ -5122,7 +5131,7 @@ void limUpdateStaRunTimeHTSwitchChnlParams( tpAniSirGlobal pMac, #if !defined WLAN_FEATURE_VOWIFI if(wlan_cfgGetInt(pMac, WNI_CFG_LOCAL_POWER_CONSTRAINT, &localPwrConstraint) != eSIR_SUCCESS) { - limLog( pMac, LOGP, FL( "Unable to get Local Power Constraint from cfg\n" )); + limLog( pMac, LOGP, FL( "Unable to get Local Power Constraint from cfg" )); return; } #endif @@ -5137,9 +5146,9 @@ void limUpdateStaRunTimeHTSwitchChnlParams( tpAniSirGlobal pMac, // Notify HAL limLog( pMac, LOGW, FL( "Channel Information in HT IE change" - "d; sending notification to HAL.\n" ) ); + "d; sending notification to HAL." ) ); limLog( pMac, LOGW, FL( "Primary Channel: %d, Secondary Chan" - "nel Offset: %d, Channel Width: %d\n" ), + "nel Offset: %d, Channel Width: %d" ), pHTInfo->primaryChannel, secondaryChnlOffset, psessionEntry->htRecommendedTxWidthSet ); psessionEntry->channelChangeReasonCode=LIM_SWITCH_CHANNEL_OPERATION; @@ -5314,7 +5323,7 @@ tSirRetStatus limProcessHalIndMessages(tpAniSirGlobal pMac, tANI_U32 msgId, void default: palFreeMemory(pMac->hHdd, msgParam); - limLog(pMac, LOGP, FL("invalid message id = %d received\n"), msgId); + limLog(pMac, LOGP, FL("invalid message id = %d received"), msgId); return eSIR_FAILURE; } @@ -5353,7 +5362,7 @@ limValidateDeltsReq(tpAniSirGlobal pMac, tpSirDeltsReq pDeltsReq, tSirMacAddr pe */ if(pDeltsReq == NULL) { - PELOGE(limLog(pMac, LOGE, FL("Delete TS request pointer is NULL\n"));) + PELOGE(limLog(pMac, LOGE, FL("Delete TS request pointer is NULL"));) return eSIR_FAILURE; } @@ -5369,7 +5378,7 @@ limValidateDeltsReq(tpAniSirGlobal pMac, tpSirDeltsReq pDeltsReq, tSirMacAddr pe if (wlan_cfgGetStr(pMac, WNI_CFG_BSSID, peerMacAddr, &val) != eSIR_SUCCESS) { /// Could not get BSSID from CFG. Log error. - limLog(pMac, LOGP, FL("could not retrieve BSSID\n")); + limLog(pMac, LOGP, FL("could not retrieve BSSID")); return eSIR_FAILURE; } #endif// TO SUPPORT BT-AMP @@ -5395,14 +5404,14 @@ limValidateDeltsReq(tpAniSirGlobal pMac, tpSirDeltsReq pDeltsReq, tSirMacAddr pe if (pSta == NULL) { - PELOGE(limLog(pMac, LOGE, "Cannot find station context for delts req\n");) + PELOGE(limLog(pMac, LOGE, "Cannot find station context for delts req");) return eSIR_FAILURE; } if ((! pSta->valid) || (pSta->mlmStaContext.mlmState != eLIM_MLM_LINK_ESTABLISHED_STATE)) { - PELOGE(limLog(pMac, LOGE, "Invalid Sta (or state) for DelTsReq\n");) + PELOGE(limLog(pMac, LOGE, "Invalid Sta (or state) for DelTsReq");) return eSIR_FAILURE; } @@ -5419,14 +5428,14 @@ limValidateDeltsReq(tpAniSirGlobal pMac, tpSirDeltsReq pDeltsReq, tSirMacAddr pe pDeltsReq->req.lleTspecPresent = 1; else { - PELOGW(limLog(pMac, LOGW, FL("DELTS_REQ ignore - qos is disabled\n"));) + PELOGW(limLog(pMac, LOGW, FL("DELTS_REQ ignore - qos is disabled"));) return eSIR_FAILURE; } tsinfo = pDeltsReq->req.wmeTspecPresent ? &pDeltsReq->req.tspec.tsinfo : &pDeltsReq->req.tsinfo; PELOG1(limLog(pMac, LOG1, - FL("received DELTS_REQ message (wmeTspecPresent = %d, lleTspecPresent = %d, wsmTspecPresent = %d, tsid %d, up %d, direction = %d)\n"), + FL("received DELTS_REQ message (wmeTspecPresent = %d, lleTspecPresent = %d, wsmTspecPresent = %d, tsid %d, up %d, direction = %d)"), pDeltsReq->req.wmeTspecPresent, pDeltsReq->req.lleTspecPresent, pDeltsReq->req.wsmTspecPresent, tsinfo->traffic.tsid, tsinfo->traffic.userPrio, tsinfo->traffic.direction);) @@ -5435,7 +5444,7 @@ limValidateDeltsReq(tpAniSirGlobal pMac, tpSirDeltsReq pDeltsReq, tSirMacAddr pe if (limAdmitControlDeleteTS(pMac, pSta->assocId, tsinfo, &tsStatus, &tspecIdx) != eSIR_SUCCESS) { - PELOGE(limLog(pMac, LOGE, "ERROR DELTS request for sta assocId %d (tsid %d, up %d)\n", + PELOGE(limLog(pMac, LOGE, "ERROR DELTS request for sta assocId %d (tsid %d, up %d)", pSta->assocId, tsinfo->traffic.tsid, tsinfo->traffic.userPrio);) return eSIR_FAILURE; } @@ -5452,7 +5461,7 @@ limValidateDeltsReq(tpAniSirGlobal pMac, tpSirDeltsReq pDeltsReq, tSirMacAddr pe //send message to HAL to delete TS if(eSIR_SUCCESS != limSendHalMsgDelTs(pMac, pSta->staIndex, tspecIdx, pDeltsReq->req, psessionEntry->peSessionId)) { - limLog(pMac, LOGW, FL("DelTs with UP %d failed in limSendHalMsgDelTs - ignoring request\n"), + limLog(pMac, LOGW, FL("DelTs with UP %d failed in limSendHalMsgDelTs - ignoring request"), tsinfo->traffic.userPrio); return eSIR_FAILURE; } @@ -5475,7 +5484,7 @@ limRegisterHalIndCallBack(tpAniSirGlobal pMac) if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pHalCB, sizeof(tHalIndCB))) { - limLog(pMac, LOGP, FL("palAllocateMemory() failed\n")); + limLog(pMac, LOGP, FL("palAllocateMemory() failed")); return; } @@ -5489,7 +5498,7 @@ limRegisterHalIndCallBack(tpAniSirGlobal pMac) if(eSIR_SUCCESS != wdaPostCtrlMsg(pMac, &msg)) { palFreeMemory(pMac->hHdd, pHalCB); - limLog(pMac, LOGP, FL("wdaPostCtrlMsg() failed\n")); + limLog(pMac, LOGP, FL("wdaPostCtrlMsg() failed")); } return; @@ -5530,7 +5539,7 @@ limProcessAddBaInd(tpAniSirGlobal pMac, tpSirMsgQ limMsg) if ((psessionEntry = peFindSessionByBssid(pMac,pBaActivityInd->bssId,&sessionId))== NULL) { - limLog(pMac, LOGE,FL("session does not exist for given BSSId\n")); + limLog(pMac, LOGE,FL("session does not exist for given BSSId")); palFreeMemory(pMac->hHdd, limMsg->bodyptr); return; } @@ -5599,60 +5608,135 @@ limProcessAddBaInd(tpAniSirGlobal pMac, tpSirMsgQ limMsg) /** ------------------------------------------------------------- -\fn limDelAllBASessions -\brief Deletes all the exisitng BA sessions. -\ Note : This API is provided for Mac OSx only. The reason for this is that Mac OSx may not -\ restart after CFG update. +\fn limDeleteBASessions +\brief Deletes all the exisitng BA sessions for given session + and BA direction. \param tpAniSirGlobal pMac -\return None +\param tpPESession pSessionEntry +\param tANI_U32 baDirection +\return None -------------------------------------------------------------*/ void -limDelAllBASessions(tpAniSirGlobal pMac) +limDeleteBASessions(tpAniSirGlobal pMac, tpPESession pSessionEntry, + tANI_U32 baDirection) { tANI_U32 i; tANI_U8 tid; tpDphHashNode pSta; - tpPESession psessionEntry = &pMac->lim.gpSession[0]; //TBD-RAJESH HOW TO GET sessionEntry????? - for(tid = 0; tid < STACFG_MAX_TC; tid++) + if (NULL == pSessionEntry) { - if((eLIM_AP_ROLE == psessionEntry->limSystemRole) ||(psessionEntry->limSystemRole == eLIM_BT_AMP_AP_ROLE)|| - (eLIM_STA_IN_IBSS_ROLE == psessionEntry->limSystemRole)) + limLog(pMac, LOGE, FL("Session does not exist")); + } + else + { + for(tid = 0; tid < STACFG_MAX_TC; tid++) { - for(i = 0; i < pMac->lim.maxStation; i++) + if ((eLIM_AP_ROLE == pSessionEntry->limSystemRole) || + (pSessionEntry->limSystemRole == eLIM_BT_AMP_AP_ROLE) || + (eLIM_STA_IN_IBSS_ROLE == pSessionEntry->limSystemRole) || + (pSessionEntry->limSystemRole == eLIM_P2P_DEVICE_GO)) + { + for (i = 0; i < pMac->lim.maxStation; i++) + { + pSta = pSessionEntry->dph.dphHashTable.pDphNodeArray + i; + if (pSta && pSta->added) + { + if ((eBA_ENABLE == pSta->tcCfg[tid].fUseBATx) && + (baDirection & BA_INITIATOR)) + { + limPostMlmDelBAReq(pMac, pSta, eBA_INITIATOR, tid, + eSIR_MAC_UNSPEC_FAILURE_REASON, + pSessionEntry); + } + if ((eBA_ENABLE == pSta->tcCfg[tid].fUseBARx) && + (baDirection & BA_RECIPIENT)) + { + limPostMlmDelBAReq(pMac, pSta, eBA_RECIPIENT, tid, + eSIR_MAC_UNSPEC_FAILURE_REASON, + pSessionEntry); + } + } + } + } + else if ((eLIM_STA_ROLE == pSessionEntry->limSystemRole) || + (eLIM_BT_AMP_STA_ROLE == pSessionEntry->limSystemRole) || + (eLIM_P2P_DEVICE_ROLE == pSessionEntry->limSystemRole)) { - pSta = psessionEntry->dph.dphHashTable.pDphNodeArray + i; + pSta = dphGetHashEntry(pMac, DPH_STA_HASH_INDEX_PEER, + &pSessionEntry->dph.dphHashTable); if (pSta && pSta->added) { - if(eBA_ENABLE == pSta->tcCfg[tid].fUseBATx) + if ((eBA_ENABLE == pSta->tcCfg[tid].fUseBATx) && + (baDirection & BA_INITIATOR)) { - limPostMlmDelBAReq(pMac, pSta, eBA_INITIATOR, tid, eSIR_MAC_UNSPEC_FAILURE_REASON,psessionEntry); + limPostMlmDelBAReq(pMac, pSta, eBA_INITIATOR, tid, + eSIR_MAC_UNSPEC_FAILURE_REASON, + pSessionEntry); } - else if(eBA_ENABLE == pSta->tcCfg[tid].fUseBARx) + if ((eBA_ENABLE == pSta->tcCfg[tid].fUseBARx) && + (baDirection & BA_RECIPIENT)) { - limPostMlmDelBAReq(pMac, pSta, eBA_RECIPIENT, tid, eSIR_MAC_UNSPEC_FAILURE_REASON,psessionEntry); + limPostMlmDelBAReq(pMac, pSta, eBA_RECIPIENT, tid, + eSIR_MAC_UNSPEC_FAILURE_REASON, + pSessionEntry); } } } } - else if((eLIM_STA_ROLE == psessionEntry->limSystemRole)||(eLIM_BT_AMP_STA_ROLE == psessionEntry->limSystemRole)) + } +} + +/** ------------------------------------------------------------- +\fn limDelAllBASessions +\brief Deletes all the exisitng BA sessions. +\param tpAniSirGlobal pMac +\return None +-------------------------------------------------------------*/ + +void limDelAllBASessions(tpAniSirGlobal pMac) +{ + tANI_U32 i; + tpPESession pSessionEntry; + + for (i = 0; i < pMac->lim.maxBssId; i++) + { + pSessionEntry = peFindSessionBySessionId(pMac, i); + if (pSessionEntry) { - pSta = dphGetHashEntry(pMac, DPH_STA_HASH_INDEX_PEER, &psessionEntry->dph.dphHashTable); - if (pSta && pSta->added) + limDeleteBASessions(pMac, pSessionEntry, BA_BOTH_DIRECTIONS); + } + } +} + +/** ------------------------------------------------------------- +\fn limDelAllBASessionsBtc +\brief Deletes all the exisitng BA receipent sessions in 2.4GHz + band. +\param tpAniSirGlobal pMac +\return None +-------------------------------------------------------------*/ + +void limDelAllBASessionsBtc(tpAniSirGlobal pMac) +{ + tANI_U32 i; + tpPESession pSessionEntry; + + for (i = 0; i < pMac->lim.maxBssId; i++) + { + pSessionEntry = peFindSessionBySessionId(pMac, i); + if (pSessionEntry) + { + if (SIR_BAND_2_4_GHZ == + limGetRFBand(pSessionEntry->currentOperChannel)) { - if(eBA_ENABLE == pSta->tcCfg[tid].fUseBATx) - { - limPostMlmDelBAReq(pMac, pSta, eBA_INITIATOR, tid, eSIR_MAC_UNSPEC_FAILURE_REASON,psessionEntry); - } - if(eBA_ENABLE == pSta->tcCfg[tid].fUseBARx) - { - limPostMlmDelBAReq(pMac, pSta, eBA_RECIPIENT, tid, eSIR_MAC_UNSPEC_FAILURE_REASON,psessionEntry); - } + limDeleteBASessions(pMac, pSessionEntry, BA_RECIPIENT); } } } } + /** ------------------------------------------------------------- \fn limProcessDelTsInd \brief handles the DeleteTS indication coming from HAL or generated by PE itself in some error cases. @@ -5675,7 +5759,7 @@ limProcessDelTsInd(tpAniSirGlobal pMac, tpSirMsgQ limMsg) if((psessionEntry = peFindSessionByBssid(pMac,pDelTsParam->bssId,&sessionId))== NULL) { - limLog(pMac, LOGE,FL("session does not exist for given BssId\n")); + limLog(pMac, LOGE,FL("session does not exist for given BssId")); palFreeMemory(pMac->hHdd, (void *)(limMsg->bodyptr)); return; } @@ -5683,21 +5767,21 @@ if((psessionEntry = peFindSessionByBssid(pMac,pDelTsParam->bssId,&sessionId))== pTspecInfo = &(pMac->lim.tspecInfo[pDelTsParam->tspecIdx]); if(pTspecInfo->inuse == false) { - PELOGE(limLog(pMac, LOGE, FL("tspec entry with index %d is not in use\n"), pDelTsParam->tspecIdx);) + PELOGE(limLog(pMac, LOGE, FL("tspec entry with index %d is not in use"), pDelTsParam->tspecIdx);) goto error1; } pSta = dphGetHashEntry(pMac, pTspecInfo->assocId, &psessionEntry->dph.dphHashTable); if(pSta == NULL) { - limLog(pMac, LOGE, FL("Could not find entry in DPH table for assocId = %d\n"), + limLog(pMac, LOGE, FL("Could not find entry in DPH table for assocId = %d"), pTspecInfo->assocId); goto error1; } if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pDelTsReq, sizeof(tSirDeltsReq))) { - PELOGE(limLog(pMac, LOGE, FL("palAllocateMemory() failed\n"));) + PELOGE(limLog(pMac, LOGE, FL("palAllocateMemory() failed"));) goto error1; } @@ -5712,10 +5796,10 @@ if((psessionEntry = peFindSessionByBssid(pMac,pDelTsParam->bssId,&sessionId))== //validate the req if (eSIR_SUCCESS != limValidateDeltsReq(pMac, pDelTsReq, peerMacAddr,psessionEntry)) { - PELOGE(limLog(pMac, LOGE, FL("limValidateDeltsReq failed\n"));) + PELOGE(limLog(pMac, LOGE, FL("limValidateDeltsReq failed"));) goto error2; } - PELOG1(limLog(pMac, LOG1, "Sent DELTS request to station with assocId = %d MacAddr = %x:%x:%x:%x:%x:%x\n", + PELOG1(limLog(pMac, LOG1, "Sent DELTS request to station with assocId = %d MacAddr = %x:%x:%x:%x:%x:%x", pDelTsReq->aid, peerMacAddr[0], peerMacAddr[1], peerMacAddr[2], peerMacAddr[3], peerMacAddr[4], peerMacAddr[5]);) @@ -5725,7 +5809,7 @@ if((psessionEntry = peFindSessionByBssid(pMac,pDelTsParam->bssId,&sessionId))== // prepare and send an sme indication to HDD if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pDelTsReqInfo, sizeof(tSirDeltsReqInfo))) { - PELOGE(limLog(pMac, LOGE, FL("palAllocateMemory() failed\n"));) + PELOGE(limLog(pMac, LOGE, FL("palAllocateMemory() failed"));) goto error3; } palZeroMemory( pMac->hHdd, (tANI_U8 *)pDelTsReqInfo, sizeof(tSirDeltsReqInfo)); @@ -5767,10 +5851,10 @@ tSirRetStatus limPostMlmAddBAReq( tpAniSirGlobal pMac, tANI_U8 tid, tANI_U16 startingSeqNum,tpPESession psessionEntry) { tSirRetStatus status = eSIR_SUCCESS; - tpLimMlmAddBAReq pMlmAddBAReq; + tpLimMlmAddBAReq pMlmAddBAReq = NULL; tpDialogueToken dialogueTokenNode; tANI_U32 val = 0; - + // Check if the peer is a 11n capable STA // FIXME - Need a 11n peer indication in DPH. // For now, using the taurusPeer attribute @@ -5782,7 +5866,7 @@ tSirRetStatus limPostMlmAddBAReq( tpAniSirGlobal pMac, (void **) &pMlmAddBAReq, sizeof( tLimMlmAddBAReq ))) { - limLog( pMac, LOGP, FL("palAllocateMemory failed\n")); + limLog( pMac, LOGP, FL("palAllocateMemory failed")); status = eSIR_MEM_ALLOC_FAILED; goto returnFailure; } @@ -5809,23 +5893,22 @@ tSirRetStatus limPostMlmAddBAReq( tpAniSirGlobal pMac, pMlmAddBAReq->baBufferSize = 0; limLog( pMac, LOGW, - FL( "Requesting an ADDBA to setup a %s BA session with STA %d for TID %d\n" ), + FL( "Requesting an ADDBA to setup a %s BA session with STA %d for TID %d" ), (pMlmAddBAReq->baPolicy ? "Immediate": "Delayed"), pStaDs->staIndex, tid ); // BA Timeout - // pMlmAddBAReq->baTimeout = pMac->hal.halMac.baTimeout; // In TU's - if (wlan_cfgGetInt(pMac, WNI_CFG_BA_TIMEOUT, &val) != eSIR_SUCCESS) + if (wlan_cfgGetInt(pMac, WNI_CFG_BA_TIMEOUT, &val) != eSIR_SUCCESS) { - limLog(pMac, LOGE, FL("could not retrieve BA TIME OUT Param CFG\n")); + limLog(pMac, LOGE, FL("could not retrieve BA TIME OUT Param CFG")); status = eSIR_FAILURE; goto returnFailure; } pMlmAddBAReq->baTimeout = val; // In TU's // ADDBA Failure Timeout - // FIXME_AMPDU - Need to retrieve this from CFG. + // FIXME_AMPDU - Need to retrieve this from CFG. //right now we are not checking for response timeout. so this field is dummy just to be compliant with the spec. pMlmAddBAReq->addBAFailureTimeout = 2000; // In TU's @@ -5837,20 +5920,26 @@ tSirRetStatus limPostMlmAddBAReq( tpAniSirGlobal pMac, LIM_SET_STA_BA_STATE(pStaDs, tid, eLIM_BA_STATE_WT_ADD_RSP); - if( NULL == (dialogueTokenNode = limAssignDialogueToken(pMac))) - goto returnFailure; - + dialogueTokenNode = limAssignDialogueToken(pMac); + if (NULL == dialogueTokenNode) + { + limLog(pMac, LOGE, FL("could not assign dialogue token")); + status = eSIR_FAILURE; + goto returnFailure; + } + pMlmAddBAReq->baDialogToken = dialogueTokenNode->token; - //set assocId and tid information in the lim linked list + //set assocId and tid information in the lim linked list dialogueTokenNode->assocId = pStaDs->assocId; dialogueTokenNode->tid = tid; // Send ADDBA Req to MLME limPostMlmMessage( pMac, LIM_MLM_ADDBA_REQ, (tANI_U32 *) pMlmAddBAReq ); + return eSIR_SUCCESS; returnFailure: - + palFreeMemory(pMac->hHdd, pMlmAddBAReq); return status; } @@ -5900,7 +5989,7 @@ tpLimMlmAddBARsp pMlmAddBARsp; sizeof( tLimMlmAddBARsp ))) { limLog( pMac, LOGE, - FL("palAllocateMemory failed with error code %d\n"), + FL("palAllocateMemory failed with error code %d"), status ); status = eSIR_MEM_ALLOC_FAILED; @@ -5976,7 +6065,7 @@ LIM_GET_STA_BA_STATE(pSta, baTID, &curBaState); if( eLIM_BA_STATE_IDLE != curBaState) { limLog( pMac, LOGE, - FL( "Received unexpected DELBA REQ when STA BA state for tid = %d is %d\n" ), + FL( "Received unexpected DELBA REQ when STA BA state for tid = %d is %d" ), baTID, curBaState); @@ -5990,7 +6079,7 @@ LIM_GET_STA_BA_STATE(pSta, baTID, &curBaState); sizeof( tLimMlmDelBAReq ))) { limLog( pMac, LOGE, - FL("palAllocateMemory failed with error code %d\n"), + FL("palAllocateMemory failed with error code %d"), status ); status = eSIR_MEM_ALLOC_FAILED; @@ -6101,7 +6190,7 @@ tSirMsgQ msgQ; sizeof( tAddBAParams )))) { limLog( pMac, LOGE, - FL("palAllocateMemory failed with error code %d\n"), + FL("palAllocateMemory failed with error code %d"), status ); retCode = eSIR_MEM_ALLOC_FAILED; @@ -6154,7 +6243,7 @@ tSirMsgQ msgQ; if( eSIR_SUCCESS != (retCode = wdaPostCtrlMsg( pMac, &msgQ ))) limLog( pMac, LOGE, - FL("Posting WDA_ADDBA_REQ to HAL failed! Reason = %d\n"), + FL("Posting WDA_ADDBA_REQ to HAL failed! Reason = %d"), retCode ); else return retCode; @@ -6206,7 +6295,7 @@ tSirMsgQ msgQ; sizeof( tDelBAParams )))) { limLog( pMac, LOGE, - FL("palAllocateMemory failed with error code %d\n"), + FL("palAllocateMemory failed with error code %d"), status ); retCode = eSIR_MEM_ALLOC_FAILED; @@ -6247,7 +6336,7 @@ tSirMsgQ msgQ; if( eSIR_SUCCESS != (retCode = wdaPostCtrlMsg( pMac, &msgQ ))) limLog( pMac, LOGE, - FL("Posting WDA_DELBA_IND to HAL failed! Reason = %d\n"), + FL("Posting WDA_DELBA_IND to HAL failed! Reason = %d"), retCode ); else { @@ -6308,7 +6397,7 @@ limPostSMStateUpdate(tpAniSirGlobal pMac, // Allocate for WDA_SET_MIMOPS_REQ status = palAllocateMemory( pMac->hHdd, (void **) &pMIMO_PSParams, sizeof( tSetMIMOPS)); if( eHAL_STATUS_SUCCESS != status) { - limLog( pMac, LOGP,FL(" palAllocateMemory failed with error code %d\n"), status ); + limLog( pMac, LOGP,FL(" palAllocateMemory failed with error code %d"), status ); return eSIR_MEM_ALLOC_FAILED; } @@ -6324,7 +6413,7 @@ limPostSMStateUpdate(tpAniSirGlobal pMac, retCode = wdaPostCtrlMsg( pMac, &msgQ ); if (eSIR_SUCCESS != retCode) { - limLog( pMac, LOGP, FL("Posting WDA_SET_MIMOPS_REQ to HAL failed! Reason = %d\n"), retCode ); + limLog( pMac, LOGP, FL("Posting WDA_SET_MIMOPS_REQ to HAL failed! Reason = %d"), retCode ); palFreeMemory(pMac->hHdd, (void *) pMIMO_PSParams); return retCode; } @@ -6402,7 +6491,7 @@ void limAddScanChannelInfo(tpAniSirGlobal pMac, tANI_U8 channelId) } else { - PELOGW(limLog(pMac, LOGW, FL(" -- number of channels exceed mac\n"));) + PELOGW(limLog(pMac, LOGW, FL(" -- number of channels exceed mac"));) } } } @@ -6436,7 +6525,7 @@ limIsChannelValidForChannelSwitch(tpAniSirGlobal pMac, tANI_U8 channel) (tANI_U8 *)validChannelList, (tANI_U32 *)&validChannelListLen) != eSIR_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("could not retrieve valid channel list\n"));) + PELOGE(limLog(pMac, LOGE, FL("could not retrieve valid channel list"));) return (eSIR_FALSE); } @@ -6495,7 +6584,7 @@ __limFillTxControlParams(tpAniSirGlobal pMac, tpTxControlParams pTxCtrlMsg, case eLIM_TX_BSS: //Fall thru... default: - PELOGW(limLog(pMac, LOGW, FL("Invalid case: Not Handled\n"));) + PELOGW(limLog(pMac, LOGW, FL("Invalid case: Not Handled"));) return eHAL_STATUS_FAILURE; } @@ -6536,7 +6625,7 @@ void limFrameTransmissionControl(tpAniSirGlobal pMac, tLimQuietTxMode type, tLim (sizeof(*pTxCtrlMsg) + nBytes)); if (status != eHAL_STATUS_SUCCESS) { - limLog(pMac, LOGP, FL("palAllocateMemory() failed\n")); + limLog(pMac, LOGP, FL("palAllocateMemory() failed")); return; } @@ -6545,7 +6634,7 @@ void limFrameTransmissionControl(tpAniSirGlobal pMac, tLimQuietTxMode type, tLim if (status != eHAL_STATUS_SUCCESS) { palFreeMemory(pMac->hHdd, (void *) pTxCtrlMsg); - limLog(pMac, LOGP, FL("palZeroMemory() failed, status = %d\n"), status); + limLog(pMac, LOGP, FL("palZeroMemory() failed, status = %d"), status); return; } @@ -6553,7 +6642,7 @@ void limFrameTransmissionControl(tpAniSirGlobal pMac, tLimQuietTxMode type, tLim if (status != eHAL_STATUS_SUCCESS) { palFreeMemory(pMac->hHdd, (void *) pTxCtrlMsg); - limLog(pMac, LOGP, FL("__limFillTxControlParams failed, status = %d\n"), status); + limLog(pMac, LOGP, FL("__limFillTxControlParams failed, status = %d"), status); return; } @@ -6566,17 +6655,17 @@ void limFrameTransmissionControl(tpAniSirGlobal pMac, tLimQuietTxMode type, tLim if(wdaPostCtrlMsg( pMac, &msgQ) != eSIR_SUCCESS) { palFreeMemory(pMac->hHdd, (void *) pTxCtrlMsg); - limLog( pMac, LOGP, FL("Posting Message to HAL failed\n")); + limLog( pMac, LOGP, FL("Posting Message to HAL failed")); return; } if (mode == eLIM_STOP_TX) { - PELOG1(limLog(pMac, LOG1, FL("Stopping the transmission of all packets, indicated softmac\n"));) + PELOG1(limLog(pMac, LOG1, FL("Stopping the transmission of all packets, indicated softmac"));) } else { - PELOG1(limLog(pMac, LOG1, FL("Resuming the transmission of all packets, indicated softmac\n"));) + PELOG1(limLog(pMac, LOG1, FL("Resuming the transmission of all packets, indicated softmac"));) } return; } @@ -6627,7 +6716,7 @@ limRestorePreChannelSwitchState(tpAniSirGlobal pMac, tpPESession psessionEntry) &val)) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("could not retrieve Background scan period value\n")); + limLog(pMac, LOGP, FL("could not retrieve Background scan period value")); return (retCode); } @@ -6689,7 +6778,7 @@ tSirRetStatus limRestorePreQuietState(tpAniSirGlobal pMac, tpPESession psessionE &val)) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("could not retrieve Background scan period value\n")); + limLog(pMac, LOGP, FL("could not retrieve Background scan period value")); return (retCode); } @@ -6756,7 +6845,7 @@ limPrepareFor11hChannelSwitch(tpAniSirGlobal pMac, tpPESession psessionEntry) if(pMac->lim.gLimSmeState == eLIM_SME_LINK_EST_WT_SCAN_STATE || pMac->lim.gLimSmeState == eLIM_SME_CHANNEL_SCAN_STATE) { - PELOGE(limLog(pMac, LOGE, FL("Posting finish scan as we are in scan state\n"));) + PELOGE(limLog(pMac, LOGE, FL("Posting finish scan as we are in scan state"));) /* Stop ongoing scanning if any */ if (GET_LIM_PROCESS_DEFD_MESGS(pMac)) { @@ -6773,7 +6862,7 @@ limPrepareFor11hChannelSwitch(tpAniSirGlobal pMac, tpPESession psessionEntry) } else { - PELOGE(limLog(pMac, LOGE, FL("Not in scan state, start channel switch timer\n"));) + PELOGE(limLog(pMac, LOGE, FL("Not in scan state, start channel switch timer"));) /** We are safe to switch channel at this point */ limStopTxAndSwitchChannel(pMac, psessionEntry->peSessionId); } @@ -6825,14 +6914,14 @@ tSirNwType limGetNwType(tpAniSirGlobal pMac, tANI_U8 channelNum, tANI_U32 type, } if (pBeacon->extendedRatesPresent) { - PELOG3(limLog(pMac, LOG3, FL("Beacon, nwtype=G\n"));) + PELOG3(limLog(pMac, LOG3, FL("Beacon, nwtype=G"));) nwType = eSIR_11G_NW_TYPE; } } else { // 11a packet - PELOG3(limLog(pMac, LOG3,FL("Beacon, nwtype=A\n"));) + PELOG3(limLog(pMac, LOG3,FL("Beacon, nwtype=A"));) nwType = eSIR_11A_NW_TYPE; } } @@ -6887,7 +6976,7 @@ void limSetTspecUapsdMask(tpAniSirGlobal pMac, tSirMacTSInfo *pTsInfo, tANI_U32 tANI_U16 direction = pTsInfo->traffic.direction; tANI_U8 ac = upToAc(userPrio); - PELOG1(limLog(pMac, LOG1, FL(" Set UAPSD mask for AC %d, direction %d, action=%d (1=set,0=clear) \n"),ac, direction, action );) + PELOG1(limLog(pMac, LOG1, FL(" Set UAPSD mask for AC %d, direction %d, action=%d (1=set,0=clear) "),ac, direction, action );) /* Converting AC to appropriate Uapsd Bit Mask * AC_BE(0) --> UAPSD_BITOFFSET_ACVO(3) @@ -6922,8 +7011,8 @@ void limSetTspecUapsdMask(tpAniSirGlobal pMac, tSirMacTSInfo *pTsInfo, tANI_U32 } } - limLog(pMac, LOGE, FL("New pMac->lim.gUapsdPerAcTriggerEnableMask = 0x%x \n"), pMac->lim.gUapsdPerAcTriggerEnableMask ); - limLog(pMac, LOGE, FL("New pMac->lim.gUapsdPerAcDeliveryEnableMask = 0x%x \n"), pMac->lim.gUapsdPerAcDeliveryEnableMask ); + limLog(pMac, LOGE, FL("New pMac->lim.gUapsdPerAcTriggerEnableMask = 0x%x "), pMac->lim.gUapsdPerAcTriggerEnableMask ); + limLog(pMac, LOGE, FL("New pMac->lim.gUapsdPerAcDeliveryEnableMask = 0x%x "), pMac->lim.gUapsdPerAcDeliveryEnableMask ); return; } @@ -6961,13 +7050,13 @@ void limHandleHeartBeatTimeout(tpAniSirGlobal pMac ) if(pMac->lim.gpSession[i].LimHBFailureStatus == eANI_BOOLEAN_TRUE) { /* Activate Probe After HeartBeat Timer incase HB Failure detected */ - PELOGW(limLog(pMac, LOGW,FL("Sending Probe for Session: %d\n"), + PELOGW(limLog(pMac, LOGW,FL("Sending Probe for Session: %d"), i);) limDeactivateAndChangeTimer(pMac, eLIM_PROBE_AFTER_HB_TIMER); MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, 0, eLIM_PROBE_AFTER_HB_TIMER)); if (tx_timer_activate(&pMac->lim.limTimers.gLimProbeAfterHBTimer) != TX_SUCCESS) { - limLog(pMac, LOGP, FL("Fail to re-activate Probe-after-heartbeat timer\n")); + limLog(pMac, LOGP, FL("Fail to re-activate Probe-after-heartbeat timer")); limReactivateHeartBeatTimer(pMac, &pMac->lim.gpSession[i]); } break; @@ -7044,7 +7133,7 @@ void limProcessAddStaRsp(tpAniSirGlobal pMac,tpSirMsgQ limMsgQ) if((psessionEntry = peFindSessionBySessionId(pMac,pAddStaParams->sessionId))==NULL) { - limLog(pMac, LOGP,FL("Session Does not exist for given sessionID\n")); + limLog(pMac, LOGP,FL("Session Does not exist for given sessionID")); palFreeMemory(pMac, pAddStaParams); return; } @@ -7107,13 +7196,14 @@ void limHandleHeartBeatFailureTimeout(tpAniSirGlobal pMac) psessionEntry = &pMac->lim.gpSession[i]; if(psessionEntry->LimHBFailureStatus == eANI_BOOLEAN_TRUE) { - limLog(pMac, LOGE, FL("Probe_hb_failure: SME %d, MLME %d, HB-Count %d\n"),psessionEntry->limSmeState, + limLog(pMac, LOGE, FL("Probe_hb_failure: SME %d, MLME %d, HB-Count %d"),psessionEntry->limSmeState, psessionEntry->limMlmState, psessionEntry->LimRxedBeaconCntDuringHB); if (psessionEntry->limMlmState == eLIM_MLM_LINK_ESTABLISHED_STATE) { - if (!LIM_IS_CONNECTION_ACTIVE(psessionEntry)) + if ((!LIM_IS_CONNECTION_ACTIVE(psessionEntry))&& + (psessionEntry->limSmeState != eLIM_SME_WT_DISASSOC_STATE)) { - limLog(pMac, LOGE, FL("Probe_hb_failure: for session:%d \n" ),psessionEntry->peSessionId); + limLog(pMac, LOGE, FL("Probe_hb_failure: for session:%d " ),psessionEntry->peSessionId); /* AP did not respond to Probe Request. Tear down link with it.*/ limTearDownLinkWithAp(pMac, psessionEntry->peSessionId, @@ -7127,7 +7217,7 @@ void limHandleHeartBeatFailureTimeout(tpAniSirGlobal pMac) } else { - limLog(pMac, LOGE, FL("Unexpected wt-probe-timeout in state \n")); + limLog(pMac, LOGE, FL("Unexpected wt-probe-timeout in state ")); limPrintMlmState(pMac, LOGE, psessionEntry->limMlmState); limReactivateHeartBeatTimer(pMac, psessionEntry); } @@ -7246,7 +7336,7 @@ void limProcessAddStaSelfRsp(tpAniSirGlobal pMac,tpSirMsgQ limMsgQ) if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pRsp, sizeof(tSirSmeAddStaSelfRsp))) { /// Buffer not available. Log error - limLog(pMac, LOGP, FL("call to palAllocateMemory failed for Add Sta self RSP\n")); + limLog(pMac, LOGP, FL("call to palAllocateMemory failed for Add Sta self RSP")); palFreeMemory( pMac->hHdd, (tANI_U8 *)pAddStaSelfParams); return; } @@ -7282,7 +7372,7 @@ void limProcessDelStaSelfRsp(tpAniSirGlobal pMac,tpSirMsgQ limMsgQ) if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pRsp, sizeof(tSirSmeDelStaSelfRsp))) { /// Buffer not available. Log error - limLog(pMac, LOGP, FL("call to palAllocateMemory failed for Add Sta self RSP\n")); + limLog(pMac, LOGP, FL("call to palAllocateMemory failed for Add Sta self RSP")); palFreeMemory( pMac->hHdd, (tANI_U8 *)pDelStaSelfParams); return; } @@ -7314,6 +7404,11 @@ void limProcessDelStaSelfRsp(tpAniSirGlobal pMac,tpSirMsgQ limMsgQ) tANI_U8 limUnmapChannel(tANI_U8 mapChannel) { if( mapChannel > 0 && mapChannel < 25 ) +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE) + return aUnsortedChannelList[mapChannel -1]; + else +#endif return abChannel[mapChannel -1]; else return 0; @@ -7376,7 +7471,7 @@ v_U8_t* limGetVendorIEOuiPtr(tpAniSirGlobal pMac, tANI_U8 *oui, tANI_U8 oui_size if(elem_len > left) { limLog( pMac, LOGE, - FL("****Invalid IEs eid = %d elem_len=%d left=%d*****\n"), + FL("****Invalid IEs eid = %d elem_len=%d left=%d*****"), elem_id,elem_len,left); return NULL; } @@ -7411,12 +7506,21 @@ v_U8_t limBuildP2pIe(tpAniSirGlobal pMac, tANI_U8 *ie, tANI_U8 *data, tANI_U8 ie v_U8_t limGetNoaAttrStreamInMultP2pIes(tpAniSirGlobal pMac,v_U8_t* noaStream,v_U8_t noaLen,v_U8_t overFlowLen) { v_U8_t overFlowP2pStream[SIR_MAX_NOA_ATTR_LEN]; - palCopyMemory( pMac->hHdd, overFlowP2pStream, noaStream + noaLen - overFlowLen, overFlowLen); - noaStream[noaLen - overFlowLen] = SIR_MAC_EID_VENDOR; - noaStream[noaLen - overFlowLen+1] = overFlowLen + SIR_MAC_P2P_OUI_SIZE; - palCopyMemory( pMac->hHdd, noaStream+ noaLen - overFlowLen+2,SIR_MAC_P2P_OUI,SIR_MAC_P2P_OUI_SIZE); - - palCopyMemory( pMac->hHdd, noaStream+ noaLen - overFlowLen+2+SIR_MAC_P2P_OUI_SIZE,overFlowP2pStream,overFlowLen); + + if ((noaLen <= (SIR_MAX_NOA_ATTR_LEN+SIR_P2P_IE_HEADER_LEN)) && + (noaLen >= overFlowLen) && (overFlowLen <= SIR_MAX_NOA_ATTR_LEN)) + { + palCopyMemory( pMac->hHdd, overFlowP2pStream, + noaStream + noaLen - overFlowLen, overFlowLen); + noaStream[noaLen - overFlowLen] = SIR_MAC_EID_VENDOR; + noaStream[noaLen - overFlowLen + 1] = overFlowLen + SIR_MAC_P2P_OUI_SIZE; + palCopyMemory( pMac->hHdd, noaStream+noaLen-overFlowLen + 2, + SIR_MAC_P2P_OUI, SIR_MAC_P2P_OUI_SIZE); + palCopyMemory( pMac->hHdd, + noaStream+noaLen + 2 + SIR_MAC_P2P_OUI_SIZE - overFlowLen, + overFlowP2pStream, overFlowLen); + } + return (noaLen + SIR_P2P_IE_HEADER_LEN); } @@ -7615,6 +7719,6 @@ tANI_U8 limGetShortSlotFromPhyMode(tpAniSirGlobal pMac, tpPESession psessionEntr // Will reach here in 11b case val = false; } - limLog(pMac, LOG1, FL("phyMode = %u shortslotsupported = %u\n"), phyMode, val); + limLog(pMac, LOG1, FL("phyMode = %u shortslotsupported = %u"), phyMode, val); return val; } diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limUtils.h b/drivers/staging/prima/CORE/MAC/src/pe/lim/limUtils.h index 3a1f9b69775..d4a17812809 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limUtils.h +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limUtils.h @@ -348,6 +348,8 @@ tSirRetStatus limPostSMStateUpdate(tpAniSirGlobal pMac, void limDeleteStaContext(tpAniSirGlobal pMac, tpSirMsgQ limMsg); void limProcessAddBaInd(tpAniSirGlobal pMac, tpSirMsgQ limMsg); +void limDeleteBASessions(tpAniSirGlobal pMac, tpPESession pSessionEntry, tANI_U32 baDirection); +void limDelAllBASessionsBtc(tpAniSirGlobal pMac); void limDelAllBASessions(tpAniSirGlobal pMac); void limDeleteDialogueTokenList(tpAniSirGlobal pMac); tSirRetStatus limSearchAndDeleteDialogueToken(tpAniSirGlobal pMac, tANI_U8 token, tANI_U16 assocId, tANI_U16 tid); diff --git a/drivers/staging/prima/CORE/MAC/src/pe/pmm/pmmApi.c b/drivers/staging/prima/CORE/MAC/src/pe/pmm/pmmApi.c index 4dfbe7587c6..d280b6336f2 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/pmm/pmmApi.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/pmm/pmmApi.c @@ -815,12 +815,6 @@ tSirRetStatus pmmSendPowerSaveCfg(tpAniSirGlobal pMac, tpSirPowerSaveCfg pUpdate pmmLog(pMac, LOGP, FL("pmmCfg: cfgGet failed for ignoreDtim")); pUpdatedPwrSaveCfg->ignoreDtim = (tANI_U8) ignoreDtim; - /* The numBeaconPerRssiAverage should be <= rssiFilter Period, - * and less than the max allowed (default set to 20 in CFG) - */ - if (numBeaconPerRssiAverage > rssiFilterPeriod) - pUpdatedPwrSaveCfg->numBeaconPerRssiAverage = (tANI_U8)GET_MIN_VALUE(rssiFilterPeriod, WNI_CFG_NUM_BEACON_PER_RSSI_AVERAGE_STAMAX); - //Save a copy of the CFG in global pmm context. palCopyMemory( pMac->hHdd, (tANI_U8 *) &pMac->pmm.gPmmCfg, pUpdatedPwrSaveCfg, sizeof(tSirPowerSaveCfg)); @@ -2157,17 +2151,23 @@ void pmmEnterWowlRequestHandler(tpAniSirGlobal pMac, tpSirMsgQ pMsg) #endif //FEATURE_WLAN_DIAG_SUPPORT pSmeWowlParams = (tpSirSmeWowlEnterParams)(pMbMsg->data); + if (NULL == pSmeWowlParams) + { + limLog(pMac, LOGE, + FL("NULL message received")); + return; + } - if((pSessionEntry = peFindSessionByBssid(pMac,pSmeWowlParams->bssId,&peSessionId))== NULL) + pSessionEntry = peFindSessionByBssid(pMac, pSmeWowlParams->bssId, + &peSessionId); + if (NULL == pSessionEntry) { - limLog(pMac, LOGE, + limLog(pMac, LOGE, FL("session does not exist for given BSSId")); goto end; } pMac->pmm.sessionId = peSessionId; - if (NULL == pSmeWowlParams) - return; // Need to fix it ASAP - TBH #if 0 if (pMac->lim.gLimSmeState != eLIM_SME_LINK_EST_STATE) diff --git a/drivers/staging/prima/CORE/MAC/src/pe/rrm/rrmApi.c b/drivers/staging/prima/CORE/MAC/src/pe/rrm/rrmApi.c index d276e519df7..29987c52ec1 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/rrm/rrmApi.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/rrm/rrmApi.c @@ -39,15 +39,15 @@ * PERFORMANCE OF THIS SOFTWARE. */ + + + /**========================================================================= \file rrmApi.c \brief implementation for PE RRM APIs - Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved. - - Qualcomm Confidential and Proprietary. ========================================================================*/ @@ -223,16 +223,31 @@ rrmSetMaxTxPowerRsp ( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ) tSirRetStatus retCode = eSIR_SUCCESS; tpMaxTxPowerParams pMaxTxParams = (tpMaxTxPowerParams) limMsgQ->bodyptr; tpPESession pSessionEntry; - tANI_U8 sessionId; + tANI_U8 sessionId, i; + tSirMacAddr bssid = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; - if((pSessionEntry = peFindSessionByBssid(pMac, pMaxTxParams->bssId, &sessionId))==NULL) + if( palEqualMemory(pMac->hHdd, bssid, pMaxTxParams->bssId, sizeof(tSirMacAddr))) { - PELOGE(limLog(pMac, LOGE, FL("Unable to find session:") );) - retCode = eSIR_FAILURE; + for (i =0;i < pMac->lim.maxBssId;i++) + { + if ( (pMac->lim.gpSession[i].valid == TRUE )) + { + pSessionEntry = &pMac->lim.gpSession[i]; + rrmCacheMgmtTxPower ( pMac, pMaxTxParams->power, pSessionEntry ); + } + } } else { - rrmCacheMgmtTxPower ( pMac, pMaxTxParams->power, pSessionEntry ); + if((pSessionEntry = peFindSessionByBssid(pMac, pMaxTxParams->bssId, &sessionId))==NULL) + { + PELOGE(limLog(pMac, LOGE, FL("Unable to find session:") );) + retCode = eSIR_FAILURE; + } + else + { + rrmCacheMgmtTxPower ( pMac, pMaxTxParams->power, pSessionEntry ); + } } palFreeMemory(pMac->hHdd, (void*)limMsgQ->bodyptr); diff --git a/drivers/staging/prima/CORE/MAC/src/pe/sch/schBeaconProcess.c b/drivers/staging/prima/CORE/MAC/src/pe/sch/schBeaconProcess.c index ab66fa211bf..3d6db8c73fc 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/sch/schBeaconProcess.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/sch/schBeaconProcess.c @@ -656,7 +656,11 @@ void schBeaconProcess(tpAniSirGlobal pMac, tANI_U8* pRxPacketInfo, tpPESession p * */ - if((pAPSession = limIsApSessionActive(pMac)) != NULL) + if (((pAPSession = limIsApSessionActive(pMac)) != NULL) +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + && (!(WDA_GET_OFFLOADSCANLEARN(pRxPacketInfo))) +#endif + ) { beaconParams.bssIdx = pAPSession->bssIdx; if (pAPSession->gLimProtectionControl != WNI_CFG_FORCE_POLICY_PROTECTION_DISABLE) diff --git a/drivers/staging/prima/CORE/SAP/inc/sapApi.h b/drivers/staging/prima/CORE/SAP/inc/sapApi.h index 18cfef49339..43c2e9d2aac 100644 --- a/drivers/staging/prima/CORE/SAP/inc/sapApi.h +++ b/drivers/staging/prima/CORE/SAP/inc/sapApi.h @@ -109,10 +109,9 @@ when who what, where, why /*-------------------------------------------------------------------------- defines and enum ------------------------------------------------------------------------*/ - + #define MAX_SSID_LEN 32 -#define MAX_MAC_ADDRESS_ACCEPTED 16 -#define MAX_MAC_ADDRESS_DENIED MAX_MAC_ADDRESS_ACCEPTED +#define MAX_ACL_MAC_ADDRESS 16 #define AUTO_CHANNEL_SELECT 0 #define MAX_ASSOC_IND_IE_LEN 255 @@ -419,11 +418,11 @@ typedef struct sap_Config { tSap_SSIDInfo_t SSIDinfo; eSapPhyMode SapHw_mode; /* Wireless Mode */ eSapMacAddrACL SapMacaddr_acl; - v_MACADDR_t accept_mac[MAX_MAC_ADDRESS_ACCEPTED]; /* MAC filtering */ + v_MACADDR_t accept_mac[MAX_ACL_MAC_ADDRESS]; /* MAC filtering */ v_BOOL_t ieee80211d; /*Specify if 11D is enabled or disabled*/ v_BOOL_t protEnabled; /*Specify if protection is enabled or disabled*/ v_BOOL_t obssProtEnabled; /*Specify if OBSS protection is enabled or disabled*/ - v_MACADDR_t deny_mac[MAX_MAC_ADDRESS_DENIED]; /* MAC filtering */ + v_MACADDR_t deny_mac[MAX_ACL_MAC_ADDRESS]; /* MAC filtering */ v_MACADDR_t self_macaddr; //self macaddress or BSSID v_U8_t channel; /* Operation channel */ @@ -906,6 +905,38 @@ WLANSAP_StartBss tsap_Config_t *pConfig, v_PVOID_t pUsrContext ); +/*========================================================================== + FUNCTION WLANSAP_SetMacACL + + DESCRIPTION + This api function provides SAP to set mac list entry in accept list as well + as deny list + + DEPENDENCIES + NA. + + PARAMETERS + + IN +pvosGCtx: Pointer to vos global context structure +pConfig: Pointer to configuration structure passed down from + HDD(HostApd for Android) + + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_SetMacACL +( + v_PVOID_t pvosGCtx, + tsap_Config_t *pConfig +); + /*========================================================================== FUNCTION WLANSAP_Stop diff --git a/drivers/staging/prima/CORE/SAP/src/sapChSelect.c b/drivers/staging/prima/CORE/SAP/src/sapChSelect.c index d7c5f924584..8c5b143410e 100644 --- a/drivers/staging/prima/CORE/SAP/src/sapChSelect.c +++ b/drivers/staging/prima/CORE/SAP/src/sapChSelect.c @@ -96,6 +96,11 @@ --------------------------------------------------------------------------*/ #define SAP_DEBUG +#define IS_RSSI_VALID( extRssi, rssi ) \ +( \ + ((extRssi < rssi)?eANI_BOOLEAN_TRUE:eANI_BOOLEAN_FALSE) \ +) + /*========================================================================== FUNCTION sapCleanupChannelList @@ -487,6 +492,7 @@ v_U32_t sapweightRssiCount(v_S7_t rssi, v_U16_t count) void sapInterferenceRssiCount(tSapSpectChInfo *pSpectCh) { tSapSpectChInfo *pExtSpectCh = NULL; + v_S31_t rssi; switch(pSpectCh->chNum) { case CHANNEL_1: @@ -494,7 +500,11 @@ void sapInterferenceRssiCount(tSapSpectChInfo *pSpectCh) if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_24GHZ_FIRST_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_24GHZ_FIRST_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -502,7 +512,11 @@ void sapInterferenceRssiCount(tSapSpectChInfo *pSpectCh) if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_24GHZ_SEC_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_24GHZ_SEC_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -510,7 +524,11 @@ void sapInterferenceRssiCount(tSapSpectChInfo *pSpectCh) if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_24GHZ_THIRD_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_24GHZ_THIRD_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -518,7 +536,11 @@ void sapInterferenceRssiCount(tSapSpectChInfo *pSpectCh) if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_24GHZ_FOURTH_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_24GHZ_FOURTH_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -528,7 +550,11 @@ void sapInterferenceRssiCount(tSapSpectChInfo *pSpectCh) if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_24GHZ_FIRST_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_24GHZ_FIRST_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -536,7 +562,11 @@ void sapInterferenceRssiCount(tSapSpectChInfo *pSpectCh) if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_24GHZ_FIRST_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_24GHZ_FIRST_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -544,7 +574,11 @@ void sapInterferenceRssiCount(tSapSpectChInfo *pSpectCh) if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_24GHZ_SEC_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_24GHZ_SEC_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -552,7 +586,11 @@ void sapInterferenceRssiCount(tSapSpectChInfo *pSpectCh) if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_24GHZ_THIRD_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_24GHZ_THIRD_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -568,7 +606,11 @@ void sapInterferenceRssiCount(tSapSpectChInfo *pSpectCh) if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_24GHZ_FIRST_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_24GHZ_FIRST_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -576,7 +618,11 @@ void sapInterferenceRssiCount(tSapSpectChInfo *pSpectCh) if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_24GHZ_FIRST_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_24GHZ_FIRST_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -584,7 +630,11 @@ void sapInterferenceRssiCount(tSapSpectChInfo *pSpectCh) if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_24GHZ_SEC_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_24GHZ_SEC_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -592,7 +642,11 @@ void sapInterferenceRssiCount(tSapSpectChInfo *pSpectCh) if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_24GHZ_SEC_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_24GHZ_SEC_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -602,7 +656,11 @@ void sapInterferenceRssiCount(tSapSpectChInfo *pSpectCh) if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_24GHZ_FIRST_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_24GHZ_FIRST_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -610,7 +668,11 @@ void sapInterferenceRssiCount(tSapSpectChInfo *pSpectCh) if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_24GHZ_FIRST_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_24GHZ_FIRST_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -618,7 +680,11 @@ void sapInterferenceRssiCount(tSapSpectChInfo *pSpectCh) if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_24GHZ_SEC_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_24GHZ_SEC_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -626,7 +692,11 @@ void sapInterferenceRssiCount(tSapSpectChInfo *pSpectCh) if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_24GHZ_THIRD_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_24GHZ_THIRD_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -636,7 +706,11 @@ void sapInterferenceRssiCount(tSapSpectChInfo *pSpectCh) if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_24GHZ_FIRST_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_24GHZ_FIRST_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -644,7 +718,11 @@ void sapInterferenceRssiCount(tSapSpectChInfo *pSpectCh) if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_24GHZ_SEC_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_24GHZ_SEC_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -652,7 +730,11 @@ void sapInterferenceRssiCount(tSapSpectChInfo *pSpectCh) if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_24GHZ_THIRD_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_24GHZ_THIRD_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -660,7 +742,11 @@ void sapInterferenceRssiCount(tSapSpectChInfo *pSpectCh) if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_24GHZ_FOURTH_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_24GHZ_FOURTH_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -797,8 +883,12 @@ void sapComputeSpectWeight( tSapChSelSpectInfo* pSpectInfoParams, if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + SAP_SUBBAND1_RSSI_EFFECT_PRIMARY; // REducing the rssi by -20 and assigning it to Extension channel - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_SUBBAND1_RSSI_EFFECT_PRIMARY); + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -807,7 +897,11 @@ void sapComputeSpectWeight( tSapChSelSpectInfo* pSpectInfoParams, pExtSpectCh = (pSpectCh - 1); if(pExtSpectCh != NULL) { - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_SUBBAND1_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_SUBBAND1_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; ++pExtSpectCh->bssCount; @@ -823,7 +917,11 @@ void sapComputeSpectWeight( tSapChSelSpectInfo* pSpectInfoParams, if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_SUBBAND1_RSSI_EFFECT_PRIMARY); // Reducing the rssi by -20 and assigning it to Subband 1 + rssi = pSpectCh->rssiAgr + SAP_SUBBAND1_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; // Reducing the rssi by -20 and assigning it to Subband 1 + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -831,7 +929,11 @@ void sapComputeSpectWeight( tSapChSelSpectInfo* pSpectInfoParams, if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_SUBBAND2_RSSI_EFFECT_PRIMARY); // Reducing the rssi by -30 and assigning it to Subband 2 + rssi = pSpectCh->rssiAgr + SAP_SUBBAND2_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; // Reducing the rssi by -30 and assigning it to Subband 2 + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -839,7 +941,11 @@ void sapComputeSpectWeight( tSapChSelSpectInfo* pSpectInfoParams, if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_SUBBAND3_RSSI_EFFECT_PRIMARY); // Reducing the rssi by -40 and assigning it to Subband 3 + rssi = pSpectCh->rssiAgr + SAP_SUBBAND3_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; // Reducing the rssi by -40 and assigning it to Subband 3 + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -851,7 +957,11 @@ void sapComputeSpectWeight( tSapChSelSpectInfo* pSpectInfoParams, if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_SUBBAND1_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_SUBBAND1_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -859,7 +969,11 @@ void sapComputeSpectWeight( tSapChSelSpectInfo* pSpectInfoParams, if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_SUBBAND1_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_SUBBAND1_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -867,7 +981,11 @@ void sapComputeSpectWeight( tSapChSelSpectInfo* pSpectInfoParams, if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_SUBBAND2_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_SUBBAND2_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -879,7 +997,11 @@ void sapComputeSpectWeight( tSapChSelSpectInfo* pSpectInfoParams, if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_SUBBAND1_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_SUBBAND1_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -887,7 +1009,11 @@ void sapComputeSpectWeight( tSapChSelSpectInfo* pSpectInfoParams, if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_SUBBAND2_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_SUBBAND2_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -895,7 +1021,11 @@ void sapComputeSpectWeight( tSapChSelSpectInfo* pSpectInfoParams, if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_SUBBAND1_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_SUBBAND1_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -907,7 +1037,11 @@ void sapComputeSpectWeight( tSapChSelSpectInfo* pSpectInfoParams, if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_SUBBAND1_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_SUBBAND1_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -915,7 +1049,11 @@ void sapComputeSpectWeight( tSapChSelSpectInfo* pSpectInfoParams, if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_SUBBAND2_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_SUBBAND2_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -923,7 +1061,11 @@ void sapComputeSpectWeight( tSapChSelSpectInfo* pSpectInfoParams, if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_SUBBAND3_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_SUBBAND3_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -937,7 +1079,7 @@ void sapComputeSpectWeight( tSapChSelSpectInfo* pSpectInfoParams, } VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, - "In %s, bssdes.ch_self=%d, bssdes.ch_ID=%d, bssdes.rssi=%d, SpectCh.bssCount=%d, pScanResult=0x%x, ChannelWidth %d, secondaryChanOffset %d, center frequency %d \n", + "In %s, bssdes.ch_self=%d, bssdes.ch_ID=%d, bssdes.rssi=%d, SpectCh.bssCount=%d, pScanResult=%p, ChannelWidth %d, secondaryChanOffset %d, center frequency %d \n", __func__, pScanResult->BssDescriptor.channelIdSelf, pScanResult->BssDescriptor.channelId, pScanResult->BssDescriptor.rssi, pSpectCh->bssCount, pScanResult,pSpectCh->channelWidth,secondaryChannelOffset,centerFreq); pSpectCh++; break; @@ -1070,57 +1212,6 @@ void sapSortChlWeight(tSapChSelSpectInfo *pSpectInfoParams) } -/*========================================================================== - FUNCTION sapComputeNonOverlapChannel - - DESCRIPTION - Checking for the Free Non Overlapping Channel - - DEPENDENCIES - NA. - - PARAMETERS - - IN - pSpectInfoParams: Spectrum Info params - - RETURN VALUE - v_U8_t : Success - Bit mask - - SIDE EFFECTS -============================================================================*/ -v_U8_t sapComputeNonOverlapChannel(tSapChSelSpectInfo* pSpectInfoParams) -{ - v_U8_t nonOverlap = 0; - tSapSpectChInfo *pSpectCh = NULL; - v_U8_t chn_num = 0; - pSpectCh = pSpectInfoParams->pSpectCh; - for (chn_num = 0; chn_num < (pSpectInfoParams->numSpectChans); chn_num++) { - if(pSpectCh->chNum == CHANNEL_1 || pSpectCh->chNum == CHANNEL_6 || pSpectCh->chNum == CHANNEL_11) - { - switch(pSpectCh->chNum) - { - case 1: - if(pSpectCh->weight == 0) - nonOverlap |= 0x1; //Bit 0 For channel 1 - break; - case 6: - if(pSpectCh->weight == 0) - nonOverlap |= 0x2; // Bit 1 For Channel 6 - break; - case 11: - if(pSpectCh->weight == 0) - nonOverlap |= 0x4; // Bit 2 for Channel 11 - break; - default: - break; - } - } - pSpectCh++; - } - return nonOverlap; -} - /*========================================================================== FUNCTION sapSelectChannel @@ -1147,7 +1238,6 @@ v_U8_t sapSelectChannel(tHalHandle halHandle, ptSapContext pSapCtx, tScanResult // DFS param object holding all the data req by the algo tSapChSelSpectInfo oSpectInfoParams = {NULL,0}; tSapChSelSpectInfo *pSpectInfoParams = &oSpectInfoParams; // Memory? NB - v_U8_t nonOverlap = 0; v_U8_t bestChNum = 0; #ifdef SOFTAP_CHANNEL_RANGE v_U32_t startChannelNum; @@ -1177,59 +1267,49 @@ v_U8_t sapSelectChannel(tHalHandle halHandle, ptSapContext pSapCtx, tScanResult ccmCfgGetInt( halHandle, WNI_CFG_SAP_CHANNEL_SELECT_END_CHANNEL, &endChannelNum); ccmCfgGetInt( halHandle, WNI_CFG_SAP_CHANNEL_SELECT_OPERATING_BAND, &operatingBand); - // Calculating the Non overlapping Channel Availability */ - if(operatingBand == RF_SUBBAND_2_4_GHZ) - nonOverlap = sapComputeNonOverlapChannel(pSpectInfoParams); - /*Loop till get the best channel in the given range */ for(count=0; count < pSpectInfoParams->numSpectChans ; count++) { if((startChannelNum <= pSpectInfoParams->pSpectCh[count].chNum)&& ( endChannelNum >= pSpectInfoParams->pSpectCh[count].chNum)) { - bestChNum = (v_U8_t)pSpectInfoParams->pSpectCh[count].chNum; - break; - } - } - + if(bestChNum == 0) + { + bestChNum = (v_U8_t)pSpectInfoParams->pSpectCh[count].chNum; + } + else + { + if(operatingBand == RF_SUBBAND_2_4_GHZ) + { + /* Give preference to Non-overlap channels */ + if(((pSpectInfoParams->pSpectCh[count].chNum == CHANNEL_1) || + (pSpectInfoParams->pSpectCh[count].chNum == CHANNEL_6) || + (pSpectInfoParams->pSpectCh[count].chNum == CHANNEL_11))&& + (pSpectInfoParams->pSpectCh[count].weight == 0)) + { + bestChNum = (v_U8_t)pSpectInfoParams->pSpectCh[count].chNum; + break; + } + } + } + } + } #else // Get the first channel in sorted array as best 20M Channel bestChNum = (v_U8_t)pSpectInfoParams->pSpectCh[0].chNum; - #endif - + //Select Best Channel from Channel List if Configured bestChNum = sapSelectPreferredChannelFromChannelList(bestChNum, pSapCtx, pSpectInfoParams); - if(operatingBand == RF_SUBBAND_2_4_GHZ) - { - if(nonOverlap) - { - switch(nonOverlap) - { - case 0x1: - bestChNum = CHANNEL_1; - break; - case 0x2: - bestChNum = CHANNEL_6; - break; - case 0x4: - bestChNum = CHANNEL_11; - break; - default: - break; - } - } - } - // Free all the allocated memory sapChanSelExit(pSpectInfoParams); VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, "In %s, Running SAP Ch select Completed, Ch=%d", - __func__, bestChNum); - + __func__, bestChNum); if (bestChNum > 0 && bestChNum <= 252) return bestChNum; else return SAP_CHANNEL_NOT_SELECTED; } + diff --git a/drivers/staging/prima/CORE/SAP/src/sapFsm.c b/drivers/staging/prima/CORE/SAP/src/sapFsm.c index 13860c10bd5..fb441a3caca 100644 --- a/drivers/staging/prima/CORE/SAP/src/sapFsm.c +++ b/drivers/staging/prima/CORE/SAP/src/sapFsm.c @@ -513,7 +513,11 @@ sapSignalHDDevent /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ /* Format the Start BSS Complete event to return... */ - VOS_ASSERT(sapContext->pfnSapEventCallback); + if (NULL == sapContext->pfnSapEventCallback) + { + VOS_ASSERT(0); + return VOS_STATUS_E_FAILURE; + } switch (sapHddevent) { diff --git a/drivers/staging/prima/CORE/SAP/src/sapInternal.h b/drivers/staging/prima/CORE/SAP/src/sapInternal.h index 915ef1f315c..a4629942b9e 100644 --- a/drivers/staging/prima/CORE/SAP/src/sapInternal.h +++ b/drivers/staging/prima/CORE/SAP/src/sapInternal.h @@ -204,9 +204,9 @@ typedef struct sSapContext { // Mac filtering settings eSapMacAddrACL eSapMacAddrAclMode; - v_MACADDR_t acceptMacList[MAX_MAC_ADDRESS_ACCEPTED]; + v_MACADDR_t acceptMacList[MAX_ACL_MAC_ADDRESS]; v_U8_t nAcceptMac; - v_MACADDR_t denyMacList[MAX_MAC_ADDRESS_DENIED]; + v_MACADDR_t denyMacList[MAX_ACL_MAC_ADDRESS]; v_U8_t nDenyMac; // QOS config @@ -592,26 +592,28 @@ sapSortMacList(v_MACADDR_t *macList, v_U8_t size); FUNCTION sapAddMacToACL - DESCRIPTION + DESCRIPTION Function to ADD a mac address in an ACL. The function ensures that the ACL list remains sorted after the addition. - This API does not take care of buffer overflow i.e. if the list is already maxed out while adding a mac address, - it will still try to add. - The caller must take care that the ACL size is less than MAX_MAC_ADDRESS_ACCEPTED before calling this function. + This API does not take care of buffer overflow i.e. if the list is already + maxed out while adding a mac address, it will still try to add. + The caller must take care that the ACL size is less than MAX_ACL_MAC_ADDRESS + before calling this function. - DEPENDENCIES + DEPENDENCIES - PARAMETERS + PARAMETERS IN macList : ACL list of mac addresses (black/white list) - size (I/O) : size of the ACL. It is an I/O arg. The API takes care of incrementing the size by 1. + size (I/O) : size of the ACL. It is an I/O arg. The API takes care + of incrementing the size by 1. peerMac : Mac address of the peer to be added RETURN VALUE None. - SIDE EFFECTS + SIDE EFFECTS ============================================================================*/ void diff --git a/drivers/staging/prima/CORE/SAP/src/sapModule.c b/drivers/staging/prima/CORE/SAP/src/sapModule.c index 4b3a9fb014f..b6a184fc6b0 100644 --- a/drivers/staging/prima/CORE/SAP/src/sapModule.c +++ b/drivers/staging/prima/CORE/SAP/src/sapModule.c @@ -466,7 +466,7 @@ WLANSAP_CleanCB pSapCtx->sapsMachine= eSAP_DISCONNECTED; - VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: Initializing State: %d, sapContext value = %x", + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: Initializing State: %d, sapContext value = %p", __func__, pSapCtx->sapsMachine, pSapCtx); pSapCtx->sessionId = 0; pSapCtx->channel = 0; @@ -674,6 +674,82 @@ WLANSAP_StartBss return vosStatus; }// WLANSAP_StartBss +/*========================================================================== + FUNCTION WLANSAP_SetMacACL + + DESCRIPTION + This api function provides SAP to set mac list entry in accept list as well + as deny list + + DEPENDENCIES + + PARAMETERS + + IN + pContext : Pointer to Sap Context structure + pQctCommitConfig : Pointer to configuration structure passed down from + HDD(HostApd for Android) + + RETURN VALUE + The result code associated with performing the operation + + VOS_STATUS_E_FAULT: Pointer to SAP cb is NULL ; access would cause a page + fault + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_SetMacACL +( + v_PVOID_t pvosGCtx, //pwextCtx + tsap_Config_t *pConfig +) +{ + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + ptSapContext pSapCtx = NULL; + + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "WLANSAP_SetMacACL"); + + if (VOS_STA_SAP_MODE == vos_get_conparam ()) + { + pSapCtx = VOS_GET_SAP_CB(pvosGCtx); + if ( NULL == pSapCtx ) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: Invalid SAP pointer from pvosGCtx", __func__); + return VOS_STATUS_E_FAULT; + } + + // Copy MAC filtering settings to sap context + pSapCtx->eSapMacAddrAclMode = pConfig->SapMacaddr_acl; + + if (eSAP_DENY_UNLESS_ACCEPTED == pSapCtx->eSapMacAddrAclMode) + { + vos_mem_copy(pSapCtx->acceptMacList, pConfig->accept_mac, + sizeof(pConfig->accept_mac)); + pSapCtx->nAcceptMac = pConfig->num_accept_mac; + sapSortMacList(pSapCtx->acceptMacList, pSapCtx->nAcceptMac); + } + else if (eSAP_ACCEPT_UNLESS_DENIED == pSapCtx->eSapMacAddrAclMode) + { + vos_mem_copy(pSapCtx->denyMacList, pConfig->deny_mac, + sizeof(pConfig->deny_mac)); + pSapCtx->nDenyMac = pConfig->num_deny_mac; + sapSortMacList(pSapCtx->denyMacList, pSapCtx->nDenyMac); + } + } + else + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s : SoftAp role has not been enabled", __func__); + return VOS_STATUS_E_FAULT; + } + + return vosStatus; +}//WLANSAP_SetMacACL + /*========================================================================== FUNCTION WLANSAP_StopBss @@ -1011,7 +1087,7 @@ WLANSAP_ModifyACL { //error check // if list is already at max, return failure - if (pSapCtx->nAcceptMac == MAX_MAC_ADDRESS_ACCEPTED) + if (pSapCtx->nAcceptMac == MAX_ACL_MAC_ADDRESS) { VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, "White list is already maxed out. Cannot accept %02x:%02x:%02x:%02x:%02x:%02x", @@ -1074,7 +1150,7 @@ WLANSAP_ModifyACL { //error check // if list is already at max, return failure - if (pSapCtx->nDenyMac == MAX_MAC_ADDRESS_ACCEPTED) + if (pSapCtx->nDenyMac == MAX_ACL_MAC_ADDRESS) { VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, "Black list is already maxed out. Cannot accept %02x:%02x:%02x:%02x:%02x:%02x", diff --git a/drivers/staging/prima/CORE/SME/inc/csrApi.h b/drivers/staging/prima/CORE/SME/inc/csrApi.h index 432c01c955a..9373f0231f5 100644 --- a/drivers/staging/prima/CORE/SME/inc/csrApi.h +++ b/drivers/staging/prima/CORE/SME/inc/csrApi.h @@ -81,9 +81,6 @@ typedef enum eCSR_AUTH_TYPE_CCKM_WPA, eCSR_AUTH_TYPE_CCKM_RSN, #endif /* FEATURE_WLAN_CCX */ -#ifdef WLAN_FEATURE_11W - eCSR_AUTH_TYPE_RSN_PSK_SHA256, -#endif eCSR_NUM_OF_SUPPORT_AUTH_TYPE, eCSR_AUTH_TYPE_FAILED = 0xff, eCSR_AUTH_TYPE_UNKNOWN = eCSR_AUTH_TYPE_FAILED, @@ -265,7 +262,9 @@ typedef struct tagCsrStaParams tANI_U8 extn_capability[SIR_MAC_MAX_EXTN_CAP]; tANI_U8 supported_rates_len; tANI_U8 supported_rates[SIR_MAC_MAX_SUPP_RATES]; + tANI_U8 htcap_present; tSirHTCap HTCap; + tANI_U8 vhtcap_present; tSirVHTCap VHTCap; tANI_U8 uapsd_queues; tANI_U8 max_sp; @@ -463,9 +462,6 @@ typedef enum eCSR_ROAM_DISCONNECT_ALL_P2P_CLIENTS, //Disaconnect all the clients eCSR_ROAM_SEND_P2P_STOP_BSS, //Stopbss triggered from SME due to different // beacon interval -#ifdef WLAN_FEATURE_11W - eCSR_ROAM_UNPROT_MGMT_FRAME_IND, -#endif }eRoamCmdStatus; @@ -711,8 +707,7 @@ typedef enum }eCsrWEPStaticKeyID; -// Two extra key indicies are used for the IGTK (which is used by BIP) -#define CSR_MAX_NUM_KEY (eCSR_SECURITY_WEP_STATIC_KEY_ID_MAX + 2 + 1) +#define CSR_MAX_NUM_KEY (eCSR_SECURITY_WEP_STATIC_KEY_ID_MAX + 1) typedef enum { @@ -833,13 +828,6 @@ typedef struct tagCsrRoamProfile //This field is for output only, not for input eCsrEncryptionType negotiatedMCEncryptionType; -#ifdef WLAN_FEATURE_11W - // Management Frame Protection - tANI_BOOLEAN MFPEnabled; - tANI_U8 MFPRequired; - tANI_U8 MFPCapable; -#endif - tCsrKeys Keys; eCsrCBChoice CBMode; //up, down or auto tCsrChannelInfo ChannelInfo; @@ -925,6 +913,7 @@ typedef struct tagCsrRoamConnectedProfile tCsrCcxCckmInfo ccxCckmInfo; tANI_BOOLEAN isCCXAssoc; #endif + tANI_U32 dot11Mode; }tCsrRoamConnectedProfile; @@ -1013,14 +1002,17 @@ typedef struct tagCsrConfigParam tANI_U32 nActiveMinChnTimeBtc; //in units of milliseconds tANI_U32 nActiveMaxChnTimeBtc; //in units of milliseconds + tANI_U32 disableAggWithBtc; #ifdef WLAN_AP_STA_CONCURRENCY tANI_U32 nPassiveMinChnTimeConc; //in units of milliseconds tANI_U32 nPassiveMaxChnTimeConc; //in units of milliseconds tANI_U32 nActiveMinChnTimeConc; //in units of milliseconds tANI_U32 nActiveMaxChnTimeConc; //in units of milliseconds tANI_U32 nRestTimeConc; //in units of milliseconds - tANI_U8 nNumChanCombinedConc; //number of channels combined - //in each split scan operation + tANI_U8 nNumStaChanCombinedConc; //number of channels combined for + //STA in each split scan operation + tANI_U8 nNumP2PChanCombinedConc; //number of channels combined for + //P2P in each split scan operation #endif tANI_BOOLEAN IsIdleScanEnabled; @@ -1041,9 +1033,10 @@ typedef struct tagCsrConfigParam #endif #if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR) - tANI_U8 isFastTransitionEnabled; - tANI_U8 RoamRssiDiff; - tANI_U8 nImmediateRoamRssiDiff; + tANI_U8 isFastTransitionEnabled; + tANI_U8 RoamRssiDiff; + tANI_U8 nImmediateRoamRssiDiff; + tANI_BOOLEAN isWESModeEnabled; #endif #ifdef WLAN_FEATURE_NEIGHBOR_ROAMING @@ -1084,10 +1077,15 @@ typedef struct tagCsrConfigParam */ tANI_BOOLEAN fFirstScanOnly2GChnl; - tANI_BOOLEAN fIgnore_chan165; #if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR) tANI_BOOLEAN nRoamPrefer5GHz; tANI_BOOLEAN nRoamIntraBand; + tANI_U8 nProbes; + tANI_U16 nRoamScanHomeAwayTime; +#endif + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + tANI_BOOLEAN isRoamOffloadScanEnabled; #endif tANI_U8 scanCfgAgingTime; diff --git a/drivers/staging/prima/CORE/SME/inc/csrInternal.h b/drivers/staging/prima/CORE/SME/inc/csrInternal.h old mode 100644 new mode 100755 index 189c1991696..366fa397ea3 --- a/drivers/staging/prima/CORE/SME/inc/csrInternal.h +++ b/drivers/staging/prima/CORE/SME/inc/csrInternal.h @@ -18,6 +18,37 @@ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ +/* + * Copyright (c) 2012, The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** ------------------------------------------------------------------------- * + ------------------------------------------------------------------------- * + + + \file csrInternal.h + + Define internal data structure for MAC. + + Copyright (C) 2006 Airgo Networks, Incorporated + ========================================================================== */ #ifndef CSRINTERNAL_H__ #define CSRINTERNAL_H__ @@ -74,6 +105,13 @@ ) #endif +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +#define CSR_IS_ROAM_SCAN_OFFLOAD_ENABLED( pMac ) \ +( \ + (((pMac)->roam.configParam.isRoamOffloadScanEnabled)?eANI_BOOLEAN_TRUE:eANI_BOOLEAN_FALSE) \ +) +#endif + //Support for "Fast roaming" (i.e., CCX, LFR, or 802.11r.) #define CSR_BG_SCAN_OCCUPIED_CHANNEL_LIST_LEN 15 @@ -135,7 +173,8 @@ typedef enum eCsrScanProbeBss, // directed probe on an entry from the candidate list - HO eCsrScanAbortBgScan, //aborting a BG scan (meaning the scan is triggered by LIM timer) eCsrScanAbortNormalScan, //aborting a normal scan (the scan is trigger by eWNI_SME_SCAN_REQ) - eCsrScanP2PFindPeer + eCsrScanP2PFindPeer, + eCsrScanGetLfrResult, // get the LFR candidates from PE scan cache }eCsrScanReason; typedef enum @@ -422,6 +461,7 @@ typedef struct tagAddStaForSessionCmd { //Session self mac addr tSirMacAddr selfMacAddr; + tVOS_CON_MODE currDeviceMode; }tAddStaForSessionCmd; typedef struct tagDelStaForSessionCmd @@ -535,14 +575,17 @@ typedef struct tagCsrConfig tANI_U32 nActiveMinChnTimeBtc; //in units of milliseconds tANI_U32 nActiveMaxChnTimeBtc; //in units of milliseconds + tANI_U8 disableAggWithBtc; #ifdef WLAN_AP_STA_CONCURRENCY tANI_U32 nPassiveMinChnTimeConc; //in units of milliseconds tANI_U32 nPassiveMaxChnTimeConc; //in units of milliseconds tANI_U32 nActiveMinChnTimeConc; //in units of milliseconds tANI_U32 nActiveMaxChnTimeConc; //in units of milliseconds tANI_U32 nRestTimeConc; //in units of milliseconds - tANI_U8 nNumChanCombinedConc; //number of channels combined - //in each split scan operation + tANI_U8 nNumStaChanCombinedConc; //number of channels combined for + //Sta in each split scan operation + tANI_U8 nNumP2PChanCombinedConc; //number of channels combined for + //P2P in each split scan operation #endif tANI_BOOLEAN IsIdleScanEnabled; @@ -561,6 +604,9 @@ typedef struct tagCsrConfig #ifdef FEATURE_WLAN_LFR tANI_U8 isFastRoamIniFeatureEnabled; +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + tANI_U8 isRoamOffloadScanEnabled; +#endif #endif #ifdef FEATURE_WLAN_CCX @@ -572,9 +618,11 @@ typedef struct tagCsrConfig tANI_U8 RoamRssiDiff; tANI_U8 nImmediateRoamRssiDiff; tANI_BOOLEAN nRoamPrefer5GHz; - tANI_BOOLEAN nRoamIntraBand; tANI_BOOLEAN isWESModeEnabled; tANI_BOOLEAN nRoamScanControl; + tANI_BOOLEAN nRoamIntraBand; + tANI_U8 nProbes; + tANI_U16 nRoamScanHomeAwayTime; #endif #ifdef WLAN_FEATURE_NEIGHBOR_ROAMING @@ -667,6 +715,7 @@ typedef struct tagCsrScanStruct tANI_U8 countryCode11d[WNI_CFG_COUNTRY_CODE_LEN]; v_REGDOMAIN_t domainIdDefault; //default regulatory domain v_REGDOMAIN_t domainIdCurrent; //current regulatory domain + tCsrBssid currentCountryBssid; // Bssid for current country code tANI_BOOLEAN f11dInfoApplied; tANI_BOOLEAN fCancelIdleScan; #ifdef FEATURE_WLAN_WAPI @@ -708,8 +757,6 @@ typedef struct tagCsrScanStruct tDblLinkList scanCmdPendingList; #endif tCsrChannel occupiedChannels; //This includes all channels on which candidate APs are found - - tANI_BOOLEAN fIgnore_chan165; }tCsrScanStruct; #ifdef FEATURE_WLAN_TDLS_INTERNAL @@ -1271,7 +1318,8 @@ tANI_BOOLEAN csrIsSetKeyAllowed(tpAniSirGlobal pMac, tANI_U32 sessionId); void csrSetOppositeBandChannelInfo( tpAniSirGlobal pMac ); void csrConstructCurrentValidChannelList( tpAniSirGlobal pMac, tDblLinkList *pChannelSetList, tANI_U8 *pChannelList, tANI_U8 bSize, tANI_U8 *pNumChannels ); - +eHalStatus csrScanSavePreferredNetworkFound(tpAniSirGlobal pMac, + tSirPrefNetworkFoundInd *pPrefNetworkFoundInd); #endif #ifdef WLAN_FEATURE_VOWIFI_11R @@ -1291,7 +1339,15 @@ void csrDisconnectAllActiveSessions(tpAniSirGlobal pMac); #ifdef FEATURE_WLAN_LFR //Returns whether "Legacy Fast Roaming" is enabled...or not tANI_BOOLEAN csrRoamIsFastRoamEnabled(tpAniSirGlobal pMac, tANI_U32 sessionId); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +tANI_BOOLEAN csrRoamIsRoamOffloadScanEnabled(tpAniSirGlobal pMac); +#endif tANI_BOOLEAN csrIsChannelPresentInList( tANI_U8 *pChannelList, int numChannels, tANI_U8 channel ); VOS_STATUS csrAddToChannelListFront( tANI_U8 *pChannelList, int numChannels, tANI_U8 channel ); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +eHalStatus csrScanRequestLfrResult(tpAniSirGlobal pMac, tANI_U32 sessionId, + csrScanCompleteCallback callback, void *pContext); +#endif +tANI_BOOLEAN csrRoamIsStaMode(tpAniSirGlobal pMac, tANI_U32 sessionId); #endif diff --git a/drivers/staging/prima/CORE/SME/inc/csrNeighborRoam.h b/drivers/staging/prima/CORE/SME/inc/csrNeighborRoam.h index dab7fa7cef0..768fd1e0505 100644 --- a/drivers/staging/prima/CORE/SME/inc/csrNeighborRoam.h +++ b/drivers/staging/prima/CORE/SME/inc/csrNeighborRoam.h @@ -245,7 +245,29 @@ VOS_STATUS csrNeighborRoamChannelsFilterByCurrentBand( tANI_U8* pOutputChannelList, int* pMergedOutputNumOfChannels ); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +#define ROAM_SCAN_OFFLOAD_START 1 +#define ROAM_SCAN_OFFLOAD_STOP 2 +#define ROAM_SCAN_OFFLOAD_RESTART 3 +#define ROAM_SCAN_OFFLOAD_UPDATE_CFG 4 +#define REASON_CONNECT 1 +#define REASON_CHANNEL_LIST_CHANGED 2 +#define REASON_LOOKUP_THRESH_CHANGED 3 +#define REASON_DISCONNECTED 4 +#define REASON_RSSI_DIFF_CHANGED 5 +#define REASON_CCX_INI_CFG_CHANGED 6 +#define REASON_NEIGHBOR_SCAN_REFRESH_PERIOD_CHANGED 7 +#define REASON_VALID_CHANNEL_LIST_CHANGED 8 +#define REASON_FLUSH_CHANNEL_LIST 9 +#define REASON_EMPTY_SCAN_REF_PERIOD_CHANGED 10 +#define REASON_PREAUTH_FAILED_FOR_ALL 11 +#define REASON_NO_CAND_FOUND_OR_NOT_ROAMING_NOW 12 +#define REASON_NPROBES_CHANGED 13 +#define REASON_HOME_AWAY_TIME_CHANGED 14 +eHalStatus csrRoamOffloadScan(tpAniSirGlobal pMac, tANI_U8 command, tANI_U8 reason); +eHalStatus csrNeighborRoamCandidateFoundIndHdlr(tpAniSirGlobal pMac, void* pMsg); +#endif #endif /* WLAN_FEATURE_NEIGHBOR_ROAMING */ diff --git a/drivers/staging/prima/CORE/SME/inc/csrSupport.h b/drivers/staging/prima/CORE/SME/inc/csrSupport.h index e2a6ba47766..1034298d70a 100644 --- a/drivers/staging/prima/CORE/SME/inc/csrSupport.h +++ b/drivers/staging/prima/CORE/SME/inc/csrSupport.h @@ -40,13 +40,15 @@ */ /** ------------------------------------------------------------------------- * + ------------------------------------------------------------------------- * + \file csrSupport.h - + Exports and types for the Common Scan and Roaming supporting interfaces. Copyright (C) 2006 Airgo Networks, Incorporated - + ========================================================================== */ #ifndef CSR_SUPPORT_H__ #define CSR_SUPPORT_H__ @@ -591,9 +593,7 @@ typedef __ani_attr_pre_packed struct tagCsrRSNCapabilities tANI_U16 NoPairwise:1; tANI_U16 PTKSAReplayCounter:2; tANI_U16 GTKSAReplayCounter:2; - tANI_U16 MFPRequired:1; - tANI_U16 MFPCapable:1; - tANI_U16 Reserved:8; + tANI_U16 Reserved:10; } __ani_attr_packed tCsrRSNCapabilities; typedef __ani_attr_pre_packed struct tagCsrRSNPMKIe @@ -827,7 +827,7 @@ csrIsconcurrentsessionValid(tpAniSirGlobal pMac,tANI_U32 cursessionId, eHalStatus csrUpdatep2pBeaconInterval(tpAniSirGlobal pMac); //BeaconInterval validation for MCC support -eHalStatus csrValidateMCCBeaconInterval(tpAniSirGlobal pMac, tANI_U8 channelId, +eHalStatus csrValidateMCCBeaconInterval(tpAniSirGlobal pMac, tANI_U8 channelId, tANI_U16 *beaconInterval, tANI_U32 cursessionId, tVOS_CON_MODE currBssPersona); diff --git a/drivers/staging/prima/CORE/SME/inc/smeInside.h b/drivers/staging/prima/CORE/SME/inc/smeInside.h index 86b5f81e24c..1a4ee23da27 100644 --- a/drivers/staging/prima/CORE/SME/inc/smeInside.h +++ b/drivers/staging/prima/CORE/SME/inc/smeInside.h @@ -140,7 +140,9 @@ typedef struct TdlsAddStaInfo tANI_U8 extnCapability[SIR_MAC_MAX_EXTN_CAP]; tANI_U8 supportedRatesLen; tANI_U8 supportedRates[SIR_MAC_MAX_SUPP_RATES]; + tANI_U8 htcap_present; tSirHTCap HTCap; + tANI_U8 vhtcap_present; tSirVHTCap VHTCap; tANI_U8 uapsdQueues; tANI_U8 maxSp; @@ -308,9 +310,10 @@ eHalStatus csrTdlsTeardownReq(tHalHandle hHal, tANI_U8 sessionId, #endif /* FEATURE_WLAN_TDLS */ #if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR) -eHalStatus csrFlushAndCreateBgScanRoamChannelList(tpAniSirGlobal pMac, - const tANI_U8 *pChannelList, - const tANI_U8 numChannels); +eHalStatus csrFlushBgScanRoamChannelList(tpAniSirGlobal pMac); +eHalStatus csrCreateBgScanRoamChannelList(tpAniSirGlobal pMac, + const tANI_U8 *pChannelList, + const tANI_U8 numChannels); eHalStatus csrUpdateBgScanConfigIniChannelList(tpAniSirGlobal pMac, eCsrBand eBand); eHalStatus csrInitCountryValidChannelList(tpAniSirGlobal pMac, tANI_U8 revision); void csr_SetRevision(tpAniSirGlobal pMac, tANI_U8 revision); diff --git a/drivers/staging/prima/CORE/SME/inc/smeInternal.h b/drivers/staging/prima/CORE/SME/inc/smeInternal.h index f37ce4b12b4..cfb7b5db7cf 100644 --- a/drivers/staging/prima/CORE/SME/inc/smeInternal.h +++ b/drivers/staging/prima/CORE/SME/inc/smeInternal.h @@ -155,6 +155,7 @@ typedef struct tagSmeStruct tDblLinkList smeCmdFreeList; //preallocated roam cmd list void (*pTxPerHitCallback) (void *pCallbackContext); /* callback for Tx PER hit to HDD */ void *pTxPerHitCbContext; + tVOS_CON_MODE currDeviceMode; } tSmeStruct, *tpSmeStruct; diff --git a/drivers/staging/prima/CORE/SME/inc/sme_Api.h b/drivers/staging/prima/CORE/SME/inc/sme_Api.h old mode 100644 new mode 100755 index 3233c8d78de..2114b960b84 --- a/drivers/staging/prima/CORE/SME/inc/sme_Api.h +++ b/drivers/staging/prima/CORE/SME/inc/sme_Api.h @@ -92,6 +92,9 @@ #define SME_INVALID_COUNTRY_CODE "XX" +//Macro to disable split scan +#define SME_DISABLE_SPLIT_SCAN 255 + /*-------------------------------------------------------------------------- Type declarations ------------------------------------------------------------------------*/ @@ -111,8 +114,9 @@ typedef struct _smeConfigParams tP2PConfigParam p2pConfig; #endif #if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR) - tANI_U8 isFastTransitionEnabled; - tANI_U8 RoamRssiDiff; + tANI_U8 isFastTransitionEnabled; + tANI_U8 RoamRssiDiff; + tANI_BOOLEAN isWESModeEnabled; #endif } tSmeConfigParams, *tpSmeConfigParams; @@ -221,9 +225,18 @@ eHalStatus sme_Stop(tHalHandle hHal, tANI_BOOLEAN pmcFlag); \sa --------------------------------------------------------------------------*/ -eHalStatus sme_OpenSession(tHalHandle hHal, csrRoamCompleteCallback callback, void *pContext, - tANI_U8 *pSelfMacAddr, tANI_U8 *pbSessionId); +eHalStatus sme_OpenSession(tHalHandle hHal, csrRoamCompleteCallback callback, + void *pContext, tANI_U8 *pSelfMacAddr, + tANI_U8 *pbSessionId); +/*-------------------------------------------------------------------------- + + \brief sme_SetCurrDeviceMode() - Sets the current operating device mode. + \param hHal - The handle returned by macOpen. + \param currDeviceMode - Current operating device mode. + --------------------------------------------------------------------------*/ + +void sme_SetCurrDeviceMode (tHalHandle hHal, tVOS_CON_MODE currDeviceMode); /*-------------------------------------------------------------------------- @@ -2260,6 +2273,28 @@ eHalStatus sme_UpdateRoamPrefer5GHz(tHalHandle hHal, v_BOOL_t nRoamPrefer5GHz); -------------------------------------------------------------------------*/ eHalStatus sme_setRoamIntraBand(tHalHandle hHal, const v_BOOL_t nRoamIntraBand); +/* --------------------------------------------------------------------------- + \fn sme_UpdateRoamScanNProbes + \brief function to update roam scan N probes + This function is called through dynamic setConfig callback function + to update roam scan N probes + \param hHal - HAL handle for device + \param nProbes number of probe requests to be sent out + \- return Success or failure + -------------------------------------------------------------------------*/ +eHalStatus sme_UpdateRoamScanNProbes(tHalHandle hHal, const v_U8_t nProbes); + +/* --------------------------------------------------------------------------- + \fn sme_UpdateRoamScanHomeAwayTime + \brief function to update roam scan Home away time + This function is called through dynamic setConfig callback function + to update roam scan home away time + \param hHal - HAL handle for device + \param nRoamScanAwayTime Scan home away time + \- return Success or failure + -------------------------------------------------------------------------*/ +eHalStatus sme_UpdateRoamScanHomeAwayTime(tHalHandle hHal, const v_U16_t nRoamScanHomeAwayTime); + /* --------------------------------------------------------------------------- \fn sme_getRoamIntraBand \brief get Intra band roaming @@ -2268,6 +2303,22 @@ eHalStatus sme_setRoamIntraBand(tHalHandle hHal, const v_BOOL_t nRoamIntraBand); -------------------------------------------------------------------------*/ v_BOOL_t sme_getRoamIntraBand(tHalHandle hHal); +/* --------------------------------------------------------------------------- + \fn sme_getRoamScanNProbes + \brief get N Probes + \param hHal - HAL handle for device + \- return Success or failure + -------------------------------------------------------------------------*/ +v_U8_t sme_getRoamScanNProbes(tHalHandle hHal); + +/* --------------------------------------------------------------------------- + \fn sme_getRoamScanHomeAwayTime + \brief get Roam scan home away time + \param hHal - HAL handle for device + \- return Success or failure + -------------------------------------------------------------------------*/ +v_U16_t sme_getRoamScanHomeAwayTime(tHalHandle hHal); + /* --------------------------------------------------------------------------- \fn sme_UpdateImmediateRoamRssiDiff \brief Update nImmediateRoamRssiDiff @@ -2309,6 +2360,29 @@ eHalStatus sme_UpdateRoamRssiDiff(tHalHandle hHal, v_U8_t RoamRssiDiff); eHalStatus sme_UpdateFastTransitionEnabled(tHalHandle hHal, v_BOOL_t isFastTransitionEnabled); + +/* --------------------------------------------------------------------------- + \fn sme_UpdateWESMode + \brief Update WESMode + This function is called through dynamic setConfig callback function + to configure isWESModeEnabled + \param hHal - HAL handle for device + \param isWESModeEnabled - Enable/Disable WES Mode + \- return Success or failure + -------------------------------------------------------------------------*/ +eHalStatus sme_UpdateWESMode(tHalHandle hHal, v_BOOL_t isWESModeEnabled); + +/* --------------------------------------------------------------------------- + \fn sme_SetRoamScanControl + \brief Set roam scan control + This function is called to set roam scan control + if roam scan control is set to 0, roaming scan cache is cleared + any value other than 0 is treated as invalid value + \param hHal - HAL handle for device + \return eHAL_STATUS_SUCCESS - SME update config successfully. + Other status means SME failure to update + -------------------------------------------------------------------------*/ +eHalStatus sme_SetRoamScanControl(tHalHandle hHal, v_BOOL_t roamScanControl); #endif /* (WLAN_FEATURE_VOWIFI_11R) || (FEATURE_WLAN_CCX) || (FEATURE_WLAN_LFR) */ #ifdef FEATURE_WLAN_LFR @@ -2563,6 +2637,24 @@ eHalStatus sme_getRoamScanChannelList(tHalHandle hHal, tANI_U8 *pChannelList, --------------------------------------------------------------------------*/ eHalStatus sme_GetCountryRevision(tHalHandle hHal, tANI_U8 *pRevision); +/*-------------------------------------------------------------------------- + \brief sme_getWESMode() - getWES Mode + This is a synchronous call + \param hHal - The handle returned by macOpen. + \return v_U8_t - WES Mode Enabled(1)/Disabled(0) + \sa + --------------------------------------------------------------------------*/ +v_BOOL_t sme_GetWESMode(tHalHandle hHal); + +/*-------------------------------------------------------------------------- + \brief sme_GetRoamScanControl() - get scan control + This is a synchronous call + \param hHal - The handle returned by macOpen. + \return v_BOOL_t - Enabled(1)/Disabled(0) + \sa + --------------------------------------------------------------------------*/ +v_BOOL_t sme_GetRoamScanControl(tHalHandle hHal); + /*-------------------------------------------------------------------------- \brief sme_getIsCcxFeatureEnabled() - get CCX feature enabled or not This is a synchronuous call @@ -2595,6 +2687,22 @@ tANI_BOOLEAN sme_getIsFtFeatureEnabled(tHalHandle hHal); #endif +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +/*-------------------------------------------------------------------------- + \brief sme_UpdateRoamScanOffloadEnabled() - enable/disable roam scan offload feaure + It is used at in the REG_DYNAMIC_VARIABLE macro definition of + gRoamScanOffloadEnabled. + This is a synchronous call + \param hHal - The handle returned by macOpen. + \return eHAL_STATUS_SUCCESS - SME update config successfully. + Other status means SME is failed to update. + \sa + --------------------------------------------------------------------------*/ + +eHalStatus sme_UpdateRoamScanOffloadEnabled(tHalHandle hHal, v_BOOL_t nRoamScanOffloadEnabled); +#endif + + /* --------------------------------------------------------------------------- \fn sme_IsFeatureSupportedByFW \brief Check if an feature is enabled by FW @@ -2647,13 +2755,6 @@ VOS_STATUS sme_AddTdlsPeerSta(tHalHandle hHal, tANI_U8 sessionId, tSirMacAddr pe \- return VOS_STATUS_SUCCES -------------------------------------------------------------------------*/ VOS_STATUS sme_DeleteTdlsPeerSta(tHalHandle hHal, tANI_U8 sessionId, tSirMacAddr peerMac); -/* --------------------------------------------------------------------------- - \fn sme_IsPmcBmps - \brief API to Check if PMC state is BMPS. - - \- return v_BOOL_t - -------------------------------------------------------------------------*/ -v_BOOL_t sme_IsPmcBmps(tHalHandle hHal); /* --------------------------------------------------------------------------- \fn sme_SetTdlsPowerSaveProhibited \API to set/reset the isTdlsPowerSaveProhibited. @@ -2662,6 +2763,14 @@ v_BOOL_t sme_IsPmcBmps(tHalHandle hHal); -------------------------------------------------------------------------*/ void sme_SetTdlsPowerSaveProhibited(tHalHandle hHal, v_BOOL_t val); #endif +/* --------------------------------------------------------------------------- + \fn sme_IsPmcBmps + \brief API to Check if PMC state is BMPS. + + \- return v_BOOL_t + -------------------------------------------------------------------------*/ +v_BOOL_t sme_IsPmcBmps(tHalHandle hHal); + #ifdef FEATURE_WLAN_TDLS_INTERNAL typedef struct smeTdlsDisResult { @@ -2674,7 +2783,61 @@ v_U8_t sme_GetTdlsDiscoveryResult(tHalHandle hHal, tSmeTdlsDisResult *disResult, v_U8_t listType); VOS_STATUS sme_StartTdlsLinkSetupReq(tHalHandle hHal, tANI_U8 sessionId, tSirMacAddr peerMac); VOS_STATUS sme_StartTdlsLinkTeardownReq(tHalHandle hHal, tANI_U8 sessionId, tSirMacAddr peerMac); - #endif /* FEATURE_WLAN_TDLS */ +eHalStatus sme_UpdateDfsSetting(tHalHandle hHal, tANI_U8 fUpdateEnableDFSChnlScan); + +/* + * SME API to enable/disable WLAN driver initiated SSR + */ +void sme_UpdateEnableSSR(tHalHandle hHal, tANI_BOOLEAN enableSSR); + +/* --------------------------------------------------------------------------- + + \fn sme_SetPhyMode + + \brief Changes the PhyMode. + + \param hHal - The handle returned by macOpen. + \param phyMode new phyMode which is to set + + \return eHalStatus SUCCESS. + + -------------------------------------------------------------------------------*/ +eHalStatus sme_SetPhyMode(tHalHandle hHal, eCsrPhyMode phyMode); + +/* --------------------------------------------------------------------------- + + \fn sme_GetPhyMode + + \brief gets current PhyMode. + + \param hHal - The handle returned by macOpen. + + \return eHalStatus PhyMode + + -------------------------------------------------------------------------------*/ +eCsrPhyMode sme_GetPhyMode(tHalHandle hHal); + +/*-------------------------------------------------------------------------- + \brief sme_isSta_p2p_clientConnected() - a wrapper function to check if there + is any connected session . + This is a synchronous call + \param hHal - The handle returned by macOpen + \return VOS_STATUS - SME passed the request to CSR successfully. + Other status means SME is failed to send the request. + \sa + --------------------------------------------------------------------------*/ +VOS_STATUS sme_isSta_p2p_clientConnected(tHalHandle hHal); + +/*-------------------------------------------------------------------------- + \brief sme_enable_disable_split_scan() - a wrapper function to set the split + scan parameter. + This is a synchronous call + \param hHal - The handle returned by macOpen + \return None. + \sa + --------------------------------------------------------------------------*/ +void sme_enable_disable_split_scan (tHalHandle hHal, tANI_U8 nNumStaChan, + tANI_U8 nNumP2PChan); #endif //#if !defined( __SME_API_H ) diff --git a/drivers/staging/prima/CORE/SME/inc/sme_FTApi.h b/drivers/staging/prima/CORE/SME/inc/sme_FTApi.h index 115f3f9f0b7..98a0e237b9b 100644 --- a/drivers/staging/prima/CORE/SME/inc/sme_FTApi.h +++ b/drivers/staging/prima/CORE/SME/inc/sme_FTApi.h @@ -39,6 +39,8 @@ * PERFORMANCE OF THIS SOFTWARE. */ + + #if !defined( __SME_FTAPI_H ) #define __SME_FTAPI_H @@ -82,9 +84,12 @@ typedef struct sFTSMEContext // Saved pFTPreAuthRsp tpSirFTPreAuthRsp psavedFTPreAuthRsp; + v_BOOL_t setFTPreAuthState; + v_BOOL_t setFTPTKState; // Time to trigger reassoc once pre-auth is successful tPalTimerHandle preAuthReassocIntvlTimer; + tCsrRoamSetKey *pCsrFTKeyInfo; } tftSMEContext, *tpftSMEContext; @@ -99,6 +104,10 @@ void csrFTPreAuthRspProcessor( tHalHandle hHal, tpSirFTPreAuthRsp pFTPreAuthRsp void sme_GetFTPreAuthResponse( tHalHandle hHal, tANI_U8 *ft_ies, tANI_U32 ft_ies_ip_len, tANI_U16 *ft_ies_length ); void sme_GetRICIEs( tHalHandle hHal, tANI_U8 *ric_ies, tANI_U32 ric_ies_ip_len, tANI_U32 *ric_ies_length ); void sme_PreauthReassocIntvlTimerCallback(void *context); +void sme_SetFTPreAuthState(tHalHandle hHal, v_BOOL_t state); +v_BOOL_t sme_GetFTPreAuthState(tHalHandle hHal); +v_BOOL_t sme_GetFTPTKState(tHalHandle hHal); +void sme_SetFTPTKState(tHalHandle hHal, v_BOOL_t state); #endif //#if !defined( __SME_FTAPI_H ) diff --git a/drivers/staging/prima/CORE/SME/src/QoS/sme_Qos.c b/drivers/staging/prima/CORE/SME/src/QoS/sme_Qos.c index bff6a5e559d..21bb864f43e 100644 --- a/drivers/staging/prima/CORE/SME/src/QoS/sme_Qos.c +++ b/drivers/staging/prima/CORE/SME/src/QoS/sme_Qos.c @@ -2766,7 +2766,7 @@ sme_QosStatusType sme_QosSetup(tpAniSirGlobal pMac, VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: %d: Session %d has an Invalid BSS Descriptor", __func__, __LINE__, - sessionId, ac); + sessionId); return status; } hstatus = csrGetParsedBssDescriptionIEs(pMac, @@ -2777,7 +2777,7 @@ sme_QosStatusType sme_QosSetup(tpAniSirGlobal pMac, VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: %d: On session %d unable to parse BSS IEs", __func__, __LINE__, - sessionId, ac); + sessionId); return status; } @@ -3598,7 +3598,7 @@ eHalStatus sme_QosProcessAggrQosRsp(tpAniSirGlobal pMac, void *pMsgBuf) addtsRsp.rsp.tspec = pAggrRsp->aggrInfo.aggrRsp[i].tspec; VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, - FL("%s: Processing Addts rsp from LIM AC=%d, flow=%d"), i, j); + FL("Processing Addts rsp from LIM AC=%d, flow=%d"), i, j); /* post ADD TS response for each */ if (sme_QosProcessAddTsRsp(pMac, &addtsRsp) != eHAL_STATUS_SUCCESS) { @@ -3807,6 +3807,7 @@ eHalStatus sme_QosAddTsReq(tpAniSirGlobal pMac, VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: %d: BSS descriptor is NULL so we don't send request to PE", __func__, __LINE__); + vos_mem_free(pMsg); return eHAL_STATUS_FAILURE; } vos_mem_copy( &pMsg->bssId[ 0 ], @@ -4412,15 +4413,19 @@ eHalStatus sme_QosProcessReassocSuccessEv(tpAniSirGlobal pMac, v_U8_t sessionId, #ifdef WLAN_FEATURE_VOWIFI_11R if (pSession->ftHandoffInProgress) { - if (csrRoamIs11rAssoc(pMac)) { - if (pCsrRoamSession->connectedInfo.nRICRspLength) { + if (csrRoamIs11rAssoc(pMac)) + { + if (pCsrRoamSession && pCsrRoamSession->connectedInfo.nRICRspLength) + { status = sme_QosProcessFTReassocRspEv(pMac, sessionId, pEvent_info); } } #ifdef FEATURE_WLAN_CCX // If CCX association check for TSPEC IEs in the reassoc rsp frame - if (csrRoamIsCCXAssoc(pMac)) { - if (pCsrRoamSession->connectedInfo.nTspecIeLength) { + if (csrRoamIsCCXAssoc(pMac)) + { + if (pCsrRoamSession && pCsrRoamSession->connectedInfo.nTspecIeLength) + { status = sme_QosCCXProcessReassocTspecRsp(pMac, sessionId, pEvent_info); } } diff --git a/drivers/staging/prima/CORE/SME/src/btc/btcApi.c b/drivers/staging/prima/CORE/SME/src/btc/btcApi.c index 4dce802c381..453508826c2 100644 --- a/drivers/staging/prima/CORE/SME/src/btc/btcApi.c +++ b/drivers/staging/prima/CORE/SME/src/btc/btcApi.c @@ -820,14 +820,24 @@ static VOS_STATUS btcDeferAclCreate( tpAniSirGlobal pMac, tpSmeBtEvent pEvent ) else { //There is history on this BD address - VOS_ASSERT(pAclEventHist->bNextEventIdx > 0); + if ((pAclEventHist->bNextEventIdx <= 0) || + (pAclEventHist->bNextEventIdx > BT_MAX_NUM_EVENT_ACL_DEFERRED)) + { + VOS_ASSERT(0); + status = VOS_STATUS_E_FAILURE; + break; + } + pAclEvent = &pAclEventHist->btAclConnection[pAclEventHist->bNextEventIdx - 1]; if(BT_EVENT_CREATE_ACL_CONNECTION == pAclEventHist->btEventType[pAclEventHist->bNextEventIdx - 1]) { //The last cached event is creation, replace it with the new one - vos_mem_copy(pAclEvent, - &pEvent->uEventParam.btAclConnection, - sizeof(tSmeBtAclConnectionParam)); + if (pAclEvent) + { + vos_mem_copy(pAclEvent, + &pEvent->uEventParam.btAclConnection, + sizeof(tSmeBtAclConnectionParam)); + } //done break; } @@ -978,15 +988,23 @@ static VOS_STATUS btcDeferSyncCreate( tpAniSirGlobal pMac, tpSmeBtEvent pEvent ) else { //There is history on this BD address - VOS_ASSERT(pSyncEventHist->bNextEventIdx > 0); + if ((pSyncEventHist->bNextEventIdx <= 0) || + (pSyncEventHist->bNextEventIdx > BT_MAX_NUM_EVENT_SCO_DEFERRED)) + { + VOS_ASSERT(0); + return VOS_STATUS_E_FAILURE; + } pSyncEvent = &pSyncEventHist->btSyncConnection[pSyncEventHist->bNextEventIdx - 1]; if(BT_EVENT_CREATE_SYNC_CONNECTION == pSyncEventHist->btEventType[pSyncEventHist->bNextEventIdx - 1]) { //The last cached event is creation, replace it with the new one - vos_mem_copy(pSyncEvent, - &pEvent->uEventParam.btSyncConnection, - sizeof(tSmeBtSyncConnectionParam)); + if(pSyncEvent) + { + vos_mem_copy(pSyncEvent, + &pEvent->uEventParam.btSyncConnection, + sizeof(tSmeBtSyncConnectionParam)); + } //done break; } @@ -1924,6 +1942,28 @@ eHalStatus btcHandleCoexInd(tHalHandle hHal, void* pMsg) smsLog(pMac, LOGW, "Coex indication in %s(), type - SIR_COEX_IND_TYPE_SCAN_NOT_COMPROMISED", __func__); } + else if (pSmeCoexInd->coexIndType == SIR_COEX_IND_TYPE_DISABLE_AGGREGATION_IN_2p4) + { + if (pMac->roam.configParam.disableAggWithBtc) + { + ccmCfgSetInt(pMac, WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC, 1, + NULL, eANI_BOOLEAN_FALSE); + smsLog(pMac, LOGW, + "Coex indication in %s(), type - SIR_COEX_IND_TYPE_DISABLE_AGGREGATION_IN_2p4", + __func__); + } + } + else if (pSmeCoexInd->coexIndType == SIR_COEX_IND_TYPE_ENABLE_AGGREGATION_IN_2p4) + { + if (pMac->roam.configParam.disableAggWithBtc) + { + ccmCfgSetInt(pMac, WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC, 0, + NULL, eANI_BOOLEAN_FALSE); + smsLog(pMac, LOGW, + "Coex indication in %s(), type - SIR_COEX_IND_TYPE_ENABLE_AGGREGATION_IN_2p4", + __func__); + } + } // unknown indication type else { diff --git a/drivers/staging/prima/CORE/SME/src/ccm/ccmApi.c b/drivers/staging/prima/CORE/SME/src/ccm/ccmApi.c index 92532182ddf..fbd891a109c 100644 --- a/drivers/staging/prima/CORE/SME/src/ccm/ccmApi.c +++ b/drivers/staging/prima/CORE/SME/src/ccm/ccmApi.c @@ -542,8 +542,8 @@ void ccmCfgCnfMsgHandler(tHalHandle hHal, void *m) { freeCfgReq(hHdd, old) ; } + pMac->ccm.comp[cfgId] = req ; } - pMac->ccm.comp[cfgId] = req ; } else { @@ -839,303 +839,3 @@ eHalStatus ccmCfgUpdate(tHalHandle hHal, tCcmCfgSetCallback callback) return status ; } -#if 0 -/////////////////////////////////////////////////////////////////// -#include -#include -extern struct net_device * hdd_dev[]; - -typedef struct pal_netdev_priv_s -{ - // pointer to the PCI device structure for this device - struct pci_dev *pci_dev; - - // TAURUS has three BAR registers - - // BAR0 is a fixed window for the PIF registers - volatile void *win0_addr; - tANI_U32 win0_size; - - // BAR1 is a movable window for all other registers - volatile void *win1_addr; - tANI_U32 win1_size; - tANI_U32 win1_current; - - // BAR2 is a movable window for all other memory - volatile void *win2_addr; - tANI_U32 win2_size; - tANI_U32 win2_current; - - -} pal_netdev_priv_t; - -typedef struct hdd_stats_s { - /* Stats on the MAC SW messages sent to applications */ - ulong stats_mac_rx_mbx_tot_cnt; - ulong stats_mac_rx_mbx_success_cnt; - ulong stats_mac_rx_mbx_drop_cnt; - - /* Stats on messages sent to the MAC SW messages from applications */ - ulong stats_mac_tx_mbx_tot_cnt; - ulong stats_mac_tx_mbx_success_cnt; - ulong stats_mac_tx_mbx_drop_cnt; -} hdd_stats_t; - -/* HDD Driver Private Data structure */ -typedef struct hdd_netdev_priv_s -{ - tANI_U32 magic_head; - - // chipset-specific private data - pal_netdev_priv_t ANI_CHIPSET; - - tHalHandle halHandle; - -#ifdef ANI_BUS_TYPE_PCI - struct pci_dev *pci_dev; - struct pci_device_id * pPciDevId; -#endif // ANI_BUS_TYPE_PCI - - // Queued EAPOL frame destination. - tANI_U32 eapol_pid; - - unsigned int num_xmit; - - /* - * Various frequently used variables that pertain to this - * instance of the driver - */ - tANI_U32 rx_buf_sz; /* Based on MTU+extra headroom needed.*/ - tANI_U32 td_enqueue_nested; - - /* - * Flag set by MAC SW to indicate a TD ring is desired - */ - int td_flush; - - int selectiveFlush; - - spinlock_t lock; - - /* Stats */ - struct net_device_stats stats; - int curr_acc_cat; - tANI_U16 lport; /* switch logical port */ - - /* management and control */ - tANI_U32 status; - tANI_U32 msg_enable; - tANI_U32 radio_id; /* Unit # of this device */ - - int ap_flag; /* - * indicates if the Radio is in AP - * or BP mode. - */ - - /* NAPI Polling suport */ - struct timer_list oom_timer; /* Out of memory timer. */ - - struct timer_list reset_req_timer;/* - * Timer started when a Reset - * request is sent to WSM. Cleared - * when a subsequent Radio Disable - * Request is received. - */ - - struct tasklet_struct *rx_tasklet; - struct tasklet_struct *tx_tasklet; - - tANI_U32 learn_mode_frame_cnt; /* - * Data Frames forwarded to MAC SW - * when Polaris is in learn mode - */ - - tANI_U32 mgmt_ctl_frames; /* MGMT/CTL Frames forwarded to MAC SW */ - - tANI_U32 nir; /* total number of times the ISR has - * been invoked.*/ - tANI_U32 stats_dummy_pkt_requeue_cnt; - tANI_U32 stats_rx_td_dummy_pkt_cnt;/* TD Dummy pkts that were after HIF loopback */ - tANI_U32 stats_rx_tm_dummy_pkt_cnt;/* TM Dummy pkts that were after HIF loopback */ - tANI_U32 stats_td_dummy_pkt_cnt; /* Dummy pkts that were succesfully - * put on the TD ring and that - * were picked up by the HIF - */ - - tANI_U32 stats_mac_dummy_pkt_drop_cnt;/* Number of dummy pkts dropped by the HDD - * due to any reason - */ - tANI_U32 stats_wns_l2update_cnt; - tANI_U32 stats_app_hif_wr_pkt_cnt; - hdd_stats_t hdd_stats; - - tANI_U32 stats_reset_req_timer_cnt; /* - * Number of times the - * Reset Req Timer expired - */ - -#ifdef TCP_PROFILE - unsigned int pv_current_ip_proto; - unsigned int pv_current_ip_byte; - unsigned int pv_current_ack_seq; - unsigned int pv_current_seq; - unsigned int pv_rtt; - unsigned int pv_sent_seq; - unsigned int pv_p_ts; - unsigned int pv_tfpl_ts; -#endif - tANI_U32 stats_mac_reset_cnt; /* MAC SW Reset Requests */ - tANI_U32 stats_mac_reset_eof_sof; - tANI_U32 stats_mac_reset_bmu; - tANI_U32 stats_mac_reset_pdu_low; - tANI_U32 stats_mac_reset_user; - tANI_U32 stats_mac_reset_wd_timeout; - tANI_U32 stats_mac_reset_unspecified; - - tANI_U32 stats_wd_timeout_cnt; - tANI_U32 stats_radio_enable_cnt; - tANI_U32 stats_radio_disable_cnt; - -#ifdef PLM_EXTRA_STATS - tANI_U32 stats_tx_xmit_refilled; /* Pkts xmit-filled */ - tANI_U32 stats_tx_queue_stop; - tANI_U32 stats_tx_queue_start; - - tANI_U32 stats_alloc_fail; - tANI_U32 stats_poll_starts; - tANI_U32 stats_poll_pkts; - tANI_U32 stats_poll_exit_done; - tANI_U32 stats_poll_exit_not_done; - tANI_U32 stats_poll_exit_oom; - tANI_U32 stats_poll_exit_done_rx_pending; - tANI_U32 stats_poll_zero_rx; - -#ifdef CONFIG_PROC_FS -#ifdef ANI_USE_TASKLET - struct proc_dir_entry *proc_driver_dir; // for /proc/net/drivers -#endif - struct proc_dir_entry *proc_ent_dir; // for the directory itself - - struct proc_dir_entry *proc_ent_stats; - struct proc_dir_entry *proc_ent_np_dump; - struct proc_dir_entry *proc_ent_ring; - char proc_fname_stats[32]; - char proc_fname_np_dump[32]; - char proc_fname_ring[32]; - - /* Setting Debug levels */ - struct proc_dir_entry * proc_ent_dbg; - char proc_fname_dbg[32]; - - /* For bypass flags */ - struct proc_dir_entry * proc_ent_bypass; - char proc_fname_bypass[32]; - - int sir_dump_cmd; // Dump SIR command - int sir_dump_arg1; // Dump SIR argument 1 - int sir_dump_arg2; // Dump SIR argument 2 - int sir_dump_arg3; // Dump SIR argument 3 - int sir_dump_arg4; // Dump SIR argument 4 - struct proc_dir_entry * proc_ent_sir_dump; - char proc_fname_sir_dump[32]; - - eHalStatus status ; - struct proc_dir_entry * proc_ent_eeprom_info; - char proc_fname_eeprom_info[32]; - -#endif /* ifdef CONFIG_PROC_FS */ - - tANI_U32 rx_small_skb_failure; - - unsigned long open_time; /* jiffies for last open */ -#endif /* PLM_EXTRA_STATS */ - - int mac_down; - tANI_U32 rx_mac_msg_cnt; - tANI_U32 tx_mac_msg_cnt; - - int mbx_sent; - - tANI_U32 bypass; // Used to various types of bypasses - // in the driver - - /* - * this table is initialized once for all by poldrv and so is not in - * mac_param struct - */ - t_mac_block_table * mac_block_table; - struct sk_buff_head mac_list; - tANI_U32 magic_tail; -} hdd_netdev_priv_t; - -static void ccm_callback(tHalHandle hHal, tANI_S32 cfgId) -{ - tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); - smsLog(pMac, LOGW, FL("cfgId = %d"), cfgId); -} - -static void ccm_callback2(tHalHandle hHal, tANI_S32 result) -{ - tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); - smsLog(pMac, LOGW, FL("result = %d"), result); -} - -void ccm_test(void) -{ - tHalHandle hHal ; - tpAniSirGlobal pMac; - eHalStatus status ; - struct net_device *dev; - hdd_netdev_priv_t *np; - char str[80] = {1} ; - - dev = hdd_dev[0]; - np = (hdd_netdev_priv_t *)dev->priv; - hHal = np->halHandle ; - pMac = PMAC_STRUCT( hHal ); - - smsLog(pMac, LOGW, "ccmStart()"); - ccmStart(hHal) ; - - status = ccmCfgUpdate(hHal, ccm_callback2) ; - smsLog(pMac, LOGW, "ccmCfgUpdate(): status=%d", status); - - status = ccmCfgSetInt(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD, 100, ccm_callback, 1) ; - smsLog(pMac, LOGW, "ccmCfgSetInt(WNI_CFG_FRAGMENTATION_THRESHOLD = %d): status=%d", - WNI_CFG_FRAGMENTATION_THRESHOLD, status); - - status = ccmCfgSetInt(hHal, WNI_CFG_RTS_THRESHOLD, 100, ccm_callback, 1) ; - smsLog(pMac, LOGW, "ccmCfgSetInt(WNI_CFG_RTS_THRESHOLD = %d): status=%d", - WNI_CFG_RTS_THRESHOLD, status); - - /* this cfgid causes reload */ - status = ccmCfgSetInt(hHal, WNI_CFG_MIMO_ENABLED, 1, ccm_callback, 1) ; - smsLog(pMac, LOGW, "ccmCfgSetInt(WNI_CFG_MIMO_ENABLED = %d): status=%d", - WNI_CFG_MIMO_ENABLED, status); - - status = ccmCfgSetInt(hHal, WNI_CFG_SHORT_RETRY_LIMIT, 100, ccm_callback, 1) ; - smsLog(pMac, LOGW, "ccmCfgSetInt(WNI_CFG_SHORT_RETRY_LIMIT = %d): status=%d", - WNI_CFG_SHORT_RETRY_LIMIT, status); - - status = ccmCfgSetInt(hHal, WNI_CFG_LONG_RETRY_LIMIT, 100, ccm_callback, 1) ; - smsLog(pMac, LOGW, "ccmCfgSetInt(WNI_CFG_LONG_RETRY_LIMIT = %d): status=%d", - WNI_CFG_LONG_RETRY_LIMIT, status); - - /* this cfgid causes restart */ - status = ccmCfgSetStr(hHal, WNI_CFG_EDCA_WME_ACVI, str, sizeof(str), ccm_callback, 1) ; - smsLog(pMac, LOGW, "ccmCfgSetStr(WNI_CFG_EDCA_WME_ACVI = %d): status=%d", - WNI_CFG_EDCA_WME_ACVI, status); - - mdelay(100); - - smsLog(pMac, LOGW, "ccmStop()"); - ccmStop(hHal); - status = ccmCfgUpdate(hHal, ccm_callback2) ; - smsLog(pMac, LOGW, "ccmCfgUpdate(): status=%d", status); - - smsLog(pMac, LOGW, "ccmStart()"); - ccmStart(hHal) ; - status = ccmCfgUpdate(hHal, ccm_callback2) ; - smsLog(pMac, LOGW, "ccmCfgUpdate(): status=%d", status); -} -#endif diff --git a/drivers/staging/prima/CORE/SME/src/csr/csrApiRoam.c b/drivers/staging/prima/CORE/SME/src/csr/csrApiRoam.c index 45b72b9f4ae..5f5653b9700 100644 --- a/drivers/staging/prima/CORE/SME/src/csr/csrApiRoam.c +++ b/drivers/staging/prima/CORE/SME/src/csr/csrApiRoam.c @@ -150,9 +150,6 @@ int diagAuthTypeFromCSRType(eCsrAuthType authType) n = AUTH_WPA2_EAP; break; case eCSR_AUTH_TYPE_RSN_PSK: -#ifdef WLAN_FEATURE_11W - case eCSR_AUTH_TYPE_RSN_PSK_SHA256: -#endif n = AUTH_WPA2_PSK; break; #ifdef FEATURE_WLAN_WAPI @@ -945,13 +942,15 @@ static void initConfigParam(tpAniSirGlobal pMac) pMac->roam.configParam.nPassiveMinChnTime = CSR_PASSIVE_MIN_CHANNEL_TIME; pMac->roam.configParam.nActiveMaxChnTimeBtc = CSR_ACTIVE_MAX_CHANNEL_TIME_BTC; pMac->roam.configParam.nActiveMinChnTimeBtc = CSR_ACTIVE_MIN_CHANNEL_TIME_BTC; + pMac->roam.configParam.disableAggWithBtc = eANI_BOOLEAN_TRUE; #ifdef WLAN_AP_STA_CONCURRENCY pMac->roam.configParam.nActiveMaxChnTimeConc = CSR_ACTIVE_MAX_CHANNEL_TIME_CONC; pMac->roam.configParam.nActiveMinChnTimeConc = CSR_ACTIVE_MIN_CHANNEL_TIME_CONC; pMac->roam.configParam.nPassiveMaxChnTimeConc = CSR_PASSIVE_MAX_CHANNEL_TIME_CONC; pMac->roam.configParam.nPassiveMinChnTimeConc = CSR_PASSIVE_MIN_CHANNEL_TIME_CONC; pMac->roam.configParam.nRestTimeConc = CSR_REST_TIME_CONC; - pMac->roam.configParam.nNumChanCombinedConc = CSR_NUM_CHAN_COMBINED_CONC; + pMac->roam.configParam.nNumStaChanCombinedConc = CSR_NUM_STA_CHAN_COMBINED_CONC; + pMac->roam.configParam.nNumP2PChanCombinedConc = CSR_NUM_P2P_CHAN_COMBINED_CONC; #endif pMac->roam.configParam.IsIdleScanEnabled = TRUE; //enable the idle scan by default pMac->roam.configParam.nTxPowerCap = CSR_MAX_TX_POWER; @@ -1030,12 +1029,9 @@ void csr_SetRevision(tpAniSirGlobal pMac, tANI_U8 revision) } /* - This function flushes the roam scan cache and creates fresh cache - based on the input channel list + This function flushes the roam scan cache */ -eHalStatus csrFlushAndCreateBgScanRoamChannelList(tpAniSirGlobal pMac, - const tANI_U8 *pChannelList, - const tANI_U8 numChannels) +eHalStatus csrFlushBgScanRoamChannelList(tpAniSirGlobal pMac) { eHalStatus status = eHAL_STATUS_SUCCESS; tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo; @@ -1045,7 +1041,24 @@ eHalStatus csrFlushAndCreateBgScanRoamChannelList(tpAniSirGlobal pMac, { vos_mem_free(pNeighborRoamInfo->cfgParams.channelInfo.ChannelList); pNeighborRoamInfo->cfgParams.channelInfo.ChannelList = NULL; + pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels = 0; } + return status; +} + + + +/* + This function flushes the roam scan cache and creates fresh cache + based on the input channel list +*/ +eHalStatus csrCreateBgScanRoamChannelList(tpAniSirGlobal pMac, + const tANI_U8 *pChannelList, + const tANI_U8 numChannels) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo; + pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels = numChannels; pNeighborRoamInfo->cfgParams.channelInfo.ChannelList = @@ -1103,7 +1116,8 @@ eHalStatus csrUpdateBgScanConfigIniChannelList(tpAniSirGlobal pMac, ChannelList[outNumChannels++] = inPtr[i]; } } - csrFlushAndCreateBgScanRoamChannelList(pMac, ChannelList, outNumChannels); + csrFlushBgScanRoamChannelList(pMac); + csrCreateBgScanRoamChannelList(pMac, ChannelList, outNumChannels); } else if (eCSR_BAND_5G == eBand) { @@ -1117,7 +1131,8 @@ eHalStatus csrUpdateBgScanConfigIniChannelList(tpAniSirGlobal pMac, ChannelList[outNumChannels++] = inPtr[i]; } } - csrFlushAndCreateBgScanRoamChannelList(pMac, ChannelList, outNumChannels); + csrFlushBgScanRoamChannelList(pMac); + csrCreateBgScanRoamChannelList(pMac, ChannelList, outNumChannels); } else if (eCSR_BAND_ALL == eBand) { @@ -1129,7 +1144,8 @@ eHalStatus csrUpdateBgScanConfigIniChannelList(tpAniSirGlobal pMac, ChannelList[outNumChannels++] = inPtr[i]; } } - csrFlushAndCreateBgScanRoamChannelList(pMac, ChannelList, outNumChannels); + csrFlushBgScanRoamChannelList(pMac); + csrCreateBgScanRoamChannelList(pMac, ChannelList, outNumChannels); } else { @@ -1149,7 +1165,7 @@ eHalStatus csrInitCountryValidChannelList(tpAniSirGlobal pMac, { eHalStatus status = eHAL_STATUS_SUCCESS; tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo; - tANI_U8 *pOutChannelList = pNeighborRoamInfo->cfgParams.countryChannelInfo.countryValidChannelList.ChannelList; + tANI_U8 **pOutChannelList = &pNeighborRoamInfo->cfgParams.countryChannelInfo.countryValidChannelList.ChannelList; tANI_U8 *pNumChannels = &pNeighborRoamInfo->cfgParams.countryChannelInfo.countryValidChannelList.numOfChannels; const tANI_U8 *pChannelList = NULL; @@ -1171,24 +1187,19 @@ eHalStatus csrInitCountryValidChannelList(tpAniSirGlobal pMac, else return eHAL_STATUS_INVALID_PARAMETER; - /* Free up the memory first */ - if (NULL != pOutChannelList) - { - vos_mem_free(pOutChannelList); - pOutChannelList = NULL; - } + /* Free any existing channel list */ + vos_mem_free(*pOutChannelList); - pOutChannelList = vos_mem_malloc(*pNumChannels); + *pOutChannelList = vos_mem_malloc(*pNumChannels); - if (NULL == pOutChannelList) + if (NULL == *pOutChannelList) { smsLog(pMac, LOGE, FL("Memory Allocation for CFG Channel List failed")); *pNumChannels = 0; return eHAL_STATUS_RESOURCES; } - /* Update the roam global structure */ - palCopyMemory(pMac->hHdd, pOutChannelList, pChannelList, *pNumChannels); + palCopyMemory(pMac->hHdd, *pOutChannelList, pChannelList, *pNumChannels); return status; } @@ -1389,6 +1400,7 @@ eHalStatus csrChangeDefaultConfigParam(tpAniSirGlobal pMac, tCsrConfigParam *pPa pMac->roam.configParam.bandCapability = pParam->bandCapability; pMac->roam.configParam.cbChoice = pParam->cbChoice; pMac->roam.configParam.bgScanInterval = pParam->bgScanInterval; + pMac->roam.configParam.disableAggWithBtc = pParam->disableAggWithBtc; //if HDD passed down non zero values then only update, //otherwise keep using the defaults if (pParam->nActiveMaxChnTime) @@ -1436,9 +1448,13 @@ eHalStatus csrChangeDefaultConfigParam(tpAniSirGlobal pMac, tCsrConfigParam *pPa { pMac->roam.configParam.nRestTimeConc = pParam->nRestTimeConc; } - if (pParam->nNumChanCombinedConc) + if (pParam->nNumStaChanCombinedConc) + { + pMac->roam.configParam.nNumStaChanCombinedConc = pParam->nNumStaChanCombinedConc; + } + if (pParam->nNumP2PChanCombinedConc) { - pMac->roam.configParam.nNumChanCombinedConc = pParam->nNumChanCombinedConc; + pMac->roam.configParam.nNumP2PChanCombinedConc = pParam->nNumP2PChanCombinedConc; } #endif //if upper layer wants to disable idle scan altogether set it to 0 @@ -1515,7 +1531,7 @@ eHalStatus csrChangeDefaultConfigParam(tpAniSirGlobal pMac, tCsrConfigParam *pPa } -#ifdef WLAN_FEATURE_VOWIFI_11R +#ifdef WLAN_FEATURE_VOWIFI_11R palCopyMemory( pMac->hHdd, &pMac->roam.configParam.csr11rConfig, &pParam->csr11rConfig, sizeof(tCsr11rConfigParams) ); smsLog( pMac, LOG1, "IsFTResourceReqSupp = %d", pMac->roam.configParam.csr11rConfig.IsFTResourceReqSupported); #endif @@ -1526,13 +1542,19 @@ eHalStatus csrChangeDefaultConfigParam(tpAniSirGlobal pMac, tCsrConfigParam *pPa smsLog( pMac, LOG1, "nImmediateRoamRssiDiff = %d", pMac->roam.configParam.nImmediateRoamRssiDiff ); pMac->roam.configParam.nRoamPrefer5GHz = pParam->nRoamPrefer5GHz; + pMac->roam.configParam.isWESModeEnabled = pParam->isWESModeEnabled; pMac->roam.configParam.nRoamIntraBand = pParam->nRoamIntraBand; + pMac->roam.configParam.nProbes = pParam->nProbes; + pMac->roam.configParam.nRoamScanHomeAwayTime = pParam->nRoamScanHomeAwayTime; +#endif +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + pMac->roam.configParam.isRoamOffloadScanEnabled = pParam->isRoamOffloadScanEnabled; #endif -#ifdef FEATURE_WLAN_LFR +#ifdef FEATURE_WLAN_LFR pMac->roam.configParam.isFastRoamIniFeatureEnabled = pParam->isFastRoamIniFeatureEnabled; #endif -#ifdef FEATURE_WLAN_CCX +#ifdef FEATURE_WLAN_CCX pMac->roam.configParam.isCcxIniFeatureEnabled = pParam->isCcxIniFeatureEnabled; #endif #ifdef WLAN_FEATURE_NEIGHBOR_ROAMING @@ -1577,7 +1599,6 @@ eHalStatus csrChangeDefaultConfigParam(tpAniSirGlobal pMac, tCsrConfigParam *pPa pMac->roam.configParam.txBFEnable= pParam->enableTxBF; pMac->roam.configParam.txBFCsnValue = pParam->txBFCsnValue; #endif - pMac->scan.fIgnore_chan165 = pParam->fIgnore_chan165; pMac->roam.configParam.txLdpcEnable = pParam->enableTxLdpc; } @@ -1613,13 +1634,17 @@ eHalStatus csrGetConfigParam(tpAniSirGlobal pMac, tCsrConfigParam *pParam) pParam->nActiveMinChnTime = pMac->roam.configParam.nActiveMinChnTime; pParam->nPassiveMaxChnTime = pMac->roam.configParam.nPassiveMaxChnTime; pParam->nPassiveMinChnTime = pMac->roam.configParam.nPassiveMinChnTime; + pParam->nActiveMaxChnTimeBtc = pMac->roam.configParam.nActiveMaxChnTimeBtc; + pParam->nActiveMinChnTimeBtc = pMac->roam.configParam.nActiveMinChnTimeBtc; + pParam->disableAggWithBtc = pMac->roam.configParam.disableAggWithBtc; #ifdef WLAN_AP_STA_CONCURRENCY pParam->nActiveMaxChnTimeConc = pMac->roam.configParam.nActiveMaxChnTimeConc; pParam->nActiveMinChnTimeConc = pMac->roam.configParam.nActiveMinChnTimeConc; pParam->nPassiveMaxChnTimeConc = pMac->roam.configParam.nPassiveMaxChnTimeConc; pParam->nPassiveMinChnTimeConc = pMac->roam.configParam.nPassiveMinChnTimeConc; pParam->nRestTimeConc = pMac->roam.configParam.nRestTimeConc; - pParam->nNumChanCombinedConc = pMac->roam.configParam.nNumChanCombinedConc; + pParam->nNumStaChanCombinedConc = pMac->roam.configParam.nNumStaChanCombinedConc; + pParam->nNumP2PChanCombinedConc = pMac->roam.configParam.nNumP2PChanCombinedConc; #endif //Change the unit from microsecond to second pParam->impsSleepTime = pMac->roam.configParam.impsSleepTime / PAL_TIMER_TO_SEC_UNIT; @@ -1645,7 +1670,6 @@ eHalStatus csrGetConfigParam(tpAniSirGlobal pMac, tCsrConfigParam *pParam) pParam->fValidateList = pMac->roam.configParam.fValidateList; pParam->fEnableBypass11d = pMac->scan.fEnableBypass11d; pParam->fEnableDFSChnlScan = pMac->scan.fEnableDFSChnlScan; - pParam->fIgnore_chan165= pMac->scan.fIgnore_chan165; pParam->fScanTwice = pMac->roam.configParam.fScanTwice; pParam->fFirstScanOnly2GChnl = pMac->scan.fFirstScanOnly2GChnl; pParam->fEnableMCCMode = pMac->roam.configParam.fenableMCCMode; @@ -1660,7 +1684,7 @@ eHalStatus csrGetConfigParam(tpAniSirGlobal pMac, tCsrConfigParam *pParam) pParam->enableTxBF = pMac->roam.configParam.txBFEnable; pParam->txBFCsnValue = pMac->roam.configParam.txBFCsnValue; #endif - + pParam->enableTxLdpc = pMac->roam.configParam.txLdpcEnable; csrSetChannels(pMac, pParam); status = eHAL_STATUS_SUCCESS; @@ -1917,8 +1941,11 @@ eHalStatus csrGet5GChannels(tpAniSirGlobal pMac) { if(pMac->scan.defaultPowerTable[Index].chanId >= 36 && pMac->scan.defaultPowerTable[Index].chanId <= 165) { - pMac->scan.base20MHzChannels.channelList[ channelList ] = pMac->scan.defaultPowerTable[Index].chanId; - channelList++; + if(channelList < WNI_CFG_VALID_CHANNEL_LIST_LEN) + { + pMac->scan.base20MHzChannels.channelList[ channelList ] = pMac->scan.defaultPowerTable[Index].chanId; + channelList++; + } } } @@ -1978,8 +2005,11 @@ eHalStatus csrGet24GChannels(tpAniSirGlobal pMac) // Restoring the Backed up 5 GHZ channels for(channelList = 0;channelList < nuum5GchannelListBackup; channelList++ ) { - pMac->scan.base20MHzChannels.channelList[ Index ] = channelList5GBackup[channelList]; - Index++; + if (Index < WNI_CFG_VALID_CHANNEL_LIST_LEN) + { + pMac->scan.base20MHzChannels.channelList[ Index ] = channelList5GBackup[channelList]; + Index++; + } } pMac->scan.numChannelsDefault = (num20MHzChannelsFound > Index) ? num20MHzChannelsFound : Index; @@ -2243,7 +2273,7 @@ eHalStatus csrRoamCallCallback(tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoam WLAN_VOS_DIAG_EVENT_DEF(connectionStatus, vos_event_wlan_status_payload_type); #endif tCsrRoamSession *pSession; - if( CSR_IS_SESSION_VALID( pMac, sessionId) ) + if( pMac->roam.roamSession && CSR_IS_SESSION_VALID( pMac, sessionId) ) { pSession = CSR_GET_SESSION( pMac, sessionId ); } @@ -2257,7 +2287,7 @@ eHalStatus csrRoamCallCallback(tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoam { smsLog(pMac, LOGW, " Assoc complete result = %d statusCode = %d reasonCode = %d", u2, pRoamInfo->statusCode, pRoamInfo->reasonCode); } - if ((u1 == eCSR_ROAM_FT_REASSOC_FAILED) && (pSession->bRefAssocStartCnt)) { + if (pSession && (u1 == eCSR_ROAM_FT_REASSOC_FAILED) && (pSession->bRefAssocStartCnt)) { /* * Decrement bRefAssocStartCnt for FT reassoc failure. * Reason: For FT reassoc failures, we first call @@ -2983,6 +3013,7 @@ void csrSetCfgPrivacy( tpAniSirGlobal pMac, tCsrRoamProfile *pProfile, tANI_BOOL break; case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY: + case eCSR_ENCRYPT_TYPE_WEP40: // Privacy is ON. NO RSN for Wep40 static key. PrivacyEnabled = 1; @@ -3036,6 +3067,7 @@ void csrSetCfgPrivacy( tpAniSirGlobal pMac, tCsrRoamProfile *pProfile, tANI_BOOL break; case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY: + case eCSR_ENCRYPT_TYPE_WEP104: // Privacy is ON. NO RSN for Wep40 static key. PrivacyEnabled = 1; @@ -3090,8 +3122,6 @@ void csrSetCfgPrivacy( tpAniSirGlobal pMac, tCsrRoamProfile *pProfile, tANI_BOOL break; - case eCSR_ENCRYPT_TYPE_WEP40: - case eCSR_ENCRYPT_TYPE_WEP104: case eCSR_ENCRYPT_TYPE_TKIP: case eCSR_ENCRYPT_TYPE_AES: #ifdef FEATURE_WLAN_WAPI @@ -4337,8 +4367,8 @@ eHalStatus csrRoamProcessCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand ) switch ( pCommand->u.roamCmd.roamReason ) { case eCsrForcedDisassoc: - csrFreeRoamProfile(pMac, sessionId); status = csrRoamProcessDisassocDeauth( pMac, pCommand, TRUE, FALSE ); + csrFreeRoamProfile(pMac, sessionId); break; case eCsrSmeIssuedDisassocForHandoff: //Not to free pMac->roam.pCurRoamProfile (via csrFreeRoamProfile) because it is needed after disconnect @@ -4350,12 +4380,12 @@ eHalStatus csrRoamProcessCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand ) break; case eCsrForcedDisassocMICFailure: - csrFreeRoamProfile(pMac, sessionId); status = csrRoamProcessDisassocDeauth( pMac, pCommand, TRUE, TRUE ); + csrFreeRoamProfile(pMac, sessionId); break; case eCsrForcedDeauth: - csrFreeRoamProfile(pMac, sessionId); status = csrRoamProcessDisassocDeauth( pMac, pCommand, FALSE, FALSE ); + csrFreeRoamProfile(pMac, sessionId); break; case eCsrHddIssuedReassocToSameAP: case eCsrSmeIssuedReassocToSameAP: @@ -4591,10 +4621,6 @@ static eHalStatus csrRoamSaveSecurityRspIE(tpAniSirGlobal pMac, tANI_U32 session || (eCSR_AUTH_TYPE_WAPI_WAI_PSK == authType) || (eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE == authType) -#endif /* FEATURE_WLAN_WAPI */ -#ifdef WLAN_FEATURE_11W - || - (eCSR_AUTH_TYPE_RSN_PSK_SHA256 == authType) #endif /* FEATURE_WLAN_WAPI */ ) { @@ -4611,9 +4637,6 @@ static eHalStatus csrRoamSaveSecurityRspIE(tpAniSirGlobal pMac, tANI_U32 session (eCSR_AUTH_TYPE_FT_RSN == authType) || (eCSR_AUTH_TYPE_FT_RSN_PSK == authType) || #endif /* WLAN_FEATURE_VOWIFI_11R */ -#if defined WLAN_FEATURE_11W - (eCSR_AUTH_TYPE_RSN_PSK_SHA256 == authType) || -#endif (eCSR_AUTH_TYPE_RSN_PSK == authType)) { if(pIesLocal->RSN.present) @@ -4866,6 +4889,13 @@ tANI_BOOLEAN csrRoamIsFastRoamEnabled(tpAniSirGlobal pMac, tANI_U32 sessionId) return (pMac->roam.configParam.isFastRoamIniFeatureEnabled && (!csrIsConcurrentSessionRunning(pMac))); } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +//Returns whether "FW based BG scan" is currently enabled...or not +tANI_BOOLEAN csrRoamIsRoamOffloadScanEnabled(tpAniSirGlobal pMac) +{ + return (pMac->roam.configParam.isRoamOffloadScanEnabled); +} +#endif #endif //Return true means the command can be release, else not @@ -5129,6 +5159,7 @@ static tANI_BOOLEAN csrRoamProcessResults( tpAniSirGlobal pMac, tSmeCmd *pComman pSession->connectedProfile.modifyProfileFields.uapsd_mask); pmcStartUapsd( pMac, NULL, NULL ); } + pSession->connectedProfile.dot11Mode = pSession->bssParams.uCfgDot11Mode; roamInfo.u.pConnectedProfile = &pSession->connectedProfile; if( pSession->bRefAssocStartCnt > 0 ) { @@ -5603,7 +5634,7 @@ static tANI_BOOLEAN csrRoamProcessResults( tpAniSirGlobal pMac, tSmeCmd *pComman case eCsrForcedDisassocSta: case eCsrForcedDeauthSta: csrRoamStateChange( pMac, eCSR_ROAMING_STATE_JOINED, sessionId); - if( CSR_IS_SESSION_VALID(pMac, sessionId) ) + if( pMac->roam.roamSession && CSR_IS_SESSION_VALID(pMac, sessionId) ) { pSession = CSR_GET_SESSION(pMac, sessionId); if (!pSession) @@ -5752,11 +5783,6 @@ eHalStatus csrRoamCopyProfile(tpAniSirGlobal pMac, tCsrRoamProfile *pDstProfile, pDstProfile->negotiatedUCEncryptionType = pSrcProfile->negotiatedUCEncryptionType; pDstProfile->negotiatedMCEncryptionType = pSrcProfile->negotiatedMCEncryptionType; pDstProfile->negotiatedAuthType = pSrcProfile->negotiatedAuthType; -#ifdef WLAN_FEATURE_11W - pDstProfile->MFPEnabled = pSrcProfile->MFPEnabled; - pDstProfile->MFPRequired = pSrcProfile->MFPRequired; - pDstProfile->MFPCapable = pSrcProfile->MFPCapable; -#endif pDstProfile->BSSType = pSrcProfile->BSSType; pDstProfile->phyMode = pSrcProfile->phyMode; pDstProfile->csrPersona = pSrcProfile->csrPersona; @@ -6707,6 +6733,11 @@ eHalStatus csrRoamSaveConnectedInfomation(tpAniSirGlobal pMac, tANI_U32 sessionI pConnectProfile->beaconInterval = pSirBssDesc->beaconInterval; palCopyMemory(pMac->hHdd, &pConnectProfile->Keys, &pProfile->Keys, sizeof(tCsrKeys)); + if(pConnectProfile->pAddIEAssoc) + { + palFreeMemory(pMac->hHdd, pConnectProfile->pAddIEAssoc); + pConnectProfile->pAddIEAssoc = NULL; + } /* saving the addional IE`s like Hot spot indication element and extended capabilities */ if(pProfile->nAddIEAssocLength) { @@ -6742,9 +6773,6 @@ eHalStatus csrRoamSaveConnectedInfomation(tpAniSirGlobal pMac, tANI_U32 sessionI || (pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_WPA) || (pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_WPA_PSK) || (pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_RSN) -#ifdef WLAN_FEATURE_11W - || (pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_RSN_PSK_SHA256) -#endif || (pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_RSN_PSK)))) && (pMac->roam.configParam.isCcxIniFeatureEnabled)) { @@ -8016,15 +8044,16 @@ static eHalStatus csrRoamIssueSetKeyCommand( tpAniSirGlobal pMac, tANI_U32 sessi #ifdef WLAN_FEATURE_11W //Check for 11w BIP - else if (eCSR_ENCRYPT_TYPE_AES_CMAC == pSetKey->encType) + else if ( eCSR_ENCRYPT_TYPE_AES_CMAC == pSetKey->encType ) { - if (pSetKey->keyLength < CSR_AES_KEY_LEN) + tANI_U16 count = 0; + if ( pSetKey->keyLength < CSR_AES_KEY_LEN ) { - smsLog(pMac, LOGW, "Invalid AES/CCMP keylength [= %d] in SetContext call", pSetKey->keyLength); + smsLog( pMac, LOGW, "Invalid AES/CCMP keylength [= %d] in SetContext call", pSetKey->keyLength ); break; } pCommand->u.setKeyCmd.keyLength = CSR_AES_KEY_LEN; - palCopyMemory(pMac->hHdd, pCommand->u.setKeyCmd.Key, pSetKey->Key, CSR_AES_KEY_LEN); + palCopyMemory( pMac->hHdd, pCommand->u.setKeyCmd.Key, pSetKey->Key, CSR_AES_KEY_LEN ); } #endif status = eHAL_STATUS_SUCCESS; @@ -8045,11 +8074,12 @@ static eHalStatus csrRoamIssueSetKeyCommand( tpAniSirGlobal pMac, tANI_U32 sessi } while (0); // Free the command if there has been a failure, or it is a // "local" operation like the set CCX CCKM KRK key. - if( (!HAL_STATUS_SUCCESS( status ) && ( NULL != pCommand )) + if ( ( NULL != pCommand ) && + ( (!HAL_STATUS_SUCCESS( status ) ) #ifdef FEATURE_WLAN_CCX || ( eCSR_ENCRYPT_TYPE_KRK == pSetKey->encType ) #endif /* FEATURE_WLAN_CCX */ - ) + ) ) { csrReleaseCommandSetKey( pMac, pCommand ); } @@ -8500,16 +8530,16 @@ static void csrUpdateRssi(tpAniSirGlobal pMac, void* pMsg) #if defined WLAN_FEATURE_VOWIFI_11R || defined FEATURE_WLAN_CCX || defined(FEATURE_WLAN_LFR) void csrRoamRssiRspProcessor(tpAniSirGlobal pMac, void* pMsg) { - v_S7_t rssi = 0; tAniGetRoamRssiRsp* pRoamRssiRsp = (tAniGetRoamRssiRsp*)pMsg; - /* Get roam Rssi request is backed up and passed back to the response, - Extract the request message to fetch callback */ - tpAniGetRssiReq reqBkp = (tAniGetRssiReq*)pRoamRssiRsp->rssiReq; - if(pRoamRssiRsp) + if (NULL != pRoamRssiRsp) { - rssi = pRoamRssiRsp->rssi; - if((reqBkp) && (NULL != reqBkp->rssiCallback)) + /* Get roam Rssi request is backed up and passed back to the response, + Extract the request message to fetch callback */ + tpAniGetRssiReq reqBkp = (tAniGetRssiReq*)pRoamRssiRsp->rssiReq; + v_S7_t rssi = pRoamRssiRsp->rssi; + + if ((NULL != reqBkp) && (NULL != reqBkp->rssiCallback)) { ((tCsrRssiCallback)(reqBkp->rssiCallback))(rssi, pRoamRssiRsp->staId, reqBkp->pDevContext); reqBkp->rssiCallback = NULL; @@ -8846,7 +8876,7 @@ void csrRoamCheckForLinkStatusChange( tpAniSirGlobal pMac, tSirSmeRsp *pSirMsg ) { tSirSmeDeauthRsp* pDeauthRsp = (tSirSmeDeauthRsp *)pSirMsg; sessionId = pDeauthRsp->sessionId; - if( CSR_IS_SESSION_VALID(pMac, sessionId) ) + if( pMac->roam.roamSession && CSR_IS_SESSION_VALID(pMac, sessionId) ) { pSession = CSR_GET_SESSION(pMac, sessionId); if(!pSession) @@ -8873,7 +8903,7 @@ void csrRoamCheckForLinkStatusChange( tpAniSirGlobal pMac, tSirSmeRsp *pSirMsg ) { tSirSmeDisassocRsp *pDisassocRsp = (tSirSmeDisassocRsp *)pSirMsg; sessionId = pDisassocRsp->sessionId; - if( CSR_IS_SESSION_VALID(pMac, sessionId) ) + if( pMac->roam.roamSession && CSR_IS_SESSION_VALID(pMac, sessionId) ) { pSession = CSR_GET_SESSION(pMac, sessionId); if(!pSession) @@ -9467,6 +9497,12 @@ void csrRoamCheckForLinkStatusChange( tpAniSirGlobal pMac, tSirSmeRsp *pSirMsg ) smsLog( pMac, LOG1, FL("RSSI indication from TL serialized through MC thread")); csrRoamRssiIndHdlr( pMac, pSirMsg ); break; +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + case eWNI_SME_CANDIDATE_FOUND_IND: + smsLog( pMac, LOG2, FL("Candidate found indication from PE")); + csrNeighborRoamCandidateFoundIndHdlr( pMac, pSirMsg ); + break; +#endif default: break; @@ -12065,19 +12101,6 @@ eHalStatus csrSendJoinReqMsg( tpAniSirGlobal pMac, tANI_U32 sessionId, tSirBssDe dwTmp = pal_cpu_to_be32( csrTranslateEncryptTypeToEdType( pProfile->negotiatedMCEncryptionType) ); palCopyMemory( pMac->hHdd, pBuf, &dwTmp, sizeof(tANI_U32) ); pBuf += sizeof(tANI_U32); -#ifdef WLAN_FEATURE_11W - //MgmtEncryption - if (pProfile->MFPEnabled) - { - dwTmp = pal_cpu_to_be32(eSIR_ED_AES_128_CMAC); - } - else - { - dwTmp = pal_cpu_to_be32(eSIR_ED_NONE); - } - palCopyMemory(pMac->hHdd, pBuf, &dwTmp, sizeof(tANI_U32)); - pBuf += sizeof(tANI_U32); -#endif #ifdef WLAN_FEATURE_VOWIFI_11R pProfile->MDID.mdiePresent = pBssDescription->mdiePresent; if (csrIsProfile11r( pProfile ) @@ -12101,6 +12124,21 @@ eHalStatus csrSendJoinReqMsg( tpAniSirGlobal pMac, tANI_U32 sessionId, tSirBssDe } #endif #ifdef FEATURE_WLAN_CCX + + // isCCXFeatureIniEnabled + if (TRUE == pMac->roam.configParam.isCcxIniFeatureEnabled) + { + dwTmp = pal_cpu_to_be32(TRUE); + palCopyMemory( pMac->hHdd, pBuf, &dwTmp, sizeof(tAniBool) ); + pBuf += sizeof(tAniBool); + } + else + { + dwTmp = pal_cpu_to_be32(FALSE); + palCopyMemory( pMac->hHdd, pBuf, &dwTmp, sizeof(tAniBool) ); + pBuf += sizeof(tAniBool); + } + /* A profile can not be both CCX and 11R. But an 802.11R AP * may be advertising support for CCX as well. So if we are * associating Open or explicitly CCX then we will get CCX. @@ -12113,9 +12151,6 @@ eHalStatus csrSendJoinReqMsg( tpAniSirGlobal pMac, tANI_U32 sessionId, tSirBssDe || (pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_WPA) || (pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_WPA_PSK) || (pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_RSN) -#ifdef WLAN_FEATURE_11W - || (pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_RSN_PSK_SHA256) -#endif || (pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_RSN_PSK)))) && (pMac->roam.configParam.isCcxIniFeatureEnabled)) { @@ -12149,9 +12184,6 @@ eHalStatus csrSendJoinReqMsg( tpAniSirGlobal pMac, tANI_U32 sessionId, tSirBssDe || (pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_WPA) || (pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_WPA_PSK) || (pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_RSN) -#ifdef WLAN_FEATURE_11W - || (pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_RSN_PSK_SHA256) -#endif || (pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_RSN_PSK)))) && (pMac->roam.configParam.isCcxIniFeatureEnabled)) { @@ -12865,8 +12897,8 @@ eHalStatus csrSendMBStartBssReqMsg( tpAniSirGlobal pMac, tANI_U32 sessionId, eCs { wTmp = pal_cpu_to_be16( WNI_CFG_BEACON_INTERVAL_STADEF ); } - if(csrIsconcurrentsessionValid (pMac, sessionId, - pParam->bssPersona) + if(csrIsconcurrentsessionValid (pMac, sessionId, + pParam->bssPersona) == eHAL_STATUS_SUCCESS ) { csrValidateMCCBeaconInterval(pMac, pParam->operationChn, &wTmp, sessionId, @@ -13145,22 +13177,24 @@ eHalStatus csrProcessAddStaSessionRsp( tpAniSirGlobal pMac, tANI_U8 *pMsg) } while(0); return status; } -eHalStatus csrSendMBAddSelfStaReqMsg( tpAniSirGlobal pMac, tSirMacAddr macAddr ) +eHalStatus csrSendMBAddSelfStaReqMsg(tpAniSirGlobal pMac, tAddStaForSessionCmd *pAddStaReq) { tSirSmeAddStaSelfReq *pMsg; tANI_U16 msgLen; eHalStatus status = eHAL_STATUS_FAILURE; do { - msgLen = sizeof( tANI_U16 ) + sizeof( tANI_U16 ) + sizeof( tSirMacAddr ) /*+ - sizeof( tSirBssType )*/; + msgLen = sizeof(tSirSmeAddStaSelfReq); status = palAllocateMemory(pMac->hHdd, (void **)&pMsg, msgLen); if ( !HAL_STATUS_SUCCESS(status) ) break; palZeroMemory(pMac->hHdd, pMsg, msgLen); pMsg->mesgType = pal_cpu_to_be16((tANI_U16)eWNI_SME_ADD_STA_SELF_REQ); pMsg->mesgLen = pal_cpu_to_be16(msgLen); // self station address - palCopyMemory( pMac->hHdd, (tANI_U8 *)pMsg->selfMacAddr, (tANI_U8 *)macAddr, sizeof(tSirMacAddr) ); - smsLog( pMac, LOG1, FL("selfMac=%02x, %02x, %02x, %02x, %02x, %02x"), + palCopyMemory(pMac->hHdd, (tANI_U8 *)pMsg->selfMacAddr, + (tANI_U8 *)&pAddStaReq->selfMacAddr, sizeof(tSirMacAddr)); + pMsg->currDeviceMode = pAddStaReq->currDeviceMode; + + smsLog( pMac, LOG1, FL("selfMac=%02x, %02x, %02x, %02x, %02x, %02x"), pMsg->selfMacAddr[0], pMsg->selfMacAddr[1], pMsg->selfMacAddr[2], @@ -13171,7 +13205,8 @@ eHalStatus csrSendMBAddSelfStaReqMsg( tpAniSirGlobal pMac, tSirMacAddr macAddr ) } while( 0 ); return( status ); } -eHalStatus csrIssueAddStaForSessionReq(tpAniSirGlobal pMac, tANI_U32 sessionId, tSirMacAddr sessionMacAddr) +eHalStatus csrIssueAddStaForSessionReq(tpAniSirGlobal pMac, tANI_U32 sessionId, + tSirMacAddr sessionMacAddr) { eHalStatus status = eHAL_STATUS_SUCCESS; tSmeCmd *pCommand; @@ -13184,7 +13219,8 @@ eHalStatus csrIssueAddStaForSessionReq(tpAniSirGlobal pMac, tANI_U32 sessionId, { pCommand->command = eSmeCommandAddStaSession; pCommand->sessionId = (tANI_U8)sessionId; - palCopyMemory( pMac->hHdd, pCommand->u.addStaSessionCmd.selfMacAddr, sessionMacAddr, sizeof( tSirMacAddr ) ); + palCopyMemory(pMac->hHdd, pCommand->u.addStaSessionCmd.selfMacAddr, sessionMacAddr, sizeof(tSirMacAddr)); + pCommand->u.addStaSessionCmd.currDeviceMode = pMac->sme.currDeviceMode; status = csrQueueSmeCommand(pMac, pCommand, TRUE); if( !HAL_STATUS_SUCCESS( status ) ) { @@ -13196,11 +13232,11 @@ eHalStatus csrIssueAddStaForSessionReq(tpAniSirGlobal pMac, tANI_U32 sessionId, } eHalStatus csrProcessAddStaSessionCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand ) { - return csrSendMBAddSelfStaReqMsg( pMac, - pCommand->u.addStaSessionCmd.selfMacAddr ); + return csrSendMBAddSelfStaReqMsg( pMac, &pCommand->u.addStaSessionCmd); } -eHalStatus csrRoamOpenSession( tpAniSirGlobal pMac, csrRoamCompleteCallback callback, void *pContext, - tANI_U8 *pSelfMacAddr, tANI_U8 *pbSessionId ) +eHalStatus csrRoamOpenSession(tpAniSirGlobal pMac, + csrRoamCompleteCallback callback, void *pContext, + tANI_U8 *pSelfMacAddr, tANI_U8 *pbSessionId) { eHalStatus status = eHAL_STATUS_SUCCESS; tANI_U32 i; @@ -13243,7 +13279,7 @@ eHalStatus csrRoamOpenSession( tpAniSirGlobal pMac, csrRoamCompleteCallback call smsLog(pMac, LOGE, FL("cannot allocate memory for IbssJoining timer")); break; } - status = csrIssueAddStaForSessionReq ( pMac, i, pSelfMacAddr ); + status = csrIssueAddStaForSessionReq(pMac, i, pSelfMacAddr); break; } } @@ -13798,6 +13834,7 @@ void csrRoamStatsRspProcessor(tpAniSirGlobal pMac, tSirSmeRsp *pSirMsg) v_PVOID_t pvosGCtx; v_S7_t rssi = 0; tANI_U32 *pRssi = NULL; + tANI_U32 linkCapacity; pSmeStatsRsp = (tAniGetPEStatsRsp *)pSirMsg; if(pSmeStatsRsp->rc) { @@ -13895,13 +13932,27 @@ void csrRoamStatsRspProcessor(tpAniSirGlobal pMac, tSirSmeRsp *pSirMsg) { pRssi = (tANI_U32*)pStats; rssi = (v_S7_t)*pRssi; + pStats += sizeof(tANI_U32); + length -= sizeof(tANI_U32); } else { /* If riva is not sending rssi, continue to use the hack */ rssi = RSSI_HACK_BMPS; } + WDA_UpdateRssiBmps(pvosGCtx, pSmeStatsRsp->staId, rssi); + + if (length != 0) + { + linkCapacity = *(tANI_U32*)pStats; + } + else + { + linkCapacity = 0; + } + + WDA_UpdateLinkCapacity(pvosGCtx, pSmeStatsRsp->staId, linkCapacity); post_update: //make sure to update the pe stats req list pEntry = csrRoamFindInPeStatsReqList(pMac, pSmeStatsRsp->statsMask); @@ -14244,8 +14295,8 @@ eHalStatus csrGetRoamRssi(tpAniSirGlobal pMac, status = palSendMBMessage(pMac->hHdd, pMsg ); if(!HAL_STATUS_SUCCESS(status)) { - smsLog(pMac, LOG1, " csrGetRoamRssi: failed to send down the stats req"); - palFreeMemory(pMac->hHdd, (void *)pMsg); + smsLog(pMac, LOG1, " csrGetRoamRssi: failed to send down the rssi req"); + //pMsg is freed by palSendMBMessage status = eHAL_STATUS_FAILURE; } return status; @@ -14521,6 +14572,365 @@ eHalStatus csrGetStatistics(tpAniSirGlobal pMac, eCsrStatsRequesterType requeste return eHAL_STATUS_SUCCESS; } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + +static tSirRetStatus +csrRoamScanOffloadPopulateMacHeader(tpAniSirGlobal pMac, + tANI_U8* pBD, + tANI_U8 type, + tANI_U8 subType, + tSirMacAddr peerAddr, + tSirMacAddr selfMacAddr) +{ + tSirRetStatus statusCode = eSIR_SUCCESS; + tpSirMacMgmtHdr pMacHdr; + + /* Prepare MAC management header */ + pMacHdr = (tpSirMacMgmtHdr) (pBD); + + /* Prepare FC */ + pMacHdr->fc.protVer = SIR_MAC_PROTOCOL_VERSION; + pMacHdr->fc.type = type; + pMacHdr->fc.subType = subType; + + /* Prepare Address 1 */ + palCopyMemory( pMac->hHdd, + (tANI_U8 *) pMacHdr->da, + (tANI_U8 *) peerAddr, + sizeof( tSirMacAddr )); + + sirCopyMacAddr(pMacHdr->sa,selfMacAddr); + + /* Prepare Address 3 */ + palCopyMemory( pMac->hHdd, + (tANI_U8 *) pMacHdr->bssId, + (tANI_U8 *) peerAddr, + sizeof( tSirMacAddr )); + return statusCode; +} /*** csrRoamScanOffloadPopulateMacHeader() ***/ + +static tSirRetStatus +csrRoamScanOffloadPrepareProbeReqTemplate(tpAniSirGlobal pMac, + tANI_U8 nChannelNum, + tANI_U32 dot11mode, + tSirMacAddr selfMacAddr, + tANI_U8 *pFrame, + tANI_U16 *pusLen) +{ + tDot11fProbeRequest pr; + tANI_U32 nStatus, nBytes, nPayload; + tSirRetStatus nSirStatus; + /*Bcast tx*/ + tSirMacAddr bssId = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + + + palZeroMemory( pMac->hHdd, ( tANI_U8* )&pr, sizeof( pr ) ); + + PopulateDot11fSuppRates( pMac, nChannelNum, &pr.SuppRates,NULL); + + if ( WNI_CFG_DOT11_MODE_11B != dot11mode ) + { + PopulateDot11fExtSuppRates1( pMac, nChannelNum, &pr.ExtSuppRates ); + } + + + if (IS_DOT11_MODE_HT(dot11mode)) + { + PopulateDot11fHTCaps( pMac, NULL, &pr.HTCaps ); + } + + + nStatus = dot11fGetPackedProbeRequestSize( pMac, &pr, &nPayload ); + if ( DOT11F_FAILED( nStatus ) ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "Failed to calculate the packed size f" + "or a Probe Request (0x%08x).\n", nStatus ); + + + nPayload = sizeof( tDot11fProbeRequest ); + } + else if ( DOT11F_WARNED( nStatus ) ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "There were warnings while calculating" + "the packed size for a Probe Request (" + "0x%08x).\n", nStatus ); + } + + nBytes = nPayload + sizeof( tSirMacMgmtHdr ); + + /* Prepare outgoing frame*/ + palZeroMemory( pMac->hHdd, pFrame, nBytes ); + + + nSirStatus = csrRoamScanOffloadPopulateMacHeader( pMac, pFrame, SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_PROBE_REQ, bssId ,selfMacAddr); + + if ( eSIR_SUCCESS != nSirStatus ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "Failed to populate the buffer descriptor for a Probe Request (%d).\n", + nSirStatus ); + return nSirStatus; + } + + + nStatus = dot11fPackProbeRequest( pMac, &pr, pFrame + + sizeof( tSirMacMgmtHdr ), + nPayload, &nPayload ); + if ( DOT11F_FAILED( nStatus ) ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "Failed to pack a Probe Request (0x%08x).\n", nStatus ); + return eSIR_FAILURE; + } + else if ( DOT11F_WARNED( nStatus ) ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "There were warnings while packing a Probe Request (0x%08x).\n" ); + } + + *pusLen = nPayload + sizeof(tSirMacMgmtHdr); + return eSIR_SUCCESS; +} + +eHalStatus csrRoamOffloadScan(tpAniSirGlobal pMac, tANI_U8 command, tANI_U8 reason) +{ + vos_msg_t msg; + tSirRoamOffloadScanReq *pRequestBuf; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo; + tCsrRoamSession *pSession; + tANI_U8 i,num_channels = 0, ucDot11Mode; + tANI_U8 *ChannelList = NULL; + tANI_U8 MaxDwellPeriod; + tANI_U32 sessionId; + eHalStatus status = eHAL_STATUS_SUCCESS; + tpCsrChannelInfo currChannelListInfo; + currChannelListInfo = &pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo; + + if (0 == pMac->roam.configParam.isRoamOffloadScanEnabled) + { + return eHAL_STATUS_FAILURE; + } + status = csrRoamGetSessionIdFromBSSID(pMac, + (tCsrBssid *)pNeighborRoamInfo->currAPbssid, + &sessionId); + /*The Dynamic Config Items Update may happen even if the state is in INIT. + * It is important to ensure that the command is passed down to the FW only + * if the Infra Station is in a connected state.A connected station could also be + * in a PREAUTH or REASSOC states.So, consider not sending the command down in INIT state. + * We also have to ensure that if there is a STOP command we always have to inform Riva, + * irrespective of whichever state we are in.*/ + if ((pMac->roam.neighborRoamInfo.neighborRoamState == eCSR_NEIGHBOR_ROAM_STATE_INIT) && + (command != ROAM_SCAN_OFFLOAD_STOP)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "Scan Command not sent to FW with state = %d and cmd = %d\n", + pMac->roam.neighborRoamInfo.neighborRoamState, command); + return eHAL_STATUS_FAILURE; + } + + if ( !HAL_STATUS_SUCCESS( status ) ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Not able to find the sessionId for Roam Offload scan request", __func__); + return eHAL_STATUS_FAILURE; + } + pSession = CSR_GET_SESSION( pMac, sessionId ); + pRequestBuf = vos_mem_malloc(sizeof(tSirRoamOffloadScanReq)); + if (NULL == pRequestBuf) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Not able to allocate memory for Roam Offload scan request", __func__); + return eHAL_STATUS_FAILED_ALLOC; + } + + vos_mem_zero(pRequestBuf,sizeof(tSirRoamOffloadScanReq)); + /* If command is STOP, then pass down ScanOffloadEnabled as Zero.This will handle the case of + * host driver reloads, but Riva still up and running*/ + if(command == ROAM_SCAN_OFFLOAD_STOP) + pRequestBuf->RoamScanOffloadEnabled = 0; + else + pRequestBuf->RoamScanOffloadEnabled = pMac->roam.configParam.isRoamOffloadScanEnabled; + vos_mem_copy(pRequestBuf->ConnectedNetwork.currAPbssid, pNeighborRoamInfo->currAPbssid, + sizeof(tCsrBssid)); + pRequestBuf->ConnectedNetwork.ssId.length = + pMac->roam.roamSession[sessionId].connectedProfile.SSID.length; + vos_mem_copy(pRequestBuf->ConnectedNetwork.ssId.ssId, + pMac->roam.roamSession[sessionId].connectedProfile.SSID.ssId, + pRequestBuf->ConnectedNetwork.ssId.length); + pRequestBuf->ConnectedNetwork.authentication = + pMac->roam.roamSession[sessionId].connectedProfile.AuthType; + pRequestBuf->ConnectedNetwork.encryption = + pMac->roam.roamSession[sessionId].connectedProfile.EncryptionType; + pRequestBuf->ConnectedNetwork.mcencryption = + pMac->roam.roamSession[sessionId].connectedProfile.mcEncryptionType; + pRequestBuf->LookupThreshold = + (v_S7_t)pNeighborRoamInfo->cfgParams.neighborLookupThreshold * (-1); + pRequestBuf->RoamRssiDiff = + pMac->roam.configParam.RoamRssiDiff; + pRequestBuf->Command = command; + pRequestBuf->StartScanReason = reason; + pRequestBuf->NeighborScanTimerPeriod = + pNeighborRoamInfo->cfgParams.neighborScanPeriod; + pRequestBuf->NeighborRoamScanRefreshPeriod = + pNeighborRoamInfo->cfgParams.neighborResultsRefreshPeriod; + pRequestBuf->NeighborScanChannelMinTime = + pNeighborRoamInfo->cfgParams.minChannelScanTime; + pRequestBuf->NeighborScanChannelMaxTime = + pNeighborRoamInfo->cfgParams.maxChannelScanTime; + pRequestBuf->EmptyRefreshScanPeriod = + pNeighborRoamInfo->cfgParams.emptyScanRefreshPeriod; +#ifdef FEATURE_WLAN_CCX + pRequestBuf->IsCCXEnabled = pMac->roam.configParam.isCcxIniFeatureEnabled; +#endif + if ( +#ifdef FEATURE_WLAN_CCX + ((pNeighborRoamInfo->isCCXAssoc) && + (pNeighborRoamInfo->roamChannelInfo.IAPPNeighborListReceived == + eANI_BOOLEAN_FALSE)) || + (pNeighborRoamInfo->isCCXAssoc == eANI_BOOLEAN_FALSE) || +#endif // CCX + currChannelListInfo->numOfChannels == 0) + { + + /*Retreive the Channel Cache either from ini or from the Occupied Channels list. + * Give Preference to INI Channels.*/ + if (pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels) + { + ChannelList = pNeighborRoamInfo->cfgParams.channelInfo.ChannelList; + for (i=0; icfgParams.channelInfo.numOfChannels ;i++) + { + if(!CSR_IS_CHANNEL_DFS(*ChannelList) && *ChannelList) + { + pRequestBuf->ConnectedNetwork.ChannelCache[num_channels++] = *ChannelList; + } + ChannelList++; + } + pRequestBuf->ConnectedNetwork.ChannelCount = num_channels; + pRequestBuf->ChannelCacheType = CHANNEL_LIST_STATIC; + } + else{ + ChannelList = pMac->scan.occupiedChannels.channelList; + for(i=0; iscan.occupiedChannels.numChannels; i++) + { + if(!CSR_IS_CHANNEL_DFS(*ChannelList) && *ChannelList) + { + pRequestBuf->ConnectedNetwork.ChannelCache[num_channels++] = *ChannelList; + } + ChannelList++; + } + pRequestBuf->ConnectedNetwork.ChannelCount = num_channels; + /* If the profile changes as to what it was earlier, inform the FW through + * FLUSH as ChannelCacheType in which case, the FW will flush the occupied channels + * for the earlier profile and try to learn them afresh.*/ + if (reason == REASON_FLUSH_CHANNEL_LIST) + pRequestBuf->ChannelCacheType = CHANNEL_LIST_DYNAMIC_FLUSH; + else { + if (csrNeighborRoamIsNewConnectedProfile(pMac)) + pRequestBuf->ChannelCacheType = CHANNEL_LIST_DYNAMIC_INIT; + else + pRequestBuf->ChannelCacheType = CHANNEL_LIST_DYNAMIC_UPDATE; + } + } + } +#ifdef FEATURE_WLAN_CCX + else + { + /* If CCX is enabled, and a neighbor Report is received,then + * Ignore the INI Channels or the Occupied Channel List. Consider + * the channels in the neighbor list sent by the CCX AP.*/ + if (currChannelListInfo->numOfChannels != 0) + { + ChannelList = currChannelListInfo->ChannelList; + for (i=0;inumOfChannels;i++) + { + if(!CSR_IS_CHANNEL_DFS(*ChannelList) && *ChannelList) + { + pRequestBuf->ConnectedNetwork.ChannelCache[num_channels++] = *ChannelList; + } + ChannelList++; + } + pRequestBuf->ConnectedNetwork.ChannelCount = num_channels; + pRequestBuf->ChannelCacheType = CHANNEL_LIST_STATIC; + } + } +#endif + num_channels = 0; + ChannelList = NULL; + + /* Maintain the Valid Channels List*/ + if (0 == strncmp(pMac->scan.countryCodeCurrent, "KR", 2)) + { + ChannelList = pNeighborRoamInfo->cfgParams.countryChannelInfo.countryValidChannelList.ChannelList; + for(i=0; icfgParams.countryChannelInfo.countryValidChannelList.numOfChannels; i++) + { + if(!CSR_IS_CHANNEL_DFS(*ChannelList) && *ChannelList) + { + pRequestBuf->ValidChannelList[num_channels++] = *ChannelList; + } + ChannelList++; + } + pRequestBuf->ValidChannelCount = num_channels; + } else { + ChannelList = pMac->roam.validChannelList; + for(i=0; iroam.numValidChannels; i++) + { + if(!CSR_IS_CHANNEL_DFS(*ChannelList) && *ChannelList) + { + pRequestBuf->ValidChannelList[num_channels++] = *ChannelList; + } + ChannelList++; + } + pRequestBuf->ValidChannelCount = num_channels; + } + pRequestBuf->MDID.mdiePresent = + pMac->roam.roamSession[sessionId].connectedProfile.MDID.mdiePresent; + pRequestBuf->MDID.mobilityDomain = + pMac->roam.roamSession[sessionId].connectedProfile.MDID.mobilityDomain; + /*Ensure that the nProbes does not fall below its MIN Value which is 2*/ + if(pMac->roam.configParam.nProbes < 2) + pRequestBuf->nProbes = 2; + else + pRequestBuf->nProbes = pMac->roam.configParam.nProbes; + + /*Max Dwell Period is calculated here to ensure that, + * Home Away Time is atleast equal to (MaxDwellPeriod + + * (2*SRF)), where SRF is the RF Switching time.The RF + * switching time is considered twice to consider the + * time to go off channel and return to the home channel.*/ + MaxDwellPeriod = pRequestBuf->NeighborScanChannelMaxTime/pRequestBuf->nProbes; + if(MaxDwellPeriod < 1) + MaxDwellPeriod = 1; + if(pMac->roam.configParam.nRoamScanHomeAwayTime < + (MaxDwellPeriod + (2 * SIR_ROAM_SCAN_CHANNEL_SWITCH_TIME))) + { + pRequestBuf->HomeAwayTime = MaxDwellPeriod + (2 * SIR_ROAM_SCAN_CHANNEL_SWITCH_TIME); + } else { + pRequestBuf->HomeAwayTime = pMac->roam.configParam.nRoamScanHomeAwayTime; + } + /*Prepare a probe request for 2.4GHz band and one for 5GHz band*/ + ucDot11Mode = (tANI_U8) csrTranslateToWNICfgDot11Mode(pMac, + csrFindBestPhyMode( pMac, pMac->roam.configParam.phyMode )); + csrRoamScanOffloadPrepareProbeReqTemplate(pMac,SIR_ROAM_SCAN_24G_DEFAULT_CH, ucDot11Mode, pSession->selfMacAddr, + pRequestBuf->p24GProbeTemplate, &pRequestBuf->us24GProbeTemplateLen); + + csrRoamScanOffloadPrepareProbeReqTemplate(pMac,SIR_ROAM_SCAN_5G_DEFAULT_CH, ucDot11Mode, pSession->selfMacAddr, + pRequestBuf->p5GProbeTemplate, &pRequestBuf->us5GProbeTemplateLen); + msg.type = WDA_ROAM_SCAN_OFFLOAD_REQ; + msg.reserved = 0; + msg.bodyptr = pRequestBuf; + if (!VOS_IS_STATUS_SUCCESS(vos_mq_post_message(VOS_MODULE_ID_WDA, &msg))) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Not able to post WDA_ROAM_SCAN_OFFLOAD_REQ message to WDA", __func__); + vos_mem_free(pRequestBuf); + return eHAL_STATUS_FAILURE; + } + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, "Roam Scan Offload Command %d, Reason %d", command, reason); + return status; +} +#endif + tCsrPeStatsReqInfo * csrRoamCheckPeStatsReqList(tpAniSirGlobal pMac, tANI_U32 statsMask, tANI_U32 periodicity, tANI_BOOLEAN *pFound, tANI_U8 staId) { @@ -14936,6 +15346,9 @@ eHalStatus csrIsFullPowerNeeded( tpAniSirGlobal pMac, tSmeCmd *pCommand, { switch( pCommand->u.scanCmd.reason ) { +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + case eCsrScanGetLfrResult: +#endif case eCsrScanGetResult: case eCsrScanBGScanAbort: case eCsrScanBGScanEnable: @@ -15513,8 +15926,48 @@ eHalStatus csrSetTxPower(tpAniSirGlobal pMac, v_U8_t sessionId, v_U8_t mW) if (!HAL_STATUS_SUCCESS(status)) { smsLog(pMac, LOGE, FL(" csr set TX Power Post MSG Fail %d "), status); - palFreeMemory(pMac->hHdd, pMsg); + //pMsg is freed by palSendMBMessage } } return status; } + +/* Returns whether a session is in VOS_STA_MODE...or not */ +tANI_BOOLEAN csrRoamIsStaMode(tpAniSirGlobal pMac, tANI_U32 sessionId) +{ + tCsrRoamSession *pSession = NULL; + pSession = CSR_GET_SESSION ( pMac, sessionId ); + if(!pSession) + { + smsLog(pMac, LOGE, FL(" %s: session %d not found "), __func__, sessionId); + return eANI_BOOLEAN_FALSE; + } + if ( !CSR_IS_SESSION_VALID ( pMac, sessionId ) ) + { + smsLog(pMac, LOGE, FL(" %s: Inactive session"), __func__); + return eANI_BOOLEAN_FALSE; + } + if ( eCSR_BSS_TYPE_INFRASTRUCTURE != pSession->connectedProfile.BSSType ) + { + return eANI_BOOLEAN_FALSE; + } + /* There is a possibility that the above check may fail,because + * P2P CLI also uses the same BSSType (eCSR_BSS_TYPE_INFRASTRUCTURE) + * when it is connected.So,we may sneak through the above check even + * if we are not a STA mode INFRA station. So, if we sneak through + * the above condition, we can use the following check if we are + * really in STA Mode.*/ + + if ( NULL != pSession->pCurRoamProfile ) + { + if ( pSession->pCurRoamProfile->csrPersona == VOS_STA_MODE ) + { + return eANI_BOOLEAN_TRUE; + } else { + smsLog(pMac, LOGE, FL(" %s: pCurRoamProfile is NULL\n"), __func__); + return eANI_BOOLEAN_FALSE; + } + } + + return eANI_BOOLEAN_FALSE; +} diff --git a/drivers/staging/prima/CORE/SME/src/csr/csrApiScan.c b/drivers/staging/prima/CORE/SME/src/csr/csrApiScan.c index d842856c267..839b1204379 100755 --- a/drivers/staging/prima/CORE/SME/src/csr/csrApiScan.c +++ b/drivers/staging/prima/CORE/SME/src/csr/csrApiScan.c @@ -114,10 +114,30 @@ RSSI *cannot* be more than 0xFF or less than 0 for meaningful WLAN operation #define CSR_SCAN_IS_OVER_BSS_LIMIT(pMac) \ ( (pMac)->scan.nBssLimit <= (csrLLCount(&(pMac)->scan.scanResultList)) ) +/* Maximum number of channels per country can be ignored */ +#define MAX_CHANNELS_IGNORE 10 + +#define MAX_COUNTRY_IGNORE 3 +#define THIRTY_PERCENT(x) (x*30/100); + +/*struct to hold the ignored channel list based on country */ +typedef struct sCsrIgnoreChannels +{ + tANI_U8 countryCode[NV_FIELD_COUNTRY_CODE_SIZE]; + tANI_U16 channelList[MAX_CHANNELS_IGNORE]; + tANI_U16 channelCount; +}tCsrIgnoreChannels; + +static tCsrIgnoreChannels countryIgnoreList[MAX_COUNTRY_IGNORE] = { + { {'U','A'}, { 136, 140}, 2}, + { {'T','W'}, { 36, 40, 44, 48, 52}, 5}, + { {'I','D'}, { 165}, 1 } + }; + //*** This is temporary work around. It need to call CCM api to get to CFG later /// Get string parameter value extern tSirRetStatus wlan_cfgGetStr(tpAniSirGlobal, tANI_U16, tANI_U8*, tANI_U32*); - + void csrScanGetResultTimerHandler(void *); void csrScanResultAgingTimerHandler(void *pv); static void csrScanResultCfgAgingTimerHandler(void *pv); @@ -437,7 +457,7 @@ eHalStatus csrQueueScanRequest( tpAniSirGlobal pMac, tSmeCmd *pScanCmd ) tANI_BOOLEAN fNoCmdPending; tSmeCmd *pQueueScanCmd=NULL; tSmeCmd *pSendScanCmd=NULL; - + tANI_U8 nNumChanCombinedConc = 0; if (NULL == pScanCmd) { smsLog (pMac, LOGE, FL("Scan Req cmd is NULL")); @@ -452,6 +472,16 @@ eHalStatus csrQueueScanRequest( tpAniSirGlobal pMac, tSmeCmd *pScanCmd ) * the scan is delaying the time it takes for LFR to find * candidates and resulting in disconnects. */ + + if(csrIsStaSessionConnected(pMac) && + !csrIsP2pSessionConnected(pMac)) + { + nNumChanCombinedConc = pMac->roam.configParam.nNumStaChanCombinedConc; + } + else if(csrIsP2pSessionConnected(pMac)) + { + nNumChanCombinedConc = pMac->roam.configParam.nNumP2PChanCombinedConc; + } if ( (csrIsStaSessionConnected(pMac) && #ifdef FEATURE_WLAN_LFR (csrIsConcurrentInfraConnected(pMac) || @@ -494,7 +524,7 @@ eHalStatus csrQueueScanRequest( tpAniSirGlobal pMac, tSmeCmd *pScanCmd ) //Whenever we get a scan request with multiple channels we break it up into 2 requests //First request for first channel to scan and second request to scan remaining channels - if (numChn > pMac->roam.configParam.nNumChanCombinedConc) + if ( numChn > nNumChanCombinedConc) { palZeroMemory(pMac->hHdd, &scanReq, sizeof(tCsrScanRequest)); @@ -527,14 +557,14 @@ eHalStatus csrQueueScanRequest( tpAniSirGlobal pMac, tSmeCmd *pScanCmd ) scanReq.ChannelInfo.ChannelList = NULL; } - pChnInfo->numOfChannels = pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels - pMac->roam.configParam.nNumChanCombinedConc; + pChnInfo->numOfChannels = pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels - nNumChanCombinedConc; VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_WARN, - FL(" &channelToScan %0x pScanCmd(0x%X) pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList(0x%X)numChn(%d)"), - &channelToScan[0], (unsigned int)pScanCmd, - (unsigned int)pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList, numChn); + FL(" &channelToScan %p pScanCmd(%p) pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList(%p)numChn(%d)"), + &channelToScan[0], pScanCmd, + pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList, numChn); - palCopyMemory(pMac->hHdd, &channelToScan[0], &pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList[pMac->roam.configParam.nNumChanCombinedConc], + palCopyMemory(pMac->hHdd, &channelToScan[0], &pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList[nNumChanCombinedConc], pChnInfo->numOfChannels * sizeof(tANI_U8)); pChnInfo->ChannelList = &channelToScan[0]; @@ -571,7 +601,7 @@ eHalStatus csrQueueScanRequest( tpAniSirGlobal pMac, tSmeCmd *pScanCmd ) /* setup the command to scan 2 channels */ pSendScanCmd = pScanCmd; - pSendScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels = pMac->roam.configParam.nNumChanCombinedConc; + pSendScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels = nNumChanCombinedConc; pSendScanCmd->u.scanCmd.u.scanRequest.BSSType = eCSR_BSS_TYPE_ANY; pSendScanCmd->u.scanCmd.u.scanRequest.scanType = eSIR_ACTIVE_SCAN; //Use concurrency values for min/maxChnTime. @@ -950,6 +980,44 @@ eHalStatus csrScanRequestResult(tpAniSirGlobal pMac) return (status); } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +eHalStatus csrScanRequestLfrResult(tpAniSirGlobal pMac, tANI_U32 sessionId, + csrScanCompleteCallback callback, void *pContext) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tSmeCmd *pScanCmd; + + if (pMac->scan.fScanEnable) + { + pScanCmd = csrGetCommandBuffer(pMac); + if (pScanCmd) + { + pScanCmd->command = eSmeCommandScan; + pScanCmd->sessionId = sessionId; + palZeroMemory(pMac->hHdd, &pScanCmd->u.scanCmd, sizeof(tScanCmd)); + pScanCmd->u.scanCmd.callback = callback; + pScanCmd->u.scanCmd.pContext = pContext; + pScanCmd->u.scanCmd.reason = eCsrScanGetLfrResult; + //Need to make the following atomic + pScanCmd->u.scanCmd.scanID = pMac->scan.nextScanID; //let it wrap around + status = csrQueueSmeCommand(pMac, pScanCmd, eANI_BOOLEAN_TRUE); + if ( !HAL_STATUS_SUCCESS( status ) ) + { + smsLog( pMac, LOGE, FL(" fail to send message status = %d\n"), status ); + csrReleaseCommandScan(pMac, pScanCmd); + } + } + else + { + //log error + smsLog(pMac, LOGE, FL("can not obtain a common buffer\n")); + status = eHAL_STATUS_RESOURCES; + } + } + + return (status); +} +#endif //WLAN_FEATURE_ROAM_SCAN_OFFLOAD eHalStatus csrScanAllChannels(tpAniSirGlobal pMac, eCsrRequestType reqType) { @@ -2735,11 +2803,14 @@ tANI_BOOLEAN csrProcessBSSDescForBKIDList(tpAniSirGlobal pMac, tSirBssDescriptio #endif -static void csrMoveTempScanResultsToMainList( tpAniSirGlobal pMac ) +static void csrMoveTempScanResultsToMainList( tpAniSirGlobal pMac, tANI_U8 reason ) { tListElem *pEntry; + tListElem *pEntryTemp; + tListElem *pNext; tCsrScanResult *pBssDescription; tANI_S8 cand_Bss_rssi; + tANI_S8 rssi_of_current_country; tANI_BOOLEAN fDupBss; #ifdef FEATURE_WLAN_WAPI tANI_BOOLEAN fNewWapiBSSForCurConnection = eANI_BOOLEAN_FALSE; @@ -2748,9 +2819,11 @@ static void csrMoveTempScanResultsToMainList( tpAniSirGlobal pMac ) tANI_U32 sessionId = CSR_SESSION_ID_INVALID; tAniSSID tmpSsid; v_TIME_t timer=0; + tCsrBssid bssid_temp = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; tmpSsid.length = 0; cand_Bss_rssi = -128; // RSSI coming from PE is -ve + rssi_of_current_country = -128; // remove the BSS descriptions from temporary list while( ( pEntry = csrLLRemoveTail( &pMac->scan.tempScanResults, LL_ACCESS_LOCK ) ) != NULL) @@ -2773,8 +2846,12 @@ static void csrMoveTempScanResultsToMainList( tpAniSirGlobal pMac ) continue; } fDupBss = csrRemoveDupBssDescription( pMac, &pBssDescription->Result.BssDescriptor, pIesLocal, &tmpSsid , &timer ); - //Check whether we have reach out limit - if( CSR_SCAN_IS_OVER_BSS_LIMIT(pMac) ) + //Check whether we have reach out limit, but don't lose the LFR candidates came from FW + if( CSR_SCAN_IS_OVER_BSS_LIMIT(pMac) +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + && !( eCsrScanGetLfrResult == reason ) +#endif + ) { //Limit reach smsLog(pMac, LOGW, FL(" BSS limit reached")); @@ -2827,14 +2904,34 @@ static void csrMoveTempScanResultsToMainList( tpAniSirGlobal pMac ) if(pIesLocal->Country.present) { cand_Bss_rssi = pBssDescription->Result.BssDescriptor.rssi; - // learn country information - csrLearnCountryInformation( pMac, &pBssDescription->Result.BssDescriptor, - pIesLocal, eANI_BOOLEAN_FALSE ); + smsLog(pMac, LOGE, FL("11d AP Bssid " MAC_ADDRESS_STR + " chan= %d, rssi = -%d, countryCode %c%c"), + MAC_ADDR_ARRAY( pBssDescription->Result.BssDescriptor.bssId), + pBssDescription->Result.BssDescriptor.channelId, + pBssDescription->Result.BssDescriptor.rssi * (-1), + pIesLocal->Country.country[0],pIesLocal->Country.country[1] ); + //Getting BSSID for best AP in scan result. + palCopyMemory(pMac->hHdd, bssid_temp, + pBssDescription->Result.BssDescriptor.bssId, sizeof(tSirMacAddr)); + } } } - + //get current rssi for BSS from which country code is acquired. + if ( csrIs11dSupported(pMac) && (csrIsMacAddressEqual(pMac, + &pMac->scan.currentCountryBssid, + &pBssDescription->Result.BssDescriptor.bssId) )) + { + smsLog(pMac, LOGE, FL("Information about current country Bssid " + MAC_ADDRESS_STR + " chan= %d, rssi = -%d, countryCode %c%c"), + MAC_ADDR_ARRAY( pBssDescription->Result.BssDescriptor.bssId), + pBssDescription->Result.BssDescriptor.channelId, + pBssDescription->Result.BssDescriptor.rssi * (-1), + pIesLocal->Country.country[0],pIesLocal->Country.country[1] ); + rssi_of_current_country = pBssDescription->Result.BssDescriptor.rssi; + } // append to main list csrScanAddResult(pMac, pBssDescription, pIesLocal); @@ -2843,6 +2940,39 @@ static void csrMoveTempScanResultsToMainList( tpAniSirGlobal pMac ) palFreeMemory(pMac->hHdd, pIesLocal); } } + // calculating 30% of current rssi is an idea for not to change + // country code so freq. + if(rssi_of_current_country != -128) + { + rssi_of_current_country = rssi_of_current_country + - THIRTY_PERCENT(rssi_of_current_country); + } + + if ((rssi_of_current_country <= cand_Bss_rssi ) || rssi_of_current_country == -128) + { + csrLLLock(&pMac->scan.scanResultList); + pEntryTemp = csrLLPeekHead(&pMac->scan.scanResultList, LL_ACCESS_NOLOCK); + while ( NULL != pEntryTemp) + { + pNext = csrLLNext(&pMac->scan.scanResultList, pEntryTemp, + LL_ACCESS_NOLOCK); + pBssDescription = GET_BASE_ADDR( pEntryTemp, tCsrScanResult, Link ); + pIesLocal = (tDot11fBeaconIEs *)( pBssDescription->Result.pvIes ); + // Need to traverse whole scan list to get description for best 11d AP. + if (csrIsMacAddressEqual(pMac, (tCsrBssid *)&bssid_temp, + (tCsrBssid *) pBssDescription->Result.BssDescriptor.bssId)) + { + palCopyMemory(pMac->hHdd, pMac->scan.currentCountryBssid, + bssid_temp, sizeof(tSirMacAddr)); + // Best AP should be passed to update reg domain. + csrLearnCountryInformation( pMac, &pBssDescription->Result.BssDescriptor, + pIesLocal, eANI_BOOLEAN_FALSE ); + break; + } + pEntryTemp = pNext; + } + csrLLUnlock(&pMac->scan.scanResultList); + } //Tush: If we can find the current 11d info in any of the scan results, or // a good enough AP with the 11d info from the scan results then no need to @@ -3078,48 +3208,65 @@ void csrApplyPower2Current( tpAniSirGlobal pMac ) void csrApplyChannelPowerCountryInfo( tpAniSirGlobal pMac, tCsrChannel *pChannelList, tANI_U8 *countryCode, tANI_BOOLEAN updateRiva) { - int i; + int i, j, count, countryIndex = -1; eNVChannelEnabledType channelEnabledType; tANI_U8 numChannels = 0; tANI_U8 tempNumChannels = 0; + tANI_U8 channelIgnore = FALSE; tCsrChannel ChannelList; + if( pChannelList->numChannels ) { + for(count=0; count < MAX_COUNTRY_IGNORE; count++) + { + if(vos_mem_compare(countryCode, countryIgnoreList[count].countryCode, + VOS_COUNTRY_CODE_LEN)) + { + countryIndex = count; + break; + } + } tempNumChannels = CSR_MIN(pChannelList->numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN); /* If user doesn't want to scan the DFS channels lets trim them from the valid channel list*/ - for(i = 0; i< tempNumChannels; i++) + for(i=0; i < tempNumChannels; i++) { - if(FALSE == pMac->scan.fEnableDFSChnlScan) - { - channelEnabledType = - vos_nv_getChannelEnabledState(pChannelList->channelList[i]); - } - else - { + channelIgnore = FALSE; + if( FALSE == pMac->scan.fEnableDFSChnlScan ) + { + channelEnabledType = + vos_nv_getChannelEnabledState(pChannelList->channelList[i]); + } + else + { channelEnabledType = NV_CHANNEL_ENABLE; - } - if( NV_CHANNEL_ENABLE == channelEnabledType) - { - // Ignore the channel 165 for the country INDONESIA - if (( pChannelList->channelList[i] == 165 ) - && ( pMac->scan.fIgnore_chan165 == VOS_TRUE ) - && vos_mem_compare(countryCode, "ID", VOS_COUNTRY_CODE_LEN )) - { - continue; - } - else - { - ChannelList.channelList[numChannels] = pChannelList->channelList[i]; - numChannels++; - } - } + } + if( NV_CHANNEL_ENABLE == channelEnabledType ) + { + if( countryIndex != -1 ) + { + for(j=0; j < countryIgnoreList[countryIndex].channelCount; j++) + { + if( pChannelList->channelList[i] == + countryIgnoreList[countryIndex].channelList[j] ) + { + channelIgnore = TRUE; + break; + } + } + } + if( FALSE == channelIgnore ) + { + ChannelList.channelList[numChannels] = pChannelList->channelList[i]; + numChannels++; + } + } } - ChannelList.numChannels = numChannels; - + ChannelList.numChannels = numChannels; csrSetCfgValidChannelList(pMac, ChannelList.channelList, ChannelList.numChannels); // extend scan capability - csrSetCfgScanControlList(pMac, countryCode, &ChannelList); // build a scan list based on the channel list : channel# + active/passive scan + // build a scan list based on the channel list : channel# + active/passive scan + csrSetCfgScanControlList(pMac, countryCode, &ChannelList); /*Send msg to Lim to clear DFS channel list */ csrClearDfsChannelList(pMac); #ifdef FEATURE_WLAN_SCAN_PNO @@ -3383,13 +3530,8 @@ void csrApplyCountryInformation( tpAniSirGlobal pMac, tANI_BOOLEAN fForce ) #endif //#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR if(pMac->scan.domainIdCurrent != domainId) { - /* Regulatory Domain Changed, Purge Only scan result - * which does not have channel number belong to 11d - * channel list - * */ smsLog(pMac, LOGW, FL("Domain Changed Old %d, new %d"), pMac->scan.domainIdCurrent, domainId); - csrScanFilter11dResult(pMac); status = WDA_SetRegDomain(pMac, domainId); } if (status != eHAL_STATUS_SUCCESS) @@ -3758,6 +3900,11 @@ tANI_BOOLEAN csrLearnCountryInformation( tpAniSirGlobal pMac, tSirBssDescription if ( domainId != pMac->scan.domainIdCurrent ) { tSirMacChanInfo* pMacChnSet = (tSirMacChanInfo *)(&pIesLocal->Country.triplets[0]); + palCopyMemory( pMac->hHdd, pMac->scan.countryCode11d, pIesLocal->Country.country, + sizeof( pMac->scan.countryCode11d ) ); + csrSetCfgCountryCode(pMac, pIesLocal->Country.country); + WDA_SetRegDomain(pMac, domainId); + pMac->scan.domainIdCurrent = domainId; // Check whether AP provided the 2.4GHZ list or 5GHZ list if(CSR_IS_CHANNEL_24GHZ(pMacChnSet[0].firstChanNum)) { @@ -3769,9 +3916,6 @@ tANI_BOOLEAN csrLearnCountryInformation( tpAniSirGlobal pMac, tSirBssDescription // AP Provided the 5G Channels, Update the 2.4GHZ channel list from nv.bin csrGet24GChannels(pMac ); } - csrSetCfgCountryCode(pMac, pIesLocal->Country.country); - WDA_SetRegDomain(pMac, domainId); - pMac->scan.domainIdCurrent = domainId; } // Populate both band channel lists based on what we found in the country information... csrSetOppositeBandChannelInfo( pMac ); @@ -3802,7 +3946,7 @@ tANI_BOOLEAN csrLearnCountryInformation( tpAniSirGlobal pMac, tSirBssDescription } -static void csrSaveScanResults( tpAniSirGlobal pMac ) +static void csrSaveScanResults( tpAniSirGlobal pMac, tANI_U8 reason ) { // initialize this to FALSE. profMoveInterimScanResultsToMainList() routine // will set this to the channel where an .11d beacon is seen @@ -3814,7 +3958,7 @@ static void csrSaveScanResults( tpAniSirGlobal pMac ) // only if the applied 11d info could be found in one of the scan results pMac->scan.fCurrent11dInfoMatch = eANI_BOOLEAN_FALSE; // move the scan results from interim list to the main scan list - csrMoveTempScanResultsToMainList( pMac ); + csrMoveTempScanResultsToMainList( pMac, reason ); // Now check if we gathered any domain/country specific information // If so, we should update channel list and apply Tx power settings @@ -4031,7 +4175,7 @@ tANI_BOOLEAN csrScanComplete( tpAniSirGlobal pMac, tSirSmeScanRsp *pScanRsp ) //This check only valid here because csrSaveScanresults is not yet called fSuccess = (!csrLLIsListEmpty(&pMac->scan.tempScanResults, LL_ACCESS_LOCK)); } - csrSaveScanResults(pMac); + csrSaveScanResults(pMac, pCommand->u.scanCmd.reason); #ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR { @@ -4489,6 +4633,14 @@ static tANI_BOOLEAN csrScanProcessScanResults( tpAniSirGlobal pMac, tSmeCmd *pCo tANI_U8 cChannels = 0; //Different scan type can reach this point, we need to distinguish it +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if( eCsrScanGetLfrResult == pCommand->u.scanCmd.reason ) + { + pChannelList = NULL; + cChannels = 0; + } + else +#endif if( eCsrScanSetBGScanParam == pCommand->u.scanCmd.reason ) { //eCsrScanSetBGScanParam uses different structure @@ -4577,6 +4729,9 @@ static tANI_BOOLEAN csrScanProcessScanResults( tpAniSirGlobal pMac, tSmeCmd *pCo //HO bg scan/probe failed no need to try autonomously if(eCsrScanBgScan == pCommand->u.scanCmd.reason || eCsrScanProbeBss == pCommand->u.scanCmd.reason || +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + eCsrScanGetLfrResult == pCommand->u.scanCmd.reason || +#endif eCsrScanSetBGScanParam == pCommand->u.scanCmd.reason) { fRemoveCommand = eANI_BOOLEAN_TRUE; @@ -4696,7 +4851,11 @@ eHalStatus csrScanSmeScanResponse( tpAniSirGlobal pMac, void *pMsgBuf ) { //Not to get channel info if the scan is not a wildcard scan because //it may cause scan results got aged out incorrectly. - if( csrScanIsWildCardScan( pMac, pCommand ) && (!pCommand->u.scanCmd.u.scanRequest.p2pSearch) ) + if( csrScanIsWildCardScan( pMac, pCommand ) && (!pCommand->u.scanCmd.u.scanRequest.p2pSearch) +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + && (pCommand->u.scanCmd.reason != eCsrScanGetLfrResult) +#endif + ) { //Get the list of channels scanned if( pCommand->u.scanCmd.reason != eCsrScanUserRequest) @@ -5097,7 +5256,7 @@ eHalStatus csrSendMBScanReq( tpAniSirGlobal pMac, tANI_U16 sessionId, return( status ); } -eHalStatus csrSendMBScanResultReq( tpAniSirGlobal pMac, tScanReqParam *pScanReqParam ) +eHalStatus csrSendMBScanResultReq( tpAniSirGlobal pMac, tANI_U32 sessionId, tScanReqParam *pScanReqParam ) { eHalStatus status = eHAL_STATUS_SUCCESS; tSirSmeScanReq *pMsg; @@ -5110,12 +5269,18 @@ eHalStatus csrSendMBScanResultReq( tpAniSirGlobal pMac, tScanReqParam *pScanReqP palZeroMemory(pMac->hHdd, pMsg, msgLen); pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_SCAN_REQ); pMsg->length = pal_cpu_to_be16(msgLen); - pMsg->sessionId = 0; + pMsg->sessionId = sessionId; + pMsg->transactionId = 0; pMsg->returnFreshResults = pScanReqParam->freshScan; //Always ask for unique result pMsg->returnUniqueResults = pScanReqParam->fUniqueResult; pMsg->returnAfterFirstMatch = pScanReqParam->bReturnAfter1stMatch; status = palSendMBMessage(pMac->hHdd, pMsg); + if (!HAL_STATUS_SUCCESS(status)) + { + smsLog( pMac, LOGE, FL(" failed to send down scan req with status = %d\n"), status ); + } + } return( status ); @@ -5195,18 +5360,30 @@ eHalStatus csrScanChannels( tpAniSirGlobal pMac, tSmeCmd *pCommand ) } -eHalStatus csrScanRetrieveResult(tpAniSirGlobal pMac) +eHalStatus csrScanRetrieveResult(tpAniSirGlobal pMac, tSmeCmd *pCommand) { eHalStatus status = eHAL_STATUS_FAILURE; tScanReqParam scanReq; do { - //not a fresh scan - scanReq.freshScan = CSR_SME_SCAN_FLAGS_DELETE_CACHE; - scanReq.fUniqueResult = TRUE; - scanReq.bReturnAfter1stMatch = CSR_SCAN_RETURN_AFTER_ALL_CHANNELS; - status = csrSendMBScanResultReq(pMac, &scanReq); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (eCsrScanGetLfrResult == pCommand->u.scanCmd.reason) + { + //to get the LFR candidates from PE cache + scanReq.freshScan = SIR_BG_SCAN_RETURN_LFR_CACHED_RESULTS|SIR_BG_SCAN_PURGE_LFR_RESULTS; + scanReq.fUniqueResult = TRUE; + scanReq.bReturnAfter1stMatch = CSR_SCAN_RETURN_AFTER_ALL_CHANNELS; + } + else +#endif + { + //not a fresh scan + scanReq.freshScan = CSR_SME_SCAN_FLAGS_DELETE_CACHE; + scanReq.fUniqueResult = TRUE; + scanReq.bReturnAfter1stMatch = CSR_SCAN_RETURN_AFTER_ALL_CHANNELS; + } + status = csrSendMBScanResultReq(pMac, pCommand->sessionId, &scanReq); }while(0); return (status); @@ -5231,9 +5408,12 @@ eHalStatus csrProcessScanCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand ) switch(pCommand->u.scanCmd.reason) { +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + case eCsrScanGetLfrResult: +#endif case eCsrScanGetResult: case eCsrScanForCapsChange: //For cap change, LIM already save BSS description - status = csrScanRetrieveResult(pMac); + status = csrScanRetrieveResult(pMac, pCommand); break; case eCsrScanSetBGScanParam: status = csrProcessSetBGScanParam(pMac, pCommand); @@ -5741,6 +5921,7 @@ static void csrStaApConcTimerHandler(void *pv) tCsrScanRequest scanReq; tSmeCmd *pSendScanCmd = NULL; tANI_U8 numChn = 0; + tANI_U8 nNumChanCombinedConc = 0; tANI_U8 i, j; tCsrChannelInfo *pChnInfo = &scanReq.ChannelInfo; tANI_U8 channelToScan[WNI_CFG_VALID_CHANNEL_LIST_LEN]; @@ -5764,7 +5945,18 @@ static void csrStaApConcTimerHandler(void *pv) * the scan is delaying the time it takes for LFR to find * candidates and resulting in disconnects. */ - if ( (numChn > pMac->roam.configParam.nNumChanCombinedConc) && + + if((csrIsStaSessionConnected(pMac) && + !csrIsP2pSessionConnected(pMac))) + { + nNumChanCombinedConc = pMac->roam.configParam.nNumStaChanCombinedConc; + } + else if(csrIsP2pSessionConnected(pMac)) + { + nNumChanCombinedConc = pMac->roam.configParam.nNumP2PChanCombinedConc; + } + + if ( (numChn > nNumChanCombinedConc) && ((csrIsStaSessionConnected(pMac) && #ifdef FEATURE_WLAN_LFR (csrIsConcurrentInfraConnected(pMac) || @@ -5801,18 +5993,18 @@ static void csrStaApConcTimerHandler(void *pv) scanReq.ChannelInfo.ChannelList = NULL; } - pChnInfo->numOfChannels = pMac->roam.configParam.nNumChanCombinedConc; + pChnInfo->numOfChannels = nNumChanCombinedConc; palCopyMemory(pMac->hHdd, &channelToScan[0], &pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList[0], pChnInfo->numOfChannels * sizeof(tANI_U8)); //just send one channel pChnInfo->ChannelList = &channelToScan[0]; - for (i = 0, j = pMac->roam.configParam.nNumChanCombinedConc; i < (numChn-pMac->roam.configParam.nNumChanCombinedConc); i++, j++) + for (i = 0, j = nNumChanCombinedConc; i < (numChn-nNumChanCombinedConc); i++, j++) { pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList[i] = pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList[j]; //Move all the channels one step } - pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels = numChn - pMac->roam.configParam.nNumChanCombinedConc; //reduce outstanding # of channels to be scanned + pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels = numChn - nNumChanCombinedConc; //reduce outstanding # of channels to be scanned scanReq.BSSType = eCSR_BSS_TYPE_ANY; //Modify callers parameters in case of concurrency @@ -6349,6 +6541,9 @@ tANI_BOOLEAN csrScanRemoveFreshScanCommand(tpAniSirGlobal pMac, tANI_U8 sessionI { switch(pCommand->u.scanCmd.reason) { +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + case eCsrScanGetLfrResult: +#endif case eCsrScanGetResult: case eCsrScanSetBGScanParam: case eCsrScanBGScanAbort: @@ -7002,7 +7197,7 @@ void csrSetCfgScanControlList( tpAniSirGlobal pMac, tANI_U8 *countryCode, tCsrCh if (found) // insert a pair(channel#, flag) { - pControlList[j+1] = csrGetScanType(pMac, pControlList[j]); + pControlList[j+1] = csrGetScanType(pMac, pControlList[j]); found = FALSE; // reset the flag } @@ -7255,6 +7450,176 @@ tANI_BOOLEAN csrRoamIsValidChannel( tpAniSirGlobal pMac, tANI_U8 channel ) return fValid; } +eHalStatus csrScanSavePreferredNetworkFound(tpAniSirGlobal pMac, + tSirPrefNetworkFoundInd *pPrefNetworkFoundInd) +{ + v_U32_t uLen = 0; + tpSirProbeRespBeacon pParsedFrame; + tCsrScanResult *pScanResult = NULL; + tSirBssDescription *pBssDescr = NULL; + tANI_BOOLEAN fDupBss; + tDot11fBeaconIEs *pIesLocal = NULL; + tAniSSID tmpSsid; + v_TIME_t timer=0; + tpSirMacMgmtHdr macHeader = (tpSirMacMgmtHdr)pPrefNetworkFoundInd->data; + + pParsedFrame = + (tpSirProbeRespBeacon) vos_mem_malloc(sizeof(tSirProbeRespBeacon)); + + if (NULL == pParsedFrame) + { + smsLog(pMac, LOGE, FL(" fail to allocate memory for frame")); + return eHAL_STATUS_RESOURCES; + } + + if ( pPrefNetworkFoundInd->frameLength <= SIR_MAC_HDR_LEN_3A ) + { + smsLog(pMac, LOGE, + FL("Not enough bytes in PNO indication probe resp frame! length=%d"), + pPrefNetworkFoundInd->frameLength); + vos_mem_free(pParsedFrame); + return eHAL_STATUS_FAILURE; + } + + if (sirConvertProbeFrame2Struct(pMac, + &pPrefNetworkFoundInd->data[SIR_MAC_HDR_LEN_3A], + pPrefNetworkFoundInd->frameLength - SIR_MAC_HDR_LEN_3A, + pParsedFrame) != eSIR_SUCCESS || + !pParsedFrame->ssidPresent) + { + smsLog(pMac, LOGE, + FL("Parse error ProbeResponse, length=%d"), + pPrefNetworkFoundInd->frameLength); + vos_mem_free(pParsedFrame); + return eHAL_STATUS_FAILURE; + } + //24 byte MAC header and 12 byte to ssid IE + if (pPrefNetworkFoundInd->frameLength > + (SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_SSID_OFFSET)) + { + uLen = pPrefNetworkFoundInd->frameLength - + (SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_SSID_OFFSET); + } + + if ( !HAL_STATUS_SUCCESS(palAllocateMemory( pMac->hHdd, + (void **)&pScanResult, sizeof(tCsrScanResult) + uLen )) ) + { + smsLog(pMac, LOGE, FL(" fail to allocate memory for frame")); + vos_mem_free(pParsedFrame); + return eHAL_STATUS_RESOURCES; + } + + palZeroMemory( pMac->hHdd, pScanResult, sizeof(tCsrScanResult) + uLen ); + pBssDescr = &pScanResult->Result.BssDescriptor; + /** + * Length of BSS desription is without length of + * length itself and length of pointer + * that holds the next BSS description + */ + pBssDescr->length = (tANI_U16)( + sizeof(tSirBssDescription) - sizeof(tANI_U16) - + sizeof(tANI_U32) + uLen); + if (pParsedFrame->dsParamsPresent) + { + pBssDescr->channelId = pParsedFrame->channelNumber; + } + else if (pParsedFrame->HTInfo.present) + { + pBssDescr->channelId = pParsedFrame->HTInfo.primaryChannel; + } + else + { + pBssDescr->channelId = pParsedFrame->channelNumber; + } + + if ((pBssDescr->channelId > 0) && (pBssDescr->channelId < 15)) + { + int i; + // 11b or 11g packet + // 11g iff extended Rate IE is present or + // if there is an A rate in suppRate IE + for (i = 0; i < pParsedFrame->supportedRates.numRates; i++) + { + if (sirIsArate(pParsedFrame->supportedRates.rate[i] & 0x7f)) + { + pBssDescr->nwType = eSIR_11G_NW_TYPE; + break; + } + } + if (pParsedFrame->extendedRatesPresent) + { + pBssDescr->nwType = eSIR_11G_NW_TYPE; + } + } + else + { + // 11a packet + pBssDescr->nwType = eSIR_11A_NW_TYPE; + } + + pBssDescr->sinr = 0; + pBssDescr->rssi = -1 * pPrefNetworkFoundInd->rssi; + pBssDescr->beaconInterval = pParsedFrame->beaconInterval; + pBssDescr->timeStamp[0] = pParsedFrame->timeStamp[0]; + pBssDescr->timeStamp[1] = pParsedFrame->timeStamp[1]; + pBssDescr->capabilityInfo = *((tANI_U16 *)&pParsedFrame->capabilityInfo); + palCopyMemory( pMac->hHdd, (tANI_U8 *) &pBssDescr->bssId, + (tANI_U8 *) macHeader->bssId, + sizeof(tSirMacAddr)); + pBssDescr->nReceivedTime = (tANI_TIMESTAMP)palGetTickCount(pMac->hHdd); + + smsLog( pMac, LOG2, "(%s):Bssid= %02x-%02x-%02x-%02x-%02x-%02x " + "chan= %d, rssi = %d", __func__, + pBssDescr->bssId[ 0 ], pBssDescr->bssId[ 1 ], + pBssDescr->bssId[ 2 ], pBssDescr->bssId[ 3 ], + pBssDescr->bssId[ 4 ], pBssDescr->bssId[ 5 ], + pBssDescr->channelId, + pBssDescr->rssi ); + + //IEs + if (uLen) + { + vos_mem_copy( &pBssDescr->ieFields, + pPrefNetworkFoundInd->data + + (SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_SSID_OFFSET), + uLen); + } + + pIesLocal = (tDot11fBeaconIEs *)( pScanResult->Result.pvIes ); + if ( !pIesLocal && + (!HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, + &pScanResult->Result.BssDescriptor, &pIesLocal))) ) + { + smsLog(pMac, LOGE, FL(" Cannot parse IEs")); + csrFreeScanResultEntry(pMac, pScanResult); + vos_mem_free(pParsedFrame); + return eHAL_STATUS_RESOURCES; + } + + fDupBss = csrRemoveDupBssDescription( pMac, + &pScanResult->Result.BssDescriptor, pIesLocal, &tmpSsid , &timer); + //Check whether we have reach out limit + if ( CSR_SCAN_IS_OVER_BSS_LIMIT(pMac) ) + { + //Limit reach + smsLog(pMac, LOGE, FL(" BSS limit reached")); + //Free the resources + if( (pScanResult->Result.pvIes == NULL) && pIesLocal ) + { + palFreeMemory(pMac->hHdd, pIesLocal); + } + csrFreeScanResultEntry(pMac, pScanResult); + vos_mem_free(pParsedFrame); + return eHAL_STATUS_RESOURCES; + } + //Add to scan cache + csrScanAddResult(pMac, pScanResult, pIesLocal); + + vos_mem_free(pParsedFrame); + + return eHAL_STATUS_SUCCESS; +} + #ifdef FEATURE_WLAN_LFR void csrInitOccupiedChannelsList(tpAniSirGlobal pMac) { diff --git a/drivers/staging/prima/CORE/SME/src/csr/csrInsideApi.h b/drivers/staging/prima/CORE/SME/src/csr/csrInsideApi.h index 2a02e3ff80d..1a8d5cf8550 100644 --- a/drivers/staging/prima/CORE/SME/src/csr/csrInsideApi.h +++ b/drivers/staging/prima/CORE/SME/src/csr/csrInsideApi.h @@ -76,7 +76,8 @@ #define CSR_REST_TIME_CONC 100 -#define CSR_NUM_CHAN_COMBINED_CONC 1 +#define CSR_NUM_STA_CHAN_COMBINED_CONC 3 +#define CSR_NUM_P2P_CHAN_COMBINED_CONC 1 #endif #define CSR_MAX_NUM_SUPPORTED_CHANNELS 55 diff --git a/drivers/staging/prima/CORE/SME/src/csr/csrNeighborRoam.c b/drivers/staging/prima/CORE/SME/src/csr/csrNeighborRoam.c index 57f1f67ab65..694e5cfc21e 100644 --- a/drivers/staging/prima/CORE/SME/src/csr/csrNeighborRoam.c +++ b/drivers/staging/prima/CORE/SME/src/csr/csrNeighborRoam.c @@ -270,7 +270,11 @@ static void csrNeighborRoamTriggerHandoff(tpAniSirGlobal pMac, tpCsrNeighborRoamControlInfo pNeighborRoamInfo) { #ifdef WLAN_FEATURE_VOWIFI_11R - if (pNeighborRoamInfo->is11rAssoc) + if ((pNeighborRoamInfo->is11rAssoc) +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + && !csrRoamIsRoamOffloadScanEnabled(pMac) +#endif + ) { if (eCSR_NEIGHBOR_ROAM_STATE_REPORT_SCAN == pNeighborRoamInfo->neighborRoamState) { @@ -286,7 +290,11 @@ static void csrNeighborRoamTriggerHandoff(tpAniSirGlobal pMac, #endif #ifdef FEATURE_WLAN_CCX - if (pNeighborRoamInfo->isCCXAssoc) + if ((pNeighborRoamInfo->isCCXAssoc) +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + && !csrRoamIsRoamOffloadScanEnabled(pMac) +#endif + ) { if (eCSR_NEIGHBOR_ROAM_STATE_REPORT_SCAN == pNeighborRoamInfo->neighborRoamState) { @@ -303,7 +311,11 @@ static void csrNeighborRoamTriggerHandoff(tpAniSirGlobal pMac, #ifdef FEATURE_WLAN_LFR if (csrRoamIsFastRoamEnabled(pMac, CSR_SESSION_ID_INVALID)) { - if (eCSR_NEIGHBOR_ROAM_STATE_REPORT_SCAN == pNeighborRoamInfo->neighborRoamState) + if ((eCSR_NEIGHBOR_ROAM_STATE_REPORT_SCAN == pNeighborRoamInfo->neighborRoamState) +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + || csrRoamIsRoamOffloadScanEnabled(pMac) +#endif + ) { csrNeighborRoamIssuePreauthReq(pMac); } @@ -337,6 +349,12 @@ VOS_STATUS csrNeighborRoamUpdateFastRoamingEnabled(tpAniSirGlobal pMac, const v_ { if (VOS_TRUE == fastRoamEnabled) { +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pMac->roam.configParam.isRoamOffloadScanEnabled) + { + csrRoamOffloadScan(pMac, ROAM_SCAN_OFFLOAD_START, REASON_CONNECT); + } else { +#endif NEIGHBOR_ROAM_DEBUG(pMac, LOG2, FL("Registering neighbor lookup DOWN event with TL, RSSI = %d"), pNeighborRoamInfo->currentNeighborLookupThreshold); /* Register Neighbor Lookup threshold callback with TL for DOWN event only */ @@ -350,12 +368,24 @@ VOS_STATUS csrNeighborRoamUpdateFastRoamingEnabled(tpAniSirGlobal pMac, const v_ smsLog(pMac, LOGW, FL(" Couldn't register csrNeighborRoamNeighborLookupDOWNCallback with TL: Status = %d"), vosStatus); vosStatus = VOS_STATUS_E_FAILURE; } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + } +#endif } else if (VOS_FALSE == fastRoamEnabled) { NEIGHBOR_ROAM_DEBUG(pMac, LOG2, FL("Currently in CONNECTED state, so deregister all events")); /* De-register existing lookup UP/DOWN, Rssi indications */ +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pMac->roam.configParam.isRoamOffloadScanEnabled) + { + csrRoamOffloadScan(pMac, ROAM_SCAN_OFFLOAD_STOP, REASON_DISCONNECTED); + } else { +#endif csrNeighborRoamDeregAllRssiIndication(pMac); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + } +#endif } } else if (eCSR_NEIGHBOR_ROAM_STATE_INIT == pNeighborRoamInfo->neighborRoamState) @@ -382,6 +412,12 @@ VOS_STATUS csrNeighborRoamUpdateCcxModeEnabled(tpAniSirGlobal pMac, const v_BOOL { NEIGHBOR_ROAM_DEBUG(pMac, LOG2, FL("Registering neighbor lookup DOWN event with TL, RSSI = %d"), pNeighborRoamInfo->currentNeighborLookupThreshold); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pMac->roam.configParam.isRoamOffloadScanEnabled) + { + csrRoamOffloadScan(pMac, ROAM_SCAN_OFFLOAD_START, REASON_CONNECT); + } else { +#endif /* Register Neighbor Lookup threshold callback with TL for DOWN event only */ vosStatus = WLANTL_RegRSSIIndicationCB(pMac->roam.gVosContext, (v_S7_t)pNeighborRoamInfo->currentNeighborLookupThreshold * (-1), WLANTL_HO_THRESHOLD_DOWN, @@ -393,12 +429,24 @@ VOS_STATUS csrNeighborRoamUpdateCcxModeEnabled(tpAniSirGlobal pMac, const v_BOOL smsLog(pMac, LOGW, FL(" Couldn't register csrNeighborRoamNeighborLookupDOWNCallback with TL: Status = %d"), vosStatus); vosStatus = VOS_STATUS_E_FAILURE; } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + } +#endif } else if (VOS_FALSE == ccxMode) { NEIGHBOR_ROAM_DEBUG(pMac, LOG2, FL("Currently in CONNECTED state, so deregister all events")); /* De-register existing lookup UP/DOWN, Rssi indications */ +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pMac->roam.configParam.isRoamOffloadScanEnabled) + { + csrRoamOffloadScan(pMac, ROAM_SCAN_OFFLOAD_STOP, REASON_DISCONNECTED); + } else { +#endif csrNeighborRoamDeregAllRssiIndication(pMac); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + } +#endif } } else if (eCSR_NEIGHBOR_ROAM_STATE_INIT == pNeighborRoamInfo->neighborRoamState) @@ -858,6 +906,12 @@ tANI_BOOLEAN csrNeighborRoamIsPreauthCandidate(tpAniSirGlobal pMac, tSirMacAddr tANI_U8 i = 0; tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo; +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (csrRoamIsRoamOffloadScanEnabled(pMac)) + { + return eANI_BOOLEAN_TRUE; + } +#endif if (0 == pNeighborRoamInfo->FTRoamInfo.preAuthFailList.numMACAddress) return eANI_BOOLEAN_TRUE; @@ -1053,32 +1107,43 @@ eHalStatus csrNeighborRoamPreauthRspHandler(tpAniSirGlobal pMac, tSirRetStatus l if (eHAL_STATUS_SUCCESS == csrNeighborRoamIssuePreauthReq(pMac)) goto DEQ_PREAUTH; - CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_REPORT_SCAN); - - /* Register Neighbor Lookup threshold callback with TL for UP event now */ - NEIGHBOR_ROAM_DEBUG(pMac, LOGE, FL("No more pre-auth candidates-" - "register UP indication with TL. RSSI = %d,"), NEIGHBOR_ROAM_LOOKUP_UP_THRESHOLD * (-1)); - - vosStatus = WLANTL_RegRSSIIndicationCB(pMac->roam.gVosContext, - (v_S7_t)NEIGHBOR_ROAM_LOOKUP_UP_THRESHOLD * (-1), - WLANTL_HO_THRESHOLD_UP, - csrNeighborRoamNeighborLookupUPCallback, - VOS_MODULE_ID_SME, pMac); - if(!VOS_IS_STATUS_SUCCESS(vosStatus)) +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (csrRoamIsRoamOffloadScanEnabled(pMac)) { - //err msg - smsLog(pMac, LOGE, FL(" Couldn't register csrNeighborRoamNeighborLookupCallback UP event with TL: Status = %d"), status); - } - - /* Start the neighbor results refresh timer and transition to REPORT_SCAN state to perform scan again */ - status = palTimerStart(pMac->hHdd, pNeighborRoamInfo->neighborResultsRefreshTimer, - pNeighborRoamInfo->cfgParams.neighborResultsRefreshPeriod * PAL_TIMER_TO_MS_UNIT, - eANI_BOOLEAN_FALSE); - if (eHAL_STATUS_SUCCESS != status) + csrRoamOffloadScan(pMac, ROAM_SCAN_OFFLOAD_RESTART, REASON_PREAUTH_FAILED_FOR_ALL); + CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_CONNECTED); + } else { - smsLog(pMac, LOGE, FL("Neighbor results refresh timer start failed with status %d"), status); +#endif + CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_REPORT_SCAN); + + /* Register Neighbor Lookup threshold callback with TL for UP event now */ + NEIGHBOR_ROAM_DEBUG(pMac, LOGE, FL("No more pre-auth candidates-" + "register UP indication with TL. RSSI = %d,"), NEIGHBOR_ROAM_LOOKUP_UP_THRESHOLD * (-1)); + + vosStatus = WLANTL_RegRSSIIndicationCB(pMac->roam.gVosContext, + (v_S7_t)NEIGHBOR_ROAM_LOOKUP_UP_THRESHOLD * (-1), + WLANTL_HO_THRESHOLD_UP, + csrNeighborRoamNeighborLookupUPCallback, + VOS_MODULE_ID_SME, pMac); + if(!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + //err msg + smsLog(pMac, LOGE, FL(" Couldn't register csrNeighborRoamNeighborLookupCallback UP event with TL: Status = %d"), status); + } + + /* Start the neighbor results refresh timer and transition to REPORT_SCAN state to perform scan again */ + status = palTimerStart(pMac->hHdd, pNeighborRoamInfo->neighborResultsRefreshTimer, + pNeighborRoamInfo->cfgParams.neighborResultsRefreshPeriod * PAL_TIMER_TO_MS_UNIT, + eANI_BOOLEAN_FALSE); + if (eHAL_STATUS_SUCCESS != status) + { + smsLog(pMac, LOGE, FL("Neighbor results refresh timer start failed with status %d"), status); + } } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD } +#endif DEQ_PREAUTH: csrRoamDequeuePreauth(pMac); @@ -1123,14 +1188,16 @@ eHalStatus csrNeighborRoamPrepareScanProfileFilter(tpAniSirGlobal pMac, tCsrScan smsLog(pMac, LOGE, FL("Scan Filter SSID mem alloc failed")); return eHAL_STATUS_FAILED_ALLOC; } - vos_mem_zero(pScanFilter->SSIDs.SSIDList, sizeof(tCsrSSIDInfo)); pScanFilter->SSIDs.SSIDList->handoffPermitted = 1; pScanFilter->SSIDs.SSIDList->ssidHidden = 0; pScanFilter->SSIDs.SSIDList->SSID.length = pCurProfile->SSID.length; vos_mem_copy((void *)pScanFilter->SSIDs.SSIDList->SSID.ssId, (void *)pCurProfile->SSID.ssId, pCurProfile->SSID.length); - NEIGHBOR_ROAM_DEBUG(pMac, LOGE, FL("Filtering for SSID %s from scan results.. SSID Length = %d"), - pScanFilter->SSIDs.SSIDList->SSID.ssId, pScanFilter->SSIDs.SSIDList->SSID.length); + NEIGHBOR_ROAM_DEBUG(pMac, LOGE, FL("Filtering for SSID %.*s from scan results," + "length of SSID = %u"), + pScanFilter->SSIDs.SSIDList->SSID.length, + pScanFilter->SSIDs.SSIDList->SSID.ssId, + pScanFilter->SSIDs.SSIDList->SSID.length); pScanFilter->authType.numEntries = 1; pScanFilter->authType.authType[0] = pCurProfile->AuthType; @@ -1272,7 +1339,11 @@ static tANI_BOOLEAN csrNeighborRoamProcessScanResults(tpAniSirGlobal pMac, /* This condition is to ensure to roam to an AP with better RSSI. if the value of RoamRssiDiff is Zero, this feature * is disabled and we continue to roam without any check*/ - if(RoamRssiDiff > 0) + if ((RoamRssiDiff > 0) +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + && !csrRoamIsRoamOffloadScanEnabled(pMac) +#endif + ) { /* * If RSSI is lower than the lookup threshold, then continue. @@ -1328,51 +1399,58 @@ static tANI_BOOLEAN csrNeighborRoamProcessScanResults(tpAniSirGlobal pMac, #endif /* WLAN_FEATURE_VOWIFI_11R */ #ifdef FEATURE_WLAN_CCX - if (pNeighborRoamInfo->isCCXAssoc) +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (!csrRoamIsRoamOffloadScanEnabled(pMac)) { - if (!csrNeighborRoamIsPreauthCandidate(pMac, pScanResult->BssDescriptor.bssId)) - { - smsLog(pMac, LOGE, FL("BSSID present in pre-auth fail list.. Ignoring")); - continue; - } - } - if ((pScanResult->BssDescriptor.QBSSLoad_present) && - (pScanResult->BssDescriptor.QBSSLoad_avail)) - { - if (pNeighborRoamInfo->isVOAdmitted) - { - smsLog(pMac, LOG1, FL("New AP has %x BW available"), (unsigned int)pScanResult->BssDescriptor.QBSSLoad_avail); - smsLog(pMac, LOG1, FL("We need %x BW available"),(unsigned int)pNeighborRoamInfo->MinQBssLoadRequired); - if (pScanResult->BssDescriptor.QBSSLoad_avail < pNeighborRoamInfo->MinQBssLoadRequired) - { - VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, - "[INFOLOG]BSSID : %02x:%02x:%02x:%02x:%02x:%02x has no bandwidth ignoring..not adding to roam list", - pScanResult->BssDescriptor.bssId[0], - pScanResult->BssDescriptor.bssId[1], - pScanResult->BssDescriptor.bssId[2], - pScanResult->BssDescriptor.bssId[3], - pScanResult->BssDescriptor.bssId[4], - pScanResult->BssDescriptor.bssId[5]); - continue; - } - } - } - else - { - smsLog(pMac, LOGE, FL("No QBss %x %x"), (unsigned int)pScanResult->BssDescriptor.QBSSLoad_avail, (unsigned int)pScanResult->BssDescriptor.QBSSLoad_present); - if (pNeighborRoamInfo->isVOAdmitted) - { - VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, - "[INFOLOG]BSSID : %02x:%02x:%02x:%02x:%02x:%02x has no QBSSLoad IE, ignoring..not adding to roam list", - pScanResult->BssDescriptor.bssId[0], - pScanResult->BssDescriptor.bssId[1], - pScanResult->BssDescriptor.bssId[2], - pScanResult->BssDescriptor.bssId[3], - pScanResult->BssDescriptor.bssId[4], - pScanResult->BssDescriptor.bssId[5]); - continue; - } +#endif + if (pNeighborRoamInfo->isCCXAssoc) + { + if (!csrNeighborRoamIsPreauthCandidate(pMac, pScanResult->BssDescriptor.bssId)) + { + smsLog(pMac, LOGE, FL("BSSID present in pre-auth fail list.. Ignoring")); + continue; + } + } + if ((pScanResult->BssDescriptor.QBSSLoad_present) && + (pScanResult->BssDescriptor.QBSSLoad_avail)) + { + if (pNeighborRoamInfo->isVOAdmitted) + { + smsLog(pMac, LOG1, FL("New AP has %x BW available"), (unsigned int)pScanResult->BssDescriptor.QBSSLoad_avail); + smsLog(pMac, LOG1, FL("We need %x BW available"),(unsigned int)pNeighborRoamInfo->MinQBssLoadRequired); + if (pScanResult->BssDescriptor.QBSSLoad_avail < pNeighborRoamInfo->MinQBssLoadRequired) + { + VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "[INFOLOG]BSSID : %02x:%02x:%02x:%02x:%02x:%02x has no bandwidth ignoring..not adding to roam list", + pScanResult->BssDescriptor.bssId[0], + pScanResult->BssDescriptor.bssId[1], + pScanResult->BssDescriptor.bssId[2], + pScanResult->BssDescriptor.bssId[3], + pScanResult->BssDescriptor.bssId[4], + pScanResult->BssDescriptor.bssId[5]); + continue; + } + } + } + else + { + smsLog(pMac, LOGE, FL("No QBss %x %x"), (unsigned int)pScanResult->BssDescriptor.QBSSLoad_avail, (unsigned int)pScanResult->BssDescriptor.QBSSLoad_present); + if (pNeighborRoamInfo->isVOAdmitted) + { + VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "[INFOLOG]BSSID : %02x:%02x:%02x:%02x:%02x:%02x has no QBSSLoad IE, ignoring..not adding to roam list", + pScanResult->BssDescriptor.bssId[0], + pScanResult->BssDescriptor.bssId[1], + pScanResult->BssDescriptor.bssId[2], + pScanResult->BssDescriptor.bssId[3], + pScanResult->BssDescriptor.bssId[4], + pScanResult->BssDescriptor.bssId[5]); + continue; + } + } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD } +#endif #endif /* FEATURE_WLAN_CCX */ #ifdef FEATURE_WLAN_LFR @@ -1390,7 +1468,11 @@ static tANI_BOOLEAN csrNeighborRoamProcessScanResults(tpAniSirGlobal pMac, /* If the received timestamp in BSS description is earlier than the scan request timestamp, skip * this result */ - if (pNeighborRoamInfo->scanRequestTimeStamp >= pScanResult->BssDescriptor.nReceivedTime) + if ((pNeighborRoamInfo->scanRequestTimeStamp >= pScanResult->BssDescriptor.nReceivedTime) +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + && !csrRoamIsRoamOffloadScanEnabled(pMac) +#endif + ) { smsLog(pMac, LOGE, FL("Ignoring BSS as it is older than the scan request timestamp")); continue; @@ -1422,7 +1504,11 @@ static tANI_BOOLEAN csrNeighborRoamProcessScanResults(tpAniSirGlobal pMac, csrLLInsertTail(&pNeighborRoamInfo->roamableAPList, &pBssInfo->List, LL_ACCESS_LOCK); #if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR) - if (abs(abs(CurrAPRssi) - abs(pScanResult->BssDescriptor.rssi)) >= immediateRoamRssiDiff) + if ((abs(abs(CurrAPRssi) - abs(pScanResult->BssDescriptor.rssi)) >= immediateRoamRssiDiff) +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + && !csrRoamIsRoamOffloadScanEnabled(pMac) +#endif + ) { VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "%s: [INFOLOG] potential candidate to roam immediately (diff=%d, expected=%d)", @@ -1430,6 +1516,14 @@ static tANI_BOOLEAN csrNeighborRoamProcessScanResults(tpAniSirGlobal pMac, immediateRoamRssiDiff); roamNow = eANI_BOOLEAN_TRUE; } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + /* If we are here means, FW already found candidates to roam, so we are + good to go with pre-auth */ + if(csrRoamIsRoamOffloadScanEnabled(pMac)) + { + roamNow = eANI_BOOLEAN_TRUE; + } +#endif #endif } @@ -1521,17 +1615,20 @@ static VOS_STATUS csrNeighborRoamHandleEmptyScanResult(tpAniSirGlobal pMac) { pNeighborRoamInfo->uEmptyScanCount = eFifthEmptyScan; } - if ((abs(pNeighborRoamInfo->lookupDOWNRssi) > - abs(pNeighborRoamInfo->cfgParams.neighborReassocThreshold)) && + if (((0 != pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels) || + (abs(pNeighborRoamInfo->lookupDOWNRssi) > + abs(pNeighborRoamInfo->cfgParams.neighborReassocThreshold))) && ((pNeighborRoamInfo->uEmptyScanCount == eSecondEmptyScan) || (pNeighborRoamInfo->uEmptyScanCount == eFourthEmptyScan))) { /* * If the scan was triggered due to lookupDOWNRssi > reassoc threshold, * then it would be a contiguous scan on all valid non-DFS channels. - * In this mode, there is no need to trigger an immediate scan upon - * empty scan results for the second and fourth time (which would - * be equivalent to scanning on channels in non-occupied list). + * If channels are configured in INI, then only those channels need + * to be scanned. + * In either of these modes, there is no need to trigger an immediate + * scan upon empty scan results for the second and fourth time (which + * would be equivalent to scanning on channels in non-occupied list). * Incrementing uEmptyScanCount will correspond to skipping this step. * NOTE: double increment of uEmptyScanCount corresponds to completion * of scans on all valid channels. @@ -1631,7 +1728,7 @@ static VOS_STATUS csrNeighborRoamHandleEmptyScanResult(tpAniSirGlobal pMac) (pNeighborRoamInfo->cfgParams.emptyScanRefreshPeriod)); } } - else + else if (eThirdEmptyScan == pNeighborRoamInfo->uEmptyScanCount) { /* Start neighbor scan results refresh timer */ if (eHAL_STATUS_SUCCESS != @@ -1673,7 +1770,11 @@ static eHalStatus csrNeighborRoamProcessScanComplete (tpAniSirGlobal pMac) #if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR) /* If the state is REPORT_SCAN, then this must be the scan after the REPORT_QUERY state. So, we should use the BSSID filter made out of neighbor reports */ - if (eCSR_NEIGHBOR_ROAM_STATE_REPORT_SCAN == pNeighborRoamInfo->neighborRoamState) + if ((eCSR_NEIGHBOR_ROAM_STATE_REPORT_SCAN == pNeighborRoamInfo->neighborRoamState) +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + && (!csrRoamIsRoamOffloadScanEnabled(pMac)) +#endif + ) { hstatus = csrNeighborRoamBssIdScanFilter(pMac, &scanFilter); NEIGHBOR_ROAM_DEBUG(pMac, LOGW, FL("11R or CCX Association: Prepare scan filter status with neighbor AP = %d"), hstatus); @@ -1703,8 +1804,12 @@ static eHalStatus csrNeighborRoamProcessScanComplete (tpAniSirGlobal pMac) tempVal = csrLLCount(&pNeighborRoamInfo->roamableAPList); - switch(pNeighborRoamInfo->neighborRoamState) +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if(!csrRoamIsRoamOffloadScanEnabled(pMac)) { +#endif + switch(pNeighborRoamInfo->neighborRoamState) + { case eCSR_NEIGHBOR_ROAM_STATE_CFG_CHAN_LIST_SCAN: if (tempVal) { @@ -1783,7 +1888,10 @@ static eHalStatus csrNeighborRoamProcessScanComplete (tpAniSirGlobal pMac) // Lets just exit out silently. return eHAL_STATUS_SUCCESS; + } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD } +#endif if (tempVal) { @@ -1791,21 +1899,28 @@ static eHalStatus csrNeighborRoamProcessScanComplete (tpAniSirGlobal pMac) if (roamNow) { - NEIGHBOR_ROAM_DEBUG(pMac, LOG2, - FL("Immediate roam-deregister UP indication. RSSI = %d"), - NEIGHBOR_ROAM_LOOKUP_UP_THRESHOLD * (-1)); - - vosStatus = WLANTL_DeregRSSIIndicationCB(pMac->roam.gVosContext, - (v_S7_t)NEIGHBOR_ROAM_LOOKUP_UP_THRESHOLD * (-1), - WLANTL_HO_THRESHOLD_UP, - csrNeighborRoamNeighborLookupUPCallback, - VOS_MODULE_ID_SME); - - if(!VOS_IS_STATUS_SUCCESS(vosStatus)) +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if(!csrRoamIsRoamOffloadScanEnabled(pMac)) { - smsLog(pMac, LOGW, - FL("Couldn't deregister lookup UP callback with TL: Status = %d"), vosStatus); +#endif + NEIGHBOR_ROAM_DEBUG(pMac, LOG2, + FL("Immediate roam-deregister UP indication. RSSI = %d"), + NEIGHBOR_ROAM_LOOKUP_UP_THRESHOLD * (-1)); + + vosStatus = WLANTL_DeregRSSIIndicationCB(pMac->roam.gVosContext, + (v_S7_t)NEIGHBOR_ROAM_LOOKUP_UP_THRESHOLD * (-1), + WLANTL_HO_THRESHOLD_UP, + csrNeighborRoamNeighborLookupUPCallback, + VOS_MODULE_ID_SME); + + if(!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + smsLog(pMac, LOGW, + FL("Couldn't deregister lookup UP callback with TL: Status = %d"), vosStatus); + } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD } +#endif csrNeighborRoamTriggerHandoff(pMac, pNeighborRoamInfo); return eHAL_STATUS_SUCCESS; @@ -1841,6 +1956,18 @@ static eHalStatus csrNeighborRoamProcessScanComplete (tpAniSirGlobal pMac) } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +if (csrRoamIsRoamOffloadScanEnabled(pMac)) + { + if (!tempVal || !roamNow) + { + /* There is no candidate or We are not roaming Now. + * Inform the FW to restart Roam Offload Scan */ + csrRoamOffloadScan(pMac, ROAM_SCAN_OFFLOAD_RESTART, REASON_NO_CAND_FOUND_OR_NOT_ROAMING_NOW); + CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_CONNECTED); + } + } +#endif return eHAL_STATUS_SUCCESS; } @@ -1872,13 +1999,28 @@ static eHalStatus csrNeighborRoamScanRequestCallback(tHalHandle halHandle, void tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo; tANI_U8 currentChanIndex; eHalStatus hstatus; +#ifdef FEATURE_WLAN_LFR + tANI_U32 sessionId = CSR_SESSION_ID_INVALID; + if (NULL != pContext) + { + sessionId = *((tANI_U32*)pContext); + if (!csrRoamIsFastRoamEnabled(pMac,sessionId)) + { + smsLog(pMac, LOGE, FL("Received when fast roam is disabled. Ignore it")); + vos_mem_free(pContext); + return eHAL_STATUS_SUCCESS; + } + } +#endif pMac->roam.neighborRoamInfo.scanRspPending = eANI_BOOLEAN_FALSE; /* This can happen when we receive a UP event from TL in any of the scan states. Silently ignore it */ if (eCSR_NEIGHBOR_ROAM_STATE_CONNECTED == pNeighborRoamInfo->neighborRoamState) { smsLog(pMac, LOGE, FL("Received in CONNECTED state. Must be because a UP event from TL after issuing scan request. Ignore it")); + if (NULL != pContext) + vos_mem_free(pContext); return eHAL_STATUS_SUCCESS; } @@ -1893,6 +2035,8 @@ static eHalStatus csrNeighborRoamScanRequestCallback(tHalHandle halHandle, void else { smsLog(pMac, LOG1, FL("Received during clean-up. Silently ignore scan completion event.")); + if (NULL != pContext) + vos_mem_free(pContext); return eHAL_STATUS_SUCCESS; } @@ -1910,6 +2054,8 @@ static eHalStatus csrNeighborRoamScanRequestCallback(tHalHandle halHandle, void if (eHAL_STATUS_SUCCESS != hstatus) { smsLog(pMac, LOGE, FL("Neighbor scan process complete failed with status %d"), hstatus); + if (NULL != pContext) + vos_mem_free(pContext); return eHAL_STATUS_FAILURE; } } @@ -1928,11 +2074,64 @@ static eHalStatus csrNeighborRoamScanRequestCallback(tHalHandle halHandle, void vos_mem_free(pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList); pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList = NULL; pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.numOfChannels = 0; + if (NULL != pContext) + vos_mem_free(pContext); return eHAL_STATUS_FAILURE; } } + + if (NULL != pContext) + vos_mem_free(pContext); + return eHAL_STATUS_SUCCESS; +} + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +/* --------------------------------------------------------------------------- + + \fn csrNeighborRoamScanResultRequestCallback + + \brief This function is the callback function registered in csrScanRequestLfrResult() to + indicate the completion of scan. If scan is completed for all the channels in + the channel list, this function gets the scan result and treats them as candidates + + \param halHandle - The handle returned by macOpen. + pContext - not used + scanId - not used + status - not used + + \return eHAL_STATUS_SUCCESS on success, corresponding error code otherwise + +---------------------------------------------------------------------------*/ +static eHalStatus csrNeighborRoamScanResultRequestCallback(tHalHandle halHandle, void *pContext, + tANI_U32 scanId, eCsrScanStatus status) +{ + tpAniSirGlobal pMac = (tpAniSirGlobal) halHandle; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo; + eHalStatus hstatus; + + smsLog(pMac, LOG2, FL("called ")); + pMac->roam.neighborRoamInfo.scanRspPending = eANI_BOOLEAN_FALSE; + + /* we must be in connected state, if not ignore it */ + if (eCSR_NEIGHBOR_ROAM_STATE_CONNECTED != pNeighborRoamInfo->neighborRoamState) + { + smsLog(pMac, LOGW, FL("Received in not CONNECTED state. Ignore it")); + return eHAL_STATUS_SUCCESS; + } + + /* Now we have completed scanning the channel list. We have get the result by applying appropriate filter + sort the results based on neighborScore and RSSI and select the best candidate out of the list */ + + hstatus = csrNeighborRoamProcessScanComplete(pMac); + + if (eHAL_STATUS_SUCCESS != hstatus) + { + smsLog(pMac, LOGE, FL("Neighbor scan process complete failed with status %d"), hstatus); + return eHAL_STATUS_FAILURE; + } return eHAL_STATUS_SUCCESS; } +#endif //WLAN_FEATURE_ROAM_SCAN_OFFLOAD #ifdef FEATURE_WLAN_LFR static eHalStatus csrNeighborRoamContiguousScanRequestCallback(tHalHandle halHandle, @@ -1941,6 +2140,18 @@ static eHalStatus csrNeighborRoamContiguousScanRequestCallback(tHalHandle halHan tpAniSirGlobal pMac = (tpAniSirGlobal) halHandle; tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo; eHalStatus hstatus = eHAL_STATUS_SUCCESS; + tANI_U32 sessionId = CSR_SESSION_ID_INVALID; + + if (NULL != pContext) + { + sessionId = *((tANI_U32*)pContext); + if (!csrRoamIsFastRoamEnabled(pMac,sessionId)) + { + smsLog(pMac, LOGE, FL("Received when fast roam is disabled. Ignore it")); + vos_mem_free(pContext); + return eHAL_STATUS_SUCCESS; + } + } pMac->roam.neighborRoamInfo.scanRspPending = eANI_BOOLEAN_FALSE; @@ -1948,12 +2159,16 @@ static eHalStatus csrNeighborRoamContiguousScanRequestCallback(tHalHandle halHan if (eCSR_NEIGHBOR_ROAM_STATE_CONNECTED == pNeighborRoamInfo->neighborRoamState) { smsLog(pMac, LOGE, FL("Received in CONNECTED state. Must be because a UP event from TL after issuing scan request. Ignore it")); + if (NULL != pContext) + vos_mem_free(pContext); return eHAL_STATUS_SUCCESS; } if (eCSR_NEIGHBOR_ROAM_STATE_INIT == pNeighborRoamInfo->neighborRoamState) { smsLog(pMac, LOGE, FL("Received in INIT state. Must have disconnected. Ignore it")); + if (NULL != pContext) + vos_mem_free(pContext); return eHAL_STATUS_SUCCESS; } @@ -1965,6 +2180,9 @@ static eHalStatus csrNeighborRoamContiguousScanRequestCallback(tHalHandle halHan smsLog(pMac, LOGE, FL("Neighbor scan process complete failed with status %d"), hstatus); } + if (NULL != pContext) + vos_mem_free(pContext); + return hstatus; } #endif @@ -1984,12 +2202,14 @@ static eHalStatus csrNeighborRoamContiguousScanRequestCallback(tHalHandle halHan ---------------------------------------------------------------------------*/ eHalStatus csrNeighborRoamIssueBgScanRequest(tpAniSirGlobal pMac, tCsrBGScanRequest *pBgScanParams, + tANI_U32 sessionId, csrScanCompleteCallback callbackfn) { eHalStatus status = eHAL_STATUS_SUCCESS; tANI_U32 scanId; tCsrScanRequest scanReq; tANI_U8 channel; + void * userData = NULL; if (1 == pBgScanParams->ChannelInfo.numOfChannels) NEIGHBOR_ROAM_DEBUG(pMac, LOGW, FL("Channel = %d, ChanIndex = %d"), @@ -2029,12 +2249,22 @@ eHalStatus csrNeighborRoamIssueBgScanRequest(tpAniSirGlobal pMac, scanReq.requestType = eCSR_SCAN_HO_BG_SCAN; scanReq.maxChnTime = pBgScanParams->maxChnTime; scanReq.minChnTime = pBgScanParams->minChnTime; + + userData = vos_mem_malloc(sizeof(tANI_U32)); + if (NULL == userData) + { + smsLog(pMac, LOGE, FL("Failed to allocate memory for scan request")); + vos_mem_free(scanReq.SSIDs.SSIDList); + return eHAL_STATUS_FAILURE; + } + *((tANI_U32*)userData) = sessionId; status = csrScanRequest(pMac, CSR_SESSION_ID_INVALID, &scanReq, - &scanId, callbackfn, NULL); + &scanId, callbackfn, (void *) userData); if (eHAL_STATUS_SUCCESS != status) { smsLog(pMac, LOGE, FL("CSR Scan Request failed with status %d"), status); vos_mem_free(scanReq.SSIDs.SSIDList); + vos_mem_free(userData); return status; } pMac->roam.neighborRoamInfo.scanRspPending = eANI_BOOLEAN_TRUE; @@ -2078,7 +2308,7 @@ static void csrNeighborRoamFillNonChannelBgScanParams (tpAniSirGlobal pMac, \return eHAL_STATUS_SUCCESS on success, corresponding error code otherwise ---------------------------------------------------------------------------*/ -eHalStatus csrNeighborRoamPerformBgScan(tpAniSirGlobal pMac) +eHalStatus csrNeighborRoamPerformBgScan(tpAniSirGlobal pMac, tANI_U32 sessionId) { eHalStatus status = eHAL_STATUS_SUCCESS; tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo; @@ -2120,8 +2350,8 @@ eHalStatus csrNeighborRoamPerformBgScan(tpAniSirGlobal pMac) csrNeighborRoamFillNonChannelBgScanParams(pMac, &bgScanParams); - status = csrNeighborRoamIssueBgScanRequest(pMac, &bgScanParams, - csrNeighborRoamScanRequestCallback); + status = csrNeighborRoamIssueBgScanRequest(pMac, &bgScanParams, + sessionId, csrNeighborRoamScanRequestCallback); if (eHAL_STATUS_SUCCESS != status) { smsLog(pMac, LOGE, FL("Issue of BG Scan request failed: Status = %d"), status); @@ -2157,7 +2387,7 @@ eHalStatus csrNeighborRoamPerformBgScan(tpAniSirGlobal pMac) } #ifdef FEATURE_WLAN_LFR -eHalStatus csrNeighborRoamPerformContiguousBgScan(tpAniSirGlobal pMac) +eHalStatus csrNeighborRoamPerformContiguousBgScan(tpAniSirGlobal pMac, tANI_U32 sessionId) { eHalStatus status = eHAL_STATUS_SUCCESS; tCsrBGScanRequest bgScanParams; @@ -2221,7 +2451,7 @@ eHalStatus csrNeighborRoamPerformContiguousBgScan(tpAniSirGlobal pMac) csrNeighborRoamFillNonChannelBgScanParams(pMac, &bgScanParams); status = csrNeighborRoamIssueBgScanRequest(pMac, &bgScanParams, - csrNeighborRoamContiguousScanRequestCallback); + sessionId, csrNeighborRoamContiguousScanRequestCallback); vos_mem_free( channelList ); @@ -2270,7 +2500,7 @@ void csrNeighborRoamNeighborScanTimerCallback(void *pv) switch(pNeighborRoamInfo->prevNeighborRoamState) { case eCSR_NEIGHBOR_ROAM_STATE_REPORT_QUERY: - csrNeighborRoamPerformBgScan(pMac); + csrNeighborRoamPerformBgScan(pMac, sessionId); break; default: smsLog(pMac, LOGE, FL("Neighbor scan callback received in state %d, prev state = %d"), @@ -2280,7 +2510,7 @@ void csrNeighborRoamNeighborScanTimerCallback(void *pv) break; #endif /* WLAN_FEATURE_VOWIFI_11R */ case eCSR_NEIGHBOR_ROAM_STATE_CFG_CHAN_LIST_SCAN: - csrNeighborRoamPerformBgScan(pMac); + csrNeighborRoamPerformBgScan(pMac, sessionId); break; default: break; @@ -2509,11 +2739,18 @@ VOS_STATUS csrNeighborRoamMergeChannelLists( int numChannels = outputNumOfChannels; // Check for NULL pointer - if (!pInputChannelList) return eHAL_STATUS_E_NULL_VALUE; + if (!pInputChannelList) return VOS_STATUS_E_INVAL; // Check for NULL pointer - if (!pOutputChannelList) return eHAL_STATUS_E_NULL_VALUE; + if (!pOutputChannelList) return VOS_STATUS_E_INVAL; + if (inputNumOfChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN) + { + VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Wrong Number of Input Channels %d", + __func__, inputNumOfChannels); + return VOS_STATUS_E_INVAL; + } // Add the "new" channels in the input list to the end of the output list. for (i = 0; i < inputNumOfChannels; i++) { @@ -2538,7 +2775,7 @@ VOS_STATUS csrNeighborRoamMergeChannelLists( // Return final number of channels *pMergedOutputNumOfChannels = numChannels; - return eHAL_STATUS_SUCCESS; + return VOS_STATUS_SUCCESS; } /* --------------------------------------------------------------------------- @@ -2660,6 +2897,12 @@ VOS_STATUS csrNeighborRoamCreateChanListFromNeighborReport(tpAniSirGlobal pMac) smsLog(pMac, LOG1, FL("IAPP Neighbor list callback received as expected in state %d."), pNeighborRoamInfo->neighborRoamState); pNeighborRoamInfo->roamChannelInfo.IAPPNeighborListReceived = eANI_BOOLEAN_TRUE; +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pMac->roam.configParam.isRoamOffloadScanEnabled) + { + csrRoamOffloadScan(pMac, ROAM_SCAN_OFFLOAD_UPDATE_CFG, REASON_CHANNEL_LIST_CHANGED); + } +#endif } pNeighborRoamInfo->roamChannelInfo.currentChanIndex = 0; pNeighborRoamInfo->roamChannelInfo.chanListScanInProgress = eANI_BOOLEAN_TRUE; @@ -2863,8 +3106,6 @@ tANI_BOOLEAN csrNeighborRoamIsNewConnectedProfile( if (fNew) { smsLog(pMac, LOG1, FL("Prev roam profile did not match current")); - csrRoamFreeConnectProfile(pMac, pPrevProfile); - csrRoamGetConnectProfile(pMac, sessionId, pPrevProfile); } else { @@ -2972,7 +3213,9 @@ VOS_STATUS csrNeighborRoamTransitToCFGChanScan(tpAniSirGlobal pMac) int numOfChannels = 0; tANI_U8 channelList[WNI_CFG_VALID_CHANNEL_LIST_LEN]; tpCsrChannelInfo currChannelListInfo; - +#ifdef FEATURE_WLAN_LFR + tANI_U32 sessionId = pNeighborRoamInfo->csrSessionId; +#endif currChannelListInfo = &pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo; if ( @@ -3022,13 +3265,16 @@ VOS_STATUS csrNeighborRoamTransitToCFGChanScan(tpAniSirGlobal pMac) currChannelListInfo->ChannelList = vos_mem_malloc(numOfChannels*sizeof(tANI_U8)); - if (NULL == currChannelListInfo->ChannelList) - { - smsLog(pMac, LOGE, FL("Memory allocation for Channel list failed")); - return VOS_STATUS_E_RESOURCES; - } - - vos_mem_copy(currChannelListInfo->ChannelList, + if (NULL == currChannelListInfo->ChannelList) + { + smsLog(pMac, LOGE, FL("Memory allocation for Channel list failed")); + return VOS_STATUS_E_RESOURCES; + } + if (WNI_CFG_VALID_CHANNEL_LIST_LEN < numOfChannels) + { + numOfChannels = WNI_CFG_VALID_CHANNEL_LIST_LEN; + } + vos_mem_copy(currChannelListInfo->ChannelList, channelList, numOfChannels * sizeof(tANI_U8)); } #ifdef FEATURE_WLAN_LFR @@ -3055,7 +3301,7 @@ VOS_STATUS csrNeighborRoamTransitToCFGChanScan(tpAniSirGlobal pMac) * purge non-P2P results from the past */ csrScanFlushSelectiveResult(pMac, VOS_FALSE); - csrNeighborRoamPerformContiguousBgScan(pMac); + csrNeighborRoamPerformContiguousBgScan(pMac, sessionId); /* Transition to CFG_CHAN_LIST_SCAN */ CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_CFG_CHAN_LIST_SCAN); @@ -3109,6 +3355,10 @@ VOS_STATUS csrNeighborRoamTransitToCFGChanScan(tpAniSirGlobal pMac) smsLog(pMac, LOGE, FL("Memory allocation for Channel list failed")); return VOS_STATUS_E_RESOURCES; } + if (WNI_CFG_VALID_CHANNEL_LIST_LEN < numOfChannels) + { + numOfChannels = WNI_CFG_VALID_CHANNEL_LIST_LEN; + } vos_mem_copy(currChannelListInfo->ChannelList, channelList, numOfChannels * sizeof(tANI_U8)); @@ -3171,9 +3421,17 @@ VOS_STATUS csrNeighborRoamTransitToCFGChanScan(tpAniSirGlobal pMac) return VOS_STATUS_E_RESOURCES; } #ifdef FEATURE_WLAN_LFR + if (WNI_CFG_VALID_CHANNEL_LIST_LEN < numOfChannels) + { + numOfChannels = WNI_CFG_VALID_CHANNEL_LIST_LEN; + } vos_mem_copy(currChannelListInfo->ChannelList, channelList, numOfChannels * sizeof(tANI_U8)); #else + if (WNI_CFG_VALID_CHANNEL_LIST_LEN < numOfChannels) + { + numOfChannels = WNI_CFG_VALID_CHANNEL_LIST_LEN; + } vos_mem_copy(currChannelListInfo->ChannelList, (tANI_U8 *)pMac->roam.validChannelList, numOfChannels * sizeof(tANI_U8)); @@ -3251,7 +3509,13 @@ VOS_STATUS csrNeighborRoamNeighborLookupUpEvent(tpAniSirGlobal pMac) /* Recheck whether the below check is needed. */ if (pNeighborRoamInfo->neighborRoamState != eCSR_NEIGHBOR_ROAM_STATE_CONNECTED) CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_CONNECTED) - +#ifdef FEATURE_WLAN_LFR + if (!csrRoamIsFastRoamEnabled(pMac,pMac->roam.neighborRoamInfo.csrSessionId)) + { + smsLog(pMac, LOGE, FL("Received when fast roam is disabled. Ignore it")); + return eHAL_STATUS_SUCCESS; + } +#endif /* Reset all the neighbor roam info control variables. Free all the allocated memory. It is like we are just associated now */ csrNeighborRoamResetConnectedStateControlInfo(pMac); @@ -3312,7 +3576,13 @@ VOS_STATUS csrNeighborRoamNeighborLookupDownEvent(tpAniSirGlobal pMac) //err msg smsLog(pMac, LOGW, FL(" Couldn't Deregister csrNeighborRoamNeighborLookupCallback DOWN event from TL: Status = %d"), vosStatus); } - +#ifdef FEATURE_WLAN_LFR + if (!csrRoamIsFastRoamEnabled(pMac,pMac->roam.neighborRoamInfo.csrSessionId)) + { + smsLog(pMac, LOGE, FL("Received when fast roam is disabled. Ignore it")); + return eHAL_STATUS_SUCCESS; + } +#endif #if defined WLAN_FEATURE_VOWIFI_11R && defined WLAN_FEATURE_VOWIFI if ((pNeighborRoamInfo->is11rAssoc) && (pMac->rrm.rrmSmeContext.rrmConfig.rrmEnabled)) @@ -3464,14 +3734,35 @@ extern int dumpCmdRSSI; eHalStatus csrNeighborRoamIndicateDisconnect(tpAniSirGlobal pMac, tANI_U8 sessionId) { tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo; +#ifdef FEATURE_WLAN_LFR + tCsrRoamConnectedProfile *pPrevProfile = &pNeighborRoamInfo->prevConnProfile; +#endif + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId); - smsLog(pMac, LOGE, FL("Disconnect indication on session %d in state %d (sub-state %d)"), - sessionId, pNeighborRoamInfo->neighborRoamState, - pMac->roam.curSubState[sessionId]); + smsLog(pMac, LOGE, FL("Disconnect indication on session %d in state %d"), + sessionId, pNeighborRoamInfo->neighborRoamState); +#ifdef FEATURE_WLAN_LFR + /*Free the current previous profile and move the current profile to prev profile.*/ + csrRoamFreeConnectProfile(pMac, pPrevProfile); + csrRoamGetConnectProfile(pMac, sessionId, pPrevProfile); +#endif + if (NULL != pSession) + { + if (NULL != pSession->pCurRoamProfile) + { + if (VOS_STA_MODE != pMac->roam.roamSession[sessionId].pCurRoamProfile->csrPersona) + { + smsLog(pMac, LOGE, FL("Ignoring Disconnect indication received from a non STA persona." + "sessionId: %d, csrPersonna %d"), sessionId, + (int)pMac->roam.roamSession[sessionId].pCurRoamProfile->csrPersona); + return eHAL_STATUS_SUCCESS; + } + } + } + #ifdef FEATURE_WLAN_CCX { - tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId); if (pSession->connectedProfile.isCCXAssoc) { vos_mem_copy(&pSession->prevApSSID, &pSession->connectedProfile.SSID, sizeof(tSirMacSSid)); @@ -3512,19 +3803,40 @@ eHalStatus csrNeighborRoamIndicateDisconnect(tpAniSirGlobal pMac, tANI_U8 sessio case eCSR_NEIGHBOR_ROAM_STATE_INIT: csrNeighborRoamResetInitStateControlInfo(pMac); - csrNeighborRoamDeregAllRssiIndication(pMac); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if(!pMac->roam.configParam.isRoamOffloadScanEnabled) + { +#endif + csrNeighborRoamDeregAllRssiIndication(pMac); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + } +#endif break; case eCSR_NEIGHBOR_ROAM_STATE_CONNECTED: CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_INIT) csrNeighborRoamResetConnectedStateControlInfo(pMac); - csrNeighborRoamDeregAllRssiIndication(pMac); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if(!pMac->roam.configParam.isRoamOffloadScanEnabled) + { +#endif + csrNeighborRoamDeregAllRssiIndication(pMac); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + } +#endif break; case eCSR_NEIGHBOR_ROAM_STATE_CFG_CHAN_LIST_SCAN: CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_INIT); csrNeighborRoamResetCfgListChanScanControlInfo(pMac); - csrNeighborRoamDeregAllRssiIndication(pMac); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (!pMac->roam.configParam.isRoamOffloadScanEnabled) + { +#endif + csrNeighborRoamDeregAllRssiIndication(pMac); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + } +#endif break; case eCSR_NEIGHBOR_ROAM_STATE_PREAUTH_DONE: @@ -3535,7 +3847,14 @@ eHalStatus csrNeighborRoamIndicateDisconnect(tpAniSirGlobal pMac, tANI_U8 sessio CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_INIT) csrNeighborRoamResetPreauthControlInfo(pMac); csrNeighborRoamResetReportScanStateControlInfo(pMac); - csrNeighborRoamDeregAllRssiIndication(pMac); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (!pMac->roam.configParam.isRoamOffloadScanEnabled) + { +#endif + csrNeighborRoamDeregAllRssiIndication(pMac); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + } +#endif break; default: @@ -3544,6 +3863,11 @@ eHalStatus csrNeighborRoamIndicateDisconnect(tpAniSirGlobal pMac, tANI_U8 sessio CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_INIT) break; } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + /*Inform the Firmware to STOP Scanning as the host has a disconnect.*/ + if (csrRoamIsStaMode(pMac, sessionId)) + csrRoamOffloadScan(pMac, ROAM_SCAN_OFFLOAD_STOP, REASON_DISCONNECTED); +#endif return eHAL_STATUS_SUCCESS; } @@ -3572,8 +3896,24 @@ eHalStatus csrNeighborRoamIndicateConnect(tpAniSirGlobal pMac, tANI_U8 sessionId int init_ft_flag = FALSE; #endif + if (NULL == pNeighborRoamInfo) + { + return eHAL_STATUS_FAILURE; + } smsLog(pMac, LOG2, FL("Connect indication received with session id %d in state %d"), sessionId, pNeighborRoamInfo->neighborRoamState); + // Bail out if this is NOT a STA persona or if a concurrent session is running + if ((pMac->roam.roamSession[sessionId].pCurRoamProfile->csrPersona != VOS_STA_MODE)|| + csrIsConcurrentSessionRunning(pMac)) + { + smsLog(pMac, LOGE, FL("Ignoring Connect indication received from a non STA persona." + "sessionId: %d, csrPersonna %d, is multisession %d"), + sessionId, + (int)pMac->roam.roamSession[sessionId].pCurRoamProfile->csrPersona, + csrIsConcurrentSessionRunning(pMac)); + return eHAL_STATUS_SUCCESS; + } + switch (pNeighborRoamInfo->neighborRoamState) { case eCSR_NEIGHBOR_ROAM_STATE_REASSOCIATING: @@ -3662,6 +4002,16 @@ eHalStatus csrNeighborRoamIndicateConnect(tpAniSirGlobal pMac, tANI_U8 sessionId /* Initialize all the data structures needed for the 11r FT Preauth */ pNeighborRoamInfo->FTRoamInfo.currentNeighborRptRetryNum = 0; csrNeighborRoamPurgePreauthFailedList(pMac); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pMac->roam.configParam.isRoamOffloadScanEnabled) + { + /*If this is not a INFRA type BSS, then do not send the command + * down to firmware.Do not send the START command for other session + * connections.*/ + if(csrRoamIsStaMode(pMac, sessionId)) + csrRoamOffloadScan(pMac, ROAM_SCAN_OFFLOAD_START, REASON_CONNECT); + } else { +#endif NEIGHBOR_ROAM_DEBUG(pMac, LOG2, FL("Registering neighbor lookup DOWN event with TL, RSSI = %d"), pNeighborRoamInfo->currentNeighborLookupThreshold); /* Register Neighbor Lookup threshold callback with TL for DOWN event only */ @@ -3678,6 +4028,9 @@ eHalStatus csrNeighborRoamIndicateConnect(tpAniSirGlobal pMac, tANI_U8 sessionId smsLog(pMac, LOGW, FL(" Couldn't register csrNeighborRoamNeighborLookupDOWNCallback with TL: Status = %d"), vstatus); status = eHAL_STATUS_FAILURE; } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + } +#endif /* WLAN_FEATURE_ROAM_SCAN_OFFLOAD */ } #endif break; @@ -4211,5 +4564,44 @@ tANI_BOOLEAN csrNeighborMiddleOfRoaming (tHalHandle hHal) (eCSR_NEIGHBOR_ROAM_STATE_CFG_CHAN_LIST_SCAN == pMac->roam.neighborRoamInfo.neighborRoamState); return (val); } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +/* --------------------------------------------------------------------------- + + \fn csrNeighborRoamCandidateFoundIndHdlr + + \brief This function is called by CSR as soon as TL posts the candidate + found indication to SME via MC thread + + \param pMac - The handle returned by macOpen. + pMsg - Msg sent by PE + \return eHAL_STATUS_SUCCESS on success, corresponding error code otherwise + +---------------------------------------------------------------------------*/ +eHalStatus csrNeighborRoamCandidateFoundIndHdlr(tpAniSirGlobal pMac, void* pMsg) +{ + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo; + eHalStatus status = eHAL_STATUS_SUCCESS; + /* we must be in connected state, if not ignore it */ + if (eCSR_NEIGHBOR_ROAM_STATE_CONNECTED != pNeighborRoamInfo->neighborRoamState) + { + smsLog(pMac, LOGW, FL("Received in not CONNECTED state. Ignore it")); + status = eHAL_STATUS_FAILURE; + } + else + { + /* We are about to start a fresh scan cycle, + * purge non-P2P results from the past */ + csrScanFlushSelectiveResult(pMac, VOS_FALSE); + /* Once it gets the candidates found indication from PE, will issue a scan + - req to PE with “freshScan” in scanreq structure set as follows: + 0x42 - Return & purge LFR scan results + */ + status = csrScanRequestLfrResult(pMac, pNeighborRoamInfo->csrSessionId, + csrNeighborRoamScanResultRequestCallback, pMac); + } + + return status; +} +#endif //WLAN_FEATURE_ROAM_SCAN_OFFLOAD #endif /* WLAN_FEATURE_NEIGHBOR_ROAMING */ diff --git a/drivers/staging/prima/CORE/SME/src/csr/csrTdlsProcess.c b/drivers/staging/prima/CORE/SME/src/csr/csrTdlsProcess.c index dccbd5e929c..697ae1f585e 100644 --- a/drivers/staging/prima/CORE/SME/src/csr/csrTdlsProcess.c +++ b/drivers/staging/prima/CORE/SME/src/csr/csrTdlsProcess.c @@ -47,8 +47,12 @@ Implementation for the TDLS interface to PE. - Copyright (C) 2010 Qualcomm, Incorporated - + Copyright (c) 2013 Qualcomm Atheros, Inc.All Rights Reserved. + Qualcomm Atheros Confidential and Proprietary. + + Copyright (c) 2010 Qualcomm Technologies, Inc.All Rights Reserved. + Qualcomm Technologies Confidential and Proprietary + ========================================================================== */ @@ -207,11 +211,19 @@ eHalStatus csrTdlsChangePeerSta(tHalHandle hHal, tANI_U8 sessionId, tSirMacAddr pstaParams->extn_capability, sizeof(pstaParams->extn_capability)); - palCopyMemory(pMac->hHdd, &tdlsAddStaCmdInfo->HTCap, - &pstaParams->HTCap, sizeof(pstaParams->HTCap)); + tdlsAddStaCmdInfo->htcap_present = pstaParams->htcap_present; + if(pstaParams->htcap_present) + palCopyMemory(pMac->hHdd, &tdlsAddStaCmdInfo->HTCap, + &pstaParams->HTCap, sizeof(pstaParams->HTCap)); + else + palZeroMemory(pMac->hHdd, &tdlsAddStaCmdInfo->HTCap, sizeof(pstaParams->HTCap)); - palCopyMemory(pMac->hHdd, &tdlsAddStaCmdInfo->VHTCap, - &pstaParams->VHTCap, sizeof(pstaParams->VHTCap)); + tdlsAddStaCmdInfo->vhtcap_present = pstaParams->vhtcap_present; + if(pstaParams->vhtcap_present) + palCopyMemory(pMac->hHdd, &tdlsAddStaCmdInfo->VHTCap, + &pstaParams->VHTCap, sizeof(pstaParams->VHTCap)); + else + palZeroMemory(pMac->hHdd, &tdlsAddStaCmdInfo->VHTCap, sizeof(pstaParams->VHTCap)); tdlsAddStaCmdInfo->supportedRatesLen = pstaParams->supported_rates_len; @@ -436,12 +448,23 @@ eHalStatus csrTdlsProcessSendMgmt( tpAniSirGlobal pMac, tSmeCmd *cmd ) tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, cmd->sessionId ); eHalStatus status = eHAL_STATUS_FAILURE; + if (NULL == pSession) + { + return eHAL_STATUS_FAILURE; + } + + if (NULL == pSession->pConnectBssDesc) + { + smsLog( pMac, LOGE, FL("BSS Description is not present") ); + return eHAL_STATUS_FAILURE; + } + status = palAllocateMemory( pMac->hHdd, (void **)&tdlsSendMgmtReq, (sizeof(tSirTdlsSendMgmtReq) + tdlsSendMgmtCmdInfo->len ) ); - if(!HAL_STATUS_SUCCESS( status ) ) + if (!HAL_STATUS_SUCCESS( status ) ) { - smsLog( pMac, LOGE, FL("alloc failed ") ); + smsLog( pMac, LOGE, FL("alloc failed") ); VOS_ASSERT(0) ; return status ; } @@ -452,16 +475,10 @@ eHalStatus csrTdlsProcessSendMgmt( tpAniSirGlobal pMac, tSmeCmd *cmd ) tdlsSendMgmtReq->dialog = tdlsSendMgmtCmdInfo->dialog ; tdlsSendMgmtReq->statusCode = tdlsSendMgmtCmdInfo->statusCode ; tdlsSendMgmtReq->responder = tdlsSendMgmtCmdInfo->responder; - if (pSession->pConnectBssDesc) - { - palCopyMemory(pMac->hHdd, tdlsSendMgmtReq->bssid, pSession->pConnectBssDesc->bssId, - sizeof (tSirMacAddr)); - } - else - { - smsLog( pMac, LOGE, FL("%s: BSS Description is not present\n"), __func__); - return eHAL_STATUS_FAILURE; - } + + palCopyMemory(pMac->hHdd, tdlsSendMgmtReq->bssid, + pSession->pConnectBssDesc->bssId, sizeof (tSirMacAddr)); + palCopyMemory(pMac->hHdd, tdlsSendMgmtReq->peerMac, tdlsSendMgmtCmdInfo->peerMac, sizeof(tSirMacAddr)) ; @@ -496,12 +513,23 @@ eHalStatus csrTdlsProcessAddSta( tpAniSirGlobal pMac, tSmeCmd *cmd ) tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, cmd->sessionId ); eHalStatus status = eHAL_STATUS_FAILURE; + if (NULL == pSession) + { + return eHAL_STATUS_FAILURE; + } + + if (NULL == pSession->pConnectBssDesc) + { + smsLog( pMac, LOGE, FL("BSS description is not present") ); + return eHAL_STATUS_FAILURE; + } + status = palAllocateMemory( pMac->hHdd, (void **)&tdlsAddStaReq, (sizeof(tSirTdlsAddStaReq) ) ); - if(!HAL_STATUS_SUCCESS( status ) ) + if (!HAL_STATUS_SUCCESS( status ) ) { - smsLog( pMac, LOGE, FL("alloc failed ") ); + smsLog( pMac, LOGE, FL("alloc failed") ); VOS_ASSERT(0) ; return status ; } @@ -510,16 +538,8 @@ eHalStatus csrTdlsProcessAddSta( tpAniSirGlobal pMac, tSmeCmd *cmd ) //Using dialog as transactionId. This can be used to match response with request tdlsAddStaReq->transactionId = 0; - if (pSession->pConnectBssDesc) - { - palCopyMemory(pMac->hHdd, tdlsAddStaReq->bssid, pSession->pConnectBssDesc->bssId, - sizeof (tSirMacAddr)); - } - else - { - smsLog( pMac, LOGE, FL("%s: BSS description is not present\n"), __func__); - return eHAL_STATUS_FAILURE; - } + palCopyMemory(pMac->hHdd, tdlsAddStaReq->bssid, + pSession->pConnectBssDesc->bssId, sizeof (tSirMacAddr)); palCopyMemory(pMac->hHdd, tdlsAddStaReq->peerMac, tdlsAddStaCmdInfo->peerMac, sizeof(tSirMacAddr)) ; @@ -531,8 +551,10 @@ eHalStatus csrTdlsProcessAddSta( tpAniSirGlobal pMac, tSmeCmd *cmd ) palCopyMemory(pMac->hHdd, tdlsAddStaReq->extn_capability, tdlsAddStaCmdInfo->extnCapability, SIR_MAC_MAX_EXTN_CAP); + tdlsAddStaReq->htcap_present = tdlsAddStaCmdInfo->htcap_present; palCopyMemory(pMac->hHdd, &tdlsAddStaReq->htCap, &tdlsAddStaCmdInfo->HTCap, sizeof(tdlsAddStaCmdInfo->HTCap)); + tdlsAddStaReq->vhtcap_present = tdlsAddStaCmdInfo->vhtcap_present; palCopyMemory(pMac->hHdd, &tdlsAddStaReq->vhtCap, &tdlsAddStaCmdInfo->VHTCap, sizeof(tdlsAddStaCmdInfo->VHTCap)); tdlsAddStaReq->supported_rates_length = tdlsAddStaCmdInfo->supportedRatesLen; @@ -557,28 +579,33 @@ eHalStatus csrTdlsProcessDelSta( tpAniSirGlobal pMac, tSmeCmd *cmd ) tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, cmd->sessionId ); eHalStatus status = eHAL_STATUS_FAILURE; + if (NULL == pSession) + { + return eHAL_STATUS_FAILURE; + } + + if (NULL == pSession->pConnectBssDesc) + { + smsLog( pMac, LOGE, FL("BSS description is not present") ); + return eHAL_STATUS_FAILURE; + } + status = palAllocateMemory( pMac->hHdd, (void **)&tdlsDelStaReq, (sizeof(tSirTdlsDelStaReq) ) ); - if(!HAL_STATUS_SUCCESS( status ) ) + if (!HAL_STATUS_SUCCESS( status ) ) { - smsLog( pMac, LOGE, FL("alloc failed ") ); + smsLog( pMac, LOGE, FL("alloc failed") ); VOS_ASSERT(0) ; return status ; } tdlsDelStaReq->sessionId = cmd->sessionId; //Using dialog as transactionId. This can be used to match response with request tdlsDelStaReq->transactionId = 0; - if (pSession->pConnectBssDesc) - { - palCopyMemory(pMac->hHdd, tdlsDelStaReq->bssid, pSession->pConnectBssDesc->bssId, - sizeof (tSirMacAddr)); - } - else - { - smsLog( pMac, LOGE, FL("%s: BSS description is not present\n"), __func__); - return eHAL_STATUS_FAILURE; - } + + palCopyMemory(pMac->hHdd, tdlsDelStaReq->bssid, + pSession->pConnectBssDesc->bssId, sizeof (tSirMacAddr)); + palCopyMemory(pMac->hHdd, tdlsDelStaReq->peerMac, tdlsDelStaCmdInfo->peerMac, sizeof(tSirMacAddr)) ; @@ -912,12 +939,12 @@ eHalStatus tdlsMsgProcessor(tpAniSirGlobal pMac, v_U16_t msgType, */ if (addStaRsp->tdlsAddOper == TDLS_OPER_ADD) roamResult = eCSR_ROAM_RESULT_ADD_TDLS_PEER; - else if (addStaRsp->tdlsAddOper == TDLS_OPER_UPDATE) + else /* addStaRsp->tdlsAddOper must be TDLS_OPER_UPDATE */ roamResult = eCSR_ROAM_RESULT_UPDATE_TDLS_PEER; csrRoamCallCallback(pMac, addStaRsp->sessionId, &roamInfo, 0, - eCSR_ROAM_TDLS_STATUS_UPDATE, - roamResult); - + eCSR_ROAM_TDLS_STATUS_UPDATE, + roamResult); + /* remove pending eSmeCommandTdlsDiscovery command */ csrTdlsRemoveSmeCmd(pMac, eSmeCommandTdlsAddPeer) ; } diff --git a/drivers/staging/prima/CORE/SME/src/csr/csrUtil.c b/drivers/staging/prima/CORE/SME/src/csr/csrUtil.c index 51a4bb3a544..a315822efb6 100644 --- a/drivers/staging/prima/CORE/SME/src/csr/csrUtil.c +++ b/drivers/staging/prima/CORE/SME/src/csr/csrUtil.c @@ -1,8 +1,46 @@ /* -* Copyright (c) 2011-2013 Qualcomm Atheros, Inc. -* All Rights Reserved. -* Qualcomm Atheros Confidential and Proprietary. -*/ + * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ +/* + * Copyright (c) 2012, The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + + + /** ------------------------------------------------------------------------- * ------------------------------------------------------------------------- * @@ -50,13 +88,8 @@ tANI_U8 csrRSNOui[][ CSR_RSN_OUI_SIZE ] = { { 0x00, 0x0F, 0xAC, 0x03 }, // Reserved { 0x00, 0x0F, 0xAC, 0x04 }, // AES-CCMP { 0x00, 0x0F, 0xAC, 0x05 }, // WEP-104 -#ifdef WLAN_FEATURE_11W - { 0x00, 0x0F, 0xAC, 0x06 }, // BIP(encryption type) or (RSN-PSK-SHA256(authentication type) -#endif -#ifdef FEATURE_WLAN_CCX - { 0x00, 0x40, 0x96, 0x00 } // CCKM -#endif /* FEATURE_WLAN_CCX */ - + { 0x00, 0x40, 0x96, 0x00 }, // CCKM + { 0x00, 0x0F, 0xAC, 0x06 } // BIP (encryption type) or RSN-PSK-SHA256 (authentication type) }; #ifdef FEATURE_WLAN_WAPI @@ -2674,9 +2707,6 @@ tANI_BOOLEAN csrIsProfileRSN( tCsrRoamProfile *pProfile ) #ifdef FEATURE_WLAN_CCX case eCSR_AUTH_TYPE_CCKM_RSN: #endif -#ifdef WLAN_FEATURE_11W - case eCSR_AUTH_TYPE_RSN_PSK_SHA256: -#endif fRSNProfile = TRUE; break; @@ -3349,23 +3379,13 @@ static tANI_BOOLEAN csrIsAuthRSN( tpAniSirGlobal pMac, tANI_U8 AllSuites[][CSR_R tANI_U8 cAllSuites, tANI_U8 Oui[] ) { -#ifdef WLAN_FEATURE_11W - return( csrIsOuiMatch( pMac, AllSuites, cAllSuites, csrRSNOui[01], Oui ) || - csrIsOuiMatch( pMac, AllSuites, cAllSuites, csrRSNOui[06], Oui )); -#else return( csrIsOuiMatch( pMac, AllSuites, cAllSuites, csrRSNOui[01], Oui ) ); -#endif } static tANI_BOOLEAN csrIsAuthRSNPsk( tpAniSirGlobal pMac, tANI_U8 AllSuites[][CSR_RSN_OUI_SIZE], tANI_U8 cAllSuites, tANI_U8 Oui[] ) { -#ifdef WLAN_FEATURE_11W - return( csrIsOuiMatch( pMac, AllSuites, cAllSuites, csrRSNOui[02], Oui ) || - csrIsOuiMatch( pMac, AllSuites, cAllSuites, csrRSNOui[06], Oui ) ); -#else return( csrIsOuiMatch( pMac, AllSuites, cAllSuites, csrRSNOui[02], Oui ) ); -#endif } #ifdef WLAN_FEATURE_11W @@ -3373,7 +3393,7 @@ static tANI_BOOLEAN csrIsAuthRSNPskSha256( tpAniSirGlobal pMac, tANI_U8 AllSuite tANI_U8 cAllSuites, tANI_U8 Oui[] ) { - return csrIsOuiMatch( pMac, AllSuites, cAllSuites, csrRSNOui[06], Oui ); + return csrIsOuiMatch( pMac, AllSuites, cAllSuites, csrRSNOui[07], Oui ); } #endif @@ -3586,13 +3606,6 @@ tANI_BOOLEAN csrGetRSNInformation( tHalHandle hHal, tCsrAuthList *pAuthType, eCs if (eCSR_AUTH_TYPE_RSN_PSK == pAuthType->authType[i]) negAuthType = eCSR_AUTH_TYPE_RSN_PSK; } -#ifdef WLAN_FEATURE_11W - if ((negAuthType == eCSR_AUTH_TYPE_UNKNOWN) && csrIsAuthRSNPskSha256( pMac, AuthSuites, cAuthSuites, Authentication ) ) - { - if (eCSR_AUTH_TYPE_RSN_PSK_SHA256 == pAuthType->authType[i]) - negAuthType = eCSR_AUTH_TYPE_RSN_PSK_SHA256; - } -#endif // The 1st auth type in the APs RSN IE, to match stations connecting // profiles auth type will cause us to exit this loop @@ -3633,12 +3646,9 @@ tANI_BOOLEAN csrGetRSNInformation( tHalHandle hHal, tCsrAuthList *pAuthType, eCs Capabilities->PreAuthSupported = (pRSNIe->RSN_Cap[0] >> 0) & 0x1 ; // Bit 0 PreAuthentication Capabilities->NoPairwise = (pRSNIe->RSN_Cap[0] >> 1) & 0x1 ; // Bit 1 No Pairwise Capabilities->PTKSAReplayCounter = (pRSNIe->RSN_Cap[0] >> 2) & 0x3 ; // Bit 2, 3 PTKSA Replay Counter - Capabilities->GTKSAReplayCounter = (pRSNIe->RSN_Cap[0] >> 4) & 0x3 ; // Bit 4, 5 GTKSA Replay Counter -#ifdef WLAN_FEATURE_11W - Capabilities->MFPRequired = (pRSNIe->RSN_Cap[0] >> 6) & 0x1 ; // Bit 6 MFPR - Capabilities->MFPCapable = (pRSNIe->RSN_Cap[0] >> 7) & 0x1 ; // Bit 7 MFPC -#endif - Capabilities->Reserved = pRSNIe->RSN_Cap[1] & 0xff ; // remaining reserved + Capabilities->GTKSAReplayCounter = (pRSNIe->RSN_Cap[0] >> 4) & 0x3 ; // Bit 4,5 GTKSA Replay Counter + Capabilities->Reserved = (pRSNIe->RSN_Cap[0] >> 6) & 0x3 ; // remaining reserved + Capabilities->Reserved = (Capabilities->Reserved >> 2) | (pRSNIe->RSN_Cap[1] & 0xff) ; // remaining reserved } } return( fAcceptableCyphers ); @@ -3720,6 +3730,9 @@ tANI_U8 csrConstructRSNIe( tHalHandle hHal, tANI_U32 sessionId, tCsrRoamProfile tCsrRSNCapabilities RSNCapabilities; tCsrRSNPMKIe *pPMK; tANI_U8 PMKId[CSR_RSN_PMKID_SIZE]; +#ifdef WLAN_FEATURE_11W + tANI_U8 *pGroupMgmtCipherSuite; +#endif tDot11fBeaconIEs *pIesLocal = pIes; smsLog(pMac, LOGW, "%s called...", __func__); @@ -3758,12 +3771,7 @@ tANI_U8 csrConstructRSNIe( tHalHandle hHal, tANI_U32 sessionId, tCsrRoamProfile // !!REVIEW - What should STA put in RSN capabilities, currently // just putting back APs capabilities // For one, we shouldn't EVER be sending out "pre-auth supported". It is an AP only capability - // For another, we should use the Management Frame Protection values given by the supplicant RSNCapabilities.PreAuthSupported = 0; -#ifdef WLAN_FEATURE_11W - RSNCapabilities.MFPRequired = pProfile->MFPRequired; - RSNCapabilities.MFPCapable = pProfile->MFPCapable; -#endif *(tANI_U16 *)( &pAuthSuite->AuthOui[ 1 ] ) = *((tANI_U16 *)(&RSNCapabilities)); pPMK = (tCsrRSNPMKIe *)( ((tANI_U8 *)(&pAuthSuite->AuthOui[ 1 ])) + sizeof(tANI_U16) ); @@ -3779,10 +3787,20 @@ tANI_U8 csrConstructRSNIe( tHalHandle hHal, tANI_U32 sessionId, tCsrRoamProfile pPMK->cPMKIDs = 0; } +#ifdef WLAN_FEATURE_11W + if ( pProfile->MFPEnabled ) + { + pGroupMgmtCipherSuite = (tANI_U8 *) pPMK + sizeof ( tANI_U16 ) + + ( pPMK->cPMKIDs * CSR_RSN_PMKID_SIZE ); + palCopyMemory( pMac->hHdd, pGroupMgmtCipherSuite, csrRSNOui[07], CSR_WPA_OUI_SIZE ); + } +#endif + // Add in the fixed fields plus 1 Unicast cypher, less the IE Header length // Add in the size of the Auth suite (count plus a single OUI) // Add in the RSN caps field. // Add PMKID count and PMKID (if any) + // Add group management cipher suite pRSNIe->IeHeader.Length = (tANI_U8) (sizeof( *pRSNIe ) - sizeof ( pRSNIe->IeHeader ) + sizeof( *pAuthSuite ) + sizeof( tCsrRSNCapabilities )); @@ -3791,6 +3809,15 @@ tANI_U8 csrConstructRSNIe( tHalHandle hHal, tANI_U32 sessionId, tCsrRoamProfile pRSNIe->IeHeader.Length += (tANI_U8)(sizeof( tANI_U16 ) + (pPMK->cPMKIDs * CSR_RSN_PMKID_SIZE)); } +#ifdef WLAN_FEATURE_11W + if ( pProfile->MFPEnabled ) + { + if ( 0 == pPMK->cPMKIDs ) + pRSNIe->IeHeader.Length += sizeof( tANI_U16 ); + pRSNIe->IeHeader.Length += CSR_WPA_OUI_SIZE; + } +#endif + // return the size of the IE header (total) constructed... cbRSNIe = pRSNIe->IeHeader.Length + sizeof( pRSNIe->IeHeader ); @@ -4007,8 +4034,10 @@ tANI_U8 csrConstructWapiIe( tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamPro pWapi = (tANI_U8 *) (&pWapiIe->AuthOui[ 1 ]); - *pWapi = (tANI_U16)1; //cUnicastCyphers - pWapi+=2; + *pWapi = (tANI_U8)1; //cUnicastCyphers + pWapi+=1; + *pWapi = (tANI_U8)0; //cUnicastCyphers + pWapi+=1; palCopyMemory( pMac->hHdd, pWapi, UnicastCypher, sizeof( UnicastCypher ) ); pWapi += sizeof( UnicastCypher ); @@ -4603,6 +4632,7 @@ tAniEdType csrTranslateEncryptTypeToEdType( eCsrEncryptionType EncryptType ) #ifdef FEATURE_WLAN_WAPI case eCSR_ENCRYPT_TYPE_WPI: edType = eSIR_ED_WPI; + break ; #endif #ifdef WLAN_FEATURE_11W //11w BIP @@ -5741,10 +5771,6 @@ void csrReleaseProfile(tpAniSirGlobal pMac, tCsrRoamProfile *pProfile) palFreeMemory(pMac->hHdd, pProfile->pAddIEAssoc); pProfile->pAddIEAssoc = NULL; } - { - palFreeMemory(pMac->hHdd, pProfile->pAddIEAssoc); - pProfile->pAddIEAssoc = NULL; - } if(pProfile->ChannelInfo.ChannelList) { @@ -5752,7 +5778,6 @@ void csrReleaseProfile(tpAniSirGlobal pMac, tCsrRoamProfile *pProfile) pProfile->ChannelInfo.ChannelList = NULL; } - palZeroMemory(pMac->hHdd, pProfile, sizeof(tCsrRoamProfile)); } } diff --git a/drivers/staging/prima/CORE/SME/src/pmc/pmc.c b/drivers/staging/prima/CORE/SME/src/pmc/pmc.c index 9fddc375761..d27e9a0ec48 100644 --- a/drivers/staging/prima/CORE/SME/src/pmc/pmc.c +++ b/drivers/staging/prima/CORE/SME/src/pmc/pmc.c @@ -18,6 +18,27 @@ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ +/* + * Copyright (c) 2012, The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + /****************************************************************************** * @@ -2107,7 +2128,7 @@ eHalStatus pmcIssueCommand( tpAniSirGlobal pMac, eSmeCommandType cmdType, void * { smePushCommand( pMac, pCommand, fPutToListHead ); } - else + else if( pCommand ) { pmcReleaseCommand( pMac, pCommand ); } @@ -2458,6 +2479,13 @@ eHalStatus pmcEnterImpsCheck( tpAniSirGlobal pMac ) return eHAL_STATUS_PMC_ALREADY_IN_IMPS; } + /* Check whether driver load unload is in progress */ + if(vos_is_load_unload_in_progress( VOS_MODULE_ID_VOSS, NULL)) + { + smsLog(pMac, LOGW, FL("Driver load/unload is in progress")); + return eHAL_STATUS_PMC_NOT_NOW; + } + return ( eHAL_STATUS_SUCCESS ); } diff --git a/drivers/staging/prima/CORE/SME/src/pmc/pmcApi.c b/drivers/staging/prima/CORE/SME/src/pmc/pmcApi.c index ad012c5f141..1e556f1932a 100644 --- a/drivers/staging/prima/CORE/SME/src/pmc/pmcApi.c +++ b/drivers/staging/prima/CORE/SME/src/pmc/pmcApi.c @@ -1,43 +1,23 @@ /* - * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. - * - * Previously licensed under the ISC license by Qualcomm Atheros, Inc. - * - * - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all - * copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ -/* - * Copyright (c) 2012, The Linux Foundation. All rights reserved. - * - * Previously licensed under the ISC license by Qualcomm Atheros, Inc. - * - * - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all - * copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ + * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. +*/ /****************************************************************************** * @@ -45,10 +25,6 @@ * * Description: Routines that make up the Power Management Control (PMC) API. * -* Copyright 2008 (c) Qualcomm, Incorporated. -* All Rights Reserved. -* Qualcomm Confidential and Proprietary. -* ******************************************************************************/ #include "palTypes.h" @@ -124,14 +100,14 @@ eHalStatus pmcOpen (tHalHandle hHal) /* Allocate a timer used in Full Power State to measure traffic levels and determine when to enter BMPS. */ - if (!VOS_IS_STATUS_SUCCESS(vos_timer_init(&pMac->pmc.hTrafficTimer, + if (!VOS_IS_STATUS_SUCCESS(vos_timer_init(&pMac->pmc.hTrafficTimer, VOS_TIMER_TYPE_SW, pmcTrafficTimerExpired, hHal))) { smsLog(pMac, LOGE, FL("Cannot allocate timer for traffic measurement")); return eHAL_STATUS_FAILURE; } -#ifdef FEATURE_WLAN_DIAG_SUPPORT +#ifdef FEATURE_WLAN_DIAG_SUPPORT /* Allocate a timer used to report current PMC state through periodic DIAG event */ if (palTimerAlloc(pMac->hHdd, &pMac->pmc.hDiagEvtTimer, pmcDiagEvtTimerExpired, hHal) != eHAL_STATUS_SUCCESS) { @@ -140,7 +116,7 @@ eHalStatus pmcOpen (tHalHandle hHal) } #endif - //Initialize the default value for Bmps related config. + //Initialize the default value for Bmps related config. pMac->pmc.bmpsConfig.trafficMeasurePeriod = BMPS_TRAFFIC_TIMER_DEFAULT; pMac->pmc.bmpsConfig.bmpsPeriod = WNI_CFG_LISTEN_INTERVAL_STADEF; @@ -152,7 +128,7 @@ eHalStatus pmcOpen (tHalHandle hHal) PMC_ABORT; return eHAL_STATUS_FAILURE; } - + /* Initialize lists for power save check routines and request full power callback routines. */ if (csrLLOpen(pMac->hHdd, &pMac->pmc.powerSaveCheckList) != eHAL_STATUS_SUCCESS) { @@ -262,12 +238,12 @@ eHalStatus pmcStart (tHalHandle hHal) } else htMimoPowerSaveState = eSIR_HT_MIMO_PS_NO_LIMIT; - + if (pmcSendMessage(hHal, eWNI_PMC_SMPS_STATE_IND, &htMimoPowerSaveState, sizeof(tSirMacHTMIMOPowerSaveState)) != eHAL_STATUS_SUCCESS) return eHAL_STATUS_FAILURE; -#ifdef FEATURE_WLAN_DIAG_SUPPORT +#ifdef FEATURE_WLAN_DIAG_SUPPORT if (pmcStartDiagEvtTimer(hHal) != eHAL_STATUS_SUCCESS) { return eHAL_STATUS_FAILURE; @@ -313,7 +289,7 @@ eHalStatus pmcStop (tHalHandle hHal) pmcStopTrafficTimer(hHal); -#ifdef FEATURE_WLAN_DIAG_SUPPORT +#ifdef FEATURE_WLAN_DIAG_SUPPORT pmcStopDiagEvtTimer(hHal); #endif @@ -376,7 +352,7 @@ eHalStatus pmcClose (tHalHandle hHal) { smsLog(pMac, LOGE, FL("Cannot deallocate traffic timer")); } -#ifdef FEATURE_WLAN_DIAG_SUPPORT +#ifdef FEATURE_WLAN_DIAG_SUPPORT if (palTimerFree(pMac->hHdd, pMac->pmc.hDiagEvtTimer) != eHAL_STATUS_SUCCESS) { smsLog(pMac, LOGE, FL("Cannot deallocate timer for diag event reporting")); @@ -388,7 +364,7 @@ eHalStatus pmcClose (tHalHandle hHal) } /* - The following list's entries are dynamically allocated so they need their own + The following list's entries are dynamically allocated so they need their own cleanup function */ pmcClosePowerSaveCheckList(pMac); @@ -464,7 +440,7 @@ eHalStatus pmcSignalPowerEvent (tHalHandle hHal, tPmcPowerEvent event) if (pMac->pmc.smpsConfig.mode == ePMC_STATIC_SMPS) htMimoPowerSaveState = eSIR_HT_MIMO_PS_STATIC; if (pmcSendMessage(hHal, eWNI_PMC_SMPS_STATE_IND, &htMimoPowerSaveState, - sizeof(tSirMacHTMIMOPowerSaveState)) != eHAL_STATUS_SUCCESS) + sizeof(tSirMacHTMIMOPowerSaveState)) != eHAL_STATUS_SUCCESS) return eHAL_STATUS_FAILURE; } return eHAL_STATUS_SUCCESS; @@ -521,7 +497,7 @@ eHalStatus pmcSetConfigPowerSave (tHalHandle hHal, tPmcPowerSavingMode psMode, v /* Configure the specified power saving mode. */ switch (psMode) { - + case ePMC_IDLE_MODE_POWER_SAVE: pMac->pmc.impsConfig = *(tpPmcImpsConfigParams)pConfigParams; smsLog(pMac, LOG3, FL("IMPS configuration")); @@ -555,13 +531,13 @@ eHalStatus pmcSetConfigPowerSave (tHalHandle hHal, tPmcPowerSavingMode psMode, v smsLog(pMac, LOG3, " value of bcnEarlyTermWakeInterval: %d", pMac->pmc.bmpsConfig.bcnEarlyTermWakeInterval); -#ifdef FEATURE_WLAN_DIAG_SUPPORT +#ifdef FEATURE_WLAN_DIAG_SUPPORT vos_mem_zero(&psRequest, sizeof(vos_event_wlan_powersave_payload_type)); psRequest.event_subtype = WLAN_BMPS_SET_CONFIG; /* possible loss of data due to mismatch but expectation is that values can reasonably be expected to fit in target widths */ psRequest.bmps_auto_timer_duration = (v_U16_t)pMac->pmc.bmpsConfig.trafficMeasurePeriod; - psRequest.bmps_period = (v_U16_t)pMac->pmc.bmpsConfig.bmpsPeriod; + psRequest.bmps_period = (v_U16_t)pMac->pmc.bmpsConfig.bmpsPeriod; WLAN_VOS_DIAG_EVENT_REPORT(&psRequest, EVENT_WLAN_POWERSAVE_GENERIC); #endif @@ -621,7 +597,7 @@ eHalStatus pmcGetConfigPowerSave (tHalHandle hHal, tPmcPowerSavingMode psMode, v /* Configure the specified power saving mode. */ switch (psMode) { - + case ePMC_IDLE_MODE_POWER_SAVE: *(tpPmcImpsConfigParams)pConfigParams = pMac->pmc.impsConfig; break; @@ -662,7 +638,7 @@ eHalStatus pmcEnablePowerSave (tHalHandle hHal, tPmcPowerSavingMode psMode) tpAniSirGlobal pMac = PMAC_STRUCT(hHal); tSirMacHTMIMOPowerSaveState htMimoPowerSaveState; -#ifdef FEATURE_WLAN_DIAG_SUPPORT +#ifdef FEATURE_WLAN_DIAG_SUPPORT WLAN_VOS_DIAG_EVENT_DEF(psRequest, vos_event_wlan_powersave_payload_type); vos_mem_zero(&psRequest, sizeof(vos_event_wlan_powersave_payload_type)); @@ -671,7 +647,7 @@ eHalStatus pmcEnablePowerSave (tHalHandle hHal, tPmcPowerSavingMode psMode) WLAN_VOS_DIAG_EVENT_REPORT(&psRequest, EVENT_WLAN_POWERSAVE_GENERIC); #endif - + smsLog(pMac, LOG2, FL("Entering pmcEnablePowerSave, power save mode %d"), psMode); /* Enable the specified power saving mode. */ @@ -730,13 +706,13 @@ eHalStatus pmcEnablePowerSave (tHalHandle hHal, tPmcPowerSavingMode psMode) module for entry into Bmps mode. This timer is started only if BMPS is enabled and whenever the device is in full power. \param hHal - The handle returned by macOpen. - \return eHalStatus + \return eHalStatus ---------------------------------------------------------------------------*/ -eHalStatus pmcStartAutoBmpsTimer (tHalHandle hHal) +eHalStatus pmcStartAutoBmpsTimer (tHalHandle hHal) { tpAniSirGlobal pMac = PMAC_STRUCT(hHal); -#ifdef FEATURE_WLAN_DIAG_SUPPORT +#ifdef FEATURE_WLAN_DIAG_SUPPORT WLAN_VOS_DIAG_EVENT_DEF(psRequest, vos_event_wlan_powersave_payload_type); vos_mem_zero(&psRequest, sizeof(vos_event_wlan_powersave_payload_type)); @@ -756,7 +732,7 @@ eHalStatus pmcStartAutoBmpsTimer (tHalHandle hHal) pMac->pmc.autoBmpsEntryEnabled = TRUE; - /* Check if there is an Infra session. If there is no Infra session, timer will be started + /* Check if there is an Infra session. If there is no Infra session, timer will be started when STA associates to AP */ if (pmcShouldBmpsTimerRun(pMac)) @@ -776,13 +752,13 @@ eHalStatus pmcStartAutoBmpsTimer (tHalHandle hHal) Stopping the timer does not cause a device state change. Only the timer is stopped. If "Full Power" is desired, use the pmcRequestFullPower API \param hHal - The handle returned by macOpen. - \return eHalStatus + \return eHalStatus ---------------------------------------------------------------------------*/ eHalStatus pmcStopAutoBmpsTimer (tHalHandle hHal) { tpAniSirGlobal pMac = PMAC_STRUCT(hHal); -#ifdef FEATURE_WLAN_DIAG_SUPPORT +#ifdef FEATURE_WLAN_DIAG_SUPPORT WLAN_VOS_DIAG_EVENT_DEF(psRequest, vos_event_wlan_powersave_payload_type); vos_mem_zero(&psRequest, sizeof(vos_event_wlan_powersave_payload_type)); @@ -822,7 +798,7 @@ eHalStatus pmcDisablePowerSave (tHalHandle hHal, tPmcPowerSavingMode psMode) tpAniSirGlobal pMac = PMAC_STRUCT(hHal); tSirMacHTMIMOPowerSaveState htMimoPowerSaveState; -#ifdef FEATURE_WLAN_DIAG_SUPPORT +#ifdef FEATURE_WLAN_DIAG_SUPPORT WLAN_VOS_DIAG_EVENT_DEF(psRequest, vos_event_wlan_powersave_payload_type); vos_mem_zero(&psRequest, sizeof(vos_event_wlan_powersave_payload_type)); @@ -911,7 +887,7 @@ eHalStatus pmcQueryPowerState (tHalHandle hHal, tPmcPowerState *pPowerState, /* Return current power state based on PMC state. */ switch (pMac->pmc.pmcState) { - + case FULL_POWER: *pPowerState = ePMC_FULL_POWER; break; @@ -960,7 +936,7 @@ tANI_BOOLEAN pmcIsPowerSaveEnabled (tHalHandle hHal, tPmcPowerSavingMode psMode) /* Check ability to enter based on the specified power saving mode. */ switch (psMode) { - + case ePMC_IDLE_MODE_POWER_SAVE: return pMac->pmc.impsEnabled && (pMac->pmc.powerSource != AC_POWER || pMac->pmc.impsConfig.enterOnAc); @@ -1021,13 +997,13 @@ eHalStatus pmcRequestFullPower (tHalHandle hHal, void (*callbackRoutine) (void * tpAniSirGlobal pMac = PMAC_STRUCT(hHal); tpRequestFullPowerEntry pEntry; -#ifdef FEATURE_WLAN_DIAG_SUPPORT +#ifdef FEATURE_WLAN_DIAG_SUPPORT WLAN_VOS_DIAG_EVENT_DEF(psRequest, vos_event_wlan_powersave_payload_type); vos_mem_zero(&psRequest, sizeof(vos_event_wlan_powersave_payload_type)); psRequest.event_subtype = WLAN_ENTER_FULL_POWER_REQ; psRequest.full_power_request_reason = fullPowerReason; - + WLAN_VOS_DIAG_EVENT_REPORT(&psRequest, EVENT_WLAN_POWERSAVE_GENERIC); #endif @@ -1125,7 +1101,7 @@ eHalStatus pmcRequestImps (tHalHandle hHal, tANI_U32 impsPeriod, tpAniSirGlobal pMac = PMAC_STRUCT(hHal); eHalStatus status; -#ifdef FEATURE_WLAN_DIAG_SUPPORT +#ifdef FEATURE_WLAN_DIAG_SUPPORT WLAN_VOS_DIAG_EVENT_DEF(psRequest, vos_event_wlan_powersave_payload_type); vos_mem_zero(&psRequest, sizeof(vos_event_wlan_powersave_payload_type)); @@ -1362,15 +1338,16 @@ static void pmcProcessResponse( tpAniSirGlobal pMac, tSirSmeRsp *pMsg ) /* Check that we are in the correct state for this message. */ if (pMac->pmc.pmcState != REQUEST_FULL_POWER) { - smsLog(pMac, LOGE, FL("Got Exit IMPS Response Message while in state %d"), pMac->pmc.pmcState); + smsLog(pMac, LOGE, FL("Got Exit IMPS Response Message while " + "in state %d"), pMac->pmc.pmcState); break; } /* Enter Full Power State. */ if (pMsg->statusCode != eSIR_SME_SUCCESS) { - smsLog(pMac, LOGP, FL("Response message to request to exit IMPS indicates failure, status %x"), - pMsg->statusCode); + smsLog(pMac, LOGE, FL("Response message to request to exit " + "IMPS indicates failure, status %x"), pMsg->statusCode); } pmcEnterFullPowerState(pMac); break; @@ -1454,7 +1431,7 @@ static void pmcProcessResponse( tpAniSirGlobal pMac, tSirSmeRsp *pMsg ) } /* Enter UAPSD State if response indicates success. */ - if (pMsg->statusCode == eSIR_SME_SUCCESS) + if (pMsg->statusCode == eSIR_SME_SUCCESS) { pmcEnterUapsdState(pMac); pmcDoStartUapsdCallbacks(pMac, eHAL_STATUS_SUCCESS); @@ -1729,7 +1706,7 @@ eHalStatus pmcRequestBmps ( tpRequestBmpsEntry pEntry; eHalStatus status; -#ifdef FEATURE_WLAN_DIAG_SUPPORT +#ifdef FEATURE_WLAN_DIAG_SUPPORT WLAN_VOS_DIAG_EVENT_DEF(psRequest, vos_event_wlan_powersave_payload_type); vos_mem_zero(&psRequest, sizeof(vos_event_wlan_powersave_payload_type)); @@ -1747,7 +1724,7 @@ eHalStatus pmcRequestBmps ( pMac->pmc.bmpsRequestedByHdd = TRUE; return eHAL_STATUS_SUCCESS; } - + status = pmcEnterBmpsCheck( pMac ); if(HAL_STATUS_SUCCESS( status )) { @@ -1785,6 +1762,24 @@ eHalStatus pmcRequestBmps ( status = eHAL_STATUS_FAILURE; } } + /* Retry to enter the BMPS if the + status = eHAL_STATUS_PMC_NOT_NOW */ + else if (status == eHAL_STATUS_PMC_NOT_NOW) + { + pmcStopTrafficTimer(hHal); + smsLog(pMac, LOG1, FL("Can't enter BMPS+++")); + if (pmcShouldBmpsTimerRun(pMac)) + { + if (pmcStartTrafficTimer(pMac, + pMac->pmc.bmpsConfig.trafficMeasurePeriod) + != eHAL_STATUS_SUCCESS) + { + smsLog(pMac, LOG1, FL("Cannot start BMPS Retry timer")); + } + smsLog(pMac, LOG1, + FL("BMPS Retry Timer already running or started")); + } + } return status; } @@ -1817,7 +1812,7 @@ eHalStatus pmcStartUapsd ( tpAniSirGlobal pMac = PMAC_STRUCT(hHal); tpStartUapsdEntry pEntry; -#ifdef FEATURE_WLAN_DIAG_SUPPORT +#ifdef FEATURE_WLAN_DIAG_SUPPORT WLAN_VOS_DIAG_EVENT_DEF(psRequest, vos_event_wlan_powersave_payload_type); vos_mem_zero(&psRequest, sizeof(vos_event_wlan_powersave_payload_type)); @@ -1906,7 +1901,7 @@ eHalStatus pmcStopUapsd (tHalHandle hHal) { tpAniSirGlobal pMac = PMAC_STRUCT(hHal); -#ifdef FEATURE_WLAN_DIAG_SUPPORT +#ifdef FEATURE_WLAN_DIAG_SUPPORT WLAN_VOS_DIAG_EVENT_DEF(psRequest, vos_event_wlan_powersave_payload_type); vos_mem_zero(&psRequest, sizeof(vos_event_wlan_powersave_payload_type)); @@ -1942,7 +1937,7 @@ eHalStatus pmcStopUapsd (tHalHandle hHal) \param hHal - The handle returned by macOpen. \param callbackRoutine - Callback routine invoked in case of success/failure \param callbackContext - value to be passed as parameter to callback - \return eHalStatus + \return eHalStatus eHAL_STATUS_SUCCESS - device is in Standby mode eHAL_STATUS_FAILURE - device cannot be put in standby mode eHAL_STATUS_PMC_PENDING - device is being put in standby mode @@ -1954,7 +1949,7 @@ extern eHalStatus pmcRequestStandby ( { tpAniSirGlobal pMac = PMAC_STRUCT(hHal); -#ifdef FEATURE_WLAN_DIAG_SUPPORT +#ifdef FEATURE_WLAN_DIAG_SUPPORT WLAN_VOS_DIAG_EVENT_DEF(psRequest, vos_event_wlan_powersave_payload_type); vos_mem_zero(&psRequest, sizeof(vos_event_wlan_powersave_payload_type)); @@ -1984,10 +1979,10 @@ extern eHalStatus pmcRequestStandby ( if (pMac->pmc.pmcState == STANDBY) return eHAL_STATUS_SUCCESS; - + if (csrIsIBSSStarted(pMac) || csrIsBTAMPStarted(pMac)) { - VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL, + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL, "WLAN: IBSS or BT-AMP session present. Cannot honor standby request"); return eHAL_STATUS_PMC_NOT_NOW; } @@ -2012,9 +2007,9 @@ extern eHalStatus pmcRequestStandby ( \param callbackContext - Cookie to be passed back during callback \return eHalStatus eHAL_STATUS_SUCCESS - successfully registered - eHAL_STATUS_FAILURE - not successfully registered + eHAL_STATUS_FAILURE - not successfully registered ---------------------------------------------------------------------------*/ -extern eHalStatus pmcRegisterDeviceStateUpdateInd (tHalHandle hHal, +extern eHalStatus pmcRegisterDeviceStateUpdateInd (tHalHandle hHal, void (*callbackRoutine) (void *callbackContext, tPmcState pmcState), void *callbackContext) { @@ -2049,9 +2044,9 @@ extern eHalStatus pmcRegisterDeviceStateUpdateInd (tHalHandle hHal, \param callbackRoutine - Callback routine to be deregistered \return eHalStatus eHAL_STATUS_SUCCESS - successfully deregistered - eHAL_STATUS_FAILURE - not successfully deregistered + eHAL_STATUS_FAILURE - not successfully deregistered ---------------------------------------------------------------------------*/ -eHalStatus pmcDeregisterDeviceStateUpdateInd (tHalHandle hHal, +eHalStatus pmcDeregisterDeviceStateUpdateInd (tHalHandle hHal, void (*callbackRoutine) (void *callbackContext, tPmcState pmcState)) { tpAniSirGlobal pMac = PMAC_STRUCT(hHal); @@ -2093,7 +2088,7 @@ eHalStatus pmcDeregisterDeviceStateUpdateInd (tHalHandle hHal, \brief fn to inform PMC that eWNI_SME_SYS_READY_IND has been sent to PE. This acts as a trigger to send a message to PE to update the power save related conig to FW. Note that if HDD configures any power save - related stuff before this API is invoked, PMC will buffer all the + related stuff before this API is invoked, PMC will buffer all the configutaion. \param hHal - The handle returned by macOpen. \return eHalStatus @@ -2123,16 +2118,16 @@ eHalStatus pmcReady(tHalHandle hHal) \fn pmcWowlAddBcastPattern \brief Add a pattern for Pattern Byte Matching in Wowl mode. Firmware will do a pattern match on these patterns when Wowl is enabled during BMPS - mode. Note that Firmware performs the pattern matching only on + mode. Note that Firmware performs the pattern matching only on broadcast frames and while Libra is in BMPS mode. \param hHal - The handle returned by macOpen. \param pattern - Pointer to the pattern to be added \return eHalStatus eHAL_STATUS_FAILURE Cannot add pattern - eHAL_STATUS_SUCCESS Request accepted. + eHAL_STATUS_SUCCESS Request accepted. ---------------------------------------------------------------------------*/ eHalStatus pmcWowlAddBcastPattern ( - tHalHandle hHal, + tHalHandle hHal, tpSirWowlAddBcastPtrn pattern, tANI_U8 sessionId) { @@ -2192,14 +2187,14 @@ eHalStatus pmcWowlAddBcastPattern ( eHalStatus status; vos_mem_copy(pattern->bssId, pSession->connectedProfile.bssid, sizeof(tSirMacAddr)); //Wake up the chip first - status = pmcDeferMsg( pMac, eWNI_PMC_WOWL_ADD_BCAST_PTRN, + status = pmcDeferMsg( pMac, eWNI_PMC_WOWL_ADD_BCAST_PTRN, pattern, sizeof(tSirWowlAddBcastPtrn) ); if( eHAL_STATUS_PMC_PENDING == status ) { return eHAL_STATUS_SUCCESS; } - else + else { //either fail or already in full power if( !HAL_STATUS_SUCCESS( status ) ) @@ -2227,22 +2222,22 @@ eHalStatus pmcWowlAddBcastPattern ( \param pattern - Pattern to be deleted \return eHalStatus eHAL_STATUS_FAILURE Cannot delete pattern - eHAL_STATUS_SUCCESS Request accepted. + eHAL_STATUS_SUCCESS Request accepted. ---------------------------------------------------------------------------*/ eHalStatus pmcWowlDelBcastPattern ( - tHalHandle hHal, + tHalHandle hHal, tpSirWowlDelBcastPtrn pattern, tANI_U8 sessionId) { tpAniSirGlobal pMac = PMAC_STRUCT(hHal); tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); -#ifdef FEATURE_WLAN_DIAG_SUPPORT +#ifdef FEATURE_WLAN_DIAG_SUPPORT WLAN_VOS_DIAG_EVENT_DEF(wowRequest, vos_event_wlan_powersave_wow_payload_type); vos_mem_zero(&wowRequest, sizeof(vos_event_wlan_powersave_wow_payload_type)); wowRequest.event_subtype = WLAN_WOW_DEL_PTRN_REQ; - wowRequest.wow_del_ptrn_id = pattern->ucPatternId; + wowRequest.wow_del_ptrn_id = pattern->ucPatternId; WLAN_VOS_DIAG_EVENT_REPORT(&wowRequest, EVENT_WLAN_POWERSAVE_WOW); #endif @@ -2275,14 +2270,14 @@ eHalStatus pmcWowlDelBcastPattern ( vos_mem_copy(pattern->bssId, pSession->connectedProfile.bssid, sizeof(tSirMacAddr)); //Wake up the chip first - status = pmcDeferMsg( pMac, eWNI_PMC_WOWL_DEL_BCAST_PTRN, + status = pmcDeferMsg( pMac, eWNI_PMC_WOWL_DEL_BCAST_PTRN, pattern, sizeof(tSirWowlDelBcastPtrn) ); if( eHAL_STATUS_PMC_PENDING == status ) { return eHAL_STATUS_SUCCESS; } - else + else { //either fail or already in full power if( !HAL_STATUS_SUCCESS( status ) ) @@ -2309,20 +2304,20 @@ eHalStatus pmcWowlDelBcastPattern ( Note 1: If "fullPowerReason" specificied in this API is set to eSME_FULL_PWR_NEEDED_BY_HDD, PMC will clear any "buffered wowl" requests and also clear any "buffered BMPS requests by HDD". Assumption is that since - HDD is requesting full power, we need to undo any previous HDD requests for + HDD is requesting full power, we need to undo any previous HDD requests for BMPS (using sme_RequestBmps) or WoWL (using sme_EnterWoWL). If the reason is specified anything other than above, the buffered requests for BMPS and WoWL will not be cleared. Note 2: Requesting full power (no matter what the fullPowerReason is) doesn't disable the "auto bmps timer" (if it is enabled) or clear any "buffered uapsd request". - Note 3: When the device finally enters Full Power PMC will start a timer + Note 3: When the device finally enters Full Power PMC will start a timer if any of the following holds true: - Auto BMPS mode is enabled - Uapsd request is pending - HDD's request for BMPS is pending - HDD's request for WoWL is pending - On timer expiry PMC will attempt to put the device in BMPS mode if following + On timer expiry PMC will attempt to put the device in BMPS mode if following (in addition to those listed above) holds true: - Polling of all modules through the Power Save Check routine passes - STA is associated to an access point @@ -2333,13 +2328,13 @@ eHalStatus pmcWowlDelBcastPattern ( \param - wakeReasonIndCBContext - Cookie to be passed back during callback \param - fullPowerReason - Reason why this API is being invoked. SME needs to distinguish between BAP and HDD requests - \return eHalStatus - status + \return eHalStatus - status eHAL_STATUS_SUCCESS - device brought to full power state eHAL_STATUS_FAILURE - device cannot be brought to full power state eHAL_STATUS_PMC_PENDING - device is being brought to full power state, ---------------------------------------------------------------------------*/ -eHalStatus pmcEnterWowl ( - tHalHandle hHal, +eHalStatus pmcEnterWowl ( + tHalHandle hHal, void (*enterWowlCallbackRoutine) (void *callbackContext, eHalStatus status), void *enterWowlCallbackContext, #ifdef WLAN_WAKEUP_EVENTS @@ -2351,7 +2346,7 @@ eHalStatus pmcEnterWowl ( tpAniSirGlobal pMac = PMAC_STRUCT(hHal); tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); -#ifdef FEATURE_WLAN_DIAG_SUPPORT +#ifdef FEATURE_WLAN_DIAG_SUPPORT WLAN_VOS_DIAG_EVENT_DEF(wowRequest, vos_event_wlan_powersave_wow_payload_type); vos_mem_zero(&wowRequest, sizeof(vos_event_wlan_powersave_wow_payload_type)); @@ -2379,7 +2374,7 @@ eHalStatus pmcEnterWowl ( return eHAL_STATUS_FAILURE; } - vos_mem_copy(wowlEnterParams->bssId, pSession->connectedProfile.bssid, + vos_mem_copy(wowlEnterParams->bssId, pSession->connectedProfile.bssid, sizeof(tSirMacAddr)); if( !PMC_IS_READY(pMac) ) @@ -2450,19 +2445,19 @@ eHalStatus pmcEnterWowl ( /* --------------------------------------------------------------------------- \fn pmcExitWowl - \brief This is the SME API exposed to HDD to request exit from WoWLAN mode. - SME will initiate exit from WoWLAN mode and device will be put in BMPS + \brief This is the SME API exposed to HDD to request exit from WoWLAN mode. + SME will initiate exit from WoWLAN mode and device will be put in BMPS mode. \param hHal - The handle returned by macOpen. \return eHalStatus eHAL_STATUS_FAILURE Device cannot exit WoWLAN mode. - eHAL_STATUS_SUCCESS Request accepted to exit WoWLAN mode. + eHAL_STATUS_SUCCESS Request accepted to exit WoWLAN mode. ---------------------------------------------------------------------------*/ eHalStatus pmcExitWowl (tHalHandle hHal) { tpAniSirGlobal pMac = PMAC_STRUCT(hHal); -#ifdef FEATURE_WLAN_DIAG_SUPPORT +#ifdef FEATURE_WLAN_DIAG_SUPPORT WLAN_VOS_DIAG_EVENT_DEF(wowRequest, vos_event_wlan_powersave_wow_payload_type); vos_mem_zero(&wowRequest, sizeof(vos_event_wlan_powersave_wow_payload_type)); @@ -2496,9 +2491,9 @@ eHalStatus pmcExitWowl (tHalHandle hHal) \param pRequest - Pointer to the offload request. \return eHalStatus eHAL_STATUS_FAILURE Cannot set the offload. - eHAL_STATUS_SUCCESS Request accepted. + eHAL_STATUS_SUCCESS Request accepted. ---------------------------------------------------------------------------*/ -eHalStatus pmcSetHostOffload (tHalHandle hHal, tpSirHostOffloadReq pRequest, +eHalStatus pmcSetHostOffload (tHalHandle hHal, tpSirHostOffloadReq pRequest, tANI_U8 sessionId) { tpSirHostOffloadReq pRequestBuf; @@ -2547,7 +2542,7 @@ eHalStatus pmcSetHostOffload (tHalHandle hHal, tpSirHostOffloadReq pRequest, \param pRequest - Pointer to the Keep Alive. \return eHalStatus eHAL_STATUS_FAILURE Cannot set the keepalive. - eHAL_STATUS_SUCCESS Request accepted. + eHAL_STATUS_SUCCESS Request accepted. ---------------------------------------------------------------------------*/ eHalStatus pmcSetKeepAlive (tHalHandle hHal, tpSirKeepAliveReq pRequest, tANI_U8 sessionId) { @@ -2605,15 +2600,14 @@ eHalStatus pmcSetKeepAlive (tHalHandle hHal, tpSirKeepAliveReq pRequest, tANI_U8 \param pRequest - Pointer to the offload request. \return eHalStatus eHAL_STATUS_FAILURE Cannot set the offload. - eHAL_STATUS_SUCCESS Request accepted. + eHAL_STATUS_SUCCESS Request accepted. ---------------------------------------------------------------------------*/ -eHalStatus pmcSetNSOffload (tHalHandle hHal, tpSirHostOffloadReq pRequest, +eHalStatus pmcSetNSOffload (tHalHandle hHal, tpSirHostOffloadReq pRequest, tANI_U8 sessionId) { tpAniSirGlobal pMac = PMAC_STRUCT(hHal); tpSirHostOffloadReq pRequestBuf; vos_msg_t msg; - int i; tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); if( NULL == pSession ) @@ -2622,7 +2616,7 @@ eHalStatus pmcSetNSOffload (tHalHandle hHal, tpSirHostOffloadReq pRequest, return eHAL_STATUS_FAILURE; } - vos_mem_copy(pRequest->bssId, pSession->connectedProfile.bssid, + vos_mem_copy(pRequest->bssId, pSession->connectedProfile.bssid, sizeof(tSirMacAddr)); pRequestBuf = vos_mem_malloc(sizeof(tSirHostOffloadReq)); @@ -2777,7 +2771,7 @@ void pmcCloseDeferredMsgList(tpAniSirGlobal pMac) #ifdef FEATURE_WLAN_SCAN_PNO -static tSirRetStatus +static tSirRetStatus pmcPopulateMacHeader( tpAniSirGlobal pMac, tANI_U8* pBD, tANI_U8 type, @@ -2787,7 +2781,7 @@ pmcPopulateMacHeader( tpAniSirGlobal pMac, { tSirRetStatus statusCode = eSIR_SUCCESS; tpSirMacMgmtHdr pMacHdr; - + /// Prepare MAC management header pMacHdr = (tpSirMacMgmtHdr) (pBD); @@ -2840,12 +2834,12 @@ pmcPrepareProbeReqTemplate(tpAniSirGlobal pMac, PopulateDot11fExtSuppRates1( pMac, nChannelNum, &pr.ExtSuppRates ); } - + if (IS_DOT11_MODE_HT(dot11mode)) { PopulateDot11fHTCaps( pMac, NULL, &pr.HTCaps ); } - + // That's it-- now we pack it. First, how much space are we going to // need? nStatus = dot11fGetPackedProbeRequestSize( pMac, &pr, &nPayload ); @@ -2867,7 +2861,7 @@ pmcPrepareProbeReqTemplate(tpAniSirGlobal pMac, } nBytes = nPayload + sizeof( tSirMacMgmtHdr ); - + /* Prepare outgoing frame*/ palZeroMemory( pMac->hHdd, pFrame, nBytes ); @@ -2895,21 +2889,21 @@ pmcPrepareProbeReqTemplate(tpAniSirGlobal pMac, } else if ( DOT11F_WARNED( nStatus ) ) { - VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, - "There were warnings while packing a Probe Request (0x%08x)." ); + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "There were warnings while packing a Probe Request" ); } - *pusLen = nPayload + sizeof(tSirMacMgmtHdr); + *pusLen = nPayload + sizeof(tSirMacMgmtHdr); return eSIR_SUCCESS; } // End pmcPrepareProbeReqTemplate. eHalStatus pmcSetPreferredNetworkList ( - tHalHandle hHal, - tpSirPNOScanReq pRequest, - tANI_U8 sessionId, - preferredNetworkFoundIndCallback callbackRoutine, + tHalHandle hHal, + tpSirPNOScanReq pRequest, + tANI_U8 sessionId, + preferredNetworkFoundIndCallback callbackRoutine, void *callbackContext ) { @@ -2950,15 +2944,15 @@ eHalStatus pmcSetPreferredNetworkList vos_mem_copy(pRequestBuf, pRequest, sizeof(tSirPNOScanReq)); /*Must translate the mode first*/ - ucDot11Mode = (tANI_U8) csrTranslateToWNICfgDot11Mode(pMac, + ucDot11Mode = (tANI_U8) csrTranslateToWNICfgDot11Mode(pMac, csrFindBestPhyMode( pMac, pMac->roam.configParam.phyMode )); /*Prepare a probe request for 2.4GHz band and one for 5GHz band*/ - pmcPrepareProbeReqTemplate(pMac,SIR_PNO_24G_DEFAULT_CH, ucDot11Mode, pSession->selfMacAddr, - pRequestBuf->p24GProbeTemplate, &pRequestBuf->us24GProbeTemplateLen); + pmcPrepareProbeReqTemplate(pMac,SIR_PNO_24G_DEFAULT_CH, ucDot11Mode, pSession->selfMacAddr, + pRequestBuf->p24GProbeTemplate, &pRequestBuf->us24GProbeTemplateLen); - pmcPrepareProbeReqTemplate(pMac,SIR_PNO_5G_DEFAULT_CH, ucDot11Mode, pSession->selfMacAddr, - pRequestBuf->p5GProbeTemplate, &pRequestBuf->us5GProbeTemplateLen); + pmcPrepareProbeReqTemplate(pMac,SIR_PNO_5G_DEFAULT_CH, ucDot11Mode, pSession->selfMacAddr, + pRequestBuf->p5GProbeTemplate, &pRequestBuf->us5GProbeTemplateLen); msg.type = WDA_SET_PNO_REQ; @@ -2994,7 +2988,7 @@ eHalStatus pmcSetRssiFilter(tHalHandle hHal, v_U8_t rssiThreshold) } - pRequestBuf->rssiThreshold = rssiThreshold; + pRequestBuf->rssiThreshold = rssiThreshold; msg.type = WDA_SET_RSSI_FILTER_REQ; msg.reserved = 0; @@ -3025,18 +3019,18 @@ eHalStatus pmcUpdateScanParams(tHalHandle hHal, tCsrConfig *pRequest, tCsrChanne return eHAL_STATUS_FAILED_ALLOC; } - // + // // Fill pRequestBuf structure from pRequest // pRequestBuf->b11dEnabled = pRequest->Is11eSupportEnabled; pRequestBuf->b11dResolved = b11dResolved; - pRequestBuf->ucChannelCount = + pRequestBuf->ucChannelCount = ( pChannelList->numChannels < SIR_PNO_MAX_NETW_CHANNELS_EX )? pChannelList->numChannels:SIR_PNO_MAX_NETW_CHANNELS_EX; for (i=0; i < pRequestBuf->ucChannelCount; i++) - { - VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "%s: Channel List %d: %d", __FUNCTION__, i, pChannelList->channelList[i] ); pRequestBuf->aChannels[i] = pChannelList->channelList[i]; @@ -3044,7 +3038,7 @@ eHalStatus pmcUpdateScanParams(tHalHandle hHal, tCsrConfig *pRequest, tCsrChanne pRequestBuf->usPassiveMinChTime = pRequest->nPassiveMinChnTime; pRequestBuf->usPassiveMaxChTime = pRequest->nPassiveMaxChnTime; pRequestBuf->usActiveMinChTime = pRequest->nActiveMinChnTime; - pRequestBuf->usActiveMaxChTime = pRequest->nActiveMaxChnTime; + pRequestBuf->usActiveMaxChTime = pRequest->nActiveMaxChnTime; pRequestBuf->ucCBState = PHY_SINGLE_CHANNEL_CENTERED; msg.type = WDA_UPDATE_SCAN_PARAMS_REQ; @@ -3082,7 +3076,7 @@ eHalStatus pmcSetPowerParams(tHalHandle hHal, tSirSetPowerParamsReq* pwParams } - vos_mem_copy(pRequestBuf, pwParams, sizeof(*pRequestBuf)); + vos_mem_copy(pRequestBuf, pwParams, sizeof(*pRequestBuf)); msg.type = WDA_SET_POWER_PARAMS_REQ; @@ -3102,8 +3096,8 @@ eHalStatus pmcSetPowerParams(tHalHandle hHal, tSirSetPowerParamsReq* pwParams #ifdef WLAN_FEATURE_PACKET_FILTERING eHalStatus pmcGetFilterMatchCount ( - tHalHandle hHal, - FilterMatchCountCallback callbackRoutine, + tHalHandle hHal, + FilterMatchCountCallback callbackRoutine, void *callbackContext, tANI_U8 sessionId ) @@ -3113,8 +3107,8 @@ eHalStatus pmcGetFilterMatchCount tpAniSirGlobal pMac = PMAC_STRUCT(hHal); tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); - VOS_TRACE( VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, - "%s: filterId = %d", __func__); + VOS_TRACE( VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s", __func__); if(NULL == pSession ) { @@ -3132,7 +3126,7 @@ eHalStatus pmcGetFilterMatchCount return eHAL_STATUS_FAILED_ALLOC; } - vos_mem_copy(pRequestBuf->bssId, pSession->connectedProfile.bssid, sizeof(tSirMacAddr)); + vos_mem_copy(pRequestBuf->bssId, pSession->connectedProfile.bssid, sizeof(tSirMacAddr)); msg.type = WDA_PACKET_COALESCING_FILTER_MATCH_COUNT_REQ; msg.reserved = 0; @@ -3141,9 +3135,9 @@ eHalStatus pmcGetFilterMatchCount /* Cache the Packet Coalescing Filter Match Count callback information */ if (NULL != pMac->pmc.FilterMatchCountCB) { - // Do we need to check if the callback is in use? + // Do we need to check if the callback is in use? // Because we are not sending the same message again when it is pending, - // the only case when the callback is not NULL is that the previous message + // the only case when the callback is not NULL is that the previous message //was timed out or failed. // So, it will be safe to set the callback in this case. } @@ -3153,7 +3147,7 @@ eHalStatus pmcGetFilterMatchCount if(VOS_STATUS_SUCCESS != vos_mq_post_message(VOS_MODULE_ID_WDA, &msg)) { - VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Not able to post WDA_PACKET_COALESCING_FILTER_MATCH_COUNT_REQ " "message to WDA", __func__); vos_mem_free(pRequestBuf); @@ -3172,9 +3166,9 @@ eHalStatus pmcGetFilterMatchCount \param pGtkOffload - Pointer to the GTK offload request. \return eHalStatus eHAL_STATUS_FAILURE Cannot set the offload. - eHAL_STATUS_SUCCESS Request accepted. + eHAL_STATUS_SUCCESS Request accepted. ---------------------------------------------------------------------------*/ -eHalStatus pmcSetGTKOffload (tHalHandle hHal, tpSirGtkOffloadParams pGtkOffload, +eHalStatus pmcSetGTKOffload (tHalHandle hHal, tpSirGtkOffloadParams pGtkOffload, tANI_U8 sessionId) { tpSirGtkOffloadParams pRequestBuf; @@ -3182,7 +3176,7 @@ eHalStatus pmcSetGTKOffload (tHalHandle hHal, tpSirGtkOffloadParams pGtkOffload, tpAniSirGlobal pMac = PMAC_STRUCT(hHal); tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: KeyReplayCounter: %d", + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: KeyReplayCounter: %d", __func__, pGtkOffload->ullKeyReplayCounter); if(NULL == pSession ) @@ -3200,7 +3194,7 @@ eHalStatus pmcSetGTKOffload (tHalHandle hHal, tpSirGtkOffloadParams pGtkOffload, return eHAL_STATUS_FAILED_ALLOC; } - vos_mem_copy(pGtkOffload->bssId, pSession->connectedProfile.bssid, sizeof(tSirMacAddr)); + vos_mem_copy(pGtkOffload->bssId, pSession->connectedProfile.bssid, sizeof(tSirMacAddr)); vos_mem_copy(pRequestBuf, pGtkOffload, sizeof(tSirGtkOffloadParams)); @@ -3225,9 +3219,9 @@ eHalStatus pmcSetGTKOffload (tHalHandle hHal, tpSirGtkOffloadParams pGtkOffload, \param callbackRoutine - Pointer to the GTK Offload Get Info response callback routine. \return eHalStatus eHAL_STATUS_FAILURE Cannot set the offload. - eHAL_STATUS_SUCCESS Request accepted. + eHAL_STATUS_SUCCESS Request accepted. ---------------------------------------------------------------------------*/ -eHalStatus pmcGetGTKOffload(tHalHandle hHal, GTKOffloadGetInfoCallback callbackRoutine, +eHalStatus pmcGetGTKOffload(tHalHandle hHal, GTKOffloadGetInfoCallback callbackRoutine, void *callbackContext, tANI_U8 sessionId) { tpSirGtkOffloadGetInfoRspParams pRequestBuf; @@ -3235,12 +3229,12 @@ eHalStatus pmcGetGTKOffload(tHalHandle hHal, GTKOffloadGetInfoCallback callbackR tpAniSirGlobal pMac = PMAC_STRUCT(hHal); tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); - VOS_TRACE( VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "%s: filterId = %d", + VOS_TRACE( VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "%s: filterId = %d", __func__); if(NULL == pSession ) { - VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Session not found ", __func__); return eHAL_STATUS_FAILURE; } @@ -3254,7 +3248,7 @@ eHalStatus pmcGetGTKOffload(tHalHandle hHal, GTKOffloadGetInfoCallback callbackR return eHAL_STATUS_FAILED_ALLOC; } - vos_mem_copy(pRequestBuf->bssId, pSession->connectedProfile.bssid, sizeof(tSirMacAddr)); + vos_mem_copy(pRequestBuf->bssId, pSession->connectedProfile.bssid, sizeof(tSirMacAddr)); msg.type = WDA_GTK_OFFLOAD_GETINFO_REQ; msg.reserved = 0; @@ -3263,7 +3257,7 @@ eHalStatus pmcGetGTKOffload(tHalHandle hHal, GTKOffloadGetInfoCallback callbackR /* Cache the Get GTK Offload callback information */ if (NULL != pMac->pmc.GtkOffloadGetInfoCB) { - // Do we need to check if the callback is in use? + // Do we need to check if the callback is in use? // Because we are not sending the same message again when it is pending, // the only case when the callback is not NULL is that the previous message was timed out or failed. // So, it will be safe to set the callback in this case. @@ -3274,7 +3268,7 @@ eHalStatus pmcGetGTKOffload(tHalHandle hHal, GTKOffloadGetInfoCallback callbackR if (!VOS_IS_STATUS_SUCCESS(vos_mq_post_message(VOS_MODULE_ID_WDA, &msg))) { - VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Not able to post WDA_GTK_OFFLOAD_GETINFO_REQ message to WDA", + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Not able to post WDA_GTK_OFFLOAD_GETINFO_REQ message to WDA", __func__); vos_mem_free(pRequestBuf); return eHAL_STATUS_FAILURE; diff --git a/drivers/staging/prima/CORE/SME/src/rrm/sme_rrm.c b/drivers/staging/prima/CORE/SME/src/rrm/sme_rrm.c index 60dcda59680..c1934809d30 100644 --- a/drivers/staging/prima/CORE/SME/src/rrm/sme_rrm.c +++ b/drivers/staging/prima/CORE/SME/src/rrm/sme_rrm.c @@ -145,7 +145,7 @@ void rrmIndicateNeighborReportResult(tpAniSirGlobal pMac, VOS_STATUS vosStatus) /* Stop the timer if it is already running. The timer should be running only in the SUCCESS case. */ if (VOS_TIMER_STATE_RUNNING == vos_timer_getCurrentState(&pMac->rrm.rrmSmeContext.neighborReqControlInfo.neighborRspWaitTimer)) { - VOS_ASSERT(VOS_STATUS_SUCCESS == vosStatus); + smsLog( pMac, LOG1, FL("No entry in neighbor report cache")); vos_timer_stop(&pMac->rrm.rrmSmeContext.neighborReqControlInfo.neighborRspWaitTimer); } callback = pMac->rrm.rrmSmeContext.neighborReqControlInfo.neighborRspCallbackInfo.neighborRspCallback; @@ -236,6 +236,8 @@ static eHalStatus sme_RrmSendBeaconReportXmitInd( tpAniSirGlobal pMac, tCsrScanR pBssDesc = &pCurResult->BssDescriptor; ie_len = GET_IE_LEN_IN_BSS( pBssDesc->length ); pBeaconRep->pBssDescription[msgCounter] = vos_mem_malloc ( ie_len+sizeof(tSirBssDescription) ); + if (NULL == pBeaconRep->pBssDescription[msgCounter]) + break; vos_mem_copy( pBeaconRep->pBssDescription[msgCounter], pBssDesc, sizeof(tSirBssDescription) ); vos_mem_copy( &pBeaconRep->pBssDescription[msgCounter]->ieFields[0], pBssDesc->ieFields, ie_len ); @@ -259,9 +261,10 @@ static eHalStatus sme_RrmSendBeaconReportXmitInd( tpAniSirGlobal pMac, tCsrScanR pBeaconRep->fMeasureDone = (pCurResult)?false:measurementDone; - status = palSendMBMessage(pMac->hHdd, pBeaconRep); + smsLog(pMac, LOGW, "SME Sending BcnRepXmit to PE numBss %d", + pBeaconRep->numBssDesc); - smsLog( pMac, LOGW, "SME Sent BcnRepXmit to PE numBss %d", pBeaconRep->numBssDesc); + status = palSendMBMessage(pMac->hHdd, pBeaconRep); } while (pCurResult); @@ -767,8 +770,16 @@ static void rrmCalculateNeighborAPRoamScore(tpAniSirGlobal pMac, tpRrmNeighborRe tpSirNeighborBssDescripton pNeighborBssDesc; tANI_U32 roamScore = 0; - VOS_ASSERT(pNeighborReportDesc != NULL); - VOS_ASSERT(pNeighborReportDesc->pNeighborBssDescription != NULL); + if (NULL == pNeighborReportDesc) + { + VOS_ASSERT(0); + return; + } + if (NULL == pNeighborReportDesc->pNeighborBssDescription) + { + VOS_ASSERT(0); + return; + } pNeighborBssDesc = pNeighborReportDesc->pNeighborBssDescription; @@ -832,8 +843,16 @@ void rrmStoreNeighborRptByRoamScore(tpAniSirGlobal pMac, tpRrmNeighborReportDesc tListElem *pEntry; tRrmNeighborReportDesc *pTempNeighborReportDesc; - VOS_ASSERT(pNeighborReportDesc != NULL); - VOS_ASSERT(pNeighborReportDesc->pNeighborBssDescription != NULL); + if (NULL == pNeighborReportDesc) + { + VOS_ASSERT(0); + return; + } + if (NULL == pNeighborReportDesc->pNeighborBssDescription) + { + VOS_ASSERT(0); + return; + } if (csrLLIsListEmpty(&pSmeRrmContext->neighborReportCache, LL_ACCESS_LOCK)) { @@ -911,6 +930,7 @@ eHalStatus sme_RrmProcessNeighborReport(tpAniSirGlobal pMac, void *pMsgBuf) if (NULL == pNeighborReportDesc->pNeighborBssDescription) { smsLog( pMac, LOGE, "Failed to allocate memory for RRM Neighbor report BSS Description"); + vos_mem_free(pNeighborReportDesc); status = eHAL_STATUS_FAILED_ALLOC; goto end; } diff --git a/drivers/staging/prima/CORE/SME/src/sme_common/sme_Api.c b/drivers/staging/prima/CORE/SME/src/sme_common/sme_Api.c old mode 100644 new mode 100755 index 43656a7bafa..1f50bc871f1 --- a/drivers/staging/prima/CORE/SME/src/sme_common/sme_Api.c +++ b/drivers/staging/prima/CORE/SME/src/sme_common/sme_Api.c @@ -118,11 +118,6 @@ eHalStatus sme_HandlePostChannelSwitchInd(tHalHandle hHal); tANI_BOOLEAN csrIsScanAllowed(tpAniSirGlobal pMac); #endif -#ifdef WLAN_FEATURE_11W -eHalStatus sme_UnprotectedMgmtFrmInd( tHalHandle hHal, - tpSirSmeUnprotMgmtFrameInd pSmeMgmtFrm ); -#endif - //Internal SME APIs eHalStatus sme_AcquireGlobalLock( tSmeStruct *psSme) { @@ -898,6 +893,7 @@ eHalStatus sme_Open(tHalHandle hHal) do { pMac->sme.state = SME_STATE_STOP; + pMac->sme.currDeviceMode = VOS_STA_MODE; if( !VOS_IS_STATUS_SUCCESS( vos_lock_init( &pMac->sme.lkSmeGlobalLock ) ) ) { smsLog( pMac, LOGE, "sme_Open failed init lock" ); @@ -1405,34 +1401,6 @@ eHalStatus sme_PCFilterMatchCountResponseHandler(tHalHandle hHal, void* pMsg) #endif // WLAN_FEATURE_PACKET_FILTERING -#ifdef WLAN_FEATURE_11W -/*------------------------------------------------------------------ - * - * Handle the unprotected management frame indication from LIM and - * forward it to HDD. - * - *------------------------------------------------------------------*/ - -eHalStatus sme_UnprotectedMgmtFrmInd( tHalHandle hHal, - tpSirSmeUnprotMgmtFrameInd pSmeMgmtFrm) -{ - tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); - eHalStatus status = eHAL_STATUS_SUCCESS; - tCsrRoamInfo pRoamInfo = {0}; - tANI_U32 SessionId = pSmeMgmtFrm->sessionId; - - pRoamInfo.nFrameLength = pSmeMgmtFrm->frameLen; - pRoamInfo.pbFrames = pSmeMgmtFrm->frameBuf; - pRoamInfo.frameType = pSmeMgmtFrm->frameType; - - /* forward the mgmt frame to HDD */ - csrRoamCallCallback(pMac, SessionId, &pRoamInfo, 0, eCSR_ROAM_UNPROT_MGMT_FRAME_IND, 0); - - return status; -} -#endif - - /*-------------------------------------------------------------------------- \brief sme_ProcessMsg() - The main message processor for SME. @@ -1741,20 +1709,6 @@ eHalStatus sme_ProcessMsg(tHalHandle hHal, vos_msg_t* pMsg) } #endif -#ifdef WLAN_FEATURE_11W - case eWNI_SME_UNPROT_MGMT_FRM_IND: - if (pMsg->bodyptr) - { - sme_UnprotectedMgmtFrmInd(pMac, pMsg->bodyptr); - vos_mem_free(pMsg->bodyptr); - } - else - { - smsLog(pMac, LOGE, "Empty rsp message for meas (eWNI_SME_UNPROT_MGMT_FRM_IND), nothing to process"); - } - break; -#endif - default: if ( ( pMsg->type >= eWNI_SME_MSG_TYPES_BEGIN ) @@ -2360,6 +2314,38 @@ eHalStatus sme_RoamConnect(tHalHandle hHal, tANI_U8 sessionId, tCsrRoamProfile * return (status); } +/* --------------------------------------------------------------------------- + + \fn sme_SetPhyMode + + \brief Changes the PhyMode. + + \param hHal - The handle returned by macOpen. + + \param phyMode new phyMode which is to set + + \return eHalStatus SUCCESS. + + -------------------------------------------------------------------------------*/ +eHalStatus sme_SetPhyMode(tHalHandle hHal, eCsrPhyMode phyMode) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + if (NULL == pMac) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: invalid context", __func__); + return eHAL_STATUS_FAILURE; + } + + pMac->roam.configParam.phyMode = phyMode; + pMac->roam.configParam.uCfgDot11Mode = csrGetCfgDot11ModeFromCsrPhyMode(NULL, + pMac->roam.configParam.phyMode, + pMac->roam.configParam.ProprietaryRatesEnabled); + + return eHAL_STATUS_SUCCESS; +} + /* --------------------------------------------------------------------------- \fn sme_RoamReassoc \brief a wrapper function to request CSR to inititiate a re-association @@ -5032,8 +5018,9 @@ eHalStatus sme_OemDataReq(tHalHandle hHal, \sa --------------------------------------------------------------------------*/ -eHalStatus sme_OpenSession(tHalHandle hHal, csrRoamCompleteCallback callback, void *pContext, - tANI_U8 *pSelfMacAddr, tANI_U8 *pbSessionId) +eHalStatus sme_OpenSession(tHalHandle hHal, csrRoamCompleteCallback callback, + void *pContext, tANI_U8 *pSelfMacAddr, + tANI_U8 *pbSessionId) { eHalStatus status; tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); @@ -5047,7 +5034,8 @@ eHalStatus sme_OpenSession(tHalHandle hHal, csrRoamCompleteCallback callback, vo status = sme_AcquireGlobalLock( &pMac->sme ); if ( HAL_STATUS_SUCCESS( status ) ) { - status = csrRoamOpenSession( pMac, callback, pContext, pSelfMacAddr, pbSessionId ); + status = csrRoamOpenSession(pMac, callback, pContext, + pSelfMacAddr, pbSessionId); sme_ReleaseGlobalLock( &pMac->sme ); } @@ -5953,6 +5941,8 @@ eHalStatus sme_PreferredNetworkFoundInd (tHalHandle hHal, void* pMsg) tpAniSirGlobal pMac = PMAC_STRUCT(hHal); eHalStatus status = eHAL_STATUS_SUCCESS; tSirPrefNetworkFoundInd *pPrefNetworkFoundInd = (tSirPrefNetworkFoundInd *)pMsg; + v_U8_t dumpSsId[SIR_MAC_MAX_SSID_LENGTH + 1]; + tANI_U8 ssIdLength = 0; if (NULL == pMsg) { @@ -5963,16 +5953,37 @@ eHalStatus sme_PreferredNetworkFoundInd (tHalHandle hHal, void* pMsg) { if (pPrefNetworkFoundInd->ssId.length > 0) { - smsLog(pMac, LOG1, "Preferred Network Found Indication in %s(), SSID=%s", - __func__, pPrefNetworkFoundInd->ssId.ssId); - + ssIdLength = CSR_MIN(SIR_MAC_MAX_SSID_LENGTH, + pPrefNetworkFoundInd->ssId.length); + vos_mem_copy(dumpSsId, pPrefNetworkFoundInd->ssId.ssId, ssIdLength); + dumpSsId[ssIdLength] = 0; + smsLog(pMac, LOG2, "%s:SSID=%s frame length %d", + __func__, dumpSsId, pPrefNetworkFoundInd->frameLength); + + //Save the frame to scan result + if (pPrefNetworkFoundInd->mesgLen > sizeof(tSirPrefNetworkFoundInd)) + { + //we may have a frame + status = csrScanSavePreferredNetworkFound(pMac, + pPrefNetworkFoundInd); + if (!HAL_STATUS_SUCCESS(status)) + { + smsLog(pMac, LOGE, FL(" fail to save preferred network")); + } + } + else + { + smsLog(pMac, LOGE, FL(" not enough data length %d needed %d"), + pPrefNetworkFoundInd->mesgLen, sizeof(tSirPrefNetworkFoundInd)); + } /* Call Preferred Netowrk Found Indication callback routine. */ - if (pMac->pmc.prefNetwFoundCB != NULL) - { - pMac->pmc.prefNetwFoundCB(pMac->pmc.preferredNetworkFoundIndCallbackContext, pPrefNetworkFoundInd); + if (HAL_STATUS_SUCCESS(status) && (pMac->pmc.prefNetwFoundCB != NULL)) + { + pMac->pmc.prefNetwFoundCB( + pMac->pmc.preferredNetworkFoundIndCallbackContext, + pPrefNetworkFoundInd); } - } else { @@ -6145,12 +6156,6 @@ eHalStatus sme_HandleChangeCountryCode(tpAniSirGlobal pMac, void *pMsgBuf) return status; } - /* purge current scan results - if i don't do this than I still get old ap's (of different country code) as available (even if they are powered off). - Looks like a bug in current scan sequence. - */ - csrScanFlushResult(pMac); - /* overwrite the defualt country code */ palCopyMemory(pMac->hHdd, pMac->scan.countryCodeDefault, pMac->scan.countryCodeCurrent, WNI_CFG_COUNTRY_CODE_LEN); @@ -6201,7 +6206,7 @@ eHalStatus sme_8023MulticastList (tHalHandle hHal, tANI_U8 sessionId, tpSirRcvFl tCsrRoamSession *pSession = NULL; VOS_TRACE( VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "%s: " - "ulMulticastAddrCnt=%d, multicastAddr[0]=%d", __func__, + "ulMulticastAddrCnt=%d, multicastAddr[0]=%p", __func__, pMulticastAddrs->ulMulticastAddrCnt, pMulticastAddrs->multicastAddr[0]); @@ -6940,6 +6945,76 @@ eHalStatus sme_setRoamIntraBand(tHalHandle hHal, const v_BOOL_t nRoamIntraBand) return status ; } +/* --------------------------------------------------------------------------- + \fn sme_UpdateRoamScanNProbes + \brief function to update roam scan N probes + This function is called through dynamic setConfig callback function + to update roam scan N probes + \param hHal - HAL handle for device + \param nProbes number of probe requests to be sent out + \- return Success or failure + -------------------------------------------------------------------------*/ +eHalStatus sme_UpdateRoamScanNProbes(tHalHandle hHal, const v_U8_t nProbes) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status = eHAL_STATUS_SUCCESS; + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s: gRoamScanNProbes is changed from %d to %d", __func__, + pMac->roam.configParam.nProbes, + nProbes); + pMac->roam.configParam.nProbes = nProbes; + sme_ReleaseGlobalLock( &pMac->sme ); + } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pMac->roam.configParam.isRoamOffloadScanEnabled) + { + csrRoamOffloadScan(pMac, ROAM_SCAN_OFFLOAD_UPDATE_CFG, + REASON_NPROBES_CHANGED); + } +#endif + return status ; +} + +/* --------------------------------------------------------------------------- + \fn sme_UpdateRoamScanHomeAwayTime + \brief function to update roam scan Home away time + This function is called through dynamic setConfig callback function + to update roam scan home away time + \param hHal - HAL handle for device + \param nRoamScanAwayTime Scan home away time + \- return Success or failure + -------------------------------------------------------------------------*/ +eHalStatus sme_UpdateRoamScanHomeAwayTime(tHalHandle hHal, const v_U16_t nRoamScanHomeAwayTime) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status = eHAL_STATUS_SUCCESS; + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s: gRoamScanHomeAwayTime is changed from %d to %d", __func__, + pMac->roam.configParam.nRoamScanHomeAwayTime, + nRoamScanHomeAwayTime); + pMac->roam.configParam.nRoamScanHomeAwayTime = nRoamScanHomeAwayTime; + sme_ReleaseGlobalLock( &pMac->sme ); + } + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pMac->roam.configParam.isRoamOffloadScanEnabled) + { + csrRoamOffloadScan(pMac, ROAM_SCAN_OFFLOAD_UPDATE_CFG, + REASON_HOME_AWAY_TIME_CHANGED); + } +#endif + return status; +} + + /* --------------------------------------------------------------------------- \fn sme_getRoamIntraBand \brief get Intra band roaming @@ -6952,6 +7027,30 @@ v_BOOL_t sme_getRoamIntraBand(tHalHandle hHal) return pMac->roam.configParam.nRoamIntraBand; } +/* --------------------------------------------------------------------------- + \fn sme_getRoamScanNProbes + \brief get N Probes + \param hHal - HAL handle for device + \- return Success or failure + -------------------------------------------------------------------------*/ +v_U8_t sme_getRoamScanNProbes(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + return pMac->roam.configParam.nProbes; +} + +/* --------------------------------------------------------------------------- + \fn sme_getRoamScanHomeAwayTime + \brief get Roam scan home away time + \param hHal - HAL handle for device + \- return Success or failure + -------------------------------------------------------------------------*/ +v_U16_t sme_getRoamScanHomeAwayTime(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + return pMac->roam.configParam.nRoamScanHomeAwayTime; +} + /* --------------------------------------------------------------------------- \fn sme_UpdateImmediateRoamRssiDiff @@ -7013,7 +7112,12 @@ eHalStatus sme_UpdateRoamRssiDiff(tHalHandle hHal, v_U8_t RoamRssiDiff) pMac->roam.configParam.RoamRssiDiff = RoamRssiDiff; sme_ReleaseGlobalLock( &pMac->sme ); } - +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pMac->roam.configParam.isRoamOffloadScanEnabled) + { + csrRoamOffloadScan(pMac, ROAM_SCAN_OFFLOAD_UPDATE_CFG, REASON_RSSI_DIFF_CHANGED); + } +#endif return status ; } @@ -7046,6 +7150,77 @@ eHalStatus sme_UpdateFastTransitionEnabled(tHalHandle hHal, return status ; } + +/* --------------------------------------------------------------------------- + \fn sme_UpdateWESMode + \brief Update WES Mode + This function is called through dynamic setConfig callback function + to configure isWESModeEnabled + \param hHal - HAL handle for device + \return eHAL_STATUS_SUCCESS - SME update isWESModeEnabled config successfully. + Other status means SME is failed to update isWESModeEnabled. + -------------------------------------------------------------------------*/ + +eHalStatus sme_UpdateWESMode(tHalHandle hHal, v_BOOL_t isWESModeEnabled) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status = eHAL_STATUS_SUCCESS; + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "LFR runtime successfully set WES Mode to %d - old value is %d - roam state is %d", + isWESModeEnabled, + pMac->roam.configParam.isWESModeEnabled, + pMac->roam.neighborRoamInfo.neighborRoamState); + pMac->roam.configParam.isWESModeEnabled = isWESModeEnabled; + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return status ; +} + +/* --------------------------------------------------------------------------- + \fn sme_SetRoamScanControl + \brief Set roam scan control + This function is called to set roam scan control + if roam scan control is set to 0, roaming scan cache is cleared + any value other than 0 is treated as invalid value + \param hHal - HAL handle for device + \return eHAL_STATUS_SUCCESS - SME update config successfully. + Other status means SME failure to update + -------------------------------------------------------------------------*/ +eHalStatus sme_SetRoamScanControl(tHalHandle hHal, v_BOOL_t roamScanControl) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status = eHAL_STATUS_SUCCESS; + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "LFR runtime successfully set roam scan control to %d - old value is %d - roam state is %d", + roamScanControl, + pMac->roam.configParam.nRoamScanControl, + pMac->roam.neighborRoamInfo.neighborRoamState); + pMac->roam.configParam.nRoamScanControl = roamScanControl; + if ( 0 == roamScanControl) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "LFR runtime successfully cleared roam scan cache"); + csrFlushBgScanRoamChannelList(pMac); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pMac->roam.configParam.isRoamOffloadScanEnabled) + { + csrRoamOffloadScan(pMac, ROAM_SCAN_OFFLOAD_UPDATE_CFG, REASON_FLUSH_CHANNEL_LIST); + } +#endif + } + sme_ReleaseGlobalLock( &pMac->sme ); + } + return status ; +} #endif /* (WLAN_FEATURE_VOWIFI_11R) || (FEATURE_WLAN_CCX) || (FEATURE_WLAN_LFR) */ #ifdef FEATURE_WLAN_LFR @@ -7154,6 +7329,12 @@ eHalStatus sme_UpdateIsCcxFeatureEnabled(tHalHandle hHal, sme_UpdateConfigFwRssiMonitoring(hHal, FALSE); } } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pMac->roam.configParam.isRoamOffloadScanEnabled) + { + csrRoamOffloadScan(pMac, ROAM_SCAN_OFFLOAD_UPDATE_CFG, REASON_CCX_INI_CFG_CHANGED); + } +#endif return eHAL_STATUS_SUCCESS; } #endif /* FEATURE_WLAN_CCX */ @@ -7217,6 +7398,12 @@ eHalStatus sme_setNeighborLookupRssiThreshold(tHalHandle hHal, sme_ReleaseGlobalLock( &pMac->sme ); } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pMac->roam.configParam.isRoamOffloadScanEnabled) + { + csrRoamOffloadScan(pMac, ROAM_SCAN_OFFLOAD_UPDATE_CFG, REASON_LOOKUP_THRESH_CHANGED); + } +#endif return status; } @@ -7297,8 +7484,48 @@ eHalStatus sme_setNeighborScanRefreshPeriod(tHalHandle hHal, sme_ReleaseGlobalLock( &pMac->sme ); } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pMac->roam.configParam.isRoamOffloadScanEnabled) + { + csrRoamOffloadScan(pMac, ROAM_SCAN_OFFLOAD_UPDATE_CFG, + REASON_NEIGHBOR_SCAN_REFRESH_PERIOD_CHANGED); + } +#endif + return status ; +} + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +/*-------------------------------------------------------------------------- + \brief sme_UpdateRoamScanOffloadEnabled() - enable/disable roam scan offload feaure + It is used at in the REG_DYNAMIC_VARIABLE macro definition of + gRoamScanOffloadEnabled. + This is a synchronous call + \param hHal - The handle returned by macOpen. + \return eHAL_STATUS_SUCCESS - SME update config successfully. + Other status means SME is failed to update. + \sa + --------------------------------------------------------------------------*/ + +eHalStatus sme_UpdateRoamScanOffloadEnabled(tHalHandle hHal, + v_BOOL_t nRoamScanOffloadEnabled) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status = eHAL_STATUS_SUCCESS; + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s: gRoamScanOffloadEnabled is changed from %d to %d", __func__, + pMac->roam.configParam.isRoamOffloadScanEnabled, + nRoamScanOffloadEnabled); + pMac->roam.configParam.isRoamOffloadScanEnabled = nRoamScanOffloadEnabled; + sme_ReleaseGlobalLock( &pMac->sme ); + } + return status ; } +#endif /*-------------------------------------------------------------------------- \brief sme_getNeighborScanRefreshPeriod() - get neighbor scan results refresh period @@ -7519,7 +7746,7 @@ eHalStatus sme_ChangeRoamScanChannelList(tHalHandle hHal, tANI_U8 *pChannelList, tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); eHalStatus status = eHAL_STATUS_SUCCESS; tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo; - tANI_U8 oldChannelList[128] = {0}; + tANI_U8 oldChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN*2] = {0}; tANI_U8 newChannelList[128] = {0}; tANI_U8 i = 0, j = 0; @@ -7534,25 +7761,36 @@ eHalStatus sme_ChangeRoamScanChannelList(tHalHandle hHal, tANI_U8 *pChannelList, pNeighborRoamInfo->cfgParams.channelInfo.ChannelList[i]); } } - csrFlushAndCreateBgScanRoamChannelList(pMac, pChannelList, numChannels); + csrFlushBgScanRoamChannelList(pMac); + csrCreateBgScanRoamChannelList(pMac, pChannelList, numChannels); status = csrUpdateBgScanConfigIniChannelList(pMac, csrGetCurrentBand(hHal)); - if (NULL != pNeighborRoamInfo->cfgParams.channelInfo.ChannelList) + if ( HAL_STATUS_SUCCESS( status )) { - j = 0; - for (i = 0; i < pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels; i++) + sme_SetRoamScanControl(hHal, 1); + if (NULL != pNeighborRoamInfo->cfgParams.channelInfo.ChannelList) { - j += snprintf(newChannelList + j, sizeof(newChannelList) - j," %d", - pNeighborRoamInfo->cfgParams.channelInfo.ChannelList[i]); + j = 0; + for (i = 0; i < pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels; i++) + { + j += snprintf(newChannelList + j, sizeof(newChannelList) - j," %d", + pNeighborRoamInfo->cfgParams.channelInfo.ChannelList[i]); + } } - } - VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, - "LFR runtime successfully set roam scan channels to %s - old value is %s - roam state is %d", - newChannelList, oldChannelList, - pMac->roam.neighborRoamInfo.neighborRoamState); + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "LFR runtime successfully set roam scan channels to %s - old value is %s - roam state is %d", + newChannelList, oldChannelList, + pMac->roam.neighborRoamInfo.neighborRoamState); + } sme_ReleaseGlobalLock( &pMac->sme ); } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pMac->roam.configParam.isRoamOffloadScanEnabled) + { + csrRoamOffloadScan(pMac, ROAM_SCAN_OFFLOAD_UPDATE_CFG, REASON_CHANNEL_LIST_CHANGED); + } +#endif return status ; } @@ -7584,6 +7822,12 @@ eHalStatus sme_ChangeCountryValidChannelListByRevision(tHalHandle hHal, csrInitCountryValidChannelList(pMac, Revision); sme_ReleaseGlobalLock( &pMac->sme ); } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pMac->roam.configParam.isRoamOffloadScanEnabled) + { + csrRoamOffloadScan(pMac, ROAM_SCAN_OFFLOAD_UPDATE_CFG, REASON_VALID_CHANNEL_LIST_CHANGED); + } +#endif return status ; } @@ -7628,8 +7872,9 @@ eHalStatus sme_getRoamScanChannelList(tHalHandle hHal, tANI_U8 *pChannelList, { VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_WARN, "Roam Scan channel list is NOT yet initialized"); + *pNumChannels = 0; sme_ReleaseGlobalLock( &pMac->sme ); - return eHAL_STATUS_NOT_INITIALIZED; + return status; } *pNumChannels = pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels; @@ -7640,7 +7885,6 @@ eHalStatus sme_getRoamScanChannelList(tHalHandle hHal, tANI_U8 *pChannelList, pOutPtr[i] = '\0'; sme_ReleaseGlobalLock( &pMac->sme ); } - return status ; } @@ -7664,6 +7908,32 @@ eHalStatus sme_GetCountryRevision(tHalHandle hHal, tANI_U8 *pRevision) return status; } +/*-------------------------------------------------------------------------- + \brief sme_GetWESMode() - get WES Mode + This is a synchronous call + \param hHal - The handle returned by macOpen + \return v_U8_t - WES Mode Enabled(1)/Disabled(0) + \sa + --------------------------------------------------------------------------*/ +v_BOOL_t sme_GetWESMode(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + return pMac->roam.configParam.isWESModeEnabled; +} + +/*-------------------------------------------------------------------------- + \brief sme_GetRoamScanControl() - get scan control + This is a synchronous call + \param hHal - The handle returned by macOpen. + \return v_BOOL_t - Enabled(1)/Disabled(0) + \sa + --------------------------------------------------------------------------*/ +v_BOOL_t sme_GetRoamScanControl(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + return pMac->roam.configParam.nRoamScanControl; +} + /*-------------------------------------------------------------------------- \brief sme_getIsCcxFeatureEnabled() - get CCX feature enabled or not This is a synchronuous call @@ -7843,16 +8113,6 @@ VOS_STATUS sme_DeleteTdlsPeerSta(tHalHandle hHal, tANI_U8 sessionId, tSirMacAddr return status ; } -/* --------------------------------------------------------------------------- - \fn sme_IsPmcBmps - \API to Check if PMC state is BMPS. - - \- return v_BOOL_t - -------------------------------------------------------------------------*/ -v_BOOL_t sme_IsPmcBmps(tHalHandle hHal) -{ - return (BMPS == pmcGetPmcState(hHal)); -} /* --------------------------------------------------------------------------- \fn sme_SetTdlsPowerSaveProhibited \API to set/reset the isTdlsPowerSaveProhibited. @@ -7867,6 +8127,17 @@ void sme_SetTdlsPowerSaveProhibited(tHalHandle hHal, v_BOOL_t val) return; } #endif +/* --------------------------------------------------------------------------- + \fn sme_IsPmcBmps + \API to Check if PMC state is BMPS. + + \- return v_BOOL_t + -------------------------------------------------------------------------*/ +v_BOOL_t sme_IsPmcBmps(tHalHandle hHal) +{ + return (BMPS == pmcGetPmcState(hHal)); +} + #ifdef FEATURE_WLAN_TDLS_INTERNAL /* * SME API to start TDLS discovery Procedure @@ -7969,3 +8240,90 @@ VOS_STATUS sme_StartTdlsLinkTeardownReq(tHalHandle hHal, tANI_U8 sessionId, tSir #endif /* FEATURE_WLAN_TDLS */ +eHalStatus sme_UpdateDfsSetting(tHalHandle hHal, tANI_U8 fUpdateEnableDFSChnlScan) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + smsLog(pMac, LOG2, FL("enter")); + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + pMac->scan.fEnableDFSChnlScan = fUpdateEnableDFSChnlScan; + sme_ReleaseGlobalLock( &pMac->sme ); + } + smsLog(pMac, LOG2, FL("exit status %d"), status); + + return (status); +} + +/* + * SME API to enable/disable WLAN driver initiated SSR + */ +void sme_UpdateEnableSSR(tHalHandle hHal, tANI_BOOLEAN enableSSR) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + eHalStatus status = eHAL_STATUS_SUCCESS; + + status = sme_AcquireGlobalLock(&pMac->sme); + if (HAL_STATUS_SUCCESS(status)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "SSR level is changed %d", enableSSR); + /* not serializing this messsage, as this is only going + * to set a variable in WDA/WDI + */ + WDA_SetEnableSSR(enableSSR); + sme_ReleaseGlobalLock(&pMac->sme); + } + return; +} + +/* + * SME API to check if there is any infra station or + * P2P client is connected + */ +VOS_STATUS sme_isSta_p2p_clientConnected(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + if(csrIsInfraConnected(pMac)) + { + return VOS_STATUS_SUCCESS; + } + return VOS_STATUS_E_FAILURE; +} + +/*-------------------------------------------------------------------------- + \brief sme_enable_disable_split_scan() - a wrapper function to set the split + scan parameter. + This is a synchronous call + \param hHal - The handle returned by macOpen + \return NONE. + \sa + --------------------------------------------------------------------------*/ +void sme_enable_disable_split_scan (tHalHandle hHal, tANI_U8 nNumStaChan, + tANI_U8 nNumP2PChan) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + pMac->roam.configParam.nNumStaChanCombinedConc = nNumStaChan; + pMac->roam.configParam.nNumP2PChanCombinedConc = nNumP2PChan; + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s: SCAN nNumStaChanCombinedConc : %d," + "nNumP2PChanCombinedConc : %d ", + __func__, nNumStaChan, nNumP2PChan); + + return; +} +/*------------------------------------------------------------------------- + \brief sme_SetCurrDeviceMode() - Sets the current operating device mode. + \param hHal - The handle returned by macOpen. + \param currDeviceMode - Current operating device mode. + --------------------------------------------------------------------------*/ +void sme_SetCurrDeviceMode (tHalHandle hHal, tVOS_CON_MODE currDeviceMode) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + pMac->sme.currDeviceMode = currDeviceMode; + return; +} diff --git a/drivers/staging/prima/CORE/SME/src/sme_common/sme_FTApi.c b/drivers/staging/prima/CORE/SME/src/sme_common/sme_FTApi.c index 81219f6402b..929592b9d16 100644 --- a/drivers/staging/prima/CORE/SME/src/sme_common/sme_FTApi.c +++ b/drivers/staging/prima/CORE/SME/src/sme_common/sme_FTApi.c @@ -70,7 +70,8 @@ void sme_FTOpen(tHalHandle hHal) pMac->ft.ftSmeContext.reassoc_ft_ies = NULL; pMac->ft.ftSmeContext.reassoc_ft_ies_length = 0; - + pMac->ft.ftSmeContext.setFTPreAuthState = FALSE; + pMac->ft.ftSmeContext.setFTPTKState = FALSE; status = palTimerAlloc(pMac->hHdd, &pMac->ft.ftSmeContext.preAuthReassocIntvlTimer, sme_PreauthReassocIntvlTimerCallback, (void *)pMac); @@ -81,6 +82,7 @@ void sme_FTOpen(tHalHandle hHal) } pMac->ft.ftSmeContext.psavedFTPreAuthRsp = NULL; + pMac->ft.ftSmeContext.pCsrFTKeyInfo = NULL; pMac->ft.ftSmeContext.FTState = eFT_START_READY; } @@ -130,6 +132,17 @@ void sme_FTClose(tHalHandle hHal) palTimerFree(pMac->hHdd, pMac->ft.ftSmeContext.preAuthReassocIntvlTimer); } +void sme_SetFTPreAuthState(tHalHandle hHal, v_BOOL_t state) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + pMac->ft.ftSmeContext.setFTPreAuthState = state; +} + +v_BOOL_t sme_GetFTPreAuthState(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + return pMac->ft.ftSmeContext.setFTPreAuthState; +} /*-------------------------------------------------------------------------- Each time the supplicant sends down the FT IEs to the driver. @@ -259,17 +272,17 @@ eHalStatus sme_FTSendUpdateKeyInd(tHalHandle hHal, tCsrRoamSetKey * pFTKeyInfo) tANI_U16 msgLen; eHalStatus status = eHAL_STATUS_FAILURE; tAniEdType tmpEdType; - tAniKeyDirection tmpDirection; - //tANI_U8 *pBuf; - tANI_U8 *p = NULL; + tSirKeyMaterial *keymaterial = NULL; tAniEdType edType; tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG int i = 0; - smsLog(pMac, LOGE, FL("keyLength %d"), pFTKeyInfo->keyLength); + smsLog(pMac, LOG1, FL("keyLength %d"), pFTKeyInfo->keyLength); - for(i=0; ikeyLength; i++) - smsLog(pMac, LOGE, FL("%02x"), pFTKeyInfo->Key[i]); + for (i=0; ikeyLength; i++) + smsLog(pMac, LOG1, FL("%02x"), pFTKeyInfo->Key[i]); +#endif msgLen = sizeof( tANI_U16) + sizeof( tANI_U16 ) + sizeof( pMsg->keyMaterial.length ) + sizeof( pMsg->keyMaterial.edType ) + @@ -285,66 +298,78 @@ eHalStatus sme_FTSendUpdateKeyInd(tHalHandle hHal, tCsrRoamSetKey * pFTKeyInfo) pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_FT_UPDATE_KEY); pMsg->length = pal_cpu_to_be16(msgLen); - p = (tANI_U8 *)&pMsg->keyMaterial; + keymaterial = &pMsg->keyMaterial; + + keymaterial->length = pFTKeyInfo->keyLength; - // Set the pMsg->keyMaterial.length field (this length is defined as all data that follows the edType field + edType = csrTranslateEncryptTypeToEdType( pFTKeyInfo->encType ); + tmpEdType = pal_cpu_to_be32(edType); + keymaterial->edType = tmpEdType; + + // Set the pMsg->keyMaterial.length field (this length is defined as all + // data that follows the edType field // in the tSirKeyMaterial keyMaterial; field). // - // !!NOTE: This keyMaterial.length contains the length of a MAX size key, though the keyLength can be + // !!NOTE: This keyMaterial.length contains the length of a MAX size key, + // though the keyLength can be // shorter than this max size. Is LIM interpreting this ok ? - p = pal_set_U16( p, pal_cpu_to_be16((tANI_U16)( sizeof( pMsg->keyMaterial.numKeys ) + - ( pMsg->keyMaterial.numKeys * sizeof( pMsg->keyMaterial.key ) ) )) ); + keymaterial->numKeys = 1; + keymaterial->key[ 0 ].keyId = pFTKeyInfo->keyId; + keymaterial->key[ 0 ].unicast = (tANI_U8)eANI_BOOLEAN_TRUE; + keymaterial->key[ 0 ].keyDirection = pFTKeyInfo->keyDirection; - // set pMsg->keyMaterial.edType - edType = csrTranslateEncryptTypeToEdType( pFTKeyInfo->encType ); - tmpEdType = pal_cpu_to_be32(edType); - palCopyMemory( pMac->hHdd, p, (tANI_U8 *)&tmpEdType, sizeof(tAniEdType) ); - p += sizeof( pMsg->keyMaterial.edType ); - - // set the pMsg->keyMaterial.numKeys field - *p = pMsg->keyMaterial.numKeys; - p += sizeof( pMsg->keyMaterial.numKeys ); - - // set pSirKey->keyId = keyId; - *p = pMsg->keyMaterial.key[ 0 ].keyId; - p += sizeof( pMsg->keyMaterial.key[ 0 ].keyId ); - - // set pSirKey->unicast = (tANI_U8)fUnicast; - *p = (tANI_U8)eANI_BOOLEAN_TRUE; - p += sizeof( pMsg->keyMaterial.key[ 0 ].unicast ); - - // set pSirKey->keyDirection = aniKeyDirection; - tmpDirection = pal_cpu_to_be32(pFTKeyInfo->keyDirection); - palCopyMemory( pMac->hHdd, p, (tANI_U8 *)&tmpDirection, sizeof(tAniKeyDirection) ); - p += sizeof(tAniKeyDirection); - // pSirKey->keyRsc = ;; - palCopyMemory( pMac->hHdd, p, pFTKeyInfo->keyRsc, CSR_MAX_RSC_LEN ); - p += sizeof( pMsg->keyMaterial.key[ 0 ].keyRsc ); - - // set pSirKey->paeRole - *p = pFTKeyInfo->paeRole; // 0 is Supplicant - p++; - - // set pSirKey->keyLength = keyLength; - p = pal_set_U16( p, pal_cpu_to_be16(pFTKeyInfo->keyLength) ); - - if ( pFTKeyInfo->keyLength && pFTKeyInfo->Key ) - { - palCopyMemory( pMac->hHdd, p, pFTKeyInfo->Key, pFTKeyInfo->keyLength ); + palCopyMemory( pMac->hHdd, &keymaterial->key[ 0 ].keyRsc, + pFTKeyInfo->keyRsc, CSR_MAX_RSC_LEN ); + + keymaterial->key[ 0 ].paeRole = pFTKeyInfo->paeRole; + + keymaterial->key[ 0 ].keyLength = pFTKeyInfo->keyLength; + + if ( pFTKeyInfo->keyLength && pFTKeyInfo->Key ) + { + palCopyMemory( pMac->hHdd, &keymaterial->key[ 0 ].key, + pFTKeyInfo->Key, pFTKeyInfo->keyLength ); if(pFTKeyInfo->keyLength == 16) { - smsLog(pMac, LOG1, " SME Set keyIdx (%d) encType(%d) key = %02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X", - pFTKeyInfo->keyId, edType, pFTKeyInfo->Key[0], pFTKeyInfo->Key[1], pFTKeyInfo->Key[2], pFTKeyInfo->Key[3], pFTKeyInfo->Key[4], - pFTKeyInfo->Key[5], pFTKeyInfo->Key[6], pFTKeyInfo->Key[7], pFTKeyInfo->Key[8], - pFTKeyInfo->Key[9], pFTKeyInfo->Key[10], pFTKeyInfo->Key[11], pFTKeyInfo->Key[12], pFTKeyInfo->Key[13], pFTKeyInfo->Key[14], pFTKeyInfo->Key[15]); + smsLog(pMac, LOG1, "SME Set Update Ind keyIdx (%d) encType(%d) key = " + "%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X", + pMsg->keyMaterial.key[0].keyId, (tAniEdType)pMsg->keyMaterial.edType, + pMsg->keyMaterial.key[0].key[0], pMsg->keyMaterial.key[0].key[1], + pMsg->keyMaterial.key[0].key[2], pMsg->keyMaterial.key[0].key[3], + pMsg->keyMaterial.key[0].key[4], pMsg->keyMaterial.key[0].key[5], + pMsg->keyMaterial.key[0].key[6], pMsg->keyMaterial.key[0].key[7], + pMsg->keyMaterial.key[0].key[8], pMsg->keyMaterial.key[0].key[9], + pMsg->keyMaterial.key[0].key[10], pMsg->keyMaterial.key[0].key[11], + pMsg->keyMaterial.key[0].key[12], pMsg->keyMaterial.key[0].key[13], + pMsg->keyMaterial.key[0].key[14], pMsg->keyMaterial.key[0].key[15]); } } + vos_mem_copy( &pMsg->bssId[ 0 ], + &pFTKeyInfo->peerMac[ 0 ], + sizeof(tCsrBssid) ); + + smsLog(pMac, LOG1, "BSSID = %02X-%02X-%02X-%02X-%02X-%02X", + pMsg->bssId[0], pMsg->bssId[1], pMsg->bssId[2], + pMsg->bssId[3], pMsg->bssId[4], pMsg->bssId[5]); + status = palSendMBMessage(pMac->hHdd, pMsg); return( status ); } +v_BOOL_t sme_GetFTPTKState(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + return pMac->ft.ftSmeContext.setFTPTKState; +} + +void sme_SetFTPTKState(tHalHandle hHal, v_BOOL_t state) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + pMac->ft.ftSmeContext.setFTPTKState = state; +} + eHalStatus sme_FTUpdateKey( tHalHandle hHal, tCsrRoamSetKey * pFTKeyInfo ) { tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); @@ -372,11 +397,28 @@ eHalStatus sme_FTUpdateKey( tHalHandle hHal, tCsrRoamSetKey * pFTKeyInfo ) switch(pMac->ft.ftSmeContext.FTState) { case eFT_SET_KEY_WAIT: - status = eHAL_STATUS_FT_PREAUTH_KEY_WAIT; - pMac->ft.ftSmeContext.FTState = eFT_START_READY; + if (sme_GetFTPreAuthState (hHal) == TRUE) + { + status = sme_FTSendUpdateKeyInd(pMac, pFTKeyInfo); + if (status != 0 ) + { + smsLog( pMac, LOGE, "%s: Key set failure %d", __func__, + status); + pMac->ft.ftSmeContext.setFTPTKState = FALSE; + status = eHAL_STATUS_FT_PREAUTH_KEY_FAILED; + } + else + { + pMac->ft.ftSmeContext.setFTPTKState = TRUE; + status = eHAL_STATUS_FT_PREAUTH_KEY_SUCCESS; + smsLog( pMac, LOG1, "%s: Key set success", __func__); + } + sme_SetFTPreAuthState(hHal, FALSE); + } + pMac->ft.ftSmeContext.FTState = eFT_START_READY; #ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG - smsLog( pMac, LOG1, "%s: state changed to %d", __func__, - pMac->ft.ftSmeContext.FTState); + smsLog( pMac, LOG1, "%s: state changed to %d status %d", __func__, + pMac->ft.ftSmeContext.FTState, status); #endif break; diff --git a/drivers/staging/prima/CORE/SVC/src/btc/wlan_btc_svc.c b/drivers/staging/prima/CORE/SVC/src/btc/wlan_btc_svc.c index b3a49dfb250..63c021ddf16 100644 --- a/drivers/staging/prima/CORE/SVC/src/btc/wlan_btc_svc.c +++ b/drivers/staging/prima/CORE/SVC/src/btc/wlan_btc_svc.c @@ -207,6 +207,7 @@ void send_btc_nlink_msg (int type, int dest_pid) default: VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "BTC: Attempt to send unknown nlink message %d\n", type); + kfree_skb(skb); return; } if(dest_pid == 0) diff --git a/drivers/staging/prima/CORE/SVC/src/ptt/wlan_ptt_sock_svc.c b/drivers/staging/prima/CORE/SVC/src/ptt/wlan_ptt_sock_svc.c index 7fa2185ecad..8e3e579d16a 100644 --- a/drivers/staging/prima/CORE/SVC/src/ptt/wlan_ptt_sock_svc.c +++ b/drivers/staging/prima/CORE/SVC/src/ptt/wlan_ptt_sock_svc.c @@ -295,12 +295,12 @@ static int ptt_sock_rx_nlink_msg (struct sk_buff * skb) switch (type) { case ANI_NL_MSG_PUMAC: //Message from the PTT socket APP PTT_TRACE(VOS_TRACE_LEVEL_INFO, "%s: Received ANI_NL_MSG_PUMAC Msg [0x%X]\n", - __func__, type, radio); + __func__, type); ptt_proc_pumac_msg(skb, &wnl->wmsg, radio); break; case ANI_NL_MSG_PTT: //Message from Quarky GUI PTT_TRACE(VOS_TRACE_LEVEL_INFO, "%s: Received ANI_NL_MSG_PTT Msg [0x%X]\n", - __func__, type, radio); + __func__, type); ptt_proc_quarky_msg(wnl, &wnl->wmsg, radio); break; default: diff --git a/drivers/staging/prima/CORE/SYS/legacy/src/pal/inc/palApi.h b/drivers/staging/prima/CORE/SYS/legacy/src/pal/inc/palApi.h index 65f8d3571b2..f1d28159602 100644 --- a/drivers/staging/prima/CORE/SYS/legacy/src/pal/inc/palApi.h +++ b/drivers/staging/prima/CORE/SYS/legacy/src/pal/inc/palApi.h @@ -18,67 +18,43 @@ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ -/* - * Copyright (c) 2012, The Linux Foundation. All rights reserved. - * - * Previously licensed under the ISC license by Qualcomm Atheros, Inc. - * - * - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all - * copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ +/** ------------------------------------------------------------------------- * + ------------------------------------------------------------------------- * -/** ------------------------------------------------------------------------- * - ------------------------------------------------------------------------- * - \file palApi.h - + \brief Exports and types for the Platform Abstraction Layer interfaces. - - $Id$ - + + $Id$ + Copyright (C) 2006 Airgo Networks, Incorporated This file contains all the interfaces for thge Platform Abstration Layer - functions. It is intended to be included in all modules that are using + functions. It is intended to be included in all modules that are using the PAL interfaces. - + ========================================================================== */ #ifndef PALAPI_H__ #define PALAPI_H__ #include "halTypes.h" -#include "palPipes.h" -//#include "palErrIsr.h" -//#include "halFrameInfo.h" /** \mainpage Platform Abstraction Layer (PAL) - + \section intro Introduction - + palApi is the Platform Abstration Layer. - - This is the latest attempt to abstract the entire Platform, including the - hardware, chip, OS and Bus into a generic API. We are doing this to give + + This is the latest attempt to abstract the entire Platform, including the + hardware, chip, OS and Bus into a generic API. We are doing this to give the MAC the ability to call - generic APIs that will allow the MAC to function in an abstract manner + generic APIs that will allow the MAC to function in an abstract manner with any Airgo chipset, on any supported OS (Windows and Linux for now) across any system bus interface (PCI, PCIe, Cardbus, USB, etc.). - + \todo - - palReadRegister: register read + - palReadRegister: register read -# add an Open/Close abstraction to accomodate the PAL before the entire MAC is loaded. -# Review with Linux folks to see this basic scructure works for them. -# Figure out how to organize the directory structure @@ -87,10 +63,10 @@ - palTx: an abstraction for transmit frames that manages the Td and Tm rings - palRx: an abstracion for receiving frames from a chip across any of the supported buses - palInterrupt: abstract the interrupts into the HAL - - + + \section impl_notes Implementation Notes - + \subsection subsection_codeStructure Code strucure */ @@ -101,18 +77,18 @@ \fn palReadRegister \brief chip and bus agnostic funtion to read a register value - + \param hHdd - HDD context handle - + \param regAddress - address (offset) of the register to be read from the start of register space. - + \param pRegValue - pointer to the memory where the register contents are written - - \return eHalStatus - status of the register read. Note that this function - can fail. In particular, when the card is removed, this function will return + + \return eHalStatus - status of the register read. Note that this function + can fail. In particular, when the card is removed, this function will return a failure. - + -------------------------------------------------------------------------------*/ eHalStatus palReadRegister( tHddHandle hHdd, tANI_U32 regAddress, tANI_U32 *pRegValue ); @@ -122,18 +98,18 @@ eHalStatus palReadRegister( tHddHandle hHdd, tANI_U32 regAddress, tANI_U32 *pReg \fn palWriteRegister \brief chip and bus agnostic funtion to write a register value - + \param hHdd - HDD context handle - + \param regAddress - address (offset) of the register to be read from the start of register space. - + \param pRegValue - pointer to the value being written into the register - - \return eHalStatus - status of the register read. Note that this function - can fail. In particular, when the card is removed, this function will return + + \return eHalStatus - status of the register read. Note that this function + can fail. In particular, when the card is removed, this function will return a failure. - + -------------------------------------------------------------------------------*/ eHalStatus palWriteRegister( tHddHandle hHdd, tANI_U32 regAddress, tANI_U32 regValue ); @@ -142,18 +118,18 @@ eHalStatus palWriteRegister( tHddHandle hHdd, tANI_U32 regAddress, tANI_U32 regV \fn palAsyncWriteRegister \brief chip and bus agnostic async funtion to write a register value - + \param hHdd - HDD context handle - + \param regAddress - address (offset) of the register to be written from the start of register space. - + \param regValue - value being written into the register - - \return eHalStatus - status of the register write. Note that this function - can fail. In particular, when the card is removed, this function will return + + \return eHalStatus - status of the register write. Note that this function + can fail. In particular, when the card is removed, this function will return a failure. - + -------------------------------------------------------------------------------*/ eHalStatus palAsyncWriteRegister( tHddHandle hHdd, tANI_U32 regAddress, tANI_U32 regValue ); @@ -164,21 +140,21 @@ eHalStatus palAsyncWriteRegister( tHddHandle hHdd, tANI_U32 regAddress, tANI_U32 \fn palReadDeviceMemory \brief chip and bus agnostic funtion to read memory from the chip - + \param hHdd - HDD context handle - - \param memOffset - address (offset) of the memory from the top of the + + \param memOffset - address (offset) of the memory from the top of the memory map (as exposed to the host) where the memory will be read from. - + \param pBuffer - pointer to a buffer where the memory will be placed in host memory space after retreived from the chip. - + \param numBytes - the number of bytes to be read. - - \return eHalStatus - status of the memory read. Note that this function - can fail. In particular, when the card is removed, this function will return + + \return eHalStatus - status of the memory read. Note that this function + can fail. In particular, when the card is removed, this function will return a failure. - + -------------------------------------------------------------------------------*/ eHalStatus palReadDeviceMemory( tHddHandle hHdd, tANI_U32 memOffset, tANI_U8 *pBuffer, tANI_U32 numBytes ); @@ -187,47 +163,47 @@ eHalStatus palReadDeviceMemory( tHddHandle hHdd, tANI_U32 memOffset, tANI_U8 *pB \fn palWriteDeviceMemory \brief chip and bus agnostic funtion to write memory to the chip - + \param hHdd - HDD context handle - - \param memOffset - address (offset) of the memory from the top of the on-chip + + \param memOffset - address (offset) of the memory from the top of the on-chip memory that will be written. - - \param pBuffer - pointer to a buffer that has the source data that will be + + \param pBuffer - pointer to a buffer that has the source data that will be written to the chip. - + \param numBytes - the number of bytes to be written. - - \return eHalStatus - status of the memory read. Note that this function - can fail. In particular, when the card is removed, this function will return + + \return eHalStatus - status of the memory read. Note that this function + can fail. In particular, when the card is removed, this function will return a failure. - + -------------------------------------------------------------------------------*/ -eHalStatus palWriteDeviceMemory( tHddHandle hHdd, tANI_U32 memOffset, tANI_U8 *pBuffer, tANI_U32 numBytes ); +eHalStatus palWriteDeviceMemory( tHddHandle hHdd, tANI_U32 memOffset, tANI_U8 *pBuffer, tANI_U32 numBytes ); /** --------------------------------------------------------------------------- \fn palAllocateMemory - \brief OS agnostic funtion to allocate host memory. - - \note Host memory that needs to be shared between the host and the + \brief OS agnostic funtion to allocate host memory. + + \note Host memory that needs to be shared between the host and the device needs to be allocated with the palAllocateSharedMemory() and free'd with palFreeSharedMemory() functions. - + \param hHdd - HDD context handle - - \param ppMemory - pointer to a void pointer where the address of the + + \param ppMemory - pointer to a void pointer where the address of the memory allocated will be placed upon return from this function. - + \param numBytes - the number of bytes to allocate. - - \return eHalStatus - status of the register read. Note that this function - can fail. In the case of a failure, a non-successful return code will be + + \return eHalStatus - status of the register read. Note that this function + can fail. In the case of a failure, a non-successful return code will be returned and no memory will be allocated (the *ppMemory will be NULL so don't try to use it unless the status returns success). - + -------------------------------------------------------------------------------*/ #ifdef MEMORY_DEBUG #define palAllocateMemory(hHdd, ppMemory, numBytes) palAllocateMemory_debug(hHdd, ppMemory, numBytes, __FILE__, __LINE__) @@ -241,22 +217,22 @@ eHalStatus palAllocateMemory( tHddHandle hHdd, void **ppMemory, tANI_U32 numByte \fn palFreeMemory - \brief OS agnostic funtion to free host memory that was allocated with + \brief OS agnostic funtion to free host memory that was allocated with palAllcoateMemory() calls. - - \note Host memory that needs to be shared between the host and the + + \note Host memory that needs to be shared between the host and the device needs to be allocated with the palAllocateSharedMemory() and free'd with palFreeSharedMemory() functions. - + \param hHdd - HDD context handle - + \param pMemory - pointer to memory that will be free'd. - - \return eHalStatus - status of the register read. Note that this function - can fail. In the case of a failure, a non-successful return code will be + + \return eHalStatus - status of the register read. Note that this function + can fail. In the case of a failure, a non-successful return code will be returned and no memory will be allocated (the *ppMemory will be NULL so don't try to use it unless the status returns success). - + -------------------------------------------------------------------------------*/ eHalStatus palFreeMemory( tHddHandle hHdd, void *pMemory ); @@ -267,20 +243,20 @@ eHalStatus palFreeMemory( tHddHandle hHdd, void *pMemory ); \fn palFillMemory \brief OS agnostic funtion to fill host memory with a specified byte value - + \param hHdd - HDD context handle - + \param pMemory - pointer to memory that will be filled. - + \param numBytes - the number of bytes to be filled. - + \param fillValue - the byte to be written to fill the memory with. - - \return eHalStatus - status of the register read. Note that this function - can fail. In the case of a failure, a non-successful return code will be + + \return eHalStatus - status of the register read. Note that this function + can fail. In the case of a failure, a non-successful return code will be returned and no memory will be allocated (the *ppMemory will be NULL so don't try to use it unless the status returns success). - + -------------------------------------------------------------------------------*/ eHalStatus palFillMemory( tHddHandle hHdd, void *pMemory, tANI_U32 numBytes, tANI_BYTE fillValue ); @@ -289,17 +265,17 @@ eHalStatus palFillMemory( tHddHandle hHdd, void *pMemory, tANI_U32 numBytes, tAN \fn palCopyMemory \brief OS agnostic funtion to copy host memory from one location to another - + \param hHdd - HDD context handle - + \param pSrc - pointer to source memory location (to copy from) \param pSrc - pointer to destination memory location (to copy to) - + \param numBytes - the number of bytes to be be copied. - - \return eHalStatus - status of the memory copy - + + \return eHalStatus - status of the memory copy + -------------------------------------------------------------------------------*/ eHalStatus palCopyMemory( tHddHandle hHdd, void *pDst, const void *pSrc, tANI_U32 numBytes ); @@ -308,76 +284,76 @@ eHalStatus palCopyMemory( tHddHandle hHdd, void *pDst, const void *pSrc, tANI_U3 \fn palFillMemory \brief OS agnostic funtion to fill host memory with a specified byte value - + \param hHdd - HDD context handle - + \param pMemory - pointer to memory that will be filled. - + \param numBytes - the number of bytes to be filled. - + \param fillValue - the byte to be written to fill the memory with. - - \return eHalStatus - status of the register read. Note that this function - can fail. In the case of a failure, a non-successful return code will be + + \return eHalStatus - status of the register read. Note that this function + can fail. In the case of a failure, a non-successful return code will be returned and no memory will be allocated (the *ppMemory will be NULL so don't try to use it unless the status returns success). - + -------------------------------------------------------------------------------*/ ANI_INLINE_FUNCTION eHalStatus palZeroMemory( tHddHandle hHdd, void *pMemory, tANI_U32 numBytes ) { return( palFillMemory( hHdd, pMemory, numBytes, 0 ) ); -} +} /** --------------------------------------------------------------------------- \fn palEqualMemory - \brief OS agnostic funtion to compare two pieces of memory, similar to + \brief OS agnostic funtion to compare two pieces of memory, similar to memcmp function in standard C. - + \param hHdd - HDD context handle - + \param pMemory1 - pointer to one location in memory to compare. \param pMemory2 - pointer to second location in memory to compare. - + \param numBytes - the number of bytes to compare. - + \return tANI_BOOLEAN - returns a boolean value that tells if the memory - locations are equal or now equal. - + locations are equal or now equal. + -------------------------------------------------------------------------------*/ -tANI_BOOLEAN palEqualMemory( tHddHandle hHdd, void *pMemory1, void *pMemory2, tANI_U32 numBytes ); +tANI_BOOLEAN palEqualMemory( tHddHandle hHdd, void *pMemory1, void *pMemory2, tANI_U32 numBytes ); /** --------------------------------------------------------------------------- \fn palFillDeviceMemory - \brief OS agnostic funtion to fill device memory with a specified + \brief OS agnostic funtion to fill device memory with a specified 32bit value - + \param hHdd - HDD context handle - + \param memOffset - offset of the memory on the device to fill. - + \param numBytes - the number of bytes to be filled. - + \param fillValue - the byte pattern to fill into memory on the device - - \return eHalStatus - status of the register read. Note that this function - can fail. - - eHAL_STATUS_DEVICE_MEMORY_LENGTH_ERROR - length of the device memory is not + + \return eHalStatus - status of the register read. Note that this function + can fail. + + eHAL_STATUS_DEVICE_MEMORY_LENGTH_ERROR - length of the device memory is not a multiple of 4 bytes. - - eHAL_STATUS_DEVICE_MEMORY_MISALIGNED - memory address is not aligned on a + + eHAL_STATUS_DEVICE_MEMORY_MISALIGNED - memory address is not aligned on a 4 byte boundary. - - \note return failure if the memOffset is not 32bit aligned and not a + + \note return failure if the memOffset is not 32bit aligned and not a multiple of 4 bytes (the device does not support anything else). - + -------------------------------------------------------------------------------*/ eHalStatus palFillDeviceMemory( tHddHandle hHdd, tANI_U32 memOffset, tANI_U32 numBytes, tANI_BYTE fillValue ); @@ -387,49 +363,49 @@ eHalStatus palFillDeviceMemory( tHddHandle hHdd, tANI_U32 memOffset, tANI_U32 nu \fn palZeroDeviceMemory \brief OS agnostic funtion to fill device memory with a specified byte value - + \param hHdd - HDD context handle - + \param memOffset - offset of the memory on the device to fill. - + \param numBytes - the number of bytes to be filled. - + \param fillValue - the 32bit pattern to fill the memory with. - - \return eHalStatus - status of the register read. Note that this function - can fail. - - eHAL_STATUS_DEVICE_MEMORY_LENGTH_ERROR - length of the device memory is not + + \return eHalStatus - status of the register read. Note that this function + can fail. + + eHAL_STATUS_DEVICE_MEMORY_LENGTH_ERROR - length of the device memory is not a multiple of 4 bytes. - - eHAL_STATUS_DEVICE_MEMORY_MISALIGNED - memory address is not aligned on a + + eHAL_STATUS_DEVICE_MEMORY_MISALIGNED - memory address is not aligned on a 4 byte boundary. - - \note return failure if the memOffset is not 32bit aligned and not a + + \note return failure if the memOffset is not 32bit aligned and not a multiple of 4 bytes (the device does not support anything else). - + -------------------------------------------------------------------------------*/ ANI_INLINE_FUNCTION eHalStatus palZeroDeviceMemory( tHddHandle hHdd, tANI_U32 memOffset, tANI_U32 numBytes ) { return( palFillDeviceMemory( hHdd, memOffset, numBytes, 0 ) ); -} +} /*---------------------------------------------------------------------------------- Allocate a packet for sending through the Tx APIs. \param hHdd - HDD context handle - + \param frmType - Frame type - + \param size \param data - - \param ppPacket - + \param ppPacket - - \return eHalStatus - + \return eHalStatus - ----------------------------------------------------------------------------------*/ eHalStatus palPktAlloc(tHddHandle hHdd, eFrameType frmType, tANI_U16 size, void **data, void **ppPacket) ; @@ -451,7 +427,7 @@ eHalStatus palSpinLockGive( tHddHandle hHdd, tPalSpinLockHandle hSpinLock ); //PAL lock functions end -//This function send a message to MAC, +//This function send a message to MAC, //pMsgBuf is a buffer allocated by caller. The actual structure varies base on message type //The beginning of the buffer can always map to tSirMbMsg //This function must take care of padding if it is required for the OS @@ -465,8 +441,8 @@ extern void palGetUnicastStats(tHddHandle hHdd, tANI_U32 *tx, tANI_U32 *rx); time difference. \param hHdd - HDD context handle - - \return tick count. + + \return tick count. ----------------------------------------------------------------------------------*/ tANI_U32 palGetTickCount(tHddHandle hHdd); @@ -476,21 +452,21 @@ tANI_U32 palGetTickCount(tHddHandle hHdd); \brief chip and bus agnostic function to read memory from the PHY register space as memory i.e. to read more than 4 bytes from the contiguous register space - + \param hHdd - HDD context handle - - \param memOffset - address (offset) of the memory from the top of the + + \param memOffset - address (offset) of the memory from the top of the memory map (as exposed to the host) where the memory will be read from. - + \param pBuffer - pointer to a buffer where the memory will be placed in host memory space after retreived from the chip. - + \param numBytes - the number of bytes to be read. - - \return eHalStatus - status of the memory read. Note that this function - can fail. In particular, when the card is removed, this function will return + + \return eHalStatus - status of the memory read. Note that this function + can fail. In particular, when the card is removed, this function will return a failure. - + -------------------------------------------------------------------------------*/ eHalStatus palReadRegMemory( tHddHandle hHdd, tANI_U32 memOffset, tANI_U8 *pBuffer, tANI_U32 numBytes ); @@ -503,19 +479,19 @@ eHalStatus palReadRegMemory( tHddHandle hHdd, tANI_U32 memOffset, tANI_U8 *pBuff API does the write asynchronously. \param hHdd - HDD context handle - - \param memOffset - address (offset) of the memory from the top of the on-chip + + \param memOffset - address (offset) of the memory from the top of the on-chip memory that will be written. - - \param pBuffer - pointer to a buffer that has the source data that will be + + \param pBuffer - pointer to a buffer that has the source data that will be written to the chip. - + \param numBytes - the number of bytes to be written. - - \return eHalStatus - status of the memory read. Note that this function - can fail. In particular, when the card is removed, this function will return + + \return eHalStatus - status of the memory read. Note that this function + can fail. In particular, when the card is removed, this function will return a failure. - + -------------------------------------------------------------------------------*/ eHalStatus palAsyncWriteRegMemory( tHddHandle hHdd, tANI_U32 memOffset, tANI_U8 *pBuffer, tANI_U32 numBytes ); @@ -524,23 +500,23 @@ eHalStatus palAsyncWriteRegMemory( tHddHandle hHdd, tANI_U32 memOffset, tANI_U8 \fn palWriteRegMemory \brief chip and bus agnostic function to write memory to the PHY register space as memory i.e. to write more than 4 bytes from the contiguous register space. The difference from the - above routine is, in USB interface, this routine performs the write synchronously where as + above routine is, in USB interface, this routine performs the write synchronously where as the above routine performs it asynchronously. \param hHdd - HDD context handle - - \param memOffset - address (offset) of the memory from the top of the on-chip + + \param memOffset - address (offset) of the memory from the top of the on-chip memory that will be written. - - \param pBuffer - pointer to a buffer that has the source data that will be + + \param pBuffer - pointer to a buffer that has the source data that will be written to the chip. - + \param numBytes - the number of bytes to be written. - - \return eHalStatus - status of the memory read. Note that this function - can fail. In particular, when the card is removed, this function will return + + \return eHalStatus - status of the memory read. Note that this function + can fail. In particular, when the card is removed, this function will return a failure. - + -------------------------------------------------------------------------------*/ eHalStatus palWriteRegMemory( tHddHandle hHdd, tANI_U32 memOffset, tANI_U8 *pBuffer, tANI_U32 numBytes ); @@ -549,15 +525,15 @@ eHalStatus palWriteRegMemory( tHddHandle hHdd, tANI_U32 memOffset, tANI_U8 *pBuf \fn palWaitRegVal - \brief is a blocking function which reads the register and waits for the given number of iterations + \brief is a blocking function which reads the register and waits for the given number of iterations until the read value matches the waitRegVal. The delay between is perIterWaitInNanoSec(in nanoseconds) - + \param hHdd - HDD context handle - + \param reg - address of the register to be read - + \param mask - mask to be applied for the read value - + \param waitRegVal - expected value from the register after applying the mask. \param perIterWaitInNanoSec - delay between the two iterations in nanoseconds @@ -565,14 +541,14 @@ eHalStatus palWriteRegMemory( tHddHandle hHdd, tANI_U32 memOffset, tANI_U8 *pBuf \param numIter - max number of reads before the timeout \param pReadRegVal - the value read from the register - - \return eHalStatus - status of the memory read. Note that this function - can fail. In particular, when the card is removed, this function will return + + \return eHalStatus - status of the memory read. Note that this function + can fail. In particular, when the card is removed, this function will return a failure. - + -------------------------------------------------------------------------------*/ -eHalStatus palWaitRegVal( tHddHandle hHdd, tANI_U32 reg, tANI_U32 mask, - tANI_U32 waitRegVal, tANI_U32 perIterWaitInNanoSec, +eHalStatus palWaitRegVal( tHddHandle hHdd, tANI_U32 reg, tANI_U32 mask, + tANI_U32 waitRegVal, tANI_U32 perIterWaitInNanoSec, tANI_U32 numIter, tANI_U32 *pReadRegVal ); /** --------------------------------------------------------------------------- @@ -583,17 +559,17 @@ eHalStatus palWaitRegVal( tHddHandle hHdd, tANI_U32 reg, tANI_U32 mask, and writes back the new value to the register \param hHdd - HDD context handle - + \param reg - address of the register to be modified. - + \param andMask - The value read will be ANDed with this mask \parma orMask - The value after applying the andMask will be ORed with this value - - \return eHalStatus - status of the memory read. Note that this function - can fail. In particular, when the card is removed, this function will return + + \return eHalStatus - status of the memory read. Note that this function + can fail. In particular, when the card is removed, this function will return a failure. - + -------------------------------------------------------------------------------*/ eHalStatus palReadModifyWriteReg( tHddHandle hHdd, tANI_U32 reg, tANI_U32 andMask, tANI_U32 orMask ); @@ -620,7 +596,7 @@ tANI_U16 pal_cpu_to_be16(tANI_U16 x) ; #if defined( ANI_LITTLE_BYTE_ENDIAN ) // Need to eliminate these and use the ani_cpu_to_le, etc. macros.... -ANI_INLINE_FUNCTION unsigned long i_htonl( unsigned long ul ) +ANI_INLINE_FUNCTION unsigned long i_htonl( unsigned long ul ) { return( ( ( ul & 0x000000ff ) << 24 ) | ( ( ul & 0x0000ff00 ) << 8 ) | @@ -653,14 +629,14 @@ ANI_INLINE_FUNCTION unsigned long i_ntohl( unsigned long ul ) \brief Assign 32-bit unsigned value to a byte array base on CPU's endianness. \note Caller must validate the byte array has enough space to hold the vlaue - + \param ptr - Starting address of a byte array - + \param value - The value to assign to the byte array - - \return - The address to the byte after the assignment. This may or may not + + \return - The address to the byte after the assignment. This may or may not be valid. Caller to verify. - + -------------------------------------------------------------------------------*/ ANI_INLINE_FUNCTION tANI_U8 * pal_set_U32(tANI_U8 *ptr, tANI_U32 value) { @@ -687,14 +663,14 @@ ANI_INLINE_FUNCTION tANI_U8 * pal_set_U32(tANI_U8 *ptr, tANI_U32 value) \brief Assign 16-bit unsigned value to a byte array base on CPU's endianness. \note Caller must validate the byte array has enough space to hold the vlaue - + \param ptr - Starting address of a byte array - + \param value - The value to assign to the byte array - - \return - The address to the byte after the assignment. This may or may not + + \return - The address to the byte after the assignment. This may or may not be valid. Caller to verify. - + -------------------------------------------------------------------------------*/ ANI_INLINE_FUNCTION tANI_U8 * pal_set_U16(tANI_U8 *ptr, tANI_U16 value) { @@ -717,15 +693,15 @@ ANI_INLINE_FUNCTION tANI_U8 * pal_set_U16(tANI_U8 *ptr, tANI_U16 value) \brief Retrieve a 16-bit unsigned value from a byte array base on CPU's endianness. \note Caller must validate the byte array has enough space to hold the vlaue - + \param ptr - Starting address of a byte array - - \param pValue - Pointer to a caller allocated buffer for 16 bit value. Value is to assign + + \param pValue - Pointer to a caller allocated buffer for 16 bit value. Value is to assign to this location. - - \return - The address to the byte after the assignment. This may or may not + + \return - The address to the byte after the assignment. This may or may not be valid. Caller to verify. - + -------------------------------------------------------------------------------*/ ANI_INLINE_FUNCTION tANI_U8 * pal_get_U16(tANI_U8 *ptr, tANI_U16 *pValue) { @@ -748,15 +724,15 @@ ANI_INLINE_FUNCTION tANI_U8 * pal_get_U16(tANI_U8 *ptr, tANI_U16 *pValue) \brief Retrieve a 32-bit unsigned value from a byte array base on CPU's endianness. \note Caller must validate the byte array has enough space to hold the vlaue - + \param ptr - Starting address of a byte array - - \param pValue - Pointer to a caller allocated buffer for 32 bit value. Value is to assign + + \param pValue - Pointer to a caller allocated buffer for 32 bit value. Value is to assign to this location. - - \return - The address to the byte after the assignment. This may or may not + + \return - The address to the byte after the assignment. This may or may not be valid. Caller to verify. - + -------------------------------------------------------------------------------*/ ANI_INLINE_FUNCTION tANI_U8 * pal_get_U32(tANI_U8 *ptr, tANI_U32 *pValue) { diff --git a/drivers/staging/prima/CORE/SYS/legacy/src/pal/src/palApiComm.c b/drivers/staging/prima/CORE/SYS/legacy/src/pal/src/palApiComm.c index 9b4cf71c384..0dfce9b8ea5 100644 --- a/drivers/staging/prima/CORE/SYS/legacy/src/pal/src/palApiComm.c +++ b/drivers/staging/prima/CORE/SYS/legacy/src/pal/src/palApiComm.c @@ -46,15 +46,6 @@ #include // needed for tSirMbMsg #include "wlan_qct_wda.h" - -// its not worth the time trying to get all the includes in place to get to -// halMmhForwardMBmsg. if I inlude halMnt.h, I get all kids of compile errros -// for things missing from palPipes.h (asicDxe.h is looking for these). palPipes -// is used only in Gen4 DVT code so why we would have it or need it is puzzling. -//#include - - - #ifdef MEMORY_DEBUG eHalStatus palAllocateMemory_debug( tHddHandle hHdd, void **ppMemory, tANI_U32 numBytes, char* fileName, tANI_U32 lineNum ) { diff --git a/drivers/staging/prima/CORE/SYS/legacy/src/utils/src/dot11f.c b/drivers/staging/prima/CORE/SYS/legacy/src/utils/src/dot11f.c index cd4dbc045df..43a192a7f84 100644 --- a/drivers/staging/prima/CORE/SYS/legacy/src/utils/src/dot11f.c +++ b/drivers/staging/prima/CORE/SYS/legacy/src/utils/src/dot11f.c @@ -1,44 +1,23 @@ /* - * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. - * - * Previously licensed under the ISC license by Qualcomm Atheros, Inc. - * - * - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all - * copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ -/* - * Copyright (c) 2012, The Linux Foundation. All rights reserved. - * - * Previously licensed under the ISC license by Qualcomm Atheros, Inc. - * - * - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all - * copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - + * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. +*/ /** * \file dot11f.c * @@ -50,7 +29,7 @@ * * * This file was automatically generated by 'framesc' - * Tue Mar 19 13:37:40 2013 from the following file(s): + * Fri Jun 7 17:41:21 2013 from the following file(s): * * dot11f.frms * @@ -949,16 +928,6 @@ void dot11fUnpackFfTimeStamp(tpAniSirGlobal pCtx, #define SigFfTimeStamp ( 0x001f ) -void dot11fUnpackFfTransactionId(tpAniSirGlobal pCtx, - tANI_U8 *pBuf, - tDot11fFfTransactionId *pDst) -{ - DOT11F_MEMCPY(pCtx, pDst->transId, pBuf, 2); - (void)pCtx; -} /* End dot11fUnpackFfTransactionId. */ - -#define SigFfTransactionId ( 0x0020 ) - void dot11fUnpackFfTxAntennaId(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tDot11fFfTxAntennaId *pDst) @@ -967,7 +936,7 @@ void dot11fUnpackFfTxAntennaId(tpAniSirGlobal pCtx, (void)pCtx; } /* End dot11fUnpackFfTxAntennaId. */ -#define SigFfTxAntennaId ( 0x0021 ) +#define SigFfTxAntennaId ( 0x0020 ) void dot11fUnpackFfTxPower(tpAniSirGlobal pCtx, tANI_U8 *pBuf, @@ -977,7 +946,7 @@ void dot11fUnpackFfTxPower(tpAniSirGlobal pCtx, (void)pCtx; } /* End dot11fUnpackFfTxPower. */ -#define SigFfTxPower ( 0x0022 ) +#define SigFfTxPower ( 0x0021 ) tANI_U32 dot11fUnpackTlvAuthorizedMACs(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U16 tlvlen, tDot11fTLVAuthorizedMACs *pDst) { @@ -1625,6 +1594,29 @@ tANI_U32 dot11fUnpackIeGTK(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tD #define SigIeHCF ( 0x0005 ) +tANI_U32 dot11fUnpackIeIGTK(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEIGTK *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + DOT11F_MEMCPY(pCtx, pDst->keyID, pBuf, 2); + pBuf += 2; + ielen -= (tANI_U8)2; + DOT11F_MEMCPY(pCtx, pDst->IPN, pBuf, 6); + pBuf += 6; + ielen -= (tANI_U8)6; + pDst->keyLength = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + DOT11F_MEMCPY(pCtx, pDst->key, pBuf, 24); + (void)pCtx; + return status; +} /* End dot11fUnpackIeIGTK. */ + +#define SigIeIGTK ( 0x0006 ) + + tANI_U32 dot11fUnpackIeLLAttr(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIELLAttr *pDst) { tANI_U32 status = DOT11F_PARSE_SUCCESS; @@ -1636,7 +1628,7 @@ tANI_U32 dot11fUnpackIeLLAttr(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, return status; } /* End dot11fUnpackIeLLAttr. */ -#define SigIeLLAttr ( 0x0006 ) +#define SigIeLLAttr ( 0x0007 ) tANI_U32 dot11fUnpackIeLoadBalance(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIELoadBalance *pDst) @@ -1653,7 +1645,7 @@ tANI_U32 dot11fUnpackIeLoadBalance(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 i return status; } /* End dot11fUnpackIeLoadBalance. */ -#define SigIeLoadBalance ( 0x0007 ) +#define SigIeLoadBalance ( 0x0008 ) tANI_U32 dot11fUnpackIeLoadInfo(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIELoadInfo *pDst) @@ -1670,10 +1662,10 @@ tANI_U32 dot11fUnpackIeLoadInfo(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 iele return status; } /* End dot11fUnpackIeLoadInfo. */ -#define SigIeLoadInfo ( 0x0008 ) +#define SigIeLoadInfo ( 0x0009 ) -#define SigIePropAssocType ( 0x0009 ) +#define SigIePropAssocType ( 0x000a ) tANI_U32 dot11fUnpackIePropCapability(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEPropCapability *pDst) @@ -1687,7 +1679,7 @@ tANI_U32 dot11fUnpackIePropCapability(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U return status; } /* End dot11fUnpackIePropCapability. */ -#define SigIePropCapability ( 0x000a ) +#define SigIePropCapability ( 0x000b ) tANI_U32 dot11fUnpackIePropChannSwitchAnn(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEPropChannSwitchAnn *pDst) @@ -1710,7 +1702,7 @@ tANI_U32 dot11fUnpackIePropChannSwitchAnn(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tA return status; } /* End dot11fUnpackIePropChannSwitchAnn. */ -#define SigIePropChannSwitchAnn ( 0x000b ) +#define SigIePropChannSwitchAnn ( 0x000c ) tANI_U32 dot11fUnpackIePropEDCAParams(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEPropEDCAParams *pDst) @@ -1795,7 +1787,7 @@ tANI_U32 dot11fUnpackIePropEDCAParams(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U return status; } /* End dot11fUnpackIePropEDCAParams. */ -#define SigIePropEDCAParams ( 0x000c ) +#define SigIePropEDCAParams ( 0x000d ) tANI_U32 dot11fUnpackIePropQuietBSS(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEPropQuietBSS *pDst) @@ -1818,7 +1810,7 @@ tANI_U32 dot11fUnpackIePropQuietBSS(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 return status; } /* End dot11fUnpackIePropQuietBSS. */ -#define SigIePropQuietBSS ( 0x000d ) +#define SigIePropQuietBSS ( 0x000e ) tANI_U32 dot11fUnpackIePropSuppRates(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEPropSuppRates *pDst) @@ -1846,7 +1838,7 @@ tANI_U32 dot11fUnpackIePropSuppRates(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 return status; } /* End dot11fUnpackIePropSuppRates. */ -#define SigIePropSuppRates ( 0x000e ) +#define SigIePropSuppRates ( 0x000f ) tANI_U32 dot11fUnpackIeR0KH_ID(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIER0KH_ID *pDst) @@ -1866,7 +1858,7 @@ tANI_U32 dot11fUnpackIeR0KH_ID(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen return status; } /* End dot11fUnpackIeR0KH_ID. */ -#define SigIeR0KH_ID ( 0x000f ) +#define SigIeR0KH_ID ( 0x0010 ) tANI_U32 dot11fUnpackIeR1KH_ID(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIER1KH_ID *pDst) @@ -1880,7 +1872,7 @@ tANI_U32 dot11fUnpackIeR1KH_ID(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen return status; } /* End dot11fUnpackIeR1KH_ID. */ -#define SigIeR1KH_ID ( 0x0010 ) +#define SigIeR1KH_ID ( 0x0011 ) tANI_U32 dot11fUnpackIeTSFInfo(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIETSFInfo *pDst) @@ -1897,7 +1889,7 @@ tANI_U32 dot11fUnpackIeTSFInfo(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen return status; } /* End dot11fUnpackIeTSFInfo. */ -#define SigIeTSFInfo ( 0x0011 ) +#define SigIeTSFInfo ( 0x0012 ) tANI_U32 dot11fUnpackIeTaurus(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIETaurus *pDst) @@ -1920,7 +1912,7 @@ tANI_U32 dot11fUnpackIeTaurus(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, return status; } /* End dot11fUnpackIeTaurus. */ -#define SigIeTaurus ( 0x0012 ) +#define SigIeTaurus ( 0x0013 ) tANI_U32 dot11fUnpackIeTitan(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIETitan *pDst) @@ -1943,10 +1935,10 @@ tANI_U32 dot11fUnpackIeTitan(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, return status; } /* End dot11fUnpackIeTitan. */ -#define SigIeTitan ( 0x0013 ) +#define SigIeTitan ( 0x0014 ) -#define SigIeTriggerStaBgScan ( 0x0014 ) +#define SigIeTriggerStaBgScan ( 0x0015 ) tANI_U32 dot11fUnpackIeVersion(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEVersion *pDst) @@ -1972,7 +1964,7 @@ tANI_U32 dot11fUnpackIeVersion(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen return status; } /* End dot11fUnpackIeVersion. */ -#define SigIeVersion ( 0x0015 ) +#define SigIeVersion ( 0x0016 ) tANI_U32 dot11fUnpackIeWDS(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWDS *pDst) @@ -1992,7 +1984,7 @@ tANI_U32 dot11fUnpackIeWDS(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tD return status; } /* End dot11fUnpackIeWDS. */ -#define SigIeWDS ( 0x0016 ) +#define SigIeWDS ( 0x0017 ) tANI_U32 dot11fUnpackIeAPChannelReport(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEAPChannelReport *pDst) @@ -2015,7 +2007,7 @@ tANI_U32 dot11fUnpackIeAPChannelReport(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_ return status; } /* End dot11fUnpackIeAPChannelReport. */ -#define SigIeAPChannelReport ( 0x0017 ) +#define SigIeAPChannelReport ( 0x0018 ) tANI_U32 dot11fUnpackIeBcnReportingDetail(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEBcnReportingDetail *pDst) @@ -2029,7 +2021,7 @@ tANI_U32 dot11fUnpackIeBcnReportingDetail(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tA return status; } /* End dot11fUnpackIeBcnReportingDetail. */ -#define SigIeBcnReportingDetail ( 0x0018 ) +#define SigIeBcnReportingDetail ( 0x0019 ) tANI_U32 dot11fUnpackIeBeaconReportFrmBody(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEBeaconReportFrmBody *pDst) @@ -2049,7 +2041,7 @@ tANI_U32 dot11fUnpackIeBeaconReportFrmBody(tpAniSirGlobal pCtx, tANI_U8 *pBuf, t return status; } /* End dot11fUnpackIeBeaconReportFrmBody. */ -#define SigIeBeaconReportFrmBody ( 0x0019 ) +#define SigIeBeaconReportFrmBody ( 0x001a ) tANI_U32 dot11fUnpackIeBeaconReporting(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEBeaconReporting *pDst) @@ -2066,7 +2058,7 @@ tANI_U32 dot11fUnpackIeBeaconReporting(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_ return status; } /* End dot11fUnpackIeBeaconReporting. */ -#define SigIeBeaconReporting ( 0x001a ) +#define SigIeBeaconReporting ( 0x001b ) tANI_U32 dot11fUnpackIeMeasurementPilot(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEMeasurementPilot *pDst) @@ -2084,7 +2076,7 @@ tANI_U32 dot11fUnpackIeMeasurementPilot(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI return status; } /* End dot11fUnpackIeMeasurementPilot. */ -#define SigIeMeasurementPilot ( 0x001b ) +#define SigIeMeasurementPilot ( 0x001c ) tANI_U32 dot11fUnpackIeMultiBssid(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEMultiBssid *pDst) @@ -2102,7 +2094,7 @@ tANI_U32 dot11fUnpackIeMultiBssid(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ie return status; } /* End dot11fUnpackIeMultiBssid. */ -#define SigIeMultiBssid ( 0x001c ) +#define SigIeMultiBssid ( 0x001d ) tANI_U32 dot11fUnpackIeRICData(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIERICData *pDst) @@ -2122,7 +2114,7 @@ tANI_U32 dot11fUnpackIeRICData(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen return status; } /* End dot11fUnpackIeRICData. */ -#define SigIeRICData ( 0x001d ) +#define SigIeRICData ( 0x001e ) tANI_U32 dot11fUnpackIeRICDescriptor(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIERICDescriptor *pDst) @@ -2140,7 +2132,7 @@ tANI_U32 dot11fUnpackIeRICDescriptor(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 return status; } /* End dot11fUnpackIeRICDescriptor. */ -#define SigIeRICDescriptor ( 0x001e ) +#define SigIeRICDescriptor ( 0x001f ) tANI_U32 dot11fUnpackIeRRMEnabledCap(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIERRMEnabledCap *pDst) @@ -2200,7 +2192,7 @@ tANI_U32 dot11fUnpackIeRRMEnabledCap(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 return status; } /* End dot11fUnpackIeRRMEnabledCap. */ -#define SigIeRRMEnabledCap ( 0x001f ) +#define SigIeRRMEnabledCap ( 0x0020 ) tANI_U32 dot11fUnpackIeRequestedInfo(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIERequestedInfo *pDst) @@ -2215,7 +2207,7 @@ tANI_U32 dot11fUnpackIeRequestedInfo(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 return status; } /* End dot11fUnpackIeRequestedInfo. */ -#define SigIeRequestedInfo ( 0x0020 ) +#define SigIeRequestedInfo ( 0x0021 ) tANI_U32 dot11fUnpackIeSSID(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIESSID *pDst) @@ -2239,7 +2231,7 @@ tANI_U32 dot11fUnpackIeSSID(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, t return status; } /* End dot11fUnpackIeSSID. */ -#define SigIeSSID ( 0x0021 ) +#define SigIeSSID ( 0x0022 ) tANI_U32 dot11fUnpackIeSchedule(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIESchedule *pDst) @@ -2270,7 +2262,7 @@ tANI_U32 dot11fUnpackIeSchedule(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 iele return status; } /* End dot11fUnpackIeSchedule. */ -#define SigIeSchedule ( 0x0022 ) +#define SigIeSchedule ( 0x0023 ) tANI_U32 dot11fUnpackIeTCLAS(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIETCLAS *pDst) @@ -2359,10 +2351,10 @@ tANI_U32 dot11fUnpackIeTCLAS(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, return status; } /* End dot11fUnpackIeTCLAS. */ -#define SigIeTCLAS ( 0x0023 ) +#define SigIeTCLAS ( 0x0024 ) -#define SigIeTCLASSPROC ( 0x0024 ) +#define SigIeTCLASSPROC ( 0x0025 ) tANI_U32 dot11fUnpackIeTSDelay(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIETSDelay *pDst) @@ -2376,7 +2368,7 @@ tANI_U32 dot11fUnpackIeTSDelay(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen return status; } /* End dot11fUnpackIeTSDelay. */ -#define SigIeTSDelay ( 0x0025 ) +#define SigIeTSDelay ( 0x0026 ) tANI_U32 dot11fUnpackIeTSPEC(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIETSPEC *pDst) @@ -2453,7 +2445,7 @@ tANI_U32 dot11fUnpackIeTSPEC(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, return status; } /* End dot11fUnpackIeTSPEC. */ -#define SigIeTSPEC ( 0x0026 ) +#define SigIeTSPEC ( 0x0027 ) tANI_U32 dot11fUnpackIeWMMSchedule(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWMMSchedule *pDst) @@ -2492,7 +2484,7 @@ tANI_U32 dot11fUnpackIeWMMSchedule(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 i return status; } /* End dot11fUnpackIeWMMSchedule. */ -#define SigIeWMMSchedule ( 0x0027 ) +#define SigIeWMMSchedule ( 0x0028 ) tANI_U32 dot11fUnpackIeWMMTCLAS(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWMMTCLAS *pDst) @@ -2589,7 +2581,7 @@ tANI_U32 dot11fUnpackIeWMMTCLAS(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 iele return status; } /* End dot11fUnpackIeWMMTCLAS. */ -#define SigIeWMMTCLAS ( 0x0028 ) +#define SigIeWMMTCLAS ( 0x0029 ) tANI_U32 dot11fUnpackIeWMMTCLASPROC(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWMMTCLASPROC *pDst) @@ -2611,7 +2603,7 @@ tANI_U32 dot11fUnpackIeWMMTCLASPROC(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 return status; } /* End dot11fUnpackIeWMMTCLASPROC. */ -#define SigIeWMMTCLASPROC ( 0x0029 ) +#define SigIeWMMTCLASPROC ( 0x002a ) tANI_U32 dot11fUnpackIeWMMTSDelay(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWMMTSDelay *pDst) @@ -2633,7 +2625,7 @@ tANI_U32 dot11fUnpackIeWMMTSDelay(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ie return status; } /* End dot11fUnpackIeWMMTSDelay. */ -#define SigIeWMMTSDelay ( 0x002a ) +#define SigIeWMMTSDelay ( 0x002b ) tANI_U32 dot11fUnpackIeWMMTSPEC(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWMMTSPEC *pDst) @@ -2718,7 +2710,7 @@ tANI_U32 dot11fUnpackIeWMMTSPEC(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 iele return status; } /* End dot11fUnpackIeWMMTSPEC. */ -#define SigIeWMMTSPEC ( 0x002b ) +#define SigIeWMMTSPEC ( 0x002c ) tANI_U32 dot11fUnpackIeAID(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEAID *pDst) @@ -2732,7 +2724,7 @@ tANI_U32 dot11fUnpackIeAID(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tD return status; } /* End dot11fUnpackIeAID. */ -#define SigIeAID ( 0x002c ) +#define SigIeAID ( 0x002d ) static const tFFDefn FFS_Airgo[ ] = { @@ -2777,7 +2769,7 @@ tANI_U32 dot11fUnpackIeAirgo(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, return status; } /* End dot11fUnpackIeAirgo. */ -#define SigIeAirgo ( 0x002d ) +#define SigIeAirgo ( 0x002e ) tANI_U32 dot11fUnpackIeCCXCckmOpaque(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIECCXCckmOpaque *pDst) @@ -2797,7 +2789,7 @@ tANI_U32 dot11fUnpackIeCCXCckmOpaque(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 return status; } /* End dot11fUnpackIeCCXCckmOpaque. */ -#define SigIeCCXCckmOpaque ( 0x002e ) +#define SigIeCCXCckmOpaque ( 0x002f ) tANI_U32 dot11fUnpackIeCCXRadMgmtCap(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIECCXRadMgmtCap *pDst) @@ -2817,7 +2809,7 @@ tANI_U32 dot11fUnpackIeCCXRadMgmtCap(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 return status; } /* End dot11fUnpackIeCCXRadMgmtCap. */ -#define SigIeCCXRadMgmtCap ( 0x002f ) +#define SigIeCCXRadMgmtCap ( 0x0030 ) tANI_U32 dot11fUnpackIeCCXTrafStrmMet(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIECCXTrafStrmMet *pDst) @@ -2837,7 +2829,7 @@ tANI_U32 dot11fUnpackIeCCXTrafStrmMet(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U return status; } /* End dot11fUnpackIeCCXTrafStrmMet. */ -#define SigIeCCXTrafStrmMet ( 0x0030 ) +#define SigIeCCXTrafStrmMet ( 0x0031 ) tANI_U32 dot11fUnpackIeCCXTrafStrmRateSet(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIECCXTrafStrmRateSet *pDst) @@ -2860,7 +2852,7 @@ tANI_U32 dot11fUnpackIeCCXTrafStrmRateSet(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tA return status; } /* End dot11fUnpackIeCCXTrafStrmRateSet. */ -#define SigIeCCXTrafStrmRateSet ( 0x0031 ) +#define SigIeCCXTrafStrmRateSet ( 0x0032 ) tANI_U32 dot11fUnpackIeCCXTxmitPower(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIECCXTxmitPower *pDst) @@ -2877,7 +2869,7 @@ tANI_U32 dot11fUnpackIeCCXTxmitPower(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 return status; } /* End dot11fUnpackIeCCXTxmitPower. */ -#define SigIeCCXTxmitPower ( 0x0032 ) +#define SigIeCCXTxmitPower ( 0x0033 ) tANI_U32 dot11fUnpackIeCCXVersion(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIECCXVersion *pDst) @@ -2891,7 +2883,7 @@ tANI_U32 dot11fUnpackIeCCXVersion(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ie return status; } /* End dot11fUnpackIeCCXVersion. */ -#define SigIeCCXVersion ( 0x0033 ) +#define SigIeCCXVersion ( 0x0034 ) tANI_U32 dot11fUnpackIeCFParams(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIECFParams *pDst) @@ -2914,7 +2906,7 @@ tANI_U32 dot11fUnpackIeCFParams(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 iele return status; } /* End dot11fUnpackIeCFParams. */ -#define SigIeCFParams ( 0x0034 ) +#define SigIeCFParams ( 0x0035 ) tANI_U32 dot11fUnpackIeChallengeText(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEChallengeText *pDst) @@ -2934,7 +2926,7 @@ tANI_U32 dot11fUnpackIeChallengeText(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 return status; } /* End dot11fUnpackIeChallengeText. */ -#define SigIeChallengeText ( 0x0035 ) +#define SigIeChallengeText ( 0x0036 ) tANI_U32 dot11fUnpackIeChanSwitchAnn(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEChanSwitchAnn *pDst) @@ -2954,7 +2946,7 @@ tANI_U32 dot11fUnpackIeChanSwitchAnn(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 return status; } /* End dot11fUnpackIeChanSwitchAnn. */ -#define SigIeChanSwitchAnn ( 0x0036 ) +#define SigIeChanSwitchAnn ( 0x0037 ) tANI_U32 dot11fUnpackIeCountry(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIECountry *pDst) @@ -2985,10 +2977,10 @@ tANI_U32 dot11fUnpackIeCountry(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen return status; } /* End dot11fUnpackIeCountry. */ -#define SigIeCountry ( 0x0037 ) +#define SigIeCountry ( 0x0038 ) -#define SigIeDSParams ( 0x0038 ) +#define SigIeDSParams ( 0x0039 ) tANI_U32 dot11fUnpackIeEDCAParamSet(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEEDCAParamSet *pDst) @@ -3073,7 +3065,7 @@ tANI_U32 dot11fUnpackIeEDCAParamSet(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 return status; } /* End dot11fUnpackIeEDCAParamSet. */ -#define SigIeEDCAParamSet ( 0x0039 ) +#define SigIeEDCAParamSet ( 0x003a ) tANI_U32 dot11fUnpackIeERPInfo(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEERPInfo *pDst) @@ -3092,7 +3084,7 @@ tANI_U32 dot11fUnpackIeERPInfo(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen return status; } /* End dot11fUnpackIeERPInfo. */ -#define SigIeERPInfo ( 0x003a ) +#define SigIeERPInfo ( 0x003b ) tANI_U32 dot11fUnpackIeExtCap(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEExtCap *pDst) @@ -3166,10 +3158,10 @@ tANI_U32 dot11fUnpackIeExtCap(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, return status; } /* End dot11fUnpackIeExtCap. */ -#define SigIeExtCap ( 0x003b ) +#define SigIeExtCap ( 0x003c ) -#define SigIeExtChanSwitchAnn ( 0x003c ) +#define SigIeExtChanSwitchAnn ( 0x003d ) tANI_U32 dot11fUnpackIeExtSuppRates(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEExtSuppRates *pDst) @@ -3197,7 +3189,7 @@ tANI_U32 dot11fUnpackIeExtSuppRates(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 return status; } /* End dot11fUnpackIeExtSuppRates. */ -#define SigIeExtSuppRates ( 0x003d ) +#define SigIeExtSuppRates ( 0x003e ) tANI_U32 dot11fUnpackIeFHParamSet(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEFHParamSet *pDst) @@ -3220,7 +3212,7 @@ tANI_U32 dot11fUnpackIeFHParamSet(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ie return status; } /* End dot11fUnpackIeFHParamSet. */ -#define SigIeFHParamSet ( 0x003e ) +#define SigIeFHParamSet ( 0x003f ) tANI_U32 dot11fUnpackIeFHParams(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEFHParams *pDst) @@ -3237,7 +3229,7 @@ tANI_U32 dot11fUnpackIeFHParams(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 iele return status; } /* End dot11fUnpackIeFHParams. */ -#define SigIeFHParams ( 0x003f ) +#define SigIeFHParams ( 0x0040 ) tANI_U32 dot11fUnpackIeFHPattTable(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEFHPattTable *pDst) @@ -3269,7 +3261,7 @@ tANI_U32 dot11fUnpackIeFHPattTable(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 i return status; } /* End dot11fUnpackIeFHPattTable. */ -#define SigIeFHPattTable ( 0x0040 ) +#define SigIeFHPattTable ( 0x0041 ) static const tFFDefn FFS_FTInfo[ ] = { @@ -3280,6 +3272,7 @@ tANI_U32 dot11fUnpackIeFHPattTable(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 i {offsetof(tDot11fIEFTInfo, R1KH_ID), offsetof(tDot11fIER1KH_ID, present), 0, "R1KH_ID" , 0, 8, 8, SigIeR1KH_ID, {0, 0, 0, 0, 0}, 0, DOT11F_EID_R1KH_ID, 0, }, {offsetof(tDot11fIEFTInfo, GTK), offsetof(tDot11fIEGTK, present), 0, "GTK" , 0, 18, 45, SigIeGTK, {0, 0, 0, 0, 0}, 0, DOT11F_EID_GTK, 0, }, {offsetof(tDot11fIEFTInfo, R0KH_ID), offsetof(tDot11fIER0KH_ID, present), 0, "R0KH_ID" , 0, 3, 50, SigIeR0KH_ID, {0, 0, 0, 0, 0}, 0, DOT11F_EID_R0KH_ID, 0, }, + {offsetof(tDot11fIEFTInfo, IGTK), offsetof(tDot11fIEIGTK, present), 0, "IGTK" , 0, 35, 35, SigIeIGTK, {0, 0, 0, 0, 0}, 0, DOT11F_EID_IGTK, 0, }, {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; @@ -3315,7 +3308,7 @@ tANI_U32 dot11fUnpackIeFTInfo(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, return status; } /* End dot11fUnpackIeFTInfo. */ -#define SigIeFTInfo ( 0x0041 ) +#define SigIeFTInfo ( 0x0042 ) tANI_U32 dot11fUnpackIeFTTimeoutInterval(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEFTTimeoutInterval *pDst) @@ -3332,7 +3325,7 @@ tANI_U32 dot11fUnpackIeFTTimeoutInterval(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tAN return status; } /* End dot11fUnpackIeFTTimeoutInterval. */ -#define SigIeFTTimeoutInterval ( 0x0042 ) +#define SigIeFTTimeoutInterval ( 0x0043 ) tANI_U32 dot11fUnpackIeHTCaps(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEHTCaps *pDst) @@ -3421,7 +3414,7 @@ tANI_U32 dot11fUnpackIeHTCaps(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, return status; } /* End dot11fUnpackIeHTCaps. */ -#define SigIeHTCaps ( 0x0043 ) +#define SigIeHTCaps ( 0x0044 ) tANI_U32 dot11fUnpackIeHTInfo(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEHTInfo *pDst) @@ -3476,7 +3469,7 @@ tANI_U32 dot11fUnpackIeHTInfo(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, return status; } /* End dot11fUnpackIeHTInfo. */ -#define SigIeHTInfo ( 0x0044 ) +#define SigIeHTInfo ( 0x0045 ) tANI_U32 dot11fUnpackIeIBSSParams(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEIBSSParams *pDst) @@ -3490,7 +3483,7 @@ tANI_U32 dot11fUnpackIeIBSSParams(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ie return status; } /* End dot11fUnpackIeIBSSParams. */ -#define SigIeIBSSParams ( 0x0045 ) +#define SigIeIBSSParams ( 0x0046 ) tANI_U32 dot11fUnpackIeLinkIdentifier(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIELinkIdentifier *pDst) @@ -3510,7 +3503,7 @@ tANI_U32 dot11fUnpackIeLinkIdentifier(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U return status; } /* End dot11fUnpackIeLinkIdentifier. */ -#define SigIeLinkIdentifier ( 0x0046 ) +#define SigIeLinkIdentifier ( 0x0047 ) static const tFFDefn FFS_reportBeacon[ ] = { @@ -3668,7 +3661,7 @@ tANI_U32 dot11fUnpackIeMeasurementReport(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tAN return status; } /* End dot11fUnpackIeMeasurementReport. */ -#define SigIeMeasurementReport ( 0x0047 ) +#define SigIeMeasurementReport ( 0x0048 ) static const tFFDefn FFS_measurement_requestBeacon[ ] = { @@ -3773,7 +3766,7 @@ tANI_U32 dot11fUnpackIeMeasurementRequest(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tA return status; } /* End dot11fUnpackIeMeasurementRequest. */ -#define SigIeMeasurementRequest ( 0x0048 ) +#define SigIeMeasurementRequest ( 0x0049 ) tANI_U32 dot11fUnpackIeMobilityDomain(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEMobilityDomain *pDst) @@ -3794,7 +3787,7 @@ tANI_U32 dot11fUnpackIeMobilityDomain(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U return status; } /* End dot11fUnpackIeMobilityDomain. */ -#define SigIeMobilityDomain ( 0x0049 ) +#define SigIeMobilityDomain ( 0x004a ) static const tFFDefn FFS_NeighborReport[ ] = { @@ -3861,7 +3854,7 @@ tANI_U32 dot11fUnpackIeNeighborReport(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U return status; } /* End dot11fUnpackIeNeighborReport. */ -#define SigIeNeighborReport ( 0x004a ) +#define SigIeNeighborReport ( 0x004b ) tANI_U32 dot11fUnpackIeOperatingMode(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEOperatingMode *pDst) @@ -3880,7 +3873,7 @@ tANI_U32 dot11fUnpackIeOperatingMode(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 return status; } /* End dot11fUnpackIeOperatingMode. */ -#define SigIeOperatingMode ( 0x004b ) +#define SigIeOperatingMode ( 0x004c ) static const tTLVDefn TLVS_P2PAssocReq[ ] = { @@ -3899,7 +3892,7 @@ tANI_U32 dot11fUnpackIeP2PAssocReq(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 i return status; } /* End dot11fUnpackIeP2PAssocReq. */ -#define SigIeP2PAssocReq ( 0x004c ) +#define SigIeP2PAssocReq ( 0x004d ) static const tTLVDefn TLVS_P2PAssocRes[ ] = { @@ -3917,7 +3910,7 @@ tANI_U32 dot11fUnpackIeP2PAssocRes(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 i return status; } /* End dot11fUnpackIeP2PAssocRes. */ -#define SigIeP2PAssocRes ( 0x004d ) +#define SigIeP2PAssocRes ( 0x004e ) static const tTLVDefn TLVS_P2PBeacon[ ] = { @@ -3936,7 +3929,7 @@ tANI_U32 dot11fUnpackIeP2PBeacon(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 iel return status; } /* End dot11fUnpackIeP2PBeacon. */ -#define SigIeP2PBeacon ( 0x004e ) +#define SigIeP2PBeacon ( 0x004f ) static const tTLVDefn TLVS_P2PBeaconProbeRes[ ] = { @@ -3958,7 +3951,7 @@ tANI_U32 dot11fUnpackIeP2PBeaconProbeRes(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tAN return status; } /* End dot11fUnpackIeP2PBeaconProbeRes. */ -#define SigIeP2PBeaconProbeRes ( 0x004f ) +#define SigIeP2PBeaconProbeRes ( 0x0050 ) static const tTLVDefn TLVS_P2PDeAuth[ ] = { @@ -3975,7 +3968,7 @@ tANI_U32 dot11fUnpackIeP2PDeAuth(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 iel return status; } /* End dot11fUnpackIeP2PDeAuth. */ -#define SigIeP2PDeAuth ( 0x0050 ) +#define SigIeP2PDeAuth ( 0x0051 ) static const tTLVDefn TLVS_P2PDeviceDiscoverabilityReq[ ] = { @@ -3993,7 +3986,7 @@ tANI_U32 dot11fUnpackIeP2PDeviceDiscoverabilityReq(tpAniSirGlobal pCtx, tANI_U8 return status; } /* End dot11fUnpackIeP2PDeviceDiscoverabilityReq. */ -#define SigIeP2PDeviceDiscoverabilityReq ( 0x0051 ) +#define SigIeP2PDeviceDiscoverabilityReq ( 0x0052 ) static const tTLVDefn TLVS_P2PDeviceDiscoverabilityRes[ ] = { @@ -4010,7 +4003,7 @@ tANI_U32 dot11fUnpackIeP2PDeviceDiscoverabilityRes(tpAniSirGlobal pCtx, tANI_U8 return status; } /* End dot11fUnpackIeP2PDeviceDiscoverabilityRes. */ -#define SigIeP2PDeviceDiscoverabilityRes ( 0x0052 ) +#define SigIeP2PDeviceDiscoverabilityRes ( 0x0053 ) static const tTLVDefn TLVS_P2PDisAssoc[ ] = { @@ -4027,7 +4020,7 @@ tANI_U32 dot11fUnpackIeP2PDisAssoc(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 i return status; } /* End dot11fUnpackIeP2PDisAssoc. */ -#define SigIeP2PDisAssoc ( 0x0053 ) +#define SigIeP2PDisAssoc ( 0x0054 ) static const tTLVDefn TLVS_P2PGONegCnf[ ] = { @@ -4048,7 +4041,7 @@ tANI_U32 dot11fUnpackIeP2PGONegCnf(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 i return status; } /* End dot11fUnpackIeP2PGONegCnf. */ -#define SigIeP2PGONegCnf ( 0x0054 ) +#define SigIeP2PGONegCnf ( 0x0055 ) static const tTLVDefn TLVS_P2PGONegReq[ ] = { @@ -4073,7 +4066,7 @@ tANI_U32 dot11fUnpackIeP2PGONegReq(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 i return status; } /* End dot11fUnpackIeP2PGONegReq. */ -#define SigIeP2PGONegReq ( 0x0055 ) +#define SigIeP2PGONegReq ( 0x0056 ) static const tTLVDefn TLVS_P2PGONegRes[ ] = { @@ -4098,7 +4091,7 @@ tANI_U32 dot11fUnpackIeP2PGONegRes(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 i return status; } /* End dot11fUnpackIeP2PGONegRes. */ -#define SigIeP2PGONegRes ( 0x0056 ) +#define SigIeP2PGONegRes ( 0x0057 ) static const tTLVDefn TLVS_P2PGONegWPS[ ] = { @@ -4116,7 +4109,7 @@ tANI_U32 dot11fUnpackIeP2PGONegWPS(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 i return status; } /* End dot11fUnpackIeP2PGONegWPS. */ -#define SigIeP2PGONegWPS ( 0x0057 ) +#define SigIeP2PGONegWPS ( 0x0058 ) tANI_U32 dot11fUnpackIeP2PIEOpaque(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEP2PIEOpaque *pDst) @@ -4136,7 +4129,7 @@ tANI_U32 dot11fUnpackIeP2PIEOpaque(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 i return status; } /* End dot11fUnpackIeP2PIEOpaque. */ -#define SigIeP2PIEOpaque ( 0x0058 ) +#define SigIeP2PIEOpaque ( 0x0059 ) static const tTLVDefn TLVS_P2PInvitationReq[ ] = { @@ -4159,7 +4152,7 @@ tANI_U32 dot11fUnpackIeP2PInvitationReq(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI return status; } /* End dot11fUnpackIeP2PInvitationReq. */ -#define SigIeP2PInvitationReq ( 0x0059 ) +#define SigIeP2PInvitationReq ( 0x005a ) static const tTLVDefn TLVS_P2PInvitationRes[ ] = { @@ -4180,7 +4173,7 @@ tANI_U32 dot11fUnpackIeP2PInvitationRes(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI return status; } /* End dot11fUnpackIeP2PInvitationRes. */ -#define SigIeP2PInvitationRes ( 0x005a ) +#define SigIeP2PInvitationRes ( 0x005b ) static const tTLVDefn TLVS_P2PNoticeOfAbsence[ ] = { @@ -4197,7 +4190,7 @@ tANI_U32 dot11fUnpackIeP2PNoticeOfAbsence(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tA return status; } /* End dot11fUnpackIeP2PNoticeOfAbsence. */ -#define SigIeP2PNoticeOfAbsence ( 0x005b ) +#define SigIeP2PNoticeOfAbsence ( 0x005c ) static const tTLVDefn TLVS_P2PPresenceResponse[ ] = { @@ -4215,7 +4208,7 @@ tANI_U32 dot11fUnpackIeP2PPresenceResponse(tpAniSirGlobal pCtx, tANI_U8 *pBuf, t return status; } /* End dot11fUnpackIeP2PPresenceResponse. */ -#define SigIeP2PPresenceResponse ( 0x005c ) +#define SigIeP2PPresenceResponse ( 0x005d ) static const tTLVDefn TLVS_P2PProbeReq[ ] = { @@ -4236,7 +4229,7 @@ tANI_U32 dot11fUnpackIeP2PProbeReq(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 i return status; } /* End dot11fUnpackIeP2PProbeReq. */ -#define SigIeP2PProbeReq ( 0x005d ) +#define SigIeP2PProbeReq ( 0x005e ) static const tTLVDefn TLVS_P2PProbeRes[ ] = { @@ -4257,7 +4250,7 @@ tANI_U32 dot11fUnpackIeP2PProbeRes(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 i return status; } /* End dot11fUnpackIeP2PProbeRes. */ -#define SigIeP2PProbeRes ( 0x005e ) +#define SigIeP2PProbeRes ( 0x005f ) static const tTLVDefn TLVS_P2PProvisionDiscoveryReq[ ] = { @@ -4276,7 +4269,7 @@ tANI_U32 dot11fUnpackIeP2PProvisionDiscoveryReq(tpAniSirGlobal pCtx, tANI_U8 *pB return status; } /* End dot11fUnpackIeP2PProvisionDiscoveryReq. */ -#define SigIeP2PProvisionDiscoveryReq ( 0x005f ) +#define SigIeP2PProvisionDiscoveryReq ( 0x0060 ) static const tTLVDefn TLVS_P2PWSCProvisionDiscoveryRes[ ] = { @@ -4293,7 +4286,7 @@ tANI_U32 dot11fUnpackIeP2PWSCProvisionDiscoveryRes(tpAniSirGlobal pCtx, tANI_U8 return status; } /* End dot11fUnpackIeP2PWSCProvisionDiscoveryRes. */ -#define SigIeP2PWSCProvisionDiscoveryRes ( 0x0060 ) +#define SigIeP2PWSCProvisionDiscoveryRes ( 0x0061 ) tANI_U32 dot11fUnpackIePTIControl(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEPTIControl *pDst) @@ -4310,7 +4303,7 @@ tANI_U32 dot11fUnpackIePTIControl(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ie return status; } /* End dot11fUnpackIePTIControl. */ -#define SigIePTIControl ( 0x0061 ) +#define SigIePTIControl ( 0x0062 ) tANI_U32 dot11fUnpackIePUBufferStatus(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEPUBufferStatus *pDst) @@ -4330,7 +4323,7 @@ tANI_U32 dot11fUnpackIePUBufferStatus(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U return status; } /* End dot11fUnpackIePUBufferStatus. */ -#define SigIePUBufferStatus ( 0x0062 ) +#define SigIePUBufferStatus ( 0x0063 ) tANI_U32 dot11fUnpackIePowerCaps(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEPowerCaps *pDst) @@ -4347,7 +4340,7 @@ tANI_U32 dot11fUnpackIePowerCaps(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 iel return status; } /* End dot11fUnpackIePowerCaps. */ -#define SigIePowerCaps ( 0x0063 ) +#define SigIePowerCaps ( 0x0064 ) tANI_U32 dot11fUnpackIePowerConstraints(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEPowerConstraints *pDst) @@ -4361,7 +4354,7 @@ tANI_U32 dot11fUnpackIePowerConstraints(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI return status; } /* End dot11fUnpackIePowerConstraints. */ -#define SigIePowerConstraints ( 0x0064 ) +#define SigIePowerConstraints ( 0x0065 ) tANI_U32 dot11fUnpackIeQBSSLoad(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEQBSSLoad *pDst) @@ -4381,7 +4374,7 @@ tANI_U32 dot11fUnpackIeQBSSLoad(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 iele return status; } /* End dot11fUnpackIeQBSSLoad. */ -#define SigIeQBSSLoad ( 0x0065 ) +#define SigIeQBSSLoad ( 0x0066 ) tANI_U32 dot11fUnpackIeQOSCapsAp(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEQOSCapsAp *pDst) @@ -4392,16 +4385,16 @@ tANI_U32 dot11fUnpackIeQOSCapsAp(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 iel if (pDst->present) status = DOT11F_DUPLICATE_IE; pDst->present = 1; tmp63__ = *pBuf; - pDst->reserved = tmp63__ >> 0 & 0x1; - pDst->txopreq = tmp63__ >> 1 & 0x1; - pDst->qreq = tmp63__ >> 2 & 0x1; - pDst->qack = tmp63__ >> 3 & 0x1; - pDst->count = tmp63__ >> 4 & 0xf; + pDst->count = tmp63__ >> 0 & 0xf; + pDst->qack = tmp63__ >> 4 & 0x1; + pDst->qreq = tmp63__ >> 5 & 0x1; + pDst->txopreq = tmp63__ >> 6 & 0x1; + pDst->reserved = tmp63__ >> 7 & 0x1; (void)pCtx; return status; } /* End dot11fUnpackIeQOSCapsAp. */ -#define SigIeQOSCapsAp ( 0x0066 ) +#define SigIeQOSCapsAp ( 0x0067 ) tANI_U32 dot11fUnpackIeQOSCapsStation(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEQOSCapsStation *pDst) @@ -4412,18 +4405,18 @@ tANI_U32 dot11fUnpackIeQOSCapsStation(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U if (pDst->present) status = DOT11F_DUPLICATE_IE; pDst->present = 1; tmp64__ = *pBuf; - pDst->more_data_ack = tmp64__ >> 0 & 0x1; - pDst->max_sp_length = tmp64__ >> 1 & 0x3; - pDst->qack = tmp64__ >> 3 & 0x1; - pDst->acbe_uapsd = tmp64__ >> 4 & 0x1; - pDst->acbk_uapsd = tmp64__ >> 5 & 0x1; - pDst->acvi_uapsd = tmp64__ >> 6 & 0x1; - pDst->acvo_uapsd = tmp64__ >> 7 & 0x1; + pDst->acvo_uapsd = tmp64__ >> 0 & 0x1; + pDst->acvi_uapsd = tmp64__ >> 1 & 0x1; + pDst->acbk_uapsd = tmp64__ >> 2 & 0x1; + pDst->acbe_uapsd = tmp64__ >> 3 & 0x1; + pDst->qack = tmp64__ >> 4 & 0x1; + pDst->max_sp_length = tmp64__ >> 5 & 0x3; + pDst->more_data_ack = tmp64__ >> 7 & 0x1; (void)pCtx; return status; } /* End dot11fUnpackIeQOSCapsStation. */ -#define SigIeQOSCapsStation ( 0x0067 ) +#define SigIeQOSCapsStation ( 0x0068 ) tANI_U32 dot11fUnpackIeQuiet(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEQuiet *pDst) @@ -4446,7 +4439,7 @@ tANI_U32 dot11fUnpackIeQuiet(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, return status; } /* End dot11fUnpackIeQuiet. */ -#define SigIeQuiet ( 0x0068 ) +#define SigIeQuiet ( 0x0069 ) tANI_U32 dot11fUnpackIeRCPIIE(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIERCPIIE *pDst) @@ -4460,7 +4453,7 @@ tANI_U32 dot11fUnpackIeRCPIIE(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, return status; } /* End dot11fUnpackIeRCPIIE. */ -#define SigIeRCPIIE ( 0x0069 ) +#define SigIeRCPIIE ( 0x006a ) static const tFFDefn FFS_RICDataDesc[ ] = { @@ -4500,7 +4493,7 @@ tANI_U32 dot11fUnpackIeRICDataDesc(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 i return status; } /* End dot11fUnpackIeRICDataDesc. */ -#define SigIeRICDataDesc ( 0x006a ) +#define SigIeRICDataDesc ( 0x006b ) tANI_U32 dot11fUnpackIeRSN(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIERSN *pDst) @@ -4593,7 +4586,7 @@ tANI_U32 dot11fUnpackIeRSN(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tD return status; } /* End dot11fUnpackIeRSN. */ -#define SigIeRSN ( 0x006b ) +#define SigIeRSN ( 0x006c ) tANI_U32 dot11fUnpackIeRSNIIE(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIERSNIIE *pDst) @@ -4607,7 +4600,7 @@ tANI_U32 dot11fUnpackIeRSNIIE(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, return status; } /* End dot11fUnpackIeRSNIIE. */ -#define SigIeRSNIIE ( 0x006c ) +#define SigIeRSNIIE ( 0x006d ) tANI_U32 dot11fUnpackIeRSNOpaque(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIERSNOpaque *pDst) @@ -4627,7 +4620,7 @@ tANI_U32 dot11fUnpackIeRSNOpaque(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 iel return status; } /* End dot11fUnpackIeRSNOpaque. */ -#define SigIeRSNOpaque ( 0x006d ) +#define SigIeRSNOpaque ( 0x006e ) tANI_U32 dot11fUnpackIeSuppChannels(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIESuppChannels *pDst) @@ -4647,7 +4640,7 @@ tANI_U32 dot11fUnpackIeSuppChannels(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 return status; } /* End dot11fUnpackIeSuppChannels. */ -#define SigIeSuppChannels ( 0x006e ) +#define SigIeSuppChannels ( 0x006f ) tANI_U32 dot11fUnpackIeSuppRates(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIESuppRates *pDst) @@ -4675,7 +4668,7 @@ tANI_U32 dot11fUnpackIeSuppRates(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 iel return status; } /* End dot11fUnpackIeSuppRates. */ -#define SigIeSuppRates ( 0x006f ) +#define SigIeSuppRates ( 0x0070 ) tANI_U32 dot11fUnpackIeTIM(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIETIM *pDst) @@ -4704,7 +4697,7 @@ tANI_U32 dot11fUnpackIeTIM(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tD return status; } /* End dot11fUnpackIeTIM. */ -#define SigIeTIM ( 0x0070 ) +#define SigIeTIM ( 0x0071 ) tANI_U32 dot11fUnpackIeTPCReport(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIETPCReport *pDst) @@ -4721,7 +4714,7 @@ tANI_U32 dot11fUnpackIeTPCReport(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 iel return status; } /* End dot11fUnpackIeTPCReport. */ -#define SigIeTPCReport ( 0x0071 ) +#define SigIeTPCReport ( 0x0072 ) tANI_U32 dot11fUnpackIeTPCRequest(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIETPCRequest *pDst) @@ -4734,7 +4727,7 @@ tANI_U32 dot11fUnpackIeTPCRequest(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ie return status; } /* End dot11fUnpackIeTPCRequest. */ -#define SigIeTPCRequest ( 0x0072 ) +#define SigIeTPCRequest ( 0x0073 ) tANI_U32 dot11fUnpackIeVHTCaps(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEVHTCaps *pDst) @@ -4787,7 +4780,7 @@ tANI_U32 dot11fUnpackIeVHTCaps(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen return status; } /* End dot11fUnpackIeVHTCaps. */ -#define SigIeVHTCaps ( 0x0073 ) +#define SigIeVHTCaps ( 0x0074 ) tANI_U32 dot11fUnpackIeVHTExtBssLoad(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEVHTExtBssLoad *pDst) @@ -4813,7 +4806,7 @@ tANI_U32 dot11fUnpackIeVHTExtBssLoad(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 return status; } /* End dot11fUnpackIeVHTExtBssLoad. */ -#define SigIeVHTExtBssLoad ( 0x0074 ) +#define SigIeVHTExtBssLoad ( 0x0075 ) tANI_U32 dot11fUnpackIeVHTOperation(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEVHTOperation *pDst) @@ -4836,7 +4829,7 @@ tANI_U32 dot11fUnpackIeVHTOperation(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 return status; } /* End dot11fUnpackIeVHTOperation. */ -#define SigIeVHTOperation ( 0x0075 ) +#define SigIeVHTOperation ( 0x0076 ) tANI_U32 dot11fUnpackIeWAPI(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWAPI *pDst) @@ -4905,7 +4898,7 @@ tANI_U32 dot11fUnpackIeWAPI(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, t return status; } /* End dot11fUnpackIeWAPI. */ -#define SigIeWAPI ( 0x0076 ) +#define SigIeWAPI ( 0x0077 ) tANI_U32 dot11fUnpackIeWAPIOpaque(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWAPIOpaque *pDst) @@ -4925,7 +4918,7 @@ tANI_U32 dot11fUnpackIeWAPIOpaque(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ie return status; } /* End dot11fUnpackIeWAPIOpaque. */ -#define SigIeWAPIOpaque ( 0x0077 ) +#define SigIeWAPIOpaque ( 0x0078 ) tANI_U32 dot11fUnpackIeWFATPC(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWFATPC *pDst) @@ -4942,7 +4935,7 @@ tANI_U32 dot11fUnpackIeWFATPC(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, return status; } /* End dot11fUnpackIeWFATPC. */ -#define SigIeWFATPC ( 0x0078 ) +#define SigIeWFATPC ( 0x0079 ) tANI_U32 dot11fUnpackIeWFDIEOpaque(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWFDIEOpaque *pDst) @@ -4962,7 +4955,7 @@ tANI_U32 dot11fUnpackIeWFDIEOpaque(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 i return status; } /* End dot11fUnpackIeWFDIEOpaque. */ -#define SigIeWFDIEOpaque ( 0x0079 ) +#define SigIeWFDIEOpaque ( 0x007a ) tANI_U32 dot11fUnpackIeWMMCaps(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWMMCaps *pDst) @@ -4990,7 +4983,7 @@ tANI_U32 dot11fUnpackIeWMMCaps(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen return status; } /* End dot11fUnpackIeWMMCaps. */ -#define SigIeWMMCaps ( 0x007a ) +#define SigIeWMMCaps ( 0x007b ) tANI_U32 dot11fUnpackIeWMMInfoAp(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWMMInfoAp *pDst) @@ -5011,7 +5004,7 @@ tANI_U32 dot11fUnpackIeWMMInfoAp(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 iel return status; } /* End dot11fUnpackIeWMMInfoAp. */ -#define SigIeWMMInfoAp ( 0x007b ) +#define SigIeWMMInfoAp ( 0x007c ) tANI_U32 dot11fUnpackIeWMMInfoStation(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWMMInfoStation *pDst) @@ -5036,7 +5029,7 @@ tANI_U32 dot11fUnpackIeWMMInfoStation(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U return status; } /* End dot11fUnpackIeWMMInfoStation. */ -#define SigIeWMMInfoStation ( 0x007c ) +#define SigIeWMMInfoStation ( 0x007d ) tANI_U32 dot11fUnpackIeWMMParams(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWMMParams *pDst) @@ -5129,7 +5122,7 @@ tANI_U32 dot11fUnpackIeWMMParams(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 iel return status; } /* End dot11fUnpackIeWMMParams. */ -#define SigIeWMMParams ( 0x007d ) +#define SigIeWMMParams ( 0x007e ) tANI_U32 dot11fUnpackIeWPA(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWPA *pDst) @@ -5211,7 +5204,7 @@ tANI_U32 dot11fUnpackIeWPA(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tD return status; } /* End dot11fUnpackIeWPA. */ -#define SigIeWPA ( 0x007e ) +#define SigIeWPA ( 0x007f ) tANI_U32 dot11fUnpackIeWPAOpaque(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWPAOpaque *pDst) @@ -5231,7 +5224,7 @@ tANI_U32 dot11fUnpackIeWPAOpaque(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 iel return status; } /* End dot11fUnpackIeWPAOpaque. */ -#define SigIeWPAOpaque ( 0x007f ) +#define SigIeWPAOpaque ( 0x0080 ) static const tTLVDefn TLVS_WSC[ ] = { @@ -5269,7 +5262,7 @@ tANI_U32 dot11fUnpackIeWSC(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tD return status; } /* End dot11fUnpackIeWSC. */ -#define SigIeWSC ( 0x0080 ) +#define SigIeWSC ( 0x0081 ) tANI_U32 dot11fUnpackIeWiderBWChanSwitchAnn(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWiderBWChanSwitchAnn *pDst) @@ -5289,7 +5282,7 @@ tANI_U32 dot11fUnpackIeWiderBWChanSwitchAnn(tpAniSirGlobal pCtx, tANI_U8 *pBuf, return status; } /* End dot11fUnpackIeWiderBWChanSwitchAnn. */ -#define SigIeWiderBWChanSwitchAnn ( 0x0081 ) +#define SigIeWiderBWChanSwitchAnn ( 0x0082 ) static const tTLVDefn TLVS_WscAssocReq[ ] = { @@ -5308,7 +5301,7 @@ tANI_U32 dot11fUnpackIeWscAssocReq(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 i return status; } /* End dot11fUnpackIeWscAssocReq. */ -#define SigIeWscAssocReq ( 0x0082 ) +#define SigIeWscAssocReq ( 0x0083 ) static const tTLVDefn TLVS_WscAssocRes[ ] = { @@ -5327,7 +5320,7 @@ tANI_U32 dot11fUnpackIeWscAssocRes(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 i return status; } /* End dot11fUnpackIeWscAssocRes. */ -#define SigIeWscAssocRes ( 0x0083 ) +#define SigIeWscAssocRes ( 0x0084 ) static const tTLVDefn TLVS_WscBeacon[ ] = { @@ -5352,7 +5345,7 @@ tANI_U32 dot11fUnpackIeWscBeacon(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 iel return status; } /* End dot11fUnpackIeWscBeacon. */ -#define SigIeWscBeacon ( 0x0084 ) +#define SigIeWscBeacon ( 0x0085 ) static const tTLVDefn TLVS_WscBeaconProbeRes[ ] = { @@ -5385,7 +5378,7 @@ tANI_U32 dot11fUnpackIeWscBeaconProbeRes(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tAN return status; } /* End dot11fUnpackIeWscBeaconProbeRes. */ -#define SigIeWscBeaconProbeRes ( 0x0085 ) +#define SigIeWscBeaconProbeRes ( 0x0086 ) tANI_U32 dot11fUnpackIeWscIEOpaque(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWscIEOpaque *pDst) @@ -5405,7 +5398,7 @@ tANI_U32 dot11fUnpackIeWscIEOpaque(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 i return status; } /* End dot11fUnpackIeWscIEOpaque. */ -#define SigIeWscIEOpaque ( 0x0086 ) +#define SigIeWscIEOpaque ( 0x0087 ) static const tTLVDefn TLVS_WscProbeReq[ ] = { @@ -5436,7 +5429,7 @@ tANI_U32 dot11fUnpackIeWscProbeReq(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 i return status; } /* End dot11fUnpackIeWscProbeReq. */ -#define SigIeWscProbeReq ( 0x0087 ) +#define SigIeWscProbeReq ( 0x0088 ) static const tTLVDefn TLVS_WscProbeRes[ ] = { @@ -5469,7 +5462,7 @@ tANI_U32 dot11fUnpackIeWscProbeRes(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 i return status; } /* End dot11fUnpackIeWscProbeRes. */ -#define SigIeWscProbeRes ( 0x0088 ) +#define SigIeWscProbeRes ( 0x0089 ) static const tTLVDefn TLVS_WscReassocRes[ ] = { @@ -5488,7 +5481,7 @@ tANI_U32 dot11fUnpackIeWscReassocRes(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 return status; } /* End dot11fUnpackIeWscReassocRes. */ -#define SigIeWscReassocRes ( 0x0089 ) +#define SigIeWscReassocRes ( 0x008a ) static const tFFDefn FFS_AddBAReq[] = { @@ -6248,13 +6241,13 @@ tANI_U32 dot11fUnpackAssocRequest(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 n } else { - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("more_data_ack (1): %d\n"), pFrm->QOSCapsStation.more_data_ack); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("max_sp_length (2): %d\n"), pFrm->QOSCapsStation.max_sp_length); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("qack (1): %d\n"), pFrm->QOSCapsStation.qack); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("acbe_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbe_uapsd); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("acbk_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbk_uapsd); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("acvi_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvi_uapsd); FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("acvo_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvo_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("acvi_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvi_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("acbk_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbk_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("acbe_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbe_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("qack (1): %d\n"), pFrm->QOSCapsStation.qack); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("max_sp_length (2): %d\n"), pFrm->QOSCapsStation.max_sp_length); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("more_data_ack (1): %d\n"), pFrm->QOSCapsStation.more_data_ack); } FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("RRMEnabledCap:\n")); if (!pFrm->RRMEnabledCap.present) @@ -6799,7 +6792,7 @@ tANI_U32 dot11fUnpackAssocRequest(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 n {offsetof(tDot11fAssocResponse, RSNIIE), offsetof(tDot11fIERSNIIE, present), 0, "RSNIIE" , 0, 3, 3, SigIeRSNIIE, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RSNIIE, 0, }, {offsetof(tDot11fAssocResponse, RRMEnabledCap), offsetof(tDot11fIERRMEnabledCap, present), 0, "RRMEnabledCap" , 0, 7, 7, SigIeRRMEnabledCap, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RRMENABLEDCAP, 0, }, {offsetof(tDot11fAssocResponse, MobilityDomain), offsetof(tDot11fIEMobilityDomain, present), 0, "MobilityDomain" , 0, 5, 5, SigIeMobilityDomain, {0, 0, 0, 0, 0}, 0, DOT11F_EID_MOBILITYDOMAIN, 0, }, - {offsetof(tDot11fAssocResponse, FTInfo), offsetof(tDot11fIEFTInfo, present), 0, "FTInfo" , 0, 84, 187, SigIeFTInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FTINFO, 0, }, + {offsetof(tDot11fAssocResponse, FTInfo), offsetof(tDot11fIEFTInfo, present), 0, "FTInfo" , 0, 84, 222, SigIeFTInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FTINFO, 0, }, {offsetof(tDot11fAssocResponse, RICDataDesc), offsetof(tDot11fIERICDataDesc, present), offsetof(tDot11fAssocResponse, num_RICDataDesc), "RICDataDesc" , 2, 2, 550, SigIeRICDataDesc, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RICDATADESC, 0, }, {offsetof(tDot11fAssocResponse, WPA), offsetof(tDot11fIEWPA, present), 0, "WPA" , 0, 8, 50, SigIeWPA, {0, 80, 242, 1, 0}, 4, DOT11F_EID_WPA, 0, }, {offsetof(tDot11fAssocResponse, HTCaps), offsetof(tDot11fIEHTCaps, present), 0, "HTCaps" , 0, 28, 60, SigIeHTCaps, {0, 0, 0, 0, 0}, 0, DOT11F_EID_HTCAPS, 0, }, @@ -7022,6 +7015,18 @@ tANI_U32 dot11fUnpackAssocResponse(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("num_PMK_R0_ID: %d.\n"), pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* ) pFrm->FTInfo.R0KH_ID.PMK_R0_ID, pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("IGTK:\n")); + if (!pFrm->FTInfo.IGTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyID, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.IGTK.IPN, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.IGTK.key, 24); + } } for (i = 0; i < pFrm->num_RICDataDesc; ++i) { @@ -7939,7 +7944,7 @@ tANI_U32 dot11fUnpackAssocResponse(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 {offsetof(tDot11fAuthentication, ChallengeText), offsetof(tDot11fIEChallengeText, present), 0, "ChallengeText" , 0, 3, 255, SigIeChallengeText, {0, 0, 0, 0, 0}, 0, DOT11F_EID_CHALLENGETEXT, 0, }, {offsetof(tDot11fAuthentication, RSNOpaque), offsetof(tDot11fIERSNOpaque, present), 0, "RSNOpaque" , 0, 8, 255, SigIeRSNOpaque, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RSNOPAQUE, 0, }, {offsetof(tDot11fAuthentication, MobilityDomain), offsetof(tDot11fIEMobilityDomain, present), 0, "MobilityDomain" , 0, 5, 5, SigIeMobilityDomain, {0, 0, 0, 0, 0}, 0, DOT11F_EID_MOBILITYDOMAIN, 0, }, - {offsetof(tDot11fAuthentication, FTInfo), offsetof(tDot11fIEFTInfo, present), 0, "FTInfo" , 0, 84, 187, SigIeFTInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FTINFO, 0, }, + {offsetof(tDot11fAuthentication, FTInfo), offsetof(tDot11fIEFTInfo, present), 0, "FTInfo" , 0, 84, 222, SigIeFTInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FTINFO, 0, }, {offsetof(tDot11fAuthentication, FTTimeoutInterval), offsetof(tDot11fIEFTTimeoutInterval, present), 0, "FTTimeoutInterval" , 0, 7, 7, SigIeFTTimeoutInterval, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FTTIMEOUTINTERVAL, 0, }, {offsetof(tDot11fAuthentication, RICDataDesc), offsetof(tDot11fIERICDataDesc, present), offsetof(tDot11fAuthentication, num_RICDataDesc), "RICDataDesc" , 2, 2, 550, SigIeRICDataDesc, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RICDATADESC, 0, }, {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; @@ -8040,6 +8045,18 @@ tANI_U32 dot11fUnpackAuthentication(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("num_PMK_R0_ID: %d.\n"), pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* ) pFrm->FTInfo.R0KH_ID.PMK_R0_ID, pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("IGTK:\n")); + if (!pFrm->FTInfo.IGTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyID, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->FTInfo.IGTK.IPN, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->FTInfo.IGTK.key, 24); + } } FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("FTTimeoutInterval:\n")); if (!pFrm->FTTimeoutInterval.present) @@ -8659,11 +8676,11 @@ tANI_U32 dot11fUnpackBeacon(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, t } else { - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("reserved (1): %d\n"), pFrm->QOSCapsAp.reserved); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("txopreq (1): %d\n"), pFrm->QOSCapsAp.txopreq); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("qreq (1): %d\n"), pFrm->QOSCapsAp.qreq); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("qack (1): %d\n"), pFrm->QOSCapsAp.qack); FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("count (4): %d\n"), pFrm->QOSCapsAp.count); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("qack (1): %d\n"), pFrm->QOSCapsAp.qack); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("qreq (1): %d\n"), pFrm->QOSCapsAp.qreq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("txopreq (1): %d\n"), pFrm->QOSCapsAp.txopreq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("reserved (1): %d\n"), pFrm->QOSCapsAp.reserved); } FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("APChannelReport:\n")); if (!pFrm->APChannelReport.present) @@ -10850,11 +10867,11 @@ tANI_U32 dot11fUnpackBeaconIEs(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf } else { - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("reserved (1): %d\n"), pFrm->QOSCapsAp.reserved); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("txopreq (1): %d\n"), pFrm->QOSCapsAp.txopreq); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("qreq (1): %d\n"), pFrm->QOSCapsAp.qreq); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("qack (1): %d\n"), pFrm->QOSCapsAp.qack); FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("count (4): %d\n"), pFrm->QOSCapsAp.count); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("qack (1): %d\n"), pFrm->QOSCapsAp.qack); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("qreq (1): %d\n"), pFrm->QOSCapsAp.qreq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("txopreq (1): %d\n"), pFrm->QOSCapsAp.txopreq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("reserved (1): %d\n"), pFrm->QOSCapsAp.reserved); } FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("APChannelReport:\n")); if (!pFrm->APChannelReport.present) @@ -15554,7 +15571,7 @@ tANI_U32 dot11fUnpackRadioMeasurementRequest(tpAniSirGlobal pCtx, tANI_U8 *pBuf, {offsetof(tDot11fReAssocRequest, QOSCapsStation), offsetof(tDot11fIEQOSCapsStation, present), 0, "QOSCapsStation" , 0, 3, 3, SigIeQOSCapsStation, {0, 0, 0, 0, 0}, 0, DOT11F_EID_QOSCAPSSTATION, 0, }, {offsetof(tDot11fReAssocRequest, RRMEnabledCap), offsetof(tDot11fIERRMEnabledCap, present), 0, "RRMEnabledCap" , 0, 7, 7, SigIeRRMEnabledCap, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RRMENABLEDCAP, 0, }, {offsetof(tDot11fReAssocRequest, MobilityDomain), offsetof(tDot11fIEMobilityDomain, present), 0, "MobilityDomain" , 0, 5, 5, SigIeMobilityDomain, {0, 0, 0, 0, 0}, 0, DOT11F_EID_MOBILITYDOMAIN, 0, }, - {offsetof(tDot11fReAssocRequest, FTInfo), offsetof(tDot11fIEFTInfo, present), 0, "FTInfo" , 0, 84, 187, SigIeFTInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FTINFO, 0, }, + {offsetof(tDot11fReAssocRequest, FTInfo), offsetof(tDot11fIEFTInfo, present), 0, "FTInfo" , 0, 84, 222, SigIeFTInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FTINFO, 0, }, {offsetof(tDot11fReAssocRequest, RICDataDesc), offsetof(tDot11fIERICDataDesc, present), offsetof(tDot11fReAssocRequest, num_RICDataDesc), "RICDataDesc" , 2, 2, 550, SigIeRICDataDesc, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RICDATADESC, 0, }, {offsetof(tDot11fReAssocRequest, WPAOpaque), offsetof(tDot11fIEWPAOpaque, present), 0, "WPAOpaque" , 0, 8, 255, SigIeWPAOpaque, {0, 80, 242, 1, 0}, 4, DOT11F_EID_WPAOPAQUE, 0, }, {offsetof(tDot11fReAssocRequest, HTCaps), offsetof(tDot11fIEHTCaps, present), 0, "HTCaps" , 0, 28, 60, SigIeHTCaps, {0, 0, 0, 0, 0}, 0, DOT11F_EID_HTCAPS, 0, }, @@ -15676,13 +15693,13 @@ tANI_U32 dot11fUnpackReAssocRequest(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 } else { - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("more_data_ack (1): %d\n"), pFrm->QOSCapsStation.more_data_ack); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("max_sp_length (2): %d\n"), pFrm->QOSCapsStation.max_sp_length); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("qack (1): %d\n"), pFrm->QOSCapsStation.qack); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("acbe_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbe_uapsd); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("acbk_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbk_uapsd); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("acvi_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvi_uapsd); FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("acvo_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvo_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("acvi_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvi_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("acbk_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbk_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("acbe_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbe_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("qack (1): %d\n"), pFrm->QOSCapsStation.qack); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("max_sp_length (2): %d\n"), pFrm->QOSCapsStation.max_sp_length); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("more_data_ack (1): %d\n"), pFrm->QOSCapsStation.more_data_ack); } FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("RRMEnabledCap:\n")); if (!pFrm->RRMEnabledCap.present) @@ -15778,6 +15795,18 @@ tANI_U32 dot11fUnpackReAssocRequest(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("num_PMK_R0_ID: %d.\n"), pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* ) pFrm->FTInfo.R0KH_ID.PMK_R0_ID, pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("IGTK:\n")); + if (!pFrm->FTInfo.IGTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyID, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->FTInfo.IGTK.IPN, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->FTInfo.IGTK.key, 24); + } } for (i = 0; i < pFrm->num_RICDataDesc; ++i) { @@ -16601,7 +16630,7 @@ tANI_U32 dot11fUnpackReAssocRequest(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 {offsetof(tDot11fReAssocResponse, RRMEnabledCap), offsetof(tDot11fIERRMEnabledCap, present), 0, "RRMEnabledCap" , 0, 7, 7, SigIeRRMEnabledCap, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RRMENABLEDCAP, 0, }, {offsetof(tDot11fReAssocResponse, RSNOpaque), offsetof(tDot11fIERSNOpaque, present), 0, "RSNOpaque" , 0, 8, 255, SigIeRSNOpaque, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RSNOPAQUE, 0, }, {offsetof(tDot11fReAssocResponse, MobilityDomain), offsetof(tDot11fIEMobilityDomain, present), 0, "MobilityDomain" , 0, 5, 5, SigIeMobilityDomain, {0, 0, 0, 0, 0}, 0, DOT11F_EID_MOBILITYDOMAIN, 0, }, - {offsetof(tDot11fReAssocResponse, FTInfo), offsetof(tDot11fIEFTInfo, present), 0, "FTInfo" , 0, 84, 187, SigIeFTInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FTINFO, 0, }, + {offsetof(tDot11fReAssocResponse, FTInfo), offsetof(tDot11fIEFTInfo, present), 0, "FTInfo" , 0, 84, 222, SigIeFTInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FTINFO, 0, }, {offsetof(tDot11fReAssocResponse, RICDataDesc), offsetof(tDot11fIERICDataDesc, present), offsetof(tDot11fReAssocResponse, num_RICDataDesc), "RICDataDesc" , 2, 2, 550, SigIeRICDataDesc, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RICDATADESC, 0, }, {offsetof(tDot11fReAssocResponse, WPA), offsetof(tDot11fIEWPA, present), 0, "WPA" , 0, 8, 50, SigIeWPA, {0, 80, 242, 1, 0}, 4, DOT11F_EID_WPA, 0, }, {offsetof(tDot11fReAssocResponse, HTCaps), offsetof(tDot11fIEHTCaps, present), 0, "HTCaps" , 0, 28, 60, SigIeHTCaps, {0, 0, 0, 0, 0}, 0, DOT11F_EID_HTCAPS, 0, }, @@ -16834,6 +16863,18 @@ tANI_U32 dot11fUnpackReAssocResponse(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U3 FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("num_PMK_R0_ID: %d.\n"), pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* ) pFrm->FTInfo.R0KH_ID.PMK_R0_ID, pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("IGTK:\n")); + if (!pFrm->FTInfo.IGTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyID, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.IGTK.IPN, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.IGTK.key, 24); + } } for (i = 0; i < pFrm->num_RICDataDesc; ++i) { @@ -17774,41 +17815,6 @@ tANI_U32 dot11fUnpackSMPowerSave(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nB } /* End dot11fUnpackSMPowerSave. */ - static const tFFDefn FFS_SaQueryRsp[] = { - { "Category", offsetof(tDot11fSaQueryRsp, Category), SigFfCategory , DOT11F_FF_CATEGORY_LEN, }, - { "Action", offsetof(tDot11fSaQueryRsp, Action), SigFfAction , DOT11F_FF_ACTION_LEN, }, - { "TransactionId", offsetof(tDot11fSaQueryRsp, TransactionId), SigFfTransactionId , DOT11F_FF_TRANSACTIONID_LEN, }, - { NULL, 0, 0, 0,}, - }; - - static const tIEDefn IES_SaQueryRsp[] = { - {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; - -tANI_U32 dot11fUnpackSaQueryRsp(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fSaQueryRsp *pFrm) -{ - tANI_U32 i = 0; - tANI_U32 status = 0; - status = UnpackCore(pCtx, pBuf, nBuf, FFS_SaQueryRsp, IES_SaQueryRsp, ( tANI_U8* )pFrm, sizeof(*pFrm)); - - (void)i; -# ifdef DOT11F_DUMP_FRAMES - if (!DOT11F_FAILED(status)) - { - FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYRSP), FRFL("Unpacked the SaQueryRsp:\n")); - FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYRSP), pBuf, nBuf); - FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYRSP), FRFL("to:\n")); - FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYRSP), FRFL("Category:\n")); - FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYRSP), ( tANI_U8* )&pFrm->Category.category, 1); - FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYRSP), FRFL("Action:\n")); - FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYRSP), ( tANI_U8* )&pFrm->Action.action, 1); - FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYRSP), FRFL("TransactionId:\n")); - FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYRSP), ( tANI_U8* )&pFrm->TransactionId.transId, 2); - } -# endif // DOT11F_DUMP_FRAMES - return status; - -} /* End dot11fUnpackSaQueryRsp. */ - static const tFFDefn FFS_TDLSDisReq[] = { { "Category", offsetof(tDot11fTDLSDisReq, Category), SigFfCategory , DOT11F_FF_CATEGORY_LEN, }, { "Action", offsetof(tDot11fTDLSDisReq, Action), SigFfAction , DOT11F_FF_ACTION_LEN, }, @@ -17870,7 +17876,7 @@ tANI_U32 dot11fUnpackTDLSDisReq(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBu {offsetof(tDot11fTDLSDisRsp, SuppChannels), offsetof(tDot11fIESuppChannels, present), 0, "SuppChannels" , 0, 4, 98, SigIeSuppChannels, {0, 0, 0, 0, 0}, 0, DOT11F_EID_SUPPCHANNELS, 0, }, {offsetof(tDot11fTDLSDisRsp, RSN), offsetof(tDot11fIERSN, present), 0, "RSN" , 0, 8, 112, SigIeRSN, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RSN, 0, }, {offsetof(tDot11fTDLSDisRsp, ExtCap), offsetof(tDot11fIEExtCap, present), 0, "ExtCap" , 0, 10, 10, SigIeExtCap, {0, 0, 0, 0, 0}, 0, DOT11F_EID_EXTCAP, 0, }, - {offsetof(tDot11fTDLSDisRsp, FTInfo), offsetof(tDot11fIEFTInfo, present), 0, "FTInfo" , 0, 84, 187, SigIeFTInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FTINFO, 0, }, + {offsetof(tDot11fTDLSDisRsp, FTInfo), offsetof(tDot11fIEFTInfo, present), 0, "FTInfo" , 0, 84, 222, SigIeFTInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FTINFO, 0, }, {offsetof(tDot11fTDLSDisRsp, FTTimeoutInterval), offsetof(tDot11fIEFTTimeoutInterval, present), 0, "FTTimeoutInterval" , 0, 7, 7, SigIeFTTimeoutInterval, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FTTIMEOUTINTERVAL, 0, }, {offsetof(tDot11fTDLSDisRsp, RICData), offsetof(tDot11fIERICData, present), 0, "RICData" , 0, 6, 6, SigIeRICData, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RICDATA, 0, }, {offsetof(tDot11fTDLSDisRsp, HTCaps), offsetof(tDot11fIEHTCaps, present), 0, "HTCaps" , 0, 28, 60, SigIeHTCaps, {0, 0, 0, 0, 0}, 0, DOT11F_EID_HTCAPS, 0, }, @@ -18065,6 +18071,18 @@ tANI_U32 dot11fUnpackTDLSDisRsp(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBu FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("num_PMK_R0_ID: %d.\n"), pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* ) pFrm->FTInfo.R0KH_ID.PMK_R0_ID, pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("IGTK:\n")); + if (!pFrm->FTInfo.IGTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyID, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->FTInfo.IGTK.IPN, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->FTInfo.IGTK.key, 24); + } } FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("FTTimeoutInterval:\n")); if (!pFrm->FTTimeoutInterval.present) @@ -18325,12 +18343,13 @@ tANI_U32 dot11fUnpackTDLSPeerTrafficRsp(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI static const tIEDefn IES_TDLSSetupCnf[] = { {offsetof(tDot11fTDLSSetupCnf, RSN), offsetof(tDot11fIERSN, present), 0, "RSN" , 0, 8, 112, SigIeRSN, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RSN, 0, }, {offsetof(tDot11fTDLSSetupCnf, EDCAParamSet), offsetof(tDot11fIEEDCAParamSet, present), 0, "EDCAParamSet" , 0, 20, 20, SigIeEDCAParamSet, {0, 0, 0, 0, 0}, 0, DOT11F_EID_EDCAPARAMSET, 0, }, - {offsetof(tDot11fTDLSSetupCnf, FTInfo), offsetof(tDot11fIEFTInfo, present), 0, "FTInfo" , 0, 84, 187, SigIeFTInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FTINFO, 0, }, + {offsetof(tDot11fTDLSSetupCnf, FTInfo), offsetof(tDot11fIEFTInfo, present), 0, "FTInfo" , 0, 84, 222, SigIeFTInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FTINFO, 0, }, {offsetof(tDot11fTDLSSetupCnf, FTTimeoutInterval), offsetof(tDot11fIEFTTimeoutInterval, present), 0, "FTTimeoutInterval" , 0, 7, 7, SigIeFTTimeoutInterval, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FTTIMEOUTINTERVAL, 0, }, {offsetof(tDot11fTDLSSetupCnf, HTInfo), offsetof(tDot11fIEHTInfo, present), 0, "HTInfo" , 0, 24, 56, SigIeHTInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_HTINFO, 0, }, {offsetof(tDot11fTDLSSetupCnf, LinkIdentifier), offsetof(tDot11fIELinkIdentifier, present), 0, "LinkIdentifier" , 0, 20, 20, SigIeLinkIdentifier, {0, 0, 0, 0, 0}, 0, DOT11F_EID_LINKIDENTIFIER, 0, }, {offsetof(tDot11fTDLSSetupCnf, WMMInfoStation), offsetof(tDot11fIEWMMInfoStation, present), 0, "WMMInfoStation" , 0, 9, 9, SigIeWMMInfoStation, {0, 80, 242, 2, 0}, 5, DOT11F_EID_WMMINFOSTATION, 0, }, {offsetof(tDot11fTDLSSetupCnf, VHTOperation), offsetof(tDot11fIEVHTOperation, present), 0, "VHTOperation" , 0, 7, 7, SigIeVHTOperation, {0, 0, 0, 0, 0}, 0, DOT11F_EID_VHTOPERATION, 0, }, + {offsetof(tDot11fTDLSSetupCnf, OperatingMode), offsetof(tDot11fIEOperatingMode, present), 0, "OperatingMode" , 0, 3, 3, SigIeOperatingMode, {0, 0, 0, 0, 0}, 0, DOT11F_EID_OPERATINGMODE, 0, }, {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; tANI_U32 dot11fUnpackTDLSSetupCnf(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fTDLSSetupCnf *pFrm) @@ -18454,6 +18473,18 @@ tANI_U32 dot11fUnpackTDLSSetupCnf(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 n FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("num_PMK_R0_ID: %d.\n"), pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* ) pFrm->FTInfo.R0KH_ID.PMK_R0_ID, pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("IGTK:\n")); + if (!pFrm->FTInfo.IGTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyID, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->FTInfo.IGTK.IPN, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->FTInfo.IGTK.key, 24); + } } FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("FTTimeoutInterval:\n")); if (!pFrm->FTTimeoutInterval.present) @@ -18533,6 +18564,18 @@ tANI_U32 dot11fUnpackTDLSSetupCnf(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 n FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->VHTOperation.chanCenterFreqSeg2, 1); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->VHTOperation.basicMCSSet, 2); } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("OperatingMode:\n")); + if (!pFrm->OperatingMode.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("chanWidth (2): %d\n"), pFrm->OperatingMode.chanWidth); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("reserved (2): %d\n"), pFrm->OperatingMode.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("rxNSS (3): %d\n"), pFrm->OperatingMode.rxNSS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("rxNSSType (1): %d\n"), pFrm->OperatingMode.rxNSSType); + } } # endif // DOT11F_DUMP_FRAMES return status; @@ -18555,7 +18598,7 @@ tANI_U32 dot11fUnpackTDLSSetupCnf(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 n {offsetof(tDot11fTDLSSetupReq, RSN), offsetof(tDot11fIERSN, present), 0, "RSN" , 0, 8, 112, SigIeRSN, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RSN, 0, }, {offsetof(tDot11fTDLSSetupReq, ExtCap), offsetof(tDot11fIEExtCap, present), 0, "ExtCap" , 0, 10, 10, SigIeExtCap, {0, 0, 0, 0, 0}, 0, DOT11F_EID_EXTCAP, 0, }, {offsetof(tDot11fTDLSSetupReq, QOSCapsStation), offsetof(tDot11fIEQOSCapsStation, present), 0, "QOSCapsStation" , 0, 3, 3, SigIeQOSCapsStation, {0, 0, 0, 0, 0}, 0, DOT11F_EID_QOSCAPSSTATION, 0, }, - {offsetof(tDot11fTDLSSetupReq, FTInfo), offsetof(tDot11fIEFTInfo, present), 0, "FTInfo" , 0, 84, 187, SigIeFTInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FTINFO, 0, }, + {offsetof(tDot11fTDLSSetupReq, FTInfo), offsetof(tDot11fIEFTInfo, present), 0, "FTInfo" , 0, 84, 222, SigIeFTInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FTINFO, 0, }, {offsetof(tDot11fTDLSSetupReq, FTTimeoutInterval), offsetof(tDot11fIEFTTimeoutInterval, present), 0, "FTTimeoutInterval" , 0, 7, 7, SigIeFTTimeoutInterval, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FTTIMEOUTINTERVAL, 0, }, {offsetof(tDot11fTDLSSetupReq, RICData), offsetof(tDot11fIERICData, present), 0, "RICData" , 0, 6, 6, SigIeRICData, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RICDATA, 0, }, {offsetof(tDot11fTDLSSetupReq, HTCaps), offsetof(tDot11fIEHTCaps, present), 0, "HTCaps" , 0, 28, 60, SigIeHTCaps, {0, 0, 0, 0, 0}, 0, DOT11F_EID_HTCAPS, 0, }, @@ -18725,13 +18768,13 @@ tANI_U32 dot11fUnpackTDLSSetupReq(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 n } else { - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("more_data_ack (1): %d\n"), pFrm->QOSCapsStation.more_data_ack); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("max_sp_length (2): %d\n"), pFrm->QOSCapsStation.max_sp_length); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("qack (1): %d\n"), pFrm->QOSCapsStation.qack); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("acbe_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbe_uapsd); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("acbk_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbk_uapsd); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("acvi_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvi_uapsd); FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("acvo_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvo_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("acvi_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvi_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("acbk_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbk_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("acbe_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbe_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("qack (1): %d\n"), pFrm->QOSCapsStation.qack); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("max_sp_length (2): %d\n"), pFrm->QOSCapsStation.max_sp_length); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("more_data_ack (1): %d\n"), pFrm->QOSCapsStation.more_data_ack); } FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("FTInfo:\n")); if (!pFrm->FTInfo.present) @@ -18778,6 +18821,18 @@ tANI_U32 dot11fUnpackTDLSSetupReq(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 n FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("num_PMK_R0_ID: %d.\n"), pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* ) pFrm->FTInfo.R0KH_ID.PMK_R0_ID, pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("IGTK:\n")); + if (!pFrm->FTInfo.IGTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyID, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->FTInfo.IGTK.IPN, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->FTInfo.IGTK.key, 24); + } } FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("FTTimeoutInterval:\n")); if (!pFrm->FTTimeoutInterval.present) @@ -18950,7 +19005,7 @@ tANI_U32 dot11fUnpackTDLSSetupReq(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 n {offsetof(tDot11fTDLSSetupRsp, RSN), offsetof(tDot11fIERSN, present), 0, "RSN" , 0, 8, 112, SigIeRSN, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RSN, 0, }, {offsetof(tDot11fTDLSSetupRsp, ExtCap), offsetof(tDot11fIEExtCap, present), 0, "ExtCap" , 0, 10, 10, SigIeExtCap, {0, 0, 0, 0, 0}, 0, DOT11F_EID_EXTCAP, 0, }, {offsetof(tDot11fTDLSSetupRsp, QOSCapsStation), offsetof(tDot11fIEQOSCapsStation, present), 0, "QOSCapsStation" , 0, 3, 3, SigIeQOSCapsStation, {0, 0, 0, 0, 0}, 0, DOT11F_EID_QOSCAPSSTATION, 0, }, - {offsetof(tDot11fTDLSSetupRsp, FTInfo), offsetof(tDot11fIEFTInfo, present), 0, "FTInfo" , 0, 84, 187, SigIeFTInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FTINFO, 0, }, + {offsetof(tDot11fTDLSSetupRsp, FTInfo), offsetof(tDot11fIEFTInfo, present), 0, "FTInfo" , 0, 84, 222, SigIeFTInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FTINFO, 0, }, {offsetof(tDot11fTDLSSetupRsp, FTTimeoutInterval), offsetof(tDot11fIEFTTimeoutInterval, present), 0, "FTTimeoutInterval" , 0, 7, 7, SigIeFTTimeoutInterval, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FTTIMEOUTINTERVAL, 0, }, {offsetof(tDot11fTDLSSetupRsp, RICData), offsetof(tDot11fIERICData, present), 0, "RICData" , 0, 6, 6, SigIeRICData, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RICDATA, 0, }, {offsetof(tDot11fTDLSSetupRsp, HTCaps), offsetof(tDot11fIEHTCaps, present), 0, "HTCaps" , 0, 28, 60, SigIeHTCaps, {0, 0, 0, 0, 0}, 0, DOT11F_EID_HTCAPS, 0, }, @@ -18958,6 +19013,7 @@ tANI_U32 dot11fUnpackTDLSSetupReq(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 n {offsetof(tDot11fTDLSSetupRsp, WMMInfoStation), offsetof(tDot11fIEWMMInfoStation, present), 0, "WMMInfoStation" , 0, 9, 9, SigIeWMMInfoStation, {0, 80, 242, 2, 0}, 5, DOT11F_EID_WMMINFOSTATION, 0, }, {offsetof(tDot11fTDLSSetupRsp, AID), offsetof(tDot11fIEAID, present), 0, "AID" , 0, 4, 4, SigIeAID, {0, 0, 0, 0, 0}, 0, DOT11F_EID_AID, 0, }, {offsetof(tDot11fTDLSSetupRsp, VHTCaps), offsetof(tDot11fIEVHTCaps, present), 0, "VHTCaps" , 0, 14, 14, SigIeVHTCaps, {0, 0, 0, 0, 0}, 0, DOT11F_EID_VHTCAPS, 0, }, + {offsetof(tDot11fTDLSSetupRsp, OperatingMode), offsetof(tDot11fIEOperatingMode, present), 0, "OperatingMode" , 0, 3, 3, SigIeOperatingMode, {0, 0, 0, 0, 0}, 0, DOT11F_EID_OPERATINGMODE, 0, }, {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; tANI_U32 dot11fUnpackTDLSSetupRsp(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fTDLSSetupRsp *pFrm) @@ -19122,13 +19178,13 @@ tANI_U32 dot11fUnpackTDLSSetupRsp(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 n } else { - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("more_data_ack (1): %d\n"), pFrm->QOSCapsStation.more_data_ack); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("max_sp_length (2): %d\n"), pFrm->QOSCapsStation.max_sp_length); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("qack (1): %d\n"), pFrm->QOSCapsStation.qack); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("acbe_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbe_uapsd); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("acbk_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbk_uapsd); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("acvi_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvi_uapsd); FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("acvo_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvo_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("acvi_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvi_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("acbk_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbk_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("acbe_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbe_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("qack (1): %d\n"), pFrm->QOSCapsStation.qack); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("max_sp_length (2): %d\n"), pFrm->QOSCapsStation.max_sp_length); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("more_data_ack (1): %d\n"), pFrm->QOSCapsStation.more_data_ack); } FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("FTInfo:\n")); if (!pFrm->FTInfo.present) @@ -19175,6 +19231,18 @@ tANI_U32 dot11fUnpackTDLSSetupRsp(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 n FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("num_PMK_R0_ID: %d.\n"), pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* ) pFrm->FTInfo.R0KH_ID.PMK_R0_ID, pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("IGTK:\n")); + if (!pFrm->FTInfo.IGTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyID, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->FTInfo.IGTK.IPN, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->FTInfo.IGTK.key, 24); + } } FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("FTTimeoutInterval:\n")); if (!pFrm->FTTimeoutInterval.present) @@ -19324,6 +19392,18 @@ tANI_U32 dot11fUnpackTDLSSetupRsp(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 n FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("txSupDataRate (13): %d\n"), pFrm->VHTCaps.txSupDataRate); FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("reserved3 (3): %d\n"), pFrm->VHTCaps.reserved3); } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("OperatingMode:\n")); + if (!pFrm->OperatingMode.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("chanWidth (2): %d\n"), pFrm->OperatingMode.chanWidth); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("reserved (2): %d\n"), pFrm->OperatingMode.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("rxNSS (3): %d\n"), pFrm->OperatingMode.rxNSS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("rxNSSType (1): %d\n"), pFrm->OperatingMode.rxNSSType); + } } # endif // DOT11F_DUMP_FRAMES return status; @@ -19338,7 +19418,7 @@ tANI_U32 dot11fUnpackTDLSSetupRsp(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 n }; static const tIEDefn IES_TDLSTeardown[] = { - {offsetof(tDot11fTDLSTeardown, FTInfo), offsetof(tDot11fIEFTInfo, present), 0, "FTInfo" , 0, 84, 187, SigIeFTInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FTINFO, 0, }, + {offsetof(tDot11fTDLSTeardown, FTInfo), offsetof(tDot11fIEFTInfo, present), 0, "FTInfo" , 0, 84, 222, SigIeFTInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FTINFO, 0, }, {offsetof(tDot11fTDLSTeardown, LinkIdentifier), offsetof(tDot11fIELinkIdentifier, present), 0, "LinkIdentifier" , 0, 20, 20, SigIeLinkIdentifier, {0, 0, 0, 0, 0}, 0, DOT11F_EID_LINKIDENTIFIER, 1, }, {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; @@ -19406,6 +19486,18 @@ tANI_U32 dot11fUnpackTDLSTeardown(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 n FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("num_PMK_R0_ID: %d.\n"), pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), ( tANI_U8* ) pFrm->FTInfo.R0KH_ID.PMK_R0_ID, pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("IGTK:\n")); + if (!pFrm->FTInfo.IGTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyID, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), ( tANI_U8* )&pFrm->FTInfo.IGTK.IPN, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), ( tANI_U8* )&pFrm->FTInfo.IGTK.key, 24); + } } FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("LinkIdentifier:\n")); if (!pFrm->LinkIdentifier.present) @@ -19906,9 +19998,6 @@ static tANI_U32 UnpackCore(tpAniSirGlobal pCtx, case SigFfTimeStamp: dot11fUnpackFfTimeStamp(pCtx, pBufRemaining, ( tDot11fFfTimeStamp* )(pFrm + pFf->offset )); break; - case SigFfTransactionId: - dot11fUnpackFfTransactionId(pCtx, pBufRemaining, ( tDot11fFfTransactionId* )(pFrm + pFf->offset )); - break; case SigFfTxAntennaId: dot11fUnpackFfTxAntennaId(pCtx, pBufRemaining, ( tDot11fFfTxAntennaId* )(pFrm + pFf->offset )); break; @@ -20019,6 +20108,9 @@ static tANI_U32 UnpackCore(tpAniSirGlobal pCtx, (tANI_U8*) &((( tDot11fIEHCF* )(pFrm + pIe->offset + sizeof( tDot11fIEHCF)*countOffset ) )->present), (tANI_U8*) &((( tDot11fIEHCF* )(pFrm + pIe->offset + sizeof(tDot11fIEHCF)*countOffset ) )->enabled) ); break; + case SigIeIGTK: + status |= dot11fUnpackIeIGTK(pCtx, pBufRemaining, len, ( tDot11fIEIGTK* )(pFrm + pIe->offset + sizeof(tDot11fIEIGTK)*countOffset) ); + break; case SigIeLLAttr: status |= dot11fUnpackIeLLAttr(pCtx, pBufRemaining, len, ( tDot11fIELLAttr* )(pFrm + pIe->offset + sizeof(tDot11fIELLAttr)*countOffset) ); break; @@ -21888,14 +21980,6 @@ tANI_U32 dot11fGetPackedSMPowerSaveSize(tpAniSirGlobal pCtx, tDot11fSMPowerSave return status; } /* End dot11fGetPackedSMPowerSaveSize. */ -tANI_U32 dot11fGetPackedSaQueryRspSize(tpAniSirGlobal pCtx, tDot11fSaQueryRsp *pFrm, tANI_U32 *pnNeeded) -{ - tANI_U32 status = 0; - *pnNeeded = 4; - status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_SaQueryRsp); - return status; -} /* End dot11fGetPackedSaQueryRspSize. */ - tANI_U32 dot11fGetPackedTDLSDisReqSize(tpAniSirGlobal pCtx, tDot11fTDLSDisReq *pFrm, tANI_U32 *pnNeeded) { tANI_U32 status = 0; @@ -22057,6 +22141,11 @@ static tANI_U32 GetPackedSizeCore(tpAniSirGlobal pCtx, byteCount = 1; pIePresent = ( (tDot11fIEHCF* )(pFrm + pIe->offset + offset * i ))->present; break; + case SigIeIGTK: + offset = sizeof(tDot11fIEIGTK); + byteCount = 33; + pIePresent = ( (tDot11fIEIGTK* )(pFrm + pIe->offset + offset * i ))->present; + break; case SigIeLLAttr: offset = sizeof(tDot11fIELLAttr); byteCount = 4; @@ -23214,14 +23303,6 @@ void dot11fPackFfTimeStamp(tpAniSirGlobal pCtx, (void)pCtx; } /* End dot11fPackFfTimeStamp. */ -void dot11fPackFfTransactionId(tpAniSirGlobal pCtx, - tDot11fFfTransactionId *pSrc, - tANI_U8 *pBuf) -{ - DOT11F_MEMCPY(pCtx, pBuf, pSrc->transId, 2); - (void)pCtx; -} /* End dot11fPackFfTransactionId. */ - void dot11fPackFfTxAntennaId(tpAniSirGlobal pCtx, tDot11fFfTxAntennaId *pSrc, tANI_U8 *pBuf) @@ -24811,6 +24892,45 @@ tANI_U32 dot11fPackIeHCF(tpAniSirGlobal pCtx, return DOT11F_PARSE_SUCCESS; } /* End dot11fPackIeHCF. */ +tANI_U32 dot11fPackIeIGTK(tpAniSirGlobal pCtx, + tDot11fIEIGTK *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 33; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 4; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + DOT11F_MEMCPY(pCtx, pBuf, pSrc->keyID, 2); + *pnConsumed += 2; + pBuf += 2; + DOT11F_MEMCPY(pCtx, pBuf, pSrc->IPN, 6); + *pnConsumed += 6; + pBuf += 6; + *pBuf = pSrc->keyLength; + *pnConsumed += 1; + pBuf += 1; + DOT11F_MEMCPY(pCtx, pBuf, pSrc->key, 24); + *pnConsumed += 24; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeIGTK. */ + tANI_U32 dot11fPackIeLLAttr(tpAniSirGlobal pCtx, tDot11fIELLAttr *pSrc, tANI_U8 *pBuf, @@ -24830,7 +24950,7 @@ tANI_U32 dot11fPackIeLLAttr(tpAniSirGlobal pCtx, ++pBuf; ++(*pnConsumed); frameshtonl(pCtx, pBuf, pSrc->defer_threshold, 1); *pnConsumed += 4; - // fieldsEndFlag = 1 + // fieldsEndFlag = 1 break; } (void)pCtx; @@ -29322,11 +29442,11 @@ tANI_U32 dot11fPackIeQOSCapsAp(tpAniSirGlobal pCtx, pIeLen = pBuf; ++pBuf; ++(*pnConsumed); tmp143__ = 0U; - tmp143__ |= ( pSrc->reserved << 0 ); - tmp143__ |= ( pSrc->txopreq << 1 ); - tmp143__ |= ( pSrc->qreq << 2 ); - tmp143__ |= ( pSrc->qack << 3 ); - tmp143__ |= ( pSrc->count << 4 ); + tmp143__ |= ( pSrc->count << 0 ); + tmp143__ |= ( pSrc->qack << 4 ); + tmp143__ |= ( pSrc->qreq << 5 ); + tmp143__ |= ( pSrc->txopreq << 6 ); + tmp143__ |= ( pSrc->reserved << 7 ); *pBuf = tmp143__; *pnConsumed += 1; // fieldsEndFlag = 1 @@ -29360,13 +29480,13 @@ tANI_U32 dot11fPackIeQOSCapsStation(tpAniSirGlobal pCtx, pIeLen = pBuf; ++pBuf; ++(*pnConsumed); tmp144__ = 0U; - tmp144__ |= ( pSrc->more_data_ack << 0 ); - tmp144__ |= ( pSrc->max_sp_length << 1 ); - tmp144__ |= ( pSrc->qack << 3 ); - tmp144__ |= ( pSrc->acbe_uapsd << 4 ); - tmp144__ |= ( pSrc->acbk_uapsd << 5 ); - tmp144__ |= ( pSrc->acvi_uapsd << 6 ); - tmp144__ |= ( pSrc->acvo_uapsd << 7 ); + tmp144__ |= ( pSrc->acvo_uapsd << 0 ); + tmp144__ |= ( pSrc->acvi_uapsd << 1 ); + tmp144__ |= ( pSrc->acbk_uapsd << 2 ); + tmp144__ |= ( pSrc->acbe_uapsd << 3 ); + tmp144__ |= ( pSrc->qack << 4 ); + tmp144__ |= ( pSrc->max_sp_length << 5 ); + tmp144__ |= ( pSrc->more_data_ack << 7 ); *pBuf = tmp144__; *pnConsumed += 1; // fieldsEndFlag = 1 @@ -31566,13 +31686,13 @@ tANI_U32 dot11fPackAssocRequest(tpAniSirGlobal pCtx, tDot11fAssocRequest *pFrm, } else { - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("more_data_ack (1): %d\n"), pFrm->QOSCapsStation.more_data_ack); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("max_sp_length (2): %d\n"), pFrm->QOSCapsStation.max_sp_length); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("qack (1): %d\n"), pFrm->QOSCapsStation.qack); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("acbe_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbe_uapsd); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("acbk_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbk_uapsd); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("acvi_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvi_uapsd); FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("acvo_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvo_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("acvi_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvi_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("acbk_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbk_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("acbe_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbe_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("qack (1): %d\n"), pFrm->QOSCapsStation.qack); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("max_sp_length (2): %d\n"), pFrm->QOSCapsStation.max_sp_length); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("more_data_ack (1): %d\n"), pFrm->QOSCapsStation.more_data_ack); } FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("RRMEnabledCap:\n")); if (!pFrm->RRMEnabledCap.present) @@ -32307,6 +32427,18 @@ tANI_U32 dot11fPackAssocResponse(tpAniSirGlobal pCtx, tDot11fAssocResponse *pFrm FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("num_PMK_R0_ID: %d.\n"), pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* ) pFrm->FTInfo.R0KH_ID.PMK_R0_ID, pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("IGTK:\n")); + if (!pFrm->FTInfo.IGTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyID, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.IGTK.IPN, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.IGTK.key, 24); + } } for (i = 0; i < pFrm->num_RICDataDesc; ++i) { @@ -33310,6 +33442,18 @@ tANI_U32 dot11fPackAuthentication(tpAniSirGlobal pCtx, tDot11fAuthentication *pF FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("num_PMK_R0_ID: %d.\n"), pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* ) pFrm->FTInfo.R0KH_ID.PMK_R0_ID, pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("IGTK:\n")); + if (!pFrm->FTInfo.IGTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyID, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->FTInfo.IGTK.IPN, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->FTInfo.IGTK.key, 24); + } } FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("FTTimeoutInterval:\n")); if (!pFrm->FTTimeoutInterval.present) @@ -33877,11 +34021,11 @@ tANI_U32 dot11fPackBeacon(tpAniSirGlobal pCtx, tDot11fBeacon *pFrm, tANI_U8 *pBu } else { - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("reserved (1): %d\n"), pFrm->QOSCapsAp.reserved); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("txopreq (1): %d\n"), pFrm->QOSCapsAp.txopreq); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("qreq (1): %d\n"), pFrm->QOSCapsAp.qreq); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("qack (1): %d\n"), pFrm->QOSCapsAp.qack); FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("count (4): %d\n"), pFrm->QOSCapsAp.count); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("qack (1): %d\n"), pFrm->QOSCapsAp.qack); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("qreq (1): %d\n"), pFrm->QOSCapsAp.qreq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("txopreq (1): %d\n"), pFrm->QOSCapsAp.txopreq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("reserved (1): %d\n"), pFrm->QOSCapsAp.reserved); } FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("APChannelReport:\n")); if (!pFrm->APChannelReport.present) @@ -35967,11 +36111,11 @@ tANI_U32 dot11fPackBeaconIEs(tpAniSirGlobal pCtx, tDot11fBeaconIEs *pFrm, tANI_U } else { - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("reserved (1): %d\n"), pFrm->QOSCapsAp.reserved); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("txopreq (1): %d\n"), pFrm->QOSCapsAp.txopreq); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("qreq (1): %d\n"), pFrm->QOSCapsAp.qreq); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("qack (1): %d\n"), pFrm->QOSCapsAp.qack); FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("count (4): %d\n"), pFrm->QOSCapsAp.count); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("qack (1): %d\n"), pFrm->QOSCapsAp.qack); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("qreq (1): %d\n"), pFrm->QOSCapsAp.qreq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("txopreq (1): %d\n"), pFrm->QOSCapsAp.txopreq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("reserved (1): %d\n"), pFrm->QOSCapsAp.reserved); } FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("APChannelReport:\n")); if (!pFrm->APChannelReport.present) @@ -40394,13 +40538,13 @@ tANI_U32 dot11fPackReAssocRequest(tpAniSirGlobal pCtx, tDot11fReAssocRequest *pF } else { - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("more_data_ack (1): %d\n"), pFrm->QOSCapsStation.more_data_ack); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("max_sp_length (2): %d\n"), pFrm->QOSCapsStation.max_sp_length); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("qack (1): %d\n"), pFrm->QOSCapsStation.qack); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("acbe_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbe_uapsd); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("acbk_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbk_uapsd); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("acvi_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvi_uapsd); FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("acvo_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvo_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("acvi_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvi_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("acbk_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbk_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("acbe_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbe_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("qack (1): %d\n"), pFrm->QOSCapsStation.qack); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("max_sp_length (2): %d\n"), pFrm->QOSCapsStation.max_sp_length); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("more_data_ack (1): %d\n"), pFrm->QOSCapsStation.more_data_ack); } FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("RRMEnabledCap:\n")); if (!pFrm->RRMEnabledCap.present) @@ -40496,6 +40640,18 @@ tANI_U32 dot11fPackReAssocRequest(tpAniSirGlobal pCtx, tDot11fReAssocRequest *pF FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("num_PMK_R0_ID: %d.\n"), pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* ) pFrm->FTInfo.R0KH_ID.PMK_R0_ID, pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("IGTK:\n")); + if (!pFrm->FTInfo.IGTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyID, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->FTInfo.IGTK.IPN, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->FTInfo.IGTK.key, 24); + } } for (i = 0; i < pFrm->num_RICDataDesc; ++i) { @@ -41518,6 +41674,18 @@ tANI_U32 dot11fPackReAssocResponse(tpAniSirGlobal pCtx, tDot11fReAssocResponse * FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("num_PMK_R0_ID: %d.\n"), pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* ) pFrm->FTInfo.R0KH_ID.PMK_R0_ID, pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("IGTK:\n")); + if (!pFrm->FTInfo.IGTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyID, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.IGTK.IPN, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.IGTK.key, 24); + } } for (i = 0; i < pFrm->num_RICDataDesc; ++i) { @@ -42451,32 +42619,6 @@ tANI_U32 dot11fPackSMPowerSave(tpAniSirGlobal pCtx, tDot11fSMPowerSave *pFrm, tA } /* End dot11fUnpackSMPowerSave. */ -tANI_U32 dot11fPackSaQueryRsp(tpAniSirGlobal pCtx, tDot11fSaQueryRsp *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) -{ - tANI_U32 i = 0; - tANI_U32 status = 0; - (void)i; - *pnConsumed = 0U; - status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_SaQueryRsp, IES_SaQueryRsp); - -# ifdef DOT11F_DUMP_FRAMES - if (!DOT11F_FAILED(status)) - { - FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYRSP), FRFL("Packed the SaQueryRsp:\n")); - FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYRSP), FRFL("Category:\n")); - FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYRSP), ( tANI_U8* )&pFrm->Category.category, 1); - FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYRSP), FRFL("Action:\n")); - FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYRSP), ( tANI_U8* )&pFrm->Action.action, 1); - FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYRSP), FRFL("TransactionId:\n")); - FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYRSP), ( tANI_U8* )&pFrm->TransactionId.transId, 2); - FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYRSP), FRFL("to:\n")); - FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYRSP), pBuf, nBuf); - } -# endif // DOT11F_DUMP_FRAMES - return status; - -} /* End dot11fUnpackSaQueryRsp. */ - tANI_U32 dot11fPackTDLSDisReq(tpAniSirGlobal pCtx, tDot11fTDLSDisReq *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) { tANI_U32 i = 0; @@ -42700,6 +42842,18 @@ tANI_U32 dot11fPackTDLSDisRsp(tpAniSirGlobal pCtx, tDot11fTDLSDisRsp *pFrm, tANI FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("num_PMK_R0_ID: %d.\n"), pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* ) pFrm->FTInfo.R0KH_ID.PMK_R0_ID, pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("IGTK:\n")); + if (!pFrm->FTInfo.IGTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyID, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->FTInfo.IGTK.IPN, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->FTInfo.IGTK.key, 24); + } } FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("FTTimeoutInterval:\n")); if (!pFrm->FTTimeoutInterval.present) @@ -43049,6 +43203,18 @@ tANI_U32 dot11fPackTDLSSetupCnf(tpAniSirGlobal pCtx, tDot11fTDLSSetupCnf *pFrm, FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("num_PMK_R0_ID: %d.\n"), pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* ) pFrm->FTInfo.R0KH_ID.PMK_R0_ID, pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("IGTK:\n")); + if (!pFrm->FTInfo.IGTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyID, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->FTInfo.IGTK.IPN, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->FTInfo.IGTK.key, 24); + } } FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("FTTimeoutInterval:\n")); if (!pFrm->FTTimeoutInterval.present) @@ -43128,6 +43294,18 @@ tANI_U32 dot11fPackTDLSSetupCnf(tpAniSirGlobal pCtx, tDot11fTDLSSetupCnf *pFrm, FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->VHTOperation.chanCenterFreqSeg2, 1); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->VHTOperation.basicMCSSet, 2); } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("OperatingMode:\n")); + if (!pFrm->OperatingMode.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("chanWidth (2): %d\n"), pFrm->OperatingMode.chanWidth); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("reserved (2): %d\n"), pFrm->OperatingMode.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("rxNSS (3): %d\n"), pFrm->OperatingMode.rxNSS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("rxNSSType (1): %d\n"), pFrm->OperatingMode.rxNSSType); + } FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("to:\n")); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), pBuf, nBuf); } @@ -43295,13 +43473,13 @@ tANI_U32 dot11fPackTDLSSetupReq(tpAniSirGlobal pCtx, tDot11fTDLSSetupReq *pFrm, } else { - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("more_data_ack (1): %d\n"), pFrm->QOSCapsStation.more_data_ack); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("max_sp_length (2): %d\n"), pFrm->QOSCapsStation.max_sp_length); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("qack (1): %d\n"), pFrm->QOSCapsStation.qack); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("acbe_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbe_uapsd); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("acbk_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbk_uapsd); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("acvi_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvi_uapsd); FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("acvo_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvo_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("acvi_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvi_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("acbk_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbk_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("acbe_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbe_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("qack (1): %d\n"), pFrm->QOSCapsStation.qack); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("max_sp_length (2): %d\n"), pFrm->QOSCapsStation.max_sp_length); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("more_data_ack (1): %d\n"), pFrm->QOSCapsStation.more_data_ack); } FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("FTInfo:\n")); if (!pFrm->FTInfo.present) @@ -43348,6 +43526,18 @@ tANI_U32 dot11fPackTDLSSetupReq(tpAniSirGlobal pCtx, tDot11fTDLSSetupReq *pFrm, FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("num_PMK_R0_ID: %d.\n"), pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* ) pFrm->FTInfo.R0KH_ID.PMK_R0_ID, pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("IGTK:\n")); + if (!pFrm->FTInfo.IGTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyID, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->FTInfo.IGTK.IPN, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->FTInfo.IGTK.key, 24); + } } FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("FTTimeoutInterval:\n")); if (!pFrm->FTTimeoutInterval.present) @@ -43666,13 +43856,13 @@ tANI_U32 dot11fPackTDLSSetupRsp(tpAniSirGlobal pCtx, tDot11fTDLSSetupRsp *pFrm, } else { - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("more_data_ack (1): %d\n"), pFrm->QOSCapsStation.more_data_ack); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("max_sp_length (2): %d\n"), pFrm->QOSCapsStation.max_sp_length); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("qack (1): %d\n"), pFrm->QOSCapsStation.qack); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("acbe_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbe_uapsd); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("acbk_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbk_uapsd); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("acvi_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvi_uapsd); FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("acvo_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvo_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("acvi_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvi_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("acbk_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbk_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("acbe_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbe_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("qack (1): %d\n"), pFrm->QOSCapsStation.qack); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("max_sp_length (2): %d\n"), pFrm->QOSCapsStation.max_sp_length); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("more_data_ack (1): %d\n"), pFrm->QOSCapsStation.more_data_ack); } FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("FTInfo:\n")); if (!pFrm->FTInfo.present) @@ -43719,6 +43909,18 @@ tANI_U32 dot11fPackTDLSSetupRsp(tpAniSirGlobal pCtx, tDot11fTDLSSetupRsp *pFrm, FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("num_PMK_R0_ID: %d.\n"), pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* ) pFrm->FTInfo.R0KH_ID.PMK_R0_ID, pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("IGTK:\n")); + if (!pFrm->FTInfo.IGTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyID, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->FTInfo.IGTK.IPN, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->FTInfo.IGTK.key, 24); + } } FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("FTTimeoutInterval:\n")); if (!pFrm->FTTimeoutInterval.present) @@ -43868,6 +44070,18 @@ tANI_U32 dot11fPackTDLSSetupRsp(tpAniSirGlobal pCtx, tDot11fTDLSSetupRsp *pFrm, FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("txSupDataRate (13): %d\n"), pFrm->VHTCaps.txSupDataRate); FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("reserved3 (3): %d\n"), pFrm->VHTCaps.reserved3); } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("OperatingMode:\n")); + if (!pFrm->OperatingMode.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("chanWidth (2): %d\n"), pFrm->OperatingMode.chanWidth); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("reserved (2): %d\n"), pFrm->OperatingMode.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("rxNSS (3): %d\n"), pFrm->OperatingMode.rxNSS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("rxNSSType (1): %d\n"), pFrm->OperatingMode.rxNSSType); + } FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("to:\n")); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), pBuf, nBuf); } @@ -43939,6 +44153,18 @@ tANI_U32 dot11fPackTDLSTeardown(tpAniSirGlobal pCtx, tDot11fTDLSTeardown *pFrm, FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("num_PMK_R0_ID: %d.\n"), pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), ( tANI_U8* ) pFrm->FTInfo.R0KH_ID.PMK_R0_ID, pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("IGTK:\n")); + if (!pFrm->FTInfo.IGTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyID, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), ( tANI_U8* )&pFrm->FTInfo.IGTK.IPN, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), ( tANI_U8* )&pFrm->FTInfo.IGTK.key, 24); + } } FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("LinkIdentifier:\n")); if (!pFrm->LinkIdentifier.present) @@ -44371,9 +44597,6 @@ static tANI_U32 PackCore(tpAniSirGlobal pCtx, case SigFfTimeStamp: dot11fPackFfTimeStamp(pCtx, (tDot11fFfTimeStamp* )(pSrc + pFf->offset), pBufRemaining); break; - case SigFfTransactionId: - dot11fPackFfTransactionId(pCtx, (tDot11fFfTransactionId* )(pSrc + pFf->offset), pBufRemaining); - break; case SigFfTxAntennaId: dot11fPackFfTxAntennaId(pCtx, (tDot11fFfTxAntennaId* )(pSrc + pFf->offset), pBufRemaining); break; @@ -44429,6 +44652,9 @@ static tANI_U32 PackCore(tpAniSirGlobal pCtx, case SigIeHCF: status |= dot11fPackIeHCF(pCtx, ( tDot11fIEHCF* )(pSrc + pIe->offset + sizeof(tDot11fIEHCF) * i ), pBufRemaining, nBufRemaining, &len); break; + case SigIeIGTK: + status |= dot11fPackIeIGTK(pCtx, ( tDot11fIEIGTK* )(pSrc + pIe->offset + sizeof(tDot11fIEIGTK) * i ), pBufRemaining, nBufRemaining, &len); + break; case SigIeLLAttr: status |= dot11fPackIeLLAttr(pCtx, ( tDot11fIELLAttr* )(pSrc + pIe->offset + sizeof(tDot11fIELLAttr) * i ), pBufRemaining, nBufRemaining, &len); break; diff --git a/drivers/staging/prima/CORE/SYS/legacy/src/utils/src/macTrace.c b/drivers/staging/prima/CORE/SYS/legacy/src/utils/src/macTrace.c index 4ed519345ff..70efdaceaaf 100644 --- a/drivers/staging/prima/CORE/SYS/legacy/src/utils/src/macTrace.c +++ b/drivers/staging/prima/CORE/SYS/legacy/src/utils/src/macTrace.c @@ -503,6 +503,9 @@ tANI_U8* macTraceGetWdaMsgString( tANI_U16 wdaMsg ) CASE_RETURN_STRING(WDA_UPDATE_SCAN_PARAMS_REQ); CASE_RETURN_STRING(WDA_SET_PNO_CHANGED_IND); #endif // FEATURE_WLAN_SCAN_PNO +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + CASE_RETURN_STRING(WDA_ROAM_SCAN_OFFLOAD_REQ); +#endif #ifdef WLAN_WAKEUP_EVENTS CASE_RETURN_STRING(WDA_WAKE_REASON_IND); #endif // WLAN_WAKEUP_EVENTS diff --git a/drivers/staging/prima/CORE/TL/inc/wlan_qct_tl.h b/drivers/staging/prima/CORE/TL/inc/wlan_qct_tl.h index 7bf957805ca..9e558f5c096 100644 --- a/drivers/staging/prima/CORE/TL/inc/wlan_qct_tl.h +++ b/drivers/staging/prima/CORE/TL/inc/wlan_qct_tl.h @@ -51,17 +51,9 @@ DESCRIPTION This file contains the external API exposed by the wlan transport layer module. -<<<<<<< HEAD:CORE/TL/inc/wlan_qct_tl.h - - Copyright (c) 2008 QUALCOMM Incorporated. All Rights Reserved. - Qualcomm Confidential and Proprietary -======= - - Copyright (c) 2008 Qualcomm Technologies, Inc. All Rights Reserved. Qualcomm Technologies Confidential and Proprietary ->>>>>>> 326d6cf... wlan: remove obsolete ANI_CHIPSET_VOLANS featurization:prima/CORE/TL/inc/wlan_qct_tl.h ===========================================================================*/ @@ -107,7 +99,6 @@ when who what, where, why #include "sirApi.h" #include "csrApi.h" #include "sapApi.h" - /*---------------------------------------------------------------------------- * Preprocessor Definitions and Constants * -------------------------------------------------------------------------*/ @@ -134,10 +125,6 @@ when who what, where, why /*Maximum number of ACs */ #define WLANTL_MAX_AC 4 - -/* Bit Mask to represent All Stations */ -#define WLAN_ALL_STA 0xFF - /* Maximum number of station supported by TL, including BC. */ #define WLAN_MAX_STA_COUNT (HAL_NUM_STA) #define WLAN_NON32_STA_COUNT 14 @@ -442,6 +429,10 @@ typedef struct v_U16_t ucDesSTAId; /*Rssi based on the received packet */ v_S7_t rssiAvg; + #ifdef FEATURE_WLAN_TDLS + /* Packet received on direct link/AP link */ + v_U8_t isStaTdls; + #endif }WLANTL_RxMetaInfoType; @@ -2625,4 +2616,170 @@ WLANTL_ClearTxXmitPending v_PVOID_t pvosGCtx ); +/*========================================================================== + FUNCTION WLANTL_UpdateSTABssIdforIBSS + + DESCRIPTION + HDD will call this API to update the BSSID for this Station. + + DEPENDENCIES + The HDD Should registered the staID with TL before calling this function. + + PARAMETERS + + IN + pvosGCtx: Pointer to the global vos context; a handle to TL's + or WDA's control block can be extracted from its context + IN + ucSTAId The Station ID for Bssid to be updated + IN + pBssid BSSID to be updated + + RETURN VALUE + The result code associated with performing the operation + + VOS_STATUS_E_INVAL: Input parameters are invalid + VOS_STATUS_E_FAULT: Station ID is outside array boundaries or pointer to + TL cb is NULL ; access would cause a page fault + VOS_STATUS_E_EXISTS: Station was not registered + VOS_STATUS_SUCCESS: Everything is good :) + + SIDE EFFECTS +============================================================================*/ + +VOS_STATUS +WLANTL_UpdateSTABssIdforIBSS +( + v_PVOID_t pvosGCtx, + v_U8_t ucSTAId, + v_U8_t *pBssid +); + + + +/*=============================================================================== + FUNCTION WLANTL_UpdateLinkCapacity + + DESCRIPTION This function updates the STA's Link Capacity in TL + + DEPENDENCIES None + + PARAMETERS + + pvosGCtx VOS context VOS Global context + staId Station ID Station ID + linkCapacity linkCapacity Link Capacity + + RETURN None + + SIDE EFFECTS none + ===============================================================================*/ + +void +WLANTL_UpdateLinkCapacity +( + v_PVOID_t pvosGCtx, + v_U8_t staId, + v_U32_t linkCapacity); + +/*=========================================================================== + + FUNCTION WLANTL_GetSTALinkCapacity + + DESCRIPTION + + Returns Link Capacity of a particular STA. + + DEPENDENCIES + + A station must have been registered before its state can be retrieved. + + PARAMETERS + + IN + pvosGCtx: pointer to the global vos context; a handle to TL's + control block can be extracted from its context + ucSTAId: identifier of the station + + OUT + plinkCapacity: the current link capacity the connection to + the given station + + + RETURN VALUE + + The result code associated with performing the operation + + VOS_STATUS_E_INVAL: Input parameters are invalid + VOS_STATUS_E_FAULT: Station ID is outside array boundaries or pointer to + TL cb is NULL ; access would cause a page fault + VOS_STATUS_E_EXISTS: Station was not registered + VOS_STATUS_SUCCESS: Everything is good :) + + SIDE EFFECTS + +============================================================================*/ + +VOS_STATUS +WLANTL_GetSTALinkCapacity +( + v_PVOID_t pvosGCtx, + v_U8_t ucSTAId, + v_U32_t *plinkCapacity +); + +/*=========================================================================== + FUNCTION WLANTL_TxThreadDebugHandler + + DESCRIPTION + Printing TL Snapshot dump, processed under TxThread context, currently + information regarding the global TlCb struture. Dumps information related + to per active STA connection currently in use by TL. + + DEPENDENCIES + The TL must be initialized before this gets called. + + PARAMETERS + + IN + pvosGCtx: Pointer to the global vos context; a handle to TL's + or WDA's control block can be extracted from its context + + RETURN VALUE None + + SIDE EFFECTS +============================================================================*/ + +v_VOID_t +WLANTL_TxThreadDebugHandler +( + v_PVOID_t *pvosGCtx +); + +/*========================================================================== + FUNCTION WLANTL_TLDebugMessage + + DESCRIPTION + Post a TL Snapshot request, posts message in TxThread. + + DEPENDENCIES + The TL must be initialized before this gets called. + + PARAMETERS + + IN + displaySnapshot Boolean showing whether to dump the snapshot or not. + + RETURN VALUE None + + SIDE EFFECTS + +============================================================================*/ + +v_VOID_t +WLANTL_TLDebugMessage +( + v_BOOL_t displaySnapshot +); + #endif /* #ifndef WLAN_QCT_WLANTL_H */ diff --git a/drivers/staging/prima/CORE/TL/src/wlan_qct_tl.c b/drivers/staging/prima/CORE/TL/src/wlan_qct_tl.c index aa6aba8ebce..dde6092495f 100644 --- a/drivers/staging/prima/CORE/TL/src/wlan_qct_tl.c +++ b/drivers/staging/prima/CORE/TL/src/wlan_qct_tl.c @@ -155,9 +155,15 @@ #endif /*Enables debugging behavior in TL*/ #define TL_DEBUG +/*Enables debugging FC control frame in TL*/ +//#define TL_DEBUG_FC //#define WLAN_SOFTAP_FLOWCTRL_EN - //#define BTAMP_TEST +#ifdef TL_DEBUG_FC +#include +#include // wpalReadRegister +#endif + /*---------------------------------------------------------------------------- * Preprocessor Definitions and Constants * -------------------------------------------------------------------------*/ @@ -335,7 +341,6 @@ typedef struct #define WLAN_TL_INVALID_B_SIG 255 #define ENTER() VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO, "Enter:%s", __func__) - #define WLAN_TL_AC_ARRAY_2_MASK( _pSTA, _ucACMask, i ) \ do\ {\ @@ -491,7 +496,7 @@ WLANTL_Open if (( NULL == pTLCb ) || ( NULL == pTLConfig ) ) { TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_FATAL, - "WLAN TL: Invalid input pointer on WLANTL_Open TL %x Config %x", pTLCb, pTLConfig )); + "WLAN TL: Invalid input pointer on WLANTL_Open TL %p Config %p", pTLCb, pTLConfig )); return VOS_STATUS_E_FAULT; } @@ -687,7 +692,6 @@ WLANTL_Start vos_atomic_set_U8( &pTLCb->ucTxSuspended, 0); pTLCb->uResCount = uResCount; - return VOS_STATUS_SUCCESS; }/* WLANTL_Start */ @@ -3039,15 +3043,14 @@ WLANTL_TxMgmtFrm "WLAN TL:Failed while attempting to get addr2 %d", vosStatus)); return vosStatus; } -#ifdef FEATURE_WLAN_CCX - /* CCX IAPP Frame which are data frames but technically used + + /* CCX IAPP/TDLS Frame which are data frames but technically used * for management functionality comes through route. */ if (WLANTL_IS_QOS_DATA_FRAME(wFrmType)) \ { uQosHdr = VOS_TRUE; } -#endif /*---------------------------------------------------------------------- Call WDA to build TX header ----------------------------------------------------------------------*/ @@ -3223,8 +3226,6 @@ WLANTL_SuspendDataTx { WLANTL_CbType* pTLCb = NULL; vos_msg_t vosMsg; - v_U8_t ucTxSuspendReq, ucTxSuspended; - v_U32_t STAId = 0; /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ @@ -3233,7 +3234,7 @@ WLANTL_SuspendDataTx Extract TL control block ------------------------------------------------------------------------*/ pTLCb = VOS_GET_TL_CB(pvosGCtx); - if ( NULL == pTLCb || NULL == pucSTAId ) + if ( NULL == pTLCb ) { TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, "WLAN TL:Invalid TL pointer from pvosGCtx on WLANTL_SuspendDataTx")); @@ -3243,65 +3244,41 @@ WLANTL_SuspendDataTx /*------------------------------------------------------------------------ Check the type of request: generic suspend, or per station suspend ------------------------------------------------------------------------*/ - /* Station IDs for Suspend request are received as bitmap */ - ucTxSuspendReq = *pucSTAId; - ucTxSuspended = pTLCb->ucTxSuspended; - - if (WLAN_ALL_STA == ucTxSuspended) - { - /* All Stations are in Suspend mode. Nothing to do */ - TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH, - "WLAN TL:All stations already suspended")); - return VOS_STATUS_E_EXISTS; - } - - if (WLAN_ALL_STA == *pucSTAId) + if (NULL == pucSTAId) { /* General Suspend Request received */ TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH, "WLAN TL:General suspend requested")); - vos_atomic_set_U8( &pTLCb->ucTxSuspended, WLAN_ALL_STA); + vos_atomic_set_U8( &pTLCb->ucTxSuspended, 1); vosMsg.reserved = WLAN_MAX_STA_COUNT; } else { - /* Station specific Suspend Request received */ - /* Update Station Id Bit map for suspend request */ - do + if ( WLANTL_STA_ID_INVALID( *pucSTAId ) ) { - /* If Bit set for this station with STAId */ - if (ucTxSuspendReq >> (STAId +1) ) - { - /* If it is Not a valid station ID */ - if ( WLANTL_STA_ID_INVALID( STAId ) ) - { - TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, - "WLAN TL:Invalid station id requested on WLANTL_SuspendDataTx")); - STAId++; - continue; - } - /* If this station is Not registered with TL */ - if( NULL == pTLCb->atlSTAClients[STAId] ) - { - TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, - "WLAN TL:Station memory was not previously allocated on WLANTL_SuspendDataTx")); - STAId++; - continue; - } - if ( 0 == pTLCb->atlSTAClients[STAId]->ucExists ) - { - TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, - "WLAN TL:Station was not previously registered on WLANTL_SuspendDataTx")); - STAId++; - continue; - } + TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "WLAN TL:Invalid station id %d requested on WLANTL_SuspendDataTx", *pucSTAId)); + return VOS_STATUS_E_FAULT; + } - TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH, - "WLAN TL:Suspend request for station: %d", STAId)); - vos_atomic_set_U8( &pTLCb->atlSTAClients[STAId]->ucTxSuspended, 1); - } - STAId++; - } while ( STAId < WLAN_MAX_STA_COUNT ); + if ( NULL == pTLCb->atlSTAClients[*pucSTAId] ) + { + TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "WLAN TL:Invalid pTLCb->atlSTAClients pointer for STA Id :%d on " + "WLANTL_SuspendDataTx", *pucSTAId)); + return VOS_STATUS_E_FAULT; + } + + if ( 0 == pTLCb->atlSTAClients[*pucSTAId]->ucExists ) + { + TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "WLAN TL:Station %d was not previously registered on WLANTL_SuspendDataTx", *pucSTAId)); + return VOS_STATUS_E_EXISTS; + } + + TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH, + "WLAN TL:Suspend request for station: %d", *pucSTAId)); + vos_atomic_set_U8( &pTLCb->atlSTAClients[*pucSTAId]->ucTxSuspended, 1); vosMsg.reserved = *pucSTAId; } @@ -3360,8 +3337,6 @@ WLANTL_ResumeDataTx ) { WLANTL_CbType* pTLCb = NULL; - v_U8_t ucTxResumeReq; - v_U32_t STAId = 0; /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ /*------------------------------------------------------------------------ @@ -3369,75 +3344,56 @@ WLANTL_ResumeDataTx Extract TL control block ------------------------------------------------------------------------*/ pTLCb = VOS_GET_TL_CB(pvosGCtx); - if ( NULL == pTLCb || NULL == pucSTAId) + if ( NULL == pTLCb ) { TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, "WLAN TL:Invalid TL pointer from pvosGCtx on WLANTL_ResumeDataTx")); return VOS_STATUS_E_FAULT; } - ucTxResumeReq = *pucSTAId; /*------------------------------------------------------------------------ Check to see the type of resume ------------------------------------------------------------------------*/ - if ( WLAN_ALL_STA == *pucSTAId) + if ( NULL == pucSTAId ) { TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH, "WLAN TL:General resume requested")); vos_atomic_set_U8( &pTLCb->ucTxSuspended, 0); - - /* Set to Resume for all stations */ - for (STAId = 0; STAId < WLAN_MAX_STA_COUNT; STAId++) - { - if( NULL != pTLCb->atlSTAClients[STAId] ) - { - vos_atomic_set_U8( &pTLCb->atlSTAClients[STAId]->ucTxSuspended, 0); - } - } } else { - do + if ( WLANTL_STA_ID_INVALID( *pucSTAId )) { - /* If Bit Set for this station with STAId */ - if (ucTxResumeReq >> (STAId + 1)) - { - /* If it is Not a valid station ID */ - if ( WLANTL_STA_ID_INVALID( STAId )) - { - TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, - "WLAN TL:Invalid station id requested on WLANTL_ResumeDataTx")); - STAId++; - continue; - } - if ( NULL == pTLCb->atlSTAClients[STAId]) - { - TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, - "WLAN TL:Station was not allocated memory on WLANTL_ResumeDataTx")); - STAId++; - continue; - } - /* If this station is Not registered with TL */ - if ( 0 == pTLCb->atlSTAClients[STAId]->ucExists ) - { - TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, - "WLAN TL:Station was not previously registered on WLANTL_ResumeDataTx")); - STAId++; - continue; - } + TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "WLAN TL:Invalid station id %d requested on WLANTL_ResumeDataTx", *pucSTAId)); + return VOS_STATUS_E_FAULT; + } - TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH, - "WLAN TL:Resume request for station: %d", STAId)); - vos_atomic_set_U8( &pTLCb->atlSTAClients[STAId]->ucTxSuspended, 0); - } - STAId++; - } while ( STAId < WLAN_MAX_STA_COUNT ); + if ( NULL == pTLCb->atlSTAClients[*pucSTAId] ) + { + TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "WLAN TL:Invalid pTLCb->atlSTAClients pointer for STA Id :%d on " + "WLANTL_ResumeDataTx", *pucSTAId)); + return VOS_STATUS_E_FAULT; + } + + if ( 0 == pTLCb->atlSTAClients[*pucSTAId]->ucExists ) + { + TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "WLAN TL:Station %d was not previously registered on WLANTL_ResumeDataTx", *pucSTAId)); + return VOS_STATUS_E_EXISTS; + } + + TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH, + "WLAN TL:Resume request for station: %d", *pucSTAId)); + vos_atomic_set_U8( &pTLCb->atlSTAClients[*pucSTAId]->ucTxSuspended, 0); } /*------------------------------------------------------------------------ Resuming transmission ------------------------------------------------------------------------*/ - if ( pTLCb->uResCount >= WDA_TLI_MIN_RES_MF ) + if (( pTLCb->uResCount >= WDA_TLI_MIN_RES_MF ) && + ( 0 == pTLCb->ucTxSuspended )) { TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH, "WLAN TL:Resuming transmission")); @@ -4378,7 +4334,7 @@ WLANTL_TxComp } TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH, - "WLAN TL:Calling Tx complete for pkt %x in function %x", + "WLAN TL:Calling Tx complete for pkt %p in function %p", vosDataBuff, pfnTxComp)); vosTempTx = vosDataBuff; @@ -4456,8 +4412,8 @@ WLANTL_CacheSTAFrame if (( NULL == pTLCb ) || ( NULL == vosTempBuff ) ) { TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, - "WLAN TL: Invalid input pointer on WLANTL_CacheSTAFrame TL %x" - " Packet %x", pTLCb, vosTempBuff )); + "WLAN TL: Invalid input pointer on WLANTL_CacheSTAFrame TL %p" + " Packet %p", pTLCb, vosTempBuff )); return VOS_STATUS_E_FAULT; } @@ -4651,7 +4607,7 @@ WLANTL_ForwardSTAFrames if ( NULL == pTLCb ) { TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, - "WLAN TL: Invalid input pointer on WLANTL_ForwardSTAFrames TL %x", + "WLAN TL: Invalid input pointer on WLANTL_ForwardSTAFrames TL %p", pTLCb )); return VOS_STATUS_E_FAULT; } @@ -5082,11 +5038,16 @@ WLANTL_ProcessFCFrame { #if 1 //enable processing of only fcStaTxDisabled bitmap for now. the else part is old better qos code. // need to revisit the old code for full implementation. - v_U8_t ucTxSuspended = 0, ucTxSuspendReq = 0, ucTxResumeReq = 0; - WLANTL_CbType* pTLCb = NULL; - + v_U8_t ucSTAId; + v_U16_t ucStaValidBitmap; + v_U16_t ucStaTxDisabledBitmap; + WLANTL_CbType* pTLCb = NULL; + #ifdef TL_DEBUG_FC + v_U32_t rxTimeStamp; + v_U32_t curTick; + #endif /*------------------------------------------------------------------------ - Extract TL control block + Extract TL control block ------------------------------------------------------------------------*/ pTLCb = VOS_GET_TL_CB(pvosGCtx); if ( NULL == pTLCb ) @@ -5095,27 +5056,30 @@ WLANTL_ProcessFCFrame "WLAN TL:Invalid TL pointer from pvosGCtx on WLANTL_SuspendDataTx")); return VOS_STATUS_E_FAULT; } + ucStaValidBitmap = WDA_GET_RX_FC_VALID_STA_MASK(pvBDHeader); + ucStaTxDisabledBitmap = WDA_GET_RX_FC_STA_TX_DISABLED_BITMAP(pvBDHeader); +#ifdef TL_DEBUG_FC + rxTimeStamp = WDA_GET_RX_TIMESTAMP(pvBDHeader); + /* hard code of MTU_GLOBAL_TIMER_ADDR to calculate the time between generated and processed */ + wpalReadRegister(0x03081400+0x1D4, &curTick); - /* Existing Stations with Tx suspended */ - ucTxSuspended = pTLCb->ucTxSuspended; - - /* Suspend Request Received */ - ucTxSuspendReq = (v_U8_t) WDA_GET_RX_FC_STA_TX_DISABLED_BITMAP(pvBDHeader); TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, - "WLANTL_ProcessFCFrame called for Stations:: Current: %x Requested: %x ", ucTxSuspended, ucTxSuspendReq)); - - ucTxResumeReq = ucTxSuspendReq ^ ( ucTxSuspended | ucTxSuspendReq ); - ucTxSuspendReq = ucTxSuspendReq ^ ( ucTxSuspended & ucTxSuspendReq ); - TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, - "Station Suspend request processed :: Suspend: %x :Resume: %x ", ucTxSuspendReq, ucTxResumeReq)); - - if ( 0 != ucTxSuspendReq ) - { - WLANTL_SuspendDataTx(pvosGCtx, &ucTxSuspendReq, NULL); - } - if ( 0 != ucTxResumeReq ) + "%ld (%ld-%ld): Disabled %x Valid %x\n", curTick > rxTimeStamp ? curTick - rxTimeStamp : rxTimeStamp - (0xFFFFFFFF - curTick), + curTick, rxTimeStamp, ucStaTxDisabledBitmap, ucStaValidBitmap)); +#endif + for(ucSTAId = 0; ucStaValidBitmap != 0; ucStaValidBitmap >>=1, ucStaTxDisabledBitmap >>= 1, ucSTAId ++) { - WLANTL_ResumeDataTx(pvosGCtx, &ucTxResumeReq); + if ( (0 == (ucStaValidBitmap & 0x1)) || (pTLCb->atlSTAClients[ucSTAId] && (0 == pTLCb->atlSTAClients[ucSTAId]->ucExists)) ) + continue; + + if (ucStaTxDisabledBitmap & 0x1) + { + WLANTL_SuspendDataTx(pvosGCtx, &ucSTAId, NULL); + } + else + { + WLANTL_ResumeDataTx(pvosGCtx, &ucSTAId); + } } #else @@ -5512,6 +5476,13 @@ WLANTL_RxFrames } +#ifdef FEATURE_WLAN_TDLS + if (( pClientSTA->ucExists ) && + (WLAN_STA_TDLS == pClientSTA->wSTADesc.wSTAType) && + (pClientSTA->ucTxSuspended)) + vos_atomic_set_U8( &pClientSTA->ucTxSuspended, 0 ); +#endif + #ifdef FEATURE_WLAN_CCX if ((pClientSTA->wSTADesc.ucIsCcxSta)|| broadcast) { @@ -5792,12 +5763,12 @@ WLANTL_RxCachedFrames -------------------------------------------------------------------------*/ if ( !bSigMatch ) { - TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_MED, "WLAN TL: Cached packet does not match DPU Sig of the new STA - drop " " DPU Sig %d UC %d BC %d B %d", uDPUSig, pClientSTA->wSTADesc.ucUcastSig, - pClientSTA->wSTADesc.ucUcastSig, + pClientSTA->wSTADesc.ucBcastSig, broadcast)); /* Drop packet */ @@ -6103,6 +6074,218 @@ WLANTL_ClearTxXmitPending return; }/*WLANTL_ClearTxXmitPending */ +/*========================================================================== + FUNCTION WLANTL_TxThreadDebugHandler + + DESCRIPTION + Printing TL Snapshot dump, processed under TxThread context, currently + information regarding the global TlCb struture. Dumps information related + to per active STA connection currently in use by TL. + + DEPENDENCIES + The TL must be initialized before this gets called. + + PARAMETERS + + IN + pvosGCtx: pointer to the global vos context; a handle to TL's + or WDA's control block can be extracted from its context + + RETURN VALUE None + + SIDE EFFECTS + +============================================================================*/ + +v_VOID_t +WLANTL_TxThreadDebugHandler +( + v_PVOID_t *pVosContext +) +{ + WLANTL_CbType* pTLCb = NULL; + WLANTL_STAClientType* pClientSTA = NULL; + int i = 0; + tWDA_CbContext *pWDA = NULL; + + TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_FATAL, + "WLAN TL: %s Enter ", __func__)); + + pTLCb = VOS_GET_TL_CB(pVosContext); + pWDA = (tWDA_CbContext *)vos_get_global_context(VOS_MODULE_ID_WDA, pVosContext); + + if ( NULL == pVosContext || NULL == pTLCb ) + { + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "Global VoS Context or TL Context are NULL")); + return; + } + + if (NULL != pWDA) + { + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "WDA uTxFlowMask: %d", pWDA->uTxFlowMask)); + } + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "************************TL DUMP INFORMATION**************")); + + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "uDelayedTriggerFrmInt:%d\tuMinFramesProcThres:%d", + pTLCb->tlConfigInfo.uDelayedTriggerFrmInt, + pTLCb->tlConfigInfo.uMinFramesProcThres)); + + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "Management Frame Client exists: %d", + pTLCb->tlMgmtFrmClient.ucExists)); + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "usPendingTxCompleteCount: %d\tucTxSuspended: %d", + pTLCb->usPendingTxCompleteCount, + pTLCb->ucTxSuspended)); + + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "uResCount: %d", pTLCb->uResCount)); + + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "ucRegisteredStaId: %d\tucCurrentSTA: %d", + pTLCb->ucRegisteredStaId, pTLCb->ucCurrentSTA)); + + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "UrgentFrameProcessing: %s\tuFramesProcThres: %d", + (pTLCb->bUrgent?"True":"False"), pTLCb->uFramesProcThres)); + + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "isTxTranmitMsgPending: %d\t isBMPS: %s", + pTLCb->isTxTranmitMsgPending, pTLCb->isBMPS?"True":"False")); + +#ifdef FEATURE_WLAN_TDLS + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "TDLS Peer Count: %d", pTLCb->ucTdlsPeerCount)); +#endif + + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "++++++++++++++++++++Registerd Client Information++++++++++")); + + for ( i =0; iatlSTAClients[i]; + if( NULL == pClientSTA || 0 == pClientSTA->ucExists) + { + continue; + } + + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "######################STA Index: %d ############################",i)); + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, "WLAN_STADescType:")); + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "STAId: %d\t STA MAC Address: %pM", pClientSTA->wSTADesc.ucSTAId, + pClientSTA->wSTADesc.vSTAMACAddress.bytes)); + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "STA Type: %d\tProtectedFrame: %d", + pClientSTA->wSTADesc.wSTAType, pClientSTA->wSTADesc.ucProtectedFrame)); + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "QoS: %d\tRxFrameTrans: %d\tTxFrameTrans: %d", + pClientSTA->wSTADesc.ucQosEnabled, pClientSTA->wSTADesc.ucSwFrameRXXlation, + pClientSTA->wSTADesc.ucSwFrameTXXlation)); + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "ucUcastSig: %d\tucBcastSig: %d", pClientSTA->wSTADesc.ucUcastSig, + pClientSTA->wSTADesc.ucBcastSig)); + + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "ClientIndex: %d\t Exists: %d", i, pClientSTA->ucExists)); + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "TL State: %d\t TL Priority: %d", pClientSTA->tlState, + pClientSTA->tlPri)); + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "ucTxSuspended: %d\tucPktPending: %d", pClientSTA->ucTxSuspended, + pClientSTA->ucPktPending)); + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "ucEAPOLPktPending: %d\tucNoMoreData: %d", + pClientSTA->ucEapolPktPending, pClientSTA->ucNoMoreData)); + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "ucRxBlocked: %d\t fcStaTxDisabled: %d", pClientSTA->ucRxBlocked, + pClientSTA->fcStaTxDisabled)); + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "ucCurrentAC: %d\tucServicedAC: %d", pClientSTA->ucCurrentAC, + pClientSTA->ucServicedAC)); + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "TID: %d\tautTxCount[0]: %d\tauRxCount[0]: %d",0, pClientSTA->auTxCount[0], + pClientSTA->auRxCount[0])); + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "aucAcMask[0]: %d\taucAcMask[1]: %d\taucAcMask[2]: %d\taucAcMask[3]: %d\t", + pClientSTA->aucACMask[0], pClientSTA->aucACMask[1], + pClientSTA->aucACMask[2], pClientSTA->aucACMask[3])); + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "ucCurrentWeight: %d", pClientSTA->ucCurrentWeight)); + + if( WLAN_STA_SOFTAP == pClientSTA->wSTADesc.wSTAType) + { + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "TrafficStatistics for SOFTAP Station:")); + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "RUF=%d\tRMF=%d\tRBF=%d", pClientSTA->trafficStatistics.rxUCFcnt, + pClientSTA->trafficStatistics.rxMCFcnt, + pClientSTA->trafficStatistics.rxBCFcnt)); + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "RUB=%d\tRMB=%d\tRBB=%d", pClientSTA->trafficStatistics.rxUCBcnt, + pClientSTA->trafficStatistics.rxMCBcnt, + pClientSTA->trafficStatistics.rxBCBcnt)); + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "TUF=%d\tTMF=%d\tTBF=%d", pClientSTA->trafficStatistics.txUCFcnt, + pClientSTA->trafficStatistics.txMCFcnt, + pClientSTA->trafficStatistics.txBCFcnt)); + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "TUB=%d\tTMB=%d\tTBB=%d", pClientSTA->trafficStatistics.txUCBcnt, + pClientSTA->trafficStatistics.txMCBcnt, + pClientSTA->trafficStatistics.txBCBcnt)); + } + } + return; +} + +/*========================================================================== + FUNCTION WLANTL_TLDebugMessage + + DESCRIPTION + Post a TL Snapshot request, posts message in TxThread. + + DEPENDENCIES + The TL must be initialized before this gets called. + + PARAMETERS + + IN + displaySnapshot Boolean showing whether to dump the snapshot or not. + + RETURN VALUE None + + SIDE EFFECTS + +============================================================================*/ + +v_VOID_t +WLANTL_TLDebugMessage +( + v_BOOL_t displaySnapshot +) +{ + vos_msg_t vosMsg; + VOS_STATUS status; + + if(displaySnapshot) + { + vosMsg.reserved = 0; + vosMsg.bodyptr = NULL; + vosMsg.type = WLANTL_TX_SNAPSHOT; + + status = vos_tx_mq_serialize( VOS_MODULE_ID_TL, &vosMsg); + if(status != VOS_STATUS_SUCCESS) + { + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, "TX Msg Posting Failed with status: %d",status)); + return; + } + } + return; +} /*============================================================================ TL STATE MACHINE @@ -6544,7 +6727,7 @@ WLANTL_STATxAuth if (( NULL == pTLCb ) || ( NULL == pvosDataBuff )) { TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, - "WLAN TL:Invalid input params on WLANTL_STATxAuth TL %x DB %x", + "WLAN TL:Invalid input params on WLANTL_STATxAuth TL %x DB %p", pTLCb, pvosDataBuff)); if (NULL != pvosDataBuff) { @@ -7407,7 +7590,7 @@ WLANTL_STARxAuth v_U16_t usActualHLen = 0; v_U8_t ucTid; #ifdef FEATURE_WLAN_WAPI - v_U16_t usEtherType; + v_U16_t usEtherType = 0; #endif v_U16_t usPktLen; vos_pkt_t* vosDataBuff ; @@ -7756,6 +7939,16 @@ if(0 == ucUnicastBroadcastType { wRxMetaInfo.ucUP = ucTid; wRxMetaInfo.rssiAvg = pClientSTA->rssiAvg; +#ifdef FEATURE_WLAN_TDLS + if (WLAN_STA_TDLS == pClientSTA->wSTADesc.wSTAType) + { + wRxMetaInfo.isStaTdls = TRUE; + } + else + { + wRxMetaInfo.isStaTdls = FALSE; + } +#endif pClientSTA->pfnSTARx( pvosGCtx, vosDataBuff, ucSTAId, &wRxMetaInfo ); } @@ -8190,10 +8383,8 @@ WLANTL_TxProcessMsg break; case WDA_DS_TX_START_XMIT: - - WLANTL_ClearTxXmitPending(pvosGCtx); - vosStatus = WDA_DS_TxFrames( pvosGCtx ); - + WLANTL_ClearTxXmitPending(pvosGCtx); + vosStatus = WDA_DS_TxFrames( pvosGCtx ); break; case WDA_DS_FINISH_ULA: @@ -8202,6 +8393,13 @@ WLANTL_TxProcessMsg callbackRoutine(callbackContext); break; + case WLANTL_TX_SNAPSHOT: + /*Dumping TL State and then continuing to print + the DXE Dump*/ + WLANTL_TxThreadDebugHandler(pvosGCtx); + WDA_TransportChannelDebug(NULL, VOS_TRUE, VOS_FALSE); + break; + default: /*no processing for now*/ break; @@ -8618,6 +8816,8 @@ WLANTL_Translate8023To80211Header for ( ucIndex = 0; ucIndex < WLAN_MAX_STA_COUNT ; ucIndex++) { if ( ucIndex != ucStaId && pTLCb->atlSTAClients[ucIndex] && pTLCb->atlSTAClients[ucIndex]->ucExists && + (pTLCb->atlSTAClients[ucIndex]->tlState == WLANTL_STA_AUTHENTICATED) && + (!pTLCb->atlSTAClients[ucIndex]->ucTxSuspended) && vos_mem_compare( (void*)pTLCb->atlSTAClients[ucIndex]->wSTADesc.vSTAMACAddress.bytes, (void*)w8023Header.vDA, 6) ) { @@ -10267,7 +10467,7 @@ WLANTL_CleanSTA ( NULL != ptlSTAClient->vosAMSDUChainRoot )) { TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_FATAL, - "WLAN TL:Non NULL vosAMSDUChainRoot (=%x) on WLANTL_CleanSTA," + "WLAN TL:Non NULL vosAMSDUChainRoot (=%p) on WLANTL_CleanSTA," "suspecting a memory corruption")); } @@ -10404,7 +10604,7 @@ WLANTL_EnableUAPSDForAC { TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, "WLAN TL:Invalid input params on WLANTL_EnableUAPSDForAC" - " TL: %x STA: %d AC: %d SI: %d", + " TL: %p STA: %d AC: %d SI: %d", pTLCb, ucSTAId, ucAC, uServiceInt )); return VOS_STATUS_E_FAULT; } @@ -10491,7 +10691,7 @@ WLANTL_DisableUAPSDForAC { TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, "WLAN TL:Invalid input params on WLANTL_DisableUAPSDForAC" - " TL: %x STA: %d AC: %d", pTLCb, ucSTAId, ucAC )); + " TL: %p STA: %d AC: %d", pTLCb, ucSTAId, ucAC )); return VOS_STATUS_E_FAULT; } @@ -11259,7 +11459,7 @@ void WLANTL_PowerStateChangedCB if (NULL == tlCtxt) { VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, - "Invalid TL Control Block", __func__ ); + "%s: Invalid TL Control Block", __func__ ); return; } @@ -11675,3 +11875,131 @@ void WLANTL_UpdateRssiBmps(v_PVOID_t pvosGCtx, v_U8_t staId, v_S7_t rssi) pTLCb->atlSTAClients[staId]->rssiAvgBmps = rssi; } } + +/*=============================================================================== + FUNCTION WLANTL_UpdateLinkCapacity + + DESCRIPTION This function updates the STA's Link Capacity in TL + + DEPENDENCIES None + + PARAMETERS + + pvosGCtx VOS context VOS Global context + staId Station ID Station ID + linkCapacity linkCapacity Link Capacity + + RETURN None + + SIDE EFFECTS none + ===============================================================================*/ + +void WLANTL_UpdateLinkCapacity(v_PVOID_t pvosGCtx, v_U8_t staId, v_U32_t linkCapacity) +{ + WLANTL_CbType* pTLCb = VOS_GET_TL_CB(pvosGCtx); + + if (NULL != pTLCb && NULL != pTLCb->atlSTAClients[staId]) + { + pTLCb->atlSTAClients[staId]->linkCapacity = linkCapacity; + } +} + + +/*=========================================================================== + + FUNCTION WLANTL_GetSTALinkCapacity + + DESCRIPTION + + Returns Link Capacity of a particular STA. + + DEPENDENCIES + + A station must have been registered before its state can be retrieved. + + + PARAMETERS + + IN + pvosGCtx: pointer to the global vos context; a handle to TL's + control block can be extracted from its context + ucSTAId: identifier of the station + + OUT + plinkCapacity: the current link capacity the connection to + the given station + + + RETURN VALUE + + The result code associated with performing the operation + + VOS_STATUS_E_INVAL: Input parameters are invalid + VOS_STATUS_E_FAULT: Station ID is outside array boundaries or pointer to + TL cb is NULL ; access would cause a page fault + VOS_STATUS_E_EXISTS: Station was not registered + VOS_STATUS_SUCCESS: Everything is good :) + + SIDE EFFECTS + +============================================================================*/ +VOS_STATUS +WLANTL_GetSTALinkCapacity +( + v_PVOID_t pvosGCtx, + v_U8_t ucSTAId, + v_U32_t *plinkCapacity +) +{ + WLANTL_CbType* pTLCb = NULL; + /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ + + /*------------------------------------------------------------------------ + Sanity check + ------------------------------------------------------------------------*/ + if ( NULL == plinkCapacity ) + { + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + FL("WLAN TL:Invalid parameter"))); + return VOS_STATUS_E_INVAL; + } + + if ( WLANTL_STA_ID_INVALID( ucSTAId ) ) + { + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + FL("WLAN TL:Invalid station id"))); + return VOS_STATUS_E_FAULT; + } + + /*------------------------------------------------------------------------ + Extract TL control block and check existance + ------------------------------------------------------------------------*/ + pTLCb = VOS_GET_TL_CB(pvosGCtx); + if ( NULL == pTLCb ) + { + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + FL("WLAN TL:Invalid TL pointer from pvosGCtx"))); + return VOS_STATUS_E_FAULT; + } + + if ( NULL == pTLCb->atlSTAClients[ucSTAId] ) + { + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + FL("WLAN TL:Client Memory was not allocated"))); + return VOS_STATUS_E_FAILURE; + } + + if ( 0 == pTLCb->atlSTAClients[ucSTAId]->ucExists ) + { + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_WARN, + FL("WLAN TL:Station was not previously registered"))); + return VOS_STATUS_E_EXISTS; + } + + /*------------------------------------------------------------------------ + Get STA state + ------------------------------------------------------------------------*/ + *plinkCapacity = pTLCb->atlSTAClients[ucSTAId]->linkCapacity; + + return VOS_STATUS_SUCCESS; +}/* WLANTL_GetSTALinkCapacity */ diff --git a/drivers/staging/prima/CORE/TL/src/wlan_qct_tl_ba.c b/drivers/staging/prima/CORE/TL/src/wlan_qct_tl_ba.c index 7fa9d2f9720..25579713242 100644 --- a/drivers/staging/prima/CORE/TL/src/wlan_qct_tl_ba.c +++ b/drivers/staging/prima/CORE/TL/src/wlan_qct_tl_ba.c @@ -749,7 +749,7 @@ WLANTL_BaSessionDel vosStatus = vos_timer_stop(&reOrderInfo->agingTimer); if(!VOS_IS_STATUS_SUCCESS(vosStatus)) { - TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"Timer stop fail", vosStatus)); + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"Timer stop fail: %d", vosStatus)); return vosStatus; } } @@ -1485,10 +1485,10 @@ VOS_STATUS WLANTL_MSDUReorder * Route all the Qed frames upper layer * Otherwise, RX thread could be stall */ vos_pkt_get_available_buffer_pool(VOS_PKT_TYPE_RX_RAW, &rxFree); - if(WLANTL_BA_MIN_FREE_RX_VOS_BUFFER > rxFree) + if(WLANTL_BA_MIN_FREE_RX_VOS_BUFFER >= rxFree) { - TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"RX Free", rxFree)); - TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"RX free buffer count is too low, Pending frame count is %d", + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO, "RX Free: %d", rxFree)); + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO, "RX free buffer count is too low, Pending frame count is %d", currentReorderInfo->pendingFramesCount)); vosPktIdx = NULL; status = WLANTL_ChainFrontPkts(ucFwdIdx, @@ -1554,7 +1554,7 @@ VOS_STATUS WLANTL_MSDUReorder WLANTL_BA_REORDERING_AGING_TIMER); if(!VOS_IS_STATUS_SUCCESS(timerStatus)) { - TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"Timer start fail", timerStatus)); + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"Timer start fail: %d", timerStatus)); lockStatus = vos_lock_release(¤tReorderInfo->reorderLock); if(!VOS_IS_STATUS_SUCCESS(lockStatus)) { diff --git a/drivers/staging/prima/CORE/TL/src/wlan_qct_tl_hosupport.c b/drivers/staging/prima/CORE/TL/src/wlan_qct_tl_hosupport.c index d6be98ab41c..22baa2dc327 100644 --- a/drivers/staging/prima/CORE/TL/src/wlan_qct_tl_hosupport.c +++ b/drivers/staging/prima/CORE/TL/src/wlan_qct_tl_hosupport.c @@ -941,6 +941,8 @@ VOS_STATUS WLANTL_HSBMPSRSSIRegionChangedNotification return VOS_STATUS_E_INVAL; } + THSGETLOCK("WLANTL_HSBMPSRSSIRegionChangedNotification", + &tlCtxt->hoSupport.hosLock); currentHO = &(tlCtxt->hoSupport.currentHOState); hoSupport = &(tlCtxt->hoSupport); preFWNotification = currentHO->fwNotification; @@ -968,6 +970,8 @@ VOS_STATUS WLANTL_HSBMPSRSSIRegionChangedNotification } else if(preFWNotification == curFWNotification) { + THSRELEASELOCK("WLANTL_HSBMPSRSSIRegionChangedNotification", + &tlCtxt->hoSupport.hosLock); return status; } @@ -1003,12 +1007,13 @@ VOS_STATUS WLANTL_HSBMPSRSSIRegionChangedNotification nRegionNumber = 1; } - newRegionNumber = (nRegionNumber > pRegionNumber) ? nRegionNumber : pRegionNumber; if((currentHO->regionNumber) && (newRegionNumber == currentHO->regionNumber)) { TLLOG1(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,"No Region Change with BMPS mode")); preFWNotification = curFWNotification; + THSRELEASELOCK("WLANTL_HSBMPSRSSIRegionChangedNotification", + &tlCtxt->hoSupport.hosLock); return status; } else if(newRegionNumber > currentHO->regionNumber) @@ -1066,6 +1071,8 @@ VOS_STATUS WLANTL_HSBMPSRSSIRegionChangedNotification TLLOG1(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,"BMPS State, MSG from FW, Trigger Event %d, region index %d", evtType, currentHO->regionNumber)); + THSRELEASELOCK("WLANTL_HSBMPSRSSIRegionChangedNotification", + &tlCtxt->hoSupport.hosLock); return VOS_STATUS_SUCCESS; } @@ -1229,6 +1236,7 @@ VOS_STATUS WLANTL_HSHandleRXFrame return VOS_STATUS_E_INVAL; } + THSGETLOCK("WLANTL_HSHandleRXFrame", &tlCtxt->hoSupport.hosLock); WLANTL_StatHandleRXFrame(pAdapter, pBDHeader, STAid, isBroadcast, dataBuffer); /* If this frame is not management frame increase frame count */ @@ -1258,12 +1266,14 @@ VOS_STATUS WLANTL_HSHandleRXFrame { WLANTL_HSGetRSSI(pAdapter, pBDHeader, STAid, ¤tAvgRSSI); currentHO->historyRSSI = currentAvgRSSI; + THSRELEASELOCK("WLANTL_HSHandleRXFrame", &tlCtxt->hoSupport.hosLock); return status; } currentTimestamp = WDA_GET_RX_TIMESTAMP(pBDHeader); if((currentTimestamp - currentHO->sampleTime) < WLANTL_HO_SAMPLING_PERIOD) { + THSRELEASELOCK("WLANTL_HSHandleRXFrame", &tlCtxt->hoSupport.hosLock); return status; } currentHO->sampleTime = currentTimestamp; @@ -1273,6 +1283,7 @@ VOS_STATUS WLANTL_HSHandleRXFrame if(!VOS_IS_STATUS_SUCCESS(status)) { TLLOG1(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,"Get RSSI Fail")); + THSRELEASELOCK("WLANTL_HSHandleRXFrame", &tlCtxt->hoSupport.hosLock); return status; } #ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE @@ -1291,11 +1302,14 @@ VOS_STATUS WLANTL_HSHandleRXFrame if(!VOS_IS_STATUS_SUCCESS(status)) { TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"Handle new RSSI fail")); + THSRELEASELOCK("WLANTL_HSHandleRXFrame", + &tlCtxt->hoSupport.hosLock); return status; } } } + THSRELEASELOCK("WLANTL_HSHandleRXFrame", &tlCtxt->hoSupport.hosLock); return status; } @@ -1425,12 +1439,12 @@ VOS_STATUS WLANTL_HSRegRSSIIndicationCB { for(sIdx = 0; sIdx < WLANTL_HS_NUM_CLIENT; sIdx++) { - TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,"Reg CB P 0x%x, registered CB P 0x%x", + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,"Reg CB P %p, registered CB P %p", crossCBFunction, hoSupport->registeredInd[idx].crossCBFunction[sIdx])); if(crossCBFunction == hoSupport->registeredInd[idx].crossCBFunction[sIdx]) { - TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,"Same RSSI %d, Same CB 0x%x already registered", + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,"Same RSSI %d, Same CB %p already registered", rssiValue, crossCBFunction)); WLANTL_HSDebugDisplay(pAdapter); THSRELEASELOCK("WLANTL_HSRegRSSIIndicationCB", &tlCtxt->hoSupport.hosLock); @@ -1693,23 +1707,26 @@ VOS_STATUS WLANTL_HSDeregRSSIIndicationCB tlCtxt->hoSupport.registeredInd[currentHO->numThreshold - 1].numClient = 0; } - if((VOS_FALSE == tlCtxt->isBMPS) && (rssiValue >= currentHO->historyRSSI)) + if( ((VOS_FALSE == tlCtxt->isBMPS) && (rssiValue >= currentHO->historyRSSI)) + || ((VOS_TRUE == tlCtxt->isBMPS) && (VOS_TRUE == bmpsAbove)) ) { - TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,"Removed Threshold above current RSSI level, old RN %d", currentHO->regionNumber)); + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO, + "Removed Threshold above current RSSI level, old RN %d", + currentHO->regionNumber)); if(0 < currentHO->regionNumber) { currentHO->regionNumber--; } else { - TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"Current Region number is 0, cannot decrease anymore")); + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "Current Region number is 0, cannot decrease anymore")); } - TLLOG1(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,"Decrease region number without notification %d", currentHO->regionNumber)); - } - else if((VOS_TRUE == tlCtxt->isBMPS) && (VOS_TRUE == bmpsAbove)) - { - currentHO->regionNumber--; + TLLOG1(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO, + "Decrease region number without notification %d", + currentHO->regionNumber)); } + /* Decrease number of thresholds */ tlCtxt->hoSupport.currentHOState.numThreshold--; /*Reset the FW notification*/ diff --git a/drivers/staging/prima/CORE/TL/src/wlan_qct_tli.h b/drivers/staging/prima/CORE/TL/src/wlan_qct_tli.h index a8fa010d1dc..2c7d9eaf59d 100644 --- a/drivers/staging/prima/CORE/TL/src/wlan_qct_tli.h +++ b/drivers/staging/prima/CORE/TL/src/wlan_qct_tli.h @@ -39,6 +39,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ + #ifndef WLAN_QCT_TLI_H #define WLAN_QCT_TLI_H @@ -52,8 +53,6 @@ DESCRIPTION This file contains the internal declarations used within wlan transport layer module. - Copyright (c) 2008 QUALCOMM Incorporated. All Rights Reserved. - Qualcomm Confidential and Proprietary ===========================================================================*/ @@ -111,7 +110,6 @@ when who what, where, why #define STATIC static - /*---------------------------------------------------------------------------- * Preprocessor Definitions and Constants * -------------------------------------------------------------------------*/ @@ -278,6 +276,9 @@ typedef enum /* Serialzie Finish UL Authentication request */ WLANTL_FINISH_ULA = 5, + /* Serialized Snapshot request indication */ + WLANTL_TX_SNAPSHOT = 6, + WLANTL_TX_MAX }WLANTL_TxSignalsType; @@ -636,6 +637,8 @@ typedef struct 1 then we have to encrypt the data irrespective of TL state (CONNECTED/AUTHENTICATED) */ v_U8_t ptkInstalled; + + v_U32_t linkCapacity; }WLANTL_STAClientType; /*--------------------------------------------------------------------------- diff --git a/drivers/staging/prima/CORE/VOSS/inc/i_vos_packet.h b/drivers/staging/prima/CORE/VOSS/inc/i_vos_packet.h index 105c4e7b8bb..58ef385f129 100644 --- a/drivers/staging/prima/CORE/VOSS/inc/i_vos_packet.h +++ b/drivers/staging/prima/CORE/VOSS/inc/i_vos_packet.h @@ -198,6 +198,10 @@ typedef struct vos_pkt_context_s //Add the field for a faster rx path v_SIZE_t rxRawFreeListCount; + // Number of RX Raw packets that will be reserved; this is a configurable + // value to the driver to save the memory usage. + v_SIZE_t numOfRxRawPackets; + // These are the structs to keep low-resource callback information. // There are separate low-resource callback information blocks for // RX_RAW, TX_DATA, and TX_MGMT. diff --git a/drivers/staging/prima/CORE/VOSS/inc/vos_packet.h b/drivers/staging/prima/CORE/VOSS/inc/vos_packet.h index 89acfdd6e2c..c57912cc9bb 100644 --- a/drivers/staging/prima/CORE/VOSS/inc/vos_packet.h +++ b/drivers/staging/prima/CORE/VOSS/inc/vos_packet.h @@ -1115,4 +1115,20 @@ VOS_STATUS vos_pkt_get_available_buffer_pool v_SIZE_t *vosFreeBuffer ); +/** + @brief vos_pkt_get_num_of_rx_raw_pkts() - Get the number of RX packets + that should be allocated. + + This function is called by VOS packet module to know how many RX raw + packets it should allocate/reserve. This value can be configured thru + Kernel device tree to save memory usage. + + @param + NONE + @return + v_SIZE_t the number of packets to allocate + +*/ +v_SIZE_t vos_pkt_get_num_of_rx_raw_pkts(void); + #endif // !defined( __VOS_PKT_H ) diff --git a/drivers/staging/prima/CORE/VOSS/inc/vos_trace.h b/drivers/staging/prima/CORE/VOSS/inc/vos_trace.h index f65502fe820..5703b5dd1b8 100644 --- a/drivers/staging/prima/CORE/VOSS/inc/vos_trace.h +++ b/drivers/staging/prima/CORE/VOSS/inc/vos_trace.h @@ -39,6 +39,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ + #if !defined( __VOS_TRACE_H ) #define __VOS_TRACE_H @@ -50,10 +51,6 @@ Trace, logging, and debugging definitions and APIs - Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved. - - Qualcomm Confidential and Proprietary. - ========================================================================*/ /* $Header$ */ @@ -105,6 +102,7 @@ typedef enum // below definition is obsolete and is no longer being used in BMP and WM // TODO: remove this once this is not used on Android #define VOS_ENABLE_TRACING +#define WCONN_TRACE_KMSG_LOG_BUFF #include @@ -153,4 +151,22 @@ void vos_trace_setLevel( VOS_MODULE_ID module, VOS_TRACE_LEVEL level ); --------------------------------------------------------------------------*/ v_BOOL_t vos_trace_getLevel( VOS_MODULE_ID module, VOS_TRACE_LEVEL level ); +#ifdef WCONN_TRACE_KMSG_LOG_BUFF +/*-------------------------------------------------------------------------- + \brief vos_wconn_trace_init(); - Initializing the spinlock, + Initialization would be called at the time of hdd_driver_init() + + \return - returns None + --------------------------------------------------------------------------*/ +void vos_wconn_trace_init(void); + +/*-------------------------------------------------------------------------- + \brief vos_wconn_trace_exit(); - De-Initializing the spinlock, + De-Initialization would be called at the time of hdd_driver_exit() + + \return - returns None + --------------------------------------------------------------------------*/ +void vos_wconn_trace_exit(void); +#endif + #endif diff --git a/drivers/staging/prima/CORE/VOSS/inc/vos_types.h b/drivers/staging/prima/CORE/VOSS/inc/vos_types.h index 58669cf98db..c2d5bb80b4c 100644 --- a/drivers/staging/prima/CORE/VOSS/inc/vos_types.h +++ b/drivers/staging/prima/CORE/VOSS/inc/vos_types.h @@ -168,6 +168,7 @@ typedef enum VOS_P2P_GO_MODE, VOS_MONITOR_MODE, VOS_FTM_MODE = 5, + VOS_P2P_DEVICE, VOS_MAX_NO_OF_MODE } tVOS_CON_MODE; diff --git a/drivers/staging/prima/CORE/VOSS/src/vos_api.c b/drivers/staging/prima/CORE/VOSS/src/vos_api.c index 1106c4a0773..354dded7457 100644 --- a/drivers/staging/prima/CORE/VOSS/src/vos_api.c +++ b/drivers/staging/prima/CORE/VOSS/src/vos_api.c @@ -1599,7 +1599,7 @@ VOS_STATUS vos_tx_mq_serialize( VOS_MQ_ID msgQueueId, vos_msg_t *pMsg ) default: VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, - "Trying to queue msg into unknown Tx Msg queue ID %d", + "%s: Trying to queue msg into unknown Tx Msg queue ID %d", __func__, msgQueueId); return VOS_STATUS_E_FAILURE; @@ -1709,7 +1709,7 @@ VOS_STATUS vos_rx_mq_serialize( VOS_MQ_ID msgQueueId, vos_msg_t *pMsg ) default: VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, - "Trying to queue msg into unknown Rx Msg queue ID %d", + "%s: Trying to queue msg into unknown Rx Msg queue ID %d", __func__, msgQueueId); return VOS_STATUS_E_FAILURE; diff --git a/drivers/staging/prima/CORE/VOSS/src/vos_nvitem.c b/drivers/staging/prima/CORE/VOSS/src/vos_nvitem.c index b192216c2fb..d002d714bfe 100644 --- a/drivers/staging/prima/CORE/VOSS/src/vos_nvitem.c +++ b/drivers/staging/prima/CORE/VOSS/src/vos_nvitem.c @@ -119,7 +119,7 @@ static CountryInfoTable_t countryInfoTable = { REGDOMAIN_N_AMER_EXC_FCC, {'A', 'F'}}, //AFGHANISTAN { REGDOMAIN_WORLD, {'A', 'G'}}, //ANTIGUA AND BARBUDA { REGDOMAIN_FCC, {'A', 'I'}}, //ANGUILLA - { REGDOMAIN_NO_5GHZ, {'A', 'L'}}, //ALBANIA + { REGDOMAIN_ETSI, {'A', 'L'}}, //ALBANIA { REGDOMAIN_N_AMER_EXC_FCC, {'A', 'M'}}, //ARMENIA { REGDOMAIN_ETSI, {'A', 'N'}}, //NETHERLANDS ANTILLES { REGDOMAIN_NO_5GHZ, {'A', 'O'}}, //ANGOLA @@ -127,13 +127,13 @@ static CountryInfoTable_t countryInfoTable = { REGDOMAIN_WORLD, {'A', 'R'}}, //ARGENTINA { REGDOMAIN_FCC, {'A', 'S'}}, //AMERICAN SOMOA { REGDOMAIN_ETSI, {'A', 'T'}}, //AUSTRIA - { REGDOMAIN_APAC, {'A', 'U'}}, //AUSTRALIA + { REGDOMAIN_WORLD, {'A', 'U'}}, //AUSTRALIA { REGDOMAIN_ETSI, {'A', 'W'}}, //ARUBA { REGDOMAIN_WORLD, {'A', 'X'}}, //ALAND ISLANDS { REGDOMAIN_N_AMER_EXC_FCC, {'A', 'Z'}}, //AZERBAIJAN { REGDOMAIN_ETSI, {'B', 'A'}}, //BOSNIA AND HERZEGOVINA { REGDOMAIN_APAC, {'B', 'B'}}, //BARBADOS - { REGDOMAIN_NO_5GHZ, {'B', 'D'}}, //BANGLADESH + { REGDOMAIN_HI_5GHZ, {'B', 'D'}}, //BANGLADESH { REGDOMAIN_ETSI, {'B', 'E'}}, //BELGIUM { REGDOMAIN_HI_5GHZ, {'B', 'F'}}, //BURKINA FASO { REGDOMAIN_ETSI, {'B', 'G'}}, //BULGARIA @@ -160,7 +160,7 @@ static CountryInfoTable_t countryInfoTable = { REGDOMAIN_WORLD, {'C', 'K'}}, //COOK ISLANDS { REGDOMAIN_APAC, {'C', 'L'}}, //CHILE { REGDOMAIN_NO_5GHZ, {'C', 'M'}}, //CAMEROON - { REGDOMAIN_HI_5GHZ, {'C', 'N'}}, //CHINA + { REGDOMAIN_APAC, {'C', 'N'}}, //CHINA { REGDOMAIN_APAC, {'C', 'O'}}, //COLOMBIA { REGDOMAIN_APAC, {'C', 'R'}}, //COSTA RICA { REGDOMAIN_NO_5GHZ, {'C', 'U'}}, //CUBA @@ -173,7 +173,7 @@ static CountryInfoTable_t countryInfoTable = { REGDOMAIN_ETSI, {'D', 'K'}}, //DENMARK { REGDOMAIN_WORLD, {'D', 'M'}}, //DOMINICA { REGDOMAIN_APAC, {'D', 'O'}}, //DOMINICAN REPUBLIC - { REGDOMAIN_NO_5GHZ, {'D', 'Z'}}, //ALGERIA + { REGDOMAIN_ETSI, {'D', 'Z'}}, //ALGERIA { REGDOMAIN_APAC, {'E', 'C'}}, //ECUADOR { REGDOMAIN_ETSI, {'E', 'E'}}, //ESTONIA { REGDOMAIN_N_AMER_EXC_FCC, {'E', 'G'}}, //EGYPT @@ -204,7 +204,7 @@ static CountryInfoTable_t countryInfoTable = { REGDOMAIN_ETSI, {'G', 'R'}}, //GREECE { REGDOMAIN_WORLD, {'G', 'S'}}, //SOUTH GEORGIA AND THE SOUTH SANDWICH ISLANDS { REGDOMAIN_APAC, {'G', 'T'}}, //GUATEMALA - { REGDOMAIN_APAC, {'G', 'U'}}, //GUAM + { REGDOMAIN_FCC, {'G', 'U'}}, //GUAM { REGDOMAIN_NO_5GHZ, {'G', 'W'}}, //GUINEA-BISSAU { REGDOMAIN_HI_5GHZ, {'G', 'Y'}}, //GUYANA { REGDOMAIN_WORLD, {'H', 'K'}}, //HONGKONG @@ -215,7 +215,7 @@ static CountryInfoTable_t countryInfoTable = { REGDOMAIN_ETSI, {'H', 'U'}}, //HUNGARY { REGDOMAIN_HI_5GHZ, {'I', 'D'}}, //INDONESIA { REGDOMAIN_ETSI, {'I', 'E'}}, //IRELAND - { REGDOMAIN_NO_5GHZ, {'I', 'L'}}, //ISRAEL + { REGDOMAIN_N_AMER_EXC_FCC, {'I', 'L'}}, //ISRAEL { REGDOMAIN_WORLD, {'I', 'M'}}, //ISLE OF MAN { REGDOMAIN_APAC, {'I', 'N'}}, //INDIA { REGDOMAIN_WORLD, {'I', 'O'}}, //BRITISH INDIAN OCEAN TERRITORY @@ -230,13 +230,13 @@ static CountryInfoTable_t countryInfoTable = { REGDOMAIN_WORLD, {'J', '5'}}, //Japan alternate 5 { REGDOMAIN_WORLD, {'J', 'E'}}, //JERSEY { REGDOMAIN_WORLD, {'J', 'M'}}, //JAMAICA - { REGDOMAIN_WORLD, {'J', 'O'}}, //JORDAN + { REGDOMAIN_APAC, {'J', 'O'}}, //JORDAN { REGDOMAIN_WORLD, {'J', 'P'}}, //JAPAN { REGDOMAIN_KOREA, {'K', '1'}}, //Korea alternate 1 { REGDOMAIN_KOREA, {'K', '2'}}, //Korea alternate 2 { REGDOMAIN_KOREA, {'K', '3'}}, //Korea alternate 3 { REGDOMAIN_KOREA, {'K', '4'}}, //Korea alternate 4 - { REGDOMAIN_HI_5GHZ, {'K', 'E'}}, //KENYA + { REGDOMAIN_APAC, {'K', 'E'}}, //KENYA { REGDOMAIN_NO_5GHZ, {'K', 'G'}}, //KYRGYZSTAN { REGDOMAIN_ETSI, {'K', 'H'}}, //CAMBODIA { REGDOMAIN_WORLD, {'K', 'I'}}, //KIRIBATI @@ -246,9 +246,9 @@ static CountryInfoTable_t countryInfoTable = { REGDOMAIN_KOREA, {'K', 'R'}}, //KOREA, REPUBLIC OF { REGDOMAIN_N_AMER_EXC_FCC, {'K', 'W'}}, //KUWAIT { REGDOMAIN_FCC, {'K', 'Y'}}, //CAYMAN ISLANDS - { REGDOMAIN_NO_5GHZ, {'K', 'Z'}}, //KAZAKHSTAN + { REGDOMAIN_WORLD, {'K', 'Z'}}, //KAZAKHSTAN { REGDOMAIN_WORLD, {'L', 'A'}}, //LAO PEOPLE'S DEMOCRATIC REPUBLIC - { REGDOMAIN_HI_5GHZ, {'L', 'B'}}, //LEBANON + { REGDOMAIN_WORLD, {'L', 'B'}}, //LEBANON { REGDOMAIN_WORLD, {'L', 'C'}}, //SAINT LUCIA { REGDOMAIN_ETSI, {'L', 'I'}}, //LIECHTENSTEIN { REGDOMAIN_WORLD, {'L', 'K'}}, //SRI LANKA @@ -258,8 +258,8 @@ static CountryInfoTable_t countryInfoTable = { REGDOMAIN_ETSI, {'L', 'U'}}, //LUXEMBOURG { REGDOMAIN_ETSI, {'L', 'V'}}, //LATVIA { REGDOMAIN_NO_5GHZ, {'L', 'Y'}}, //LIBYAN ARAB JAMAHIRIYA - { REGDOMAIN_NO_5GHZ, {'M', 'A'}}, //MOROCCO - { REGDOMAIN_N_AMER_EXC_FCC, {'M', 'C'}}, //MONACO + { REGDOMAIN_APAC, {'M', 'A'}}, //MOROCCO + { REGDOMAIN_ETSI, {'M', 'C'}}, //MONACO { REGDOMAIN_ETSI, {'M', 'D'}}, //MOLDOVA, REPUBLIC OF { REGDOMAIN_ETSI, {'M', 'E'}}, //MONTENEGRO { REGDOMAIN_NO_5GHZ, {'M', 'G'}}, //MADAGASCAR @@ -267,7 +267,7 @@ static CountryInfoTable_t countryInfoTable = { REGDOMAIN_ETSI, {'M', 'K'}}, //MACEDONIA, THE FORMER YUGOSLAV REPUBLIC OF { REGDOMAIN_NO_5GHZ, {'M', 'L'}}, //MALI { REGDOMAIN_WORLD, {'M', 'M'}}, //MYANMAR - { REGDOMAIN_NO_5GHZ, {'M', 'N'}}, //MONGOLIA + { REGDOMAIN_WORLD, {'M', 'N'}}, //MONGOLIA { REGDOMAIN_APAC, {'M', 'O'}}, //MACAO { REGDOMAIN_FCC, {'M', 'P'}}, //NORTHERN MARIANA ISLANDS { REGDOMAIN_ETSI, {'M', 'Q'}}, //MARTINIQUE @@ -288,16 +288,16 @@ static CountryInfoTable_t countryInfoTable = { REGDOMAIN_WORLD, {'N', 'I'}}, //NICARAGUA { REGDOMAIN_ETSI, {'N', 'L'}}, //NETHERLANDS { REGDOMAIN_ETSI, {'N', 'O'}}, //NORWAY - { REGDOMAIN_HI_5GHZ, {'N', 'P'}}, //NEPAL + { REGDOMAIN_APAC, {'N', 'P'}}, //NEPAL { REGDOMAIN_NO_5GHZ, {'N', 'R'}}, //NAURU { REGDOMAIN_WORLD, {'N', 'U'}}, //NIUE { REGDOMAIN_APAC, {'N', 'Z'}}, //NEW ZEALAND - { REGDOMAIN_WORLD, {'O', 'M'}}, //OMAN + { REGDOMAIN_ETSI, {'O', 'M'}}, //OMAN { REGDOMAIN_APAC, {'P', 'A'}}, //PANAMA - { REGDOMAIN_HI_5GHZ, {'P', 'E'}}, //PERU + { REGDOMAIN_WORLD, {'P', 'E'}}, //PERU { REGDOMAIN_ETSI, {'P', 'F'}}, //FRENCH POLYNESIA - { REGDOMAIN_APAC, {'P', 'G'}}, //PAPUA NEW GUINEA - { REGDOMAIN_HI_5GHZ, {'P', 'H'}}, //PHILIPPINES + { REGDOMAIN_WORLD, {'P', 'G'}}, //PAPUA NEW GUINEA + { REGDOMAIN_WORLD, {'P', 'H'}}, //PHILIPPINES { REGDOMAIN_HI_5GHZ, {'P', 'K'}}, //PAKISTAN { REGDOMAIN_ETSI, {'P', 'L'}}, //POLAND { REGDOMAIN_WORLD, {'P', 'M'}}, //SAINT PIERRE AND MIQUELON @@ -311,9 +311,9 @@ static CountryInfoTable_t countryInfoTable = { REGDOMAIN_ETSI, {'R', 'E'}}, //REUNION { REGDOMAIN_ETSI, {'R', 'O'}}, //ROMANIA { REGDOMAIN_ETSI, {'R', 'S'}}, //SERBIA - { REGDOMAIN_HI_5GHZ, {'R', 'U'}}, //RUSSIA - { REGDOMAIN_HI_5GHZ, {'R', 'W'}}, //RWANDA - { REGDOMAIN_APAC, {'S', 'A'}}, //SAUDI ARABIA + { REGDOMAIN_APAC, {'R', 'U'}}, //RUSSIA + { REGDOMAIN_WORLD, {'R', 'W'}}, //RWANDA + { REGDOMAIN_WORLD, {'S', 'A'}}, //SAUDI ARABIA { REGDOMAIN_NO_5GHZ, {'S', 'B'}}, //SOLOMON ISLANDS { REGDOMAIN_NO_5GHZ, {'S', 'C'}}, //SEYCHELLES { REGDOMAIN_WORLD, {'S', 'D'}}, //SUDAN @@ -343,22 +343,22 @@ static CountryInfoTable_t countryInfoTable = { REGDOMAIN_NO_5GHZ, {'T', 'M'}}, //TURKMENISTAN { REGDOMAIN_N_AMER_EXC_FCC, {'T', 'N'}}, //TUNISIA { REGDOMAIN_NO_5GHZ, {'T', 'O'}}, //TONGA - { REGDOMAIN_ETSI, {'T', 'R'}}, //TURKEY + { REGDOMAIN_ETSI, {'T', 'R'}}, //TURKEY { REGDOMAIN_WORLD, {'T', 'T'}}, //TRINIDAD AND TOBAGO { REGDOMAIN_NO_5GHZ, {'T', 'V'}}, //TUVALU { REGDOMAIN_JAPAN, {'T', 'W'}}, //TAIWAN, PROVINCE OF CHINA { REGDOMAIN_HI_5GHZ, {'T', 'Z'}}, //TANZANIA, UNITED REPUBLIC OF - { REGDOMAIN_NO_5GHZ, {'U', 'A'}}, //UKRAINE - { REGDOMAIN_WORLD, {'U', 'G'}}, //UGANDA + { REGDOMAIN_WORLD, {'U', 'A'}}, //UKRAINE + { REGDOMAIN_KOREA, {'U', 'G'}}, //UGANDA { REGDOMAIN_FCC, {'U', 'M'}}, //UNITED STATES MINOR OUTLYING ISLANDS { REGDOMAIN_WORLD, {'U', 'Y'}}, //URUGUAY - { REGDOMAIN_WORLD, {'U', 'Z'}}, //UZBEKISTAN + { REGDOMAIN_FCC, {'U', 'Z'}}, //UZBEKISTAN { REGDOMAIN_ETSI, {'V', 'A'}}, //HOLY SEE (VATICAN CITY STATE) { REGDOMAIN_WORLD, {'V', 'C'}}, //SAINT VINCENT AND THE GRENADINES { REGDOMAIN_HI_5GHZ, {'V', 'E'}}, //VENEZUELA { REGDOMAIN_ETSI, {'V', 'G'}}, //VIRGIN ISLANDS, BRITISH { REGDOMAIN_FCC, {'V', 'I'}}, //VIRGIN ISLANDS, US - { REGDOMAIN_WORLD, {'V', 'N'}}, //VIET NAM + { REGDOMAIN_FCC, {'V', 'N'}}, //VIET NAM { REGDOMAIN_NO_5GHZ, {'V', 'U'}}, //VANUATU { REGDOMAIN_WORLD, {'W', 'F'}}, //WALLIS AND FUTUNA { REGDOMAIN_N_AMER_EXC_FCC, {'W', 'S'}}, //SOMOA @@ -366,7 +366,7 @@ static CountryInfoTable_t countryInfoTable = { REGDOMAIN_ETSI, {'Y', 'T'}}, //MAYOTTE { REGDOMAIN_WORLD, {'Z', 'A'}}, //SOUTH AFRICA { REGDOMAIN_APAC, {'Z', 'M'}}, //ZAMBIA - { REGDOMAIN_NO_5GHZ, {'Z', 'W'}}, //ZIMBABWE + { REGDOMAIN_ETSI, {'Z', 'W'}}, //ZIMBABWE } }; typedef struct nvEFSTable_s @@ -1002,7 +1002,7 @@ VOS_STATUS vos_nv_readMultiMacAddress( v_U8_t *pMacAddress, (NULL == pMacAddress)) { VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, - " Invalid Parameter from NV Client macCount %d, pMacAddress 0x%x", + " Invalid Parameter from NV Client macCount %d, pMacAddress %p", macCount, pMacAddress); } @@ -1759,9 +1759,9 @@ VOS_STATUS vos_nv_getNVBuffer(v_VOID_t **pNvBuffer,v_SIZE_t *pSize) -------------------------------------------------------------------------*/ VOS_STATUS vos_nv_setRegDomain(void * clientCtxt, v_REGDOMAIN_t regId) { - v_CONTEXT_t pVosContext = NULL; - hdd_context_t *pHddCtx = NULL; - struct wiphy *wiphy = NULL; + v_CONTEXT_t pVosContext = NULL; + hdd_context_t *pHddCtx = NULL; + struct wiphy *wiphy = NULL; /* Client Context Argumant not used for PRIMA */ if (regId >= REGDOMAIN_COUNT) { @@ -1781,8 +1781,8 @@ VOS_STATUS vos_nv_setRegDomain(void * clientCtxt, v_REGDOMAIN_t regId) /* when CRDA is not running then we are world roaming. In this case if 11d is enabled, then country code should be update on basis of world roaming */ - if (memcmp(pHddCtx->cfg_ini->crdaDefaultCountryCode, - CFG_CRDA_DEFAULT_COUNTRY_CODE_DEFAULT , 2) == 0) + if ((NULL != pHddCtx) && (memcmp(pHddCtx->cfg_ini->crdaDefaultCountryCode, + CFG_CRDA_DEFAULT_COUNTRY_CODE_DEFAULT , 2) == 0)) { wiphy = pHddCtx->wiphy; regulatory_hint(wiphy, "00"); @@ -1866,6 +1866,68 @@ static int bw20_ch_index_to_bw40_ch_index(int k) return m; } +void crda_regulatory_entry_default(v_U8_t *countryCode, int domain_id) +{ + int k; + pr_info("Country %c%c domain_id %d\n enable ch 1 - 11.\n", + countryCode[0], countryCode[1], domain_id); + for (k = RF_CHAN_1; k <= RF_CHAN_11; k++) { + pnvEFSTable->halnv.tables.regDomains[domain_id].channels[k].enabled = + NV_CHANNEL_ENABLE; + /* Max Tx Power 20dBm */ + pnvEFSTable->halnv.tables.regDomains[domain_id].channels[k].pwrLimit = 20; + } + /* enable ch 12 to ch 14 passive scan */ + pr_info(" enable ch 12 - 14 to scan passively by setting DFS flag.\n"); + for (k = RF_CHAN_12; k <= MAX_2_4GHZ_CHANNEL; k++) { + pnvEFSTable->halnv.tables.regDomains[domain_id].channels[k].enabled = + NV_CHANNEL_DFS; + pnvEFSTable->halnv.tables.regDomains[domain_id].channels[k].pwrLimit = 0; + } + pr_info(" enable 5GHz to scan passively by setting DFS flag.\n"); + for (k = MIN_5GHZ_CHANNEL; k <= MAX_5GHZ_CHANNEL; k++) { + pnvEFSTable->halnv.tables.regDomains[domain_id].channels[k].enabled = + NV_CHANNEL_DFS; + pnvEFSTable->halnv.tables.regDomains[domain_id].channels[k].pwrLimit = 0; + } +#ifdef PASSIVE_SCAN_4_9GHZ + pr_info(" enable 4.9 GHz to scan passively by setting DFS flag.\n"); + for (k = RF_CHAN_240; k <= RF_CHAN_216; k++) { + pnvEFSTable->halnv.tables.regDomains[domain_id].channels[k].enabled = + NV_CHANNEL_DFS; + pnvEFSTable->halnv.tables.regDomains[domain_id].channels[k].pwrLimit = 0; + } +#endif + if (domain_id == NUM_REG_DOMAINS-1) + { /* init time */ + crda_alpha2[0] = countryCode[0]; + crda_alpha2[1] = countryCode[1]; + crda_regulatory_entry_valid = VOS_TRUE; + pnvEFSTable->halnv.tables.defaultCountryTable.countryCode[0] = countryCode[0]; + pnvEFSTable->halnv.tables.defaultCountryTable.countryCode[1] = countryCode[1]; + pnvEFSTable->halnv.tables.defaultCountryTable.countryCode[2] = 'I'; + pnvEFSTable->halnv.tables.defaultCountryTable.regDomain = NUM_REG_DOMAINS-1; + } + if (domain_id == NUM_REG_DOMAINS-2) + { /* none-default country */ + run_time_alpha2[0] = countryCode[0]; + run_time_alpha2[1] = countryCode[1]; + crda_regulatory_run_time_entry_valid = VOS_TRUE; + } +} + +static int crda_regulatory_entry_post_processing(struct wiphy *wiphy, + struct regulatory_request *request, + v_U8_t nBandCapability, + int domain_id) +{ + if (request->alpha2[0] == '0' && request->alpha2[1] == '0') { + pr_info("Country 00 special handling to enable passive scan.\n"); + crda_regulatory_entry_default(request->alpha2, domain_id); + } + return 0; +} + /* create_crda_regulatory_entry should be called from user command or 11d country IE */ static int create_crda_regulatory_entry(struct wiphy *wiphy, struct regulatory_request *request, @@ -1925,16 +1987,16 @@ static int create_crda_regulatory_entry(struct wiphy *wiphy, { pnvEFSTable->halnv.tables.regDomains[NUM_REG_DOMAINS-2].channels[k].enabled = NV_CHANNEL_DFS; - // max_power is in mBm = 100 * d + // max_power is in mBm = 100 * dBm pnvEFSTable->halnv.tables.regDomains[NUM_REG_DOMAINS-2].channels[k].pwrLimit = - (tANI_S8) (wiphy->bands[i]->channels[j].max_power); + (tANI_S8) ((wiphy->bands[i]->channels[j].max_power)/100); if ((wiphy->bands[i]->channels[j].flags & IEEE80211_CHAN_NO_HT40) == 0) { pnvEFSTable->halnv.tables.regDomains[NUM_REG_DOMAINS-2].channels[n].enabled = NV_CHANNEL_DFS; // 40MHz channel power is half of 20MHz (-3dB) ?? pnvEFSTable->halnv.tables.regDomains[NUM_REG_DOMAINS-2].channels[n].pwrLimit = - (tANI_S8) ((wiphy->bands[i]->channels[j].max_power)-3); + (tANI_S8) (((wiphy->bands[i]->channels[j].max_power)/100)-3); } } else // Enable is only last flag we support @@ -1943,14 +2005,14 @@ static int create_crda_regulatory_entry(struct wiphy *wiphy, NV_CHANNEL_ENABLE; // max_power is in dBm pnvEFSTable->halnv.tables.regDomains[NUM_REG_DOMAINS-2].channels[k].pwrLimit = - (tANI_S8) (wiphy->bands[i]->channels[j].max_power); + (tANI_S8) ((wiphy->bands[i]->channels[j].max_power)/100); if ((wiphy->bands[i]->channels[j].flags & IEEE80211_CHAN_NO_HT40) == 0) { pnvEFSTable->halnv.tables.regDomains[NUM_REG_DOMAINS-2].channels[n].enabled = NV_CHANNEL_ENABLE; // 40MHz channel power is half of 20MHz (-3dB) ?? pnvEFSTable->halnv.tables.regDomains[NUM_REG_DOMAINS-2].channels[n].pwrLimit = - (tANI_S8) ((wiphy->bands[i]->channels[j].max_power)-3); + (tANI_S8) (((wiphy->bands[i]->channels[j].max_power)/100)-3); } } /* ignore CRDA max_antenna_gain typical is 3dBi, nv.bin antennaGain is @@ -1962,6 +2024,7 @@ static int create_crda_regulatory_entry(struct wiphy *wiphy, run_time_alpha2[0] = request->alpha2[0]; run_time_alpha2[1] = request->alpha2[1]; crda_regulatory_run_time_entry_valid = VOS_TRUE; + crda_regulatory_entry_post_processing(wiphy, request, nBandCapability, NUM_REG_DOMAINS-2); return 0; } v_BOOL_t is_crda_regulatory_entry_valid(void) @@ -2229,6 +2292,7 @@ static int create_crda_regulatory_entry_from_regd(struct wiphy *wiphy, run_time_alpha2[1] = request->alpha2[1]; crda_regulatory_run_time_entry_valid = VOS_TRUE; } + crda_regulatory_entry_post_processing(wiphy, request, nBandCapability, domain_id); return 0; } @@ -2246,8 +2310,8 @@ int wlan_hdd_crda_reg_notifier(struct wiphy *wiphy, v_REGDOMAIN_t domainIdCurrent; tANI_U8 ccode[WNI_CFG_COUNTRY_CODE_LEN]; tANI_U8 uBufLen = WNI_CFG_COUNTRY_CODE_LEN; - eCsrBand nBandCapability; - int i=0,j=0,k=0,m=0; + tANI_U8 nBandCapability; + int i,j,k,m; wiphy_dbg(wiphy, "info: cfg80211 reg_notifier callback for country" " %c%c\n", request->alpha2[0], request->alpha2[1]); if (request->initiator == NL80211_REGDOM_SET_BY_USER) @@ -2325,7 +2389,7 @@ int wlan_hdd_crda_reg_notifier(struct wiphy *wiphy, } else { - sme_GetFreqBand(pHddCtx->hHal, &nBandCapability); + nBandCapability = pHddCtx->cfg_ini->nBandCapability; for (i=0, m=0; ibands[i]) @@ -2343,21 +2407,7 @@ int wlan_hdd_crda_reg_notifier(struct wiphy *wiphy, } else { - if( wiphy->bands[i-1] == NULL) - { - m = 14; - } - else - { - if(eCSR_BAND_5G == nBandCapability) - { - m = wiphy->bands[i-1]->n_channels + 11; - } - else - { - m = wiphy->bands[i-1]->n_channels + m; - } - } + m = wiphy->bands[i-1]?wiphy->bands[i-1]->n_channels + m:m; } for (j=0; jbands[i]->n_channels; j++) @@ -2365,7 +2415,6 @@ int wlan_hdd_crda_reg_notifier(struct wiphy *wiphy, // k = (m + j) is internal current channel index for 20MHz channel // n is internal channel index for corresponding 40MHz channel k = m + j; - if (IEEE80211_BAND_2GHZ == i && eCSR_BAND_5G == nBandCapability) // 5G only { // Enable social channels for P2P @@ -2433,8 +2482,7 @@ int wlan_hdd_crda_reg_notifier(struct wiphy *wiphy, } } } - - if (request->initiator == NL80211_REGDOM_SET_BY_CORE || request->initiator == NL80211_REGDOM_SET_BY_DRIVER) + if (request->initiator == NL80211_REGDOM_SET_BY_CORE) { request->processed = 1; } diff --git a/drivers/staging/prima/CORE/VOSS/src/vos_packet.c b/drivers/staging/prima/CORE/VOSS/src/vos_packet.c index 768754d127b..6d9436471d4 100644 --- a/drivers/staging/prima/CORE/VOSS/src/vos_packet.c +++ b/drivers/staging/prima/CORE/VOSS/src/vos_packet.c @@ -63,6 +63,7 @@ #include #include #include +#include /*-------------------------------------------------------------------------- Preprocessor definitions and constants @@ -194,9 +195,9 @@ static void vos_pkti_replenish_raw_pool(void) mutex_lock(&gpVosPacketContext->mlock); - if ((gpVosPacketContext->rxReplenishListCount < VPKT_RX_REPLENISH_THRESHOLD) - && - (!list_empty(&gpVosPacketContext->rxRawFreeList))) + if ((gpVosPacketContext->rxReplenishListCount < + gpVosPacketContext->numOfRxRawPackets/4) && + (!list_empty(&gpVosPacketContext->rxRawFreeList))) { mutex_unlock(&gpVosPacketContext->mlock); return; @@ -398,8 +399,10 @@ VOS_STATUS vos_packet_open( v_VOID_t *pVosContext, pVosPacketContext->rxRawFreeListCount = 0; INIT_LIST_HEAD(pFreeList); + pVosPacketContext->numOfRxRawPackets = vos_pkt_get_num_of_rx_raw_pkts(); + // fill the rxRaw free list - for (idx = 0; idx < VPKT_NUM_RX_RAW_PACKETS; idx++) + for (idx = 0; idx < pVosPacketContext->numOfRxRawPackets; idx++) { pPkt = &pVosPacketContext->vosPktBuffers[freePacketIndex++]; vosStatus = vos_pkti_packet_init(pPkt, VOS_PKT_TYPE_RX_RAW); @@ -873,7 +876,7 @@ VOS_STATUS vos_pkt_wrap_data_packet( vos_pkt_t **ppPacket, if (unlikely(VOS_PKT_TYPE_TX_802_3_DATA != pktType)) { VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, - "VPKT [%d]: invalid pktType", __LINE__, pktType); + "VPKT [%d]: invalid pktType %d", __LINE__, pktType); return VOS_STATUS_E_INVAL; } @@ -2950,6 +2953,32 @@ VOS_STATUS vos_pkt_get_available_buffer_pool (VOS_PKT_TYPE pktType, return VOS_STATUS_SUCCESS; } +/** + @brief vos_pkt_get_num_of_rx_raw_pkts() - Get the number of RX packets + that should be allocated. + + This function is called by VOS packet module to know how many RX raw + packets it should allocate/reserve. This value can be configured thru + Kernel device tree to save memory usage. + + @param + NONE + @return + v_SIZE_t the number of packets to allocate + +*/ +v_SIZE_t vos_pkt_get_num_of_rx_raw_pkts(void) +{ +#ifdef HAVE_WCNSS_RX_BUFF_COUNT + v_SIZE_t buffCount; + + buffCount = wcnss_get_wlan_rx_buff_count(); + return (buffCount > VPKT_NUM_RX_RAW_PACKETS ? + VPKT_NUM_RX_RAW_PACKETS : buffCount); +#else + return VPKT_NUM_RX_RAW_PACKETS; +#endif +} #ifdef VOS_PACKET_UNIT_TEST #include "vos_packet_test.c" diff --git a/drivers/staging/prima/CORE/VOSS/src/vos_sched.c b/drivers/staging/prima/CORE/VOSS/src/vos_sched.c index ded3bfceee7..cff46c48882 100644 --- a/drivers/staging/prima/CORE/VOSS/src/vos_sched.c +++ b/drivers/staging/prima/CORE/VOSS/src/vos_sched.c @@ -1121,7 +1121,7 @@ static int VosRXThread ( void * Arg ) /* Rx Thread Suspended */ complete(&pHddCtx->rx_sus_event_var); - init_completion(&pSchedContext->ResumeRxEvent); + INIT_COMPLETION(pSchedContext->ResumeRxEvent); spin_unlock(&pSchedContext->RxThreadLock); /* Wait for Resume Indication */ diff --git a/drivers/staging/prima/CORE/VOSS/src/vos_timer.c b/drivers/staging/prima/CORE/VOSS/src/vos_timer.c index d28b6fc2d82..112f07b1bf2 100644 --- a/drivers/staging/prima/CORE/VOSS/src/vos_timer.c +++ b/drivers/staging/prima/CORE/VOSS/src/vos_timer.c @@ -723,9 +723,12 @@ VOS_STATUS vos_timer_start( vos_timer_t *timer, v_U32_t expirationTime ) // Check if timer refers to an uninitialized object if ( LINUX_TIMER_COOKIE != timer->platformInfo.cookie ) { - VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, - "%s: Cannot start uninitialized timer",__func__); - VOS_ASSERT(0); + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Cannot start uninitialized timer",__func__); + if ( LINUX_INVALID_TIMER_COOKIE != timer->platformInfo.cookie ) + { + VOS_ASSERT(0); + } return VOS_STATUS_E_INVAL; } @@ -820,8 +823,11 @@ VOS_STATUS vos_timer_stop ( vos_timer_t *timer ) if ( LINUX_TIMER_COOKIE != timer->platformInfo.cookie ) { VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, - "%s: Cannot stop uninitialized timer",__func__); - VOS_ASSERT(0); + "%s: Cannot stop uninitialized timer",__func__); + if ( LINUX_INVALID_TIMER_COOKIE != timer->platformInfo.cookie ) + { + VOS_ASSERT(0); + } return VOS_STATUS_E_INVAL; } diff --git a/drivers/staging/prima/CORE/VOSS/src/vos_trace.c b/drivers/staging/prima/CORE/VOSS/src/vos_trace.c index 13ffded7a88..29604de6de9 100644 --- a/drivers/staging/prima/CORE/VOSS/src/vos_trace.c +++ b/drivers/staging/prima/CORE/VOSS/src/vos_trace.c @@ -219,6 +219,72 @@ void vos_snprintf(char *strBuffer, unsigned int size, char *strFormat, ...) va_end( val ); } +#ifdef WCONN_TRACE_KMSG_LOG_BUFF + +/* 64k:: size should be power of 2 to + get serial 'wconnstrContBuffIdx' index */ +#define KMSG_WCONN_TRACE_LOG_MAX 65536 + +static char wconnStrLogBuff[KMSG_WCONN_TRACE_LOG_MAX]; +static unsigned int wconnstrContBuffIdx; +static void kmsgwconnstrlogchar(char c) +{ + wconnStrLogBuff[wconnstrContBuffIdx & (KMSG_WCONN_TRACE_LOG_MAX-1)] = c; + wconnstrContBuffIdx++; +} + +/****************************************************************************** + * function:: kmsgwconnBuffWrite() + * wconnlogstrRead -> Recieved the string(log msg) from vos_trace_msg() + * 1) Get the timetick, convert into HEX and store in wconnStrLogBuff[] + * 2) And 'pwconnlogstr' would be copied into wconnStrLogBuff[] character by + character + * 3) wconnStrLogBuff[] is been treated as circular buffer. + * + * Note:: In T32 simulator the content of wconnStrLogBuff[] will appear as + continuous string please use logparse.cmm file to extract into + readable format + *******************************************************************************/ + +void kmsgwconnBuffWrite(const char *wconnlogstrRead) +{ + const char *pwconnlogstr = wconnlogstrRead; + static const char num[16] = {'0','1','2','3','4','5','6','7','8','9','A', + 'B','C','D','E','F'}; + unsigned int timetick; + int bits; /*timetick for now returns 32 bit number*/ + + timetick = ( jiffies_to_msecs(jiffies) / 10 ); + bits = sizeof(timetick) * 8/*number of bits in a byte*/; + + kmsgwconnstrlogchar('['); + + for ( ; bits > 0; bits -= 4 ) + kmsgwconnstrlogchar( num[((timetick & (0xF << (bits-4)))>>(bits-4))] ); + + kmsgwconnstrlogchar(']'); + + for ( ; *pwconnlogstr; pwconnlogstr++) + { + kmsgwconnstrlogchar(*pwconnlogstr); + } + kmsgwconnstrlogchar('\n');/*log \n*/ +} + +spinlock_t gVosSpinLock; + +void vos_wconn_trace_init(void) +{ + spin_lock_init(&gVosSpinLock); +} + +void vos_wconn_trace_exit(void) +{ + /* does nothing */ +} + +#endif + #ifdef VOS_ENABLE_TRACING /*---------------------------------------------------------------------------- @@ -248,6 +314,7 @@ void vos_trace_msg( VOS_MODULE_ID module, VOS_TRACE_LEVEL level, char *strFormat { char strBuffer[VOS_TRACE_BUFFER_SIZE]; int n; + unsigned long irq_flag; // Print the trace message when the desired level bit is set in the module // tracel level mask. @@ -269,12 +336,18 @@ void vos_trace_msg( VOS_MODULE_ID module, VOS_TRACE_LEVEL level, char *strFormat (char *) gVosTraceInfo[ module ].moduleNameStr ); // print the formatted log message after the prefix string. - if (n < VOS_TRACE_BUFFER_SIZE) + if ((n >= 0) && (n < VOS_TRACE_BUFFER_SIZE)) { vsnprintf(strBuffer + n, VOS_TRACE_BUFFER_SIZE - n, strFormat, val ); + +#ifdef WCONN_TRACE_KMSG_LOG_BUFF + spin_lock_irqsave (&gVosSpinLock, irq_flag); + kmsgwconnBuffWrite(strBuffer); + spin_unlock_irqrestore (&gVosSpinLock, irq_flag); +#endif pr_err("%s\n", strBuffer); } - va_end( val); + va_end(val); } } diff --git a/drivers/staging/prima/CORE/VOSS/src/vos_utils.c b/drivers/staging/prima/CORE/VOSS/src/vos_utils.c index 958b2cc1efe..27d5f874dd0 100644 --- a/drivers/staging/prima/CORE/VOSS/src/vos_utils.c +++ b/drivers/staging/prima/CORE/VOSS/src/vos_utils.c @@ -38,9 +38,6 @@ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ - -/* - * */ /*============================================================================ FILE: vos_utils.c @@ -303,7 +300,7 @@ int hmac_sha1(v_U8_t *key, v_U8_t ksize, char *plaintext, v_U8_t psize, ahash_request_set_crypt(req, &sg, hash_result, psize); ret = wcnss_wlan_crypto_ahash_digest(req); - VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "ret 0x%x"); + VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "ret 0x%x", ret); switch (ret) { case 0: @@ -406,7 +403,7 @@ int hmac_md5(v_U8_t *key, v_U8_t ksize, char *plaintext, v_U8_t psize, struct crypto_ahash *tfm; struct scatterlist sg; struct ahash_request *req; - struct hmac_md5_result tresult; + struct hmac_md5_result tresult = {.err = 0}; void *hash_buff = NULL; unsigned char hash_result[64]; @@ -458,7 +455,7 @@ int hmac_md5(v_U8_t *key, v_U8_t ksize, char *plaintext, v_U8_t psize, ahash_request_set_crypt(req, &sg, hash_result, psize); ret = wcnss_wlan_crypto_ahash_digest(req); - VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "ret 0x%x"); + VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "ret 0x%x", ret); switch (ret) { case 0: diff --git a/drivers/staging/prima/CORE/WDA/inc/legacy/halMsgApi.h b/drivers/staging/prima/CORE/WDA/inc/legacy/halMsgApi.h index 98a8bbdda6f..c8575ff05b8 100644 --- a/drivers/staging/prima/CORE/WDA/inc/legacy/halMsgApi.h +++ b/drivers/staging/prima/CORE/WDA/inc/legacy/halMsgApi.h @@ -1296,7 +1296,7 @@ typedef struct sMaxTxPowerParams typedef struct sAddStaSelfParams { tSirMacAddr selfMacAddr; - + tVOS_CON_MODE currDeviceMode; tANI_U32 status; }tAddStaSelfParams, *tpAddStaSelfParams; diff --git a/drivers/staging/prima/CORE/WDA/inc/legacy/halTypes.h b/drivers/staging/prima/CORE/WDA/inc/legacy/halTypes.h index f3ca8abe211..2e729565559 100644 --- a/drivers/staging/prima/CORE/WDA/inc/legacy/halTypes.h +++ b/drivers/staging/prima/CORE/WDA/inc/legacy/halTypes.h @@ -39,6 +39,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ + /** ------------------------------------------------------------------------- * ------------------------------------------------------------------------- * @@ -230,7 +231,8 @@ typedef enum eHAL_STATUS_SET_CHAN_ALREADY_ON_REQUESTED_CHAN, #ifdef WLAN_FEATURE_VOWIFI_11R - eHAL_STATUS_FT_PREAUTH_KEY_WAIT, + eHAL_STATUS_FT_PREAUTH_KEY_SUCCESS, + eHAL_STATUS_FT_PREAUTH_KEY_FAILED, #endif // not a real status. Just a way to mark the maximum in the enum. diff --git a/drivers/staging/prima/CORE/WDA/inc/wlan_qct_wda.h b/drivers/staging/prima/CORE/WDA/inc/wlan_qct_wda.h index 658a0aaa22a..2eb8c743941 100644 --- a/drivers/staging/prima/CORE/WDA/inc/wlan_qct_wda.h +++ b/drivers/staging/prima/CORE/WDA/inc/wlan_qct_wda.h @@ -118,6 +118,30 @@ typedef enum WDA_INVALID_STA_INDEX, WDA_VALID_STA_INDEX }WDA_ValidStaIndex; +typedef enum +{ + eWDA_AUTH_TYPE_NONE, //never used + // MAC layer authentication types + eWDA_AUTH_TYPE_OPEN_SYSTEM, + // Upper layer authentication types + eWDA_AUTH_TYPE_WPA, + eWDA_AUTH_TYPE_WPA_PSK, + + eWDA_AUTH_TYPE_RSN, + eWDA_AUTH_TYPE_RSN_PSK, + eWDA_AUTH_TYPE_FT_RSN, + eWDA_AUTH_TYPE_FT_RSN_PSK, + eWDA_AUTH_TYPE_WAPI_WAI_CERTIFICATE, + eWDA_AUTH_TYPE_WAPI_WAI_PSK, + eWDA_AUTH_TYPE_CCKM_WPA, + eWDA_AUTH_TYPE_CCKM_RSN, + eWDA_AUTH_TYPE_WPA_NONE, + eWDA_AUTH_TYPE_AUTOSWITCH, + eWDA_AUTH_TYPE_SHARED_KEY, + eWDA_NUM_OF_SUPPORT_AUTH_TYPE, + eWDA_AUTH_TYPE_FAILED = 0xff, + eWDA_AUTH_TYPE_UNKNOWN = eCSR_AUTH_TYPE_FAILED, +}WDA_AuthType; /*-------------------------------------------------------------------------- Utilities @@ -137,6 +161,11 @@ typedef enum #define IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE 0 #endif +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +#define IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE ((WDI_getHostWlanFeatCaps(WLAN_ROAM_SCAN_OFFLOAD)) & (WDA_getFwWlanFeatCaps(WLAN_ROAM_SCAN_OFFLOAD))) +#else +#define IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE 0 +#endif /*-------------------------------------------------------------------------- Definitions for Data path APIs @@ -499,7 +528,6 @@ tBssSystemRole wdaGetGlobalSystemRole(tpAniSirGlobal pMac); // FIXME Temporary value for R33D integaration //#define WDA_TL_TX_FRAME_TIMEOUT 20000 /* in msec a very high upper limit */ -#define DPU_FEEDBACK_UNPROTECTED_ERROR 0x0F /* --------------------------------------------------------------------------- @@ -641,7 +669,12 @@ tBssSystemRole wdaGetGlobalSystemRole(tpAniSirGlobal pMac); /* WDA_IS_RX_IN_SCAN *********************************************************/ # define WDA_IS_RX_IN_SCAN(pRxMeta) (((WDI_DS_RxMetaInfoType*)(pRxMeta))->scan) - +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +/* WDA_GET_OFFLOADSCANLEARN **************************************************/ +# define WDA_GET_OFFLOADSCANLEARN(pRxMeta) (((WDI_DS_RxMetaInfoType*)(pRxMeta))->offloadScanLearn) +/* WDA_GET_ROAMCANDIDATEIND **************************************************/ +# define WDA_GET_ROAMCANDIDATEIND(pRxMeta) (((WDI_DS_RxMetaInfoType*)(pRxMeta))->roamCandidateInd) +#endif /* WDA_GET_RX_RSSI_DB ********************************************************/ // Volans RF # define WDA_RSSI_OFFSET 100 @@ -696,10 +729,7 @@ tBssSystemRole wdaGetGlobalSystemRole(tpAniSirGlobal pMac); /* WDA_GETRSSI1 ***************************************************************/ # define WDA_GETRSSI1(pRxMeta) (((WDI_DS_RxMetaInfoType*)(pRxMeta))->rssi1) -/* WDA_GET_RX_RMF *****************************************************/ -#ifdef WLAN_FEATURE_11W -# define WDA_GET_RX_RMF(pRxMeta) (((WDI_DS_RxMetaInfoType*)(pRxMeta))->rmf) -#endif + /* --------------------------------------------------------------------*/ @@ -890,9 +920,6 @@ tSirRetStatus uMacPostCtrlMsg(void* pSirGlobal, tSirMbMsg* pMb); #define WDA_TIMER_ADC_RSSI_STATS SIR_HAL_TIMER_ADC_RSSI_STATS #define WDA_TIMER_TRAFFIC_STATS_IND SIR_HAL_TRAFFIC_STATS_IND -#ifdef WLAN_FEATURE_11W -#define WDA_EXCLUDE_UNENCRYPTED_IND SIR_HAL_EXCLUDE_UNENCRYPTED_IND -#endif #ifdef FEATURE_WLAN_CCX #define WDA_TSM_STATS_REQ SIR_HAL_TSM_STATS_REQ @@ -1001,6 +1028,10 @@ tSirRetStatus uMacPostCtrlMsg(void* pSirGlobal, tSirMbMsg* pMb); #define WDA_SET_PNO_CHANGED_IND SIR_HAL_SET_PNO_CHANGED_IND #endif // FEATURE_WLAN_SCAN_PNO +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +#define WDA_ROAM_SCAN_OFFLOAD_REQ SIR_HAL_ROAM_SCAN_OFFLOAD_REQ +#endif + #ifdef WLAN_WAKEUP_EVENTS #define WDA_WAKE_REASON_IND SIR_HAL_WAKE_REASON_IND #endif // WLAN_WAKEUP_EVENTS @@ -1081,6 +1112,9 @@ v_BOOL_t WDA_IsHwFrameTxTranslationCapable(v_PVOID_t pVosGCtx, #define WDA_UpdateRssiBmps(pvosGCtx, staId, rssi) \ WLANTL_UpdateRssiBmps(pvosGCtx, staId, rssi) +#define WDA_UpdateLinkCapacity(pvosGCtx, staId, linkCapacity) \ + WLANTL_UpdateLinkCapacity(pvosGCtx, staId, linkCapacity) + #ifdef WLAN_PERF /*========================================================================== FUNCTION WDA_TLI_FastHwFwdDataFrame @@ -1801,4 +1835,19 @@ void WDA_TransportChannelDebug ===========================================================================*/ void WDA_TrafficStatsTimerActivate(wpt_boolean activate); +/*========================================================================== + FUNCTION WDA_SetEnableSSR + + DESCRIPTION + API to enable/disable SSR on WDI timeout + + PARAMETERS + enableSSR : enable/disable SSR + + RETURN VALUE + NONE + +===========================================================================*/ +void WDA_SetEnableSSR(v_BOOL_t enableSSR); + #endif diff --git a/drivers/staging/prima/CORE/WDA/src/wlan_qct_wda.c b/drivers/staging/prima/CORE/WDA/src/wlan_qct_wda.c index ef5953ac0d3..2ff8273ece0 100644 --- a/drivers/staging/prima/CORE/WDA/src/wlan_qct_wda.c +++ b/drivers/staging/prima/CORE/WDA/src/wlan_qct_wda.c @@ -180,6 +180,12 @@ static VOS_STATUS WDA_ProcessSetPrefNetworkReq(tWDA_CbContext *pWDA, tSirPNOScan static VOS_STATUS WDA_ProcessSetRssiFilterReq(tWDA_CbContext *pWDA, tSirSetRSSIFilterReq* pRssiFilterParams); static VOS_STATUS WDA_ProcessUpdateScanParams(tWDA_CbContext *pWDA, tSirUpdateScanParams *pUpdateScanParams); #endif // FEATURE_WLAN_SCAN_PNO +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +VOS_STATUS WDA_ProcessRoamScanOffloadReq(tWDA_CbContext *pWDA,tSirRoamOffloadScanReq *pRoamOffloadScanReqParams); +void WDA_RoamOffloadScanReqCallback(WDI_Status status, void* pUserData); +void WDA_ConvertSirAuthToWDIAuth(WDI_AuthType *AuthType, v_U8_t csrAuthType); +void WDA_ConvertSirEncToWDIEnc(WDI_EdType *EncrType, v_U8_t csrEncrType); +#endif #ifdef WLAN_FEATURE_PACKET_FILTERING static VOS_STATUS WDA_Process8023MulticastListReq ( tWDA_CbContext *pWDA, @@ -1868,8 +1874,8 @@ VOS_STATUS WDA_WniCfgDnld(tWDA_CbContext *pWDA) v_SIZE_t cbFileImageSize = 0; v_VOID_t *pCfgBinary = NULL; v_SIZE_t cbCfgBinarySize = 0; - v_BOOL_t bStatus = VOS_FALSE; + if (NULL == pMac ) { VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, @@ -1926,16 +1932,12 @@ VOS_STATUS WDA_WniCfgDnld(tWDA_CbContext *pWDA) * for now calling the existing cfg download API */ processCfgDownloadReq(pMac,cbCfgBinarySize,pCfgBinary); - if( pFileImage != NULL ) - { - vos_mem_free( pFileImage ); - } - return vosStatus; + vosStatus = VOS_STATUS_SUCCESS; + + /* fall through to clean up and return success */ fail: - if(pCfgBinary != NULL) - vos_mem_free( pFileImage ); - + vos_mem_free( pFileImage ); return vosStatus; } /* ----------------------------------------------------------------- @@ -1995,7 +1997,6 @@ VOS_STATUS WDA_SuspendDataTx(tWDA_CbContext *pWDA) { VOS_STATUS status = VOS_STATUS_E_FAILURE; tANI_U8 eventIdx = 0; - tANI_U8 ucSTAId = 0; VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, "%s: Entered " ,__func__); @@ -2015,8 +2016,7 @@ VOS_STATUS WDA_SuspendDataTx(tWDA_CbContext *pWDA) return VOS_STATUS_E_FAILURE; } /*Indicate TL to suspend transmission for all Sta Id */ - ucSTAId = WLAN_ALL_STA; - status = WLANTL_SuspendDataTx(pWDA->pVosContext, &ucSTAId, + status = WLANTL_SuspendDataTx(pWDA->pVosContext, NULL, WDA_SuspendDataTxCallback); if(status != VOS_STATUS_SUCCESS) { @@ -2054,12 +2054,11 @@ VOS_STATUS WDA_SuspendDataTx(tWDA_CbContext *pWDA) VOS_STATUS WDA_ResumeDataTx(tWDA_CbContext *pWDA) { VOS_STATUS status = VOS_STATUS_SUCCESS; - tANI_U8 ucSTAId = 0; VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, "%s: Entered " ,__func__); - ucSTAId = WLAN_ALL_STA; - status = WLANTL_ResumeDataTx(pWDA->pVosContext, &ucSTAId); + + status = WLANTL_ResumeDataTx(pWDA->pVosContext, NULL); return status; } /* @@ -2898,12 +2897,20 @@ VOS_STATUS WDA_ProcessConfigBssReq(tWDA_CbContext *pWDA, tAddBssParams* configBssReqParam) { WDI_Status status = WDI_STATUS_SUCCESS ; - WDI_ConfigBSSReqParamsType *wdiConfigBssReqParam = - (WDI_ConfigBSSReqParamsType *)vos_mem_malloc( - sizeof(WDI_ConfigBSSReqParamsType)) ; + WDI_ConfigBSSReqParamsType *wdiConfigBssReqParam; tWDA_ReqParams *pWdaParams ; VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, "------> %s " ,__func__); + if (NULL == configBssReqParam) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_FATAL, + "%s: configBssReqParam is NULL", __func__); + return VOS_STATUS_E_INVAL; + } + + wdiConfigBssReqParam = (WDI_ConfigBSSReqParamsType *)vos_mem_malloc( + sizeof(WDI_ConfigBSSReqParamsType)) ; + if(NULL == wdiConfigBssReqParam) { VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, @@ -3430,6 +3437,7 @@ VOS_STATUS WDA_ProcessAddStaSelfReq( tWDA_CbContext *pWDA, tpAddStaSelfParams pA } wdiAddStaSelfReq->wdiReqStatusCB = NULL; vos_mem_copy( wdiAddStaSelfReq->wdiAddSTASelfInfo.selfMacAddr, pAddStaSelfReq->selfMacAddr, 6); + wdiAddStaSelfReq->wdiAddSTASelfInfo.currDeviceMode = pAddStaSelfReq->currDeviceMode; /* Store Init Req pointer, as this will be used for response */ /* store Params pass it to WDI */ pWdaParams->pWdaContext = pWDA; @@ -3492,7 +3500,7 @@ void WDA_DelSTASelfReqCallback(WDI_Status wdiStatus, tDelStaSelfParams *delStaSelfParams; VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, - "<------ %s, wdiStatus: %d pWdaParams: 0x%x", + "<------ %s, wdiStatus: %d pWdaParams: %p", __func__, wdiStatus, pWdaParams); if (NULL == pWdaParams) @@ -3642,8 +3650,6 @@ void WDA_UpdateBSSParams(tWDA_CbContext *pWDA, wdiBssParams->ucCurrentExtChannel = wdaBssParams->currentExtChannel ; wdiBssParams->bHiddenSSIDEn = wdaBssParams->bHiddenSSIDEn ; - wdiBssParams->ucRMFEnabled = wdaBssParams->rmfEnabled; - /* copy SSID into WDI structure */ wdiBssParams->wdiSSID.ucLength = wdaBssParams->ssId.length ; vos_mem_copy(wdiBssParams->wdiSSID.sSSID, @@ -4862,7 +4868,6 @@ void WDA_GetStatsReqParamsCallback( pGetPEStatsRspParams->msgType = wdiGetStatsRsp->usMsgType; pGetPEStatsRspParams->msgLen = sizeof(tAniGetPEStatsRsp) + (wdiGetStatsRsp->usMsgLen - sizeof(WDI_GetStatsRspParamsType)); - pGetPEStatsRspParams->msgLen = wdiGetStatsRsp->usMsgLen + sizeof(tANI_U8); //Fill the Session Id Properly in PE pGetPEStatsRspParams->sessionId = 0; @@ -5306,6 +5311,8 @@ VOS_STATUS WDA_ProcessAddBASessionReq(tWDA_CbContext *pWDA, (WDI_AddBASessionReqParamsType *)vos_mem_malloc( sizeof(WDI_AddBASessionReqParamsType)) ; tWDA_ReqParams *pWdaParams ; + WLANTL_STAStateType tlSTAState = 0; + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, "------> %s " ,__func__); if(NULL == wdiAddBASessionReqParam) @@ -5357,6 +5364,27 @@ VOS_STATUS WDA_ProcessAddBASessionReq(tWDA_CbContext *pWDA, pWdaParams->wdaMsgParam = (void *)pAddBAReqParams ; /* store Params pass it to WDI */ pWdaParams->wdaWdiApiMsgParam = (void *)wdiAddBASessionReqParam ; + + /* In TDLS case, there is a possibility that TL hasn't registered peer yet, but + the peer thinks that we already setup TDLS link, and send us ADDBA request packet + */ + if((VOS_STATUS_SUCCESS != WDA_TL_GET_STA_STATE(pWDA->pVosContext, pAddBAReqParams->staIdx, &tlSTAState)) || + ((WLANTL_STA_CONNECTED != tlSTAState) && (WLANTL_STA_AUTHENTICATED != tlSTAState))) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "Peer staIdx %d hasn't established yet(%d). Send ADD BA failure to PE.\n", pAddBAReqParams->staIdx, tlSTAState ); + status = WDI_STATUS_E_NOT_ALLOWED; + pAddBAReqParams->status = + CONVERT_WDI2SIR_STATUS(status) ; + WDA_SendMsg(pWDA, WDA_ADDBA_RSP, (void *)pAddBAReqParams , 0) ; + /*Reset the WDA state to READY */ + pWDA->wdaState = WDA_READY_STATE; + vos_mem_free(pWdaParams->wdaWdiApiMsgParam) ; + vos_mem_free(pWdaParams); + + return CONVERT_WDI2VOS_STATUS(status) ; + } + status = WDI_AddBASessionReq(wdiAddBASessionReqParam, (WDI_AddBASessionRspCb)WDA_AddBASessionReqCallback, pWdaParams); if(IS_WDI_STATUS_FAILURE(status)) @@ -5368,6 +5396,8 @@ VOS_STATUS WDA_ProcessAddBASessionReq(tWDA_CbContext *pWDA, pAddBAReqParams->status = CONVERT_WDI2SIR_STATUS(status) ; WDA_SendMsg(pWDA, WDA_ADDBA_RSP, (void *)pAddBAReqParams , 0) ; + /*Reset the WDA state to READY */ + pWDA->wdaState = WDA_READY_STATE; vos_mem_free(pWdaParams->wdaWdiApiMsgParam) ; vos_mem_free(pWdaParams); } @@ -6564,10 +6594,10 @@ VOS_STATUS WDA_ProcessExitImpsReq(tWDA_CbContext *pWDA) return CONVERT_WDI2VOS_STATUS(status) ; } /* - * FUNCTION: WDA_EnterBmpsReqCallback + * FUNCTION: WDA_EnterBmpsRespCallback * send Enter BMPS RSP back to PE */ -void WDA_EnterBmpsReqCallback(WDI_EnterBmpsRspParamsType *pwdiEnterBmpsRsp, void* pUserData) +void WDA_EnterBmpsRespCallback(WDI_EnterBmpsRspParamsType *pwdiEnterBmpsRsp, void* pUserData) { tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; tWDA_CbContext *pWDA; @@ -6595,6 +6625,41 @@ void WDA_EnterBmpsReqCallback(WDI_EnterBmpsRspParamsType *pwdiEnterBmpsRsp, void return ; } +/* + * FUNCTION: WDA_EnterBmpsReqCallback + * Free memory and send Enter BMPS RSP back to PE. + * Invoked when Enter BMPS REQ failed in WDI and no RSP callback is generated. + */ +void WDA_EnterBmpsReqCallback(WDI_Status wdiStatus, void* pUserData) +{ + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; + tWDA_CbContext *pWDA; + tEnterBmpsParams *pEnterBmpsRspParams; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s, wdiStatus: %d", __func__, wdiStatus); + + if(NULL == pWdaParams) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return; + } + + pWDA = (tWDA_CbContext *)pWdaParams->pWdaContext; + pEnterBmpsRspParams = (tEnterBmpsParams *)pWdaParams->wdaMsgParam; + pEnterBmpsRspParams->status = wdiStatus; + + if(IS_WDI_STATUS_FAILURE(wdiStatus)) + { + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams); + WDA_SendMsg(pWDA, WDA_ENTER_BMPS_RSP, (void *)pEnterBmpsRspParams, 0); + } + + return; +} /* * FUNCTION: WDA_ProcessEnterBmpsReq * Request to WDI to Enter BMPS power state. @@ -6643,7 +6708,8 @@ VOS_STATUS WDA_ProcessEnterBmpsReq(tWDA_CbContext *pWDA, wdiEnterBmpsReqParams->wdiEnterBmpsInfo.rssiFilterPeriod = (wpt_uint32)pEnterBmpsReqParams->rssiFilterPeriod; wdiEnterBmpsReqParams->wdiEnterBmpsInfo.numBeaconPerRssiAverage = (wpt_uint32)pEnterBmpsReqParams->numBeaconPerRssiAverage; wdiEnterBmpsReqParams->wdiEnterBmpsInfo.bRssiFilterEnable = (wpt_uint8)pEnterBmpsReqParams->bRssiFilterEnable; - wdiEnterBmpsReqParams->wdiReqStatusCB = NULL; + wdiEnterBmpsReqParams->wdiReqStatusCB = WDA_EnterBmpsReqCallback; + wdiEnterBmpsReqParams->pUserData = pWdaParams; /* Store param pointer as passed in by caller */ /* store Params pass it to WDI */ @@ -6651,7 +6717,7 @@ VOS_STATUS WDA_ProcessEnterBmpsReq(tWDA_CbContext *pWDA, pWdaParams->wdaMsgParam = pEnterBmpsReqParams; pWdaParams->pWdaContext = pWDA; status = WDI_EnterBmpsReq(wdiEnterBmpsReqParams, - (WDI_EnterBmpsRspCb)WDA_EnterBmpsReqCallback, pWdaParams); + (WDI_EnterBmpsRspCb)WDA_EnterBmpsRespCallback, pWdaParams); if (IS_WDI_STATUS_FAILURE(status)) { VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, @@ -6676,10 +6742,10 @@ static void WDA_SendExitBmpsRsp(tWDA_CbContext *pWDA, /* - * FUNCTION: WDA_ExitBmpsReqCallback + * FUNCTION: WDA_ExitBmpsRespCallback * send Exit BMPS RSP back to PE */ -void WDA_ExitBmpsReqCallback(WDI_ExitBmpsRspParamsType *pwdiExitBmpsRsp, void* pUserData) +void WDA_ExitBmpsRespCallback(WDI_ExitBmpsRspParamsType *pwdiExitBmpsRsp, void* pUserData) { tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; tWDA_CbContext *pWDA; @@ -6707,6 +6773,41 @@ void WDA_ExitBmpsReqCallback(WDI_ExitBmpsRspParamsType *pwdiExitBmpsRsp, void* p WDA_SendMsg(pWDA, WDA_EXIT_BMPS_RSP, (void *)pExitBmpsRspParams , 0) ; return ; } +/* + * FUNCTION: WDA_ExitBmpsReqCallback + * Free memory and send Exit BMPS RSP back to PE. + * Invoked when Exit BMPS REQ failed in WDI and no RSP callback is generated. + */ +void WDA_ExitBmpsReqCallback(WDI_Status wdiStatus, void* pUserData) +{ + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; + tWDA_CbContext *pWDA; + tExitBmpsParams *pExitBmpsRspParams; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s, wdiStatus: %d", __func__, wdiStatus); + + if(NULL == pWdaParams) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return; + } + + pWDA = (tWDA_CbContext *)pWdaParams->pWdaContext; + pExitBmpsRspParams = (tExitBmpsParams *)pWdaParams->wdaMsgParam; + pExitBmpsRspParams->status = wdiStatus; + + if(IS_WDI_STATUS_FAILURE(wdiStatus)) + { + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams); + WDA_SendMsg(pWDA, WDA_EXIT_BMPS_RSP, (void *)pExitBmpsRspParams, 0); + } + + return; +} /* * FUNCTION: WDA_ProcessExitBmpsReq * Request to WDI to Exit BMPS power state. @@ -6742,15 +6843,16 @@ VOS_STATUS WDA_ProcessExitBmpsReq(tWDA_CbContext *pWDA, wdiExitBmpsReqParams->wdiExitBmpsInfo.bssIdx = pExitBmpsReqParams->bssIdx; - wdiExitBmpsReqParams->wdiReqStatusCB = NULL; - + wdiExitBmpsReqParams->wdiReqStatusCB = WDA_ExitBmpsReqCallback; + wdiExitBmpsReqParams->pUserData = pWdaParams; + /* Store param pointer as passed in by caller */ /* store Params pass it to WDI */ pWdaParams->wdaWdiApiMsgParam = wdiExitBmpsReqParams; pWdaParams->pWdaContext = pWDA; pWdaParams->wdaMsgParam = pExitBmpsReqParams; status = WDI_ExitBmpsReq(wdiExitBmpsReqParams, - (WDI_ExitBmpsRspCb)WDA_ExitBmpsReqCallback, pWdaParams); + (WDI_ExitBmpsRspCb)WDA_ExitBmpsRespCallback, pWdaParams); if(IS_WDI_STATUS_FAILURE(status)) { VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, @@ -6762,10 +6864,10 @@ VOS_STATUS WDA_ProcessExitBmpsReq(tWDA_CbContext *pWDA, return CONVERT_WDI2VOS_STATUS(status) ; } /* - * FUNCTION: WDA_EnterUapsdReqCallback + * FUNCTION: WDA_EnterUapsdRespCallback * send Enter UAPSD RSP back to PE */ -void WDA_EnterUapsdReqCallback( WDI_EnterUapsdRspParamsType *pwdiEnterUapsdRspParams, void* pUserData) +void WDA_EnterUapsdRespCallback( WDI_EnterUapsdRspParamsType *pwdiEnterUapsdRspParams, void* pUserData) { tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; tWDA_CbContext *pWDA; @@ -6791,6 +6893,41 @@ void WDA_EnterUapsdReqCallback( WDI_EnterUapsdRspParamsType *pwdiEnterUapsdRspP WDA_SendMsg(pWDA, WDA_ENTER_UAPSD_RSP, (void *)pEnterUapsdRsqParams , 0) ; return ; } +/* + * FUNCTION: WDA_EnterUapsdReqCallback + * Free memory and send Enter UAPSD RSP back to PE. + * Invoked when Enter UAPSD REQ failed in WDI and no RSP callback is generated. + */ +void WDA_EnterUapsdReqCallback(WDI_Status wdiStatus, void* pUserData) +{ + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; + tWDA_CbContext *pWDA; + tUapsdParams *pEnterUapsdRsqParams; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s, wdiStatus: %d", __func__, wdiStatus); + + if(NULL == pWdaParams) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return; + } + + pWDA = (tWDA_CbContext *)pWdaParams->pWdaContext; + pEnterUapsdRsqParams = (tUapsdParams *)pWdaParams->wdaMsgParam; + pEnterUapsdRsqParams->status = wdiStatus; + + if(IS_WDI_STATUS_FAILURE(wdiStatus)) + { + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams); + WDA_SendMsg(pWDA, WDA_ENTER_UAPSD_RSP, (void *)pEnterUapsdRsqParams, 0); + } + + return; +} /* * FUNCTION: WDA_ProcessEnterUapsdReq * Request to WDI to Enter UAPSD power state. @@ -6839,7 +6976,8 @@ VOS_STATUS WDA_ProcessEnterUapsdReq(tWDA_CbContext *pWDA, pEnterUapsdReqParams->voTriggerEnabled; wdiEnterUapsdReqParams->wdiEnterUapsdInfo.bssIdx = pEnterUapsdReqParams->bssIdx; - wdiEnterUapsdReqParams->wdiReqStatusCB = NULL; + wdiEnterUapsdReqParams->wdiReqStatusCB = WDA_EnterUapsdReqCallback; + wdiEnterUapsdReqParams->pUserData = pWdaParams; /* Store param pointer as passed in by caller */ /* store Params pass it to WDI */ @@ -6847,7 +6985,7 @@ VOS_STATUS WDA_ProcessEnterUapsdReq(tWDA_CbContext *pWDA, pWdaParams->pWdaContext = pWDA; pWdaParams->wdaMsgParam = pEnterUapsdReqParams; status = WDI_EnterUapsdReq(wdiEnterUapsdReqParams, - (WDI_EnterUapsdRspCb)WDA_EnterUapsdReqCallback, pWdaParams); + (WDI_EnterUapsdRspCb)WDA_EnterUapsdRespCallback, pWdaParams); if(IS_WDI_STATUS_FAILURE(status)) { VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, @@ -6859,10 +6997,10 @@ VOS_STATUS WDA_ProcessEnterUapsdReq(tWDA_CbContext *pWDA, return CONVERT_WDI2VOS_STATUS(status) ; } /* - * FUNCTION: WDA_ExitUapsdReqCallback + * FUNCTION: WDA_ExitUapsdRespCallback * send Exit UAPSD RSP back to PE */ -void WDA_ExitUapsdReqCallback(WDI_ExitUapsdRspParamsType *pwdiExitRspParam, void* pUserData) +void WDA_ExitUapsdRespCallback(WDI_ExitUapsdRspParamsType *pwdiExitRspParam, void* pUserData) { tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; @@ -6891,6 +7029,41 @@ void WDA_ExitUapsdReqCallback(WDI_ExitUapsdRspParamsType *pwdiExitRspParam, void WDA_SendMsg(pWDA, WDA_EXIT_UAPSD_RSP, (void *)pExitUapsdRspParams, 0) ; return ; } +/* + * FUNCTION: WDA_ExitUapsdReqCallback + * Free memory and send Exit UAPSD RSP back to PE. + * Invoked when Exit UAPSD REQ failed in WDI and no RSP callback is generated. + */ +void WDA_ExitUapsdReqCallback(WDI_Status wdiStatus, void* pUserData) +{ + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; + tWDA_CbContext *pWDA; + tExitUapsdParams *pExitUapsdRspParams; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s, wdiStatus: %d", __func__, wdiStatus); + + if(NULL == pWdaParams) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return; + } + + pWDA = (tWDA_CbContext *)pWdaParams->pWdaContext; + pExitUapsdRspParams = (tExitUapsdParams *)pWdaParams->wdaMsgParam; + pExitUapsdRspParams->status = wdiStatus; + + if(IS_WDI_STATUS_FAILURE(wdiStatus)) + { + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams); + WDA_SendMsg(pWDA, WDA_EXIT_UAPSD_RSP, (void *)pExitUapsdRspParams, 0); + } + + return; +} /* * FUNCTION: WDA_ProcessExitUapsdReq * Request to WDI to Exit UAPSD power state. @@ -6925,7 +7098,8 @@ VOS_STATUS WDA_ProcessExitUapsdReq(tWDA_CbContext *pWDA, } wdiExitUapsdReqParams->wdiExitUapsdInfo.bssIdx = pExitUapsdParams->bssIdx; - wdiExitUapsdReqParams->wdiReqStatusCB = NULL; + wdiExitUapsdReqParams->wdiReqStatusCB = WDA_ExitUapsdReqCallback; + wdiExitUapsdReqParams->pUserData = pWdaParams; /* Store param pointer as passed in by caller */ /* store Params pass it to WDI */ @@ -6933,7 +7107,7 @@ VOS_STATUS WDA_ProcessExitUapsdReq(tWDA_CbContext *pWDA, pWdaParams->pWdaContext = pWDA; pWdaParams->wdaMsgParam = pExitUapsdParams; - status = WDI_ExitUapsdReq(wdiExitUapsdReqParams, (WDI_ExitUapsdRspCb)WDA_ExitUapsdReqCallback, pWdaParams); + status = WDI_ExitUapsdReq(wdiExitUapsdReqParams, (WDI_ExitUapsdRspCb)WDA_ExitUapsdRespCallback, pWdaParams); if(IS_WDI_STATUS_FAILURE(status)) { VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, @@ -7133,19 +7307,57 @@ VOS_STATUS WDA_ProcessSetPwrSaveCfgReq(tWDA_CbContext *pWDA, return CONVERT_WDI2VOS_STATUS(status); } /* - * FUNCTION: WDA_SetUapsdAcParamsReqCallback + * FUNCTION: WDA_SetUapsdAcParamsRespCallback * */ -void WDA_SetUapsdAcParamsReqCallback(WDI_Status status, void* pUserData) +void WDA_SetUapsdAcParamsRespCallback(WDI_Status status, void* pUserData) { - tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData ; + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData ; + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, "<------ %s " ,__func__); - vos_mem_free(pWdaParams->wdaWdiApiMsgParam) ; + + if(NULL == pWdaParams) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return ; + } + + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); vos_mem_free(pWdaParams); return ; } +/* + * FUNCTION: WDA_SetUapsdAcParamsReqCallback + * Free memory. + * Invoked when SetUAPSDACParams REQ failed in WDI and no RSP callback is generated. + */ +void WDA_SetUapsdAcParamsReqCallback(WDI_Status wdiStatus, void* pUserData) +{ + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s, wdiStatus: %d", __func__, wdiStatus); + + if(NULL == pWdaParams) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return; + } + + if(IS_WDI_STATUS_FAILURE(wdiStatus)) + { + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams); + } + + return; +} /* * FUNCTION: WDA_SetUapsdAcParamsReq * Request to WDI to set the UAPSD params for an ac (sta mode). @@ -7183,7 +7395,9 @@ VOS_STATUS WDA_SetUapsdAcParamsReq(v_PVOID_t pVosContext, v_U8_t staIdx, wdiUapsdParams->wdiUapsdInfo.ucSTAIdx = pUapsdInfo->staidx; wdiUapsdParams->wdiUapsdInfo.uSusInterval = pUapsdInfo->susInterval; wdiUapsdParams->wdiUapsdInfo.ucUp = pUapsdInfo->up; - wdiUapsdParams->wdiReqStatusCB = NULL; + wdiUapsdParams->wdiReqStatusCB = WDA_SetUapsdAcParamsReqCallback; + wdiUapsdParams->pUserData = pWdaParams; + pWDA = vos_get_context( VOS_MODULE_ID_WDA, pVosContext ); pWdaParams->pWdaContext = pWDA; /* Store param pointer as passed in by caller */ @@ -7191,7 +7405,7 @@ VOS_STATUS WDA_SetUapsdAcParamsReq(v_PVOID_t pVosContext, v_U8_t staIdx, /* store Params pass it to WDI */ pWdaParams->wdaWdiApiMsgParam = (void *)wdiUapsdParams; status = WDI_SetUapsdAcParamsReq(wdiUapsdParams, - (WDI_SetUapsdAcParamsCb)WDA_SetUapsdAcParamsReqCallback, + (WDI_SetUapsdAcParamsCb)WDA_SetUapsdAcParamsRespCallback, pWdaParams); if(IS_WDI_STATUS_FAILURE(status)) { @@ -7220,10 +7434,10 @@ VOS_STATUS WDA_ClearUapsdAcParamsReq(v_PVOID_t pVosContext, v_U8_t staIdx, wpt_u return VOS_STATUS_SUCCESS; } /* - * FUNCTION: WDA_UpdateUapsdParamsReqCallback + * FUNCTION: WDA_UpdateUapsdParamsRespCallback * */ -void WDA_UpdateUapsdParamsReqCallback(WDI_Status status, void* pUserData) +void WDA_UpdateUapsdParamsRespCallback(WDI_Status status, void* pUserData) { tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData ; @@ -7244,9 +7458,38 @@ void WDA_UpdateUapsdParamsReqCallback(WDI_Status status, void* pUserData) //print a msg, nothing else to do VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, - "WDA_UpdateUapsdParamsReqCallback invoked " ); + "WDA_UpdateUapsdParamsRespCallback invoked " ); return ; } +/* + * FUNCTION: WDA_UpdateUapsdParamsReqCallback + * Free memory. + * Invoked when UpdateUAPSDParams REQ failed in WDI and no RSP callback is generated. + */ +void WDA_UpdateUapsdParamsReqCallback(WDI_Status wdiStatus, void* pUserData) +{ + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s, wdiStatus: %d", __func__, wdiStatus); + + if(NULL == pWdaParams) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return; + } + + if(IS_WDI_STATUS_FAILURE(wdiStatus)) + { + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams->wdaMsgParam); + vos_mem_free(pWdaParams); + } + + return; +} /* * FUNCTION: WDA_UpdateUapsdParamsReq * Request to WDI to update UAPSD params (in softAP mode) for a station. @@ -7273,6 +7516,8 @@ VOS_STATUS WDA_UpdateUapsdParamsReq(tWDA_CbContext *pWDA, wdiUpdateUapsdParams->wdiUpdateUapsdInfo.uMaxSpLen = pUpdateUapsdInfo->maxSpLen; wdiUpdateUapsdParams->wdiUpdateUapsdInfo.ucSTAIdx = pUpdateUapsdInfo->staIdx; wdiUpdateUapsdParams->wdiUpdateUapsdInfo.ucUapsdACMask = pUpdateUapsdInfo->uapsdACMask; + wdiUpdateUapsdParams->wdiReqStatusCB = WDA_UpdateUapsdParamsReqCallback; + wdiUpdateUapsdParams->pUserData = pWdaParams; pWdaParams = (tWDA_ReqParams *)vos_mem_malloc(sizeof(tWDA_ReqParams)) ; if(NULL == pWdaParams) @@ -7291,7 +7536,7 @@ VOS_STATUS WDA_UpdateUapsdParamsReq(tWDA_CbContext *pWDA, pWdaParams->pWdaContext = pWDA; wstatus = WDI_UpdateUapsdParamsReq(wdiUpdateUapsdParams, - (WDI_UpdateUapsdParamsCb)WDA_UpdateUapsdParamsReqCallback, + (WDI_UpdateUapsdParamsCb)WDA_UpdateUapsdParamsRespCallback, pWdaParams); if(IS_WDI_STATUS_FAILURE(wstatus)) @@ -7306,10 +7551,10 @@ VOS_STATUS WDA_UpdateUapsdParamsReq(tWDA_CbContext *pWDA, return status; } /* - * FUNCTION: WDA_ConfigureRxpFilterCallback + * FUNCTION: WDA_ConfigureRxpFilterRespCallback * */ -void WDA_ConfigureRxpFilterCallback(WDI_Status wdiStatus, void* pUserData) +void WDA_ConfigureRxpFilterRespCallback(WDI_Status wdiStatus, void* pUserData) { tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData ; VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, @@ -7331,6 +7576,35 @@ void WDA_ConfigureRxpFilterCallback(WDI_Status wdiStatus, void* pUserData) vos_mem_free(pWdaParams); return ; } +/* + * FUNCTION: WDA_ConfigureRxpFilterReqCallback + * Free memory. + * Invoked when ConfigureRXPFilter REQ failed in WDI and no RSP callback is generated. + */ +void WDA_ConfigureRxpFilterReqCallback(WDI_Status wdiStatus, void* pUserData) +{ + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s, wdiStatus: %d", __func__, wdiStatus); + + if(NULL == pWdaParams) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return; + } + + if(IS_WDI_STATUS_FAILURE(wdiStatus)) + { + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams->wdaMsgParam); + vos_mem_free(pWdaParams); + } + + return; +} /* * FUNCTION: WDA_ProcessConfigureRxpFilterReq * @@ -7369,12 +7643,14 @@ VOS_STATUS WDA_ProcessConfigureRxpFilterReq(tWDA_CbContext *pWDA, wdiRxpFilterParams->wdiRxpFilterParam.ucSetMcstBcstFilterSetting = pWlanSuspendParam->configuredMcstBcstFilterSetting; - wdiRxpFilterParams->wdiReqStatusCB = NULL; + wdiRxpFilterParams->wdiReqStatusCB = WDA_ConfigureRxpFilterReqCallback; + wdiRxpFilterParams->pUserData = pWdaParams; + pWdaParams->pWdaContext = pWDA; pWdaParams->wdaMsgParam = pWlanSuspendParam; pWdaParams->wdaWdiApiMsgParam = (void *)wdiRxpFilterParams; wstatus = WDI_ConfigureRxpFilterReq(wdiRxpFilterParams, - (WDI_ConfigureRxpFilterCb)WDA_ConfigureRxpFilterCallback, + (WDI_ConfigureRxpFilterCb)WDA_ConfigureRxpFilterRespCallback, pWdaParams); if(IS_WDI_STATUS_FAILURE(wstatus)) { @@ -7428,51 +7704,15 @@ VOS_STATUS WDA_ProcessWlanSuspendInd(tWDA_CbContext *pWDA, return CONVERT_WDI2VOS_STATUS(wdiStatus) ; } -#ifdef WLAN_FEATURE_11W /* - * FUNCTION: WDA_ProcessExcludeUnecryptInd - * - */ -VOS_STATUS WDA_ProcessExcludeUnecryptInd(tWDA_CbContext *pWDA, - tSirWlanExcludeUnencryptParam *pExclUnencryptParam) + * FUNCTION: WDA_ProcessWlanResumeCallback + * + */ +void WDA_ProcessWlanResumeCallback( + WDI_SuspendResumeRspParamsType *resumeRspParams, + void* pUserData) { - WDI_Status wdiStatus; - WDI_ExcludeUnencryptIndType wdiExclUnencryptParams; - VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, - "------> %s ", __func__); - - wdiExclUnencryptParams.bExcludeUnencrypt = pExclUnencryptParam->excludeUnencrypt; - vos_mem_copy(wdiExclUnencryptParams.bssid, pExclUnencryptParam->bssId, - sizeof(tSirMacAddr)); - - wdiExclUnencryptParams.wdiReqStatusCB = NULL; - wdiExclUnencryptParams.pUserData = pWDA; - - wdiStatus = WDI_ExcludeUnencryptedInd(&wdiExclUnencryptParams); - if(WDI_STATUS_PENDING == wdiStatus) - { - VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, - "Pending received for %s:%d ", __func__, __LINE__ ); - } - else if( WDI_STATUS_SUCCESS_SYNC != wdiStatus ) - { - VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, - "Failure in %s:%d ", __func__, __LINE__ ); - } - vos_mem_free(pExclUnencryptParam); - return CONVERT_WDI2VOS_STATUS(wdiStatus) ; -} -#endif - -/* - * FUNCTION: WDA_ProcessWlanResumeCallback - * - */ -void WDA_ProcessWlanResumeCallback( - WDI_SuspendResumeRspParamsType *resumeRspParams, - void* pUserData) -{ - tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, "<------ %s " ,__func__); if(NULL == pWdaParams) @@ -7545,10 +7785,10 @@ VOS_STATUS WDA_ProcessWlanResumeReq(tWDA_CbContext *pWDA, } /* - * FUNCTION: WDA_SetBeaconFilterReqCallback + * FUNCTION: WDA_SetBeaconFilterRespCallback * */ -void WDA_SetBeaconFilterReqCallback(WDI_Status status, void* pUserData) +void WDA_SetBeaconFilterRespCallback(WDI_Status status, void* pUserData) { tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, @@ -7571,6 +7811,35 @@ void WDA_SetBeaconFilterReqCallback(WDI_Status status, void* pUserData) return ; } +/* + * FUNCTION: WDA_SetBeaconFilterReqCallback + * Free memory. + * Invoked when SetBeaconFilter REQ failed in WDI and no RSP callback is generated. + */ +void WDA_SetBeaconFilterReqCallback(WDI_Status wdiStatus, void* pUserData) +{ + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s, wdiStatus: %d", __func__, wdiStatus); + + if(NULL == pWdaParams) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return; + } + + if(IS_WDI_STATUS_FAILURE(wdiStatus)) + { + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams->wdaMsgParam); + vos_mem_free(pWdaParams); + } + + return; +} /* * FUNCTION: WDA_SetBeaconFilterReq * Request to WDI to send the beacon filtering related information. @@ -7623,7 +7892,9 @@ VOS_STATUS WDA_SetBeaconFilterReq(tWDA_CbContext *pWDA, filterLength = WDI_BEACON_FILTER_LEN; } vos_mem_copy(dstPtr, srcPtr, filterLength); - wdiBeaconFilterInfo->wdiReqStatusCB = NULL; + wdiBeaconFilterInfo->wdiReqStatusCB = WDA_SetBeaconFilterReqCallback; + wdiBeaconFilterInfo->pUserData = pWdaParams; + /* Store param pointer as passed in by caller */ /* store Params pass it to WDI */ pWdaParams->wdaWdiApiMsgParam = wdiBeaconFilterInfo; @@ -7631,7 +7902,7 @@ VOS_STATUS WDA_SetBeaconFilterReq(tWDA_CbContext *pWDA, pWdaParams->wdaMsgParam = pBeaconFilterInfo; status = WDI_SetBeaconFilterReq(wdiBeaconFilterInfo, - (WDI_SetBeaconFilterCb)WDA_SetBeaconFilterReqCallback, pWdaParams); + (WDI_SetBeaconFilterCb)WDA_SetBeaconFilterRespCallback, pWdaParams); if(IS_WDI_STATUS_FAILURE(status)) { VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, @@ -7643,10 +7914,10 @@ VOS_STATUS WDA_SetBeaconFilterReq(tWDA_CbContext *pWDA, return CONVERT_WDI2VOS_STATUS(status) ; } /* - * FUNCTION: WDA_RemBeaconFilterReqCallback + * FUNCTION: WDA_RemBeaconFilterRespCallback * */ -void WDA_RemBeaconFilterReqCallback(WDI_Status status, void* pUserData) +void WDA_RemBeaconFilterRespCallback(WDI_Status status, void* pUserData) { tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData ; @@ -7667,8 +7938,37 @@ void WDA_RemBeaconFilterReqCallback(WDI_Status status, void* pUserData) //print a msg, nothing else to do VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, - "WDA_RemBeaconFilterReqCallback invoked " ); + "WDA_RemBeaconFilterRespCallback invoked " ); return ; +} +/* + * FUNCTION: WDA_RemBeaconFilterReqCallback + * Free memory. + * Invoked when RemBeaconFilter REQ failed in WDI and no RSP callback is generated. + */ +void WDA_RemBeaconFilterReqCallback(WDI_Status wdiStatus, void* pUserData) +{ + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s, wdiStatus: %d", __func__, wdiStatus); + + if(NULL == pWdaParams) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return; + } + + if(IS_WDI_STATUS_FAILURE(wdiStatus)) + { + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams->wdaMsgParam); + vos_mem_free(pWdaParams); + } + + return; } // TODO: PE does not have this feature for now implemented, // but the support for removing beacon filter exists between @@ -7697,14 +7997,6 @@ VOS_STATUS WDA_RemBeaconFilterReq(tWDA_CbContext *pWDA, VOS_ASSERT(0); return VOS_STATUS_E_NOMEM; } - wdiBeaconFilterInfo->wdiBeaconFilterInfo.ucIeCount = - pBeaconFilterInfo->ucIeCount; - //Fill structure with info contained in the ucRemIeId - vos_mem_copy(wdiBeaconFilterInfo->wdiBeaconFilterInfo.ucRemIeId, - pBeaconFilterInfo->ucRemIeId, - wdiBeaconFilterInfo->wdiBeaconFilterInfo.ucIeCount); - wdiBeaconFilterInfo->wdiReqStatusCB = NULL; - pWdaParams = (tWDA_ReqParams *)vos_mem_malloc(sizeof(tWDA_ReqParams)) ; if(NULL == pWdaParams) { @@ -7715,6 +8007,15 @@ VOS_STATUS WDA_RemBeaconFilterReq(tWDA_CbContext *pWDA, vos_mem_free(pBeaconFilterInfo); return VOS_STATUS_E_NOMEM; } + + wdiBeaconFilterInfo->wdiBeaconFilterInfo.ucIeCount = + pBeaconFilterInfo->ucIeCount; + //Fill structure with info contained in the ucRemIeId + vos_mem_copy(wdiBeaconFilterInfo->wdiBeaconFilterInfo.ucRemIeId, + pBeaconFilterInfo->ucRemIeId, + wdiBeaconFilterInfo->wdiBeaconFilterInfo.ucIeCount); + wdiBeaconFilterInfo->wdiReqStatusCB = WDA_RemBeaconFilterReqCallback; + wdiBeaconFilterInfo->pUserData = pWdaParams; /* Store param pointer as passed in by caller */ pWdaParams->wdaMsgParam = pBeaconFilterInfo; @@ -7724,7 +8025,7 @@ VOS_STATUS WDA_RemBeaconFilterReq(tWDA_CbContext *pWDA, pWdaParams->pWdaContext = pWDA; wstatus = WDI_RemBeaconFilterReq(wdiBeaconFilterInfo, - (WDI_RemBeaconFilterCb)WDA_RemBeaconFilterReqCallback, pWdaParams); + (WDI_RemBeaconFilterCb)WDA_RemBeaconFilterRespCallback, pWdaParams); if(IS_WDI_STATUS_FAILURE(wstatus)) { VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, @@ -7737,10 +8038,10 @@ VOS_STATUS WDA_RemBeaconFilterReq(tWDA_CbContext *pWDA, return status; } /* - * FUNCTION: WDA_SetRSSIThresholdsReqCallback + * FUNCTION: WDA_SetRSSIThresholdsRespCallback * */ -void WDA_SetRSSIThresholdsReqCallback(WDI_Status status, void* pUserData) +void WDA_SetRSSIThresholdsRespCallback(WDI_Status status, void* pUserData) { tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, @@ -7758,6 +8059,34 @@ void WDA_SetRSSIThresholdsReqCallback(WDI_Status status, void* pUserData) return ; } +/* + * FUNCTION: WDA_SetRSSIThresholdsReqCallback + * Free memory. + * Invoked when SetRSSIThresholds REQ failed in WDI and no RSP callback is generated. + */ +void WDA_SetRSSIThresholdsReqCallback(WDI_Status wdiStatus, void* pUserData) +{ + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s, wdiStatus: %d", __func__, wdiStatus); + + if(NULL == pWdaParams) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return; + } + + if(IS_WDI_STATUS_FAILURE(wdiStatus)) + { + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams); + } + + return; +} /* * FUNCTION: WDA_SetRSSIThresholdsReq * Request to WDI to set the RSSI thresholds (sta mode). @@ -7800,7 +8129,8 @@ VOS_STATUS WDA_SetRSSIThresholdsReq(tpAniSirGlobal pMac, tSirRSSIThresholds *pBm wdiRSSIThresholdsInfo->wdiRSSIThresholdsInfo.bRssiThres1PosNotify = pBmpsThresholds->bRssiThres1PosNotify; wdiRSSIThresholdsInfo->wdiRSSIThresholdsInfo.bRssiThres2PosNotify = pBmpsThresholds->bRssiThres2PosNotify; wdiRSSIThresholdsInfo->wdiRSSIThresholdsInfo.bRssiThres3PosNotify = pBmpsThresholds->bRssiThres3PosNotify; - wdiRSSIThresholdsInfo->wdiReqStatusCB = NULL; + wdiRSSIThresholdsInfo->wdiReqStatusCB = WDA_SetRSSIThresholdsReqCallback; + wdiRSSIThresholdsInfo->pUserData = pWdaParams; pVosContext = vos_get_global_context(VOS_MODULE_ID_PE, (void *)pMac); pWDA = vos_get_context( VOS_MODULE_ID_WDA, pVosContext ); @@ -7810,7 +8140,7 @@ VOS_STATUS WDA_SetRSSIThresholdsReq(tpAniSirGlobal pMac, tSirRSSIThresholds *pBm pWdaParams->pWdaContext = pWDA; pWdaParams->wdaMsgParam = pBmpsThresholds; wstatus = WDI_SetRSSIThresholdsReq(wdiRSSIThresholdsInfo, - (WDI_SetRSSIThresholdsCb)WDA_SetRSSIThresholdsReqCallback, pWdaParams); + (WDI_SetRSSIThresholdsCb)WDA_SetRSSIThresholdsRespCallback, pWdaParams); if(IS_WDI_STATUS_FAILURE(wstatus)) { VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, @@ -7851,7 +8181,8 @@ void WDA_HostOffloadRespCallback(WDI_Status status, void* pUserData) } /* * FUNCTION: WDA_HostOffloadReqCallback - * + * Free memory. + * Invoked when HostOffload REQ failed in WDI and no RSP callback is generated. */ void WDA_HostOffloadReqCallback(WDI_Status wdiStatus, void* pUserData) { @@ -7982,6 +8313,8 @@ VOS_STATUS WDA_ProcessHostOffloadReq(tWDA_CbContext *pWDA, { wdiHostOffloadInfo->wdiNsOffloadParams.targetIPv6Addr2Valid = 0; } + wdiHostOffloadInfo->wdiNsOffloadParams.slotIdx = + pHostOffloadParams->nsOffloadInfo.slotIdx; break; #endif //WLAN_NS_OFFLOAD default: @@ -8018,10 +8351,10 @@ VOS_STATUS WDA_ProcessHostOffloadReq(tWDA_CbContext *pWDA, }/*WDA_HostOffloadReq*/ /* - * FUNCTION: WDA_KeepAliveReqCallback + * FUNCTION: WDA_KeepAliveRespCallback * */ -void WDA_KeepAliveReqCallback(WDI_Status status, void* pUserData) +void WDA_KeepAliveRespCallback(WDI_Status status, void* pUserData) { tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData ; @@ -8039,12 +8372,41 @@ void WDA_KeepAliveReqCallback(WDI_Status status, void* pUserData) vos_mem_free(pWdaParams->wdaWdiApiMsgParam); vos_mem_free(pWdaParams->wdaMsgParam); vos_mem_free(pWdaParams); - + //print a msg, nothing else to do VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, - "WDA_KeepAliveReqCallback invoked " ); + "WDA_KeepAliveRespCallback invoked " ); return ; } +/* + * FUNCTION: WDA_KeepAliveReqCallback + * Free memory. + * Invoked when KeepAlive REQ failed in WDI and no RSP callback is generated. + */ +void WDA_KeepAliveReqCallback(WDI_Status wdiStatus, void* pUserData) +{ + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s, wdiStatus: %d", __func__, wdiStatus); + + if(NULL == pWdaParams) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return; + } + + if(IS_WDI_STATUS_FAILURE(wdiStatus)) + { + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams->wdaMsgParam); + vos_mem_free(pWdaParams); + } + + return; +} /* * FUNCTION: WDA_ProcessKeepAliveReq * Request to WDI to send Keep Alive packets to minimize unnecessary host @@ -8115,7 +8477,8 @@ VOS_STATUS WDA_ProcessKeepAliveReq(tWDA_CbContext *pWDA, SIR_MAC_ADDR_LEN, 0); } - wdiKeepAliveInfo->wdiReqStatusCB = NULL; + wdiKeepAliveInfo->wdiReqStatusCB = WDA_KeepAliveReqCallback; + wdiKeepAliveInfo->pUserData = pWdaParams; /* Store param pointer as passed in by caller */ pWdaParams->wdaMsgParam = pKeepAliveParams; @@ -8146,7 +8509,7 @@ VOS_STATUS WDA_ProcessKeepAliveReq(tWDA_CbContext *pWDA, wdiKeepAliveInfo->wdiKeepAliveInfo.ucTimePeriod, wdiKeepAliveInfo->wdiKeepAliveInfo.ucPacketType); wstatus = WDI_KeepAliveReq(wdiKeepAliveInfo, - (WDI_KeepAliveCb)WDA_KeepAliveReqCallback, pWdaParams); + (WDI_KeepAliveCb)WDA_KeepAliveRespCallback, pWdaParams); if(IS_WDI_STATUS_FAILURE(wstatus)) { @@ -8161,10 +8524,10 @@ VOS_STATUS WDA_ProcessKeepAliveReq(tWDA_CbContext *pWDA, }/*WDA_KeepAliveReq*/ /* - * FUNCTION: WDA_WowlAddBcPtrnReqCallback + * FUNCTION: WDA_WowlAddBcPtrnRespCallback * */ -void WDA_WowlAddBcPtrnReqCallback( +void WDA_WowlAddBcPtrnRespCallback( WDI_WowlAddBcPtrnRspParamsType *pWdiWowlAddBcstPtrRsp, void* pUserData) { @@ -8183,6 +8546,36 @@ void WDA_WowlAddBcPtrnReqCallback( vos_mem_free(pWdaParams) ; return ; } +/* + * FUNCTION: WDA_WowlAddBcPtrnReqCallback + * Free memory. + * Invoked when WOWLAddBCPTRN REQ failed in WDI and no RSP callback is generated. + */ +void WDA_WowlAddBcPtrnReqCallback(WDI_Status wdiStatus, void* pUserData) +{ + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s, wdiStatus: %d", __func__, wdiStatus); + + if(NULL == pWdaParams) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return; + } + + if(IS_WDI_STATUS_FAILURE(wdiStatus)) + { + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams->wdaMsgParam); + vos_mem_free(pWdaParams); + } + + return; +} + /* * FUNCTION: WDA_ProcessWowlAddBcPtrnReq * Request to WDI to add WOWL Bcast pattern @@ -8251,14 +8644,15 @@ VOS_STATUS WDA_ProcessWowlAddBcPtrnReq(tWDA_CbContext *pWDA, vos_mem_copy(wdiWowlAddBcPtrnInfo->wdiWowlAddBcPtrnInfo.bssId, pWowlAddBcPtrnParams->bssId, sizeof(wpt_macAddr)); - wdiWowlAddBcPtrnInfo->wdiReqStatusCB = NULL; + wdiWowlAddBcPtrnInfo->wdiReqStatusCB = WDA_WowlAddBcPtrnReqCallback; + wdiWowlAddBcPtrnInfo->pUserData = pWdaParams; /* Store param pointer as passed in by caller */ /* store Params pass it to WDI */ pWdaParams->wdaWdiApiMsgParam = wdiWowlAddBcPtrnInfo; pWdaParams->pWdaContext = pWDA; pWdaParams->wdaMsgParam = pWowlAddBcPtrnParams; wstatus = WDI_WowlAddBcPtrnReq(wdiWowlAddBcPtrnInfo, - (WDI_WowlAddBcPtrnCb)WDA_WowlAddBcPtrnReqCallback, pWdaParams); + (WDI_WowlAddBcPtrnCb)WDA_WowlAddBcPtrnRespCallback, pWdaParams); if(IS_WDI_STATUS_FAILURE(wstatus)) { VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, @@ -8272,10 +8666,10 @@ VOS_STATUS WDA_ProcessWowlAddBcPtrnReq(tWDA_CbContext *pWDA, }/*WDA_ProcessWowlAddBcPtrnReq*/ /* - * FUNCTION: WDA_WowlDelBcPtrnReqCallback + * FUNCTION: WDA_WowlDelBcPtrnRespCallback * */ -void WDA_WowlDelBcPtrnReqCallback( +void WDA_WowlDelBcPtrnRespCallback( WDI_WowlDelBcPtrnRspParamsType *pWdiWowlDelBcstPtrRsp, void* pUserData) { @@ -8294,6 +8688,35 @@ void WDA_WowlDelBcPtrnReqCallback( vos_mem_free(pWdaParams) ; return ; } +/* + * FUNCTION: WDA_WowlDelBcPtrnReqCallback + * Free memory. + * Invoked when WOWLDelBCPTRN REQ failed in WDI and no RSP callback is generated. + */ +void WDA_WowlDelBcPtrnReqCallback(WDI_Status wdiStatus, void* pUserData) +{ + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s, wdiStatus: %d", __func__, wdiStatus); + + if(NULL == pWdaParams) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return; + } + + if(IS_WDI_STATUS_FAILURE(wdiStatus)) + { + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams->wdaMsgParam); + vos_mem_free(pWdaParams); + } + + return; +} /* * FUNCTION: WDA_ProcessWowlDelBcPtrnReq * Request to WDI to delete WOWL Bcast pattern @@ -8331,14 +8754,15 @@ VOS_STATUS WDA_ProcessWowlDelBcPtrnReq(tWDA_CbContext *pWDA, vos_mem_copy(wdiWowlDelBcPtrnInfo->wdiWowlDelBcPtrnInfo.bssId, pWowlDelBcPtrnParams->bssId, sizeof(wpt_macAddr)); - wdiWowlDelBcPtrnInfo->wdiReqStatusCB = NULL; + wdiWowlDelBcPtrnInfo->wdiReqStatusCB = WDA_WowlDelBcPtrnReqCallback; + wdiWowlDelBcPtrnInfo->pUserData = pWdaParams; /* Store param pointer as passed in by caller */ /* store Params pass it to WDI */ pWdaParams->wdaWdiApiMsgParam = wdiWowlDelBcPtrnInfo; pWdaParams->pWdaContext = pWDA; pWdaParams->wdaMsgParam = pWowlDelBcPtrnParams; wstatus = WDI_WowlDelBcPtrnReq(wdiWowlDelBcPtrnInfo, - (WDI_WowlDelBcPtrnCb)WDA_WowlDelBcPtrnReqCallback, pWdaParams); + (WDI_WowlDelBcPtrnCb)WDA_WowlDelBcPtrnRespCallback, pWdaParams); if(IS_WDI_STATUS_FAILURE(wstatus)) { VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, @@ -8352,10 +8776,10 @@ VOS_STATUS WDA_ProcessWowlDelBcPtrnReq(tWDA_CbContext *pWDA, }/*WDA_ProcessWowlDelBcPtrnReq*/ /* - * FUNCTION: WDA_WowlEnterReqCallback + * FUNCTION: WDA_WowlEnterRespCallback * */ -void WDA_WowlEnterReqCallback(WDI_WowlEnterRspParamsType *pwdiWowlEnterRspParam, void* pUserData) +void WDA_WowlEnterRespCallback(WDI_WowlEnterRspParamsType *pwdiWowlEnterRspParam, void* pUserData) { tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; tWDA_CbContext *pWDA; @@ -8382,6 +8806,41 @@ void WDA_WowlEnterReqCallback(WDI_WowlEnterRspParamsType *pwdiWowlEnterRspParam, WDA_SendMsg(pWDA, WDA_WOWL_ENTER_RSP, (void *)pWowlEnterParams , 0) ; return ; } +/* + * FUNCTION: WDA_WowlEnterReqCallback + * Free memory and send WOWL Enter RSP back to PE. + * Invoked when WOWL Enter REQ failed in WDI and no RSP callback is generated. + */ +void WDA_WowlEnterReqCallback(WDI_Status wdiStatus, void* pUserData) +{ + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; + tWDA_CbContext *pWDA; + tSirHalWowlEnterParams *pWowlEnterParams; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s, wdiStatus: %d", __func__, wdiStatus); + + if(NULL == pWdaParams) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return; + } + + pWDA = (tWDA_CbContext *)pWdaParams->pWdaContext; + pWowlEnterParams = (tSirHalWowlEnterParams *)pWdaParams->wdaMsgParam; + pWowlEnterParams->status = wdiStatus; + + if(IS_WDI_STATUS_FAILURE(wdiStatus)) + { + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams); + WDA_SendMsg(pWDA, WDA_WOWL_ENTER_RSP, (void *)pWowlEnterParams , 0); + } + + return; +} /* * FUNCTION: WDA_ProcessWowlEnterReq * Request to WDI to enter WOWL @@ -8452,14 +8911,15 @@ VOS_STATUS WDA_ProcessWowlEnterReq(tWDA_CbContext *pWDA, wdiWowlEnterInfo->wdiWowlEnterInfo.bssIdx = pWowlEnterParams->bssIdx; - wdiWowlEnterInfo->wdiReqStatusCB = NULL; + wdiWowlEnterInfo->wdiReqStatusCB = WDA_WowlEnterReqCallback; + wdiWowlEnterInfo->pUserData = pWdaParams; /* Store param pointer as passed in by caller */ /* store Params pass it to WDI */ pWdaParams->wdaWdiApiMsgParam = wdiWowlEnterInfo; pWdaParams->pWdaContext = pWDA; pWdaParams->wdaMsgParam = pWowlEnterParams; wstatus = WDI_WowlEnterReq(wdiWowlEnterInfo, - (WDI_WowlEnterReqCb)WDA_WowlEnterReqCallback, pWdaParams); + (WDI_WowlEnterReqCb)WDA_WowlEnterRespCallback, pWdaParams); if(IS_WDI_STATUS_FAILURE(wstatus)) { VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, @@ -8473,10 +8933,10 @@ VOS_STATUS WDA_ProcessWowlEnterReq(tWDA_CbContext *pWDA, }/*WDA_ProcessWowlEnterReq*/ /* - * FUNCTION: WDA_WowlExitReqCallback + * FUNCTION: WDA_WowlExitRespCallback * */ -void WDA_WowlExitReqCallback( WDI_WowlExitRspParamsType *pwdiWowlExitRsp, void* pUserData) +void WDA_WowlExitRespCallback( WDI_WowlExitRspParamsType *pwdiWowlExitRsp, void* pUserData) { tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; tWDA_CbContext *pWDA; @@ -8504,6 +8964,41 @@ void WDA_WowlExitReqCallback( WDI_WowlExitRspParamsType *pwdiWowlExitRsp, void* WDA_SendMsg(pWDA, WDA_WOWL_EXIT_RSP, (void *)pWowlExitParams, 0) ; return ; } +/* + * FUNCTION: WDA_WowlExitReqCallback + * Free memory and send WOWL Exit RSP back to PE. + * Invoked when WOWL Exit REQ failed in WDI and no RSP callback is generated. + */ +void WDA_WowlExitReqCallback(WDI_Status wdiStatus, void* pUserData) +{ + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; + tWDA_CbContext *pWDA; + tSirHalWowlExitParams *pWowlExitParams; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s, wdiStatus: %d", __func__, wdiStatus); + + if(NULL == pWdaParams) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return; + } + + pWDA = (tWDA_CbContext *)pWdaParams->pWdaContext; + pWowlExitParams = (tSirHalWowlExitParams *)pWdaParams->wdaMsgParam; + pWowlExitParams->status = wdiStatus; + + if(IS_WDI_STATUS_FAILURE(wdiStatus)) + { + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams); + WDA_SendMsg(pWDA, WDA_WOWL_EXIT_RSP, (void *)pWowlExitParams, 0); + } + + return; +} /* * FUNCTION: WDA_ProcessWowlExitReq * Request to WDI to add WOWL Bcast pattern @@ -8539,7 +9034,8 @@ VOS_STATUS WDA_ProcessWowlExitReq(tWDA_CbContext *pWDA, wdiWowlExitInfo->wdiWowlExitInfo.bssIdx = pWowlExitParams->bssIdx; - wdiWowlExitInfo->wdiReqStatusCB = NULL; + wdiWowlExitInfo->wdiReqStatusCB = WDA_WowlExitReqCallback; + wdiWowlExitInfo->pUserData = pWdaParams; /* Store param pointer as passed in by caller */ /* store Params pass it to WDI */ @@ -8548,7 +9044,7 @@ VOS_STATUS WDA_ProcessWowlExitReq(tWDA_CbContext *pWDA, pWdaParams->wdaMsgParam = pWowlExitParams; wstatus = WDI_WowlExitReq(wdiWowlExitInfo, - (WDI_WowlExitReqCb)WDA_WowlExitReqCallback, pWdaParams); + (WDI_WowlExitReqCb)WDA_WowlExitRespCallback, pWdaParams); if(IS_WDI_STATUS_FAILURE(wstatus)) { @@ -8770,10 +9266,10 @@ VOS_STATUS WDA_ProcessFlushAcReq(tWDA_CbContext *pWDA, return CONVERT_WDI2VOS_STATUS(status) ; } /* - * FUNCTION: WDA_BtAmpEventReqCallback + * FUNCTION: WDA_BtAmpEventRespCallback * */ -void WDA_BtAmpEventReqCallback(WDI_Status status, void* pUserData) +void WDA_BtAmpEventRespCallback(WDI_Status status, void* pUserData) { tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; tWDA_CbContext *pWDA; @@ -8804,7 +9300,46 @@ void WDA_BtAmpEventReqCallback(WDI_Status status, void* pUserData) */ return ; } +/* + * FUNCTION: WDA_BtAmpEventReqCallback + * Free memory. + * Invoked when BTAMPEvent REQ failed in WDI and no RSP callback is generated. + */ +void WDA_BtAmpEventReqCallback(WDI_Status wdiStatus, void* pUserData) +{ + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; + tWDA_CbContext *pWDA; + WDI_BtAmpEventParamsType *wdiBtAmpEventParam; + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s, wdiStatus: %d", __func__, wdiStatus); + + if(NULL == pWdaParams) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return; + } + + pWDA = (tWDA_CbContext *)pWdaParams->pWdaContext; + wdiBtAmpEventParam = (WDI_BtAmpEventParamsType *)pWdaParams->wdaWdiApiMsgParam; + + if(BTAMP_EVENT_CONNECTION_TERMINATED == + wdiBtAmpEventParam->wdiBtAmpEventInfo.ucBtAmpEventType) + { + pWDA->wdaAmpSessionOn = VOS_FALSE; + } + + if(IS_WDI_STATUS_FAILURE(wdiStatus)) + { + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams->wdaMsgParam); + vos_mem_free(pWdaParams); + } + + return; +} /* * FUNCTION: WDA_ProcessBtAmpEventReq * Request to WDI to Update with BT AMP events. @@ -8837,14 +9372,15 @@ VOS_STATUS WDA_ProcessBtAmpEventReq(tWDA_CbContext *pWDA, } wdiBtAmpEventParam->wdiBtAmpEventInfo.ucBtAmpEventType = pBtAmpEventParams->btAmpEventType; - wdiBtAmpEventParam->wdiReqStatusCB = NULL; + wdiBtAmpEventParam->wdiReqStatusCB = WDA_BtAmpEventReqCallback; + wdiBtAmpEventParam->pUserData = pWdaParams; /* Store BT AMP event pointer, as this will be used for response */ /* store Params pass it to WDI */ pWdaParams->pWdaContext = pWDA; pWdaParams->wdaMsgParam = pBtAmpEventParams; pWdaParams->wdaWdiApiMsgParam = wdiBtAmpEventParam; status = WDI_BtAmpEventReq(wdiBtAmpEventParam, - (WDI_BtAmpEventRspCb)WDA_BtAmpEventReqCallback, pWdaParams); + (WDI_BtAmpEventRspCb)WDA_BtAmpEventRespCallback, pWdaParams); if(IS_WDI_STATUS_FAILURE(status)) { VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, @@ -8872,7 +9408,7 @@ void WDA_FTMCommandReqCallback(void *ftmCmdRspData, if((NULL == pWDA) || (NULL == ftmCmdRspData)) { VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, - "%s, invalid input 0x%x, 0x%x",__func__, pWDA, ftmCmdRspData); + "%s, invalid input %p, %p",__func__, pWDA, ftmCmdRspData); return; } /* Release Current FTM Command Request */ @@ -9032,10 +9568,10 @@ VOS_STATUS WDA_ProcessStartOemDataReq(tWDA_CbContext *pWDA, } #endif /* FEATURE_OEM_DATA_SUPPORT */ /* - * FUNCTION: WDA_SetTxPerTrackingReqCallback + * FUNCTION: WDA_SetTxPerTrackingRespCallback * */ -void WDA_SetTxPerTrackingReqCallback(WDI_Status status, void* pUserData) +void WDA_SetTxPerTrackingRespCallback(WDI_Status status, void* pUserData) { tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, @@ -9047,25 +9583,48 @@ void WDA_SetTxPerTrackingReqCallback(WDI_Status status, void* pUserData) VOS_ASSERT(0) ; return ; } - - if(NULL != pWdaParams->wdaMsgParam) + + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams->wdaMsgParam); + vos_mem_free(pWdaParams); + + return ; +} +/* + * FUNCTION: WDA_SetTxPerTrackingReqCallback + * Free memory. + * Invoked when SetTXPerTracking REQ failed in WDI and no RSP callback is generated. + */ +void WDA_SetTxPerTrackingReqCallback(WDI_Status wdiStatus, void* pUserData) +{ + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s, wdiStatus: %d", __func__, wdiStatus); + + if(NULL == pWdaParams) { - vos_mem_free(pWdaParams->wdaMsgParam); + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return; } - if(NULL != pWdaParams->wdaWdiApiMsgParam) + + if(IS_WDI_STATUS_FAILURE(wdiStatus)) { vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams->wdaMsgParam); + vos_mem_free(pWdaParams); } - - vos_mem_free(pWdaParams); - return ; + + return; } #ifdef WLAN_FEATURE_GTK_OFFLOAD /* - * FUNCTION: WDA_HostOffloadReqCallback + * FUNCTION: WDA_GTKOffloadRespCallback * */ -void WDA_GTKOffloadReqCallback( WDI_GtkOffloadRspParams *pwdiGtkOffloadRsparams, +void WDA_GTKOffloadRespCallback( WDI_GtkOffloadRspParams *pwdiGtkOffloadRsparams, void* pUserData) { tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; @@ -9081,11 +9640,39 @@ void WDA_GTKOffloadReqCallback( WDI_GtkOffloadRspParams *pwdiGtkOffloadRsparams //print a msg, nothing else to do VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, - "WDA_GTKOffloadReqCallback invoked " ); + "WDA_GTKOffloadRespCallback invoked " ); return ; } +/* + * FUNCTION: WDA_GTKOffloadReqCallback + * Free memory. + * Invoked when GTKOffload REQ failed in WDI and no RSP callback is generated. + */ +void WDA_GTKOffloadReqCallback(WDI_Status wdiStatus, void* pUserData) +{ + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s, wdiStatus: %d", __func__, wdiStatus); + + if(NULL == pWdaParams) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return; + } + if(IS_WDI_STATUS_FAILURE(wdiStatus)) + { + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams->wdaMsgParam); + vos_mem_free(pWdaParams); + } + + return; +} /* * FUNCTION: WDA_ProcessGTKOffloadReq * Request to WDI to set the filter to minimize unnecessary host wakeup due @@ -9137,7 +9724,8 @@ VOS_STATUS WDA_ProcessGTKOffloadReq(tWDA_CbContext *pWDA, vos_mem_copy(&(wdiGtkOffloadReqMsg->gtkOffloadReqParams.ullKeyReplayCounter), &(pGtkOffloadParams->ullKeyReplayCounter), sizeof(v_U64_t)); - wdiGtkOffloadReqMsg->wdiReqStatusCB = NULL; + wdiGtkOffloadReqMsg->wdiReqStatusCB = WDA_GTKOffloadReqCallback; + wdiGtkOffloadReqMsg->pUserData = pWdaParams; /* Store Params pass it to WDI */ @@ -9146,7 +9734,7 @@ VOS_STATUS WDA_ProcessGTKOffloadReq(tWDA_CbContext *pWDA, /* Store param pointer as passed in by caller */ pWdaParams->wdaMsgParam = pGtkOffloadParams; - status = WDI_GTKOffloadReq(wdiGtkOffloadReqMsg, (WDI_GtkOffloadCb)WDA_GTKOffloadReqCallback, pWdaParams); + status = WDI_GTKOffloadReq(wdiGtkOffloadReqMsg, (WDI_GtkOffloadCb)WDA_GTKOffloadRespCallback, pWdaParams); if(IS_WDI_STATUS_FAILURE(status)) { @@ -9161,16 +9749,16 @@ VOS_STATUS WDA_ProcessGTKOffloadReq(tWDA_CbContext *pWDA, } /* - * FUNCTION: WDA_GtkOffloadGetInfoCallback + * FUNCTION: WDA_GtkOffloadGetInfoRespCallback * */ -void WDA_GtkOffloadGetInfoCallback( WDI_GtkOffloadGetInfoRspParams *pwdiGtkOffloadGetInfoRsparams, +void WDA_GtkOffloadGetInfoRespCallback( WDI_GtkOffloadGetInfoRspParams *pwdiGtkOffloadGetInfoRsparams, void * pUserData) { tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; tWDA_CbContext *pWDA; tpSirGtkOffloadGetInfoRspParams pGtkOffloadGetInfoReq; - tpSirGtkOffloadGetInfoRspParams pGtkOffloadGetInfoRsp = vos_mem_malloc(sizeof(tpSirGtkOffloadGetInfoRspParams)) ; + tpSirGtkOffloadGetInfoRspParams pGtkOffloadGetInfoRsp = vos_mem_malloc(sizeof(tSirGtkOffloadGetInfoRspParams)) ; vos_msg_t vosMsg; VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, @@ -9211,6 +9799,44 @@ void WDA_GtkOffloadGetInfoCallback( WDI_GtkOffloadGetInfoRspParams *pwdiGtkOfflo vos_mem_free(pWdaParams->wdaMsgParam) ; vos_mem_free(pWdaParams->wdaWdiApiMsgParam); vos_mem_free(pWdaParams) ; + + return; +} +/* + * FUNCTION: WDA_GtkOffloadGetInfoReqCallback + * Free memory and send RSP back to SME. + * Invoked when GTKOffloadGetInfo REQ failed in WDI and no RSP callback is generated. + */ +void WDA_GtkOffloadGetInfoReqCallback(WDI_Status wdiStatus, void * pUserData) +{ + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; + vos_msg_t vosMsg; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s, wdiStatus: %d", __func__, wdiStatus); + + if(NULL == pWdaParams) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return; + } + + /* VOS message wrapper */ + vosMsg.type = eWNI_PMC_GTK_OFFLOAD_GETINFO_RSP; + vosMsg.bodyptr = NULL; + vosMsg.bodyval = 0; + + if(IS_WDI_STATUS_FAILURE(wdiStatus)) + { + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams->wdaMsgParam); + vos_mem_free(pWdaParams); + vos_mq_post_message(VOS_MQ_ID_SME, (vos_msg_t*)&vosMsg); + } + + return; } #endif @@ -9254,7 +9880,8 @@ VOS_STATUS WDA_ProcessSetTxPerTrackingReq(tWDA_CbContext *pWDA, tSirTxPerTrackin pTxPerTrackingParams->ucTxPerTrackingRatio; pwdiSetTxPerTrackingReqParams->wdiTxPerTrackingParam.uTxPerTrackingWatermark = pTxPerTrackingParams->uTxPerTrackingWatermark; - pwdiSetTxPerTrackingReqParams->wdiReqStatusCB = NULL; + pwdiSetTxPerTrackingReqParams->wdiReqStatusCB = WDA_SetTxPerTrackingReqCallback; + pwdiSetTxPerTrackingReqParams->pUserData = pWdaParams; /* Store param pointer as passed in by caller */ /* store Params pass it to WDI Ideally, the memory allocated here will be free at WDA_SetTxPerTrackingReqCallback */ @@ -9262,7 +9889,7 @@ VOS_STATUS WDA_ProcessSetTxPerTrackingReq(tWDA_CbContext *pWDA, tSirTxPerTrackin pWdaParams->pWdaContext = pWDA; pWdaParams->wdaMsgParam = pTxPerTrackingParams; wstatus = WDI_SetTxPerTrackingReq(pwdiSetTxPerTrackingReqParams, - (WDI_SetTxPerTrackingRspCb)WDA_SetTxPerTrackingReqCallback, pWdaParams); + (WDI_SetTxPerTrackingRspCb)WDA_SetTxPerTrackingRespCallback, pWdaParams); if(IS_WDI_STATUS_FAILURE(wstatus)) { VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, @@ -9407,7 +10034,8 @@ VOS_STATUS WDA_ProcessGTKOffloadGetInfoReq(tWDA_CbContext *pWDA, return VOS_STATUS_E_NOMEM; } - pwdiGtkOffloadGetInfoReqMsg->wdiReqStatusCB = NULL; + pwdiGtkOffloadGetInfoReqMsg->wdiReqStatusCB = WDA_GtkOffloadGetInfoReqCallback; + pwdiGtkOffloadGetInfoReqMsg->pUserData = pWdaParams; /* Store Params pass it to WDI */ pWdaParams->wdaWdiApiMsgParam = (void *)pwdiGtkOffloadGetInfoReqMsg; @@ -9418,7 +10046,7 @@ VOS_STATUS WDA_ProcessGTKOffloadGetInfoReq(tWDA_CbContext *pWDA, vos_mem_copy(pwdiGtkOffloadGetInfoReqMsg->WDI_GtkOffloadGetInfoReqParams.bssId, pGtkOffloadGetInfoRsp->bssId, sizeof (wpt_macAddr)); - status = WDI_GTKOffloadGetInfoReq(pwdiGtkOffloadGetInfoReqMsg, (WDI_GtkOffloadGetInfoCb)WDA_GtkOffloadGetInfoCallback, pWdaParams); + status = WDI_GTKOffloadGetInfoReq(pwdiGtkOffloadGetInfoReqMsg, (WDI_GtkOffloadGetInfoCb)WDA_GtkOffloadGetInfoRespCallback, pWdaParams); if(IS_WDI_STATUS_FAILURE(status)) { @@ -9483,7 +10111,7 @@ VOS_STATUS WDA_TxComplete( v_PVOID_t pVosContext, vos_pkt_t *pData, else { VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_WARN, - "%s:packet (0x%X) is already freed", + "%s:packet (%p) is already freed", __func__, pData); //Return from here since we reaching here because the packet already timeout return status; @@ -9529,14 +10157,14 @@ VOS_STATUS WDA_TxPacket(tWDA_CbContext *pWDA, if((NULL == pWDA)||(NULL == pFrmBuf)) { VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, - "%s:pWDA %x or pFrmBuf %x is NULL", + "%s:pWDA %p or pFrmBuf %p is NULL", __func__,pWDA,pFrmBuf); VOS_ASSERT(0); return VOS_STATUS_E_FAILURE; } VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO_HIGH, - "Tx Mgmt Frame Subtype: %d alloc(%x)\n", pFc->subType, pFrmBuf); + "Tx Mgmt Frame Subtype: %d alloc(%p)\n", pFc->subType, pFrmBuf); pMac = (tpAniSirGlobal )VOS_GET_MAC_CTXT(pWDA->pVosContext); if(NULL == pMac) { @@ -10255,6 +10883,13 @@ VOS_STATUS WDA_McProcessMsg( v_CONTEXT_t pVosContext, vos_msg_t *pMsg ) break; } #endif // FEATURE_WLAN_SCAN_PNO +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + case WDA_ROAM_SCAN_OFFLOAD_REQ: + { + WDA_ProcessRoamScanOffloadReq(pWDA, (tSirRoamOffloadScanReq *)pMsg->bodyptr); + break; + } +#endif case WDA_SET_TX_PER_TRACKING_REQ: { WDA_ProcessSetTxPerTrackingReq(pWDA, (tSirTxPerTrackingParam *)pMsg->bodyptr); @@ -10330,13 +10965,6 @@ VOS_STATUS WDA_McProcessMsg( v_CONTEXT_t pVosContext, vos_msg_t *pMsg ) " 11AC Feature is Not Supported \n"); break; } -#endif -#ifdef WLAN_FEATURE_11W - case WDA_EXCLUDE_UNENCRYPTED_IND: - { - WDA_ProcessExcludeUnecryptInd(pWDA, (tSirWlanExcludeUnencryptParam *)pMsg->bodyptr); - break; - } #endif default: { @@ -10643,7 +11271,11 @@ void WDA_lowLevelIndCallback(WDI_LowLevelIndType *wdiLowLevelInd, case WDI_PREF_NETWORK_FOUND_IND: { vos_msg_t vosMsg; - tSirPrefNetworkFoundInd *pPrefNetworkFoundInd = (tSirPrefNetworkFoundInd *)vos_mem_malloc(sizeof(tSirPrefNetworkFoundInd)); + v_U32_t size = sizeof(tSirPrefNetworkFoundInd) + + wdiLowLevelInd->wdiIndicationData.wdiPrefNetworkFoundInd.frameLength; + tSirPrefNetworkFoundInd *pPrefNetworkFoundInd = + (tSirPrefNetworkFoundInd *)vos_mem_malloc(size); + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, "Received WDI_PREF_NETWORK_FOUND_IND from WDI"); if (NULL == pPrefNetworkFoundInd) @@ -10655,7 +11287,7 @@ void WDA_lowLevelIndCallback(WDI_LowLevelIndType *wdiLowLevelInd, } /* Message Header */ pPrefNetworkFoundInd->mesgType = eWNI_SME_PREF_NETWORK_FOUND_IND; - pPrefNetworkFoundInd->mesgLen = sizeof(*pPrefNetworkFoundInd); + pPrefNetworkFoundInd->mesgLen = size; /* Info from WDI Indication */ pPrefNetworkFoundInd->ssId.length = @@ -10664,6 +11296,21 @@ void WDA_lowLevelIndCallback(WDI_LowLevelIndType *wdiLowLevelInd, vos_mem_copy( pPrefNetworkFoundInd->ssId.ssId, wdiLowLevelInd->wdiIndicationData.wdiPrefNetworkFoundInd.ssId.sSSID, pPrefNetworkFoundInd->ssId.length); + if (NULL != + wdiLowLevelInd->wdiIndicationData.wdiPrefNetworkFoundInd.pData) + { + pPrefNetworkFoundInd->frameLength = + wdiLowLevelInd->wdiIndicationData.wdiPrefNetworkFoundInd.frameLength; + vos_mem_copy( pPrefNetworkFoundInd->data, + wdiLowLevelInd->wdiIndicationData.wdiPrefNetworkFoundInd.pData, + pPrefNetworkFoundInd->frameLength); + wpalMemoryFree(wdiLowLevelInd->wdiIndicationData.wdiPrefNetworkFoundInd.pData); + wdiLowLevelInd->wdiIndicationData.wdiPrefNetworkFoundInd.pData = NULL; + } + else + { + pPrefNetworkFoundInd->frameLength = 0; + } pPrefNetworkFoundInd ->rssi = wdiLowLevelInd->wdiIndicationData.wdiPrefNetworkFoundInd.rssi; /* VOS message wrapper */ vosMsg.type = eWNI_SME_PREF_NETWORK_FOUND_IND; @@ -11284,66 +11931,108 @@ eHalStatus WDA_SetRegDomain(void * clientCtxt, v_REGDOMAIN_t regId) #ifdef FEATURE_WLAN_SCAN_PNO /* - * FUNCTION: WDA_PNOScanReqCallback + * FUNCTION: WDA_PNOScanRespCallback * */ -void WDA_PNOScanReqCallback(WDI_Status status, void* pUserData) +void WDA_PNOScanRespCallback(WDI_Status status, void* pUserData) { tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, "<------ %s " ,__func__); - if(NULL == pWdaParams) + if(NULL == pWdaParams) { VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, "%s: pWdaParams received NULL", __func__); VOS_ASSERT(0) ; return ; } - if( pWdaParams != NULL ) + + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams->wdaMsgParam); + vos_mem_free(pWdaParams); + + return ; +} +/* + * FUNCTION: WDA_PNOScanReqCallback + * Free memory. + * Invoked when PNOScan REQ failed in WDI and no RSP callback is generated. + */ +void WDA_PNOScanReqCallback(WDI_Status wdiStatus, void* pUserData) +{ + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s, wdiStatus: %d", __func__, wdiStatus); + + if(NULL == pWdaParams) { - if( pWdaParams->wdaWdiApiMsgParam != NULL ) - { - vos_mem_free(pWdaParams->wdaWdiApiMsgParam); - } - if( pWdaParams->wdaMsgParam != NULL) - { - vos_mem_free(pWdaParams->wdaMsgParam); - } + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return; + } - vos_mem_free(pWdaParams) ; + if(IS_WDI_STATUS_FAILURE(wdiStatus)) + { + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams->wdaMsgParam); + vos_mem_free(pWdaParams); } - return ; + return; } /* - * FUNCTION: WDA_UpdateScanParamsCallback - * - */ -void WDA_UpdateScanParamsCallback(WDI_Status status, void* pUserData) + * FUNCTION: WDA_UpdateScanParamsRespCallback + * + */ +void WDA_UpdateScanParamsRespCallback(WDI_Status status, void* pUserData) { - tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, "<------ %s " ,__func__); - if(NULL == pWdaParams) + if(NULL == pWdaParams) { VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, "%s: pWdaParams received NULL", __func__); VOS_ASSERT(0) ; return ; } - if( pWdaParams != NULL ) + + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams->wdaMsgParam); + vos_mem_free(pWdaParams); + + return ; +} +/* + * FUNCTION: WDA_UpdateScanParamsReqCallback + * Free memory. + * Invoked when UpdateScanParams REQ failed in WDI and no RSP callback is generated. + */ +void WDA_UpdateScanParamsReqCallback(WDI_Status wdiStatus, void* pUserData) +{ + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s, wdiStatus: %d", __func__, wdiStatus); + + if(NULL == pWdaParams) { - if( pWdaParams->wdaWdiApiMsgParam != NULL ) - { - vos_mem_free(pWdaParams->wdaWdiApiMsgParam); - } - if( pWdaParams->wdaMsgParam != NULL) - { - vos_mem_free(pWdaParams->wdaMsgParam); - } - vos_mem_free(pWdaParams) ; + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return; } - return ; + + if(IS_WDI_STATUS_FAILURE(wdiStatus)) + { + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams->wdaMsgParam); + vos_mem_free(pWdaParams); + } + + return; } /* * FUNCTION: WDA_ProcessSetPreferredNetworkList @@ -11407,7 +12096,8 @@ VOS_STATUS WDA_ProcessSetPrefNetworkReq(tWDA_CbContext *pWDA, vos_mem_copy( &pwdiPNOScanReqInfo->wdiPNOScanInfo.a5GProbeTemplate, pPNOScanReqParams->p5GProbeTemplate, pwdiPNOScanReqInfo->wdiPNOScanInfo.us5GProbeSize); - pwdiPNOScanReqInfo->wdiReqStatusCB = NULL; + pwdiPNOScanReqInfo->wdiReqStatusCB = WDA_PNOScanReqCallback; + pwdiPNOScanReqInfo->pUserData = pWdaParams; /* Store Params pass it to WDI */ pWdaParams->wdaWdiApiMsgParam = (void *)pwdiPNOScanReqInfo; @@ -11415,7 +12105,7 @@ VOS_STATUS WDA_ProcessSetPrefNetworkReq(tWDA_CbContext *pWDA, /* Store param pointer as passed in by caller */ pWdaParams->wdaMsgParam = pPNOScanReqParams; status = WDI_SetPreferredNetworkReq(pwdiPNOScanReqInfo, - (WDI_PNOScanCb)WDA_PNOScanReqCallback, pWdaParams); + (WDI_PNOScanCb)WDA_PNOScanRespCallback, pWdaParams); if(IS_WDI_STATUS_FAILURE(status)) { VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, @@ -11427,11 +12117,247 @@ VOS_STATUS WDA_ProcessSetPrefNetworkReq(tWDA_CbContext *pWDA, } return CONVERT_WDI2VOS_STATUS(status) ; } + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + +void WDA_ConvertSirAuthToWDIAuth(WDI_AuthType *AuthType, v_U8_t csrAuthType) +{ + /*Convert the CSR Auth types to WDI Auth types */ + switch (csrAuthType) + { + case eCSR_AUTH_TYPE_OPEN_SYSTEM: + *AuthType = eWDA_AUTH_TYPE_OPEN_SYSTEM; + break; +#ifdef FEATURE_WLAN_CCX + case eCSR_AUTH_TYPE_CCKM_WPA: + *AuthType = eWDA_AUTH_TYPE_CCKM_WPA; + break; +#endif + case eCSR_AUTH_TYPE_WPA: + *AuthType = eWDA_AUTH_TYPE_WPA; + break; + case eCSR_AUTH_TYPE_WPA_PSK: + *AuthType = eWDA_AUTH_TYPE_WPA_PSK; + break; +#ifdef FEATURE_WLAN_CCX + case eCSR_AUTH_TYPE_CCKM_RSN: + *AuthType = eWDA_AUTH_TYPE_CCKM_RSN; + break; +#endif + case eCSR_AUTH_TYPE_RSN: + *AuthType = eWDA_AUTH_TYPE_RSN; + break; + case eCSR_AUTH_TYPE_RSN_PSK: + *AuthType = eWDA_AUTH_TYPE_RSN_PSK; + break; +#if defined WLAN_FEATURE_VOWIFI_11R + case eCSR_AUTH_TYPE_FT_RSN: + *AuthType = eWDA_AUTH_TYPE_FT_RSN; + break; + case eCSR_AUTH_TYPE_FT_RSN_PSK: + *AuthType = eWDA_AUTH_TYPE_FT_RSN_PSK; + break; +#endif +#ifdef FEATURE_WLAN_WAPI + case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE: + *AuthType = eWDA_AUTH_TYPE_WAPI_WAI_CERTIFICATE; + break; + case eCSR_AUTH_TYPE_WAPI_WAI_PSK: + *AuthType = eWDA_AUTH_TYPE_WAPI_WAI_PSK; + break; +#endif /* FEATURE_WLAN_WAPI */ + case eCSR_AUTH_TYPE_SHARED_KEY: + case eCSR_AUTH_TYPE_AUTOSWITCH: + *AuthType = eWDA_AUTH_TYPE_OPEN_SYSTEM; + break; +#if 0 + case eCSR_AUTH_TYPE_SHARED_KEY: + *AuthType = eWDA_AUTH_TYPE_SHARED_KEY; + break; + case eCSR_AUTH_TYPE_AUTOSWITCH: + *AuthType = eWDA_AUTH_TYPE_AUTOSWITCH; +#endif + default: + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: Unknown Auth Type", __func__); + break; + } +} +void WDA_ConvertSirEncToWDIEnc(WDI_EdType *EncrType, v_U8_t csrEncrType) +{ + switch (csrEncrType) + { + case eCSR_ENCRYPT_TYPE_NONE: + *EncrType = WDI_ED_NONE; + break; + case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY: + case eCSR_ENCRYPT_TYPE_WEP40: + *EncrType = WDI_ED_WEP40; + break; + case eCSR_ENCRYPT_TYPE_WEP104: + case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY: + *EncrType = WDI_ED_WEP104; + break; + case eCSR_ENCRYPT_TYPE_TKIP: + *EncrType = WDI_ED_TKIP; + break; + case eCSR_ENCRYPT_TYPE_AES: + *EncrType = WDI_ED_CCMP; + break; +#ifdef WLAN_FEATURE_11W + case eCSR_ENCRYPT_TYPE_AES_CMAC: + *EncrType = WDI_ED_AES_128_CMAC; + break; +#endif +#ifdef FEATURE_WLAN_WAPI + case eCSR_ENCRYPT_TYPE_WPI: + *EncrType = WDI_ED_WPI; + break; +#endif + case eCSR_ENCRYPT_TYPE_ANY: + *EncrType = WDI_ED_ANY; + break; + + default: + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: Unknown Encryption Type", __func__); + break; + } +} + +/* + * FUNCTION: WDA_ProcessRoamScanOffloadReq + * Request to WDI to set Roam Offload Scan + */ +VOS_STATUS WDA_ProcessRoamScanOffloadReq(tWDA_CbContext *pWDA, + tSirRoamOffloadScanReq *pRoamOffloadScanReqParams) +{ + WDI_Status status; + WDI_RoamScanOffloadReqParamsType *pwdiRoamScanOffloadReqParams = + (WDI_RoamScanOffloadReqParamsType *)vos_mem_malloc(sizeof(WDI_RoamScanOffloadReqParamsType)); + tWDA_ReqParams *pWdaParams ; + v_U8_t csrAuthType; + WDI_RoamNetworkType *pwdiRoamNetworkType; + WDI_RoamOffloadScanInfo *pwdiRoamOffloadScanInfo; + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "------> %s " ,__func__); + if (NULL == pwdiRoamScanOffloadReqParams) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "%s: VOS MEM Alloc Failure", __func__); + VOS_ASSERT(0); + return VOS_STATUS_E_NOMEM; + } + pWdaParams = (tWDA_ReqParams *)vos_mem_malloc(sizeof(tWDA_ReqParams)) ; + if (NULL == pWdaParams) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: VOS MEM Alloc Failure", __func__); + VOS_ASSERT(0); + vos_mem_free(pwdiRoamScanOffloadReqParams); + return VOS_STATUS_E_NOMEM; + } + + pwdiRoamNetworkType = + &pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.ConnectedNetwork; + pwdiRoamOffloadScanInfo = + &pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo; + vos_mem_zero (pwdiRoamScanOffloadReqParams,sizeof(WDI_RoamScanOffloadReqParamsType)); + csrAuthType = pRoamOffloadScanReqParams->ConnectedNetwork.authentication; + pwdiRoamOffloadScanInfo->RoamScanOffloadEnabled = + pRoamOffloadScanReqParams->RoamScanOffloadEnabled; + vos_mem_copy(pwdiRoamNetworkType->currAPbssid, + pRoamOffloadScanReqParams->ConnectedNetwork.currAPbssid, + sizeof(pwdiRoamNetworkType->currAPbssid)); + WDA_ConvertSirAuthToWDIAuth(&pwdiRoamNetworkType->authentication, + csrAuthType); + WDA_ConvertSirEncToWDIEnc(&pwdiRoamNetworkType->encryption, + pRoamOffloadScanReqParams->ConnectedNetwork.encryption); + WDA_ConvertSirEncToWDIEnc(&pwdiRoamNetworkType->mcencryption, + pRoamOffloadScanReqParams->ConnectedNetwork.mcencryption); + pwdiRoamOffloadScanInfo->LookupThreshold = + pRoamOffloadScanReqParams->LookupThreshold ; + pwdiRoamOffloadScanInfo->RoamRssiDiff = + pRoamOffloadScanReqParams->RoamRssiDiff ; + pwdiRoamOffloadScanInfo->Command = + pRoamOffloadScanReqParams->Command ; + pwdiRoamOffloadScanInfo->StartScanReason = + pRoamOffloadScanReqParams->StartScanReason ; + pwdiRoamOffloadScanInfo->NeighborScanTimerPeriod = + pRoamOffloadScanReqParams->NeighborScanTimerPeriod ; + pwdiRoamOffloadScanInfo->NeighborRoamScanRefreshPeriod = + pRoamOffloadScanReqParams->NeighborRoamScanRefreshPeriod ; + pwdiRoamOffloadScanInfo->NeighborScanChannelMinTime = + pRoamOffloadScanReqParams->NeighborScanChannelMinTime ; + pwdiRoamOffloadScanInfo->NeighborScanChannelMaxTime = + pRoamOffloadScanReqParams->NeighborScanChannelMaxTime ; + pwdiRoamOffloadScanInfo->EmptyRefreshScanPeriod = + pRoamOffloadScanReqParams->EmptyRefreshScanPeriod ; + pwdiRoamOffloadScanInfo->IsCCXEnabled = + pRoamOffloadScanReqParams->IsCCXEnabled ; + vos_mem_copy(&pwdiRoamNetworkType->ssId.sSSID, + &pRoamOffloadScanReqParams->ConnectedNetwork.ssId.ssId, + pRoamOffloadScanReqParams->ConnectedNetwork.ssId.length); + pwdiRoamNetworkType->ssId.ucLength = + pRoamOffloadScanReqParams->ConnectedNetwork.ssId.length; + vos_mem_copy(pwdiRoamNetworkType->ChannelCache, + pRoamOffloadScanReqParams->ConnectedNetwork.ChannelCache, + pRoamOffloadScanReqParams->ConnectedNetwork.ChannelCount); + pwdiRoamNetworkType->ChannelCount = + pRoamOffloadScanReqParams->ConnectedNetwork.ChannelCount; + pwdiRoamOffloadScanInfo->ChannelCacheType = + pRoamOffloadScanReqParams->ChannelCacheType; + vos_mem_copy(pwdiRoamOffloadScanInfo->ValidChannelList, + pRoamOffloadScanReqParams->ValidChannelList, + pRoamOffloadScanReqParams->ValidChannelCount); + pwdiRoamOffloadScanInfo->ValidChannelCount = + pRoamOffloadScanReqParams->ValidChannelCount; + pwdiRoamOffloadScanInfo->us24GProbeSize = + (pRoamOffloadScanReqParams->us24GProbeTemplateLenus24GProbeTemplateLen:WDI_PNO_MAX_PROBE_SIZE; + vos_mem_copy(&pwdiRoamOffloadScanInfo->a24GProbeTemplate, + pRoamOffloadScanReqParams->p24GProbeTemplate, + pwdiRoamOffloadScanInfo->us24GProbeSize); + pwdiRoamOffloadScanInfo->us5GProbeSize = + (pRoamOffloadScanReqParams->us5GProbeTemplateLenus5GProbeTemplateLen:WDI_PNO_MAX_PROBE_SIZE; + vos_mem_copy(&pwdiRoamOffloadScanInfo->a5GProbeTemplate, + pRoamOffloadScanReqParams->p5GProbeTemplate, + pwdiRoamOffloadScanInfo->us5GProbeSize); + pwdiRoamOffloadScanInfo->MDID.mdiePresent = + pRoamOffloadScanReqParams->MDID.mdiePresent; + pwdiRoamOffloadScanInfo->MDID.mobilityDomain = + pRoamOffloadScanReqParams->MDID.mobilityDomain; + pwdiRoamOffloadScanInfo->nProbes = + pRoamOffloadScanReqParams->nProbes; + pwdiRoamOffloadScanInfo->HomeAwayTime = + pRoamOffloadScanReqParams->HomeAwayTime; + pwdiRoamScanOffloadReqParams->wdiReqStatusCB = NULL; + /* Store Params pass it to WDI */ + pWdaParams->wdaWdiApiMsgParam = (void *)pwdiRoamScanOffloadReqParams; + pWdaParams->pWdaContext = pWDA; + /* Store param pointer as passed in by caller */ + pWdaParams->wdaMsgParam = pRoamOffloadScanReqParams; + status = WDI_RoamScanOffloadReq(pwdiRoamScanOffloadReqParams, + (WDI_RoamOffloadScanCb)WDA_RoamOffloadScanReqCallback, pWdaParams); + if(IS_WDI_STATUS_FAILURE(status)) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "Failure in Start Roam Candidate Lookup Req WDI API, free all the memory " ); + vos_mem_free(pWdaParams->wdaWdiApiMsgParam) ; + vos_mem_free(pWdaParams->wdaMsgParam); + pWdaParams->wdaWdiApiMsgParam = NULL; + pWdaParams->wdaMsgParam = NULL; + } + return CONVERT_WDI2VOS_STATUS(status) ; +} +#endif + /* - * FUNCTION: WDA_RssiFilterCallback + * FUNCTION: WDA_RssiFilterRespCallback * */ -void WDA_RssiFilterCallback(WDI_Status status, void* pUserData) +void WDA_RssiFilterRespCallback(WDI_Status status, void* pUserData) { tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; @@ -11441,16 +12367,46 @@ void WDA_RssiFilterCallback(WDI_Status status, void* pUserData) if(NULL == pWdaParams) { VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, - "%s: pWdaParams is NULL", __func__); + "%s: pWdaParams received NULL", __func__); VOS_ASSERT(0); - return ; + return; } + vos_mem_free(pWdaParams->wdaMsgParam) ; vos_mem_free(pWdaParams->wdaWdiApiMsgParam); vos_mem_free(pWdaParams) ; return ; } +/* + * FUNCTION: WDA_RssiFilterReqCallback + * Free memory. + * Invoked when RSSIFilter REQ failed in WDI and no RSP callback is generated. + */ +void WDA_RssiFilterReqCallback(WDI_Status wdiStatus, void* pUserData) +{ + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s, wdiStatus: %d", __func__, wdiStatus); + + if(NULL == pWdaParams) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return; + } + + if(IS_WDI_STATUS_FAILURE(wdiStatus)) + { + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams->wdaMsgParam); + vos_mem_free(pWdaParams); + } + + return; +} /* * FUNCTION: WDA_ProcessSetPreferredNetworkList * Request to WDI to set Preferred Network List.Offload @@ -11481,7 +12437,8 @@ VOS_STATUS WDA_ProcessSetRssiFilterReq(tWDA_CbContext *pWDA, return VOS_STATUS_E_NOMEM; } pwdiSetRssiFilterReqInfo->rssiThreshold = pRssiFilterParams->rssiThreshold; - pwdiSetRssiFilterReqInfo->wdiReqStatusCB = NULL; + pwdiSetRssiFilterReqInfo->wdiReqStatusCB = WDA_RssiFilterReqCallback; + pwdiSetRssiFilterReqInfo->pUserData = pWdaParams; /* Store Params pass it to WDI */ pWdaParams->wdaWdiApiMsgParam = (void *)pwdiSetRssiFilterReqInfo; @@ -11489,7 +12446,7 @@ VOS_STATUS WDA_ProcessSetRssiFilterReq(tWDA_CbContext *pWDA, /* Store param pointer as passed in by caller */ pWdaParams->wdaMsgParam = pRssiFilterParams; status = WDI_SetRssiFilterReq( pwdiSetRssiFilterReqInfo, - (WDI_PNOScanCb)WDA_RssiFilterCallback, + (WDI_PNOScanCb)WDA_RssiFilterRespCallback, pWdaParams); if(IS_WDI_STATUS_FAILURE(status)) { @@ -11583,7 +12540,8 @@ VOS_STATUS WDA_ProcessUpdateScanParams(tWDA_CbContext *pWDA, pUpdateScanParams->aChannels[i]; } - wdiUpdateScanParamsInfoType->wdiReqStatusCB = NULL; + wdiUpdateScanParamsInfoType->wdiReqStatusCB = WDA_UpdateScanParamsReqCallback; + wdiUpdateScanParamsInfoType->pUserData = pWdaParams; /* Store Params pass it to WDI */ pWdaParams->wdaWdiApiMsgParam = wdiUpdateScanParamsInfoType; @@ -11594,7 +12552,7 @@ VOS_STATUS WDA_ProcessUpdateScanParams(tWDA_CbContext *pWDA, status = WDI_UpdateScanParamsReq(wdiUpdateScanParamsInfoType, - (WDI_UpdateScanParamsCb)WDA_UpdateScanParamsCallback, + (WDI_UpdateScanParamsCb)WDA_UpdateScanParamsRespCallback, pWdaParams); if(IS_WDI_STATUS_FAILURE(status)) { @@ -11607,11 +12565,46 @@ VOS_STATUS WDA_ProcessUpdateScanParams(tWDA_CbContext *pWDA, return CONVERT_WDI2VOS_STATUS(status) ; } #endif // FEATURE_WLAN_SCAN_PNO + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +/* + * FUNCTION: WDA_RoamOffloadScanReqCallback + * + */ +void WDA_RoamOffloadScanReqCallback(WDI_Status status, void* pUserData) +{ + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s " ,__func__); + if (NULL == pWdaParams) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0) ; + return ; + } + if ( pWdaParams != NULL ) + { + if ( pWdaParams->wdaWdiApiMsgParam != NULL ) + { + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + } + if ( pWdaParams->wdaMsgParam != NULL) + { + vos_mem_free(pWdaParams->wdaMsgParam); + } + + vos_mem_free(pWdaParams) ; + } + return ; +} +#endif + /* - * FUNCTION: WDA_SetPowerParamsCallback + * FUNCTION: WDA_SetPowerParamsRespCallback * */ -void WDA_SetPowerParamsCallback(WDI_Status status, void* pUserData) +void WDA_SetPowerParamsRespCallback(WDI_Status status, void* pUserData) { tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; @@ -11625,27 +12618,49 @@ void WDA_SetPowerParamsCallback(WDI_Status status, void* pUserData) VOS_ASSERT(0); return; } - if( pWdaParams != NULL ) + + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams->wdaMsgParam); + vos_mem_free(pWdaParams); + + return; +} +/* + * FUNCTION: WDA_SetPowerParamsReqCallback + * Free memory. + * Invoked when SetPowerParams REQ failed in WDI and no RSP callback is generated. + */ +void WDA_SetPowerParamsReqCallback(WDI_Status wdiStatus, void* pUserData) +{ + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s, wdiStatus: %d", __func__, wdiStatus); + + if(NULL == pWdaParams) { - if( pWdaParams->wdaWdiApiMsgParam != NULL ) - { - vos_mem_free(pWdaParams->wdaWdiApiMsgParam); - } - if( pWdaParams->wdaMsgParam != NULL) - { - vos_mem_free(pWdaParams->wdaMsgParam); - } + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return; + } + + if(IS_WDI_STATUS_FAILURE(wdiStatus)) + { + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams->wdaMsgParam); vos_mem_free(pWdaParams); } + return; } #ifdef WLAN_FEATURE_PACKET_FILTERING /* - * FUNCTION: WDA_8023MulticastListReqCallback + * FUNCTION: WDA_8023MulticastListRespCallback * */ -void WDA_8023MulticastListReqCallback( +void WDA_8023MulticastListRespCallback( WDI_RcvFltPktSetMcListRspParamsType *pwdiRcvFltPktSetMcListRspInfo, void * pUserData) { @@ -11665,9 +12680,38 @@ void WDA_8023MulticastListReqCallback( vos_mem_free(pWdaParams) ; //print a msg, nothing else to do VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, - "WDA_8023MulticastListReqCallback invoked " ); + "WDA_8023MulticastListRespCallback invoked " ); return ; } +/* + * FUNCTION: WDA_8023MulticastListReqCallback + * Free memory. + * Invoked when 8023MulticastList REQ failed in WDI and no RSP callback is generated. + */ +void WDA_8023MulticastListReqCallback(WDI_Status wdiStatus, void* pUserData) +{ + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s, wdiStatus: %d", __func__, wdiStatus); + + if(NULL == pWdaParams) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return; + } + + if(IS_WDI_STATUS_FAILURE(wdiStatus)) + { + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams->wdaMsgParam); + vos_mem_free(pWdaParams); + } + + return; +} /* * FUNCTION: WDA_Process8023MulticastListReq * Request to WDI to add 8023 Multicast List @@ -11717,7 +12761,8 @@ VOS_STATUS WDA_Process8023MulticastListReq (tWDA_CbContext *pWDA, &(pRcvFltMcAddrList->multicastAddr[i]), sizeof(tSirMacAddr)); } - pwdiFltPktSetMcListReqParamsType->wdiReqStatusCB = NULL; + pwdiFltPktSetMcListReqParamsType->wdiReqStatusCB = WDA_8023MulticastListReqCallback; + pwdiFltPktSetMcListReqParamsType->pUserData = pWdaParams; /* Store Params pass it to WDI */ pWdaParams->wdaWdiApiMsgParam = (void *)pwdiFltPktSetMcListReqParamsType; @@ -11726,7 +12771,7 @@ VOS_STATUS WDA_Process8023MulticastListReq (tWDA_CbContext *pWDA, pWdaParams->wdaMsgParam = pRcvFltMcAddrList; status = WDI_8023MulticastListReq( pwdiFltPktSetMcListReqParamsType, - (WDI_8023MulticastListCb)WDA_8023MulticastListReqCallback, + (WDI_8023MulticastListCb)WDA_8023MulticastListRespCallback, pWdaParams); if(IS_WDI_STATUS_FAILURE(status)) { @@ -11768,10 +12813,11 @@ void WDA_ReceiveFilterSetFilterRespCallback( } /* - * FUNCTION: WDA_ReqCallback - * + * FUNCTION: WDA_ReceiveFilterSetFilterReqCallback + * Free memory. + * Invoked when ReceiveFilterSetFilter REQ failed in WDI and no RSP callback is generated. */ -void WDA_ReqCallback(WDI_Status wdiStatus, +void WDA_ReceiveFilterSetFilterReqCallback(WDI_Status wdiStatus, void* pUserData) { tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; @@ -11892,7 +12938,7 @@ VOS_STATUS WDA_ProcessReceiveFilterSetFilterReq (tWDA_CbContext *pWDA, pwdiSetRcvPktFilterReqParamsType-> wdiPktFilterCfg.paramsData[i].dataMask[5]); } - pwdiSetRcvPktFilterReqParamsType->wdiReqStatusCB = WDA_ReqCallback; + pwdiSetRcvPktFilterReqParamsType->wdiReqStatusCB = WDA_ReceiveFilterSetFilterReqCallback; pwdiSetRcvPktFilterReqParamsType->pUserData = pWdaParams; /* Store Params pass it to WDI */ pWdaParams->wdaWdiApiMsgParam = (void *)pwdiSetRcvPktFilterReqParamsType; @@ -11913,10 +12959,10 @@ VOS_STATUS WDA_ProcessReceiveFilterSetFilterReq (tWDA_CbContext *pWDA, return CONVERT_WDI2VOS_STATUS(status) ; } /* - * FUNCTION: WDA_FilterMatchCountReqCallback + * FUNCTION: WDA_FilterMatchCountRespCallback * */ -void WDA_FilterMatchCountReqCallback( +void WDA_FilterMatchCountRespCallback( WDI_RcvFltPktMatchCntRspParamsType *pwdiRcvFltPktMatchRspParams, void * pUserData) { @@ -11978,6 +13024,44 @@ void WDA_FilterMatchCountReqCallback( vos_mem_free(pWdaParams->wdaMsgParam) ; vos_mem_free(pWdaParams->wdaWdiApiMsgParam); vos_mem_free(pWdaParams) ; + + return; +} +/* + * FUNCTION: WDA_FilterMatchCountReqCallback + * Free memory and send RSP back to SME. + * Invoked when FilterMatchCount REQ failed in WDI and no RSP callback is generated. + */ +void WDA_FilterMatchCountReqCallback(WDI_Status wdiStatus, void * pUserData) +{ + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; + vos_msg_t vosMsg; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s, wdiStatus: %d", __func__, wdiStatus); + + if(NULL == pWdaParams) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return; + } + + /* VOS message wrapper */ + vosMsg.type = eWNI_PMC_PACKET_COALESCING_FILTER_MATCH_COUNT_RSP; + vosMsg.bodyptr = NULL; + vosMsg.bodyval = 0; + + if(IS_WDI_STATUS_FAILURE(wdiStatus)) + { + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams->wdaMsgParam); + vos_mem_free(pWdaParams); + vos_mq_post_message(VOS_MQ_ID_SME, (vos_msg_t*)&vosMsg); + } + + return; } /* * FUNCTION: WDA_ProcessPacketFilterMatchCountReq @@ -12008,7 +13092,8 @@ VOS_STATUS WDA_ProcessPacketFilterMatchCountReq (tWDA_CbContext *pWDA, tpSirRcvF return VOS_STATUS_E_NOMEM; } - pwdiRcvFltPktMatchCntReqParamsType->wdiReqStatusCB = NULL; + pwdiRcvFltPktMatchCntReqParamsType->wdiReqStatusCB = WDA_FilterMatchCountReqCallback; + pwdiRcvFltPktMatchCntReqParamsType->pUserData = pWdaParams; vos_mem_copy( pwdiRcvFltPktMatchCntReqParamsType->bssId, pRcvFltPktMatchRsp->bssId, @@ -12020,7 +13105,7 @@ VOS_STATUS WDA_ProcessPacketFilterMatchCountReq (tWDA_CbContext *pWDA, tpSirRcvF /* Store param pointer as passed in by caller */ pWdaParams->wdaMsgParam = pRcvFltPktMatchRsp; status = WDI_FilterMatchCountReq(pwdiRcvFltPktMatchCntReqParamsType, - (WDI_FilterMatchCountCb)WDA_FilterMatchCountReqCallback, + (WDI_FilterMatchCountCb)WDA_FilterMatchCountRespCallback, pWdaParams); if(IS_WDI_STATUS_FAILURE(status)) { @@ -12062,6 +13147,35 @@ void WDA_ReceiveFilterClearFilterRespCallback( "WDA_ReceiveFilterClearFilterRespCallback invoked " ); return ; } +/* + * FUNCTION: WDA_ReceiveFilterClearFilterReqCallback + * Free memory. + * Invoked when ReceiveFilterClearFilter REQ failed in WDI and no RSP callback is generated. + */ +void WDA_ReceiveFilterClearFilterReqCallback(WDI_Status wdiStatus, void* pUserData) +{ + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s, wdiStatus: %d", __func__, wdiStatus); + + if(NULL == pWdaParams) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid pWdaParams pointer", __func__); + VOS_ASSERT(0); + return; + } + + if(IS_WDI_STATUS_FAILURE(wdiStatus)) + { + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams->wdaMsgParam); + vos_mem_free(pWdaParams); + } + + return; +} /* * FUNCTION: WDA_ProcessReceiveFilterClearFilterReq * Request to WDI to clear Receive Filters @@ -12098,7 +13212,7 @@ VOS_STATUS WDA_ProcessReceiveFilterClearFilterReq (tWDA_CbContext *pWDA, vos_mem_copy(pwdiRcvFltPktClearReqParamsType->filterClearParam.bssId, pRcvFltPktClearParam->bssId, sizeof(wpt_macAddr)); - pwdiRcvFltPktClearReqParamsType->wdiReqStatusCB = WDA_ReqCallback; + pwdiRcvFltPktClearReqParamsType->wdiReqStatusCB = WDA_ReceiveFilterClearFilterReqCallback; pwdiRcvFltPktClearReqParamsType->pUserData = pWdaParams; /* Store Params pass it to WDI */ pWdaParams->wdaWdiApiMsgParam = (void *)pwdiRcvFltPktClearReqParamsType; @@ -12163,7 +13277,10 @@ VOS_STATUS WDA_ProcessSetPowerParamsReq(tWDA_CbContext *pWDA, pPowerParams->uEnableBET; pwdiSetPowerParamsReqInfo->wdiSetPowerParamsInfo.uBETInterval = pPowerParams->uBETInterval; - pwdiSetPowerParamsReqInfo->wdiReqStatusCB = NULL; + pwdiSetPowerParamsReqInfo->wdiSetPowerParamsInfo.uMaxLIModulatedDTIM = + pPowerParams->uMaxLIModulatedDTIM; + pwdiSetPowerParamsReqInfo->wdiReqStatusCB = WDA_SetPowerParamsReqCallback; + pwdiSetPowerParamsReqInfo->pUserData = pWdaParams; /* Store Params pass it to WDI */ pWdaParams->wdaWdiApiMsgParam = (void *)pwdiSetPowerParamsReqInfo; @@ -12171,7 +13288,7 @@ VOS_STATUS WDA_ProcessSetPowerParamsReq(tWDA_CbContext *pWDA, /* Store param pointer as passed in by caller */ pWdaParams->wdaMsgParam = pPowerParams; status = WDI_SetPowerParamsReq( pwdiSetPowerParamsReqInfo, - (WDI_SetPowerParamsCb)WDA_SetPowerParamsCallback, + (WDI_SetPowerParamsCb)WDA_SetPowerParamsRespCallback, pWdaParams); if(IS_WDI_STATUS_FAILURE(status)) { @@ -12563,3 +13680,21 @@ void WDA_TransportChannelDebug WDI_TransportChannelDebug(displaySnapshot, toggleStallDetect); return; } + +/*========================================================================== + FUNCTION WDA_SetEnableSSR + + DESCRIPTION + API to enable/disable SSR on WDI timeout + + PARAMETERS + enableSSR : enable/disable SSR + + RETURN VALUE + NONE + +===========================================================================*/ +void WDA_SetEnableSSR(v_BOOL_t enableSSR) +{ + WDI_SetEnableSSR(enableSSR); +} diff --git a/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi.h b/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi.h index 84000536256..1706a9af62c 100644 --- a/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi.h +++ b/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi.h @@ -510,9 +510,11 @@ typedef struct typedef struct { /* Network that was found with the highest RSSI*/ - WDI_MacSSid ssId; + WDI_MacSSid ssId; /* Indicates the RSSI */ - wpt_uint8 rssi; + wpt_uint8 rssi; + wpt_uint16 frameLength; + wpt_uint8 *pData; } WDI_PrefNetworkFoundInd; #endif // FEATURE_WLAN_SCAN_PNO @@ -3059,6 +3061,9 @@ typedef struct /*Self Station MAC address*/ wpt_macAddr selfMacAddr; + /*Self STA device mode*/ + wpt_uint32 currDeviceMode; + /*Status of the operation*/ wpt_uint32 uStatus; }WDI_AddSTASelfInfoType; @@ -3520,6 +3525,7 @@ typedef struct wpt_uint8 srcIPv6AddrValid : 1; wpt_uint8 targetIPv6Addr1Valid : 1; wpt_uint8 targetIPv6Addr2Valid : 1; + wpt_uint8 slotIdx; } WDI_NSOffloadParams; #endif //WLAN_NS_OFFLOAD @@ -4084,23 +4090,6 @@ typedef struct void* pUserData; }WDI_TrafficStatsIndType; -#ifdef WLAN_FEATURE_11W -typedef struct -{ - - wpt_boolean bExcludeUnencrypt; - wpt_macAddr bssid; - /*Request status callback offered by UMAC - it is called if the current - req has returned PENDING as status; it delivers the status of sending - the message over the BUS */ - WDI_ReqStatusCb wdiReqStatusCB; - - /*The user data passed in by UMAC, it will be sent back when the above - function pointer will be called */ - void* pUserData; -}WDI_ExcludeUnencryptIndType; -#endif - /*--------------------------------------------------------------------------- WDI_WlanResumeInfoType ---------------------------------------------------------------------------*/ @@ -4259,6 +4248,11 @@ typedef struct #define WDI_PNO_MAX_PROBE_SIZE 450 +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +#define WDI_ROAM_SCAN_MAX_CHANNELS 80 /* NUM_RF_CHANNELS */ +#define WDI_ROAM_SCAN_MAX_PROBE_SIZE 450 +#define WDI_ROAM_SCAN_RESERVED_BYTES 61 +#endif /*--------------------------------------------------------------------------- WDI_AuthType @@ -4349,7 +4343,7 @@ typedef struct wpt_uint8 ucChannelCount; /*the actual channels*/ - wpt_uint8 aChannels[WDI_PNO_MAX_NETW_CHANNELS]; + wpt_uint8 aChannels[WDI_PNO_MAX_NETW_CHANNELS_EX]; /*rssi threshold that a network must meet to be considered, 0 - for any*/ wpt_uint8 rssiThreshold; @@ -4426,6 +4420,88 @@ typedef struct void* pUserData; } WDI_PNOScanReqParamsType; +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + +typedef struct +{ + /*The SSID of the preferred network*/ + WDI_MacSSid ssId; + wpt_uint8 currAPbssid[WDI_MAC_ADDR_LEN]; + + /*The authentication method of the preferred network*/ + WDI_AuthType authentication; + + /*The encryption method of the preferred network*/ + WDI_EdType encryption; + WDI_EdType mcencryption; + + /*SSID broadcast type, normal, hidden or unknown*/ + //WDI_SSIDBcastType wdiBcastNetworkType; + + /*channel count - 0 for all channels*/ + wpt_uint8 ChannelCount; + + /*the actual channels*/ + wpt_uint8 ChannelCache[WDI_ROAM_SCAN_MAX_CHANNELS]; + +} WDI_RoamNetworkType; + +typedef struct WDIMobilityDomainInfo +{ + wpt_uint8 mdiePresent; + wpt_uint16 mobilityDomain; +} WDI_MobilityDomainInfo; + +/*--------------------------------------------------------------------------- + WDI_RoamOffloadScanInfo +---------------------------------------------------------------------------*/ +typedef struct +{ + wpt_boolean RoamScanOffloadEnabled; + wpt_uint8 LookupThreshold; + wpt_uint8 RoamRssiDiff; + wpt_uint8 ChannelCacheType; + wpt_uint8 Command; + wpt_uint8 StartScanReason; + wpt_uint16 NeighborScanTimerPeriod; + wpt_uint16 NeighborRoamScanRefreshPeriod; + wpt_uint16 NeighborScanChannelMinTime; + wpt_uint16 NeighborScanChannelMaxTime; + wpt_uint16 EmptyRefreshScanPeriod; + wpt_uint8 ValidChannelCount; + wpt_uint8 ValidChannelList[WDI_ROAM_SCAN_MAX_CHANNELS]; + wpt_boolean IsCCXEnabled; + /*Probe template for 2.4GHz band*/ + wpt_uint16 us24GProbeSize; + wpt_uint8 a24GProbeTemplate[WDI_ROAM_SCAN_MAX_PROBE_SIZE]; + + /*Probe template for 5GHz band*/ + wpt_uint16 us5GProbeSize; + wpt_uint8 a5GProbeTemplate[WDI_ROAM_SCAN_MAX_PROBE_SIZE]; + /*LFR BG Scan will currently look for only one network to which it is initially connected. + * As per requirement, later, the following structure can be used as an array of networks.*/ + WDI_RoamNetworkType ConnectedNetwork; + WDI_MobilityDomainInfo MDID; + wpt_uint8 nProbes; + wpt_uint16 HomeAwayTime; + wpt_uint8 ReservedBytes[WDI_ROAM_SCAN_RESERVED_BYTES]; +} WDI_RoamOffloadScanInfo; + +typedef struct +{ + /* Start Roam Candidate Lookup Offload Back Ground Info Type */ + WDI_RoamOffloadScanInfo wdiRoamOffloadScanInfo; + /* Request status callback offered by UMAC - it is called if the current req + has returned PENDING as status; it delivers the status of sending the message + over the BUS */ + WDI_ReqStatusCb wdiReqStatusCB; + /* The user data passed in by UMAC, it will be sent back when the above + function pointer will be called */ + void* pUserData; +} WDI_RoamScanOffloadReqParamsType; + +#endif + /*--------------------------------------------------------------------------- WDI_SetRssiFilterReqParamsType PNO info passed to WDI form WDA @@ -4517,6 +4593,9 @@ typedef struct /* Beacon Early Termination Interval */ wpt_uint32 uBETInterval; + /* MAX LI for modulated DTIM */ + wpt_uint32 uMaxLIModulatedDTIM; + } WDI_SetPowerParamsInfo; /*--------------------------------------------------------------------------- @@ -6334,6 +6413,30 @@ typedef void (*WDI_UpdateScanParamsCb)(WDI_Status wdiStatus, void* pUserData); #endif // FEATURE_WLAN_SCAN_PNO +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +/*--------------------------------------------------------------------------- + WDI_RoamOffloadScanCb + + DESCRIPTION + + This callback is invoked by DAL when it has received a Start Roam Candidate Lookup Req + response from the underlying device. + + PARAMETERS + + IN + wdiStatus: response status received from HAL + pUserData: user data + + + + RETURN VALUE + The result code associated with performing the operation +---------------------------------------------------------------------------*/ +typedef void (*WDI_RoamOffloadScanCb)(WDI_Status wdiStatus, + void* pUserData); + +#endif /*--------------------------------------------------------------------------- WDI_SetTxPerTrackingRspCb @@ -8912,24 +9015,6 @@ WDI_TrafficStatsInd WDI_TrafficStatsIndType *pWdiTrafficStatsIndParams ); -#ifdef WLAN_FEATURE_11W -/** - @brief WDI_ExcludeUnencryptedInd - Register with HAL to receive/drop unencrypted frames - - @param WDI_ExcludeUnencryptIndType - - @see - - @return Status of the request -*/ -WDI_Status -WDI_ExcludeUnencryptedInd -( - WDI_ExcludeUnencryptIndType *pWdiExcUnencParams -); -#endif - #ifdef FEATURE_WLAN_SCAN_PNO /** @brief WDI_SetPreferredNetworkList @@ -9004,6 +9089,31 @@ WDI_UpdateScanParamsReq ); #endif // FEATURE_WLAN_SCAN_PNO +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +/** + @brief WDI_RoamScanOffloadReq + + @param pwdiRoamScanOffloadReqParams: Start Roam Candidate Lookup Req as specified + by the Device Interface + + wdiRoamOffloadScanCb: callback for passing back the response + of the Start Roam Candidate Lookup operation received from the + device + + pUserData: user data will be passed back with the + callback + + @return Result of the function call +*/ +WDI_Status +WDI_RoamScanOffloadReq +( + WDI_RoamScanOffloadReqParamsType *pwdiRoamScanOffloadReqParams, + WDI_RoamOffloadScanCb wdiRoamOffloadScancb, + void* pUserData +); +#endif + /** @brief WDI_SetTxPerTrackingReq will be called when the upper MAC wants to set the Tx Per Tracking configurations. @@ -9399,6 +9509,17 @@ WDI_SsrTimerCB void *pUserData ); +/** + @brief WDI_SetEnableSSR - + This API is called to enable/disable SSR on WDI timeout. + + @param enableSSR : enable/disable SSR + + @see + @return none +*/ +void WDI_SetEnableSSR(wpt_boolean enableSSR); + #ifdef __cplusplus } #endif diff --git a/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi_bd.h b/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi_bd.h index 22b2a421e08..10aef2a62ae 100644 --- a/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi_bd.h +++ b/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi_bd.h @@ -309,38 +309,51 @@ typedef struct /* 0x10 */ #ifdef WPT_BIG_BYTE_ENDIAN - - /** This is the length (in number of bytes) of the entire MPDU + + /** This is the length (in number of bytes) of the entire MPDU (header and data). Note that the length does not include FCS field. */ wpt_uint32 mpduLength:16; - + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + wpt_uint32 offloadScanLearn:1; + wpt_uint32 roamCandidateInd:1; +#else + wpt_uint32 reserved22:2; +#endif + #ifdef WCN_PRONTO - wpt_uint32 reserved3: 3; - wpt_uint32 rxDXEPriorityRouting:1; + wpt_uint32 reserved3: 1; + wpt_uint32 rxDXEPriorityRouting:1; #else - wpt_uint32 reserved3:4; + wpt_uint32 reserved3:2; #endif //WCN_PRONTO - - + + /** Traffic Identifier Indicates the traffic class the frame belongs to. For non QoS frames, this field is set to zero. */ wpt_uint32 tid:4; - + wpt_uint32 reserved4:8; #else wpt_uint32 reserved4:8; wpt_uint32 tid:4; #ifdef WCN_PRONTO - wpt_uint32 rxDXEPriorityRouting:1; - wpt_uint32 reserved3: 3; + wpt_uint32 rxDXEPriorityRouting:1; + wpt_uint32 reserved3: 1; #else - wpt_uint32 reserved3:4; + wpt_uint32 reserved3:2; #endif //WCN_PRONTO - +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + wpt_uint32 roamCandidateInd:1; + wpt_uint32 offloadScanLearn:1; +#else + wpt_uint32 reserved22:2; +#endif + wpt_uint32 mpduLength:16; #endif - + /* 0x14 */ #ifdef WPT_BIG_BYTE_ENDIAN diff --git a/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi_dp.h b/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi_dp.h index 646ab576dd4..5472bbdc52b 100644 --- a/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi_dp.h +++ b/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi_dp.h @@ -299,6 +299,11 @@ when who what, where, why #define WDI_RX_FC_BD_GET_FC( _pvBDHeader ) (((WDI_FcRxBdType*)_pvBDHeader)->fc) #define WDI_RX_FC_BD_GET_STA_VALID_MASK( _pvBDHeader ) (((WDI_FcRxBdType*)_pvBDHeader)->fcSTAValidMask) +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +//LFR scan related +#define WDI_RX_BD_GET_OFFLOADSCANLEARN( _pvBDHeader ) (((WDI_RxBdType*)_pvBDHeader)->offloadScanLearn) +#define WDI_RX_BD_GET_ROAMCANDIDATEIND( _pvBDHeader ) (((WDI_RxBdType*)_pvBDHeader)->roamCandidateInd) +#endif /*------------ RSSI and SNR Information extraction -------------*/ #define WDI_RX_BD_GET_RSSI0( _pvBDHeader ) \ @@ -346,10 +351,6 @@ when who what, where, why #define WDI_RX_BD_GET_PMICMD_24TO25(_pvBDHeader) (((WDI_RxBdType*)_pvBDHeader)->pmiCmd24to25) -#ifdef WLAN_FEATURE_11W -#define WDI_RX_BD_GET_RMF( _pvBDHeader ) (((WDI_RxBdType*)_pvBDHeader)->rmf) -#endif - #define WDI_RX_BD_ASF_SET 1 /*The value of the field when set and pkt is AMSDU*/ #define WDI_RX_BD_FSF_SET 1 diff --git a/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi_i.h b/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi_i.h index e2fab24c62d..1acf6cb6edb 100644 --- a/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi_i.h +++ b/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi_i.h @@ -444,7 +444,7 @@ typedef enum /*WLAN DAL Set Tx Power Request*/ WDI_SET_TX_POWER_REQ = 82, - + WDI_ROAM_SCAN_OFFLOAD_REQ = 83, WDI_MAX_REQ, /*Send a suspend Indication down to HAL*/ @@ -453,9 +453,6 @@ typedef enum /* Send a traffic stats indication to HAL */ WDI_TRAFFIC_STATS_IND, - /* Drop/Receive unencrypted frames indication to HAL */ - WDI_EXCLUDE_UNENCRYPTED_IND, - /*Keep adding the indications to the max request such that we keep them sepparate */ @@ -710,7 +707,7 @@ typedef enum WDI_GET_ROAM_RSSI_RESP = 80, WDI_SET_TX_POWER_RESP = 81, - + WDI_ROAM_SCAN_OFFLOAD_RESP = 82, /*------------------------------------------------------------------------- Indications !! Keep these last in the enum if possible @@ -1088,6 +1085,9 @@ typedef struct /*timestamp when we get response timer event*/ wpt_uint32 uTimeStampRspTmrExp; + + /* enable/disable SSR on WDI timeout */ + wpt_boolean bEnableSSR; }WDI_ControlBlockType; @@ -2729,26 +2729,6 @@ WDI_ProcessTrafficStatsInd WDI_ControlBlockType* pWDICtx, WDI_EventInfoType* pEventData ); - -#ifdef WLAN_FEATURE_11W -/** - @brief Process Exclude Unencrypted Indications function (called - when Main FSM allows it) - - @param pWDICtx: pointer to the WLAN DAL context - pEventData: pointer to the event information structure - - @see - @return Result of the function call -*/ -WDI_Status -WDI_ProcessExcludeUnencryptInd -( - WDI_ControlBlockType* pWDICtx, - WDI_EventInfoType* pEventData -); -#endif - /*======================================================================== Main DAL Control Path Response Processing API ========================================================================*/ @@ -4866,6 +4846,40 @@ WDI_ProcessUpdateScanParamsRsp ); #endif // FEATURE_WLAN_SCAN_PNO +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +/** + @brief Process Start Roam Candidate Lookup Request function + + @param pWDICtx: pointer to the WLAN DAL context + pEventData: pointer to the event information structure + + @see + @return Result of the function call +*/ +WDI_Status +WDI_ProcessRoamScanOffloadReq +( + WDI_ControlBlockType* pWDICtx, + WDI_EventInfoType* pEventData +); +/** + @brief Process Start Roam Candidate Lookup Response function (called when a + response is being received over the bus from HAL) + + @param pWDICtx: pointer to the WLAN DAL context + pEventData: pointer to the event information structure + + @see + @return Result of the function call +*/ +WDI_Status +WDI_ProcessRoamScanOffloadRsp +( + WDI_ControlBlockType* pWDICtx, + WDI_EventInfoType* pEventData +); +#endif + #ifdef WLAN_FEATURE_PACKET_FILTERING /** @brief Process 8023 Multicast List Request function @@ -5119,6 +5133,23 @@ WDI_ProcessUpdateVHTOpModeRsp WDI_EventInfoType* pEventData ); #endif +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +/** + * @brief WDI_wdiEdTypeEncToEdTypeEnc - + * The firmware expects the Encryption type to be in EdType. + * This function converts the WdiEdType encryption to EdType. + * @param tEdType : EdType to which the encryption needs to be converted. + * @param WDI_EdType : wdiEdType passed from the upper layer. + * @see + * @return none + * */ +void +WDI_wdiEdTypeEncToEdTypeEnc +( + tEdType *EdType, + WDI_EdType wdiEdType +); +#endif #endif /*WLAN_QCT_WDI_I_H*/ diff --git a/drivers/staging/prima/CORE/WDI/CP/src/wlan_qct_wdi.c b/drivers/staging/prima/CORE/WDI/CP/src/wlan_qct_wdi.c index ab41e2dff2e..df0a01f6d20 100644 --- a/drivers/staging/prima/CORE/WDI/CP/src/wlan_qct_wdi.c +++ b/drivers/staging/prima/CORE/WDI/CP/src/wlan_qct_wdi.c @@ -112,7 +112,7 @@ #define MAC_ADDR_ARRAY(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5] #define MAC_ADDRESS_STR "%02x:%02x:%02x:%02x:%02x:%02x" -#define FEATURE_NOT_SUPPORTED 128 +#define FEATURE_NOT_SUPPORTED 127 #ifdef FEATURE_WLAN_SCAN_PNO #define WDI_PNO_VERSION_MASK 0x8000 @@ -142,6 +142,11 @@ static placeHolderInCapBitmap supportEnabledFeatures[] = ,WLANACTIVE_OFFLOAD #else ,FEATURE_NOT_SUPPORTED +#endif +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + ,WLAN_ROAM_SCAN_OFFLOAD +#else + ,FEATURE_NOT_SUPPORTED #endif }; @@ -349,16 +354,16 @@ WDI_ReqProcFuncType pfnReqProcTbl[WDI_MAX_UMAC_IND] = NULL, #endif WDI_ProcessSetTxPowerReq, /* WDI_SET_TX_POWER_REQ*/ +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + WDI_ProcessRoamScanOffloadReq, /* WDI_ROAM_SCAN_OFFLOAD_REQ */ +#else + NULL, +#endif /* WLAN_FEATURE_ROAM_SCAN_OFFLOAD */ /*------------------------------------------------------------------------- Indications -------------------------------------------------------------------------*/ WDI_ProcessHostSuspendInd, /* WDI_HOST_SUSPEND_IND*/ WDI_ProcessTrafficStatsInd, /* WDI_TRAFFIC_STATS_IND*/ -#ifdef WLAN_FEATURE_11W - WDI_ProcessExcludeUnencryptInd, /* WDI_EXCLUDE_UNENCRYPTED_IND */ -#else - NULL, -#endif }; @@ -527,7 +532,11 @@ WDI_RspProcFuncType pfnRspProcTbl[WDI_MAX_RESP] = NULL, #endif WDI_ProcessSetTxPowerRsp, /* WDI_SET_TX_POWER_RESP */ - +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + WDI_ProcessRoamScanOffloadRsp, /* WDI_ROAM_SCAN_OFFLOAD_RESP */ +#else + NULL, +#endif /*--------------------------------------------------------------------- Indications ---------------------------------------------------------------------*/ @@ -848,6 +857,9 @@ static char *WDI_getReqMsgString(wpt_uint16 wdiReqMsgId) CASE_RETURN_STRING( WDI_SET_RSSI_FILTER_REQ ); CASE_RETURN_STRING( WDI_UPDATE_SCAN_PARAMS_REQ ); #endif +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + CASE_RETURN_STRING( WDI_ROAM_SCAN_OFFLOAD_REQ ); +#endif CASE_RETURN_STRING( WDI_SET_TX_PER_TRACKING_REQ ); CASE_RETURN_STRING( WDI_8023_MULTICAST_LIST_REQ ); CASE_RETURN_STRING( WDI_RECEIVE_FILTER_SET_FILTER_REQ ); @@ -859,9 +871,6 @@ static char *WDI_getReqMsgString(wpt_uint16 wdiReqMsgId) CASE_RETURN_STRING( WDI_SET_POWER_PARAMS_REQ ); CASE_RETURN_STRING( WDI_TRAFFIC_STATS_IND ); CASE_RETURN_STRING( WDI_GET_ROAM_RSSI_REQ ); -#ifdef WLAN_FEATURE_11W - CASE_RETURN_STRING( WDI_EXCLUDE_UNENCRYPTED_IND ); -#endif default: return "Unknown WDI MessageId"; } @@ -949,6 +958,9 @@ static char *WDI_getRespMsgString(wpt_uint16 wdiRespMsgId) CASE_RETURN_STRING( WDI_SET_RSSI_FILTER_RESP ); CASE_RETURN_STRING( WDI_UPDATE_SCAN_PARAMS_RESP ); #endif +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + CASE_RETURN_STRING( WDI_ROAM_SCAN_OFFLOAD_RESP ); +#endif CASE_RETURN_STRING( WDI_SET_TX_PER_TRACKING_RESP ); CASE_RETURN_STRING( WDI_8023_MULTICAST_LIST_RESP ); CASE_RETURN_STRING( WDI_RECEIVE_FILTER_SET_FILTER_RESP ); @@ -5715,52 +5727,6 @@ WDI_TrafficStatsInd }/*WDI_TrafficStatsInd*/ -#ifdef WLAN_FEATURE_11W -/** - @brief WDI_ExcludeUnencryptedInd - Register with HAL to receive/drop unencrypted frames - - @param WDI_ExcludeUnencryptIndType - - @see - - @return Status of the request -*/ -WDI_Status -WDI_ExcludeUnencryptedInd -( - WDI_ExcludeUnencryptIndType *pWdiExcUnencParams -) -{ - - WDI_EventInfoType wdiEventData; - /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - - /*------------------------------------------------------------------------ - Sanity Check - ------------------------------------------------------------------------*/ - if ( eWLAN_PAL_FALSE == gWDIInitialized ) - { - WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, - "WDI API call before module is initialized - Fail request"); - - return WDI_STATUS_E_NOT_ALLOWED; - } - - /*------------------------------------------------------------------------ - Fill in Event data and post to the Main FSM - ------------------------------------------------------------------------*/ - wdiEventData.wdiRequest = WDI_EXCLUDE_UNENCRYPTED_IND; - wdiEventData.pEventData = pWdiExcUnencParams; - wdiEventData.uEventDataSize = sizeof(*pWdiExcUnencParams); - wdiEventData.pCBfnc = NULL; - wdiEventData.pUserData = NULL; - - return WDI_PostMainEvent(&gWDICb, WDI_REQUEST_EVENT, &wdiEventData); - -}/*WDI_TrafficStatsInd*/ -#endif - /** @brief WDI_HALDumpCmdReq Post HAL DUMP Command Event @@ -10049,7 +10015,7 @@ WDI_ProcessAddSTASelfReq wpt_uint8* pSendBuffer = NULL; wpt_uint16 usDataOffset = 0; wpt_uint16 usSendSize = 0; - tAddStaSelfParams halAddSTASelfParams; + tAddStaSelfParams_V1 halAddSTASelfParams; /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /*------------------------------------------------------------------------- @@ -10074,9 +10040,9 @@ WDI_ProcessAddSTASelfReq -----------------------------------------------------------------------*/ if (( WDI_STATUS_SUCCESS != WDI_GetMessageBuffer( pWDICtx, WDI_ADD_STA_SELF_REQ, - sizeof(tAddStaSelfParams), + sizeof(tAddStaSelfParams_V1), &pSendBuffer, &usDataOffset, &usSendSize))|| - ( usSendSize < (usDataOffset + sizeof(tAddStaSelfParams) ))) + ( usSendSize < (usDataOffset + sizeof(tAddStaSelfParams_V1) ))) { WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN, "Unable to get send buffer in ADD STA SELF REQ %x %x %x", @@ -10090,10 +10056,22 @@ WDI_ProcessAddSTASelfReq sizeof(pWDICtx->wdiCacheAddSTASelfReq)); wpalMemoryCopy(halAddSTASelfParams.selfMacAddr, - pwdiAddSTASelfReqParams->wdiAddSTASelfInfo.selfMacAddr, 6) ; + pwdiAddSTASelfReqParams->wdiAddSTASelfInfo.selfMacAddr, 6); + halAddSTASelfParams.iface_persona = HAL_IFACE_UNKNOWN; + if (pwdiAddSTASelfReqParams->wdiAddSTASelfInfo.currDeviceMode == VOS_STA_MODE) + { + halAddSTASelfParams.iface_persona = HAL_IFACE_STA_MODE; + } + else if ((pwdiAddSTASelfReqParams->wdiAddSTASelfInfo.currDeviceMode == + VOS_P2P_CLIENT_MODE) || + (pwdiAddSTASelfReqParams->wdiAddSTASelfInfo.currDeviceMode == + VOS_P2P_DEVICE)) + { + halAddSTASelfParams.iface_persona = HAL_IFACE_P2P_MODE; + } wpalMemoryCopy( pSendBuffer+usDataOffset, &halAddSTASelfParams, - sizeof(tAddStaSelfParams)); + sizeof(tAddStaSelfParams_V1)); pWDICtx->wdiReqStatusCB = pwdiAddSTASelfReqParams->wdiReqStatusCB; pWDICtx->pReqStatusUserData = pwdiAddSTASelfReqParams->pUserData; @@ -10565,78 +10543,6 @@ WDI_ProcessTrafficStatsInd return ( wdiStatus != WDI_STATUS_SUCCESS )?wdiStatus:WDI_STATUS_SUCCESS_SYNC; }/*WDI_ProcessTrafficStatsInd*/ -#ifdef WLAN_FEATURE_11W -/** - @brief Process Exclude Unencrypted Indications function (called - when Main FSM allows it) - - @param pWDICtx: pointer to the WLAN DAL context - pEventData: pointer to the event information structure - - @see - @return Result of the function call -*/ -WDI_Status -WDI_ProcessExcludeUnencryptInd -( - WDI_ControlBlockType* pWDICtx, - WDI_EventInfoType* pEventData -) -{ - WDI_ExcludeUnencryptIndType* pWDIExcUnencIndParams; - wpt_uint8* pSendBuffer = NULL; - wpt_uint16 usDataOffset = 0; - wpt_uint16 usSendSize = 0; - WDI_Status wdiStatus; - tHalWlanExcludeUnEncryptedIndParam* pHalExcUnencIndParams; - /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - - /*------------------------------------------------------------------------- - Sanity check - -------------------------------------------------------------------------*/ - if (( NULL == pEventData ) || ( NULL == pEventData->pEventData )) - { - WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN, - "%s: Invalid parameters in Exclude Unencrypted ind",__func__); - WDI_ASSERT(0); - return WDI_STATUS_E_FAILURE; - } - - pWDIExcUnencIndParams = (WDI_ExcludeUnencryptIndType *)pEventData->pEventData; - - /*----------------------------------------------------------------------- - Get message buffer - -----------------------------------------------------------------------*/ - if (( WDI_STATUS_SUCCESS != WDI_GetMessageBuffer( pWDICtx, - WDI_EXCLUDE_UNENCRYPTED_IND, - sizeof(tHalWlanExcludeUnEncryptedIndParam), - &pSendBuffer, &usDataOffset, &usSendSize))|| - (usSendSize < (usDataOffset + sizeof(tHalWlanExcludeUnEncryptedIndParam)))) - { - WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_FATAL, - "Unable to get send buffer in Exclude Unencrypted Ind "); - WDI_ASSERT(0); - return WDI_STATUS_E_FAILURE; - } - - pHalExcUnencIndParams = (tHalWlanExcludeUnEncryptedIndParam*)(pSendBuffer+usDataOffset); - - pHalExcUnencIndParams->bDot11ExcludeUnencrypted = pWDIExcUnencIndParams->bExcludeUnencrypt; - - wpalMemoryCopy(pHalExcUnencIndParams->bssId, - pWDIExcUnencIndParams->bssid, WDI_MAC_ADDR_LEN); - - /*------------------------------------------------------------------------- - Send Suspend Request to HAL - -------------------------------------------------------------------------*/ - pWDICtx->wdiReqStatusCB = pWDIExcUnencIndParams->wdiReqStatusCB; - pWDICtx->pReqStatusUserData = pWDIExcUnencIndParams->pUserData; - - wdiStatus = WDI_SendIndication( pWDICtx, pSendBuffer, usSendSize); - return ( wdiStatus != WDI_STATUS_SUCCESS )?wdiStatus:WDI_STATUS_SUCCESS_SYNC; -}/*WDI_ProcessExcludeUnencryptInd*/ -#endif - /*========================================================================== MISC CONTROL PROCESSING REQUEST API ==========================================================================*/ @@ -13274,7 +13180,8 @@ WDI_ProcessHostOffloadReq if ( NULL == pBSSSes ) { WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, - " %s : Association for this BSSID does not exist",__func__); + " %s : Association for this BSSID does not exist " MAC_ADDRESS_STR, + __func__, MAC_ADDR_ARRAY(pwdiHostOffloadParams->wdiHostOffloadInfo.bssId)); goto fail; } @@ -13312,9 +13219,17 @@ WDI_ProcessHostOffloadReq wpalMemoryCopy(nsOffloadParams.selfMacAddr, pwdiHostOffloadParams->wdiNsOffloadParams.selfMacAddr, 6); - nsOffloadParams.srcIPv6AddrValid = pwdiHostOffloadParams->wdiNsOffloadParams.srcIPv6AddrValid; - nsOffloadParams.targetIPv6Addr1Valid = pwdiHostOffloadParams->wdiNsOffloadParams.targetIPv6Addr1Valid; - nsOffloadParams.targetIPv6Addr2Valid = pwdiHostOffloadParams->wdiNsOffloadParams.targetIPv6Addr2Valid; + nsOffloadParams.srcIPv6AddrValid = + pwdiHostOffloadParams->wdiNsOffloadParams.srcIPv6AddrValid; + + nsOffloadParams.targetIPv6Addr1Valid = + pwdiHostOffloadParams->wdiNsOffloadParams.targetIPv6Addr1Valid; + + nsOffloadParams.targetIPv6Addr2Valid = + pwdiHostOffloadParams->wdiNsOffloadParams.targetIPv6Addr2Valid; + + nsOffloadParams.slotIndex = + pwdiHostOffloadParams->wdiNsOffloadParams.slotIdx; #endif // WLAN_NS_OFFLOAD } @@ -17642,6 +17557,10 @@ WDI_ProcessExitImpsRsp halStatus = *((eHalStatus*)pEventData->pEventData); wdiStatus = WDI_HAL_2_WDI_STATUS(halStatus); + if (halStatus != eHAL_STATUS_SUCCESS) + WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, + "%s: Exit IMPS response is a failure with halStatus %d", __func__, halStatus); + // notify DTS that we are entering Full power wptStatus = WDTS_SetPowerState(pWDICtx, WDTS_POWER_STATE_FULL, NULL); if( eWLAN_PAL_STATUS_SUCCESS != wptStatus ) @@ -19780,7 +19699,7 @@ WDI_ProcessHALDumpCmdRsp wpalMemoryCopy( wdiHALDumpCmdRsp.pBuffer, &halDumpCmdRspParams.rspBuffer, - sizeof(wdiHALDumpCmdRsp.usBufferLen)); + halDumpCmdRspParams.rspLength); } /*Notify UMAC*/ @@ -20363,9 +20282,9 @@ WDI_ResponseTimerCB WDI_ControlBlockType* pWDICtx = (WDI_ControlBlockType*)pUserData; /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - if (NULL == pWDICtx ) + if (NULL == pWDICtx) { - WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN, + WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN, "%s: Invalid parameters", __func__); WDI_ASSERT(0); return; @@ -20388,33 +20307,41 @@ WDI_ResponseTimerCB return; } - if ( WDI_MAX_RESP != pWDICtx->wdiExpectedResponse ) + if (WDI_MAX_RESP != pWDICtx->wdiExpectedResponse) { - WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_FATAL, + WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_FATAL, "Timeout occurred while waiting for %s (%d) message from device " " - catastrophic failure, timeStampTmrStart: %ld, timeStampTmrExp: %ld", WDI_getRespMsgString(pWDICtx->wdiExpectedResponse), pWDICtx->wdiExpectedResponse, pWDICtx->uTimeStampRspTmrStart, pWDICtx->uTimeStampRspTmrExp); - /* WDI timeout means Riva is not responding or SMD communication to Riva - * is not happening. The only possible way to recover from this error - * is to initiate SSR from APPS - * There is also an option to re-enable wifi, which will eventually - * trigger SSR - */ + + /* WDI timeout means Riva is not responding or SMD communication to Riva + * is not happening. The only possible way to recover from this error + * is to initiate SSR from APPS. + * There is also an option to re-enable wifi, which will eventually + * trigger SSR + */ + if (gWDICb.bEnableSSR == false) + { + WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_FATAL, + "SSR is not enabled on WDI timeout"); + WDI_DetectedDeviceError(pWDICtx, WDI_ERR_BASIC_OP_FAILURE); + return; + } #ifndef WDI_RE_ENABLE_WIFI_ON_WDI_TIMEOUT - wpalWcnssResetIntr(); - /* if this timer fires, it means Riva did not receive the FIQ */ - wpalTimerStart(&pWDICtx->ssrTimer, WDI_SSR_TIMEOUT); + wpalWcnssResetIntr(); + /* if this timer fires, it means Riva did not receive the FIQ */ + wpalTimerStart(&pWDICtx->ssrTimer, WDI_SSR_TIMEOUT); #else - WDI_DetectedDeviceError( pWDICtx, WDI_ERR_BASIC_OP_FAILURE); - wpalWlanReload(); + WDI_DetectedDeviceError(pWDICtx, WDI_ERR_BASIC_OP_FAILURE); + wpalWlanReload(); #endif } else { - WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, + WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, "Timeout occurred but not waiting for any response %d " "timeStampTmrStart: %ld, timeStampTmrExp: %ld", pWDICtx->wdiExpectedResponse, pWDICtx->uTimeStampRspTmrStart, @@ -21744,13 +21671,12 @@ WDI_2_HAL_REQ_TYPE return WLAN_HAL_HOST_SUSPEND_IND; case WDI_TRAFFIC_STATS_IND: return WLAN_HAL_CLASS_B_STATS_IND; -#ifdef WLAN_FEATURE_11W - case WDI_EXCLUDE_UNENCRYPTED_IND: - return WLAN_HAL_EXCLUDE_UNENCRYPTED_IND; -#endif case WDI_KEEP_ALIVE_REQ: return WLAN_HAL_KEEP_ALIVE_REQ; - +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + case WDI_ROAM_SCAN_OFFLOAD_REQ: + return WLAN_ROAM_SCAN_OFFLOAD_REQ; +#endif #ifdef FEATURE_WLAN_SCAN_PNO case WDI_SET_PREF_NETWORK_REQ: return WLAN_HAL_SET_PREF_NETWORK_REQ; @@ -21974,6 +21900,10 @@ case WLAN_HAL_DEL_STA_SELF_RSP: case WLAN_HAL_PREF_NETW_FOUND_IND: return WDI_HAL_PREF_NETWORK_FOUND_IND; #endif // FEATURE_WLAN_SCAN_PNO +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + case WLAN_ROAM_SCAN_OFFLOAD_RSP: + return WDI_ROAM_SCAN_OFFLOAD_RESP; +#endif case WLAN_HAL_SET_TX_PER_TRACKING_RSP: return WDI_SET_TX_PER_TRACKING_RESP; #ifdef WLAN_FEATURE_PACKET_FILTERING @@ -22062,8 +21992,8 @@ WDI_2_HAL_STOP_REASON { case WDI_STOP_TYPE_SYS_RESET: return HAL_STOP_TYPE_SYS_RESET; - case WDI_DRIVER_TYPE_MFG: - return WDI_STOP_TYPE_SYS_DEEP_SLEEP; + case WDI_STOP_TYPE_SYS_DEEP_SLEEP: + return HAL_STOP_TYPE_SYS_DEEP_SLEEP; case WDI_STOP_TYPE_RF_KILL: return HAL_STOP_TYPE_RF_KILL; } @@ -22907,6 +22837,14 @@ WDI_ExtractRequestCBFromEvent *ppfnReqCB = ((WDI_EnterUapsdReqParamsType*)pEvent->pEventData)->wdiReqStatusCB; *ppUserData = ((WDI_EnterUapsdReqParamsType*)pEvent->pEventData)->pUserData; break; + case WDI_EXIT_UAPSD_REQ: + *ppfnReqCB = ((WDI_ExitUapsdReqParamsType*)pEvent->pEventData)->wdiReqStatusCB; + *ppUserData = ((WDI_ExitUapsdReqParamsType*)pEvent->pEventData)->pUserData; + break; + case WDI_SET_UAPSD_PARAM_REQ: + *ppfnReqCB = ((WDI_SetUapsdAcParamsReqParamsType*)pEvent->pEventData)->wdiReqStatusCB; + *ppUserData = ((WDI_SetUapsdAcParamsReqParamsType*)pEvent->pEventData)->pUserData; + break; case WDI_UPDATE_UAPSD_PARAM_REQ: *ppfnReqCB = ((WDI_UpdateUapsdReqParamsType*)pEvent->pEventData)->wdiReqStatusCB; *ppUserData = ((WDI_UpdateUapsdReqParamsType*)pEvent->pEventData)->pUserData; @@ -22943,6 +22881,10 @@ WDI_ExtractRequestCBFromEvent *ppfnReqCB = ((WDI_WowlEnterReqParamsType*)pEvent->pEventData)->wdiReqStatusCB; *ppUserData = ((WDI_WowlEnterReqParamsType*)pEvent->pEventData)->pUserData; break; + case WDI_WOWL_EXIT_REQ: + *ppfnReqCB = ((WDI_WowlExitReqParamsType*)pEvent->pEventData)->wdiReqStatusCB; + *ppUserData = ((WDI_WowlExitReqParamsType*)pEvent->pEventData)->pUserData; + break; case WDI_CONFIGURE_APPS_CPU_WAKEUP_STATE_REQ: *ppfnReqCB = ((WDI_ConfigureAppsCpuWakeupStateReqParamsType*)pEvent->pEventData)->wdiReqStatusCB; *ppUserData = ((WDI_ConfigureAppsCpuWakeupStateReqParamsType*)pEvent->pEventData)->pUserData; @@ -22959,10 +22901,29 @@ WDI_ExtractRequestCBFromEvent *ppfnReqCB = ((WDI_KeepAliveReqParamsType*)pEvent->pEventData)->wdiReqStatusCB; *ppUserData = ((WDI_KeepAliveReqParamsType*)pEvent->pEventData)->pUserData; break; +#if defined FEATURE_WLAN_SCAN_PNO + case WDI_SET_PREF_NETWORK_REQ: + *ppfnReqCB = ((WDI_PNOScanReqParamsType*)pEvent->pEventData)->wdiReqStatusCB; + *ppUserData = ((WDI_PNOScanReqParamsType*)pEvent->pEventData)->pUserData; + break; + case WDI_SET_RSSI_FILTER_REQ: + *ppfnReqCB = ((WDI_SetRssiFilterReqParamsType*)pEvent->pEventData)->wdiReqStatusCB; + *ppUserData = ((WDI_SetRssiFilterReqParamsType*)pEvent->pEventData)->pUserData; + break; + case WDI_UPDATE_SCAN_PARAMS_REQ: + *ppfnReqCB = ((WDI_UpdateScanParamsInfoType*)pEvent->pEventData)->wdiReqStatusCB; + *ppUserData = ((WDI_UpdateScanParamsInfoType*)pEvent->pEventData)->pUserData; + break; +#endif case WDI_SET_TX_PER_TRACKING_REQ: *ppfnReqCB = ((WDI_SetTxPerTrackingReqParamsType*)pEvent->pEventData)->wdiReqStatusCB; *ppUserData = ((WDI_SetTxPerTrackingReqParamsType*)pEvent->pEventData)->pUserData; break; +#if defined WLAN_FEATURE_PACKET_FILTERING + case WDI_8023_MULTICAST_LIST_REQ: + *ppfnReqCB = ((WDI_RcvFltPktSetMcListReqParamsType*)pEvent->pEventData)->wdiReqStatusCB; + *ppUserData = ((WDI_RcvFltPktSetMcListReqParamsType*)pEvent->pEventData)->pUserData; + break; case WDI_RECEIVE_FILTER_SET_FILTER_REQ: *ppfnReqCB = ((WDI_SetRcvPktFilterReqParamsType*)pEvent->pEventData)->wdiReqStatusCB; *ppUserData = ((WDI_SetRcvPktFilterReqParamsType*)pEvent->pEventData)->pUserData; @@ -22975,6 +22936,21 @@ WDI_ExtractRequestCBFromEvent *ppfnReqCB = ((WDI_RcvFltPktClearReqParamsType*)pEvent->pEventData)->wdiReqStatusCB; *ppUserData = ((WDI_RcvFltPktClearReqParamsType*)pEvent->pEventData)->pUserData; break; +#endif + case WDI_SET_POWER_PARAMS_REQ: + *ppfnReqCB = ((WDI_SetPowerParamsReqParamsType*)pEvent->pEventData)->wdiReqStatusCB; + *ppUserData = ((WDI_SetPowerParamsReqParamsType*)pEvent->pEventData)->pUserData; + break; +#if defined WLAN_FEATURE_GTK_OFFLOAD + case WDI_GTK_OFFLOAD_REQ: + *ppfnReqCB = ((WDI_GtkOffloadReqMsg*)pEvent->pEventData)->wdiReqStatusCB; + *ppUserData = ((WDI_GtkOffloadReqMsg*)pEvent->pEventData)->pUserData; + break; + case WDI_GTK_OFFLOAD_GETINFO_REQ: + *ppfnReqCB = ((WDI_GtkOffloadGetInfoReqMsg*)pEvent->pEventData)->wdiReqStatusCB; + *ppUserData = ((WDI_GtkOffloadGetInfoReqMsg*)pEvent->pEventData)->pUserData; + break; +#endif default: *ppfnReqCB = NULL; @@ -23624,7 +23600,338 @@ WDI_ProcessSetRssiFilterReq return WDI_SendMsg( pWDICtx, pSendBuffer, usSendSize, wdiRssiFilterCb, pEventData->pUserData, WDI_SET_RSSI_FILTER_RESP); } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +/** + @brief WDI_RoamScanOffloadReq + + @param pwdiRoamScanOffloadReqParams: the LookupReq as specified + by the Device Interface + + wdiRoamOffloadScancb: callback for passing back the response + of the Roam Candidate Lookup Req operation received from the + device + + pUserData: user data will be passed back with the + callback + @return Result of the function call +*/ +WDI_Status +WDI_RoamScanOffloadReq +( + WDI_RoamScanOffloadReqParamsType* pwdiRoamScanOffloadReqParams, + WDI_RoamOffloadScanCb wdiRoamOffloadScancb, + void* pUserData +) +{ + WDI_EventInfoType wdiEventData = {{0}}; + /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + + /*------------------------------------------------------------------------ + Sanity Check + ------------------------------------------------------------------------*/ + if ( eWLAN_PAL_FALSE == gWDIInitialized ) + { + WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, + "WDI API call before module is initialized - Fail request"); + + return WDI_STATUS_E_NOT_ALLOWED; + } + + /*------------------------------------------------------------------------ + Fill in Event data and post to the Main FSM + ------------------------------------------------------------------------*/ + wdiEventData.wdiRequest = WDI_ROAM_SCAN_OFFLOAD_REQ; + wdiEventData.pEventData = pwdiRoamScanOffloadReqParams; + wdiEventData.uEventDataSize = sizeof(*pwdiRoamScanOffloadReqParams); + wdiEventData.pCBfnc = wdiRoamOffloadScancb; + wdiEventData.pUserData = pUserData; + + return WDI_PostMainEvent(&gWDICb, WDI_REQUEST_EVENT, &wdiEventData); +} + +void +WDI_wdiEdTypeEncToEdTypeEnc(tEdType *EdType, WDI_EdType wdiEdType) +{ + switch (wdiEdType) + { + case WDI_ED_NONE: + *EdType = eED_NONE; + break; + case WDI_ED_WEP40: + case WDI_ED_WEP104: + *EdType = eED_WEP; + break; + case WDI_ED_TKIP: + *EdType = eED_TKIP; + break; + case WDI_ED_CCMP: +#ifdef WLAN_FEATURE_11W + case WDI_ED_AES_128_CMAC: +#endif + *EdType = eED_CCMP; + break; +#ifdef FEATURE_WLAN_WAPI + case WDI_ED_WPI: + *EdType = eED_WPI; + break; +#endif + case WDI_ED_ANY: + *EdType = eED_ANY; + break; + + default: + WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN, + "%s: Unknown Encryption Type", __func__); + break; + } +} + +/** + @brief Helper function to pack Start Roam Candidate Lookup + Request parameters + + @param pWDICtx: pointer to the WLAN DAL context + pwdiRoamScanOffloadReqParams: pointer to the info received + from upper layers + ppSendBuffer, pSize - out pointers of the packed buffer + and its size + + @return Result of the function call +*/ + +WDI_Status +WDI_PackRoamScanOffloadParams +( + WDI_ControlBlockType* pWDICtx, + WDI_RoamScanOffloadReqParamsType* pwdiRoamScanOffloadReqParams, + wpt_uint8** ppSendBuffer, + wpt_uint16* pSize +) +{ + wpt_uint8* pSendBuffer = NULL; + wpt_uint16 usDataOffset = 0; + wpt_uint16 usSendSize = 0; + tpRoamCandidateListParams pRoamCandidateListParams = NULL; + wpt_uint8 i; + /*----------------------------------------------------------------------- + Get message buffer + -----------------------------------------------------------------------*/ + if (( WDI_STATUS_SUCCESS != WDI_GetMessageBuffer( pWDICtx, WDI_ROAM_SCAN_OFFLOAD_REQ, + sizeof(tRoamCandidateListParams), + &pSendBuffer, &usDataOffset, &usSendSize))|| + ( usSendSize < (usDataOffset + sizeof(tpRoamCandidateListParams) ))) + { + WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN, + "Unable to get send buffer in Start Roam Candidate Lookup Req %x ", + pwdiRoamScanOffloadReqParams); + WDI_ASSERT(0); + return WDI_STATUS_E_FAILURE; + } + pRoamCandidateListParams = (tpRoamCandidateListParams)(pSendBuffer + usDataOffset); + wpalMemoryZero(pRoamCandidateListParams, sizeof(tpRoamCandidateListParams)); + pRoamCandidateListParams->RoamScanOffloadEnabled = pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.RoamScanOffloadEnabled; + wpalMemoryCopy(pRoamCandidateListParams->ConnectedNetwork.currAPbssid, + pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.ConnectedNetwork.currAPbssid, + HAL_MAC_ADDR_LEN); + pRoamCandidateListParams->ConnectedNetwork.authentication = pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.ConnectedNetwork.authentication; + WDI_wdiEdTypeEncToEdTypeEnc(&pRoamCandidateListParams->ConnectedNetwork.encryption, + pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.ConnectedNetwork.encryption); + WDI_wdiEdTypeEncToEdTypeEnc(&pRoamCandidateListParams->ConnectedNetwork.mcencryption, + pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.ConnectedNetwork.mcencryption); + + pRoamCandidateListParams->ConnectedNetwork.ssId.length + = pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.ConnectedNetwork.ssId.ucLength; + wpalMemoryCopy( pRoamCandidateListParams->ConnectedNetwork.ssId.ssId, + pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.ConnectedNetwork.ssId.sSSID, + pRoamCandidateListParams->ConnectedNetwork.ssId.length); + wpalMemoryCopy(pRoamCandidateListParams->ConnectedNetwork.ChannelCache, + pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.ConnectedNetwork.ChannelCache, + pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.ConnectedNetwork.ChannelCount ); + pRoamCandidateListParams->ConnectedNetwork.ChannelCount = pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.ConnectedNetwork.ChannelCount; + pRoamCandidateListParams->ChannelCacheType = pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.ChannelCacheType ; + pRoamCandidateListParams->LookupThreshold = pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.LookupThreshold; + pRoamCandidateListParams->RoamRssiDiff = pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.RoamRssiDiff ; + pRoamCandidateListParams->Command = pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.Command ; + pRoamCandidateListParams->StartScanReason = pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.StartScanReason ; + pRoamCandidateListParams->NeighborScanTimerPeriod = pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.NeighborScanTimerPeriod ; + pRoamCandidateListParams->NeighborRoamScanRefreshPeriod = pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.NeighborRoamScanRefreshPeriod ; + pRoamCandidateListParams->NeighborScanChannelMinTime = pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.NeighborScanChannelMinTime ; + pRoamCandidateListParams->NeighborScanChannelMaxTime = pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.NeighborScanChannelMaxTime ; + pRoamCandidateListParams->EmptyRefreshScanPeriod = pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.EmptyRefreshScanPeriod ; + pRoamCandidateListParams->IsCCXEnabled = pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.IsCCXEnabled ; + wpalMemoryCopy(pRoamCandidateListParams->ValidChannelList, + pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.ValidChannelList, + pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.ValidChannelCount); + pRoamCandidateListParams->ValidChannelCount = pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.ValidChannelCount; + + WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO_HIGH, + "Values are ssid = %s, RoamOffloadScan=%d,Command=%d," + "StartScanReason=%d,NeighborScanTimerPeriod=%d," + "NeighborRoamScanRefreshPeriod=%d,NeighborScanChannelMinTime=%d," + "NeighborScanChannelMaxTime = %d,EmptyRefreshScanPeriod=%d," + "mdiePresent=%d,MDID=%d, auth=%d, uce=%d, mce=%d, nProbes=%d," + "HomeAwayTime=%d\n", + pRoamCandidateListParams->ConnectedNetwork.ssId.ssId, + pRoamCandidateListParams->RoamScanOffloadEnabled, + pRoamCandidateListParams->Command, + pRoamCandidateListParams->StartScanReason, + pRoamCandidateListParams->NeighborScanTimerPeriod, + pRoamCandidateListParams->NeighborRoamScanRefreshPeriod, + pRoamCandidateListParams->NeighborScanChannelMinTime, + pRoamCandidateListParams->NeighborScanChannelMaxTime, + pRoamCandidateListParams->EmptyRefreshScanPeriod, + pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.MDID.mdiePresent, + pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.MDID.mobilityDomain, + pRoamCandidateListParams->ConnectedNetwork.authentication, + pRoamCandidateListParams->ConnectedNetwork.encryption, + pRoamCandidateListParams->ConnectedNetwork.mcencryption, + pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.nProbes, + pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.HomeAwayTime); + pRoamCandidateListParams->us24GProbeSize = + (pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.us24GProbeSize< + WLAN_HAL_ROAM_SCAN_MAX_PROBE_SIZE)? + pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.us24GProbeSize: + WLAN_HAL_ROAM_SCAN_MAX_PROBE_SIZE; + wpalMemoryCopy(pRoamCandidateListParams->a24GProbeTemplate, + pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.a24GProbeTemplate, + pRoamCandidateListParams->us24GProbeSize); + pRoamCandidateListParams->us5GProbeSize = + (pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.us5GProbeSize< + WLAN_HAL_ROAM_SCAN_MAX_PROBE_SIZE)? + pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.us5GProbeSize: + WLAN_HAL_ROAM_SCAN_MAX_PROBE_SIZE; + wpalMemoryCopy(pRoamCandidateListParams->a5GProbeTemplate, + pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.a5GProbeTemplate, + pRoamCandidateListParams->us5GProbeSize); + pRoamCandidateListParams->MDID.mdiePresent = pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.MDID.mdiePresent; + pRoamCandidateListParams->MDID.mobilityDomain = pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.MDID.mobilityDomain; + pRoamCandidateListParams->nProbes = + pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.nProbes; + pRoamCandidateListParams->HomeAwayTime = + pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.HomeAwayTime; + WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO_HIGH,"Valid Channel List"); + for (i=0; iValidChannelCount ; i++) + { + WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO_HIGH,"%d", pRoamCandidateListParams->ValidChannelList[i]); + } + + + /*Set the output values*/ + *ppSendBuffer = pSendBuffer; + *pSize = usSendSize; + return WDI_STATUS_SUCCESS; +}/*WDI_PackRoamScanOffloadParams*/ + +/** + @brief Process Start Roam Candidate Lookup Request function + + @param pWDICtx: pointer to the WLAN DAL context + pEventData: pointer to the event information structure + + @return Result of the function call +*/ +WDI_Status +WDI_ProcessRoamScanOffloadReq +( + WDI_ControlBlockType* pWDICtx, + WDI_EventInfoType* pEventData +) +{ + WDI_RoamScanOffloadReqParamsType* pwdiRoamScanOffloadReqParams = NULL; + WDI_RoamOffloadScanCb wdiRoamOffloadScancb = NULL; + wpt_uint8* pSendBuffer = NULL; + wpt_uint16 usSendSize = 0; + WDI_Status wdiStatus; + /*------------------------------------------------------------------------- + Sanity check + -------------------------------------------------------------------------*/ + if (( NULL == pEventData ) || + ( NULL == (pwdiRoamScanOffloadReqParams = (WDI_RoamScanOffloadReqParamsType*)pEventData->pEventData)) || + ( NULL == (wdiRoamOffloadScancb = (WDI_RoamOffloadScanCb)pEventData->pCBfnc))) + { + WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN, + "%s: Invalid parameters", __func__); + WDI_ASSERT(0); + return WDI_STATUS_E_FAILURE; + } + + /*------------------------------------------------------------------------- + Pack the Start Roam Candidate Lookup request structure based on version + -------------------------------------------------------------------------*/ + WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO, + "%s: Packing Roam Candidate Lookup request ", __func__); + + wdiStatus = WDI_PackRoamScanOffloadParams( pWDICtx, pwdiRoamScanOffloadReqParams, + &pSendBuffer, &usSendSize); + + if (( WDI_STATUS_SUCCESS != wdiStatus )|| + ( NULL == pSendBuffer )||( 0 == usSendSize )) + { + WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN, + "%s: failed to pack request parameters", __func__); + WDI_ASSERT(0); + return wdiStatus; + } + + pWDICtx->wdiReqStatusCB = pwdiRoamScanOffloadReqParams->wdiReqStatusCB; + pWDICtx->pReqStatusUserData = pwdiRoamScanOffloadReqParams->pUserData; + + /*------------------------------------------------------------------------- + Send WDI_ROAM_SCAN_OFFLOAD_REQ to HAL + -------------------------------------------------------------------------*/ + return WDI_SendMsg( pWDICtx, pSendBuffer, usSendSize, + wdiRoamOffloadScancb, pEventData->pUserData, WDI_ROAM_SCAN_OFFLOAD_RESP); +} + +/** + @brief Process Start Roam Candidate Lookup Rsp function (called when a + response is being received over the bus from HAL) + + @param pWDICtx: pointer to the WLAN DAL context + pEventData: pointer to the event information structure + + @see + @return Result of the function call +*/ +WDI_Status +WDI_ProcessRoamScanOffloadRsp +( + WDI_ControlBlockType* pWDICtx, + WDI_EventInfoType* pEventData +) +{ + WDI_Status wdiStatus; + eHalStatus halStatus; + WDI_RoamOffloadScanCb wdiRoamOffloadScancb = NULL; + + /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + + /*------------------------------------------------------------------------- + Sanity check + -------------------------------------------------------------------------*/ + if (( NULL == pWDICtx ) || ( NULL == pEventData ) || + ( NULL == pEventData->pEventData )) + { + WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN, + "%s: Invalid parameters", __func__); + WDI_ASSERT(0); + return WDI_STATUS_E_FAILURE; + } + wdiRoamOffloadScancb = (WDI_RoamOffloadScanCb)pWDICtx->pfncRspCB; + + /*------------------------------------------------------------------------- + Extract response and send it to UMAC + -------------------------------------------------------------------------*/ + halStatus = *((eHalStatus*)pEventData->pEventData); + wdiStatus = WDI_HAL_2_WDI_STATUS(halStatus); + + /*Notify UMAC*/ + wdiRoamOffloadScancb(wdiStatus, pWDICtx->pRspCBUserData); + + return WDI_STATUS_SUCCESS; +}/* WDI_ProcessRoamScanOffloadRsp */ +#endif /** @brief Process Update Scan Params function @@ -23867,8 +24174,9 @@ WDI_ProcessPrefNetworkFoundInd WDI_EventInfoType* pEventData ) { - WDI_LowLevelIndType wdiInd; - tPrefNetwFoundInd prefNetwFoundInd = {{0}}; + WDI_LowLevelIndType wdiInd; + tpPrefNetwFoundParams pNetwFoundParams; + wpt_uint32 msgsize; /*------------------------------------------------------------------------- @@ -23886,25 +24194,34 @@ WDI_ProcessPrefNetworkFoundInd /*------------------------------------------------------------------------- Extract indication and send it to UMAC -------------------------------------------------------------------------*/ - wpalMemoryCopy( (void *)&prefNetwFoundInd.prefNetwFoundParams, - pEventData->pEventData, - sizeof(tPrefNetwFoundParams)); + pNetwFoundParams = (tpPrefNetwFoundParams)(pEventData->pEventData); - /*Fill in the indication parameters*/ - wdiInd.wdiIndicationType = WDI_PREF_NETWORK_FOUND_IND; + msgsize = sizeof(tPrefNetwFoundParams) + pNetwFoundParams->frameLength; + wdiInd.wdiIndicationData.wdiPrefNetworkFoundInd.pData = + (wpt_uint8 *)wpalMemoryAllocate(msgsize); - wpalMemoryZero(wdiInd.wdiIndicationData.wdiPrefNetworkFoundInd.ssId.sSSID,32); + if (NULL == wdiInd.wdiIndicationData.wdiPrefNetworkFoundInd.pData) + { + WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, + "%s: fail to allocate memory", __func__); + return WDI_STATUS_MEM_FAILURE; + } wdiInd.wdiIndicationData.wdiPrefNetworkFoundInd.ssId.ucLength = - (prefNetwFoundInd.prefNetwFoundParams.ssId.length < 31 )? - prefNetwFoundInd.prefNetwFoundParams.ssId.length : 31; - + (pNetwFoundParams->ssId.length < 32 )? + pNetwFoundParams->ssId.length : 32; wpalMemoryCopy( wdiInd.wdiIndicationData.wdiPrefNetworkFoundInd.ssId.sSSID, - prefNetwFoundInd.prefNetwFoundParams.ssId.ssId, - wdiInd.wdiIndicationData.wdiPrefNetworkFoundInd.ssId.ucLength); + pNetwFoundParams->ssId.ssId, + wdiInd.wdiIndicationData.wdiPrefNetworkFoundInd.ssId.ucLength); + wdiInd.wdiIndicationData.wdiPrefNetworkFoundInd.rssi = pNetwFoundParams->rssi; + wdiInd.wdiIndicationData.wdiPrefNetworkFoundInd.frameLength = + pNetwFoundParams->frameLength; + wpalMemoryCopy( wdiInd.wdiIndicationData.wdiPrefNetworkFoundInd.pData, + (wpt_uint8 *)pEventData->pEventData + sizeof(tPrefNetwFoundParams), + pNetwFoundParams->frameLength); - wdiInd.wdiIndicationData.wdiPrefNetworkFoundInd.rssi = - prefNetwFoundInd.prefNetwFoundParams.rssi; + /*Fill in the indication parameters*/ + wdiInd.wdiIndicationType = WDI_PREF_NETWORK_FOUND_IND; // DEBUG WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_FATAL, @@ -24319,6 +24636,7 @@ WDI_Process8023MulticastListReq "WDI_Process8023MulticastListReq() %x %x %x", pEventData, pwdiFltPktSetMcListReqParamsType, wdi8023MulticastListCb); + wpalMemoryFree(pRcvFltMcAddrListType); WDI_ASSERT(0); return WDI_STATUS_E_FAILURE; } @@ -25243,6 +25561,9 @@ WDI_ProcessSetPowerParamsReq powerParams.uBETInterval = pwdiPowerParamsReqParams->wdiSetPowerParamsInfo.uBETInterval; + /* MAX LI for modulated DTIM */ + powerParams.uMaxLIModulatedDTIM = + pwdiPowerParamsReqParams->wdiSetPowerParamsInfo.uMaxLIModulatedDTIM; wpalMemoryCopy( pSendBuffer+usDataOffset, &powerParams, @@ -26478,3 +26799,17 @@ WDI_SsrTimerCB return; }/*WDI_SsrTimerCB*/ + +/** + @brief WDI_SetEnableSSR - + This API is called to enable/disable SSR on WDI timeout. + + @param enableSSR : enable/disable SSR + + @see + @return none +*/ +void WDI_SetEnableSSR(wpt_boolean enableSSR) +{ + gWDICb.bEnableSSR = enableSSR; +} diff --git a/drivers/staging/prima/CORE/WDI/CP/src/wlan_qct_wdi_dp.c b/drivers/staging/prima/CORE/WDI/CP/src/wlan_qct_wdi_dp.c index 04b9db084b3..7cc3571c5f7 100644 --- a/drivers/staging/prima/CORE/WDI/CP/src/wlan_qct_wdi_dp.c +++ b/drivers/staging/prima/CORE/WDI/CP/src/wlan_qct_wdi_dp.c @@ -607,13 +607,21 @@ WDI_FillTxBd * Sanity: Force HW frame translation OFF for mgmt frames. --------------------------------------------------------------------*/ /* apply to both ucast/mcast mgmt frames */ - if (useStaRateForBcastFrames) + /* Probe requests are sent using BD rate */ + if( ucSubType == WDI_MAC_MGMT_PROBE_REQ ) { - pBd->bdRate = (ucUnicastDst)? WDI_BDRATE_BCMGMT_FRAME : WDI_TXBD_BDRATE_DEFAULT; + pBd->bdRate = WDI_BDRATE_BCMGMT_FRAME; } else { - pBd->bdRate = WDI_BDRATE_BCMGMT_FRAME; + if (useStaRateForBcastFrames) + { + pBd->bdRate = (ucUnicastDst)? WDI_BDRATE_BCMGMT_FRAME : WDI_TXBD_BDRATE_DEFAULT; + } + else + { + pBd->bdRate = WDI_BDRATE_BCMGMT_FRAME; + } } if ( ucTxFlag & WDI_USE_BD_RATE2_FOR_MANAGEMENT_FRAME) @@ -677,8 +685,6 @@ WDI_FillTxBd if (WDI_STATUS_SUCCESS != wdiStatus) { WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR, "WDI_STATableFindStaidByAddr failed"); - WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR, "STA ID = %d " MAC_ADDRESS_STR, - ucStaId, MAC_ADDR_ARRAY(*(wpt_macAddr*)pAddr2)); return WDI_STATUS_E_NOT_ALLOWED; } #else @@ -844,25 +850,7 @@ WDI_FillTxBd if(!ucUnicastDst) pBd->dpuDescIdx = pSta->bcastMgmtDpuIndex; /* IGTK */ else - { - wpt_uint8 peerStaId; - - //We need to find the peer's station's DPU index to send this - //frame using PTK - wdiStatus = WDI_STATableFindStaidByAddr( pWDICtx, - *(wpt_macAddr*)pDestMacAddr, &peerStaId ); - if (WDI_STATUS_SUCCESS != wdiStatus) - { - WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR, - "%s failed to find peer sta %02X-%02X-%02X-%02X-%02X-%02X", - __FUNCTION__, ((wpt_uint8 *)pDestMacAddr)[0], - ((wpt_uint8 *)pDestMacAddr)[1], ((wpt_uint8 *)pDestMacAddr)[5], - ((wpt_uint8 *)pDestMacAddr)[3], ((wpt_uint8 *)pDestMacAddr)[4], - ((wpt_uint8 *)pDestMacAddr)[5]); - return WDI_STATUS_E_FAILURE; - } - pBd->dpuDescIdx = ((WDI_StaStruct*)pWDICtx->staTable)[peerStaId].dpuIndex; /* PTK */ - } + pBd->dpuDescIdx = pSta->dpuIndex; /* PTK */ } else { diff --git a/drivers/staging/prima/CORE/WDI/DP/inc/wlan_qct_wdi_ds.h b/drivers/staging/prima/CORE/WDI/DP/inc/wlan_qct_wdi_ds.h index c23d2cb6230..53cc6cd7915 100644 --- a/drivers/staging/prima/CORE/WDI/DP/inc/wlan_qct_wdi_ds.h +++ b/drivers/staging/prima/CORE/WDI/DP/inc/wlan_qct_wdi_ds.h @@ -166,6 +166,10 @@ typedef struct #ifdef WLAN_FEATURE_11W wpt_uint32 rmf:1; #endif +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + wpt_uint32 offloadScanLearn; + wpt_uint32 roamCandidateInd; +#endif } WDI_DS_RxMetaInfoType; typedef struct sPktMetaInfo diff --git a/drivers/staging/prima/CORE/WDI/TRP/DTS/src/wlan_qct_wdi_dts.c b/drivers/staging/prima/CORE/WDI/TRP/DTS/src/wlan_qct_wdi_dts.c index 1c9b4e7ef5a..e6ff98fabaf 100644 --- a/drivers/staging/prima/CORE/WDI/TRP/DTS/src/wlan_qct_wdi_dts.c +++ b/drivers/staging/prima/CORE/WDI/TRP/DTS/src/wlan_qct_wdi_dts.c @@ -614,6 +614,10 @@ wpt_status WDTS_RxPacket (void *pContext, wpt_packet *pFrame, WDTS_ChannelType c #ifdef WLAN_FEATURE_11W pRxMetadata->rmf = WDI_RX_BD_GET_RMF(pBDHeader); #endif +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + pRxMetadata->offloadScanLearn = WDI_RX_BD_GET_OFFLOADSCANLEARN(pBDHeader); + pRxMetadata->roamCandidateInd = WDI_RX_BD_GET_ROAMCANDIDATEIND(pBDHeader); +#endif /* typeSubtype in BD doesn't look like correct. Fill from frame ctrl TL does it for Volans but TL does not know BD for Prima. WDI should do it */ @@ -690,6 +694,7 @@ wpt_status WDTS_RxPacket (void *pContext, wpt_packet *pFrame, WDTS_ChannelType c pRxMetadata = WDI_DS_ExtractRxMetaData(pFrame); //flow control related pRxMetadata->fc = isFcBd; + pRxMetadata->mclkRxTimestamp = WDI_RX_BD_GET_TIMESTAMP(pBDHeader); pRxMetadata->fcStaTxDisabledBitmap = WDI_RX_FC_BD_GET_STA_TX_DISABLED_BITMAP(pBDHeader); pRxMetadata->fcSTAValidMask = WDI_RX_FC_BD_GET_STA_VALID_MASK(pBDHeader); // Invoke Rx complete callback diff --git a/drivers/staging/prima/CORE/WDI/WPAL/inc/wlan_qct_os_trace.h b/drivers/staging/prima/CORE/WDI/WPAL/inc/wlan_qct_os_trace.h index 13c274cac6f..2af6fc2eab9 100644 --- a/drivers/staging/prima/CORE/WDI/WPAL/inc/wlan_qct_os_trace.h +++ b/drivers/staging/prima/CORE/WDI/WPAL/inc/wlan_qct_os_trace.h @@ -1,44 +1,23 @@ /* - * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. - * - * Previously licensed under the ISC license by Qualcomm Atheros, Inc. - * - * - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all - * copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ -/* - * Copyright (c) 2012, The Linux Foundation. All rights reserved. - * - * Previously licensed under the ISC license by Qualcomm Atheros, Inc. - * - * - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all - * copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - + * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. +*/ #if !defined( __WLAN_QCT_OS_TRACE_H ) #define __WLAN_QCT_OS_TRACE_H @@ -96,9 +75,6 @@ void wpalTrace( wpt_moduleid module, wpt_tracelevel level, char *strFormat, ... void wpalDump( wpt_moduleid module, wpt_tracelevel level, wpt_uint8 *memory, wpt_uint32 length); -#define WPAL_TRACE wpalTrace -#define WPAL_DUMP wpalDump - #define WPAL_ASSERT( _condition ) do { \ if ( ! ( _condition ) ) \ { \ @@ -108,10 +84,18 @@ void wpalDump( wpt_moduleid module, wpt_tracelevel level, } while (0) #else //WLAN_DEBUG -#define WPAL_TRACE -#define WPAL_DUMP -#define WPAL_ASSERT +static inline void wpalTrace( wpt_moduleid module, wpt_tracelevel level, + char *strFormat, ... ){}; +static inline void wpalDump( wpt_moduleid module, wpt_tracelevel level, + wpt_uint8 *memory, wpt_uint32 length) {}; +static inline void wpalTraceSetLevel( wpt_moduleid module, + wpt_tracelevel level, wpt_boolean on ) {}; +static inline void wpalTraceDisplay(void) {}; +#define WPAL_ASSERT(x) do {} while (0); #endif //WLAN_DEBUG +#define WPAL_TRACE wpalTrace +#define WPAL_DUMP wpalDump + #endif // __WLAN_QCT_OS_TRACE_H diff --git a/drivers/staging/prima/CORE/WDI/WPAL/inc/wlan_qct_pal_packet.h b/drivers/staging/prima/CORE/WDI/WPAL/inc/wlan_qct_pal_packet.h index 8c09035a262..46d548495b9 100644 --- a/drivers/staging/prima/CORE/WDI/WPAL/inc/wlan_qct_pal_packet.h +++ b/drivers/staging/prima/CORE/WDI/WPAL/inc/wlan_qct_pal_packet.h @@ -39,6 +39,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ + #if !defined( __WLAN_QCT_PAL_PACKET_H ) #define __WLAN_QCT_PAL_PACKET_H @@ -50,10 +51,6 @@ Definitions for platform independent. - Copyright 2010 (c) Qualcomm, Incorporated. All Rights Reserved. - - Qualcomm Confidential and Proprietary. - ========================================================================*/ #include "wlan_qct_pal_type.h" @@ -329,4 +326,14 @@ wpt_int32 wpalPacketGetFragCount(wpt_packet *pPkt); ---------------------------------------------------------------------------*/ wpt_status wpalIsPacketLocked( wpt_packet *pPacket); +/*--------------------------------------------------------------------------- + wpalGetNumRxRawPacket Query available RX RAW total buffer count + param: + numRxResource pointer of queried value + + return: + eWLAN_PAL_STATUS_SUCCESS +---------------------------------------------------------------------------*/ +wpt_status wpalGetNumRxRawPacket(wpt_uint32 *numRxResource); + #endif // __WLAN_QCT_PAL_PACKET_H diff --git a/drivers/staging/prima/CORE/WDI/WPAL/src/wlan_qct_pal_packet.c b/drivers/staging/prima/CORE/WDI/WPAL/src/wlan_qct_pal_packet.c index 1f13c6338af..43cbde7c09e 100644 --- a/drivers/staging/prima/CORE/WDI/WPAL/src/wlan_qct_pal_packet.c +++ b/drivers/staging/prima/CORE/WDI/WPAL/src/wlan_qct_pal_packet.c @@ -184,13 +184,16 @@ wpt_packet * wpalPacketAlloc(wpt_packet_type pktType, wpt_uint32 nPktSize, wpalPacketAvailableCB = rxLowCB; } #endif /* FEATURE_R33D */ - vos_pkt_get_packet_length(pVosPkt, &allocLen); - if (nPktSize != allocLen) + if((NULL != pVosPkt) && (VOS_STATUS_E_RESOURCES != vosStatus)) { - WPAL_TRACE(eWLAN_MODULE_PAL, eWLAN_PAL_TRACE_LEVEL_ERROR, - "RX packet alloc has problem, discard this frame, Len %d", allocLen); - vos_pkt_return_packet(pVosPkt); - return NULL; + vos_pkt_get_packet_length(pVosPkt, &allocLen); + if (nPktSize != allocLen) + { + WPAL_TRACE(eWLAN_MODULE_PAL, eWLAN_PAL_TRACE_LEVEL_ERROR, + "RX packet alloc has problem, discard this frame, Len %d", allocLen); + vos_pkt_return_packet(pVosPkt); + return NULL; + } } break; @@ -794,7 +797,7 @@ wpt_status wpalIsPacketLocked( wpt_packet *pPacket) /* Validate the parameter pointers */ if (NULL == pPacket) { - WPAL_TRACE(eWLAN_MODULE_PAL, eWLAN_PAL_TRACE_LEVEL_ERROR, + WPAL_TRACE(eWLAN_MODULE_PAL, eWLAN_PAL_TRACE_LEVEL_WARN, "%s : NULL input pointer", __func__); return eWLAN_PAL_STATUS_E_INVAL; } @@ -805,3 +808,17 @@ wpt_status wpalIsPacketLocked( wpt_packet *pPacket) eWLAN_PAL_STATUS_SUCCESS; }/*wpalIsPacketLocked*/ +/*--------------------------------------------------------------------------- + wpalGetNumRxRawPacket Query available RX RAW total buffer count + param: + numRxResource pointer of queried value + + return: + eWLAN_PAL_STATUS_SUCCESS +---------------------------------------------------------------------------*/ +wpt_status wpalGetNumRxRawPacket(wpt_uint32 *numRxResource) +{ + *numRxResource = (wpt_uint32)vos_pkt_get_num_of_rx_raw_pkts(); + + return eWLAN_PAL_STATUS_SUCCESS; +} diff --git a/drivers/staging/prima/CORE/WDI/WPAL/src/wlan_qct_pal_trace.c b/drivers/staging/prima/CORE/WDI/WPAL/src/wlan_qct_pal_trace.c index 914e00fdff5..e2c86ace29c 100644 --- a/drivers/staging/prima/CORE/WDI/WPAL/src/wlan_qct_pal_trace.c +++ b/drivers/staging/prima/CORE/WDI/WPAL/src/wlan_qct_pal_trace.c @@ -284,7 +284,7 @@ void wpalTrace( wpt_moduleid module, wpt_tracelevel level, char *strFormat, ... // print the formatted log message after the prefix string. // note we reserve space for the terminating NUL - if (n < WPAL_TRACE_BUFFER_SIZE) + if ((n >= 0) && (n < WPAL_TRACE_BUFFER_SIZE)) { vsnprintf(strBuffer + n, WPAL_TRACE_BUFFER_SIZE - n - 1, strFormat, val); wpalOutput(level, strBuffer); diff --git a/drivers/staging/prima/Kbuild b/drivers/staging/prima/Kbuild index adb1b113b08..ce33a11b232 100644 --- a/drivers/staging/prima/Kbuild +++ b/drivers/staging/prima/Kbuild @@ -11,6 +11,8 @@ ifeq ($(KERNEL_BUILD),1) # Need to explicitly define for Kernel-based builds MODNAME := wlan WLAN_ROOT := drivers/staging/prima + #Flag to enable TDLS feature + CONFIG_QCOM_TDLS := y endif ifeq ($(KERNEL_BUILD),0) @@ -33,7 +35,7 @@ ifeq ($(KERNEL_BUILD),0) CONFIG_QCOM_TDLS := y #Flag to enable Fast Transition (11r) feature - CONFIG_QCOM_VOWIFI_11R := n + CONFIG_QCOM_VOWIFI_11R := y endif @@ -46,7 +48,7 @@ BUILD_DEBUG_VERSION := 1 BUILD_DIAG_VERSION := 0 #Do we panic on bug? default is to warn -PANIC_ON_BUG := 0 +PANIC_ON_BUG := 1 #Re-enable wifi on WDI timeout RE_ENABLE_WIFI_ON_WDI_TIMEOUT := 0 @@ -512,9 +514,11 @@ CDEFINES := -DANI_BUS_TYPE_PLATFORM=1 \ -DWLAN_FEATURE_P2P_DEBUG \ -DWLAN_ENABLE_AGEIE_ON_SCAN_RESULTS \ -DWLANTL_DEBUG\ + -DWLAN_NS_OFFLOAD \ -DWLAN_ACTIVEMODE_OFFLOAD_FEATURE \ -DWLAN_FEATURE_HOLD_RX_WAKELOCK \ - -DWLAN_SOFTAP_VSTA_FEATURE + -DWLAN_SOFTAP_VSTA_FEATURE \ + -DWLAN_FEATURE_ROAM_SCAN_OFFLOAD ifneq ($(CONFIG_PRONTO_WLAN),) CDEFINES += -DWCN_PRONTO @@ -538,6 +542,10 @@ endif ifeq ($(HAVE_CFG80211),1) CDEFINES += -DWLAN_FEATURE_P2P CDEFINES += -DWLAN_FEATURE_WFD +ifeq ($(CONFIG_QCOM_VOWIFI_11R),y) +CDEFINES += -DKERNEL_SUPPORT_11R_CFG80211 +CDEFINES += -DUSE_80211_WMMTSPEC_FOR_RIC +endif endif ifeq ($(CONFIG_QCOM_CCX),y) @@ -547,7 +555,9 @@ endif #normally, TDLS negative behavior is not needed ifeq ($(CONFIG_QCOM_TDLS),y) CDEFINES += -DFEATURE_WLAN_TDLS +ifeq ($(BUILD_DEBUG_VERSION),1) CDEFINES += -DWLAN_FEATURE_TDLS_DEBUG +endif CDEFINES += -DCONFIG_TDLS_IMPLICIT #CDEFINES += -DFEATURE_WLAN_TDLS_NEGATIVE #Code under FEATURE_WLAN_TDLS_INTERNAL is ported from volans, This code diff --git a/drivers/staging/prima/Kconfig b/drivers/staging/prima/Kconfig index 64606d72975..7ba2fc4bbee 100644 --- a/drivers/staging/prima/Kconfig +++ b/drivers/staging/prima/Kconfig @@ -27,4 +27,8 @@ config PRIMA_WLAN_11AC_HIGH_TP bool "Enable the Prima WLAN 802.11ac High Throughput option (depends upon kernel support)" default n +config QCOM_VOWIFI_11R + bool "Enable Fast Transition (11r) feature" + default n + endif # PRIMA_WLAN diff --git a/drivers/staging/prima/firmware_bin/WCNSS_cfg.dat b/drivers/staging/prima/firmware_bin/WCNSS_cfg.dat index 297b3cd4722454468ae45bbede7a9e1523c00147..a5ee46c6abd0c1a78b833e72b479fade60a4f88a 100644 GIT binary patch delta 668 zcma*j%TE(Q9KiA4ZpThb*UkY91w1r93!V(&B!^9mf{z#yZ(j6I*qav*<={;dlR0qp zj%dsH#6nVIeDKivOhjn~=}w39ga*mep!b%@TrC=02@ue?rTF zq?RK02b;8vGIJ>{PE6PtXlv9i{ebs$UDfuGYEQB(Uo+}aWY4J9)~r#_BO{Y}BU6~h z4D2P<*&7-4A#cK2_CMki=Gd!>ks3a;KaT}5>I=T|Y!ORXc5|xW+rf@*SJHv9*W=1w zNhDk)Rrfv5mD8)rTeQQ?N4nPtu#OFU$4~r1UE;DSJA+h{h)IuBx35N;4cFE(6gyww zM{2Yw(q$A*(sG+mAEV73=5gBe(Waj^cey`7n|sWYw7E~4Q-KZ}UB>VbC5&SNr)gy} z?R_kt(CR6F`7BE*OkxVtn86FGyv!S^;1you4d>tD9o|Q2u~DY2QL{?T8s{k|l#>O{ zQcnJqV}A+DV$=#&dA^2kSa;>jW8V#Soc&kQR#N@;LQ=V0w$vy(zvuVgqPhPodidfN D*UPqo delta 644 zcma*j%}x_h7>DtH+apKl&_e=-iiw4MdI2uFab-+MCWMO+ zux0!NA<-BWsNZ6wYN1++2n38fS3U(VfJ}aQXXd=gWS&ZHGS?sRV)2Ngkuw=7D#?Ib z)jOqqOs`8ifvuU{D;tqkOZ_9Uv(q=Mf4kt!D8}S8j@}llJIp?7b$GwkkyfiB&qv#= zO3X~$YC_J>de#r~E^y|6J$B3bkGMZ>dRm8^d6IYLX*#%Sy1VmEvjwL)%%hA~oCeoT z_H@Ddi=0>R1z$P)CZ{Tv*jYwR&V0uY-qo>!Mp!e&XgF*KOt78Gg?-*=H2B=^h0BSG ziPVFs&Vf^F{PsFFu!$}F#virluiCwMo8%H>)!nNZWFyRWjl`}kQKU$X5+;;T$Oq3+ zo*29J5vuH4EPln|~X%lXzI$}EwJ9-=c8)o*_@aEz_nDVd1 diff --git a/drivers/staging/prima/firmware_bin/WCNSS_qcom_cfg.ini b/drivers/staging/prima/firmware_bin/WCNSS_qcom_cfg.ini index de53949c057..8b32fbd0c1b 100644 --- a/drivers/staging/prima/firmware_bin/WCNSS_qcom_cfg.ini +++ b/drivers/staging/prima/firmware_bin/WCNSS_qcom_cfg.ini @@ -93,6 +93,10 @@ McastBcastFilter=3 hostArpOffload=1 +#Flag to enable HostNSOffload feature or not + +hostNSOffload=0 + #SoftAP Related Parameters # AP MAc addr @@ -353,12 +357,6 @@ gVhtTxMCS=2 # gPassiveMinChannelTime=60 # gActiveMaxChannelTime=40 # gActiveMinChannelTime=20 -gPassiveMaxChannelTimeConc=110 -gPassiveMinChannelTimeConc=60 -gActiveMaxChannelTimeConc=27 -gActiveMinChannelTimeConc=20 -gRestTimeConc=100 -gNumChanCombinedConc=1 #If set to 0, MCC is not allowed. gEnableMCCMode=1 @@ -381,6 +379,23 @@ isAndroidPsEn=0 #disable LDPC in STA mode if the AP is TXBF capable gDisableLDPCWithTxbfAP=1 + +#Enable thermal mitigation +gThermalMitigationEnable=1 + +#List of Country codes for which 11ac needs to be disabled +#Each country code must be delimited by comma(,) +gListOfNon11acCountryCode=RU,UA,ZA + +#Maxium Channel time in msec +gMaxMediumTime = 6000 + +# 802.11K support +gRrmEnable=1 +gRrmOperChanMax=8 +gRrmNonOperChanMax=8 +gRrmRandIntvl=100 + END # Note: Configuration parser would not read anything past the END marker diff --git a/drivers/staging/prima/riva/inc/wlan_hal_cfg.h b/drivers/staging/prima/riva/inc/wlan_hal_cfg.h index 6d80cee6a92..c9a319c7756 100644 --- a/drivers/staging/prima/riva/inc/wlan_hal_cfg.h +++ b/drivers/staging/prima/riva/inc/wlan_hal_cfg.h @@ -155,7 +155,8 @@ #define QWLAN_HAL_CFG_ENABLE_DETECT_PS_SUPPORT 101 #define QWLAN_HAL_CFG_AP_LINK_MONITOR_TIMEOUT 102 #define QWLAN_HAL_CFG_BTC_DWELL_TIME_MULTIPLIER 103 -#define QWLAN_HAL_CFG_MAX_PARAMS 104 +#define QWLAN_HAL_CFG_ENABLE_TDLS_OXYGEN_MODE 104 +#define QWLAN_HAL_CFG_MAX_PARAMS 105 diff --git a/drivers/staging/prima/riva/inc/wlan_hal_msg.h b/drivers/staging/prima/riva/inc/wlan_hal_msg.h index 4c2758383c9..3526e330cd2 100644 --- a/drivers/staging/prima/riva/inc/wlan_hal_msg.h +++ b/drivers/staging/prima/riva/inc/wlan_hal_msg.h @@ -101,11 +101,21 @@ typedef tANI_U8 tHalIpv4Addr[4]; PARAM_llGCOEXIST_CHANGED|PARAM_HT20MHZCOEXIST_CHANGED|PARAM_NON_GF_DEVICES_PRESENT_CHANGED|PARAM_RIFS_MODE_CHANGED|PARAM_LSIG_TXOP_FULL_SUPPORT_CHANGED| PARAM_OBSS_MODE_CHANGED) /*Dump command response Buffer size*/ -#define DUMPCMD_RSP_BUFFER 100 +#define DUMPCMD_RSP_BUFFER 500 /*Version string max length (including NUL) */ #define WLAN_HAL_VERSION_LENGTH 64 +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +#define CHANNEL_LIST_STATIC 1 /* Occupied channel list remains static */ +#define CHANNEL_LIST_DYNAMIC_INIT 2 /* Occupied channel list can be learnt after init */ +#define CHANNEL_LIST_DYNAMIC_FLUSH 3 /* Occupied channel list can be learnt after flush */ +#define CHANNEL_LIST_DYNAMIC_UPDATE 4 /* Occupied channel list can be learnt after update */ +#define WLAN_HAL_ROAM_SCAN_MAX_PROBE_SIZE 450 +#define WLAN_HAL_ROAM_SCAN_MAX_CHANNELS NUM_RF_CHANNELS +#define WLAN_HAL_ROAM_SCAN_RESERVED_BYTES 61 +#endif + /* Message types for messages exchanged between WDI and HAL */ typedef enum { @@ -362,7 +372,10 @@ typedef enum WLAN_HAL_DEL_BA_IND = 188, WLAN_HAL_DHCP_START_IND = 189, WLAN_HAL_DHCP_STOP_IND = 190, - + WLAN_ROAM_SCAN_OFFLOAD_REQ = 191, + WLAN_ROAM_SCAN_OFFLOAD_RSP = 192, + WLAN_HAL_WIFI_PROXIMITY_REQ = 193, + WLAN_HAL_WIFI_PROXIMITY_RSP = 194, WLAN_HAL_MSG_MAX = WLAN_HAL_MSG_TYPE_MAX_ENUM_SIZE }tHalHostMsgType; @@ -556,6 +569,7 @@ typedef enum eSriLinkState { eSIR_LINK_FINISH_CAL_STATE = 13, #ifdef WLAN_FEATURE_P2P eSIR_LINK_LISTEN_STATE = 14, + eSIR_LINK_SEND_ACTION_STATE = 15, #endif eSIR_LINK_MAX = WLAN_HAL_MAX_ENUM_SIZE } tSirLinkState; @@ -1618,6 +1632,15 @@ typedef enum HAL_MAX_CONCURRENCY_PERSONA=4 } tHalConcurrencyMode; +// IFACE PERSONA for different Operating modes +typedef enum +{ + HAL_IFACE_UNKNOWN=0, + HAL_IFACE_STA_MODE=1, + HAL_IFACE_P2P_MODE=2, + HAL_IFACE_MAX=0x7FFFFFFF, +}tHalIfacePersona; + typedef PACKED_PRE struct PACKED_POST { /* BSSID */ @@ -4537,11 +4560,20 @@ typedef PACKED_PRE struct PACKED_POST tANI_U32 status; }tAddStaSelfParams, *tpAddStaSelfParams; +typedef PACKED_PRE struct PACKED_POST +{ + tSirMacAddr selfMacAddr; + tANI_U32 status; + tHalIfacePersona iface_persona; +}tAddStaSelfParams_V1, *tpAddStaSelfParams_V1; typedef PACKED_PRE struct PACKED_POST { tHalMsgHeader header; + PACKED_PRE union PACKED_POST { tAddStaSelfParams addStaSelfParams; + tAddStaSelfParams_V1 addStaSelfParams_V1; + }uAddStaSelfParams; }tAddStaSelfReq, *tpAddStaSelfReq; /*--------------------------------------------------------------------------- @@ -4933,6 +4965,7 @@ typedef enum ePNO_MODE_IMMEDIATE, ePNO_MODE_ON_SUSPEND, ePNO_MODE_ON_RESUME, + ePNO_MODE_DELAY, ePNO_MODE_MAX = WLAN_HAL_MAX_ENUM_SIZE } ePNOMode; @@ -4952,6 +4985,8 @@ typedef enum eAUTH_TYPE_FT_RSN_PSK = 7, eAUTH_TYPE_WAPI_WAI_CERTIFICATE = 8, eAUTH_TYPE_WAPI_WAI_PSK = 9, + eAUTH_TYPE_CCKM_WPA = 10, + eAUTH_TYPE_CCKM_RSN = 11, eAUTH_TYPE_MAX = WLAN_HAL_MAX_ENUM_SIZE @@ -5149,16 +5184,18 @@ typedef PACKED_PRE struct PACKED_POST } tSetPrefNetwListResp, *tpSetPrefNetwListResp; /* - Preferred network indication parameters + Preferred network indication parameters */ typedef PACKED_PRE struct PACKED_POST { /*Network that was found with the highest RSSI*/ tSirMacSSid ssId; - + /*Indicates the RSSI */ tANI_U8 rssi; + tANI_U16 frameLength; + } tPrefNetwFoundParams, * tpPrefNetwFoundParams; /* @@ -5177,7 +5214,67 @@ typedef PACKED_PRE struct PACKED_POST { tANI_U8 ucRssiThreshold; } tRssiFilterParams, * tpRssiFilterParams; +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +typedef PACKED_PRE struct PACKED_POST +{ + tSirMacSSid ssId; + tANI_U8 currAPbssid[HAL_MAC_ADDR_LEN]; + tANI_U32 authentication; + tEdType encryption; + tEdType mcencryption; + tANI_U8 ChannelCount; + tANI_U8 ChannelCache[WLAN_HAL_ROAM_SCAN_MAX_CHANNELS]; +}tRoamNetworkType; +typedef PACKED_PRE struct PACKED_POST +{ + tANI_U8 mdiePresent; + tANI_U16 mobilityDomain; +}tMobilityDomainInfo; + +typedef PACKED_PRE struct PACKED_POST { + eAniBoolean RoamScanOffloadEnabled; + tANI_S8 LookupThreshold; + tANI_U8 RoamRssiDiff; + tANI_U8 ChannelCacheType; + tANI_U8 Command; + tANI_U8 StartScanReason; + tANI_U16 NeighborScanTimerPeriod; + tANI_U16 NeighborRoamScanRefreshPeriod; + tANI_U16 NeighborScanChannelMinTime; + tANI_U16 NeighborScanChannelMaxTime; + tANI_U16 EmptyRefreshScanPeriod; + tANI_U8 ValidChannelCount; + tANI_U8 ValidChannelList[WLAN_HAL_ROAM_SCAN_MAX_CHANNELS]; + eAniBoolean IsCCXEnabled; + + tANI_U16 us24GProbeSize; + tANI_U8 a24GProbeTemplate[WLAN_HAL_ROAM_SCAN_MAX_PROBE_SIZE]; + tANI_U16 us5GProbeSize; + tANI_U8 a5GProbeTemplate[WLAN_HAL_ROAM_SCAN_MAX_PROBE_SIZE]; + /* Add Reserved bytes */ + tANI_U8 nProbes; + tANI_U16 HomeAwayTime; + tANI_U8 ReservedBytes[WLAN_HAL_ROAM_SCAN_RESERVED_BYTES]; + tRoamNetworkType ConnectedNetwork; + tMobilityDomainInfo MDID; +} tRoamCandidateListParams, * tpRoamCandidateListParams; + +typedef PACKED_PRE struct PACKED_POST +{ + tHalMsgHeader header; + tRoamCandidateListParams RoamScanOffloadNetwListParams; +} tSetRoamScanOffloadReq, *tpRoamScanOffloadReq; + +typedef PACKED_PRE struct PACKED_POST +{ + tHalMsgHeader header; + + /*status of the request - just to indicate that PNO has acknowledged + * the request and will start scanning*/ + tANI_U32 status; +} tSetRoamOffloadScanResp, *tpSetRoamOffloadScanResp; +#endif /* RSSI Filter request */ @@ -5520,6 +5617,9 @@ typedef PACKED_PRE struct PACKED_POST /* Beacon Early Termination Interval */ tANI_U32 uBETInterval; + + /* MAX LI for modulated DTIM */ + tANI_U32 uMaxLIModulatedDTIM; }tSetPowerParamsType, *tpSetPowerParamsType; typedef PACKED_PRE struct PACKED_POST @@ -5564,7 +5664,8 @@ typedef enum { BCN_FILTER = 19, RTT = 20, RATECTRL = 21, - WOW = 22 + WOW = 22, + WLAN_ROAM_SCAN_OFFLOAD = 23, //MAX_FEATURE_SUPPORTED = 128 } placeHolderInCapBitmap; @@ -5584,6 +5685,9 @@ typedef PACKED_PRE struct PACKED_POST{ #define IS_SLM_SESSIONIZATION_SUPPORTED_BY_HOST (!!(halMsg_GetHostWlanFeatCaps(SLM_SESSIONIZATION))) #define IS_FEATURE_SUPPORTED_BY_HOST(featEnumValue) (!!halMsg_GetHostWlanFeatCaps(featEnumValue)) #define IS_WLANACTIVE_OFFLOAD_SUPPORTED_BY_HOST (!!(halMsg_GetHostWlanFeatCaps(WLANACTIVE_OFFLOAD))) +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +#define IS_ROAM_SCAN_OFFLOAD_SUPPORTED_BY_HOST (!!(halMsg_GetHostWlanFeatCaps(WLAN_ROAM_SCAN_OFFLOAD))) +#endif tANI_U8 halMsg_GetHostWlanFeatCaps(tANI_U8 feat_enum_value); diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index d30a1676e68..249041346d7 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -20,11 +20,12 @@ #include #include #include +#include #include #include #include #include -#include +#include #include #include @@ -2038,6 +2039,14 @@ int usb_new_device(struct usb_device *udev) /* Tell the world! */ announce_device(udev); + if (udev->serial) + add_device_randomness(udev->serial, strlen(udev->serial)); + if (udev->product) + add_device_randomness(udev->product, strlen(udev->product)); + if (udev->manufacturer) + add_device_randomness(udev->manufacturer, + strlen(udev->manufacturer)); + device_enable_async_suspend(&udev->dev); /* diff --git a/drivers/video/msm/mdp4.h b/drivers/video/msm/mdp4.h index b9305fb6842..653ea096340 100644 --- a/drivers/video/msm/mdp4.h +++ b/drivers/video/msm/mdp4.h @@ -298,8 +298,6 @@ struct mdp4_overlay_pipe { uint32 src_format; uint32 src_width; /* source img width */ uint32 src_height; /* source img height */ - uint32 prev_src_width; /* source img width */ - uint32 prev_src_height; /* source img height */ uint32 is_3d; uint32 src_width_3d; /* source img width */ uint32 src_height_3d; /* source img height */ diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c index 74ec84ed6a7..03d6e658973 100644 --- a/drivers/video/msm/mdp4_overlay.c +++ b/drivers/video/msm/mdp4_overlay.c @@ -989,29 +989,8 @@ void mdp4_overlay_vg_setup(struct mdp4_overlay_pipe *pipe) outpdw(vg_base + 0x0008, dst_size); /* MDP_RGB_DST_SIZE */ outpdw(vg_base + 0x000c, dst_xy); /* MDP_RGB_DST_XY */ - if (pipe->frame_format != MDP4_FRAME_FORMAT_LINEAR) { - struct mdp4_overlay_pipe *real_pipe; - u32 psize, csize; - - /* - * video tile frame size register is NOT double buffered. - * when this register updated, it kicks in immediatly - * During transition from smaller resolution to higher - * resolution it may have possibility that mdp still fetch - * from smaller resolution buffer with new higher resolution - * frame size. This will cause iommu page fault. - */ - real_pipe = mdp4_overlay_ndx2pipe(pipe->pipe_ndx); - psize = real_pipe->prev_src_height * real_pipe->prev_src_width; - csize = pipe->src_height * pipe->src_width; - if (psize && (csize > psize)) { - frame_size = (real_pipe->prev_src_height << 16 | - real_pipe->prev_src_width); - } + if (pipe->frame_format != MDP4_FRAME_FORMAT_LINEAR) outpdw(vg_base + 0x0048, frame_size); /* TILE frame size */ - real_pipe->prev_src_height = pipe->src_height; - real_pipe->prev_src_width = pipe->src_width; - } /* * Adjust src X offset to avoid MDP from overfetching pixels diff --git a/drivers/video/msm/mipi_JDI.c b/drivers/video/msm/mipi_JDI.c index 343d0da00d7..1c39145d779 100644 --- a/drivers/video/msm/mipi_JDI.c +++ b/drivers/video/msm/mipi_JDI.c @@ -254,7 +254,7 @@ static void JDI_command_backlight(int level) cmdreq_JDI.cmds = backlight_cmd; cmdreq_JDI.cmds_cnt = ARRAY_SIZE(backlight_cmd); - cmdreq_JDI.flags = CMD_REQ_COMMIT; + cmdreq_JDI.flags = CMD_REQ_COMMIT | CMD_CLK_CTRL; cmdreq_JDI.rlen = 0; cmdreq_JDI.cb = NULL; mipi_dsi_cmdlist_put(&cmdreq_JDI); @@ -369,7 +369,7 @@ static void mipi_JDI_lcd_shutdown(void) pr_info("%s, JDI display off command+\n", __func__); cmdreq_JDI.cmds = JDI_display_off_cmds; cmdreq_JDI.cmds_cnt = ARRAY_SIZE(JDI_display_off_cmds); - cmdreq_JDI.flags = CMD_REQ_COMMIT; + cmdreq_JDI.flags = CMD_REQ_COMMIT | CMD_CLK_CTRL; cmdreq_JDI.rlen = 0; cmdreq_JDI.cb = NULL; mipi_dsi_cmdlist_put(&cmdreq_JDI); diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c index 89fb312b61b..34b13a77f7b 100644 --- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c +++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c @@ -2003,14 +2003,19 @@ u32 ddl_set_default_decoder_buffer_req(struct ddl_decoder_data *decoder, struct vcd_buffer_requirement *output_buf_req; u32 min_dpb, y_cb_cr_size; u32 frame_height_actual = 0; + u32 min_dpb_from_res_trk = 0; - if (!decoder->codec.codec) + if (!decoder->codec.codec) { + DDL_MSG_ERROR("%s: codec not set", __func__); return false; + } if (estimate) { - if (!decoder->cont_mode) - min_dpb = ddl_decoder_min_num_dpb(decoder); - else + if (decoder->cont_mode && + decoder->codec.codec == VCD_CODEC_H264) { min_dpb = res_trk_get_min_dpb_count(); + min_dpb_from_res_trk = 1; + } else + min_dpb = ddl_decoder_min_num_dpb(decoder); frame_size = &decoder->client_frame_size; output_buf_req = &decoder->client_output_buf_req; input_buf_req = &decoder->client_input_buf_req; @@ -2023,6 +2028,17 @@ u32 ddl_set_default_decoder_buffer_req(struct ddl_decoder_data *decoder, output_buf_req = &decoder->actual_output_buf_req; input_buf_req = &decoder->actual_input_buf_req; min_dpb = decoder->min_dpb_num; + if (decoder->cont_mode && + decoder->codec.codec == VCD_CODEC_H264) { + min_dpb = res_trk_get_min_dpb_count(); + min_dpb_from_res_trk = 1; + if (min_dpb < decoder->min_dpb_num) { + DDL_MSG_HIGH("Warning: cont_mode dpb count"\ + "(%u) is less than decoder min dpb count(%u)", + min_dpb, decoder->min_dpb_num); + min_dpb = decoder->min_dpb_num; + } + } if ((decoder->buf_format.buffer_format == VCD_BUFFER_FORMAT_TILE_4x2) && (frame_size->height < MDP_MIN_TILE_HEIGHT)) { @@ -2041,14 +2057,13 @@ u32 ddl_set_default_decoder_buffer_req(struct ddl_decoder_data *decoder, } memset(output_buf_req, 0, sizeof(struct vcd_buffer_requirement)); - if (!decoder->idr_only_decoding && !decoder->cont_mode) + if (!decoder->idr_only_decoding && !min_dpb_from_res_trk) output_buf_req->actual_count = min_dpb + 4; else output_buf_req->actual_count = min_dpb; output_buf_req->min_count = min_dpb; output_buf_req->max_count = DDL_MAX_BUFFER_COUNT; output_buf_req->sz = y_cb_cr_size; - DDL_MSG_LOW("output_buf_req->sz : %d", output_buf_req->sz); if (decoder->buf_format.buffer_format != VCD_BUFFER_FORMAT_NV12) output_buf_req->align = DDL_TILE_BUFFER_ALIGN_BYTES; else @@ -2057,6 +2072,14 @@ u32 ddl_set_default_decoder_buffer_req(struct ddl_decoder_data *decoder, output_buf_req); decoder->min_output_buf_req = *output_buf_req; + DDL_MSG_HIGH("out_buf_req: estimate = %u, WxH = %ux%u, "\ + "min_dpb = %u, sz = %d, act = %u, min = %u, max = %u, "\ + "align = %u, meta_buf_size = %d", estimate, + frame_size->width, frame_size->height, min_dpb, + output_buf_req->sz, output_buf_req->actual_count, + output_buf_req->min_count, output_buf_req->max_count, + output_buf_req->align, output_buf_req->meta_buffer_size); + memset(input_buf_req, 0, sizeof(struct vcd_buffer_requirement)); input_buf_req->min_count = 1; @@ -2173,8 +2196,8 @@ static u32 ddl_decoder_min_num_dpb(struct ddl_decoder_data *decoder) case VCD_CODEC_H264: { u32 yuv_size_in_mb = DDL_MIN(DDL_NO_OF_MB( - decoder->client_frame_size.stride, - decoder->client_frame_size.scan_lines), + decoder->client_frame_size.width, + decoder->client_frame_size.height), MAX_FRAME_SIZE_L4PT0_MBS); min_dpb = DDL_MIN((MAX_DPB_SIZE_L4PT0_MBS / yuv_size_in_mb), 16); diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index 1607615186c..f2273995d82 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c @@ -340,7 +340,7 @@ wait_for_response(struct TCP_Server_Info *server, struct mid_q_entry *midQ) { int error; - error = wait_event_freezekillable(server->response_q, + error = wait_event_freezekillable_unsafe(server->response_q, midQ->mid_state != MID_REQUEST_SUBMITTED); if (error < 0) return -ERESTARTSYS; diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 1030a716d15..a789934737e 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -90,6 +90,56 @@ static void pad_len_spaces(struct seq_file *m, int len) seq_printf(m, "%*c", len, ' '); } +static void seq_print_vma_name(struct seq_file *m, struct vm_area_struct *vma) +{ + const char __user *name = vma_get_anon_name(vma); + struct mm_struct *mm = vma->vm_mm; + + unsigned long page_start_vaddr; + unsigned long page_offset; + unsigned long num_pages; + unsigned long max_len = NAME_MAX; + int i; + + page_start_vaddr = (unsigned long)name & PAGE_MASK; + page_offset = (unsigned long)name - page_start_vaddr; + num_pages = DIV_ROUND_UP(page_offset + max_len, PAGE_SIZE); + + seq_puts(m, "[anon:"); + + for (i = 0; i < num_pages; i++) { + int len; + int write_len; + const char *kaddr; + long pages_pinned; + struct page *page; + + pages_pinned = get_user_pages(current, mm, page_start_vaddr, + 1, 0, 0, &page, NULL); + if (pages_pinned < 1) { + seq_puts(m, "]"); + return; + } + + kaddr = (const char *)kmap(page); + len = min(max_len, PAGE_SIZE - page_offset); + write_len = strnlen(kaddr + page_offset, len); + seq_write(m, kaddr + page_offset, write_len); + kunmap(page); + put_page(page); + + /* if strnlen hit a null terminator then we're done */ + if (write_len != len) + break; + + max_len -= len; + page_offset = 0; + page_start_vaddr += PAGE_SIZE; + } + + seq_putc(m, ']'); +} + static void vma_stop(struct proc_maps_private *priv, struct vm_area_struct *vma) { if (vma && vma != priv->tail_vma) { @@ -289,6 +339,12 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma, int is_pid) pad_len_spaces(m, len); seq_printf(m, "[stack:%d]", tid); } + goto done; + } + + if (vma_get_anon_name(vma)) { + pad_len_spaces(m, len); + seq_print_vma_name(m, vma); } } @@ -521,6 +577,12 @@ static int show_smap(struct seq_file *m, void *v, int is_pid) (vma->vm_flags & VM_LOCKED) ? (unsigned long)(mss.pss >> (10 + PSS_SHIFT)) : 0); + if (vma_get_anon_name(vma)) { + seq_puts(m, "Name: "); + seq_print_vma_name(m, vma); + seq_putc(m, '\n'); + } + if (m->count < m->size) /* vma is copied successfully */ m->version = (vma != get_gate_vma(task->mm)) ? vma->vm_start : 0; diff --git a/fs/select.c b/fs/select.c index c4aa6a5971b..0f8684a5934 100644 --- a/fs/select.c +++ b/fs/select.c @@ -27,6 +27,7 @@ #include #include #include + #include diff --git a/include/drm/kgsl_drm.h b/include/drm/kgsl_drm.h index f1c7f4e22f3..8a4d56f94be 100644 --- a/include/drm/kgsl_drm.h +++ b/include/drm/kgsl_drm.h @@ -19,6 +19,12 @@ #define DRM_KGSL_GEM_UNLOCK_HANDLE 0x0C #define DRM_KGSL_GEM_UNLOCK_ON_TS 0x0D #define DRM_KGSL_GEM_CREATE_FD 0x0E +#define DRM_KGSL_GEM_GET_ION_FD 0x0F +#define DRM_KGSL_GEM_CREATE_FROM_ION 0x10 +#define DRM_KGSL_GEM_SET_GLOCK_HANDLES_INFO 0x11 +#define DRM_KGSL_GEM_GET_GLOCK_HANDLES_INFO 0x12 +#define DRM_KGSL_GEM_GET_BUFCOUNT 0x13 + #define DRM_IOCTL_KGSL_GEM_CREATE \ DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_CREATE, struct drm_kgsl_gem_create) @@ -55,6 +61,10 @@ DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_GET_BUFINFO, \ DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_SET_BUFCOUNT, \ struct drm_kgsl_gem_bufcount) +#define DRM_IOCTL_KGSL_GEM_GET_BUFCOUNT \ +DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_GET_BUFCOUNT, \ + struct drm_kgsl_gem_bufcount) + #define DRM_IOCTL_KGSL_GEM_SET_ACTIVE \ DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_SET_ACTIVE, \ struct drm_kgsl_gem_active) @@ -75,6 +85,24 @@ struct drm_kgsl_gem_unlock_on_ts) DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_CREATE_FD, \ struct drm_kgsl_gem_create_fd) +#define DRM_IOCTL_KGSL_GEM_GET_ION_FD \ +DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_GET_ION_FD, \ +struct drm_kgsl_gem_get_ion_fd) + +#define DRM_IOCTL_KGSL_GEM_CREATE_FROM_ION \ +DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_CREATE_FROM_ION, \ +struct drm_kgsl_gem_create_from_ion) + +#define DRM_IOCTL_KGSL_GEM_SET_GLOCK_HANDLES_INFO \ +DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_SET_GLOCK_HANDLES_INFO, \ +struct drm_kgsl_gem_glockinfo) + +#define DRM_IOCTL_KGSL_GEM_GET_GLOCK_HANDLES_INFO \ +DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_GET_GLOCK_HANDLES_INFO, \ +struct drm_kgsl_gem_glockinfo) + + + /* Maximum number of sub buffers per GEM object */ #define DRM_KGSL_GEM_MAX_BUFFERS 2 @@ -157,6 +185,11 @@ struct drm_kgsl_gem_bufinfo { uint32_t gpuaddr[DRM_KGSL_GEM_MAX_BUFFERS]; }; +struct drm_kgsl_gem_glockinfo { + uint32_t handle; + int glockhandle[DRM_KGSL_GEM_MAX_BUFFERS]; +}; + struct drm_kgsl_gem_bufcount { uint32_t handle; uint32_t bufcount; @@ -189,4 +222,14 @@ struct drm_kgsl_gem_create_fd { uint32_t handle; }; +struct drm_kgsl_gem_get_ion_fd { + uint32_t ion_fd; + uint32_t handle; +}; + +struct drm_kgsl_gem_create_from_ion { + uint32_t ion_fd; + uint32_t handle; +}; + #endif diff --git a/include/linux/console.h b/include/linux/console.h index 7201ce4280c..dffe4772a53 100644 --- a/include/linux/console.h +++ b/include/linux/console.h @@ -153,6 +153,7 @@ extern int braille_register_console(struct console *, int index, extern int braille_unregister_console(struct console *); extern void console_sysfs_notify(void); extern bool console_suspend_enabled; +extern int is_console_suspended(void); /* Suspend and resume console messages over PM events */ extern void suspend_console(void); diff --git a/include/linux/freezer.h b/include/linux/freezer.h index 6a060aeb3d5..ba9b9133f54 100644 --- a/include/linux/freezer.h +++ b/include/linux/freezer.h @@ -42,16 +42,24 @@ extern int freeze_kernel_threads(void); extern void thaw_processes(void); extern void thaw_kernel_threads(void); +/* + * HACK: prevent sleeping while atomic warnings due to ARM signal handling + * disabling irqs + */ +static inline bool try_to_freeze_nowarn(void) +{ + if (likely(!freezing(current))) + return false; + return __refrigerator(false); +} + /* * DO NOT ADD ANY NEW CALLERS OF THIS FUNCTION * If try_to_freeze causes a lockdep warning it means the caller may deadlock */ static inline bool try_to_freeze_unsafe(void) { -/* This causes problems for ARM targets and is a known - * problem upstream. - * might_sleep(); - */ + might_sleep(); if (likely(!freezing(current))) return false; return __refrigerator(false); @@ -90,23 +98,41 @@ static inline bool cgroup_freezing(struct task_struct *task) */ -/* Tell the freezer not to count the current task as freezable. */ +/** + * freezer_do_not_count - tell freezer to ignore %current + * + * Tell freezers to ignore the current task when determining whether the + * target frozen state is reached. IOW, the current task will be + * considered frozen enough by freezers. + * + * The caller shouldn't do anything which isn't allowed for a frozen task + * until freezer_cont() is called. Usually, freezer[_do_not]_count() pair + * wrap a scheduling operation and nothing much else. + */ static inline void freezer_do_not_count(void) { current->flags |= PF_FREEZER_SKIP; } -/* - * Tell the freezer to count the current task as freezable again and try to - * freeze it. +/** + * freezer_count - tell freezer to stop ignoring %current + * + * Undo freezer_do_not_count(). It tells freezers that %current should be + * considered again and tries to freeze if freezing condition is already in + * effect. */ static inline void freezer_count(void) { current->flags &= ~PF_FREEZER_SKIP; + /* + * If freezing is in progress, the following paired with smp_mb() + * in freezer_should_skip() ensures that either we see %true + * freezing() or freezer_should_skip() sees !PF_FREEZER_SKIP. + */ + smp_mb(); try_to_freeze(); } - /* DO NOT ADD ANY NEW CALLERS OF THIS FUNCTION */ static inline void freezer_count_unsafe(void) { @@ -125,13 +151,21 @@ static inline void freezer_count_unsafe(void) * state is reached. IOW, if this function returns %true, @p is considered * frozen enough. */ -static inline int freezer_should_skip(struct task_struct *p) +static inline bool freezer_should_skip(struct task_struct *p) { - return !!(p->flags & PF_FREEZER_SKIP); + /* + * The following smp_mb() paired with the one in freezer_count() + * ensures that either freezer_count() sees %true freezing() or we + * see cleared %PF_FREEZER_SKIP and return %false. This makes it + * impossible for a task to slip frozen state testing after + * clearing %PF_FREEZER_SKIP. + */ + smp_mb(); + return p->flags & PF_FREEZER_SKIP; } /* - * These macros are intended to be used whenever you want allow a task that's + * These functions are intended to be used whenever you want allow a task that's * sleeping in TASK_UNINTERRUPTIBLE or TASK_KILLABLE state to be frozen. Note * that neither return any clear indication of whether a freeze event happened * while in this function. @@ -228,6 +262,16 @@ static inline int freezable_schedule_hrtimeout_range(ktime_t *expires, __retval; \ }) +/* DO NOT ADD ANY NEW CALLERS OF THIS FUNCTION */ +#define wait_event_freezekillable_unsafe(wq, condition) \ +({ \ + int __retval; \ + freezer_do_not_count(); \ + __retval = wait_event_killable(wq, (condition)); \ + freezer_count_unsafe(); \ + __retval; \ +}) + #define wait_event_freezable(wq, condition) \ ({ \ int __retval; \ @@ -305,6 +349,9 @@ static inline void set_freezable(void) {} #define wait_event_freezekillable(wq, condition) \ wait_event_killable(wq, condition) +#define wait_event_freezekillable_unsafe(wq, condition) \ + wait_event_killable(wq, condition) + #endif /* !CONFIG_FREEZER */ #endif /* FREEZER_H_INCLUDED */ diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index a2b59d795ae..1ca1b835902 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -1074,6 +1074,90 @@ struct ieee80211_ht_info { #define WLAN_HT_SMPS_CONTROL_STATIC 1 #define WLAN_HT_SMPS_CONTROL_DYNAMIC 3 +/** + * struct ieee80211_vht_mcs_info - VHT MCS information + * @rx_mcs_map: RX MCS map 2 bits for each stream, total 8 streams + * @rx_highest: Indicates highest long GI VHT PPDU data rate + * STA can receive. Rate expressed in units of 1 Mbps. + * If this field is 0 this value should not be used to + * consider the highest RX data rate supported. + * @tx_mcs_map: TX MCS map 2 bits for each stream, total 8 streams + * @tx_highest: Indicates highest long GI VHT PPDU data rate + * STA can transmit. Rate expressed in units of 1 Mbps. + * If this field is 0 this value should not be used to + * consider the highest TX data rate supported. + */ +struct ieee80211_vht_mcs_info { + __le16 rx_mcs_map; + __le16 rx_highest; + __le16 tx_mcs_map; + __le16 tx_highest; +} __packed; + +/** + * struct ieee80211_vht_cap - VHT capabilities + * + * This structure is the "VHT capabilities element" as + * described in 802.11ac D3.0 8.4.2.160 + * @vht_cap_info: VHT capability info + * @supp_mcs: VHT MCS supported rates + */ +struct ieee80211_vht_cap { + __le32 vht_cap_info; + struct ieee80211_vht_mcs_info supp_mcs; +} __packed; + +/** + * struct ieee80211_vht_operation - VHT operation IE + * + * This structure is the "VHT operation element" as + * described in 802.11ac D3.0 8.4.2.161 + * @chan_width: Operating channel width + * @center_freq_seg1_idx: center freq segment 1 index + * @center_freq_seg2_idx: center freq segment 2 index + * @basic_mcs_set: VHT Basic MCS rate set + */ +struct ieee80211_vht_operation { + u8 chan_width; + u8 center_freq_seg1_idx; + u8 center_freq_seg2_idx; + __le16 basic_mcs_set; +} __packed; + + +#define IEEE80211_VHT_MCS_ZERO_TO_SEVEN_SUPPORT 0 +#define IEEE80211_VHT_MCS_ZERO_TO_EIGHT_SUPPORT 1 +#define IEEE80211_VHT_MCS_ZERO_TO_NINE_SUPPORT 2 +#define IEEE80211_VHT_MCS_NOT_SUPPORTED 3 + +/* 802.11ac VHT Capabilities */ +#define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895 0x00000000 +#define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 0x00000001 +#define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 0x00000002 +#define IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ 0x00000004 +#define IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ 0x00000008 +#define IEEE80211_VHT_CAP_RXLDPC 0x00000010 +#define IEEE80211_VHT_CAP_SHORT_GI_80 0x00000020 +#define IEEE80211_VHT_CAP_SHORT_GI_160 0x00000040 +#define IEEE80211_VHT_CAP_TXSTBC 0x00000080 +#define IEEE80211_VHT_CAP_RXSTBC_1 0x00000100 +#define IEEE80211_VHT_CAP_RXSTBC_2 0x00000200 +#define IEEE80211_VHT_CAP_RXSTBC_3 0x00000300 +#define IEEE80211_VHT_CAP_RXSTBC_4 0x00000400 +#define IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE 0x00000800 +#define IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE 0x00001000 +#define IEEE80211_VHT_CAP_BEAMFORMER_ANTENNAS_MAX 0x00006000 +#define IEEE80211_VHT_CAP_SOUNDING_DIMENTION_MAX 0x00030000 +#define IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE 0x00080000 +#define IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE 0x00100000 +#define IEEE80211_VHT_CAP_VHT_TXOP_PS 0x00200000 +#define IEEE80211_VHT_CAP_HTC_VHT 0x00400000 +#define IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT 0x00800000 +#define IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_UNSOL_MFB 0x08000000 +#define IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB 0x0c000000 +#define IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN 0x10000000 +#define IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN 0x20000000 + /* Authentication algorithms */ #define WLAN_AUTH_OPEN 0 #define WLAN_AUTH_SHARED_KEY 1 @@ -1334,6 +1418,9 @@ enum ieee80211_eid { WLAN_EID_DSE_REGISTERED_LOCATION = 58, WLAN_EID_SUPPORTED_REGULATORY_CLASSES = 59, WLAN_EID_EXT_CHANSWITCH_ANN = 60, + + WLAN_EID_VHT_CAPABILITY = 191, + WLAN_EID_VHT_OPERATION = 192, }; /* Action category code */ diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 95b15d6ef6c..dbe13ba323a 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -37,12 +37,13 @@ struct iommu_domain; #define IOMMU_FAULT_WRITE 0x1 typedef int (*iommu_fault_handler_t)(struct iommu_domain *, - struct device *, unsigned long, int); + struct device *, unsigned long, int, void *); struct iommu_domain { struct iommu_ops *ops; void *priv; iommu_fault_handler_t handler; + void *handler_token; }; #define IOMMU_CAP_CACHE_COHERENCY 0x1 @@ -107,7 +108,7 @@ extern int iommu_domain_has_cap(struct iommu_domain *domain, unsigned long cap); extern phys_addr_t iommu_get_pt_base_addr(struct iommu_domain *domain); extern void iommu_set_fault_handler(struct iommu_domain *domain, - iommu_fault_handler_t handler); + iommu_fault_handler_t handler, void *token); extern int iommu_device_group(struct device *dev, unsigned int *groupid); /** @@ -144,7 +145,8 @@ static inline int report_iommu_fault(struct iommu_domain *domain, * invoke it. */ if (domain->handler) - ret = domain->handler(domain, dev, iova, flags); + ret = domain->handler(domain, dev, iova, flags, + domain->handler_token); return ret; } @@ -221,7 +223,7 @@ static inline phys_addr_t iommu_get_pt_base_addr(struct iommu_domain *domain) } static inline void iommu_set_fault_handler(struct iommu_domain *domain, - iommu_fault_handler_t handler) + iommu_fault_handler_t handler, void *token) { } diff --git a/include/linux/irqdesc.h b/include/linux/irqdesc.h index 771cb354348..4d22be25b48 100644 --- a/include/linux/irqdesc.h +++ b/include/linux/irqdesc.h @@ -39,7 +39,6 @@ struct module; */ struct irq_desc { struct irq_data irq_data; - struct timer_rand_state *timer_rand_state; unsigned int __percpu *kstat_irqs; irq_flow_handler_t handle_irq; #ifdef CONFIG_IRQ_PREFLOW_FASTEOI diff --git a/include/linux/kref.h b/include/linux/kref.h index 9c07dcebded..aa5acc26019 100644 --- a/include/linux/kref.h +++ b/include/linux/kref.h @@ -93,4 +93,26 @@ static inline int kref_put(struct kref *kref, void (*release)(struct kref *kref) { return kref_sub(kref, 1, release); } + + +/** + * kref_get_unless_zero - Increment refcount for object unless it is zero. + * @kref: object. + * + * Return non-zero if the increment succeeded. Otherwise return 0. + * + * This function is intended to simplify locking around refcounting for + * objects that can be looked up from a lookup structure, and which are + * removed from that lookup structure in the object destructor. + * Operations on such objects require at least a read lock around + * lookup + kref_get, and a write lock around kref_put + remove from lookup + * structure. Furthermore, RCU implementations become extremely tricky. + * With a lookup followed by a kref_get_unless_zero *with return value check* + * locking in the kref_put path can be deferred to the actual removal from + * the lookup structure and RCU lookups become trivial. + */ +static inline int __must_check kref_get_unless_zero(struct kref *kref) +{ + return atomic_add_unless(&kref->refcount, 1, 0); +} #endif /* _KREF_H_ */ diff --git a/include/linux/mfd/pm8xxx/pm8921-bms.h b/include/linux/mfd/pm8xxx/pm8921-bms.h index 722ecda7dd3..21f9873edec 100644 --- a/include/linux/mfd/pm8xxx/pm8921-bms.h +++ b/include/linux/mfd/pm8xxx/pm8921-bms.h @@ -220,6 +220,15 @@ int pm8921_bms_get_rbatt(void); * soc stored in a coincell backed register */ void pm8921_bms_invalidate_shutdown_soc(void); + +/** + * pm8921_bms_cc_uah - function to get the coulomb counter based charge. Note + * that the coulomb counter are reset when the current + * consumption is low (below 8mA for more than 5 minutes), + * This will lead in a very low coulomb counter charge + * value upon wakeup from sleep. + */ +int pm8921_bms_cc_uah(int *cc_uah); #else static inline int pm8921_bms_get_vsense_avg(int *result) { @@ -258,6 +267,10 @@ static inline int pm8921_bms_get_rbatt(void) static inline void pm8921_bms_invalidate_shutdown_soc(void) { } +static inline int pm8921_bms_cc_uah(int *cc_uah) +{ + return -ENXIO; +} #endif #endif diff --git a/include/linux/mm.h b/include/linux/mm.h index 777117b1c3d..379fe6a3eb7 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -1369,7 +1369,7 @@ extern int vma_adjust(struct vm_area_struct *vma, unsigned long start, extern struct vm_area_struct *vma_merge(struct mm_struct *, struct vm_area_struct *prev, unsigned long addr, unsigned long end, unsigned long vm_flags, struct anon_vma *, struct file *, pgoff_t, - struct mempolicy *); + struct mempolicy *, const char __user *); extern struct anon_vma *find_mergeable_anon_vma(struct vm_area_struct *); extern int split_vma(struct mm_struct *, struct vm_area_struct *, unsigned long addr, int new_below); diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h index 3cc3062b376..9035d0a71a8 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h @@ -216,6 +216,10 @@ struct vm_area_struct { * linkage into the address_space->i_mmap prio tree, or * linkage to the list of like vmas hanging off its node, or * linkage of vma in the address_space->i_mmap_nonlinear list. + * + * For private anonymous mappings, a pointer to a null terminated string + * in the user process containing the name given to the vma, or NULL + * if unnamed. */ union { struct { @@ -225,6 +229,7 @@ struct vm_area_struct { } vm_set; struct raw_prio_tree_node prio_tree_node; + const char __user *anon_name; } shared; /* @@ -403,4 +408,14 @@ static inline cpumask_t *mm_cpumask(struct mm_struct *mm) return mm->cpu_vm_mask_var; } + +/* Return the name for an anonymous mapping or NULL for a file-backed mapping */ +static inline const char __user *vma_get_anon_name(struct vm_area_struct *vma) +{ + if (vma->vm_file) + return NULL; + + return vma->shared.anon_name; +} + #endif /* _LINUX_MM_TYPES_H */ diff --git a/include/linux/msm_kgsl.h b/include/linux/msm_kgsl.h index 0af811c86ab..a36e60d97e7 100644 --- a/include/linux/msm_kgsl.h +++ b/include/linux/msm_kgsl.h @@ -230,6 +230,7 @@ struct kgsl_version { #define KGSL_PERFCOUNTER_GROUP_VBIF_PWR 0xE #define KGSL_PERFCOUNTER_NOT_USED 0xFFFFFFFF +#define KGSL_PERFCOUNTER_BROKEN 0xFFFFFFFE /* structure holds list of ibs */ struct kgsl_ibdesc { diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 61989d0e909..760db5c3fcb 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -170,6 +170,9 @@ * %NL80211_ATTR_CIPHER_GROUP, %NL80211_ATTR_WPA_VERSIONS, * %NL80211_ATTR_AKM_SUITES, %NL80211_ATTR_PRIVACY, * %NL80211_ATTR_AUTH_TYPE and %NL80211_ATTR_INACTIVITY_TIMEOUT. + * %NL80211_ATTR_ACL_POLICY and %NL80211_ATTR_MAC_ADDRS. + * The channel to use can be set on the interface or be given using the + * %NL80211_ATTR_WIPHY_FREQ and the attributes determining channel width. * @NL80211_CMD_NEW_BEACON: old alias for %NL80211_CMD_START_AP * @NL80211_CMD_STOP_AP: Stop AP operation on the given interface * @NL80211_CMD_DEL_BEACON: old alias for %NL80211_CMD_STOP_AP @@ -554,6 +557,64 @@ * @NL80211_CMD_SET_NOACK_MAP: sets a bitmap for the individual TIDs whether * No Acknowledgement Policy should be applied. * + * @NL80211_CMD_CH_SWITCH_NOTIFY: An AP or GO may decide to switch channels + * independently of the userspace SME, send this event indicating + * %NL80211_ATTR_IFINDEX is now on %NL80211_ATTR_WIPHY_FREQ and the + * attributes determining channel width. + * + * @NL80211_CMD_START_P2P_DEVICE: Start the given P2P Device, identified by + * its %NL80211_ATTR_WDEV identifier. It must have been created with + * %NL80211_CMD_NEW_INTERFACE previously. After it has been started, the + * P2P Device can be used for P2P operations, e.g. remain-on-channel and + * public action frame TX. + * @NL80211_CMD_STOP_P2P_DEVICE: Stop the given P2P Device, identified by + * its %NL80211_ATTR_WDEV identifier. + * + * @NL80211_CMD_CONN_FAILED: connection request to an AP failed; used to + * notify userspace that AP has rejected the connection request from a + * station, due to particular reason. %NL80211_ATTR_CONN_FAILED_REASON + * is used for this. + * + * @NL80211_CMD_SET_MCAST_RATE: Change the rate used to send multicast frames + * for IBSS or MESH vif. + * + * @NL80211_CMD_SET_MAC_ACL: sets ACL for MAC address based access control. + * This is to be used with the drivers advertising the support of MAC + * address based access control. List of MAC addresses is passed in + * %NL80211_ATTR_MAC_ADDRS and ACL policy is passed in + * %NL80211_ATTR_ACL_POLICY. Driver will enable ACL with this list, if it + * is not already done. The new list will replace any existing list. Driver + * will clear its ACL when the list of MAC addresses passed is empty. This + * command is used in AP/P2P GO mode. Driver has to make sure to clear its + * ACL list during %NL80211_CMD_STOP_AP. + * + * @NL80211_CMD_RADAR_DETECT: Start a Channel availability check (CAC). Once + * a radar is detected or the channel availability scan (CAC) has finished + * or was aborted, or a radar was detected, usermode will be notified with + * this event. This command is also used to notify userspace about radars + * while operating on this channel. + * %NL80211_ATTR_RADAR_EVENT is used to inform about the type of the + * event. + * + * @NL80211_CMD_GET_PROTOCOL_FEATURES: Get global nl80211 protocol features, + * i.e. features for the nl80211 protocol rather than device features. + * Returns the features in the %NL80211_ATTR_PROTOCOL_FEATURES bitmap. + * + * @NL80211_CMD_UPDATE_FT_IES: Pass down the most up-to-date Fast Transition + * Information Element to the WLAN driver + * + * @NL80211_CMD_FT_EVENT: Send a Fast transition event from the WLAN driver + * to the supplicant. This will carry the target AP's MAC address along + * with the relevant Information Elements. This event is used to report + * received FT IEs (MDIE, FTIE, RSN IE, TIE, RICIE). + * + * @NL80211_CMD_CRIT_PROTOCOL_START: Indicates user-space will start running + * a critical protocol that needs more reliability in the connection to + * complete. + * + * @NL80211_CMD_CRIT_PROTOCOL_STOP: Indicates the connection reliability can + * return back to normal. + * * @NL80211_CMD_MAX: highest used command number * @__NL80211_CMD_AFTER_LAST: internal use */ @@ -695,6 +756,28 @@ enum nl80211_commands { NL80211_CMD_SET_NOACK_MAP, + + NL80211_CMD_CH_SWITCH_NOTIFY, + + NL80211_CMD_START_P2P_DEVICE, + NL80211_CMD_STOP_P2P_DEVICE, + + NL80211_CMD_CONN_FAILED, + + NL80211_CMD_SET_MCAST_RATE, + + NL80211_CMD_SET_MAC_ACL, + + NL80211_CMD_RADAR_DETECT, + + NL80211_CMD_GET_PROTOCOL_FEATURES, + + NL80211_CMD_UPDATE_FT_IES, + NL80211_CMD_FT_EVENT, + + NL80211_CMD_CRIT_PROTOCOL_START, + NL80211_CMD_CRIT_PROTOCOL_STOP, + /* add new commands above here */ /* used to define NL80211_CMD_MAX below */ @@ -1221,6 +1304,82 @@ enum nl80211_commands { * @NL80211_ATTR_BG_SCAN_PERIOD: Background scan period in seconds * or 0 to disable background scan. * + * @NL80211_ATTR_USER_REG_HINT_TYPE: type of regulatory hint passed from + * userspace. If unset it is assumed the hint comes directly from + * a user. If set code could specify exactly what type of source + * was used to provide the hint. For the different types of + * allowed user regulatory hints see nl80211_user_reg_hint_type. + * + * @NL80211_ATTR_CONN_FAILED_REASON: The reason for which AP has rejected + * the connection request from a station. nl80211_connect_failed_reason + * enum has different reasons of connection failure. + * + * @NL80211_ATTR_SAE_DATA: SAE elements in Authentication frames. This starts + * with the Authentication transaction sequence number field. + * + * @NL80211_ATTR_VHT_CAPABILITY: VHT Capability information element (from + * association request when used with NL80211_CMD_NEW_STATION) + * + * @NL80211_ATTR_SCAN_FLAGS: scan request control flags (u32) + * + * @NL80211_ATTR_P2P_CTWINDOW: P2P GO Client Traffic Window (u8), used with + * the START_AP and SET_BSS commands + * @NL80211_ATTR_P2P_OPPPS: P2P GO opportunistic PS (u8), used with the + * START_AP and SET_BSS commands. This can have the values 0 or 1; + * if not given in START_AP 0 is assumed, if not given in SET_BSS + * no change is made. + * + * @NL80211_ATTR_LOCAL_MESH_POWER_MODE: local mesh STA link-specific power mode + * defined in &enum nl80211_mesh_power_mode. + * + * @NL80211_ATTR_ACL_POLICY: ACL policy, see &enum nl80211_acl_policy, + * carried in a u32 attribute + * + * @NL80211_ATTR_MAC_ADDRS: Array of nested MAC addresses, used for + * MAC ACL. + * + * @NL80211_ATTR_MAC_ACL_MAX: u32 attribute to advertise the maximum + * number of MAC addresses that a device can support for MAC + * ACL. + * + * @NL80211_ATTR_RADAR_EVENT: Type of radar event for notification to userspace, + * contains a value of enum nl80211_radar_event (u32). + * + * @NL80211_ATTR_EXT_CAPA: 802.11 extended capabilities that the kernel driver + * has and handles. The format is the same as the IE contents. See + * 802.11-2012 8.4.2.29 for more information. + * @NL80211_ATTR_EXT_CAPA_MASK: Extended capabilities that the kernel driver + * has set in the %NL80211_ATTR_EXT_CAPA value, for multibit fields. + * + * @NL80211_ATTR_STA_CAPABILITY: Station capabilities (u16) are advertised to + * the driver, e.g., to enable TDLS power save (PU-APSD). + * + * @NL80211_ATTR_STA_EXT_CAPABILITY: Station extended capabilities are + * advertised to the driver, e.g., to enable TDLS off channel operations + * and PU-APSD. + * + * @NL80211_ATTR_PROTOCOL_FEATURES: global nl80211 feature flags, see + * &enum nl80211_protocol_features, the attribute is a u32. + * + * @NL80211_ATTR_SPLIT_WIPHY_DUMP: flag attribute, userspace supports + * receiving the data for a single wiphy split across multiple + * messages, given with wiphy dump message + * + * @NL80211_ATTR_MDID: Mobility Domain Identifier + * + * @NL80211_ATTR_IE_RIC: Resource Information Container Information + * Element + * + * @NL80211_ATTR_CRIT_PROT_ID: critical protocol identifier requiring increased + * reliability, see &enum nl80211_crit_proto_id (u16). + * @NL80211_ATTR_MAX_CRIT_PROT_DURATION: duration in milliseconds in which + * the connection should have increased reliability (u16). + * + * @NL80211_ATTR_PEER_AID: Association ID for the peer TDLS station (u16). + * This is similar to @NL80211_ATTR_STA_AID but with a difference of being + * allowed to be used with the first @NL80211_CMD_SET_STATION command to + * update a TDLS peer STA entry. + * * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use */ @@ -1472,6 +1631,55 @@ enum nl80211_attrs { NL80211_ATTR_BG_SCAN_PERIOD, + NL80211_ATTR_WDEV, + + NL80211_ATTR_USER_REG_HINT_TYPE, + + NL80211_ATTR_CONN_FAILED_REASON, + + NL80211_ATTR_SAE_DATA, + + NL80211_ATTR_VHT_CAPABILITY, + + NL80211_ATTR_SCAN_FLAGS, + + NL80211_ATTR_CHANNEL_WIDTH, + NL80211_ATTR_CENTER_FREQ1, + NL80211_ATTR_CENTER_FREQ2, + + NL80211_ATTR_P2P_CTWINDOW, + NL80211_ATTR_P2P_OPPPS, + + NL80211_ATTR_LOCAL_MESH_POWER_MODE, + + NL80211_ATTR_ACL_POLICY, + + NL80211_ATTR_MAC_ADDRS, + + NL80211_ATTR_MAC_ACL_MAX, + + NL80211_ATTR_RADAR_EVENT, + + NL80211_ATTR_EXT_CAPA, + NL80211_ATTR_EXT_CAPA_MASK, + + NL80211_ATTR_STA_CAPABILITY, + NL80211_ATTR_STA_EXT_CAPABILITY, + + NL80211_ATTR_PROTOCOL_FEATURES, + NL80211_ATTR_SPLIT_WIPHY_DUMP, + + NL80211_ATTR_DISABLE_VHT, + NL80211_ATTR_VHT_CAPABILITY_MASK, + + NL80211_ATTR_MDID, + NL80211_ATTR_IE_RIC, + + NL80211_ATTR_CRIT_PROT_ID, + NL80211_ATTR_MAX_CRIT_PROT_DURATION, + + NL80211_ATTR_PEER_AID, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, @@ -1515,6 +1723,7 @@ enum nl80211_attrs { #define NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY 16 #define NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY 24 #define NL80211_HT_CAPABILITY_LEN 26 +#define NL80211_VHT_CAPABILITY_LEN 12 #define NL80211_MAX_NR_CIPHER_SUITES 5 #define NL80211_MAX_NR_AKM_SUITES 2 @@ -1793,6 +2002,9 @@ enum nl80211_mpath_info { * @NL80211_BAND_ATTR_HT_CAPA: HT capabilities, as in the HT information IE * @NL80211_BAND_ATTR_HT_AMPDU_FACTOR: A-MPDU factor, as in 11n * @NL80211_BAND_ATTR_HT_AMPDU_DENSITY: A-MPDU density, as in 11n + * @NL80211_BAND_ATTR_VHT_MCS_SET: 32-byte attribute containing the MCS set as + * defined in 802.11ac + * @NL80211_BAND_ATTR_VHT_CAPA: VHT capabilities, as in the HT information IE * @NL80211_BAND_ATTR_MAX: highest band attribute currently defined * @__NL80211_BAND_ATTR_AFTER_LAST: internal use */ @@ -1806,6 +2018,9 @@ enum nl80211_band_attr { NL80211_BAND_ATTR_HT_AMPDU_FACTOR, NL80211_BAND_ATTR_HT_AMPDU_DENSITY, + NL80211_BAND_ATTR_VHT_MCS_SET, + NL80211_BAND_ATTR_VHT_CAPA, + /* keep last */ __NL80211_BAND_ATTR_AFTER_LAST, NL80211_BAND_ATTR_MAX = __NL80211_BAND_ATTR_AFTER_LAST - 1 @@ -2879,4 +3094,53 @@ enum nl80211_probe_resp_offload_support_attr { NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U = 1<<3, }; +/** + * enum nl80211_connect_failed_reason - connection request failed reasons + * @NL80211_CONN_FAIL_MAX_CLIENTS: Maximum number of clients that can be + * handled by the AP is reached. + * @NL80211_CONN_FAIL_BLOCKED_CLIENT: Connection request is rejected due to ACL. + */ +enum nl80211_connect_failed_reason { + NL80211_CONN_FAIL_MAX_CLIENTS, + NL80211_CONN_FAIL_BLOCKED_CLIENT, +}; + +/** + * enum nl80211_acl_policy - access control policy + * + * Access control policy is applied on a MAC list set by + * %NL80211_CMD_START_AP and %NL80211_CMD_SET_MAC_ACL, to + * be used with %NL80211_ATTR_ACL_POLICY. + * + * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are + * listed in ACL, i.e. allow all the stations which are not listed + * in ACL to authenticate. + * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow the stations which are listed + * in ACL, i.e. deny all the stations which are not listed in ACL. + */ +enum nl80211_acl_policy { + NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED, + NL80211_ACL_POLICY_DENY_UNLESS_LISTED, +}; +/** + * enum nl80211_crit_proto_id - nl80211 critical protocol identifiers + * + * @NL80211_CRIT_PROTO_UNSPEC: protocol unspecified. + * @NL80211_CRIT_PROTO_DHCP: BOOTP or DHCPv6 protocol. + * @NL80211_CRIT_PROTO_EAPOL: EAPOL protocol. + * @NL80211_CRIT_PROTO_APIPA: APIPA protocol. + * @NUM_NL80211_CRIT_PROTO: must be kept last. + */ +enum nl80211_crit_proto_id { + NL80211_CRIT_PROTO_UNSPEC, + NL80211_CRIT_PROTO_DHCP, + NL80211_CRIT_PROTO_EAPOL, + NL80211_CRIT_PROTO_APIPA, + /* add other protocols before this one */ + NUM_NL80211_CRIT_PROTO +}; + +/* maximum duration for critical protocol measures */ +#define NL80211_CRIT_PROTO_MAX_DURATION 5000 /* msec */ + #endif /* __LINUX_NL80211_H */ diff --git a/include/linux/prctl.h b/include/linux/prctl.h index be9042b2ca7..ce853707a31 100644 --- a/include/linux/prctl.h +++ b/include/linux/prctl.h @@ -124,6 +124,9 @@ #define PR_SET_CHILD_SUBREAPER 36 #define PR_GET_CHILD_SUBREAPER 37 +#define PR_SET_VMA 0x53564d41 +# define PR_SET_VMA_ANON_NAME 0 + /* * Get effective timerslack value for the process. * It can be higher than PR_GET_TIMERSLACK. diff --git a/include/linux/random.h b/include/linux/random.h index 8f74538c96d..ac621ce886c 100644 --- a/include/linux/random.h +++ b/include/linux/random.h @@ -48,13 +48,13 @@ struct rnd_state { #ifdef __KERNEL__ -extern void rand_initialize_irq(int irq); - +extern void add_device_randomness(const void *, unsigned int); extern void add_input_randomness(unsigned int type, unsigned int code, unsigned int value); -extern void add_interrupt_randomness(int irq); +extern void add_interrupt_randomness(int irq, int irq_flags); extern void get_random_bytes(void *buf, int nbytes); +extern void get_random_bytes_arch(void *buf, int nbytes); void generate_random_uuid(unsigned char uuid_out[16]); #ifndef MODULE diff --git a/include/linux/wcnss_wlan.h b/include/linux/wcnss_wlan.h index eaf7ed383dc..766e5c61527 100644 --- a/include/linux/wcnss_wlan.h +++ b/include/linux/wcnss_wlan.h @@ -25,6 +25,12 @@ struct wcnss_wlan_config { int use_48mhz_xo; }; +enum { + WCNSS_XO_48MHZ = 1, + WCNSS_XO_19MHZ, + WCNSS_XO_INVALID, +}; + #define WCNSS_WLAN_IRQ_INVALID -1 #define HAVE_WCNSS_RESET_INTR 1 @@ -54,6 +60,7 @@ void wcnss_prevent_suspend(void); void wcnss_ssr_boot_notify(void); void wcnss_reset_intr(void); int wcnss_cold_boot_done(void); +int wcnss_wlan_iris_xo_mode(void); #define wcnss_wlan_get_drvdata(dev) dev_get_drvdata(dev) #define wcnss_wlan_set_drvdata(dev, data) dev_set_drvdata((dev), (data)) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index d29c15790f8..8f33405a19d 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -210,6 +210,22 @@ struct ieee80211_sta_ht_cap { struct ieee80211_mcs_info mcs; }; +/** + * struct ieee80211_sta_vht_cap - STA's VHT capabilities + * + * This structure describes most essential parameters needed + * to describe 802.11ac VHT capabilities for an STA. + * + * @vht_supported: is VHT supported by the STA + * @cap: VHT capabilities map as described in 802.11ac spec + * @vht_mcs: Supported VHT MCS rates + */ +struct ieee80211_sta_vht_cap { + bool vht_supported; + u32 cap; /* use IEEE80211_VHT_CAP_ */ + struct ieee80211_vht_mcs_info vht_mcs; +}; + /** * struct ieee80211_supported_band - frequency band definition * @@ -233,6 +249,7 @@ struct ieee80211_supported_band { int n_channels; int n_bitrates; struct ieee80211_sta_ht_cap ht_cap; + struct ieee80211_sta_vht_cap vht_cap; }; /* @@ -399,6 +416,26 @@ struct cfg80211_beacon_data { size_t probe_resp_len; }; +struct mac_address { + u8 addr[ETH_ALEN]; +}; + +/** + * struct cfg80211_acl_data - Access control list data + * + * @acl_policy: ACL policy to be applied on the station's + * entry specified by mac_addr + * @n_acl_entries: Number of MAC address entries passed + * @mac_addrs: List of MAC addresses of stations to be used for ACL + */ +struct cfg80211_acl_data { + enum nl80211_acl_policy acl_policy; + int n_acl_entries; + + /* Keep it last */ + struct mac_address mac_addrs[]; +}; + /** * struct cfg80211_ap_settings - AP configuration * @@ -415,6 +452,8 @@ struct cfg80211_beacon_data { * @privacy: the BSS uses privacy * @auth_type: Authentication type (algorithm) * @inactivity_timeout: time in seconds to determine station's inactivity. + * @acl: ACL configuration used by the drivers which has support for + * MAC address based access control */ struct cfg80211_ap_settings { struct cfg80211_beacon_data beacon; @@ -427,6 +466,7 @@ struct cfg80211_ap_settings { bool privacy; enum nl80211_auth_type auth_type; int inactivity_timeout; + const struct cfg80211_acl_data *acl; }; /** @@ -445,12 +485,14 @@ enum plink_actions { /** * enum station_parameters_apply_mask - station parameter values to apply * @STATION_PARAM_APPLY_UAPSD: apply new uAPSD parameters (uapsd_queues, max_sp) + * @STATION_PARAM_APPLY_CAPABILITY: apply new capability * * Not all station parameters have in-band "no change" signalling, * for those that don't these flags will are used. */ enum station_parameters_apply_mask { STATION_PARAM_APPLY_UAPSD = BIT(0), + STATION_PARAM_APPLY_CAPABILITY = BIT(1), }; /** @@ -471,6 +513,7 @@ enum station_parameters_apply_mask { * @plink_action: plink action to take * @plink_state: set the peer link state for a station * @ht_capa: HT capabilities of station + * @vht_capa: VHT capabilities of station * @uapsd_queues: bitmap of queues configured for uapsd. same format * as the AC bitmap in the QoS info field * @max_sp: max Service Period. same format as the MAX_SP in the @@ -478,6 +521,9 @@ enum station_parameters_apply_mask { * @sta_modify_mask: bitmap indicating which parameters changed * (for those that don't have a natural "no change" value), * see &enum station_parameters_apply_mask + * @capability: station capability + * @ext_capab: extended capabilities of the station + * @ext_capab_len: number of extended capabilities */ struct station_parameters { u8 *supported_rates; @@ -490,8 +536,12 @@ struct station_parameters { u8 plink_action; u8 plink_state; struct ieee80211_ht_cap *ht_capa; + struct ieee80211_vht_cap *vht_capa; u8 uapsd_queues; u8 max_sp; + u16 capability; + u8 *ext_capab; + u8 ext_capab_len; }; /** @@ -1331,6 +1381,21 @@ struct cfg80211_gtk_rekey_data { u8 replay_ctr[NL80211_REPLAY_CTR_LEN]; }; +/** + * struct cfg80211_update_ft_ies_params - FT IE Information + * + * This structure provides information needed to update the fast transition IE + * + * @md: The Mobility Domain ID, 2 Octet value + * @ie: Fast Transition IEs + * @ie_len: Length of ft_ie in octets + */ +struct cfg80211_update_ft_ies_params { + u16 md; + const u8 *ie; + size_t ie_len; +}; + /** * struct cfg80211_ops - backend description for wireless configuration * @@ -1515,6 +1580,13 @@ struct cfg80211_gtk_rekey_data { * later passes to cfg80211_probe_status(). * * @set_noack_map: Set the NoAck Map for the TIDs. + * @set_mac_acl: Sets MAC address control list in AP and P2P GO mode. + * Parameters include ACL policy, an array of MAC address of stations + * and the number of MAC addresses. If there is already a list in driver + * this new list replaces the existing one. Driver has to clear its ACL + * when number of MAC addresses entries is passed as 0. Drivers which + * advertise the support for MAC based ACL have to implement this callback. + * */ struct cfg80211_ops { int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow); @@ -1711,6 +1783,11 @@ struct cfg80211_ops { u16 noack_map); struct ieee80211_channel *(*get_channel)(struct wiphy *wiphy); + int (*update_ft_ies)(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_update_ft_ies_params *ftie); + + int (*set_mac_acl)(struct wiphy *wiphy, struct net_device *dev, + const struct cfg80211_acl_data *params); }; /* @@ -1878,10 +1955,6 @@ struct ieee80211_iface_combination { bool beacon_int_infra_match; }; -struct mac_address { - u8 addr[ETH_ALEN]; -}; - struct ieee80211_txrx_stypes { u16 tx, rx; }; @@ -2022,6 +2095,9 @@ struct wiphy_wowlan_support { * @ap_sme_capa: AP SME capabilities, flags from &enum nl80211_ap_sme_features. * @ht_capa_mod_mask: Specify what ht_cap values can be over-ridden. * If null, then none can be over-ridden. + * + * @max_acl_mac_addrs: Maximum number of MAC addresses that the device + * supports for ACL. */ struct wiphy { /* assign these fields before you register the wiphy */ @@ -2043,6 +2119,8 @@ struct wiphy { /* Supported interface modes, OR together BIT(NL80211_IFTYPE_...) */ u16 interface_modes; + u16 max_acl_mac_addrs; + u32 flags, features; u32 ap_sme_capa; @@ -3381,6 +3459,31 @@ void cfg80211_tdls_oper_request(struct net_device *dev, const u8 *peer, */ u16 cfg80211_calculate_bitrate(struct rate_info *rate); +/** + * struct cfg80211_ft_event - FT Information Elements + * @ies: FT IEs + * @ies_len: length of the FT IE in bytes + * @target_ap: target AP's MAC address + * @ric_ies: RIC IE + * @ric_ies_len: length of the RIC IE in bytes + */ +struct cfg80211_ft_event_params { + const u8 *ies; + size_t ies_len; + const u8 *target_ap; + const u8 *ric_ies; + size_t ric_ies_len; +}; + +/** + * cfg80211_ft_event - notify userspace about FT IE and RIC IE + * @netdev: network device + * @ft_event: IE information + */ +void cfg80211_ft_event(struct net_device *netdev, + struct cfg80211_ft_event_params *ft_event); + + /* Logging, debugging and troubleshooting/diagnostic helpers. */ /* wiphy_printk helpers, similar to dev_printk */ diff --git a/include/net/inet6_hashtables.h b/include/net/inet6_hashtables.h index 00cbb4384c7..2da45ce8acb 100644 --- a/include/net/inet6_hashtables.h +++ b/include/net/inet6_hashtables.h @@ -28,16 +28,16 @@ struct inet_hashinfo; -/* I have no idea if this is a good hash for v6 or not. -DaveM */ static inline unsigned int inet6_ehashfn(struct net *net, const struct in6_addr *laddr, const u16 lport, const struct in6_addr *faddr, const __be16 fport) { - u32 ports = (lport ^ (__force u16)fport); + u32 ports = (((u32)lport) << 16) | (__force u32)fport; return jhash_3words((__force u32)laddr->s6_addr32[3], - (__force u32)faddr->s6_addr32[3], - ports, inet_ehash_secret + net_hash_mix(net)); + ipv6_addr_jhash(faddr), + ports, + inet_ehash_secret + net_hash_mix(net)); } static inline int inet6_sk_ehashfn(const struct sock *sk) diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h index ae17e1352d7..8cd2e1d0ec3 100644 --- a/include/net/inet_sock.h +++ b/include/net/inet_sock.h @@ -202,6 +202,7 @@ static inline void inet_sk_copy_descendant(struct sock *sk_to, extern int inet_sk_rebuild_header(struct sock *sk); extern u32 inet_ehash_secret; +extern u32 ipv6_hash_secret; extern void build_ehash_secret(void); static inline unsigned int inet_ehashfn(struct net *net, diff --git a/include/net/ipv6.h b/include/net/ipv6.h index e4170a22fc6..5381973f099 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -15,6 +15,7 @@ #include #include +#include #include #include #include @@ -252,6 +253,14 @@ static inline void fl6_sock_release(struct ip6_flowlabel *fl) atomic_dec(&fl->users); } +extern void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info); + +int icmpv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6, + struct icmp6hdr *thdr, int len); + +struct dst_entry *icmpv6_route_lookup(struct net *net, struct sk_buff *skb, + struct sock *sk, struct flowi6 *fl6); + extern int ip6_ra_control(struct sock *sk, int sel); extern int ipv6_parse_hopopts(struct sk_buff *skb); @@ -294,6 +303,18 @@ static inline int ipv6_addr_src_scope(const struct in6_addr *addr) return __ipv6_addr_src_scope(__ipv6_addr_type(addr)); } +static inline bool __ipv6_addr_needs_scope_id(int type) +{ + return type & IPV6_ADDR_LINKLOCAL || + (type & IPV6_ADDR_MULTICAST && + (type & (IPV6_ADDR_LOOPBACK|IPV6_ADDR_LINKLOCAL))); +} + +static inline __u32 ipv6_iface_scope_id(const struct in6_addr *addr, int iface) +{ + return __ipv6_addr_needs_scope_id(__ipv6_addr_type(addr)) ? iface : 0; +} + static inline int ipv6_addr_cmp(const struct in6_addr *a1, const struct in6_addr *a2) { return memcmp(a1, a2, sizeof(struct in6_addr)); @@ -396,6 +417,17 @@ static inline int ipv6_addr_any(const struct in6_addr *a) a->s6_addr32[2] | a->s6_addr32[3]) == 0; } +/* more secured version of ipv6_addr_hash() */ +static inline u32 ipv6_addr_jhash(const struct in6_addr *a) +{ + u32 v = (__force u32)a->s6_addr32[0] ^ (__force u32)a->s6_addr32[1]; + + return jhash_3words(v, + (__force u32)a->s6_addr32[2], + (__force u32)a->s6_addr32[3], + ipv6_hash_secret); +} + static inline int ipv6_addr_loopback(const struct in6_addr *a) { return (a->s6_addr32[0] | a->s6_addr32[1] | diff --git a/include/net/ping.h b/include/net/ping.h index 682b5ae9af5..b1717ae93da 100644 --- a/include/net/ping.h +++ b/include/net/ping.h @@ -13,6 +13,7 @@ #ifndef _PING_H #define _PING_H +#include #include /* PING_HTABLE_SIZE must be power of 2 */ @@ -28,6 +29,18 @@ */ #define GID_T_MAX (((gid_t)~0U) >> 1) +/* Compatibility glue so we can support IPv6 when it's compiled as a module */ +struct pingv6_ops { + int (*ipv6_recv_error)(struct sock *sk, struct msghdr *msg, int len); + int (*datagram_recv_ctl)(struct sock *sk, struct msghdr *msg, + struct sk_buff *skb); + int (*icmpv6_err_convert)(u8 type, u8 code, int *err); + void (*ipv6_icmp_error)(struct sock *sk, struct sk_buff *skb, int err, + __be16 port, u32 info, u8 *payload); + int (*ipv6_chk_addr)(struct net *net, const struct in6_addr *addr, + struct net_device *dev, int strict); +}; + struct ping_table { struct hlist_nulls_head hash[PING_HTABLE_SIZE]; rwlock_t lock; @@ -39,10 +52,40 @@ struct ping_iter_state { }; extern struct proto ping_prot; +extern struct ping_table ping_table; +#if IS_ENABLED(CONFIG_IPV6) +extern struct pingv6_ops pingv6_ops; +#endif +struct pingfakehdr { + struct icmphdr icmph; + struct iovec *iov; + sa_family_t family; + __wsum wcheck; +}; -extern void ping_rcv(struct sk_buff *); -extern void ping_err(struct sk_buff *, u32 info); +int ping_get_port(struct sock *sk, unsigned short ident); +void ping_hash(struct sock *sk); +void ping_unhash(struct sock *sk); + +int ping_init_sock(struct sock *sk); +void ping_close(struct sock *sk, long timeout); +int ping_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len); +void ping_err(struct sk_buff *skb, int offset, u32 info); +void ping_v4_err(struct sk_buff *skb, u32 info); +int ping_getfrag(void *from, char *to, int offset, int fraglen, int odd, + struct sk_buff *); + +int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + size_t len, int noblock, int flags, int *addr_len); +int ping_common_sendmsg(int family, struct msghdr *msg, size_t len, + void *user_icmph, size_t icmph_len); +int ping_v4_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + size_t len); +int ping_v6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + size_t len); +int ping_queue_rcv_skb(struct sock *sk, struct sk_buff *skb); +void ping_rcv(struct sk_buff *skb); #ifdef CONFIG_PROC_FS extern int __init ping_proc_init(void); @@ -50,6 +93,7 @@ extern void ping_proc_exit(void); #endif void __init ping_init(void); - +int __init pingv6_init(void); +void pingv6_exit(void); #endif /* _PING_H */ diff --git a/include/net/secure_seq.h b/include/net/secure_seq.h index c2e542b27a5..6ca975bebd3 100644 --- a/include/net/secure_seq.h +++ b/include/net/secure_seq.h @@ -3,6 +3,7 @@ #include +extern void net_secret_init(void); extern __u32 secure_ip_id(__be32 daddr); extern __u32 secure_ipv6_id(const __be32 daddr[4]); extern u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport); diff --git a/include/net/transp_v6.h b/include/net/transp_v6.h index 498433dd067..48b42ea9c2f 100644 --- a/include/net/transp_v6.h +++ b/include/net/transp_v6.h @@ -11,6 +11,7 @@ extern struct proto rawv6_prot; extern struct proto udpv6_prot; extern struct proto udplitev6_prot; extern struct proto tcpv6_prot; +extern struct proto pingv6_prot; struct flowi6; @@ -21,6 +22,8 @@ extern int ipv6_frag_init(void); extern void ipv6_frag_exit(void); /* transport protocols */ +extern int pingv6_init(void); +extern void pingv6_exit(void); extern int rawv6_init(void); extern void rawv6_exit(void); extern int udpv6_init(void); diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c index bdb18032555..131ca176b49 100644 --- a/kernel/irq/handle.c +++ b/kernel/irq/handle.c @@ -133,7 +133,7 @@ irqreturn_t handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action) { irqreturn_t retval = IRQ_NONE; - unsigned int random = 0, irq = desc->irq_data.irq; + unsigned int flags = 0, irq = desc->irq_data.irq; do { irqreturn_t res; @@ -161,7 +161,7 @@ handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action) /* Fall through to add to randomness */ case IRQ_HANDLED: - random |= action->flags; + flags |= action->flags; break; default: @@ -172,8 +172,7 @@ handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action) action = action->next; } while (action); - if (random & IRQF_SAMPLE_RANDOM) - add_interrupt_randomness(irq); + add_interrupt_randomness(irq, flags); if (!noirqdebug) note_interrupt(irq, desc, retval); diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 165d5dc53fd..8550d4b3437 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -916,22 +916,6 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) return -ENOSYS; if (!try_module_get(desc->owner)) return -ENODEV; - /* - * Some drivers like serial.c use request_irq() heavily, - * so we have to be careful not to interfere with a - * running system. - */ - if (new->flags & IRQF_SAMPLE_RANDOM) { - /* - * This function might sleep, we want to call it first, - * outside of the atomic block. - * Yes, this might clear the entropy pool if the wrong - * driver is attempted to be loaded, without actually - * installing a new handler, but is this really a problem, - * only the sysadmin is able to do this. - */ - rand_initialize_irq(irq); - } /* * Check whether the interrupt nests into another interrupt @@ -1372,7 +1356,6 @@ EXPORT_SYMBOL(free_irq); * Flags: * * IRQF_SHARED Interrupt is shared - * IRQF_SAMPLE_RANDOM The interrupt can be used for entropy * IRQF_TRIGGER_* Specify active edge(s) or level * */ diff --git a/kernel/panic.c b/kernel/panic.c index 4ffbce815c5..2bd000132e0 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -24,6 +24,7 @@ #include #include #include +#include #define PANIC_TIMER_STEP 100 #define PANIC_BLINK_SPD 18 @@ -133,6 +134,10 @@ void panic(const char *fmt, ...) kmsg_dump(KMSG_DUMP_PANIC); + /* print last_kmsg even after console suspend */ + if (is_console_suspended()) + resume_console(); + /* * Note smp_send_stop is the usual smp shutdown function, which * unfortunately means it may not be hardened to work in a panic diff --git a/kernel/power/process.c b/kernel/power/process.c index 93ab3aee230..fa899042eec 100644 --- a/kernel/power/process.c +++ b/kernel/power/process.c @@ -32,8 +32,8 @@ static int try_to_freeze_tasks(bool user_only) unsigned int todo; bool wq_busy = false; struct timeval start, end; - u64 elapsed_msecs64; - unsigned int elapsed_msecs; + u64 elapsed_msecs64; + unsigned int elapsed_msecs; bool wakeup = false; int sleep_usecs = USEC_PER_MSEC; @@ -72,10 +72,6 @@ static int try_to_freeze_tasks(bool user_only) todo += wq_busy; } - if (todo && has_wake_lock(WAKE_LOCK_SUSPEND)) { - wakeup = 1; - break; - } if (!todo || time_after(jiffies, end_time)) break; @@ -86,11 +82,12 @@ static int try_to_freeze_tasks(bool user_only) /* * We need to retry, but first give the freezing tasks some - * time to enter the regrigerator. + * time to enter the refrigerator. Start with an initial + * 1 ms sleep followed by exponential backoff until 8 ms. */ usleep_range(sleep_usecs / 2, sleep_usecs); - if (sleep_usecs < 8 * USEC_PER_MSEC) - sleep_usecs *= 2; + if (sleep_usecs < 8 * USEC_PER_MSEC) + sleep_usecs *= 2; } do_gettimeofday(&end); @@ -99,31 +96,18 @@ static int try_to_freeze_tasks(bool user_only) elapsed_msecs = elapsed_msecs64; if (todo) { - /* This does not unfreeze processes that are already frozen - * (we have slightly ugly calling convention in that respect, - * and caller must call thaw_processes() if something fails), - * but it cleans up leftover PF_FREEZE requests. - */ - if(wakeup) { - printk("\n"); - printk(KERN_ERR "Freezing of %s aborted\n", - user_only ? "user space " : "tasks "); - } - else { - printk("\n"); - printk(KERN_ERR "Freezing of tasks %s after %d.%03d seconds " - "(%d tasks refusing to freeze, wq_busy=%d):\n", - wakeup ? "aborted" : "failed", - elapsed_msecs / 1000, elapsed_msecs % 1000, - todo - wq_busy, wq_busy); - } + printk("\n"); + printk(KERN_ERR "Freezing of tasks %s after %d.%03d seconds " + "(%d tasks refusing to freeze, wq_busy=%d):\n", + wakeup ? "aborted" : "failed", + elapsed_msecs / 1000, elapsed_msecs % 1000, + todo - wq_busy, wq_busy); if (!wakeup) { read_lock(&tasklist_lock); do_each_thread(g, p) { if (p != current && !freezer_should_skip(p) - && freezing(p) && !frozen(p) && - elapsed_msecs > 1000) + && freezing(p) && !frozen(p)) sched_show_task(p); } while_each_thread(g, p); read_unlock(&tasklist_lock); diff --git a/kernel/printk.c b/kernel/printk.c index 86590409dc0..b0722979200 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -1188,6 +1188,12 @@ module_param_named(console_suspend, console_suspend_enabled, MODULE_PARM_DESC(console_suspend, "suspend console during suspend" " and hibernate operations"); +/* check current suspend/resume status of the console */ +int is_console_suspended(void) +{ + return console_suspended; +} + /** * suspend_console - suspend the console subsystem * diff --git a/kernel/signal.c b/kernel/signal.c index dde41622e34..cd0e615b558 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -2211,7 +2211,7 @@ int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka, * Now that we woke up, it's crucial if we're supposed to be * frozen that we freeze now before running anything substantial. */ - try_to_freeze(); + try_to_freeze_nowarn(); spin_lock_irq(&sighand->siglock); /* diff --git a/kernel/sys.c b/kernel/sys.c index 7095efafff6..81a2107d330 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -40,6 +40,8 @@ #include #include #include +#include +#include #include #include @@ -1821,6 +1823,146 @@ static int prctl_set_mm(int opt, unsigned long addr, } #endif + +static int prctl_update_vma_anon_name(struct vm_area_struct *vma, + struct vm_area_struct **prev, + unsigned long start, unsigned long end, + const char __user *name_addr) +{ + struct mm_struct * mm = vma->vm_mm; + int error = 0; + pgoff_t pgoff; + + if (name_addr == vma_get_anon_name(vma)) { + *prev = vma; + goto out; + } + + pgoff = vma->vm_pgoff + ((start - vma->vm_start) >> PAGE_SHIFT); + *prev = vma_merge(mm, *prev, start, end, vma->vm_flags, vma->anon_vma, + vma->vm_file, pgoff, vma_policy(vma), + name_addr); + if (*prev) { + vma = *prev; + goto success; + } + + *prev = vma; + + if (start != vma->vm_start) { + error = split_vma(mm, vma, start, 1); + if (error) + goto out; + } + + if (end != vma->vm_end) { + error = split_vma(mm, vma, end, 0); + if (error) + goto out; + } + +success: + if (!vma->vm_file) + vma->shared.anon_name = name_addr; + +out: + if (error == -ENOMEM) + error = -EAGAIN; + return error; +} + +static int prctl_set_vma_anon_name(unsigned long start, unsigned long end, + unsigned long arg) +{ + unsigned long tmp; + struct vm_area_struct * vma, *prev; + int unmapped_error = 0; + int error = -EINVAL; + + /* + * If the interval [start,end) covers some unmapped address + * ranges, just ignore them, but return -ENOMEM at the end. + * - this matches the handling in madvise. + */ + vma = find_vma_prev(current->mm, start, &prev); + if (vma && start > vma->vm_start) + prev = vma; + + for (;;) { + /* Still start < end. */ + error = -ENOMEM; + if (!vma) + return error; + + /* Here start < (end|vma->vm_end). */ + if (start < vma->vm_start) { + unmapped_error = -ENOMEM; + start = vma->vm_start; + if (start >= end) + return error; + } + + /* Here vma->vm_start <= start < (end|vma->vm_end) */ + tmp = vma->vm_end; + if (end < tmp) + tmp = end; + + /* Here vma->vm_start <= start < tmp <= (end|vma->vm_end). */ + error = prctl_update_vma_anon_name(vma, &prev, start, end, + (const char __user *)arg); + if (error) + return error; + start = tmp; + if (prev && start < prev->vm_end) + start = prev->vm_end; + error = unmapped_error; + if (start >= end) + return error; + if (prev) + vma = prev->vm_next; + else /* madvise_remove dropped mmap_sem */ + vma = find_vma(current->mm, start); + } +} + +static int prctl_set_vma(unsigned long opt, unsigned long start, + unsigned long len_in, unsigned long arg) +{ + struct mm_struct *mm = current->mm; + int error; + unsigned long len; + unsigned long end; + + if (start & ~PAGE_MASK) + return -EINVAL; + len = (len_in + ~PAGE_MASK) & PAGE_MASK; + + /* Check to see whether len was rounded up from small -ve to zero */ + if (len_in && !len) + return -EINVAL; + + end = start + len; + if (end < start) + return -EINVAL; + + if (end == start) + return 0; + + down_write(&mm->mmap_sem); + + switch (opt) { + case PR_SET_VMA_ANON_NAME: + error = prctl_set_vma_anon_name(start, end, arg); + break; + default: + error = -EINVAL; + } + + up_write(&mm->mmap_sem); + + return error; +} + SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, unsigned long, arg4, unsigned long, arg5) { @@ -1984,6 +2126,9 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, error = put_user(me->signal->is_child_subreaper, (int __user *) arg2); break; + case PR_SET_VMA: + error = prctl_set_vma(arg2, arg3, arg4, arg5); + break; default: error = -EINVAL; break; diff --git a/mm/madvise.c b/mm/madvise.c index 55f645c85a3..b075d1d1f6c 100644 --- a/mm/madvise.c +++ b/mm/madvise.c @@ -93,7 +93,8 @@ static long madvise_behavior(struct vm_area_struct * vma, pgoff = vma->vm_pgoff + ((start - vma->vm_start) >> PAGE_SHIFT); *prev = vma_merge(mm, *prev, start, end, new_flags, vma->anon_vma, - vma->vm_file, pgoff, vma_policy(vma)); + vma->vm_file, pgoff, vma_policy(vma), + vma_get_anon_name(vma)); if (*prev) { vma = *prev; goto success; diff --git a/mm/mempolicy.c b/mm/mempolicy.c index bf5b485ecd3..008de5baa82 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -639,7 +639,7 @@ static int mbind_range(struct mm_struct *mm, unsigned long start, ((vmstart - vma->vm_start) >> PAGE_SHIFT); prev = vma_merge(mm, prev, vmstart, vmend, vma->vm_flags, vma->anon_vma, vma->vm_file, pgoff, - new_pol); + new_pol, vma_get_anon_name(name)); if (prev) { vma = prev; next = vma->vm_next; diff --git a/mm/mlock.c b/mm/mlock.c index ef726e8aa8e..263e49dd1ba 100644 --- a/mm/mlock.c +++ b/mm/mlock.c @@ -329,7 +329,8 @@ static int mlock_fixup(struct vm_area_struct *vma, struct vm_area_struct **prev, pgoff = vma->vm_pgoff + ((start - vma->vm_start) >> PAGE_SHIFT); *prev = vma_merge(mm, *prev, start, end, newflags, vma->anon_vma, - vma->vm_file, pgoff, vma_policy(vma)); + vma->vm_file, pgoff, vma_policy(vma), + vma_get_anon_name(vma)); if (*prev) { vma = *prev; goto success; diff --git a/mm/mmap.c b/mm/mmap.c index 848ef52d960..ded6fe9f144 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -649,7 +649,8 @@ again: remove_next = 1 + (end > next->vm_end); * per-vma resources, so we don't attempt to merge those. */ static inline int is_mergeable_vma(struct vm_area_struct *vma, - struct file *file, unsigned long vm_flags) + struct file *file, unsigned long vm_flags, + const char __user *anon_name) { /* VM_CAN_NONLINEAR may get set later by f_op->mmap() */ if ((vma->vm_flags ^ vm_flags) & ~VM_CAN_NONLINEAR) @@ -658,6 +659,8 @@ static inline int is_mergeable_vma(struct vm_area_struct *vma, return 0; if (vma->vm_ops && vma->vm_ops->close) return 0; + if (vma_get_anon_name(vma) != anon_name) + return 0; return 1; } @@ -688,9 +691,10 @@ static inline int is_mergeable_anon_vma(struct anon_vma *anon_vma1, */ static int can_vma_merge_before(struct vm_area_struct *vma, unsigned long vm_flags, - struct anon_vma *anon_vma, struct file *file, pgoff_t vm_pgoff) + struct anon_vma *anon_vma, struct file *file, pgoff_t vm_pgoff, + const char __user *anon_name) { - if (is_mergeable_vma(vma, file, vm_flags) && + if (is_mergeable_vma(vma, file, vm_flags, anon_name) && is_mergeable_anon_vma(anon_vma, vma->anon_vma, vma)) { if (vma->vm_pgoff == vm_pgoff) return 1; @@ -707,9 +711,10 @@ can_vma_merge_before(struct vm_area_struct *vma, unsigned long vm_flags, */ static int can_vma_merge_after(struct vm_area_struct *vma, unsigned long vm_flags, - struct anon_vma *anon_vma, struct file *file, pgoff_t vm_pgoff) + struct anon_vma *anon_vma, struct file *file, pgoff_t vm_pgoff, + const char __user *anon_name) { - if (is_mergeable_vma(vma, file, vm_flags) && + if (is_mergeable_vma(vma, file, vm_flags, anon_name) && is_mergeable_anon_vma(anon_vma, vma->anon_vma, vma)) { pgoff_t vm_pglen; vm_pglen = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; @@ -720,9 +725,9 @@ can_vma_merge_after(struct vm_area_struct *vma, unsigned long vm_flags, } /* - * Given a mapping request (addr,end,vm_flags,file,pgoff), figure out - * whether that can be merged with its predecessor or its successor. - * Or both (it neatly fills a hole). + * Given a mapping request (addr,end,vm_flags,file,pgoff,anon_name), + * figure out whether that can be merged with its predecessor or its + * successor. Or both (it neatly fills a hole). * * In most cases - when called for mmap, brk or mremap - [addr,end) is * certain not to be mapped by the time vma_merge is called; but when @@ -752,7 +757,8 @@ struct vm_area_struct *vma_merge(struct mm_struct *mm, struct vm_area_struct *prev, unsigned long addr, unsigned long end, unsigned long vm_flags, struct anon_vma *anon_vma, struct file *file, - pgoff_t pgoff, struct mempolicy *policy) + pgoff_t pgoff, struct mempolicy *policy, + const char __user *anon_name) { pgoff_t pglen = (end - addr) >> PAGE_SHIFT; struct vm_area_struct *area, *next; @@ -778,15 +784,15 @@ struct vm_area_struct *vma_merge(struct mm_struct *mm, */ if (prev && prev->vm_end == addr && mpol_equal(vma_policy(prev), policy) && - can_vma_merge_after(prev, vm_flags, - anon_vma, file, pgoff)) { + can_vma_merge_after(prev, vm_flags, anon_vma, + file, pgoff, anon_name)) { /* * OK, it can. Can we now merge in the successor as well? */ if (next && end == next->vm_start && mpol_equal(policy, vma_policy(next)) && - can_vma_merge_before(next, vm_flags, - anon_vma, file, pgoff+pglen) && + can_vma_merge_before(next, vm_flags, anon_vma, + file, pgoff+pglen, anon_name) && is_mergeable_anon_vma(prev->anon_vma, next->anon_vma, NULL)) { /* cases 1, 6 */ @@ -806,8 +812,8 @@ struct vm_area_struct *vma_merge(struct mm_struct *mm, */ if (next && end == next->vm_start && mpol_equal(policy, vma_policy(next)) && - can_vma_merge_before(next, vm_flags, - anon_vma, file, pgoff+pglen)) { + can_vma_merge_before(next, vm_flags, anon_vma, + file, pgoff+pglen, anon_name)) { if (prev && addr < prev->vm_end) /* case 4 */ err = vma_adjust(prev, prev->vm_start, addr, prev->vm_pgoff, NULL); @@ -1282,7 +1288,8 @@ unsigned long mmap_region(struct file *file, unsigned long addr, /* * Can we just expand an old mapping? */ - vma = vma_merge(mm, prev, addr, addr + len, vm_flags, NULL, file, pgoff, NULL); + vma = vma_merge(mm, prev, addr, addr + len, vm_flags, NULL, file, pgoff, + NULL, NULL); if (vma) goto out; @@ -2232,7 +2239,7 @@ static unsigned long do_brk(unsigned long addr, unsigned long len) /* Can we just expand an old private anonymous mapping? */ vma = vma_merge(mm, prev, addr, addr + len, flags, - NULL, NULL, pgoff, NULL); + NULL, NULL, pgoff, NULL, NULL); if (vma) goto out; @@ -2382,7 +2389,8 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap, find_vma_prepare(mm, addr, &prev, &rb_link, &rb_parent); new_vma = vma_merge(mm, prev, addr, addr + len, vma->vm_flags, - vma->anon_vma, vma->vm_file, pgoff, vma_policy(vma)); + vma->anon_vma, vma->vm_file, pgoff, vma_policy(vma), + vma_get_anon_name(vma)); if (new_vma) { /* * Source vma may have been merged into new_vma diff --git a/mm/mprotect.c b/mm/mprotect.c index a40992610ab..10add6b44c5 100644 --- a/mm/mprotect.c +++ b/mm/mprotect.c @@ -179,7 +179,8 @@ mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev, */ pgoff = vma->vm_pgoff + ((start - vma->vm_start) >> PAGE_SHIFT); *pprev = vma_merge(mm, *pprev, start, end, newflags, - vma->anon_vma, vma->vm_file, pgoff, vma_policy(vma)); + vma->anon_vma, vma->vm_file, pgoff, vma_policy(vma), + vma_get_anon_name(vma)); if (*pprev) { vma = *pprev; goto success; diff --git a/net/core/dev.c b/net/core/dev.c index 99e1d759f41..70145dcd17f 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1173,6 +1173,7 @@ static int __dev_open(struct net_device *dev) net_dmaengine_get(); dev_set_rx_mode(dev); dev_activate(dev); + add_device_randomness(dev->dev_addr, dev->addr_len); } return ret; @@ -4786,6 +4787,7 @@ int dev_set_mac_address(struct net_device *dev, struct sockaddr *sa) err = ops->ndo_set_mac_address(dev, sa); if (!err) call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); + add_device_randomness(dev->dev_addr, dev->addr_len); return err; } EXPORT_SYMBOL(dev_set_mac_address); @@ -5564,6 +5566,7 @@ int register_netdevice(struct net_device *dev) dev_init_scheduler(dev); dev_hold(dev); list_netdevice(dev); + add_device_randomness(dev->dev_addr, dev->addr_len); /* Notify protocols, that a new device appeared. */ ret = call_netdevice_notifiers(NETDEV_REGISTER, dev); diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 90430b776ec..c897d512f2c 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -1370,6 +1370,7 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, goto errout; send_addr_notify = 1; modified = 1; + add_device_randomness(dev->dev_addr, dev->addr_len); } if (tb[IFLA_MTU]) { diff --git a/net/core/secure_seq.c b/net/core/secure_seq.c index 99b2596531b..a4ba3800628 100644 --- a/net/core/secure_seq.c +++ b/net/core/secure_seq.c @@ -12,12 +12,10 @@ static u32 net_secret[MD5_MESSAGE_BYTES / 4] ____cacheline_aligned; -static int __init net_secret_init(void) +void net_secret_init(void) { get_random_bytes(net_secret, sizeof(net_secret)); - return 0; } -late_initcall(net_secret_init); #ifdef CONFIG_INET static u32 seq_scale(u32 seq) diff --git a/net/core/sock_diag.c b/net/core/sock_diag.c index b9868e1fd62..aa74be442df 100644 --- a/net/core/sock_diag.c +++ b/net/core/sock_diag.c @@ -126,6 +126,9 @@ static int __sock_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) if (nlmsg_len(nlh) < sizeof(*req)) return -EINVAL; + if (req->sdiag_family >= AF_MAX) + return -EINVAL; + hndl = sock_diag_lock_handler(req->sdiag_family); if (hndl == NULL) err = -ENOENT; diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 0b711659ac7..690948330d5 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -115,6 +115,7 @@ #include #include #include +#include #ifdef CONFIG_IP_MROUTE #include #endif @@ -240,8 +241,12 @@ EXPORT_SYMBOL(inet_listen); u32 inet_ehash_secret __read_mostly; EXPORT_SYMBOL(inet_ehash_secret); +u32 ipv6_hash_secret __read_mostly; +EXPORT_SYMBOL(ipv6_hash_secret); + /* - * inet_ehash_secret must be set exactly once + * inet_ehash_secret must be set exactly once, and to a non nul value + * ipv6_hash_secret must be set exactly once. */ void build_ehash_secret(void) { @@ -251,7 +256,10 @@ void build_ehash_secret(void) get_random_bytes(&rnd, sizeof(rnd)); } while (rnd == 0); - cmpxchg(&inet_ehash_secret, 0, rnd); + if (cmpxchg(&inet_ehash_secret, 0, rnd) == 0) { + get_random_bytes(&ipv6_hash_secret, sizeof(ipv6_hash_secret)); + net_secret_init(); + } } EXPORT_SYMBOL(build_ehash_secret); @@ -1559,7 +1567,7 @@ static const struct net_protocol udp_protocol = { static const struct net_protocol icmp_protocol = { .handler = icmp_rcv, - .err_handler = ping_err, + .err_handler = ping_v4_err, .no_policy = 1, .netns_ok = 1, }; diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 2cb2bf84564..2e109ff62ea 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -788,7 +788,7 @@ static void icmp_redirect(struct sk_buff *skb) if (iph->protocol == IPPROTO_ICMP && iph->ihl >= 5 && pskb_may_pull(skb, (iph->ihl<<2)+8)) { - ping_err(skb, icmp_hdr(skb)->un.gateway); + ping_v4_err(skb, icmp_hdr(skb)->un.gateway); } out: diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index 50009c787bc..a8d7ed06234 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c @@ -33,7 +33,6 @@ #include #include #include -#include #include #include #include @@ -46,8 +45,18 @@ #include #include +#if IS_ENABLED(CONFIG_IPV6) +#include +#include +#include +#include +#include +#endif -static struct ping_table ping_table; + +struct ping_table ping_table; +struct pingv6_ops pingv6_ops; +EXPORT_SYMBOL_GPL(pingv6_ops); static u16 ping_port_rover; @@ -57,6 +66,7 @@ static inline int ping_hashfn(struct net *net, unsigned num, unsigned mask) pr_debug("hash(%d) = %d\n", num, res); return res; } +EXPORT_SYMBOL_GPL(ping_hash); static inline struct hlist_nulls_head *ping_hashslot(struct ping_table *table, struct net *net, unsigned num) @@ -64,7 +74,7 @@ static inline struct hlist_nulls_head *ping_hashslot(struct ping_table *table, return &table->hash[ping_hashfn(net, num, PING_HTABLE_MASK)]; } -static int ping_v4_get_port(struct sock *sk, unsigned short ident) +int ping_get_port(struct sock *sk, unsigned short ident) { struct hlist_nulls_node *node; struct hlist_nulls_head *hlist; @@ -102,6 +112,10 @@ static int ping_v4_get_port(struct sock *sk, unsigned short ident) ping_portaddr_for_each_entry(sk2, node, hlist) { isk2 = inet_sk(sk2); + /* BUG? Why is this reuse and not reuseaddr? ping.c + * doesn't turn off SO_REUSEADDR, and it doesn't expect + * that other ping processes can steal its packets. + */ if ((isk2->inet_num == ident) && (sk2 != sk) && (!sk2->sk_reuse || !sk->sk_reuse)) @@ -124,17 +138,18 @@ static int ping_v4_get_port(struct sock *sk, unsigned short ident) write_unlock_bh(&ping_table.lock); return 1; } +EXPORT_SYMBOL_GPL(ping_get_port); -static void ping_v4_hash(struct sock *sk) +void ping_hash(struct sock *sk) { - pr_debug("ping_v4_hash(sk->port=%u)\n", inet_sk(sk)->inet_num); + pr_debug("ping_hash(sk->port=%u)\n", inet_sk(sk)->inet_num); BUG(); /* "Please do not press this button again." */ } -static void ping_v4_unhash(struct sock *sk) +void ping_unhash(struct sock *sk) { struct inet_sock *isk = inet_sk(sk); - pr_debug("ping_v4_unhash(isk=%p,isk->num=%u)\n", isk, isk->inet_num); + pr_debug("ping_unhash(isk=%p,isk->num=%u)\n", isk, isk->inet_num); if (sk_hashed(sk)) { write_lock_bh(&ping_table.lock); hlist_nulls_del(&sk->sk_nulls_node); @@ -145,31 +160,61 @@ static void ping_v4_unhash(struct sock *sk) write_unlock_bh(&ping_table.lock); } } +EXPORT_SYMBOL_GPL(ping_unhash); -static struct sock *ping_v4_lookup(struct net *net, __be32 saddr, __be32 daddr, - u16 ident, int dif) +static struct sock *ping_lookup(struct net *net, struct sk_buff *skb, u16 ident) { struct hlist_nulls_head *hslot = ping_hashslot(&ping_table, net, ident); struct sock *sk = NULL; struct inet_sock *isk; struct hlist_nulls_node *hnode; + int dif = skb->dev->ifindex; + + if (skb->protocol == htons(ETH_P_IP)) { + pr_debug("try to find: num = %d, daddr = %pI4, dif = %d\n", + (int)ident, &ip_hdr(skb)->daddr, dif); +#if IS_ENABLED(CONFIG_IPV6) + } else if (skb->protocol == htons(ETH_P_IPV6)) { + pr_debug("try to find: num = %d, daddr = %pI6c, dif = %d\n", + (int)ident, &ipv6_hdr(skb)->daddr, dif); +#endif + } - pr_debug("try to find: num = %d, daddr = %pI4, dif = %d\n", - (int)ident, &daddr, dif); read_lock_bh(&ping_table.lock); ping_portaddr_for_each_entry(sk, hnode, hslot) { isk = inet_sk(sk); - pr_debug("found: %p: num = %d, daddr = %pI4, dif = %d\n", sk, - (int)isk->inet_num, &isk->inet_rcv_saddr, - sk->sk_bound_dev_if); - pr_debug("iterate\n"); if (isk->inet_num != ident) continue; - if (isk->inet_rcv_saddr && isk->inet_rcv_saddr != daddr) - continue; + + if (skb->protocol == htons(ETH_P_IP) && + sk->sk_family == AF_INET) { + pr_debug("found: %p: num=%d, daddr=%pI4, dif=%d\n", sk, + (int) isk->inet_num, &isk->inet_rcv_saddr, + sk->sk_bound_dev_if); + + if (isk->inet_rcv_saddr && + isk->inet_rcv_saddr != ip_hdr(skb)->daddr) + continue; +#if IS_ENABLED(CONFIG_IPV6) + } else if (skb->protocol == htons(ETH_P_IPV6) && + sk->sk_family == AF_INET6) { + struct ipv6_pinfo *np = inet6_sk(sk); + + pr_debug("found: %p: num=%d, daddr=%pI6c, dif=%d\n", sk, + (int) isk->inet_num, + &inet6_sk(sk)->rcv_saddr, + sk->sk_bound_dev_if); + + if (!ipv6_addr_any(&np->rcv_saddr) && + !ipv6_addr_equal(&np->rcv_saddr, + &ipv6_hdr(skb)->daddr)) + continue; +#endif + } + if (sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif) continue; @@ -198,7 +243,7 @@ static void inet_get_ping_group_range_net(struct net *net, gid_t *low, } -static int ping_init_sock(struct sock *sk) +int ping_init_sock(struct sock *sk) { struct net *net = sock_net(sk); gid_t group = current_egid(); @@ -224,8 +269,9 @@ static int ping_init_sock(struct sock *sk) return -EACCES; } +EXPORT_SYMBOL_GPL(ping_init_sock); -static void ping_close(struct sock *sk, long timeout) +void ping_close(struct sock *sk, long timeout) { pr_debug("ping_close(sk=%p,sk->num=%u)\n", inet_sk(sk), inet_sk(sk)->inet_num); @@ -233,36 +279,122 @@ static void ping_close(struct sock *sk, long timeout) sk_common_release(sk); } +EXPORT_SYMBOL_GPL(ping_close); + +/* Checks the bind address and possibly modifies sk->sk_bound_dev_if. */ +int ping_check_bind_addr(struct sock *sk, struct inet_sock *isk, + struct sockaddr *uaddr, int addr_len) { + struct net *net = sock_net(sk); + if (sk->sk_family == AF_INET) { + struct sockaddr_in *addr = (struct sockaddr_in *) uaddr; + int chk_addr_ret; + + if (addr_len < sizeof(*addr)) + return -EINVAL; + + pr_debug("ping_check_bind_addr(sk=%p,addr=%pI4,port=%d)\n", + sk, &addr->sin_addr.s_addr, ntohs(addr->sin_port)); + + chk_addr_ret = inet_addr_type(net, addr->sin_addr.s_addr); + + if (addr->sin_addr.s_addr == htonl(INADDR_ANY)) + chk_addr_ret = RTN_LOCAL; + if ((sysctl_ip_nonlocal_bind == 0 && + isk->freebind == 0 && isk->transparent == 0 && + chk_addr_ret != RTN_LOCAL) || + chk_addr_ret == RTN_MULTICAST || + chk_addr_ret == RTN_BROADCAST) + return -EADDRNOTAVAIL; + +#if IS_ENABLED(CONFIG_IPV6) + } else if (sk->sk_family == AF_INET6) { + struct sockaddr_in6 *addr = (struct sockaddr_in6 *) uaddr; + int addr_type, scoped, has_addr; + struct net_device *dev = NULL; + + if (addr_len < sizeof(*addr)) + return -EINVAL; + + pr_debug("ping_check_bind_addr(sk=%p,addr=%pI6c,port=%d)\n", + sk, addr->sin6_addr.s6_addr, ntohs(addr->sin6_port)); + + addr_type = ipv6_addr_type(&addr->sin6_addr); + scoped = __ipv6_addr_needs_scope_id(addr_type); + if ((addr_type != IPV6_ADDR_ANY && + !(addr_type & IPV6_ADDR_UNICAST)) || + (scoped && !addr->sin6_scope_id)) + return -EINVAL; + + rcu_read_lock(); + if (addr->sin6_scope_id) { + dev = dev_get_by_index_rcu(net, addr->sin6_scope_id); + if (!dev) { + rcu_read_unlock(); + return -ENODEV; + } + } + has_addr = pingv6_ops.ipv6_chk_addr(net, &addr->sin6_addr, dev, + scoped); + rcu_read_unlock(); + + if (!(isk->freebind || isk->transparent || has_addr || + addr_type == IPV6_ADDR_ANY)) + return -EADDRNOTAVAIL; + + if (scoped) + sk->sk_bound_dev_if = addr->sin6_scope_id; +#endif + } else { + return -EAFNOSUPPORT; + } + return 0; +} + +void ping_set_saddr(struct sock *sk, struct sockaddr *saddr) +{ + if (saddr->sa_family == AF_INET) { + struct inet_sock *isk = inet_sk(sk); + struct sockaddr_in *addr = (struct sockaddr_in *) saddr; + isk->inet_rcv_saddr = isk->inet_saddr = addr->sin_addr.s_addr; +#if IS_ENABLED(CONFIG_IPV6) + } else if (saddr->sa_family == AF_INET6) { + struct sockaddr_in6 *addr = (struct sockaddr_in6 *) saddr; + struct ipv6_pinfo *np = inet6_sk(sk); + np->rcv_saddr = np->saddr = addr->sin6_addr; +#endif + } +} + +void ping_clear_saddr(struct sock *sk, int dif) +{ + sk->sk_bound_dev_if = dif; + if (sk->sk_family == AF_INET) { + struct inet_sock *isk = inet_sk(sk); + isk->inet_rcv_saddr = isk->inet_saddr = 0; +#if IS_ENABLED(CONFIG_IPV6) + } else if (sk->sk_family == AF_INET6) { + struct ipv6_pinfo *np = inet6_sk(sk); + memset(&np->rcv_saddr, 0, sizeof(np->rcv_saddr)); + memset(&np->saddr, 0, sizeof(np->saddr)); +#endif + } +} /* * We need our own bind because there are no privileged id's == local ports. * Moreover, we don't allow binding to multi- and broadcast addresses. */ -static int ping_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) +int ping_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) { - struct sockaddr_in *addr = (struct sockaddr_in *)uaddr; struct inet_sock *isk = inet_sk(sk); unsigned short snum; - int chk_addr_ret; int err; + int dif = sk->sk_bound_dev_if; - if (addr_len < sizeof(struct sockaddr_in)) - return -EINVAL; - - pr_debug("ping_v4_bind(sk=%p,sa_addr=%08x,sa_port=%d)\n", - sk, addr->sin_addr.s_addr, ntohs(addr->sin_port)); - - chk_addr_ret = inet_addr_type(sock_net(sk), addr->sin_addr.s_addr); - if (addr->sin_addr.s_addr == htonl(INADDR_ANY)) - chk_addr_ret = RTN_LOCAL; - - if ((sysctl_ip_nonlocal_bind == 0 && - isk->freebind == 0 && isk->transparent == 0 && - chk_addr_ret != RTN_LOCAL) || - chk_addr_ret == RTN_MULTICAST || - chk_addr_ret == RTN_BROADCAST) - return -EADDRNOTAVAIL; + err = ping_check_bind_addr(sk, isk, uaddr, addr_len); + if (err) + return err; lock_sock(sk); @@ -271,42 +403,50 @@ static int ping_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) goto out; err = -EADDRINUSE; - isk->inet_rcv_saddr = isk->inet_saddr = addr->sin_addr.s_addr; - snum = ntohs(addr->sin_port); - if (ping_v4_get_port(sk, snum) != 0) { - isk->inet_saddr = isk->inet_rcv_saddr = 0; + ping_set_saddr(sk, uaddr); + snum = ntohs(((struct sockaddr_in *)uaddr)->sin_port); + if (ping_get_port(sk, snum) != 0) { + ping_clear_saddr(sk, dif); goto out; } - pr_debug("after bind(): num = %d, daddr = %pI4, dif = %d\n", + pr_debug("after bind(): num = %d, dif = %d\n", (int)isk->inet_num, - &isk->inet_rcv_saddr, (int)sk->sk_bound_dev_if); err = 0; - if (isk->inet_rcv_saddr) + if ((sk->sk_family == AF_INET && isk->inet_rcv_saddr) || + (sk->sk_family == AF_INET6 && + !ipv6_addr_any(&inet6_sk(sk)->rcv_saddr))) sk->sk_userlocks |= SOCK_BINDADDR_LOCK; + if (snum) sk->sk_userlocks |= SOCK_BINDPORT_LOCK; isk->inet_sport = htons(isk->inet_num); isk->inet_daddr = 0; isk->inet_dport = 0; + +#if IS_ENABLED(CONFIG_IPV6) + if (sk->sk_family == AF_INET6) + memset(&inet6_sk(sk)->daddr, 0, sizeof(inet6_sk(sk)->daddr)); +#endif + sk_dst_reset(sk); out: release_sock(sk); pr_debug("ping_v4_bind -> %d\n", err); return err; } +EXPORT_SYMBOL_GPL(ping_bind); /* * Is this a supported type of ICMP message? */ -static inline int ping_supported(int type, int code) +static inline int ping_supported(int family, int type, int code) { - if (type == ICMP_ECHO && code == 0) - return 1; - return 0; + return (family == AF_INET && type == ICMP_ECHO && code == 0) || + (family == AF_INET6 && type == ICMPV6_ECHO_REQUEST && code == 0); } /* @@ -314,30 +454,44 @@ static inline int ping_supported(int type, int code) * sort of error condition. */ -static int ping_queue_rcv_skb(struct sock *sk, struct sk_buff *skb); - -void ping_err(struct sk_buff *skb, u32 info) +void ping_err(struct sk_buff *skb, int offset, u32 info) { - struct iphdr *iph = (struct iphdr *)skb->data; - struct icmphdr *icmph = (struct icmphdr *)(skb->data+(iph->ihl<<2)); + int family; + struct icmphdr *icmph; struct inet_sock *inet_sock; - int type = icmph->type; - int code = icmph->code; + int type; + int code; struct net *net = dev_net(skb->dev); struct sock *sk; int harderr; int err; + if (skb->protocol == htons(ETH_P_IP)) { + struct iphdr *iph = (struct iphdr *)skb->data; + offset = iph->ihl << 2; + family = AF_INET; + type = icmp_hdr(skb)->type; + code = icmp_hdr(skb)->code; + icmph = (struct icmphdr *)(skb->data + offset); + } else if (skb->protocol == htons(ETH_P_IPV6)) { + family = AF_INET6; + type = icmp6_hdr(skb)->icmp6_type; + code = icmp6_hdr(skb)->icmp6_code; + icmph = (struct icmphdr *) (skb->data + offset); + } else { + BUG(); + } + /* We assume the packet has already been checked by icmp_unreach */ - if (!ping_supported(icmph->type, icmph->code)) + if (!ping_supported(family, icmph->type, icmph->code)) return; - pr_debug("ping_err(type=%04x,code=%04x,id=%04x,seq=%04x)\n", type, - code, ntohs(icmph->un.echo.id), ntohs(icmph->un.echo.sequence)); + pr_debug("ping_err(proto=0x%x,type=%d,code=%d,id=%04x,seq=%04x)\n", + skb->protocol, type, code, ntohs(icmph->un.echo.id), + ntohs(icmph->un.echo.sequence)); - sk = ping_v4_lookup(net, iph->daddr, iph->saddr, - ntohs(icmph->un.echo.id), skb->dev->ifindex); + sk = ping_lookup(net, skb, ntohs(icmph->un.echo.id)); if (sk == NULL) { pr_debug("no socket, dropping\n"); return; /* No socket for error */ @@ -348,70 +502,85 @@ void ping_err(struct sk_buff *skb, u32 info) harderr = 0; inet_sock = inet_sk(sk); - switch (type) { - default: - case ICMP_TIME_EXCEEDED: - err = EHOSTUNREACH; - break; - case ICMP_SOURCE_QUENCH: - /* This is not a real error but ping wants to see it. - * Report it with some fake errno. */ - err = EREMOTEIO; - break; - case ICMP_PARAMETERPROB: - err = EPROTO; - harderr = 1; - break; - case ICMP_DEST_UNREACH: - if (code == ICMP_FRAG_NEEDED) { /* Path MTU discovery */ - if (inet_sock->pmtudisc != IP_PMTUDISC_DONT) { - err = EMSGSIZE; - harderr = 1; - break; + if (skb->protocol == htons(ETH_P_IP)) { + switch (type) { + default: + case ICMP_TIME_EXCEEDED: + err = EHOSTUNREACH; + break; + case ICMP_SOURCE_QUENCH: + /* This is not a real error but ping wants to see it. + * Report it with some fake errno. */ + err = EREMOTEIO; + break; + case ICMP_PARAMETERPROB: + err = EPROTO; + harderr = 1; + break; + case ICMP_DEST_UNREACH: + if (code == ICMP_FRAG_NEEDED) { /* Path MTU discovery */ + if (inet_sock->pmtudisc != IP_PMTUDISC_DONT) { + err = EMSGSIZE; + harderr = 1; + break; + } + goto out; } - goto out; - } - err = EHOSTUNREACH; - if (code <= NR_ICMP_UNREACH) { - harderr = icmp_err_convert[code].fatal; - err = icmp_err_convert[code].errno; + err = EHOSTUNREACH; + if (code <= NR_ICMP_UNREACH) { + harderr = icmp_err_convert[code].fatal; + err = icmp_err_convert[code].errno; + } + break; + case ICMP_REDIRECT: + /* See ICMP_SOURCE_QUENCH */ + err = EREMOTEIO; + break; } - break; - case ICMP_REDIRECT: - /* See ICMP_SOURCE_QUENCH */ - err = EREMOTEIO; - break; +#if IS_ENABLED(CONFIG_IPV6) + } else if (skb->protocol == htons(ETH_P_IPV6)) { + harderr = pingv6_ops.icmpv6_err_convert(type, code, &err); +#endif } /* * RFC1122: OK. Passes ICMP errors back to application, as per * 4.1.3.3. */ - if (!inet_sock->recverr) { + if ((family == AF_INET && !inet_sock->recverr) || + (family == AF_INET6 && !inet6_sk(sk)->recverr)) { if (!harderr || sk->sk_state != TCP_ESTABLISHED) goto out; } else { - ip_icmp_error(sk, skb, err, 0 /* no remote port */, - info, (u8 *)icmph); + if (family == AF_INET) { + ip_icmp_error(sk, skb, err, 0 /* no remote port */, + info, (u8 *)icmph); +#if IS_ENABLED(CONFIG_IPV6) + } else if (family == AF_INET6) { + pingv6_ops.ipv6_icmp_error(sk, skb, err, 0, + info, (u8 *)icmph); +#endif + } } sk->sk_err = err; sk->sk_error_report(sk); out: sock_put(sk); } +EXPORT_SYMBOL_GPL(ping_err); + +void ping_v4_err(struct sk_buff *skb, u32 info) +{ + ping_err(skb, 0, info); +} /* - * Copy and checksum an ICMP Echo packet from user space into a buffer. + * Copy and checksum an ICMP Echo packet from user space into a buffer + * starting from the payload. */ -struct pingfakehdr { - struct icmphdr icmph; - struct iovec *iov; - __wsum wcheck; -}; - -static int ping_getfrag(void *from, char * to, - int offset, int fraglen, int odd, struct sk_buff *skb) +int ping_getfrag(void *from, char *to, + int offset, int fraglen, int odd, struct sk_buff *skb) { struct pingfakehdr *pfh = (struct pingfakehdr *)from; @@ -422,20 +591,33 @@ static int ping_getfrag(void *from, char * to, pfh->iov, 0, fraglen - sizeof(struct icmphdr), &pfh->wcheck)) return -EFAULT; + } else if (offset < sizeof(struct icmphdr)) { + BUG(); + } else { + if (csum_partial_copy_fromiovecend + (to, pfh->iov, offset - sizeof(struct icmphdr), + fraglen, &pfh->wcheck)) + return -EFAULT; + } - return 0; +#if IS_ENABLED(CONFIG_IPV6) + /* For IPv6, checksum each skb as we go along, as expected by + * icmpv6_push_pending_frames. For IPv4, accumulate the checksum in + * wcheck, it will be finalized in ping_v4_push_pending_frames. + */ + if (pfh->family == AF_INET6) { + skb->csum = pfh->wcheck; + skb->ip_summed = CHECKSUM_NONE; + pfh->wcheck = 0; } - if (offset < sizeof(struct icmphdr)) - BUG(); - if (csum_partial_copy_fromiovecend - (to, pfh->iov, offset - sizeof(struct icmphdr), - fraglen, &pfh->wcheck)) - return -EFAULT; +#endif + return 0; } +EXPORT_SYMBOL_GPL(ping_getfrag); -static int ping_push_pending_frames(struct sock *sk, struct pingfakehdr *pfh, - struct flowi4 *fl4) +static int ping_v4_push_pending_frames(struct sock *sk, struct pingfakehdr *pfh, + struct flowi4 *fl4) { struct sk_buff *skb = skb_peek(&sk->sk_write_queue); @@ -447,24 +629,9 @@ static int ping_push_pending_frames(struct sock *sk, struct pingfakehdr *pfh, return ip_push_pending_frames(sk, fl4); } -static int ping_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, - size_t len) -{ - struct net *net = sock_net(sk); - struct flowi4 fl4; - struct inet_sock *inet = inet_sk(sk); - struct ipcm_cookie ipc; - struct icmphdr user_icmph; - struct pingfakehdr pfh; - struct rtable *rt = NULL; - struct ip_options_data opt_copy; - int free = 0; - __be32 saddr, daddr, faddr; - u8 tos; - int err; - - pr_debug("ping_sendmsg(sk=%p,sk->num=%u)\n", inet, inet->inet_num); - +int ping_common_sendmsg(int family, struct msghdr *msg, size_t len, + void *user_icmph, size_t icmph_len) { + u8 type, code; if (len > 0xFFFF) return -EMSGSIZE; @@ -479,15 +646,53 @@ static int ping_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, /* * Fetch the ICMP header provided by the userland. - * iovec is modified! + * iovec is modified! The ICMP header is consumed. */ - - if (memcpy_fromiovec((u8 *)&user_icmph, msg->msg_iov, - sizeof(struct icmphdr))) + if (memcpy_fromiovec(user_icmph, msg->msg_iov, icmph_len)) return -EFAULT; - if (!ping_supported(user_icmph.type, user_icmph.code)) + + if (family == AF_INET) { + type = ((struct icmphdr *) user_icmph)->type; + code = ((struct icmphdr *) user_icmph)->code; +#if IS_ENABLED(CONFIG_IPV6) + } else if (family == AF_INET6) { + type = ((struct icmp6hdr *) user_icmph)->icmp6_type; + code = ((struct icmp6hdr *) user_icmph)->icmp6_code; +#endif + } else { + BUG(); + } + + if (!ping_supported(family, type, code)) return -EINVAL; + return 0; +} +EXPORT_SYMBOL_GPL(ping_common_sendmsg); + +int ping_v4_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + size_t len) +{ + struct net *net = sock_net(sk); + struct flowi4 fl4; + struct inet_sock *inet = inet_sk(sk); + struct ipcm_cookie ipc; + struct icmphdr user_icmph; + struct pingfakehdr pfh; + struct rtable *rt = NULL; + struct ip_options_data opt_copy; + int free = 0; + __be32 saddr, daddr, faddr; + u8 tos; + int err; + + pr_debug("ping_v4_sendmsg(sk=%p,sk->num=%u)\n", inet, inet->inet_num); + + err = ping_common_sendmsg(AF_INET, msg, len, &user_icmph, + sizeof(user_icmph)); + if (err) + return err; + /* * Get and verify the address. */ @@ -593,13 +798,14 @@ static int ping_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, pfh.icmph.un.echo.sequence = user_icmph.un.echo.sequence; pfh.iov = msg->msg_iov; pfh.wcheck = 0; + pfh.family = AF_INET; err = ip_append_data(sk, &fl4, ping_getfrag, &pfh, len, 0, &ipc, &rt, msg->msg_flags); if (err) ip_flush_pending_frames(sk); else - err = ping_push_pending_frames(sk, &pfh, &fl4); + err = ping_v4_push_pending_frames(sk, &pfh, &fl4); release_sock(sk); out: @@ -620,11 +826,13 @@ static int ping_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, goto out; } -static int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, - size_t len, int noblock, int flags, int *addr_len) +int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + size_t len, int noblock, int flags, int *addr_len) { struct inet_sock *isk = inet_sk(sk); - struct sockaddr_in *sin = (struct sockaddr_in *)msg->msg_name; + int family = sk->sk_family; + struct sockaddr_in *sin; + struct sockaddr_in6 *sin6; struct sk_buff *skb; int copied, err; @@ -634,11 +842,22 @@ static int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, if (flags & MSG_OOB) goto out; - if (addr_len) - *addr_len = sizeof(*sin); + if (addr_len) { + if (family == AF_INET) + *addr_len = sizeof(*sin); + else if (family == AF_INET6 && addr_len) + *addr_len = sizeof(*sin6); + } - if (flags & MSG_ERRQUEUE) - return ip_recv_error(sk, msg, len); + if (flags & MSG_ERRQUEUE) { + if (family == AF_INET) { + return ip_recv_error(sk, msg, len); +#if IS_ENABLED(CONFIG_IPV6) + } else if (family == AF_INET6) { + return pingv6_ops.ipv6_recv_error(sk, msg, len); +#endif + } + } skb = skb_recv_datagram(sk, flags, noblock, &err); if (!skb) @@ -657,15 +876,41 @@ static int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, sock_recv_timestamp(msg, sk, skb); - /* Copy the address. */ - if (sin) { + /* Copy the address and add cmsg data. */ + if (family == AF_INET) { + sin = (struct sockaddr_in *) msg->msg_name; sin->sin_family = AF_INET; sin->sin_port = 0 /* skb->h.uh->source */; sin->sin_addr.s_addr = ip_hdr(skb)->saddr; memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); + + if (isk->cmsg_flags) + ip_cmsg_recv(msg, skb); + +#if IS_ENABLED(CONFIG_IPV6) + } else if (family == AF_INET6) { + struct ipv6_pinfo *np = inet6_sk(sk); + struct ipv6hdr *ip6 = ipv6_hdr(skb); + sin6 = (struct sockaddr_in6 *) msg->msg_name; + sin6->sin6_family = AF_INET6; + sin6->sin6_port = 0; + sin6->sin6_addr = ip6->saddr; + + sin6->sin6_flowinfo = 0; + if (np->sndflow) + sin6->sin6_flowinfo = + *(__be32 *)ip6 & IPV6_FLOWINFO_MASK; + + sin6->sin6_scope_id = ipv6_iface_scope_id(&sin6->sin6_addr, + IP6CB(skb)->iif); + + if (inet6_sk(sk)->rxopt.all) + pingv6_ops.datagram_recv_ctl(sk, msg, skb); +#endif + } else { + BUG(); } - if (isk->cmsg_flags) - ip_cmsg_recv(msg, skb); + err = copied; done: @@ -674,8 +919,9 @@ static int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, pr_debug("ping_recvmsg -> %d\n", err); return err; } +EXPORT_SYMBOL_GPL(ping_recvmsg); -static int ping_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) +int ping_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) { pr_debug("ping_queue_rcv_skb(sk=%p,sk->num=%d,skb=%p)\n", inet_sk(sk), inet_sk(sk)->inet_num, skb); @@ -686,6 +932,7 @@ static int ping_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) } return 0; } +EXPORT_SYMBOL_GPL(ping_queue_rcv_skb); /* @@ -696,10 +943,7 @@ void ping_rcv(struct sk_buff *skb) { struct sock *sk; struct net *net = dev_net(skb->dev); - struct iphdr *iph = ip_hdr(skb); struct icmphdr *icmph = icmp_hdr(skb); - __be32 saddr = iph->saddr; - __be32 daddr = iph->daddr; /* We assume the packet has already been checked by icmp_rcv */ @@ -709,8 +953,7 @@ void ping_rcv(struct sk_buff *skb) /* Push ICMP header back */ skb_push(skb, skb->data - (u8 *)icmph); - sk = ping_v4_lookup(net, saddr, daddr, ntohs(icmph->un.echo.id), - skb->dev->ifindex); + sk = ping_lookup(net, skb, ntohs(icmph->un.echo.id)); if (sk != NULL) { pr_debug("rcv on socket %p\n", sk); ping_queue_rcv_skb(sk, skb_get(skb)); @@ -721,6 +964,7 @@ void ping_rcv(struct sk_buff *skb) /* We're called from icmp_rcv(). kfree_skb() is done there. */ } +EXPORT_SYMBOL_GPL(ping_rcv); struct proto ping_prot = { .name = "PING", @@ -731,13 +975,13 @@ struct proto ping_prot = { .disconnect = udp_disconnect, .setsockopt = ip_setsockopt, .getsockopt = ip_getsockopt, - .sendmsg = ping_sendmsg, + .sendmsg = ping_v4_sendmsg, .recvmsg = ping_recvmsg, .bind = ping_bind, .backlog_rcv = ping_queue_rcv_skb, - .hash = ping_v4_hash, - .unhash = ping_v4_unhash, - .get_port = ping_v4_get_port, + .hash = ping_hash, + .unhash = ping_unhash, + .get_port = ping_get_port, .obj_size = sizeof(struct inet_sock), }; EXPORT_SYMBOL(ping_prot); diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile index 686934acfac..753be5dd409 100644 --- a/net/ipv6/Makefile +++ b/net/ipv6/Makefile @@ -7,7 +7,7 @@ obj-$(CONFIG_IPV6) += ipv6.o ipv6-objs := af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o \ addrlabel.o \ route.o ip6_fib.o ipv6_sockglue.o ndisc.o udp.o udplite.o \ - raw.o protocol.o icmp.o mcast.o reassembly.o tcp_ipv6.o \ + raw.o protocol.o icmp.o mcast.o reassembly.o tcp_ipv6.o ping.o \ exthdrs.o datagram.o ip6_flowlabel.o inet6_connection_sock.o ipv6-$(CONFIG_SYSCTL) = sysctl_net_ipv6.o diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 29625e9a51a..22ebbb97283 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -49,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -1130,6 +1131,9 @@ static int __init inet6_init(void) if (err) goto out_unregister_udplite_proto; + err = proto_register(&pingv6_prot, 1); + if (err) + goto out_unregister_ping_proto; /* We MUST register RAW sockets before we create the ICMP6, * IGMP6, or NDISC control sockets. @@ -1225,6 +1229,10 @@ static int __init inet6_init(void) if (err) goto ipv6_packet_fail; + err = pingv6_init(); + if (err) + goto pingv6_fail; + #ifdef CONFIG_SYSCTL err = ipv6_sysctl_register(); if (err) @@ -1237,6 +1245,8 @@ static int __init inet6_init(void) sysctl_fail: ipv6_packet_cleanup(); #endif +pingv6_fail: + pingv6_exit(); ipv6_packet_fail: tcpv6_exit(); tcpv6_fail: @@ -1284,6 +1294,8 @@ static int __init inet6_init(void) rtnl_unregister_all(PF_INET6); out_sock_register_fail: rawv6_exit(); +out_unregister_ping_proto: + proto_unregister(&pingv6_prot); out_unregister_raw_proto: proto_unregister(&rawv6_prot); out_unregister_udplite_proto: diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 27ac95a6342..ba0c1479ba0 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -55,6 +55,7 @@ #include #include +#include #include #include #include @@ -79,10 +80,22 @@ static inline struct sock *icmpv6_sk(struct net *net) return net->ipv6.icmp_sk[smp_processor_id()]; } +static void icmpv6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, + u8 type, u8 code, int offset, __be32 info) +{ + /* icmpv6_notify checks 8 bytes can be pulled, icmp6hdr is 8 bytes */ + struct icmp6hdr *icmp6 = (struct icmp6hdr *) (skb->data + offset); + + if (!(type & ICMPV6_INFOMSG_MASK)) + if (icmp6->icmp6_type == ICMPV6_ECHO_REQUEST) + ping_err(skb, offset, info); +} + static int icmpv6_rcv(struct sk_buff *skb); static const struct inet6_protocol icmpv6_protocol = { .handler = icmpv6_rcv, + .err_handler = icmpv6_err, .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, }; @@ -217,7 +230,8 @@ static __inline__ int opt_unrec(struct sk_buff *skb, __u32 offset) return (*op & 0xC0) == 0x80; } -static int icmpv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6, struct icmp6hdr *thdr, int len) +int icmpv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6, + struct icmp6hdr *thdr, int len) { struct sk_buff *skb; struct icmp6hdr *icmp6h; @@ -300,8 +314,8 @@ static void mip6_addr_swap(struct sk_buff *skb) static inline void mip6_addr_swap(struct sk_buff *skb) {} #endif -static struct dst_entry *icmpv6_route_lookup(struct net *net, struct sk_buff *skb, - struct sock *sk, struct flowi6 *fl6) +struct dst_entry *icmpv6_route_lookup(struct net *net, struct sk_buff *skb, + struct sock *sk, struct flowi6 *fl6) { struct dst_entry *dst, *dst2; struct flowi6 fl2; @@ -594,7 +608,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb) icmpv6_xmit_unlock(sk); } -static void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info) +void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info) { const struct inet6_protocol *ipprot; int inner_offset; @@ -687,7 +701,8 @@ static int icmpv6_rcv(struct sk_buff *skb) skb->csum = ~csum_unfold(csum_ipv6_magic(saddr, daddr, skb->len, IPPROTO_ICMPV6, 0)); if (__skb_checksum_complete(skb)) { - LIMIT_NETDEBUG(KERN_DEBUG "ICMPv6 checksum failed [%pI6 > %pI6]\n", + LIMIT_NETDEBUG(KERN_DEBUG + "ICMPv6 checksum failed [%pI6c > %pI6c]\n", saddr, daddr); goto discard_it; } @@ -708,7 +723,7 @@ static int icmpv6_rcv(struct sk_buff *skb) break; case ICMPV6_ECHO_REPLY: - /* we couldn't care less */ + ping_rcv(skb); break; case ICMPV6_PKT_TOOBIG: diff --git a/net/ipv6/ping.c b/net/ipv6/ping.c new file mode 100644 index 00000000000..cfb1b5de810 --- /dev/null +++ b/net/ipv6/ping.c @@ -0,0 +1,222 @@ +/* + * INET An implementation of the TCP/IP protocol suite for the LINUX + * operating system. INET is implemented using the BSD Socket + * interface as the means of communication with the user level. + * + * "Ping" sockets + * + * 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. + * + * Based on ipv4/ping.c code. + * + * Authors: Lorenzo Colitti (IPv6 support) + * Vasiliy Kulikov / Openwall (IPv4 implementation, for Linux 2.6), + * Pavel Kankovsky (IPv4 implementation, for Linux 2.4.32) + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +struct proto pingv6_prot = { + .name = "PINGv6", + .owner = THIS_MODULE, + .init = ping_init_sock, + .close = ping_close, + .connect = ip6_datagram_connect, + .disconnect = udp_disconnect, + .setsockopt = ipv6_setsockopt, + .getsockopt = ipv6_getsockopt, + .sendmsg = ping_v6_sendmsg, + .recvmsg = ping_recvmsg, + .bind = ping_bind, + .backlog_rcv = ping_queue_rcv_skb, + .hash = ping_hash, + .unhash = ping_unhash, + .get_port = ping_get_port, + .obj_size = sizeof(struct raw6_sock), +}; +EXPORT_SYMBOL_GPL(pingv6_prot); + +static struct inet_protosw pingv6_protosw = { + .type = SOCK_DGRAM, + .protocol = IPPROTO_ICMPV6, + .prot = &pingv6_prot, + .ops = &inet6_dgram_ops, + .no_check = UDP_CSUM_DEFAULT, + .flags = INET_PROTOSW_REUSE, +}; + + +/* Compatibility glue so we can support IPv6 when it's compiled as a module */ +int dummy_ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len) +{ + return -EAFNOSUPPORT; +} +int dummy_datagram_recv_ctl(struct sock *sk, struct msghdr *msg, + struct sk_buff *skb) +{ + return -EAFNOSUPPORT; +} +int dummy_icmpv6_err_convert(u8 type, u8 code, int *err) +{ + return -EAFNOSUPPORT; +} +void dummy_ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err, + __be16 port, u32 info, u8 *payload) {} +int dummy_ipv6_chk_addr(struct net *net, const struct in6_addr *addr, + struct net_device *dev, int strict) +{ + return 0; +} + +int __init pingv6_init(void) +{ + pingv6_ops.ipv6_recv_error = ipv6_recv_error; + pingv6_ops.datagram_recv_ctl = datagram_recv_ctl; + pingv6_ops.icmpv6_err_convert = icmpv6_err_convert; + pingv6_ops.ipv6_icmp_error = ipv6_icmp_error; + pingv6_ops.ipv6_chk_addr = ipv6_chk_addr; + return inet6_register_protosw(&pingv6_protosw); +} + +/* This never gets called because it's not possible to unload the ipv6 module, + * but just in case. + */ +void pingv6_exit(void) +{ + pingv6_ops.ipv6_recv_error = dummy_ipv6_recv_error; + pingv6_ops.datagram_recv_ctl = dummy_datagram_recv_ctl; + pingv6_ops.icmpv6_err_convert = dummy_icmpv6_err_convert; + pingv6_ops.ipv6_icmp_error = dummy_ipv6_icmp_error; + pingv6_ops.ipv6_chk_addr = dummy_ipv6_chk_addr; + inet6_unregister_protosw(&pingv6_protosw); +} + +int ping_v6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + size_t len) +{ + struct inet_sock *inet = inet_sk(sk); + struct ipv6_pinfo *np = inet6_sk(sk); + struct icmp6hdr user_icmph; + int addr_type; + struct in6_addr *daddr; + int iif = 0; + struct flowi6 fl6; + int err; + int hlimit; + struct dst_entry *dst; + struct rt6_info *rt; + struct pingfakehdr pfh; + + pr_debug("ping_v6_sendmsg(sk=%p,sk->num=%u)\n", inet, inet->inet_num); + + err = ping_common_sendmsg(AF_INET6, msg, len, &user_icmph, + sizeof(user_icmph)); + if (err) + return err; + + if (msg->msg_name) { + struct sockaddr_in6 *u = (struct sockaddr_in6 *) msg->msg_name; + if (msg->msg_namelen < sizeof(struct sockaddr_in6) || + u->sin6_family != AF_INET6) { + return -EINVAL; + } + if (sk->sk_bound_dev_if && + sk->sk_bound_dev_if != u->sin6_scope_id) { + return -EINVAL; + } + daddr = &(u->sin6_addr); + iif = u->sin6_scope_id; + } else { + if (sk->sk_state != TCP_ESTABLISHED) + return -EDESTADDRREQ; + daddr = &np->daddr; + } + + if (!iif) + iif = sk->sk_bound_dev_if; + + addr_type = ipv6_addr_type(daddr); + if (__ipv6_addr_needs_scope_id(addr_type) && !iif) + return -EINVAL; + if (addr_type & IPV6_ADDR_MAPPED) + return -EINVAL; + + /* TODO: use ip6_datagram_send_ctl to get options from cmsg */ + + memset(&fl6, 0, sizeof(fl6)); + + fl6.flowi6_proto = IPPROTO_ICMPV6; + fl6.saddr = np->saddr; + fl6.daddr = *daddr; + fl6.fl6_icmp_type = user_icmph.icmp6_type; + fl6.fl6_icmp_code = user_icmph.icmp6_code; + security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); + + if (!fl6.flowi6_oif && ipv6_addr_is_multicast(&fl6.daddr)) + fl6.flowi6_oif = np->mcast_oif; + else if (!fl6.flowi6_oif) + fl6.flowi6_oif = np->ucast_oif; + + dst = ip6_sk_dst_lookup_flow(sk, &fl6, daddr, 1); + if (IS_ERR(dst)) + return PTR_ERR(dst); + rt = (struct rt6_info *) dst; + + np = inet6_sk(sk); + if (!np) + return -EBADF; + + if (!fl6.flowi6_oif && ipv6_addr_is_multicast(&fl6.daddr)) + fl6.flowi6_oif = np->mcast_oif; + else if (!fl6.flowi6_oif) + fl6.flowi6_oif = np->ucast_oif; + + pfh.icmph.type = user_icmph.icmp6_type; + pfh.icmph.code = user_icmph.icmp6_code; + pfh.icmph.checksum = 0; + pfh.icmph.un.echo.id = inet->inet_sport; + pfh.icmph.un.echo.sequence = user_icmph.icmp6_sequence; + pfh.iov = msg->msg_iov; + pfh.wcheck = 0; + pfh.family = AF_INET6; + + if (ipv6_addr_is_multicast(&fl6.daddr)) + hlimit = np->mcast_hops; + else + hlimit = np->hop_limit; + if (hlimit < 0) + hlimit = ip6_dst_hoplimit(dst); + + lock_sock(sk); + err = ip6_append_data(sk, ping_getfrag, &pfh, len, + 0, hlimit, + np->tclass, NULL, &fl6, rt, + MSG_DONTWAIT, np->dontfrag); + + if (err) { + ICMP6_INC_STATS_BH(sock_net(sk), rt->rt6i_idev, + ICMP6_MIB_OUTERRORS); + ip6_flush_pending_frames(sk); + } else { + err = icmpv6_push_pending_frames(sk, &fl6, + (struct icmp6hdr *) &pfh.icmph, + len); + } + release_sock(sk); + + if (err) + return err; + + return len; +} diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 677d6592978..685553b412b 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -984,9 +984,11 @@ static int ieee80211_change_station(struct wiphy *wiphy, return -ENOENT; } - /* in station mode, supported rates are only valid with TDLS */ + /* in station mode, some updates are only valid with TDLS */ if (sdata->vif.type == NL80211_IFTYPE_STATION && - params->supported_rates && + (params->supported_rates || params->ht_capa || params->vht_capa || + params->sta_modify_mask || + (params->sta_flags_mask & BIT(NL80211_STA_FLAG_WME))) && !test_sta_flag(sta, WLAN_STA_TDLS_PEER)) { mutex_unlock(&local->sta_mtx); return -EINVAL; diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index db8fae51714..a99a71517c4 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -378,6 +378,7 @@ enum ieee80211_sta_flags { IEEE80211_STA_UAPSD_ENABLED = BIT(7), IEEE80211_STA_NULLFUNC_ACKED = BIT(8), IEEE80211_STA_RESET_SIGNAL_AVE = BIT(9), + IEEE80211_STA_DISABLE_VHT = BIT(11), }; struct ieee80211_mgd_auth_data { @@ -1475,6 +1476,8 @@ u8 *ieee80211_ie_build_ht_info(u8 *pos, struct ieee80211_channel *channel, enum nl80211_channel_type channel_type); +u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap, + u32 cap); /* internal work items */ void ieee80211_work_init(struct ieee80211_local *local); void ieee80211_add_work(struct ieee80211_work *wk); diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 16336480c63..018e3fbc2c2 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -673,7 +673,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) int result, i; enum ieee80211_band band; int channels, max_bitrates; - bool supp_ht; + bool supp_ht, supp_vht; static const u32 cipher_suites[] = { /* keep WEP first, it may be removed below */ WLAN_CIPHER_SUITE_WEP40, @@ -706,6 +706,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) channels = 0; max_bitrates = 0; supp_ht = false; + supp_vht = false; for (band = 0; band < IEEE80211_NUM_BANDS; band++) { struct ieee80211_supported_band *sband; @@ -723,6 +724,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) if (max_bitrates < sband->n_bitrates) max_bitrates = sband->n_bitrates; supp_ht = supp_ht || sband->ht_cap.ht_supported; + supp_vht = supp_vht || sband->vht_cap.vht_supported; } local->int_scan_req = kzalloc(sizeof(*local->int_scan_req) + @@ -798,6 +800,10 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) if (supp_ht) local->scan_ies_len += 2 + sizeof(struct ieee80211_ht_cap); + if (supp_vht) + local->scan_ies_len += + 2 + sizeof(struct ieee80211_vht_cap); + if (!local->ops->hw_scan) { /* For hw_scan, driver needs to set these up. */ local->hw.wiphy->max_scan_ssids = 4; diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 20c680bfc3a..a48a35c7ce6 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -383,6 +383,26 @@ static void ieee80211_add_ht_ie(struct ieee80211_sub_if_data *sdata, ieee80211_ie_build_ht_cap(pos, &ht_cap, cap); } +static void ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata, + struct sk_buff *skb, + struct ieee80211_supported_band *sband) +{ + u8 *pos; + u32 cap; + struct ieee80211_sta_vht_cap vht_cap; + + BUILD_BUG_ON(sizeof(vht_cap) != sizeof(sband->vht_cap)); + + memcpy(&vht_cap, &sband->vht_cap, sizeof(vht_cap)); + + /* determine capability flags */ + cap = vht_cap.cap; + + /* reserve and fill IE */ + pos = skb_put(skb, sizeof(struct ieee80211_vht_cap) + 2); + ieee80211_ie_build_vht_cap(pos, &vht_cap, cap); +} + static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) { struct ieee80211_local *local = sdata->local; @@ -428,6 +448,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) 4 + /* power capability */ 2 + 2 * sband->n_channels + /* supported channels */ 2 + sizeof(struct ieee80211_ht_cap) + /* HT */ + 2 + sizeof(struct ieee80211_vht_cap) + /* VHT */ assoc_data->ie_len + /* extra IEs */ 9, /* WMM */ GFP_KERNEL); @@ -560,6 +581,9 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) ieee80211_add_ht_ie(sdata, skb, assoc_data->ht_information_ie, sband, local->oper_channel, ifmgd->ap_smps); + if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) + ieee80211_add_vht_ie(sdata, skb, sband); + /* if present, add any custom non-vendor IEs that go after HT */ if (assoc_data->ie_len && assoc_data->ie) { noffset = ieee80211_ie_split_vendor(assoc_data->ie, @@ -3289,6 +3313,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, ifmgd->flags &= ~IEEE80211_STA_DISABLE_11N; ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED; + ifmgd->flags &= ~IEEE80211_STA_DISABLE_VHT; ifmgd->beacon_crc_valid = false; @@ -3299,14 +3324,21 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, * We can set this to true for non-11n hardware, that'll be checked * separately along with the peer capabilities. */ - for (i = 0; i < req->crypto.n_ciphers_pairwise; i++) + for (i = 0; i < req->crypto.n_ciphers_pairwise; i++) { if (req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP40 || req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_TKIP || - req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP104) + req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP104) { ifmgd->flags |= IEEE80211_STA_DISABLE_11N; + ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; + netdev_info(sdata->dev, + "disabling HT/VHT due to WEP/TKIP use\n"); + } + } - if (req->flags & ASSOC_REQ_DISABLE_HT) + if (req->flags & ASSOC_REQ_DISABLE_HT) { ifmgd->flags |= IEEE80211_STA_DISABLE_11N; + ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; + } /* Also disable HT if we don't support it or the AP doesn't use WMM */ sband = local->hw.wiphy->bands[req->bss->channel->band]; @@ -3314,6 +3346,14 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, local->hw.queues < 4 || !bss->wmm_used) ifmgd->flags |= IEEE80211_STA_DISABLE_11N; + /* disable VHT if we don't support it or the AP doesn't use WMM */ + if (!sband->vht_cap.vht_supported || + local->hw.queues < IEEE80211_NUM_ACS || !bss->wmm_used) { + ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; + netdev_info(sdata->dev, + "disabling VHT as WMM/QoS is not supported\n"); + } + memcpy(&ifmgd->ht_capa, &req->ht_capa, sizeof(ifmgd->ht_capa)); memcpy(&ifmgd->ht_capa_mask, &req->ht_capa_mask, sizeof(ifmgd->ht_capa_mask)); diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 32f7a3b3d43..1faea9dce64 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -1031,6 +1031,9 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, pos += noffset - offset; } + if (sband->vht_cap.vht_supported) + pos = ieee80211_ie_build_vht_cap(pos, &sband->vht_cap, + sband->vht_cap.cap); return pos - buffer; } @@ -1611,6 +1614,27 @@ u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, return pos; } +u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap, + u32 cap) +{ + __le32 tmp; + + *pos++ = WLAN_EID_VHT_CAPABILITY; + *pos++ = sizeof(struct ieee80211_vht_cap); + memset(pos, 0, sizeof(struct ieee80211_vht_cap)); + + /* capability flags */ + tmp = cpu_to_le32(cap); + memcpy(pos, &tmp, sizeof(u32)); + pos += sizeof(u32); + + /* VHT MCS set */ + memcpy(pos, &vht_cap->vht_mcs, sizeof(vht_cap->vht_mcs)); + pos += sizeof(vht_cap->vht_mcs); + + return pos; +} + u8 *ieee80211_ie_build_ht_info(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, struct ieee80211_channel *channel, diff --git a/net/netfilter/xt_qtaguid.c b/net/netfilter/xt_qtaguid.c index 5bdb42bd28d..88c61bdf1d2 100644 --- a/net/netfilter/xt_qtaguid.c +++ b/net/netfilter/xt_qtaguid.c @@ -1468,6 +1468,8 @@ static void if_tag_stat_update(const char *ifname, uid_t uid, * - No {0, uid_tag} stats and no {acc_tag, uid_tag} stats. */ new_tag_stat = create_if_tag_stat(iface_entry, uid_tag); + if (!new_tag_stat) + goto unlock; uid_tag_counters = &new_tag_stat->counters; } else { uid_tag_counters = &tag_stat_entry->counters; @@ -1476,6 +1478,8 @@ static void if_tag_stat_update(const char *ifname, uid_t uid, if (acct_tag) { /* Create the child {acct_tag, uid_tag} and hook up parent. */ new_tag_stat = create_if_tag_stat(iface_entry, tag); + if (!new_tag_stat) + goto unlock; new_tag_stat->parent_counters = uid_tag_counters; } else { /* @@ -1489,6 +1493,7 @@ static void if_tag_stat_update(const char *ifname, uid_t uid, BUG_ON(!new_tag_stat); } tag_stat_update(new_tag_stat, direction, proto, bytes); +unlock: spin_unlock_bh(&iface_entry->tag_stat_list_lock); } @@ -2596,8 +2601,9 @@ static int pp_stats_line(struct proc_print_info *ppi, int cnt_set) } else { tag_t tag = ppi->ts_entry->tn.tag; uid_t stat_uid = get_uid_from_tag(tag); - - if (!can_read_other_uid_stats(stat_uid)) { + /* Detailed tags are not available to everybody */ + if (get_atag_from_tag(tag) + && !can_read_other_uid_stats(stat_uid)) { CT_DEBUG("qtaguid: stats line: " "%s 0x%llx %u: insufficient priv " "from pid=%u tgid=%u uid=%u stats.gid=%u\n", @@ -2760,7 +2766,7 @@ static int qtudev_open(struct inode *inode, struct file *file) utd_entry = get_uid_data(current_fsuid(), &utd_entry_found); if (IS_ERR_OR_NULL(utd_entry)) { res = PTR_ERR(utd_entry); - goto err; + goto err_unlock; } /* Look for existing PID based proc_data */ @@ -2802,8 +2808,8 @@ static int qtudev_open(struct inode *inode, struct file *file) rb_erase(&utd_entry->node, &uid_tag_data_tree); kfree(utd_entry); } +err_unlock: spin_unlock_bh(&uid_tag_data_tree_lock); -err: return res; } diff --git a/net/wireless/core.c b/net/wireless/core.c index ccdfed89765..674c1fa2bd6 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -505,6 +505,11 @@ int wiphy_register(struct wiphy *wiphy) ETH_ALEN))) return -EINVAL; + if (WARN_ON(wiphy->max_acl_mac_addrs && + (!(wiphy->flags & WIPHY_FLAG_HAVE_AP_SME) || + !rdev->ops->set_mac_acl))) + return -EINVAL; + if (wiphy->addresses) memcpy(wiphy->perm_addr, wiphy->addresses[0].addr, ETH_ALEN); diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 4df009cd5ff..13fcc641e13 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -206,6 +206,26 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { [NL80211_ATTR_NOACK_MAP] = { .type = NLA_U16 }, [NL80211_ATTR_INACTIVITY_TIMEOUT] = { .type = NLA_U16 }, [NL80211_ATTR_BG_SCAN_PERIOD] = { .type = NLA_U16 }, + [NL80211_ATTR_WDEV] = { .type = NLA_U64 }, + [NL80211_ATTR_USER_REG_HINT_TYPE] = { .type = NLA_U32 }, + [NL80211_ATTR_SAE_DATA] = { .type = NLA_BINARY, }, + [NL80211_ATTR_VHT_CAPABILITY] = { .len = NL80211_VHT_CAPABILITY_LEN }, + [NL80211_ATTR_SCAN_FLAGS] = { .type = NLA_U32 }, + [NL80211_ATTR_P2P_CTWINDOW] = { .type = NLA_U8 }, + [NL80211_ATTR_P2P_OPPPS] = { .type = NLA_U8 }, + [NL80211_ATTR_ACL_POLICY] = {. type = NLA_U32 }, + [NL80211_ATTR_MAC_ADDRS] = { .type = NLA_NESTED }, + [NL80211_ATTR_STA_CAPABILITY] = { .type = NLA_U16 }, + [NL80211_ATTR_STA_EXT_CAPABILITY] = { .type = NLA_BINARY, }, + [NL80211_ATTR_SPLIT_WIPHY_DUMP] = { .type = NLA_FLAG, }, + [NL80211_ATTR_DISABLE_VHT] = { .type = NLA_FLAG }, + [NL80211_ATTR_VHT_CAPABILITY_MASK] = { + .len = NL80211_VHT_CAPABILITY_LEN, + }, + [NL80211_ATTR_MDID] = { .type = NLA_U16 }, + [NL80211_ATTR_IE_RIC] = { .type = NLA_BINARY, + .len = IEEE80211_MAX_DATA_LEN }, + [NL80211_ATTR_PEER_AID] = { .type = NLA_U16 }, }; /* policy for the key attributes */ @@ -811,6 +831,15 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, dev->wiphy.bands[band]->ht_cap.ampdu_density); } + /* add VHT info */ + if (dev->wiphy.bands[band]->vht_cap.vht_supported && + (nla_put(msg, NL80211_BAND_ATTR_VHT_MCS_SET, + sizeof(dev->wiphy.bands[band]->vht_cap.vht_mcs), + &dev->wiphy.bands[band]->vht_cap.vht_mcs) || + nla_put_u32(msg, NL80211_BAND_ATTR_VHT_CAPA, + dev->wiphy.bands[band]->vht_cap.cap))) + goto nla_put_failure; + /* add frequencies */ nl_freqs = nla_nest_start(msg, NL80211_BAND_ATTR_FREQS); if (!nl_freqs) @@ -1043,6 +1072,11 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, sizeof(*dev->wiphy.ht_capa_mod_mask), dev->wiphy.ht_capa_mod_mask); + if (dev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME && + dev->wiphy.max_acl_mac_addrs) + NLA_PUT_U32(msg, NL80211_ATTR_MAC_ACL_MAX, + dev->wiphy.max_acl_mac_addrs); + return genlmsg_end(msg, hdr); nla_put_failure: @@ -2082,6 +2116,97 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info) return err; } +/* This function returns an error or the number of nested attributes */ +static int validate_acl_mac_addrs(struct nlattr *nl_attr) +{ + struct nlattr *attr; + int n_entries = 0, tmp; + + nla_for_each_nested(attr, nl_attr, tmp) { + if (nla_len(attr) != ETH_ALEN) + return -EINVAL; + + n_entries++; + } + + return n_entries; +} + +/* + * This function parses ACL information and allocates memory for ACL data. + * On successful return, the calling function is responsible to free the + * ACL buffer returned by this function. + */ +static struct cfg80211_acl_data *parse_acl_data(struct wiphy *wiphy, + struct genl_info *info) +{ + enum nl80211_acl_policy acl_policy; + struct nlattr *attr; + struct cfg80211_acl_data *acl; + int i = 0, n_entries, tmp; + + if (!wiphy->max_acl_mac_addrs) + return ERR_PTR(-EOPNOTSUPP); + + if (!info->attrs[NL80211_ATTR_ACL_POLICY]) + return ERR_PTR(-EINVAL); + + acl_policy = nla_get_u32(info->attrs[NL80211_ATTR_ACL_POLICY]); + if (acl_policy != NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED && + acl_policy != NL80211_ACL_POLICY_DENY_UNLESS_LISTED) + return ERR_PTR(-EINVAL); + + if (!info->attrs[NL80211_ATTR_MAC_ADDRS]) + return ERR_PTR(-EINVAL); + + n_entries = validate_acl_mac_addrs(info->attrs[NL80211_ATTR_MAC_ADDRS]); + if (n_entries < 0) + return ERR_PTR(n_entries); + + if (n_entries > wiphy->max_acl_mac_addrs) + return ERR_PTR(-ENOTSUPP); + + acl = kzalloc(sizeof(*acl) + (sizeof(struct mac_address) * n_entries), + GFP_KERNEL); + if (!acl) + return ERR_PTR(-ENOMEM); + + nla_for_each_nested(attr, info->attrs[NL80211_ATTR_MAC_ADDRS], tmp) { + memcpy(acl->mac_addrs[i].addr, nla_data(attr), ETH_ALEN); + i++; + } + + acl->n_acl_entries = n_entries; + acl->acl_policy = acl_policy; + + return acl; +} + +static int nl80211_set_mac_acl(struct sk_buff *skb, struct genl_info *info) +{ + struct cfg80211_registered_device *rdev = info->user_ptr[0]; + struct net_device *dev = info->user_ptr[1]; + struct cfg80211_acl_data *acl; + int err; + + if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && + dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) + return -EOPNOTSUPP; + + if (!dev->ieee80211_ptr->beacon_interval) + return -EINVAL; + + acl = parse_acl_data(&rdev->wiphy, info); + if (IS_ERR(acl)) + return PTR_ERR(acl); + + err = rdev->ops->set_mac_acl(&rdev->wiphy, dev, acl); + + kfree(acl); + + return err; +} + static int nl80211_parse_beacon(struct genl_info *info, struct cfg80211_beacon_data *bcn) { @@ -2228,9 +2353,18 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]); } + if (info->attrs[NL80211_ATTR_ACL_POLICY]) { + params.acl = parse_acl_data(&rdev->wiphy, info); + if (IS_ERR(params.acl)) + return PTR_ERR(params.acl); + } + err = rdev->ops->start_ap(&rdev->wiphy, dev, ¶ms); if (!err) wdev->beacon_interval = params.beacon_interval; + + kfree(params.acl); + return err; } @@ -2643,6 +2777,56 @@ static struct net_device *get_vlan(struct genl_info *info, return ERR_PTR(ret); } +static struct nla_policy +nl80211_sta_wme_policy[NL80211_STA_WME_MAX + 1] __read_mostly = { + [NL80211_STA_WME_UAPSD_QUEUES] = { .type = NLA_U8 }, + [NL80211_STA_WME_MAX_SP] = { .type = NLA_U8 }, +}; + +static int nl80211_set_station_tdls(struct genl_info *info, + struct station_parameters *params) +{ + struct nlattr *tb[NL80211_STA_WME_MAX + 1]; + struct nlattr *nla; + int err; + + /* Dummy STA entry gets updated once the peer capabilities are known */ + if (info->attrs[NL80211_ATTR_PEER_AID]) + params->aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]); + if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) + params->ht_capa = + nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]); + if (info->attrs[NL80211_ATTR_VHT_CAPABILITY]) + params->vht_capa = + nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]); + + /* parse WME attributes if present */ + if (!info->attrs[NL80211_ATTR_STA_WME]) + return 0; + + nla = info->attrs[NL80211_ATTR_STA_WME]; + err = nla_parse_nested(tb, NL80211_STA_WME_MAX, nla, + nl80211_sta_wme_policy); + if (err) + return err; + + if (tb[NL80211_STA_WME_UAPSD_QUEUES]) + params->uapsd_queues = nla_get_u8( + tb[NL80211_STA_WME_UAPSD_QUEUES]); + if (params->uapsd_queues & ~IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK) + return -EINVAL; + + if (tb[NL80211_STA_WME_MAX_SP]) + params->max_sp = nla_get_u8(tb[NL80211_STA_WME_MAX_SP]); + + if (params->max_sp & ~IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK) + return -EINVAL; + + params->sta_modify_mask |= STATION_PARAM_APPLY_UAPSD; + + return 0; +} + static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) { struct cfg80211_registered_device *rdev = info->user_ptr[0]; @@ -2671,6 +2855,19 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]); } + if (info->attrs[NL80211_ATTR_STA_CAPABILITY]) { + params.capability = + nla_get_u16(info->attrs[NL80211_ATTR_STA_CAPABILITY]); + params.sta_modify_mask |= STATION_PARAM_APPLY_CAPABILITY; + } + + if (info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]) { + params.ext_capab = + nla_data(info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]); + params.ext_capab_len = + nla_len(info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]); + } + if (info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]) params.listen_interval = nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]); @@ -2719,6 +2916,14 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) BIT(NL80211_STA_FLAG_MFP))) return -EINVAL; + if (info->attrs[NL80211_ATTR_STA_CAPABILITY]) + return -EINVAL; + if (info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]) + return -EINVAL; + if (info->attrs[NL80211_ATTR_HT_CAPABILITY] || + info->attrs[NL80211_ATTR_VHT_CAPABILITY]) + return -EINVAL; + /* must be last in here for error handling */ params.vlan = get_vlan(info, rdev); if (IS_ERR(params.vlan)) @@ -2733,7 +2938,17 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) * to change the flag. */ params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER); - /* fall through */ + /* Include parameters for TDLS peer (driver will check) */ + err = nl80211_set_station_tdls(info, ¶ms); + if (err) + return err; + /* disallow things sta doesn't support */ + if (params.plink_action) + return -EINVAL; + if (params.sta_flags_mask & ~(BIT(NL80211_STA_FLAG_AUTHORIZED) | + BIT(NL80211_STA_FLAG_WME))) + return -EINVAL; + break; case NL80211_IFTYPE_ADHOC: /* disallow things sta doesn't support */ if (params.plink_action) @@ -2742,6 +2957,9 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) return -EINVAL; if (params.listen_interval >= 0) return -EINVAL; + if (info->attrs[NL80211_ATTR_HT_CAPABILITY] || + info->attrs[NL80211_ATTR_VHT_CAPABILITY]) + return -EINVAL; /* reject any changes other than AUTHORIZED */ if (params.sta_flags_mask & ~BIT(NL80211_STA_FLAG_AUTHORIZED)) return -EINVAL; @@ -2754,6 +2972,13 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) return -EINVAL; if (params.listen_interval >= 0) return -EINVAL; + if (info->attrs[NL80211_ATTR_STA_CAPABILITY]) + return -EINVAL; + if (info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]) + return -EINVAL; + if (info->attrs[NL80211_ATTR_HT_CAPABILITY] || + info->attrs[NL80211_ATTR_VHT_CAPABILITY]) + return -EINVAL; /* * No special handling for TDLS here -- the userspace * mesh code doesn't have this bug. @@ -2778,12 +3003,6 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) return err; } -static struct nla_policy -nl80211_sta_wme_policy[NL80211_STA_WME_MAX + 1] __read_mostly = { - [NL80211_STA_WME_UAPSD_QUEUES] = { .type = NLA_U8 }, - [NL80211_STA_WME_MAX_SP] = { .type = NLA_U8 }, -}; - static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) { struct cfg80211_registered_device *rdev = info->user_ptr[0]; @@ -2803,7 +3022,8 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) if (!info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]) return -EINVAL; - if (!info->attrs[NL80211_ATTR_STA_AID]) + if (!info->attrs[NL80211_ATTR_STA_AID] && + !info->attrs[NL80211_ATTR_PEER_AID]) return -EINVAL; mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); @@ -2814,14 +3034,34 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) params.listen_interval = nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]); - params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]); + if (info->attrs[NL80211_ATTR_PEER_AID]) + params.aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]); + else + params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]); if (!params.aid || params.aid > IEEE80211_MAX_AID) return -EINVAL; + if (info->attrs[NL80211_ATTR_STA_CAPABILITY]) { + params.capability = + nla_get_u16(info->attrs[NL80211_ATTR_STA_CAPABILITY]); + params.sta_modify_mask |= STATION_PARAM_APPLY_CAPABILITY; + } + + if (info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]) { + params.ext_capab = + nla_data(info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]); + params.ext_capab_len = + nla_len(info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]); + } + if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) params.ht_capa = nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]); + if (info->attrs[NL80211_ATTR_VHT_CAPABILITY]) + params.vht_capa = + nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]); + if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION]) params.plink_action = nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]); @@ -2867,7 +3107,8 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) params.sta_modify_mask |= STATION_PARAM_APPLY_UAPSD; } /* TDLS peers cannot be added */ - if (params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) + if ((params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) || + info->attrs[NL80211_ATTR_PEER_AID]) return -EINVAL; /* but don't bother the driver with it */ params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER); @@ -2879,10 +3120,12 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) break; case NL80211_IFTYPE_MESH_POINT: /* TDLS peers cannot be added */ - if (params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) + if ((params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) || + info->attrs[NL80211_ATTR_PEER_AID]) return -EINVAL; break; case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_P2P_CLIENT: /* Only TDLS peers can be added */ if (!(params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))) return -EINVAL; @@ -6320,6 +6563,27 @@ static int nl80211_register_beacons(struct sk_buff *skb, struct genl_info *info) return 0; } +static int nl80211_update_ft_ies(struct sk_buff *skb, struct genl_info *info) +{ + struct cfg80211_registered_device *rdev = info->user_ptr[0]; + struct cfg80211_update_ft_ies_params ft_params; + struct net_device *dev = info->user_ptr[1]; + + if (!rdev->ops->update_ft_ies) + return -EOPNOTSUPP; + + if (!info->attrs[NL80211_ATTR_MDID] || + !is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) + return -EINVAL; + + memset(&ft_params, 0, sizeof(ft_params)); + ft_params.md = nla_get_u16(info->attrs[NL80211_ATTR_MDID]); + ft_params.ie = nla_data(info->attrs[NL80211_ATTR_IE]); + ft_params.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); + + return rdev->ops->update_ft_ies(&rdev->wiphy, dev, &ft_params); +} + #define NL80211_FLAG_NEED_WIPHY 0x01 #define NL80211_FLAG_NEED_NETDEV 0x02 #define NL80211_FLAG_NEED_RTNL 0x04 @@ -6908,6 +7172,22 @@ static struct genl_ops nl80211_ops[] = { .internal_flags = NL80211_FLAG_NEED_NETDEV | NL80211_FLAG_NEED_RTNL, }, + { + .cmd = NL80211_CMD_SET_MAC_ACL, + .doit = nl80211_set_mac_acl, + .policy = nl80211_policy, + .flags = GENL_ADMIN_PERM, + .internal_flags = NL80211_FLAG_NEED_NETDEV | + NL80211_FLAG_NEED_RTNL, + }, + { + .cmd = NL80211_CMD_UPDATE_FT_IES, + .doit = nl80211_update_ft_ies, + .policy = nl80211_policy, + .flags = GENL_ADMIN_PERM, + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | + NL80211_FLAG_NEED_RTNL, + }, }; @@ -8145,6 +8425,48 @@ static struct notifier_block nl80211_netlink_notifier = { .notifier_call = nl80211_netlink_notify, }; +void cfg80211_ft_event(struct net_device *netdev, + struct cfg80211_ft_event_params *ft_event) +{ + struct wiphy *wiphy = netdev->ieee80211_ptr->wiphy; + struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); + struct sk_buff *msg; + void *hdr; + int err; + + if (!ft_event->target_ap) + return; + + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!msg) + return; + + hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FT_EVENT); + if (!hdr) { + nlmsg_free(msg); + return; + } + + nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); + nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); + nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, ft_event->target_ap); + if (ft_event->ies) + nla_put(msg, NL80211_ATTR_IE, ft_event->ies_len, ft_event->ies); + if (ft_event->ric_ies) + nla_put(msg, NL80211_ATTR_IE_RIC, ft_event->ric_ies_len, + ft_event->ric_ies); + + err = genlmsg_end(msg, hdr); + if (err < 0) { + nlmsg_free(msg); + return; + } + + genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, + nl80211_mlme_mcgrp.id, GFP_KERNEL); +} +EXPORT_SYMBOL(cfg80211_ft_event); + /* initialisation/exit functions */ int nl80211_init(void) diff --git a/sound/soc/msm/asustek_headset.c b/sound/soc/msm/asustek_headset.c index 3d4ce127ed9..1dd69251ed7 100644 --- a/sound/soc/msm/asustek_headset.c +++ b/sound/soc/msm/asustek_headset.c @@ -240,7 +240,7 @@ static void detection_work(struct work_struct *work) printk(KERN_INFO "HOOK_GPIO value: %d\n", mic_in); if (switch_get_state(&hs_data->sdev) == NO_DEVICE) insert_headset(); - else if (mic_in == 1) + if (mic_in == 1) goto closed_micbias; } else{ printk(KERN_INFO "HEADSET: Jack-in GPIO is low, but not a headset\n"); From 76c0128217c2eda2d1cafcacf624cc91eb7ff1ec Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Wed, 20 Nov 2013 23:22:48 +0100 Subject: [PATCH 013/215] Aroma : Add selectable minimum cpu frequency option --- .../META-INF/com/google/android/aroma-config | 9 +++++ .../com/google/android/updater-script | 29 ++++++++++++++++ release/aroma/config/buildconfig.sh | 16 +++++++++ release/aroma/system/etc/init.d/99glitch | 33 +++++++++++++++++-- 4 files changed, 85 insertions(+), 2 deletions(-) diff --git a/release/aroma/META-INF/com/google/android/aroma-config b/release/aroma/META-INF/com/google/android/aroma-config index 5bba8232b29..3f5d3a8f23a 100755 --- a/release/aroma/META-INF/com/google/android/aroma-config +++ b/release/aroma/META-INF/com/google/android/aroma-config @@ -176,6 +176,15 @@ selectbox( endif; +selectbox( + "Minimum CPU Frequency","Select minimum CPU frequency\n","@personalize","minfreq.prop", + "162MHz","",0, + "270MHz","",0, + "384MHz","(stock)",1, + "594MHz","",0, + "810MHz","",0 +); + selectbox( "Select CPU optimization level","Overclocks L2 cache and bus bandwidth. If you experience instability, choose stock\n","@personalize","opt.prop", "stock","(1.13GHz-4.26GBps)",0, diff --git a/release/aroma/META-INF/com/google/android/updater-script b/release/aroma/META-INF/com/google/android/updater-script index c441cec5e06..edf4ba29aaf 100755 --- a/release/aroma/META-INF/com/google/android/updater-script +++ b/release/aroma/META-INF/com/google/android/updater-script @@ -41,6 +41,35 @@ if ui_print("CPU optimization: glitchy"); endif; +if + file_getprop("/tmp/aroma/minfreq.prop","selected.0") == "1" + then + ui_print("Minimum frequency: 162 MHz"); +endif; + +if + file_getprop("/tmp/aroma/minfreq.prop","selected.0") == "2" + then + ui_print("Minimum frequency: 270 MHz"); +endif; + +if + file_getprop("/tmp/aroma/minfreq.prop","selected.0") == "3" + then + ui_print("Minimum frequency: 384 MHz"); +endif; + +if + file_getprop("/tmp/aroma/minfreq.prop","selected.0") == "4" + then + ui_print("Minimum frequency: 594 MHz"); +endif; + +if + file_getprop("/tmp/aroma/minfreq.prop","selected.0") == "5" + then + ui_print("Minimum frequency: 810 MHz"); +endif; if file_getprop("/tmp/aroma/uv.prop","selected.0") == "1" diff --git a/release/aroma/config/buildconfig.sh b/release/aroma/config/buildconfig.sh index 481ad454e9a..391e9070e87 100755 --- a/release/aroma/config/buildconfig.sh +++ b/release/aroma/config/buildconfig.sh @@ -3,6 +3,22 @@ #Build config file CONFIGFILE="/tmp/settings.conf" +#MINFREQ +MINF=`cat /tmp/aroma/minfreq.prop | cut -d '=' -f2` +echo -e "\n\n##### Minimum frequency #####\n# 1 162 MHz" >> $CONFIGFILE +echo -e "\n# 2 270 MHz\n# 3 384 MHz (stock)\n# 4 594 MHz\n# 5 810 MHz\n" >> $CONFIGFILE +if [ $MINF = 2 ]; then + echo "MINF=2" >> $CONFIGFILE; +elif [ $MINF = 3 ]; then + echo "MINF=3" >> $CONFIGFILE; +elif [ $MINF = 4 ]; then + echo "MINF=4" >> $CONFIGFILE; +elif [ $MINF = 5 ]; then + echo "MINF=5" >> $CONFIGFILE; +else + echo "MINF=1" >> $CONFIGFILE; +fi + #S2W S2W=`grep "item.0.1" /tmp/aroma/mods.prop | cut -d '=' -f2` S2S=`grep "item.0.2" /tmp/aroma/mods.prop | cut -d '=' -f2` diff --git a/release/aroma/system/etc/init.d/99glitch b/release/aroma/system/etc/init.d/99glitch index 2b03498daca..91816eaac16 100755 --- a/release/aroma/system/etc/init.d/99glitch +++ b/release/aroma/system/etc/init.d/99glitch @@ -9,17 +9,46 @@ fi echo $(date) >> $KERNEL_LOGFILE -#Set CPU_FREQ +#Max CPU_FREQ MAXF="`cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq`" echo $MAXF > /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq; echo $MAXF > /sys/devices/system/cpu/cpu1/cpufreq/scaling_max_freq; echo $MAXF > /sys/devices/system/cpu/cpu2/cpufreq/scaling_max_freq; echo $MAXF > /sys/devices/system/cpu/cpu3/cpufreq/scaling_max_freq; +echo Max CPU Frequency: $MAXF >> $KERNEL_LOGFILE + +#Min CPU_FREQ +if [ "`grep MINF=1 $KERNEL_CONF`" ]; then echo 162000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq; echo 162000 > /sys/devices/system/cpu/cpu1/cpufreq/scaling_min_freq; echo 162000 > /sys/devices/system/cpu/cpu2/cpufreq/scaling_min_freq; echo 162000 > /sys/devices/system/cpu/cpu3/cpufreq/scaling_min_freq; -echo Max CPU Frequency: $MAXF >> $KERNEL_LOGFILE +echo Min CPU Frequency: 162000 >> $KERNEL_LOGFILE +elif [ "`grep MINF=2 $KERNEL_CONF`" ]; then +echo 270000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq; +echo 270000 > /sys/devices/system/cpu/cpu1/cpufreq/scaling_min_freq; +echo 270000 > /sys/devices/system/cpu/cpu2/cpufreq/scaling_min_freq; +echo 270000 > /sys/devices/system/cpu/cpu3/cpufreq/scaling_min_freq; +echo Min CPU Frequency: 270000 >> $KERNEL_LOGFILE +elif [ "`grep MINF=4 $KERNEL_CONF`" ]; then +echo 594000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq; +echo 594000 > /sys/devices/system/cpu/cpu1/cpufreq/scaling_min_freq; +echo 594000 > /sys/devices/system/cpu/cpu2/cpufreq/scaling_min_freq; +echo 594000 > /sys/devices/system/cpu/cpu3/cpufreq/scaling_min_freq; +echo Min CPU Frequency: 594000 >> $KERNEL_LOGFILE +elif [ "`grep MINF=5 $KERNEL_CONF`" ]; then +echo 810000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq; +echo 810000 > /sys/devices/system/cpu/cpu1/cpufreq/scaling_min_freq; +echo 810000 > /sys/devices/system/cpu/cpu2/cpufreq/scaling_min_freq; +echo 810000 > /sys/devices/system/cpu/cpu3/cpufreq/scaling_min_freq; +echo Min CPU Frequency: 810000 >> $KERNEL_LOGFILE +else +echo 384000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq; +echo 384000 > /sys/devices/system/cpu/cpu1/cpufreq/scaling_min_freq; +echo 384000 > /sys/devices/system/cpu/cpu2/cpufreq/scaling_min_freq; +echo 384000 > /sys/devices/system/cpu/cpu3/cpufreq/scaling_min_freq; +echo Min CPU Frequency: 384000 >> $KERNEL_LOGFILE +fi #Set SWEEP2WAKE if [ "`grep SWEEP2WAKE=0 $KERNEL_CONF`" ]; then From 2f92e98bb417f2b603aaa781e411bf07781ea7c3 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Thu, 21 Nov 2013 17:01:22 +0100 Subject: [PATCH 014/215] Update intelli-plug - Thanks to Faux123 --- arch/arm/mach-msm/intelli_plug.c | 133 +++++++++++++++++++++++++++---- 1 file changed, 119 insertions(+), 14 deletions(-) diff --git a/arch/arm/mach-msm/intelli_plug.c b/arch/arm/mach-msm/intelli_plug.c index 44fa649184a..ef7281adb47 100644 --- a/arch/arm/mach-msm/intelli_plug.c +++ b/arch/arm/mach-msm/intelli_plug.c @@ -20,19 +20,23 @@ #include #include #include +#include +#include //#define DEBUG_INTELLI_PLUG #undef DEBUG_INTELLI_PLUG -#define INTELLI_PLUG_MAJOR_VERSION 1 -#define INTELLI_PLUG_MINOR_VERSION 6 +#define INTELLI_PLUG_MAJOR_VERSION 2 +#define INTELLI_PLUG_MINOR_VERSION 0 -#define DEF_SAMPLING_RATE (50000) -#define DEF_SAMPLING_MS (200) +#define DEF_SAMPLING_MS (500) +#define BUSY_SAMPLING_MS (1000) -#define DUAL_CORE_PERSISTENCE 15 -#define TRI_CORE_PERSISTENCE 12 -#define QUAD_CORE_PERSISTENCE 9 +#define DUAL_CORE_PERSISTENCE 9 +#define TRI_CORE_PERSISTENCE 7 +#define QUAD_CORE_PERSISTENCE 4 + +#define BUSY_PERSISTENCE 5 #define RUN_QUEUE_THRESHOLD 38 @@ -48,7 +52,11 @@ module_param(intelli_plug_active, uint, 0644); static unsigned int eco_mode_active = 0; module_param(eco_mode_active, uint, 0644); +static unsigned int sampling_time = 0; + static unsigned int persist_count = 0; +static unsigned int busy_persist_count = 0; + static bool suspended = false; #define NR_FSHIFT 3 @@ -196,6 +204,18 @@ static void __cpuinit intelli_plug_work_fn(struct work_struct *work) } } } + /* it's busy.. lets help it a bit */ + if (cpu_count > 2) { + if (busy_persist_count == 0) { + sampling_time = BUSY_SAMPLING_MS; + busy_persist_count = BUSY_PERSISTENCE; + } + } else { + if (busy_persist_count > 0) + busy_persist_count--; + else + sampling_time = DEF_SAMPLING_MS; + } if (!suspended) { switch (cpu_count) { @@ -263,7 +283,7 @@ static void __cpuinit intelli_plug_work_fn(struct work_struct *work) #endif } schedule_delayed_work_on(0, &intelli_plug_work, - msecs_to_jiffies(DEF_SAMPLING_MS)); + msecs_to_jiffies(sampling_time)); } #ifdef CONFIG_HAS_EARLYSUSPEND @@ -316,21 +336,106 @@ static struct early_suspend intelli_plug_early_suspend_struct_driver = { }; #endif /* CONFIG_HAS_EARLYSUSPEND */ -int __init intelli_plug_init(void) +static void intelli_plug_input_event(struct input_handle *handle, + unsigned int type, unsigned int code, int value) +{ +#ifdef DEBUG_INTELLI_PLUG + pr_info("intelli_plug touched!\n"); +#endif + + cancel_delayed_work(&intelli_plug_work); + + sampling_time = BUSY_SAMPLING_MS; + busy_persist_count = BUSY_PERSISTENCE; + + schedule_delayed_work_on(0, &intelli_plug_work, + msecs_to_jiffies(sampling_time)); +} + +static int input_dev_filter(const char *input_dev_name) { - /* We want all CPUs to do sampling nearly on same jiffy */ - int delay = usecs_to_jiffies(DEF_SAMPLING_RATE); + if (strstr(input_dev_name, "touchscreen") || + strstr(input_dev_name, "sec_touchscreen") || + strstr(input_dev_name, "touch_dev") || + strstr(input_dev_name, "-keypad") || + strstr(input_dev_name, "-nav") || + strstr(input_dev_name, "-oj")) { + pr_info("touch dev: %s\n", input_dev_name); + return 0; + } else { + pr_info("touch dev: %s\n", input_dev_name); + return 1; + } +} - if (num_online_cpus() > 1) - delay -= jiffies % delay; +static int intelli_plug_input_connect(struct input_handler *handler, + struct input_dev *dev, const struct input_device_id *id) +{ + struct input_handle *handle; + int error; + + if (input_dev_filter(dev->name)) + return -ENODEV; + + handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL); + if (!handle) + return -ENOMEM; + + handle->dev = dev; + handle->handler = handler; + handle->name = "intelliplug"; + + error = input_register_handle(handle); + if (error) + goto err2; + + error = input_open_device(handle); + if (error) + goto err1; + pr_info("%s found and connected!\n", dev->name); + return 0; +err1: + input_unregister_handle(handle); +err2: + kfree(handle); + return error; +} + +static void intelli_plug_input_disconnect(struct input_handle *handle) +{ + input_close_device(handle); + input_unregister_handle(handle); + kfree(handle); +} + +static const struct input_device_id intelli_plug_ids[] = { + { .driver_info = 1 }, + { }, +}; + +static struct input_handler intelli_plug_input_handler = { + .event = intelli_plug_input_event, + .connect = intelli_plug_input_connect, + .disconnect = intelli_plug_input_disconnect, + .name = "intelliplug_handler", + .id_table = intelli_plug_ids, +}; + +int __init intelli_plug_init(void) +{ + int rc; //pr_info("intelli_plug: scheduler delay is: %d\n", delay); pr_info("intelli_plug: version %d.%d by faux123\n", INTELLI_PLUG_MAJOR_VERSION, INTELLI_PLUG_MINOR_VERSION); + sampling_time = DEF_SAMPLING_MS; + + rc = input_register_handler(&intelli_plug_input_handler); INIT_DELAYED_WORK(&intelli_plug_work, intelli_plug_work_fn); - schedule_delayed_work_on(0, &intelli_plug_work, delay); + schedule_delayed_work_on(0, &intelli_plug_work, + msecs_to_jiffies(sampling_time)); #ifdef CONFIG_HAS_EARLYSUSPEND register_early_suspend(&intelli_plug_early_suspend_struct_driver); From 65cf6ed8b4efb7197b45c38f4dc6019cf763da47 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Thu, 21 Nov 2013 17:06:20 +0100 Subject: [PATCH 015/215] softirq: reduce latencies Date Thu, 03 Jan 2013 23:49:40 -0800 In various network workloads, __do_softirq() latencies can be up to 20 ms if HZ=1000, and 200 ms if HZ=100. This is because we iterate 10 times in the softirq dispatcher, and some actions can consume a lot of cycles. This patch changes the fallback to ksoftirqd condition to : - A time limit of 2 ms. - need_resched() being set on current task When one of this condition is met, we wakeup ksoftirqd for further softirq processing if we still have pending softirqs. Using need_resched() as the only condition can trigger RCU stalls, as we can keep BH disabled for too long. I ran several benchmarks and got no significant difference in throughput, but a very significant reduction of latencies (one order of magnitude) : In following bench, 200 antagonist "netperf -t TCP_RR" are started in background, using all available cpus. Then we start one "netperf -t TCP_RR", bound to the cpu handling the NIC IRQ (hard+soft) Before patch : RT_LATENCY,MIN_LATENCY,MAX_LATENCY,P50_LATENCY,P90_LATENCY,P99_LATENCY,MEAN_LATENCY,STDDEV_LATENCY MIGRATED TCP REQUEST/RESPONSE TEST from 0.0.0.0 (0.0.0.0) port 0 AF_INET to 7.7.7.84 () port 0 AF_INET : first burst 0 : cpu bind RT_LATENCY=550110.424 MIN_LATENCY=146858 MAX_LATENCY=997109 P50_LATENCY=305000 P90_LATENCY=550000 P99_LATENCY=710000 MEAN_LATENCY=376989.12 STDDEV_LATENCY=184046.92 After patch : RT_LATENCY,MIN_LATENCY,MAX_LATENCY,P50_LATENCY,P90_LATENCY,P99_LATENCY,MEAN_LATENCY,STDDEV_LATENCY MIGRATED TCP REQUEST/RESPONSE TEST from 0.0.0.0 (0.0.0.0) port 0 AF_INET to 7.7.7.84 () port 0 AF_INET : first burst 0 : cpu bind RT_LATENCY=40545.492 MIN_LATENCY=9834 MAX_LATENCY=78366 P50_LATENCY=33583 P90_LATENCY=59000 P99_LATENCY=69000 MEAN_LATENCY=38364.67 STDDEV_LATENCY=12865.26 Signed-off-by: Eric Dumazet Cc: David Miller Cc: Tom Herbert Cc: Ben Hutchings Signed-off-by: Tk-Glitch --- kernel/softirq.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/kernel/softirq.c b/kernel/softirq.c index 0df8be0885c..90baebc075e 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c @@ -194,21 +194,21 @@ void local_bh_enable_ip(unsigned long ip) EXPORT_SYMBOL(local_bh_enable_ip); /* - * We restart softirq processing MAX_SOFTIRQ_RESTART times, - * and we fall back to softirqd after that. + * We restart softirq processing for at most 2 ms, + * and if need_resched() is not set. * - * This number has been established via experimentation. + * These limits have been established via experimentation. * The two things to balance is latency against fairness - * we want to handle softirqs as soon as possible, but they * should not be able to lock up the box. */ -#define MAX_SOFTIRQ_RESTART 10 +#define MAX_SOFTIRQ_TIME max(1, (2*HZ/1000)) asmlinkage void __do_softirq(void) { struct softirq_action *h; __u32 pending; - int max_restart = MAX_SOFTIRQ_RESTART; + unsigned long end = jiffies + MAX_SOFTIRQ_TIME; int cpu; pending = local_softirq_pending(); @@ -255,11 +255,12 @@ asmlinkage void __do_softirq(void) local_irq_disable(); pending = local_softirq_pending(); - if (pending && --max_restart) - goto restart; + if (pending) { + if (time_before(jiffies, end) && !need_resched()) + goto restart; - if (pending) wakeup_softirqd(); + } lockdep_softirq_exit(); From 00244c23c1c05a5ee20ed6b0916a168ab709e860 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Wed, 27 Nov 2013 18:06:35 +0100 Subject: [PATCH 016/215] Command line options for s2w_orientation and pwrkey_suspend and disable s2w/dt2w when magnetic cover is used Signed-off-by: flar2 Signed-off-by: Tk-Glitch --- drivers/input/lid.c | 7 ++ drivers/input/touchscreen/ektf3k.c | 137 ++++++++++++++++++++++++++++- include/linux/sweep2wake.h | 1 + 3 files changed, 143 insertions(+), 2 deletions(-) diff --git a/drivers/input/lid.c b/drivers/input/lid.c index cd6b34a7daa..45e42b65047 100644 --- a/drivers/input/lid.c +++ b/drivers/input/lid.c @@ -12,6 +12,8 @@ #include #include +#include + #define LID_DEBUG 0 #define CONVERSION_TIME_MS 50 @@ -30,6 +32,8 @@ struct delayed_work lid_hall_sensor_work; +int lid_closed = 0; + int enable_lid = 1; module_param( enable_lid, int, 0644 ); @@ -98,6 +102,9 @@ static void lid_report_function(struct work_struct *dat) input_report_switch(lid_indev, SW_LID, !value); input_sync(lid_indev); + if (value == 0) + lid_closed = 1; + LID_NOTICE("SW_LID report value = %d\n", value); } diff --git a/drivers/input/touchscreen/ektf3k.c b/drivers/input/touchscreen/ektf3k.c index 7ab0f541707..f85ccb45f53 100755 --- a/drivers/input/touchscreen/ektf3k.c +++ b/drivers/input/touchscreen/ektf3k.c @@ -208,6 +208,7 @@ static DEFINE_MUTEX(s2w_lock); static bool scr_suspended = false; static int pwrkey_suspend = 1; +static int lid_suspend = 1; static int s2w_orientation = 0; static int shortsweep = 0; static int dt2w_switch = 1; @@ -456,6 +457,108 @@ static void doubletap2wake_func(int x, int y) return; } +static int __init get_s2w_opt(char *s2w) +{ + if (strcmp(s2w, "0") == 0) { + s2w_switch = 0; + } else if (strcmp(s2w, "1") == 0) { + s2w_switch = 1; + } else if (strcmp(s2w, "2") == 0) { + s2w_switch = 2; + } else { + s2w_switch = 0; + } + return 1; +} + +__setup("s2w=", get_s2w_opt); + +static int __init get_dt2w_opt(char *dt2w) +{ + if (strcmp(dt2w, "0") == 0) { + dt2w_switch = 0; + } else if (strcmp(dt2w, "1") == 0) { + dt2w_switch = 1; + } else { + dt2w_switch = 0; + } + return 1; +} + +__setup("dt2w=", get_dt2w_opt); + +static int __init get_shortsweep_opt(char *shorts) +{ + if (strcmp(shorts, "0") == 0) { + shortsweep = 0; + } else if (strcmp(shorts, "1") == 0) { + shortsweep = 1; + } else { + shortsweep = 0; + } + + if (shortsweep) { + s2w_begin_v = 400 ; + s2w_end_v = 950; + s2w_begin_h = 650; + s2w_end_h = 1600; + } else { + s2w_begin_v = 150; + s2w_end_v = 1200; + s2w_begin_h = 350; + s2w_end_h = 1900; + } + + return 1; +} + +__setup("shorts=", get_shortsweep_opt); + + +static int __init get_orient_opt(char *orient) +{ + if (strcmp(orient, "0") == 0) { + s2w_orientation = 0; + } else if (strcmp(orient, "1") == 0) { + s2w_orientation = 1; + } else if (strcmp(orient, "2") == 0) { + s2w_orientation = 2; + } else { + s2w_orientation = 0; + } + return 1; +} + +__setup("orient=", get_orient_opt); + +static int __init get_pwr_key_opt(char *pwr_key) +{ + if (strcmp(pwr_key, "0") == 0) { + pwrkey_suspend = 0; + } else if (strcmp(pwr_key, "1") == 0) { + pwrkey_suspend = 1; + } else { + pwrkey_suspend = 0; + } + return 1; +} + +__setup("pwr_key=", get_pwr_key_opt); + +static int __init get_lid_suspend_opt(char *lid_sus) +{ + if (strcmp(lid_sus, "0") == 0) { + lid_suspend = 0; + } else if (strcmp(lid_sus, "1") == 0) { + lid_suspend = 1; + } else { + lid_suspend = 0; + } + return 1; +} + +__setup("lid_sus=", get_lid_suspend_opt); + /* end sweep2wake */ @@ -699,6 +802,28 @@ static ssize_t elan_ktf3k_pwrkey_suspend_dump(struct device *dev, static DEVICE_ATTR(pwrkey_suspend, (S_IWUSR|S_IRUGO), elan_ktf3k_pwrkey_suspend_show, elan_ktf3k_pwrkey_suspend_dump); +static ssize_t elan_ktf3k_lid_suspend_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + size_t count = 0; + count += sprintf(buf, "%d\n", lid_suspend); + return count; +} + +static ssize_t elan_ktf3k_lid_suspend_dump(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + if (buf[0] >= '0' && buf[0] <= '1' && buf[1] == '\n') + if (lid_suspend != buf[0] - '0') + lid_suspend = buf[0] - '0'; + + return count; +} + +static DEVICE_ATTR(lid_suspend, (S_IWUSR|S_IRUGO), + elan_ktf3k_lid_suspend_show, elan_ktf3k_lid_suspend_dump); + + static ssize_t elan_ktf3k_orientation_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -867,6 +992,7 @@ static struct attribute *elan_attr[] = { &dev_attr_doubletap2wake.attr, &dev_attr_shortsweep.attr, &dev_attr_pwrkey_suspend.attr, + &dev_attr_lid_suspend.attr, &dev_attr_orientation.attr, NULL }; @@ -916,6 +1042,11 @@ static int elan_ktf3k_touch_sysfs_init(void) touch_debug(DEBUG_ERROR, "[elan]%s: sysfs_create_group failed\n", __func__); return ret; } + ret = sysfs_create_file(android_touch_kobj, &dev_attr_lid_suspend.attr); + if (ret) { + touch_debug(DEBUG_ERROR, "[elan]%s: sysfs_create_group failed\n", __func__); + return ret; + } ret = sysfs_create_file(android_touch_kobj, &dev_attr_orientation.attr); if (ret) { touch_debug(DEBUG_ERROR, "[elan]%s: sysfs_create_group failed\n", __func__); @@ -933,6 +1064,7 @@ static void elan_touch_sysfs_deinit(void) sysfs_remove_file(android_touch_kobj, &dev_attr_doubletap2wake.attr); sysfs_remove_file(android_touch_kobj, &dev_attr_shortsweep.attr); sysfs_remove_file(android_touch_kobj, &dev_attr_pwrkey_suspend.attr); + sysfs_remove_file(android_touch_kobj, &dev_attr_lid_suspend.attr); sysfs_remove_file(android_touch_kobj, &dev_attr_orientation.attr); kobject_del(android_touch_kobj); } @@ -2188,8 +2320,9 @@ static int elan_ktf3k_ts_suspend(struct i2c_client *client, pm_message_t mesg) enable_irq(client->irq); /*s2w*/ - if(((s2w_switch != 1 && !dt2w_switch) || (pwrkey_suspend && pwr_key_pressed)) && work_lock == 0) { + if(((s2w_switch != 1 && !dt2w_switch) || (lid_suspend && lid_closed) || (pwrkey_suspend && pwr_key_pressed)) && work_lock == 0) { pwr_key_pressed = 0; + lid_closed = 0; rc = elan_ktf3k_ts_set_power_state(client, PWR_STATE_DEEP_SLEEP); } /*s2w*/ @@ -2235,6 +2368,7 @@ static int elan_ktf3k_ts_resume(struct i2c_client *client) scr_suspended = false; pwr_key_pressed = 0; + lid_closed = 0; /* end s2w */ return 0; @@ -2291,4 +2425,3 @@ module_exit(elan_ktf3k_ts_exit); MODULE_DESCRIPTION("ELAN KTF3K Touchscreen Driver"); MODULE_LICENSE("GPL"); - diff --git a/include/linux/sweep2wake.h b/include/linux/sweep2wake.h index d2a083649a7..d2a00a77ed6 100644 --- a/include/linux/sweep2wake.h +++ b/include/linux/sweep2wake.h @@ -21,3 +21,4 @@ extern void sweep2wake_setdev(struct input_dev * input_device); extern int pwr_key_pressed; +extern int lid_closed; From 1b1375838c9884d627dafaccbcb4920e42d4d6e5 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Wed, 27 Nov 2013 18:11:56 +0100 Subject: [PATCH 017/215] intellidemand : Change optimal freq for power saving --- drivers/cpufreq/cpufreq_intellidemand.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/cpufreq/cpufreq_intellidemand.c b/drivers/cpufreq/cpufreq_intellidemand.c index cfb47ed1f62..ff3d9c15301 100644 --- a/drivers/cpufreq/cpufreq_intellidemand.c +++ b/drivers/cpufreq/cpufreq_intellidemand.c @@ -59,7 +59,7 @@ #define BOOSTED_SAMPLING_RATE (15000) #define DBS_INPUT_EVENT_MIN_FREQ (1026000) #define DBS_SYNC_FREQ (702000) -#define DBS_OPTIMAL_FREQ (1458000) +#define DBS_OPTIMAL_FREQ (1296000) #ifdef CONFIG_CPUFREQ_ID_PERFLOCK #define DBS_PERFLOCK_MIN_FREQ (594000) @@ -2038,4 +2038,3 @@ fs_initcall(cpufreq_gov_dbs_init); module_init(cpufreq_gov_dbs_init); #endif module_exit(cpufreq_gov_dbs_exit); - From b3bcddcc34448d7468301e008a9d56ef9e24d8e4 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Wed, 27 Nov 2013 18:13:24 +0100 Subject: [PATCH 018/215] intelli_plug: performance tune-up continued... Signed-off-by: Paul Reioux --- arch/arm/mach-msm/intelli_plug.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-msm/intelli_plug.c b/arch/arm/mach-msm/intelli_plug.c index ef7281adb47..00b2e5f1f0c 100644 --- a/arch/arm/mach-msm/intelli_plug.c +++ b/arch/arm/mach-msm/intelli_plug.c @@ -29,14 +29,14 @@ #define INTELLI_PLUG_MAJOR_VERSION 2 #define INTELLI_PLUG_MINOR_VERSION 0 -#define DEF_SAMPLING_MS (500) -#define BUSY_SAMPLING_MS (1000) +#define DEF_SAMPLING_MS (1000) +#define BUSY_SAMPLING_MS (500) -#define DUAL_CORE_PERSISTENCE 9 -#define TRI_CORE_PERSISTENCE 7 -#define QUAD_CORE_PERSISTENCE 4 +#define DUAL_CORE_PERSISTENCE 7 +#define TRI_CORE_PERSISTENCE 5 +#define QUAD_CORE_PERSISTENCE 3 -#define BUSY_PERSISTENCE 5 +#define BUSY_PERSISTENCE 10 #define RUN_QUEUE_THRESHOLD 38 From dccfb03e96b77c351ffec8a4950f2f4e2e4ac58c Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Wed, 27 Nov 2013 18:36:49 +0100 Subject: [PATCH 019/215] SCHEDULER: Autogroup patch group by current user android UID instead of task ID Signed-off-by: godmachine81 --- arch/arm/configs/flo_defconfig | 2 +- kernel/sys.c | 3 ++- kernel/sysctl.c | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/arch/arm/configs/flo_defconfig b/arch/arm/configs/flo_defconfig index 072afd1809c..a1bd6a77d6f 100644 --- a/arch/arm/configs/flo_defconfig +++ b/arch/arm/configs/flo_defconfig @@ -108,7 +108,7 @@ CONFIG_NAMESPACES=y # CONFIG_USER_NS is not set # CONFIG_PID_NS is not set # CONFIG_NET_NS is not set -# CONFIG_SCHED_AUTOGROUP is not set +CONFIG_SCHED_AUTOGROUP=y # CONFIG_SYSFS_DEPRECATED is not set # CONFIG_RELAY is not set CONFIG_BLK_DEV_INITRD=y diff --git a/kernel/sys.c b/kernel/sys.c index 81a2107d330..c2331850308 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -652,6 +652,7 @@ static int set_user(struct cred *new) free_uid(new->user); new->user = new_user; + sched_autogroup_create_attach(current); return 0; } @@ -1161,7 +1162,7 @@ SYSCALL_DEFINE0(setsid) write_unlock_irq(&tasklist_lock); if (err > 0) { proc_sid_connector(group_leader); - sched_autogroup_create_attach(group_leader); + } return err; } diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 178759331b4..956363b294c 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -359,7 +359,7 @@ static struct ctl_table kern_table[] = { .data = &sysctl_sched_autogroup_enabled, .maxlen = sizeof(unsigned int), .mode = 0644, - .proc_handler = proc_dointvec_minmax, + .proc_handler = proc_dointvec, .extra1 = &zero, .extra2 = &one, }, From 4639d873deb9d9ba1a29dc6631fe3c7230ff99c9 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Tue, 10 Dec 2013 17:24:46 +0100 Subject: [PATCH 020/215] Sound Control: (Optional) work around for WCD93xx audio issues (Use this only for devices with audio reset issues) Also bump version to 3.1 Signed-off-by: Paul Reioux wcd9xxx-core: add register write without mutex protection This is assuming the calling function will take care of the mutex. Signed-off-by: Paul Reioux --- drivers/mfd/wcd9xxx-core.c | 16 ++++++ include/linux/mfd/wcd9xxx/core.h | 3 ++ sound/soc/codecs/sound_control_3_gpl.c | 73 +++++++++++++++++++++++--- sound/soc/codecs/wcd9310.c | 63 +++++++++++++--------- 4 files changed, 125 insertions(+), 30 deletions(-) diff --git a/drivers/mfd/wcd9xxx-core.c b/drivers/mfd/wcd9xxx-core.c index 6152bc2ef54..f2c24ba5df0 100644 --- a/drivers/mfd/wcd9xxx-core.c +++ b/drivers/mfd/wcd9xxx-core.c @@ -82,6 +82,22 @@ int wcd9xxx_reg_read(struct wcd9xxx *wcd9xxx, unsigned short reg) } EXPORT_SYMBOL_GPL(wcd9xxx_reg_read); +#ifdef CONFIG_SOUND_CONTROL_HAX_3_GPL +int wcd9xxx_reg_read_safe(struct wcd9xxx *wcd9xxx, unsigned short reg) +{ + u8 val; + int ret; + + ret = wcd9xxx_read(wcd9xxx, reg, 1, &val, false); + + if (ret < 0) + return ret; + else + return val; +} +EXPORT_SYMBOL_GPL(wcd9xxx_reg_read_safe); +#endif + static int wcd9xxx_write(struct wcd9xxx *wcd9xxx, unsigned short reg, int bytes, void *src, bool interface_reg) { diff --git a/include/linux/mfd/wcd9xxx/core.h b/include/linux/mfd/wcd9xxx/core.h index 508bf3bb55e..40e3a83790c 100644 --- a/include/linux/mfd/wcd9xxx/core.h +++ b/include/linux/mfd/wcd9xxx/core.h @@ -161,6 +161,9 @@ struct wcd9xxx { }; int wcd9xxx_reg_read(struct wcd9xxx *wcd9xxx, unsigned short reg); +#ifdef CONFIG_SOUND_CONTROL_HAX_3_GPL +int wcd9xxx_reg_read_safe(struct wcd9xxx *wcd9xxx, unsigned short reg); +#endif int wcd9xxx_reg_write(struct wcd9xxx *wcd9xxx, unsigned short reg, u8 val); int wcd9xxx_interface_reg_read(struct wcd9xxx *wcd9xxx, unsigned short reg); diff --git a/sound/soc/codecs/sound_control_3_gpl.c b/sound/soc/codecs/sound_control_3_gpl.c index b7c32860eb4..446127138ef 100644 --- a/sound/soc/codecs/sound_control_3_gpl.c +++ b/sound/soc/codecs/sound_control_3_gpl.c @@ -22,14 +22,48 @@ #include #define SOUND_CONTROL_MAJOR_VERSION 3 -#define SOUND_CONTROL_MINOR_VERSION 0 +#define SOUND_CONTROL_MINOR_VERSION 1 extern struct snd_soc_codec *fauxsound_codec_ptr; +static int snd_ctrl_locked = 0; + unsigned int tabla_read(struct snd_soc_codec *codec, unsigned int reg); int tabla_write(struct snd_soc_codec *codec, unsigned int reg, unsigned int value); +int reg_access(unsigned int reg) +{ + int ret = 1; + + switch (reg) { + case TABLA_A_CDC_RX1_VOL_CTL_B2_CTL: + case TABLA_A_CDC_RX2_VOL_CTL_B2_CTL: + case TABLA_A_CDC_RX3_VOL_CTL_B2_CTL: + case TABLA_A_CDC_RX4_VOL_CTL_B2_CTL: + case TABLA_A_CDC_RX5_VOL_CTL_B2_CTL: + case TABLA_A_CDC_RX6_VOL_CTL_B2_CTL: + case TABLA_A_CDC_RX7_VOL_CTL_B2_CTL: + case TABLA_A_CDC_TX1_VOL_CTL_GAIN: + case TABLA_A_CDC_TX2_VOL_CTL_GAIN: + case TABLA_A_CDC_TX3_VOL_CTL_GAIN: + case TABLA_A_CDC_TX4_VOL_CTL_GAIN: + case TABLA_A_CDC_TX5_VOL_CTL_GAIN: + case TABLA_A_CDC_TX6_VOL_CTL_GAIN: + case TABLA_A_CDC_TX7_VOL_CTL_GAIN: + case TABLA_A_CDC_TX8_VOL_CTL_GAIN: + case TABLA_A_CDC_TX9_VOL_CTL_GAIN: + case TABLA_A_CDC_TX10_VOL_CTL_GAIN: + if (snd_ctrl_locked) + ret = 0; + break; + default: + break; + } + return ret; +} +EXPORT_SYMBOL(reg_access); + static bool calc_checksum(unsigned int a, unsigned int b, unsigned int c) { unsigned char chksum = 0; @@ -46,7 +80,7 @@ static bool calc_checksum(unsigned int a, unsigned int b, unsigned int c) static ssize_t cam_mic_gain_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { - return sprintf(buf, "%u", + return sprintf(buf, "%u\n", tabla_read(fauxsound_codec_ptr, TABLA_A_CDC_TX6_VOL_CTL_GAIN)); @@ -69,7 +103,7 @@ static ssize_t cam_mic_gain_store(struct kobject *kobj, static ssize_t mic_gain_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { - return sprintf(buf, "%u", + return sprintf(buf, "%u\n", tabla_read(fauxsound_codec_ptr, TABLA_A_CDC_TX7_VOL_CTL_GAIN)); } @@ -92,7 +126,7 @@ static ssize_t mic_gain_store(struct kobject *kobj, static ssize_t speaker_gain_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { - return sprintf(buf, "%u %u", + return sprintf(buf, "%u %u\n", tabla_read(fauxsound_codec_ptr, TABLA_A_CDC_RX3_VOL_CTL_B2_CTL), tabla_read(fauxsound_codec_ptr, @@ -119,7 +153,7 @@ static ssize_t speaker_gain_store(struct kobject *kobj, static ssize_t headphone_gain_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { - return sprintf(buf, "%u %u", + return sprintf(buf, "%u %u\n", tabla_read(fauxsound_codec_ptr, TABLA_A_CDC_RX1_VOL_CTL_B2_CTL), tabla_read(fauxsound_codec_ptr, @@ -145,7 +179,7 @@ static ssize_t headphone_gain_store(struct kobject *kobj, static ssize_t headphone_pa_gain_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { - return sprintf(buf, "%u %u", + return sprintf(buf, "%u %u\n", tabla_read(fauxsound_codec_ptr, TABLA_A_RX_HPH_L_GAIN), tabla_read(fauxsound_codec_ptr, TABLA_A_RX_HPH_R_GAIN)); } @@ -186,6 +220,26 @@ static ssize_t sound_control_version_show(struct kobject *kobj, struct kobj_attr SOUND_CONTROL_MINOR_VERSION); } +static ssize_t sound_control_locked_store(struct kobject *kobj, + struct kobj_attribute *attr, const char *buf, size_t count) +{ + int inp; + + sscanf(buf, "%d", &inp); + + if (inp == 0) + snd_ctrl_locked = 0; + else + snd_ctrl_locked = 1; + + return count; +} + +static ssize_t sound_control_locked_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) +{ + return sprintf(buf, "%d\n", snd_ctrl_locked); +} + static struct kobj_attribute cam_mic_gain_attribute = __ATTR(gpl_cam_mic_gain, 0666, @@ -216,6 +270,12 @@ static struct kobj_attribute headphone_pa_gain_attribute = headphone_pa_gain_show, headphone_pa_gain_store); +static struct kobj_attribute sound_control_locked_attribute = + __ATTR(gpl_sound_control_locked, + 0666, + sound_control_locked_show, + sound_control_locked_store); + static struct kobj_attribute sound_control_version_attribute = __ATTR(gpl_sound_control_version, 0444, @@ -228,6 +288,7 @@ static struct attribute *sound_control_attrs[] = &speaker_gain_attribute.attr, &headphone_gain_attribute.attr, &headphone_pa_gain_attribute.attr, + &sound_control_locked_attribute.attr, &sound_control_version_attribute.attr, NULL, }; diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c index e84ff57933d..1a36b6a466c 100644 --- a/sound/soc/codecs/wcd9310.c +++ b/sound/soc/codecs/wcd9310.c @@ -3919,31 +3919,13 @@ static int tabla_volatile(struct snd_soc_codec *ssc, unsigned int reg) return 0; } - #define TABLA_FORMATS (SNDRV_PCM_FMTBIT_S16_LE) -#ifndef CONFIG_SOUND_CONTROL_HAX_GPL -static -#endif -int tabla_write(struct snd_soc_codec *codec, unsigned int reg, - unsigned int value) -{ - int ret; - BUG_ON(reg > TABLA_MAX_REGISTER); - if (!tabla_volatile(codec, reg)) { - ret = snd_soc_cache_write(codec, reg, value); - if (ret != 0) - dev_err(codec->dev, "Cache write to %x failed: %d\n", - reg, ret); - } - - return wcd9xxx_reg_write(codec->control_data, reg, value); -} -#ifdef CONFIG_SOUND_CONTROL_HAX_GPL -EXPORT_SYMBOL(tabla_write); +#ifdef CONFIG_SOUND_CONTROL_HAX_3_GPL +extern int reg_access(unsigned int reg); #endif -#ifndef CONFIG_SOUND_CONTROL_HAX_GPL +#ifndef CONFIG_SOUND_CONTROL_HAX_3_GPL static #endif unsigned int tabla_read(struct snd_soc_codec *codec, @@ -3967,10 +3949,43 @@ unsigned int tabla_read(struct snd_soc_codec *codec, val = wcd9xxx_reg_read(codec->control_data, reg); return val; } -#ifdef CONFIG_SOUND_CONTROL_HAX_GPL +#ifdef CONFIG_SOUND_CONTROL_HAX_3_GPL EXPORT_SYMBOL(tabla_read); #endif +#ifndef CONFIG_SOUND_CONTROL_HAX_3_GPL +static +#endif +int tabla_write(struct snd_soc_codec *codec, unsigned int reg, + unsigned int value) +{ + int ret; +#ifdef CONFIG_SOUND_CONTROL_HAX_3_GPL + int val; +#endif + + BUG_ON(reg > TABLA_MAX_REGISTER); + + if (!tabla_volatile(codec, reg)) { + ret = snd_soc_cache_write(codec, reg, value); + if (ret != 0) + dev_err(codec->dev, "Cache write to %x failed: %d\n", + reg, ret); + } +#ifdef CONFIG_SOUND_CONTROL_HAX_3_GPL + if (!reg_access(reg)) + val = wcd9xxx_reg_read_safe(codec->control_data, reg); + else + val = value; + return wcd9xxx_reg_write(codec->control_data, reg, val); +#else + return wcd9xxx_reg_write(codec->control_data, reg, value); +#endif +} +#ifdef CONFIG_SOUND_CONTROL_HAX_3_GPL +EXPORT_SYMBOL(tabla_write); +#endif + static s16 tabla_get_current_v_ins(struct tabla_priv *tabla, bool hu) { s16 v_ins; @@ -8405,7 +8420,7 @@ static const struct file_operations codec_mbhc_debug_ops = { }; #endif -#ifdef CONFIG_SOUND_CONTROL_HAX_GPL +#ifdef CONFIG_SOUND_CONTROL_HAX_3_GPL struct snd_kcontrol_new *gpl_faux_snd_controls_ptr = (struct snd_kcontrol_new *)tabla_snd_controls; struct snd_soc_codec *fauxsound_codec_ptr; @@ -8421,7 +8436,7 @@ static int tabla_codec_probe(struct snd_soc_codec *codec) int i; int ch_cnt; -#ifdef CONFIG_SOUND_CONTROL_HAX_GPL +#ifdef CONFIG_SOUND_CONTROL_HAX_3_GPL pr_info("tabla codec probe...\n"); fauxsound_codec_ptr = codec; #endif From d842b2de3ca1c7189b87010f5d0f2cceaf509240 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Tue, 10 Dec 2013 17:25:47 +0100 Subject: [PATCH 021/215] Sound Control: (OPTIONAL) add power amp registers access control as well Signed-off-by: Paul Reioux --- sound/soc/codecs/sound_control_3_gpl.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/soc/codecs/sound_control_3_gpl.c b/sound/soc/codecs/sound_control_3_gpl.c index 446127138ef..bc0cb53a6c9 100644 --- a/sound/soc/codecs/sound_control_3_gpl.c +++ b/sound/soc/codecs/sound_control_3_gpl.c @@ -37,6 +37,10 @@ int reg_access(unsigned int reg) int ret = 1; switch (reg) { + case TABLA_A_RX_HPH_L_GAIN: + case TABLA_A_RX_HPH_R_GAIN: + case TABLA_A_RX_HPH_L_STATUS: + case TABLA_A_RX_HPH_R_STATUS: case TABLA_A_CDC_RX1_VOL_CTL_B2_CTL: case TABLA_A_CDC_RX2_VOL_CTL_B2_CTL: case TABLA_A_CDC_RX3_VOL_CTL_B2_CTL: From dce1de3aaef9053a9339d5fe3ad2ee7afb0fb960 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Tue, 10 Dec 2013 17:27:25 +0100 Subject: [PATCH 022/215] sound control: add register cache bump to version 3.2 Signed-off-by: Paul Reioux --- sound/soc/codecs/sound_control_3_gpl.c | 100 ++++++++++++++++++++++++- sound/soc/codecs/wcd9310.c | 14 +++- 2 files changed, 106 insertions(+), 8 deletions(-) diff --git a/sound/soc/codecs/sound_control_3_gpl.c b/sound/soc/codecs/sound_control_3_gpl.c index bc0cb53a6c9..5376620462c 100644 --- a/sound/soc/codecs/sound_control_3_gpl.c +++ b/sound/soc/codecs/sound_control_3_gpl.c @@ -22,7 +22,9 @@ #include #define SOUND_CONTROL_MAJOR_VERSION 3 -#define SOUND_CONTROL_MINOR_VERSION 1 +#define SOUND_CONTROL_MINOR_VERSION 2 + +#define REG_SZ 21 extern struct snd_soc_codec *fauxsound_codec_ptr; @@ -32,7 +34,96 @@ unsigned int tabla_read(struct snd_soc_codec *codec, unsigned int reg); int tabla_write(struct snd_soc_codec *codec, unsigned int reg, unsigned int value); -int reg_access(unsigned int reg) + +static unsigned int cached_regs[] = {6, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0 }; + +static unsigned int *cache_select(unsigned int reg) +{ + unsigned int *out = NULL; + + switch (reg) { + case TABLA_A_RX_HPH_L_GAIN: + out = &cached_regs[0]; + break; + case TABLA_A_RX_HPH_R_GAIN: + out = &cached_regs[1]; + break; + case TABLA_A_CDC_RX1_VOL_CTL_B2_CTL: + out = &cached_regs[4]; + break; + case TABLA_A_CDC_RX2_VOL_CTL_B2_CTL: + out = &cached_regs[5]; + break; + case TABLA_A_CDC_RX3_VOL_CTL_B2_CTL: + out = &cached_regs[6]; + break; + case TABLA_A_CDC_RX4_VOL_CTL_B2_CTL: + out = &cached_regs[7]; + break; + case TABLA_A_CDC_RX5_VOL_CTL_B2_CTL: + out = &cached_regs[8]; + break; + case TABLA_A_CDC_RX6_VOL_CTL_B2_CTL: + out = &cached_regs[9]; + break; + case TABLA_A_CDC_RX7_VOL_CTL_B2_CTL: + out = &cached_regs[10]; + break; + case TABLA_A_CDC_TX1_VOL_CTL_GAIN: + out = &cached_regs[11]; + break; + case TABLA_A_CDC_TX2_VOL_CTL_GAIN: + out = &cached_regs[12]; + break; + case TABLA_A_CDC_TX3_VOL_CTL_GAIN: + out = &cached_regs[13]; + break; + case TABLA_A_CDC_TX4_VOL_CTL_GAIN: + out = &cached_regs[14]; + break; + case TABLA_A_CDC_TX5_VOL_CTL_GAIN: + out = &cached_regs[15]; + break; + case TABLA_A_CDC_TX6_VOL_CTL_GAIN: + out = &cached_regs[16]; + break; + case TABLA_A_CDC_TX7_VOL_CTL_GAIN: + out = &cached_regs[17]; + break; + case TABLA_A_CDC_TX8_VOL_CTL_GAIN: + out = &cached_regs[18]; + break; + case TABLA_A_CDC_TX9_VOL_CTL_GAIN: + out = &cached_regs[19]; + break; + case TABLA_A_CDC_TX10_VOL_CTL_GAIN: + out = &cached_regs[20]; + break; + } + return out; +} + +void snd_hax_cache_write(unsigned int reg, unsigned int value) +{ + unsigned int *tmp = cache_select(reg); + + if (tmp != NULL) + *tmp = value; +} +EXPORT_SYMBOL(snd_hax_cache_write); + +unsigned int snd_hax_cache_read(unsigned int reg) +{ + if (cache_select(reg) != NULL) + return *cache_select(reg); + else + return -1; +} +EXPORT_SYMBOL(snd_hax_cache_read); + +int snd_hax_reg_access(unsigned int reg) { int ret = 1; @@ -66,7 +157,7 @@ int reg_access(unsigned int reg) } return ret; } -EXPORT_SYMBOL(reg_access); +EXPORT_SYMBOL(snd_hax_reg_access); static bool calc_checksum(unsigned int a, unsigned int b, unsigned int c) { @@ -217,7 +308,8 @@ static ssize_t headphone_pa_gain_store(struct kobject *kobj, return count; } -static ssize_t sound_control_version_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) +static ssize_t sound_control_version_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) { return sprintf(buf, "version: %u.%u\n", SOUND_CONTROL_MAJOR_VERSION, diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c index 1a36b6a466c..803bd8274eb 100644 --- a/sound/soc/codecs/wcd9310.c +++ b/sound/soc/codecs/wcd9310.c @@ -3922,7 +3922,9 @@ static int tabla_volatile(struct snd_soc_codec *ssc, unsigned int reg) #define TABLA_FORMATS (SNDRV_PCM_FMTBIT_S16_LE) #ifdef CONFIG_SOUND_CONTROL_HAX_3_GPL -extern int reg_access(unsigned int reg); +extern int snd_hax_reg_access(unsigned int); +extern unsigned int snd_hax_cache_read(unsigned int); +extern void snd_hax_cache_write(unsigned int, unsigned int); #endif #ifndef CONFIG_SOUND_CONTROL_HAX_3_GPL @@ -3973,10 +3975,14 @@ int tabla_write(struct snd_soc_codec *codec, unsigned int reg, reg, ret); } #ifdef CONFIG_SOUND_CONTROL_HAX_3_GPL - if (!reg_access(reg)) - val = wcd9xxx_reg_read_safe(codec->control_data, reg); - else + if (!snd_hax_reg_access(reg)) { + if (!((val = snd_hax_cache_read(reg)) != -1)) { + val = wcd9xxx_reg_read_safe(codec->control_data, reg); + } + } else { + snd_hax_cache_write(reg, value); val = value; + } return wcd9xxx_reg_write(codec->control_data, reg, val); #else return wcd9xxx_reg_write(codec->control_data, reg, value); From a1f4b3419208ca95b58d339bf853fdea2416dd00 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Tue, 10 Dec 2013 17:28:20 +0100 Subject: [PATCH 023/215] intell_plug: add FLO/DEB specific touchscreen device input Signed-off-by: Paul Reioux --- arch/arm/mach-msm/intelli_plug.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-msm/intelli_plug.c b/arch/arm/mach-msm/intelli_plug.c index 00b2e5f1f0c..3a7d739a365 100644 --- a/arch/arm/mach-msm/intelli_plug.c +++ b/arch/arm/mach-msm/intelli_plug.c @@ -355,6 +355,7 @@ static void intelli_plug_input_event(struct input_handle *handle, static int input_dev_filter(const char *input_dev_name) { if (strstr(input_dev_name, "touchscreen") || + strstr(input_dev_name, "elan-touchscreen") || strstr(input_dev_name, "sec_touchscreen") || strstr(input_dev_name, "touch_dev") || strstr(input_dev_name, "-keypad") || From cb33ffe04f08258017910d0741a6c68b0e7e547b Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Tue, 10 Dec 2013 17:29:20 +0100 Subject: [PATCH 024/215] msm: kgsl: Add an input handler to power up the GPU on a touch event On a device where the primary input is a touchscreen nobody is surprised that touch events are often the catalyst for drawing frames. If the GPU is in slumber we can get a jump on the action by watching for touch events and turning the GPU on in anticipation of a draw call. Register for events from all input drivers returning EV_ABS events and queue a work task to power up the GPU if it is currently in slumber. Change-Id: Ic0dedbadbdc96ef9ddd78252ea65f8e1cdd00110 Signed-off-by: Jordan Crouse adapted for FLO/DEB use Signed-off-by: Paul Reioux --- drivers/gpu/msm/adreno.c | 162 ++++++++++++++++++++++++++++ drivers/gpu/msm/adreno.h | 2 + drivers/gpu/msm/adreno_ringbuffer.c | 7 ++ drivers/gpu/msm/kgsl_device.h | 2 + 4 files changed, 173 insertions(+) diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index 72d7410ae26..8a9f00e9124 100644 --- a/drivers/gpu/msm/adreno.c +++ b/drivers/gpu/msm/adreno.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -80,6 +81,8 @@ static const struct kgsl_functable adreno_functable; +static void adreno_input_work(struct work_struct *work); + static struct adreno_device device_3d0 = { .dev = { KGSL_DEVICE_COMMON_INIT(device_3d0.dev), @@ -124,6 +127,8 @@ static struct adreno_device device_3d0 = { .ft_pf_policy = KGSL_FT_PAGEFAULT_DEFAULT_POLICY, .fast_hang_detect = 1, .long_ib_detect = 1, + .input_work = __WORK_INITIALIZER(device_3d0.input_work, + adreno_input_work), }; unsigned int ft_detect_regs[FT_DETECT_REGS_COUNT]; @@ -217,6 +222,119 @@ static const struct { 512, 0, 2, (SZ_1M + SZ_512K), NO_VER, NO_VER }, }; +/* Number of milliseconds to stay active active after a wake on touch */ +static unsigned int _wake_timeout = 100; + +/* + * A workqueue callback responsible for actually turning on the GPU after a + * touch event. kgsl_pwrctrl_wake() is used without any active_count protection + * to avoid the need to maintain state. Either somebody will start using the + * GPU or the idle timer will fire and put the GPU back into slumber + */ +static void adreno_input_work(struct work_struct *work) +{ + struct adreno_device *adreno_dev = container_of(work, + struct adreno_device, input_work); + struct kgsl_device *device = &adreno_dev->dev; + + mutex_lock(&device->mutex); + + device->flags |= KGSL_FLAG_WAKE_ON_TOUCH; + + /* + * Don't schedule adreno_start in a high priority workqueue, we are + * already in a workqueue which should be sufficient + */ + kgsl_pwrctrl_wake(device); + + /* + * When waking up from a touch event we want to stay active long enough + * for the user to send a draw command. The default idle timer timeout + * is shorter than we want so go ahead and push the idle timer out + * further for this special case + */ + mod_timer(&device->idle_timer, + jiffies + msecs_to_jiffies(_wake_timeout)); + mutex_unlock(&device->mutex); +} + +/* + * Process input events and schedule work if needed. At this point we are only + * interested in groking EV_ABS touchscreen events + */ +static void adreno_input_event(struct input_handle *handle, unsigned int type, + unsigned int code, int value) +{ + struct kgsl_device *device = handle->handler->private; + struct adreno_device *adreno_dev = ADRENO_DEVICE(device); + + /* + * Only queue the work under certain circumstances: we have to be in + * slumber, the event has to be EV_EBS and we had to have processed an + * IB since the last time we called wake on touch. + */ + if ((type == EV_ABS) && + !(device->flags & KGSL_FLAG_WAKE_ON_TOUCH) && + (device->state == KGSL_STATE_SLUMBER)) + schedule_work(&adreno_dev->input_work); +} + +static int adreno_input_connect(struct input_handler *handler, + struct input_dev *dev, const struct input_device_id *id) +{ + struct input_handle *handle; + int ret; + + handle = kzalloc(sizeof(*handle), GFP_KERNEL); + if (handle == NULL) + return -ENOMEM; + + handle->dev = dev; + handle->handler = handler; + handle->name = handler->name; + + ret = input_register_handle(handle); + if (ret) { + kfree(handle); + return ret; + } + + ret = input_open_device(handle); + if (ret) { + input_unregister_handle(handle); + kfree(handle); + } + + return ret; +} + +static void adreno_input_disconnect(struct input_handle *handle) +{ + input_close_device(handle); + input_unregister_handle(handle); + kfree(handle); +} + +/* + * We are only interested in EV_ABS events so only register handlers for those + * input devices that have EV_ABS events + */ +static const struct input_device_id adreno_input_ids[] = { + { + .flags = INPUT_DEVICE_ID_MATCH_EVBIT, + .evbit = { BIT_MASK(EV_ABS) }, + }, + { }, +}; + +static struct input_handler adreno_input_handler = { + .event = adreno_input_event, + .connect = adreno_input_connect, + .disconnect = adreno_input_disconnect, + .name = "kgsl", + .id_table = adreno_input_ids, +}; + /** * adreno_perfcounter_init: Reserve kernel performance counters * @device: device to configure @@ -1546,11 +1664,21 @@ adreno_probe(struct platform_device *pdev) kgsl_pwrscale_init(device); kgsl_pwrscale_attach_policy(device, ADRENO_DEFAULT_PWRSCALE_POLICY); + device->flags &= ~KGSL_FLAGS_SOFT_RESET; pdata = kgsl_device_get_drvdata(device); adreno_coresight_init(pdev); + adreno_input_handler.private = device; + + /* + * It isn't fatal if we cannot register the input handler. Sad, + * perhaps, but not fatal + */ + if (input_register_handler(&adreno_input_handler)) + KGSL_DRV_ERR(device, "Unable to register the input handler\n"); + return 0; error_close_device: @@ -1571,6 +1699,8 @@ static int __devexit adreno_remove(struct platform_device *pdev) device = (struct kgsl_device *)pdev->id_entry->driver_data; adreno_dev = ADRENO_DEVICE(device); + input_unregister_handler(&adreno_input_handler); + adreno_coresight_remove(pdev); kgsl_pwrscale_detach_policy(device); @@ -2075,6 +2205,36 @@ static int _ft_long_ib_detect_show(struct device *dev, (adreno_dev->long_ib_detect ? 1 : 0)); } +/** + * _wake_timeout_store() - Store the amount of time to extend idle check after + * wake on touch + * @dev: device ptr + * @attr: Device attribute + * @buf: value to write + * @count: size of the value to write + * + */ +static ssize_t _wake_timeout_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + return _ft_sysfs_store(buf, count, &_wake_timeout); +} + +/** + * _wake_timeout_show() - Show the amount of time idle check gets extended + * after wake on touch + * detect policy + * @dev: device ptr + * @attr: Device attribute + * @buf: value read + */ +static ssize_t _wake_timeout_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%d\n", _wake_timeout); +} #define FT_DEVICE_ATTR(name) \ DEVICE_ATTR(name, 0644, _ ## name ## _show, _ ## name ## _store); @@ -2084,12 +2244,14 @@ FT_DEVICE_ATTR(ft_pagefault_policy); FT_DEVICE_ATTR(ft_fast_hang_detect); FT_DEVICE_ATTR(ft_long_ib_detect); +static FT_DEVICE_ATTR(wake_timeout); const struct device_attribute *ft_attr_list[] = { &dev_attr_ft_policy, &dev_attr_ft_pagefault_policy, &dev_attr_ft_fast_hang_detect, &dev_attr_ft_long_ib_detect, + &dev_attr_wake_timeout, NULL, }; diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h index 881e39c9707..b271f838ff9 100644 --- a/drivers/gpu/msm/adreno.h +++ b/drivers/gpu/msm/adreno.h @@ -183,6 +183,8 @@ struct adreno_device { struct adreno_dispatcher dispatcher; struct kgsl_memdesc pwron_fixup; unsigned int pwron_fixup_dwords; + + struct work_struct input_work; }; /** diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c index 2fe2c4cb1c0..2d42bba3402 100644 --- a/drivers/gpu/msm/adreno_ringbuffer.c +++ b/drivers/gpu/msm/adreno_ringbuffer.c @@ -1006,6 +1006,13 @@ adreno_ringbuffer_issueibcmds(struct kgsl_device_private *dev_priv, /* For now everybody has the same priority */ cmdbatch->priority = ADRENO_CONTEXT_DEFAULT_PRIORITY; + /* + * Clear the wake on touch bit to indicate an IB has been submitted + * since the last time we set it + */ + + device->flags &= ~KGSL_FLAG_WAKE_ON_TOUCH; + /* Queue the command in the ringbuffer */ ret = adreno_dispatcher_queue_cmd(adreno_dev, drawctxt, cmdbatch, timestamp); diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h index c9be418d034..3dcf7d7a18f 100644 --- a/drivers/gpu/msm/kgsl_device.h +++ b/drivers/gpu/msm/kgsl_device.h @@ -62,6 +62,8 @@ #define KGSL_EVENT_TIMESTAMP_RETIRED 0 #define KGSL_EVENT_CANCELLED 1 +#define KGSL_FLAG_WAKE_ON_TOUCH BIT(0) + /* * "list" of event types for ftrace symbolic magic */ From ff0b7a4663e3c37b2c8f1c12b74015bb907a73cf Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Tue, 10 Dec 2013 17:30:00 +0100 Subject: [PATCH 025/215] intellidemand: sync with Hammerhead Intellidemand 5.0 Signed-off-by: Paul Reioux --- drivers/cpufreq/cpufreq_intellidemand.c | 1812 ++++++++++++++--------- 1 file changed, 1107 insertions(+), 705 deletions(-) diff --git a/drivers/cpufreq/cpufreq_intellidemand.c b/drivers/cpufreq/cpufreq_intellidemand.c index ff3d9c15301..cb0a36bce89 100644 --- a/drivers/cpufreq/cpufreq_intellidemand.c +++ b/drivers/cpufreq/cpufreq_intellidemand.c @@ -4,8 +4,8 @@ * Copyright (C) 2001 Russell King * (C) 2003 Venkatesh Pallipadi . * Jun Nakajima - * (C) 2012 Paul Reioux - * (C) 2013 Paul Reioux + * (C) 2013 The Linux Foundation. All rights reserved. + * (C) 2013 Paul Reioux * * 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,49 +23,100 @@ #include #include #include +#include #include #include #include #include -#ifdef CONFIG_EARLYSUSPEND -#include -#endif -#include -#include -#include +#if 0 +#include +#endif -#define INTELLIDEMAND_MAJOR_VERSION 4 -#define INTELLIDEMAND_MINOR_VERSION 2 +#define INTELLIDEMAND_MAJOR_VERSION 5 +#define INTELLIDEMAND_MINOR_VERSION 0 /* * dbs is used in this file as a shortform for demandbased switching * It helps to keep variable names smaller, simpler */ +#define DEF_SAMPLING_RATE (50000) #define DEF_FREQUENCY_DOWN_DIFFERENTIAL (10) -#define DEF_FREQUENCY_UP_THRESHOLD (75) +#define DEF_FREQUENCY_UP_THRESHOLD (80) #define DEF_SAMPLING_DOWN_FACTOR (1) -#define BOOSTED_SAMPLING_DOWN_FACTOR (10) #define MAX_SAMPLING_DOWN_FACTOR (100000) #define MICRO_FREQUENCY_DOWN_DIFFERENTIAL (3) -#define MICRO_FREQUENCY_UP_THRESHOLD (75) -#define MICRO_FREQUENCY_MIN_SAMPLE_RATE (15000) +#define MICRO_FREQUENCY_UP_THRESHOLD (95) +#define MICRO_FREQUENCY_MIN_SAMPLE_RATE (10000) #define MIN_FREQUENCY_UP_THRESHOLD (11) #define MAX_FREQUENCY_UP_THRESHOLD (100) #define MIN_FREQUENCY_DOWN_DIFFERENTIAL (1) -#define DEFAULT_FREQ_BOOST_TIME (2500000) -#define DEF_SAMPLING_RATE (50000) -#define BOOSTED_SAMPLING_RATE (15000) -#define DBS_INPUT_EVENT_MIN_FREQ (1026000) -#define DBS_SYNC_FREQ (702000) -#define DBS_OPTIMAL_FREQ (1296000) +#define DBS_INPUT_EVENT_MIN_FREQ (1190400) +#define DEF_UI_DYNAMIC_SAMPLING_RATE (30000) +#define DBS_UI_SAMPLING_MIN_TIMEOUT (30) +#define DBS_UI_SAMPLING_MAX_TIMEOUT (1000) +#define DBS_UI_SAMPLING_TIMEOUT (80) + +#define DEF_FREQ_STEP (25) +#define DEF_STEP_UP_EARLY_HISPEED (1190400) +#define DEF_STEP_UP_INTERIM_HISPEED (1728000) +#define DEF_SAMPLING_EARLY_HISPEED_FACTOR (2) +#define DEF_SAMPLING_INTERIM_HISPEED_FACTOR (3) + +/* PATCH : SMART_UP */ +#define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) + +#define SMART_UP_PLUS (0) +#define SMART_UP_SLOW_UP_AT_HIGH_FREQ (1) +#define SUP_MAX_STEP (3) +#define SUP_CORE_NUM (4) +#define SUP_SLOW_UP_DUR (5) +#define SUP_SLOW_UP_DUR_DEFAULT (2) + +#define SUP_HIGH_SLOW_UP_DUR (5) +#define SUP_FREQ_LEVEL (14) + +#if 0 +static unsigned long stored_sampling_rate; +#endif + +#if defined(SMART_UP_PLUS) +static unsigned int SUP_THRESHOLD_STEPS[SUP_MAX_STEP] = {75, 85, 90}; +static unsigned int SUP_FREQ_STEPS[SUP_MAX_STEP] = {4, 3, 2}; +//static unsigned int min_range = 108000; +typedef struct{ + unsigned int freq_idx; + unsigned int freq_value; +} freq_table_idx; +freq_table_idx pre_freq_idx[SUP_CORE_NUM] = {}; + +#endif + + +#if defined(SMART_UP_SLOW_UP_AT_HIGH_FREQ) + +#define SUP_SLOW_UP_FREQUENCY (1574400) +#define SUP_HIGH_SLOW_UP_FREQUENCY (1728000) +#define SUP_SLOW_UP_LOAD (90) + +typedef struct { + unsigned int hist_max_load[SUP_SLOW_UP_DUR]; + unsigned int hist_load_cnt; +} history_load; +static void reset_hist(history_load *hist_load); +history_load hist_load[SUP_CORE_NUM] = {}; + +typedef struct { + unsigned int hist_max_load[SUP_HIGH_SLOW_UP_DUR]; + unsigned int hist_load_cnt; +} history_load_high; +static void reset_hist_high(history_load_high *hist_load); +history_load_high hist_load_high[SUP_CORE_NUM] = {}; -#ifdef CONFIG_CPUFREQ_ID_PERFLOCK -#define DBS_PERFLOCK_MIN_FREQ (594000) #endif -static u64 freq_boosted_time; + /* * The polling frequency of this governor depends on the capability of * the processor. Default polling frequency is 1000 times the transition @@ -79,9 +130,7 @@ static u64 freq_boosted_time; #define MIN_SAMPLING_RATE_RATIO (2) static unsigned int min_sampling_rate; -#ifdef CONFIG_EARLYSUSPEND -static unsigned long stored_sampling_rate; -#endif +static unsigned int skip_intellidemand = 0; #define LATENCY_MULTIPLIER (1000) #define MIN_LATENCY_MULTIPLIER (20) @@ -90,16 +139,6 @@ static unsigned long stored_sampling_rate; #define POWERSAVE_BIAS_MAXLEVEL (1000) #define POWERSAVE_BIAS_MINLEVEL (-1000) -/* have the timer rate booted for this much time 2.5s*/ -#define TIMER_RATE_BOOST_TIME 2500000 -static int sampling_rate_boosted; -static u64 sampling_rate_boosted_time; -static unsigned int current_sampling_rate; - -#ifdef CONFIG_CPUFREQ_ID_PERFLOCK -static unsigned int saved_policy_min = 0; -#endif - static void do_dbs_timer(struct work_struct *work); static int cpufreq_governor_dbs(struct cpufreq_policy *policy, unsigned int event); @@ -133,12 +172,18 @@ struct cpu_dbs_info_s { unsigned int max_load; int cpu; unsigned int sample_type:1; + unsigned int freq_stay_count; /* * percpu mutex that serializes governor limit change with * do_dbs_timer invocation. We do not want do_dbs_timer to run * when user is changing the governor or limits. */ struct mutex timer_mutex; + + struct task_struct *sync_thread; + wait_queue_head_t sync_wq; + atomic_t src_sync_cpu; + atomic_t sync_enabled; }; static DEFINE_PER_CPU(struct cpu_dbs_info_s, id_cpu_dbs_info); @@ -147,12 +192,17 @@ static inline void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info); static unsigned int dbs_enable; /* number of CPUs using this policy */ +static DEFINE_PER_CPU(struct task_struct *, up_task); +static spinlock_t input_boost_lock; +static bool input_event_boost = false; +static unsigned long ui_sampling_expired = 0; + /* - * dbs_mutex protects dbs_enable in governor start/stop. + * dbs_mutex protects dbs_enable and dbs_info during start/stop. */ static DEFINE_MUTEX(dbs_mutex); -static struct workqueue_struct *input_wq; +static struct workqueue_struct *dbs_wq; struct dbs_work_struct { struct work_struct work; @@ -174,10 +224,26 @@ static struct dbs_tuners { unsigned int sampling_down_factor; int powersave_bias; unsigned int io_is_busy; - unsigned int boosted; - unsigned int freq_boost_time; - unsigned int boostfreq; + //20130711 smart_up + unsigned int smart_up; + unsigned int smart_slow_up_load; + unsigned int smart_slow_up_freq; + unsigned int smart_slow_up_dur; + unsigned int smart_high_slow_up_freq; + unsigned int smart_high_slow_up_dur; + unsigned int smart_each_off; + // end smart_up + unsigned int freq_step; + unsigned int step_up_early_hispeed; + unsigned int step_up_interim_hispeed; + unsigned int sampling_early_factor; + unsigned int sampling_interim_factor; unsigned int two_phase_freq; + unsigned int origin_sampling_rate; + unsigned int ui_sampling_rate; + unsigned int ui_timeout; + unsigned int enable_boost_cpu; + } dbs_tuners_ins = { .up_threshold_multi_core = DEF_FREQUENCY_UP_THRESHOLD, .up_threshold = DEF_FREQUENCY_UP_THRESHOLD, @@ -187,14 +253,30 @@ static struct dbs_tuners { .up_threshold_any_cpu_load = DEF_FREQUENCY_UP_THRESHOLD, .ignore_nice = 0, .powersave_bias = 0, - .sync_freq = DBS_SYNC_FREQ, - .optimal_freq = DBS_OPTIMAL_FREQ, - .freq_boost_time = DEFAULT_FREQ_BOOST_TIME, + .sync_freq = 0, + .optimal_freq = 0, + //20130711 smart_up + .smart_up = SMART_UP_PLUS, + .smart_slow_up_load = SUP_SLOW_UP_LOAD, + .smart_slow_up_freq = SUP_SLOW_UP_FREQUENCY, + .smart_slow_up_dur = SUP_SLOW_UP_DUR_DEFAULT, + .smart_high_slow_up_freq = SUP_HIGH_SLOW_UP_FREQUENCY, + .smart_high_slow_up_dur = SUP_HIGH_SLOW_UP_DUR, + .smart_each_off = 0, + // end smart_up + .freq_step = DEF_FREQ_STEP, + .step_up_early_hispeed = DEF_STEP_UP_EARLY_HISPEED, + .step_up_interim_hispeed = DEF_STEP_UP_INTERIM_HISPEED, + .sampling_early_factor = DEF_SAMPLING_EARLY_HISPEED_FACTOR, + .sampling_interim_factor = DEF_SAMPLING_INTERIM_HISPEED_FACTOR, .two_phase_freq = 0, + .ui_sampling_rate = DEF_UI_DYNAMIC_SAMPLING_RATE, + .ui_timeout = DBS_UI_SAMPLING_TIMEOUT, + .enable_boost_cpu = 1, + }; -static inline cputime64_t get_cpu_idle_time_jiffy(unsigned int cpu, - cputime64_t *wall) +static inline u64 get_cpu_idle_time_jiffy(unsigned int cpu, u64 *wall) { u64 idle_time; u64 cur_wall_time; @@ -329,6 +411,35 @@ static void intellidemand_powersave_bias_init(void) } } +void intellidemand_boost_cpu(int boost) +{ + int cpu; + + if (!dbs_tuners_ins.enable_boost_cpu) + return; + + for_each_online_cpu(cpu) { + struct cpufreq_policy *policy; + struct cpu_dbs_info_s *dbs_info; + + policy = cpufreq_cpu_get(cpu); + if (!policy) + continue; + dbs_info = &per_cpu(id_cpu_dbs_info, policy->cpu); + cpufreq_cpu_put(policy); + + mutex_lock(&dbs_info->timer_mutex); + if (boost) { + skip_intellidemand = 1; + __cpufreq_driver_target(policy, policy->max, CPUFREQ_RELATION_H); + } else { + skip_intellidemand = 0; + } + mutex_unlock(&dbs_info->timer_mutex); + } +} +EXPORT_SYMBOL(intellidemand_boost_cpu); + /************************** sysfs interface ************************/ static ssize_t show_sampling_rate_min(struct kobject *kobj, @@ -356,53 +467,21 @@ show_one(ignore_nice_load, ignore_nice); show_one(optimal_freq, optimal_freq); show_one(up_threshold_any_cpu_load, up_threshold_any_cpu_load); show_one(sync_freq, sync_freq); -show_one(boostpulse, boosted); -show_one(boosttime, freq_boost_time); -show_one(boostfreq, boostfreq); -show_one(two_phase_freq, two_phase_freq); - -#ifdef CONFIG_CPUFREQ_LIMIT_MAX_FREQ -void set_lmf_browsing_state(bool onOff); -void set_lmf_active_max_freq(unsigned long freq); -void set_lmf_inactive_max_freq(unsigned long freq); -void set_lmf_active_load(unsigned long freq); -void set_lmf_inactive_load(unsigned long freq); -bool get_lmf_browsing_state(void); -unsigned long get_lmf_active_max_freq(void); -unsigned long get_lmf_inactive_max_freq(void); -unsigned long get_lmf_active_load(void); -unsigned long get_lmf_inactive_load(void); - -static ssize_t show_lmf_browser(struct kobject *kobj, - struct attribute *attr, char *buf) -{ - return sprintf(buf, "%u\n", get_lmf_browsing_state()); -} - -static ssize_t show_lmf_active_max_freq(struct kobject *kobj, - struct attribute *attr, char *buf) -{ - return sprintf(buf, "%ld\n", get_lmf_active_max_freq()); -} - -static ssize_t show_lmf_inactive_max_freq(struct kobject *kobj, - struct attribute *attr, char *buf) -{ - return sprintf(buf, "%ld\n", get_lmf_inactive_max_freq()); -} - -static ssize_t show_lmf_active_load(struct kobject *kobj, - struct attribute *attr, char *buf) -{ - return sprintf(buf, "%ld\n", get_lmf_active_load()); -} - -static ssize_t show_lmf_inactive_load(struct kobject *kobj, - struct attribute *attr, char *buf) -{ - return sprintf(buf, "%ld\n", get_lmf_inactive_load()); -} -#endif +//20130711 smart_up +show_one(smart_up, smart_up); +show_one(smart_slow_up_load, smart_slow_up_load); +show_one(smart_slow_up_freq, smart_slow_up_freq); +show_one(smart_slow_up_dur, smart_slow_up_dur); +show_one(smart_high_slow_up_freq, smart_high_slow_up_freq); +show_one(smart_high_slow_up_dur, smart_high_slow_up_dur); +show_one(smart_each_off, smart_each_off); +// end smart_up +show_one(freq_step, freq_step); +show_one(step_up_early_hispeed, step_up_early_hispeed); +show_one(step_up_interim_hispeed, step_up_interim_hispeed); +show_one(sampling_early_factor, sampling_early_factor); +show_one(sampling_interim_factor, sampling_interim_factor); +show_one(enable_boost_cpu, enable_boost_cpu) static ssize_t show_powersave_bias (struct kobject *kobj, struct attribute *attr, char *buf) @@ -410,58 +489,6 @@ static ssize_t show_powersave_bias return snprintf(buf, PAGE_SIZE, "%d\n", dbs_tuners_ins.powersave_bias); } -static ssize_t store_boosttime(struct kobject *kobj, struct attribute *attr, - const char *buf, size_t count) -{ - unsigned int input; - int ret; - - ret = sscanf(buf, "%u", &input); - if (ret != 1) - return -EINVAL; - - dbs_tuners_ins.freq_boost_time = input; - return count; -} - -static ssize_t store_boostpulse(struct kobject *kobj, struct attribute *attr, - const char *buf, size_t count) -{ - int ret; - unsigned long val; - - ret = kstrtoul(buf, 0, &val); - if (ret < 0) { - pr_err("Bad Boost reqeust!\n"); - return ret; - } - - //pr_info("Boost requested!\n"); - - dbs_tuners_ins.boosted = 1; - freq_boosted_time = ktime_to_us(ktime_get()); - - if (sampling_rate_boosted) { - sampling_rate_boosted = 0; - dbs_tuners_ins.sampling_rate = current_sampling_rate; - //pr_info("Boosted Sampling rate %u\n", current_sampling_rate); - } - return count; -} - -static ssize_t store_boostfreq(struct kobject *a, struct attribute *b, - const char *buf, size_t count) -{ - unsigned int input; - int ret; - - ret = sscanf(buf, "%u", &input); - if (ret != 1) - return -EINVAL; - dbs_tuners_ins.boostfreq = input; - return count; -} - /** * update_sampling_rate - update sampling rate effective immediately if needed. * @new_rate: new sampling rate @@ -469,7 +496,7 @@ static ssize_t store_boostfreq(struct kobject *a, struct attribute *b, * If new rate is smaller than the old, simply updaing * dbs_tuners_int.sampling_rate might not be appropriate. For example, * if the original sampling_rate was 1 second and the requested new sampling - * rate is 10 ms because the user needs immediate reaction from ondemand + * rate is 10 ms because the user needs immediate reaction from intellidemand * governor, but not sure if higher frequency will be required or not, * then, the governor may change the sampling rate too late; up to 1 second * later. Thus, if we are reducing the sampling rate, we need to make the @@ -482,6 +509,7 @@ static void update_sampling_rate(unsigned int new_rate) dbs_tuners_ins.sampling_rate = new_rate = max(new_rate, min_sampling_rate); + get_online_cpus(); for_each_online_cpu(cpu) { struct cpufreq_policy *policy; struct cpu_dbs_info_s *dbs_info; @@ -510,14 +538,108 @@ static void update_sampling_rate(unsigned int new_rate) cancel_delayed_work_sync(&dbs_info->work); mutex_lock(&dbs_info->timer_mutex); - schedule_delayed_work_on(dbs_info->cpu, &dbs_info->work, - usecs_to_jiffies(new_rate)); + queue_delayed_work_on(dbs_info->cpu, dbs_wq, + &dbs_info->work, usecs_to_jiffies(new_rate)); } mutex_unlock(&dbs_info->timer_mutex); } + put_online_cpus(); +} + +show_one(ui_timeout, ui_timeout); + +static ssize_t store_ui_timeout(struct kobject *a, struct attribute *b, + const char *buf, size_t count) +{ + unsigned int input; + int ret; + ret = sscanf(buf, "%u", &input); + if (ret != 1) + return -EINVAL; + + input = max(input, (unsigned int)DBS_UI_SAMPLING_MIN_TIMEOUT); + dbs_tuners_ins.ui_timeout = min(input, (unsigned int)DBS_UI_SAMPLING_MAX_TIMEOUT); + + return count; +} + +static int two_phase_freq_array[NR_CPUS] = {[0 ... NR_CPUS-1] = 0} ; + +static ssize_t show_two_phase_freq +(struct kobject *kobj, struct attribute *attr, char *buf) +{ + int i = 0 ; + int shift = 0 ; + char *buf_pos = buf; + for ( i = 0 ; i < NR_CPUS; i++) { + shift = sprintf(buf_pos,"%d,",two_phase_freq_array[i]); + buf_pos += shift; + } + *(buf_pos-1) = '\0'; + return strlen(buf); +} + +static ssize_t store_two_phase_freq(struct kobject *a, struct attribute *b, + const char *buf, size_t count) +{ + + int ret = 0; + if (NR_CPUS == 1) + ret = sscanf(buf,"%u",&two_phase_freq_array[0]); + else if (NR_CPUS == 2) + ret = sscanf(buf,"%u,%u",&two_phase_freq_array[0], + &two_phase_freq_array[1]); + else if (NR_CPUS == 4) + ret = sscanf(buf, "%u,%u,%u,%u", &two_phase_freq_array[0], + &two_phase_freq_array[1], + &two_phase_freq_array[2], + &two_phase_freq_array[3]); + if (ret < NR_CPUS) + return -EINVAL; + + return count; +} + +static int input_event_min_freq_array[NR_CPUS] = {[0 ... NR_CPUS-1] = DBS_INPUT_EVENT_MIN_FREQ} ; + +static ssize_t show_input_event_min_freq +(struct kobject *kobj, struct attribute *attr, char *buf) +{ + int i = 0 ; + int shift = 0 ; + char *buf_pos = buf; + for ( i = 0 ; i < NR_CPUS; i++) { + shift = sprintf(buf_pos,"%d,",input_event_min_freq_array[i]); + buf_pos += shift; + } + *(buf_pos-1) = '\0'; + return strlen(buf); +} + +static ssize_t store_input_event_min_freq(struct kobject *a, struct attribute *b, + const char *buf, size_t count) +{ + + int ret = 0; + if (NR_CPUS == 1) + ret = sscanf(buf,"%u",&input_event_min_freq_array[0]); + else if (NR_CPUS == 2) + ret = sscanf(buf,"%u,%u",&input_event_min_freq_array[0], + &input_event_min_freq_array[1]); + else if (NR_CPUS == 4) + ret = sscanf(buf, "%u,%u,%u,%u", &input_event_min_freq_array[0], + &input_event_min_freq_array[1], + &input_event_min_freq_array[2], + &input_event_min_freq_array[3]); + if (ret < NR_CPUS) + return -EINVAL; + + return count; } +show_one(ui_sampling_rate, ui_sampling_rate); + static ssize_t store_sampling_rate(struct kobject *a, struct attribute *b, const char *buf, size_t count) { @@ -526,13 +648,15 @@ static ssize_t store_sampling_rate(struct kobject *a, struct attribute *b, ret = sscanf(buf, "%u", &input); if (ret != 1) return -EINVAL; + if (input == dbs_tuners_ins.origin_sampling_rate) + return count; update_sampling_rate(input); - current_sampling_rate = dbs_tuners_ins.sampling_rate; + dbs_tuners_ins.origin_sampling_rate = dbs_tuners_ins.sampling_rate; return count; } -static ssize_t store_two_phase_freq(struct kobject *a, struct attribute *b, - const char *buf, size_t count) +static ssize_t store_ui_sampling_rate(struct kobject *a, struct attribute *b, + const char *buf, size_t count) { unsigned int input; int ret; @@ -540,7 +664,7 @@ static ssize_t store_two_phase_freq(struct kobject *a, struct attribute *b, if (ret != 1) return -EINVAL; - dbs_tuners_ins.two_phase_freq = input; + dbs_tuners_ins.ui_sampling_rate = max(input, min_sampling_rate); return count; } @@ -694,6 +818,7 @@ static ssize_t store_ignore_nice_load(struct kobject *a, struct attribute *b, &dbs_info->prev_cpu_wall); if (dbs_tuners_ins.ignore_nice) dbs_info->prev_cpu_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE]; + } return count; } @@ -733,6 +858,10 @@ static ssize_t store_powersave_bias(struct kobject *a, struct attribute *b, POWERSAVE_BIAS_MINLEVEL)); dbs_tuners_ins.powersave_bias = input; + + get_online_cpus(); + mutex_lock(&dbs_mutex); + if (!bypass) { if (reenable_timer) { /* reinstate dbs timer */ @@ -744,9 +873,7 @@ static ssize_t store_powersave_bias(struct kobject *a, struct attribute *b, for_each_cpu(j, &cpus_timer_done) { if (!dbs_info->cur_policy) { - printk(KERN_ERR - "%s Dbs policy is NULL\n", - __func__); + pr_err("Dbs policy is NULL\n"); goto skip_this_cpu; } if (cpumask_test_cpu(j, dbs_info-> @@ -758,6 +885,9 @@ static ssize_t store_powersave_bias(struct kobject *a, struct attribute *b, if (dbs_info->cur_policy) { /* restart dbs timer */ dbs_timer_init(dbs_info); + /* Enable frequency synchronization + * of CPUs */ + atomic_set(&dbs_info->sync_enabled, 1); } skip_this_cpu: unlock_policy_rwsem_write(cpu); @@ -775,9 +905,7 @@ static ssize_t store_powersave_bias(struct kobject *a, struct attribute *b, for_each_cpu(j, &cpus_timer_done) { if (!dbs_info->cur_policy) { - printk(KERN_ERR - "%s Dbs policy is NULL\n", - __func__); + pr_err("Dbs policy is NULL\n"); goto skip_this_cpu_bypass; } if (cpumask_test_cpu(j, dbs_info-> @@ -789,111 +917,301 @@ static ssize_t store_powersave_bias(struct kobject *a, struct attribute *b, if (dbs_info->cur_policy) { /* cpu using intellidemand, cancel dbs timer */ - mutex_lock(&dbs_info->timer_mutex); dbs_timer_exit(dbs_info); + /* Disable frequency synchronization of + * CPUs to avoid re-queueing of work from + * sync_thread */ + atomic_set(&dbs_info->sync_enabled, 0); + mutex_lock(&dbs_info->timer_mutex); intellidemand_powersave_bias_setspeed( dbs_info->cur_policy, NULL, input); - mutex_unlock(&dbs_info->timer_mutex); + } skip_this_cpu_bypass: unlock_policy_rwsem_write(cpu); } } + mutex_unlock(&dbs_mutex); + put_online_cpus(); + return count; } -#ifdef CONFIG_CPUFREQ_LIMIT_MAX_FREQ -static ssize_t store_lmf_browser(struct kobject *a, struct attribute *b, - const char *buf, size_t count) +static ssize_t store_enable_boost_cpu(struct kobject *a, struct attribute *b, + const char *buf, size_t count) { unsigned int input; int ret; ret = sscanf(buf, "%u", &input); - if (ret != 1) + if(ret != 1) return -EINVAL; - mutex_lock(&dbs_mutex); - set_lmf_browsing_state(input); - mutex_unlock(&dbs_mutex); - + dbs_tuners_ins.enable_boost_cpu = (input > 0 ? input : 0); return count; } -static ssize_t store_lmf_active_max_freq(struct kobject *a, struct attribute *b, +/* PATCH : SMART_UP */ +#if defined(SMART_UP_SLOW_UP_AT_HIGH_FREQ) +static void reset_hist(history_load *hist_load) +{ int i; + + for (i = 0; i < SUP_SLOW_UP_DUR ; i++) + hist_load->hist_max_load[i] = 0; + + hist_load->hist_load_cnt = 0; +} + + +static void reset_hist_high(history_load_high *hist_load) +{ int i; + + for (i = 0; i < SUP_HIGH_SLOW_UP_DUR ; i++) + hist_load->hist_max_load[i] = 0; + + hist_load->hist_load_cnt = 0; +} + +#endif + +//20130711 smart_up +static ssize_t store_smart_up(struct kobject *a, struct attribute *b, const char *buf, size_t count) { - unsigned long input; + unsigned int input; int ret; + unsigned int i; - ret = sscanf(buf, "%ld", &input); + ret = sscanf(buf, "%u", &input); if (ret != 1) return -EINVAL; + if (input > 1 ){ + input = 1; + }else if (input < 0 ){ + input = 0; + } + + // buffer reset + for_each_online_cpu(i){ + reset_hist(&hist_load[i]); + reset_hist_high(&hist_load_high[i]); + } + dbs_tuners_ins.smart_up = input; + return count; +} - mutex_lock(&dbs_mutex); - set_lmf_active_max_freq(input); - mutex_unlock(&dbs_mutex); +static ssize_t store_smart_slow_up_load(struct kobject *a, struct attribute *b, + const char *buf, size_t count) +{ + unsigned int input; + int ret; + unsigned int i; + ret = sscanf(buf, "%u", &input); + if (ret != 1) + return -EINVAL; + if (input > 100 ){ + input = 100; + }else if (input < 0){ + input = 0; + } + // buffer reset + for_each_online_cpu(i){ + reset_hist(&hist_load[i]); + reset_hist_high(&hist_load_high[i]); + } + dbs_tuners_ins.smart_slow_up_load = input; return count; } -static ssize_t store_lmf_inactive_max_freq(struct kobject *a, struct attribute *b, +static ssize_t store_smart_slow_up_freq(struct kobject *a, struct attribute *b, const char *buf, size_t count) { - unsigned long input; + unsigned int input; int ret; + unsigned int i; - ret = sscanf(buf, "%ld", &input); + ret = sscanf(buf, "%u", &input); if (ret != 1) return -EINVAL; - - mutex_lock(&dbs_mutex); - set_lmf_inactive_max_freq(input); - mutex_unlock(&dbs_mutex); - + if (input < 0) + input = 0; + // buffer reset + for_each_online_cpu(i){ + reset_hist(&hist_load[i]); + reset_hist_high(&hist_load_high[i]); + } + dbs_tuners_ins.smart_slow_up_freq = input; return count; } - -static ssize_t store_lmf_active_load(struct kobject *a, struct attribute *b, +static ssize_t store_smart_slow_up_dur(struct kobject *a, struct attribute *b, const char *buf, size_t count) { - unsigned long input; + unsigned int input; int ret; + unsigned int i; - ret = sscanf(buf, "%ld", &input); + ret = sscanf(buf, "%u", &input); if (ret != 1) return -EINVAL; - - mutex_lock(&dbs_mutex); - set_lmf_active_load(input); - mutex_unlock(&dbs_mutex); - + if (input > SUP_SLOW_UP_DUR ){ + input = SUP_SLOW_UP_DUR; + }else if (input < 1 ){ + input = 1; + } + // buffer reset + for_each_online_cpu(i){ + reset_hist(&hist_load[i]); + reset_hist_high(&hist_load_high[i]); + } + dbs_tuners_ins.smart_slow_up_dur = input; return count; } +static ssize_t store_smart_high_slow_up_freq(struct kobject *a, struct attribute *b, + const char *buf, size_t count) +{ + unsigned int input; + int ret; + unsigned int i; -static ssize_t store_lmf_inactive_load(struct kobject *a, struct attribute *b, + ret = sscanf(buf, "%u", &input); + if (ret != 1) + return -EINVAL; + if (input < 0) + input = 0; + // buffer reset + for_each_online_cpu(i){ + reset_hist(&hist_load[i]); + reset_hist_high(&hist_load_high[i]); + } + dbs_tuners_ins.smart_high_slow_up_freq = input; + return count; +} +static ssize_t store_smart_high_slow_up_dur(struct kobject *a, struct attribute *b, const char *buf, size_t count) { - unsigned long input; + unsigned int input; int ret; + unsigned int i; - ret = sscanf(buf, "%ld", &input); + ret = sscanf(buf, "%u", &input); if (ret != 1) return -EINVAL; + if (input > SUP_HIGH_SLOW_UP_DUR ){ + input = SUP_HIGH_SLOW_UP_DUR; + }else if (input < 1 ){ + input = 1; + } + // buffer reset + for_each_online_cpu(i){ + reset_hist(&hist_load[i]); + reset_hist_high(&hist_load_high[i]); + } + dbs_tuners_ins.smart_high_slow_up_dur = input; + return count; +} +static ssize_t store_smart_each_off(struct kobject *a, struct attribute *b, + const char *buf, size_t count) +{ + unsigned int input; + int ret; + unsigned int i; - mutex_lock(&dbs_mutex); - set_lmf_inactive_load(input); - mutex_unlock(&dbs_mutex); + ret = sscanf(buf, "%u", &input); + if (ret != 1) + return -EINVAL; + if (input > SUP_CORE_NUM){ + input = SUP_CORE_NUM; + }else if ( input < 0){ + input = 0; + } + // buffer reset + for_each_online_cpu(i){ + reset_hist(&hist_load[i]); + reset_hist_high(&hist_load_high[i]); + } + dbs_tuners_ins.smart_each_off = input; return count; } -#endif +//end smart_up -define_one_global_rw(sampling_rate); +static ssize_t store_freq_step(struct kobject *a, + struct attribute *b, const char *buf, size_t count) +{ + unsigned int input; + int ret; + ret = sscanf(buf, "%u", &input); + + if (ret != 1 || input > 100 || + input < 0) { + return -EINVAL; + } + dbs_tuners_ins.freq_step = input; + return count; +} + +static ssize_t store_step_up_early_hispeed(struct kobject *a, + struct attribute *b, const char *buf, size_t count) +{ + unsigned int input; + int ret; + ret = sscanf(buf, "%u", &input); + + if (ret != 1 || input > 2265600 || + input < 0) { + return -EINVAL; + } + dbs_tuners_ins.step_up_early_hispeed = input; + return count; +} + +static ssize_t store_step_up_interim_hispeed(struct kobject *a, + struct attribute *b, const char *buf, size_t count) +{ + unsigned int input; + int ret; + ret = sscanf(buf, "%u", &input); + + if (ret != 1 || input > 2265600 || + input < 0) { + return -EINVAL; + } + dbs_tuners_ins.step_up_interim_hispeed = input; + return count; +} + +static ssize_t store_sampling_early_factor(struct kobject *a, + struct attribute *b, const char *buf, size_t count) +{ + unsigned int input; + int ret; + ret = sscanf(buf, "%u", &input); + + if (ret != 1 || input < 1) + return -EINVAL; + dbs_tuners_ins.sampling_early_factor = input; + return count; +} + +static ssize_t store_sampling_interim_factor(struct kobject *a, + struct attribute *b, const char *buf, size_t count) +{ + unsigned int input; + int ret; + ret = sscanf(buf, "%u", &input); + + if (ret != 1 || input < 1) + return -EINVAL; + dbs_tuners_ins.sampling_interim_factor = input; + return count; +} + +define_one_global_rw(sampling_rate); define_one_global_rw(io_is_busy); define_one_global_rw(up_threshold); define_one_global_rw(down_differential); @@ -904,18 +1222,25 @@ define_one_global_rw(up_threshold_multi_core); define_one_global_rw(optimal_freq); define_one_global_rw(up_threshold_any_cpu_load); define_one_global_rw(sync_freq); -define_one_global_rw(boostpulse); -define_one_global_rw(boosttime); -define_one_global_rw(boostfreq); +//20130711 smart_up +define_one_global_rw(smart_up); +define_one_global_rw(smart_slow_up_load); +define_one_global_rw(smart_slow_up_freq); +define_one_global_rw(smart_slow_up_dur); +define_one_global_rw(smart_high_slow_up_freq); +define_one_global_rw(smart_high_slow_up_dur); +define_one_global_rw(smart_each_off); +// end smart_up +define_one_global_rw(freq_step); +define_one_global_rw(step_up_early_hispeed); +define_one_global_rw(step_up_interim_hispeed); +define_one_global_rw(sampling_early_factor); +define_one_global_rw(sampling_interim_factor); define_one_global_rw(two_phase_freq); - -#ifdef CONFIG_CPUFREQ_LIMIT_MAX_FREQ -define_one_global_rw(lmf_browser); -define_one_global_rw(lmf_active_max_freq); -define_one_global_rw(lmf_inactive_max_freq); -define_one_global_rw(lmf_active_load); -define_one_global_rw(lmf_inactive_load); -#endif +define_one_global_rw(input_event_min_freq); +define_one_global_rw(ui_sampling_rate); +define_one_global_rw(ui_timeout); +define_one_global_rw(enable_boost_cpu); static struct attribute *dbs_attributes[] = { &sampling_rate_min.attr, @@ -930,17 +1255,26 @@ static struct attribute *dbs_attributes[] = { &optimal_freq.attr, &up_threshold_any_cpu_load.attr, &sync_freq.attr, - &boostpulse.attr, - &boosttime.attr, - &boostfreq.attr, + //20130711 smart_up + &smart_up.attr, + &smart_slow_up_load.attr, + &smart_slow_up_freq.attr, + &smart_slow_up_dur.attr, + &smart_high_slow_up_freq.attr, + &smart_high_slow_up_dur.attr, + &smart_each_off.attr, + // end smart_up + &freq_step.attr, + &step_up_early_hispeed.attr, + &step_up_interim_hispeed.attr, + &sampling_early_factor.attr, + &sampling_interim_factor.attr, &two_phase_freq.attr, -#ifdef CONFIG_CPUFREQ_LIMIT_MAX_FREQ - &lmf_browser.attr, - &lmf_active_max_freq.attr, - &lmf_inactive_max_freq.attr, - &lmf_active_load.attr, - &lmf_inactive_load.attr, -#endif + &input_event_min_freq.attr, + &ui_sampling_rate.attr, + &ui_timeout.attr, + &enable_boost_cpu.attr, + NULL }; @@ -962,14 +1296,45 @@ static void dbs_freq_increase(struct cpufreq_policy *p, unsigned int freq) CPUFREQ_RELATION_L : CPUFREQ_RELATION_H); } -int id_set_two_phase_freq(int cpufreq) +int set_two_phase_freq(int cpufreq) { - dbs_tuners_ins.two_phase_freq = cpufreq; + int i = 0; + for ( i = 0 ; i < NR_CPUS; i++) + two_phase_freq_array[i] = cpufreq; + return 0; +} + +void set_two_phase_freq_by_cpu ( int cpu_nr, int cpufreq){ + two_phase_freq_array[cpu_nr-1] = cpufreq; +} + +int input_event_boosted(void) +{ + unsigned long flags; + + + spin_lock_irqsave(&input_boost_lock, flags); + if (input_event_boost) { + if (time_before(jiffies, ui_sampling_expired)) { + spin_unlock_irqrestore(&input_boost_lock, flags); + return 1; + } + input_event_boost = false; + dbs_tuners_ins.sampling_rate = dbs_tuners_ins.origin_sampling_rate; + } + spin_unlock_irqrestore(&input_boost_lock, flags); + return 0; } static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) { + +#if defined(SMART_UP_PLUS) + unsigned int max_load = 0; + unsigned int core_j = 0; +#endif + /* Extrapolated load of this CPU */ unsigned int load_at_max_freq = 0; unsigned int max_load_freq; @@ -980,28 +1345,11 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) unsigned int j; static unsigned int phase = 0; static unsigned int counter = 0; + unsigned int nr_cpus; this_dbs_info->freq_lo = 0; policy = this_dbs_info->cur_policy; - /* Only core0 controls the boost */ - if (dbs_tuners_ins.boosted && policy->cpu == 0) { - if (ktime_to_us(ktime_get()) - freq_boosted_time >= - dbs_tuners_ins.freq_boost_time) { - dbs_tuners_ins.boosted = 0; - } - } - - /* Only core0 controls the timer_rate */ - if (sampling_rate_boosted && policy->cpu == 0) { - if (ktime_to_us(ktime_get()) - sampling_rate_boosted_time >= - TIMER_RATE_BOOST_TIME) { - - dbs_tuners_ins.sampling_rate = current_sampling_rate; - sampling_rate_boosted = 0; - } - } - /* * Every sampling_rate, we check, if current idle time is less * than 20% (default), then we try to increase frequency @@ -1081,6 +1429,12 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) load_freq = cur_load * freq_avg; if (load_freq > max_load_freq) max_load_freq = load_freq; + +#if defined(SMART_UP_PLUS) + max_load = cur_load; + core_j = j; +#endif + } for_each_online_cpu(j) { @@ -1108,47 +1462,212 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) dbs_tuners_ins.up_threshold_any_cpu_load; } } + /* calculate the scaled load across CPU */ load_at_max_freq = (cur_load * policy->cur)/policy->cpuinfo.max_freq; cpufreq_notify_utilization(policy, load_at_max_freq); - /* Check for frequency increase */ - if (max_load_freq > dbs_tuners_ins.up_threshold * policy->cur) { - /* If switching to max speed, apply sampling_down_factor */ +/* PATCH : SMART_UP */ + if (dbs_tuners_ins.smart_up && ( core_j + 1 ) > dbs_tuners_ins.smart_each_off ){ + + if (max_load_freq > SUP_THRESHOLD_STEPS[0] * policy->cur) { + int smart_up_inc = + (policy->max - policy->cur) / SUP_FREQ_STEPS[0]; + int freq_next = 0; + int i = 0; + + //20130429 UPDATE + int check_idx = 0; + int check_freq = 0; + int temp_up_inc =0; + if (counter < 5) { counter++; - if (counter > 2) { - /* change to busy phase */ + if (counter > 2) { phase = 1; } } - if (dbs_tuners_ins.two_phase_freq != 0 && phase == 0) { - /* idle phase */ - dbs_freq_increase(policy, - (((dbs_tuners_ins.two_phase_freq)> (int)(policy->max*80/100)) - ?(dbs_tuners_ins.two_phase_freq) : (int)(policy->max*80/100)) ); - } else { - /* busy phase */ - if (policy->cur < policy->max) { - if (sampling_rate_boosted && - (dbs_tuners_ins.sampling_down_factor < - BOOSTED_SAMPLING_DOWN_FACTOR)) { - this_dbs_info->rate_mult = - BOOSTED_SAMPLING_DOWN_FACTOR; - } else { - this_dbs_info->rate_mult = - dbs_tuners_ins.sampling_down_factor; + + nr_cpus = num_online_cpus(); + dbs_tuners_ins.two_phase_freq = two_phase_freq_array[nr_cpus-1]; + if (dbs_tuners_ins.two_phase_freq < policy->cur) + phase = 1; + if (dbs_tuners_ins.two_phase_freq != 0 && phase == 0) { + dbs_freq_increase(policy, dbs_tuners_ins.two_phase_freq); + } else { + if (policy->cur < policy->max) + this_dbs_info->rate_mult = + dbs_tuners_ins.sampling_down_factor; + dbs_freq_increase(policy, policy->max); + } + + for (i = (SUP_MAX_STEP - 1); i > 0; i--) { + if (max_load_freq > SUP_THRESHOLD_STEPS[i] + * policy->cur) { + smart_up_inc = (policy->max - policy->cur) + / SUP_FREQ_STEPS[i]; + + break; + } + } + + //20130429 UPDATE + check_idx = pre_freq_idx[core_j].freq_idx; + check_freq = pre_freq_idx[core_j].freq_value; + if ( ( check_idx == 0) + || (this_dbs_info->freq_table[check_idx].frequency + != policy->cur) ) + { + int i = 0; + for( i =0; i < SUP_FREQ_LEVEL; i ++) + { + if (this_dbs_info->freq_table[i].frequency == policy->cur) + { + + pre_freq_idx[core_j].freq_idx = i; + pre_freq_idx[core_j].freq_value = policy->cur; + check_idx = i; + check_freq = policy->cur; + break; } } - dbs_freq_increase(policy, policy->max); + + } + if( check_idx < SUP_FREQ_LEVEL-1 ){ + temp_up_inc = + this_dbs_info->freq_table[check_idx + 1].frequency + - check_freq; } + + if (smart_up_inc < temp_up_inc ) + smart_up_inc = temp_up_inc; + + freq_next = MIN((policy->cur + smart_up_inc), policy->max); + + + if (policy->cur >= dbs_tuners_ins.smart_high_slow_up_freq){ + int idx = hist_load_high[core_j].hist_load_cnt; + int avg_hist_load = 0; + + if (idx >= dbs_tuners_ins.smart_high_slow_up_dur) + idx = 0; + + hist_load_high[core_j].hist_max_load[idx] = max_load; + hist_load_high[core_j].hist_load_cnt = idx + 1; + + /* note : check history_load and get_sum_hist_load */ + if (hist_load_high[core_j]. + hist_max_load[dbs_tuners_ins.smart_high_slow_up_dur - 1] > 0) { + int sum_hist_load_freq = 0; + int i = 0; + for (i = 0; i < dbs_tuners_ins.smart_high_slow_up_dur; i++) + sum_hist_load_freq += + hist_load_high[core_j].hist_max_load[i]; + + avg_hist_load = sum_hist_load_freq + /dbs_tuners_ins.smart_high_slow_up_dur; + + if (avg_hist_load > dbs_tuners_ins.smart_slow_up_load){ + reset_hist_high(&hist_load_high[core_j]); + freq_next = MIN((policy->cur + temp_up_inc), policy->max); + } else + freq_next = policy->cur; + } else { + freq_next = policy->cur; + } + + } else if (policy->cur >= dbs_tuners_ins.smart_slow_up_freq ) { + int idx = hist_load[core_j].hist_load_cnt; + int avg_hist_load = 0; + + if (idx >= dbs_tuners_ins.smart_slow_up_dur) + idx = 0; + + hist_load[core_j].hist_max_load[idx] = max_load; + hist_load[core_j].hist_load_cnt = idx + 1; + + /* note : check history_load and get_sum_hist_load */ + if (hist_load[core_j]. + hist_max_load[dbs_tuners_ins.smart_slow_up_dur - 1] > 0) { + int sum_hist_load_freq = 0; + int i = 0; + for (i = 0; i < dbs_tuners_ins.smart_slow_up_dur; i++) + sum_hist_load_freq += + hist_load[core_j].hist_max_load[i]; + + avg_hist_load = sum_hist_load_freq + / dbs_tuners_ins.smart_slow_up_dur ; + + if (avg_hist_load > dbs_tuners_ins.smart_slow_up_load){ + reset_hist(&hist_load[core_j]); + freq_next = MIN((policy->cur + temp_up_inc), policy->max); + } else + freq_next = policy->cur; + } else { + freq_next = policy->cur; + } + } else { + reset_hist(&hist_load[core_j]); + } + if (freq_next == policy->max) + this_dbs_info->rate_mult = + dbs_tuners_ins.sampling_down_factor; + + dbs_freq_increase(policy, freq_next); + return; } + }else{ + /* Check for frequency increase */ + if (max_load_freq > dbs_tuners_ins.up_threshold * policy->cur) { + int target; + int inc; + + if (policy->cur < dbs_tuners_ins.step_up_early_hispeed) { + target = dbs_tuners_ins.step_up_early_hispeed; + }else if (policy->cur < dbs_tuners_ins.step_up_interim_hispeed) { + if(policy->cur == dbs_tuners_ins.step_up_early_hispeed) { + if(this_dbs_info->freq_stay_count < + dbs_tuners_ins.sampling_early_factor) { + this_dbs_info->freq_stay_count++; + return; + } + } + this_dbs_info->freq_stay_count = 1; + inc = (policy->max * dbs_tuners_ins.freq_step) / 100; + target = min(dbs_tuners_ins.step_up_interim_hispeed, + policy->cur + inc); + }else { + if(policy->cur == dbs_tuners_ins.step_up_interim_hispeed) { + if(this_dbs_info->freq_stay_count < + dbs_tuners_ins.sampling_interim_factor) { + this_dbs_info->freq_stay_count++; + return; + } + } + this_dbs_info->freq_stay_count = 1; + target = policy->max; + + //int inc = (policy->max * dbs_tuners_ins.freq_step) / 100; + //target = min(policy->max, policy->cur + inc); + } + + pr_debug("%s: cpu=%d, cur=%d, target=%d\n", + __func__, policy->cpu, policy->cur, target); + + /* If switching to max speed, apply sampling_down_factor */ + if (target == policy->max) + this_dbs_info->rate_mult = + dbs_tuners_ins.sampling_down_factor; + + dbs_freq_increase(policy, target); + return; + } + } if (counter > 0) { counter--; - if (counter == 0) { - /* change to idle phase */ + if (counter == 0) { phase = 0; } } @@ -1172,6 +1691,10 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) } } + if (input_event_boosted()) { + return; + } + /* Check for frequency decrease */ /* if we cannot reduce the frequency anymore, break out early */ if (policy->cur == policy->min) @@ -1190,13 +1713,47 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) (dbs_tuners_ins.up_threshold - dbs_tuners_ins.down_differential); - if (dbs_tuners_ins.boosted && - freq_next < dbs_tuners_ins.boostfreq) { - freq_next = dbs_tuners_ins.boostfreq; + pr_debug("%s: cpu=%d, cur=%d, target=%d (down)\n", + __func__, policy->cpu, policy->cur, freq_next); + +/* PATCH : SMART_UP */ + if (dbs_tuners_ins.smart_up && ( core_j + 1 ) > dbs_tuners_ins.smart_each_off ){ + + if (freq_next >= dbs_tuners_ins.smart_high_slow_up_freq){ + int idx = hist_load_high[core_j].hist_load_cnt; + + if (idx >= dbs_tuners_ins.smart_high_slow_up_dur ) + idx = 0; + + hist_load_high[core_j].hist_max_load[idx] = max_load; + hist_load_high[core_j].hist_load_cnt = idx + 1; + + + }else if (freq_next >= dbs_tuners_ins.smart_slow_up_freq) { + int idx = hist_load[core_j].hist_load_cnt; + + if (idx >= dbs_tuners_ins.smart_slow_up_dur) + idx = 0; + + hist_load[core_j].hist_max_load[idx] = max_load; + hist_load[core_j].hist_load_cnt = idx + 1; + + reset_hist_high(&hist_load_high[core_j]); + + + } else if (policy->cur >= dbs_tuners_ins.smart_slow_up_freq) { + reset_hist(&hist_load[core_j]); + reset_hist_high(&hist_load_high[core_j]); + + + } } +//#endif /* No longer fully busy, reset rate_mult */ this_dbs_info->rate_mult = 1; + this_dbs_info->freq_stay_count = 1; + if (freq_next < policy->min) freq_next = policy->min; @@ -1216,7 +1773,6 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) freq_next = dbs_tuners_ins.optimal_freq; } - if (!dbs_tuners_ins.powersave_bias) { __cpufreq_driver_target(policy, freq_next, CPUFREQ_RELATION_L); @@ -1229,355 +1785,16 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) } } -#ifdef CONFIG_CPUFREQ_LIMIT_MAX_FREQ - -enum { - SET_MIN = 0, - SET_MAX -}; - -enum { - BOOT_CPU = 0, - NON_BOOT_CPU1, - NON_BOOT_CPU2, - NON_BOOT_CPU3, -}; - -#define SAMPLE_DURATION_MSEC (10*1000) // 10 secs >= 10000 msec -#define ACTIVE_DURATION_MSEC (3*60*1000) // 3 mins -#define INACTIVE_DURATION_MSEC (1*60*1000) // 1 mins -#define MAX_ACTIVE_FREQ_LIMIT 30 // % -#define MAX_INACTIVE_FREQ_LIMIT 20 // % -#define ACTIVE_MAX_FREQ CONFIG_INTELLI_MAX_ACTIVE_FREQ // 1.512GHZ -#define INACTIVE_MAX_FREQ CONFIG_INTELLI_MAX_INACTIVE_FREQ // 1.134GHZ - -#define NUM_ACTIVE_LOAD_ARRAY (ACTIVE_DURATION_MSEC/SAMPLE_DURATION_MSEC) -#define NUM_INACTIVE_LOAD_ARRAY (INACTIVE_DURATION_MSEC/SAMPLE_DURATION_MSEC) - -bool lmf_browsing_state = true; -bool lmf_screen_state = true; - -static unsigned long lmf_active_max_limit = ACTIVE_MAX_FREQ; -static unsigned long lmf_inactive_max_limit = INACTIVE_MAX_FREQ; -static unsigned long lmf_active_load_limit = MAX_ACTIVE_FREQ_LIMIT; -static unsigned long lmf_inactive_load_limit = MAX_INACTIVE_FREQ_LIMIT; - -static unsigned long jiffies_old = 0; -static unsigned long time_int = 0; -static unsigned long time_int1 = 0; -static unsigned long load_state_total0 = 0; -static unsigned long load_state_total1 = 0; -static unsigned long load_limit_index = 0; -static unsigned long load_limit_total[NUM_ACTIVE_LOAD_ARRAY]; -static unsigned long msecs_limit_total = 0; -static bool active_state = true; -static bool lmf_old_state = false; - -extern int cpufreq_set_limits(int cpu, unsigned int limit, unsigned int value); -extern int cpufreq_set_limits_off(int cpu, unsigned int limit, unsigned int value); - -void set_lmf_browsing_state(bool onOff) -{ - if (onOff) - lmf_browsing_state = true; - else - lmf_browsing_state = false; -} - -void set_lmf_active_max_freq(unsigned long freq) -{ - lmf_active_max_limit = freq; -} - -void set_lmf_inactive_max_freq(unsigned long freq) -{ - lmf_inactive_max_limit = freq; -} - -void set_lmf_active_load(unsigned long freq) -{ - lmf_active_load_limit = freq; -} - -void set_lmf_inactive_load(unsigned long freq) -{ - lmf_inactive_load_limit = freq; -} - -bool get_lmf_browsing_state(void) -{ - return lmf_browsing_state; -} - -unsigned long get_lmf_active_max_freq(void) -{ - return lmf_active_max_limit; -} - -unsigned long get_lmf_inactive_max_freq(void) -{ - return lmf_inactive_max_limit; -} - -unsigned long get_lmf_active_load(void) -{ - return lmf_active_load_limit; -} - -unsigned long get_lmf_inactive_load(void) -{ - return lmf_inactive_load_limit; -} -#endif - -static unsigned int rq_persist_count = 0; - static void do_dbs_timer(struct work_struct *work) { struct cpu_dbs_info_s *dbs_info = container_of(work, struct cpu_dbs_info_s, work.work); unsigned int cpu = dbs_info->cpu; int sample_type = dbs_info->sample_type; + int delay = msecs_to_jiffies(50); - int delay; -#ifdef CONFIG_CPUFREQ_ID_PERFLOCK - struct cpufreq_policy *policy; - - policy = dbs_info->cur_policy; -#endif - - if (num_online_cpus() >= 2 && rq_info.rq_avg > 38) - rq_persist_count++; - else - if (rq_persist_count > 0) - rq_persist_count--; - -#ifdef CONFIG_CPUFREQ_ID_PERFLOCK - if (cpu == 0) { - if (num_online_cpus() >= 2) { - if (saved_policy_min != 0) - policy->min = saved_policy_min; - } else if (num_online_cpus() == 1) { - saved_policy_min = policy->min; - policy->min = DBS_PERFLOCK_MIN_FREQ; - } - } -#endif - -#ifdef CONFIG_CPUFREQ_LIMIT_MAX_FREQ - if (rq_persist_count > 3) { - lmf_browsing_state = false; - rq_persist_count = 0; - } - else - lmf_browsing_state = true; - //pr_info("Run Queue Average: %u\n", rq_info.rq_avg); - - if (!lmf_browsing_state && lmf_screen_state) - { - if (cpu == BOOT_CPU) - { - if (lmf_old_state == true) - { - pr_warn("LMF: disabled!\n"); - lmf_old_state = false; - } - - if (!active_state) - { - /* set freq to 1.5GHz */ - //pr_info("LMF: CPU0 set max freq to: %lu\n", lmf_active_max_limit); - cpufreq_set_limits(BOOT_CPU, SET_MAX, lmf_active_max_limit); - - //pr_info("LMF: CPUX set max freq to: %lu\n", lmf_active_max_limit); - if (cpu_online(NON_BOOT_CPU1) || - cpu_online(NON_BOOT_CPU2) || - cpu_online(NON_BOOT_CPU3)) { - cpufreq_set_limits(NON_BOOT_CPU1, SET_MAX, lmf_active_max_limit); - cpufreq_set_limits(NON_BOOT_CPU2, SET_MAX, lmf_active_max_limit); - cpufreq_set_limits(NON_BOOT_CPU3, SET_MAX, lmf_active_max_limit); - } else { - cpufreq_set_limits_off(NON_BOOT_CPU1, SET_MAX, lmf_active_max_limit); - cpufreq_set_limits_off(NON_BOOT_CPU2, SET_MAX, lmf_active_max_limit); - cpufreq_set_limits_off(NON_BOOT_CPU3, SET_MAX, lmf_active_max_limit); - } - } - - jiffies_old = 0; - time_int = 0; - time_int1 = 0; - load_state_total0 = 0; - load_state_total1 = 0; - msecs_limit_total = 0; - load_limit_index = 0; - active_state = true; - } - } - else if (lmf_browsing_state && lmf_screen_state) // lmf_browsing_state -> TRUE - { - struct cpufreq_policy *policy; - unsigned long load_state_cpu = 0; - unsigned int delay_msec = 0; - unsigned long load_total = 0; - unsigned long jiffies_cur = jiffies; - - if (cpu == NON_BOOT_CPU1 || cpu == NON_BOOT_CPU2 || cpu == NON_BOOT_CPU3) - { - delay_msec = (dbs_tuners_ins.sampling_rate * dbs_info->rate_mult) / 1000; - policy = dbs_info->cur_policy; - load_state_cpu = ((policy->cur) * delay_msec)/10000; - - time_int1 += delay_msec; - load_state_total1 += load_state_cpu; - } - else - { - if (lmf_old_state == false) - { - pr_warn("LMF: enabled!\n"); - lmf_old_state = true; - } - - if (jiffies_old == 0) - { - jiffies_old = jiffies_cur; - } - else - { - delay_msec = jiffies_to_msecs(jiffies_cur - jiffies_old); - jiffies_old = jiffies_cur; - policy = dbs_info->cur_policy; - load_state_cpu = ((policy->cur) * delay_msec)/10000; - - time_int += delay_msec; - load_state_total0 += load_state_cpu; - - /* average */ - if (time_int >= SAMPLE_DURATION_MSEC) - { - int i = 0; - unsigned long ave_max = 0; - unsigned long average = 0; - unsigned long average_dec = 0; - unsigned long total_load = 0; - - load_total = load_state_total0 + load_state_total1; - ave_max = (time_int / 10) * ((lmf_active_max_limit/1000) * 2); - average = (load_total * 100) / ave_max; - average_dec = (load_total * 100) % ave_max; - - msecs_limit_total += time_int; - load_limit_total[load_limit_index++] = average; - - //pr_warn("LMF: average = %ld.%ld, (%ld:%ld) (%ld:%ld) (%ld:%ld)\n", - // average, average_dec, time_int, time_int1, load_state_total0, load_state_total1, load_limit_index-1, msecs_limit_total); - - time_int = 0; - time_int1 = 0; - load_state_total0 = 0; - load_state_total1 = 0; - - /* active */ - if (active_state) - { - if (load_limit_index >= NUM_ACTIVE_LOAD_ARRAY) - { - load_limit_index = 0; - } - - if (msecs_limit_total > ACTIVE_DURATION_MSEC) - { - for (i=0; i lmf_active_load_limit) - { - msecs_limit_total = 0; - load_limit_index = 0; - active_state = false; - - /* set freq to 1.0GHz */ - //pr_info("LMF: CPU0 set max freq to: %lu\n", lmf_inactive_max_limit); - cpufreq_set_limits(BOOT_CPU, SET_MAX, lmf_inactive_max_limit); - - //pr_info("LMF: CPUX set max freq to: %lu\n", lmf_inactive_max_limit); - if (cpu_online(NON_BOOT_CPU1) || - cpu_online(NON_BOOT_CPU2) || - cpu_online(NON_BOOT_CPU3)) { - cpufreq_set_limits(NON_BOOT_CPU1, SET_MAX, lmf_inactive_max_limit); - cpufreq_set_limits(NON_BOOT_CPU2, SET_MAX, lmf_inactive_max_limit); - cpufreq_set_limits(NON_BOOT_CPU3, SET_MAX, lmf_inactive_max_limit); - } else { - cpufreq_set_limits_off(NON_BOOT_CPU1, SET_MAX, lmf_inactive_max_limit); - cpufreq_set_limits_off(NON_BOOT_CPU2, SET_MAX, lmf_inactive_max_limit); - cpufreq_set_limits_off(NON_BOOT_CPU3, SET_MAX, lmf_inactive_max_limit); - } - } - else - { - msecs_limit_total = ACTIVE_DURATION_MSEC; // to prevent overflow - } - } - } - else /* inactive */ - { - if (load_limit_index >= NUM_INACTIVE_LOAD_ARRAY) - { - load_limit_index = 0; - } - - if (msecs_limit_total > INACTIVE_DURATION_MSEC) - { - for (i=0; itimer_mutex); @@ -1601,11 +1818,15 @@ static void do_dbs_timer(struct work_struct *work) delay -= jiffies % delay; } } else { + if (input_event_boosted()) + goto sched_wait; + __cpufreq_driver_target(dbs_info->cur_policy, dbs_info->freq_lo, CPUFREQ_RELATION_H); delay = dbs_info->freq_lo_jiffies; } - schedule_delayed_work_on(cpu, &dbs_info->work, delay); +sched_wait: + queue_delayed_work_on(cpu, dbs_wq, &dbs_info->work, delay); mutex_unlock(&dbs_info->timer_mutex); } @@ -1619,7 +1840,7 @@ static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info) dbs_info->sample_type = DBS_NORMAL_SAMPLE; INIT_DELAYED_WORK_DEFERRABLE(&dbs_info->work, do_dbs_timer); - schedule_delayed_work_on(dbs_info->cpu, &dbs_info->work, delay); + queue_delayed_work_on(dbs_info->cpu, dbs_wq, &dbs_info->work, delay); } static inline void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info) @@ -1647,26 +1868,7 @@ static int should_io_be_busy(void) boot_cpu_data.x86_model >= 15) return 1; #endif -#if defined(CONFIG_ARM) - return 1; /* tread I/O as busy always for ARM */ -#else return 0; -#endif -} - -#define AID_SYSTEM (1000) -static void dbs_chown(void) -{ - int ret; - - ret = - sys_chown("/sys/devices/system/cpu/cpufreq/intellidemand/sampling_rate", - low2highuid(AID_SYSTEM), low2highgid(0)); - ret = - sys_chown("/sys/devices/system/cpu/cpufreq/intellidemand/boostpulse", - low2highuid(AID_SYSTEM), low2highgid(0)); - if (ret) - pr_err("sys_chown: boostpulse error: %d", ret); } static void dbs_refresh_callback(struct work_struct *work) @@ -1691,22 +1893,19 @@ static void dbs_refresh_callback(struct work_struct *work) goto bail_incorrect_governor; } - if (policy->cur < DBS_INPUT_EVENT_MIN_FREQ) { -#if 0 - pr_info("%s: set cpufreq to DBS_INPUT_EVENT_MIN_FREQ(%d) \ - directly due to input events!\n", __func__, \ - DBS_INPUT_EVENT_MIN_FREQ); -#endif + if (policy->cur < policy->max) { /* * Arch specific cpufreq driver may fail. * Don't update governor frequency upon failure. */ - if (__cpufreq_driver_target(policy, DBS_INPUT_EVENT_MIN_FREQ, - CPUFREQ_RELATION_L) >= 0); - policy->cur = DBS_INPUT_EVENT_MIN_FREQ; + if (__cpufreq_driver_target(policy, policy->max, + CPUFREQ_RELATION_L) >= 0) + policy->cur = policy->max; + this_dbs_info->prev_cpu_idle = get_cpu_idle_time(cpu, &this_dbs_info->prev_cpu_wall); } + bail_incorrect_governor: unlock_policy_rwsem_write(cpu); @@ -1715,56 +1914,163 @@ static void dbs_refresh_callback(struct work_struct *work) return; } -static unsigned int enable_dbs_input_event = 1; -static void dbs_input_event(struct input_handle *handle, unsigned int type, - unsigned int code, int value) +static int dbs_migration_notify(struct notifier_block *nb, + unsigned long target_cpu, void *arg) { - int i; + struct cpu_dbs_info_s *target_dbs_info = + &per_cpu(id_cpu_dbs_info, target_cpu); - if (enable_dbs_input_event) { + atomic_set(&target_dbs_info->src_sync_cpu, (int)arg); + wake_up(&target_dbs_info->sync_wq); - if ((dbs_tuners_ins.powersave_bias == POWERSAVE_BIAS_MAXLEVEL) || - (dbs_tuners_ins.powersave_bias == POWERSAVE_BIAS_MINLEVEL)) { - /* nothing to do */ - return; + return NOTIFY_OK; +} + +static struct notifier_block dbs_migration_nb = { + .notifier_call = dbs_migration_notify, +}; + +static int sync_pending(struct cpu_dbs_info_s *this_dbs_info) +{ + return atomic_read(&this_dbs_info->src_sync_cpu) >= 0; +} + +static int dbs_sync_thread(void *data) +{ + int src_cpu, cpu = (int)data; + unsigned int src_freq, src_max_load; + struct cpu_dbs_info_s *this_dbs_info, *src_dbs_info; + struct cpufreq_policy *policy; + int delay; + + this_dbs_info = &per_cpu(id_cpu_dbs_info, cpu); + + while (1) { + wait_event(this_dbs_info->sync_wq, + sync_pending(this_dbs_info) || + kthread_should_stop()); + + if (kthread_should_stop()) + break; + + get_online_cpus(); + + src_cpu = atomic_read(&this_dbs_info->src_sync_cpu); + src_dbs_info = &per_cpu(id_cpu_dbs_info, src_cpu); + if (src_dbs_info != NULL && + src_dbs_info->cur_policy != NULL) { + src_freq = src_dbs_info->cur_policy->cur; + src_max_load = src_dbs_info->max_load; + } else { + src_freq = dbs_tuners_ins.sync_freq; + src_max_load = 0; } - if (current_sampling_rate > BOOSTED_SAMPLING_RATE) { - dbs_tuners_ins.sampling_rate = BOOSTED_SAMPLING_RATE; - sampling_rate_boosted_time = ktime_to_us(ktime_get()); - sampling_rate_boosted = 1; + if (lock_policy_rwsem_write(cpu) < 0) + goto bail_acq_sema_failed; + + if (!atomic_read(&this_dbs_info->sync_enabled)) { + atomic_set(&this_dbs_info->src_sync_cpu, -1); + put_online_cpus(); + unlock_policy_rwsem_write(cpu); + continue; } - for_each_online_cpu(i) - queue_work_on(i, input_wq, &per_cpu(dbs_refresh_work, i).work); + policy = this_dbs_info->cur_policy; + if (!policy) { + /* CPU not using intellidemand governor */ + goto bail_incorrect_governor; + } + delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate); + + + if (policy->cur < src_freq) { + /* cancel the next intellidemand sample */ + cancel_delayed_work_sync(&this_dbs_info->work); + + /* + * Arch specific cpufreq driver may fail. + * Don't update governor frequency upon failure. + */ + if (__cpufreq_driver_target(policy, src_freq, + CPUFREQ_RELATION_L) >= 0) { + policy->cur = src_freq; + if (src_max_load > this_dbs_info->max_load) { + this_dbs_info->max_load = src_max_load; + this_dbs_info->prev_load = src_max_load; + } + } + + /* reschedule the next intellidemand sample */ + mutex_lock(&this_dbs_info->timer_mutex); + queue_delayed_work_on(cpu, dbs_wq, + &this_dbs_info->work, delay); + mutex_unlock(&this_dbs_info->timer_mutex); + } + +bail_incorrect_governor: + unlock_policy_rwsem_write(cpu); +bail_acq_sema_failed: + put_online_cpus(); + atomic_set(&this_dbs_info->src_sync_cpu, -1); + } + + return 0; +} + +static void dbs_input_event(struct input_handle *handle, unsigned int type, + unsigned int code, int value) +{ + int i; + struct cpu_dbs_info_s *dbs_info; + unsigned long flags; + int input_event_min_freq; + + if ((dbs_tuners_ins.powersave_bias == POWERSAVE_BIAS_MAXLEVEL) || + (dbs_tuners_ins.powersave_bias == POWERSAVE_BIAS_MINLEVEL)) { + /* nothing to do */ + return; + } + + if (type == EV_SYN && code == SYN_REPORT) { + spin_lock_irqsave(&input_boost_lock, flags); + input_event_boost = true; + ui_sampling_expired = jiffies + msecs_to_jiffies(dbs_tuners_ins.ui_timeout); + spin_unlock_irqrestore(&input_boost_lock, flags); + + input_event_min_freq = input_event_min_freq_array[num_online_cpus() - 1]; + for_each_online_cpu(i) { + dbs_info = &per_cpu(id_cpu_dbs_info, i); + if (dbs_info->cur_policy && + dbs_info->cur_policy->cur < input_event_min_freq) { + wake_up_process(per_cpu(up_task, i)); + } + } } } -#if 1 static int input_dev_filter(const char *input_dev_name) { - if (strstr(input_dev_name, "elan-touchscreen") || - strstr(input_dev_name, "-keypad") || - strstr(input_dev_name, "-nav") || - strstr(input_dev_name, "-oj")) { - return 0; + if (strstr(input_dev_name, "touchscreen") || + strstr(input_dev_name, "elan-touchscreen") || + strstr(input_dev_name, "touch_dev") || + strstr(input_dev_name, "sec-touchscreen") || + strstr(input_dev_name, "keypad")) { + return 0; } else { return 1; } } -#endif + static int dbs_input_connect(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id) { struct input_handle *handle; int error; - -#if 1 - /* filter out those input_dev that we don't care */ + if (input_dev_filter(dev->name)) return -ENODEV; -#endif handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL); if (!handle) @@ -1806,10 +2112,22 @@ static struct input_handler dbs_input_handler = { .event = dbs_input_event, .connect = dbs_input_connect, .disconnect = dbs_input_disconnect, - .name = "cpufreq_intelli", + .name = "cpufreq_ond", .id_table = dbs_ids, }; +int set_input_event_min_freq(int cpufreq) +{ + int i = 0; + for ( i = 0 ; i < NR_CPUS; i++) + input_event_min_freq_array[i] = cpufreq; + return 0; +} + +void set_input_event_min_freq_by_cpu ( int cpu_nr, int cpufreq){ + input_event_min_freq_array[cpu_nr-1] = cpufreq; +} + static int cpufreq_governor_dbs(struct cpufreq_policy *policy, unsigned int event) { @@ -1827,8 +2145,6 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, mutex_lock(&dbs_mutex); - dbs_chown(); - dbs_enable++; for_each_cpu(j, policy->cpus) { struct cpu_dbs_info_s *j_dbs_info; @@ -1837,13 +2153,17 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, j_dbs_info->prev_cpu_idle = get_cpu_idle_time(j, &j_dbs_info->prev_cpu_wall); - if (dbs_tuners_ins.ignore_nice) { - j_dbs_info->prev_cpu_nice - = kcpustat_cpu(j).cpustat[CPUTIME_NICE]; - } + if (dbs_tuners_ins.ignore_nice) + j_dbs_info->prev_cpu_nice = + kcpustat_cpu(j).cpustat[CPUTIME_NICE]; + set_cpus_allowed(j_dbs_info->sync_thread, + *cpumask_of(j)); + if (!dbs_tuners_ins.powersave_bias) + atomic_set(&j_dbs_info->sync_enabled, 1); } this_dbs_info->cpu = cpu; this_dbs_info->rate_mult = 1; + this_dbs_info->freq_stay_count = 1; intellidemand_powersave_bias_init_cpu(cpu); /* * Start the timerschedule work, when this governor @@ -1869,6 +2189,9 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, dbs_tuners_ins.sampling_rate = max(min_sampling_rate, latency * LATENCY_MULTIPLIER); + if (dbs_tuners_ins.sampling_rate < DEF_SAMPLING_RATE) + dbs_tuners_ins.sampling_rate = DEF_SAMPLING_RATE; + dbs_tuners_ins.origin_sampling_rate = dbs_tuners_ins.sampling_rate; dbs_tuners_ins.io_is_busy = should_io_be_busy(); if (dbs_tuners_ins.optimal_freq == 0) @@ -1876,11 +2199,15 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, if (dbs_tuners_ins.sync_freq == 0) dbs_tuners_ins.sync_freq = policy->min; + + atomic_notifier_chain_register(&migration_notifier_head, + &dbs_migration_nb); } if (!cpu) rc = input_register_handler(&dbs_input_handler); mutex_unlock(&dbs_mutex); + if (!intellidemand_powersave_bias_setspeed( this_dbs_info->cur_policy, NULL, @@ -1893,19 +2220,35 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, mutex_lock(&dbs_mutex); dbs_enable--; + + for_each_cpu(j, policy->cpus) { + struct cpu_dbs_info_s *j_dbs_info; + j_dbs_info = &per_cpu(id_cpu_dbs_info, j); + atomic_set(&j_dbs_info->sync_enabled, 0); + } + /* If device is being removed, policy is no longer * valid. */ this_dbs_info->cur_policy = NULL; if (!cpu) input_unregister_handler(&dbs_input_handler); - if (!dbs_enable) + if (!dbs_enable) { sysfs_remove_group(cpufreq_global_kobject, &dbs_attr_group); + atomic_notifier_chain_unregister( + &migration_notifier_head, + &dbs_migration_nb); + } + mutex_unlock(&dbs_mutex); break; case CPUFREQ_GOV_LIMITS: + if (this_dbs_info->cur_policy == NULL) { + pr_debug("Unable to limit cpu freq due to cur_policy == NULL\n"); + return -EPERM; + } mutex_lock(&this_dbs_info->timer_mutex); if (policy->max < this_dbs_info->cur_policy->cur) __cpufreq_driver_target(this_dbs_info->cur_policy, @@ -1924,8 +2267,60 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, return 0; } -#ifdef CONFIG_EARLYSUSPEND -static void cpufreq_intellidemand_early_suspend(struct early_suspend *h) +static int cpufreq_gov_dbs_up_task(void *data) +{ + struct cpufreq_policy *policy; + struct cpu_dbs_info_s *this_dbs_info; + unsigned int cpu = smp_processor_id(); + int input_event_min_freq; + + while (1) { + set_current_state(TASK_INTERRUPTIBLE); + schedule(); + + if (kthread_should_stop()) + break; + + set_current_state(TASK_RUNNING); + + get_online_cpus(); + + if (lock_policy_rwsem_write(cpu) < 0) + goto bail_acq_sema_failed; + + this_dbs_info = &per_cpu(id_cpu_dbs_info, cpu); + policy = this_dbs_info->cur_policy; + if (!policy) { + + goto bail_incorrect_governor; + } + + mutex_lock(&this_dbs_info->timer_mutex); + + input_event_min_freq = input_event_min_freq_array[num_online_cpus() - 1]; + if (policy->cur < input_event_min_freq) { + + dbs_tuners_ins.powersave_bias = 0; + dbs_freq_increase(policy, input_event_min_freq); + this_dbs_info->prev_cpu_idle = get_cpu_idle_time(cpu, &this_dbs_info->prev_cpu_wall); + } + + mutex_unlock(&this_dbs_info->timer_mutex); + +bail_incorrect_governor: + unlock_policy_rwsem_write(cpu); + +bail_acq_sema_failed: + put_online_cpus(); + + dbs_tuners_ins.sampling_rate = dbs_tuners_ins.ui_sampling_rate; + } + + return 0; +} + +#if 0 +static void cpufreq_intellidemand_power_suspend(struct power_suspend *h) { mutex_lock(&dbs_mutex); stored_sampling_rate = dbs_tuners_ins.sampling_rate; @@ -1934,7 +2329,7 @@ static void cpufreq_intellidemand_early_suspend(struct early_suspend *h) mutex_unlock(&dbs_mutex); } -static void cpufreq_intellidemand_late_resume(struct early_suspend *h) +static void cpufreq_intellidemand_power_resume(struct power_suspend *h) { mutex_lock(&dbs_mutex); dbs_tuners_ins.sampling_rate = stored_sampling_rate; @@ -1942,10 +2337,9 @@ static void cpufreq_intellidemand_late_resume(struct early_suspend *h) mutex_unlock(&dbs_mutex); } -static struct early_suspend cpufreq_intellidemand_early_suspend_info = { - .suspend = cpufreq_intellidemand_early_suspend, - .resume = cpufreq_intellidemand_late_resume, - .level = EARLY_SUSPEND_LEVEL_DISABLE_FB+1, +static struct power_suspend cpufreq_intellidemand_power_suspend_info = { + .suspend = cpufreq_intellidemand_power_suspend, + .resume = cpufreq_intellidemand_power_resume, }; #endif @@ -1953,6 +2347,8 @@ static int __init cpufreq_gov_dbs_init(void) { u64 idle_time; unsigned int i; + struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 }; + struct task_struct *pthread; int cpu = get_cpu(); idle_time = get_cpu_idle_time_us(cpu, NULL); @@ -1963,7 +2359,7 @@ static int __init cpufreq_gov_dbs_init(void) dbs_tuners_ins.down_differential = MICRO_FREQUENCY_DOWN_DIFFERENTIAL; /* - * In no_hz/micro accounting case we set the minimum frequency + * In nohz/micro accounting case we set the minimum frequency * not depending on HZ, but fixed (very low). The deferred * timer might skip some samples if idle/sleeping as needed. */ @@ -1974,9 +2370,9 @@ static int __init cpufreq_gov_dbs_init(void) MIN_SAMPLING_RATE_RATIO * jiffies_to_usecs(10); } - input_wq = create_workqueue("iewq"); - if (!input_wq) { - printk(KERN_ERR "Failed to create iewq workqueue\n"); + dbs_wq = alloc_workqueue("intellidemand_dbs_wq", WQ_HIGHPRI, 0); + if (!dbs_wq) { + printk(KERN_ERR "Failed to create intellidemand_dbs_wq workqueue\n"); return -EFAULT; } for_each_possible_cpu(i) { @@ -1985,13 +2381,30 @@ static int __init cpufreq_gov_dbs_init(void) struct dbs_work_struct *dbs_work = &per_cpu(dbs_refresh_work, i); + pthread = kthread_create_on_node(cpufreq_gov_dbs_up_task, + NULL, cpu_to_node(i), + "kdbs_up/%d", i); + if (likely(!IS_ERR(pthread))) { + kthread_bind(pthread, i); + sched_setscheduler_nocheck(pthread, SCHED_FIFO, ¶m); + get_task_struct(pthread); + per_cpu(up_task, i) = pthread; + } + mutex_init(&this_dbs_info->timer_mutex); INIT_WORK(&dbs_work->work, dbs_refresh_callback); dbs_work->cpu = i; + + atomic_set(&this_dbs_info->src_sync_cpu, -1); + init_waitqueue_head(&this_dbs_info->sync_wq); + + this_dbs_info->sync_thread = kthread_run(dbs_sync_thread, + (void *)i, + "dbs_sync/%d", i); } -#ifdef CONFIG_EARLYSUSPEND - register_early_suspend(&cpufreq_intellidemand_early_suspend_info); +#if 0 + register_power_suspend(&cpufreq_intellidemand_power_suspend_info); #endif return cpufreq_register_governor(&cpufreq_gov_intellidemand); } @@ -2005,30 +2418,19 @@ static void __exit cpufreq_gov_dbs_exit(void) struct cpu_dbs_info_s *this_dbs_info = &per_cpu(id_cpu_dbs_info, i); mutex_destroy(&this_dbs_info->timer_mutex); + kthread_stop(this_dbs_info->sync_thread); + if (per_cpu(up_task, i)) { + kthread_stop(per_cpu(up_task, i)); + put_task_struct(per_cpu(up_task, i)); + } } -#ifdef CONFIG_EARLYSUSPEND - unregister_early_suspend(&cpufreq_intellidemand_early_suspend_info); -#endif - destroy_workqueue(input_wq); -} - -static int set_enable_dbs_input_event_param(const char *val, struct kernel_param *kp) -{ - int ret = 0; - - ret = param_set_uint(val, kp); - if (ret) - pr_err("%s: error setting value %d\n", __func__, ret); - - return ret; + destroy_workqueue(dbs_wq); } -module_param_call(enable_dbs_input_event, set_enable_dbs_input_event_param, param_get_uint, - &enable_dbs_input_event, S_IWUSR | S_IRUGO); MODULE_AUTHOR("Venkatesh Pallipadi "); MODULE_AUTHOR("Alexey Starikovskiy "); MODULE_AUTHOR("Paul Reioux "); -MODULE_DESCRIPTION("'cpufreq_intellidemand' - An intelligent dynamic cpufreq governor for " +MODULE_DESCRIPTION("'cpufreq_intellidemand' - A dynamic cpufreq governor for " "Low Latency Frequency Transition capable processors"); MODULE_LICENSE("GPL"); From 73c74eb6c98e11b067945cd0bf8f280c130cf82c Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Tue, 10 Dec 2013 17:30:36 +0100 Subject: [PATCH 026/215] intellidemand: minor clean up and tailor for APQ8064 devices Signed-off-by: Paul Reioux --- drivers/cpufreq/cpufreq_intellidemand.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/cpufreq/cpufreq_intellidemand.c b/drivers/cpufreq/cpufreq_intellidemand.c index cb0a36bce89..35f849e93f2 100644 --- a/drivers/cpufreq/cpufreq_intellidemand.c +++ b/drivers/cpufreq/cpufreq_intellidemand.c @@ -52,15 +52,15 @@ #define MIN_FREQUENCY_UP_THRESHOLD (11) #define MAX_FREQUENCY_UP_THRESHOLD (100) #define MIN_FREQUENCY_DOWN_DIFFERENTIAL (1) -#define DBS_INPUT_EVENT_MIN_FREQ (1190400) +#define DBS_INPUT_EVENT_MIN_FREQ (1242000) #define DEF_UI_DYNAMIC_SAMPLING_RATE (30000) #define DBS_UI_SAMPLING_MIN_TIMEOUT (30) #define DBS_UI_SAMPLING_MAX_TIMEOUT (1000) #define DBS_UI_SAMPLING_TIMEOUT (80) #define DEF_FREQ_STEP (25) -#define DEF_STEP_UP_EARLY_HISPEED (1190400) -#define DEF_STEP_UP_INTERIM_HISPEED (1728000) +#define DEF_STEP_UP_EARLY_HISPEED (1134000) +#define DEF_STEP_UP_INTERIM_HISPEED (1350000) #define DEF_SAMPLING_EARLY_HISPEED_FACTOR (2) #define DEF_SAMPLING_INTERIM_HISPEED_FACTOR (3) @@ -82,22 +82,22 @@ static unsigned long stored_sampling_rate; #endif #if defined(SMART_UP_PLUS) -static unsigned int SUP_THRESHOLD_STEPS[SUP_MAX_STEP] = {75, 85, 90}; +static unsigned int SUP_THRESHOLD_STEPS[SUP_MAX_STEP] = {75, 85, 95}; static unsigned int SUP_FREQ_STEPS[SUP_MAX_STEP] = {4, 3, 2}; //static unsigned int min_range = 108000; typedef struct{ unsigned int freq_idx; unsigned int freq_value; } freq_table_idx; -freq_table_idx pre_freq_idx[SUP_CORE_NUM] = {}; +static freq_table_idx pre_freq_idx[SUP_CORE_NUM] = {}; #endif #if defined(SMART_UP_SLOW_UP_AT_HIGH_FREQ) -#define SUP_SLOW_UP_FREQUENCY (1574400) -#define SUP_HIGH_SLOW_UP_FREQUENCY (1728000) +#define SUP_SLOW_UP_FREQUENCY (1350000) +#define SUP_HIGH_SLOW_UP_FREQUENCY (1512000) #define SUP_SLOW_UP_LOAD (90) typedef struct { @@ -105,14 +105,14 @@ typedef struct { unsigned int hist_load_cnt; } history_load; static void reset_hist(history_load *hist_load); -history_load hist_load[SUP_CORE_NUM] = {}; +static history_load hist_load[SUP_CORE_NUM] = {}; typedef struct { unsigned int hist_max_load[SUP_HIGH_SLOW_UP_DUR]; unsigned int hist_load_cnt; } history_load_high; static void reset_hist_high(history_load_high *hist_load); -history_load_high hist_load_high[SUP_CORE_NUM] = {}; +static history_load_high hist_load_high[SUP_CORE_NUM] = {}; #endif @@ -1177,7 +1177,7 @@ static ssize_t store_step_up_interim_hispeed(struct kobject *a, int ret; ret = sscanf(buf, "%u", &input); - if (ret != 1 || input > 2265600 || + if (ret != 1 || input > 1512000 || input < 0) { return -EINVAL; } From 80c90f6c0a21981d7cc0a7df2b526f7beae010b1 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Tue, 10 Dec 2013 17:31:10 +0100 Subject: [PATCH 027/215] intelli_plug: tune for tablet devices Signed-off-by: Paul Reioux --- arch/arm/mach-msm/intelli_plug.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/arm/mach-msm/intelli_plug.c b/arch/arm/mach-msm/intelli_plug.c index 3a7d739a365..ffaa9a8cc0b 100644 --- a/arch/arm/mach-msm/intelli_plug.c +++ b/arch/arm/mach-msm/intelli_plug.c @@ -29,14 +29,14 @@ #define INTELLI_PLUG_MAJOR_VERSION 2 #define INTELLI_PLUG_MINOR_VERSION 0 -#define DEF_SAMPLING_MS (1000) -#define BUSY_SAMPLING_MS (500) +#define DEF_SAMPLING_MS (500) +#define BUSY_SAMPLING_MS (250) -#define DUAL_CORE_PERSISTENCE 7 -#define TRI_CORE_PERSISTENCE 5 -#define QUAD_CORE_PERSISTENCE 3 +#define DUAL_CORE_PERSISTENCE 14 +#define TRI_CORE_PERSISTENCE 10 +#define QUAD_CORE_PERSISTENCE 6 -#define BUSY_PERSISTENCE 10 +#define BUSY_PERSISTENCE 20 #define RUN_QUEUE_THRESHOLD 38 From 46a069759005e953a2b48d28e3954e88d0901ac4 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Tue, 10 Dec 2013 17:41:25 +0100 Subject: [PATCH 028/215] Merge with kitkat-mr1 Signed-off-by: Tk-Glitch --- arch/arm/configs/flo_defconfig | 2 +- drivers/gpu/msm/adreno.c | 31 +- drivers/gpu/msm/adreno.h | 21 +- drivers/gpu/msm/adreno_a2xx.c | 89 +++--- drivers/gpu/msm/adreno_a3xx.c | 69 ++--- drivers/gpu/msm/adreno_a4xx.c | 66 ----- drivers/gpu/msm/adreno_dispatch.c | 147 ++++------ drivers/gpu/msm/adreno_drawctxt.c | 146 +++++++--- drivers/gpu/msm/adreno_drawctxt.h | 28 +- drivers/gpu/msm/adreno_postmortem.c | 2 +- drivers/gpu/msm/adreno_ringbuffer.c | 12 +- drivers/gpu/msm/adreno_trace.h | 19 +- drivers/gpu/msm/kgsl.c | 269 +++++++++++------- drivers/gpu/msm/kgsl.h | 2 + drivers/gpu/msm/kgsl_device.h | 5 +- drivers/gpu/msm/kgsl_events.c | 14 - drivers/gpu/msm/kgsl_pwrctrl.c | 5 +- drivers/gpu/msm/kgsl_pwrctrl.h | 4 +- drivers/gpu/msm/z180.c | 22 +- .../platform/msm/camera_v2/camera/camera.c | 9 +- .../msm/camera_v2/gemini/msm_gemini_hw.c | 2 +- .../msm/camera_v2/gemini/msm_gemini_hw.h | 2 +- .../msm/camera_v2/gemini/msm_gemini_sync.c | 11 +- .../platform/msm/camera_v2/isp/msm_isp32.c | 15 +- .../platform/msm/camera_v2/isp/msm_isp_util.c | 6 +- drivers/media/platform/msm/camera_v2/msm.c | 13 +- .../msm/camera_v2/sensor/cci/msm_cci.c | 20 +- drivers/power/smb345-charger.c | 12 + .../staging/prima/CORE/HDD/inc/wlan_hdd_cfg.h | 10 +- .../prima/CORE/HDD/inc/wlan_hdd_main.h | 8 +- .../prima/CORE/HDD/inc/wlan_hdd_tdls.h | 10 + .../prima/CORE/HDD/src/wlan_hdd_assoc.c | 9 +- .../staging/prima/CORE/HDD/src/wlan_hdd_cfg.c | 6 + .../prima/CORE/HDD/src/wlan_hdd_cfg80211.c | 77 +++-- .../CORE/HDD/src/wlan_hdd_early_suspend.c | 91 ++++-- .../prima/CORE/HDD/src/wlan_hdd_tdls.c | 155 +++++++++- .../prima/CORE/MAC/inc/qwlan_version.h | 4 +- drivers/usb/otg/msm_otg.c | 11 +- drivers/video/msm/mdp4_overlay.c | 9 + .../video/msm/vidc/common/enc/venc_internal.c | 40 ++- include/linux/usb/msm_hsusb.h | 1 + net/core/flow_dissector.c | 4 +- sound/soc/codecs/wcd9310.c | 21 +- sound/soc/msm/asustek_headset.c | 16 +- 44 files changed, 986 insertions(+), 529 deletions(-) diff --git a/arch/arm/configs/flo_defconfig b/arch/arm/configs/flo_defconfig index a1bd6a77d6f..926fdc9f6ad 100644 --- a/arch/arm/configs/flo_defconfig +++ b/arch/arm/configs/flo_defconfig @@ -960,7 +960,7 @@ CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y # CONFIG_NETFILTER_XT_TARGET_TPROXY is not set # CONFIG_NETFILTER_XT_TARGET_TRACE is not set CONFIG_NETFILTER_XT_TARGET_SECMARK=y -# CONFIG_NETFILTER_XT_TARGET_TCPMSS is not set +CONFIG_NETFILTER_XT_TARGET_TCPMSS=y # CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set # diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index 8a9f00e9124..85016cd1755 100644 --- a/drivers/gpu/msm/adreno.c +++ b/drivers/gpu/msm/adreno.c @@ -1873,7 +1873,7 @@ static int adreno_start(struct kgsl_device *device) goto error_rb_stop; /* Start the dispatcher */ - adreno_dispatcher_start(adreno_dev); + adreno_dispatcher_start(device); device->reset_counter++; @@ -2573,14 +2573,13 @@ int adreno_idle(struct kgsl_device *device) * adreno_drain() - Drain the dispatch queue * @device: Pointer to the KGSL device structure for the GPU * - * Tell the dispatcher to pause - this has the effect of draining the inflight - * command batches + * Drain the dispatcher of existing command batches. This halts + * additional commands from being issued until the gate is completed. */ static int adreno_drain(struct kgsl_device *device) { - struct adreno_device *adreno_dev = ADRENO_DEVICE(device); + INIT_COMPLETION(device->cmdbatch_gate); - adreno_dispatcher_pause(adreno_dev); return 0; } @@ -2882,8 +2881,17 @@ static long adreno_ioctl(struct kgsl_device_private *dev_priv, } case IOCTL_KGSL_PERFCOUNTER_GET: { struct kgsl_perfcounter_get *get = data; + /* + * adreno_perfcounter_get() is called by kernel clients + * during start(), so it is not safe to take an + * active count inside this function. + */ + result = kgsl_active_count_get(device); + if (result) + break; result = adreno_perfcounter_get(adreno_dev, get->groupid, get->countable, &get->offset, PERFCOUNTER_FLAG_NONE); + kgsl_active_count_put(device); break; } case IOCTL_KGSL_PERFCOUNTER_PUT: { @@ -2901,8 +2909,12 @@ static long adreno_ioctl(struct kgsl_device_private *dev_priv, } case IOCTL_KGSL_PERFCOUNTER_READ: { struct kgsl_perfcounter_read *read = data; + result = kgsl_active_count_get(device); + if (result) + break; result = adreno_perfcounter_read_group(adreno_dev, read->reads, read->count); + kgsl_active_count_put(device); break; } default: @@ -2979,13 +2991,6 @@ static unsigned int adreno_gpuid(struct kgsl_device *device, return (0x0003 << 16) | ((int) adreno_dev->gpurev); } -static void adreno_resume(struct kgsl_device *device) -{ - struct adreno_device *adreno_dev = ADRENO_DEVICE(device); - - adreno_dispatcher_resume(adreno_dev); -} - static const struct kgsl_functable adreno_functable = { /* Mandatory functions */ .regread = adreno_regread, @@ -3017,7 +3022,7 @@ static const struct kgsl_functable adreno_functable = { .setproperty = adreno_setproperty, .postmortem_dump = adreno_dump, .drawctxt_sched = adreno_drawctxt_sched, - .resume = adreno_resume, + .resume = adreno_dispatcher_start, }; static struct platform_driver adreno_platform_driver = { diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h index b271f838ff9..d419292ed37 100644 --- a/drivers/gpu/msm/adreno.h +++ b/drivers/gpu/msm/adreno.h @@ -126,7 +126,7 @@ enum coresight_debug_reg { */ struct adreno_dispatcher { struct mutex mutex; - unsigned int state; + unsigned long priv; struct timer_list timer; struct timer_list fault_timer; unsigned int inflight; @@ -140,6 +140,10 @@ struct adreno_dispatcher { struct kobject kobj; }; +enum adreno_dispatcher_flags { + ADRENO_DISPATCHER_POWER = 0, +}; + struct adreno_gpudev; struct adreno_device { @@ -357,10 +361,6 @@ struct adreno_gpudev { /* GPU specific function hooks */ int (*ctxt_create)(struct adreno_device *, struct adreno_context *); - int (*ctxt_save)(struct adreno_device *, struct adreno_context *); - int (*ctxt_restore)(struct adreno_device *, struct adreno_context *); - int (*ctxt_draw_workaround)(struct adreno_device *, - struct adreno_context *); irqreturn_t (*irq_handler)(struct adreno_device *); void (*irq_control)(struct adreno_device *, int); unsigned int (*irq_pending)(struct adreno_device *); @@ -408,6 +408,14 @@ struct log_field { #define KGSL_FT_PAGEFAULT_LOG_ONE_PER_INT BIT(3) #define KGSL_FT_PAGEFAULT_DEFAULT_POLICY KGSL_FT_PAGEFAULT_INT_ENABLE +#define ADRENO_FT_TYPES \ + { BIT(KGSL_FT_OFF), "off" }, \ + { BIT(KGSL_FT_REPLAY), "replay" }, \ + { BIT(KGSL_FT_SKIPIB), "skipib" }, \ + { BIT(KGSL_FT_SKIPFRAME), "skipframe" }, \ + { BIT(KGSL_FT_DISABLE), "disable" }, \ + { BIT(KGSL_FT_TEMP_DISABLE), "temp" } + #define ADRENO_FT_TYPES \ { BIT(KGSL_FT_OFF), "off" }, \ { BIT(KGSL_FT_REPLAY), "replay" }, \ @@ -479,7 +487,7 @@ struct kgsl_memdesc *adreno_find_ctxtmem(struct kgsl_device *device, void *adreno_snapshot(struct kgsl_device *device, void *snapshot, int *remain, int hang); -void adreno_dispatcher_start(struct adreno_device *adreno_dev); +void adreno_dispatcher_start(struct kgsl_device *device); int adreno_dispatcher_init(struct adreno_device *adreno_dev); void adreno_dispatcher_close(struct adreno_device *adreno_dev); int adreno_dispatcher_idle(struct adreno_device *adreno_dev, @@ -493,7 +501,6 @@ int adreno_dispatcher_queue_cmd(struct adreno_device *adreno_dev, void adreno_dispatcher_schedule(struct kgsl_device *device); void adreno_dispatcher_pause(struct adreno_device *adreno_dev); -void adreno_dispatcher_resume(struct adreno_device *adreno_dev); void adreno_dispatcher_queue_context(struct kgsl_device *device, struct adreno_context *drawctxt); int adreno_reset(struct kgsl_device *device); diff --git a/drivers/gpu/msm/adreno_a2xx.c b/drivers/gpu/msm/adreno_a2xx.c index 1f4544fbcdd..a5987afaad8 100644 --- a/drivers/gpu/msm/adreno_a2xx.c +++ b/drivers/gpu/msm/adreno_a2xx.c @@ -1398,11 +1398,56 @@ static int a2xx_create_gmem_shadow(struct adreno_device *adreno_dev, return 0; } +static void a2xx_drawctxt_detach(struct adreno_context *drawctxt) +{ + kgsl_sharedmem_free(&drawctxt->gpustate); + kgsl_sharedmem_free(&drawctxt->context_gmem_shadow.gmemshadow); +} + +static int a2xx_drawctxt_save(struct adreno_device *adreno_dev, + struct adreno_context *context); + +static int a2xx_drawctxt_restore(struct adreno_device *adreno_dev, + struct adreno_context *context); + +static int a2xx_drawctxt_draw_workaround(struct adreno_device *adreno_dev, + struct adreno_context *context); + +static const struct adreno_context_ops a225_preamble_ctx_ops = { + .restore = adreno_context_restore, + .draw_workaround = a2xx_drawctxt_draw_workaround, +}; + +static const struct adreno_context_ops a225_legacy_ctx_ops = { + .save = a2xx_drawctxt_save, + .restore = a2xx_drawctxt_restore, + .draw_workaround = a2xx_drawctxt_draw_workaround, + .detach = a2xx_drawctxt_detach, +}; + +static const struct adreno_context_ops a2xx_legacy_ctx_ops = { + .save = a2xx_drawctxt_save, + .restore = a2xx_drawctxt_restore, + .detach = a2xx_drawctxt_detach, +}; + + static int a2xx_drawctxt_create(struct adreno_device *adreno_dev, struct adreno_context *drawctxt) { int ret; + if (drawctxt->flags & CTXT_FLAGS_PREAMBLE + && drawctxt->flags & CTXT_FLAGS_NOGMEMALLOC) { + drawctxt->ops = (adreno_is_a225(adreno_dev)) + ? &a225_preamble_ctx_ops : &adreno_preamble_ctx_ops; + + return 0; + } + + drawctxt->ops = (adreno_is_a225(adreno_dev)) + ? &a225_legacy_ctx_ops : &a2xx_legacy_ctx_ops; + /* * Allocate memory for the GPU state and the context commands. * Despite the name, this is much more then just storage for @@ -1510,12 +1555,6 @@ static int a2xx_drawctxt_save(struct adreno_device *adreno_dev, struct kgsl_device *device = &adreno_dev->dev; int ret; - if (context == NULL || (context->flags & CTXT_FLAGS_BEING_DESTROYED)) - return 0; - - if (context->state == ADRENO_CONTEXT_STATE_INVALID) - return 0; - if (!(context->flags & CTXT_FLAGS_PREAMBLE)) { kgsl_cffdump_syncmem(context->base.device, &context->gpustate, context->reg_save[1], @@ -1597,40 +1636,14 @@ static int a2xx_drawctxt_restore(struct adreno_device *adreno_dev, struct adreno_context *context) { struct kgsl_device *device = &adreno_dev->dev; - unsigned int cmds[5]; - int ret = 0; - - if (context == NULL) { - /* No context - set the default pagetable and thats it */ - unsigned int id; - /* - * If there isn't a current context, the kgsl_mmu_setstate - * will use the CPU path so we don't need to give - * it a valid context id. - */ - id = (adreno_dev->drawctxt_active != NULL) - ? adreno_dev->drawctxt_active->base.id - : KGSL_CONTEXT_INVALID; - kgsl_mmu_setstate(&device->mmu, device->mmu.defaultpagetable, - id); - return 0; - } + int ret; - cmds[0] = cp_nop_packet(1); - cmds[1] = KGSL_CONTEXT_TO_MEM_IDENTIFIER; - cmds[2] = cp_type3_packet(CP_MEM_WRITE, 2); - cmds[3] = device->memstore.gpuaddr + - KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, current_context); - cmds[4] = context->base.id; - ret = adreno_ringbuffer_issuecmds(device, context, KGSL_CMD_FLAGS_NONE, - cmds, 5); + ret = adreno_context_restore(adreno_dev, context); if (ret) return ret; - kgsl_mmu_setstate(&device->mmu, context->base.proc_priv->pagetable, - context->base.id); - - /* restore gmem. + /* + * restore gmem. * (note: changes shader. shader must not already be restored.) */ if (context->flags & CTXT_FLAGS_GMEM_RESTORE) { @@ -1689,6 +1702,7 @@ static int a2xx_drawctxt_restore(struct adreno_device *adreno_dev, } if (adreno_is_a20x(adreno_dev)) { + unsigned int cmds[2]; cmds[0] = cp_type3_packet(CP_SET_BIN_BASE_OFFSET, 1); cmds[1] = context->bin_base_offset; ret = adreno_ringbuffer_issuecmds(device, context, @@ -2293,9 +2307,6 @@ struct adreno_gpudev adreno_a2xx_gpudev = { .reg_offsets = &a2xx_reg_offsets, .ctxt_create = a2xx_drawctxt_create, - .ctxt_save = a2xx_drawctxt_save, - .ctxt_restore = a2xx_drawctxt_restore, - .ctxt_draw_workaround = a2xx_drawctxt_draw_workaround, .irq_handler = a2xx_irq_handler, .irq_control = a2xx_irq_control, .irq_pending = a2xx_irq_pending, diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c index b563c13fcd3..3934226fdfd 100644 --- a/drivers/gpu/msm/adreno_a3xx.c +++ b/drivers/gpu/msm/adreno_a3xx.c @@ -2343,17 +2343,40 @@ static int a3xx_create_gmem_shadow(struct adreno_device *adreno_dev, return 0; } +static void a3xx_drawctxt_detach(struct adreno_context *drawctxt) +{ + kgsl_sharedmem_free(&drawctxt->gpustate); + kgsl_sharedmem_free(&drawctxt->context_gmem_shadow.gmemshadow); +} + +static int a3xx_drawctxt_save(struct adreno_device *adreno_dev, + struct adreno_context *context); + +static int a3xx_drawctxt_restore(struct adreno_device *adreno_dev, + struct adreno_context *context); + +static const struct adreno_context_ops a3xx_legacy_ctx_ops = { + .save = a3xx_drawctxt_save, + .restore = a3xx_drawctxt_restore, + .detach = a3xx_drawctxt_detach, +}; + + static int a3xx_drawctxt_create(struct adreno_device *adreno_dev, struct adreno_context *drawctxt) { int ret; /* - * Allocate memory for the GPU state and the context commands. - * Despite the name, this is much more then just storage for - * the gpustate. This contains command space for gmem save - * and texture and vertex buffer storage too + * Nothing to do here if the context is using preambles and doesn't need + * GMEM save/restore */ + if ((drawctxt->flags & CTXT_FLAGS_PREAMBLE) && + (drawctxt->flags & CTXT_FLAGS_NOGMEMALLOC)) { + drawctxt->ops = &adreno_preamble_ctx_ops; + return 0; + } + drawctxt->ops = &a3xx_legacy_ctx_ops; ret = kgsl_allocate(&drawctxt->gpustate, drawctxt->base.proc_priv->pagetable, CONTEXT_SIZE); @@ -2389,9 +2412,6 @@ static int a3xx_drawctxt_save(struct adreno_device *adreno_dev, struct kgsl_device *device = &adreno_dev->dev; int ret; - if (context == NULL || (context->flags & CTXT_FLAGS_BEING_DESTROYED)) - return 0; - if (context->state == ADRENO_CONTEXT_STATE_INVALID) return 0; @@ -2449,39 +2469,13 @@ static int a3xx_drawctxt_restore(struct adreno_device *adreno_dev, struct adreno_context *context) { struct kgsl_device *device = &adreno_dev->dev; - unsigned int cmds[5]; - int ret = 0; - - if (context == NULL) { - /* No context - set the default pagetable and thats it */ - unsigned int id; - /* - * If there isn't a current context, the kgsl_mmu_setstate - * will use the CPU path so we don't need to give - * it a valid context id. - */ - id = (adreno_dev->drawctxt_active != NULL) - ? adreno_dev->drawctxt_active->base.id - : KGSL_CONTEXT_INVALID; - kgsl_mmu_setstate(&device->mmu, device->mmu.defaultpagetable, - id); - return 0; - } + int ret; - cmds[0] = cp_nop_packet(1); - cmds[1] = KGSL_CONTEXT_TO_MEM_IDENTIFIER; - cmds[2] = cp_type3_packet(CP_MEM_WRITE, 2); - cmds[3] = device->memstore.gpuaddr + - KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, current_context); - cmds[4] = context->base.id; - ret = adreno_ringbuffer_issuecmds(device, context, KGSL_CMD_FLAGS_NONE, - cmds, 5); + /* do the common part */ + ret = adreno_context_restore(adreno_dev, context); if (ret) return ret; - kgsl_mmu_setstate(&device->mmu, context->base.proc_priv->pagetable, - context->base.id); - /* * Restore GMEM. (note: changes shader. * Shader must not already be restored.) @@ -4384,9 +4378,6 @@ struct adreno_gpudev adreno_a3xx_gpudev = { .perfcounters = &a3xx_perfcounters, .ctxt_create = a3xx_drawctxt_create, - .ctxt_save = a3xx_drawctxt_save, - .ctxt_restore = a3xx_drawctxt_restore, - .ctxt_draw_workaround = NULL, .rb_init = a3xx_rb_init, .perfcounter_init = a3xx_perfcounter_init, .perfcounter_close = a3xx_perfcounter_close, diff --git a/drivers/gpu/msm/adreno_a4xx.c b/drivers/gpu/msm/adreno_a4xx.c index 90d816b49d7..9f8b75837eb 100644 --- a/drivers/gpu/msm/adreno_a4xx.c +++ b/drivers/gpu/msm/adreno_a4xx.c @@ -106,70 +106,6 @@ const unsigned int a4xx_registers[] = { const unsigned int a4xx_registers_count = ARRAY_SIZE(a4xx_registers) / 2; -static int a4xx_drawctxt_create(struct adreno_device *adreno_dev, - struct adreno_context *drawctxt) -{ - int ret = 0; - struct kgsl_device *device = &adreno_dev->dev; - - if (!(drawctxt->flags & CTXT_FLAGS_PREAMBLE)) { - /* This option is not supported on a4xx */ - KGSL_DRV_ERR(device, - "Preambles required for A4XX draw contexts\n"); - ret = -EPERM; - goto done; - } - - if (!(drawctxt->flags & CTXT_FLAGS_NOGMEMALLOC)) { - /* This option is not supported on a4xx */ - KGSL_DRV_ERR(device, - "Cannot create context with gmemalloc\n"); - ret = -EPERM; - } - -done: - return ret; -} - -static int a4xx_drawctxt_restore(struct adreno_device *adreno_dev, - struct adreno_context *context) -{ - struct kgsl_device *device = &adreno_dev->dev; - unsigned int cmds[5]; - int ret; - - if (context == NULL) { - /* No context - set the default pagetable and thats it */ - unsigned int id; - /* - * If there isn't a current context, the kgsl_mmu_setstate - * will use the CPU path so we don't need to give - * it a valid context id. - */ - id = (adreno_dev->drawctxt_active != NULL) - ? adreno_dev->drawctxt_active->base.id - : KGSL_CONTEXT_INVALID; - kgsl_mmu_setstate(&device->mmu, device->mmu.defaultpagetable, - id); - return 0; - } - - cmds[0] = cp_nop_packet(1); - cmds[1] = KGSL_CONTEXT_TO_MEM_IDENTIFIER; - cmds[2] = cp_type3_packet(CP_MEM_WRITE, 2); - cmds[3] = device->memstore.gpuaddr + - KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, current_context); - cmds[4] = context->base.id; - ret = adreno_ringbuffer_issuecmds(device, context, KGSL_CMD_FLAGS_NONE, - cmds, 5); - if (ret) - return ret; - ret = kgsl_mmu_setstate(&device->mmu, - context->base.proc_priv->pagetable, - context->base.id); - return ret; -} - static const struct adreno_vbif_data a420_vbif[] = { { A4XX_VBIF_ABIT_SORT, 0x0001001F }, { A4XX_VBIF_ABIT_SORT_CONF, 0x000000A4 }, @@ -294,8 +230,6 @@ const struct adreno_reg_offsets a4xx_reg_offsets = { struct adreno_gpudev adreno_a4xx_gpudev = { .reg_offsets = &a4xx_reg_offsets, - .ctxt_create = a4xx_drawctxt_create, - .ctxt_restore = a4xx_drawctxt_restore, .rb_init = a3xx_rb_init, .irq_control = a3xx_irq_control, .irq_handler = a3xx_irq_handler, diff --git a/drivers/gpu/msm/adreno_dispatch.c b/drivers/gpu/msm/adreno_dispatch.c index 3bcc7a3bb8f..357242f4eaf 100644 --- a/drivers/gpu/msm/adreno_dispatch.c +++ b/drivers/gpu/msm/adreno_dispatch.c @@ -22,13 +22,6 @@ #include "adreno_ringbuffer.h" #include "adreno_trace.h" -#define ADRENO_DISPATCHER_ACTIVE 0 -#define ADRENO_DISPATCHER_PAUSE 1 - -#define ADRENO_DISPATCHER_SOFT_FAULT 1 -#define ADRENO_DISPATCHER_HARD_FAULT 2 -#define ADRENO_DISPATCHER_TIMEOUT_FAULT 3 - #define CMDQUEUE_NEXT(_i, _s) (((_i) + 1) % (_s)) /* Number of commands that can be queued in a context before it sleeps */ @@ -134,12 +127,12 @@ static int fault_detect_read_compare(struct kgsl_device *device) } /** - * adreno_context_get_cmdbatch() - Get a new command from a context queue + * adreno_dispatcher_get_cmdbatch() - Get a new command from a context queue * @drawctxt: Pointer to the adreno draw context * * Dequeue a new command batch from the context list */ -static inline struct kgsl_cmdbatch *adreno_context_get_cmdbatch( +static inline struct kgsl_cmdbatch *adreno_dispatcher_get_cmdbatch( struct adreno_context *drawctxt) { struct kgsl_cmdbatch *cmdbatch = NULL; @@ -170,7 +163,8 @@ static inline struct kgsl_cmdbatch *adreno_context_get_cmdbatch( } /** - * adreno_context_requeue_cmdbatch() - Put a command back on the context queue + * adreno_dispatcher_requeue_cmdbatch() - Put a command back on the context + * queue * @drawctxt: Pointer to the adreno draw context * @cmdbatch: Pointer to the KGSL cmdbatch to requeue * @@ -261,7 +255,9 @@ static int sendcmd(struct adreno_device *adreno_dev, dispatcher->inflight++; - if (dispatcher->inflight == 1) { + if (dispatcher->inflight == 1 && + !test_bit(ADRENO_DISPATCHER_POWER, &dispatcher->priv)) { + /* Time to make the donuts. Turn on the GPU */ ret = kgsl_active_count_get(device); if (ret) { @@ -269,6 +265,8 @@ static int sendcmd(struct adreno_device *adreno_dev, mutex_unlock(&device->mutex); return ret; } + + set_bit(ADRENO_DISPATCHER_POWER, &dispatcher->priv); } ret = adreno_ringbuffer_submitcmd(adreno_dev, cmdbatch); @@ -281,8 +279,10 @@ static int sendcmd(struct adreno_device *adreno_dev, if (dispatcher->inflight == 1) { if (ret == 0) fault_detect_read(device); - else + else { kgsl_active_count_put(device); + clear_bit(ADRENO_DISPATCHER_POWER, &dispatcher->priv); + } } mutex_unlock(&device->mutex); @@ -340,11 +340,15 @@ static int dispatcher_context_sendcmds(struct adreno_device *adreno_dev, /* * Each context can send a specific number of command batches per cycle */ - for ( ; count < _context_cmdbatch_burst && - dispatcher->inflight < _dispatcher_inflight; count++) { + while ((count < _context_cmdbatch_burst) && + (dispatcher->inflight < _dispatcher_inflight)) { int ret; - struct kgsl_cmdbatch *cmdbatch = - adreno_context_get_cmdbatch(drawctxt); + struct kgsl_cmdbatch *cmdbatch; + + if (adreno_gpu_fault(adreno_dev) != 0) + break; + + cmdbatch = adreno_dispatcher_get_cmdbatch(drawctxt); if (cmdbatch == NULL) break; @@ -369,7 +373,6 @@ static int dispatcher_context_sendcmds(struct adreno_device *adreno_dev, */ if (cmdbatch->flags & KGSL_CONTEXT_SYNC) { - count--; kgsl_cmdbatch_destroy(cmdbatch); continue; } @@ -424,8 +427,7 @@ static int _adreno_dispatcher_issuecmds(struct adreno_device *adreno_dev) int ret; /* Leave early if the dispatcher isn't in a happy state */ - if ((dispatcher->state != ADRENO_DISPATCHER_ACTIVE) || - adreno_gpu_fault(adreno_dev) != 0) + if (adreno_gpu_fault(adreno_dev) != 0) return 0; plist_head_init(&requeue); @@ -434,8 +436,7 @@ static int _adreno_dispatcher_issuecmds(struct adreno_device *adreno_dev) while (dispatcher->inflight < _dispatcher_inflight) { /* Stop doing things if the dispatcher is paused or faulted */ - if ((dispatcher->state != ADRENO_DISPATCHER_ACTIVE) || - adreno_gpu_fault(adreno_dev) != 0) + if (adreno_gpu_fault(adreno_dev) != 0) break; spin_lock(&dispatcher->plist_lock); @@ -596,7 +597,7 @@ int adreno_dispatcher_queue_cmd(struct adreno_device *adreno_dev, mutex_lock(&drawctxt->mutex); - if (drawctxt->flags & CTXT_FLAGS_BEING_DESTROYED) { + if (kgsl_context_detached(&drawctxt->base)) { mutex_unlock(&drawctxt->mutex); return -EINVAL; } @@ -607,7 +608,7 @@ int adreno_dispatcher_queue_cmd(struct adreno_device *adreno_dev, */ if (drawctxt->flags & CTXT_FLAGS_FORCE_PREAMBLE) { - cmdbatch->priv |= CMDBATCH_FLAG_FORCE_PREAMBLE; + set_bit(CMDBATCH_FLAG_FORCE_PREAMBLE, &cmdbatch->priv); drawctxt->flags &= ~CTXT_FLAGS_FORCE_PREAMBLE; } @@ -618,7 +619,7 @@ int adreno_dispatcher_queue_cmd(struct adreno_device *adreno_dev, */ if (drawctxt->flags & CTXT_FLAGS_SKIP_EOF) { - cmdbatch->priv |= CMDBATCH_FLAG_SKIP; + set_bit(CMDBATCH_FLAG_SKIP, &cmdbatch->priv); /* * If this command batch represents the EOF then clear the way @@ -640,7 +641,7 @@ int adreno_dispatcher_queue_cmd(struct adreno_device *adreno_dev, /* Wait for room in the context queue */ while (drawctxt->queued >= _context_cmdqueue_size) { - trace_adreno_context_sleep(drawctxt); + trace_adreno_drawctxt_sleep(drawctxt); mutex_unlock(&drawctxt->mutex); ret = wait_event_interruptible_timeout(drawctxt->wq, @@ -648,7 +649,7 @@ int adreno_dispatcher_queue_cmd(struct adreno_device *adreno_dev, msecs_to_jiffies(_context_queue_wait)); mutex_lock(&drawctxt->mutex); - trace_adreno_context_wake(drawctxt); + trace_adreno_drawctxt_wake(drawctxt); if (ret <= 0) { mutex_unlock(&drawctxt->mutex); @@ -677,9 +678,6 @@ int adreno_dispatcher_queue_cmd(struct adreno_device *adreno_dev, cmdbatch->timestamp = *timestamp; - /* The batch fault policy is the current system fault policy */ - cmdbatch->fault_policy = adreno_dev->ft_policy; - /* * Set the fault tolerance policy for the command batch - assuming the * context hsn't disabled FT use the current device policy @@ -1156,10 +1154,6 @@ static int dispatcher_do_fault(struct kgsl_device *device) } } - mutex_lock(&device->mutex); - kgsl_active_count_put(device); - mutex_unlock(&device->mutex); - kfree(replay); return 1; @@ -1327,19 +1321,16 @@ static void adreno_dispatcher_work(struct work_struct *work) */ if (!fault_handled && dispatcher_do_fault(device)) goto done; + /* - * Decrement the active count to 0 - this will allow the system to go - * into suspend even if there are queued command batches + * If inflight went to 0, queue back up the event processor to catch + * stragglers */ - - mutex_lock(&device->mutex); if (count && dispatcher->inflight == 0) { - del_timer_sync(&dispatcher->fault_timer); - kgsl_active_count_put(device); - /* Queue back up the event processor to catch stragglers */ + mutex_lock(&device->mutex); queue_work(device->work_queue, &device->ts_expired_ws); + mutex_unlock(&device->mutex); } - mutex_unlock(&device->mutex); /* Dispatch new commands if we have the room */ if (dispatcher->inflight < _dispatcher_inflight) @@ -1353,12 +1344,29 @@ static void adreno_dispatcher_work(struct work_struct *work) /* Update the timeout timer for the next command batch */ mod_timer(&dispatcher->timer, cmdbatch->expires); - } - /* Before leaving update the pwrscale information */ - mutex_lock(&device->mutex); - kgsl_pwrscale_idle(device); - mutex_unlock(&device->mutex); + /* There are still things in flight - update the idle counts */ + mutex_lock(&device->mutex); + kgsl_pwrscale_idle(device); + mutex_unlock(&device->mutex); + } else { + /* There is nothing left in the pipeline. Shut 'er down boys */ + mutex_lock(&device->mutex); + + /* + * Stop the fault timer before decrementing the active count to + * avoid reading the hardware registers while we are trying to + * turn clocks off + */ + del_timer_sync(&dispatcher->fault_timer); + + if (test_bit(ADRENO_DISPATCHER_POWER, &dispatcher->priv)) { + kgsl_active_count_put(device); + clear_bit(ADRENO_DISPATCHER_POWER, &dispatcher->priv); + } + + mutex_unlock(&device->mutex); + } mutex_unlock(&dispatcher->mutex); } @@ -1451,55 +1459,18 @@ void adreno_dispatcher_irq_fault(struct kgsl_device *device) adreno_dispatcher_schedule(device); } -/** - * adreno_dispatcher_pause() - stop the dispatcher - * @adreno_dev: pointer to the adreno device structure - * - * Pause the dispather so it doesn't accept any new commands - */ -void adreno_dispatcher_pause(struct adreno_device *adreno_dev) -{ - struct adreno_dispatcher *dispatcher = &adreno_dev->dispatcher; - - /* - * This will probably get called while holding other mutexes so don't - * take the dispatcher mutex. The biggest penalty is that another - * command might be submitted while we are in here but thats okay - * because whoever is waiting for the drain will just have another - * command batch to wait for - */ - - dispatcher->state = ADRENO_DISPATCHER_PAUSE; -} - -/** - * adreno_dispatcher_resume() - resume the dispatcher - * @adreno_dev: pointer to the adreno device structure - * - * Set the dispatcher active so it can start accepting commands again - */ -void adreno_dispatcher_resume(struct adreno_device *adreno_dev) -{ - struct adreno_dispatcher *dispatcher = &adreno_dev->dispatcher; - - dispatcher->state = ADRENO_DISPATCHER_ACTIVE; - adreno_dispatcher_schedule(&adreno_dev->dev); -} - /** * adreno_dispatcher_start() - activate the dispatcher * @adreno_dev: pointer to the adreno device structure * * Set the disaptcher active and start the loop once to get things going */ -void adreno_dispatcher_start(struct adreno_device *adreno_dev) +void adreno_dispatcher_start(struct kgsl_device *device) { - struct adreno_dispatcher *dispatcher = &adreno_dev->dispatcher; - - dispatcher->state = ADRENO_DISPATCHER_ACTIVE; + complete_all(&device->cmdbatch_gate); /* Schedule the work loop to get things going */ - adreno_dispatcher_schedule(&adreno_dev->dev); + adreno_dispatcher_schedule(device); } /** @@ -1514,8 +1485,6 @@ void adreno_dispatcher_stop(struct adreno_device *adreno_dev) del_timer_sync(&dispatcher->timer); del_timer_sync(&dispatcher->fault_timer); - - dispatcher->state = ADRENO_DISPATCHER_PAUSE; } /** @@ -1688,8 +1657,6 @@ int adreno_dispatcher_init(struct adreno_device *adreno_dev) plist_head_init(&dispatcher->pending); spin_lock_init(&dispatcher->plist_lock); - dispatcher->state = ADRENO_DISPATCHER_ACTIVE; - ret = kobject_init_and_add(&dispatcher->kobj, &ktype_dispatcher, &device->dev->kobj, "dispatch"); diff --git a/drivers/gpu/msm/adreno_drawctxt.c b/drivers/gpu/msm/adreno_drawctxt.c index b666c47b667..a62c96ceb3e 100644 --- a/drivers/gpu/msm/adreno_drawctxt.c +++ b/drivers/gpu/msm/adreno_drawctxt.c @@ -455,10 +455,21 @@ adreno_drawctxt_create(struct kgsl_device_private *dev_priv, drawctxt->type = (*flags & KGSL_CONTEXT_TYPE_MASK) >> KGSL_CONTEXT_TYPE_SHIFT; - ret = adreno_dev->gpudev->ctxt_create(adreno_dev, drawctxt); - if (ret) + if (adreno_dev->gpudev->ctxt_create) { + ret = adreno_dev->gpudev->ctxt_create(adreno_dev, drawctxt); + if (ret) + goto err; + } else if ((*flags & KGSL_CONTEXT_PREAMBLE) == 0 || + (*flags & KGSL_CONTEXT_NO_GMEM_ALLOC) == 0) { + KGSL_DEV_ERR_ONCE(device, + "legacy context switch not supported\n"); + ret = -EINVAL; goto err; + } else { + drawctxt->ops = &adreno_preamble_ctx_ops; + } + kgsl_sharedmem_writel(device, &device->memstore, KGSL_MEMSTORE_OFFSET(drawctxt->base.id, soptimestamp), 0); @@ -507,19 +518,8 @@ int adreno_drawctxt_detach(struct kgsl_context *context) drawctxt = ADRENO_CONTEXT(context); /* deactivate context */ - if (adreno_dev->drawctxt_active == drawctxt) { - /* no need to save GMEM or shader, the context is - * being destroyed. - */ - drawctxt->flags &= ~(CTXT_FLAGS_GMEM_SAVE | - CTXT_FLAGS_SHADER_SAVE | - CTXT_FLAGS_GMEM_SHADOW | - CTXT_FLAGS_STATE_SHADOW); - - drawctxt->flags |= CTXT_FLAGS_BEING_DESTROYED; - + if (adreno_dev->drawctxt_active == drawctxt) adreno_drawctxt_switch(adreno_dev, NULL, 0); - } mutex_lock(&drawctxt->mutex); @@ -566,6 +566,9 @@ int adreno_drawctxt_detach(struct kgsl_context *context) kgsl_sharedmem_free(&drawctxt->gpustate); kgsl_sharedmem_free(&drawctxt->context_gmem_shadow.gmemshadow); + if (drawctxt->ops->detach) + drawctxt->ops->detach(drawctxt); + /* wake threads waiting to submit commands from this context */ wake_up_interruptible_all(&drawctxt->waiting); wake_up_interruptible_all(&drawctxt->wq); @@ -584,6 +587,69 @@ void adreno_drawctxt_destroy(struct kgsl_context *context) kfree(drawctxt); } + +/** + * adreno_context_restore() - generic context restore handler + * @adreno_dev: the device + * @context: the context + * + * Basic context restore handler that writes the context identifier + * to the ringbuffer and issues pagetable switch commands if necessary. + * May be called directly from the adreno_context_ops.restore function + * pointer or as the first action in a hardware specific restore + * function. + */ +int adreno_context_restore(struct adreno_device *adreno_dev, + struct adreno_context *context) +{ + int ret; + struct kgsl_device *device; + unsigned int cmds[5]; + + if (adreno_dev == NULL || context == NULL) + return -EINVAL; + + device = &adreno_dev->dev; + /* write the context identifier to the ringbuffer */ + cmds[0] = cp_nop_packet(1); + cmds[1] = KGSL_CONTEXT_TO_MEM_IDENTIFIER; + cmds[2] = cp_type3_packet(CP_MEM_WRITE, 2); + cmds[3] = device->memstore.gpuaddr + + KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, current_context); + cmds[4] = context->base.id; + ret = adreno_ringbuffer_issuecmds(device, context, KGSL_CMD_FLAGS_NONE, + cmds, 5); + if (ret) + return ret; + + return kgsl_mmu_setstate(&device->mmu, + context->base.proc_priv->pagetable, + context->base.id); +} + + +const struct adreno_context_ops adreno_preamble_ctx_ops = { + .restore = adreno_context_restore, +}; + +/** + * context_save() - save old context when necessary + * @drawctxt - the old context + * + * For legacy context switching, we need to issue save + * commands unless the context is being destroyed. + */ +static inline int context_save(struct adreno_device *adreno_dev, + struct adreno_context *context) +{ + if (context->ops->save == NULL + || kgsl_context_detached(&context->base) + || context->state == ADRENO_CONTEXT_STATE_INVALID) + return 0; + + return context->ops->save(adreno_dev, context); +} + /** * adreno_drawctxt_set_bin_base_offset - set bin base offset for the context * @device - KGSL device that owns the context @@ -622,6 +688,12 @@ int adreno_drawctxt_switch(struct adreno_device *adreno_dev, int ret = 0; if (drawctxt) { + /* + * Handle legacy gmem / save restore flag on each IB. + * Userspace sets to guard IB sequences that require + * gmem to be saved and clears it at the end of the + * sequence. + */ if (flags & KGSL_CONTEXT_SAVE_GMEM) /* Set the flag in context so that the save is done * when this context is switched out. */ @@ -633,46 +705,52 @@ int adreno_drawctxt_switch(struct adreno_device *adreno_dev, /* already current? */ if (adreno_dev->drawctxt_active == drawctxt) { - if (adreno_dev->gpudev->ctxt_draw_workaround && - adreno_is_a225(adreno_dev)) - ret = adreno_dev->gpudev->ctxt_draw_workaround( - adreno_dev, drawctxt); + if (drawctxt && drawctxt->ops->draw_workaround) + ret = drawctxt->ops->draw_workaround(adreno_dev, + drawctxt); return ret; } trace_adreno_drawctxt_switch(adreno_dev->drawctxt_active, drawctxt, flags); - /* Save the old context */ - if (adreno_dev->gpudev->ctxt_save) { - ret = adreno_dev->gpudev->ctxt_save(adreno_dev, - adreno_dev->drawctxt_active); - + if (adreno_dev->drawctxt_active) { + ret = context_save(adreno_dev, adreno_dev->drawctxt_active); if (ret) { KGSL_DRV_ERR(device, "Error in GPU context %d save: %d\n", adreno_dev->drawctxt_active->base.id, ret); return ret; } - } - /* Put the old instance of the active drawctxt */ - if (adreno_dev->drawctxt_active) + /* Put the old instance of the active drawctxt */ kgsl_context_put(&adreno_dev->drawctxt_active->base); + adreno_dev->drawctxt_active = NULL; + } /* Get a refcount to the new instance */ if (drawctxt) { if (!_kgsl_context_get(&drawctxt->base)) return -EINVAL; - } - /* Set the new context */ - ret = adreno_dev->gpudev->ctxt_restore(adreno_dev, drawctxt); - if (ret) { - KGSL_DRV_ERR(device, - "Error in GPU context %d restore: %d\n", - drawctxt->base.id, ret); - return ret; + /* Set the new context */ + ret = drawctxt->ops->restore(adreno_dev, drawctxt); + if (ret) { + KGSL_DRV_ERR(device, + "Error in GPU context %d restore: %d\n", + drawctxt->base.id, ret); + return ret; + } + } else { + /* + * No context - set the default pagetable and thats it. + * If there isn't a current context, the kgsl_mmu_setstate + * will use the CPU path so we don't need to give + * it a valid context id. + */ + ret = kgsl_mmu_setstate(&device->mmu, + device->mmu.defaultpagetable, + KGSL_CONTEXT_INVALID); } adreno_dev->drawctxt_active = drawctxt; diff --git a/drivers/gpu/msm/adreno_drawctxt.h b/drivers/gpu/msm/adreno_drawctxt.h index 0f65d4b565b..9312db63bd1 100644 --- a/drivers/gpu/msm/adreno_drawctxt.h +++ b/drivers/gpu/msm/adreno_drawctxt.h @@ -46,8 +46,6 @@ #define CTXT_FLAGS_PER_CONTEXT_TS BIT(11) /* Context has caused a GPU hang and fault tolerance successful */ #define CTXT_FLAGS_GPU_HANG_FT BIT(12) -/* Context is being destroyed so dont save it */ -#define CTXT_FLAGS_BEING_DESTROYED BIT(13) /* User mode generated timestamps enabled */ #define CTXT_FLAGS_USER_GENERATED_TS BIT(14) /* Context skip till EOF */ @@ -102,6 +100,29 @@ struct gmem_shadow_t { struct kgsl_memdesc quad_vertices_restore; }; +struct adreno_context; + +/** + * struct adreno_context_ops - context state management functions + * @save: optional hook for saving context state + * @restore: required hook for restoring state, + * adreno_context_restore() may be used directly here. + * @draw_workaround: optional hook for a workaround after every IB + * @detach: optional hook for freeing state tracking memory. + */ +struct adreno_context_ops { + int (*save)(struct adreno_device *, struct adreno_context *); + int (*restore)(struct adreno_device *, struct adreno_context *); + int (*draw_workaround)(struct adreno_device *, + struct adreno_context *); + void (*detach)(struct adreno_context *); +}; + +int adreno_context_restore(struct adreno_device *, struct adreno_context *); + +/* generic context ops for preamble context switch */ +extern const struct adreno_context_ops adreno_preamble_ctx_ops; + /** * struct adreno_context - Adreno GPU draw context * @id: Unique integer ID of the context @@ -140,6 +161,7 @@ struct gmem_shadow_t { * @wq: Workqueue structure for contexts to sleep pending room in the queue * @waiting: Workqueue structure for contexts waiting for a timestamp or event * @queued: Number of commands queued in the cmdqueue + * @ops: Context switch functions for this context. */ struct adreno_context { struct kgsl_context base; @@ -186,6 +208,8 @@ struct adreno_context { wait_queue_head_t waiting; int queued; + + const struct adreno_context_ops *ops; }; diff --git a/drivers/gpu/msm/adreno_postmortem.c b/drivers/gpu/msm/adreno_postmortem.c index 33aa0954976..2c9b968a198 100644 --- a/drivers/gpu/msm/adreno_postmortem.c +++ b/drivers/gpu/msm/adreno_postmortem.c @@ -626,7 +626,7 @@ int adreno_dump(struct kgsl_device *device, int manual) end: /* Restart the dispatcher after a manually triggered dump */ if (manual) - adreno_dispatcher_start(adreno_dev); + adreno_dispatcher_start(device); return result; } diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c index 2d42bba3402..9e69a4954bb 100644 --- a/drivers/gpu/msm/adreno_ringbuffer.c +++ b/drivers/gpu/msm/adreno_ringbuffer.c @@ -1006,12 +1006,8 @@ adreno_ringbuffer_issueibcmds(struct kgsl_device_private *dev_priv, /* For now everybody has the same priority */ cmdbatch->priority = ADRENO_CONTEXT_DEFAULT_PRIORITY; - /* - * Clear the wake on touch bit to indicate an IB has been submitted - * since the last time we set it - */ - - device->flags &= ~KGSL_FLAG_WAKE_ON_TOUCH; + /* wait for the suspend gate */ + wait_for_completion(&device->cmdbatch_gate); /* Queue the command in the ringbuffer */ ret = adreno_dispatcher_queue_cmd(adreno_dev, drawctxt, cmdbatch, @@ -1154,12 +1150,14 @@ int adreno_ringbuffer_submitcmd(struct adreno_device *adreno_dev, cmdbatch->timestamp); #ifdef CONFIG_MSM_KGSL_CFF_DUMP + if (ret) + goto done; /* * insert wait for idle after every IB1 * this is conservative but works reliably and is ok * even for performance simulations */ - adreno_idle(device); + ret = adreno_idle(device); #endif done: diff --git a/drivers/gpu/msm/adreno_trace.h b/drivers/gpu/msm/adreno_trace.h index 8a9046c4752..6079b612185 100644 --- a/drivers/gpu/msm/adreno_trace.h +++ b/drivers/gpu/msm/adreno_trace.h @@ -29,15 +29,21 @@ TRACE_EVENT(adreno_cmdbatch_queued, __field(unsigned int, id) __field(unsigned int, timestamp) __field(unsigned int, queued) + __field(unsigned int, flags) ), TP_fast_assign( __entry->id = cmdbatch->context->id; __entry->timestamp = cmdbatch->timestamp; __entry->queued = queued; + __entry->flags = cmdbatch->flags; ), TP_printk( - "ctx=%u ts=%u queued=%u", - __entry->id, __entry->timestamp, __entry->queued + "ctx=%u ts=%u queued=%u flags=%s", + __entry->id, __entry->timestamp, __entry->queued, + __entry->flags ? __print_flags(__entry->flags, "|", + { KGSL_CONTEXT_SYNC, "SYNC" }, + { KGSL_CONTEXT_END_OF_FRAME, "EOF" }) + : "none" ) ); @@ -147,12 +153,12 @@ DECLARE_EVENT_CLASS(adreno_drawctxt_template, TP_printk("ctx=%u", __entry->id) ); -DEFINE_EVENT(adreno_drawctxt_template, adreno_context_sleep, +DEFINE_EVENT(adreno_drawctxt_template, adreno_drawctxt_sleep, TP_PROTO(struct adreno_context *drawctxt), TP_ARGS(drawctxt) ); -DEFINE_EVENT(adreno_drawctxt_template, adreno_context_wake, +DEFINE_EVENT(adreno_drawctxt_template, adreno_drawctxt_wake, TP_PROTO(struct adreno_context *drawctxt), TP_ARGS(drawctxt) ); @@ -162,6 +168,11 @@ DEFINE_EVENT(adreno_drawctxt_template, dispatch_queue_context, TP_ARGS(drawctxt) ); +DEFINE_EVENT(adreno_drawctxt_template, adreno_drawctxt_invalidate, + TP_PROTO(struct adreno_context *drawctxt), + TP_ARGS(drawctxt) +); + TRACE_EVENT(adreno_drawctxt_wait_start, TP_PROTO(unsigned int id, unsigned int ts), TP_ARGS(id, ts), diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index 8ca70e14692..72888b2d32b 100644 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -934,21 +934,16 @@ int kgsl_close_device(struct kgsl_device *device) device->open_count--; if (device->open_count == 0) { - /* Wait for the active count to go to 1 */ - kgsl_active_count_wait(device, 1); + /* Wait for the active count to go to 0 */ + kgsl_active_count_wait(device, 0); /* Fail if the wait times out */ - BUG_ON(atomic_read(&device->active_cnt) > 1); + BUG_ON(atomic_read(&device->active_cnt) > 0); + /* Force power on to do the stop */ + kgsl_pwrctrl_enable(device); result = device->ftbl->stop(device); kgsl_pwrctrl_set_state(device, KGSL_STATE_INIT); - /* - * active_cnt special case: we just stopped the device, - * so no need to use kgsl_active_count_put() - */ - atomic_dec(&device->active_cnt); - } else { - kgsl_active_count_put(device); } return result; @@ -967,7 +962,6 @@ static int kgsl_release(struct inode *inodep, struct file *filep) filep->private_data = NULL; mutex_lock(&device->mutex); - kgsl_active_count_get(device); while (1) { read_lock(&device->context_lock); @@ -1454,6 +1448,7 @@ static long kgsl_ioctl_device_waittimestamp_ctxtid(struct kgsl_device_private * @timestamp: Pending timestamp for the event * @handle: Pointer to a sync fence handle * @device: Pointer to the KGSL device + * @refcount: Allow event to be destroyed asynchronously */ struct kgsl_cmdbatch_sync_event { int type; @@ -1463,9 +1458,36 @@ struct kgsl_cmdbatch_sync_event { unsigned int timestamp; struct kgsl_sync_fence_waiter *handle; struct kgsl_device *device; - spinlock_t lock; + struct kref refcount; }; +/** + * kgsl_cmdbatch_sync_event_destroy() - Destroy a sync event object + * @kref: Pointer to the kref structure for this object + * + * Actually destroy a sync event object. Called from + * kgsl_cmdbatch_sync_event_put. + */ +static void kgsl_cmdbatch_sync_event_destroy(struct kref *kref) +{ + struct kgsl_cmdbatch_sync_event *event = container_of(kref, + struct kgsl_cmdbatch_sync_event, refcount); + + kgsl_cmdbatch_put(event->cmdbatch); + kfree(event); +} + +/** + * kgsl_cmdbatch_sync_event_put() - Decrement the refcount for a + * sync event object + * @event: Pointer to the sync event object + */ +static inline void kgsl_cmdbatch_sync_event_put( + struct kgsl_cmdbatch_sync_event *event) +{ + kref_put(&event->refcount, kgsl_cmdbatch_sync_event_destroy); +} + /** * kgsl_cmdbatch_destroy_object() - Destroy a cmdbatch object * @kref: Pointer to the kref structure for this object @@ -1484,13 +1506,32 @@ void kgsl_cmdbatch_destroy_object(struct kref *kref) } EXPORT_SYMBOL(kgsl_cmdbatch_destroy_object); +/* + * a generic function to retire a pending sync event and (possibly) + * kick the dispatcher + */ static void kgsl_cmdbatch_sync_expire(struct kgsl_device *device, struct kgsl_cmdbatch_sync_event *event) { + struct kgsl_cmdbatch_sync_event *e, *tmp; int sched = 0; + int removed = 0; spin_lock(&event->cmdbatch->lock); - list_del(&event->node); + + /* + * sync events that are contained by a cmdbatch which has been + * destroyed may have already been removed from the synclist + */ + + list_for_each_entry_safe(e, tmp, &event->cmdbatch->synclist, node) { + if (e == event) { + list_del_init(&event->node); + removed = 1; + break; + } + } + sched = list_empty(&event->cmdbatch->synclist) ? 1 : 0; spin_unlock(&event->cmdbatch->lock); @@ -1501,6 +1542,10 @@ static void kgsl_cmdbatch_sync_expire(struct kgsl_device *device, if (sched && device->ftbl->drawctxt_sched) device->ftbl->drawctxt_sched(device, event->cmdbatch->context); + + /* Put events that have been removed from the synclist */ + if (removed) + kgsl_cmdbatch_sync_event_put(event); } @@ -1514,11 +1559,9 @@ static void kgsl_cmdbatch_sync_func(struct kgsl_device *device, void *priv, struct kgsl_cmdbatch_sync_event *event = priv; kgsl_cmdbatch_sync_expire(device, event); - kgsl_context_put(event->context); - kgsl_cmdbatch_put(event->cmdbatch); - - kfree(event); + /* Put events that have signaled */ + kgsl_cmdbatch_sync_event_put(event); } /** @@ -1526,64 +1569,63 @@ static void kgsl_cmdbatch_sync_func(struct kgsl_device *device, void *priv, * @cmdbatch: Pointer to the command batch object to destroy * * Start the process of destroying a command batch. Cancel any pending events - * and decrement the refcount. + * and decrement the refcount. Asynchronous events can still signal after + * kgsl_cmdbatch_destroy has returned. */ void kgsl_cmdbatch_destroy(struct kgsl_cmdbatch *cmdbatch) { struct kgsl_cmdbatch_sync_event *event, *tmp; - int canceled = 0; + LIST_HEAD(cancel_synclist); + /* + * Empty the synclist before canceling events + */ spin_lock(&cmdbatch->lock); + list_splice_init(&cmdbatch->synclist, &cancel_synclist); + spin_unlock(&cmdbatch->lock); - /* Delete any pending sync points for this command batch */ - list_for_each_entry_safe(event, tmp, &cmdbatch->synclist, node) { + /* + * Finish canceling events outside the cmdbatch spinlock and + * require the cancel function to return if the event was + * successfully canceled meaning that the event is guaranteed + * not to signal the callback. This guarantee ensures that + * the reference count for the event and cmdbatch is correct. + */ + list_for_each_entry_safe(event, tmp, &cancel_synclist, node) { - switch (event->type) { - case KGSL_CMD_SYNCPOINT_TYPE_TIMESTAMP: { - /* Cancel the event if it still exists */ - mutex_lock(&cmdbatch->device->mutex); + if (event->type == KGSL_CMD_SYNCPOINT_TYPE_TIMESTAMP) { + /* + * Timestamp events are guaranteed to signal + * when canceled + */ kgsl_cancel_event(cmdbatch->device, event->context, event->timestamp, kgsl_cmdbatch_sync_func, event); - canceled = 1; - mutex_unlock(&cmdbatch->device->mutex); - kgsl_context_put(event->context); - break; + } else if (event->type == KGSL_CMD_SYNCPOINT_TYPE_FENCE) { + /* Put events that are successfully canceled */ + if (kgsl_sync_fence_async_cancel(event->handle)) + kgsl_cmdbatch_sync_event_put(event); } - case KGSL_CMD_SYNCPOINT_TYPE_FENCE: - canceled = kgsl_sync_fence_async_cancel(event->handle); - break; - default: - break; - } - - if(canceled) { - list_del(&event->node); - kfree(event); - - /* - * Put back a instance of the cmdbatch for each pending event - * that we canceled - */ - kgsl_cmdbatch_put(cmdbatch); - } + /* Put events that have been removed from the synclist */ + list_del_init(&event->node); + kgsl_cmdbatch_sync_event_put(event); } - spin_unlock(&cmdbatch->lock); - kgsl_cmdbatch_put(cmdbatch); } EXPORT_SYMBOL(kgsl_cmdbatch_destroy); +/* + * A callback that gets registered with kgsl_sync_fence_async_wait and is fired + * when a fence is expired + */ static void kgsl_cmdbatch_sync_fence_func(void *priv) { struct kgsl_cmdbatch_sync_event *event = priv; - spin_lock(&event->lock); kgsl_cmdbatch_sync_expire(event->device, event); - kgsl_cmdbatch_put(event->cmdbatch); - spin_unlock(&event->lock); - kfree(event); + /* Put events that have signaled */ + kgsl_cmdbatch_sync_event_put(event); } /* kgsl_cmdbatch_add_sync_fence() - Add a new sync fence syncpoint @@ -1609,28 +1651,33 @@ static int kgsl_cmdbatch_add_sync_fence(struct kgsl_device *device, event->type = KGSL_CMD_SYNCPOINT_TYPE_FENCE; event->cmdbatch = cmdbatch; event->device = device; - spin_lock_init(&event->lock); + event->context = NULL; + + /* + * Initial kref is to ensure async callback does not free the + * event before this function sets the event handle + */ + kref_init(&event->refcount); /* * Add it to the list first to account for the possiblity that the * callback will happen immediately after the call to - * kgsl_sync_fence_async_wait + * kgsl_sync_fence_async_wait. Decrement the event refcount when + * removing from the synclist. */ spin_lock(&cmdbatch->lock); + kref_get(&event->refcount); list_add(&event->node, &cmdbatch->synclist); spin_unlock(&cmdbatch->lock); /* - * There is a distinct race condition that can occur if the fence - * callback is fired before the function has a chance to return. The - * event struct would be freed before we could write event->handle and - * hilarity ensued. Protect against this by protecting the call to - * kgsl_sync_fence_async_wait and the kfree in the callback with a lock. + * Increment the reference count for the async callback. + * Decrement when the callback is successfully canceled, when + * the callback is signaled or if the async wait fails. */ - spin_lock(&event->lock); - + kref_get(&event->refcount); event->handle = kgsl_sync_fence_async_wait(sync->fd, kgsl_cmdbatch_sync_fence_func, event); @@ -1638,18 +1685,27 @@ static int kgsl_cmdbatch_add_sync_fence(struct kgsl_device *device, if (IS_ERR_OR_NULL(event->handle)) { int ret = PTR_ERR(event->handle); + /* Failed to add the event to the async callback */ + kgsl_cmdbatch_sync_event_put(event); + + /* Remove event from the synclist */ spin_lock(&cmdbatch->lock); list_del(&event->node); + kgsl_cmdbatch_sync_event_put(event); spin_unlock(&cmdbatch->lock); - kgsl_cmdbatch_put(cmdbatch); - spin_unlock(&event->lock); - kfree(event); + /* Event no longer needed by this function */ + kgsl_cmdbatch_sync_event_put(event); return ret; } - spin_unlock(&event->lock); + /* + * Event was successfully added to the synclist, the async + * callback and handle to cancel event has been set. + */ + kgsl_cmdbatch_sync_event_put(event); + return 0; } @@ -1680,9 +1736,15 @@ static int kgsl_cmdbatch_add_sync_timestamp(struct kgsl_device *device, */ if (context == cmdbatch->context) { - KGSL_DRV_ERR(device, - "Cannot create a sync point on your own context\n"); - goto done; + unsigned int queued = kgsl_readtimestamp(device, context, + KGSL_TIMESTAMP_QUEUED); + + if (timestamp_cmp(sync->timestamp, queued) > 0) { + KGSL_DRV_ERR(device, + "Cannot create syncpoint for future timestamp %d (current %d)\n", + sync->timestamp, queued); + goto done; + } } event = kzalloc(sizeof(*event), GFP_KERNEL); @@ -1698,15 +1760,24 @@ static int kgsl_cmdbatch_add_sync_timestamp(struct kgsl_device *device, event->context = context; event->timestamp = sync->timestamp; + /* + * Two krefs are required to support events. The first kref is for + * the synclist which holds the event in the cmdbatch. The second + * kref is for the callback which can be asynchronous and be called + * after kgsl_cmdbatch_destroy. The kref should be put when the event + * is removed from the synclist, if the callback is successfully + * canceled or when the callback is signaled. + */ + kref_init(&event->refcount); + kref_get(&event->refcount); + spin_lock(&cmdbatch->lock); list_add(&event->node, &cmdbatch->synclist); spin_unlock(&cmdbatch->lock); mutex_lock(&device->mutex); - kgsl_active_count_get(device); ret = kgsl_add_event(device, context->id, sync->timestamp, kgsl_cmdbatch_sync_func, event, NULL); - kgsl_active_count_put(device); mutex_unlock(&device->mutex); if (ret) { @@ -1821,7 +1892,7 @@ static struct kgsl_cmdbatch *kgsl_cmdbatch_create(struct kgsl_device *device, cmdbatch->device = device; cmdbatch->ibcount = (flags & KGSL_CONTEXT_SYNC) ? 0 : numibs; cmdbatch->context = context; - cmdbatch->flags = flags; + cmdbatch->flags = flags & ~KGSL_CONTEXT_SUBMIT_IB_LIST; return cmdbatch; } @@ -1844,15 +1915,22 @@ static bool _kgsl_cmdbatch_verify(struct kgsl_device_private *dev_priv, for (i = 0; i < cmdbatch->ibcount; i++) { if (cmdbatch->ibdesc[i].sizedwords == 0) { KGSL_DRV_ERR(dev_priv->device, - "Invalid IB: size is 0\n"); + "invalid size ctx %d ib(%d) %X/%X\n", + cmdbatch->context->id, i, + cmdbatch->ibdesc[i].gpuaddr, + cmdbatch->ibdesc[i].sizedwords); + return false; } if (!kgsl_mmu_gpuaddr_in_range(private->pagetable, cmdbatch->ibdesc[i].gpuaddr)) { KGSL_DRV_ERR(dev_priv->device, - "Invalid IB: address 0x%X is out of range\n", - cmdbatch->ibdesc[i].gpuaddr); + "Invalid address ctx %d ib(%d) %X/%X\n", + cmdbatch->context->id, i, + cmdbatch->ibdesc[i].gpuaddr, + cmdbatch->ibdesc[i].sizedwords); + return false; } } @@ -1948,8 +2026,6 @@ static struct kgsl_cmdbatch *_kgsl_cmdbatch_create(struct kgsl_device *device, return ERR_PTR(ret); } - cmdbatch->flags = flags; - return cmdbatch; } @@ -1977,7 +2053,7 @@ static long kgsl_ioctl_rb_issueibcmds(struct kgsl_device_private *dev_priv, * submission */ - if (param->numibs == 0 || param->numibs > 100000) + if (param->numibs == 0 || param->numibs > KGSL_MAX_NUMIBS) goto done; cmdbatch = _kgsl_cmdbatch_create(device, context, param->flags, @@ -1991,10 +2067,8 @@ static long kgsl_ioctl_rb_issueibcmds(struct kgsl_device_private *dev_priv, } /* Run basic sanity checking on the command */ - if (!_kgsl_cmdbatch_verify(dev_priv, cmdbatch)) { - KGSL_DRV_ERR(device, "Unable to verify the IBs\n"); + if (!_kgsl_cmdbatch_verify(dev_priv, cmdbatch)) goto free_cmdbatch; - } result = dev_priv->device->ftbl->issueibcmds(dev_priv, context, cmdbatch, ¶m->timestamp); @@ -2020,10 +2094,10 @@ static long kgsl_ioctl_submit_commands(struct kgsl_device_private *dev_priv, /* The number of IBs are completely ignored for sync commands */ if (!(param->flags & KGSL_CONTEXT_SYNC)) { - if (param->numcmds == 0 || param->numcmds > 100000) + if (param->numcmds == 0 || param->numcmds > KGSL_MAX_NUMIBS) return -EINVAL; } else if (param->numcmds != 0) { - KGSL_DRV_ERR(device, + KGSL_DEV_ERR_ONCE(device, "Commands specified with the SYNC flag. They will be ignored\n"); } @@ -2041,10 +2115,8 @@ static long kgsl_ioctl_submit_commands(struct kgsl_device_private *dev_priv, } /* Run basic sanity checking on the command */ - if (!_kgsl_cmdbatch_verify(dev_priv, cmdbatch)) { - KGSL_DRV_ERR(device, "Unable to verify the IBs\n"); + if (!_kgsl_cmdbatch_verify(dev_priv, cmdbatch)) goto free_cmdbatch; - } result = dev_priv->device->ftbl->issueibcmds(dev_priv, context, cmdbatch, ¶m->timestamp); @@ -3292,7 +3364,6 @@ typedef long (*kgsl_ioctl_func_t)(struct kgsl_device_private *, { .cmd = (_cmd), .func = (_func), .flags = (_flags) } #define KGSL_IOCTL_LOCK BIT(0) -#define KGSL_IOCTL_WAKE BIT(1) static const struct { unsigned int cmd; @@ -3304,10 +3375,10 @@ static const struct { KGSL_IOCTL_LOCK), KGSL_IOCTL_FUNC(IOCTL_KGSL_DEVICE_WAITTIMESTAMP, kgsl_ioctl_device_waittimestamp, - KGSL_IOCTL_LOCK | KGSL_IOCTL_WAKE), + KGSL_IOCTL_LOCK), KGSL_IOCTL_FUNC(IOCTL_KGSL_DEVICE_WAITTIMESTAMP_CTXTID, kgsl_ioctl_device_waittimestamp_ctxtid, - KGSL_IOCTL_LOCK | KGSL_IOCTL_WAKE), + KGSL_IOCTL_LOCK), KGSL_IOCTL_FUNC(IOCTL_KGSL_RINGBUFFER_ISSUEIBCMDS, kgsl_ioctl_rb_issueibcmds, 0), KGSL_IOCTL_FUNC(IOCTL_KGSL_SUBMIT_COMMANDS, @@ -3329,7 +3400,7 @@ static const struct { KGSL_IOCTL_LOCK), KGSL_IOCTL_FUNC(IOCTL_KGSL_DRAWCTXT_DESTROY, kgsl_ioctl_drawctxt_destroy, - KGSL_IOCTL_LOCK | KGSL_IOCTL_WAKE), + KGSL_IOCTL_LOCK), KGSL_IOCTL_FUNC(IOCTL_KGSL_MAP_USER_MEM, kgsl_ioctl_map_user_mem, 0), KGSL_IOCTL_FUNC(IOCTL_KGSL_SHAREDMEM_FROM_PMEM, @@ -3367,7 +3438,7 @@ static long kgsl_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) struct kgsl_device_private *dev_priv = filep->private_data; unsigned int nr; kgsl_ioctl_func_t func; - int lock, ret, use_hw; + int lock, ret; char ustack[64]; void *uptr = NULL; @@ -3425,7 +3496,6 @@ static long kgsl_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) func = kgsl_ioctl_funcs[nr].func; lock = kgsl_ioctl_funcs[nr].flags & KGSL_IOCTL_LOCK; - use_hw = kgsl_ioctl_funcs[nr].flags & KGSL_IOCTL_WAKE; } else { func = dev_priv->device->ftbl->ioctl; if (!func) { @@ -3435,28 +3505,15 @@ static long kgsl_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) goto done; } lock = 1; - use_hw = 1; } - if (lock) { + if (lock) mutex_lock(&dev_priv->device->mutex); - if (use_hw) { - ret = kgsl_active_count_get(dev_priv->device); - if (ret < 0) { - use_hw = 0; - goto unlock; - } - } - } ret = func(dev_priv, cmd, uptr); -unlock: - if (lock) { - if (use_hw) - kgsl_active_count_put(dev_priv->device); + if (lock) mutex_unlock(&dev_priv->device->mutex); - } /* * Still copy back on failure, but assume function took diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h index 651d5974f52..32f105c7c11 100644 --- a/drivers/gpu/msm/kgsl.h +++ b/drivers/gpu/msm/kgsl.h @@ -78,6 +78,8 @@ #define KGSL_MEMFREE_HIST_SIZE ((int)(PAGE_SIZE * 2)) +#define KGSL_MAX_NUMIBS 100000 + struct kgsl_memfree_hist_elem { unsigned int pid; unsigned int gpuaddr; diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h index 3dcf7d7a18f..963f389a1df 100644 --- a/drivers/gpu/msm/kgsl_device.h +++ b/drivers/gpu/msm/kgsl_device.h @@ -244,6 +244,7 @@ struct kgsl_device { struct kgsl_mh mh; struct kgsl_mmu mmu; struct completion hwaccess_gate; + struct completion cmdbatch_gate; const struct kgsl_functable *ftbl; struct work_struct idle_check_ws; struct timer_list idle_timer; @@ -316,6 +317,7 @@ void kgsl_check_fences(struct work_struct *work); #define KGSL_DEVICE_COMMON_INIT(_dev) \ .hwaccess_gate = COMPLETION_INITIALIZER((_dev).hwaccess_gate),\ + .cmdbatch_gate = COMPLETION_INITIALIZER((_dev).cmdbatch_gate),\ .idle_check_ws = __WORK_INITIALIZER((_dev).idle_check_ws,\ kgsl_idle_check),\ .ts_expired_ws = __WORK_INITIALIZER((_dev).ts_expired_ws,\ @@ -687,7 +689,8 @@ void kgsl_cmdbatch_destroy_object(struct kref *kref); */ static inline void kgsl_cmdbatch_put(struct kgsl_cmdbatch *cmdbatch) { - kref_put(&cmdbatch->refcount, kgsl_cmdbatch_destroy_object); + if (cmdbatch) + kref_put(&cmdbatch->refcount, kgsl_cmdbatch_destroy_object); } /** diff --git a/drivers/gpu/msm/kgsl_events.c b/drivers/gpu/msm/kgsl_events.c index 277eae0127c..d76b628df1c 100644 --- a/drivers/gpu/msm/kgsl_events.c +++ b/drivers/gpu/msm/kgsl_events.c @@ -58,8 +58,6 @@ static inline void _do_signal_event(struct kgsl_device *device, list_del(&event->list); kgsl_context_put(event->context); kfree(event); - - kgsl_active_count_put(device); } static void _retire_events(struct kgsl_device *device, @@ -212,7 +210,6 @@ EXPORT_SYMBOL(kgsl_signal_events); int kgsl_add_event(struct kgsl_device *device, u32 id, u32 ts, kgsl_event_func func, void *priv, void *owner) { - int ret; struct kgsl_event *event; unsigned int cur_ts; struct kgsl_context *context = NULL; @@ -262,17 +259,6 @@ int kgsl_add_event(struct kgsl_device *device, u32 id, u32 ts, return -ENOMEM; } - /* - * Increase the active count on the device to avoid going into power - * saving modes while events are pending - */ - ret = kgsl_active_count_get(device); - if (ret < 0) { - kgsl_context_put(context); - kfree(event); - return ret; - } - event->context = context; event->timestamp = ts; event->priv = priv; diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c index 0e7740439f3..e4f381857c2 100644 --- a/drivers/gpu/msm/kgsl_pwrctrl.c +++ b/drivers/gpu/msm/kgsl_pwrctrl.c @@ -1481,6 +1481,8 @@ int kgsl_pwrctrl_wake(struct kgsl_device *device) /* Enable state before turning on irq */ kgsl_pwrctrl_set_state(device, KGSL_STATE_ACTIVE); kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_ON); + mod_timer(&device->idle_timer, jiffies + + device->pwrctrl.interval_timeout); pm_qos_update_request(&device->pwrctrl.pm_qos_req_dma, device->pwrctrl.pm_qos_latency); case KGSL_STATE_ACTIVE: @@ -1583,9 +1585,6 @@ int kgsl_active_count_get(struct kgsl_device *device) mutex_lock(&device->mutex); } - /* Stop the idle timer */ - del_timer_sync(&device->idle_timer); - ret = kgsl_pwrctrl_wake(device); } if (ret == 0) diff --git a/drivers/gpu/msm/kgsl_pwrctrl.h b/drivers/gpu/msm/kgsl_pwrctrl.h index 71a0fdd4b61..9f181606bd8 100644 --- a/drivers/gpu/msm/kgsl_pwrctrl.h +++ b/drivers/gpu/msm/kgsl_pwrctrl.h @@ -120,8 +120,8 @@ static inline unsigned long kgsl_get_clkrate(struct clk *clk) void kgsl_pwrctrl_set_state(struct kgsl_device *device, unsigned int state); void kgsl_pwrctrl_request_state(struct kgsl_device *device, unsigned int state); -int kgsl_active_count_get(struct kgsl_device *device); -int kgsl_active_count_get_light(struct kgsl_device *device); +int __must_check kgsl_active_count_get(struct kgsl_device *device); +int __must_check kgsl_active_count_get_light(struct kgsl_device *device); void kgsl_active_count_put(struct kgsl_device *device); int kgsl_active_count_wait(struct kgsl_device *device, int count); diff --git a/drivers/gpu/msm/z180.c b/drivers/gpu/msm/z180.c index ac50a91cdd8..45f200c3454 100644 --- a/drivers/gpu/msm/z180.c +++ b/drivers/gpu/msm/z180.c @@ -406,7 +406,9 @@ z180_cmdstream_issueibcmds(struct kgsl_device_private *dev_priv, mutex_lock(&device->mutex); - kgsl_active_count_get(device); + result = kgsl_active_count_get(device); + if (result) + goto error_active_count; if (cmdbatch == NULL) { result = EINVAL; @@ -515,7 +517,7 @@ z180_cmdstream_issueibcmds(struct kgsl_device_private *dev_priv, *timestamp, cmdbatch->flags, result, 0); kgsl_active_count_put(device); - +error_active_count: mutex_unlock(&device->mutex); return (int)result; @@ -864,9 +866,13 @@ static int z180_waittimestamp(struct kgsl_device *device, if (msecs == -1) msecs = Z180_IDLE_TIMEOUT; - mutex_unlock(&device->mutex); - status = z180_wait(device, context, timestamp, msecs); - mutex_lock(&device->mutex); + status = kgsl_active_count_get(device); + if (!status) { + mutex_unlock(&device->mutex); + status = z180_wait(device, context, timestamp, msecs); + mutex_lock(&device->mutex); + kgsl_active_count_put(device); + } return status; } @@ -915,12 +921,17 @@ z180_drawctxt_create(struct kgsl_device_private *dev_priv, static int z180_drawctxt_detach(struct kgsl_context *context) { + int ret; struct kgsl_device *device; struct z180_device *z180_dev; device = context->device; z180_dev = Z180_DEVICE(device); + ret = kgsl_active_count_get(device); + if (ret) + return ret; + z180_idle(device); if (z180_dev->ringbuffer.prevctx == context->id) { @@ -932,6 +943,7 @@ z180_drawctxt_detach(struct kgsl_context *context) KGSL_MMUFLAGS_PTUPDATE); } + kgsl_active_count_put(device); return 0; } diff --git a/drivers/media/platform/msm/camera_v2/camera/camera.c b/drivers/media/platform/msm/camera_v2/camera/camera.c index e6e6cfeffb7..125dd5aa8b8 100644 --- a/drivers/media/platform/msm/camera_v2/camera/camera.c +++ b/drivers/media/platform/msm/camera_v2/camera/camera.c @@ -540,7 +540,6 @@ static int camera_v4l2_open(struct file *filep) rc = msm_create_session(pvdev->vdev->num, pvdev->vdev); if (rc < 0) goto session_fail; - rc = msm_create_command_ack_q(pvdev->vdev->num, 0); if (rc < 0) goto command_ack_q_fail; @@ -604,14 +603,12 @@ static int camera_v4l2_close(struct file *filep) camera_pack_event(filep, MSM_CAMERA_SET_PARM, MSM_CAMERA_PRIV_DEL_STREAM, -1, &event); - - /* Donot wait, imaging server may have crashed */ msm_post_event(&event, MSM_POST_EVT_TIMEOUT); camera_pack_event(filep, MSM_CAMERA_DEL_SESSION, 0, -1, &event); + msm_post_event(&event, MSM_POST_EVT_TIMEOUT); - /* Donot wait, imaging server may have crashed */ - msm_post_event(&event, -1); + msm_delete_command_ack_q(pvdev->vdev->num, 0); /* This should take care of both normal close * and application crashes */ @@ -620,8 +617,6 @@ static int camera_v4l2_close(struct file *filep) } else { camera_pack_event(filep, MSM_CAMERA_SET_PARM, MSM_CAMERA_PRIV_DEL_STREAM, -1, &event); - - /* Donot wait, imaging server may have crashed */ msm_post_event(&event, MSM_POST_EVT_TIMEOUT); msm_delete_command_ack_q(pvdev->vdev->num, diff --git a/drivers/media/platform/msm/camera_v2/gemini/msm_gemini_hw.c b/drivers/media/platform/msm/camera_v2/gemini/msm_gemini_hw.c index 96470fdb31b..da6f69f9705 100644 --- a/drivers/media/platform/msm/camera_v2/gemini/msm_gemini_hw.c +++ b/drivers/media/platform/msm/camera_v2/gemini/msm_gemini_hw.c @@ -426,7 +426,7 @@ void msm_gemini_hw_delay(struct msm_gemini_hw_cmd *hw_cmd_p, int m_us) } } -int msm_gemini_hw_exec_cmds(struct msm_gemini_hw_cmd *hw_cmd_p, int m_cmds) +int msm_gemini_hw_exec_cmds(struct msm_gemini_hw_cmd *hw_cmd_p, uint32_t m_cmds) { int is_copy_to_user = -1; uint32_t data; diff --git a/drivers/media/platform/msm/camera_v2/gemini/msm_gemini_hw.h b/drivers/media/platform/msm/camera_v2/gemini/msm_gemini_hw.h index 84eed720f44..4a55565528c 100644 --- a/drivers/media/platform/msm/camera_v2/gemini/msm_gemini_hw.h +++ b/drivers/media/platform/msm/camera_v2/gemini/msm_gemini_hw.h @@ -94,7 +94,7 @@ uint32_t msm_gemini_hw_read(struct msm_gemini_hw_cmd *hw_cmd_p); void msm_gemini_hw_write(struct msm_gemini_hw_cmd *hw_cmd_p); int msm_gemini_hw_wait(struct msm_gemini_hw_cmd *hw_cmd_p, int m_us); void msm_gemini_hw_delay(struct msm_gemini_hw_cmd *hw_cmd_p, int m_us); -int msm_gemini_hw_exec_cmds(struct msm_gemini_hw_cmd *hw_cmd_p, int m_cmds); +int msm_gemini_hw_exec_cmds(struct msm_gemini_hw_cmd *hw_cmd_p, uint32_t m_cmds); void msm_gemini_io_dump(int size); #define MSM_GEMINI_PIPELINE_CLK_128MHZ 128 /* 8MP 128MHz */ diff --git a/drivers/media/platform/msm/camera_v2/gemini/msm_gemini_sync.c b/drivers/media/platform/msm/camera_v2/gemini/msm_gemini_sync.c index 010f7a2c016..15a540520f1 100644 --- a/drivers/media/platform/msm/camera_v2/gemini/msm_gemini_sync.c +++ b/drivers/media/platform/msm/camera_v2/gemini/msm_gemini_sync.c @@ -23,6 +23,7 @@ #include "msm_gemini_platform.h" #include "msm_gemini_common.h" +# define UINT32_MAX (4294967295U) static int release_buf; /* size is based on 4k page size */ @@ -811,7 +812,7 @@ static int msm_gemini_ioctl_hw_cmds(struct msm_gemini_device *pgmn_dev, void * __user arg) { int is_copy_to_user; - int len; + uint32_t len; uint32_t m; struct msm_gemini_hw_cmds *hw_cmds_p; struct msm_gemini_hw_cmd *hw_cmd_p; @@ -820,6 +821,14 @@ static int msm_gemini_ioctl_hw_cmds(struct msm_gemini_device *pgmn_dev, GMN_PR_ERR("%s:%d] failed\n", __func__, __LINE__); return -EFAULT; } + + if ((m == 0) || (m > ((UINT32_MAX-sizeof(struct msm_gemini_hw_cmds))/ + sizeof(struct msm_gemini_hw_cmd)))) { + GMN_PR_ERR("%s:%d] outof range of hwcmds\n", + __func__, __LINE__); + return -EINVAL; + } + if (m > g_max_hw_cmds_cnt) { GMN_PR_ERR("%s:%d] hw_cmds_cnt of %d exceeds limit of %d\n", __func__, __LINE__, m, g_max_hw_cmds_cnt); diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c index 8cc15f6fb21..20178cffc65 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c @@ -24,7 +24,7 @@ #define VFE32_BURST_LEN 3 #define VFE32_UB_SIZE 1024 -#define VFE32_EQUAL_SLICE_UB 204 +#define VFE32_EQUAL_SLICE_UB 198 #define VFE32_WM_BASE(idx) (0x4C + 0x18 * idx) #define VFE32_RDI_BASE(idx) (idx ? 0x734 + 0x4 * (idx - 1) : 0x06FC) #define VFE32_XBAR_BASE(idx) (0x40 + 0x4 * (idx / 4)) @@ -119,7 +119,6 @@ static void msm_vfe32_init_hardware_reg(struct vfe_device *vfe_dev) msm_camera_io_w(0xFFFFFFFF, vfe_dev->vfe_base + 0x24); msm_camera_io_w_mb(0x1FFFFFFF, vfe_dev->vfe_base + 0x28); msm_camera_io_w(0x80000000, vfe_dev->vfe_base + 0x600); - } static void msm_vfe32_process_reset_irq(struct vfe_device *vfe_dev, @@ -813,13 +812,13 @@ static void msm_vfe32_stats_cfg_ub(struct vfe_device *vfe_dev) int i; uint32_t ub_offset = VFE32_UB_SIZE; uint32_t ub_size[VFE32_NUM_STATS_TYPE] = { - 64, /*MSM_ISP_STATS_BG*/ - 64, /*MSM_ISP_STATS_BF*/ - 16, /*MSM_ISP_STATS_AWB*/ - 8, /*MSM_ISP_STATS_RS*/ + 107, /*MSM_ISP_STATS_BG*/ + 92, /*MSM_ISP_STATS_BF*/ + 2, /*MSM_ISP_STATS_AWB*/ + 7, /*MSM_ISP_STATS_RS*/ 16, /*MSM_ISP_STATS_CS*/ - 16, /*MSM_ISP_STATS_IHIST*/ - 16, /*MSM_ISP_STATS_BHIST*/ + 2, /*MSM_ISP_STATS_IHIST*/ + 7, /*MSM_ISP_STATS_BHIST*/ }; for (i = 0; i < VFE32_NUM_STATS_TYPE; i++) { diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c index 34445067040..2061c69db7f 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c @@ -883,10 +883,12 @@ int msm_isp_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) rc = vfe_dev->hw_info->vfe_ops.core_ops.reset_hw(vfe_dev); if (rc <= 0) { - pr_err("%s: reset timeout\n", __func__); + pr_err("%s: reset timeout, rc = %ld\n", __func__, rc); mutex_unlock(&vfe_dev->core_mutex); mutex_unlock(&vfe_dev->realtime_mutex); - return -EINVAL; + if (rc != -ERESTARTSYS) + rc = -EINVAL; + return rc; } vfe_dev->vfe_hw_version = msm_camera_io_r(vfe_dev->vfe_base); ISP_DBG("%s: HW Version: 0x%x\n", __func__, vfe_dev->vfe_hw_version); diff --git a/drivers/media/platform/msm/camera_v2/msm.c b/drivers/media/platform/msm/camera_v2/msm.c index 8a691c5f310..d8ad1d5fd09 100644 --- a/drivers/media/platform/msm/camera_v2/msm.c +++ b/drivers/media/platform/msm/camera_v2/msm.c @@ -402,19 +402,24 @@ void msm_delete_command_ack_q(unsigned int session_id, unsigned int stream_id) list, __msm_queue_find_session, &session_id); if (!session) return; + mutex_lock(&session->lock); cmd_ack = msm_queue_find(&session->command_ack_q, struct msm_command_ack, list, __msm_queue_find_command_ack_q, &stream_id); - if (!cmd_ack) + if (!cmd_ack) { + mutex_unlock(&session->lock); return; + } msm_queue_drain(&cmd_ack->command_q, struct msm_command, list); spin_lock_irqsave(&(session->command_ack_q.lock), flags); list_del_init(&cmd_ack->list); + kzfree(cmd_ack); session->command_ack_q.len--; spin_unlock_irqrestore(&(session->command_ack_q.lock), flags); + mutex_unlock(&session->lock); } static inline int __msm_sd_close_subdevs(struct msm_sd_subdev *msm_sd, @@ -464,6 +469,7 @@ static void msm_remove_session_cmd_ack_q(struct msm_session *session) if (!session) return; + mutex_lock(&session->lock); /* to ensure error handling purpose, it needs to detach all subdevs * which are being connected to streams */ msm_queue_traverse_action(&session->command_ack_q, @@ -471,6 +477,8 @@ static void msm_remove_session_cmd_ack_q(struct msm_session *session) __msm_remove_session_cmd_ack_q, NULL); msm_queue_drain(&session->command_ack_q, struct msm_command_ack, list); + + mutex_unlock(&session->lock); } int msm_destroy_session(unsigned int session_id) @@ -646,7 +654,8 @@ int msm_post_event(struct v4l2_event *event, int timeout) msecs_to_jiffies(timeout)); if (list_empty_careful(&cmd_ack->command_q.list)) { if (!rc) { - pr_err("%s: Timed out\n", __func__); + pr_err("%s: Timed out for event type %d\n", + __func__, event->type); rc = -ETIMEDOUT; } if (rc < 0) { diff --git a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c index 451d81b8a61..d84ffe75141 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c +++ b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c @@ -150,17 +150,20 @@ static int32_t msm_cci_validate_queue(struct cci_device *cci_dev, __func__, __LINE__); rc = wait_for_completion_interruptible_timeout(&cci_dev-> cci_master_info[master].reset_complete, CCI_TIMEOUT); - if (rc <= 0) { + if (rc == -ERESTARTSYS) { + pr_err("%s:%d failed: rc %d", __func__, __LINE__, rc); + } else if (rc <= 0) { pr_err("%s: wait_for_completion_interruptible_timeout %d\n", __func__, __LINE__); if (rc == 0) rc = -ETIMEDOUT; msm_cci_flush_queue(cci_dev, master); return rc; + } else { + rc = cci_dev->cci_master_info[master].status; + if (rc < 0) + pr_err("%s failed rc %d\n", __func__, rc); } - rc = cci_dev->cci_master_info[master].status; - if (rc < 0) - pr_err("%s failed rc %d\n", __func__, rc); } return rc; } @@ -330,7 +333,10 @@ static int32_t msm_cci_i2c_read(struct v4l2_subdev *sd, __LINE__); rc = wait_for_completion_interruptible_timeout(&cci_dev-> cci_master_info[master].reset_complete, CCI_TIMEOUT); - if (rc <= 0) { + if (rc == -ERESTARTSYS) { + pr_err("%s:%d failed: rc %d", __func__, __LINE__, rc); + goto ERROR; + } else if (rc <= 0) { pr_err("%s: wait_for_completion_interruptible_timeout %d\n", __func__, __LINE__); if (rc == 0) @@ -500,7 +506,9 @@ static int32_t msm_cci_i2c_write(struct v4l2_subdev *sd, __func__, __LINE__); rc = wait_for_completion_interruptible_timeout(&cci_dev-> cci_master_info[master].reset_complete, CCI_TIMEOUT); - if (rc <= 0) { + if (rc == -ERESTARTSYS) { + pr_err("%s:%d failed: rc %d", __func__, __LINE__, rc); + } else if (rc <= 0) { pr_err("%s: wait_for_completion_interruptible_timeout %d\n", __func__, __LINE__); if (rc == 0) diff --git a/drivers/power/smb345-charger.c b/drivers/power/smb345-charger.c index d4bb9cdd460..8c3f9405f74 100644 --- a/drivers/power/smb345-charger.c +++ b/drivers/power/smb345-charger.c @@ -624,6 +624,11 @@ static void wireless_isr_work_function(struct work_struct *dat) SMB_NOTICE("wireless state = %d\n", wireless_is_plugged()); + if (otg_on) { + SMB_NOTICE("bypass wireless isr due to otg_on\n"); + return; + } + if (wireless_is_plugged()) wireless_set(); else @@ -632,6 +637,10 @@ static void wireless_isr_work_function(struct work_struct *dat) static void wireless_det_work_function(struct work_struct *dat) { + if (otg_on) { + SMB_NOTICE("bypass wireless isr due to otg_on\n"); + return; + } if (wireless_is_plugged()) wireless_set(); } @@ -776,6 +785,9 @@ void smb345_otg_status(bool on) "otg..\n", __func__); return; } + if (wireless_is_plugged()) + wireless_reset(); + return; } else otg_on = false; diff --git a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_cfg.h b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_cfg.h index 09e60085142..3a2d70b8577 100644 --- a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_cfg.h +++ b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_cfg.h @@ -1608,7 +1608,7 @@ typedef enum #define CFG_TDLS_IMPLICIT_TRIGGER_DEFAULT ( 0 ) #define CFG_TDLS_TX_STATS_PERIOD "gTDLSTxStatsPeriod" -#define CFG_TDLS_TX_STATS_PERIOD_MIN ( 2000 ) +#define CFG_TDLS_TX_STATS_PERIOD_MIN ( 10 ) #define CFG_TDLS_TX_STATS_PERIOD_MAX ( 4294967295UL ) #define CFG_TDLS_TX_STATS_PERIOD_DEFAULT ( 5000 ) @@ -1633,7 +1633,7 @@ typedef enum #define CFG_TDLS_IDLE_TIMEOUT_DEFAULT ( 5000 ) #define CFG_TDLS_IDLE_PACKET_THRESHOLD "gTDLSIdlePacketThreshold" -#define CFG_TDLS_IDLE_PACKET_THRESHOLD_MIN ( 1 ) +#define CFG_TDLS_IDLE_PACKET_THRESHOLD_MIN ( 0 ) #define CFG_TDLS_IDLE_PACKET_THRESHOLD_MAX ( 40000 ) #define CFG_TDLS_IDLE_PACKET_THRESHOLD_DEFAULT ( 5 ) @@ -1651,6 +1651,11 @@ typedef enum #define CFG_TDLS_RSSI_TEARDOWN_THRESHOLD_MIN ( -120 ) #define CFG_TDLS_RSSI_TEARDOWN_THRESHOLD_MAX ( 0 ) #define CFG_TDLS_RSSI_TEARDOWN_THRESHOLD_DEFAULT ( -75 ) + +#define CFG_TDLS_EXTERNAL_CONTROL "gTDLSExternalControl" +#define CFG_TDLS_EXTERNAL_CONTROL_MIN (0) +#define CFG_TDLS_EXTERNAL_CONTROL_MAX (1) +#define CFG_TDLS_EXTERNAL_CONTROL_DEFAULT (0) #endif #ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE @@ -2135,6 +2140,7 @@ typedef struct v_U32_t fTDLSRSSIHysteresis; v_S31_t fTDLSRSSITriggerThreshold; v_S31_t fTDLSRSSITeardownThreshold; + v_BOOL_t fTDLSExternalControl; #endif v_U32_t enableLpwrImgTransition; #ifdef WLAN_SOFTAP_VSTA_FEATURE diff --git a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_main.h b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_main.h index 8ed33322645..33fb44e8cbf 100755 --- a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_main.h +++ b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_main.h @@ -997,24 +997,28 @@ struct hdd_context_s * */ v_U8_t configuredMcastBcastFilter; + v_U8_t sus_res_mcastbcast_filter; + + v_BOOL_t sus_res_mcastbcast_filter_valid; + /* Use below lock to protect access to isSchedScanUpdatePending * since it will be accessed in two different contexts. */ spinlock_t schedScan_lock; - v_U8_t sus_res_mcastbcast_filter; - // Flag keeps track of wiphy suspend/resume v_BOOL_t isWiphySuspended; // Indicates about pending sched_scan results v_BOOL_t isSchedScanUpdatePending; + /* * TX_rx_pkt_count_timer */ vos_timer_t tx_rx_trafficTmr; v_U8_t drvr_miracast; v_U8_t issplitscan_enabled; + }; diff --git a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_tdls.h b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_tdls.h index c0e8bdadae8..bd470ac3883 100644 --- a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_tdls.h +++ b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_tdls.h @@ -125,6 +125,11 @@ typedef struct { } tdls_rssi_config_t; struct _hddTdlsPeer_t; + +typedef struct { + tSirMacAddr macAddr; +} hddTdlsForcePeer_t; + typedef struct { struct list_head peer_list[256]; hdd_adapter_t *pAdapter; @@ -140,6 +145,8 @@ typedef struct { struct _hddTdlsPeer_t *curr_candidate; struct work_struct implicit_setup; v_U32_t magic; + hddTdlsForcePeer_t forcePeer[HDD_MAX_NUM_TDLS_STA]; + tANI_U8 forcePeerCnt; } tdlsCtx_t; typedef struct _hddTdlsPeer_t { @@ -260,5 +267,8 @@ void wlan_hdd_tdls_indicate_teardown(hdd_adapter_t *pAdapter, hddTdlsPeer_t *curr_peer, tANI_U16 reason); +int wlan_hdd_tdls_add_force_peer(hdd_adapter_t *pAdapter, u8 *mac); + +int wlan_hdd_tdls_remove_force_peer(hdd_adapter_t *pAdapter, u8 *mac); #endif // __HDD_TDSL_H diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_assoc.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_assoc.c index c68522e4113..d3bf1a024bb 100755 --- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_assoc.c +++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_assoc.c @@ -2301,7 +2301,14 @@ eHalStatus hdd_smeRoamCallback( void *pContext, tCsrRoamInfo *pRoamInfo, tANI_U3 hdd_conf_mcastbcast_filter(pHddCtx, FALSE); pHddCtx->configuredMcastBcastFilter = pHddCtx->sus_res_mcastbcast_filter; - + pHddCtx->sus_res_mcastbcast_filter_valid = VOS_FALSE; + + hddLog(VOS_TRACE_LEVEL_INFO, + "offload: disassociation happening, restoring configuredMcastBcastFilter"); + hddLog(VOS_TRACE_LEVEL_INFO,"McastBcastFilter = %d", + pHddCtx->configuredMcastBcastFilter); + hddLog(VOS_TRACE_LEVEL_INFO, + "offload: already called mcastbcast filter"); (WLAN_HDD_GET_CTX(pAdapter))->hdd_mcastbcast_filter_set = FALSE; } #ifdef WLAN_FEATURE_PACKET_FILTERING diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_cfg.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_cfg.c index 8c951e9a9dd..cb9a5b9a367 100644 --- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_cfg.c +++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_cfg.c @@ -2161,6 +2161,12 @@ REG_VARIABLE( CFG_TDLS_RSSI_TEARDOWN_THRESHOLD, WLAN_PARAM_SignedInteger, CFG_TDLS_RSSI_TEARDOWN_THRESHOLD_DEFAULT, CFG_TDLS_RSSI_TEARDOWN_THRESHOLD_MIN, CFG_TDLS_RSSI_TEARDOWN_THRESHOLD_MAX ), +REG_VARIABLE( CFG_TDLS_EXTERNAL_CONTROL, WLAN_PARAM_Integer, + hdd_config_t, fTDLSExternalControl, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_TDLS_EXTERNAL_CONTROL_DEFAULT, + CFG_TDLS_EXTERNAL_CONTROL_MIN, + CFG_TDLS_EXTERNAL_CONTROL_MAX ), #endif #ifdef WLAN_SOFTAP_VSTA_FEATURE diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_cfg80211.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_cfg80211.c index aa9598061ce..2986887774a 100755 --- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_cfg80211.c +++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_cfg80211.c @@ -6734,6 +6734,9 @@ static int wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy, (eConnectionState_Associated == (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState)) { + + hddLog(VOS_TRACE_LEVEL_INFO, + "offload: in cfg80211_set_power_mgmt, calling arp offload"); vos_status = hdd_conf_arp_offload(pAdapter, TRUE); if (!VOS_IS_STATUS_SUCCESS(vos_status)) { @@ -7565,15 +7568,6 @@ static int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *d hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); hdd_context_t *pHddCtx = wiphy_priv(wiphy); int status; -#ifdef WLAN_FEATURE_TDLS_DEBUG - const char *tdls_oper_str[]= { - "NL80211_TDLS_DISCOVERY_REQ", - "NL80211_TDLS_SETUP", - "NL80211_TDLS_TEARDOWN", - "NL80211_TDLS_ENABLE_LINK", - "NL80211_TDLS_DISABLE_LINK", - "NL80211_TDLS_UNKNOWN_OPER"}; -#endif if ( NULL == peer ) { @@ -7591,15 +7585,6 @@ static int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *d return status; } -#ifdef WLAN_FEATURE_TDLS_DEBUG - if((int)oper > 4) - oper = 5; - - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s: " MAC_ADDRESS_STR " %d (%s) ", "tdls_oper", - MAC_ADDR_ARRAY(peer), (int)oper, - tdls_oper_str[(int)oper]); -#endif if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport || FALSE == sme_IsFeatureSupportedByFW(TDLS)) @@ -7698,7 +7683,63 @@ static int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *d } break; case NL80211_TDLS_TEARDOWN: + { + hddTdlsPeer_t *pTdlsPeer; + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + " %s : NL80211_TDLS_TEARDOWN for " MAC_ADDRESS_STR, + __func__, MAC_ADDR_ARRAY(peer)); + + if ( (FALSE == pHddCtx->cfg_ini->fTDLSExternalControl) || + (FALSE == pHddCtx->cfg_ini->fEnableTDLSImplicitTrigger) ) { + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + " %s TDLS External control and Implicit Trigger not enabled ", + __func__); + return -ENOTSUPP; + } + + if ( 0 != wlan_hdd_tdls_remove_force_peer(pAdapter, peer) ) + return -EINVAL; + + pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer); + + if ( NULL == pTdlsPeer ) { + hddLog(VOS_TRACE_LEVEL_INFO, "%s: " MAC_ADDRESS_STR + " (oper %d) peer not exsting", + __func__, MAC_ADDR_ARRAY(peer)); + } + else { + wlan_hdd_tdls_indicate_teardown(pAdapter, pTdlsPeer, + eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON); + } + break; + } case NL80211_TDLS_SETUP: + { + hddTdlsPeer_t *pTdlsPeer; + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + " %s : NL80211_TDLS_SETUP for " MAC_ADDRESS_STR, + __func__, MAC_ADDR_ARRAY(peer)); + + if ( (FALSE == pHddCtx->cfg_ini->fTDLSExternalControl) || + (FALSE == pHddCtx->cfg_ini->fEnableTDLSImplicitTrigger) ) { + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + " %s TDLS External control and Implicit Trigger not enabled ", + __func__); + return -ENOTSUPP; + } + + if ( 0 != wlan_hdd_tdls_add_force_peer(pAdapter, peer) ) + return -EINVAL; + /* To cater the requirement of establishing the TDLS link + * irrespective of the data traffic , get an entry of TDLS peer. + */ + pTdlsPeer = wlan_hdd_tdls_get_peer(pAdapter, peer); + if (pTdlsPeer == NULL) + return -EINVAL; + break; + } case NL80211_TDLS_DISCOVERY_REQ: /* We don't support in-driver setup/teardown/discovery */ return -ENOTSUPP; diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_early_suspend.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_early_suspend.c index 0a974d02126..b3e798efe53 100644 --- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_early_suspend.c +++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_early_suspend.c @@ -647,10 +647,11 @@ void hdd_conf_ns_offload(hdd_adapter_t *pAdapter, v_BOOL_t fenable) hddLog (VOS_TRACE_LEVEL_INFO, "configuredMcastBcastFilter: %d",pHddCtx->configuredMcastBcastFilter); - if((HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST == - pHddCtx->configuredMcastBcastFilter) || - (HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST_BROADCAST == - pHddCtx->configuredMcastBcastFilter)) + if ((VOS_TRUE == pHddCtx->sus_res_mcastbcast_filter_valid) + && ((HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST == + pHddCtx->sus_res_mcastbcast_filter) || + (HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST_BROADCAST == + pHddCtx->sus_res_mcastbcast_filter))) { hddLog (VOS_TRACE_LEVEL_INFO, "Set offLoadRequest with SIR_OFFLOAD_NS_AND_MCAST_FILTER_ENABLE \n", __func__); @@ -736,15 +737,21 @@ VOS_STATUS hdd_conf_arp_offload(hdd_adapter_t *pAdapter, v_BOOL_t fenable) hddLog(VOS_TRACE_LEVEL_INFO, "%s: Enabled \n", __func__); - if((HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST == - pHddCtx->configuredMcastBcastFilter) || - (HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST_BROADCAST == - pHddCtx->configuredMcastBcastFilter)) + if (((HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST == + pHddCtx->sus_res_mcastbcast_filter) || + (HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST_BROADCAST == + pHddCtx->sus_res_mcastbcast_filter)) && + (VOS_TRUE == pHddCtx->sus_res_mcastbcast_filter_valid)) { offLoadRequest.enableOrDisable = - SIR_OFFLOAD_ARP_AND_BCAST_FILTER_ENABLE; + SIR_OFFLOAD_ARP_AND_BCAST_FILTER_ENABLE; + hddLog(VOS_TRACE_LEVEL_INFO, + "offload: inside arp offload conditional check"); } + hddLog(VOS_TRACE_LEVEL_INFO, "offload: arp filter programmed = %d", + offLoadRequest.enableOrDisable); + //converting u32 to IPV4 address for(i = 0 ; i < 4; i++) { @@ -870,8 +877,16 @@ static void hdd_conf_suspend_ind(hdd_context_t* pHddCtx, tpSirWlanSuspendParam wlanSuspendParam = vos_mem_malloc(sizeof(tSirWlanSuspendParam)); - pHddCtx->sus_res_mcastbcast_filter = - pHddCtx->configuredMcastBcastFilter; + if (VOS_FALSE == pHddCtx->sus_res_mcastbcast_filter_valid) { + pHddCtx->sus_res_mcastbcast_filter = + pHddCtx->configuredMcastBcastFilter; + pHddCtx->sus_res_mcastbcast_filter_valid = VOS_TRUE; + hddLog(VOS_TRACE_LEVEL_INFO, "offload: hdd_conf_suspend_ind"); + hddLog(VOS_TRACE_LEVEL_INFO, "configuredMCastBcastFilter saved = %d", + pHddCtx->configuredMcastBcastFilter); + + } + if(NULL == wlanSuspendParam) { @@ -924,30 +939,36 @@ static void hdd_conf_resume_ind(hdd_adapter_t *pAdapter) hddLog(VOS_TRACE_LEVEL_INFO, "%s: send wlan resume indication", __func__); - if (pHddCtx->hdd_mcastbcast_filter_set == TRUE) - { - wlanResumeParam = vos_mem_malloc(sizeof(tSirWlanResumeParam)); + wlanResumeParam = vos_mem_malloc(sizeof(tSirWlanResumeParam)); - if(NULL == wlanResumeParam) - { - hddLog(VOS_TRACE_LEVEL_FATAL, - "%s: vos_mem_alloc failed ", __func__); - return; - } + if (NULL == wlanResumeParam) + { + hddLog(VOS_TRACE_LEVEL_FATAL, + "%s: memory allocation failed for wlanResumeParam ", __func__); + return; + } - //Disable supported OffLoads - hdd_conf_hostoffload(pAdapter, FALSE); + //Disable supported OffLoads + hdd_conf_hostoffload(pAdapter, FALSE); - wlanResumeParam->configuredMcstBcstFilterSetting = - pHddCtx->configuredMcastBcastFilter; - halStatus = sme_ConfigureResumeReq(pHddCtx->hHal, wlanResumeParam); - if (eHAL_STATUS_SUCCESS != halStatus) - vos_mem_free(wlanResumeParam); - pHddCtx->hdd_mcastbcast_filter_set = FALSE; + wlanResumeParam->configuredMcstBcstFilterSetting = + pHddCtx->configuredMcastBcastFilter; + halStatus = sme_ConfigureResumeReq(pHddCtx->hHal, wlanResumeParam); + if (eHAL_STATUS_SUCCESS != halStatus) + { + vos_mem_free(wlanResumeParam); } + pHddCtx->hdd_mcastbcast_filter_set = FALSE; + pHddCtx->configuredMcastBcastFilter = pHddCtx->sus_res_mcastbcast_filter; + pHddCtx->sus_res_mcastbcast_filter_valid = VOS_FALSE; + + hddLog(VOS_TRACE_LEVEL_INFO, + "offload: in hdd_conf_resume_ind, restoring configuredMcastBcastFilter"); + hddLog(VOS_TRACE_LEVEL_INFO, "configuredMcastBcastFilter = %d", + pHddCtx->configuredMcastBcastFilter); #ifdef WLAN_FEATURE_PACKET_FILTERING @@ -1080,7 +1101,19 @@ static void hdd_PowerStateChangedCB spin_lock(&pHddCtx->filter_lock); if((newState == BMPS) && pHddCtx->hdd_wlan_suspended) { spin_unlock(&pHddCtx->filter_lock); - pHddCtx->sus_res_mcastbcast_filter = pHddCtx->configuredMcastBcastFilter; + if (VOS_FALSE == pHddCtx->sus_res_mcastbcast_filter_valid) { + pHddCtx->sus_res_mcastbcast_filter = + pHddCtx->configuredMcastBcastFilter; + pHddCtx->sus_res_mcastbcast_filter_valid = VOS_TRUE; + + hddLog(VOS_TRACE_LEVEL_INFO, "offload: callback to associated"); + hddLog(VOS_TRACE_LEVEL_INFO, "saving configuredMcastBcastFilter = %d", + pHddCtx->configuredMcastBcastFilter); + hddLog(VOS_TRACE_LEVEL_INFO, + "offload: calling hdd_conf_mcastbcast_filter"); + + } + hdd_conf_mcastbcast_filter(pHddCtx, TRUE); if(pHddCtx->hdd_mcastbcast_filter_set != TRUE) hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not able to set mcast/bcast filter ", __func__); diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_tdls.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_tdls.c index 4242081bced..189f4b99ca0 100644 --- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_tdls.c +++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_tdls.c @@ -45,7 +45,7 @@ static struct mutex tdls_lock; static tANI_S32 wlan_hdd_get_tdls_discovery_peer_cnt(tdlsCtx_t *pHddTdlsCtx); static tANI_S32 wlan_hdd_tdls_peer_reset_discovery_processed(tdlsCtx_t *pHddTdlsCtx); static void wlan_hdd_tdls_timers_destroy(tdlsCtx_t *pHddTdlsCtx); - +int wpa_tdls_is_allowed_force_peer(tdlsCtx_t *pHddTdlsCtx, u8 *mac); #ifdef CONFIG_TDLS_IMPLICIT static void wlan_hdd_tdls_pre_setup(struct work_struct *work); #endif @@ -258,6 +258,7 @@ static v_VOID_t wlan_hdd_tdls_update_peer_cb( v_PVOID_t userData ) struct list_head *pos; hddTdlsPeer_t *curr_peer; tdlsCtx_t *pHddTdlsCtx; + hdd_context_t *pHddCtx; if (mutex_lock_interruptible(&tdls_lock)) { @@ -278,6 +279,14 @@ static v_VOID_t wlan_hdd_tdls_update_peer_cb( v_PVOID_t userData ) return; } + pHddCtx = WLAN_HDD_GET_CTX( pHddTdlsCtx->pAdapter ); + + if (NULL == pHddCtx) + { + mutex_unlock(&tdls_lock); + return; + } + for (i = 0; i < 256; i++) { head = &pHddTdlsCtx->peer_list[i]; @@ -288,6 +297,10 @@ static v_VOID_t wlan_hdd_tdls_update_peer_cb( v_PVOID_t userData ) "%s: " MAC_ADDRESS_STR " link_status %d" " tdls_support %d", __func__, MAC_ADDR_ARRAY(curr_peer->peerMac), curr_peer->link_status, curr_peer->tdls_support); + if (pHddCtx->cfg_ini->fTDLSExternalControl && + (0 == wpa_tdls_is_allowed_force_peer (pHddTdlsCtx, curr_peer->peerMac))) { + continue; + } if (eTDLS_CAP_SUPPORTED == curr_peer->tdls_support) { VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, @@ -338,10 +351,15 @@ static v_VOID_t wlan_hdd_tdls_update_peer_cb( v_PVOID_t userData ) goto next_peer; } - if ((curr_peer->tx_pkt < + /* Only teardown based on non zero idle packet threshold, to address a use + * case where this threshold does not get consider for TEAR DOWN. + */ + + if (( 0 != pHddTdlsCtx->threshold_config.idle_packet_n ) && + ((curr_peer->tx_pkt < pHddTdlsCtx->threshold_config.idle_packet_n) && (curr_peer->rx_pkt < - pHddTdlsCtx->threshold_config.idle_packet_n)) { + pHddTdlsCtx->threshold_config.idle_packet_n))) { if (VOS_TIMER_STATE_RUNNING != vos_timer_getCurrentState(&curr_peer->peerIdleTimer)) { VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, @@ -1146,6 +1164,137 @@ int wlan_hdd_tdls_set_sta_id(hdd_adapter_t *pAdapter, u8 *mac, u8 staId) return 0; } +int wpa_tdls_is_allowed_force_peer(tdlsCtx_t *pHddTdlsCtx, u8 *mac) +{ + int i; + for (i=0; iforcePeerCnt; i++) + { + if (!memcmp(mac, pHddTdlsCtx->forcePeer[i].macAddr, 6)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: " MAC_ADDRESS_STR "is a forced peer", + __func__,MAC_ADDR_ARRAY(mac)); + return 1; + } + } + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: " MAC_ADDRESS_STR "is not a forced peer", + __func__,MAC_ADDR_ARRAY(mac)); + return 0; +} + +int wlan_hdd_tdls_remove_force_peer(hdd_adapter_t *pAdapter, u8 *mac) +{ + int i; + tdlsCtx_t *pHddTdlsCtx; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + if ((NULL == pHddCtx)) return -1; + + if (mutex_lock_interruptible(&tdls_lock)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: unable to lock list", __func__); + return -1; + } + + pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter); + if (NULL == pHddTdlsCtx) + { + mutex_unlock(&tdls_lock); + return -1; + } + + for (i=0; iforcePeer[i].macAddr, 6)) + { + /* + * Entry Already Exists,Clear the entry and return. + */ + memset(pHddTdlsCtx->forcePeer[i].macAddr, 0, 6); + pHddTdlsCtx->forcePeerCnt--; + mutex_unlock(&tdls_lock); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Removed the requested foce peer", __func__); + return 0; + } + } + + /* Should not have come here if the existing entry has to be removed */ + mutex_unlock(&tdls_lock); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to remove the requested force peer: No Entry Found ", __func__); + return -1; +} + +int wlan_hdd_tdls_add_force_peer(hdd_adapter_t *pAdapter, u8 *mac) +{ + int i =0; + tdlsCtx_t *pHddTdlsCtx; + tANI_U8 zeroMac[6] = {0}; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + if ((NULL == pHddCtx)) return -1; + + if (mutex_lock_interruptible(&tdls_lock)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: unable to lock list", __func__); + return -1; + } + + pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter); + if (NULL == pHddTdlsCtx) + { + mutex_unlock(&tdls_lock); + return -1; + } + + if (pHddTdlsCtx->forcePeerCnt >= HDD_MAX_NUM_TDLS_STA ) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Fail to add the requested foce peer : Quota Full" + " forcePeerCnt is %d ", __func__,pHddTdlsCtx->forcePeerCnt); + /* Quota Full, hence return failure from here*/ + goto error; + } + + for (i=0; iforcePeer[i].macAddr, 6)) + { + /* + * Entry Already Exists,No need to create a new one. + * Hence return from here. + */ + mutex_unlock(&tdls_lock); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Add the requested foce peer success : Entry present" + " forcePeerCnt is %d ", __func__, + pHddTdlsCtx->forcePeerCnt); + return 0; + } + } + for (i=0; iforcePeer[i].macAddr, zeroMac, 6) ) + { + memcpy(pHddTdlsCtx->forcePeer[i].macAddr, mac, 6); + pHddTdlsCtx->forcePeerCnt++; + mutex_unlock(&tdls_lock); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Add the requested foce peer success at index i" + " forcePeerCnt is %d ", __func__, i, + pHddTdlsCtx->forcePeerCnt); + return 0; + } + } +error: + mutex_unlock(&tdls_lock); + return -1; +} + /* if peerMac is found, then it returns pointer to hddTdlsPeer_t otherwise, it returns NULL */ diff --git a/drivers/staging/prima/CORE/MAC/inc/qwlan_version.h b/drivers/staging/prima/CORE/MAC/inc/qwlan_version.h index 707407aca66..50398427319 100644 --- a/drivers/staging/prima/CORE/MAC/inc/qwlan_version.h +++ b/drivers/staging/prima/CORE/MAC/inc/qwlan_version.h @@ -60,9 +60,9 @@ BRIEF DESCRIPTION: #define QWLAN_VERSION_MINOR 2 #define QWLAN_VERSION_PATCH 3 #define QWLAN_VERSION_EXTRA "" -#define QWLAN_VERSION_BUILD 10 +#define QWLAN_VERSION_BUILD 13 -#define QWLAN_VERSIONSTR "3.2.3.10" +#define QWLAN_VERSIONSTR "3.2.3.13" #endif /* QWLAN_VERSION_H */ diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c index b0b5f5cc7ae..77cbd6fcbd8 100755 --- a/drivers/usb/otg/msm_otg.c +++ b/drivers/usb/otg/msm_otg.c @@ -3262,7 +3262,7 @@ static irqreturn_t msm_otg_acok_irq(int irq, void *dev_id) struct msm_otg *motg = dev_id; queue_delayed_work(msm_otg_acok_wq, &motg->acok_irq_work, 0.6*HZ); - wake_lock_timeout(&motg->wlock, 1*HZ); + wake_lock_timeout(&motg->cable_lock, 1*HZ); return IRQ_HANDLED; } @@ -3272,7 +3272,7 @@ static irqreturn_t msm_otg_id_pin_irq(int irq, void *dev_id) struct msm_otg *motg = dev_id; queue_delayed_work(msm_otg_id_pin_wq, &motg->id_pin_irq_work, 0.6*HZ); - wake_lock_timeout(&motg->wlock, 1*HZ); + wake_lock_timeout(&motg->cable_lock, 1*HZ); return IRQ_HANDLED; } @@ -4039,6 +4039,7 @@ static int __init msm_otg_probe(struct platform_device *pdev) if (ret) dev_dbg(&pdev->dev, "MHL can not be supported\n"); wake_lock_init(&motg->wlock, WAKE_LOCK_SUSPEND, "msm_otg"); + wake_lock_init(&motg->cable_lock, WAKE_LOCK_SUSPEND, "msm_cable_dectect"); msm_otg_init_timer(motg); INIT_WORK(&motg->sm_work, msm_otg_sm_work); INIT_DELAYED_WORK(&motg->chg_work, msm_chg_detect_work); @@ -4161,6 +4162,7 @@ static int __init msm_otg_probe(struct platform_device *pdev) free_irq(motg->irq, motg); destroy_wlock: wake_lock_destroy(&motg->wlock); + wake_lock_destroy(&motg->cable_lock); clk_disable_unprepare(motg->core_clk); msm_hsusb_ldo_enable(motg, 0); free_ldo_init: @@ -4219,6 +4221,7 @@ static int __devexit msm_otg_remove(struct platform_device *pdev) device_init_wakeup(&pdev->dev, 0); pm_runtime_disable(&pdev->dev); wake_lock_destroy(&motg->wlock); + wake_lock_destroy(&motg->cable_lock); msm_otg_id_pin_free(motg); msm_otg_acok_free(motg); @@ -4361,12 +4364,12 @@ static int msm_otg_pm_resume(struct device *dev) if (gpio_get_value(vbus_det_gpio) != global_vbus_suspend_status) { dev_info(dev, "%s: usb vbus change in suspend\n", __func__); - wake_lock_timeout(&motg->wlock, 1*HZ); + wake_lock_timeout(&motg->cable_lock, 1*HZ); } if (gpio_get_value(id_gpio) != global_id_pin_suspend_status) { dev_info(dev, "%s: usb id pin change in suspend\n", __func__); - wake_lock_timeout(&motg->wlock, 1*HZ); + wake_lock_timeout(&motg->cable_lock, 1*HZ); } return 0; diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c index 03d6e658973..6f05e97a920 100644 --- a/drivers/video/msm/mdp4_overlay.c +++ b/drivers/video/msm/mdp4_overlay.c @@ -44,6 +44,8 @@ #define VERSION_KEY_MASK 0xFFFFFF00 +static u64 MDP_BUS_SCALE_MIN_IB_FOR_MAX_LAYERS = 0x60000000; + struct mdp4_overlay_ctrl { struct mdp4_overlay_pipe plist[OVERLAY_PIPE_MAX]; struct mdp4_overlay_pipe *stage[MDP4_MIXER_MAX][MDP4_MIXER_STAGE_MAX]; @@ -3027,6 +3029,13 @@ int mdp4_overlay_mdp_perf_req(struct msm_fb_data_type *mfd) } } + /* Flo specific change to increase IB request when we have >4 layers + * but not all of them are covering the whole screen */ + if (cnt > 4) { + ib_quota_total = max(ib_quota_total, + MDP_BUS_SCALE_MIN_IB_FOR_MAX_LAYERS); + } + perf_req->mdp_ab_bw = roundup(ab_quota_total, MDP_BUS_SCALE_AB_STEP); perf_req->mdp_ib_bw = roundup(ib_quota_total, MDP_BUS_SCALE_AB_STEP); diff --git a/drivers/video/msm/vidc/common/enc/venc_internal.c b/drivers/video/msm/vidc/common/enc/venc_internal.c index 808ba7999f0..7418ac4e0ae 100644 --- a/drivers/video/msm/vidc/common/enc/venc_internal.c +++ b/drivers/video/msm/vidc/common/enc/venc_internal.c @@ -1584,7 +1584,12 @@ u32 vid_enc_set_buffer(struct video_client_ctx *client_ctx, enum vcd_buffer_type vcd_buffer_t = VCD_BUFFER_INPUT; enum buffer_dir dir_buffer = BUFFER_TYPE_INPUT; u32 vcd_status = VCD_ERR_FAIL; - unsigned long kernel_vaddr, length = 0; + unsigned long kernel_vaddr, length, user_vaddr, phy_addr = 0; + int pmem_fd = 0; + struct ion_handle *buff_handle = NULL; + u32 ion_flag = 0; + struct file *file = NULL; + s32 buffer_index = 0; if (!client_ctx || !buffer_info) return false; @@ -1606,6 +1611,39 @@ u32 vid_enc_set_buffer(struct video_client_ctx *client_ctx, return false; } + /* + * Invalidate output buffers explcitly once, during registration + * This ensures any pending CPU writes (eg. memset 0 after allocation) + * are not flushed _after_the hardware has written bitstream. + * rare bug, but can happen + */ + if (buffer == VEN_BUFFER_TYPE_OUTPUT) { + user_vaddr = (unsigned long)buffer_info->pbuffer; + if (!vidc_lookup_addr_table(client_ctx, BUFFER_TYPE_OUTPUT, + true, &user_vaddr, &kernel_vaddr, + &phy_addr, &pmem_fd, &file, + &buffer_index)) { + ERR("%s(): vidc_lookup_addr_table failed\n", + __func__); + return false; + } + + ion_flag = vidc_get_fd_info(client_ctx, BUFFER_TYPE_OUTPUT, + buffer_info->fd, kernel_vaddr, buffer_index, + &buff_handle); + + if (ion_flag == ION_FLAG_CACHED && buff_handle && + kernel_vaddr) { + msm_ion_do_cache_op( + client_ctx->user_ion_client, + buff_handle, + (unsigned long *) kernel_vaddr, + (unsigned long) length, + ION_IOC_INV_CACHES); + } + } + + vcd_status = vcd_set_buffer(client_ctx->vcd_handle, vcd_buffer_t, (u8 *) kernel_vaddr, buffer_info->sz); diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h index d6ffea7101c..14459bf6832 100644 --- a/include/linux/usb/msm_hsusb.h +++ b/include/linux/usb/msm_hsusb.h @@ -333,6 +333,7 @@ struct msm_otg { enum usb_chg_type chg_type; unsigned dcd_time; struct wake_lock wlock; + struct wake_lock cable_lock; struct notifier_block usbdev_nb; unsigned mA_port; struct timer_list id_timer; diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index a225089df5b..96c5f0edb4c 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c @@ -35,7 +35,9 @@ bool skb_flow_dissect(const struct sk_buff *skb, struct flow_keys *flow) struct iphdr _iph; ip: iph = skb_header_pointer(skb, nhoff, sizeof(_iph), &_iph); - if (!iph) + + /* CVE-2013-4348 issue : make sure iph->ihl is not zero ... */ + if (!iph || iph->ihl < 5) return false; if (ip_is_fragment(iph)) diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c index 803bd8274eb..b4d4918c3d5 100644 --- a/sound/soc/codecs/wcd9310.c +++ b/sound/soc/codecs/wcd9310.c @@ -2887,11 +2887,27 @@ static int tabla_codec_reset_interpolator(struct snd_soc_dapm_widget *w, static int tabla_codec_enable_ldo_h(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { + struct snd_soc_codec *codec = w->codec; + struct tabla_priv *tabla = NULL; + + if (codec != NULL) + tabla = snd_soc_codec_get_drvdata(codec); + switch (event) { case SND_SOC_DAPM_POST_PMU: - case SND_SOC_DAPM_POST_PMD: usleep_range(1000, 1000); break; + case SND_SOC_DAPM_POST_PMD: + /* + * Don't disable LDO_H while headset is inserted. + * Headset need LDO_H always on. + */ + if (tabla->h2w_state == H2W_HEADSET) { + snd_soc_update_bits(codec, TABLA_A_LDO_H_MODE_1, + 0x80, 0x80); + } else + usleep_range(1000, 1000); + break; } return 0; } @@ -5199,7 +5215,8 @@ static const struct snd_soc_dapm_widget tabla_dapm_widgets[] = { 0), SND_SOC_DAPM_SUPPLY("LDO_H", TABLA_A_LDO_H_MODE_1, 7, 0, - tabla_codec_enable_ldo_h, SND_SOC_DAPM_POST_PMU), + tabla_codec_enable_ldo_h, SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_SUPPLY("COMP1_CLK", SND_SOC_NOPM, 0, 0, tabla_config_compander, SND_SOC_DAPM_PRE_PMU | diff --git a/sound/soc/msm/asustek_headset.c b/sound/soc/msm/asustek_headset.c index 1dd69251ed7..68b34824d47 100644 --- a/sound/soc/msm/asustek_headset.c +++ b/sound/soc/msm/asustek_headset.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -104,11 +105,16 @@ struct work_struct lineout_work; static void set_hs_micbias(int status) { + struct snd_soc_dapm_widget *w = NULL; + if (wcd9310_codec == NULL) { printk(KERN_INFO "%s: wcd9310_codec = NULL\n", __func__); return; } + w = snd_soc_get_codec_widget(wcd9310_codec->card, + wcd9310_codec, "LDO_H"); + if (status) { snd_soc_update_bits(wcd9310_codec, TABLA_A_MICB_CFILT_2_VAL, 0xFC, (0x28 << 2)); @@ -127,8 +133,14 @@ static void set_hs_micbias(int status) } else { snd_soc_update_bits(wcd9310_codec, TABLA_A_MICB_2_CTL, 0xC0, 0x00); - snd_soc_update_bits(wcd9310_codec, TABLA_A_LDO_H_MODE_1, - 0xff, 0x6d); + /* Keep LDO_H power on while using */ + if (w != NULL && w->power) + printk(KERN_INFO "%s widget LDO_H power on. Keep it\n", + __func__); + else + snd_soc_update_bits(wcd9310_codec, + TABLA_A_LDO_H_MODE_1, 0xff, 0x6d); + if (tabla_check_bandgap_status(wcd9310_codec) == 0) { /* Disable Bandgap Reference power */ printk(KERN_INFO "%s badgap status: OFF power down bandgap\n", From c6359b98de3e9810195f16476368dad40fbd8a9d Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Tue, 10 Dec 2013 17:47:51 +0100 Subject: [PATCH 029/215] ARM: Use -mcpu=cortex-a15 when targeting MSM Krait CPUs Enable compiler optimizations specific to the Cortex-A15 processor when targeting MSM Krait CPUs. This is necessary take advantage of the UDIV/SDIV instructions supported by these processors. To accomplish this, we need to remove the -march=armv7-a ISA restriction from the compiler options because 'cortex-a15' is a superset of 'armv7-a'. Change-Id: I6215aecc11fb4f77c971de7b84f68649ef234357 Signed-off-by: Stepan Moskovchenko --- arch/arm/Makefile | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/arch/arm/Makefile b/arch/arm/Makefile index ded63846c4a..e5f2df04a95 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -69,6 +69,18 @@ arch-$(CONFIG_CPU_32v4T) :=-D__LINUX_ARM_ARCH__=4 -march=armv4t arch-$(CONFIG_CPU_32v4) :=-D__LINUX_ARM_ARCH__=4 -march=armv4 arch-$(CONFIG_CPU_32v3) :=-D__LINUX_ARM_ARCH__=3 -march=armv3 +# Since 'cortex-a15' is a superset of the 'armv7-a' arch spec, we need to +# explicitly redefine the arch options to not include '-march=armv7-a' when +# generating code for Krait, which is compatible with the instruction set of the +# Cortex-A15, because GCC will warn us about ambiguous ISA restrictions caused +# by seemingly conflicting -march and -mcpu options. +# If $(CC) does not support the -mcpu=cortex-a15 option, fall back on passing +# -march=armv7-a to specify the ISA restriction, though this is suboptimal. To +# keep things simpler, we don't bother with a fallback option if the compiler +# doesn't even support -march=armv7-a, since in that situation we would have +# bigger problems. +arch-$(CONFIG_ARCH_MSM_KRAIT) :=-D__LINUX_ARM_ARCH__=7 $(call cc-option,-mcpu=cortex-a15,-march=armv7-a) + # This selects how we optimise for the processor. tune-$(CONFIG_CPU_ARM610) :=-mtune=arm610 tune-$(CONFIG_CPU_ARM710) :=-mtune=arm710 From 999f8c3fdc69e6ad36039ef5ceef345e5ac60ef5 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Tue, 10 Dec 2013 18:37:53 +0100 Subject: [PATCH 030/215] Makefile adjustments Fix commit 064206656b --- Makefile | 12 ++++++------ arch/arm/Kconfig | 10 +++++----- arch/arm/Kconfig.debug | 2 +- arch/arm/Makefile | 4 ---- arch/arm/configs/flo_defconfig | 8 +------- drivers/staging/android/Kconfig | 1 + kernel/sched/Makefile | 9 --------- kernel/trace/Kconfig | 4 +++- 8 files changed, 17 insertions(+), 33 deletions(-) diff --git a/Makefile b/Makefile index ba3b12175ce..1e67a0bf464 100644 --- a/Makefile +++ b/Makefile @@ -615,18 +615,18 @@ endif # Use make W=1 to enable this warning (see scripts/Makefile.build) KBUILD_CFLAGS += $(call cc-disable-warning, unused-but-set-variable) -ifdef CONFIG_FRAME_POINTER -KBUILD_CFLAGS += -fno-omit-frame-pointer -fno-optimize-sibling-calls -else +# ifdef CONFIG_FRAME_POINTER +# KBUILD_CFLAGS += -fno-omit-frame-pointer -fno-optimize-sibling-calls +# else # Some targets (ARM with Thumb2, for example), can't be built with frame # pointers. For those, we don't have FUNCTION_TRACER automatically # select FRAME_POINTER. However, FUNCTION_TRACER adds -pg, and this is # incompatible with -fomit-frame-pointer with current GCC, so we don't use # -fomit-frame-pointer with FUNCTION_TRACER. -ifndef CONFIG_FUNCTION_TRACER +# ifndef CONFIG_FUNCTION_TRACER KBUILD_CFLAGS += -fomit-frame-pointer -endif -endif +# endif +# endif ifdef CONFIG_DEBUG_INFO KBUILD_CFLAGS += -g diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index a54d7ab9e93..e6ea0b1cf21 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -12,13 +12,13 @@ config ARM select GENERIC_ATOMIC64 if (CPU_V6 || !CPU_32v6K || !AEABI) select HAVE_OPROFILE if (HAVE_PERF_EVENTS) select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL - select HAVE_ARCH_KGDB + #select HAVE_ARCH_KGDB select HAVE_KPROBES if !XIP_KERNEL select HAVE_KRETPROBES if (HAVE_KPROBES) - select HAVE_FUNCTION_TRACER if (!XIP_KERNEL) - select HAVE_FTRACE_MCOUNT_RECORD if (!XIP_KERNEL) - select HAVE_DYNAMIC_FTRACE if (!XIP_KERNEL) - select HAVE_FUNCTION_GRAPH_TRACER if (!THUMB2_KERNEL) + #select HAVE_FUNCTION_TRACER if (!XIP_KERNEL) + #select HAVE_FTRACE_MCOUNT_RECORD if (!XIP_KERNEL) + #select HAVE_DYNAMIC_FTRACE if (!XIP_KERNEL) + #select HAVE_FUNCTION_GRAPH_TRACER if (!THUMB2_KERNEL) select ARCH_BINFMT_ELF_RANDOMIZE_PIE select HAVE_GENERIC_DMA_COHERENT select HAVE_KERNEL_GZIP diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index 1c010a809da..85e5542ca8b 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -44,7 +44,7 @@ config ARM_UNWIND config OLD_MCOUNT bool depends on FUNCTION_TRACER && FRAME_POINTER - default y + default n config DEBUG_USER bool "Verbose user fault messages" diff --git a/arch/arm/Makefile b/arch/arm/Makefile index e5f2df04a95..79a8ea6e4ed 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -33,10 +33,6 @@ ifeq ($(CONFIG_MMU),) MMUEXT := -nommu endif -ifeq ($(CONFIG_FRAME_POINTER),y) -KBUILD_CFLAGS +=-fno-omit-frame-pointer -mapcs -mno-sched-prolog -endif - ifeq ($(CONFIG_CC_STACKPROTECTOR),y) KBUILD_CFLAGS +=-fstack-protector endif diff --git a/arch/arm/configs/flo_defconfig b/arch/arm/configs/flo_defconfig index 926fdc9f6ad..04b2fb396fe 100644 --- a/arch/arm/configs/flo_defconfig +++ b/arch/arm/configs/flo_defconfig @@ -3516,7 +3516,6 @@ CONFIG_ASHMEM=y CONFIG_ANDROID_LOGGER=y CONFIG_ANDROID_PERSISTENT_RAM=y CONFIG_ANDROID_RAM_CONSOLE=y -# CONFIG_PERSISTENT_TRACER is not set CONFIG_ANDROID_TIMED_OUTPUT=y CONFIG_ANDROID_TIMED_GPIO=y CONFIG_ANDROID_LOW_MEMORY_KILLER=y @@ -3534,6 +3533,7 @@ CONFIG_PRIMA_WLAN=y CONFIG_PRIMA_WLAN_LFR=y CONFIG_PRIMA_WLAN_OKC=y # CONFIG_PRIMA_WLAN_11AC_HIGH_TP is not set +# CONFIG_QCOM_VOWIFI_11R is not set CONFIG_CPUPOWER=y # @@ -3804,10 +3804,6 @@ CONFIG_RCU_CPU_STALL_VERBOSE=y # CONFIG_CPU_NOTIFIER_ERROR_INJECT is not set # CONFIG_FAULT_INJECTION is not set # CONFIG_DEBUG_PAGEALLOC is not set -CONFIG_HAVE_FUNCTION_TRACER=y -CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y -CONFIG_HAVE_DYNAMIC_FTRACE=y -CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y CONFIG_HAVE_C_RECORDMCOUNT=y CONFIG_TRACING_SUPPORT=y # CONFIG_FTRACE is not set @@ -3815,8 +3811,6 @@ CONFIG_DYNAMIC_DEBUG=y # CONFIG_DMA_API_DEBUG is not set # CONFIG_ATOMIC64_SELFTEST is not set # CONFIG_SAMPLES is not set -CONFIG_HAVE_ARCH_KGDB=y -# CONFIG_KGDB is not set # CONFIG_TEST_KSTRTOX is not set # CONFIG_STRICT_DEVMEM is not set CONFIG_ARM_UNWIND=y diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig index 43d17c27695..815cd7ab2e0 100644 --- a/drivers/staging/android/Kconfig +++ b/drivers/staging/android/Kconfig @@ -43,6 +43,7 @@ config PERSISTENT_TRACER depends on HAVE_FUNCTION_TRACER select FUNCTION_TRACER select ANDROID_PERSISTENT_RAM + default n help persistent_trace traces function calls into a persistent ram buffer that can be decoded and dumped after reboot through diff --git a/kernel/sched/Makefile b/kernel/sched/Makefile index 3ede7d92480..4ef7ddeddb8 100644 --- a/kernel/sched/Makefile +++ b/kernel/sched/Makefile @@ -2,15 +2,6 @@ ifdef CONFIG_FUNCTION_TRACER CFLAGS_REMOVE_clock.o = -pg endif -ifneq ($(CONFIG_SCHED_OMIT_FRAME_POINTER),y) -# According to Alan Modra , the -fno-omit-frame-pointer is -# needed for x86 only. Why this used to be enabled for all architectures is beyond -# me. I suspect most platforms don't need this, but until we know that for sure -# I turn this off for IA-64 only. Andreas Schwab says it's also needed on m68k -# to get a correct value for the wait-channel (WCHAN in ps). --davidm -CFLAGS_core.o := $(PROFILING) -fno-omit-frame-pointer -endif - obj-y += core.o clock.o idle_task.o fair.o rt.o stop_task.o sched_avg.o obj-$(CONFIG_SMP) += cpupri.o obj-$(CONFIG_SCHED_AUTOGROUP) += auto_group.o diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig index bfc6704f1d1..00586680b93 100644 --- a/kernel/trace/Kconfig +++ b/kernel/trace/Kconfig @@ -148,6 +148,7 @@ config FUNCTION_TRACER select KALLSYMS select GENERIC_TRACER select CONTEXT_SWITCH_TRACER + default n help Enable the kernel to trace every kernel function. This is done by using a compiler feature to insert a small, 5-byte No-Operation @@ -328,6 +329,7 @@ config STACK_TRACER select FUNCTION_TRACER select STACKTRACE select KALLSYMS + default n help This special tracer records the maximum stack footprint of the kernel and displays it in /sys/kernel/debug/tracing/stack_trace. @@ -392,7 +394,7 @@ config DYNAMIC_FTRACE bool "enable/disable ftrace tracepoints dynamically" depends on FUNCTION_TRACER depends on HAVE_DYNAMIC_FTRACE - default y + default n help This option will modify all the calls to ftrace dynamically (will patch them out of the binary image and replace them From 61f99ebf1578d676317928b6748001813e6eab57 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Tue, 10 Dec 2013 18:39:19 +0100 Subject: [PATCH 031/215] sched: Fix clear NOHZ_BALANCE_KICK I have faced a sequence where the Idle Load Balance was sometime not triggered for a while on my platform, in the following scenario: CPU 0 and CPU 1 are running tasks and CPU 2 is idle CPU 1 kicks the Idle Load Balance CPU 1 selects CPU 2 as the new Idle Load Balancer CPU 2 sets NOHZ_BALANCE_KICK for CPU 2 CPU 2 sends a reschedule IPI to CPU 2 While CPU 3 wakes up, CPU 0 or CPU 1 migrates a waking up task A on CPU 2 CPU 2 finally wakes up, runs task A and discards the Idle Load Balance task A quickly goes back to sleep (before a tick occurs on CPU 2) CPU 2 goes back to idle with NOHZ_BALANCE_KICK set Whenever CPU 2 will be selected as the ILB, no reschedule IPI will be sent because NOHZ_BALANCE_KICK is already set and no Idle Load Balance will be performed. We must wait for the sched softirq to be raised on CPU 2 thanks to another part the kernel to come back to clear NOHZ_BALANCE_KICK. The proposed solution clears NOHZ_BALANCE_KICK in schedule_ipi if we can't raise the sched_softirq for the Idle Load Balance. Change since V1: - move the clear of NOHZ_BALANCE_KICK in got_nohz_idle_kick if the ILB can't run on this CPU (as suggested by Peter) Signed-off-by: Vincent Guittot Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1370419991-13870-1-git-send-email-vincent.guittot@linaro.org Signed-off-by: Ingo Molnar Git-commit: 873b4c65b519fd769940eb281f77848227d4e5c1 Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git [smuckle@codeaurora.org: minor merge resolution for 3.4 in scheduler_ipi()] Signed-off-by: Steve Muckle Change-Id: I3548612057cccc2ecc29429c129c44183083831f --- kernel/sched/core.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index eea5ec83927..b943d44b425 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -621,7 +621,19 @@ void wake_up_idle_cpu(int cpu) static inline bool got_nohz_idle_kick(void) { int cpu = smp_processor_id(); - return idle_cpu(cpu) && test_bit(NOHZ_BALANCE_KICK, nohz_flags(cpu)); + + if (!test_bit(NOHZ_BALANCE_KICK, nohz_flags(cpu))) + return false; + + if (idle_cpu(cpu) && !need_resched()) + return true; + + /* + * We can't run Idle Load Balance on this CPU for this time so we + * cancel it and clear NOHZ_BALANCE_KICK + */ + clear_bit(NOHZ_BALANCE_KICK, nohz_flags(cpu)); + return false; } #else /* CONFIG_NO_HZ */ @@ -1517,7 +1529,7 @@ void scheduler_ipi(void) /* * Check if someone kicked us for doing the nohz idle load balance. */ - if (unlikely(got_nohz_idle_kick() && !need_resched())) { + if (unlikely(got_nohz_idle_kick())) { this_rq()->idle_balance = 1; raise_softirq_irqoff(SCHED_SOFTIRQ); } From 7a84f6a5131801aacd3b9536c4b2dbee1d49ce47 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Tue, 10 Dec 2013 18:40:01 +0100 Subject: [PATCH 032/215] msm: idle-v7: flush non secure L1 cache lines for l2 GDHS LPM mode It is LPM driver(HLOS) responsiblity to flush non secure lines of L1 cache when the core decide to enter a LPM mode where core get powered off. But current code is not flushing the non secure lines of L1 cache when the core decide to enter into L2 GDHS LPM mode. This change addresses the flushing of non secure lines of L1 cache. CRs-fixed: 555905 Change-Id: I721947386091875994bcb71bd8b9b9b793a72349 Signed-off-by: Murali Nalajala --- arch/arm/mach-msm/idle-v7.S | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-msm/idle-v7.S b/arch/arm/mach-msm/idle-v7.S index 9e823c39568..6ec38f328be 100644 --- a/arch/arm/mach-msm/idle-v7.S +++ b/arch/arm/mach-msm/idle-v7.S @@ -110,6 +110,7 @@ ENTRY(msm_pm_collapse) mov r2, #1 and r1, r2, r1, ASR #30 /* Check if the cache is write back */ orr r1, r0, r1 + and r1, r1, #1 cmp r1, #1 bne skip bl v7_flush_dcache_all From df7b148b206c799e72f6d9754d4c7ea9dc359453 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Tue, 10 Dec 2013 18:40:46 +0100 Subject: [PATCH 033/215] writeback: fix race that cause writeback hung There is a race between mark inode dirty and writeback thread, see the following scenario. In this case, writeback thread will not run though there is dirty_io. __mark_inode_dirty() bdi_writeback_workfn() ... ... spin_lock(&inode->i_lock); ... if (bdi_cap_writeback_dirty(bdi)) { <<< assume wb has dirty_io, so wakeup_bdi is false. <<< the following inode_dirty also have wakeup_bdi false. if (!wb_has_dirty_io(&bdi->wb)) wakeup_bdi = true; } spin_unlock(&inode->i_lock); <<< assume last dirty_io is removed here. pages_written = wb_do_writeback(wb); ... <<< work_list empty and wb has no dirty_io, <<< delayed_work will not be queued. if (!list_empty(&bdi->work_list) || (wb_has_dirty_io(wb) && dirty_writeback_interval)) queue_delayed_work(bdi_wq, &wb->dwork, msecs_to_jiffies(dirty_writeback_interval * 10)); spin_lock(&bdi->wb.list_lock); inode->dirtied_when = jiffies; <<< new dirty_io is added. list_move(&inode->i_wb_list, &bdi->wb.b_dirty); spin_unlock(&bdi->wb.list_lock); <<< though there is dirty_io, but wakeup_bdi is false, <<< so writeback thread will not be waked up and <<< the new dirty_io will not be flushed. if (wakeup_bdi) bdi_wakeup_thread_delayed(bdi); Writeback will run until there is a new flush work queued. This may cause a lot of dirty pages stay in memory for a long time. Signed-off-by: Junxiao Bi Reviewed-by: Jan Kara Cc: Fengguang Wu Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/fs-writeback.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 1b21e0a061d..c0bacaf7053 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -1119,6 +1119,8 @@ void __mark_inode_dirty(struct inode *inode, int flags) bool wakeup_bdi = false; bdi = inode_to_bdi(inode); + spin_unlock(&inode->i_lock); + spin_lock(&bdi->wb.list_lock); if (bdi_cap_writeback_dirty(bdi)) { WARN(!test_bit(BDI_registered, &bdi->state), "bdi-%s not registered\n", bdi->name); @@ -1133,8 +1135,6 @@ void __mark_inode_dirty(struct inode *inode, int flags) wakeup_bdi = true; } - spin_unlock(&inode->i_lock); - spin_lock(&bdi->wb.list_lock); inode->dirtied_when = jiffies; list_move(&inode->i_wb_list, &bdi->wb.b_dirty); spin_unlock(&bdi->wb.list_lock); From 688753ff81d0a47003696cd8b6d67b1269ab3e7d Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Tue, 10 Dec 2013 18:41:23 +0100 Subject: [PATCH 034/215] cfg80211: Fix memory leak When a driver requests a specific regulatory domain after cfg80211 already has one, a struct ieee80211_regdomain is leaked. Change-Id: Id28fc9861b9c911a97bd242439eabca097d76258 Reported-by: Larry Finger Tested-by: Larry Finger Signed-off-by: Larry Finger Signed-off-by: Johannes Berg Git-commit: b7566fc363e23f0efd3fa1e1460f9421cdc0d77e Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git [mattw@codeaurora.org: trivially backport to the msm-3.4 kernel] Signed-off-by: Matt Wagantall --- net/wireless/reg.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) mode change 100644 => 100755 net/wireless/reg.c diff --git a/net/wireless/reg.c b/net/wireless/reg.c old mode 100644 new mode 100755 index 15f347477a9..165937663d3 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -2195,10 +2195,15 @@ static int __set_regdom(const struct ieee80211_regdomain *rd) * However if a driver requested this specific regulatory * domain we keep it for its private use */ - if (last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER) + if (last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER) { + const struct ieee80211_regdomain *tmp; + + tmp = request_wiphy->regd; request_wiphy->regd = rd; - else + kfree(tmp); + } else { kfree(rd); + } rd = NULL; From 63873de2fc4c3d333058d1d5b80c893cefe30b98 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Tue, 10 Dec 2013 19:39:50 +0100 Subject: [PATCH 035/215] Aroma : December release --- release/aroma/META-INF/com/google/android/aroma-config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release/aroma/META-INF/com/google/android/aroma-config b/release/aroma/META-INF/com/google/android/aroma-config index 3f5d3a8f23a..832f1b8fe51 100755 --- a/release/aroma/META-INF/com/google/android/aroma-config +++ b/release/aroma/META-INF/com/google/android/aroma-config @@ -34,7 +34,7 @@ ini_set("rom_name", "Glitch kernel"); ini_set("rom_version", "N7-AOSP"); ini_set("rom_author", "Tk-Glitch"); ini_set("rom_device", "Nexus 7 (2013)"); -ini_set("rom_date", "November 2013"); +ini_set("rom_date", "December 2013"); ini_set("force_colorspace","rgba"); #ini_set("dp","6"); From 6cc09524b1cd1595708fd036e0e34ea1d8bb3642 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Sat, 14 Dec 2013 03:39:39 +0100 Subject: [PATCH 036/215] Add a hotplug driver selector and change a few default values --- .../META-INF/com/google/android/aroma-config | 15 ++++++++--- .../com/google/android/updater-script | 25 +++++++++++++++++++ release/aroma/config/buildconfig.sh | 12 +++++++++ release/aroma/config/compatibility2.sh | 13 ++++++++++ release/aroma/system/etc/init.d/99glitch | 15 +++++++++++ 5 files changed, 76 insertions(+), 4 deletions(-) create mode 100644 release/aroma/config/compatibility2.sh diff --git a/release/aroma/META-INF/com/google/android/aroma-config b/release/aroma/META-INF/com/google/android/aroma-config index 832f1b8fe51..0514c9b733c 100755 --- a/release/aroma/META-INF/com/google/android/aroma-config +++ b/release/aroma/META-INF/com/google/android/aroma-config @@ -195,6 +195,13 @@ selectbox( "glitchy","(1.49GHz-4.96GBps)",0 ); +selectbox( + "Hotplug driver","Select default hotplug driver to use\n","@personalize","hotplug.prop", + "Qualcomm mpdecision","(stock)",0, + "Showp1984 msm_mpdecision","",1, + "Faux123 Intelli-plug","",0 +); + selectbox( "Auto Undervolting","Lowers the voltage for the lowest cpu frequency. Undervolting may cause instability.\n","@personalize","uv.prop", "Stock (no undervolt)","",1, @@ -221,8 +228,8 @@ selectbox( selectbox( "Select Battery life eXtender settings","Sets the charge voltage of the battery to extend its lifespan\n","@personalize","ble.prop", - "4.3V","(100% - stock)",0, - "4.2V","(93% - balanced)",1, + "4.3V","(100% - stock)",1, + "4.2V","(93% - balanced)",0, "4.1V","(83% - conservative)",0, "4.0V","(73% - very conservative)",0 ); @@ -231,8 +238,8 @@ checkbox( "Other settings","Select the mods you want to install\n","@personalize","mods.prop", "Sweep2Wake","Sweep across buttons to sleep/wake device",0, "Sweep2Sleep Only","Sweep across buttons to sleep device",1, - "S2W/DT2W power toggle","Makes the power button toggle s2w/dt2w",0, - "Shortsweep","Shorter sweep distance for Sweep2Wake",1, + "S2W/DT2W power toggle","Makes the power button toggle s2w/dt2w",1, + "Shortsweep","Shorter sweep distance for Sweep2Wake",0, "DoubleTap2Wake","Double tap screen to wake device",1, "Disable magnetic on/off","",0, "Enable USB OTG+Charge mode","Allows charging in USB host mode (disables self-powered OTG)",0 diff --git a/release/aroma/META-INF/com/google/android/updater-script b/release/aroma/META-INF/com/google/android/updater-script index edf4ba29aaf..ebb0de7e058 100755 --- a/release/aroma/META-INF/com/google/android/updater-script +++ b/release/aroma/META-INF/com/google/android/updater-script @@ -220,10 +220,35 @@ delete("/system/lib/modules/scsi_wait_scan.ko"); set_perm(0, 0, 0777, "/tmp/systemcheck.sh"); run_program("/tmp/systemcheck.sh"); +if + file_getprop("/tmp/aroma/hotplug.prop","selected.0") == "1" + then + ui_print("Qualcomm mpdecision enabled"); +ui_print("Renaming binaries..."); +ui_print(" /system/bin/mpdecision_bck -> mpdecision"); +ui_print(" /system/bin/thermald -> thermald_bck"); +run_program("/tmp/compatibility2.sh"); +endif; + +if + file_getprop("/tmp/aroma/hotplug.prop","selected.0") == "2" + then + ui_print("Showp1984 msm_mpdecision enabled"); ui_print("Renaming binaries..."); ui_print(" /system/bin/mpdecision -> mpdecision_bck"); ui_print(" /system/bin/thermald -> thermald_bck"); run_program("/tmp/compatibility.sh"); +endif; + +if + file_getprop("/tmp/aroma/hotplug.prop","selected.0") == "3" + then + ui_print("Faux123 Intelli-plug enabled"); +ui_print("Renaming binaries..."); +ui_print(" /system/bin/mpdecision -> mpdecision_bck"); +ui_print(" /system/bin/thermald -> thermald_bck"); +run_program("/tmp/compatibility.sh"); +endif; ui_print("Installing system files"); package_extract_dir("system", "/system"); diff --git a/release/aroma/config/buildconfig.sh b/release/aroma/config/buildconfig.sh index 391e9070e87..b85055eb396 100755 --- a/release/aroma/config/buildconfig.sh +++ b/release/aroma/config/buildconfig.sh @@ -19,6 +19,18 @@ else echo "MINF=1" >> $CONFIGFILE; fi +#HOTPLUGDRV +HOTPLUGDRV=`cat /tmp/aroma/hotplug.prop | cut -d '=' -f2` +echo -e "\n\n##### Hotplug driver Settings #####\n# 0 to enable qualcomm mpdecision (stock)" >> $CONFIGFILE +echo -e "# 1 to enable msm_mpdecision (recommended)\n# 2 to enable intelli-plug\n" >> $CONFIGFILE +if [ $HOTPLUGDRV = 2 ]; then + echo "HOTPLUGDRV=1" >> $CONFIGFILE; +elif [ $HOTPLUGDRV = 3 ]; then + echo "HOTPLUGDRV=2" >> $CONFIGFILE; +else + echo "HOTPLUGDRV=0" >> $CONFIGFILE; +fi + #S2W S2W=`grep "item.0.1" /tmp/aroma/mods.prop | cut -d '=' -f2` S2S=`grep "item.0.2" /tmp/aroma/mods.prop | cut -d '=' -f2` diff --git a/release/aroma/config/compatibility2.sh b/release/aroma/config/compatibility2.sh new file mode 100644 index 00000000000..872100f16b7 --- /dev/null +++ b/release/aroma/config/compatibility2.sh @@ -0,0 +1,13 @@ +#!/sbin/sh +# + +#remove the binaries as they are no longer needed. (kernel handled) +if [ -e /system/bin/mpdecision_bck ] ; then + busybox mv /system/bin/mpdecision_bck /system/bin/mpdecision +fi +if [ -e /system/bin/thermald ] ; then + busybox mv /system/bin/thermald /system/bin/thermald_bck +fi + +return $? + diff --git a/release/aroma/system/etc/init.d/99glitch b/release/aroma/system/etc/init.d/99glitch index 91816eaac16..e40aeb0f032 100755 --- a/release/aroma/system/etc/init.d/99glitch +++ b/release/aroma/system/etc/init.d/99glitch @@ -50,6 +50,21 @@ echo 384000 > /sys/devices/system/cpu/cpu3/cpufreq/scaling_min_freq; echo Min CPU Frequency: 384000 >> $KERNEL_LOGFILE fi +#Set HOTPLUGDRV +if [ "`grep HOTPLUGDRV=1 $KERNEL_CONF`" ]; then + echo 1 > /sys/kernel/msm_mpdecision/conf/enabled; + echo 0 > /sys/module/intelli_plug/parameters/intelli_plug_active; + echo msm_mpdecision enabled >> $KERNEL_LOGFILE; +elif [ "`grep HOTPLUGDRV=2 $KERNEL_CONF`" ]; then + echo 0 > /sys/kernel/msm_mpdecision/conf/enabled; + echo 1 > /sys/module/intelli_plug/parameters/intelli_plug_active; + echo intelli_plug enabled >> $KERNEL_LOGFILE; +else + echo 0 > /sys/kernel/msm_mpdecision/conf/enabled; + echo 0 > /sys/module/intelli_plug/parameters/intelli_plug_active; + echo qualcomm_mpdecision enabled >> $KERNEL_LOGFILE; +fi + #Set SWEEP2WAKE if [ "`grep SWEEP2WAKE=0 $KERNEL_CONF`" ]; then echo 0 > /sys/android_touch/sweep2wake; From daf26982bd4dbc04b3de22b48474ce6924f46e1a Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Sat, 14 Dec 2013 03:52:52 +0100 Subject: [PATCH 037/215] cpu: noop nonboot_cpu calls if MSM_MPDEC is compiled Signed-off-by: Dennis Rassmann --- include/linux/cpu.h | 2 +- kernel/cpu.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/include/linux/cpu.h b/include/linux/cpu.h index 1743b63de2c..d50d59d8e1b 100644 --- a/include/linux/cpu.h +++ b/include/linux/cpu.h @@ -204,7 +204,7 @@ static inline void cpu_hotplug_driver_unlock(void) #define unregister_hotcpu_notifier(nb) ({ (void)(nb); }) #endif /* CONFIG_HOTPLUG_CPU */ -#ifdef CONFIG_PM_SLEEP_SMP +#if defined(CONFIG_PM_SLEEP_SMP) && !defined(CONFIG_MSM_MPDEC) extern int disable_nonboot_cpus(void); extern void enable_nonboot_cpus(void); #else /* !CONFIG_PM_SLEEP_SMP */ diff --git a/kernel/cpu.c b/kernel/cpu.c index 48663d332f6..900f1856fa8 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -384,6 +384,7 @@ EXPORT_SYMBOL_GPL(cpu_up); #ifdef CONFIG_PM_SLEEP_SMP static cpumask_var_t frozen_cpus; +#if !defined(CONFIG_MSM_MPDEC) void __weak arch_disable_nonboot_cpus_begin(void) { } @@ -469,6 +470,7 @@ void __ref enable_nonboot_cpus(void) out: cpu_maps_update_done(); } +#endif static int __init alloc_frozen_cpus(void) { From 0094d4eb97a1695bfac0ba98aa2558f594c13679 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Sat, 14 Dec 2013 04:01:58 +0100 Subject: [PATCH 038/215] msm_mpdecision : update to latest, thanks to showp1984 --- arch/arm/mach-msm/msm_mpdecision.c | 1660 ++++++++++++++-------------- arch/arm/mach-msm/msm_mpdecision.h | 85 ++ 2 files changed, 936 insertions(+), 809 deletions(-) create mode 100644 arch/arm/mach-msm/msm_mpdecision.h diff --git a/arch/arm/mach-msm/msm_mpdecision.c b/arch/arm/mach-msm/msm_mpdecision.c index 1f133c05c3d..241bc470b89 100644 --- a/arch/arm/mach-msm/msm_mpdecision.c +++ b/arch/arm/mach-msm/msm_mpdecision.c @@ -23,7 +23,12 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#include "msm_mpdecision.h" +#ifndef CONFIG_HAS_EARLYSUSPEND +#include +#else #include +#endif #include #include #include @@ -42,49 +47,17 @@ #define DEBUG 0 -#define MPDEC_TAG "[MPDEC]: " -#define MSM_MPDEC_STARTDELAY 20000 -#define MSM_MPDEC_DELAY 130 -#define MSM_MPDEC_PAUSE 10000 -#define MSM_MPDEC_IDLE_FREQ 486000 -#ifdef CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN -#define MSM_MPDEC_BOOSTTIME 1000 -#define MSM_MPDEC_BOOSTFREQ_CPU0 1026000 -#define MSM_MPDEC_BOOSTFREQ_CPU1 810000 -#define MSM_MPDEC_BOOSTFREQ_CPU2 702000 -#define MSM_MPDEC_BOOSTFREQ_CPU3 594000 -#endif +DEFINE_PER_CPU(struct msm_mpdec_cpudata_t, msm_mpdec_cpudata); +EXPORT_PER_CPU_SYMBOL_GPL(msm_mpdec_cpudata); -enum { - MSM_MPDEC_DISABLED = 0, - MSM_MPDEC_IDLE, - MSM_MPDEC_DOWN, - MSM_MPDEC_UP, -}; - -struct msm_mpdec_cpudata_t { - struct mutex hotplug_mutex; - int online; - int device_suspended; - cputime64_t on_time; - cputime64_t on_time_total; - long long unsigned int times_cpu_hotplugged; - long long unsigned int times_cpu_unplugged; -#ifdef CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN - struct mutex boost_mutex; - struct mutex unboost_mutex; - unsigned long int norm_min_freq; - unsigned long int boost_freq; - cputime64_t boost_until; - bool is_boosted; - bool revib_wq_running; +static bool mpdec_suspended = false; +#ifndef CONFIG_HAS_EARLYSUSPEND +static struct notifier_block msm_mpdec_lcd_notif; #endif -}; -static DEFINE_PER_CPU(struct msm_mpdec_cpudata_t, msm_mpdec_cpudata); - static struct delayed_work msm_mpdec_work; static struct workqueue_struct *msm_mpdec_workq; static DEFINE_MUTEX(mpdec_msm_cpu_lock); +static DEFINE_MUTEX(mpdec_msm_susres_lock); #ifdef CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN static struct workqueue_struct *mpdec_input_wq; static DEFINE_PER_CPU(struct work_struct, mpdec_input_work); @@ -93,35 +66,35 @@ static DEFINE_PER_CPU(struct delayed_work, msm_mpdec_revib_work); #endif static struct msm_mpdec_tuners { - unsigned int startdelay; - unsigned int delay; - unsigned int pause; - bool scroff_single_core; - unsigned long int idle_freq; - unsigned int max_cpus; - unsigned int min_cpus; + unsigned int startdelay; + unsigned int delay; + unsigned int pause; + bool scroff_single_core; + unsigned long int idle_freq; + unsigned int max_cpus; + unsigned int min_cpus; #ifdef CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN - bool boost_enabled; - unsigned int boost_time; - unsigned long int boost_freq[4]; + bool boost_enabled; + unsigned int boost_time; + unsigned long int boost_freq[4]; #endif } msm_mpdec_tuners_ins = { - .startdelay = MSM_MPDEC_STARTDELAY, - .delay = MSM_MPDEC_DELAY, - .pause = MSM_MPDEC_PAUSE, - .scroff_single_core = true, - .idle_freq = MSM_MPDEC_IDLE_FREQ, - .max_cpus = CONFIG_NR_CPUS, - .min_cpus = 1, + .startdelay = MSM_MPDEC_STARTDELAY, + .delay = MSM_MPDEC_DELAY, + .pause = MSM_MPDEC_PAUSE, + .scroff_single_core = true, + .idle_freq = MSM_MPDEC_IDLE_FREQ, + .max_cpus = CONFIG_NR_CPUS, + .min_cpus = 1, #ifdef CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN - .boost_enabled = true, - .boost_time = MSM_MPDEC_BOOSTTIME, - .boost_freq = { - MSM_MPDEC_BOOSTFREQ_CPU0, - MSM_MPDEC_BOOSTFREQ_CPU1, - MSM_MPDEC_BOOSTFREQ_CPU2, - MSM_MPDEC_BOOSTFREQ_CPU3 - }, + .boost_enabled = true, + .boost_time = MSM_MPDEC_BOOSTTIME, + .boost_freq = { + MSM_MPDEC_BOOSTFREQ_CPU0, + MSM_MPDEC_BOOSTFREQ_CPU1, + MSM_MPDEC_BOOSTFREQ_CPU2, + MSM_MPDEC_BOOSTFREQ_CPU3 + }, #endif }; @@ -136,490 +109,543 @@ bool was_paused = false; #ifdef CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN bool is_screen_on = true; static int update_cpu_min_freq(struct cpufreq_policy *cpu_policy, - int cpu, int new_freq); + int cpu, int new_freq); static void unboost_cpu(int cpu); #endif static cputime64_t mpdec_paused_until = 0; static unsigned long get_rate(int cpu) { - return acpuclk_get_rate(cpu); + return acpuclk_get_rate(cpu); } static int get_slowest_cpu(void) { - int i, cpu = 0; - unsigned long rate, slow_rate = 0; - - for (i = 1; i < CONFIG_NR_CPUS; i++) { - if (!cpu_online(i)) - continue; - rate = get_rate(i); - if (slow_rate == 0) { - slow_rate = rate; - } - if ((rate <= slow_rate) && (slow_rate != 0)) { - cpu = i; - slow_rate = rate; - } - } - - return cpu; + int i, cpu = 0; + unsigned long rate, slow_rate = 0; + + for (i = 1; i < CONFIG_NR_CPUS; i++) { + if (!cpu_online(i)) + continue; + rate = get_rate(i); + if (slow_rate == 0) { + cpu = i; + slow_rate = rate; + continue; + } + if ((rate <= slow_rate) && (slow_rate != 0)) { + cpu = i; + slow_rate = rate; + } + } + + return cpu; } static unsigned long get_slowest_cpu_rate(void) { - int i = 0; - unsigned long rate, slow_rate = 0; - - for (i = 0; i < CONFIG_NR_CPUS; i++) { - if (!cpu_online(i)) - continue; - rate = get_rate(i); - if ((rate < slow_rate) && (slow_rate != 0)) { - slow_rate = rate; - } - if (slow_rate == 0) { - slow_rate = rate; - } - } - - return slow_rate; + int i = 0; + unsigned long rate, slow_rate = 0; + + for (i = 0; i < CONFIG_NR_CPUS; i++) { + if (!cpu_online(i)) + continue; + rate = get_rate(i); + if ((rate < slow_rate) && (slow_rate != 0)) { + slow_rate = rate; + continue; + } + if (slow_rate == 0) { + slow_rate = rate; + } + } + + return slow_rate; } static void mpdec_cpu_up(int cpu) { - if (!cpu_online(cpu)) { - mutex_lock(&per_cpu(msm_mpdec_cpudata, cpu).hotplug_mutex); - cpu_up(cpu); - per_cpu(msm_mpdec_cpudata, cpu).on_time = ktime_to_ms(ktime_get()); - per_cpu(msm_mpdec_cpudata, cpu).online = true; - per_cpu(msm_mpdec_cpudata, cpu).times_cpu_hotplugged += 1; - pr_info(MPDEC_TAG"CPU[%d] off->on | Mask=[%d%d%d%d]\n", - cpu, cpu_online(0), cpu_online(1), cpu_online(2), cpu_online(3)); - mutex_unlock(&per_cpu(msm_mpdec_cpudata, cpu).hotplug_mutex); - } + if (!cpu_online(cpu)) { + mutex_lock(&per_cpu(msm_mpdec_cpudata, cpu).hotplug_mutex); + cpu_up(cpu); + per_cpu(msm_mpdec_cpudata, cpu).on_time = ktime_to_ms(ktime_get()); + per_cpu(msm_mpdec_cpudata, cpu).online = true; + per_cpu(msm_mpdec_cpudata, cpu).times_cpu_hotplugged += 1; + pr_info(MPDEC_TAG"CPU[%d] off->on | Mask=[%d%d%d%d]\n", + cpu, cpu_online(0), cpu_online(1), cpu_online(2), cpu_online(3)); + mutex_unlock(&per_cpu(msm_mpdec_cpudata, cpu).hotplug_mutex); + } } EXPORT_SYMBOL_GPL(mpdec_cpu_up); static void mpdec_cpu_down(int cpu) { - cputime64_t on_time = 0; - if (cpu_online(cpu)) { - mutex_lock(&per_cpu(msm_mpdec_cpudata, cpu).hotplug_mutex); - cpu_down(cpu); - on_time = (ktime_to_ms(ktime_get()) - per_cpu(msm_mpdec_cpudata, cpu).on_time); - per_cpu(msm_mpdec_cpudata, cpu).online = false; - per_cpu(msm_mpdec_cpudata, cpu).on_time_total += on_time; - per_cpu(msm_mpdec_cpudata, cpu).times_cpu_unplugged += 1; - pr_info(MPDEC_TAG"CPU[%d] on->off | Mask=[%d%d%d%d] | time online: %llu\n", - cpu, cpu_online(0), cpu_online(1), cpu_online(2), cpu_online(3), on_time); - mutex_unlock(&per_cpu(msm_mpdec_cpudata, cpu).hotplug_mutex); - } + cputime64_t on_time = 0; + if (cpu_online(cpu)) { + mutex_lock(&per_cpu(msm_mpdec_cpudata, cpu).hotplug_mutex); + cpu_down(cpu); + on_time = (ktime_to_ms(ktime_get()) - per_cpu(msm_mpdec_cpudata, cpu).on_time); + per_cpu(msm_mpdec_cpudata, cpu).online = false; + per_cpu(msm_mpdec_cpudata, cpu).on_time_total += on_time; + per_cpu(msm_mpdec_cpudata, cpu).times_cpu_unplugged += 1; + pr_info(MPDEC_TAG"CPU[%d] on->off | Mask=[%d%d%d%d] | time online: %llu\n", + cpu, cpu_online(0), cpu_online(1), cpu_online(2), cpu_online(3), on_time); + mutex_unlock(&per_cpu(msm_mpdec_cpudata, cpu).hotplug_mutex); + } } EXPORT_SYMBOL_GPL(mpdec_cpu_down); static int mp_decision(void) { - static bool first_call = true; - int new_state = MSM_MPDEC_IDLE; - int nr_cpu_online; - int index; - unsigned int rq_depth; - static cputime64_t total_time = 0; - static cputime64_t last_time; - cputime64_t current_time; - cputime64_t this_time = 0; - - if (state == MSM_MPDEC_DISABLED) - return MSM_MPDEC_DISABLED; - - current_time = ktime_to_ms(ktime_get()); - if (current_time <= msm_mpdec_tuners_ins.startdelay) - return MSM_MPDEC_IDLE; - - if (first_call) { - first_call = false; - } else { - this_time = current_time - last_time; - } - total_time += this_time; - - rq_depth = get_rq_info(); - nr_cpu_online = num_online_cpus(); - - if (nr_cpu_online) { - index = (nr_cpu_online - 1) * 2; - if ((nr_cpu_online < CONFIG_NR_CPUS) && (rq_depth >= NwNs_Threshold[index])) { - if ((total_time >= TwTs_Threshold[index]) && - (nr_cpu_online < msm_mpdec_tuners_ins.max_cpus)) { - new_state = MSM_MPDEC_UP; - if (get_slowest_cpu_rate() <= msm_mpdec_tuners_ins.idle_freq) - new_state = MSM_MPDEC_IDLE; - } - } else if ((nr_cpu_online > 1) && (rq_depth <= NwNs_Threshold[index+1])) { - if ((total_time >= TwTs_Threshold[index+1]) && - (nr_cpu_online > msm_mpdec_tuners_ins.min_cpus)) { - new_state = MSM_MPDEC_DOWN; - if (get_slowest_cpu_rate() > msm_mpdec_tuners_ins.idle_freq) - new_state = MSM_MPDEC_IDLE; - } - } else { - new_state = MSM_MPDEC_IDLE; - total_time = 0; - } - } else { - total_time = 0; - } - - if (new_state != MSM_MPDEC_IDLE) { - total_time = 0; - } - - last_time = ktime_to_ms(ktime_get()); + static bool first_call = true; + int new_state = MSM_MPDEC_IDLE; + int nr_cpu_online; + int index; + unsigned int rq_depth; + static cputime64_t total_time = 0; + static cputime64_t last_time; + cputime64_t current_time; + cputime64_t this_time = 0; + + if (state == MSM_MPDEC_DISABLED) + return MSM_MPDEC_DISABLED; + + current_time = ktime_to_ms(ktime_get()); + + if (first_call) { + first_call = false; + } else { + this_time = current_time - last_time; + } + total_time += this_time; + + rq_depth = get_rq_info(); + nr_cpu_online = num_online_cpus(); + + if (nr_cpu_online) { + index = (nr_cpu_online - 1) * 2; + if ((nr_cpu_online < CONFIG_NR_CPUS) && (rq_depth >= NwNs_Threshold[index])) { + if ((total_time >= TwTs_Threshold[index]) && + (nr_cpu_online < msm_mpdec_tuners_ins.max_cpus)) { + new_state = MSM_MPDEC_UP; + if (get_slowest_cpu_rate() <= msm_mpdec_tuners_ins.idle_freq) + new_state = MSM_MPDEC_IDLE; + } + } else if ((nr_cpu_online > 1) && (rq_depth <= NwNs_Threshold[index+1])) { + if ((total_time >= TwTs_Threshold[index+1]) && + (nr_cpu_online > msm_mpdec_tuners_ins.min_cpus)) { + new_state = MSM_MPDEC_DOWN; + if (get_slowest_cpu_rate() > msm_mpdec_tuners_ins.idle_freq) + new_state = MSM_MPDEC_IDLE; + } + } else { + new_state = MSM_MPDEC_IDLE; + total_time = 0; + } + } else { + total_time = 0; + } + + if (new_state != MSM_MPDEC_IDLE) { + total_time = 0; + } + + last_time = ktime_to_ms(ktime_get()); #if DEBUG - pr_info(MPDEC_TAG"[DEBUG] rq: %u, new_state: %i | Mask=[%d%d%d%d]\n", - rq_depth, new_state, cpu_online(0), cpu_online(1), cpu_online(2), cpu_online(3)); + pr_info(MPDEC_TAG"[DEBUG] rq: %u, new_state: %i | Mask=[%d%d%d%d]\n", + rq_depth, new_state, cpu_online(0), cpu_online(1), cpu_online(2), cpu_online(3)); #endif - return new_state; + return new_state; } static void msm_mpdec_work_thread(struct work_struct *work) { - unsigned int cpu = nr_cpu_ids; - bool suspended = false; - - if (ktime_to_ms(ktime_get()) <= msm_mpdec_tuners_ins.startdelay) - goto out; - - /* Check if we are paused */ - if (mpdec_paused_until >= ktime_to_ms(ktime_get())) - goto out; - - for_each_possible_cpu(cpu) { - if ((per_cpu(msm_mpdec_cpudata, cpu).device_suspended == true)) { - suspended = true; - break; - } - } - if (suspended == true) - goto out; - - if (!mutex_trylock(&mpdec_msm_cpu_lock)) - goto out; - - /* if sth messed with the cpus, update the check vars so we can proceed */ - if (was_paused) { - for_each_possible_cpu(cpu) { - if (cpu_online(cpu)) - per_cpu(msm_mpdec_cpudata, cpu).online = true; - else if (!cpu_online(cpu)) - per_cpu(msm_mpdec_cpudata, cpu).online = false; - } - was_paused = false; - } - - state = mp_decision(); - switch (state) { - case MSM_MPDEC_DISABLED: - case MSM_MPDEC_IDLE: - break; - case MSM_MPDEC_DOWN: - cpu = get_slowest_cpu(); - if (cpu < nr_cpu_ids) { - if ((per_cpu(msm_mpdec_cpudata, cpu).online == true) && (cpu_online(cpu))) { + unsigned int cpu = nr_cpu_ids; + + /* Check if we are paused */ + if (mpdec_paused_until >= ktime_to_ms(ktime_get())) + goto out; + + if (mpdec_suspended == true) + goto out; + + if (!mutex_trylock(&mpdec_msm_cpu_lock)) + goto out; + + /* if sth messed with the cpus, update the check vars so we can proceed */ + if (was_paused) { + for_each_possible_cpu(cpu) { + if (cpu_online(cpu)) + per_cpu(msm_mpdec_cpudata, cpu).online = true; + else if (!cpu_online(cpu)) + per_cpu(msm_mpdec_cpudata, cpu).online = false; + } + was_paused = false; + } + + state = mp_decision(); + switch (state) { + case MSM_MPDEC_DISABLED: + case MSM_MPDEC_IDLE: + break; + case MSM_MPDEC_DOWN: + cpu = get_slowest_cpu(); + if (cpu < nr_cpu_ids) { + if ((per_cpu(msm_mpdec_cpudata, cpu).online == true) && (cpu_online(cpu))) { #ifdef CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN - unboost_cpu(cpu); + unboost_cpu(cpu); #endif - mpdec_cpu_down(cpu); - } else if (per_cpu(msm_mpdec_cpudata, cpu).online != cpu_online(cpu)) { - pr_info(MPDEC_TAG"CPU[%d] was controlled outside of mpdecision! | pausing [%d]ms\n", - cpu, msm_mpdec_tuners_ins.pause); - mpdec_paused_until = ktime_to_ms(ktime_get()) + msm_mpdec_tuners_ins.pause; - was_paused = true; - } - } - break; - case MSM_MPDEC_UP: - cpu = cpumask_next_zero(0, cpu_online_mask); - if (cpu < nr_cpu_ids) { - if ((per_cpu(msm_mpdec_cpudata, cpu).online == false) && (!cpu_online(cpu))) { - mpdec_cpu_up(cpu); + mpdec_cpu_down(cpu); + } else if (per_cpu(msm_mpdec_cpudata, cpu).online != cpu_online(cpu)) { + pr_info(MPDEC_TAG"CPU[%d] was controlled outside of mpdecision! | pausing [%d]ms\n", + cpu, msm_mpdec_tuners_ins.pause); + mpdec_paused_until = ktime_to_ms(ktime_get()) + msm_mpdec_tuners_ins.pause; + was_paused = true; + } + } + break; + case MSM_MPDEC_UP: + cpu = cpumask_next_zero(0, cpu_online_mask); + if (cpu < nr_cpu_ids) { + if ((per_cpu(msm_mpdec_cpudata, cpu).online == false) && (!cpu_online(cpu))) { + mpdec_cpu_up(cpu); #ifdef CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN - unboost_cpu(cpu); + unboost_cpu(cpu); #endif - } else if (per_cpu(msm_mpdec_cpudata, cpu).online != cpu_online(cpu)) { - pr_info(MPDEC_TAG"CPU[%d] was controlled outside of mpdecision! | pausing [%d]ms\n", - cpu, msm_mpdec_tuners_ins.pause); - mpdec_paused_until = ktime_to_ms(ktime_get()) + msm_mpdec_tuners_ins.pause; - was_paused = true; - } - } - break; - default: - pr_err(MPDEC_TAG"%s: invalid mpdec hotplug state %d\n", - __func__, state); - } - mutex_unlock(&mpdec_msm_cpu_lock); + } else if (per_cpu(msm_mpdec_cpudata, cpu).online != cpu_online(cpu)) { + pr_info(MPDEC_TAG"CPU[%d] was controlled outside of mpdecision! | pausing [%d]ms\n", + cpu, msm_mpdec_tuners_ins.pause); + mpdec_paused_until = ktime_to_ms(ktime_get()) + msm_mpdec_tuners_ins.pause; + was_paused = true; + } + } + break; + default: + pr_err(MPDEC_TAG"%s: invalid mpdec hotplug state %d\n", + __func__, state); + } + mutex_unlock(&mpdec_msm_cpu_lock); out: - if (state != MSM_MPDEC_DISABLED) - queue_delayed_work(msm_mpdec_workq, &msm_mpdec_work, - msecs_to_jiffies(msm_mpdec_tuners_ins.delay)); - return; + if (state != MSM_MPDEC_DISABLED) + queue_delayed_work(msm_mpdec_workq, &msm_mpdec_work, + msecs_to_jiffies(msm_mpdec_tuners_ins.delay)); + return; } #ifdef CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN static int update_cpu_min_freq(struct cpufreq_policy *cpu_policy, - int cpu, int new_freq) { - int ret = 0; + int cpu, int new_freq) { + int ret = 0; - if (!cpu_policy) - return -EINVAL; + if (!cpu_policy) + return -EINVAL; - cpufreq_verify_within_limits(cpu_policy, new_freq, cpu_policy->max); - cpu_policy->user_policy.min = new_freq; + cpufreq_verify_within_limits(cpu_policy, new_freq, cpu_policy->max); + cpu_policy->user_policy.min = new_freq; - ret = cpufreq_update_policy(cpu); - if (!ret) { - pr_debug(MPDEC_TAG"Touch event! Setting CPU%d min frequency to %d\n", - cpu, new_freq); - } - return ret; + ret = cpufreq_update_policy(cpu); + if (!ret) { + pr_debug(MPDEC_TAG"Touch event! Setting CPU%d min frequency to %d\n", + cpu, new_freq); + } + return ret; } static void unboost_cpu(int cpu) { - struct cpufreq_policy *cpu_policy = NULL; - - if (cpu_online(cpu)) { - if (per_cpu(msm_mpdec_cpudata, cpu).is_boosted) { - if (mutex_trylock(&per_cpu(msm_mpdec_cpudata, cpu).unboost_mutex)) { - cpu_policy = cpufreq_cpu_get(cpu); - if (!cpu_policy) { - pr_debug(MPDEC_TAG"NULL policy on cpu %d\n", cpu); - return; - } + struct cpufreq_policy *cpu_policy = NULL; + + if (cpu_online(cpu)) { + if (per_cpu(msm_mpdec_cpudata, cpu).is_boosted) { + if (mutex_trylock(&per_cpu(msm_mpdec_cpudata, cpu).unboost_mutex)) { + cpu_policy = cpufreq_cpu_get(cpu); + if (!cpu_policy) { + pr_debug(MPDEC_TAG"NULL policy on cpu %d\n", cpu); + return; + } #if DEBUG - pr_info(MPDEC_TAG"un boosted cpu%i to %lu", cpu, per_cpu(msm_mpdec_cpudata, cpu).norm_min_freq); + pr_info(MPDEC_TAG"un boosted cpu%i to %lu", cpu, per_cpu(msm_mpdec_cpudata, cpu).norm_min_freq); #endif - per_cpu(msm_mpdec_cpudata, cpu).is_boosted = false; - per_cpu(msm_mpdec_cpudata, cpu).revib_wq_running = false; - if ((cpu_policy->min != per_cpu(msm_mpdec_cpudata, cpu).boost_freq) && - (cpu_policy->min != per_cpu(msm_mpdec_cpudata, cpu).norm_min_freq)) { - pr_info(MPDEC_TAG"cpu%u min was changed while boosted (%lu->%u), using new min", - cpu, per_cpu(msm_mpdec_cpudata, cpu).norm_min_freq, cpu_policy->min); - per_cpu(msm_mpdec_cpudata, cpu).norm_min_freq = cpu_policy->min; - } - update_cpu_min_freq(cpu_policy, cpu, per_cpu(msm_mpdec_cpudata, cpu).norm_min_freq); - cpufreq_cpu_put(cpu_policy); - mutex_unlock(&per_cpu(msm_mpdec_cpudata, cpu).unboost_mutex); - } - } - } - - return; + per_cpu(msm_mpdec_cpudata, cpu).is_boosted = false; + per_cpu(msm_mpdec_cpudata, cpu).revib_wq_running = false; + if ((cpu_policy->min != per_cpu(msm_mpdec_cpudata, cpu).boost_freq) && + (cpu_policy->min != per_cpu(msm_mpdec_cpudata, cpu).norm_min_freq)) { + pr_info(MPDEC_TAG"cpu%u min was changed while boosted (%lu->%u), using new min", + cpu, per_cpu(msm_mpdec_cpudata, cpu).norm_min_freq, cpu_policy->min); + per_cpu(msm_mpdec_cpudata, cpu).norm_min_freq = cpu_policy->min; + } + update_cpu_min_freq(cpu_policy, cpu, per_cpu(msm_mpdec_cpudata, cpu).norm_min_freq); + cpufreq_cpu_put(cpu_policy); + mutex_unlock(&per_cpu(msm_mpdec_cpudata, cpu).unboost_mutex); + } + } + } + + return; } static void msm_mpdec_revib_work_thread(struct work_struct *work) { - int cpu = smp_processor_id(); - - if (per_cpu(msm_mpdec_cpudata, cpu).is_boosted) { - per_cpu(msm_mpdec_cpudata, cpu).revib_wq_running = true; - if (ktime_to_ms(ktime_get()) > per_cpu(msm_mpdec_cpudata, cpu).boost_until) { - unboost_cpu(cpu); - } else { - queue_delayed_work_on(cpu, - msm_mpdec_revib_workq, - &per_cpu(msm_mpdec_revib_work, cpu), - msecs_to_jiffies((per_cpu(msm_mpdec_cpudata, cpu).boost_until - ktime_to_ms(ktime_get())))); - } - } else { - per_cpu(msm_mpdec_cpudata, cpu).revib_wq_running = false; - } - return; + int cpu = smp_processor_id(); + + if (per_cpu(msm_mpdec_cpudata, cpu).is_boosted) { + per_cpu(msm_mpdec_cpudata, cpu).revib_wq_running = true; + if (ktime_to_ms(ktime_get()) > per_cpu(msm_mpdec_cpudata, cpu).boost_until) { + unboost_cpu(cpu); + } else { + queue_delayed_work_on( + cpu, + msm_mpdec_revib_workq, + &per_cpu(msm_mpdec_revib_work, cpu), + msecs_to_jiffies((per_cpu(msm_mpdec_cpudata, cpu).boost_until - ktime_to_ms(ktime_get()))) + ); + } + } else { + per_cpu(msm_mpdec_cpudata, cpu).revib_wq_running = false; + } + return; } static void mpdec_input_callback(struct work_struct *unused) { - struct cpufreq_policy *cpu_policy = NULL; - int cpu = smp_processor_id(); - bool boosted = false; - - if (!per_cpu(msm_mpdec_cpudata, cpu).is_boosted) { - if (mutex_trylock(&per_cpu(msm_mpdec_cpudata, cpu).boost_mutex)) { - cpu_policy = cpufreq_cpu_get(cpu); - if (!cpu_policy) { - pr_debug(MPDEC_TAG"NULL policy on cpu %d\n", cpu); - return; - } - per_cpu(msm_mpdec_cpudata, cpu).norm_min_freq = cpu_policy->min; - update_cpu_min_freq(cpu_policy, cpu, per_cpu(msm_mpdec_cpudata, cpu).boost_freq); + struct cpufreq_policy *cpu_policy = NULL; + int cpu = smp_processor_id(); + bool boosted = false; + + if (!per_cpu(msm_mpdec_cpudata, cpu).is_boosted) { + if (mutex_trylock(&per_cpu(msm_mpdec_cpudata, cpu).boost_mutex)) { + cpu_policy = cpufreq_cpu_get(cpu); + if (!cpu_policy) { + pr_debug(MPDEC_TAG"NULL policy on cpu %d\n", cpu); + return; + } + per_cpu(msm_mpdec_cpudata, cpu).norm_min_freq = cpu_policy->min; + + /* check if boost freq is > minfreq */ + cpufreq_verify_within_limits(cpu_policy, cpu_policy->min, per_cpu(msm_mpdec_cpudata, cpu).boost_freq); + + update_cpu_min_freq(cpu_policy, cpu, per_cpu(msm_mpdec_cpudata, cpu).boost_freq); #if DEBUG - pr_info(MPDEC_TAG"boosted cpu%i to %lu", cpu, per_cpu(msm_mpdec_cpudata, cpu).boost_freq); + pr_info(MPDEC_TAG"boosted cpu%i to %lu", cpu, per_cpu(msm_mpdec_cpudata, cpu).boost_freq); #endif - per_cpu(msm_mpdec_cpudata, cpu).is_boosted = true; - per_cpu(msm_mpdec_cpudata, cpu).boost_until = ktime_to_ms(ktime_get()) + MSM_MPDEC_BOOSTTIME; - boosted = true; - cpufreq_cpu_put(cpu_policy); - mutex_unlock(&per_cpu(msm_mpdec_cpudata, cpu).boost_mutex); - } - } else { - boosted = true; - } - if (boosted && !per_cpu(msm_mpdec_cpudata, cpu).revib_wq_running) { - per_cpu(msm_mpdec_cpudata, cpu).revib_wq_running = true; - queue_delayed_work_on(cpu, - msm_mpdec_revib_workq, - &per_cpu(msm_mpdec_revib_work, cpu), - msecs_to_jiffies(MSM_MPDEC_BOOSTTIME)); - } else if (boosted && per_cpu(msm_mpdec_cpudata, cpu).revib_wq_running) { - per_cpu(msm_mpdec_cpudata, cpu).boost_until = ktime_to_ms(ktime_get()) + MSM_MPDEC_BOOSTTIME; - } - - return; + per_cpu(msm_mpdec_cpudata, cpu).is_boosted = true; + per_cpu(msm_mpdec_cpudata, cpu).boost_until = ktime_to_ms(ktime_get()) + msm_mpdec_tuners_ins.boost_time; + boosted = true; + cpufreq_cpu_put(cpu_policy); + mutex_unlock(&per_cpu(msm_mpdec_cpudata, cpu).boost_mutex); + } + } else { + boosted = true; + } + if (boosted && !per_cpu(msm_mpdec_cpudata, cpu).revib_wq_running) { + per_cpu(msm_mpdec_cpudata, cpu).revib_wq_running = true; + queue_delayed_work_on( + cpu, + msm_mpdec_revib_workq, + &per_cpu(msm_mpdec_revib_work, cpu), + msecs_to_jiffies(msm_mpdec_tuners_ins.boost_time) + ); + } else if (boosted && per_cpu(msm_mpdec_cpudata, cpu).revib_wq_running) { + per_cpu(msm_mpdec_cpudata, cpu).boost_until = ktime_to_ms(ktime_get()) + msm_mpdec_tuners_ins.boost_time; + } + + return; } +#ifdef CONFIG_BRICKED_THERMAL +extern int bricked_thermal_throttled; +#endif + static void mpdec_input_event(struct input_handle *handle, unsigned int type, - unsigned int code, int value) { - int i = 0; + unsigned int code, int value) { + int i = 0; - if (!msm_mpdec_tuners_ins.boost_enabled) - return; +#ifdef CONFIG_BRICKED_THERMAL + if (bricked_thermal_throttled > 0) + return; +#endif + + if (!msm_mpdec_tuners_ins.boost_enabled) + return; - if (!is_screen_on) - return; + if (!is_screen_on) + return; - for_each_online_cpu(i) { - queue_work_on(i, mpdec_input_wq, &per_cpu(mpdec_input_work, i)); - } + for_each_online_cpu(i) { + queue_work_on(i, mpdec_input_wq, &per_cpu(mpdec_input_work, i)); + } } static int input_dev_filter(const char *input_dev_name) { - if (strstr(input_dev_name, "touch") || - strstr(input_dev_name, "keypad")) { - return 0; - } else { - return 1; - } + if (strstr(input_dev_name, "touch") || + strstr(input_dev_name, "key") || + strstr(input_dev_name, "power") || + strstr(input_dev_name, "pwr") || + strstr(input_dev_name, "lid")) { + return 0; + } else { + return 1; + } } static int mpdec_input_connect(struct input_handler *handler, - struct input_dev *dev, const struct input_device_id *id) { - struct input_handle *handle; - int error; + struct input_dev *dev, const struct input_device_id *id) { + struct input_handle *handle; + int error; - if (input_dev_filter(dev->name)) - return -ENODEV; + if (input_dev_filter(dev->name)) + return -ENODEV; - handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL); - if (!handle) - return -ENOMEM; + handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL); + if (!handle) + return -ENOMEM; - handle->dev = dev; - handle->handler = handler; - handle->name = "mpdec"; + handle->dev = dev; + handle->handler = handler; + handle->name = "mpdec"; - error = input_register_handle(handle); - if (error) - goto err2; + error = input_register_handle(handle); + if (error) + goto err2; - error = input_open_device(handle); - if (error) - goto err1; + error = input_open_device(handle); + if (error) + goto err1; - return 0; + return 0; err1: - input_unregister_handle(handle); + input_unregister_handle(handle); err2: - kfree(handle); - return error; + kfree(handle); + return error; } static void mpdec_input_disconnect(struct input_handle *handle) { - input_close_device(handle); - input_unregister_handle(handle); - kfree(handle); + input_close_device(handle); + input_unregister_handle(handle); + kfree(handle); } static const struct input_device_id mpdec_ids[] = { - { .driver_info = 1 }, - { }, + { .driver_info = 1 }, + { }, }; static struct input_handler mpdec_input_handler = { - .event = mpdec_input_event, - .connect = mpdec_input_connect, - .disconnect = mpdec_input_disconnect, - .name = "mpdec_inputreq", - .id_table = mpdec_ids, + .event = mpdec_input_event, + .connect = mpdec_input_connect, + .disconnect = mpdec_input_disconnect, + .name = "mpdec_inputreq", + .id_table = mpdec_ids, }; #endif -static void msm_mpdec_early_suspend(struct early_suspend *h) { - int cpu = nr_cpu_ids; +static void msm_mpdec_suspend(struct work_struct * msm_mpdec_suspend_work) { + int cpu = nr_cpu_ids; #ifdef CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN - is_screen_on = false; + is_screen_on = false; #endif - if (!msm_mpdec_tuners_ins.scroff_single_core) { - pr_info(MPDEC_TAG"Screen -> off\n"); - return; - } + if (!msm_mpdec_tuners_ins.scroff_single_core) { + pr_info(MPDEC_TAG"Screen -> off\n"); + return; + } - /* main work thread can sleep now */ - cancel_delayed_work_sync(&msm_mpdec_work); + /* main work thread can sleep now */ + cancel_delayed_work_sync(&msm_mpdec_work); - for_each_possible_cpu(cpu) { + for_each_possible_cpu(cpu) { #ifdef CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN - unboost_cpu(cpu); + unboost_cpu(cpu); #endif - if ((cpu >= 1) && (cpu_online(cpu))) { - mpdec_cpu_down(cpu); - } - per_cpu(msm_mpdec_cpudata, cpu).device_suspended = true; - } + if ((cpu >= 1) && (cpu_online(cpu))) { + mpdec_cpu_down(cpu); + } + } + mpdec_suspended = true; - pr_info(MPDEC_TAG"Screen -> off. Deactivated mpdecision.\n"); + pr_info(MPDEC_TAG"Screen -> off. Deactivated mpdecision.\n"); } +static DECLARE_WORK(msm_mpdec_suspend_work, msm_mpdec_suspend); -static void msm_mpdec_late_resume(struct early_suspend *h) { - int cpu = nr_cpu_ids; +static void msm_mpdec_resume(struct work_struct * msm_mpdec_suspend_work) { + int cpu = nr_cpu_ids; #ifdef CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN - is_screen_on = true; + is_screen_on = true; #endif - for_each_possible_cpu(cpu) - per_cpu(msm_mpdec_cpudata, cpu).device_suspended = false; - - if (msm_mpdec_tuners_ins.scroff_single_core) { - /* wake up main work thread */ - was_paused = true; - queue_delayed_work(msm_mpdec_workq, &msm_mpdec_work, 0); - - /* restore min/max cpus limits */ - for (cpu=1; cpu msm_mpdec_tuners_ins.max_cpus) { - if (cpu_online(cpu)) - mpdec_cpu_down(cpu); - } - } - - pr_info(MPDEC_TAG"Screen -> on. Activated mpdecision. | Mask=[%d%d%d%d]\n", - cpu_online(0), cpu_online(1), cpu_online(2), cpu_online(3)); - } else { - pr_info(MPDEC_TAG"Screen -> on\n"); - } + if (!mpdec_suspended) + return; + + mpdec_suspended = false; + + if (msm_mpdec_tuners_ins.scroff_single_core) { + /* wake up main work thread */ + was_paused = true; + queue_delayed_work(msm_mpdec_workq, &msm_mpdec_work, 0); + /* restore min/max cpus limits */ + for (cpu=1; cpu msm_mpdec_tuners_ins.max_cpus) { + if (cpu_online(cpu)) + mpdec_cpu_down(cpu); + } + } + pr_info(MPDEC_TAG"Screen -> on. Activated mpdecision. | Mask=[%d%d%d%d]\n", + cpu_online(0), cpu_online(1), cpu_online(2), cpu_online(3)); + } else { + pr_info(MPDEC_TAG"Screen -> on\n"); + } +} +static DECLARE_WORK(msm_mpdec_resume_work, msm_mpdec_resume); + +#ifndef CONFIG_HAS_EARLYSUSPEND +static int msm_mpdec_lcd_notifier_callback(struct notifier_block *this, + unsigned long event, void *data) { + pr_debug("%s: event = %lu\n", __func__, event); + + switch (event) { + case LCD_EVENT_OFF_START: + mutex_lock(&mpdec_msm_susres_lock); + schedule_work(&msm_mpdec_suspend_work); + break; + case LCD_EVENT_ON_START: + mutex_lock(&mpdec_msm_susres_lock); + schedule_work(&msm_mpdec_resume_work); + break; + case LCD_EVENT_OFF_END: + mutex_unlock(&mpdec_msm_susres_lock); + break; + case LCD_EVENT_ON_END: + mutex_unlock(&mpdec_msm_susres_lock); + break; + default: + break; + } + + return 0; +} +#else +static void msm_mpdec_early_suspend(struct early_suspend *h) { + mutex_lock(&mpdec_msm_susres_lock); + schedule_work(&msm_mpdec_suspend_work); + mutex_unlock(&mpdec_msm_susres_lock); +} + +static void msm_mpdec_late_resume(struct early_suspend *h) { + mutex_lock(&mpdec_msm_susres_lock); + schedule_work(&msm_mpdec_resume_work); + mutex_unlock(&mpdec_msm_susres_lock); } static struct early_suspend msm_mpdec_early_suspend_handler = { - .level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN, - .suspend = msm_mpdec_early_suspend, - .resume = msm_mpdec_late_resume, + .level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN, + .suspend = msm_mpdec_early_suspend, + .resume = msm_mpdec_late_resume, }; +#endif /**************************** SYSFS START ****************************/ struct kobject *msm_mpdec_kobject; -#define show_one(file_name, object) \ -static ssize_t show_##file_name \ -(struct kobject *kobj, struct attribute *attr, char *buf) \ -{ \ - return sprintf(buf, "%u\n", msm_mpdec_tuners_ins.object); \ +#define show_one(file_name, object) \ +static ssize_t show_##file_name \ +(struct kobject *kobj, struct attribute *attr, char *buf) \ +{ \ + return sprintf(buf, "%u\n", msm_mpdec_tuners_ins.object); \ } show_one(startdelay, startdelay); @@ -633,11 +659,11 @@ show_one(boost_enabled, boost_enabled); show_one(boost_time, boost_time); #endif -#define show_one_twts(file_name, arraypos) \ -static ssize_t show_##file_name \ -(struct kobject *kobj, struct attribute *attr, char *buf) \ -{ \ - return sprintf(buf, "%u\n", TwTs_Threshold[arraypos]); \ +#define show_one_twts(file_name, arraypos) \ +static ssize_t show_##file_name \ +(struct kobject *kobj, struct attribute *attr, char *buf) \ +{ \ + return sprintf(buf, "%u\n", TwTs_Threshold[arraypos]); \ } show_one_twts(twts_threshold_0, 0); show_one_twts(twts_threshold_1, 1); @@ -648,18 +674,18 @@ show_one_twts(twts_threshold_5, 5); show_one_twts(twts_threshold_6, 6); show_one_twts(twts_threshold_7, 7); -#define store_one_twts(file_name, arraypos) \ -static ssize_t store_##file_name \ -(struct kobject *a, struct attribute *b, const char *buf, size_t count) \ -{ \ - unsigned int input; \ - int ret; \ - ret = sscanf(buf, "%u", &input); \ - if (ret != 1) \ - return -EINVAL; \ - TwTs_Threshold[arraypos] = input; \ - return count; \ -} \ +#define store_one_twts(file_name, arraypos) \ +static ssize_t store_##file_name \ +(struct kobject *a, struct attribute *b, const char *buf, size_t count) \ +{ \ + unsigned int input; \ + int ret; \ + ret = sscanf(buf, "%u", &input); \ + if (ret != 1) \ + return -EINVAL; \ + TwTs_Threshold[arraypos] = input; \ + return count; \ +} \ define_one_global_rw(file_name); store_one_twts(twts_threshold_0, 0); store_one_twts(twts_threshold_1, 1); @@ -670,11 +696,11 @@ store_one_twts(twts_threshold_5, 5); store_one_twts(twts_threshold_6, 6); store_one_twts(twts_threshold_7, 7); -#define show_one_nwns(file_name, arraypos) \ -static ssize_t show_##file_name \ -(struct kobject *kobj, struct attribute *attr, char *buf) \ -{ \ - return sprintf(buf, "%u\n", NwNs_Threshold[arraypos]); \ +#define show_one_nwns(file_name, arraypos) \ +static ssize_t show_##file_name \ +(struct kobject *kobj, struct attribute *attr, char *buf) \ +{ \ + return sprintf(buf, "%u\n", NwNs_Threshold[arraypos]); \ } show_one_nwns(nwns_threshold_0, 0); show_one_nwns(nwns_threshold_1, 1); @@ -685,18 +711,18 @@ show_one_nwns(nwns_threshold_5, 5); show_one_nwns(nwns_threshold_6, 6); show_one_nwns(nwns_threshold_7, 7); -#define store_one_nwns(file_name, arraypos) \ -static ssize_t store_##file_name \ -(struct kobject *a, struct attribute *b, const char *buf, size_t count) \ -{ \ - unsigned int input; \ - int ret; \ - ret = sscanf(buf, "%u", &input); \ - if (ret != 1) \ - return -EINVAL; \ - NwNs_Threshold[arraypos] = input; \ - return count; \ -} \ +#define store_one_nwns(file_name, arraypos) \ +static ssize_t store_##file_name \ +(struct kobject *a, struct attribute *b, const char *buf, size_t count) \ +{ \ + unsigned int input; \ + int ret; \ + ret = sscanf(buf, "%u", &input); \ + if (ret != 1) \ + return -EINVAL; \ + NwNs_Threshold[arraypos] = input; \ + return count; \ +} \ define_one_global_rw(file_name); store_one_nwns(nwns_threshold_0, 0); store_one_nwns(nwns_threshold_1, 1); @@ -708,262 +734,262 @@ store_one_nwns(nwns_threshold_6, 6); store_one_nwns(nwns_threshold_7, 7); static ssize_t show_idle_freq (struct kobject *kobj, struct attribute *attr, - char *buf) + char *buf) { - return sprintf(buf, "%lu\n", msm_mpdec_tuners_ins.idle_freq); + return sprintf(buf, "%lu\n", msm_mpdec_tuners_ins.idle_freq); } static ssize_t show_enabled(struct kobject *a, struct attribute *b, - char *buf) + char *buf) { - unsigned int enabled; - switch (state) { - case MSM_MPDEC_DISABLED: - enabled = 0; - break; - case MSM_MPDEC_IDLE: - case MSM_MPDEC_DOWN: - case MSM_MPDEC_UP: - enabled = 1; - break; - default: - enabled = 333; - } - return sprintf(buf, "%u\n", enabled); + unsigned int enabled; + switch (state) { + case MSM_MPDEC_DISABLED: + enabled = 0; + break; + case MSM_MPDEC_IDLE: + case MSM_MPDEC_DOWN: + case MSM_MPDEC_UP: + enabled = 1; + break; + default: + enabled = 333; + } + return sprintf(buf, "%u\n", enabled); } static ssize_t store_startdelay(struct kobject *a, struct attribute *b, - const char *buf, size_t count) + const char *buf, size_t count) { - unsigned int input; - int ret; - ret = sscanf(buf, "%u", &input); - if (ret != 1) - return -EINVAL; + unsigned int input; + int ret; + ret = sscanf(buf, "%u", &input); + if (ret != 1) + return -EINVAL; - msm_mpdec_tuners_ins.startdelay = input; + msm_mpdec_tuners_ins.startdelay = input; - return count; + return count; } static ssize_t store_delay(struct kobject *a, struct attribute *b, - const char *buf, size_t count) + const char *buf, size_t count) { - unsigned int input; - int ret; - ret = sscanf(buf, "%u", &input); - if (ret != 1) - return -EINVAL; + unsigned int input; + int ret; + ret = sscanf(buf, "%u", &input); + if (ret != 1) + return -EINVAL; - msm_mpdec_tuners_ins.delay = input; + msm_mpdec_tuners_ins.delay = input; - return count; + return count; } static ssize_t store_pause(struct kobject *a, struct attribute *b, - const char *buf, size_t count) + const char *buf, size_t count) { - unsigned int input; - int ret; - ret = sscanf(buf, "%u", &input); - if (ret != 1) - return -EINVAL; + unsigned int input; + int ret; + ret = sscanf(buf, "%u", &input); + if (ret != 1) + return -EINVAL; - msm_mpdec_tuners_ins.pause = input; + msm_mpdec_tuners_ins.pause = input; - return count; + return count; } static ssize_t store_idle_freq(struct kobject *a, struct attribute *b, - const char *buf, size_t count) + const char *buf, size_t count) { - long unsigned int input; - int ret; - ret = sscanf(buf, "%lu", &input); - if (ret != 1) - return -EINVAL; + long unsigned int input; + int ret; + ret = sscanf(buf, "%lu", &input); + if (ret != 1) + return -EINVAL; - msm_mpdec_tuners_ins.idle_freq = input; + msm_mpdec_tuners_ins.idle_freq = input; - return count; + return count; } static ssize_t store_scroff_single_core(struct kobject *a, struct attribute *b, - const char *buf, size_t count) + const char *buf, size_t count) { - unsigned int input; - int ret; - ret = sscanf(buf, "%u", &input); - if (ret != 1) - return -EINVAL; - switch (buf[0]) { - case '0': - case '1': - msm_mpdec_tuners_ins.scroff_single_core = input; - break; - default: - ret = -EINVAL; - } - return count; + unsigned int input; + int ret; + ret = sscanf(buf, "%u", &input); + if (ret != 1) + return -EINVAL; + switch (buf[0]) { + case '0': + case '1': + msm_mpdec_tuners_ins.scroff_single_core = input; + break; + default: + ret = -EINVAL; + } + return count; } static ssize_t store_max_cpus(struct kobject *a, struct attribute *b, - const char *buf, size_t count) + const char *buf, size_t count) { - unsigned int input; - int ret, cpu; - ret = sscanf(buf, "%u", &input); - if ((ret != 1) || input > CONFIG_NR_CPUS || input < msm_mpdec_tuners_ins.min_cpus) - return -EINVAL; - - msm_mpdec_tuners_ins.max_cpus = input; - if (num_online_cpus() > input) { - for (cpu=CONFIG_NR_CPUS; cpu>0; cpu--) { - if (num_online_cpus() <= input) - break; - if (!cpu_online(cpu)) - continue; - mpdec_cpu_down(cpu); - } - pr_info(MPDEC_TAG"max_cpus set to %u. Affected CPUs were unplugged!\n", input); - } - - return count; + unsigned int input; + int ret, cpu; + ret = sscanf(buf, "%u", &input); + if ((ret != 1) || input > CONFIG_NR_CPUS || input < msm_mpdec_tuners_ins.min_cpus) + return -EINVAL; + + msm_mpdec_tuners_ins.max_cpus = input; + if (num_online_cpus() > input) { + for (cpu=CONFIG_NR_CPUS; cpu>0; cpu--) { + if (num_online_cpus() <= input) + break; + if (!cpu_online(cpu)) + continue; + mpdec_cpu_down(cpu); + } + pr_info(MPDEC_TAG"max_cpus set to %u. Affected CPUs were unplugged!\n", input); + } + + return count; } static ssize_t store_min_cpus(struct kobject *a, struct attribute *b, - const char *buf, size_t count) + const char *buf, size_t count) { - unsigned int input; - int ret, cpu; - ret = sscanf(buf, "%u", &input); - if ((ret != 1) || input < 1 || input > msm_mpdec_tuners_ins.max_cpus) - return -EINVAL; - - msm_mpdec_tuners_ins.min_cpus = input; - if (num_online_cpus() < input) { - for (cpu=1; cpu= input) - break; - if (cpu_online(cpu)) - continue; - mpdec_cpu_up(cpu); - } - pr_info(MPDEC_TAG"min_cpus set to %u. Affected CPUs were hotplugged!\n", input); - } - - return count; + unsigned int input; + int ret, cpu; + ret = sscanf(buf, "%u", &input); + if ((ret != 1) || input < 1 || input > msm_mpdec_tuners_ins.max_cpus) + return -EINVAL; + + msm_mpdec_tuners_ins.min_cpus = input; + if (num_online_cpus() < input) { + for (cpu=1; cpu= input) + break; + if (cpu_online(cpu)) + continue; + mpdec_cpu_up(cpu); + } + pr_info(MPDEC_TAG"min_cpus set to %u. Affected CPUs were hotplugged!\n", input); + } + + return count; } static ssize_t store_enabled(struct kobject *a, struct attribute *b, - const char *buf, size_t count) + const char *buf, size_t count) { - unsigned int cpu, input, enabled; - int ret; - ret = sscanf(buf, "%u", &input); - if (ret != 1) - return -EINVAL; - - switch (state) { - case MSM_MPDEC_DISABLED: - enabled = 0; - break; - case MSM_MPDEC_IDLE: - case MSM_MPDEC_DOWN: - case MSM_MPDEC_UP: - enabled = 1; - break; - default: - enabled = 333; - } - - if (buf[0] == enabled) - return -EINVAL; - - switch (buf[0]) { - case '0': - state = MSM_MPDEC_DISABLED; - pr_info(MPDEC_TAG"nap time... Hot plugging offline CPUs...\n"); - for (cpu = 1; cpu < CONFIG_NR_CPUS; cpu++) - if (!cpu_online(cpu)) - mpdec_cpu_up(cpu); - break; - case '1': - state = MSM_MPDEC_IDLE; - was_paused = true; - queue_delayed_work(msm_mpdec_workq, &msm_mpdec_work, - msecs_to_jiffies(msm_mpdec_tuners_ins.delay)); - pr_info(MPDEC_TAG"firing up mpdecision...\n"); - break; - default: - ret = -EINVAL; - } - return count; + unsigned int cpu, input, enabled; + int ret; + ret = sscanf(buf, "%u", &input); + if (ret != 1) + return -EINVAL; + + switch (state) { + case MSM_MPDEC_DISABLED: + enabled = 0; + break; + case MSM_MPDEC_IDLE: + case MSM_MPDEC_DOWN: + case MSM_MPDEC_UP: + enabled = 1; + break; + default: + enabled = 333; + } + + if (buf[0] == enabled) + return -EINVAL; + + switch (buf[0]) { + case '0': + state = MSM_MPDEC_DISABLED; + pr_info(MPDEC_TAG"nap time... Hot plugging offline CPUs...\n"); + for (cpu = 1; cpu < CONFIG_NR_CPUS; cpu++) + if (!cpu_online(cpu)) + mpdec_cpu_up(cpu); + break; + case '1': + state = MSM_MPDEC_IDLE; + was_paused = true; + queue_delayed_work(msm_mpdec_workq, &msm_mpdec_work, + msecs_to_jiffies(msm_mpdec_tuners_ins.delay)); + pr_info(MPDEC_TAG"firing up mpdecision...\n"); + break; + default: + ret = -EINVAL; + } + return count; } #ifdef CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN static ssize_t store_boost_enabled(struct kobject *a, struct attribute *b, - const char *buf, size_t count) + const char *buf, size_t count) { - unsigned int input; - int ret; - ret = sscanf(buf, "%u", &input); - if (ret != 1) - return -EINVAL; + unsigned int input; + int ret; + ret = sscanf(buf, "%u", &input); + if (ret != 1) + return -EINVAL; - msm_mpdec_tuners_ins.boost_enabled = input; + msm_mpdec_tuners_ins.boost_enabled = input; - return count; + return count; } static ssize_t store_boost_time(struct kobject *a, struct attribute *b, - const char *buf, size_t count) + const char *buf, size_t count) { - unsigned int input; - int ret; - ret = sscanf(buf, "%u", &input); - if (ret != 1) - return -EINVAL; + unsigned int input; + int ret; + ret = sscanf(buf, "%u", &input); + if (ret != 1) + return -EINVAL; - msm_mpdec_tuners_ins.boost_time = input; + msm_mpdec_tuners_ins.boost_time = input; - return count; + return count; } static ssize_t show_boost_freqs(struct kobject *a, struct attribute *b, - char *buf) + char *buf) { - ssize_t len = 0; - int cpu = 0; + ssize_t len = 0; + int cpu = 0; - for_each_present_cpu(cpu) { - len += sprintf(buf + len, "%lu\n", per_cpu(msm_mpdec_cpudata, cpu).boost_freq); - } - return len; + for_each_present_cpu(cpu) { + len += sprintf(buf + len, "%lu\n", per_cpu(msm_mpdec_cpudata, cpu).boost_freq); + } + return len; } static ssize_t store_boost_freqs(struct kobject *a, struct attribute *b, - const char *buf, size_t count) + const char *buf, size_t count) { - int i = 0; - unsigned int cpu = 0; - long unsigned int hz = 0; - const char *chz = NULL; - - for (i=0; i + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __MSM_MPDEC_H__ +#define __MSM_MPDEC_H__ + +#include +#include + +#define MPDEC_TAG "[MPDEC]: " +#define MSM_MPDEC_STARTDELAY 20000 +#define MSM_MPDEC_DELAY 130 +#define MSM_MPDEC_PAUSE 10000 + +#ifdef CONFIG_ARCH_MSM8974 +#define MSM_MPDEC_IDLE_FREQ 499200 +#elif defined CONFIG_ARCH_MSM8X60 || defined CONFIG_ARCH_MSM8960 || defined CONFIG_ARCH_MSM8930 +#define MSM_MPDEC_IDLE_FREQ 486000 +#else +#define MSM_MPDEC_IDLE_FREQ 486000 +#endif + +#ifdef CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN +#define MSM_MPDEC_BOOSTTIME 1000 +#ifdef CONFIG_ARCH_MSM8974 +#define MSM_MPDEC_BOOSTFREQ_CPU0 960000 +#define MSM_MPDEC_BOOSTFREQ_CPU1 960000 +#define MSM_MPDEC_BOOSTFREQ_CPU2 729600 +#define MSM_MPDEC_BOOSTFREQ_CPU3 576000 +#elif defined CONFIG_ARCH_MSM8X60 || defined CONFIG_ARCH_MSM8960 || defined CONFIG_ARCH_MSM8930 +#define MSM_MPDEC_BOOSTFREQ_CPU0 918000 +#define MSM_MPDEC_BOOSTFREQ_CPU1 918000 +#define MSM_MPDEC_BOOSTFREQ_CPU2 702000 +#define MSM_MPDEC_BOOSTFREQ_CPU3 594000 +#else +#define MSM_MPDEC_BOOSTFREQ_CPU0 918000 +#define MSM_MPDEC_BOOSTFREQ_CPU1 918000 +#define MSM_MPDEC_BOOSTFREQ_CPU2 702000 +#define MSM_MPDEC_BOOSTFREQ_CPU3 594000 +#endif +#endif + +enum { + MSM_MPDEC_DISABLED = 0, + MSM_MPDEC_IDLE, + MSM_MPDEC_DOWN, + MSM_MPDEC_UP, +}; + +struct msm_mpdec_cpudata_t { + struct mutex hotplug_mutex; + int online; + cputime64_t on_time; + cputime64_t on_time_total; + long long unsigned int times_cpu_hotplugged; + long long unsigned int times_cpu_unplugged; +#ifdef CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN + struct mutex boost_mutex; + struct mutex unboost_mutex; + unsigned long int norm_min_freq; + unsigned long int boost_freq; + cputime64_t boost_until; + bool is_boosted; + bool revib_wq_running; +#endif +}; +#endif //__MSM_MPDEC_H__ + From c2e39465740fbc399a602e4db8ed6ad7238248d9 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Thu, 19 Dec 2013 14:44:32 +0100 Subject: [PATCH 039/215] Add back Faux123's msm_cpufreq_limiter --- arch/arm/mach-msm/Kconfig | 11 +++ arch/arm/mach-msm/Makefile | 2 + arch/arm/mach-msm/cpufreq_limit.c | 131 ++++++++++++++++++++++++++++++ 3 files changed, 144 insertions(+) create mode 100644 arch/arm/mach-msm/cpufreq_limit.c diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig index 93669196fa5..d8b76651d7d 100644 --- a/arch/arm/mach-msm/Kconfig +++ b/arch/arm/mach-msm/Kconfig @@ -1644,6 +1644,17 @@ config MSM_CPU_FREQ_MIN endif # CPU_FREQ_MSM +config MSM_CPUFREQ_LIMITER + tristate "MSM CPU frequency limiter" + default n + help + This driver limits MSM CPU frequency through sysfs file system. + + To compile this driver as a module, choose M here: the + module will be called cpufreq_stats. + + If in doubt, say N. + config INTELLI_PLUG bool "Enable intelli-plug cpu hotplug driver" default n diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile index 2783612867f..40cd18d86d1 100644 --- a/arch/arm/mach-msm/Makefile +++ b/arch/arm/mach-msm/Makefile @@ -396,3 +396,5 @@ ifdef CONFIG_MSM_CPR obj-$(CONFIG_DEBUG_FS) += msm_cpr-debug.o endif obj-$(CONFIG_MSM_CPU_PWRCTL) += msm_cpu_pwrctl.o + +obj-$(CONFIG_MSM_CPUFREQ_LIMITER) += cpufreq_limit.o diff --git a/arch/arm/mach-msm/cpufreq_limit.c b/arch/arm/mach-msm/cpufreq_limit.c new file mode 100644 index 00000000000..830f0202e36 --- /dev/null +++ b/arch/arm/mach-msm/cpufreq_limit.c @@ -0,0 +1,131 @@ +/* + * Author: Paul Reioux aka Faux123 + * + * Copyright 2012 Paul Reioux + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include + +#include +#include + +#include + +#define MSM_CPUFREQ_LIMIT_VERSION 1 + +static uint32_t limited_max_freq = MSM_CPUFREQ_NO_LIMIT; + +static int update_cpu_max_freq(int cpu, uint32_t max_freq) +{ + int ret = 0; + + ret = msm_cpufreq_set_freq_limits(cpu, MSM_CPUFREQ_NO_LIMIT, max_freq); + if (ret) + return ret; + + limited_max_freq = max_freq; + if (max_freq != MSM_CPUFREQ_NO_LIMIT) + pr_info("msm_cpufreq_limit: Limiting cpu%d max frequency to %d\n", + cpu, max_freq); + else + pr_info("msm_cpufreq_limit: Max frequency reset for cpu%d\n", cpu); + + ret = cpufreq_update_policy(cpu); + + return ret; +} + +static ssize_t msm_cpufreq_limit_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) +{ + return sprintf(buf, "%u\n", limited_max_freq); +} + +static ssize_t msm_cpufreq_limit_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) +{ + int cpu = 0; + int ret = 0; + + unsigned int data; + + if(sscanf(buf, "%u\n", &data) == 1) { + for_each_possible_cpu(cpu) { + ret = update_cpu_max_freq(cpu, data); + if (ret) + pr_debug("Unable to limit cpu%d max freq to %d\n", + cpu, data); + } + if (!ret) + limited_max_freq = data; + } + + return count; +} + +static ssize_t msm_cpufreq_limit_version_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) +{ + return sprintf(buf, "version: %u\n", MSM_CPUFREQ_LIMIT_VERSION); +} + +static struct kobj_attribute msm_cpufreq_limit_attribute = + __ATTR(cpufreq_limit, 0666, msm_cpufreq_limit_show, msm_cpufreq_limit_store); + +static struct kobj_attribute msm_cpufreq_limit_version_attribute = + __ATTR(msm_cpufreq_limit_version, 0444 , msm_cpufreq_limit_version_show, NULL); + +static struct attribute *msm_cpufreq_limit_attrs[] = + { + &msm_cpufreq_limit_attribute.attr, + &msm_cpufreq_limit_version_attribute.attr, + NULL, + }; + +static struct attribute_group msm_cpufreq_limit_attr_group = + { + .attrs = msm_cpufreq_limit_attrs, + }; + +static struct kobject *msm_cpufreq_limit_kobj; + +static int msm_cpufreq_limit_init(void) +{ + int sysfs_result; + + msm_cpufreq_limit_kobj = kobject_create_and_add("msm_cpufreq_limit", kernel_kobj); + if (!msm_cpufreq_limit_kobj) { + pr_err("%s msm_cpufreq_limit_kobj kobject create failed!\n", __FUNCTION__); + return -ENOMEM; + } + + sysfs_result = sysfs_create_group(msm_cpufreq_limit_kobj, &msm_cpufreq_limit_attr_group); + + if (sysfs_result) { + pr_info("%s msm_cpufreq_limit_kobj create failed!\n", __FUNCTION__); + kobject_put(msm_cpufreq_limit_kobj); + } + return sysfs_result; +} + +static void msm_cpufreq_limit_exit(void) +{ + if (msm_cpufreq_limit_kobj != NULL) + kobject_put(msm_cpufreq_limit_kobj); +} + +module_init(msm_cpufreq_limit_init); +module_exit(msm_cpufreq_limit_exit); +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Paul Reioux "); +MODULE_DESCRIPTION("Krait CPU frequency Limit Driver"); + From 46da09e23a97ef2d4b0d62bbecdbc739d0e7720e Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Thu, 19 Dec 2013 14:45:48 +0100 Subject: [PATCH 040/215] cpufreq: enable sibling cpu policy sharing disable Qualcomm's cpu policy restore (conflicts with sibling sharing) Signed-off-by: Paul Reioux --- drivers/cpufreq/cpufreq.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 527022d5910..03424d28d44 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -842,6 +842,7 @@ static int cpufreq_add_dev_policy(unsigned int cpu, #ifdef CONFIG_SMP unsigned long flags; unsigned int j; +/* #ifdef CONFIG_HOTPLUG_CPU struct cpufreq_governor *gov; @@ -862,7 +863,7 @@ static int cpufreq_add_dev_policy(unsigned int cpu, pr_debug("Restoring CPU%d min %d and max %d\n", cpu, policy->min, policy->max); #endif - +*/ for_each_cpu(j, policy->cpus) { struct cpufreq_policy *managed_policy; @@ -1090,10 +1091,15 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) #ifdef CONFIG_HOTPLUG_CPU for_each_online_cpu(sibling) { struct cpufreq_policy *cp = per_cpu(cpufreq_cpu_data, sibling); - if (cp && cp->governor && - (cpumask_test_cpu(cpu, cp->related_cpus))) { + if (cp && cp->governor) { policy->governor = cp->governor; + policy->min = cp->min; + policy->max = cp->max; + policy->user_policy.min = cp->user_policy.min; + policy->user_policy.max = cp->user_policy.max; + found = 1; + //pr_info("sibling: found sibling!\n"); break; } } From 5430698af17e50db2ad3ce8065afff8a8fac7262 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Thu, 19 Dec 2013 15:30:05 +0100 Subject: [PATCH 041/215] Update defconfig - Disable MPDEC inputboost - disable freq min/max - disable cpufreq limiter --- arch/arm/configs/flo_defconfig | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/arch/arm/configs/flo_defconfig b/arch/arm/configs/flo_defconfig index 04b2fb396fe..a1951d3c0f8 100644 --- a/arch/arm/configs/flo_defconfig +++ b/arch/arm/configs/flo_defconfig @@ -459,10 +459,11 @@ CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y CONFIG_MSM_IPC_ROUTER_SECURITY=y # CONFIG_MSM_DALRPC is not set CONFIG_MSM_MPDEC=y -CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN=y -CONFIG_MSM_CPU_FREQ_SET_MIN_MAX=y -CONFIG_MSM_CPU_FREQ_MAX=2322000 -CONFIG_MSM_CPU_FREQ_MIN=162000 +# CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN is not set +# CONFIG_MSM_CPU_FREQ_SET_MIN_MAX is not set +# CONFIG_MSM_CPU_FREQ_MAX=2322000 is not set +# CONFIG_MSM_CPU_FREQ_MIN=162000 is not set +# CONFIG_MSM_CPUFREQ_LIMITER is not set CONFIG_INTELLI_PLUG=y CONFIG_CPU_VOLTAGE_TABLE=y CONFIG_MSM_AVS_HW=y From d8e654f153d47c2e01a50f08866e253cc02411cc Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Thu, 19 Dec 2013 15:30:26 +0100 Subject: [PATCH 042/215] Revert "Add back Faux123's msm_cpufreq_limiter" This reverts commit c2e39465740fbc399a602e4db8ed6ad7238248d9. --- arch/arm/mach-msm/Kconfig | 11 --- arch/arm/mach-msm/Makefile | 2 - arch/arm/mach-msm/cpufreq_limit.c | 131 ------------------------------ 3 files changed, 144 deletions(-) delete mode 100644 arch/arm/mach-msm/cpufreq_limit.c diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig index d8b76651d7d..93669196fa5 100644 --- a/arch/arm/mach-msm/Kconfig +++ b/arch/arm/mach-msm/Kconfig @@ -1644,17 +1644,6 @@ config MSM_CPU_FREQ_MIN endif # CPU_FREQ_MSM -config MSM_CPUFREQ_LIMITER - tristate "MSM CPU frequency limiter" - default n - help - This driver limits MSM CPU frequency through sysfs file system. - - To compile this driver as a module, choose M here: the - module will be called cpufreq_stats. - - If in doubt, say N. - config INTELLI_PLUG bool "Enable intelli-plug cpu hotplug driver" default n diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile index 40cd18d86d1..2783612867f 100644 --- a/arch/arm/mach-msm/Makefile +++ b/arch/arm/mach-msm/Makefile @@ -396,5 +396,3 @@ ifdef CONFIG_MSM_CPR obj-$(CONFIG_DEBUG_FS) += msm_cpr-debug.o endif obj-$(CONFIG_MSM_CPU_PWRCTL) += msm_cpu_pwrctl.o - -obj-$(CONFIG_MSM_CPUFREQ_LIMITER) += cpufreq_limit.o diff --git a/arch/arm/mach-msm/cpufreq_limit.c b/arch/arm/mach-msm/cpufreq_limit.c deleted file mode 100644 index 830f0202e36..00000000000 --- a/arch/arm/mach-msm/cpufreq_limit.c +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Author: Paul Reioux aka Faux123 - * - * Copyright 2012 Paul Reioux - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#include -#include -#include - -#include -#include - -#include - -#define MSM_CPUFREQ_LIMIT_VERSION 1 - -static uint32_t limited_max_freq = MSM_CPUFREQ_NO_LIMIT; - -static int update_cpu_max_freq(int cpu, uint32_t max_freq) -{ - int ret = 0; - - ret = msm_cpufreq_set_freq_limits(cpu, MSM_CPUFREQ_NO_LIMIT, max_freq); - if (ret) - return ret; - - limited_max_freq = max_freq; - if (max_freq != MSM_CPUFREQ_NO_LIMIT) - pr_info("msm_cpufreq_limit: Limiting cpu%d max frequency to %d\n", - cpu, max_freq); - else - pr_info("msm_cpufreq_limit: Max frequency reset for cpu%d\n", cpu); - - ret = cpufreq_update_policy(cpu); - - return ret; -} - -static ssize_t msm_cpufreq_limit_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) -{ - return sprintf(buf, "%u\n", limited_max_freq); -} - -static ssize_t msm_cpufreq_limit_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) -{ - int cpu = 0; - int ret = 0; - - unsigned int data; - - if(sscanf(buf, "%u\n", &data) == 1) { - for_each_possible_cpu(cpu) { - ret = update_cpu_max_freq(cpu, data); - if (ret) - pr_debug("Unable to limit cpu%d max freq to %d\n", - cpu, data); - } - if (!ret) - limited_max_freq = data; - } - - return count; -} - -static ssize_t msm_cpufreq_limit_version_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) -{ - return sprintf(buf, "version: %u\n", MSM_CPUFREQ_LIMIT_VERSION); -} - -static struct kobj_attribute msm_cpufreq_limit_attribute = - __ATTR(cpufreq_limit, 0666, msm_cpufreq_limit_show, msm_cpufreq_limit_store); - -static struct kobj_attribute msm_cpufreq_limit_version_attribute = - __ATTR(msm_cpufreq_limit_version, 0444 , msm_cpufreq_limit_version_show, NULL); - -static struct attribute *msm_cpufreq_limit_attrs[] = - { - &msm_cpufreq_limit_attribute.attr, - &msm_cpufreq_limit_version_attribute.attr, - NULL, - }; - -static struct attribute_group msm_cpufreq_limit_attr_group = - { - .attrs = msm_cpufreq_limit_attrs, - }; - -static struct kobject *msm_cpufreq_limit_kobj; - -static int msm_cpufreq_limit_init(void) -{ - int sysfs_result; - - msm_cpufreq_limit_kobj = kobject_create_and_add("msm_cpufreq_limit", kernel_kobj); - if (!msm_cpufreq_limit_kobj) { - pr_err("%s msm_cpufreq_limit_kobj kobject create failed!\n", __FUNCTION__); - return -ENOMEM; - } - - sysfs_result = sysfs_create_group(msm_cpufreq_limit_kobj, &msm_cpufreq_limit_attr_group); - - if (sysfs_result) { - pr_info("%s msm_cpufreq_limit_kobj create failed!\n", __FUNCTION__); - kobject_put(msm_cpufreq_limit_kobj); - } - return sysfs_result; -} - -static void msm_cpufreq_limit_exit(void) -{ - if (msm_cpufreq_limit_kobj != NULL) - kobject_put(msm_cpufreq_limit_kobj); -} - -module_init(msm_cpufreq_limit_init); -module_exit(msm_cpufreq_limit_exit); -MODULE_LICENSE("GPL v2"); -MODULE_AUTHOR("Paul Reioux "); -MODULE_DESCRIPTION("Krait CPU frequency Limit Driver"); - From 2c3ff674eb8d7d9e2de3a18cc740475a7f1a9f9a Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Thu, 19 Dec 2013 16:41:18 +0100 Subject: [PATCH 043/215] Aroma : Add an option to enable/disable Showp1984's input-boost. Signed-off-by: Tk-Glitch --- arch/arm/configs/flo_defconfig | 1 - release/aroma/META-INF/com/google/android/aroma-config | 3 ++- release/aroma/META-INF/com/google/android/updater-script | 6 ++++++ release/aroma/config/buildconfig.sh | 9 +++++++++ release/aroma/system/etc/init.d/99glitch | 9 +++++++++ 5 files changed, 26 insertions(+), 2 deletions(-) diff --git a/arch/arm/configs/flo_defconfig b/arch/arm/configs/flo_defconfig index a1951d3c0f8..9c0bf806401 100644 --- a/arch/arm/configs/flo_defconfig +++ b/arch/arm/configs/flo_defconfig @@ -463,7 +463,6 @@ CONFIG_MSM_MPDEC=y # CONFIG_MSM_CPU_FREQ_SET_MIN_MAX is not set # CONFIG_MSM_CPU_FREQ_MAX=2322000 is not set # CONFIG_MSM_CPU_FREQ_MIN=162000 is not set -# CONFIG_MSM_CPUFREQ_LIMITER is not set CONFIG_INTELLI_PLUG=y CONFIG_CPU_VOLTAGE_TABLE=y CONFIG_MSM_AVS_HW=y diff --git a/release/aroma/META-INF/com/google/android/aroma-config b/release/aroma/META-INF/com/google/android/aroma-config index 0514c9b733c..95ebca2c404 100755 --- a/release/aroma/META-INF/com/google/android/aroma-config +++ b/release/aroma/META-INF/com/google/android/aroma-config @@ -242,7 +242,8 @@ checkbox( "Shortsweep","Shorter sweep distance for Sweep2Wake",0, "DoubleTap2Wake","Double tap screen to wake device",1, "Disable magnetic on/off","",0, - "Enable USB OTG+Charge mode","Allows charging in USB host mode (disables self-powered OTG)",0 + "Enable USB OTG+Charge mode","Allows charging in USB host mode (disables self-powered OTG)",0, + "Enable input-boost","Improves smoothness with kernel-side hotplug drivers",1 ); if file_getprop("/tmp/aroma/mods.prop","item.0.1") == "1" && file_getprop("/tmp/aroma/mods.prop","item.0.2") == "1" diff --git a/release/aroma/META-INF/com/google/android/updater-script b/release/aroma/META-INF/com/google/android/updater-script index ebb0de7e058..a75b32c866a 100755 --- a/release/aroma/META-INF/com/google/android/updater-script +++ b/release/aroma/META-INF/com/google/android/updater-script @@ -198,6 +198,12 @@ if ui_print("OTG+Charge mode enabled"); endif; +if + file_getprop("/tmp/aroma/mods.prop","item.0.8") == "1" + then + ui_print("Input-boost enabled"); +endif; + set_progress(0.3); diff --git a/release/aroma/config/buildconfig.sh b/release/aroma/config/buildconfig.sh index b85055eb396..ede46eb43a8 100755 --- a/release/aroma/config/buildconfig.sh +++ b/release/aroma/config/buildconfig.sh @@ -105,6 +105,15 @@ else echo "OTGCM=0" >> $CONFIGFILE; fi +#Input-boost +INPUTBOOST=`grep "item.0.8" /tmp/aroma/mods.prop | cut -d '=' -f2` +echo -e "\n\n##### Input-booster Settings ######\n# 1 to enable Input-boost\n# 0 to disable Input-boost\n" >> $CONFIGFILE +if [ $INPUTBOOST = 1 ]; then + echo "INPUTBOOST=1" >> $CONFIGFILE; +else + echo "INPUTBOOST=0" >> $CONFIGFILE; +fi + #THERMAL THERM=`cat /tmp/aroma/thermal.prop | cut -d '=' -f2` echo -e "\n\n##### Thermal Settings #####\n# 0 for default thermal throttling" >> $CONFIGFILE diff --git a/release/aroma/system/etc/init.d/99glitch b/release/aroma/system/etc/init.d/99glitch index e40aeb0f032..fb2d58fd384 100755 --- a/release/aroma/system/etc/init.d/99glitch +++ b/release/aroma/system/etc/init.d/99glitch @@ -129,6 +129,15 @@ if [ "`grep OTGCM=1 $KERNEL_CONF`" ]; then echo USB OTG+Charge mode enabled >> $KERNEL_LOGFILE; fi +#Input boost +if [ "`grep INPUTBOOST=0 $KERNEL_CONF`" ]; then + echo 0 > /sys/kernel/msm_mpdecision/conf/boost_enabled; + echo Input-Boost disabled >> $KERNEL_LOGFILE; +else + echo 1 > /sys/kernel/msm_mpdecision/conf/boost_enabled; + echo Input-Boost enabled >> $KERNEL_LOGFILE; +fi + #fstrim fstrim -v /cache | tee -a $KERNEL_LOGFILE; fstrim -v /data | tee -a $KERNEL_LOGFILE; From 0d67297c8ca9d9c78fba2449268e8c4d04c612ef Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Thu, 19 Dec 2013 16:47:55 +0100 Subject: [PATCH 044/215] defconfig : Get back input-boost and freq min/max. --- arch/arm/configs/flo_defconfig | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/configs/flo_defconfig b/arch/arm/configs/flo_defconfig index 9c0bf806401..04b2fb396fe 100644 --- a/arch/arm/configs/flo_defconfig +++ b/arch/arm/configs/flo_defconfig @@ -459,10 +459,10 @@ CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y CONFIG_MSM_IPC_ROUTER_SECURITY=y # CONFIG_MSM_DALRPC is not set CONFIG_MSM_MPDEC=y -# CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN is not set -# CONFIG_MSM_CPU_FREQ_SET_MIN_MAX is not set -# CONFIG_MSM_CPU_FREQ_MAX=2322000 is not set -# CONFIG_MSM_CPU_FREQ_MIN=162000 is not set +CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN=y +CONFIG_MSM_CPU_FREQ_SET_MIN_MAX=y +CONFIG_MSM_CPU_FREQ_MAX=2322000 +CONFIG_MSM_CPU_FREQ_MIN=162000 CONFIG_INTELLI_PLUG=y CONFIG_CPU_VOLTAGE_TABLE=y CONFIG_MSM_AVS_HW=y From 0810beaa9cfe608c5bfc6918e62cb7bf58c42dbc Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Thu, 19 Dec 2013 17:57:39 +0100 Subject: [PATCH 045/215] Aroma : Added an option to keep settings from a previous installation. Signed-off-by: Tk-Glitch --- .../META-INF/com/google/android/aroma-config | 45 ++++++++++++++----- .../com/google/android/updater-script | 29 ++++++++++++ 2 files changed, 63 insertions(+), 11 deletions(-) diff --git a/release/aroma/META-INF/com/google/android/aroma-config b/release/aroma/META-INF/com/google/android/aroma-config index 95ebca2c404..3d8b9d7c6b8 100755 --- a/release/aroma/META-INF/com/google/android/aroma-config +++ b/release/aroma/META-INF/com/google/android/aroma-config @@ -176,6 +176,26 @@ selectbox( endif; +selectbox( + "Auto Undervolting","Lowers the voltage for the lowest cpu frequency. Undervolting may cause instability.\n","@personalize","uv.prop", + "Stock (no undervolt)","",1, + "Undervolt (850 min)","",0, + "Undervolt (825 min)","",0, + "Undervolt (800 min)","",0, + "Undervolt (775 min)","",0, + "Undervolt (750 min)","",0, + "Undervolt (725 min)","",0 +); + +selectbox( + "My device is already Glitched","If you're already running Glitch kernel and you want to keep your actual settings, say yes\n","@personalize","glitched.prop", + "No","(Full install)",1, + "Yes","",0 +); + +if file_getprop("/tmp/aroma/glitched.prop","selected.0") == "1" +then + selectbox( "Minimum CPU Frequency","Select minimum CPU frequency\n","@personalize","minfreq.prop", "162MHz","",0, @@ -202,17 +222,6 @@ selectbox( "Faux123 Intelli-plug","",0 ); -selectbox( - "Auto Undervolting","Lowers the voltage for the lowest cpu frequency. Undervolting may cause instability.\n","@personalize","uv.prop", - "Stock (no undervolt)","",1, - "Undervolt (850 min)","",0, - "Undervolt (825 min)","",0, - "Undervolt (800 min)","",0, - "Undervolt (775 min)","",0, - "Undervolt (750 min)","",0, - "Undervolt (725 min)","",0 -); - selectbox( "Select thermal settings","Determines the amount of thermal throttling for the CPU\n","@personalize","thermal.prop", "run cool","more thermal throttling",0, @@ -267,6 +276,20 @@ selectbox( ); endif; +endif; + +if file_getprop("/tmp/aroma/glitched.prop","selected.0") == "2" +then + +alert( + "WARNING:", + "You MUST already have Glitch kernel installed and running on this device or this will fail !", + "@alert", + "OK" +); + +endif; + menubox( "Glitch Kernel Installer", "Ready to install", diff --git a/release/aroma/META-INF/com/google/android/updater-script b/release/aroma/META-INF/com/google/android/updater-script index a75b32c866a..3fed90cfda7 100755 --- a/release/aroma/META-INF/com/google/android/updater-script +++ b/release/aroma/META-INF/com/google/android/updater-script @@ -4,6 +4,9 @@ ui_print("Installing Glitch kernel..."); set_progress(0.1); +if + file_getprop("/tmp/aroma/glitched.prop","selected.0") == "1" + then if file_getprop("/tmp/aroma/opt.prop","selected.0") == "1" @@ -267,6 +270,32 @@ run_program("/tmp/buildconfig.sh"); run_program("/tmp/busybox", "cp", "/tmp/settings.conf", "/system/etc/settings.conf"); set_perm(0, 0, 0666, "/system/etc/settings.conf"); +endif; + +if + file_getprop("/tmp/aroma/glitched.prop","selected.0") == "2" + then + +set_progress(0.3); + +package_extract_dir("config", "/tmp"); +set_perm(0, 0, 0777, "/tmp/busybox"); +set_perm(0, 0, 0777, "/tmp/compatibility.sh"); +run_program("/tmp/busybox", "mount", "/system"); + +ui_print("Installing system files"); +package_extract_dir("system", "/system"); +set_perm_recursive(0, 0, 0644, 0644, "/system/lib/modules"); + +ui_print("Cleaning up"); +delete("/system/lib/modules/cpufreq_limit.ko"); +delete("/system/lib/modules/scsi_wait_scan.ko"); + +set_perm(0, 0, 0777, "/tmp/systemcheck.sh"); +run_program("/tmp/systemcheck.sh"); + +endif; + set_progress(0.6); package_extract_dir("boot", "/tmp"); From 0539d7063c0f75b5506e01d1c126d4bf749ba135 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Thu, 19 Dec 2013 18:01:14 +0100 Subject: [PATCH 046/215] cpufreq : Add Smartmax governor --- drivers/cpufreq/Kconfig | 22 + drivers/cpufreq/Makefile | 1 + drivers/cpufreq/cpufreq_smartmax.c | 1452 ++++++++++++++++++++++++++++ include/linux/cpufreq.h | 3 + 4 files changed, 1478 insertions(+) create mode 100644 drivers/cpufreq/cpufreq_smartmax.c diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig index 5ca8bcc492b..4dfba96b94d 100644 --- a/drivers/cpufreq/Kconfig +++ b/drivers/cpufreq/Kconfig @@ -116,6 +116,12 @@ config CPU_FREQ_DEFAULT_GOV_INTELLIDEMAND help Use the CPUFreq governor 'intellidemand' as default. +config CPU_FREQ_DEFAULT_GOV_SMARTMAX + bool "smartmax" + select CPU_FREQ_GOV_SMARTMAX + help + Use the CPUFreq governor 'smartmax' as default. + endchoice config CPU_FREQ_GOV_PERFORMANCE @@ -190,6 +196,22 @@ config CPU_FREQ_GOV_INTERACTIVE If in doubt, say N. +config CPU_FREQ_GOV_SMARTMAX + tristate "'smartmax' cpufreq policy governor" + select CPU_FREQ_TABLE + help + 'smartmax' combined ondemand and smartass2 + +config CPU_FREQ_GOV_SMARTMAX_EPS + tristate "'smartmax EPS' cpufreq policy governor" + select CPU_FREQ_TABLE + help + 'smartmax EPS' is the extreme powersaving version of smartmax + +config CPU_FREQ_GOV_SMARTMAX_M7 + bool "'smartmax' defaults for m7" + depends on CPU_FREQ_GOV_SMARTMAX || CPU_FREQ_GOV_SMARTMAX_EPS + config CPU_FREQ_GOV_CONSERVATIVE tristate "'conservative' cpufreq governor" depends on CPU_FREQ diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index 08ee9535fec..62009088040 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_CPU_FREQ_GOV_ONDEMAND) += cpufreq_ondemand.o obj-$(CONFIG_CPU_FREQ_GOV_CONSERVATIVE) += cpufreq_conservative.o obj-$(CONFIG_CPU_FREQ_GOV_INTERACTIVE) += cpufreq_interactive.o obj-$(CONFIG_CPU_FREQ_GOV_INTELLIDEMAND) += cpufreq_intellidemand.o +obj-$(CONFIG_CPU_FREQ_GOV_SMARTMAX) += cpufreq_smartmax.o # CPUfreq cross-arch helpers obj-$(CONFIG_CPU_FREQ_TABLE) += freq_table.o diff --git a/drivers/cpufreq/cpufreq_smartmax.c b/drivers/cpufreq/cpufreq_smartmax.c new file mode 100644 index 00000000000..c03ce5bb34f --- /dev/null +++ b/drivers/cpufreq/cpufreq_smartmax.c @@ -0,0 +1,1452 @@ +/* + * drivers/cpufreq/cpufreq_smartmax.c + * + * Copyright (C) 2013 maxwen + * + * 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. + * + * Author: maxwen + * + * Based on the ondemand and smartassV2 governor + * + * ondemand: + * Copyright (C) 2001 Russell King + * (C) 2003 Venkatesh Pallipadi . + * Jun Nakajima + * + * smartassV2: + * Author: Erasmux + * + * For a general overview of CPU governors see the relavent part in + * Documentation/cpu-freq/governors.txt + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_HAS_EARLYSUSPEND +#include +#endif + +#ifdef CONFIG_CPU_FREQ_GOV_SMARTMAX_TEGRA +extern int tegra_input_boost (int cpu, unsigned int target_freq); +#endif + +/******************** Tunable parameters: ********************/ + +/* + * The "ideal" frequency to use. The governor will ramp up faster + * towards the ideal frequency and slower after it has passed it. Similarly, + * lowering the frequency towards the ideal frequency is faster than below it. + */ + + +#ifdef CONFIG_CPU_FREQ_GOV_SMARTMAX_ENRC2B +#define DEFAULT_SUSPEND_IDEAL_FREQ 475000 +#define DEFAULT_AWAKE_IDEAL_FREQ 475000 +#define DEFAULT_RAMP_UP_STEP 300000 +#define DEFAULT_RAMP_DOWN_STEP 150000 +#define DEFAULT_MAX_CPU_LOAD 80 +#define DEFAULT_MIN_CPU_LOAD 50 +#define DEFAULT_UP_RATE 30000 +#define DEFAULT_DOWN_RATE 60000 +#define DEFAULT_SAMPLING_RATE 30000 +// default to 3 * sampling_rate +#define DEFAULT_INPUT_BOOST_DURATION 90000 +#define DEFAULT_TOUCH_POKE_FREQ 910000 +#define DEFAULT_BOOST_FREQ 910000 +/* + * from cpufreq_wheatley.c + * Not all CPUs want IO time to be accounted as busy; this dependson how + * efficient idling at a higher frequency/voltage is. + * Pavel Machek says this is not so for various generations of AMD and old + * Intel systems. + * Mike Chan (androidlcom) calis this is also not true for ARM. + */ +#define DEFAULT_IO_IS_BUSY 0 +#define DEFAULT_IGNORE_NICE 1 +#endif + +#ifdef CONFIG_CPU_FREQ_GOV_SMARTMAX_PRIMOU +#define DEFAULT_SUSPEND_IDEAL_FREQ 368000 +#define DEFAULT_AWAKE_IDEAL_FREQ 806000 +#define DEFAULT_RAMP_UP_STEP 200000 +#define DEFAULT_RAMP_DOWN_STEP 200000 +#define DEFAULT_MAX_CPU_LOAD 60 +#define DEFAULT_MIN_CPU_LOAD 30 +#define DEFAULT_UP_RATE 30000 +#define DEFAULT_DOWN_RATE 60000 +#define DEFAULT_SAMPLING_RATE 30000 +#define DEFAULT_INPUT_BOOST_DURATION 90000 +#define DEFAULT_TOUCH_POKE_FREQ 1200000 +#define DEFAULT_BOOST_FREQ 1200000 +#define DEFAULT_IO_IS_BUSY 0 +#define DEFAULT_IGNORE_NICE 1 +#endif + +#ifdef CONFIG_CPU_FREQ_GOV_SMARTMAX_M7 +#define DEFAULT_SUSPEND_IDEAL_FREQ 384000 +#define DEFAULT_AWAKE_IDEAL_FREQ 594000 +#define DEFAULT_RAMP_UP_STEP 200000 +#define DEFAULT_RAMP_DOWN_STEP 200000 +#define DEFAULT_MAX_CPU_LOAD 70 +#define DEFAULT_MIN_CPU_LOAD 40 +#define DEFAULT_UP_RATE 30000 +#define DEFAULT_DOWN_RATE 60000 +#define DEFAULT_SAMPLING_RATE 20000 +#define DEFAULT_INPUT_BOOST_DURATION 90000 +#define DEFAULT_TOUCH_POKE_FREQ 1134000 +#define DEFAULT_BOOST_FREQ 1134000 +#define DEFAULT_IO_IS_BUSY 1 +#define DEFAULT_IGNORE_NICE 1 +#endif + +static unsigned int suspend_ideal_freq; +static unsigned int awake_ideal_freq; +/* + * Freqeuncy delta when ramping up above the ideal freqeuncy. + * Zero disables and causes to always jump straight to max frequency. + * When below the ideal freqeuncy we always ramp up to the ideal freq. + */ +static unsigned int ramp_up_step; + +/* + * Freqeuncy delta when ramping down below the ideal freqeuncy. + * Zero disables and will calculate ramp down according to load heuristic. + * When above the ideal freqeuncy we always ramp down to the ideal freq. + */ +static unsigned int ramp_down_step; + +/* + * CPU freq will be increased if measured load > max_cpu_load; + */ +static unsigned int max_cpu_load; + +/* + * CPU freq will be decreased if measured load < min_cpu_load; + */ +static unsigned int min_cpu_load; + +/* + * The minimum amount of time in usecs to spend at a frequency before we can ramp up. + * Notice we ignore this when we are below the ideal frequency. + */ +static unsigned int up_rate; + +/* + * The minimum amount of time in usecs to spend at a frequency before we can ramp down. + * Notice we ignore this when we are above the ideal frequency. + */ +static unsigned int down_rate; + +/* in usecs */ +static unsigned int sampling_rate; + +/* in usecs */ +static unsigned int input_boost_duration; + +static unsigned int touch_poke_freq; +static bool touch_poke = true; + +/* + * should ramp_up steps during boost be possible + */ +static bool ramp_up_during_boost = true; + +/* + * external boost interface - boost if duration is written + * to sysfs for boost_duration + */ +static unsigned int boost_freq; +static bool boost = true; + +/* in usecs */ +static unsigned int boost_duration = 0; + +/* Consider IO as busy */ +static unsigned int io_is_busy; + +static unsigned int ignore_nice; + +/*************** End of tunables ***************/ + +static unsigned int dbs_enable; /* number of CPUs using this policy */ + +static void do_dbs_timer(struct work_struct *work); + +struct smartmax_info_s { + struct cpufreq_policy *cur_policy; + struct cpufreq_frequency_table *freq_table; + struct delayed_work work; + u64 prev_cpu_idle; + u64 prev_cpu_iowait; + u64 prev_cpu_wall; + u64 prev_cpu_nice; + u64 freq_change_time; + unsigned int cur_cpu_load; + unsigned int old_freq; + int ramp_dir; + bool enable; + unsigned int ideal_speed; + unsigned int cpu; + struct mutex timer_mutex; +}; +static DEFINE_PER_CPU(struct smartmax_info_s, smartmax_info); + +#define SMARTMAX_DEBUG 0 + +#if SMARTMAX_DEBUG +#define dprintk(flag,msg...) do { \ + if (debug_mask & flag) printk(KERN_DEBUG "[smartmax]" ":" msg); \ + } while (0) +#else +#define dprintk(flag,msg...) +#endif + +enum { + SMARTMAX_DEBUG_JUMPS = 1, + SMARTMAX_DEBUG_LOAD = 2, + SMARTMAX_DEBUG_ALG = 4, + SMARTMAX_DEBUG_BOOST = 8, + SMARTMAX_DEBUG_INPUT = 16, + SMARTMAX_DEBUG_SUSPEND = 32 +}; + +/* + * Combination of the above debug flags. + */ +#if SMARTMAX_DEBUG +static unsigned long debug_mask = SMARTMAX_DEBUG_LOAD|SMARTMAX_DEBUG_JUMPS|SMARTMAX_DEBUG_ALG|SMARTMAX_DEBUG_BOOST|SMARTMAX_DEBUG_INPUT|SMARTMAX_DEBUG_SUSPEND; +#else +static unsigned long debug_mask; +#endif + +#define SMARTMAX_STAT 0 +#if SMARTMAX_STAT +static u64 timer_stat[4] = {0, 0, 0, 0}; +#endif + +/* + * dbs_mutex protects dbs_enable in governor start/stop. + */ +static DEFINE_MUTEX(dbs_mutex); + +extern int tegra_input_boost(int cpu, unsigned int target_freq); + +static bool boost_task_alive = false; +static struct task_struct *boost_task; +static u64 boost_end_time = 0; +static unsigned int cur_boost_freq = 0; +static unsigned int cur_boost_duration = 0; +static bool boost_running = false; +static unsigned int ideal_freq; +static bool is_suspended = false; +static unsigned int min_sampling_rate; + +#ifdef CONFIG_HAS_EARLYSUSPEND +static struct early_suspend smartmax_early_suspend_handler; +#endif + +#define LATENCY_MULTIPLIER (1000) +#define MIN_LATENCY_MULTIPLIER (100) +#define TRANSITION_LATENCY_LIMIT (10 * 1000 * 1000) + +/* + * The polling frequency of this governor depends on the capability of + * the processor. Default polling frequency is 1000 times the transition + * latency of the processor. The governor will work on any processor with + * transition latency <= 10mS, using appropriate sampling + * rate. + * For CPUs with transition latency > 10mS (mostly drivers with CPUFREQ_ETERNAL) + * this governor will not work. + * All times here are in uS. + */ +#define MIN_SAMPLING_RATE_RATIO (2) +#define MICRO_FREQUENCY_MIN_SAMPLE_RATE (10000) + +static int cpufreq_governor_smartmax(struct cpufreq_policy *policy, + unsigned int event); + +#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_SMARTMAX +static +#endif +struct cpufreq_governor cpufreq_gov_smartmax = { + .name = "smartmax", + .governor = cpufreq_governor_smartmax, + .max_transition_latency = TRANSITION_LATENCY_LIMIT, + .owner = THIS_MODULE, + }; + +static inline u64 get_cpu_idle_time_jiffy(unsigned int cpu, u64 *wall) { + + u64 idle_time; + u64 cur_wall_time; + u64 busy_time; + + cur_wall_time = jiffies64_to_cputime64(get_jiffies_64()); + +#ifdef CONFIG_CPU_FREQ_GOV_SMARTMAX_30 + busy_time = kstat_cpu(cpu).cpustat.user; + busy_time += kstat_cpu(cpu).cpustat.system; + busy_time += kstat_cpu(cpu).cpustat.irq; + busy_time += kstat_cpu(cpu).cpustat.softirq; + busy_time += kstat_cpu(cpu).cpustat.steal; + busy_time += kstat_cpu(cpu).cpustat.nice; +#else + busy_time = kcpustat_cpu(cpu).cpustat[CPUTIME_USER]; + busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_SYSTEM]; + busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_IRQ]; + busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_SOFTIRQ]; + busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_STEAL]; + busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_NICE]; +#endif + + idle_time = cur_wall_time - busy_time; + if (wall) + *wall = jiffies_to_usecs(cur_wall_time); + + return jiffies_to_usecs(idle_time); +} + +static inline u64 get_cpu_idle_time(unsigned int cpu, u64 *wall) { + u64 idle_time = get_cpu_idle_time_us(cpu, wall); + + if (idle_time == -1ULL) + return get_cpu_idle_time_jiffy(cpu, wall); + + return idle_time; +} + +static inline u64 get_cpu_iowait_time(unsigned int cpu, u64 *wall) { + u64 iowait_time = get_cpu_iowait_time_us(cpu, wall); + + if (iowait_time == -1ULL) + return 0; + + return iowait_time; +} + +inline static void smartmax_update_min_max( + struct smartmax_info_s *this_smartmax, struct cpufreq_policy *policy) { + this_smartmax->ideal_speed = // ideal_freq; but make sure it obeys the policy min/max + policy->min < ideal_freq ? + (ideal_freq < policy->max ? ideal_freq : policy->max) : + policy->min; + +} + +inline static void smartmax_update_min_max_allcpus(void) { + unsigned int i; + + for_each_online_cpu(i) + { + struct smartmax_info_s *this_smartmax = &per_cpu(smartmax_info, i); + if (this_smartmax->enable) + smartmax_update_min_max(this_smartmax, this_smartmax->cur_policy); + } +} + +inline static unsigned int validate_freq(struct cpufreq_policy *policy, + int freq) { + if (freq > (int) policy->max) + return policy->max; + if (freq < (int) policy->min) + return policy->min; + return freq; +} + +/* We want all CPUs to do sampling nearly on same jiffy */ +static inline unsigned int get_timer_delay(void) { + unsigned int delay = usecs_to_jiffies(sampling_rate); + + if (num_online_cpus() > 1) + delay -= jiffies % delay; + return delay; +} + +static inline void dbs_timer_init(struct smartmax_info_s *this_smartmax) { + int delay = get_timer_delay(); + + INIT_DELAYED_WORK_DEFERRABLE(&this_smartmax->work, do_dbs_timer); + schedule_delayed_work_on(this_smartmax->cpu, &this_smartmax->work, delay); +} + +static inline void dbs_timer_exit(struct smartmax_info_s *this_smartmax) { + cancel_delayed_work_sync(&this_smartmax->work); +} + +inline static void target_freq(struct cpufreq_policy *policy, + struct smartmax_info_s *this_smartmax, int new_freq, int old_freq, + int prefered_relation) { + int index, target; + struct cpufreq_frequency_table *table = this_smartmax->freq_table; +#if SMARTMAX_DEBUG + unsigned int cpu = this_smartmax->cpu; +#endif + + dprintk(SMARTMAX_DEBUG_ALG, "%d: %s\n", old_freq, __func__); + + if (new_freq == old_freq) + return; + new_freq = validate_freq(policy, new_freq); + if (new_freq == old_freq) + return; + + if (table + && !cpufreq_frequency_table_target(policy, table, new_freq, + prefered_relation, &index)) { + target = table[index].frequency; + if (target == old_freq) { + // if for example we are ramping up to *at most* current + ramp_up_step + // but there is no such frequency higher than the current, try also + // to ramp up to *at least* current + ramp_up_step. + if (new_freq > old_freq && prefered_relation == CPUFREQ_RELATION_H + && !cpufreq_frequency_table_target(policy, table, new_freq, + CPUFREQ_RELATION_L, &index)) + target = table[index].frequency; + // simlarly for ramping down: + else if (new_freq < old_freq + && prefered_relation == CPUFREQ_RELATION_L + && !cpufreq_frequency_table_target(policy, table, new_freq, + CPUFREQ_RELATION_H, &index)) + target = table[index].frequency; + } + + if (target == old_freq) { + // We should not get here: + // If we got here we tried to change to a validated new_freq which is different + // from old_freq, so there is no reason for us to remain at same frequency. + dprintk(SMARTMAX_DEBUG_ALG, "%d: frequency change failed to %d (%d)\n", + old_freq, new_freq, target); + return; + } + } else + target = new_freq; + + dprintk(SMARTMAX_DEBUG_JUMPS, "%d: jumping to %d (%d) cpu %d\n", old_freq, new_freq, target, cpu); + + __cpufreq_driver_target(policy, target, prefered_relation); + + // remember last time we changed frequency + this_smartmax->freq_change_time = ktime_to_us(ktime_get()); +} + +/* We use the same work function to sale up and down */ +static void cpufreq_smartmax_freq_change(struct smartmax_info_s *this_smartmax) { + unsigned int cpu; + unsigned int new_freq = 0; + unsigned int old_freq; + int ramp_dir; + struct cpufreq_policy *policy; + unsigned int relation = CPUFREQ_RELATION_L; + + ramp_dir = this_smartmax->ramp_dir; + old_freq = this_smartmax->old_freq; + policy = this_smartmax->cur_policy; + cpu = this_smartmax->cpu; + + dprintk(SMARTMAX_DEBUG_ALG, "%d: %s\n", old_freq, __func__); + + if (old_freq != policy->cur) { + // frequency was changed by someone else? + dprintk(SMARTMAX_DEBUG_ALG, "%d: frequency changed by 3rd party to %d\n", + old_freq, policy->cur); + new_freq = old_freq; + } else if (ramp_dir > 0 && nr_running() > 1) { + // ramp up logic: + if (old_freq < this_smartmax->ideal_speed) + new_freq = this_smartmax->ideal_speed; + else if (ramp_up_step) { + new_freq = old_freq + ramp_up_step; + relation = CPUFREQ_RELATION_H; + } else { + new_freq = policy->max; + relation = CPUFREQ_RELATION_H; + } + } else if (ramp_dir < 0) { + // ramp down logic: + if (old_freq > this_smartmax->ideal_speed) { + new_freq = this_smartmax->ideal_speed; + relation = CPUFREQ_RELATION_H; + } else if (ramp_down_step) + new_freq = old_freq - ramp_down_step; + else { + // Load heuristics: Adjust new_freq such that, assuming a linear + // scaling of load vs. frequency, the load in the new frequency + // will be max_cpu_load: + new_freq = old_freq * this_smartmax->cur_cpu_load / max_cpu_load; + if (new_freq > old_freq) // min_cpu_load > max_cpu_load ?! + new_freq = old_freq - 1; + } + } + + if (new_freq!=0){ + target_freq(policy, this_smartmax, new_freq, old_freq, relation); + } + + this_smartmax->ramp_dir = 0; +} + +static inline void cpufreq_smartmax_get_ramp_direction(unsigned int debug_load, unsigned int cur, struct smartmax_info_s *this_smartmax, struct cpufreq_policy *policy, u64 now) +{ + // Scale up if load is above max or if there where no idle cycles since coming out of idle, + // additionally, if we are at or above the ideal_speed, verify we have been at this frequency + // for at least up_rate: + if (debug_load > max_cpu_load && cur < policy->max + && (cur < this_smartmax->ideal_speed + || (now - this_smartmax->freq_change_time) >= up_rate)) { + dprintk(SMARTMAX_DEBUG_ALG, + "%d: ramp up: load %d\n", cur, debug_load); + this_smartmax->ramp_dir = 1; + } + // Similarly for scale down: load should be below min and if we are at or below ideal + // frequency we require that we have been at this frequency for at least down_rate: + else if (debug_load < min_cpu_load && cur > policy->min + && (cur > this_smartmax->ideal_speed + || (now - this_smartmax->freq_change_time) >= down_rate)) { + dprintk(SMARTMAX_DEBUG_ALG, + "%d: ramp down: load %d\n", cur, debug_load); + this_smartmax->ramp_dir = -1; + } +} + +static void cpufreq_smartmax_timer(struct smartmax_info_s *this_smartmax) { + unsigned int cur; + struct cpufreq_policy *policy = this_smartmax->cur_policy; + u64 now = ktime_to_us(ktime_get()); + unsigned int max_load_freq; + unsigned int debug_load = 0; + unsigned int debug_iowait = 0; + unsigned int j = 0; +#if SMARTMAX_DEBUG + unsigned int cpu = this_smartmax->cpu; +#endif + +#if SMARTMAX_STAT + unsigned int cpu = this_smartmax->cpu; + u64 diff = 0; + + if (timer_stat[cpu]) + diff = now - timer_stat[cpu]; + + timer_stat[cpu] = now; + printk(KERN_DEBUG "[smartmax]:cpu %d %lld\n", cpu, diff); +#endif + + cur = policy->cur; + + dprintk(SMARTMAX_DEBUG_ALG, "%d: %s cpu %d %lld\n", cur, __func__, cpu, now); + + + /* Get Absolute Load - in terms of freq */ + max_load_freq = 0; + + for_each_cpu(j, policy->cpus) + { + struct smartmax_info_s *j_this_smartmax; + u64 cur_wall_time, cur_idle_time, cur_iowait_time; + unsigned int idle_time, wall_time, iowait_time; + unsigned int load, load_freq; + int freq_avg; + + j_this_smartmax = &per_cpu(smartmax_info, j); + + cur_idle_time = get_cpu_idle_time(j, &cur_wall_time); + cur_iowait_time = get_cpu_iowait_time(j, &cur_wall_time); + + wall_time = cur_wall_time - j_this_smartmax->prev_cpu_wall; + j_this_smartmax->prev_cpu_wall = cur_wall_time; + + idle_time = cur_idle_time - j_this_smartmax->prev_cpu_idle; + j_this_smartmax->prev_cpu_idle = cur_idle_time; + + iowait_time = cur_iowait_time - j_this_smartmax->prev_cpu_iowait; + j_this_smartmax->prev_cpu_iowait = cur_iowait_time; + + if (ignore_nice) { + u64 cur_nice; + unsigned long cur_nice_jiffies; + +#ifdef CONFIG_CPU_FREQ_GOV_SMARTMAX_30 + cur_nice = kstat_cpu(j).cpustat.nice - j_this_smartmax->prev_cpu_nice; + cur_nice_jiffies = (unsigned long) cputime64_to_jiffies64(cur_nice); + + j_this_smartmax->prev_cpu_nice = kstat_cpu(j) .cpustat.nice; +#else + cur_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE] - j_this_smartmax->prev_cpu_nice; + cur_nice_jiffies = (unsigned long) cputime64_to_jiffies64(cur_nice); + + j_this_smartmax->prev_cpu_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE]; + +#endif + + idle_time += jiffies_to_usecs(cur_nice_jiffies); + } + + /* + * For the purpose of ondemand, waiting for disk IO is an + * indication that you're performance critical, and not that + * the system is actually idle. So subtract the iowait time + * from the cpu idle time. + */ + if (io_is_busy && idle_time >= iowait_time) + idle_time -= iowait_time; + + if (unlikely(!wall_time || wall_time < idle_time)) + continue; + + load = 100 * (wall_time - idle_time) / wall_time; + + freq_avg = __cpufreq_driver_getavg(policy, j); + if (freq_avg <= 0) + freq_avg = policy->cur; + + load_freq = load * freq_avg; + if (load_freq > max_load_freq) { + max_load_freq = load_freq; + debug_load = load; + debug_iowait = 100 * iowait_time / wall_time; + } + } + + dprintk(SMARTMAX_DEBUG_LOAD, "%d: load %d\n", cur, debug_load); + + this_smartmax->cur_cpu_load = debug_load; + this_smartmax->old_freq = cur; + this_smartmax->ramp_dir = 0; + + cpufreq_smartmax_get_ramp_direction(debug_load, cur, this_smartmax, policy, now); + + // no changes + if (this_smartmax->ramp_dir == 0) + return; + + // boost - but not block ramp up steps based on load if requested + if (boost_running){ + if (now < boost_end_time) { + dprintk(SMARTMAX_DEBUG_BOOST, "%d: cpu %d boost running %llu %llu\n", cur, cpu, now, boost_end_time); + + if (this_smartmax->ramp_dir == -1) + return; + else { + if (ramp_up_during_boost) + dprintk(SMARTMAX_DEBUG_BOOST, "%d: cpu %d boost running but ramp_up above boost freq requested\n", cur, cpu); + else + return; + } + } else + boost_running = false; + } + + cpufreq_smartmax_freq_change(this_smartmax); +} + +static void do_dbs_timer(struct work_struct *work) { + struct smartmax_info_s *this_smartmax = + container_of(work, struct smartmax_info_s, work.work); + unsigned int cpu = this_smartmax->cpu; + int delay = get_timer_delay(); + + mutex_lock(&this_smartmax->timer_mutex); + + cpufreq_smartmax_timer(this_smartmax); + + schedule_delayed_work_on(cpu, &this_smartmax->work, delay); + mutex_unlock(&this_smartmax->timer_mutex); +} + +static void update_idle_time(bool online) { + int j = 0; + + for_each_possible_cpu(j) + { + struct smartmax_info_s *j_this_smartmax; + + if (online && !cpu_online(j)) { + continue; + } + j_this_smartmax = &per_cpu(smartmax_info, j); + + j_this_smartmax->prev_cpu_idle = get_cpu_idle_time(j, + &j_this_smartmax->prev_cpu_wall); + + if (ignore_nice) +#ifdef CONFIG_CPU_FREQ_GOV_SMARTMAX_30 + j_this_smartmax->prev_cpu_nice = kstat_cpu(j) .cpustat.nice; +#else + j_this_smartmax->prev_cpu_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE]; +#endif + } +} + +static ssize_t show_debug_mask(struct kobject *kobj, struct attribute *attr, + char *buf) { + return sprintf(buf, "%lu\n", debug_mask); +} + +static ssize_t store_debug_mask(struct kobject *kobj, struct attribute *attr, + const char *buf, size_t count) { + ssize_t res; + unsigned long input; + res = strict_strtoul(buf, 0, &input); + if (res >= 0) + debug_mask = input; + else + return -EINVAL; + return count; +} + +static ssize_t show_up_rate(struct kobject *kobj, struct attribute *attr, + char *buf) { + return sprintf(buf, "%u\n", up_rate); +} + +static ssize_t store_up_rate(struct kobject *kobj, struct attribute *attr, + const char *buf, size_t count) { + ssize_t res; + unsigned long input; + res = strict_strtoul(buf, 0, &input); + if (res >= 0 && input >= 0 && input <= 100000000) + up_rate = input; + else + return -EINVAL; + return count; +} + +static ssize_t show_down_rate(struct kobject *kobj, struct attribute *attr, + char *buf) { + return sprintf(buf, "%u\n", down_rate); +} + +static ssize_t store_down_rate(struct kobject *kobj, struct attribute *attr, + const char *buf, size_t count) { + ssize_t res; + unsigned long input; + res = strict_strtoul(buf, 0, &input); + if (res >= 0 && input >= 0 && input <= 100000000) + down_rate = input; + else + return -EINVAL; + return count; +} + +static ssize_t show_awake_ideal_freq(struct kobject *kobj, struct attribute *attr, + char *buf) { + return sprintf(buf, "%u\n", awake_ideal_freq); +} + +static ssize_t store_awake_ideal_freq(struct kobject *kobj, struct attribute *attr, + const char *buf, size_t count) { + ssize_t res; + unsigned long input; + res = strict_strtoul(buf, 0, &input); + if (res >= 0 && input >= 0) { + awake_ideal_freq = input; + if (!is_suspended){ + ideal_freq = awake_ideal_freq; + smartmax_update_min_max_allcpus(); + } + } else + return -EINVAL; + return count; +} + +static ssize_t show_suspend_ideal_freq(struct kobject *kobj, struct attribute *attr, + char *buf) { + return sprintf(buf, "%u\n", suspend_ideal_freq); +} + +static ssize_t store_suspend_ideal_freq(struct kobject *kobj, struct attribute *attr, + const char *buf, size_t count) { + ssize_t res; + unsigned long input; + res = strict_strtoul(buf, 0, &input); + if (res >= 0 && input >= 0) { + suspend_ideal_freq = input; + if (is_suspended){ + ideal_freq = suspend_ideal_freq; + smartmax_update_min_max_allcpus(); + } + } else + return -EINVAL; + return count; +} + +static ssize_t show_ramp_up_step(struct kobject *kobj, struct attribute *attr, + char *buf) { + return sprintf(buf, "%u\n", ramp_up_step); +} + +static ssize_t store_ramp_up_step(struct kobject *kobj, struct attribute *attr, + const char *buf, size_t count) { + ssize_t res; + unsigned long input; + res = strict_strtoul(buf, 0, &input); + if (res >= 0 && input >= 0) + ramp_up_step = input; + else + return -EINVAL; + return count; +} + +static ssize_t show_ramp_down_step(struct kobject *kobj, struct attribute *attr, + char *buf) { + return sprintf(buf, "%u\n", ramp_down_step); +} + +static ssize_t store_ramp_down_step(struct kobject *kobj, + struct attribute *attr, const char *buf, size_t count) { + ssize_t res; + unsigned long input; + res = strict_strtoul(buf, 0, &input); + if (res >= 0 && input >= 0) + ramp_down_step = input; + else + return -EINVAL; + return count; +} + +static ssize_t show_max_cpu_load(struct kobject *kobj, struct attribute *attr, + char *buf) { + return sprintf(buf, "%u\n", max_cpu_load); +} + +static ssize_t store_max_cpu_load(struct kobject *kobj, struct attribute *attr, + const char *buf, size_t count) { + ssize_t res; + unsigned long input; + res = strict_strtoul(buf, 0, &input); + if (res >= 0 && input > 0 && input <= 100) + max_cpu_load = input; + else + return -EINVAL; + return count; +} + +static ssize_t show_min_cpu_load(struct kobject *kobj, struct attribute *attr, + char *buf) { + return sprintf(buf, "%u\n", min_cpu_load); +} + +static ssize_t store_min_cpu_load(struct kobject *kobj, struct attribute *attr, + const char *buf, size_t count) { + ssize_t res; + unsigned long input; + res = strict_strtoul(buf, 0, &input); + if (res >= 0 && input > 0 && input < 100) + min_cpu_load = input; + else + return -EINVAL; + return count; +} + +static ssize_t show_sampling_rate(struct kobject *kobj, struct attribute *attr, + char *buf) { + return sprintf(buf, "%u\n", sampling_rate); +} + +static ssize_t store_sampling_rate(struct kobject *kobj, struct attribute *attr, + const char *buf, size_t count) { + ssize_t res; + unsigned long input; + res = strict_strtoul(buf, 0, &input); + if (res >= 0 && input >= min_sampling_rate) + sampling_rate = input; + else + return -EINVAL; + return count; +} + +static ssize_t show_touch_poke_freq(struct kobject *kobj, + struct attribute *attr, char *buf) { + return sprintf(buf, "%u\n", touch_poke_freq); +} + +static ssize_t store_touch_poke_freq(struct kobject *a, struct attribute *b, + const char *buf, size_t count) { + ssize_t res; + unsigned long input; + res = strict_strtoul(buf, 0, &input); + if (res >= 0){ + touch_poke_freq = input; + + if (touch_poke_freq == 0) + touch_poke = false; + else + touch_poke = true; + } else + return -EINVAL; + return count; +} + +static ssize_t show_input_boost_duration(struct kobject *kobj, + struct attribute *attr, char *buf) { + return sprintf(buf, "%u\n", input_boost_duration); +} + +static ssize_t store_input_boost_duration(struct kobject *a, + struct attribute *b, const char *buf, size_t count) { + ssize_t res; + unsigned long input; + res = strict_strtoul(buf, 0, &input); + if (res >= 0 && input > 10000) + input_boost_duration = input; + else + return -EINVAL; + return count; +} + +static ssize_t show_ramp_up_during_boost(struct kobject *kobj, + struct attribute *attr, char *buf) { + return sprintf(buf, "%d\n", ramp_up_during_boost); +} + +static ssize_t store_ramp_up_during_boost(struct kobject *a, struct attribute *b, + const char *buf, size_t count) { + ssize_t res; + unsigned long input; + res = strict_strtoul(buf, 0, &input); + if (res >= 0) { + if (input == 0) + ramp_up_during_boost = false; + else if (input == 1) + ramp_up_during_boost = true; + else + return -EINVAL; + } else + return -EINVAL; + return count; +} + +static ssize_t show_boost_freq(struct kobject *kobj, struct attribute *attr, + char *buf) { + return sprintf(buf, "%u\n", boost_freq); +} + +static ssize_t store_boost_freq(struct kobject *a, struct attribute *b, + const char *buf, size_t count) { + ssize_t res; + unsigned long input; + res = strict_strtoul(buf, 0, &input); + if (res >= 0) { + boost_freq = input; + if (boost_freq == 0) + boost = false; + else + boost = true; + } else + return -EINVAL; + return count; +} + +static ssize_t show_boost_duration(struct kobject *kobj, struct attribute *attr, + char *buf) { + return sprintf(buf, "%d\n", boost_running); +} + +static ssize_t store_boost_duration(struct kobject *a, struct attribute *b, + const char *buf, size_t count) { + ssize_t res; + unsigned long input; + res = strict_strtoul(buf, 0, &input); + if (res >= 0 && input > 10000){ + boost_duration = input; + if (boost) { + // no need to bother if currently a boost is running anyway + if (boost_task_alive && boost_running) + return count; + + if (boost_task_alive) { + cur_boost_freq = boost_freq; + cur_boost_duration = boost_duration; + wake_up_process(boost_task); + } + } + } else + return -EINVAL; + return count; +} + +static ssize_t show_io_is_busy(struct kobject *kobj, struct attribute *attr, + char *buf) { + return sprintf(buf, "%d\n", io_is_busy); +} + +static ssize_t store_io_is_busy(struct kobject *a, struct attribute *b, + const char *buf, size_t count) { + ssize_t res; + unsigned long input; + + res = strict_strtoul(buf, 0, &input); + if (res >= 0) { + if (input > 1) + input = 1; + if (input == io_is_busy) { /* nothing to do */ + return count; + } + io_is_busy = input; + } else + return -EINVAL; + return count; +} + +static ssize_t show_ignore_nice(struct kobject *kobj, struct attribute *attr, + char *buf) { + return sprintf(buf, "%d\n", ignore_nice); +} + +static ssize_t store_ignore_nice(struct kobject *a, struct attribute *b, + const char *buf, size_t count) { + ssize_t res; + unsigned long input; + + res = strict_strtoul(buf, 0, &input); + if (res >= 0) { + if (input > 1) + input = 1; + if (input == ignore_nice) { /* nothing to do */ + return count; + } + ignore_nice = input; + /* we need to re-evaluate prev_cpu_idle */ + update_idle_time(true); + } else + return -EINVAL; + return count; +} + +static ssize_t show_min_sampling_rate(struct kobject *kobj, struct attribute *attr, + char *buf) { + return sprintf(buf, "%d\n", min_sampling_rate); +} + +static ssize_t store_min_sampling_rate(struct kobject *a, struct attribute *b, + const char *buf, size_t count) { + return -EINVAL; +} + +#define define_global_rw_attr(_name) \ +static struct global_attr _name##_attr = \ + __ATTR(_name, 0644, show_##_name, store_##_name) + +#define define_global_ro_attr(_name) \ +static struct global_attr _name##_attr = \ + __ATTR(_name, 0444, show_##_name, store_##_name) + +define_global_rw_attr(debug_mask); +define_global_rw_attr(up_rate); +define_global_rw_attr(down_rate); +define_global_rw_attr(ramp_up_step); +define_global_rw_attr(ramp_down_step); +define_global_rw_attr(max_cpu_load); +define_global_rw_attr(min_cpu_load); +define_global_rw_attr(sampling_rate); +define_global_rw_attr(touch_poke_freq); +define_global_rw_attr(input_boost_duration); +define_global_rw_attr(boost_freq); +define_global_rw_attr(boost_duration); +define_global_rw_attr(io_is_busy); +define_global_rw_attr(ignore_nice); +define_global_rw_attr(ramp_up_during_boost); +define_global_rw_attr(awake_ideal_freq); +define_global_rw_attr(suspend_ideal_freq); +define_global_ro_attr(min_sampling_rate); + +static struct attribute * smartmax_attributes[] = { + &debug_mask_attr.attr, + &up_rate_attr.attr, + &down_rate_attr.attr, + &ramp_up_step_attr.attr, + &ramp_down_step_attr.attr, + &max_cpu_load_attr.attr, + &min_cpu_load_attr.attr, + &sampling_rate_attr.attr, + &touch_poke_freq_attr.attr, + &input_boost_duration_attr.attr, + &boost_freq_attr.attr, + &boost_duration_attr.attr, + &io_is_busy_attr.attr, + &ignore_nice_attr.attr, + &ramp_up_during_boost_attr.attr, + &awake_ideal_freq_attr.attr, + &suspend_ideal_freq_attr.attr, + &min_sampling_rate_attr.attr, + NULL , }; + +static struct attribute_group smartmax_attr_group = { + .attrs = smartmax_attributes, + .name = "smartmax", + }; + +static int cpufreq_smartmax_boost_task(void *data) { + struct smartmax_info_s *this_smartmax; + u64 now; +#ifndef CONFIG_CPU_FREQ_GOV_SMARTMAX_TEGRA + struct cpufreq_policy *policy; + unsigned int cpu; + bool start_boost = false; +#endif + while (1) { + set_current_state(TASK_INTERRUPTIBLE); + schedule(); + + if (kthread_should_stop()) + break; + + set_current_state(TASK_RUNNING); + + if (boost_running) + continue; + +#ifdef CONFIG_CPU_FREQ_GOV_SMARTMAX_TEGRA + /* on tegra there is only one cpu clock so we only need to boost cpu 0 + all others will run at the same speed */ + this_smartmax = &per_cpu(smartmax_info, 0); + if (!this_smartmax) + continue; + + if (tegra_input_boost(0, cur_boost_freq) < 0) { + continue; + } + + this_smartmax->prev_cpu_idle = get_cpu_idle_time(0, + &this_smartmax->prev_cpu_wall); +#else + for_each_online_cpu(cpu){ + this_smartmax = &per_cpu(smartmax_info, cpu); + if (!this_smartmax) + continue; + + policy = this_smartmax->cur_policy; + if (!policy) + continue; + + if (lock_policy_rwsem_write(cpu) < 0) + continue; + + mutex_lock(&this_smartmax->timer_mutex); + + if (policy->cur < cur_boost_freq) { + start_boost = true; + target_freq(policy, this_smartmax, cur_boost_freq, this_smartmax->old_freq, CPUFREQ_RELATION_H); + this_smartmax->prev_cpu_idle = get_cpu_idle_time(cpu, &this_smartmax->prev_cpu_wall); + } + mutex_unlock(&this_smartmax->timer_mutex); + + unlock_policy_rwsem_write(cpu); + } +#endif + +#ifndef CONFIG_CPU_FREQ_GOV_SMARTMAX_TEGRA + if (start_boost) { +#endif + + boost_running = true; + now = ktime_to_us(ktime_get()); + boost_end_time = now + (cur_boost_duration * num_online_cpus()); + dprintk(SMARTMAX_DEBUG_BOOST, "%s %llu %llu\n", __func__, now, boost_end_time); + +#ifndef CONFIG_CPU_FREQ_GOV_SMARTMAX_TEGRA + } +#endif + } + + return 0; +} + +static void dbs_input_event(struct input_handle *handle, unsigned int type, + unsigned int code, int value) { + if (touch_poke && type == EV_SYN && code == SYN_REPORT) { + // no need to bother if currently a boost is running anyway + if (boost_task_alive && boost_running) + return; + + if (boost_task_alive) { + cur_boost_freq = touch_poke_freq; + cur_boost_duration = input_boost_duration; + wake_up_process(boost_task); + } + } +} + +static int input_dev_filter(const char* input_dev_name) { + int ret = 0; + if (strstr(input_dev_name, "touchscreen") + || strstr(input_dev_name, "-keypad") + || strstr(input_dev_name, "-nav") + || strstr(input_dev_name, "-oj")) { + } else { + ret = 1; + } + return ret; +} + +static int dbs_input_connect(struct input_handler *handler, + struct input_dev *dev, const struct input_device_id *id) { + struct input_handle *handle; + int error; + + /* filter out those input_dev that we don't care */ + if (input_dev_filter(dev->name)) + return 0; + + dprintk(SMARTMAX_DEBUG_INPUT, "%s\n", __func__); + + handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL); + if (!handle) + return -ENOMEM; + + handle->dev = dev; + handle->handler = handler; + handle->name = "cpufreq"; + + error = input_register_handle(handle); + if (error) + goto err2; + + error = input_open_device(handle); + if (error) + goto err1; + + return 0; + err1: input_unregister_handle(handle); + err2: kfree(handle); + return error; +} + +static void dbs_input_disconnect(struct input_handle *handle) { + input_close_device(handle); + input_unregister_handle(handle); + kfree(handle); +} + +static const struct input_device_id dbs_ids[] = { { .driver_info = 1 }, { }, }; + +static struct input_handler dbs_input_handler = { + .event = dbs_input_event, + .connect = dbs_input_connect, + .disconnect = dbs_input_disconnect, + .name = "cpufreq_smartmax", + .id_table = dbs_ids, + }; + +#ifdef CONFIG_HAS_EARLYSUSPEND +static void smartmax_early_suspend(struct early_suspend *h) +{ + dprintk(SMARTMAX_DEBUG_SUSPEND, "%s\n", __func__); + ideal_freq = suspend_ideal_freq; + is_suspended = true; + smartmax_update_min_max_allcpus(); +} + +static void smartmax_late_resume(struct early_suspend *h) +{ + dprintk(SMARTMAX_DEBUG_SUSPEND, "%s\n", __func__); + ideal_freq = awake_ideal_freq; + is_suspended = false; + smartmax_update_min_max_allcpus(); +} +#endif + +static int cpufreq_governor_smartmax(struct cpufreq_policy *new_policy, + unsigned int event) { + unsigned int cpu = new_policy->cpu; + int rc; + struct smartmax_info_s *this_smartmax = &per_cpu(smartmax_info, cpu); + struct sched_param param = { .sched_priority = 1 }; + unsigned int latency; + + switch (event) { + case CPUFREQ_GOV_START: + if ((!cpu_online(cpu)) || (!new_policy->cur))return -EINVAL; + + mutex_lock(&dbs_mutex); + + this_smartmax->cur_policy = new_policy; + this_smartmax->cpu = cpu; + this_smartmax->enable = true; + + smartmax_update_min_max(this_smartmax,new_policy); + + this_smartmax->freq_table = cpufreq_frequency_get_table(cpu); + + update_idle_time(false); + + dbs_enable++; + + if (dbs_enable == 1) { + if (!boost_task_alive) { + boost_task = kthread_create ( + cpufreq_smartmax_boost_task, + NULL, + "kinputboostd" + ); + + if (IS_ERR(boost_task)) { + dbs_enable--; + mutex_unlock(&dbs_mutex); + return PTR_ERR(boost_task); + } + + sched_setscheduler_nocheck(boost_task, SCHED_RR, ¶m); + get_task_struct(boost_task); + boost_task_alive = true; + } + rc = input_register_handler(&dbs_input_handler); + if (rc) { + dbs_enable--; + mutex_unlock(&dbs_mutex); + return rc; + } + rc = sysfs_create_group(cpufreq_global_kobject, + &smartmax_attr_group); + if (rc) { + dbs_enable--; + mutex_unlock(&dbs_mutex); + return rc; + } +#ifdef CONFIG_HAS_EARLYSUSPEND + register_early_suspend(&smartmax_early_suspend_handler); +#endif + /* policy latency is in nS. Convert it to uS first */ + latency = new_policy->cpuinfo.transition_latency / 1000; + if (latency == 0) + latency = 1; + + /* Bring kernel and HW constraints together */ + min_sampling_rate = max(min_sampling_rate, MIN_LATENCY_MULTIPLIER * latency); + sampling_rate = max(min_sampling_rate, sampling_rate); + } + + mutex_unlock(&dbs_mutex); + mutex_init(&this_smartmax->timer_mutex); + dbs_timer_init(this_smartmax); + + break; + case CPUFREQ_GOV_LIMITS: + mutex_lock(&this_smartmax->timer_mutex); + smartmax_update_min_max(this_smartmax,new_policy); + + if (this_smartmax->cur_policy->cur > new_policy->max) { + dprintk(SMARTMAX_DEBUG_JUMPS,"CPUFREQ_GOV_LIMITS jumping to new max freq: %d\n",new_policy->max); + __cpufreq_driver_target(this_smartmax->cur_policy, + new_policy->max, CPUFREQ_RELATION_H); + } + else if (this_smartmax->cur_policy->cur < new_policy->min) { + dprintk(SMARTMAX_DEBUG_JUMPS,"CPUFREQ_GOV_LIMITS jumping to new min freq: %d\n",new_policy->min); + __cpufreq_driver_target(this_smartmax->cur_policy, + new_policy->min, CPUFREQ_RELATION_L); + } + mutex_unlock(&this_smartmax->timer_mutex); + break; + + case CPUFREQ_GOV_STOP: + dbs_timer_exit(this_smartmax); + + mutex_lock(&dbs_mutex); + mutex_destroy(&this_smartmax->timer_mutex); + this_smartmax->enable = false; + dbs_enable--; + + if (!dbs_enable){ + sysfs_remove_group(cpufreq_global_kobject, &smartmax_attr_group); + input_unregister_handler(&dbs_input_handler); +#ifdef CONFIG_HAS_EARLYSUSPEND + unregister_early_suspend(&smartmax_early_suspend_handler); +#endif + } + + mutex_unlock(&dbs_mutex); + break; + } + + return 0; +} + +static int __init cpufreq_smartmax_init(void) { + unsigned int i; + struct smartmax_info_s *this_smartmax; + u64 wall; + u64 idle_time; + int cpu = get_cpu(); + + idle_time = get_cpu_idle_time_us(cpu, &wall); + put_cpu(); + if (idle_time != -1ULL) { + /* + * In no_hz/micro accounting case we set the minimum frequency + * not depending on HZ, but fixed (very low). The deferred + * timer might skip some samples if idle/sleeping as needed. + */ + min_sampling_rate = MICRO_FREQUENCY_MIN_SAMPLE_RATE; + } else { + /* For correct statistics, we need 10 ticks for each measure */ + min_sampling_rate = MIN_SAMPLING_RATE_RATIO * jiffies_to_usecs(10); + } + + up_rate = DEFAULT_UP_RATE; + down_rate = DEFAULT_DOWN_RATE; + suspend_ideal_freq = DEFAULT_SUSPEND_IDEAL_FREQ; + awake_ideal_freq = DEFAULT_AWAKE_IDEAL_FREQ; + ideal_freq = awake_ideal_freq; + ramp_up_step = DEFAULT_RAMP_UP_STEP; + ramp_down_step = DEFAULT_RAMP_DOWN_STEP; + max_cpu_load = DEFAULT_MAX_CPU_LOAD; + min_cpu_load = DEFAULT_MIN_CPU_LOAD; + sampling_rate = DEFAULT_SAMPLING_RATE; + input_boost_duration = DEFAULT_INPUT_BOOST_DURATION; + io_is_busy = DEFAULT_IO_IS_BUSY; + ignore_nice = DEFAULT_IGNORE_NICE; + touch_poke_freq = DEFAULT_TOUCH_POKE_FREQ; + boost_freq = DEFAULT_BOOST_FREQ; + + /* Initalize per-cpu data: */for_each_possible_cpu(i) + { + this_smartmax = &per_cpu(smartmax_info, i); + this_smartmax->enable = false; + this_smartmax->cur_policy = 0; + this_smartmax->ramp_dir = 0; + this_smartmax->freq_change_time = 0; + this_smartmax->cur_cpu_load = 0; + } + +#ifdef CONFIG_HAS_EARLYSUSPEND + smartmax_early_suspend_handler.suspend = smartmax_early_suspend; + smartmax_early_suspend_handler.resume = smartmax_late_resume; + smartmax_early_suspend_handler.level = EARLY_SUSPEND_LEVEL_DISABLE_FB + 100; +#endif + + return cpufreq_register_governor(&cpufreq_gov_smartmax); +} + +#ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_SMARTMAX +fs_initcall(cpufreq_smartmax_init); +#else +module_init(cpufreq_smartmax_init); +#endif + +static void __exit cpufreq_smartmax_exit(void) { + cpufreq_unregister_governor(&cpufreq_gov_smartmax); +} + +module_exit(cpufreq_smartmax_exit); + +MODULE_AUTHOR("maxwen"); +MODULE_DESCRIPTION("'cpufreq_smartmax' - A smart cpufreq governor"); +MODULE_LICENSE("GPL"); diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 1903f2b5e5e..aba90056a2c 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -373,6 +373,9 @@ extern struct cpufreq_governor cpufreq_gov_userspace; #elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND) extern struct cpufreq_governor cpufreq_gov_ondemand; #define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_ondemand) +#elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_SMARTMAX) +extern struct cpufreq_governor cpufreq_gov_smartmax; +#define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_smartmax) #elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE) extern struct cpufreq_governor cpufreq_gov_conservative; #define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_conservative) From c87f8fd5aaf8e0a16c85613be5966e2fb17b46c9 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Thu, 19 Dec 2013 18:26:23 +0100 Subject: [PATCH 047/215] defconfig : get conservative back and enable smartmax --- arch/arm/configs/flo_defconfig | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/arm/configs/flo_defconfig b/arch/arm/configs/flo_defconfig index 04b2fb396fe..5494f0395b9 100644 --- a/arch/arm/configs/flo_defconfig +++ b/arch/arm/configs/flo_defconfig @@ -730,12 +730,16 @@ CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y # CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set # CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE is not set # CONFIG_CPU_FREQ_DEFAULT_GOV_INTELLIDEMAND is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_SMARTMAX is not set CONFIG_CPU_FREQ_GOV_PERFORMANCE=y # CONFIG_CPU_FREQ_GOV_POWERSAVE is not set CONFIG_CPU_FREQ_GOV_USERSPACE=y CONFIG_CPU_FREQ_GOV_ONDEMAND=y CONFIG_CPU_FREQ_GOV_INTERACTIVE=y -# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set +CONFIG_CPU_FREQ_GOV_SMARTMAX=y +# CONFIG_CPU_FREQ_GOV_SMARTMAX_EPS is not set +CONFIG_CPU_FREQ_GOV_SMARTMAX_M7=y +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y CONFIG_CPU_FREQ_GOV_INTELLIDEMAND=y # CONFIG_CPUFREQ_ID_PERFLOCK is not set From 321de91c328e7f00c5eb031e3cdb5bed2b634926 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Thu, 19 Dec 2013 18:41:47 +0100 Subject: [PATCH 048/215] Aroma : Get the L2/bus OC out of the full install only as we need it on the partial install as well. --- .../META-INF/com/google/android/aroma-config | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/release/aroma/META-INF/com/google/android/aroma-config b/release/aroma/META-INF/com/google/android/aroma-config index 3d8b9d7c6b8..c3026389104 100755 --- a/release/aroma/META-INF/com/google/android/aroma-config +++ b/release/aroma/META-INF/com/google/android/aroma-config @@ -176,6 +176,16 @@ selectbox( endif; +selectbox( + "Select CPU optimization level","Overclocks L2 cache and bus bandwidth. If you experience instability, choose stock\n","@personalize","opt.prop", + "stock","(1.13GHz-4.26GBps)",0, + "improved","(1.19GHz-4.26GBps)",0, + "balanced","(1.22GHz-4.66GBps)",1, + "fast","(1.35GHz-4.66GBps)",0, + "extreme","(1.43GHz-4.80GBps)",0, + "glitchy","(1.49GHz-4.96GBps)",0 +); + selectbox( "Auto Undervolting","Lowers the voltage for the lowest cpu frequency. Undervolting may cause instability.\n","@personalize","uv.prop", "Stock (no undervolt)","",1, @@ -205,16 +215,6 @@ selectbox( "810MHz","",0 ); -selectbox( - "Select CPU optimization level","Overclocks L2 cache and bus bandwidth. If you experience instability, choose stock\n","@personalize","opt.prop", - "stock","(1.13GHz-4.26GBps)",0, - "improved","(1.19GHz-4.26GBps)",0, - "balanced","(1.22GHz-4.66GBps)",1, - "fast","(1.35GHz-4.66GBps)",0, - "extreme","(1.43GHz-4.80GBps)",0, - "glitchy","(1.49GHz-4.96GBps)",0 -); - selectbox( "Hotplug driver","Select default hotplug driver to use\n","@personalize","hotplug.prop", "Qualcomm mpdecision","(stock)",0, From 3f691a1d9369233d432148f9293cc1f3780dbbe9 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Fri, 20 Dec 2013 19:25:19 +0100 Subject: [PATCH 049/215] tick: Dynamically set broadcast irq affinity When a cpu goes to a deep idle state where its local timer is shutdown, it notifies the time frame work to use the broadcast timer instead. Unfortunately, the broadcast device could wake up any CPU, including an idle one which is not concerned by the wake up at all. So in the worst case an idle CPU will wake up to send an IPI to the CPU whose timer expired. Provide an opt-in feature CLOCK_EVT_FEAT_DYNIRQ which tells the core that is should set the interrupt affinity of the broadcast interrupt to the cpu which has the earliest expiry time. This avoids unnecessary spurious wakeups and IPIs. [ tglx: Adopted to cpumask rework, silenced an uninitialized warning, massaged changelog ] Signed-off-by: Daniel Lezcano Cc: viresh.kumar@linaro.org Cc: jacob.jun.pan@linux.intel.com Cc: linux-arm-kernel@lists.infradead.org Cc: santosh.shilimkar@ti.com Cc: linaro-kernel@lists.linaro.org Cc: patches@linaro.org Cc: rickard.andersson@stericsson.com Cc: vincent.guittot@linaro.org Cc: linus.walleij@stericsson.com Cc: john.stultz@linaro.org Link: http://lkml.kernel.org/r/1362219013-18173-3-git-send-email-daniel.lezcano@linaro.org Signed-off-by: Thomas Gleixner Change-Id: I6a880a39dd595526b80a6d72b88be74163513da9 Signed-off-by: Karthik Parsha Signed-off-by: Mahesh Sivasubramanian Signed-off-by: franciscofranco --- include/linux/clockchips.h | 5 +++++ include/linux/tick.h | 1 + kernel/time/tick-broadcast.c | 40 ++++++++++++++++++++++++++++-------- 3 files changed, 37 insertions(+), 9 deletions(-) diff --git a/include/linux/clockchips.h b/include/linux/clockchips.h index 81e803e90aa..20b84465a09 100644 --- a/include/linux/clockchips.h +++ b/include/linux/clockchips.h @@ -55,6 +55,11 @@ enum clock_event_nofitiers { #define CLOCK_EVT_FEAT_C3STOP 0x000008 #define CLOCK_EVT_FEAT_DUMMY 0x000010 +/* + * Core shall set the interrupt affinity dynamically in broadcast mode + */ +#define CLOCK_EVT_FEAT_DYNIRQ 0x000020 + /** * struct clock_event_device - clock event device descriptor * @event_handler: Assigned by the framework to be called by the low diff --git a/include/linux/tick.h b/include/linux/tick.h index 94759671062..6792eb51891 100644 --- a/include/linux/tick.h +++ b/include/linux/tick.h @@ -8,6 +8,7 @@ #include #include +#include #ifdef CONFIG_GENERIC_CLOCKEVENTS diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c index f113755695e..d6d0d4127d7 100644 --- a/kernel/time/tick-broadcast.c +++ b/kernel/time/tick-broadcast.c @@ -370,14 +370,34 @@ struct cpumask *tick_get_broadcast_oneshot_mask(void) return to_cpumask(tick_broadcast_oneshot_mask); } -static int tick_broadcast_set_event(ktime_t expires, int force) +/* + * Set broadcast interrupt affinity + */ +static void tick_broadcast_set_affinity(struct clock_event_device *bc, + const struct cpumask *cpumask) { - struct clock_event_device *bc = tick_broadcast_device.evtdev; + if (!(bc->features & CLOCK_EVT_FEAT_DYNIRQ)) + return; + + if (cpumask_equal(bc->cpumask, cpumask)) + return; + + bc->cpumask = cpumask; + irq_set_affinity(bc->irq, bc->cpumask); +} + +static int tick_broadcast_set_event(struct clock_event_device *bc, int cpu, + ktime_t expires, int force) +{ + int ret; if (bc->mode != CLOCK_EVT_MODE_ONESHOT) clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT); - return clockevents_program_event(bc, expires, force); + ret = clockevents_program_event(bc, expires, force); + if (!ret) + tick_broadcast_set_affinity(bc, cpumask_of(cpu)); + return ret; } int tick_resume_broadcast_oneshot(struct clock_event_device *bc) @@ -406,7 +426,7 @@ static void tick_handle_oneshot_broadcast(struct clock_event_device *dev) { struct tick_device *td; ktime_t now, next_event; - int cpu; + int cpu, next_cpu = 0; raw_spin_lock(&tick_broadcast_lock); again: @@ -417,10 +437,12 @@ static void tick_handle_oneshot_broadcast(struct clock_event_device *dev) /* Find all expired events */ for_each_cpu(cpu, tick_get_broadcast_oneshot_mask()) { td = &per_cpu(tick_cpu_device, cpu); - if (td->evtdev->next_event.tv64 <= now.tv64) + if (td->evtdev->next_event.tv64 <= now.tv64) { cpumask_set_cpu(cpu, to_cpumask(tmpmask)); - else if (td->evtdev->next_event.tv64 < next_event.tv64) + } else if (td->evtdev->next_event.tv64 < next_event.tv64) { next_event.tv64 = td->evtdev->next_event.tv64; + next_cpu = cpu; + } } /* @@ -443,7 +465,7 @@ static void tick_handle_oneshot_broadcast(struct clock_event_device *dev) * Rearm the broadcast device. If event expired, * repeat the above */ - if (tick_broadcast_set_event(next_event, 0)) + if (tick_broadcast_set_event(dev, next_cpu, next_event, 0)) goto again; } raw_spin_unlock(&tick_broadcast_lock); @@ -486,7 +508,7 @@ void tick_broadcast_oneshot_control(unsigned long reason) cpumask_set_cpu(cpu, tick_get_broadcast_oneshot_mask()); clockevents_set_mode(dev, CLOCK_EVT_MODE_SHUTDOWN); if (dev->next_event.tv64 < bc->next_event.tv64) - tick_broadcast_set_event(dev->next_event, 1); + tick_broadcast_set_event(bc, cpu, dev->next_event, 1); } } else { if (cpumask_test_cpu(cpu, tick_get_broadcast_oneshot_mask())) { @@ -555,7 +577,7 @@ void tick_broadcast_setup_oneshot(struct clock_event_device *bc) clockevents_set_mode(bc, CLOCK_EVT_MODE_ONESHOT); tick_broadcast_init_next_event(to_cpumask(tmpmask), tick_next_period); - tick_broadcast_set_event(tick_next_period, 1); + tick_broadcast_set_event(bc, cpu, tick_next_period, 1); } else bc->next_event.tv64 = KTIME_MAX; } else { From 0777d5ae3a6874a4adc1911e3204be243f0a8bd4 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Fri, 20 Dec 2013 19:26:42 +0100 Subject: [PATCH 050/215] cpuidle: make a single register function for all The usual scheme to initialize a cpuidle driver on a SMP is: cpuidle_register_driver(drv); for_each_possible_cpu(cpu) { device = &per_cpu(cpuidle_dev, cpu); cpuidle_register_device(device); } This code is duplicated in each cpuidle driver. On UP systems, it is done this way: cpuidle_register_driver(drv); device = &per_cpu(cpuidle_dev, cpu); cpuidle_register_device(device); On UP, the macro 'for_each_cpu' does one iteration: for ((cpu) = 0; (cpu) < 1; (cpu)++, (void)mask) Hence, the initialization loop is the same for UP than SMP. Beside, we saw different bugs / mis-initialization / return code unchecked in the different drivers, the code is duplicated including bugs. After fixing all these ones, it appears the initialization pattern is the same for everyone. Please note, some drivers are doing dev->state_count = drv->state_count. This is not necessary because it is done by the cpuidle_enable_device function in the cpuidle framework. This is true, until you have the same states for all your devices. Otherwise, the 'low level' API should be used instead with the specific initialization for the driver. Let's add a wrapper function doing this initialization with a cpumask parameter for the coupled idle states and use it for all the drivers. That will save a lot of LOC, consolidate the code, and the modifications in the future could be done in a single place. Another benefit is the consolidation of the cpuidle_device variable which is now in the cpuidle framework and no longer spread accross the different arch specific drivers. Change-Id: I8f75188d5770871620f758c2973b74384ac570d5 Signed-off-by: Daniel Lezcano Signed-off-by: Rafael J. Wysocki Signed-off-by: Karthik Parsha Signed-off-by: Mahesh Sivasubramanian Signed-off-by: franciscofranco --- Documentation/cpuidle/driver.txt | 6 +++ drivers/cpuidle/cpuidle.c | 72 ++++++++++++++++++++++++++++++++ include/linux/cpuidle.h | 9 +++- 3 files changed, 85 insertions(+), 2 deletions(-) diff --git a/Documentation/cpuidle/driver.txt b/Documentation/cpuidle/driver.txt index 7a9e09ece93..1b0d81d9258 100644 --- a/Documentation/cpuidle/driver.txt +++ b/Documentation/cpuidle/driver.txt @@ -15,11 +15,17 @@ has mechanisms in place to support actual entry-exit into CPU idle states. cpuidle driver initializes the cpuidle_device structure for each CPU device and registers with cpuidle using cpuidle_register_device. +If all the idle states are the same, the wrapper function cpuidle_register +could be used instead. + It can also support the dynamic changes (like battery <-> AC), by using cpuidle_pause_and_lock, cpuidle_disable_device and cpuidle_enable_device, cpuidle_resume_and_unlock. Interfaces: +extern int cpuidle_register(struct cpuidle_driver *drv, + const struct cpumask *const coupled_cpus); +extern int cpuidle_unregister(struct cpuidle_driver *drv); extern int cpuidle_register_driver(struct cpuidle_driver *drv); extern void cpuidle_unregister_driver(struct cpuidle_driver *drv); extern int cpuidle_register_device(struct cpuidle_device *dev); diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 8d5d5a95f2e..cf60f482d23 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -23,6 +23,7 @@ #include "cpuidle.h" DEFINE_PER_CPU(struct cpuidle_device *, cpuidle_devices); +DEFINE_PER_CPU(struct cpuidle_device, cpuidle_dev); DEFINE_MUTEX(cpuidle_lock); LIST_HEAD(cpuidle_detected_devices); @@ -440,6 +441,77 @@ void cpuidle_unregister_device(struct cpuidle_device *dev) EXPORT_SYMBOL_GPL(cpuidle_unregister_device); +/* + * cpuidle_unregister: unregister a driver and the devices. This function + * can be used only if the driver has been previously registered through + * the cpuidle_register function. + * + * @drv: a valid pointer to a struct cpuidle_driver + */ +void cpuidle_unregister(struct cpuidle_driver *drv) +{ + int cpu; + struct cpuidle_device *device; + + for_each_possible_cpu(cpu) { + device = &per_cpu(cpuidle_dev, cpu); + cpuidle_unregister_device(device); + } + + cpuidle_unregister_driver(drv); +} +EXPORT_SYMBOL_GPL(cpuidle_unregister); + +/** + * cpuidle_register: registers the driver and the cpu devices with the + * coupled_cpus passed as parameter. This function is used for all common + * initialization pattern there are in the arch specific drivers. The + * devices is globally defined in this file. + * + * @drv : a valid pointer to a struct cpuidle_driver + * @coupled_cpus: a cpumask for the coupled states + * + * Returns 0 on success, < 0 otherwise + */ +int cpuidle_register(struct cpuidle_driver *drv, + const struct cpumask *const coupled_cpus) +{ + int ret, cpu; + struct cpuidle_device *device; + + ret = cpuidle_register_driver(drv); + if (ret) { + pr_err("failed to register cpuidle driver\n"); + return ret; + } + + for_each_possible_cpu(cpu) { + device = &per_cpu(cpuidle_dev, cpu); + device->cpu = cpu; + +#ifdef CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED + /* + * On multiplatform for ARM, the coupled idle states could + * enabled in the kernel even if the cpuidle driver does not + * use it. Note, coupled_cpus is a struct copy. + */ + if (coupled_cpus) + device->coupled_cpus = *coupled_cpus; +#endif + ret = cpuidle_register_device(device); + if (!ret) + continue; + + pr_err("Failed to register cpuidle device for cpu%d\n", cpu); + + cpuidle_unregister(drv); + break; + } + + return ret; +} +EXPORT_SYMBOL_GPL(cpuidle_register); + #ifdef CONFIG_SMP static void smp_callback(void *v) diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index fa7d3dcd36f..9feeddf9179 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h @@ -140,7 +140,9 @@ struct cpuidle_driver *cpuidle_get_driver(void); extern void cpuidle_unregister_driver(struct cpuidle_driver *drv); extern int cpuidle_register_device(struct cpuidle_device *dev); extern void cpuidle_unregister_device(struct cpuidle_device *dev); - +extern int cpuidle_register(struct cpuidle_driver *drv, + const struct cpumask *const coupled_cpus); +extern void cpuidle_unregister(struct cpuidle_driver *drv); extern void cpuidle_pause_and_lock(void); extern void cpuidle_resume_and_unlock(void); extern int cpuidle_enable_device(struct cpuidle_device *dev); @@ -161,7 +163,10 @@ static inline void cpuidle_unregister_driver(struct cpuidle_driver *drv) { } static inline int cpuidle_register_device(struct cpuidle_device *dev) {return -ENODEV; } static inline void cpuidle_unregister_device(struct cpuidle_device *dev) { } - +static inline int cpuidle_register(struct cpuidle_driver *drv, + const struct cpumask *const coupled_cpus) +{return -ENODEV; } +static inline void cpuidle_unregister(struct cpuidle_driver *drv) { } static inline void cpuidle_pause_and_lock(void) { } static inline void cpuidle_resume_and_unlock(void) { } static inline int cpuidle_enable_device(struct cpuidle_device *dev) From fce310298c4ab5e1b47aca11aa4dd095654e509c Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Fri, 20 Dec 2013 19:27:34 +0100 Subject: [PATCH 051/215] kthread: squash https://github.com/torvalds/linux/commit/9a2e03d8ed518a61154f18d83d6466628e519f94 and https://github.com/torvalds/linux/commit/46f3d976213452350f9d10b0c2780c2681f7075b Signed-off-by: franciscofranco --- include/linux/kthread.h | 8 +--- kernel/kthread.c | 88 ++++++++++++++++++++++++----------------- 2 files changed, 54 insertions(+), 42 deletions(-) diff --git a/include/linux/kthread.h b/include/linux/kthread.h index 0714b24c0e4..22ccf9dee17 100644 --- a/include/linux/kthread.h +++ b/include/linux/kthread.h @@ -49,8 +49,6 @@ extern int tsk_fork_get_node(struct task_struct *tsk); * can be queued and flushed using queue/flush_kthread_work() * respectively. Queued kthread_works are processed by a kthread * running kthread_worker_fn(). - * - * A kthread_work can't be freed while it is executing. */ struct kthread_work; typedef void (*kthread_work_func_t)(struct kthread_work *work); @@ -59,15 +57,14 @@ struct kthread_worker { spinlock_t lock; struct list_head work_list; struct task_struct *task; + struct kthread_work *current_work; }; struct kthread_work { struct list_head node; kthread_work_func_t func; wait_queue_head_t done; - atomic_t flushing; - int queue_seq; - int done_seq; + struct kthread_worker *worker; }; #define KTHREAD_WORKER_INIT(worker) { \ @@ -79,7 +76,6 @@ struct kthread_work { .node = LIST_HEAD_INIT((work).node), \ .func = (fn), \ .done = __WAIT_QUEUE_HEAD_INITIALIZER((work).done), \ - .flushing = ATOMIC_INIT(0), \ } #define DEFINE_KTHREAD_WORKER(worker) \ diff --git a/kernel/kthread.c b/kernel/kthread.c index 3d3de633702..b579af57ea1 100644 --- a/kernel/kthread.c +++ b/kernel/kthread.c @@ -360,16 +360,12 @@ int kthread_worker_fn(void *worker_ptr) struct kthread_work, node); list_del_init(&work->node); } + worker->current_work = work; spin_unlock_irq(&worker->lock); if (work) { __set_current_state(TASK_RUNNING); work->func(work); - smp_wmb(); /* wmb worker-b0 paired with flush-b1 */ - work->done_seq = work->queue_seq; - smp_mb(); /* mb worker-b1 paired with flush-b0 */ - if (atomic_read(&work->flushing)) - wake_up_all(&work->done); } else if (!freezing(current)) schedule(); @@ -378,6 +374,19 @@ int kthread_worker_fn(void *worker_ptr) } EXPORT_SYMBOL_GPL(kthread_worker_fn); +/* insert @work before @pos in @worker */ +static void insert_kthread_work(struct kthread_worker *worker, + struct kthread_work *work, + struct list_head *pos) +{ + lockdep_assert_held(&worker->lock); + + list_add_tail(&work->node, pos); + work->worker = worker; + if (likely(worker->task)) + wake_up_process(worker->task); +} + /** * queue_kthread_work - queue a kthread_work * @worker: target kthread_worker @@ -395,10 +404,7 @@ bool queue_kthread_work(struct kthread_worker *worker, spin_lock_irqsave(&worker->lock, flags); if (list_empty(&work->node)) { - list_add_tail(&work->node, &worker->work_list); - work->queue_seq++; - if (likely(worker->task)) - wake_up_process(worker->task); + insert_kthread_work(worker, work, &worker->work_list); ret = true; } spin_unlock_irqrestore(&worker->lock, flags); @@ -406,6 +412,18 @@ bool queue_kthread_work(struct kthread_worker *worker, } EXPORT_SYMBOL_GPL(queue_kthread_work); +struct kthread_flush_work { + struct kthread_work work; + struct completion done; +}; + +static void kthread_flush_work_fn(struct kthread_work *work) +{ + struct kthread_flush_work *fwork = + container_of(work, struct kthread_flush_work, work); + complete(&fwork->done); +} + /** * flush_kthread_work - flush a kthread_work * @work: work to flush @@ -414,39 +432,37 @@ EXPORT_SYMBOL_GPL(queue_kthread_work); */ void flush_kthread_work(struct kthread_work *work) { - int seq = work->queue_seq; - - atomic_inc(&work->flushing); + struct kthread_flush_work fwork = { + KTHREAD_WORK_INIT(fwork.work, kthread_flush_work_fn), + COMPLETION_INITIALIZER_ONSTACK(fwork.done), + }; + struct kthread_worker *worker; + bool noop = false; - /* - * mb flush-b0 paired with worker-b1, to make sure either - * worker sees the above increment or we see done_seq update. - */ - smp_mb__after_atomic_inc(); +retry: + worker = work->worker; + if (!worker) + return; - /* A - B <= 0 tests whether B is in front of A regardless of overflow */ - wait_event(work->done, seq - work->done_seq <= 0); - atomic_dec(&work->flushing); + spin_lock_irq(&worker->lock); + if (work->worker != worker) { + spin_unlock_irq(&worker->lock); + goto retry; + } - /* - * rmb flush-b1 paired with worker-b0, to make sure our caller - * sees every change made by work->func(). - */ - smp_mb__after_atomic_dec(); -} -EXPORT_SYMBOL_GPL(flush_kthread_work); + if (!list_empty(&work->node)) + insert_kthread_work(worker, &fwork.work, work->node.next); + else if (worker->current_work == work) + insert_kthread_work(worker, &fwork.work, worker->work_list.next); + else + noop = true; -struct kthread_flush_work { - struct kthread_work work; - struct completion done; -}; + spin_unlock_irq(&worker->lock); -static void kthread_flush_work_fn(struct kthread_work *work) -{ - struct kthread_flush_work *fwork = - container_of(work, struct kthread_flush_work, work); - complete(&fwork->done); + if (!noop) + wait_for_completion(&fwork.done); } +EXPORT_SYMBOL_GPL(flush_kthread_work); /** * flush_kthread_worker - flush all current works on a kthread_worker From b3ceb521d6291e0747a3add14033263ea8270edd Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Fri, 20 Dec 2013 19:28:32 +0100 Subject: [PATCH 052/215] kthread: Implement park/unpark facility To avoid the full teardown/setup of per cpu kthreads in the case of cpu hot(un)plug, provide a facility which allows to put the kthread into a park position and unpark it when the cpu comes online again. Signed-off-by: Thomas Gleixner Reviewed-by: Namhyung Kim Cc: Peter Zijlstra Reviewed-by: Srivatsa S. Bhat Cc: Rusty Russell Reviewed-by: Paul E. McKenney Link: http://lkml.kernel.org/r/20120716103948.236618824@linutronix.de Signed-off-by: Thomas Gleixner Signed-off-by: franciscofranco --- include/linux/kthread.h | 11 ++- kernel/kthread.c | 185 +++++++++++++++++++++++++++++++++++----- 2 files changed, 176 insertions(+), 20 deletions(-) diff --git a/include/linux/kthread.h b/include/linux/kthread.h index 22ccf9dee17..8d816646f76 100644 --- a/include/linux/kthread.h +++ b/include/linux/kthread.h @@ -14,6 +14,11 @@ struct task_struct *kthread_create_on_node(int (*threadfn)(void *data), kthread_create_on_node(threadfn, data, -1, namefmt, ##arg) +struct task_struct *kthread_create_on_cpu(int (*threadfn)(void *data), + void *data, + unsigned int cpu, + const char *namefmt); + /** * kthread_run - create and wake a thread. * @threadfn: the function to run until signal_pending(current). @@ -34,9 +39,13 @@ struct task_struct *kthread_create_on_node(int (*threadfn)(void *data), void kthread_bind(struct task_struct *k, unsigned int cpu); int kthread_stop(struct task_struct *k); -int kthread_should_stop(void); +bool kthread_should_stop(void); +bool kthread_should_park(void); bool kthread_freezable_should_stop(bool *was_frozen); void *kthread_data(struct task_struct *k); +int kthread_park(struct task_struct *k); +void kthread_unpark(struct task_struct *k); +void kthread_parkme(void); int kthreadd(void *unused); extern struct task_struct *kthreadd_task; diff --git a/kernel/kthread.c b/kernel/kthread.c index b579af57ea1..146a6fa9682 100644 --- a/kernel/kthread.c +++ b/kernel/kthread.c @@ -37,11 +37,20 @@ struct kthread_create_info }; struct kthread { - int should_stop; + unsigned long flags; + unsigned int cpu; void *data; + struct completion parked; struct completion exited; }; +enum KTHREAD_BITS { + KTHREAD_IS_PER_CPU = 0, + KTHREAD_SHOULD_STOP, + KTHREAD_SHOULD_PARK, + KTHREAD_IS_PARKED, +}; + #define to_kthread(tsk) \ container_of((tsk)->vfork_done, struct kthread, exited) @@ -52,12 +61,28 @@ struct kthread { * and this will return true. You should then return, and your return * value will be passed through to kthread_stop(). */ -int kthread_should_stop(void) +bool kthread_should_stop(void) { - return to_kthread(current)->should_stop; + return test_bit(KTHREAD_SHOULD_STOP, &to_kthread(current)->flags); } EXPORT_SYMBOL(kthread_should_stop); +/** + * kthread_should_park - should this kthread park now? + * + * When someone calls kthread_park() on your kthread, it will be woken + * and this will return true. You should then do the necessary + * cleanup and call kthread_parkme() + * + * Similar to kthread_should_stop(), but this keeps the thread alive + * and in a park position. kthread_unpark() "restarts" the thread and + * calls the thread function again. + */ +bool kthread_should_park(void) +{ + return test_bit(KTHREAD_SHOULD_PARK, &to_kthread(current)->flags); +} + /** * kthread_freezable_should_stop - should this freezable kthread return now? * @was_frozen: optional out parameter, indicates whether %current was frozen @@ -96,6 +121,24 @@ void *kthread_data(struct task_struct *task) return to_kthread(task)->data; } +static void __kthread_parkme(struct kthread *self) +{ + __set_current_state(TASK_INTERRUPTIBLE); + while (test_bit(KTHREAD_SHOULD_PARK, &self->flags)) { + if (!test_and_set_bit(KTHREAD_IS_PARKED, &self->flags)) + complete(&self->parked); + schedule(); + __set_current_state(TASK_INTERRUPTIBLE); + } + clear_bit(KTHREAD_IS_PARKED, &self->flags); + __set_current_state(TASK_RUNNING); +} + +void kthread_parkme(void) +{ + __kthread_parkme(to_kthread(current)); +} + static int kthread(void *_create) { /* Copy data: it's on kthread's stack */ @@ -105,9 +148,10 @@ static int kthread(void *_create) struct kthread self; int ret; - self.should_stop = 0; + self.flags = 0; self.data = data; init_completion(&self.exited); + init_completion(&self.parked); current->vfork_done = &self.exited; /* OK, tell user we're spawned, wait for stop or wakeup */ @@ -117,9 +161,11 @@ static int kthread(void *_create) schedule(); ret = -EINTR; - if (!self.should_stop) - ret = threadfn(data); + if (!test_bit(KTHREAD_SHOULD_STOP, &self.flags)) { + __kthread_parkme(&self); + ret = threadfn(data); + } /* we can't just return, we must preserve "self" on stack */ do_exit(ret); } @@ -172,8 +218,7 @@ static void create_kthread(struct kthread_create_info *create) * Returns a task_struct or ERR_PTR(-ENOMEM). */ struct task_struct *kthread_create_on_node(int (*threadfn)(void *data), - void *data, - int node, + void *data, int node, const char namefmt[], ...) { @@ -210,6 +255,13 @@ struct task_struct *kthread_create_on_node(int (*threadfn)(void *data), } EXPORT_SYMBOL(kthread_create_on_node); +static void __kthread_bind(struct task_struct *p, unsigned int cpu) +{ + /* It's safe because the task is inactive. */ + do_set_cpus_allowed(p, cpumask_of(cpu)); + p->flags |= PF_THREAD_BOUND; +} + /** * kthread_bind - bind a just-created kthread to a cpu. * @p: thread created by kthread_create(). @@ -226,13 +278,111 @@ void kthread_bind(struct task_struct *p, unsigned int cpu) WARN_ON(1); return; } - - /* It's safe because the task is inactive. */ - do_set_cpus_allowed(p, cpumask_of(cpu)); - p->flags |= PF_THREAD_BOUND; + __kthread_bind(p, cpu); } EXPORT_SYMBOL(kthread_bind); +/** + * kthread_create_on_cpu - Create a cpu bound kthread + * @threadfn: the function to run until signal_pending(current). + * @data: data ptr for @threadfn. + * @cpu: The cpu on which the thread should be bound, + * @namefmt: printf-style name for the thread. Format is restricted + * to "name.*%u". Code fills in cpu number. + * + * Description: This helper function creates and names a kernel thread + * The thread will be woken and put into park mode. + */ +struct task_struct *kthread_create_on_cpu(int (*threadfn)(void *data), + void *data, unsigned int cpu, + const char *namefmt) +{ + struct task_struct *p; + + p = kthread_create_on_node(threadfn, data, cpu_to_node(cpu), namefmt, + cpu); + if (IS_ERR(p)) + return p; + set_bit(KTHREAD_IS_PER_CPU, &to_kthread(p)->flags); + to_kthread(p)->cpu = cpu; + /* Park the thread to get it out of TASK_UNINTERRUPTIBLE state */ + kthread_park(p); + return p; +} + +static struct kthread *task_get_live_kthread(struct task_struct *k) +{ + struct kthread *kthread; + + get_task_struct(k); + kthread = to_kthread(k); + /* It might have exited */ + barrier(); + if (k->vfork_done != NULL) + return kthread; + return NULL; +} + +/** + * kthread_unpark - unpark a thread created by kthread_create(). + * @k: thread created by kthread_create(). + * + * Sets kthread_should_park() for @k to return false, wakes it, and + * waits for it to return. If the thread is marked percpu then its + * bound to the cpu again. + */ +void kthread_unpark(struct task_struct *k) +{ + struct kthread *kthread = task_get_live_kthread(k); + + if (kthread) { + clear_bit(KTHREAD_SHOULD_PARK, &kthread->flags); + /* + * We clear the IS_PARKED bit here as we don't wait + * until the task has left the park code. So if we'd + * park before that happens we'd see the IS_PARKED bit + * which might be about to be cleared. + */ + if (test_and_clear_bit(KTHREAD_IS_PARKED, &kthread->flags)) { + if (test_bit(KTHREAD_IS_PER_CPU, &kthread->flags)) + __kthread_bind(k, kthread->cpu); + wake_up_process(k); + } + } + put_task_struct(k); +} + +/** + * kthread_park - park a thread created by kthread_create(). + * @k: thread created by kthread_create(). + * + * Sets kthread_should_park() for @k to return true, wakes it, and + * waits for it to return. This can also be called after kthread_create() + * instead of calling wake_up_process(): the thread will park without + * calling threadfn(). + * + * Returns 0 if the thread is parked, -ENOSYS if the thread exited. + * If called by the kthread itself just the park bit is set. + */ +int kthread_park(struct task_struct *k) +{ + struct kthread *kthread = task_get_live_kthread(k); + int ret = -ENOSYS; + + if (kthread) { + if (!test_bit(KTHREAD_IS_PARKED, &kthread->flags)) { + set_bit(KTHREAD_SHOULD_PARK, &kthread->flags); + if (k != current) { + wake_up_process(k); + wait_for_completion(&kthread->parked); + } + } + ret = 0; + } + put_task_struct(k); + return ret; +} + /** * kthread_stop - stop a thread created by kthread_create(). * @k: thread created by kthread_create(). @@ -250,16 +400,13 @@ EXPORT_SYMBOL(kthread_bind); */ int kthread_stop(struct task_struct *k) { - struct kthread *kthread; + struct kthread *kthread = task_get_live_kthread(k); int ret; trace_sched_kthread_stop(k); - get_task_struct(k); - - kthread = to_kthread(k); - barrier(); /* it might have exited */ - if (k->vfork_done != NULL) { - kthread->should_stop = 1; + if (kthread) { + set_bit(KTHREAD_SHOULD_STOP, &kthread->flags); + clear_bit(KTHREAD_SHOULD_PARK, &kthread->flags); wake_up_process(k); wait_for_completion(&kthread->exited); } From 946fded5cb106363750dfc36cbc62a2c2700aef6 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Fri, 20 Dec 2013 19:37:45 +0100 Subject: [PATCH 053/215] block: row: add magic values. Signed-off-by: franciscofranco --- block/row-iosched.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/block/row-iosched.c b/block/row-iosched.c index ad30e81499a..f08806246b2 100644 --- a/block/row-iosched.c +++ b/block/row-iosched.c @@ -86,18 +86,18 @@ struct row_queue_params { */ static const struct row_queue_params row_queues_def[] = { /* idling_enabled, quantum, is_urgent */ - {true, 10, true}, /* ROWQ_PRIO_HIGH_READ */ - {false, 1, false}, /* ROWQ_PRIO_HIGH_SWRITE */ - {true, 100, true}, /* ROWQ_PRIO_REG_READ */ - {false, 1, false}, /* ROWQ_PRIO_REG_SWRITE */ - {false, 1, false}, /* ROWQ_PRIO_REG_WRITE */ - {false, 1, false}, /* ROWQ_PRIO_LOW_READ */ - {false, 1, false} /* ROWQ_PRIO_LOW_SWRITE */ + {true, 100, true}, /* ROWQ_PRIO_HIGH_READ */ + {false, 5, false}, /* ROWQ_PRIO_HIGH_SWRITE */ + {true, 75, true}, /* ROWQ_PRIO_REG_READ */ + {false, 4, false}, /* ROWQ_PRIO_REG_SWRITE */ + {false, 4, false}, /* ROWQ_PRIO_REG_WRITE */ + {false, 3, false}, /* ROWQ_PRIO_LOW_READ */ + {false, 2, false} /* ROWQ_PRIO_LOW_SWRITE */ }; /* Default values for idling on read queues (in msec) */ -#define ROW_IDLE_TIME_MSEC 5 -#define ROW_READ_FREQ_MSEC 20 +#define ROW_IDLE_TIME_MSEC 10 +#define ROW_READ_FREQ_MSEC 25 /** * struct rowq_idling_data - parameters for idling on the queue From 58819f3e1625228df00ce24dd3855faad1d59f34 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Fri, 20 Dec 2013 21:04:30 +0100 Subject: [PATCH 054/215] smp: patches from mainline 3.5 to hopefully help with hotplug efficiency Thomas Gleixner's generic-idle patches: smp: Add task_struct argument to __cpu_up() Preparatory patch to make the idle thread allocation for secondary cpus generic. http://git.kernel.org/?p=linux/kernel/git/tip/tip.git;a=commit;h=8239c25f47d2b318156993b15f33900a86ea5e17 smp: Add generic smpboot facility Start a new file, which will hold SMP and CPU hotplug related generic infrastructure. http://git.kernel.org/?p=linux/kernel/git/tip/tip.git;a=commit;h=38498a67aa2cf8c80754b8d304bfacc10bc582b5 smp: Provide generic idle thread allocation All SMP architectures have magic to fork the idle task and to store it for reusage when cpu hotplug is enabled. Provide a generic infrastructure for it. Create/reinit the idle thread for the cpu which is brought up in the generic code and hand the thread pointer to the architecture code via __cpu_up(). Note, that fork_idle() is called via a workqueue, because this guarantees that the idle thread does not get a reference to a user space VM. This can happen when the boot process did not bring up all possible cpus and a later cpu_up() is initiated via the sysfs interface. In that case fork_idle() would be called in the context of the user space task and take a reference on the user space VM. http://git.kernel.org/?p=linux/kernel/git/tip/tip.git;a=commit;h=29d5e0476e1c4a513859e7858845ad172f560389 arm: Use generic idle thread allocation http://git.kernel.org/?p=linux/kernel/git/tip/tip.git;a=commit;h=84ec6d5796e095e2f8698bd2b5d33849ed26d9e2 Signed-off-by: Francisco Franco Signed-off-by: Tk-Glitch --- arch/Kconfig | 3 ++ arch/arm/Kconfig | 1 + arch/arm/include/asm/cpu.h | 1 - arch/arm/kernel/smp.c | 26 +---------- include/linux/smp.h | 2 +- kernel/Makefile | 1 + kernel/cpu.c | 10 +++- kernel/sched/core.c | 2 + kernel/smpboot.c | 96 ++++++++++++++++++++++++++++++++++++++ kernel/smpboot.h | 16 +++++++ 10 files changed, 130 insertions(+), 28 deletions(-) create mode 100644 kernel/smpboot.c create mode 100644 kernel/smpboot.h diff --git a/arch/Kconfig b/arch/Kconfig index 0d887601807..e77b8d27388 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -148,6 +148,9 @@ config HAVE_DMA_CONTIGUOUS config USE_GENERIC_SMP_HELPERS bool +config GENERIC_SMP_IDLE_THREAD + bool + config HAVE_REGS_AND_STACK_ACCESS_API bool help diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index e6ea0b1cf21..69b94144ee5 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -36,6 +36,7 @@ config ARM select CPU_PM if (SUSPEND || CPU_IDLE) select GENERIC_PCI_IOMAP select HAVE_BPF_JIT if NET + select GENERIC_SMP_IDLE_THREAD help The ARM series is a line of low-power-consumption RISC chip designs licensed by ARM Ltd and targeted at embedded applications and diff --git a/arch/arm/include/asm/cpu.h b/arch/arm/include/asm/cpu.h index 793968173be..d797223b39d 100644 --- a/arch/arm/include/asm/cpu.h +++ b/arch/arm/include/asm/cpu.h @@ -16,7 +16,6 @@ struct cpuinfo_arm { struct cpu cpu; #ifdef CONFIG_SMP - struct task_struct *idle; unsigned int loops_per_jiffy; #endif }; diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index f99d85d3921..528828109b8 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -63,31 +63,10 @@ enum ipi_msg_type { static DECLARE_COMPLETION(cpu_running); -int __cpu_up(unsigned int cpu) +int __cpu_up(unsigned int cpu, struct task_struct *idle) { - struct cpuinfo_arm *ci = &per_cpu(cpu_data, cpu); - struct task_struct *idle = ci->idle; int ret; - /* - * Spawn a new process manually, if not already done. - * Grab a pointer to its task struct so we can mess with it - */ - if (!idle) { - idle = fork_idle(cpu); - if (IS_ERR(idle)) { - printk(KERN_ERR "CPU%u: fork() failed\n", cpu); - return PTR_ERR(idle); - } - ci->idle = idle; - } else { - /* - * Since this idle thread is being re-used, call - * init_idle() to reinitialize the thread structure. - */ - init_idle(idle, cpu); - } - /* * We need to tell the secondary core where to find * its stack and the page tables. @@ -319,9 +298,6 @@ void __init smp_cpus_done(unsigned int max_cpus) void __init smp_prepare_boot_cpu(void) { - unsigned int cpu = smp_processor_id(); - - per_cpu(cpu_data, cpu).idle = current; } void __init smp_prepare_cpus(unsigned int max_cpus) diff --git a/include/linux/smp.h b/include/linux/smp.h index 10530d92c04..24360de6c96 100644 --- a/include/linux/smp.h +++ b/include/linux/smp.h @@ -61,7 +61,7 @@ extern void smp_prepare_cpus(unsigned int max_cpus); /* * Bring a CPU up */ -extern int __cpu_up(unsigned int cpunum); +extern int __cpu_up(unsigned int cpunum, struct task_struct *tidle); /* * Final polishing of CPUs diff --git a/kernel/Makefile b/kernel/Makefile index 446798f8f54..6e9096a473a 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -43,6 +43,7 @@ obj-$(CONFIG_DEBUG_RT_MUTEXES) += rtmutex-debug.o obj-$(CONFIG_RT_MUTEX_TESTER) += rtmutex-tester.o obj-$(CONFIG_GENERIC_ISA_DMA) += dma.o obj-$(CONFIG_SMP) += smp.o +obj-$(CONFIG_SMP) += smpboot.o ifneq ($(CONFIG_SMP),y) obj-y += up.o endif diff --git a/kernel/cpu.c b/kernel/cpu.c index 900f1856fa8..0ffe11b6eff 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -17,6 +17,8 @@ #include #include +#include "smpboot.h" + #ifdef CONFIG_SMP /* Serializes the updates to cpu_online_mask, cpu_present_mask */ static DEFINE_MUTEX(cpu_add_remove_lock); @@ -300,6 +302,11 @@ static int _cpu_up(unsigned int cpu, int tasks_frozen) return -EINVAL; cpu_hotplug_begin(); + + ret = smpboot_prepare(cpu); + if (ret) + goto out; + ret = __cpu_notify(CPU_UP_PREPARE | mod, hcpu, -1, &nr_calls); if (ret) { nr_calls--; @@ -309,7 +316,7 @@ static int _cpu_up(unsigned int cpu, int tasks_frozen) } /* Arch-specific enabling code. */ - ret = __cpu_up(cpu); + ret = __cpu_up(cpu, idle_thread_get(cpu)); if (ret != 0) goto out_notify; BUG_ON(!cpu_online(cpu)); @@ -320,6 +327,7 @@ static int _cpu_up(unsigned int cpu, int tasks_frozen) out_notify: if (ret != 0) __cpu_notify(CPU_UP_CANCELED | mod, hcpu, nr_calls, NULL); +out: cpu_hotplug_done(); return ret; diff --git a/kernel/sched/core.c b/kernel/sched/core.c index b943d44b425..aa1324d7a3a 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -83,6 +83,7 @@ #include "sched.h" #include "../workqueue_sched.h" +#include "../smpboot.h" #define CREATE_TRACE_POINTS #include @@ -7139,6 +7140,7 @@ void __init sched_init(void) /* May be allocated at isolcpus cmdline parse time */ if (cpu_isolated_map == NULL) zalloc_cpumask_var(&cpu_isolated_map, GFP_NOWAIT); + idle_thread_set_boot_cpu(); #endif init_sched_fair_class(); diff --git a/kernel/smpboot.c b/kernel/smpboot.c new file mode 100644 index 00000000000..ed157698180 --- /dev/null +++ b/kernel/smpboot.c @@ -0,0 +1,96 @@ +/* + * Common SMP CPU bringup/teardown functions + */ +#include +#include +#include +#include +#include +#include + +#include "smpboot.h" + +#ifdef CONFIG_GENERIC_SMP_IDLE_THREAD +struct create_idle { + struct work_struct work; + struct task_struct *idle; + struct completion done; + unsigned int cpu; +}; + +static void __cpuinit do_fork_idle(struct work_struct *work) +{ + struct create_idle *c = container_of(work, struct create_idle, work); + + c->idle = fork_idle(c->cpu); + complete(&c->done); +} + +static struct task_struct * __cpuinit idle_thread_create(unsigned int cpu) +{ + struct create_idle c_idle = { + .cpu = cpu, + .done = COMPLETION_INITIALIZER_ONSTACK(c_idle.done), + }; + + INIT_WORK_ONSTACK(&c_idle.work, do_fork_idle); + schedule_work(&c_idle.work); + wait_for_completion(&c_idle.done); + destroy_work_on_stack(&c_idle.work); + return c_idle.idle; +} + +/* + * For the hotplug case we keep the task structs around and reuse + * them. + */ +static DEFINE_PER_CPU(struct task_struct *, idle_threads); + +static inline struct task_struct *get_idle_for_cpu(unsigned int cpu) +{ + struct task_struct *tsk = per_cpu(idle_threads, cpu); + + if (!tsk) + return idle_thread_create(cpu); + init_idle(tsk, cpu); + return tsk; +} + +struct task_struct * __cpuinit idle_thread_get(unsigned int cpu) +{ + return per_cpu(idle_threads, cpu); +} + +void __init idle_thread_set_boot_cpu(void) +{ + per_cpu(idle_threads, smp_processor_id()) = current; +} + +/** + * idle_thread_init - Initialize the idle thread for a cpu + * @cpu: The cpu for which the idle thread should be initialized + * + * Creates the thread if it does not exist. + */ +static int __cpuinit idle_thread_init(unsigned int cpu) +{ + struct task_struct *idle = get_idle_for_cpu(cpu); + + if (IS_ERR(idle)) { + printk(KERN_ERR "failed fork for CPU %u\n", cpu); + return PTR_ERR(idle); + } + per_cpu(idle_threads, cpu) = idle; + return 0; +} +#else +static inline int idle_thread_init(unsigned int cpu) { return 0; } +#endif + +/** + * smpboot_prepare - generic smpboot preparation + */ +int __cpuinit smpboot_prepare(unsigned int cpu) +{ + return idle_thread_init(cpu); +} diff --git a/kernel/smpboot.h b/kernel/smpboot.h new file mode 100644 index 00000000000..4d5b3e2741f --- /dev/null +++ b/kernel/smpboot.h @@ -0,0 +1,16 @@ +#ifndef SMPBOOT_H +#define SMPBOOT_H + +struct task_struct; + +int smpboot_prepare(unsigned int cpu); + +#ifdef CONFIG_GENERIC_SMP_IDLE_THREAD +struct task_struct *idle_thread_get(unsigned int cpu); +void idle_thread_set_boot_cpu(void); +#else +static inline struct task_struct *idle_thread_get(unsigned int cpu) { return NULL; } +static inline void idle_thread_set_boot_cpu(void) { } +#endif + +#endif \ No newline at end of file From 275eabd2d8d57e23d0abf2804b5a114ae577dfd6 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Fri, 20 Dec 2013 21:05:26 +0100 Subject: [PATCH 055/215] smp, idle: Allocate idle thread for each possible cpu during boot percpu areas are already allocated during boot for each possible cpu. percpu idle threads can be considered as an extension of the percpu areas, and allocate them for each possible cpu during boot. This will eliminate the need for workqueue based idle thread allocation. In future we can move the idle thread area into the percpu area too. [ tglx: Moved the loop into smpboot.c and added an error check when the init code failed to allocate an idle thread for a cpu which should be onlined ] Signed-off-by: Suresh Siddha Cc: Peter Zijlstra Cc: Rusty Russell Cc: Paul E. McKenney Cc: Srivatsa S. Bhat Cc: Tejun Heo Cc: David Rientjes Cc: venki@google.com Link: http://lkml.kernel.org/r/1334966930.28674.245.camel@sbsiddha-desk.sc.intel.com Signed-off-by: Thomas Gleixner Signed-off-by: franciscofranco --- kernel/cpu.c | 9 ++++-- kernel/smp.c | 4 +++ kernel/smpboot.c | 72 +++++++++++++----------------------------------- kernel/smpboot.h | 4 ++- 4 files changed, 32 insertions(+), 57 deletions(-) diff --git a/kernel/cpu.c b/kernel/cpu.c index 0ffe11b6eff..aeadfbfe744 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -297,15 +297,18 @@ static int _cpu_up(unsigned int cpu, int tasks_frozen) int ret, nr_calls = 0; void *hcpu = (void *)(long)cpu; unsigned long mod = tasks_frozen ? CPU_TASKS_FROZEN : 0; + struct task_struct *idle; if (cpu_online(cpu) || !cpu_present(cpu)) return -EINVAL; cpu_hotplug_begin(); - ret = smpboot_prepare(cpu); - if (ret) + idle = idle_thread_get(cpu); + if (IS_ERR(idle)) { + ret = PTR_ERR(idle); goto out; + } ret = __cpu_notify(CPU_UP_PREPARE | mod, hcpu, -1, &nr_calls); if (ret) { @@ -316,7 +319,7 @@ static int _cpu_up(unsigned int cpu, int tasks_frozen) } /* Arch-specific enabling code. */ - ret = __cpu_up(cpu, idle_thread_get(cpu)); + ret = __cpu_up(cpu, idle); if (ret != 0) goto out_notify; BUG_ON(!cpu_online(cpu)); diff --git a/kernel/smp.c b/kernel/smp.c index ecc3638dac6..da6b76e04e4 100644 --- a/kernel/smp.c +++ b/kernel/smp.c @@ -13,6 +13,8 @@ #include #include +#include "smpboot.h" + #ifdef CONFIG_USE_GENERIC_SMP_HELPERS static struct { struct list_head queue; @@ -669,6 +671,8 @@ void __init smp_init(void) { unsigned int cpu; + idle_threads_init(); + /* FIXME: This should be done in userspace --RR */ for_each_present_cpu(cpu) { if (num_online_cpus() >= setup_max_cpus) diff --git a/kernel/smpboot.c b/kernel/smpboot.c index ed157698180..e1a797e028a 100644 --- a/kernel/smpboot.c +++ b/kernel/smpboot.c @@ -6,64 +6,42 @@ #include #include #include -#include #include "smpboot.h" #ifdef CONFIG_GENERIC_SMP_IDLE_THREAD -struct create_idle { - struct work_struct work; - struct task_struct *idle; - struct completion done; - unsigned int cpu; -}; - -static void __cpuinit do_fork_idle(struct work_struct *work) -{ - struct create_idle *c = container_of(work, struct create_idle, work); - - c->idle = fork_idle(c->cpu); - complete(&c->done); -} - -static struct task_struct * __cpuinit idle_thread_create(unsigned int cpu) -{ - struct create_idle c_idle = { - .cpu = cpu, - .done = COMPLETION_INITIALIZER_ONSTACK(c_idle.done), - }; - - INIT_WORK_ONSTACK(&c_idle.work, do_fork_idle); - schedule_work(&c_idle.work); - wait_for_completion(&c_idle.done); - destroy_work_on_stack(&c_idle.work); - return c_idle.idle; -} - /* * For the hotplug case we keep the task structs around and reuse * them. */ static DEFINE_PER_CPU(struct task_struct *, idle_threads); -static inline struct task_struct *get_idle_for_cpu(unsigned int cpu) +struct task_struct * __cpuinit idle_thread_get(unsigned int cpu) { struct task_struct *tsk = per_cpu(idle_threads, cpu); if (!tsk) - return idle_thread_create(cpu); + return ERR_PTR(-ENOMEM); init_idle(tsk, cpu); return tsk; } -struct task_struct * __cpuinit idle_thread_get(unsigned int cpu) +void __init idle_thread_set_boot_cpu(void) { - return per_cpu(idle_threads, cpu); + per_cpu(idle_threads, smp_processor_id()) = current; } -void __init idle_thread_set_boot_cpu(void) +static inline void idle_init(unsigned int cpu) { - per_cpu(idle_threads, smp_processor_id()) = current; + struct task_struct *tsk = per_cpu(idle_threads, cpu); + + if (!tsk) { + tsk = fork_idle(cpu); + if (IS_ERR(tsk)) + pr_err("SMP: fork_idle() failed for CPU %u\n", cpu); + else + per_cpu(idle_threads, cpu) = tsk; + } } /** @@ -72,25 +50,13 @@ void __init idle_thread_set_boot_cpu(void) * * Creates the thread if it does not exist. */ -static int __cpuinit idle_thread_init(unsigned int cpu) +void __init idle_threads_init(void) { - struct task_struct *idle = get_idle_for_cpu(cpu); + unsigned int cpu; - if (IS_ERR(idle)) { - printk(KERN_ERR "failed fork for CPU %u\n", cpu); - return PTR_ERR(idle); + for_each_possible_cpu(cpu) { + if (cpu != smp_processor_id()) + idle_init(cpu); } - per_cpu(idle_threads, cpu) = idle; - return 0; } -#else -static inline int idle_thread_init(unsigned int cpu) { return 0; } #endif - -/** - * smpboot_prepare - generic smpboot preparation - */ -int __cpuinit smpboot_prepare(unsigned int cpu) -{ - return idle_thread_init(cpu); -} diff --git a/kernel/smpboot.h b/kernel/smpboot.h index 4d5b3e2741f..4cfbcb8a836 100644 --- a/kernel/smpboot.h +++ b/kernel/smpboot.h @@ -8,9 +8,11 @@ int smpboot_prepare(unsigned int cpu); #ifdef CONFIG_GENERIC_SMP_IDLE_THREAD struct task_struct *idle_thread_get(unsigned int cpu); void idle_thread_set_boot_cpu(void); +void idle_threads_init(void); #else static inline struct task_struct *idle_thread_get(unsigned int cpu) { return NULL; } static inline void idle_thread_set_boot_cpu(void) { } +static inline void idle_threads_init(unsigned int cpu) { } #endif -#endif \ No newline at end of file +#endif From a5d5cc40d5f85c82c9488fe46a34076c4bc9b9b6 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Fri, 20 Dec 2013 21:06:21 +0100 Subject: [PATCH 056/215] smpboot, idle: Optimize calls to smp_processor_id() in idle_threads_init() While trying to initialize idle threads for all cpus, idle_threads_init() calls smp_processor_id() in a loop, which is unnecessary. The intent is to initialize idle threads for all non-boot cpus. So just use a variable to note the boot cpu and use it in the loop. Signed-off-by: Srivatsa S. Bhat Cc: suresh.b.siddha@intel.com Cc: venki@google.com Cc: nikunj@linux.vnet.ibm.com Link: http://lkml.kernel.org/r/20120524151055.2549.64309.stgit@srivatsabhat.in.ibm.com Signed-off-by: Thomas Gleixner Signed-off-by: franciscofranco --- kernel/smpboot.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/kernel/smpboot.c b/kernel/smpboot.c index e1a797e028a..0f2162f808a 100644 --- a/kernel/smpboot.c +++ b/kernel/smpboot.c @@ -52,10 +52,12 @@ static inline void idle_init(unsigned int cpu) */ void __init idle_threads_init(void) { - unsigned int cpu; + unsigned int cpu, boot_cpu; + + boot_cpu = smp_processor_id(); for_each_possible_cpu(cpu) { - if (cpu != smp_processor_id()) + if (cpu != boot_cpu) idle_init(cpu); } } From 6bb5717b81ecc16a2418e546233e20afd0bf8f22 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Fri, 20 Dec 2013 21:07:01 +0100 Subject: [PATCH 057/215] smpboot, idle: Fix comment mismatch over idle_threads_init() The comment over idle_threads_init() really talks about the functionality of idle_init(). Move that comment to idle_init(), and add a suitable comment over idle_threads_init(). Signed-off-by: Srivatsa S. Bhat Cc: suresh.b.siddha@intel.com Cc: venki@google.com Cc: nikunj@linux.vnet.ibm.com Link: http://lkml.kernel.org/r/20120524151100.2549.66501.stgit@srivatsabhat.in.ibm.com Signed-off-by: Thomas Gleixner Signed-off-by: franciscofranco --- kernel/smpboot.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/kernel/smpboot.c b/kernel/smpboot.c index 0f2162f808a..98f60c5caa1 100644 --- a/kernel/smpboot.c +++ b/kernel/smpboot.c @@ -31,6 +31,12 @@ void __init idle_thread_set_boot_cpu(void) per_cpu(idle_threads, smp_processor_id()) = current; } +/** + * idle_init - Initialize the idle thread for a cpu + * @cpu: The cpu for which the idle thread should be initialized + * + * Creates the thread if it does not exist. + */ static inline void idle_init(unsigned int cpu) { struct task_struct *tsk = per_cpu(idle_threads, cpu); @@ -45,10 +51,7 @@ static inline void idle_init(unsigned int cpu) } /** - * idle_thread_init - Initialize the idle thread for a cpu - * @cpu: The cpu for which the idle thread should be initialized - * - * Creates the thread if it does not exist. + * idle_threads_init - Initialize idle threads for all cpus */ void __init idle_threads_init(void) { From 889be9b0853750f9e911e31cacd2338ea53eb4f9 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Fri, 20 Dec 2013 21:07:45 +0100 Subject: [PATCH 058/215] smpboot: Provide infrastructure for percpu hotplug threads Provide a generic interface for setting up and tearing down percpu threads. On registration the threads for already online cpus are created and started. On deregistration (modules) the threads are stoppped. During hotplug operations the threads are created, started, parked and unparked. The datastructure for registration provides a pointer to percpu storage space and optional setup, cleanup, park, unpark functions. These functions are called when the thread state changes. Each implementation has to provide a function which is queried and returns whether the thread should run and the thread function itself. The core code handles all state transitions and avoids duplicated code in the call sites. [ paulmck: Preemption leak fix ] Signed-off-by: Thomas Gleixner Cc: Peter Zijlstra Reviewed-by: Srivatsa S. Bhat Cc: Rusty Russell Reviewed-by: Paul E. McKenney Cc: Namhyung Kim Link: http://lkml.kernel.org/r/20120716103948.352501068@linutronix.de Signed-off-by: Thomas Gleixner Signed-off-by: franciscofranco --- include/linux/smpboot.h | 43 ++++++++ kernel/cpu.c | 10 +- kernel/smpboot.c | 229 ++++++++++++++++++++++++++++++++++++++++ kernel/smpboot.h | 4 + 4 files changed, 285 insertions(+), 1 deletion(-) create mode 100644 include/linux/smpboot.h diff --git a/include/linux/smpboot.h b/include/linux/smpboot.h new file mode 100644 index 00000000000..e0106d8581d --- /dev/null +++ b/include/linux/smpboot.h @@ -0,0 +1,43 @@ +#ifndef _LINUX_SMPBOOT_H +#define _LINUX_SMPBOOT_H + +#include + +struct task_struct; +/* Cookie handed to the thread_fn*/ +struct smpboot_thread_data; + +/** + * struct smp_hotplug_thread - CPU hotplug related thread descriptor + * @store: Pointer to per cpu storage for the task pointers + * @list: List head for core management + * @thread_should_run: Check whether the thread should run or not. Called with + * preemption disabled. + * @thread_fn: The associated thread function + * @setup: Optional setup function, called when the thread gets + * operational the first time + * @cleanup: Optional cleanup function, called when the thread + * should stop (module exit) + * @park: Optional park function, called when the thread is + * parked (cpu offline) + * @unpark: Optional unpark function, called when the thread is + * unparked (cpu online) + * @thread_comm: The base name of the thread + */ +struct smp_hotplug_thread { + struct task_struct __percpu **store; + struct list_head list; + int (*thread_should_run)(unsigned int cpu); + void (*thread_fn)(unsigned int cpu); + void (*setup)(unsigned int cpu); + void (*cleanup)(unsigned int cpu, bool online); + void (*park)(unsigned int cpu); + void (*unpark)(unsigned int cpu); + const char *thread_comm; +}; + +int smpboot_register_percpu_thread(struct smp_hotplug_thread *plug_thread); +void smpboot_unregister_percpu_thread(struct smp_hotplug_thread *plug_thread); +int smpboot_thread_schedule(void); + +#endif diff --git a/kernel/cpu.c b/kernel/cpu.c index aeadfbfe744..507420e13f8 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -236,12 +236,13 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen) __func__, cpu); goto out_release; } + smpboot_park_threads(cpu); err = __stop_machine(take_cpu_down, &tcd_param, cpumask_of(cpu)); if (err) { /* CPU didn't die: tell everyone. Can't complain. */ + smpboot_unpark_threads(cpu); cpu_notify_nofail(CPU_DOWN_FAILED | mod, hcpu); - goto out_release; } BUG_ON(cpu_online(cpu)); @@ -310,6 +311,10 @@ static int _cpu_up(unsigned int cpu, int tasks_frozen) goto out; } + ret = smpboot_create_threads(cpu); + if (ret) + goto out; + ret = __cpu_notify(CPU_UP_PREPARE | mod, hcpu, -1, &nr_calls); if (ret) { nr_calls--; @@ -324,6 +329,9 @@ static int _cpu_up(unsigned int cpu, int tasks_frozen) goto out_notify; BUG_ON(!cpu_online(cpu)); + /* Wake the per cpu threads */ + smpboot_unpark_threads(cpu); + /* Now call notifier in preparation. */ cpu_notify(CPU_ONLINE | mod, hcpu); diff --git a/kernel/smpboot.c b/kernel/smpboot.c index 98f60c5caa1..9d5f7b04025 100644 --- a/kernel/smpboot.c +++ b/kernel/smpboot.c @@ -1,11 +1,17 @@ /* * Common SMP CPU bringup/teardown functions */ +#include #include #include #include +#include +#include #include +#include #include +#include +#include #include "smpboot.h" @@ -65,3 +71,226 @@ void __init idle_threads_init(void) } } #endif + +static LIST_HEAD(hotplug_threads); +static DEFINE_MUTEX(smpboot_threads_lock); + +struct smpboot_thread_data { + unsigned int cpu; + unsigned int status; + struct smp_hotplug_thread *ht; +}; + +enum { + HP_THREAD_NONE = 0, + HP_THREAD_ACTIVE, + HP_THREAD_PARKED, +}; + +/** + * smpboot_thread_fn - percpu hotplug thread loop function + * @data: thread data pointer + * + * Checks for thread stop and park conditions. Calls the necessary + * setup, cleanup, park and unpark functions for the registered + * thread. + * + * Returns 1 when the thread should exit, 0 otherwise. + */ +static int smpboot_thread_fn(void *data) +{ + struct smpboot_thread_data *td = data; + struct smp_hotplug_thread *ht = td->ht; + + while (1) { + set_current_state(TASK_INTERRUPTIBLE); + preempt_disable(); + if (kthread_should_stop()) { + set_current_state(TASK_RUNNING); + preempt_enable(); + if (ht->cleanup) + ht->cleanup(td->cpu, cpu_online(td->cpu)); + kfree(td); + return 0; + } + + if (kthread_should_park()) { + __set_current_state(TASK_RUNNING); + preempt_enable(); + if (ht->park && td->status == HP_THREAD_ACTIVE) { + BUG_ON(td->cpu != smp_processor_id()); + ht->park(td->cpu); + td->status = HP_THREAD_PARKED; + } + kthread_parkme(); + /* We might have been woken for stop */ + continue; + } + + BUG_ON(td->cpu != smp_processor_id()); + + /* Check for state change setup */ + switch (td->status) { + case HP_THREAD_NONE: + preempt_enable(); + if (ht->setup) + ht->setup(td->cpu); + td->status = HP_THREAD_ACTIVE; + preempt_disable(); + break; + case HP_THREAD_PARKED: + preempt_enable(); + if (ht->unpark) + ht->unpark(td->cpu); + td->status = HP_THREAD_ACTIVE; + preempt_disable(); + break; + } + + if (!ht->thread_should_run(td->cpu)) { + preempt_enable(); + schedule(); + } else { + set_current_state(TASK_RUNNING); + preempt_enable(); + ht->thread_fn(td->cpu); + } + } +} + +static int +__smpboot_create_thread(struct smp_hotplug_thread *ht, unsigned int cpu) +{ + struct task_struct *tsk = *per_cpu_ptr(ht->store, cpu); + struct smpboot_thread_data *td; + + if (tsk) + return 0; + + td = kzalloc_node(sizeof(*td), GFP_KERNEL, cpu_to_node(cpu)); + if (!td) + return -ENOMEM; + td->cpu = cpu; + td->ht = ht; + + tsk = kthread_create_on_cpu(smpboot_thread_fn, td, cpu, + ht->thread_comm); + if (IS_ERR(tsk)) { + kfree(td); + return PTR_ERR(tsk); + } + + get_task_struct(tsk); + *per_cpu_ptr(ht->store, cpu) = tsk; + return 0; +} + +int smpboot_create_threads(unsigned int cpu) +{ + struct smp_hotplug_thread *cur; + int ret = 0; + + mutex_lock(&smpboot_threads_lock); + list_for_each_entry(cur, &hotplug_threads, list) { + ret = __smpboot_create_thread(cur, cpu); + if (ret) + break; + } + mutex_unlock(&smpboot_threads_lock); + return ret; +} + +static void smpboot_unpark_thread(struct smp_hotplug_thread *ht, unsigned int cpu) +{ + struct task_struct *tsk = *per_cpu_ptr(ht->store, cpu); + + kthread_unpark(tsk); +} + +void smpboot_unpark_threads(unsigned int cpu) +{ + struct smp_hotplug_thread *cur; + + mutex_lock(&smpboot_threads_lock); + list_for_each_entry(cur, &hotplug_threads, list) + smpboot_unpark_thread(cur, cpu); + mutex_unlock(&smpboot_threads_lock); +} + +static void smpboot_park_thread(struct smp_hotplug_thread *ht, unsigned int cpu) +{ + struct task_struct *tsk = *per_cpu_ptr(ht->store, cpu); + + if (tsk) + kthread_park(tsk); +} + +void smpboot_park_threads(unsigned int cpu) +{ + struct smp_hotplug_thread *cur; + + mutex_lock(&smpboot_threads_lock); + list_for_each_entry_reverse(cur, &hotplug_threads, list) + smpboot_park_thread(cur, cpu); + mutex_unlock(&smpboot_threads_lock); +} + +static void smpboot_destroy_threads(struct smp_hotplug_thread *ht) +{ + unsigned int cpu; + + /* We need to destroy also the parked threads of offline cpus */ + for_each_possible_cpu(cpu) { + struct task_struct *tsk = *per_cpu_ptr(ht->store, cpu); + + if (tsk) { + kthread_stop(tsk); + put_task_struct(tsk); + *per_cpu_ptr(ht->store, cpu) = NULL; + } + } +} + +/** + * smpboot_register_percpu_thread - Register a per_cpu thread related to hotplug + * @plug_thread: Hotplug thread descriptor + * + * Creates and starts the threads on all online cpus. + */ +int smpboot_register_percpu_thread(struct smp_hotplug_thread *plug_thread) +{ + unsigned int cpu; + int ret = 0; + + mutex_lock(&smpboot_threads_lock); + for_each_online_cpu(cpu) { + ret = __smpboot_create_thread(plug_thread, cpu); + if (ret) { + smpboot_destroy_threads(plug_thread); + goto out; + } + smpboot_unpark_thread(plug_thread, cpu); + } + list_add(&plug_thread->list, &hotplug_threads); +out: + mutex_unlock(&smpboot_threads_lock); + return ret; +} +EXPORT_SYMBOL_GPL(smpboot_register_percpu_thread); + +/** + * smpboot_unregister_percpu_thread - Unregister a per_cpu thread related to hotplug + * @plug_thread: Hotplug thread descriptor + * + * Stops all threads on all possible cpus. + */ +void smpboot_unregister_percpu_thread(struct smp_hotplug_thread *plug_thread) +{ + get_online_cpus(); + mutex_lock(&smpboot_threads_lock); + list_del(&plug_thread->list); + smpboot_destroy_threads(plug_thread); + mutex_unlock(&smpboot_threads_lock); + put_online_cpus(); +} +EXPORT_SYMBOL_GPL(smpboot_unregister_percpu_thread); diff --git a/kernel/smpboot.h b/kernel/smpboot.h index 4cfbcb8a836..b99b014c07a 100644 --- a/kernel/smpboot.h +++ b/kernel/smpboot.h @@ -15,4 +15,8 @@ static inline void idle_thread_set_boot_cpu(void) { } static inline void idle_threads_init(unsigned int cpu) { } #endif +int smpboot_create_threads(unsigned int cpu); +void smpboot_park_threads(unsigned int cpu); +void smpboot_unpark_threads(unsigned int cpu); + #endif From 69afa4c1cc106600b55cb46058ee1fa2278e195b Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Fri, 20 Dec 2013 21:08:44 +0100 Subject: [PATCH 059/215] hotplug: Fix UP bug in smpboot hotplug code Because kernel subsystems need their per-CPU kthreads on UP systems as well as on SMP systems, the smpboot hotplug kthread functions must be provided in UP builds as well as in SMP builds. This commit therefore adds smpboot.c to UP builds and excludes irrelevant code via #ifdef. Signed-off-by: Paul E. McKenney Signed-off-by: Paul E. McKenney Signed-off-by: Thomas Gleixner Signed-off-by: franciscofranco --- kernel/Makefile | 3 +-- kernel/smpboot.c | 4 ++++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/kernel/Makefile b/kernel/Makefile index 6e9096a473a..b8cb15a47f8 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -10,7 +10,7 @@ obj-y = fork.o exec_domain.o panic.o printk.o \ kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \ hrtimer.o rwsem.o nsproxy.o srcu.o semaphore.o \ notifier.o ksysfs.o cred.o \ - async.o range.o groups.o + async.o range.o groups.o smpboot.o ifdef CONFIG_FUNCTION_TRACER # Do not trace debug files and internal ftrace files @@ -43,7 +43,6 @@ obj-$(CONFIG_DEBUG_RT_MUTEXES) += rtmutex-debug.o obj-$(CONFIG_RT_MUTEX_TESTER) += rtmutex-tester.o obj-$(CONFIG_GENERIC_ISA_DMA) += dma.o obj-$(CONFIG_SMP) += smp.o -obj-$(CONFIG_SMP) += smpboot.o ifneq ($(CONFIG_SMP),y) obj-y += up.o endif diff --git a/kernel/smpboot.c b/kernel/smpboot.c index 9d5f7b04025..d6c5fc05424 100644 --- a/kernel/smpboot.c +++ b/kernel/smpboot.c @@ -15,6 +15,8 @@ #include "smpboot.h" +#ifdef CONFIG_SMP + #ifdef CONFIG_GENERIC_SMP_IDLE_THREAD /* * For the hotplug case we keep the task structs around and reuse @@ -72,6 +74,8 @@ void __init idle_threads_init(void) } #endif +#endif /* #ifdef CONFIG_SMP */ + static LIST_HEAD(hotplug_threads); static DEFINE_MUTEX(smpboot_threads_lock); From b4443bf7d9f2181063f0949e3ab9848cb4621874 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Fri, 20 Dec 2013 21:09:17 +0100 Subject: [PATCH 060/215] smpboot: Allow selfparking per cpu threads The stop machine threads are still killed when a cpu goes offline. The reason is that the thread is used to bring the cpu down, so it can't be parked along with the other per cpu threads. Allow a per cpu thread to be excluded from automatic parking, so it can park itself once it's done Add a create callback function as well. Signed-off-by: Thomas Gleixner Cc: Peter Zijlstra Cc: Rusty Russell Cc: Paul McKenney Cc: Srivatsa S. Bhat Cc: Arjan van de Veen Cc: Paul Turner Cc: Richard Weinberger Cc: Magnus Damm Link: http://lkml.kernel.org/r/20130131120741.553993267@linutronix.de Signed-off-by: Thomas Gleixner Signed-off-by: franciscofranco --- include/linux/smpboot.h | 5 +++++ kernel/smpboot.c | 5 +++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/include/linux/smpboot.h b/include/linux/smpboot.h index e0106d8581d..c65dee05991 100644 --- a/include/linux/smpboot.h +++ b/include/linux/smpboot.h @@ -14,6 +14,8 @@ struct smpboot_thread_data; * @thread_should_run: Check whether the thread should run or not. Called with * preemption disabled. * @thread_fn: The associated thread function + * @create: Optional setup function, called when the thread gets + * created (Not called from the thread context) * @setup: Optional setup function, called when the thread gets * operational the first time * @cleanup: Optional cleanup function, called when the thread @@ -22,6 +24,7 @@ struct smpboot_thread_data; * parked (cpu offline) * @unpark: Optional unpark function, called when the thread is * unparked (cpu online) + * @selfparking: Thread is not parked by the park function. * @thread_comm: The base name of the thread */ struct smp_hotplug_thread { @@ -29,10 +32,12 @@ struct smp_hotplug_thread { struct list_head list; int (*thread_should_run)(unsigned int cpu); void (*thread_fn)(unsigned int cpu); + void (*create)(unsigned int cpu); void (*setup)(unsigned int cpu); void (*cleanup)(unsigned int cpu, bool online); void (*park)(unsigned int cpu); void (*unpark)(unsigned int cpu); + bool selfparking; const char *thread_comm; }; diff --git a/kernel/smpboot.c b/kernel/smpboot.c index d6c5fc05424..d4abac26177 100644 --- a/kernel/smpboot.c +++ b/kernel/smpboot.c @@ -183,9 +183,10 @@ __smpboot_create_thread(struct smp_hotplug_thread *ht, unsigned int cpu) kfree(td); return PTR_ERR(tsk); } - get_task_struct(tsk); *per_cpu_ptr(ht->store, cpu) = tsk; + if (ht->create) + ht->create(cpu); return 0; } @@ -225,7 +226,7 @@ static void smpboot_park_thread(struct smp_hotplug_thread *ht, unsigned int cpu) { struct task_struct *tsk = *per_cpu_ptr(ht->store, cpu); - if (tsk) + if (tsk && !ht->selfparking) kthread_park(tsk); } From 1c762225ba33935cb9e228a925dc63e211d4ce7e Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Fri, 20 Dec 2013 21:09:51 +0100 Subject: [PATCH 061/215] stop_machine: Store task reference in a separate per cpu variable To allow the stopper thread being managed by the smpboot thread infrastructure separate out the task storage from the stopper data structure. Signed-off-by: Thomas Gleixner Cc: Peter Zijlstra Cc: Rusty Russell Cc: Paul McKenney Cc: Srivatsa S. Bhat Cc: Arjan van de Veen Cc: Paul Turner Cc: Richard Weinberger Cc: Magnus Damm Link: http://lkml.kernel.org/r/20130131120741.626690384@linutronix.de Signed-off-by: Thomas Gleixner Signed-off-by: franciscofranco --- kernel/stop_machine.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c index 9e4017a58b3..8c42940ee29 100644 --- a/kernel/stop_machine.c +++ b/kernel/stop_machine.c @@ -37,10 +37,10 @@ struct cpu_stopper { spinlock_t lock; bool enabled; /* is this stopper enabled? */ struct list_head works; /* list of pending works */ - struct task_struct *thread; /* stopper thread */ }; static DEFINE_PER_CPU(struct cpu_stopper, cpu_stopper); +static DEFINE_PER_CPU(struct task_struct *, cpu_stopper_task); static bool stop_machine_initialized = false; static void cpu_stop_init_done(struct cpu_stop_done *done, unsigned int nr_todo) @@ -62,16 +62,18 @@ static void cpu_stop_signal_done(struct cpu_stop_done *done, bool executed) } /* queue @work to @stopper. if offline, @work is completed immediately */ -static void cpu_stop_queue_work(struct cpu_stopper *stopper, - struct cpu_stop_work *work) +static void cpu_stop_queue_work(unsigned int cpu, struct cpu_stop_work *work) { + struct cpu_stopper *stopper = &per_cpu(cpu_stopper, cpu); + struct task_struct *p = per_cpu(cpu_stopper_task, cpu); + unsigned long flags; spin_lock_irqsave(&stopper->lock, flags); if (stopper->enabled) { list_add_tail(&work->list, &stopper->works); - wake_up_process(stopper->thread); + wake_up_process(p); } else cpu_stop_signal_done(work->done, false); @@ -108,7 +110,7 @@ int stop_one_cpu(unsigned int cpu, cpu_stop_fn_t fn, void *arg) struct cpu_stop_work work = { .fn = fn, .arg = arg, .done = &done }; cpu_stop_init_done(&done, 1); - cpu_stop_queue_work(&per_cpu(cpu_stopper, cpu), &work); + cpu_stop_queue_work(cpu, &work); wait_for_completion(&done.completion); return done.executed ? done.ret : -ENOENT; } @@ -130,7 +132,7 @@ void stop_one_cpu_nowait(unsigned int cpu, cpu_stop_fn_t fn, void *arg, struct cpu_stop_work *work_buf) { *work_buf = (struct cpu_stop_work){ .fn = fn, .arg = arg, }; - cpu_stop_queue_work(&per_cpu(cpu_stopper, cpu), work_buf); + cpu_stop_queue_work(cpu, work_buf); } /* static data for stop_cpus */ @@ -159,8 +161,7 @@ static void queue_stop_cpus_work(const struct cpumask *cpumask, */ preempt_disable(); for_each_cpu(cpu, cpumask) - cpu_stop_queue_work(&per_cpu(cpu_stopper, cpu), - &per_cpu(stop_cpus_work, cpu)); + cpu_stop_queue_work(cpu, &per_cpu(stop_cpus_work, cpu)); preempt_enable(); } @@ -304,12 +305,11 @@ static int cpu_stop_cpu_callback(struct notifier_block *nfb, { unsigned int cpu = (unsigned long)hcpu; struct cpu_stopper *stopper = &per_cpu(cpu_stopper, cpu); - struct task_struct *p; + struct task_struct *p = per_cpu(cpu_stopper_task, cpu); switch (action & ~CPU_TASKS_FROZEN) { case CPU_UP_PREPARE: - BUG_ON(stopper->thread || stopper->enabled || - !list_empty(&stopper->works)); + BUG_ON(p || stopper->enabled || !list_empty(&stopper->works)); p = kthread_create_on_node(cpu_stopper_thread, stopper, cpu_to_node(cpu), @@ -319,12 +319,12 @@ static int cpu_stop_cpu_callback(struct notifier_block *nfb, get_task_struct(p); kthread_bind(p, cpu); sched_set_stop_task(cpu, p); - stopper->thread = p; + per_cpu(cpu_stopper_task, cpu) = p; break; case CPU_ONLINE: /* strictly unnecessary, as first user will wake it */ - wake_up_process(stopper->thread); + wake_up_process(p); /* mark enabled */ spin_lock_irq(&stopper->lock); stopper->enabled = true; @@ -339,7 +339,7 @@ static int cpu_stop_cpu_callback(struct notifier_block *nfb, sched_set_stop_task(cpu, NULL); /* kill the stopper */ - kthread_stop(stopper->thread); + kthread_stop(p); /* drain remaining works */ spin_lock_irq(&stopper->lock); list_for_each_entry(work, &stopper->works, list) @@ -347,8 +347,8 @@ static int cpu_stop_cpu_callback(struct notifier_block *nfb, stopper->enabled = false; spin_unlock_irq(&stopper->lock); /* release the stopper */ - put_task_struct(stopper->thread); - stopper->thread = NULL; + put_task_struct(p); + per_cpu(cpu_stopper_task, cpu) = NULL; break; } #endif From 5743ddd04bc02350651ec7c9b24884f7da39c86c Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Fri, 20 Dec 2013 21:14:11 +0100 Subject: [PATCH 062/215] stop_machine: Use smpboot threads Use the smpboot thread infrastructure. Mark the stopper thread selfparking and park it after it has finished the take_cpu_down() work. Signed-off-by: Thomas Gleixner Cc: Peter Zijlstra Cc: Rusty Russell Cc: Paul McKenney Cc: Srivatsa S. Bhat Cc: Arjan van de Veen Cc: Paul Turner Cc: Richard Weinberger Cc: Magnus Damm Link: http://lkml.kernel.org/r/20130131120741.686315164@linutronix.de Signed-off-by: Thomas Gleixner Signed-off-by: franciscofranco Signed-off-by: Tk-Glitch --- kernel/cpu.c | 2 + kernel/stop_machine.c | 136 ++++++++++++++++-------------------------- 2 files changed, 52 insertions(+), 86 deletions(-) diff --git a/kernel/cpu.c b/kernel/cpu.c index 507420e13f8..d947ab08cf1 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -206,6 +206,8 @@ static int __ref take_cpu_down(void *_param) return err; cpu_notify(CPU_DYING | param->mod, param->hcpu); + /* Park the stopper thread */ + kthread_park(current); return 0; } diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c index 8c42940ee29..95d178c62d5 100644 --- a/kernel/stop_machine.c +++ b/kernel/stop_machine.c @@ -18,7 +18,7 @@ #include #include #include - +#include #include /* @@ -245,20 +245,25 @@ int try_stop_cpus(const struct cpumask *cpumask, cpu_stop_fn_t fn, void *arg) return ret; } -static int cpu_stopper_thread(void *data) +static int cpu_stop_should_run(unsigned int cpu) +{ + struct cpu_stopper *stopper = &per_cpu(cpu_stopper, cpu); + unsigned long flags; + int run; + + spin_lock_irqsave(&stopper->lock, flags); + run = !list_empty(&stopper->works); + spin_unlock_irqrestore(&stopper->lock, flags); + return run; +} + +static void cpu_stopper_thread(unsigned int cpu) { - struct cpu_stopper *stopper = data; + struct cpu_stopper *stopper = &per_cpu(cpu_stopper, cpu); struct cpu_stop_work *work; int ret; repeat: - set_current_state(TASK_INTERRUPTIBLE); /* mb paired w/ kthread_stop */ - - if (kthread_should_stop()) { - __set_current_state(TASK_RUNNING); - return 0; - } - work = NULL; spin_lock_irq(&stopper->lock); if (!list_empty(&stopper->works)) { @@ -274,8 +279,6 @@ static int cpu_stopper_thread(void *data) struct cpu_stop_done *done = work->done; char ksym_buf[KSYM_NAME_LEN] __maybe_unused; - __set_current_state(TASK_RUNNING); - /* cpu stop callbacks are not allowed to sleep */ preempt_disable(); @@ -291,87 +294,55 @@ static int cpu_stopper_thread(void *data) ksym_buf), arg); cpu_stop_signal_done(done, true); - } else - schedule(); - - goto repeat; + goto repeat; + } } extern void sched_set_stop_task(int cpu, struct task_struct *stop); -/* manage stopper for a cpu, mostly lifted from sched migration thread mgmt */ -static int cpu_stop_cpu_callback(struct notifier_block *nfb, - unsigned long action, void *hcpu) +static void cpu_stop_create(unsigned int cpu) +{ + sched_set_stop_task(cpu, per_cpu(cpu_stopper_task, cpu)); +} + +static void cpu_stop_park(unsigned int cpu) { - unsigned int cpu = (unsigned long)hcpu; struct cpu_stopper *stopper = &per_cpu(cpu_stopper, cpu); - struct task_struct *p = per_cpu(cpu_stopper_task, cpu); + struct cpu_stop_work *work; + unsigned long flags; - switch (action & ~CPU_TASKS_FROZEN) { - case CPU_UP_PREPARE: - BUG_ON(p || stopper->enabled || !list_empty(&stopper->works)); - p = kthread_create_on_node(cpu_stopper_thread, - stopper, - cpu_to_node(cpu), - "migration/%d", cpu); - if (IS_ERR(p)) - return notifier_from_errno(PTR_ERR(p)); - get_task_struct(p); - kthread_bind(p, cpu); - sched_set_stop_task(cpu, p); - per_cpu(cpu_stopper_task, cpu) = p; - break; - - case CPU_ONLINE: - /* strictly unnecessary, as first user will wake it */ - wake_up_process(p); - /* mark enabled */ - spin_lock_irq(&stopper->lock); - stopper->enabled = true; - spin_unlock_irq(&stopper->lock); - break; - -#ifdef CONFIG_HOTPLUG_CPU - case CPU_UP_CANCELED: - case CPU_POST_DEAD: - { - struct cpu_stop_work *work; - - sched_set_stop_task(cpu, NULL); - /* kill the stopper */ - kthread_stop(p); - /* drain remaining works */ - spin_lock_irq(&stopper->lock); - list_for_each_entry(work, &stopper->works, list) - cpu_stop_signal_done(work->done, false); - stopper->enabled = false; - spin_unlock_irq(&stopper->lock); - /* release the stopper */ - put_task_struct(p); - per_cpu(cpu_stopper_task, cpu) = NULL; - break; - } -#endif - } + /* drain remaining works */ + spin_lock_irqsave(&stopper->lock, flags); + list_for_each_entry(work, &stopper->works, list) + cpu_stop_signal_done(work->done, false); + stopper->enabled = false; + spin_unlock_irqrestore(&stopper->lock, flags); +} - return NOTIFY_OK; +static void cpu_stop_unpark(unsigned int cpu) +{ + struct cpu_stopper *stopper = &per_cpu(cpu_stopper, cpu); + + spin_lock_irq(&stopper->lock); + stopper->enabled = true; + spin_unlock_irq(&stopper->lock); } -/* - * Give it a higher priority so that cpu stopper is available to other - * cpu notifiers. It currently shares the same priority as sched - * migration_notifier. - */ -static struct notifier_block cpu_stop_cpu_notifier = { - .notifier_call = cpu_stop_cpu_callback, - .priority = 10, +static struct smp_hotplug_thread cpu_stop_threads = { + .store = &cpu_stopper_task, + .thread_should_run = cpu_stop_should_run, + .thread_fn = cpu_stopper_thread, + .thread_comm = "migration/%u", + .create = cpu_stop_create, + .setup = cpu_stop_unpark, + .park = cpu_stop_park, + .unpark = cpu_stop_unpark, + .selfparking = true, }; static int __init cpu_stop_init(void) { - void *bcpu = (void *)(long)smp_processor_id(); unsigned int cpu; - int err; for_each_possible_cpu(cpu) { struct cpu_stopper *stopper = &per_cpu(cpu_stopper, cpu); @@ -380,15 +351,8 @@ static int __init cpu_stop_init(void) INIT_LIST_HEAD(&stopper->works); } - /* start one for the boot cpu */ - err = cpu_stop_cpu_callback(&cpu_stop_cpu_notifier, CPU_UP_PREPARE, - bcpu); - BUG_ON(err != NOTIFY_OK); - cpu_stop_cpu_callback(&cpu_stop_cpu_notifier, CPU_ONLINE, bcpu); - register_cpu_notifier(&cpu_stop_cpu_notifier); - + BUG_ON(smpboot_register_percpu_thread(&cpu_stop_threads)); stop_machine_initialized = true; - return 0; } early_initcall(cpu_stop_init); From 1cd3b43aa0d850a53f390741804b4d7d57fd4488 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Fri, 20 Dec 2013 21:14:57 +0100 Subject: [PATCH 063/215] stop_machine: Mark per cpu stopper enabled early commit 14e568e78 (stop_machine: Use smpboot threads) introduced the following regression: Before this commit the stopper enabled bit was set in the online notifier. CPU0 CPU1 cpu_up cpu online hotplug_notifier(ONLINE) stopper(CPU1)->enabled = true; ... stop_machine() The conversion to smpboot threads moved the enablement to the wakeup path of the parked thread. The majority of users seem to have the following working order: CPU0 CPU1 cpu_up cpu online unpark_threads() wakeup(stopper[CPU1]) .... stopper thread runs stopper(CPU1)->enabled = true; stop_machine() But Konrad and Sander have observed: CPU0 CPU1 cpu_up cpu online unpark_threads() wakeup(stopper[CPU1]) .... stop_machine() stopper thread runs stopper(CPU1)->enabled = true; Now the stop machinery kicks CPU0 into the stop loop, where it gets stuck forever because the queue code saw stopper(CPU1)->enabled == false, so CPU0 waits for CPU1 to enter stomp_machine, but the CPU1 stopper work got discarded due to enabled == false. Add a pre_unpark function to the smpboot thread descriptor and call it before waking the thread. This fixes the problem at hand, but the stop_machine code should be more robust. The stopper->enabled flag smells fishy at best. Thanks to Konrad for going through a loop of debug patches and providing the information to decode this issue. Reported-and-tested-by: Konrad Rzeszutek Wilk Reported-and-tested-by: Sander Eikelenboom Cc: Srivatsa S. Bhat Cc: Rusty Russell Link: http://lkml.kernel.org/r/alpine.LFD.2.02.1302261843240.22263@ionos Signed-off-by: Thomas Gleixner Signed-off-by: franciscofranco --- include/linux/smpboot.h | 4 ++++ kernel/smpboot.c | 2 ++ kernel/stop_machine.c | 2 +- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/include/linux/smpboot.h b/include/linux/smpboot.h index c65dee05991..13e92967955 100644 --- a/include/linux/smpboot.h +++ b/include/linux/smpboot.h @@ -24,6 +24,9 @@ struct smpboot_thread_data; * parked (cpu offline) * @unpark: Optional unpark function, called when the thread is * unparked (cpu online) + * @pre_unpark: Optional unpark function, called before the thread is + * unparked (cpu online). This is not guaranteed to be + * called on the target cpu of the thread. Careful! * @selfparking: Thread is not parked by the park function. * @thread_comm: The base name of the thread */ @@ -37,6 +40,7 @@ struct smp_hotplug_thread { void (*cleanup)(unsigned int cpu, bool online); void (*park)(unsigned int cpu); void (*unpark)(unsigned int cpu); + void (*pre_unpark)(unsigned int cpu); bool selfparking; const char *thread_comm; }; diff --git a/kernel/smpboot.c b/kernel/smpboot.c index d4abac26177..8eaed9aa9cf 100644 --- a/kernel/smpboot.c +++ b/kernel/smpboot.c @@ -209,6 +209,8 @@ static void smpboot_unpark_thread(struct smp_hotplug_thread *ht, unsigned int cp { struct task_struct *tsk = *per_cpu_ptr(ht->store, cpu); + if (ht->pre_unpark) + ht->pre_unpark(cpu); kthread_unpark(tsk); } diff --git a/kernel/stop_machine.c b/kernel/stop_machine.c index 95d178c62d5..c09f2955ae3 100644 --- a/kernel/stop_machine.c +++ b/kernel/stop_machine.c @@ -336,7 +336,7 @@ static struct smp_hotplug_thread cpu_stop_threads = { .create = cpu_stop_create, .setup = cpu_stop_unpark, .park = cpu_stop_park, - .unpark = cpu_stop_unpark, + .pre_unpark = cpu_stop_unpark, .selfparking = true, }; From b1680a0c336645fe97db35d6a08760ea4c277a00 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Fri, 20 Dec 2013 21:15:36 +0100 Subject: [PATCH 064/215] kthread: Prevent unpark race which puts threads on the wrong cpu The smpboot threads rely on the park/unpark mechanism which binds per cpu threads on a particular core. Though the functionality is racy: CPU0 CPU1 CPU2 unpark(T) wake_up_process(T) clear(SHOULD_PARK) T runs leave parkme() due to !SHOULD_PARK bind_to(CPU2) BUG_ON(wrong CPU) We cannot let the tasks move themself to the target CPU as one of those tasks is actually the migration thread itself, which requires that it starts running on the target cpu right away. The solution to this problem is to prevent wakeups in park mode which are not from unpark(). That way we can guarantee that the association of the task to the target cpu is working correctly. Add a new task state (TASK_PARKED) which prevents other wakeups and use this state explicitly for the unpark wakeup. Peter noticed: Also, since the task state is visible to userspace and all the parked tasks are still in the PID space, its a good hint in ps and friends that these tasks aren't really there for the moment. The migration thread has another related issue. CPU0 CPU1 Bring up CPU2 create_thread(T) park(T) wait_for_completion() parkme() complete() sched_set_stop_task() schedule(TASK_PARKED) The sched_set_stop_task() call is issued while the task is on the runqueue of CPU1 and that confuses the hell out of the stop_task class on that cpu. So we need the same synchronizaion before sched_set_stop_task(). Reported-by: Dave Jones Reported-and-tested-by: Dave Hansen Reported-and-tested-by: Borislav Petkov Acked-by: Peter Ziljstra Cc: Srivatsa S. Bhat Cc: dhillf@gmail.com Cc: Ingo Molnar Cc: stable@vger.kernel.org Link: http://lkml.kernel.org/r/alpine.LFD.2.02.1304091635430.21884@ionos Signed-off-by: Thomas Gleixner Signed-off-by: franciscofranco --- fs/proc/array.c | 1 + include/linux/sched.h | 5 ++-- include/trace/events/sched.h | 2 +- kernel/kthread.c | 52 +++++++++++++++++++----------------- kernel/smpboot.c | 14 ++++++++-- 5 files changed, 45 insertions(+), 29 deletions(-) diff --git a/fs/proc/array.c b/fs/proc/array.c index f9bd395b347..2168d6a9398 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -142,6 +142,7 @@ static const char * const task_state_array[] = { "x (dead)", /* 64 */ "K (wakekill)", /* 128 */ "W (waking)", /* 256 */ + "P (parked)", /* 512 */ }; static inline const char *get_task_state(struct task_struct *tsk) diff --git a/include/linux/sched.h b/include/linux/sched.h index 78ccca7b32f..6fb22c10bb7 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -194,9 +194,10 @@ print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq) #define TASK_DEAD 64 #define TASK_WAKEKILL 128 #define TASK_WAKING 256 -#define TASK_STATE_MAX 512 +#define TASK_PARKED 512 +#define TASK_STATE_MAX 1024 -#define TASK_STATE_TO_CHAR_STR "RSDTtZXxKW" +#define TASK_STATE_TO_CHAR_STR "RSDTtZXxKWP" extern char ___assert_task_state[1 - 2*!!( sizeof(TASK_STATE_TO_CHAR_STR)-1 != ilog2(TASK_STATE_MAX)+1)]; diff --git a/include/trace/events/sched.h b/include/trace/events/sched.h index ea7a2035456..be16a72903f 100644 --- a/include/trace/events/sched.h +++ b/include/trace/events/sched.h @@ -144,7 +144,7 @@ TRACE_EVENT(sched_switch, __print_flags(__entry->prev_state & (TASK_STATE_MAX-1), "|", { 1, "S"} , { 2, "D" }, { 4, "T" }, { 8, "t" }, { 16, "Z" }, { 32, "X" }, { 64, "x" }, - { 128, "W" }) : "R", + { 128, "K" }, { 256, "W" }, { 512, "P" }) : "R", __entry->prev_state & TASK_STATE_MAX ? "+" : "", __entry->next_comm, __entry->next_pid, __entry->next_prio) ); diff --git a/kernel/kthread.c b/kernel/kthread.c index 146a6fa9682..3b72b80dd0f 100644 --- a/kernel/kthread.c +++ b/kernel/kthread.c @@ -123,12 +123,12 @@ void *kthread_data(struct task_struct *task) static void __kthread_parkme(struct kthread *self) { - __set_current_state(TASK_INTERRUPTIBLE); + __set_current_state(TASK_PARKED); while (test_bit(KTHREAD_SHOULD_PARK, &self->flags)) { if (!test_and_set_bit(KTHREAD_IS_PARKED, &self->flags)) complete(&self->parked); schedule(); - __set_current_state(TASK_INTERRUPTIBLE); + __set_current_state(TASK_PARKED); } clear_bit(KTHREAD_IS_PARKED, &self->flags); __set_current_state(TASK_RUNNING); @@ -255,8 +255,13 @@ struct task_struct *kthread_create_on_node(int (*threadfn)(void *data), } EXPORT_SYMBOL(kthread_create_on_node); -static void __kthread_bind(struct task_struct *p, unsigned int cpu) +static void __kthread_bind(struct task_struct *p, unsigned int cpu, long state) { + /* Must have done schedule() in kthread() before we set_task_cpu */ + if (!wait_task_inactive(p, state)) { + WARN_ON(1); + return; + } /* It's safe because the task is inactive. */ do_set_cpus_allowed(p, cpumask_of(cpu)); p->flags |= PF_THREAD_BOUND; @@ -273,12 +278,7 @@ static void __kthread_bind(struct task_struct *p, unsigned int cpu) */ void kthread_bind(struct task_struct *p, unsigned int cpu) { - /* Must have done schedule() in kthread() before we set_task_cpu */ - if (!wait_task_inactive(p, TASK_UNINTERRUPTIBLE)) { - WARN_ON(1); - return; - } - __kthread_bind(p, cpu); + __kthread_bind(p, cpu, TASK_UNINTERRUPTIBLE); } EXPORT_SYMBOL(kthread_bind); @@ -323,6 +323,22 @@ static struct kthread *task_get_live_kthread(struct task_struct *k) return NULL; } +static void __kthread_unpark(struct task_struct *k, struct kthread *kthread) +{ + clear_bit(KTHREAD_SHOULD_PARK, &kthread->flags); + /* + * We clear the IS_PARKED bit here as we don't wait + * until the task has left the park code. So if we'd + * park before that happens we'd see the IS_PARKED bit + * which might be about to be cleared. + */ + if (test_and_clear_bit(KTHREAD_IS_PARKED, &kthread->flags)) { + if (test_bit(KTHREAD_IS_PER_CPU, &kthread->flags)) + __kthread_bind(k, kthread->cpu, TASK_PARKED); + wake_up_state(k, TASK_PARKED); + } +} + /** * kthread_unpark - unpark a thread created by kthread_create(). * @k: thread created by kthread_create(). @@ -335,20 +351,8 @@ void kthread_unpark(struct task_struct *k) { struct kthread *kthread = task_get_live_kthread(k); - if (kthread) { - clear_bit(KTHREAD_SHOULD_PARK, &kthread->flags); - /* - * We clear the IS_PARKED bit here as we don't wait - * until the task has left the park code. So if we'd - * park before that happens we'd see the IS_PARKED bit - * which might be about to be cleared. - */ - if (test_and_clear_bit(KTHREAD_IS_PARKED, &kthread->flags)) { - if (test_bit(KTHREAD_IS_PER_CPU, &kthread->flags)) - __kthread_bind(k, kthread->cpu); - wake_up_process(k); - } - } + if (kthread) + __kthread_unpark(k, kthread); put_task_struct(k); } @@ -406,7 +410,7 @@ int kthread_stop(struct task_struct *k) trace_sched_kthread_stop(k); if (kthread) { set_bit(KTHREAD_SHOULD_STOP, &kthread->flags); - clear_bit(KTHREAD_SHOULD_PARK, &kthread->flags); + __kthread_unpark(k, kthread); wake_up_process(k); wait_for_completion(&kthread->exited); } diff --git a/kernel/smpboot.c b/kernel/smpboot.c index 8eaed9aa9cf..02fc5c93367 100644 --- a/kernel/smpboot.c +++ b/kernel/smpboot.c @@ -185,8 +185,18 @@ __smpboot_create_thread(struct smp_hotplug_thread *ht, unsigned int cpu) } get_task_struct(tsk); *per_cpu_ptr(ht->store, cpu) = tsk; - if (ht->create) - ht->create(cpu); + if (ht->create) { + /* + * Make sure that the task has actually scheduled out + * into park position, before calling the create + * callback. At least the migration thread callback + * requires that the task is off the runqueue. + */ + if (!wait_task_inactive(tsk, TASK_PARKED)) + WARN_ON(1); + else + ht->create(cpu); + } return 0; } From c46918c056f9481ee50444e8773a4d92906d43be Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Fri, 20 Dec 2013 21:20:14 +0100 Subject: [PATCH 065/215] sched: Fix select_idle_sibling() bouncing cow syndrome If the previous CPU is cache affine and idle, select it. The current implementation simply traverses the sd_llc domain, taking the first idle CPU encountered, which walks buddy pairs hand in hand over the package, inflicting excruciating pain. 1 tbench pair (worst case) in a 10 core + SMT package: pre 15.22 MB/sec 1 procs post 252.01 MB/sec 1 procs Signed-off-by: Mike Galbraith Cc: Peter Zijlstra Link: http://lkml.kernel.org/r/1359371965.5783.127.camel@marge.simpson.net Signed-off-by: Ingo Molnar --- kernel/sched/fair.c | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index ca424764da4..f84802846cb 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -2634,25 +2634,18 @@ find_idlest_cpu(struct sched_group *group, struct task_struct *p, int this_cpu) */ static int select_idle_sibling(struct task_struct *p, int target) { - int cpu = smp_processor_id(); - int prev_cpu = task_cpu(p); struct sched_domain *sd; struct sched_group *sg; - int i; + int i = task_cpu(p); - /* - * If the task is going to be woken-up on this cpu and if it is - * already idle, then it is the right target. - */ - if (target == cpu && idle_cpu(cpu)) - return cpu; + if (idle_cpu(target)) + return target; /* - * If the task is going to be woken-up on the cpu where it previously - * ran and if it is currently idle, then it the right target. + * If the prevous cpu is cache affine and idle, don't be stupid. */ - if (target == prev_cpu && idle_cpu(prev_cpu)) - return prev_cpu; + if (i != target && cpus_share_cache(i, target) && idle_cpu(i)) + return i; /* * Otherwise, iterate the domains and find an elegible idle cpu. @@ -2666,7 +2659,7 @@ static int select_idle_sibling(struct task_struct *p, int target) goto next; for_each_cpu(i, sched_group_cpus(sg)) { - if (!idle_cpu(i)) + if (i == target || !idle_cpu(i)) goto next; } From 005515d893cb72499e00ea7226e7e5c7bb125707 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Fri, 20 Dec 2013 21:21:05 +0100 Subject: [PATCH 066/215] sched: Implement smarter wake-affine logic The wake-affine scheduler feature is currently always trying to pull the wakee close to the waker. In theory this should be beneficial if the waker's CPU caches hot data for the wakee, and it's also beneficial in the extreme ping-pong high context switch rate case. Testing shows it can benefit hackbench up to 15%. However, the feature is somewhat blind, from which some workloads such as pgbench suffer. It's also time-consuming algorithmically. Testing shows it can damage pgbench up to 50% - far more than the benefit it brings in the best case. So wake-affine should be smarter and it should realize when to stop its thankless effort at trying to find a suitable CPU to wake on. This patch introduces 'wakee_flips', which will be increased each time the task flips (switches) its wakee target. So a high 'wakee_flips' value means the task has more than one wakee, and the bigger the number, the higher the wakeup frequency. Now when making the decision on whether to pull or not, pay attention to the wakee with a high 'wakee_flips', pulling such a task may benefit the wakee. Also imply that the waker will face cruel competition later, it could be very cruel or very fast depends on the story behind 'wakee_flips', waker therefore suffers. Furthermore, if waker also has a high 'wakee_flips', that implies that multiple tasks rely on it, then waker's higher latency will damage all of them, so pulling wakee seems to be a bad deal. Thus, when 'waker->wakee_flips / wakee->wakee_flips' becomes higher and higher, the cost of pulling seems to be worse and worse. The patch therefore helps the wake-affine feature to stop its pulling work when: wakee->wakee_flips > factor && waker->wakee_flips > (factor * wakee->wakee_flips) The 'factor' here is the number of CPUs in the current CPU's NUMA node, so a bigger node will lead to more pulling since the trial becomes more severe. After applying the patch, pgbench shows up to 40% improvements and no regressions. Tested with 12 cpu x86 server and tip 3.10.0-rc7. The percentages in the final column highlight the areas with the biggest wins, all other areas improved as well: pgbench base smart | db_size | clients | tps | | tps | +---------+---------+-------+ +-------+ | 22 MB | 1 | 10598 | | 10796 | | 22 MB | 2 | 21257 | | 21336 | | 22 MB | 4 | 41386 | | 41622 | | 22 MB | 8 | 51253 | | 57932 | | 22 MB | 12 | 48570 | | 54000 | | 22 MB | 16 | 46748 | | 55982 | +19.75% | 22 MB | 24 | 44346 | | 55847 | +25.93% | 22 MB | 32 | 43460 | | 54614 | +25.66% | 7484 MB | 1 | 8951 | | 9193 | | 7484 MB | 2 | 19233 | | 19240 | | 7484 MB | 4 | 37239 | | 37302 | | 7484 MB | 8 | 46087 | | 50018 | | 7484 MB | 12 | 42054 | | 48763 | | 7484 MB | 16 | 40765 | | 51633 | +26.66% | 7484 MB | 24 | 37651 | | 52377 | +39.11% | 7484 MB | 32 | 37056 | | 51108 | +37.92% | 15 GB | 1 | 8845 | | 9104 | | 15 GB | 2 | 19094 | | 19162 | | 15 GB | 4 | 36979 | | 36983 | | 15 GB | 8 | 46087 | | 49977 | | 15 GB | 12 | 41901 | | 48591 | | 15 GB | 16 | 40147 | | 50651 | +26.16% | 15 GB | 24 | 37250 | | 52365 | +40.58% | 15 GB | 32 | 36470 | | 50015 | +37.14% Signed-off-by: Michael Wang Cc: Mike Galbraith Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/51D50057.9000809@linux.vnet.ibm.com [ Improved the changelog. ] Signed-off-by: Ingo Molnar --- include/linux/sched.h | 3 +++ kernel/sched/fair.c | 47 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/include/linux/sched.h b/include/linux/sched.h index 6fb22c10bb7..fdd51b1af65 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1275,6 +1275,9 @@ struct task_struct { #ifdef CONFIG_SMP struct llist_node wake_entry; int on_cpu; + struct task_struct *last_wakee; + unsigned long wakee_flips; + unsigned long wakee_flip_decay_ts; #endif int on_rq; diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index f84802846cb..f1039c5db18 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -2331,6 +2331,23 @@ static unsigned long cpu_avg_load_per_task(int cpu) return 0; } +static void record_wakee(struct task_struct *p) +{ + /* + * Rough decay (wiping) for cost saving, don't worry + * about the boundary, really active task won't care + * about the loss. + */ + if (jiffies > current->wakee_flip_decay_ts + HZ) { + current->wakee_flips = 0; + current->wakee_flip_decay_ts = jiffies; + } + + if (current->last_wakee != p) { + current->last_wakee = p; + current->wakee_flips++; + } +} static void task_waking_fair(struct task_struct *p) { @@ -2351,6 +2368,7 @@ static void task_waking_fair(struct task_struct *p) #endif se->vruntime -= min_vruntime; + record_wakee(p); } #ifdef CONFIG_FAIR_GROUP_SCHED @@ -2469,6 +2487,28 @@ static inline unsigned long effective_load(struct task_group *tg, int cpu, #endif +static int wake_wide(struct task_struct *p) +{ + int factor = nr_cpus_node(cpu_to_node(smp_processor_id())); + + /* + * Yeah, it's the switching-frequency, could means many wakee or + * rapidly switch, use factor here will just help to automatically + * adjust the loose-degree, so bigger node will lead to more pull. + */ + if (p->wakee_flips > factor) { + /* + * wakee is somewhat hot, it needs certain amount of cpu + * resource, so if waker is far more hot, prefer to leave + * it alone. + */ + if (current->wakee_flips > (factor * p->wakee_flips)) + return 1; + } + + return 0; +} + static int wake_affine(struct sched_domain *sd, struct task_struct *p, int sync) { s64 this_load, load; @@ -2478,6 +2518,13 @@ static int wake_affine(struct sched_domain *sd, struct task_struct *p, int sync) unsigned long weight; int balanced; + /* + * If we wake multiple tasks be careful to not bounce + * ourselves around too much. + */ + if (wake_wide(p)) + return 0; + idx = sd->wake_idx; this_cpu = smp_processor_id(); prev_cpu = task_cpu(p); From dfeb6201fe99852e5feb6a2853e0253924c7c7f5 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Fri, 20 Dec 2013 21:22:09 +0100 Subject: [PATCH 067/215] sched: Micro-optimize the smart wake-affine logic Smart wake-affine is using node-size as the factor currently, but the overhead of the mask operation is high. Thus, this patch introduce the 'sd_llc_size' percpu variable, which will record the highest cache-share domain size, and make it to be the new factor, in order to reduce the overhead and make it more reasonable. Tested-by: Davidlohr Bueso Tested-by: Michael Wang Signed-off-by: Peter Zijlstra Acked-by: Michael Wang Cc: Mike Galbraith Link: http://lkml.kernel.org/r/51D5008E.6030102@linux.vnet.ibm.com [ Tidied up the changelog. ] Signed-off-by: Ingo Molnar --- kernel/sched/core.c | 7 ++++++- kernel/sched/fair.c | 2 +- kernel/sched/sched.h | 1 + 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index aa1324d7a3a..a73710a5cf7 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -5906,18 +5906,23 @@ static void destroy_sched_domains(struct sched_domain *sd, int cpu) * two cpus are in the same cache domain, see cpus_share_cache(). */ DEFINE_PER_CPU(struct sched_domain *, sd_llc); +DEFINE_PER_CPU(int, sd_llc_size); DEFINE_PER_CPU(int, sd_llc_id); static void update_top_cache_domain(int cpu) { struct sched_domain *sd; int id = cpu; + int size = 1; sd = highest_flag_domain(cpu, SD_SHARE_PKG_RESOURCES); - if (sd) + if (sd) { id = cpumask_first(sched_domain_span(sd)); + size = cpumask_weight(sched_domain_span(sd)); + } rcu_assign_pointer(per_cpu(sd_llc, cpu), sd); + per_cpu(sd_llc_size, cpu) = size; per_cpu(sd_llc_id, cpu) = id; } diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index f1039c5db18..400f838dea1 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -2489,7 +2489,7 @@ static inline unsigned long effective_load(struct task_group *tg, int cpu, static int wake_wide(struct task_struct *p) { - int factor = nr_cpus_node(cpu_to_node(smp_processor_id())); + int factor = this_cpu_read(sd_llc_size); /* * Yeah, it's the switching-frequency, could means many wakee or diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index 3ae7dc7438d..b9c312a4db7 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -531,6 +531,7 @@ static inline struct sched_domain *highest_flag_domain(int cpu, int flag) } DECLARE_PER_CPU(struct sched_domain *, sd_llc); +DECLARE_PER_CPU(int, sd_llc_size); DECLARE_PER_CPU(int, sd_llc_id); #endif /* CONFIG_SMP */ From 294ed2c8d45e9a8b2511f13e6cff20b310727950 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Fri, 20 Dec 2013 21:25:51 +0100 Subject: [PATCH 068/215] Aroma : change the aroma loading image --- .../com/google/android/aroma/glitch.png | Bin 196355 -> 223763 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/release/aroma/META-INF/com/google/android/aroma/glitch.png b/release/aroma/META-INF/com/google/android/aroma/glitch.png index ed14cd64c03141902b9737b056520f748f3ea50c..c2c0640574d5dc0687b14f7e758bfe6117a5ebe2 100644 GIT binary patch literal 223763 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

      1. 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 Date: Fri, 20 Dec 2013 21:31:32 +0100 Subject: [PATCH 069/215] defconfig : Add GENERIC_SMP_IDLE_THREAD --- arch/arm/configs/flo_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/flo_defconfig b/arch/arm/configs/flo_defconfig index 5494f0395b9..04c5a8cdb57 100644 --- a/arch/arm/configs/flo_defconfig +++ b/arch/arm/configs/flo_defconfig @@ -168,6 +168,7 @@ CONFIG_HAVE_KRETPROBES=y CONFIG_HAVE_DMA_ATTRS=y CONFIG_HAVE_DMA_CONTIGUOUS=y CONFIG_USE_GENERIC_SMP_HELPERS=y +CONFIG_GENERIC_SMP_IDLE_THREAD=y CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y CONFIG_HAVE_CLK=y CONFIG_HAVE_DMA_API_DEBUG=y From 8f7edee7e85da62fc31a7aec1def0b9ca6e29262 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Fri, 20 Dec 2013 21:58:00 +0100 Subject: [PATCH 070/215] cpuinit: get rid of __cpuinit in the new smpboot.c Signed-off-by: Tk-Glitch --- kernel/smpboot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/smpboot.c b/kernel/smpboot.c index 02fc5c93367..905b27482eb 100644 --- a/kernel/smpboot.c +++ b/kernel/smpboot.c @@ -24,7 +24,7 @@ */ static DEFINE_PER_CPU(struct task_struct *, idle_threads); -struct task_struct * __cpuinit idle_thread_get(unsigned int cpu) +struct task_struct * idle_thread_get(unsigned int cpu) { struct task_struct *tsk = per_cpu(idle_threads, cpu); From 02617d855d6d6f47d68e5f3a5892be6657c65033 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Sat, 21 Dec 2013 09:58:49 +0100 Subject: [PATCH 071/215] Linux 3.4.2 --- Makefile | 2 +- arch/arm/Kconfig | 2 +- arch/arm/mach-ixp4xx/common.c | 48 ++++++++- arch/arm/mach-ixp4xx/include/mach/gpio.h | 79 +------------- arch/x86/kernel/nmi.c | 6 +- arch/x86/kernel/ptrace.c | 6 -- arch/x86/xen/enlighten.c | 3 + drivers/acpi/battery.c | 10 +- drivers/atm/solos-pci.c | 4 +- drivers/gpu/drm/i915/intel_display.c | 2 +- drivers/gpu/drm/i915/intel_dp.c | 17 ++- drivers/gpu/drm/i915/intel_lvds.c | 8 ++ drivers/gpu/drm/i915/intel_sdvo.c | 12 ++- drivers/gpu/drm/i915/intel_sdvo_regs.h | 5 + drivers/gpu/drm/i915/intel_tv.c | 53 +++++++++ drivers/gpu/drm/radeon/evergreen.c | 18 +++- drivers/gpu/drm/radeon/evergreend.h | 1 + drivers/gpu/drm/radeon/ni.c | 32 ++++-- drivers/gpu/drm/radeon/r600_audio.c | 5 +- drivers/gpu/drm/radeon/radeon_atombios.c | 4 +- drivers/gpu/drm/radeon/radeon_cs.c | 31 +++--- drivers/gpu/drm/radeon/radeon_gart.c | 19 ++-- drivers/gpu/drm/radeon/rv770.c | 10 +- drivers/gpu/drm/radeon/rv770d.h | 1 + drivers/gpu/drm/ttm/ttm_bo.c | 1 + drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c | 2 +- drivers/iommu/amd_iommu.c | 108 ++++++++++++------- drivers/iommu/amd_iommu_init.c | 13 +-- drivers/iommu/amd_iommu_types.h | 3 + drivers/mtd/Kconfig | 2 +- drivers/mtd/devices/block2mtd.c | 1 - drivers/mtd/nand/mxc_nand.c | 12 +-- drivers/mtd/nand/nand_bbt.c | 1 + drivers/net/ethernet/freescale/fec_mpc52xx.c | 2 +- drivers/net/usb/asix.c | 3 +- drivers/net/wireless/ath/ath9k/xmit.c | 16 +-- drivers/net/wireless/iwlwifi/iwl-2000.c | 4 +- drivers/net/wireless/iwlwifi/iwl-6000.c | 6 +- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 1 + drivers/net/wireless/wl1251/sdio.c | 2 +- drivers/net/wireless/wl1251/spi.c | 3 +- drivers/scsi/scsi_lib.c | 11 +- drivers/scsi/scsi_wait_scan.c | 2 +- fs/attr.c | 5 + fs/cifs/cifsglob.h | 1 + fs/cifs/cifsproto.h | 6 +- fs/cifs/cifssmb.c | 12 +-- fs/cifs/file.c | 57 +++++----- fs/cifs/readdir.c | 15 ++- fs/exofs/super.c | 2 +- fs/ext4/ialloc.c | 10 +- fs/ext4/ioctl.c | 13 ++- fs/ext4/mballoc.c | 6 +- fs/ext4/resize.c | 2 + fs/ext4/super.c | 4 +- fs/namespace.c | 3 +- fs/nfs/idmap.c | 10 +- fs/nfs/nfs4proc.c | 2 + fs/proc/base.c | 17 +-- fs/proc/task_mmu.c | 2 +- include/drm/drm_pciids.h | 17 ++- include/linux/Kbuild | 1 + include/linux/kernel-page-flags.h | 4 + include/linux/radix-tree.h | 5 +- include/linux/skbuff.h | 2 - include/net/dst.h | 1 + kernel/fork.c | 3 +- lib/radix-tree.c | 3 + mm/hugetlb.c | 29 +++-- mm/vmscan.c | 2 +- net/ipv4/esp4.c | 24 ++--- net/ipv6/esp6.c | 18 ++-- net/ipv6/ip6_output.c | 68 ++++++++---- net/l2tp/l2tp_ip.c | 30 ++++-- net/mac80211/util.c | 12 +-- net/sunrpc/clnt.c | 2 + net/sunrpc/xprt.c | 5 +- net/xfrm/xfrm_policy.c | 3 + sound/usb/pcm.c | 3 + tools/vm/page-types.c | 28 +---- 80 files changed, 617 insertions(+), 381 deletions(-) diff --git a/Makefile b/Makefile index 1e67a0bf464..63ac07f255c 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 4 -SUBLEVEL = 1 +SUBLEVEL = 2 EXTRAVERSION = NAME = Saber-toothed Squirrel diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 69b94144ee5..d7e3e4364f0 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -575,7 +575,7 @@ config ARCH_IXP4XX select ARCH_HAS_DMA_SET_COHERENT_MASK select CLKSRC_MMIO select CPU_XSCALE - select GENERIC_GPIO + select ARCH_REQUIRE_GPIOLIB select GENERIC_CLOCKEVENTS select MIGHT_HAVE_PCI select NEED_MACH_IO_H diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c index ebbd7fc90eb..a9f80943d01 100644 --- a/arch/arm/mach-ixp4xx/common.c +++ b/arch/arm/mach-ixp4xx/common.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -107,7 +108,7 @@ static signed char irq2gpio[32] = { 7, 8, 9, 10, 11, 12, -1, -1, }; -int gpio_to_irq(int gpio) +static int ixp4xx_gpio_to_irq(struct gpio_chip *chip, unsigned gpio) { int irq; @@ -117,7 +118,6 @@ int gpio_to_irq(int gpio) } return -EINVAL; } -EXPORT_SYMBOL(gpio_to_irq); int irq_to_gpio(unsigned int irq) { @@ -383,12 +383,56 @@ static struct platform_device *ixp46x_devices[] __initdata = { unsigned long ixp4xx_exp_bus_size; EXPORT_SYMBOL(ixp4xx_exp_bus_size); +static int ixp4xx_gpio_direction_input(struct gpio_chip *chip, unsigned gpio) +{ + gpio_line_config(gpio, IXP4XX_GPIO_IN); + + return 0; +} + +static int ixp4xx_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, + int level) +{ + gpio_line_set(gpio, level); + gpio_line_config(gpio, IXP4XX_GPIO_OUT); + + return 0; +} + +static int ixp4xx_gpio_get_value(struct gpio_chip *chip, unsigned gpio) +{ + int value; + + gpio_line_get(gpio, &value); + + return value; +} + +static void ixp4xx_gpio_set_value(struct gpio_chip *chip, unsigned gpio, + int value) +{ + gpio_line_set(gpio, value); +} + +static struct gpio_chip ixp4xx_gpio_chip = { + .label = "IXP4XX_GPIO_CHIP", + .direction_input = ixp4xx_gpio_direction_input, + .direction_output = ixp4xx_gpio_direction_output, + .get = ixp4xx_gpio_get_value, + .set = ixp4xx_gpio_set_value, + .to_irq = ixp4xx_gpio_to_irq, + .base = 0, + .ngpio = 16, +}; + void __init ixp4xx_sys_init(void) { ixp4xx_exp_bus_size = SZ_16M; platform_add_devices(ixp4xx_devices, ARRAY_SIZE(ixp4xx_devices)); + gpiochip_add(&ixp4xx_gpio_chip); + if (cpu_is_ixp46x()) { int region; diff --git a/arch/arm/mach-ixp4xx/include/mach/gpio.h b/arch/arm/mach-ixp4xx/include/mach/gpio.h index 83d6b4ed60b..ef37f2635b0 100644 --- a/arch/arm/mach-ixp4xx/include/mach/gpio.h +++ b/arch/arm/mach-ixp4xx/include/mach/gpio.h @@ -1,79 +1,2 @@ -/* - * arch/arm/mach-ixp4xx/include/mach/gpio.h - * - * IXP4XX GPIO wrappers for arch-neutral GPIO calls - * - * Written by Milan Svoboda - * Based on PXA implementation by Philipp Zabel - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#ifndef __ASM_ARCH_IXP4XX_GPIO_H -#define __ASM_ARCH_IXP4XX_GPIO_H - -#include -#include - -#define __ARM_GPIOLIB_COMPLEX - -static inline int gpio_request(unsigned gpio, const char *label) -{ - return 0; -} - -static inline void gpio_free(unsigned gpio) -{ - might_sleep(); - - return; -} - -static inline int gpio_direction_input(unsigned gpio) -{ - gpio_line_config(gpio, IXP4XX_GPIO_IN); - return 0; -} - -static inline int gpio_direction_output(unsigned gpio, int level) -{ - gpio_line_set(gpio, level); - gpio_line_config(gpio, IXP4XX_GPIO_OUT); - return 0; -} - -static inline int gpio_get_value(unsigned gpio) -{ - int value; - - gpio_line_get(gpio, &value); - - return value; -} - -static inline void gpio_set_value(unsigned gpio, int value) -{ - gpio_line_set(gpio, value); -} - -#include /* cansleep wrappers */ - -extern int gpio_to_irq(int gpio); -#define gpio_to_irq gpio_to_irq -extern int irq_to_gpio(unsigned int irq); - -#endif +/* empty */ diff --git a/arch/x86/kernel/nmi.c b/arch/x86/kernel/nmi.c index 47acaf31916..32856fa4384 100644 --- a/arch/x86/kernel/nmi.c +++ b/arch/x86/kernel/nmi.c @@ -491,14 +491,16 @@ static inline void nmi_nesting_preprocess(struct pt_regs *regs) */ if (unlikely(is_debug_stack(regs->sp))) { debug_stack_set_zero(); - __get_cpu_var(update_debug_stack) = 1; + this_cpu_write(update_debug_stack, 1); } } static inline void nmi_nesting_postprocess(void) { - if (unlikely(__get_cpu_var(update_debug_stack))) + if (unlikely(this_cpu_read(update_debug_stack))) { debug_stack_reset(); + this_cpu_write(update_debug_stack, 0); + } } #endif diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index 685845cf16e..cf1178332bc 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c @@ -1211,12 +1211,6 @@ static long x32_arch_ptrace(struct task_struct *child, 0, sizeof(struct user_i387_struct), datap); - /* normal 64bit interface to access TLS data. - Works just like arch_prctl, except that the arguments - are reversed. */ - case PTRACE_ARCH_PRCTL: - return do_arch_prctl(child, data, addr); - default: return compat_ptrace_request(child, request, addr, data); } diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index ad6c4e06498..c4c183d0ba9 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -1106,7 +1106,10 @@ static const struct pv_cpu_ops xen_cpu_ops __initconst = { .wbinvd = native_wbinvd, .read_msr = native_read_msr_safe, + .rdmsr_regs = native_rdmsr_safe_regs, .write_msr = xen_write_msr_safe, + .wrmsr_regs = native_wrmsr_safe_regs, + .read_tsc = native_read_tsc, .read_pmc = native_read_pmc, diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 86933ca8b47..7dd3f9fb9f3 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -643,11 +643,19 @@ static int acpi_battery_update(struct acpi_battery *battery) static void acpi_battery_refresh(struct acpi_battery *battery) { + int power_unit; + if (!battery->bat.dev) return; + power_unit = battery->power_unit; + acpi_battery_get_info(battery); - /* The battery may have changed its reporting units. */ + + if (power_unit == battery->power_unit) + return; + + /* The battery has changed its reporting units. */ sysfs_remove_battery(battery); sysfs_add_battery(battery); } diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index e8cd652d201..98510931c81 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c @@ -984,6 +984,7 @@ static uint32_t fpga_tx(struct solos_card *card) } else if (skb && card->using_dma) { SKB_CB(skb)->dma_addr = pci_map_single(card->dev, skb->data, skb->len, PCI_DMA_TODEVICE); + card->tx_skb[port] = skb; iowrite32(SKB_CB(skb)->dma_addr, card->config_regs + TX_DMA_ADDR(port)); } @@ -1152,7 +1153,8 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id) db_fpga_upgrade = db_firmware_upgrade = 0; } - if (card->fpga_version >= DMA_SUPPORTED){ + if (card->fpga_version >= DMA_SUPPORTED) { + pci_set_master(dev); card->using_dma = 1; } else { card->using_dma = 0; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 79a7de1f31b..d4d162f6bab 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -8368,7 +8368,7 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv) I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10); I915_WRITE(GEN6_RP_CONTROL, GEN6_RP_MEDIA_TURBO | - GEN6_RP_MEDIA_HW_MODE | + GEN6_RP_MEDIA_HW_NORMAL_MODE | GEN6_RP_MEDIA_IS_GFX | GEN6_RP_ENABLE | GEN6_RP_UP_BUSY_AVG | diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 4b637919f74..1d19408192b 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1148,10 +1148,10 @@ static void ironlake_edp_panel_off(struct intel_dp *intel_dp) DRM_DEBUG_KMS("Turn eDP power off\n"); - WARN(intel_dp->want_panel_vdd, "Cannot turn power off while VDD is on\n"); + WARN(!intel_dp->want_panel_vdd, "Need VDD to turn off panel\n"); pp = ironlake_get_pp_control(dev_priv); - pp &= ~(POWER_TARGET_ON | EDP_FORCE_VDD | PANEL_POWER_RESET | EDP_BLC_ENABLE); + pp &= ~(POWER_TARGET_ON | PANEL_POWER_RESET | EDP_BLC_ENABLE); I915_WRITE(PCH_PP_CONTROL, pp); POSTING_READ(PCH_PP_CONTROL); @@ -1259,18 +1259,16 @@ static void intel_dp_prepare(struct drm_encoder *encoder) { struct intel_dp *intel_dp = enc_to_intel_dp(encoder); + + /* Make sure the panel is off before trying to change the mode. But also + * ensure that we have vdd while we switch off the panel. */ + ironlake_edp_panel_vdd_on(intel_dp); ironlake_edp_backlight_off(intel_dp); ironlake_edp_panel_off(intel_dp); - /* Wake up the sink first */ - ironlake_edp_panel_vdd_on(intel_dp); intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); intel_dp_link_down(intel_dp); ironlake_edp_panel_vdd_off(intel_dp, false); - - /* Make sure the panel is off before trying to - * change the mode - */ } static void intel_dp_commit(struct drm_encoder *encoder) @@ -1302,10 +1300,11 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode) uint32_t dp_reg = I915_READ(intel_dp->output_reg); if (mode != DRM_MODE_DPMS_ON) { + /* Switching the panel off requires vdd. */ + ironlake_edp_panel_vdd_on(intel_dp); ironlake_edp_backlight_off(intel_dp); ironlake_edp_panel_off(intel_dp); - ironlake_edp_panel_vdd_on(intel_dp); intel_dp_sink_dpms(intel_dp, mode); intel_dp_link_down(intel_dp); ironlake_edp_panel_vdd_off(intel_dp, false); diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 9c71183629c..9fadd643181 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -745,6 +745,14 @@ static const struct dmi_system_id intel_no_lvds[] = { DMI_MATCH(DMI_BOARD_NAME, "AT5NM10T-I"), }, }, + { + .callback = intel_no_lvds_dmi_callback, + .ident = "Hewlett-Packard HP t5740e Thin Client", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP t5740e Thin Client"), + }, + }, { .callback = intel_no_lvds_dmi_callback, .ident = "Hewlett-Packard t5745", diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index ae5e748f39b..eea58c6cb05 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -769,10 +769,12 @@ static void intel_sdvo_get_dtd_from_mode(struct intel_sdvo_dtd *dtd, ((v_sync_len & 0x30) >> 4); dtd->part2.dtd_flags = 0x18; + if (mode->flags & DRM_MODE_FLAG_INTERLACE) + dtd->part2.dtd_flags |= DTD_FLAG_INTERLACE; if (mode->flags & DRM_MODE_FLAG_PHSYNC) - dtd->part2.dtd_flags |= 0x2; + dtd->part2.dtd_flags |= DTD_FLAG_HSYNC_POSITIVE; if (mode->flags & DRM_MODE_FLAG_PVSYNC) - dtd->part2.dtd_flags |= 0x4; + dtd->part2.dtd_flags |= DTD_FLAG_VSYNC_POSITIVE; dtd->part2.sdvo_flags = 0; dtd->part2.v_sync_off_high = v_sync_offset & 0xc0; @@ -806,9 +808,11 @@ static void intel_sdvo_get_mode_from_dtd(struct drm_display_mode * mode, mode->clock = dtd->part1.clock * 10; mode->flags &= ~(DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC); - if (dtd->part2.dtd_flags & 0x2) + if (dtd->part2.dtd_flags & DTD_FLAG_INTERLACE) + mode->flags |= DRM_MODE_FLAG_INTERLACE; + if (dtd->part2.dtd_flags & DTD_FLAG_HSYNC_POSITIVE) mode->flags |= DRM_MODE_FLAG_PHSYNC; - if (dtd->part2.dtd_flags & 0x4) + if (dtd->part2.dtd_flags & DTD_FLAG_VSYNC_POSITIVE) mode->flags |= DRM_MODE_FLAG_PVSYNC; } diff --git a/drivers/gpu/drm/i915/intel_sdvo_regs.h b/drivers/gpu/drm/i915/intel_sdvo_regs.h index 6b7b22f4d63..9d030142ee4 100644 --- a/drivers/gpu/drm/i915/intel_sdvo_regs.h +++ b/drivers/gpu/drm/i915/intel_sdvo_regs.h @@ -61,6 +61,11 @@ struct intel_sdvo_caps { u16 output_flags; } __attribute__((packed)); +/* Note: SDVO detailed timing flags match EDID misc flags. */ +#define DTD_FLAG_HSYNC_POSITIVE (1 << 1) +#define DTD_FLAG_VSYNC_POSITIVE (1 << 2) +#define DTD_FLAG_INTERLACE (1 << 7) + /** This matches the EDID DTD structure, more or less */ struct intel_sdvo_dtd { struct { diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index 05f765ef546..c82b1d4fd24 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -673,6 +673,54 @@ static const struct tv_mode tv_modes[] = { .filter_table = filter_table, }, + { + .name = "480p", + .clock = 107520, + .refresh = 59940, + .oversample = TV_OVERSAMPLE_4X, + .component_only = 1, + + .hsync_end = 64, .hblank_end = 122, + .hblank_start = 842, .htotal = 857, + + .progressive = true, .trilevel_sync = false, + + .vsync_start_f1 = 12, .vsync_start_f2 = 12, + .vsync_len = 12, + + .veq_ena = false, + + .vi_end_f1 = 44, .vi_end_f2 = 44, + .nbr_end = 479, + + .burst_ena = false, + + .filter_table = filter_table, + }, + { + .name = "576p", + .clock = 107520, + .refresh = 50000, + .oversample = TV_OVERSAMPLE_4X, + .component_only = 1, + + .hsync_end = 64, .hblank_end = 139, + .hblank_start = 859, .htotal = 863, + + .progressive = true, .trilevel_sync = false, + + .vsync_start_f1 = 10, .vsync_start_f2 = 10, + .vsync_len = 10, + + .veq_ena = false, + + .vi_end_f1 = 48, .vi_end_f2 = 48, + .nbr_end = 575, + + .burst_ena = false, + + .filter_table = filter_table, + }, { .name = "720p@60Hz", .clock = 148800, @@ -1185,6 +1233,11 @@ intel_tv_detect_type(struct intel_tv *intel_tv, I915_WRITE(TV_DAC, save_tv_dac & ~TVDAC_STATE_CHG_EN); I915_WRITE(TV_CTL, save_tv_ctl); + POSTING_READ(TV_CTL); + + /* For unknown reasons the hw barfs if we don't do this vblank wait. */ + intel_wait_for_vblank(intel_tv->base.base.dev, + to_intel_crtc(intel_tv->base.base.crtc)->pipe); /* Restore interrupt config */ if (connector->polled & DRM_CONNECTOR_POLL_HPD) { diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index cfa372cb1cb..51e8d086767 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -1029,6 +1029,11 @@ int evergreen_pcie_gart_enable(struct radeon_device *rdev) WREG32(MC_VM_MD_L1_TLB0_CNTL, tmp); WREG32(MC_VM_MD_L1_TLB1_CNTL, tmp); WREG32(MC_VM_MD_L1_TLB2_CNTL, tmp); + if ((rdev->family == CHIP_JUNIPER) || + (rdev->family == CHIP_CYPRESS) || + (rdev->family == CHIP_HEMLOCK) || + (rdev->family == CHIP_BARTS)) + WREG32(MC_VM_MD_L1_TLB3_CNTL, tmp); } WREG32(MC_VM_MB_L1_TLB0_CNTL, tmp); WREG32(MC_VM_MB_L1_TLB1_CNTL, tmp); @@ -2136,9 +2141,12 @@ static void evergreen_gpu_init(struct radeon_device *rdev) /* num banks is 8 on all fusion asics. 0 = 4, 1 = 8, 2 = 16 */ if (rdev->flags & RADEON_IS_IGP) rdev->config.evergreen.tile_config |= 1 << 4; - else - rdev->config.evergreen.tile_config |= - ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) << 4; + else { + if ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) + rdev->config.evergreen.tile_config |= 1 << 4; + else + rdev->config.evergreen.tile_config |= 0 << 4; + } rdev->config.evergreen.tile_config |= ((mc_arb_ramcfg & BURSTLENGTH_MASK) >> BURSTLENGTH_SHIFT) << 8; rdev->config.evergreen.tile_config |= @@ -2170,9 +2178,9 @@ static void evergreen_gpu_init(struct radeon_device *rdev) WREG32(CC_SYS_RB_BACKEND_DISABLE, rb); WREG32(GC_USER_RB_BACKEND_DISABLE, rb); WREG32(CC_GC_SHADER_PIPE_CONFIG, sp); - } + } - grbm_gfx_index |= SE_BROADCAST_WRITES; + grbm_gfx_index = INSTANCE_BROADCAST_WRITES | SE_BROADCAST_WRITES; WREG32(GRBM_GFX_INDEX, grbm_gfx_index); WREG32(RLC_GFX_INDEX, grbm_gfx_index); diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h index b4eefc355f1..a5b88aad834 100644 --- a/drivers/gpu/drm/radeon/evergreend.h +++ b/drivers/gpu/drm/radeon/evergreend.h @@ -232,6 +232,7 @@ #define MC_VM_MD_L1_TLB0_CNTL 0x2654 #define MC_VM_MD_L1_TLB1_CNTL 0x2658 #define MC_VM_MD_L1_TLB2_CNTL 0x265C +#define MC_VM_MD_L1_TLB3_CNTL 0x2698 #define FUS_MC_VM_MD_L1_TLB0_CNTL 0x265C #define FUS_MC_VM_MD_L1_TLB1_CNTL 0x2660 diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index a48ca53fcd6..ad0a38007de 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c @@ -657,15 +657,28 @@ static void cayman_gpu_init(struct radeon_device *rdev) rdev->config.cayman.max_pipes_per_simd = 4; rdev->config.cayman.max_tile_pipes = 2; if ((rdev->pdev->device == 0x9900) || - (rdev->pdev->device == 0x9901)) { + (rdev->pdev->device == 0x9901) || + (rdev->pdev->device == 0x9905) || + (rdev->pdev->device == 0x9906) || + (rdev->pdev->device == 0x9907) || + (rdev->pdev->device == 0x9908) || + (rdev->pdev->device == 0x9909) || + (rdev->pdev->device == 0x9910) || + (rdev->pdev->device == 0x9917)) { rdev->config.cayman.max_simds_per_se = 6; rdev->config.cayman.max_backends_per_se = 2; } else if ((rdev->pdev->device == 0x9903) || - (rdev->pdev->device == 0x9904)) { + (rdev->pdev->device == 0x9904) || + (rdev->pdev->device == 0x990A) || + (rdev->pdev->device == 0x9913) || + (rdev->pdev->device == 0x9918)) { rdev->config.cayman.max_simds_per_se = 4; rdev->config.cayman.max_backends_per_se = 2; - } else if ((rdev->pdev->device == 0x9990) || - (rdev->pdev->device == 0x9991)) { + } else if ((rdev->pdev->device == 0x9919) || + (rdev->pdev->device == 0x9990) || + (rdev->pdev->device == 0x9991) || + (rdev->pdev->device == 0x9994) || + (rdev->pdev->device == 0x99A0)) { rdev->config.cayman.max_simds_per_se = 3; rdev->config.cayman.max_backends_per_se = 1; } else { @@ -865,10 +878,13 @@ static void cayman_gpu_init(struct radeon_device *rdev) /* num banks is 8 on all fusion asics. 0 = 4, 1 = 8, 2 = 16 */ if (rdev->flags & RADEON_IS_IGP) - rdev->config.evergreen.tile_config |= 1 << 4; - else - rdev->config.cayman.tile_config |= - ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) << 4; + rdev->config.cayman.tile_config |= 1 << 4; + else { + if ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) + rdev->config.cayman.tile_config |= 1 << 4; + else + rdev->config.cayman.tile_config |= 0 << 4; + } rdev->config.cayman.tile_config |= ((gb_addr_config & PIPE_INTERLEAVE_SIZE_MASK) >> PIPE_INTERLEAVE_SIZE_SHIFT) << 8; rdev->config.cayman.tile_config |= diff --git a/drivers/gpu/drm/radeon/r600_audio.c b/drivers/gpu/drm/radeon/r600_audio.c index ba66f3093d4..24e39399367 100644 --- a/drivers/gpu/drm/radeon/r600_audio.c +++ b/drivers/gpu/drm/radeon/r600_audio.c @@ -239,6 +239,7 @@ void r600_audio_set_clock(struct drm_encoder *encoder, int clock) struct radeon_device *rdev = dev->dev_private; struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; + struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); int base_rate = 48000; switch (radeon_encoder->encoder_id) { @@ -264,8 +265,8 @@ void r600_audio_set_clock(struct drm_encoder *encoder, int clock) WREG32(EVERGREEN_AUDIO_PLL1_DIV, clock * 10); WREG32(EVERGREEN_AUDIO_PLL1_UNK, 0x00000071); - /* Some magic trigger or src sel? */ - WREG32_P(0x5ac, 0x01, ~0x77); + /* Select DTO source */ + WREG32(0x5ac, radeon_crtc->crtc_id); } else { switch (dig->dig_encoder) { case 0: diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index f6e69b8c06c..b1e3820df36 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -444,7 +444,9 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev, */ if ((dev->pdev->device == 0x9498) && (dev->pdev->subsystem_vendor == 0x1682) && - (dev->pdev->subsystem_device == 0x2452)) { + (dev->pdev->subsystem_device == 0x2452) && + (i2c_bus->valid == false) && + !(supported_device & (ATOM_DEVICE_TV_SUPPORT | ATOM_DEVICE_CV_SUPPORT))) { struct radeon_device *rdev = dev->dev_private; *i2c_bus = radeon_lookup_i2c_gpio(rdev, 0x93); } diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index 5cac8327833..2418cf6da1c 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c @@ -158,6 +158,7 @@ static int radeon_cs_sync_rings(struct radeon_cs_parser *p) return 0; } +/* XXX: note that this is called from the legacy UMS CS ioctl as well */ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data) { struct drm_radeon_cs *cs = data; @@ -252,22 +253,24 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data) } } - if ((p->cs_flags & RADEON_CS_USE_VM) && - !p->rdev->vm_manager.enabled) { - DRM_ERROR("VM not active on asic!\n"); - return -EINVAL; - } - - /* we only support VM on SI+ */ - if ((p->rdev->family >= CHIP_TAHITI) && - ((p->cs_flags & RADEON_CS_USE_VM) == 0)) { - DRM_ERROR("VM required on SI+!\n"); - return -EINVAL; - } + /* these are KMS only */ + if (p->rdev) { + if ((p->cs_flags & RADEON_CS_USE_VM) && + !p->rdev->vm_manager.enabled) { + DRM_ERROR("VM not active on asic!\n"); + return -EINVAL; + } - if (radeon_cs_get_ring(p, ring, priority)) - return -EINVAL; + /* we only support VM on SI+ */ + if ((p->rdev->family >= CHIP_TAHITI) && + ((p->cs_flags & RADEON_CS_USE_VM) == 0)) { + DRM_ERROR("VM required on SI+!\n"); + return -EINVAL; + } + if (radeon_cs_get_ring(p, ring, priority)) + return -EINVAL; + } /* deal with non-vm */ if ((p->chunk_ib_idx != -1) && diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c index c58a036233f..62050f52194 100644 --- a/drivers/gpu/drm/radeon/radeon_gart.c +++ b/drivers/gpu/drm/radeon/radeon_gart.c @@ -478,12 +478,18 @@ int radeon_vm_bo_add(struct radeon_device *rdev, mutex_lock(&vm->mutex); if (last_pfn > vm->last_pfn) { - /* grow va space 32M by 32M */ - unsigned align = ((32 << 20) >> 12) - 1; + /* release mutex and lock in right order */ + mutex_unlock(&vm->mutex); radeon_mutex_lock(&rdev->cs_mutex); - radeon_vm_unbind_locked(rdev, vm); + mutex_lock(&vm->mutex); + /* and check again */ + if (last_pfn > vm->last_pfn) { + /* grow va space 32M by 32M */ + unsigned align = ((32 << 20) >> 12) - 1; + radeon_vm_unbind_locked(rdev, vm); + vm->last_pfn = (last_pfn + align) & ~align; + } radeon_mutex_unlock(&rdev->cs_mutex); - vm->last_pfn = (last_pfn + align) & ~align; } head = &vm->va; last_offset = 0; @@ -597,8 +603,8 @@ int radeon_vm_bo_rmv(struct radeon_device *rdev, if (bo_va == NULL) return 0; - mutex_lock(&vm->mutex); radeon_mutex_lock(&rdev->cs_mutex); + mutex_lock(&vm->mutex); radeon_vm_bo_update_pte(rdev, vm, bo, NULL); radeon_mutex_unlock(&rdev->cs_mutex); list_del(&bo_va->vm_list); @@ -643,9 +649,8 @@ void radeon_vm_fini(struct radeon_device *rdev, struct radeon_vm *vm) struct radeon_bo_va *bo_va, *tmp; int r; - mutex_lock(&vm->mutex); - radeon_mutex_lock(&rdev->cs_mutex); + mutex_lock(&vm->mutex); radeon_vm_unbind_locked(rdev, vm); radeon_mutex_unlock(&rdev->cs_mutex); diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index cdab1aeaed6..80a292bc457 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -151,6 +151,8 @@ int rv770_pcie_gart_enable(struct radeon_device *rdev) WREG32(MC_VM_MD_L1_TLB0_CNTL, tmp); WREG32(MC_VM_MD_L1_TLB1_CNTL, tmp); WREG32(MC_VM_MD_L1_TLB2_CNTL, tmp); + if (rdev->family == CHIP_RV740) + WREG32(MC_VM_MD_L1_TLB3_CNTL, tmp); WREG32(MC_VM_MB_L1_TLB0_CNTL, tmp); WREG32(MC_VM_MB_L1_TLB1_CNTL, tmp); WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp); @@ -689,8 +691,12 @@ static void rv770_gpu_init(struct radeon_device *rdev) if (rdev->family == CHIP_RV770) gb_tiling_config |= BANK_TILING(1); - else - gb_tiling_config |= BANK_TILING((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT); + else { + if ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) + gb_tiling_config |= BANK_TILING(1); + else + gb_tiling_config |= BANK_TILING(0); + } rdev->config.rv770.tiling_nbanks = 4 << ((gb_tiling_config >> 4) & 0x3); gb_tiling_config |= GROUP_SIZE((mc_arb_ramcfg & BURSTLENGTH_MASK) >> BURSTLENGTH_SHIFT); if ((mc_arb_ramcfg & BURSTLENGTH_MASK) >> BURSTLENGTH_SHIFT) diff --git a/drivers/gpu/drm/radeon/rv770d.h b/drivers/gpu/drm/radeon/rv770d.h index 79fa588e9ed..75380927e9c 100644 --- a/drivers/gpu/drm/radeon/rv770d.h +++ b/drivers/gpu/drm/radeon/rv770d.h @@ -174,6 +174,7 @@ #define MC_VM_MD_L1_TLB0_CNTL 0x2654 #define MC_VM_MD_L1_TLB1_CNTL 0x2658 #define MC_VM_MD_L1_TLB2_CNTL 0x265C +#define MC_VM_MD_L1_TLB3_CNTL 0x2698 #define MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR 0x203C #define MC_VM_SYSTEM_APERTURE_HIGH_ADDR 0x2038 #define MC_VM_SYSTEM_APERTURE_LOW_ADDR 0x2034 diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 1f5c67c579c..18434186ed1 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -1821,6 +1821,7 @@ static int ttm_bo_swapout(struct ttm_mem_shrink *shrink) spin_unlock(&glob->lru_lock); (void) ttm_bo_cleanup_refs(bo, false, false, false); kref_put(&bo->list_kref, ttm_bo_release_list); + spin_lock(&glob->lru_lock); continue; } diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c b/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c index 51c9ba5cd2f..21ee7822656 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c @@ -66,7 +66,7 @@ static int vmw_gmr2_bind(struct vmw_private *dev_priv, cmd += sizeof(remap_cmd) / sizeof(uint32); for (i = 0; i < num_pages; ++i) { - if (VMW_PPN_SIZE > 4) + if (VMW_PPN_SIZE <= 4) *cmd = page_to_pfn(*pages++); else *((uint64_t *)cmd) = page_to_pfn(*pages++); diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index a5bee8e2dfc..a2e418cba0f 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -450,12 +450,27 @@ static void dump_command(unsigned long phys_addr) static void iommu_print_event(struct amd_iommu *iommu, void *__evt) { - u32 *event = __evt; - int type = (event[1] >> EVENT_TYPE_SHIFT) & EVENT_TYPE_MASK; - int devid = (event[0] >> EVENT_DEVID_SHIFT) & EVENT_DEVID_MASK; - int domid = (event[1] >> EVENT_DOMID_SHIFT) & EVENT_DOMID_MASK; - int flags = (event[1] >> EVENT_FLAGS_SHIFT) & EVENT_FLAGS_MASK; - u64 address = (u64)(((u64)event[3]) << 32) | event[2]; + int type, devid, domid, flags; + volatile u32 *event = __evt; + int count = 0; + u64 address; + +retry: + type = (event[1] >> EVENT_TYPE_SHIFT) & EVENT_TYPE_MASK; + devid = (event[0] >> EVENT_DEVID_SHIFT) & EVENT_DEVID_MASK; + domid = (event[1] >> EVENT_DOMID_SHIFT) & EVENT_DOMID_MASK; + flags = (event[1] >> EVENT_FLAGS_SHIFT) & EVENT_FLAGS_MASK; + address = (u64)(((u64)event[3]) << 32) | event[2]; + + if (type == 0) { + /* Did we hit the erratum? */ + if (++count == LOOP_TIMEOUT) { + pr_err("AMD-Vi: No event written to event log\n"); + return; + } + udelay(1); + goto retry; + } printk(KERN_ERR "AMD-Vi: Event logged ["); @@ -508,6 +523,8 @@ static void iommu_print_event(struct amd_iommu *iommu, void *__evt) default: printk(KERN_ERR "UNKNOWN type=0x%02x]\n", type); } + + memset(__evt, 0, 4 * sizeof(u32)); } static void iommu_poll_events(struct amd_iommu *iommu) @@ -530,26 +547,12 @@ static void iommu_poll_events(struct amd_iommu *iommu) spin_unlock_irqrestore(&iommu->lock, flags); } -static void iommu_handle_ppr_entry(struct amd_iommu *iommu, u32 head) +static void iommu_handle_ppr_entry(struct amd_iommu *iommu, u64 *raw) { struct amd_iommu_fault fault; - volatile u64 *raw; - int i; INC_STATS_COUNTER(pri_requests); - raw = (u64 *)(iommu->ppr_log + head); - - /* - * Hardware bug: Interrupt may arrive before the entry is written to - * memory. If this happens we need to wait for the entry to arrive. - */ - for (i = 0; i < LOOP_TIMEOUT; ++i) { - if (PPR_REQ_TYPE(raw[0]) != 0) - break; - udelay(1); - } - if (PPR_REQ_TYPE(raw[0]) != PPR_REQ_FAULT) { pr_err_ratelimited("AMD-Vi: Unknown PPR request received\n"); return; @@ -561,12 +564,6 @@ static void iommu_handle_ppr_entry(struct amd_iommu *iommu, u32 head) fault.tag = PPR_TAG(raw[0]); fault.flags = PPR_FLAGS(raw[0]); - /* - * To detect the hardware bug we need to clear the entry - * to back to zero. - */ - raw[0] = raw[1] = 0; - atomic_notifier_call_chain(&ppr_notifier, 0, &fault); } @@ -578,25 +575,62 @@ static void iommu_poll_ppr_log(struct amd_iommu *iommu) if (iommu->ppr_log == NULL) return; + /* enable ppr interrupts again */ + writel(MMIO_STATUS_PPR_INT_MASK, iommu->mmio_base + MMIO_STATUS_OFFSET); + spin_lock_irqsave(&iommu->lock, flags); head = readl(iommu->mmio_base + MMIO_PPR_HEAD_OFFSET); tail = readl(iommu->mmio_base + MMIO_PPR_TAIL_OFFSET); while (head != tail) { + volatile u64 *raw; + u64 entry[2]; + int i; - /* Handle PPR entry */ - iommu_handle_ppr_entry(iommu, head); + raw = (u64 *)(iommu->ppr_log + head); - /* Update and refresh ring-buffer state*/ + /* + * Hardware bug: Interrupt may arrive before the entry is + * written to memory. If this happens we need to wait for the + * entry to arrive. + */ + for (i = 0; i < LOOP_TIMEOUT; ++i) { + if (PPR_REQ_TYPE(raw[0]) != 0) + break; + udelay(1); + } + + /* Avoid memcpy function-call overhead */ + entry[0] = raw[0]; + entry[1] = raw[1]; + + /* + * To detect the hardware bug we need to clear the entry + * back to zero. + */ + raw[0] = raw[1] = 0UL; + + /* Update head pointer of hardware ring-buffer */ head = (head + PPR_ENTRY_SIZE) % PPR_LOG_SIZE; writel(head, iommu->mmio_base + MMIO_PPR_HEAD_OFFSET); + + /* + * Release iommu->lock because ppr-handling might need to + * re-aquire it + */ + spin_unlock_irqrestore(&iommu->lock, flags); + + /* Handle PPR entry */ + iommu_handle_ppr_entry(iommu, entry); + + spin_lock_irqsave(&iommu->lock, flags); + + /* Refresh ring-buffer information */ + head = readl(iommu->mmio_base + MMIO_PPR_HEAD_OFFSET); tail = readl(iommu->mmio_base + MMIO_PPR_TAIL_OFFSET); } - /* enable ppr interrupts again */ - writel(MMIO_STATUS_PPR_INT_MASK, iommu->mmio_base + MMIO_STATUS_OFFSET); - spin_unlock_irqrestore(&iommu->lock, flags); } @@ -2035,20 +2069,20 @@ static int pdev_iommuv2_enable(struct pci_dev *pdev) } /* FIXME: Move this to PCI code */ -#define PCI_PRI_TLP_OFF (1 << 2) +#define PCI_PRI_TLP_OFF (1 << 15) bool pci_pri_tlp_required(struct pci_dev *pdev) { - u16 control; + u16 status; int pos; pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_PRI); if (!pos) return false; - pci_read_config_word(pdev, pos + PCI_PRI_CTRL, &control); + pci_read_config_word(pdev, pos + PCI_PRI_STATUS, &status); - return (control & PCI_PRI_TLP_OFF) ? true : false; + return (status & PCI_PRI_TLP_OFF) ? true : false; } /* diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index c56790375e0..542024ba6db 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c @@ -1029,6 +1029,9 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h) if (!iommu->dev) return 1; + iommu->root_pdev = pci_get_bus_and_slot(iommu->dev->bus->number, + PCI_DEVFN(0, 0)); + iommu->cap_ptr = h->cap_ptr; iommu->pci_seg = h->pci_seg; iommu->mmio_phys = h->mmio_phys; @@ -1323,20 +1326,16 @@ static void iommu_apply_resume_quirks(struct amd_iommu *iommu) { int i, j; u32 ioc_feature_control; - struct pci_dev *pdev = NULL; + struct pci_dev *pdev = iommu->root_pdev; /* RD890 BIOSes may not have completely reconfigured the iommu */ - if (!is_rd890_iommu(iommu->dev)) + if (!is_rd890_iommu(iommu->dev) || !pdev) return; /* * First, we need to ensure that the iommu is enabled. This is * controlled by a register in the northbridge */ - pdev = pci_get_bus_and_slot(iommu->dev->bus->number, PCI_DEVFN(0, 0)); - - if (!pdev) - return; /* Select Northbridge indirect register 0x75 and enable writing */ pci_write_config_dword(pdev, 0x60, 0x75 | (1 << 7)); @@ -1346,8 +1345,6 @@ static void iommu_apply_resume_quirks(struct amd_iommu *iommu) if (!(ioc_feature_control & 0x1)) pci_write_config_dword(pdev, 0x64, ioc_feature_control | 1); - pci_dev_put(pdev); - /* Restore the iommu BAR */ pci_write_config_dword(iommu->dev, iommu->cap_ptr + 4, iommu->stored_addr_lo); diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h index 2452f3b7173..24355559a2a 100644 --- a/drivers/iommu/amd_iommu_types.h +++ b/drivers/iommu/amd_iommu_types.h @@ -481,6 +481,9 @@ struct amd_iommu { /* Pointer to PCI device of this IOMMU */ struct pci_dev *dev; + /* Cache pdev to root device for resume quirks */ + struct pci_dev *root_pdev; + /* physical address of MMIO space */ u64 mmio_phys; /* virtual address of MMIO space */ diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig index 04796aff10e..f2c5815afb5 100644 --- a/drivers/mtd/Kconfig +++ b/drivers/mtd/Kconfig @@ -128,7 +128,7 @@ config MTD_AFS_PARTS config MTD_OF_PARTS tristate "OpenFirmware partitioning information support" - default Y + default y depends on OF help This provides a partition parsing function which derives diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c index a4a80b742e6..7d7000d2fff 100644 --- a/drivers/mtd/devices/block2mtd.c +++ b/drivers/mtd/devices/block2mtd.c @@ -271,7 +271,6 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size) dev->mtd.flags = MTD_CAP_RAM; dev->mtd._erase = block2mtd_erase; dev->mtd._write = block2mtd_write; - dev->mtd._writev = mtd_writev; dev->mtd._sync = block2mtd_sync; dev->mtd._read = block2mtd_read; dev->mtd.priv = dev; diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index cc0678a967c..6f87c7464ec 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c @@ -1219,12 +1219,6 @@ static int __init mxcnd_probe(struct platform_device *pdev) if (nfc_is_v21() && mtd->writesize == 4096) this->ecc.layout = &nandv2_hw_eccoob_4k; - /* second phase scan */ - if (nand_scan_tail(mtd)) { - err = -ENXIO; - goto escan; - } - if (this->ecc.mode == NAND_ECC_HW) { if (nfc_is_v1()) this->ecc.strength = 1; @@ -1232,6 +1226,12 @@ static int __init mxcnd_probe(struct platform_device *pdev) this->ecc.strength = (host->eccsize == 4) ? 4 : 8; } + /* second phase scan */ + if (nand_scan_tail(mtd)) { + err = -ENXIO; + goto escan; + } + /* Register the partitions */ mtd_device_parse_register(mtd, part_probes, NULL, pdata->parts, pdata->nr_parts); diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c index 20a112f591f..30d1319ff06 100644 --- a/drivers/mtd/nand/nand_bbt.c +++ b/drivers/mtd/nand/nand_bbt.c @@ -324,6 +324,7 @@ static int scan_read_raw_oob(struct mtd_info *mtd, uint8_t *buf, loff_t offs, buf += mtd->oobsize + mtd->writesize; len -= mtd->writesize; + offs += mtd->writesize; } return 0; } diff --git a/drivers/net/ethernet/freescale/fec_mpc52xx.c b/drivers/net/ethernet/freescale/fec_mpc52xx.c index 7b34d8c698d..fc87e8933ce 100644 --- a/drivers/net/ethernet/freescale/fec_mpc52xx.c +++ b/drivers/net/ethernet/freescale/fec_mpc52xx.c @@ -437,7 +437,7 @@ static irqreturn_t mpc52xx_fec_rx_interrupt(int irq, void *dev_id) length = status & BCOM_FEC_RX_BD_LEN_MASK; skb_put(rskb, length - 4); /* length without CRC32 */ rskb->protocol = eth_type_trans(rskb, dev); - if (!skb_defer_rx_timestamp(skb)) + if (!skb_defer_rx_timestamp(rskb)) netif_rx(rskb); spin_lock(&priv->lock); diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c index 42b5151aa78..609fcc33159 100644 --- a/drivers/net/usb/asix.c +++ b/drivers/net/usb/asix.c @@ -35,6 +35,7 @@ #include #include #include +#include #define DRIVER_VERSION "22-Dec-2011" #define DRIVER_NAME "asix" @@ -321,7 +322,7 @@ static int asix_rx_fixup(struct usbnet *dev, struct sk_buff *skb) return 0; } - if ((size > dev->net->mtu + ETH_HLEN) || + if ((size > dev->net->mtu + ETH_HLEN + VLAN_HLEN) || (size + offset > skb->len)) { netdev_err(dev->net, "asix_rx_fixup() Bad RX Length %d\n", size); diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 23eaa1b26eb..d59dd01d6cd 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -64,7 +64,8 @@ static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid, static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc, struct ath_txq *txq, struct ath_atx_tid *tid, - struct sk_buff *skb); + struct sk_buff *skb, + bool dequeue); enum { MCS_HT20, @@ -811,7 +812,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, fi = get_frame_info(skb); bf = fi->bf; if (!fi->bf) - bf = ath_tx_setup_buffer(sc, txq, tid, skb); + bf = ath_tx_setup_buffer(sc, txq, tid, skb, true); if (!bf) continue; @@ -1726,7 +1727,7 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid, return; } - bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb); + bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb, false); if (!bf) return; @@ -1753,7 +1754,7 @@ static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, bf = fi->bf; if (!bf) - bf = ath_tx_setup_buffer(sc, txq, tid, skb); + bf = ath_tx_setup_buffer(sc, txq, tid, skb, false); if (!bf) return; @@ -1814,7 +1815,8 @@ u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate) static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc, struct ath_txq *txq, struct ath_atx_tid *tid, - struct sk_buff *skb) + struct sk_buff *skb, + bool dequeue) { struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath_frame_info *fi = get_frame_info(skb); @@ -1863,6 +1865,8 @@ static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc, return bf; error: + if (dequeue) + __skb_unlink(skb, &tid->buf_q); dev_kfree_skb_any(skb); return NULL; } @@ -1893,7 +1897,7 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb, */ ath_tx_send_ampdu(sc, tid, skb, txctl); } else { - bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb); + bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb, false); if (!bf) return; diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c index ea108622e0b..4da050ffa62 100644 --- a/drivers/net/wireless/iwlwifi/iwl-2000.c +++ b/drivers/net/wireless/iwlwifi/iwl-2000.c @@ -183,7 +183,7 @@ static const struct iwl_base_params iwl2000_base_params = { .chain_noise_scale = 1000, .wd_timeout = IWL_DEF_WD_TIMEOUT, .max_event_log_size = 512, - .shadow_reg_enable = true, + .shadow_reg_enable = false, /* TODO: fix bugs using this feature */ .hd_v2 = true, }; @@ -202,7 +202,7 @@ static const struct iwl_base_params iwl2030_base_params = { .chain_noise_scale = 1000, .wd_timeout = IWL_LONG_WD_TIMEOUT, .max_event_log_size = 512, - .shadow_reg_enable = true, + .shadow_reg_enable = false, /* TODO: fix bugs using this feature */ .hd_v2 = true, }; diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index f0c91505a7f..9f71b85f591 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -282,7 +282,7 @@ static const struct iwl_base_params iwl6000_base_params = { .chain_noise_scale = 1000, .wd_timeout = IWL_DEF_WD_TIMEOUT, .max_event_log_size = 512, - .shadow_reg_enable = true, + .shadow_reg_enable = false, /* TODO: fix bugs using this feature */ }; static const struct iwl_base_params iwl6050_base_params = { @@ -299,7 +299,7 @@ static const struct iwl_base_params iwl6050_base_params = { .chain_noise_scale = 1500, .wd_timeout = IWL_DEF_WD_TIMEOUT, .max_event_log_size = 1024, - .shadow_reg_enable = true, + .shadow_reg_enable = false, /* TODO: fix bugs using this feature */ }; static const struct iwl_base_params iwl6000_g2_base_params = { @@ -316,7 +316,7 @@ static const struct iwl_base_params iwl6000_g2_base_params = { .chain_noise_scale = 1000, .wd_timeout = IWL_LONG_WD_TIMEOUT, .max_event_log_size = 512, - .shadow_reg_enable = true, + .shadow_reg_enable = false, /* TODO: fix bugs using this feature */ }; static const struct iwl_ht_params iwl6000_ht_params = { diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 7e590b349dd..da2be3e09ee 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -884,6 +884,7 @@ static void rs_bt_update_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx, if ((priv->bt_traffic_load != priv->last_bt_traffic_load) || (priv->bt_full_concurrent != full_concurrent)) { priv->bt_full_concurrent = full_concurrent; + priv->last_bt_traffic_load = priv->bt_traffic_load; /* Update uCode's rate table. */ tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); diff --git a/drivers/net/wireless/wl1251/sdio.c b/drivers/net/wireless/wl1251/sdio.c index 1b851f650e0..e2750a12c6f 100644 --- a/drivers/net/wireless/wl1251/sdio.c +++ b/drivers/net/wireless/wl1251/sdio.c @@ -260,6 +260,7 @@ static int wl1251_sdio_probe(struct sdio_func *func, } if (wl->irq) { + irq_set_status_flags(wl->irq, IRQ_NOAUTOEN); ret = request_irq(wl->irq, wl1251_line_irq, 0, "wl1251", wl); if (ret < 0) { wl1251_error("request_irq() failed: %d", ret); @@ -267,7 +268,6 @@ static int wl1251_sdio_probe(struct sdio_func *func, } irq_set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING); - disable_irq(wl->irq); wl1251_sdio_ops.enable_irq = wl1251_enable_line_irq; wl1251_sdio_ops.disable_irq = wl1251_disable_line_irq; diff --git a/drivers/net/wireless/wl1251/spi.c b/drivers/net/wireless/wl1251/spi.c index 6248c354fc5..87f6305bda2 100644 --- a/drivers/net/wireless/wl1251/spi.c +++ b/drivers/net/wireless/wl1251/spi.c @@ -281,6 +281,7 @@ static int __devinit wl1251_spi_probe(struct spi_device *spi) wl->use_eeprom = pdata->use_eeprom; + irq_set_status_flags(wl->irq, IRQ_NOAUTOEN); ret = request_irq(wl->irq, wl1251_irq, 0, DRIVER_NAME, wl); if (ret < 0) { wl1251_error("request_irq() failed: %d", ret); @@ -289,8 +290,6 @@ static int __devinit wl1251_spi_probe(struct spi_device *spi) irq_set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING); - disable_irq(wl->irq); - ret = wl1251_init_ieee80211(wl); if (ret) goto out_irq; diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 5dfd7495d1a..4037fd5b1e0 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1378,16 +1378,19 @@ static int scsi_lld_busy(struct request_queue *q) { struct scsi_device *sdev = q->queuedata; struct Scsi_Host *shost; - struct scsi_target *starget; if (!sdev) return 0; shost = sdev->host; - starget = scsi_target(sdev); - if (scsi_host_in_recovery(shost) || scsi_host_is_busy(shost) || - scsi_target_is_busy(starget) || scsi_device_is_busy(sdev)) + /* + * Ignore host/starget busy state. + * Since block layer does not have a concept of fairness across + * multiple queues, congestion of host/starget needs to be handled + * in SCSI layer. + */ + if (scsi_host_in_recovery(shost) || scsi_device_is_busy(sdev)) return 1; return 0; diff --git a/drivers/scsi/scsi_wait_scan.c b/drivers/scsi/scsi_wait_scan.c index 74708fcaf82..ae781487461 100644 --- a/drivers/scsi/scsi_wait_scan.c +++ b/drivers/scsi/scsi_wait_scan.c @@ -12,7 +12,7 @@ #include #include -#include +#include "scsi_priv.h" static int __init wait_scan_init(void) { diff --git a/fs/attr.c b/fs/attr.c index 73f69a6ce9e..d94d1b63c63 100644 --- a/fs/attr.c +++ b/fs/attr.c @@ -176,6 +176,11 @@ int notify_change(struct dentry * dentry, struct iattr * attr) return -EPERM; } + if ((ia_valid & ATTR_SIZE) && IS_I_VERSION(inode)) { + if (attr->ia_size != inode->i_size) + inode_inc_iversion(inode); + } + if ((ia_valid & ATTR_MODE)) { umode_t amode = attr->ia_mode; /* Flag setting protected by i_mutex */ diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 4ff6313f0a9..73fea285b84 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -43,6 +43,7 @@ #define CIFS_MIN_RCV_POOL 4 +#define MAX_REOPEN_ATT 5 /* these many maximum attempts to reopen a file */ /* * default attribute cache timeout (jiffies) */ diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 96192c1e380..97f5d0371cb 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -192,11 +192,13 @@ extern int CIFSTCon(unsigned int xid, struct cifs_ses *ses, extern int CIFSFindFirst(const int xid, struct cifs_tcon *tcon, const char *searchName, const struct nls_table *nls_codepage, - __u16 *searchHandle, struct cifs_search_info *psrch_inf, + __u16 *searchHandle, __u16 search_flags, + struct cifs_search_info *psrch_inf, int map, const char dirsep); extern int CIFSFindNext(const int xid, struct cifs_tcon *tcon, - __u16 searchHandle, struct cifs_search_info *psrch_inf); + __u16 searchHandle, __u16 search_flags, + struct cifs_search_info *psrch_inf); extern int CIFSFindClose(const int, struct cifs_tcon *tcon, const __u16 search_handle); diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index da2f5446fa7..6b79efd7d75 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -4344,7 +4344,7 @@ int CIFSFindFirst(const int xid, struct cifs_tcon *tcon, const char *searchName, const struct nls_table *nls_codepage, - __u16 *pnetfid, + __u16 *pnetfid, __u16 search_flags, struct cifs_search_info *psrch_inf, int remap, const char dirsep) { /* level 257 SMB_ */ @@ -4416,8 +4416,7 @@ CIFSFindFirst(const int xid, struct cifs_tcon *tcon, cpu_to_le16(ATTR_READONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_DIRECTORY); pSMB->SearchCount = cpu_to_le16(CIFSMaxBufSize/sizeof(FILE_UNIX_INFO)); - pSMB->SearchFlags = cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | - CIFS_SEARCH_RETURN_RESUME); + pSMB->SearchFlags = cpu_to_le16(search_flags); pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level); /* BB what should we set StorageType to? Does it matter? BB */ @@ -4487,8 +4486,8 @@ CIFSFindFirst(const int xid, struct cifs_tcon *tcon, return rc; } -int CIFSFindNext(const int xid, struct cifs_tcon *tcon, - __u16 searchHandle, struct cifs_search_info *psrch_inf) +int CIFSFindNext(const int xid, struct cifs_tcon *tcon, __u16 searchHandle, + __u16 search_flags, struct cifs_search_info *psrch_inf) { TRANSACTION2_FNEXT_REQ *pSMB = NULL; TRANSACTION2_FNEXT_RSP *pSMBr = NULL; @@ -4531,8 +4530,7 @@ int CIFSFindNext(const int xid, struct cifs_tcon *tcon, cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO)); pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level); pSMB->ResumeKey = psrch_inf->resume_key; - pSMB->SearchFlags = - cpu_to_le16(CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME); + pSMB->SearchFlags = cpu_to_le16(search_flags); name_len = psrch_inf->resume_name_len; params += name_len; diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 81725e9286e..e7ebb5a2ed1 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -1539,10 +1539,11 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode, struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode, bool fsuid_only) { - struct cifsFileInfo *open_file; + struct cifsFileInfo *open_file, *inv_file = NULL; struct cifs_sb_info *cifs_sb; bool any_available = false; int rc; + unsigned int refind = 0; /* Having a null inode here (because mapping->host was set to zero by the VFS or MM) should not happen but we had reports of on oops (due to @@ -1562,40 +1563,25 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode, spin_lock(&cifs_file_list_lock); refind_writable: + if (refind > MAX_REOPEN_ATT) { + spin_unlock(&cifs_file_list_lock); + return NULL; + } list_for_each_entry(open_file, &cifs_inode->openFileList, flist) { if (!any_available && open_file->pid != current->tgid) continue; if (fsuid_only && open_file->uid != current_fsuid()) continue; if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) { - cifsFileInfo_get(open_file); - if (!open_file->invalidHandle) { /* found a good writable file */ + cifsFileInfo_get(open_file); spin_unlock(&cifs_file_list_lock); return open_file; + } else { + if (!inv_file) + inv_file = open_file; } - - spin_unlock(&cifs_file_list_lock); - - /* Had to unlock since following call can block */ - rc = cifs_reopen_file(open_file, false); - if (!rc) - return open_file; - - /* if it fails, try another handle if possible */ - cFYI(1, "wp failed on reopen file"); - cifsFileInfo_put(open_file); - - spin_lock(&cifs_file_list_lock); - - /* else we simply continue to the next entry. Thus - we do not loop on reopen errors. If we - can not reopen the file, for example if we - reconnected to a server with another client - racing to delete or lock the file we would not - make progress if we restarted before the beginning - of the loop here. */ } } /* couldn't find useable FH with same pid, try any available */ @@ -1603,7 +1589,30 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode, any_available = true; goto refind_writable; } + + if (inv_file) { + any_available = false; + cifsFileInfo_get(inv_file); + } + spin_unlock(&cifs_file_list_lock); + + if (inv_file) { + rc = cifs_reopen_file(inv_file, false); + if (!rc) + return inv_file; + else { + spin_lock(&cifs_file_list_lock); + list_move_tail(&inv_file->flist, + &cifs_inode->openFileList); + spin_unlock(&cifs_file_list_lock); + cifsFileInfo_put(inv_file); + spin_lock(&cifs_file_list_lock); + ++refind; + goto refind_writable; + } + } + return NULL; } diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index e2bbc683e01..0a8224d1c4c 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c @@ -219,6 +219,7 @@ int get_symlink_reparse_path(char *full_path, struct cifs_sb_info *cifs_sb, static int initiate_cifs_search(const int xid, struct file *file) { + __u16 search_flags; int rc = 0; char *full_path = NULL; struct cifsFileInfo *cifsFile; @@ -270,8 +271,12 @@ static int initiate_cifs_search(const int xid, struct file *file) cifsFile->srch_inf.info_level = SMB_FIND_FILE_DIRECTORY_INFO; } + search_flags = CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME; + if (backup_cred(cifs_sb)) + search_flags |= CIFS_SEARCH_BACKUP_SEARCH; + rc = CIFSFindFirst(xid, pTcon, full_path, cifs_sb->local_nls, - &cifsFile->netfid, &cifsFile->srch_inf, + &cifsFile->netfid, search_flags, &cifsFile->srch_inf, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR, CIFS_DIR_SEP(cifs_sb)); if (rc == 0) @@ -502,11 +507,13 @@ static int cifs_save_resume_key(const char *current_entry, static int find_cifs_entry(const int xid, struct cifs_tcon *pTcon, struct file *file, char **ppCurrentEntry, int *num_to_ret) { + __u16 search_flags; int rc = 0; int pos_in_buf = 0; loff_t first_entry_in_buffer; loff_t index_to_find = file->f_pos; struct cifsFileInfo *cifsFile = file->private_data; + struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); /* check if index in the buffer */ if ((cifsFile == NULL) || (ppCurrentEntry == NULL) || @@ -560,10 +567,14 @@ static int find_cifs_entry(const int xid, struct cifs_tcon *pTcon, cifsFile); } + search_flags = CIFS_SEARCH_CLOSE_AT_END | CIFS_SEARCH_RETURN_RESUME; + if (backup_cred(cifs_sb)) + search_flags |= CIFS_SEARCH_BACKUP_SEARCH; + while ((index_to_find >= cifsFile->srch_inf.index_of_last_entry) && (rc == 0) && !cifsFile->srch_inf.endOfSearch) { cFYI(1, "calling findnext2"); - rc = CIFSFindNext(xid, pTcon, cifsFile->netfid, + rc = CIFSFindNext(xid, pTcon, cifsFile->netfid, search_flags, &cifsFile->srch_inf); /* FindFirst/Next set last_entry to NULL on malformed reply */ if (cifsFile->srch_inf.last_entry) diff --git a/fs/exofs/super.c b/fs/exofs/super.c index 735ca06430a..59e0849772b 100644 --- a/fs/exofs/super.c +++ b/fs/exofs/super.c @@ -745,7 +745,6 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent) sbi->one_comp.obj.partition = opts->pid; sbi->one_comp.obj.id = 0; exofs_make_credential(sbi->one_comp.cred, &sbi->one_comp.obj); - sbi->oc.numdevs = 1; sbi->oc.single_comp = EC_SINGLE_COMP; sbi->oc.comps = &sbi->one_comp; @@ -804,6 +803,7 @@ static int exofs_fill_super(struct super_block *sb, void *data, int silent) goto free_sbi; ore_comp_set_dev(&sbi->oc, 0, od); + sbi->oc.numdevs = 1; } __sbi_read_stats(sbi); diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index cb90020459f..b4a7dd56eb8 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c @@ -488,10 +488,12 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, for (i = 0; i < ngroups; i++) { grp = (parent_group + i) % ngroups; desc = ext4_get_group_desc(sb, grp, NULL); - grp_free = ext4_free_inodes_count(sb, desc); - if (desc && grp_free && grp_free >= avefreei) { - *group = grp; - return 0; + if (desc) { + grp_free = ext4_free_inodes_count(sb, desc); + if (grp_free && grp_free >= avefreei) { + *group = grp; + return 0; + } } } diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index 6eee25591b8..1365903a514 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c @@ -38,7 +38,7 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) handle_t *handle = NULL; int err, migrate = 0; struct ext4_iloc iloc; - unsigned int oldflags; + unsigned int oldflags, mask, i; unsigned int jflag; if (!inode_owner_or_capable(inode)) @@ -115,9 +115,14 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) if (err) goto flags_err; - flags = flags & EXT4_FL_USER_MODIFIABLE; - flags |= oldflags & ~EXT4_FL_USER_MODIFIABLE; - ei->i_flags = flags; + for (i = 0, mask = 1; i < 32; i++, mask <<= 1) { + if (!(mask & EXT4_FL_USER_MODIFIABLE)) + continue; + if (mask & flags) + ext4_set_inode_flag(inode, i); + else + ext4_clear_inode_flag(inode, i); + } ext4_set_inode_flags(inode); inode->i_ctime = ext4_current_time(inode); diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 99ab428bcfa..6b0a57eafb5 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -2517,6 +2517,9 @@ int ext4_mb_release(struct super_block *sb) struct ext4_sb_info *sbi = EXT4_SB(sb); struct kmem_cache *cachep = get_groupinfo_cache(sb->s_blocksize_bits); + if (sbi->s_proc) + remove_proc_entry("mb_groups", sbi->s_proc); + if (sbi->s_group_info) { for (i = 0; i < ngroups; i++) { grinfo = ext4_get_group_info(sb, i); @@ -2564,8 +2567,6 @@ int ext4_mb_release(struct super_block *sb) } free_percpu(sbi->s_locality_groups); - if (sbi->s_proc) - remove_proc_entry("mb_groups", sbi->s_proc); return 0; } @@ -4636,6 +4637,7 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode, */ new_entry = kmem_cache_alloc(ext4_free_data_cachep, GFP_NOFS); if (!new_entry) { + ext4_mb_unload_buddy(&e4b); err = -ENOMEM; goto error_return; } diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index 59fa0be2725..53589ff8824 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c @@ -161,6 +161,8 @@ static struct ext4_new_flex_group_data *alloc_flex_gd(unsigned long flexbg_size) if (flex_gd == NULL) goto out3; + if (flexbg_size >= UINT_MAX / sizeof(struct ext4_new_flex_group_data)) + goto out2; flex_gd->count = flexbg_size; flex_gd->groups = kmalloc(sizeof(struct ext4_new_group_data) * diff --git a/fs/ext4/super.c b/fs/ext4/super.c index e1fb1d5de58..a68703a5610 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -497,6 +497,7 @@ void __ext4_error(struct super_block *sb, const char *function, printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: comm %s: %pV\n", sb->s_id, function, line, current->comm, &vaf); va_end(args); + save_error_info(sb, function, line); ext4_handle_error(sb); } @@ -3592,7 +3593,8 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) goto failed_mount4; } - ext4_setup_super(sb, es, sb->s_flags & MS_RDONLY); + if (ext4_setup_super(sb, es, sb->s_flags & MS_RDONLY)) + sb->s_flags |= MS_RDONLY; /* determine the minimum size of new large inodes, if present */ if (sbi->s_inode_size > EXT4_GOOD_OLD_INODE_SIZE) { diff --git a/fs/namespace.c b/fs/namespace.c index 0968eb5d8f5..5e4e6c7c8b6 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -1073,8 +1073,9 @@ void umount_tree(struct mount *mnt, int propagate, struct list_head *kill) list_del_init(&p->mnt_expire); list_del_init(&p->mnt_list); __touch_mnt_namespace(p->mnt_ns); + if (p->mnt_ns) + __mnt_make_shortterm(p); p->mnt_ns = NULL; - __mnt_make_shortterm(p); list_del_init(&p->mnt_child); if (mnt_has_parent(p)) { p->mnt_parent->mnt_ghosts++; diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c index ba3019f5934..3e8edbe71ec 100644 --- a/fs/nfs/idmap.c +++ b/fs/nfs/idmap.c @@ -640,20 +640,16 @@ static int nfs_idmap_legacy_upcall(struct key_construction *cons, struct idmap_msg *im; struct idmap *idmap = (struct idmap *)aux; struct key *key = cons->key; - int ret; + int ret = -ENOMEM; /* msg and im are freed in idmap_pipe_destroy_msg */ msg = kmalloc(sizeof(*msg), GFP_KERNEL); - if (IS_ERR(msg)) { - ret = PTR_ERR(msg); + if (!msg) goto out0; - } im = kmalloc(sizeof(*im), GFP_KERNEL); - if (IS_ERR(im)) { - ret = PTR_ERR(im); + if (!im) goto out1; - } ret = nfs_idmap_prepare_message(key->description, im, msg); if (ret < 0) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index bf6b8dfa3e2..9e217326831 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -101,6 +101,8 @@ static int nfs4_map_errors(int err) case -NFS4ERR_BADOWNER: case -NFS4ERR_BADNAME: return -EINVAL; + case -NFS4ERR_SHARE_DENIED: + return -EACCES; default: dprintk("%s could not handle NFSv4 error %d\n", __func__, -err); diff --git a/fs/proc/base.c b/fs/proc/base.c index 2f198dad12c..c8cb15dcca0 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -1838,7 +1838,7 @@ static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd) rcu_read_lock(); file = fcheck_files(files, fd); if (file) { - unsigned i_mode, f_mode = file->f_mode; + unsigned f_mode = file->f_mode; rcu_read_unlock(); put_files_struct(files); @@ -1854,12 +1854,14 @@ static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd) inode->i_gid = 0; } - i_mode = S_IFLNK; - if (f_mode & FMODE_READ) - i_mode |= S_IRUSR | S_IXUSR; - if (f_mode & FMODE_WRITE) - i_mode |= S_IWUSR | S_IXUSR; - inode->i_mode = i_mode; + if (S_ISLNK(inode->i_mode)) { + unsigned i_mode = S_IFLNK; + if (f_mode & FMODE_READ) + i_mode |= S_IRUSR | S_IXUSR; + if (f_mode & FMODE_WRITE) + i_mode |= S_IWUSR | S_IXUSR; + inode->i_mode = i_mode; + } security_task_to_inode(task, inode); put_task_struct(task); @@ -1894,6 +1896,7 @@ static struct dentry *proc_fd_instantiate(struct inode *dir, ei = PROC_I(inode); ei->fd = fd; + inode->i_mode = S_IFLNK; inode->i_op = &proc_pid_link_inode_operations; inode->i_size = 64; ei->op.proc_get_link = proc_fd_link; diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index a789934737e..03d41ed9bb1 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -846,7 +846,7 @@ static int pagemap_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, /* find the first VMA at or above 'addr' */ vma = find_vma(walk->mm, addr); - if (pmd_trans_huge_lock(pmd, vma) == 1) { + if (vma && pmd_trans_huge_lock(pmd, vma) == 1) { for (; addr != end; addr += PAGE_SIZE) { unsigned long offset; diff --git a/include/drm/drm_pciids.h b/include/drm/drm_pciids.h index 58d0bdab68d..81368ab6c61 100644 --- a/include/drm/drm_pciids.h +++ b/include/drm/drm_pciids.h @@ -181,6 +181,7 @@ {0x1002, 0x6747, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6748, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6749, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x674A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6750, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6751, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6758, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TURKS|RADEON_NEW_MEMMAP}, \ @@ -198,6 +199,7 @@ {0x1002, 0x6767, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6768, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6770, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6771, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6772, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6778, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6779, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CAICOS|RADEON_NEW_MEMMAP}, \ @@ -229,10 +231,11 @@ {0x1002, 0x6827, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6828, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6829, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x682B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x682D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x682F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ - {0x1002, 0x6830, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_NEW_MEMMAP}, \ - {0x1002, 0x6831, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6830, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6831, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6837, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6838, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6839, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_NEW_MEMMAP}, \ @@ -531,6 +534,7 @@ {0x1002, 0x9645, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO2|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x9647, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP},\ {0x1002, 0x9648, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP},\ + {0x1002, 0x9649, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP},\ {0x1002, 0x964a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x964b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x964c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ @@ -550,6 +554,7 @@ {0x1002, 0x9807, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PALM|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x9808, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PALM|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x9809, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PALM|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x980A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PALM|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x9900, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x9901, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x9903, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ @@ -561,11 +566,19 @@ {0x1002, 0x9909, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x990A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x990F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x9910, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x9913, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x9917, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x9918, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x9919, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x9990, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x9991, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x9992, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x9993, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x9994, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x99A0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x99A2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x99A4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0, 0, 0} #define r128_PCI_IDS \ diff --git a/include/linux/Kbuild b/include/linux/Kbuild index 3e681aa6016..183da95aad3 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -233,6 +233,7 @@ header-y += kd.h header-y += kdev_t.h header-y += kernel.h header-y += kernelcapi.h +header-y += kernel-page-flags.h header-y += keyboard.h header-y += keyctl.h header-y += l2tp.h diff --git a/include/linux/kernel-page-flags.h b/include/linux/kernel-page-flags.h index 26a65711676..a1bdf696635 100644 --- a/include/linux/kernel-page-flags.h +++ b/include/linux/kernel-page-flags.h @@ -32,6 +32,8 @@ #define KPF_KSM 21 #define KPF_THP 22 +#ifdef __KERNEL__ + /* kernel hacking assistances * WARNING: subject to change, never rely on them! */ @@ -44,4 +46,6 @@ #define KPF_ARCH 38 #define KPF_UNCACHED 39 +#endif /* __KERNEL__ */ + #endif /* LINUX_KERNEL_PAGE_FLAGS_H */ diff --git a/include/linux/radix-tree.h b/include/linux/radix-tree.h index 0d04cd69ab9..ffc444c38b0 100644 --- a/include/linux/radix-tree.h +++ b/include/linux/radix-tree.h @@ -368,8 +368,11 @@ radix_tree_next_slot(void **slot, struct radix_tree_iter *iter, unsigned flags) iter->index++; if (likely(*slot)) return slot; - if (flags & RADIX_TREE_ITER_CONTIG) + if (flags & RADIX_TREE_ITER_CONTIG) { + /* forbid switching to the next chunk */ + iter->next_index = 0; break; + } } } return NULL; diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 111f26b6e28..c1689071fa2 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -1881,8 +1881,6 @@ static inline int __skb_cow(struct sk_buff *skb, unsigned int headroom, { int delta = 0; - if (headroom < NET_SKB_PAD) - headroom = NET_SKB_PAD; if (headroom > skb_headroom(skb)) delta = headroom - skb_headroom(skb); diff --git a/include/net/dst.h b/include/net/dst.h index bed833d9796..8197eadca81 100644 --- a/include/net/dst.h +++ b/include/net/dst.h @@ -60,6 +60,7 @@ struct dst_entry { #define DST_NOCOUNT 0x0020 #define DST_NOPEER 0x0040 #define DST_FAKE_RTABLE 0x0080 +#define DST_XFRM_TUNNEL 0x0100 short error; short obsolete; diff --git a/kernel/fork.c b/kernel/fork.c index 2a3cd0aea6a..e775c328172 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -372,7 +372,8 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) } charge = 0; if (mpnt->vm_flags & VM_ACCOUNT) { - unsigned int len = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT; + unsigned long len; + len = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT; if (security_vm_enough_memory_mm(oldmm, len)) /* sic */ goto fail_nomem; charge = len; diff --git a/lib/radix-tree.c b/lib/radix-tree.c index 86516f5588e..3ac50dc5563 100644 --- a/lib/radix-tree.c +++ b/lib/radix-tree.c @@ -673,6 +673,9 @@ void **radix_tree_next_chunk(struct radix_tree_root *root, * during iterating; it can be zero only at the beginning. * And we cannot overflow iter->next_index in a single step, * because RADIX_TREE_MAP_SHIFT < BITS_PER_LONG. + * + * This condition also used by radix_tree_next_slot() to stop + * contiguous iterating, and forbid swithing to the next chunk. */ index = iter->next_index; if (!index && iter->index) diff --git a/mm/hugetlb.c b/mm/hugetlb.c index ae8f708e3d7..263e17703b3 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -2157,6 +2157,15 @@ static void hugetlb_vm_op_open(struct vm_area_struct *vma) kref_get(&reservations->refs); } +static void resv_map_put(struct vm_area_struct *vma) +{ + struct resv_map *reservations = vma_resv_map(vma); + + if (!reservations) + return; + kref_put(&reservations->refs, resv_map_release); +} + static void hugetlb_vm_op_close(struct vm_area_struct *vma) { struct hstate *h = hstate_vma(vma); @@ -2173,7 +2182,7 @@ static void hugetlb_vm_op_close(struct vm_area_struct *vma) reserve = (end - start) - region_count(&reservations->regions, start, end); - kref_put(&reservations->refs, resv_map_release); + resv_map_put(vma); if (reserve) { hugetlb_acct_memory(h, -reserve); @@ -2990,12 +2999,16 @@ int hugetlb_reserve_pages(struct inode *inode, set_vma_resv_flags(vma, HPAGE_RESV_OWNER); } - if (chg < 0) - return chg; + if (chg < 0) { + ret = chg; + goto out_err; + } /* There must be enough pages in the subpool for the mapping */ - if (hugepage_subpool_get_pages(spool, chg)) - return -ENOSPC; + if (hugepage_subpool_get_pages(spool, chg)) { + ret = -ENOSPC; + goto out_err; + } /* * Check enough hugepages are available for the reservation. @@ -3004,7 +3017,7 @@ int hugetlb_reserve_pages(struct inode *inode, ret = hugetlb_acct_memory(h, chg); if (ret < 0) { hugepage_subpool_put_pages(spool, chg); - return ret; + goto out_err; } /* @@ -3021,6 +3034,10 @@ int hugetlb_reserve_pages(struct inode *inode, if (!vma || vma->vm_flags & VM_MAYSHARE) region_add(&inode->i_mapping->private_list, from, to); return 0; +out_err: + if (vma) + resv_map_put(vma); + return ret; } void hugetlb_unreserve_pages(struct inode *inode, long offset, long freed) diff --git a/mm/vmscan.c b/mm/vmscan.c index fd8ef669f36..cb515d7fe49 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -722,7 +722,7 @@ static enum page_references page_check_references(struct page *page, return PAGEREF_RECLAIM; if (referenced_ptes) { - if (PageAnon(page)) + if (PageSwapBacked(page)) return PAGEREF_ACTIVATE; /* * All mapped pages start out with page table diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c index 89a47b35905..cb982a61536 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c @@ -459,28 +459,22 @@ static u32 esp4_get_mtu(struct xfrm_state *x, int mtu) struct esp_data *esp = x->data; u32 blksize = ALIGN(crypto_aead_blocksize(esp->aead), 4); u32 align = max_t(u32, blksize, esp->padlen); - u32 rem; - - mtu -= x->props.header_len + crypto_aead_authsize(esp->aead); - rem = mtu & (align - 1); - mtu &= ~(align - 1); + unsigned int net_adj; switch (x->props.mode) { - case XFRM_MODE_TUNNEL: - break; - default: case XFRM_MODE_TRANSPORT: - /* The worst case */ - mtu -= blksize - 4; - mtu += min_t(u32, blksize - 4, rem); - break; case XFRM_MODE_BEET: - /* The worst case. */ - mtu += min_t(u32, IPV4_BEET_PHMAXLEN, rem); + net_adj = sizeof(struct iphdr); break; + case XFRM_MODE_TUNNEL: + net_adj = 0; + break; + default: + BUG(); } - return mtu - 2; + return ((mtu - x->props.header_len - crypto_aead_authsize(esp->aead) - + net_adj) & ~(align - 1)) + (net_adj - 2); } static void esp4_err(struct sk_buff *skb, u32 info) diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index 1ac7938dd9e..65dd5433f08 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c @@ -411,19 +411,15 @@ static u32 esp6_get_mtu(struct xfrm_state *x, int mtu) struct esp_data *esp = x->data; u32 blksize = ALIGN(crypto_aead_blocksize(esp->aead), 4); u32 align = max_t(u32, blksize, esp->padlen); - u32 rem; + unsigned int net_adj; - mtu -= x->props.header_len + crypto_aead_authsize(esp->aead); - rem = mtu & (align - 1); - mtu &= ~(align - 1); - - if (x->props.mode != XFRM_MODE_TUNNEL) { - u32 padsize = ((blksize - 1) & 7) + 1; - mtu -= blksize - padsize; - mtu += min_t(u32, blksize - padsize, rem); - } + if (x->props.mode != XFRM_MODE_TUNNEL) + net_adj = sizeof(struct ipv6hdr); + else + net_adj = 0; - return mtu - 2; + return ((mtu - x->props.header_len - crypto_aead_authsize(esp->aead) - + net_adj) & ~(align - 1)) + (net_adj - 2); } static void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 02d7f1cdd2f..ec329a3c5b5 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -1182,6 +1182,29 @@ static inline struct ipv6_rt_hdr *ip6_rthdr_dup(struct ipv6_rt_hdr *src, return src ? kmemdup(src, (src->hdrlen + 1) * 8, gfp) : NULL; } +static void ip6_append_data_mtu(int *mtu, + int *maxfraglen, + unsigned int fragheaderlen, + struct sk_buff *skb, + struct rt6_info *rt) +{ + if (!(rt->dst.flags & DST_XFRM_TUNNEL)) { + if (skb == NULL) { + /* first fragment, reserve header_len */ + *mtu = *mtu - rt->dst.header_len; + + } else { + /* + * this fragment is not first, the headers + * space is regarded as data space. + */ + *mtu = dst_mtu(rt->dst.path); + } + *maxfraglen = ((*mtu - fragheaderlen) & ~7) + + fragheaderlen - sizeof(struct frag_hdr); + } +} + int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb), void *from, int length, int transhdrlen, @@ -1191,7 +1214,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, struct inet_sock *inet = inet_sk(sk); struct ipv6_pinfo *np = inet6_sk(sk); struct inet_cork *cork; - struct sk_buff *skb; + struct sk_buff *skb, *skb_prev = NULL; unsigned int maxfraglen, fragheaderlen; int exthdrlen; int dst_exthdrlen; @@ -1249,8 +1272,12 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, inet->cork.fl.u.ip6 = *fl6; np->cork.hop_limit = hlimit; np->cork.tclass = tclass; - mtu = np->pmtudisc == IPV6_PMTUDISC_PROBE ? - rt->dst.dev->mtu : dst_mtu(&rt->dst); + if (rt->dst.flags & DST_XFRM_TUNNEL) + mtu = np->pmtudisc == IPV6_PMTUDISC_PROBE ? + rt->dst.dev->mtu : dst_mtu(&rt->dst); + else + mtu = np->pmtudisc == IPV6_PMTUDISC_PROBE ? + rt->dst.dev->mtu : dst_mtu(rt->dst.path); if (np->frag_size < mtu) { if (np->frag_size) mtu = np->frag_size; @@ -1346,25 +1373,27 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, unsigned int fraglen; unsigned int fraggap; unsigned int alloclen; - struct sk_buff *skb_prev; alloc_new_skb: - skb_prev = skb; - /* There's no room in the current skb */ - if (skb_prev) - fraggap = skb_prev->len - maxfraglen; + if (skb) + fraggap = skb->len - maxfraglen; else fraggap = 0; + /* update mtu and maxfraglen if necessary */ + if (skb == NULL || skb_prev == NULL) + ip6_append_data_mtu(&mtu, &maxfraglen, + fragheaderlen, skb, rt); + + skb_prev = skb; /* * If remaining data exceeds the mtu, * we know we need more fragment(s). */ datalen = length + fraggap; - if (datalen > (cork->length <= mtu && !(cork->flags & IPCORK_ALLFRAG) ? mtu : maxfraglen) - fragheaderlen) - datalen = maxfraglen - fragheaderlen; - fraglen = datalen + fragheaderlen; + if (datalen > (cork->length <= mtu && !(cork->flags & IPCORK_ALLFRAG) ? mtu : maxfraglen) - fragheaderlen) + datalen = maxfraglen - fragheaderlen - rt->dst.trailer_len; if ((flags & MSG_MORE) && !(rt->dst.dev->features&NETIF_F_SG)) alloclen = mtu; @@ -1373,13 +1402,16 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, alloclen += dst_exthdrlen; - /* - * The last fragment gets additional space at tail. - * Note: we overallocate on fragments with MSG_MODE - * because we have no idea if we're the last one. - */ - if (datalen == length + fraggap) - alloclen += rt->dst.trailer_len; + if (datalen != length + fraggap) { + /* + * this is not the last fragment, the trailer + * space is regarded as data space. + */ + datalen += rt->dst.trailer_len; + } + + alloclen += rt->dst.trailer_len; + fraglen = datalen + fragheaderlen; /* * We just reserve space for fragment header. diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c index 6274f0be82b..cc8ad7bf51d 100644 --- a/net/l2tp/l2tp_ip.c +++ b/net/l2tp/l2tp_ip.c @@ -251,9 +251,16 @@ static int l2tp_ip_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) { struct inet_sock *inet = inet_sk(sk); struct sockaddr_l2tpip *addr = (struct sockaddr_l2tpip *) uaddr; - int ret = -EINVAL; + int ret; int chk_addr_ret; + if (!sock_flag(sk, SOCK_ZAPPED)) + return -EINVAL; + if (addr_len < sizeof(struct sockaddr_l2tpip)) + return -EINVAL; + if (addr->l2tp_family != AF_INET) + return -EINVAL; + ret = -EADDRINUSE; read_lock_bh(&l2tp_ip_lock); if (__l2tp_ip_bind_lookup(&init_net, addr->l2tp_addr.s_addr, sk->sk_bound_dev_if, addr->l2tp_conn_id)) @@ -284,6 +291,8 @@ static int l2tp_ip_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) sk_del_node_init(sk); write_unlock_bh(&l2tp_ip_lock); ret = 0; + sock_reset_flag(sk, SOCK_ZAPPED); + out: release_sock(sk); @@ -304,13 +313,14 @@ static int l2tp_ip_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len __be32 saddr; int oif, rc; - rc = -EINVAL; + if (sock_flag(sk, SOCK_ZAPPED)) /* Must bind first - autobinding does not work */ + return -EINVAL; + if (addr_len < sizeof(*lsa)) - goto out; + return -EINVAL; - rc = -EAFNOSUPPORT; if (lsa->l2tp_family != AF_INET) - goto out; + return -EAFNOSUPPORT; lock_sock(sk); @@ -364,6 +374,14 @@ static int l2tp_ip_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len return rc; } +static int l2tp_ip_disconnect(struct sock *sk, int flags) +{ + if (sock_flag(sk, SOCK_ZAPPED)) + return 0; + + return udp_disconnect(sk, flags); +} + static int l2tp_ip_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_len, int peer) { @@ -599,7 +617,7 @@ static struct proto l2tp_ip_prot = { .close = l2tp_ip_close, .bind = l2tp_ip_bind, .connect = l2tp_ip_connect, - .disconnect = udp_disconnect, + .disconnect = l2tp_ip_disconnect, .ioctl = udp_ioctl, .destroy = l2tp_ip_destroy_sock, .setsockopt = ip_setsockopt, diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 1faea9dce64..494933c8214 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -1324,6 +1324,12 @@ int ieee80211_reconfig(struct ieee80211_local *local) } } + /* add back keys */ + list_for_each_entry(sdata, &local->interfaces, list) + if (ieee80211_sdata_running(sdata)) + ieee80211_enable_keys(sdata); + + wake_up: /* * Clear the WLAN_STA_BLOCK_BA flag so new aggregation * sessions can be established after a resume. @@ -1345,12 +1351,6 @@ int ieee80211_reconfig(struct ieee80211_local *local) mutex_unlock(&local->sta_mtx); } - /* add back keys */ - list_for_each_entry(sdata, &local->interfaces, list) - if (ieee80211_sdata_running(sdata)) - ieee80211_enable_keys(sdata); - - wake_up: ieee80211_wake_queues_by_reason(hw, IEEE80211_QUEUE_STOP_REASON_SUSPEND); diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index adf2990aceb..25302c80246 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c @@ -1288,6 +1288,8 @@ call_reserveresult(struct rpc_task *task) } switch (status) { + case -ENOMEM: + rpc_delay(task, HZ >> 2); case -EAGAIN: /* woken up; retry */ task->tk_action = call_reserve; return; diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index 0cbcd1ab49a..da72492360b 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c @@ -984,15 +984,16 @@ static void xprt_alloc_slot(struct rpc_task *task) goto out_init_req; switch (PTR_ERR(req)) { case -ENOMEM: - rpc_delay(task, HZ >> 2); dprintk("RPC: dynamic allocation of request slot " "failed! Retrying\n"); + task->tk_status = -ENOMEM; break; case -EAGAIN: rpc_sleep_on(&xprt->backlog, task, NULL); dprintk("RPC: waiting for request slot\n"); + default: + task->tk_status = -EAGAIN; } - task->tk_status = -EAGAIN; return; out_init_req: task->tk_status = 0; diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 7661576b6f4..a15d2a03172 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -1919,6 +1919,9 @@ struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig, } ok: xfrm_pols_put(pols, drop_pols); + if (dst && dst->xfrm && + dst->xfrm->props.mode == XFRM_MODE_TUNNEL) + dst->flags |= DST_XFRM_TUNNEL; return dst; nopol: diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 0eed6115c2d..67a4d6dbb32 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -699,6 +699,9 @@ static int snd_usb_pcm_check_knot(struct snd_pcm_runtime *runtime, int count = 0, needs_knot = 0; int err; + kfree(subs->rate_list.list); + subs->rate_list.list = NULL; + list_for_each_entry(fp, &subs->fmt_list, list) { if (fp->rates & SNDRV_PCM_RATE_CONTINUOUS) return 0; diff --git a/tools/vm/page-types.c b/tools/vm/page-types.c index 7dab7b25b5c..f77c96bec7e 100644 --- a/tools/vm/page-types.c +++ b/tools/vm/page-types.c @@ -35,6 +35,7 @@ #include #include #include "../../include/linux/magic.h" +#include "../../include/linux/kernel-page-flags.h" #ifndef MAX_PATH @@ -73,33 +74,6 @@ #define KPF_BYTES 8 #define PROC_KPAGEFLAGS "/proc/kpageflags" -/* copied from kpageflags_read() */ -#define KPF_LOCKED 0 -#define KPF_ERROR 1 -#define KPF_REFERENCED 2 -#define KPF_UPTODATE 3 -#define KPF_DIRTY 4 -#define KPF_LRU 5 -#define KPF_ACTIVE 6 -#define KPF_SLAB 7 -#define KPF_WRITEBACK 8 -#define KPF_RECLAIM 9 -#define KPF_BUDDY 10 - -/* [11-20] new additions in 2.6.31 */ -#define KPF_MMAP 11 -#define KPF_ANON 12 -#define KPF_SWAPCACHE 13 -#define KPF_SWAPBACKED 14 -#define KPF_COMPOUND_HEAD 15 -#define KPF_COMPOUND_TAIL 16 -#define KPF_HUGE 17 -#define KPF_UNEVICTABLE 18 -#define KPF_HWPOISON 19 -#define KPF_NOPAGE 20 -#define KPF_KSM 21 -#define KPF_THP 22 - /* [32-] kernel hacking assistances */ #define KPF_RESERVED 32 #define KPF_MLOCKED 33 From 3809182cb304e4d739d8b294a14940c4758ce16d Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Sat, 21 Dec 2013 10:00:09 +0100 Subject: [PATCH 072/215] Linux 3.4.3 --- Makefile | 2 +- arch/x86/crypto/aesni-intel_asm.S | 6 +- arch/x86/include/asm/uv/uv_bau.h | 1 - arch/x86/kernel/cpu/mcheck/mce_amd.c | 56 ++++++++-- arch/x86/platform/uv/tlb_uv.c | 1 - drivers/acpi/video.c | 5 +- drivers/ata/ata_piix.c | 36 ++++++ drivers/ata/libata-core.c | 6 + drivers/bcma/driver_chipcommon_pmu.c | 4 +- drivers/bcma/sprom.c | 4 +- drivers/char/agp/intel-agp.c | 1 + drivers/char/agp/intel-agp.h | 1 + drivers/char/hw_random/atmel-rng.c | 7 ++ drivers/gpu/drm/gma500/psb_drv.c | 2 +- drivers/gpu/drm/i915/intel_ringbuffer.c | 5 + drivers/gpu/drm/nouveau/nouveau_connector.c | 8 +- drivers/gpu/drm/radeon/evergreen_cs.c | 49 +++++++- drivers/gpu/drm/radeon/radeon_drv.c | 3 +- drivers/gpu/drm/ttm/ttm_bo.c | 13 +-- drivers/net/can/c_can/c_can.c | 16 +-- drivers/net/can/c_can/c_can.h | 1 + drivers/net/usb/sierra_net.c | 14 ++- drivers/net/wireless/iwlwifi/iwl-agn-sta.c | 2 +- drivers/net/wireless/iwlwifi/iwl-mac80211.c | 3 + drivers/net/wireless/iwlwifi/iwl-prph.h | 1 + drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 5 + drivers/net/wireless/rt2x00/rt2800usb.c | 25 +++-- drivers/net/wireless/rt2x00/rt2x00.h | 3 +- drivers/net/wireless/rt2x00/rt2x00mac.c | 1 - drivers/net/wireless/rt2x00/rt2x00queue.c | 13 +-- fs/btrfs/inode.c | 5 +- fs/ext4/balloc.c | 8 +- fs/fuse/dir.c | 1 + fs/fuse/fuse_i.h | 3 + fs/fuse/inode.c | 17 ++- include/linux/libata.h | 1 + include/linux/moduleparam.h | 10 +- init/main.c | 2 +- kernel/sched/core.c | 9 +- kernel/time/timekeeping.c | 2 + lib/btree.c | 4 +- net/mac80211/iface.c | 12 ++ net/mac80211/offchannel.c | 16 +++ net/mac80211/sta_info.c | 4 +- net/mac80211/util.c | 2 +- net/wireless/util.c | 19 +++- sound/pci/hda/patch_realtek.c | 9 ++ sound/soc/codecs/wm8994.c | 105 +++++++++++------- 48 files changed, 391 insertions(+), 132 deletions(-) diff --git a/Makefile b/Makefile index 63ac07f255c..9f65fd199b8 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 4 -SUBLEVEL = 2 +SUBLEVEL = 3 EXTRAVERSION = NAME = Saber-toothed Squirrel diff --git a/arch/x86/crypto/aesni-intel_asm.S b/arch/x86/crypto/aesni-intel_asm.S index be6d9e365a8..3470624d783 100644 --- a/arch/x86/crypto/aesni-intel_asm.S +++ b/arch/x86/crypto/aesni-intel_asm.S @@ -2460,10 +2460,12 @@ ENTRY(aesni_cbc_dec) pxor IN3, STATE4 movaps IN4, IV #else - pxor (INP), STATE2 - pxor 0x10(INP), STATE3 pxor IN1, STATE4 movaps IN2, IV + movups (INP), IN1 + pxor IN1, STATE2 + movups 0x10(INP), IN2 + pxor IN2, STATE3 #endif movups STATE1, (OUTP) movups STATE2, 0x10(OUTP) diff --git a/arch/x86/include/asm/uv/uv_bau.h b/arch/x86/include/asm/uv/uv_bau.h index becf47b8173..6149b476d9d 100644 --- a/arch/x86/include/asm/uv/uv_bau.h +++ b/arch/x86/include/asm/uv/uv_bau.h @@ -149,7 +149,6 @@ /* 4 bits of software ack period */ #define UV2_ACK_MASK 0x7UL #define UV2_ACK_UNITS_SHFT 3 -#define UV2_LEG_SHFT UV2H_LB_BAU_MISC_CONTROL_USE_LEGACY_DESCRIPTOR_FORMATS_SHFT #define UV2_EXT_SHFT UV2H_LB_BAU_MISC_CONTROL_ENABLE_EXTENDED_SB_STATUS_SHFT /* diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c index 25785f7d1ce..1405e0918b1 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_amd.c +++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c @@ -51,6 +51,7 @@ struct threshold_block { unsigned int cpu; u32 address; u16 interrupt_enable; + bool interrupt_capable; u16 threshold_limit; struct kobject kobj; struct list_head miscj; @@ -83,6 +84,21 @@ struct thresh_restart { u16 old_limit; }; +static bool lvt_interrupt_supported(unsigned int bank, u32 msr_high_bits) +{ + /* + * bank 4 supports APIC LVT interrupts implicitly since forever. + */ + if (bank == 4) + return true; + + /* + * IntP: interrupt present; if this bit is set, the thresholding + * bank can generate APIC LVT interrupts + */ + return msr_high_bits & BIT(28); +} + static int lvt_off_valid(struct threshold_block *b, int apic, u32 lo, u32 hi) { int msr = (hi & MASK_LVTOFF_HI) >> 20; @@ -104,8 +120,10 @@ static int lvt_off_valid(struct threshold_block *b, int apic, u32 lo, u32 hi) return 1; }; -/* must be called with correct cpu affinity */ -/* Called via smp_call_function_single() */ +/* + * Called via smp_call_function_single(), must be called with correct + * cpu affinity. + */ static void threshold_restart_bank(void *_tr) { struct thresh_restart *tr = _tr; @@ -128,6 +146,12 @@ static void threshold_restart_bank(void *_tr) (new_count & THRESHOLD_MAX); } + /* clear IntType */ + hi &= ~MASK_INT_TYPE_HI; + + if (!tr->b->interrupt_capable) + goto done; + if (tr->set_lvt_off) { if (lvt_off_valid(tr->b, tr->lvt_off, lo, hi)) { /* set new lvt offset */ @@ -136,9 +160,10 @@ static void threshold_restart_bank(void *_tr) } } - tr->b->interrupt_enable ? - (hi = (hi & ~MASK_INT_TYPE_HI) | INT_TYPE_APIC) : - (hi &= ~MASK_INT_TYPE_HI); + if (tr->b->interrupt_enable) + hi |= INT_TYPE_APIC; + + done: hi |= MASK_COUNT_EN_HI; wrmsr(tr->b->address, lo, hi); @@ -202,14 +227,17 @@ void mce_amd_feature_init(struct cpuinfo_x86 *c) if (shared_bank[bank] && c->cpu_core_id) break; - offset = setup_APIC_mce(offset, - (high & MASK_LVTOFF_HI) >> 20); - memset(&b, 0, sizeof(b)); - b.cpu = cpu; - b.bank = bank; - b.block = block; - b.address = address; + b.cpu = cpu; + b.bank = bank; + b.block = block; + b.address = address; + b.interrupt_capable = lvt_interrupt_supported(bank, high); + + if (b.interrupt_capable) { + int new = (high & MASK_LVTOFF_HI) >> 20; + offset = setup_APIC_mce(offset, new); + } mce_threshold_block_init(&b, offset); mce_threshold_vector = amd_threshold_interrupt; @@ -309,6 +337,9 @@ store_interrupt_enable(struct threshold_block *b, const char *buf, size_t size) struct thresh_restart tr; unsigned long new; + if (!b->interrupt_capable) + return -EINVAL; + if (strict_strtoul(buf, 0, &new) < 0) return -EINVAL; @@ -467,6 +498,7 @@ static int allocate_threshold_blocks(unsigned int cpu, b->cpu = cpu; b->address = address; b->interrupt_enable = 0; + b->interrupt_capable = lvt_interrupt_supported(bank, high); b->threshold_limit = THRESHOLD_MAX; INIT_LIST_HEAD(&b->miscj); diff --git a/arch/x86/platform/uv/tlb_uv.c b/arch/x86/platform/uv/tlb_uv.c index 3ae0e61abd2..59880afa851 100644 --- a/arch/x86/platform/uv/tlb_uv.c +++ b/arch/x86/platform/uv/tlb_uv.c @@ -1295,7 +1295,6 @@ static void __init enable_timeouts(void) */ mmr_image |= (1L << SOFTACK_MSHIFT); if (is_uv2_hub()) { - mmr_image &= ~(1L << UV2_LEG_SHFT); mmr_image |= (1L << UV2_EXT_SHFT); } write_mmr_misc_control(pnode, mmr_image); diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 9577b6fa265..66e8f7333e9 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -1745,6 +1745,7 @@ static int acpi_video_bus_remove(struct acpi_device *device, int type) static int __init intel_opregion_present(void) { + int i915 = 0; #if defined(CONFIG_DRM_I915) || defined(CONFIG_DRM_I915_MODULE) struct pci_dev *dev = NULL; u32 address; @@ -1757,10 +1758,10 @@ static int __init intel_opregion_present(void) pci_read_config_dword(dev, 0xfc, &address); if (!address) continue; - return 1; + i915 = 1; } #endif - return 0; + return i915; } int acpi_video_register(void) diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index 7857e8fd0a3..3c809bfbccf 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -1554,6 +1554,39 @@ static bool piix_broken_system_poweroff(struct pci_dev *pdev) return false; } +static int prefer_ms_hyperv = 1; +module_param(prefer_ms_hyperv, int, 0); + +static void piix_ignore_devices_quirk(struct ata_host *host) +{ +#if IS_ENABLED(CONFIG_HYPERV_STORAGE) + static const struct dmi_system_id ignore_hyperv[] = { + { + /* On Hyper-V hypervisors the disks are exposed on + * both the emulated SATA controller and on the + * paravirtualised drivers. The CD/DVD devices + * are only exposed on the emulated controller. + * Request we ignore ATA devices on this host. + */ + .ident = "Hyper-V Virtual Machine", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, + "Microsoft Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"), + }, + }, + { } /* terminate list */ + }; + const struct dmi_system_id *dmi = dmi_first_match(ignore_hyperv); + + if (dmi && prefer_ms_hyperv) { + host->flags |= ATA_HOST_IGNORE_ATA; + dev_info(host->dev, "%s detected, ATA device ignore set\n", + dmi->ident); + } +#endif +} + /** * piix_init_one - Register PIIX ATA PCI device with kernel services * @pdev: PCI device to register @@ -1669,6 +1702,9 @@ static int __devinit piix_init_one(struct pci_dev *pdev, } host->flags |= ATA_HOST_PARALLEL_SCAN; + /* Allow hosts to specify device types to ignore when scanning. */ + piix_ignore_devices_quirk(host); + pci_set_master(pdev); return ata_pci_sff_activate_host(host, ata_bmdma_interrupt, sht); } diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 23763a1ec57..d31ee557b39 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -1973,6 +1973,12 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class, if (class == ATA_DEV_ATA) { if (!ata_id_is_ata(id) && !ata_id_is_cfa(id)) goto err_out; + if (ap->host->flags & ATA_HOST_IGNORE_ATA && + ata_id_is_ata(id)) { + ata_dev_dbg(dev, + "host indicates ignore ATA devices, ignored\n"); + return -ENOENT; + } } else { if (ata_id_is_ata(id)) goto err_out; diff --git a/drivers/bcma/driver_chipcommon_pmu.c b/drivers/bcma/driver_chipcommon_pmu.c index a058842f14f..61ce4054b3c 100644 --- a/drivers/bcma/driver_chipcommon_pmu.c +++ b/drivers/bcma/driver_chipcommon_pmu.c @@ -139,7 +139,9 @@ void bcma_pmu_workarounds(struct bcma_drv_cc *cc) bcma_chipco_chipctl_maskset(cc, 0, ~0, 0x7); break; case 0x4331: - /* BCM4331 workaround is SPROM-related, we put it in sprom.c */ + case 43431: + /* Ext PA lines must be enabled for tx on BCM4331 */ + bcma_chipco_bcm4331_ext_pa_lines_ctl(cc, true); break; case 43224: if (bus->chipinfo.rev == 0) { diff --git a/drivers/bcma/sprom.c b/drivers/bcma/sprom.c index 3e2a6002aae..4588da2729b 100644 --- a/drivers/bcma/sprom.c +++ b/drivers/bcma/sprom.c @@ -432,13 +432,13 @@ int bcma_sprom_get(struct bcma_bus *bus) if (!sprom) return -ENOMEM; - if (bus->chipinfo.id == 0x4331) + if (bus->chipinfo.id == 0x4331 || bus->chipinfo.id == 43431) bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, false); pr_debug("SPROM offset 0x%x\n", offset); bcma_sprom_read(bus, offset, sprom); - if (bus->chipinfo.id == 0x4331) + if (bus->chipinfo.id == 0x4331 || bus->chipinfo.id == 43431) bcma_chipco_bcm4331_ext_pa_lines_ctl(&bus->drv_cc, true); err = bcma_sprom_valid(sprom); diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index 962e75dc478..4293c484056 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c @@ -898,6 +898,7 @@ static struct pci_device_id agp_intel_pci_table[] = { ID(PCI_DEVICE_ID_INTEL_B43_HB), ID(PCI_DEVICE_ID_INTEL_B43_1_HB), ID(PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB), + ID(PCI_DEVICE_ID_INTEL_IRONLAKE_D2_HB), ID(PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB), ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB), ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB), diff --git a/drivers/char/agp/intel-agp.h b/drivers/char/agp/intel-agp.h index 7ea18a5fe71..439d7e7553b 100644 --- a/drivers/char/agp/intel-agp.h +++ b/drivers/char/agp/intel-agp.h @@ -211,6 +211,7 @@ #define PCI_DEVICE_ID_INTEL_G41_HB 0x2E30 #define PCI_DEVICE_ID_INTEL_G41_IG 0x2E32 #define PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB 0x0040 +#define PCI_DEVICE_ID_INTEL_IRONLAKE_D2_HB 0x0069 #define PCI_DEVICE_ID_INTEL_IRONLAKE_D_IG 0x0042 #define PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB 0x0044 #define PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB 0x0062 diff --git a/drivers/char/hw_random/atmel-rng.c b/drivers/char/hw_random/atmel-rng.c index f518b99f53f..6289f0eee24 100644 --- a/drivers/char/hw_random/atmel-rng.c +++ b/drivers/char/hw_random/atmel-rng.c @@ -36,6 +36,13 @@ static int atmel_trng_read(struct hwrng *rng, void *buf, size_t max, /* data ready? */ if (readl(trng->base + TRNG_ODATA) & 1) { *data = readl(trng->base + TRNG_ODATA); + /* + ensure data ready is only set again AFTER the next data + word is ready in case it got set between checking ISR + and reading ODATA, so we don't risk re-reading the + same word + */ + readl(trng->base + TRNG_ISR); return 4; } else return 0; diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c index c34adf9d910..09af2ffbb30 100644 --- a/drivers/gpu/drm/gma500/psb_drv.c +++ b/drivers/gpu/drm/gma500/psb_drv.c @@ -349,7 +349,7 @@ static int psb_driver_load(struct drm_device *dev, unsigned long chipset) PSB_WSGX32(0x30000000, PSB_CR_BIF_3D_REQ_BASE); /* igd_opregion_init(&dev_priv->opregion_dev); */ - acpi_video_register(); +/* acpi_video_register(); */ if (dev_priv->lid_state) psb_lid_timer_init(dev_priv); diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 62892a826ed..302d3d54fb4 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -309,6 +309,7 @@ static int init_ring_common(struct intel_ring_buffer *ring) ring->head = I915_READ_HEAD(ring); ring->tail = I915_READ_TAIL(ring) & TAIL_ADDR; ring->space = ring_space(ring); + ring->last_retired_head = -1; } return 0; @@ -1026,6 +1027,10 @@ int intel_init_ring_buffer(struct drm_device *dev, if (ret) goto err_unref; + ret = i915_gem_object_set_to_gtt_domain(obj, true); + if (ret) + goto err_unpin; + ring->map.size = ring->size; ring->map.offset = dev->agp->base + obj->gtt_offset; ring->map.type = 0; diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index fa860358add..7b11edb077d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -654,7 +654,13 @@ nouveau_connector_detect_depth(struct drm_connector *connector) if (nv_connector->edid && connector->display_info.bpc) return; - /* if not, we're out of options unless we're LVDS, default to 8bpc */ + /* EDID 1.4 is *supposed* to be supported on eDP, but, Apple... */ + if (nv_connector->type == DCB_CONNECTOR_eDP) { + connector->display_info.bpc = 6; + return; + } + + /* we're out of options unless we're LVDS, default to 8bpc */ if (nv_encoder->dcb->type != OUTPUT_LVDS) { connector->display_info.bpc = 8; return; diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c index 70089d32b80..ea69daeffac 100644 --- a/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/drivers/gpu/drm/radeon/evergreen_cs.c @@ -52,6 +52,7 @@ struct evergreen_cs_track { u32 cb_color_view[12]; u32 cb_color_pitch[12]; u32 cb_color_slice[12]; + u32 cb_color_slice_idx[12]; u32 cb_color_attrib[12]; u32 cb_color_cmask_slice[8];/* unused */ u32 cb_color_fmask_slice[8];/* unused */ @@ -127,12 +128,14 @@ static void evergreen_cs_track_init(struct evergreen_cs_track *track) track->cb_color_info[i] = 0; track->cb_color_view[i] = 0xFFFFFFFF; track->cb_color_pitch[i] = 0; - track->cb_color_slice[i] = 0; + track->cb_color_slice[i] = 0xfffffff; + track->cb_color_slice_idx[i] = 0; } track->cb_target_mask = 0xFFFFFFFF; track->cb_shader_mask = 0xFFFFFFFF; track->cb_dirty = true; + track->db_depth_slice = 0xffffffff; track->db_depth_view = 0xFFFFC000; track->db_depth_size = 0xFFFFFFFF; track->db_depth_control = 0xFFFFFFFF; @@ -250,10 +253,9 @@ static int evergreen_surface_check_2d(struct radeon_cs_parser *p, { struct evergreen_cs_track *track = p->track; unsigned palign, halign, tileb, slice_pt; + unsigned mtile_pr, mtile_ps, mtileb; tileb = 64 * surf->bpe * surf->nsamples; - palign = track->group_size / (8 * surf->bpe * surf->nsamples); - palign = MAX(8, palign); slice_pt = 1; if (tileb > surf->tsplit) { slice_pt = tileb / surf->tsplit; @@ -262,7 +264,10 @@ static int evergreen_surface_check_2d(struct radeon_cs_parser *p, /* macro tile width & height */ palign = (8 * surf->bankw * track->npipes) * surf->mtilea; halign = (8 * surf->bankh * surf->nbanks) / surf->mtilea; - surf->layer_size = surf->nbx * surf->nby * surf->bpe * slice_pt; + mtileb = (palign / 8) * (halign / 8) * tileb;; + mtile_pr = surf->nbx / palign; + mtile_ps = (mtile_pr * surf->nby) / halign; + surf->layer_size = mtile_ps * mtileb * slice_pt; surf->base_align = (palign / 8) * (halign / 8) * tileb; surf->palign = palign; surf->halign = halign; @@ -434,6 +439,39 @@ static int evergreen_cs_track_validate_cb(struct radeon_cs_parser *p, unsigned i offset += surf.layer_size * mslice; if (offset > radeon_bo_size(track->cb_color_bo[id])) { + /* old ddx are broken they allocate bo with w*h*bpp but + * program slice with ALIGN(h, 8), catch this and patch + * command stream. + */ + if (!surf.mode) { + volatile u32 *ib = p->ib->ptr; + unsigned long tmp, nby, bsize, size, min = 0; + + /* find the height the ddx wants */ + if (surf.nby > 8) { + min = surf.nby - 8; + } + bsize = radeon_bo_size(track->cb_color_bo[id]); + tmp = track->cb_color_bo_offset[id] << 8; + for (nby = surf.nby; nby > min; nby--) { + size = nby * surf.nbx * surf.bpe * surf.nsamples; + if ((tmp + size * mslice) <= bsize) { + break; + } + } + if (nby > min) { + surf.nby = nby; + slice = ((nby * surf.nbx) / 64) - 1; + if (!evergreen_surface_check(p, &surf, "cb")) { + /* check if this one works */ + tmp += surf.layer_size * mslice; + if (tmp <= bsize) { + ib[track->cb_color_slice_idx[id]] = slice; + goto old_ddx_ok; + } + } + } + } dev_warn(p->dev, "%s:%d cb[%d] bo too small (layer size %d, " "offset %d, max layer %d, bo size %ld, slice %d)\n", __func__, __LINE__, id, surf.layer_size, @@ -446,6 +484,7 @@ static int evergreen_cs_track_validate_cb(struct radeon_cs_parser *p, unsigned i surf.tsplit, surf.mtilea); return -EINVAL; } +old_ddx_ok: return 0; } @@ -1532,6 +1571,7 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) case CB_COLOR7_SLICE: tmp = (reg - CB_COLOR0_SLICE) / 0x3c; track->cb_color_slice[tmp] = radeon_get_ib_value(p, idx); + track->cb_color_slice_idx[tmp] = idx; track->cb_dirty = true; break; case CB_COLOR8_SLICE: @@ -1540,6 +1580,7 @@ static int evergreen_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) case CB_COLOR11_SLICE: tmp = ((reg - CB_COLOR8_SLICE) / 0x1c) + 8; track->cb_color_slice[tmp] = radeon_get_ib_value(p, idx); + track->cb_color_slice_idx[tmp] = idx; track->cb_dirty = true; break; case CB_COLOR0_ATTRIB: diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index ef7bb3f6eca..15250fbee7d 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -57,9 +57,10 @@ * 2.13.0 - virtual memory support, streamout * 2.14.0 - add evergreen tiling informations * 2.15.0 - add max_pipes query + * 2.16.0 - fix evergreen 2D tiled surface calculation */ #define KMS_DRIVER_MAJOR 2 -#define KMS_DRIVER_MINOR 15 +#define KMS_DRIVER_MINOR 16 #define KMS_DRIVER_PATCHLEVEL 0 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); int radeon_driver_unload_kms(struct drm_device *dev); diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 18434186ed1..8b73ae84efe 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -1193,6 +1193,7 @@ int ttm_bo_init(struct ttm_bo_device *bdev, (*destroy)(bo); else kfree(bo); + ttm_mem_global_free(mem_glob, acc_size); return -EINVAL; } bo->destroy = destroy; @@ -1294,22 +1295,14 @@ int ttm_bo_create(struct ttm_bo_device *bdev, struct ttm_buffer_object **p_bo) { struct ttm_buffer_object *bo; - struct ttm_mem_global *mem_glob = bdev->glob->mem_glob; size_t acc_size; int ret; - acc_size = ttm_bo_acc_size(bdev, size, sizeof(struct ttm_buffer_object)); - ret = ttm_mem_global_alloc(mem_glob, acc_size, false, false); - if (unlikely(ret != 0)) - return ret; - bo = kzalloc(sizeof(*bo), GFP_KERNEL); - - if (unlikely(bo == NULL)) { - ttm_mem_global_free(mem_glob, acc_size); + if (unlikely(bo == NULL)) return -ENOMEM; - } + acc_size = ttm_bo_acc_size(bdev, size, sizeof(struct ttm_buffer_object)); ret = ttm_bo_init(bdev, bo, size, type, placement, page_alignment, buffer_start, interruptible, persistent_swap_storage, acc_size, NULL); diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c index 536bda072a1..8dc84d66eea 100644 --- a/drivers/net/can/c_can/c_can.c +++ b/drivers/net/can/c_can/c_can.c @@ -686,7 +686,7 @@ static int c_can_get_berr_counter(const struct net_device *dev, * * We iterate from priv->tx_echo to priv->tx_next and check if the * packet has been transmitted, echo it back to the CAN framework. - * If we discover a not yet transmitted package, stop looking for more. + * If we discover a not yet transmitted packet, stop looking for more. */ static void c_can_do_tx(struct net_device *dev) { @@ -698,7 +698,7 @@ static void c_can_do_tx(struct net_device *dev) for (/* nix */; (priv->tx_next - priv->tx_echo) > 0; priv->tx_echo++) { msg_obj_no = get_tx_echo_msg_obj(priv); val = c_can_read_reg32(priv, &priv->regs->txrqst1); - if (!(val & (1 << msg_obj_no))) { + if (!(val & (1 << (msg_obj_no - 1)))) { can_get_echo_skb(dev, msg_obj_no - C_CAN_MSG_OBJ_TX_FIRST); stats->tx_bytes += priv->read_reg(priv, @@ -706,6 +706,8 @@ static void c_can_do_tx(struct net_device *dev) & IF_MCONT_DLC_MASK; stats->tx_packets++; c_can_inval_msg_object(dev, 0, msg_obj_no); + } else { + break; } } @@ -950,7 +952,7 @@ static int c_can_poll(struct napi_struct *napi, int quota) struct net_device *dev = napi->dev; struct c_can_priv *priv = netdev_priv(dev); - irqstatus = priv->read_reg(priv, &priv->regs->interrupt); + irqstatus = priv->irqstatus; if (!irqstatus) goto end; @@ -1028,12 +1030,11 @@ static int c_can_poll(struct napi_struct *napi, int quota) static irqreturn_t c_can_isr(int irq, void *dev_id) { - u16 irqstatus; struct net_device *dev = (struct net_device *)dev_id; struct c_can_priv *priv = netdev_priv(dev); - irqstatus = priv->read_reg(priv, &priv->regs->interrupt); - if (!irqstatus) + priv->irqstatus = priv->read_reg(priv, &priv->regs->interrupt); + if (!priv->irqstatus) return IRQ_NONE; /* disable all interrupts and schedule the NAPI */ @@ -1063,10 +1064,11 @@ static int c_can_open(struct net_device *dev) goto exit_irq_fail; } + napi_enable(&priv->napi); + /* start the c_can controller */ c_can_start(dev); - napi_enable(&priv->napi); netif_start_queue(dev); return 0; diff --git a/drivers/net/can/c_can/c_can.h b/drivers/net/can/c_can/c_can.h index 9b7fbef3d09..5f32d34af50 100644 --- a/drivers/net/can/c_can/c_can.h +++ b/drivers/net/can/c_can/c_can.h @@ -76,6 +76,7 @@ struct c_can_priv { unsigned int tx_next; unsigned int tx_echo; void *priv; /* for board-specific data */ + u16 irqstatus; }; struct net_device *alloc_c_can_dev(void); diff --git a/drivers/net/usb/sierra_net.c b/drivers/net/usb/sierra_net.c index b59cf20c781..cc9776c2a39 100644 --- a/drivers/net/usb/sierra_net.c +++ b/drivers/net/usb/sierra_net.c @@ -946,7 +946,7 @@ struct sk_buff *sierra_net_tx_fixup(struct usbnet *dev, struct sk_buff *skb, } static const u8 sierra_net_ifnum_list[] = { 7, 10, 11 }; -static const struct sierra_net_info_data sierra_net_info_data_68A3 = { +static const struct sierra_net_info_data sierra_net_info_data_direct_ip = { .rx_urb_size = 8 * 1024, .whitelist = { .infolen = ARRAY_SIZE(sierra_net_ifnum_list), @@ -954,7 +954,7 @@ static const struct sierra_net_info_data sierra_net_info_data_68A3 = { } }; -static const struct driver_info sierra_net_info_68A3 = { +static const struct driver_info sierra_net_info_direct_ip = { .description = "Sierra Wireless USB-to-WWAN Modem", .flags = FLAG_WWAN | FLAG_SEND_ZLP, .bind = sierra_net_bind, @@ -962,12 +962,18 @@ static const struct driver_info sierra_net_info_68A3 = { .status = sierra_net_status, .rx_fixup = sierra_net_rx_fixup, .tx_fixup = sierra_net_tx_fixup, - .data = (unsigned long)&sierra_net_info_data_68A3, + .data = (unsigned long)&sierra_net_info_data_direct_ip, }; static const struct usb_device_id products[] = { {USB_DEVICE(0x1199, 0x68A3), /* Sierra Wireless USB-to-WWAN modem */ - .driver_info = (unsigned long) &sierra_net_info_68A3}, + .driver_info = (unsigned long) &sierra_net_info_direct_ip}, + {USB_DEVICE(0x0F3D, 0x68A3), /* AT&T Direct IP modem */ + .driver_info = (unsigned long) &sierra_net_info_direct_ip}, + {USB_DEVICE(0x1199, 0x68AA), /* Sierra Wireless Direct IP LTE modem */ + .driver_info = (unsigned long) &sierra_net_info_direct_ip}, + {USB_DEVICE(0x0F3D, 0x68AA), /* AT&T Direct IP LTE modem */ + .driver_info = (unsigned long) &sierra_net_info_direct_ip}, {}, /* last item */ }; diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c index c4175603864..bef3f242434 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c @@ -1222,7 +1222,7 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv, key_flags |= STA_KEY_MULTICAST_MSK; sta_cmd.key.key_flags = key_flags; - sta_cmd.key.key_offset = WEP_INVALID_OFFSET; + sta_cmd.key.key_offset = keyconf->hw_key_idx; sta_cmd.sta.modify_mask = STA_MODIFY_KEY_MASK; sta_cmd.mode = STA_CONTROL_MODIFY_MSK; diff --git a/drivers/net/wireless/iwlwifi/iwl-mac80211.c b/drivers/net/wireless/iwlwifi/iwl-mac80211.c index c24a7134a6f..1018f9b8b41 100644 --- a/drivers/net/wireless/iwlwifi/iwl-mac80211.c +++ b/drivers/net/wireless/iwlwifi/iwl-mac80211.c @@ -196,6 +196,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv, WIPHY_FLAG_DISABLE_BEACON_HINTS | WIPHY_FLAG_IBSS_RSN; +#ifdef CONFIG_PM_SLEEP if (priv->fw->img[IWL_UCODE_WOWLAN].sec[0].len && trans(priv)->ops->wowlan_suspend && device_can_wakeup(trans(priv)->dev)) { @@ -214,6 +215,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv, hw->wiphy->wowlan.pattern_max_len = IWLAGN_WOWLAN_MAX_PATTERN_LEN; } +#endif if (iwlagn_mod_params.power_save) hw->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; @@ -243,6 +245,7 @@ int iwlagn_mac_setup_register(struct iwl_priv *priv, ret = ieee80211_register_hw(priv->hw); if (ret) { IWL_ERR(priv, "Failed to register hw (error %d)\n", ret); + iwl_leds_exit(priv); return ret; } priv->mac80211_registered = 1; diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h index 3b1069290fa..dfd54662e3e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/iwlwifi/iwl-prph.h @@ -224,6 +224,7 @@ #define SCD_TXFACT (SCD_BASE + 0x10) #define SCD_ACTIVE (SCD_BASE + 0x14) #define SCD_QUEUECHAIN_SEL (SCD_BASE + 0xe8) +#define SCD_CHAINEXT_EN (SCD_BASE + 0x244) #define SCD_AGGR_SEL (SCD_BASE + 0x248) #define SCD_INTERRUPT_MASK (SCD_BASE + 0x108) diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index 4d7b30d3e64..66df0166cfd 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c @@ -1128,6 +1128,11 @@ static void iwl_tx_start(struct iwl_trans *trans) iwl_write_prph(trans, SCD_DRAM_BASE_ADDR, trans_pcie->scd_bc_tbls.dma >> 10); + /* The chain extension of the SCD doesn't work well. This feature is + * enabled by default by the HW, so we need to disable it manually. + */ + iwl_write_prph(trans, SCD_CHAINEXT_EN, 0); + /* Enable DMA channel */ for (chan = 0; chan < FH_TCSR_CHNL_NUM ; chan++) iwl_write_direct32(trans, FH_TCSR_CHNL_TX_CONFIG_REG(chan), diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 001735f7a66..5601302d09a 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -922,6 +922,7 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x1482, 0x3c09) }, /* AirTies */ { USB_DEVICE(0x1eda, 0x2012) }, + { USB_DEVICE(0x1eda, 0x2210) }, { USB_DEVICE(0x1eda, 0x2310) }, /* Allwin */ { USB_DEVICE(0x8516, 0x2070) }, @@ -991,6 +992,7 @@ static struct usb_device_id rt2800usb_device_table[] = { /* DVICO */ { USB_DEVICE(0x0fe9, 0xb307) }, /* Edimax */ + { USB_DEVICE(0x7392, 0x4085) }, { USB_DEVICE(0x7392, 0x7711) }, { USB_DEVICE(0x7392, 0x7717) }, { USB_DEVICE(0x7392, 0x7718) }, @@ -1066,6 +1068,7 @@ static struct usb_device_id rt2800usb_device_table[] = { /* Philips */ { USB_DEVICE(0x0471, 0x200f) }, /* Planex */ + { USB_DEVICE(0x2019, 0x5201) }, { USB_DEVICE(0x2019, 0xab25) }, { USB_DEVICE(0x2019, 0xed06) }, /* Quanta */ @@ -1134,6 +1137,10 @@ static struct usb_device_id rt2800usb_device_table[] = { #ifdef CONFIG_RT2800USB_RT33XX /* Belkin */ { USB_DEVICE(0x050d, 0x945b) }, + /* Panasonic */ + { USB_DEVICE(0x083a, 0xb511) }, + /* Philips */ + { USB_DEVICE(0x0471, 0x20dd) }, /* Ralink */ { USB_DEVICE(0x148f, 0x3370) }, { USB_DEVICE(0x148f, 0x8070) }, @@ -1145,6 +1152,8 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x8516, 0x3572) }, /* Askey */ { USB_DEVICE(0x1690, 0x0744) }, + { USB_DEVICE(0x1690, 0x0761) }, + { USB_DEVICE(0x1690, 0x0764) }, /* Cisco */ { USB_DEVICE(0x167b, 0x4001) }, /* EnGenius */ @@ -1159,20 +1168,25 @@ static struct usb_device_id rt2800usb_device_table[] = { /* Sitecom */ { USB_DEVICE(0x0df6, 0x0041) }, { USB_DEVICE(0x0df6, 0x0062) }, + { USB_DEVICE(0x0df6, 0x0065) }, + { USB_DEVICE(0x0df6, 0x0066) }, + { USB_DEVICE(0x0df6, 0x0068) }, /* Toshiba */ { USB_DEVICE(0x0930, 0x0a07) }, /* Zinwell */ { USB_DEVICE(0x5a57, 0x0284) }, #endif #ifdef CONFIG_RT2800USB_RT53XX - /* Alpha */ - { USB_DEVICE(0x2001, 0x3c15) }, - { USB_DEVICE(0x2001, 0x3c19) }, /* Arcadyan */ { USB_DEVICE(0x043e, 0x7a12) }, /* Azurewave */ { USB_DEVICE(0x13d3, 0x3329) }, { USB_DEVICE(0x13d3, 0x3365) }, + /* D-Link */ + { USB_DEVICE(0x2001, 0x3c15) }, + { USB_DEVICE(0x2001, 0x3c19) }, + { USB_DEVICE(0x2001, 0x3c1c) }, + { USB_DEVICE(0x2001, 0x3c1d) }, /* LG innotek */ { USB_DEVICE(0x043e, 0x7a22) }, /* Panasonic */ @@ -1224,12 +1238,8 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x07d1, 0x3c0b) }, { USB_DEVICE(0x07d1, 0x3c17) }, { USB_DEVICE(0x2001, 0x3c17) }, - /* Edimax */ - { USB_DEVICE(0x7392, 0x4085) }, /* Encore */ { USB_DEVICE(0x203d, 0x14a1) }, - /* Fujitsu Stylistic 550 */ - { USB_DEVICE(0x1690, 0x0761) }, /* Gemtek */ { USB_DEVICE(0x15a9, 0x0010) }, /* Gigabyte */ @@ -1250,7 +1260,6 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x05a6, 0x0101) }, { USB_DEVICE(0x1d4d, 0x0010) }, /* Planex */ - { USB_DEVICE(0x2019, 0x5201) }, { USB_DEVICE(0x2019, 0xab24) }, /* Qcom */ { USB_DEVICE(0x18e8, 0x6259) }, diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index 471f87cab4a..c264dfa6e61 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h @@ -396,8 +396,7 @@ struct rt2x00_intf { * for hardware which doesn't support hardware * sequence counting. */ - spinlock_t seqlock; - u16 seqno; + atomic_t seqno; }; static inline struct rt2x00_intf* vif_to_intf(struct ieee80211_vif *vif) diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index 2df2eb6d3e0..a8885f06006 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -277,7 +277,6 @@ int rt2x00mac_add_interface(struct ieee80211_hw *hw, else rt2x00dev->intf_sta_count++; - spin_lock_init(&intf->seqlock); mutex_init(&intf->beacon_skb_mutex); intf->beacon = entry; diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 9b1b2b7a780..50f92d5a2bd 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -207,6 +207,7 @@ static void rt2x00queue_create_tx_descriptor_seq(struct rt2x00_dev *rt2x00dev, struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif); + u16 seqno; if (!(tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)) return; @@ -227,15 +228,13 @@ static void rt2x00queue_create_tx_descriptor_seq(struct rt2x00_dev *rt2x00dev, * sequence counting per-frame, since those will override the * sequence counter given by mac80211. */ - spin_lock(&intf->seqlock); - if (test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags)) - intf->seqno += 0x10; - hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); - hdr->seq_ctrl |= cpu_to_le16(intf->seqno); - - spin_unlock(&intf->seqlock); + seqno = atomic_add_return(0x10, &intf->seqno); + else + seqno = atomic_read(&intf->seqno); + hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); + hdr->seq_ctrl |= cpu_to_le16(seqno); } static void rt2x00queue_create_tx_descriptor_plcp(struct rt2x00_dev *rt2x00dev, diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 61b16c641ce..0df0d1fd4fe 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -257,10 +257,13 @@ static noinline int cow_file_range_inline(struct btrfs_trans_handle *trans, ret = insert_inline_extent(trans, root, inode, start, inline_len, compressed_size, compress_type, compressed_pages); - if (ret) { + if (ret && ret != -ENOSPC) { btrfs_abort_transaction(trans, root, ret); return ret; + } else if (ret == -ENOSPC) { + return 1; } + btrfs_delalloc_release_metadata(inode, end + 1 - start); btrfs_drop_extent_cache(inode, start, aligned_end - 1, 0); return 0; diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index 4bbd07a6fa1..8da837be0c8 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c @@ -90,8 +90,8 @@ unsigned ext4_num_overhead_clusters(struct super_block *sb, * unusual file system layouts. */ if (ext4_block_in_group(sb, ext4_block_bitmap(sb, gdp), block_group)) { - block_cluster = EXT4_B2C(sbi, (start - - ext4_block_bitmap(sb, gdp))); + block_cluster = EXT4_B2C(sbi, + ext4_block_bitmap(sb, gdp) - start); if (block_cluster < num_clusters) block_cluster = -1; else if (block_cluster == num_clusters) { @@ -102,7 +102,7 @@ unsigned ext4_num_overhead_clusters(struct super_block *sb, if (ext4_block_in_group(sb, ext4_inode_bitmap(sb, gdp), block_group)) { inode_cluster = EXT4_B2C(sbi, - start - ext4_inode_bitmap(sb, gdp)); + ext4_inode_bitmap(sb, gdp) - start); if (inode_cluster < num_clusters) inode_cluster = -1; else if (inode_cluster == num_clusters) { @@ -114,7 +114,7 @@ unsigned ext4_num_overhead_clusters(struct super_block *sb, itbl_blk = ext4_inode_table(sb, gdp); for (i = 0; i < sbi->s_itb_per_group; i++) { if (ext4_block_in_group(sb, itbl_blk + i, block_group)) { - c = EXT4_B2C(sbi, start - itbl_blk + i); + c = EXT4_B2C(sbi, itbl_blk + i - start); if ((c < num_clusters) || (c == inode_cluster) || (c == block_cluster) || (c == itbl_cluster)) continue; diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index df5ac048dc7..bc438320cac 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -863,6 +863,7 @@ int fuse_update_attributes(struct inode *inode, struct kstat *stat, if (stat) { generic_fillattr(inode, stat); stat->mode = fi->orig_i_mode; + stat->ino = fi->orig_ino; } } diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 572cefc7801..d1819269aab 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -82,6 +82,9 @@ struct fuse_inode { preserve the original mode */ umode_t orig_i_mode; + /** 64 bit inode number */ + u64 orig_ino; + /** Version of last attribute change */ u64 attr_version; diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 26783eb2b1f..a59cf5e673d 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -91,6 +91,7 @@ static struct inode *fuse_alloc_inode(struct super_block *sb) fi->nlookup = 0; fi->attr_version = 0; fi->writectr = 0; + fi->orig_ino = 0; INIT_LIST_HEAD(&fi->write_files); INIT_LIST_HEAD(&fi->queued_writes); INIT_LIST_HEAD(&fi->writepages); @@ -139,6 +140,18 @@ static int fuse_remount_fs(struct super_block *sb, int *flags, char *data) return 0; } +/* + * ino_t is 32-bits on 32-bit arch. We have to squash the 64-bit value down + * so that it will fit. + */ +static ino_t fuse_squash_ino(u64 ino64) +{ + ino_t ino = (ino_t) ino64; + if (sizeof(ino_t) < sizeof(u64)) + ino ^= ino64 >> (sizeof(u64) - sizeof(ino_t)) * 8; + return ino; +} + void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr, u64 attr_valid) { @@ -148,7 +161,7 @@ void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr, fi->attr_version = ++fc->attr_version; fi->i_time = attr_valid; - inode->i_ino = attr->ino; + inode->i_ino = fuse_squash_ino(attr->ino); inode->i_mode = (inode->i_mode & S_IFMT) | (attr->mode & 07777); set_nlink(inode, attr->nlink); inode->i_uid = attr->uid; @@ -174,6 +187,8 @@ void fuse_change_attributes_common(struct inode *inode, struct fuse_attr *attr, fi->orig_i_mode = inode->i_mode; if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS)) inode->i_mode &= ~S_ISVTX; + + fi->orig_ino = attr->ino; } void fuse_change_attributes(struct inode *inode, struct fuse_attr *attr, diff --git a/include/linux/libata.h b/include/linux/libata.h index e926df7b54c..6e887c742a2 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -247,6 +247,7 @@ enum { ATA_HOST_SIMPLEX = (1 << 0), /* Host is simplex, one DMA channel per host only */ ATA_HOST_STARTED = (1 << 1), /* Host started */ ATA_HOST_PARALLEL_SCAN = (1 << 2), /* Ports on this host can be scanned in parallel */ + ATA_HOST_IGNORE_ATA = (1 << 3), /* Ignore ATA devices on this host. */ /* bits 24:31 of host->flags are reserved for LLD specific flags */ diff --git a/include/linux/moduleparam.h b/include/linux/moduleparam.h index ea36486378d..944bc186ea3 100644 --- a/include/linux/moduleparam.h +++ b/include/linux/moduleparam.h @@ -128,7 +128,7 @@ struct kparam_array * The ops can have NULL set or get functions. */ #define module_param_cb(name, ops, arg, perm) \ - __module_param_call(MODULE_PARAM_PREFIX, name, ops, arg, perm, 0) + __module_param_call(MODULE_PARAM_PREFIX, name, ops, arg, perm, -1) /** * _param_cb - general callback for a module/cmdline parameter @@ -192,7 +192,7 @@ struct kparam_array { (void *)set, (void *)get }; \ __module_param_call(MODULE_PARAM_PREFIX, \ name, &__param_ops_##name, arg, \ - (perm) + sizeof(__check_old_set_param(set))*0, 0) + (perm) + sizeof(__check_old_set_param(set))*0, -1) /* We don't get oldget: it's often a new-style param_get_uint, etc. */ static inline int @@ -272,7 +272,7 @@ static inline void __kernel_param_unlock(void) */ #define core_param(name, var, type, perm) \ param_check_##type(name, &(var)); \ - __module_param_call("", name, ¶m_ops_##type, &var, perm, 0) + __module_param_call("", name, ¶m_ops_##type, &var, perm, -1) #endif /* !MODULE */ /** @@ -290,7 +290,7 @@ static inline void __kernel_param_unlock(void) = { len, string }; \ __module_param_call(MODULE_PARAM_PREFIX, name, \ ¶m_ops_string, \ - .str = &__param_string_##name, perm, 0); \ + .str = &__param_string_##name, perm, -1); \ __MODULE_PARM_TYPE(name, "string") /** @@ -431,7 +431,7 @@ extern int param_set_bint(const char *val, const struct kernel_param *kp); __module_param_call(MODULE_PARAM_PREFIX, name, \ ¶m_array_ops, \ .arr = &__param_arr_##name, \ - perm, 0); \ + perm, -1); \ __MODULE_PARM_TYPE(name, "array of " #type) extern struct kernel_param_ops param_array_ops; diff --git a/init/main.c b/init/main.c index 032cf65b4cb..feb0ba56a74 100644 --- a/init/main.c +++ b/init/main.c @@ -510,7 +510,7 @@ asmlinkage void __init start_kernel(void) parse_early_param(); parse_args("Booting kernel", static_command_line, __start___param, __stop___param - __start___param, - 0, 0, &unknown_bootoption); + -1, -1, &unknown_bootoption); jump_label_init(); diff --git a/kernel/sched/core.c b/kernel/sched/core.c index a73710a5cf7..1dae88fa9ad 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -6314,11 +6314,8 @@ int sched_domain_level_max; static int __init setup_relax_domain_level(char *str) { - unsigned long val; - - val = simple_strtoul(str, NULL, 0); - if (val < sched_domain_level_max) - default_relax_domain_level = val; + if (kstrtoint(str, 0, &default_relax_domain_level)) + pr_warn("Unable to set relax_domain_level\n"); return 1; } @@ -6523,7 +6520,6 @@ struct sched_domain *build_sched_domain(struct sched_domain_topology_level *tl, if (!sd) return child; - set_domain_attribute(sd, attr); cpumask_and(sched_domain_span(sd), cpu_map, tl->mask(cpu)); if (child) { sd->level = child->level + 1; @@ -6531,6 +6527,7 @@ struct sched_domain *build_sched_domain(struct sched_domain_topology_level *tl, child->parent = sd; } sd->child = child; + set_domain_attribute(sd, attr); return sd; } diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 3581b605725..2f7b1b42ec2 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -964,6 +964,7 @@ static cycle_t logarithmic_accumulation(cycle_t offset, int shift) timekeeper.xtime.tv_sec++; leap = second_overflow(timekeeper.xtime.tv_sec); timekeeper.xtime.tv_sec += leap; + timekeeper.wall_to_monotonic.tv_sec -= leap; } /* Accumulate raw time */ @@ -1079,6 +1080,7 @@ static void update_wall_time(void) timekeeper.xtime.tv_sec++; leap = second_overflow(timekeeper.xtime.tv_sec); timekeeper.xtime.tv_sec += leap; + timekeeper.wall_to_monotonic.tv_sec -= leap; } timekeeping_update(false); diff --git a/lib/btree.c b/lib/btree.c index e5ec1e9c1aa..5cf9e74ec3f 100644 --- a/lib/btree.c +++ b/lib/btree.c @@ -319,8 +319,8 @@ void *btree_get_prev(struct btree_head *head, struct btree_geo *geo, if (head->height == 0) return NULL; -retry: longcpy(key, __key, geo->keylen); +retry: dec_key(geo, key); node = head->node; @@ -351,7 +351,7 @@ void *btree_get_prev(struct btree_head *head, struct btree_geo *geo, } miss: if (retry_key) { - __key = retry_key; + longcpy(key, retry_key, geo->keylen); retry_key = NULL; goto retry; } diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index c20051b7ffc..48f937e1ecf 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -514,6 +514,18 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, ieee80211_configure_filter(local); break; default: + mutex_lock(&local->mtx); + if (local->hw_roc_dev == sdata->dev && + local->hw_roc_channel) { + /* ignore return value since this is racy */ + drv_cancel_remain_on_channel(local); + ieee80211_queue_work(&local->hw, &local->hw_roc_done); + } + mutex_unlock(&local->mtx); + + flush_work(&local->hw_roc_start); + flush_work(&local->hw_roc_done); + flush_work(&sdata->work); /* * When we get here, the interface is marked down. diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index f054e94901a..935aa4b6dee 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c @@ -234,6 +234,22 @@ static void ieee80211_hw_roc_done(struct work_struct *work) return; } + /* was never transmitted */ + if (local->hw_roc_skb) { + u64 cookie; + + cookie = local->hw_roc_cookie ^ 2; + + cfg80211_mgmt_tx_status(local->hw_roc_dev, cookie, + local->hw_roc_skb->data, + local->hw_roc_skb->len, false, + GFP_KERNEL); + + kfree_skb(local->hw_roc_skb); + local->hw_roc_skb = NULL; + local->hw_roc_skb_for_status = NULL; + } + if (!local->hw_roc_for_tx) cfg80211_remain_on_channel_expired(local->hw_roc_dev, local->hw_roc_cookie, diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 38137cb5f6f..d93d39b8434 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -378,7 +378,7 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU) /* make the station visible */ sta_info_hash_add(local, sta); - list_add(&sta->list, &local->sta_list); + list_add_rcu(&sta->list, &local->sta_list); set_sta_flag(sta, WLAN_STA_INSERTED); @@ -688,7 +688,7 @@ int __must_check __sta_info_destroy(struct sta_info *sta) if (ret) return ret; - list_del(&sta->list); + list_del_rcu(&sta->list); mutex_lock(&local->key_mtx); for (i = 0; i < NUM_DEFAULT_KEYS; i++) diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 494933c8214..70699db0cce 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -1227,7 +1227,7 @@ int ieee80211_reconfig(struct ieee80211_local *local) enum ieee80211_sta_state state; for (state = IEEE80211_STA_NOTEXIST; - state < sta->sta_state - 1; state++) + state < sta->sta_state; state++) WARN_ON(drv_sta_state(local, sta->sdata, sta, state, state + 1)); } diff --git a/net/wireless/util.c b/net/wireless/util.c index b89fb9451d9..7e8a63e2da5 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -1013,6 +1013,7 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, enum nl80211_iftype iftype) { struct wireless_dev *wdev_iter; + u32 used_iftypes = BIT(iftype); int num[NUM_NL80211_IFTYPES]; int total = 1; int i, j; @@ -1046,12 +1047,14 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, num[wdev_iter->iftype]++; total++; + used_iftypes |= BIT(wdev_iter->iftype); } mutex_unlock(&rdev->devlist_mtx); for (i = 0; i < rdev->wiphy.n_iface_combinations; i++) { const struct ieee80211_iface_combination *c; struct ieee80211_iface_limit *limits; + u32 all_iftypes = 0; c = &rdev->wiphy.iface_combinations[i]; @@ -1066,6 +1069,7 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, if (rdev->wiphy.software_iftypes & BIT(iftype)) continue; for (j = 0; j < c->n_limits; j++) { + all_iftypes |= limits[j].types; if (!(limits[j].types & BIT(iftype))) continue; if (limits[j].max < num[iftype]) @@ -1073,7 +1077,20 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, limits[j].max -= num[iftype]; } } - /* yay, it fits */ + + /* + * Finally check that all iftypes that we're currently + * using are actually part of this combination. If they + * aren't then we can't use this combination and have + * to continue to the next. + */ + if ((all_iftypes & used_iftypes) != used_iftypes) + goto cont; + + /* + * This combination covered all interface types and + * supported the requested numbers, so we're good. + */ kfree(limits); return 0; cont: diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 7810913d07a..e56c2c817e0 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -6606,6 +6606,7 @@ enum { ALC662_FIXUP_ASUS_MODE7, ALC662_FIXUP_ASUS_MODE8, ALC662_FIXUP_NO_JACK_DETECT, + ALC662_FIXUP_ZOTAC_Z68, }; static const struct alc_fixup alc662_fixups[] = { @@ -6755,6 +6756,13 @@ static const struct alc_fixup alc662_fixups[] = { .type = ALC_FIXUP_FUNC, .v.func = alc_fixup_no_jack_detect, }, + [ALC662_FIXUP_ZOTAC_Z68] = { + .type = ALC_FIXUP_PINS, + .v.pins = (const struct alc_pincfg[]) { + { 0x1b, 0x02214020 }, /* Front HP */ + { } + } + }, }; static const struct snd_pci_quirk alc662_fixup_tbl[] = { @@ -6768,6 +6776,7 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = { SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD), SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD), SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD), + SND_PCI_QUIRK(0x19da, 0xa130, "Zotac Z68", ALC662_FIXUP_ZOTAC_Z68), SND_PCI_QUIRK(0x1b35, 0x2206, "CZC P10T", ALC662_FIXUP_CZC_P10T), #if 0 diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 2de12ebe43b..f351b933f5c 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -46,6 +46,39 @@ #define WM8994_NUM_DRC 3 #define WM8994_NUM_EQ 3 +static struct { + unsigned int reg; + unsigned int mask; +} wm8994_vu_bits[] = { + { WM8994_LEFT_LINE_INPUT_1_2_VOLUME, WM8994_IN1_VU }, + { WM8994_RIGHT_LINE_INPUT_1_2_VOLUME, WM8994_IN1_VU }, + { WM8994_LEFT_LINE_INPUT_3_4_VOLUME, WM8994_IN2_VU }, + { WM8994_RIGHT_LINE_INPUT_3_4_VOLUME, WM8994_IN2_VU }, + { WM8994_SPEAKER_VOLUME_LEFT, WM8994_SPKOUT_VU }, + { WM8994_SPEAKER_VOLUME_RIGHT, WM8994_SPKOUT_VU }, + { WM8994_LEFT_OUTPUT_VOLUME, WM8994_HPOUT1_VU }, + { WM8994_RIGHT_OUTPUT_VOLUME, WM8994_HPOUT1_VU }, + { WM8994_LEFT_OPGA_VOLUME, WM8994_MIXOUT_VU }, + { WM8994_RIGHT_OPGA_VOLUME, WM8994_MIXOUT_VU }, + + { WM8994_AIF1_DAC1_LEFT_VOLUME, WM8994_AIF1DAC1_VU }, + { WM8994_AIF1_DAC1_RIGHT_VOLUME, WM8994_AIF1DAC1_VU }, + { WM8994_AIF1_DAC2_LEFT_VOLUME, WM8994_AIF1DAC2_VU }, + { WM8994_AIF1_DAC2_RIGHT_VOLUME, WM8994_AIF1DAC2_VU }, + { WM8994_AIF2_DAC_LEFT_VOLUME, WM8994_AIF2DAC_VU }, + { WM8994_AIF2_DAC_RIGHT_VOLUME, WM8994_AIF2DAC_VU }, + { WM8994_AIF1_ADC1_LEFT_VOLUME, WM8994_AIF1ADC1_VU }, + { WM8994_AIF1_ADC1_RIGHT_VOLUME, WM8994_AIF1ADC1_VU }, + { WM8994_AIF1_ADC2_LEFT_VOLUME, WM8994_AIF1ADC2_VU }, + { WM8994_AIF1_ADC2_RIGHT_VOLUME, WM8994_AIF1ADC2_VU }, + { WM8994_AIF2_ADC_LEFT_VOLUME, WM8994_AIF2ADC_VU }, + { WM8994_AIF2_ADC_RIGHT_VOLUME, WM8994_AIF1ADC2_VU }, + { WM8994_DAC1_LEFT_VOLUME, WM8994_DAC1_VU }, + { WM8994_DAC1_RIGHT_VOLUME, WM8994_DAC1_VU }, + { WM8994_DAC2_LEFT_VOLUME, WM8994_DAC2_VU }, + { WM8994_DAC2_RIGHT_VOLUME, WM8994_DAC2_VU }, +}; + static int wm8994_drc_base[] = { WM8994_AIF1_DRC1_1, WM8994_AIF1_DRC2_1, @@ -1006,6 +1039,7 @@ static int aif1clk_ev(struct snd_soc_dapm_widget *w, struct snd_soc_codec *codec = w->codec; struct wm8994 *control = codec->control_data; int mask = WM8994_AIF1DAC1L_ENA | WM8994_AIF1DAC1R_ENA; + int i; int dac; int adc; int val; @@ -1064,6 +1098,13 @@ static int aif1clk_ev(struct snd_soc_dapm_widget *w, WM8994_AIF1DAC2L_ENA); break; + case SND_SOC_DAPM_POST_PMU: + for (i = 0; i < ARRAY_SIZE(wm8994_vu_bits); i++) + snd_soc_write(codec, wm8994_vu_bits[i].reg, + snd_soc_read(codec, + wm8994_vu_bits[i].reg)); + break; + case SND_SOC_DAPM_PRE_PMD: case SND_SOC_DAPM_POST_PMD: snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_5, @@ -1089,6 +1130,7 @@ static int aif2clk_ev(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_codec *codec = w->codec; + int i; int dac; int adc; int val; @@ -1139,6 +1181,13 @@ static int aif2clk_ev(struct snd_soc_dapm_widget *w, WM8994_AIF2DACR_ENA); break; + case SND_SOC_DAPM_POST_PMU: + for (i = 0; i < ARRAY_SIZE(wm8994_vu_bits); i++) + snd_soc_write(codec, wm8994_vu_bits[i].reg, + snd_soc_read(codec, + wm8994_vu_bits[i].reg)); + break; + case SND_SOC_DAPM_PRE_PMD: case SND_SOC_DAPM_POST_PMD: snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_5, @@ -1207,17 +1256,19 @@ static int late_enable_ev(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_PRE_PMU: if (wm8994->aif1clk_enable) { - aif1clk_ev(w, kcontrol, event); + aif1clk_ev(w, kcontrol, SND_SOC_DAPM_PRE_PMU); snd_soc_update_bits(codec, WM8994_AIF1_CLOCKING_1, WM8994_AIF1CLK_ENA_MASK, WM8994_AIF1CLK_ENA); + aif1clk_ev(w, kcontrol, SND_SOC_DAPM_POST_PMU); wm8994->aif1clk_enable = 0; } if (wm8994->aif2clk_enable) { - aif2clk_ev(w, kcontrol, event); + aif2clk_ev(w, kcontrol, SND_SOC_DAPM_PRE_PMU); snd_soc_update_bits(codec, WM8994_AIF2_CLOCKING_1, WM8994_AIF2CLK_ENA_MASK, WM8994_AIF2CLK_ENA); + aif2clk_ev(w, kcontrol, SND_SOC_DAPM_POST_PMU); wm8994->aif2clk_enable = 0; } break; @@ -1238,15 +1289,17 @@ static int late_disable_ev(struct snd_soc_dapm_widget *w, switch (event) { case SND_SOC_DAPM_POST_PMD: if (wm8994->aif1clk_disable) { + aif1clk_ev(w, kcontrol, SND_SOC_DAPM_PRE_PMD); snd_soc_update_bits(codec, WM8994_AIF1_CLOCKING_1, WM8994_AIF1CLK_ENA_MASK, 0); - aif1clk_ev(w, kcontrol, event); + aif1clk_ev(w, kcontrol, SND_SOC_DAPM_POST_PMD); wm8994->aif1clk_disable = 0; } if (wm8994->aif2clk_disable) { + aif2clk_ev(w, kcontrol, SND_SOC_DAPM_PRE_PMD); snd_soc_update_bits(codec, WM8994_AIF2_CLOCKING_1, WM8994_AIF2CLK_ENA_MASK, 0); - aif2clk_ev(w, kcontrol, event); + aif2clk_ev(w, kcontrol, SND_SOC_DAPM_POST_PMD); wm8994->aif2clk_disable = 0; } break; @@ -1583,9 +1636,11 @@ SND_SOC_DAPM_POST("Late Disable PGA", late_disable_ev) static const struct snd_soc_dapm_widget wm8994_lateclk_widgets[] = { SND_SOC_DAPM_SUPPLY("AIF1CLK", WM8994_AIF1_CLOCKING_1, 0, 0, aif1clk_ev, - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD), SND_SOC_DAPM_SUPPLY("AIF2CLK", WM8994_AIF2_CLOCKING_1, 0, 0, aif2clk_ev, - SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD), SND_SOC_DAPM_PGA("Direct Voice", SND_SOC_NOPM, 0, 0, NULL, 0), SND_SOC_DAPM_MIXER("SPKL", WM8994_POWER_MANAGEMENT_3, 8, 0, left_speaker_mixer, ARRAY_SIZE(left_speaker_mixer)), @@ -3939,39 +3994,11 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) pm_runtime_put(codec->dev); - /* Latch volume updates (right only; we always do left then right). */ - snd_soc_update_bits(codec, WM8994_AIF1_DAC1_LEFT_VOLUME, - WM8994_AIF1DAC1_VU, WM8994_AIF1DAC1_VU); - snd_soc_update_bits(codec, WM8994_AIF1_DAC1_RIGHT_VOLUME, - WM8994_AIF1DAC1_VU, WM8994_AIF1DAC1_VU); - snd_soc_update_bits(codec, WM8994_AIF1_DAC2_LEFT_VOLUME, - WM8994_AIF1DAC2_VU, WM8994_AIF1DAC2_VU); - snd_soc_update_bits(codec, WM8994_AIF1_DAC2_RIGHT_VOLUME, - WM8994_AIF1DAC2_VU, WM8994_AIF1DAC2_VU); - snd_soc_update_bits(codec, WM8994_AIF2_DAC_LEFT_VOLUME, - WM8994_AIF2DAC_VU, WM8994_AIF2DAC_VU); - snd_soc_update_bits(codec, WM8994_AIF2_DAC_RIGHT_VOLUME, - WM8994_AIF2DAC_VU, WM8994_AIF2DAC_VU); - snd_soc_update_bits(codec, WM8994_AIF1_ADC1_LEFT_VOLUME, - WM8994_AIF1ADC1_VU, WM8994_AIF1ADC1_VU); - snd_soc_update_bits(codec, WM8994_AIF1_ADC1_RIGHT_VOLUME, - WM8994_AIF1ADC1_VU, WM8994_AIF1ADC1_VU); - snd_soc_update_bits(codec, WM8994_AIF1_ADC2_LEFT_VOLUME, - WM8994_AIF1ADC2_VU, WM8994_AIF1ADC2_VU); - snd_soc_update_bits(codec, WM8994_AIF1_ADC2_RIGHT_VOLUME, - WM8994_AIF1ADC2_VU, WM8994_AIF1ADC2_VU); - snd_soc_update_bits(codec, WM8994_AIF2_ADC_LEFT_VOLUME, - WM8994_AIF2ADC_VU, WM8994_AIF1ADC2_VU); - snd_soc_update_bits(codec, WM8994_AIF2_ADC_RIGHT_VOLUME, - WM8994_AIF2ADC_VU, WM8994_AIF1ADC2_VU); - snd_soc_update_bits(codec, WM8994_DAC1_LEFT_VOLUME, - WM8994_DAC1_VU, WM8994_DAC1_VU); - snd_soc_update_bits(codec, WM8994_DAC1_RIGHT_VOLUME, - WM8994_DAC1_VU, WM8994_DAC1_VU); - snd_soc_update_bits(codec, WM8994_DAC2_LEFT_VOLUME, - WM8994_DAC2_VU, WM8994_DAC2_VU); - snd_soc_update_bits(codec, WM8994_DAC2_RIGHT_VOLUME, - WM8994_DAC2_VU, WM8994_DAC2_VU); + /* Latch volume update bits */ + for (i = 0; i < ARRAY_SIZE(wm8994_vu_bits); i++) + snd_soc_update_bits(codec, wm8994_vu_bits[i].reg, + wm8994_vu_bits[i].mask, + wm8994_vu_bits[i].mask); /* Set the low bit of the 3D stereo depth so TLV matches */ snd_soc_update_bits(codec, WM8994_AIF1_DAC1_FILTERS_2, From c8453575bb39b0fc112019ad202733968dfabfb5 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Sat, 21 Dec 2013 10:01:00 +0100 Subject: [PATCH 073/215] Linux 3.4.4 --- Makefile | 2 +- arch/arm/mach-imx/crm-regs-imx5.h | 2 +- arch/arm/mach-imx/hotplug.c | 42 +++++++- arch/arm/mach-imx/mach-mx21ads.c | 2 +- arch/x86/xen/enlighten.c | 8 ++ drivers/char/hw_random/atmel-rng.c | 2 +- drivers/edac/i7core_edac.c | 15 +-- drivers/edac/sb_edac.c | 10 +- drivers/gpu/drm/i915/intel_dp.c | 7 +- drivers/gpu/drm/radeon/evergreen.c | 3 + drivers/gpu/drm/radeon/evergreend.h | 1 + drivers/gpu/drm/radeon/r600.c | 1 + drivers/gpu/drm/radeon/r600d.h | 1 + drivers/gpu/drm/radeon/rv770.c | 5 +- drivers/gpu/drm/radeon/rv770d.h | 3 + drivers/gpu/drm/sis/sis_drv.c | 2 +- drivers/gpu/drm/udl/udl_drv.c | 15 ++- drivers/gpu/drm/via/via_map.c | 3 +- drivers/net/ethernet/intel/e1000e/82571.c | 3 +- drivers/net/ethernet/intel/e1000e/netdev.c | 8 -- drivers/net/wireless/iwlwifi/iwl-6000.c | 23 ++++- drivers/net/wireless/iwlwifi/iwl-eeprom.c | 18 ++-- .../net/wireless/iwlwifi/iwl-trans-pcie-int.h | 2 +- .../net/wireless/iwlwifi/iwl-trans-pcie-tx.c | 20 ++-- drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 4 +- drivers/pci/pci.c | 5 + drivers/pci/quirks.c | 26 +++++ drivers/remoteproc/omap_remoteproc.c | 2 +- drivers/remoteproc/remoteproc_core.c | 10 +- drivers/scsi/mpt2sas/mpt2sas_base.c | 2 +- drivers/target/target_core_alua.c | 8 +- drivers/tty/hvc/hvc_xen.c | 31 +++--- drivers/usb/class/cdc-acm.c | 8 ++ drivers/usb/class/cdc-wdm.c | 9 ++ drivers/usb/core/hcd-pci.c | 9 -- drivers/usb/core/message.c | 3 +- drivers/usb/host/ehci-hcd.c | 2 + drivers/usb/host/ehci-pci.c | 8 -- drivers/usb/host/xhci-mem.c | 74 +++++--------- drivers/usb/host/xhci.c | 8 +- drivers/usb/musb/davinci.c | 1 + drivers/usb/musb/davinci.h | 4 +- drivers/usb/musb/musb_gadget.c | 1 + drivers/usb/serial/cp210x.c | 1 + drivers/usb/serial/ftdi_sio.c | 1 + drivers/usb/serial/ftdi_sio_ids.h | 1 + drivers/usb/serial/mct_u232.c | 13 ++- drivers/usb/serial/mos7840.c | 2 +- drivers/usb/serial/option.c | 96 +++++++++---------- drivers/usb/serial/qcserial.c | 6 ++ drivers/usb/serial/sierra.c | 4 + drivers/usb/serial/usb-serial.c | 6 +- drivers/usb/storage/unusual_devs.h | 7 ++ fs/hfsplus/ioctl.c | 9 +- fs/hfsplus/wrapper.c | 2 +- fs/nfs/nfs4proc.c | 1 + fs/nfsd/nfs4state.c | 4 +- include/linux/pci.h | 2 + include/linux/swapops.h | 8 +- include/linux/usb/hcd.h | 2 - kernel/panic.c | 4 +- kernel/time/ntp.c | 2 +- kernel/trace/trace.c | 2 +- mm/swapfile.c | 12 +-- net/9p/trans_virtio.c | 2 +- net/sunrpc/rpc_pipe.c | 12 +-- net/sunrpc/svc.c | 3 +- sound/soc/codecs/wm8904.c | 13 ++- 68 files changed, 381 insertions(+), 247 deletions(-) diff --git a/Makefile b/Makefile index 9f65fd199b8..bd66308f3d9 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 4 -SUBLEVEL = 3 +SUBLEVEL = 4 EXTRAVERSION = NAME = Saber-toothed Squirrel diff --git a/arch/arm/mach-imx/crm-regs-imx5.h b/arch/arm/mach-imx/crm-regs-imx5.h index 5e11ba7daee..5e3f1f0f4ca 100644 --- a/arch/arm/mach-imx/crm-regs-imx5.h +++ b/arch/arm/mach-imx/crm-regs-imx5.h @@ -23,7 +23,7 @@ #define MX53_DPLL1_BASE MX53_IO_ADDRESS(MX53_PLL1_BASE_ADDR) #define MX53_DPLL2_BASE MX53_IO_ADDRESS(MX53_PLL2_BASE_ADDR) #define MX53_DPLL3_BASE MX53_IO_ADDRESS(MX53_PLL3_BASE_ADDR) -#define MX53_DPLL4_BASE MX53_IO_ADDRESS(MX53_PLL3_BASE_ADDR) +#define MX53_DPLL4_BASE MX53_IO_ADDRESS(MX53_PLL4_BASE_ADDR) /* PLL Register Offsets */ #define MXC_PLL_DP_CTL 0x00 diff --git a/arch/arm/mach-imx/hotplug.c b/arch/arm/mach-imx/hotplug.c index 89493abd497..20ed2d56c1a 100644 --- a/arch/arm/mach-imx/hotplug.c +++ b/arch/arm/mach-imx/hotplug.c @@ -12,6 +12,7 @@ #include #include +#include #include int platform_cpu_kill(unsigned int cpu) @@ -19,6 +20,44 @@ int platform_cpu_kill(unsigned int cpu) return 1; } +static inline void cpu_enter_lowpower(void) +{ + unsigned int v; + + flush_cache_all(); + asm volatile( + "mcr p15, 0, %1, c7, c5, 0\n" + " mcr p15, 0, %1, c7, c10, 4\n" + /* + * Turn off coherency + */ + " mrc p15, 0, %0, c1, c0, 1\n" + " bic %0, %0, %3\n" + " mcr p15, 0, %0, c1, c0, 1\n" + " mrc p15, 0, %0, c1, c0, 0\n" + " bic %0, %0, %2\n" + " mcr p15, 0, %0, c1, c0, 0\n" + : "=&r" (v) + : "r" (0), "Ir" (CR_C), "Ir" (0x40) + : "cc"); +} + +static inline void cpu_leave_lowpower(void) +{ + unsigned int v; + + asm volatile( + "mrc p15, 0, %0, c1, c0, 0\n" + " orr %0, %0, %1\n" + " mcr p15, 0, %0, c1, c0, 0\n" + " mrc p15, 0, %0, c1, c0, 1\n" + " orr %0, %0, %2\n" + " mcr p15, 0, %0, c1, c0, 1\n" + : "=&r" (v) + : "Ir" (CR_C), "Ir" (0x40) + : "cc"); +} + /* * platform-specific code to shutdown a CPU * @@ -26,9 +65,10 @@ int platform_cpu_kill(unsigned int cpu) */ void platform_cpu_die(unsigned int cpu) { - flush_cache_all(); + cpu_enter_lowpower(); imx_enable_cpu(cpu, false); cpu_do_idle(); + cpu_leave_lowpower(); /* We should never return from idle */ panic("cpu %d unexpectedly exit from shutdown\n", cpu); diff --git a/arch/arm/mach-imx/mach-mx21ads.c b/arch/arm/mach-imx/mach-mx21ads.c index e432d4acee1..4460d25faae 100644 --- a/arch/arm/mach-imx/mach-mx21ads.c +++ b/arch/arm/mach-imx/mach-mx21ads.c @@ -32,7 +32,7 @@ * Memory-mapped I/O on MX21ADS base board */ #define MX21ADS_MMIO_BASE_ADDR 0xf5000000 -#define MX21ADS_MMIO_SIZE SZ_16M +#define MX21ADS_MMIO_SIZE 0xc00000 #define MX21ADS_REG_ADDR(offset) (void __force __iomem *) \ (MX21ADS_MMIO_BASE_ADDR + (offset)) diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index c4c183d0ba9..495fc63f5a1 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -207,6 +207,9 @@ static void __init xen_banner(void) xen_feature(XENFEAT_mmu_pt_update_preserve_ad) ? " (preserve-AD)" : ""); } +#define CPUID_THERM_POWER_LEAF 6 +#define APERFMPERF_PRESENT 0 + static __read_mostly unsigned int cpuid_leaf1_edx_mask = ~0; static __read_mostly unsigned int cpuid_leaf1_ecx_mask = ~0; @@ -240,6 +243,11 @@ static void xen_cpuid(unsigned int *ax, unsigned int *bx, *dx = cpuid_leaf5_edx_val; return; + case CPUID_THERM_POWER_LEAF: + /* Disabling APERFMPERF for kernel usage */ + maskecx = ~(1 << APERFMPERF_PRESENT); + break; + case 0xb: /* Suppress extended topology stuff */ maskebx = 0; diff --git a/drivers/char/hw_random/atmel-rng.c b/drivers/char/hw_random/atmel-rng.c index 6289f0eee24..731c9046cf7 100644 --- a/drivers/char/hw_random/atmel-rng.c +++ b/drivers/char/hw_random/atmel-rng.c @@ -34,7 +34,7 @@ static int atmel_trng_read(struct hwrng *rng, void *buf, size_t max, u32 *data = buf; /* data ready? */ - if (readl(trng->base + TRNG_ODATA) & 1) { + if (readl(trng->base + TRNG_ISR) & 1) { *data = readl(trng->base + TRNG_ODATA); /* ensure data ready is only set again AFTER the next data diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c index 85226ccf529..0fe2277d867 100644 --- a/drivers/edac/i7core_edac.c +++ b/drivers/edac/i7core_edac.c @@ -1932,12 +1932,6 @@ static int i7core_mce_check_error(struct notifier_block *nb, unsigned long val, if (mce->bank != 8) return NOTIFY_DONE; -#ifdef CONFIG_SMP - /* Only handle if it is the right mc controller */ - if (mce->socketid != pvt->i7core_dev->socket) - return NOTIFY_DONE; -#endif - smp_rmb(); if ((pvt->mce_out + 1) % MCE_LOG_LEN == pvt->mce_in) { smp_wmb(); @@ -2234,8 +2228,6 @@ static void i7core_unregister_mci(struct i7core_dev *i7core_dev) if (pvt->enable_scrub) disable_sdram_scrub_setting(mci); - mce_unregister_decode_chain(&i7_mce_dec); - /* Disable EDAC polling */ i7core_pci_ctl_release(pvt); @@ -2336,8 +2328,6 @@ static int i7core_register_mci(struct i7core_dev *i7core_dev) /* DCLK for scrub rate setting */ pvt->dclk_freq = get_dclk_freq(); - mce_register_decode_chain(&i7_mce_dec); - return 0; fail0: @@ -2481,8 +2471,10 @@ static int __init i7core_init(void) pci_rc = pci_register_driver(&i7core_driver); - if (pci_rc >= 0) + if (pci_rc >= 0) { + mce_register_decode_chain(&i7_mce_dec); return 0; + } i7core_printk(KERN_ERR, "Failed to register device with error %d.\n", pci_rc); @@ -2498,6 +2490,7 @@ static void __exit i7core_exit(void) { debugf2("MC: " __FILE__ ": %s()\n", __func__); pci_unregister_driver(&i7core_driver); + mce_unregister_decode_chain(&i7_mce_dec); } module_init(i7core_init); diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c index a203536d90d..0f9552d6b56 100644 --- a/drivers/edac/sb_edac.c +++ b/drivers/edac/sb_edac.c @@ -599,7 +599,7 @@ static int get_dimm_config(const struct mem_ctl_info *mci) pvt->is_close_pg = false; } - pci_read_config_dword(pvt->pci_ta, RANK_CFG_A, ®); + pci_read_config_dword(pvt->pci_ddrio, RANK_CFG_A, ®); if (IS_RDIMM_ENABLED(reg)) { /* FIXME: Can also be LRDIMM */ debugf0("Memory is registered\n"); @@ -1669,8 +1669,6 @@ static void sbridge_unregister_mci(struct sbridge_dev *sbridge_dev) debugf0("MC: " __FILE__ ": %s(): mci = %p, dev = %p\n", __func__, mci, &sbridge_dev->pdev[0]->dev); - mce_unregister_decode_chain(&sbridge_mce_dec); - /* Remove MC sysfs nodes */ edac_mc_del_mc(mci->dev); @@ -1738,7 +1736,6 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev) goto fail0; } - mce_register_decode_chain(&sbridge_mce_dec); return 0; fail0: @@ -1867,8 +1864,10 @@ static int __init sbridge_init(void) pci_rc = pci_register_driver(&sbridge_driver); - if (pci_rc >= 0) + if (pci_rc >= 0) { + mce_register_decode_chain(&sbridge_mce_dec); return 0; + } sbridge_printk(KERN_ERR, "Failed to register device with error %d.\n", pci_rc); @@ -1884,6 +1883,7 @@ static void __exit sbridge_exit(void) { debugf2("MC: " __FILE__ ": %s()\n", __func__); pci_unregister_driver(&sbridge_driver); + mce_unregister_decode_chain(&sbridge_mce_dec); } module_init(sbridge_init); diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 1d19408192b..68624218d05 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -368,7 +368,7 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, int recv_bytes; uint32_t status; uint32_t aux_clock_divider; - int try, precharge = 5; + int try, precharge; intel_dp_check_edp(intel_dp); /* The clock divider is based off the hrawclk, @@ -388,6 +388,11 @@ intel_dp_aux_ch(struct intel_dp *intel_dp, else aux_clock_divider = intel_hrawclk(dev) / 2; + if (IS_GEN6(dev)) + precharge = 3; + else + precharge = 5; + /* Try to wait for any previous AUX channel activity */ for (try = 0; try < 3; try++) { status = I915_READ(ch_ctl); diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 51e8d086767..e72c03ff595 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -2210,6 +2210,9 @@ static void evergreen_gpu_init(struct radeon_device *rdev) smx_dc_ctl0 |= NUMBER_OF_SETS(rdev->config.evergreen.sx_num_of_sets); WREG32(SMX_DC_CTL0, smx_dc_ctl0); + if (rdev->family <= CHIP_SUMO2) + WREG32(SMX_SAR_CTL0, 0x00010000); + WREG32(SX_EXPORT_BUFFER_SIZES, (COLOR_BUFFER_SIZE((rdev->config.evergreen.sx_max_export_size / 4) - 1) | POSITION_BUFFER_SIZE((rdev->config.evergreen.sx_max_export_pos_size / 4) - 1) | SMX_BUFFER_SIZE((rdev->config.evergreen.sx_max_export_smx_size / 4) - 1))); diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h index a5b88aad834..f62ccd3555d 100644 --- a/drivers/gpu/drm/radeon/evergreend.h +++ b/drivers/gpu/drm/radeon/evergreend.h @@ -273,6 +273,7 @@ #define SCRATCH_UMSK 0x8540 #define SCRATCH_ADDR 0x8544 +#define SMX_SAR_CTL0 0xA008 #define SMX_DC_CTL0 0xA020 #define USE_HASH_FUNCTION (1 << 0) #define NUMBER_OF_SETS(x) ((x) << 1) diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index c8187c4b6ae..b1ff9ccd2d6 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -1906,6 +1906,7 @@ void r600_gpu_init(struct radeon_device *rdev) WREG32(PA_CL_ENHANCE, (CLIP_VTX_REORDER_ENA | NUM_CLIP_SEQ(3))); WREG32(PA_SC_ENHANCE, FORCE_EOV_MAX_CLK_CNT(4095)); + WREG32(VC_ENHANCE, 0); } diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h index 59f9c993cc3..12ceb829a03 100644 --- a/drivers/gpu/drm/radeon/r600d.h +++ b/drivers/gpu/drm/radeon/r600d.h @@ -483,6 +483,7 @@ #define TC_L2_SIZE(x) ((x)<<5) #define L2_DISABLE_LATE_HIT (1<<9) +#define VC_ENHANCE 0x9714 #define VGT_CACHE_INVALIDATION 0x88C4 #define CACHE_INVALIDATION(x) ((x)<<0) diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index 80a292bc457..591040b9466 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -782,6 +782,9 @@ static void rv770_gpu_init(struct radeon_device *rdev) ACK_FLUSH_CTL(3) | SYNC_FLUSH_CTL)); + if (rdev->family != CHIP_RV770) + WREG32(SMX_SAR_CTL0, 0x00003f3f); + db_debug3 = RREG32(DB_DEBUG3); db_debug3 &= ~DB_CLK_OFF_DELAY(0x1f); switch (rdev->family) { @@ -960,7 +963,7 @@ static void rv770_gpu_init(struct radeon_device *rdev) WREG32(PA_CL_ENHANCE, (CLIP_VTX_REORDER_ENA | NUM_CLIP_SEQ(3))); - + WREG32(VC_ENHANCE, 0); } void r700_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc) diff --git a/drivers/gpu/drm/radeon/rv770d.h b/drivers/gpu/drm/radeon/rv770d.h index 75380927e9c..7095a713ad8 100644 --- a/drivers/gpu/drm/radeon/rv770d.h +++ b/drivers/gpu/drm/radeon/rv770d.h @@ -208,6 +208,7 @@ #define SCRATCH_UMSK 0x8540 #define SCRATCH_ADDR 0x8544 +#define SMX_SAR_CTL0 0xA008 #define SMX_DC_CTL0 0xA020 #define USE_HASH_FUNCTION (1 << 0) #define CACHE_DEPTH(x) ((x) << 1) @@ -307,6 +308,8 @@ #define TCP_CNTL 0x9610 #define TCP_CHAN_STEER 0x9614 +#define VC_ENHANCE 0x9714 + #define VGT_CACHE_INVALIDATION 0x88C4 #define CACHE_INVALIDATION(x) ((x)<<0) #define VC_ONLY 0 diff --git a/drivers/gpu/drm/sis/sis_drv.c b/drivers/gpu/drm/sis/sis_drv.c index 30d98d14b5c..dd14cd1a003 100644 --- a/drivers/gpu/drm/sis/sis_drv.c +++ b/drivers/gpu/drm/sis/sis_drv.c @@ -47,9 +47,9 @@ static int sis_driver_load(struct drm_device *dev, unsigned long chipset) if (dev_priv == NULL) return -ENOMEM; + idr_init(&dev_priv->object_idr); dev->dev_private = (void *)dev_priv; dev_priv->chipset = chipset; - idr_init(&dev->object_name_idr); return 0; } diff --git a/drivers/gpu/drm/udl/udl_drv.c b/drivers/gpu/drm/udl/udl_drv.c index 53673907a6a..08eff0dbb80 100644 --- a/drivers/gpu/drm/udl/udl_drv.c +++ b/drivers/gpu/drm/udl/udl_drv.c @@ -13,8 +13,21 @@ static struct drm_driver driver; +/* + * There are many DisplayLink-based graphics products, all with unique PIDs. + * So we match on DisplayLink's VID + Vendor-Defined Interface Class (0xff) + * We also require a match on SubClass (0x00) and Protocol (0x00), + * which is compatible with all known USB 2.0 era graphics chips and firmware, + * but allows DisplayLink to increment those for any future incompatible chips + */ static struct usb_device_id id_table[] = { - {.idVendor = 0x17e9, .match_flags = USB_DEVICE_ID_MATCH_VENDOR,}, + {.idVendor = 0x17e9, .bInterfaceClass = 0xff, + .bInterfaceSubClass = 0x00, + .bInterfaceProtocol = 0x00, + .match_flags = USB_DEVICE_ID_MATCH_VENDOR | + USB_DEVICE_ID_MATCH_INT_CLASS | + USB_DEVICE_ID_MATCH_INT_SUBCLASS | + USB_DEVICE_ID_MATCH_INT_PROTOCOL,}, {}, }; MODULE_DEVICE_TABLE(usb, id_table); diff --git a/drivers/gpu/drm/via/via_map.c b/drivers/gpu/drm/via/via_map.c index 1f182254e81..c126182ac07 100644 --- a/drivers/gpu/drm/via/via_map.c +++ b/drivers/gpu/drm/via/via_map.c @@ -100,12 +100,11 @@ int via_driver_load(struct drm_device *dev, unsigned long chipset) if (dev_priv == NULL) return -ENOMEM; + idr_init(&dev_priv->object_idr); dev->dev_private = (void *)dev_priv; dev_priv->chipset = chipset; - idr_init(&dev->object_name_idr); - pci_set_master(dev->pdev); ret = drm_vblank_init(dev, 1); diff --git a/drivers/net/ethernet/intel/e1000e/82571.c b/drivers/net/ethernet/intel/e1000e/82571.c index b3fdc6977f2..c6d95f2031e 100644 --- a/drivers/net/ethernet/intel/e1000e/82571.c +++ b/drivers/net/ethernet/intel/e1000e/82571.c @@ -2061,8 +2061,9 @@ const struct e1000_info e1000_82574_info = { | FLAG_HAS_SMART_POWER_DOWN | FLAG_HAS_AMT | FLAG_HAS_CTRLEXT_ON_LOAD, - .flags2 = FLAG2_CHECK_PHY_HANG + .flags2 = FLAG2_CHECK_PHY_HANG | FLAG2_DISABLE_ASPM_L0S + | FLAG2_DISABLE_ASPM_L1 | FLAG2_NO_DISABLE_RX, .pba = 32, .max_hw_frame_size = DEFAULT_JUMBO, diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index 9520a6ac1f3..00e961e42c6 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@ -5293,14 +5293,6 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu) return -EINVAL; } - /* 82573 Errata 17 */ - if (((adapter->hw.mac.type == e1000_82573) || - (adapter->hw.mac.type == e1000_82574)) && - (max_frame > ETH_FRAME_LEN + ETH_FCS_LEN)) { - adapter->flags2 |= FLAG2_DISABLE_ASPM_L1; - e1000e_disable_aspm(adapter->pdev, PCIE_LINK_STATE_L1); - } - while (test_and_set_bit(__E1000_RESETTING, &adapter->state)) usleep_range(1000, 2000); /* e1000e_down -> e1000e_reset dependent on max_frame_size & mtu */ diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index 9f71b85f591..c0cfa4e652c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -49,17 +49,20 @@ #define IWL6000_UCODE_API_MAX 6 #define IWL6050_UCODE_API_MAX 5 #define IWL6000G2_UCODE_API_MAX 6 +#define IWL6035_UCODE_API_MAX 6 /* Oldest version we won't warn about */ #define IWL6000_UCODE_API_OK 4 #define IWL6000G2_UCODE_API_OK 5 #define IWL6050_UCODE_API_OK 5 #define IWL6000G2B_UCODE_API_OK 6 +#define IWL6035_UCODE_API_OK 6 /* Lowest firmware API version supported */ #define IWL6000_UCODE_API_MIN 4 #define IWL6050_UCODE_API_MIN 4 -#define IWL6000G2_UCODE_API_MIN 4 +#define IWL6000G2_UCODE_API_MIN 5 +#define IWL6035_UCODE_API_MIN 6 #define IWL6000_FW_PRE "iwlwifi-6000-" #define IWL6000_MODULE_FIRMWARE(api) IWL6000_FW_PRE __stringify(api) ".ucode" @@ -425,9 +428,25 @@ const struct iwl_cfg iwl6030_2bg_cfg = { IWL_DEVICE_6030, }; +#define IWL_DEVICE_6035 \ + .fw_name_pre = IWL6030_FW_PRE, \ + .ucode_api_max = IWL6035_UCODE_API_MAX, \ + .ucode_api_ok = IWL6035_UCODE_API_OK, \ + .ucode_api_min = IWL6035_UCODE_API_MIN, \ + .max_inst_size = IWL60_RTC_INST_SIZE, \ + .max_data_size = IWL60_RTC_DATA_SIZE, \ + .eeprom_ver = EEPROM_6030_EEPROM_VERSION, \ + .eeprom_calib_ver = EEPROM_6030_TX_POWER_VERSION, \ + .lib = &iwl6030_lib, \ + .base_params = &iwl6000_g2_base_params, \ + .bt_params = &iwl6000_bt_params, \ + .need_temp_offset_calib = true, \ + .led_mode = IWL_LED_RF_STATE, \ + .adv_pm = true + const struct iwl_cfg iwl6035_2agn_cfg = { .name = "Intel(R) Centrino(R) Advanced-N 6235 AGN", - IWL_DEVICE_6030, + IWL_DEVICE_6035, .ht_params = &iwl6000_ht_params, }; diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index 23cea42b949..79dddc481da 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -513,28 +513,28 @@ static int iwl_find_otp_image(struct iwl_trans *trans, * iwl_get_max_txpower_avg - get the highest tx power from all chains. * find the highest tx power from all chains for the channel */ -static s8 iwl_get_max_txpower_avg(const struct iwl_cfg *cfg, +static s8 iwl_get_max_txpower_avg(struct iwl_priv *priv, struct iwl_eeprom_enhanced_txpwr *enhanced_txpower, int element, s8 *max_txpower_in_half_dbm) { s8 max_txpower_avg = 0; /* (dBm) */ /* Take the highest tx power from any valid chains */ - if ((cfg->valid_tx_ant & ANT_A) && + if ((hw_params(priv).valid_tx_ant & ANT_A) && (enhanced_txpower[element].chain_a_max > max_txpower_avg)) max_txpower_avg = enhanced_txpower[element].chain_a_max; - if ((cfg->valid_tx_ant & ANT_B) && + if ((hw_params(priv).valid_tx_ant & ANT_B) && (enhanced_txpower[element].chain_b_max > max_txpower_avg)) max_txpower_avg = enhanced_txpower[element].chain_b_max; - if ((cfg->valid_tx_ant & ANT_C) && + if ((hw_params(priv).valid_tx_ant & ANT_C) && (enhanced_txpower[element].chain_c_max > max_txpower_avg)) max_txpower_avg = enhanced_txpower[element].chain_c_max; - if (((cfg->valid_tx_ant == ANT_AB) | - (cfg->valid_tx_ant == ANT_BC) | - (cfg->valid_tx_ant == ANT_AC)) && + if (((hw_params(priv).valid_tx_ant == ANT_AB) | + (hw_params(priv).valid_tx_ant == ANT_BC) | + (hw_params(priv).valid_tx_ant == ANT_AC)) && (enhanced_txpower[element].mimo2_max > max_txpower_avg)) max_txpower_avg = enhanced_txpower[element].mimo2_max; - if ((cfg->valid_tx_ant == ANT_ABC) && + if ((hw_params(priv).valid_tx_ant == ANT_ABC) && (enhanced_txpower[element].mimo3_max > max_txpower_avg)) max_txpower_avg = enhanced_txpower[element].mimo3_max; @@ -637,7 +637,7 @@ static void iwl_eeprom_enhanced_txpower(struct iwl_priv *priv) ((txp->delta_20_in_40 & 0xf0) >> 4), (txp->delta_20_in_40 & 0x0f)); - max_txp_avg = iwl_get_max_txpower_avg(cfg(priv), txp_array, idx, + max_txp_avg = iwl_get_max_txpower_avg(priv, txp_array, idx, &max_txp_avg_halfdbm); /* diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h index 1c2fe87bd7e..3b844b79b14 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-int.h @@ -342,7 +342,7 @@ void iwl_trans_pcie_tx_agg_setup(struct iwl_trans *trans, enum iwl_rxon_context_id ctx, int sta_id, int tid, int frame_limit, u16 ssn); void iwlagn_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq, - int index, enum dma_data_direction dma_dir); + enum dma_data_direction dma_dir); int iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index, struct sk_buff_head *skbs); int iwl_queue_space(const struct iwl_queue *q); diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c index e92972fd6ec..d7964b12ef1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie-tx.c @@ -237,32 +237,38 @@ static void iwlagn_unmap_tfd(struct iwl_trans *trans, struct iwl_cmd_meta *meta, for (i = 1; i < num_tbs; i++) dma_unmap_single(trans->dev, iwl_tfd_tb_get_addr(tfd, i), iwl_tfd_tb_get_len(tfd, i), dma_dir); + + tfd->num_tbs = 0; } /** * iwlagn_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr] * @trans - transport private data * @txq - tx queue - * @index - the index of the TFD to be freed - *@dma_dir - the direction of the DMA mapping + * @dma_dir - the direction of the DMA mapping * * Does NOT advance any TFD circular buffer read/write indexes * Does NOT free the TFD itself (which is within circular buffer) */ void iwlagn_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq, - int index, enum dma_data_direction dma_dir) + enum dma_data_direction dma_dir) { struct iwl_tfd *tfd_tmp = txq->tfds; + /* rd_ptr is bounded by n_bd and idx is bounded by n_window */ + int rd_ptr = txq->q.read_ptr; + int idx = get_cmd_index(&txq->q, rd_ptr); + lockdep_assert_held(&txq->lock); - iwlagn_unmap_tfd(trans, &txq->meta[index], &tfd_tmp[index], dma_dir); + /* We have only q->n_window txq->entries, but we use q->n_bd tfds */ + iwlagn_unmap_tfd(trans, &txq->meta[idx], &tfd_tmp[rd_ptr], dma_dir); /* free SKB */ if (txq->skbs) { struct sk_buff *skb; - skb = txq->skbs[index]; + skb = txq->skbs[idx]; /* Can be called from irqs-disabled context * If skb is not NULL, it means that the whole queue is being @@ -270,7 +276,7 @@ void iwlagn_txq_free_tfd(struct iwl_trans *trans, struct iwl_tx_queue *txq, */ if (skb) { iwl_op_mode_free_skb(trans->op_mode, skb); - txq->skbs[index] = NULL; + txq->skbs[idx] = NULL; } } } @@ -1100,7 +1106,7 @@ int iwl_tx_queue_reclaim(struct iwl_trans *trans, int txq_id, int index, iwlagn_txq_inval_byte_cnt_tbl(trans, txq); - iwlagn_txq_free_tfd(trans, txq, txq->q.read_ptr, DMA_TO_DEVICE); + iwlagn_txq_free_tfd(trans, txq, DMA_TO_DEVICE); freed++; } return freed; diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index 66df0166cfd..6eac984b2d0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c @@ -430,9 +430,7 @@ static void iwl_tx_queue_unmap(struct iwl_trans *trans, int txq_id) spin_lock_bh(&txq->lock); while (q->write_ptr != q->read_ptr) { - /* The read_ptr needs to bound by q->n_window */ - iwlagn_txq_free_tfd(trans, txq, get_cmd_index(q, q->read_ptr), - dma_dir); + iwlagn_txq_free_tfd(trans, txq, dma_dir); q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd); } spin_unlock_bh(&txq->lock); diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 111569ccab4..f597a1aa5e6 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1743,6 +1743,11 @@ int pci_prepare_to_sleep(struct pci_dev *dev) if (target_state == PCI_POWER_ERROR) return -EIO; + /* Some devices mustn't be in D3 during system sleep */ + if (target_state == PCI_D3hot && + (dev->dev_flags & PCI_DEV_FLAGS_NO_D3_DURING_SLEEP)) + return 0; + pci_enable_wake(dev, target_state, device_may_wakeup(&dev->dev)); error = pci_set_power_state(dev, target_state); diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 4bf71028556..bf33f0b7f95 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -2917,6 +2917,32 @@ static void __devinit disable_igfx_irq(struct pci_dev *dev) DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0102, disable_igfx_irq); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x010a, disable_igfx_irq); +/* + * The Intel 6 Series/C200 Series chipset's EHCI controllers on many + * ASUS motherboards will cause memory corruption or a system crash + * if they are in D3 while the system is put into S3 sleep. + */ +static void __devinit asus_ehci_no_d3(struct pci_dev *dev) +{ + const char *sys_info; + static const char good_Asus_board[] = "P8Z68-V"; + + if (dev->dev_flags & PCI_DEV_FLAGS_NO_D3_DURING_SLEEP) + return; + if (dev->subsystem_vendor != PCI_VENDOR_ID_ASUSTEK) + return; + sys_info = dmi_get_system_info(DMI_BOARD_NAME); + if (sys_info && memcmp(sys_info, good_Asus_board, + sizeof(good_Asus_board) - 1) == 0) + return; + + dev_info(&dev->dev, "broken D3 during system sleep on ASUS\n"); + dev->dev_flags |= PCI_DEV_FLAGS_NO_D3_DURING_SLEEP; + device_set_wakeup_capable(&dev->dev, false); +} +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1c26, asus_ehci_no_d3); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1c2d, asus_ehci_no_d3); + static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_fixup *end) { diff --git a/drivers/remoteproc/omap_remoteproc.c b/drivers/remoteproc/omap_remoteproc.c index 69425c4e86f..de138e30d3e 100644 --- a/drivers/remoteproc/omap_remoteproc.c +++ b/drivers/remoteproc/omap_remoteproc.c @@ -182,7 +182,7 @@ static int __devinit omap_rproc_probe(struct platform_device *pdev) ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); if (ret) { - dev_err(pdev->dev.parent, "dma_set_coherent_mask: %d\n", ret); + dev_err(&pdev->dev, "dma_set_coherent_mask: %d\n", ret); return ret; } diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index 289293a5cbb..0142e523220 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c @@ -247,7 +247,7 @@ rproc_load_segments(struct rproc *rproc, const u8 *elf_data, size_t len) } if (offset + filesz > len) { - dev_err(dev, "truncated fw: need 0x%x avail 0x%x\n", + dev_err(dev, "truncated fw: need 0x%x avail 0x%zx\n", offset + filesz, len); ret = -EINVAL; break; @@ -934,7 +934,7 @@ static void rproc_resource_cleanup(struct rproc *rproc) unmapped = iommu_unmap(rproc->domain, entry->da, entry->len); if (unmapped != entry->len) { /* nothing much to do besides complaining */ - dev_err(dev, "failed to unmap %u/%u\n", entry->len, + dev_err(dev, "failed to unmap %u/%zu\n", entry->len, unmapped); } @@ -1020,7 +1020,7 @@ static int rproc_fw_boot(struct rproc *rproc, const struct firmware *fw) ehdr = (struct elf32_hdr *)fw->data; - dev_info(dev, "Booting fw image %s, size %d\n", name, fw->size); + dev_info(dev, "Booting fw image %s, size %zd\n", name, fw->size); /* * if enabling an IOMMU isn't relevant for this rproc, this is @@ -1041,8 +1041,10 @@ static int rproc_fw_boot(struct rproc *rproc, const struct firmware *fw) /* look for the resource table */ table = rproc_find_rsc_table(rproc, fw->data, fw->size, &tablesz); - if (!table) + if (!table) { + ret = -EINVAL; goto clean_up; + } /* handle fw resources which are required to boot rproc */ ret = rproc_handle_boot_rsc(rproc, table, tablesz); diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index 18084788ee3..3f03342b303 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c @@ -1785,7 +1785,7 @@ static inline void _base_writeq(__u64 b, volatile void __iomem *addr, static inline u8 _base_get_msix_index(struct MPT2SAS_ADAPTER *ioc) { - return ioc->cpu_msix_table[smp_processor_id()]; + return ioc->cpu_msix_table[raw_smp_processor_id()]; } /** diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c index c7746a3339d..f30e124874b 100644 --- a/drivers/target/target_core_alua.c +++ b/drivers/target/target_core_alua.c @@ -351,9 +351,11 @@ int target_emulate_set_target_port_groups(struct se_task *task) out: transport_kunmap_data_sg(cmd); - task->task_scsi_status = GOOD; - transport_complete_task(task, 1); - return 0; + if (!rc) { + task->task_scsi_status = GOOD; + transport_complete_task(task, 1); + } + return rc; } static inline int core_alua_state_nonoptimized( diff --git a/drivers/tty/hvc/hvc_xen.c b/drivers/tty/hvc/hvc_xen.c index d3d91dae065..944eaeb8e0c 100644 --- a/drivers/tty/hvc/hvc_xen.c +++ b/drivers/tty/hvc/hvc_xen.c @@ -214,24 +214,24 @@ static int xen_hvm_console_init(void) /* already configured */ if (info->intf != NULL) return 0; - + /* + * If the toolstack (or the hypervisor) hasn't set these values, the + * default value is 0. Even though mfn = 0 and evtchn = 0 are + * theoretically correct values, in practice they never are and they + * mean that a legacy toolstack hasn't initialized the pv console correctly. + */ r = hvm_get_parameter(HVM_PARAM_CONSOLE_EVTCHN, &v); - if (r < 0) { - kfree(info); - return -ENODEV; - } + if (r < 0 || v == 0) + goto err; info->evtchn = v; - hvm_get_parameter(HVM_PARAM_CONSOLE_PFN, &v); - if (r < 0) { - kfree(info); - return -ENODEV; - } + v = 0; + r = hvm_get_parameter(HVM_PARAM_CONSOLE_PFN, &v); + if (r < 0 || v == 0) + goto err; mfn = v; info->intf = ioremap(mfn << PAGE_SHIFT, PAGE_SIZE); - if (info->intf == NULL) { - kfree(info); - return -ENODEV; - } + if (info->intf == NULL) + goto err; info->vtermno = HVC_COOKIE; spin_lock(&xencons_lock); @@ -239,6 +239,9 @@ static int xen_hvm_console_init(void) spin_unlock(&xencons_lock); return 0; +err: + kfree(info); + return -ENODEV; } static int xen_pv_console_init(void) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index b32ccb46101..640cf7983b0 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -567,6 +567,14 @@ static int acm_port_activate(struct tty_port *port, struct tty_struct *tty) usb_autopm_put_interface(acm->control); + /* + * Unthrottle device in case the TTY was closed while throttled. + */ + spin_lock_irq(&acm->read_lock); + acm->throttled = 0; + acm->throttle_req = 0; + spin_unlock_irq(&acm->read_lock); + if (acm_submit_read_urbs(acm, GFP_KERNEL)) goto error_submit_read_urbs; diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 4c8321ea4c5..83d14bfc2b2 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -55,6 +55,15 @@ static const struct usb_device_id wdm_ids[] = { .bInterfaceSubClass = 1, .bInterfaceProtocol = 9, /* NOTE: CDC ECM control interface! */ }, + { + /* Vodafone/Huawei K5005 (12d1:14c8) and similar modems */ + .match_flags = USB_DEVICE_ID_MATCH_VENDOR | + USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = HUAWEI_VENDOR_ID, + .bInterfaceClass = USB_CLASS_VENDOR_SPEC, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 57, /* NOTE: CDC ECM control interface! */ + }, { } }; diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index 57ed9e400c0..622b4a48e73 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c @@ -493,15 +493,6 @@ static int hcd_pci_suspend_noirq(struct device *dev) pci_save_state(pci_dev); - /* - * Some systems crash if an EHCI controller is in D3 during - * a sleep transition. We have to leave such controllers in D0. - */ - if (hcd->broken_pci_sleep) { - dev_dbg(dev, "Staying in PCI D0\n"); - return retval; - } - /* If the root hub is dead rather than suspended, disallow remote * wakeup. usb_hc_died() should ensure that both hosts are marked as * dying, so we only need to check the primary roothub. diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 3aa16b12e26..2c9fc0319ac 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -1807,7 +1807,6 @@ int usb_set_configuration(struct usb_device *dev, int configuration) intfc = cp->intf_cache[i]; intf->altsetting = intfc->altsetting; intf->num_altsetting = intfc->num_altsetting; - intf->intf_assoc = find_iad(dev, cp, i); kref_get(&intfc->ref); alt = usb_altnum_to_altsetting(intf, 0); @@ -1820,6 +1819,8 @@ int usb_set_configuration(struct usb_device *dev, int configuration) if (!alt) alt = &intf->altsetting[0]; + intf->intf_assoc = + find_iad(dev, cp, alt->desc.bInterfaceNumber); intf->cur_altsetting = alt; usb_enable_interface(dev, intf, true); intf->dev.parent = &dev->dev; diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index adbf2178019..020a153676c 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -684,7 +684,9 @@ static int ehci_init(struct usb_hcd *hcd) hw = ehci->async->hw; hw->hw_next = QH_NEXT(ehci, ehci->async->qh_dma); hw->hw_info1 = cpu_to_hc32(ehci, QH_HEAD); +#if defined(CONFIG_PPC_PS3) hw->hw_info1 |= cpu_to_hc32(ehci, (1 << 7)); /* I = 1 */ +#endif hw->hw_token = cpu_to_hc32(ehci, QTD_STS_HALT); hw->hw_qtd_next = EHCI_LIST_END(ehci); ehci->async->qh_state = QH_STATE_LINKED; diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index bc94d7bf072..123481793a4 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -144,14 +144,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd) hcd->has_tt = 1; tdi_reset(ehci); } - if (pdev->subsystem_vendor == PCI_VENDOR_ID_ASUSTEK) { - /* EHCI #1 or #2 on 6 Series/C200 Series chipset */ - if (pdev->device == 0x1c26 || pdev->device == 0x1c2d) { - ehci_info(ehci, "broken D3 during system sleep on ASUS\n"); - hcd->broken_pci_sleep = 1; - device_set_wakeup_capable(&pdev->dev, false); - } - } break; case PCI_VENDOR_ID_TDI: if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) { diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 497ed7723e4..6b908249b01 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -793,10 +793,9 @@ static void xhci_free_tt_info(struct xhci_hcd *xhci, struct xhci_virt_device *virt_dev, int slot_id) { - struct list_head *tt; struct list_head *tt_list_head; - struct list_head *tt_next; - struct xhci_tt_bw_info *tt_info; + struct xhci_tt_bw_info *tt_info, *next; + bool slot_found = false; /* If the device never made it past the Set Address stage, * it may not have the real_port set correctly. @@ -808,34 +807,16 @@ static void xhci_free_tt_info(struct xhci_hcd *xhci, } tt_list_head = &(xhci->rh_bw[virt_dev->real_port - 1].tts); - if (list_empty(tt_list_head)) - return; - - list_for_each(tt, tt_list_head) { - tt_info = list_entry(tt, struct xhci_tt_bw_info, tt_list); - if (tt_info->slot_id == slot_id) + list_for_each_entry_safe(tt_info, next, tt_list_head, tt_list) { + /* Multi-TT hubs will have more than one entry */ + if (tt_info->slot_id == slot_id) { + slot_found = true; + list_del(&tt_info->tt_list); + kfree(tt_info); + } else if (slot_found) { break; + } } - /* Cautionary measure in case the hub was disconnected before we - * stored the TT information. - */ - if (tt_info->slot_id != slot_id) - return; - - tt_next = tt->next; - tt_info = list_entry(tt, struct xhci_tt_bw_info, - tt_list); - /* Multi-TT hubs will have more than one entry */ - do { - list_del(tt); - kfree(tt_info); - tt = tt_next; - if (list_empty(tt_list_head)) - break; - tt_next = tt->next; - tt_info = list_entry(tt, struct xhci_tt_bw_info, - tt_list); - } while (tt_info->slot_id == slot_id); } int xhci_alloc_tt_info(struct xhci_hcd *xhci, @@ -1791,17 +1772,9 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) { struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller); struct dev_info *dev_info, *next; - struct list_head *tt_list_head; - struct list_head *tt; - struct list_head *endpoints; - struct list_head *ep, *q; - struct xhci_tt_bw_info *tt_info; - struct xhci_interval_bw_table *bwt; - struct xhci_virt_ep *virt_ep; - unsigned long flags; int size; - int i; + int i, j, num_ports; /* Free the Event Ring Segment Table and the actual Event Ring */ size = sizeof(struct xhci_erst_entry)*(xhci->erst.num_entries); @@ -1858,21 +1831,22 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) } spin_unlock_irqrestore(&xhci->lock, flags); - bwt = &xhci->rh_bw->bw_table; - for (i = 0; i < XHCI_MAX_INTERVAL; i++) { - endpoints = &bwt->interval_bw[i].endpoints; - list_for_each_safe(ep, q, endpoints) { - virt_ep = list_entry(ep, struct xhci_virt_ep, bw_endpoint_list); - list_del(&virt_ep->bw_endpoint_list); - kfree(virt_ep); + num_ports = HCS_MAX_PORTS(xhci->hcs_params1); + for (i = 0; i < num_ports; i++) { + struct xhci_interval_bw_table *bwt = &xhci->rh_bw[i].bw_table; + for (j = 0; j < XHCI_MAX_INTERVAL; j++) { + struct list_head *ep = &bwt->interval_bw[j].endpoints; + while (!list_empty(ep)) + list_del_init(ep->next); } } - tt_list_head = &xhci->rh_bw->tts; - list_for_each_safe(tt, q, tt_list_head) { - tt_info = list_entry(tt, struct xhci_tt_bw_info, tt_list); - list_del(tt); - kfree(tt_info); + for (i = 0; i < num_ports; i++) { + struct xhci_tt_bw_info *tt, *n; + list_for_each_entry_safe(tt, n, &xhci->rh_bw[i].tts, tt_list) { + list_del(&tt->tt_list); + kfree(tt); + } } xhci->num_usb2_ports = 0; diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 73356dcb9ae..dc1bbc524a5 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -805,8 +805,8 @@ int xhci_suspend(struct xhci_hcd *xhci) command = xhci_readl(xhci, &xhci->op_regs->command); command |= CMD_CSS; xhci_writel(xhci, command, &xhci->op_regs->command); - if (handshake(xhci, &xhci->op_regs->status, STS_SAVE, 0, 10*100)) { - xhci_warn(xhci, "WARN: xHC CMD_CSS timeout\n"); + if (handshake(xhci, &xhci->op_regs->status, STS_SAVE, 0, 10 * 1000)) { + xhci_warn(xhci, "WARN: xHC save state timeout\n"); spin_unlock_irq(&xhci->lock); return -ETIMEDOUT; } @@ -858,8 +858,8 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) command |= CMD_CRS; xhci_writel(xhci, command, &xhci->op_regs->command); if (handshake(xhci, &xhci->op_regs->status, - STS_RESTORE, 0, 10*100)) { - xhci_dbg(xhci, "WARN: xHC CMD_CSS timeout\n"); + STS_RESTORE, 0, 10 * 1000)) { + xhci_warn(xhci, "WARN: xHC restore state timeout\n"); spin_unlock_irq(&xhci->lock); return -ETIMEDOUT; } diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c index 768b4b55c81..9d63ba4d10d 100644 --- a/drivers/usb/musb/davinci.c +++ b/drivers/usb/musb/davinci.c @@ -34,6 +34,7 @@ #include #include +#include #include diff --git a/drivers/usb/musb/davinci.h b/drivers/usb/musb/davinci.h index 046c84433ca..371baa0ee50 100644 --- a/drivers/usb/musb/davinci.h +++ b/drivers/usb/musb/davinci.h @@ -15,7 +15,7 @@ */ /* Integrated highspeed/otg PHY */ -#define USBPHY_CTL_PADDR (DAVINCI_SYSTEM_MODULE_BASE + 0x34) +#define USBPHY_CTL_PADDR 0x01c40034 #define USBPHY_DATAPOL BIT(11) /* (dm355) switch D+/D- */ #define USBPHY_PHYCLKGD BIT(8) #define USBPHY_SESNDEN BIT(7) /* v(sess_end) comparator */ @@ -27,7 +27,7 @@ #define USBPHY_OTGPDWN BIT(1) #define USBPHY_PHYPDWN BIT(0) -#define DM355_DEEPSLEEP_PADDR (DAVINCI_SYSTEM_MODULE_BASE + 0x48) +#define DM355_DEEPSLEEP_PADDR 0x01c40048 #define DRVVBUS_FORCE BIT(2) #define DRVVBUS_OVERRIDE BIT(1) diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index f42c29b11f7..95918dacc99 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -1232,6 +1232,7 @@ static int musb_gadget_disable(struct usb_ep *ep) } musb_ep->desc = NULL; + musb_ep->end_point.desc = NULL; /* abort all pending DMA and requests */ nuke(musb_ep, -ESHUTDOWN); diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index ec30f95ef39..95de9c08da1 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -82,6 +82,7 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x10C4, 0x8066) }, /* Argussoft In-System Programmer */ { USB_DEVICE(0x10C4, 0x806F) }, /* IMS USB to RS422 Converter Cable */ { USB_DEVICE(0x10C4, 0x807A) }, /* Crumb128 board */ + { USB_DEVICE(0x10C4, 0x80C4) }, /* Cygnal Integrated Products, Inc., Optris infrared thermometer */ { USB_DEVICE(0x10C4, 0x80CA) }, /* Degree Controls Inc */ { USB_DEVICE(0x10C4, 0x80DD) }, /* Tracient RFID */ { USB_DEVICE(0x10C4, 0x80F6) }, /* Suunto sports instrument */ diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 95bba992416..53e3e2c5b33 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -737,6 +737,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(TELLDUS_VID, TELLDUS_TELLSTICK_PID) }, { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_SERIAL_VX7_PID) }, { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_CT29B_PID) }, + { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_RTS01_PID) }, { USB_DEVICE(FTDI_VID, FTDI_MAXSTREAM_PID) }, { USB_DEVICE(FTDI_VID, FTDI_PHI_FISCO_PID) }, { USB_DEVICE(TML_VID, TML_USB_SERIAL_PID) }, diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index f3c7c78ede3..5661c7e2d41 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -784,6 +784,7 @@ #define RTSYSTEMS_VID 0x2100 /* Vendor ID */ #define RTSYSTEMS_SERIAL_VX7_PID 0x9e52 /* Serial converter for VX-7 Radios using FT232RL */ #define RTSYSTEMS_CT29B_PID 0x9e54 /* CT29B Radio Cable */ +#define RTSYSTEMS_RTS01_PID 0x9e57 /* USB-RTS01 Radio Cable */ /* diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index 6edd26130e2..ef4d7adfbd9 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -317,13 +317,16 @@ static int mct_u232_set_modem_ctrl(struct usb_serial *serial, MCT_U232_SET_REQUEST_TYPE, 0, 0, buf, MCT_U232_SET_MODEM_CTRL_SIZE, WDR_TIMEOUT); - if (rc < 0) - dev_err(&serial->dev->dev, - "Set MODEM CTRL 0x%x failed (error = %d)\n", mcr, rc); + kfree(buf); + dbg("set_modem_ctrl: state=0x%x ==> mcr=0x%x", control_state, mcr); - kfree(buf); - return rc; + if (rc < 0) { + dev_err(&serial->dev->dev, + "Set MODEM CTRL 0x%x failed (error = %d)\n", mcr, rc); + return rc; + } + return 0; } /* mct_u232_set_modem_ctrl */ static int mct_u232_get_modem_stat(struct usb_serial *serial, diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index c526550694a..62739ff58c7 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -206,7 +206,7 @@ static const struct usb_device_id moschip_port_id_table[] = { {} /* terminating entry */ }; -static const struct usb_device_id moschip_id_table_combined[] __devinitconst = { +static const struct usb_device_id moschip_id_table_combined[] = { {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7840)}, {USB_DEVICE(USB_VENDOR_ID_MOSCHIP, MOSCHIP_DEVICE_ID_7820)}, {USB_DEVICE(USB_VENDOR_ID_BANDB, BANDB_DEVICE_ID_USO9ML2_2)}, diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index f4465ccddc3..2706d8acb94 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -47,6 +47,7 @@ /* Function prototypes */ static int option_probe(struct usb_serial *serial, const struct usb_device_id *id); +static void option_release(struct usb_serial *serial); static int option_send_setup(struct usb_serial_port *port); static void option_instat_callback(struct urb *urb); @@ -150,6 +151,7 @@ static void option_instat_callback(struct urb *urb); #define HUAWEI_PRODUCT_E14AC 0x14AC #define HUAWEI_PRODUCT_K3806 0x14AE #define HUAWEI_PRODUCT_K4605 0x14C6 +#define HUAWEI_PRODUCT_K5005 0x14C8 #define HUAWEI_PRODUCT_K3770 0x14C9 #define HUAWEI_PRODUCT_K3771 0x14CA #define HUAWEI_PRODUCT_K4510 0x14CB @@ -425,7 +427,7 @@ static void option_instat_callback(struct urb *urb); #define SAMSUNG_VENDOR_ID 0x04e8 #define SAMSUNG_PRODUCT_GT_B3730 0x6889 -/* YUGA products www.yuga-info.com*/ +/* YUGA products www.yuga-info.com gavin.kx@qq.com */ #define YUGA_VENDOR_ID 0x257A #define YUGA_PRODUCT_CEM600 0x1601 #define YUGA_PRODUCT_CEM610 0x1602 @@ -442,6 +444,8 @@ static void option_instat_callback(struct urb *urb); #define YUGA_PRODUCT_CEU516 0x160C #define YUGA_PRODUCT_CEU528 0x160D #define YUGA_PRODUCT_CEU526 0x160F +#define YUGA_PRODUCT_CEU881 0x161F +#define YUGA_PRODUCT_CEU882 0x162F #define YUGA_PRODUCT_CWM600 0x2601 #define YUGA_PRODUCT_CWM610 0x2602 @@ -457,23 +461,26 @@ static void option_instat_callback(struct urb *urb); #define YUGA_PRODUCT_CWU518 0x260B #define YUGA_PRODUCT_CWU516 0x260C #define YUGA_PRODUCT_CWU528 0x260D +#define YUGA_PRODUCT_CWU581 0x260E #define YUGA_PRODUCT_CWU526 0x260F - -#define YUGA_PRODUCT_CLM600 0x2601 -#define YUGA_PRODUCT_CLM610 0x2602 -#define YUGA_PRODUCT_CLM500 0x2603 -#define YUGA_PRODUCT_CLM510 0x2604 -#define YUGA_PRODUCT_CLM800 0x2605 -#define YUGA_PRODUCT_CLM900 0x2606 - -#define YUGA_PRODUCT_CLU718 0x2607 -#define YUGA_PRODUCT_CLU716 0x2608 -#define YUGA_PRODUCT_CLU728 0x2609 -#define YUGA_PRODUCT_CLU726 0x260A -#define YUGA_PRODUCT_CLU518 0x260B -#define YUGA_PRODUCT_CLU516 0x260C -#define YUGA_PRODUCT_CLU528 0x260D -#define YUGA_PRODUCT_CLU526 0x260F +#define YUGA_PRODUCT_CWU582 0x261F +#define YUGA_PRODUCT_CWU583 0x262F + +#define YUGA_PRODUCT_CLM600 0x3601 +#define YUGA_PRODUCT_CLM610 0x3602 +#define YUGA_PRODUCT_CLM500 0x3603 +#define YUGA_PRODUCT_CLM510 0x3604 +#define YUGA_PRODUCT_CLM800 0x3605 +#define YUGA_PRODUCT_CLM900 0x3606 + +#define YUGA_PRODUCT_CLU718 0x3607 +#define YUGA_PRODUCT_CLU716 0x3608 +#define YUGA_PRODUCT_CLU728 0x3609 +#define YUGA_PRODUCT_CLU726 0x360A +#define YUGA_PRODUCT_CLU518 0x360B +#define YUGA_PRODUCT_CLU516 0x360C +#define YUGA_PRODUCT_CLU528 0x360D +#define YUGA_PRODUCT_CLU526 0x360F /* Viettel products */ #define VIETTEL_VENDOR_ID 0x2262 @@ -666,6 +673,11 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3806, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4605, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t) &huawei_cdc12_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4605, 0xff, 0x01, 0x31) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4605, 0xff, 0x01, 0x32) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K5005, 0xff, 0x01, 0x31) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K5005, 0xff, 0x01, 0x32) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K5005, 0xff, 0x01, 0x33) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3770, 0xff, 0x02, 0x31) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3770, 0xff, 0x02, 0x32) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3771, 0xff, 0x02, 0x31) }, @@ -1209,6 +1221,11 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU516) }, { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU528) }, { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CLU526) }, + { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEU881) }, + { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEU882) }, + { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWU581) }, + { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWU582) }, + { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CWU583) }, { USB_DEVICE_AND_INTERFACE_INFO(VIETTEL_VENDOR_ID, VIETTEL_PRODUCT_VT1000, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZD_VENDOR_ID, ZD_PRODUCT_7000, 0xff, 0xff, 0xff) }, { USB_DEVICE(LG_VENDOR_ID, LG_PRODUCT_L02C) }, /* docomo L-02C modem */ @@ -1257,7 +1274,7 @@ static struct usb_serial_driver option_1port_device = { .ioctl = usb_wwan_ioctl, .attach = usb_wwan_startup, .disconnect = usb_wwan_disconnect, - .release = usb_wwan_release, + .release = option_release, .read_int_callback = option_instat_callback, #ifdef CONFIG_PM .suspend = usb_wwan_suspend, @@ -1271,35 +1288,6 @@ static struct usb_serial_driver * const serial_drivers[] = { static bool debug; -/* per port private data */ - -#define N_IN_URB 4 -#define N_OUT_URB 4 -#define IN_BUFLEN 4096 -#define OUT_BUFLEN 4096 - -struct option_port_private { - /* Input endpoints and buffer for this port */ - struct urb *in_urbs[N_IN_URB]; - u8 *in_buffer[N_IN_URB]; - /* Output endpoints and buffer for this port */ - struct urb *out_urbs[N_OUT_URB]; - u8 *out_buffer[N_OUT_URB]; - unsigned long out_busy; /* Bit vector of URBs in use */ - int opened; - struct usb_anchor delayed; - - /* Settings for the port */ - int rts_state; /* Handshaking pins (outputs) */ - int dtr_state; - int cts_state; /* Handshaking pins (inputs) */ - int dsr_state; - int dcd_state; - int ri_state; - - unsigned long tx_start_time[N_OUT_URB]; -}; - module_usb_serial_driver(option_driver, serial_drivers); static bool is_blacklisted(const u8 ifnum, enum option_blacklist_reason reason, @@ -1368,12 +1356,22 @@ static int option_probe(struct usb_serial *serial, return 0; } +static void option_release(struct usb_serial *serial) +{ + struct usb_wwan_intf_private *priv = usb_get_serial_data(serial); + + usb_wwan_release(serial); + + kfree(priv); +} + static void option_instat_callback(struct urb *urb) { int err; int status = urb->status; struct usb_serial_port *port = urb->context; - struct option_port_private *portdata = usb_get_serial_port_data(port); + struct usb_wwan_port_private *portdata = + usb_get_serial_port_data(port); dbg("%s", __func__); dbg("%s: urb %p port %p has data %p", __func__, urb, port, portdata); @@ -1434,7 +1432,7 @@ static int option_send_setup(struct usb_serial_port *port) struct usb_serial *serial = port->serial; struct usb_wwan_intf_private *intfdata = (struct usb_wwan_intf_private *) serial->private; - struct option_port_private *portdata; + struct usb_wwan_port_private *portdata; int ifNum = serial->interface->cur_altsetting->desc.bInterfaceNumber; int val = 0; dbg("%s", __func__); diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index fd6c48dbb44..f5b2c9564b2 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c @@ -105,7 +105,13 @@ static const struct usb_device_id id_table[] = { {USB_DEVICE(0x1410, 0xa021)}, /* Novatel Gobi 3000 Composite */ {USB_DEVICE(0x413c, 0x8193)}, /* Dell Gobi 3000 QDL */ {USB_DEVICE(0x413c, 0x8194)}, /* Dell Gobi 3000 Composite */ + {USB_DEVICE(0x1199, 0x9010)}, /* Sierra Wireless Gobi 3000 QDL */ + {USB_DEVICE(0x1199, 0x9012)}, /* Sierra Wireless Gobi 3000 QDL */ {USB_DEVICE(0x1199, 0x9013)}, /* Sierra Wireless Gobi 3000 Modem device (MC8355) */ + {USB_DEVICE(0x1199, 0x9014)}, /* Sierra Wireless Gobi 3000 QDL */ + {USB_DEVICE(0x1199, 0x9015)}, /* Sierra Wireless Gobi 3000 Modem device */ + {USB_DEVICE(0x1199, 0x9018)}, /* Sierra Wireless Gobi 3000 QDL */ + {USB_DEVICE(0x1199, 0x9019)}, /* Sierra Wireless Gobi 3000 Modem device */ {USB_DEVICE(0x12D1, 0x14F0)}, /* Sony Gobi 3000 QDL */ {USB_DEVICE(0x12D1, 0x14F1)}, /* Sony Gobi 3000 Composite */ {USB_DEVICE(0x05c6, 0x9048)}, /* MDM9x15 device */ diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 8c8bf806f6f..449bf6d31e2 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -304,6 +304,10 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x1199, 0x68A3), /* Sierra Wireless Direct IP modems */ .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist }, + /* AT&T Direct IP LTE modems */ + { USB_DEVICE_AND_INTERFACE_INFO(0x0F3D, 0x68AA, 0xFF, 0xFF, 0xFF), + .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist + }, { USB_DEVICE(0x0f3d, 0x68A3), /* Airprime/Sierra Wireless Direct IP modems */ .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist }, diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 6933355c964..bcf261778d0 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -670,12 +670,14 @@ static const struct usb_device_id *get_iface_id(struct usb_serial_driver *drv, static struct usb_serial_driver *search_serial_device( struct usb_interface *iface) { - const struct usb_device_id *id; + const struct usb_device_id *id = NULL; struct usb_serial_driver *drv; + struct usb_driver *driver = to_usb_driver(iface->dev.driver); /* Check if the usb id matches a known device */ list_for_each_entry(drv, &usb_serial_driver_list, driver_list) { - id = get_iface_id(drv, iface); + if (drv->usb_driver == driver) + id = get_iface_id(drv, iface); if (id) return drv; } diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 8f3cbb8dc81..f4d3e1a8e7d 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1107,6 +1107,13 @@ UNUSUAL_DEV( 0x090a, 0x1200, 0x0000, 0x9999, USB_SC_RBC, USB_PR_BULK, NULL, 0 ), +/* Feiya QDI U2 DISK, reported by Hans de Goede */ +UNUSUAL_DEV( 0x090c, 0x1000, 0x0000, 0xffff, + "Feiya", + "QDI U2 DISK", + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_NO_READ_CAPACITY_16 ), + /* aeb */ UNUSUAL_DEV( 0x090c, 0x1132, 0x0000, 0xffff, "Feiya", diff --git a/fs/hfsplus/ioctl.c b/fs/hfsplus/ioctl.c index c640ba57074..09addc8615f 100644 --- a/fs/hfsplus/ioctl.c +++ b/fs/hfsplus/ioctl.c @@ -31,6 +31,7 @@ static int hfsplus_ioctl_bless(struct file *file, int __user *user_flags) struct hfsplus_sb_info *sbi = HFSPLUS_SB(inode->i_sb); struct hfsplus_vh *vh = sbi->s_vhdr; struct hfsplus_vh *bvh = sbi->s_backup_vhdr; + u32 cnid = (unsigned long)dentry->d_fsdata; if (!capable(CAP_SYS_ADMIN)) return -EPERM; @@ -41,8 +42,12 @@ static int hfsplus_ioctl_bless(struct file *file, int __user *user_flags) vh->finder_info[0] = bvh->finder_info[0] = cpu_to_be32(parent_ino(dentry)); - /* Bootloader */ - vh->finder_info[1] = bvh->finder_info[1] = cpu_to_be32(inode->i_ino); + /* + * Bootloader. Just using the inode here breaks in the case of + * hard links - the firmware wants the ID of the hard link file, + * but the inode points at the indirect inode + */ + vh->finder_info[1] = bvh->finder_info[1] = cpu_to_be32(cnid); /* Per spec, the OS X system folder - same as finder_info[0] here */ vh->finder_info[5] = bvh->finder_info[5] = diff --git a/fs/hfsplus/wrapper.c b/fs/hfsplus/wrapper.c index 7daf4b852d1..90effcccca9 100644 --- a/fs/hfsplus/wrapper.c +++ b/fs/hfsplus/wrapper.c @@ -56,7 +56,7 @@ int hfsplus_submit_bio(struct super_block *sb, sector_t sector, DECLARE_COMPLETION_ONSTACK(wait); struct bio *bio; int ret = 0; - unsigned int io_size; + u64 io_size; loff_t start; int offset; diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 9e217326831..535f38420ca 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -1861,6 +1861,7 @@ static struct nfs4_state *nfs4_do_open(struct inode *dir, struct dentry *dentry, struct nfs4_state *res; int status; + fmode &= FMODE_READ|FMODE_WRITE; do { status = _nfs4_do_open(dir, dentry, fmode, flags, sattr, cred, &res); if (status == 0) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 7f71c69cdcd..e79c24e232f 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -862,7 +862,7 @@ static void free_session(struct kref *kref) struct nfsd4_session *ses; int mem; - BUG_ON(!spin_is_locked(&client_lock)); + lockdep_assert_held(&client_lock); ses = container_of(kref, struct nfsd4_session, se_ref); nfsd4_del_conns(ses); spin_lock(&nfsd_drc_lock); @@ -1041,7 +1041,7 @@ static struct nfs4_client *alloc_client(struct xdr_netobj name) static inline void free_client(struct nfs4_client *clp) { - BUG_ON(!spin_is_locked(&client_lock)); + lockdep_assert_held(&client_lock); while (!list_empty(&clp->cl_sessions)) { struct nfsd4_session *ses; ses = list_entry(clp->cl_sessions.next, struct nfsd4_session, diff --git a/include/linux/pci.h b/include/linux/pci.h index e444f5b4911..8b2921ad51a 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -176,6 +176,8 @@ enum pci_dev_flags { PCI_DEV_FLAGS_NO_D3 = (__force pci_dev_flags_t) 2, /* Provide indication device is assigned by a Virtual Machine Manager */ PCI_DEV_FLAGS_ASSIGNED = (__force pci_dev_flags_t) 4, + /* Device causes system crash if in D3 during S3 sleep */ + PCI_DEV_FLAGS_NO_D3_DURING_SLEEP = (__force pci_dev_flags_t) 8, }; enum pci_irq_reroute_variant { diff --git a/include/linux/swapops.h b/include/linux/swapops.h index 792d16d9cbc..47ead515c81 100644 --- a/include/linux/swapops.h +++ b/include/linux/swapops.h @@ -9,13 +9,15 @@ * get good packing density in that tree, so the index should be dense in * the low-order bits. * - * We arrange the `type' and `offset' fields so that `type' is at the five + * We arrange the `type' and `offset' fields so that `type' is at the seven * high-order bits of the swp_entry_t and `offset' is right-aligned in the - * remaining bits. + * remaining bits. Although `type' itself needs only five bits, we allow for + * shmem/tmpfs to shift it all up a further two bits: see swp_to_radix_entry(). * * swp_entry_t's are *never* stored anywhere in their arch-dependent format. */ -#define SWP_TYPE_SHIFT(e) (sizeof(e.val) * 8 - MAX_SWAPFILES_SHIFT) +#define SWP_TYPE_SHIFT(e) ((sizeof(e.val) * 8) - \ + (MAX_SWAPFILES_SHIFT + RADIX_TREE_EXCEPTIONAL_SHIFT)) #define SWP_OFFSET_MASK(e) ((1UL << SWP_TYPE_SHIFT(e)) - 1) /* diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h index a2c6424b9a0..961d7c75d9f 100644 --- a/include/linux/usb/hcd.h +++ b/include/linux/usb/hcd.h @@ -126,8 +126,6 @@ struct usb_hcd { unsigned wireless:1; /* Wireless USB HCD */ unsigned authorized_default:1; unsigned has_tt:1; /* Integrated TT in root hub */ - unsigned broken_pci_sleep:1; /* Don't put the - controller in PCI-D3 for system sleep */ unsigned int irq; /* irq allocated */ void __iomem *regs; /* device memory/io */ diff --git a/kernel/panic.c b/kernel/panic.c index 2bd000132e0..4931ce33305 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -132,8 +132,6 @@ void panic(const char *fmt, ...) */ crash_kexec(NULL); - kmsg_dump(KMSG_DUMP_PANIC); - /* print last_kmsg even after console suspend */ if (is_console_suspended()) resume_console(); @@ -145,6 +143,8 @@ void panic(const char *fmt, ...) */ smp_send_stop(); + kmsg_dump(KMSG_DUMP_PANIC); + atomic_notifier_call_chain(&panic_notifier_list, 0, buf); bust_spinlocks(0); diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c index f03fd83b170..e8c867173ae 100644 --- a/kernel/time/ntp.c +++ b/kernel/time/ntp.c @@ -412,6 +412,7 @@ int second_overflow(unsigned long secs) if (secs % 86400 == 0) { leap = -1; time_state = TIME_OOP; + time_tai++; printk(KERN_NOTICE "Clock: inserting leap second 23:59:60 UTC\n"); } @@ -426,7 +427,6 @@ int second_overflow(unsigned long secs) } break; case TIME_OOP: - time_tai++; time_state = TIME_WAIT; break; diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 700d2ae5f38..f3200176c49 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -384,7 +384,7 @@ EXPORT_SYMBOL_GPL(tracing_on); void tracing_off(void) { if (global_trace.buffer) - ring_buffer_record_on(global_trace.buffer); + ring_buffer_record_off(global_trace.buffer); /* * This flag is only looked at when buffers haven't been * allocated yet. We don't really care about the race diff --git a/mm/swapfile.c b/mm/swapfile.c index fafc26d1b1d..38186d96a72 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -1924,24 +1924,20 @@ static unsigned long read_swap_header(struct swap_info_struct *p, /* * Find out how many pages are allowed for a single swap - * device. There are three limiting factors: 1) the number + * device. There are two limiting factors: 1) the number * of bits for the swap offset in the swp_entry_t type, and * 2) the number of bits in the swap pte as defined by the - * the different architectures, and 3) the number of free bits - * in an exceptional radix_tree entry. In order to find the + * different architectures. In order to find the * largest possible bit mask, a swap entry with swap type 0 * and swap offset ~0UL is created, encoded to a swap pte, * decoded to a swp_entry_t again, and finally the swap * offset is extracted. This will mask all the bits from * the initial ~0UL mask that can't be encoded in either * the swp_entry_t or the architecture definition of a - * swap pte. Then the same is done for a radix_tree entry. + * swap pte. */ maxpages = swp_offset(pte_to_swp_entry( - swp_entry_to_pte(swp_entry(0, ~0UL)))); - maxpages = swp_offset(radix_to_swp_entry( - swp_to_radix_entry(swp_entry(0, maxpages)))) + 1; - + swp_entry_to_pte(swp_entry(0, ~0UL)))) + 1; if (maxpages > swap_header->info.last_page) { maxpages = swap_header->info.last_page + 1; /* p->max is an unsigned int: don't overflow it */ diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c index 3d432068f62..052d343d43f 100644 --- a/net/9p/trans_virtio.c +++ b/net/9p/trans_virtio.c @@ -192,10 +192,10 @@ static int pack_sg_list(struct scatterlist *sg, int start, s = rest_of_page(data); if (s > count) s = count; + BUG_ON(index > limit); sg_set_buf(&sg[index++], data, s); count -= s; data += s; - BUG_ON(index > limit); } return index-start; diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 3b62cf28803..faa078f74b2 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c @@ -71,7 +71,9 @@ static void rpc_purge_list(wait_queue_head_t *waitq, struct list_head *head, msg->errno = err; destroy_msg(msg); } while (!list_empty(head)); - wake_up(waitq); + + if (waitq) + wake_up(waitq); } static void @@ -91,11 +93,9 @@ rpc_timeout_upcall_queue(struct work_struct *work) } dentry = dget(pipe->dentry); spin_unlock(&pipe->lock); - if (dentry) { - rpc_purge_list(&RPC_I(dentry->d_inode)->waitq, - &free_list, destroy_msg, -ETIMEDOUT); - dput(dentry); - } + rpc_purge_list(dentry ? &RPC_I(dentry->d_inode)->waitq : NULL, + &free_list, destroy_msg, -ETIMEDOUT); + dput(dentry); } ssize_t rpc_pipe_generic_upcall(struct file *filp, struct rpc_pipe_msg *msg, diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index 4153846984a..234ee39000a 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c @@ -1379,7 +1379,8 @@ bc_svc_process(struct svc_serv *serv, struct rpc_rqst *req, sizeof(req->rq_snd_buf)); return bc_send(req); } else { - /* Nothing to do to drop request */ + /* drop request */ + xprt_free_bc_request(req); return 0; } } diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index 65d525d74c5..4e190b5950b 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c @@ -2084,7 +2084,6 @@ static int wm8904_probe(struct snd_soc_codec *codec) { struct wm8904_priv *wm8904 = snd_soc_codec_get_drvdata(codec); struct wm8904_pdata *pdata = wm8904->pdata; - u16 *reg_cache = codec->reg_cache; int ret, i; codec->cache_sync = 1; @@ -2180,14 +2179,18 @@ static int wm8904_probe(struct snd_soc_codec *codec) if (!pdata->gpio_cfg[i]) continue; - reg_cache[WM8904_GPIO_CONTROL_1 + i] - = pdata->gpio_cfg[i] & 0xffff; + regmap_update_bits(wm8904->regmap, + WM8904_GPIO_CONTROL_1 + i, + 0xffff, + pdata->gpio_cfg[i]); } /* Zero is the default value for these anyway */ for (i = 0; i < WM8904_MIC_REGS; i++) - reg_cache[WM8904_MIC_BIAS_CONTROL_0 + i] - = pdata->mic_cfg[i]; + regmap_update_bits(wm8904->regmap, + WM8904_MIC_BIAS_CONTROL_0 + i, + 0xffff, + pdata->mic_cfg[i]); } /* Set Class W by default - this will be managed by the Class From cbac6fedf2fb073dfb5d14c318d22379a78a26f3 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Sat, 21 Dec 2013 10:03:39 +0100 Subject: [PATCH 074/215] Linux 3.4.5 --- Documentation/device-mapper/verity.txt | 131 ++++++------------ Documentation/stable_kernel_rules.txt | 6 + Makefile | 2 +- arch/arm/mach-dove/include/mach/bridge-regs.h | 1 + arch/arm/mach-dove/include/mach/dove.h | 1 + .../mach-kirkwood/include/mach/bridge-regs.h | 1 + .../arm/mach-kirkwood/include/mach/kirkwood.h | 1 + .../mach-mv78xx0/include/mach/bridge-regs.h | 1 + arch/arm/mach-mv78xx0/include/mach/mv78xx0.h | 2 + .../mach-orion5x/include/mach/bridge-regs.h | 2 +- arch/arm/mach-orion5x/include/mach/orion5x.h | 1 + arch/arm/mach-tegra/reset.c | 2 +- arch/arm/mm/mmu.c | 73 ++++++++++ arch/arm/plat-orion/common.c | 2 +- arch/arm/plat-samsung/include/plat/map-s3c.h | 2 +- .../include/plat/watchdog-reset.h | 2 +- arch/x86/ia32/ia32_signal.c | 2 +- arch/x86/include/asm/cpufeature.h | 2 +- arch/x86/include/asm/pgtable-3level.h | 54 ++++++++ arch/x86/kernel/acpi/boot.c | 27 ++-- arch/x86/kernel/cpu/scattered.c | 2 +- arch/x86/kernel/reboot.c | 8 ++ drivers/acpi/acpi_pad.c | 7 +- drivers/acpi/acpica/hwsleep.c | 22 --- drivers/acpi/apei/apei-base.c | 17 ++- drivers/acpi/apei/apei-internal.h | 9 ++ drivers/acpi/apei/ghes.c | 6 +- drivers/acpi/sleep.c | 4 +- drivers/acpi/sysfs.c | 4 +- drivers/acpi/video.c | 2 + drivers/block/umem.c | 40 ++++++ drivers/block/xen-blkback/common.h | 2 + drivers/clk/clk.c | 27 ++-- drivers/dma/pl330.c | 2 +- drivers/gpio/gpio-wm8994.c | 5 +- drivers/gpu/drm/drm_edid.c | 2 +- drivers/gpu/drm/i915/i915_irq.c | 57 ++++---- drivers/gpu/drm/i915/i915_suspend.c | 5 +- drivers/gpu/drm/nouveau/nouveau_fbcon.c | 2 +- drivers/gpu/drm/radeon/radeon_gart.c | 13 +- drivers/gpu/drm/radeon/si.c | 4 +- drivers/hwmon/applesmc.c | 4 +- drivers/hwmon/coretemp.c | 4 +- drivers/hwspinlock/hwspinlock_core.c | 4 +- drivers/iommu/amd_iommu.c | 9 ++ drivers/iommu/amd_iommu_init.c | 4 +- drivers/iommu/tegra-smmu.c | 4 +- .../md/persistent-data/dm-space-map-checker.c | 54 +++++--- .../md/persistent-data/dm-space-map-disk.c | 11 +- .../persistent-data/dm-transaction-manager.c | 11 +- drivers/media/dvb/siano/smsusb.c | 2 + drivers/media/video/gspca/gspca.c | 4 +- drivers/mtd/nand/cafe_nand.c | 2 +- drivers/net/bonding/bond_main.c | 9 +- drivers/net/can/c_can/c_can.c | 4 +- drivers/net/can/flexcan.c | 4 +- drivers/net/dummy.c | 4 +- drivers/net/ethernet/broadcom/bnx2x/bnx2x.h | 15 -- .../net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | 35 +++-- drivers/net/ethernet/broadcom/tg3.c | 3 +- drivers/net/ethernet/emulex/benet/be_main.c | 5 +- drivers/net/ethernet/intel/e1000e/defines.h | 1 + drivers/net/ethernet/intel/e1000e/ethtool.c | 6 +- drivers/net/ethernet/intel/e1000e/mac.c | 2 +- drivers/net/ethernet/intel/e1000e/netdev.c | 79 +++-------- drivers/net/ethernet/intel/e1000e/phy.c | 8 +- drivers/net/ethernet/intel/igbvf/ethtool.c | 29 ++-- drivers/net/ethernet/intel/ixgbe/ixgbe.h | 4 +- drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c | 2 +- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 14 +- drivers/net/ethernet/marvell/sky2.c | 10 +- drivers/net/ethernet/nxp/lpc_eth.c | 11 +- drivers/net/ethernet/realtek/r8169.c | 3 + drivers/net/ethernet/sun/niu.c | 12 +- drivers/net/macvtap.c | 25 +++- drivers/net/usb/ipheth.c | 5 + drivers/net/usb/qmi_wwan.c | 109 +++++++++------ drivers/net/wireless/ath/ath.h | 1 + drivers/net/wireless/ath/ath9k/ath9k.h | 1 + drivers/net/wireless/ath/ath9k/htc_drv_main.c | 5 +- drivers/net/wireless/ath/ath9k/hw.c | 16 ++- drivers/net/wireless/ath/ath9k/main.c | 18 +-- drivers/net/wireless/ath/ath9k/recv.c | 7 +- drivers/net/wireless/ath/ath9k/xmit.c | 31 +++-- drivers/net/wireless/ath/key.c | 4 + drivers/net/wireless/ipw2x00/ipw.h | 23 +++ drivers/net/wireless/ipw2x00/ipw2100.c | 4 + drivers/net/wireless/ipw2x00/ipw2200.c | 4 + drivers/net/wireless/iwlwifi/iwl-mac80211.c | 12 ++ drivers/net/wireless/iwlwifi/iwl-trans-pcie.c | 6 + drivers/net/wireless/mwifiex/11n_rxreorder.c | 5 +- drivers/net/wireless/mwifiex/11n_rxreorder.h | 7 + drivers/net/wireless/mwifiex/cfg80211.c | 21 ++- drivers/net/wireless/mwifiex/wmm.c | 3 + drivers/net/wireless/rtl818x/rtl8187/leds.c | 2 +- drivers/net/wireless/rtlwifi/rtl8192cu/sw.c | 3 + drivers/net/xen-netfront.c | 8 +- drivers/oprofile/oprofile_perf.c | 2 +- drivers/pci/pci-driver.c | 12 ++ drivers/pci/pci.c | 5 - drivers/pci/quirks.c | 26 ---- drivers/remoteproc/Kconfig | 2 + drivers/rpmsg/virtio_rpmsg_bus.c | 55 +++++++- drivers/rtc/rtc-ab8500.c | 2 +- drivers/rtc/rtc-mxc.c | 5 +- drivers/rtc/rtc-spear.c | 2 +- drivers/scsi/aic94xx/aic94xx_task.c | 2 +- drivers/scsi/libsas/sas_ata.c | 12 +- drivers/scsi/sd.c | 2 + drivers/staging/iio/adc/ad7606_core.c | 1 + drivers/staging/rtl8712/usb_intf.c | 2 + drivers/target/tcm_fc/tfc_sess.c | 3 +- drivers/usb/class/cdc-wdm.c | 2 + drivers/usb/core/hub.c | 18 +-- drivers/usb/host/xhci-hub.c | 44 +++++- drivers/usb/host/xhci.h | 6 +- drivers/usb/serial/cp210x.c | 11 ++ drivers/usb/serial/metro-usb.c | 8 -- drivers/usb/serial/option.c | 34 +++++ drivers/usb/storage/scsiglue.c | 6 + drivers/usb/storage/unusual_devs.h | 7 - drivers/video/omap2/dss/apply.c | 2 +- drivers/video/omap2/dss/dispc.c | 5 +- drivers/video/omap2/dss/dss.h | 3 +- fs/btrfs/tree-log.c | 6 + fs/cifs/connect.c | 41 +++--- fs/exec.c | 2 +- fs/lockd/clntlock.c | 13 +- fs/lockd/svc.c | 38 +++-- fs/nfs/callback.c | 16 ++- fs/nfs/idmap.c | 13 +- fs/nfsd/nfsctl.c | 12 +- fs/nfsd/nfssvc.c | 29 +++- fs/nilfs2/gcinode.c | 2 + fs/nilfs2/segment.c | 2 + fs/ocfs2/file.c | 6 +- fs/open.c | 6 +- fs/ramfs/file-nommu.c | 1 + fs/splice.c | 35 +++-- fs/udf/super.c | 102 +++++++++----- include/asm-generic/pgtable.h | 32 ++++- include/linux/aio.h | 1 + include/linux/lockd/bind.h | 4 +- include/linux/memblock.h | 4 +- include/linux/mm_types.h | 10 ++ include/linux/mmzone.h | 2 +- include/linux/pci.h | 2 - include/linux/rpmsg.h | 6 + include/linux/skbuff.h | 7 +- include/linux/splice.h | 8 +- include/linux/sunrpc/svc.h | 1 + include/net/cipso_ipv4.h | 29 +++- include/net/inetpeer.h | 5 +- include/net/sch_generic.h | 7 +- include/scsi/libsas.h | 6 +- include/scsi/scsi_cmnd.h | 8 +- include/scsi/scsi_device.h | 1 + kernel/exit.c | 1 + kernel/relay.c | 5 +- kernel/trace/trace.c | 8 +- lib/dynamic_queue_limits.c | 18 ++- mm/compaction.c | 5 +- mm/memblock.c | 123 ++++++++++------ mm/nobootmem.c | 38 +++-- mm/shmem.c | 3 +- mm/vmscan.c | 7 +- net/batman-adv/routing.c | 2 + net/batman-adv/translation-table.c | 8 +- net/bridge/br_if.c | 1 + net/bridge/br_netlink.c | 2 +- net/bridge/br_private.h | 1 + net/can/raw.c | 3 - net/core/dev.c | 23 +-- net/core/drop_monitor.c | 102 +++++--------- net/core/neighbour.c | 14 +- net/core/netpoll.c | 11 +- net/core/skbuff.c | 3 +- net/core/sock.c | 7 +- net/ipv4/inetpeer.c | 16 ++- net/ipv6/ip6_fib.c | 2 +- net/ipv6/route.c | 41 ++++-- net/iucv/af_iucv.c | 1 - net/l2tp/l2tp_eth.c | 2 + net/l2tp/l2tp_ip.c | 9 +- net/mac80211/mlme.c | 24 ++-- net/mac80211/rx.c | 5 +- net/nfc/nci/ntf.c | 10 +- net/nfc/rawsock.c | 5 +- net/sunrpc/rpcb_clnt.c | 12 +- net/sunrpc/svc.c | 23 ++- net/wireless/reg.c | 2 +- sound/pci/hda/hda_codec.c | 2 + sound/pci/hda/patch_realtek.c | 1 + sound/pci/hda/patch_sigmatel.c | 4 +- sound/soc/codecs/tlv320aic3x.c | 4 +- sound/soc/codecs/tlv320aic3x.h | 1 + sound/soc/codecs/wm2200.c | 1 + tools/hv/hv_kvp_daemon.c | 10 +- 198 files changed, 1597 insertions(+), 947 deletions(-) create mode 100644 drivers/net/wireless/ipw2x00/ipw.h diff --git a/Documentation/device-mapper/verity.txt b/Documentation/device-mapper/verity.txt index 32e48797a14..9884681535e 100644 --- a/Documentation/device-mapper/verity.txt +++ b/Documentation/device-mapper/verity.txt @@ -7,39 +7,39 @@ This target is read-only. Construction Parameters ======================= - + - This is the version number of the on-disk format. + This is the type of the on-disk hash format. 0 is the original format used in the Chromium OS. - The salt is appended when hashing, digests are stored continuously and - the rest of the block is padded with zeros. + The salt is appended when hashing, digests are stored continuously and + the rest of the block is padded with zeros. 1 is the current format that should be used for new devices. - The salt is prepended when hashing and each digest is - padded with zeros to the power of two. + The salt is prepended when hashing and each digest is + padded with zeros to the power of two. - This is the device containing the data the integrity of which needs to be + This is the device containing data, the integrity of which needs to be checked. It may be specified as a path, like /dev/sdaX, or a device number, :. - This is the device that that supplies the hash tree data. It may be + This is the device that supplies the hash tree data. It may be specified similarly to the device path and may be the same device. If the - same device is used, the hash_start should be outside of the dm-verity - configured device size. + same device is used, the hash_start should be outside the configured + dm-verity device. - The block size on a data device. Each block corresponds to one digest on - the hash device. + The block size on a data device in bytes. + Each block corresponds to one digest on the hash device. - The size of a hash block. + The size of a hash block in bytes. The number of data blocks on the data device. Additional blocks are @@ -65,7 +65,7 @@ Construction Parameters Theory of operation =================== -dm-verity is meant to be setup as part of a verified boot path. This +dm-verity is meant to be set up as part of a verified boot path. This may be anything ranging from a boot using tboot or trustedgrub to just booting from a known-good device (like a USB drive or CD). @@ -73,20 +73,20 @@ When a dm-verity device is configured, it is expected that the caller has been authenticated in some way (cryptographic signatures, etc). After instantiation, all hashes will be verified on-demand during disk access. If they cannot be verified up to the root node of the -tree, the root hash, then the I/O will fail. This should identify +tree, the root hash, then the I/O will fail. This should detect tampering with any data on the device and the hash data. Cryptographic hashes are used to assert the integrity of the device on a -per-block basis. This allows for a lightweight hash computation on first read -into the page cache. Block hashes are stored linearly-aligned to the nearest -block the size of a page. +per-block basis. This allows for a lightweight hash computation on first read +into the page cache. Block hashes are stored linearly, aligned to the nearest +block size. Hash Tree --------- Each node in the tree is a cryptographic hash. If it is a leaf node, the hash -is of some block data on disk. If it is an intermediary node, then the hash is -of a number of child nodes. +of some data block on disk is calculated. If it is an intermediary node, +the hash of a number of child nodes is calculated. Each entry in the tree is a collection of neighboring nodes that fit in one block. The number is determined based on block_size and the size of the @@ -110,63 +110,23 @@ alg = sha256, num_blocks = 32768, block_size = 4096 On-disk format ============== -Below is the recommended on-disk format. The verity kernel code does not -read the on-disk header. It only reads the hash blocks which directly -follow the header. It is expected that a user-space tool will verify the -integrity of the verity_header and then call dmsetup with the correct -parameters. Alternatively, the header can be omitted and the dmsetup -parameters can be passed via the kernel command-line in a rooted chain -of trust where the command-line is verified. +The verity kernel code does not read the verity metadata on-disk header. +It only reads the hash blocks which directly follow the header. +It is expected that a user-space tool will verify the integrity of the +verity header. -The on-disk format is especially useful in cases where the hash blocks -are on a separate partition. The magic number allows easy identification -of the partition contents. Alternatively, the hash blocks can be stored -in the same partition as the data to be verified. In such a configuration -the filesystem on the partition would be sized a little smaller than -the full-partition, leaving room for the hash blocks. - -struct superblock { - uint8_t signature[8] - "verity\0\0"; - - uint8_t version; - 1 - current format - - uint8_t data_block_bits; - log2(data block size) - - uint8_t hash_block_bits; - log2(hash block size) - - uint8_t pad1[1]; - zero padding - - uint16_t salt_size; - big-endian salt size - - uint8_t pad2[2]; - zero padding - - uint32_t data_blocks_hi; - big-endian high 32 bits of the 64-bit number of data blocks - - uint32_t data_blocks_lo; - big-endian low 32 bits of the 64-bit number of data blocks - - uint8_t algorithm[16]; - cryptographic algorithm - - uint8_t salt[384]; - salt (the salt size is specified above) - - uint8_t pad3[88]; - zero padding to 512-byte boundary -} +Alternatively, the header can be omitted and the dmsetup parameters can +be passed via the kernel command-line in a rooted chain of trust where +the command-line is verified. Directly following the header (and with sector number padded to the next hash block boundary) are the hash blocks which are stored a depth at a time (starting from the root), sorted in order of increasing index. +The full specification of kernel parameters and on-disk metadata format +is available at the cryptsetup project's wiki page + http://code.google.com/p/cryptsetup/wiki/DMVerity + Status ====== V (for Valid) is returned if every check performed so far was valid. @@ -174,21 +134,22 @@ If any check failed, C (for Corruption) is returned. Example ======= - -Setup a device: - dmsetup create vroot --table \ - "0 2097152 "\ - "verity 1 /dev/sda1 /dev/sda2 4096 4096 2097152 1 "\ +Set up a device: + # dmsetup create vroot --readonly --table \ + "0 2097152 verity 1 /dev/sda1 /dev/sda2 4096 4096 262144 1 sha256 "\ "4392712ba01368efdf14b05c76f9e4df0d53664630b5d48632ed17a137f39076 "\ "1234000000000000000000000000000000000000000000000000000000000000" A command line tool veritysetup is available to compute or verify -the hash tree or activate the kernel driver. This is available from -the LVM2 upstream repository and may be supplied as a package called -device-mapper-verity-tools: - git://sources.redhat.com/git/lvm2 - http://sourceware.org/git/?p=lvm2.git - http://sourceware.org/cgi-bin/cvsweb.cgi/LVM2/verity?cvsroot=lvm2 - -veritysetup -a vroot /dev/sda1 /dev/sda2 \ - 4392712ba01368efdf14b05c76f9e4df0d53664630b5d48632ed17a137f39076 +the hash tree or activate the kernel device. This is available from +the cryptsetup upstream repository http://code.google.com/p/cryptsetup/ +(as a libcryptsetup extension). + +Create hash on the device: + # veritysetup format /dev/sda1 /dev/sda2 + ... + Root hash: 4392712ba01368efdf14b05c76f9e4df0d53664630b5d48632ed17a137f39076 + +Activate the device: + # veritysetup create vroot /dev/sda1 /dev/sda2 \ + 4392712ba01368efdf14b05c76f9e4df0d53664630b5d48632ed17a137f39076 diff --git a/Documentation/stable_kernel_rules.txt b/Documentation/stable_kernel_rules.txt index f0ab5cf28fc..4a7b54bd37e 100644 --- a/Documentation/stable_kernel_rules.txt +++ b/Documentation/stable_kernel_rules.txt @@ -12,6 +12,12 @@ Rules on what kind of patches are accepted, and which ones are not, into the marked CONFIG_BROKEN), an oops, a hang, data corruption, a real security issue, or some "oh, that's not good" issue. In short, something critical. + - Serious issues as reported by a user of a distribution kernel may also + be considered if they fix a notable performance or interactivity issue. + As these fixes are not as obvious and have a higher risk of a subtle + regression they should only be submitted by a distribution kernel + maintainer and include an addendum linking to a bugzilla entry if it + exists and additional information on the user-visible impact. - New device IDs and quirks are also accepted. - No "theoretical race condition" issues, unless an explanation of how the race can be exploited is also provided. diff --git a/Makefile b/Makefile index bd66308f3d9..8fd6fb4e32c 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 4 -SUBLEVEL = 4 +SUBLEVEL = 5 EXTRAVERSION = NAME = Saber-toothed Squirrel diff --git a/arch/arm/mach-dove/include/mach/bridge-regs.h b/arch/arm/mach-dove/include/mach/bridge-regs.h index 226949dc4ac..f953bb54aa9 100644 --- a/arch/arm/mach-dove/include/mach/bridge-regs.h +++ b/arch/arm/mach-dove/include/mach/bridge-regs.h @@ -50,5 +50,6 @@ #define POWER_MANAGEMENT (BRIDGE_VIRT_BASE | 0x011c) #define TIMER_VIRT_BASE (BRIDGE_VIRT_BASE | 0x0300) +#define TIMER_PHYS_BASE (BRIDGE_PHYS_BASE | 0x0300) #endif diff --git a/arch/arm/mach-dove/include/mach/dove.h b/arch/arm/mach-dove/include/mach/dove.h index ad1165d488c..d52b0ef313b 100644 --- a/arch/arm/mach-dove/include/mach/dove.h +++ b/arch/arm/mach-dove/include/mach/dove.h @@ -78,6 +78,7 @@ /* North-South Bridge */ #define BRIDGE_VIRT_BASE (DOVE_SB_REGS_VIRT_BASE | 0x20000) +#define BRIDGE_PHYS_BASE (DOVE_SB_REGS_PHYS_BASE | 0x20000) /* Cryptographic Engine */ #define DOVE_CRYPT_PHYS_BASE (DOVE_SB_REGS_PHYS_BASE | 0x30000) diff --git a/arch/arm/mach-kirkwood/include/mach/bridge-regs.h b/arch/arm/mach-kirkwood/include/mach/bridge-regs.h index 957bd7997d7..086f25e761d 100644 --- a/arch/arm/mach-kirkwood/include/mach/bridge-regs.h +++ b/arch/arm/mach-kirkwood/include/mach/bridge-regs.h @@ -38,6 +38,7 @@ #define IRQ_MASK_HIGH_OFF 0x0014 #define TIMER_VIRT_BASE (BRIDGE_VIRT_BASE | 0x0300) +#define TIMER_PHYS_BASE (BRIDGE_PHYS_BASE | 0x0300) #define L2_CONFIG_REG (BRIDGE_VIRT_BASE | 0x0128) #define L2_WRITETHROUGH 0x00000010 diff --git a/arch/arm/mach-kirkwood/include/mach/kirkwood.h b/arch/arm/mach-kirkwood/include/mach/kirkwood.h index fede3d503ef..c5b68510776 100644 --- a/arch/arm/mach-kirkwood/include/mach/kirkwood.h +++ b/arch/arm/mach-kirkwood/include/mach/kirkwood.h @@ -80,6 +80,7 @@ #define UART1_VIRT_BASE (DEV_BUS_VIRT_BASE | 0x2100) #define BRIDGE_VIRT_BASE (KIRKWOOD_REGS_VIRT_BASE | 0x20000) +#define BRIDGE_PHYS_BASE (KIRKWOOD_REGS_PHYS_BASE | 0x20000) #define CRYPTO_PHYS_BASE (KIRKWOOD_REGS_PHYS_BASE | 0x30000) diff --git a/arch/arm/mach-mv78xx0/include/mach/bridge-regs.h b/arch/arm/mach-mv78xx0/include/mach/bridge-regs.h index c64dbb96dba..eb187e0e059 100644 --- a/arch/arm/mach-mv78xx0/include/mach/bridge-regs.h +++ b/arch/arm/mach-mv78xx0/include/mach/bridge-regs.h @@ -31,5 +31,6 @@ #define IRQ_MASK_HIGH_OFF 0x0014 #define TIMER_VIRT_BASE (BRIDGE_VIRT_BASE | 0x0300) +#define TIMER_PHYS_BASE (BRIDGE_PHYS_BASE | 0x0300) #endif diff --git a/arch/arm/mach-mv78xx0/include/mach/mv78xx0.h b/arch/arm/mach-mv78xx0/include/mach/mv78xx0.h index 3674497162e..e807c4c52a0 100644 --- a/arch/arm/mach-mv78xx0/include/mach/mv78xx0.h +++ b/arch/arm/mach-mv78xx0/include/mach/mv78xx0.h @@ -42,6 +42,7 @@ #define MV78XX0_CORE0_REGS_PHYS_BASE 0xf1020000 #define MV78XX0_CORE1_REGS_PHYS_BASE 0xf1024000 #define MV78XX0_CORE_REGS_VIRT_BASE 0xfe400000 +#define MV78XX0_CORE_REGS_PHYS_BASE 0xfe400000 #define MV78XX0_CORE_REGS_SIZE SZ_16K #define MV78XX0_PCIE_IO_PHYS_BASE(i) (0xf0800000 + ((i) << 20)) @@ -59,6 +60,7 @@ * Core-specific peripheral registers. */ #define BRIDGE_VIRT_BASE (MV78XX0_CORE_REGS_VIRT_BASE) +#define BRIDGE_PHYS_BASE (MV78XX0_CORE_REGS_PHYS_BASE) /* * Register Map diff --git a/arch/arm/mach-orion5x/include/mach/bridge-regs.h b/arch/arm/mach-orion5x/include/mach/bridge-regs.h index 96484bcd34c..11a3c1e9801 100644 --- a/arch/arm/mach-orion5x/include/mach/bridge-regs.h +++ b/arch/arm/mach-orion5x/include/mach/bridge-regs.h @@ -35,5 +35,5 @@ #define MAIN_IRQ_MASK (ORION5X_BRIDGE_VIRT_BASE | 0x204) #define TIMER_VIRT_BASE (ORION5X_BRIDGE_VIRT_BASE | 0x300) - +#define TIMER_PHYS_BASE (ORION5X_BRIDGE_PHYS_BASE | 0x300) #endif diff --git a/arch/arm/mach-orion5x/include/mach/orion5x.h b/arch/arm/mach-orion5x/include/mach/orion5x.h index 2745f5d95b3..683e085ce16 100644 --- a/arch/arm/mach-orion5x/include/mach/orion5x.h +++ b/arch/arm/mach-orion5x/include/mach/orion5x.h @@ -82,6 +82,7 @@ #define UART1_VIRT_BASE (ORION5X_DEV_BUS_VIRT_BASE | 0x2100) #define ORION5X_BRIDGE_VIRT_BASE (ORION5X_REGS_VIRT_BASE | 0x20000) +#define ORION5X_BRIDGE_PHYS_BASE (ORION5X_REGS_PHYS_BASE | 0x20000) #define ORION5X_PCI_VIRT_BASE (ORION5X_REGS_VIRT_BASE | 0x30000) diff --git a/arch/arm/mach-tegra/reset.c b/arch/arm/mach-tegra/reset.c index 4d6a2ee99c3..5beb7ebe294 100644 --- a/arch/arm/mach-tegra/reset.c +++ b/arch/arm/mach-tegra/reset.c @@ -33,7 +33,7 @@ static bool is_enabled; -static void tegra_cpu_reset_handler_enable(void) +static void __init tegra_cpu_reset_handler_enable(void) { void __iomem *iram_base = IO_ADDRESS(TEGRA_IRAM_RESET_BASE); void __iomem *evp_cpu_reset = diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index da33be0f13c..275979be531 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -912,6 +912,79 @@ static void __init fill_pmd_gaps(void) #define fill_pmd_gaps() do { } while (0) #endif +#ifndef CONFIG_ARM_LPAE + +/* + * The Linux PMD is made of two consecutive section entries covering 2MB + * (see definition in include/asm/pgtable-2level.h). However a call to + * create_mapping() may optimize static mappings by using individual + * 1MB section mappings. This leaves the actual PMD potentially half + * initialized if the top or bottom section entry isn't used, leaving it + * open to problems if a subsequent ioremap() or vmalloc() tries to use + * the virtual space left free by that unused section entry. + * + * Let's avoid the issue by inserting dummy vm entries covering the unused + * PMD halves once the static mappings are in place. + */ + +static void __init pmd_empty_section_gap(unsigned long addr) +{ + struct vm_struct *vm; + + vm = early_alloc_aligned(sizeof(*vm), __alignof__(*vm)); + vm->addr = (void *)addr; + vm->size = SECTION_SIZE; + vm->flags = VM_IOREMAP | VM_ARM_STATIC_MAPPING; + vm->caller = pmd_empty_section_gap; + vm_area_add_early(vm); +} + +static void __init fill_pmd_gaps(void) +{ + struct vm_struct *vm; + unsigned long addr, next = 0; + pmd_t *pmd; + + /* we're still single threaded hence no lock needed here */ + for (vm = vmlist; vm; vm = vm->next) { + if (!(vm->flags & VM_ARM_STATIC_MAPPING)) + continue; + addr = (unsigned long)vm->addr; + if (addr < next) + continue; + + /* + * Check if this vm starts on an odd section boundary. + * If so and the first section entry for this PMD is free + * then we block the corresponding virtual address. + */ + if ((addr & ~PMD_MASK) == SECTION_SIZE) { + pmd = pmd_off_k(addr); + if (pmd_none(*pmd)) + pmd_empty_section_gap(addr & PMD_MASK); + } + + /* + * Then check if this vm ends on an odd section boundary. + * If so and the second section entry for this PMD is empty + * then we block the corresponding virtual address. + */ + addr += vm->size; + if ((addr & ~PMD_MASK) == SECTION_SIZE) { + pmd = pmd_off_k(addr) + 1; + if (pmd_none(*pmd)) + pmd_empty_section_gap(addr); + } + + /* no need to look at any vm entry until we hit the next PMD */ + next = (addr + PMD_SIZE - 1) & PMD_MASK; + } +} + +#else +#define fill_pmd_gaps() do { } while (0) +#endif + static void * __initdata vmalloc_min = (void *)(VMALLOC_END - (240 << 20) - VMALLOC_OFFSET); diff --git a/arch/arm/plat-orion/common.c b/arch/arm/plat-orion/common.c index 74daf5ed143..331f8bbded9 100644 --- a/arch/arm/plat-orion/common.c +++ b/arch/arm/plat-orion/common.c @@ -570,7 +570,7 @@ void __init orion_spi_1_init(unsigned long mapbase, static struct orion_wdt_platform_data orion_wdt_data; static struct resource orion_wdt_resource = - DEFINE_RES_MEM(TIMER_VIRT_BASE, 0x28); + DEFINE_RES_MEM(TIMER_PHYS_BASE, 0x28); static struct platform_device orion_wdt_device = { .name = "orion_wdt", diff --git a/arch/arm/plat-samsung/include/plat/map-s3c.h b/arch/arm/plat-samsung/include/plat/map-s3c.h index 7d048759b77..c0c70a895ca 100644 --- a/arch/arm/plat-samsung/include/plat/map-s3c.h +++ b/arch/arm/plat-samsung/include/plat/map-s3c.h @@ -22,7 +22,7 @@ #define S3C24XX_VA_WATCHDOG S3C_VA_WATCHDOG #define S3C2412_VA_SSMC S3C_ADDR_CPU(0x00000000) -#define S3C2412_VA_EBI S3C_ADDR_CPU(0x00010000) +#define S3C2412_VA_EBI S3C_ADDR_CPU(0x00100000) #define S3C2410_PA_UART (0x50000000) #define S3C24XX_PA_UART S3C2410_PA_UART diff --git a/arch/arm/plat-samsung/include/plat/watchdog-reset.h b/arch/arm/plat-samsung/include/plat/watchdog-reset.h index f19aff19205..bc4db9b04e3 100644 --- a/arch/arm/plat-samsung/include/plat/watchdog-reset.h +++ b/arch/arm/plat-samsung/include/plat/watchdog-reset.h @@ -25,7 +25,7 @@ static inline void arch_wdt_reset(void) __raw_writel(0, S3C2410_WTCON); /* disable watchdog, to be safe */ - if (s3c2410_wdtclk) + if (!IS_ERR(s3c2410_wdtclk)) clk_enable(s3c2410_wdtclk); /* put initial values into count and data */ diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c index a69245ba27e..4f5bfacf464 100644 --- a/arch/x86/ia32/ia32_signal.c +++ b/arch/x86/ia32/ia32_signal.c @@ -38,7 +38,7 @@ int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from) { int err = 0; - bool ia32 = is_ia32_task(); + bool ia32 = test_thread_flag(TIF_IA32); if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t))) return -EFAULT; diff --git a/arch/x86/include/asm/cpufeature.h b/arch/x86/include/asm/cpufeature.h index 340ee49961a..f91e80f4f18 100644 --- a/arch/x86/include/asm/cpufeature.h +++ b/arch/x86/include/asm/cpufeature.h @@ -176,7 +176,7 @@ #define X86_FEATURE_XSAVEOPT (7*32+ 4) /* Optimized Xsave */ #define X86_FEATURE_PLN (7*32+ 5) /* Intel Power Limit Notification */ #define X86_FEATURE_PTS (7*32+ 6) /* Intel Package Thermal Status */ -#define X86_FEATURE_DTS (7*32+ 7) /* Digital Thermal Sensor */ +#define X86_FEATURE_DTHERM (7*32+ 7) /* Digital Thermal Sensor */ #define X86_FEATURE_HW_PSTATE (7*32+ 8) /* AMD HW-PState */ /* Virtualization flags: Linux defined, word 8 */ diff --git a/arch/x86/include/asm/pgtable-3level.h b/arch/x86/include/asm/pgtable-3level.h index effff47a3c8..cb00ccc7d57 100644 --- a/arch/x86/include/asm/pgtable-3level.h +++ b/arch/x86/include/asm/pgtable-3level.h @@ -31,6 +31,60 @@ static inline void native_set_pte(pte_t *ptep, pte_t pte) ptep->pte_low = pte.pte_low; } +#define pmd_read_atomic pmd_read_atomic +/* + * pte_offset_map_lock on 32bit PAE kernels was reading the pmd_t with + * a "*pmdp" dereference done by gcc. Problem is, in certain places + * where pte_offset_map_lock is called, concurrent page faults are + * allowed, if the mmap_sem is hold for reading. An example is mincore + * vs page faults vs MADV_DONTNEED. On the page fault side + * pmd_populate rightfully does a set_64bit, but if we're reading the + * pmd_t with a "*pmdp" on the mincore side, a SMP race can happen + * because gcc will not read the 64bit of the pmd atomically. To fix + * this all places running pmd_offset_map_lock() while holding the + * mmap_sem in read mode, shall read the pmdp pointer using this + * function to know if the pmd is null nor not, and in turn to know if + * they can run pmd_offset_map_lock or pmd_trans_huge or other pmd + * operations. + * + * Without THP if the mmap_sem is hold for reading, the pmd can only + * transition from null to not null while pmd_read_atomic runs. So + * we can always return atomic pmd values with this function. + * + * With THP if the mmap_sem is hold for reading, the pmd can become + * trans_huge or none or point to a pte (and in turn become "stable") + * at any time under pmd_read_atomic. We could read it really + * atomically here with a atomic64_read for the THP enabled case (and + * it would be a whole lot simpler), but to avoid using cmpxchg8b we + * only return an atomic pmdval if the low part of the pmdval is later + * found stable (i.e. pointing to a pte). And we're returning a none + * pmdval if the low part of the pmd is none. In some cases the high + * and low part of the pmdval returned may not be consistent if THP is + * enabled (the low part may point to previously mapped hugepage, + * while the high part may point to a more recently mapped hugepage), + * but pmd_none_or_trans_huge_or_clear_bad() only needs the low part + * of the pmd to be read atomically to decide if the pmd is unstable + * or not, with the only exception of when the low part of the pmd is + * zero in which case we return a none pmd. + */ +static inline pmd_t pmd_read_atomic(pmd_t *pmdp) +{ + pmdval_t ret; + u32 *tmp = (u32 *)pmdp; + + ret = (pmdval_t) (*tmp); + if (ret) { + /* + * If the low part is null, we must not read the high part + * or we can end up with a partial pmd. + */ + smp_rmb(); + ret |= ((pmdval_t)*(tmp + 1)) << 32; + } + + return (pmd_t) { ret }; +} + static inline void native_set_pte_atomic(pte_t *ptep, pte_t pte) { set_64bit((unsigned long long *)(ptep), native_pte_val(pte)); diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index d4686c94067..8f489064db5 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -422,12 +422,14 @@ acpi_parse_int_src_ovr(struct acpi_subtable_header * header, return 0; } - if (intsrc->source_irq == 0 && intsrc->global_irq == 2) { + if (intsrc->source_irq == 0) { if (acpi_skip_timer_override) { - printk(PREFIX "BIOS IRQ0 pin2 override ignored.\n"); + printk(PREFIX "BIOS IRQ0 override ignored.\n"); return 0; } - if (acpi_fix_pin2_polarity && (intsrc->inti_flags & ACPI_MADT_POLARITY_MASK)) { + + if ((intsrc->global_irq == 2) && acpi_fix_pin2_polarity + && (intsrc->inti_flags & ACPI_MADT_POLARITY_MASK)) { intsrc->inti_flags &= ~ACPI_MADT_POLARITY_MASK; printk(PREFIX "BIOS IRQ0 pin2 override: forcing polarity to high active.\n"); } @@ -1334,17 +1336,12 @@ static int __init dmi_disable_acpi(const struct dmi_system_id *d) } /* - * Force ignoring BIOS IRQ0 pin2 override + * Force ignoring BIOS IRQ0 override */ static int __init dmi_ignore_irq0_timer_override(const struct dmi_system_id *d) { - /* - * The ati_ixp4x0_rev() early PCI quirk should have set - * the acpi_skip_timer_override flag already: - */ if (!acpi_skip_timer_override) { - WARN(1, KERN_ERR "ati_ixp4x0 quirk not complete.\n"); - pr_notice("%s detected: Ignoring BIOS IRQ0 pin2 override\n", + pr_notice("%s detected: Ignoring BIOS IRQ0 override\n", d->ident); acpi_skip_timer_override = 1; } @@ -1438,7 +1435,7 @@ static struct dmi_system_id __initdata acpi_dmi_table_late[] = { * is enabled. This input is incorrectly designated the * ISA IRQ 0 via an interrupt source override even though * it is wired to the output of the master 8259A and INTIN0 - * is not connected at all. Force ignoring BIOS IRQ0 pin2 + * is not connected at all. Force ignoring BIOS IRQ0 * override in that cases. */ { @@ -1473,6 +1470,14 @@ static struct dmi_system_id __initdata acpi_dmi_table_late[] = { DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq 6715b"), }, }, + { + .callback = dmi_ignore_irq0_timer_override, + .ident = "FUJITSU SIEMENS", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU SIEMENS"), + DMI_MATCH(DMI_PRODUCT_NAME, "AMILO PRO V2030"), + }, + }, {} }; diff --git a/arch/x86/kernel/cpu/scattered.c b/arch/x86/kernel/cpu/scattered.c index 354c4e024da..5e26bb2570b 100644 --- a/arch/x86/kernel/cpu/scattered.c +++ b/arch/x86/kernel/cpu/scattered.c @@ -31,7 +31,7 @@ void init_scattered_cpuid_features(struct cpuinfo_x86 *c) const struct cpuid_bit *cb; static const struct cpuid_bit cpuid_bits[] = { - { X86_FEATURE_DTS, CR_EAX, 0, 0x00000006, 0 }, + { X86_FEATURE_DTHERM, CR_EAX, 0, 0x00000006, 0 }, { X86_FEATURE_IDA, CR_EAX, 1, 0x00000006, 0 }, { X86_FEATURE_ARAT, CR_EAX, 2, 0x00000006, 0 }, { X86_FEATURE_PLN, CR_EAX, 4, 0x00000006, 0 }, diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index d840e69a853..3034ee5afb0 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c @@ -471,6 +471,14 @@ static struct dmi_system_id __initdata pci_reboot_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "OptiPlex 990"), }, }, + { /* Handle problems with rebooting on the Precision M6600. */ + .callback = set_pci_reboot, + .ident = "Dell OptiPlex 990", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Precision M6600"), + }, + }, { } }; diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c index a43fa1a57d5..1502c50273b 100644 --- a/drivers/acpi/acpi_pad.c +++ b/drivers/acpi/acpi_pad.c @@ -36,6 +36,7 @@ #define ACPI_PROCESSOR_AGGREGATOR_DEVICE_NAME "Processor Aggregator" #define ACPI_PROCESSOR_AGGREGATOR_NOTIFY 0x80 static DEFINE_MUTEX(isolated_cpus_lock); +static DEFINE_MUTEX(round_robin_lock); static unsigned long power_saving_mwait_eax; @@ -107,7 +108,7 @@ static void round_robin_cpu(unsigned int tsk_index) if (!alloc_cpumask_var(&tmp, GFP_KERNEL)) return; - mutex_lock(&isolated_cpus_lock); + mutex_lock(&round_robin_lock); cpumask_clear(tmp); for_each_cpu(cpu, pad_busy_cpus) cpumask_or(tmp, tmp, topology_thread_cpumask(cpu)); @@ -116,7 +117,7 @@ static void round_robin_cpu(unsigned int tsk_index) if (cpumask_empty(tmp)) cpumask_andnot(tmp, cpu_online_mask, pad_busy_cpus); if (cpumask_empty(tmp)) { - mutex_unlock(&isolated_cpus_lock); + mutex_unlock(&round_robin_lock); return; } for_each_cpu(cpu, tmp) { @@ -131,7 +132,7 @@ static void round_robin_cpu(unsigned int tsk_index) tsk_in_cpu[tsk_index] = preferred_cpu; cpumask_set_cpu(preferred_cpu, pad_busy_cpus); cpu_weight[preferred_cpu]++; - mutex_unlock(&isolated_cpus_lock); + mutex_unlock(&round_robin_lock); set_cpus_allowed_ptr(current, cpumask_of(preferred_cpu)); } diff --git a/drivers/acpi/acpica/hwsleep.c b/drivers/acpi/acpica/hwsleep.c index 0ed85cac323..615996a36be 100644 --- a/drivers/acpi/acpica/hwsleep.c +++ b/drivers/acpi/acpica/hwsleep.c @@ -95,18 +95,6 @@ acpi_status acpi_hw_legacy_sleep(u8 sleep_state, u8 flags) return_ACPI_STATUS(status); } - if (sleep_state != ACPI_STATE_S5) { - /* - * Disable BM arbitration. This feature is contained within an - * optional register (PM2 Control), so ignore a BAD_ADDRESS - * exception. - */ - status = acpi_write_bit_register(ACPI_BITREG_ARB_DISABLE, 1); - if (ACPI_FAILURE(status) && (status != AE_BAD_ADDRESS)) { - return_ACPI_STATUS(status); - } - } - /* * 1) Disable/Clear all GPEs * 2) Enable all wakeup GPEs @@ -364,16 +352,6 @@ acpi_status acpi_hw_legacy_wake(u8 sleep_state, u8 flags) [ACPI_EVENT_POWER_BUTTON]. status_register_id, ACPI_CLEAR_STATUS); - /* - * Enable BM arbitration. This feature is contained within an - * optional register (PM2 Control), so ignore a BAD_ADDRESS - * exception. - */ - status = acpi_write_bit_register(ACPI_BITREG_ARB_DISABLE, 0); - if (ACPI_FAILURE(status) && (status != AE_BAD_ADDRESS)) { - return_ACPI_STATUS(status); - } - acpi_hw_execute_sleep_method(METHOD_PATHNAME__SST, ACPI_SST_WORKING); return_ACPI_STATUS(status); } diff --git a/drivers/acpi/apei/apei-base.c b/drivers/acpi/apei/apei-base.c index 5577762daee..6686b1eaf13 100644 --- a/drivers/acpi/apei/apei-base.c +++ b/drivers/acpi/apei/apei-base.c @@ -243,7 +243,7 @@ static int pre_map_gar_callback(struct apei_exec_context *ctx, u8 ins = entry->instruction; if (ctx->ins_table[ins].flags & APEI_EXEC_INS_ACCESS_REGISTER) - return acpi_os_map_generic_address(&entry->register_region); + return apei_map_generic_address(&entry->register_region); return 0; } @@ -276,7 +276,7 @@ static int post_unmap_gar_callback(struct apei_exec_context *ctx, u8 ins = entry->instruction; if (ctx->ins_table[ins].flags & APEI_EXEC_INS_ACCESS_REGISTER) - acpi_os_unmap_generic_address(&entry->register_region); + apei_unmap_generic_address(&entry->register_region); return 0; } @@ -606,6 +606,19 @@ static int apei_check_gar(struct acpi_generic_address *reg, u64 *paddr, return 0; } +int apei_map_generic_address(struct acpi_generic_address *reg) +{ + int rc; + u32 access_bit_width; + u64 address; + + rc = apei_check_gar(reg, &address, &access_bit_width); + if (rc) + return rc; + return acpi_os_map_generic_address(reg); +} +EXPORT_SYMBOL_GPL(apei_map_generic_address); + /* read GAR in interrupt (including NMI) or process context */ int apei_read(u64 *val, struct acpi_generic_address *reg) { diff --git a/drivers/acpi/apei/apei-internal.h b/drivers/acpi/apei/apei-internal.h index cca240a3303..f220d642136 100644 --- a/drivers/acpi/apei/apei-internal.h +++ b/drivers/acpi/apei/apei-internal.h @@ -7,6 +7,8 @@ #define APEI_INTERNAL_H #include +#include +#include struct apei_exec_context; @@ -68,6 +70,13 @@ static inline int apei_exec_run_optional(struct apei_exec_context *ctx, u8 actio /* IP has been set in instruction function */ #define APEI_EXEC_SET_IP 1 +int apei_map_generic_address(struct acpi_generic_address *reg); + +static inline void apei_unmap_generic_address(struct acpi_generic_address *reg) +{ + acpi_os_unmap_generic_address(reg); +} + int apei_read(u64 *val, struct acpi_generic_address *reg); int apei_write(u64 val, struct acpi_generic_address *reg); diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c index 9b3cac0abec..1599566ed1f 100644 --- a/drivers/acpi/apei/ghes.c +++ b/drivers/acpi/apei/ghes.c @@ -301,7 +301,7 @@ static struct ghes *ghes_new(struct acpi_hest_generic *generic) if (!ghes) return ERR_PTR(-ENOMEM); ghes->generic = generic; - rc = acpi_os_map_generic_address(&generic->error_status_address); + rc = apei_map_generic_address(&generic->error_status_address); if (rc) goto err_free; error_block_length = generic->error_block_length; @@ -321,7 +321,7 @@ static struct ghes *ghes_new(struct acpi_hest_generic *generic) return ghes; err_unmap: - acpi_os_unmap_generic_address(&generic->error_status_address); + apei_unmap_generic_address(&generic->error_status_address); err_free: kfree(ghes); return ERR_PTR(rc); @@ -330,7 +330,7 @@ static struct ghes *ghes_new(struct acpi_hest_generic *generic) static void ghes_fini(struct ghes *ghes) { kfree(ghes->estatus); - acpi_os_unmap_generic_address(&ghes->generic->error_status_address); + apei_unmap_generic_address(&ghes->generic->error_status_address); } enum { diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index eb6fd233764..2377445f4a3 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -732,8 +732,8 @@ int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p) * can wake the system. _S0W may be valid, too. */ if (acpi_target_sleep_state == ACPI_STATE_S0 || - (device_may_wakeup(dev) && - adev->wakeup.sleep_state <= acpi_target_sleep_state)) { + (device_may_wakeup(dev) && adev->wakeup.flags.valid && + adev->wakeup.sleep_state >= acpi_target_sleep_state)) { acpi_status status; acpi_method[3] = 'W'; diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c index 9f66181c814..240a2440097 100644 --- a/drivers/acpi/sysfs.c +++ b/drivers/acpi/sysfs.c @@ -173,7 +173,7 @@ static int param_set_trace_state(const char *val, struct kernel_param *kp) { int result = 0; - if (!strncmp(val, "enable", strlen("enable") - 1)) { + if (!strncmp(val, "enable", strlen("enable"))) { result = acpi_debug_trace(trace_method_name, trace_debug_level, trace_debug_layer, 0); if (result) @@ -181,7 +181,7 @@ static int param_set_trace_state(const char *val, struct kernel_param *kp) goto exit; } - if (!strncmp(val, "disable", strlen("disable") - 1)) { + if (!strncmp(val, "disable", strlen("disable"))) { int name = 0; result = acpi_debug_trace((char *)&name, trace_debug_level, trace_debug_layer, 0); diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 66e8f7333e9..48b5a3cda37 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -558,6 +558,8 @@ acpi_video_bus_DOS(struct acpi_video_bus *video, int bios_flag, int lcd_flag) union acpi_object arg0 = { ACPI_TYPE_INTEGER }; struct acpi_object_list args = { 1, &arg0 }; + if (!video->cap._DOS) + return 0; if (bios_flag < 0 || bios_flag > 3 || lcd_flag < 0 || lcd_flag > 1) return -EINVAL; diff --git a/drivers/block/umem.c b/drivers/block/umem.c index aa2712060bf..9a72277a31d 100644 --- a/drivers/block/umem.c +++ b/drivers/block/umem.c @@ -513,6 +513,44 @@ static void process_page(unsigned long data) } } +struct mm_plug_cb { + struct blk_plug_cb cb; + struct cardinfo *card; +}; + +static void mm_unplug(struct blk_plug_cb *cb) +{ + struct mm_plug_cb *mmcb = container_of(cb, struct mm_plug_cb, cb); + + spin_lock_irq(&mmcb->card->lock); + activate(mmcb->card); + spin_unlock_irq(&mmcb->card->lock); + kfree(mmcb); +} + +static int mm_check_plugged(struct cardinfo *card) +{ + struct blk_plug *plug = current->plug; + struct mm_plug_cb *mmcb; + + if (!plug) + return 0; + + list_for_each_entry(mmcb, &plug->cb_list, cb.list) { + if (mmcb->cb.callback == mm_unplug && mmcb->card == card) + return 1; + } + /* Not currently on the callback list */ + mmcb = kmalloc(sizeof(*mmcb), GFP_ATOMIC); + if (!mmcb) + return 0; + + mmcb->card = card; + mmcb->cb.callback = mm_unplug; + list_add(&mmcb->cb.list, &plug->cb_list); + return 1; +} + static void mm_make_request(struct request_queue *q, struct bio *bio) { struct cardinfo *card = q->queuedata; @@ -523,6 +561,8 @@ static void mm_make_request(struct request_queue *q, struct bio *bio) *card->biotail = bio; bio->bi_next = NULL; card->biotail = &bio->bi_next; + if (bio->bi_rw & REQ_SYNC || !mm_check_plugged(card)) + activate(card); spin_unlock_irq(&card->lock); return; diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h index 773cf27dc23..9ad3b5ec1dc 100644 --- a/drivers/block/xen-blkback/common.h +++ b/drivers/block/xen-blkback/common.h @@ -257,6 +257,7 @@ static inline void blkif_get_x86_32_req(struct blkif_request *dst, break; case BLKIF_OP_DISCARD: dst->u.discard.flag = src->u.discard.flag; + dst->u.discard.id = src->u.discard.id; dst->u.discard.sector_number = src->u.discard.sector_number; dst->u.discard.nr_sectors = src->u.discard.nr_sectors; break; @@ -287,6 +288,7 @@ static inline void blkif_get_x86_64_req(struct blkif_request *dst, break; case BLKIF_OP_DISCARD: dst->u.discard.flag = src->u.discard.flag; + dst->u.discard.id = src->u.discard.id; dst->u.discard.sector_number = src->u.discard.sector_number; dst->u.discard.nr_sectors = src->u.discard.nr_sectors; break; diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 9cf6f59e3e1..2da025ee226 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -997,7 +997,7 @@ static struct clk *__clk_init_parent(struct clk *clk) if (!clk->parents) clk->parents = - kmalloc((sizeof(struct clk*) * clk->num_parents), + kzalloc((sizeof(struct clk*) * clk->num_parents), GFP_KERNEL); if (!clk->parents) @@ -1062,21 +1062,24 @@ static int __clk_set_parent(struct clk *clk, struct clk *parent) old_parent = clk->parent; - /* find index of new parent clock using cached parent ptrs */ - for (i = 0; i < clk->num_parents; i++) - if (clk->parents[i] == parent) - break; + if (!clk->parents) + clk->parents = kzalloc((sizeof(struct clk*) * clk->num_parents), + GFP_KERNEL); /* - * find index of new parent clock using string name comparison - * also try to cache the parent to avoid future calls to __clk_lookup + * find index of new parent clock using cached parent ptrs, + * or if not yet cached, use string name comparison and cache + * them now to avoid future calls to __clk_lookup. */ - if (i == clk->num_parents) - for (i = 0; i < clk->num_parents; i++) - if (!strcmp(clk->parent_names[i], parent->name)) { + for (i = 0; i < clk->num_parents; i++) { + if (clk->parents && clk->parents[i] == parent) + break; + else if (!strcmp(clk->parent_names[i], parent->name)) { + if (clk->parents) clk->parents[i] = __clk_lookup(parent->name); - break; - } + break; + } + } if (i == clk->num_parents) { pr_debug("%s: clock %s is not a possible parent of clock %s\n", diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c index fa3fb21e60b..8c44f17a99e 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c @@ -2322,7 +2322,7 @@ static void pl330_tasklet(unsigned long data) /* Pick up ripe tomatoes */ list_for_each_entry_safe(desc, _dt, &pch->work_list, node) if (desc->status == DONE) { - if (pch->cyclic) + if (!pch->cyclic) dma_cookie_complete(&desc->txd); list_move_tail(&desc->node, &list); } diff --git a/drivers/gpio/gpio-wm8994.c b/drivers/gpio/gpio-wm8994.c index 92ea5350dfe..aa61ad2fcaa 100644 --- a/drivers/gpio/gpio-wm8994.c +++ b/drivers/gpio/gpio-wm8994.c @@ -89,8 +89,11 @@ static int wm8994_gpio_direction_out(struct gpio_chip *chip, struct wm8994_gpio *wm8994_gpio = to_wm8994_gpio(chip); struct wm8994 *wm8994 = wm8994_gpio->wm8994; + if (value) + value = WM8994_GPN_LVL; + return wm8994_set_bits(wm8994, WM8994_GPIO_1 + offset, - WM8994_GPN_DIR, 0); + WM8994_GPN_DIR | WM8994_GPN_LVL, value); } static void wm8994_gpio_set(struct gpio_chip *chip, unsigned offset, int value) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 5a18b0df828..6e38325d04a 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -574,7 +574,7 @@ static bool drm_monitor_supports_rb(struct edid *edid) { if (edid->revision >= 4) { - bool ret; + bool ret = false; drm_for_each_detailed_block((u8 *)edid, is_rb, &ret); return ret; } diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index f57e5cfb162..26c67a78877 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -424,6 +424,30 @@ static void gen6_pm_rps_work(struct work_struct *work) mutex_unlock(&dev_priv->dev->struct_mutex); } +static void gen6_queue_rps_work(struct drm_i915_private *dev_priv, + u32 pm_iir) +{ + unsigned long flags; + + /* + * IIR bits should never already be set because IMR should + * prevent an interrupt from being shown in IIR. The warning + * displays a case where we've unsafely cleared + * dev_priv->pm_iir. Although missing an interrupt of the same + * type is not a problem, it displays a problem in the logic. + * + * The mask bit in IMR is cleared by rps_work. + */ + + spin_lock_irqsave(&dev_priv->rps_lock, flags); + dev_priv->pm_iir |= pm_iir; + I915_WRITE(GEN6_PMIMR, dev_priv->pm_iir); + POSTING_READ(GEN6_PMIMR); + spin_unlock_irqrestore(&dev_priv->rps_lock, flags); + + queue_work(dev_priv->wq, &dev_priv->rps_work); +} + static void pch_irq_handler(struct drm_device *dev, u32 pch_iir) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; @@ -529,16 +553,8 @@ static irqreturn_t ivybridge_irq_handler(DRM_IRQ_ARGS) pch_irq_handler(dev, pch_iir); } - if (pm_iir & GEN6_PM_DEFERRED_EVENTS) { - unsigned long flags; - spin_lock_irqsave(&dev_priv->rps_lock, flags); - WARN(dev_priv->pm_iir & pm_iir, "Missed a PM interrupt\n"); - dev_priv->pm_iir |= pm_iir; - I915_WRITE(GEN6_PMIMR, dev_priv->pm_iir); - POSTING_READ(GEN6_PMIMR); - spin_unlock_irqrestore(&dev_priv->rps_lock, flags); - queue_work(dev_priv->wq, &dev_priv->rps_work); - } + if (pm_iir & GEN6_PM_DEFERRED_EVENTS) + gen6_queue_rps_work(dev_priv, pm_iir); /* should clear PCH hotplug event before clear CPU irq */ I915_WRITE(SDEIIR, pch_iir); @@ -634,25 +650,8 @@ static irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS) i915_handle_rps_change(dev); } - if (IS_GEN6(dev) && pm_iir & GEN6_PM_DEFERRED_EVENTS) { - /* - * IIR bits should never already be set because IMR should - * prevent an interrupt from being shown in IIR. The warning - * displays a case where we've unsafely cleared - * dev_priv->pm_iir. Although missing an interrupt of the same - * type is not a problem, it displays a problem in the logic. - * - * The mask bit in IMR is cleared by rps_work. - */ - unsigned long flags; - spin_lock_irqsave(&dev_priv->rps_lock, flags); - WARN(dev_priv->pm_iir & pm_iir, "Missed a PM interrupt\n"); - dev_priv->pm_iir |= pm_iir; - I915_WRITE(GEN6_PMIMR, dev_priv->pm_iir); - POSTING_READ(GEN6_PMIMR); - spin_unlock_irqrestore(&dev_priv->rps_lock, flags); - queue_work(dev_priv->wq, &dev_priv->rps_work); - } + if (IS_GEN6(dev) && pm_iir & GEN6_PM_DEFERRED_EVENTS) + gen6_queue_rps_work(dev_priv, pm_iir); /* should clear PCH hotplug event before clear CPU irq */ I915_WRITE(SDEIIR, pch_iir); diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index 2b5eb229ff2..0d13778a5aa 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c @@ -740,8 +740,11 @@ static void i915_restore_display(struct drm_device *dev) if (HAS_PCH_SPLIT(dev)) { I915_WRITE(BLC_PWM_PCH_CTL1, dev_priv->saveBLC_PWM_CTL); I915_WRITE(BLC_PWM_PCH_CTL2, dev_priv->saveBLC_PWM_CTL2); - I915_WRITE(BLC_PWM_CPU_CTL, dev_priv->saveBLC_CPU_PWM_CTL); + /* NOTE: BLC_PWM_CPU_CTL must be written after BLC_PWM_CPU_CTL2; + * otherwise we get blank eDP screen after S3 on some machines + */ I915_WRITE(BLC_PWM_CPU_CTL2, dev_priv->saveBLC_CPU_PWM_CTL2); + I915_WRITE(BLC_PWM_CPU_CTL, dev_priv->saveBLC_CPU_PWM_CTL); I915_WRITE(PCH_PP_ON_DELAYS, dev_priv->savePP_ON_DELAYS); I915_WRITE(PCH_PP_OFF_DELAYS, dev_priv->savePP_OFF_DELAYS); I915_WRITE(PCH_PP_DIVISOR, dev_priv->savePP_DIVISOR); diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c index 8113e9201ed..6fd2211121f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c @@ -497,7 +497,7 @@ int nouveau_fbcon_init(struct drm_device *dev) nfbdev->helper.funcs = &nouveau_fbcon_helper_funcs; ret = drm_fb_helper_init(dev, &nfbdev->helper, - nv_two_heads(dev) ? 2 : 1, 4); + dev->mode_config.num_crtc, 4); if (ret) { kfree(nfbdev); return ret; diff --git a/drivers/gpu/drm/radeon/radeon_gart.c b/drivers/gpu/drm/radeon/radeon_gart.c index 62050f52194..2a4c592a75a 100644 --- a/drivers/gpu/drm/radeon/radeon_gart.c +++ b/drivers/gpu/drm/radeon/radeon_gart.c @@ -289,8 +289,9 @@ int radeon_vm_manager_init(struct radeon_device *rdev) rdev->vm_manager.enabled = false; /* mark first vm as always in use, it's the system one */ + /* allocate enough for 2 full VM pts */ r = radeon_sa_bo_manager_init(rdev, &rdev->vm_manager.sa_manager, - rdev->vm_manager.max_pfn * 8, + rdev->vm_manager.max_pfn * 8 * 2, RADEON_GEM_DOMAIN_VRAM); if (r) { dev_err(rdev->dev, "failed to allocate vm bo (%dKB)\n", @@ -635,7 +636,15 @@ int radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm) mutex_init(&vm->mutex); INIT_LIST_HEAD(&vm->list); INIT_LIST_HEAD(&vm->va); - vm->last_pfn = 0; + /* SI requires equal sized PTs for all VMs, so always set + * last_pfn to max_pfn. cayman allows variable sized + * pts so we can grow then as needed. Once we switch + * to two level pts we can unify this again. + */ + if (rdev->family >= CHIP_TAHITI) + vm->last_pfn = rdev->vm_manager.max_pfn; + else + vm->last_pfn = 0; /* map the ib pool buffer at 0 in virtual address space, set * read only */ diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 27bda986fc2..2af1ce69e6e 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -2527,12 +2527,12 @@ int si_pcie_gart_enable(struct radeon_device *rdev) WREG32(0x15DC, 0); /* empty context1-15 */ - /* FIXME start with 1G, once using 2 level pt switch to full + /* FIXME start with 4G, once using 2 level pt switch to full * vm size space */ /* set vm size, must be a multiple of 4 */ WREG32(VM_CONTEXT1_PAGE_TABLE_START_ADDR, 0); - WREG32(VM_CONTEXT1_PAGE_TABLE_END_ADDR, (1 << 30) / RADEON_GPU_PAGE_SIZE); + WREG32(VM_CONTEXT1_PAGE_TABLE_END_ADDR, rdev->vm_manager.max_pfn); for (i = 1; i < 16; i++) { if (i < 8) WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR + (i << 2), diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c index f082e48ab11..70d62f5bc90 100644 --- a/drivers/hwmon/applesmc.c +++ b/drivers/hwmon/applesmc.c @@ -215,7 +215,7 @@ static int read_smc(u8 cmd, const char *key, u8 *buffer, u8 len) int i; if (send_command(cmd) || send_argument(key)) { - pr_warn("%s: read arg fail\n", key); + pr_warn("%.4s: read arg fail\n", key); return -EIO; } @@ -223,7 +223,7 @@ static int read_smc(u8 cmd, const char *key, u8 *buffer, u8 len) for (i = 0; i < len; i++) { if (__wait_status(0x05)) { - pr_warn("%s: read data fail\n", key); + pr_warn("%.4s: read data fail\n", key); return -EIO; } buffer[i] = inb(APPLESMC_DATA_PORT); diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c index 74123d26283..07291e1d4fa 100644 --- a/drivers/hwmon/coretemp.c +++ b/drivers/hwmon/coretemp.c @@ -664,7 +664,7 @@ static void get_core_online(unsigned int cpu) * sensors. We check this bit only, all the early CPUs * without thermal sensors will be filtered out. */ - if (!cpu_has(c, X86_FEATURE_DTS)) + if (!cpu_has(c, X86_FEATURE_DTHERM)) return; if (!pdev) { @@ -765,7 +765,7 @@ static struct notifier_block coretemp_cpu_notifier __refdata = { }; static const struct x86_cpu_id coretemp_ids[] = { - { X86_VENDOR_INTEL, X86_FAMILY_ANY, X86_MODEL_ANY, X86_FEATURE_DTS }, + { X86_VENDOR_INTEL, X86_FAMILY_ANY, X86_MODEL_ANY, X86_FEATURE_DTHERM }, {} }; MODULE_DEVICE_TABLE(x86cpu, coretemp_ids); diff --git a/drivers/hwspinlock/hwspinlock_core.c b/drivers/hwspinlock/hwspinlock_core.c index 61c9cf15fa5..1201a15784c 100644 --- a/drivers/hwspinlock/hwspinlock_core.c +++ b/drivers/hwspinlock/hwspinlock_core.c @@ -345,7 +345,7 @@ int hwspin_lock_register(struct hwspinlock_device *bank, struct device *dev, spin_lock_init(&hwlock->lock); hwlock->bank = bank; - ret = hwspin_lock_register_single(hwlock, i); + ret = hwspin_lock_register_single(hwlock, base_id + i); if (ret) goto reg_failed; } @@ -354,7 +354,7 @@ int hwspin_lock_register(struct hwspinlock_device *bank, struct device *dev, reg_failed: while (--i >= 0) - hwspin_lock_unregister_single(i); + hwspin_lock_unregister_single(base_id + i); return ret; } EXPORT_SYMBOL_GPL(hwspin_lock_register); diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index a2e418cba0f..dfe7d37c82c 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -83,6 +83,8 @@ static struct iommu_ops amd_iommu_ops; static ATOMIC_NOTIFIER_HEAD(ppr_notifier); int amd_iommu_max_glx_val = -1; +static struct dma_map_ops amd_iommu_dma_ops; + /* * general struct to manage commands send to an IOMMU */ @@ -2267,6 +2269,13 @@ static int device_change_notifier(struct notifier_block *nb, list_add_tail(&dma_domain->list, &iommu_pd_list); spin_unlock_irqrestore(&iommu_pd_list_lock, flags); + dev_data = get_dev_data(dev); + + if (!dev_data->passthrough) + dev->archdata.dma_ops = &amd_iommu_dma_ops; + else + dev->archdata.dma_ops = &nommu_dma_ops; + break; case BUS_NOTIFY_DEL_DEVICE: diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index 542024ba6db..c04ddca7f12 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c @@ -1641,6 +1641,8 @@ static int __init amd_iommu_init(void) amd_iommu_init_api(); + x86_platform.iommu_shutdown = disable_iommus; + if (iommu_pass_through) goto out; @@ -1649,8 +1651,6 @@ static int __init amd_iommu_init(void) else printk(KERN_INFO "AMD-Vi: Lazy IO/TLB flushing enabled\n"); - x86_platform.iommu_shutdown = disable_iommus; - out: return ret; diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index eb93c821f59..17ef6c49366 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c @@ -550,13 +550,13 @@ static int alloc_pdir(struct smmu_as *as) return 0; as->pte_count = devm_kzalloc(smmu->dev, - sizeof(as->pte_count[0]) * SMMU_PDIR_COUNT, GFP_KERNEL); + sizeof(as->pte_count[0]) * SMMU_PDIR_COUNT, GFP_ATOMIC); if (!as->pte_count) { dev_err(smmu->dev, "failed to allocate smmu_device PTE cunters\n"); return -ENOMEM; } - as->pdir_page = alloc_page(GFP_KERNEL | __GFP_DMA); + as->pdir_page = alloc_page(GFP_ATOMIC | __GFP_DMA); if (!as->pdir_page) { dev_err(smmu->dev, "failed to allocate smmu_device page directory\n"); diff --git a/drivers/md/persistent-data/dm-space-map-checker.c b/drivers/md/persistent-data/dm-space-map-checker.c index 50ed53bf4aa..fc90c11620a 100644 --- a/drivers/md/persistent-data/dm-space-map-checker.c +++ b/drivers/md/persistent-data/dm-space-map-checker.c @@ -8,6 +8,7 @@ #include #include +#include #ifdef CONFIG_DM_DEBUG_SPACE_MAPS @@ -89,13 +90,23 @@ static int ca_create(struct count_array *ca, struct dm_space_map *sm) ca->nr = nr_blocks; ca->nr_free = nr_blocks; - ca->counts = kzalloc(sizeof(*ca->counts) * nr_blocks, GFP_KERNEL); - if (!ca->counts) - return -ENOMEM; + + if (!nr_blocks) + ca->counts = NULL; + else { + ca->counts = vzalloc(sizeof(*ca->counts) * nr_blocks); + if (!ca->counts) + return -ENOMEM; + } return 0; } +static void ca_destroy(struct count_array *ca) +{ + vfree(ca->counts); +} + static int ca_load(struct count_array *ca, struct dm_space_map *sm) { int r; @@ -126,12 +137,14 @@ static int ca_load(struct count_array *ca, struct dm_space_map *sm) static int ca_extend(struct count_array *ca, dm_block_t extra_blocks) { dm_block_t nr_blocks = ca->nr + extra_blocks; - uint32_t *counts = kzalloc(sizeof(*counts) * nr_blocks, GFP_KERNEL); + uint32_t *counts = vzalloc(sizeof(*counts) * nr_blocks); if (!counts) return -ENOMEM; - memcpy(counts, ca->counts, sizeof(*counts) * ca->nr); - kfree(ca->counts); + if (ca->counts) { + memcpy(counts, ca->counts, sizeof(*counts) * ca->nr); + ca_destroy(ca); + } ca->nr = nr_blocks; ca->nr_free += extra_blocks; ca->counts = counts; @@ -151,11 +164,6 @@ static int ca_commit(struct count_array *old, struct count_array *new) return 0; } -static void ca_destroy(struct count_array *ca) -{ - kfree(ca->counts); -} - /*----------------------------------------------------------------*/ struct sm_checker { @@ -343,25 +351,25 @@ struct dm_space_map *dm_sm_checker_create(struct dm_space_map *sm) int r; struct sm_checker *smc; - if (!sm) - return NULL; + if (IS_ERR_OR_NULL(sm)) + return ERR_PTR(-EINVAL); smc = kmalloc(sizeof(*smc), GFP_KERNEL); if (!smc) - return NULL; + return ERR_PTR(-ENOMEM); memcpy(&smc->sm, &ops_, sizeof(smc->sm)); r = ca_create(&smc->old_counts, sm); if (r) { kfree(smc); - return NULL; + return ERR_PTR(r); } r = ca_create(&smc->counts, sm); if (r) { ca_destroy(&smc->old_counts); kfree(smc); - return NULL; + return ERR_PTR(r); } smc->real_sm = sm; @@ -371,7 +379,7 @@ struct dm_space_map *dm_sm_checker_create(struct dm_space_map *sm) ca_destroy(&smc->counts); ca_destroy(&smc->old_counts); kfree(smc); - return NULL; + return ERR_PTR(r); } r = ca_commit(&smc->old_counts, &smc->counts); @@ -379,7 +387,7 @@ struct dm_space_map *dm_sm_checker_create(struct dm_space_map *sm) ca_destroy(&smc->counts); ca_destroy(&smc->old_counts); kfree(smc); - return NULL; + return ERR_PTR(r); } return &smc->sm; @@ -391,25 +399,25 @@ struct dm_space_map *dm_sm_checker_create_fresh(struct dm_space_map *sm) int r; struct sm_checker *smc; - if (!sm) - return NULL; + if (IS_ERR_OR_NULL(sm)) + return ERR_PTR(-EINVAL); smc = kmalloc(sizeof(*smc), GFP_KERNEL); if (!smc) - return NULL; + return ERR_PTR(-ENOMEM); memcpy(&smc->sm, &ops_, sizeof(smc->sm)); r = ca_create(&smc->old_counts, sm); if (r) { kfree(smc); - return NULL; + return ERR_PTR(r); } r = ca_create(&smc->counts, sm); if (r) { ca_destroy(&smc->old_counts); kfree(smc); - return NULL; + return ERR_PTR(r); } smc->real_sm = sm; diff --git a/drivers/md/persistent-data/dm-space-map-disk.c b/drivers/md/persistent-data/dm-space-map-disk.c index fc469ba9f62..3d0ed533288 100644 --- a/drivers/md/persistent-data/dm-space-map-disk.c +++ b/drivers/md/persistent-data/dm-space-map-disk.c @@ -290,7 +290,16 @@ struct dm_space_map *dm_sm_disk_create(struct dm_transaction_manager *tm, dm_block_t nr_blocks) { struct dm_space_map *sm = dm_sm_disk_create_real(tm, nr_blocks); - return dm_sm_checker_create_fresh(sm); + struct dm_space_map *smc; + + if (IS_ERR_OR_NULL(sm)) + return sm; + + smc = dm_sm_checker_create_fresh(sm); + if (IS_ERR(smc)) + dm_sm_destroy(sm); + + return smc; } EXPORT_SYMBOL_GPL(dm_sm_disk_create); diff --git a/drivers/md/persistent-data/dm-transaction-manager.c b/drivers/md/persistent-data/dm-transaction-manager.c index 6f8d38747d7..ba54aacf398 100644 --- a/drivers/md/persistent-data/dm-transaction-manager.c +++ b/drivers/md/persistent-data/dm-transaction-manager.c @@ -138,6 +138,9 @@ EXPORT_SYMBOL_GPL(dm_tm_create_non_blocking_clone); void dm_tm_destroy(struct dm_transaction_manager *tm) { + if (!tm->is_clone) + wipe_shadow_table(tm); + kfree(tm); } EXPORT_SYMBOL_GPL(dm_tm_destroy); @@ -342,8 +345,10 @@ static int dm_tm_create_internal(struct dm_block_manager *bm, } *sm = dm_sm_checker_create(inner); - if (!*sm) + if (IS_ERR(*sm)) { + r = PTR_ERR(*sm); goto bad2; + } } else { r = dm_bm_write_lock(dm_tm_get_bm(*tm), sb_location, @@ -362,8 +367,10 @@ static int dm_tm_create_internal(struct dm_block_manager *bm, } *sm = dm_sm_checker_create(inner); - if (!*sm) + if (IS_ERR(*sm)) { + r = PTR_ERR(*sm); goto bad2; + } } return 0; diff --git a/drivers/media/dvb/siano/smsusb.c b/drivers/media/dvb/siano/smsusb.c index 63c004a25e0..664e460f247 100644 --- a/drivers/media/dvb/siano/smsusb.c +++ b/drivers/media/dvb/siano/smsusb.c @@ -544,6 +544,8 @@ static const struct usb_device_id smsusb_id_table[] __devinitconst = { .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, { USB_DEVICE(0x2040, 0xc0a0), .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, + { USB_DEVICE(0x2040, 0xf5a0), + .driver_info = SMS1XXX_BOARD_HAUPPAUGE_WINDHAM }, { } /* Terminating entry */ }; diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index ca5a2b139d0..4dc88527961 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c @@ -1723,7 +1723,7 @@ static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type buf_type) { struct gspca_dev *gspca_dev = priv; - int ret; + int i, ret; if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; @@ -1754,6 +1754,8 @@ static int vidioc_streamoff(struct file *file, void *priv, wake_up_interruptible(&gspca_dev->wq); /* empty the transfer queues */ + for (i = 0; i < gspca_dev->nframes; i++) + gspca_dev->frame[i].v4l2_buf.flags &= ~BUF_ALL_FLAGS; atomic_set(&gspca_dev->fr_q, 0); atomic_set(&gspca_dev->fr_i, 0); gspca_dev->fr_o = 0; diff --git a/drivers/mtd/nand/cafe_nand.c b/drivers/mtd/nand/cafe_nand.c index 2a96e1a1206..6d22755969d 100644 --- a/drivers/mtd/nand/cafe_nand.c +++ b/drivers/mtd/nand/cafe_nand.c @@ -102,7 +102,7 @@ static const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL }; static int cafe_device_ready(struct mtd_info *mtd) { struct cafe_priv *cafe = mtd->priv; - int result = !!(cafe_readl(cafe, NAND_STATUS) | 0x40000000); + int result = !!(cafe_readl(cafe, NAND_STATUS) & 0x40000000); uint32_t irqs = cafe_readl(cafe, NAND_IRQ); cafe_writel(cafe, irqs, NAND_IRQ); diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index bc13b3d7743..a579a2f57c5 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -76,6 +76,7 @@ #include #include #include +#include #include "bonding.h" #include "bond_3ad.h" #include "bond_alb.h" @@ -381,8 +382,6 @@ struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr) return next; } -#define bond_queue_mapping(skb) (*(u16 *)((skb)->cb)) - /** * bond_dev_queue_xmit - Prepare skb for xmit. * @@ -395,7 +394,9 @@ int bond_dev_queue_xmit(struct bonding *bond, struct sk_buff *skb, { skb->dev = slave_dev; - skb->queue_mapping = bond_queue_mapping(skb); + BUILD_BUG_ON(sizeof(skb->queue_mapping) != + sizeof(qdisc_skb_cb(skb)->bond_queue_mapping)); + skb->queue_mapping = qdisc_skb_cb(skb)->bond_queue_mapping; if (unlikely(netpoll_tx_running(slave_dev))) bond_netpoll_send_skb(bond_get_slave_by_dev(bond, slave_dev), skb); @@ -4162,7 +4163,7 @@ static u16 bond_select_queue(struct net_device *dev, struct sk_buff *skb) /* * Save the original txq to restore before passing to the driver */ - bond_queue_mapping(skb) = skb->queue_mapping; + qdisc_skb_cb(skb)->bond_queue_mapping = skb->queue_mapping; if (unlikely(txq >= dev->real_num_tx_queues)) { do { diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c index 8dc84d66eea..86cd532c78f 100644 --- a/drivers/net/can/c_can/c_can.c +++ b/drivers/net/can/c_can/c_can.c @@ -590,8 +590,8 @@ static void c_can_chip_config(struct net_device *dev) priv->write_reg(priv, &priv->regs->control, CONTROL_ENABLE_AR); - if (priv->can.ctrlmode & (CAN_CTRLMODE_LISTENONLY & - CAN_CTRLMODE_LOOPBACK)) { + if ((priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) && + (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK)) { /* loopback + silent mode : useful for hot self-test */ priv->write_reg(priv, &priv->regs->control, CONTROL_EIE | CONTROL_SIE | CONTROL_IE | CONTROL_TEST); diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index 1efb08386c6..00baa7e094f 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -933,12 +933,12 @@ static int __devinit flexcan_probe(struct platform_device *pdev) u32 clock_freq = 0; if (pdev->dev.of_node) { - const u32 *clock_freq_p; + const __be32 *clock_freq_p; clock_freq_p = of_get_property(pdev->dev.of_node, "clock-frequency", NULL); if (clock_freq_p) - clock_freq = *clock_freq_p; + clock_freq = be32_to_cpup(clock_freq_p); } if (!clock_freq) { diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c index 442d91a2747..bab0158f1cc 100644 --- a/drivers/net/dummy.c +++ b/drivers/net/dummy.c @@ -187,8 +187,10 @@ static int __init dummy_init_module(void) rtnl_lock(); err = __rtnl_link_register(&dummy_link_ops); - for (i = 0; i < numdummies && !err; i++) + for (i = 0; i < numdummies && !err; i++) { err = dummy_init_one(); + cond_resched(); + } if (err < 0) __rtnl_link_unregister(&dummy_link_ops); rtnl_unlock(); diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h index 2c9ee552dff..75d35ec9b71 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h @@ -744,21 +744,6 @@ struct bnx2x_fastpath { #define ETH_RX_ERROR_FALGS ETH_FAST_PATH_RX_CQE_PHY_DECODE_ERR_FLG -#define BNX2X_IP_CSUM_ERR(cqe) \ - (!((cqe)->fast_path_cqe.status_flags & \ - ETH_FAST_PATH_RX_CQE_IP_XSUM_NO_VALIDATION_FLG) && \ - ((cqe)->fast_path_cqe.type_error_flags & \ - ETH_FAST_PATH_RX_CQE_IP_BAD_XSUM_FLG)) - -#define BNX2X_L4_CSUM_ERR(cqe) \ - (!((cqe)->fast_path_cqe.status_flags & \ - ETH_FAST_PATH_RX_CQE_L4_XSUM_NO_VALIDATION_FLG) && \ - ((cqe)->fast_path_cqe.type_error_flags & \ - ETH_FAST_PATH_RX_CQE_L4_BAD_XSUM_FLG)) - -#define BNX2X_RX_CSUM_OK(cqe) \ - (!(BNX2X_L4_CSUM_ERR(cqe) || BNX2X_IP_CSUM_ERR(cqe))) - #define BNX2X_PRS_FLAG_OVERETH_IPV4(flags) \ (((le16_to_cpu(flags) & \ PARSING_FLAGS_OVER_ETHERNET_PROTOCOL) >> \ diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index 4b054812713..41bb34fcf68 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -191,7 +191,7 @@ int bnx2x_tx_int(struct bnx2x *bp, struct bnx2x_fp_txdata *txdata) if ((netif_tx_queue_stopped(txq)) && (bp->state == BNX2X_STATE_OPEN) && - (bnx2x_tx_avail(bp, txdata) >= MAX_SKB_FRAGS + 3)) + (bnx2x_tx_avail(bp, txdata) >= MAX_SKB_FRAGS + 4)) netif_tx_wake_queue(txq); __netif_tx_unlock(txq); @@ -568,6 +568,25 @@ static inline void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp, fp->eth_q_stats.rx_skb_alloc_failed++; } +static void bnx2x_csum_validate(struct sk_buff *skb, union eth_rx_cqe *cqe, + struct bnx2x_fastpath *fp) +{ + /* Do nothing if no IP/L4 csum validation was done */ + + if (cqe->fast_path_cqe.status_flags & + (ETH_FAST_PATH_RX_CQE_IP_XSUM_NO_VALIDATION_FLG | + ETH_FAST_PATH_RX_CQE_L4_XSUM_NO_VALIDATION_FLG)) + return; + + /* If both IP/L4 validation were done, check if an error was found. */ + + if (cqe->fast_path_cqe.type_error_flags & + (ETH_FAST_PATH_RX_CQE_IP_BAD_XSUM_FLG | + ETH_FAST_PATH_RX_CQE_L4_BAD_XSUM_FLG)) + fp->eth_q_stats.hw_csum_err++; + else + skb->ip_summed = CHECKSUM_UNNECESSARY; +} int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget) { @@ -757,13 +776,9 @@ int bnx2x_rx_int(struct bnx2x_fastpath *fp, int budget) skb_checksum_none_assert(skb); - if (bp->dev->features & NETIF_F_RXCSUM) { + if (bp->dev->features & NETIF_F_RXCSUM) + bnx2x_csum_validate(skb, cqe, fp); - if (likely(BNX2X_RX_CSUM_OK(cqe))) - skb->ip_summed = CHECKSUM_UNNECESSARY; - else - fp->eth_q_stats.hw_csum_err++; - } skb_record_rx_queue(skb, fp->rx_queue); @@ -2334,8 +2349,6 @@ int bnx2x_poll(struct napi_struct *napi, int budget) /* we split the first BD into headers and data BDs * to ease the pain of our fellow microcode engineers * we use one mapping for both BDs - * So far this has only been observed to happen - * in Other Operating Systems(TM) */ static noinline u16 bnx2x_tx_split(struct bnx2x *bp, struct bnx2x_fp_txdata *txdata, @@ -2987,7 +3000,7 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) txdata->tx_bd_prod += nbd; - if (unlikely(bnx2x_tx_avail(bp, txdata) < MAX_SKB_FRAGS + 3)) { + if (unlikely(bnx2x_tx_avail(bp, txdata) < MAX_SKB_FRAGS + 4)) { netif_tx_stop_queue(txq); /* paired memory barrier is in bnx2x_tx_int(), we have to keep @@ -2996,7 +3009,7 @@ netdev_tx_t bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) smp_mb(); fp->eth_q_stats.driver_xoff++; - if (bnx2x_tx_avail(bp, txdata) >= MAX_SKB_FRAGS + 3) + if (bnx2x_tx_avail(bp, txdata) >= MAX_SKB_FRAGS + 4) netif_tx_wake_queue(txq); } txdata->tx_pkt++; diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index ceeab8e852e..1a1b29ff814 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -14248,7 +14248,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) } } - if (tg3_flag(tp, 5755_PLUS)) + if (tg3_flag(tp, 5755_PLUS) || + GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) tg3_flag_set(tp, SHORT_DMA_BUG); if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 528a886bc2c..1bbf6b3eca9 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -731,6 +731,8 @@ static netdev_tx_t be_xmit(struct sk_buff *skb, copied = make_tx_wrbs(adapter, txq, skb, wrb_cnt, dummy_wrb); if (copied) { + int gso_segs = skb_shinfo(skb)->gso_segs; + /* record the sent skb in the sent_skb table */ BUG_ON(txo->sent_skb_list[start]); txo->sent_skb_list[start] = skb; @@ -748,8 +750,7 @@ static netdev_tx_t be_xmit(struct sk_buff *skb, be_txq_notify(adapter, txq->id, wrb_cnt); - be_tx_stats_update(txo, wrb_cnt, copied, - skb_shinfo(skb)->gso_segs, stopped); + be_tx_stats_update(txo, wrb_cnt, copied, gso_segs, stopped); } else { txq->head = start; dev_kfree_skb_any(skb); diff --git a/drivers/net/ethernet/intel/e1000e/defines.h b/drivers/net/ethernet/intel/e1000e/defines.h index 3a502591716..eb84fe7b1c0 100644 --- a/drivers/net/ethernet/intel/e1000e/defines.h +++ b/drivers/net/ethernet/intel/e1000e/defines.h @@ -101,6 +101,7 @@ #define E1000_RXD_ERR_SEQ 0x04 /* Sequence Error */ #define E1000_RXD_ERR_CXE 0x10 /* Carrier Extension Error */ #define E1000_RXD_ERR_TCPE 0x20 /* TCP/UDP Checksum Error */ +#define E1000_RXD_ERR_IPE 0x40 /* IP Checksum Error */ #define E1000_RXD_ERR_RXE 0x80 /* Rx Data Error */ #define E1000_RXD_SPC_VLAN_MASK 0x0FFF /* VLAN ID is in lower 12 bits */ diff --git a/drivers/net/ethernet/intel/e1000e/ethtool.c b/drivers/net/ethernet/intel/e1000e/ethtool.c index db35dd5d96d..e48f2d2665c 100644 --- a/drivers/net/ethernet/intel/e1000e/ethtool.c +++ b/drivers/net/ethernet/intel/e1000e/ethtool.c @@ -258,7 +258,8 @@ static int e1000_set_settings(struct net_device *netdev, * When SoL/IDER sessions are active, autoneg/speed/duplex * cannot be changed */ - if (hw->phy.ops.check_reset_block(hw)) { + if (hw->phy.ops.check_reset_block && + hw->phy.ops.check_reset_block(hw)) { e_err("Cannot change link characteristics when SoL/IDER is " "active.\n"); return -EINVAL; @@ -1604,7 +1605,8 @@ static int e1000_loopback_test(struct e1000_adapter *adapter, u64 *data) * PHY loopback cannot be performed if SoL/IDER * sessions are active */ - if (hw->phy.ops.check_reset_block(hw)) { + if (hw->phy.ops.check_reset_block && + hw->phy.ops.check_reset_block(hw)) { e_err("Cannot do PHY loopback test when SoL/IDER is active.\n"); *data = 0; goto out; diff --git a/drivers/net/ethernet/intel/e1000e/mac.c b/drivers/net/ethernet/intel/e1000e/mac.c index decad98c105..efecb509fcd 100644 --- a/drivers/net/ethernet/intel/e1000e/mac.c +++ b/drivers/net/ethernet/intel/e1000e/mac.c @@ -709,7 +709,7 @@ s32 e1000e_setup_link_generic(struct e1000_hw *hw) * In the case of the phy reset being blocked, we already have a link. * We do not need to set it up again. */ - if (hw->phy.ops.check_reset_block(hw)) + if (hw->phy.ops.check_reset_block && hw->phy.ops.check_reset_block(hw)) return 0; /* diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index 00e961e42c6..5621d5b2876 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@ -495,7 +495,7 @@ static void e1000_receive_skb(struct e1000_adapter *adapter, * @sk_buff: socket buffer with received data **/ static void e1000_rx_checksum(struct e1000_adapter *adapter, u32 status_err, - __le16 csum, struct sk_buff *skb) + struct sk_buff *skb) { u16 status = (u16)status_err; u8 errors = (u8)(status_err >> 24); @@ -510,8 +510,8 @@ static void e1000_rx_checksum(struct e1000_adapter *adapter, u32 status_err, if (status & E1000_RXD_STAT_IXSM) return; - /* TCP/UDP checksum error bit is set */ - if (errors & E1000_RXD_ERR_TCPE) { + /* TCP/UDP checksum error bit or IP checksum error bit is set */ + if (errors & (E1000_RXD_ERR_TCPE | E1000_RXD_ERR_IPE)) { /* let the stack verify checksum errors */ adapter->hw_csum_err++; return; @@ -522,19 +522,7 @@ static void e1000_rx_checksum(struct e1000_adapter *adapter, u32 status_err, return; /* It must be a TCP or UDP packet with a valid checksum */ - if (status & E1000_RXD_STAT_TCPCS) { - /* TCP checksum is good */ - skb->ip_summed = CHECKSUM_UNNECESSARY; - } else { - /* - * IP fragment with UDP payload - * Hardware complements the payload checksum, so we undo it - * and then put the value in host order for further stack use. - */ - __sum16 sum = (__force __sum16)swab16((__force u16)csum); - skb->csum = csum_unfold(~sum); - skb->ip_summed = CHECKSUM_COMPLETE; - } + skb->ip_summed = CHECKSUM_UNNECESSARY; adapter->hw_csum_good++; } @@ -978,8 +966,7 @@ static bool e1000_clean_rx_irq(struct e1000_ring *rx_ring, int *work_done, skb_put(skb, length); /* Receive Checksum Offload */ - e1000_rx_checksum(adapter, staterr, - rx_desc->wb.lower.hi_dword.csum_ip.csum, skb); + e1000_rx_checksum(adapter, staterr, skb); e1000_rx_hash(netdev, rx_desc->wb.lower.hi_dword.rss, skb); @@ -1360,8 +1347,7 @@ static bool e1000_clean_rx_irq_ps(struct e1000_ring *rx_ring, int *work_done, total_rx_bytes += skb->len; total_rx_packets++; - e1000_rx_checksum(adapter, staterr, - rx_desc->wb.lower.hi_dword.csum_ip.csum, skb); + e1000_rx_checksum(adapter, staterr, skb); e1000_rx_hash(netdev, rx_desc->wb.lower.hi_dword.rss, skb); @@ -1531,9 +1517,8 @@ static bool e1000_clean_jumbo_rx_irq(struct e1000_ring *rx_ring, int *work_done, } } - /* Receive Checksum Offload XXX recompute due to CRC strip? */ - e1000_rx_checksum(adapter, staterr, - rx_desc->wb.lower.hi_dword.csum_ip.csum, skb); + /* Receive Checksum Offload */ + e1000_rx_checksum(adapter, staterr, skb); e1000_rx_hash(netdev, rx_desc->wb.lower.hi_dword.rss, skb); @@ -3120,19 +3105,10 @@ static void e1000_configure_rx(struct e1000_adapter *adapter) /* Enable Receive Checksum Offload for TCP and UDP */ rxcsum = er32(RXCSUM); - if (adapter->netdev->features & NETIF_F_RXCSUM) { + if (adapter->netdev->features & NETIF_F_RXCSUM) rxcsum |= E1000_RXCSUM_TUOFL; - - /* - * IPv4 payload checksum for UDP fragments must be - * used in conjunction with packet-split. - */ - if (adapter->rx_ps_pages) - rxcsum |= E1000_RXCSUM_IPPCSE; - } else { + else rxcsum &= ~E1000_RXCSUM_TUOFL; - /* no need to clear IPPCSE as it defaults to 0 */ - } ew32(RXCSUM, rxcsum); if (adapter->hw.mac.type == e1000_pch2lan) { @@ -5260,22 +5236,10 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu) int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN; /* Jumbo frame support */ - if (max_frame > ETH_FRAME_LEN + ETH_FCS_LEN) { - if (!(adapter->flags & FLAG_HAS_JUMBO_FRAMES)) { - e_err("Jumbo Frames not supported.\n"); - return -EINVAL; - } - - /* - * IP payload checksum (enabled with jumbos/packet-split when - * Rx checksum is enabled) and generation of RSS hash is - * mutually exclusive in the hardware. - */ - if ((netdev->features & NETIF_F_RXCSUM) && - (netdev->features & NETIF_F_RXHASH)) { - e_err("Jumbo frames cannot be enabled when both receive checksum offload and receive hashing are enabled. Disable one of the receive offload features before enabling jumbos.\n"); - return -EINVAL; - } + if ((max_frame > ETH_FRAME_LEN + ETH_FCS_LEN) && + !(adapter->flags & FLAG_HAS_JUMBO_FRAMES)) { + e_err("Jumbo Frames not supported.\n"); + return -EINVAL; } /* Supported frame sizes */ @@ -6049,17 +6013,6 @@ static int e1000_set_features(struct net_device *netdev, NETIF_F_RXALL))) return 0; - /* - * IP payload checksum (enabled with jumbos/packet-split when Rx - * checksum is enabled) and generation of RSS hash is mutually - * exclusive in the hardware. - */ - if (adapter->rx_ps_pages && - (features & NETIF_F_RXCSUM) && (features & NETIF_F_RXHASH)) { - e_err("Enabling both receive checksum offload and receive hashing is not possible with jumbo frames. Disable jumbos or enable only one of the receive offload features.\n"); - return -EINVAL; - } - if (changed & NETIF_F_RXFCS) { if (features & NETIF_F_RXFCS) { adapter->flags2 &= ~FLAG2_CRC_STRIPPING; @@ -6256,7 +6209,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev, adapter->hw.phy.ms_type = e1000_ms_hw_default; } - if (hw->phy.ops.check_reset_block(hw)) + if (hw->phy.ops.check_reset_block && hw->phy.ops.check_reset_block(hw)) e_info("PHY reset is blocked due to SOL/IDER session.\n"); /* Set initial default active device features */ @@ -6423,7 +6376,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev, if (!(adapter->flags & FLAG_HAS_AMT)) e1000e_release_hw_control(adapter); err_eeprom: - if (!hw->phy.ops.check_reset_block(hw)) + if (hw->phy.ops.check_reset_block && !hw->phy.ops.check_reset_block(hw)) e1000_phy_hw_reset(&adapter->hw); err_hw_init: kfree(adapter->tx_ring); diff --git a/drivers/net/ethernet/intel/e1000e/phy.c b/drivers/net/ethernet/intel/e1000e/phy.c index 35b45578c60..c4befb3dd26 100644 --- a/drivers/net/ethernet/intel/e1000e/phy.c +++ b/drivers/net/ethernet/intel/e1000e/phy.c @@ -2121,9 +2121,11 @@ s32 e1000e_phy_hw_reset_generic(struct e1000_hw *hw) s32 ret_val; u32 ctrl; - ret_val = phy->ops.check_reset_block(hw); - if (ret_val) - return 0; + if (phy->ops.check_reset_block) { + ret_val = phy->ops.check_reset_block(hw); + if (ret_val) + return 0; + } ret_val = phy->ops.acquire(hw); if (ret_val) diff --git a/drivers/net/ethernet/intel/igbvf/ethtool.c b/drivers/net/ethernet/intel/igbvf/ethtool.c index 8ce67064b9c..90eef07943f 100644 --- a/drivers/net/ethernet/intel/igbvf/ethtool.c +++ b/drivers/net/ethernet/intel/igbvf/ethtool.c @@ -357,21 +357,28 @@ static int igbvf_set_coalesce(struct net_device *netdev, struct igbvf_adapter *adapter = netdev_priv(netdev); struct e1000_hw *hw = &adapter->hw; - if ((ec->rx_coalesce_usecs > IGBVF_MAX_ITR_USECS) || - ((ec->rx_coalesce_usecs > 3) && - (ec->rx_coalesce_usecs < IGBVF_MIN_ITR_USECS)) || - (ec->rx_coalesce_usecs == 2)) - return -EINVAL; - - /* convert to rate of irq's per second */ - if (ec->rx_coalesce_usecs && ec->rx_coalesce_usecs <= 3) { + if ((ec->rx_coalesce_usecs >= IGBVF_MIN_ITR_USECS) && + (ec->rx_coalesce_usecs <= IGBVF_MAX_ITR_USECS)) { + adapter->current_itr = ec->rx_coalesce_usecs << 2; + adapter->requested_itr = 1000000000 / + (adapter->current_itr * 256); + } else if ((ec->rx_coalesce_usecs == 3) || + (ec->rx_coalesce_usecs == 2)) { adapter->current_itr = IGBVF_START_ITR; adapter->requested_itr = ec->rx_coalesce_usecs; - } else { - adapter->current_itr = ec->rx_coalesce_usecs << 2; + } else if (ec->rx_coalesce_usecs == 0) { + /* + * The user's desire is to turn off interrupt throttling + * altogether, but due to HW limitations, we can't do that. + * Instead we set a very small value in EITR, which would + * allow ~967k interrupts per second, but allow the adapter's + * internal clocking to still function properly. + */ + adapter->current_itr = 4; adapter->requested_itr = 1000000000 / (adapter->current_itr * 256); - } + } else + return -EINVAL; writel(adapter->current_itr, hw->hw_addr + adapter->rx_ring->itr_register); diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h index 81b15558953..f8f85eca4ae 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h @@ -189,7 +189,7 @@ enum ixgbe_ring_state_t { __IXGBE_HANG_CHECK_ARMED, __IXGBE_RX_RSC_ENABLED, __IXGBE_RX_CSUM_UDP_ZERO_ERR, - __IXGBE_RX_FCOE_BUFSZ, + __IXGBE_RX_FCOE, }; #define check_for_tx_hang(ring) \ @@ -283,7 +283,7 @@ struct ixgbe_ring_feature { #if defined(IXGBE_FCOE) && (PAGE_SIZE < 8192) static inline unsigned int ixgbe_rx_pg_order(struct ixgbe_ring *ring) { - return test_bit(__IXGBE_RX_FCOE_BUFSZ, &ring->state) ? 1 : 0; + return test_bit(__IXGBE_RX_FCOE, &ring->state) ? 1 : 0; } #else #define ixgbe_rx_pg_order(_ring) 0 diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c index ed1b47dc083..a269d11259c 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c @@ -628,7 +628,7 @@ static int ixgbe_alloc_q_vector(struct ixgbe_adapter *adapter, int v_idx, f = &adapter->ring_feature[RING_F_FCOE]; if ((rxr_idx >= f->mask) && (rxr_idx < f->mask + f->indices)) - set_bit(__IXGBE_RX_FCOE_BUFSZ, &ring->state); + set_bit(__IXGBE_RX_FCOE, &ring->state); } #endif /* IXGBE_FCOE */ diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 467948e9ecd..a66c2159b1f 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -1036,17 +1036,17 @@ static inline void ixgbe_rx_hash(struct ixgbe_ring *ring, #ifdef IXGBE_FCOE /** * ixgbe_rx_is_fcoe - check the rx desc for incoming pkt type - * @adapter: address of board private structure + * @ring: structure containing ring specific data * @rx_desc: advanced rx descriptor * * Returns : true if it is FCoE pkt */ -static inline bool ixgbe_rx_is_fcoe(struct ixgbe_adapter *adapter, +static inline bool ixgbe_rx_is_fcoe(struct ixgbe_ring *ring, union ixgbe_adv_rx_desc *rx_desc) { __le16 pkt_info = rx_desc->wb.lower.lo_dword.hs_rss.pkt_info; - return (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) && + return test_bit(__IXGBE_RX_FCOE, &ring->state) && ((pkt_info & cpu_to_le16(IXGBE_RXDADV_PKTTYPE_ETQF_MASK)) == (cpu_to_le16(IXGBE_ETQF_FILTER_FCOE << IXGBE_RXDADV_PKTTYPE_ETQF_SHIFT))); @@ -1519,6 +1519,12 @@ static bool ixgbe_cleanup_headers(struct ixgbe_ring *rx_ring, skb->truesize -= ixgbe_rx_bufsz(rx_ring); } +#ifdef IXGBE_FCOE + /* do not attempt to pad FCoE Frames as this will disrupt DDP */ + if (ixgbe_rx_is_fcoe(rx_ring, rx_desc)) + return false; + +#endif /* if skb_pad returns an error the skb was freed */ if (unlikely(skb->len < 60)) { int pad_len = 60 - skb->len; @@ -1745,7 +1751,7 @@ static bool ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector, #ifdef IXGBE_FCOE /* if ddp, not passing to ULD unless for FCP_RSP or error */ - if (ixgbe_rx_is_fcoe(adapter, rx_desc)) { + if (ixgbe_rx_is_fcoe(rx_ring, rx_desc)) { ddp_bytes = ixgbe_fcoe_ddp(adapter, rx_desc, skb); if (!ddp_bytes) { dev_kfree_skb_any(skb); diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c index 487a6c8bd4e..589753fb673 100644 --- a/drivers/net/ethernet/marvell/sky2.c +++ b/drivers/net/ethernet/marvell/sky2.c @@ -4381,10 +4381,12 @@ static int sky2_set_features(struct net_device *dev, netdev_features_t features) struct sky2_port *sky2 = netdev_priv(dev); netdev_features_t changed = dev->features ^ features; - if (changed & NETIF_F_RXCSUM) { - bool on = features & NETIF_F_RXCSUM; - sky2_write32(sky2->hw, Q_ADDR(rxqaddr[sky2->port], Q_CSR), - on ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM); + if ((changed & NETIF_F_RXCSUM) && + !(sky2->hw->flags & SKY2_HW_NEW_LE)) { + sky2_write32(sky2->hw, + Q_ADDR(rxqaddr[sky2->port], Q_CSR), + (features & NETIF_F_RXCSUM) + ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM); } if (changed & NETIF_F_RXHASH) diff --git a/drivers/net/ethernet/nxp/lpc_eth.c b/drivers/net/ethernet/nxp/lpc_eth.c index 6dfc26d85e4..0c5edc17a1e 100644 --- a/drivers/net/ethernet/nxp/lpc_eth.c +++ b/drivers/net/ethernet/nxp/lpc_eth.c @@ -936,16 +936,16 @@ static void __lpc_handle_xmit(struct net_device *ndev) /* Update stats */ ndev->stats.tx_packets++; ndev->stats.tx_bytes += skb->len; - - /* Free buffer */ - dev_kfree_skb_irq(skb); } + dev_kfree_skb_irq(skb); txcidx = readl(LPC_ENET_TXCONSUMEINDEX(pldat->net_base)); } - if (netif_queue_stopped(ndev)) - netif_wake_queue(ndev); + if (pldat->num_used_tx_buffs <= ENET_TX_DESC/2) { + if (netif_queue_stopped(ndev)) + netif_wake_queue(ndev); + } } static int __lpc_handle_recv(struct net_device *ndev, int budget) @@ -1310,6 +1310,7 @@ static const struct net_device_ops lpc_netdev_ops = { .ndo_set_rx_mode = lpc_eth_set_multicast_list, .ndo_do_ioctl = lpc_eth_ioctl, .ndo_set_mac_address = lpc_set_mac_address, + .ndo_change_mtu = eth_change_mtu, }; static int lpc_eth_drv_probe(struct platform_device *pdev) diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index ce6b44d1f25..161e0451747 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -5966,6 +5966,8 @@ static void __devexit rtl_remove_one(struct pci_dev *pdev) cancel_work_sync(&tp->wk.work); + netif_napi_del(&tp->napi); + unregister_netdev(dev); rtl_release_firmware(tp); @@ -6288,6 +6290,7 @@ rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) return rc; err_out_msi_4: + netif_napi_del(&tp->napi); rtl_disable_msi(pdev, tp); iounmap(ioaddr); err_out_free_res_3: diff --git a/drivers/net/ethernet/sun/niu.c b/drivers/net/ethernet/sun/niu.c index c99b3b0e2ea..8489d09494a 100644 --- a/drivers/net/ethernet/sun/niu.c +++ b/drivers/net/ethernet/sun/niu.c @@ -3598,7 +3598,6 @@ static int release_tx_packet(struct niu *np, struct tx_ring_info *rp, int idx) static void niu_tx_work(struct niu *np, struct tx_ring_info *rp) { struct netdev_queue *txq; - unsigned int tx_bytes; u16 pkt_cnt, tmp; int cons, index; u64 cs; @@ -3621,18 +3620,12 @@ static void niu_tx_work(struct niu *np, struct tx_ring_info *rp) netif_printk(np, tx_done, KERN_DEBUG, np->dev, "%s() pkt_cnt[%u] cons[%d]\n", __func__, pkt_cnt, cons); - tx_bytes = 0; - tmp = pkt_cnt; - while (tmp--) { - tx_bytes += rp->tx_buffs[cons].skb->len; + while (pkt_cnt--) cons = release_tx_packet(np, rp, cons); - } rp->cons = cons; smp_mb(); - netdev_tx_completed_queue(txq, pkt_cnt, tx_bytes); - out: if (unlikely(netif_tx_queue_stopped(txq) && (niu_tx_avail(rp) > NIU_TX_WAKEUP_THRESH(rp)))) { @@ -4333,7 +4326,6 @@ static void niu_free_channels(struct niu *np) struct tx_ring_info *rp = &np->tx_rings[i]; niu_free_tx_ring_info(np, rp); - netdev_tx_reset_queue(netdev_get_tx_queue(np->dev, i)); } kfree(np->tx_rings); np->tx_rings = NULL; @@ -6739,8 +6731,6 @@ static netdev_tx_t niu_start_xmit(struct sk_buff *skb, prod = NEXT_TX(rp, prod); } - netdev_tx_sent_queue(txq, skb->len); - if (prod < rp->prod) rp->wrap_bit ^= TX_RING_KICK_WRAP; rp->prod = prod; diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index cb8fd5069db..c1d602d5f15 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -528,9 +528,10 @@ static int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from, } base = (unsigned long)from->iov_base + offset1; size = ((base & ~PAGE_MASK) + len + ~PAGE_MASK) >> PAGE_SHIFT; + if (i + size > MAX_SKB_FRAGS) + return -EMSGSIZE; num_pages = get_user_pages_fast(base, size, 0, &page[i]); - if ((num_pages != size) || - (num_pages > MAX_SKB_FRAGS - skb_shinfo(skb)->nr_frags)) + if (num_pages != size) /* put_page is in skb free */ return -EFAULT; skb->data_len += len; @@ -647,7 +648,7 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, int err; struct virtio_net_hdr vnet_hdr = { 0 }; int vnet_hdr_len = 0; - int copylen; + int copylen = 0; bool zerocopy = false; if (q->flags & IFF_VNET_HDR) { @@ -676,15 +677,31 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, if (unlikely(len < ETH_HLEN)) goto err; + err = -EMSGSIZE; + if (unlikely(count > UIO_MAXIOV)) + goto err; + if (m && m->msg_control && sock_flag(&q->sk, SOCK_ZEROCOPY)) zerocopy = true; if (zerocopy) { + /* Userspace may produce vectors with count greater than + * MAX_SKB_FRAGS, so we need to linearize parts of the skb + * to let the rest of data to be fit in the frags. + */ + if (count > MAX_SKB_FRAGS) { + copylen = iov_length(iv, count - MAX_SKB_FRAGS); + if (copylen < vnet_hdr_len) + copylen = 0; + else + copylen -= vnet_hdr_len; + } /* There are 256 bytes to be copied in skb, so there is enough * room for skb expand head in case it is used. * The rest buffer is mapped from userspace. */ - copylen = vnet_hdr.hdr_len; + if (copylen < vnet_hdr.hdr_len) + copylen = vnet_hdr.hdr_len; if (!copylen) copylen = GOODCOPY_LEN; } else diff --git a/drivers/net/usb/ipheth.c b/drivers/net/usb/ipheth.c index dd78c4cbd45..5cba41517f7 100644 --- a/drivers/net/usb/ipheth.c +++ b/drivers/net/usb/ipheth.c @@ -59,6 +59,7 @@ #define USB_PRODUCT_IPHONE_3G 0x1292 #define USB_PRODUCT_IPHONE_3GS 0x1294 #define USB_PRODUCT_IPHONE_4 0x1297 +#define USB_PRODUCT_IPAD 0x129a #define USB_PRODUCT_IPHONE_4_VZW 0x129c #define USB_PRODUCT_IPHONE_4S 0x12a0 @@ -100,6 +101,10 @@ static struct usb_device_id ipheth_table[] = { USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_4, IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, IPHETH_USBINTF_PROTO) }, + { USB_DEVICE_AND_INTERFACE_INFO( + USB_VENDOR_APPLE, USB_PRODUCT_IPAD, + IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, + IPHETH_USBINTF_PROTO) }, { USB_DEVICE_AND_INTERFACE_INFO( USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_4_VZW, IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index d316503b35d..c2ae4266617 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -197,6 +197,10 @@ static int qmi_wwan_manage_power(struct usbnet *dev, int on) static int qmi_wwan_cdc_wdm_manage_power(struct usb_interface *intf, int on) { struct usbnet *dev = usb_get_intfdata(intf); + + /* can be called while disconnecting */ + if (!dev) + return 0; return qmi_wwan_manage_power(dev, on); } @@ -257,29 +261,6 @@ static int qmi_wwan_bind_shared(struct usbnet *dev, struct usb_interface *intf) return rv; } -/* Gobi devices uses identical class/protocol codes for all interfaces regardless - * of function. Some of these are CDC ACM like and have the exact same endpoints - * we are looking for. This leaves two possible strategies for identifying the - * correct interface: - * a) hardcoding interface number, or - * b) use the fact that the wwan interface is the only one lacking additional - * (CDC functional) descriptors - * - * Let's see if we can get away with the generic b) solution. - */ -static int qmi_wwan_bind_gobi(struct usbnet *dev, struct usb_interface *intf) -{ - int rv = -EINVAL; - - /* ignore any interface with additional descriptors */ - if (intf->cur_altsetting->extralen) - goto err; - - rv = qmi_wwan_bind_shared(dev, intf); -err: - return rv; -} - static void qmi_wwan_unbind_shared(struct usbnet *dev, struct usb_interface *intf) { struct usb_driver *subdriver = (void *)dev->data[0]; @@ -347,19 +328,37 @@ static const struct driver_info qmi_wwan_shared = { .manage_power = qmi_wwan_manage_power, }; -static const struct driver_info qmi_wwan_gobi = { - .description = "Qualcomm Gobi wwan/QMI device", +static const struct driver_info qmi_wwan_force_int0 = { + .description = "Qualcomm WWAN/QMI device", + .flags = FLAG_WWAN, + .bind = qmi_wwan_bind_shared, + .unbind = qmi_wwan_unbind_shared, + .manage_power = qmi_wwan_manage_power, + .data = BIT(0), /* interface whitelist bitmap */ +}; + +static const struct driver_info qmi_wwan_force_int1 = { + .description = "Qualcomm WWAN/QMI device", + .flags = FLAG_WWAN, + .bind = qmi_wwan_bind_shared, + .unbind = qmi_wwan_unbind_shared, + .manage_power = qmi_wwan_manage_power, + .data = BIT(1), /* interface whitelist bitmap */ +}; + +static const struct driver_info qmi_wwan_force_int3 = { + .description = "Qualcomm WWAN/QMI device", .flags = FLAG_WWAN, - .bind = qmi_wwan_bind_gobi, + .bind = qmi_wwan_bind_shared, .unbind = qmi_wwan_unbind_shared, .manage_power = qmi_wwan_manage_power, + .data = BIT(3), /* interface whitelist bitmap */ }; -/* ZTE suck at making USB descriptors */ static const struct driver_info qmi_wwan_force_int4 = { - .description = "Qualcomm Gobi wwan/QMI device", + .description = "Qualcomm WWAN/QMI device", .flags = FLAG_WWAN, - .bind = qmi_wwan_bind_gobi, + .bind = qmi_wwan_bind_shared, .unbind = qmi_wwan_unbind_shared, .manage_power = qmi_wwan_manage_power, .data = BIT(4), /* interface whitelist bitmap */ @@ -381,16 +380,23 @@ static const struct driver_info qmi_wwan_force_int4 = { static const struct driver_info qmi_wwan_sierra = { .description = "Sierra Wireless wwan/QMI device", .flags = FLAG_WWAN, - .bind = qmi_wwan_bind_gobi, + .bind = qmi_wwan_bind_shared, .unbind = qmi_wwan_unbind_shared, .manage_power = qmi_wwan_manage_power, .data = BIT(8) | BIT(19), /* interface whitelist bitmap */ }; #define HUAWEI_VENDOR_ID 0x12D1 + +/* Gobi 1000 QMI/wwan interface number is 3 according to qcserial */ +#define QMI_GOBI1K_DEVICE(vend, prod) \ + USB_DEVICE(vend, prod), \ + .driver_info = (unsigned long)&qmi_wwan_force_int3 + +/* Gobi 2000 and Gobi 3000 QMI/wwan interface number is 0 according to qcserial */ #define QMI_GOBI_DEVICE(vend, prod) \ USB_DEVICE(vend, prod), \ - .driver_info = (unsigned long)&qmi_wwan_gobi + .driver_info = (unsigned long)&qmi_wwan_force_int0 static const struct usb_device_id products[] = { { /* Huawei E392, E398 and possibly others sharing both device id and more... */ @@ -430,6 +436,15 @@ static const struct usb_device_id products[] = { .bInterfaceProtocol = 0xff, .driver_info = (unsigned long)&qmi_wwan_force_int4, }, + { /* ZTE (Vodafone) K3520-Z */ + .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x19d2, + .idProduct = 0x0055, + .bInterfaceClass = 0xff, + .bInterfaceSubClass = 0xff, + .bInterfaceProtocol = 0xff, + .driver_info = (unsigned long)&qmi_wwan_force_int1, + }, { /* ZTE (Vodafone) K3565-Z */ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, .idVendor = 0x19d2, @@ -475,20 +490,24 @@ static const struct usb_device_id products[] = { .bInterfaceProtocol = 0xff, .driver_info = (unsigned long)&qmi_wwan_sierra, }, - {QMI_GOBI_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */ - {QMI_GOBI_DEVICE(0x03f0, 0x1f1d)}, /* HP un2400 Gobi Modem Device */ - {QMI_GOBI_DEVICE(0x03f0, 0x371d)}, /* HP un2430 Mobile Broadband Module */ - {QMI_GOBI_DEVICE(0x04da, 0x250d)}, /* Panasonic Gobi Modem device */ - {QMI_GOBI_DEVICE(0x413c, 0x8172)}, /* Dell Gobi Modem device */ - {QMI_GOBI_DEVICE(0x1410, 0xa001)}, /* Novatel Gobi Modem device */ - {QMI_GOBI_DEVICE(0x0b05, 0x1776)}, /* Asus Gobi Modem device */ - {QMI_GOBI_DEVICE(0x19d2, 0xfff3)}, /* ONDA Gobi Modem device */ - {QMI_GOBI_DEVICE(0x05c6, 0x9001)}, /* Generic Gobi Modem device */ - {QMI_GOBI_DEVICE(0x05c6, 0x9002)}, /* Generic Gobi Modem device */ - {QMI_GOBI_DEVICE(0x05c6, 0x9202)}, /* Generic Gobi Modem device */ - {QMI_GOBI_DEVICE(0x05c6, 0x9203)}, /* Generic Gobi Modem device */ - {QMI_GOBI_DEVICE(0x05c6, 0x9222)}, /* Generic Gobi Modem device */ - {QMI_GOBI_DEVICE(0x05c6, 0x9009)}, /* Generic Gobi Modem device */ + + /* Gobi 1000 devices */ + {QMI_GOBI1K_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */ + {QMI_GOBI1K_DEVICE(0x03f0, 0x1f1d)}, /* HP un2400 Gobi Modem Device */ + {QMI_GOBI1K_DEVICE(0x03f0, 0x371d)}, /* HP un2430 Mobile Broadband Module */ + {QMI_GOBI1K_DEVICE(0x04da, 0x250d)}, /* Panasonic Gobi Modem device */ + {QMI_GOBI1K_DEVICE(0x413c, 0x8172)}, /* Dell Gobi Modem device */ + {QMI_GOBI1K_DEVICE(0x1410, 0xa001)}, /* Novatel Gobi Modem device */ + {QMI_GOBI1K_DEVICE(0x0b05, 0x1776)}, /* Asus Gobi Modem device */ + {QMI_GOBI1K_DEVICE(0x19d2, 0xfff3)}, /* ONDA Gobi Modem device */ + {QMI_GOBI1K_DEVICE(0x05c6, 0x9001)}, /* Generic Gobi Modem device */ + {QMI_GOBI1K_DEVICE(0x05c6, 0x9002)}, /* Generic Gobi Modem device */ + {QMI_GOBI1K_DEVICE(0x05c6, 0x9202)}, /* Generic Gobi Modem device */ + {QMI_GOBI1K_DEVICE(0x05c6, 0x9203)}, /* Generic Gobi Modem device */ + {QMI_GOBI1K_DEVICE(0x05c6, 0x9222)}, /* Generic Gobi Modem device */ + {QMI_GOBI1K_DEVICE(0x05c6, 0x9009)}, /* Generic Gobi Modem device */ + + /* Gobi 2000 and 3000 devices */ {QMI_GOBI_DEVICE(0x413c, 0x8186)}, /* Dell Gobi 2000 Modem device (N0218, VU936) */ {QMI_GOBI_DEVICE(0x05c6, 0x920b)}, /* Generic Gobi 2000 Modem device */ {QMI_GOBI_DEVICE(0x05c6, 0x9225)}, /* Sony Gobi 2000 Modem device (N0279, VU730) */ diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h index c54b7d37bff..420d69b2674 100644 --- a/drivers/net/wireless/ath/ath.h +++ b/drivers/net/wireless/ath/ath.h @@ -143,6 +143,7 @@ struct ath_common { u32 keymax; DECLARE_BITMAP(keymap, ATH_KEYMAX); DECLARE_BITMAP(tkip_keymap, ATH_KEYMAX); + DECLARE_BITMAP(ccmp_keymap, ATH_KEYMAX); enum ath_crypt_caps crypt_caps; unsigned int clockrate; diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 8c84049682a..4bfb44a094d 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -213,6 +213,7 @@ struct ath_frame_info { enum ath9k_key_type keytype; u8 keyix; u8 retries; + u8 rtscts_rate; }; struct ath_buf_state { diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 2b8f61c210e..abbd6effd60 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -1496,6 +1496,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, priv->num_sta_assoc_vif++ : priv->num_sta_assoc_vif--; if (priv->ah->opmode == NL80211_IFTYPE_STATION) { + ath9k_htc_choose_set_bssid(priv); if (bss_conf->assoc && (priv->num_sta_assoc_vif == 1)) ath9k_htc_start_ani(priv); else if (priv->num_sta_assoc_vif == 0) @@ -1503,13 +1504,11 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw, } } - if (changed & BSS_CHANGED_BSSID) { + if (changed & BSS_CHANGED_IBSS) { if (priv->ah->opmode == NL80211_IFTYPE_ADHOC) { common->curaid = bss_conf->aid; memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN); ath9k_htc_set_bssid(priv); - } else if (priv->ah->opmode == NL80211_IFTYPE_STATION) { - ath9k_htc_choose_set_bssid(priv); } } diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index fa84e37bf09..6dfd9644884 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -558,7 +558,7 @@ static int __ath9k_hw_init(struct ath_hw *ah) if (NR_CPUS > 1 && ah->config.serialize_regmode == SER_REG_MODE_AUTO) { if (ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCI || - ((AR_SREV_9160(ah) || AR_SREV_9280(ah)) && + ((AR_SREV_9160(ah) || AR_SREV_9280(ah) || AR_SREV_9287(ah)) && !ah->is_pciexpress)) { ah->config.serialize_regmode = SER_REG_MODE_ON; @@ -720,13 +720,25 @@ static void ath9k_hw_init_qos(struct ath_hw *ah) u32 ar9003_get_pll_sqsum_dvc(struct ath_hw *ah) { + struct ath_common *common = ath9k_hw_common(ah); + int i = 0; + REG_CLR_BIT(ah, PLL3, PLL3_DO_MEAS_MASK); udelay(100); REG_SET_BIT(ah, PLL3, PLL3_DO_MEAS_MASK); - while ((REG_READ(ah, PLL4) & PLL4_MEAS_DONE) == 0) + while ((REG_READ(ah, PLL4) & PLL4_MEAS_DONE) == 0) { + udelay(100); + if (WARN_ON_ONCE(i >= 100)) { + ath_err(common, "PLL4 meaurement not done\n"); + break; + } + + i++; + } + return (REG_READ(ah, PLL3) & SQSUM_DVC_MASK) >> 3; } EXPORT_SYMBOL(ar9003_get_pll_sqsum_dvc); diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 798ea57252b..d5dabcb61a0 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -960,6 +960,15 @@ void ath_hw_pll_work(struct work_struct *work) hw_pll_work.work); u32 pll_sqsum; + /* + * ensure that the PLL WAR is executed only + * after the STA is associated (or) if the + * beaconing had started in interfaces that + * uses beacons. + */ + if (!(sc->sc_flags & SC_OP_BEACONS)) + return; + if (AR_SREV_9485(sc->sc_ah)) { ath9k_ps_wakeup(sc); @@ -1419,15 +1428,6 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, } } - if ((ah->opmode == NL80211_IFTYPE_ADHOC) || - ((vif->type == NL80211_IFTYPE_ADHOC) && - sc->nvifs > 0)) { - ath_err(common, "Cannot create ADHOC interface when other" - " interfaces already exist.\n"); - ret = -EINVAL; - goto out; - } - ath_dbg(common, CONFIG, "Attach a VIF of type: %d\n", vif->type); sc->nvifs++; diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 1c4583c7ff7..a2f7ae81a41 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -695,9 +695,9 @@ static bool ath_edma_get_buffers(struct ath_softc *sc, __skb_unlink(skb, &rx_edma->rx_fifo); list_add_tail(&bf->list, &sc->rx.rxbuf); ath_rx_edma_buf_link(sc, qtype); - } else { - bf = NULL; } + + bf = NULL; } *dest = bf; @@ -821,7 +821,8 @@ static bool ath9k_rx_accept(struct ath_common *common, * descriptor does contain a valid key index. This has been observed * mostly with CCMP encryption. */ - if (rx_stats->rs_keyix == ATH9K_RXKEYIX_INVALID) + if (rx_stats->rs_keyix == ATH9K_RXKEYIX_INVALID || + !test_bit(rx_stats->rs_keyix, common->ccmp_keymap)) rx_stats->rs_status &= ~ATH9K_RXERR_KEYMISS; if (!rx_stats->rs_datalen) diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index d59dd01d6cd..4d571394c7a 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -938,6 +938,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, struct ieee80211_tx_rate *rates; const struct ieee80211_rate *rate; struct ieee80211_hdr *hdr; + struct ath_frame_info *fi = get_frame_info(bf->bf_mpdu); int i; u8 rix = 0; @@ -948,18 +949,7 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, /* set dur_update_en for l-sig computation except for PS-Poll frames */ info->dur_update = !ieee80211_is_pspoll(hdr->frame_control); - - /* - * We check if Short Preamble is needed for the CTS rate by - * checking the BSS's global flag. - * But for the rate series, IEEE80211_TX_RC_USE_SHORT_PREAMBLE is used. - */ - rate = ieee80211_get_rts_cts_rate(sc->hw, tx_info); - info->rtscts_rate = rate->hw_value; - - if (tx_info->control.vif && - tx_info->control.vif->bss_conf.use_short_preamble) - info->rtscts_rate |= rate->hw_value_short; + info->rtscts_rate = fi->rtscts_rate; for (i = 0; i < 4; i++) { bool is_40, is_sgi, is_sp; @@ -1001,13 +991,13 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf, } /* legacy rates */ + rate = &sc->sbands[tx_info->band].bitrates[rates[i].idx]; if ((tx_info->band == IEEE80211_BAND_2GHZ) && !(rate->flags & IEEE80211_RATE_ERP_G)) phy = WLAN_RC_PHY_CCK; else phy = WLAN_RC_PHY_OFDM; - rate = &sc->sbands[tx_info->band].bitrates[rates[i].idx]; info->rates[i].Rate = rate->hw_value; if (rate->hw_value_short) { if (rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) @@ -1776,10 +1766,22 @@ static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb, struct ieee80211_sta *sta = tx_info->control.sta; struct ieee80211_key_conf *hw_key = tx_info->control.hw_key; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + const struct ieee80211_rate *rate; struct ath_frame_info *fi = get_frame_info(skb); struct ath_node *an = NULL; enum ath9k_key_type keytype; + bool short_preamble = false; + + /* + * We check if Short Preamble is needed for the CTS rate by + * checking the BSS's global flag. + * But for the rate series, IEEE80211_TX_RC_USE_SHORT_PREAMBLE is used. + */ + if (tx_info->control.vif && + tx_info->control.vif->bss_conf.use_short_preamble) + short_preamble = true; + rate = ieee80211_get_rts_cts_rate(hw, tx_info); keytype = ath9k_cmn_get_hw_crypto_keytype(skb); if (sta) @@ -1794,6 +1796,9 @@ static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb, fi->keyix = ATH9K_TXKEYIX_INVALID; fi->keytype = keytype; fi->framelen = framelen; + fi->rtscts_rate = rate->hw_value; + if (short_preamble) + fi->rtscts_rate |= rate->hw_value_short; } u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate) diff --git a/drivers/net/wireless/ath/key.c b/drivers/net/wireless/ath/key.c index 0e81904956c..5c54aa43ca2 100644 --- a/drivers/net/wireless/ath/key.c +++ b/drivers/net/wireless/ath/key.c @@ -556,6 +556,9 @@ int ath_key_config(struct ath_common *common, return -EIO; set_bit(idx, common->keymap); + if (key->cipher == WLAN_CIPHER_SUITE_CCMP) + set_bit(idx, common->ccmp_keymap); + if (key->cipher == WLAN_CIPHER_SUITE_TKIP) { set_bit(idx + 64, common->keymap); set_bit(idx, common->tkip_keymap); @@ -582,6 +585,7 @@ void ath_key_delete(struct ath_common *common, struct ieee80211_key_conf *key) return; clear_bit(key->hw_key_idx, common->keymap); + clear_bit(key->hw_key_idx, common->ccmp_keymap); if (key->cipher != WLAN_CIPHER_SUITE_TKIP) return; diff --git a/drivers/net/wireless/ipw2x00/ipw.h b/drivers/net/wireless/ipw2x00/ipw.h new file mode 100644 index 00000000000..4007bf5ed6f --- /dev/null +++ b/drivers/net/wireless/ipw2x00/ipw.h @@ -0,0 +1,23 @@ +/* + * Intel Pro/Wireless 2100, 2200BG, 2915ABG network connection driver + * + * Copyright 2012 Stanislav Yakovlev + * + * 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 __IPW_H__ +#define __IPW_H__ + +#include + +static const u32 ipw_cipher_suites[] = { + WLAN_CIPHER_SUITE_WEP40, + WLAN_CIPHER_SUITE_WEP104, + WLAN_CIPHER_SUITE_TKIP, + WLAN_CIPHER_SUITE_CCMP, +}; + +#endif diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c index f0551f807f6..7c8e8b11054 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.c @@ -166,6 +166,7 @@ that only one external action is invoked at a time. #include #include "ipw2100.h" +#include "ipw.h" #define IPW2100_VERSION "git-1.2.2" @@ -1946,6 +1947,9 @@ static int ipw2100_wdev_init(struct net_device *dev) wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = bg_band; } + wdev->wiphy->cipher_suites = ipw_cipher_suites; + wdev->wiphy->n_cipher_suites = ARRAY_SIZE(ipw_cipher_suites); + set_wiphy_dev(wdev->wiphy, &priv->pci_dev->dev); if (wiphy_register(wdev->wiphy)) { ipw2100_down(priv); diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index 1779db3aa2b..3a6b991f023 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c @@ -34,6 +34,7 @@ #include #include #include "ipw2200.h" +#include "ipw.h" #ifndef KBUILD_EXTMOD @@ -11544,6 +11545,9 @@ static int ipw_wdev_init(struct net_device *dev) wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = a_band; } + wdev->wiphy->cipher_suites = ipw_cipher_suites; + wdev->wiphy->n_cipher_suites = ARRAY_SIZE(ipw_cipher_suites); + set_wiphy_dev(wdev->wiphy, &priv->pci_dev->dev); /* With that information in place, we can now register the wiphy... */ diff --git a/drivers/net/wireless/iwlwifi/iwl-mac80211.c b/drivers/net/wireless/iwlwifi/iwl-mac80211.c index 1018f9b8b41..e0e6c6745d1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-mac80211.c +++ b/drivers/net/wireless/iwlwifi/iwl-mac80211.c @@ -788,6 +788,18 @@ static int iwlagn_mac_sta_state(struct ieee80211_hw *hw, switch (op) { case ADD: ret = iwlagn_mac_sta_add(hw, vif, sta); + if (ret) + break; + /* + * Clear the in-progress flag, the AP station entry was added + * but we'll initialize LQ only when we've associated (which + * would also clear the in-progress flag). This is necessary + * in case we never initialize LQ because association fails. + */ + spin_lock_bh(&priv->sta_lock); + priv->stations[iwl_sta_id(sta)].used &= + ~IWL_STA_UCODE_INPROGRESS; + spin_unlock_bh(&priv->sta_lock); break; case REMOVE: ret = iwlagn_mac_sta_remove(hw, vif, sta); diff --git a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c index 6eac984b2d0..8741048eb85 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c +++ b/drivers/net/wireless/iwlwifi/iwl-trans-pcie.c @@ -2000,6 +2000,7 @@ static ssize_t iwl_dbgfs_rx_queue_read(struct file *file, return simple_read_from_buffer(user_buf, count, ppos, buf, pos); } +#ifdef CONFIG_IWLWIFI_DEBUG static ssize_t iwl_dbgfs_log_event_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) @@ -2037,6 +2038,7 @@ static ssize_t iwl_dbgfs_log_event_write(struct file *file, return count; } +#endif static ssize_t iwl_dbgfs_interrupt_read(struct file *file, char __user *user_buf, @@ -2164,7 +2166,9 @@ static ssize_t iwl_dbgfs_fh_reg_read(struct file *file, return ret; } +#ifdef CONFIG_IWLWIFI_DEBUG DEBUGFS_READ_WRITE_FILE_OPS(log_event); +#endif DEBUGFS_READ_WRITE_FILE_OPS(interrupt); DEBUGFS_READ_FILE_OPS(fh_reg); DEBUGFS_READ_FILE_OPS(rx_queue); @@ -2180,7 +2184,9 @@ static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans, { DEBUGFS_ADD_FILE(rx_queue, dir, S_IRUSR); DEBUGFS_ADD_FILE(tx_queue, dir, S_IRUSR); +#ifdef CONFIG_IWLWIFI_DEBUG DEBUGFS_ADD_FILE(log_event, dir, S_IWUSR | S_IRUSR); +#endif DEBUGFS_ADD_FILE(interrupt, dir, S_IWUSR | S_IRUSR); DEBUGFS_ADD_FILE(csr, dir, S_IWUSR); DEBUGFS_ADD_FILE(fh_reg, dir, S_IRUSR); diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.c b/drivers/net/wireless/mwifiex/11n_rxreorder.c index 9c44088054d..900ee129e82 100644 --- a/drivers/net/wireless/mwifiex/11n_rxreorder.c +++ b/drivers/net/wireless/mwifiex/11n_rxreorder.c @@ -256,7 +256,8 @@ mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta, else last_seq = priv->rx_seq[tid]; - if (last_seq >= new_node->start_win) + if (last_seq != MWIFIEX_DEF_11N_RX_SEQ_NUM && + last_seq >= new_node->start_win) new_node->start_win = last_seq + 1; new_node->win_size = win_size; @@ -596,5 +597,5 @@ void mwifiex_11n_cleanup_reorder_tbl(struct mwifiex_private *priv) spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags); INIT_LIST_HEAD(&priv->rx_reorder_tbl_ptr); - memset(priv->rx_seq, 0, sizeof(priv->rx_seq)); + mwifiex_reset_11n_rx_seq_num(priv); } diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.h b/drivers/net/wireless/mwifiex/11n_rxreorder.h index f1bffebabc6..6c9815a0f5d 100644 --- a/drivers/net/wireless/mwifiex/11n_rxreorder.h +++ b/drivers/net/wireless/mwifiex/11n_rxreorder.h @@ -37,6 +37,13 @@ #define ADDBA_RSP_STATUS_ACCEPT 0 +#define MWIFIEX_DEF_11N_RX_SEQ_NUM 0xffff + +static inline void mwifiex_reset_11n_rx_seq_num(struct mwifiex_private *priv) +{ + memset(priv->rx_seq, 0xff, sizeof(priv->rx_seq)); +} + int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *, u16 seqNum, u16 tid, u8 *ta, diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 65050384c42..baf691949c3 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -1214,11 +1214,11 @@ struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy, void *mdev_priv; if (!priv) - return NULL; + return ERR_PTR(-EFAULT); adapter = priv->adapter; if (!adapter) - return NULL; + return ERR_PTR(-EFAULT); switch (type) { case NL80211_IFTYPE_UNSPECIFIED: @@ -1227,7 +1227,7 @@ struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy, if (priv->bss_mode) { wiphy_err(wiphy, "cannot create multiple" " station/adhoc interfaces\n"); - return NULL; + return ERR_PTR(-EINVAL); } if (type == NL80211_IFTYPE_UNSPECIFIED) @@ -1244,14 +1244,15 @@ struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy, break; default: wiphy_err(wiphy, "type not supported\n"); - return NULL; + return ERR_PTR(-EINVAL); } dev = alloc_netdev_mq(sizeof(struct mwifiex_private *), name, ether_setup, 1); if (!dev) { wiphy_err(wiphy, "no memory available for netdevice\n"); - goto error; + priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED; + return ERR_PTR(-ENOMEM); } dev_net_set(dev, wiphy_net(wiphy)); @@ -1276,7 +1277,9 @@ struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy, /* Register network device */ if (register_netdevice(dev)) { wiphy_err(wiphy, "cannot register virtual network device\n"); - goto error; + free_netdev(dev); + priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED; + return ERR_PTR(-EFAULT); } sema_init(&priv->async_sem, 1); @@ -1288,12 +1291,6 @@ struct net_device *mwifiex_add_virtual_intf(struct wiphy *wiphy, mwifiex_dev_debugfs_init(priv); #endif return dev; -error: - if (dev && (dev->reg_state == NETREG_UNREGISTERED)) - free_netdev(dev); - priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED; - - return NULL; } EXPORT_SYMBOL_GPL(mwifiex_add_virtual_intf); diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c index 5a7316c6f12..3e6abf018b5 100644 --- a/drivers/net/wireless/mwifiex/wmm.c +++ b/drivers/net/wireless/mwifiex/wmm.c @@ -404,6 +404,8 @@ mwifiex_wmm_init(struct mwifiex_adapter *adapter) priv->add_ba_param.tx_win_size = MWIFIEX_AMPDU_DEF_TXWINSIZE; priv->add_ba_param.rx_win_size = MWIFIEX_AMPDU_DEF_RXWINSIZE; + mwifiex_reset_11n_rx_seq_num(priv); + atomic_set(&priv->wmm.tx_pkts_queued, 0); atomic_set(&priv->wmm.highest_queued_prio, HIGH_PRIO_TID); } @@ -1209,6 +1211,7 @@ mwifiex_dequeue_tx_packet(struct mwifiex_adapter *adapter) if (!ptr->is_11n_enabled || mwifiex_is_ba_stream_setup(priv, ptr, tid) || + priv->wps.session_enable || ((priv->sec_info.wpa_enabled || priv->sec_info.wpa2_enabled) && !priv->wpa_is_gtk_set)) { diff --git a/drivers/net/wireless/rtl818x/rtl8187/leds.c b/drivers/net/wireless/rtl818x/rtl8187/leds.c index 2e0de2f5f0f..c2d5b495c17 100644 --- a/drivers/net/wireless/rtl818x/rtl8187/leds.c +++ b/drivers/net/wireless/rtl818x/rtl8187/leds.c @@ -117,7 +117,7 @@ static void rtl8187_led_brightness_set(struct led_classdev *led_dev, radio_on = true; } else if (radio_on) { radio_on = false; - cancel_delayed_work_sync(&priv->led_on); + cancel_delayed_work(&priv->led_on); ieee80211_queue_delayed_work(hw, &priv->led_off, 0); } } else if (radio_on) { diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c index 82c85286ab2..5bd40856635 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c @@ -301,9 +301,11 @@ 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(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*/ {RTL_USB_DEVICE(0x0eb0, 0x9071, rtl92cu_hal_cfg)}, /*NO Brand - Etop*/ + {RTL_USB_DEVICE(0x4856, 0x0091, rtl92cu_hal_cfg)}, /*NetweeN - Feixun*/ /* HP - Lite-On ,8188CUS Slim Combo */ {RTL_USB_DEVICE(0x103c, 0x1629, rtl92cu_hal_cfg)}, {RTL_USB_DEVICE(0x13d3, 0x3357, rtl92cu_hal_cfg)}, /* AzureWave */ @@ -345,6 +347,7 @@ static struct usb_device_id rtl8192c_usb_ids[] = { {RTL_USB_DEVICE(0x07b8, 0x8178, rtl92cu_hal_cfg)}, /*Funai -Abocom*/ {RTL_USB_DEVICE(0x0846, 0x9021, rtl92cu_hal_cfg)}, /*Netgear-Sercomm*/ {RTL_USB_DEVICE(0x0b05, 0x17ab, rtl92cu_hal_cfg)}, /*ASUS-Edimax*/ + {RTL_USB_DEVICE(0x0bda, 0x8186, rtl92cu_hal_cfg)}, /*Realtek 92CE-VAU*/ {RTL_USB_DEVICE(0x0df6, 0x0061, rtl92cu_hal_cfg)}, /*Sitecom-Edimax*/ {RTL_USB_DEVICE(0x0e66, 0x0019, rtl92cu_hal_cfg)}, /*Hawking-Edimax*/ {RTL_USB_DEVICE(0x2001, 0x3307, rtl92cu_hal_cfg)}, /*D-Link-Cameo*/ diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index 0ebbb1906c3..796afbf13eb 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -1935,14 +1935,14 @@ static int __devexit xennet_remove(struct xenbus_device *dev) dev_dbg(&dev->dev, "%s\n", dev->nodename); - unregister_netdev(info->netdev); - xennet_disconnect_backend(info); - del_timer_sync(&info->rx_refill_timer); - xennet_sysfs_delif(info->netdev); + unregister_netdev(info->netdev); + + del_timer_sync(&info->rx_refill_timer); + free_percpu(info->stats); free_netdev(info->netdev); diff --git a/drivers/oprofile/oprofile_perf.c b/drivers/oprofile/oprofile_perf.c index da14432806c..efc4b7f308c 100644 --- a/drivers/oprofile/oprofile_perf.c +++ b/drivers/oprofile/oprofile_perf.c @@ -25,7 +25,7 @@ static int oprofile_perf_enabled; static DEFINE_MUTEX(oprofile_perf_mutex); static struct op_counter_config *counter_config; -static struct perf_event **perf_events[nr_cpumask_bits]; +static struct perf_event **perf_events[NR_CPUS]; static int num_counters; /* diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 9a18a97e0f8..9c1d37bd65f 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -725,6 +725,18 @@ static int pci_pm_suspend_noirq(struct device *dev) pci_pm_set_unknown_state(pci_dev); + /* + * Some BIOSes from ASUS have a bug: If a USB EHCI host controller's + * PCI COMMAND register isn't 0, the BIOS assumes that the controller + * hasn't been quiesced and tries to turn it off. If the controller + * is already in D3, this can hang or cause memory corruption. + * + * Since the value of the COMMAND register doesn't matter once the + * device has been suspended, we can safely set it to 0 here. + */ + if (pci_dev->class == PCI_CLASS_SERIAL_USB_EHCI) + pci_write_config_word(pci_dev, PCI_COMMAND, 0); + return 0; } diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index f597a1aa5e6..111569ccab4 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1743,11 +1743,6 @@ int pci_prepare_to_sleep(struct pci_dev *dev) if (target_state == PCI_POWER_ERROR) return -EIO; - /* Some devices mustn't be in D3 during system sleep */ - if (target_state == PCI_D3hot && - (dev->dev_flags & PCI_DEV_FLAGS_NO_D3_DURING_SLEEP)) - return 0; - pci_enable_wake(dev, target_state, device_may_wakeup(&dev->dev)); error = pci_set_power_state(dev, target_state); diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index bf33f0b7f95..4bf71028556 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -2917,32 +2917,6 @@ static void __devinit disable_igfx_irq(struct pci_dev *dev) DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0102, disable_igfx_irq); DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x010a, disable_igfx_irq); -/* - * The Intel 6 Series/C200 Series chipset's EHCI controllers on many - * ASUS motherboards will cause memory corruption or a system crash - * if they are in D3 while the system is put into S3 sleep. - */ -static void __devinit asus_ehci_no_d3(struct pci_dev *dev) -{ - const char *sys_info; - static const char good_Asus_board[] = "P8Z68-V"; - - if (dev->dev_flags & PCI_DEV_FLAGS_NO_D3_DURING_SLEEP) - return; - if (dev->subsystem_vendor != PCI_VENDOR_ID_ASUSTEK) - return; - sys_info = dmi_get_system_info(DMI_BOARD_NAME); - if (sys_info && memcmp(sys_info, good_Asus_board, - sizeof(good_Asus_board) - 1) == 0) - return; - - dev_info(&dev->dev, "broken D3 during system sleep on ASUS\n"); - dev->dev_flags |= PCI_DEV_FLAGS_NO_D3_DURING_SLEEP; - device_set_wakeup_capable(&dev->dev, false); -} -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1c26, asus_ehci_no_d3); -DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1c2d, asus_ehci_no_d3); - static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_fixup *end) { diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig index 24d880e78ec..f8d818abf98 100644 --- a/drivers/remoteproc/Kconfig +++ b/drivers/remoteproc/Kconfig @@ -4,9 +4,11 @@ menu "Remoteproc drivers (EXPERIMENTAL)" config REMOTEPROC tristate depends on EXPERIMENTAL + select FW_CONFIG config OMAP_REMOTEPROC tristate "OMAP remoteproc support" + depends on EXPERIMENTAL depends on ARCH_OMAP4 depends on OMAP_IOMMU select REMOTEPROC diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c index 75506ec2840..39d3aa41add 100644 --- a/drivers/rpmsg/virtio_rpmsg_bus.c +++ b/drivers/rpmsg/virtio_rpmsg_bus.c @@ -188,6 +188,26 @@ static int rpmsg_uevent(struct device *dev, struct kobj_uevent_env *env) rpdev->id.name); } +/** + * __ept_release() - deallocate an rpmsg endpoint + * @kref: the ept's reference count + * + * This function deallocates an ept, and is invoked when its @kref refcount + * drops to zero. + * + * Never invoke this function directly! + */ +static void __ept_release(struct kref *kref) +{ + struct rpmsg_endpoint *ept = container_of(kref, struct rpmsg_endpoint, + refcount); + /* + * At this point no one holds a reference to ept anymore, + * so we can directly free it + */ + kfree(ept); +} + /* for more info, see below documentation of rpmsg_create_ept() */ static struct rpmsg_endpoint *__rpmsg_create_ept(struct virtproc_info *vrp, struct rpmsg_channel *rpdev, rpmsg_rx_cb_t cb, @@ -206,6 +226,9 @@ static struct rpmsg_endpoint *__rpmsg_create_ept(struct virtproc_info *vrp, return NULL; } + kref_init(&ept->refcount); + mutex_init(&ept->cb_lock); + ept->rpdev = rpdev; ept->cb = cb; ept->priv = priv; @@ -238,7 +261,7 @@ static struct rpmsg_endpoint *__rpmsg_create_ept(struct virtproc_info *vrp, idr_remove(&vrp->endpoints, request); free_ept: mutex_unlock(&vrp->endpoints_lock); - kfree(ept); + kref_put(&ept->refcount, __ept_release); return NULL; } @@ -302,11 +325,17 @@ EXPORT_SYMBOL(rpmsg_create_ept); static void __rpmsg_destroy_ept(struct virtproc_info *vrp, struct rpmsg_endpoint *ept) { + /* make sure new inbound messages can't find this ept anymore */ mutex_lock(&vrp->endpoints_lock); idr_remove(&vrp->endpoints, ept->addr); mutex_unlock(&vrp->endpoints_lock); - kfree(ept); + /* make sure in-flight inbound messages won't invoke cb anymore */ + mutex_lock(&ept->cb_lock); + ept->cb = NULL; + mutex_unlock(&ept->cb_lock); + + kref_put(&ept->refcount, __ept_release); } /** @@ -790,12 +819,28 @@ static void rpmsg_recv_done(struct virtqueue *rvq) /* use the dst addr to fetch the callback of the appropriate user */ mutex_lock(&vrp->endpoints_lock); + ept = idr_find(&vrp->endpoints, msg->dst); + + /* let's make sure no one deallocates ept while we use it */ + if (ept) + kref_get(&ept->refcount); + mutex_unlock(&vrp->endpoints_lock); - if (ept && ept->cb) - ept->cb(ept->rpdev, msg->data, msg->len, ept->priv, msg->src); - else + if (ept) { + /* make sure ept->cb doesn't go away while we use it */ + mutex_lock(&ept->cb_lock); + + if (ept->cb) + ept->cb(ept->rpdev, msg->data, msg->len, ept->priv, + msg->src); + + mutex_unlock(&ept->cb_lock); + + /* farewell, ept, we don't need you anymore */ + kref_put(&ept->refcount, __ept_release); + } else dev_warn(dev, "msg received with no recepient\n"); /* publish the real size of the buffer */ diff --git a/drivers/rtc/rtc-ab8500.c b/drivers/rtc/rtc-ab8500.c index 4bcf9ca2818..b11a2ecef3f 100644 --- a/drivers/rtc/rtc-ab8500.c +++ b/drivers/rtc/rtc-ab8500.c @@ -422,7 +422,7 @@ static int __devinit ab8500_rtc_probe(struct platform_device *pdev) } err = request_threaded_irq(irq, NULL, rtc_alarm_handler, - IRQF_NO_SUSPEND, "ab8500-rtc", rtc); + IRQF_NO_SUSPEND | IRQF_ONESHOT, "ab8500-rtc", rtc); if (err < 0) { rtc_device_unregister(rtc); return err; diff --git a/drivers/rtc/rtc-mxc.c b/drivers/rtc/rtc-mxc.c index 5e1d64ee522..e3e50d69baf 100644 --- a/drivers/rtc/rtc-mxc.c +++ b/drivers/rtc/rtc-mxc.c @@ -202,10 +202,11 @@ static irqreturn_t mxc_rtc_interrupt(int irq, void *dev_id) struct platform_device *pdev = dev_id; struct rtc_plat_data *pdata = platform_get_drvdata(pdev); void __iomem *ioaddr = pdata->ioaddr; + unsigned long flags; u32 status; u32 events = 0; - spin_lock_irq(&pdata->rtc->irq_lock); + spin_lock_irqsave(&pdata->rtc->irq_lock, flags); status = readw(ioaddr + RTC_RTCISR) & readw(ioaddr + RTC_RTCIENR); /* clear interrupt sources */ writew(status, ioaddr + RTC_RTCISR); @@ -224,7 +225,7 @@ static irqreturn_t mxc_rtc_interrupt(int irq, void *dev_id) events |= (RTC_PF | RTC_IRQF); rtc_update_irq(pdata->rtc, 1, events); - spin_unlock_irq(&pdata->rtc->irq_lock); + spin_unlock_irqrestore(&pdata->rtc->irq_lock, flags); return IRQ_HANDLED; } diff --git a/drivers/rtc/rtc-spear.c b/drivers/rtc/rtc-spear.c index e38da0dc418..235b0efaa34 100644 --- a/drivers/rtc/rtc-spear.c +++ b/drivers/rtc/rtc-spear.c @@ -457,12 +457,12 @@ static int __devexit spear_rtc_remove(struct platform_device *pdev) clk_disable(config->clk); clk_put(config->clk); iounmap(config->ioaddr); - kfree(config); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (res) release_mem_region(res->start, resource_size(res)); platform_set_drvdata(pdev, NULL); rtc_device_unregister(config->rtc); + kfree(config); return 0; } diff --git a/drivers/scsi/aic94xx/aic94xx_task.c b/drivers/scsi/aic94xx/aic94xx_task.c index 532d212b6b2..393e7ce8e95 100644 --- a/drivers/scsi/aic94xx/aic94xx_task.c +++ b/drivers/scsi/aic94xx/aic94xx_task.c @@ -201,7 +201,7 @@ static void asd_get_response_tasklet(struct asd_ascb *ascb, if (SAS_STATUS_BUF_SIZE >= sizeof(*resp)) { resp->frame_len = le16_to_cpu(*(__le16 *)(r+6)); - memcpy(&resp->ending_fis[0], r+16, 24); + memcpy(&resp->ending_fis[0], r+16, ATA_RESP_FIS_SIZE); ts->buf_valid_size = sizeof(*resp); } } diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c index 441d88ad99a..d109cc3a17b 100644 --- a/drivers/scsi/libsas/sas_ata.c +++ b/drivers/scsi/libsas/sas_ata.c @@ -139,12 +139,12 @@ static void sas_ata_task_done(struct sas_task *task) if (stat->stat == SAS_PROTO_RESPONSE || stat->stat == SAM_STAT_GOOD || ((stat->stat == SAM_STAT_CHECK_CONDITION && dev->sata_dev.command_set == ATAPI_COMMAND_SET))) { - ata_tf_from_fis(resp->ending_fis, &dev->sata_dev.tf); + memcpy(dev->sata_dev.fis, resp->ending_fis, ATA_RESP_FIS_SIZE); if (!link->sactive) { - qc->err_mask |= ac_err_mask(dev->sata_dev.tf.command); + qc->err_mask |= ac_err_mask(dev->sata_dev.fis[2]); } else { - link->eh_info.err_mask |= ac_err_mask(dev->sata_dev.tf.command); + link->eh_info.err_mask |= ac_err_mask(dev->sata_dev.fis[2]); if (unlikely(link->eh_info.err_mask)) qc->flags |= ATA_QCFLAG_FAILED; } @@ -161,8 +161,8 @@ static void sas_ata_task_done(struct sas_task *task) qc->flags |= ATA_QCFLAG_FAILED; } - dev->sata_dev.tf.feature = 0x04; /* status err */ - dev->sata_dev.tf.command = ATA_ERR; + dev->sata_dev.fis[3] = 0x04; /* status err */ + dev->sata_dev.fis[2] = ATA_ERR; } } @@ -269,7 +269,7 @@ static bool sas_ata_qc_fill_rtf(struct ata_queued_cmd *qc) { struct domain_device *dev = qc->ap->private_data; - memcpy(&qc->result_tf, &dev->sata_dev.tf, sizeof(qc->result_tf)); + ata_tf_from_fis(dev->sata_dev.fis, &qc->result_tf); return true; } diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 5ba5c2a9e8e..a239382b2bd 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1898,6 +1898,8 @@ static int sd_try_rc16_first(struct scsi_device *sdp) { if (sdp->host->max_cmd_len < 16) return 0; + if (sdp->try_rc_10_first) + return 0; if (sdp->scsi_level > SCSI_SPC_2) return 1; if (scsi_device_protection(sdp)) diff --git a/drivers/staging/iio/adc/ad7606_core.c b/drivers/staging/iio/adc/ad7606_core.c index 97e8d3d4471..7322c168be4 100644 --- a/drivers/staging/iio/adc/ad7606_core.c +++ b/drivers/staging/iio/adc/ad7606_core.c @@ -235,6 +235,7 @@ static const struct attribute_group ad7606_attribute_group_range = { .indexed = 1, \ .channel = num, \ .address = num, \ + .info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT, \ .scan_index = num, \ .scan_type = IIO_ST('s', 16, 16, 0), \ } diff --git a/drivers/staging/rtl8712/usb_intf.c b/drivers/staging/rtl8712/usb_intf.c index e419b4fd82b..2c80745a446 100644 --- a/drivers/staging/rtl8712/usb_intf.c +++ b/drivers/staging/rtl8712/usb_intf.c @@ -102,6 +102,8 @@ static struct usb_device_id rtl871x_usb_id_tbl[] = { /* - */ {USB_DEVICE(0x20F4, 0x646B)}, {USB_DEVICE(0x083A, 0xC512)}, + {USB_DEVICE(0x25D4, 0x4CA1)}, + {USB_DEVICE(0x25D4, 0x4CAB)}, /* RTL8191SU */ /* Realtek */ diff --git a/drivers/target/tcm_fc/tfc_sess.c b/drivers/target/tcm_fc/tfc_sess.c index cb99da92006..87901fa74dd 100644 --- a/drivers/target/tcm_fc/tfc_sess.c +++ b/drivers/target/tcm_fc/tfc_sess.c @@ -58,7 +58,8 @@ static struct ft_tport *ft_tport_create(struct fc_lport *lport) struct ft_tport *tport; int i; - tport = rcu_dereference(lport->prov[FC_TYPE_FCP]); + tport = rcu_dereference_protected(lport->prov[FC_TYPE_FCP], + lockdep_is_held(&ft_lport_lock)); if (tport && tport->tpg) return tport; diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 83d14bfc2b2..01d247e8808 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -497,6 +497,8 @@ static ssize_t wdm_read goto retry; } if (!desc->reslength) { /* zero length read */ + dev_dbg(&desc->intf->dev, "%s: zero length - clearing WDM_READ\n", __func__); + clear_bit(WDM_READ, &desc->flags); spin_unlock_irq(&desc->iuspin); goto retry; } diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 249041346d7..67eae2c943a 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2198,12 +2198,16 @@ static unsigned hub_is_wusb(struct usb_hub *hub) static int hub_port_reset(struct usb_hub *hub, int port1, struct usb_device *udev, unsigned int delay, bool warm); -/* Is a USB 3.0 port in the Inactive state? */ -static bool hub_port_inactive(struct usb_hub *hub, u16 portstatus) +/* Is a USB 3.0 port in the Inactive or Complinance Mode state? + * Port worm reset is required to recover + */ +static bool hub_port_warm_reset_required(struct usb_hub *hub, u16 portstatus) { return hub_is_superspeed(hub->hdev) && - (portstatus & USB_PORT_STAT_LINK_STATE) == - USB_SS_PORT_LS_SS_INACTIVE; + (((portstatus & USB_PORT_STAT_LINK_STATE) == + USB_SS_PORT_LS_SS_INACTIVE) || + ((portstatus & USB_PORT_STAT_LINK_STATE) == + USB_SS_PORT_LS_COMP_MOD)) ; } static int hub_port_wait_reset(struct usb_hub *hub, int port1, @@ -2239,7 +2243,7 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1, * * See https://bugzilla.kernel.org/show_bug.cgi?id=41752 */ - if (hub_port_inactive(hub, portstatus)) { + if (hub_port_warm_reset_required(hub, portstatus)) { int ret; if ((portchange & USB_PORT_STAT_C_CONNECTION)) @@ -4084,9 +4088,7 @@ static void hub_events(void) /* Warm reset a USB3 protocol port if it's in * SS.Inactive state. */ - if (hub_is_superspeed(hub->hdev) && - (portstatus & USB_PORT_STAT_LINK_STATE) - == USB_SS_PORT_LS_SS_INACTIVE) { + if (hub_port_warm_reset_required(hub, portstatus)) { dev_dbg(hub_dev, "warm reset port %d\n", i); hub_port_reset(hub, i, NULL, HUB_BH_RESET_TIME, true); diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 68a0523b635..f97ab9f9452 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -472,6 +472,42 @@ void xhci_test_and_clear_bit(struct xhci_hcd *xhci, __le32 __iomem **port_array, } } +/* Updates Link Status for super Speed port */ +static void xhci_hub_report_link_state(u32 *status, u32 status_reg) +{ + u32 pls = status_reg & PORT_PLS_MASK; + + /* resume state is a xHCI internal state. + * Do not report it to usb core. + */ + if (pls == XDEV_RESUME) + return; + + /* When the CAS bit is set then warm reset + * should be performed on port + */ + if (status_reg & PORT_CAS) { + /* The CAS bit can be set while the port is + * in any link state. + * Only roothubs have CAS bit, so we + * pretend to be in compliance mode + * unless we're already in compliance + * or the inactive state. + */ + if (pls != USB_SS_PORT_LS_COMP_MOD && + pls != USB_SS_PORT_LS_SS_INACTIVE) { + pls = USB_SS_PORT_LS_COMP_MOD; + } + /* Return also connection bit - + * hub state machine resets port + * when this bit is set. + */ + pls |= USB_PORT_STAT_CONNECTION; + } + /* update status field */ + *status |= pls; +} + int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength) { @@ -615,13 +651,9 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, else status |= USB_PORT_STAT_POWER; } - /* Port Link State */ + /* Update Port Link State for super speed ports*/ if (hcd->speed == HCD_USB3) { - /* resume state is a xHCI internal state. - * Do not report it to usb core. - */ - if ((temp & PORT_PLS_MASK) != XDEV_RESUME) - status |= (temp & PORT_PLS_MASK); + xhci_hub_report_link_state(&status, temp); } if (bus_state->port_c_suspend & (1 << wIndex)) status |= 1 << USB_PORT_FEAT_C_SUSPEND; diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index b15d80052f0..03fd3965e9f 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -341,7 +341,11 @@ struct xhci_op_regs { #define PORT_PLC (1 << 22) /* port configure error change - port failed to configure its link partner */ #define PORT_CEC (1 << 23) -/* bit 24 reserved */ +/* Cold Attach Status - xHC can set this bit to report device attached during + * Sx state. Warm port reset should be perfomed to clear this bit and move port + * to connected state. + */ +#define PORT_CAS (1 << 24) /* wake on connect (enable) */ #define PORT_WKCONN_E (1 << 25) /* wake on disconnect (enable) */ diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 95de9c08da1..53e7e692d61 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -93,6 +93,7 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x10C4, 0x814B) }, /* West Mountain Radio RIGtalk */ { USB_DEVICE(0x10C4, 0x8156) }, /* B&G H3000 link cable */ { USB_DEVICE(0x10C4, 0x815E) }, /* Helicomm IP-Link 1220-DVM */ + { USB_DEVICE(0x10C4, 0x815F) }, /* Timewave HamLinkUSB */ { USB_DEVICE(0x10C4, 0x818B) }, /* AVIT Research USB to TTL */ { USB_DEVICE(0x10C4, 0x819F) }, /* MJS USB Toslink Switcher */ { USB_DEVICE(0x10C4, 0x81A6) }, /* ThinkOptics WavIt */ @@ -134,7 +135,13 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x10CE, 0xEA6A) }, /* Silicon Labs MobiData GPRS USB Modem 100EU */ { USB_DEVICE(0x13AD, 0x9999) }, /* Baltech card reader */ { USB_DEVICE(0x1555, 0x0004) }, /* Owen AC4 USB-RS485 Converter */ + { USB_DEVICE(0x166A, 0x0201) }, /* Clipsal 5500PACA C-Bus Pascal Automation Controller */ + { USB_DEVICE(0x166A, 0x0301) }, /* Clipsal 5800PC C-Bus Wireless PC Interface */ { USB_DEVICE(0x166A, 0x0303) }, /* Clipsal 5500PCU C-Bus USB interface */ + { USB_DEVICE(0x166A, 0x0304) }, /* Clipsal 5000CT2 C-Bus Black and White Touchscreen */ + { USB_DEVICE(0x166A, 0x0305) }, /* Clipsal C-5000CT2 C-Bus Spectrum Colour Touchscreen */ + { USB_DEVICE(0x166A, 0x0401) }, /* Clipsal L51xx C-Bus Architectural Dimmer */ + { USB_DEVICE(0x166A, 0x0101) }, /* Clipsal 5560884 C-Bus Multi-room Audio Matrix Switcher */ { USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */ { USB_DEVICE(0x16DC, 0x0010) }, /* W-IE-NE-R Plein & Baus GmbH PL512 Power Supply */ { USB_DEVICE(0x16DC, 0x0011) }, /* W-IE-NE-R Plein & Baus GmbH RCM Remote Control for MARATON Power Supply */ @@ -146,7 +153,11 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */ { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */ { USB_DEVICE(0x1BE3, 0x07A6) }, /* WAGO 750-923 USB Service Cable */ + { USB_DEVICE(0x1E29, 0x0102) }, /* Festo CPX-USB */ + { USB_DEVICE(0x1E29, 0x0501) }, /* Festo CMSP */ { USB_DEVICE(0x3195, 0xF190) }, /* Link Instruments MSO-19 */ + { USB_DEVICE(0x3195, 0xF280) }, /* Link Instruments MSO-28 */ + { USB_DEVICE(0x3195, 0xF281) }, /* Link Instruments MSO-28 */ { USB_DEVICE(0x413C, 0x9500) }, /* DW700 GPS USB interface */ { } /* Terminating Entry */ }; diff --git a/drivers/usb/serial/metro-usb.c b/drivers/usb/serial/metro-usb.c index 08d16e8c002..7c14671d6bd 100644 --- a/drivers/usb/serial/metro-usb.c +++ b/drivers/usb/serial/metro-usb.c @@ -171,14 +171,6 @@ static int metrousb_open(struct tty_struct *tty, struct usb_serial_port *port) metro_priv->throttled = 0; spin_unlock_irqrestore(&metro_priv->lock, flags); - /* - * Force low_latency on so that our tty_push actually forces the data - * through, otherwise it is scheduled, and with high data rates (like - * with OHCI) data can get lost. - */ - if (tty) - tty->low_latency = 1; - /* Clear the urb pipe. */ usb_clear_halt(serial->dev, port->interrupt_in_urb->pipe); diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 2706d8acb94..49484b39cc0 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -236,6 +236,7 @@ static void option_instat_callback(struct urb *urb); #define NOVATELWIRELESS_PRODUCT_G1 0xA001 #define NOVATELWIRELESS_PRODUCT_G1_M 0xA002 #define NOVATELWIRELESS_PRODUCT_G2 0xA010 +#define NOVATELWIRELESS_PRODUCT_MC551 0xB001 /* AMOI PRODUCTS */ #define AMOI_VENDOR_ID 0x1614 @@ -496,6 +497,19 @@ static void option_instat_callback(struct urb *urb); /* MediaTek products */ #define MEDIATEK_VENDOR_ID 0x0e8d +#define MEDIATEK_PRODUCT_DC_1COM 0x00a0 +#define MEDIATEK_PRODUCT_DC_4COM 0x00a5 +#define MEDIATEK_PRODUCT_DC_5COM 0x00a4 +#define MEDIATEK_PRODUCT_7208_1COM 0x7101 +#define MEDIATEK_PRODUCT_7208_2COM 0x7102 +#define MEDIATEK_PRODUCT_FP_1COM 0x0003 +#define MEDIATEK_PRODUCT_FP_2COM 0x0023 +#define MEDIATEK_PRODUCT_FPDC_1COM 0x0043 +#define MEDIATEK_PRODUCT_FPDC_2COM 0x0033 + +/* Cellient products */ +#define CELLIENT_VENDOR_ID 0x2692 +#define CELLIENT_PRODUCT_MEN200 0x9005 /* some devices interfaces need special handling due to a number of reasons */ enum option_blacklist_reason { @@ -549,6 +563,10 @@ static const struct option_blacklist_info net_intf1_blacklist = { .reserved = BIT(1), }; +static const struct option_blacklist_info net_intf2_blacklist = { + .reserved = BIT(2), +}; + static const struct option_blacklist_info net_intf3_blacklist = { .reserved = BIT(3), }; @@ -734,6 +752,8 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_G1) }, { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_G1_M) }, { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_G2) }, + /* Novatel Ovation MC551 a.k.a. Verizon USB551L */ + { USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC551, 0xff, 0xff, 0xff) }, { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01) }, { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01A) }, @@ -1092,6 +1112,8 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1298, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1299, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1300, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1402, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf2_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2002, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&zte_k3765_z_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2003, 0xff, 0xff, 0xff) }, @@ -1233,6 +1255,18 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a1, 0xff, 0x02, 0x01) }, { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a2, 0xff, 0x00, 0x00) }, { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x00a2, 0xff, 0x02, 0x01) }, /* MediaTek MT6276M modem & app port */ + { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_1COM, 0x0a, 0x00, 0x00) }, + { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_5COM, 0xff, 0x02, 0x01) }, + { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_5COM, 0xff, 0x00, 0x00) }, + { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_4COM, 0xff, 0x02, 0x01) }, + { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_4COM, 0xff, 0x00, 0x00) }, + { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_7208_1COM, 0x02, 0x00, 0x00) }, + { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_7208_2COM, 0x02, 0x02, 0x01) }, + { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FP_1COM, 0x0a, 0x00, 0x00) }, + { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FP_2COM, 0x0a, 0x00, 0x00) }, + { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FPDC_1COM, 0x0a, 0x00, 0x00) }, + { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FPDC_2COM, 0x0a, 0x00, 0x00) }, + { USB_DEVICE(CELLIENT_VENDOR_ID, CELLIENT_PRODUCT_MEN200) }, { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, option_ids); diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c index a324a5d21e9..11418da9bc0 100644 --- a/drivers/usb/storage/scsiglue.c +++ b/drivers/usb/storage/scsiglue.c @@ -202,6 +202,12 @@ static int slave_configure(struct scsi_device *sdev) if (us->fflags & US_FL_NO_READ_CAPACITY_16) sdev->no_read_capacity_16 = 1; + /* + * Many devices do not respond properly to READ_CAPACITY_16. + * Tell the SCSI layer to try READ_CAPACITY_10 first. + */ + sdev->try_rc_10_first = 1; + /* assume SPC3 or latter devices support sense size > 18 */ if (sdev->scsi_level > SCSI_SPC_2) us->fflags |= US_FL_SANE_SENSE; diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index f4d3e1a8e7d..8f3cbb8dc81 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1107,13 +1107,6 @@ UNUSUAL_DEV( 0x090a, 0x1200, 0x0000, 0x9999, USB_SC_RBC, USB_PR_BULK, NULL, 0 ), -/* Feiya QDI U2 DISK, reported by Hans de Goede */ -UNUSUAL_DEV( 0x090c, 0x1000, 0x0000, 0xffff, - "Feiya", - "QDI U2 DISK", - USB_SC_DEVICE, USB_PR_DEVICE, NULL, - US_FL_NO_READ_CAPACITY_16 ), - /* aeb */ UNUSUAL_DEV( 0x090c, 0x1132, 0x0000, 0xffff, "Feiya", diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c index b10b3bc1931..cb19af2d6da 100644 --- a/drivers/video/omap2/dss/apply.c +++ b/drivers/video/omap2/dss/apply.c @@ -927,7 +927,7 @@ static void dss_ovl_setup_fifo(struct omap_overlay *ovl, dssdev = ovl->manager->device; dispc_ovl_compute_fifo_thresholds(ovl->id, &fifo_low, &fifo_high, - use_fifo_merge); + use_fifo_merge, ovl_manual_update(ovl)); dss_apply_ovl_fifo_thresholds(ovl, fifo_low, fifo_high); } diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index ee30937482e..c4d0e445f41 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c @@ -1063,7 +1063,8 @@ void dispc_enable_fifomerge(bool enable) } void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane, - u32 *fifo_low, u32 *fifo_high, bool use_fifomerge) + u32 *fifo_low, u32 *fifo_high, bool use_fifomerge, + bool manual_update) { /* * All sizes are in bytes. Both the buffer and burst are made of @@ -1091,7 +1092,7 @@ void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane, * combined fifo size */ - if (dss_has_feature(FEAT_OMAP3_DSI_FIFO_BUG)) { + if (manual_update && dss_has_feature(FEAT_OMAP3_DSI_FIFO_BUG)) { *fifo_low = ovl_fifo_size - burst_size * 2; *fifo_high = total_fifo_size - burst_size; } else { diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index d4b3dff2ead..d0638da92a9 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h @@ -424,7 +424,8 @@ int dispc_calc_clock_rates(unsigned long dispc_fclk_rate, void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high); void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane, - u32 *fifo_low, u32 *fifo_high, bool use_fifomerge); + u32 *fifo_low, u32 *fifo_high, bool use_fifomerge, + bool manual_update); int dispc_ovl_setup(enum omap_plane plane, struct omap_overlay_info *oi, bool ilace, bool replication); int dispc_ovl_enable(enum omap_plane plane, bool enable); diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index eb1ae908582..dce89da9c86 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c @@ -690,6 +690,8 @@ static noinline int drop_one_dir_item(struct btrfs_trans_handle *trans, kfree(name); iput(inode); + + btrfs_run_delayed_items(trans, root); return ret; } @@ -895,6 +897,7 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans, ret = btrfs_unlink_inode(trans, root, dir, inode, victim_name, victim_name_len); + btrfs_run_delayed_items(trans, root); } kfree(victim_name); ptr = (unsigned long)(victim_ref + 1) + victim_name_len; @@ -1475,6 +1478,9 @@ static noinline int check_item_in_log(struct btrfs_trans_handle *trans, ret = btrfs_unlink_inode(trans, root, dir, inode, name, name_len); BUG_ON(ret); + + btrfs_run_delayed_items(trans, root); + kfree(name); iput(inode); diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index e0b56d7a19c..402fa0f9bc0 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -1585,24 +1585,26 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, * If yes, we have encountered a double deliminator * reset the NULL character to the deliminator */ - if (tmp_end < end && tmp_end[1] == delim) + if (tmp_end < end && tmp_end[1] == delim) { tmp_end[0] = delim; - /* Keep iterating until we get to a single deliminator - * OR the end - */ - while ((tmp_end = strchr(tmp_end, delim)) != NULL && - (tmp_end[1] == delim)) { - tmp_end = (char *) &tmp_end[2]; - } + /* Keep iterating until we get to a single + * deliminator OR the end + */ + while ((tmp_end = strchr(tmp_end, delim)) + != NULL && (tmp_end[1] == delim)) { + tmp_end = (char *) &tmp_end[2]; + } - /* Reset var options to point to next element */ - if (tmp_end) { - tmp_end[0] = '\0'; - options = (char *) &tmp_end[1]; - } else - /* Reached the end of the mount option string */ - options = end; + /* Reset var options to point to next element */ + if (tmp_end) { + tmp_end[0] = '\0'; + options = (char *) &tmp_end[1]; + } else + /* Reached the end of the mount option + * string */ + options = end; + } /* Now build new password string */ temp_len = strlen(value); @@ -3396,18 +3398,15 @@ cifs_negotiate_rsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info) * MS-CIFS indicates that servers are only limited by the client's * bufsize for reads, testing against win98se shows that it throws * INVALID_PARAMETER errors if you try to request too large a read. + * OS/2 just sends back short reads. * - * If the server advertises a MaxBufferSize of less than one page, - * assume that it also can't satisfy reads larger than that either. - * - * FIXME: Is there a better heuristic for this? + * If the server doesn't advertise CAP_LARGE_READ_X, then assume that + * it can't handle a read request larger than its MaxBufferSize either. */ if (tcon->unix_ext && (unix_cap & CIFS_UNIX_LARGE_READ_CAP)) defsize = CIFS_DEFAULT_IOSIZE; else if (server->capabilities & CAP_LARGE_READ_X) defsize = CIFS_DEFAULT_NON_POSIX_RSIZE; - else if (server->maxBuf >= PAGE_CACHE_SIZE) - defsize = CIFSMaxBufSize; else defsize = server->maxBuf - sizeof(READ_RSP); diff --git a/fs/exec.c b/fs/exec.c index b1fd2025e59..29e5f840544 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -823,10 +823,10 @@ static int exec_mmap(struct mm_struct *mm) /* Notify parent that we're no longer interested in the old VM */ tsk = current; old_mm = current->mm; - sync_mm_rss(old_mm); mm_release(tsk, old_mm); if (old_mm) { + sync_mm_rss(old_mm); /* * Make sure that if there is a core dump in progress * for the old mm, we get out and die instead of going diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c index ba1dc2eebd1..ca0a0800144 100644 --- a/fs/lockd/clntlock.c +++ b/fs/lockd/clntlock.c @@ -56,7 +56,7 @@ struct nlm_host *nlmclnt_init(const struct nlmclnt_initdata *nlm_init) u32 nlm_version = (nlm_init->nfs_version == 2) ? 1 : 4; int status; - status = lockd_up(); + status = lockd_up(nlm_init->net); if (status < 0) return ERR_PTR(status); @@ -65,7 +65,7 @@ struct nlm_host *nlmclnt_init(const struct nlmclnt_initdata *nlm_init) nlm_init->hostname, nlm_init->noresvport, nlm_init->net); if (host == NULL) { - lockd_down(); + lockd_down(nlm_init->net); return ERR_PTR(-ENOLCK); } @@ -80,8 +80,10 @@ EXPORT_SYMBOL_GPL(nlmclnt_init); */ void nlmclnt_done(struct nlm_host *host) { + struct net *net = host->net; + nlmclnt_release_host(host); - lockd_down(); + lockd_down(net); } EXPORT_SYMBOL_GPL(nlmclnt_done); @@ -220,11 +222,12 @@ reclaimer(void *ptr) struct nlm_wait *block; struct file_lock *fl, *next; u32 nsmstate; + struct net *net = host->net; allow_signal(SIGKILL); down_write(&host->h_rwsem); - lockd_up(); /* note: this cannot fail as lockd is already running */ + lockd_up(net); /* note: this cannot fail as lockd is already running */ dprintk("lockd: reclaiming locks for host %s\n", host->h_name); @@ -275,6 +278,6 @@ reclaimer(void *ptr) /* Release host handle after use */ nlmclnt_release_host(host); - lockd_down(); + lockd_down(net); return 0; } diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c index f49b9afc443..3250f280a17 100644 --- a/fs/lockd/svc.c +++ b/fs/lockd/svc.c @@ -257,7 +257,7 @@ static int lockd_up_net(struct net *net) struct svc_serv *serv = nlmsvc_rqst->rq_server; int error; - if (ln->nlmsvc_users) + if (ln->nlmsvc_users++) return 0; error = svc_rpcb_setup(serv, net); @@ -272,6 +272,7 @@ static int lockd_up_net(struct net *net) err_socks: svc_rpcb_cleanup(serv, net); err_rpcb: + ln->nlmsvc_users--; return error; } @@ -295,11 +296,11 @@ static void lockd_down_net(struct net *net) /* * Bring up the lockd process if it's not already up. */ -int lockd_up(void) +int lockd_up(struct net *net) { struct svc_serv *serv; int error = 0; - struct net *net = current->nsproxy->net_ns; + struct lockd_net *ln = net_generic(net, lockd_net_id); mutex_lock(&nlmsvc_mutex); /* @@ -325,9 +326,17 @@ int lockd_up(void) goto out; } + error = svc_bind(serv, net); + if (error < 0) { + printk(KERN_WARNING "lockd_up: bind service failed\n"); + goto destroy_and_out; + } + + ln->nlmsvc_users++; + error = make_socks(serv, net); if (error < 0) - goto destroy_and_out; + goto err_start; /* * Create the kernel thread and wait for it to start. @@ -339,7 +348,7 @@ int lockd_up(void) printk(KERN_WARNING "lockd_up: svc_rqst allocation failed, error=%d\n", error); - goto destroy_and_out; + goto err_start; } svc_sock_update_bufs(serv); @@ -353,7 +362,7 @@ int lockd_up(void) nlmsvc_rqst = NULL; printk(KERN_WARNING "lockd_up: kthread_run failed, error=%d\n", error); - goto destroy_and_out; + goto err_start; } /* @@ -363,14 +372,14 @@ int lockd_up(void) destroy_and_out: svc_destroy(serv); out: - if (!error) { - struct lockd_net *ln = net_generic(net, lockd_net_id); - - ln->nlmsvc_users++; + if (!error) nlmsvc_users++; - } mutex_unlock(&nlmsvc_mutex); return error; + +err_start: + lockd_down_net(net); + goto destroy_and_out; } EXPORT_SYMBOL_GPL(lockd_up); @@ -378,14 +387,13 @@ EXPORT_SYMBOL_GPL(lockd_up); * Decrement the user count and bring down lockd if we're the last. */ void -lockd_down(void) +lockd_down(struct net *net) { mutex_lock(&nlmsvc_mutex); + lockd_down_net(net); if (nlmsvc_users) { - if (--nlmsvc_users) { - lockd_down_net(current->nsproxy->net_ns); + if (--nlmsvc_users) goto out; - } } else { printk(KERN_ERR "lockd_down: no users! task=%p\n", nlmsvc_task); diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c index eb95f5091c1..38a44c679a0 100644 --- a/fs/nfs/callback.c +++ b/fs/nfs/callback.c @@ -106,7 +106,7 @@ nfs4_callback_up(struct svc_serv *serv, struct rpc_xprt *xprt) { int ret; - ret = svc_create_xprt(serv, "tcp", xprt->xprt_net, PF_INET, + ret = svc_create_xprt(serv, "tcp", &init_net, PF_INET, nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS); if (ret <= 0) goto out_err; @@ -114,7 +114,7 @@ nfs4_callback_up(struct svc_serv *serv, struct rpc_xprt *xprt) dprintk("NFS: Callback listener port = %u (af %u)\n", nfs_callback_tcpport, PF_INET); - ret = svc_create_xprt(serv, "tcp", xprt->xprt_net, PF_INET6, + ret = svc_create_xprt(serv, "tcp", &init_net, PF_INET6, nfs_callback_set_tcpport, SVC_SOCK_ANONYMOUS); if (ret > 0) { nfs_callback_tcpport6 = ret; @@ -183,7 +183,7 @@ nfs41_callback_up(struct svc_serv *serv, struct rpc_xprt *xprt) * fore channel connection. * Returns the input port (0) and sets the svc_serv bc_xprt on success */ - ret = svc_create_xprt(serv, "tcp-bc", xprt->xprt_net, PF_INET, 0, + ret = svc_create_xprt(serv, "tcp-bc", &init_net, PF_INET, 0, SVC_SOCK_ANONYMOUS); if (ret < 0) { rqstp = ERR_PTR(ret); @@ -253,6 +253,7 @@ int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt) char svc_name[12]; int ret = 0; int minorversion_setup; + struct net *net = &init_net; mutex_lock(&nfs_callback_mutex); if (cb_info->users++ || cb_info->task != NULL) { @@ -265,6 +266,12 @@ int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt) goto out_err; } + ret = svc_bind(serv, net); + if (ret < 0) { + printk(KERN_WARNING "NFS: bind callback service failed\n"); + goto out_err; + } + minorversion_setup = nfs_minorversion_callback_svc_setup(minorversion, serv, xprt, &rqstp, &callback_svc); if (!minorversion_setup) { @@ -306,6 +313,8 @@ int nfs_callback_up(u32 minorversion, struct rpc_xprt *xprt) dprintk("NFS: Couldn't create callback socket or server thread; " "err = %d\n", ret); cb_info->users--; + if (serv) + svc_shutdown_net(serv, net); goto out; } @@ -320,6 +329,7 @@ void nfs_callback_down(int minorversion) cb_info->users--; if (cb_info->users == 0 && cb_info->task != NULL) { kthread_stop(cb_info->task); + svc_shutdown_net(cb_info->serv, &init_net); svc_exit_thread(cb_info->rqst); cb_info->serv = NULL; cb_info->rqst = NULL; diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c index 3e8edbe71ec..93aa3a4c4b0 100644 --- a/fs/nfs/idmap.c +++ b/fs/nfs/idmap.c @@ -57,6 +57,11 @@ unsigned int nfs_idmap_cache_timeout = 600; static const struct cred *id_resolver_cache; static struct key_type key_type_id_resolver_legacy; +struct idmap { + struct rpc_pipe *idmap_pipe; + struct key_construction *idmap_key_cons; + struct mutex idmap_mutex; +}; /** * nfs_fattr_init_names - initialise the nfs_fattr owner_name/group_name fields @@ -310,9 +315,11 @@ static ssize_t nfs_idmap_get_key(const char *name, size_t namelen, name, namelen, type, data, data_size, NULL); if (ret < 0) { + mutex_lock(&idmap->idmap_mutex); ret = nfs_idmap_request_key(&key_type_id_resolver_legacy, name, namelen, type, data, data_size, idmap); + mutex_unlock(&idmap->idmap_mutex); } return ret; } @@ -354,11 +361,6 @@ static int nfs_idmap_lookup_id(const char *name, size_t namelen, const char *typ /* idmap classic begins here */ module_param(nfs_idmap_cache_timeout, int, 0644); -struct idmap { - struct rpc_pipe *idmap_pipe; - struct key_construction *idmap_key_cons; -}; - enum { Opt_find_uid, Opt_find_gid, Opt_find_user, Opt_find_group, Opt_find_err }; @@ -469,6 +471,7 @@ nfs_idmap_new(struct nfs_client *clp) return error; } idmap->idmap_pipe = pipe; + mutex_init(&idmap->idmap_mutex); clp->cl_idmap = idmap; return 0; diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 2c53be6d357..3ab12eb2967 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -651,6 +651,7 @@ static ssize_t __write_ports_addfd(char *buf) { char *mesg = buf; int fd, err; + struct net *net = &init_net; err = get_int(&mesg, &fd); if (err != 0 || fd < 0) @@ -662,6 +663,8 @@ static ssize_t __write_ports_addfd(char *buf) err = svc_addsock(nfsd_serv, fd, buf, SIMPLE_TRANSACTION_LIMIT); if (err < 0) { + if (nfsd_serv->sv_nrthreads == 1) + svc_shutdown_net(nfsd_serv, net); svc_destroy(nfsd_serv); return err; } @@ -699,6 +702,7 @@ static ssize_t __write_ports_addxprt(char *buf) char transport[16]; struct svc_xprt *xprt; int port, err; + struct net *net = &init_net; if (sscanf(buf, "%15s %4u", transport, &port) != 2) return -EINVAL; @@ -710,12 +714,12 @@ static ssize_t __write_ports_addxprt(char *buf) if (err != 0) return err; - err = svc_create_xprt(nfsd_serv, transport, &init_net, + err = svc_create_xprt(nfsd_serv, transport, net, PF_INET, port, SVC_SOCK_ANONYMOUS); if (err < 0) goto out_err; - err = svc_create_xprt(nfsd_serv, transport, &init_net, + err = svc_create_xprt(nfsd_serv, transport, net, PF_INET6, port, SVC_SOCK_ANONYMOUS); if (err < 0 && err != -EAFNOSUPPORT) goto out_close; @@ -724,12 +728,14 @@ static ssize_t __write_ports_addxprt(char *buf) nfsd_serv->sv_nrthreads--; return 0; out_close: - xprt = svc_find_xprt(nfsd_serv, transport, &init_net, PF_INET, port); + xprt = svc_find_xprt(nfsd_serv, transport, net, PF_INET, port); if (xprt != NULL) { svc_close_xprt(xprt); svc_xprt_put(xprt); } out_err: + if (nfsd_serv->sv_nrthreads == 1) + svc_shutdown_net(nfsd_serv, net); svc_destroy(nfsd_serv); return err; } diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index 28dfad39f0c..bcda12a3f08 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -220,7 +221,7 @@ static int nfsd_startup(unsigned short port, int nrservs) ret = nfsd_init_socks(port); if (ret) goto out_racache; - ret = lockd_up(); + ret = lockd_up(&init_net); if (ret) goto out_racache; ret = nfs4_state_start(); @@ -229,7 +230,7 @@ static int nfsd_startup(unsigned short port, int nrservs) nfsd_up = true; return 0; out_lockd: - lockd_down(); + lockd_down(&init_net); out_racache: nfsd_racache_shutdown(); return ret; @@ -246,7 +247,7 @@ static void nfsd_shutdown(void) if (!nfsd_up) return; nfs4_state_shutdown(); - lockd_down(); + lockd_down(&init_net); nfsd_racache_shutdown(); nfsd_up = false; } @@ -330,6 +331,8 @@ static int nfsd_get_default_max_blksize(void) int nfsd_create_serv(void) { + int error; + WARN_ON(!mutex_is_locked(&nfsd_mutex)); if (nfsd_serv) { svc_get(nfsd_serv); @@ -343,6 +346,12 @@ int nfsd_create_serv(void) if (nfsd_serv == NULL) return -ENOMEM; + error = svc_bind(nfsd_serv, current->nsproxy->net_ns); + if (error < 0) { + svc_destroy(nfsd_serv); + return error; + } + set_max_drc(); do_gettimeofday(&nfssvc_boot); /* record boot time */ return 0; @@ -373,6 +382,7 @@ int nfsd_set_nrthreads(int n, int *nthreads) int i = 0; int tot = 0; int err = 0; + struct net *net = &init_net; WARN_ON(!mutex_is_locked(&nfsd_mutex)); @@ -417,6 +427,9 @@ int nfsd_set_nrthreads(int n, int *nthreads) if (err) break; } + + if (nfsd_serv->sv_nrthreads == 1) + svc_shutdown_net(nfsd_serv, net); svc_destroy(nfsd_serv); return err; @@ -432,6 +445,7 @@ nfsd_svc(unsigned short port, int nrservs) { int error; bool nfsd_up_before; + struct net *net = &init_net; mutex_lock(&nfsd_mutex); dprintk("nfsd: creating service\n"); @@ -464,6 +478,8 @@ nfsd_svc(unsigned short port, int nrservs) if (error < 0 && !nfsd_up_before) nfsd_shutdown(); out_destroy: + if (nfsd_serv->sv_nrthreads == 1) + svc_shutdown_net(nfsd_serv, net); svc_destroy(nfsd_serv); /* Release server */ out: mutex_unlock(&nfsd_mutex); @@ -547,6 +563,9 @@ nfsd(void *vrqstp) nfsdstats.th_cnt --; out: + if (rqstp->rq_server->sv_nrthreads == 1) + svc_shutdown_net(rqstp->rq_server, &init_net); + /* Release the thread */ svc_exit_thread(rqstp); @@ -659,8 +678,12 @@ int nfsd_pool_stats_open(struct inode *inode, struct file *file) int nfsd_pool_stats_release(struct inode *inode, struct file *file) { int ret = seq_release(inode, file); + struct net *net = &init_net; + mutex_lock(&nfsd_mutex); /* this function really, really should have been called svc_put() */ + if (nfsd_serv->sv_nrthreads == 1) + svc_shutdown_net(nfsd_serv, net); svc_destroy(nfsd_serv); mutex_unlock(&nfsd_mutex); return ret; diff --git a/fs/nilfs2/gcinode.c b/fs/nilfs2/gcinode.c index 08a07a218d2..57ceaf33d17 100644 --- a/fs/nilfs2/gcinode.c +++ b/fs/nilfs2/gcinode.c @@ -191,6 +191,8 @@ void nilfs_remove_all_gcinodes(struct the_nilfs *nilfs) while (!list_empty(head)) { ii = list_first_entry(head, struct nilfs_inode_info, i_dirty); list_del_init(&ii->i_dirty); + truncate_inode_pages(&ii->vfs_inode.i_data, 0); + nilfs_btnode_cache_clear(&ii->i_btnode_cache); iput(&ii->vfs_inode); } } diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index 0e72ad6f22a..88e11fb346b 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c @@ -2309,6 +2309,8 @@ nilfs_remove_written_gcinodes(struct the_nilfs *nilfs, struct list_head *head) if (!test_bit(NILFS_I_UPDATED, &ii->i_state)) continue; list_del_init(&ii->i_dirty); + truncate_inode_pages(&ii->vfs_inode.i_data, 0); + nilfs_btnode_cache_clear(&ii->i_btnode_cache); iput(&ii->vfs_inode); } } diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index da47ae766fa..d5facce62be 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -1950,7 +1950,7 @@ static int __ocfs2_change_file_space(struct file *file, struct inode *inode, if (ret < 0) mlog_errno(ret); - if (file->f_flags & O_SYNC) + if (file && (file->f_flags & O_SYNC)) handle->h_sync = 1; ocfs2_commit_trans(osb, handle); @@ -2422,8 +2422,10 @@ static ssize_t ocfs2_file_aio_write(struct kiocb *iocb, unaligned_dio = 0; } - if (unaligned_dio) + if (unaligned_dio) { + ocfs2_iocb_clear_unaligned_aio(iocb); atomic_dec(&OCFS2_I(inode)->ip_unaligned_aio); + } out: if (rw_level != -1) diff --git a/fs/open.c b/fs/open.c index 5720854156d..3f1108b1914 100644 --- a/fs/open.c +++ b/fs/open.c @@ -396,10 +396,10 @@ SYSCALL_DEFINE1(fchdir, unsigned int, fd) { struct file *file; struct inode *inode; - int error; + int error, fput_needed; error = -EBADF; - file = fget(fd); + file = fget_raw_light(fd, &fput_needed); if (!file) goto out; @@ -413,7 +413,7 @@ SYSCALL_DEFINE1(fchdir, unsigned int, fd) if (!error) set_fs_pwd(current->fs, &file->f_path); out_putf: - fput(file); + fput_light(file, fput_needed); out: return error; } diff --git a/fs/ramfs/file-nommu.c b/fs/ramfs/file-nommu.c index fbb0b478a34..d5378d02858 100644 --- a/fs/ramfs/file-nommu.c +++ b/fs/ramfs/file-nommu.c @@ -110,6 +110,7 @@ int ramfs_nommu_expand_for_mapping(struct inode *inode, size_t newsize) /* prevent the page from being discarded on memory pressure */ SetPageDirty(page); + SetPageUptodate(page); unlock_page(page); put_page(page); diff --git a/fs/splice.c b/fs/splice.c index 034567d86b2..060e9e4b8a4 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -273,13 +273,16 @@ void spd_release_page(struct splice_pipe_desc *spd, unsigned int i) * Check if we need to grow the arrays holding pages and partial page * descriptions. */ -int splice_grow_spd(struct pipe_inode_info *pipe, struct splice_pipe_desc *spd) +int splice_grow_spd(const struct pipe_inode_info *pipe, struct splice_pipe_desc *spd) { - if (pipe->buffers <= PIPE_DEF_BUFFERS) + unsigned int buffers = ACCESS_ONCE(pipe->buffers); + + spd->nr_pages_max = buffers; + if (buffers <= PIPE_DEF_BUFFERS) return 0; - spd->pages = kmalloc(pipe->buffers * sizeof(struct page *), GFP_KERNEL); - spd->partial = kmalloc(pipe->buffers * sizeof(struct partial_page), GFP_KERNEL); + spd->pages = kmalloc(buffers * sizeof(struct page *), GFP_KERNEL); + spd->partial = kmalloc(buffers * sizeof(struct partial_page), GFP_KERNEL); if (spd->pages && spd->partial) return 0; @@ -289,10 +292,9 @@ int splice_grow_spd(struct pipe_inode_info *pipe, struct splice_pipe_desc *spd) return -ENOMEM; } -void splice_shrink_spd(struct pipe_inode_info *pipe, - struct splice_pipe_desc *spd) +void splice_shrink_spd(struct splice_pipe_desc *spd) { - if (pipe->buffers <= PIPE_DEF_BUFFERS) + if (spd->nr_pages_max <= PIPE_DEF_BUFFERS) return; kfree(spd->pages); @@ -315,6 +317,7 @@ __generic_file_splice_read(struct file *in, loff_t *ppos, struct splice_pipe_desc spd = { .pages = pages, .partial = partial, + .nr_pages_max = PIPE_DEF_BUFFERS, .flags = flags, .ops = &page_cache_pipe_buf_ops, .spd_release = spd_release_page, @@ -326,7 +329,7 @@ __generic_file_splice_read(struct file *in, loff_t *ppos, index = *ppos >> PAGE_CACHE_SHIFT; loff = *ppos & ~PAGE_CACHE_MASK; req_pages = (len + loff + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; - nr_pages = min(req_pages, pipe->buffers); + nr_pages = min(req_pages, spd.nr_pages_max); /* * Lookup the (hopefully) full range of pages we need. @@ -497,7 +500,7 @@ __generic_file_splice_read(struct file *in, loff_t *ppos, if (spd.nr_pages) error = splice_to_pipe(pipe, &spd); - splice_shrink_spd(pipe, &spd); + splice_shrink_spd(&spd); return error; } @@ -598,6 +601,7 @@ ssize_t default_file_splice_read(struct file *in, loff_t *ppos, struct splice_pipe_desc spd = { .pages = pages, .partial = partial, + .nr_pages_max = PIPE_DEF_BUFFERS, .flags = flags, .ops = &default_pipe_buf_ops, .spd_release = spd_release_page, @@ -608,8 +612,8 @@ ssize_t default_file_splice_read(struct file *in, loff_t *ppos, res = -ENOMEM; vec = __vec; - if (pipe->buffers > PIPE_DEF_BUFFERS) { - vec = kmalloc(pipe->buffers * sizeof(struct iovec), GFP_KERNEL); + if (spd.nr_pages_max > PIPE_DEF_BUFFERS) { + vec = kmalloc(spd.nr_pages_max * sizeof(struct iovec), GFP_KERNEL); if (!vec) goto shrink_ret; } @@ -617,7 +621,7 @@ ssize_t default_file_splice_read(struct file *in, loff_t *ppos, offset = *ppos & ~PAGE_CACHE_MASK; nr_pages = (len + offset + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; - for (i = 0; i < nr_pages && i < pipe->buffers && len; i++) { + for (i = 0; i < nr_pages && i < spd.nr_pages_max && len; i++) { struct page *page; page = alloc_page(GFP_USER); @@ -665,7 +669,7 @@ ssize_t default_file_splice_read(struct file *in, loff_t *ppos, shrink_ret: if (vec != __vec) kfree(vec); - splice_shrink_spd(pipe, &spd); + splice_shrink_spd(&spd); return res; err: @@ -1609,6 +1613,7 @@ static long vmsplice_to_pipe(struct file *file, const struct iovec __user *iov, struct splice_pipe_desc spd = { .pages = pages, .partial = partial, + .nr_pages_max = PIPE_DEF_BUFFERS, .flags = flags, .ops = &user_page_pipe_buf_ops, .spd_release = spd_release_page, @@ -1624,13 +1629,13 @@ static long vmsplice_to_pipe(struct file *file, const struct iovec __user *iov, spd.nr_pages = get_iovec_page_array(iov, nr_segs, spd.pages, spd.partial, flags & SPLICE_F_GIFT, - pipe->buffers); + spd.nr_pages_max); if (spd.nr_pages <= 0) ret = spd.nr_pages; else ret = splice_to_pipe(pipe, &spd); - splice_shrink_spd(pipe, &spd); + splice_shrink_spd(&spd); return ret; } diff --git a/fs/udf/super.c b/fs/udf/super.c index ac8a348dcb6..8d86a8706c0 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -56,6 +56,7 @@ #include #include #include +#include #include #include "udf_sb.h" @@ -1215,16 +1216,65 @@ static int udf_load_partdesc(struct super_block *sb, sector_t block) return ret; } +static int udf_load_sparable_map(struct super_block *sb, + struct udf_part_map *map, + struct sparablePartitionMap *spm) +{ + uint32_t loc; + uint16_t ident; + struct sparingTable *st; + struct udf_sparing_data *sdata = &map->s_type_specific.s_sparing; + int i; + struct buffer_head *bh; + + map->s_partition_type = UDF_SPARABLE_MAP15; + sdata->s_packet_len = le16_to_cpu(spm->packetLength); + if (!is_power_of_2(sdata->s_packet_len)) { + udf_err(sb, "error loading logical volume descriptor: " + "Invalid packet length %u\n", + (unsigned)sdata->s_packet_len); + return -EIO; + } + if (spm->numSparingTables > 4) { + udf_err(sb, "error loading logical volume descriptor: " + "Too many sparing tables (%d)\n", + (int)spm->numSparingTables); + return -EIO; + } + + for (i = 0; i < spm->numSparingTables; i++) { + loc = le32_to_cpu(spm->locSparingTable[i]); + bh = udf_read_tagged(sb, loc, loc, &ident); + if (!bh) + continue; + + st = (struct sparingTable *)bh->b_data; + if (ident != 0 || + strncmp(st->sparingIdent.ident, UDF_ID_SPARING, + strlen(UDF_ID_SPARING)) || + sizeof(*st) + le16_to_cpu(st->reallocationTableLen) > + sb->s_blocksize) { + brelse(bh); + continue; + } + + sdata->s_spar_map[i] = bh; + } + map->s_partition_func = udf_get_pblock_spar15; + return 0; +} + static int udf_load_logicalvol(struct super_block *sb, sector_t block, struct kernel_lb_addr *fileset) { struct logicalVolDesc *lvd; - int i, j, offset; + int i, offset; uint8_t type; struct udf_sb_info *sbi = UDF_SB(sb); struct genericPartitionMap *gpm; uint16_t ident; struct buffer_head *bh; + unsigned int table_len; int ret = 0; bh = udf_read_tagged(sb, block, block, &ident); @@ -1232,15 +1282,20 @@ static int udf_load_logicalvol(struct super_block *sb, sector_t block, return 1; BUG_ON(ident != TAG_IDENT_LVD); lvd = (struct logicalVolDesc *)bh->b_data; - - i = udf_sb_alloc_partition_maps(sb, le32_to_cpu(lvd->numPartitionMaps)); - if (i != 0) { - ret = i; + table_len = le32_to_cpu(lvd->mapTableLength); + if (sizeof(*lvd) + table_len > sb->s_blocksize) { + udf_err(sb, "error loading logical volume descriptor: " + "Partition table too long (%u > %lu)\n", table_len, + sb->s_blocksize - sizeof(*lvd)); goto out_bh; } + ret = udf_sb_alloc_partition_maps(sb, le32_to_cpu(lvd->numPartitionMaps)); + if (ret) + goto out_bh; + for (i = 0, offset = 0; - i < sbi->s_partitions && offset < le32_to_cpu(lvd->mapTableLength); + i < sbi->s_partitions && offset < table_len; i++, offset += gpm->partitionMapLength) { struct udf_part_map *map = &sbi->s_partmaps[i]; gpm = (struct genericPartitionMap *) @@ -1275,38 +1330,9 @@ static int udf_load_logicalvol(struct super_block *sb, sector_t block, } else if (!strncmp(upm2->partIdent.ident, UDF_ID_SPARABLE, strlen(UDF_ID_SPARABLE))) { - uint32_t loc; - struct sparingTable *st; - struct sparablePartitionMap *spm = - (struct sparablePartitionMap *)gpm; - - map->s_partition_type = UDF_SPARABLE_MAP15; - map->s_type_specific.s_sparing.s_packet_len = - le16_to_cpu(spm->packetLength); - for (j = 0; j < spm->numSparingTables; j++) { - struct buffer_head *bh2; - - loc = le32_to_cpu( - spm->locSparingTable[j]); - bh2 = udf_read_tagged(sb, loc, loc, - &ident); - map->s_type_specific.s_sparing. - s_spar_map[j] = bh2; - - if (bh2 == NULL) - continue; - - st = (struct sparingTable *)bh2->b_data; - if (ident != 0 || strncmp( - st->sparingIdent.ident, - UDF_ID_SPARING, - strlen(UDF_ID_SPARING))) { - brelse(bh2); - map->s_type_specific.s_sparing. - s_spar_map[j] = NULL; - } - } - map->s_partition_func = udf_get_pblock_spar15; + if (udf_load_sparable_map(sb, map, + (struct sparablePartitionMap *)gpm) < 0) + goto out_bh; } else if (!strncmp(upm2->partIdent.ident, UDF_ID_METADATA, strlen(UDF_ID_METADATA))) { diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h index 125c54e9851..c7ec2cdc904 100644 --- a/include/asm-generic/pgtable.h +++ b/include/asm-generic/pgtable.h @@ -446,6 +446,18 @@ static inline int pmd_write(pmd_t pmd) #endif /* __HAVE_ARCH_PMD_WRITE */ #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ +#ifndef pmd_read_atomic +static inline pmd_t pmd_read_atomic(pmd_t *pmdp) +{ + /* + * Depend on compiler for an atomic pmd read. NOTE: this is + * only going to work, if the pmdval_t isn't larger than + * an unsigned long. + */ + return *pmdp; +} +#endif + /* * This function is meant to be used by sites walking pagetables with * the mmap_sem hold in read mode to protect against MADV_DONTNEED and @@ -459,14 +471,30 @@ static inline int pmd_write(pmd_t pmd) * undefined so behaving like if the pmd was none is safe (because it * can return none anyway). The compiler level barrier() is critically * important to compute the two checks atomically on the same pmdval. + * + * For 32bit kernels with a 64bit large pmd_t this automatically takes + * care of reading the pmd atomically to avoid SMP race conditions + * against pmd_populate() when the mmap_sem is hold for reading by the + * caller (a special atomic read not done by "gcc" as in the generic + * version above, is also needed when THP is disabled because the page + * fault can populate the pmd from under us). */ static inline int pmd_none_or_trans_huge_or_clear_bad(pmd_t *pmd) { - /* depend on compiler for an atomic pmd read */ - pmd_t pmdval = *pmd; + pmd_t pmdval = pmd_read_atomic(pmd); /* * The barrier will stabilize the pmdval in a register or on * the stack so that it will stop changing under the code. + * + * When CONFIG_TRANSPARENT_HUGEPAGE=y on x86 32bit PAE, + * pmd_read_atomic is allowed to return a not atomic pmdval + * (for example pointing to an hugepage that has never been + * mapped in the pmd). The below checks will only care about + * the low part of the pmd with 32bit PAE x86 anyway, with the + * exception of pmd_none(). So the important thing is that if + * the low part of the pmd is found null, the high part will + * be also null or the pmd_none() check below would be + * confused. */ #ifdef CONFIG_TRANSPARENT_HUGEPAGE barrier(); diff --git a/include/linux/aio.h b/include/linux/aio.h index 2314ad8b3c9..b1a520ec8b5 100644 --- a/include/linux/aio.h +++ b/include/linux/aio.h @@ -140,6 +140,7 @@ struct kiocb { (x)->ki_dtor = NULL; \ (x)->ki_obj.tsk = tsk; \ (x)->ki_user_data = 0; \ + (x)->private = NULL; \ } while (0) #define AIO_RING_MAGIC 0xa10a10a1 diff --git a/include/linux/lockd/bind.h b/include/linux/lockd/bind.h index 11a966e5f82..4d24d64578c 100644 --- a/include/linux/lockd/bind.h +++ b/include/linux/lockd/bind.h @@ -54,7 +54,7 @@ extern void nlmclnt_done(struct nlm_host *host); extern int nlmclnt_proc(struct nlm_host *host, int cmd, struct file_lock *fl); -extern int lockd_up(void); -extern void lockd_down(void); +extern int lockd_up(struct net *net); +extern void lockd_down(struct net *net); #endif /* LINUX_LOCKD_BIND_H */ diff --git a/include/linux/memblock.h b/include/linux/memblock.h index 36bc2f5b6a1..224336260a7 100644 --- a/include/linux/memblock.h +++ b/include/linux/memblock.h @@ -50,9 +50,7 @@ phys_addr_t memblock_find_in_range_node(phys_addr_t start, phys_addr_t end, phys_addr_t size, phys_addr_t align, int nid); phys_addr_t memblock_find_in_range(phys_addr_t start, phys_addr_t end, phys_addr_t size, phys_addr_t align); -int memblock_free_reserved_regions(void); -int memblock_reserve_reserved_regions(void); - +phys_addr_t get_allocated_memblock_reserved_regions_info(phys_addr_t *addr); void memblock_allow_resize(void); int memblock_add_node(phys_addr_t base, phys_addr_t size, int nid); int memblock_add(phys_addr_t base, phys_addr_t size); diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h index 9035d0a71a8..4fc12b203f0 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h @@ -56,8 +56,18 @@ struct page { }; union { +#if defined(CONFIG_HAVE_CMPXCHG_DOUBLE) && \ + defined(CONFIG_HAVE_ALIGNED_STRUCT_PAGE) /* Used for cmpxchg_double in slub */ unsigned long counters; +#else + /* + * Keep _count separate from slub cmpxchg_double data. + * As the rest of the double word is protected by + * slab_lock but _count is not. + */ + unsigned counters; +#endif struct { diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index ca7a586f05c..c0efc1fe251 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -708,7 +708,7 @@ typedef struct pglist_data { range, including holes */ int node_id; wait_queue_head_t kswapd_wait; - struct task_struct *kswapd; + struct task_struct *kswapd; /* Protected by lock_memory_hotplug() */ int kswapd_max_order; enum zone_type classzone_idx; } pg_data_t; diff --git a/include/linux/pci.h b/include/linux/pci.h index 8b2921ad51a..e444f5b4911 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -176,8 +176,6 @@ enum pci_dev_flags { PCI_DEV_FLAGS_NO_D3 = (__force pci_dev_flags_t) 2, /* Provide indication device is assigned by a Virtual Machine Manager */ PCI_DEV_FLAGS_ASSIGNED = (__force pci_dev_flags_t) 4, - /* Device causes system crash if in D3 during S3 sleep */ - PCI_DEV_FLAGS_NO_D3_DURING_SLEEP = (__force pci_dev_flags_t) 8, }; enum pci_irq_reroute_variant { diff --git a/include/linux/rpmsg.h b/include/linux/rpmsg.h index a8e50e44203..82a673905ed 100644 --- a/include/linux/rpmsg.h +++ b/include/linux/rpmsg.h @@ -38,6 +38,8 @@ #include #include #include +#include +#include /* The feature bitmap for virtio rpmsg */ #define VIRTIO_RPMSG_F_NS 0 /* RP supports name service notifications */ @@ -120,7 +122,9 @@ typedef void (*rpmsg_rx_cb_t)(struct rpmsg_channel *, void *, int, void *, u32); /** * struct rpmsg_endpoint - binds a local rpmsg address to its user * @rpdev: rpmsg channel device + * @refcount: when this drops to zero, the ept is deallocated * @cb: rx callback handler + * @cb_lock: must be taken before accessing/changing @cb * @addr: local rpmsg address * @priv: private data for the driver's use * @@ -140,7 +144,9 @@ typedef void (*rpmsg_rx_cb_t)(struct rpmsg_channel *, void *, int, void *, u32); */ struct rpmsg_endpoint { struct rpmsg_channel *rpdev; + struct kref refcount; rpmsg_rx_cb_t cb; + struct mutex cb_lock; u32 addr; void *priv; }; diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index c1689071fa2..c1bae8dff77 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -225,14 +225,11 @@ enum { /* device driver is going to provide hardware time stamp */ SKBTX_IN_PROGRESS = 1 << 2, - /* ensure the originating sk reference is available on driver level */ - SKBTX_DRV_NEEDS_SK_REF = 1 << 3, - /* device driver supports TX zero-copy buffers */ - SKBTX_DEV_ZEROCOPY = 1 << 4, + SKBTX_DEV_ZEROCOPY = 1 << 3, /* generate wifi status information (where possible) */ - SKBTX_WIFI_STATUS = 1 << 5, + SKBTX_WIFI_STATUS = 1 << 4, }; /* diff --git a/include/linux/splice.h b/include/linux/splice.h index 26e5b613ded..09a545a7dfa 100644 --- a/include/linux/splice.h +++ b/include/linux/splice.h @@ -51,7 +51,8 @@ struct partial_page { struct splice_pipe_desc { struct page **pages; /* page map */ struct partial_page *partial; /* pages[] may not be contig */ - int nr_pages; /* number of pages in map */ + int nr_pages; /* number of populated pages in map */ + unsigned int nr_pages_max; /* pages[] & partial[] arrays size */ unsigned int flags; /* splice flags */ const struct pipe_buf_operations *ops;/* ops associated with output pipe */ void (*spd_release)(struct splice_pipe_desc *, unsigned int); @@ -85,9 +86,8 @@ extern ssize_t splice_direct_to_actor(struct file *, struct splice_desc *, /* * for dynamic pipe sizing */ -extern int splice_grow_spd(struct pipe_inode_info *, struct splice_pipe_desc *); -extern void splice_shrink_spd(struct pipe_inode_info *, - struct splice_pipe_desc *); +extern int splice_grow_spd(const struct pipe_inode_info *, struct splice_pipe_desc *); +extern void splice_shrink_spd(struct splice_pipe_desc *); extern void spd_release_page(struct splice_pipe_desc *, unsigned int); extern const struct pipe_buf_operations page_cache_pipe_buf_ops; diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h index 51b29ac45a8..2b43e021426 100644 --- a/include/linux/sunrpc/svc.h +++ b/include/linux/sunrpc/svc.h @@ -416,6 +416,7 @@ struct svc_procedure { */ int svc_rpcb_setup(struct svc_serv *serv, struct net *net); void svc_rpcb_cleanup(struct svc_serv *serv, struct net *net); +int svc_bind(struct svc_serv *serv, struct net *net); struct svc_serv *svc_create(struct svc_program *, unsigned int, void (*shutdown)(struct svc_serv *, struct net *net)); struct svc_rqst *svc_prepare_thread(struct svc_serv *serv, diff --git a/include/net/cipso_ipv4.h b/include/net/cipso_ipv4.h index 9808877c2ab..a7a683e30b6 100644 --- a/include/net/cipso_ipv4.h +++ b/include/net/cipso_ipv4.h @@ -42,6 +42,7 @@ #include #include #include +#include /* known doi values */ #define CIPSO_V4_DOI_UNKNOWN 0x00000000 @@ -285,7 +286,33 @@ static inline int cipso_v4_skbuff_getattr(const struct sk_buff *skb, static inline int cipso_v4_validate(const struct sk_buff *skb, unsigned char **option) { - return -ENOSYS; + unsigned char *opt = *option; + unsigned char err_offset = 0; + u8 opt_len = opt[1]; + u8 opt_iter; + + if (opt_len < 8) { + err_offset = 1; + goto out; + } + + if (get_unaligned_be32(&opt[2]) == 0) { + err_offset = 2; + goto out; + } + + for (opt_iter = 6; opt_iter < opt_len;) { + if (opt[opt_iter + 1] > (opt_len - opt_iter)) { + err_offset = opt_iter + 1; + goto out; + } + opt_iter += opt[opt_iter + 1]; + } + +out: + *option = opt + err_offset; + return err_offset; + } #endif /* CONFIG_NETLABEL */ diff --git a/include/net/inetpeer.h b/include/net/inetpeer.h index b94765e38e8..2040bff945d 100644 --- a/include/net/inetpeer.h +++ b/include/net/inetpeer.h @@ -40,7 +40,10 @@ struct inet_peer { u32 pmtu_orig; u32 pmtu_learned; struct inetpeer_addr_base redirect_learned; - struct list_head gc_list; + union { + struct list_head gc_list; + struct rcu_head gc_rcu; + }; /* * Once inet_peer is queued for deletion (refcnt == -1), following fields * are not available: rid, ip_id_count, tcp_ts, tcp_ts_stamp diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index 55ce96b53b0..9d7d54a00e6 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h @@ -220,13 +220,16 @@ struct tcf_proto { struct qdisc_skb_cb { unsigned int pkt_len; - unsigned char data[24]; + u16 bond_queue_mapping; + u16 _pad; + unsigned char data[20]; }; static inline void qdisc_cb_private_validate(const struct sk_buff *skb, int sz) { struct qdisc_skb_cb *qcb; - BUILD_BUG_ON(sizeof(skb->cb) < sizeof(unsigned int) + sz); + + BUILD_BUG_ON(sizeof(skb->cb) < offsetof(struct qdisc_skb_cb, data) + sz); BUILD_BUG_ON(sizeof(qcb->data) < sz); } diff --git a/include/scsi/libsas.h b/include/scsi/libsas.h index f4f1c96dca7..10ce74f589c 100644 --- a/include/scsi/libsas.h +++ b/include/scsi/libsas.h @@ -163,6 +163,8 @@ enum ata_command_set { ATAPI_COMMAND_SET = 1, }; +#define ATA_RESP_FIS_SIZE 24 + struct sata_device { enum ata_command_set command_set; struct smp_resp rps_resp; /* report_phy_sata_resp */ @@ -171,7 +173,7 @@ struct sata_device { struct ata_port *ap; struct ata_host ata_host; - struct ata_taskfile tf; + u8 fis[ATA_RESP_FIS_SIZE]; }; enum { @@ -537,7 +539,7 @@ enum exec_status { */ struct ata_task_resp { u16 frame_len; - u8 ending_fis[24]; /* dev to host or data-in */ + u8 ending_fis[ATA_RESP_FIS_SIZE]; /* dev to host or data-in */ }; #define SAS_STATUS_BUF_SIZE 96 diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h index 1e1198546c7..ac06cc59589 100644 --- a/include/scsi/scsi_cmnd.h +++ b/include/scsi/scsi_cmnd.h @@ -134,10 +134,16 @@ struct scsi_cmnd { static inline struct scsi_driver *scsi_cmd_to_driver(struct scsi_cmnd *cmd) { + struct scsi_driver **sdp; + if (!cmd->request->rq_disk) return NULL; - return *(struct scsi_driver **)cmd->request->rq_disk->private_data; + sdp = (struct scsi_driver **)cmd->request->rq_disk->private_data; + if (!sdp) + return NULL; + + return *sdp; } extern struct scsi_cmnd *scsi_get_command(struct scsi_device *, gfp_t); diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h index 6efb2e1416e..ba969885232 100644 --- a/include/scsi/scsi_device.h +++ b/include/scsi/scsi_device.h @@ -151,6 +151,7 @@ struct scsi_device { SD_LAST_BUGGY_SECTORS */ unsigned no_read_disc_info:1; /* Avoid READ_DISC_INFO cmds */ unsigned no_read_capacity_16:1; /* Avoid READ_CAPACITY_16 cmds */ + unsigned try_rc_10_first:1; /* Try READ_CAPACACITY_10 first */ unsigned is_visible:1; /* is the device visible in sysfs */ DECLARE_BITMAP(supported_events, SDEV_EVT_MAXBITS); /* supported events */ diff --git a/kernel/exit.c b/kernel/exit.c index bc7d69084fd..b5109b6367a 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -644,6 +644,7 @@ static void exit_mm(struct task_struct * tsk) mm_release(tsk, mm); if (!mm) return; + sync_mm_rss(mm); /* * Serialize with any possible pending coredump. * We must hold mmap_sem around checking core_state diff --git a/kernel/relay.c b/kernel/relay.c index 1175b4cfb0e..a86fcab6b33 100644 --- a/kernel/relay.c +++ b/kernel/relay.c @@ -1235,6 +1235,7 @@ static ssize_t subbuf_splice_actor(struct file *in, struct splice_pipe_desc spd = { .pages = pages, .nr_pages = 0, + .nr_pages_max = PIPE_DEF_BUFFERS, .partial = partial, .flags = flags, .ops = &relay_pipe_buf_ops, @@ -1302,8 +1303,8 @@ static ssize_t subbuf_splice_actor(struct file *in, ret += padding; out: - splice_shrink_spd(pipe, &spd); - return ret; + splice_shrink_spd(&spd); + return ret; } static ssize_t relay_file_splice_read(struct file *in, diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index f3200176c49..8da07dd9227 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -2650,10 +2650,12 @@ tracing_cpumask_write(struct file *filp, const char __user *ubuf, if (cpumask_test_cpu(cpu, tracing_cpumask) && !cpumask_test_cpu(cpu, tracing_cpumask_new)) { atomic_inc(&global_trace.data[cpu]->disabled); + ring_buffer_record_disable_cpu(global_trace.buffer, cpu); } if (!cpumask_test_cpu(cpu, tracing_cpumask) && cpumask_test_cpu(cpu, tracing_cpumask_new)) { atomic_dec(&global_trace.data[cpu]->disabled); + ring_buffer_record_enable_cpu(global_trace.buffer, cpu); } } arch_spin_unlock(&ftrace_max_lock); @@ -3565,6 +3567,7 @@ static ssize_t tracing_splice_read_pipe(struct file *filp, .pages = pages_def, .partial = partial_def, .nr_pages = 0, /* This gets updated below. */ + .nr_pages_max = PIPE_DEF_BUFFERS, .flags = flags, .ops = &tracing_pipe_buf_ops, .spd_release = tracing_spd_release_pipe, @@ -3636,7 +3639,7 @@ static ssize_t tracing_splice_read_pipe(struct file *filp, ret = splice_to_pipe(pipe, &spd); out: - splice_shrink_spd(pipe, &spd); + splice_shrink_spd(&spd); return ret; out_err: @@ -4128,6 +4131,7 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos, struct splice_pipe_desc spd = { .pages = pages_def, .partial = partial_def, + .nr_pages_max = PIPE_DEF_BUFFERS, .flags = flags, .ops = &buffer_pipe_buf_ops, .spd_release = buffer_spd_release, @@ -4215,7 +4219,7 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos, } ret = splice_to_pipe(pipe, &spd); - splice_shrink_spd(pipe, &spd); + splice_shrink_spd(&spd); out: return ret; } diff --git a/lib/dynamic_queue_limits.c b/lib/dynamic_queue_limits.c index 6ab4587d052..0777c5a45fa 100644 --- a/lib/dynamic_queue_limits.c +++ b/lib/dynamic_queue_limits.c @@ -10,23 +10,27 @@ #include #include -#define POSDIFF(A, B) ((A) > (B) ? (A) - (B) : 0) +#define POSDIFF(A, B) ((int)((A) - (B)) > 0 ? (A) - (B) : 0) +#define AFTER_EQ(A, B) ((int)((A) - (B)) >= 0) /* Records completed count and recalculates the queue limit */ void dql_completed(struct dql *dql, unsigned int count) { unsigned int inprogress, prev_inprogress, limit; - unsigned int ovlimit, all_prev_completed, completed; + unsigned int ovlimit, completed, num_queued; + bool all_prev_completed; + + num_queued = ACCESS_ONCE(dql->num_queued); /* Can't complete more than what's in queue */ - BUG_ON(count > dql->num_queued - dql->num_completed); + BUG_ON(count > num_queued - dql->num_completed); completed = dql->num_completed + count; limit = dql->limit; - ovlimit = POSDIFF(dql->num_queued - dql->num_completed, limit); - inprogress = dql->num_queued - completed; + ovlimit = POSDIFF(num_queued - dql->num_completed, limit); + inprogress = num_queued - completed; prev_inprogress = dql->prev_num_queued - dql->num_completed; - all_prev_completed = POSDIFF(completed, dql->prev_num_queued); + all_prev_completed = AFTER_EQ(completed, dql->prev_num_queued); if ((ovlimit && !inprogress) || (dql->prev_ovlimit && all_prev_completed)) { @@ -104,7 +108,7 @@ void dql_completed(struct dql *dql, unsigned int count) dql->prev_ovlimit = ovlimit; dql->prev_last_obj_cnt = dql->last_obj_cnt; dql->num_completed = completed; - dql->prev_num_queued = dql->num_queued; + dql->prev_num_queued = num_queued; } EXPORT_SYMBOL(dql_completed); diff --git a/mm/compaction.c b/mm/compaction.c index 353f1c577ca..260a4870253 100644 --- a/mm/compaction.c +++ b/mm/compaction.c @@ -698,8 +698,11 @@ static int compact_zone(struct zone *zone, struct compact_control *cc) if (err) { putback_lru_pages(&cc->migratepages); cc->nr_migratepages = 0; + if (err == -ENOMEM) { + ret = COMPACT_PARTIAL; + goto out; + } } - } out: diff --git a/mm/memblock.c b/mm/memblock.c index b510ca5c5cb..85ba00a52d4 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -37,6 +37,8 @@ struct memblock memblock __initdata_memblock = { int memblock_debug __initdata_memblock; static int memblock_can_resize __initdata_memblock; +static int memblock_memory_in_slab __initdata_memblock = 0; +static int memblock_reserved_in_slab __initdata_memblock = 0; /* inline so we don't get a warning when pr_debug is compiled out */ static inline const char *memblock_type_name(struct memblock_type *type) @@ -141,30 +143,6 @@ phys_addr_t __init_memblock memblock_find_in_range(phys_addr_t start, MAX_NUMNODES); } -/* - * Free memblock.reserved.regions - */ -int __init_memblock memblock_free_reserved_regions(void) -{ - if (memblock.reserved.regions == memblock_reserved_init_regions) - return 0; - - return memblock_free(__pa(memblock.reserved.regions), - sizeof(struct memblock_region) * memblock.reserved.max); -} - -/* - * Reserve memblock.reserved.regions - */ -int __init_memblock memblock_reserve_reserved_regions(void) -{ - if (memblock.reserved.regions == memblock_reserved_init_regions) - return 0; - - return memblock_reserve(__pa(memblock.reserved.regions), - sizeof(struct memblock_region) * memblock.reserved.max); -} - static void __init_memblock memblock_remove_region(struct memblock_type *type, unsigned long r) { type->total_size -= type->regions[r].size; @@ -182,11 +160,42 @@ static void __init_memblock memblock_remove_region(struct memblock_type *type, u } } -static int __init_memblock memblock_double_array(struct memblock_type *type) +phys_addr_t __init_memblock get_allocated_memblock_reserved_regions_info( + phys_addr_t *addr) +{ + if (memblock.reserved.regions == memblock_reserved_init_regions) + return 0; + + *addr = __pa(memblock.reserved.regions); + + return PAGE_ALIGN(sizeof(struct memblock_region) * + memblock.reserved.max); +} + +/** + * memblock_double_array - double the size of the memblock regions array + * @type: memblock type of the regions array being doubled + * @new_area_start: starting address of memory range to avoid overlap with + * @new_area_size: size of memory range to avoid overlap with + * + * Double the size of the @type regions array. If memblock is being used to + * allocate memory for a new reserved regions array and there is a previously + * allocated memory range [@new_area_start,@new_area_start+@new_area_size] + * waiting to be reserved, ensure the memory used by the new array does + * not overlap. + * + * RETURNS: + * 0 on success, -1 on failure. + */ +static int __init_memblock memblock_double_array(struct memblock_type *type, + phys_addr_t new_area_start, + phys_addr_t new_area_size) { struct memblock_region *new_array, *old_array; + phys_addr_t old_alloc_size, new_alloc_size; phys_addr_t old_size, new_size, addr; int use_slab = slab_is_available(); + int *in_slab; /* We don't allow resizing until we know about the reserved regions * of memory that aren't suitable for allocation @@ -197,6 +206,18 @@ static int __init_memblock memblock_double_array(struct memblock_type *type) /* Calculate new doubled size */ old_size = type->max * sizeof(struct memblock_region); new_size = old_size << 1; + /* + * We need to allocated new one align to PAGE_SIZE, + * so we can free them completely later. + */ + old_alloc_size = PAGE_ALIGN(old_size); + new_alloc_size = PAGE_ALIGN(new_size); + + /* Retrieve the slab flag */ + if (type == &memblock.memory) + in_slab = &memblock_memory_in_slab; + else + in_slab = &memblock_reserved_in_slab; /* Try to find some space for it. * @@ -212,14 +233,26 @@ static int __init_memblock memblock_double_array(struct memblock_type *type) if (use_slab) { new_array = kmalloc(new_size, GFP_KERNEL); addr = new_array ? __pa(new_array) : 0; - } else - addr = memblock_find_in_range(0, MEMBLOCK_ALLOC_ACCESSIBLE, new_size, sizeof(phys_addr_t)); + } else { + /* only exclude range when trying to double reserved.regions */ + if (type != &memblock.reserved) + new_area_start = new_area_size = 0; + + addr = memblock_find_in_range(new_area_start + new_area_size, + memblock.current_limit, + new_alloc_size, PAGE_SIZE); + if (!addr && new_area_size) + addr = memblock_find_in_range(0, + min(new_area_start, memblock.current_limit), + new_alloc_size, PAGE_SIZE); + + new_array = addr ? __va(addr) : 0; + } if (!addr) { pr_err("memblock: Failed to double %s array from %ld to %ld entries !\n", memblock_type_name(type), type->max, type->max * 2); return -1; } - new_array = __va(addr); memblock_dbg("memblock: %s array is doubled to %ld at [%#010llx-%#010llx]", memblock_type_name(type), type->max * 2, (u64)addr, (u64)addr + new_size - 1); @@ -234,21 +267,23 @@ static int __init_memblock memblock_double_array(struct memblock_type *type) type->regions = new_array; type->max <<= 1; - /* If we use SLAB that's it, we are done */ - if (use_slab) - return 0; - - /* Add the new reserved region now. Should not fail ! */ - BUG_ON(memblock_reserve(addr, new_size)); - - /* If the array wasn't our static init one, then free it. We only do - * that before SLAB is available as later on, we don't know whether - * to use kfree or free_bootmem_pages(). Shouldn't be a big deal - * anyways + /* Free old array. We needn't free it if the array is the + * static one */ - if (old_array != memblock_memory_init_regions && - old_array != memblock_reserved_init_regions) - memblock_free(__pa(old_array), old_size); + if (*in_slab) + kfree(old_array); + else if (old_array != memblock_memory_init_regions && + old_array != memblock_reserved_init_regions) + memblock_free(__pa(old_array), old_alloc_size); + + /* Reserve the new array if that comes from the memblock. + * Otherwise, we needn't do it + */ + if (!use_slab) + BUG_ON(memblock_reserve(addr, new_alloc_size)); + + /* Update slab flag */ + *in_slab = use_slab; return 0; } @@ -387,7 +422,7 @@ static int __init_memblock memblock_add_region(struct memblock_type *type, */ if (!insert) { while (type->cnt + nr_new > type->max) - if (memblock_double_array(type) < 0) + if (memblock_double_array(type, obase, size) < 0) return -ENOMEM; insert = true; goto repeat; @@ -438,7 +473,7 @@ static int __init_memblock memblock_isolate_range(struct memblock_type *type, /* we'll create at most two more regions */ while (type->cnt + 2 > type->max) - if (memblock_double_array(type) < 0) + if (memblock_double_array(type, base, size) < 0) return -ENOMEM; for (i = 0; i < type->cnt; i++) { diff --git a/mm/nobootmem.c b/mm/nobootmem.c index 1983fb1c702..218e6f95d44 100644 --- a/mm/nobootmem.c +++ b/mm/nobootmem.c @@ -105,27 +105,35 @@ static void __init __free_pages_memory(unsigned long start, unsigned long end) __free_pages_bootmem(pfn_to_page(i), 0); } +static unsigned long __init __free_memory_core(phys_addr_t start, + phys_addr_t end) +{ + unsigned long start_pfn = PFN_UP(start); + unsigned long end_pfn = min_t(unsigned long, + PFN_DOWN(end), max_low_pfn); + + if (start_pfn > end_pfn) + return 0; + + __free_pages_memory(start_pfn, end_pfn); + + return end_pfn - start_pfn; +} + unsigned long __init free_low_memory_core_early(int nodeid) { unsigned long count = 0; - phys_addr_t start, end; + phys_addr_t start, end, size; u64 i; - /* free reserved array temporarily so that it's treated as free area */ - memblock_free_reserved_regions(); - - for_each_free_mem_range(i, MAX_NUMNODES, &start, &end, NULL) { - unsigned long start_pfn = PFN_UP(start); - unsigned long end_pfn = min_t(unsigned long, - PFN_DOWN(end), max_low_pfn); - if (start_pfn < end_pfn) { - __free_pages_memory(start_pfn, end_pfn); - count += end_pfn - start_pfn; - } - } + for_each_free_mem_range(i, MAX_NUMNODES, &start, &end, NULL) + count += __free_memory_core(start, end); + + /* free range that is used for reserved array if we allocate it */ + size = get_allocated_memblock_reserved_regions_info(&start); + if (size) + count += __free_memory_core(start, start + size); - /* put region array back? */ - memblock_reserve_reserved_regions(); return count; } diff --git a/mm/shmem.c b/mm/shmem.c index e281f0658cb..2910f0d58c4 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -1365,6 +1365,7 @@ static ssize_t shmem_file_splice_read(struct file *in, loff_t *ppos, struct splice_pipe_desc spd = { .pages = pages, .partial = partial, + .nr_pages_max = PIPE_DEF_BUFFERS, .flags = flags, .ops = &page_cache_pipe_buf_ops, .spd_release = spd_release_page, @@ -1453,7 +1454,7 @@ static ssize_t shmem_file_splice_read(struct file *in, loff_t *ppos, if (spd.nr_pages) error = splice_to_pipe(pipe, &spd); - splice_shrink_spd(pipe, &spd); + splice_shrink_spd(&spd); if (error > 0) { *ppos += error; diff --git a/mm/vmscan.c b/mm/vmscan.c index cb515d7fe49..086613f36f4 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -3279,14 +3279,17 @@ int kswapd_run(int nid) } /* - * Called by memory hotplug when all memory in a node is offlined. + * Called by memory hotplug when all memory in a node is offlined. Caller must + * hold lock_memory_hotplug(). */ void kswapd_stop(int nid) { struct task_struct *kswapd = NODE_DATA(nid)->kswapd; - if (kswapd) + if (kswapd) { kthread_stop(kswapd); + NODE_DATA(nid)->kswapd = NULL; + } } static int __init kswapd_init(void) diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index 7f8e1589941..8df3a1ff516 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c @@ -618,6 +618,8 @@ int recv_tt_query(struct sk_buff *skb, struct hard_iface *recv_if) * changes */ if (skb_linearize(skb) < 0) goto out; + /* skb_linearize() possibly changed skb->data */ + tt_query = (struct tt_query_packet *)skb->data; tt_len = tt_query->tt_data * sizeof(struct tt_change); diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index 1f869212784..f014bf83aed 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c @@ -1803,10 +1803,10 @@ bool is_ap_isolated(struct bat_priv *bat_priv, uint8_t *src, uint8_t *dst) { struct tt_local_entry *tt_local_entry = NULL; struct tt_global_entry *tt_global_entry = NULL; - bool ret = true; + bool ret = false; if (!atomic_read(&bat_priv->ap_isolation)) - return false; + goto out; tt_local_entry = tt_local_hash_find(bat_priv, dst); if (!tt_local_entry) @@ -1816,10 +1816,10 @@ bool is_ap_isolated(struct bat_priv *bat_priv, uint8_t *src, uint8_t *dst) if (!tt_global_entry) goto out; - if (_is_ap_isolated(tt_local_entry, tt_global_entry)) + if (!_is_ap_isolated(tt_local_entry, tt_global_entry)) goto out; - ret = false; + ret = true; out: if (tt_global_entry) diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index 0a942fbccc9..e1144e1617b 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -240,6 +240,7 @@ int br_add_bridge(struct net *net, const char *name) return -ENOMEM; dev_net_set(dev, net); + dev->rtnl_link_ops = &br_link_ops; res = register_netdev(dev); if (res) diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index a1daf8227ed..cbf9ccd4578 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c @@ -211,7 +211,7 @@ static int br_validate(struct nlattr *tb[], struct nlattr *data[]) return 0; } -static struct rtnl_link_ops br_link_ops __read_mostly = { +struct rtnl_link_ops br_link_ops __read_mostly = { .kind = "bridge", .priv_size = sizeof(struct net_bridge), .setup = br_dev_setup, diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index e1d88225787..51e8826e78c 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -538,6 +538,7 @@ extern int (*br_fdb_test_addr_hook)(struct net_device *dev, unsigned char *addr) #endif /* br_netlink.c */ +extern struct rtnl_link_ops br_link_ops; extern int br_netlink_init(void); extern void br_netlink_fini(void); extern void br_ifinfo_notify(int event, struct net_bridge_port *port); diff --git a/net/can/raw.c b/net/can/raw.c index cde1b4a20f7..46cca3a91d1 100644 --- a/net/can/raw.c +++ b/net/can/raw.c @@ -681,9 +681,6 @@ static int raw_sendmsg(struct kiocb *iocb, struct socket *sock, if (err < 0) goto free_skb; - /* to be able to check the received tx sock reference in raw_rcv() */ - skb_shinfo(skb)->tx_flags |= SKBTX_DRV_NEEDS_SK_REF; - skb->dev = dev; skb->sk = sk; diff --git a/net/core/dev.c b/net/core/dev.c index 70145dcd17f..c299416d0e8 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2092,25 +2092,6 @@ static int dev_gso_segment(struct sk_buff *skb, netdev_features_t features) return 0; } -/* - * Try to orphan skb early, right before transmission by the device. - * We cannot orphan skb if tx timestamp is requested or the sk-reference - * is needed on driver level for other reasons, e.g. see net/can/raw.c - */ -static inline void skb_orphan_try(struct sk_buff *skb) -{ - struct sock *sk = skb->sk; - - if (sk && !skb_shinfo(skb)->tx_flags) { - /* skb_tx_hash() wont be able to get sk. - * We copy sk_hash into skb->rxhash - */ - if (!skb->rxhash) - skb->rxhash = sk->sk_hash; - skb_orphan(skb); - } -} - static bool can_checksum_protocol(netdev_features_t features, __be16 protocol) { return ((features & NETIF_F_GEN_CSUM) || @@ -2196,8 +2177,6 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev, if (!list_empty(&ptype_all)) dev_queue_xmit_nit(skb, dev); - skb_orphan_try(skb); - features = netif_skb_features(skb); if (vlan_tx_tag_present(skb) && @@ -2307,7 +2286,7 @@ u16 __skb_tx_hash(const struct net_device *dev, const struct sk_buff *skb, if (skb->sk && skb->sk->sk_hash) hash = skb->sk->sk_hash; else - hash = (__force u16) skb->protocol ^ skb->rxhash; + hash = (__force u16) skb->protocol; hash = jhash_1word(hash, hashrnd); return (u16) (((u64) hash * qcount) >> 32) + qoffset; diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c index a7cad741df0..b856f87e63d 100644 --- a/net/core/drop_monitor.c +++ b/net/core/drop_monitor.c @@ -33,9 +33,6 @@ #define TRACE_ON 1 #define TRACE_OFF 0 -static void send_dm_alert(struct work_struct *unused); - - /* * Globals, our netlink socket pointer * and the work handle that will send up @@ -45,11 +42,10 @@ static int trace_state = TRACE_OFF; static DEFINE_MUTEX(trace_state_mutex); struct per_cpu_dm_data { - struct work_struct dm_alert_work; - struct sk_buff __rcu *skb; - atomic_t dm_hit_count; - struct timer_list send_timer; - int cpu; + spinlock_t lock; + struct sk_buff *skb; + struct work_struct dm_alert_work; + struct timer_list send_timer; }; struct dm_hw_stat_delta { @@ -75,13 +71,13 @@ static int dm_delay = 1; static unsigned long dm_hw_check_delta = 2*HZ; static LIST_HEAD(hw_stats_list); -static void reset_per_cpu_data(struct per_cpu_dm_data *data) +static struct sk_buff *reset_per_cpu_data(struct per_cpu_dm_data *data) { size_t al; struct net_dm_alert_msg *msg; struct nlattr *nla; struct sk_buff *skb; - struct sk_buff *oskb = rcu_dereference_protected(data->skb, 1); + unsigned long flags; al = sizeof(struct net_dm_alert_msg); al += dm_hit_limit * sizeof(struct net_dm_drop_point); @@ -96,65 +92,40 @@ static void reset_per_cpu_data(struct per_cpu_dm_data *data) sizeof(struct net_dm_alert_msg)); msg = nla_data(nla); memset(msg, 0, al); - } else - schedule_work_on(data->cpu, &data->dm_alert_work); - - /* - * Don't need to lock this, since we are guaranteed to only - * run this on a single cpu at a time. - * Note also that we only update data->skb if the old and new skb - * pointers don't match. This ensures that we don't continually call - * synchornize_rcu if we repeatedly fail to alloc a new netlink message. - */ - if (skb != oskb) { - rcu_assign_pointer(data->skb, skb); - - synchronize_rcu(); - - atomic_set(&data->dm_hit_count, dm_hit_limit); + } else { + mod_timer(&data->send_timer, jiffies + HZ / 10); } + spin_lock_irqsave(&data->lock, flags); + swap(data->skb, skb); + spin_unlock_irqrestore(&data->lock, flags); + + return skb; } -static void send_dm_alert(struct work_struct *unused) +static void send_dm_alert(struct work_struct *work) { struct sk_buff *skb; - struct per_cpu_dm_data *data = &get_cpu_var(dm_cpu_data); + struct per_cpu_dm_data *data; - WARN_ON_ONCE(data->cpu != smp_processor_id()); + data = container_of(work, struct per_cpu_dm_data, dm_alert_work); - /* - * Grab the skb we're about to send - */ - skb = rcu_dereference_protected(data->skb, 1); + skb = reset_per_cpu_data(data); - /* - * Replace it with a new one - */ - reset_per_cpu_data(data); - - /* - * Ship it! - */ if (skb) genlmsg_multicast(skb, 0, NET_DM_GRP_ALERT, GFP_KERNEL); - - put_cpu_var(dm_cpu_data); } /* * This is the timer function to delay the sending of an alert * in the event that more drops will arrive during the - * hysteresis period. Note that it operates under the timer interrupt - * so we don't need to disable preemption here + * hysteresis period. */ -static void sched_send_work(unsigned long unused) +static void sched_send_work(unsigned long _data) { - struct per_cpu_dm_data *data = &get_cpu_var(dm_cpu_data); + struct per_cpu_dm_data *data = (struct per_cpu_dm_data *)_data; - schedule_work_on(smp_processor_id(), &data->dm_alert_work); - - put_cpu_var(dm_cpu_data); + schedule_work(&data->dm_alert_work); } static void trace_drop_common(struct sk_buff *skb, void *location) @@ -164,33 +135,28 @@ static void trace_drop_common(struct sk_buff *skb, void *location) struct nlattr *nla; int i; struct sk_buff *dskb; - struct per_cpu_dm_data *data = &get_cpu_var(dm_cpu_data); - + struct per_cpu_dm_data *data; + unsigned long flags; - rcu_read_lock(); - dskb = rcu_dereference(data->skb); + local_irq_save(flags); + data = &__get_cpu_var(dm_cpu_data); + spin_lock(&data->lock); + dskb = data->skb; if (!dskb) goto out; - if (!atomic_add_unless(&data->dm_hit_count, -1, 0)) { - /* - * we're already at zero, discard this hit - */ - goto out; - } - nlh = (struct nlmsghdr *)dskb->data; nla = genlmsg_data(nlmsg_data(nlh)); msg = nla_data(nla); for (i = 0; i < msg->entries; i++) { if (!memcmp(&location, msg->points[i].pc, sizeof(void *))) { msg->points[i].count++; - atomic_inc(&data->dm_hit_count); goto out; } } - + if (msg->entries == dm_hit_limit) + goto out; /* * We need to create a new entry */ @@ -202,13 +168,11 @@ static void trace_drop_common(struct sk_buff *skb, void *location) if (!timer_pending(&data->send_timer)) { data->send_timer.expires = jiffies + dm_delay * HZ; - add_timer_on(&data->send_timer, smp_processor_id()); + add_timer(&data->send_timer); } out: - rcu_read_unlock(); - put_cpu_var(dm_cpu_data); - return; + spin_unlock_irqrestore(&data->lock, flags); } static void trace_kfree_skb_hit(void *ignore, struct sk_buff *skb, void *location) @@ -406,11 +370,11 @@ static int __init init_net_drop_monitor(void) for_each_present_cpu(cpu) { data = &per_cpu(dm_cpu_data, cpu); - data->cpu = cpu; INIT_WORK(&data->dm_alert_work, send_dm_alert); init_timer(&data->send_timer); - data->send_timer.data = cpu; + data->send_timer.data = (unsigned long)data; data->send_timer.function = sched_send_work; + spin_lock_init(&data->lock); reset_per_cpu_data(data); } diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 0a68045782d..73b90351df5 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -2214,9 +2214,7 @@ static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb, rcu_read_lock_bh(); nht = rcu_dereference_bh(tbl->nht); - for (h = 0; h < (1 << nht->hash_shift); h++) { - if (h < s_h) - continue; + for (h = s_h; h < (1 << nht->hash_shift); h++) { if (h > s_h) s_idx = 0; for (n = rcu_dereference_bh(nht->hash_buckets[h]), idx = 0; @@ -2255,9 +2253,7 @@ static int pneigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb, read_lock_bh(&tbl->lock); - for (h = 0; h <= PNEIGH_HASHMASK; h++) { - if (h < s_h) - continue; + for (h = s_h; h <= PNEIGH_HASHMASK; h++) { if (h > s_h) s_idx = 0; for (n = tbl->phash_buckets[h], idx = 0; n; n = n->next) { @@ -2292,7 +2288,7 @@ static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb) struct neigh_table *tbl; int t, family, s_t; int proxy = 0; - int err = 0; + int err; read_lock(&neigh_tbl_lock); family = ((struct rtgenmsg *) nlmsg_data(cb->nlh))->rtgen_family; @@ -2306,7 +2302,7 @@ static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb) s_t = cb->args[0]; - for (tbl = neigh_tables, t = 0; tbl && (err >= 0); + for (tbl = neigh_tables, t = 0; tbl; tbl = tbl->next, t++) { if (t < s_t || (family && tbl->family != family)) continue; @@ -2317,6 +2313,8 @@ static int neigh_dump_info(struct sk_buff *skb, struct netlink_callback *cb) err = pneigh_dump_table(tbl, skb, cb); else err = neigh_dump_table(tbl, skb, cb); + if (err < 0) + break; } read_unlock(&neigh_tbl_lock); diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 3d84fb9d887..f9f40b932e4 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -362,22 +362,23 @@ EXPORT_SYMBOL(netpoll_send_skb_on_dev); void netpoll_send_udp(struct netpoll *np, const char *msg, int len) { - int total_len, eth_len, ip_len, udp_len; + int total_len, ip_len, udp_len; struct sk_buff *skb; struct udphdr *udph; struct iphdr *iph; struct ethhdr *eth; udp_len = len + sizeof(*udph); - ip_len = eth_len = udp_len + sizeof(*iph); - total_len = eth_len + ETH_HLEN + NET_IP_ALIGN; + ip_len = udp_len + sizeof(*iph); + total_len = ip_len + LL_RESERVED_SPACE(np->dev); - skb = find_skb(np, total_len, total_len - len); + skb = find_skb(np, total_len + np->dev->needed_tailroom, + total_len - len); if (!skb) return; skb_copy_to_linear_data(skb, msg, len); - skb->len += len; + skb_put(skb, len); skb_push(skb, sizeof(*udph)); skb_reset_transport_header(skb); diff --git a/net/core/skbuff.c b/net/core/skbuff.c index e59840010d4..e99aedd9c49 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -1712,6 +1712,7 @@ int skb_splice_bits(struct sk_buff *skb, unsigned int offset, struct splice_pipe_desc spd = { .pages = pages, .partial = partial, + .nr_pages_max = MAX_SKB_FRAGS, .flags = flags, .ops = &sock_pipe_buf_ops, .spd_release = sock_spd_release, @@ -1758,7 +1759,7 @@ int skb_splice_bits(struct sk_buff *skb, unsigned int offset, lock_sock(sk); } - splice_shrink_spd(pipe, &spd); + splice_shrink_spd(&spd); return ret; } diff --git a/net/core/sock.c b/net/core/sock.c index b2e14c07d92..0f8402ea434 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -1600,6 +1600,11 @@ struct sk_buff *sock_alloc_send_pskb(struct sock *sk, unsigned long header_len, gfp_t gfp_mask; long timeo; int err; + int npages = (data_len + (PAGE_SIZE - 1)) >> PAGE_SHIFT; + + err = -EMSGSIZE; + if (npages > MAX_SKB_FRAGS) + goto failure; gfp_mask = sk->sk_allocation; if (gfp_mask & __GFP_WAIT) @@ -1618,14 +1623,12 @@ struct sk_buff *sock_alloc_send_pskb(struct sock *sk, unsigned long header_len, if (atomic_read(&sk->sk_wmem_alloc) < sk->sk_sndbuf) { skb = alloc_skb(header_len, gfp_mask); if (skb) { - int npages; int i; /* No pages, we're done... */ if (!data_len) break; - npages = (data_len + (PAGE_SIZE - 1)) >> PAGE_SHIFT; skb->truesize += data_len; skb_shinfo(skb)->nr_frags = npages; for (i = 0; i < npages; i++) { diff --git a/net/ipv4/inetpeer.c b/net/ipv4/inetpeer.c index d4d61b694fa..dfba343b250 100644 --- a/net/ipv4/inetpeer.c +++ b/net/ipv4/inetpeer.c @@ -560,6 +560,17 @@ bool inet_peer_xrlim_allow(struct inet_peer *peer, int timeout) } EXPORT_SYMBOL(inet_peer_xrlim_allow); +static void inetpeer_inval_rcu(struct rcu_head *head) +{ + struct inet_peer *p = container_of(head, struct inet_peer, gc_rcu); + + spin_lock_bh(&gc_lock); + list_add_tail(&p->gc_list, &gc_list); + spin_unlock_bh(&gc_lock); + + schedule_delayed_work(&gc_work, gc_delay); +} + void inetpeer_invalidate_tree(int family) { struct inet_peer *old, *new, *prev; @@ -576,10 +587,7 @@ void inetpeer_invalidate_tree(int family) prev = cmpxchg(&base->root, old, new); if (prev == old) { base->total = 0; - spin_lock(&gc_lock); - list_add_tail(&prev->gc_list, &gc_list); - spin_unlock(&gc_lock); - schedule_delayed_work(&gc_work, gc_delay); + call_rcu(&prev->gc_rcu, inetpeer_inval_rcu); } out: diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 93717435013..92bb9cba5c3 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -1560,7 +1560,7 @@ static int fib6_age(struct rt6_info *rt, void *arg) neigh_flags = neigh->flags; neigh_release(neigh); } - if (neigh_flags & NTF_ROUTER) { + if (!(neigh_flags & NTF_ROUTER)) { RT6_TRACE("purging route %p via non-router but gateway\n", rt); return -1; diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 76e2afe077f..1cc2af65636 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -2954,10 +2954,6 @@ static int __net_init ip6_route_net_init(struct net *net) net->ipv6.sysctl.ip6_rt_mtu_expires = 10*60*HZ; net->ipv6.sysctl.ip6_rt_min_advmss = IPV6_MIN_MTU - 20 - 40; -#ifdef CONFIG_PROC_FS - proc_net_fops_create(net, "ipv6_route", 0, &ipv6_route_proc_fops); - proc_net_fops_create(net, "rt6_stats", S_IRUGO, &rt6_stats_seq_fops); -#endif net->ipv6.ip6_rt_gc_expire = 30*HZ; ret = 0; @@ -2978,10 +2974,6 @@ static int __net_init ip6_route_net_init(struct net *net) static void __net_exit ip6_route_net_exit(struct net *net) { -#ifdef CONFIG_PROC_FS - proc_net_remove(net, "ipv6_route"); - proc_net_remove(net, "rt6_stats"); -#endif kfree(net->ipv6.ip6_null_entry); #ifdef CONFIG_IPV6_MULTIPLE_TABLES kfree(net->ipv6.ip6_prohibit_entry); @@ -2990,11 +2982,33 @@ static void __net_exit ip6_route_net_exit(struct net *net) dst_entries_destroy(&net->ipv6.ip6_dst_ops); } +static int __net_init ip6_route_net_init_late(struct net *net) +{ +#ifdef CONFIG_PROC_FS + proc_net_fops_create(net, "ipv6_route", 0, &ipv6_route_proc_fops); + proc_net_fops_create(net, "rt6_stats", S_IRUGO, &rt6_stats_seq_fops); +#endif + return 0; +} + +static void __net_exit ip6_route_net_exit_late(struct net *net) +{ +#ifdef CONFIG_PROC_FS + proc_net_remove(net, "ipv6_route"); + proc_net_remove(net, "rt6_stats"); +#endif +} + static struct pernet_operations ip6_route_net_ops = { .init = ip6_route_net_init, .exit = ip6_route_net_exit, }; +static struct pernet_operations ip6_route_net_late_ops = { + .init = ip6_route_net_init_late, + .exit = ip6_route_net_exit_late, +}; + static struct notifier_block ip6_route_dev_notifier = { .notifier_call = ip6_route_dev_notify, .priority = 0, @@ -3044,19 +3058,25 @@ int __init ip6_route_init(void) if (ret) goto xfrm6_init; + ret = register_pernet_subsys(&ip6_route_net_late_ops); + if (ret) + goto fib6_rules_init; + ret = -ENOBUFS; if (__rtnl_register(PF_INET6, RTM_NEWROUTE, inet6_rtm_newroute, NULL, NULL) || __rtnl_register(PF_INET6, RTM_DELROUTE, inet6_rtm_delroute, NULL, NULL) || __rtnl_register(PF_INET6, RTM_GETROUTE, inet6_rtm_getroute, NULL, NULL)) - goto fib6_rules_init; + goto out_register_late_subsys; ret = register_netdevice_notifier(&ip6_route_dev_notifier); if (ret) - goto fib6_rules_init; + goto out_register_late_subsys; out: return ret; +out_register_late_subsys: + unregister_pernet_subsys(&ip6_route_net_late_ops); fib6_rules_init: fib6_rules_cleanup(); xfrm6_init: @@ -3075,6 +3095,7 @@ int __init ip6_route_init(void) void ip6_route_cleanup(void) { unregister_netdevice_notifier(&ip6_route_dev_notifier); + unregister_pernet_subsys(&ip6_route_net_late_ops); fib6_rules_cleanup(); xfrm6_fini(); fib6_gc_cleanup(); diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index 07d7d55a1b9..cd6f7a991d8 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c @@ -372,7 +372,6 @@ static int afiucv_hs_send(struct iucv_message *imsg, struct sock *sock, skb_trim(skb, skb->dev->mtu); } skb->protocol = ETH_P_AF_IUCV; - skb_shinfo(skb)->tx_flags |= SKBTX_DRV_NEEDS_SK_REF; nskb = skb_clone(skb, GFP_ATOMIC); if (!nskb) return -ENOMEM; diff --git a/net/l2tp/l2tp_eth.c b/net/l2tp/l2tp_eth.c index 63fe5f353f0..7446038e6b4 100644 --- a/net/l2tp/l2tp_eth.c +++ b/net/l2tp/l2tp_eth.c @@ -167,6 +167,7 @@ static void l2tp_eth_delete(struct l2tp_session *session) if (dev) { unregister_netdev(dev); spriv->dev = NULL; + module_put(THIS_MODULE); } } } @@ -254,6 +255,7 @@ static int l2tp_eth_create(struct net *net, u32 tunnel_id, u32 session_id, u32 p if (rc < 0) goto out_del_dev; + __module_get(THIS_MODULE); /* Must be done after register_netdev() */ strlcpy(session->ifname, dev->name, IFNAMSIZ); diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c index cc8ad7bf51d..b1d4370c896 100644 --- a/net/l2tp/l2tp_ip.c +++ b/net/l2tp/l2tp_ip.c @@ -516,10 +516,12 @@ static int l2tp_ip_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *m sk->sk_bound_dev_if); if (IS_ERR(rt)) goto no_route; - if (connected) + if (connected) { sk_setup_caps(sk, &rt->dst); - else - dst_release(&rt->dst); /* safe since we hold rcu_read_lock */ + } else { + skb_dst_set(skb, &rt->dst); + goto xmit; + } } /* We dont need to clone dst here, it is guaranteed to not disappear. @@ -527,6 +529,7 @@ static int l2tp_ip_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *m */ skb_dst_set_noref(skb, &rt->dst); +xmit: /* Queue the packet to IP for output */ rc = ip_queue_xmit(skb, &inet->cork.fl); rcu_read_unlock(); diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index a48a35c7ce6..036a2ca477f 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -187,7 +187,7 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, u32 changed = 0; int hti_cfreq; u16 ht_opmode; - bool enable_ht = true; + bool enable_ht = true, queues_stopped = false; enum nl80211_channel_type prev_chantype; enum nl80211_channel_type rx_channel_type = NL80211_CHAN_NO_HT; enum nl80211_channel_type tx_channel_type; @@ -254,6 +254,7 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, */ ieee80211_stop_queues_by_reason(&sdata->local->hw, IEEE80211_QUEUE_STOP_REASON_CHTYPE_CHANGE); + queues_stopped = true; /* flush out all packets */ synchronize_net(); @@ -272,12 +273,12 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, IEEE80211_RC_HT_CHANGED, tx_channel_type); rcu_read_unlock(); - - if (beacon_htcap_ie) - ieee80211_wake_queues_by_reason(&sdata->local->hw, - IEEE80211_QUEUE_STOP_REASON_CHTYPE_CHANGE); } + if (queues_stopped) + ieee80211_wake_queues_by_reason(&sdata->local->hw, + IEEE80211_QUEUE_STOP_REASON_CHTYPE_CHANGE); + ht_opmode = le16_to_cpu(hti->operation_mode); /* if bss configuration changed store the new one */ @@ -1399,7 +1400,6 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, struct ieee80211_local *local = sdata->local; struct sta_info *sta; u32 changed = 0; - u8 bssid[ETH_ALEN]; ASSERT_MGD_MTX(ifmgd); @@ -1409,10 +1409,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, if (WARN_ON(!ifmgd->associated)) return; - memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN); - ifmgd->associated = NULL; - memset(ifmgd->bssid, 0, ETH_ALEN); /* * we need to commit the associated = NULL change because the @@ -1432,7 +1429,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, netif_carrier_off(sdata->dev); mutex_lock(&local->sta_mtx); - sta = sta_info_get(sdata, bssid); + sta = sta_info_get(sdata, ifmgd->bssid); if (sta) { set_sta_flag(sta, WLAN_STA_BLOCK_BA); ieee80211_sta_tear_down_BA_sessions(sta, tx); @@ -1441,13 +1438,16 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, /* deauthenticate/disassociate now */ if (tx || frame_buf) - ieee80211_send_deauth_disassoc(sdata, bssid, stype, reason, - tx, frame_buf); + ieee80211_send_deauth_disassoc(sdata, ifmgd->bssid, stype, + reason, tx, frame_buf); /* flush out frame */ if (tx) drv_flush(local, false); + /* clear bssid only after building the needed mgmt frames */ + memset(ifmgd->bssid, 0, ETH_ALEN); + /* remove AP and TDLS peers */ sta_info_flush(local, sdata); diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index d64e285400a..c9b508ea9d6 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -2459,7 +2459,7 @@ ieee80211_rx_h_action_return(struct ieee80211_rx_data *rx) * frames that we didn't handle, including returning unknown * ones. For all other modes we will return them to the sender, * setting the 0x80 bit in the action category, as required by - * 802.11-2007 7.3.1.11. + * 802.11-2012 9.24.4. * Newer versions of hostapd shall also use the management frame * registration mechanisms, but older ones still use cooked * monitor interfaces so push all frames there. @@ -2469,6 +2469,9 @@ ieee80211_rx_h_action_return(struct ieee80211_rx_data *rx) sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) return RX_DROP_MONITOR; + if (is_multicast_ether_addr(mgmt->da)) + return RX_DROP_MONITOR; + /* do not return rejected action frames */ if (mgmt->u.action.category & 0x80) return RX_DROP_UNUSABLE; diff --git a/net/nfc/nci/ntf.c b/net/nfc/nci/ntf.c index 2e3dee42196..e460cf13c56 100644 --- a/net/nfc/nci/ntf.c +++ b/net/nfc/nci/ntf.c @@ -106,7 +106,7 @@ static __u8 *nci_extract_rf_params_nfca_passive_poll(struct nci_dev *ndev, nfca_poll->sens_res = __le16_to_cpu(*((__u16 *)data)); data += 2; - nfca_poll->nfcid1_len = *data++; + nfca_poll->nfcid1_len = min_t(__u8, *data++, NFC_NFCID1_MAXSIZE); pr_debug("sens_res 0x%x, nfcid1_len %d\n", nfca_poll->sens_res, nfca_poll->nfcid1_len); @@ -130,7 +130,7 @@ static __u8 *nci_extract_rf_params_nfcb_passive_poll(struct nci_dev *ndev, struct rf_tech_specific_params_nfcb_poll *nfcb_poll, __u8 *data) { - nfcb_poll->sensb_res_len = *data++; + nfcb_poll->sensb_res_len = min_t(__u8, *data++, NFC_SENSB_RES_MAXSIZE); pr_debug("sensb_res_len %d\n", nfcb_poll->sensb_res_len); @@ -145,7 +145,7 @@ static __u8 *nci_extract_rf_params_nfcf_passive_poll(struct nci_dev *ndev, __u8 *data) { nfcf_poll->bit_rate = *data++; - nfcf_poll->sensf_res_len = *data++; + nfcf_poll->sensf_res_len = min_t(__u8, *data++, NFC_SENSF_RES_MAXSIZE); pr_debug("bit_rate %d, sensf_res_len %d\n", nfcf_poll->bit_rate, nfcf_poll->sensf_res_len); @@ -331,7 +331,7 @@ static int nci_extract_activation_params_iso_dep(struct nci_dev *ndev, switch (ntf->activation_rf_tech_and_mode) { case NCI_NFC_A_PASSIVE_POLL_MODE: nfca_poll = &ntf->activation_params.nfca_poll_iso_dep; - nfca_poll->rats_res_len = *data++; + nfca_poll->rats_res_len = min_t(__u8, *data++, 20); pr_debug("rats_res_len %d\n", nfca_poll->rats_res_len); if (nfca_poll->rats_res_len > 0) { memcpy(nfca_poll->rats_res, @@ -341,7 +341,7 @@ static int nci_extract_activation_params_iso_dep(struct nci_dev *ndev, case NCI_NFC_B_PASSIVE_POLL_MODE: nfcb_poll = &ntf->activation_params.nfcb_poll_iso_dep; - nfcb_poll->attrib_res_len = *data++; + nfcb_poll->attrib_res_len = min_t(__u8, *data++, 50); pr_debug("attrib_res_len %d\n", nfcb_poll->attrib_res_len); if (nfcb_poll->attrib_res_len > 0) { memcpy(nfcb_poll->attrib_res, diff --git a/net/nfc/rawsock.c b/net/nfc/rawsock.c index 5a839ceb2e8..e879dce5281 100644 --- a/net/nfc/rawsock.c +++ b/net/nfc/rawsock.c @@ -54,7 +54,10 @@ static int rawsock_release(struct socket *sock) { struct sock *sk = sock->sk; - pr_debug("sock=%p\n", sock); + pr_debug("sock=%p sk=%p\n", sock, sk); + + if (!sk) + return 0; sock_orphan(sk); sock_put(sk); diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c index 78ac39fd9fe..4c38b33ab8a 100644 --- a/net/sunrpc/rpcb_clnt.c +++ b/net/sunrpc/rpcb_clnt.c @@ -180,14 +180,16 @@ void rpcb_put_local(struct net *net) struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); struct rpc_clnt *clnt = sn->rpcb_local_clnt; struct rpc_clnt *clnt4 = sn->rpcb_local_clnt4; - int shutdown; + int shutdown = 0; spin_lock(&sn->rpcb_clnt_lock); - if (--sn->rpcb_users == 0) { - sn->rpcb_local_clnt = NULL; - sn->rpcb_local_clnt4 = NULL; + if (sn->rpcb_users) { + if (--sn->rpcb_users == 0) { + sn->rpcb_local_clnt = NULL; + sn->rpcb_local_clnt4 = NULL; + } + shutdown = !sn->rpcb_users; } - shutdown = !sn->rpcb_users; spin_unlock(&sn->rpcb_clnt_lock); if (shutdown) { diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index 234ee39000a..cb7c13fc485 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c @@ -407,6 +407,14 @@ static int svc_uses_rpcbind(struct svc_serv *serv) return 0; } +int svc_bind(struct svc_serv *serv, struct net *net) +{ + if (!svc_uses_rpcbind(serv)) + return 0; + return svc_rpcb_setup(serv, net); +} +EXPORT_SYMBOL_GPL(svc_bind); + /* * Create an RPC service */ @@ -471,15 +479,8 @@ __svc_create(struct svc_program *prog, unsigned int bufsize, int npools, spin_lock_init(&pool->sp_lock); } - if (svc_uses_rpcbind(serv)) { - if (svc_rpcb_setup(serv, current->nsproxy->net_ns) < 0) { - kfree(serv->sv_pools); - kfree(serv); - return NULL; - } - if (!serv->sv_shutdown) - serv->sv_shutdown = svc_rpcb_cleanup; - } + if (svc_uses_rpcbind(serv) && (!serv->sv_shutdown)) + serv->sv_shutdown = svc_rpcb_cleanup; return serv; } @@ -536,8 +537,6 @@ EXPORT_SYMBOL_GPL(svc_shutdown_net); void svc_destroy(struct svc_serv *serv) { - struct net *net = current->nsproxy->net_ns; - dprintk("svc: svc_destroy(%s, %d)\n", serv->sv_program->pg_name, serv->sv_nrthreads); @@ -552,8 +551,6 @@ svc_destroy(struct svc_serv *serv) del_timer_sync(&serv->sv_temptimer); - svc_shutdown_net(serv, net); - /* * The last user is gone and thus all sockets have to be destroyed to * the point. Check this. diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 165937663d3..1078e07da2a 100755 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -1389,7 +1389,7 @@ static void reg_set_request_processed(void) spin_unlock(®_requests_lock); if (last_request->initiator == NL80211_REGDOM_SET_BY_USER) - cancel_delayed_work_sync(®_timeout); + cancel_delayed_work(®_timeout); if (need_more_processing) schedule_work(®_work); diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 841475cc13b..926b455392c 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -1192,6 +1192,7 @@ static void snd_hda_codec_free(struct hda_codec *codec) { if (!codec) return; + snd_hda_jack_tbl_clear(codec); restore_init_pincfgs(codec); #ifdef CONFIG_SND_HDA_POWER_SAVE cancel_delayed_work(&codec->power_work); @@ -1200,6 +1201,7 @@ static void snd_hda_codec_free(struct hda_codec *codec) list_del(&codec->list); snd_array_free(&codec->mixers); snd_array_free(&codec->nids); + snd_array_free(&codec->cvt_setups); snd_array_free(&codec->conn_lists); snd_array_free(&codec->spdif_out); codec->bus->caddr_tbl[codec->addr] = NULL; diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index e56c2c817e0..c43264f5981 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -6976,6 +6976,7 @@ static const struct hda_codec_preset snd_hda_preset_realtek[] = { { .id = 0x10ec0272, .name = "ALC272", .patch = patch_alc662 }, { .id = 0x10ec0275, .name = "ALC275", .patch = patch_alc269 }, { .id = 0x10ec0276, .name = "ALC276", .patch = patch_alc269 }, + { .id = 0x10ec0280, .name = "ALC280", .patch = patch_alc269 }, { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660", .patch = patch_alc861 }, { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd }, diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 2cb1e08f962..7494fbc1f26 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -4388,7 +4388,7 @@ static int stac92xx_init(struct hda_codec *codec) AC_PINCTL_IN_EN); for (i = 0; i < spec->num_pwrs; i++) { hda_nid_t nid = spec->pwr_nids[i]; - int pinctl, def_conf; + unsigned int pinctl, def_conf; /* power on when no jack detection is available */ /* or when the VREF is used for controlling LED */ @@ -4415,7 +4415,7 @@ static int stac92xx_init(struct hda_codec *codec) def_conf = get_defcfg_connect(def_conf); /* skip any ports that don't have jacks since presence * detection is useless */ - if (def_conf != AC_JACK_PORT_NONE && + if (def_conf != AC_JACK_PORT_COMPLEX || !is_jack_detectable(codec, nid)) { stac_toggle_power_map(codec, nid, 1); continue; diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index 8d20f6ec20f..b8f0262ac3e 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c @@ -936,9 +936,7 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream, } found: - data = snd_soc_read(codec, AIC3X_PLL_PROGA_REG); - snd_soc_write(codec, AIC3X_PLL_PROGA_REG, - data | (pll_p << PLLP_SHIFT)); + snd_soc_update_bits(codec, AIC3X_PLL_PROGA_REG, PLLP_MASK, pll_p); snd_soc_write(codec, AIC3X_OVRF_STATUS_AND_PLLR_REG, pll_r << PLLR_SHIFT); snd_soc_write(codec, AIC3X_PLL_PROGB_REG, pll_j << PLLJ_SHIFT); diff --git a/sound/soc/codecs/tlv320aic3x.h b/sound/soc/codecs/tlv320aic3x.h index 6f097fb6068..08c7f6685ff 100644 --- a/sound/soc/codecs/tlv320aic3x.h +++ b/sound/soc/codecs/tlv320aic3x.h @@ -166,6 +166,7 @@ /* PLL registers bitfields */ #define PLLP_SHIFT 0 +#define PLLP_MASK 7 #define PLLQ_SHIFT 3 #define PLLR_SHIFT 0 #define PLLJ_SHIFT 2 diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c index acbdc5fde92..32682c1b7cd 100644 --- a/sound/soc/codecs/wm2200.c +++ b/sound/soc/codecs/wm2200.c @@ -1491,6 +1491,7 @@ static int wm2200_bclk_rates_dat[WM2200_NUM_BCLK_RATES] = { static int wm2200_bclk_rates_cd[WM2200_NUM_BCLK_RATES] = { 5644800, + 3763200, 2882400, 1881600, 1411200, diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c index 146fd6147e8..d9834b36294 100644 --- a/tools/hv/hv_kvp_daemon.c +++ b/tools/hv/hv_kvp_daemon.c @@ -701,14 +701,18 @@ int main(void) pfd.fd = fd; while (1) { + struct sockaddr *addr_p = (struct sockaddr *) &addr; + socklen_t addr_l = sizeof(addr); pfd.events = POLLIN; pfd.revents = 0; poll(&pfd, 1, -1); - len = recv(fd, kvp_recv_buffer, sizeof(kvp_recv_buffer), 0); + len = recvfrom(fd, kvp_recv_buffer, sizeof(kvp_recv_buffer), 0, + addr_p, &addr_l); - if (len < 0) { - syslog(LOG_ERR, "recv failed; error:%d", len); + if (len < 0 || addr.nl_pid) { + syslog(LOG_ERR, "recvfrom failed; pid:%u error:%d %s", + addr.nl_pid, errno, strerror(errno)); close(fd); return -1; } From c17cb403df29b6ff8403922dc4e0bb9a3ba1890d Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Sat, 21 Dec 2013 10:18:46 +0100 Subject: [PATCH 075/215] ARM: 7583/1: decompressor: Enable unaligned memory access Modern GCC can generate code which makes use of the CPU's native unaligned memory access capabilities. This is useful for the C decompressor implementations used for unpacking compressed kernels. This patch disables alignment faults and enables the v6 unaligned access model on CPUs which support these features (i.e., v6 and later), allowing full unaligned access support for C code in the decompressor. The decompressor C code must not be built to assume that unaligned access works if support for v5 or older platforms is included in the kernel. For correct code generation, C decompressor code must always use the get_unaligned and put_unaligned accessors when dealing with unaligned pointers, regardless of this patch. Signed-off-by: Dave Martin Acked-by: Nicolas Pitre Signed-off-by: Russell King Glitched-off-by: Tk-Glitch --- arch/arm/boot/compressed/head.S | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index f6fa5df63fc..06fa42db311 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S @@ -710,6 +710,15 @@ __setup_mmu: sub r3, r4, #16384 @ Page directory size mov pc, lr ENDPROC(__setup_mmu) +@ Enable unaligned access on v6, to allow better code generation +@ for the decompressor C code: +__armv6_mmu_cache_on: + mrc p15, 0, r0, c1, c0, 0 @ read SCTLR + bic r0, r0, #2 @ A (no unaligned access fault) + orr r0, r0, #1 << 22 @ U (v6 unaligned access model) + mcr p15, 0, r0, c1, c0, 0 @ write SCTLR + b __armv4_mmu_cache_on + __arm926ejs_mmu_cache_on: #ifdef CONFIG_CPU_DCACHE_WRITETHROUGH mov r0, #4 @ put dcache in WT mode @@ -751,6 +760,9 @@ __armv7_mmu_cache_on: mrc p15, 0, r0, c1, c0, 0 @ read control reg orr r0, r0, #0x5000 @ I-cache enable, RR cache replacement orr r0, r0, #0x003c @ write buffer + bic r0, r0, #2 @ A (no unaligned access fault) + orr r0, r0, #1 << 22 @ U (v6 unaligned access model) + @ (needed for ARM1176) #ifdef CONFIG_MMU #ifdef CONFIG_CPU_ENDIAN_BE8 orr r0, r0, #1 << 25 @ big-endian page tables @@ -991,7 +1003,7 @@ proc_types: .word 0x0007b000 @ ARMv6 .word 0x000ff000 - W(b) __armv4_mmu_cache_on + W(b) __armv6_mmu_cache_on W(b) __armv4_mmu_cache_off W(b) __armv6_mmu_cache_flush From c20ecac9c2434ed2690c0a48d9b8ac144172442d Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Sat, 21 Dec 2013 10:20:12 +0100 Subject: [PATCH 076/215] arch/arm/Kconfig: enable unaligned capability for ARM Signed-off-by: faux123 Signed-off-by: Tk-Glitch --- arch/arm/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index d7e3e4364f0..50752e996c3 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -20,6 +20,7 @@ config ARM #select HAVE_DYNAMIC_FTRACE if (!XIP_KERNEL) #select HAVE_FUNCTION_GRAPH_TRACER if (!THUMB2_KERNEL) select ARCH_BINFMT_ELF_RANDOMIZE_PIE + select HAVE_EFFICIENT_UNALIGNED_ACCESS select HAVE_GENERIC_DMA_COHERENT select HAVE_KERNEL_GZIP select HAVE_KERNEL_LZO From 7787981b895324db61ce4b4f51f1bd4b82b36736 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Sat, 21 Dec 2013 10:21:12 +0100 Subject: [PATCH 077/215] sched: Add sysinterface for GENTLE_FAIR_SLEEPERS Signed-off-by: Pranav Vashi --- kernel/ksysfs.c | 43 +++++++++++++++++++++++++++++++++++++++++++ kernel/sched/fair.c | 8 +++++++- 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/kernel/ksysfs.c b/kernel/ksysfs.c index 4e316e1acf5..1c08175a90c 100644 --- a/kernel/ksysfs.c +++ b/kernel/ksysfs.c @@ -189,9 +189,46 @@ static struct attribute_group kernel_attr_group = { .attrs = kernel_attrs, }; + +static unsigned int Lgentle_fair_sleepers = 1; +extern void relay_gfs(unsigned int gfs); + +static ssize_t gentle_fair_sleepers_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) +{ + return sprintf(buf, "%u\n", Lgentle_fair_sleepers); +} +static ssize_t gentle_fair_sleepers_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) +{ + unsigned int input; + int ret, cpu; + ret = sscanf(buf, "%u", &input); + if (input != 0 && input != 1) + input = 0; + + Lgentle_fair_sleepers = input; + relay_gfs(Lgentle_fair_sleepers); + return count; +} + +static struct kobj_attribute gentle_fair_sleepers_attribute = +__ATTR(gentle_fair_sleepers, 0666, gentle_fair_sleepers_show, gentle_fair_sleepers_store); + +static struct attribute *gentle_fair_sleepers_attrs[] = { +&gentle_fair_sleepers_attribute.attr, +NULL, +}; + +static struct attribute_group gentle_fair_sleepers_attr_group = { +.attrs = gentle_fair_sleepers_attrs, +}; + +/* Initialize fast charge sysfs folder */ +static struct kobject *gentle_fair_sleepers_kobj; + static int __init ksysfs_init(void) { int error; + int retval; kernel_kobj = kobject_create_and_add("kernel", NULL); if (!kernel_kobj) { @@ -202,6 +239,12 @@ static int __init ksysfs_init(void) if (error) goto kset_exit; + gentle_fair_sleepers_kobj = kobject_create_and_add("sched", kernel_kobj); + retval = sysfs_create_group(gentle_fair_sleepers_kobj, &gentle_fair_sleepers_attr_group); + + if (retval) + kobject_put(gentle_fair_sleepers_kobj); + if (notes_size > 0) { notes_attr.size = notes_size; error = sysfs_create_bin_file(kernel_kobj, ¬es_attr); diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 400f838dea1..6172320383b 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -1046,6 +1046,12 @@ static void check_spread(struct cfs_rq *cfs_rq, struct sched_entity *se) #endif } +static unsigned int Lgentle_fair_sleepers = 1; +void relay_gfs(unsigned int gfs) +{ + Lgentle_fair_sleepers = gfs; +} + static void place_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int initial) { @@ -1068,7 +1074,7 @@ place_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int initial) * Halve their sleep time's effect, to allow * for a gentler effect of sleepers: */ - if (sched_feat(GENTLE_FAIR_SLEEPERS)) + if (Lgentle_fair_sleepers) thresh >>= 1; vruntime -= thresh; From 24028effa454a864a67e9c0436ae8127e1b1e39c Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Sat, 21 Dec 2013 10:29:42 +0100 Subject: [PATCH 078/215] kernel: Move REPEAT_BYTE definition into linux/kernel.h And make sure that everything using it explicitly includes that header file. Signed-off-by: David S. Miller modified for Mako kernel from kernel.org Signed-off-by: faux123 --- arch/x86/include/asm/word-at-a-time.h | 4 ++-- fs/namei.c | 1 + include/linux/kernel.h | 2 ++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/word-at-a-time.h b/arch/x86/include/asm/word-at-a-time.h index e58f03b206c..ae03facfadd 100644 --- a/arch/x86/include/asm/word-at-a-time.h +++ b/arch/x86/include/asm/word-at-a-time.h @@ -1,6 +1,8 @@ #ifndef _ASM_WORD_AT_A_TIME_H #define _ASM_WORD_AT_A_TIME_H +#include + /* * This is largely generic for little-endian machines, but the * optimal byte mask counting is probably going to be something @@ -35,8 +37,6 @@ static inline long count_masked_bytes(long mask) #endif -#define REPEAT_BYTE(x) ((~0ul / 0xff) * (x)) - /* Return the high bit set in the first byte that is a zero */ static inline unsigned long has_zero(unsigned long a) { diff --git a/fs/namei.c b/fs/namei.c index 4a353b8aad1..f17574cc7fc 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -16,6 +16,7 @@ #include #include +#include #include #include #include diff --git a/include/linux/kernel.h b/include/linux/kernel.h index 2d2e1eee550..447bd194f4c 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -38,6 +38,8 @@ #define STACK_MAGIC 0xdeadbeef +#define REPEAT_BYTE(x) ((~0ul / 0xff) * (x)) + #define ALIGN(x, a) __ALIGN_KERNEL((x), (a)) #define __ALIGN_MASK(x, mask) __ALIGN_KERNEL_MASK((x), (mask)) #define PTR_ALIGN(p, a) ((typeof(p))ALIGN((unsigned long)(p), (a))) From bc22792c5f34bf13066591b5125b5da12f3ef192 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Sat, 21 Dec 2013 10:37:30 +0100 Subject: [PATCH 079/215] ARM: 7493/1: use generic unaligned.h This moves ARM over to the asm-generic/unaligned.h header. This has the benefit of better code generated especially for ARMv7 on gcc 4.7+ compilers. As Arnd Bergmann, points out: The asm-generic version uses the "struct" version for native-endian unaligned access and the "byteshift" version for the opposite endianess. The current ARM version however uses the "byteshift" implementation for both. Thanks to Nicolas Pitre for the excellent analysis: Test case: int foo (int *x) { return get_unaligned(x); } long long bar (long long *x) { return get_unaligned(x); } With the current ARM version: foo: ldrb r3, [r0, #2] @ zero_extendqisi2 @ MEM[(const u8 *)x_1(D) + 2B], MEM[(const u8 *)x_1(D) + 2B] ldrb r1, [r0, #1] @ zero_extendqisi2 @ MEM[(const u8 *)x_1(D) + 1B], MEM[(const u8 *)x_1(D) + 1B] ldrb r2, [r0, #0] @ zero_extendqisi2 @ MEM[(const u8 *)x_1(D)], MEM[(const u8 *)x_1(D)] mov r3, r3, asl #16 @ tmp154, MEM[(const u8 *)x_1(D) + 2B], ldrb r0, [r0, #3] @ zero_extendqisi2 @ MEM[(const u8 *)x_1(D) + 3B], MEM[(const u8 *)x_1(D) + 3B] orr r3, r3, r1, asl #8 @, tmp155, tmp154, MEM[(const u8 *)x_1(D) + 1B], orr r3, r3, r2 @ tmp157, tmp155, MEM[(const u8 *)x_1(D)] orr r0, r3, r0, asl #24 @,, tmp157, MEM[(const u8 *)x_1(D) + 3B], bx lr @ bar: stmfd sp!, {r4, r5, r6, r7} @, mov r2, #0 @ tmp184, ldrb r5, [r0, #6] @ zero_extendqisi2 @ MEM[(const u8 *)x_1(D) + 6B], MEM[(const u8 *)x_1(D) + 6B] ldrb r4, [r0, #5] @ zero_extendqisi2 @ MEM[(const u8 *)x_1(D) + 5B], MEM[(const u8 *)x_1(D) + 5B] ldrb ip, [r0, #2] @ zero_extendqisi2 @ MEM[(const u8 *)x_1(D) + 2B], MEM[(const u8 *)x_1(D) + 2B] ldrb r1, [r0, #4] @ zero_extendqisi2 @ MEM[(const u8 *)x_1(D) + 4B], MEM[(const u8 *)x_1(D) + 4B] mov r5, r5, asl #16 @ tmp175, MEM[(const u8 *)x_1(D) + 6B], ldrb r7, [r0, #1] @ zero_extendqisi2 @ MEM[(const u8 *)x_1(D) + 1B], MEM[(const u8 *)x_1(D) + 1B] orr r5, r5, r4, asl #8 @, tmp176, tmp175, MEM[(const u8 *)x_1(D) + 5B], ldrb r6, [r0, #7] @ zero_extendqisi2 @ MEM[(const u8 *)x_1(D) + 7B], MEM[(const u8 *)x_1(D) + 7B] orr r5, r5, r1 @ tmp178, tmp176, MEM[(const u8 *)x_1(D) + 4B] ldrb r4, [r0, #0] @ zero_extendqisi2 @ MEM[(const u8 *)x_1(D)], MEM[(const u8 *)x_1(D)] mov ip, ip, asl #16 @ tmp188, MEM[(const u8 *)x_1(D) + 2B], ldrb r1, [r0, #3] @ zero_extendqisi2 @ MEM[(const u8 *)x_1(D) + 3B], MEM[(const u8 *)x_1(D) + 3B] orr ip, ip, r7, asl #8 @, tmp189, tmp188, MEM[(const u8 *)x_1(D) + 1B], orr r3, r5, r6, asl #24 @,, tmp178, MEM[(const u8 *)x_1(D) + 7B], orr ip, ip, r4 @ tmp191, tmp189, MEM[(const u8 *)x_1(D)] orr ip, ip, r1, asl #24 @, tmp194, tmp191, MEM[(const u8 *)x_1(D) + 3B], mov r1, r3 @, orr r0, r2, ip @ tmp171, tmp184, tmp194 ldmfd sp!, {r4, r5, r6, r7} bx lr In both cases the code is slightly suboptimal. One may wonder why wasting r2 with the constant 0 in the second case for example. And all the mov's could be folded in subsequent orr's, etc. Now with the asm-generic version: foo: ldr r0, [r0, #0] @ unaligned @,* x bx lr @ bar: mov r3, r0 @ x, x ldr r0, [r0, #0] @ unaligned @,* x ldr r1, [r3, #4] @ unaligned @, bx lr @ This is way better of course, but only because this was compiled for ARMv7. In this case the compiler knows that the hardware can do unaligned word access. This isn't that obvious for foo(), but if we remove the get_unaligned() from bar as follows: long long bar (long long *x) {return *x; } then the resulting code is: bar: ldmia r0, {r0, r1} @ x,, bx lr @ So this proves that the presumed aligned vs unaligned cases does have influence on the instructions the compiler may use and that the above unaligned code results are not just an accident. Still... this isn't fully conclusive without at least looking at the resulting assembly fron a pre ARMv6 compilation. Let's see with an ARMv5 target: foo: ldrb r3, [r0, #0] @ zero_extendqisi2 @ tmp139,* x ldrb r1, [r0, #1] @ zero_extendqisi2 @ tmp140, ldrb r2, [r0, #2] @ zero_extendqisi2 @ tmp143, ldrb r0, [r0, #3] @ zero_extendqisi2 @ tmp146, orr r3, r3, r1, asl #8 @, tmp142, tmp139, tmp140, orr r3, r3, r2, asl #16 @, tmp145, tmp142, tmp143, orr r0, r3, r0, asl #24 @,, tmp145, tmp146, bx lr @ bar: stmfd sp!, {r4, r5, r6, r7} @, ldrb r2, [r0, #0] @ zero_extendqisi2 @ tmp139,* x ldrb r7, [r0, #1] @ zero_extendqisi2 @ tmp140, ldrb r3, [r0, #4] @ zero_extendqisi2 @ tmp149, ldrb r6, [r0, #5] @ zero_extendqisi2 @ tmp150, ldrb r5, [r0, #2] @ zero_extendqisi2 @ tmp143, ldrb r4, [r0, #6] @ zero_extendqisi2 @ tmp153, ldrb r1, [r0, #7] @ zero_extendqisi2 @ tmp156, ldrb ip, [r0, #3] @ zero_extendqisi2 @ tmp146, orr r2, r2, r7, asl #8 @, tmp142, tmp139, tmp140, orr r3, r3, r6, asl #8 @, tmp152, tmp149, tmp150, orr r2, r2, r5, asl #16 @, tmp145, tmp142, tmp143, orr r3, r3, r4, asl #16 @, tmp155, tmp152, tmp153, orr r0, r2, ip, asl #24 @,, tmp145, tmp146, orr r1, r3, r1, asl #24 @,, tmp155, tmp156, ldmfd sp!, {r4, r5, r6, r7} bx lr Compared to the initial results, this is really nicely optimized and I couldn't do much better if I were to hand code it myself. Signed-off-by: Rob Herring Reviewed-by: Nicolas Pitre Tested-by: Thomas Petazzoni Reviewed-by: Arnd Bergmann Signed-off-by: Russell King modified for Mako from kernel.org reference --- arch/arm/include/asm/Kbuild | 1 + arch/arm/include/asm/unaligned.h | 19 ------------------- 2 files changed, 1 insertion(+), 19 deletions(-) delete mode 100644 arch/arm/include/asm/unaligned.h diff --git a/arch/arm/include/asm/Kbuild b/arch/arm/include/asm/Kbuild index 960abceb8e1..2312fe5b9b0 100644 --- a/arch/arm/include/asm/Kbuild +++ b/arch/arm/include/asm/Kbuild @@ -18,3 +18,4 @@ generic-y += resource.h generic-y += sections.h generic-y += siginfo.h generic-y += sizes.h +generic-y += unaligned.h diff --git a/arch/arm/include/asm/unaligned.h b/arch/arm/include/asm/unaligned.h deleted file mode 100644 index 44593a89490..00000000000 --- a/arch/arm/include/asm/unaligned.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef _ASM_ARM_UNALIGNED_H -#define _ASM_ARM_UNALIGNED_H - -#include -#include -#include - -/* - * Select endianness - */ -#ifndef __ARMEB__ -#define get_unaligned __get_unaligned_le -#define put_unaligned __put_unaligned_le -#else -#define get_unaligned __get_unaligned_be -#define put_unaligned __put_unaligned_be -#endif - -#endif /* _ASM_ARM_UNALIGNED_H */ From 1ecf1fc89284abd26cca8e0d9c1285e38c200a1c Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Sat, 21 Dec 2013 10:39:11 +0100 Subject: [PATCH 080/215] ARM: 7592/1: nommu: prevent generation of kernel unaligned memory accesses Recent ARMv7 toolchains assume that unaligned memory accesses will not fault and will instead be handled by the processor. For the nommu case (without an MPU), memory will be treated as strongly-ordered and therefore unaligned accesses may fault regardless of the SCTLR.A setting. This patch passes -mno-unaligned-access to GCC when compiling for nommu targets, preventing the generation of unaligned memory access in the kernel. Acked-by: Nicolas Pitre Tested-by: Jonathan Austin Signed-off-by: Will Deacon Signed-off-by: Russell King Signed-off-by: Tk-Glitch --- arch/arm/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 79a8ea6e4ed..ca3dcb51dde 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -31,6 +31,7 @@ KBUILD_DEFCONFIG := versatile_defconfig # defines filename extension depending memory management type. ifeq ($(CONFIG_MMU),) MMUEXT := -nommu +KBUILD_CFLAGS += $(call cc-option,-mno-unaligned-access) endif ifeq ($(CONFIG_CC_STACKPROTECTOR),y) From 3d19f5a200113c0a1b4f11c82dccc87b496ea9f5 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Sat, 21 Dec 2013 11:10:05 +0100 Subject: [PATCH 081/215] Fix derp --- arch/arm/mm/mmu.c | 73 ----------------------------------------------- 1 file changed, 73 deletions(-) diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 275979be531..da33be0f13c 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -912,79 +912,6 @@ static void __init fill_pmd_gaps(void) #define fill_pmd_gaps() do { } while (0) #endif -#ifndef CONFIG_ARM_LPAE - -/* - * The Linux PMD is made of two consecutive section entries covering 2MB - * (see definition in include/asm/pgtable-2level.h). However a call to - * create_mapping() may optimize static mappings by using individual - * 1MB section mappings. This leaves the actual PMD potentially half - * initialized if the top or bottom section entry isn't used, leaving it - * open to problems if a subsequent ioremap() or vmalloc() tries to use - * the virtual space left free by that unused section entry. - * - * Let's avoid the issue by inserting dummy vm entries covering the unused - * PMD halves once the static mappings are in place. - */ - -static void __init pmd_empty_section_gap(unsigned long addr) -{ - struct vm_struct *vm; - - vm = early_alloc_aligned(sizeof(*vm), __alignof__(*vm)); - vm->addr = (void *)addr; - vm->size = SECTION_SIZE; - vm->flags = VM_IOREMAP | VM_ARM_STATIC_MAPPING; - vm->caller = pmd_empty_section_gap; - vm_area_add_early(vm); -} - -static void __init fill_pmd_gaps(void) -{ - struct vm_struct *vm; - unsigned long addr, next = 0; - pmd_t *pmd; - - /* we're still single threaded hence no lock needed here */ - for (vm = vmlist; vm; vm = vm->next) { - if (!(vm->flags & VM_ARM_STATIC_MAPPING)) - continue; - addr = (unsigned long)vm->addr; - if (addr < next) - continue; - - /* - * Check if this vm starts on an odd section boundary. - * If so and the first section entry for this PMD is free - * then we block the corresponding virtual address. - */ - if ((addr & ~PMD_MASK) == SECTION_SIZE) { - pmd = pmd_off_k(addr); - if (pmd_none(*pmd)) - pmd_empty_section_gap(addr & PMD_MASK); - } - - /* - * Then check if this vm ends on an odd section boundary. - * If so and the second section entry for this PMD is empty - * then we block the corresponding virtual address. - */ - addr += vm->size; - if ((addr & ~PMD_MASK) == SECTION_SIZE) { - pmd = pmd_off_k(addr) + 1; - if (pmd_none(*pmd)) - pmd_empty_section_gap(addr); - } - - /* no need to look at any vm entry until we hit the next PMD */ - next = (addr + PMD_SIZE - 1) & PMD_MASK; - } -} - -#else -#define fill_pmd_gaps() do { } while (0) -#endif - static void * __initdata vmalloc_min = (void *)(VMALLOC_END - (240 << 20) - VMALLOC_OFFSET); From c5872a7e3a13f7bfac5a648c51505daffdbb309e Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Sat, 21 Dec 2013 11:10:57 +0100 Subject: [PATCH 082/215] defconfig : Update defconfig --- arch/arm/configs/flo_defconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/configs/flo_defconfig b/arch/arm/configs/flo_defconfig index 04c5a8cdb57..2e12f55da20 100644 --- a/arch/arm/configs/flo_defconfig +++ b/arch/arm/configs/flo_defconfig @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/arm 3.4.1 Kernel Configuration +# Linux/arm 3.4.5 Kernel Configuration # CONFIG_ARM=y CONFIG_ARM_HAS_SG_CHAIN=y @@ -163,6 +163,7 @@ CONFIG_PROFILING=y CONFIG_HAVE_OPROFILE=y # CONFIG_KPROBES is not set # CONFIG_JUMP_LABEL is not set +CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y CONFIG_HAVE_KPROBES=y CONFIG_HAVE_KRETPROBES=y CONFIG_HAVE_DMA_ATTRS=y From aa005ddcfaf9bcbb82a4281b22e6e7c5d32c63a8 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Sat, 21 Dec 2013 15:43:57 +0100 Subject: [PATCH 083/215] Linux 3.4.6 - 3.4.30 --- Documentation/ABI/testing/sysfs-bus-rbd | 6 - Documentation/cgroups/memory.txt | 4 + .../devicetree/bindings/arm/atmel-at91.txt | 2 +- Documentation/dvb/get_dvb_firmware | 2 +- Documentation/i2c/busses/i2c-i801 | 1 + Documentation/networking/ip-sysctl.txt | 5 + Documentation/sound/alsa/HD-Audio-Models.txt | 4 +- Documentation/stable_kernel_rules.txt | 19 +- Documentation/workqueue.txt | 103 +- MAINTAINERS | 2 +- Makefile | 2 +- arch/alpha/include/asm/atomic.h | 4 +- arch/alpha/include/asm/fpu.h | 2 + arch/alpha/include/asm/socket.h | 2 + arch/alpha/kernel/process.c | 4 + arch/arm/Kconfig | 12 + arch/arm/boot/compressed/head.S | 1 + arch/arm/boot/dts/imx53-ard.dts | 20 + arch/arm/configs/mxs_defconfig | 1 - arch/arm/include/asm/cacheflush.h | 8 +- arch/arm/include/asm/hwcap.h | 3 +- arch/arm/include/asm/mutex.h | 3 +- arch/arm/include/asm/pgtable.h | 40 +- arch/arm/include/asm/vfpmacros.h | 12 +- arch/arm/kernel/entry-armv.S | 111 +- arch/arm/kernel/hw_breakpoint.c | 55 +- arch/arm/kernel/process.c | 2 + arch/arm/kernel/smp.c | 14 +- arch/arm/kernel/swp_emulate.c | 2 + arch/arm/kernel/traps.c | 19 +- arch/arm/mach-at91/at91rm9200_devices.c | 2 +- arch/arm/mach-at91/at91sam9260_devices.c | 2 +- arch/arm/mach-at91/at91sam9261_devices.c | 2 +- arch/arm/mach-at91/at91sam9263_devices.c | 2 +- arch/arm/mach-at91/at91sam9rl_devices.c | 2 +- arch/arm/mach-at91/setup.c | 4 +- arch/arm/mach-dove/include/mach/pm.h | 2 +- arch/arm/mach-dove/irq.c | 14 +- arch/arm/mach-imx/hotplug.c | 23 +- arch/arm/mach-kirkwood/pcie.c | 11 +- arch/arm/mach-omap2/opp.c | 3 +- arch/arm/mach-pxa/include/mach/mfp-pxa27x.h | 3 + arch/arm/mach-pxa/pxa27x.c | 4 +- arch/arm/mach-pxa/raumfeld.c | 2 +- .../arm/mach-realview/include/mach/board-eb.h | 2 +- arch/arm/mach-s3c24xx/include/mach/dma.h | 3 +- arch/arm/mm/cache-v7.S | 3 + arch/arm/mm/flush.c | 2 - arch/arm/mm/mmu.c | 2 +- arch/arm/plat-omap/counter_32k.c | 21 +- arch/arm/plat-omap/dmtimer.c | 2 +- arch/arm/plat-s3c24xx/dma.c | 2 +- arch/arm/plat-s5p/clock.c | 1 + arch/arm/plat-samsung/adc.c | 8 +- arch/arm/vfp/entry.S | 22 +- arch/arm/vfp/vfphw.S | 23 +- arch/arm/vfp/vfpmodule.c | 9 +- arch/cris/include/asm/io.h | 39 +- arch/cris/kernel/process.c | 3 + arch/frv/kernel/process.c | 3 + arch/h8300/kernel/process.c | 3 + arch/ia64/include/asm/atomic.h | 4 +- arch/ia64/kernel/process.c | 3 + arch/m32r/kernel/process.c | 3 + arch/m68k/include/asm/entry.h | 4 +- arch/m68k/include/asm/signal.h | 6 +- arch/m68k/kernel/process.c | 3 + arch/m68k/kernel/sys_m68k.c | 8 +- arch/mips/Makefile | 2 +- arch/mips/include/asm/thread_info.h | 4 +- arch/mips/kernel/Makefile | 2 +- arch/mips/kernel/kgdb.c | 9 + arch/mips/kernel/kspd.c | 2 +- arch/mips/kernel/process.c | 4 +- arch/mips/kernel/vmlinux.lds.S | 3 +- arch/mips/mm/gup.c | 2 + arch/mn10300/Makefile | 2 +- arch/mn10300/kernel/process.c | 3 + arch/parisc/include/asm/atomic.h | 4 +- arch/parisc/kernel/process.c | 3 + arch/parisc/kernel/signal32.c | 6 +- arch/parisc/kernel/sys_parisc.c | 2 + arch/powerpc/boot/dts/p1022ds.dtsi | 16 - arch/powerpc/include/asm/pci-bridge.h | 8 + arch/powerpc/include/asm/reg.h | 3 +- arch/powerpc/kernel/asm-offsets.c | 1 + arch/powerpc/kernel/dbell.c | 2 + arch/powerpc/kernel/entry_64.S | 23 +- arch/powerpc/kernel/ftrace.c | 12 +- arch/powerpc/kernel/head_64.S | 2 +- arch/powerpc/kernel/process.c | 12 +- arch/powerpc/kernel/smp.c | 11 +- arch/powerpc/kernel/sysfs.c | 10 + arch/powerpc/kernel/time.c | 5 - arch/powerpc/kernel/traps.c | 3 +- arch/powerpc/kvm/44x_emulate.c | 2 + arch/powerpc/platforms/40x/ppc40x_simple.c | 3 +- arch/powerpc/platforms/85xx/p1022_ds.c | 202 ++- arch/powerpc/platforms/pseries/eeh.c | 2 +- arch/powerpc/platforms/pseries/eeh_driver.c | 95 +- arch/powerpc/platforms/pseries/eeh_event.c | 6 +- arch/powerpc/sysdev/xics/icp-hv.c | 6 +- arch/s390/boot/compressed/vmlinux.lds.S | 2 +- arch/s390/include/asm/compat.h | 2 +- arch/s390/include/asm/mmu_context.h | 14 +- arch/s390/include/asm/processor.h | 2 + arch/s390/include/asm/ptrace.h | 4 +- arch/s390/include/asm/timex.h | 28 + arch/s390/kernel/compat_linux.c | 2 - arch/s390/kernel/compat_signal.c | 14 +- arch/s390/kernel/compat_wrapper.S | 4 +- arch/s390/kernel/processor.c | 2 + arch/s390/kernel/signal.c | 14 +- arch/s390/kernel/smp.c | 3 - arch/s390/kernel/time.c | 2 +- arch/s390/kernel/vmlinux.lds.S | 2 +- arch/s390/kvm/interrupt.c | 2 +- arch/s390/mm/fault.c | 13 +- arch/s390/mm/gup.c | 2 +- arch/s390/mm/mmap.c | 12 +- arch/s390/mm/pgtable.c | 5 - arch/s390/oprofile/init.c | 10 +- arch/score/kernel/process.c | 4 +- arch/sh/include/asm/elf.h | 4 +- arch/sparc/include/asm/hugetlb.h | 10 +- arch/sparc/kernel/perf_event.c | 15 +- arch/sparc/kernel/signal_64.c | 4 +- arch/sparc/kernel/sys_sparc_64.c | 10 +- arch/sparc/kernel/syscalls.S | 32 +- arch/sparc/mm/init_64.c | 28 +- arch/tile/Makefile | 4 + arch/x86/Makefile | 2 +- arch/x86/boot/compressed/Makefile | 3 + arch/x86/boot/compressed/eboot.c | 2 + arch/x86/ia32/ia32entry.S | 4 +- arch/x86/include/asm/efi.h | 1 + arch/x86/include/asm/fpu-internal.h | 15 +- arch/x86/include/asm/pgtable.h | 11 +- arch/x86/include/asm/ptrace.h | 15 +- arch/x86/include/asm/xen/page.h | 3 +- arch/x86/kernel/alternative.c | 4 +- arch/x86/kernel/cpu/amd.c | 28 + arch/x86/kernel/cpu/mcheck/mce.c | 6 +- arch/x86/kernel/e820.c | 3 + arch/x86/kernel/entry_32.S | 9 +- arch/x86/kernel/entry_64.S | 2 +- arch/x86/kernel/hpet.c | 4 +- arch/x86/kernel/microcode_amd.c | 11 +- arch/x86/kernel/microcode_core.c | 31 +- arch/x86/kernel/msr.c | 3 + arch/x86/kernel/ptrace.c | 30 + arch/x86/kernel/setup.c | 110 +- arch/x86/kernel/smpboot.c | 5 + arch/x86/kvm/cpuid.h | 3 + arch/x86/kvm/x86.c | 3 + arch/x86/mm/hugetlbpage.c | 21 +- arch/x86/mm/init.c | 69 +- arch/x86/oprofile/nmi_int.c | 2 +- arch/x86/pci/fixup.c | 17 + arch/x86/platform/efi/efi.c | 44 +- arch/x86/platform/efi/efi_64.c | 22 +- arch/x86/syscalls/syscall_64.tbl | 6 +- arch/x86/xen/enlighten.c | 18 +- arch/x86/xen/mmu.c | 21 +- arch/x86/xen/p2m.c | 63 +- arch/x86/xen/setup.c | 13 +- arch/xtensa/kernel/process.c | 3 + block/blk-core.c | 2 +- block/scsi_ioctl.c | 5 +- crypto/cryptd.c | 11 +- drivers/acpi/ac.c | 4 +- drivers/acpi/acpica/nspredef.c | 2 +- drivers/acpi/acpica/tbxface.c | 1 + drivers/acpi/apei/apei-base.c | 5 + drivers/acpi/battery.c | 77 ++ drivers/acpi/bus.c | 8 +- drivers/acpi/ec.c | 30 +- drivers/acpi/power.c | 36 +- drivers/acpi/processor_core.c | 6 +- drivers/acpi/processor_driver.c | 3 +- drivers/acpi/processor_idle.c | 4 + drivers/acpi/scan.c | 9 +- drivers/acpi/sleep.c | 340 ++--- drivers/acpi/video.c | 25 +- drivers/ata/ahci.c | 15 +- drivers/ata/libata-core.c | 2 + drivers/ata/libata-eh.c | 1 + drivers/ata/libata-scsi.c | 6 +- drivers/ata/sata_promise.c | 15 +- drivers/ata/sata_svw.c | 35 + drivers/atm/solos-pci.c | 5 +- drivers/base/power/main.c | 2 +- drivers/base/power/qos.c | 2 +- drivers/base/power/runtime.c | 5 +- drivers/base/regmap/regmap-debugfs.c | 2 +- drivers/bcma/driver_mips.c | 2 +- drivers/bcma/main.c | 5 +- drivers/block/aoe/aoe.h | 2 +- drivers/block/aoe/aoeblk.c | 5 - drivers/block/aoe/aoecmd.c | 1 + drivers/block/cciss_scsi.c | 12 +- drivers/block/drbd/drbd_req.c | 1 + drivers/block/floppy.c | 1 + drivers/block/nbd.c | 9 + drivers/block/nvme.c | 2 +- drivers/block/rbd.c | 322 ++--- drivers/block/xen-blkback/blkback.c | 2 +- drivers/bluetooth/ath3k.c | 4 + drivers/bluetooth/btusb.c | 17 + drivers/char/mspec.c | 2 +- drivers/char/random.c | 69 +- drivers/char/tpm/tpm.c | 33 +- drivers/char/ttyprintk.c | 2 +- drivers/clk/clk.c | 9 +- drivers/cpufreq/powernow-k8.c | 56 +- drivers/dma/at_hdmac.c | 13 +- drivers/dma/dmaengine.c | 2 +- drivers/dma/imx-dma.c | 4 +- drivers/dma/ioat/dma_v3.c | 2 +- drivers/dma/pl330.c | 21 +- drivers/dma/sirf-dma.c | 4 +- drivers/edac/amd64_edac.c | 11 +- drivers/edac/edac_pci_sysfs.c | 2 +- drivers/edac/i7300_edac.c | 8 +- drivers/firewire/core-cdev.c | 4 +- drivers/firewire/net.c | 13 +- drivers/firmware/dmi_scan.c | 81 +- drivers/firmware/efivars.c | 17 +- drivers/firmware/pcdp.c | 4 +- drivers/gpio/gpio-lpc32xx.c | 5 + drivers/gpio/gpio-timberdale.c | 4 +- drivers/gpio/gpiolib.c | 10 +- drivers/gpu/drm/drm_crtc.c | 10 +- drivers/gpu/drm/drm_edid.c | 22 +- drivers/gpu/drm/drm_fops.c | 5 +- drivers/gpu/drm/i915/i915_drv.c | 10 + drivers/gpu/drm/i915/i915_drv.h | 11 +- drivers/gpu/drm/i915/i915_gem.c | 4 +- drivers/gpu/drm/i915/i915_gem_execbuffer.c | 21 + drivers/gpu/drm/i915/i915_irq.c | 44 +- drivers/gpu/drm/i915/i915_reg.h | 26 +- drivers/gpu/drm/i915/intel_bios.c | 47 +- drivers/gpu/drm/i915/intel_crt.c | 36 +- drivers/gpu/drm/i915/intel_display.c | 232 ++-- drivers/gpu/drm/i915/intel_dp.c | 18 +- drivers/gpu/drm/i915/intel_drv.h | 6 +- drivers/gpu/drm/i915/intel_hdmi.c | 13 +- drivers/gpu/drm/i915/intel_lvds.c | 16 + drivers/gpu/drm/i915/intel_modes.c | 31 +- drivers/gpu/drm/i915/intel_overlay.c | 14 +- drivers/gpu/drm/i915/intel_ringbuffer.c | 22 +- drivers/gpu/drm/i915/intel_sdvo.c | 89 +- drivers/gpu/drm/i915/intel_sdvo_regs.h | 2 + drivers/gpu/drm/nouveau/nouveau_display.c | 2 +- drivers/gpu/drm/nouveau/nouveau_drv.c | 20 +- drivers/gpu/drm/nouveau/nouveau_state.c | 4 +- drivers/gpu/drm/nouveau/nv04_dac.c | 8 +- drivers/gpu/drm/nouveau/nv04_dfp.c | 8 +- drivers/gpu/drm/nouveau/nv04_tv.c | 4 +- drivers/gpu/drm/nouveau/nva3_copy.fuc | 4 +- drivers/gpu/drm/nouveau/nva3_copy.fuc.h | 94 +- drivers/gpu/drm/nouveau/nvc0_copy.fuc.h | 87 +- drivers/gpu/drm/nouveau/nvd0_display.c | 2 +- drivers/gpu/drm/radeon/atombios_crtc.c | 79 +- drivers/gpu/drm/radeon/atombios_dp.c | 10 +- drivers/gpu/drm/radeon/atombios_encoders.c | 138 +- drivers/gpu/drm/radeon/evergreen.c | 272 ++-- drivers/gpu/drm/radeon/evergreen_cs.c | 5 + drivers/gpu/drm/radeon/evergreen_reg.h | 2 + drivers/gpu/drm/radeon/evergreend.h | 11 + drivers/gpu/drm/radeon/ni.c | 14 +- drivers/gpu/drm/radeon/radeon.h | 15 - drivers/gpu/drm/radeon/radeon_agp.c | 5 +- drivers/gpu/drm/radeon/radeon_asic.h | 9 +- drivers/gpu/drm/radeon/radeon_atombios.c | 2 +- drivers/gpu/drm/radeon/radeon_atpx_handler.c | 56 +- drivers/gpu/drm/radeon/radeon_bios.c | 138 +- drivers/gpu/drm/radeon/radeon_combios.c | 8 + drivers/gpu/drm/radeon/radeon_connectors.c | 45 +- drivers/gpu/drm/radeon/radeon_cs.c | 2 +- drivers/gpu/drm/radeon/radeon_cursor.c | 11 +- drivers/gpu/drm/radeon/radeon_device.c | 2 +- drivers/gpu/drm/radeon/radeon_display.c | 19 +- drivers/gpu/drm/radeon/radeon_i2c.c | 10 +- drivers/gpu/drm/radeon/radeon_irq_kms.c | 10 + drivers/gpu/drm/radeon/radeon_legacy_crtc.c | 4 + .../gpu/drm/radeon/radeon_legacy_encoders.c | 15 +- drivers/gpu/drm/radeon/radeon_mode.h | 3 +- drivers/gpu/drm/radeon/radeon_pm.c | 8 +- drivers/gpu/drm/radeon/radeon_ring.c | 3 + drivers/gpu/drm/radeon/reg_srcs/cayman | 1 + drivers/gpu/drm/radeon/rv515.c | 13 - drivers/gpu/drm/radeon/si.c | 1 + drivers/gpu/drm/radeon/sid.h | 1 + drivers/gpu/drm/savage/savage_bci.c | 2 + drivers/gpu/drm/ttm/ttm_page_alloc.c | 5 +- drivers/gpu/drm/udl/udl_connector.c | 24 +- drivers/gpu/drm/udl/udl_drv.h | 2 +- drivers/gpu/drm/udl/udl_fb.c | 12 +- drivers/gpu/drm/udl/udl_transfer.c | 5 +- drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c | 2 +- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 11 + drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 10 + drivers/gpu/drm/vmwgfx/vmwgfx_fence.c | 2 +- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 6 +- drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 73 ++ drivers/hid/hid-apple.c | 6 + drivers/hid/hid-chicony.c | 1 + drivers/hid/hid-core.c | 11 + drivers/hid/hid-cypress.c | 2 + drivers/hid/hid-ids.h | 20 + drivers/hid/hid-input.c | 3 + drivers/hid/hid-microsoft.c | 18 +- drivers/hid/hid-multitouch.c | 9 + drivers/hid/usbhid/hid-quirks.c | 3 + drivers/hv/channel.c | 24 +- drivers/hwmon/ad7314.c | 8 + drivers/hwmon/ads7871.c | 9 + drivers/hwmon/asus_atk0110.c | 6 + drivers/hwmon/fam15h_power.c | 19 +- drivers/hwmon/it87.c | 2 +- drivers/hwmon/lm73.c | 16 +- drivers/hwmon/twl4030-madc-hwmon.c | 9 +- drivers/hwmon/w83627ehf.c | 1 + drivers/i2c/busses/Kconfig | 6 + drivers/i2c/busses/Makefile | 5 +- drivers/i2c/busses/i2c-designware-core.c | 11 + drivers/i2c/busses/i2c-i801.c | 3 + drivers/infiniband/core/cma.c | 3 +- drivers/infiniband/core/netlink.c | 1 + drivers/infiniband/hw/nes/nes.h | 1 + drivers/infiniband/hw/nes/nes_hw.c | 9 +- drivers/infiniband/hw/nes/nes_verbs.c | 9 +- drivers/infiniband/ulp/ipoib/ipoib_main.c | 2 +- .../infiniband/ulp/ipoib/ipoib_multicast.c | 19 +- drivers/infiniband/ulp/srp/ib_srp.c | 88 +- drivers/input/joystick/walkera0701.c | 7 +- drivers/input/joystick/xpad.c | 6 +- drivers/input/mouse/bcm5974.c | 20 + drivers/input/mouse/sentelic.c | 2 +- drivers/input/serio/i8042-x86ia64io.h | 29 + drivers/input/tablet/wacom_wac.c | 2 +- drivers/input/touchscreen/eeti_ts.c | 21 +- drivers/input/touchscreen/tsc40.c | 1 - drivers/iommu/amd_iommu.c | 17 +- drivers/iommu/amd_iommu_init.c | 34 + drivers/iommu/amd_iommu_v2.c | 2 + drivers/iommu/intel-iommu.c | 67 +- drivers/iommu/intr_remapping.c | 18 +- drivers/iommu/tegra-smmu.c | 2 +- drivers/isdn/gigaset/bas-gigaset.c | 19 +- drivers/isdn/isdnloop/isdnloop.c | 12 - drivers/leds/leds-lp5521.c | 12 +- .../md/persistent-data/dm-btree-internal.h | 16 +- drivers/md/persistent-data/dm-btree-remove.c | 50 +- drivers/md/persistent-data/dm-btree-spine.c | 6 +- drivers/md/persistent-data/dm-btree.c | 22 +- drivers/media/dvb/dvb-core/dvbdev.c | 1 + drivers/media/dvb/siano/smsusb.c | 2 +- drivers/media/rc/ene_ir.c | 3 +- drivers/media/rc/ite-cir.c | 2 +- drivers/media/rc/rc-main.c | 5 +- drivers/media/video/au0828/au0828-video.c | 12 +- drivers/media/video/cx231xx/cx231xx-audio.c | 4 +- drivers/media/video/cx231xx/cx231xx-vbi.c | 2 +- drivers/media/video/cx25821/cx25821-core.c | 3 - drivers/media/video/cx25821/cx25821.h | 2 +- drivers/media/video/gspca/jl2005bcd.c | 2 +- drivers/media/video/gspca/pac7302.c | 1 + drivers/media/video/gspca/spca506.c | 2 +- drivers/media/video/uvc/uvc_queue.c | 1 + drivers/mfd/ezx-pcap.c | 2 +- drivers/mfd/max8925-core.c | 10 + drivers/mfd/mfd-core.c | 15 +- drivers/mfd/wm831x-otp.c | 8 + drivers/mfd/wm8994-core.c | 1 + drivers/misc/sgi-xp/xpc_main.c | 34 +- drivers/misc/sgi-xp/xpc_uv.c | 84 +- drivers/mmc/host/mxs-mmc.c | 4 +- drivers/mmc/host/omap_hsmmc.c | 3 +- drivers/mmc/host/sdhci-esdhc.h | 6 +- drivers/mmc/host/sdhci-pci.c | 1 + drivers/mmc/host/sdhci-s3c.c | 2 +- drivers/mmc/host/sdhci.c | 21 +- drivers/mmc/host/sh_mmcif.c | 4 +- drivers/mtd/devices/slram.c | 2 +- drivers/mtd/maps/autcpu12-nvram.c | 19 +- drivers/mtd/mtdpart.c | 5 +- drivers/mtd/nand/cs553x_nand.c | 3 +- drivers/mtd/nand/gpmi-nand/gpmi-lib.c | 9 + drivers/mtd/nand/nand_base.c | 9 +- drivers/mtd/nand/nand_bbt.c | 2 +- drivers/mtd/nand/nandsim.c | 13 +- drivers/mtd/nand/omap2.c | 3 +- drivers/mtd/ofpart.c | 2 +- drivers/mtd/ubi/build.c | 5 + drivers/mtd/ubi/vtbl.c | 4 +- drivers/net/bonding/bond_debugfs.c | 2 +- drivers/net/bonding/bond_main.c | 16 +- drivers/net/bonding/bond_sysfs.c | 2 + drivers/net/caif/caif_serial.c | 3 + drivers/net/can/c_can/c_can.c | 4 +- drivers/net/can/dev.c | 3 +- drivers/net/can/janz-ican3.c | 4 +- drivers/net/can/mcp251x.c | 11 +- drivers/net/can/mscan/mpc5xxx_can.c | 4 +- drivers/net/can/pch_can.c | 2 +- drivers/net/can/ti_hecc.c | 6 +- drivers/net/can/usb/peak_usb/pcan_usb.c | 8 +- drivers/net/can/usb/peak_usb/pcan_usb_pro.c | 8 +- drivers/net/ethernet/8390/ne.c | 1 + .../net/ethernet/atheros/atl1c/atl1c_main.c | 1 - drivers/net/ethernet/broadcom/bnx2.c | 6 +- .../net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | 12 +- .../net/ethernet/broadcom/bnx2x/bnx2x_main.c | 11 +- drivers/net/ethernet/broadcom/tg3.c | 10 +- drivers/net/ethernet/freescale/gianfar.c | 9 +- drivers/net/ethernet/ibm/ibmveth.c | 26 +- drivers/net/ethernet/intel/e1000e/82571.c | 7 +- drivers/net/ethernet/intel/e1000e/e1000.h | 6 +- drivers/net/ethernet/intel/e1000e/netdev.c | 2 +- drivers/net/ethernet/intel/igb/igb_main.c | 22 +- .../net/ethernet/intel/ixgbe/ixgbe_common.c | 1 + .../net/ethernet/intel/ixgbe/ixgbe_ethtool.c | 1 + drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 2 + drivers/net/ethernet/intel/ixgbe/ixgbe_type.h | 1 + drivers/net/ethernet/marvell/skge.c | 7 + drivers/net/ethernet/marvell/sky2.c | 4 +- drivers/net/ethernet/nxp/lpc_eth.c | 1 + .../ethernet/qlogic/netxen/netxen_nic_main.c | 4 + drivers/net/ethernet/realtek/r8169.c | 62 +- drivers/net/ethernet/sfc/efx.c | 6 + drivers/net/ethernet/sfc/efx.h | 14 +- drivers/net/ethernet/sfc/ethtool.c | 20 +- drivers/net/ethernet/sfc/tx.c | 19 + .../net/ethernet/stmicro/stmmac/stmmac_main.c | 3 + drivers/net/ethernet/ti/davinci_cpdma.c | 1 + drivers/net/irda/sir_dev.c | 2 +- drivers/net/macvtap.c | 35 +- drivers/net/netconsole.c | 1 - drivers/net/ppp/pppoe.c | 2 +- drivers/net/ppp/pptp.c | 4 +- drivers/net/rionet.c | 20 +- drivers/net/tun.c | 10 +- drivers/net/usb/asix.c | 4 + drivers/net/usb/ipheth.c | 5 + drivers/net/usb/kaweth.c | 2 +- drivers/net/usb/qmi_wwan.c | 95 ++ drivers/net/usb/sierra_net.c | 2 +- drivers/net/wan/ixp4xx_hss.c | 1 + drivers/net/wimax/i2400m/i2400m-usb.h | 3 + drivers/net/wimax/i2400m/usb.c | 6 + drivers/net/wireless/ath/ath5k/base.c | 4 +- drivers/net/wireless/ath/ath5k/mac80211-ops.c | 2 +- .../wireless/ath/ath9k/ar9003_2p2_initvals.h | 182 +-- .../net/wireless/ath/ath9k/ar9003_eeprom.h | 6 +- drivers/net/wireless/ath/ath9k/beacon.c | 3 +- drivers/net/wireless/ath/ath9k/calib.c | 1 + drivers/net/wireless/ath/ath9k/calib.h | 3 + drivers/net/wireless/ath/ath9k/htc_hst.c | 2 + drivers/net/wireless/ath/ath9k/hw.c | 1 + drivers/net/wireless/ath/ath9k/hw.h | 1 + drivers/net/wireless/ath/ath9k/main.c | 2 +- drivers/net/wireless/ath/ath9k/pci.c | 6 +- drivers/net/wireless/ath/ath9k/recv.c | 12 +- drivers/net/wireless/ath/ath9k/xmit.c | 63 +- drivers/net/wireless/b43/b43.h | 5 + drivers/net/wireless/b43/dma.c | 7 +- drivers/net/wireless/b43/main.c | 68 +- drivers/net/wireless/b43/main.h | 5 +- drivers/net/wireless/b43/pio.c | 4 +- drivers/net/wireless/b43legacy/b43legacy.h | 5 + drivers/net/wireless/b43legacy/main.c | 39 +- .../wireless/brcm80211/brcmfmac/dhd_common.c | 26 +- .../wireless/brcm80211/brcmfmac/wl_cfg80211.c | 6 +- .../wireless/brcm80211/brcmsmac/mac80211_if.c | 7 +- drivers/net/wireless/ipw2x00/ipw2200.c | 2 +- drivers/net/wireless/iwlegacy/4965-mac.c | 4 +- drivers/net/wireless/iwlegacy/common.c | 49 +- drivers/net/wireless/iwlwifi/iwl-6000.c | 33 +- drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 13 +- drivers/net/wireless/iwlwifi/iwl-agn-sta.c | 1 + drivers/net/wireless/mwifiex/cfg80211.c | 4 +- drivers/net/wireless/mwifiex/cmdevt.c | 11 +- drivers/net/wireless/mwifiex/pcie.c | 2 +- drivers/net/wireless/mwifiex/sdio.c | 11 +- drivers/net/wireless/mwifiex/sta_ioctl.c | 21 +- drivers/net/wireless/p54/p54usb.c | 6 +- drivers/net/wireless/rt2x00/rt2400pci.c | 9 + drivers/net/wireless/rt2x00/rt2400pci.h | 1 + drivers/net/wireless/rt2x00/rt2500pci.c | 9 + drivers/net/wireless/rt2x00/rt2500usb.c | 11 +- drivers/net/wireless/rt2x00/rt2500usb.h | 17 +- drivers/net/wireless/rt2x00/rt2800lib.c | 2 +- drivers/net/wireless/rt2x00/rt2800pci.c | 9 + drivers/net/wireless/rt2x00/rt2800usb.c | 26 +- drivers/net/wireless/rt2x00/rt2x00dev.c | 2 +- drivers/net/wireless/rt2x00/rt2x00usb.c | 2 +- drivers/net/wireless/rt2x00/rt61pci.c | 12 +- drivers/net/wireless/rt2x00/rt61pci.h | 1 + drivers/net/wireless/rt2x00/rt73usb.c | 9 + drivers/net/wireless/rt2x00/rt73usb.h | 3 + drivers/net/wireless/rtl818x/rtl8187/dev.c | 2 +- drivers/net/wireless/rtlwifi/rtl8192ce/def.h | 1 + drivers/net/wireless/rtlwifi/rtl8192ce/hw.c | 12 +- drivers/net/wireless/rtlwifi/rtl8192ce/sw.c | 6 +- drivers/net/wireless/rtlwifi/rtl8192cu/sw.c | 1 + drivers/net/wireless/rtlwifi/rtl8192de/phy.c | 6 +- drivers/net/wireless/rtlwifi/rtl8192se/phy.c | 3 + drivers/net/wireless/rtlwifi/usb.c | 21 +- drivers/net/wireless/rtlwifi/wifi.h | 1 + drivers/nfc/pn533.c | 16 +- drivers/pci/hotplug/acpiphp_glue.c | 13 +- drivers/pci/hotplug/pciehp.h | 2 +- drivers/pci/hotplug/pciehp_core.c | 11 +- drivers/pci/hotplug/pciehp_ctrl.c | 8 +- drivers/pci/hotplug/pciehp_hpc.c | 11 +- drivers/pci/hotplug/shpchp.h | 1 - drivers/pci/hotplug/shpchp_core.c | 10 - drivers/pci/hotplug/shpchp_ctrl.c | 2 +- drivers/pci/pci-driver.c | 7 + drivers/pci/pcie/aer/aerdrv_core.c | 1 + drivers/pci/pcie/aspm.c | 3 + drivers/pci/probe.c | 6 +- drivers/pci/quirks.c | 7 +- drivers/pcmcia/pxa2xx_sharpsl.c | 2 +- drivers/pinctrl/pinctrl-tegra.c | 2 +- drivers/pinctrl/pinctrl-tegra30.c | 24 +- drivers/platform/x86/asus-laptop.c | 8 +- drivers/platform/x86/asus-nb-wmi.c | 4 + drivers/platform/x86/asus-wmi.c | 7 +- drivers/platform/x86/intel_ips.c | 22 + drivers/platform/x86/samsung-laptop.c | 10 + drivers/pnp/pnpacpi/core.c | 5 +- drivers/rapidio/devices/tsi721.c | 12 +- drivers/regulator/twl-regulator.c | 4 +- drivers/regulator/wm831x-dcdc.c | 2 +- drivers/remoteproc/Kconfig | 1 + drivers/remoteproc/remoteproc_core.c | 22 +- drivers/rpmsg/virtio_rpmsg_bus.c | 2 +- drivers/rtc/rtc-imxdi.c | 2 + drivers/rtc/rtc-isl1208.c | 3 + drivers/rtc/rtc-rs5c348.c | 7 +- drivers/rtc/rtc-twl.c | 5 + drivers/rtc/rtc-vt8500.c | 11 +- drivers/rtc/rtc-wm831x.c | 24 +- drivers/s390/cio/device_pgid.c | 10 +- drivers/s390/net/qeth_l3_main.c | 4 + drivers/s390/scsi/zfcp_aux.c | 1 + drivers/s390/scsi/zfcp_ccw.c | 73 +- drivers/s390/scsi/zfcp_cfdc.c | 2 +- drivers/s390/scsi/zfcp_dbf.c | 22 +- drivers/s390/scsi/zfcp_dbf.h | 1 + drivers/s390/scsi/zfcp_def.h | 2 + drivers/s390/scsi/zfcp_ext.h | 2 + drivers/s390/scsi/zfcp_fsf.c | 57 +- drivers/s390/scsi/zfcp_qdio.c | 16 +- drivers/s390/scsi/zfcp_sysfs.c | 18 +- drivers/s390/scsi/zfcp_unit.c | 36 +- drivers/scsi/aha152x.c | 4 +- drivers/scsi/atp870u.c | 11 +- drivers/scsi/bnx2i/bnx2i_hwi.c | 3 + drivers/scsi/device_handler/scsi_dh_alua.c | 3 +- drivers/scsi/hosts.c | 7 +- drivers/scsi/hpsa.c | 44 +- drivers/scsi/hpsa.h | 2 + drivers/scsi/hpsa_cmd.h | 1 + drivers/scsi/ibmvscsi/ibmvscsi.c | 3 + drivers/scsi/isci/init.c | 1 - drivers/scsi/isci/probe_roms.c | 1 - drivers/scsi/isci/request.c | 2 +- drivers/scsi/libsas/sas_expander.c | 47 +- drivers/scsi/lpfc/Makefile | 2 + drivers/scsi/megaraid/megaraid_sas_base.c | 3 +- drivers/scsi/mpt2sas/mpt2sas_base.c | 20 +- drivers/scsi/mvsas/mv_94xx.h | 14 +- drivers/scsi/mvsas/mv_sas.c | 3 +- drivers/scsi/mvsas/mv_sas.h | 2 +- drivers/scsi/qla2xxx/qla_os.c | 4 +- drivers/scsi/scsi_debug.c | 2 +- drivers/scsi/scsi_error.c | 24 + drivers/scsi/scsi_lib.c | 48 +- drivers/scsi/scsi_priv.h | 1 - drivers/scsi/scsi_scan.c | 13 + drivers/scsi/scsi_sysfs.c | 55 +- drivers/scsi/sd.c | 13 +- drivers/scsi/storvsc_drv.c | 5 + drivers/scsi/virtio_scsi.c | 2 +- drivers/spi/spi-pl022.c | 5 + drivers/staging/android/binder.c | 2 +- drivers/staging/comedi/Kconfig | 1 + drivers/staging/comedi/comedi_fops.c | 26 +- drivers/staging/comedi/comedidev.h | 1 + drivers/staging/comedi/drivers.c | 34 +- drivers/staging/comedi/drivers/amplc_pc236.c | 2 +- drivers/staging/comedi/drivers/comedi_test.c | 2 +- drivers/staging/comedi/drivers/das08.c | 2 +- drivers/staging/comedi/drivers/jr3_pci.c | 2 +- drivers/staging/comedi/drivers/ni_pcimio.c | 16 +- drivers/staging/comedi/drivers/s626.c | 2 +- drivers/staging/comedi/internal.h | 1 + drivers/staging/media/lirc/lirc_sir.c | 60 +- drivers/staging/rtl8712/recv_linux.c | 7 +- drivers/staging/rtl8712/rtl8712_recv.c | 5 +- drivers/staging/rtl8712/usb_intf.c | 2 + drivers/staging/speakup/main.c | 2 +- drivers/staging/speakup/speakup_soft.c | 13 +- drivers/staging/speakup/synth.c | 4 +- drivers/staging/telephony/ixj.c | 24 +- drivers/staging/vt6656/bssdb.h | 1 - drivers/staging/vt6656/dpc.c | 6 +- drivers/staging/vt6656/int.h | 1 - drivers/staging/vt6656/iocmd.h | 33 +- drivers/staging/vt6656/iowpa.h | 8 +- drivers/staging/vt6656/key.c | 53 +- drivers/staging/vt6656/key.h | 8 +- drivers/staging/vt6656/mac.c | 6 +- drivers/staging/vt6656/main_usb.c | 2 +- drivers/staging/vt6656/rf.c | 3 + drivers/staging/vt6656/rxtx.c | 56 +- drivers/staging/vt6656/ttype.h | 16 +- drivers/staging/vt6656/wcmd.c | 20 +- drivers/staging/vt6656/wpa2.h | 4 +- drivers/staging/winbond/wbusb.c | 2 +- drivers/staging/wlan-ng/prism2mgmt.c | 2 +- drivers/staging/zcache/zcache-main.c | 7 +- drivers/staging/zsmalloc/zsmalloc-main.c | 33 +- drivers/target/iscsi/iscsi_target.c | 30 +- drivers/target/iscsi/iscsi_target_core.h | 7 +- drivers/target/iscsi/iscsi_target_login.c | 61 +- drivers/target/iscsi/iscsi_target_tpg.c | 12 + drivers/target/iscsi/iscsi_target_util.c | 22 +- drivers/target/iscsi/iscsi_target_util.h | 1 + drivers/target/target_core_cdb.c | 45 +- drivers/target/target_core_configfs.c | 11 +- drivers/target/target_core_device.c | 19 +- drivers/target/target_core_fabric_configfs.c | 11 + drivers/target/target_core_pr.c | 7 +- drivers/target/target_core_tmr.c | 6 +- drivers/target/target_core_tpg.c | 1 + drivers/target/target_core_transport.c | 27 +- drivers/target/tcm_fc/tfc_cmd.c | 2 + drivers/target/tcm_fc/tfc_sess.c | 14 +- drivers/tty/n_gsm.c | 26 +- drivers/tty/n_tty.c | 3 +- drivers/tty/serial/8250/8250_dw.c | 2 +- drivers/tty/serial/8250/8250_pci.c | 9 +- drivers/tty/serial/amba-pl011.c | 15 +- drivers/tty/serial/ifx6x60.c | 1 + drivers/tty/serial/imx.c | 12 +- drivers/tty/serial/pch_uart.c | 59 +- drivers/tty/serial/pmac_zilog.c | 12 +- drivers/tty/vt/keyboard.c | 3 - drivers/tty/vt/vt.c | 13 + drivers/usb/class/cdc-acm.c | 69 +- drivers/usb/class/cdc-wdm.c | 12 +- drivers/usb/core/devices.c | 2 +- drivers/usb/core/devio.c | 10 +- drivers/usb/core/hcd.c | 6 +- drivers/usb/core/hub.c | 197 ++- drivers/usb/core/message.c | 56 +- drivers/usb/core/quirks.c | 4 + drivers/usb/dwc3/gadget.c | 1 + drivers/usb/early/ehci-dbgp.c | 2 +- drivers/usb/gadget/at91_udc.c | 2 +- drivers/usb/gadget/dummy_hcd.c | 17 +- drivers/usb/gadget/f_ecm.c | 4 +- drivers/usb/gadget/f_eem.c | 5 +- drivers/usb/gadget/f_midi.c | 1 + drivers/usb/gadget/f_ncm.c | 4 +- drivers/usb/gadget/f_phonet.c | 8 +- drivers/usb/gadget/f_rndis.c | 4 +- drivers/usb/gadget/f_subset.c | 4 +- drivers/usb/gadget/f_uvc.c | 39 +- drivers/usb/gadget/u_ether.c | 6 + drivers/usb/host/ehci-hub.c | 6 +- drivers/usb/host/ehci-pci.c | 3 +- drivers/usb/host/ehci-sched.c | 2 +- drivers/usb/host/ohci-at91.c | 13 +- drivers/usb/host/ohci-q.c | 19 + drivers/usb/host/pci-quirks.c | 56 +- drivers/usb/host/pci-quirks.h | 1 + drivers/usb/host/uhci-hcd.c | 15 +- drivers/usb/host/xhci-hub.c | 80 +- drivers/usb/host/xhci-mem.c | 18 +- drivers/usb/host/xhci-pci.c | 18 +- drivers/usb/host/xhci-plat.c | 2 +- drivers/usb/host/xhci-ring.c | 351 ++++- drivers/usb/host/xhci.c | 174 ++- drivers/usb/host/xhci.h | 26 +- drivers/usb/misc/emi62.c | 2 +- drivers/usb/musb/cppi_dma.c | 1 + drivers/usb/musb/musb_core.c | 5 +- drivers/usb/serial/cp210x.c | 1 + drivers/usb/serial/ftdi_sio.c | 32 +- drivers/usb/serial/ftdi_sio_ids.h | 62 +- drivers/usb/serial/mct_u232.c | 14 +- drivers/usb/serial/mos7840.c | 40 +- drivers/usb/serial/opticon.c | 11 +- drivers/usb/serial/option.c | 442 ++++--- drivers/usb/serial/qcaux.c | 10 +- drivers/usb/serial/qcserial.c | 1 + drivers/usb/serial/sierra.c | 26 +- drivers/usb/serial/usb-serial.c | 6 +- drivers/usb/serial/whiteheat.c | 1 + drivers/usb/storage/Kconfig | 2 +- drivers/usb/storage/initializers.c | 76 +- drivers/usb/storage/initializers.h | 4 +- drivers/usb/storage/uas.c | 90 +- drivers/usb/storage/unusual_devs.h | 335 +---- drivers/usb/storage/usb.c | 12 + drivers/usb/storage/usual-tables.c | 15 + drivers/vhost/net.c | 3 +- drivers/video/console/fbcon.c | 9 +- drivers/video/mxsfb.c | 3 +- drivers/video/smscufx.c | 2 +- drivers/video/udlfb.c | 2 +- drivers/video/via/via_clock.c | 19 + drivers/virtio/virtio_ring.c | 7 + drivers/watchdog/hpwdt.c | 3 + drivers/xen/events.c | 2 +- drivers/xen/gntdev.c | 41 +- drivers/xen/grant-table.c | 54 +- drivers/xen/swiotlb-xen.c | 2 +- drivers/xen/xen-pciback/pci_stub.c | 8 +- fs/autofs4/root.c | 6 +- fs/binfmt_elf.c | 19 +- fs/binfmt_misc.c | 5 +- fs/binfmt_script.c | 4 +- fs/btrfs/async-thread.c | 9 +- fs/buffer.c | 66 +- fs/ceph/addr.c | 49 +- fs/ceph/caps.c | 16 +- fs/ceph/debugfs.c | 1 + fs/ceph/export.c | 18 +- fs/ceph/file.c | 4 +- fs/ceph/inode.c | 30 +- fs/ceph/mds_client.c | 77 +- fs/ceph/mds_client.h | 5 +- fs/ceph/super.c | 2 - fs/cifs/cifs_dfs_ref.c | 2 + fs/cifs/cifs_unicode.c | 24 +- fs/cifs/cifsacl.c | 49 +- fs/cifs/cifssmb.c | 30 + fs/cifs/connect.c | 36 +- fs/cifs/readdir.c | 7 +- fs/compat.c | 10 +- fs/compat_ioctl.c | 2 + fs/dcache.c | 4 +- fs/eventpoll.c | 22 +- fs/exec.c | 20 +- fs/exofs/ore.c | 22 +- fs/exofs/ore_raid.c | 67 +- fs/ext3/inode.c | 17 +- fs/ext4/acl.c | 6 +- fs/ext4/balloc.c | 3 +- fs/ext4/bitmap.c | 12 +- fs/ext4/ext4.h | 6 +- fs/ext4/extents.c | 126 +- fs/ext4/ialloc.c | 9 +- fs/ext4/inode.c | 43 +- fs/ext4/ioctl.c | 1 - fs/ext4/mballoc.c | 5 +- fs/ext4/move_extent.c | 174 +-- fs/ext4/namei.c | 8 +- fs/ext4/resize.c | 33 +- fs/ext4/super.c | 208 ++- fs/fifo.c | 9 +- fs/fuse/dev.c | 1 + fs/fuse/file.c | 2 +- fs/gfs2/export.c | 4 + fs/gfs2/lops.c | 18 +- fs/gfs2/trans.c | 8 + fs/isofs/export.c | 2 +- fs/jbd/commit.c | 45 +- fs/jbd/transaction.c | 66 +- fs/jbd2/journal.c | 8 +- fs/jffs2/file.c | 39 +- fs/jffs2/nodemgmt.c | 6 +- fs/jffs2/wbuf.c | 8 +- fs/lockd/clntxdr.c | 2 +- fs/lockd/mon.c | 4 +- fs/lockd/svc.c | 12 +- fs/lockd/svcproc.c | 3 +- fs/locks.c | 8 +- fs/nfs/blocklayout/blocklayout.c | 176 ++- fs/nfs/blocklayout/blocklayout.h | 1 + fs/nfs/client.c | 3 +- fs/nfs/dir.c | 15 +- fs/nfs/dns_resolve.c | 5 +- fs/nfs/file.c | 7 +- fs/nfs/idmap.c | 86 +- fs/nfs/inode.c | 2 +- fs/nfs/internal.h | 5 +- fs/nfs/mount_clnt.c | 2 +- fs/nfs/namespace.c | 39 +- fs/nfs/nfs3proc.c | 4 +- fs/nfs/nfs4namespace.c | 3 +- fs/nfs/nfs4proc.c | 130 +- fs/nfs/nfs4xdr.c | 3 +- fs/nfs/objlayout/objio_osd.c | 25 +- fs/nfs/pnfs.c | 39 +- fs/nfs/pnfs.h | 2 +- fs/nfs/super.c | 8 +- fs/nfsd/export.c | 6 +- fs/nfsd/nfs4idmap.c | 2 +- fs/nfsd/nfs4proc.c | 8 +- fs/nfsd/nfs4state.c | 3 +- fs/nfsd/nfs4xdr.c | 13 +- fs/nfsd/nfsctl.c | 8 +- fs/nfsd/nfsd.h | 11 + fs/nfsd/nfssvc.c | 26 +- fs/nfsd/vfs.c | 10 +- fs/nilfs2/ioctl.c | 9 +- fs/nilfs2/super.c | 3 + fs/nilfs2/the_nilfs.c | 1 + fs/nilfs2/the_nilfs.h | 2 + fs/notify/fanotify/fanotify.c | 1 + fs/open.c | 7 +- fs/proc/page.c | 8 +- fs/proc/proc_sysctl.c | 5 +- fs/reiserfs/inode.c | 16 +- fs/reiserfs/stree.c | 4 + fs/reiserfs/super.c | 60 +- fs/select.c | 10 +- fs/splice.c | 4 +- fs/stat.c | 2 +- fs/sysfs/dir.c | 16 +- fs/ubifs/debug.h | 2 +- fs/ubifs/find.c | 12 +- fs/ubifs/lprops.c | 6 + fs/ubifs/sb.c | 8 +- fs/ubifs/ubifs.h | 3 + fs/udf/file.c | 35 +- fs/udf/inode.c | 11 +- fs/udf/super.c | 7 +- fs/xfs/xfs_aops.c | 2 +- fs/xfs/xfs_buf.c | 14 +- fs/xfs/xfs_export.c | 3 + fs/xfs/xfs_log_recover.c | 2 +- include/asm-generic/tlb.h | 9 + include/drm/drm_mode.h | 5 +- include/drm/drm_pciids.h | 7 + include/linux/Kbuild | 1 + include/linux/binfmts.h | 1 + include/linux/bug.h | 6 + include/linux/ceph/auth.h | 12 +- include/linux/ceph/libceph.h | 4 +- include/linux/ceph/messenger.h | 78 +- include/linux/ceph/mon_client.h | 2 +- include/linux/ceph/msgpool.h | 3 +- include/linux/ceph/osd_client.h | 13 +- include/linux/ceph/osdmap.h | 6 +- include/linux/cpu.h | 5 +- include/linux/crush/crush.h | 7 +- include/linux/crush/mapper.h | 6 +- include/linux/dcache.h | 2 + include/linux/efi.h | 5 + include/linux/hrtimer.h | 10 +- include/linux/if_vlan.h | 8 +- include/linux/init_task.h | 13 +- include/linux/input/eeti_ts.h | 1 + include/linux/jbd2.h | 1 + include/linux/kobject.h | 2 +- include/linux/ktime.h | 7 - include/linux/memblock.h | 1 + include/linux/memory.h | 2 +- include/linux/mempolicy.h | 18 +- include/linux/mfd/ezx-pcap.h | 1 + include/linux/mm.h | 1 + include/linux/mtd/nand.h | 3 - include/linux/net.h | 1 + include/linux/netdevice.h | 4 + .../linux/netfilter/ipset/ip_set_timeout.h | 4 + include/linux/netlink.h | 21 +- include/linux/nfs_fs.h | 5 - include/linux/page-flags.h | 8 +- include/linux/pci_ids.h | 4 +- include/linux/perf_event.h | 2 +- include/linux/posix_types.h | 18 +- include/linux/sched.h | 13 +- include/linux/snmp.h | 3 +- include/linux/sunrpc/cache.h | 16 + include/linux/sunrpc/xprt.h | 3 + include/linux/time.h | 37 +- include/linux/usb.h | 21 + include/linux/usb/ch9.h | 6 + include/linux/xfrm.h | 2 + include/net/cfg80211.h | 9 + include/net/inet_connection_sock.h | 1 + include/net/ip_vs.h | 2 +- include/net/netfilter/nf_conntrack_ecache.h | 1 + include/net/sock.h | 2 + include/net/tcp.h | 1 + include/net/xfrm.h | 3 + include/rdma/rdma_netlink.h | 1 + include/sound/core.h | 3 + include/target/target_core_base.h | 5 + include/trace/events/kmem.h | 4 +- include/trace/events/random.h | 134 ++ include/trace/events/workqueue.h | 2 +- include/trace/events/xen.h | 8 + include/xen/grant_table.h | 3 +- init/main.c | 3 + kernel/async.c | 13 +- kernel/audit_tree.c | 11 +- kernel/cgroup.c | 43 +- kernel/cpuset.c | 3 + kernel/debug/kdb/kdb_io.c | 33 +- kernel/events/core.c | 62 +- kernel/exit.c | 2 +- kernel/futex.c | 76 +- kernel/hrtimer.c | 53 +- kernel/irq/manage.c | 23 +- kernel/module.c | 31 +- kernel/power/hibernate.c | 6 + kernel/power/suspend.c | 3 + kernel/rcutree.c | 14 +- kernel/sched/auto_group.c | 4 - kernel/sched/auto_group.h | 5 - kernel/sched/core.c | 359 ++++-- kernel/sched/idle_task.c | 1 - kernel/sched/rt.c | 2 +- kernel/sched/sched.h | 27 +- kernel/sched/stop_task.c | 22 +- kernel/smp.c | 13 +- kernel/sys.c | 1 + kernel/time/ntp.c | 8 +- kernel/time/tick-sched.c | 3 + kernel/time/timekeeping.c | 99 +- kernel/trace/ftrace.c | 4 +- kernel/trace/ring_buffer.c | 7 +- kernel/watchdog.c | 4 +- kernel/workqueue.c | 706 ++++++----- lib/Kconfig.debug | 7 + lib/atomic64.c | 17 +- lib/digsig.c | 8 +- lib/gcd.c | 3 + lib/genalloc.c | 2 +- lib/list_debug.c | 9 +- lib/mpi/longlong.h | 19 +- lib/spinlock_debug.c | 2 + mm/bootmem.c | 8 +- mm/compaction.c | 6 +- mm/huge_memory.c | 3 + mm/hugetlb.c | 28 +- mm/memblock.c | 24 + mm/memcontrol.c | 21 +- mm/memory-failure.c | 28 +- mm/memory.c | 23 +- mm/memory_hotplug.c | 16 +- mm/mempolicy.c | 225 ++-- mm/mmu_notifier.c | 45 +- mm/page-writeback.c | 25 +- mm/page_alloc.c | 2 +- mm/rmap.c | 20 +- mm/shmem.c | 34 +- mm/slab.c | 6 +- mm/sparse.c | 10 +- mm/truncate.c | 3 +- mm/vmscan.c | 13 +- net/8021q/vlan.c | 3 + net/8021q/vlan_core.c | 13 +- net/atm/common.c | 1 + net/atm/pvc.c | 1 + net/batman-adv/bat_iv_ogm.c | 2 +- net/bluetooth/hci_core.c | 2 + net/bluetooth/hci_event.c | 3 +- net/bluetooth/hci_sock.c | 2 + net/bluetooth/hidp/core.c | 2 +- net/bluetooth/l2cap_sock.c | 1 + net/bluetooth/rfcomm/sock.c | 6 +- net/bluetooth/rfcomm/tty.c | 2 +- net/bluetooth/smp.c | 4 + net/caif/caif_dev.c | 2 +- net/can/bcm.c | 3 + net/ceph/auth_none.c | 15 +- net/ceph/auth_x.c | 15 +- net/ceph/ceph_common.c | 31 +- net/ceph/crush/crush.c | 14 +- net/ceph/crush/mapper.c | 66 +- net/ceph/crypto.c | 1 + net/ceph/crypto.h | 3 +- net/ceph/debugfs.c | 4 + net/ceph/messenger.c | 1127 ++++++++++------- net/ceph/mon_client.c | 135 +- net/ceph/msgpool.c | 7 +- net/ceph/osd_client.c | 261 ++-- net/ceph/osdmap.c | 69 +- net/compat.c | 4 +- net/core/dev.c | 55 +- net/core/dev_addr_lists.c | 3 +- net/core/neighbour.c | 6 +- net/core/net_namespace.c | 4 +- net/core/pktgen.c | 2 +- net/core/rtnetlink.c | 8 +- net/core/sock.c | 4 +- net/dccp/ccid.h | 4 +- net/dccp/ccids/ccid3.c | 1 + net/dccp/ipv4.c | 4 +- net/dccp/ipv6.c | 3 +- net/ipv4/cipso_ipv4.c | 6 +- net/ipv4/inet_connection_sock.c | 16 + net/ipv4/inet_diag.c | 159 ++- net/ipv4/ip_fragment.c | 19 +- net/ipv4/ip_sockglue.c | 35 +- net/ipv4/ipmr.c | 14 +- net/ipv4/netfilter/nf_nat_sip.c | 10 +- net/ipv4/netfilter/nf_nat_standalone.c | 6 +- net/ipv4/proc.c | 3 +- net/ipv4/raw.c | 14 +- net/ipv4/sysctl_net_ipv4.c | 7 + net/ipv4/tcp.c | 19 +- net/ipv4/tcp_cong.c | 3 +- net/ipv4/tcp_illinois.c | 8 +- net/ipv4/tcp_input.c | 112 +- net/ipv4/tcp_ipv4.c | 13 +- net/ipv4/tcp_output.c | 21 +- net/ipv6/addrconf.c | 29 +- net/ipv6/ip6_fib.c | 4 + net/ipv6/ipv6_sockglue.c | 1 + net/ipv6/mip6.c | 20 +- net/ipv6/ndisc.c | 3 +- net/ipv6/raw.c | 21 +- net/ipv6/route.c | 15 +- net/ipv6/tcp_ipv6.c | 6 +- net/l2tp/l2tp_core.c | 3 +- net/l2tp/l2tp_core.h | 1 + net/l2tp/l2tp_eth.c | 3 +- net/llc/af_llc.c | 3 +- net/mac80211/cfg.c | 12 +- net/mac80211/ibss.c | 19 +- net/mac80211/ieee80211_i.h | 14 +- net/mac80211/mesh.c | 1 + net/mac80211/mlme.c | 14 +- net/mac80211/offchannel.c | 17 +- net/mac80211/rx.c | 72 +- net/mac80211/scan.c | 49 +- net/mac80211/sta_info.c | 13 +- net/mac80211/status.c | 9 + net/mac80211/tx.c | 9 +- net/mac80211/util.c | 41 +- net/mac80211/work.c | 4 +- net/mac80211/wpa.c | 3 +- net/netfilter/ipvs/ip_vs_ctl.c | 6 +- net/netfilter/nf_conntrack_core.c | 16 +- net/netfilter/nf_conntrack_expect.c | 29 +- net/netfilter/nf_conntrack_proto_tcp.c | 29 +- net/netfilter/xt_hashlimit.c | 8 +- net/netfilter/xt_limit.c | 13 +- net/netfilter/xt_set.c | 17 +- net/netlink/af_netlink.c | 29 +- net/netrom/af_netrom.c | 7 +- net/nfc/llcp/llcp.c | 2 +- net/openvswitch/vport-internal_dev.c | 8 + net/packet/af_packet.c | 10 +- net/rds/recv.c | 3 + net/rds/send.c | 2 +- net/sched/act_gact.c | 14 +- net/sched/sch_cbq.c | 5 +- net/sched/sch_htb.c | 2 +- net/sched/sch_netem.c | 42 +- net/sched/sch_sfb.c | 2 + net/sctp/chunk.c | 20 +- net/sctp/input.c | 7 +- net/sctp/output.c | 21 +- net/sctp/sm_sideeffect.c | 3 +- net/sctp/socket.c | 16 +- net/socket.c | 8 +- net/sunrpc/cache.c | 4 +- net/sunrpc/clnt.c | 5 +- net/sunrpc/rpc_pipe.c | 7 +- net/sunrpc/rpcb_clnt.c | 4 +- net/sunrpc/sched.c | 32 +- net/sunrpc/svc_xprt.c | 10 +- net/sunrpc/svcsock.c | 2 +- net/sunrpc/xprt.c | 46 +- net/sunrpc/xprtrdma/transport.c | 4 +- net/sunrpc/xprtsock.c | 76 +- net/wanrouter/wanmain.c | 51 +- net/wireless/core.c | 8 +- net/wireless/core.h | 1 + net/wireless/reg.c | 33 +- net/wireless/util.c | 21 +- net/xfrm/xfrm_input.c | 2 +- net/xfrm/xfrm_policy.c | 2 +- net/xfrm/xfrm_replay.c | 15 + net/xfrm/xfrm_user.c | 57 +- scripts/Kbuild.include | 14 +- scripts/gcc-version.sh | 6 +- scripts/gcc-x86_32-has-stack-protector.sh | 2 +- scripts/gcc-x86_64-has-stack-protector.sh | 2 +- scripts/kconfig/check.sh | 2 +- scripts/kconfig/lxdialog/check-lxdialog.sh | 2 +- scripts/kconfig/streamline_config.pl | 2 + scripts/package/buildtar | 2 +- security/integrity/evm/evm_crypto.c | 4 +- security/selinux/hooks.c | 2 +- security/selinux/netnode.c | 3 +- security/yama/yama_lsm.c | 2 +- sound/arm/pxa2xx-ac97-lib.c | 26 +- sound/core/compress_offload.c | 9 +- sound/core/control.c | 5 + sound/core/hwdep.c | 12 +- sound/core/init.c | 50 +- sound/core/oss/mixer_oss.c | 11 +- sound/core/oss/pcm_oss.c | 7 + sound/core/pcm.c | 13 +- sound/core/pcm_native.c | 35 +- sound/core/rawmidi.c | 26 +- sound/core/sound.c | 11 +- sound/core/sound_oss.c | 10 +- sound/drivers/aloop.c | 6 + sound/drivers/mpu401/mpu401_uart.c | 1 + sound/pci/ac97/ac97_codec.c | 2 + sound/pci/emu10k1/emu10k1_main.c | 9 + sound/pci/hda/hda_codec.c | 2 +- sound/pci/hda/hda_proc.c | 2 +- sound/pci/hda/patch_analog.c | 1 + sound/pci/hda/patch_ca0132.c | 8 + sound/pci/hda/patch_cirrus.c | 23 +- sound/pci/hda/patch_conexant.c | 1 - sound/pci/hda/patch_hdmi.c | 12 +- sound/pci/hda/patch_realtek.c | 89 +- sound/pci/hda/patch_sigmatel.c | 27 +- sound/pci/hda/patch_via.c | 32 +- sound/pci/ice1712/prodigy_hifi.c | 3 +- sound/soc/Makefile | 5 +- sound/soc/codecs/sigmadsp.c | 2 +- sound/soc/codecs/wm2000.c | 6 +- sound/soc/codecs/wm2200.c | 14 +- sound/soc/codecs/wm5100.c | 6 - sound/soc/codecs/wm8962.c | 6 + sound/soc/codecs/wm8978.c | 2 +- sound/soc/codecs/wm8994.c | 2 +- sound/soc/codecs/wm9712.c | 21 +- sound/soc/omap/mcbsp.c | 2 +- sound/soc/omap/omap-abe-twl6040.c | 2 +- sound/soc/samsung/dma.c | 8 +- sound/soc/sh/fsi.c | 15 +- sound/soc/soc-dapm.c | 12 +- sound/soc/tegra/tegra_alc5632.c | 1 - sound/usb/caiaq/device.c | 2 +- sound/usb/card.c | 14 +- sound/usb/card.h | 1 + sound/usb/clock.c | 3 +- sound/usb/endpoint.c | 3 +- sound/usb/midi.c | 87 +- sound/usb/mixer.c | 89 +- sound/usb/mixer_quirks.c | 37 +- sound/usb/pcm.c | 35 +- sound/usb/proc.c | 4 +- sound/usb/quirks-table.h | 53 + sound/usb/quirks.c | 8 +- sound/usb/usbaudio.h | 2 +- tools/hv/hv_kvp_daemon.c | 45 +- tools/lguest/lguest.c | 1 + tools/perf/Makefile | 2 +- tools/perf/builtin-test.c | 38 +- tools/power/cpupower/Makefile | 2 +- usr/gen_init_cpio.c | 43 +- virt/kvm/kvm_main.c | 13 +- 1162 files changed, 14485 insertions(+), 7353 deletions(-) create mode 100644 include/trace/events/random.h diff --git a/Documentation/ABI/testing/sysfs-bus-rbd b/Documentation/ABI/testing/sysfs-bus-rbd index dbedafb095e..eb781c624a7 100644 --- a/Documentation/ABI/testing/sysfs-bus-rbd +++ b/Documentation/ABI/testing/sysfs-bus-rbd @@ -51,12 +51,6 @@ current_snap The current snapshot for which the device is mapped. -create_snap - - Create a snapshot: - - $ echo > /sys/bus/rbd/devices//snap_create - snap_* A directory per each snapshot diff --git a/Documentation/cgroups/memory.txt b/Documentation/cgroups/memory.txt index 9b1067afb22..68c5411d70a 100644 --- a/Documentation/cgroups/memory.txt +++ b/Documentation/cgroups/memory.txt @@ -466,6 +466,10 @@ Note: 5.3 swappiness Similar to /proc/sys/vm/swappiness, but affecting a hierarchy of groups only. +Please note that unlike the global swappiness, memcg knob set to 0 +really prevents from any swapping even if there is a swap storage +available. This might lead to memcg OOM killer if there are no file +pages to reclaim. Following cgroups' swappiness can't be changed. - root cgroup (uses /proc/sys/vm/swappiness). diff --git a/Documentation/devicetree/bindings/arm/atmel-at91.txt b/Documentation/devicetree/bindings/arm/atmel-at91.txt index ecc81e36871..d187e9f7cf1 100644 --- a/Documentation/devicetree/bindings/arm/atmel-at91.txt +++ b/Documentation/devicetree/bindings/arm/atmel-at91.txt @@ -8,7 +8,7 @@ PIT Timer required properties: shared across all System Controller members. TC/TCLIB Timer required properties: -- compatible: Should be "atmel,-pit". +- compatible: Should be "atmel,-tcb". can be "at91rm9200" or "at91sam9x5" - reg: Should contain registers location and length - interrupts: Should contain all interrupts for the TC block diff --git a/Documentation/dvb/get_dvb_firmware b/Documentation/dvb/get_dvb_firmware index d1d4a179a38..b361e08570f 100755 --- a/Documentation/dvb/get_dvb_firmware +++ b/Documentation/dvb/get_dvb_firmware @@ -115,7 +115,7 @@ sub tda10045 { sub tda10046 { my $sourcefile = "TT_PCI_2.19h_28_11_2006.zip"; - my $url = "http://www.tt-download.com/download/updates/219/$sourcefile"; + my $url = "http://technotrend.com.ua/download/software/219/$sourcefile"; my $hash = "6a7e1e2f2644b162ff0502367553c72d"; my $outfile = "dvb-fe-tda10046.fw"; my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1); diff --git a/Documentation/i2c/busses/i2c-i801 b/Documentation/i2c/busses/i2c-i801 index 71f55bbcefc..99d4e442b77 100644 --- a/Documentation/i2c/busses/i2c-i801 +++ b/Documentation/i2c/busses/i2c-i801 @@ -21,6 +21,7 @@ Supported adapters: * Intel DH89xxCC (PCH) * Intel Panther Point (PCH) * Intel Lynx Point (PCH) + * Intel Lynx Point-LP (PCH) Datasheets: Publicly available at the Intel website On Intel Patsburg and later chipsets, both the normal host SMBus controller diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index 5aecb488941..026c59b2b4b 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt @@ -537,6 +537,11 @@ tcp_thin_dupack - BOOLEAN Documentation/networking/tcp-thin.txt Default: 0 +tcp_challenge_ack_limit - INTEGER + Limits number of Challenge ACK sent per second, as recommended + in RFC 5961 (Improving TCP's Robustness to Blind In-Window Attacks) + Default: 100 + UDP variables: udp_mem - vector of 3 INTEGERs: min, pressure, max diff --git a/Documentation/sound/alsa/HD-Audio-Models.txt b/Documentation/sound/alsa/HD-Audio-Models.txt index 03f7897c641..82dd174396d 100644 --- a/Documentation/sound/alsa/HD-Audio-Models.txt +++ b/Documentation/sound/alsa/HD-Audio-Models.txt @@ -21,10 +21,11 @@ ALC267/268 ========== N/A -ALC269 +ALC269/270/275/276/280/282 ====== laptop-amic Laptops with analog-mic input laptop-dmic Laptops with digital-mic input + lenovo-dock Enables docking station I/O for some Lenovos ALC662/663/272 ============== @@ -46,6 +47,7 @@ ALC882/883/885/888/889 acer-aspire-4930g Acer Aspire 4930G/5930G/6530G/6930G/7730G acer-aspire-8930g Acer Aspire 8330G/6935G acer-aspire Acer Aspire others + no-primary-hp VAIO Z workaround (for fixed speaker DAC) ALC861/660 ========== diff --git a/Documentation/stable_kernel_rules.txt b/Documentation/stable_kernel_rules.txt index 4a7b54bd37e..b0714d8f678 100644 --- a/Documentation/stable_kernel_rules.txt +++ b/Documentation/stable_kernel_rules.txt @@ -1,4 +1,4 @@ -Everything you ever wanted to know about Linux 2.6 -stable releases. +Everything you ever wanted to know about Linux -stable releases. Rules on what kind of patches are accepted, and which ones are not, into the "-stable" tree: @@ -42,10 +42,10 @@ Procedure for submitting patches to the -stable tree: cherry-picked than this can be specified in the following format in the sign-off area: - Cc: # .32.x: a1f84a3: sched: Check for idle - Cc: # .32.x: 1b9508f: sched: Rate-limit newidle - Cc: # .32.x: fd21073: sched: Fix affinity logic - Cc: # .32.x + Cc: # 3.3.x: a1f84a3: sched: Check for idle + Cc: # 3.3.x: 1b9508f: sched: Rate-limit newidle + Cc: # 3.3.x: fd21073: sched: Fix affinity logic + Cc: # 3.3.x Signed-off-by: Ingo Molnar The tag sequence has the meaning of: @@ -79,6 +79,15 @@ Review cycle: security kernel team, and not go through the normal review cycle. Contact the kernel security team for more details on this procedure. +Trees: + + - The queues of patches, for both completed versions and in progress + versions can be found at: + http://git.kernel.org/?p=linux/kernel/git/stable/stable-queue.git + - The finalized and tagged releases of all stable kernels can be found + in separate branches per version at: + http://git.kernel.org/?p=linux/kernel/git/stable/linux-stable.git + Review committee: diff --git a/Documentation/workqueue.txt b/Documentation/workqueue.txt index a0b577de918..a6ab4b62d92 100644 --- a/Documentation/workqueue.txt +++ b/Documentation/workqueue.txt @@ -89,25 +89,28 @@ called thread-pools. The cmwq design differentiates between the user-facing workqueues that subsystems and drivers queue work items on and the backend mechanism -which manages thread-pool and processes the queued work items. +which manages thread-pools and processes the queued work items. The backend is called gcwq. There is one gcwq for each possible CPU -and one gcwq to serve work items queued on unbound workqueues. +and one gcwq to serve work items queued on unbound workqueues. Each +gcwq has two thread-pools - one for normal work items and the other +for high priority ones. Subsystems and drivers can create and queue work items through special workqueue API functions as they see fit. They can influence some aspects of the way the work items are executed by setting flags on the workqueue they are putting the work item on. These flags include -things like CPU locality, reentrancy, concurrency limits and more. To -get a detailed overview refer to the API description of +things like CPU locality, reentrancy, concurrency limits, priority and +more. To get a detailed overview refer to the API description of alloc_workqueue() below. -When a work item is queued to a workqueue, the target gcwq is -determined according to the queue parameters and workqueue attributes -and appended on the shared worklist of the gcwq. For example, unless -specifically overridden, a work item of a bound workqueue will be -queued on the worklist of exactly that gcwq that is associated to the -CPU the issuer is running on. +When a work item is queued to a workqueue, the target gcwq and +thread-pool is determined according to the queue parameters and +workqueue attributes and appended on the shared worklist of the +thread-pool. For example, unless specifically overridden, a work item +of a bound workqueue will be queued on the worklist of either normal +or highpri thread-pool of the gcwq that is associated to the CPU the +issuer is running on. For any worker pool implementation, managing the concurrency level (how many execution contexts are active) is an important issue. cmwq @@ -115,26 +118,26 @@ tries to keep the concurrency at a minimal but sufficient level. Minimal to save resources and sufficient in that the system is used at its full capacity. -Each gcwq bound to an actual CPU implements concurrency management by -hooking into the scheduler. The gcwq is notified whenever an active -worker wakes up or sleeps and keeps track of the number of the -currently runnable workers. Generally, work items are not expected to -hog a CPU and consume many cycles. That means maintaining just enough -concurrency to prevent work processing from stalling should be -optimal. As long as there are one or more runnable workers on the -CPU, the gcwq doesn't start execution of a new work, but, when the -last running worker goes to sleep, it immediately schedules a new -worker so that the CPU doesn't sit idle while there are pending work -items. This allows using a minimal number of workers without losing -execution bandwidth. +Each thread-pool bound to an actual CPU implements concurrency +management by hooking into the scheduler. The thread-pool is notified +whenever an active worker wakes up or sleeps and keeps track of the +number of the currently runnable workers. Generally, work items are +not expected to hog a CPU and consume many cycles. That means +maintaining just enough concurrency to prevent work processing from +stalling should be optimal. As long as there are one or more runnable +workers on the CPU, the thread-pool doesn't start execution of a new +work, but, when the last running worker goes to sleep, it immediately +schedules a new worker so that the CPU doesn't sit idle while there +are pending work items. This allows using a minimal number of workers +without losing execution bandwidth. Keeping idle workers around doesn't cost other than the memory space for kthreads, so cmwq holds onto idle ones for a while before killing them. For an unbound wq, the above concurrency management doesn't apply and -the gcwq for the pseudo unbound CPU tries to start executing all work -items as soon as possible. The responsibility of regulating +the thread-pools for the pseudo unbound CPU try to start executing all +work items as soon as possible. The responsibility of regulating concurrency level is on the users. There is also a flag to mark a bound wq to ignore the concurrency management. Please refer to the API section for details. @@ -205,31 +208,22 @@ resources, scheduled and executed. WQ_HIGHPRI - Work items of a highpri wq are queued at the head of the - worklist of the target gcwq and start execution regardless of - the current concurrency level. In other words, highpri work - items will always start execution as soon as execution - resource is available. + Work items of a highpri wq are queued to the highpri + thread-pool of the target gcwq. Highpri thread-pools are + served by worker threads with elevated nice level. - Ordering among highpri work items is preserved - a highpri - work item queued after another highpri work item will start - execution after the earlier highpri work item starts. - - Although highpri work items are not held back by other - runnable work items, they still contribute to the concurrency - level. Highpri work items in runnable state will prevent - non-highpri work items from starting execution. - - This flag is meaningless for unbound wq. + Note that normal and highpri thread-pools don't interact with + each other. Each maintain its separate pool of workers and + implements concurrency management among its workers. WQ_CPU_INTENSIVE Work items of a CPU intensive wq do not contribute to the concurrency level. In other words, runnable CPU intensive - work items will not prevent other work items from starting - execution. This is useful for bound work items which are - expected to hog CPU cycles so that their execution is - regulated by the system scheduler. + work items will not prevent other work items in the same + thread-pool from starting execution. This is useful for bound + work items which are expected to hog CPU cycles so that their + execution is regulated by the system scheduler. Although CPU intensive work items don't contribute to the concurrency level, start of their executions is still @@ -239,14 +233,6 @@ resources, scheduled and executed. This flag is meaningless for unbound wq. - WQ_HIGHPRI | WQ_CPU_INTENSIVE - - This combination makes the wq avoid interaction with - concurrency management completely and behave as a simple - per-CPU execution context provider. Work items queued on a - highpri CPU-intensive wq start execution as soon as resources - are available and don't affect execution of other work items. - @max_active: @max_active determines the maximum number of execution contexts per @@ -328,20 +314,7 @@ If @max_active == 2, 35 w2 wakes up and finishes Now, let's assume w1 and w2 are queued to a different wq q1 which has -WQ_HIGHPRI set, - - TIME IN MSECS EVENT - 0 w1 and w2 start and burn CPU - 5 w1 sleeps - 10 w2 sleeps - 10 w0 starts and burns CPU - 15 w0 sleeps - 15 w1 wakes up and finishes - 20 w2 wakes up and finishes - 25 w0 wakes up and burns CPU - 30 w0 finishes - -If q1 has WQ_CPU_INTENSIVE set, +WQ_CPU_INTENSIVE set, TIME IN MSECS EVENT 0 w0 starts and burns CPU diff --git a/MAINTAINERS b/MAINTAINERS index 5f8ab499444..c56bd02248d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -5566,7 +5566,7 @@ F: Documentation/blockdev/ramdisk.txt F: drivers/block/brd.c RANDOM NUMBER DRIVER -M: Matt Mackall +M: Theodore Ts'o" S: Maintained F: drivers/char/random.c diff --git a/Makefile b/Makefile index 8fd6fb4e32c..dc49d53a357 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 4 -SUBLEVEL = 5 +SUBLEVEL = 30 EXTRAVERSION = NAME = Saber-toothed Squirrel diff --git a/arch/alpha/include/asm/atomic.h b/arch/alpha/include/asm/atomic.h index 3bb7ffeae3b..c2cbe4fc391 100644 --- a/arch/alpha/include/asm/atomic.h +++ b/arch/alpha/include/asm/atomic.h @@ -14,8 +14,8 @@ */ -#define ATOMIC_INIT(i) ( (atomic_t) { (i) } ) -#define ATOMIC64_INIT(i) ( (atomic64_t) { (i) } ) +#define ATOMIC_INIT(i) { (i) } +#define ATOMIC64_INIT(i) { (i) } #define atomic_read(v) (*(volatile int *)&(v)->counter) #define atomic64_read(v) (*(volatile long *)&(v)->counter) diff --git a/arch/alpha/include/asm/fpu.h b/arch/alpha/include/asm/fpu.h index db00f7885fa..e477bcd5b94 100644 --- a/arch/alpha/include/asm/fpu.h +++ b/arch/alpha/include/asm/fpu.h @@ -1,7 +1,9 @@ #ifndef __ASM_ALPHA_FPU_H #define __ASM_ALPHA_FPU_H +#ifdef __KERNEL__ #include +#endif /* * Alpha floating-point control register defines: diff --git a/arch/alpha/include/asm/socket.h b/arch/alpha/include/asm/socket.h index dcb221a4b5b..7d2f75be932 100644 --- a/arch/alpha/include/asm/socket.h +++ b/arch/alpha/include/asm/socket.h @@ -76,9 +76,11 @@ /* Instruct lower device to use last 4-bytes of skb data as FCS */ #define SO_NOFCS 43 +#ifdef __KERNEL__ /* O_NONBLOCK clashes with the bits used for socket types. Therefore we * have to define SOCK_NONBLOCK to a different value here. */ #define SOCK_NONBLOCK 0x40000000 +#endif /* __KERNEL__ */ #endif /* _ASM_SOCKET_H */ diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c index 153d3fce3e8..8e3d91be76b 100644 --- a/arch/alpha/kernel/process.c +++ b/arch/alpha/kernel/process.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -54,8 +55,11 @@ cpu_idle(void) /* FIXME -- EV6 and LCA45 know how to power down the CPU. */ + rcu_idle_enter(); while (!need_resched()) cpu_relax(); + + rcu_idle_exit(); schedule(); } } diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 50752e996c3..275f20264e4 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -599,6 +599,7 @@ config ARCH_KIRKWOOD bool "Marvell Kirkwood" select CPU_FEROCEON select PCI + select PCI_QUIRKS select ARCH_REQUIRE_GPIOLIB select GENERIC_CLOCKEVENTS select NEED_MACH_IO_H @@ -1454,6 +1455,16 @@ config KSAPI Scorpion processor supported hardware performance counters on a per thread basis or AXI counters on an overall system basis. +config ARM_ERRATA_775420 + bool "ARM errata: A data cache maintenance operation which aborts, might lead to deadlock" + depends on CPU_V7 + help + This option enables the workaround for the 775420 Cortex-A9 (r2p2, + r2p6,r2p8,r2p10,r3p0) erratum. In case a date cache maintenance + operation aborts with MMU exception, it might cause the processor + to deadlock. This workaround puts DSB before executing ISB if + an abort may occur on cache maintenance. + endmenu source "arch/arm/common/Kconfig" @@ -2243,6 +2254,7 @@ source "drivers/cpufreq/Kconfig" config CPU_FREQ_IMX tristate "CPUfreq driver for i.MX CPUs" depends on ARCH_MXC && CPU_FREQ + select CPU_FREQ_TABLE help This enables the CPUfreq driver for i.MX CPUs. diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index 06fa42db311..5ee8032ec0b 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S @@ -758,6 +758,7 @@ __armv7_mmu_cache_on: mcrne p15, 0, r0, c8, c7, 0 @ flush I,D TLBs #endif mrc p15, 0, r0, c1, c0, 0 @ read control reg + bic r0, r0, #1 << 28 @ clear SCTLR.TRE orr r0, r0, #0x5000 @ I-cache enable, RR cache replacement orr r0, r0, #0x003c @ write buffer bic r0, r0, #2 @ A (no unaligned access fault) diff --git a/arch/arm/boot/dts/imx53-ard.dts b/arch/arm/boot/dts/imx53-ard.dts index 2dccce46ed8..7541a91b8fa 100644 --- a/arch/arm/boot/dts/imx53-ard.dts +++ b/arch/arm/boot/dts/imx53-ard.dts @@ -70,10 +70,30 @@ interrupt-parent = <&gpio2>; interrupts = <31>; reg-io-width = <4>; + /* + * VDD33A and VDDVARIO of LAN9220 are supplied by + * SW4_3V3 of LTC3589. Before the regulator driver + * for this PMIC is available, we use a fixed dummy + * 3V3 regulator to get LAN9220 driver probing work. + */ + vdd33a-supply = <®_3p3v>; + vddvario-supply = <®_3p3v>; smsc,irq-push-pull; }; }; + regulators { + compatible = "simple-bus"; + + reg_3p3v: 3p3v { + compatible = "regulator-fixed"; + regulator-name = "3P3V"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + }; + gpio-keys { compatible = "gpio-keys"; diff --git a/arch/arm/configs/mxs_defconfig b/arch/arm/configs/mxs_defconfig index 1ebbf451c48..70d0bf40c96 100644 --- a/arch/arm/configs/mxs_defconfig +++ b/arch/arm/configs/mxs_defconfig @@ -32,7 +32,6 @@ CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_PREEMPT_VOLUNTARY=y CONFIG_AEABI=y -CONFIG_DEFAULT_MMAP_MIN_ADDR=65536 CONFIG_AUTO_ZRELADDR=y CONFIG_FPE_NWFPE=y CONFIG_NET=y diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h index d021905cfd1..31fd8cc39e6 100644 --- a/arch/arm/include/asm/cacheflush.h +++ b/arch/arm/include/asm/cacheflush.h @@ -237,7 +237,9 @@ static inline void vivt_flush_cache_mm(struct mm_struct *mm) static inline void vivt_flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end) { - if (cpumask_test_cpu(smp_processor_id(), mm_cpumask(vma->vm_mm))) + struct mm_struct *mm = vma->vm_mm; + + if (!mm || cpumask_test_cpu(smp_processor_id(), mm_cpumask(mm))) __cpuc_flush_user_range(start & PAGE_MASK, PAGE_ALIGN(end), vma->vm_flags); } @@ -245,7 +247,9 @@ vivt_flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned static inline void vivt_flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr, unsigned long pfn) { - if (cpumask_test_cpu(smp_processor_id(), mm_cpumask(vma->vm_mm))) { + struct mm_struct *mm = vma->vm_mm; + + if (!mm || cpumask_test_cpu(smp_processor_id(), mm_cpumask(mm))) { unsigned long addr = user_addr & PAGE_MASK; __cpuc_flush_user_range(addr, addr + PAGE_SIZE, vma->vm_flags); } diff --git a/arch/arm/include/asm/hwcap.h b/arch/arm/include/asm/hwcap.h index 917626128a1..a2fe893802a 100644 --- a/arch/arm/include/asm/hwcap.h +++ b/arch/arm/include/asm/hwcap.h @@ -18,11 +18,12 @@ #define HWCAP_THUMBEE (1 << 11) #define HWCAP_NEON (1 << 12) #define HWCAP_VFPv3 (1 << 13) -#define HWCAP_VFPv3D16 (1 << 14) +#define HWCAP_VFPv3D16 (1 << 14) /* also set for VFPv4-D16 */ #define HWCAP_TLS (1 << 15) #define HWCAP_VFPv4 (1 << 16) #define HWCAP_IDIVA (1 << 17) #define HWCAP_IDIVT (1 << 18) +#define HWCAP_VFPD32 (1 << 19) /* set if VFP has 32 regs (not 16) */ #define HWCAP_IDIV (HWCAP_IDIVA | HWCAP_IDIVT) #if defined(__KERNEL__) diff --git a/arch/arm/include/asm/mutex.h b/arch/arm/include/asm/mutex.h index 87c044910fe..aa872b07e39 100644 --- a/arch/arm/include/asm/mutex.h +++ b/arch/arm/include/asm/mutex.h @@ -18,4 +18,5 @@ #else #include #endif -#endif /* _ASM_MUTEX_H */ +#endif + diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h index 2512e1b7145..6e7b31a9229 100644 --- a/arch/arm/include/asm/pgtable.h +++ b/arch/arm/include/asm/pgtable.h @@ -209,6 +209,18 @@ static inline pte_t *pmd_page_vaddr(pmd_t pmd) #define pte_clear(mm,addr,ptep) set_pte_ext(ptep, __pte(0), 0) +#define pte_none(pte) (!pte_val(pte)) +#define pte_present(pte) (pte_val(pte) & L_PTE_PRESENT) +#define pte_write(pte) (!(pte_val(pte) & L_PTE_RDONLY)) +#define pte_dirty(pte) (pte_val(pte) & L_PTE_DIRTY) +#define pte_young(pte) (pte_val(pte) & L_PTE_YOUNG) +#define pte_exec(pte) (!(pte_val(pte) & L_PTE_XN)) +#define pte_special(pte) (0) + +#define pte_present_user(pte) \ + ((pte_val(pte) & (L_PTE_PRESENT | L_PTE_USER)) == \ + (L_PTE_PRESENT | L_PTE_USER)) + #if __LINUX_ARM_ARCH__ < 6 static inline void __sync_icache_dcache(pte_t pteval) { @@ -220,25 +232,15 @@ extern void __sync_icache_dcache(pte_t pteval); static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pteval) { - if (addr >= TASK_SIZE) - set_pte_ext(ptep, pteval, 0); - else { + unsigned long ext = 0; + + if (addr < TASK_SIZE && pte_present_user(pteval)) { __sync_icache_dcache(pteval); - set_pte_ext(ptep, pteval, PTE_EXT_NG); + ext |= PTE_EXT_NG; } -} -#define pte_none(pte) (!pte_val(pte)) -#define pte_present(pte) (pte_val(pte) & L_PTE_PRESENT) -#define pte_write(pte) (!(pte_val(pte) & L_PTE_RDONLY)) -#define pte_dirty(pte) (pte_val(pte) & L_PTE_DIRTY) -#define pte_young(pte) (pte_val(pte) & L_PTE_YOUNG) -#define pte_exec(pte) (!(pte_val(pte) & L_PTE_XN)) -#define pte_special(pte) (0) - -#define pte_present_user(pte) \ - ((pte_val(pte) & (L_PTE_PRESENT | L_PTE_USER)) == \ - (L_PTE_PRESENT | L_PTE_USER)) + set_pte_ext(ptep, pteval, ext); +} #define PTE_BIT_FUNC(fn,op) \ static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; } @@ -265,13 +267,13 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) * * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 - * <--------------- offset --------------------> <- type --> 0 0 0 + * <--------------- offset ----------------------> < type -> 0 0 0 * - * This gives us up to 63 swap files and 32GB per swap file. Note that + * This gives us up to 31 swap files and 64GB per swap file. Note that * the offset field is always non-zero. */ #define __SWP_TYPE_SHIFT 3 -#define __SWP_TYPE_BITS 6 +#define __SWP_TYPE_BITS 5 #define __SWP_TYPE_MASK ((1 << __SWP_TYPE_BITS) - 1) #define __SWP_OFFSET_SHIFT (__SWP_TYPE_BITS + __SWP_TYPE_SHIFT) diff --git a/arch/arm/include/asm/vfpmacros.h b/arch/arm/include/asm/vfpmacros.h index 3d5fc41ae8d..c49c8f778b5 100644 --- a/arch/arm/include/asm/vfpmacros.h +++ b/arch/arm/include/asm/vfpmacros.h @@ -27,9 +27,9 @@ #if __LINUX_ARM_ARCH__ <= 6 ldr \tmp, =elf_hwcap @ may not have MVFR regs ldr \tmp, [\tmp, #0] - tst \tmp, #HWCAP_VFPv3D16 - ldceq p11, cr0, [\base],#32*4 @ FLDMIAD \base!, {d16-d31} - addne \base, \base, #32*4 @ step over unused register space + tst \tmp, #HWCAP_VFPD32 + ldcnel p11, cr0, [\base],#32*4 @ FLDMIAD \base!, {d16-d31} + addeq \base, \base, #32*4 @ step over unused register space #else VFPFMRX \tmp, MVFR0 @ Media and VFP Feature Register 0 and \tmp, \tmp, #MVFR0_A_SIMD_MASK @ A_SIMD field @@ -51,9 +51,9 @@ #if __LINUX_ARM_ARCH__ <= 6 ldr \tmp, =elf_hwcap @ may not have MVFR regs ldr \tmp, [\tmp, #0] - tst \tmp, #HWCAP_VFPv3D16 - stceq p11, cr0, [\base],#32*4 @ FSTMIAD \base!, {d16-d31} - addne \base, \base, #32*4 @ step over unused register space + tst \tmp, #HWCAP_VFPD32 + stcnel p11, cr0, [\base],#32*4 @ FSTMIAD \base!, {d16-d31} + addeq \base, \base, #32*4 @ step over unused register space #else VFPFMRX \tmp, MVFR0 @ Media and VFP Feature Register 0 and \tmp, \tmp, #MVFR0_A_SIMD_MASK @ A_SIMD field diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 3a4ceabf78a..9fd63186e4c 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -244,6 +244,19 @@ svc_preempt: b 1b #endif +__und_fault: + @ Correct the PC such that it is pointing at the instruction + @ which caused the fault. If the faulting instruction was ARM + @ the PC will be pointing at the next instruction, and have to + @ subtract 4. Otherwise, it is Thumb, and the PC will be + @ pointing at the second half of the Thumb instruction. We + @ have to subtract 2. + ldr r2, [r0, #S_PC] + sub r2, r2, r1 + str r2, [r0, #S_PC] + b do_undefinstr +ENDPROC(__und_fault) + .align 5 __und_svc: #ifdef CONFIG_KPROBES @@ -261,25 +274,32 @@ __und_svc: @ @ r0 - instruction @ -#ifndef CONFIG_THUMB2_KERNEL +#ifndef CONFIG_THUMB2_KERNEL ldr r0, [r4, #-4] #else + mov r1, #2 ldrh r0, [r4, #-2] @ Thumb instruction at LR - 2 cmp r0, #0xe800 @ 32-bit instruction if xx >= 0 - ldrhhs r9, [r4] @ bottom 16 bits - orrhs r0, r9, r0, lsl #16 + blo __und_svc_fault + ldrh r9, [r4] @ bottom 16 bits + add r4, r4, #2 + str r4, [sp, #S_PC] + orr r0, r9, r0, lsl #16 #endif - adr r9, BSYM(1f) + adr r9, BSYM(__und_svc_finish) mov r2, r4 bl call_fpe + mov r1, #4 @ PC correction to apply +__und_svc_fault: mov r0, sp @ struct pt_regs *regs - bl do_undefinstr + bl __und_fault @ @ IRQs off again before pulling preserved data off the stack @ -1: disable_irq_notrace +__und_svc_finish: + disable_irq_notrace @ @ restore SPSR and restart the instruction @@ -423,25 +443,33 @@ __und_usr: mov r2, r4 mov r3, r5 + @ r2 = regs->ARM_pc, which is either 2 or 4 bytes ahead of the + @ faulting instruction depending on Thumb mode. + @ r3 = regs->ARM_cpsr @ - @ fall through to the emulation code, which returns using r9 if - @ it has emulated the instruction, or the more conventional lr - @ if we are to treat this as a real undefined instruction - @ - @ r0 - instruction + @ The emulation code returns using r9 if it has emulated the + @ instruction, or the more conventional lr if we are to treat + @ this as a real undefined instruction @ adr r9, BSYM(ret_from_exception) - adr lr, BSYM(__und_usr_unknown) + tst r3, #PSR_T_BIT @ Thumb mode? - itet eq @ explicit IT needed for the 1f label - subeq r4, r2, #4 @ ARM instr at LR - 4 - subne r4, r2, #2 @ Thumb instr at LR - 2 -1: ldreqt r0, [r4] + bne __und_usr_thumb + sub r4, r2, #4 @ ARM instr at LR - 4 +1: ldrt r0, [r4] #ifdef CONFIG_CPU_ENDIAN_BE8 - reveq r0, r0 @ little endian instruction + rev r0, r0 @ little endian instruction #endif - beq call_fpe + @ r0 = 32-bit ARM instruction which caused the exception + @ r2 = PC value for the following instruction (:= regs->ARM_pc) + @ r4 = PC value for the faulting instruction + @ lr = 32-bit undefined instruction function + adr lr, BSYM(__und_usr_fault_32) + b call_fpe + +__und_usr_thumb: @ Thumb instruction + sub r4, r2, #2 @ First half of thumb instr at LR - 2 #if CONFIG_ARM_THUMB && __LINUX_ARM_ARCH__ >= 6 && CONFIG_CPU_V7 /* * Thumb-2 instruction handling. Note that because pre-v6 and >= v6 platforms @@ -455,7 +483,7 @@ __und_usr: ldr r5, .LCcpu_architecture ldr r5, [r5] cmp r5, #CPU_ARCH_ARMv7 - blo __und_usr_unknown + blo __und_usr_fault_16 @ 16bit undefined instruction /* * The following code won't get run unless the running CPU really is v7, so * coding round the lack of ldrht on older arches is pointless. Temporarily @@ -463,15 +491,18 @@ __und_usr: */ .arch armv6t2 #endif -2: - ARM( ldrht r5, [r4], #2 ) - THUMB( ldrht r5, [r4] ) - THUMB( add r4, r4, #2 ) +2: ldrht r5, [r4] cmp r5, #0xe800 @ 32bit instruction if xx != 0 - blo __und_usr_unknown -3: ldrht r0, [r4] + blo __und_usr_fault_16 @ 16bit undefined instruction +3: ldrht r0, [r2] add r2, r2, #2 @ r2 is PC + 2, make it PC + 4 + str r2, [sp, #S_PC] @ it's a 2x16bit instr, update orr r0, r0, r5, lsl #16 + adr lr, BSYM(__und_usr_fault_32) + @ r0 = the two 16-bit Thumb instructions which caused the exception + @ r2 = PC value for the following Thumb instruction (:= regs->ARM_pc) + @ r4 = PC value for the first 16-bit Thumb instruction + @ lr = 32bit undefined instruction function #if __LINUX_ARM_ARCH__ < 7 /* If the target arch was overridden, change it back: */ @@ -482,17 +513,13 @@ __und_usr: #endif #endif /* __LINUX_ARM_ARCH__ < 7 */ #else /* !(CONFIG_ARM_THUMB && __LINUX_ARM_ARCH__ >= 6 && CONFIG_CPU_V7) */ - b __und_usr_unknown + b __und_usr_fault_16 #endif - UNWIND(.fnend ) + UNWIND(.fnend) ENDPROC(__und_usr) - @ - @ fallthrough to call_fpe - @ - /* - * The out of line fixup for the ldrt above. + * The out of line fixup for the ldrt instructions above. */ .pushsection .fixup, "ax" 4: mov pc, r9 @@ -523,11 +550,12 @@ ENDPROC(__und_usr) * NEON handler code. * * Emulators may wish to make use of the following registers: - * r0 = instruction opcode. - * r2 = PC+4 + * r0 = instruction opcode (32-bit ARM or two 16-bit Thumb) + * r2 = PC value to resume execution after successful emulation * r9 = normal "successful" return address - * r10 = this threads thread_info structure. + * r10 = this threads thread_info structure * lr = unrecognised instruction return address + * IRQs disabled, FIQs enabled. */ @ @ Fall-through from Thumb-2 __und_usr @@ -662,12 +690,17 @@ ENTRY(no_fp) mov pc, lr ENDPROC(no_fp) -__und_usr_unknown: - enable_irq +__und_usr_fault_32: + mov r1, #4 + b 1f +__und_usr_fault_16: + mov r1, #2 +1: enable_irq mov r0, sp adr lr, BSYM(ret_from_exception) - b do_undefinstr -ENDPROC(__und_usr_unknown) + b __und_fault +ENDPROC(__und_usr_fault_32) +ENDPROC(__und_usr_fault_16) .align 5 __pabt_usr: diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c index 21920cebf83..952b5778f07 100644 --- a/arch/arm/kernel/hw_breakpoint.c +++ b/arch/arm/kernel/hw_breakpoint.c @@ -159,6 +159,12 @@ static int debug_arch_supported(void) arch >= ARM_DEBUG_ARCH_V7_1; } +/* Can we determine the watchpoint access type from the fsr? */ +static int debug_exception_updates_fsr(void) +{ + return 0; +} + /* Determine number of WRP registers available. */ static int get_num_wrp_resources(void) { @@ -619,18 +625,35 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp) info->address &= ~alignment_mask; info->ctrl.len <<= offset; - /* - * Currently we rely on an overflow handler to take - * care of single-stepping the breakpoint when it fires. - * In the case of userspace breakpoints on a core with V7 debug, - * we can use the mismatch feature as a poor-man's hardware - * single-step, but this only works for per-task breakpoints. - */ - if (!bp->overflow_handler && (arch_check_bp_in_kernelspace(bp) || - !core_has_mismatch_brps() || !bp->hw.bp_target)) { - pr_warning("overflow handler required but none found\n"); - ret = -EINVAL; + if (!bp->overflow_handler) { + /* + * Mismatch breakpoints are required for single-stepping + * breakpoints. + */ + if (!core_has_mismatch_brps()) + return -EINVAL; + + /* We don't allow mismatch breakpoints in kernel space. */ + if (arch_check_bp_in_kernelspace(bp)) + return -EPERM; + + /* + * Per-cpu breakpoints are not supported by our stepping + * mechanism. + */ + if (!bp->hw.bp_target) + return -EINVAL; + + /* + * We only support specific access types if the fsr + * reports them. + */ + if (!debug_exception_updates_fsr() && + (info->ctrl.type == ARM_BREAKPOINT_LOAD || + info->ctrl.type == ARM_BREAKPOINT_STORE)) + return -EINVAL; } + out: return ret; } @@ -706,10 +729,12 @@ static void watchpoint_handler(unsigned long addr, unsigned int fsr, goto unlock; /* Check that the access type matches. */ - access = (fsr & ARM_FSR_ACCESS_MASK) ? HW_BREAKPOINT_W : - HW_BREAKPOINT_R; - if (!(access & hw_breakpoint_type(wp))) - goto unlock; + if (debug_exception_updates_fsr()) { + access = (fsr & ARM_FSR_ACCESS_MASK) ? + HW_BREAKPOINT_W : HW_BREAKPOINT_R; + if (!(access & hw_breakpoint_type(wp))) + goto unlock; + } /* We have a winner. */ info->trigger = addr; diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 0ff45bdf83f..691ddcfb839 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -318,6 +318,7 @@ void machine_shutdown(void) void machine_halt(void) { machine_shutdown(); + local_irq_disable(); while (1); } @@ -343,6 +344,7 @@ void machine_restart(char *cmd) /* Whoops - the platform was unable to reboot. Tell the user! */ printk("Reboot failed -- System halted\n"); + local_irq_disable(); while (1); } diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 528828109b8..bf28ac064e7 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -229,18 +229,24 @@ static void smp_store_cpu_info(unsigned int cpuid) asmlinkage void secondary_start_kernel(void) { struct mm_struct *mm = &init_mm; - unsigned int cpu = smp_processor_id(); + unsigned int cpu; + + /* + * The identity mapping is uncached (strongly ordered), so + * switch away from it before attempting any exclusive accesses. + */ + cpu_switch_mm(mm->pgd, mm); + enter_lazy_tlb(mm, current); + local_flush_tlb_all(); /* * All kernel threads share the same mm context; grab a * reference and switch to it. */ + cpu = smp_processor_id(); atomic_inc(&mm->mm_count); current->active_mm = mm; cpumask_set_cpu(cpu, mm_cpumask(mm)); - cpu_switch_mm(mm->pgd, mm); - enter_lazy_tlb(mm, current); - local_flush_tlb_all(); pr_debug("CPU%u: Booted secondary processor\n", cpu); diff --git a/arch/arm/kernel/swp_emulate.c b/arch/arm/kernel/swp_emulate.c index 5d144851288..dd5ba5e7b6f 100644 --- a/arch/arm/kernel/swp_emulate.c +++ b/arch/arm/kernel/swp_emulate.c @@ -109,10 +109,12 @@ static void set_segfault(struct pt_regs *regs, unsigned long addr) { siginfo_t info; + down_read(¤t->mm->mmap_sem); if (find_vma(current->mm, addr) == NULL) info.si_code = SEGV_MAPERR; else info.si_code = SEGV_ACCERR; + up_read(¤t->mm->mmap_sem); info.si_signo = SIGSEGV; info.si_errno = 0; diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 12e6fcbd500..0d4e5daa4c1 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -399,18 +399,10 @@ static int call_undef_hook(struct pt_regs *regs, unsigned int instr) asmlinkage void __exception do_undefinstr(struct pt_regs *regs) { - unsigned int correction = thumb_mode(regs) ? 2 : 4; unsigned int instr; siginfo_t info; void __user *pc; - /* - * According to the ARM ARM, PC is 2 or 4 bytes ahead, - * depending whether we're in Thumb mode or not. - * Correct this offset. - */ - regs->ARM_pc -= correction; - pc = (void __user *)instruction_pointer(regs); if (processor_mode(regs) == SVC_MODE) { @@ -425,20 +417,23 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs) #endif instr = *(u32 *) pc; } else if (thumb_mode(regs)) { - get_user(instr, (u16 __user *)pc); + if (get_user(instr, (u16 __user *)pc)) + goto die_sig; if (is_wide_instruction(instr)) { unsigned int instr2; - get_user(instr2, (u16 __user *)pc+1); + if (get_user(instr2, (u16 __user *)pc+1)) + goto die_sig; instr <<= 16; instr |= instr2; } - } else { - get_user(instr, (u32 __user *)pc); + } else if (get_user(instr, (u32 __user *)pc)) { + goto die_sig; } if (call_undef_hook(regs, instr) == 0) return; +die_sig: trace_undef_instr(regs, (void *)pc); #ifdef CONFIG_DEBUG_USER diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c index 05774e5b1cb..3b0c719f9fe 100644 --- a/arch/arm/mach-at91/at91rm9200_devices.c +++ b/arch/arm/mach-at91/at91rm9200_devices.c @@ -463,7 +463,7 @@ static struct i2c_gpio_platform_data pdata = { static struct platform_device at91rm9200_twi_device = { .name = "i2c-gpio", - .id = -1, + .id = 0, .dev.platform_data = &pdata, }; diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c index 5652dde4bbe..151fec4ccf2 100644 --- a/arch/arm/mach-at91/at91sam9260_devices.c +++ b/arch/arm/mach-at91/at91sam9260_devices.c @@ -468,7 +468,7 @@ static struct i2c_gpio_platform_data pdata = { static struct platform_device at91sam9260_twi_device = { .name = "i2c-gpio", - .id = -1, + .id = 0, .dev.platform_data = &pdata, }; diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c index 4db961a9308..8a29c6cbe08 100644 --- a/arch/arm/mach-at91/at91sam9261_devices.c +++ b/arch/arm/mach-at91/at91sam9261_devices.c @@ -285,7 +285,7 @@ static struct i2c_gpio_platform_data pdata = { static struct platform_device at91sam9261_twi_device = { .name = "i2c-gpio", - .id = -1, + .id = 0, .dev.platform_data = &pdata, }; diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c index fe99206de88..8d443225266 100644 --- a/arch/arm/mach-at91/at91sam9263_devices.c +++ b/arch/arm/mach-at91/at91sam9263_devices.c @@ -542,7 +542,7 @@ static struct i2c_gpio_platform_data pdata = { static struct platform_device at91sam9263_twi_device = { .name = "i2c-gpio", - .id = -1, + .id = 0, .dev.platform_data = &pdata, }; diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c index fe4ae22e856..b8d4114ea22 100644 --- a/arch/arm/mach-at91/at91sam9rl_devices.c +++ b/arch/arm/mach-at91/at91sam9rl_devices.c @@ -314,7 +314,7 @@ static struct i2c_gpio_platform_data pdata = { static struct platform_device at91sam9rl_twi_device = { .name = "i2c-gpio", - .id = -1, + .id = 0, .dev.platform_data = &pdata, }; diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c index f44a2e7272e..55293a78cfa 100644 --- a/arch/arm/mach-at91/setup.c +++ b/arch/arm/mach-at91/setup.c @@ -104,6 +104,8 @@ static void __init soc_detect(u32 dbgu_base) switch (socid) { case ARCH_ID_AT91RM9200: at91_soc_initdata.type = AT91_SOC_RM9200; + if (at91_soc_initdata.subtype == AT91_SOC_SUBTYPE_NONE) + at91_soc_initdata.subtype = AT91_SOC_RM9200_BGA; at91_boot_soc = at91rm9200_soc; break; @@ -146,7 +148,7 @@ static void __init soc_detect(u32 dbgu_base) } /* at91sam9g10 */ - if ((cidr & ~AT91_CIDR_EXT) == ARCH_ID_AT91SAM9G10) { + if ((socid & ~AT91_CIDR_EXT) == ARCH_ID_AT91SAM9G10) { at91_soc_initdata.type = AT91_SOC_SAM9G10; at91_boot_soc = at91sam9261_soc; } diff --git a/arch/arm/mach-dove/include/mach/pm.h b/arch/arm/mach-dove/include/mach/pm.h index 3ad9f946a9e..11799c33475 100644 --- a/arch/arm/mach-dove/include/mach/pm.h +++ b/arch/arm/mach-dove/include/mach/pm.h @@ -45,7 +45,7 @@ static inline int pmu_to_irq(int pin) static inline int irq_to_pmu(int irq) { - if (IRQ_DOVE_PMU_START < irq && irq < NR_IRQS) + if (IRQ_DOVE_PMU_START <= irq && irq < NR_IRQS) return irq - IRQ_DOVE_PMU_START; return -EINVAL; diff --git a/arch/arm/mach-dove/irq.c b/arch/arm/mach-dove/irq.c index f07fd16e0c9..9f2fd100174 100644 --- a/arch/arm/mach-dove/irq.c +++ b/arch/arm/mach-dove/irq.c @@ -61,8 +61,20 @@ static void pmu_irq_ack(struct irq_data *d) int pin = irq_to_pmu(d->irq); u32 u; + /* + * The PMU mask register is not RW0C: it is RW. This means that + * the bits take whatever value is written to them; if you write + * a '1', you will set the interrupt. + * + * Unfortunately this means there is NO race free way to clear + * these interrupts. + * + * So, let's structure the code so that the window is as small as + * possible. + */ u = ~(1 << (pin & 31)); - writel(u, PMU_INTERRUPT_CAUSE); + u &= readl_relaxed(PMU_INTERRUPT_CAUSE); + writel_relaxed(u, PMU_INTERRUPT_CAUSE); } static struct irq_chip pmu_irq_chip = { diff --git a/arch/arm/mach-imx/hotplug.c b/arch/arm/mach-imx/hotplug.c index 20ed2d56c1a..f8f7437c83b 100644 --- a/arch/arm/mach-imx/hotplug.c +++ b/arch/arm/mach-imx/hotplug.c @@ -42,22 +42,6 @@ static inline void cpu_enter_lowpower(void) : "cc"); } -static inline void cpu_leave_lowpower(void) -{ - unsigned int v; - - asm volatile( - "mrc p15, 0, %0, c1, c0, 0\n" - " orr %0, %0, %1\n" - " mcr p15, 0, %0, c1, c0, 0\n" - " mrc p15, 0, %0, c1, c0, 1\n" - " orr %0, %0, %2\n" - " mcr p15, 0, %0, c1, c0, 1\n" - : "=&r" (v) - : "Ir" (CR_C), "Ir" (0x40) - : "cc"); -} - /* * platform-specific code to shutdown a CPU * @@ -67,11 +51,10 @@ void platform_cpu_die(unsigned int cpu) { cpu_enter_lowpower(); imx_enable_cpu(cpu, false); - cpu_do_idle(); - cpu_leave_lowpower(); - /* We should never return from idle */ - panic("cpu %d unexpectedly exit from shutdown\n", cpu); + /* spin here until hardware takes it down */ + while (1) + ; } int platform_cpu_disable(unsigned int cpu) diff --git a/arch/arm/mach-kirkwood/pcie.c b/arch/arm/mach-kirkwood/pcie.c index f56a0118c1b..c46d20e5f3f 100644 --- a/arch/arm/mach-kirkwood/pcie.c +++ b/arch/arm/mach-kirkwood/pcie.c @@ -212,14 +212,19 @@ static int __init kirkwood_pcie_setup(int nr, struct pci_sys_data *sys) return 1; } +/* + * The root complex has a hardwired class of PCI_CLASS_MEMORY_OTHER, when it + * is operating as a root complex this needs to be switched to + * PCI_CLASS_BRIDGE_HOST or Linux will errantly try to process the BAR's on + * the device. Decoding setup is handled by the orion code. + */ static void __devinit rc_pci_fixup(struct pci_dev *dev) { - /* - * Prevent enumeration of root complex. - */ if (dev->bus->parent == NULL && dev->devfn == 0) { int i; + dev->class &= 0xff; + dev->class |= PCI_CLASS_BRIDGE_HOST << 8; for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) { dev->resource[i].start = 0; dev->resource[i].end = 0; diff --git a/arch/arm/mach-omap2/opp.c b/arch/arm/mach-omap2/opp.c index de6d4645174..d8f6dbf45d1 100644 --- a/arch/arm/mach-omap2/opp.c +++ b/arch/arm/mach-omap2/opp.c @@ -53,7 +53,7 @@ int __init omap_init_opp_table(struct omap_opp_def *opp_def, omap_table_init = 1; /* Lets now register with OPP library */ - for (i = 0; i < opp_def_size; i++) { + for (i = 0; i < opp_def_size; i++, opp_def++) { struct omap_hwmod *oh; struct device *dev; @@ -86,7 +86,6 @@ int __init omap_init_opp_table(struct omap_opp_def *opp_def, __func__, opp_def->freq, opp_def->hwmod_name, i, r); } - opp_def++; } return 0; diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h b/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h index a65867209aa..b4eb3daf037 100644 --- a/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h +++ b/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h @@ -462,6 +462,9 @@ GPIO76_LCD_PCLK, \ GPIO77_LCD_BIAS +/* these enable a work-around for a hw bug in pxa27x during ac97 warm reset */ +#define GPIO113_AC97_nRESET_GPIO_HIGH MFP_CFG_OUT(GPIO113, AF0, DEFAULT) +#define GPIO95_AC97_nRESET_GPIO_HIGH MFP_CFG_OUT(GPIO95, AF0, DEFAULT) extern int keypad_set_wake(unsigned int on); #endif /* __ASM_ARCH_MFP_PXA27X_H */ diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c index 4726c246dcd..a2fe795bae1 100644 --- a/arch/arm/mach-pxa/pxa27x.c +++ b/arch/arm/mach-pxa/pxa27x.c @@ -47,9 +47,9 @@ void pxa27x_clear_otgph(void) EXPORT_SYMBOL(pxa27x_clear_otgph); static unsigned long ac97_reset_config[] = { - GPIO113_GPIO, + GPIO113_AC97_nRESET_GPIO_HIGH, GPIO113_AC97_nRESET, - GPIO95_GPIO, + GPIO95_AC97_nRESET_GPIO_HIGH, GPIO95_AC97_nRESET, }; diff --git a/arch/arm/mach-pxa/raumfeld.c b/arch/arm/mach-pxa/raumfeld.c index 5905ed130e9..d89d87ae144 100644 --- a/arch/arm/mach-pxa/raumfeld.c +++ b/arch/arm/mach-pxa/raumfeld.c @@ -953,12 +953,12 @@ static struct i2c_board_info raumfeld_connector_i2c_board_info __initdata = { static struct eeti_ts_platform_data eeti_ts_pdata = { .irq_active_high = 1, + .irq_gpio = GPIO_TOUCH_IRQ, }; static struct i2c_board_info raumfeld_controller_i2c_board_info __initdata = { .type = "eeti_ts", .addr = 0x0a, - .irq = PXA_GPIO_TO_IRQ(GPIO_TOUCH_IRQ), .platform_data = &eeti_ts_pdata, }; diff --git a/arch/arm/mach-realview/include/mach/board-eb.h b/arch/arm/mach-realview/include/mach/board-eb.h index 124bce6b4d7..a301e61a555 100644 --- a/arch/arm/mach-realview/include/mach/board-eb.h +++ b/arch/arm/mach-realview/include/mach/board-eb.h @@ -47,7 +47,7 @@ #define REALVIEW_EB_USB_BASE 0x4F000000 /* USB */ #ifdef CONFIG_REALVIEW_EB_ARM11MP_REVB -#define REALVIEW_EB11MP_PRIV_MEM_BASE 0x1F000000 +#define REALVIEW_EB11MP_PRIV_MEM_BASE 0x10100000 #define REALVIEW_EB11MP_L220_BASE 0x10102000 /* L220 registers */ #define REALVIEW_EB11MP_SYS_PLD_CTRL1 0xD8 /* Register offset for MPCore sysctl */ #else diff --git a/arch/arm/mach-s3c24xx/include/mach/dma.h b/arch/arm/mach-s3c24xx/include/mach/dma.h index acbdfecd418..ccaaafc65c1 100644 --- a/arch/arm/mach-s3c24xx/include/mach/dma.h +++ b/arch/arm/mach-s3c24xx/include/mach/dma.h @@ -24,7 +24,8 @@ */ enum dma_ch { - DMACH_XD0, + DMACH_DT_PROP = -1, /* not yet supported, do not use */ + DMACH_XD0 = 0, DMACH_XD1, DMACH_SDI, DMACH_SPI0, diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S index a655d3da386..82ab2c5b4ac 100644 --- a/arch/arm/mm/cache-v7.S +++ b/arch/arm/mm/cache-v7.S @@ -211,6 +211,9 @@ ENTRY(v7_coherent_user_range) * isn't mapped, just try the next page. */ 9001: +#ifdef CONFIG_ARM_ERRATA_775420 + dsb +#endif mov r12, r12, lsr #12 mov r12, r12, lsl #12 add r12, r12, #4096 diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c index 77458548e03..40ca11ed6e5 100644 --- a/arch/arm/mm/flush.c +++ b/arch/arm/mm/flush.c @@ -231,8 +231,6 @@ void __sync_icache_dcache(pte_t pteval) struct page *page; struct address_space *mapping; - if (!pte_present_user(pteval)) - return; if (cache_is_vipt_nonaliasing() && !pte_exec(pteval)) /* only flush non-aliasing VIPT caches for exec mappings */ return; diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index da33be0f13c..aa6462321c1 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -525,7 +525,7 @@ static void __init build_mem_type_table(void) #endif for (i = 0; i < 16; i++) { - unsigned long v = pgprot_val(protection_map[i]); + pteval_t v = pgprot_val(protection_map[i]); protection_map[i] = __pgprot(v | user_pgprot); } diff --git a/arch/arm/plat-omap/counter_32k.c b/arch/arm/plat-omap/counter_32k.c index 5068fe5a691..fd433e7a25f 100644 --- a/arch/arm/plat-omap/counter_32k.c +++ b/arch/arm/plat-omap/counter_32k.c @@ -50,22 +50,29 @@ static u32 notrace omap_32k_read_sched_clock(void) * nsecs and adds to a monotonically increasing timespec. */ static struct timespec persistent_ts; -static cycles_t cycles, last_cycles; +static cycles_t cycles; static unsigned int persistent_mult, persistent_shift; +static DEFINE_SPINLOCK(read_persistent_clock_lock); + void read_persistent_clock(struct timespec *ts) { unsigned long long nsecs; - cycles_t delta; - struct timespec *tsp = &persistent_ts; + cycles_t last_cycles; + unsigned long flags; + + spin_lock_irqsave(&read_persistent_clock_lock, flags); last_cycles = cycles; cycles = timer_32k_base ? __raw_readl(timer_32k_base) : 0; - delta = cycles - last_cycles; - nsecs = clocksource_cyc2ns(delta, persistent_mult, persistent_shift); + nsecs = clocksource_cyc2ns(cycles - last_cycles, + persistent_mult, persistent_shift); + + timespec_add_ns(&persistent_ts, nsecs); + + *ts = persistent_ts; - timespec_add_ns(tsp, nsecs); - *ts = *tsp; + spin_unlock_irqrestore(&read_persistent_clock_lock, flags); } int __init omap_init_clocksource_32k(void) diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c index 652139c0339..7ac301ee283 100644 --- a/arch/arm/plat-omap/dmtimer.c +++ b/arch/arm/plat-omap/dmtimer.c @@ -238,7 +238,7 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_enable); void omap_dm_timer_disable(struct omap_dm_timer *timer) { - pm_runtime_put(&timer->pdev->dev); + pm_runtime_put_sync(&timer->pdev->dev); } EXPORT_SYMBOL_GPL(omap_dm_timer_disable); diff --git a/arch/arm/plat-s3c24xx/dma.c b/arch/arm/plat-s3c24xx/dma.c index 28f898f7538..db98e7021f0 100644 --- a/arch/arm/plat-s3c24xx/dma.c +++ b/arch/arm/plat-s3c24xx/dma.c @@ -430,7 +430,7 @@ s3c2410_dma_canload(struct s3c2410_dma_chan *chan) * when necessary. */ -int s3c2410_dma_enqueue(unsigned int channel, void *id, +int s3c2410_dma_enqueue(enum dma_ch channel, void *id, dma_addr_t data, int size) { struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel); diff --git a/arch/arm/plat-s5p/clock.c b/arch/arm/plat-s5p/clock.c index f68a9bb1194..b04279512e2 100644 --- a/arch/arm/plat-s5p/clock.c +++ b/arch/arm/plat-s5p/clock.c @@ -38,6 +38,7 @@ struct clk clk_ext_xtal_mux = { struct clk clk_xusbxti = { .name = "xusbxti", .id = -1, + .rate = 24000000, }; struct clk s5p_clk_27m = { diff --git a/arch/arm/plat-samsung/adc.c b/arch/arm/plat-samsung/adc.c index 33ecd0c9f0c..b1e05ccff3a 100644 --- a/arch/arm/plat-samsung/adc.c +++ b/arch/arm/plat-samsung/adc.c @@ -157,11 +157,13 @@ int s3c_adc_start(struct s3c_adc_client *client, return -EINVAL; } - if (client->is_ts && adc->ts_pend) - return -EAGAIN; - spin_lock_irqsave(&adc->lock, flags); + if (client->is_ts && adc->ts_pend) { + spin_unlock_irqrestore(&adc->lock, flags); + return -EAGAIN; + } + client->channel = channel; client->nr_samples = nr_samples; diff --git a/arch/arm/vfp/entry.S b/arch/arm/vfp/entry.S index c1a97840258..50a724a8334 100644 --- a/arch/arm/vfp/entry.S +++ b/arch/arm/vfp/entry.S @@ -7,20 +7,22 @@ * 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. - * - * Basic entry code, called from the kernel's undefined instruction trap. - * r0 = faulted instruction - * r2 = faulted PC+4 - * r9 = successful return - * r10 = thread_info structure - * lr = failure return */ #include #include #include "../kernel/entry-header.S" +@ VFP entry point. +@ +@ r0 = instruction opcode (32-bit ARM or two 16-bit Thumb) +@ r2 = PC value to resume execution after successful emulation +@ r9 = normal "successful" return address +@ r10 = this threads thread_info structure +@ lr = unrecognised instruction return address +@ IRQs disabled. +@ ENTRY(do_vfp) -#ifdef CONFIG_PREEMPT +#ifdef CONFIG_PREEMPT_COUNT ldr r4, [r10, #TI_PREEMPT] @ get preempt count add r11, r4, #1 @ increment it str r11, [r10, #TI_PREEMPT] @@ -34,7 +36,7 @@ ENTRY(do_vfp) ENDPROC(do_vfp) ENTRY(vfp_null_entry) -#ifdef CONFIG_PREEMPT +#ifdef CONFIG_PREEMPT_COUNT get_thread_info r10 ldr r4, [r10, #TI_PREEMPT] @ get preempt count sub r11, r4, #1 @ decrement it @@ -52,7 +54,7 @@ ENDPROC(vfp_null_entry) __INIT ENTRY(vfp_testing_entry) -#ifdef CONFIG_PREEMPT +#ifdef CONFIG_PREEMPT_COUNT get_thread_info r10 ldr r4, [r10, #TI_PREEMPT] @ get preempt count sub r11, r4, #1 @ decrement it diff --git a/arch/arm/vfp/vfphw.S b/arch/arm/vfp/vfphw.S index bd3d7717e85..e8a55b7533e 100644 --- a/arch/arm/vfp/vfphw.S +++ b/arch/arm/vfp/vfphw.S @@ -61,13 +61,13 @@ @ VFP hardware support entry point. @ -@ r0 = faulted instruction -@ r2 = faulted PC+4 -@ r9 = successful return +@ r0 = instruction opcode (32-bit ARM or two 16-bit Thumb) +@ r2 = PC value to resume execution after successful emulation +@ r9 = normal "successful" return address @ r10 = vfp_state union @ r11 = CPU number -@ lr = failure return - +@ lr = unrecognised instruction return address +@ IRQs enabled. ENTRY(vfp_support_entry) DBGSTR3 "instr %08x pc %08x state %p", r0, r2, r10 @@ -161,10 +161,13 @@ vfp_hw_state_valid: @ exception before retrying branch @ out before setting an FPEXC that @ stops us reading stuff - VFPFMXR FPEXC, r1 @ restore FPEXC last - sub r2, r2, #4 - str r2, [sp, #S_PC] @ retry the instruction -#ifdef CONFIG_PREEMPT + VFPFMXR FPEXC, r1 @ Restore FPEXC last + sub r2, r2, #4 @ Retry current instruction - if Thumb + str r2, [sp, #S_PC] @ mode it's two 16-bit instructions, + @ else it's one 32-bit instruction, so + @ always subtract 4 from the following + @ instruction address. +#ifdef CONFIG_PREEMPT_COUNT get_thread_info r10 ldr r4, [r10, #TI_PREEMPT] @ get preempt count sub r11, r4, #1 @ decrement it @@ -204,7 +207,7 @@ skip: @ not recognised by VFP DBGSTR "not VFP" -#ifdef CONFIG_PREEMPT +#ifdef CONFIG_PREEMPT_COUNT get_thread_info r10 ldr r4, [r10, #TI_PREEMPT] @ get preempt count sub r11, r4, #1 @ decrement it diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c index e62af21a725..fb540cc60b7 100644 --- a/arch/arm/vfp/vfpmodule.c +++ b/arch/arm/vfp/vfpmodule.c @@ -730,11 +730,14 @@ static int __init vfp_init(void) elf_hwcap |= HWCAP_VFPv3; /* - * Check for VFPv3 D16. CPUs in this configuration - * only have 16 x 64bit registers. + * Check for VFPv3 D16 and VFPv4 D16. CPUs in + * this configuration only have 16 x 64bit + * registers. */ if (((fmrx(MVFR0) & MVFR0_A_SIMD_MASK)) == 1) - elf_hwcap |= HWCAP_VFPv3D16; + elf_hwcap |= HWCAP_VFPv3D16; /* also v4-D16 */ + else + elf_hwcap |= HWCAP_VFPD32; } #endif /* diff --git a/arch/cris/include/asm/io.h b/arch/cris/include/asm/io.h index 32567bc2a42..ac12ae2b928 100644 --- a/arch/cris/include/asm/io.h +++ b/arch/cris/include/asm/io.h @@ -133,12 +133,39 @@ static inline void writel(unsigned int b, volatile void __iomem *addr) #define insb(port,addr,count) (cris_iops ? cris_iops->read_io(port,addr,1,count) : 0) #define insw(port,addr,count) (cris_iops ? cris_iops->read_io(port,addr,2,count) : 0) #define insl(port,addr,count) (cris_iops ? cris_iops->read_io(port,addr,4,count) : 0) -#define outb(data,port) if (cris_iops) cris_iops->write_io(port,(void*)(unsigned)data,1,1) -#define outw(data,port) if (cris_iops) cris_iops->write_io(port,(void*)(unsigned)data,2,1) -#define outl(data,port) if (cris_iops) cris_iops->write_io(port,(void*)(unsigned)data,4,1) -#define outsb(port,addr,count) if(cris_iops) cris_iops->write_io(port,(void*)addr,1,count) -#define outsw(port,addr,count) if(cris_iops) cris_iops->write_io(port,(void*)addr,2,count) -#define outsl(port,addr,count) if(cris_iops) cris_iops->write_io(port,(void*)addr,3,count) +static inline void outb(unsigned char data, unsigned int port) +{ + if (cris_iops) + cris_iops->write_io(port, (void *) &data, 1, 1); +} +static inline void outw(unsigned short data, unsigned int port) +{ + if (cris_iops) + cris_iops->write_io(port, (void *) &data, 2, 1); +} +static inline void outl(unsigned int data, unsigned int port) +{ + if (cris_iops) + cris_iops->write_io(port, (void *) &data, 4, 1); +} +static inline void outsb(unsigned int port, const void *addr, + unsigned long count) +{ + if (cris_iops) + cris_iops->write_io(port, (void *)addr, 1, count); +} +static inline void outsw(unsigned int port, const void *addr, + unsigned long count) +{ + if (cris_iops) + cris_iops->write_io(port, (void *)addr, 2, count); +} +static inline void outsl(unsigned int port, const void *addr, + unsigned long count) +{ + if (cris_iops) + cris_iops->write_io(port, (void *)addr, 4, count); +} /* * Convert a physical pointer to a virtual kernel pointer for /dev/mem diff --git a/arch/cris/kernel/process.c b/arch/cris/kernel/process.c index 891dad85e8b..c722027d69a 100644 --- a/arch/cris/kernel/process.c +++ b/arch/cris/kernel/process.c @@ -25,6 +25,7 @@ #include #include #include +#include //#define DEBUG @@ -102,6 +103,7 @@ void cpu_idle (void) { /* endless idle loop with no priority at all */ while (1) { + rcu_idle_enter(); while (!need_resched()) { void (*idle)(void); /* @@ -114,6 +116,7 @@ void cpu_idle (void) idle = default_idle; idle(); } + rcu_idle_exit(); schedule_preempt_disabled(); } } diff --git a/arch/frv/kernel/process.c b/arch/frv/kernel/process.c index d4de48bd5ef..3941cbc91ff 100644 --- a/arch/frv/kernel/process.c +++ b/arch/frv/kernel/process.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -84,12 +85,14 @@ void cpu_idle(void) { /* endless idle loop with no priority at all */ while (1) { + rcu_idle_enter(); while (!need_resched()) { check_pgt_cache(); if (!frv_dma_inprogress && idle) idle(); } + rcu_idle_exit(); schedule_preempt_disabled(); } diff --git a/arch/h8300/kernel/process.c b/arch/h8300/kernel/process.c index 0e9c315be10..f153ed1a4c0 100644 --- a/arch/h8300/kernel/process.c +++ b/arch/h8300/kernel/process.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -78,8 +79,10 @@ void (*idle)(void) = default_idle; void cpu_idle(void) { while (1) { + rcu_idle_enter(); while (!need_resched()) idle(); + rcu_idle_exit(); schedule_preempt_disabled(); } } diff --git a/arch/ia64/include/asm/atomic.h b/arch/ia64/include/asm/atomic.h index 7d9116600a3..6e6fe1839f5 100644 --- a/arch/ia64/include/asm/atomic.h +++ b/arch/ia64/include/asm/atomic.h @@ -17,8 +17,8 @@ #include -#define ATOMIC_INIT(i) ((atomic_t) { (i) }) -#define ATOMIC64_INIT(i) ((atomic64_t) { (i) }) +#define ATOMIC_INIT(i) { (i) } +#define ATOMIC64_INIT(i) { (i) } #define atomic_read(v) (*(volatile int *)&(v)->counter) #define atomic64_read(v) (*(volatile long *)&(v)->counter) diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c index ce74e143aea..86d74ab9800 100644 --- a/arch/ia64/kernel/process.c +++ b/arch/ia64/kernel/process.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -301,6 +302,7 @@ cpu_idle (void) /* endless idle loop with no priority at all */ while (1) { + rcu_idle_enter(); if (can_do_pal_halt) { current_thread_info()->status &= ~TS_POLLING; /* @@ -331,6 +333,7 @@ cpu_idle (void) normal_xtp(); #endif } + rcu_idle_exit(); schedule_preempt_disabled(); check_pgt_cache(); if (cpu_is_offline(cpu)) diff --git a/arch/m32r/kernel/process.c b/arch/m32r/kernel/process.c index 3a4a32b2720..384e63f3a4c 100644 --- a/arch/m32r/kernel/process.c +++ b/arch/m32r/kernel/process.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -82,6 +83,7 @@ void cpu_idle (void) { /* endless idle loop with no priority at all */ while (1) { + rcu_idle_enter(); while (!need_resched()) { void (*idle)(void) = pm_idle; @@ -90,6 +92,7 @@ void cpu_idle (void) idle(); } + rcu_idle_exit(); schedule_preempt_disabled(); } } diff --git a/arch/m68k/include/asm/entry.h b/arch/m68k/include/asm/entry.h index 622138dc728..34c25209b66 100644 --- a/arch/m68k/include/asm/entry.h +++ b/arch/m68k/include/asm/entry.h @@ -33,8 +33,8 @@ /* the following macro is used when enabling interrupts */ #if defined(MACH_ATARI_ONLY) - /* block out HSYNC on the atari */ -#define ALLOWINT (~0x400) + /* block out HSYNC = ipl 2 on the atari */ +#define ALLOWINT (~0x500) #define MAX_NOINT_IPL 3 #else /* portable version */ diff --git a/arch/m68k/include/asm/signal.h b/arch/m68k/include/asm/signal.h index 60e88660169..93fe83e7ffb 100644 --- a/arch/m68k/include/asm/signal.h +++ b/arch/m68k/include/asm/signal.h @@ -156,7 +156,7 @@ typedef struct sigaltstack { static inline void sigaddset(sigset_t *set, int _sig) { asm ("bfset %0{%1,#1}" - : "+od" (*set) + : "+o" (*set) : "id" ((_sig - 1) ^ 31) : "cc"); } @@ -164,7 +164,7 @@ static inline void sigaddset(sigset_t *set, int _sig) static inline void sigdelset(sigset_t *set, int _sig) { asm ("bfclr %0{%1,#1}" - : "+od" (*set) + : "+o" (*set) : "id" ((_sig - 1) ^ 31) : "cc"); } @@ -180,7 +180,7 @@ static inline int __gen_sigismember(sigset_t *set, int _sig) int ret; asm ("bfextu %1{%2,#1},%0" : "=d" (ret) - : "od" (*set), "id" ((_sig-1) ^ 31) + : "o" (*set), "id" ((_sig-1) ^ 31) : "cc"); return ret; } diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c index c488e3cfab5..ac2892e49c7 100644 --- a/arch/m68k/kernel/process.c +++ b/arch/m68k/kernel/process.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -75,8 +76,10 @@ void cpu_idle(void) { /* endless idle loop with no priority at all */ while (1) { + rcu_idle_enter(); while (!need_resched()) idle(); + rcu_idle_exit(); schedule_preempt_disabled(); } } diff --git a/arch/m68k/kernel/sys_m68k.c b/arch/m68k/kernel/sys_m68k.c index 8623f8dc16f..9a5932ec368 100644 --- a/arch/m68k/kernel/sys_m68k.c +++ b/arch/m68k/kernel/sys_m68k.c @@ -479,9 +479,13 @@ sys_atomic_cmpxchg_32(unsigned long newval, int oldval, int d3, int d4, int d5, goto bad_access; } - mem_value = *mem; + /* + * No need to check for EFAULT; we know that the page is + * present and writable. + */ + __get_user(mem_value, mem); if (mem_value == oldval) - *mem = newval; + __put_user(newval, mem); pte_unmap_unlock(pte, ptl); up_read(&mm->mmap_sem); diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 4fedf5a51d9..5c1e75d1c41 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -225,7 +225,7 @@ KBUILD_CPPFLAGS += -D"DATAOFFSET=$(if $(dataoffset-y),$(dataoffset-y),0)" LDFLAGS += -m $(ld-emul) ifdef CONFIG_MIPS -CHECKFLAGS += $(shell $(CC) $(KBUILD_CFLAGS) -dM -E -xc /dev/null | \ +CHECKFLAGS += $(shell $(CC) $(KBUILD_CFLAGS) -dM -E -x c /dev/null | \ egrep -vw '__GNUC_(|MINOR_|PATCHLEVEL_)_' | \ sed -e "s/^\#define /-D'/" -e "s/ /'='/" -e "s/$$/'/") ifdef CONFIG_64BIT diff --git a/arch/mips/include/asm/thread_info.h b/arch/mips/include/asm/thread_info.h index 0d85d8e440c..abb13e83dfd 100644 --- a/arch/mips/include/asm/thread_info.h +++ b/arch/mips/include/asm/thread_info.h @@ -60,6 +60,8 @@ struct thread_info { register struct thread_info *__current_thread_info __asm__("$28"); #define current_thread_info() __current_thread_info +#endif /* !__ASSEMBLY__ */ + /* thread information allocation */ #if defined(CONFIG_PAGE_SIZE_4KB) && defined(CONFIG_32BIT) #define THREAD_SIZE_ORDER (1) @@ -97,8 +99,6 @@ register struct thread_info *__current_thread_info __asm__("$28"); #define free_thread_info(info) kfree(info) -#endif /* !__ASSEMBLY__ */ - #define PREEMPT_ACTIVE 0x10000000 /* diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile index 0c6877ea900..d3d6fa97c09 100644 --- a/arch/mips/kernel/Makefile +++ b/arch/mips/kernel/Makefile @@ -104,7 +104,7 @@ obj-$(CONFIG_MIPS_MACHINE) += mips_machine.o obj-$(CONFIG_OF) += prom.o -CFLAGS_cpu-bugs64.o = $(shell if $(CC) $(KBUILD_CFLAGS) -Wa,-mdaddi -c -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-DHAVE_AS_SET_DADDI"; fi) +CFLAGS_cpu-bugs64.o = $(shell if $(CC) $(KBUILD_CFLAGS) -Wa,-mdaddi -c -o /dev/null -x c /dev/null >/dev/null 2>&1; then echo "-DHAVE_AS_SET_DADDI"; fi) obj-$(CONFIG_HAVE_STD_PC_SERIAL_PORT) += 8250-platform.o diff --git a/arch/mips/kernel/kgdb.c b/arch/mips/kernel/kgdb.c index f4546e97c60..23817a6e32b 100644 --- a/arch/mips/kernel/kgdb.c +++ b/arch/mips/kernel/kgdb.c @@ -283,6 +283,15 @@ static int kgdb_mips_notify(struct notifier_block *self, unsigned long cmd, struct pt_regs *regs = args->regs; int trap = (regs->cp0_cause & 0x7c) >> 2; +#ifdef CONFIG_KPROBES + /* + * Return immediately if the kprobes fault notifier has set + * DIE_PAGE_FAULT. + */ + if (cmd == DIE_PAGE_FAULT) + return NOTIFY_DONE; +#endif /* CONFIG_KPROBES */ + /* Userspace events, ignore. */ if (user_mode(regs)) return NOTIFY_DONE; diff --git a/arch/mips/kernel/kspd.c b/arch/mips/kernel/kspd.c index 84d0639e458..b77f56bbb47 100644 --- a/arch/mips/kernel/kspd.c +++ b/arch/mips/kernel/kspd.c @@ -323,7 +323,7 @@ static void sp_cleanup(void) fdt = files_fdtable(files); for (;;) { unsigned long set; - i = j * __NFDBITS; + i = j * BITS_PER_LONG; if (i >= fdt->max_fds) break; set = fdt->open_fds[j++]; diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index e9a5fd7277f..69b17a92004 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -72,9 +72,7 @@ void __noreturn cpu_idle(void) } } #ifdef CONFIG_HOTPLUG_CPU - if (!cpu_online(cpu) && !cpu_isset(cpu, cpu_callin_map) && - (system_state == SYSTEM_RUNNING || - system_state == SYSTEM_BOOTING)) + if (!cpu_online(cpu) && !cpu_isset(cpu, cpu_callin_map)) play_dead(); #endif rcu_idle_exit(); diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S index 924da5eb703..df243a64f43 100644 --- a/arch/mips/kernel/vmlinux.lds.S +++ b/arch/mips/kernel/vmlinux.lds.S @@ -1,5 +1,6 @@ #include #include +#include #include #undef mips @@ -72,7 +73,7 @@ SECTIONS .data : { /* Data */ . = . + DATAOFFSET; /* for CONFIG_MAPPED_KERNEL */ - INIT_TASK_DATA(PAGE_SIZE) + INIT_TASK_DATA(THREAD_SIZE) NOSAVE_DATA CACHELINE_ALIGNED_DATA(1 << CONFIG_MIPS_L1_CACHE_SHIFT) READ_MOSTLY_DATA(1 << CONFIG_MIPS_L1_CACHE_SHIFT) diff --git a/arch/mips/mm/gup.c b/arch/mips/mm/gup.c index 33aadbcf170..dcfd573871c 100644 --- a/arch/mips/mm/gup.c +++ b/arch/mips/mm/gup.c @@ -152,6 +152,8 @@ static int gup_huge_pud(pud_t pud, unsigned long addr, unsigned long end, do { VM_BUG_ON(compound_head(page) != head); pages[*nr] = page; + if (PageTail(page)) + get_huge_page_tail(page); (*nr)++; page++; refs++; diff --git a/arch/mn10300/Makefile b/arch/mn10300/Makefile index 7120282bf0d..3eb4a52ff9a 100644 --- a/arch/mn10300/Makefile +++ b/arch/mn10300/Makefile @@ -26,7 +26,7 @@ CHECKFLAGS += PROCESSOR := unset UNIT := unset -KBUILD_CFLAGS += -mam33 -mmem-funcs -DCPU=AM33 +KBUILD_CFLAGS += -mam33 -DCPU=AM33 $(call cc-option,-mmem-funcs,) KBUILD_AFLAGS += -mam33 -DCPU=AM33 ifeq ($(CONFIG_MN10300_CURRENT_IN_E2),y) diff --git a/arch/mn10300/kernel/process.c b/arch/mn10300/kernel/process.c index 14707f25153..675d8f2c32e 100644 --- a/arch/mn10300/kernel/process.c +++ b/arch/mn10300/kernel/process.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -107,6 +108,7 @@ void cpu_idle(void) { /* endless idle loop with no priority at all */ for (;;) { + rcu_idle_enter(); while (!need_resched()) { void (*idle)(void); @@ -121,6 +123,7 @@ void cpu_idle(void) } idle(); } + rcu_idle_exit(); schedule_preempt_disabled(); } diff --git a/arch/parisc/include/asm/atomic.h b/arch/parisc/include/asm/atomic.h index 6c6defc2461..af9cf30ed47 100644 --- a/arch/parisc/include/asm/atomic.h +++ b/arch/parisc/include/asm/atomic.h @@ -141,7 +141,7 @@ static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u) #define atomic_sub_and_test(i,v) (atomic_sub_return((i),(v)) == 0) -#define ATOMIC_INIT(i) ((atomic_t) { (i) }) +#define ATOMIC_INIT(i) { (i) } #define smp_mb__before_atomic_dec() smp_mb() #define smp_mb__after_atomic_dec() smp_mb() @@ -150,7 +150,7 @@ static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u) #ifdef CONFIG_64BIT -#define ATOMIC64_INIT(i) ((atomic64_t) { (i) }) +#define ATOMIC64_INIT(i) { (i) } static __inline__ s64 __atomic64_add_return(s64 i, atomic64_t *v) diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c index d4b94b395c1..c54a4dbcb38 100644 --- a/arch/parisc/kernel/process.c +++ b/arch/parisc/kernel/process.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include @@ -69,8 +70,10 @@ void cpu_idle(void) /* endless idle loop with no priority at all */ while (1) { + rcu_idle_enter(); while (!need_resched()) barrier(); + rcu_idle_exit(); schedule_preempt_disabled(); check_pgt_cache(); } diff --git a/arch/parisc/kernel/signal32.c b/arch/parisc/kernel/signal32.c index e1413243076..d0ea054bd3d 100644 --- a/arch/parisc/kernel/signal32.c +++ b/arch/parisc/kernel/signal32.c @@ -67,7 +67,8 @@ put_sigset32(compat_sigset_t __user *up, sigset_t *set, size_t sz) { compat_sigset_t s; - if (sz != sizeof *set) panic("put_sigset32()"); + if (sz != sizeof *set) + return -EINVAL; sigset_64to32(&s, set); return copy_to_user(up, &s, sizeof s); @@ -79,7 +80,8 @@ get_sigset32(compat_sigset_t __user *up, sigset_t *set, size_t sz) compat_sigset_t s; int r; - if (sz != sizeof *set) panic("put_sigset32()"); + if (sz != sizeof *set) + return -EINVAL; if ((r = copy_from_user(&s, up, sz)) == 0) { sigset_32to64(set, &s); diff --git a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c index c9b932260f4..7ea75d14aa6 100644 --- a/arch/parisc/kernel/sys_parisc.c +++ b/arch/parisc/kernel/sys_parisc.c @@ -73,6 +73,8 @@ static unsigned long get_shared_area(struct address_space *mapping, struct vm_area_struct *vma; int offset = mapping ? get_offset(mapping) : 0; + offset = (offset + (pgoff << PAGE_SHIFT)) & 0x3FF000; + addr = DCACHE_ALIGN(addr - offset) + offset; for (vma = find_vma(current->mm, addr); ; vma = vma->vm_next) { diff --git a/arch/powerpc/boot/dts/p1022ds.dtsi b/arch/powerpc/boot/dts/p1022ds.dtsi index 7cdb505036b..1b0673e3631 100644 --- a/arch/powerpc/boot/dts/p1022ds.dtsi +++ b/arch/powerpc/boot/dts/p1022ds.dtsi @@ -33,22 +33,6 @@ */ &board_lbc { - /* - * This node is used to access the pixis via "indirect" mode, - * which is done by writing the pixis register index to chip - * select 0 and the value to/from chip select 1. Indirect - * mode is the only way to access the pixis when DIU video - * is enabled. Note that this assumes that the first column - * of the 'ranges' property above is the chip select number. - */ - board-control@0,0 { - compatible = "fsl,p1022ds-indirect-pixis"; - reg = <0x0 0x0 1 /* CS0 */ - 0x1 0x0 1>; /* CS1 */ - interrupt-parent = <&mpic>; - interrupts = <8 0 0 0>; - }; - nor@0,0 { #address-cells = <1>; #size-cells = <1>; diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h index ac39e6a3b25..2974edd999d 100644 --- a/arch/powerpc/include/asm/pci-bridge.h +++ b/arch/powerpc/include/asm/pci-bridge.h @@ -181,6 +181,14 @@ static inline int pci_device_from_OF_node(struct device_node *np, #if defined(CONFIG_EEH) static inline struct eeh_dev *of_node_to_eeh_dev(struct device_node *dn) { + /* + * For those OF nodes whose parent isn't PCI bridge, they + * don't have PCI_DN actually. So we have to skip them for + * any EEH operations. + */ + if (!dn || !PCI_DN(dn)) + return NULL; + return PCI_DN(dn)->edev; } #endif diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h index 9d7f0fb6902..cae0ed7878e 100644 --- a/arch/powerpc/include/asm/reg.h +++ b/arch/powerpc/include/asm/reg.h @@ -1022,7 +1022,8 @@ /* Macros for setting and retrieving special purpose registers */ #ifndef __ASSEMBLY__ #define mfmsr() ({unsigned long rval; \ - asm volatile("mfmsr %0" : "=r" (rval)); rval;}) + asm volatile("mfmsr %0" : "=r" (rval) : \ + : "memory"); rval;}) #ifdef CONFIG_PPC_BOOK3S_64 #define __mtmsrd(v, l) asm volatile("mtmsrd %0," __stringify(l) \ : : "r" (v) : "memory") diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 34b8afe94a5..ec0b529c395 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c @@ -76,6 +76,7 @@ int main(void) DEFINE(SIGSEGV, SIGSEGV); DEFINE(NMI_MASK, NMI_MASK); DEFINE(THREAD_DSCR, offsetof(struct thread_struct, dscr)); + DEFINE(THREAD_DSCR_INHERIT, offsetof(struct thread_struct, dscr_inherit)); #else DEFINE(THREAD_INFO, offsetof(struct task_struct, stack)); #endif /* CONFIG_PPC64 */ diff --git a/arch/powerpc/kernel/dbell.c b/arch/powerpc/kernel/dbell.c index 5b25c8060fd..a892680668d 100644 --- a/arch/powerpc/kernel/dbell.c +++ b/arch/powerpc/kernel/dbell.c @@ -28,6 +28,8 @@ void doorbell_setup_this_cpu(void) void doorbell_cause_ipi(int cpu, unsigned long data) { + /* Order previous accesses vs. msgsnd, which is treated as a store */ + mb(); ppc_msgsnd(PPC_DBELL, 0, data); } diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index ef2074c3e90..e500969bea0 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S @@ -373,6 +373,12 @@ _GLOBAL(ret_from_fork) li r3,0 b syscall_exit + .section ".toc","aw" +DSCR_DEFAULT: + .tc dscr_default[TC],dscr_default + + .section ".text" + /* * This routine switches between two different tasks. The process * state of one is saved on its kernel stack. Then the state @@ -512,9 +518,6 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT) mr r1,r8 /* start using new stack pointer */ std r7,PACAKSAVE(r13) - ld r6,_CCR(r1) - mtcrf 0xFF,r6 - #ifdef CONFIG_ALTIVEC BEGIN_FTR_SECTION ld r0,THREAD_VRSAVE(r4) @@ -523,14 +526,22 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) #endif /* CONFIG_ALTIVEC */ #ifdef CONFIG_PPC64 BEGIN_FTR_SECTION + lwz r6,THREAD_DSCR_INHERIT(r4) + ld r7,DSCR_DEFAULT@toc(2) ld r0,THREAD_DSCR(r4) - cmpd r0,r25 - beq 1f + cmpwi r6,0 + bne 1f + ld r0,0(r7) +1: cmpd r0,r25 + beq 2f mtspr SPRN_DSCR,r0 -1: +2: END_FTR_SECTION_IFSET(CPU_FTR_DSCR) #endif + ld r6,_CCR(r1) + mtcrf 0xFF,r6 + /* r3-r13 are destroyed -- Cort */ REST_8GPRS(14, r1) REST_10GPRS(22, r1) diff --git a/arch/powerpc/kernel/ftrace.c b/arch/powerpc/kernel/ftrace.c index bf99cfa6bbf..63240081133 100644 --- a/arch/powerpc/kernel/ftrace.c +++ b/arch/powerpc/kernel/ftrace.c @@ -245,9 +245,9 @@ __ftrace_make_nop(struct module *mod, /* * On PPC32 the trampoline looks like: - * 0x3d, 0x60, 0x00, 0x00 lis r11,sym@ha - * 0x39, 0x6b, 0x00, 0x00 addi r11,r11,sym@l - * 0x7d, 0x69, 0x03, 0xa6 mtctr r11 + * 0x3d, 0x80, 0x00, 0x00 lis r12,sym@ha + * 0x39, 0x8c, 0x00, 0x00 addi r12,r12,sym@l + * 0x7d, 0x89, 0x03, 0xa6 mtctr r12 * 0x4e, 0x80, 0x04, 0x20 bctr */ @@ -262,9 +262,9 @@ __ftrace_make_nop(struct module *mod, pr_devel(" %08x %08x ", jmp[0], jmp[1]); /* verify that this is what we expect it to be */ - if (((jmp[0] & 0xffff0000) != 0x3d600000) || - ((jmp[1] & 0xffff0000) != 0x396b0000) || - (jmp[2] != 0x7d6903a6) || + if (((jmp[0] & 0xffff0000) != 0x3d800000) || + ((jmp[1] & 0xffff0000) != 0x398c0000) || + (jmp[2] != 0x7d8903a6) || (jmp[3] != 0x4e800420)) { printk(KERN_ERR "Not a trampoline\n"); return -EINVAL; diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 58bddee8e1e..9e07bd038dd 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -422,7 +422,7 @@ _STATIC(__after_prom_start) tovirt(r6,r6) /* on booke, we already run at PAGE_OFFSET */ #endif -#ifdef CONFIG_CRASH_DUMP +#ifdef CONFIG_RELOCATABLE /* * Check if the kernel has to be running as relocatable kernel based on the * variable __run_at_load, if it is set the kernel is treated as relocatable diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 4937c969009..94178e55f49 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -799,16 +799,8 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, #endif /* CONFIG_PPC_STD_MMU_64 */ #ifdef CONFIG_PPC64 if (cpu_has_feature(CPU_FTR_DSCR)) { - if (current->thread.dscr_inherit) { - p->thread.dscr_inherit = 1; - p->thread.dscr = current->thread.dscr; - } else if (0 != dscr_default) { - p->thread.dscr_inherit = 1; - p->thread.dscr = dscr_default; - } else { - p->thread.dscr_inherit = 0; - p->thread.dscr = 0; - } + p->thread.dscr_inherit = current->thread.dscr_inherit; + p->thread.dscr = current->thread.dscr; } #endif diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index 0337086a2b8..6da97e55f25 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -215,8 +215,15 @@ void smp_muxed_ipi_message_pass(int cpu, int msg) struct cpu_messages *info = &per_cpu(ipi_message, cpu); char *message = (char *)&info->messages; + /* + * Order previous accesses before accesses in the IPI handler. + */ + smp_mb(); message[msg] = 1; - mb(); + /* + * cause_ipi functions are required to include a full barrier + * before doing whatever causes the IPI. + */ smp_ops->cause_ipi(cpu, info->data); } @@ -228,7 +235,7 @@ irqreturn_t smp_ipi_demux(void) mb(); /* order any irq clear */ do { - all = xchg_local(&info->messages, 0); + all = xchg(&info->messages, 0); #ifdef __BIG_ENDIAN if (all & (1 << (24 - 8 * PPC_MSG_CALL_FUNCTION))) diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c index a6289ae14e8..886b8183000 100644 --- a/arch/powerpc/kernel/sysfs.c +++ b/arch/powerpc/kernel/sysfs.c @@ -194,6 +194,14 @@ static ssize_t show_dscr_default(struct device *dev, return sprintf(buf, "%lx\n", dscr_default); } +static void update_dscr(void *dummy) +{ + if (!current->thread.dscr_inherit) { + current->thread.dscr = dscr_default; + mtspr(SPRN_DSCR, dscr_default); + } +} + static ssize_t __used store_dscr_default(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -206,6 +214,8 @@ static ssize_t __used store_dscr_default(struct device *dev, return -EINVAL; dscr_default = val; + on_each_cpu(update_dscr, NULL, 1); + return count; } diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index a6ceb9f4b6d..b2413bc9205 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -741,13 +741,8 @@ void update_vsyscall(struct timespec *wall_time, struct timespec *wtm, void update_vsyscall_tz(void) { - /* Make userspace gettimeofday spin until we're done. */ - ++vdso_data->tb_update_count; - smp_mb(); vdso_data->tz_minuteswest = sys_tz.tz_minuteswest; vdso_data->tz_dsttime = sys_tz.tz_dsttime; - smp_mb(); - ++vdso_data->tb_update_count; } static void __init clocksource_init(void) diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 158972341a2..ae0843fa7a6 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -972,8 +972,9 @@ static int emulate_instruction(struct pt_regs *regs) cpu_has_feature(CPU_FTR_DSCR)) { PPC_WARN_EMULATED(mtdscr, regs); rd = (instword >> 21) & 0x1f; - mtspr(SPRN_DSCR, regs->gpr[rd]); + current->thread.dscr = regs->gpr[rd]; current->thread.dscr_inherit = 1; + mtspr(SPRN_DSCR, current->thread.dscr); return 0; } #endif diff --git a/arch/powerpc/kvm/44x_emulate.c b/arch/powerpc/kvm/44x_emulate.c index 549bb2c9a47..ded8a1a0426 100644 --- a/arch/powerpc/kvm/44x_emulate.c +++ b/arch/powerpc/kvm/44x_emulate.c @@ -79,6 +79,7 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu, run->dcr.dcrn = dcrn; run->dcr.data = 0; run->dcr.is_write = 0; + vcpu->arch.dcr_is_write = 0; vcpu->arch.io_gpr = rt; vcpu->arch.dcr_needed = 1; kvmppc_account_exit(vcpu, DCR_EXITS); @@ -100,6 +101,7 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu, run->dcr.dcrn = dcrn; run->dcr.data = kvmppc_get_gpr(vcpu, rs); run->dcr.is_write = 1; + vcpu->arch.dcr_is_write = 1; vcpu->arch.dcr_needed = 1; kvmppc_account_exit(vcpu, DCR_EXITS); emulated = EMULATE_DO_DCR; diff --git a/arch/powerpc/platforms/40x/ppc40x_simple.c b/arch/powerpc/platforms/40x/ppc40x_simple.c index 97612068fae..f0eee75ac05 100644 --- a/arch/powerpc/platforms/40x/ppc40x_simple.c +++ b/arch/powerpc/platforms/40x/ppc40x_simple.c @@ -57,7 +57,8 @@ static const char *board[] __initdata = { "amcc,makalu", "apm,klondike", "est,hotfoot", - "plathome,obs600" + "plathome,obs600", + NULL }; static int __init ppc40x_probe(void) diff --git a/arch/powerpc/platforms/85xx/p1022_ds.c b/arch/powerpc/platforms/85xx/p1022_ds.c index f700c81a132..f80887f40f0 100644 --- a/arch/powerpc/platforms/85xx/p1022_ds.c +++ b/arch/powerpc/platforms/85xx/p1022_ds.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "smp.h" #include "mpc85xx.h" @@ -142,17 +143,74 @@ static void p1022ds_set_gamma_table(enum fsl_diu_monitor_port port, { } +struct fsl_law { + u32 lawbar; + u32 reserved1; + u32 lawar; + u32 reserved[5]; +}; + +#define LAWBAR_MASK 0x00F00000 +#define LAWBAR_SHIFT 12 + +#define LAWAR_EN 0x80000000 +#define LAWAR_TGT_MASK 0x01F00000 +#define LAW_TRGT_IF_LBC (0x04 << 20) + +#define LAWAR_MASK (LAWAR_EN | LAWAR_TGT_MASK) +#define LAWAR_MATCH (LAWAR_EN | LAW_TRGT_IF_LBC) + +#define BR_BA 0xFFFF8000 + +/* + * Map a BRx value to a physical address + * + * The localbus BRx registers only store the lower 32 bits of the address. To + * obtain the upper four bits, we need to scan the LAW table. The entry which + * maps to the localbus will contain the upper four bits. + */ +static phys_addr_t lbc_br_to_phys(const void *ecm, unsigned int count, u32 br) +{ +#ifndef CONFIG_PHYS_64BIT + /* + * If we only have 32-bit addressing, then the BRx address *is* the + * physical address. + */ + return br & BR_BA; +#else + const struct fsl_law *law = ecm + 0xc08; + unsigned int i; + + for (i = 0; i < count; i++) { + u64 lawbar = in_be32(&law[i].lawbar); + u32 lawar = in_be32(&law[i].lawar); + + if ((lawar & LAWAR_MASK) == LAWAR_MATCH) + /* Extract the upper four bits */ + return (br & BR_BA) | ((lawbar & LAWBAR_MASK) << 12); + } + + return 0; +#endif +} + /** * p1022ds_set_monitor_port: switch the output to a different monitor port - * */ static void p1022ds_set_monitor_port(enum fsl_diu_monitor_port port) { struct device_node *guts_node; - struct device_node *indirect_node = NULL; + struct device_node *lbc_node = NULL; + struct device_node *law_node = NULL; struct ccsr_guts __iomem *guts; + struct fsl_lbc_regs *lbc = NULL; + void *ecm = NULL; u8 __iomem *lbc_lcs0_ba = NULL; u8 __iomem *lbc_lcs1_ba = NULL; + phys_addr_t cs0_addr, cs1_addr; + u32 br0, or0, br1, or1; + const __be32 *iprop; + unsigned int num_laws; u8 b; /* Map the global utilities registers. */ @@ -168,22 +226,99 @@ static void p1022ds_set_monitor_port(enum fsl_diu_monitor_port port) goto exit; } - indirect_node = of_find_compatible_node(NULL, NULL, - "fsl,p1022ds-indirect-pixis"); - if (!indirect_node) { - pr_err("p1022ds: missing pixis indirect mode node\n"); + lbc_node = of_find_compatible_node(NULL, NULL, "fsl,p1022-elbc"); + if (!lbc_node) { + pr_err("p1022ds: missing localbus node\n"); goto exit; } - lbc_lcs0_ba = of_iomap(indirect_node, 0); - if (!lbc_lcs0_ba) { - pr_err("p1022ds: could not map localbus chip select 0\n"); + lbc = of_iomap(lbc_node, 0); + if (!lbc) { + pr_err("p1022ds: could not map localbus node\n"); + goto exit; + } + + law_node = of_find_compatible_node(NULL, NULL, "fsl,ecm-law"); + if (!law_node) { + pr_err("p1022ds: missing local access window node\n"); + goto exit; + } + + ecm = of_iomap(law_node, 0); + if (!ecm) { + pr_err("p1022ds: could not map local access window node\n"); + goto exit; + } + + iprop = of_get_property(law_node, "fsl,num-laws", 0); + if (!iprop) { + pr_err("p1022ds: LAW node is missing fsl,num-laws property\n"); goto exit; } + num_laws = be32_to_cpup(iprop); - lbc_lcs1_ba = of_iomap(indirect_node, 1); + /* + * Indirect mode requires both BR0 and BR1 to be set to "GPCM", + * otherwise writes to these addresses won't actually appear on the + * local bus, and so the PIXIS won't see them. + * + * In FCM mode, writes go to the NAND controller, which does not pass + * them to the localbus directly. So we force BR0 and BR1 into GPCM + * mode, since we don't care about what's behind the localbus any + * more. + */ + br0 = in_be32(&lbc->bank[0].br); + br1 = in_be32(&lbc->bank[1].br); + or0 = in_be32(&lbc->bank[0].or); + or1 = in_be32(&lbc->bank[1].or); + + /* Make sure CS0 and CS1 are programmed */ + if (!(br0 & BR_V) || !(br1 & BR_V)) { + pr_err("p1022ds: CS0 and/or CS1 is not programmed\n"); + goto exit; + } + + /* + * Use the existing BRx/ORx values if it's already GPCM. Otherwise, + * force the values to simple 32KB GPCM windows with the most + * conservative timing. + */ + if ((br0 & BR_MSEL) != BR_MS_GPCM) { + br0 = (br0 & BR_BA) | BR_V; + or0 = 0xFFFF8000 | 0xFF7; + out_be32(&lbc->bank[0].br, br0); + out_be32(&lbc->bank[0].or, or0); + } + if ((br1 & BR_MSEL) != BR_MS_GPCM) { + br1 = (br1 & BR_BA) | BR_V; + or1 = 0xFFFF8000 | 0xFF7; + out_be32(&lbc->bank[1].br, br1); + out_be32(&lbc->bank[1].or, or1); + } + + cs0_addr = lbc_br_to_phys(ecm, num_laws, br0); + if (!cs0_addr) { + pr_err("p1022ds: could not determine physical address for CS0" + " (BR0=%08x)\n", br0); + goto exit; + } + cs1_addr = lbc_br_to_phys(ecm, num_laws, br1); + if (!cs0_addr) { + pr_err("p1022ds: could not determine physical address for CS1" + " (BR1=%08x)\n", br1); + goto exit; + } + + lbc_lcs0_ba = ioremap(cs0_addr, 1); + if (!lbc_lcs0_ba) { + pr_err("p1022ds: could not ioremap CS0 address %llx\n", + (unsigned long long)cs0_addr); + goto exit; + } + lbc_lcs1_ba = ioremap(cs1_addr, 1); if (!lbc_lcs1_ba) { - pr_err("p1022ds: could not map localbus chip select 1\n"); + pr_err("p1022ds: could not ioremap CS1 address %llx\n", + (unsigned long long)cs1_addr); goto exit; } @@ -254,10 +389,15 @@ static void p1022ds_set_monitor_port(enum fsl_diu_monitor_port port) iounmap(lbc_lcs1_ba); if (lbc_lcs0_ba) iounmap(lbc_lcs0_ba); + if (lbc) + iounmap(lbc); + if (ecm) + iounmap(ecm); if (guts) iounmap(guts); - of_node_put(indirect_node); + of_node_put(law_node); + of_node_put(lbc_node); of_node_put(guts_node); } @@ -355,6 +495,8 @@ static void __init disable_one_node(struct device_node *np, struct property *new prom_update_property(np, new, old); else prom_add_property(np, new); + + pr_info("p1022ds: disabling %s node\n", np->full_name); } /* TRUE if there is a "video=fslfb" command-line parameter. */ @@ -419,28 +561,46 @@ static void __init p1022_ds_setup_arch(void) diu_ops.valid_monitor_port = p1022ds_valid_monitor_port; /* - * Disable the NOR flash node if there is video=fslfb... command-line - * parameter. When the DIU is active, NOR flash is unavailable, so we - * have to disable the node before the MTD driver loads. + * Disable the NOR and NAND flash nodes if there is video=fslfb... + * command-line parameter. When the DIU is active, the localbus is + * unavailable, so we have to disable these nodes before the MTD + * driver loads. */ if (fslfb) { struct device_node *np = of_find_compatible_node(NULL, NULL, "fsl,p1022-elbc"); if (np) { - np = of_find_compatible_node(np, NULL, "cfi-flash"); - if (np) { + struct device_node *np2; + + of_node_get(np); + np2 = of_find_compatible_node(np, NULL, "cfi-flash"); + if (np2) { static struct property nor_status = { .name = "status", .value = "disabled", .length = sizeof("disabled"), }; - pr_info("p1022ds: disabling %s node", - np->full_name); - disable_one_node(np, &nor_status); - of_node_put(np); + disable_one_node(np2, &nor_status); + of_node_put(np2); + } + + of_node_get(np); + np2 = of_find_compatible_node(np, NULL, + "fsl,elbc-fcm-nand"); + if (np2) { + static struct property nand_status = { + .name = "status", + .value = "disabled", + .length = sizeof("disabled"), + }; + + disable_one_node(np2, &nand_status); + of_node_put(np2); } + + of_node_put(np); } } diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c index a75e37dc41a..41d4b163c06 100644 --- a/arch/powerpc/platforms/pseries/eeh.c +++ b/arch/powerpc/platforms/pseries/eeh.c @@ -1029,7 +1029,7 @@ static void eeh_add_device_early(struct device_node *dn) { struct pci_controller *phb; - if (!dn || !of_node_to_eeh_dev(dn)) + if (!of_node_to_eeh_dev(dn)) return; phb = of_node_to_eeh_dev(dn)->phb; diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c index baf92cd9dfa..041e28d0e70 100644 --- a/arch/powerpc/platforms/pseries/eeh_driver.c +++ b/arch/powerpc/platforms/pseries/eeh_driver.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -47,6 +48,41 @@ static inline const char *eeh_pcid_name(struct pci_dev *pdev) return ""; } +/** + * eeh_pcid_get - Get the PCI device driver + * @pdev: PCI device + * + * The function is used to retrieve the PCI device driver for + * the indicated PCI device. Besides, we will increase the reference + * of the PCI device driver to prevent that being unloaded on + * the fly. Otherwise, kernel crash would be seen. + */ +static inline struct pci_driver *eeh_pcid_get(struct pci_dev *pdev) +{ + if (!pdev || !pdev->driver) + return NULL; + + if (!try_module_get(pdev->driver->driver.owner)) + return NULL; + + return pdev->driver; +} + +/** + * eeh_pcid_put - Dereference on the PCI device driver + * @pdev: PCI device + * + * The function is called to do dereference on the PCI device + * driver of the indicated PCI device. + */ +static inline void eeh_pcid_put(struct pci_dev *pdev) +{ + if (!pdev || !pdev->driver) + return; + + module_put(pdev->driver->driver.owner); +} + #if 0 static void print_device_node_tree(struct pci_dn *pdn, int dent) { @@ -126,18 +162,20 @@ static void eeh_enable_irq(struct pci_dev *dev) static int eeh_report_error(struct pci_dev *dev, void *userdata) { enum pci_ers_result rc, *res = userdata; - struct pci_driver *driver = dev->driver; + struct pci_driver *driver; dev->error_state = pci_channel_io_frozen; - if (!driver) - return 0; + driver = eeh_pcid_get(dev); + if (!driver) return 0; eeh_disable_irq(dev); if (!driver->err_handler || - !driver->err_handler->error_detected) + !driver->err_handler->error_detected) { + eeh_pcid_put(dev); return 0; + } rc = driver->err_handler->error_detected(dev, pci_channel_io_frozen); @@ -145,6 +183,7 @@ static int eeh_report_error(struct pci_dev *dev, void *userdata) if (rc == PCI_ERS_RESULT_NEED_RESET) *res = rc; if (*res == PCI_ERS_RESULT_NONE) *res = rc; + eeh_pcid_put(dev); return 0; } @@ -160,12 +199,16 @@ static int eeh_report_error(struct pci_dev *dev, void *userdata) static int eeh_report_mmio_enabled(struct pci_dev *dev, void *userdata) { enum pci_ers_result rc, *res = userdata; - struct pci_driver *driver = dev->driver; + struct pci_driver *driver; + + driver = eeh_pcid_get(dev); + if (!driver) return 0; - if (!driver || - !driver->err_handler || - !driver->err_handler->mmio_enabled) + if (!driver->err_handler || + !driver->err_handler->mmio_enabled) { + eeh_pcid_put(dev); return 0; + } rc = driver->err_handler->mmio_enabled(dev); @@ -173,6 +216,7 @@ static int eeh_report_mmio_enabled(struct pci_dev *dev, void *userdata) if (rc == PCI_ERS_RESULT_NEED_RESET) *res = rc; if (*res == PCI_ERS_RESULT_NONE) *res = rc; + eeh_pcid_put(dev); return 0; } @@ -189,18 +233,20 @@ static int eeh_report_mmio_enabled(struct pci_dev *dev, void *userdata) static int eeh_report_reset(struct pci_dev *dev, void *userdata) { enum pci_ers_result rc, *res = userdata; - struct pci_driver *driver = dev->driver; - - if (!driver) - return 0; + struct pci_driver *driver; dev->error_state = pci_channel_io_normal; + driver = eeh_pcid_get(dev); + if (!driver) return 0; + eeh_enable_irq(dev); if (!driver->err_handler || - !driver->err_handler->slot_reset) + !driver->err_handler->slot_reset) { + eeh_pcid_put(dev); return 0; + } rc = driver->err_handler->slot_reset(dev); if ((*res == PCI_ERS_RESULT_NONE) || @@ -208,6 +254,7 @@ static int eeh_report_reset(struct pci_dev *dev, void *userdata) if (*res == PCI_ERS_RESULT_DISCONNECT && rc == PCI_ERS_RESULT_NEED_RESET) *res = rc; + eeh_pcid_put(dev); return 0; } @@ -222,21 +269,24 @@ static int eeh_report_reset(struct pci_dev *dev, void *userdata) */ static int eeh_report_resume(struct pci_dev *dev, void *userdata) { - struct pci_driver *driver = dev->driver; + struct pci_driver *driver; dev->error_state = pci_channel_io_normal; - if (!driver) - return 0; + driver = eeh_pcid_get(dev); + if (!driver) return 0; eeh_enable_irq(dev); if (!driver->err_handler || - !driver->err_handler->resume) + !driver->err_handler->resume) { + eeh_pcid_put(dev); return 0; + } driver->err_handler->resume(dev); + eeh_pcid_put(dev); return 0; } @@ -250,21 +300,24 @@ static int eeh_report_resume(struct pci_dev *dev, void *userdata) */ static int eeh_report_failure(struct pci_dev *dev, void *userdata) { - struct pci_driver *driver = dev->driver; + struct pci_driver *driver; dev->error_state = pci_channel_io_perm_failure; - if (!driver) - return 0; + driver = eeh_pcid_get(dev); + if (!driver) return 0; eeh_disable_irq(dev); if (!driver->err_handler || - !driver->err_handler->error_detected) + !driver->err_handler->error_detected) { + eeh_pcid_put(dev); return 0; + } driver->err_handler->error_detected(dev, pci_channel_io_perm_failure); + eeh_pcid_put(dev); return 0; } diff --git a/arch/powerpc/platforms/pseries/eeh_event.c b/arch/powerpc/platforms/pseries/eeh_event.c index 4cb375c0f8d..fb506317ebb 100644 --- a/arch/powerpc/platforms/pseries/eeh_event.c +++ b/arch/powerpc/platforms/pseries/eeh_event.c @@ -85,8 +85,10 @@ static int eeh_event_handler(void * dummy) set_current_state(TASK_INTERRUPTIBLE); /* Don't add to load average */ edev = handle_eeh_events(event); - eeh_clear_slot(eeh_dev_to_of_node(edev), EEH_MODE_RECOVERING); - pci_dev_put(edev->pdev); + if (edev) { + eeh_clear_slot(eeh_dev_to_of_node(edev), EEH_MODE_RECOVERING); + pci_dev_put(edev->pdev); + } kfree(event); mutex_unlock(&eeh_event_mutex); diff --git a/arch/powerpc/sysdev/xics/icp-hv.c b/arch/powerpc/sysdev/xics/icp-hv.c index 253dce98c16..762c5ca3760 100644 --- a/arch/powerpc/sysdev/xics/icp-hv.c +++ b/arch/powerpc/sysdev/xics/icp-hv.c @@ -65,7 +65,11 @@ static inline void icp_hv_set_xirr(unsigned int value) static inline void icp_hv_set_qirr(int n_cpu , u8 value) { int hw_cpu = get_hard_smp_processor_id(n_cpu); - long rc = plpar_hcall_norets(H_IPI, hw_cpu, value); + long rc; + + /* Make sure all previous accesses are ordered before IPI sending */ + mb(); + rc = plpar_hcall_norets(H_IPI, hw_cpu, value); if (rc != H_SUCCESS) { pr_err("%s: bad return code qirr cpu=%d hw_cpu=%d mfrr=0x%x " "returned %ld\n", __func__, n_cpu, hw_cpu, value, rc); diff --git a/arch/s390/boot/compressed/vmlinux.lds.S b/arch/s390/boot/compressed/vmlinux.lds.S index d80f79d8dd9..8e1fb823928 100644 --- a/arch/s390/boot/compressed/vmlinux.lds.S +++ b/arch/s390/boot/compressed/vmlinux.lds.S @@ -5,7 +5,7 @@ OUTPUT_FORMAT("elf64-s390", "elf64-s390", "elf64-s390") OUTPUT_ARCH(s390:64-bit) #else OUTPUT_FORMAT("elf32-s390", "elf32-s390", "elf32-s390") -OUTPUT_ARCH(s390) +OUTPUT_ARCH(s390:31-bit) #endif ENTRY(startup) diff --git a/arch/s390/include/asm/compat.h b/arch/s390/include/asm/compat.h index 234f1d859ce..2e0a15b4359 100644 --- a/arch/s390/include/asm/compat.h +++ b/arch/s390/include/asm/compat.h @@ -20,7 +20,7 @@ #define PSW32_MASK_CC 0x00003000UL #define PSW32_MASK_PM 0x00000f00UL -#define PSW32_MASK_USER 0x00003F00UL +#define PSW32_MASK_USER 0x0000FF00UL #define PSW32_ADDR_AMODE 0x80000000UL #define PSW32_ADDR_INSN 0x7FFFFFFFUL diff --git a/arch/s390/include/asm/mmu_context.h b/arch/s390/include/asm/mmu_context.h index 5d09e405c54..5d211f70d83 100644 --- a/arch/s390/include/asm/mmu_context.h +++ b/arch/s390/include/asm/mmu_context.h @@ -13,7 +13,6 @@ #include #include #include -#include static inline int init_new_context(struct task_struct *tsk, struct mm_struct *mm) @@ -93,4 +92,17 @@ static inline void activate_mm(struct mm_struct *prev, switch_mm(prev, next, current); } +static inline void arch_dup_mmap(struct mm_struct *oldmm, + struct mm_struct *mm) +{ +#ifdef CONFIG_64BIT + if (oldmm->context.asce_limit < mm->context.asce_limit) + crst_table_downgrade(mm, oldmm->context.asce_limit); +#endif +} + +static inline void arch_exit_mmap(struct mm_struct *mm) +{ +} + #endif /* __S390_MMU_CONTEXT_H */ diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h index d499b30ea48..8b6f62e1c36 100644 --- a/arch/s390/include/asm/processor.h +++ b/arch/s390/include/asm/processor.h @@ -129,7 +129,9 @@ struct stack_frame { regs->psw.mask = psw_user_bits | PSW_MASK_BA; \ regs->psw.addr = new_psw | PSW_ADDR_AMODE; \ regs->gprs[15] = new_stackp; \ + __tlb_flush_mm(current->mm); \ crst_table_downgrade(current->mm, 1UL << 31); \ + update_mm(current->mm, current); \ } while (0) /* Forward declaration, a strange C thing */ diff --git a/arch/s390/include/asm/ptrace.h b/arch/s390/include/asm/ptrace.h index aeb77f01798..d3750e79fcc 100644 --- a/arch/s390/include/asm/ptrace.h +++ b/arch/s390/include/asm/ptrace.h @@ -240,7 +240,7 @@ typedef struct #define PSW_MASK_EA 0x00000000UL #define PSW_MASK_BA 0x00000000UL -#define PSW_MASK_USER 0x00003F00UL +#define PSW_MASK_USER 0x0000FF00UL #define PSW_ADDR_AMODE 0x80000000UL #define PSW_ADDR_INSN 0x7FFFFFFFUL @@ -269,7 +269,7 @@ typedef struct #define PSW_MASK_EA 0x0000000100000000UL #define PSW_MASK_BA 0x0000000080000000UL -#define PSW_MASK_USER 0x00003F0180000000UL +#define PSW_MASK_USER 0x0000FF0180000000UL #define PSW_ADDR_AMODE 0x0000000000000000UL #define PSW_ADDR_INSN 0xFFFFFFFFFFFFFFFFUL diff --git a/arch/s390/include/asm/timex.h b/arch/s390/include/asm/timex.h index c447a27a7fd..945b7cdf493 100644 --- a/arch/s390/include/asm/timex.h +++ b/arch/s390/include/asm/timex.h @@ -137,4 +137,32 @@ static inline unsigned long long get_clock_monotonic(void) return get_clock_xt() - sched_clock_base_cc; } +/** + * tod_to_ns - convert a TOD format value to nanoseconds + * @todval: to be converted TOD format value + * Returns: number of nanoseconds that correspond to the TOD format value + * + * Converting a 64 Bit TOD format value to nanoseconds means that the value + * must be divided by 4.096. In order to achieve that we multiply with 125 + * and divide by 512: + * + * ns = (todval * 125) >> 9; + * + * In order to avoid an overflow with the multiplication we can rewrite this. + * With a split todval == 2^32 * th + tl (th upper 32 bits, tl lower 32 bits) + * we end up with + * + * ns = ((2^32 * th + tl) * 125 ) >> 9; + * -> ns = (2^23 * th * 125) + ((tl * 125) >> 9); + * + */ +static inline unsigned long long tod_to_ns(unsigned long long todval) +{ + unsigned long long ns; + + ns = ((todval >> 32) << 23) * 125; + ns += ((todval & 0xffffffff) * 125) >> 9; + return ns; +} + #endif diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c index ab64bdbab2a..36e6c3092e6 100644 --- a/arch/s390/kernel/compat_linux.c +++ b/arch/s390/kernel/compat_linux.c @@ -612,7 +612,6 @@ asmlinkage unsigned long old32_mmap(struct mmap_arg_struct_emu31 __user *arg) return -EFAULT; if (a.offset & ~PAGE_MASK) return -EINVAL; - a.addr = (unsigned long) compat_ptr(a.addr); return sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, a.offset >> PAGE_SHIFT); } @@ -623,7 +622,6 @@ asmlinkage long sys32_mmap2(struct mmap_arg_struct_emu31 __user *arg) if (copy_from_user(&a, arg, sizeof(a))) return -EFAULT; - a.addr = (unsigned long) compat_ptr(a.addr); return sys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, a.offset); } diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c index 28040fd5e8a..0bdca3ac9a6 100644 --- a/arch/s390/kernel/compat_signal.c +++ b/arch/s390/kernel/compat_signal.c @@ -313,6 +313,10 @@ static int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs) regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) | (__u64)(regs32.psw.mask & PSW32_MASK_USER) << 32 | (__u64)(regs32.psw.addr & PSW32_ADDR_AMODE); + /* Check for invalid user address space control. */ + if ((regs->psw.mask & PSW_MASK_ASC) >= (psw_kernel_bits & PSW_MASK_ASC)) + regs->psw.mask = (psw_user_bits & PSW_MASK_ASC) | + (regs->psw.mask & ~PSW_MASK_ASC); regs->psw.addr = (__u64)(regs32.psw.addr & PSW32_ADDR_INSN); for (i = 0; i < NUM_GPRS; i++) regs->gprs[i] = (__u64) regs32.gprs[i]; @@ -494,7 +498,10 @@ static int setup_frame32(int sig, struct k_sigaction *ka, /* Set up registers for signal handler */ regs->gprs[15] = (__force __u64) frame; - regs->psw.mask |= PSW_MASK_BA; /* force amode 31 */ + /* Force 31 bit amode and default user address space control. */ + regs->psw.mask = PSW_MASK_BA | + (psw_user_bits & PSW_MASK_ASC) | + (regs->psw.mask & ~PSW_MASK_ASC); regs->psw.addr = (__force __u64) ka->sa.sa_handler; regs->gprs[2] = map_signal(sig); @@ -562,7 +569,10 @@ static int setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info, /* Set up registers for signal handler */ regs->gprs[15] = (__force __u64) frame; - regs->psw.mask |= PSW_MASK_BA; /* force amode 31 */ + /* Force 31 bit amode and default user address space control. */ + regs->psw.mask = PSW_MASK_BA | + (psw_user_bits & PSW_MASK_ASC) | + (regs->psw.mask & ~PSW_MASK_ASC); regs->psw.addr = (__u64) ka->sa.sa_handler; regs->gprs[2] = map_signal(sig); diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S index ff605a39cf4..cfe3efda69d 100644 --- a/arch/s390/kernel/compat_wrapper.S +++ b/arch/s390/kernel/compat_wrapper.S @@ -1636,7 +1636,7 @@ ENTRY(compat_sys_process_vm_readv_wrapper) llgfr %r6,%r6 # unsigned long llgf %r0,164(%r15) # unsigned long stg %r0,160(%r15) - jg sys_process_vm_readv + jg compat_sys_process_vm_readv ENTRY(compat_sys_process_vm_writev_wrapper) lgfr %r2,%r2 # compat_pid_t @@ -1646,4 +1646,4 @@ ENTRY(compat_sys_process_vm_writev_wrapper) llgfr %r6,%r6 # unsigned long llgf %r0,164(%r15) # unsigned long stg %r0,160(%r15) - jg sys_process_vm_writev + jg compat_sys_process_vm_writev diff --git a/arch/s390/kernel/processor.c b/arch/s390/kernel/processor.c index 510027dcad7..348b2563824 100644 --- a/arch/s390/kernel/processor.c +++ b/arch/s390/kernel/processor.c @@ -26,12 +26,14 @@ static DEFINE_PER_CPU(struct cpuid, cpu_id); void cpu_init(void) { struct cpuid *id = &per_cpu(cpu_id, smp_processor_id()); + struct s390_idle_data *idle = &__get_cpu_var(s390_idle); get_cpu_id(id); atomic_inc(&init_mm.mm_count); current->active_mm = &init_mm; BUG_ON(current->mm); enter_lazy_tlb(&init_mm, current); + memset(idle, 0, sizeof(*idle)); } /* diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c index f7582b27f60..74f58e211ac 100644 --- a/arch/s390/kernel/signal.c +++ b/arch/s390/kernel/signal.c @@ -148,6 +148,10 @@ static int restore_sigregs(struct pt_regs *regs, _sigregs __user *sregs) /* Use regs->psw.mask instead of psw_user_bits to preserve PER bit. */ regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) | (user_sregs.regs.psw.mask & PSW_MASK_USER); + /* Check for invalid user address space control. */ + if ((regs->psw.mask & PSW_MASK_ASC) >= (psw_kernel_bits & PSW_MASK_ASC)) + regs->psw.mask = (psw_user_bits & PSW_MASK_ASC) | + (regs->psw.mask & ~PSW_MASK_ASC); /* Check for invalid amode */ if (regs->psw.mask & PSW_MASK_EA) regs->psw.mask |= PSW_MASK_BA; @@ -294,7 +298,10 @@ static int setup_frame(int sig, struct k_sigaction *ka, /* Set up registers for signal handler */ regs->gprs[15] = (unsigned long) frame; - regs->psw.mask |= PSW_MASK_EA | PSW_MASK_BA; /* 64 bit amode */ + /* Force default amode and default user address space control. */ + regs->psw.mask = PSW_MASK_EA | PSW_MASK_BA | + (psw_user_bits & PSW_MASK_ASC) | + (regs->psw.mask & ~PSW_MASK_ASC); regs->psw.addr = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE; regs->gprs[2] = map_signal(sig); @@ -367,7 +374,10 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, /* Set up registers for signal handler */ regs->gprs[15] = (unsigned long) frame; - regs->psw.mask |= PSW_MASK_EA | PSW_MASK_BA; /* 64 bit amode */ + /* Force default amode and default user address space control. */ + regs->psw.mask = PSW_MASK_EA | PSW_MASK_BA | + (psw_user_bits & PSW_MASK_ASC) | + (regs->psw.mask & ~PSW_MASK_ASC); regs->psw.addr = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE; regs->gprs[2] = map_signal(sig); diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 621a39455f2..6b503387815 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -1034,14 +1034,11 @@ static int smp_cpu_notify(struct notifier_block *self, unsigned int cpu = (unsigned int)(long)hcpu; struct cpu *c = &pcpu_devices[cpu].cpu; struct device *s = &c->dev; - struct s390_idle_data *idle; int err = 0; switch (action) { case CPU_ONLINE: case CPU_ONLINE_FROZEN: - idle = &per_cpu(s390_idle, cpu); - memset(idle, 0, sizeof(struct s390_idle_data)); err = sysfs_create_group(&s->kobj, &cpu_online_attr_group); break; case CPU_DEAD: diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index d4e1cb1dbcd..c5531dbc8b2 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c @@ -64,7 +64,7 @@ static DEFINE_PER_CPU(struct clock_event_device, comparators); */ unsigned long long notrace __kprobes sched_clock(void) { - return (get_clock_monotonic() * 125) >> 9; + return tod_to_ns(get_clock_monotonic()); } /* diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S index 21109c63eb1..1343d7cf444 100644 --- a/arch/s390/kernel/vmlinux.lds.S +++ b/arch/s390/kernel/vmlinux.lds.S @@ -8,7 +8,7 @@ #ifndef CONFIG_64BIT OUTPUT_FORMAT("elf32-s390", "elf32-s390", "elf32-s390") -OUTPUT_ARCH(s390) +OUTPUT_ARCH(s390:31-bit) ENTRY(startup) jiffies = jiffies_64 + 4; #else diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c index 2d9f9a72bb8..10e13b331d3 100644 --- a/arch/s390/kvm/interrupt.c +++ b/arch/s390/kvm/interrupt.c @@ -390,7 +390,7 @@ int kvm_s390_handle_wait(struct kvm_vcpu *vcpu) return 0; } - sltime = ((vcpu->arch.sie_block->ckc - now)*125)>>9; + sltime = tod_to_ns(vcpu->arch.sie_block->ckc - now); hrtimer_start(&vcpu->arch.ckc_timer, ktime_set (0, sltime) , HRTIMER_MODE_REL); VCPU_EVENT(vcpu, 5, "enabled wait via clock comparator: %llx ns", sltime); diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index d02a1463680..b34e4e0275a 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c @@ -443,6 +443,7 @@ int __handle_fault(unsigned long uaddr, unsigned long pgm_int_code, int write) struct pt_regs regs; int access, fault; + /* Emulate a uaccess fault from kernel mode. */ regs.psw.mask = psw_kernel_bits | PSW_MASK_DAT | PSW_MASK_MCHECK; if (!irqs_disabled()) regs.psw.mask |= PSW_MASK_IO | PSW_MASK_EXT; @@ -452,12 +453,12 @@ int __handle_fault(unsigned long uaddr, unsigned long pgm_int_code, int write) regs.int_parm_long = (uaddr & PAGE_MASK) | 2; access = write ? VM_WRITE : VM_READ; fault = do_exception(®s, access); - if (unlikely(fault)) { - if (fault & VM_FAULT_OOM) - return -EFAULT; - else if (fault & VM_FAULT_SIGBUS) - do_sigbus(®s); - } + /* + * Since the fault happened in kernel mode while performing a uaccess + * all we need to do now is emulating a fixup in case "fault" is not + * zero. + * For the calling uaccess functions this results always in -EFAULT. + */ return fault ? -EFAULT : 0; } diff --git a/arch/s390/mm/gup.c b/arch/s390/mm/gup.c index 65cb06e2af4..4ccf9f54355 100644 --- a/arch/s390/mm/gup.c +++ b/arch/s390/mm/gup.c @@ -183,7 +183,7 @@ int get_user_pages_fast(unsigned long start, int nr_pages, int write, addr = start; len = (unsigned long) nr_pages << PAGE_SHIFT; end = start + len; - if (end < start) + if ((end < start) || (end > TASK_SIZE)) goto slow_irqon; /* diff --git a/arch/s390/mm/mmap.c b/arch/s390/mm/mmap.c index 2857c48486e..a64fe53c720 100644 --- a/arch/s390/mm/mmap.c +++ b/arch/s390/mm/mmap.c @@ -105,9 +105,15 @@ void arch_pick_mmap_layout(struct mm_struct *mm) int s390_mmap_check(unsigned long addr, unsigned long len) { + int rc; + if (!is_compat_task() && - len >= TASK_SIZE && TASK_SIZE < (1UL << 53)) - return crst_table_upgrade(current->mm, 1UL << 53); + len >= TASK_SIZE && TASK_SIZE < (1UL << 53)) { + rc = crst_table_upgrade(current->mm, 1UL << 53); + if (rc) + return rc; + update_mm(current->mm, current); + } return 0; } @@ -127,6 +133,7 @@ s390_get_unmapped_area(struct file *filp, unsigned long addr, rc = crst_table_upgrade(mm, 1UL << 53); if (rc) return (unsigned long) rc; + update_mm(mm, current); area = arch_get_unmapped_area(filp, addr, len, pgoff, flags); } return area; @@ -149,6 +156,7 @@ s390_get_unmapped_area_topdown(struct file *filp, const unsigned long addr, rc = crst_table_upgrade(mm, 1UL << 53); if (rc) return (unsigned long) rc; + update_mm(mm, current); area = arch_get_unmapped_area_topdown(filp, addr, len, pgoff, flags); } diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c index 6e765bf0067..87f0efd0e77 100644 --- a/arch/s390/mm/pgtable.c +++ b/arch/s390/mm/pgtable.c @@ -85,7 +85,6 @@ int crst_table_upgrade(struct mm_struct *mm, unsigned long limit) crst_table_free(mm, table); if (mm->context.asce_limit < limit) goto repeat; - update_mm(mm, current); return 0; } @@ -93,9 +92,6 @@ void crst_table_downgrade(struct mm_struct *mm, unsigned long limit) { pgd_t *pgd; - if (mm->context.asce_limit <= limit) - return; - __tlb_flush_mm(mm); while (mm->context.asce_limit > limit) { pgd = mm->pgd; switch (pgd_val(*pgd) & _REGION_ENTRY_TYPE_MASK) { @@ -118,7 +114,6 @@ void crst_table_downgrade(struct mm_struct *mm, unsigned long limit) mm->task_size = mm->context.asce_limit; crst_table_free(mm, (unsigned long *) pgd); } - update_mm(mm, current); } #endif diff --git a/arch/s390/oprofile/init.c b/arch/s390/oprofile/init.c index 2297be406c6..abe8722adda 100644 --- a/arch/s390/oprofile/init.c +++ b/arch/s390/oprofile/init.c @@ -171,7 +171,7 @@ static ssize_t hw_interval_write(struct file *file, char const __user *buf, if (*offset) return -EINVAL; retval = oprofilefs_ulong_from_user(&val, buf, count); - if (retval) + if (retval <= 0) return retval; if (val < oprofile_min_interval) oprofile_hw_interval = oprofile_min_interval; @@ -214,7 +214,7 @@ static ssize_t hwsampler_zero_write(struct file *file, char const __user *buf, return -EINVAL; retval = oprofilefs_ulong_from_user(&val, buf, count); - if (retval) + if (retval <= 0) return retval; if (val != 0) return -EINVAL; @@ -245,7 +245,7 @@ static ssize_t hwsampler_kernel_write(struct file *file, char const __user *buf, return -EINVAL; retval = oprofilefs_ulong_from_user(&val, buf, count); - if (retval) + if (retval <= 0) return retval; if (val != 0 && val != 1) @@ -280,7 +280,7 @@ static ssize_t hwsampler_user_write(struct file *file, char const __user *buf, return -EINVAL; retval = oprofilefs_ulong_from_user(&val, buf, count); - if (retval) + if (retval <= 0) return retval; if (val != 0 && val != 1) @@ -319,7 +319,7 @@ static ssize_t timer_enabled_write(struct file *file, char const __user *buf, return -EINVAL; retval = oprofilefs_ulong_from_user(&val, buf, count); - if (retval) + if (retval <= 0) return retval; if (val != 0 && val != 1) diff --git a/arch/score/kernel/process.c b/arch/score/kernel/process.c index 2707023c756..637970cfd3f 100644 --- a/arch/score/kernel/process.c +++ b/arch/score/kernel/process.c @@ -27,6 +27,7 @@ #include #include #include +#include void (*pm_power_off)(void); EXPORT_SYMBOL(pm_power_off); @@ -50,9 +51,10 @@ void __noreturn cpu_idle(void) { /* endless idle loop with no priority at all */ while (1) { + rcu_idle_enter(); while (!need_resched()) barrier(); - + rcu_idle_exit(); schedule_preempt_disabled(); } } diff --git a/arch/sh/include/asm/elf.h b/arch/sh/include/asm/elf.h index f38112be67d..978b7fd6d47 100644 --- a/arch/sh/include/asm/elf.h +++ b/arch/sh/include/asm/elf.h @@ -202,9 +202,9 @@ extern void __kernel_vsyscall; if (vdso_enabled) \ NEW_AUX_ENT(AT_SYSINFO_EHDR, VDSO_BASE); \ else \ - NEW_AUX_ENT(AT_IGNORE, 0); + NEW_AUX_ENT(AT_IGNORE, 0) #else -#define VSYSCALL_AUX_ENT +#define VSYSCALL_AUX_ENT NEW_AUX_ENT(AT_IGNORE, 0) #endif /* CONFIG_VSYSCALL */ #ifdef CONFIG_SH_FPU diff --git a/arch/sparc/include/asm/hugetlb.h b/arch/sparc/include/asm/hugetlb.h index 177061064ee..f368cef0379 100644 --- a/arch/sparc/include/asm/hugetlb.h +++ b/arch/sparc/include/asm/hugetlb.h @@ -58,14 +58,20 @@ static inline pte_t huge_pte_wrprotect(pte_t pte) static inline void huge_ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { - ptep_set_wrprotect(mm, addr, ptep); + pte_t old_pte = *ptep; + set_huge_pte_at(mm, addr, ptep, pte_wrprotect(old_pte)); } static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep, pte_t pte, int dirty) { - return ptep_set_access_flags(vma, addr, ptep, pte, dirty); + int changed = !pte_same(*ptep, pte); + if (changed) { + set_huge_pte_at(vma->vm_mm, addr, ptep, pte); + flush_tlb_page(vma, addr); + } + return changed; } static inline pte_t huge_ptep_get(pte_t *ptep) diff --git a/arch/sparc/kernel/perf_event.c b/arch/sparc/kernel/perf_event.c index 28559ce5eeb..602eca8ef8c 100644 --- a/arch/sparc/kernel/perf_event.c +++ b/arch/sparc/kernel/perf_event.c @@ -557,11 +557,13 @@ static u64 nop_for_index(int idx) static inline void sparc_pmu_enable_event(struct cpu_hw_events *cpuc, struct hw_perf_event *hwc, int idx) { - u64 val, mask = mask_for_index(idx); + u64 enc, val, mask = mask_for_index(idx); + + enc = perf_event_get_enc(cpuc->events[idx]); val = cpuc->pcr; val &= ~mask; - val |= hwc->config; + val |= event_encoding(enc, idx); cpuc->pcr = val; pcr_ops->write(cpuc->pcr); @@ -1428,8 +1430,6 @@ static void perf_callchain_user_64(struct perf_callchain_entry *entry, { unsigned long ufp; - perf_callchain_store(entry, regs->tpc); - ufp = regs->u_regs[UREG_I6] + STACK_BIAS; do { struct sparc_stackf *usf, sf; @@ -1450,8 +1450,6 @@ static void perf_callchain_user_32(struct perf_callchain_entry *entry, { unsigned long ufp; - perf_callchain_store(entry, regs->tpc); - ufp = regs->u_regs[UREG_I6] & 0xffffffffUL; do { struct sparc_stackf32 *usf, sf; @@ -1470,6 +1468,11 @@ static void perf_callchain_user_32(struct perf_callchain_entry *entry, void perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs) { + perf_callchain_store(entry, regs->tpc); + + if (!current->mm) + return; + flushw_user(); if (test_thread_flag(TIF_32BIT)) perf_callchain_user_32(entry, regs); diff --git a/arch/sparc/kernel/signal_64.c b/arch/sparc/kernel/signal_64.c index 48b0f57b65f..40837f07143 100644 --- a/arch/sparc/kernel/signal_64.c +++ b/arch/sparc/kernel/signal_64.c @@ -309,9 +309,7 @@ void do_rt_sigreturn(struct pt_regs *regs) err |= restore_fpu_state(regs, fpu_save); err |= __copy_from_user(&set, &sf->mask, sizeof(sigset_t)); - err |= do_sigaltstack(&sf->stack, NULL, (unsigned long)sf); - - if (err) + if (err || do_sigaltstack(&sf->stack, NULL, (unsigned long)sf) == -EFAULT) goto segv; err |= __get_user(rwin_save, &sf->rwin_save); diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c index 3ee51f189a5..57b7cab1e26 100644 --- a/arch/sparc/kernel/sys_sparc_64.c +++ b/arch/sparc/kernel/sys_sparc_64.c @@ -519,12 +519,12 @@ SYSCALL_DEFINE1(sparc64_personality, unsigned long, personality) { int ret; - if (current->personality == PER_LINUX32 && - personality == PER_LINUX) - personality = PER_LINUX32; + if (personality(current->personality) == PER_LINUX32 && + personality(personality) == PER_LINUX) + personality |= PER_LINUX32; ret = sys_personality(personality); - if (ret == PER_LINUX32) - ret = PER_LINUX; + if (personality(ret) == PER_LINUX32) + ret &= ~PER_LINUX32; return ret; } diff --git a/arch/sparc/kernel/syscalls.S b/arch/sparc/kernel/syscalls.S index 1d7e274f3f2..7f5f65d0b3f 100644 --- a/arch/sparc/kernel/syscalls.S +++ b/arch/sparc/kernel/syscalls.S @@ -212,24 +212,20 @@ linux_sparc_syscall: 3: stx %o0, [%sp + PTREGS_OFF + PT_V9_I0] ret_sys_call: ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %g3 - ldx [%sp + PTREGS_OFF + PT_V9_TNPC], %l1 ! pc = npc sra %o0, 0, %o0 mov %ulo(TSTATE_XCARRY | TSTATE_ICARRY), %g2 sllx %g2, 32, %g2 - /* Check if force_successful_syscall_return() - * was invoked. - */ - ldub [%g6 + TI_SYS_NOERROR], %l2 - brnz,a,pn %l2, 80f - stb %g0, [%g6 + TI_SYS_NOERROR] - cmp %o0, -ERESTART_RESTARTBLOCK bgeu,pn %xcc, 1f - andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT), %l6 -80: + andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT), %g0 + ldx [%sp + PTREGS_OFF + PT_V9_TNPC], %l1 ! pc = npc + +2: + stb %g0, [%g6 + TI_SYS_NOERROR] /* System call success, clear Carry condition code. */ andn %g3, %g2, %g3 +3: stx %g3, [%sp + PTREGS_OFF + PT_V9_TSTATE] bne,pn %icc, linux_syscall_trace2 add %l1, 0x4, %l2 ! npc = npc+4 @@ -238,20 +234,20 @@ ret_sys_call: stx %l2, [%sp + PTREGS_OFF + PT_V9_TNPC] 1: + /* Check if force_successful_syscall_return() + * was invoked. + */ + ldub [%g6 + TI_SYS_NOERROR], %l2 + brnz,pn %l2, 2b + ldx [%sp + PTREGS_OFF + PT_V9_TNPC], %l1 ! pc = npc /* System call failure, set Carry condition code. * Also, get abs(errno) to return to the process. */ - andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT), %l6 sub %g0, %o0, %o0 - or %g3, %g2, %g3 stx %o0, [%sp + PTREGS_OFF + PT_V9_I0] - stx %g3, [%sp + PTREGS_OFF + PT_V9_TSTATE] - bne,pn %icc, linux_syscall_trace2 - add %l1, 0x4, %l2 ! npc = npc+4 - stx %l1, [%sp + PTREGS_OFF + PT_V9_TPC] + ba,pt %xcc, 3b + or %g3, %g2, %g3 - b,pt %xcc, rtrap - stx %l2, [%sp + PTREGS_OFF + PT_V9_TNPC] linux_syscall_trace2: call syscall_trace_leave add %sp, PTREGS_OFF, %o0 diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c index 4aff8f39fce..e5ce436ec30 100644 --- a/arch/sparc/mm/init_64.c +++ b/arch/sparc/mm/init_64.c @@ -2099,6 +2099,9 @@ EXPORT_SYMBOL(_PAGE_CACHE); #ifdef CONFIG_SPARSEMEM_VMEMMAP unsigned long vmemmap_table[VMEMMAP_SIZE]; +static long __meminitdata addr_start, addr_end; +static int __meminitdata node_start; + int __meminit vmemmap_populate(struct page *start, unsigned long nr, int node) { unsigned long vstart = (unsigned long) start; @@ -2129,15 +2132,30 @@ int __meminit vmemmap_populate(struct page *start, unsigned long nr, int node) *vmem_pp = pte_base | __pa(block); - printk(KERN_INFO "[%p-%p] page_structs=%lu " - "node=%d entry=%lu/%lu\n", start, block, nr, - node, - addr >> VMEMMAP_CHUNK_SHIFT, - VMEMMAP_SIZE); + /* check to see if we have contiguous blocks */ + if (addr_end != addr || node_start != node) { + if (addr_start) + printk(KERN_DEBUG " [%lx-%lx] on node %d\n", + addr_start, addr_end-1, node_start); + addr_start = addr; + node_start = node; + } + addr_end = addr + VMEMMAP_CHUNK; } } return 0; } + +void __meminit vmemmap_populate_print_last(void) +{ + if (addr_start) { + printk(KERN_DEBUG " [%lx-%lx] on node %d\n", + addr_start, addr_end-1, node_start); + addr_start = 0; + addr_end = 0; + node_start = 0; + } +} #endif /* CONFIG_SPARSEMEM_VMEMMAP */ static void prot_init_common(unsigned long page_none, diff --git a/arch/tile/Makefile b/arch/tile/Makefile index 9520bc5a4b7..99f461d8d9d 100644 --- a/arch/tile/Makefile +++ b/arch/tile/Makefile @@ -26,6 +26,10 @@ $(error Set TILERA_ROOT or CROSS_COMPILE when building $(ARCH) on $(HOST_ARCH)) endif endif +# The tile compiler may emit .eh_frame information for backtracing. +# In kernel modules, this causes load failures due to unsupported relocations. +KBUILD_CFLAGS += -fno-asynchronous-unwind-tables + ifneq ($(CONFIG_DEBUG_EXTRA_FLAGS),"") KBUILD_CFLAGS += $(CONFIG_DEBUG_EXTRA_FLAGS) endif diff --git a/arch/x86/Makefile b/arch/x86/Makefile index b1c611e6da6..f1276aaeffd 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -85,7 +85,7 @@ endif ifdef CONFIG_X86_X32 x32_ld_ok := $(call try-run,\ /bin/echo -e '1: .quad 1b' | \ - $(CC) $(KBUILD_AFLAGS) -c -xassembler -o "$$TMP" - && \ + $(CC) $(KBUILD_AFLAGS) -c -x assembler -o "$$TMP" - && \ $(OBJCOPY) -O elf32-x86-64 "$$TMP" "$$TMPO" && \ $(LD) -m elf32_x86_64 "$$TMPO" -o "$$TMP",y,n) ifeq ($(x32_ld_ok),y) diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile index e398bb5d63b..8a84501acb1 100644 --- a/arch/x86/boot/compressed/Makefile +++ b/arch/x86/boot/compressed/Makefile @@ -28,6 +28,9 @@ VMLINUX_OBJS = $(obj)/vmlinux.lds $(obj)/head_$(BITS).o $(obj)/misc.o \ $(obj)/string.o $(obj)/cmdline.o $(obj)/early_serial_console.o \ $(obj)/piggy.o +$(obj)/eboot.o: KBUILD_CFLAGS += -fshort-wchar -mno-red-zone +$(obj)/efi_stub_$(BITS).o: KBUILD_CLFAGS += -fshort-wchar -mno-red-zone + ifeq ($(CONFIG_EFI_STUB), y) VMLINUX_OBJS += $(obj)/eboot.o $(obj)/efi_stub_$(BITS).o endif diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c index 0cdfc0d2315..8bb90707cb5 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c @@ -12,6 +12,8 @@ #include #include +#undef memcpy /* Use memcpy from misc.c */ + #include "eboot.h" static efi_system_table_t *sys_table; diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S index e3e734005e1..66c4cae439c 100644 --- a/arch/x86/ia32/ia32entry.S +++ b/arch/x86/ia32/ia32entry.S @@ -205,7 +205,7 @@ sysexit_from_sys_call: testl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET) jnz ia32_ret_from_sys_call TRACE_IRQS_ON - sti + ENABLE_INTERRUPTS(CLBR_NONE) movl %eax,%esi /* second arg, syscall return value */ cmpl $-MAX_ERRNO,%eax /* is it an error ? */ jbe 1f @@ -215,7 +215,7 @@ sysexit_from_sys_call: call __audit_syscall_exit movq RAX-ARGOFFSET(%rsp),%rax /* reload syscall return value */ movl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),%edi - cli + DISABLE_INTERRUPTS(CLBR_NONE) TRACE_IRQS_OFF testl %edi,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET) jz \exit diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h index c9dcc181d4d..029189db84d 100644 --- a/arch/x86/include/asm/efi.h +++ b/arch/x86/include/asm/efi.h @@ -98,6 +98,7 @@ extern void efi_set_executable(efi_memory_desc_t *md, bool executable); extern int efi_memblock_x86_reserve_range(void); extern void efi_call_phys_prelog(void); extern void efi_call_phys_epilog(void); +extern void efi_unmap_memmap(void); #ifndef CONFIG_EFI /* diff --git a/arch/x86/include/asm/fpu-internal.h b/arch/x86/include/asm/fpu-internal.h index 4fa88154e4d..92e05b6c84f 100644 --- a/arch/x86/include/asm/fpu-internal.h +++ b/arch/x86/include/asm/fpu-internal.h @@ -334,14 +334,17 @@ static inline void __thread_fpu_begin(struct task_struct *tsk) typedef struct { int preload; } fpu_switch_t; /* - * FIXME! We could do a totally lazy restore, but we need to - * add a per-cpu "this was the task that last touched the FPU - * on this CPU" variable, and the task needs to have a "I last - * touched the FPU on this CPU" and check them. + * Must be run with preemption disabled: this clears the fpu_owner_task, + * on this CPU. * - * We don't do that yet, so "fpu_lazy_restore()" always returns - * false, but some day.. + * This will disable any lazy FPU state restore of the current FPU state, + * but if the current thread owns the FPU, it will still be saved by. */ +static inline void __cpu_disable_lazy_restore(unsigned int cpu) +{ + per_cpu(fpu_owner_task, cpu) = NULL; +} + static inline int fpu_lazy_restore(struct task_struct *new, unsigned int cpu) { return new == percpu_read_stable(fpu_owner_task) && diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index 49afb3f41eb..c3520d76820 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -146,8 +146,7 @@ static inline unsigned long pmd_pfn(pmd_t pmd) static inline int pmd_large(pmd_t pte) { - return (pmd_flags(pte) & (_PAGE_PSE | _PAGE_PRESENT)) == - (_PAGE_PSE | _PAGE_PRESENT); + return pmd_flags(pte) & _PAGE_PSE; } #ifdef CONFIG_TRANSPARENT_HUGEPAGE @@ -415,7 +414,13 @@ static inline int pte_hidden(pte_t pte) static inline int pmd_present(pmd_t pmd) { - return pmd_flags(pmd) & _PAGE_PRESENT; + /* + * Checking for _PAGE_PSE is needed too because + * split_huge_page will temporarily clear the present bit (but + * the _PAGE_PSE flag will remain set at all times while the + * _PAGE_PRESENT bit is clear). + */ + return pmd_flags(pmd) & (_PAGE_PRESENT | _PAGE_PROTNONE | _PAGE_PSE); } static inline int pmd_none(pmd_t pmd) diff --git a/arch/x86/include/asm/ptrace.h b/arch/x86/include/asm/ptrace.h index dcfde52979c..19f16ebaf4f 100644 --- a/arch/x86/include/asm/ptrace.h +++ b/arch/x86/include/asm/ptrace.h @@ -205,21 +205,14 @@ static inline bool user_64bit_mode(struct pt_regs *regs) } #endif -/* - * X86_32 CPUs don't save ss and esp if the CPU is already in kernel mode - * when it traps. The previous stack will be directly underneath the saved - * registers, and 'sp/ss' won't even have been saved. Thus the '®s->sp'. - * - * This is valid only for kernel mode traps. - */ -static inline unsigned long kernel_stack_pointer(struct pt_regs *regs) -{ #ifdef CONFIG_X86_32 - return (unsigned long)(®s->sp); +extern unsigned long kernel_stack_pointer(struct pt_regs *regs); #else +static inline unsigned long kernel_stack_pointer(struct pt_regs *regs) +{ return regs->sp; -#endif } +#endif #define GET_IP(regs) ((regs)->ip) #define GET_FP(regs) ((regs)->bp) diff --git a/arch/x86/include/asm/xen/page.h b/arch/x86/include/asm/xen/page.h index c34f96c2f7a..1bd321d00f2 100644 --- a/arch/x86/include/asm/xen/page.h +++ b/arch/x86/include/asm/xen/page.h @@ -50,7 +50,8 @@ extern unsigned long set_phys_range_identity(unsigned long pfn_s, extern int m2p_add_override(unsigned long mfn, struct page *page, struct gnttab_map_grant_ref *kmap_op); -extern int m2p_remove_override(struct page *page, bool clear_pte); +extern int m2p_remove_override(struct page *page, + struct gnttab_map_grant_ref *kmap_op); extern struct page *m2p_find_override(unsigned long mfn); extern unsigned long m2p_find_override_pfn(unsigned long mfn, unsigned long pfn); diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index 1f84794f075..bda833c5f6c 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c @@ -160,7 +160,7 @@ static const unsigned char * const k7_nops[ASM_NOP_MAX+2] = #endif #ifdef P6_NOP1 -static const unsigned char __initconst_or_module p6nops[] = +static const unsigned char p6nops[] = { P6_NOP1, P6_NOP2, @@ -219,7 +219,7 @@ void __init arch_init_ideal_nops(void) ideal_nops = intel_nops; #endif } - + break; default: #ifdef CONFIG_X86_64 ideal_nops = k8_nops; diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index d40b9ca6a56..9f83547eb07 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -598,6 +598,34 @@ static void init_amd(struct cpuinfo_x86 *c) } } + /* + * The way access filter has a performance penalty on some workloads. + * Disable it on the affected CPUs. + */ + if ((c->x86 == 0x15) && + (c->x86_model >= 0x02) && (c->x86_model < 0x20)) { + u64 val; + + if (!rdmsrl_safe(0xc0011021, &val) && !(val & 0x1E)) { + val |= 0x1E; + checking_wrmsrl(0xc0011021, val); + } + } + + /* + * The way access filter has a performance penalty on some workloads. + * Disable it on the affected CPUs. + */ + if ((c->x86 == 0x15) && + (c->x86_model >= 0x02) && (c->x86_model < 0x20)) { + u64 val; + + if (!rdmsrl_safe(0xc0011021, &val) && !(val & 0x1E)) { + val |= 0x1E; + checking_wrmsrl(0xc0011021, val); + } + } + cpu_detect_cache_sizes(c); /* Multi core CPU? */ diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index 6640374cdcc..41547f29acf 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c @@ -1180,6 +1180,7 @@ void mce_notify_process(void) { unsigned long pfn; struct mce_info *mi = mce_find_info(); + int flags = MF_ACTION_REQUIRED; if (!mi) mce_panic("Lost physical address for unconsumed uncorrectable error", NULL, NULL); @@ -1194,8 +1195,9 @@ void mce_notify_process(void) * doomed. We still need to mark the page as poisoned and alert any * other users of the page. */ - if (memory_failure(pfn, MCE_VECTOR, MF_ACTION_REQUIRED) < 0 || - mi->restartable == 0) { + if (!mi->restartable) + flags |= MF_MUST_KILL; + if (memory_failure(pfn, MCE_VECTOR, flags) < 0) { pr_err("Memory error not recovered"); force_sig(SIGBUS, current); } diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c index 62d61e9976e..298dc000378 100644 --- a/arch/x86/kernel/e820.c +++ b/arch/x86/kernel/e820.c @@ -1076,6 +1076,9 @@ void __init memblock_x86_fill(void) memblock_add(ei->addr, ei->size); } + /* throw away partial pages */ + memblock_trim_memory(PAGE_SIZE); + memblock_dump_all(); } diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S index 7b784f4ef1e..2af4ccd88d1 100644 --- a/arch/x86/kernel/entry_32.S +++ b/arch/x86/kernel/entry_32.S @@ -1025,7 +1025,7 @@ ENTRY(xen_sysenter_target) ENTRY(xen_hypervisor_callback) CFI_STARTPROC - pushl_cfi $0 + pushl_cfi $-1 /* orig_ax = -1 => not a system call */ SAVE_ALL TRACE_IRQS_OFF @@ -1067,14 +1067,15 @@ ENTRY(xen_failsafe_callback) 2: mov 8(%esp),%es 3: mov 12(%esp),%fs 4: mov 16(%esp),%gs + /* EAX == 0 => Category 1 (Bad segment) + EAX != 0 => Category 2 (Bad IRET) */ testl %eax,%eax popl_cfi %eax lea 16(%esp),%esp CFI_ADJUST_CFA_OFFSET -16 jz 5f - addl $16,%esp - jmp iret_exc # EAX != 0 => Category 2 (Bad IRET) -5: pushl_cfi $0 # EAX == 0 => Category 1 (Bad segment) + jmp iret_exc +5: pushl_cfi $-1 /* orig_ax = -1 => not a system call */ SAVE_ALL jmp ret_from_exception CFI_ENDPROC diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index cdc79b5cfcd..bd6f59203b5 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S @@ -1351,7 +1351,7 @@ ENTRY(xen_failsafe_callback) CFI_RESTORE r11 addq $0x30,%rsp CFI_ADJUST_CFA_OFFSET -0x30 - pushq_cfi $0 + pushq_cfi $-1 /* orig_ax = -1 => not a system call */ SAVE_ALL jmp error_exit CFI_ENDPROC diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c index ad0de0c2714..2861b4cafd2 100644 --- a/arch/x86/kernel/hpet.c +++ b/arch/x86/kernel/hpet.c @@ -431,7 +431,7 @@ void hpet_msi_unmask(struct irq_data *data) /* unmask it */ cfg = hpet_readl(HPET_Tn_CFG(hdev->num)); - cfg |= HPET_TN_FSB; + cfg |= HPET_TN_ENABLE | HPET_TN_FSB; hpet_writel(cfg, HPET_Tn_CFG(hdev->num)); } @@ -442,7 +442,7 @@ void hpet_msi_mask(struct irq_data *data) /* mask it */ cfg = hpet_readl(HPET_Tn_CFG(hdev->num)); - cfg &= ~HPET_TN_FSB; + cfg &= ~(HPET_TN_ENABLE | HPET_TN_FSB); hpet_writel(cfg, HPET_Tn_CFG(hdev->num)); } diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c index 8a2ce8fd41c..5d8cf0d6796 100644 --- a/arch/x86/kernel/microcode_amd.c +++ b/arch/x86/kernel/microcode_amd.c @@ -97,6 +97,7 @@ static unsigned int verify_ucode_size(int cpu, u32 patch_size, #define F1XH_MPB_MAX_SIZE 2048 #define F14H_MPB_MAX_SIZE 1824 #define F15H_MPB_MAX_SIZE 4096 +#define F16H_MPB_MAX_SIZE 3458 switch (c->x86) { case 0x14: @@ -105,6 +106,9 @@ static unsigned int verify_ucode_size(int cpu, u32 patch_size, case 0x15: max_size = F15H_MPB_MAX_SIZE; break; + case 0x16: + max_size = F16H_MPB_MAX_SIZE; + break; default: max_size = F1XH_MPB_MAX_SIZE; break; @@ -143,11 +147,12 @@ static int get_matching_microcode(int cpu, const u8 *ucode_ptr, unsigned int *current_size) { struct microcode_header_amd *mc_hdr; - unsigned int actual_size; + unsigned int actual_size, patch_size; u16 equiv_cpu_id; /* size of the current patch we're staring at */ - *current_size = *(u32 *)(ucode_ptr + 4) + SECTION_HDR_SIZE; + patch_size = *(u32 *)(ucode_ptr + 4); + *current_size = patch_size + SECTION_HDR_SIZE; equiv_cpu_id = find_equiv_id(); if (!equiv_cpu_id) @@ -174,7 +179,7 @@ static int get_matching_microcode(int cpu, const u8 *ucode_ptr, /* * now that the header looks sane, verify its size */ - actual_size = verify_ucode_size(cpu, *current_size, leftover_size); + actual_size = verify_ucode_size(cpu, patch_size, leftover_size); if (!actual_size) return 0; diff --git a/arch/x86/kernel/microcode_core.c b/arch/x86/kernel/microcode_core.c index 937cb7e0c65..a88575fe9e8 100644 --- a/arch/x86/kernel/microcode_core.c +++ b/arch/x86/kernel/microcode_core.c @@ -298,20 +298,31 @@ static ssize_t reload_store(struct device *dev, const char *buf, size_t size) { unsigned long val; - int cpu = dev->id; - int ret = 0; - char *end; + int cpu; + ssize_t ret = 0, tmp_ret; - val = simple_strtoul(buf, &end, 0); - if (end == buf) + /* allow reload only from the BSP */ + if (boot_cpu_data.cpu_index != dev->id) return -EINVAL; - if (val == 1) { - get_online_cpus(); - if (cpu_online(cpu)) - ret = reload_for_cpu(cpu); - put_online_cpus(); + ret = kstrtoul(buf, 0, &val); + if (ret) + return ret; + + if (val != 1) + return size; + + get_online_cpus(); + for_each_online_cpu(cpu) { + tmp_ret = reload_for_cpu(cpu); + if (tmp_ret != 0) + pr_warn("Error reloading microcode on CPU %d\n", cpu); + + /* save retval of the first encountered reload error */ + if (!ret) + ret = tmp_ret; } + put_online_cpus(); if (!ret) ret = size; diff --git a/arch/x86/kernel/msr.c b/arch/x86/kernel/msr.c index 3757df2721e..7786b65f7cc 100644 --- a/arch/x86/kernel/msr.c +++ b/arch/x86/kernel/msr.c @@ -174,6 +174,9 @@ static int msr_open(struct inode *inode, struct file *file) unsigned int cpu; struct cpuinfo_x86 *c; + if (!capable(CAP_SYS_RAWIO)) + return -EPERM; + cpu = iminor(file->f_path.dentry->d_inode); if (cpu >= nr_cpu_ids || !cpu_online(cpu)) return -ENXIO; /* No such CPU */ diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index cf1178332bc..c4410fb4938 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -165,6 +166,35 @@ static inline bool invalid_selector(u16 value) #define FLAG_MASK FLAG_MASK_32 +/* + * X86_32 CPUs don't save ss and esp if the CPU is already in kernel mode + * when it traps. The previous stack will be directly underneath the saved + * registers, and 'sp/ss' won't even have been saved. Thus the '®s->sp'. + * + * Now, if the stack is empty, '®s->sp' is out of range. In this + * case we try to take the previous stack. To always return a non-null + * stack pointer we fall back to regs as stack if no previous stack + * exists. + * + * This is valid only for kernel mode traps. + */ +unsigned long kernel_stack_pointer(struct pt_regs *regs) +{ + unsigned long context = (unsigned long)regs & ~(THREAD_SIZE - 1); + unsigned long sp = (unsigned long)®s->sp; + struct thread_info *tinfo; + + if (context == (sp & ~(THREAD_SIZE - 1))) + return sp; + + tinfo = (struct thread_info *)context; + if (tinfo->previous_esp) + return tinfo->previous_esp; + + return (unsigned long)regs; +} +EXPORT_SYMBOL_GPL(kernel_stack_pointer); + static unsigned long *pt_regs_access(struct pt_regs *regs, unsigned long regno) { BUILD_BUG_ON(offsetof(struct pt_regs, bx) != 0); diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index a3e9be27539..2d68753e39d 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -621,6 +621,83 @@ static __init void reserve_ibft_region(void) static unsigned reserve_low = CONFIG_X86_RESERVE_LOW << 10; +static bool __init snb_gfx_workaround_needed(void) +{ +#ifdef CONFIG_PCI + int i; + u16 vendor, devid; + static const u16 snb_ids[] = { + 0x0102, + 0x0112, + 0x0122, + 0x0106, + 0x0116, + 0x0126, + 0x010a, + }; + + /* Assume no if something weird is going on with PCI */ + if (!early_pci_allowed()) + return false; + + vendor = read_pci_config_16(0, 2, 0, PCI_VENDOR_ID); + if (vendor != 0x8086) + return false; + + devid = read_pci_config_16(0, 2, 0, PCI_DEVICE_ID); + for (i = 0; i < ARRAY_SIZE(snb_ids); i++) + if (devid == snb_ids[i]) + return true; +#endif + + return false; +} + +/* + * Sandy Bridge graphics has trouble with certain ranges, exclude + * them from allocation. + */ +static void __init trim_snb_memory(void) +{ + static const unsigned long bad_pages[] = { + 0x20050000, + 0x20110000, + 0x20130000, + 0x20138000, + 0x40004000, + }; + int i; + + if (!snb_gfx_workaround_needed()) + return; + + printk(KERN_DEBUG "reserving inaccessible SNB gfx pages\n"); + + /* + * Reserve all memory below the 1 MB mark that has not + * already been reserved. + */ + memblock_reserve(0, 1<<20); + + for (i = 0; i < ARRAY_SIZE(bad_pages); i++) { + if (memblock_reserve(bad_pages[i], PAGE_SIZE)) + printk(KERN_WARNING "failed to reserve 0x%08lx\n", + bad_pages[i]); + } +} + +/* + * Here we put platform-specific memory range workarounds, i.e. + * memory known to be corrupt or otherwise in need to be reserved on + * specific platforms. + * + * If this gets used more widely it could use a real dispatch mechanism. + */ +static void __init trim_platform_memory_ranges(void) +{ + trim_snb_memory(); +} + static void __init trim_bios_range(void) { /* @@ -641,6 +718,7 @@ static void __init trim_bios_range(void) * take them out. */ e820_remove_range(BIOS_BEGIN, BIOS_END - BIOS_BEGIN, E820_RAM, 1); + sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map); } @@ -920,6 +998,8 @@ void __init setup_arch(char **cmdline_p) setup_trampolines(); + trim_platform_memory_ranges(); + init_gbpages(); /* max_pfn_mapped is updated here */ @@ -928,8 +1008,22 @@ void __init setup_arch(char **cmdline_p) #ifdef CONFIG_X86_64 if (max_pfn > max_low_pfn) { - max_pfn_mapped = init_memory_mapping(1UL<<32, - max_pfn< #include #include +#include +#include #include #include #include @@ -851,6 +853,9 @@ int native_cpu_up(unsigned int cpu) per_cpu(cpu_state, cpu) = CPU_UP_PREPARE; + /* the FPU context is blank, nobody can own it */ + __cpu_disable_lazy_restore(cpu); + err = do_boot_cpu(apicid, cpu); if (err) { pr_debug("do_boot_cpu failed %d\n", err); diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h index 26d1fb437eb..638de3efd7a 100644 --- a/arch/x86/kvm/cpuid.h +++ b/arch/x86/kvm/cpuid.h @@ -23,6 +23,9 @@ static inline bool guest_cpuid_has_xsave(struct kvm_vcpu *vcpu) { struct kvm_cpuid_entry2 *best; + if (!static_cpu_has(X86_FEATURE_XSAVE)) + return 0; + best = kvm_find_cpuid_entry(vcpu, 1, 0); return best && (best->ecx & bit(X86_FEATURE_XSAVE)); } diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 185a2b823a2..e28fb97a1a8 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -5697,6 +5697,9 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, int pending_vec, max_bits, idx; struct desc_ptr dt; + if (!guest_cpuid_has_xsave(vcpu) && (sregs->cr4 & X86_CR4_OSXSAVE)) + return -EINVAL; + dt.size = sregs->idt.limit; dt.address = sregs->idt.base; kvm_x86_ops->set_idt(vcpu, &dt); diff --git a/arch/x86/mm/hugetlbpage.c b/arch/x86/mm/hugetlbpage.c index f6679a7fb8c..b91e4851242 100644 --- a/arch/x86/mm/hugetlbpage.c +++ b/arch/x86/mm/hugetlbpage.c @@ -56,9 +56,16 @@ static int vma_shareable(struct vm_area_struct *vma, unsigned long addr) } /* - * search for a shareable pmd page for hugetlb. + * Search for a shareable pmd page for hugetlb. In any case calls pmd_alloc() + * and returns the corresponding pte. While this is not necessary for the + * !shared pmd case because we can allocate the pmd later as well, it makes the + * code much cleaner. pmd allocation is essential for the shared case because + * pud has to be populated inside the same i_mmap_mutex section - otherwise + * racing tasks could either miss the sharing (see huge_pte_offset) or select a + * bad pmd for sharing. */ -static void huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud) +static pte_t * +huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud) { struct vm_area_struct *vma = find_vma(mm, addr); struct address_space *mapping = vma->vm_file->f_mapping; @@ -68,9 +75,10 @@ static void huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud) struct vm_area_struct *svma; unsigned long saddr; pte_t *spte = NULL; + pte_t *pte; if (!vma_shareable(vma, addr)) - return; + return (pte_t *)pmd_alloc(mm, pud, addr); mutex_lock(&mapping->i_mmap_mutex); vma_prio_tree_foreach(svma, &iter, &mapping->i_mmap, idx, idx) { @@ -97,7 +105,9 @@ static void huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud) put_page(virt_to_page(spte)); spin_unlock(&mm->page_table_lock); out: + pte = (pte_t *)pmd_alloc(mm, pud, addr); mutex_unlock(&mapping->i_mmap_mutex); + return pte; } /* @@ -142,8 +152,9 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, } else { BUG_ON(sz != PMD_SIZE); if (pud_none(*pud)) - huge_pmd_share(mm, addr, pud); - pte = (pte_t *) pmd_alloc(mm, pud, addr); + pte = huge_pmd_share(mm, addr, pud); + else + pte = (pte_t *)pmd_alloc(mm, pud, addr); } } BUG_ON(pte && !pte_none(*pte) && !pte_huge(*pte)); diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c index 4f0cec7e4ff..fae70904ed0 100644 --- a/arch/x86/mm/init.c +++ b/arch/x86/mm/init.c @@ -29,36 +29,50 @@ int direct_gbpages #endif ; -static void __init find_early_table_space(unsigned long end, int use_pse, - int use_gbpages) +struct map_range { + unsigned long start; + unsigned long end; + unsigned page_size_mask; +}; + +/* + * First calculate space needed for kernel direct mapping page tables to cover + * mr[0].start to mr[nr_range - 1].end, while accounting for possible 2M and 1GB + * pages. Then find enough contiguous space for those page tables. + */ +static void __init find_early_table_space(struct map_range *mr, int nr_range) { - unsigned long puds, pmds, ptes, tables, start = 0, good_end = end; + int i; + unsigned long puds = 0, pmds = 0, ptes = 0, tables; + unsigned long start = 0, good_end; phys_addr_t base; - puds = (end + PUD_SIZE - 1) >> PUD_SHIFT; - tables = roundup(puds * sizeof(pud_t), PAGE_SIZE); + for (i = 0; i < nr_range; i++) { + unsigned long range, extra; - if (use_gbpages) { - unsigned long extra; + range = mr[i].end - mr[i].start; + puds += (range + PUD_SIZE - 1) >> PUD_SHIFT; - extra = end - ((end>>PUD_SHIFT) << PUD_SHIFT); - pmds = (extra + PMD_SIZE - 1) >> PMD_SHIFT; - } else - pmds = (end + PMD_SIZE - 1) >> PMD_SHIFT; - - tables += roundup(pmds * sizeof(pmd_t), PAGE_SIZE); + if (mr[i].page_size_mask & (1 << PG_LEVEL_1G)) { + extra = range - ((range >> PUD_SHIFT) << PUD_SHIFT); + pmds += (extra + PMD_SIZE - 1) >> PMD_SHIFT; + } else { + pmds += (range + PMD_SIZE - 1) >> PMD_SHIFT; + } - if (use_pse) { - unsigned long extra; - - extra = end - ((end>>PMD_SHIFT) << PMD_SHIFT); + if (mr[i].page_size_mask & (1 << PG_LEVEL_2M)) { + extra = range - ((range >> PMD_SHIFT) << PMD_SHIFT); #ifdef CONFIG_X86_32 - extra += PMD_SIZE; + extra += PMD_SIZE; #endif - ptes = (extra + PAGE_SIZE - 1) >> PAGE_SHIFT; - } else - ptes = (end + PAGE_SIZE - 1) >> PAGE_SHIFT; + ptes += (extra + PAGE_SIZE - 1) >> PAGE_SHIFT; + } else { + ptes += (range + PAGE_SIZE - 1) >> PAGE_SHIFT; + } + } + tables = roundup(puds * sizeof(pud_t), PAGE_SIZE); + tables += roundup(pmds * sizeof(pmd_t), PAGE_SIZE); tables += roundup(ptes * sizeof(pte_t), PAGE_SIZE); #ifdef CONFIG_X86_32 @@ -75,8 +89,9 @@ static void __init find_early_table_space(unsigned long end, int use_pse, pgt_buf_end = pgt_buf_start; pgt_buf_top = pgt_buf_start + (tables >> PAGE_SHIFT); - printk(KERN_DEBUG "kernel direct mapping tables up to %lx @ %lx-%lx\n", - end, pgt_buf_start << PAGE_SHIFT, pgt_buf_top << PAGE_SHIFT); + printk(KERN_DEBUG "kernel direct mapping tables up to %#lx @ [mem %#010lx-%#010lx]\n", + mr[nr_range - 1].end - 1, pgt_buf_start << PAGE_SHIFT, + (pgt_buf_top << PAGE_SHIFT) - 1); } void __init native_pagetable_reserve(u64 start, u64 end) @@ -84,12 +99,6 @@ void __init native_pagetable_reserve(u64 start, u64 end) memblock_reserve(start, end - start); } -struct map_range { - unsigned long start; - unsigned long end; - unsigned page_size_mask; -}; - #ifdef CONFIG_X86_32 #define NR_RANGE_MR 3 #else /* CONFIG_X86_64 */ @@ -261,7 +270,7 @@ unsigned long __init_refok init_memory_mapping(unsigned long start, * nodes are discovered. */ if (!after_bootmem) - find_early_table_space(end, use_pse, use_gbpages); + find_early_table_space(mr, nr_range); for (i = 0; i < nr_range; i++) ret = kernel_physical_mapping_init(mr[i].start, mr[i].end, diff --git a/arch/x86/oprofile/nmi_int.c b/arch/x86/oprofile/nmi_int.c index 26b8a8514ee..48768df2471 100644 --- a/arch/x86/oprofile/nmi_int.c +++ b/arch/x86/oprofile/nmi_int.c @@ -55,7 +55,7 @@ u64 op_x86_get_ctrl(struct op_x86_model_spec const *model, val |= counter_config->extra; event &= model->event_mask ? model->event_mask : 0xFF; val |= event & 0xFF; - val |= (event & 0x0F00) << 24; + val |= (u64)(event & 0x0F00) << 24; return val; } diff --git a/arch/x86/pci/fixup.c b/arch/x86/pci/fixup.c index d0e6e403b4f..5dd467bd612 100644 --- a/arch/x86/pci/fixup.c +++ b/arch/x86/pci/fixup.c @@ -519,3 +519,20 @@ static void sb600_disable_hpet_bar(struct pci_dev *dev) } } DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_ATI, 0x4385, sb600_disable_hpet_bar); + +/* + * Twinhead H12Y needs us to block out a region otherwise we map devices + * there and any access kills the box. + * + * See: https://bugzilla.kernel.org/show_bug.cgi?id=10231 + * + * Match off the LPC and svid/sdid (older kernels lose the bridge subvendor) + */ +static void __devinit twinhead_reserve_killing_zone(struct pci_dev *dev) +{ + if (dev->subsystem_vendor == 0x14FF && dev->subsystem_device == 0xA003) { + pr_info("Reserving memory on Twinhead H12Y\n"); + request_mem_region(0xFFB00000, 0x100000, "twinhead"); + } +} +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x27B9, twinhead_reserve_killing_zone); diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 92660edaa1e..6825327d00a 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -69,11 +69,15 @@ EXPORT_SYMBOL(efi); struct efi_memory_map memmap; bool efi_64bit; -static bool efi_native; static struct efi efi_phys __initdata; static efi_system_table_t efi_systab __initdata; +static inline bool efi_is_native(void) +{ + return IS_ENABLED(CONFIG_X86_64) == efi_64bit; +} + static int __init setup_noefi(char *arg) { efi_enabled = 0; @@ -419,10 +423,21 @@ void __init efi_reserve_boot_services(void) } } -static void __init efi_free_boot_services(void) +void __init efi_unmap_memmap(void) +{ + if (memmap.map) { + early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size); + memmap.map = NULL; + } +} + +void __init efi_free_boot_services(void) { void *p; + if (!efi_is_native()) + return; + for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { efi_memory_desc_t *md = p; unsigned long long start = md->phys_addr; @@ -438,6 +453,8 @@ static void __init efi_free_boot_services(void) free_bootmem_late(start, size); } + + efi_unmap_memmap(); } static int __init efi_systab_init(void *phys) @@ -670,12 +687,10 @@ void __init efi_init(void) return; } efi_phys.systab = (efi_system_table_t *)boot_params.efi_info.efi_systab; - efi_native = !efi_64bit; #else efi_phys.systab = (efi_system_table_t *) (boot_params.efi_info.efi_systab | ((__u64)boot_params.efi_info.efi_systab_hi<<32)); - efi_native = efi_64bit; #endif if (efi_systab_init(efi_phys.systab)) { @@ -709,7 +724,7 @@ void __init efi_init(void) * that doesn't match the kernel 32/64-bit mode. */ - if (!efi_native) + if (!efi_is_native()) pr_info("No EFI runtime due to 32/64-bit mismatch with kernel\n"); else if (efi_runtime_init()) { efi_enabled = 0; @@ -721,7 +736,7 @@ void __init efi_init(void) return; } #ifdef CONFIG_X86_32 - if (efi_native) { + if (efi_is_native()) { x86_platform.get_wallclock = efi_get_time; x86_platform.set_wallclock = efi_set_rtc_mmss; } @@ -787,8 +802,10 @@ void __init efi_enter_virtual_mode(void) * non-native EFI */ - if (!efi_native) - goto out; + if (!efi_is_native()) { + efi_unmap_memmap(); + return; + } /* Merge contiguous regions of the same type and attribute */ for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { @@ -877,19 +894,13 @@ void __init efi_enter_virtual_mode(void) panic("EFI call to SetVirtualAddressMap() failed!"); } - /* - * Thankfully, it does seem that no runtime services other than - * SetVirtualAddressMap() will touch boot services code, so we can - * get rid of it all at this point - */ - efi_free_boot_services(); - /* * Now that EFI is in virtual mode, update the function * pointers in the runtime service table to the new virtual addresses. * * Call EFI services through wrapper functions. */ + efi.runtime_version = efi_systab.hdr.revision; efi.get_time = virt_efi_get_time; efi.set_time = virt_efi_set_time; efi.get_wakeup_time = virt_efi_get_wakeup_time; @@ -906,9 +917,6 @@ void __init efi_enter_virtual_mode(void) if (__supported_pte_mask & _PAGE_NX) runtime_code_page_mkexec(); -out: - early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size); - memmap.map = NULL; kfree(new_memmap); } diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c index ac3aa54e265..0fba86da589 100644 --- a/arch/x86/platform/efi/efi_64.c +++ b/arch/x86/platform/efi/efi_64.c @@ -38,7 +38,7 @@ #include #include -static pgd_t save_pgd __initdata; +static pgd_t *save_pgd __initdata; static unsigned long efi_flags __initdata; static void __init early_code_mapping_set_exec(int executable) @@ -61,12 +61,20 @@ static void __init early_code_mapping_set_exec(int executable) void __init efi_call_phys_prelog(void) { unsigned long vaddress; + int pgd; + int n_pgds; early_code_mapping_set_exec(1); local_irq_save(efi_flags); - vaddress = (unsigned long)__va(0x0UL); - save_pgd = *pgd_offset_k(0x0UL); - set_pgd(pgd_offset_k(0x0UL), *pgd_offset_k(vaddress)); + + n_pgds = DIV_ROUND_UP((max_pfn << PAGE_SHIFT), PGDIR_SIZE); + save_pgd = kmalloc(n_pgds * sizeof(pgd_t), GFP_KERNEL); + + for (pgd = 0; pgd < n_pgds; pgd++) { + save_pgd[pgd] = *pgd_offset_k(pgd * PGDIR_SIZE); + vaddress = (unsigned long)__va(pgd * PGDIR_SIZE); + set_pgd(pgd_offset_k(pgd * PGDIR_SIZE), *pgd_offset_k(vaddress)); + } __flush_tlb_all(); } @@ -75,7 +83,11 @@ void __init efi_call_phys_epilog(void) /* * After the lock is released, the original page table is restored. */ - set_pgd(pgd_offset_k(0x0UL), save_pgd); + int pgd; + int n_pgds = DIV_ROUND_UP((max_pfn << PAGE_SHIFT) , PGDIR_SIZE); + for (pgd = 0; pgd < n_pgds; pgd++) + set_pgd(pgd_offset_k(pgd * PGDIR_SIZE), save_pgd[pgd]); + kfree(save_pgd); __flush_tlb_all(); local_irq_restore(efi_flags); early_code_mapping_set_exec(0); diff --git a/arch/x86/syscalls/syscall_64.tbl b/arch/x86/syscalls/syscall_64.tbl index dd29a9ea27c..fd1f1034813 100644 --- a/arch/x86/syscalls/syscall_64.tbl +++ b/arch/x86/syscalls/syscall_64.tbl @@ -60,8 +60,8 @@ 51 common getsockname sys_getsockname 52 common getpeername sys_getpeername 53 common socketpair sys_socketpair -54 common setsockopt sys_setsockopt -55 common getsockopt sys_getsockopt +54 64 setsockopt sys_setsockopt +55 64 getsockopt sys_getsockopt 56 common clone stub_clone 57 common fork stub_fork 58 common vfork stub_vfork @@ -351,3 +351,5 @@ 538 x32 sendmmsg compat_sys_sendmmsg 539 x32 process_vm_readv compat_sys_process_vm_readv 540 x32 process_vm_writev compat_sys_process_vm_writev +541 x32 setsockopt compat_sys_setsockopt +542 x32 getsockopt compat_sys_getsockopt diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 495fc63f5a1..660c036ef4e 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -942,7 +942,16 @@ static void xen_write_cr4(unsigned long cr4) native_write_cr4(cr4); } - +#ifdef CONFIG_X86_64 +static inline unsigned long xen_read_cr8(void) +{ + return 0; +} +static inline void xen_write_cr8(unsigned long val) +{ + BUG_ON(val); +} +#endif static int xen_write_msr_safe(unsigned int msr, unsigned low, unsigned high) { int ret; @@ -1111,6 +1120,11 @@ static const struct pv_cpu_ops xen_cpu_ops __initconst = { .read_cr4_safe = native_read_cr4_safe, .write_cr4 = xen_write_cr4, +#ifdef CONFIG_X86_64 + .read_cr8 = xen_read_cr8, + .write_cr8 = xen_write_cr8, +#endif + .wbinvd = native_wbinvd, .read_msr = native_read_msr_safe, @@ -1121,6 +1135,8 @@ static const struct pv_cpu_ops xen_cpu_ops __initconst = { .read_tsc = native_read_tsc, .read_pmc = native_read_pmc, + .read_tscp = native_read_tscp, + .iret = xen_iret, .irq_enable_sysexit = xen_sysexit, #ifdef CONFIG_X86_64 diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 69f5857660a..5cb8e27d43d 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c @@ -1203,6 +1203,25 @@ unsigned long xen_read_cr2_direct(void) return this_cpu_read(xen_vcpu_info.arch.cr2); } +void xen_flush_tlb_all(void) +{ + struct mmuext_op *op; + struct multicall_space mcs; + + trace_xen_mmu_flush_tlb_all(0); + + preempt_disable(); + + mcs = xen_mc_entry(sizeof(*op)); + + op = mcs.args; + op->cmd = MMUEXT_TLB_FLUSH_ALL; + MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF); + + xen_mc_issue(PARAVIRT_LAZY_MMU); + + preempt_enable(); +} static void xen_flush_tlb(void) { struct mmuext_op *op; @@ -2364,7 +2383,7 @@ int xen_remap_domain_mfn_range(struct vm_area_struct *vma, err = 0; out: - flush_tlb_all(); + xen_flush_tlb_all(); return err; } diff --git a/arch/x86/xen/p2m.c b/arch/x86/xen/p2m.c index 1b267e75158..3ace8176947 100644 --- a/arch/x86/xen/p2m.c +++ b/arch/x86/xen/p2m.c @@ -686,6 +686,7 @@ int m2p_add_override(unsigned long mfn, struct page *page, unsigned long uninitialized_var(address); unsigned level; pte_t *ptep = NULL; + int ret = 0; pfn = page_to_pfn(page); if (!PageHighMem(page)) { @@ -713,18 +714,34 @@ int m2p_add_override(unsigned long mfn, struct page *page, xen_mc_issue(PARAVIRT_LAZY_MMU); } - /* let's use dev_bus_addr to record the old mfn instead */ - kmap_op->dev_bus_addr = page->index; - page->index = (unsigned long) kmap_op; } spin_lock_irqsave(&m2p_override_lock, flags); list_add(&page->lru, &m2p_overrides[mfn_hash(mfn)]); spin_unlock_irqrestore(&m2p_override_lock, flags); + /* p2m(m2p(mfn)) == mfn: the mfn is already present somewhere in + * this domain. Set the FOREIGN_FRAME_BIT in the p2m for the other + * pfn so that the following mfn_to_pfn(mfn) calls will return the + * pfn from the m2p_override (the backend pfn) instead. + * We need to do this because the pages shared by the frontend + * (xen-blkfront) can be already locked (lock_page, called by + * do_read_cache_page); when the userspace backend tries to use them + * with direct_IO, mfn_to_pfn returns the pfn of the frontend, so + * do_blockdev_direct_IO is going to try to lock the same pages + * again resulting in a deadlock. + * As a side effect get_user_pages_fast might not be safe on the + * frontend pages while they are being shared with the backend, + * because mfn_to_pfn (that ends up being called by GUPF) will + * return the backend pfn rather than the frontend pfn. */ + ret = __get_user(pfn, &machine_to_phys_mapping[mfn]); + if (ret == 0 && get_phys_to_machine(pfn) == mfn) + set_phys_to_machine(pfn, FOREIGN_FRAME(mfn)); + return 0; } EXPORT_SYMBOL_GPL(m2p_add_override); -int m2p_remove_override(struct page *page, bool clear_pte) +int m2p_remove_override(struct page *page, + struct gnttab_map_grant_ref *kmap_op) { unsigned long flags; unsigned long mfn; @@ -732,6 +749,7 @@ int m2p_remove_override(struct page *page, bool clear_pte) unsigned long uninitialized_var(address); unsigned level; pte_t *ptep = NULL; + int ret = 0; pfn = page_to_pfn(page); mfn = get_phys_to_machine(pfn); @@ -753,10 +771,8 @@ int m2p_remove_override(struct page *page, bool clear_pte) WARN_ON(!PagePrivate(page)); ClearPagePrivate(page); - if (clear_pte) { - struct gnttab_map_grant_ref *map_op = - (struct gnttab_map_grant_ref *) page->index; - set_phys_to_machine(pfn, map_op->dev_bus_addr); + set_phys_to_machine(pfn, page->index); + if (kmap_op != NULL) { if (!PageHighMem(page)) { struct multicall_space mcs; struct gnttab_unmap_grant_ref *unmap_op; @@ -768,13 +784,13 @@ int m2p_remove_override(struct page *page, bool clear_pte) * issued. In this case handle is going to -1 because * it hasn't been modified yet. */ - if (map_op->handle == -1) + if (kmap_op->handle == -1) xen_mc_flush(); /* - * Now if map_op->handle is negative it means that the + * Now if kmap_op->handle is negative it means that the * hypercall actually returned an error. */ - if (map_op->handle == GNTST_general_error) { + if (kmap_op->handle == GNTST_general_error) { printk(KERN_WARNING "m2p_remove_override: " "pfn %lx mfn %lx, failed to modify kernel mappings", pfn, mfn); @@ -784,8 +800,8 @@ int m2p_remove_override(struct page *page, bool clear_pte) mcs = xen_mc_entry( sizeof(struct gnttab_unmap_grant_ref)); unmap_op = mcs.args; - unmap_op->host_addr = map_op->host_addr; - unmap_op->handle = map_op->handle; + unmap_op->host_addr = kmap_op->host_addr; + unmap_op->handle = kmap_op->handle; unmap_op->dev_bus_addr = 0; MULTI_grant_table_op(mcs.mc, @@ -796,10 +812,25 @@ int m2p_remove_override(struct page *page, bool clear_pte) set_pte_at(&init_mm, address, ptep, pfn_pte(pfn, PAGE_KERNEL)); __flush_tlb_single(address); - map_op->host_addr = 0; + kmap_op->host_addr = 0; } - } else - set_phys_to_machine(pfn, page->index); + } + + /* p2m(m2p(mfn)) == FOREIGN_FRAME(mfn): the mfn is already present + * somewhere in this domain, even before being added to the + * m2p_override (see comment above in m2p_add_override). + * If there are no other entries in the m2p_override corresponding + * to this mfn, then remove the FOREIGN_FRAME_BIT from the p2m for + * the original pfn (the one shared by the frontend): the backend + * cannot do any IO on this page anymore because it has been + * unshared. Removing the FOREIGN_FRAME_BIT from the p2m entry of + * the original pfn causes mfn_to_pfn(mfn) to return the frontend + * pfn again. */ + mfn &= ~FOREIGN_FRAME_BIT; + ret = __get_user(pfn, &machine_to_phys_mapping[mfn]); + if (ret == 0 && get_phys_to_machine(pfn) == FOREIGN_FRAME(mfn) && + m2p_find_override(mfn) == NULL) + set_phys_to_machine(pfn, mfn); return 0; } diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c index ad1cd644894..7dfd1a586f5 100644 --- a/arch/x86/xen/setup.c +++ b/arch/x86/xen/setup.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -79,9 +80,16 @@ static void __init xen_add_extra_mem(u64 start, u64 size) memblock_reserve(start, size); xen_max_p2m_pfn = PFN_DOWN(start + size); + for (pfn = PFN_DOWN(start); pfn < xen_max_p2m_pfn; pfn++) { + unsigned long mfn = pfn_to_mfn(pfn); + + if (WARN(mfn == pfn, "Trying to over-write 1-1 mapping (pfn: %lx)\n", pfn)) + continue; + WARN(mfn != INVALID_P2M_ENTRY, "Trying to remove %lx which has %lx mfn!\n", + pfn, mfn); - for (pfn = PFN_DOWN(start); pfn <= xen_max_p2m_pfn; pfn++) __set_phys_to_machine(pfn, INVALID_P2M_ENTRY); + } } static unsigned long __init xen_release_chunk(unsigned long start, @@ -424,4 +432,7 @@ void __init xen_arch_setup(void) disable_cpufreq(); WARN_ON(set_pm_idle_to_default()); fiddle_vdso(); +#ifdef CONFIG_NUMA + numa_off = 1; +#endif } diff --git a/arch/xtensa/kernel/process.c b/arch/xtensa/kernel/process.c index 6a2d6edf8f7..7a41d9ec8ac 100644 --- a/arch/xtensa/kernel/process.c +++ b/arch/xtensa/kernel/process.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -110,8 +111,10 @@ void cpu_idle(void) /* endless idle loop with no priority at all */ while (1) { + rcu_idle_enter(); while (!need_resched()) platform_idle(); + rcu_idle_exit(); schedule_preempt_disabled(); } } diff --git a/block/blk-core.c b/block/blk-core.c index 69764dfbd80..b57ea48cb45 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -615,7 +615,7 @@ blk_init_allocated_queue(struct request_queue *q, request_fn_proc *rfn, q->request_fn = rfn; q->prep_rq_fn = NULL; q->unprep_rq_fn = NULL; - q->queue_flags = QUEUE_FLAG_DEFAULT; + q->queue_flags |= QUEUE_FLAG_DEFAULT; /* Override internal queue lock with supplied lock pointer */ if (lock) diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c index 260fa80ef57..9a87daa6f4f 100644 --- a/block/scsi_ioctl.c +++ b/block/scsi_ioctl.c @@ -721,11 +721,14 @@ int scsi_verify_blk_ioctl(struct block_device *bd, unsigned int cmd) break; } + if (capable(CAP_SYS_RAWIO)) + return 0; + /* In particular, rule out all resets and host-specific ioctls. */ printk_ratelimited(KERN_WARNING "%s: sending ioctl %x to a partition!\n", current->comm, cmd); - return capable(CAP_SYS_RAWIO) ? 0 : -ENOIOCTLCMD; + return -ENOIOCTLCMD; } EXPORT_SYMBOL(scsi_verify_blk_ioctl); diff --git a/crypto/cryptd.c b/crypto/cryptd.c index 671d4d6d14d..7bdd61b867c 100644 --- a/crypto/cryptd.c +++ b/crypto/cryptd.c @@ -137,13 +137,18 @@ static void cryptd_queue_worker(struct work_struct *work) struct crypto_async_request *req, *backlog; cpu_queue = container_of(work, struct cryptd_cpu_queue, work); - /* Only handle one request at a time to avoid hogging crypto - * workqueue. preempt_disable/enable is used to prevent - * being preempted by cryptd_enqueue_request() */ + /* + * Only handle one request at a time to avoid hogging crypto workqueue. + * preempt_disable/enable is used to prevent being preempted by + * cryptd_enqueue_request(). local_bh_disable/enable is used to prevent + * cryptd_enqueue_request() being accessed from software interrupts. + */ + local_bh_disable(); preempt_disable(); backlog = crypto_get_backlog(&cpu_queue->queue); req = crypto_dequeue_request(&cpu_queue->queue); preempt_enable(); + local_bh_enable(); if (!req) return; diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c index 6512b20aecc..d1fcbc0f6cb 100644 --- a/drivers/acpi/ac.c +++ b/drivers/acpi/ac.c @@ -292,7 +292,9 @@ static int acpi_ac_add(struct acpi_device *device) ac->charger.properties = ac_props; ac->charger.num_properties = ARRAY_SIZE(ac_props); ac->charger.get_property = get_ac_property; - power_supply_register(&ac->device->dev, &ac->charger); + result = power_supply_register(&ac->device->dev, &ac->charger); + if (result) + goto end; printk(KERN_INFO PREFIX "%s [%s] (%s)\n", acpi_device_name(device), acpi_device_bid(device), diff --git a/drivers/acpi/acpica/nspredef.c b/drivers/acpi/acpica/nspredef.c index 23ce0968641..fe662603549 100644 --- a/drivers/acpi/acpica/nspredef.c +++ b/drivers/acpi/acpica/nspredef.c @@ -638,7 +638,7 @@ acpi_ns_check_package(struct acpi_predefined_data *data, /* Create the new outer package and populate it */ status = - acpi_ns_wrap_with_package(data, *elements, + acpi_ns_wrap_with_package(data, return_object, return_object_ptr); if (ACPI_FAILURE(status)) { return (status); diff --git a/drivers/acpi/acpica/tbxface.c b/drivers/acpi/acpica/tbxface.c index abcc6412c24..33214d77888 100644 --- a/drivers/acpi/acpica/tbxface.c +++ b/drivers/acpi/acpica/tbxface.c @@ -436,6 +436,7 @@ acpi_get_table_with_size(char *signature, return (AE_NOT_FOUND); } +ACPI_EXPORT_SYMBOL(acpi_get_table_with_size) acpi_status acpi_get_table(char *signature, diff --git a/drivers/acpi/apei/apei-base.c b/drivers/acpi/apei/apei-base.c index 6686b1eaf13..00a783661d0 100644 --- a/drivers/acpi/apei/apei-base.c +++ b/drivers/acpi/apei/apei-base.c @@ -586,6 +586,11 @@ static int apei_check_gar(struct acpi_generic_address *reg, u64 *paddr, } *access_bit_width = 1UL << (access_size_code + 2); + /* Fixup common BIOS bug */ + if (bit_width == 32 && bit_offset == 0 && (*paddr & 0x03) == 0 && + *access_bit_width < 32) + *access_bit_width = 32; + if ((bit_width + bit_offset) > *access_bit_width) { pr_warning(FW_BUG APEI_PFX "Invalid bit width + offset in GAR [0x%llx/%u/%u/%u/%u]\n", diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 7dd3f9fb9f3..6ea287e2229 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -34,6 +34,7 @@ #include #include #include +#include #ifdef CONFIG_ACPI_PROCFS_POWER #include @@ -95,6 +96,18 @@ enum { ACPI_BATTERY_ALARM_PRESENT, ACPI_BATTERY_XINFO_PRESENT, ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, + /* On Lenovo Thinkpad models from 2010 and 2011, the power unit + switches between mWh and mAh depending on whether the system + is running on battery or not. When mAh is the unit, most + reported values are incorrect and need to be adjusted by + 10000/design_voltage. Verified on x201, t410, t410s, and x220. + Pre-2010 and 2012 models appear to always report in mWh and + are thus unaffected (tested with t42, t61, t500, x200, x300, + and x230). Also, in mid-2012 Lenovo issued a BIOS update for + the 2011 models that fixes the issue (tested on x220 with a + post-1.29 BIOS), but as of Nov. 2012, no such update is + available for the 2010 models. */ + ACPI_BATTERY_QUIRK_THINKPAD_MAH, }; struct acpi_battery { @@ -429,6 +442,21 @@ static int acpi_battery_get_info(struct acpi_battery *battery) kfree(buffer.pointer); if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags)) battery->full_charge_capacity = battery->design_capacity; + if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags) && + battery->power_unit && battery->design_voltage) { + battery->design_capacity = battery->design_capacity * + 10000 / battery->design_voltage; + battery->full_charge_capacity = battery->full_charge_capacity * + 10000 / battery->design_voltage; + battery->design_capacity_warning = + battery->design_capacity_warning * + 10000 / battery->design_voltage; + /* Curiously, design_capacity_low, unlike the rest of them, + is correct. */ + /* capacity_granularity_* equal 1 on the systems tested, so + it's impossible to tell if they would need an adjustment + or not if their values were higher. */ + } return result; } @@ -477,6 +505,11 @@ static int acpi_battery_get_state(struct acpi_battery *battery) && battery->capacity_now >= 0 && battery->capacity_now <= 100) battery->capacity_now = (battery->capacity_now * battery->full_charge_capacity) / 100; + if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags) && + battery->power_unit && battery->design_voltage) { + battery->capacity_now = battery->capacity_now * + 10000 / battery->design_voltage; + } return result; } @@ -586,6 +619,24 @@ static void sysfs_remove_battery(struct acpi_battery *battery) mutex_unlock(&battery->sysfs_lock); } +static void find_battery(const struct dmi_header *dm, void *private) +{ + struct acpi_battery *battery = (struct acpi_battery *)private; + /* Note: the hardcoded offsets below have been extracted from + the source code of dmidecode. */ + if (dm->type == DMI_ENTRY_PORTABLE_BATTERY && dm->length >= 8) { + const u8 *dmi_data = (const u8 *)(dm + 1); + int dmi_capacity = get_unaligned((const u16 *)(dmi_data + 6)); + if (dm->length >= 18) + dmi_capacity *= dmi_data[17]; + if (battery->design_capacity * battery->design_voltage / 1000 + != dmi_capacity && + battery->design_capacity * 10 == dmi_capacity) + set_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, + &battery->flags); + } +} + /* * According to the ACPI spec, some kinds of primary batteries can * report percentage battery remaining capacity directly to OS. @@ -611,6 +662,32 @@ static void acpi_battery_quirks(struct acpi_battery *battery) battery->capacity_now = (battery->capacity_now * battery->full_charge_capacity) / 100; } + + if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, &battery->flags)) + return ; + + if (battery->power_unit && dmi_name_in_vendors("LENOVO")) { + const char *s; + s = dmi_get_system_info(DMI_PRODUCT_VERSION); + if (s && !strnicmp(s, "ThinkPad", 8)) { + dmi_walk(find_battery, battery); + if (test_bit(ACPI_BATTERY_QUIRK_THINKPAD_MAH, + &battery->flags) && + battery->design_voltage) { + battery->design_capacity = + battery->design_capacity * + 10000 / battery->design_voltage; + battery->full_charge_capacity = + battery->full_charge_capacity * + 10000 / battery->design_voltage; + battery->design_capacity_warning = + battery->design_capacity_warning * + 10000 / battery->design_voltage; + battery->capacity_now = battery->capacity_now * + 10000 / battery->design_voltage; + } + } + } } static int acpi_battery_update(struct acpi_battery *battery) diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 3188da3df8d..cf02e971467 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -954,14 +954,18 @@ static int __init acpi_bus_init(void) status = acpi_ec_ecdt_probe(); /* Ignore result. Not having an ECDT is not fatal. */ - acpi_bus_osc_support(); - status = acpi_initialize_objects(ACPI_FULL_INITIALIZATION); if (ACPI_FAILURE(status)) { printk(KERN_ERR PREFIX "Unable to initialize ACPI objects\n"); goto error1; } + /* + * _OSC method may exist in module level code, + * so it must be run after ACPI_FULL_INITIALIZATION + */ + acpi_bus_osc_support(); + /* * _PDC control method may load dynamic SSDT tables, * and we need to install the table handler before that. diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 7edaccce664..a51df968131 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -71,9 +71,6 @@ enum ec_command { #define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */ #define ACPI_EC_MSI_UDELAY 550 /* Wait 550us for MSI EC */ -#define ACPI_EC_STORM_THRESHOLD 8 /* number of false interrupts - per one transaction */ - enum { EC_FLAGS_QUERY_PENDING, /* Query is pending */ EC_FLAGS_GPE_STORM, /* GPE storm detected */ @@ -87,6 +84,15 @@ static unsigned int ec_delay __read_mostly = ACPI_EC_DELAY; module_param(ec_delay, uint, 0644); MODULE_PARM_DESC(ec_delay, "Timeout(ms) waited until an EC command completes"); +/* + * If the number of false interrupts per one transaction exceeds + * this threshold, will think there is a GPE storm happened and + * will disable the GPE for normal transaction. + */ +static unsigned int ec_storm_threshold __read_mostly = 8; +module_param(ec_storm_threshold, uint, 0644); +MODULE_PARM_DESC(ec_storm_threshold, "Maxim false GPE numbers not considered as GPE storm"); + /* If we find an EC via the ECDT, we need to keep a ptr to its context */ /* External interfaces use first EC only, so remember */ typedef int (*acpi_ec_query_func) (void *data); @@ -319,7 +325,7 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t) msleep(1); /* It is safe to enable the GPE outside of the transaction. */ acpi_enable_gpe(NULL, ec->gpe); - } else if (t->irq_count > ACPI_EC_STORM_THRESHOLD) { + } else if (t->irq_count > ec_storm_threshold) { pr_info(PREFIX "GPE storm detected, " "transactions will use polling mode\n"); set_bit(EC_FLAGS_GPE_STORM, &ec->flags); @@ -924,6 +930,17 @@ static int ec_flag_msi(const struct dmi_system_id *id) return 0; } +/* + * Clevo M720 notebook actually works ok with IRQ mode, if we lifted + * the GPE storm threshold back to 20 + */ +static int ec_enlarge_storm_threshold(const struct dmi_system_id *id) +{ + pr_debug("Setting the EC GPE storm threshold to 20\n"); + ec_storm_threshold = 20; + return 0; +} + static struct dmi_system_id __initdata ec_dmi_table[] = { { ec_skip_dsdt_scan, "Compal JFL92", { @@ -955,10 +972,13 @@ static struct dmi_system_id __initdata ec_dmi_table[] = { { ec_validate_ecdt, "ASUS hardware", { DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer Inc.") }, NULL}, + { + ec_enlarge_storm_threshold, "CLEVO hardware", { + DMI_MATCH(DMI_SYS_VENDOR, "CLEVO Co."), + DMI_MATCH(DMI_PRODUCT_NAME, "M720T/M730T"),}, NULL}, {}, }; - int __init acpi_ec_ecdt_probe(void) { acpi_status status; diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 0500f719f63..2adef535f15 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -103,6 +103,7 @@ struct acpi_power_resource { /* List of devices relying on this power resource */ struct acpi_power_resource_device *devices; + struct mutex devices_lock; }; static struct list_head acpi_power_resource_list; @@ -221,7 +222,6 @@ static void acpi_power_on_device(struct acpi_power_managed_device *device) static int __acpi_power_on(struct acpi_power_resource *resource) { - struct acpi_power_resource_device *device_list = resource->devices; acpi_status status = AE_OK; status = acpi_evaluate_object(resource->device->handle, "_ON", NULL, NULL); @@ -234,19 +234,15 @@ static int __acpi_power_on(struct acpi_power_resource *resource) ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Power resource [%s] turned on\n", resource->name)); - while (device_list) { - acpi_power_on_device(device_list->device); - - device_list = device_list->next; - } - return 0; } static int acpi_power_on(acpi_handle handle) { int result = 0; + bool resume_device = false; struct acpi_power_resource *resource = NULL; + struct acpi_power_resource_device *device_list; result = acpi_power_get_context(handle, &resource); if (result) @@ -262,10 +258,25 @@ static int acpi_power_on(acpi_handle handle) result = __acpi_power_on(resource); if (result) resource->ref_count--; + else + resume_device = true; } mutex_unlock(&resource->resource_lock); + if (!resume_device) + return result; + + mutex_lock(&resource->devices_lock); + + device_list = resource->devices; + while (device_list) { + acpi_power_on_device(device_list->device); + device_list = device_list->next; + } + + mutex_unlock(&resource->devices_lock); + return result; } @@ -351,7 +362,7 @@ static void __acpi_power_resource_unregister_device(struct device *dev, if (acpi_power_get_context(res_handle, &resource)) return; - mutex_lock(&resource->resource_lock); + mutex_lock(&resource->devices_lock); prev = NULL; curr = resource->devices; while (curr) { @@ -368,7 +379,7 @@ static void __acpi_power_resource_unregister_device(struct device *dev, prev = curr; curr = curr->next; } - mutex_unlock(&resource->resource_lock); + mutex_unlock(&resource->devices_lock); } /* Unlink dev from all power resources in _PR0 */ @@ -409,10 +420,10 @@ static int __acpi_power_resource_register_device( power_resource_device->device = powered_device; - mutex_lock(&resource->resource_lock); + mutex_lock(&resource->devices_lock); power_resource_device->next = resource->devices; resource->devices = power_resource_device; - mutex_unlock(&resource->resource_lock); + mutex_unlock(&resource->devices_lock); return 0; } @@ -457,7 +468,7 @@ int acpi_power_resource_register_device(struct device *dev, acpi_handle handle) return ret; no_power_resource: - printk(KERN_WARNING PREFIX "Invalid Power Resource to register!"); + printk(KERN_DEBUG PREFIX "Invalid Power Resource to register!"); return -ENODEV; } @@ -715,6 +726,7 @@ static int acpi_power_add(struct acpi_device *device) resource->device = device; mutex_init(&resource->resource_lock); + mutex_init(&resource->devices_lock); strcpy(resource->name, device->pnp.bus_id); strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_POWER_CLASS); diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index f9f09d1ac66..52e2053cf14 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c @@ -189,10 +189,12 @@ int acpi_get_cpuid(acpi_handle handle, int type, u32 acpi_id) * Processor (CPU3, 0x03, 0x00000410, 0x06) {} * } * - * Ignores apic_id and always return 0 for CPU0's handle. + * Ignores apic_id and always returns 0 for the processor + * handle with acpi id 0 if nr_cpu_ids is 1. + * This should be the case if SMP tables are not found. * Return -1 for other CPU's handle. */ - if (acpi_id == 0) + if (nr_cpu_ids <= 1 && acpi_id == 0) return acpi_id; else return apic_id; diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index ada43215f1c..7ab45b976e7 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c @@ -407,6 +407,7 @@ static void acpi_processor_notify(struct acpi_device *device, u32 event) acpi_bus_generate_proc_event(device, event, 0); acpi_bus_generate_netlink_event(device->pnp.device_class, dev_name(&device->dev), event, 0); + break; default: ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Unsupported event [0x%x]\n", event)); @@ -442,7 +443,7 @@ static int acpi_cpu_soft_notify(struct notifier_block *nfb, /* Normal CPU soft online event */ } else { acpi_processor_ppc_has_changed(pr, 0); - acpi_processor_cst_has_changed(pr); + acpi_processor_hotplug(pr); acpi_processor_reevaluate_tstate(pr, action); acpi_processor_tstate_has_changed(pr); } diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index e7ccfd690e2..95526dee8c2 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -1018,6 +1018,9 @@ static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr) return -EINVAL; } + if (!dev) + return -EINVAL; + dev->cpu = pr->id; if (max_cstate == 0) @@ -1205,6 +1208,7 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr) } /* Populate Updated C-state information */ + acpi_processor_get_power_info(pr); acpi_processor_setup_cpuidle_states(pr); /* Enable all cpuidle devices */ diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 85cbfdccc97..619a2e4402d 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -789,8 +789,8 @@ acpi_bus_extract_wakeup_device_power_package(acpi_handle handle, static void acpi_bus_set_run_wake_flags(struct acpi_device *device) { struct acpi_device_id button_device_ids[] = { - {"PNP0C0D", 0}, {"PNP0C0C", 0}, + {"PNP0C0D", 0}, {"PNP0C0E", 0}, {"", 0}, }; @@ -802,6 +802,11 @@ static void acpi_bus_set_run_wake_flags(struct acpi_device *device) /* Power button, Lid switch always enable wakeup */ if (!acpi_match_device_ids(device, button_device_ids)) { device->wakeup.flags.run_wake = 1; + if (!acpi_match_device_ids(device, &button_device_ids[1])) { + /* Do not use Lid/sleep button for S5 wakeup */ + if (device->wakeup.sleep_state == ACPI_STATE_S5) + device->wakeup.sleep_state = ACPI_STATE_S4; + } device_set_wakeup_capable(&device->dev, true); return; } @@ -1157,7 +1162,7 @@ static void acpi_device_set_id(struct acpi_device *device) acpi_add_id(device, ACPI_DOCK_HID); else if (!acpi_ibm_smbus_match(device)) acpi_add_id(device, ACPI_SMBUS_IBM_HID); - else if (!acpi_device_hid(device) && + else if (list_empty(&device->pnp.ids) && ACPI_IS_ROOT_DEVICE(device->parent)) { acpi_add_id(device, ACPI_BUS_HID); /* \_SB, LNXSYBUS */ strcpy(device->pnp.device_name, ACPI_BUS_DEVICE_NAME); diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 2377445f4a3..aa0a904e563 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -138,6 +138,180 @@ void __init acpi_old_suspend_ordering(void) old_suspend_ordering = true; } +static int __init init_old_suspend_ordering(const struct dmi_system_id *d) +{ + acpi_old_suspend_ordering(); + return 0; +} + +static int __init init_nvs_nosave(const struct dmi_system_id *d) +{ + acpi_nvs_nosave(); + return 0; +} + +static struct dmi_system_id __initdata acpisleep_dmi_table[] = { + { + .callback = init_old_suspend_ordering, + .ident = "Abit KN9 (nForce4 variant)", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "http://www.abit.com.tw/"), + DMI_MATCH(DMI_BOARD_NAME, "KN9 Series(NF-CK804)"), + }, + }, + { + .callback = init_old_suspend_ordering, + .ident = "HP xw4600 Workstation", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP xw4600 Workstation"), + }, + }, + { + .callback = init_old_suspend_ordering, + .ident = "Asus Pundit P1-AH2 (M2N8L motherboard)", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTek Computer INC."), + DMI_MATCH(DMI_BOARD_NAME, "M2N8L"), + }, + }, + { + .callback = init_old_suspend_ordering, + .ident = "Panasonic CF51-2L", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, + "Matsushita Electric Industrial Co.,Ltd."), + DMI_MATCH(DMI_BOARD_NAME, "CF51-2L"), + }, + }, + { + .callback = init_nvs_nosave, + .ident = "Sony Vaio VGN-FW21E", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FW21E"), + }, + }, + { + .callback = init_nvs_nosave, + .ident = "Sony Vaio VPCEB17FX", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "VPCEB17FX"), + }, + }, + { + .callback = init_nvs_nosave, + .ident = "Sony Vaio VGN-SR11M", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR11M"), + }, + }, + { + .callback = init_nvs_nosave, + .ident = "Everex StepNote Series", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Everex Systems, Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Everex StepNote Series"), + }, + }, + { + .callback = init_nvs_nosave, + .ident = "Sony Vaio VPCEB1Z1E", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "VPCEB1Z1E"), + }, + }, + { + .callback = init_nvs_nosave, + .ident = "Sony Vaio VGN-NW130D", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NW130D"), + }, + }, + { + .callback = init_nvs_nosave, + .ident = "Sony Vaio VPCCW29FX", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "VPCCW29FX"), + }, + }, + { + .callback = init_nvs_nosave, + .ident = "Averatec AV1020-ED2", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "AVERATEC"), + DMI_MATCH(DMI_PRODUCT_NAME, "1000 Series"), + }, + }, + { + .callback = init_old_suspend_ordering, + .ident = "Asus A8N-SLI DELUXE", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), + DMI_MATCH(DMI_BOARD_NAME, "A8N-SLI DELUXE"), + }, + }, + { + .callback = init_old_suspend_ordering, + .ident = "Asus A8N-SLI Premium", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), + DMI_MATCH(DMI_BOARD_NAME, "A8N-SLI Premium"), + }, + }, + { + .callback = init_nvs_nosave, + .ident = "Sony Vaio VGN-SR26GN_P", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR26GN_P"), + }, + }, + { + .callback = init_nvs_nosave, + .ident = "Sony Vaio VPCEB1S1E", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "VPCEB1S1E"), + }, + }, + { + .callback = init_nvs_nosave, + .ident = "Sony Vaio VGN-FW520F", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FW520F"), + }, + }, + { + .callback = init_nvs_nosave, + .ident = "Asus K54C", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "K54C"), + }, + }, + { + .callback = init_nvs_nosave, + .ident = "Asus K54HR", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "K54HR"), + }, + }, + {}, +}; + +static void acpi_sleep_dmi_check(void) +{ + dmi_check_system(acpisleep_dmi_table); +} + /** * acpi_pm_freeze - Disable the GPEs and suspend EC transactions. */ @@ -227,6 +401,7 @@ static void acpi_pm_end(void) } #else /* !CONFIG_ACPI_SLEEP */ #define acpi_target_sleep_state ACPI_STATE_S0 +static inline void acpi_sleep_dmi_check(void) {} #endif /* CONFIG_ACPI_SLEEP */ #ifdef CONFIG_SUSPEND @@ -371,167 +546,6 @@ static const struct platform_suspend_ops acpi_suspend_ops_old = { .end = acpi_pm_end, .recover = acpi_pm_finish, }; - -static int __init init_old_suspend_ordering(const struct dmi_system_id *d) -{ - old_suspend_ordering = true; - return 0; -} - -static int __init init_nvs_nosave(const struct dmi_system_id *d) -{ - acpi_nvs_nosave(); - return 0; -} - -static struct dmi_system_id __initdata acpisleep_dmi_table[] = { - { - .callback = init_old_suspend_ordering, - .ident = "Abit KN9 (nForce4 variant)", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "http://www.abit.com.tw/"), - DMI_MATCH(DMI_BOARD_NAME, "KN9 Series(NF-CK804)"), - }, - }, - { - .callback = init_old_suspend_ordering, - .ident = "HP xw4600 Workstation", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_PRODUCT_NAME, "HP xw4600 Workstation"), - }, - }, - { - .callback = init_old_suspend_ordering, - .ident = "Asus Pundit P1-AH2 (M2N8L motherboard)", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTek Computer INC."), - DMI_MATCH(DMI_BOARD_NAME, "M2N8L"), - }, - }, - { - .callback = init_old_suspend_ordering, - .ident = "Panasonic CF51-2L", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, - "Matsushita Electric Industrial Co.,Ltd."), - DMI_MATCH(DMI_BOARD_NAME, "CF51-2L"), - }, - }, - { - .callback = init_nvs_nosave, - .ident = "Sony Vaio VGN-FW21E", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), - DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FW21E"), - }, - }, - { - .callback = init_nvs_nosave, - .ident = "Sony Vaio VPCEB17FX", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), - DMI_MATCH(DMI_PRODUCT_NAME, "VPCEB17FX"), - }, - }, - { - .callback = init_nvs_nosave, - .ident = "Sony Vaio VGN-SR11M", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), - DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR11M"), - }, - }, - { - .callback = init_nvs_nosave, - .ident = "Everex StepNote Series", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Everex Systems, Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "Everex StepNote Series"), - }, - }, - { - .callback = init_nvs_nosave, - .ident = "Sony Vaio VPCEB1Z1E", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), - DMI_MATCH(DMI_PRODUCT_NAME, "VPCEB1Z1E"), - }, - }, - { - .callback = init_nvs_nosave, - .ident = "Sony Vaio VGN-NW130D", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), - DMI_MATCH(DMI_PRODUCT_NAME, "VGN-NW130D"), - }, - }, - { - .callback = init_nvs_nosave, - .ident = "Sony Vaio VPCCW29FX", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), - DMI_MATCH(DMI_PRODUCT_NAME, "VPCCW29FX"), - }, - }, - { - .callback = init_nvs_nosave, - .ident = "Averatec AV1020-ED2", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "AVERATEC"), - DMI_MATCH(DMI_PRODUCT_NAME, "1000 Series"), - }, - }, - { - .callback = init_old_suspend_ordering, - .ident = "Asus A8N-SLI DELUXE", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), - DMI_MATCH(DMI_BOARD_NAME, "A8N-SLI DELUXE"), - }, - }, - { - .callback = init_old_suspend_ordering, - .ident = "Asus A8N-SLI Premium", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), - DMI_MATCH(DMI_BOARD_NAME, "A8N-SLI Premium"), - }, - }, - { - .callback = init_nvs_nosave, - .ident = "Sony Vaio VGN-SR26GN_P", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), - DMI_MATCH(DMI_PRODUCT_NAME, "VGN-SR26GN_P"), - }, - }, - { - .callback = init_nvs_nosave, - .ident = "Sony Vaio VGN-FW520F", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), - DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FW520F"), - }, - }, - { - .callback = init_nvs_nosave, - .ident = "Asus K54C", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "K54C"), - }, - }, - { - .callback = init_nvs_nosave, - .ident = "Asus K54HR", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK Computer Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "K54HR"), - }, - }, - {}, -}; #endif /* CONFIG_SUSPEND */ #ifdef CONFIG_HIBERNATION @@ -872,13 +886,13 @@ int __init acpi_sleep_init(void) u8 type_a, type_b; #ifdef CONFIG_SUSPEND int i = 0; - - dmi_check_system(acpisleep_dmi_table); #endif if (acpi_disabled) return 0; + acpi_sleep_dmi_check(); + sleep_states[ACPI_STATE_S0] = 1; printk(KERN_INFO PREFIX "(supports S0"); diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 48b5a3cda37..91357e1a1a8 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -389,6 +389,12 @@ static int __init video_set_bqc_offset(const struct dmi_system_id *d) return 0; } +static int video_ignore_initial_backlight(const struct dmi_system_id *d) +{ + use_bios_initial_backlight = 0; + return 0; +} + static struct dmi_system_id video_dmi_table[] __initdata = { /* * Broken _BQC workaround http://bugzilla.kernel.org/show_bug.cgi?id=13121 @@ -433,6 +439,14 @@ static struct dmi_system_id video_dmi_table[] __initdata = { DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 7720"), }, }, + { + .callback = video_ignore_initial_backlight, + .ident = "HP Folio 13-2000", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP Folio 13 - 2000 Notebook PC"), + }, + }, {} }; @@ -1345,12 +1359,15 @@ static int acpi_video_bus_get_devices(struct acpi_video_bus *video, struct acpi_device *device) { - int status; + int status = 0; struct acpi_device *dev; - status = acpi_video_device_enumerate(video); - if (status) - return status; + /* + * There are systems where video module known to work fine regardless + * of broken _DOD and ignoring returned value here doesn't cause + * any issues later. + */ + acpi_video_device_enumerate(video); list_for_each_entry(dev, &device->children, node) { diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index ebaf67e4b2b..71a4d040f14 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -53,6 +53,7 @@ enum { AHCI_PCI_BAR_STA2X11 = 0, + AHCI_PCI_BAR_ENMOTUS = 2, AHCI_PCI_BAR_STANDARD = 5, }; @@ -396,6 +397,8 @@ static const struct pci_device_id ahci_pci_tbl[] = { .driver_data = board_ahci_yes_fbs }, /* 88se9125 */ { PCI_DEVICE(0x1b4b, 0x917a), .driver_data = board_ahci_yes_fbs }, /* 88se9172 */ + { PCI_DEVICE(0x1b4b, 0x9192), + .driver_data = board_ahci_yes_fbs }, /* 88se9172 on some Gigabyte */ { PCI_DEVICE(0x1b4b, 0x91a3), .driver_data = board_ahci_yes_fbs }, @@ -403,7 +406,13 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(PROMISE, 0x3f20), board_ahci }, /* PDC42819 */ /* Asmedia */ - { PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci }, /* ASM1061 */ + { PCI_VDEVICE(ASMEDIA, 0x0601), board_ahci }, /* ASM1060 */ + { PCI_VDEVICE(ASMEDIA, 0x0602), board_ahci }, /* ASM1060 */ + { PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci }, /* ASM1061 */ + { PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci }, /* ASM1062 */ + + /* Enmotus */ + { PCI_DEVICE(0x1c44, 0x8000), board_ahci }, /* Generic, PCI class code for AHCI */ { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, @@ -1077,9 +1086,11 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) dev_info(&pdev->dev, "PDC42819 can only drive SATA devices with this driver\n"); - /* The Connext uses non-standard BAR */ + /* Both Connext and Enmotus devices use non-standard BARs */ if (pdev->vendor == PCI_VENDOR_ID_STMICRO && pdev->device == 0xCC06) ahci_pci_bar = AHCI_PCI_BAR_STA2X11; + else if (pdev->vendor == 0x1c44 && pdev->device == 0x8000) + ahci_pci_bar = AHCI_PCI_BAR_ENMOTUS; /* acquire resources */ rc = pcim_enable_device(pdev); diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index d31ee557b39..4b4caa3db6c 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -2536,6 +2536,7 @@ int ata_bus_probe(struct ata_port *ap) * bus as we may be talking too fast. */ dev->pio_mode = XFER_PIO_0; + dev->dma_mode = 0xff; /* If the controller has a pio mode setup function * then use it to set the chipset to rights. Don't @@ -4125,6 +4126,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { /* Devices which aren't very happy with higher link speeds */ { "WD My Book", NULL, ATA_HORKAGE_1_5_GBPS, }, + { "Seagate FreeAgent GoFlex", NULL, ATA_HORKAGE_1_5_GBPS, }, /* * Devices which choke on SETXFER. Applies only if both the diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index d1fbd59ead1..e47c224d7c2 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -2600,6 +2600,7 @@ int ata_eh_reset(struct ata_link *link, int classify, * bus as we may be talking too fast. */ dev->pio_mode = XFER_PIO_0; + dev->dma_mode = 0xff; /* If the controller has a pio mode setup function * then use it to set the chipset to rights. Don't diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 22226350cd0..15863a4b619 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -309,7 +309,8 @@ ata_scsi_activity_show(struct device *dev, struct device_attribute *attr, struct ata_port *ap = ata_shost_to_port(sdev->host); struct ata_device *atadev = ata_scsi_find_dev(ap, sdev); - if (ap->ops->sw_activity_show && (ap->flags & ATA_FLAG_SW_ACTIVITY)) + if (atadev && ap->ops->sw_activity_show && + (ap->flags & ATA_FLAG_SW_ACTIVITY)) return ap->ops->sw_activity_show(atadev, buf); return -EINVAL; } @@ -324,7 +325,8 @@ ata_scsi_activity_store(struct device *dev, struct device_attribute *attr, enum sw_activity val; int rc; - if (ap->ops->sw_activity_store && (ap->flags & ATA_FLAG_SW_ACTIVITY)) { + if (atadev && ap->ops->sw_activity_store && + (ap->flags & ATA_FLAG_SW_ACTIVITY)) { val = simple_strtoul(buf, NULL, 0); switch (val) { case OFF: case BLINK_ON: case BLINK_OFF: diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c index 000fcc99e01..ef6e328784e 100644 --- a/drivers/ata/sata_promise.c +++ b/drivers/ata/sata_promise.c @@ -147,6 +147,10 @@ struct pdc_port_priv { dma_addr_t pkt_dma; }; +struct pdc_host_priv { + spinlock_t hard_reset_lock; +}; + static int pdc_sata_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val); static int pdc_sata_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val); static int pdc_ata_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); @@ -801,9 +805,10 @@ static void pdc_hard_reset_port(struct ata_port *ap) void __iomem *host_mmio = ap->host->iomap[PDC_MMIO_BAR]; void __iomem *pcictl_b1_mmio = host_mmio + PDC_PCI_CTL + 1; unsigned int ata_no = pdc_ata_port_to_ata_no(ap); + struct pdc_host_priv *hpriv = ap->host->private_data; u8 tmp; - spin_lock(&ap->host->lock); + spin_lock(&hpriv->hard_reset_lock); tmp = readb(pcictl_b1_mmio); tmp &= ~(0x10 << ata_no); @@ -814,7 +819,7 @@ static void pdc_hard_reset_port(struct ata_port *ap) writeb(tmp, pcictl_b1_mmio); readb(pcictl_b1_mmio); /* flush */ - spin_unlock(&ap->host->lock); + spin_unlock(&hpriv->hard_reset_lock); } static int pdc_sata_hardreset(struct ata_link *link, unsigned int *class, @@ -1182,6 +1187,7 @@ static int pdc_ata_init_one(struct pci_dev *pdev, const struct ata_port_info *pi = &pdc_port_info[ent->driver_data]; const struct ata_port_info *ppi[PDC_MAX_PORTS]; struct ata_host *host; + struct pdc_host_priv *hpriv; void __iomem *host_mmio; int n_ports, i, rc; int is_sataii_tx4; @@ -1218,6 +1224,11 @@ static int pdc_ata_init_one(struct pci_dev *pdev, dev_err(&pdev->dev, "failed to allocate host\n"); return -ENOMEM; } + hpriv = devm_kzalloc(&pdev->dev, sizeof *hpriv, GFP_KERNEL); + if (!hpriv) + return -ENOMEM; + spin_lock_init(&hpriv->hard_reset_lock); + host->private_data = hpriv; host->iomap = pcim_iomap_table(pdev); is_sataii_tx4 = pdc_is_sataii_tx4(pi->flags); diff --git a/drivers/ata/sata_svw.c b/drivers/ata/sata_svw.c index c646118943f..833607f5ae4 100644 --- a/drivers/ata/sata_svw.c +++ b/drivers/ata/sata_svw.c @@ -142,6 +142,39 @@ static int k2_sata_scr_write(struct ata_link *link, return 0; } +static int k2_sata_softreset(struct ata_link *link, + unsigned int *class, unsigned long deadline) +{ + u8 dmactl; + void __iomem *mmio = link->ap->ioaddr.bmdma_addr; + + dmactl = readb(mmio + ATA_DMA_CMD); + + /* Clear the start bit */ + if (dmactl & ATA_DMA_START) { + dmactl &= ~ATA_DMA_START; + writeb(dmactl, mmio + ATA_DMA_CMD); + } + + return ata_sff_softreset(link, class, deadline); +} + +static int k2_sata_hardreset(struct ata_link *link, + unsigned int *class, unsigned long deadline) +{ + u8 dmactl; + void __iomem *mmio = link->ap->ioaddr.bmdma_addr; + + dmactl = readb(mmio + ATA_DMA_CMD); + + /* Clear the start bit */ + if (dmactl & ATA_DMA_START) { + dmactl &= ~ATA_DMA_START; + writeb(dmactl, mmio + ATA_DMA_CMD); + } + + return sata_sff_hardreset(link, class, deadline); +} static void k2_sata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf) { @@ -346,6 +379,8 @@ static struct scsi_host_template k2_sata_sht = { static struct ata_port_operations k2_sata_ops = { .inherits = &ata_bmdma_port_ops, + .softreset = k2_sata_softreset, + .hardreset = k2_sata_hardreset, .sff_tf_load = k2_sata_tf_load, .sff_tf_read = k2_sata_tf_read, .sff_check_status = k2_stat_check_status, diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index 98510931c81..1853a45c668 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c @@ -967,10 +967,11 @@ static uint32_t fpga_tx(struct solos_card *card) for (port = 0; tx_pending; tx_pending >>= 1, port++) { if (tx_pending & 1) { struct sk_buff *oldskb = card->tx_skb[port]; - if (oldskb) + if (oldskb) { pci_unmap_single(card->dev, SKB_CB(oldskb)->dma_addr, oldskb->len, PCI_DMA_TODEVICE); - + card->tx_skb[port] = NULL; + } spin_lock(&card->tx_queue_lock); skb = skb_dequeue(&card->tx_queue[port]); if (!skb) diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index dbebba91b0d..72c10145929 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -1012,7 +1012,7 @@ int dpm_suspend_end(pm_message_t state) error = dpm_suspend_noirq(state); if (error) { - dpm_resume_early(state); + dpm_resume_early(resume_event(state)); return error; } diff --git a/drivers/base/power/qos.c b/drivers/base/power/qos.c index 71855570922..c365c93abe1 100644 --- a/drivers/base/power/qos.c +++ b/drivers/base/power/qos.c @@ -446,7 +446,7 @@ int dev_pm_qos_add_ancestor_request(struct device *dev, if (ancestor) error = dev_pm_qos_add_request(ancestor, req, value); - if (error) + if (error < 0) req->dev = NULL; return error; diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index bd0f3949bcf..bb82b1817ae 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -430,7 +430,6 @@ static int rpm_suspend(struct device *dev, int rpmflags) goto repeat; } - dev->power.deferred_resume = false; if (dev->power.no_callbacks) goto no_callback; /* Assume success. */ @@ -506,6 +505,7 @@ static int rpm_suspend(struct device *dev, int rpmflags) wake_up_all(&dev->power.wait_queue); if (dev->power.deferred_resume) { + dev->power.deferred_resume = false; rpm_resume(dev, 0); retval = -EAGAIN; goto out; @@ -652,6 +652,7 @@ static int rpm_resume(struct device *dev, int rpmflags) || dev->parent->power.runtime_status == RPM_ACTIVE) { atomic_inc(&dev->parent->power.child_count); spin_unlock(&dev->parent->power.lock); + retval = 1; goto no_callback; /* Assume success. */ } spin_unlock(&dev->parent->power.lock); @@ -735,7 +736,7 @@ static int rpm_resume(struct device *dev, int rpmflags) } wake_up_all(&dev->power.wait_queue); - if (!retval) + if (retval >= 0) rpm_idle(dev, RPM_ASYNC); out: diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c index 251eb70f83e..8ab1eab90be 100644 --- a/drivers/base/regmap/regmap-debugfs.c +++ b/drivers/base/regmap/regmap-debugfs.c @@ -90,7 +90,7 @@ static ssize_t regmap_map_read_file(struct file *file, char __user *user_buf, /* If we're in the region the user is trying to read */ if (p >= *ppos) { /* ...but not beyond it */ - if (buf_pos >= count - 1 - tot_len) + if (buf_pos + 1 + tot_len >= count) break; /* Format the register */ diff --git a/drivers/bcma/driver_mips.c b/drivers/bcma/driver_mips.c index c3e9dff4224..041fddfd01a 100644 --- a/drivers/bcma/driver_mips.c +++ b/drivers/bcma/driver_mips.c @@ -115,7 +115,7 @@ static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq) bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) & ~(1 << irqflag)); else - bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq), 0); + bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(oldirq), 0); /* assign the new one */ if (irq == 0) { diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c index 7e138ec2135..edb9233b26d 100644 --- a/drivers/bcma/main.c +++ b/drivers/bcma/main.c @@ -131,9 +131,10 @@ static int bcma_register_cores(struct bcma_bus *bus) static void bcma_unregister_cores(struct bcma_bus *bus) { - struct bcma_device *core; + struct bcma_device *core, *tmp; - list_for_each_entry(core, &bus->cores, list) { + list_for_each_entry_safe(core, tmp, &bus->cores, list) { + list_del(&core->list); if (core->dev_registered) device_unregister(&core->dev); } diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h index db195abad69..e49ddd0aea1 100644 --- a/drivers/block/aoe/aoe.h +++ b/drivers/block/aoe/aoe.h @@ -1,5 +1,5 @@ /* Copyright (c) 2007 Coraid, Inc. See COPYING for GPL terms. */ -#define VERSION "47" +#define VERSION "47q" #define AOE_MAJOR 152 #define DEVICE_NAME "aoe" diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c index 321de7b6c44..7eca46349c4 100644 --- a/drivers/block/aoe/aoeblk.c +++ b/drivers/block/aoe/aoeblk.c @@ -276,8 +276,6 @@ aoeblk_gdalloc(void *vp) goto err_mempool; blk_queue_make_request(d->blkq, aoeblk_make_request); d->blkq->backing_dev_info.name = "aoe"; - if (bdi_init(&d->blkq->backing_dev_info)) - goto err_blkq; spin_lock_irqsave(&d->lock, flags); gd->major = AOE_MAJOR; gd->first_minor = d->sysminor * AOE_PARTITIONS; @@ -298,9 +296,6 @@ aoeblk_gdalloc(void *vp) aoedisk_add_sysfs(d); return; -err_blkq: - blk_cleanup_queue(d->blkq); - d->blkq = NULL; err_mempool: mempool_destroy(d->bufpool); err_disk: diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index de0435e63b0..887f68f6d79 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -35,6 +35,7 @@ new_skb(ulong len) skb_reset_mac_header(skb); skb_reset_network_header(skb); skb->protocol = __constant_htons(ETH_P_AOE); + skb_checksum_none_assert(skb); } return skb; } diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c index acda773b372..da3311129a0 100644 --- a/drivers/block/cciss_scsi.c +++ b/drivers/block/cciss_scsi.c @@ -763,16 +763,7 @@ static void complete_scsi_command(CommandList_struct *c, int timeout, { case CMD_TARGET_STATUS: /* Pass it up to the upper layers... */ - if( ei->ScsiStatus) - { -#if 0 - printk(KERN_WARNING "cciss: cmd %p " - "has SCSI Status = %x\n", - c, ei->ScsiStatus); -#endif - cmd->result |= (ei->ScsiStatus << 1); - } - else { /* scsi status is zero??? How??? */ + if (!ei->ScsiStatus) { /* Ordinarily, this case should never happen, but there is a bug in some released firmware revisions that allows it to happen @@ -804,6 +795,7 @@ static void complete_scsi_command(CommandList_struct *c, int timeout, } break; case CMD_PROTOCOL_ERR: + cmd->result = DID_ERROR << 16; dev_warn(&h->pdev->dev, "%p has protocol error\n", c); break; diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c index 4a0f314086e..be984e07366 100644 --- a/drivers/block/drbd/drbd_req.c +++ b/drivers/block/drbd/drbd_req.c @@ -37,6 +37,7 @@ static void _drbd_start_io_acct(struct drbd_conf *mdev, struct drbd_request *req const int rw = bio_data_dir(bio); int cpu; cpu = part_stat_lock(); + part_round_stats(cpu, &mdev->vdisk->part0); part_stat_inc(cpu, &mdev->vdisk->part0, ios[rw]); part_stat_add(cpu, &mdev->vdisk->part0, sectors[rw], bio_sectors(bio)); part_inc_in_flight(&mdev->vdisk->part0, rw); diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index b0b00d70c16..c82f06e639f 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -4161,6 +4161,7 @@ static int __init floppy_init(void) disks[dr]->queue = blk_init_queue(do_fd_request, &floppy_lock); if (!disks[dr]->queue) { + put_disk(disks[dr]); err = -ENOMEM; goto out_put_disk; } diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 061427a75d3..3c4c225d198 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -445,6 +445,14 @@ static void nbd_clear_que(struct nbd_device *nbd) req->errors++; nbd_end_request(req); } + + while (!list_empty(&nbd->waiting_queue)) { + req = list_entry(nbd->waiting_queue.next, struct request, + queuelist); + list_del_init(&req->queuelist); + req->errors++; + nbd_end_request(req); + } } @@ -594,6 +602,7 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd, nbd->file = NULL; nbd_clear_que(nbd); BUG_ON(!list_empty(&nbd->queue_head)); + BUG_ON(!list_empty(&nbd->waiting_queue)); if (file) fput(file); return 0; diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 38a2d063188..9782340b669 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c @@ -1153,7 +1153,7 @@ static int nvme_user_admin_cmd(struct nvme_ns *ns, struct nvme_admin_cmd cmd; struct nvme_command c; int status, length; - struct nvme_iod *iod; + struct nvme_iod *uninitialized_var(iod); if (!capable(CAP_SYS_ADMIN)) return -EACCES; diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 013c7a549fb..cba3d0278b8 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -71,7 +71,7 @@ #define DEV_NAME_LEN 32 #define MAX_INT_FORMAT_WIDTH ((5 * sizeof (int)) / 2 + 1) -#define RBD_NOTIFY_TIMEOUT_DEFAULT 10 +#define RBD_READ_ONLY_DEFAULT false /* * block device image metadata (in-memory version) @@ -94,7 +94,7 @@ struct rbd_image_header { }; struct rbd_options { - int notify_timeout; + bool read_only; }; /* @@ -174,10 +174,13 @@ struct rbd_device { /* protects updating the header */ struct rw_semaphore header_rwsem; + /* name of the snapshot this device reads from */ char snap_name[RBD_MAX_SNAP_NAME_LEN]; - u32 cur_snap; /* index+1 of current snapshot within snap context - 0 - for the head */ - int read_only; + /* id of the snapshot this device reads from */ + u64 snap_id; /* current snapshot id */ + /* whether the snap_id this device reads from still exists */ + bool snap_exists; + bool read_only; struct list_head node; @@ -186,6 +189,7 @@ struct rbd_device { /* sysfs related */ struct device dev; + unsigned long open_count; }; static DEFINE_MUTEX(ctl_mutex); /* Serialize open/close/setup/teardown */ @@ -198,10 +202,6 @@ static DEFINE_SPINLOCK(rbd_client_list_lock); static int __rbd_init_snaps_header(struct rbd_device *rbd_dev); static void rbd_dev_release(struct device *dev); -static ssize_t rbd_snap_add(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count); static void __rbd_remove_snap_dev(struct rbd_device *rbd_dev, struct rbd_snap *snap); @@ -247,13 +247,15 @@ static int rbd_open(struct block_device *bdev, fmode_t mode) { struct rbd_device *rbd_dev = bdev->bd_disk->private_data; - rbd_get_dev(rbd_dev); - - set_device_ro(bdev, rbd_dev->read_only); - if ((mode & FMODE_WRITE) && rbd_dev->read_only) return -EROFS; + mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); + rbd_get_dev(rbd_dev); + set_device_ro(bdev, rbd_dev->read_only); + rbd_dev->open_count++; + mutex_unlock(&ctl_mutex); + return 0; } @@ -261,7 +263,11 @@ static int rbd_release(struct gendisk *disk, fmode_t mode) { struct rbd_device *rbd_dev = disk->private_data; + mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); + BUG_ON(!rbd_dev->open_count); + rbd_dev->open_count--; rbd_put_dev(rbd_dev); + mutex_unlock(&ctl_mutex); return 0; } @@ -343,17 +349,24 @@ static struct rbd_client *__rbd_client_find(struct ceph_options *opt) * mount options */ enum { - Opt_notify_timeout, Opt_last_int, /* int args above */ Opt_last_string, /* string args above */ + Opt_read_only, + Opt_read_write, + /* Boolean args above */ + Opt_last_bool, }; static match_table_t rbdopt_tokens = { - {Opt_notify_timeout, "notify_timeout=%d"}, /* int args above */ /* string args above */ + {Opt_read_only, "read_only"}, + {Opt_read_only, "ro"}, /* Alternate spelling */ + {Opt_read_write, "read_write"}, + {Opt_read_write, "rw"}, /* Alternate spelling */ + /* Boolean args above */ {-1, NULL} }; @@ -378,13 +391,18 @@ static int parse_rbd_opts_token(char *c, void *private) } else if (token > Opt_last_int && token < Opt_last_string) { dout("got string token %d val %s\n", token, argstr[0].from); + } else if (token > Opt_last_string && token < Opt_last_bool) { + dout("got Boolean token %d\n", token); } else { dout("got token %d\n", token); } switch (token) { - case Opt_notify_timeout: - rbdopt->notify_timeout = intval; + case Opt_read_only: + rbdopt->read_only = true; + break; + case Opt_read_write: + rbdopt->read_only = false; break; default: BUG_ON(token); @@ -408,7 +426,7 @@ static struct rbd_client *rbd_get_client(const char *mon_addr, if (!rbd_opts) return ERR_PTR(-ENOMEM); - rbd_opts->notify_timeout = RBD_NOTIFY_TIMEOUT_DEFAULT; + rbd_opts->read_only = RBD_READ_ONLY_DEFAULT; opt = ceph_parse_options(options, mon_addr, mon_addr + mon_addr_len, @@ -450,7 +468,9 @@ static void rbd_client_release(struct kref *kref) struct rbd_client *rbdc = container_of(kref, struct rbd_client, kref); dout("rbd_release_client %p\n", rbdc); + spin_lock(&rbd_client_list_lock); list_del(&rbdc->node); + spin_unlock(&rbd_client_list_lock); ceph_destroy_client(rbdc->client); kfree(rbdc->rbd_opts); @@ -463,9 +483,7 @@ static void rbd_client_release(struct kref *kref) */ static void rbd_put_client(struct rbd_device *rbd_dev) { - spin_lock(&rbd_client_list_lock); kref_put(&rbd_dev->rbd_client->kref, rbd_client_release); - spin_unlock(&rbd_client_list_lock); rbd_dev->rbd_client = NULL; } @@ -498,7 +516,7 @@ static int rbd_header_from_disk(struct rbd_image_header *header, snap_count = le32_to_cpu(ondisk->snap_count); header->snapc = kmalloc(sizeof(struct ceph_snap_context) + - snap_count * sizeof (*ondisk), + snap_count * sizeof(u64), gfp_flags); if (!header->snapc) return -ENOMEM; @@ -552,21 +570,6 @@ static int rbd_header_from_disk(struct rbd_image_header *header, return -ENOMEM; } -static int snap_index(struct rbd_image_header *header, int snap_num) -{ - return header->total_snaps - snap_num; -} - -static u64 cur_snap_id(struct rbd_device *rbd_dev) -{ - struct rbd_image_header *header = &rbd_dev->header; - - if (!rbd_dev->cur_snap) - return 0; - - return header->snapc->snaps[snap_index(header, rbd_dev->cur_snap)]; -} - static int snap_by_name(struct rbd_image_header *header, const char *snap_name, u64 *seq, u64 *size) { @@ -605,17 +608,18 @@ static int rbd_header_set_snap(struct rbd_device *dev, u64 *size) snapc->seq = header->snap_seq; else snapc->seq = 0; - dev->cur_snap = 0; - dev->read_only = 0; + dev->snap_id = CEPH_NOSNAP; + dev->snap_exists = false; + dev->read_only = dev->rbd_client->rbd_opts->read_only; if (size) *size = header->image_size; } else { ret = snap_by_name(header, dev->snap_name, &snapc->seq, size); if (ret < 0) goto done; - - dev->cur_snap = header->total_snaps - ret; - dev->read_only = 1; + dev->snap_id = snapc->seq; + dev->snap_exists = true; + dev->read_only = true; /* No choice for snapshots */ } ret = 0; @@ -626,7 +630,7 @@ static int rbd_header_set_snap(struct rbd_device *dev, u64 *size) static void rbd_header_free(struct rbd_image_header *header) { - kfree(header->snapc); + ceph_put_snap_context(header->snapc); kfree(header->snap_names); kfree(header->snap_sizes); } @@ -904,13 +908,10 @@ static int rbd_do_request(struct request *rq, dout("rbd_do_request obj=%s ofs=%lld len=%lld\n", obj, len, ofs); - down_read(&dev->header_rwsem); - osdc = &dev->rbd_client->client->osdc; req = ceph_osdc_alloc_request(osdc, flags, snapc, ops, false, GFP_NOIO, pages, bio); if (!req) { - up_read(&dev->header_rwsem); ret = -ENOMEM; goto done_pages; } @@ -937,15 +938,15 @@ static int rbd_do_request(struct request *rq, layout->fl_object_size = cpu_to_le32(1 << RBD_MAX_OBJ_ORDER); layout->fl_pg_preferred = cpu_to_le32(-1); layout->fl_pg_pool = cpu_to_le32(dev->poolid); - ceph_calc_raw_layout(osdc, layout, snapid, ofs, &len, &bno, - req, ops); + ret = ceph_calc_raw_layout(osdc, layout, snapid, ofs, &len, &bno, + req, ops); + BUG_ON(ret != 0); ceph_osdc_build_request(req, ofs, &len, ops, snapc, &mtime, req->r_oid, req->r_oid_len); - up_read(&dev->header_rwsem); if (linger_req) { ceph_osdc_set_request_linger(osdc, req); @@ -1210,7 +1211,7 @@ static int rbd_req_sync_notify_ack(struct rbd_device *dev, if (ret < 0) return ret; - ops[0].watch.ver = cpu_to_le64(dev->header.obj_version); + ops[0].watch.ver = cpu_to_le64(ver); ops[0].watch.cookie = notify_id; ops[0].watch.flag = 0; @@ -1230,6 +1231,7 @@ static int rbd_req_sync_notify_ack(struct rbd_device *dev, static void rbd_watch_cb(u64 ver, u64 notify_id, u8 opcode, void *data) { struct rbd_device *dev = (struct rbd_device *)data; + u64 hver; int rc; if (!dev) @@ -1239,12 +1241,13 @@ static void rbd_watch_cb(u64 ver, u64 notify_id, u8 opcode, void *data) notify_id, (int)opcode); mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); rc = __rbd_update_snaps(dev); + hver = dev->header.obj_version; mutex_unlock(&ctl_mutex); if (rc) pr_warning(RBD_DRV_NAME "%d got notification but failed to " " update snaps: %d\n", dev->major, rc); - rbd_req_sync_notify_ack(dev, ver, notify_id, dev->obj_md_name); + rbd_req_sync_notify_ack(dev, hver, notify_id, dev->obj_md_name); } /* @@ -1321,71 +1324,7 @@ static int rbd_req_sync_unwatch(struct rbd_device *dev, return ret; } -struct rbd_notify_info { - struct rbd_device *dev; -}; - -static void rbd_notify_cb(u64 ver, u64 notify_id, u8 opcode, void *data) -{ - struct rbd_device *dev = (struct rbd_device *)data; - if (!dev) - return; - - dout("rbd_notify_cb %s notify_id=%lld opcode=%d\n", dev->obj_md_name, - notify_id, (int)opcode); -} - -/* - * Request sync osd notify - */ -static int rbd_req_sync_notify(struct rbd_device *dev, - const char *obj) -{ - struct ceph_osd_req_op *ops; - struct ceph_osd_client *osdc = &dev->rbd_client->client->osdc; - struct ceph_osd_event *event; - struct rbd_notify_info info; - int payload_len = sizeof(u32) + sizeof(u32); - int ret; - - ret = rbd_create_rw_ops(&ops, 1, CEPH_OSD_OP_NOTIFY, payload_len); - if (ret < 0) - return ret; - - info.dev = dev; - - ret = ceph_osdc_create_event(osdc, rbd_notify_cb, 1, - (void *)&info, &event); - if (ret < 0) - goto fail; - - ops[0].watch.ver = 1; - ops[0].watch.flag = 1; - ops[0].watch.cookie = event->cookie; - ops[0].watch.prot_ver = RADOS_NOTIFY_VER; - ops[0].watch.timeout = 12; - - ret = rbd_req_sync_op(dev, NULL, - CEPH_NOSNAP, - 0, - CEPH_OSD_FLAG_WRITE | CEPH_OSD_FLAG_ONDISK, - ops, - 1, obj, 0, 0, NULL, NULL, NULL); - if (ret < 0) - goto fail_event; - - ret = ceph_osdc_wait_event(event, CEPH_OSD_TIMEOUT_DEFAULT); - dout("ceph_osdc_wait_event returned %d\n", ret); - rbd_destroy_ops(ops); - return 0; - -fail_event: - ceph_osdc_cancel_event(event); -fail: - rbd_destroy_ops(ops); - return ret; -} - +#if 0 /* * Request sync osd read */ @@ -1425,6 +1364,7 @@ static int rbd_req_sync_exec(struct rbd_device *dev, dout("cls_exec returned %d\n", ret); return ret; } +#endif static struct rbd_req_coll *rbd_alloc_coll(int num_reqs) { @@ -1457,6 +1397,7 @@ static void rbd_rq_fn(struct request_queue *q) u64 ofs; int num_segs, cur_seg = 0; struct rbd_req_coll *coll; + struct ceph_snap_context *snapc; /* peek at request from block layer */ if (!rq) @@ -1483,6 +1424,20 @@ static void rbd_rq_fn(struct request_queue *q) spin_unlock_irq(q->queue_lock); + down_read(&rbd_dev->header_rwsem); + + if (rbd_dev->snap_id != CEPH_NOSNAP && !rbd_dev->snap_exists) { + up_read(&rbd_dev->header_rwsem); + dout("request for non-existent snapshot"); + spin_lock_irq(q->queue_lock); + __blk_end_request_all(rq, -ENXIO); + continue; + } + + snapc = ceph_get_snap_context(rbd_dev->header.snapc); + + up_read(&rbd_dev->header_rwsem); + dout("%s 0x%x bytes at 0x%llx\n", do_write ? "write" : "read", size, blk_rq_pos(rq) * SECTOR_SIZE); @@ -1492,6 +1447,7 @@ static void rbd_rq_fn(struct request_queue *q) if (!coll) { spin_lock_irq(q->queue_lock); __blk_end_request_all(rq, -ENOMEM); + ceph_put_snap_context(snapc); continue; } @@ -1515,13 +1471,13 @@ static void rbd_rq_fn(struct request_queue *q) /* init OSD command: write or read */ if (do_write) rbd_req_write(rq, rbd_dev, - rbd_dev->header.snapc, + snapc, ofs, op_size, bio, coll, cur_seg); else rbd_req_read(rq, rbd_dev, - cur_snap_id(rbd_dev), + rbd_dev->snap_id, ofs, op_size, bio, coll, cur_seg); @@ -1538,6 +1494,8 @@ static void rbd_rq_fn(struct request_queue *q) if (bp) bio_pair_release(bp); spin_lock_irq(q->queue_lock); + + ceph_put_snap_context(snapc); } } @@ -1641,55 +1599,6 @@ static int rbd_read_header(struct rbd_device *rbd_dev, return rc; } -/* - * create a snapshot - */ -static int rbd_header_add_snap(struct rbd_device *dev, - const char *snap_name, - gfp_t gfp_flags) -{ - int name_len = strlen(snap_name); - u64 new_snapid; - int ret; - void *data, *p, *e; - u64 ver; - struct ceph_mon_client *monc; - - /* we should create a snapshot only if we're pointing at the head */ - if (dev->cur_snap) - return -EINVAL; - - monc = &dev->rbd_client->client->monc; - ret = ceph_monc_create_snapid(monc, dev->poolid, &new_snapid); - dout("created snapid=%lld\n", new_snapid); - if (ret < 0) - return ret; - - data = kmalloc(name_len + 16, gfp_flags); - if (!data) - return -ENOMEM; - - p = data; - e = data + name_len + 16; - - ceph_encode_string_safe(&p, e, snap_name, name_len, bad); - ceph_encode_64_safe(&p, e, new_snapid, bad); - - ret = rbd_req_sync_exec(dev, dev->obj_md_name, "rbd", "snap_add", - data, p - data, &ver); - - kfree(data); - - if (ret < 0) - return ret; - - dev->header.snapc->seq = new_snapid; - - return 0; -bad: - return -ERANGE; -} - static void __rbd_remove_all_snaps(struct rbd_device *rbd_dev) { struct rbd_snap *snap; @@ -1714,10 +1623,15 @@ static int __rbd_update_snaps(struct rbd_device *rbd_dev) if (ret < 0) return ret; + down_write(&rbd_dev->header_rwsem); + /* resized? */ - set_capacity(rbd_dev->disk, h.image_size / SECTOR_SIZE); + if (rbd_dev->snap_id == CEPH_NOSNAP) { + sector_t size = (sector_t) h.image_size / SECTOR_SIZE; - down_write(&rbd_dev->header_rwsem); + dout("setting size to %llu sectors", (unsigned long long) size); + set_capacity(rbd_dev->disk, size); + } snap_seq = rbd_dev->header.snapc->seq; if (rbd_dev->header.total_snaps && @@ -1726,10 +1640,12 @@ static int __rbd_update_snaps(struct rbd_device *rbd_dev) if head moves */ follow_seq = 1; - kfree(rbd_dev->header.snapc); + ceph_put_snap_context(rbd_dev->header.snapc); kfree(rbd_dev->header.snap_names); kfree(rbd_dev->header.snap_sizes); + rbd_dev->header.obj_version = h.obj_version; + rbd_dev->header.image_size = h.image_size; rbd_dev->header.total_snaps = h.total_snaps; rbd_dev->header.snapc = h.snapc; rbd_dev->header.snap_names = h.snap_names; @@ -1833,8 +1749,13 @@ static ssize_t rbd_size_show(struct device *dev, struct device_attribute *attr, char *buf) { struct rbd_device *rbd_dev = dev_to_rbd_dev(dev); + sector_t size; + + down_read(&rbd_dev->header_rwsem); + size = get_capacity(rbd_dev->disk); + up_read(&rbd_dev->header_rwsem); - return sprintf(buf, "%llu\n", (unsigned long long)rbd_dev->header.image_size); + return sprintf(buf, "%llu\n", (unsigned long long) size * SECTOR_SIZE); } static ssize_t rbd_major_show(struct device *dev, @@ -1905,7 +1826,6 @@ static DEVICE_ATTR(pool, S_IRUGO, rbd_pool_show, NULL); static DEVICE_ATTR(name, S_IRUGO, rbd_name_show, NULL); static DEVICE_ATTR(refresh, S_IWUSR, NULL, rbd_image_refresh); static DEVICE_ATTR(current_snap, S_IRUGO, rbd_snap_show, NULL); -static DEVICE_ATTR(create_snap, S_IWUSR, NULL, rbd_snap_add); static struct attribute *rbd_attrs[] = { &dev_attr_size.attr, @@ -1915,7 +1835,6 @@ static struct attribute *rbd_attrs[] = { &dev_attr_name.attr, &dev_attr_current_snap.attr, &dev_attr_refresh.attr, - &dev_attr_create_snap.attr, NULL }; @@ -2084,7 +2003,14 @@ static int __rbd_init_snaps_header(struct rbd_device *rbd_dev) cur_id = rbd_dev->header.snapc->snaps[i - 1]; if (!i || old_snap->id < cur_id) { - /* old_snap->id was skipped, thus was removed */ + /* + * old_snap->id was skipped, thus was + * removed. If this rbd_dev is mapped to + * the removed snapshot, record that it no + * longer exists, to prevent further I/O. + */ + if (rbd_dev->snap_id == old_snap->id) + rbd_dev->snap_exists = false; __rbd_remove_snap_dev(rbd_dev, old_snap); continue; } @@ -2232,8 +2158,8 @@ static void rbd_id_put(struct rbd_device *rbd_dev) struct rbd_device *rbd_dev; rbd_dev = list_entry(tmp, struct rbd_device, node); - if (rbd_id > max_id) - max_id = rbd_id; + if (rbd_dev->id > max_id) + max_id = rbd_dev->id; } spin_unlock(&rbd_dev_list_lock); @@ -2530,6 +2456,11 @@ static ssize_t rbd_remove(struct bus_type *bus, goto done; } + if (rbd_dev->open_count) { + ret = -EBUSY; + goto done; + } + __rbd_remove_all_snaps(rbd_dev); rbd_bus_del_dev(rbd_dev); @@ -2538,47 +2469,6 @@ static ssize_t rbd_remove(struct bus_type *bus, return ret; } -static ssize_t rbd_snap_add(struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - struct rbd_device *rbd_dev = dev_to_rbd_dev(dev); - int ret; - char *name = kmalloc(count + 1, GFP_KERNEL); - if (!name) - return -ENOMEM; - - snprintf(name, count, "%s", buf); - - mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); - - ret = rbd_header_add_snap(rbd_dev, - name, GFP_KERNEL); - if (ret < 0) - goto err_unlock; - - ret = __rbd_update_snaps(rbd_dev); - if (ret < 0) - goto err_unlock; - - /* shouldn't hold ctl_mutex when notifying.. notify might - trigger a watch callback that would need to get that mutex */ - mutex_unlock(&ctl_mutex); - - /* make a best effort, don't error if failed */ - rbd_req_sync_notify(rbd_dev, rbd_dev->obj_md_name); - - ret = count; - kfree(name); - return ret; - -err_unlock: - mutex_unlock(&ctl_mutex); - kfree(name); - return ret; -} - /* * create control files in sysfs * /sys/bus/rbd/... diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index 73f196ca713..c6decb901e5 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c @@ -337,7 +337,7 @@ static void xen_blkbk_unmap(struct pending_req *req) invcount++; } - ret = gnttab_unmap_refs(unmap, pages, invcount, false); + ret = gnttab_unmap_refs(unmap, NULL, pages, invcount); BUG_ON(ret); } diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index 55bc2facb25..98ee436e0f0 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c @@ -62,6 +62,10 @@ static struct usb_device_id ath3k_table[] = { /* Atheros AR3011 with sflash firmware*/ { USB_DEVICE(0x0CF3, 0x3002) }, + { USB_DEVICE(0x13d3, 0x3304) }, + { USB_DEVICE(0x0930, 0x0215) }, + { USB_DEVICE(0x0489, 0xE03D) }, + { USB_DEVICE(0x0489, 0xE027) }, /* Atheros AR9285 Malbec with sflash firmware */ { USB_DEVICE(0x03F0, 0x311D) }, diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index ea2f2d26aea..75f711fe062 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -60,6 +60,9 @@ static struct usb_device_id btusb_table[] = { /* Generic Bluetooth USB device */ { USB_DEVICE_INFO(0xe0, 0x01, 0x01) }, + /* Apple-specific (Broadcom) devices */ + { USB_VENDOR_AND_INTERFACE_INFO(0x05ac, 0xff, 0x01, 0x01) }, + /* Broadcom SoftSailing reporting vendor specific */ { USB_DEVICE(0x05ac, 0x21e1) }, @@ -100,6 +103,16 @@ static struct usb_device_id btusb_table[] = { /* Canyon CN-BTU1 with HID interfaces */ { USB_DEVICE(0x0c10, 0x0000) }, + /* Broadcom BCM20702A0 */ + { USB_DEVICE(0x0489, 0xe042) }, + { USB_DEVICE(0x413c, 0x8197) }, + + /* Foxconn - Hon Hai */ + { USB_DEVICE(0x0489, 0xe033) }, + + /*Broadcom devices with vendor specific id */ + { USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01) }, + { } /* Terminating entry */ }; @@ -114,6 +127,10 @@ static struct usb_device_id blacklist_table[] = { /* Atheros 3011 with sflash firmware */ { USB_DEVICE(0x0cf3, 0x3002), .driver_info = BTUSB_IGNORE }, + { USB_DEVICE(0x13d3, 0x3304), .driver_info = BTUSB_IGNORE }, + { USB_DEVICE(0x0930, 0x0215), .driver_info = BTUSB_IGNORE }, + { USB_DEVICE(0x0489, 0xe03d), .driver_info = BTUSB_IGNORE }, + { USB_DEVICE(0x0489, 0xe027), .driver_info = BTUSB_IGNORE }, /* Atheros AR9285 Malbec with sflash firmware */ { USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE }, diff --git a/drivers/char/mspec.c b/drivers/char/mspec.c index 8b78750f1ef..845f97fd183 100644 --- a/drivers/char/mspec.c +++ b/drivers/char/mspec.c @@ -283,7 +283,7 @@ mspec_mmap(struct file *file, struct vm_area_struct *vma, vdata->flags = flags; vdata->type = type; spin_lock_init(&vdata->lock); - vdata->refcnt = ATOMIC_INIT(1); + atomic_set(&vdata->refcnt, 1); vma->vm_private_data = vdata; vma->vm_flags |= (VM_IO | VM_RESERVED | VM_PFNMAP | VM_DONTEXPAND); diff --git a/drivers/char/random.c b/drivers/char/random.c index 4d8458f1319..0a7c7bb495f 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -274,6 +274,8 @@ #define SEC_XFER_SIZE 512 #define EXTRACT_SIZE 10 +#define LONGS(x) (((x) + sizeof(unsigned long) - 1)/sizeof(unsigned long)) + /* * The minimum number of bits of entropy before we wake up a read on * /dev/random. Should be enough to do a significant reseed. @@ -798,11 +800,7 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf, */ static void xfer_secondary_pool(struct entropy_store *r, size_t nbytes) { - union { - __u32 tmp[OUTPUT_POOL_WORDS]; - long hwrand[4]; - } u; - int i; + __u32 tmp[OUTPUT_POOL_WORDS]; if (r->pull && r->entropy_count < nbytes * 8 && r->entropy_count < r->poolinfo->POOLBITS) { @@ -813,23 +811,17 @@ static void xfer_secondary_pool(struct entropy_store *r, size_t nbytes) /* pull at least as many as BYTES as wakeup BITS */ bytes = max_t(int, bytes, random_read_wakeup_thresh / 8); /* but never more than the buffer size */ - bytes = min_t(int, bytes, sizeof(u.tmp)); + bytes = min_t(int, bytes, sizeof(tmp)); DEBUG_ENT("going to reseed %s with %d bits " "(%d of %d requested)\n", r->name, bytes * 8, nbytes * 8, r->entropy_count); - bytes = extract_entropy(r->pull, u.tmp, bytes, + bytes = extract_entropy(r->pull, tmp, bytes, random_read_wakeup_thresh / 8, rsvd); - mix_pool_bytes(r, u.tmp, bytes, NULL); + mix_pool_bytes(r, tmp, bytes, NULL); credit_entropy_bits(r, bytes*8); } - kmemcheck_mark_initialized(&u.hwrand, sizeof(u.hwrand)); - for (i = 0; i < 4; i++) - if (arch_get_random_long(&u.hwrand[i])) - break; - if (i) - mix_pool_bytes(r, &u.hwrand, sizeof(u.hwrand), 0); } /* @@ -886,15 +878,19 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min, static void extract_buf(struct entropy_store *r, __u8 *out) { int i; - __u32 hash[5], workspace[SHA_WORKSPACE_WORDS]; + union { + __u32 w[5]; + unsigned long l[LONGS(EXTRACT_SIZE)]; + } hash; + __u32 workspace[SHA_WORKSPACE_WORDS]; __u8 extract[64]; unsigned long flags; /* Generate a hash across the pool, 16 words (512 bits) at a time */ - sha_init(hash); + sha_init(hash.w); spin_lock_irqsave(&r->lock, flags); for (i = 0; i < r->poolinfo->poolwords; i += 16) - sha_transform(hash, (__u8 *)(r->pool + i), workspace); + sha_transform(hash.w, (__u8 *)(r->pool + i), workspace); /* * We mix the hash back into the pool to prevent backtracking @@ -905,14 +901,14 @@ static void extract_buf(struct entropy_store *r, __u8 *out) * brute-forcing the feedback as hard as brute-forcing the * hash. */ - __mix_pool_bytes(r, hash, sizeof(hash), extract); + __mix_pool_bytes(r, hash.w, sizeof(hash.w), extract); spin_unlock_irqrestore(&r->lock, flags); /* * To avoid duplicates, we atomically extract a portion of the * pool while mixing, and hash one final time. */ - sha_transform(hash, extract, workspace); + sha_transform(hash.w, extract, workspace); memset(extract, 0, sizeof(extract)); memset(workspace, 0, sizeof(workspace)); @@ -921,11 +917,23 @@ static void extract_buf(struct entropy_store *r, __u8 *out) * pattern, we fold it in half. Thus, we always feed back * twice as much data as we output. */ - hash[0] ^= hash[3]; - hash[1] ^= hash[4]; - hash[2] ^= rol32(hash[2], 16); - memcpy(out, hash, EXTRACT_SIZE); - memset(hash, 0, sizeof(hash)); + hash.w[0] ^= hash.w[3]; + hash.w[1] ^= hash.w[4]; + hash.w[2] ^= rol32(hash.w[2], 16); + + /* + * If we have a architectural hardware random number + * generator, mix that in, too. + */ + for (i = 0; i < LONGS(EXTRACT_SIZE); i++) { + unsigned long v; + if (!arch_get_random_long(&v)) + break; + hash.l[i] ^= v; + } + + memcpy(out, &hash, EXTRACT_SIZE); + memset(&hash, 0, sizeof(hash)); } static ssize_t extract_entropy(struct entropy_store *r, void *buf, @@ -1069,6 +1077,16 @@ static void init_std_data(struct entropy_store *r) mix_pool_bytes(r, utsname(), sizeof(*(utsname())), NULL); } +/* + * Note that setup_arch() may call add_device_randomness() + * long before we get here. This allows seeding of the pools + * with some platform dependent data very early in the boot + * process. But it limits our options here. We must use + * statically allocated structures that already have all + * initializations complete at compile time. We should also + * take care not to overwrite the precious per platform data + * we were given. + */ static int rand_initialize(void) { init_std_data(&input_pool); @@ -1399,12 +1417,11 @@ ctl_table random_table[] = { static u32 random_int_secret[MD5_MESSAGE_BYTES / 4] ____cacheline_aligned; -static int __init random_int_secret_init(void) +int random_int_secret_init(void) { get_random_bytes(random_int_secret, sizeof(random_int_secret)); return 0; } -late_initcall(random_int_secret_init); /* * Get a random word for internal kernel use only. Similar to urandom but diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index ad7c7320dd1..27f8ddf09d4 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c @@ -827,10 +827,10 @@ EXPORT_SYMBOL_GPL(tpm_pcr_extend); int tpm_do_selftest(struct tpm_chip *chip) { int rc; - u8 digest[TPM_DIGEST_SIZE]; unsigned int loops; unsigned int delay_msec = 1000; unsigned long duration; + struct tpm_cmd_t cmd; duration = tpm_calc_ordinal_duration(chip, TPM_ORD_CONTINUE_SELFTEST); @@ -845,7 +845,15 @@ int tpm_do_selftest(struct tpm_chip *chip) return rc; do { - rc = __tpm_pcr_read(chip, 0, digest); + /* Attempt to read a PCR value */ + cmd.header.in = pcrread_header; + cmd.params.pcrread_in.pcr_idx = cpu_to_be32(0); + rc = tpm_transmit(chip, (u8 *) &cmd, READ_PCR_RESULT_SIZE); + + if (rc < TPM_HEADER_SIZE) + return -EFAULT; + + rc = be32_to_cpu(cmd.header.out.return_code); if (rc == TPM_ERR_DISABLED || rc == TPM_ERR_DEACTIVATED) { dev_info(chip->dev, "TPM is disabled/deactivated (0x%X)\n", rc); @@ -1178,17 +1186,20 @@ ssize_t tpm_write(struct file *file, const char __user *buf, size_t size, loff_t *off) { struct tpm_chip *chip = file->private_data; - size_t in_size = size, out_size; + size_t in_size = size; + ssize_t out_size; /* cannot perform a write until the read has cleared - either via tpm_read or a user_read_timer timeout */ - while (atomic_read(&chip->data_pending) != 0) - msleep(TPM_TIMEOUT); - - mutex_lock(&chip->buffer_mutex); + either via tpm_read or a user_read_timer timeout. + This also prevents splitted buffered writes from blocking here. + */ + if (atomic_read(&chip->data_pending) != 0) + return -EBUSY; if (in_size > TPM_BUFSIZE) - in_size = TPM_BUFSIZE; + return -E2BIG; + + mutex_lock(&chip->buffer_mutex); if (copy_from_user (chip->data_buffer, (void __user *) buf, in_size)) { @@ -1198,6 +1209,10 @@ ssize_t tpm_write(struct file *file, const char __user *buf, /* atomic tpm command send and result receive */ out_size = tpm_transmit(chip, chip->data_buffer, TPM_BUFSIZE); + if (out_size < 0) { + mutex_unlock(&chip->buffer_mutex); + return out_size; + } atomic_set(&chip->data_pending, out_size); mutex_unlock(&chip->buffer_mutex); diff --git a/drivers/char/ttyprintk.c b/drivers/char/ttyprintk.c index 46b77ede84c..a7c6d6a07d3 100644 --- a/drivers/char/ttyprintk.c +++ b/drivers/char/ttyprintk.c @@ -67,7 +67,7 @@ static int tpk_printk(const unsigned char *buf, int count) tmp[tpk_curr + 1] = '\0'; printk(KERN_INFO "%s%s", tpk_tag, tmp); tpk_curr = 0; - if (buf[i + 1] == '\n') + if ((i + 1) < count && buf[i + 1] == '\n') i++; break; case '\n': diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 2da025ee226..7f1ea568b44 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -834,18 +834,21 @@ static void clk_change_rate(struct clk *clk) { struct clk *child; unsigned long old_rate; + unsigned long best_parent_rate = 0; struct hlist_node *tmp; old_rate = clk->rate; + if (clk->parent) + best_parent_rate = clk->parent->rate; + if (clk->ops->set_rate) clk->ops->set_rate(clk->hw, clk->new_rate); if (clk->ops->recalc_rate) - clk->rate = clk->ops->recalc_rate(clk->hw, - clk->parent->rate); + clk->rate = clk->ops->recalc_rate(clk->hw, best_parent_rate); else - clk->rate = clk->parent->rate; + clk->rate = best_parent_rate; if (clk->notifier_count && old_rate != clk->rate) __clk_notify(clk, POST_RATE_CHANGE, old_rate, clk->rate); diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c index 81a4f1c5ad0..d33d4dd97b9 100644 --- a/drivers/cpufreq/powernow-k8.c +++ b/drivers/cpufreq/powernow-k8.c @@ -35,7 +35,6 @@ #include #include #include -#include /* for current / set_cpus_allowed() */ #include #include @@ -1139,16 +1138,23 @@ static int transition_frequency_pstate(struct powernow_k8_data *data, return res; } -/* Driver entry point to switch to the target frequency */ -static int powernowk8_target(struct cpufreq_policy *pol, - unsigned targfreq, unsigned relation) +struct powernowk8_target_arg { + struct cpufreq_policy *pol; + unsigned targfreq; + unsigned relation; +}; + +static long powernowk8_target_fn(void *arg) { - cpumask_var_t oldmask; + struct powernowk8_target_arg *pta = arg; + struct cpufreq_policy *pol = pta->pol; + unsigned targfreq = pta->targfreq; + unsigned relation = pta->relation; struct powernow_k8_data *data = per_cpu(powernow_data, pol->cpu); u32 checkfid; u32 checkvid; unsigned int newstate; - int ret = -EIO; + int ret; if (!data) return -EINVAL; @@ -1156,29 +1162,16 @@ static int powernowk8_target(struct cpufreq_policy *pol, checkfid = data->currfid; checkvid = data->currvid; - /* only run on specific CPU from here on. */ - /* This is poor form: use a workqueue or smp_call_function_single */ - if (!alloc_cpumask_var(&oldmask, GFP_KERNEL)) - return -ENOMEM; - - cpumask_copy(oldmask, tsk_cpus_allowed(current)); - set_cpus_allowed_ptr(current, cpumask_of(pol->cpu)); - - if (smp_processor_id() != pol->cpu) { - printk(KERN_ERR PFX "limiting to cpu %u failed\n", pol->cpu); - goto err_out; - } - if (pending_bit_stuck()) { printk(KERN_ERR PFX "failing targ, change pending bit set\n"); - goto err_out; + return -EIO; } pr_debug("targ: cpu %d, %d kHz, min %d, max %d, relation %d\n", pol->cpu, targfreq, pol->min, pol->max, relation); if (query_current_values_with_pending_wait(data)) - goto err_out; + return -EIO; if (cpu_family != CPU_HW_PSTATE) { pr_debug("targ: curr fid 0x%x, vid 0x%x\n", @@ -1196,7 +1189,7 @@ static int powernowk8_target(struct cpufreq_policy *pol, if (cpufreq_frequency_table_target(pol, data->powernow_table, targfreq, relation, &newstate)) - goto err_out; + return -EIO; mutex_lock(&fidvid_mutex); @@ -1209,9 +1202,8 @@ static int powernowk8_target(struct cpufreq_policy *pol, ret = transition_frequency_fidvid(data, newstate); if (ret) { printk(KERN_ERR PFX "transition frequency failed\n"); - ret = 1; mutex_unlock(&fidvid_mutex); - goto err_out; + return 1; } mutex_unlock(&fidvid_mutex); @@ -1220,12 +1212,18 @@ static int powernowk8_target(struct cpufreq_policy *pol, data->powernow_table[newstate].index); else pol->cur = find_khz_freq_from_fid(data->currfid); - ret = 0; -err_out: - set_cpus_allowed_ptr(current, oldmask); - free_cpumask_var(oldmask); - return ret; + return 0; +} + +/* Driver entry point to switch to the target frequency */ +static int powernowk8_target(struct cpufreq_policy *pol, + unsigned targfreq, unsigned relation) +{ + struct powernowk8_target_arg pta = { .pol = pol, .targfreq = targfreq, + .relation = relation }; + + return work_on_cpu(pol->cpu, powernowk8_target_fn, &pta); } /* Driver entry point to verify the policy and range of frequencies */ diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index bf0d7e4e345..9ec3943b123 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -664,7 +664,7 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, flags); if (unlikely(!atslave || !sg_len)) { - dev_dbg(chan2dev(chan), "prep_dma_memcpy: length is zero!\n"); + dev_dbg(chan2dev(chan), "prep_slave_sg: sg length is zero!\n"); return NULL; } @@ -691,6 +691,11 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, mem = sg_dma_address(sg); len = sg_dma_len(sg); + if (unlikely(!len)) { + dev_dbg(chan2dev(chan), + "prep_slave_sg: sg(%d) data length is zero\n", i); + goto err; + } mem_width = 2; if (unlikely(mem & 3 || len & 3)) mem_width = 0; @@ -726,6 +731,11 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, mem = sg_dma_address(sg); len = sg_dma_len(sg); + if (unlikely(!len)) { + dev_dbg(chan2dev(chan), + "prep_slave_sg: sg(%d) data length is zero\n", i); + goto err; + } mem_width = 2; if (unlikely(mem & 3 || len & 3)) mem_width = 0; @@ -759,6 +769,7 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, err_desc_get: dev_err(chan2dev(chan), "not enough descriptors available\n"); +err: atc_desc_put(atchan, first); return NULL; } diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index 2397f6f451b..6c87d676c62 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c @@ -578,7 +578,7 @@ void dmaengine_get(void) list_del_rcu(&device->global_node); break; } else if (err) - pr_err("%s: failed to get %s: (%d)\n", + pr_debug("%s: failed to get %s: (%d)\n", __func__, dma_chan_name(chan), err); } } diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c index bb787d8e152..180f5235acc 100644 --- a/drivers/dma/imx-dma.c +++ b/drivers/dma/imx-dma.c @@ -473,8 +473,10 @@ static int imxdma_xfer_desc(struct imxdma_desc *d) slot = i; break; } - if (slot < 0) + if (slot < 0) { + spin_unlock_irqrestore(&imxdma->lock, flags); return -EBUSY; + } imxdma->slots_2d[slot].xsr = d->x; imxdma->slots_2d[slot].ysr = d->y; diff --git a/drivers/dma/ioat/dma_v3.c b/drivers/dma/ioat/dma_v3.c index f7f1dc62c15..ed0e8b796a9 100644 --- a/drivers/dma/ioat/dma_v3.c +++ b/drivers/dma/ioat/dma_v3.c @@ -951,7 +951,7 @@ static int __devinit ioat_xor_val_self_test(struct ioatdma_device *device) goto free_resources; } } - dma_sync_single_for_device(dev, dest_dma, PAGE_SIZE, DMA_TO_DEVICE); + dma_sync_single_for_device(dev, dest_dma, PAGE_SIZE, DMA_FROM_DEVICE); /* skip validate if the capability is not present */ if (!dma_has_cap(DMA_XOR_VAL, dma_chan->device->cap_mask)) diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c index 8c44f17a99e..758122f33a9 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c @@ -1568,17 +1568,19 @@ static int pl330_submit_req(void *ch_id, struct pl330_req *r) goto xfer_exit; } - /* Prefer Secure Channel */ - if (!_manager_ns(thrd)) - r->cfg->nonsecure = 0; - else - r->cfg->nonsecure = 1; /* Use last settings, if not provided */ - if (r->cfg) + if (r->cfg) { + /* Prefer Secure Channel */ + if (!_manager_ns(thrd)) + r->cfg->nonsecure = 0; + else + r->cfg->nonsecure = 1; + ccr = _prepare_ccr(r->cfg); - else + } else { ccr = readl(regs + CC(thrd->id)); + } /* If this req doesn't have valid xfer settings */ if (!_is_valid(ccr)) { @@ -2935,6 +2937,11 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id) num_chan = max_t(int, pi->pcfg.num_peri, pi->pcfg.num_chan); pdmac->peripherals = kzalloc(num_chan * sizeof(*pch), GFP_KERNEL); + if (!pdmac->peripherals) { + ret = -ENOMEM; + dev_err(&adev->dev, "unable to allocate pdmac->peripherals\n"); + goto probe_err5; + } for (i = 0; i < num_chan; i++) { pch = &pdmac->peripherals[i]; diff --git a/drivers/dma/sirf-dma.c b/drivers/dma/sirf-dma.c index 434ad31174f..c4394892eda 100644 --- a/drivers/dma/sirf-dma.c +++ b/drivers/dma/sirf-dma.c @@ -109,7 +109,7 @@ static void sirfsoc_dma_execute(struct sirfsoc_dma_chan *schan) sdesc = list_first_entry(&schan->queued, struct sirfsoc_dma_desc, node); /* Move the first queued descriptor to active list */ - list_move_tail(&schan->queued, &schan->active); + list_move_tail(&sdesc->node, &schan->active); /* Start the DMA transfer */ writel_relaxed(sdesc->width, sdma->base + SIRFSOC_DMA_WIDTH_0 + @@ -428,7 +428,7 @@ static struct dma_async_tx_descriptor *sirfsoc_dma_prep_interleaved( unsigned long iflags; int ret; - if ((xt->dir != DMA_MEM_TO_DEV) || (xt->dir != DMA_DEV_TO_MEM)) { + if ((xt->dir != DMA_MEM_TO_DEV) && (xt->dir != DMA_DEV_TO_MEM)) { ret = -EINVAL; goto err_dir; } diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index 7ef73c919c5..a8bfe1c5378 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c @@ -170,8 +170,11 @@ static int __amd64_set_scrub_rate(struct pci_dev *ctl, u32 new_bw, u32 min_rate) * memory controller and apply to register. Search for the first * bandwidth entry that is greater or equal than the setting requested * and program that. If at last entry, turn off DRAM scrubbing. + * + * If no suitable bandwidth is found, turn off DRAM scrubbing entirely + * by falling back to the last element in scrubrates[]. */ - for (i = 0; i < ARRAY_SIZE(scrubrates); i++) { + for (i = 0; i < ARRAY_SIZE(scrubrates) - 1; i++) { /* * skip scrub rates which aren't recommended * (see F10 BKDG, F3x58) @@ -181,12 +184,6 @@ static int __amd64_set_scrub_rate(struct pci_dev *ctl, u32 new_bw, u32 min_rate) if (scrubrates[i].bandwidth <= new_bw) break; - - /* - * if no suitable bandwidth found, turn off DRAM scrubbing - * entirely by falling back to the last element in the - * scrubrates array. - */ } scrubval = scrubrates[i].scrubval; diff --git a/drivers/edac/edac_pci_sysfs.c b/drivers/edac/edac_pci_sysfs.c index 97f5064e399..686ac03de13 100644 --- a/drivers/edac/edac_pci_sysfs.c +++ b/drivers/edac/edac_pci_sysfs.c @@ -257,7 +257,7 @@ static ssize_t edac_pci_dev_store(struct kobject *kobj, struct edac_pci_dev_attribute *edac_pci_dev; edac_pci_dev = (struct edac_pci_dev_attribute *)attr; - if (edac_pci_dev->show) + if (edac_pci_dev->store) return edac_pci_dev->store(edac_pci_dev->value, buffer, count); return -EIO; } diff --git a/drivers/edac/i7300_edac.c b/drivers/edac/i7300_edac.c index 3bafa3bca14..f4059e9da30 100644 --- a/drivers/edac/i7300_edac.c +++ b/drivers/edac/i7300_edac.c @@ -215,8 +215,8 @@ static const char *ferr_fat_fbd_name[] = { [0] = "Memory Write error on non-redundant retry or " "FBD configuration Write error on retry", }; -#define GET_FBD_FAT_IDX(fbderr) (fbderr & (3 << 28)) -#define FERR_FAT_FBD_ERR_MASK ((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3)) +#define GET_FBD_FAT_IDX(fbderr) (((fbderr) >> 28) & 3) +#define FERR_FAT_FBD_ERR_MASK ((1 << 0) | (1 << 1) | (1 << 2) | (1 << 22)) #define FERR_NF_FBD 0xa0 static const char *ferr_nf_fbd_name[] = { @@ -243,7 +243,7 @@ static const char *ferr_nf_fbd_name[] = { [1] = "Aliased Uncorrectable Non-Mirrored Demand Data ECC", [0] = "Uncorrectable Data ECC on Replay", }; -#define GET_FBD_NF_IDX(fbderr) (fbderr & (3 << 28)) +#define GET_FBD_NF_IDX(fbderr) (((fbderr) >> 28) & 3) #define FERR_NF_FBD_ERR_MASK ((1 << 24) | (1 << 23) | (1 << 22) | (1 << 21) |\ (1 << 18) | (1 << 17) | (1 << 16) | (1 << 15) |\ (1 << 14) | (1 << 13) | (1 << 11) | (1 << 10) |\ @@ -485,7 +485,7 @@ static void i7300_process_fbd_error(struct mem_ctl_info *mci) errnum = find_first_bit(&errors, ARRAY_SIZE(ferr_nf_fbd_name)); specific = GET_ERR_FROM_TABLE(ferr_nf_fbd_name, errnum); - branch = (GET_FBD_FAT_IDX(error_reg) == 2) ? 1 : 0; + branch = (GET_FBD_NF_IDX(error_reg) == 2) ? 1 : 0; pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map, REDMEMA, &syndrome); diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index 2e6b24547e2..b8e4809cae0 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c @@ -471,8 +471,8 @@ static int ioctl_get_info(struct client *client, union ioctl_arg *arg) client->bus_reset_closure = a->bus_reset_closure; if (a->bus_reset != 0) { fill_bus_reset_event(&bus_reset, client); - ret = copy_to_user(u64_to_uptr(a->bus_reset), - &bus_reset, sizeof(bus_reset)); + /* unaligned size of bus_reset is 36 bytes */ + ret = copy_to_user(u64_to_uptr(a->bus_reset), &bus_reset, 36); } if (ret == 0 && list_empty(&client->link)) list_add_tail(&client->link, &client->device->client_list); diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c index 08c674957af..638e1f71284 100644 --- a/drivers/firewire/net.c +++ b/drivers/firewire/net.c @@ -861,8 +861,8 @@ static void fwnet_receive_broadcast(struct fw_iso_context *context, if (specifier_id == IANA_SPECIFIER_ID && ver == RFC2734_SW_VERSION) { buf_ptr += 2; length -= IEEE1394_GASP_HDR_SIZE; - fwnet_incoming_packet(dev, buf_ptr, length, - source_node_id, -1, true); + fwnet_incoming_packet(dev, buf_ptr, length, source_node_id, + context->card->generation, true); } packet.payload_length = dev->rcv_buffer_size; @@ -958,7 +958,12 @@ static void fwnet_transmit_packet_done(struct fwnet_packet_task *ptask) break; } - skb_pull(skb, ptask->max_payload); + if (ptask->dest_node == IEEE1394_ALL_NODES) { + skb_pull(skb, + ptask->max_payload + IEEE1394_GASP_HDR_SIZE); + } else { + skb_pull(skb, ptask->max_payload); + } if (ptask->outstanding_pkts > 1) { fwnet_make_sf_hdr(&ptask->hdr, RFC2374_HDR_INTFRAG, dg_size, fg_off, datagram_label); @@ -1062,7 +1067,7 @@ static int fwnet_send_packet(struct fwnet_packet_task *ptask) smp_rmb(); node_id = dev->card->node_id; - p = skb_push(ptask->skb, 8); + p = skb_push(ptask->skb, IEEE1394_GASP_HDR_SIZE); put_unaligned_be32(node_id << 16 | IANA_SPECIFIER_ID >> 8, p); put_unaligned_be32((IANA_SPECIFIER_ID & 0xff) << 24 | RFC2734_SW_VERSION, &p[4]); diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index 153980be4ee..fd3ae6290d7 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c @@ -6,6 +6,7 @@ #include #include #include +#include #include /* @@ -15,6 +16,7 @@ */ static char dmi_empty_string[] = " "; +static u16 __initdata dmi_ver; /* * Catch too early calls to dmi_check_system(): */ @@ -111,16 +113,18 @@ static int __init dmi_walk_early(void (*decode)(const struct dmi_header *, dmi_table(buf, dmi_len, dmi_num, decode, NULL); + add_device_randomness(buf, dmi_len); + dmi_iounmap(buf, dmi_len); return 0; } -static int __init dmi_checksum(const u8 *buf) +static int __init dmi_checksum(const u8 *buf, u8 len) { u8 sum = 0; int a; - for (a = 0; a < 15; a++) + for (a = 0; a < len; a++) sum += buf[a]; return sum == 0; @@ -158,8 +162,10 @@ static void __init dmi_save_uuid(const struct dmi_header *dm, int slot, int inde return; for (i = 0; i < 16 && (is_ff || is_00); i++) { - if(d[i] != 0x00) is_ff = 0; - if(d[i] != 0xFF) is_00 = 0; + if (d[i] != 0x00) + is_00 = 0; + if (d[i] != 0xFF) + is_ff = 0; } if (is_ff || is_00) @@ -169,7 +175,15 @@ static void __init dmi_save_uuid(const struct dmi_header *dm, int slot, int inde if (!s) return; - sprintf(s, "%pUB", d); + /* + * As of version 2.6 of the SMBIOS specification, the first 3 fields of + * the UUID are supposed to be little-endian encoded. The specification + * says that this is the defacto standard. + */ + if (dmi_ver >= 0x0206) + sprintf(s, "%pUL", d); + else + sprintf(s, "%pUB", d); dmi_ident[slot] = s; } @@ -401,29 +415,57 @@ static int __init dmi_present(const char __iomem *p) u8 buf[15]; memcpy_fromio(buf, p, 15); - if ((memcmp(buf, "_DMI_", 5) == 0) && dmi_checksum(buf)) { + if (dmi_checksum(buf, 15)) { dmi_num = (buf[13] << 8) | buf[12]; dmi_len = (buf[7] << 8) | buf[6]; dmi_base = (buf[11] << 24) | (buf[10] << 16) | (buf[9] << 8) | buf[8]; - /* - * DMI version 0.0 means that the real version is taken from - * the SMBIOS version, which we don't know at this point. - */ - if (buf[14] != 0) - printk(KERN_INFO "DMI %d.%d present.\n", - buf[14] >> 4, buf[14] & 0xF); - else - printk(KERN_INFO "DMI present.\n"); if (dmi_walk_early(dmi_decode) == 0) { + if (dmi_ver) + pr_info("SMBIOS %d.%d present.\n", + dmi_ver >> 8, dmi_ver & 0xFF); + else { + dmi_ver = (buf[14] & 0xF0) << 4 | + (buf[14] & 0x0F); + pr_info("Legacy DMI %d.%d present.\n", + dmi_ver >> 8, dmi_ver & 0xFF); + } dmi_dump_ids(); return 0; } } + dmi_ver = 0; return 1; } +static int __init smbios_present(const char __iomem *p) +{ + u8 buf[32]; + int offset = 0; + + memcpy_fromio(buf, p, 32); + if ((buf[5] < 32) && dmi_checksum(buf, buf[5])) { + dmi_ver = (buf[6] << 8) + buf[7]; + + /* Some BIOS report weird SMBIOS version, fix that up */ + switch (dmi_ver) { + case 0x021F: + case 0x0221: + pr_debug("SMBIOS version fixup(2.%d->2.%d)\n", + dmi_ver & 0xFF, 3); + dmi_ver = 0x0203; + break; + case 0x0233: + pr_debug("SMBIOS version fixup(2.%d->2.%d)\n", 51, 6); + dmi_ver = 0x0206; + break; + } + offset = 16; + } + return dmi_present(buf + offset); +} + void __init dmi_scan_machine(void) { char __iomem *p, *q; @@ -441,7 +483,7 @@ void __init dmi_scan_machine(void) if (p == NULL) goto error; - rc = dmi_present(p + 0x10); /* offset of _DMI_ string */ + rc = smbios_present(p); dmi_iounmap(p, 32); if (!rc) { dmi_available = 1; @@ -459,7 +501,12 @@ void __init dmi_scan_machine(void) goto error; for (q = p; q < p + 0x10000; q += 16) { - rc = dmi_present(q); + if (memcmp(q, "_SM_", 4) == 0 && q - p <= 0xFFE0) + rc = smbios_present(q); + else if (memcmp(q, "_DMI_", 5) == 0) + rc = dmi_present(q); + else + continue; if (!rc) { dmi_available = 1; dmi_iounmap(p, 0x10000); diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c index 47408e802ab..d10c9873dd9 100644 --- a/drivers/firmware/efivars.c +++ b/drivers/firmware/efivars.c @@ -435,12 +435,23 @@ efivar_attr_read(struct efivar_entry *entry, char *buf) if (status != EFI_SUCCESS) return -EIO; - if (var->Attributes & 0x1) + if (var->Attributes & EFI_VARIABLE_NON_VOLATILE) str += sprintf(str, "EFI_VARIABLE_NON_VOLATILE\n"); - if (var->Attributes & 0x2) + if (var->Attributes & EFI_VARIABLE_BOOTSERVICE_ACCESS) str += sprintf(str, "EFI_VARIABLE_BOOTSERVICE_ACCESS\n"); - if (var->Attributes & 0x4) + if (var->Attributes & EFI_VARIABLE_RUNTIME_ACCESS) str += sprintf(str, "EFI_VARIABLE_RUNTIME_ACCESS\n"); + if (var->Attributes & EFI_VARIABLE_HARDWARE_ERROR_RECORD) + str += sprintf(str, "EFI_VARIABLE_HARDWARE_ERROR_RECORD\n"); + if (var->Attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) + str += sprintf(str, + "EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS\n"); + if (var->Attributes & + EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) + str += sprintf(str, + "EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS\n"); + if (var->Attributes & EFI_VARIABLE_APPEND_WRITE) + str += sprintf(str, "EFI_VARIABLE_APPEND_WRITE\n"); return str - buf; } diff --git a/drivers/firmware/pcdp.c b/drivers/firmware/pcdp.c index 51e0e2d8fac..a330492e06f 100644 --- a/drivers/firmware/pcdp.c +++ b/drivers/firmware/pcdp.c @@ -95,7 +95,7 @@ efi_setup_pcdp_console(char *cmdline) if (efi.hcdp == EFI_INVALID_TABLE_ADDR) return -ENODEV; - pcdp = ioremap(efi.hcdp, 4096); + pcdp = early_ioremap(efi.hcdp, 4096); printk(KERN_INFO "PCDP: v%d at 0x%lx\n", pcdp->rev, efi.hcdp); if (strstr(cmdline, "console=hcdp")) { @@ -131,6 +131,6 @@ efi_setup_pcdp_console(char *cmdline) } out: - iounmap(pcdp); + early_iounmap(pcdp, 4096); return rc; } diff --git a/drivers/gpio/gpio-lpc32xx.c b/drivers/gpio/gpio-lpc32xx.c index 61c2d08d37b..e42e4b84016 100644 --- a/drivers/gpio/gpio-lpc32xx.c +++ b/drivers/gpio/gpio-lpc32xx.c @@ -304,6 +304,7 @@ static int lpc32xx_gpio_dir_output_p012(struct gpio_chip *chip, unsigned pin, { struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip); + __set_gpio_level_p012(group, pin, value); __set_gpio_dir_p012(group, pin, 0); return 0; @@ -314,6 +315,7 @@ static int lpc32xx_gpio_dir_output_p3(struct gpio_chip *chip, unsigned pin, { struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip); + __set_gpio_level_p3(group, pin, value); __set_gpio_dir_p3(group, pin, 0); return 0; @@ -322,6 +324,9 @@ static int lpc32xx_gpio_dir_output_p3(struct gpio_chip *chip, unsigned pin, static int lpc32xx_gpio_dir_out_always(struct gpio_chip *chip, unsigned pin, int value) { + struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip); + + __set_gpo_level_p3(group, pin, value); return 0; } diff --git a/drivers/gpio/gpio-timberdale.c b/drivers/gpio/gpio-timberdale.c index 031c6adf5b6..1a3e2b9b477 100644 --- a/drivers/gpio/gpio-timberdale.c +++ b/drivers/gpio/gpio-timberdale.c @@ -116,7 +116,7 @@ static void timbgpio_irq_disable(struct irq_data *d) unsigned long flags; spin_lock_irqsave(&tgpio->lock, flags); - tgpio->last_ier &= ~(1 << offset); + tgpio->last_ier &= ~(1UL << offset); iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER); spin_unlock_irqrestore(&tgpio->lock, flags); } @@ -128,7 +128,7 @@ static void timbgpio_irq_enable(struct irq_data *d) unsigned long flags; spin_lock_irqsave(&tgpio->lock, flags); - tgpio->last_ier |= 1 << offset; + tgpio->last_ier |= 1UL << offset; iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER); spin_unlock_irqrestore(&tgpio->lock, flags); } diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 5a75510d66b..112c16e0847 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -623,9 +623,11 @@ static ssize_t export_store(struct class *class, */ status = gpio_request(gpio, "sysfs"); - if (status < 0) + if (status < 0) { + if (status == -EPROBE_DEFER) + status = -ENODEV; goto done; - + } status = gpio_export(gpio, true); if (status < 0) gpio_free(gpio); @@ -1191,8 +1193,10 @@ int gpio_request(unsigned gpio, const char *label) spin_lock_irqsave(&gpio_lock, flags); - if (!gpio_is_valid(gpio)) + if (!gpio_is_valid(gpio)) { + status = -EINVAL; goto done; + } desc = &gpio_desc[gpio]; chip = desc->chip; if (chip == NULL) diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index c79870a75c2..4fd363f1656 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -1028,15 +1028,15 @@ void drm_mode_config_cleanup(struct drm_device *dev) fb->funcs->destroy(fb); } - list_for_each_entry_safe(crtc, ct, &dev->mode_config.crtc_list, head) { - crtc->funcs->destroy(crtc); - } - list_for_each_entry_safe(plane, plt, &dev->mode_config.plane_list, head) { plane->funcs->destroy(plane); } + list_for_each_entry_safe(crtc, ct, &dev->mode_config.crtc_list, head) { + crtc->funcs->destroy(crtc); + } + idr_remove_all(&dev->mode_config.crtc_idr); idr_destroy(&dev->mode_config.crtc_idr); } @@ -1981,7 +1981,7 @@ int drm_mode_cursor_ioctl(struct drm_device *dev, if (!drm_core_check_feature(dev, DRIVER_MODESET)) return -EINVAL; - if (!req->flags) + if (!req->flags || (~DRM_MODE_CURSOR_FLAGS & req->flags)) return -EINVAL; mutex_lock(&dev->mode_config.mutex); diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 6e38325d04a..9d9835a4fee 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -66,6 +66,8 @@ #define EDID_QUIRK_FIRST_DETAILED_PREFERRED (1 << 5) /* use +hsync +vsync for detailed mode */ #define EDID_QUIRK_DETAILED_SYNC_PP (1 << 6) +/* Force reduced-blanking timings for detailed modes */ +#define EDID_QUIRK_FORCE_REDUCED_BLANKING (1 << 7) struct detailed_mode_closure { struct drm_connector *connector; @@ -120,6 +122,9 @@ static struct edid_quirk { /* Samsung SyncMaster 22[5-6]BW */ { "SAM", 596, EDID_QUIRK_PREFER_LARGE_60 }, { "SAM", 638, EDID_QUIRK_PREFER_LARGE_60 }, + + /* ViewSonic VA2026w */ + { "VSC", 5020, EDID_QUIRK_FORCE_REDUCED_BLANKING }, }; /*** DDC fetch and block validation ***/ @@ -852,12 +857,19 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev, "Wrong Hsync/Vsync pulse width\n"); return NULL; } + + if (quirks & EDID_QUIRK_FORCE_REDUCED_BLANKING) { + mode = drm_cvt_mode(dev, hactive, vactive, 60, true, false, false); + if (!mode) + return NULL; + + goto set_size; + } + mode = drm_mode_create(dev); if (!mode) return NULL; - mode->type = DRM_MODE_TYPE_DRIVER; - if (quirks & EDID_QUIRK_135_CLOCK_TOO_HIGH) timing->pixel_clock = cpu_to_le16(1088); @@ -881,8 +893,6 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev, drm_mode_do_interlace_quirk(mode, pt); - drm_mode_set_name(mode); - if (quirks & EDID_QUIRK_DETAILED_SYNC_PP) { pt->misc |= DRM_EDID_PT_HSYNC_POSITIVE | DRM_EDID_PT_VSYNC_POSITIVE; } @@ -892,6 +902,7 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev, mode->flags |= (pt->misc & DRM_EDID_PT_VSYNC_POSITIVE) ? DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC; +set_size: mode->width_mm = pt->width_mm_lo | (pt->width_height_mm_hi & 0xf0) << 4; mode->height_mm = pt->height_mm_lo | (pt->width_height_mm_hi & 0xf) << 8; @@ -905,6 +916,9 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev, mode->height_mm = edid->height_cm * 10; } + mode->type = DRM_MODE_TYPE_DRIVER; + drm_mode_set_name(mode); + return mode; } diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 123de28f94e..b90abff1934 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -139,8 +139,11 @@ int drm_open(struct inode *inode, struct file *filp) retcode = drm_open_helper(inode, filp, dev); if (!retcode) { atomic_inc(&dev->counts[_DRM_STAT_OPENS]); - if (!dev->open_count++) + if (!dev->open_count++) { retcode = drm_setup(dev); + if (retcode) + dev->open_count--; + } } if (!retcode) { mutex_lock(&dev->struct_mutex); diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index ae8a64f9f84..89f3d4aed66 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -224,6 +224,7 @@ static const struct intel_device_info intel_sandybridge_d_info = { .has_bsd_ring = 1, .has_blt_ring = 1, .has_llc = 1, + .has_force_wake = 1, }; static const struct intel_device_info intel_sandybridge_m_info = { @@ -233,6 +234,7 @@ static const struct intel_device_info intel_sandybridge_m_info = { .has_bsd_ring = 1, .has_blt_ring = 1, .has_llc = 1, + .has_force_wake = 1, }; static const struct intel_device_info intel_ivybridge_d_info = { @@ -241,6 +243,7 @@ static const struct intel_device_info intel_ivybridge_d_info = { .has_bsd_ring = 1, .has_blt_ring = 1, .has_llc = 1, + .has_force_wake = 1, }; static const struct intel_device_info intel_ivybridge_m_info = { @@ -250,6 +253,7 @@ static const struct intel_device_info intel_ivybridge_m_info = { .has_bsd_ring = 1, .has_blt_ring = 1, .has_llc = 1, + .has_force_wake = 1, }; static const struct pci_device_id pciidlist[] = { /* aka */ @@ -993,6 +997,12 @@ MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL and additional rights"); +/* We give fast paths for the really cool registers */ +#define NEEDS_FORCE_WAKE(dev_priv, reg) \ + ((HAS_FORCE_WAKE((dev_priv)->dev)) && \ + ((reg) < 0x40000) && \ + ((reg) != FORCEWAKE)) + #define __i915_read(x, y) \ u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \ u##x val = 0; \ diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 5fabc6c31fe..45c5cf83fae 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -255,6 +255,7 @@ struct intel_device_info { u8 is_broadwater:1; u8 is_crestline:1; u8 is_ivybridge:1; + u8 has_force_wake:1; u8 has_fbc:1; u8 has_pipe_cxsr:1; u8 has_hotplug:1; @@ -405,6 +406,8 @@ typedef struct drm_i915_private { unsigned int lvds_use_ssc:1; unsigned int display_clock_mode:1; int lvds_ssc_freq; + unsigned int bios_lvds_val; /* initial [PCH_]LVDS reg val in VBIOS */ + unsigned int lvds_val; /* used for checking LVDS channel mode */ struct { int rate; int lanes; @@ -1051,6 +1054,8 @@ struct drm_i915_file_private { #define HAS_PCH_CPT(dev) (INTEL_PCH_TYPE(dev) == PCH_CPT) #define HAS_PCH_IBX(dev) (INTEL_PCH_TYPE(dev) == PCH_IBX) +#define HAS_FORCE_WAKE(dev) (INTEL_INFO(dev)->has_force_wake) + #include "i915_trace.h" /** @@ -1450,12 +1455,6 @@ void gen6_gt_force_wake_get(struct drm_i915_private *dev_priv); void gen6_gt_force_wake_put(struct drm_i915_private *dev_priv); int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv); -/* We give fast paths for the really cool registers */ -#define NEEDS_FORCE_WAKE(dev_priv, reg) \ - (((dev_priv)->info->gen >= 6) && \ - ((reg) < 0x40000) && \ - ((reg) != FORCEWAKE)) - #define __i915_read(x, y) \ u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 0d1e4b7b4b9..a230a93935b 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -928,6 +928,7 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data, } if (obj->gtt_space && + obj->tiling_mode == I915_TILING_NONE && obj->base.write_domain != I915_GEM_DOMAIN_CPU) { ret = i915_gem_object_pin(obj, 0, true); if (ret) @@ -3317,7 +3318,8 @@ i915_gem_object_pin(struct drm_i915_gem_object *obj, struct drm_i915_private *dev_priv = dev->dev_private; int ret; - BUG_ON(obj->pin_count == DRM_I915_GEM_OBJECT_MAX_PIN_COUNT); + if (WARN_ON(obj->pin_count == DRM_I915_GEM_OBJECT_MAX_PIN_COUNT)) + return -EBUSY; WARN_ON(i915_verify_lists(dev)); if (obj->gtt_space != NULL) { diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index de431942ded..d4417e3cc3d 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -707,6 +707,8 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev, total = 0; for (i = 0; i < count; i++) { struct drm_i915_gem_relocation_entry __user *user_relocs; + u64 invalid_offset = (u64)-1; + int j; user_relocs = (void __user *)(uintptr_t)exec[i].relocs_ptr; @@ -717,6 +719,25 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev, goto err; } + /* As we do not update the known relocation offsets after + * relocating (due to the complexities in lock handling), + * we need to mark them as invalid now so that we force the + * relocation processing next time. Just in case the target + * object is evicted and then rebound into its old + * presumed_offset before the next execbuffer - if that + * happened we would make the mistake of assuming that the + * relocations were valid. + */ + for (j = 0; j < exec[i].relocation_count; j++) { + if (copy_to_user(&user_relocs[j].presumed_offset, + &invalid_offset, + sizeof(invalid_offset))) { + ret = -EFAULT; + mutex_lock(&dev->struct_mutex); + goto err; + } + } + reloc_offset[i] = total; total += exec[i].relocation_count; } diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 26c67a78877..8bca2d2d804 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -530,6 +530,12 @@ static irqreturn_t ivybridge_irq_handler(DRM_IRQ_ARGS) if (de_iir & DE_GSE_IVB) intel_opregion_gse_intr(dev); + if (de_iir & DE_PIPEA_VBLANK_IVB) + drm_handle_vblank(dev, 0); + + if (de_iir & DE_PIPEB_VBLANK_IVB) + drm_handle_vblank(dev, 1); + if (de_iir & DE_PLANEA_FLIP_DONE_IVB) { intel_prepare_page_flip(dev, 0); intel_finish_page_flip_plane(dev, 0); @@ -540,12 +546,6 @@ static irqreturn_t ivybridge_irq_handler(DRM_IRQ_ARGS) intel_finish_page_flip_plane(dev, 1); } - if (de_iir & DE_PIPEA_VBLANK_IVB) - drm_handle_vblank(dev, 0); - - if (de_iir & DE_PIPEB_VBLANK_IVB) - drm_handle_vblank(dev, 1); - /* check event from PCH */ if (de_iir & DE_PCH_EVENT_IVB) { if (pch_iir & SDE_HOTPLUG_MASK_CPT) @@ -622,6 +622,12 @@ static irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS) if (de_iir & DE_GSE) intel_opregion_gse_intr(dev); + if (de_iir & DE_PIPEA_VBLANK) + drm_handle_vblank(dev, 0); + + if (de_iir & DE_PIPEB_VBLANK) + drm_handle_vblank(dev, 1); + if (de_iir & DE_PLANEA_FLIP_DONE) { intel_prepare_page_flip(dev, 0); intel_finish_page_flip_plane(dev, 0); @@ -632,12 +638,6 @@ static irqreturn_t ironlake_irq_handler(DRM_IRQ_ARGS) intel_finish_page_flip_plane(dev, 1); } - if (de_iir & DE_PIPEA_VBLANK) - drm_handle_vblank(dev, 0); - - if (de_iir & DE_PIPEB_VBLANK) - drm_handle_vblank(dev, 1); - /* check event from PCH */ if (de_iir & DE_PCH_EVENT) { if (pch_iir & hotplug_mask) @@ -2051,10 +2051,22 @@ static int i915_driver_irq_postinstall(struct drm_device *dev) hotplug_en |= HDMIC_HOTPLUG_INT_EN; if (dev_priv->hotplug_supported_mask & HDMID_HOTPLUG_INT_STATUS) hotplug_en |= HDMID_HOTPLUG_INT_EN; - if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS) - hotplug_en |= SDVOC_HOTPLUG_INT_EN; - if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS) - hotplug_en |= SDVOB_HOTPLUG_INT_EN; + if (IS_G4X(dev)) { + if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS_G4X) + hotplug_en |= SDVOC_HOTPLUG_INT_EN; + if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS_G4X) + hotplug_en |= SDVOB_HOTPLUG_INT_EN; + } else if (IS_GEN4(dev)) { + if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS_I965) + hotplug_en |= SDVOC_HOTPLUG_INT_EN; + if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS_I965) + hotplug_en |= SDVOB_HOTPLUG_INT_EN; + } else { + if (dev_priv->hotplug_supported_mask & SDVOC_HOTPLUG_INT_STATUS_I915) + hotplug_en |= SDVOC_HOTPLUG_INT_EN; + if (dev_priv->hotplug_supported_mask & SDVOB_HOTPLUG_INT_STATUS_I915) + hotplug_en |= SDVOB_HOTPLUG_INT_EN; + } if (dev_priv->hotplug_supported_mask & CRT_HOTPLUG_INT_STATUS) { hotplug_en |= CRT_HOTPLUG_INT_EN; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 29bfd899573..dde62bf3b1c 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -27,6 +27,8 @@ #define _PIPE(pipe, a, b) ((a) + (pipe)*((b)-(a))) +#define _MASKED_BIT_ENABLE(a) (((a) << 16) | (a)) + /* * The Bridge device's PCI config space has information about the * fb aperture size and the amount of pre-reserved memory. @@ -197,6 +199,14 @@ #define MI_DISPLAY_FLIP MI_INSTR(0x14, 2) #define MI_DISPLAY_FLIP_I915 MI_INSTR(0x14, 1) #define MI_DISPLAY_FLIP_PLANE(n) ((n) << 20) +/* IVB has funny definitions for which plane to flip. */ +#define MI_DISPLAY_FLIP_IVB_PLANE_A (0 << 19) +#define MI_DISPLAY_FLIP_IVB_PLANE_B (1 << 19) +#define MI_DISPLAY_FLIP_IVB_SPRITE_A (2 << 19) +#define MI_DISPLAY_FLIP_IVB_SPRITE_B (3 << 19) +#define MI_DISPLAY_FLIP_IVB_PLANE_C (4 << 19) +#define MI_DISPLAY_FLIP_IVB_SPRITE_C (5 << 19) + #define MI_SET_CONTEXT MI_INSTR(0x18, 0) #define MI_MM_SPACE_GTT (1<<8) #define MI_MM_SPACE_PHYSICAL (0<<8) @@ -425,6 +435,7 @@ * the enables for writing to the corresponding low bit. */ #define _3D_CHICKEN 0x02084 +#define _3D_CHICKEN_HIZ_PLANE_DISABLE_MSAA_4X_SNB (1 << 10) #define _3D_CHICKEN2 0x0208c /* Disables pipelining of read flushes past the SF-WIZ interface. * Required on all Ironlake steppings according to the B-Spec, but the @@ -437,6 +448,9 @@ # define VS_TIMER_DISPATCH (1 << 6) # define MI_FLUSH_ENABLE (1 << 12) +#define GEN6_GT_MODE 0x20d0 +#define GEN6_GT_MODE_HI (1 << 9) + #define GFX_MODE 0x02520 #define GFX_MODE_GEN7 0x0229c #define RING_MODE_GEN7(ring) ((ring)->mmio_base+0x29c) @@ -1483,14 +1497,20 @@ #define DPC_HOTPLUG_INT_STATUS (1 << 28) #define HDMID_HOTPLUG_INT_STATUS (1 << 27) #define DPD_HOTPLUG_INT_STATUS (1 << 27) +/* CRT/TV common between gen3+ */ #define CRT_HOTPLUG_INT_STATUS (1 << 11) #define TV_HOTPLUG_INT_STATUS (1 << 10) #define CRT_HOTPLUG_MONITOR_MASK (3 << 8) #define CRT_HOTPLUG_MONITOR_COLOR (3 << 8) #define CRT_HOTPLUG_MONITOR_MONO (2 << 8) #define CRT_HOTPLUG_MONITOR_NONE (0 << 8) -#define SDVOC_HOTPLUG_INT_STATUS (1 << 7) -#define SDVOB_HOTPLUG_INT_STATUS (1 << 6) +/* SDVO is different across gen3/4 */ +#define SDVOC_HOTPLUG_INT_STATUS_G4X (1 << 3) +#define SDVOB_HOTPLUG_INT_STATUS_G4X (1 << 2) +#define SDVOC_HOTPLUG_INT_STATUS_I965 (3 << 4) +#define SDVOB_HOTPLUG_INT_STATUS_I965 (3 << 2) +#define SDVOC_HOTPLUG_INT_STATUS_I915 (1 << 7) +#define SDVOB_HOTPLUG_INT_STATUS_I915 (1 << 6) /* SDVO port control */ #define SDVOB 0x61140 @@ -3015,6 +3035,8 @@ #define _PFA_CTL_1 0x68080 #define _PFB_CTL_1 0x68880 #define PF_ENABLE (1<<31) +#define PF_PIPE_SEL_MASK_IVB (3<<29) +#define PF_PIPE_SEL_IVB(pipe) ((pipe)<<29) #define PF_FILTER_MASK (3<<23) #define PF_FILTER_PROGRAMMED (0<<23) #define PF_FILTER_MED_3x3 (1<<23) diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index b48fc2a8410..a2c9e56c0c1 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -174,6 +174,28 @@ get_lvds_dvo_timing(const struct bdb_lvds_lfp_data *lvds_lfp_data, return (struct lvds_dvo_timing *)(entry + dvo_timing_offset); } +/* get lvds_fp_timing entry + * this function may return NULL if the corresponding entry is invalid + */ +static const struct lvds_fp_timing * +get_lvds_fp_timing(const struct bdb_header *bdb, + const struct bdb_lvds_lfp_data *data, + const struct bdb_lvds_lfp_data_ptrs *ptrs, + int index) +{ + size_t data_ofs = (const u8 *)data - (const u8 *)bdb; + u16 data_size = ((const u16 *)data)[-1]; /* stored in header */ + size_t ofs; + + if (index >= ARRAY_SIZE(ptrs->ptr)) + return NULL; + ofs = ptrs->ptr[index].fp_timing_offset; + if (ofs < data_ofs || + ofs + sizeof(struct lvds_fp_timing) > data_ofs + data_size) + return NULL; + return (const struct lvds_fp_timing *)((const u8 *)bdb + ofs); +} + /* Try to find integrated panel data */ static void parse_lfp_panel_data(struct drm_i915_private *dev_priv, @@ -183,6 +205,7 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv, const struct bdb_lvds_lfp_data *lvds_lfp_data; const struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs; const struct lvds_dvo_timing *panel_dvo_timing; + const struct lvds_fp_timing *fp_timing; struct drm_display_mode *panel_fixed_mode; int i, downclock; @@ -244,6 +267,19 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv, "Normal Clock %dKHz, downclock %dKHz\n", panel_fixed_mode->clock, 10*downclock); } + + fp_timing = get_lvds_fp_timing(bdb, lvds_lfp_data, + lvds_lfp_data_ptrs, + lvds_options->panel_type); + if (fp_timing) { + /* check the resolution, just to be sure */ + if (fp_timing->x_res == panel_fixed_mode->hdisplay && + fp_timing->y_res == panel_fixed_mode->vdisplay) { + dev_priv->bios_lvds_val = fp_timing->lvds_reg_val; + DRM_DEBUG_KMS("VBT initial LVDS value %x\n", + dev_priv->bios_lvds_val); + } + } } /* Try to find sdvo panel data */ @@ -459,12 +495,8 @@ parse_edp(struct drm_i915_private *dev_priv, struct bdb_header *bdb) edp = find_section(bdb, BDB_EDP); if (!edp) { - if (SUPPORTS_EDP(dev_priv->dev) && dev_priv->edp.support) { - DRM_DEBUG_KMS("No eDP BDB found but eDP panel " - "supported, assume %dbpp panel color " - "depth.\n", - dev_priv->edp.bpp); - } + if (SUPPORTS_EDP(dev_priv->dev) && dev_priv->edp.support) + DRM_DEBUG_KMS("No eDP BDB found but eDP panel supported.\n"); return; } @@ -617,9 +649,6 @@ init_vbt_defaults(struct drm_i915_private *dev_priv) dev_priv->lvds_use_ssc = 1; dev_priv->lvds_ssc_freq = intel_bios_ssc_frequency(dev, 1); DRM_DEBUG_KMS("Set default to SSC at %dMHz\n", dev_priv->lvds_ssc_freq); - - /* eDP data */ - dev_priv->edp.bpp = 18; } static int __init intel_no_opregion_vbt_callback(const struct dmi_system_id *id) diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 90b9793fd5d..342ffb7ec3d 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -266,6 +266,36 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector) return ret; } +static struct edid *intel_crt_get_edid(struct drm_connector *connector, + struct i2c_adapter *i2c) +{ + struct edid *edid; + + edid = drm_get_edid(connector, i2c); + + if (!edid && !intel_gmbus_is_forced_bit(i2c)) { + DRM_DEBUG_KMS("CRT GMBUS EDID read failed, retry using GPIO bit-banging\n"); + intel_gmbus_force_bit(i2c, true); + edid = drm_get_edid(connector, i2c); + intel_gmbus_force_bit(i2c, false); + } + + return edid; +} + +/* local version of intel_ddc_get_modes() to use intel_crt_get_edid() */ +static int intel_crt_ddc_get_modes(struct drm_connector *connector, + struct i2c_adapter *adapter) +{ + struct edid *edid; + + edid = intel_crt_get_edid(connector, adapter); + if (!edid) + return 0; + + return intel_connector_update_modes(connector, edid); +} + static bool intel_crt_detect_ddc(struct drm_connector *connector) { struct intel_crt *crt = intel_attached_crt(connector); @@ -279,7 +309,7 @@ static bool intel_crt_detect_ddc(struct drm_connector *connector) struct edid *edid; bool is_digital = false; - edid = drm_get_edid(connector, + edid = intel_crt_get_edid(connector, &dev_priv->gmbus[dev_priv->crt_ddc_pin].adapter); /* * This may be a DVI-I connector with a shared DDC @@ -477,13 +507,13 @@ static int intel_crt_get_modes(struct drm_connector *connector) struct drm_i915_private *dev_priv = dev->dev_private; int ret; - ret = intel_ddc_get_modes(connector, + ret = intel_crt_ddc_get_modes(connector, &dev_priv->gmbus[dev_priv->crt_ddc_pin].adapter); if (ret || !IS_G4X(dev)) return ret; /* Try to probe digital port for output in DVI-I -> VGA mode. */ - return intel_ddc_get_modes(connector, + return intel_crt_ddc_get_modes(connector, &dev_priv->gmbus[GMBUS_PORT_DPB].adapter); } diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index d4d162f6bab..3c9b9c57040 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -360,6 +360,27 @@ static const intel_limit_t intel_limits_ironlake_display_port = { .find_pll = intel_find_pll_ironlake_dp, }; +static bool is_dual_link_lvds(struct drm_i915_private *dev_priv, + unsigned int reg) +{ + unsigned int val; + + if (dev_priv->lvds_val) + val = dev_priv->lvds_val; + else { + /* BIOS should set the proper LVDS register value at boot, but + * in reality, it doesn't set the value when the lid is closed; + * we need to check "the value to be set" in VBT when LVDS + * register is uninitialized. + */ + val = I915_READ(reg); + if (!(val & ~LVDS_DETECTED)) + val = dev_priv->bios_lvds_val; + dev_priv->lvds_val = val; + } + return (val & LVDS_CLKB_POWER_MASK) == LVDS_CLKB_POWER_UP; +} + static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc, int refclk) { @@ -368,8 +389,7 @@ static const intel_limit_t *intel_ironlake_limit(struct drm_crtc *crtc, const intel_limit_t *limit; if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { - if ((I915_READ(PCH_LVDS) & LVDS_CLKB_POWER_MASK) == - LVDS_CLKB_POWER_UP) { + if (is_dual_link_lvds(dev_priv, PCH_LVDS)) { /* LVDS dual channel */ if (refclk == 100000) limit = &intel_limits_ironlake_dual_lvds_100m; @@ -397,8 +417,7 @@ static const intel_limit_t *intel_g4x_limit(struct drm_crtc *crtc) const intel_limit_t *limit; if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) { - if ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) == - LVDS_CLKB_POWER_UP) + if (is_dual_link_lvds(dev_priv, LVDS)) /* LVDS with dual channel */ limit = &intel_limits_g4x_dual_channel_lvds; else @@ -536,8 +555,7 @@ intel_find_best_PLL(const intel_limit_t *limit, struct drm_crtc *crtc, * reliably set up different single/dual channel state, if we * even can. */ - if ((I915_READ(LVDS) & LVDS_CLKB_POWER_MASK) == - LVDS_CLKB_POWER_UP) + if (is_dual_link_lvds(dev_priv, LVDS)) clock.p2 = limit->p2.p2_fast; else clock.p2 = limit->p2.p2_slow; @@ -1099,7 +1117,7 @@ static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv, enum pipe pipe, int reg) { u32 val = I915_READ(reg); - WARN(hdmi_pipe_enabled(dev_priv, val, pipe), + WARN(hdmi_pipe_enabled(dev_priv, pipe, val), "PCH HDMI (0x%08x) enabled on transcoder %c, should be disabled\n", reg, pipe_name(pipe)); } @@ -1116,13 +1134,13 @@ static void assert_pch_ports_disabled(struct drm_i915_private *dev_priv, reg = PCH_ADPA; val = I915_READ(reg); - WARN(adpa_pipe_enabled(dev_priv, val, pipe), + WARN(adpa_pipe_enabled(dev_priv, pipe, val), "PCH VGA enabled on transcoder %c, should be disabled\n", pipe_name(pipe)); reg = PCH_LVDS; val = I915_READ(reg); - WARN(lvds_pipe_enabled(dev_priv, val, pipe), + WARN(lvds_pipe_enabled(dev_priv, pipe, val), "PCH LVDS enabled on transcoder %c, should be disabled\n", pipe_name(pipe)); @@ -1487,7 +1505,7 @@ static void disable_pch_hdmi(struct drm_i915_private *dev_priv, enum pipe pipe, int reg) { u32 val = I915_READ(reg); - if (hdmi_pipe_enabled(dev_priv, val, pipe)) { + if (hdmi_pipe_enabled(dev_priv, pipe, val)) { DRM_DEBUG_KMS("Disabling pch HDMI %x on pipe %d\n", reg, pipe); I915_WRITE(reg, val & ~PORT_ENABLE); @@ -1509,12 +1527,12 @@ static void intel_disable_pch_ports(struct drm_i915_private *dev_priv, reg = PCH_ADPA; val = I915_READ(reg); - if (adpa_pipe_enabled(dev_priv, val, pipe)) + if (adpa_pipe_enabled(dev_priv, pipe, val)) I915_WRITE(reg, val & ~ADPA_DAC_ENABLE); reg = PCH_LVDS; val = I915_READ(reg); - if (lvds_pipe_enabled(dev_priv, val, pipe)) { + if (lvds_pipe_enabled(dev_priv, pipe, val)) { DRM_DEBUG_KMS("disable lvds on pipe %d val 0x%08x\n", pipe, val); I915_WRITE(reg, val & ~LVDS_PORT_EN); POSTING_READ(reg); @@ -2424,18 +2442,6 @@ static void intel_fdi_normal_train(struct drm_crtc *crtc) FDI_FE_ERRC_ENABLE); } -static void cpt_phase_pointer_enable(struct drm_device *dev, int pipe) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - u32 flags = I915_READ(SOUTH_CHICKEN1); - - flags |= FDI_PHASE_SYNC_OVR(pipe); - I915_WRITE(SOUTH_CHICKEN1, flags); /* once to unlock... */ - flags |= FDI_PHASE_SYNC_EN(pipe); - I915_WRITE(SOUTH_CHICKEN1, flags); /* then again to enable */ - POSTING_READ(SOUTH_CHICKEN1); -} - /* The FDI link training functions for ILK/Ibexpeak. */ static void ironlake_fdi_link_train(struct drm_crtc *crtc) { @@ -2586,9 +2592,6 @@ static void gen6_fdi_link_train(struct drm_crtc *crtc) POSTING_READ(reg); udelay(150); - if (HAS_PCH_CPT(dev)) - cpt_phase_pointer_enable(dev, pipe); - for (i = 0; i < 4; i++) { reg = FDI_TX_CTL(pipe); temp = I915_READ(reg); @@ -2707,9 +2710,6 @@ static void ivb_manual_fdi_link_train(struct drm_crtc *crtc) POSTING_READ(reg); udelay(150); - if (HAS_PCH_CPT(dev)) - cpt_phase_pointer_enable(dev, pipe); - for (i = 0; i < 4; i++) { reg = FDI_TX_CTL(pipe); temp = I915_READ(reg); @@ -2819,17 +2819,6 @@ static void ironlake_fdi_pll_enable(struct drm_crtc *crtc) } } -static void cpt_phase_pointer_disable(struct drm_device *dev, int pipe) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - u32 flags = I915_READ(SOUTH_CHICKEN1); - - flags &= ~(FDI_PHASE_SYNC_EN(pipe)); - I915_WRITE(SOUTH_CHICKEN1, flags); /* once to disable... */ - flags &= ~(FDI_PHASE_SYNC_OVR(pipe)); - I915_WRITE(SOUTH_CHICKEN1, flags); /* then again to lock */ - POSTING_READ(SOUTH_CHICKEN1); -} static void ironlake_fdi_disable(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; @@ -2859,8 +2848,6 @@ static void ironlake_fdi_disable(struct drm_crtc *crtc) I915_WRITE(FDI_RX_CHICKEN(pipe), I915_READ(FDI_RX_CHICKEN(pipe) & ~FDI_RX_PHASE_SYNC_POINTER_EN)); - } else if (HAS_PCH_CPT(dev)) { - cpt_phase_pointer_disable(dev, pipe); } /* still set train pattern 1 */ @@ -2908,18 +2895,37 @@ static void intel_clear_scanline_wait(struct drm_device *dev) I915_WRITE_CTL(ring, tmp); } +static bool intel_crtc_has_pending_flip(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + unsigned long flags; + bool pending; + + if (atomic_read(&dev_priv->mm.wedged)) + return false; + + spin_lock_irqsave(&dev->event_lock, flags); + pending = to_intel_crtc(crtc)->unpin_work != NULL; + spin_unlock_irqrestore(&dev->event_lock, flags); + + return pending; +} + static void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc) { - struct drm_i915_gem_object *obj; - struct drm_i915_private *dev_priv; + struct drm_device *dev = crtc->dev; + struct drm_i915_private *dev_priv = dev->dev_private; if (crtc->fb == NULL) return; - obj = to_intel_framebuffer(crtc->fb)->obj; - dev_priv = crtc->dev->dev_private; wait_event(dev_priv->pending_flip_queue, - atomic_read(&obj->pending_flip) == 0); + !intel_crtc_has_pending_flip(crtc)); + + mutex_lock(&dev->struct_mutex); + intel_finish_fb(crtc->fb); + mutex_unlock(&dev->struct_mutex); } static bool intel_crtc_driving_pch(struct drm_crtc *crtc) @@ -3095,7 +3101,11 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc) * as some pre-programmed values are broken, * e.g. x201. */ - I915_WRITE(PF_CTL(pipe), PF_ENABLE | PF_FILTER_MED_3x3); + if (IS_IVYBRIDGE(dev)) + I915_WRITE(PF_CTL(pipe), PF_ENABLE | PF_FILTER_MED_3x3 | + PF_PIPE_SEL_IVB(pipe)); + else + I915_WRITE(PF_CTL(pipe), PF_ENABLE | PF_FILTER_MED_3x3); I915_WRITE(PF_WIN_POS(pipe), dev_priv->pch_pf_pos); I915_WRITE(PF_WIN_SZ(pipe), dev_priv->pch_pf_size); } @@ -3381,23 +3391,6 @@ static void intel_crtc_disable(struct drm_crtc *crtc) struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; struct drm_device *dev = crtc->dev; - /* Flush any pending WAITs before we disable the pipe. Note that - * we need to drop the struct_mutex in order to acquire it again - * during the lowlevel dpms routines around a couple of the - * operations. It does not look trivial nor desirable to move - * that locking higher. So instead we leave a window for the - * submission of further commands on the fb before we can actually - * disable it. This race with userspace exists anyway, and we can - * only rely on the pipe being disabled by userspace after it - * receives the hotplug notification and has flushed any pending - * batches. - */ - if (crtc->fb) { - mutex_lock(&dev->struct_mutex); - intel_finish_fb(crtc->fb); - mutex_unlock(&dev->struct_mutex); - } - crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF); assert_plane_disabled(dev->dev_private, to_intel_crtc(crtc)->plane); assert_pipe_disabled(dev->dev_private, to_intel_crtc(crtc)->pipe); @@ -4982,17 +4975,6 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc, continue; } - if (intel_encoder->type == INTEL_OUTPUT_EDP) { - /* Use VBT settings if we have an eDP panel */ - unsigned int edp_bpc = dev_priv->edp.bpp / 3; - - if (edp_bpc < display_bpc) { - DRM_DEBUG_KMS("clamping display bpc (was %d) to eDP (%d)\n", display_bpc, edp_bpc); - display_bpc = edp_bpc; - } - continue; - } - /* Not one of the known troublemakers, check the EDID */ list_for_each_entry(connector, &dev->mode_config.connector_list, head) { @@ -5007,6 +4989,17 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc, } } + if (intel_encoder->type == INTEL_OUTPUT_EDP) { + /* Use VBT settings if we have an eDP panel */ + unsigned int edp_bpc = dev_priv->edp.bpp / 3; + + if (edp_bpc && edp_bpc < display_bpc) { + DRM_DEBUG_KMS("clamping display bpc (was %d) to eDP (%d)\n", display_bpc, edp_bpc); + display_bpc = edp_bpc; + } + continue; + } + /* * HDMI is either 12 or 8, so if the display lets 10bpc sneak * through, clamp it down. (Note: >12bpc will be caught below.) @@ -5329,7 +5322,7 @@ static int i9xx_crtc_mode_set(struct drm_crtc *crtc, /* default to 8bpc */ pipeconf &= ~(PIPECONF_BPP_MASK | PIPECONF_DITHER_EN); if (is_dp) { - if (mode->private_flags & INTEL_MODE_DP_FORCE_6BPC) { + if (adjusted_mode->private_flags & INTEL_MODE_DP_FORCE_6BPC) { pipeconf |= PIPECONF_BPP_6 | PIPECONF_DITHER_EN | PIPECONF_DITHER_TYPE_SP; @@ -5793,7 +5786,7 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, /* determine panel color depth */ temp = I915_READ(PIPECONF(pipe)); temp &= ~PIPE_BPC_MASK; - dither = intel_choose_pipe_bpp_dither(crtc, &pipe_bpp, mode); + dither = intel_choose_pipe_bpp_dither(crtc, &pipe_bpp, adjusted_mode); switch (pipe_bpp) { case 18: temp |= PIPE_6BPC; @@ -7286,9 +7279,8 @@ static void do_intel_finish_page_flip(struct drm_device *dev, atomic_clear_mask(1 << intel_crtc->plane, &obj->pending_flip.counter); - if (atomic_read(&obj->pending_flip) == 0) - wake_up(&dev_priv->pending_flip_queue); + wake_up(&dev_priv->pending_flip_queue); schedule_work(&work->work); trace_i915_flip_complete(intel_crtc->plane, work->pending_flip_obj); @@ -7340,14 +7332,14 @@ static int intel_gen2_queue_flip(struct drm_device *dev, ret = intel_pin_and_fence_fb_obj(dev, obj, LP_RING(dev_priv)); if (ret) - goto out; + goto err; /* Offset into the new buffer for cases of shared fbs between CRTCs */ offset = crtc->y * fb->pitches[0] + crtc->x * fb->bits_per_pixel/8; ret = BEGIN_LP_RING(6); if (ret) - goto out; + goto err_unpin; /* Can't queue multiple flips, so wait for the previous * one to finish before executing the next. @@ -7364,7 +7356,11 @@ static int intel_gen2_queue_flip(struct drm_device *dev, OUT_RING(obj->gtt_offset + offset); OUT_RING(0); /* aux display base address, unused */ ADVANCE_LP_RING(); -out: + return 0; + +err_unpin: + intel_unpin_fb_obj(obj); +err: return ret; } @@ -7381,14 +7377,14 @@ static int intel_gen3_queue_flip(struct drm_device *dev, ret = intel_pin_and_fence_fb_obj(dev, obj, LP_RING(dev_priv)); if (ret) - goto out; + goto err; /* Offset into the new buffer for cases of shared fbs between CRTCs */ offset = crtc->y * fb->pitches[0] + crtc->x * fb->bits_per_pixel/8; ret = BEGIN_LP_RING(6); if (ret) - goto out; + goto err_unpin; if (intel_crtc->plane) flip_mask = MI_WAIT_FOR_PLANE_B_FLIP; @@ -7403,7 +7399,11 @@ static int intel_gen3_queue_flip(struct drm_device *dev, OUT_RING(MI_NOOP); ADVANCE_LP_RING(); -out: + return 0; + +err_unpin: + intel_unpin_fb_obj(obj); +err: return ret; } @@ -7419,11 +7419,11 @@ static int intel_gen4_queue_flip(struct drm_device *dev, ret = intel_pin_and_fence_fb_obj(dev, obj, LP_RING(dev_priv)); if (ret) - goto out; + goto err; ret = BEGIN_LP_RING(4); if (ret) - goto out; + goto err_unpin; /* i965+ uses the linear or tiled offsets from the * Display Registers (which do not change across a page-flip) @@ -7442,7 +7442,11 @@ static int intel_gen4_queue_flip(struct drm_device *dev, pipesrc = I915_READ(PIPESRC(intel_crtc->pipe)) & 0x0fff0fff; OUT_RING(pf | pipesrc); ADVANCE_LP_RING(); -out: + return 0; + +err_unpin: + intel_unpin_fb_obj(obj); +err: return ret; } @@ -7458,11 +7462,11 @@ static int intel_gen6_queue_flip(struct drm_device *dev, ret = intel_pin_and_fence_fb_obj(dev, obj, LP_RING(dev_priv)); if (ret) - goto out; + goto err; ret = BEGIN_LP_RING(4); if (ret) - goto out; + goto err_unpin; OUT_RING(MI_DISPLAY_FLIP | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); @@ -7479,7 +7483,11 @@ static int intel_gen6_queue_flip(struct drm_device *dev, pipesrc = I915_READ(PIPESRC(intel_crtc->pipe)) & 0x0fff0fff; OUT_RING(pf | pipesrc); ADVANCE_LP_RING(); -out: + return 0; + +err_unpin: + intel_unpin_fb_obj(obj); +err: return ret; } @@ -7497,22 +7505,43 @@ static int intel_gen7_queue_flip(struct drm_device *dev, struct drm_i915_private *dev_priv = dev->dev_private; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_ring_buffer *ring = &dev_priv->ring[BCS]; + uint32_t plane_bit = 0; int ret; ret = intel_pin_and_fence_fb_obj(dev, obj, ring); if (ret) - goto out; + goto err; + + switch(intel_crtc->plane) { + case PLANE_A: + plane_bit = MI_DISPLAY_FLIP_IVB_PLANE_A; + break; + case PLANE_B: + plane_bit = MI_DISPLAY_FLIP_IVB_PLANE_B; + break; + case PLANE_C: + plane_bit = MI_DISPLAY_FLIP_IVB_PLANE_C; + break; + default: + WARN_ONCE(1, "unknown plane in flip command\n"); + ret = -ENODEV; + goto err_unpin; + } ret = intel_ring_begin(ring, 4); if (ret) - goto out; + goto err_unpin; - intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | (intel_crtc->plane << 19)); + intel_ring_emit(ring, MI_DISPLAY_FLIP_I915 | plane_bit); intel_ring_emit(ring, (fb->pitches[0] | obj->tiling_mode)); intel_ring_emit(ring, (obj->gtt_offset)); intel_ring_emit(ring, (MI_NOOP)); intel_ring_advance(ring); -out: + return 0; + +err_unpin: + intel_unpin_fb_obj(obj); +err: return ret; } @@ -8563,6 +8592,10 @@ static void gen6_init_clock_gating(struct drm_device *dev) I915_READ(ILK_DISPLAY_CHICKEN2) | ILK_ELPIN_409_SELECT); + /* WaDisableHiZPlanesWhenMSAAEnabled */ + I915_WRITE(_3D_CHICKEN, + _MASKED_BIT_ENABLE(_3D_CHICKEN_HIZ_PLANE_DISABLE_MSAA_4X_SNB)); + I915_WRITE(WM3_LP_ILK, 0); I915_WRITE(WM2_LP_ILK, 0); I915_WRITE(WM1_LP_ILK, 0); @@ -8611,6 +8644,11 @@ static void gen6_init_clock_gating(struct drm_device *dev) DISPPLANE_TRICKLE_FEED_DISABLE); intel_flush_display_plane(dev_priv, pipe); } + + /* The default value should be 0x200 according to docs, but the two + * platforms I checked have a 0 for this. (Maybe BIOS overrides?) */ + I915_WRITE(GEN6_GT_MODE, 0xffff << 16); + I915_WRITE(GEN6_GT_MODE, GEN6_GT_MODE_HI << 16 | GEN6_GT_MODE_HI); } static void gen7_setup_fixed_func_scheduler(struct drm_i915_private *dev_priv) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 68624218d05..069725c5c1a 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -712,8 +712,8 @@ intel_dp_mode_fixup(struct drm_encoder *encoder, struct drm_display_mode *mode, bpp = adjusted_mode->private_flags & INTEL_MODE_DP_FORCE_6BPC ? 18 : 24; - for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) { - for (clock = 0; clock <= max_clock; clock++) { + for (clock = 0; clock <= max_clock; clock++) { + for (lane_count = 1; lane_count <= max_lane_count; lane_count <<= 1) { int link_avail = intel_dp_max_data_rate(intel_dp_link_clock(bws[clock]), lane_count); if (intel_dp_link_required(mode->clock, bpp) @@ -1156,10 +1156,14 @@ static void ironlake_edp_panel_off(struct intel_dp *intel_dp) WARN(!intel_dp->want_panel_vdd, "Need VDD to turn off panel\n"); pp = ironlake_get_pp_control(dev_priv); - pp &= ~(POWER_TARGET_ON | PANEL_POWER_RESET | EDP_BLC_ENABLE); + /* We need to switch off panel power _and_ force vdd, for otherwise some + * panels get very unhappy and cease to work. */ + pp &= ~(POWER_TARGET_ON | EDP_FORCE_VDD | PANEL_POWER_RESET | EDP_BLC_ENABLE); I915_WRITE(PCH_PP_CONTROL, pp); POSTING_READ(PCH_PP_CONTROL); + intel_dp->want_panel_vdd = false; + ironlake_wait_panel_off(intel_dp); } @@ -1269,11 +1273,9 @@ static void intel_dp_prepare(struct drm_encoder *encoder) * ensure that we have vdd while we switch off the panel. */ ironlake_edp_panel_vdd_on(intel_dp); ironlake_edp_backlight_off(intel_dp); - ironlake_edp_panel_off(intel_dp); - intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); + ironlake_edp_panel_off(intel_dp); intel_dp_link_down(intel_dp); - ironlake_edp_panel_vdd_off(intel_dp, false); } static void intel_dp_commit(struct drm_encoder *encoder) @@ -1308,11 +1310,9 @@ intel_dp_dpms(struct drm_encoder *encoder, int mode) /* Switching the panel off requires vdd. */ ironlake_edp_panel_vdd_on(intel_dp); ironlake_edp_backlight_off(intel_dp); - ironlake_edp_panel_off(intel_dp); - intel_dp_sink_dpms(intel_dp, mode); + ironlake_edp_panel_off(intel_dp); intel_dp_link_down(intel_dp); - ironlake_edp_panel_vdd_off(intel_dp, false); if (is_cpu_edp(intel_dp)) ironlake_edp_pll_off(encoder); diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 715afa15302..cd623e899f5 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -247,12 +247,12 @@ struct dip_infoframe { uint16_t bottom_bar_start; uint16_t left_bar_end; uint16_t right_bar_start; - } avi; + } __attribute__ ((packed)) avi; struct { uint8_t vn[8]; uint8_t pd[16]; uint8_t sdi; - } spd; + } __attribute__ ((packed)) spd; uint8_t payload[27]; } __attribute__ ((packed)) body; } __attribute__((packed)); @@ -288,6 +288,8 @@ struct intel_fbc_work { int interval; }; +int intel_connector_update_modes(struct drm_connector *connector, + struct edid *edid); int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *adapter); extern bool intel_ddc_probe(struct intel_encoder *intel_encoder, int ddc_bus); diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 2d7f47b56b6..c60100d48ce 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -138,14 +138,17 @@ static void i9xx_write_infoframe(struct drm_encoder *encoder, I915_WRITE(VIDEO_DIP_CTL, VIDEO_DIP_ENABLE | val | port | flags); + mmiowb(); for (i = 0; i < len; i += 4) { I915_WRITE(VIDEO_DIP_DATA, *data); data++; } + mmiowb(); flags |= intel_infoframe_flags(frame); I915_WRITE(VIDEO_DIP_CTL, VIDEO_DIP_ENABLE | val | port | flags); + POSTING_READ(VIDEO_DIP_CTL); } static void ironlake_write_infoframe(struct drm_encoder *encoder, @@ -168,14 +171,17 @@ static void ironlake_write_infoframe(struct drm_encoder *encoder, I915_WRITE(reg, VIDEO_DIP_ENABLE | val | flags); + mmiowb(); for (i = 0; i < len; i += 4) { I915_WRITE(TVIDEO_DIP_DATA(intel_crtc->pipe), *data); data++; } + mmiowb(); flags |= intel_infoframe_flags(frame); I915_WRITE(reg, VIDEO_DIP_ENABLE | val | flags); + POSTING_READ(reg); } static void intel_set_infoframe(struct drm_encoder *encoder, struct dip_infoframe *frame) @@ -271,7 +277,7 @@ static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode) u32 temp; u32 enable_bits = SDVO_ENABLE; - if (intel_hdmi->has_audio) + if (intel_hdmi->has_audio || mode != DRM_MODE_DPMS_ON) enable_bits |= SDVO_AUDIO_ENABLE; temp = I915_READ(intel_hdmi->sdvox_reg); @@ -549,10 +555,13 @@ void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) if (!HAS_PCH_SPLIT(dev)) { intel_hdmi->write_infoframe = i9xx_write_infoframe; I915_WRITE(VIDEO_DIP_CTL, 0); + POSTING_READ(VIDEO_DIP_CTL); } else { intel_hdmi->write_infoframe = ironlake_write_infoframe; - for_each_pipe(i) + for_each_pipe(i) { I915_WRITE(TVIDEO_DIP_CTL(i), 0); + POSTING_READ(TVIDEO_DIP_CTL(i)); + } } drm_encoder_helper_add(&intel_encoder->base, &intel_hdmi_helper_funcs); diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 9fadd643181..a8b28c493a8 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -777,6 +777,22 @@ static const struct dmi_system_id intel_no_lvds[] = { DMI_MATCH(DMI_BOARD_NAME, "MS-7469"), }, }, + { + .callback = intel_no_lvds_dmi_callback, + .ident = "Gigabyte GA-D525TUD", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co., Ltd."), + DMI_MATCH(DMI_BOARD_NAME, "D525TUD"), + }, + }, + { + .callback = intel_no_lvds_dmi_callback, + .ident = "Supermicro X7SPA-H", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Supermicro"), + DMI_MATCH(DMI_PRODUCT_NAME, "X7SPA-H"), + }, + }, { } /* terminating entry */ }; diff --git a/drivers/gpu/drm/i915/intel_modes.c b/drivers/gpu/drm/i915/intel_modes.c index d1928e79d9b..9a2b27031a4 100644 --- a/drivers/gpu/drm/i915/intel_modes.c +++ b/drivers/gpu/drm/i915/intel_modes.c @@ -59,6 +59,25 @@ bool intel_ddc_probe(struct intel_encoder *intel_encoder, int ddc_bus) return i2c_transfer(&dev_priv->gmbus[ddc_bus].adapter, msgs, 2) == 2; } +/** + * intel_connector_update_modes - update connector from edid + * @connector: DRM connector device to use + * @edid: previously read EDID information + */ +int intel_connector_update_modes(struct drm_connector *connector, + struct edid *edid) +{ + int ret; + + drm_mode_connector_update_edid_property(connector, edid); + ret = drm_add_edid_modes(connector, edid); + drm_edid_to_eld(connector, edid); + connector->display_info.raw_edid = NULL; + kfree(edid); + + return ret; +} + /** * intel_ddc_get_modes - get modelist from monitor * @connector: DRM connector device to use @@ -70,18 +89,12 @@ int intel_ddc_get_modes(struct drm_connector *connector, struct i2c_adapter *adapter) { struct edid *edid; - int ret = 0; edid = drm_get_edid(connector, adapter); - if (edid) { - drm_mode_connector_update_edid_property(connector, edid); - ret = drm_add_edid_modes(connector, edid); - drm_edid_to_eld(connector, edid); - connector->display_info.raw_edid = NULL; - kfree(edid); - } + if (!edid) + return 0; - return ret; + return intel_connector_update_modes(connector, edid); } static const struct drm_prop_enum_list force_audio_names[] = { diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index 80b331c322f..5ba5e66fa07 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c @@ -427,9 +427,17 @@ static int intel_overlay_off(struct intel_overlay *overlay) OUT_RING(flip_addr); OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); /* turn overlay off */ - OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_OFF); - OUT_RING(flip_addr); - OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); + if (IS_I830(dev)) { + /* Workaround: Don't disable the overlay fully, since otherwise + * it dies on the next OVERLAY_ON cmd. */ + OUT_RING(MI_NOOP); + OUT_RING(MI_NOOP); + OUT_RING(MI_NOOP); + } else { + OUT_RING(MI_OVERLAY_FLIP | MI_OVERLAY_OFF); + OUT_RING(flip_addr); + OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); + } ADVANCE_LP_RING(); return intel_overlay_do_wait_request(overlay, request, diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 302d3d54fb4..c17325ce379 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -249,10 +249,15 @@ u32 intel_ring_get_active_head(struct intel_ring_buffer *ring) static int init_ring_common(struct intel_ring_buffer *ring) { - drm_i915_private_t *dev_priv = ring->dev->dev_private; + struct drm_device *dev = ring->dev; + drm_i915_private_t *dev_priv = dev->dev_private; struct drm_i915_gem_object *obj = ring->obj; + int ret = 0; u32 head; + if (HAS_FORCE_WAKE(dev)) + gen6_gt_force_wake_get(dev_priv); + /* Stop the ring if it's running. */ I915_WRITE_CTL(ring, 0); I915_WRITE_HEAD(ring, 0); @@ -290,9 +295,9 @@ static int init_ring_common(struct intel_ring_buffer *ring) | RING_VALID); /* If the head is still not zero, the ring is dead */ - if ((I915_READ_CTL(ring) & RING_VALID) == 0 || - I915_READ_START(ring) != obj->gtt_offset || - (I915_READ_HEAD(ring) & HEAD_ADDR) != 0) { + if (wait_for((I915_READ_CTL(ring) & RING_VALID) != 0 && + I915_READ_START(ring) == obj->gtt_offset && + (I915_READ_HEAD(ring) & HEAD_ADDR) == 0, 50)) { DRM_ERROR("%s initialization failed " "ctl %08x head %08x tail %08x start %08x\n", ring->name, @@ -300,7 +305,8 @@ static int init_ring_common(struct intel_ring_buffer *ring) I915_READ_HEAD(ring), I915_READ_TAIL(ring), I915_READ_START(ring)); - return -EIO; + ret = -EIO; + goto out; } if (!drm_core_check_feature(ring->dev, DRIVER_MODESET)) @@ -312,7 +318,11 @@ static int init_ring_common(struct intel_ring_buffer *ring) ring->last_retired_head = -1; } - return 0; +out: + if (HAS_FORCE_WAKE(dev)) + gen6_gt_force_wake_put(dev_priv); + + return ret; } static int diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index eea58c6cb05..1b6b1570f4c 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -868,31 +868,38 @@ static void intel_sdvo_dump_hdmi_buf(struct intel_sdvo *intel_sdvo) } #endif -static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo) +static bool intel_sdvo_write_infoframe(struct intel_sdvo *intel_sdvo, + unsigned if_index, uint8_t tx_rate, + uint8_t *data, unsigned length) { - struct dip_infoframe avi_if = { - .type = DIP_TYPE_AVI, - .ver = DIP_VERSION_AVI, - .len = DIP_LEN_AVI, - }; - uint8_t tx_rate = SDVO_HBUF_TX_VSYNC; - uint8_t set_buf_index[2] = { 1, 0 }; - uint64_t *data = (uint64_t *)&avi_if; - unsigned i; - - intel_dip_infoframe_csum(&avi_if); + uint8_t set_buf_index[2] = { if_index, 0 }; + uint8_t hbuf_size, tmp[8]; + int i; if (!intel_sdvo_set_value(intel_sdvo, SDVO_CMD_SET_HBUF_INDEX, set_buf_index, 2)) return false; - for (i = 0; i < sizeof(avi_if); i += 8) { + if (!intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_HBUF_INFO, + &hbuf_size, 1)) + return false; + + /* Buffer size is 0 based, hooray! */ + hbuf_size++; + + DRM_DEBUG_KMS("writing sdvo hbuf: %i, hbuf_size %i, hbuf_size: %i\n", + if_index, length, hbuf_size); + + for (i = 0; i < hbuf_size; i += 8) { + memset(tmp, 0, 8); + if (i < length) + memcpy(tmp, data + i, min_t(unsigned, 8, length - i)); + if (!intel_sdvo_set_value(intel_sdvo, SDVO_CMD_SET_HBUF_DATA, - data, 8)) + tmp, 8)) return false; - data++; } return intel_sdvo_set_value(intel_sdvo, @@ -900,6 +907,28 @@ static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo) &tx_rate, 1); } +static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo) +{ + struct dip_infoframe avi_if = { + .type = DIP_TYPE_AVI, + .ver = DIP_VERSION_AVI, + .len = DIP_LEN_AVI, + }; + uint8_t sdvo_data[4 + sizeof(avi_if.body.avi)]; + + intel_dip_infoframe_csum(&avi_if); + + /* sdvo spec says that the ecc is handled by the hw, and it looks like + * we must not send the ecc field, either. */ + memcpy(sdvo_data, &avi_if, 3); + sdvo_data[3] = avi_if.checksum; + memcpy(&sdvo_data[4], &avi_if.body, sizeof(avi_if.body.avi)); + + return intel_sdvo_write_infoframe(intel_sdvo, SDVO_HBUF_INDEX_AVI_IF, + SDVO_HBUF_TX_VSYNC, + sdvo_data, sizeof(sdvo_data)); +} + static bool intel_sdvo_set_tv_format(struct intel_sdvo *intel_sdvo) { struct intel_sdvo_tv_format format; @@ -2499,6 +2528,7 @@ bool intel_sdvo_init(struct drm_device *dev, int sdvo_reg) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_encoder *intel_encoder; struct intel_sdvo *intel_sdvo; + u32 hotplug_mask; int i; intel_sdvo = kzalloc(sizeof(struct intel_sdvo), GFP_KERNEL); @@ -2529,10 +2559,17 @@ bool intel_sdvo_init(struct drm_device *dev, int sdvo_reg) } } - if (IS_SDVOB(sdvo_reg)) - dev_priv->hotplug_supported_mask |= SDVOB_HOTPLUG_INT_STATUS; - else - dev_priv->hotplug_supported_mask |= SDVOC_HOTPLUG_INT_STATUS; + hotplug_mask = 0; + if (IS_G4X(dev)) { + hotplug_mask = IS_SDVOB(sdvo_reg) ? + SDVOB_HOTPLUG_INT_STATUS_G4X : SDVOC_HOTPLUG_INT_STATUS_G4X; + } else if (IS_GEN4(dev)) { + hotplug_mask = IS_SDVOB(sdvo_reg) ? + SDVOB_HOTPLUG_INT_STATUS_I965 : SDVOC_HOTPLUG_INT_STATUS_I965; + } else { + hotplug_mask = IS_SDVOB(sdvo_reg) ? + SDVOB_HOTPLUG_INT_STATUS_I915 : SDVOC_HOTPLUG_INT_STATUS_I915; + } drm_encoder_helper_add(&intel_encoder->base, &intel_sdvo_helper_funcs); @@ -2540,14 +2577,6 @@ bool intel_sdvo_init(struct drm_device *dev, int sdvo_reg) if (!intel_sdvo_get_capabilities(intel_sdvo, &intel_sdvo->caps)) goto err; - /* Set up hotplug command - note paranoia about contents of reply. - * We assume that the hardware is in a sane state, and only touch - * the bits we think we understand. - */ - intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_ACTIVE_HOT_PLUG, - &intel_sdvo->hotplug_active, 2); - intel_sdvo->hotplug_active[0] &= ~0x3; - if (intel_sdvo_output_setup(intel_sdvo, intel_sdvo->caps.output_flags) != true) { DRM_DEBUG_KMS("SDVO output failed to setup on SDVO%c\n", @@ -2555,6 +2584,12 @@ bool intel_sdvo_init(struct drm_device *dev, int sdvo_reg) goto err; } + /* Only enable the hotplug irq if we need it, to work around noisy + * hotplug lines. + */ + if (intel_sdvo->hotplug_active[0]) + dev_priv->hotplug_supported_mask |= hotplug_mask; + intel_sdvo_select_ddc_bus(dev_priv, intel_sdvo, sdvo_reg); /* Set the input timing to the screen. Assume always input 0. */ diff --git a/drivers/gpu/drm/i915/intel_sdvo_regs.h b/drivers/gpu/drm/i915/intel_sdvo_regs.h index 9d030142ee4..770bdd6ecd9 100644 --- a/drivers/gpu/drm/i915/intel_sdvo_regs.h +++ b/drivers/gpu/drm/i915/intel_sdvo_regs.h @@ -708,6 +708,8 @@ struct intel_sdvo_enhancements_arg { #define SDVO_CMD_SET_AUDIO_STAT 0x91 #define SDVO_CMD_GET_AUDIO_STAT 0x92 #define SDVO_CMD_SET_HBUF_INDEX 0x93 + #define SDVO_HBUF_INDEX_ELD 0 + #define SDVO_HBUF_INDEX_AVI_IF 1 #define SDVO_CMD_GET_HBUF_INDEX 0x94 #define SDVO_CMD_GET_HBUF_INFO 0x95 #define SDVO_CMD_SET_HBUF_AV_SPLIT 0x96 diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index a85e112863d..f233b8fe2da 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -586,7 +586,7 @@ nouveau_display_dumb_create(struct drm_file *file_priv, struct drm_device *dev, args->size = args->pitch * args->height; args->size = roundup(args->size, PAGE_SIZE); - ret = nouveau_gem_new(dev, args->size, 0, TTM_PL_FLAG_VRAM, 0, 0, &bo); + ret = nouveau_gem_new(dev, args->size, 0, NOUVEAU_GEM_DOMAIN_VRAM, 0, 0, &bo); if (ret) return ret; diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c index 4f2030bd567..05091c22a03 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.c +++ b/drivers/gpu/drm/nouveau/nouveau_drv.c @@ -186,11 +186,13 @@ nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state) if (dev->switch_power_state == DRM_SWITCH_POWER_OFF) return 0; - NV_INFO(dev, "Disabling display...\n"); - nouveau_display_fini(dev); + if (dev->mode_config.num_crtc) { + NV_INFO(dev, "Disabling display...\n"); + nouveau_display_fini(dev); - NV_INFO(dev, "Disabling fbcon...\n"); - nouveau_fbcon_set_suspend(dev, 1); + NV_INFO(dev, "Disabling fbcon...\n"); + nouveau_fbcon_set_suspend(dev, 1); + } NV_INFO(dev, "Unpinning framebuffer(s)...\n"); list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { @@ -363,10 +365,12 @@ nouveau_pci_resume(struct pci_dev *pdev) NV_ERROR(dev, "Could not pin/map cursor.\n"); } - nouveau_fbcon_set_suspend(dev, 0); - nouveau_fbcon_zfill_all(dev); + if (dev->mode_config.num_crtc) { + nouveau_fbcon_set_suspend(dev, 0); + nouveau_fbcon_zfill_all(dev); - nouveau_display_init(dev); + nouveau_display_init(dev); + } /* Force CLUT to get re-loaded during modeset */ list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { @@ -468,9 +472,7 @@ static int __init nouveau_init(void) #ifdef CONFIG_VGA_CONSOLE if (vgacon_text_force()) nouveau_modeset = 0; - else #endif - nouveau_modeset = 1; } if (!nouveau_modeset) diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index c2a8511e855..b096cf28213 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c @@ -47,6 +47,7 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; struct nouveau_engine *engine = &dev_priv->engine; + u32 pclass = dev->pdev->class >> 8; switch (dev_priv->chipset & 0xf0) { case 0x00: @@ -526,7 +527,8 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) } /* headless mode */ - if (nouveau_modeset == 2) { + if (nouveau_modeset == 2 || + (nouveau_modeset < 0 && pclass != PCI_CLASS_DISPLAY_VGA)) { engine->display.early_init = nouveau_stub_init; engine->display.late_takedown = nouveau_stub_takedown; engine->display.create = nouveau_stub_init; diff --git a/drivers/gpu/drm/nouveau/nv04_dac.c b/drivers/gpu/drm/nouveau/nv04_dac.c index 8300266ffae..f180dcfb12f 100644 --- a/drivers/gpu/drm/nouveau/nv04_dac.c +++ b/drivers/gpu/drm/nouveau/nv04_dac.c @@ -210,7 +210,7 @@ static enum drm_connector_status nv04_dac_detect(struct drm_encoder *encoder, NVWriteVgaCrtc(dev, 0, NV_CIO_CR_MODE_INDEX, saved_cr_mode); if (blue == 0x18) { - NV_INFO(dev, "Load detected on head A\n"); + NV_DEBUG(dev, "Load detected on head A\n"); return connector_status_connected; } @@ -323,7 +323,7 @@ nv17_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) if (nv17_dac_sample_load(encoder) & NV_PRAMDAC_TEST_CONTROL_SENSEB_ALLHI) { - NV_INFO(dev, "Load detected on output %c\n", + NV_DEBUG(dev, "Load detected on output %c\n", '@' + ffs(dcb->or)); return connector_status_connected; } else { @@ -398,7 +398,7 @@ static void nv04_dac_commit(struct drm_encoder *encoder) helper->dpms(encoder, DRM_MODE_DPMS_ON); - NV_INFO(dev, "Output %s is running on CRTC %d using output %c\n", + NV_DEBUG(dev, "Output %s is running on CRTC %d using output %c\n", drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); } @@ -447,7 +447,7 @@ static void nv04_dac_dpms(struct drm_encoder *encoder, int mode) return; nv_encoder->last_dpms = mode; - NV_INFO(dev, "Setting dpms mode %d on vga encoder (output %d)\n", + NV_DEBUG(dev, "Setting dpms mode %d on vga encoder (output %d)\n", mode, nv_encoder->dcb->index); nv04_dac_update_dacclk(encoder, mode == DRM_MODE_DPMS_ON); diff --git a/drivers/gpu/drm/nouveau/nv04_dfp.c b/drivers/gpu/drm/nouveau/nv04_dfp.c index 2258746016f..71b62352315 100644 --- a/drivers/gpu/drm/nouveau/nv04_dfp.c +++ b/drivers/gpu/drm/nouveau/nv04_dfp.c @@ -476,7 +476,7 @@ static void nv04_dfp_commit(struct drm_encoder *encoder) helper->dpms(encoder, DRM_MODE_DPMS_ON); - NV_INFO(dev, "Output %s is running on CRTC %d using output %c\n", + NV_DEBUG(dev, "Output %s is running on CRTC %d using output %c\n", drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); } @@ -504,7 +504,7 @@ static void nv04_dfp_update_backlight(struct drm_encoder *encoder, int mode) static inline bool is_powersaving_dpms(int mode) { - return (mode != DRM_MODE_DPMS_ON); + return mode != DRM_MODE_DPMS_ON && mode != NV_DPMS_CLEARED; } static void nv04_lvds_dpms(struct drm_encoder *encoder, int mode) @@ -519,7 +519,7 @@ static void nv04_lvds_dpms(struct drm_encoder *encoder, int mode) return; nv_encoder->last_dpms = mode; - NV_INFO(dev, "Setting dpms mode %d on lvds encoder (output %d)\n", + NV_DEBUG(dev, "Setting dpms mode %d on lvds encoder (output %d)\n", mode, nv_encoder->dcb->index); if (was_powersaving && is_powersaving_dpms(mode)) @@ -564,7 +564,7 @@ static void nv04_tmds_dpms(struct drm_encoder *encoder, int mode) return; nv_encoder->last_dpms = mode; - NV_INFO(dev, "Setting dpms mode %d on tmds encoder (output %d)\n", + NV_DEBUG(dev, "Setting dpms mode %d on tmds encoder (output %d)\n", mode, nv_encoder->dcb->index); nv04_dfp_update_backlight(encoder, mode); diff --git a/drivers/gpu/drm/nouveau/nv04_tv.c b/drivers/gpu/drm/nouveau/nv04_tv.c index 3eb605ddfd0..4de1fbeb849 100644 --- a/drivers/gpu/drm/nouveau/nv04_tv.c +++ b/drivers/gpu/drm/nouveau/nv04_tv.c @@ -69,7 +69,7 @@ static void nv04_tv_dpms(struct drm_encoder *encoder, int mode) struct nv04_mode_state *state = &dev_priv->mode_reg; uint8_t crtc1A; - NV_INFO(dev, "Setting dpms mode %d on TV encoder (output %d)\n", + NV_DEBUG(dev, "Setting dpms mode %d on TV encoder (output %d)\n", mode, nv_encoder->dcb->index); state->pllsel &= ~(PLLSEL_TV_CRTC1_MASK | PLLSEL_TV_CRTC2_MASK); @@ -162,7 +162,7 @@ static void nv04_tv_commit(struct drm_encoder *encoder) helper->dpms(encoder, DRM_MODE_DPMS_ON); - NV_INFO(dev, "Output %s is running on CRTC %d using output %c\n", + NV_DEBUG(dev, "Output %s is running on CRTC %d using output %c\n", drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); } diff --git a/drivers/gpu/drm/nouveau/nva3_copy.fuc b/drivers/gpu/drm/nouveau/nva3_copy.fuc index abc36626fef..219850d5328 100644 --- a/drivers/gpu/drm/nouveau/nva3_copy.fuc +++ b/drivers/gpu/drm/nouveau/nva3_copy.fuc @@ -119,9 +119,9 @@ dispatch_dma: // mthd 0x030c-0x0340, various stuff .b16 0xc3 14 .b32 #ctx_src_address_high ~0x000000ff -.b32 #ctx_src_address_low ~0xfffffff0 +.b32 #ctx_src_address_low ~0xffffffff .b32 #ctx_dst_address_high ~0x000000ff -.b32 #ctx_dst_address_low ~0xfffffff0 +.b32 #ctx_dst_address_low ~0xffffffff .b32 #ctx_src_pitch ~0x0007ffff .b32 #ctx_dst_pitch ~0x0007ffff .b32 #ctx_xcnt ~0x0000ffff diff --git a/drivers/gpu/drm/nouveau/nva3_copy.fuc.h b/drivers/gpu/drm/nouveau/nva3_copy.fuc.h index 1f33fbdc00b..37d6de3c9d6 100644 --- a/drivers/gpu/drm/nouveau/nva3_copy.fuc.h +++ b/drivers/gpu/drm/nouveau/nva3_copy.fuc.h @@ -1,37 +1,72 @@ -uint32_t nva3_pcopy_data[] = { +u32 nva3_pcopy_data[] = { +/* 0x0000: ctx_object */ 0x00000000, +/* 0x0004: ctx_dma */ +/* 0x0004: ctx_dma_query */ 0x00000000, +/* 0x0008: ctx_dma_src */ 0x00000000, +/* 0x000c: ctx_dma_dst */ 0x00000000, +/* 0x0010: ctx_query_address_high */ 0x00000000, +/* 0x0014: ctx_query_address_low */ 0x00000000, +/* 0x0018: ctx_query_counter */ 0x00000000, +/* 0x001c: ctx_src_address_high */ 0x00000000, +/* 0x0020: ctx_src_address_low */ 0x00000000, +/* 0x0024: ctx_src_pitch */ 0x00000000, +/* 0x0028: ctx_src_tile_mode */ 0x00000000, +/* 0x002c: ctx_src_xsize */ 0x00000000, +/* 0x0030: ctx_src_ysize */ 0x00000000, +/* 0x0034: ctx_src_zsize */ 0x00000000, +/* 0x0038: ctx_src_zoff */ 0x00000000, +/* 0x003c: ctx_src_xoff */ 0x00000000, +/* 0x0040: ctx_src_yoff */ 0x00000000, +/* 0x0044: ctx_src_cpp */ 0x00000000, +/* 0x0048: ctx_dst_address_high */ 0x00000000, +/* 0x004c: ctx_dst_address_low */ 0x00000000, +/* 0x0050: ctx_dst_pitch */ 0x00000000, +/* 0x0054: ctx_dst_tile_mode */ 0x00000000, +/* 0x0058: ctx_dst_xsize */ 0x00000000, +/* 0x005c: ctx_dst_ysize */ 0x00000000, +/* 0x0060: ctx_dst_zsize */ 0x00000000, +/* 0x0064: ctx_dst_zoff */ 0x00000000, +/* 0x0068: ctx_dst_xoff */ 0x00000000, +/* 0x006c: ctx_dst_yoff */ 0x00000000, +/* 0x0070: ctx_dst_cpp */ 0x00000000, +/* 0x0074: ctx_format */ 0x00000000, +/* 0x0078: ctx_swz_const0 */ 0x00000000, +/* 0x007c: ctx_swz_const1 */ 0x00000000, +/* 0x0080: ctx_xcnt */ 0x00000000, +/* 0x0084: ctx_ycnt */ 0x00000000, 0x00000000, 0x00000000, @@ -63,6 +98,7 @@ uint32_t nva3_pcopy_data[] = { 0x00000000, 0x00000000, 0x00000000, +/* 0x0100: dispatch_table */ 0x00010000, 0x00000000, 0x00000000, @@ -73,6 +109,7 @@ uint32_t nva3_pcopy_data[] = { 0x00010162, 0x00000000, 0x00030060, +/* 0x0128: dispatch_dma */ 0x00010170, 0x00000000, 0x00010170, @@ -118,11 +155,11 @@ uint32_t nva3_pcopy_data[] = { 0x0000001c, 0xffffff00, 0x00000020, - 0x0000000f, + 0x00000000, 0x00000048, 0xffffff00, 0x0000004c, - 0x0000000f, + 0x00000000, 0x00000024, 0xfff80000, 0x00000050, @@ -146,7 +183,8 @@ uint32_t nva3_pcopy_data[] = { 0x00000800, }; -uint32_t nva3_pcopy_code[] = { +u32 nva3_pcopy_code[] = { +/* 0x0000: main */ 0x04fe04bd, 0x3517f000, 0xf10010fe, @@ -158,23 +196,31 @@ uint32_t nva3_pcopy_code[] = { 0x17f11031, 0x27f01200, 0x0012d003, +/* 0x002f: spin */ 0xf40031f4, 0x0ef40028, +/* 0x0035: ih */ 0x8001cffd, 0xf40812c4, 0x21f4060b, +/* 0x0041: ih_no_chsw */ 0x0412c472, 0xf4060bf4, +/* 0x004a: ih_no_cmd */ 0x11c4c321, 0x4001d00c, +/* 0x0052: swctx */ 0x47f101f8, 0x4bfe7700, 0x0007fe00, 0xf00204b9, 0x01f40643, 0x0604fa09, +/* 0x006b: swctx_load */ 0xfa060ef4, +/* 0x006e: swctx_done */ 0x03f80504, +/* 0x0072: chsw */ 0x27f100f8, 0x23cf1400, 0x1e3fc800, @@ -183,18 +229,22 @@ uint32_t nva3_pcopy_code[] = { 0x1e3af052, 0xf00023d0, 0x24d00147, +/* 0x0093: chsw_no_unload */ 0xcf00f880, 0x3dc84023, 0x220bf41e, 0xf40131f4, 0x57f05221, 0x0367f004, +/* 0x00a8: chsw_load_ctx_dma */ 0xa07856bc, 0xb6018068, 0x87d00884, 0x0162b600, +/* 0x00bb: chsw_finish_load */ 0xf0f018f4, 0x23d00237, +/* 0x00c3: dispatch */ 0xf100f880, 0xcf190037, 0x33cf4032, @@ -202,6 +252,7 @@ uint32_t nva3_pcopy_code[] = { 0x1024b607, 0x010057f1, 0x74bd64bd, +/* 0x00dc: dispatch_loop */ 0x58005658, 0x50b60157, 0x0446b804, @@ -211,6 +262,7 @@ uint32_t nva3_pcopy_code[] = { 0xb60276bb, 0x57bb0374, 0xdf0ef400, +/* 0x0100: dispatch_valid_mthd */ 0xb60246bb, 0x45bb0344, 0x01459800, @@ -220,31 +272,41 @@ uint32_t nva3_pcopy_code[] = { 0xb0014658, 0x1bf40064, 0x00538009, +/* 0x0127: dispatch_cmd */ 0xf4300ef4, 0x55f90132, 0xf40c01f4, +/* 0x0132: dispatch_invalid_bitfield */ 0x25f0250e, +/* 0x0135: dispatch_illegal_mthd */ 0x0125f002, +/* 0x0138: dispatch_error */ 0x100047f1, 0xd00042d0, 0x27f04043, 0x0002d040, +/* 0x0148: hostirq_wait */ 0xf08002cf, 0x24b04024, 0xf71bf400, +/* 0x0154: dispatch_done */ 0x1d0027f1, 0xd00137f0, 0x00f80023, +/* 0x0160: cmd_nop */ +/* 0x0162: cmd_pm_trigger */ 0x27f100f8, 0x34bd2200, 0xd00233f0, 0x00f80023, +/* 0x0170: cmd_dma */ 0x012842b7, 0xf00145b6, 0x43801e39, 0x0040b701, 0x0644b606, 0xf80043d0, +/* 0x0189: cmd_exec_set_format */ 0xf030f400, 0xb00001b0, 0x01b00101, @@ -256,20 +318,26 @@ uint32_t nva3_pcopy_code[] = { 0x70b63847, 0x0232f401, 0x94bd84bd, +/* 0x01b4: ncomp_loop */ 0xb60f4ac4, 0xb4bd0445, +/* 0x01bc: bpc_loop */ 0xf404a430, 0xa5ff0f18, 0x00cbbbc0, 0xf40231f4, +/* 0x01ce: cmp_c0 */ 0x1bf4220e, 0x10c7f00c, 0xf400cbbb, +/* 0x01da: cmp_c1 */ 0xa430160e, 0x0c18f406, 0xbb14c7f0, 0x0ef400cb, +/* 0x01e9: cmp_zero */ 0x80c7f107, +/* 0x01ed: bpc_next */ 0x01c83800, 0xb60180b6, 0xb5b801b0, @@ -280,6 +348,7 @@ uint32_t nva3_pcopy_code[] = { 0x98110680, 0x68fd2008, 0x0502f400, +/* 0x0216: dst_xcnt */ 0x75fd64bd, 0x1c078000, 0xf10078fd, @@ -304,6 +373,7 @@ uint32_t nva3_pcopy_code[] = { 0x980056d0, 0x56d01f06, 0x1030f440, +/* 0x0276: cmd_exec_set_surface_tiled */ 0x579800f8, 0x6879c70a, 0xb66478c7, @@ -311,9 +381,11 @@ uint32_t nva3_pcopy_code[] = { 0x0e76b060, 0xf0091bf4, 0x0ef40477, +/* 0x0291: xtile64 */ 0x027cf00f, 0xfd1170b6, 0x77f00947, +/* 0x029d: xtileok */ 0x0f5a9806, 0xfd115b98, 0xb7f000ab, @@ -371,6 +443,7 @@ uint32_t nva3_pcopy_code[] = { 0x67d00600, 0x0060b700, 0x0068d004, +/* 0x0382: cmd_exec_set_surface_linear */ 0x6cf000f8, 0x0260b702, 0x0864b602, @@ -381,13 +454,16 @@ uint32_t nva3_pcopy_code[] = { 0xb70067d0, 0x98040060, 0x67d00957, +/* 0x03ab: cmd_exec_wait */ 0xf900f800, 0xf110f900, 0xb6080007, +/* 0x03b6: loop */ 0x01cf0604, 0x0114f000, 0xfcfa1bf4, 0xf800fc10, +/* 0x03c5: cmd_exec_query */ 0x0d34c800, 0xf5701bf4, 0xf103ab21, @@ -417,6 +493,7 @@ uint32_t nva3_pcopy_code[] = { 0x47f10153, 0x44b60800, 0x0045d006, +/* 0x0438: query_counter */ 0x03ab21f5, 0x080c47f1, 0x980644b6, @@ -439,11 +516,13 @@ uint32_t nva3_pcopy_code[] = { 0x47f10153, 0x44b60800, 0x0045d006, +/* 0x0492: cmd_exec */ 0x21f500f8, 0x3fc803ab, 0x0e0bf400, 0x018921f5, 0x020047f1, +/* 0x04a7: cmd_exec_no_format */ 0xf11e0ef4, 0xb6081067, 0x77f00664, @@ -451,19 +530,24 @@ uint32_t nva3_pcopy_code[] = { 0x981c0780, 0x67d02007, 0x4067d000, +/* 0x04c2: cmd_exec_init_src_surface */ 0x32f444bd, 0xc854bd02, 0x0bf4043f, 0x8221f50a, 0x0a0ef403, +/* 0x04d4: src_tiled */ 0x027621f5, +/* 0x04db: cmd_exec_init_dst_surface */ 0xf40749f0, 0x57f00231, 0x083fc82c, 0xf50a0bf4, 0xf4038221, +/* 0x04ee: dst_tiled */ 0x21f50a0e, 0x49f00276, +/* 0x04f5: cmd_exec_kick */ 0x0057f108, 0x0654b608, 0xd0210698, @@ -473,6 +557,8 @@ uint32_t nva3_pcopy_code[] = { 0xc80054d0, 0x0bf40c3f, 0xc521f507, +/* 0x0519: cmd_exec_done */ +/* 0x051b: cmd_wrcache_flush */ 0xf100f803, 0xbd220027, 0x0133f034, diff --git a/drivers/gpu/drm/nouveau/nvc0_copy.fuc.h b/drivers/gpu/drm/nouveau/nvc0_copy.fuc.h index a8d17458ced..cd879f31bb3 100644 --- a/drivers/gpu/drm/nouveau/nvc0_copy.fuc.h +++ b/drivers/gpu/drm/nouveau/nvc0_copy.fuc.h @@ -1,34 +1,65 @@ -uint32_t nvc0_pcopy_data[] = { +u32 nvc0_pcopy_data[] = { +/* 0x0000: ctx_object */ 0x00000000, +/* 0x0004: ctx_query_address_high */ 0x00000000, +/* 0x0008: ctx_query_address_low */ 0x00000000, +/* 0x000c: ctx_query_counter */ 0x00000000, +/* 0x0010: ctx_src_address_high */ 0x00000000, +/* 0x0014: ctx_src_address_low */ 0x00000000, +/* 0x0018: ctx_src_pitch */ 0x00000000, +/* 0x001c: ctx_src_tile_mode */ 0x00000000, +/* 0x0020: ctx_src_xsize */ 0x00000000, +/* 0x0024: ctx_src_ysize */ 0x00000000, +/* 0x0028: ctx_src_zsize */ 0x00000000, +/* 0x002c: ctx_src_zoff */ 0x00000000, +/* 0x0030: ctx_src_xoff */ 0x00000000, +/* 0x0034: ctx_src_yoff */ 0x00000000, +/* 0x0038: ctx_src_cpp */ 0x00000000, +/* 0x003c: ctx_dst_address_high */ 0x00000000, +/* 0x0040: ctx_dst_address_low */ 0x00000000, +/* 0x0044: ctx_dst_pitch */ 0x00000000, +/* 0x0048: ctx_dst_tile_mode */ 0x00000000, +/* 0x004c: ctx_dst_xsize */ 0x00000000, +/* 0x0050: ctx_dst_ysize */ 0x00000000, +/* 0x0054: ctx_dst_zsize */ 0x00000000, +/* 0x0058: ctx_dst_zoff */ 0x00000000, +/* 0x005c: ctx_dst_xoff */ 0x00000000, +/* 0x0060: ctx_dst_yoff */ 0x00000000, +/* 0x0064: ctx_dst_cpp */ 0x00000000, +/* 0x0068: ctx_format */ 0x00000000, +/* 0x006c: ctx_swz_const0 */ 0x00000000, +/* 0x0070: ctx_swz_const1 */ 0x00000000, +/* 0x0074: ctx_xcnt */ 0x00000000, +/* 0x0078: ctx_ycnt */ 0x00000000, 0x00000000, 0x00000000, @@ -63,6 +94,7 @@ uint32_t nvc0_pcopy_data[] = { 0x00000000, 0x00000000, 0x00000000, +/* 0x0100: dispatch_table */ 0x00010000, 0x00000000, 0x00000000, @@ -111,11 +143,11 @@ uint32_t nvc0_pcopy_data[] = { 0x00000010, 0xffffff00, 0x00000014, - 0x0000000f, + 0x00000000, 0x0000003c, 0xffffff00, 0x00000040, - 0x0000000f, + 0x00000000, 0x00000018, 0xfff80000, 0x00000044, @@ -139,7 +171,8 @@ uint32_t nvc0_pcopy_data[] = { 0x00000800, }; -uint32_t nvc0_pcopy_code[] = { +u32 nvc0_pcopy_code[] = { +/* 0x0000: main */ 0x04fe04bd, 0x3517f000, 0xf10010fe, @@ -151,15 +184,20 @@ uint32_t nvc0_pcopy_code[] = { 0x17f11031, 0x27f01200, 0x0012d003, +/* 0x002f: spin */ 0xf40031f4, 0x0ef40028, +/* 0x0035: ih */ 0x8001cffd, 0xf40812c4, 0x21f4060b, +/* 0x0041: ih_no_chsw */ 0x0412c4ca, 0xf5070bf4, +/* 0x004b: ih_no_cmd */ 0xc4010221, 0x01d00c11, +/* 0x0053: swctx */ 0xf101f840, 0xfe770047, 0x47f1004b, @@ -188,8 +226,11 @@ uint32_t nvc0_pcopy_code[] = { 0xf00204b9, 0x01f40643, 0x0604fa09, +/* 0x00c3: swctx_load */ 0xfa060ef4, +/* 0x00c6: swctx_done */ 0x03f80504, +/* 0x00ca: chsw */ 0x27f100f8, 0x23cf1400, 0x1e3fc800, @@ -198,18 +239,22 @@ uint32_t nvc0_pcopy_code[] = { 0x1e3af053, 0xf00023d0, 0x24d00147, +/* 0x00eb: chsw_no_unload */ 0xcf00f880, 0x3dc84023, 0x090bf41e, 0xf40131f4, +/* 0x00fa: chsw_finish_load */ 0x37f05321, 0x8023d002, +/* 0x0102: dispatch */ 0x37f100f8, 0x32cf1900, 0x0033cf40, 0x07ff24e4, 0xf11024b6, 0xbd010057, +/* 0x011b: dispatch_loop */ 0x5874bd64, 0x57580056, 0x0450b601, @@ -219,6 +264,7 @@ uint32_t nvc0_pcopy_code[] = { 0xbb0f08f4, 0x74b60276, 0x0057bb03, +/* 0x013f: dispatch_valid_mthd */ 0xbbdf0ef4, 0x44b60246, 0x0045bb03, @@ -229,24 +275,33 @@ uint32_t nvc0_pcopy_code[] = { 0x64b00146, 0x091bf400, 0xf4005380, +/* 0x0166: dispatch_cmd */ 0x32f4300e, 0xf455f901, 0x0ef40c01, +/* 0x0171: dispatch_invalid_bitfield */ 0x0225f025, +/* 0x0174: dispatch_illegal_mthd */ +/* 0x0177: dispatch_error */ 0xf10125f0, 0xd0100047, 0x43d00042, 0x4027f040, +/* 0x0187: hostirq_wait */ 0xcf0002d0, 0x24f08002, 0x0024b040, +/* 0x0193: dispatch_done */ 0xf1f71bf4, 0xf01d0027, 0x23d00137, +/* 0x019f: cmd_nop */ 0xf800f800, +/* 0x01a1: cmd_pm_trigger */ 0x0027f100, 0xf034bd22, 0x23d00233, +/* 0x01af: cmd_exec_set_format */ 0xf400f800, 0x01b0f030, 0x0101b000, @@ -258,20 +313,26 @@ uint32_t nvc0_pcopy_code[] = { 0x3847c701, 0xf40170b6, 0x84bd0232, +/* 0x01da: ncomp_loop */ 0x4ac494bd, 0x0445b60f, +/* 0x01e2: bpc_loop */ 0xa430b4bd, 0x0f18f404, 0xbbc0a5ff, 0x31f400cb, 0x220ef402, +/* 0x01f4: cmp_c0 */ 0xf00c1bf4, 0xcbbb10c7, 0x160ef400, +/* 0x0200: cmp_c1 */ 0xf406a430, 0xc7f00c18, 0x00cbbb14, +/* 0x020f: cmp_zero */ 0xf1070ef4, +/* 0x0213: bpc_next */ 0x380080c7, 0x80b601c8, 0x01b0b601, @@ -283,6 +344,7 @@ uint32_t nvc0_pcopy_code[] = { 0x1d08980e, 0xf40068fd, 0x64bd0502, +/* 0x023c: dst_xcnt */ 0x800075fd, 0x78fd1907, 0x1057f100, @@ -307,15 +369,18 @@ uint32_t nvc0_pcopy_code[] = { 0x1c069800, 0xf44056d0, 0x00f81030, +/* 0x029c: cmd_exec_set_surface_tiled */ 0xc7075798, 0x78c76879, 0x0380b664, 0xb06077c7, 0x1bf40e76, 0x0477f009, +/* 0x02b7: xtile64 */ 0xf00f0ef4, 0x70b6027c, 0x0947fd11, +/* 0x02c3: xtileok */ 0x980677f0, 0x5b980c5a, 0x00abfd0e, @@ -374,6 +439,7 @@ uint32_t nvc0_pcopy_code[] = { 0xb70067d0, 0xd0040060, 0x00f80068, +/* 0x03a8: cmd_exec_set_surface_linear */ 0xb7026cf0, 0xb6020260, 0x57980864, @@ -384,12 +450,15 @@ uint32_t nvc0_pcopy_code[] = { 0x0060b700, 0x06579804, 0xf80067d0, +/* 0x03d1: cmd_exec_wait */ 0xf900f900, 0x0007f110, 0x0604b608, +/* 0x03dc: loop */ 0xf00001cf, 0x1bf40114, 0xfc10fcfa, +/* 0x03eb: cmd_exec_query */ 0xc800f800, 0x1bf40d34, 0xd121f570, @@ -419,6 +488,7 @@ uint32_t nvc0_pcopy_code[] = { 0x0153f026, 0x080047f1, 0xd00644b6, +/* 0x045e: query_counter */ 0x21f50045, 0x47f103d1, 0x44b6080c, @@ -442,11 +512,13 @@ uint32_t nvc0_pcopy_code[] = { 0x080047f1, 0xd00644b6, 0x00f80045, +/* 0x04b8: cmd_exec */ 0x03d121f5, 0xf4003fc8, 0x21f50e0b, 0x47f101af, 0x0ef40200, +/* 0x04cd: cmd_exec_no_format */ 0x1067f11e, 0x0664b608, 0x800177f0, @@ -454,18 +526,23 @@ uint32_t nvc0_pcopy_code[] = { 0x1d079819, 0xd00067d0, 0x44bd4067, +/* 0x04e8: cmd_exec_init_src_surface */ 0xbd0232f4, 0x043fc854, 0xf50a0bf4, 0xf403a821, +/* 0x04fa: src_tiled */ 0x21f50a0e, 0x49f0029c, +/* 0x0501: cmd_exec_init_dst_surface */ 0x0231f407, 0xc82c57f0, 0x0bf4083f, 0xa821f50a, 0x0a0ef403, +/* 0x0514: dst_tiled */ 0x029c21f5, +/* 0x051b: cmd_exec_kick */ 0xf10849f0, 0xb6080057, 0x06980654, @@ -475,7 +552,9 @@ uint32_t nvc0_pcopy_code[] = { 0x54d00546, 0x0c3fc800, 0xf5070bf4, +/* 0x053f: cmd_exec_done */ 0xf803eb21, +/* 0x0541: cmd_wrcache_flush */ 0x0027f100, 0xf034bd22, 0x23d00133, diff --git a/drivers/gpu/drm/nouveau/nvd0_display.c b/drivers/gpu/drm/nouveau/nvd0_display.c index 0247250939e..8a555fb6702 100644 --- a/drivers/gpu/drm/nouveau/nvd0_display.c +++ b/drivers/gpu/drm/nouveau/nvd0_display.c @@ -790,7 +790,7 @@ nvd0_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); int ch = EVO_CURS(nv_crtc->index); - evo_piow(crtc->dev, ch, 0x0084, (y << 16) | x); + evo_piow(crtc->dev, ch, 0x0084, (y << 16) | (x & 0xffff)); evo_piow(crtc->dev, ch, 0x0080, 0x00000000); return 0; } diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index af1054f8202..15594a30ebd 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -258,8 +258,7 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode) radeon_crtc->enabled = true; /* adjust pm to dpms changes BEFORE enabling crtcs */ radeon_pm_compute_clocks(rdev); - /* disable crtc pair power gating before programming */ - if (ASIC_IS_DCE6(rdev)) + if (ASIC_IS_DCE6(rdev) && !radeon_crtc->in_mode_set) atombios_powergate_crtc(crtc, ATOM_DISABLE); atombios_enable_crtc(crtc, ATOM_ENABLE); if (ASIC_IS_DCE3(rdev) && !ASIC_IS_DCE6(rdev)) @@ -278,25 +277,8 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode) atombios_enable_crtc_memreq(crtc, ATOM_DISABLE); atombios_enable_crtc(crtc, ATOM_DISABLE); radeon_crtc->enabled = false; - /* power gating is per-pair */ - if (ASIC_IS_DCE6(rdev)) { - struct drm_crtc *other_crtc; - struct radeon_crtc *other_radeon_crtc; - list_for_each_entry(other_crtc, &rdev->ddev->mode_config.crtc_list, head) { - other_radeon_crtc = to_radeon_crtc(other_crtc); - if (((radeon_crtc->crtc_id == 0) && (other_radeon_crtc->crtc_id == 1)) || - ((radeon_crtc->crtc_id == 1) && (other_radeon_crtc->crtc_id == 0)) || - ((radeon_crtc->crtc_id == 2) && (other_radeon_crtc->crtc_id == 3)) || - ((radeon_crtc->crtc_id == 3) && (other_radeon_crtc->crtc_id == 2)) || - ((radeon_crtc->crtc_id == 4) && (other_radeon_crtc->crtc_id == 5)) || - ((radeon_crtc->crtc_id == 5) && (other_radeon_crtc->crtc_id == 4))) { - /* if both crtcs in the pair are off, enable power gating */ - if (other_radeon_crtc->enabled == false) - atombios_powergate_crtc(crtc, ATOM_ENABLE); - break; - } - } - } + if (ASIC_IS_DCE6(rdev) && !radeon_crtc->in_mode_set) + atombios_powergate_crtc(crtc, ATOM_ENABLE); /* adjust pm to dpms changes AFTER disabling crtcs */ radeon_pm_compute_clocks(rdev); break; @@ -444,11 +426,28 @@ union atom_enable_ss { static void atombios_crtc_program_ss(struct radeon_device *rdev, int enable, int pll_id, + int crtc_id, struct radeon_atom_ss *ss) { + unsigned i; int index = GetIndexIntoMasterTable(COMMAND, EnableSpreadSpectrumOnPPLL); union atom_enable_ss args; + if (!enable) { + for (i = 0; i < rdev->num_crtc; i++) { + if (rdev->mode_info.crtcs[i] && + rdev->mode_info.crtcs[i]->enabled && + i != crtc_id && + pll_id == rdev->mode_info.crtcs[i]->pll_id) { + /* one other crtc is using this pll don't turn + * off spread spectrum as it might turn off + * display on active crtc + */ + return; + } + } + } + memset(&args, 0, sizeof(args)); if (ASIC_IS_DCE5(rdev)) { @@ -1039,7 +1038,7 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode radeon_compute_pll_legacy(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div, &ref_div, &post_div); - atombios_crtc_program_ss(rdev, ATOM_DISABLE, radeon_crtc->pll_id, &ss); + atombios_crtc_program_ss(rdev, ATOM_DISABLE, radeon_crtc->pll_id, radeon_crtc->crtc_id, &ss); atombios_crtc_program_pll(crtc, radeon_crtc->crtc_id, radeon_crtc->pll_id, encoder_mode, radeon_encoder->encoder_id, mode->clock, @@ -1062,7 +1061,7 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode ss.step = step_size; } - atombios_crtc_program_ss(rdev, ATOM_ENABLE, radeon_crtc->pll_id, &ss); + atombios_crtc_program_ss(rdev, ATOM_ENABLE, radeon_crtc->pll_id, radeon_crtc->crtc_id, &ss); } } @@ -1534,8 +1533,12 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc) * crtc virtual pixel clock. */ if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_encoder))) { - if (ASIC_IS_DCE5(rdev) || rdev->clock.dp_extclk) + if (rdev->clock.dp_extclk) return ATOM_PPLL_INVALID; + else if (ASIC_IS_DCE6(rdev)) + return ATOM_PPLL0; + else if (ASIC_IS_DCE5(rdev)) + return ATOM_DCPLL; } } } @@ -1571,11 +1574,11 @@ void radeon_atom_disp_eng_pll_init(struct radeon_device *rdev) ASIC_INTERNAL_SS_ON_DCPLL, rdev->clock.default_dispclk); if (ss_enabled) - atombios_crtc_program_ss(rdev, ATOM_DISABLE, ATOM_DCPLL, &ss); + atombios_crtc_program_ss(rdev, ATOM_DISABLE, ATOM_DCPLL, -1, &ss); /* XXX: DCE5, make sure voltage, dispclk is high enough */ atombios_crtc_set_disp_eng_pll(rdev, rdev->clock.default_dispclk); if (ss_enabled) - atombios_crtc_program_ss(rdev, ATOM_ENABLE, ATOM_DCPLL, &ss); + atombios_crtc_program_ss(rdev, ATOM_ENABLE, ATOM_DCPLL, -1, &ss); } } @@ -1634,18 +1637,28 @@ static bool atombios_crtc_mode_fixup(struct drm_crtc *crtc, static void atombios_crtc_prepare(struct drm_crtc *crtc) { struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + struct drm_device *dev = crtc->dev; + struct radeon_device *rdev = dev->dev_private; + radeon_crtc->in_mode_set = true; /* pick pll */ radeon_crtc->pll_id = radeon_atom_pick_pll(crtc); + /* disable crtc pair power gating before programming */ + if (ASIC_IS_DCE6(rdev)) + atombios_powergate_crtc(crtc, ATOM_DISABLE); + atombios_lock_crtc(crtc, ATOM_ENABLE); atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); } static void atombios_crtc_commit(struct drm_crtc *crtc) { + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); + atombios_crtc_dpms(crtc, DRM_MODE_DPMS_ON); atombios_lock_crtc(crtc, ATOM_DISABLE); + radeon_crtc->in_mode_set = false; } static void atombios_crtc_disable(struct drm_crtc *crtc) @@ -1654,9 +1667,22 @@ static void atombios_crtc_disable(struct drm_crtc *crtc) struct drm_device *dev = crtc->dev; struct radeon_device *rdev = dev->dev_private; struct radeon_atom_ss ss; + int i; atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); + for (i = 0; i < rdev->num_crtc; i++) { + if (rdev->mode_info.crtcs[i] && + rdev->mode_info.crtcs[i]->enabled && + i != radeon_crtc->crtc_id && + radeon_crtc->pll_id == rdev->mode_info.crtcs[i]->pll_id) { + /* one other crtc is using this pll don't turn + * off the pll + */ + goto done; + } + } + switch (radeon_crtc->pll_id) { case ATOM_PPLL1: case ATOM_PPLL2: @@ -1673,6 +1699,7 @@ static void atombios_crtc_disable(struct drm_crtc *crtc) default: break; } +done: radeon_crtc->pll_id = -1; } diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c index c57d85664e7..886b41f44a5 100644 --- a/drivers/gpu/drm/radeon/atombios_dp.c +++ b/drivers/gpu/drm/radeon/atombios_dp.c @@ -22,6 +22,7 @@ * * Authors: Dave Airlie * Alex Deucher + * Jerome Glisse */ #include "drmP.h" #include "radeon_drm.h" @@ -637,7 +638,6 @@ static bool radeon_dp_get_link_status(struct radeon_connector *radeon_connector, ret = radeon_dp_aux_native_read(radeon_connector, DP_LANE0_1_STATUS, link_status, DP_LINK_STATUS_SIZE, 100); if (ret <= 0) { - DRM_ERROR("displayport link status failed\n"); return false; } @@ -816,8 +816,10 @@ static int radeon_dp_link_train_cr(struct radeon_dp_link_train_info *dp_info) else mdelay(dp_info->rd_interval * 4); - if (!radeon_dp_get_link_status(dp_info->radeon_connector, dp_info->link_status)) + if (!radeon_dp_get_link_status(dp_info->radeon_connector, dp_info->link_status)) { + DRM_ERROR("displayport link status failed\n"); break; + } if (dp_clock_recovery_ok(dp_info->link_status, dp_info->dp_lane_count)) { clock_recovery = true; @@ -879,8 +881,10 @@ static int radeon_dp_link_train_ce(struct radeon_dp_link_train_info *dp_info) else mdelay(dp_info->rd_interval * 4); - if (!radeon_dp_get_link_status(dp_info->radeon_connector, dp_info->link_status)) + if (!radeon_dp_get_link_status(dp_info->radeon_connector, dp_info->link_status)) { + DRM_ERROR("displayport link status failed\n"); break; + } if (dp_channel_eq_ok(dp_info->link_status, dp_info->dp_lane_count)) { channel_eq = true; diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c index 2d39f9977e0..23e3ea6ba14 100644 --- a/drivers/gpu/drm/radeon/atombios_encoders.c +++ b/drivers/gpu/drm/radeon/atombios_encoders.c @@ -95,7 +95,7 @@ static bool radeon_atom_mode_fixup(struct drm_encoder *encoder, ((radeon_encoder->active_device & (ATOM_DEVICE_DFP_SUPPORT | ATOM_DEVICE_LCD_SUPPORT)) || (radeon_encoder_get_dp_bridge_encoder_id(encoder) != ENCODER_OBJECT_ID_NONE))) { struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); - radeon_dp_set_link_config(connector, mode); + radeon_dp_set_link_config(connector, adjusted_mode); } return true; @@ -1379,6 +1379,8 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode) struct drm_device *dev = encoder->dev; struct radeon_device *rdev = dev->dev_private; struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); + struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder); + struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); struct radeon_connector *radeon_connector = NULL; struct radeon_connector_atom_dig *radeon_dig_connector = NULL; @@ -1390,12 +1392,38 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode) switch (mode) { case DRM_MODE_DPMS_ON: - /* some early dce3.2 boards have a bug in their transmitter control table */ - if ((rdev->family == CHIP_RV710) || (rdev->family == CHIP_RV730) || - ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) + if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) { + if (!connector) + dig->panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE; + else + dig->panel_mode = radeon_dp_get_panel_mode(encoder, connector); + + /* setup and enable the encoder */ + atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0); + atombios_dig_encoder_setup(encoder, + ATOM_ENCODER_CMD_SETUP_PANEL_MODE, + dig->panel_mode); + if (ext_encoder) { + if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev)) + atombios_external_encoder_setup(encoder, ext_encoder, + EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP); + } + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); + } else if (ASIC_IS_DCE4(rdev)) { + /* setup and enable the encoder */ + atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0); + /* enable the transmitter */ atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); - else atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); + } else { + /* setup and enable the encoder and transmitter */ + atombios_dig_encoder_setup(encoder, ATOM_ENABLE, 0); + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0); + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); + /* some early dce3.2 boards have a bug in their transmitter control table */ + if ((rdev->family != CHIP_RV710) && (rdev->family != CHIP_RV730)) + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); + } if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) { if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) { atombios_set_edp_panel_power(connector, @@ -1412,10 +1440,19 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode) case DRM_MODE_DPMS_STANDBY: case DRM_MODE_DPMS_SUSPEND: case DRM_MODE_DPMS_OFF: - if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) + if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) { + /* disable the transmitter */ atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); - else + } else if (ASIC_IS_DCE4(rdev)) { + /* disable the transmitter */ atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0); + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); + } else { + /* disable the encoder and transmitter */ + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0); + atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); + atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0); + } if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) { if (ASIC_IS_DCE4(rdev)) atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0); @@ -1732,13 +1769,34 @@ static int radeon_atom_pick_dig_encoder(struct drm_encoder *encoder) struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct drm_encoder *test_encoder; - struct radeon_encoder_atom_dig *dig; + struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; uint32_t dig_enc_in_use = 0; - /* DCE4/5 */ - if (ASIC_IS_DCE4(rdev)) { - dig = radeon_encoder->enc_priv; - if (ASIC_IS_DCE41(rdev)) { + if (ASIC_IS_DCE6(rdev)) { + /* DCE6 */ + switch (radeon_encoder->encoder_id) { + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY: + if (dig->linkb) + return 1; + else + return 0; + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: + if (dig->linkb) + return 3; + else + return 2; + break; + case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: + if (dig->linkb) + return 5; + else + return 4; + break; + } + } else if (ASIC_IS_DCE4(rdev)) { + /* DCE4/5 */ + if (ASIC_IS_DCE41(rdev) && !ASIC_IS_DCE61(rdev)) { /* ontario follows DCE4 */ if (rdev->family == CHIP_PALM) { if (dig->linkb) @@ -1840,10 +1898,12 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder, struct drm_device *dev = encoder->dev; struct radeon_device *rdev = dev->dev_private; struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); - struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder); radeon_encoder->pixel_clock = adjusted_mode->clock; + /* need to call this here rather than in prepare() since we need some crtc info */ + radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); + if (ASIC_IS_AVIVO(rdev) && !ASIC_IS_DCE4(rdev)) { if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT)) atombios_yuv_setup(encoder, true); @@ -1862,38 +1922,7 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder, case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: - if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) { - struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); - struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; - - if (!connector) - dig->panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE; - else - dig->panel_mode = radeon_dp_get_panel_mode(encoder, connector); - - /* setup and enable the encoder */ - atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0); - atombios_dig_encoder_setup(encoder, - ATOM_ENCODER_CMD_SETUP_PANEL_MODE, - dig->panel_mode); - } else if (ASIC_IS_DCE4(rdev)) { - /* disable the transmitter */ - atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); - /* setup and enable the encoder */ - atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0); - - /* enable the transmitter */ - atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); - } else { - /* disable the encoder and transmitter */ - atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); - atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0); - - /* setup and enable the encoder and transmitter */ - atombios_dig_encoder_setup(encoder, ATOM_ENABLE, 0); - atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0); - atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); - } + /* handled in dpms */ break; case ENCODER_OBJECT_ID_INTERNAL_DDI: case ENCODER_OBJECT_ID_INTERNAL_DVO1: @@ -1914,14 +1943,6 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder, break; } - if (ext_encoder) { - if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev)) - atombios_external_encoder_setup(encoder, ext_encoder, - EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP); - else - atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE); - } - atombios_apply_encoder_quirks(encoder, adjusted_mode); if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) { @@ -2094,7 +2115,6 @@ static void radeon_atom_encoder_prepare(struct drm_encoder *encoder) } radeon_atom_output_lock(encoder, true); - radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF); if (connector) { struct radeon_connector *radeon_connector = to_radeon_connector(connector); @@ -2115,6 +2135,7 @@ static void radeon_atom_encoder_prepare(struct drm_encoder *encoder) static void radeon_atom_encoder_commit(struct drm_encoder *encoder) { + /* need to call this here as we need the crtc set up */ radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_ON); radeon_atom_output_lock(encoder, false); } @@ -2155,14 +2176,7 @@ static void radeon_atom_encoder_disable(struct drm_encoder *encoder) case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1: case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2: case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA: - if (ASIC_IS_DCE4(rdev)) - /* disable the transmitter */ - atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); - else { - /* disable the encoder and transmitter */ - atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0); - atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0); - } + /* handled in dpms */ break; case ENCODER_OBJECT_ID_INTERNAL_DDI: case ENCODER_OBJECT_ID_INTERNAL_DVO1: diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index e72c03ff595..c62132cecaf 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -37,6 +37,16 @@ #define EVERGREEN_PFP_UCODE_SIZE 1120 #define EVERGREEN_PM4_UCODE_SIZE 1376 +static const u32 crtc_offsets[6] = +{ + EVERGREEN_CRTC0_REGISTER_OFFSET, + EVERGREEN_CRTC1_REGISTER_OFFSET, + EVERGREEN_CRTC2_REGISTER_OFFSET, + EVERGREEN_CRTC3_REGISTER_OFFSET, + EVERGREEN_CRTC4_REGISTER_OFFSET, + EVERGREEN_CRTC5_REGISTER_OFFSET +}; + static void evergreen_gpu_init(struct radeon_device *rdev); void evergreen_fini(struct radeon_device *rdev); void evergreen_pcie_gen2_enable(struct radeon_device *rdev); @@ -101,17 +111,19 @@ void evergreen_fix_pci_max_read_req_size(struct radeon_device *rdev) void dce4_wait_for_vblank(struct radeon_device *rdev, int crtc) { - struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc]; int i; - if (RREG32(EVERGREEN_CRTC_CONTROL + radeon_crtc->crtc_offset) & EVERGREEN_CRTC_MASTER_EN) { + if (crtc >= rdev->num_crtc) + return; + + if (RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[crtc]) & EVERGREEN_CRTC_MASTER_EN) { for (i = 0; i < rdev->usec_timeout; i++) { - if (!(RREG32(EVERGREEN_CRTC_STATUS + radeon_crtc->crtc_offset) & EVERGREEN_CRTC_V_BLANK)) + if (!(RREG32(EVERGREEN_CRTC_STATUS + crtc_offsets[crtc]) & EVERGREEN_CRTC_V_BLANK)) break; udelay(1); } for (i = 0; i < rdev->usec_timeout; i++) { - if (RREG32(EVERGREEN_CRTC_STATUS + radeon_crtc->crtc_offset) & EVERGREEN_CRTC_V_BLANK) + if (RREG32(EVERGREEN_CRTC_STATUS + crtc_offsets[crtc]) & EVERGREEN_CRTC_V_BLANK) break; udelay(1); } @@ -1117,175 +1129,117 @@ void evergreen_agp_enable(struct radeon_device *rdev) void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save) { - save->vga_control[0] = RREG32(D1VGA_CONTROL); - save->vga_control[1] = RREG32(D2VGA_CONTROL); + u32 crtc_enabled, tmp, frame_count, blackout; + int i, j; + save->vga_render_control = RREG32(VGA_RENDER_CONTROL); save->vga_hdp_control = RREG32(VGA_HDP_CONTROL); - save->crtc_control[0] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET); - save->crtc_control[1] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET); - if (rdev->num_crtc >= 4) { - save->vga_control[2] = RREG32(EVERGREEN_D3VGA_CONTROL); - save->vga_control[3] = RREG32(EVERGREEN_D4VGA_CONTROL); - save->crtc_control[2] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET); - save->crtc_control[3] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET); - } - if (rdev->num_crtc >= 6) { - save->vga_control[4] = RREG32(EVERGREEN_D5VGA_CONTROL); - save->vga_control[5] = RREG32(EVERGREEN_D6VGA_CONTROL); - save->crtc_control[4] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET); - save->crtc_control[5] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET); - } - /* Stop all video */ + /* disable VGA render */ WREG32(VGA_RENDER_CONTROL, 0); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 1); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 1); - if (rdev->num_crtc >= 4) { - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 1); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 1); - } - if (rdev->num_crtc >= 6) { - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 1); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 1); - } - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); - if (rdev->num_crtc >= 4) { - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); - } - if (rdev->num_crtc >= 6) { - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); - } - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); - if (rdev->num_crtc >= 4) { - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); - } - if (rdev->num_crtc >= 6) { - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); + /* blank the display controllers */ + for (i = 0; i < rdev->num_crtc; i++) { + crtc_enabled = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]) & EVERGREEN_CRTC_MASTER_EN; + if (crtc_enabled) { + save->crtc_enabled[i] = true; + if (ASIC_IS_DCE6(rdev)) { + tmp = RREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i]); + if (!(tmp & EVERGREEN_CRTC_BLANK_DATA_EN)) { + radeon_wait_for_vblank(rdev, i); + tmp |= EVERGREEN_CRTC_BLANK_DATA_EN; + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1); + WREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i], tmp); + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0); + } + } else { + tmp = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]); + if (!(tmp & EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE)) { + radeon_wait_for_vblank(rdev, i); + tmp |= EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE; + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1); + WREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i], tmp); + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0); + } + } + /* wait for the next frame */ + frame_count = radeon_get_vblank_counter(rdev, i); + for (j = 0; j < rdev->usec_timeout; j++) { + if (radeon_get_vblank_counter(rdev, i) != frame_count) + break; + udelay(1); + } + } else { + save->crtc_enabled[i] = false; + } } - WREG32(D1VGA_CONTROL, 0); - WREG32(D2VGA_CONTROL, 0); - if (rdev->num_crtc >= 4) { - WREG32(EVERGREEN_D3VGA_CONTROL, 0); - WREG32(EVERGREEN_D4VGA_CONTROL, 0); - } - if (rdev->num_crtc >= 6) { - WREG32(EVERGREEN_D5VGA_CONTROL, 0); - WREG32(EVERGREEN_D6VGA_CONTROL, 0); + radeon_mc_wait_for_idle(rdev); + + blackout = RREG32(MC_SHARED_BLACKOUT_CNTL); + if ((blackout & BLACKOUT_MODE_MASK) != 1) { + /* Block CPU access */ + WREG32(BIF_FB_EN, 0); + /* blackout the MC */ + blackout &= ~BLACKOUT_MODE_MASK; + WREG32(MC_SHARED_BLACKOUT_CNTL, blackout | 1); } + /* wait for the MC to settle */ + udelay(100); } void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save) { - WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC0_REGISTER_OFFSET, - upper_32_bits(rdev->mc.vram_start)); - WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC0_REGISTER_OFFSET, - upper_32_bits(rdev->mc.vram_start)); - WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC0_REGISTER_OFFSET, - (u32)rdev->mc.vram_start); - WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC0_REGISTER_OFFSET, - (u32)rdev->mc.vram_start); - - WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC1_REGISTER_OFFSET, - upper_32_bits(rdev->mc.vram_start)); - WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC1_REGISTER_OFFSET, - upper_32_bits(rdev->mc.vram_start)); - WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC1_REGISTER_OFFSET, - (u32)rdev->mc.vram_start); - WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC1_REGISTER_OFFSET, - (u32)rdev->mc.vram_start); - - if (rdev->num_crtc >= 4) { - WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC2_REGISTER_OFFSET, - upper_32_bits(rdev->mc.vram_start)); - WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC2_REGISTER_OFFSET, - upper_32_bits(rdev->mc.vram_start)); - WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC2_REGISTER_OFFSET, - (u32)rdev->mc.vram_start); - WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC2_REGISTER_OFFSET, - (u32)rdev->mc.vram_start); - - WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC3_REGISTER_OFFSET, - upper_32_bits(rdev->mc.vram_start)); - WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC3_REGISTER_OFFSET, - upper_32_bits(rdev->mc.vram_start)); - WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC3_REGISTER_OFFSET, - (u32)rdev->mc.vram_start); - WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC3_REGISTER_OFFSET, - (u32)rdev->mc.vram_start); - } - if (rdev->num_crtc >= 6) { - WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC4_REGISTER_OFFSET, - upper_32_bits(rdev->mc.vram_start)); - WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC4_REGISTER_OFFSET, - upper_32_bits(rdev->mc.vram_start)); - WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC4_REGISTER_OFFSET, - (u32)rdev->mc.vram_start); - WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC4_REGISTER_OFFSET, - (u32)rdev->mc.vram_start); + u32 tmp, frame_count; + int i, j; - WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC5_REGISTER_OFFSET, + /* update crtc base addresses */ + for (i = 0; i < rdev->num_crtc; i++) { + WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + crtc_offsets[i], upper_32_bits(rdev->mc.vram_start)); - WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC5_REGISTER_OFFSET, + WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + crtc_offsets[i], upper_32_bits(rdev->mc.vram_start)); - WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + EVERGREEN_CRTC5_REGISTER_OFFSET, + WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + crtc_offsets[i], (u32)rdev->mc.vram_start); - WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + EVERGREEN_CRTC5_REGISTER_OFFSET, + WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + crtc_offsets[i], (u32)rdev->mc.vram_start); } - WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS_HIGH, upper_32_bits(rdev->mc.vram_start)); WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS, (u32)rdev->mc.vram_start); - /* Unlock host access */ + + /* unblackout the MC */ + tmp = RREG32(MC_SHARED_BLACKOUT_CNTL); + tmp &= ~BLACKOUT_MODE_MASK; + WREG32(MC_SHARED_BLACKOUT_CNTL, tmp); + /* allow CPU access */ + WREG32(BIF_FB_EN, FB_READ_EN | FB_WRITE_EN); + + for (i = 0; i < rdev->num_crtc; i++) { + if (save->crtc_enabled) { + if (ASIC_IS_DCE6(rdev)) { + tmp = RREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i]); + tmp |= EVERGREEN_CRTC_BLANK_DATA_EN; + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1); + WREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i], tmp); + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0); + } else { + tmp = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]); + tmp &= ~EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE; + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1); + WREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i], tmp); + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0); + } + /* wait for the next frame */ + frame_count = radeon_get_vblank_counter(rdev, i); + for (j = 0; j < rdev->usec_timeout; j++) { + if (radeon_get_vblank_counter(rdev, i) != frame_count) + break; + udelay(1); + } + } + } + /* Unlock vga access */ WREG32(VGA_HDP_CONTROL, save->vga_hdp_control); mdelay(1); - /* Restore video state */ - WREG32(D1VGA_CONTROL, save->vga_control[0]); - WREG32(D2VGA_CONTROL, save->vga_control[1]); - if (rdev->num_crtc >= 4) { - WREG32(EVERGREEN_D3VGA_CONTROL, save->vga_control[2]); - WREG32(EVERGREEN_D4VGA_CONTROL, save->vga_control[3]); - } - if (rdev->num_crtc >= 6) { - WREG32(EVERGREEN_D5VGA_CONTROL, save->vga_control[4]); - WREG32(EVERGREEN_D6VGA_CONTROL, save->vga_control[5]); - } - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 1); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 1); - if (rdev->num_crtc >= 4) { - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 1); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 1); - } - if (rdev->num_crtc >= 6) { - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 1); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 1); - } - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, save->crtc_control[0]); - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, save->crtc_control[1]); - if (rdev->num_crtc >= 4) { - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, save->crtc_control[2]); - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, save->crtc_control[3]); - } - if (rdev->num_crtc >= 6) { - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, save->crtc_control[4]); - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, save->crtc_control[5]); - } - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); - if (rdev->num_crtc >= 4) { - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); - } - if (rdev->num_crtc >= 6) { - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); - } WREG32(VGA_RENDER_CONTROL, save->vga_render_control); } @@ -2142,10 +2096,18 @@ static void evergreen_gpu_init(struct radeon_device *rdev) if (rdev->flags & RADEON_IS_IGP) rdev->config.evergreen.tile_config |= 1 << 4; else { - if ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) - rdev->config.evergreen.tile_config |= 1 << 4; - else + switch ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) { + case 0: /* four banks */ rdev->config.evergreen.tile_config |= 0 << 4; + break; + case 1: /* eight banks */ + rdev->config.evergreen.tile_config |= 1 << 4; + break; + case 2: /* sixteen banks */ + default: + rdev->config.evergreen.tile_config |= 2 << 4; + break; + } } rdev->config.evergreen.tile_config |= ((mc_arb_ramcfg & BURSTLENGTH_MASK) >> BURSTLENGTH_SHIFT) << 8; diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c index ea69daeffac..2cbd369e0fc 100644 --- a/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/drivers/gpu/drm/radeon/evergreen_cs.c @@ -2670,7 +2670,11 @@ static bool evergreen_vm_reg_valid(u32 reg) /* check config regs */ switch (reg) { + case WAIT_UNTIL: case GRBM_GFX_INDEX: + case CP_STRMOUT_CNTL: + case CP_COHER_CNTL: + case CP_COHER_SIZE: case VGT_VTX_VECT_EJECT_REG: case VGT_CACHE_INVALIDATION: case VGT_GS_VERTEX_REUSE: @@ -2775,6 +2779,7 @@ static bool evergreen_vm_reg_valid(u32 reg) case CAYMAN_SQ_EX_ALLOC_TABLE_SLOTS: return true; default: + DRM_ERROR("Invalid register 0x%x in CS\n", reg); return false; } } diff --git a/drivers/gpu/drm/radeon/evergreen_reg.h b/drivers/gpu/drm/radeon/evergreen_reg.h index 96c10b3991a..34a0e856069 100644 --- a/drivers/gpu/drm/radeon/evergreen_reg.h +++ b/drivers/gpu/drm/radeon/evergreen_reg.h @@ -218,6 +218,8 @@ #define EVERGREEN_CRTC_CONTROL 0x6e70 # define EVERGREEN_CRTC_MASTER_EN (1 << 0) # define EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE (1 << 24) +#define EVERGREEN_CRTC_BLANK_CONTROL 0x6e74 +# define EVERGREEN_CRTC_BLANK_DATA_EN (1 << 8) #define EVERGREEN_CRTC_STATUS 0x6e8c # define EVERGREEN_CRTC_V_BLANK (1 << 0) #define EVERGREEN_CRTC_STATUS_POSITION 0x6e90 diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h index f62ccd3555d..81e744fab31 100644 --- a/drivers/gpu/drm/radeon/evergreend.h +++ b/drivers/gpu/drm/radeon/evergreend.h @@ -77,6 +77,14 @@ #define CONFIG_MEMSIZE 0x5428 +#define BIF_FB_EN 0x5490 +#define FB_READ_EN (1 << 0) +#define FB_WRITE_EN (1 << 1) + +#define CP_STRMOUT_CNTL 0x84FC + +#define CP_COHER_CNTL 0x85F0 +#define CP_COHER_SIZE 0x85F4 #define CP_COHER_BASE 0x85F8 #define CP_ME_CNTL 0x86D8 #define CP_ME_HALT (1 << 28) @@ -196,6 +204,9 @@ #define NOOFCHAN_MASK 0x00003000 #define MC_SHARED_CHREMAP 0x2008 +#define MC_SHARED_BLACKOUT_CNTL 0x20ac +#define BLACKOUT_MODE_MASK 0x00000007 + #define MC_ARB_RAMCFG 0x2760 #define NOOFBANK_SHIFT 0 #define NOOFBANK_MASK 0x00000003 diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index ad0a38007de..9934c9d9e51 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c @@ -880,10 +880,18 @@ static void cayman_gpu_init(struct radeon_device *rdev) if (rdev->flags & RADEON_IS_IGP) rdev->config.cayman.tile_config |= 1 << 4; else { - if ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) - rdev->config.cayman.tile_config |= 1 << 4; - else + switch ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) { + case 0: /* four banks */ rdev->config.cayman.tile_config |= 0 << 4; + break; + case 1: /* eight banks */ + rdev->config.cayman.tile_config |= 1 << 4; + break; + case 2: /* sixteen banks */ + default: + rdev->config.cayman.tile_config |= 2 << 4; + break; + } } rdev->config.cayman.tile_config |= ((gb_addr_config & PIPE_INTERLEAVE_SIZE_MASK) >> PIPE_INTERLEAVE_SIZE_SHIFT) << 8; diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 138b95216d8..66150f0ffc7 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -138,21 +138,6 @@ struct radeon_device; /* * BIOS. */ -#define ATRM_BIOS_PAGE 4096 - -#if defined(CONFIG_VGA_SWITCHEROO) -bool radeon_atrm_supported(struct pci_dev *pdev); -int radeon_atrm_get_bios_chunk(uint8_t *bios, int offset, int len); -#else -static inline bool radeon_atrm_supported(struct pci_dev *pdev) -{ - return false; -} - -static inline int radeon_atrm_get_bios_chunk(uint8_t *bios, int offset, int len){ - return -EINVAL; -} -#endif bool radeon_get_bios(struct radeon_device *rdev); diff --git a/drivers/gpu/drm/radeon/radeon_agp.c b/drivers/gpu/drm/radeon/radeon_agp.c index bd2f33e5c91..bc6b64fe0e0 100644 --- a/drivers/gpu/drm/radeon/radeon_agp.c +++ b/drivers/gpu/drm/radeon/radeon_agp.c @@ -70,9 +70,12 @@ static struct radeon_agpmode_quirk radeon_agpmode_quirk_list[] = { /* Intel 82830 830 Chipset Host Bridge / Mobility M6 LY Needs AGPMode 2 (fdo #17360)*/ { PCI_VENDOR_ID_INTEL, 0x3575, PCI_VENDOR_ID_ATI, 0x4c59, PCI_VENDOR_ID_DELL, 0x00e3, 2}, - /* Intel 82852/82855 host bridge / Mobility FireGL 9000 R250 Needs AGPMode 1 (lp #296617) */ + /* Intel 82852/82855 host bridge / Mobility FireGL 9000 RV250 Needs AGPMode 1 (lp #296617) */ { PCI_VENDOR_ID_INTEL, 0x3580, PCI_VENDOR_ID_ATI, 0x4c66, PCI_VENDOR_ID_DELL, 0x0149, 1}, + /* Intel 82855PM host bridge / Mobility FireGL 9000 RV250 Needs AGPMode 1 for suspend/resume */ + { PCI_VENDOR_ID_INTEL, 0x3340, PCI_VENDOR_ID_ATI, 0x4c66, + PCI_VENDOR_ID_IBM, 0x0531, 1}, /* Intel 82852/82855 host bridge / Mobility 9600 M10 RV350 Needs AGPMode 1 (deb #467460) */ { PCI_VENDOR_ID_INTEL, 0x3580, PCI_VENDOR_ID_ATI, 0x4e50, 0x1025, 0x0061, 1}, diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index 3d9f9f1d8f9..917e49cb490 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h @@ -262,13 +262,10 @@ extern int rs690_mc_wait_for_idle(struct radeon_device *rdev); * rv515 */ struct rv515_mc_save { - u32 d1vga_control; - u32 d2vga_control; u32 vga_render_control; u32 vga_hdp_control; - u32 d1crtc_control; - u32 d2crtc_control; }; + int rv515_init(struct radeon_device *rdev); void rv515_fini(struct radeon_device *rdev); uint32_t rv515_mc_rreg(struct radeon_device *rdev, uint32_t reg); @@ -401,11 +398,11 @@ void r700_cp_fini(struct radeon_device *rdev); * evergreen */ struct evergreen_mc_save { - u32 vga_control[6]; u32 vga_render_control; u32 vga_hdp_control; - u32 crtc_control[6]; + bool crtc_enabled[RADEON_MAX_CRTCS]; }; + void evergreen_pcie_gart_tlb_flush(struct radeon_device *rdev); int evergreen_init(struct radeon_device *rdev); void evergreen_fini(struct radeon_device *rdev); diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index b1e3820df36..5e30e126bfe 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -452,7 +452,7 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev, } /* Fujitsu D3003-S2 board lists DVI-I as DVI-D and VGA */ - if ((dev->pdev->device == 0x9802) && + if (((dev->pdev->device == 0x9802) || (dev->pdev->device == 0x9806)) && (dev->pdev->subsystem_vendor == 0x1734) && (dev->pdev->subsystem_device == 0x11bd)) { if (*connector_type == DRM_MODE_CONNECTOR_VGA) { diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c b/drivers/gpu/drm/radeon/radeon_atpx_handler.c index 98724fcb008..2a2cf0b88a2 100644 --- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c +++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c @@ -30,57 +30,8 @@ static struct radeon_atpx_priv { /* handle for device - and atpx */ acpi_handle dhandle; acpi_handle atpx_handle; - acpi_handle atrm_handle; } radeon_atpx_priv; -/* retrieve the ROM in 4k blocks */ -static int radeon_atrm_call(acpi_handle atrm_handle, uint8_t *bios, - int offset, int len) -{ - acpi_status status; - union acpi_object atrm_arg_elements[2], *obj; - struct acpi_object_list atrm_arg; - struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL}; - - atrm_arg.count = 2; - atrm_arg.pointer = &atrm_arg_elements[0]; - - atrm_arg_elements[0].type = ACPI_TYPE_INTEGER; - atrm_arg_elements[0].integer.value = offset; - - atrm_arg_elements[1].type = ACPI_TYPE_INTEGER; - atrm_arg_elements[1].integer.value = len; - - status = acpi_evaluate_object(atrm_handle, NULL, &atrm_arg, &buffer); - if (ACPI_FAILURE(status)) { - printk("failed to evaluate ATRM got %s\n", acpi_format_exception(status)); - return -ENODEV; - } - - obj = (union acpi_object *)buffer.pointer; - memcpy(bios+offset, obj->buffer.pointer, obj->buffer.length); - len = obj->buffer.length; - kfree(buffer.pointer); - return len; -} - -bool radeon_atrm_supported(struct pci_dev *pdev) -{ - /* get the discrete ROM only via ATRM */ - if (!radeon_atpx_priv.atpx_detected) - return false; - - if (radeon_atpx_priv.dhandle == DEVICE_ACPI_HANDLE(&pdev->dev)) - return false; - return true; -} - - -int radeon_atrm_get_bios_chunk(uint8_t *bios, int offset, int len) -{ - return radeon_atrm_call(radeon_atpx_priv.atrm_handle, bios, offset, len); -} - static int radeon_atpx_get_version(acpi_handle handle) { acpi_status status; @@ -198,7 +149,7 @@ static int radeon_atpx_power_state(enum vga_switcheroo_client_id id, static bool radeon_atpx_pci_probe_handle(struct pci_dev *pdev) { - acpi_handle dhandle, atpx_handle, atrm_handle; + acpi_handle dhandle, atpx_handle; acpi_status status; dhandle = DEVICE_ACPI_HANDLE(&pdev->dev); @@ -209,13 +160,8 @@ static bool radeon_atpx_pci_probe_handle(struct pci_dev *pdev) if (ACPI_FAILURE(status)) return false; - status = acpi_get_handle(dhandle, "ATRM", &atrm_handle); - if (ACPI_FAILURE(status)) - return false; - radeon_atpx_priv.dhandle = dhandle; radeon_atpx_priv.atpx_handle = atpx_handle; - radeon_atpx_priv.atrm_handle = atrm_handle; return true; } diff --git a/drivers/gpu/drm/radeon/radeon_bios.c b/drivers/gpu/drm/radeon/radeon_bios.c index 501f4881e5a..d306cc8fdea 100644 --- a/drivers/gpu/drm/radeon/radeon_bios.c +++ b/drivers/gpu/drm/radeon/radeon_bios.c @@ -32,6 +32,7 @@ #include #include +#include /* * BIOS. */ @@ -98,16 +99,81 @@ static bool radeon_read_bios(struct radeon_device *rdev) return true; } +#ifdef CONFIG_ACPI /* ATRM is used to get the BIOS on the discrete cards in * dual-gpu systems. */ +/* retrieve the ROM in 4k blocks */ +#define ATRM_BIOS_PAGE 4096 +/** + * radeon_atrm_call - fetch a chunk of the vbios + * + * @atrm_handle: acpi ATRM handle + * @bios: vbios image pointer + * @offset: offset of vbios image data to fetch + * @len: length of vbios image data to fetch + * + * Executes ATRM to fetch a chunk of the discrete + * vbios image on PX systems (all asics). + * Returns the length of the buffer fetched. + */ +static int radeon_atrm_call(acpi_handle atrm_handle, uint8_t *bios, + int offset, int len) +{ + acpi_status status; + union acpi_object atrm_arg_elements[2], *obj; + struct acpi_object_list atrm_arg; + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL}; + + atrm_arg.count = 2; + atrm_arg.pointer = &atrm_arg_elements[0]; + + atrm_arg_elements[0].type = ACPI_TYPE_INTEGER; + atrm_arg_elements[0].integer.value = offset; + + atrm_arg_elements[1].type = ACPI_TYPE_INTEGER; + atrm_arg_elements[1].integer.value = len; + + status = acpi_evaluate_object(atrm_handle, NULL, &atrm_arg, &buffer); + if (ACPI_FAILURE(status)) { + printk("failed to evaluate ATRM got %s\n", acpi_format_exception(status)); + return -ENODEV; + } + + obj = (union acpi_object *)buffer.pointer; + memcpy(bios+offset, obj->buffer.pointer, obj->buffer.length); + len = obj->buffer.length; + kfree(buffer.pointer); + return len; +} + static bool radeon_atrm_get_bios(struct radeon_device *rdev) { int ret; int size = 256 * 1024; int i; + struct pci_dev *pdev = NULL; + acpi_handle dhandle, atrm_handle; + acpi_status status; + bool found = false; + + /* ATRM is for the discrete card only */ + if (rdev->flags & RADEON_IS_IGP) + return false; + + while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) { + dhandle = DEVICE_ACPI_HANDLE(&pdev->dev); + if (!dhandle) + continue; + + status = acpi_get_handle(dhandle, "ATRM", &atrm_handle); + if (!ACPI_FAILURE(status)) { + found = true; + break; + } + } - if (!radeon_atrm_supported(rdev->pdev)) + if (!found) return false; rdev->bios = kmalloc(size, GFP_KERNEL); @@ -117,9 +183,10 @@ static bool radeon_atrm_get_bios(struct radeon_device *rdev) } for (i = 0; i < size / ATRM_BIOS_PAGE; i++) { - ret = radeon_atrm_get_bios_chunk(rdev->bios, - (i * ATRM_BIOS_PAGE), - ATRM_BIOS_PAGE); + ret = radeon_atrm_call(atrm_handle, + rdev->bios, + (i * ATRM_BIOS_PAGE), + ATRM_BIOS_PAGE); if (ret < ATRM_BIOS_PAGE) break; } @@ -130,6 +197,12 @@ static bool radeon_atrm_get_bios(struct radeon_device *rdev) } return true; } +#else +static inline bool radeon_atrm_get_bios(struct radeon_device *rdev) +{ + return false; +} +#endif static bool ni_read_disabled_bios(struct radeon_device *rdev) { @@ -476,6 +549,61 @@ static bool radeon_read_disabled_bios(struct radeon_device *rdev) return legacy_read_disabled_bios(rdev); } +#ifdef CONFIG_ACPI +static bool radeon_acpi_vfct_bios(struct radeon_device *rdev) +{ + bool ret = false; + struct acpi_table_header *hdr; + acpi_size tbl_size; + UEFI_ACPI_VFCT *vfct; + GOP_VBIOS_CONTENT *vbios; + VFCT_IMAGE_HEADER *vhdr; + + if (!ACPI_SUCCESS(acpi_get_table_with_size("VFCT", 1, &hdr, &tbl_size))) + return false; + if (tbl_size < sizeof(UEFI_ACPI_VFCT)) { + DRM_ERROR("ACPI VFCT table present but broken (too short #1)\n"); + goto out_unmap; + } + + vfct = (UEFI_ACPI_VFCT *)hdr; + if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) > tbl_size) { + DRM_ERROR("ACPI VFCT table present but broken (too short #2)\n"); + goto out_unmap; + } + + vbios = (GOP_VBIOS_CONTENT *)((char *)hdr + vfct->VBIOSImageOffset); + vhdr = &vbios->VbiosHeader; + DRM_INFO("ACPI VFCT contains a BIOS for %02x:%02x.%d %04x:%04x, size %d\n", + vhdr->PCIBus, vhdr->PCIDevice, vhdr->PCIFunction, + vhdr->VendorID, vhdr->DeviceID, vhdr->ImageLength); + + if (vhdr->PCIBus != rdev->pdev->bus->number || + vhdr->PCIDevice != PCI_SLOT(rdev->pdev->devfn) || + vhdr->PCIFunction != PCI_FUNC(rdev->pdev->devfn) || + vhdr->VendorID != rdev->pdev->vendor || + vhdr->DeviceID != rdev->pdev->device) { + DRM_INFO("ACPI VFCT table is not for this card\n"); + goto out_unmap; + }; + + if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) + vhdr->ImageLength > tbl_size) { + DRM_ERROR("ACPI VFCT image truncated\n"); + goto out_unmap; + } + + rdev->bios = kmemdup(&vbios->VbiosContent, vhdr->ImageLength, GFP_KERNEL); + ret = !!rdev->bios; + +out_unmap: + return ret; +} +#else +static inline bool radeon_acpi_vfct_bios(struct radeon_device *rdev) +{ + return false; +} +#endif bool radeon_get_bios(struct radeon_device *rdev) { @@ -483,6 +611,8 @@ bool radeon_get_bios(struct radeon_device *rdev) uint16_t tmp; r = radeon_atrm_get_bios(rdev); + if (r == false) + r = radeon_acpi_vfct_bios(rdev); if (r == false) r = igp_read_bios_from_vram(rdev); if (r == false) diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index 2cad9fde92f..a2470d96deb 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c @@ -2338,6 +2338,14 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) 1), ATOM_DEVICE_CRT1_SUPPORT); } + /* RV100 board with external TDMS bit mis-set. + * Actually uses internal TMDS, clear the bit. + */ + if (dev->pdev->device == 0x5159 && + dev->pdev->subsystem_vendor == 0x1014 && + dev->pdev->subsystem_device == 0x029A) { + tmp &= ~(1 << 4); + } if ((tmp >> 4) & 0x1) { devices |= ATOM_DEVICE_DFP2_SUPPORT; radeon_add_legacy_encoder(dev, diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 3c2e7a000a2..ab63bcd1727 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -64,14 +64,33 @@ void radeon_connector_hotplug(struct drm_connector *connector) /* just deal with DP (not eDP) here. */ if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) { - int saved_dpms = connector->dpms; - - /* Only turn off the display it it's physically disconnected */ - if (!radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) - drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); - else if (radeon_dp_needs_link_train(radeon_connector)) - drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON); - connector->dpms = saved_dpms; + struct radeon_connector_atom_dig *dig_connector = + radeon_connector->con_priv; + + /* if existing sink type was not DP no need to retrain */ + if (dig_connector->dp_sink_type != CONNECTOR_OBJECT_ID_DISPLAYPORT) + return; + + /* first get sink type as it may be reset after (un)plug */ + dig_connector->dp_sink_type = radeon_dp_getsinktype(radeon_connector); + /* don't do anything if sink is not display port, i.e., + * passive dp->(dvi|hdmi) adaptor + */ + if (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) { + int saved_dpms = connector->dpms; + /* Only turn off the display if it's physically disconnected */ + if (!radeon_hpd_sense(rdev, radeon_connector->hpd.hpd)) { + drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF); + } else if (radeon_dp_needs_link_train(radeon_connector)) { + /* set it to OFF so that drm_helper_connector_dpms() + * won't return immediately since the current state + * is ON at this point. + */ + connector->dpms = DRM_MODE_DPMS_OFF; + drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON); + } + connector->dpms = saved_dpms; + } } } @@ -670,7 +689,7 @@ radeon_vga_detect(struct drm_connector *connector, bool force) ret = connector_status_disconnected; if (radeon_connector->ddc_bus) - dret = radeon_ddc_probe(radeon_connector); + dret = radeon_ddc_probe(radeon_connector, false); if (dret) { radeon_connector->detected_by_load = false; if (radeon_connector->edid) { @@ -876,7 +895,7 @@ radeon_dvi_detect(struct drm_connector *connector, bool force) return connector->status; if (radeon_connector->ddc_bus) - dret = radeon_ddc_probe(radeon_connector); + dret = radeon_ddc_probe(radeon_connector, false); if (dret) { radeon_connector->detected_by_load = false; if (radeon_connector->edid) { @@ -1316,7 +1335,8 @@ radeon_dp_detect(struct drm_connector *connector, bool force) if (encoder) { /* setup ddc on the bridge */ radeon_atom_ext_encoder_setup_ddc(encoder); - if (radeon_ddc_probe(radeon_connector)) /* try DDC */ + /* bridge chips are always aux */ + if (radeon_ddc_probe(radeon_connector, true)) /* try DDC */ ret = connector_status_connected; else if (radeon_connector->dac_load_detect) { /* try load detection */ struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; @@ -1334,7 +1354,8 @@ radeon_dp_detect(struct drm_connector *connector, bool force) if (radeon_dp_getdpcd(radeon_connector)) ret = connector_status_connected; } else { - if (radeon_ddc_probe(radeon_connector)) + /* try non-aux ddc (DP to DVI/HMDI/etc. adapter) */ + if (radeon_ddc_probe(radeon_connector, false)) ret = connector_status_connected; } } diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index 2418cf6da1c..cf723c4297a 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c @@ -377,7 +377,7 @@ static int radeon_cs_ib_chunk(struct radeon_device *rdev, if (r) { DRM_ERROR("Failed to schedule IB !\n"); } - return 0; + return r; } static int radeon_bo_vm_update_pte(struct radeon_cs_parser *parser, diff --git a/drivers/gpu/drm/radeon/radeon_cursor.c b/drivers/gpu/drm/radeon/radeon_cursor.c index 42acc6449dd..8fb6f41bd1f 100644 --- a/drivers/gpu/drm/radeon/radeon_cursor.c +++ b/drivers/gpu/drm/radeon/radeon_cursor.c @@ -238,7 +238,8 @@ int radeon_crtc_cursor_move(struct drm_crtc *crtc, y = 0; } - if (ASIC_IS_AVIVO(rdev)) { + /* fixed on DCE6 and newer */ + if (ASIC_IS_AVIVO(rdev) && !ASIC_IS_DCE6(rdev)) { int i = 0; struct drm_crtc *crtc_p; @@ -262,8 +263,14 @@ int radeon_crtc_cursor_move(struct drm_crtc *crtc, if (!(cursor_end & 0x7f)) w--; } - if (w <= 0) + if (w <= 0) { w = 1; + cursor_end = x - xorigin + w; + if (!(cursor_end & 0x7f)) { + x--; + WARN_ON_ONCE(x < 0); + } + } } } diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 5992502a344..de5e0b51dc6 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -772,7 +772,7 @@ int radeon_device_init(struct radeon_device *rdev, if (rdev->flags & RADEON_IS_AGP) rdev->need_dma32 = true; if ((rdev->flags & RADEON_IS_PCI) && - (rdev->family < CHIP_RS400)) + (rdev->family <= CHIP_RS740)) rdev->need_dma32 = true; dma_bits = rdev->need_dma32 ? 32 : 40; diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 0a1d4bd65ed..00d9cac69f9 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -713,10 +713,15 @@ int radeon_ddc_get_modes(struct radeon_connector *radeon_connector) if (radeon_connector->router.ddc_valid) radeon_router_select_ddc_port(radeon_connector); - if ((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) || - (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP) || - (radeon_connector_encoder_get_dp_bridge_encoder_id(&radeon_connector->base) != - ENCODER_OBJECT_ID_NONE)) { + if (radeon_connector_encoder_get_dp_bridge_encoder_id(&radeon_connector->base) != + ENCODER_OBJECT_ID_NONE) { + struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; + + if (dig->dp_i2c_bus) + radeon_connector->edid = drm_get_edid(&radeon_connector->base, + &dig->dp_i2c_bus->adapter); + } else if ((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) || + (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP)) { struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; if ((dig->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT || @@ -1124,14 +1129,16 @@ radeon_user_framebuffer_create(struct drm_device *dev, } radeon_fb = kzalloc(sizeof(*radeon_fb), GFP_KERNEL); - if (radeon_fb == NULL) + if (radeon_fb == NULL) { + drm_gem_object_unreference_unlocked(obj); return ERR_PTR(-ENOMEM); + } ret = radeon_framebuffer_init(dev, radeon_fb, mode_cmd, obj); if (ret) { kfree(radeon_fb); drm_gem_object_unreference_unlocked(obj); - return NULL; + return ERR_PTR(ret); } return &radeon_fb->base; diff --git a/drivers/gpu/drm/radeon/radeon_i2c.c b/drivers/gpu/drm/radeon/radeon_i2c.c index 3edec1c198e..6076e85aa5d 100644 --- a/drivers/gpu/drm/radeon/radeon_i2c.c +++ b/drivers/gpu/drm/radeon/radeon_i2c.c @@ -39,7 +39,7 @@ extern u32 radeon_atom_hw_i2c_func(struct i2c_adapter *adap); * radeon_ddc_probe * */ -bool radeon_ddc_probe(struct radeon_connector *radeon_connector) +bool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool use_aux) { u8 out = 0x0; u8 buf[8]; @@ -63,7 +63,13 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector) if (radeon_connector->router.ddc_valid) radeon_router_select_ddc_port(radeon_connector); - ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2); + if (use_aux) { + struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; + ret = i2c_transfer(&dig->dp_i2c_bus->adapter, msgs, 2); + } else { + ret = i2c_transfer(&radeon_connector->ddc_bus->adapter, msgs, 2); + } + if (ret != 2) /* Couldn't find an accessible DDC on this connector */ return false; diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c index 65060b77c80..645dcbf6490 100644 --- a/drivers/gpu/drm/radeon/radeon_irq_kms.c +++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c @@ -147,6 +147,16 @@ static bool radeon_msi_ok(struct radeon_device *rdev) (rdev->pdev->subsystem_device == 0x01fd)) return true; + /* Gateway RS690 only seems to work with MSIs. */ + if ((rdev->pdev->device == 0x791f) && + (rdev->pdev->subsystem_vendor == 0x107b) && + (rdev->pdev->subsystem_device == 0x0185)) + return true; + + /* try and enable MSIs by default on all RS690s */ + if (rdev->family == CHIP_RS690) + return true; + /* RV515 seems to have MSI issues where it loses * MSI rearms occasionally. This leads to lockups and freezes. * disable it by default. diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c index 210317c7045..9760e5addcc 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c @@ -1025,9 +1025,11 @@ static int radeon_crtc_mode_set(struct drm_crtc *crtc, static void radeon_crtc_prepare(struct drm_crtc *crtc) { + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); struct drm_device *dev = crtc->dev; struct drm_crtc *crtci; + radeon_crtc->in_mode_set = true; /* * The hardware wedges sometimes if you reconfigure one CRTC * whilst another is running (see fdo bug #24611). @@ -1038,6 +1040,7 @@ static void radeon_crtc_prepare(struct drm_crtc *crtc) static void radeon_crtc_commit(struct drm_crtc *crtc) { + struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); struct drm_device *dev = crtc->dev; struct drm_crtc *crtci; @@ -1048,6 +1051,7 @@ static void radeon_crtc_commit(struct drm_crtc *crtc) if (crtci->enabled) radeon_crtc_dpms(crtci, DRM_MODE_DPMS_ON); } + radeon_crtc->in_mode_set = false; } static const struct drm_crtc_helper_funcs legacy_helper_funcs = { diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c index 42db254f6bb..53b07a3a8bb 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c @@ -617,6 +617,14 @@ static enum drm_connector_status radeon_legacy_primary_dac_detect(struct drm_enc enum drm_connector_status found = connector_status_disconnected; bool color = true; + /* just don't bother on RN50 those chip are often connected to remoting + * console hw and often we get failure to load detect those. So to make + * everyone happy report the encoder as always connected. + */ + if (ASIC_IS_RN50(rdev)) { + return connector_status_connected; + } + /* save the regs we need */ vclk_ecp_cntl = RREG32_PLL(RADEON_VCLK_ECP_CNTL); crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL); @@ -650,6 +658,7 @@ static enum drm_connector_status radeon_legacy_primary_dac_detect(struct drm_enc tmp |= RADEON_DAC_RANGE_CNTL_PS2 | RADEON_DAC_CMP_EN; WREG32(RADEON_DAC_CNTL, tmp); + tmp = dac_macro_cntl; tmp &= ~(RADEON_DAC_PDWN_R | RADEON_DAC_PDWN_G | RADEON_DAC_PDWN_B); @@ -973,11 +982,7 @@ static void radeon_legacy_tmds_ext_mode_set(struct drm_encoder *encoder, static void radeon_ext_tmds_enc_destroy(struct drm_encoder *encoder) { struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); - struct radeon_encoder_ext_tmds *tmds = radeon_encoder->enc_priv; - if (tmds) { - if (tmds->i2c_bus) - radeon_i2c_destroy(tmds->i2c_bus); - } + /* don't destroy the i2c bus record here, this will be done in radeon_i2c_fini */ kfree(radeon_encoder->enc_priv); drm_encoder_cleanup(encoder); kfree(radeon_encoder); diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index f7eb5d8b9fd..dabfefda8f5 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -266,6 +266,7 @@ struct radeon_crtc { u16 lut_r[256], lut_g[256], lut_b[256]; bool enabled; bool can_tile; + bool in_mode_set; uint32_t crtc_offset; struct drm_gem_object *cursor_bo; uint64_t cursor_addr; @@ -526,7 +527,7 @@ extern void radeon_i2c_put_byte(struct radeon_i2c_chan *i2c, u8 val); extern void radeon_router_select_ddc_port(struct radeon_connector *radeon_connector); extern void radeon_router_select_cd_port(struct radeon_connector *radeon_connector); -extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector); +extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector, bool use_aux); extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector); extern struct drm_encoder *radeon_best_encoder(struct drm_connector *connector); diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index caa55d68f31..b8459bdce42 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c @@ -567,7 +567,9 @@ void radeon_pm_suspend(struct radeon_device *rdev) void radeon_pm_resume(struct radeon_device *rdev) { /* set up the default clocks if the MC ucode is loaded */ - if (ASIC_IS_DCE5(rdev) && rdev->mc_fw) { + if ((rdev->family >= CHIP_BARTS) && + (rdev->family <= CHIP_CAYMAN) && + rdev->mc_fw) { if (rdev->pm.default_vddc) radeon_atom_set_voltage(rdev, rdev->pm.default_vddc, SET_VOLTAGE_TYPE_ASIC_VDDC); @@ -622,7 +624,9 @@ int radeon_pm_init(struct radeon_device *rdev) radeon_pm_print_states(rdev); radeon_pm_init_profile(rdev); /* set up the default clocks if the MC ucode is loaded */ - if (ASIC_IS_DCE5(rdev) && rdev->mc_fw) { + if ((rdev->family >= CHIP_BARTS) && + (rdev->family <= CHIP_CAYMAN) && + rdev->mc_fw) { if (rdev->pm.default_vddc) radeon_atom_set_voltage(rdev, rdev->pm.default_vddc, SET_VOLTAGE_TYPE_ASIC_VDDC); diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c index cc33b3d7c33..33eff8bcabe 100644 --- a/drivers/gpu/drm/radeon/radeon_ring.c +++ b/drivers/gpu/drm/radeon/radeon_ring.c @@ -311,6 +311,9 @@ int radeon_ring_alloc(struct radeon_device *rdev, struct radeon_ring *ring, unsi { int r; + /* make sure we aren't trying to allocate more space than there is on the ring */ + if (ndw > (ring->ring_size / 4)) + return -ENOMEM; /* Align requested size with padding so unlock_commit can * pad safely */ ndw = (ndw + ring->align_mask) & ~ring->align_mask; diff --git a/drivers/gpu/drm/radeon/reg_srcs/cayman b/drivers/gpu/drm/radeon/reg_srcs/cayman index 0f656b111c1..a072fa8c46b 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/cayman +++ b/drivers/gpu/drm/radeon/reg_srcs/cayman @@ -1,5 +1,6 @@ cayman 0x9400 0x0000802C GRBM_GFX_INDEX +0x00008040 WAIT_UNTIL 0x000084FC CP_STRMOUT_CNTL 0x000085F0 CP_COHER_CNTL 0x000085F4 CP_COHER_SIZE diff --git a/drivers/gpu/drm/radeon/rv515.c b/drivers/gpu/drm/radeon/rv515.c index d8d78fe1794..43af363ead3 100644 --- a/drivers/gpu/drm/radeon/rv515.c +++ b/drivers/gpu/drm/radeon/rv515.c @@ -281,12 +281,8 @@ int rv515_debugfs_ga_info_init(struct radeon_device *rdev) void rv515_mc_stop(struct radeon_device *rdev, struct rv515_mc_save *save) { - save->d1vga_control = RREG32(R_000330_D1VGA_CONTROL); - save->d2vga_control = RREG32(R_000338_D2VGA_CONTROL); save->vga_render_control = RREG32(R_000300_VGA_RENDER_CONTROL); save->vga_hdp_control = RREG32(R_000328_VGA_HDP_CONTROL); - save->d1crtc_control = RREG32(R_006080_D1CRTC_CONTROL); - save->d2crtc_control = RREG32(R_006880_D2CRTC_CONTROL); /* Stop all video */ WREG32(R_0068E8_D2CRTC_UPDATE_LOCK, 0); @@ -311,15 +307,6 @@ void rv515_mc_resume(struct radeon_device *rdev, struct rv515_mc_save *save) /* Unlock host access */ WREG32(R_000328_VGA_HDP_CONTROL, save->vga_hdp_control); mdelay(1); - /* Restore video state */ - WREG32(R_000330_D1VGA_CONTROL, save->d1vga_control); - WREG32(R_000338_D2VGA_CONTROL, save->d2vga_control); - WREG32(R_0060E8_D1CRTC_UPDATE_LOCK, 1); - WREG32(R_0068E8_D2CRTC_UPDATE_LOCK, 1); - WREG32(R_006080_D1CRTC_CONTROL, save->d1crtc_control); - WREG32(R_006880_D2CRTC_CONTROL, save->d2crtc_control); - WREG32(R_0060E8_D1CRTC_UPDATE_LOCK, 0); - WREG32(R_0068E8_D2CRTC_UPDATE_LOCK, 0); WREG32(R_000300_VGA_RENDER_CONTROL, save->vga_render_control); } diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 2af1ce69e6e..1197f2187d7 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -2593,6 +2593,7 @@ static bool si_vm_reg_valid(u32 reg) /* check config regs */ switch (reg) { case GRBM_GFX_INDEX: + case CP_STRMOUT_CNTL: case VGT_VTX_VECT_EJECT_REG: case VGT_CACHE_INVALIDATION: case VGT_ESGS_RING_SIZE: diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h index 53ea2c42dbd..2c2bc63d6da 100644 --- a/drivers/gpu/drm/radeon/sid.h +++ b/drivers/gpu/drm/radeon/sid.h @@ -413,6 +413,7 @@ # define RDERR_INT_ENABLE (1 << 0) # define GUI_IDLE_INT_ENABLE (1 << 19) +#define CP_STRMOUT_CNTL 0x84FC #define SCRATCH_REG0 0x8500 #define SCRATCH_REG1 0x8504 #define SCRATCH_REG2 0x8508 diff --git a/drivers/gpu/drm/savage/savage_bci.c b/drivers/gpu/drm/savage/savage_bci.c index cb1ee4e0050..2a258887e41 100644 --- a/drivers/gpu/drm/savage/savage_bci.c +++ b/drivers/gpu/drm/savage/savage_bci.c @@ -547,6 +547,8 @@ int savage_driver_load(struct drm_device *dev, unsigned long chipset) dev_priv->chipset = (enum savage_family)chipset; + pci_set_master(dev->pdev); + return 0; } diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc.c b/drivers/gpu/drm/ttm/ttm_page_alloc.c index ebc6fac96e3..578207ecc43 100644 --- a/drivers/gpu/drm/ttm/ttm_page_alloc.c +++ b/drivers/gpu/drm/ttm/ttm_page_alloc.c @@ -749,7 +749,10 @@ static int ttm_get_pages(struct page **pages, unsigned npages, int flags, /* clear the pages coming from the pool if requested */ if (flags & TTM_PAGE_FLAG_ZERO_ALLOC) { list_for_each_entry(p, &plist, lru) { - clear_page(page_address(p)); + if (PageHighMem(p)) + clear_highpage(p); + else + clear_page(page_address(p)); } } diff --git a/drivers/gpu/drm/udl/udl_connector.c b/drivers/gpu/drm/udl/udl_connector.c index ba055e9ca00..32342247d91 100644 --- a/drivers/gpu/drm/udl/udl_connector.c +++ b/drivers/gpu/drm/udl/udl_connector.c @@ -22,13 +22,17 @@ static u8 *udl_get_edid(struct udl_device *udl) { u8 *block; - char rbuf[3]; + char *rbuf; int ret, i; block = kmalloc(EDID_LENGTH, GFP_KERNEL); if (block == NULL) return NULL; + rbuf = kmalloc(2, GFP_KERNEL); + if (rbuf == NULL) + goto error; + for (i = 0; i < EDID_LENGTH; i++) { ret = usb_control_msg(udl->ddev->usbdev, usb_rcvctrlpipe(udl->ddev->usbdev, 0), (0x02), @@ -36,16 +40,17 @@ static u8 *udl_get_edid(struct udl_device *udl) HZ); if (ret < 1) { DRM_ERROR("Read EDID byte %d failed err %x\n", i, ret); - i--; goto error; } block[i] = rbuf[1]; } + kfree(rbuf); return block; error: kfree(block); + kfree(rbuf); return NULL; } @@ -59,6 +64,14 @@ static int udl_get_modes(struct drm_connector *connector) connector->display_info.raw_edid = (char *)edid; + /* + * We only read the main block, but if the monitor reports extension + * blocks then the drm edid code expects them to be present, so patch + * the extension count to 0. + */ + edid->checksum += edid->extensions; + edid->extensions = 0; + drm_mode_connector_update_edid_property(connector, edid); ret = drm_add_edid_modes(connector, edid); connector->display_info.raw_edid = NULL; @@ -69,6 +82,13 @@ static int udl_get_modes(struct drm_connector *connector) static int udl_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { + struct udl_device *udl = connector->dev->dev_private; + if (!udl->sku_pixel_limit) + return 0; + + if (mode->vdisplay * mode->hdisplay > udl->sku_pixel_limit) + return MODE_VIRTUAL_Y; + return 0; } diff --git a/drivers/gpu/drm/udl/udl_drv.h b/drivers/gpu/drm/udl/udl_drv.h index 96820d03a30..e7605758661 100644 --- a/drivers/gpu/drm/udl/udl_drv.h +++ b/drivers/gpu/drm/udl/udl_drv.h @@ -103,7 +103,7 @@ udl_fb_user_fb_create(struct drm_device *dev, int udl_render_hline(struct drm_device *dev, int bpp, struct urb **urb_ptr, const char *front, char **urb_buf_ptr, - u32 byte_offset, u32 byte_width, + u32 byte_offset, u32 device_byte_offset, u32 byte_width, int *ident_ptr, int *sent_ptr); int udl_dumb_create(struct drm_file *file_priv, diff --git a/drivers/gpu/drm/udl/udl_fb.c b/drivers/gpu/drm/udl/udl_fb.c index 4d9c3a5d8a4..b9282cf7aea 100644 --- a/drivers/gpu/drm/udl/udl_fb.c +++ b/drivers/gpu/drm/udl/udl_fb.c @@ -114,9 +114,10 @@ static void udlfb_dpy_deferred_io(struct fb_info *info, list_for_each_entry(cur, &fbdefio->pagelist, lru) { if (udl_render_hline(dev, (ufbdev->ufb.base.bits_per_pixel / 8), - &urb, (char *) info->fix.smem_start, - &cmd, cur->index << PAGE_SHIFT, - PAGE_SIZE, &bytes_identical, &bytes_sent)) + &urb, (char *) info->fix.smem_start, + &cmd, cur->index << PAGE_SHIFT, + cur->index << PAGE_SHIFT, + PAGE_SIZE, &bytes_identical, &bytes_sent)) goto error; bytes_rendered += PAGE_SIZE; } @@ -178,10 +179,11 @@ int udl_handle_damage(struct udl_framebuffer *fb, int x, int y, for (i = y; i < y + height ; i++) { const int line_offset = fb->base.pitches[0] * i; const int byte_offset = line_offset + (x * bpp); - + const int dev_byte_offset = (fb->base.width * bpp * i) + (x * bpp); if (udl_render_hline(dev, bpp, &urb, (char *) fb->obj->vmapping, - &cmd, byte_offset, width * bpp, + &cmd, byte_offset, dev_byte_offset, + width * bpp, &bytes_identical, &bytes_sent)) goto error; } diff --git a/drivers/gpu/drm/udl/udl_transfer.c b/drivers/gpu/drm/udl/udl_transfer.c index b9320e2608d..fc1134416bc 100644 --- a/drivers/gpu/drm/udl/udl_transfer.c +++ b/drivers/gpu/drm/udl/udl_transfer.c @@ -213,11 +213,12 @@ static void udl_compress_hline16( */ int udl_render_hline(struct drm_device *dev, int bpp, struct urb **urb_ptr, const char *front, char **urb_buf_ptr, - u32 byte_offset, u32 byte_width, + u32 byte_offset, u32 device_byte_offset, + u32 byte_width, int *ident_ptr, int *sent_ptr) { const u8 *line_start, *line_end, *next_pixel; - u32 base16 = 0 + (byte_offset / bpp) * 2; + u32 base16 = 0 + (device_byte_offset / bpp) * 2; struct urb *urb = *urb_ptr; u8 *cmd = *urb_buf_ptr; u8 *cmd_end = (u8 *) urb->transfer_buffer + urb->transfer_buffer_length; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c index 3fa884db08a..27151f74fec 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_dmabuf.c @@ -306,7 +306,7 @@ void vmw_bo_pin(struct ttm_buffer_object *bo, bool pin) BUG_ON(!atomic_read(&bo->reserved)); BUG_ON(old_mem_type != TTM_PL_VRAM && - old_mem_type != VMW_PL_FLAG_GMR); + old_mem_type != VMW_PL_GMR); pl_flags = TTM_PL_FLAG_VRAM | VMW_PL_FLAG_GMR | TTM_PL_FLAG_CACHED; if (pin) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index ee24d216aa8..db50604ac21 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -182,6 +182,7 @@ static struct pci_device_id vmw_pci_id_list[] = { {0x15ad, 0x0405, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VMWGFX_CHIP_SVGAII}, {0, 0, 0} }; +MODULE_DEVICE_TABLE(pci, vmw_pci_id_list); static int enable_fbdev; @@ -1101,6 +1102,11 @@ static void vmw_pm_complete(struct device *kdev) struct drm_device *dev = pci_get_drvdata(pdev); struct vmw_private *dev_priv = vmw_priv(dev); + mutex_lock(&dev_priv->hw_mutex); + vmw_write(dev_priv, SVGA_REG_ID, SVGA_ID_2); + (void) vmw_read(dev_priv, SVGA_REG_ID); + mutex_unlock(&dev_priv->hw_mutex); + /** * Reclaim 3d reference held by fbdev and potentially * start fifo. @@ -1158,6 +1164,11 @@ static struct drm_driver driver = { .open = vmw_driver_open, .preclose = vmw_preclose, .postclose = vmw_postclose, + + .dumb_create = vmw_dumb_create, + .dumb_map_offset = vmw_dumb_map_offset, + .dumb_destroy = vmw_dumb_destroy, + .fops = &vmwgfx_driver_fops, .name = VMWGFX_DRIVER_NAME, .desc = VMWGFX_DRIVER_DESC, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index d0f2c079ee2..29c984ff7f2 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -645,6 +645,16 @@ int vmw_kms_readback(struct vmw_private *dev_priv, int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); +int vmw_dumb_create(struct drm_file *file_priv, + struct drm_device *dev, + struct drm_mode_create_dumb *args); + +int vmw_dumb_map_offset(struct drm_file *file_priv, + struct drm_device *dev, uint32_t handle, + uint64_t *offset); +int vmw_dumb_destroy(struct drm_file *file_priv, + struct drm_device *dev, + uint32_t handle); /** * Overlay control - vmwgfx_overlay.c */ diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c index f2fb8f15e2f..7e0743358df 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c @@ -1018,7 +1018,7 @@ int vmw_event_fence_action_create(struct drm_file *file_priv, } - event = kzalloc(sizeof(event->event), GFP_KERNEL); + event = kzalloc(sizeof(*event), GFP_KERNEL); if (unlikely(event == NULL)) { DRM_ERROR("Failed to allocate an event.\n"); ret = -ENOMEM; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 2286d47e502..00fb5aa2bf7 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -1688,15 +1688,19 @@ int vmw_du_page_flip(struct drm_crtc *crtc, struct vmw_private *dev_priv = vmw_priv(crtc->dev); struct drm_framebuffer *old_fb = crtc->fb; struct vmw_framebuffer *vfb = vmw_framebuffer_to_vfb(fb); - struct drm_file *file_priv = event->base.file_priv; + struct drm_file *file_priv ; struct vmw_fence_obj *fence = NULL; struct drm_clip_rect clips; int ret; + if (event == NULL) + return -EINVAL; + /* require ScreenObject support for page flipping */ if (!dev_priv->sou_priv) return -ENOSYS; + file_priv = event->base.file_priv; if (!vmw_kms_screen_object_flippable(dev_priv, crtc)) return -EINVAL; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c index a37abb581cb..059b32c6f22 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c @@ -1917,3 +1917,76 @@ int vmw_user_stream_lookup(struct vmw_private *dev_priv, vmw_resource_unreference(&res); return ret; } + + +int vmw_dumb_create(struct drm_file *file_priv, + struct drm_device *dev, + struct drm_mode_create_dumb *args) +{ + struct vmw_private *dev_priv = vmw_priv(dev); + struct vmw_master *vmaster = vmw_master(file_priv->master); + struct vmw_user_dma_buffer *vmw_user_bo; + struct ttm_buffer_object *tmp; + int ret; + + args->pitch = args->width * ((args->bpp + 7) / 8); + args->size = args->pitch * args->height; + + vmw_user_bo = kzalloc(sizeof(*vmw_user_bo), GFP_KERNEL); + if (vmw_user_bo == NULL) + return -ENOMEM; + + ret = ttm_read_lock(&vmaster->lock, true); + if (ret != 0) { + kfree(vmw_user_bo); + return ret; + } + + ret = vmw_dmabuf_init(dev_priv, &vmw_user_bo->dma, args->size, + &vmw_vram_sys_placement, true, + &vmw_user_dmabuf_destroy); + if (ret != 0) + goto out_no_dmabuf; + + tmp = ttm_bo_reference(&vmw_user_bo->dma.base); + ret = ttm_base_object_init(vmw_fpriv(file_priv)->tfile, + &vmw_user_bo->base, + false, + ttm_buffer_type, + &vmw_user_dmabuf_release, NULL); + if (unlikely(ret != 0)) + goto out_no_base_object; + + args->handle = vmw_user_bo->base.hash.key; + +out_no_base_object: + ttm_bo_unref(&tmp); +out_no_dmabuf: + ttm_read_unlock(&vmaster->lock); + return ret; +} + +int vmw_dumb_map_offset(struct drm_file *file_priv, + struct drm_device *dev, uint32_t handle, + uint64_t *offset) +{ + struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; + struct vmw_dma_buffer *out_buf; + int ret; + + ret = vmw_user_dmabuf_lookup(tfile, handle, &out_buf); + if (ret != 0) + return -EINVAL; + + *offset = out_buf->base.addr_space_offset; + vmw_dmabuf_unreference(&out_buf); + return 0; +} + +int vmw_dumb_destroy(struct drm_file *file_priv, + struct drm_device *dev, + uint32_t handle) +{ + return ttm_ref_object_base_unref(vmw_fpriv(file_priv)->tfile, + handle, TTM_REF_USAGE); +} diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c index 299d2387112..899c71200bd 100644 --- a/drivers/hid/hid-apple.c +++ b/drivers/hid/hid-apple.c @@ -514,6 +514,12 @@ static const struct hid_device_id apple_devices[] = { .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS), .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI), + .driver_data = APPLE_HAS_FN }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ISO), + .driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS), + .driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI), .driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO), diff --git a/drivers/hid/hid-chicony.c b/drivers/hid/hid-chicony.c index b99af346fdf..a2abb8e1572 100644 --- a/drivers/hid/hid-chicony.c +++ b/drivers/hid/hid-chicony.c @@ -60,6 +60,7 @@ static int ch_input_mapping(struct hid_device *hdev, struct hid_input *hi, static const struct hid_device_id ch_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) }, { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS2) }, + { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_AK1D) }, { } }; MODULE_DEVICE_TABLE(hid, ch_devices); diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 4da66b4b977..1a92a271adb 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1379,15 +1379,20 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ISO) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUS_T91MT) }, { HID_USB_DEVICE(USB_VENDOR_ID_ASUS, USB_DEVICE_ID_ASUSTEK_MULTITOUCH_YFO) }, { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) }, + { HID_USB_DEVICE(USB_VENDOR_ID_BAANTO, USB_DEVICE_ID_BAANTO_MT_190W2), }, { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE) }, { HID_USB_DEVICE(USB_VENDOR_ID_BTC, USB_DEVICE_ID_BTC_EMPREX_REMOTE_2) }, { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH) }, @@ -1400,12 +1405,14 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) }, { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS) }, { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS2) }, + { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_AK1D) }, { HID_USB_DEVICE(USB_VENDOR_ID_CHUNGHWAT, USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH) }, { HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_PRODIKEYS_PCMIDI) }, { HID_USB_DEVICE(USB_VENDOR_ID_CVTOUCH, USB_DEVICE_ID_CVTOUCH_SCREEN) }, { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) }, { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2) }, { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_3) }, + { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_4) }, { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE) }, { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_TRUETOUCH) }, { HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006) }, @@ -1914,6 +1921,7 @@ static const struct hid_device_id hid_ignore_list[] = { { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MCT) }, { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_HYBRID) }, { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_HEATCONTROL) }, + { HID_USB_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_BEATPAD) }, { HID_USB_DEVICE(USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1024LS) }, { HID_USB_DEVICE(USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1208LS) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICKIT1) }, @@ -2008,6 +2016,9 @@ static const struct hid_device_id hid_mouse_ignore_list[] = { { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ISO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) }, { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, { } diff --git a/drivers/hid/hid-cypress.c b/drivers/hid/hid-cypress.c index 2f0be4c66af..9e43aaca977 100644 --- a/drivers/hid/hid-cypress.c +++ b/drivers/hid/hid-cypress.c @@ -129,6 +129,8 @@ static const struct hid_device_id cp_devices[] = { .driver_data = CP_RDESC_SWAPPED_MIN_MAX }, { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_3), .driver_data = CP_RDESC_SWAPPED_MIN_MAX }, + { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_4), + .driver_data = CP_RDESC_SWAPPED_MIN_MAX }, { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE), .driver_data = CP_2WHEEL_MOUSE_HACK }, { } diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index e39aecb1f9f..72b7b97fe6a 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -125,6 +125,9 @@ #define USB_DEVICE_ID_APPLE_WELLSPRING6_ANSI 0x024c #define USB_DEVICE_ID_APPLE_WELLSPRING6_ISO 0x024d #define USB_DEVICE_ID_APPLE_WELLSPRING6_JIS 0x024e +#define USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI 0x0262 +#define USB_DEVICE_ID_APPLE_WELLSPRING7_ISO 0x0263 +#define USB_DEVICE_ID_APPLE_WELLSPRING7_JIS 0x0264 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI 0x0239 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO 0x023a #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS 0x023b @@ -157,6 +160,9 @@ #define USB_VENDOR_ID_AVERMEDIA 0x07ca #define USB_DEVICE_ID_AVER_FM_MR800 0xb800 +#define USB_VENDOR_ID_BAANTO 0x2453 +#define USB_DEVICE_ID_BAANTO_MT_190W2 0x0100 + #define USB_VENDOR_ID_BELKIN 0x050d #define USB_DEVICE_ID_FLIP_KVM 0x3201 @@ -196,6 +202,7 @@ #define USB_DEVICE_ID_CHICONY_MULTI_TOUCH 0xb19d #define USB_DEVICE_ID_CHICONY_WIRELESS 0x0618 #define USB_DEVICE_ID_CHICONY_WIRELESS2 0x1123 +#define USB_DEVICE_ID_CHICONY_AK1D 0x1125 #define USB_VENDOR_ID_CHUNGHWAT 0x2247 #define USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH 0x0001 @@ -225,6 +232,7 @@ #define USB_DEVICE_ID_CYPRESS_BARCODE_1 0xde61 #define USB_DEVICE_ID_CYPRESS_BARCODE_2 0xde64 #define USB_DEVICE_ID_CYPRESS_BARCODE_3 0xbca1 +#define USB_DEVICE_ID_CYPRESS_BARCODE_4 0xed81 #define USB_DEVICE_ID_CYPRESS_TRUETOUCH 0xc001 #define USB_VENDOR_ID_DEALEXTREAME 0x10c5 @@ -509,6 +517,9 @@ #define USB_DEVICE_ID_CRYSTALTOUCH 0x0006 #define USB_DEVICE_ID_CRYSTALTOUCH_DUAL 0x0007 +#define USB_VENDOR_ID_MADCATZ 0x0738 +#define USB_DEVICE_ID_MADCATZ_BEATPAD 0x4540 + #define USB_VENDOR_ID_MCC 0x09db #define USB_DEVICE_ID_MCC_PMD1024LS 0x0076 #define USB_DEVICE_ID_MCC_PMD1208LS 0x007a @@ -558,6 +569,9 @@ #define USB_VENDOR_ID_NINTENDO 0x057e #define USB_DEVICE_ID_NINTENDO_WIIMOTE 0x0306 +#define USB_VENDOR_ID_NOVATEK 0x0603 +#define USB_DEVICE_ID_NOVATEK_PCT 0x0600 + #define USB_VENDOR_ID_NTRIG 0x1b96 #define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN 0x0001 #define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_1 0x0003 @@ -644,9 +658,15 @@ #define USB_DEVICE_ID_SAMSUNG_IR_REMOTE 0x0001 #define USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE 0x0600 +#define USB_VENDOR_ID_SENNHEISER 0x1395 +#define USB_DEVICE_ID_SENNHEISER_BTD500USB 0x002c + #define USB_VENDOR_ID_SIGMA_MICRO 0x1c4f #define USB_DEVICE_ID_SIGMA_MICRO_KEYBOARD 0x0002 +#define USB_VENDOR_ID_SIGMATEL 0x066F +#define USB_DEVICE_ID_SIGMATEL_STMP3780 0x3780 + #define USB_VENDOR_ID_SKYCABLE 0x1223 #define USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER 0x3F07 diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index c19bff70ce7..43669731afc 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -290,6 +290,9 @@ static const struct hid_device_id hid_battery_quirks[] = { { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2011_ANSI), HID_BATTERY_QUIRK_PERCENT | HID_BATTERY_QUIRK_FEATURE }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, + USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI), + HID_BATTERY_QUIRK_PERCENT | HID_BATTERY_QUIRK_FEATURE }, {} }; diff --git a/drivers/hid/hid-microsoft.c b/drivers/hid/hid-microsoft.c index e5c699b6c6f..38999898d04 100644 --- a/drivers/hid/hid-microsoft.c +++ b/drivers/hid/hid-microsoft.c @@ -29,22 +29,30 @@ #define MS_RDESC 0x08 #define MS_NOGET 0x10 #define MS_DUPLICATE_USAGES 0x20 +#define MS_RDESC_3K 0x40 -/* - * Microsoft Wireless Desktop Receiver (Model 1028) has - * 'Usage Min/Max' where it ought to have 'Physical Min/Max' - */ static __u8 *ms_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) { unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); + /* + * Microsoft Wireless Desktop Receiver (Model 1028) has + * 'Usage Min/Max' where it ought to have 'Physical Min/Max' + */ if ((quirks & MS_RDESC) && *rsize == 571 && rdesc[557] == 0x19 && rdesc[559] == 0x29) { hid_info(hdev, "fixing up Microsoft Wireless Receiver Model 1028 report descriptor\n"); rdesc[557] = 0x35; rdesc[559] = 0x45; } + /* the same as above (s/usage/physical/) */ + if ((quirks & MS_RDESC_3K) && *rsize == 106 && + !memcmp((char []){ 0x19, 0x00, 0x29, 0xff }, + &rdesc[94], 4)) { + rdesc[94] = 0x35; + rdesc[96] = 0x45; + } return rdesc; } @@ -193,7 +201,7 @@ static const struct hid_device_id ms_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_USB), .driver_data = MS_PRESENTER }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K), - .driver_data = MS_ERGONOMY }, + .driver_data = MS_ERGONOMY | MS_RDESC_3K }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0), .driver_data = MS_NOGET }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500), diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 1432594c4e2..7f562ee0e3b 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -760,6 +760,10 @@ static const struct hid_device_id mt_devices[] = { HID_USB_DEVICE(USB_VENDOR_ID_ATMEL, USB_DEVICE_ID_ATMEL_MXT_DIGITIZER) }, + /* Baanto multitouch devices */ + { .driver_data = MT_CLS_DEFAULT, + HID_USB_DEVICE(USB_VENDOR_ID_BAANTO, + USB_DEVICE_ID_BAANTO_MT_190W2) }, /* Cando panels */ { .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER, HID_USB_DEVICE(USB_VENDOR_ID_CANDO, @@ -913,6 +917,11 @@ static const struct hid_device_id mt_devices[] = { HID_USB_DEVICE(USB_VENDOR_ID_PANASONIC, USB_DEVICE_ID_PANABOARD_UBT880) }, + /* Novatek Panel */ + { .driver_data = MT_CLS_DEFAULT, + HID_USB_DEVICE(USB_VENDOR_ID_NOVATEK, + USB_DEVICE_ID_NOVATEK_PCT) }, + /* PenMount panels */ { .driver_data = MT_CLS_CONFIDENCE, HID_USB_DEVICE(USB_VENDOR_ID_PENMOUNT, diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 782c63955f2..9fea98f7c37 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -70,12 +70,15 @@ static const struct hid_blacklist { { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_AXIS_295, HID_QUIRK_NOGET }, { USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET }, { USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET }, { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN2, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_PRODIGE, USB_DEVICE_ID_PRODIGE_CORDLESS, HID_QUIRK_NOGET }, { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NOGET }, { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_SENNHEISER, USB_DEVICE_ID_SENNHEISER_BTD500USB, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_SIGMATEL, USB_DEVICE_ID_SIGMATEL_STMP3780, HID_QUIRK_NOGET }, { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET }, { USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_1, HID_QUIRK_NOGET }, { USB_VENDOR_ID_SYMBOL, USB_DEVICE_ID_SYMBOL_SCANNER_2, HID_QUIRK_NOGET }, diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c index 406537420ff..f4c3d28cd1f 100644 --- a/drivers/hv/channel.c +++ b/drivers/hv/channel.c @@ -146,14 +146,14 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, if (ret != 0) { err = ret; - goto errorout; + goto error0; } ret = hv_ringbuffer_init( &newchannel->inbound, in, recv_ringbuffer_size); if (ret != 0) { err = ret; - goto errorout; + goto error0; } @@ -168,7 +168,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, if (ret != 0) { err = ret; - goto errorout; + goto error0; } /* Create and init the channel open message */ @@ -177,7 +177,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, GFP_KERNEL); if (!open_info) { err = -ENOMEM; - goto errorout; + goto error0; } init_completion(&open_info->waitevent); @@ -193,7 +193,7 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, if (userdatalen > MAX_USER_DEFINED_BYTES) { err = -EINVAL; - goto errorout; + goto error0; } if (userdatalen) @@ -208,19 +208,18 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, sizeof(struct vmbus_channel_open_channel)); if (ret != 0) - goto cleanup; + goto error1; t = wait_for_completion_timeout(&open_info->waitevent, 5*HZ); if (t == 0) { err = -ETIMEDOUT; - goto errorout; + goto error1; } if (open_info->response.open_result.status) err = open_info->response.open_result.status; -cleanup: spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); list_del(&open_info->msglistentry); spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); @@ -228,9 +227,12 @@ int vmbus_open(struct vmbus_channel *newchannel, u32 send_ringbuffer_size, kfree(open_info); return err; -errorout: - hv_ringbuffer_cleanup(&newchannel->outbound); - hv_ringbuffer_cleanup(&newchannel->inbound); +error1: + spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); + list_del(&open_info->msglistentry); + spin_unlock_irqrestore(&vmbus_connection.channelmsg_lock, flags); + +error0: free_pages((unsigned long)out, get_order(send_ringbuffer_size + recv_ringbuffer_size)); kfree(open_info); diff --git a/drivers/hwmon/ad7314.c b/drivers/hwmon/ad7314.c index f85ce70d967..9815f9cc8f7 100644 --- a/drivers/hwmon/ad7314.c +++ b/drivers/hwmon/ad7314.c @@ -94,10 +94,18 @@ static ssize_t ad7314_show_temperature(struct device *dev, } } +static ssize_t ad7314_show_name(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + return sprintf(buf, "%s\n", to_spi_device(dev)->modalias); +} + +static DEVICE_ATTR(name, S_IRUGO, ad7314_show_name, NULL); static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, ad7314_show_temperature, NULL, 0); static struct attribute *ad7314_attributes[] = { + &dev_attr_name.attr, &sensor_dev_attr_temp1_input.dev_attr.attr, NULL, }; diff --git a/drivers/hwmon/ads7871.c b/drivers/hwmon/ads7871.c index e65c6e45d36..7bf4ce3d405 100644 --- a/drivers/hwmon/ads7871.c +++ b/drivers/hwmon/ads7871.c @@ -139,6 +139,12 @@ static ssize_t show_voltage(struct device *dev, } } +static ssize_t ads7871_show_name(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + return sprintf(buf, "%s\n", to_spi_device(dev)->modalias); +} + static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, show_voltage, NULL, 0); static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_voltage, NULL, 1); static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_voltage, NULL, 2); @@ -148,6 +154,8 @@ static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, show_voltage, NULL, 5); static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, show_voltage, NULL, 6); static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, show_voltage, NULL, 7); +static DEVICE_ATTR(name, S_IRUGO, ads7871_show_name, NULL); + static struct attribute *ads7871_attributes[] = { &sensor_dev_attr_in0_input.dev_attr.attr, &sensor_dev_attr_in1_input.dev_attr.attr, @@ -157,6 +165,7 @@ static struct attribute *ads7871_attributes[] = { &sensor_dev_attr_in5_input.dev_attr.attr, &sensor_dev_attr_in6_input.dev_attr.attr, &sensor_dev_attr_in7_input.dev_attr.attr, + &dev_attr_name.attr, NULL }; diff --git a/drivers/hwmon/asus_atk0110.c b/drivers/hwmon/asus_atk0110.c index 351d1f4593e..4ee57894872 100644 --- a/drivers/hwmon/asus_atk0110.c +++ b/drivers/hwmon/asus_atk0110.c @@ -34,6 +34,12 @@ static const struct dmi_system_id __initconst atk_force_new_if[] = { .matches = { DMI_MATCH(DMI_BOARD_NAME, "SABERTOOTH X58") } + }, { + /* Old interface reads the same sensor for fan0 and fan1 */ + .ident = "Asus M5A78L", + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "M5A78L") + } }, { } }; diff --git a/drivers/hwmon/fam15h_power.c b/drivers/hwmon/fam15h_power.c index e8e18cab1fb..770e95951a5 100644 --- a/drivers/hwmon/fam15h_power.c +++ b/drivers/hwmon/fam15h_power.c @@ -31,6 +31,9 @@ MODULE_DESCRIPTION("AMD Family 15h CPU processor power monitor"); MODULE_AUTHOR("Andreas Herrmann "); MODULE_LICENSE("GPL"); +/* Family 16h Northbridge's function 4 PCI ID */ +#define PCI_DEVICE_ID_AMD_16H_NB_F4 0x1534 + /* D18F3 */ #define REG_NORTHBRIDGE_CAP 0xe8 @@ -128,12 +131,12 @@ static bool __devinit fam15h_power_is_internal_node0(struct pci_dev *f4) * counter saturations resulting in bogus power readings. * We correct this value ourselves to cope with older BIOSes. */ -static DEFINE_PCI_DEVICE_TABLE(affected_device) = { +static const struct pci_device_id affected_device[] = { { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F4) }, { 0 } }; -static void __devinit tweak_runavg_range(struct pci_dev *pdev) +static void tweak_runavg_range(struct pci_dev *pdev) { u32 val; @@ -157,6 +160,16 @@ static void __devinit tweak_runavg_range(struct pci_dev *pdev) REG_TDP_RUNNING_AVERAGE, val); } +#ifdef CONFIG_PM +static int fam15h_power_resume(struct pci_dev *pdev) +{ + tweak_runavg_range(pdev); + return 0; +} +#else +#define fam15h_power_resume NULL +#endif + static void __devinit fam15h_power_init_data(struct pci_dev *f4, struct fam15h_power_data *data) { @@ -246,6 +259,7 @@ static void __devexit fam15h_power_remove(struct pci_dev *pdev) static DEFINE_PCI_DEVICE_TABLE(fam15h_power_id_table) = { { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F4) }, + { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_16H_NB_F4) }, {} }; MODULE_DEVICE_TABLE(pci, fam15h_power_id_table); @@ -255,6 +269,7 @@ static struct pci_driver fam15h_power_driver = { .id_table = fam15h_power_id_table, .probe = fam15h_power_probe, .remove = __devexit_p(fam15h_power_remove), + .resume = fam15h_power_resume, }; static int __init fam15h_power_init(void) diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 0b204e4cf51..f524882aaeb 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -2157,7 +2157,7 @@ static void __devinit it87_init_device(struct platform_device *pdev) /* Start monitoring */ it87_write_value(data, IT87_REG_CONFIG, - (it87_read_value(data, IT87_REG_CONFIG) & 0x36) + (it87_read_value(data, IT87_REG_CONFIG) & 0x3e) | (update_vbat ? 0x41 : 0x01)); } diff --git a/drivers/hwmon/lm73.c b/drivers/hwmon/lm73.c index 8fa2632cbba..7272176a9ec 100644 --- a/drivers/hwmon/lm73.c +++ b/drivers/hwmon/lm73.c @@ -49,6 +49,7 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *da, struct i2c_client *client = to_i2c_client(dev); long temp; short value; + s32 err; int status = kstrtol(buf, 10, &temp); if (status < 0) @@ -57,8 +58,8 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *da, /* Write value */ value = (short) SENSORS_LIMIT(temp/250, (LM73_TEMP_MIN*4), (LM73_TEMP_MAX*4)) << 5; - i2c_smbus_write_word_swapped(client, attr->index, value); - return count; + err = i2c_smbus_write_word_swapped(client, attr->index, value); + return (err < 0) ? err : count; } static ssize_t show_temp(struct device *dev, struct device_attribute *da, @@ -66,11 +67,16 @@ static ssize_t show_temp(struct device *dev, struct device_attribute *da, { struct sensor_device_attribute *attr = to_sensor_dev_attr(da); struct i2c_client *client = to_i2c_client(dev); + int temp; + + s32 err = i2c_smbus_read_word_swapped(client, attr->index); + if (err < 0) + return err; + /* use integer division instead of equivalent right shift to guarantee arithmetic shift and preserve the sign */ - int temp = ((s16) (i2c_smbus_read_word_swapped(client, - attr->index))*250) / 32; - return sprintf(buf, "%d\n", temp); + temp = (((s16) err) * 250) / 32; + return scnprintf(buf, PAGE_SIZE, "%d\n", temp); } diff --git a/drivers/hwmon/twl4030-madc-hwmon.c b/drivers/hwmon/twl4030-madc-hwmon.c index 0018c7dd009..1a174f0a3cd 100644 --- a/drivers/hwmon/twl4030-madc-hwmon.c +++ b/drivers/hwmon/twl4030-madc-hwmon.c @@ -44,12 +44,13 @@ static ssize_t madc_read(struct device *dev, struct device_attribute *devattr, char *buf) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct twl4030_madc_request req; + struct twl4030_madc_request req = { + .channels = 1 << attr->index, + .method = TWL4030_MADC_SW2, + .type = TWL4030_MADC_WAIT, + }; long val; - req.channels = (1 << attr->index); - req.method = TWL4030_MADC_SW2; - req.func_cb = NULL; val = twl4030_madc_conversion(&req); if (val < 0) return val; diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c index 54922ed1297..88effda1919 100644 --- a/drivers/hwmon/w83627ehf.c +++ b/drivers/hwmon/w83627ehf.c @@ -2082,6 +2082,7 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev) mutex_init(&data->lock); mutex_init(&data->update_lock); data->name = w83627ehf_device_names[sio_data->kind]; + data->bank = 0xff; /* Force initial bank selection */ platform_set_drvdata(pdev, data); /* 627EHG and 627EHF have 10 voltage inputs; 627DHG and 667HG have 9 */ diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 574ec8a64b5..ac2e1e1d3e0 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -104,6 +104,7 @@ config I2C_I801 DH89xxCC (PCH) Panther Point (PCH) Lynx Point (PCH) + Lynx Point-LP (PCH) This driver can also be built as a module. If so, the module will be called i2c-i801. @@ -350,9 +351,13 @@ config I2C_DAVINCI devices such as DaVinci NIC. For details please see http://www.ti.com/davinci +config I2C_DESIGNWARE_CORE + tristate + config I2C_DESIGNWARE_PLATFORM tristate "Synopsys DesignWare Platfrom" depends on HAVE_CLK + select I2C_DESIGNWARE_CORE help If you say yes to this option, support will be included for the Synopsys DesignWare I2C adapter. Only master mode is supported. @@ -363,6 +368,7 @@ config I2C_DESIGNWARE_PLATFORM config I2C_DESIGNWARE_PCI tristate "Synopsys DesignWare PCI" depends on PCI + select I2C_DESIGNWARE_CORE help If you say yes to this option, support will be included for the Synopsys DesignWare I2C adapter. Only master mode is supported. diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index 4f494fcd74b..453819bfc7f 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -33,10 +33,11 @@ obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o obj-$(CONFIG_I2C_CPM) += i2c-cpm.o obj-$(CONFIG_I2C_DAVINCI) += i2c-davinci.o +obj-$(CONFIG_I2C_DESIGNWARE_CORE) += i2c-designware-core.o obj-$(CONFIG_I2C_DESIGNWARE_PLATFORM) += i2c-designware-platform.o -i2c-designware-platform-objs := i2c-designware-platdrv.o i2c-designware-core.o +i2c-designware-platform-objs := i2c-designware-platdrv.o obj-$(CONFIG_I2C_DESIGNWARE_PCI) += i2c-designware-pci.o -i2c-designware-pci-objs := i2c-designware-pcidrv.o i2c-designware-core.o +i2c-designware-pci-objs := i2c-designware-pcidrv.o obj-$(CONFIG_I2C_EG20T) += i2c-eg20t.o obj-$(CONFIG_I2C_GPIO) += i2c-gpio.o obj-$(CONFIG_I2C_HIGHLANDER) += i2c-highlander.o diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c index df879924100..619334994df 100644 --- a/drivers/i2c/busses/i2c-designware-core.c +++ b/drivers/i2c/busses/i2c-designware-core.c @@ -25,6 +25,7 @@ * ---------------------------------------------------------------------------- * */ +#include #include #include #include @@ -305,6 +306,7 @@ int i2c_dw_init(struct dw_i2c_dev *dev) dw_writel(dev, dev->master_cfg , DW_IC_CON); return 0; } +EXPORT_SYMBOL_GPL(i2c_dw_init); /* * Waiting for bus not busy @@ -557,12 +559,14 @@ i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) return ret; } +EXPORT_SYMBOL_GPL(i2c_dw_xfer); u32 i2c_dw_func(struct i2c_adapter *adap) { struct dw_i2c_dev *dev = i2c_get_adapdata(adap); return dev->functionality; } +EXPORT_SYMBOL_GPL(i2c_dw_func); static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev) { @@ -667,17 +671,20 @@ irqreturn_t i2c_dw_isr(int this_irq, void *dev_id) return IRQ_HANDLED; } +EXPORT_SYMBOL_GPL(i2c_dw_isr); void i2c_dw_enable(struct dw_i2c_dev *dev) { /* Enable the adapter */ dw_writel(dev, 1, DW_IC_ENABLE); } +EXPORT_SYMBOL_GPL(i2c_dw_enable); u32 i2c_dw_is_enabled(struct dw_i2c_dev *dev) { return dw_readl(dev, DW_IC_ENABLE); } +EXPORT_SYMBOL_GPL(i2c_dw_is_enabled); void i2c_dw_disable(struct dw_i2c_dev *dev) { @@ -688,18 +695,22 @@ void i2c_dw_disable(struct dw_i2c_dev *dev) dw_writel(dev, 0, DW_IC_INTR_MASK); dw_readl(dev, DW_IC_CLR_INTR); } +EXPORT_SYMBOL_GPL(i2c_dw_disable); void i2c_dw_clear_int(struct dw_i2c_dev *dev) { dw_readl(dev, DW_IC_CLR_INTR); } +EXPORT_SYMBOL_GPL(i2c_dw_clear_int); void i2c_dw_disable_int(struct dw_i2c_dev *dev) { dw_writel(dev, 0, DW_IC_INTR_MASK); } +EXPORT_SYMBOL_GPL(i2c_dw_disable_int); u32 i2c_dw_read_comp_param(struct dw_i2c_dev *dev) { return dw_readl(dev, DW_IC_COMP_PARAM_1); } +EXPORT_SYMBOL_GPL(i2c_dw_read_comp_param); diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index ae2945a5e00..d88ec812160 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -52,6 +52,7 @@ DH89xxCC (PCH) 0x2330 32 hard yes yes yes Panther Point (PCH) 0x1e22 32 hard yes yes yes Lynx Point (PCH) 0x8c22 32 hard yes yes yes + Lynx Point-LP (PCH) 0x9c22 32 hard yes yes yes Features supported by this driver: Software PEC no @@ -147,6 +148,7 @@ #define PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS 0x2330 #define PCI_DEVICE_ID_INTEL_5_3400_SERIES_SMBUS 0x3b30 #define PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS 0x8c22 +#define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_SMBUS 0x9c22 struct i801_priv { struct i2c_adapter adapter; @@ -636,6 +638,7 @@ static DEFINE_PCI_DEVICE_TABLE(i801_ids) = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PANTHERPOINT_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_SMBUS) }, { 0, } }; diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index e3e470fecaa..67432e200c6 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -3451,7 +3451,8 @@ static int cma_get_id_stats(struct sk_buff *skb, struct netlink_callback *cb) } static const struct ibnl_client_cbs cma_cb_table[] = { - [RDMA_NL_RDMA_CM_ID_STATS] = { .dump = cma_get_id_stats }, + [RDMA_NL_RDMA_CM_ID_STATS] = { .dump = cma_get_id_stats, + .module = THIS_MODULE }, }; static int __init cma_init(void) diff --git a/drivers/infiniband/core/netlink.c b/drivers/infiniband/core/netlink.c index 396e2937030..8c3b08ac496 100644 --- a/drivers/infiniband/core/netlink.c +++ b/drivers/infiniband/core/netlink.c @@ -151,6 +151,7 @@ static int ibnl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) { struct netlink_dump_control c = { .dump = client->cb_table[op].dump, + .module = client->cb_table[op].module, }; return netlink_dump_start(nls, skb, nlh, &c); } diff --git a/drivers/infiniband/hw/nes/nes.h b/drivers/infiniband/hw/nes/nes.h index c438e4691b3..3f41d9f5f70 100644 --- a/drivers/infiniband/hw/nes/nes.h +++ b/drivers/infiniband/hw/nes/nes.h @@ -524,6 +524,7 @@ void nes_iwarp_ce_handler(struct nes_device *, struct nes_hw_cq *); int nes_destroy_cqp(struct nes_device *); int nes_nic_cm_xmit(struct sk_buff *, struct net_device *); void nes_recheck_link_status(struct work_struct *work); +void nes_terminate_timeout(unsigned long context); /* nes_nic.c */ struct net_device *nes_netdev_init(struct nes_device *, void __iomem *); diff --git a/drivers/infiniband/hw/nes/nes_hw.c b/drivers/infiniband/hw/nes/nes_hw.c index d42c9f435b1..96801c3a1fe 100644 --- a/drivers/infiniband/hw/nes/nes_hw.c +++ b/drivers/infiniband/hw/nes/nes_hw.c @@ -75,7 +75,6 @@ static void nes_process_iwarp_aeqe(struct nes_device *nesdev, static void process_critical_error(struct nes_device *nesdev); static void nes_process_mac_intr(struct nes_device *nesdev, u32 mac_number); static unsigned int nes_reset_adapter_ne020(struct nes_device *nesdev, u8 *OneG_Mode); -static void nes_terminate_timeout(unsigned long context); static void nes_terminate_start_timer(struct nes_qp *nesqp); #ifdef CONFIG_INFINIBAND_NES_DEBUG @@ -3522,7 +3521,7 @@ static void nes_terminate_received(struct nes_device *nesdev, } /* Timeout routine in case terminate fails to complete */ -static void nes_terminate_timeout(unsigned long context) +void nes_terminate_timeout(unsigned long context) { struct nes_qp *nesqp = (struct nes_qp *)(unsigned long)context; @@ -3532,11 +3531,7 @@ static void nes_terminate_timeout(unsigned long context) /* Set a timer in case hw cannot complete the terminate sequence */ static void nes_terminate_start_timer(struct nes_qp *nesqp) { - init_timer(&nesqp->terminate_timer); - nesqp->terminate_timer.function = nes_terminate_timeout; - nesqp->terminate_timer.expires = jiffies + HZ; - nesqp->terminate_timer.data = (unsigned long)nesqp; - add_timer(&nesqp->terminate_timer); + mod_timer(&nesqp->terminate_timer, (jiffies + HZ)); } /** diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c index 8b8812de4b5..da84ea383f9 100644 --- a/drivers/infiniband/hw/nes/nes_verbs.c +++ b/drivers/infiniband/hw/nes/nes_verbs.c @@ -1404,6 +1404,9 @@ static struct ib_qp *nes_create_qp(struct ib_pd *ibpd, } nesqp->sig_all = (init_attr->sq_sig_type == IB_SIGNAL_ALL_WR); + init_timer(&nesqp->terminate_timer); + nesqp->terminate_timer.function = nes_terminate_timeout; + nesqp->terminate_timer.data = (unsigned long)nesqp; /* update the QP table */ nesdev->nesadapter->qp_table[nesqp->hwqp.qp_id-NES_FIRST_QPN] = nesqp; @@ -1413,7 +1416,6 @@ static struct ib_qp *nes_create_qp(struct ib_pd *ibpd, return &nesqp->ibqp; } - /** * nes_clean_cq */ @@ -2559,6 +2561,11 @@ static struct ib_mr *nes_reg_user_mr(struct ib_pd *pd, u64 start, u64 length, return ibmr; case IWNES_MEMREG_TYPE_QP: case IWNES_MEMREG_TYPE_CQ: + if (!region->length) { + nes_debug(NES_DBG_MR, "Unable to register zero length region for CQ\n"); + ib_umem_release(region); + return ERR_PTR(-EINVAL); + } nespbl = kzalloc(sizeof(*nespbl), GFP_KERNEL); if (!nespbl) { nes_debug(NES_DBG_MR, "Unable to allocate PBL\n"); diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 3974c290b66..69b23c22d4e 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -148,7 +148,7 @@ static int ipoib_stop(struct net_device *dev) netif_stop_queue(dev); - ipoib_ib_dev_down(dev, 0); + ipoib_ib_dev_down(dev, 1); ipoib_ib_dev_stop(dev, 0); if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) { diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index 20ebc6fd1bb..213965d5bc8 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c @@ -190,7 +190,9 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast, mcast->mcmember = *mcmember; - /* Set the cached Q_Key before we attach if it's the broadcast group */ + /* Set the multicast MTU and cached Q_Key before we attach if it's + * the broadcast group. + */ if (!memcmp(mcast->mcmember.mgid.raw, priv->dev->broadcast + 4, sizeof (union ib_gid))) { spin_lock_irq(&priv->lock); @@ -198,10 +200,17 @@ static int ipoib_mcast_join_finish(struct ipoib_mcast *mcast, spin_unlock_irq(&priv->lock); return -EAGAIN; } + priv->mcast_mtu = IPOIB_UD_MTU(ib_mtu_enum_to_int(priv->broadcast->mcmember.mtu)); priv->qkey = be32_to_cpu(priv->broadcast->mcmember.qkey); spin_unlock_irq(&priv->lock); priv->tx_wr.wr.ud.remote_qkey = priv->qkey; set_qkey = 1; + + if (!ipoib_cm_admin_enabled(dev)) { + rtnl_lock(); + dev_set_mtu(dev, min(priv->mcast_mtu, priv->admin_mtu)); + rtnl_unlock(); + } } if (!test_bit(IPOIB_MCAST_FLAG_SENDONLY, &mcast->flags)) { @@ -589,14 +598,6 @@ void ipoib_mcast_join_task(struct work_struct *work) return; } - priv->mcast_mtu = IPOIB_UD_MTU(ib_mtu_enum_to_int(priv->broadcast->mcmember.mtu)); - - if (!ipoib_cm_admin_enabled(dev)) { - rtnl_lock(); - dev_set_mtu(dev, min(priv->mcast_mtu, priv->admin_mtu)); - rtnl_unlock(); - } - ipoib_dbg_mcast(priv, "successfully joined all multicast groups\n"); clear_bit(IPOIB_MCAST_RUN, &priv->flags); diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index bcbf22ee0aa..922d845f76b 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -586,24 +586,62 @@ static void srp_unmap_data(struct scsi_cmnd *scmnd, scmnd->sc_data_direction); } -static void srp_remove_req(struct srp_target_port *target, - struct srp_request *req, s32 req_lim_delta) +/** + * srp_claim_req - Take ownership of the scmnd associated with a request. + * @target: SRP target port. + * @req: SRP request. + * @scmnd: If NULL, take ownership of @req->scmnd. If not NULL, only take + * ownership of @req->scmnd if it equals @scmnd. + * + * Return value: + * Either NULL or a pointer to the SCSI command the caller became owner of. + */ +static struct scsi_cmnd *srp_claim_req(struct srp_target_port *target, + struct srp_request *req, + struct scsi_cmnd *scmnd) +{ + unsigned long flags; + + spin_lock_irqsave(&target->lock, flags); + if (!scmnd) { + scmnd = req->scmnd; + req->scmnd = NULL; + } else if (req->scmnd == scmnd) { + req->scmnd = NULL; + } else { + scmnd = NULL; + } + spin_unlock_irqrestore(&target->lock, flags); + + return scmnd; +} + +/** + * srp_free_req() - Unmap data and add request to the free request list. + */ +static void srp_free_req(struct srp_target_port *target, + struct srp_request *req, struct scsi_cmnd *scmnd, + s32 req_lim_delta) { unsigned long flags; - srp_unmap_data(req->scmnd, target, req); + srp_unmap_data(scmnd, target, req); + spin_lock_irqsave(&target->lock, flags); target->req_lim += req_lim_delta; - req->scmnd = NULL; list_add_tail(&req->list, &target->free_reqs); spin_unlock_irqrestore(&target->lock, flags); } static void srp_reset_req(struct srp_target_port *target, struct srp_request *req) { - req->scmnd->result = DID_RESET << 16; - req->scmnd->scsi_done(req->scmnd); - srp_remove_req(target, req, 0); + struct scsi_cmnd *scmnd = srp_claim_req(target, req, NULL); + + if (scmnd) { + srp_free_req(target, req, scmnd, 0); + scmnd->result = DID_RESET << 16; + scmnd->scsi_done(scmnd); + } } static int srp_reconnect_target(struct srp_target_port *target) @@ -1073,11 +1111,18 @@ static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp) complete(&target->tsk_mgmt_done); } else { req = &target->req_ring[rsp->tag]; - scmnd = req->scmnd; - if (!scmnd) + scmnd = srp_claim_req(target, req, NULL); + if (!scmnd) { shost_printk(KERN_ERR, target->scsi_host, "Null scmnd for RSP w/tag %016llx\n", (unsigned long long) rsp->tag); + + spin_lock_irqsave(&target->lock, flags); + target->req_lim += be32_to_cpu(rsp->req_lim_delta); + spin_unlock_irqrestore(&target->lock, flags); + + return; + } scmnd->result = rsp->status; if (rsp->flags & SRP_RSP_FLAG_SNSVALID) { @@ -1092,7 +1137,9 @@ static void srp_process_rsp(struct srp_target_port *target, struct srp_rsp *rsp) else if (rsp->flags & (SRP_RSP_FLAG_DIOVER | SRP_RSP_FLAG_DIUNDER)) scsi_set_resid(scmnd, be32_to_cpu(rsp->data_in_res_cnt)); - srp_remove_req(target, req, be32_to_cpu(rsp->req_lim_delta)); + srp_free_req(target, req, scmnd, + be32_to_cpu(rsp->req_lim_delta)); + scmnd->host_scribble = NULL; scmnd->scsi_done(scmnd); } @@ -1631,25 +1678,18 @@ static int srp_abort(struct scsi_cmnd *scmnd) { struct srp_target_port *target = host_to_target(scmnd->device->host); struct srp_request *req = (struct srp_request *) scmnd->host_scribble; - int ret = SUCCESS; shost_printk(KERN_ERR, target->scsi_host, "SRP abort called\n"); - if (!req || target->qp_in_error) + if (!req || target->qp_in_error || !srp_claim_req(target, req, scmnd)) return FAILED; - if (srp_send_tsk_mgmt(target, req->index, scmnd->device->lun, - SRP_TSK_ABORT_TASK)) - return FAILED; - - if (req->scmnd) { - if (!target->tsk_mgmt_status) { - srp_remove_req(target, req, 0); - scmnd->result = DID_ABORT << 16; - } else - ret = FAILED; - } + srp_send_tsk_mgmt(target, req->index, scmnd->device->lun, + SRP_TSK_ABORT_TASK); + srp_free_req(target, req, scmnd, 0); + scmnd->result = DID_ABORT << 16; + scmnd->scsi_done(scmnd); - return ret; + return SUCCESS; } static int srp_reset_device(struct scsi_cmnd *scmnd) diff --git a/drivers/input/joystick/walkera0701.c b/drivers/input/joystick/walkera0701.c index 4dfa1eed4b7..f8f892b076e 100644 --- a/drivers/input/joystick/walkera0701.c +++ b/drivers/input/joystick/walkera0701.c @@ -196,6 +196,7 @@ static void walkera0701_close(struct input_dev *dev) struct walkera_dev *w = input_get_drvdata(dev); parport_disable_irq(w->parport); + hrtimer_cancel(&w->timer); } static int walkera0701_connect(struct walkera_dev *w, int parport) @@ -224,6 +225,9 @@ static int walkera0701_connect(struct walkera_dev *w, int parport) if (parport_claim(w->pardevice)) goto init_err1; + hrtimer_init(&w->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + w->timer.function = timer_handler; + w->input_dev = input_allocate_device(); if (!w->input_dev) goto init_err2; @@ -254,8 +258,6 @@ static int walkera0701_connect(struct walkera_dev *w, int parport) if (err) goto init_err3; - hrtimer_init(&w->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - w->timer.function = timer_handler; return 0; init_err3: @@ -271,7 +273,6 @@ static int walkera0701_connect(struct walkera_dev *w, int parport) static void walkera0701_disconnect(struct walkera_dev *w) { - hrtimer_cancel(&w->timer); input_unregister_device(w->input_dev); parport_release(w->pardevice); parport_unregister_device(w->pardevice); diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index fd7a0d5bc94..42f7b257feb 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c @@ -142,6 +142,7 @@ static const struct xpad_device { { 0x0c12, 0x880a, "Pelican Eclipse PL-2023", 0, XTYPE_XBOX }, { 0x0c12, 0x8810, "Zeroplus Xbox Controller", 0, XTYPE_XBOX }, { 0x0c12, 0x9902, "HAMA VibraX - *FAULTY HARDWARE*", 0, XTYPE_XBOX }, + { 0x0d2f, 0x0002, "Andamiro Pump It Up pad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX }, { 0x0e4c, 0x1097, "Radica Gamester Controller", 0, XTYPE_XBOX }, { 0x0e4c, 0x2390, "Radica Games Jtech Controller", 0, XTYPE_XBOX }, { 0x0e6f, 0x0003, "Logic3 Freebird wireless Controller", 0, XTYPE_XBOX }, @@ -164,6 +165,7 @@ static const struct xpad_device { { 0x1bad, 0x0003, "Harmonix Rock Band Drumkit", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, { 0x0f0d, 0x0016, "Hori Real Arcade Pro.EX", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, { 0x0f0d, 0x000d, "Hori Fighting Stick EX2", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 }, + { 0x1689, 0xfd00, "Razer Onza Tournament Edition", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 }, { 0xffff, 0xffff, "Chinese-made Xbox Controller", 0, XTYPE_XBOX }, { 0x0000, 0x0000, "Generic X-Box pad", 0, XTYPE_UNKNOWN } }; @@ -238,12 +240,14 @@ static struct usb_device_id xpad_table [] = { XPAD_XBOX360_VENDOR(0x045e), /* Microsoft X-Box 360 controllers */ XPAD_XBOX360_VENDOR(0x046d), /* Logitech X-Box 360 style controllers */ XPAD_XBOX360_VENDOR(0x0738), /* Mad Catz X-Box 360 controllers */ + { USB_DEVICE(0x0738, 0x4540) }, /* Mad Catz Beat Pad */ XPAD_XBOX360_VENDOR(0x0e6f), /* 0x0e6f X-Box 360 controllers */ XPAD_XBOX360_VENDOR(0x12ab), /* X-Box 360 dance pads */ XPAD_XBOX360_VENDOR(0x1430), /* RedOctane X-Box 360 controllers */ XPAD_XBOX360_VENDOR(0x146b), /* BigBen Interactive Controllers */ XPAD_XBOX360_VENDOR(0x1bad), /* Harminix Rock Band Guitar and Drums */ - XPAD_XBOX360_VENDOR(0x0f0d), /* Hori Controllers */ + XPAD_XBOX360_VENDOR(0x0f0d), /* Hori Controllers */ + XPAD_XBOX360_VENDOR(0x1689), /* Razer Onza */ { } }; diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c index f9e2758b9f4..e410b98c227 100644 --- a/drivers/input/mouse/bcm5974.c +++ b/drivers/input/mouse/bcm5974.c @@ -79,6 +79,10 @@ #define USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI 0x0252 #define USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO 0x0253 #define USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS 0x0254 +/* MacbookPro10,1 (unibody, June 2012) */ +#define USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI 0x0262 +#define USB_DEVICE_ID_APPLE_WELLSPRING7_ISO 0x0263 +#define USB_DEVICE_ID_APPLE_WELLSPRING7_JIS 0x0264 #define BCM5974_DEVICE(prod) { \ .match_flags = (USB_DEVICE_ID_MATCH_DEVICE | \ @@ -128,6 +132,10 @@ static const struct usb_device_id bcm5974_table[] = { BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI), BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO), BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS), + /* MacbookPro10,1 */ + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI), + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7_ISO), + BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7_JIS), /* Terminating entry */ {} }; @@ -354,6 +362,18 @@ static const struct bcm5974_config bcm5974_config_table[] = { { DIM_X, DIM_X / SN_COORD, -4620, 5140 }, { DIM_Y, DIM_Y / SN_COORD, -150, 6600 } }, + { + USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI, + USB_DEVICE_ID_APPLE_WELLSPRING7_ISO, + USB_DEVICE_ID_APPLE_WELLSPRING7_JIS, + HAS_INTEGRATED_BUTTON, + 0x84, sizeof(struct bt_data), + 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS, + { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 }, + { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 }, + { DIM_X, DIM_X / SN_COORD, -4750, 5280 }, + { DIM_Y, DIM_Y / SN_COORD, -150, 6730 } + }, {} }; diff --git a/drivers/input/mouse/sentelic.c b/drivers/input/mouse/sentelic.c index 661a0ca3b3d..1257ce8147f 100644 --- a/drivers/input/mouse/sentelic.c +++ b/drivers/input/mouse/sentelic.c @@ -759,7 +759,7 @@ static psmouse_ret_t fsp_process_byte(struct psmouse *psmouse) fsp_set_slot(dev, 0, fgrs > 0, abs_x, abs_y); fsp_set_slot(dev, 1, false, 0, 0); } - if (fgrs > 0) { + if (fgrs == 1 || (fgrs == 2 && !(packet[0] & FSP_PB0_MFMC_FGR2))) { input_report_abs(dev, ABS_X, abs_x); input_report_abs(dev, ABS_Y, abs_y); } diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index 5ec774d6c82..5f306f79da0 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -176,6 +176,20 @@ static const struct dmi_system_id __initconst i8042_dmi_noloop_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Spring Peak"), }, }, + { + /* Gigabyte T1005 - defines wrong chassis type ("Other") */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"), + DMI_MATCH(DMI_PRODUCT_NAME, "T1005"), + }, + }, + { + /* Gigabyte T1005M/P - defines wrong chassis type ("Other") */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"), + DMI_MATCH(DMI_PRODUCT_NAME, "T1005M/P"), + }, + }, { .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), @@ -319,6 +333,12 @@ static const struct dmi_system_id __initconst i8042_dmi_nomux_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "EQUIUM A110"), }, }, + { + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "SATELLITE C850D"), + }, + }, { .matches = { DMI_MATCH(DMI_SYS_VENDOR, "ALIENWARE"), @@ -901,6 +921,7 @@ static int __init i8042_platform_init(void) int retval; #ifdef CONFIG_X86 + u8 a20_on = 0xdf; /* Just return if pre-detection shows no i8042 controller exist */ if (!x86_platform.i8042_detect()) return -ENODEV; @@ -940,6 +961,14 @@ static int __init i8042_platform_init(void) if (dmi_check_system(i8042_dmi_dritek_table)) i8042_dritek = true; + + /* + * A20 was already enabled during early kernel init. But some buggy + * BIOSes (in MSI Laptops) require A20 to be enabled using 8042 to + * resume from S3. So we do it here and hope that nothing breaks. + */ + i8042_command(&a20_on, 0x10d1); + i8042_command(NULL, 0x00ff); /* Null command for SMM firmware */ #endif /* CONFIG_X86 */ return retval; diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index cecd35c8f0b..c77032c943e 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -243,7 +243,7 @@ static int wacom_graphire_irq(struct wacom_wac *wacom) input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2])); input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4])); if (wacom->tool[0] != BTN_TOOL_MOUSE) { - input_report_abs(input, ABS_PRESSURE, data[6] | ((data[7] & 0x01) << 8)); + input_report_abs(input, ABS_PRESSURE, data[6] | ((data[7] & 0x03) << 8)); input_report_key(input, BTN_TOUCH, data[1] & 0x01); input_report_key(input, BTN_STYLUS, data[1] & 0x02); input_report_key(input, BTN_STYLUS2, data[1] & 0x04); diff --git a/drivers/input/touchscreen/eeti_ts.c b/drivers/input/touchscreen/eeti_ts.c index 503c7096ed3..908407efc67 100644 --- a/drivers/input/touchscreen/eeti_ts.c +++ b/drivers/input/touchscreen/eeti_ts.c @@ -48,7 +48,7 @@ struct eeti_ts_priv { struct input_dev *input; struct work_struct work; struct mutex mutex; - int irq, irq_active_high; + int irq_gpio, irq, irq_active_high; }; #define EETI_TS_BITDEPTH (11) @@ -62,7 +62,7 @@ struct eeti_ts_priv { static inline int eeti_ts_irq_active(struct eeti_ts_priv *priv) { - return gpio_get_value(irq_to_gpio(priv->irq)) == priv->irq_active_high; + return gpio_get_value(priv->irq_gpio) == priv->irq_active_high; } static void eeti_ts_read(struct work_struct *work) @@ -157,7 +157,7 @@ static void eeti_ts_close(struct input_dev *dev) static int __devinit eeti_ts_probe(struct i2c_client *client, const struct i2c_device_id *idp) { - struct eeti_ts_platform_data *pdata; + struct eeti_ts_platform_data *pdata = client->dev.platform_data; struct eeti_ts_priv *priv; struct input_dev *input; unsigned int irq_flags; @@ -199,9 +199,12 @@ static int __devinit eeti_ts_probe(struct i2c_client *client, priv->client = client; priv->input = input; - priv->irq = client->irq; + priv->irq_gpio = pdata->irq_gpio; + priv->irq = gpio_to_irq(pdata->irq_gpio); - pdata = client->dev.platform_data; + err = gpio_request_one(pdata->irq_gpio, GPIOF_IN, client->name); + if (err < 0) + goto err1; if (pdata) priv->irq_active_high = pdata->irq_active_high; @@ -215,13 +218,13 @@ static int __devinit eeti_ts_probe(struct i2c_client *client, err = input_register_device(input); if (err) - goto err1; + goto err2; err = request_irq(priv->irq, eeti_ts_isr, irq_flags, client->name, priv); if (err) { dev_err(&client->dev, "Unable to request touchscreen IRQ.\n"); - goto err2; + goto err3; } /* @@ -233,9 +236,11 @@ static int __devinit eeti_ts_probe(struct i2c_client *client, device_init_wakeup(&client->dev, 0); return 0; -err2: +err3: input_unregister_device(input); input = NULL; /* so we dont try to free it below */ +err2: + gpio_free(pdata->irq_gpio); err1: input_free_device(input); kfree(priv); diff --git a/drivers/input/touchscreen/tsc40.c b/drivers/input/touchscreen/tsc40.c index 29d5ed4dd31..80d46100d37 100644 --- a/drivers/input/touchscreen/tsc40.c +++ b/drivers/input/touchscreen/tsc40.c @@ -107,7 +107,6 @@ static int tsc_connect(struct serio *serio, struct serio_driver *drv) __set_bit(BTN_TOUCH, input_dev->keybit); input_set_abs_params(ptsc->dev, ABS_X, 0, 0x3ff, 0, 0); input_set_abs_params(ptsc->dev, ABS_Y, 0, 0x3ff, 0, 0); - input_set_abs_params(ptsc->dev, ABS_PRESSURE, 0, 0, 0, 0); serio_set_drvdata(serio, ptsc); diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index dfe7d37c82c..57ed244cf99 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -2254,6 +2254,18 @@ static int device_change_notifier(struct notifier_block *nb, iommu_init_device(dev); + /* + * dev_data is still NULL and + * got initialized in iommu_init_device + */ + dev_data = get_dev_data(dev); + + if (iommu_pass_through || dev_data->iommu_v2) { + dev_data->passthrough = true; + attach_device(dev, pt_domain); + break; + } + domain = domain_for_device(dev); /* allocate a protection domain if a device is added */ @@ -2271,10 +2283,7 @@ static int device_change_notifier(struct notifier_block *nb, dev_data = get_dev_data(dev); - if (!dev_data->passthrough) - dev->archdata.dma_ops = &amd_iommu_dma_ops; - else - dev->archdata.dma_ops = &nommu_dma_ops; + dev->archdata.dma_ops = &amd_iommu_dma_ops; break; case BUS_NOTIFY_DEL_DEVICE: diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index c04ddca7f12..ef0ae93500f 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c @@ -1001,6 +1001,38 @@ static void __init free_iommu_all(void) } } +/* + * Family15h Model 10h-1fh erratum 746 (IOMMU Logging May Stall Translations) + * Workaround: + * BIOS should disable L2B micellaneous clock gating by setting + * L2_L2B_CK_GATE_CONTROL[CKGateL2BMiscDisable](D0F2xF4_x90[2]) = 1b + */ +static void __init amd_iommu_erratum_746_workaround(struct amd_iommu *iommu) +{ + u32 value; + + if ((boot_cpu_data.x86 != 0x15) || + (boot_cpu_data.x86_model < 0x10) || + (boot_cpu_data.x86_model > 0x1f)) + return; + + pci_write_config_dword(iommu->dev, 0xf0, 0x90); + pci_read_config_dword(iommu->dev, 0xf4, &value); + + if (value & BIT(2)) + return; + + /* Select NB indirect register 0x90 and enable writing */ + pci_write_config_dword(iommu->dev, 0xf0, 0x90 | (1 << 8)); + + pci_write_config_dword(iommu->dev, 0xf4, value | 0x4); + pr_info("AMD-Vi: Applying erratum 746 workaround for IOMMU at %s\n", + dev_name(&iommu->dev->dev)); + + /* Clear the enable writing bit */ + pci_write_config_dword(iommu->dev, 0xf0, 0x90); +} + /* * This function clues the initialization function for one IOMMU * together and also allocates the command buffer and programs the @@ -1062,6 +1094,8 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h) if (iommu->cap & (1UL << IOMMU_CAP_NPCACHE)) amd_iommu_np_cache = true; + amd_iommu_erratum_746_workaround(iommu); + return pci_enable_device(iommu->dev); } diff --git a/drivers/iommu/amd_iommu_v2.c b/drivers/iommu/amd_iommu_v2.c index 036fe9bf157..a1f1bc87604 100644 --- a/drivers/iommu/amd_iommu_v2.c +++ b/drivers/iommu/amd_iommu_v2.c @@ -681,6 +681,8 @@ int amd_iommu_bind_pasid(struct pci_dev *pdev, int pasid, atomic_set(&pasid_state->count, 1); init_waitqueue_head(&pasid_state->wq); + spin_lock_init(&pasid_state->lock); + pasid_state->task = task; pasid_state->mm = get_task_mm(task); pasid_state->device_state = dev_state; diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 5fda348702c..5d71873c6f6 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -588,7 +588,9 @@ static void domain_update_iommu_coherency(struct dmar_domain *domain) { int i; - domain->iommu_coherency = 1; + i = find_first_bit(domain->iommu_bmp, g_num_of_iommus); + + domain->iommu_coherency = i < g_num_of_iommus ? 1 : 0; for_each_set_bit(i, domain->iommu_bmp, g_num_of_iommus) { if (!ecap_coherent(g_iommus[i]->ecap)) { @@ -1824,10 +1826,17 @@ static int __domain_mapping(struct dmar_domain *domain, unsigned long iov_pfn, if (!pte) return -ENOMEM; /* It is large page*/ - if (largepage_lvl > 1) + if (largepage_lvl > 1) { pteval |= DMA_PTE_LARGE_PAGE; - else + /* Ensure that old small page tables are removed to make room + for superpage, if they exist. */ + dma_pte_clear_range(domain, iov_pfn, + iov_pfn + lvl_to_nr_pages(largepage_lvl) - 1); + dma_pte_free_pagetable(domain, iov_pfn, + iov_pfn + lvl_to_nr_pages(largepage_lvl) - 1); + } else { pteval &= ~(uint64_t)DMA_PTE_LARGE_PAGE; + } } /* We don't need lock here, nobody else @@ -2312,8 +2321,39 @@ static int domain_add_dev_info(struct dmar_domain *domain, return 0; } +static bool device_has_rmrr(struct pci_dev *dev) +{ + struct dmar_rmrr_unit *rmrr; + int i; + + for_each_rmrr_units(rmrr) { + for (i = 0; i < rmrr->devices_cnt; i++) { + /* + * Return TRUE if this RMRR contains the device that + * is passed in. + */ + if (rmrr->devices[i] == dev) + return true; + } + } + return false; +} + static int iommu_should_identity_map(struct pci_dev *pdev, int startup) { + + /* + * We want to prevent any device associated with an RMRR from + * getting placed into the SI Domain. This is done because + * problems exist when devices are moved in and out of domains + * and their respective RMRR info is lost. We exempt USB devices + * from this process due to their usage of RMRRs that are known + * to not be needed after BIOS hand-off to OS. + */ + if (device_has_rmrr(pdev) && + (pdev->class >> 8) != PCI_CLASS_SERIAL_USB) + return 0; + if ((iommu_identity_mapping & IDENTMAP_AZALIA) && IS_AZALIA(pdev)) return 1; @@ -4153,6 +4193,21 @@ static struct iommu_ops intel_iommu_ops = { .pgsize_bitmap = INTEL_IOMMU_PGSIZES, }; +static void __devinit quirk_iommu_g4x_gfx(struct pci_dev *dev) +{ + /* G4x/GM45 integrated gfx dmar support is totally busted. */ + printk(KERN_INFO "DMAR: Disabling IOMMU for graphics on this chipset\n"); + dmar_map_gfx = 0; +} + +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_g4x_gfx); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e00, quirk_iommu_g4x_gfx); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e10, quirk_iommu_g4x_gfx); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e20, quirk_iommu_g4x_gfx); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e30, quirk_iommu_g4x_gfx); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e40, quirk_iommu_g4x_gfx); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e90, quirk_iommu_g4x_gfx); + static void __devinit quirk_iommu_rwbf(struct pci_dev *dev) { /* @@ -4161,12 +4216,6 @@ static void __devinit quirk_iommu_rwbf(struct pci_dev *dev) */ printk(KERN_INFO "DMAR: Forcing write-buffer flush capability\n"); rwbf_quirk = 1; - - /* https://bugzilla.redhat.com/show_bug.cgi?id=538163 */ - if (dev->revision == 0x07) { - printk(KERN_INFO "DMAR: Disabling IOMMU for graphics on this chipset\n"); - dmar_map_gfx = 0; - } } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_rwbf); diff --git a/drivers/iommu/intr_remapping.c b/drivers/iommu/intr_remapping.c index 6777ca04947..73ca321f330 100644 --- a/drivers/iommu/intr_remapping.c +++ b/drivers/iommu/intr_remapping.c @@ -752,6 +752,7 @@ int __init parse_ioapics_under_ir(void) { struct dmar_drhd_unit *drhd; int ir_supported = 0; + int ioapic_idx; for_each_drhd_unit(drhd) { struct intel_iommu *iommu = drhd->iommu; @@ -764,13 +765,20 @@ int __init parse_ioapics_under_ir(void) } } - if (ir_supported && ir_ioapic_num != nr_ioapics) { - printk(KERN_WARNING - "Not all IO-APIC's listed under remapping hardware\n"); - return -1; + if (!ir_supported) + return 0; + + for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++) { + int ioapic_id = mpc_ioapic_id(ioapic_idx); + if (!map_ioapic_to_ir(ioapic_id)) { + pr_err(FW_BUG "ioapic %d has no mapping iommu, " + "interrupt remapping will be disabled\n", + ioapic_id); + return -1; + } } - return ir_supported; + return 1; } int __init ir_dev_scope_init(void) diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c index 17ef6c49366..035f28edf8f 100644 --- a/drivers/iommu/tegra-smmu.c +++ b/drivers/iommu/tegra-smmu.c @@ -148,7 +148,7 @@ #define SMMU_ADDR_TO_PFN(addr) ((addr) >> 12) #define SMMU_ADDR_TO_PDN(addr) ((addr) >> 22) -#define SMMU_PDN_TO_ADDR(addr) ((pdn) << 22) +#define SMMU_PDN_TO_ADDR(pdn) ((pdn) << 22) #define _READABLE (1 << SMMU_PTB_DATA_ASID_READABLE_SHIFT) #define _WRITABLE (1 << SMMU_PTB_DATA_ASID_WRITABLE_SHIFT) diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c index afa080258bf..5e1bf61e80e 100644 --- a/drivers/isdn/gigaset/bas-gigaset.c +++ b/drivers/isdn/gigaset/bas-gigaset.c @@ -616,7 +616,13 @@ static void int_in_work(struct work_struct *work) if (rc == 0) /* success, resubmit interrupt read URB */ rc = usb_submit_urb(urb, GFP_ATOMIC); - if (rc != 0 && rc != -ENODEV) { + + switch (rc) { + case 0: /* success */ + case -ENODEV: /* device gone */ + case -EINVAL: /* URB already resubmitted, or terminal badness */ + break; + default: /* failure: try to recover by resetting the device */ dev_err(cs->dev, "clear halt failed: %s\n", get_usb_rcmsg(rc)); rc = usb_lock_device_for_reset(ucs->udev, ucs->interface); if (rc == 0) { @@ -2437,7 +2443,9 @@ static void gigaset_disconnect(struct usb_interface *interface) } /* gigaset_suspend - * This function is called before the USB connection is suspended. + * This function is called before the USB connection is suspended + * or before the USB device is reset. + * In the latter case, message == PMSG_ON. */ static int gigaset_suspend(struct usb_interface *intf, pm_message_t message) { @@ -2493,7 +2501,12 @@ static int gigaset_suspend(struct usb_interface *intf, pm_message_t message) del_timer_sync(&ucs->timer_atrdy); del_timer_sync(&ucs->timer_cmd_in); del_timer_sync(&ucs->timer_int_in); - cancel_work_sync(&ucs->int_in_wq); + + /* don't try to cancel int_in_wq from within reset as it + * might be the one requesting the reset + */ + if (message.event != PM_EVENT_ON) + cancel_work_sync(&ucs->int_in_wq); gig_dbg(DEBUG_SUSPEND, "suspend complete"); return 0; diff --git a/drivers/isdn/isdnloop/isdnloop.c b/drivers/isdn/isdnloop/isdnloop.c index 5405ec644db..baf2686aa8e 100644 --- a/drivers/isdn/isdnloop/isdnloop.c +++ b/drivers/isdn/isdnloop/isdnloop.c @@ -16,7 +16,6 @@ #include #include "isdnloop.h" -static char *revision = "$Revision: 1.11.6.7 $"; static char *isdnloop_id = "loop0"; MODULE_DESCRIPTION("ISDN4Linux: Pseudo Driver that simulates an ISDN card"); @@ -1494,17 +1493,6 @@ isdnloop_addcard(char *id1) static int __init isdnloop_init(void) { - char *p; - char rev[10]; - - if ((p = strchr(revision, ':'))) { - strcpy(rev, p + 1); - p = strchr(rev, '$'); - *p = 0; - } else - strcpy(rev, " ??? "); - printk(KERN_NOTICE "isdnloop-ISDN-driver Rev%s\n", rev); - if (isdnloop_id) return (isdnloop_addcard(isdnloop_id)); diff --git a/drivers/leds/leds-lp5521.c b/drivers/leds/leds-lp5521.c index 410a723b869..23815624f35 100644 --- a/drivers/leds/leds-lp5521.c +++ b/drivers/leds/leds-lp5521.c @@ -193,9 +193,14 @@ static int lp5521_load_program(struct lp5521_engine *eng, const u8 *pattern) /* move current engine to direct mode and remember the state */ ret = lp5521_set_engine_mode(eng, LP5521_CMD_DIRECT); + if (ret) + return ret; + /* Mode change requires min 500 us delay. 1 - 2 ms with margin */ usleep_range(1000, 2000); - ret |= lp5521_read(client, LP5521_REG_OP_MODE, &mode); + ret = lp5521_read(client, LP5521_REG_OP_MODE, &mode); + if (ret) + return ret; /* For loading, all the engines to load mode */ lp5521_write(client, LP5521_REG_OP_MODE, LP5521_CMD_DIRECT); @@ -211,8 +216,7 @@ static int lp5521_load_program(struct lp5521_engine *eng, const u8 *pattern) LP5521_PROG_MEM_SIZE, pattern); - ret |= lp5521_write(client, LP5521_REG_OP_MODE, mode); - return ret; + return lp5521_write(client, LP5521_REG_OP_MODE, mode); } static int lp5521_set_led_current(struct lp5521_chip *chip, int led, u8 curr) @@ -785,7 +789,7 @@ static int __devinit lp5521_probe(struct i2c_client *client, * LP5521_REG_ENABLE register will not have any effect - strange! */ ret = lp5521_read(client, LP5521_REG_R_CURRENT, &buf); - if (buf != LP5521_REG_R_CURR_DEFAULT) { + if (ret || buf != LP5521_REG_R_CURR_DEFAULT) { dev_err(&client->dev, "error in resetting chip\n"); goto fail2; } diff --git a/drivers/md/persistent-data/dm-btree-internal.h b/drivers/md/persistent-data/dm-btree-internal.h index 5709bfeab1e..accbb05f17b 100644 --- a/drivers/md/persistent-data/dm-btree-internal.h +++ b/drivers/md/persistent-data/dm-btree-internal.h @@ -36,13 +36,13 @@ struct node_header { __le32 padding; } __packed; -struct node { +struct btree_node { struct node_header header; __le64 keys[0]; } __packed; -void inc_children(struct dm_transaction_manager *tm, struct node *n, +void inc_children(struct dm_transaction_manager *tm, struct btree_node *n, struct dm_btree_value_type *vt); int new_block(struct dm_btree_info *info, struct dm_block **result); @@ -64,7 +64,7 @@ struct ro_spine { void init_ro_spine(struct ro_spine *s, struct dm_btree_info *info); int exit_ro_spine(struct ro_spine *s); int ro_step(struct ro_spine *s, dm_block_t new_child); -struct node *ro_node(struct ro_spine *s); +struct btree_node *ro_node(struct ro_spine *s); struct shadow_spine { struct dm_btree_info *info; @@ -98,17 +98,17 @@ int shadow_root(struct shadow_spine *s); /* * Some inlines. */ -static inline __le64 *key_ptr(struct node *n, uint32_t index) +static inline __le64 *key_ptr(struct btree_node *n, uint32_t index) { return n->keys + index; } -static inline void *value_base(struct node *n) +static inline void *value_base(struct btree_node *n) { return &n->keys[le32_to_cpu(n->header.max_entries)]; } -static inline void *value_ptr(struct node *n, uint32_t index) +static inline void *value_ptr(struct btree_node *n, uint32_t index) { uint32_t value_size = le32_to_cpu(n->header.value_size); return value_base(n) + (value_size * index); @@ -117,7 +117,7 @@ static inline void *value_ptr(struct node *n, uint32_t index) /* * Assumes the values are suitably-aligned and converts to core format. */ -static inline uint64_t value64(struct node *n, uint32_t index) +static inline uint64_t value64(struct btree_node *n, uint32_t index) { __le64 *values_le = value_base(n); @@ -127,7 +127,7 @@ static inline uint64_t value64(struct node *n, uint32_t index) /* * Searching for a key within a single node. */ -int lower_bound(struct node *n, uint64_t key); +int lower_bound(struct btree_node *n, uint64_t key); extern struct dm_block_validator btree_node_validator; diff --git a/drivers/md/persistent-data/dm-btree-remove.c b/drivers/md/persistent-data/dm-btree-remove.c index aa71e2359a0..c4f28133ef8 100644 --- a/drivers/md/persistent-data/dm-btree-remove.c +++ b/drivers/md/persistent-data/dm-btree-remove.c @@ -53,7 +53,7 @@ /* * Some little utilities for moving node data around. */ -static void node_shift(struct node *n, int shift) +static void node_shift(struct btree_node *n, int shift) { uint32_t nr_entries = le32_to_cpu(n->header.nr_entries); uint32_t value_size = le32_to_cpu(n->header.value_size); @@ -79,7 +79,7 @@ static void node_shift(struct node *n, int shift) } } -static void node_copy(struct node *left, struct node *right, int shift) +static void node_copy(struct btree_node *left, struct btree_node *right, int shift) { uint32_t nr_left = le32_to_cpu(left->header.nr_entries); uint32_t value_size = le32_to_cpu(left->header.value_size); @@ -108,7 +108,7 @@ static void node_copy(struct node *left, struct node *right, int shift) /* * Delete a specific entry from a leaf node. */ -static void delete_at(struct node *n, unsigned index) +static void delete_at(struct btree_node *n, unsigned index) { unsigned nr_entries = le32_to_cpu(n->header.nr_entries); unsigned nr_to_copy = nr_entries - (index + 1); @@ -128,7 +128,7 @@ static void delete_at(struct node *n, unsigned index) n->header.nr_entries = cpu_to_le32(nr_entries - 1); } -static unsigned merge_threshold(struct node *n) +static unsigned merge_threshold(struct btree_node *n) { return le32_to_cpu(n->header.max_entries) / 3; } @@ -136,7 +136,7 @@ static unsigned merge_threshold(struct node *n) struct child { unsigned index; struct dm_block *block; - struct node *n; + struct btree_node *n; }; static struct dm_btree_value_type le64_type = { @@ -147,7 +147,7 @@ static struct dm_btree_value_type le64_type = { .equal = NULL }; -static int init_child(struct dm_btree_info *info, struct node *parent, +static int init_child(struct dm_btree_info *info, struct btree_node *parent, unsigned index, struct child *result) { int r, inc; @@ -177,7 +177,7 @@ static int exit_child(struct dm_btree_info *info, struct child *c) return dm_tm_unlock(info->tm, c->block); } -static void shift(struct node *left, struct node *right, int count) +static void shift(struct btree_node *left, struct btree_node *right, int count) { uint32_t nr_left = le32_to_cpu(left->header.nr_entries); uint32_t nr_right = le32_to_cpu(right->header.nr_entries); @@ -203,11 +203,11 @@ static void shift(struct node *left, struct node *right, int count) right->header.nr_entries = cpu_to_le32(nr_right + count); } -static void __rebalance2(struct dm_btree_info *info, struct node *parent, +static void __rebalance2(struct dm_btree_info *info, struct btree_node *parent, struct child *l, struct child *r) { - struct node *left = l->n; - struct node *right = r->n; + struct btree_node *left = l->n; + struct btree_node *right = r->n; uint32_t nr_left = le32_to_cpu(left->header.nr_entries); uint32_t nr_right = le32_to_cpu(right->header.nr_entries); unsigned threshold = 2 * merge_threshold(left) + 1; @@ -239,7 +239,7 @@ static int rebalance2(struct shadow_spine *s, struct dm_btree_info *info, unsigned left_index) { int r; - struct node *parent; + struct btree_node *parent; struct child left, right; parent = dm_block_data(shadow_current(s)); @@ -270,9 +270,9 @@ static int rebalance2(struct shadow_spine *s, struct dm_btree_info *info, * in right, then rebalance2. This wastes some cpu, but I want something * simple atm. */ -static void delete_center_node(struct dm_btree_info *info, struct node *parent, +static void delete_center_node(struct dm_btree_info *info, struct btree_node *parent, struct child *l, struct child *c, struct child *r, - struct node *left, struct node *center, struct node *right, + struct btree_node *left, struct btree_node *center, struct btree_node *right, uint32_t nr_left, uint32_t nr_center, uint32_t nr_right) { uint32_t max_entries = le32_to_cpu(left->header.max_entries); @@ -301,9 +301,9 @@ static void delete_center_node(struct dm_btree_info *info, struct node *parent, /* * Redistributes entries among 3 sibling nodes. */ -static void redistribute3(struct dm_btree_info *info, struct node *parent, +static void redistribute3(struct dm_btree_info *info, struct btree_node *parent, struct child *l, struct child *c, struct child *r, - struct node *left, struct node *center, struct node *right, + struct btree_node *left, struct btree_node *center, struct btree_node *right, uint32_t nr_left, uint32_t nr_center, uint32_t nr_right) { int s; @@ -343,12 +343,12 @@ static void redistribute3(struct dm_btree_info *info, struct node *parent, *key_ptr(parent, r->index) = right->keys[0]; } -static void __rebalance3(struct dm_btree_info *info, struct node *parent, +static void __rebalance3(struct dm_btree_info *info, struct btree_node *parent, struct child *l, struct child *c, struct child *r) { - struct node *left = l->n; - struct node *center = c->n; - struct node *right = r->n; + struct btree_node *left = l->n; + struct btree_node *center = c->n; + struct btree_node *right = r->n; uint32_t nr_left = le32_to_cpu(left->header.nr_entries); uint32_t nr_center = le32_to_cpu(center->header.nr_entries); @@ -371,7 +371,7 @@ static int rebalance3(struct shadow_spine *s, struct dm_btree_info *info, unsigned left_index) { int r; - struct node *parent = dm_block_data(shadow_current(s)); + struct btree_node *parent = dm_block_data(shadow_current(s)); struct child left, center, right; /* @@ -421,7 +421,7 @@ static int get_nr_entries(struct dm_transaction_manager *tm, { int r; struct dm_block *block; - struct node *n; + struct btree_node *n; r = dm_tm_read_lock(tm, b, &btree_node_validator, &block); if (r) @@ -438,7 +438,7 @@ static int rebalance_children(struct shadow_spine *s, { int i, r, has_left_sibling, has_right_sibling; uint32_t child_entries; - struct node *n; + struct btree_node *n; n = dm_block_data(shadow_current(s)); @@ -483,7 +483,7 @@ static int rebalance_children(struct shadow_spine *s, return r; } -static int do_leaf(struct node *n, uint64_t key, unsigned *index) +static int do_leaf(struct btree_node *n, uint64_t key, unsigned *index) { int i = lower_bound(n, key); @@ -506,7 +506,7 @@ static int remove_raw(struct shadow_spine *s, struct dm_btree_info *info, uint64_t key, unsigned *index) { int i = *index, r; - struct node *n; + struct btree_node *n; for (;;) { r = shadow_step(s, root, vt); @@ -556,7 +556,7 @@ int dm_btree_remove(struct dm_btree_info *info, dm_block_t root, unsigned level, last_level = info->levels - 1; int index = 0, r = 0; struct shadow_spine spine; - struct node *n; + struct btree_node *n; init_shadow_spine(&spine, info); for (level = 0; level < info->levels; level++) { diff --git a/drivers/md/persistent-data/dm-btree-spine.c b/drivers/md/persistent-data/dm-btree-spine.c index d9a7912ee8e..2f0805c3263 100644 --- a/drivers/md/persistent-data/dm-btree-spine.c +++ b/drivers/md/persistent-data/dm-btree-spine.c @@ -23,7 +23,7 @@ static void node_prepare_for_write(struct dm_block_validator *v, struct dm_block *b, size_t block_size) { - struct node *n = dm_block_data(b); + struct btree_node *n = dm_block_data(b); struct node_header *h = &n->header; h->blocknr = cpu_to_le64(dm_block_location(b)); @@ -38,7 +38,7 @@ static int node_check(struct dm_block_validator *v, struct dm_block *b, size_t block_size) { - struct node *n = dm_block_data(b); + struct btree_node *n = dm_block_data(b); struct node_header *h = &n->header; size_t value_size; __le32 csum_disk; @@ -164,7 +164,7 @@ int ro_step(struct ro_spine *s, dm_block_t new_child) return r; } -struct node *ro_node(struct ro_spine *s) +struct btree_node *ro_node(struct ro_spine *s) { struct dm_block *block; diff --git a/drivers/md/persistent-data/dm-btree.c b/drivers/md/persistent-data/dm-btree.c index d12b2cc51f1..371f3d49d18 100644 --- a/drivers/md/persistent-data/dm-btree.c +++ b/drivers/md/persistent-data/dm-btree.c @@ -38,7 +38,7 @@ static void array_insert(void *base, size_t elt_size, unsigned nr_elts, /*----------------------------------------------------------------*/ /* makes the assumption that no two keys are the same. */ -static int bsearch(struct node *n, uint64_t key, int want_hi) +static int bsearch(struct btree_node *n, uint64_t key, int want_hi) { int lo = -1, hi = le32_to_cpu(n->header.nr_entries); @@ -58,12 +58,12 @@ static int bsearch(struct node *n, uint64_t key, int want_hi) return want_hi ? hi : lo; } -int lower_bound(struct node *n, uint64_t key) +int lower_bound(struct btree_node *n, uint64_t key) { return bsearch(n, key, 0); } -void inc_children(struct dm_transaction_manager *tm, struct node *n, +void inc_children(struct dm_transaction_manager *tm, struct btree_node *n, struct dm_btree_value_type *vt) { unsigned i; @@ -77,7 +77,7 @@ void inc_children(struct dm_transaction_manager *tm, struct node *n, vt->inc(vt->context, value_ptr(n, i)); } -static int insert_at(size_t value_size, struct node *node, unsigned index, +static int insert_at(size_t value_size, struct btree_node *node, unsigned index, uint64_t key, void *value) __dm_written_to_disk(value) { @@ -122,7 +122,7 @@ int dm_btree_empty(struct dm_btree_info *info, dm_block_t *root) { int r; struct dm_block *b; - struct node *n; + struct btree_node *n; size_t block_size; uint32_t max_entries; @@ -154,7 +154,7 @@ EXPORT_SYMBOL_GPL(dm_btree_empty); #define MAX_SPINE_DEPTH 64 struct frame { struct dm_block *b; - struct node *n; + struct btree_node *n; unsigned level; unsigned nr_children; unsigned current_child; @@ -295,7 +295,7 @@ EXPORT_SYMBOL_GPL(dm_btree_del); /*----------------------------------------------------------------*/ static int btree_lookup_raw(struct ro_spine *s, dm_block_t block, uint64_t key, - int (*search_fn)(struct node *, uint64_t), + int (*search_fn)(struct btree_node *, uint64_t), uint64_t *result_key, void *v, size_t value_size) { int i, r; @@ -406,7 +406,7 @@ static int btree_split_sibling(struct shadow_spine *s, dm_block_t root, size_t size; unsigned nr_left, nr_right; struct dm_block *left, *right, *parent; - struct node *ln, *rn, *pn; + struct btree_node *ln, *rn, *pn; __le64 location; left = shadow_current(s); @@ -491,7 +491,7 @@ static int btree_split_beneath(struct shadow_spine *s, uint64_t key) size_t size; unsigned nr_left, nr_right; struct dm_block *left, *right, *new_parent; - struct node *pn, *ln, *rn; + struct btree_node *pn, *ln, *rn; __le64 val; new_parent = shadow_current(s); @@ -576,7 +576,7 @@ static int btree_insert_raw(struct shadow_spine *s, dm_block_t root, uint64_t key, unsigned *index) { int r, i = *index, top = 1; - struct node *node; + struct btree_node *node; for (;;) { r = shadow_step(s, root, vt); @@ -643,7 +643,7 @@ static int insert(struct dm_btree_info *info, dm_block_t root, unsigned level, index = -1, last_level = info->levels - 1; dm_block_t block = root; struct shadow_spine spine; - struct node *n; + struct btree_node *n; struct dm_btree_value_type le64_type; le64_type.context = NULL; diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c index 00a67326c19..39eab73b01a 100644 --- a/drivers/media/dvb/dvb-core/dvbdev.c +++ b/drivers/media/dvb/dvb-core/dvbdev.c @@ -243,6 +243,7 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, if (minor == MAX_DVB_MINORS) { kfree(dvbdevfops); kfree(dvbdev); + up_write(&minor_rwsem); mutex_unlock(&dvbdev_register_lock); return -EINVAL; } diff --git a/drivers/media/dvb/siano/smsusb.c b/drivers/media/dvb/siano/smsusb.c index 664e460f247..aac622200e9 100644 --- a/drivers/media/dvb/siano/smsusb.c +++ b/drivers/media/dvb/siano/smsusb.c @@ -481,7 +481,7 @@ static int smsusb_resume(struct usb_interface *intf) return 0; } -static const struct usb_device_id smsusb_id_table[] __devinitconst = { +static const struct usb_device_id smsusb_id_table[] = { { USB_DEVICE(0x187f, 0x0010), .driver_info = SMS1XXX_BOARD_SIANO_STELLAR }, { USB_DEVICE(0x187f, 0x0100), diff --git a/drivers/media/rc/ene_ir.c b/drivers/media/rc/ene_ir.c index bef5296173c..647dd951b0e 100644 --- a/drivers/media/rc/ene_ir.c +++ b/drivers/media/rc/ene_ir.c @@ -1018,6 +1018,8 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id) spin_lock_init(&dev->hw_lock); + dev->hw_io = pnp_port_start(pnp_dev, 0); + pnp_set_drvdata(pnp_dev, dev); dev->pnp_dev = pnp_dev; @@ -1072,7 +1074,6 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id) /* claim the resources */ error = -EBUSY; - dev->hw_io = pnp_port_start(pnp_dev, 0); if (!request_region(dev->hw_io, ENE_IO_SIZE, ENE_DRIVER_NAME)) { dev->hw_io = -1; dev->irq = -1; diff --git a/drivers/media/rc/ite-cir.c b/drivers/media/rc/ite-cir.c index 0e49c99abf6..c06992e1320 100644 --- a/drivers/media/rc/ite-cir.c +++ b/drivers/media/rc/ite-cir.c @@ -1473,6 +1473,7 @@ static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id rdev = rc_allocate_device(); if (!rdev) goto failure; + itdev->rdev = rdev; ret = -ENODEV; @@ -1604,7 +1605,6 @@ static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id if (ret) goto failure; - itdev->rdev = rdev; ite_pr(KERN_NOTICE, "driver has been successfully loaded\n"); return 0; diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index 6e16b09c24a..cabc19c1051 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c @@ -775,10 +775,11 @@ static ssize_t show_protocols(struct device *device, if (dev->driver_type == RC_DRIVER_SCANCODE) { enabled = dev->rc_map.rc_type; allowed = dev->allowed_protos; - } else { + } else if (dev->raw) { enabled = dev->raw->enabled_protocols; allowed = ir_raw_get_allowed_protocols(); - } + } else + return -ENODEV; IR_dprintk(1, "allowed - 0x%llx, enabled - 0x%llx\n", (long long)allowed, diff --git a/drivers/media/video/au0828/au0828-video.c b/drivers/media/video/au0828/au0828-video.c index 0b3e481ffe8..eab06419473 100644 --- a/drivers/media/video/au0828/au0828-video.c +++ b/drivers/media/video/au0828/au0828-video.c @@ -1692,14 +1692,18 @@ static int vidioc_streamoff(struct file *file, void *priv, (AUVI_INPUT(i).audio_setup)(dev, 0); } - videobuf_streamoff(&fh->vb_vidq); - res_free(fh, AU0828_RESOURCE_VIDEO); + if (res_check(fh, AU0828_RESOURCE_VIDEO)) { + videobuf_streamoff(&fh->vb_vidq); + res_free(fh, AU0828_RESOURCE_VIDEO); + } } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { dev->vbi_timeout_running = 0; del_timer_sync(&dev->vbi_timeout); - videobuf_streamoff(&fh->vb_vbiq); - res_free(fh, AU0828_RESOURCE_VBI); + if (res_check(fh, AU0828_RESOURCE_VBI)) { + videobuf_streamoff(&fh->vb_vbiq); + res_free(fh, AU0828_RESOURCE_VBI); + } } return 0; diff --git a/drivers/media/video/cx231xx/cx231xx-audio.c b/drivers/media/video/cx231xx/cx231xx-audio.c index a2c2b7d343e..e5742a0e19a 100644 --- a/drivers/media/video/cx231xx/cx231xx-audio.c +++ b/drivers/media/video/cx231xx/cx231xx-audio.c @@ -307,7 +307,7 @@ static int cx231xx_init_audio_isoc(struct cx231xx *dev) urb->context = dev; urb->pipe = usb_rcvisocpipe(dev->udev, dev->adev.end_point_addr); - urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP; + urb->transfer_flags = URB_ISO_ASAP; urb->transfer_buffer = dev->adev.transfer_buffer[i]; urb->interval = 1; urb->complete = cx231xx_audio_isocirq; @@ -368,7 +368,7 @@ static int cx231xx_init_audio_bulk(struct cx231xx *dev) urb->context = dev; urb->pipe = usb_rcvbulkpipe(dev->udev, dev->adev.end_point_addr); - urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP; + urb->transfer_flags = 0; urb->transfer_buffer = dev->adev.transfer_buffer[i]; urb->complete = cx231xx_audio_bulkirq; urb->transfer_buffer_length = sb_size; diff --git a/drivers/media/video/cx231xx/cx231xx-vbi.c b/drivers/media/video/cx231xx/cx231xx-vbi.c index 8cdee5f78f1..9c5967e1d0c 100644 --- a/drivers/media/video/cx231xx/cx231xx-vbi.c +++ b/drivers/media/video/cx231xx/cx231xx-vbi.c @@ -452,7 +452,7 @@ int cx231xx_init_vbi_isoc(struct cx231xx *dev, int max_packets, return -ENOMEM; } dev->vbi_mode.bulk_ctl.urb[i] = urb; - urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP; + urb->transfer_flags = 0; dev->vbi_mode.bulk_ctl.transfer_buffer[i] = kzalloc(sb_size, GFP_KERNEL); diff --git a/drivers/media/video/cx25821/cx25821-core.c b/drivers/media/video/cx25821/cx25821-core.c index 7930ca58349..235bf7da6c0 100644 --- a/drivers/media/video/cx25821/cx25821-core.c +++ b/drivers/media/video/cx25821/cx25821-core.c @@ -912,9 +912,6 @@ static int cx25821_dev_setup(struct cx25821_dev *dev) list_add_tail(&dev->devlist, &cx25821_devlist); mutex_unlock(&cx25821_devlist_mutex); - strcpy(cx25821_boards[UNKNOWN_BOARD].name, "unknown"); - strcpy(cx25821_boards[CX25821_BOARD].name, "cx25821"); - if (dev->pci->device != 0x8210) { pr_info("%s(): Exiting. Incorrect Hardware device = 0x%02x\n", __func__, dev->pci->device); diff --git a/drivers/media/video/cx25821/cx25821.h b/drivers/media/video/cx25821/cx25821.h index b9aa801b00a..029f2934a6d 100644 --- a/drivers/media/video/cx25821/cx25821.h +++ b/drivers/media/video/cx25821/cx25821.h @@ -187,7 +187,7 @@ enum port { }; struct cx25821_board { - char *name; + const char *name; enum port porta; enum port portb; enum port portc; diff --git a/drivers/media/video/gspca/jl2005bcd.c b/drivers/media/video/gspca/jl2005bcd.c index 53f58ef367c..3264d878cfd 100644 --- a/drivers/media/video/gspca/jl2005bcd.c +++ b/drivers/media/video/gspca/jl2005bcd.c @@ -510,7 +510,7 @@ static const struct sd_desc sd_desc = { }; /* -- module initialisation -- */ -static const __devinitdata struct usb_device_id device_table[] = { +static const struct usb_device_id device_table[] = { {USB_DEVICE(0x0979, 0x0227)}, {} }; diff --git a/drivers/media/video/gspca/pac7302.c b/drivers/media/video/gspca/pac7302.c index 30662fccb0c..63f571b7cc2 100644 --- a/drivers/media/video/gspca/pac7302.c +++ b/drivers/media/video/gspca/pac7302.c @@ -945,6 +945,7 @@ static const struct usb_device_id device_table[] = { {USB_DEVICE(0x093a, 0x262a)}, {USB_DEVICE(0x093a, 0x262c)}, {USB_DEVICE(0x145f, 0x013c)}, + {USB_DEVICE(0x1ae7, 0x2001)}, /* SpeedLink Snappy Mic SL-6825-SBK */ {} }; MODULE_DEVICE_TABLE(usb, device_table); diff --git a/drivers/media/video/gspca/spca506.c b/drivers/media/video/gspca/spca506.c index 54eed87672d..21e6a37bc7a 100644 --- a/drivers/media/video/gspca/spca506.c +++ b/drivers/media/video/gspca/spca506.c @@ -685,7 +685,7 @@ static const struct sd_desc sd_desc = { }; /* -- module initialisation -- */ -static const struct usb_device_id device_table[] __devinitconst = { +static const struct usb_device_id device_table[] = { {USB_DEVICE(0x06e1, 0xa190)}, /*fixme: may be IntelPCCameraPro BRIDGE_SPCA505 {USB_DEVICE(0x0733, 0x0430)}, */ diff --git a/drivers/media/video/uvc/uvc_queue.c b/drivers/media/video/uvc/uvc_queue.c index 8f54e24e3f3..4261bf23193 100644 --- a/drivers/media/video/uvc/uvc_queue.c +++ b/drivers/media/video/uvc/uvc_queue.c @@ -355,6 +355,7 @@ struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue, if ((queue->flags & UVC_QUEUE_DROP_CORRUPTED) && buf->error) { buf->error = 0; buf->state = UVC_BUF_STATE_QUEUED; + buf->bytesused = 0; vb2_set_plane_payload(&buf->buf, 0, 0); return buf; } diff --git a/drivers/mfd/ezx-pcap.c b/drivers/mfd/ezx-pcap.c index 43a76c41cfc..db662e2dcfa 100644 --- a/drivers/mfd/ezx-pcap.c +++ b/drivers/mfd/ezx-pcap.c @@ -202,7 +202,7 @@ static void pcap_isr_work(struct work_struct *work) } local_irq_enable(); ezx_pcap_write(pcap, PCAP_REG_MSR, pcap->msr); - } while (gpio_get_value(irq_to_gpio(pcap->spi->irq))); + } while (gpio_get_value(pdata->gpio)); } static void pcap_irq_handler(unsigned int irq, struct irq_desc *desc) diff --git a/drivers/mfd/max8925-core.c b/drivers/mfd/max8925-core.c index ca881efedf7..746a59c29fe 100644 --- a/drivers/mfd/max8925-core.c +++ b/drivers/mfd/max8925-core.c @@ -18,12 +18,19 @@ #include #include +static struct resource io_parent = { + .start = 0, + .end = 0xffffffff, + .flags = IORESOURCE_IO, +}; + static struct resource backlight_resources[] = { { .name = "max8925-backlight", .start = MAX8925_WLED_MODE_CNTL, .end = MAX8925_WLED_CNTL, .flags = IORESOURCE_IO, + .parent = &io_parent, }, }; @@ -42,6 +49,7 @@ static struct resource touch_resources[] = { .start = MAX8925_TSC_IRQ, .end = MAX8925_ADC_RES_END, .flags = IORESOURCE_IO, + .parent = &io_parent, }, }; @@ -60,6 +68,7 @@ static struct resource power_supply_resources[] = { .start = MAX8925_CHG_IRQ1, .end = MAX8925_CHG_IRQ1_MASK, .flags = IORESOURCE_IO, + .parent = &io_parent, }, }; @@ -118,6 +127,7 @@ static struct mfd_cell onkey_devs[] = { .start = MAX8925_##_start, \ .end = MAX8925_##_end, \ .flags = IORESOURCE_IO, \ + .parent = &io_parent, \ } static struct resource regulator_resources[] = { diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c index ffc3d48676a..ef80da67eb5 100644 --- a/drivers/mfd/mfd-core.c +++ b/drivers/mfd/mfd-core.c @@ -19,6 +19,10 @@ #include #include +static struct device_type mfd_dev_type = { + .name = "mfd_device", +}; + int mfd_cell_enable(struct platform_device *pdev) { const struct mfd_cell *cell = mfd_get_cell(pdev); @@ -88,6 +92,7 @@ static int mfd_add_device(struct device *parent, int id, goto fail_device; pdev->dev.parent = parent; + pdev->dev.type = &mfd_dev_type; if (cell->pdata_size) { ret = platform_device_add_data(pdev, @@ -183,10 +188,16 @@ EXPORT_SYMBOL(mfd_add_devices); static int mfd_remove_devices_fn(struct device *dev, void *c) { - struct platform_device *pdev = to_platform_device(dev); - const struct mfd_cell *cell = mfd_get_cell(pdev); + struct platform_device *pdev; + const struct mfd_cell *cell; atomic_t **usage_count = c; + if (dev->type != &mfd_dev_type) + return 0; + + pdev = to_platform_device(dev); + cell = mfd_get_cell(pdev); + /* find the base address of usage_count pointers (for freeing) */ if (!*usage_count || (cell->usage_count < *usage_count)) *usage_count = cell->usage_count; diff --git a/drivers/mfd/wm831x-otp.c b/drivers/mfd/wm831x-otp.c index f742745ff35..b90f3e06b6c 100644 --- a/drivers/mfd/wm831x-otp.c +++ b/drivers/mfd/wm831x-otp.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -66,6 +67,7 @@ static DEVICE_ATTR(unique_id, 0444, wm831x_unique_id_show, NULL); int wm831x_otp_init(struct wm831x *wm831x) { + char uuid[WM831X_UNIQUE_ID_LEN]; int ret; ret = device_create_file(wm831x->dev, &dev_attr_unique_id); @@ -73,6 +75,12 @@ int wm831x_otp_init(struct wm831x *wm831x) dev_err(wm831x->dev, "Unique ID attribute not created: %d\n", ret); + ret = wm831x_unique_id_read(wm831x, uuid); + if (ret == 0) + add_device_randomness(uuid, sizeof(uuid)); + else + dev_err(wm831x->dev, "Failed to read UUID: %d\n", ret); + return ret; } diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c index 9d7ca1e978f..8d46e68cb17 100644 --- a/drivers/mfd/wm8994-core.c +++ b/drivers/mfd/wm8994-core.c @@ -541,6 +541,7 @@ static __devinit int wm8994_device_init(struct wm8994 *wm8994, int irq) case 1: case 2: case 3: + case 4: regmap_patch = wm1811_reva_patch; patch_regs = ARRAY_SIZE(wm1811_reva_patch); break; diff --git a/drivers/misc/sgi-xp/xpc_main.c b/drivers/misc/sgi-xp/xpc_main.c index 8d082b46426..d971817182f 100644 --- a/drivers/misc/sgi-xp/xpc_main.c +++ b/drivers/misc/sgi-xp/xpc_main.c @@ -53,6 +53,10 @@ #include #include "xpc.h" +#ifdef CONFIG_X86_64 +#include +#endif + /* define two XPC debug device structures to be used with dev_dbg() et al */ struct device_driver xpc_dbg_name = { @@ -1079,6 +1083,9 @@ xpc_system_reboot(struct notifier_block *nb, unsigned long event, void *unused) return NOTIFY_DONE; } +/* Used to only allow one cpu to complete disconnect */ +static unsigned int xpc_die_disconnecting; + /* * Notify other partitions to deactivate from us by first disengaging from all * references to our memory. @@ -1092,6 +1099,9 @@ xpc_die_deactivate(void) long keep_waiting; long wait_to_print; + if (cmpxchg(&xpc_die_disconnecting, 0, 1)) + return; + /* keep xpc_hb_checker thread from doing anything (just in case) */ xpc_exiting = 1; @@ -1159,7 +1169,7 @@ xpc_die_deactivate(void) * about the lack of a heartbeat. */ static int -xpc_system_die(struct notifier_block *nb, unsigned long event, void *unused) +xpc_system_die(struct notifier_block *nb, unsigned long event, void *_die_args) { #ifdef CONFIG_IA64 /* !!! temporary kludge */ switch (event) { @@ -1191,7 +1201,27 @@ xpc_system_die(struct notifier_block *nb, unsigned long event, void *unused) break; } #else - xpc_die_deactivate(); + struct die_args *die_args = _die_args; + + switch (event) { + case DIE_TRAP: + if (die_args->trapnr == X86_TRAP_DF) + xpc_die_deactivate(); + + if (((die_args->trapnr == X86_TRAP_MF) || + (die_args->trapnr == X86_TRAP_XF)) && + !user_mode_vm(die_args->regs)) + xpc_die_deactivate(); + + break; + case DIE_INT3: + case DIE_DEBUG: + break; + case DIE_OOPS: + case DIE_GPF: + default: + xpc_die_deactivate(); + } #endif return NOTIFY_DONE; diff --git a/drivers/misc/sgi-xp/xpc_uv.c b/drivers/misc/sgi-xp/xpc_uv.c index 17bbacb1b4b..cc2ae7ec0d2 100644 --- a/drivers/misc/sgi-xp/xpc_uv.c +++ b/drivers/misc/sgi-xp/xpc_uv.c @@ -18,6 +18,8 @@ #include #include #include +#include +#include #include #include #include @@ -59,6 +61,8 @@ static struct xpc_heartbeat_uv *xpc_heartbeat_uv; XPC_NOTIFY_MSG_SIZE_UV) #define XPC_NOTIFY_IRQ_NAME "xpc_notify" +static int xpc_mq_node = -1; + static struct xpc_gru_mq_uv *xpc_activate_mq_uv; static struct xpc_gru_mq_uv *xpc_notify_mq_uv; @@ -109,11 +113,8 @@ xpc_get_gru_mq_irq_uv(struct xpc_gru_mq_uv *mq, int cpu, char *irq_name) #if defined CONFIG_X86_64 mq->irq = uv_setup_irq(irq_name, cpu, mq->mmr_blade, mq->mmr_offset, UV_AFFINITY_CPU); - if (mq->irq < 0) { - dev_err(xpc_part, "uv_setup_irq() returned error=%d\n", - -mq->irq); + if (mq->irq < 0) return mq->irq; - } mq->mmr_value = uv_read_global_mmr64(mmr_pnode, mq->mmr_offset); @@ -238,8 +239,9 @@ xpc_create_gru_mq_uv(unsigned int mq_size, int cpu, char *irq_name, mq->mmr_blade = uv_cpu_to_blade_id(cpu); nid = cpu_to_node(cpu); - page = alloc_pages_exact_node(nid, GFP_KERNEL | __GFP_ZERO | GFP_THISNODE, - pg_order); + page = alloc_pages_exact_node(nid, + GFP_KERNEL | __GFP_ZERO | GFP_THISNODE, + pg_order); if (page == NULL) { dev_err(xpc_part, "xpc_create_gru_mq_uv() failed to alloc %d " "bytes of memory on nid=%d for GRU mq\n", mq_size, nid); @@ -1731,9 +1733,50 @@ static struct xpc_arch_operations xpc_arch_ops_uv = { .notify_senders_of_disconnect = xpc_notify_senders_of_disconnect_uv, }; +static int +xpc_init_mq_node(int nid) +{ + int cpu; + + get_online_cpus(); + + for_each_cpu(cpu, cpumask_of_node(nid)) { + xpc_activate_mq_uv = + xpc_create_gru_mq_uv(XPC_ACTIVATE_MQ_SIZE_UV, nid, + XPC_ACTIVATE_IRQ_NAME, + xpc_handle_activate_IRQ_uv); + if (!IS_ERR(xpc_activate_mq_uv)) + break; + } + if (IS_ERR(xpc_activate_mq_uv)) { + put_online_cpus(); + return PTR_ERR(xpc_activate_mq_uv); + } + + for_each_cpu(cpu, cpumask_of_node(nid)) { + xpc_notify_mq_uv = + xpc_create_gru_mq_uv(XPC_NOTIFY_MQ_SIZE_UV, nid, + XPC_NOTIFY_IRQ_NAME, + xpc_handle_notify_IRQ_uv); + if (!IS_ERR(xpc_notify_mq_uv)) + break; + } + if (IS_ERR(xpc_notify_mq_uv)) { + xpc_destroy_gru_mq_uv(xpc_activate_mq_uv); + put_online_cpus(); + return PTR_ERR(xpc_notify_mq_uv); + } + + put_online_cpus(); + return 0; +} + int xpc_init_uv(void) { + int nid; + int ret = 0; + xpc_arch_ops = xpc_arch_ops_uv; if (sizeof(struct xpc_notify_mq_msghdr_uv) > XPC_MSG_HDR_MAX_SIZE) { @@ -1742,21 +1785,21 @@ xpc_init_uv(void) return -E2BIG; } - xpc_activate_mq_uv = xpc_create_gru_mq_uv(XPC_ACTIVATE_MQ_SIZE_UV, 0, - XPC_ACTIVATE_IRQ_NAME, - xpc_handle_activate_IRQ_uv); - if (IS_ERR(xpc_activate_mq_uv)) - return PTR_ERR(xpc_activate_mq_uv); + if (xpc_mq_node < 0) + for_each_online_node(nid) { + ret = xpc_init_mq_node(nid); - xpc_notify_mq_uv = xpc_create_gru_mq_uv(XPC_NOTIFY_MQ_SIZE_UV, 0, - XPC_NOTIFY_IRQ_NAME, - xpc_handle_notify_IRQ_uv); - if (IS_ERR(xpc_notify_mq_uv)) { - xpc_destroy_gru_mq_uv(xpc_activate_mq_uv); - return PTR_ERR(xpc_notify_mq_uv); - } + if (!ret) + break; + } + else + ret = xpc_init_mq_node(xpc_mq_node); - return 0; + if (ret < 0) + dev_err(xpc_part, "xpc_init_mq_node() returned error=%d\n", + -ret); + + return ret; } void @@ -1765,3 +1808,6 @@ xpc_exit_uv(void) xpc_destroy_gru_mq_uv(xpc_notify_mq_uv); xpc_destroy_gru_mq_uv(xpc_activate_mq_uv); } + +module_param(xpc_mq_node, int, 0); +MODULE_PARM_DESC(xpc_mq_node, "Node number on which to allocate message queues."); diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c index e3f5af96ab8..b6def202bf4 100644 --- a/drivers/mmc/host/mxs-mmc.c +++ b/drivers/mmc/host/mxs-mmc.c @@ -280,11 +280,11 @@ static irqreturn_t mxs_mmc_irq_handler(int irq, void *dev_id) writel(stat & MXS_MMC_IRQ_BITS, host->base + HW_SSP_CTRL1 + MXS_CLR_ADDR); + spin_unlock(&host->lock); + if ((stat & BM_SSP_CTRL1_SDIO_IRQ) && (stat & BM_SSP_CTRL1_SDIO_IRQ_EN)) mmc_signal_sdio_irq(host->mmc); - spin_unlock(&host->lock); - if (stat & BM_SSP_CTRL1_RESP_TIMEOUT_IRQ) cmd->error = -ETIMEDOUT; else if (stat & BM_SSP_CTRL1_RESP_ERR_IRQ) diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index 71a0c4ea1bc..10253773348 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c @@ -2097,8 +2097,7 @@ static int omap_hsmmc_suspend(struct device *dev) if (ret) { host->suspended = 0; if (host->pdata->resume) { - ret = host->pdata->resume(dev, host->slot_id); - if (ret) + if (host->pdata->resume(dev, host->slot_id)) dev_dbg(dev, "Unmask interrupt failed\n"); } goto err; diff --git a/drivers/mmc/host/sdhci-esdhc.h b/drivers/mmc/host/sdhci-esdhc.h index b97b2f5dafd..d25f9ab9a54 100644 --- a/drivers/mmc/host/sdhci-esdhc.h +++ b/drivers/mmc/host/sdhci-esdhc.h @@ -48,14 +48,14 @@ static inline void esdhc_set_clock(struct sdhci_host *host, unsigned int clock) int div = 1; u32 temp; + if (clock == 0) + goto out; + temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL); temp &= ~(ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN | ESDHC_CLOCK_MASK); sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL); - if (clock == 0) - goto out; - while (host->max_clk / pre_div / 16 > clock && pre_div < 256) pre_div *= 2; diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c index 69ef0beae10..504da715a41 100644 --- a/drivers/mmc/host/sdhci-pci.c +++ b/drivers/mmc/host/sdhci-pci.c @@ -157,6 +157,7 @@ static const struct sdhci_pci_fixes sdhci_ene_714 = { static const struct sdhci_pci_fixes sdhci_cafe = { .quirks = SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER | SDHCI_QUIRK_NO_BUSY_IRQ | + SDHCI_QUIRK_BROKEN_CARD_DETECTION | SDHCI_QUIRK_BROKEN_TIMEOUT_VAL, }; diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c index 55a164fcaa1..9e2c5585efa 100644 --- a/drivers/mmc/host/sdhci-s3c.c +++ b/drivers/mmc/host/sdhci-s3c.c @@ -656,7 +656,7 @@ static int __devexit sdhci_s3c_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); - for (ptr = 0; ptr < 3; ptr++) { + for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) { if (sc->clk_bus[ptr]) { clk_disable(sc->clk_bus[ptr]); clk_put(sc->clk_bus[ptr]); diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 1270e008ff7..783b84df8c7 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -27,6 +27,7 @@ #include #include +#include #include "sdhci.h" @@ -1242,6 +1243,7 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) struct sdhci_host *host; bool present; unsigned long flags; + u32 tuning_opcode; host = mmc_priv(mmc); @@ -1289,12 +1291,19 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) */ if ((host->flags & SDHCI_NEEDS_RETUNING) && !(present_state & (SDHCI_DOING_WRITE | SDHCI_DOING_READ))) { - spin_unlock_irqrestore(&host->lock, flags); - sdhci_execute_tuning(mmc, mrq->cmd->opcode); - spin_lock_irqsave(&host->lock, flags); - - /* Restore original mmc_request structure */ - host->mrq = mrq; + if (mmc->card) { + /* eMMC uses cmd21 but sd and sdio use cmd19 */ + tuning_opcode = + mmc->card->type == MMC_TYPE_MMC ? + MMC_SEND_TUNING_BLOCK_HS200 : + MMC_SEND_TUNING_BLOCK; + spin_unlock_irqrestore(&host->lock, flags); + sdhci_execute_tuning(mmc, tuning_opcode); + spin_lock_irqsave(&host->lock, flags); + + /* Restore original mmc_request structure */ + host->mrq = mrq; + } } if (mrq->sbc && !(host->flags & SDHCI_AUTO_CMD23)) diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index 724b35e85a2..a5786a837a2 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/drivers/mmc/host/sh_mmcif.c @@ -1066,7 +1066,6 @@ static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id) { struct sh_mmcif_host *host = dev_id; struct mmc_request *mrq = host->mrq; - struct mmc_data *data = mrq->data; cancel_delayed_work_sync(&host->timeout_work); @@ -1114,13 +1113,14 @@ static irqreturn_t sh_mmcif_irqt(int irq, void *dev_id) case MMCIF_WAIT_FOR_READ_END: case MMCIF_WAIT_FOR_WRITE_END: if (host->sd_error) - data->error = sh_mmcif_error_manage(host); + mrq->data->error = sh_mmcif_error_manage(host); break; default: BUG(); } if (host->wait_for != MMCIF_WAIT_FOR_STOP) { + struct mmc_data *data = mrq->data; if (!mrq->cmd->error && data && !data->error) data->bytes_xfered = data->blocks * data->blksz; diff --git a/drivers/mtd/devices/slram.c b/drivers/mtd/devices/slram.c index 8f52fc858e4..5a5cd2ace4a 100644 --- a/drivers/mtd/devices/slram.c +++ b/drivers/mtd/devices/slram.c @@ -240,7 +240,7 @@ static int parse_cmdline(char *devname, char *szstart, char *szlength) if (*(szlength) != '+') { devlength = simple_strtoul(szlength, &buffer, 0); - devlength = handle_unit(devlength, buffer) - devstart; + devlength = handle_unit(devlength, buffer); if (devlength < devstart) goto err_out; diff --git a/drivers/mtd/maps/autcpu12-nvram.c b/drivers/mtd/maps/autcpu12-nvram.c index e5bfd0e093b..0598d52eaf9 100644 --- a/drivers/mtd/maps/autcpu12-nvram.c +++ b/drivers/mtd/maps/autcpu12-nvram.c @@ -43,7 +43,8 @@ struct map_info autcpu12_sram_map = { static int __init init_autcpu12_sram (void) { - int err, save0, save1; + map_word tmp, save0, save1; + int err; autcpu12_sram_map.virt = ioremap(0x12000000, SZ_128K); if (!autcpu12_sram_map.virt) { @@ -51,7 +52,7 @@ static int __init init_autcpu12_sram (void) err = -EIO; goto out; } - simple_map_init(&autcpu_sram_map); + simple_map_init(&autcpu12_sram_map); /* * Check for 32K/128K @@ -61,20 +62,22 @@ static int __init init_autcpu12_sram (void) * Read and check result on ofs 0x0 * Restore contents */ - save0 = map_read32(&autcpu12_sram_map,0); - save1 = map_read32(&autcpu12_sram_map,0x10000); - map_write32(&autcpu12_sram_map,~save0,0x10000); + save0 = map_read(&autcpu12_sram_map, 0); + save1 = map_read(&autcpu12_sram_map, 0x10000); + tmp.x[0] = ~save0.x[0]; + map_write(&autcpu12_sram_map, tmp, 0x10000); /* if we find this pattern on 0x0, we have 32K size * restore contents and exit */ - if ( map_read32(&autcpu12_sram_map,0) != save0) { - map_write32(&autcpu12_sram_map,save0,0x0); + tmp = map_read(&autcpu12_sram_map, 0); + if (!map_word_equal(&autcpu12_sram_map, tmp, save0)) { + map_write(&autcpu12_sram_map, save0, 0x0); goto map; } /* We have a 128K found, restore 0x10000 and set size * to 128K */ - map_write32(&autcpu12_sram_map,save1,0x10000); + map_write(&autcpu12_sram_map, save1, 0x10000); autcpu12_sram_map.size = SZ_128K; map: diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c index 0c634ca8c3e..4a818c5b90d 100644 --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c @@ -728,6 +728,8 @@ static const char *default_mtd_part_types[] = { * partition parsers, specified in @types. However, if @types is %NULL, then * the default list of parsers is used. The default list contains only the * "cmdlinepart" and "ofpart" parsers ATM. + * Note: If there are more then one parser in @types, the kernel only takes the + * partitions parsed out by the first parser. * * This function may return: * o a negative error code in case of failure @@ -752,11 +754,12 @@ int parse_mtd_partitions(struct mtd_info *master, const char **types, if (!parser) continue; ret = (*parser->parse_fn)(master, pparts, data); + put_partition_parser(parser); if (ret > 0) { printk(KERN_NOTICE "%d %s partitions found on MTD device %s\n", ret, parser->name, master->name); + break; } - put_partition_parser(parser); } return ret; } diff --git a/drivers/mtd/nand/cs553x_nand.c b/drivers/mtd/nand/cs553x_nand.c index 821c34c6250..0b9b472b52b 100644 --- a/drivers/mtd/nand/cs553x_nand.c +++ b/drivers/mtd/nand/cs553x_nand.c @@ -237,6 +237,7 @@ static int __init cs553x_init_one(int cs, int mmio, unsigned long adr) this->ecc.hwctl = cs_enable_hwecc; this->ecc.calculate = cs_calculate_ecc; this->ecc.correct = nand_correct_data; + this->ecc.strength = 1; /* Enable the following for a flash based bad block table */ this->bbt_options = NAND_BBT_USE_FLASH; @@ -248,8 +249,6 @@ static int __init cs553x_init_one(int cs, int mmio, unsigned long adr) goto out_ior; } - this->ecc.strength = 1; - new_mtd->name = kasprintf(GFP_KERNEL, "cs553x_nand_cs%d", cs); cs553x_mtd[cs] = new_mtd; diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c index e8ea7107932..022feb45c15 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c +++ b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c @@ -135,6 +135,15 @@ int gpmi_init(struct gpmi_nand_data *this) if (ret) goto err_out; + /* + * Reset BCH here, too. We got failures otherwise :( + * See later BCH reset for explanation of MX23 handling + */ + ret = gpmi_reset_block(r->bch_regs, GPMI_IS_MX23(this)); + if (ret) + goto err_out; + + /* Choose NAND mode. */ writel(BM_GPMI_CTRL1_GPMI_MODE, r->gpmi_regs + HW_GPMI_CTRL1_CLR); diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 47b19c0bb07..eb9f5fb02ee 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -2897,9 +2897,7 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip, if (le16_to_cpu(p->features) & 1) *busw = NAND_BUSWIDTH_16; - chip->options &= ~NAND_CHIPOPTIONS_MSK; - chip->options |= (NAND_NO_READRDY | - NAND_NO_AUTOINCR) & NAND_CHIPOPTIONS_MSK; + chip->options |= NAND_NO_READRDY | NAND_NO_AUTOINCR; pr_info("ONFI flash detected\n"); return 1; @@ -3064,9 +3062,8 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, mtd->erasesize <<= ((id_data[3] & 0x03) << 1); } } - /* Get chip options, preserve non chip based options */ - chip->options &= ~NAND_CHIPOPTIONS_MSK; - chip->options |= type->options & NAND_CHIPOPTIONS_MSK; + /* Get chip options */ + chip->options |= type->options; /* * Check if chip is not a Samsung device. Do not clear the diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c index 30d1319ff06..c126469b064 100644 --- a/drivers/mtd/nand/nand_bbt.c +++ b/drivers/mtd/nand/nand_bbt.c @@ -390,7 +390,7 @@ static int read_abs_bbts(struct mtd_info *mtd, uint8_t *buf, /* Read the mirror version, if available */ if (md && (md->options & NAND_BBT_VERSION)) { scan_read_raw(mtd, buf, (loff_t)md->pages[0] << this->page_shift, - mtd->writesize, td); + mtd->writesize, md); md->version[0] = buf[bbt_get_ver_offs(mtd, md)]; pr_info("Bad block table at page %d, version 0x%02X\n", md->pages[0], md->version[0]); diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c index 261f478f8cc..b9cbd65f49b 100644 --- a/drivers/mtd/nand/nandsim.c +++ b/drivers/mtd/nand/nandsim.c @@ -28,7 +28,7 @@ #include #include #include -#include +#include #include #include #include @@ -547,12 +547,6 @@ static char *get_partition_name(int i) return kstrdup(buf, GFP_KERNEL); } -static uint64_t divide(uint64_t n, uint32_t d) -{ - do_div(n, d); - return n; -} - /* * Initialize the nandsim structure. * @@ -581,7 +575,7 @@ static int init_nandsim(struct mtd_info *mtd) ns->geom.oobsz = mtd->oobsize; ns->geom.secsz = mtd->erasesize; ns->geom.pgszoob = ns->geom.pgsz + ns->geom.oobsz; - ns->geom.pgnum = divide(ns->geom.totsz, ns->geom.pgsz); + ns->geom.pgnum = div_u64(ns->geom.totsz, ns->geom.pgsz); ns->geom.totszoob = ns->geom.totsz + (uint64_t)ns->geom.pgnum * ns->geom.oobsz; ns->geom.secshift = ffs(ns->geom.secsz) - 1; ns->geom.pgshift = chip->page_shift; @@ -924,7 +918,7 @@ static int setup_wear_reporting(struct mtd_info *mtd) if (!rptwear) return 0; - wear_eb_count = divide(mtd->size, mtd->erasesize); + wear_eb_count = div_u64(mtd->size, mtd->erasesize); mem = wear_eb_count * sizeof(unsigned long); if (mem / sizeof(unsigned long) != wear_eb_count) { NS_ERR("Too many erase blocks for wear reporting\n"); @@ -2361,6 +2355,7 @@ static int __init ns_init_module(void) uint64_t new_size = (uint64_t)nsmtd->erasesize << overridesize; if (new_size >> overridesize != nsmtd->erasesize) { NS_ERR("overridesize is too big\n"); + retval = -EINVAL; goto err_exit; } /* N.B. This relies on nand_scan not doing anything with the size before we change it */ diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index c2b0bba9d8b..62d039af102 100644 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -1133,7 +1133,8 @@ static int omap_nand_remove(struct platform_device *pdev) /* Release NAND device, its internal structures and partitions */ nand_release(&info->mtd); iounmap(info->nand.IO_ADDR_R); - kfree(&info->mtd); + release_mem_region(info->phys_base, NAND_IO_SIZE); + kfree(info); return 0; } diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c index 64be8f0848b..d9127e2ed80 100644 --- a/drivers/mtd/ofpart.c +++ b/drivers/mtd/ofpart.c @@ -121,7 +121,7 @@ static int parse_ofoldpart_partitions(struct mtd_info *master, nr_parts = plen / sizeof(part[0]); *pparts = kzalloc(nr_parts * sizeof(*(*pparts)), GFP_KERNEL); - if (!pparts) + if (!*pparts) return -ENOMEM; names = of_get_property(dp, "partition-names", &plen); diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index 0fde9fc7d2e..83bab2c7983 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c @@ -816,6 +816,11 @@ static int autoresize(struct ubi_device *ubi, int vol_id) struct ubi_volume *vol = ubi->volumes[vol_id]; int err, old_reserved_pebs = vol->reserved_pebs; + if (ubi->ro_mode) { + ubi_warn("skip auto-resize because of R/O mode"); + return 0; + } + /* * Clear the auto-resize flag in the volume in-memory copy of the * volume table, and 'ubi_resize_volume()' will propagate this change diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c index 17cec0c0154..c015fc0a76d 100644 --- a/drivers/mtd/ubi/vtbl.c +++ b/drivers/mtd/ubi/vtbl.c @@ -346,7 +346,7 @@ static int create_vtbl(struct ubi_device *ubi, struct ubi_scan_info *si, */ err = ubi_scan_add_used(ubi, si, new_seb->pnum, new_seb->ec, vid_hdr, 0); - kfree(new_seb); + kmem_cache_free(si->scan_leb_slab, new_seb); ubi_free_vid_hdr(ubi, vid_hdr); return err; @@ -359,7 +359,7 @@ static int create_vtbl(struct ubi_device *ubi, struct ubi_scan_info *si, list_add(&new_seb->u.list, &si->erase); goto retry; } - kfree(new_seb); + kmem_cache_free(si->scan_leb_slab, new_seb); out_free: ubi_free_vid_hdr(ubi, vid_hdr); return err; diff --git a/drivers/net/bonding/bond_debugfs.c b/drivers/net/bonding/bond_debugfs.c index 3680aa251de..2cf084eb9d5 100644 --- a/drivers/net/bonding/bond_debugfs.c +++ b/drivers/net/bonding/bond_debugfs.c @@ -6,7 +6,7 @@ #include "bonding.h" #include "bond_alb.h" -#ifdef CONFIG_DEBUG_FS +#if defined(CONFIG_DEBUG_FS) && !defined(CONFIG_NET_NS) #include #include diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index a579a2f57c5..6df52c9ba49 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1383,6 +1383,8 @@ static void bond_compute_features(struct bonding *bond) struct net_device *bond_dev = bond->dev; netdev_features_t vlan_features = BOND_VLAN_FEATURES; unsigned short max_hard_header_len = ETH_HLEN; + unsigned int gso_max_size = GSO_MAX_SIZE; + u16 gso_max_segs = GSO_MAX_SEGS; int i; read_lock(&bond->lock); @@ -1396,11 +1398,16 @@ static void bond_compute_features(struct bonding *bond) if (slave->dev->hard_header_len > max_hard_header_len) max_hard_header_len = slave->dev->hard_header_len; + + gso_max_size = min(gso_max_size, slave->dev->gso_max_size); + gso_max_segs = min(gso_max_segs, slave->dev->gso_max_segs); } done: bond_dev->vlan_features = vlan_features; bond_dev->hard_header_len = max_hard_header_len; + bond_dev->gso_max_segs = gso_max_segs; + netif_set_gso_max_size(bond_dev, gso_max_size); read_unlock(&bond->lock); @@ -3218,6 +3225,12 @@ static int bond_master_netdev_event(unsigned long event, switch (event) { case NETDEV_CHANGENAME: return bond_event_changename(event_bond); + case NETDEV_UNREGISTER: + bond_remove_proc_entry(event_bond); + break; + case NETDEV_REGISTER: + bond_create_proc_entry(event_bond); + break; default: break; } @@ -4402,8 +4415,6 @@ static void bond_uninit(struct net_device *bond_dev) bond_work_cancel_all(bond); - bond_remove_proc_entry(bond); - bond_debug_unregister(bond); __hw_addr_flush(&bond->mc_list); @@ -4805,7 +4816,6 @@ static int bond_init(struct net_device *bond_dev) bond_set_lockdep_class(bond_dev); - bond_create_proc_entry(bond); list_add_tail(&bond->bond_list, &bn->dev_list); bond_prepare_sysfs_group(bond); diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index aef42f04532..6734737c953 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -1578,6 +1578,7 @@ static ssize_t bonding_store_slaves_active(struct device *d, goto out; } + read_lock(&bond->lock); bond_for_each_slave(bond, slave, i) { if (!bond_is_active_slave(slave)) { if (new_value) @@ -1586,6 +1587,7 @@ static ssize_t bonding_store_slaves_active(struct device *d, slave->inactive = 1; } } + read_unlock(&bond->lock); out: return ret; } diff --git a/drivers/net/caif/caif_serial.c b/drivers/net/caif/caif_serial.c index 8a3054b8481..5de74e76202 100644 --- a/drivers/net/caif/caif_serial.c +++ b/drivers/net/caif/caif_serial.c @@ -325,6 +325,9 @@ static int ldisc_open(struct tty_struct *tty) sprintf(name, "cf%s", tty->name); dev = alloc_netdev(sizeof(*ser), name, caifdev_setup); + if (!dev) + return -ENOMEM; + ser = netdev_priv(dev); ser->tty = tty_kref_get(tty); ser->dev = dev; diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c index 86cd532c78f..21a3d77ea7e 100644 --- a/drivers/net/can/c_can/c_can.c +++ b/drivers/net/can/c_can/c_can.c @@ -914,7 +914,7 @@ static int c_can_handle_bus_err(struct net_device *dev, break; case LEC_ACK_ERROR: netdev_dbg(dev, "ack error\n"); - cf->data[2] |= (CAN_ERR_PROT_LOC_ACK | + cf->data[3] |= (CAN_ERR_PROT_LOC_ACK | CAN_ERR_PROT_LOC_ACK_DEL); break; case LEC_BIT1_ERROR: @@ -927,7 +927,7 @@ static int c_can_handle_bus_err(struct net_device *dev, break; case LEC_CRC_ERROR: netdev_dbg(dev, "CRC error\n"); - cf->data[2] |= (CAN_ERR_PROT_LOC_CRC_SEQ | + cf->data[3] |= (CAN_ERR_PROT_LOC_CRC_SEQ | CAN_ERR_PROT_LOC_CRC_DEL); break; default: diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c index c5fe3a3db8c..e86f4c37f98 100644 --- a/drivers/net/can/dev.c +++ b/drivers/net/can/dev.c @@ -576,8 +576,7 @@ void close_candev(struct net_device *dev) { struct can_priv *priv = netdev_priv(dev); - if (del_timer_sync(&priv->restart_timer)) - dev_put(dev); + del_timer_sync(&priv->restart_timer); can_flush_echo_skb(dev); } EXPORT_SYMBOL_GPL(close_candev); diff --git a/drivers/net/can/janz-ican3.c b/drivers/net/can/janz-ican3.c index 08c893cb789..e7823dd989f 100644 --- a/drivers/net/can/janz-ican3.c +++ b/drivers/net/can/janz-ican3.c @@ -1250,7 +1250,6 @@ static irqreturn_t ican3_irq(int irq, void *dev_id) */ static int ican3_reset_module(struct ican3_dev *mod) { - u8 val = 1 << mod->num; unsigned long start; u8 runold, runnew; @@ -1264,8 +1263,7 @@ static int ican3_reset_module(struct ican3_dev *mod) runold = ioread8(mod->dpm + TARGET_RUNNING); /* reset the module */ - iowrite8(val, &mod->ctrl->reset_assert); - iowrite8(val, &mod->ctrl->reset_deassert); + iowrite8(0x00, &mod->dpmctrl->hwreset); /* wait until the module has finished resetting and is running */ start = jiffies; diff --git a/drivers/net/can/mcp251x.c b/drivers/net/can/mcp251x.c index 346785c56a2..9d6074273ca 100644 --- a/drivers/net/can/mcp251x.c +++ b/drivers/net/can/mcp251x.c @@ -83,6 +83,11 @@ #define INSTRUCTION_LOAD_TXB(n) (0x40 + 2 * (n)) #define INSTRUCTION_READ_RXB(n) (((n) == 0) ? 0x90 : 0x94) #define INSTRUCTION_RESET 0xC0 +#define RTS_TXB0 0x01 +#define RTS_TXB1 0x02 +#define RTS_TXB2 0x04 +#define INSTRUCTION_RTS(n) (0x80 | ((n) & 0x07)) + /* MPC251x registers */ #define CANSTAT 0x0e @@ -397,6 +402,7 @@ static void mcp251x_hw_tx_frame(struct spi_device *spi, u8 *buf, static void mcp251x_hw_tx(struct spi_device *spi, struct can_frame *frame, int tx_buf_idx) { + struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev); u32 sid, eid, exide, rtr; u8 buf[SPI_TRANSFER_BUF_LEN]; @@ -418,7 +424,10 @@ static void mcp251x_hw_tx(struct spi_device *spi, struct can_frame *frame, buf[TXBDLC_OFF] = (rtr << DLC_RTR_SHIFT) | frame->can_dlc; memcpy(buf + TXBDAT_OFF, frame->data, frame->can_dlc); mcp251x_hw_tx_frame(spi, buf, frame->can_dlc, tx_buf_idx); - mcp251x_write_reg(spi, TXBCTRL(tx_buf_idx), TXBCTRL_TXREQ); + + /* use INSTRUCTION_RTS, to avoid "repeated frame problem" */ + priv->spi_tx_buf[0] = INSTRUCTION_RTS(1 << tx_buf_idx); + mcp251x_spi_trans(priv->spi, 1); } static void mcp251x_hw_rx_frame(struct spi_device *spi, u8 *buf, diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c index 5caa572d71e..957f000263d 100644 --- a/drivers/net/can/mscan/mpc5xxx_can.c +++ b/drivers/net/can/mscan/mpc5xxx_can.c @@ -181,7 +181,7 @@ static u32 __devinit mpc512x_can_get_clock(struct platform_device *ofdev, if (!clock_name || !strcmp(clock_name, "sys")) { sys_clk = clk_get(&ofdev->dev, "sys_clk"); - if (!sys_clk) { + if (IS_ERR(sys_clk)) { dev_err(&ofdev->dev, "couldn't get sys_clk\n"); goto exit_unmap; } @@ -204,7 +204,7 @@ static u32 __devinit mpc512x_can_get_clock(struct platform_device *ofdev, if (clocksrc < 0) { ref_clk = clk_get(&ofdev->dev, "ref_clk"); - if (!ref_clk) { + if (IS_ERR(ref_clk)) { dev_err(&ofdev->dev, "couldn't get ref_clk\n"); goto exit_unmap; } diff --git a/drivers/net/can/pch_can.c b/drivers/net/can/pch_can.c index 2bb215e00eb..ab13a57ae3b 100644 --- a/drivers/net/can/pch_can.c +++ b/drivers/net/can/pch_can.c @@ -560,7 +560,7 @@ static void pch_can_error(struct net_device *ndev, u32 status) stats->rx_errors++; break; case PCH_CRC_ERR: - cf->data[2] |= CAN_ERR_PROT_LOC_CRC_SEQ | + cf->data[3] |= CAN_ERR_PROT_LOC_CRC_SEQ | CAN_ERR_PROT_LOC_CRC_DEL; priv->can.can_stats.bus_error++; stats->rx_errors++; diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c index 4accd7ec695..19000aa8680 100644 --- a/drivers/net/can/ti_hecc.c +++ b/drivers/net/can/ti_hecc.c @@ -746,12 +746,12 @@ static int ti_hecc_error(struct net_device *ndev, int int_status, } if (err_status & HECC_CANES_CRCE) { hecc_set_bit(priv, HECC_CANES, HECC_CANES_CRCE); - cf->data[2] |= CAN_ERR_PROT_LOC_CRC_SEQ | + cf->data[3] |= CAN_ERR_PROT_LOC_CRC_SEQ | CAN_ERR_PROT_LOC_CRC_DEL; } if (err_status & HECC_CANES_ACKE) { hecc_set_bit(priv, HECC_CANES, HECC_CANES_ACKE); - cf->data[2] |= CAN_ERR_PROT_LOC_ACK | + cf->data[3] |= CAN_ERR_PROT_LOC_ACK | CAN_ERR_PROT_LOC_ACK_DEL; } } @@ -984,12 +984,12 @@ static int __devexit ti_hecc_remove(struct platform_device *pdev) struct net_device *ndev = platform_get_drvdata(pdev); struct ti_hecc_priv *priv = netdev_priv(ndev); + unregister_candev(ndev); clk_disable(priv->clk); clk_put(priv->clk); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); iounmap(priv->base); release_mem_region(res->start, resource_size(res)); - unregister_candev(ndev); free_candev(ndev); platform_set_drvdata(pdev, NULL); diff --git a/drivers/net/can/usb/peak_usb/pcan_usb.c b/drivers/net/can/usb/peak_usb/pcan_usb.c index 86f26a1ede4..25723d8ee20 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb.c +++ b/drivers/net/can/usb/peak_usb/pcan_usb.c @@ -519,8 +519,10 @@ static int pcan_usb_decode_error(struct pcan_usb_msg_context *mc, u8 n, mc->pdev->dev.can.state = new_state; if (status_len & PCAN_USB_STATUSLEN_TIMESTAMP) { + struct skb_shared_hwtstamps *hwts = skb_hwtstamps(skb); + peak_usb_get_ts_tv(&mc->pdev->time_ref, mc->ts16, &tv); - skb->tstamp = timeval_to_ktime(tv); + hwts->hwtstamp = timeval_to_ktime(tv); } netif_rx(skb); @@ -605,6 +607,7 @@ static int pcan_usb_decode_data(struct pcan_usb_msg_context *mc, u8 status_len) struct sk_buff *skb; struct can_frame *cf; struct timeval tv; + struct skb_shared_hwtstamps *hwts; skb = alloc_can_skb(mc->netdev, &cf); if (!skb) @@ -652,7 +655,8 @@ static int pcan_usb_decode_data(struct pcan_usb_msg_context *mc, u8 status_len) /* convert timestamp into kernel time */ peak_usb_get_ts_tv(&mc->pdev->time_ref, mc->ts16, &tv); - skb->tstamp = timeval_to_ktime(tv); + hwts = skb_hwtstamps(skb); + hwts->hwtstamp = timeval_to_ktime(tv); /* push the skb */ netif_rx(skb); diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_pro.c b/drivers/net/can/usb/peak_usb/pcan_usb_pro.c index 629c4ba5d49..c95913a0973 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb_pro.c +++ b/drivers/net/can/usb/peak_usb/pcan_usb_pro.c @@ -532,6 +532,7 @@ static int pcan_usb_pro_handle_canmsg(struct pcan_usb_pro_interface *usb_if, struct can_frame *can_frame; struct sk_buff *skb; struct timeval tv; + struct skb_shared_hwtstamps *hwts; skb = alloc_can_skb(netdev, &can_frame); if (!skb) @@ -549,7 +550,8 @@ static int pcan_usb_pro_handle_canmsg(struct pcan_usb_pro_interface *usb_if, memcpy(can_frame->data, rx->data, can_frame->can_dlc); peak_usb_get_ts_tv(&usb_if->time_ref, le32_to_cpu(rx->ts32), &tv); - skb->tstamp = timeval_to_ktime(tv); + hwts = skb_hwtstamps(skb); + hwts->hwtstamp = timeval_to_ktime(tv); netif_rx(skb); netdev->stats.rx_packets++; @@ -570,6 +572,7 @@ static int pcan_usb_pro_handle_error(struct pcan_usb_pro_interface *usb_if, u8 err_mask = 0; struct sk_buff *skb; struct timeval tv; + struct skb_shared_hwtstamps *hwts; /* nothing should be sent while in BUS_OFF state */ if (dev->can.state == CAN_STATE_BUS_OFF) @@ -664,7 +667,8 @@ static int pcan_usb_pro_handle_error(struct pcan_usb_pro_interface *usb_if, dev->can.state = new_state; peak_usb_get_ts_tv(&usb_if->time_ref, le32_to_cpu(er->ts32), &tv); - skb->tstamp = timeval_to_ktime(tv); + hwts = skb_hwtstamps(skb); + hwts->hwtstamp = timeval_to_ktime(tv); netif_rx(skb); netdev->stats.rx_packets++; netdev->stats.rx_bytes += can_frame->can_dlc; diff --git a/drivers/net/ethernet/8390/ne.c b/drivers/net/ethernet/8390/ne.c index d04911d33b6..47618e50535 100644 --- a/drivers/net/ethernet/8390/ne.c +++ b/drivers/net/ethernet/8390/ne.c @@ -813,6 +813,7 @@ static int __init ne_drv_probe(struct platform_device *pdev) dev->irq = irq[this_dev]; dev->mem_end = bad[this_dev]; } + SET_NETDEV_DEV(dev, &pdev->dev); err = do_ne_probe(dev); if (err) { free_netdev(dev); diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c index 1ef0c9275de..65fe6324d81 100644 --- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c +++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c @@ -267,7 +267,6 @@ static void atl1c_check_link_status(struct atl1c_adapter *adapter) dev_warn(&pdev->dev, "stop mac failed\n"); atl1c_set_aspm(hw, false); netif_carrier_off(netdev); - netif_stop_queue(netdev); atl1c_phy_reset(hw); atl1c_phy_init(&adapter->hw); } else { diff --git a/drivers/net/ethernet/broadcom/bnx2.c b/drivers/net/ethernet/broadcom/bnx2.c index 8297e286873..b8ade570759 100644 --- a/drivers/net/ethernet/broadcom/bnx2.c +++ b/drivers/net/ethernet/broadcom/bnx2.c @@ -5372,7 +5372,7 @@ bnx2_free_tx_skbs(struct bnx2 *bp) int k, last; if (skb == NULL) { - j++; + j = NEXT_TX_BD(j); continue; } @@ -5384,8 +5384,8 @@ bnx2_free_tx_skbs(struct bnx2 *bp) tx_buf->skb = NULL; last = tx_buf->nr_frags; - j++; - for (k = 0; k < last; k++, j++) { + j = NEXT_TX_BD(j); + for (k = 0; k < last; k++, j = NEXT_TX_BD(j)) { tx_buf = &txr->tx_buf_ring[TX_RING_IDX(j)]; dma_unmap_page(&bp->pdev->dev, dma_unmap_addr(tx_buf, mapping), diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index 41bb34fcf68..acd82466036 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -571,14 +571,16 @@ static inline void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp, static void bnx2x_csum_validate(struct sk_buff *skb, union eth_rx_cqe *cqe, struct bnx2x_fastpath *fp) { - /* Do nothing if no IP/L4 csum validation was done */ - + /* Do nothing if no L4 csum validation was done. + * We do not check whether IP csum was validated. For IPv4 we assume + * that if the card got as far as validating the L4 csum, it also + * validated the IP csum. IPv6 has no IP csum. + */ if (cqe->fast_path_cqe.status_flags & - (ETH_FAST_PATH_RX_CQE_IP_XSUM_NO_VALIDATION_FLG | - ETH_FAST_PATH_RX_CQE_L4_XSUM_NO_VALIDATION_FLG)) + ETH_FAST_PATH_RX_CQE_L4_XSUM_NO_VALIDATION_FLG) return; - /* If both IP/L4 validation were done, check if an error was found. */ + /* If L4 validation was done, check if an error was found. */ if (cqe->fast_path_cqe.type_error_flags & (ETH_FAST_PATH_RX_CQE_IP_BAD_XSUM_FLG | diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 6af310195ba..b8e7f3e082e 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -9131,10 +9131,13 @@ static int __devinit bnx2x_prev_unload_common(struct bnx2x *bp) */ static void __devinit bnx2x_prev_interrupted_dmae(struct bnx2x *bp) { - u32 val = REG_RD(bp, PGLUE_B_REG_PGLUE_B_INT_STS); - if (val & PGLUE_B_PGLUE_B_INT_STS_REG_WAS_ERROR_ATTN) { - BNX2X_ERR("was error bit was found to be set in pglueb upon startup. Clearing"); - REG_WR(bp, PGLUE_B_REG_WAS_ERROR_PF_7_0_CLR, 1 << BP_FUNC(bp)); + if (!CHIP_IS_E1x(bp)) { + u32 val = REG_RD(bp, PGLUE_B_REG_PGLUE_B_INT_STS); + if (val & PGLUE_B_PGLUE_B_INT_STS_REG_WAS_ERROR_ATTN) { + BNX2X_ERR("was error bit was found to be set in pglueb upon startup. Clearing"); + REG_WR(bp, PGLUE_B_REG_WAS_ERROR_PF_7_0_CLR, + 1 << BP_FUNC(bp)); + } } } diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index 1a1b29ff814..689d2a1935b 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -298,6 +298,7 @@ static DEFINE_PCI_DEVICE_TABLE(tg3_pci_tbl) = { {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57795)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5719)}, {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_5720)}, + {PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, TG3PCI_DEVICE_TIGON3_57762)}, {PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9DXX)}, {PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_9MXX)}, {PCI_DEVICE(PCI_VENDOR_ID_ALTIMA, PCI_DEVICE_ID_ALTIMA_AC1000)}, @@ -8948,8 +8949,7 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780 || tg3_flag(tp, 57765_PLUS)) { val = tr32(TG3_RDMA_RSRVCTRL_REG); - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || - GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5720) { + if (tp->pci_chip_rev_id == CHIPREV_ID_5719_A0) { val &= ~(TG3_RDMA_RSRVCTRL_TXMRGN_MASK | TG3_RDMA_RSRVCTRL_FIFO_LWM_MASK | TG3_RDMA_RSRVCTRL_FIFO_HWM_MASK); @@ -12255,10 +12255,12 @@ static struct rtnl_link_stats64 *tg3_get_stats64(struct net_device *dev, { struct tg3 *tp = netdev_priv(dev); - if (!tp->hw_stats) + spin_lock_bh(&tp->lock); + if (!tp->hw_stats) { + spin_unlock_bh(&tp->lock); return &tp->net_stats_prev; + } - spin_lock_bh(&tp->lock); tg3_get_nstats(tp, stats); spin_unlock_bh(&tp->lock); diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c index e7bed530399..0819a740384 100644 --- a/drivers/net/ethernet/freescale/gianfar.c +++ b/drivers/net/ethernet/freescale/gianfar.c @@ -1037,7 +1037,7 @@ static int gfar_probe(struct platform_device *ofdev) if (priv->device_flags & FSL_GIANFAR_DEV_HAS_VLAN) { dev->hw_features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; - dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; + dev->features |= NETIF_F_HW_VLAN_RX; } if (priv->device_flags & FSL_GIANFAR_DEV_HAS_EXTENDED_HASH) { @@ -2065,10 +2065,9 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; } - /* Steal sock reference for processing TX time stamps */ - swap(skb_new->sk, skb->sk); - swap(skb_new->destructor, skb->destructor); - kfree_skb(skb); + if (skb->sk) + skb_set_owner_w(skb_new, skb->sk); + consume_skb(skb); skb = skb_new; } diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c index 9010cea68bc..b68d28a130e 100644 --- a/drivers/net/ethernet/ibm/ibmveth.c +++ b/drivers/net/ethernet/ibm/ibmveth.c @@ -472,14 +472,9 @@ static void ibmveth_cleanup(struct ibmveth_adapter *adapter) } if (adapter->rx_queue.queue_addr != NULL) { - if (!dma_mapping_error(dev, adapter->rx_queue.queue_dma)) { - dma_unmap_single(dev, - adapter->rx_queue.queue_dma, - adapter->rx_queue.queue_len, - DMA_BIDIRECTIONAL); - adapter->rx_queue.queue_dma = DMA_ERROR_CODE; - } - kfree(adapter->rx_queue.queue_addr); + dma_free_coherent(dev, adapter->rx_queue.queue_len, + adapter->rx_queue.queue_addr, + adapter->rx_queue.queue_dma); adapter->rx_queue.queue_addr = NULL; } @@ -556,10 +551,13 @@ static int ibmveth_open(struct net_device *netdev) goto err_out; } + dev = &adapter->vdev->dev; + adapter->rx_queue.queue_len = sizeof(struct ibmveth_rx_q_entry) * rxq_entries; - adapter->rx_queue.queue_addr = kmalloc(adapter->rx_queue.queue_len, - GFP_KERNEL); + adapter->rx_queue.queue_addr = + dma_alloc_coherent(dev, adapter->rx_queue.queue_len, + &adapter->rx_queue.queue_dma, GFP_KERNEL); if (!adapter->rx_queue.queue_addr) { netdev_err(netdev, "unable to allocate rx queue pages\n"); @@ -567,19 +565,13 @@ static int ibmveth_open(struct net_device *netdev) goto err_out; } - dev = &adapter->vdev->dev; - adapter->buffer_list_dma = dma_map_single(dev, adapter->buffer_list_addr, 4096, DMA_BIDIRECTIONAL); adapter->filter_list_dma = dma_map_single(dev, adapter->filter_list_addr, 4096, DMA_BIDIRECTIONAL); - adapter->rx_queue.queue_dma = dma_map_single(dev, - adapter->rx_queue.queue_addr, - adapter->rx_queue.queue_len, DMA_BIDIRECTIONAL); if ((dma_mapping_error(dev, adapter->buffer_list_dma)) || - (dma_mapping_error(dev, adapter->filter_list_dma)) || - (dma_mapping_error(dev, adapter->rx_queue.queue_dma))) { + (dma_mapping_error(dev, adapter->filter_list_dma))) { netdev_err(netdev, "unable to map filter or buffer list " "pages\n"); rc = -ENOMEM; diff --git a/drivers/net/ethernet/intel/e1000e/82571.c b/drivers/net/ethernet/intel/e1000e/82571.c index c6d95f2031e..c098b2495b7 100644 --- a/drivers/net/ethernet/intel/e1000e/82571.c +++ b/drivers/net/ethernet/intel/e1000e/82571.c @@ -1553,6 +1553,9 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw) ctrl = er32(CTRL); status = er32(STATUS); rxcw = er32(RXCW); + /* SYNCH bit and IV bit are sticky */ + udelay(10); + rxcw = er32(RXCW); if ((rxcw & E1000_RXCW_SYNCH) && !(rxcw & E1000_RXCW_IV)) { @@ -1579,10 +1582,8 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw) * auto-negotiation in the TXCW register and disable * forced link in the Device Control register in an * attempt to auto-negotiate with our link partner. - * If the partner code word is null, stop forcing - * and restart auto negotiation. */ - if ((rxcw & E1000_RXCW_C) || !(rxcw & E1000_RXCW_CW)) { + if (rxcw & E1000_RXCW_C) { /* Enable autoneg, and unforce link up */ ew32(TXCW, mac->txcw); ew32(CTRL, (ctrl & ~E1000_CTRL_SLU)); diff --git a/drivers/net/ethernet/intel/e1000e/e1000.h b/drivers/net/ethernet/intel/e1000e/e1000.h index b83897f76ee..1ab8067b028 100644 --- a/drivers/net/ethernet/intel/e1000e/e1000.h +++ b/drivers/net/ethernet/intel/e1000e/e1000.h @@ -175,13 +175,13 @@ struct e1000_info; /* * in the case of WTHRESH, it appears at least the 82571/2 hardware * writes back 4 descriptors when WTHRESH=5, and 3 descriptors when - * WTHRESH=4, and since we want 64 bytes at a time written back, set - * it to 5 + * WTHRESH=4, so a setting of 5 gives the most efficient bus + * utilization but to avoid possible Tx stalls, set it to 1 */ #define E1000_TXDCTL_DMA_BURST_ENABLE \ (E1000_TXDCTL_GRAN | /* set descriptor granularity */ \ E1000_TXDCTL_COUNT_DESC | \ - (5 << 16) | /* wthresh must be +1 more than desired */\ + (1 << 16) | /* wthresh must be +1 more than desired */\ (1 << 8) | /* hthresh */ \ 0x1f) /* pthresh */ diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index 5621d5b2876..7e88aaff6ec 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@ -2806,7 +2806,7 @@ static void e1000_configure_tx(struct e1000_adapter *adapter) * set up some performance related parameters to encourage the * hardware to use the bus more efficiently in bursts, depends * on the tx_int_delay to be enabled, - * wthresh = 5 ==> burst write a cacheline (64 bytes) at a time + * wthresh = 1 ==> burst write is disabled to avoid Tx stalls * hthresh = 1 ==> prefetch when one or more available * pthresh = 0x1f ==> prefetch if internal cache 31 or less * BEWARE: this seems to work but should be considered first if diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index 8683ca4748c..6b4f0148ee6 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -951,17 +951,18 @@ static int igb_request_msix(struct igb_adapter *adapter) { struct net_device *netdev = adapter->netdev; struct e1000_hw *hw = &adapter->hw; - int i, err = 0, vector = 0; + int i, err = 0, vector = 0, free_vector = 0; err = request_irq(adapter->msix_entries[vector].vector, igb_msix_other, 0, netdev->name, adapter); if (err) - goto out; - vector++; + goto err_out; for (i = 0; i < adapter->num_q_vectors; i++) { struct igb_q_vector *q_vector = adapter->q_vector[i]; + vector++; + q_vector->itr_register = hw->hw_addr + E1000_EITR(vector); if (q_vector->rx.ring && q_vector->tx.ring) @@ -980,13 +981,22 @@ static int igb_request_msix(struct igb_adapter *adapter) igb_msix_ring, 0, q_vector->name, q_vector); if (err) - goto out; - vector++; + goto err_free; } igb_configure_msix(adapter); return 0; -out: + +err_free: + /* free already assigned IRQs */ + free_irq(adapter->msix_entries[free_vector++].vector, adapter); + + vector--; + for (i = 0; i < vector; i++) { + free_irq(adapter->msix_entries[free_vector++].vector, + adapter->q_vector[i]); + } +err_out: return err; } diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c index 49aa41fe7b8..ab4d4d219e3 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c @@ -3216,6 +3216,7 @@ static s32 ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw) switch (hw->device_id) { case IXGBE_DEV_ID_X540T: + case IXGBE_DEV_ID_X540T1: return 0; case IXGBE_DEV_ID_82599_T3_LOM: return 0; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c index cfe7d269590..6757d6c30fe 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c @@ -2006,6 +2006,7 @@ static int ixgbe_wol_exclusion(struct ixgbe_adapter *adapter, retval = 0; break; case IXGBE_DEV_ID_X540T: + case IXGBE_DEV_ID_X540T1: /* check eeprom to see if enabled wol */ if ((wol_cap == IXGBE_DEVICE_CAPS_WOL_PORT0_1) || ((wol_cap == IXGBE_DEVICE_CAPS_WOL_PORT0) && diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index a66c2159b1f..6d1f6c51262 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -114,6 +114,7 @@ static DEFINE_PCI_DEVICE_TABLE(ixgbe_pci_tbl) = { {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_LS), board_82599 }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599EN_SFP), board_82599 }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_SFP_SF_QP), board_82599 }, + {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X540T1), board_X540 }, /* required last entry */ {0, } }; @@ -7060,6 +7061,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, adapter->wol = IXGBE_WUFC_MAG; break; case IXGBE_DEV_ID_X540T: + case IXGBE_DEV_ID_X540T1: /* Check eeprom to see if it is enabled */ hw->eeprom.ops.read(hw, 0x2c, &adapter->eeprom_cap); wol_cap = adapter->eeprom_cap & IXGBE_DEVICE_CAPS_WOL_MASK; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h index 8636e8344fc..37eb39c013a 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h @@ -67,6 +67,7 @@ #define IXGBE_DEV_ID_82599_LS 0x154F #define IXGBE_DEV_ID_X540T 0x1528 #define IXGBE_DEV_ID_82599_SFP_SF_QP 0x154A +#define IXGBE_DEV_ID_X540T1 0x1560 /* VF Device IDs */ #define IXGBE_DEV_ID_82599_VF 0x10ED diff --git a/drivers/net/ethernet/marvell/skge.c b/drivers/net/ethernet/marvell/skge.c index 5a30bf82309..f4be8f7c286 100644 --- a/drivers/net/ethernet/marvell/skge.c +++ b/drivers/net/ethernet/marvell/skge.c @@ -4153,6 +4153,13 @@ static struct dmi_system_id skge_32bit_dma_boards[] = { DMI_MATCH(DMI_BOARD_NAME, "nForce"), }, }, + { + .ident = "ASUS P5NSLI", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), + DMI_MATCH(DMI_BOARD_NAME, "P5NSLI") + }, + }, {} }; diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c index 589753fb673..2b78ddd5d63 100644 --- a/drivers/net/ethernet/marvell/sky2.c +++ b/drivers/net/ethernet/marvell/sky2.c @@ -3079,8 +3079,10 @@ static irqreturn_t sky2_intr(int irq, void *dev_id) /* Reading this mask interrupts as side effect */ status = sky2_read32(hw, B0_Y2_SP_ISRC2); - if (status == 0 || status == ~0) + if (status == 0 || status == ~0) { + sky2_write32(hw, B0_Y2_SP_ICR, 2); return IRQ_NONE; + } prefetch(&hw->st_le[hw->st_idx]); diff --git a/drivers/net/ethernet/nxp/lpc_eth.c b/drivers/net/ethernet/nxp/lpc_eth.c index 0c5edc17a1e..077bb00cbac 100644 --- a/drivers/net/ethernet/nxp/lpc_eth.c +++ b/drivers/net/ethernet/nxp/lpc_eth.c @@ -1523,6 +1523,7 @@ static int lpc_eth_drv_remove(struct platform_device *pdev) pldat->dma_buff_base_p); free_irq(ndev->irq, ndev); iounmap(pldat->net_base); + mdiobus_unregister(pldat->mii_bus); mdiobus_free(pldat->mii_bus); clk_disable(pldat->clk); clk_put(pldat->clk); diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c index 65a718f9ccd..22b399a9db9 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c @@ -1370,6 +1370,10 @@ static void netxen_mask_aer_correctable(struct netxen_adapter *adapter) struct pci_dev *root = pdev->bus->self; u32 aer_pos; + /* root bus? */ + if (!root) + return; + if (adapter->ahw.board_type != NETXEN_BRDTYPE_P3_4_GB_MM && adapter->ahw.board_type != NETXEN_BRDTYPE_P3_10G_TP) return; diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index 161e0451747..06ee243d41a 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -73,7 +73,7 @@ static const int multicast_filter_limit = 32; #define MAX_READ_REQUEST_SHIFT 12 -#define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ +#define TX_DMA_BURST 7 /* Maximum PCI burst, '7' is unlimited */ #define SafeMtu 0x1c20 /* ... actually life sucks beyond ~7k */ #define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ @@ -319,6 +319,8 @@ enum rtl_registers { Config0 = 0x51, Config1 = 0x52, Config2 = 0x53, +#define PME_SIGNAL (1 << 5) /* 8168c and later */ + Config3 = 0x54, Config4 = 0x55, Config5 = 0x56, @@ -1400,7 +1402,6 @@ static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts) u16 reg; u8 mask; } cfg[] = { - { WAKE_ANY, Config1, PMEnable }, { WAKE_PHY, Config3, LinkUp }, { WAKE_MAGIC, Config3, MagicPacket }, { WAKE_UCAST, Config5, UWF }, @@ -1408,16 +1409,32 @@ static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts) { WAKE_MCAST, Config5, MWF }, { WAKE_ANY, Config5, LanWake } }; + u8 options; RTL_W8(Cfg9346, Cfg9346_Unlock); for (i = 0; i < ARRAY_SIZE(cfg); i++) { - u8 options = RTL_R8(cfg[i].reg) & ~cfg[i].mask; + options = RTL_R8(cfg[i].reg) & ~cfg[i].mask; if (wolopts & cfg[i].opt) options |= cfg[i].mask; RTL_W8(cfg[i].reg, options); } + switch (tp->mac_version) { + case RTL_GIGA_MAC_VER_01 ... RTL_GIGA_MAC_VER_17: + options = RTL_R8(Config1) & ~PMEnable; + if (wolopts) + options |= PMEnable; + RTL_W8(Config1, options); + break; + default: + options = RTL_R8(Config2) & ~PME_SIGNAL; + if (wolopts) + options |= PME_SIGNAL; + RTL_W8(Config2, options); + break; + } + RTL_W8(Cfg9346, Cfg9346_Lock); } @@ -3471,6 +3488,8 @@ static void rtl_wol_suspend_quirk(struct rtl8169_private *tp) void __iomem *ioaddr = tp->mmio_addr; switch (tp->mac_version) { + case RTL_GIGA_MAC_VER_25: + case RTL_GIGA_MAC_VER_26: case RTL_GIGA_MAC_VER_29: case RTL_GIGA_MAC_VER_30: case RTL_GIGA_MAC_VER_32: @@ -3737,6 +3756,7 @@ static void rtl_init_rxcfg(struct rtl8169_private *tp) case RTL_GIGA_MAC_VER_22: case RTL_GIGA_MAC_VER_23: case RTL_GIGA_MAC_VER_24: + case RTL_GIGA_MAC_VER_34: RTL_W32(RxConfig, RX128_INT_EN | RX_MULTI_EN | RX_DMA_BURST); break; default: @@ -4111,6 +4131,9 @@ static void rtl_set_rx_mode(struct net_device *dev) mc_filter[1] = swab32(data); } + if (tp->mac_version == RTL_GIGA_MAC_VER_35) + mc_filter[1] = mc_filter[0] = 0xffffffff; + RTL_W32(MAR0 + 4, mc_filter[1]); RTL_W32(MAR0 + 0, mc_filter[0]); @@ -5000,7 +5023,6 @@ static void rtl8169_tx_clear(struct rtl8169_private *tp) { rtl8169_tx_clear_range(tp, tp->dirty_tx, NUM_TX_DESC); tp->cur_tx = tp->dirty_tx = 0; - netdev_reset_queue(tp->dev); } static void rtl_reset_work(struct rtl8169_private *tp) @@ -5155,8 +5177,6 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, txd->opts2 = cpu_to_le32(opts[1]); - netdev_sent_queue(dev, skb->len); - skb_tx_timestamp(skb); wmb(); @@ -5253,16 +5273,9 @@ static void rtl8169_pcierr_interrupt(struct net_device *dev) rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING); } -struct rtl_txc { - int packets; - int bytes; -}; - static void rtl_tx(struct net_device *dev, struct rtl8169_private *tp) { - struct rtl8169_stats *tx_stats = &tp->tx_stats; unsigned int dirty_tx, tx_left; - struct rtl_txc txc = { 0, 0 }; dirty_tx = tp->dirty_tx; smp_rmb(); @@ -5281,24 +5294,17 @@ static void rtl_tx(struct net_device *dev, struct rtl8169_private *tp) rtl8169_unmap_tx_skb(&tp->pci_dev->dev, tx_skb, tp->TxDescArray + entry); if (status & LastFrag) { - struct sk_buff *skb = tx_skb->skb; - - txc.packets++; - txc.bytes += skb->len; - dev_kfree_skb(skb); + u64_stats_update_begin(&tp->tx_stats.syncp); + 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); tx_skb->skb = NULL; } dirty_tx++; tx_left--; } - u64_stats_update_begin(&tx_stats->syncp); - tx_stats->packets += txc.packets; - tx_stats->bytes += txc.bytes; - u64_stats_update_end(&tx_stats->syncp); - - netdev_completed_queue(dev, txc.packets, txc.bytes); - if (tp->dirty_tx != dirty_tx) { tp->dirty_tx = dirty_tx; /* Sync with rtl8169_start_xmit: @@ -5510,11 +5516,7 @@ static void rtl_slow_event_work(struct rtl8169_private *tp) if (status & LinkChg) __rtl8169_check_link_status(dev, tp, tp->mmio_addr, true); - napi_disable(&tp->napi); - rtl_irq_disable(tp); - - napi_enable(&tp->napi); - napi_schedule(&tp->napi); + rtl_irq_enable_all(tp); } static void rtl_task(struct work_struct *work) diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index 4a0005342e6..954b8854b25 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -1498,6 +1498,11 @@ static int efx_probe_all(struct efx_nic *efx) goto fail2; } + BUILD_BUG_ON(EFX_DEFAULT_DMAQ_SIZE < EFX_RXQ_MIN_ENT); + if (WARN_ON(EFX_DEFAULT_DMAQ_SIZE < EFX_TXQ_MIN_ENT(efx))) { + rc = -EINVAL; + goto fail3; + } efx->rxq_entries = efx->txq_entries = EFX_DEFAULT_DMAQ_SIZE; rc = efx_probe_filters(efx); @@ -2065,6 +2070,7 @@ static int efx_register_netdev(struct efx_nic *efx) net_dev->irq = efx->pci_dev->irq; net_dev->netdev_ops = &efx_netdev_ops; SET_ETHTOOL_OPS(net_dev, &efx_ethtool_ops); + net_dev->gso_max_segs = EFX_TSO_MAX_SEGS; rtnl_lock(); diff --git a/drivers/net/ethernet/sfc/efx.h b/drivers/net/ethernet/sfc/efx.h index be8f9158a71..70755c97251 100644 --- a/drivers/net/ethernet/sfc/efx.h +++ b/drivers/net/ethernet/sfc/efx.h @@ -30,6 +30,7 @@ extern netdev_tx_t efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb); extern void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index); extern int efx_setup_tc(struct net_device *net_dev, u8 num_tc); +extern unsigned int efx_tx_max_skb_descs(struct efx_nic *efx); /* RX */ extern int efx_probe_rx_queue(struct efx_rx_queue *rx_queue); @@ -52,10 +53,15 @@ extern void efx_schedule_slow_fill(struct efx_rx_queue *rx_queue); #define EFX_MAX_EVQ_SIZE 16384UL #define EFX_MIN_EVQ_SIZE 512UL -/* The smallest [rt]xq_entries that the driver supports. Callers of - * efx_wake_queue() assume that they can subsequently send at least one - * skb. Falcon/A1 may require up to three descriptors per skb_frag. */ -#define EFX_MIN_RING_SIZE (roundup_pow_of_two(2 * 3 * MAX_SKB_FRAGS)) +/* Maximum number of TCP segments we support for soft-TSO */ +#define EFX_TSO_MAX_SEGS 100 + +/* The smallest [rt]xq_entries that the driver supports. RX minimum + * is a bit arbitrary. For TX, we must have space for at least 2 + * TSO skbs. + */ +#define EFX_RXQ_MIN_ENT 128U +#define EFX_TXQ_MIN_ENT(efx) (2 * efx_tx_max_skb_descs(efx)) /* Filters */ extern int efx_probe_filters(struct efx_nic *efx); diff --git a/drivers/net/ethernet/sfc/ethtool.c b/drivers/net/ethernet/sfc/ethtool.c index f22f45f515a..ff64def0ffd 100644 --- a/drivers/net/ethernet/sfc/ethtool.c +++ b/drivers/net/ethernet/sfc/ethtool.c @@ -680,21 +680,27 @@ static int efx_ethtool_set_ringparam(struct net_device *net_dev, struct ethtool_ringparam *ring) { struct efx_nic *efx = netdev_priv(net_dev); + u32 txq_entries; if (ring->rx_mini_pending || ring->rx_jumbo_pending || ring->rx_pending > EFX_MAX_DMAQ_SIZE || ring->tx_pending > EFX_MAX_DMAQ_SIZE) return -EINVAL; - if (ring->rx_pending < EFX_MIN_RING_SIZE || - ring->tx_pending < EFX_MIN_RING_SIZE) { + if (ring->rx_pending < EFX_RXQ_MIN_ENT) { netif_err(efx, drv, efx->net_dev, - "TX and RX queues cannot be smaller than %ld\n", - EFX_MIN_RING_SIZE); + "RX queues cannot be smaller than %u\n", + EFX_RXQ_MIN_ENT); return -EINVAL; } - return efx_realloc_channels(efx, ring->rx_pending, ring->tx_pending); + txq_entries = max(ring->tx_pending, EFX_TXQ_MIN_ENT(efx)); + if (txq_entries != ring->tx_pending) + netif_warn(efx, drv, efx->net_dev, + "increasing TX queue size to minimum of %u\n", + txq_entries); + + return efx_realloc_channels(efx, ring->rx_pending, txq_entries); } static int efx_ethtool_set_pauseparam(struct net_device *net_dev, @@ -857,8 +863,8 @@ static int efx_ethtool_get_class_rule(struct efx_nic *efx, &ip_entry->ip4dst, &ip_entry->pdst); if (rc != 0) { rc = efx_filter_get_ipv4_full( - &spec, &proto, &ip_entry->ip4src, &ip_entry->psrc, - &ip_entry->ip4dst, &ip_entry->pdst); + &spec, &proto, &ip_entry->ip4dst, &ip_entry->pdst, + &ip_entry->ip4src, &ip_entry->psrc); EFX_WARN_ON_PARANOID(rc); ip_mask->ip4src = ~0; ip_mask->psrc = ~0; diff --git a/drivers/net/ethernet/sfc/tx.c b/drivers/net/ethernet/sfc/tx.c index 94d0365b31c..305430da48f 100644 --- a/drivers/net/ethernet/sfc/tx.c +++ b/drivers/net/ethernet/sfc/tx.c @@ -119,6 +119,25 @@ efx_max_tx_len(struct efx_nic *efx, dma_addr_t dma_addr) return len; } +unsigned int efx_tx_max_skb_descs(struct efx_nic *efx) +{ + /* Header and payload descriptor for each output segment, plus + * one for every input fragment boundary within a segment + */ + unsigned int max_descs = EFX_TSO_MAX_SEGS * 2 + MAX_SKB_FRAGS; + + /* Possibly one more per segment for the alignment workaround */ + if (EFX_WORKAROUND_5391(efx)) + max_descs += EFX_TSO_MAX_SEGS; + + /* Possibly more for PCIe page boundaries within input fragments */ + if (PAGE_SIZE > EFX_PAGE_SIZE) + max_descs += max_t(unsigned int, MAX_SKB_FRAGS, + DIV_ROUND_UP(GSO_MAX_SIZE, EFX_PAGE_SIZE)); + + return max_descs; +} + /* * Add a socket buffer to a TX queue * diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 48d56da62f0..9bdfaba4e30 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1158,6 +1158,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) priv->hw->desc->prepare_tx_desc(desc, 0, len, csum_insertion); wmb(); priv->hw->desc->set_tx_owner(desc); + wmb(); } /* Interrupt on completition only for the latest segment */ @@ -1173,6 +1174,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev) /* To avoid raise condition */ priv->hw->desc->set_tx_owner(first); + wmb(); priv->cur_tx++; @@ -1236,6 +1238,7 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv) } wmb(); priv->hw->desc->set_rx_owner(p + entry); + wmb(); } } diff --git a/drivers/net/ethernet/ti/davinci_cpdma.c b/drivers/net/ethernet/ti/davinci_cpdma.c index 34558766cbf..06f2b495428 100644 --- a/drivers/net/ethernet/ti/davinci_cpdma.c +++ b/drivers/net/ethernet/ti/davinci_cpdma.c @@ -851,6 +851,7 @@ int cpdma_chan_stop(struct cpdma_chan *chan) next_dma = desc_read(desc, hw_next); chan->head = desc_from_phys(pool, next_dma); + chan->count--; chan->stats.teardown_dequeue++; /* issue callback without locks held */ diff --git a/drivers/net/irda/sir_dev.c b/drivers/net/irda/sir_dev.c index 5039f08f5a5..43e9ab4f4d7 100644 --- a/drivers/net/irda/sir_dev.c +++ b/drivers/net/irda/sir_dev.c @@ -222,7 +222,7 @@ static void sirdev_config_fsm(struct work_struct *work) break; case SIRDEV_STATE_DONGLE_SPEED: - if (dev->dongle_drv->reset) { + if (dev->dongle_drv->set_speed) { ret = dev->dongle_drv->set_speed(dev, fsm->param); if (ret < 0) { fsm->result = ret; diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index c1d602d5f15..b99c418d6b2 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -506,10 +506,11 @@ static int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from, if (copy > size) { ++from; --count; - } + offset = 0; + } else + offset += size; copy -= size; offset1 += size; - offset = 0; } if (len == offset1) @@ -519,25 +520,28 @@ static int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from, struct page *page[MAX_SKB_FRAGS]; int num_pages; unsigned long base; + unsigned long truesize; - len = from->iov_len - offset1; + len = from->iov_len - offset; if (!len) { - offset1 = 0; + offset = 0; ++from; continue; } - base = (unsigned long)from->iov_base + offset1; + base = (unsigned long)from->iov_base + offset; size = ((base & ~PAGE_MASK) + len + ~PAGE_MASK) >> PAGE_SHIFT; if (i + size > MAX_SKB_FRAGS) return -EMSGSIZE; num_pages = get_user_pages_fast(base, size, 0, &page[i]); - if (num_pages != size) - /* put_page is in skb free */ - return -EFAULT; + if (num_pages != size) { + for (i = 0; i < num_pages; i++) + put_page(page[i]); + } + truesize = size * PAGE_SIZE; skb->data_len += len; skb->len += len; - skb->truesize += len; - atomic_add(len, &skb->sk->sk_wmem_alloc); + skb->truesize += truesize; + atomic_add(truesize, &skb->sk->sk_wmem_alloc); while (len) { int off = base & ~PAGE_MASK; int size = min_t(int, len, PAGE_SIZE - off); @@ -548,7 +552,7 @@ static int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from, len -= size; i++; } - offset1 = 0; + offset = 0; ++from; } return 0; @@ -712,10 +716,9 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, if (!skb) goto err; - if (zerocopy) { + if (zerocopy) err = zerocopy_sg_from_iovec(skb, iv, vnet_hdr_len, count); - skb_shinfo(skb)->tx_flags |= SKBTX_DEV_ZEROCOPY; - } else + else err = skb_copy_datagram_from_iovec(skb, 0, iv, vnet_hdr_len, len); if (err) @@ -734,8 +737,10 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, rcu_read_lock_bh(); vlan = rcu_dereference_bh(q->vlan); /* copy skb_ubuf_info for callback when skb has no error */ - if (zerocopy) + if (zerocopy) { skb_shinfo(skb)->destructor_arg = m->msg_control; + skb_shinfo(skb)->tx_flags |= SKBTX_DEV_ZEROCOPY; + } if (vlan) macvlan_start_xmit(skb, vlan->dev); else diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c index f9347ea3d38..63ffbdfe36c 100644 --- a/drivers/net/netconsole.c +++ b/drivers/net/netconsole.c @@ -648,7 +648,6 @@ static int netconsole_netdev_event(struct notifier_block *this, flags); dev_put(nt->np.dev); nt->np.dev = NULL; - netconsole_target_put(nt); } nt->enabled = 0; stopped = true; diff --git a/drivers/net/ppp/pppoe.c b/drivers/net/ppp/pppoe.c index 2fa1a9b6f49..2e0d8762bb5 100644 --- a/drivers/net/ppp/pppoe.c +++ b/drivers/net/ppp/pppoe.c @@ -576,7 +576,7 @@ static int pppoe_release(struct socket *sock) po = pppox_sk(sk); - if (sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND)) { + if (sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND | PPPOX_ZOMBIE)) { dev_put(po->pppoe_dev); po->pppoe_dev = NULL; } diff --git a/drivers/net/ppp/pptp.c b/drivers/net/ppp/pptp.c index 885dbdd9c39..f617566bbba 100644 --- a/drivers/net/ppp/pptp.c +++ b/drivers/net/ppp/pptp.c @@ -189,7 +189,7 @@ static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb) if (sk_pppox(po)->sk_state & PPPOX_DEAD) goto tx_error; - rt = ip_route_output_ports(&init_net, &fl4, NULL, + rt = ip_route_output_ports(sock_net(sk), &fl4, NULL, opt->dst_addr.sin_addr.s_addr, opt->src_addr.sin_addr.s_addr, 0, 0, IPPROTO_GRE, @@ -468,7 +468,7 @@ static int pptp_connect(struct socket *sock, struct sockaddr *uservaddr, po->chan.private = sk; po->chan.ops = &pptp_chan_ops; - rt = ip_route_output_ports(&init_net, &fl4, sk, + rt = ip_route_output_ports(sock_net(sk), &fl4, sk, opt->dst_addr.sin_addr.s_addr, opt->src_addr.sin_addr.s_addr, 0, 0, diff --git a/drivers/net/rionet.c b/drivers/net/rionet.c index 91d25888a1b..1470d3e86e3 100644 --- a/drivers/net/rionet.c +++ b/drivers/net/rionet.c @@ -79,6 +79,7 @@ static int rionet_capable = 1; * on system trade-offs. */ static struct rio_dev **rionet_active; +static int nact; /* total number of active rionet peers */ #define is_rionet_capable(src_ops, dst_ops) \ ((src_ops & RIO_SRC_OPS_DATA_MSG) && \ @@ -175,6 +176,7 @@ static int rionet_start_xmit(struct sk_buff *skb, struct net_device *ndev) struct ethhdr *eth = (struct ethhdr *)skb->data; u16 destid; unsigned long flags; + int add_num = 1; local_irq_save(flags); if (!spin_trylock(&rnet->tx_lock)) { @@ -182,7 +184,10 @@ static int rionet_start_xmit(struct sk_buff *skb, struct net_device *ndev) return NETDEV_TX_LOCKED; } - if ((rnet->tx_cnt + 1) > RIONET_TX_RING_SIZE) { + if (is_multicast_ether_addr(eth->h_dest)) + add_num = nact; + + if ((rnet->tx_cnt + add_num) > RIONET_TX_RING_SIZE) { netif_stop_queue(ndev); spin_unlock_irqrestore(&rnet->tx_lock, flags); printk(KERN_ERR "%s: BUG! Tx Ring full when queue awake!\n", @@ -191,11 +196,16 @@ static int rionet_start_xmit(struct sk_buff *skb, struct net_device *ndev) } if (is_multicast_ether_addr(eth->h_dest)) { + int count = 0; for (i = 0; i < RIO_MAX_ROUTE_ENTRIES(rnet->mport->sys_size); i++) - if (rionet_active[i]) + if (rionet_active[i]) { rionet_queue_tx_msg(skb, ndev, rionet_active[i]); + if (count) + atomic_inc(&skb->users); + count++; + } } else if (RIONET_MAC_MATCH(eth->h_dest)) { destid = RIONET_GET_DESTID(eth->h_dest); if (rionet_active[destid]) @@ -220,14 +230,17 @@ static void rionet_dbell_event(struct rio_mport *mport, void *dev_id, u16 sid, u if (info == RIONET_DOORBELL_JOIN) { if (!rionet_active[sid]) { list_for_each_entry(peer, &rionet_peers, node) { - if (peer->rdev->destid == sid) + if (peer->rdev->destid == sid) { rionet_active[sid] = peer->rdev; + nact++; + } } rio_mport_send_doorbell(mport, sid, RIONET_DOORBELL_JOIN); } } else if (info == RIONET_DOORBELL_LEAVE) { rionet_active[sid] = NULL; + nact--; } else { if (netif_msg_intr(rnet)) printk(KERN_WARNING "%s: unhandled doorbell\n", @@ -523,6 +536,7 @@ static int rionet_probe(struct rio_dev *rdev, const struct rio_device_id *id) rc = rionet_setup_netdev(rdev->net->hport, ndev); rionet_check = 1; + nact = 0; } /* diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 2391dae6c05..279d860ee90 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -185,7 +185,6 @@ static void __tun_detach(struct tun_struct *tun) netif_tx_lock_bh(tun->dev); netif_carrier_off(tun->dev); tun->tfile = NULL; - tun->socket.file = NULL; netif_tx_unlock_bh(tun->dev); /* Drop read queue */ @@ -358,6 +357,8 @@ static void tun_free_netdev(struct net_device *dev) { struct tun_struct *tun = netdev_priv(dev); + BUG_ON(!test_bit(SOCK_EXTERNALLY_ALLOCATED, &tun->socket.flags)); + sk_release_kernel(tun->socket.sk); } @@ -1115,6 +1116,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) tun->flags = flags; tun->txflt.count = 0; tun->vnet_hdr_sz = sizeof(struct virtio_net_hdr); + set_bit(SOCK_EXTERNALLY_ALLOCATED, &tun->socket.flags); err = -ENOMEM; sk = sk_alloc(&init_net, AF_UNSPEC, GFP_KERNEL, &tun_proto); @@ -1258,10 +1260,12 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, } #endif - if (cmd == TUNSETIFF || _IOC_TYPE(cmd) == 0x89) + if (cmd == TUNSETIFF || _IOC_TYPE(cmd) == 0x89) { if (copy_from_user(&ifr, argp, ifreq_len)) return -EFAULT; - + } else { + memset(&ifr, 0, sizeof(ifr)); + } if (cmd == TUNGETFEATURES) { /* Currently this just means: "what IFF flags are valid?". * This is needed because we never checked for invalid flags on diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c index 609fcc33159..ef84a586c17 100644 --- a/drivers/net/usb/asix.c +++ b/drivers/net/usb/asix.c @@ -1603,6 +1603,10 @@ static const struct usb_device_id products [] = { // DLink DUB-E100 H/W Ver B1 Alternate USB_DEVICE (0x2001, 0x3c05), .driver_info = (unsigned long) &ax88772_info, +}, { + // DLink DUB-E100 H/W Ver C1 + USB_DEVICE (0x2001, 0x1a02), + .driver_info = (unsigned long) &ax88772_info, }, { // Linksys USB1000 USB_DEVICE (0x1737, 0x0039), diff --git a/drivers/net/usb/ipheth.c b/drivers/net/usb/ipheth.c index 5cba41517f7..32e47918e59 100644 --- a/drivers/net/usb/ipheth.c +++ b/drivers/net/usb/ipheth.c @@ -62,6 +62,7 @@ #define USB_PRODUCT_IPAD 0x129a #define USB_PRODUCT_IPHONE_4_VZW 0x129c #define USB_PRODUCT_IPHONE_4S 0x12a0 +#define USB_PRODUCT_IPHONE_5 0x12a8 #define IPHETH_USBINTF_CLASS 255 #define IPHETH_USBINTF_SUBCLASS 253 @@ -113,6 +114,10 @@ static struct usb_device_id ipheth_table[] = { USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_4S, IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, IPHETH_USBINTF_PROTO) }, + { USB_DEVICE_AND_INTERFACE_INFO( + USB_VENDOR_APPLE, USB_PRODUCT_IPHONE_5, + IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, + IPHETH_USBINTF_PROTO) }, { } }; MODULE_DEVICE_TABLE(usb, ipheth_table); diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c index df2a2cf35a9..7a6ccd6c3b4 100644 --- a/drivers/net/usb/kaweth.c +++ b/drivers/net/usb/kaweth.c @@ -1302,7 +1302,7 @@ static int kaweth_internal_control_msg(struct usb_device *usb_dev, int retv; int length = 0; /* shut up GCC */ - urb = usb_alloc_urb(0, GFP_NOIO); + urb = usb_alloc_urb(0, GFP_ATOMIC); if (!urb) return -ENOMEM; diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index c2ae4266617..8669c77fa7c 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -346,6 +346,15 @@ static const struct driver_info qmi_wwan_force_int1 = { .data = BIT(1), /* interface whitelist bitmap */ }; +static const struct driver_info qmi_wwan_force_int2 = { + .description = "Qualcomm WWAN/QMI device", + .flags = FLAG_WWAN, + .bind = qmi_wwan_bind_shared, + .unbind = qmi_wwan_unbind_shared, + .manage_power = qmi_wwan_manage_power, + .data = BIT(2), /* interface whitelist bitmap */ +}; + static const struct driver_info qmi_wwan_force_int3 = { .description = "Qualcomm WWAN/QMI device", .flags = FLAG_WWAN, @@ -407,6 +416,14 @@ static const struct usb_device_id products[] = { .bInterfaceProtocol = 8, /* NOTE: This is the *slave* interface of the CDC Union! */ .driver_info = (unsigned long)&qmi_wwan_info, }, + { /* Vodafone/Huawei K5005 (12d1:14c8) and similar modems */ + .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = HUAWEI_VENDOR_ID, + .bInterfaceClass = USB_CLASS_VENDOR_SPEC, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 56, /* NOTE: This is the *slave* interface of the CDC Union! */ + .driver_info = (unsigned long)&qmi_wwan_info, + }, { /* Huawei E392, E398 and possibly others in "Windows mode" * using a combined control and data interface without any CDC * functional descriptors @@ -427,6 +444,15 @@ static const struct usb_device_id products[] = { .bInterfaceProtocol = 0xff, .driver_info = (unsigned long)&qmi_wwan_shared, }, + { /* Pantech UML290 - newer firmware */ + .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x106c, + .idProduct = 0x3718, + .bInterfaceClass = 0xff, + .bInterfaceSubClass = 0xf1, + .bInterfaceProtocol = 0xff, + .driver_info = (unsigned long)&qmi_wwan_shared, + }, { /* ZTE MF820D */ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, .idVendor = 0x19d2, @@ -436,6 +462,15 @@ static const struct usb_device_id products[] = { .bInterfaceProtocol = 0xff, .driver_info = (unsigned long)&qmi_wwan_force_int4, }, + { /* ZTE MF821D */ + .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x19d2, + .idProduct = 0x0326, + .bInterfaceClass = 0xff, + .bInterfaceSubClass = 0xff, + .bInterfaceProtocol = 0xff, + .driver_info = (unsigned long)&qmi_wwan_force_int4, + }, { /* ZTE (Vodafone) K3520-Z */ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, .idVendor = 0x19d2, @@ -472,6 +507,15 @@ static const struct usb_device_id products[] = { .bInterfaceProtocol = 0xff, .driver_info = (unsigned long)&qmi_wwan_force_int4, }, + { /* ZTE (Vodafone) K3765-Z */ + .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x19d2, + .idProduct = 0x2002, + .bInterfaceClass = 0xff, + .bInterfaceSubClass = 0xff, + .bInterfaceProtocol = 0xff, + .driver_info = (unsigned long)&qmi_wwan_force_int4, + }, { /* ZTE (Vodafone) K4505-Z */ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, .idVendor = 0x19d2, @@ -481,6 +525,24 @@ static const struct usb_device_id products[] = { .bInterfaceProtocol = 0xff, .driver_info = (unsigned long)&qmi_wwan_force_int4, }, + { /* ZTE (Vodafone) K5006-Z */ + .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x19d2, + .idProduct = 0x1018, + .bInterfaceClass = 0xff, + .bInterfaceSubClass = 0xff, + .bInterfaceProtocol = 0xff, + .driver_info = (unsigned long)&qmi_wwan_force_int3, + }, + { /* ZTE MF60 */ + .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x19d2, + .idProduct = 0x1402, + .bInterfaceClass = 0xff, + .bInterfaceSubClass = 0xff, + .bInterfaceProtocol = 0xff, + .driver_info = (unsigned long)&qmi_wwan_force_int2, + }, { /* Sierra Wireless MC77xx in QMI mode */ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, .idVendor = 0x1199, @@ -490,6 +552,33 @@ static const struct usb_device_id products[] = { .bInterfaceProtocol = 0xff, .driver_info = (unsigned long)&qmi_wwan_sierra, }, + { /* Sierra Wireless MC7700 */ + .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x0f3d, + .idProduct = 0x68a2, + .bInterfaceClass = 0xff, + .bInterfaceSubClass = 0xff, + .bInterfaceProtocol = 0xff, + .driver_info = (unsigned long)&qmi_wwan_sierra, + }, + { /* Sierra Wireless MC7750 */ + .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x114f, + .idProduct = 0x68a2, + .bInterfaceClass = 0xff, + .bInterfaceSubClass = 0xff, + .bInterfaceProtocol = 0xff, + .driver_info = (unsigned long)&qmi_wwan_sierra, + }, + { /* Sierra Wireless EM7700 */ + .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x1199, + .idProduct = 0x901c, + .bInterfaceClass = 0xff, + .bInterfaceSubClass = 0xff, + .bInterfaceProtocol = 0xff, + .driver_info = (unsigned long)&qmi_wwan_sierra, + }, /* Gobi 1000 devices */ {QMI_GOBI1K_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */ @@ -517,6 +606,8 @@ static const struct usb_device_id products[] = { {QMI_GOBI_DEVICE(0x05c6, 0x9265)}, /* Asus Gobi 2000 Modem device (VR305) */ {QMI_GOBI_DEVICE(0x05c6, 0x9235)}, /* Top Global Gobi 2000 Modem device (VR306) */ {QMI_GOBI_DEVICE(0x05c6, 0x9275)}, /* iRex Technologies Gobi 2000 Modem device (VR307) */ + {QMI_GOBI_DEVICE(0x1199, 0x68a5)}, /* Sierra Wireless Modem */ + {QMI_GOBI_DEVICE(0x1199, 0x68a9)}, /* Sierra Wireless Modem */ {QMI_GOBI_DEVICE(0x1199, 0x9001)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */ {QMI_GOBI_DEVICE(0x1199, 0x9002)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */ {QMI_GOBI_DEVICE(0x1199, 0x9003)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */ @@ -531,6 +622,10 @@ static const struct usb_device_id products[] = { {QMI_GOBI_DEVICE(0x16d8, 0x8002)}, /* CMDTech Gobi 2000 Modem device (VU922) */ {QMI_GOBI_DEVICE(0x05c6, 0x9205)}, /* Gobi 2000 Modem device */ {QMI_GOBI_DEVICE(0x1199, 0x9013)}, /* Sierra Wireless Gobi 3000 Modem device (MC8355) */ + {QMI_GOBI_DEVICE(0x1199, 0x9015)}, /* Sierra Wireless Gobi 3000 Modem device */ + {QMI_GOBI_DEVICE(0x1199, 0x9019)}, /* Sierra Wireless Gobi 3000 Modem device */ + {QMI_GOBI_DEVICE(0x1199, 0x901b)}, /* Sierra Wireless MC7770 */ + { } /* END */ }; MODULE_DEVICE_TABLE(usb, products); diff --git a/drivers/net/usb/sierra_net.c b/drivers/net/usb/sierra_net.c index cc9776c2a39..8789bc58b17 100644 --- a/drivers/net/usb/sierra_net.c +++ b/drivers/net/usb/sierra_net.c @@ -678,7 +678,7 @@ static int sierra_net_get_fw_attr(struct usbnet *dev, u16 *datap) return -EIO; } - *datap = *attrdata; + *datap = le16_to_cpu(*attrdata); kfree(attrdata); return result; diff --git a/drivers/net/wan/ixp4xx_hss.c b/drivers/net/wan/ixp4xx_hss.c index aaaca9aa229..3f575afd8cf 100644 --- a/drivers/net/wan/ixp4xx_hss.c +++ b/drivers/net/wan/ixp4xx_hss.c @@ -10,6 +10,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include #include #include #include diff --git a/drivers/net/wimax/i2400m/i2400m-usb.h b/drivers/net/wimax/i2400m/i2400m-usb.h index 6650fde99e1..9f1e947f355 100644 --- a/drivers/net/wimax/i2400m/i2400m-usb.h +++ b/drivers/net/wimax/i2400m/i2400m-usb.h @@ -152,6 +152,9 @@ enum { /* Device IDs */ USB_DEVICE_ID_I6050 = 0x0186, USB_DEVICE_ID_I6050_2 = 0x0188, + USB_DEVICE_ID_I6150 = 0x07d6, + USB_DEVICE_ID_I6150_2 = 0x07d7, + USB_DEVICE_ID_I6150_3 = 0x07d9, USB_DEVICE_ID_I6250 = 0x0187, }; diff --git a/drivers/net/wimax/i2400m/usb.c b/drivers/net/wimax/i2400m/usb.c index 29b1e033a10..f0f16e0c612 100644 --- a/drivers/net/wimax/i2400m/usb.c +++ b/drivers/net/wimax/i2400m/usb.c @@ -510,6 +510,9 @@ int i2400mu_probe(struct usb_interface *iface, switch (id->idProduct) { case USB_DEVICE_ID_I6050: case USB_DEVICE_ID_I6050_2: + case USB_DEVICE_ID_I6150: + case USB_DEVICE_ID_I6150_2: + case USB_DEVICE_ID_I6150_3: case USB_DEVICE_ID_I6250: i2400mu->i6050 = 1; break; @@ -759,6 +762,9 @@ static struct usb_device_id i2400mu_id_table[] = { { USB_DEVICE(0x8086, USB_DEVICE_ID_I6050) }, { USB_DEVICE(0x8086, USB_DEVICE_ID_I6050_2) }, + { USB_DEVICE(0x8087, USB_DEVICE_ID_I6150) }, + { USB_DEVICE(0x8087, USB_DEVICE_ID_I6150_2) }, + { USB_DEVICE(0x8087, USB_DEVICE_ID_I6150_3) }, { USB_DEVICE(0x8086, USB_DEVICE_ID_I6250) }, { USB_DEVICE(0x8086, 0x0181) }, { USB_DEVICE(0x8086, 0x1403) }, diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 0e643b016b3..c7d1437c770 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c @@ -843,7 +843,7 @@ ath5k_txbuf_free_skb(struct ath5k_hw *ah, struct ath5k_buf *bf) return; dma_unmap_single(ah->dev, bf->skbaddr, bf->skb->len, DMA_TO_DEVICE); - dev_kfree_skb_any(bf->skb); + ieee80211_free_txskb(ah->hw, bf->skb); bf->skb = NULL; bf->skbaddr = 0; bf->desc->ds_data = 0; @@ -1570,7 +1570,7 @@ ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, return; drop_packet: - dev_kfree_skb_any(skb); + ieee80211_free_txskb(hw, skb); } static void diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c index 5c532995541..5d1be4daa56 100644 --- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c +++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c @@ -59,7 +59,7 @@ ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) u16 qnum = skb_get_queue_mapping(skb); if (WARN_ON(qnum >= ah->ah_capabilities.cap_queues.q_tx_num)) { - dev_kfree_skb_any(skb); + ieee80211_free_txskb(hw, skb); return; } diff --git a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h index 46c79a3d473..4e2a52c342d 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h @@ -533,107 +533,107 @@ static const u32 ar9300_2p2_baseband_core[][2] = { static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = { /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ - {0x0000a2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352}, - {0x0000a2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584}, - {0x0000a2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800}, + {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, + {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, + {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, - {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9}, - {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002}, - {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004}, - {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200}, - {0x0000a510, 0x15000028, 0x15000028, 0x0f000202, 0x0f000202}, - {0x0000a514, 0x1b00002b, 0x1b00002b, 0x12000400, 0x12000400}, - {0x0000a518, 0x1f020028, 0x1f020028, 0x16000402, 0x16000402}, - {0x0000a51c, 0x2502002b, 0x2502002b, 0x19000404, 0x19000404}, - {0x0000a520, 0x2a04002a, 0x2a04002a, 0x1c000603, 0x1c000603}, - {0x0000a524, 0x2e06002a, 0x2e06002a, 0x21000a02, 0x21000a02}, - {0x0000a528, 0x3302202d, 0x3302202d, 0x25000a04, 0x25000a04}, - {0x0000a52c, 0x3804202c, 0x3804202c, 0x28000a20, 0x28000a20}, - {0x0000a530, 0x3c06202c, 0x3c06202c, 0x2c000e20, 0x2c000e20}, - {0x0000a534, 0x4108202d, 0x4108202d, 0x30000e22, 0x30000e22}, - {0x0000a538, 0x4506402d, 0x4506402d, 0x34000e24, 0x34000e24}, - {0x0000a53c, 0x4906222d, 0x4906222d, 0x38001640, 0x38001640}, - {0x0000a540, 0x4d062231, 0x4d062231, 0x3c001660, 0x3c001660}, - {0x0000a544, 0x50082231, 0x50082231, 0x3f001861, 0x3f001861}, - {0x0000a548, 0x5608422e, 0x5608422e, 0x43001a81, 0x43001a81}, - {0x0000a54c, 0x5a08442e, 0x5a08442e, 0x47001a83, 0x47001a83}, - {0x0000a550, 0x5e0a4431, 0x5e0a4431, 0x4a001c84, 0x4a001c84}, - {0x0000a554, 0x640a4432, 0x640a4432, 0x4e001ce3, 0x4e001ce3}, - {0x0000a558, 0x680a4434, 0x680a4434, 0x52001ce5, 0x52001ce5}, - {0x0000a55c, 0x6c0a6434, 0x6c0a6434, 0x56001ce9, 0x56001ce9}, - {0x0000a560, 0x6f0a6633, 0x6f0a6633, 0x5a001ceb, 0x5a001ceb}, - {0x0000a564, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, - {0x0000a568, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, - {0x0000a56c, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, - {0x0000a570, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, - {0x0000a574, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, - {0x0000a578, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, - {0x0000a57c, 0x730c6634, 0x730c6634, 0x5d001eec, 0x5d001eec}, - {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000}, - {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002}, - {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004}, - {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200}, - {0x0000a590, 0x15800028, 0x15800028, 0x0f800202, 0x0f800202}, - {0x0000a594, 0x1b80002b, 0x1b80002b, 0x12800400, 0x12800400}, - {0x0000a598, 0x1f820028, 0x1f820028, 0x16800402, 0x16800402}, - {0x0000a59c, 0x2582002b, 0x2582002b, 0x19800404, 0x19800404}, - {0x0000a5a0, 0x2a84002a, 0x2a84002a, 0x1c800603, 0x1c800603}, - {0x0000a5a4, 0x2e86002a, 0x2e86002a, 0x21800a02, 0x21800a02}, - {0x0000a5a8, 0x3382202d, 0x3382202d, 0x25800a04, 0x25800a04}, - {0x0000a5ac, 0x3884202c, 0x3884202c, 0x28800a20, 0x28800a20}, - {0x0000a5b0, 0x3c86202c, 0x3c86202c, 0x2c800e20, 0x2c800e20}, - {0x0000a5b4, 0x4188202d, 0x4188202d, 0x30800e22, 0x30800e22}, - {0x0000a5b8, 0x4586402d, 0x4586402d, 0x34800e24, 0x34800e24}, - {0x0000a5bc, 0x4986222d, 0x4986222d, 0x38801640, 0x38801640}, - {0x0000a5c0, 0x4d862231, 0x4d862231, 0x3c801660, 0x3c801660}, - {0x0000a5c4, 0x50882231, 0x50882231, 0x3f801861, 0x3f801861}, - {0x0000a5c8, 0x5688422e, 0x5688422e, 0x43801a81, 0x43801a81}, - {0x0000a5cc, 0x5a88442e, 0x5a88442e, 0x47801a83, 0x47801a83}, - {0x0000a5d0, 0x5e8a4431, 0x5e8a4431, 0x4a801c84, 0x4a801c84}, - {0x0000a5d4, 0x648a4432, 0x648a4432, 0x4e801ce3, 0x4e801ce3}, - {0x0000a5d8, 0x688a4434, 0x688a4434, 0x52801ce5, 0x52801ce5}, - {0x0000a5dc, 0x6c8a6434, 0x6c8a6434, 0x56801ce9, 0x56801ce9}, - {0x0000a5e0, 0x6f8a6633, 0x6f8a6633, 0x5a801ceb, 0x5a801ceb}, - {0x0000a5e4, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, - {0x0000a5e8, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, - {0x0000a5ec, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, - {0x0000a5f0, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, - {0x0000a5f4, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, - {0x0000a5f8, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, - {0x0000a5fc, 0x738c6634, 0x738c6634, 0x5d801eec, 0x5d801eec}, + {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9}, + {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, + {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002}, + {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004}, + {0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200}, + {0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202}, + {0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400}, + {0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402}, + {0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404}, + {0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603}, + {0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02}, + {0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04}, + {0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20}, + {0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20}, + {0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22}, + {0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24}, + {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640}, + {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660}, + {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861}, + {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81}, + {0x0000a54c, 0x59025eb2, 0x59025eb2, 0x42001a83, 0x42001a83}, + {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84}, + {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3}, + {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5}, + {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9}, + {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb}, + {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, + {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000}, + {0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002}, + {0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004}, + {0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200}, + {0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202}, + {0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400}, + {0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402}, + {0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404}, + {0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603}, + {0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02}, + {0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04}, + {0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20}, + {0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20}, + {0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22}, + {0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24}, + {0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640}, + {0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660}, + {0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861}, + {0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81}, + {0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83}, + {0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84}, + {0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3}, + {0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5}, + {0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9}, + {0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb}, + {0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, + {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a608, 0x01804601, 0x01804601, 0x00000000, 0x00000000}, - {0x0000a60c, 0x01804601, 0x01804601, 0x00000000, 0x00000000}, - {0x0000a610, 0x01804601, 0x01804601, 0x00000000, 0x00000000}, - {0x0000a614, 0x01804601, 0x01804601, 0x01404000, 0x01404000}, - {0x0000a618, 0x01804601, 0x01804601, 0x01404501, 0x01404501}, - {0x0000a61c, 0x01804601, 0x01804601, 0x02008501, 0x02008501}, - {0x0000a620, 0x03408d02, 0x03408d02, 0x0280ca03, 0x0280ca03}, - {0x0000a624, 0x0300cc03, 0x0300cc03, 0x03010c04, 0x03010c04}, - {0x0000a628, 0x03410d04, 0x03410d04, 0x04014c04, 0x04014c04}, - {0x0000a62c, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, - {0x0000a630, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, - {0x0000a634, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, - {0x0000a638, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, - {0x0000a63c, 0x03410d04, 0x03410d04, 0x04015005, 0x04015005}, - {0x0000b2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352}, - {0x0000b2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584}, - {0x0000b2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800}, + {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000a610, 0x00804000, 0x00804000, 0x00000000, 0x00000000}, + {0x0000a614, 0x00804201, 0x00804201, 0x01404000, 0x01404000}, + {0x0000a618, 0x0280c802, 0x0280c802, 0x01404501, 0x01404501}, + {0x0000a61c, 0x0280ca03, 0x0280ca03, 0x02008501, 0x02008501}, + {0x0000a620, 0x04c15104, 0x04c15104, 0x0280ca03, 0x0280ca03}, + {0x0000a624, 0x04c15305, 0x04c15305, 0x03010c04, 0x03010c04}, + {0x0000a628, 0x04c15305, 0x04c15305, 0x04014c04, 0x04014c04}, + {0x0000a62c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, + {0x0000a630, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, + {0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, + {0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, + {0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, + {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, + {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, + {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, - {0x0000c2dc, 0x000cfff0, 0x000cfff0, 0x03aaa352, 0x03aaa352}, - {0x0000c2e0, 0x000f0000, 0x000f0000, 0x03ccc584, 0x03ccc584}, - {0x0000c2e4, 0x03f00000, 0x03f00000, 0x03f0f800, 0x03f0f800}, + {0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, + {0x0000c2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, + {0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, - {0x00016048, 0x61200001, 0x61200001, 0x66480001, 0x66480001}, + {0x00016048, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, {0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, - {0x00016448, 0x61200001, 0x61200001, 0x66480001, 0x66480001}, + {0x00016448, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, {0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4}, - {0x00016848, 0x61200001, 0x61200001, 0x66480001, 0x66480001}, + {0x00016848, 0x66480001, 0x66480001, 0x66480001, 0x66480001}, {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c}, }; diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h index bb223fe8281..582ebc4bc5e 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h @@ -69,13 +69,13 @@ #define AR9300_BASE_ADDR 0x3ff #define AR9300_BASE_ADDR_512 0x1ff -#define AR9300_OTP_BASE 0x14000 -#define AR9300_OTP_STATUS 0x15f18 +#define AR9300_OTP_BASE (AR_SREV_9340(ah) ? 0x30000 : 0x14000) +#define AR9300_OTP_STATUS (AR_SREV_9340(ah) ? 0x30018 : 0x15f18) #define AR9300_OTP_STATUS_TYPE 0x7 #define AR9300_OTP_STATUS_VALID 0x4 #define AR9300_OTP_STATUS_ACCESS_BUSY 0x2 #define AR9300_OTP_STATUS_SM_BUSY 0x1 -#define AR9300_OTP_READ_DATA 0x15f1c +#define AR9300_OTP_READ_DATA (AR_SREV_9340(ah) ? 0x3001c : 0x15f1c) enum targetPowerHTRates { HT_TARGET_RATE_0_8_16, diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index 626418222c8..2e4243fcadc 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c @@ -121,7 +121,7 @@ static void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb) if (ath_tx_start(hw, skb, &txctl) != 0) { ath_dbg(common, XMIT, "CABQ TX failed\n"); - dev_kfree_skb_any(skb); + ieee80211_free_txskb(hw, skb); } } @@ -154,6 +154,7 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw, skb->len, DMA_TO_DEVICE); dev_kfree_skb_any(skb); bf->bf_buf_addr = 0; + bf->bf_mpdu = NULL; } /* Get a new beacon from mac80211 */ diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index e5cceb07757..bbd249df23e 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c @@ -69,6 +69,7 @@ s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan) if (chan && chan->noisefloor) { s8 delta = chan->noisefloor - + ATH9K_NF_CAL_NOISE_THRESH - ath9k_hw_get_default_nf(ah, chan); if (delta > 0) noise += delta; diff --git a/drivers/net/wireless/ath/ath9k/calib.h b/drivers/net/wireless/ath/ath9k/calib.h index 3b33996d97d..1f2e01a96d2 100644 --- a/drivers/net/wireless/ath/ath9k/calib.h +++ b/drivers/net/wireless/ath/ath9k/calib.h @@ -21,6 +21,9 @@ #define AR_PHY_CCA_FILTERWINDOW_LENGTH 5 +/* Internal noise floor can vary by about 6db depending on the frequency */ +#define ATH9K_NF_CAL_NOISE_THRESH 6 + #define NUM_NF_READINGS 6 #define ATH9K_NF_CAL_HIST_MAX 5 diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c index c25226a32dd..ec86d981abc 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.c +++ b/drivers/net/wireless/ath/ath9k/htc_hst.c @@ -342,6 +342,8 @@ void ath9k_htc_txcompletion_cb(struct htc_target *htc_handle, endpoint->ep_callbacks.tx(endpoint->ep_callbacks.priv, skb, htc_hdr->endpoint_id, txok); + } else { + kfree_skb(skb); } } diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 6dfd9644884..28a0edd57f0 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -676,6 +676,7 @@ int ath9k_hw_init(struct ath_hw *ah) case AR9300_DEVID_AR9340: case AR9300_DEVID_AR9580: case AR9300_DEVID_AR9462: + case AR9485_DEVID_AR1111: break; default: if (common->bus_ops->ath_bus_type == ATH_USB) diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index e88f182ff45..f8e1fbbbfc5 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -48,6 +48,7 @@ #define AR9300_DEVID_AR9580 0x0033 #define AR9300_DEVID_AR9462 0x0034 #define AR9300_DEVID_AR9330 0x0035 +#define AR9485_DEVID_AR1111 0x0037 #define AR5416_AR9100_DEVID 0x000b diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index d5dabcb61a0..91e2c4f53d1 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1147,7 +1147,7 @@ static void ath9k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) return; exit: - dev_kfree_skb_any(skb); + ieee80211_free_txskb(hw, skb); } static void ath9k_stop(struct ieee80211_hw *hw) diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index 77dc327def8..0e7d6c188cc 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c @@ -35,6 +35,7 @@ static DEFINE_PCI_DEVICE_TABLE(ath_pci_id_table) = { { PCI_VDEVICE(ATHEROS, 0x0032) }, /* PCI-E AR9485 */ { PCI_VDEVICE(ATHEROS, 0x0033) }, /* PCI-E AR9580 */ { PCI_VDEVICE(ATHEROS, 0x0034) }, /* PCI-E AR9462 */ + { PCI_VDEVICE(ATHEROS, 0x0037) }, /* PCI-E AR1111/AR9485 */ { 0 } }; @@ -121,8 +122,9 @@ static void ath_pci_aspm_init(struct ath_common *common) if (!parent) return; - if (ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_NONE) { - /* Bluetooth coexistance requires disabling ASPM. */ + if ((ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_NONE) && + (AR_SREV_9285(ah))) { + /* Bluetooth coexistance requires disabling ASPM for AR9285. */ pci_read_config_byte(pdev, pos + PCI_EXP_LNKCTL, &aspm); aspm &= ~(PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1); pci_write_config_byte(pdev, pos + PCI_EXP_LNKCTL, aspm); diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index a2f7ae81a41..039bac7e0c6 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -778,6 +778,7 @@ static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc, return NULL; } + list_del(&bf->list); if (!bf->bf_mpdu) return bf; @@ -1774,7 +1775,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) struct ieee80211_hw *hw = sc->hw; struct ieee80211_hdr *hdr; int retval; - bool decrypt_error = false; struct ath_rx_status rs; enum ath9k_rx_qtype qtype; bool edma = !!(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA); @@ -1796,6 +1796,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) tsf_lower = tsf & 0xffffffff; do { + bool decrypt_error = false; /* If handling rx interrupt and flush is in progress => exit */ if ((sc->sc_flags & SC_OP_RXFLUSH) && (flush == 0)) break; @@ -1966,14 +1967,15 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) sc->rx.frag = NULL; } requeue: + list_add_tail(&bf->list, &sc->rx.rxbuf); + if (flush) + continue; + if (edma) { - list_add_tail(&bf->list, &sc->rx.rxbuf); ath_rx_edma_buf_link(sc, qtype); } else { - list_move_tail(&bf->list, &sc->rx.rxbuf); ath_rx_buf_link(sc, bf); - if (!flush) - ath9k_hw_rxena(ah); + ath9k_hw_rxena(ah); } } while (1); diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 4d571394c7a..12a42f2c1e8 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -64,8 +64,7 @@ static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid, static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc, struct ath_txq *txq, struct ath_atx_tid *tid, - struct sk_buff *skb, - bool dequeue); + struct sk_buff *skb); enum { MCS_HT20, @@ -201,7 +200,15 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) fi = get_frame_info(skb); bf = fi->bf; - if (bf && fi->retries) { + if (!bf) { + bf = ath_tx_setup_buffer(sc, txq, tid, skb); + if (!bf) { + ieee80211_free_txskb(sc->hw, skb); + continue; + } + } + + if (fi->retries) { list_add_tail(&bf->list, &bf_head); ath_tx_update_baw(sc, tid, bf->bf_state.seqno); ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0); @@ -330,6 +337,7 @@ static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc) } bf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list); + bf->bf_next = NULL; list_del(&bf->list); spin_unlock_bh(&sc->tx.txbuflock); @@ -411,7 +419,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, u16 seq_st = 0, acked_cnt = 0, txfail_cnt = 0, seq_first; u32 ba[WME_BA_BMP_SIZE >> 5]; int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0; - bool rc_update = true; + bool rc_update = true, isba; struct ieee80211_tx_rate rates[4]; struct ath_frame_info *fi; int nframes; @@ -455,13 +463,17 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK; tid = ATH_AN_2_TID(an, tidno); seq_first = tid->seq_start; + isba = ts->ts_flags & ATH9K_TX_BA; /* * The hardware occasionally sends a tx status for the wrong TID. * In this case, the BA status cannot be considered valid and all * subframes need to be retransmitted + * + * Only BlockAcks have a TID and therefore normal Acks cannot be + * checked */ - if (tidno != ts->tid) + if (isba && tidno != ts->tid) txok = false; isaggr = bf_isaggr(bf); @@ -812,10 +824,13 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, fi = get_frame_info(skb); bf = fi->bf; if (!fi->bf) - bf = ath_tx_setup_buffer(sc, txq, tid, skb, true); + bf = ath_tx_setup_buffer(sc, txq, tid, skb); - if (!bf) + if (!bf) { + __skb_unlink(skb, &tid->buf_q); + ieee80211_free_txskb(sc->hw, skb); continue; + } bf->bf_state.bf_type = BUF_AMPDU | BUF_AGGR; seqno = bf->bf_state.seqno; @@ -1717,9 +1732,11 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid, return; } - bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb, false); - if (!bf) + bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb); + if (!bf) { + ieee80211_free_txskb(sc->hw, skb); return; + } bf->bf_state.bf_type = BUF_AMPDU; INIT_LIST_HEAD(&bf_head); @@ -1743,16 +1760,12 @@ static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, struct ath_buf *bf; bf = fi->bf; - if (!bf) - bf = ath_tx_setup_buffer(sc, txq, tid, skb, false); - - if (!bf) - return; INIT_LIST_HEAD(&bf_head); list_add_tail(&bf->list, &bf_head); bf->bf_state.bf_type = 0; + bf->bf_next = NULL; bf->bf_lastbf = bf; ath_tx_fill_desc(sc, bf, txq, fi->framelen); ath_tx_txqaddbuf(sc, txq, &bf_head, false); @@ -1820,8 +1833,7 @@ u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate) static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc, struct ath_txq *txq, struct ath_atx_tid *tid, - struct sk_buff *skb, - bool dequeue) + struct sk_buff *skb) { struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath_frame_info *fi = get_frame_info(skb); @@ -1833,7 +1845,7 @@ static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc, bf = ath_tx_get_buffer(sc); if (!bf) { ath_dbg(common, XMIT, "TX buffers are full\n"); - goto error; + return NULL; } ATH_TXBUF_RESET(bf); @@ -1862,18 +1874,12 @@ static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc, ath_err(ath9k_hw_common(sc->sc_ah), "dma_mapping_error() on TX\n"); ath_tx_return_buffer(sc, bf); - goto error; + return NULL; } fi->bf = bf; return bf; - -error: - if (dequeue) - __skb_unlink(skb, &tid->buf_q); - dev_kfree_skb_any(skb); - return NULL; } /* FIXME: tx power */ @@ -1902,9 +1908,14 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct sk_buff *skb, */ ath_tx_send_ampdu(sc, tid, skb, txctl); } else { - bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb, false); - if (!bf) + bf = ath_tx_setup_buffer(sc, txctl->txq, tid, skb); + if (!bf) { + if (txctl->paprd) + dev_kfree_skb_any(skb); + else + ieee80211_free_txskb(sc->hw, skb); return; + } bf->bf_state.bfs_paprd = txctl->paprd; diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index 67c13af6f20..05cb5f6b8d4 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h @@ -7,6 +7,7 @@ #include #include #include +#include #include #include "debugfs.h" @@ -718,6 +719,10 @@ enum b43_firmware_file_type { struct b43_request_fw_context { /* The device we are requesting the fw for. */ struct b43_wldev *dev; + /* a completion event structure needed if this call is asynchronous */ + struct completion fw_load_complete; + /* a pointer to the firmware object */ + const struct firmware *blob; /* The type of firmware to request. */ enum b43_firmware_file_type req_type; /* Error messages for each firmware type. */ diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index b5f1b91002b..65f831faf2a 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c @@ -409,7 +409,10 @@ static inline struct b43_dmadesc_meta *meta) { if (meta->skb) { - dev_kfree_skb_any(meta->skb); + if (ring->tx) + ieee80211_free_txskb(ring->dev->wl->hw, meta->skb); + else + dev_kfree_skb_any(meta->skb); meta->skb = NULL; } } @@ -1454,7 +1457,7 @@ int b43_dma_tx(struct b43_wldev *dev, struct sk_buff *skb) if (unlikely(err == -ENOKEY)) { /* Drop this packet, as we don't have the encryption key * anymore and must not transmit it unencrypted. */ - dev_kfree_skb_any(skb); + ieee80211_free_txskb(dev->wl->hw, skb); err = 0; goto out; } diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index e4d6dc2e37d..14fd2caa1f9 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -2088,11 +2088,18 @@ static void b43_print_fw_helptext(struct b43_wl *wl, bool error) b43warn(wl, text); } +static void b43_fw_cb(const struct firmware *firmware, void *context) +{ + struct b43_request_fw_context *ctx = context; + + ctx->blob = firmware; + complete(&ctx->fw_load_complete); +} + int b43_do_request_fw(struct b43_request_fw_context *ctx, const char *name, - struct b43_firmware_file *fw) + struct b43_firmware_file *fw, bool async) { - const struct firmware *blob; struct b43_fw_header *hdr; u32 size; int err; @@ -2131,11 +2138,31 @@ int b43_do_request_fw(struct b43_request_fw_context *ctx, B43_WARN_ON(1); return -ENOSYS; } - err = request_firmware(&blob, ctx->fwname, ctx->dev->dev->dev); + if (async) { + /* do this part asynchronously */ + init_completion(&ctx->fw_load_complete); + err = request_firmware_nowait(THIS_MODULE, 1, ctx->fwname, + ctx->dev->dev->dev, GFP_KERNEL, + ctx, b43_fw_cb); + if (err < 0) { + pr_err("Unable to load firmware\n"); + return err; + } + /* stall here until fw ready */ + wait_for_completion(&ctx->fw_load_complete); + if (ctx->blob) + goto fw_ready; + /* On some ARM systems, the async request will fail, but the next sync + * request works. For this reason, we dall through here + */ + } + err = request_firmware(&ctx->blob, ctx->fwname, + ctx->dev->dev->dev); if (err == -ENOENT) { snprintf(ctx->errors[ctx->req_type], sizeof(ctx->errors[ctx->req_type]), - "Firmware file \"%s\" not found\n", ctx->fwname); + "Firmware file \"%s\" not found\n", + ctx->fwname); return err; } else if (err) { snprintf(ctx->errors[ctx->req_type], @@ -2144,14 +2171,15 @@ int b43_do_request_fw(struct b43_request_fw_context *ctx, ctx->fwname, err); return err; } - if (blob->size < sizeof(struct b43_fw_header)) +fw_ready: + if (ctx->blob->size < sizeof(struct b43_fw_header)) goto err_format; - hdr = (struct b43_fw_header *)(blob->data); + hdr = (struct b43_fw_header *)(ctx->blob->data); switch (hdr->type) { case B43_FW_TYPE_UCODE: case B43_FW_TYPE_PCM: size = be32_to_cpu(hdr->size); - if (size != blob->size - sizeof(struct b43_fw_header)) + if (size != ctx->blob->size - sizeof(struct b43_fw_header)) goto err_format; /* fallthrough */ case B43_FW_TYPE_IV: @@ -2162,7 +2190,7 @@ int b43_do_request_fw(struct b43_request_fw_context *ctx, goto err_format; } - fw->data = blob; + fw->data = ctx->blob; fw->filename = name; fw->type = ctx->req_type; @@ -2172,7 +2200,7 @@ int b43_do_request_fw(struct b43_request_fw_context *ctx, snprintf(ctx->errors[ctx->req_type], sizeof(ctx->errors[ctx->req_type]), "Firmware file \"%s\" format error.\n", ctx->fwname); - release_firmware(blob); + release_firmware(ctx->blob); return -EPROTO; } @@ -2223,7 +2251,7 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx) goto err_no_ucode; } } - err = b43_do_request_fw(ctx, filename, &fw->ucode); + err = b43_do_request_fw(ctx, filename, &fw->ucode, true); if (err) goto err_load; @@ -2235,7 +2263,7 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx) else goto err_no_pcm; fw->pcm_request_failed = false; - err = b43_do_request_fw(ctx, filename, &fw->pcm); + err = b43_do_request_fw(ctx, filename, &fw->pcm, false); if (err == -ENOENT) { /* We did not find a PCM file? Not fatal, but * core rev <= 10 must do without hwcrypto then. */ @@ -2296,7 +2324,7 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx) default: goto err_no_initvals; } - err = b43_do_request_fw(ctx, filename, &fw->initvals); + err = b43_do_request_fw(ctx, filename, &fw->initvals, false); if (err) goto err_load; @@ -2355,7 +2383,7 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx) default: goto err_no_initvals; } - err = b43_do_request_fw(ctx, filename, &fw->initvals_band); + err = b43_do_request_fw(ctx, filename, &fw->initvals_band, false); if (err) goto err_load; @@ -3393,7 +3421,7 @@ static void b43_tx_work(struct work_struct *work) break; } if (unlikely(err)) - dev_kfree_skb(skb); /* Drop it */ + ieee80211_free_txskb(wl->hw, skb); err = 0; } @@ -3414,7 +3442,7 @@ static void b43_op_tx(struct ieee80211_hw *hw, if (unlikely(skb->len < 2 + 2 + 6)) { /* Too short, this can't be a valid frame. */ - dev_kfree_skb_any(skb); + ieee80211_free_txskb(hw, skb); return; } B43_WARN_ON(skb_shinfo(skb)->nr_frags); @@ -4210,8 +4238,12 @@ static struct b43_wldev * b43_wireless_core_stop(struct b43_wldev *dev) /* Drain all TX queues. */ for (queue_num = 0; queue_num < B43_QOS_QUEUE_NUM; queue_num++) { - while (skb_queue_len(&wl->tx_queue[queue_num])) - dev_kfree_skb(skb_dequeue(&wl->tx_queue[queue_num])); + while (skb_queue_len(&wl->tx_queue[queue_num])) { + struct sk_buff *skb; + + skb = skb_dequeue(&wl->tx_queue[queue_num]); + ieee80211_free_txskb(wl->hw, skb); + } } b43_mac_suspend(dev); @@ -5430,6 +5462,8 @@ static void b43_ssb_remove(struct ssb_device *sdev) cancel_work_sync(&wldev->restart_work); B43_WARN_ON(!wl); + if (!wldev->fw.ucode.data) + return; /* NULL if firmware never loaded */ if (wl->current_dev == wldev) { /* Restore the queues count before unregistering, because firmware detect * might have modified it. Restoring is important, so the networking diff --git a/drivers/net/wireless/b43/main.h b/drivers/net/wireless/b43/main.h index 8c684cd3352..abac25ee958 100644 --- a/drivers/net/wireless/b43/main.h +++ b/drivers/net/wireless/b43/main.h @@ -137,9 +137,8 @@ void b43_mac_phy_clock_set(struct b43_wldev *dev, bool on); struct b43_request_fw_context; -int b43_do_request_fw(struct b43_request_fw_context *ctx, - const char *name, - struct b43_firmware_file *fw); +int b43_do_request_fw(struct b43_request_fw_context *ctx, const char *name, + struct b43_firmware_file *fw, bool async); void b43_do_release_fw(struct b43_firmware_file *fw); #endif /* B43_MAIN_H_ */ diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c index 3533ab86bd3..a73ff8c9deb 100644 --- a/drivers/net/wireless/b43/pio.c +++ b/drivers/net/wireless/b43/pio.c @@ -196,7 +196,7 @@ static void b43_pio_cancel_tx_packets(struct b43_pio_txqueue *q) for (i = 0; i < ARRAY_SIZE(q->packets); i++) { pack = &(q->packets[i]); if (pack->skb) { - dev_kfree_skb_any(pack->skb); + ieee80211_free_txskb(q->dev->wl->hw, pack->skb); pack->skb = NULL; } } @@ -552,7 +552,7 @@ int b43_pio_tx(struct b43_wldev *dev, struct sk_buff *skb) if (unlikely(err == -ENOKEY)) { /* Drop this packet, as we don't have the encryption key * anymore and must not transmit it unencrypted. */ - dev_kfree_skb_any(skb); + ieee80211_free_txskb(dev->wl->hw, skb); err = 0; goto out; } diff --git a/drivers/net/wireless/b43legacy/b43legacy.h b/drivers/net/wireless/b43legacy/b43legacy.h index a29da674e69..482476fdb1f 100644 --- a/drivers/net/wireless/b43legacy/b43legacy.h +++ b/drivers/net/wireless/b43legacy/b43legacy.h @@ -13,6 +13,7 @@ #include #include +#include #include @@ -733,6 +734,10 @@ struct b43legacy_wldev { /* Firmware data */ struct b43legacy_firmware fw; + const struct firmware *fwp; /* needed to pass fw pointer */ + + /* completion struct for firmware loading */ + struct completion fw_load_complete; /* Devicelist in struct b43legacy_wl (all 802.11 cores) */ struct list_head list; diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index a98db30b7ac..53696efbe15 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -1511,9 +1511,17 @@ static void b43legacy_print_fw_helptext(struct b43legacy_wl *wl) "and download the correct firmware (version 3).\n"); } +static void b43legacy_fw_cb(const struct firmware *firmware, void *context) +{ + struct b43legacy_wldev *dev = context; + + dev->fwp = firmware; + complete(&dev->fw_load_complete); +} + static int do_request_fw(struct b43legacy_wldev *dev, const char *name, - const struct firmware **fw) + const struct firmware **fw, bool async) { char path[sizeof(modparam_fwpostfix) + 32]; struct b43legacy_fw_header *hdr; @@ -1526,7 +1534,24 @@ static int do_request_fw(struct b43legacy_wldev *dev, snprintf(path, ARRAY_SIZE(path), "b43legacy%s/%s.fw", modparam_fwpostfix, name); - err = request_firmware(fw, path, dev->dev->dev); + b43legacyinfo(dev->wl, "Loading firmware %s\n", path); + if (async) { + init_completion(&dev->fw_load_complete); + err = request_firmware_nowait(THIS_MODULE, 1, path, + dev->dev->dev, GFP_KERNEL, + dev, b43legacy_fw_cb); + if (err) { + b43legacyerr(dev->wl, "Unable to load firmware\n"); + return err; + } + /* stall here until fw ready */ + wait_for_completion(&dev->fw_load_complete); + if (!dev->fwp) + err = -EINVAL; + *fw = dev->fwp; + } else { + err = request_firmware(fw, path, dev->dev->dev); + } if (err) { b43legacyerr(dev->wl, "Firmware file \"%s\" not found " "or load failed.\n", path); @@ -1578,7 +1603,7 @@ static void b43legacy_request_firmware(struct work_struct *work) filename = "ucode4"; else filename = "ucode5"; - err = do_request_fw(dev, filename, &fw->ucode); + err = do_request_fw(dev, filename, &fw->ucode, true); if (err) goto err_load; } @@ -1587,7 +1612,7 @@ static void b43legacy_request_firmware(struct work_struct *work) filename = "pcm4"; else filename = "pcm5"; - err = do_request_fw(dev, filename, &fw->pcm); + err = do_request_fw(dev, filename, &fw->pcm, false); if (err) goto err_load; } @@ -1605,7 +1630,7 @@ static void b43legacy_request_firmware(struct work_struct *work) default: goto err_no_initvals; } - err = do_request_fw(dev, filename, &fw->initvals); + err = do_request_fw(dev, filename, &fw->initvals, false); if (err) goto err_load; } @@ -1625,7 +1650,7 @@ static void b43legacy_request_firmware(struct work_struct *work) default: goto err_no_initvals; } - err = do_request_fw(dev, filename, &fw->initvals_band); + err = do_request_fw(dev, filename, &fw->initvals_band, false); if (err) goto err_load; } @@ -3892,6 +3917,8 @@ static void b43legacy_remove(struct ssb_device *dev) cancel_work_sync(&wl->firmware_load); B43legacy_WARN_ON(!wl); + if (!wldev->fw.ucode) + return; /* NULL if fw never loaded */ if (wl->current_dev == wldev) ieee80211_unregister_hw(wl->hw); diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c index 4187435220f..4db878dfc36 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c @@ -764,8 +764,11 @@ static void brcmf_c_arp_offload_set(struct brcmf_pub *drvr, int arp_mode) { char iovbuf[32]; int retcode; + __le32 arp_mode_le; - brcmf_c_mkiovar("arp_ol", (char *)&arp_mode, 4, iovbuf, sizeof(iovbuf)); + arp_mode_le = cpu_to_le32(arp_mode); + brcmf_c_mkiovar("arp_ol", (char *)&arp_mode_le, 4, iovbuf, + sizeof(iovbuf)); retcode = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf, sizeof(iovbuf)); retcode = retcode >= 0 ? 0 : retcode; @@ -781,8 +784,11 @@ static void brcmf_c_arp_offload_enable(struct brcmf_pub *drvr, int arp_enable) { char iovbuf[32]; int retcode; + __le32 arp_enable_le; - brcmf_c_mkiovar("arpoe", (char *)&arp_enable, 4, + arp_enable_le = cpu_to_le32(arp_enable); + + brcmf_c_mkiovar("arpoe", (char *)&arp_enable_le, 4, iovbuf, sizeof(iovbuf)); retcode = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf, sizeof(iovbuf)); @@ -803,10 +809,10 @@ int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr) char buf[128], *ptr; u32 dongle_align = drvr->bus_if->align; u32 glom = 0; - u32 roaming = 1; - uint bcn_timeout = 3; - int scan_assoc_time = 40; - int scan_unassoc_time = 40; + __le32 roaming_le = cpu_to_le32(1); + __le32 bcn_timeout_le = cpu_to_le32(3); + __le32 scan_assoc_time_le = cpu_to_le32(40); + __le32 scan_unassoc_time_le = cpu_to_le32(40); int i; mutex_lock(&drvr->proto_block); @@ -841,14 +847,14 @@ int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr) /* Setup timeout if Beacons are lost and roam is off to report link down */ - brcmf_c_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf, + brcmf_c_mkiovar("bcn_timeout", (char *)&bcn_timeout_le, 4, iovbuf, sizeof(iovbuf)); brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf, sizeof(iovbuf)); /* Enable/Disable build-in roaming to allowed ext supplicant to take of romaing */ - brcmf_c_mkiovar("roam_off", (char *)&roaming, 4, + brcmf_c_mkiovar("roam_off", (char *)&roaming_le, 4, iovbuf, sizeof(iovbuf)); brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf, sizeof(iovbuf)); @@ -863,9 +869,9 @@ int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr) sizeof(iovbuf)); brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_SCAN_CHANNEL_TIME, - (char *)&scan_assoc_time, sizeof(scan_assoc_time)); + (char *)&scan_assoc_time_le, sizeof(scan_assoc_time_le)); brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_SCAN_UNASSOC_TIME, - (char *)&scan_unassoc_time, sizeof(scan_unassoc_time)); + (char *)&scan_unassoc_time_le, sizeof(scan_unassoc_time_le)); /* Set and enable ARP offload feature */ brcmf_c_arp_offload_set(drvr, BRCMF_ARPOL_MODE); diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index d13ae9c299f..e360939f790 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c @@ -500,8 +500,10 @@ static void wl_iscan_prep(struct brcmf_scan_params_le *params_le, params_le->active_time = cpu_to_le32(-1); params_le->passive_time = cpu_to_le32(-1); params_le->home_time = cpu_to_le32(-1); - if (ssid && ssid->SSID_len) - memcpy(¶ms_le->ssid_le, ssid, sizeof(struct brcmf_ssid)); + if (ssid && ssid->SSID_len) { + params_le->ssid_le.SSID_len = cpu_to_le32(ssid->SSID_len); + memcpy(¶ms_le->ssid_le.SSID, ssid->SSID, ssid->SSID_len); + } } static s32 diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c index 569ab8abd2a..27f37c7379d 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c @@ -1400,9 +1400,10 @@ void brcms_add_timer(struct brcms_timer *t, uint ms, int periodic) #endif t->ms = ms; t->periodic = (bool) periodic; - t->set = true; - - atomic_inc(&t->wl->callbacks); + if (!t->set) { + t->set = true; + atomic_inc(&t->wl->callbacks); + } ieee80211_queue_delayed_work(hw, &t->dly_wrk, msecs_to_jiffies(ms)); } diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index 3a6b991f023..3dd80dfdcfd 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c @@ -10471,7 +10471,7 @@ static void ipw_handle_promiscuous_tx(struct ipw_priv *priv, } else len = src->len; - dst = alloc_skb(len + sizeof(*rt_hdr), GFP_ATOMIC); + dst = alloc_skb(len + sizeof(*rt_hdr) + sizeof(u16)*2, GFP_ATOMIC); if (!dst) continue; diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c index c46275a9256..9aa48074ee2 100644 --- a/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/iwlegacy/4965-mac.c @@ -3405,7 +3405,7 @@ il4965_remove_dynamic_key(struct il_priv *il, return 0; } - if (il->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET) { + if (il->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_INVALID) { IL_WARN("Removing wrong key %d 0x%x\n", keyconf->keyidx, key_flags); spin_unlock_irqrestore(&il->sta_lock, flags); @@ -3420,7 +3420,7 @@ il4965_remove_dynamic_key(struct il_priv *il, memset(&il->stations[sta_id].sta.key, 0, sizeof(struct il4965_keyinfo)); il->stations[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC | STA_KEY_FLG_INVALID; - il->stations[sta_id].sta.key.key_offset = WEP_INVALID_OFFSET; + il->stations[sta_id].sta.key.key_offset = keyconf->hw_key_idx; il->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; il->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c index eaf249452e5..2ab6b968c5f 100644 --- a/drivers/net/wireless/iwlegacy/common.c +++ b/drivers/net/wireless/iwlegacy/common.c @@ -3957,17 +3957,21 @@ il_connection_init_rx_config(struct il_priv *il) memset(&il->staging, 0, sizeof(il->staging)); - if (!il->vif) { + switch (il->iw_mode) { + case NL80211_IFTYPE_UNSPECIFIED: il->staging.dev_type = RXON_DEV_TYPE_ESS; - } else if (il->vif->type == NL80211_IFTYPE_STATION) { + break; + case NL80211_IFTYPE_STATION: il->staging.dev_type = RXON_DEV_TYPE_ESS; il->staging.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK; - } else if (il->vif->type == NL80211_IFTYPE_ADHOC) { + break; + case NL80211_IFTYPE_ADHOC: il->staging.dev_type = RXON_DEV_TYPE_IBSS; il->staging.flags = RXON_FLG_SHORT_PREAMBLE_MSK; il->staging.filter_flags = RXON_FILTER_BCON_AWARE_MSK | RXON_FILTER_ACCEPT_GRP_MSK; - } else { + break; + default: IL_ERR("Unsupported interface type %d\n", il->vif->type); return; } @@ -4550,8 +4554,7 @@ il_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) EXPORT_SYMBOL(il_mac_add_interface); static void -il_teardown_interface(struct il_priv *il, struct ieee80211_vif *vif, - bool mode_change) +il_teardown_interface(struct il_priv *il, struct ieee80211_vif *vif) { lockdep_assert_held(&il->mutex); @@ -4560,9 +4563,7 @@ il_teardown_interface(struct il_priv *il, struct ieee80211_vif *vif, il_force_scan_end(il); } - if (!mode_change) - il_set_mode(il); - + il_set_mode(il); } void @@ -4575,8 +4576,8 @@ il_mac_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) WARN_ON(il->vif != vif); il->vif = NULL; - - il_teardown_interface(il, vif, false); + il->iw_mode = NL80211_IFTYPE_UNSPECIFIED; + il_teardown_interface(il, vif); memset(il->bssid, 0, ETH_ALEN); D_MAC80211("leave\n"); @@ -4685,18 +4686,10 @@ il_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, } /* success */ - il_teardown_interface(il, vif, true); vif->type = newtype; vif->p2p = false; - err = il_set_mode(il); - WARN_ON(err); - /* - * We've switched internally, but submitting to the - * device may have failed for some reason. Mask this - * error, because otherwise mac80211 will not switch - * (and set the interface type back) and we'll be - * out of sync with it. - */ + il->iw_mode = newtype; + il_teardown_interface(il, vif); err = 0; out: @@ -4767,14 +4760,12 @@ il_bg_watchdog(unsigned long data) return; /* monitor and check for other stuck queues */ - if (il_is_any_associated(il)) { - for (cnt = 0; cnt < il->hw_params.max_txq_num; cnt++) { - /* skip as we already checked the command queue */ - if (cnt == il->cmd_queue) - continue; - if (il_check_stuck_queue(il, cnt)) - return; - } + for (cnt = 0; cnt < il->hw_params.max_txq_num; cnt++) { + /* skip as we already checked the command queue */ + if (cnt == il->cmd_queue) + continue; + if (il_check_stuck_queue(il, cnt)) + return; } mod_timer(&il->watchdog, diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c index c0cfa4e652c..2067bdff83a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ b/drivers/net/wireless/iwlwifi/iwl-6000.c @@ -170,7 +170,7 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, * See iwlagn_mac_channel_switch. */ struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; - struct iwl6000_channel_switch_cmd cmd; + struct iwl6000_channel_switch_cmd *cmd; const struct iwl_channel_info *ch_info; u32 switch_time_in_usec, ucode_switch_time; u16 ch; @@ -180,18 +180,25 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, struct ieee80211_vif *vif = ctx->vif; struct iwl_host_cmd hcmd = { .id = REPLY_CHANNEL_SWITCH, - .len = { sizeof(cmd), }, + .len = { sizeof(*cmd), }, .flags = CMD_SYNC, - .data = { &cmd, }, + .dataflags[0] = IWL_HCMD_DFL_NOCOPY, }; + int err; - cmd.band = priv->band == IEEE80211_BAND_2GHZ; + cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); + if (!cmd) + return -ENOMEM; + + hcmd.data[0] = cmd; + + cmd->band = priv->band == IEEE80211_BAND_2GHZ; ch = ch_switch->channel->hw_value; IWL_DEBUG_11H(priv, "channel switch from %u to %u\n", ctx->active.channel, ch); - cmd.channel = cpu_to_le16(ch); - cmd.rxon_flags = ctx->staging.flags; - cmd.rxon_filter_flags = ctx->staging.filter_flags; + cmd->channel = cpu_to_le16(ch); + cmd->rxon_flags = ctx->staging.flags; + cmd->rxon_filter_flags = ctx->staging.filter_flags; switch_count = ch_switch->count; tsf_low = ch_switch->timestamp & 0x0ffffffff; /* @@ -207,30 +214,32 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv, switch_count = 0; } if (switch_count <= 1) - cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); + cmd->switch_time = cpu_to_le32(priv->ucode_beacon_time); else { switch_time_in_usec = vif->bss_conf.beacon_int * switch_count * TIME_UNIT; ucode_switch_time = iwl_usecs_to_beacons(priv, switch_time_in_usec, beacon_interval); - cmd.switch_time = iwl_add_beacon_time(priv, + cmd->switch_time = iwl_add_beacon_time(priv, priv->ucode_beacon_time, ucode_switch_time, beacon_interval); } IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n", - cmd.switch_time); + cmd->switch_time); ch_info = iwl_get_channel_info(priv, priv->band, ch); if (ch_info) - cmd.expect_beacon = is_channel_radar(ch_info); + cmd->expect_beacon = is_channel_radar(ch_info); else { IWL_ERR(priv, "invalid channel switch from %u to %u\n", ctx->active.channel, ch); return -EFAULT; } - return iwl_dvm_send_cmd(priv, &hcmd); + err = iwl_dvm_send_cmd(priv, &hcmd); + kfree(cmd); + return err; } static struct iwl_lib_ops iwl6000_lib = { diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index da2be3e09ee..7db5d45da23 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c @@ -709,11 +709,14 @@ static int rs_toggle_antenna(u32 valid_ant, u32 *rate_n_flags, */ static bool rs_use_green(struct ieee80211_sta *sta) { - struct iwl_station_priv *sta_priv = (void *)sta->drv_priv; - struct iwl_rxon_context *ctx = sta_priv->ctx; - - return (sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD) && - !(ctx->ht.non_gf_sta_present); + /* + * There's a bug somewhere in this code that causes the + * scaling to get stuck because GF+SGI can't be combined + * in SISO rates. Until we find that bug, disable GF, it + * has only limited benefit and we still interoperate with + * GF APs since we can always receive GF transmissions. + */ + return false; } /** diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c index bef3f242434..8be535f8f6d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-sta.c @@ -191,6 +191,7 @@ static void iwl_sta_calc_ht_flags(struct iwl_priv *priv, mimo_ps_mode = (sta_ht_inf->cap & IEEE80211_HT_CAP_SM_PS) >> 2; IWL_DEBUG_INFO(priv, "STA %pM SM PS mode: %s\n", + sta->addr, (mimo_ps_mode == WLAN_HT_CAP_SM_PS_STATIC) ? "static" : (mimo_ps_mode == WLAN_HT_CAP_SM_PS_DYNAMIC) ? diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index baf691949c3..03560a8a858 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -544,9 +544,9 @@ mwifiex_dump_station_info(struct mwifiex_private *priv, /* * Bit 0 in tx_htinfo indicates that current Tx rate is 11n rate. Valid - * MCS index values for us are 0 to 7. + * MCS index values for us are 0 to 15. */ - if ((priv->tx_htinfo & BIT(0)) && (priv->tx_rate < 8)) { + if ((priv->tx_htinfo & BIT(0)) && (priv->tx_rate < 16)) { sinfo->txrate.mcs = priv->tx_rate; sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS; /* 40MHz rate */ diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c index 07f6e009255..2977a12410c 100644 --- a/drivers/net/wireless/mwifiex/cmdevt.c +++ b/drivers/net/wireless/mwifiex/cmdevt.c @@ -816,9 +816,6 @@ mwifiex_cmd_timeout_func(unsigned long function_context) return; } cmd_node = adapter->curr_cmd; - if (cmd_node->wait_q_enabled) - adapter->cmd_wait_q.status = -ETIMEDOUT; - if (cmd_node) { adapter->dbg.timeout_cmd_id = adapter->dbg.last_cmd_id[adapter->dbg.last_cmd_index]; @@ -864,6 +861,14 @@ mwifiex_cmd_timeout_func(unsigned long function_context) dev_err(adapter->dev, "ps_mode=%d ps_state=%d\n", adapter->ps_mode, adapter->ps_state); + + if (cmd_node->wait_q_enabled) { + adapter->cmd_wait_q.status = -ETIMEDOUT; + wake_up_interruptible(&adapter->cmd_wait_q.wait); + mwifiex_cancel_pending_ioctl(adapter); + /* reset cmd_sent flag to unblock new commands */ + adapter->cmd_sent = false; + } } if (adapter->hw_status == MWIFIEX_HW_STATUS_INITIALIZING) mwifiex_init_fw_complete(adapter); diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c index 5867facd415..6ca3d8a3e0e 100644 --- a/drivers/net/wireless/mwifiex/pcie.c +++ b/drivers/net/wireless/mwifiex/pcie.c @@ -158,7 +158,7 @@ static int mwifiex_pcie_suspend(struct pci_dev *pdev, pm_message_t state) if (pdev) { card = (struct pcie_service_card *) pci_get_drvdata(pdev); - if (!card || card->adapter) { + if (!card || !card->adapter) { pr_err("Card or adapter structure is not valid\n"); return 0; } diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c index f8012e2b7f7..7d00a87e9a1 100644 --- a/drivers/net/wireless/mwifiex/sdio.c +++ b/drivers/net/wireless/mwifiex/sdio.c @@ -158,7 +158,6 @@ static int mwifiex_sdio_suspend(struct device *dev) struct sdio_mmc_card *card; struct mwifiex_adapter *adapter; mmc_pm_flag_t pm_flag = 0; - int hs_actived = 0; int i; int ret = 0; @@ -185,12 +184,14 @@ static int mwifiex_sdio_suspend(struct device *dev) adapter = card->adapter; /* Enable the Host Sleep */ - hs_actived = mwifiex_enable_hs(adapter); - if (hs_actived) { - pr_debug("cmd: suspend with MMC_PM_KEEP_POWER\n"); - ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); + if (!mwifiex_enable_hs(adapter)) { + dev_err(adapter->dev, "cmd: failed to suspend\n"); + return -EFAULT; } + dev_dbg(adapter->dev, "cmd: suspend with MMC_PM_KEEP_POWER\n"); + ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); + /* Indicate device suspended */ adapter->is_suspended = true; diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index d7b11defafe..4fb146a8fac 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c @@ -53,7 +53,6 @@ int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist, */ int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter) { - bool cancel_flag = false; int status; struct cmd_ctrl_node *cmd_queued; @@ -70,14 +69,11 @@ int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter) queue_work(adapter->workqueue, &adapter->main_work); /* Wait for completion */ - wait_event_interruptible(adapter->cmd_wait_q.wait, - *(cmd_queued->condition)); - if (!*(cmd_queued->condition)) - cancel_flag = true; - - if (cancel_flag) { - mwifiex_cancel_pending_ioctl(adapter); - dev_dbg(adapter->dev, "cmd cancel\n"); + status = wait_event_interruptible(adapter->cmd_wait_q.wait, + *(cmd_queued->condition)); + if (status) { + dev_err(adapter->dev, "cmd_wait_q terminated: %d\n", status); + return status; } status = adapter->cmd_wait_q.status; @@ -436,8 +432,11 @@ int mwifiex_enable_hs(struct mwifiex_adapter *adapter) return false; } - wait_event_interruptible(adapter->hs_activate_wait_q, - adapter->hs_activate_wait_q_woken); + if (wait_event_interruptible(adapter->hs_activate_wait_q, + adapter->hs_activate_wait_q_woken)) { + dev_err(adapter->dev, "hs_activate_wait_q terminated\n"); + return false; + } return true; } diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index f4d28c39aac..be20cf765bc 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c @@ -42,11 +42,12 @@ MODULE_FIRMWARE("isl3887usb"); * whenever you add a new device. */ -static struct usb_device_id p54u_table[] __devinitdata = { +static struct usb_device_id p54u_table[] = { /* Version 1 devices (pci chip + net2280) */ {USB_DEVICE(0x0411, 0x0050)}, /* Buffalo WLI2-USB2-G54 */ {USB_DEVICE(0x045e, 0x00c2)}, /* Microsoft MN-710 */ {USB_DEVICE(0x0506, 0x0a11)}, /* 3COM 3CRWE254G72 */ + {USB_DEVICE(0x0675, 0x0530)}, /* DrayTek Vigor 530 */ {USB_DEVICE(0x06b9, 0x0120)}, /* Thomson SpeedTouch 120g */ {USB_DEVICE(0x0707, 0xee06)}, /* SMC 2862W-G */ {USB_DEVICE(0x07aa, 0x001c)}, /* Corega CG-WLUSB2GT */ @@ -82,6 +83,8 @@ static struct usb_device_id p54u_table[] __devinitdata = { {USB_DEVICE(0x06a9, 0x000e)}, /* Westell 802.11g USB (A90-211WG-01) */ {USB_DEVICE(0x06b9, 0x0121)}, /* Thomson SpeedTouch 121g */ {USB_DEVICE(0x0707, 0xee13)}, /* SMC 2862W-G version 2 */ + {USB_DEVICE(0x0803, 0x4310)}, /* Zoom 4410a */ + {USB_DEVICE(0x083a, 0x4503)}, /* T-Com Sinus 154 data II */ {USB_DEVICE(0x083a, 0x4521)}, /* Siemens Gigaset USB Adapter 54 version 2 */ {USB_DEVICE(0x083a, 0xc501)}, /* Zoom Wireless-G 4410 */ {USB_DEVICE(0x083a, 0xf503)}, /* Accton FD7050E ver 1010ec */ @@ -101,6 +104,7 @@ static struct usb_device_id p54u_table[] __devinitdata = { {USB_DEVICE(0x13B1, 0x000C)}, /* Linksys WUSB54AG */ {USB_DEVICE(0x1413, 0x5400)}, /* Telsey 802.11g USB2.0 Adapter */ {USB_DEVICE(0x1435, 0x0427)}, /* Inventel UR054G */ + /* {USB_DEVICE(0x15a9, 0x0002)}, * Also SparkLAN WL-682 with 3887 */ {USB_DEVICE(0x1668, 0x1050)}, /* Actiontec 802UIG-1 */ {USB_DEVICE(0x1740, 0x1000)}, /* Senao NUB-350 */ {USB_DEVICE(0x2001, 0x3704)}, /* DLink DWL-G122 rev A2 */ diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 3a6b40239bc..0ea85f46659 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1611,6 +1611,7 @@ static int rt2400pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; + u32 reg; /* * Allocate eeprom data. @@ -1623,6 +1624,14 @@ static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev) if (retval) return retval; + /* + * Enable rfkill polling by setting GPIO direction of the + * rfkill switch GPIO pin correctly. + */ + rt2x00pci_register_read(rt2x00dev, GPIOCSR, ®); + rt2x00_set_field32(®, GPIOCSR_BIT8, 1); + rt2x00pci_register_write(rt2x00dev, GPIOCSR, reg); + /* * Initialize hw specifications. */ diff --git a/drivers/net/wireless/rt2x00/rt2400pci.h b/drivers/net/wireless/rt2x00/rt2400pci.h index d3a4a68cc43..7564ae992b7 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.h +++ b/drivers/net/wireless/rt2x00/rt2400pci.h @@ -670,6 +670,7 @@ #define GPIOCSR_BIT5 FIELD32(0x00000020) #define GPIOCSR_BIT6 FIELD32(0x00000040) #define GPIOCSR_BIT7 FIELD32(0x00000080) +#define GPIOCSR_BIT8 FIELD32(0x00000100) /* * BBPPCSR: BBP Pin control register. diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c index dcc0e1fcca7..aa10c48c0df 100644 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ b/drivers/net/wireless/rt2x00/rt2500pci.c @@ -1929,6 +1929,7 @@ static int rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; + u32 reg; /* * Allocate eeprom data. @@ -1941,6 +1942,14 @@ static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev) if (retval) return retval; + /* + * Enable rfkill polling by setting GPIO direction of the + * rfkill switch GPIO pin correctly. + */ + rt2x00pci_register_read(rt2x00dev, GPIOCSR, ®); + rt2x00_set_field32(®, GPIOCSR_DIR0, 1); + rt2x00pci_register_write(rt2x00dev, GPIOCSR, reg); + /* * Initialize hw specifications. */ diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index 1de9c752c88..e0a7efccb73 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c @@ -283,7 +283,7 @@ static int rt2500usb_rfkill_poll(struct rt2x00_dev *rt2x00dev) u16 reg; rt2500usb_register_read(rt2x00dev, MAC_CSR19, ®); - return rt2x00_get_field32(reg, MAC_CSR19_BIT7); + return rt2x00_get_field16(reg, MAC_CSR19_BIT7); } #ifdef CONFIG_RT2X00_LIB_LEDS @@ -1768,6 +1768,7 @@ static int rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; + u16 reg; /* * Allocate eeprom data. @@ -1780,6 +1781,14 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev) if (retval) return retval; + /* + * Enable rfkill polling by setting GPIO direction of the + * rfkill switch GPIO pin correctly. + */ + rt2500usb_register_read(rt2x00dev, MAC_CSR19, ®); + rt2x00_set_field16(®, MAC_CSR19_BIT8, 0); + rt2500usb_register_write(rt2x00dev, MAC_CSR19, reg); + /* * Initialize hw specifications. */ diff --git a/drivers/net/wireless/rt2x00/rt2500usb.h b/drivers/net/wireless/rt2x00/rt2500usb.h index b493306a7ee..196bd5103e4 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.h +++ b/drivers/net/wireless/rt2x00/rt2500usb.h @@ -189,14 +189,15 @@ * MAC_CSR19: GPIO control register. */ #define MAC_CSR19 0x0426 -#define MAC_CSR19_BIT0 FIELD32(0x0001) -#define MAC_CSR19_BIT1 FIELD32(0x0002) -#define MAC_CSR19_BIT2 FIELD32(0x0004) -#define MAC_CSR19_BIT3 FIELD32(0x0008) -#define MAC_CSR19_BIT4 FIELD32(0x0010) -#define MAC_CSR19_BIT5 FIELD32(0x0020) -#define MAC_CSR19_BIT6 FIELD32(0x0040) -#define MAC_CSR19_BIT7 FIELD32(0x0080) +#define MAC_CSR19_BIT0 FIELD16(0x0001) +#define MAC_CSR19_BIT1 FIELD16(0x0002) +#define MAC_CSR19_BIT2 FIELD16(0x0004) +#define MAC_CSR19_BIT3 FIELD16(0x0008) +#define MAC_CSR19_BIT4 FIELD16(0x0010) +#define MAC_CSR19_BIT5 FIELD16(0x0020) +#define MAC_CSR19_BIT6 FIELD16(0x0040) +#define MAC_CSR19_BIT7 FIELD16(0x0080) +#define MAC_CSR19_BIT8 FIELD16(0x0100) /* * MAC_CSR20: LED control register. diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 6c0a12ea6a1..2ce6bf5b671 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -2235,7 +2235,7 @@ static int rt2800_get_gain_calibration_delta(struct rt2x00_dev *rt2x00dev) /* * Check if temperature compensation is supported. */ - if (tssi_bounds[4] == 0xff) + if (tssi_bounds[4] == 0xff || step == 0xff) return 0; /* diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 0397bbf0ce0..ff81e761d20 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -973,6 +973,7 @@ static int rt2800pci_validate_eeprom(struct rt2x00_dev *rt2x00dev) static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; + u32 reg; /* * Allocate eeprom data. @@ -985,6 +986,14 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev) if (retval) return retval; + /* + * Enable rfkill polling by setting GPIO direction of the + * rfkill switch GPIO pin correctly. + */ + rt2x00pci_register_read(rt2x00dev, GPIO_CTRL_CFG, ®); + rt2x00_set_field32(®, GPIO_CTRL_CFG_GPIOD_BIT2, 1); + rt2x00pci_register_write(rt2x00dev, GPIO_CTRL_CFG, reg); + /* * Initialize hw specifications. */ diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 5601302d09a..65cb4250259 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -667,8 +667,16 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry, skb_pull(entry->skb, RXINFO_DESC_SIZE); /* - * FIXME: we need to check for rx_pkt_len validity + * Check for rx_pkt_len validity. Return if invalid, leaving + * rxdesc->size zeroed out by the upper level. */ + if (unlikely(rx_pkt_len == 0 || + rx_pkt_len > entry->queue->data_size)) { + ERROR(entry->queue->rt2x00dev, + "Bad frame size %d, forcing to 0\n", rx_pkt_len); + return; + } + rxd = (__le32 *)(entry->skb->data + rx_pkt_len); /* @@ -736,6 +744,7 @@ static int rt2800usb_validate_eeprom(struct rt2x00_dev *rt2x00dev) static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; + u32 reg; /* * Allocate eeprom data. @@ -748,6 +757,14 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev) if (retval) return retval; + /* + * Enable rfkill polling by setting GPIO direction of the + * rfkill switch GPIO pin correctly. + */ + rt2x00usb_register_read(rt2x00dev, GPIO_CTRL_CFG, ®); + rt2x00_set_field32(®, GPIO_CTRL_CFG_GPIOD_BIT2, 1); + rt2x00usb_register_write(rt2x00dev, GPIO_CTRL_CFG, reg); + /* * Initialize hw specifications. */ @@ -971,6 +988,7 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x0411, 0x015d) }, { USB_DEVICE(0x0411, 0x016f) }, { USB_DEVICE(0x0411, 0x01a2) }, + { USB_DEVICE(0x0411, 0x01ee) }, /* Corega */ { USB_DEVICE(0x07aa, 0x002f) }, { USB_DEVICE(0x07aa, 0x003c) }, @@ -1137,6 +1155,8 @@ static struct usb_device_id rt2800usb_device_table[] = { #ifdef CONFIG_RT2800USB_RT33XX /* Belkin */ { USB_DEVICE(0x050d, 0x945b) }, + /* D-Link */ + { USB_DEVICE(0x2001, 0x3c17) }, /* Panasonic */ { USB_DEVICE(0x083a, 0xb511) }, /* Philips */ @@ -1154,6 +1174,8 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x1690, 0x0744) }, { USB_DEVICE(0x1690, 0x0761) }, { USB_DEVICE(0x1690, 0x0764) }, + /* ASUS */ + { USB_DEVICE(0x0b05, 0x179d) }, /* Cisco */ { USB_DEVICE(0x167b, 0x4001) }, /* EnGenius */ @@ -1219,7 +1241,6 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x0b05, 0x1760) }, { USB_DEVICE(0x0b05, 0x1761) }, { USB_DEVICE(0x0b05, 0x1790) }, - { USB_DEVICE(0x0b05, 0x179d) }, /* AzureWave */ { USB_DEVICE(0x13d3, 0x3262) }, { USB_DEVICE(0x13d3, 0x3284) }, @@ -1237,7 +1258,6 @@ static struct usb_device_id rt2800usb_device_table[] = { /* D-Link */ { USB_DEVICE(0x07d1, 0x3c0b) }, { USB_DEVICE(0x07d1, 0x3c17) }, - { USB_DEVICE(0x2001, 0x3c17) }, /* Encore */ { USB_DEVICE(0x203d, 0x14a1) }, /* Gemtek */ diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 90cc5e77265..12b1ff5a6a3 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -628,7 +628,7 @@ void rt2x00lib_rxdone(struct queue_entry *entry) */ if (unlikely(rxdesc.size == 0 || rxdesc.size > entry->queue->data_size)) { - WARNING(rt2x00dev, "Wrong frame size %d max %d.\n", + ERROR(rt2x00dev, "Wrong frame size %d max %d.\n", rxdesc.size, entry->queue->data_size); dev_kfree_skb(entry->skb); goto renew_skb; diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 66094eb21b6..507085facb8 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -436,8 +436,8 @@ void rt2x00usb_kick_queue(struct data_queue *queue) case QID_RX: if (!rt2x00queue_full(queue)) rt2x00queue_for_each_entry(queue, - Q_INDEX_DONE, Q_INDEX, + Q_INDEX_DONE, NULL, rt2x00usb_kick_rx_entry); break; diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index e0c6d117429..bdaba3fddd9 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -2243,8 +2243,7 @@ static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev) static void rt61pci_wakeup(struct rt2x00_dev *rt2x00dev) { - struct ieee80211_conf conf = { .flags = 0 }; - struct rt2x00lib_conf libconf = { .conf = &conf }; + struct rt2x00lib_conf libconf = { .conf = &rt2x00dev->hw->conf }; rt61pci_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS); } @@ -2833,6 +2832,7 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; + u32 reg; /* * Disable power saving. @@ -2850,6 +2850,14 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev) if (retval) return retval; + /* + * Enable rfkill polling by setting GPIO direction of the + * rfkill switch GPIO pin correctly. + */ + rt2x00pci_register_read(rt2x00dev, MAC_CSR13, ®); + rt2x00_set_field32(®, MAC_CSR13_BIT13, 1); + rt2x00pci_register_write(rt2x00dev, MAC_CSR13, reg); + /* * Initialize hw specifications. */ diff --git a/drivers/net/wireless/rt2x00/rt61pci.h b/drivers/net/wireless/rt2x00/rt61pci.h index e3cd6db76b0..8f3da5a5676 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.h +++ b/drivers/net/wireless/rt2x00/rt61pci.h @@ -372,6 +372,7 @@ struct hw_pairwise_ta_entry { #define MAC_CSR13_BIT10 FIELD32(0x00000400) #define MAC_CSR13_BIT11 FIELD32(0x00000800) #define MAC_CSR13_BIT12 FIELD32(0x00001000) +#define MAC_CSR13_BIT13 FIELD32(0x00002000) /* * MAC_CSR14: LED control register. diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index e477a964081..fda8671474d 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -2177,6 +2177,7 @@ static int rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev) { int retval; + u32 reg; /* * Allocate eeprom data. @@ -2189,6 +2190,14 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev) if (retval) return retval; + /* + * Enable rfkill polling by setting GPIO direction of the + * rfkill switch GPIO pin correctly. + */ + rt2x00usb_register_read(rt2x00dev, MAC_CSR13, ®); + rt2x00_set_field32(®, MAC_CSR13_BIT15, 0); + rt2x00usb_register_write(rt2x00dev, MAC_CSR13, reg); + /* * Initialize hw specifications. */ diff --git a/drivers/net/wireless/rt2x00/rt73usb.h b/drivers/net/wireless/rt2x00/rt73usb.h index 9f6b470414d..df1cc116b83 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.h +++ b/drivers/net/wireless/rt2x00/rt73usb.h @@ -282,6 +282,9 @@ struct hw_pairwise_ta_entry { #define MAC_CSR13_BIT10 FIELD32(0x00000400) #define MAC_CSR13_BIT11 FIELD32(0x00000800) #define MAC_CSR13_BIT12 FIELD32(0x00001000) +#define MAC_CSR13_BIT13 FIELD32(0x00002000) +#define MAC_CSR13_BIT14 FIELD32(0x00004000) +#define MAC_CSR13_BIT15 FIELD32(0x00008000) /* * MAC_CSR14: LED control register. diff --git a/drivers/net/wireless/rtl818x/rtl8187/dev.c b/drivers/net/wireless/rtl818x/rtl8187/dev.c index cf53ac9d6f2..86467a20c5b 100644 --- a/drivers/net/wireless/rtl818x/rtl8187/dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187/dev.c @@ -44,7 +44,7 @@ MODULE_AUTHOR("Larry Finger "); MODULE_DESCRIPTION("RTL8187/RTL8187B USB wireless driver"); MODULE_LICENSE("GPL"); -static struct usb_device_id rtl8187_table[] __devinitdata = { +static struct usb_device_id rtl8187_table[] = { /* Asus */ {USB_DEVICE(0x0b05, 0x171d), .driver_info = DEVICE_RTL8187}, /* Belkin */ diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/def.h b/drivers/net/wireless/rtlwifi/rtl8192ce/def.h index 04c3aef8a4f..2925094b2d9 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/def.h +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/def.h @@ -117,6 +117,7 @@ #define CHIP_VER_B BIT(4) #define CHIP_92C_BITMASK BIT(0) +#define CHIP_UNKNOWN BIT(7) #define CHIP_92C_1T2R 0x03 #define CHIP_92C 0x01 #define CHIP_88C 0x00 diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c index 5c4d9bc040f..509f66195f2 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c @@ -995,8 +995,16 @@ static enum version_8192c _rtl92ce_read_chip_version(struct ieee80211_hw *hw) version = (value32 & TYPE_ID) ? VERSION_A_CHIP_92C : VERSION_A_CHIP_88C; } else { - version = (value32 & TYPE_ID) ? VERSION_B_CHIP_92C : - VERSION_B_CHIP_88C; + version = (enum version_8192c) (CHIP_VER_B | + ((value32 & TYPE_ID) ? CHIP_92C_BITMASK : 0) | + ((value32 & VENDOR_ID) ? CHIP_VENDOR_UMC : 0)); + if ((!IS_CHIP_VENDOR_UMC(version)) && (value32 & + CHIP_VER_RTL_MASK)) { + version = (enum version_8192c)(version | + ((((value32 & CHIP_VER_RTL_MASK) == BIT(12)) + ? CHIP_VENDOR_UMC_B_CUT : CHIP_UNKNOWN) | + CHIP_VENDOR_UMC)); + } } switch (version) { diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c index 2c3b73366cd..4e2a45839ed 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c @@ -162,10 +162,12 @@ int rtl92c_init_sw_vars(struct ieee80211_hw *hw) /* request fw */ if (IS_VENDOR_UMC_A_CUT(rtlhal->version) && - !IS_92C_SERIAL(rtlhal->version)) + !IS_92C_SERIAL(rtlhal->version)) { rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cfwU.bin"; - else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version)) + } else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version)) { rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cfwU_B.bin"; + pr_info("****** This B_CUT device may not work with kernels 3.6 and earlier\n"); + } rtlpriv->max_fw_size = 0x4000; pr_info("Using firmware %s\n", rtlpriv->cfg->fw_name); diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c index 5bd40856635..61e57689a05 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c @@ -297,6 +297,7 @@ static struct usb_device_id rtl8192c_usb_ids[] = { /*=== Customer ID ===*/ /****** 8188CU ********/ {RTL_USB_DEVICE(0x050d, 0x1102, rtl92cu_hal_cfg)}, /*Belkin - Edimax*/ + {RTL_USB_DEVICE(0x050d, 0x11f2, rtl92cu_hal_cfg)}, /*Belkin - ISY*/ {RTL_USB_DEVICE(0x06f8, 0xe033, rtl92cu_hal_cfg)}, /*Hercules - Edimax*/ {RTL_USB_DEVICE(0x07b8, 0x8188, rtl92cu_hal_cfg)}, /*Abocom - Abocom*/ {RTL_USB_DEVICE(0x07b8, 0x8189, rtl92cu_hal_cfg)}, /*Funai - Abocom*/ diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/phy.c b/drivers/net/wireless/rtlwifi/rtl8192de/phy.c index 28fc5fb8057..46f7917fed5 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/phy.c +++ b/drivers/net/wireless/rtlwifi/rtl8192de/phy.c @@ -3344,21 +3344,21 @@ void rtl92d_phy_config_macphymode_info(struct ieee80211_hw *hw) switch (rtlhal->macphymode) { case DUALMAC_SINGLEPHY: rtlphy->rf_type = RF_2T2R; - rtlhal->version |= CHIP_92D_SINGLEPHY; + rtlhal->version |= RF_TYPE_2T2R; rtlhal->bandset = BAND_ON_BOTH; rtlhal->current_bandtype = BAND_ON_2_4G; break; case SINGLEMAC_SINGLEPHY: rtlphy->rf_type = RF_2T2R; - rtlhal->version |= CHIP_92D_SINGLEPHY; + rtlhal->version |= RF_TYPE_2T2R; rtlhal->bandset = BAND_ON_BOTH; rtlhal->current_bandtype = BAND_ON_2_4G; break; case DUALMAC_DUALPHY: rtlphy->rf_type = RF_1T1R; - rtlhal->version &= (~CHIP_92D_SINGLEPHY); + rtlhal->version &= RF_TYPE_1T1R; /* Now we let MAC0 run on 5G band. */ if (rtlhal->interfaceindex == 0) { rtlhal->bandset = BAND_ON_5G; diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/phy.c b/drivers/net/wireless/rtlwifi/rtl8192se/phy.c index 4a499928e4c..a2a5c92a180 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/phy.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/phy.c @@ -1247,6 +1247,9 @@ static void _rtl92s_phy_get_txpower_index(struct ieee80211_hw *hw, u8 channel, /* Read HT 40 OFDM TX power */ ofdmpowerLevel[0] = rtlefuse->txpwrlevel_ht40_2s[0][index]; ofdmpowerLevel[1] = rtlefuse->txpwrlevel_ht40_2s[1][index]; + } else { + ofdmpowerLevel[0] = 0; + ofdmpowerLevel[1] = 0; } } diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c index a6049d7d51b..8fa144fa0c9 100644 --- a/drivers/net/wireless/rtlwifi/usb.c +++ b/drivers/net/wireless/rtlwifi/usb.c @@ -131,15 +131,19 @@ static u32 _usb_read_sync(struct rtl_priv *rtlpriv, u32 addr, u16 len) u8 request; u16 wvalue; u16 index; - __le32 *data = &rtlpriv->usb_data[rtlpriv->usb_data_index]; + __le32 *data; + unsigned long flags; + spin_lock_irqsave(&rtlpriv->locks.usb_lock, flags); + if (++rtlpriv->usb_data_index >= RTL_USB_MAX_RX_COUNT) + rtlpriv->usb_data_index = 0; + data = &rtlpriv->usb_data[rtlpriv->usb_data_index]; + spin_unlock_irqrestore(&rtlpriv->locks.usb_lock, flags); request = REALTEK_USB_VENQT_CMD_REQ; index = REALTEK_USB_VENQT_CMD_IDX; /* n/a */ wvalue = (u16)addr; _usbctrl_vendorreq_sync_read(udev, request, wvalue, index, data, len); - if (++rtlpriv->usb_data_index >= RTL_USB_MAX_RX_COUNT) - rtlpriv->usb_data_index = 0; return le32_to_cpu(*data); } @@ -206,17 +210,16 @@ static void _usb_writeN_sync(struct rtl_priv *rtlpriv, u32 addr, void *data, u16 index = REALTEK_USB_VENQT_CMD_IDX; int pipe = usb_sndctrlpipe(udev, 0); /* write_out */ u8 *buffer; - dma_addr_t dma_addr; - wvalue = (u16)(addr&0x0000ffff); - buffer = usb_alloc_coherent(udev, (size_t)len, GFP_ATOMIC, &dma_addr); + wvalue = (u16)(addr & 0x0000ffff); + buffer = kmalloc(len, GFP_ATOMIC); if (!buffer) return; memcpy(buffer, data, len); usb_control_msg(udev, pipe, request, reqtype, wvalue, index, buffer, len, 50); - usb_free_coherent(udev, (size_t)len, buffer, dma_addr); + kfree(buffer); } static void _rtl_usb_io_handler_init(struct device *dev, @@ -951,6 +954,10 @@ int __devinit rtl_usb_probe(struct usb_interface *intf, GFP_KERNEL); if (!rtlpriv->usb_data) return -ENOMEM; + + /* this spin lock must be initialized early */ + spin_lock_init(&rtlpriv->locks.usb_lock); + rtlpriv->usb_data_index = 0; init_completion(&rtlpriv->firmware_loading_complete); SET_IEEE80211_DEV(hw, &intf->dev); diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h index 28ebc69218a..717d3bad17d 100644 --- a/drivers/net/wireless/rtlwifi/wifi.h +++ b/drivers/net/wireless/rtlwifi/wifi.h @@ -1555,6 +1555,7 @@ struct rtl_locks { spinlock_t rf_ps_lock; spinlock_t rf_lock; spinlock_t waitq_lock; + spinlock_t usb_lock; /*Dual mac*/ spinlock_t cck_and_rw_pagea_lock; diff --git a/drivers/nfc/pn533.c b/drivers/nfc/pn533.c index cb6204f7830..692bd1e8d6b 100644 --- a/drivers/nfc/pn533.c +++ b/drivers/nfc/pn533.c @@ -1278,11 +1278,14 @@ static void pn533_deactivate_target(struct nfc_dev *nfc_dev, u32 target_idx) static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg, u8 *params, int params_len) { - struct pn533_cmd_jump_dep *cmd; struct pn533_cmd_jump_dep_response *resp; struct nfc_target nfc_target; u8 target_gt_len; int rc; + struct pn533_cmd_jump_dep *cmd = (struct pn533_cmd_jump_dep *)arg; + u8 active = cmd->active; + + kfree(arg); if (params_len == -ENOENT) { nfc_dev_dbg(&dev->interface->dev, ""); @@ -1304,7 +1307,6 @@ static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg, } resp = (struct pn533_cmd_jump_dep_response *) params; - cmd = (struct pn533_cmd_jump_dep *) arg; rc = resp->status & PN533_CMD_RET_MASK; if (rc != PN533_CMD_RET_SUCCESS) { nfc_dev_err(&dev->interface->dev, @@ -1334,7 +1336,7 @@ static int pn533_in_dep_link_up_complete(struct pn533 *dev, void *arg, if (rc == 0) rc = nfc_dep_link_is_up(dev->nfc_dev, dev->nfc_dev->targets[0].idx, - !cmd->active, NFC_RF_INITIATOR); + !active, NFC_RF_INITIATOR); return 0; } @@ -1385,12 +1387,8 @@ static int pn533_dep_link_up(struct nfc_dev *nfc_dev, int target_idx, rc = pn533_send_cmd_frame_async(dev, dev->out_frame, dev->in_frame, dev->in_maxlen, pn533_in_dep_link_up_complete, cmd, GFP_KERNEL); - if (rc) - goto out; - - -out: - kfree(cmd); + if (rc < 0) + kfree(cmd); return rc; } diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 806c44fa645..09bf3772184 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -132,6 +132,15 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) if (!acpi_pci_check_ejectable(pbus, handle) && !is_dock_device(handle)) return AE_OK; + status = acpi_evaluate_integer(handle, "_ADR", NULL, &adr); + if (ACPI_FAILURE(status)) { + warn("can't evaluate _ADR (%#x)\n", status); + return AE_OK; + } + + device = (adr >> 16) & 0xffff; + function = adr & 0xffff; + pdev = pbus->self; if (pdev && pci_is_pcie(pdev)) { tmp = acpi_find_root_bridge_handle(pdev); @@ -144,10 +153,6 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) } } - acpi_evaluate_integer(handle, "_ADR", NULL, &adr); - device = (adr >> 16) & 0xffff; - function = adr & 0xffff; - newfunc = kzalloc(sizeof(struct acpiphp_func), GFP_KERNEL); if (!newfunc) return AE_NO_MEMORY; diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index 4b7cce1de6e..a321b77a5e8 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -44,7 +44,6 @@ extern bool pciehp_poll_mode; extern int pciehp_poll_time; extern bool pciehp_debug; extern bool pciehp_force; -extern struct workqueue_struct *pciehp_wq; #define dbg(format, arg...) \ do { \ @@ -78,6 +77,7 @@ struct slot { struct hotplug_slot *hotplug_slot; struct delayed_work work; /* work for button event */ struct mutex lock; + struct workqueue_struct *wq; }; struct event_info { diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index 365c6b96c64..9e39df96956 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c @@ -42,7 +42,6 @@ bool pciehp_debug; bool pciehp_poll_mode; int pciehp_poll_time; bool pciehp_force; -struct workqueue_struct *pciehp_wq; #define DRIVER_VERSION "0.4" #define DRIVER_AUTHOR "Dan Zink , Greg Kroah-Hartman , Dely Sy " @@ -340,18 +339,13 @@ static int __init pcied_init(void) { int retval = 0; - pciehp_wq = alloc_workqueue("pciehp", 0, 0); - if (!pciehp_wq) - return -ENOMEM; - pciehp_firmware_init(); retval = pcie_port_service_register(&hpdriver_portdrv); dbg("pcie_port_service_register = %d\n", retval); info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); - if (retval) { - destroy_workqueue(pciehp_wq); + if (retval) dbg("Failure to register service\n"); - } + return retval; } @@ -359,7 +353,6 @@ static void __exit pcied_cleanup(void) { dbg("unload_pciehpd()\n"); pcie_port_service_unregister(&hpdriver_portdrv); - destroy_workqueue(pciehp_wq); info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n"); } diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index 27f44295a65..38f01867917 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c @@ -49,7 +49,7 @@ static int queue_interrupt_event(struct slot *p_slot, u32 event_type) info->p_slot = p_slot; INIT_WORK(&info->work, interrupt_event_handler); - queue_work(pciehp_wq, &info->work); + queue_work(p_slot->wq, &info->work); return 0; } @@ -344,7 +344,7 @@ void pciehp_queue_pushbutton_work(struct work_struct *work) kfree(info); goto out; } - queue_work(pciehp_wq, &info->work); + queue_work(p_slot->wq, &info->work); out: mutex_unlock(&p_slot->lock); } @@ -377,7 +377,7 @@ static void handle_button_press_event(struct slot *p_slot) if (ATTN_LED(ctrl)) pciehp_set_attention_status(p_slot, 0); - queue_delayed_work(pciehp_wq, &p_slot->work, 5*HZ); + queue_delayed_work(p_slot->wq, &p_slot->work, 5*HZ); break; case BLINKINGOFF_STATE: case BLINKINGON_STATE: @@ -439,7 +439,7 @@ static void handle_surprise_event(struct slot *p_slot) else p_slot->state = POWERON_STATE; - queue_work(pciehp_wq, &info->work); + queue_work(p_slot->wq, &info->work); } static void interrupt_event_handler(struct work_struct *work) diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index a960faec102..9dd2c01a2e1 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -874,23 +874,32 @@ static void pcie_shutdown_notification(struct controller *ctrl) static int pcie_init_slot(struct controller *ctrl) { struct slot *slot; + char name[32]; slot = kzalloc(sizeof(*slot), GFP_KERNEL); if (!slot) return -ENOMEM; + snprintf(name, sizeof(name), "pciehp-%u", PSN(ctrl)); + slot->wq = alloc_workqueue(name, 0, 0); + if (!slot->wq) + goto abort; + slot->ctrl = ctrl; mutex_init(&slot->lock); INIT_DELAYED_WORK(&slot->work, pciehp_queue_pushbutton_work); ctrl->slot = slot; return 0; +abort: + kfree(slot); + return -ENOMEM; } static void pcie_cleanup_slot(struct controller *ctrl) { struct slot *slot = ctrl->slot; cancel_delayed_work(&slot->work); - flush_workqueue(pciehp_wq); + destroy_workqueue(slot->wq); kfree(slot); } diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index ca64932e658..1b69d955a31 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h @@ -47,7 +47,6 @@ extern bool shpchp_poll_mode; extern int shpchp_poll_time; extern bool shpchp_debug; extern struct workqueue_struct *shpchp_wq; -extern struct workqueue_struct *shpchp_ordered_wq; #define dbg(format, arg...) \ do { \ diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index 7414fd9ad1d..5f1f0d93dc1 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c @@ -40,7 +40,6 @@ bool shpchp_debug; bool shpchp_poll_mode; int shpchp_poll_time; struct workqueue_struct *shpchp_wq; -struct workqueue_struct *shpchp_ordered_wq; #define DRIVER_VERSION "0.4" #define DRIVER_AUTHOR "Dan Zink , Greg Kroah-Hartman , Dely Sy " @@ -175,7 +174,6 @@ void cleanup_slots(struct controller *ctrl) list_del(&slot->slot_list); cancel_delayed_work(&slot->work); flush_workqueue(shpchp_wq); - flush_workqueue(shpchp_ordered_wq); pci_hp_deregister(slot->hotplug_slot); } } @@ -364,17 +362,10 @@ static int __init shpcd_init(void) if (!shpchp_wq) return -ENOMEM; - shpchp_ordered_wq = alloc_ordered_workqueue("shpchp_ordered", 0); - if (!shpchp_ordered_wq) { - destroy_workqueue(shpchp_wq); - return -ENOMEM; - } - retval = pci_register_driver(&shpc_driver); dbg("%s: pci_register_driver = %d\n", __func__, retval); info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); if (retval) { - destroy_workqueue(shpchp_ordered_wq); destroy_workqueue(shpchp_wq); } return retval; @@ -384,7 +375,6 @@ static void __exit shpcd_cleanup(void) { dbg("unload_shpchpd()\n"); pci_unregister_driver(&shpc_driver); - destroy_workqueue(shpchp_ordered_wq); destroy_workqueue(shpchp_wq); info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n"); } diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index b00b09bdd38..bba5b3e0bf8 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c @@ -456,7 +456,7 @@ void shpchp_queue_pushbutton_work(struct work_struct *work) kfree(info); goto out; } - queue_work(shpchp_ordered_wq, &info->work); + queue_work(shpchp_wq, &info->work); out: mutex_unlock(&p_slot->lock); } diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 9c1d37bd65f..2ab18ec45eb 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -935,6 +935,13 @@ static int pci_pm_poweroff_noirq(struct device *dev) if (!pci_dev->state_saved && !pci_is_bridge(pci_dev)) pci_prepare_to_sleep(pci_dev); + /* + * The reason for doing this here is the same as for the analogous code + * in pci_pm_suspend_noirq(). + */ + if (pci_dev->class == PCI_CLASS_SERIAL_USB_EHCI) + pci_write_config_word(pci_dev, PCI_COMMAND, 0); + return 0; } diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c index 0ca05353814..a56105b66f1 100644 --- a/drivers/pci/pcie/aer/aerdrv_core.c +++ b/drivers/pci/pcie/aer/aerdrv_core.c @@ -637,6 +637,7 @@ static void aer_recover_work_func(struct work_struct *work) continue; } do_recovery(pdev, entry.severity); + pci_dev_put(pdev); } } #endif diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index b500840a143..474f22f304e 100644 --- a/drivers/pci/pcie/aspm.c +++ b/drivers/pci/pcie/aspm.c @@ -798,6 +798,9 @@ void pcie_clear_aspm(struct pci_bus *bus) { struct pci_dev *child; + if (aspm_force) + return; + /* * Clear any ASPM setup that the firmware has carried out on this bus */ diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 5e1ca3c58a7..63e0199f7c7 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -749,8 +749,10 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, /* Check if setup is sensible at all */ if (!pass && - (primary != bus->number || secondary <= bus->number)) { - dev_dbg(&dev->dev, "bus configuration invalid, reconfiguring\n"); + (primary != bus->number || secondary <= bus->number || + secondary > subordinate)) { + dev_info(&dev->dev, "bridge configuration invalid ([bus %02x-%02x]), reconfiguring\n", + secondary, subordinate); broken = 1; } diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 4bf71028556..680dbfa1b61 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -2708,7 +2708,7 @@ static void ricoh_mmc_fixup_r5c832(struct pci_dev *dev) if (PCI_FUNC(dev->devfn)) return; /* - * RICOH 0xe823 SD/MMC card reader fails to recognize + * RICOH 0xe822 and 0xe823 SD/MMC card readers fail to recognize * certain types of SD/MMC cards. Lowering the SD base * clock frequency from 200Mhz to 50Mhz fixes this issue. * @@ -2719,7 +2719,8 @@ static void ricoh_mmc_fixup_r5c832(struct pci_dev *dev) * 0xf9 - Key register for 0x150 * 0xfc - key register for 0xe1 */ - if (dev->device == PCI_DEVICE_ID_RICOH_R5CE823) { + if (dev->device == PCI_DEVICE_ID_RICOH_R5CE822 || + dev->device == PCI_DEVICE_ID_RICOH_R5CE823) { pci_write_config_byte(dev, 0xf9, 0xfc); pci_write_config_byte(dev, 0x150, 0x10); pci_write_config_byte(dev, 0xf9, 0x00); @@ -2746,6 +2747,8 @@ static void ricoh_mmc_fixup_r5c832(struct pci_dev *dev) } DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, ricoh_mmc_fixup_r5c832); DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5C832, ricoh_mmc_fixup_r5c832); +DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5CE822, ricoh_mmc_fixup_r5c832); +DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5CE822, ricoh_mmc_fixup_r5c832); DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5CE823, ricoh_mmc_fixup_r5c832); DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_R5CE823, ricoh_mmc_fixup_r5c832); #endif /*CONFIG_MMC_RICOH_MMC*/ diff --git a/drivers/pcmcia/pxa2xx_sharpsl.c b/drivers/pcmcia/pxa2xx_sharpsl.c index b066273b6b4..7dd879ce514 100644 --- a/drivers/pcmcia/pxa2xx_sharpsl.c +++ b/drivers/pcmcia/pxa2xx_sharpsl.c @@ -194,7 +194,7 @@ static void sharpsl_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt) sharpsl_pcmcia_init_reset(skt); } -static struct pcmcia_low_level sharpsl_pcmcia_ops __initdata = { +static struct pcmcia_low_level sharpsl_pcmcia_ops = { .owner = THIS_MODULE, .hw_init = sharpsl_pcmcia_hw_init, .socket_state = sharpsl_pcmcia_socket_state, diff --git a/drivers/pinctrl/pinctrl-tegra.c b/drivers/pinctrl/pinctrl-tegra.c index 9b329688120..2a32a2ff732 100644 --- a/drivers/pinctrl/pinctrl-tegra.c +++ b/drivers/pinctrl/pinctrl-tegra.c @@ -259,7 +259,7 @@ static int tegra_pinconf_reg(struct tegra_pmx *pmx, *bank = g->drv_bank; *reg = g->drv_reg; *bit = g->lpmd_bit; - *width = 1; + *width = 2; break; case TEGRA_PINCONF_PARAM_DRIVE_DOWN_STRENGTH: *bank = g->drv_bank; diff --git a/drivers/pinctrl/pinctrl-tegra30.c b/drivers/pinctrl/pinctrl-tegra30.c index 4d7571d4a43..636d96c4b3e 100644 --- a/drivers/pinctrl/pinctrl-tegra30.c +++ b/drivers/pinctrl/pinctrl-tegra30.c @@ -3343,10 +3343,10 @@ static const struct tegra_function tegra30_functions[] = { FUNCTION(vi_alt3), }; -#define MUXCTL_REG_A 0x3000 -#define PINGROUP_REG_A 0x868 +#define DRV_PINGROUP_REG_A 0x868 /* bank 0 */ +#define PINGROUP_REG_A 0x3000 /* bank 1 */ -#define PINGROUP_REG_Y(r) ((r) - MUXCTL_REG_A) +#define PINGROUP_REG_Y(r) ((r) - PINGROUP_REG_A) #define PINGROUP_REG_N(r) -1 #define PINGROUP(pg_name, f0, f1, f2, f3, f_safe, r, od, ior) \ @@ -3362,25 +3362,25 @@ static const struct tegra_function tegra30_functions[] = { }, \ .func_safe = TEGRA_MUX_ ## f_safe, \ .mux_reg = PINGROUP_REG_Y(r), \ - .mux_bank = 0, \ + .mux_bank = 1, \ .mux_bit = 0, \ .pupd_reg = PINGROUP_REG_Y(r), \ - .pupd_bank = 0, \ + .pupd_bank = 1, \ .pupd_bit = 2, \ .tri_reg = PINGROUP_REG_Y(r), \ - .tri_bank = 0, \ + .tri_bank = 1, \ .tri_bit = 4, \ .einput_reg = PINGROUP_REG_Y(r), \ - .einput_bank = 0, \ + .einput_bank = 1, \ .einput_bit = 5, \ .odrain_reg = PINGROUP_REG_##od(r), \ - .odrain_bank = 0, \ + .odrain_bank = 1, \ .odrain_bit = 6, \ .lock_reg = PINGROUP_REG_Y(r), \ - .lock_bank = 0, \ + .lock_bank = 1, \ .lock_bit = 7, \ .ioreset_reg = PINGROUP_REG_##ior(r), \ - .ioreset_bank = 0, \ + .ioreset_bank = 1, \ .ioreset_bit = 8, \ .drv_reg = -1, \ } @@ -3399,8 +3399,8 @@ static const struct tegra_function tegra30_functions[] = { .odrain_reg = -1, \ .lock_reg = -1, \ .ioreset_reg = -1, \ - .drv_reg = ((r) - PINGROUP_REG_A), \ - .drv_bank = 1, \ + .drv_reg = ((r) - DRV_PINGROUP_REG_A), \ + .drv_bank = 0, \ .hsm_bit = hsm_b, \ .schmitt_bit = schmitt_b, \ .lpmd_bit = lpmd_b, \ diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index e38f91be0b1..110c7778cbf 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -863,9 +863,9 @@ static ssize_t show_infos(struct device *dev, * The significance of others is yet to be found. * If we don't find the method, we assume the device are present. */ - rv = acpi_evaluate_integer(asus->handle, "HRWS", NULL, &temp); + rv = acpi_evaluate_integer(asus->handle, "HWRS", NULL, &temp); if (!ACPI_FAILURE(rv)) - len += sprintf(page + len, "HRWS value : %#x\n", + len += sprintf(page + len, "HWRS value : %#x\n", (uint) temp); /* * Another value for userspace: the ASYM method returns 0x02 for @@ -1751,9 +1751,9 @@ static int asus_laptop_get_info(struct asus_laptop *asus) * The significance of others is yet to be found. */ status = - acpi_evaluate_integer(asus->handle, "HRWS", NULL, &hwrs_result); + acpi_evaluate_integer(asus->handle, "HWRS", NULL, &hwrs_result); if (!ACPI_FAILURE(status)) - pr_notice(" HRWS returned %x", (int)hwrs_result); + pr_notice(" HWRS returned %x", (int)hwrs_result); if (!acpi_check_handle(asus->handle, METHOD_WL_STATUS, NULL)) asus->have_rsts = true; diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c index 99a30b51313..6de14fd090a 100644 --- a/drivers/platform/x86/asus-nb-wmi.c +++ b/drivers/platform/x86/asus-nb-wmi.c @@ -94,6 +94,10 @@ static const struct key_entry asus_nb_wmi_keymap[] = { { KE_KEY, 0x8A, { KEY_PROG1 } }, { KE_KEY, 0x95, { KEY_MEDIA } }, { KE_KEY, 0x99, { KEY_PHONE } }, + { KE_KEY, 0xA0, { KEY_SWITCHVIDEOMODE } }, /* SDSP HDMI only */ + { KE_KEY, 0xA1, { KEY_SWITCHVIDEOMODE } }, /* SDSP LCD + HDMI */ + { KE_KEY, 0xA2, { KEY_SWITCHVIDEOMODE } }, /* SDSP CRT + HDMI */ + { KE_KEY, 0xA3, { KEY_SWITCHVIDEOMODE } }, /* SDSP TV + HDMI */ { KE_KEY, 0xb5, { KEY_CALC } }, { KE_KEY, 0xc4, { KEY_KBDILLUMUP } }, { KE_KEY, 0xc5, { KEY_KBDILLUMDOWN } }, diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c index 77aadde5281..556cbb455ed 100644 --- a/drivers/platform/x86/asus-wmi.c +++ b/drivers/platform/x86/asus-wmi.c @@ -1467,14 +1467,9 @@ static int asus_wmi_platform_init(struct asus_wmi *asus) */ if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_DSTS, 0, 0, NULL)) asus->dsts_id = ASUS_WMI_METHODID_DSTS; - else if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_DSTS2, 0, 0, NULL)) + else asus->dsts_id = ASUS_WMI_METHODID_DSTS2; - if (!asus->dsts_id) { - pr_err("Can't find DSTS"); - return -ENODEV; - } - /* CWAP allow to define the behavior of the Fn+F2 key, * this method doesn't seems to be present on Eee PCs */ if (asus->driver->quirks->wapf >= 0) diff --git a/drivers/platform/x86/intel_ips.c b/drivers/platform/x86/intel_ips.c index 0ffdb3cde2b..9af4257d490 100644 --- a/drivers/platform/x86/intel_ips.c +++ b/drivers/platform/x86/intel_ips.c @@ -72,6 +72,7 @@ #include #include #include +#include #include #include #include @@ -1485,6 +1486,24 @@ static DEFINE_PCI_DEVICE_TABLE(ips_id_table) = { MODULE_DEVICE_TABLE(pci, ips_id_table); +static int ips_blacklist_callback(const struct dmi_system_id *id) +{ + pr_info("Blacklisted intel_ips for %s\n", id->ident); + return 1; +} + +static const struct dmi_system_id ips_blacklist[] = { + { + .callback = ips_blacklist_callback, + .ident = "HP ProBook", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP ProBook"), + }, + }, + { } /* terminating entry */ +}; + static int ips_probe(struct pci_dev *dev, const struct pci_device_id *id) { u64 platform_info; @@ -1494,6 +1513,9 @@ static int ips_probe(struct pci_dev *dev, const struct pci_device_id *id) u16 htshi, trc, trc_required_mask; u8 tse; + if (dmi_check_system(ips_blacklist)) + return -ENODEV; + ips = kzalloc(sizeof(struct ips_driver), GFP_KERNEL); if (!ips) return -ENOMEM; diff --git a/drivers/platform/x86/samsung-laptop.c b/drivers/platform/x86/samsung-laptop.c index e2a34b42ddc..1afbe5e0a34 100644 --- a/drivers/platform/x86/samsung-laptop.c +++ b/drivers/platform/x86/samsung-laptop.c @@ -1506,6 +1506,16 @@ static struct dmi_system_id __initdata samsung_dmi_table[] = { }, .driver_data = &samsung_broken_acpi_video, }, + { + .callback = samsung_dmi_matched, + .ident = "N250P", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), + DMI_MATCH(DMI_PRODUCT_NAME, "N250P"), + DMI_MATCH(DMI_BOARD_NAME, "N250P"), + }, + .driver_data = &samsung_broken_acpi_video, + }, { }, }; MODULE_DEVICE_TABLE(dmi, samsung_dmi_table); diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c index d21e8f59c84..291906e8e9a 100644 --- a/drivers/pnp/pnpacpi/core.c +++ b/drivers/pnp/pnpacpi/core.c @@ -58,7 +58,7 @@ static inline int __init is_exclusive_device(struct acpi_device *dev) if (!(('0' <= (c) && (c) <= '9') || ('A' <= (c) && (c) <= 'F'))) \ return 0 #define TEST_ALPHA(c) \ - if (!('@' <= (c) || (c) <= 'Z')) \ + if (!('A' <= (c) && (c) <= 'Z')) \ return 0 static int __init ispnpidacpi(const char *id) { @@ -95,6 +95,9 @@ static int pnpacpi_set_resources(struct pnp_dev *dev) return -ENODEV; } + if (WARN_ON_ONCE(acpi_dev != dev->data)) + dev->data = acpi_dev; + ret = pnpacpi_build_resource_template(dev, &buffer); if (ret) return ret; diff --git a/drivers/rapidio/devices/tsi721.c b/drivers/rapidio/devices/tsi721.c index 30d2072f480..33471e11a73 100644 --- a/drivers/rapidio/devices/tsi721.c +++ b/drivers/rapidio/devices/tsi721.c @@ -439,6 +439,9 @@ static void tsi721_db_dpc(struct work_struct *work) " info %4.4x\n", DBELL_SID(idb.bytes), DBELL_TID(idb.bytes), DBELL_INF(idb.bytes)); } + + wr_ptr = ioread32(priv->regs + + TSI721_IDQ_WP(IDB_QUEUE)) % IDB_QSIZE; } iowrite32(rd_ptr & (IDB_QSIZE - 1), @@ -449,6 +452,10 @@ static void tsi721_db_dpc(struct work_struct *work) regval |= TSI721_SR_CHINT_IDBQRCV; iowrite32(regval, priv->regs + TSI721_SR_CHINTE(IDB_QUEUE)); + + wr_ptr = ioread32(priv->regs + TSI721_IDQ_WP(IDB_QUEUE)) % IDB_QSIZE; + if (wr_ptr != rd_ptr) + schedule_work(&priv->idb_work); } /** @@ -2155,7 +2162,7 @@ static int __devinit tsi721_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct tsi721_device *priv; - int i, cap; + int cap; int err; u32 regval; @@ -2175,12 +2182,15 @@ static int __devinit tsi721_probe(struct pci_dev *pdev, priv->pdev = pdev; #ifdef DEBUG + { + int i; for (i = 0; i <= PCI_STD_RESOURCE_END; i++) { dev_dbg(&pdev->dev, "res[%d] @ 0x%llx (0x%lx, 0x%lx)\n", i, (unsigned long long)pci_resource_start(pdev, i), (unsigned long)pci_resource_len(pdev, i), pci_resource_flags(pdev, i)); } + } #endif /* * Verify BAR configuration diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index 9cdfc389ca2..1eb7a151093 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c @@ -1085,7 +1085,7 @@ TWL6025_ADJUSTABLE_LDO(LDO7, 0x74, 1000, 3300); TWL6025_ADJUSTABLE_LDO(LDO6, 0x60, 1000, 3300); TWL6025_ADJUSTABLE_LDO(LDOLN, 0x64, 1000, 3300); TWL6025_ADJUSTABLE_LDO(LDOUSB, 0x70, 1000, 3300); -TWL4030_FIXED_LDO(VINTANA2, 0x3f, 1500, 11, 100, 0x08); +TWL4030_FIXED_LDO(VINTANA1, 0x3f, 1500, 11, 100, 0x08); TWL4030_FIXED_LDO(VINTDIG, 0x47, 1500, 13, 100, 0x08); TWL4030_FIXED_LDO(VUSB1V5, 0x71, 1500, 17, 100, 0x08); TWL4030_FIXED_LDO(VUSB1V8, 0x74, 1800, 18, 100, 0x08); @@ -1166,7 +1166,7 @@ static const struct of_device_id twl_of_match[] __devinitconst = { TWL6025_OF_MATCH("ti,twl6025-ldo6", LDO6), TWL6025_OF_MATCH("ti,twl6025-ldoln", LDOLN), TWL6025_OF_MATCH("ti,twl6025-ldousb", LDOUSB), - TWLFIXED_OF_MATCH("ti,twl4030-vintana2", VINTANA2), + TWLFIXED_OF_MATCH("ti,twl4030-vintana1", VINTANA1), TWLFIXED_OF_MATCH("ti,twl4030-vintdig", VINTDIG), TWLFIXED_OF_MATCH("ti,twl4030-vusb1v5", VUSB1V5), TWLFIXED_OF_MATCH("ti,twl4030-vusb1v8", VUSB1V8), diff --git a/drivers/regulator/wm831x-dcdc.c b/drivers/regulator/wm831x-dcdc.c index ff810e787ea..97bb31d0bbe 100644 --- a/drivers/regulator/wm831x-dcdc.c +++ b/drivers/regulator/wm831x-dcdc.c @@ -330,7 +330,7 @@ static int wm831x_buckv_set_voltage(struct regulator_dev *rdev, if (vsel > dcdc->dvs_vsel) { ret = wm831x_set_bits(wm831x, dvs_reg, WM831X_DC1_DVS_VSEL_MASK, - dcdc->dvs_vsel); + vsel); if (ret == 0) dcdc->dvs_vsel = vsel; else diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig index f8d818abf98..811ff72df4d 100644 --- a/drivers/remoteproc/Kconfig +++ b/drivers/remoteproc/Kconfig @@ -5,6 +5,7 @@ config REMOTEPROC tristate depends on EXPERIMENTAL select FW_CONFIG + select VIRTIO config OMAP_REMOTEPROC tristate "OMAP remoteproc support" diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index 0142e523220..0f58d5102da 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c @@ -643,17 +643,10 @@ static int rproc_handle_carveout(struct rproc *rproc, dev_dbg(dev, "carveout rsc: da %x, pa %x, len %x, flags %x\n", rsc->da, rsc->pa, rsc->len, rsc->flags); - mapping = kzalloc(sizeof(*mapping), GFP_KERNEL); - if (!mapping) { - dev_err(dev, "kzalloc mapping failed\n"); - return -ENOMEM; - } - carveout = kzalloc(sizeof(*carveout), GFP_KERNEL); if (!carveout) { dev_err(dev, "kzalloc carveout failed\n"); - ret = -ENOMEM; - goto free_mapping; + return -ENOMEM; } va = dma_alloc_coherent(dev, rsc->len, &dma, GFP_KERNEL); @@ -683,11 +676,18 @@ static int rproc_handle_carveout(struct rproc *rproc, * physical address in this case. */ if (rproc->domain) { + mapping = kzalloc(sizeof(*mapping), GFP_KERNEL); + if (!mapping) { + dev_err(dev, "kzalloc mapping failed\n"); + ret = -ENOMEM; + goto dma_free; + } + ret = iommu_map(rproc->domain, rsc->da, dma, rsc->len, rsc->flags); if (ret) { dev_err(dev, "iommu_map failed: %d\n", ret); - goto dma_free; + goto free_mapping; } /* @@ -728,12 +728,12 @@ static int rproc_handle_carveout(struct rproc *rproc, return 0; +free_mapping: + kfree(mapping); dma_free: dma_free_coherent(dev, rsc->len, va, dma); free_carv: kfree(carveout); -free_mapping: - kfree(mapping); return ret; } diff --git a/drivers/rpmsg/virtio_rpmsg_bus.c b/drivers/rpmsg/virtio_rpmsg_bus.c index 39d3aa41add..f56c8ba3a86 100644 --- a/drivers/rpmsg/virtio_rpmsg_bus.c +++ b/drivers/rpmsg/virtio_rpmsg_bus.c @@ -1085,7 +1085,7 @@ static int __init rpmsg_init(void) return ret; } -module_init(rpmsg_init); +subsys_initcall(rpmsg_init); static void __exit rpmsg_fini(void) { diff --git a/drivers/rtc/rtc-imxdi.c b/drivers/rtc/rtc-imxdi.c index d93a9608b1f..bc744b490b0 100644 --- a/drivers/rtc/rtc-imxdi.c +++ b/drivers/rtc/rtc-imxdi.c @@ -392,6 +392,8 @@ static int dryice_rtc_probe(struct platform_device *pdev) if (imxdi->ioaddr == NULL) return -ENOMEM; + spin_lock_init(&imxdi->irq_lock); + imxdi->irq = platform_get_irq(pdev, 0); if (imxdi->irq < 0) return imxdi->irq; diff --git a/drivers/rtc/rtc-isl1208.c b/drivers/rtc/rtc-isl1208.c index dd2aeee6c66..8f8c8ae3523 100644 --- a/drivers/rtc/rtc-isl1208.c +++ b/drivers/rtc/rtc-isl1208.c @@ -494,6 +494,7 @@ isl1208_rtc_interrupt(int irq, void *data) { unsigned long timeout = jiffies + msecs_to_jiffies(1000); struct i2c_client *client = data; + struct rtc_device *rtc = i2c_get_clientdata(client); int handled = 0, sr, err; /* @@ -516,6 +517,8 @@ isl1208_rtc_interrupt(int irq, void *data) if (sr & ISL1208_REG_SR_ALM) { dev_dbg(&client->dev, "alarm!\n"); + rtc_update_irq(rtc, 1, RTC_IRQF | RTC_AF); + /* Clear the alarm */ sr &= ~ISL1208_REG_SR_ALM; sr = i2c_smbus_write_byte_data(client, ISL1208_REG_SR, sr); diff --git a/drivers/rtc/rtc-rs5c348.c b/drivers/rtc/rtc-rs5c348.c index 77074ccd285..fd5c7af04ae 100644 --- a/drivers/rtc/rtc-rs5c348.c +++ b/drivers/rtc/rtc-rs5c348.c @@ -122,9 +122,12 @@ rs5c348_rtc_read_time(struct device *dev, struct rtc_time *tm) tm->tm_min = bcd2bin(rxbuf[RS5C348_REG_MINS] & RS5C348_MINS_MASK); tm->tm_hour = bcd2bin(rxbuf[RS5C348_REG_HOURS] & RS5C348_HOURS_MASK); if (!pdata->rtc_24h) { - tm->tm_hour %= 12; - if (rxbuf[RS5C348_REG_HOURS] & RS5C348_BIT_PM) + if (rxbuf[RS5C348_REG_HOURS] & RS5C348_BIT_PM) { + tm->tm_hour -= 20; + tm->tm_hour %= 12; tm->tm_hour += 12; + } else + tm->tm_hour %= 12; } tm->tm_wday = bcd2bin(rxbuf[RS5C348_REG_WDAY] & RS5C348_WDAY_MASK); tm->tm_mday = bcd2bin(rxbuf[RS5C348_REG_DAY] & RS5C348_DAY_MASK); diff --git a/drivers/rtc/rtc-twl.c b/drivers/rtc/rtc-twl.c index 258abeabf62..63ccc0f9427 100644 --- a/drivers/rtc/rtc-twl.c +++ b/drivers/rtc/rtc-twl.c @@ -495,6 +495,11 @@ static int __devinit twl_rtc_probe(struct platform_device *pdev) if (ret < 0) goto out1; + /* ensure interrupts are disabled, bootloaders can be strange */ + ret = twl_rtc_write_u8(0, REG_RTC_INTERRUPTS_REG); + if (ret < 0) + dev_warn(&pdev->dev, "unable to disable interrupt\n"); + /* init cached IRQ enable bits */ ret = twl_rtc_read_u8(&rtc_irq_bits, REG_RTC_INTERRUPTS_REG); if (ret < 0) diff --git a/drivers/rtc/rtc-vt8500.c b/drivers/rtc/rtc-vt8500.c index 9e94fb147c2..44878da1f06 100644 --- a/drivers/rtc/rtc-vt8500.c +++ b/drivers/rtc/rtc-vt8500.c @@ -69,7 +69,7 @@ | ALARM_SEC_BIT) #define VT8500_RTC_CR_ENABLE (1 << 0) /* Enable RTC */ -#define VT8500_RTC_CR_24H (1 << 1) /* 24h time format */ +#define VT8500_RTC_CR_12H (1 << 1) /* 12h time format */ #define VT8500_RTC_CR_SM_ENABLE (1 << 2) /* Enable periodic irqs */ #define VT8500_RTC_CR_SM_SEC (1 << 3) /* 0: 1Hz/60, 1: 1Hz */ #define VT8500_RTC_CR_CALIB (1 << 4) /* Enable calibration */ @@ -118,7 +118,7 @@ static int vt8500_rtc_read_time(struct device *dev, struct rtc_time *tm) tm->tm_min = bcd2bin((time & TIME_MIN_MASK) >> TIME_MIN_S); tm->tm_hour = bcd2bin((time & TIME_HOUR_MASK) >> TIME_HOUR_S); tm->tm_mday = bcd2bin(date & DATE_DAY_MASK); - tm->tm_mon = bcd2bin((date & DATE_MONTH_MASK) >> DATE_MONTH_S); + tm->tm_mon = bcd2bin((date & DATE_MONTH_MASK) >> DATE_MONTH_S) - 1; tm->tm_year = bcd2bin((date & DATE_YEAR_MASK) >> DATE_YEAR_S) + ((date >> DATE_CENTURY_S) & 1 ? 200 : 100); tm->tm_wday = (time & TIME_DOW_MASK) >> TIME_DOW_S; @@ -137,8 +137,9 @@ static int vt8500_rtc_set_time(struct device *dev, struct rtc_time *tm) } writel((bin2bcd(tm->tm_year - 100) << DATE_YEAR_S) - | (bin2bcd(tm->tm_mon) << DATE_MONTH_S) - | (bin2bcd(tm->tm_mday)), + | (bin2bcd(tm->tm_mon + 1) << DATE_MONTH_S) + | (bin2bcd(tm->tm_mday)) + | ((tm->tm_year >= 200) << DATE_CENTURY_S), vt8500_rtc->regbase + VT8500_RTC_DS); writel((bin2bcd(tm->tm_wday) << TIME_DOW_S) | (bin2bcd(tm->tm_hour) << TIME_HOUR_S) @@ -248,7 +249,7 @@ static int __devinit vt8500_rtc_probe(struct platform_device *pdev) } /* Enable RTC and set it to 24-hour mode */ - writel(VT8500_RTC_CR_ENABLE | VT8500_RTC_CR_24H, + writel(VT8500_RTC_CR_ENABLE, vt8500_rtc->regbase + VT8500_RTC_CR); vt8500_rtc->rtc = rtc_device_register("vt8500-rtc", &pdev->dev, diff --git a/drivers/rtc/rtc-wm831x.c b/drivers/rtc/rtc-wm831x.c index 3b6e6a67e76..41c06fe5415 100644 --- a/drivers/rtc/rtc-wm831x.c +++ b/drivers/rtc/rtc-wm831x.c @@ -24,7 +24,7 @@ #include #include #include - +#include /* * R16416 (0x4020) - RTC Write Counter @@ -96,6 +96,26 @@ struct wm831x_rtc { unsigned int alarm_enabled:1; }; +static void wm831x_rtc_add_randomness(struct wm831x *wm831x) +{ + int ret; + u16 reg; + + /* + * The write counter contains a pseudo-random number which is + * regenerated every time we set the RTC so it should be a + * useful per-system source of entropy. + */ + ret = wm831x_reg_read(wm831x, WM831X_RTC_WRITE_COUNTER); + if (ret >= 0) { + reg = ret; + add_device_randomness(®, sizeof(reg)); + } else { + dev_warn(wm831x->dev, "Failed to read RTC write counter: %d\n", + ret); + } +} + /* * Read current time and date in RTC */ @@ -431,6 +451,8 @@ static int wm831x_rtc_probe(struct platform_device *pdev) alm_irq, ret); } + wm831x_rtc_add_randomness(wm831x); + return 0; err: diff --git a/drivers/s390/cio/device_pgid.c b/drivers/s390/cio/device_pgid.c index 07a4fd29f09..daa6b903aa9 100644 --- a/drivers/s390/cio/device_pgid.c +++ b/drivers/s390/cio/device_pgid.c @@ -234,7 +234,7 @@ static int pgid_cmp(struct pgid *p1, struct pgid *p2) * Determine pathgroup state from PGID data. */ static void pgid_analyze(struct ccw_device *cdev, struct pgid **p, - int *mismatch, int *reserved, u8 *reset) + int *mismatch, u8 *reserved, u8 *reset) { struct pgid *pgid = &cdev->private->pgid[0]; struct pgid *first = NULL; @@ -248,7 +248,7 @@ static void pgid_analyze(struct ccw_device *cdev, struct pgid **p, if ((cdev->private->pgid_valid_mask & lpm) == 0) continue; if (pgid->inf.ps.state2 == SNID_STATE2_RESVD_ELSE) - *reserved = 1; + *reserved |= lpm; if (pgid_is_reset(pgid)) { *reset |= lpm; continue; @@ -316,14 +316,14 @@ static void snid_done(struct ccw_device *cdev, int rc) struct subchannel *sch = to_subchannel(cdev->dev.parent); struct pgid *pgid; int mismatch = 0; - int reserved = 0; + u8 reserved = 0; u8 reset = 0; u8 donepm; if (rc) goto out; pgid_analyze(cdev, &pgid, &mismatch, &reserved, &reset); - if (reserved) + if (reserved == cdev->private->pgid_valid_mask) rc = -EUSERS; else if (mismatch) rc = -EOPNOTSUPP; @@ -336,7 +336,7 @@ static void snid_done(struct ccw_device *cdev, int rc) } out: CIO_MSG_EVENT(2, "snid: device 0.%x.%04x: rc=%d pvm=%02x vpm=%02x " - "todo=%02x mism=%d rsvd=%d reset=%02x\n", id->ssid, + "todo=%02x mism=%d rsvd=%02x reset=%02x\n", id->ssid, id->devno, rc, cdev->private->pgid_valid_mask, sch->vpm, cdev->private->pgid_todo_mask, mismatch, reserved, reset); switch (rc) { diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index f8592160768..951b6cf086a 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -1818,6 +1818,8 @@ static void qeth_l3_free_vlan_addresses4(struct qeth_card *card, QETH_CARD_TEXT(card, 4, "frvaddr4"); netdev = __vlan_find_dev_deep(card->dev, vid); + if (!netdev) + return; in_dev = in_dev_get(netdev); if (!in_dev) return; @@ -1846,6 +1848,8 @@ static void qeth_l3_free_vlan_addresses6(struct qeth_card *card, QETH_CARD_TEXT(card, 4, "frvaddr6"); netdev = __vlan_find_dev_deep(card->dev, vid); + if (!netdev) + return; in6_dev = in6_dev_get(netdev); if (!in6_dev) return; diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index 08601810966..4f1b10b7dea 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c @@ -519,6 +519,7 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn, rwlock_init(&port->unit_list_lock); INIT_LIST_HEAD(&port->unit_list); + atomic_set(&port->units, 0); INIT_WORK(&port->gid_pn_work, zfcp_fc_port_did_lookup); INIT_WORK(&port->test_link_work, zfcp_fc_link_test_work); diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c index 96f13ad8812..79a6afe0212 100644 --- a/drivers/s390/scsi/zfcp_ccw.c +++ b/drivers/s390/scsi/zfcp_ccw.c @@ -39,17 +39,23 @@ void zfcp_ccw_adapter_put(struct zfcp_adapter *adapter) spin_unlock_irqrestore(&zfcp_ccw_adapter_ref_lock, flags); } -static int zfcp_ccw_activate(struct ccw_device *cdev) - +/** + * zfcp_ccw_activate - activate adapter and wait for it to finish + * @cdev: pointer to belonging ccw device + * @clear: Status flags to clear. + * @tag: s390dbf trace record tag + */ +static int zfcp_ccw_activate(struct ccw_device *cdev, int clear, char *tag) { struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev); if (!adapter) return 0; + zfcp_erp_clear_adapter_status(adapter, clear); zfcp_erp_set_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING); zfcp_erp_adapter_reopen(adapter, ZFCP_STATUS_COMMON_ERP_FAILED, - "ccresu2"); + tag); zfcp_erp_wait(adapter); flush_work(&adapter->scan_work); @@ -164,32 +170,47 @@ static int zfcp_ccw_set_online(struct ccw_device *cdev) BUG_ON(!zfcp_reqlist_isempty(adapter->req_list)); adapter->req_no = 0; - zfcp_ccw_activate(cdev); + zfcp_ccw_activate(cdev, 0, "ccsonl1"); zfcp_ccw_adapter_put(adapter); return 0; } /** - * zfcp_ccw_set_offline - set_offline function of zfcp driver + * zfcp_ccw_offline_sync - shut down adapter and wait for it to finish * @cdev: pointer to belonging ccw device + * @set: Status flags to set. + * @tag: s390dbf trace record tag * * This function gets called by the common i/o layer and sets an adapter * into state offline. */ -static int zfcp_ccw_set_offline(struct ccw_device *cdev) +static int zfcp_ccw_offline_sync(struct ccw_device *cdev, int set, char *tag) { struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(cdev); if (!adapter) return 0; - zfcp_erp_adapter_shutdown(adapter, 0, "ccsoff1"); + zfcp_erp_set_adapter_status(adapter, set); + zfcp_erp_adapter_shutdown(adapter, 0, tag); zfcp_erp_wait(adapter); zfcp_ccw_adapter_put(adapter); return 0; } +/** + * zfcp_ccw_set_offline - set_offline function of zfcp driver + * @cdev: pointer to belonging ccw device + * + * This function gets called by the common i/o layer and sets an adapter + * into state offline. + */ +static int zfcp_ccw_set_offline(struct ccw_device *cdev) +{ + return zfcp_ccw_offline_sync(cdev, 0, "ccsoff1"); +} + /** * zfcp_ccw_notify - ccw notify function * @cdev: pointer to belonging ccw device @@ -207,6 +228,11 @@ static int zfcp_ccw_notify(struct ccw_device *cdev, int event) switch (event) { case CIO_GONE: + if (atomic_read(&adapter->status) & + ZFCP_STATUS_ADAPTER_SUSPENDED) { /* notification ignore */ + zfcp_dbf_hba_basic("ccnigo1", adapter); + break; + } dev_warn(&cdev->dev, "The FCP device has been detached\n"); zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti1"); break; @@ -216,6 +242,11 @@ static int zfcp_ccw_notify(struct ccw_device *cdev, int event) zfcp_erp_adapter_shutdown(adapter, 0, "ccnoti2"); break; case CIO_OPER: + if (atomic_read(&adapter->status) & + ZFCP_STATUS_ADAPTER_SUSPENDED) { /* notification ignore */ + zfcp_dbf_hba_basic("ccniop1", adapter); + break; + } dev_info(&cdev->dev, "The FCP device is operational again\n"); zfcp_erp_set_adapter_status(adapter, ZFCP_STATUS_COMMON_RUNNING); @@ -251,6 +282,28 @@ static void zfcp_ccw_shutdown(struct ccw_device *cdev) zfcp_ccw_adapter_put(adapter); } +static int zfcp_ccw_suspend(struct ccw_device *cdev) +{ + zfcp_ccw_offline_sync(cdev, ZFCP_STATUS_ADAPTER_SUSPENDED, "ccsusp1"); + return 0; +} + +static int zfcp_ccw_thaw(struct ccw_device *cdev) +{ + /* trace records for thaw and final shutdown during suspend + can only be found in system dump until the end of suspend + but not after resume because it's based on the memory image + right after the very first suspend (freeze) callback */ + zfcp_ccw_activate(cdev, 0, "ccthaw1"); + return 0; +} + +static int zfcp_ccw_resume(struct ccw_device *cdev) +{ + zfcp_ccw_activate(cdev, ZFCP_STATUS_ADAPTER_SUSPENDED, "ccresu1"); + return 0; +} + struct ccw_driver zfcp_ccw_driver = { .driver = { .owner = THIS_MODULE, @@ -263,7 +316,7 @@ struct ccw_driver zfcp_ccw_driver = { .set_offline = zfcp_ccw_set_offline, .notify = zfcp_ccw_notify, .shutdown = zfcp_ccw_shutdown, - .freeze = zfcp_ccw_set_offline, - .thaw = zfcp_ccw_activate, - .restore = zfcp_ccw_activate, + .freeze = zfcp_ccw_suspend, + .thaw = zfcp_ccw_thaw, + .restore = zfcp_ccw_resume, }; diff --git a/drivers/s390/scsi/zfcp_cfdc.c b/drivers/s390/scsi/zfcp_cfdc.c index fab2c2592a9..8ed63aa9abe 100644 --- a/drivers/s390/scsi/zfcp_cfdc.c +++ b/drivers/s390/scsi/zfcp_cfdc.c @@ -293,7 +293,7 @@ void zfcp_cfdc_adapter_access_changed(struct zfcp_adapter *adapter) } read_unlock_irqrestore(&adapter->port_list_lock, flags); - shost_for_each_device(sdev, port->adapter->scsi_host) { + shost_for_each_device(sdev, adapter->scsi_host) { zfcp_sdev = sdev_to_zfcp(sdev); status = atomic_read(&zfcp_sdev->status); if ((status & ZFCP_STATUS_COMMON_ACCESS_DENIED) || diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c index a9a816e4aa5..79b98482547 100644 --- a/drivers/s390/scsi/zfcp_dbf.c +++ b/drivers/s390/scsi/zfcp_dbf.c @@ -191,7 +191,7 @@ void zfcp_dbf_hba_def_err(struct zfcp_adapter *adapter, u64 req_id, u16 scount, length = min((u16)sizeof(struct qdio_buffer), (u16)ZFCP_DBF_PAY_MAX_REC); - while ((char *)pl[payload->counter] && payload->counter < scount) { + while (payload->counter < scount && (char *)pl[payload->counter]) { memcpy(payload->data, (char *)pl[payload->counter], length); debug_event(dbf->pay, 1, payload, zfcp_dbf_plen(length)); payload->counter++; @@ -200,6 +200,26 @@ void zfcp_dbf_hba_def_err(struct zfcp_adapter *adapter, u64 req_id, u16 scount, spin_unlock_irqrestore(&dbf->pay_lock, flags); } +/** + * zfcp_dbf_hba_basic - trace event for basic adapter events + * @adapter: pointer to struct zfcp_adapter + */ +void zfcp_dbf_hba_basic(char *tag, struct zfcp_adapter *adapter) +{ + struct zfcp_dbf *dbf = adapter->dbf; + struct zfcp_dbf_hba *rec = &dbf->hba_buf; + unsigned long flags; + + spin_lock_irqsave(&dbf->hba_lock, flags); + memset(rec, 0, sizeof(*rec)); + + memcpy(rec->tag, tag, ZFCP_DBF_TAG_LEN); + rec->id = ZFCP_DBF_HBA_BASIC; + + debug_event(dbf->hba, 1, rec, sizeof(*rec)); + spin_unlock_irqrestore(&dbf->hba_lock, flags); +} + static void zfcp_dbf_set_common(struct zfcp_dbf_rec *rec, struct zfcp_adapter *adapter, struct zfcp_port *port, diff --git a/drivers/s390/scsi/zfcp_dbf.h b/drivers/s390/scsi/zfcp_dbf.h index 714f087eb7a..3ac7a4b30dd 100644 --- a/drivers/s390/scsi/zfcp_dbf.h +++ b/drivers/s390/scsi/zfcp_dbf.h @@ -154,6 +154,7 @@ enum zfcp_dbf_hba_id { ZFCP_DBF_HBA_RES = 1, ZFCP_DBF_HBA_USS = 2, ZFCP_DBF_HBA_BIT = 3, + ZFCP_DBF_HBA_BASIC = 4, }; /** diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index ed5d921e82c..f172b844217 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h @@ -77,6 +77,7 @@ struct zfcp_reqlist; #define ZFCP_STATUS_ADAPTER_SIOSL_ISSUED 0x00000004 #define ZFCP_STATUS_ADAPTER_XCONFIG_OK 0x00000008 #define ZFCP_STATUS_ADAPTER_HOST_CON_INIT 0x00000010 +#define ZFCP_STATUS_ADAPTER_SUSPENDED 0x00000040 #define ZFCP_STATUS_ADAPTER_ERP_PENDING 0x00000100 #define ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED 0x00000200 #define ZFCP_STATUS_ADAPTER_DATA_DIV_ENABLED 0x00000400 @@ -204,6 +205,7 @@ struct zfcp_port { struct zfcp_adapter *adapter; /* adapter used to access port */ struct list_head unit_list; /* head of logical unit list */ rwlock_t unit_list_lock; /* unit list lock */ + atomic_t units; /* zfcp_unit count */ atomic_t status; /* status of this remote port */ u64 wwnn; /* WWNN if known */ u64 wwpn; /* WWPN */ diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index 2302e1cfb76..ef9e50225ee 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h @@ -54,6 +54,7 @@ extern void zfcp_dbf_hba_fsf_res(char *, struct zfcp_fsf_req *); extern void zfcp_dbf_hba_bit_err(char *, struct zfcp_fsf_req *); extern void zfcp_dbf_hba_berr(struct zfcp_dbf *, struct zfcp_fsf_req *); extern void zfcp_dbf_hba_def_err(struct zfcp_adapter *, u64, u16, void **); +extern void zfcp_dbf_hba_basic(char *, struct zfcp_adapter *); extern void zfcp_dbf_san_req(char *, struct zfcp_fsf_req *, u32); extern void zfcp_dbf_san_res(char *, struct zfcp_fsf_req *); extern void zfcp_dbf_san_in_els(char *, struct zfcp_fsf_req *); @@ -158,6 +159,7 @@ extern void zfcp_scsi_dif_sense_error(struct scsi_cmnd *, int); extern struct attribute_group zfcp_sysfs_unit_attrs; extern struct attribute_group zfcp_sysfs_adapter_attrs; extern struct attribute_group zfcp_sysfs_port_attrs; +extern struct mutex zfcp_sysfs_port_units_mutex; extern struct device_attribute *zfcp_sysfs_sdev_attrs[]; extern struct device_attribute *zfcp_sysfs_shost_attrs[]; diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index e9a787e2e6a..2136fc2178e 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -219,7 +219,7 @@ static void zfcp_fsf_status_read_handler(struct zfcp_fsf_req *req) return; } - zfcp_dbf_hba_fsf_uss("fssrh_2", req); + zfcp_dbf_hba_fsf_uss("fssrh_4", req); switch (sr_buf->status_type) { case FSF_STATUS_READ_PORT_CLOSED: @@ -437,6 +437,34 @@ void zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter) } } +#define ZFCP_FSF_PORTSPEED_1GBIT (1 << 0) +#define ZFCP_FSF_PORTSPEED_2GBIT (1 << 1) +#define ZFCP_FSF_PORTSPEED_4GBIT (1 << 2) +#define ZFCP_FSF_PORTSPEED_10GBIT (1 << 3) +#define ZFCP_FSF_PORTSPEED_8GBIT (1 << 4) +#define ZFCP_FSF_PORTSPEED_16GBIT (1 << 5) +#define ZFCP_FSF_PORTSPEED_NOT_NEGOTIATED (1 << 15) + +static u32 zfcp_fsf_convert_portspeed(u32 fsf_speed) +{ + u32 fdmi_speed = 0; + if (fsf_speed & ZFCP_FSF_PORTSPEED_1GBIT) + fdmi_speed |= FC_PORTSPEED_1GBIT; + if (fsf_speed & ZFCP_FSF_PORTSPEED_2GBIT) + fdmi_speed |= FC_PORTSPEED_2GBIT; + if (fsf_speed & ZFCP_FSF_PORTSPEED_4GBIT) + fdmi_speed |= FC_PORTSPEED_4GBIT; + if (fsf_speed & ZFCP_FSF_PORTSPEED_10GBIT) + fdmi_speed |= FC_PORTSPEED_10GBIT; + if (fsf_speed & ZFCP_FSF_PORTSPEED_8GBIT) + fdmi_speed |= FC_PORTSPEED_8GBIT; + if (fsf_speed & ZFCP_FSF_PORTSPEED_16GBIT) + fdmi_speed |= FC_PORTSPEED_16GBIT; + if (fsf_speed & ZFCP_FSF_PORTSPEED_NOT_NEGOTIATED) + fdmi_speed |= FC_PORTSPEED_NOT_NEGOTIATED; + return fdmi_speed; +} + static int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req) { struct fsf_qtcb_bottom_config *bottom = &req->qtcb->bottom.config; @@ -456,7 +484,8 @@ static int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req) fc_host_port_name(shost) = nsp->fl_wwpn; fc_host_node_name(shost) = nsp->fl_wwnn; fc_host_port_id(shost) = ntoh24(bottom->s_id); - fc_host_speed(shost) = bottom->fc_link_speed; + fc_host_speed(shost) = + zfcp_fsf_convert_portspeed(bottom->fc_link_speed); fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3; adapter->hydra_version = bottom->adapter_type; @@ -580,7 +609,8 @@ static void zfcp_fsf_exchange_port_evaluate(struct zfcp_fsf_req *req) } else fc_host_permanent_port_name(shost) = fc_host_port_name(shost); fc_host_maxframe_size(shost) = bottom->maximum_frame_size; - fc_host_supported_speeds(shost) = bottom->supported_speed; + fc_host_supported_speeds(shost) = + zfcp_fsf_convert_portspeed(bottom->supported_speed); memcpy(fc_host_supported_fc4s(shost), bottom->supported_fc4_types, FC_FC4_LIST_SIZE); memcpy(fc_host_active_fc4s(shost), bottom->active_fc4_types, @@ -771,12 +801,14 @@ int zfcp_fsf_status_read(struct zfcp_qdio *qdio) static void zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *req) { struct scsi_device *sdev = req->data; - struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); + struct zfcp_scsi_dev *zfcp_sdev; union fsf_status_qual *fsq = &req->qtcb->header.fsf_status_qual; if (req->status & ZFCP_STATUS_FSFREQ_ERROR) return; + zfcp_sdev = sdev_to_zfcp(sdev); + switch (req->qtcb->header.fsf_status) { case FSF_PORT_HANDLE_NOT_VALID: if (fsq->word[0] == fsq->word[1]) { @@ -885,7 +917,7 @@ static void zfcp_fsf_send_ct_handler(struct zfcp_fsf_req *req) switch (header->fsf_status) { case FSF_GOOD: - zfcp_dbf_san_res("fsscth1", req); + zfcp_dbf_san_res("fsscth2", req); ct->status = 0; break; case FSF_SERVICE_CLASS_NOT_SUPPORTED: @@ -1739,13 +1771,15 @@ static void zfcp_fsf_open_lun_handler(struct zfcp_fsf_req *req) { struct zfcp_adapter *adapter = req->adapter; struct scsi_device *sdev = req->data; - struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); + struct zfcp_scsi_dev *zfcp_sdev; struct fsf_qtcb_header *header = &req->qtcb->header; struct fsf_qtcb_bottom_support *bottom = &req->qtcb->bottom.support; if (req->status & ZFCP_STATUS_FSFREQ_ERROR) return; + zfcp_sdev = sdev_to_zfcp(sdev); + atomic_clear_mask(ZFCP_STATUS_COMMON_ACCESS_DENIED | ZFCP_STATUS_COMMON_ACCESS_BOXED | ZFCP_STATUS_LUN_SHARED | @@ -1856,11 +1890,13 @@ int zfcp_fsf_open_lun(struct zfcp_erp_action *erp_action) static void zfcp_fsf_close_lun_handler(struct zfcp_fsf_req *req) { struct scsi_device *sdev = req->data; - struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); + struct zfcp_scsi_dev *zfcp_sdev; if (req->status & ZFCP_STATUS_FSFREQ_ERROR) return; + zfcp_sdev = sdev_to_zfcp(sdev); + switch (req->qtcb->header.fsf_status) { case FSF_PORT_HANDLE_NOT_VALID: zfcp_erp_adapter_reopen(zfcp_sdev->port->adapter, 0, "fscuh_1"); @@ -1950,7 +1986,7 @@ static void zfcp_fsf_req_trace(struct zfcp_fsf_req *req, struct scsi_cmnd *scsi) { struct fsf_qual_latency_info *lat_in; struct latency_cont *lat = NULL; - struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(scsi->device); + struct zfcp_scsi_dev *zfcp_sdev; struct zfcp_blk_drv_data blktrc; int ticks = req->adapter->timer_ticks; @@ -1965,6 +2001,7 @@ static void zfcp_fsf_req_trace(struct zfcp_fsf_req *req, struct scsi_cmnd *scsi) if (req->adapter->adapter_features & FSF_FEATURE_MEASUREMENT_DATA && !(req->status & ZFCP_STATUS_FSFREQ_ERROR)) { + zfcp_sdev = sdev_to_zfcp(scsi->device); blktrc.flags |= ZFCP_BLK_LAT_VALID; blktrc.channel_lat = lat_in->channel_lat * ticks; blktrc.fabric_lat = lat_in->fabric_lat * ticks; @@ -2002,12 +2039,14 @@ static void zfcp_fsf_fcp_handler_common(struct zfcp_fsf_req *req) { struct scsi_cmnd *scmnd = req->data; struct scsi_device *sdev = scmnd->device; - struct zfcp_scsi_dev *zfcp_sdev = sdev_to_zfcp(sdev); + struct zfcp_scsi_dev *zfcp_sdev; struct fsf_qtcb_header *header = &req->qtcb->header; if (unlikely(req->status & ZFCP_STATUS_FSFREQ_ERROR)) return; + zfcp_sdev = sdev_to_zfcp(sdev); + switch (header->fsf_status) { case FSF_HANDLE_MISMATCH: case FSF_PORT_HANDLE_NOT_VALID: diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c index e14da5751d3..e76d003ebdb 100644 --- a/drivers/s390/scsi/zfcp_qdio.c +++ b/drivers/s390/scsi/zfcp_qdio.c @@ -102,18 +102,22 @@ static void zfcp_qdio_int_resp(struct ccw_device *cdev, unsigned int qdio_err, { struct zfcp_qdio *qdio = (struct zfcp_qdio *) parm; struct zfcp_adapter *adapter = qdio->adapter; - struct qdio_buffer_element *sbale; int sbal_no, sbal_idx; - void *pl[ZFCP_QDIO_MAX_SBALS_PER_REQ + 1]; - u64 req_id; - u8 scount; if (unlikely(qdio_err)) { - memset(pl, 0, ZFCP_QDIO_MAX_SBALS_PER_REQ * sizeof(void *)); if (zfcp_adapter_multi_buffer_active(adapter)) { + void *pl[ZFCP_QDIO_MAX_SBALS_PER_REQ + 1]; + struct qdio_buffer_element *sbale; + u64 req_id; + u8 scount; + + memset(pl, 0, + ZFCP_QDIO_MAX_SBALS_PER_REQ * sizeof(void *)); sbale = qdio->res_q[idx]->element; req_id = (u64) sbale->addr; - scount = sbale->scount + 1; /* incl. signaling SBAL */ + scount = min(sbale->scount + 1, + ZFCP_QDIO_MAX_SBALS_PER_REQ + 1); + /* incl. signaling SBAL */ for (sbal_no = 0; sbal_no < scount; sbal_no++) { sbal_idx = (idx + sbal_no) % diff --git a/drivers/s390/scsi/zfcp_sysfs.c b/drivers/s390/scsi/zfcp_sysfs.c index cdc4ff78a7b..9e62210b294 100644 --- a/drivers/s390/scsi/zfcp_sysfs.c +++ b/drivers/s390/scsi/zfcp_sysfs.c @@ -227,6 +227,8 @@ static ssize_t zfcp_sysfs_port_rescan_store(struct device *dev, static ZFCP_DEV_ATTR(adapter, port_rescan, S_IWUSR, NULL, zfcp_sysfs_port_rescan_store); +DEFINE_MUTEX(zfcp_sysfs_port_units_mutex); + static ssize_t zfcp_sysfs_port_remove_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -249,6 +251,16 @@ static ssize_t zfcp_sysfs_port_remove_store(struct device *dev, else retval = 0; + mutex_lock(&zfcp_sysfs_port_units_mutex); + if (atomic_read(&port->units) > 0) { + retval = -EBUSY; + mutex_unlock(&zfcp_sysfs_port_units_mutex); + goto out; + } + /* port is about to be removed, so no more unit_add */ + atomic_set(&port->units, -1); + mutex_unlock(&zfcp_sysfs_port_units_mutex); + write_lock_irq(&adapter->port_list_lock); list_del(&port->list); write_unlock_irq(&adapter->port_list_lock); @@ -289,12 +301,14 @@ static ssize_t zfcp_sysfs_unit_add_store(struct device *dev, { struct zfcp_port *port = container_of(dev, struct zfcp_port, dev); u64 fcp_lun; + int retval; if (strict_strtoull(buf, 0, (unsigned long long *) &fcp_lun)) return -EINVAL; - if (zfcp_unit_add(port, fcp_lun)) - return -EINVAL; + retval = zfcp_unit_add(port, fcp_lun); + if (retval) + return retval; return count; } diff --git a/drivers/s390/scsi/zfcp_unit.c b/drivers/s390/scsi/zfcp_unit.c index 20796ebc33c..4e6a5356bdb 100644 --- a/drivers/s390/scsi/zfcp_unit.c +++ b/drivers/s390/scsi/zfcp_unit.c @@ -104,7 +104,7 @@ static void zfcp_unit_release(struct device *dev) { struct zfcp_unit *unit = container_of(dev, struct zfcp_unit, dev); - put_device(&unit->port->dev); + atomic_dec(&unit->port->units); kfree(unit); } @@ -119,16 +119,27 @@ static void zfcp_unit_release(struct device *dev) int zfcp_unit_add(struct zfcp_port *port, u64 fcp_lun) { struct zfcp_unit *unit; + int retval = 0; + + mutex_lock(&zfcp_sysfs_port_units_mutex); + if (atomic_read(&port->units) == -1) { + /* port is already gone */ + retval = -ENODEV; + goto out; + } unit = zfcp_unit_find(port, fcp_lun); if (unit) { put_device(&unit->dev); - return -EEXIST; + retval = -EEXIST; + goto out; } unit = kzalloc(sizeof(struct zfcp_unit), GFP_KERNEL); - if (!unit) - return -ENOMEM; + if (!unit) { + retval = -ENOMEM; + goto out; + } unit->port = port; unit->fcp_lun = fcp_lun; @@ -139,28 +150,33 @@ int zfcp_unit_add(struct zfcp_port *port, u64 fcp_lun) if (dev_set_name(&unit->dev, "0x%016llx", (unsigned long long) fcp_lun)) { kfree(unit); - return -ENOMEM; + retval = -ENOMEM; + goto out; } - get_device(&port->dev); - if (device_register(&unit->dev)) { put_device(&unit->dev); - return -ENOMEM; + retval = -ENOMEM; + goto out; } if (sysfs_create_group(&unit->dev.kobj, &zfcp_sysfs_unit_attrs)) { device_unregister(&unit->dev); - return -EINVAL; + retval = -EINVAL; + goto out; } + atomic_inc(&port->units); /* under zfcp_sysfs_port_units_mutex ! */ + write_lock_irq(&port->unit_list_lock); list_add_tail(&unit->list, &port->unit_list); write_unlock_irq(&port->unit_list_lock); zfcp_unit_scsi_scan(unit); - return 0; +out: + mutex_unlock(&zfcp_sysfs_port_units_mutex); + return retval; } /** diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c index 19a36945e6f..dd4547bf688 100644 --- a/drivers/scsi/aha152x.c +++ b/drivers/scsi/aha152x.c @@ -2984,8 +2984,8 @@ static int get_command(char *pos, Scsi_Cmnd * ptr) char *start = pos; int i; - SPRINTF("0x%08x: target=%d; lun=%d; cmnd=( ", - (unsigned int) ptr, ptr->device->id, ptr->device->lun); + SPRINTF("%p: target=%d; lun=%d; cmnd=( ", + ptr, ptr->device->id, ptr->device->lun); for (i = 0; i < COMMAND_SIZE(ptr->cmnd[0]); i++) SPRINTF("0x%02x ", ptr->cmnd[i]); diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c index 68ce08552f6..a540162ac59 100644 --- a/drivers/scsi/atp870u.c +++ b/drivers/scsi/atp870u.c @@ -1173,7 +1173,16 @@ static void tscam(struct Scsi_Host *host) outw(val, tmport); outb(2, 0x80); TCM_SYNC: - udelay(0x800); + /* + * The funny division into multiple delays is to accomodate + * arches like ARM where udelay() multiplies its argument by + * a large number to initialize a loop counter. To avoid + * overflow, the maximum supported udelay is 2000 microseconds. + * + * XXX it would be more polite to find a way to use msleep() + */ + mdelay(2); + udelay(48); if ((inb(tmport) & 0x80) == 0x00) { /* bsy ? */ outw(0, tmport--); outb(0, tmport); diff --git a/drivers/scsi/bnx2i/bnx2i_hwi.c b/drivers/scsi/bnx2i/bnx2i_hwi.c index f9d6f412909..72de3ba5165 100644 --- a/drivers/scsi/bnx2i/bnx2i_hwi.c +++ b/drivers/scsi/bnx2i/bnx2i_hwi.c @@ -1264,6 +1264,9 @@ int bnx2i_send_fw_iscsi_init_msg(struct bnx2i_hba *hba) int rc = 0; u64 mask64; + memset(&iscsi_init, 0x00, sizeof(struct iscsi_kwqe_init1)); + memset(&iscsi_init2, 0x00, sizeof(struct iscsi_kwqe_init2)); + bnx2i_adjust_qp_size(hba); iscsi_init.flags = diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index 04c5cea47a2..3a8ba3e433d 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -583,8 +583,7 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h) h->state = TPGS_STATE_STANDBY; break; case TPGS_STATE_OFFLINE: - case TPGS_STATE_UNAVAILABLE: - /* Path unusable for unavailable/offline */ + /* Path unusable */ err = SCSI_DH_DEV_OFFLINED; break; default: diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index a3a056a9db6..b48c24f7d21 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -290,6 +290,7 @@ static void scsi_host_dev_release(struct device *dev) struct Scsi_Host *shost = dev_to_shost(dev); struct device *parent = dev->parent; struct request_queue *q; + void *queuedata; scsi_proc_hostdir_rm(shost->hostt); @@ -299,9 +300,9 @@ static void scsi_host_dev_release(struct device *dev) destroy_workqueue(shost->work_q); q = shost->uspace_req_q; if (q) { - kfree(q->queuedata); - q->queuedata = NULL; - scsi_free_queue(q); + queuedata = q->queuedata; + blk_cleanup_queue(q); + kfree(queuedata); } scsi_destroy_command_freelist(shost); diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 500e20dd56e..b0fefc435c0 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -548,12 +548,42 @@ static void set_performant_mode(struct ctlr_info *h, struct CommandList *c) c->busaddr |= 1 | (h->blockFetchTable[c->Header.SGList] << 1); } +static int is_firmware_flash_cmd(u8 *cdb) +{ + return cdb[0] == BMIC_WRITE && cdb[6] == BMIC_FLASH_FIRMWARE; +} + +/* + * During firmware flash, the heartbeat register may not update as frequently + * as it should. So we dial down lockup detection during firmware flash. and + * dial it back up when firmware flash completes. + */ +#define HEARTBEAT_SAMPLE_INTERVAL_DURING_FLASH (240 * HZ) +#define HEARTBEAT_SAMPLE_INTERVAL (30 * HZ) +static void dial_down_lockup_detection_during_fw_flash(struct ctlr_info *h, + struct CommandList *c) +{ + if (!is_firmware_flash_cmd(c->Request.CDB)) + return; + atomic_inc(&h->firmware_flash_in_progress); + h->heartbeat_sample_interval = HEARTBEAT_SAMPLE_INTERVAL_DURING_FLASH; +} + +static void dial_up_lockup_detection_on_fw_flash_complete(struct ctlr_info *h, + struct CommandList *c) +{ + if (is_firmware_flash_cmd(c->Request.CDB) && + atomic_dec_and_test(&h->firmware_flash_in_progress)) + h->heartbeat_sample_interval = HEARTBEAT_SAMPLE_INTERVAL; +} + static void enqueue_cmd_and_start_io(struct ctlr_info *h, struct CommandList *c) { unsigned long flags; set_performant_mode(h, c); + dial_down_lockup_detection_during_fw_flash(h, c); spin_lock_irqsave(&h->lock, flags); addQ(&h->reqQ, c); h->Qdepth++; @@ -1264,8 +1294,9 @@ static void complete_scsi_command(struct CommandList *cp) } break; case CMD_PROTOCOL_ERR: + cmd->result = DID_ERROR << 16; dev_warn(&h->pdev->dev, "cp %p has " - "protocol error \n", cp); + "protocol error\n", cp); break; case CMD_HARDWARE_ERR: cmd->result = DID_ERROR << 16; @@ -2942,7 +2973,7 @@ static void fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h, c->Request.Timeout = 0; /* Don't time out */ memset(&c->Request.CDB[0], 0, sizeof(c->Request.CDB)); c->Request.CDB[0] = cmd; - c->Request.CDB[1] = 0x03; /* Reset target above */ + c->Request.CDB[1] = HPSA_RESET_TYPE_LUN; /* If bytes 4-7 are zero, it means reset the */ /* LunID device */ c->Request.CDB[4] = 0x00; @@ -3048,6 +3079,7 @@ static inline int bad_tag(struct ctlr_info *h, u32 tag_index, static inline void finish_cmd(struct CommandList *c, u32 raw_tag) { removeQ(c); + dial_up_lockup_detection_on_fw_flash_complete(c->h, c); if (likely(c->cmd_type == CMD_SCSI)) complete_scsi_command(c); else if (c->cmd_type == CMD_IOCTL_PEND) @@ -4188,9 +4220,6 @@ static void controller_lockup_detected(struct ctlr_info *h) spin_unlock_irqrestore(&h->lock, flags); } -#define HEARTBEAT_SAMPLE_INTERVAL (10 * HZ) -#define HEARTBEAT_CHECK_MINIMUM_INTERVAL (HEARTBEAT_SAMPLE_INTERVAL / 2) - static void detect_controller_lockup(struct ctlr_info *h) { u64 now; @@ -4201,7 +4230,7 @@ static void detect_controller_lockup(struct ctlr_info *h) now = get_jiffies_64(); /* If we've received an interrupt recently, we're ok. */ if (time_after64(h->last_intr_timestamp + - (HEARTBEAT_CHECK_MINIMUM_INTERVAL), now)) + (h->heartbeat_sample_interval), now)) return; /* @@ -4210,7 +4239,7 @@ static void detect_controller_lockup(struct ctlr_info *h) * otherwise don't care about signals in this thread. */ if (time_after64(h->last_heartbeat_timestamp + - (HEARTBEAT_CHECK_MINIMUM_INTERVAL), now)) + (h->heartbeat_sample_interval), now)) return; /* If heartbeat has not changed since we last looked, we're not ok. */ @@ -4252,6 +4281,7 @@ static void add_ctlr_to_lockup_detector_list(struct ctlr_info *h) { unsigned long flags; + h->heartbeat_sample_interval = HEARTBEAT_SAMPLE_INTERVAL; spin_lock_irqsave(&lockup_detector_lock, flags); list_add_tail(&h->lockup_list, &hpsa_ctlr_list); spin_unlock_irqrestore(&lockup_detector_lock, flags); diff --git a/drivers/scsi/hpsa.h b/drivers/scsi/hpsa.h index 7b28d54fa87..6f30a6f477c 100644 --- a/drivers/scsi/hpsa.h +++ b/drivers/scsi/hpsa.h @@ -123,6 +123,8 @@ struct ctlr_info { u64 last_intr_timestamp; u32 last_heartbeat; u64 last_heartbeat_timestamp; + u32 heartbeat_sample_interval; + atomic_t firmware_flash_in_progress; u32 lockup_detected; struct list_head lockup_list; }; diff --git a/drivers/scsi/hpsa_cmd.h b/drivers/scsi/hpsa_cmd.h index 8049815d8c1..cdd742e4406 100644 --- a/drivers/scsi/hpsa_cmd.h +++ b/drivers/scsi/hpsa_cmd.h @@ -162,6 +162,7 @@ struct SenseSubsystem_info { #define BMIC_WRITE 0x27 #define BMIC_CACHE_FLUSH 0xc2 #define HPSA_CACHE_FLUSH 0x01 /* C2 was already being used by HPSA */ +#define BMIC_FLASH_FIRMWARE 0xF7 /* Command List Structure */ union SCSI3Addr { diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c index 3a6c4742951..337e8b33d9a 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c @@ -1541,6 +1541,9 @@ static int ibmvscsi_do_host_config(struct ibmvscsi_host_data *hostdata, host_config = &evt_struct->iu.mad.host_config; + /* The transport length field is only 16-bit */ + length = min(0xffff, length); + /* Set up a lun reset SRP command */ memset(host_config, 0x00, sizeof(*host_config)); host_config->common.type = VIOSRP_HOST_CONFIG_TYPE; diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index bc6cf888631..4c150dffb1a 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -481,7 +481,6 @@ static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_devic orom->hdr.version)) { dev_warn(&pdev->dev, "[%d]: invalid oem parameters detected, falling back to firmware\n", i); - devm_kfree(&pdev->dev, orom); orom = NULL; break; } diff --git a/drivers/scsi/isci/probe_roms.c b/drivers/scsi/isci/probe_roms.c index 9b8117b9d75..4c66f4682fd 100644 --- a/drivers/scsi/isci/probe_roms.c +++ b/drivers/scsi/isci/probe_roms.c @@ -104,7 +104,6 @@ struct isci_orom *isci_request_oprom(struct pci_dev *pdev) if (i >= len) { dev_err(&pdev->dev, "oprom parse error\n"); - devm_kfree(&pdev->dev, rom); rom = NULL; } pci_unmap_biosrom(oprom); diff --git a/drivers/scsi/isci/request.c b/drivers/scsi/isci/request.c index 2def1e3960f..05c3fc0ce27 100644 --- a/drivers/scsi/isci/request.c +++ b/drivers/scsi/isci/request.c @@ -1970,7 +1970,7 @@ sci_io_request_frame_handler(struct isci_request *ireq, frame_index, (void **)&frame_buffer); - sci_controller_copy_sata_response(&ireq->stp.req, + sci_controller_copy_sata_response(&ireq->stp.rsp, frame_header, frame_buffer); diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c index caa0525d252..101b28e61c6 100644 --- a/drivers/scsi/libsas/sas_expander.c +++ b/drivers/scsi/libsas/sas_expander.c @@ -868,7 +868,7 @@ static struct domain_device *sas_ex_discover_end_dev( } /* See if this phy is part of a wide port */ -static int sas_ex_join_wide_port(struct domain_device *parent, int phy_id) +static bool sas_ex_join_wide_port(struct domain_device *parent, int phy_id) { struct ex_phy *phy = &parent->ex_dev.ex_phy[phy_id]; int i; @@ -884,11 +884,11 @@ static int sas_ex_join_wide_port(struct domain_device *parent, int phy_id) sas_port_add_phy(ephy->port, phy->phy); phy->port = ephy->port; phy->phy_state = PHY_DEVICE_DISCOVERED; - return 0; + return true; } } - return -ENODEV; + return false; } static struct domain_device *sas_ex_discover_expander( @@ -1030,8 +1030,7 @@ static int sas_ex_discover_dev(struct domain_device *dev, int phy_id) return res; } - res = sas_ex_join_wide_port(dev, phy_id); - if (!res) { + if (sas_ex_join_wide_port(dev, phy_id)) { SAS_DPRINTK("Attaching ex phy%d to wide port %016llx\n", phy_id, SAS_ADDR(ex_phy->attached_sas_addr)); return res; @@ -1077,8 +1076,7 @@ static int sas_ex_discover_dev(struct domain_device *dev, int phy_id) if (SAS_ADDR(ex->ex_phy[i].attached_sas_addr) == SAS_ADDR(child->sas_addr)) { ex->ex_phy[i].phy_state= PHY_DEVICE_DISCOVERED; - res = sas_ex_join_wide_port(dev, i); - if (!res) + if (sas_ex_join_wide_port(dev, i)) SAS_DPRINTK("Attaching ex phy%d to wide port %016llx\n", i, SAS_ADDR(ex->ex_phy[i].attached_sas_addr)); @@ -1943,32 +1941,20 @@ static int sas_discover_new(struct domain_device *dev, int phy_id) { struct ex_phy *ex_phy = &dev->ex_dev.ex_phy[phy_id]; struct domain_device *child; - bool found = false; - int res, i; + int res; SAS_DPRINTK("ex %016llx phy%d new device attached\n", SAS_ADDR(dev->sas_addr), phy_id); res = sas_ex_phy_discover(dev, phy_id); if (res) - goto out; - /* to support the wide port inserted */ - for (i = 0; i < dev->ex_dev.num_phys; i++) { - struct ex_phy *ex_phy_temp = &dev->ex_dev.ex_phy[i]; - if (i == phy_id) - continue; - if (SAS_ADDR(ex_phy_temp->attached_sas_addr) == - SAS_ADDR(ex_phy->attached_sas_addr)) { - found = true; - break; - } - } - if (found) { - sas_ex_join_wide_port(dev, phy_id); + return res; + + if (sas_ex_join_wide_port(dev, phy_id)) return 0; - } + res = sas_ex_discover_devices(dev, phy_id); - if (!res) - goto out; + if (res) + return res; list_for_each_entry(child, &dev->ex_dev.children, siblings) { if (SAS_ADDR(child->sas_addr) == SAS_ADDR(ex_phy->attached_sas_addr)) { @@ -1978,7 +1964,6 @@ static int sas_discover_new(struct domain_device *dev, int phy_id) break; } } -out: return res; } @@ -2109,9 +2094,7 @@ int sas_ex_revalidate_domain(struct domain_device *port_dev) struct domain_device *dev = NULL; res = sas_find_bcast_dev(port_dev, &dev); - if (res) - goto out; - if (dev) { + while (res == 0 && dev) { struct expander_device *ex = &dev->ex_dev; int i = 0, phy_id; @@ -2123,8 +2106,10 @@ int sas_ex_revalidate_domain(struct domain_device *port_dev) res = sas_rediscover(dev, phy_id); i = phy_id + 1; } while (i < ex->num_phys); + + dev = NULL; + res = sas_find_bcast_dev(port_dev, &dev); } -out: return res; } diff --git a/drivers/scsi/lpfc/Makefile b/drivers/scsi/lpfc/Makefile index fe5d396aca7..e2516ba8ebf 100644 --- a/drivers/scsi/lpfc/Makefile +++ b/drivers/scsi/lpfc/Makefile @@ -22,7 +22,9 @@ ccflags-$(GCOV) := -fprofile-arcs -ftest-coverage ccflags-$(GCOV) += -O0 +ifdef WARNINGS_BECOME_ERRORS ccflags-y += -Werror +endif obj-$(CONFIG_SCSI_LPFC) := lpfc.o diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index 8b300be4428..6308a8ddf6f 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -4066,7 +4066,6 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) spin_lock_init(&instance->cmd_pool_lock); spin_lock_init(&instance->hba_lock); spin_lock_init(&instance->completion_lock); - spin_lock_init(&poll_aen_lock); mutex_init(&instance->aen_mutex); mutex_init(&instance->reset_mutex); @@ -5392,6 +5391,8 @@ static int __init megasas_init(void) printk(KERN_INFO "megasas: %s %s\n", MEGASAS_VERSION, MEGASAS_EXT_VERSION); + spin_lock_init(&poll_aen_lock); + support_poll_for_event = 2; support_device_change = 1; diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index 3f03342b303..db793621c40 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c @@ -1202,6 +1202,13 @@ _base_check_enable_msix(struct MPT2SAS_ADAPTER *ioc) u16 message_control; + /* Check whether controller SAS2008 B0 controller, + if it is SAS2008 B0 controller use IO-APIC instead of MSIX */ + if (ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2008 && + ioc->pdev->revision == 0x01) { + return -EINVAL; + } + base = pci_find_capability(ioc->pdev, PCI_CAP_ID_MSIX); if (!base) { dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "msix not " @@ -2417,10 +2424,13 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) } /* command line tunables for max controller queue depth */ - if (max_queue_depth != -1) - max_request_credit = (max_queue_depth < facts->RequestCredit) - ? max_queue_depth : facts->RequestCredit; - else + if (max_queue_depth != -1 && max_queue_depth != 0) { + max_request_credit = min_t(u16, max_queue_depth + + ioc->hi_priority_depth + ioc->internal_depth, + facts->RequestCredit); + if (max_request_credit > MAX_HBA_QUEUE_DEPTH) + max_request_credit = MAX_HBA_QUEUE_DEPTH; + } else max_request_credit = min_t(u16, facts->RequestCredit, MAX_HBA_QUEUE_DEPTH); @@ -2495,7 +2505,7 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag) /* set the scsi host can_queue depth * with some internal commands that could be outstanding */ - ioc->shost->can_queue = ioc->scsiio_depth - (2); + ioc->shost->can_queue = ioc->scsiio_depth; dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "scsi host: " "can_queue depth (%d)\n", ioc->name, ioc->shost->can_queue)); diff --git a/drivers/scsi/mvsas/mv_94xx.h b/drivers/scsi/mvsas/mv_94xx.h index 8f7eb4f2114..487aa6f9741 100644 --- a/drivers/scsi/mvsas/mv_94xx.h +++ b/drivers/scsi/mvsas/mv_94xx.h @@ -258,21 +258,11 @@ enum sas_sata_phy_regs { #define SPI_ADDR_VLD_94XX (1U << 1) #define SPI_CTRL_SpiStart_94XX (1U << 0) -#define mv_ffc(x) ffz(x) - static inline int mv_ffc64(u64 v) { - int i; - i = mv_ffc((u32)v); - if (i >= 0) - return i; - i = mv_ffc((u32)(v>>32)); - - if (i != 0) - return 32 + i; - - return -1; + u64 x = ~v; + return x ? __ffs64(x) : -1; } #define r_reg_set_enable(i) \ diff --git a/drivers/scsi/mvsas/mv_sas.c b/drivers/scsi/mvsas/mv_sas.c index fd3b2839843..dbb8edfc8ba 100644 --- a/drivers/scsi/mvsas/mv_sas.c +++ b/drivers/scsi/mvsas/mv_sas.c @@ -885,7 +885,6 @@ static int mvs_task_exec(struct sas_task *task, const int num, gfp_t gfp_flags, struct completion *completion, int is_tmf, struct mvs_tmf_task *tmf) { - struct domain_device *dev = task->dev; struct mvs_info *mvi = NULL; u32 rc = 0; u32 pass = 0; @@ -1630,7 +1629,7 @@ int mvs_abort_task(struct sas_task *task) mv_dprintk("mvs_abort_task() mvi=%p task=%p " "slot=%p slot_idx=x%x\n", mvi, task, slot, slot_idx); - mvs_tmf_timedout((unsigned long)task); + task->task_state_flags |= SAS_TASK_STATE_ABORTED; mvs_slot_task_free(mvi, task, slot, slot_idx); rc = TMF_RESP_FUNC_COMPLETE; goto out; diff --git a/drivers/scsi/mvsas/mv_sas.h b/drivers/scsi/mvsas/mv_sas.h index c04a4f5b597..da249553858 100644 --- a/drivers/scsi/mvsas/mv_sas.h +++ b/drivers/scsi/mvsas/mv_sas.h @@ -69,7 +69,7 @@ extern struct kmem_cache *mvs_task_list_cache; #define DEV_IS_EXPANDER(type) \ ((type == EDGE_DEV) || (type == FANOUT_DEV)) -#define bit(n) ((u32)1 << n) +#define bit(n) ((u64)1 << n) #define for_each_phy(__lseq_mask, __mc, __lseq) \ for ((__mc) = (__lseq_mask), (__lseq) = 0; \ diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 7db803377c6..da1315ede00 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -3735,9 +3735,9 @@ qla2x00_do_dpc(void *data) "ISP abort end.\n"); } - if (test_bit(FCPORT_UPDATE_NEEDED, &base_vha->dpc_flags)) { + if (test_and_clear_bit(FCPORT_UPDATE_NEEDED, + &base_vha->dpc_flags)) { qla2x00_update_fcports(base_vha); - clear_bit(FCPORT_UPDATE_NEEDED, &base_vha->dpc_flags); } if (test_bit(ISP_QUIESCE_NEEDED, &base_vha->dpc_flags)) { diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 182d5a57ab7..f4cc4139ada 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -2054,7 +2054,7 @@ static void unmap_region(sector_t lba, unsigned int len) block = lba + alignment; rem = do_div(block, granularity); - if (rem == 0 && lba + granularity <= end && block < map_size) { + if (rem == 0 && lba + granularity < end && block < map_size) { clear_bit(block, map_storep); if (scsi_debug_lbprz) memset(fake_storep + diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 386f0c53bea..b3f0b0f6d44 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -42,6 +42,8 @@ #include +static void scsi_eh_done(struct scsi_cmnd *scmd); + #define SENSE_TIMEOUT (10*HZ) /* @@ -241,6 +243,14 @@ static int scsi_check_sense(struct scsi_cmnd *scmd) if (! scsi_command_normalize_sense(scmd, &sshdr)) return FAILED; /* no valid sense data */ + if (scmd->cmnd[0] == TEST_UNIT_READY && scmd->scsi_done != scsi_eh_done) + /* + * nasty: for mid-layer issued TURs, we need to return the + * actual sense data without any recovery attempt. For eh + * issued ones, we need to try to recover and interpret + */ + return SUCCESS; + if (scsi_sense_is_deferred(&sshdr)) return NEEDS_RETRY; @@ -1687,6 +1697,20 @@ static void scsi_restart_operations(struct Scsi_Host *shost) * requests are started. */ scsi_run_host_queues(shost); + + /* + * if eh is active and host_eh_scheduled is pending we need to re-run + * recovery. we do this check after scsi_run_host_queues() to allow + * everything pent up since the last eh run a chance to make forward + * progress before we sync again. Either we'll immediately re-run + * recovery or scsi_device_unbusy() will wake us again when these + * pending commands complete. + */ + spin_lock_irqsave(shost->host_lock, flags); + if (shost->host_eh_scheduled) + if (scsi_host_set_state(shost, SHOST_RECOVERY)) + WARN_ON(scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY)); + spin_unlock_irqrestore(shost->host_lock, flags); } /** diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 4037fd5b1e0..2bc036292d9 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -406,10 +406,6 @@ static void scsi_run_queue(struct request_queue *q) LIST_HEAD(starved_list); unsigned long flags; - /* if the device is dead, sdev will be NULL, so no queue to run */ - if (!sdev) - return; - shost = sdev->host; if (scsi_target(sdev)->single_lun) scsi_single_lun_run(sdev); @@ -483,15 +479,26 @@ void scsi_requeue_run_queue(struct work_struct *work) */ static void scsi_requeue_command(struct request_queue *q, struct scsi_cmnd *cmd) { + struct scsi_device *sdev = cmd->device; struct request *req = cmd->request; unsigned long flags; + /* + * We need to hold a reference on the device to avoid the queue being + * killed after the unlock and before scsi_run_queue is invoked which + * may happen because scsi_unprep_request() puts the command which + * releases its reference on the device. + */ + get_device(&sdev->sdev_gendev); + spin_lock_irqsave(q->queue_lock, flags); scsi_unprep_request(req); blk_requeue_request(q, req); spin_unlock_irqrestore(q->queue_lock, flags); scsi_run_queue(q); + + put_device(&sdev->sdev_gendev); } void scsi_next_command(struct scsi_cmnd *cmd) @@ -753,7 +760,6 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) } if (req->cmd_type == REQ_TYPE_BLOCK_PC) { /* SG_IO ioctl from block level */ - req->errors = result; if (result) { if (sense_valid && req->sense) { /* @@ -769,6 +775,10 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) if (!sense_deferred) error = __scsi_error_from_host_byte(cmd, result); } + /* + * __scsi_error_from_host_byte may have reset the host_byte + */ + req->errors = cmd->result; req->resid_len = scsi_get_resid(cmd); @@ -1370,16 +1380,16 @@ static inline int scsi_host_queue_ready(struct request_queue *q, * may be changed after request stacking drivers call the function, * regardless of taking lock or not. * - * When scsi can't dispatch I/Os anymore and needs to kill I/Os - * (e.g. !sdev), scsi needs to return 'not busy'. - * Otherwise, request stacking drivers may hold requests forever. + * When scsi can't dispatch I/Os anymore and needs to kill I/Os scsi + * needs to return 'not busy'. Otherwise, request stacking drivers + * may hold requests forever. */ static int scsi_lld_busy(struct request_queue *q) { struct scsi_device *sdev = q->queuedata; struct Scsi_Host *shost; - if (!sdev) + if (blk_queue_dead(q)) return 0; shost = sdev->host; @@ -1490,12 +1500,6 @@ static void scsi_request_fn(struct request_queue *q) struct scsi_cmnd *cmd; struct request *req; - if (!sdev) { - while ((req = blk_peek_request(q)) != NULL) - scsi_kill_request(req, q); - return; - } - if(!get_device(&sdev->sdev_gendev)) /* We must be tearing the block queue down already */ return; @@ -1697,20 +1701,6 @@ struct request_queue *scsi_alloc_queue(struct scsi_device *sdev) return q; } -void scsi_free_queue(struct request_queue *q) -{ - unsigned long flags; - - WARN_ON(q->queuedata); - - /* cause scsi_request_fn() to kill all non-finished requests */ - spin_lock_irqsave(q->queue_lock, flags); - q->request_fn(q); - spin_unlock_irqrestore(q->queue_lock, flags); - - blk_cleanup_queue(q); -} - /* * Function: scsi_block_requests() * diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index be4fa6d179b..fd9f57fd210 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h @@ -84,7 +84,6 @@ extern void scsi_next_command(struct scsi_cmnd *cmd); extern void scsi_io_completion(struct scsi_cmnd *, unsigned int); extern void scsi_run_host_queues(struct Scsi_Host *shost); extern struct request_queue *scsi_alloc_queue(struct scsi_device *sdev); -extern void scsi_free_queue(struct request_queue *q); extern int scsi_init_queue(void); extern void scsi_exit_queue(void); struct request_queue; diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index 01b03744f1f..348840e8092 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -776,6 +776,16 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, sdev->model = (char *) (sdev->inquiry + 16); sdev->rev = (char *) (sdev->inquiry + 32); + if (strncmp(sdev->vendor, "ATA ", 8) == 0) { + /* + * sata emulation layer device. This is a hack to work around + * the SATL power management specifications which state that + * when the SATL detects the device has gone into standby + * mode, it shall respond with NOT READY. + */ + sdev->allow_restart = 1; + } + if (*bflags & BLIST_ISROM) { sdev->type = TYPE_ROM; sdev->removable = 1; @@ -1714,6 +1724,9 @@ static void scsi_sysfs_add_devices(struct Scsi_Host *shost) { struct scsi_device *sdev; shost_for_each_device(sdev, shost) { + /* target removed before the device could be added */ + if (sdev->sdev_state == SDEV_DEL) + continue; if (!scsi_host_scan_allowed(shost) || scsi_sysfs_add_sdev(sdev) != 0) __scsi_remove_device(sdev); diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 04c2a278076..72ca515a430 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -246,11 +246,11 @@ show_shost_active_mode(struct device *dev, static DEVICE_ATTR(active_mode, S_IRUGO | S_IWUSR, show_shost_active_mode, NULL); -static int check_reset_type(char *str) +static int check_reset_type(const char *str) { - if (strncmp(str, "adapter", 10) == 0) + if (sysfs_streq(str, "adapter")) return SCSI_ADAPTER_RESET; - else if (strncmp(str, "firmware", 10) == 0) + else if (sysfs_streq(str, "firmware")) return SCSI_FIRMWARE_RESET; else return 0; @@ -263,12 +263,9 @@ store_host_reset(struct device *dev, struct device_attribute *attr, struct Scsi_Host *shost = class_to_shost(dev); struct scsi_host_template *sht = shost->hostt; int ret = -EINVAL; - char str[10]; int type; - sscanf(buf, "%s", str); - type = check_reset_type(str); - + type = check_reset_type(buf); if (!type) goto exit_store_host_reset; @@ -971,11 +968,8 @@ void __scsi_remove_device(struct scsi_device *sdev) sdev->host->hostt->slave_destroy(sdev); transport_destroy_device(dev); - /* cause the request function to reject all I/O requests */ - sdev->request_queue->queuedata = NULL; - /* Freeing the queue signals to block that we're done */ - scsi_free_queue(sdev->request_queue); + blk_cleanup_queue(sdev->request_queue); put_device(dev); } @@ -1000,7 +994,6 @@ static void __scsi_remove_target(struct scsi_target *starget) struct scsi_device *sdev; spin_lock_irqsave(shost->host_lock, flags); - starget->reap_ref++; restart: list_for_each_entry(sdev, &shost->__devices, siblings) { if (sdev->channel != starget->channel || @@ -1014,14 +1007,6 @@ static void __scsi_remove_target(struct scsi_target *starget) goto restart; } spin_unlock_irqrestore(shost->host_lock, flags); - scsi_target_reap(starget); -} - -static int __remove_child (struct device * dev, void * data) -{ - if (scsi_is_target_device(dev)) - __scsi_remove_target(to_scsi_target(dev)); - return 0; } /** @@ -1034,14 +1019,32 @@ static int __remove_child (struct device * dev, void * data) */ void scsi_remove_target(struct device *dev) { - if (scsi_is_target_device(dev)) { - __scsi_remove_target(to_scsi_target(dev)); - return; + struct Scsi_Host *shost = dev_to_shost(dev->parent); + struct scsi_target *starget, *last = NULL; + unsigned long flags; + + /* remove targets being careful to lookup next entry before + * deleting the last + */ + spin_lock_irqsave(shost->host_lock, flags); + list_for_each_entry(starget, &shost->__targets, siblings) { + if (starget->state == STARGET_DEL) + continue; + if (starget->dev.parent == dev || &starget->dev == dev) { + /* assuming new targets arrive at the end */ + starget->reap_ref++; + spin_unlock_irqrestore(shost->host_lock, flags); + if (last) + scsi_target_reap(last); + last = starget; + __scsi_remove_target(starget); + spin_lock_irqsave(shost->host_lock, flags); + } } + spin_unlock_irqrestore(shost->host_lock, flags); - get_device(dev); - device_for_each_child(dev, NULL, __remove_child); - put_device(dev); + if (last) + scsi_target_reap(last); } EXPORT_SYMBOL(scsi_remove_target); diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index a239382b2bd..5b3cadbffcf 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -2919,10 +2919,6 @@ static int __init init_sd(void) if (err) goto err_out; - err = scsi_register_driver(&sd_template.gendrv); - if (err) - goto err_out_class; - sd_cdb_cache = kmem_cache_create("sd_ext_cdb", SD_EXT_CDB_SIZE, 0, 0, NULL); if (!sd_cdb_cache) { @@ -2936,8 +2932,15 @@ static int __init init_sd(void) goto err_out_cache; } + err = scsi_register_driver(&sd_template.gendrv); + if (err) + goto err_out_driver; + return 0; +err_out_driver: + mempool_destroy(sd_cdb_pool); + err_out_cache: kmem_cache_destroy(sd_cdb_cache); @@ -2960,10 +2963,10 @@ static void __exit exit_sd(void) SCSI_LOG_HLQUEUE(3, printk("exit_sd: exiting sd driver\n")); + scsi_unregister_driver(&sd_template.gendrv); mempool_destroy(sd_cdb_pool); kmem_cache_destroy(sd_cdb_cache); - scsi_unregister_driver(&sd_template.gendrv); class_unregister(&sd_disk_class); for (i = 0; i < SD_MAJORS; i++) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 83a1972a199..40a45700c8d 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -1211,7 +1211,12 @@ static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd) /* * At this point, all outstanding requests in the adapter * should have been flushed out and return to us + * There is a potential race here where the host may be in + * the process of responding when we return from here. + * Just wait for all in-transit packets to be accounted for + * before we return from here. */ + storvsc_wait_to_drain(stor_device); return SUCCESS; } diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c index 1b384311726..6661610c752 100644 --- a/drivers/scsi/virtio_scsi.c +++ b/drivers/scsi/virtio_scsi.c @@ -198,7 +198,7 @@ static void virtscsi_map_sgl(struct scatterlist *sg, unsigned int *p_idx, int i; for_each_sg(table->sgl, sg_elem, table->nents, i) - sg_set_buf(&sg[idx++], sg_virt(sg_elem), sg_elem->length); + sg[idx++] = *sg_elem; *p_idx = idx; } diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index 400ae2121a2..469eb28e832 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c @@ -489,6 +489,11 @@ static void giveback(struct pl022 *pl022) pl022->cur_transfer = NULL; pl022->cur_chip = NULL; spi_finalize_current_message(pl022->master); + + /* disable the SPI/SSP operation */ + writew((readw(SSP_CR1(pl022->virtbase)) & + (~SSP_CR1_MASK_SSE)), SSP_CR1(pl022->virtbase)); + } /** diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c index 80793e84ae0..65bca1fa684 100644 --- a/drivers/staging/android/binder.c +++ b/drivers/staging/android/binder.c @@ -673,7 +673,7 @@ static int binder_update_page_range(struct binder_proc *proc, int allocate, page = &proc->pages[(page_addr - proc->buffer) / PAGE_SIZE]; BUG_ON(*page); - *page = alloc_page(GFP_KERNEL | __GFP_ZERO); + *page = alloc_page(GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO); if (*page == NULL) { printk(KERN_ERR "binder: %d: binder_alloc_buf failed " "for page at %p\n", proc->pid, page_addr); diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig index 12c691d9090..f11cfc87012 100644 --- a/drivers/staging/comedi/Kconfig +++ b/drivers/staging/comedi/Kconfig @@ -424,6 +424,7 @@ config COMEDI_ADQ12B config COMEDI_NI_AT_A2150 tristate "NI AT-A2150 ISA card support" + select COMEDI_FC depends on COMEDI_NI_COMMON depends on VIRT_TO_BUS default N diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index a796964bfff..b67c1070df7 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -138,6 +138,9 @@ static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd, if (cmd == COMEDI_DEVCONFIG) { rc = do_devconfig_ioctl(dev, (struct comedi_devconfig __user *)arg); + if (rc == 0) + /* Evade comedi_auto_unconfig(). */ + dev_file_info->hardware_device = NULL; goto done; } @@ -843,7 +846,7 @@ static int parse_insn(struct comedi_device *dev, struct comedi_insn *insn, ret = -EAGAIN; break; } - ret = s->async->inttrig(dev, s, insn->data[0]); + ret = s->async->inttrig(dev, s, data[0]); if (ret >= 0) ret = 1; break; @@ -1088,7 +1091,6 @@ static int do_cmd_ioctl(struct comedi_device *dev, goto cleanup; } - kfree(async->cmd.chanlist); async->cmd = user_cmd; async->cmd.data = NULL; /* load channel/gain list */ @@ -1833,6 +1835,8 @@ void do_become_nonbusy(struct comedi_device *dev, struct comedi_subdevice *s) if (async) { comedi_reset_async_buf(async); async->inttrig = NULL; + kfree(async->cmd.chanlist); + async->cmd.chanlist = NULL; } else { printk(KERN_ERR "BUG: (?) do_become_nonbusy called with async=0\n"); @@ -2206,6 +2210,7 @@ int comedi_alloc_board_minor(struct device *hardware_device) kfree(info); return -ENOMEM; } + info->hardware_device = hardware_device; comedi_device_init(info->device); spin_lock_irqsave(&comedi_file_info_table_lock, flags); for (i = 0; i < COMEDI_NUM_BOARD_MINORS; ++i) { @@ -2294,6 +2299,23 @@ void comedi_free_board_minor(unsigned minor) } } +int comedi_find_board_minor(struct device *hardware_device) +{ + int minor; + struct comedi_device_file_info *info; + + for (minor = 0; minor < COMEDI_NUM_BOARD_MINORS; minor++) { + spin_lock(&comedi_file_info_table_lock); + info = comedi_file_info_table[minor]; + if (info && info->hardware_device == hardware_device) { + spin_unlock(&comedi_file_info_table_lock); + return minor; + } + spin_unlock(&comedi_file_info_table_lock); + } + return -ENODEV; +} + int comedi_alloc_subdevice_minor(struct comedi_device *dev, struct comedi_subdevice *s) { diff --git a/drivers/staging/comedi/comedidev.h b/drivers/staging/comedi/comedidev.h index 7a0d4bcbc35..00d3c65589b 100644 --- a/drivers/staging/comedi/comedidev.h +++ b/drivers/staging/comedi/comedidev.h @@ -234,6 +234,7 @@ struct comedi_device_file_info { struct comedi_device *device; struct comedi_subdevice *read_subdevice; struct comedi_subdevice *write_subdevice; + struct device *hardware_device; }; #ifdef CONFIG_COMEDI_DEBUG diff --git a/drivers/staging/comedi/drivers.c b/drivers/staging/comedi/drivers.c index bf185e2807d..0fc1b9939d9 100644 --- a/drivers/staging/comedi/drivers.c +++ b/drivers/staging/comedi/drivers.c @@ -822,25 +822,14 @@ static int comedi_auto_config(struct device *hardware_device, int minor; struct comedi_device_file_info *dev_file_info; int retval; - unsigned *private_data = NULL; - if (!comedi_autoconfig) { - dev_set_drvdata(hardware_device, NULL); + if (!comedi_autoconfig) return 0; - } minor = comedi_alloc_board_minor(hardware_device); if (minor < 0) return minor; - private_data = kmalloc(sizeof(unsigned), GFP_KERNEL); - if (private_data == NULL) { - retval = -ENOMEM; - goto cleanup; - } - *private_data = minor; - dev_set_drvdata(hardware_device, private_data); - dev_file_info = comedi_get_device_file_info(minor); memset(&it, 0, sizeof(it)); @@ -853,25 +842,22 @@ static int comedi_auto_config(struct device *hardware_device, retval = comedi_device_attach(dev_file_info->device, &it); mutex_unlock(&dev_file_info->device->mutex); -cleanup: - if (retval < 0) { - kfree(private_data); + if (retval < 0) comedi_free_board_minor(minor); - } return retval; } static void comedi_auto_unconfig(struct device *hardware_device) { - unsigned *minor = (unsigned *)dev_get_drvdata(hardware_device); - if (minor == NULL) - return; - - BUG_ON(*minor >= COMEDI_NUM_BOARD_MINORS); + int minor; - comedi_free_board_minor(*minor); - dev_set_drvdata(hardware_device, NULL); - kfree(minor); + if (hardware_device == NULL) + return; + minor = comedi_find_board_minor(hardware_device); + if (minor < 0) + return; + BUG_ON(minor >= COMEDI_NUM_BOARD_MINORS); + comedi_free_board_minor(minor); } int comedi_pci_auto_config(struct pci_dev *pcidev, const char *board_name) diff --git a/drivers/staging/comedi/drivers/amplc_pc236.c b/drivers/staging/comedi/drivers/amplc_pc236.c index 7972cadd403..9a23d20938a 100644 --- a/drivers/staging/comedi/drivers/amplc_pc236.c +++ b/drivers/staging/comedi/drivers/amplc_pc236.c @@ -468,7 +468,7 @@ static int pc236_detach(struct comedi_device *dev) { printk(KERN_DEBUG "comedi%d: %s: detach\n", dev->minor, PC236_DRIVER_NAME); - if (devpriv) + if (dev->iobase) pc236_intr_disable(dev); if (dev->irq) diff --git a/drivers/staging/comedi/drivers/comedi_test.c b/drivers/staging/comedi/drivers/comedi_test.c index a804742b802..2567f9ab416 100644 --- a/drivers/staging/comedi/drivers/comedi_test.c +++ b/drivers/staging/comedi/drivers/comedi_test.c @@ -461,7 +461,7 @@ static int waveform_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) { devpriv->timer_running = 0; - del_timer(&devpriv->timer); + del_timer_sync(&devpriv->timer); return 0; } diff --git a/drivers/staging/comedi/drivers/das08.c b/drivers/staging/comedi/drivers/das08.c index c2dd0ed36a7..d2dd75e2af7 100644 --- a/drivers/staging/comedi/drivers/das08.c +++ b/drivers/staging/comedi/drivers/das08.c @@ -653,7 +653,7 @@ static int das08jr_ao_winsn(struct comedi_device *dev, int chan; lsb = data[0] & 0xff; - msb = (data[0] >> 8) & 0xf; + msb = (data[0] >> 8) & 0xff; chan = CR_CHAN(insn->chanspec); diff --git a/drivers/staging/comedi/drivers/jr3_pci.c b/drivers/staging/comedi/drivers/jr3_pci.c index 6a79ba10630..d7e63419e61 100644 --- a/drivers/staging/comedi/drivers/jr3_pci.c +++ b/drivers/staging/comedi/drivers/jr3_pci.c @@ -905,7 +905,7 @@ static int jr3_pci_attach(struct comedi_device *dev, } /* Reset DSP card */ - devpriv->iobase->channel[0].reset = 0; + writel(0, &devpriv->iobase->channel[0].reset); result = comedi_load_firmware(dev, "jr3pci.idm", jr3_download_firmware); dev_dbg(dev->hw_dev, "Firmare load %d\n", result); diff --git a/drivers/staging/comedi/drivers/ni_pcimio.c b/drivers/staging/comedi/drivers/ni_pcimio.c index 27baefa32b1..59c1f88894a 100644 --- a/drivers/staging/comedi/drivers/ni_pcimio.c +++ b/drivers/staging/comedi/drivers/ni_pcimio.c @@ -1023,7 +1023,7 @@ static const struct ni_board_struct ni_boards[] = { .ao_range_table = &range_ni_M_625x_ao, .reg_type = ni_reg_625x, .ao_unipolar = 0, - .ao_speed = 357, + .ao_speed = 350, .num_p0_dio_channels = 8, .caldac = {caldac_none}, .has_8255 = 0, @@ -1042,7 +1042,7 @@ static const struct ni_board_struct ni_boards[] = { .ao_range_table = &range_ni_M_625x_ao, .reg_type = ni_reg_625x, .ao_unipolar = 0, - .ao_speed = 357, + .ao_speed = 350, .num_p0_dio_channels = 8, .caldac = {caldac_none}, .has_8255 = 0, @@ -1061,7 +1061,7 @@ static const struct ni_board_struct ni_boards[] = { .ao_range_table = &range_ni_M_625x_ao, .reg_type = ni_reg_625x, .ao_unipolar = 0, - .ao_speed = 357, + .ao_speed = 350, .num_p0_dio_channels = 8, .caldac = {caldac_none}, .has_8255 = 0, @@ -1097,7 +1097,7 @@ static const struct ni_board_struct ni_boards[] = { .ao_range_table = &range_ni_M_625x_ao, .reg_type = ni_reg_625x, .ao_unipolar = 0, - .ao_speed = 357, + .ao_speed = 350, .num_p0_dio_channels = 32, .caldac = {caldac_none}, .has_8255 = 0, @@ -1116,7 +1116,7 @@ static const struct ni_board_struct ni_boards[] = { .ao_range_table = &range_ni_M_625x_ao, .reg_type = ni_reg_625x, .ao_unipolar = 0, - .ao_speed = 357, + .ao_speed = 350, .num_p0_dio_channels = 32, .caldac = {caldac_none}, .has_8255 = 0, @@ -1152,7 +1152,7 @@ static const struct ni_board_struct ni_boards[] = { .ao_range_table = &range_ni_M_628x_ao, .reg_type = ni_reg_628x, .ao_unipolar = 1, - .ao_speed = 357, + .ao_speed = 350, .num_p0_dio_channels = 8, .caldac = {caldac_none}, .has_8255 = 0, @@ -1171,7 +1171,7 @@ static const struct ni_board_struct ni_boards[] = { .ao_range_table = &range_ni_M_628x_ao, .reg_type = ni_reg_628x, .ao_unipolar = 1, - .ao_speed = 357, + .ao_speed = 350, .num_p0_dio_channels = 8, .caldac = {caldac_none}, .has_8255 = 0, @@ -1207,7 +1207,7 @@ static const struct ni_board_struct ni_boards[] = { .ao_range_table = &range_ni_M_628x_ao, .reg_type = ni_reg_628x, .ao_unipolar = 1, - .ao_speed = 357, + .ao_speed = 350, .num_p0_dio_channels = 32, .caldac = {caldac_none}, .has_8255 = 0, diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c index 23fc64b9988..c72128f30f1 100644 --- a/drivers/staging/comedi/drivers/s626.c +++ b/drivers/staging/comedi/drivers/s626.c @@ -2370,7 +2370,7 @@ static int s626_enc_insn_config(struct comedi_device *dev, /* (data==NULL) ? (Preloadvalue=0) : (Preloadvalue=data[0]); */ k->SetMode(dev, k, Setup, TRUE); - Preload(dev, k, *(insn->data)); + Preload(dev, k, data[0]); k->PulseIndex(dev, k); SetLatchSource(dev, k, valueSrclatch); k->SetEnable(dev, k, (uint16_t) (enab != 0)); diff --git a/drivers/staging/comedi/internal.h b/drivers/staging/comedi/internal.h index 434ce343336..4208fb4cf0f 100644 --- a/drivers/staging/comedi/internal.h +++ b/drivers/staging/comedi/internal.h @@ -7,6 +7,7 @@ int insn_inval(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data); int comedi_alloc_board_minor(struct device *hardware_device); void comedi_free_board_minor(unsigned minor); +int comedi_find_board_minor(struct device *hardware_device); void comedi_reset_async_buf(struct comedi_async *async); int comedi_buf_alloc(struct comedi_device *dev, struct comedi_subdevice *s, unsigned long new_size); diff --git a/drivers/staging/media/lirc/lirc_sir.c b/drivers/staging/media/lirc/lirc_sir.c index 945d9623550..4afc3b41973 100644 --- a/drivers/staging/media/lirc/lirc_sir.c +++ b/drivers/staging/media/lirc/lirc_sir.c @@ -52,6 +52,7 @@ #include #include #include +#include #ifdef LIRC_ON_SA1100 #include #ifdef CONFIG_SA1100_COLLIE @@ -487,9 +488,11 @@ static struct lirc_driver driver = { .owner = THIS_MODULE, }; +static struct platform_device *lirc_sir_dev; static int init_chrdev(void) { + driver.dev = &lirc_sir_dev->dev; driver.minor = lirc_register_driver(&driver); if (driver.minor < 0) { printk(KERN_ERR LIRC_DRIVER_NAME ": init_chrdev() failed.\n"); @@ -1215,20 +1218,71 @@ static int init_lirc_sir(void) return 0; } +static int __devinit lirc_sir_probe(struct platform_device *dev) +{ + return 0; +} + +static int __devexit lirc_sir_remove(struct platform_device *dev) +{ + return 0; +} + +static struct platform_driver lirc_sir_driver = { + .probe = lirc_sir_probe, + .remove = __devexit_p(lirc_sir_remove), + .driver = { + .name = "lirc_sir", + .owner = THIS_MODULE, + }, +}; static int __init lirc_sir_init(void) { int retval; + retval = platform_driver_register(&lirc_sir_driver); + if (retval) { + printk(KERN_ERR LIRC_DRIVER_NAME ": Platform driver register " + "failed!\n"); + return -ENODEV; + } + + lirc_sir_dev = platform_device_alloc("lirc_dev", 0); + if (!lirc_sir_dev) { + printk(KERN_ERR LIRC_DRIVER_NAME ": Platform device alloc " + "failed!\n"); + retval = -ENOMEM; + goto pdev_alloc_fail; + } + + retval = platform_device_add(lirc_sir_dev); + if (retval) { + printk(KERN_ERR LIRC_DRIVER_NAME ": Platform device add " + "failed!\n"); + retval = -ENODEV; + goto pdev_add_fail; + } + retval = init_chrdev(); if (retval < 0) - return retval; + goto fail; + retval = init_lirc_sir(); if (retval) { drop_chrdev(); - return retval; + goto fail; } + return 0; + +fail: + platform_device_del(lirc_sir_dev); +pdev_add_fail: + platform_device_put(lirc_sir_dev); +pdev_alloc_fail: + platform_driver_unregister(&lirc_sir_driver); + return retval; } static void __exit lirc_sir_exit(void) @@ -1236,6 +1290,8 @@ static void __exit lirc_sir_exit(void) drop_hardware(); drop_chrdev(); drop_port(); + platform_device_unregister(lirc_sir_dev); + platform_driver_unregister(&lirc_sir_driver); printk(KERN_INFO LIRC_DRIVER_NAME ": Uninstalled.\n"); } diff --git a/drivers/staging/rtl8712/recv_linux.c b/drivers/staging/rtl8712/recv_linux.c index 0e26d5f6cf2..495ee1205e0 100644 --- a/drivers/staging/rtl8712/recv_linux.c +++ b/drivers/staging/rtl8712/recv_linux.c @@ -117,13 +117,8 @@ void r8712_recv_indicatepkt(struct _adapter *padapter, if (skb == NULL) goto _recv_indicatepkt_drop; skb->data = precv_frame->u.hdr.rx_data; -#ifdef NET_SKBUFF_DATA_USES_OFFSET - skb->tail = (sk_buff_data_t)(precv_frame->u.hdr.rx_tail - - precv_frame->u.hdr.rx_head); -#else - skb->tail = (sk_buff_data_t)precv_frame->u.hdr.rx_tail; -#endif skb->len = precv_frame->u.hdr.len; + skb_set_tail_pointer(skb, skb->len); if ((pattrib->tcpchk_valid == 1) && (pattrib->tcp_chkrpt == 1)) skb->ip_summed = CHECKSUM_UNNECESSARY; else diff --git a/drivers/staging/rtl8712/rtl8712_recv.c b/drivers/staging/rtl8712/rtl8712_recv.c index fa6dc9c09b3..887a80709ab 100644 --- a/drivers/staging/rtl8712/rtl8712_recv.c +++ b/drivers/staging/rtl8712/rtl8712_recv.c @@ -1126,6 +1126,9 @@ static void recv_tasklet(void *priv) recvbuf2recvframe(padapter, pskb); skb_reset_tail_pointer(pskb); pskb->len = 0; - skb_queue_tail(&precvpriv->free_recv_skb_queue, pskb); + if (!skb_cloned(pskb)) + skb_queue_tail(&precvpriv->free_recv_skb_queue, pskb); + else + consume_skb(pskb); } } diff --git a/drivers/staging/rtl8712/usb_intf.c b/drivers/staging/rtl8712/usb_intf.c index 2c80745a446..7b3ae00ac54 100644 --- a/drivers/staging/rtl8712/usb_intf.c +++ b/drivers/staging/rtl8712/usb_intf.c @@ -66,6 +66,8 @@ static struct usb_device_id rtl871x_usb_id_tbl[] = { {USB_DEVICE(0x0B05, 0x1791)}, /* 11n mode disable */ /* Belkin */ {USB_DEVICE(0x050D, 0x945A)}, + /* ISY IWL - Belkin clone */ + {USB_DEVICE(0x050D, 0x11F1)}, /* Corega */ {USB_DEVICE(0x07AA, 0x0047)}, /* D-Link */ diff --git a/drivers/staging/speakup/main.c b/drivers/staging/speakup/main.c index 92b34e29ad0..40e2488b967 100644 --- a/drivers/staging/speakup/main.c +++ b/drivers/staging/speakup/main.c @@ -1854,7 +1854,7 @@ static void speakup_bits(struct vc_data *vc) static int handle_goto(struct vc_data *vc, u_char type, u_char ch, u_short key) { - static u_char *goto_buf = "\0\0\0\0\0\0"; + static u_char goto_buf[8]; static int num; int maxlen, go_pos; char *cp; diff --git a/drivers/staging/speakup/speakup_soft.c b/drivers/staging/speakup/speakup_soft.c index 42cdafeea35..b5130c8bcb6 100644 --- a/drivers/staging/speakup/speakup_soft.c +++ b/drivers/staging/speakup/speakup_soft.c @@ -40,7 +40,7 @@ static int softsynth_is_alive(struct spk_synth *synth); static unsigned char get_index(void); static struct miscdevice synth_device; -static int initialized; +static int init_pos; static int misc_registered; static struct var_t vars[] = { @@ -194,7 +194,7 @@ static int softsynth_close(struct inode *inode, struct file *fp) unsigned long flags; spk_lock(flags); synth_soft.alive = 0; - initialized = 0; + init_pos = 0; spk_unlock(flags); /* Make sure we let applications go before leaving */ speakup_start_ttys(); @@ -239,13 +239,8 @@ static ssize_t softsynth_read(struct file *fp, char *buf, size_t count, ch = '\x18'; } else if (synth_buffer_empty()) { break; - } else if (!initialized) { - if (*init) { - ch = *init; - init++; - } else { - initialized = 1; - } + } else if (init[init_pos]) { + ch = init[init_pos++]; } else { ch = synth_buffer_getc(); } diff --git a/drivers/staging/speakup/synth.c b/drivers/staging/speakup/synth.c index 331eae78870..5710fc582be 100644 --- a/drivers/staging/speakup/synth.c +++ b/drivers/staging/speakup/synth.c @@ -342,7 +342,7 @@ int synth_init(char *synth_name) mutex_lock(&spk_mutex); /* First, check if we already have it loaded. */ - for (i = 0; synths[i] != NULL && i < MAXSYNTHS; i++) + for (i = 0; i < MAXSYNTHS && synths[i] != NULL; i++) if (strcmp(synths[i]->name, synth_name) == 0) synth = synths[i]; @@ -423,7 +423,7 @@ int synth_add(struct spk_synth *in_synth) int i; int status = 0; mutex_lock(&spk_mutex); - for (i = 0; synths[i] != NULL && i < MAXSYNTHS; i++) + for (i = 0; i < MAXSYNTHS && synths[i] != NULL; i++) /* synth_remove() is responsible for rotating the array down */ if (in_synth == synths[i]) { mutex_unlock(&spk_mutex); diff --git a/drivers/staging/telephony/ixj.c b/drivers/staging/telephony/ixj.c index f96027921f6..638d2b8c687 100644 --- a/drivers/staging/telephony/ixj.c +++ b/drivers/staging/telephony/ixj.c @@ -3190,12 +3190,12 @@ static void ixj_write_cid(IXJ *j) ixj_fsk_alloc(j); - strcpy(sdmf1, j->cid_send.month); - strcat(sdmf1, j->cid_send.day); - strcat(sdmf1, j->cid_send.hour); - strcat(sdmf1, j->cid_send.min); - strcpy(sdmf2, j->cid_send.number); - strcpy(sdmf3, j->cid_send.name); + strlcpy(sdmf1, j->cid_send.month, sizeof(sdmf1)); + strlcat(sdmf1, j->cid_send.day, sizeof(sdmf1)); + strlcat(sdmf1, j->cid_send.hour, sizeof(sdmf1)); + strlcat(sdmf1, j->cid_send.min, sizeof(sdmf1)); + strlcpy(sdmf2, j->cid_send.number, sizeof(sdmf2)); + strlcpy(sdmf3, j->cid_send.name, sizeof(sdmf3)); len1 = strlen(sdmf1); len2 = strlen(sdmf2); @@ -3340,12 +3340,12 @@ static void ixj_write_cidcw(IXJ *j) ixj_pre_cid(j); } j->flags.cidcw_ack = 0; - strcpy(sdmf1, j->cid_send.month); - strcat(sdmf1, j->cid_send.day); - strcat(sdmf1, j->cid_send.hour); - strcat(sdmf1, j->cid_send.min); - strcpy(sdmf2, j->cid_send.number); - strcpy(sdmf3, j->cid_send.name); + strlcpy(sdmf1, j->cid_send.month, sizeof(sdmf1)); + strlcat(sdmf1, j->cid_send.day, sizeof(sdmf1)); + strlcat(sdmf1, j->cid_send.hour, sizeof(sdmf1)); + strlcat(sdmf1, j->cid_send.min, sizeof(sdmf1)); + strlcpy(sdmf2, j->cid_send.number, sizeof(sdmf2)); + strlcpy(sdmf3, j->cid_send.name, sizeof(sdmf3)); len1 = strlen(sdmf1); len2 = strlen(sdmf2); diff --git a/drivers/staging/vt6656/bssdb.h b/drivers/staging/vt6656/bssdb.h index a8f97ebb659..991ce3eecd8 100644 --- a/drivers/staging/vt6656/bssdb.h +++ b/drivers/staging/vt6656/bssdb.h @@ -92,7 +92,6 @@ typedef struct tagSRSNCapObject { } SRSNCapObject, *PSRSNCapObject; // BSS info(AP) -#pragma pack(1) typedef struct tagKnownBSS { // BSS info BOOL bActive; diff --git a/drivers/staging/vt6656/dpc.c b/drivers/staging/vt6656/dpc.c index c0edf97535d..4664e9d81d0 100644 --- a/drivers/staging/vt6656/dpc.c +++ b/drivers/staging/vt6656/dpc.c @@ -200,7 +200,7 @@ s_vProcessRxMACHeader ( } else if (!compare_ether_addr(pbyRxBuffer, &pDevice->abySNAP_RFC1042[0])) { cbHeaderSize += 6; pwType = (PWORD) (pbyRxBufferAddr + cbHeaderSize); - if ((*pwType == cpu_to_le16(ETH_P_IPX)) || + if ((*pwType == cpu_to_be16(ETH_P_IPX)) || (*pwType == cpu_to_le16(0xF380))) { cbHeaderSize -= 8; pwType = (PWORD) (pbyRxBufferAddr + cbHeaderSize); @@ -1238,7 +1238,7 @@ static BOOL s_bHandleRxEncryption ( PayloadLen -= (WLAN_HDR_ADDR3_LEN + 8 + 4); // 24 is 802.11 header, 8 is IV&ExtIV, 4 is crc *pdwRxTSC47_16 = cpu_to_le32(*(PDWORD)(pbyIV + 4)); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ExtIV: %lx\n",*pdwRxTSC47_16); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ExtIV: %x\n", *pdwRxTSC47_16); if (byDecMode == KEY_CTL_TKIP) { *pwRxTSC15_0 = cpu_to_le16(MAKEWORD(*(pbyIV+2), *pbyIV)); } else { @@ -1349,7 +1349,7 @@ static BOOL s_bHostWepRxEncryption ( PayloadLen -= (WLAN_HDR_ADDR3_LEN + 8 + 4); // 24 is 802.11 header, 8 is IV&ExtIV, 4 is crc *pdwRxTSC47_16 = cpu_to_le32(*(PDWORD)(pbyIV + 4)); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ExtIV: %lx\n",*pdwRxTSC47_16); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ExtIV: %x\n", *pdwRxTSC47_16); if (byDecMode == KEY_CTL_TKIP) { *pwRxTSC15_0 = cpu_to_le16(MAKEWORD(*(pbyIV+2), *pbyIV)); diff --git a/drivers/staging/vt6656/int.h b/drivers/staging/vt6656/int.h index a5d96b96817..27bc7f548ab 100644 --- a/drivers/staging/vt6656/int.h +++ b/drivers/staging/vt6656/int.h @@ -34,7 +34,6 @@ #include "device.h" /*--------------------- Export Definitions -------------------------*/ -#pragma pack(1) typedef struct tagSINTData { BYTE byTSR0; BYTE byPkt0; diff --git a/drivers/staging/vt6656/iocmd.h b/drivers/staging/vt6656/iocmd.h index 22710cef751..ae6e2d237b2 100644 --- a/drivers/staging/vt6656/iocmd.h +++ b/drivers/staging/vt6656/iocmd.h @@ -95,13 +95,12 @@ typedef enum tagWZONETYPE { // Ioctl interface structure // Command structure // -#pragma pack(1) typedef struct tagSCmdRequest { u8 name[16]; void *data; u16 wResult; u16 wCmdCode; -} SCmdRequest, *PSCmdRequest; +} __packed SCmdRequest, *PSCmdRequest; // // Scan @@ -111,7 +110,7 @@ typedef struct tagSCmdScan { u8 ssid[SSID_MAXLEN + 2]; -} SCmdScan, *PSCmdScan; +} __packed SCmdScan, *PSCmdScan; // // BSS Join @@ -126,7 +125,7 @@ typedef struct tagSCmdBSSJoin { BOOL bPSEnable; BOOL bShareKeyAuth; -} SCmdBSSJoin, *PSCmdBSSJoin; +} __packed SCmdBSSJoin, *PSCmdBSSJoin; // // Zonetype Setting @@ -137,7 +136,7 @@ typedef struct tagSCmdZoneTypeSet { BOOL bWrite; WZONETYPE ZoneType; -} SCmdZoneTypeSet, *PSCmdZoneTypeSet; +} __packed SCmdZoneTypeSet, *PSCmdZoneTypeSet; typedef struct tagSWPAResult { char ifname[100]; @@ -145,7 +144,7 @@ typedef struct tagSWPAResult { u8 key_mgmt; u8 eap_type; BOOL authenticated; -} SWPAResult, *PSWPAResult; +} __packed SWPAResult, *PSWPAResult; typedef struct tagSCmdStartAP { @@ -157,7 +156,7 @@ typedef struct tagSCmdStartAP { BOOL bShareKeyAuth; u8 byBasicRate; -} SCmdStartAP, *PSCmdStartAP; +} __packed SCmdStartAP, *PSCmdStartAP; typedef struct tagSCmdSetWEP { @@ -167,7 +166,7 @@ typedef struct tagSCmdSetWEP { BOOL bWepKeyAvailable[WEP_NKEYS]; u32 auWepKeyLength[WEP_NKEYS]; -} SCmdSetWEP, *PSCmdSetWEP; +} __packed SCmdSetWEP, *PSCmdSetWEP; typedef struct tagSBSSIDItem { @@ -180,14 +179,14 @@ typedef struct tagSBSSIDItem { BOOL bWEPOn; u32 uRSSI; -} SBSSIDItem; +} __packed SBSSIDItem; typedef struct tagSBSSIDList { u32 uItem; SBSSIDItem sBSSIDList[0]; -} SBSSIDList, *PSBSSIDList; +} __packed SBSSIDList, *PSBSSIDList; typedef struct tagSNodeItem { @@ -208,7 +207,7 @@ typedef struct tagSNodeItem { u32 uTxAttempts; u16 wFailureRatio; -} SNodeItem; +} __packed SNodeItem; typedef struct tagSNodeList { @@ -216,7 +215,7 @@ typedef struct tagSNodeList { u32 uItem; SNodeItem sNodeList[0]; -} SNodeList, *PSNodeList; +} __packed SNodeList, *PSNodeList; typedef struct tagSCmdLinkStatus { @@ -229,7 +228,7 @@ typedef struct tagSCmdLinkStatus { u32 uChannel; u32 uLinkRate; -} SCmdLinkStatus, *PSCmdLinkStatus; +} __packed SCmdLinkStatus, *PSCmdLinkStatus; // // 802.11 counter @@ -247,7 +246,7 @@ typedef struct tagSDot11MIBCount { u32 ReceivedFragmentCount; u32 MulticastReceivedFrameCount; u32 FCSErrorCount; -} SDot11MIBCount, *PSDot11MIBCount; +} __packed SDot11MIBCount, *PSDot11MIBCount; @@ -355,13 +354,13 @@ typedef struct tagSStatMIBCount { u32 ullTxBroadcastBytes[2]; u32 ullTxMulticastBytes[2]; u32 ullTxDirectedBytes[2]; -} SStatMIBCount, *PSStatMIBCount; +} __packed SStatMIBCount, *PSStatMIBCount; typedef struct tagSCmdValue { u32 dwValue; -} SCmdValue, *PSCmdValue; +} __packed SCmdValue, *PSCmdValue; // // hostapd & viawget ioctl related @@ -431,7 +430,7 @@ struct viawget_hostapd_param { u8 ssid[32]; } scan_req; } u; -}; +} __packed; /*--------------------- Export Classes ----------------------------*/ diff --git a/drivers/staging/vt6656/iowpa.h b/drivers/staging/vt6656/iowpa.h index 959c8868f6e..2522ddec718 100644 --- a/drivers/staging/vt6656/iowpa.h +++ b/drivers/staging/vt6656/iowpa.h @@ -67,12 +67,11 @@ enum { -#pragma pack(1) typedef struct viawget_wpa_header { u8 type; u16 req_ie_len; u16 resp_ie_len; -} viawget_wpa_header; +} __packed viawget_wpa_header; struct viawget_wpa_param { u32 cmd; @@ -113,9 +112,8 @@ struct viawget_wpa_param { u8 *buf; } scan_results; } u; -}; +} __packed; -#pragma pack(1) struct viawget_scan_result { u8 bssid[6]; u8 ssid[32]; @@ -130,7 +128,7 @@ struct viawget_scan_result { int noise; int level; int maxrate; -}; +} __packed; /*--------------------- Export Classes ----------------------------*/ diff --git a/drivers/staging/vt6656/key.c b/drivers/staging/vt6656/key.c index ee62a06a75f..ba3a561a79a 100644 --- a/drivers/staging/vt6656/key.c +++ b/drivers/staging/vt6656/key.c @@ -223,7 +223,7 @@ BOOL KeybSetKey( PSKeyManagement pTable, PBYTE pbyBSSID, DWORD dwKeyIndex, - unsigned long uKeyLength, + u32 uKeyLength, PQWORD pKeyRSC, PBYTE pbyKey, BYTE byKeyDecMode @@ -235,7 +235,8 @@ BOOL KeybSetKey( PSKeyItem pKey; unsigned int uKeyIdx; - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Enter KeybSetKey: %lX\n", dwKeyIndex); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO + "Enter KeybSetKey: %X\n", dwKeyIndex); j = (MAX_KEY_TABLE-1); for (i=0;i<(MAX_KEY_TABLE-1);i++) { @@ -261,7 +262,9 @@ BOOL KeybSetKey( if ((dwKeyIndex & TRANSMIT_KEY) != 0) { // Group transmit key pTable->KeyTable[i].dwGTKeyIndex = dwKeyIndex; - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Group transmit key(R)[%lX]: %d\n", pTable->KeyTable[i].dwGTKeyIndex, i); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO + "Group transmit key(R)[%X]: %d\n", + pTable->KeyTable[i].dwGTKeyIndex, i); } pTable->KeyTable[i].wKeyCtl &= 0xFF0F; // clear group key control filed pTable->KeyTable[i].wKeyCtl |= (byKeyDecMode << 4); @@ -302,9 +305,12 @@ BOOL KeybSetKey( } DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n"); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwTSC47_16: %lx\n ", pKey->dwTSC47_16); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->wTSC15_0: %x\n ", pKey->wTSC15_0); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwKeyIndex: %lx\n ", pKey->dwKeyIndex); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwTSC47_16: %x\n ", + pKey->dwTSC47_16); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->wTSC15_0: %x\n ", + pKey->wTSC15_0); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwKeyIndex: %x\n ", + pKey->dwKeyIndex); return (TRUE); } @@ -326,7 +332,9 @@ BOOL KeybSetKey( if ((dwKeyIndex & TRANSMIT_KEY) != 0) { // Group transmit key pTable->KeyTable[j].dwGTKeyIndex = dwKeyIndex; - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Group transmit key(N)[%lX]: %d\n", pTable->KeyTable[j].dwGTKeyIndex, j); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO + "Group transmit key(N)[%X]: %d\n", + pTable->KeyTable[j].dwGTKeyIndex, j); } pTable->KeyTable[j].wKeyCtl &= 0xFF0F; // clear group key control filed pTable->KeyTable[j].wKeyCtl |= (byKeyDecMode << 4); @@ -367,9 +375,11 @@ BOOL KeybSetKey( } DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n"); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwTSC47_16: %lx\n ", pKey->dwTSC47_16); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwTSC47_16: %x\n ", + pKey->dwTSC47_16); DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->wTSC15_0: %x\n ", pKey->wTSC15_0); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwKeyIndex: %lx\n ", pKey->dwKeyIndex); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwKeyIndex: %x\n ", + pKey->dwKeyIndex); return (TRUE); } @@ -597,7 +607,8 @@ BOOL KeybGetTransmitKey(PSKeyManagement pTable, PBYTE pbyBSSID, DWORD dwKeyType, DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"%x ", pTable->KeyTable[i].abyBSSID[ii]); } DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n"); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"dwGTKeyIndex: %lX\n", pTable->KeyTable[i].dwGTKeyIndex); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"dwGTKeyIndex: %X\n", + pTable->KeyTable[i].dwGTKeyIndex); return (TRUE); } @@ -664,7 +675,7 @@ BOOL KeybSetDefaultKey( void *pDeviceHandler, PSKeyManagement pTable, DWORD dwKeyIndex, - unsigned long uKeyLength, + u32 uKeyLength, PQWORD pKeyRSC, PBYTE pbyKey, BYTE byKeyDecMode @@ -696,7 +707,10 @@ BOOL KeybSetDefaultKey( if ((dwKeyIndex & TRANSMIT_KEY) != 0) { // Group transmit key pTable->KeyTable[MAX_KEY_TABLE-1].dwGTKeyIndex = dwKeyIndex; - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Group transmit key(R)[%lX]: %d\n", pTable->KeyTable[MAX_KEY_TABLE-1].dwGTKeyIndex, MAX_KEY_TABLE-1); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO + "Group transmit key(R)[%X]: %d\n", + pTable->KeyTable[MAX_KEY_TABLE-1].dwGTKeyIndex, + MAX_KEY_TABLE-1); } pTable->KeyTable[MAX_KEY_TABLE-1].wKeyCtl &= 0x7F00; // clear all key control filed @@ -747,9 +761,11 @@ BOOL KeybSetDefaultKey( } DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"\n"); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwTSC47_16: %lx\n", pKey->dwTSC47_16); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwTSC47_16: %x\n", + pKey->dwTSC47_16); DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->wTSC15_0: %x\n", pKey->wTSC15_0); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwKeyIndex: %lx\n", pKey->dwKeyIndex); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"pKey->dwKeyIndex: %x\n", + pKey->dwKeyIndex); return (TRUE); } @@ -775,7 +791,7 @@ BOOL KeybSetAllGroupKey( void *pDeviceHandler, PSKeyManagement pTable, DWORD dwKeyIndex, - unsigned long uKeyLength, + u32 uKeyLength, PQWORD pKeyRSC, PBYTE pbyKey, BYTE byKeyDecMode @@ -787,7 +803,8 @@ BOOL KeybSetAllGroupKey( PSKeyItem pKey; unsigned int uKeyIdx; - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Enter KeybSetAllGroupKey: %lX\n", dwKeyIndex); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Enter KeybSetAllGroupKey: %X\n", + dwKeyIndex); if ((dwKeyIndex & PAIRWISE_KEY) != 0) { // Pairwise key @@ -804,7 +821,9 @@ BOOL KeybSetAllGroupKey( if ((dwKeyIndex & TRANSMIT_KEY) != 0) { // Group transmit key pTable->KeyTable[i].dwGTKeyIndex = dwKeyIndex; - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Group transmit key(R)[%lX]: %d\n", pTable->KeyTable[i].dwGTKeyIndex, i); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO + "Group transmit key(R)[%X]: %d\n", + pTable->KeyTable[i].dwGTKeyIndex, i); } pTable->KeyTable[i].wKeyCtl &= 0xFF0F; // clear group key control filed diff --git a/drivers/staging/vt6656/key.h b/drivers/staging/vt6656/key.h index f749c7a027d..bd35d39621a 100644 --- a/drivers/staging/vt6656/key.h +++ b/drivers/staging/vt6656/key.h @@ -58,7 +58,7 @@ typedef struct tagSKeyItem { BOOL bKeyValid; - unsigned long uKeyLength; + u32 uKeyLength; BYTE abyKey[MAX_KEY_LEN]; QWORD KeyRSC; DWORD dwTSC47_16; @@ -107,7 +107,7 @@ BOOL KeybSetKey( PSKeyManagement pTable, PBYTE pbyBSSID, DWORD dwKeyIndex, - unsigned long uKeyLength, + u32 uKeyLength, PQWORD pKeyRSC, PBYTE pbyKey, BYTE byKeyDecMode @@ -146,7 +146,7 @@ BOOL KeybSetDefaultKey( void *pDeviceHandler, PSKeyManagement pTable, DWORD dwKeyIndex, - unsigned long uKeyLength, + u32 uKeyLength, PQWORD pKeyRSC, PBYTE pbyKey, BYTE byKeyDecMode @@ -156,7 +156,7 @@ BOOL KeybSetAllGroupKey( void *pDeviceHandler, PSKeyManagement pTable, DWORD dwKeyIndex, - unsigned long uKeyLength, + u32 uKeyLength, PQWORD pKeyRSC, PBYTE pbyKey, BYTE byKeyDecMode diff --git a/drivers/staging/vt6656/mac.c b/drivers/staging/vt6656/mac.c index af4a29d1477..8fddc7b3930 100644 --- a/drivers/staging/vt6656/mac.c +++ b/drivers/staging/vt6656/mac.c @@ -260,7 +260,8 @@ BYTE pbyData[24]; dwData1 <<= 16; dwData1 |= MAKEWORD(*(pbyAddr+4), *(pbyAddr+5)); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"1. wOffset: %d, Data: %lX, KeyCtl:%X\n", wOffset, dwData1, wKeyCtl); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"1. wOffset: %d, Data: %X,"\ + " KeyCtl:%X\n", wOffset, dwData1, wKeyCtl); //VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset); //VNSvOutPortD(dwIoBase + MAC_REG_MISCFFDATA, dwData); @@ -277,7 +278,8 @@ BYTE pbyData[24]; dwData2 <<= 8; dwData2 |= *(pbyAddr+0); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"2. wOffset: %d, Data: %lX\n", wOffset, dwData2); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"2. wOffset: %d, Data: %X\n", + wOffset, dwData2); //VNSvOutPortW(dwIoBase + MAC_REG_MISCFFNDEX, wOffset); //VNSvOutPortD(dwIoBase + MAC_REG_MISCFFDATA, dwData); diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c index 763e028a5cc..87394541d71 100644 --- a/drivers/staging/vt6656/main_usb.c +++ b/drivers/staging/vt6656/main_usb.c @@ -222,7 +222,7 @@ DEVICE_PARAM(b80211hEnable, "802.11h mode"); // Static vars definitions // -static struct usb_device_id vt6656_table[] __devinitdata = { +static struct usb_device_id vt6656_table[] = { {USB_DEVICE(VNT_USB_VENDOR_ID, VNT_USB_PRODUCT_ID)}, {} }; diff --git a/drivers/staging/vt6656/rf.c b/drivers/staging/vt6656/rf.c index 3fd0478a9a5..8cf0881888b 100644 --- a/drivers/staging/vt6656/rf.c +++ b/drivers/staging/vt6656/rf.c @@ -769,6 +769,9 @@ BYTE byPwr = pDevice->byCCKPwr; return TRUE; } + if (uCH == 0) + return -EINVAL; + switch (uRATE) { case RATE_1M: case RATE_2M: diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c index 9b64b102f55..3beb126e90f 100644 --- a/drivers/staging/vt6656/rxtx.c +++ b/drivers/staging/vt6656/rxtx.c @@ -377,7 +377,8 @@ s_vFillTxKey ( *(pbyIVHead+3) = (BYTE)(((pDevice->byKeyIndex << 6) & 0xc0) | 0x20); // 0x20 is ExtIV // Append IV&ExtIV after Mac Header *pdwExtIV = cpu_to_le32(pTransmitKey->dwTSC47_16); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"vFillTxKey()---- pdwExtIV: %lx\n", *pdwExtIV); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"vFillTxKey()---- pdwExtIV: %x\n", + *pdwExtIV); } else if (pTransmitKey->byCipherSuite == KEY_CTL_CCMP) { pTransmitKey->wTSC15_0++; @@ -1701,7 +1702,7 @@ s_bPacketToWirelessUsb( // 802.1H if (ntohs(psEthHeader->wType) > ETH_DATA_LEN) { if (pDevice->dwDiagRefCount == 0) { - if ((psEthHeader->wType == cpu_to_le16(ETH_P_IPX)) || + if ((psEthHeader->wType == cpu_to_be16(ETH_P_IPX)) || (psEthHeader->wType == cpu_to_le16(0xF380))) { memcpy((PBYTE) (pbyPayloadHead), abySNAP_Bridgetunnel, 6); @@ -1753,7 +1754,8 @@ s_bPacketToWirelessUsb( MIC_vAppend((PBYTE)&(psEthHeader->abyDstAddr[0]), 12); dwMIC_Priority = 0; MIC_vAppend((PBYTE)&dwMIC_Priority, 4); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MIC KEY: %lX, %lX\n", dwMICKey0, dwMICKey1); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MIC KEY: %X, %X\n", + dwMICKey0, dwMICKey1); /////////////////////////////////////////////////////////////////// @@ -2635,7 +2637,8 @@ vDMA0_tx_80211(PSDevice pDevice, struct sk_buff *skb) { MIC_vAppend((PBYTE)&(sEthHeader.abyDstAddr[0]), 12); dwMIC_Priority = 0; MIC_vAppend((PBYTE)&dwMIC_Priority, 4); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"DMA0_tx_8021:MIC KEY: %lX, %lX\n", dwMICKey0, dwMICKey1); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"DMA0_tx_8021:MIC KEY:"\ + " %X, %X\n", dwMICKey0, dwMICKey1); uLength = cbHeaderSize + cbMacHdLen + uPadding + cbIVlen; @@ -2655,7 +2658,8 @@ vDMA0_tx_80211(PSDevice pDevice, struct sk_buff *skb) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"uLength: %d, %d\n", uLength, cbFrameBodySize); DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"cbReqCount:%d, %d, %d, %d\n", cbReqCount, cbHeaderSize, uPadding, cbIVlen); - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MIC:%lx, %lx\n", *pdwMIC_L, *pdwMIC_R); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"MIC:%x, %x\n", + *pdwMIC_L, *pdwMIC_R); } @@ -2840,10 +2844,10 @@ int nsDMA_tx_packet(PSDevice pDevice, unsigned int uDMAIdx, struct sk_buff *skb) Packet_Type = skb->data[ETH_HLEN+1]; Descriptor_type = skb->data[ETH_HLEN+1+1+2]; Key_info = (skb->data[ETH_HLEN+1+1+2+1] << 8)|(skb->data[ETH_HLEN+1+1+2+2]); - if (pDevice->sTxEthHeader.wType == cpu_to_le16(ETH_P_PAE)) { - /* 802.1x OR eapol-key challenge frame transfer */ - if (((Protocol_Version == 1) || (Protocol_Version == 2)) && - (Packet_Type == 3)) { + if (pDevice->sTxEthHeader.wType == cpu_to_be16(ETH_P_PAE)) { + /* 802.1x OR eapol-key challenge frame transfer */ + if (((Protocol_Version == 1) || (Protocol_Version == 2)) && + (Packet_Type == 3)) { bTxeapol_key = TRUE; if(!(Key_info & BIT3) && //WPA or RSN group-key challenge (Key_info & BIT8) && (Key_info & BIT9)) { //send 2/2 key @@ -2989,19 +2993,19 @@ int nsDMA_tx_packet(PSDevice pDevice, unsigned int uDMAIdx, struct sk_buff *skb) } } - if (pDevice->sTxEthHeader.wType == cpu_to_le16(ETH_P_PAE)) { - if (pDevice->byBBType != BB_TYPE_11A) { - pDevice->wCurrentRate = RATE_1M; - pDevice->byACKRate = RATE_1M; - pDevice->byTopCCKBasicRate = RATE_1M; - pDevice->byTopOFDMBasicRate = RATE_6M; - } else { - pDevice->wCurrentRate = RATE_6M; - pDevice->byACKRate = RATE_6M; - pDevice->byTopCCKBasicRate = RATE_1M; - pDevice->byTopOFDMBasicRate = RATE_6M; - } - } + if (pDevice->sTxEthHeader.wType == cpu_to_be16(ETH_P_PAE)) { + if (pDevice->byBBType != BB_TYPE_11A) { + pDevice->wCurrentRate = RATE_1M; + pDevice->byACKRate = RATE_1M; + pDevice->byTopCCKBasicRate = RATE_1M; + pDevice->byTopOFDMBasicRate = RATE_6M; + } else { + pDevice->wCurrentRate = RATE_6M; + pDevice->byACKRate = RATE_6M; + pDevice->byTopCCKBasicRate = RATE_1M; + pDevice->byTopOFDMBasicRate = RATE_6M; + } + } DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "dma_tx: pDevice->wCurrentRate = %d\n", @@ -3017,7 +3021,7 @@ int nsDMA_tx_packet(PSDevice pDevice, unsigned int uDMAIdx, struct sk_buff *skb) if (bNeedEncryption == TRUE) { DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ntohs Pkt Type=%04x\n", ntohs(pDevice->sTxEthHeader.wType)); - if ((pDevice->sTxEthHeader.wType) == cpu_to_le16(ETH_P_PAE)) { + if ((pDevice->sTxEthHeader.wType) == cpu_to_be16(ETH_P_PAE)) { bNeedEncryption = FALSE; DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Pkt Type=%04x\n", (pDevice->sTxEthHeader.wType)); if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && (pMgmt->eCurrState == WMAC_STATE_ASSOC)) { @@ -3029,7 +3033,8 @@ int nsDMA_tx_packet(PSDevice pDevice, unsigned int uDMAIdx, struct sk_buff *skb) DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"error: KEY is GTK!!~~\n"); } else { - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Find PTK [%lX]\n", pTransmitKey->dwKeyIndex); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Find PTK [%X]\n", + pTransmitKey->dwKeyIndex); bNeedEncryption = TRUE; } } @@ -3043,7 +3048,8 @@ int nsDMA_tx_packet(PSDevice pDevice, unsigned int uDMAIdx, struct sk_buff *skb) if (pDevice->bEnableHostWEP) { if ((uNodeIndex != 0) && (pMgmt->sNodeDBTable[uNodeIndex].dwKeyIndex & PAIRWISE_KEY)) { - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Find PTK [%lX]\n", pTransmitKey->dwKeyIndex); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Find PTK [%X]\n", + pTransmitKey->dwKeyIndex); bNeedEncryption = TRUE; } } diff --git a/drivers/staging/vt6656/ttype.h b/drivers/staging/vt6656/ttype.h index 8e9450ef399..dfbf74713a8 100644 --- a/drivers/staging/vt6656/ttype.h +++ b/drivers/staging/vt6656/ttype.h @@ -29,6 +29,8 @@ #ifndef __TTYPE_H__ #define __TTYPE_H__ +#include + /******* Common definitions and typedefs ***********************************/ typedef int BOOL; @@ -42,17 +44,17 @@ typedef int BOOL; /****** Simple typedefs ***************************************************/ -typedef unsigned char BYTE; // 8-bit -typedef unsigned short WORD; // 16-bit -typedef unsigned long DWORD; // 32-bit +typedef u8 BYTE; +typedef u16 WORD; +typedef u32 DWORD; // QWORD is for those situation that we want // an 8-byte-aligned 8 byte long structure // which is NOT really a floating point number. typedef union tagUQuadWord { struct { - DWORD dwLowDword; - DWORD dwHighDword; + u32 dwLowDword; + u32 dwHighDword; } u; double DoNotUseThisField; } UQuadWord; @@ -60,8 +62,8 @@ typedef UQuadWord QWORD; // 64-bit /****** Common pointer types ***********************************************/ -typedef unsigned long ULONG_PTR; // 32-bit -typedef unsigned long DWORD_PTR; // 32-bit +typedef u32 ULONG_PTR; +typedef u32 DWORD_PTR; // boolean pointer diff --git a/drivers/staging/vt6656/wcmd.c b/drivers/staging/vt6656/wcmd.c index 78ea121b7e2..31fb96a54cf 100644 --- a/drivers/staging/vt6656/wcmd.c +++ b/drivers/staging/vt6656/wcmd.c @@ -316,17 +316,19 @@ s_MgrMakeProbeRequest( return pTxPacket; } -void vCommandTimerWait(void *hDeviceContext, unsigned int MSecond) +void vCommandTimerWait(void *hDeviceContext, unsigned long MSecond) { - PSDevice pDevice = (PSDevice)hDeviceContext; + PSDevice pDevice = (PSDevice)hDeviceContext; - init_timer(&pDevice->sTimerCommand); - pDevice->sTimerCommand.data = (unsigned long)pDevice; - pDevice->sTimerCommand.function = (TimerFunction)vRunCommand; - // RUN_AT :1 msec ~= (HZ/1024) - pDevice->sTimerCommand.expires = (unsigned int)RUN_AT((MSecond * HZ) >> 10); - add_timer(&pDevice->sTimerCommand); - return; + init_timer(&pDevice->sTimerCommand); + + pDevice->sTimerCommand.data = (unsigned long)pDevice; + pDevice->sTimerCommand.function = (TimerFunction)vRunCommand; + pDevice->sTimerCommand.expires = RUN_AT((MSecond * HZ) / 1000); + + add_timer(&pDevice->sTimerCommand); + + return; } void vRunCommand(void *hDeviceContext) diff --git a/drivers/staging/vt6656/wpa2.h b/drivers/staging/vt6656/wpa2.h index 46c295905b4..c359252a6b0 100644 --- a/drivers/staging/vt6656/wpa2.h +++ b/drivers/staging/vt6656/wpa2.h @@ -45,8 +45,8 @@ typedef struct tagsPMKIDInfo { } PMKIDInfo, *PPMKIDInfo; typedef struct tagSPMKIDCache { - unsigned long BSSIDInfoCount; - PMKIDInfo BSSIDInfo[MAX_PMKID_CACHE]; + u32 BSSIDInfoCount; + PMKIDInfo BSSIDInfo[MAX_PMKID_CACHE]; } SPMKIDCache, *PSPMKIDCache; diff --git a/drivers/staging/winbond/wbusb.c b/drivers/staging/winbond/wbusb.c index c3751a71838..9160049ff54 100644 --- a/drivers/staging/winbond/wbusb.c +++ b/drivers/staging/winbond/wbusb.c @@ -25,7 +25,7 @@ MODULE_DESCRIPTION("IS89C35 802.11bg WLAN USB Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION("0.1"); -static const struct usb_device_id wb35_table[] __devinitconst = { +static const struct usb_device_id wb35_table[] = { { USB_DEVICE(0x0416, 0x0035) }, { USB_DEVICE(0x18E8, 0x6201) }, { USB_DEVICE(0x18E8, 0x6206) }, diff --git a/drivers/staging/wlan-ng/prism2mgmt.c b/drivers/staging/wlan-ng/prism2mgmt.c index c3bb05dd744..4110a2f9425 100644 --- a/drivers/staging/wlan-ng/prism2mgmt.c +++ b/drivers/staging/wlan-ng/prism2mgmt.c @@ -406,7 +406,7 @@ int prism2mgmt_scan_results(wlandevice_t *wlandev, void *msgp) /* SSID */ req->ssid.status = P80211ENUM_msgitem_status_data_ok; req->ssid.data.len = le16_to_cpu(item->ssid.len); - req->ssid.data.len = min_t(u16, req->ssid.data.len, WLAN_BSSID_LEN); + req->ssid.data.len = min_t(u16, req->ssid.data.len, WLAN_SSID_MAXLEN); memcpy(req->ssid.data.data, item->ssid.data, req->ssid.data.len); /* supported rates */ diff --git a/drivers/staging/zcache/zcache-main.c b/drivers/staging/zcache/zcache-main.c index 2734dacacba..1812bedab32 100644 --- a/drivers/staging/zcache/zcache-main.c +++ b/drivers/staging/zcache/zcache-main.c @@ -1259,13 +1259,12 @@ static int zcache_pampd_get_data_and_free(char *data, size_t *bufsize, bool raw, void *pampd, struct tmem_pool *pool, struct tmem_oid *oid, uint32_t index) { - int ret = 0; - BUG_ON(!is_ephemeral(pool)); - zbud_decompress((struct page *)(data), pampd); + if (zbud_decompress((struct page *)(data), pampd) < 0) + return -EINVAL; zbud_free_and_delist((struct zbud_hdr *)pampd); atomic_dec(&zcache_curr_eph_pampd_count); - return ret; + return 0; } /* diff --git a/drivers/staging/zsmalloc/zsmalloc-main.c b/drivers/staging/zsmalloc/zsmalloc-main.c index 917461c6601..175b3c94d5a 100644 --- a/drivers/staging/zsmalloc/zsmalloc-main.c +++ b/drivers/staging/zsmalloc/zsmalloc-main.c @@ -426,12 +426,6 @@ static struct page *find_get_zspage(struct size_class *class) } -/* - * If this becomes a separate module, register zs_init() with - * module_init(), zs_exit with module_exit(), and remove zs_initialized -*/ -static int zs_initialized; - static int zs_cpu_notifier(struct notifier_block *nb, unsigned long action, void *pcpu) { @@ -490,7 +484,7 @@ static int zs_init(void) struct zs_pool *zs_create_pool(const char *name, gfp_t flags) { - int i, error, ovhd_size; + int i, ovhd_size; struct zs_pool *pool; if (!name) @@ -517,28 +511,9 @@ struct zs_pool *zs_create_pool(const char *name, gfp_t flags) } - /* - * If this becomes a separate module, register zs_init with - * module_init, and remove this block - */ - if (!zs_initialized) { - error = zs_init(); - if (error) - goto cleanup; - zs_initialized = 1; - } - pool->flags = flags; pool->name = name; - error = 0; /* Success */ - -cleanup: - if (error) { - zs_destroy_pool(pool); - pool = NULL; - } - return pool; } EXPORT_SYMBOL_GPL(zs_create_pool); @@ -749,3 +724,9 @@ u64 zs_get_total_size_bytes(struct zs_pool *pool) 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 "); diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index e56913259c9..a493049fd63 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -427,19 +427,8 @@ int iscsit_reset_np_thread( int iscsit_del_np_comm(struct iscsi_np *np) { - if (!np->np_socket) - return 0; - - /* - * Some network transports allocate their own struct sock->file, - * see if we need to free any additional allocated resources. - */ - if (np->np_flags & NPF_SCTP_STRUCT_FILE) { - kfree(np->np_socket->file); - np->np_socket->file = NULL; - } - - sock_release(np->np_socket); + if (np->np_socket) + sock_release(np->np_socket); return 0; } @@ -2365,7 +2354,7 @@ static void iscsit_build_conn_drop_async_message(struct iscsi_conn *conn) if (!conn_p) return; - cmd = iscsit_allocate_cmd(conn_p, GFP_KERNEL); + cmd = iscsit_allocate_cmd(conn_p, GFP_ATOMIC); if (!cmd) { iscsit_dec_conn_usage_count(conn_p); return; @@ -3202,7 +3191,6 @@ static int iscsit_build_sendtargets_response(struct iscsi_cmd *cmd) len += 1; if ((len + payload_len) > buffer_len) { - spin_unlock(&tiqn->tiqn_tpg_lock); end_of_buf = 1; goto eob; } @@ -3355,6 +3343,7 @@ static int iscsit_send_reject( hdr->opcode = ISCSI_OP_REJECT; hdr->flags |= ISCSI_FLAG_CMD_FINAL; hton24(hdr->dlength, ISCSI_HDR_LEN); + hdr->ffffffff = 0xffffffff; cmd->stat_sn = conn->stat_sn++; hdr->statsn = cpu_to_be32(cmd->stat_sn); hdr->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn); @@ -3520,7 +3509,9 @@ int iscsi_target_tx_thread(void *arg) */ iscsit_thread_check_cpumask(conn, current, 1); - schedule_timeout_interruptible(MAX_SCHEDULE_TIMEOUT); + wait_event_interruptible(conn->queues_wq, + !iscsit_conn_all_queues_empty(conn) || + ts->status == ISCSI_THREAD_SET_RESET); if ((ts->status == ISCSI_THREAD_SET_RESET) || signal_pending(current)) @@ -4089,13 +4080,8 @@ int iscsit_close_connection( kfree(conn->conn_ops); conn->conn_ops = NULL; - if (conn->sock) { - if (conn->conn_flags & CONNFLAG_SCTP_STRUCT_FILE) { - kfree(conn->sock->file); - conn->sock->file = NULL; - } + if (conn->sock) sock_release(conn->sock); - } conn->thread_set = NULL; pr_debug("Moving to TARG_CONN_STATE_FREE.\n"); diff --git a/drivers/target/iscsi/iscsi_target_core.h b/drivers/target/iscsi/iscsi_target_core.h index 2aaee7efa68..2e46ea404ca 100644 --- a/drivers/target/iscsi/iscsi_target_core.h +++ b/drivers/target/iscsi/iscsi_target_core.h @@ -25,10 +25,10 @@ #define NA_DATAOUT_TIMEOUT_RETRIES 5 #define NA_DATAOUT_TIMEOUT_RETRIES_MAX 15 #define NA_DATAOUT_TIMEOUT_RETRIES_MIN 1 -#define NA_NOPIN_TIMEOUT 5 +#define NA_NOPIN_TIMEOUT 15 #define NA_NOPIN_TIMEOUT_MAX 60 #define NA_NOPIN_TIMEOUT_MIN 3 -#define NA_NOPIN_RESPONSE_TIMEOUT 5 +#define NA_NOPIN_RESPONSE_TIMEOUT 30 #define NA_NOPIN_RESPONSE_TIMEOUT_MAX 60 #define NA_NOPIN_RESPONSE_TIMEOUT_MIN 3 #define NA_RANDOM_DATAIN_PDU_OFFSETS 0 @@ -224,7 +224,6 @@ enum iscsi_timer_flags_table { /* Used for struct iscsi_np->np_flags */ enum np_flags_table { NPF_IP_NETWORK = 0x00, - NPF_SCTP_STRUCT_FILE = 0x01 /* Bugfix */ }; /* Used for struct iscsi_np->np_thread_state */ @@ -492,6 +491,7 @@ struct iscsi_tmr_req { }; struct iscsi_conn { + wait_queue_head_t queues_wq; /* Authentication Successful for this connection */ u8 auth_complete; /* State connection is currently in */ @@ -511,7 +511,6 @@ struct iscsi_conn { u16 local_port; int net_size; u32 auth_id; -#define CONNFLAG_SCTP_STRUCT_FILE 0x01 u32 conn_flags; /* Used for iscsi_tx_login_rsp() */ u32 login_itt; diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c index a3656c9903a..3cb7a4f5b98 100644 --- a/drivers/target/iscsi/iscsi_target_login.c +++ b/drivers/target/iscsi/iscsi_target_login.c @@ -45,6 +45,7 @@ extern spinlock_t sess_idr_lock; static int iscsi_login_init_conn(struct iscsi_conn *conn) { + init_waitqueue_head(&conn->queues_wq); INIT_LIST_HEAD(&conn->conn_list); INIT_LIST_HEAD(&conn->conn_cmd_list); INIT_LIST_HEAD(&conn->immed_queue_list); @@ -794,22 +795,6 @@ int iscsi_target_setup_login_socket( return ret; } np->np_socket = sock; - /* - * The SCTP stack needs struct socket->file. - */ - if ((np->np_network_transport == ISCSI_SCTP_TCP) || - (np->np_network_transport == ISCSI_SCTP_UDP)) { - if (!sock->file) { - sock->file = kzalloc(sizeof(struct file), GFP_KERNEL); - if (!sock->file) { - pr_err("Unable to allocate struct" - " file for SCTP\n"); - ret = -ENOMEM; - goto fail; - } - np->np_flags |= NPF_SCTP_STRUCT_FILE; - } - } /* * Setup the np->np_sockaddr from the passed sockaddr setup * in iscsi_target_configfs.c code.. @@ -869,21 +854,15 @@ int iscsi_target_setup_login_socket( fail: np->np_socket = NULL; - if (sock) { - if (np->np_flags & NPF_SCTP_STRUCT_FILE) { - kfree(sock->file); - sock->file = NULL; - } - + if (sock) sock_release(sock); - } return ret; } static int __iscsi_target_login_thread(struct iscsi_np *np) { u8 buffer[ISCSI_HDR_LEN], iscsi_opcode, zero_tsih = 0; - int err, ret = 0, set_sctp_conn_flag, stop; + int err, ret = 0, stop; struct iscsi_conn *conn = NULL; struct iscsi_login *login; struct iscsi_portal_group *tpg = NULL; @@ -894,7 +873,6 @@ static int __iscsi_target_login_thread(struct iscsi_np *np) struct sockaddr_in6 sock_in6; flush_signals(current); - set_sctp_conn_flag = 0; sock = np->np_socket; spin_lock_bh(&np->np_thread_lock); @@ -917,35 +895,12 @@ static int __iscsi_target_login_thread(struct iscsi_np *np) spin_unlock_bh(&np->np_thread_lock); goto out; } - /* - * The SCTP stack needs struct socket->file. - */ - if ((np->np_network_transport == ISCSI_SCTP_TCP) || - (np->np_network_transport == ISCSI_SCTP_UDP)) { - if (!new_sock->file) { - new_sock->file = kzalloc( - sizeof(struct file), GFP_KERNEL); - if (!new_sock->file) { - pr_err("Unable to allocate struct" - " file for SCTP\n"); - sock_release(new_sock); - /* Get another socket */ - return 1; - } - set_sctp_conn_flag = 1; - } - } - iscsi_start_login_thread_timer(np); conn = kzalloc(sizeof(struct iscsi_conn), GFP_KERNEL); if (!conn) { pr_err("Could not allocate memory for" " new connection\n"); - if (set_sctp_conn_flag) { - kfree(new_sock->file); - new_sock->file = NULL; - } sock_release(new_sock); /* Get another socket */ return 1; @@ -955,9 +910,6 @@ static int __iscsi_target_login_thread(struct iscsi_np *np) conn->conn_state = TARG_CONN_STATE_FREE; conn->sock = new_sock; - if (set_sctp_conn_flag) - conn->conn_flags |= CONNFLAG_SCTP_STRUCT_FILE; - pr_debug("Moving to TARG_CONN_STATE_XPT_UP.\n"); conn->conn_state = TARG_CONN_STATE_XPT_UP; @@ -1205,13 +1157,8 @@ static int __iscsi_target_login_thread(struct iscsi_np *np) iscsi_release_param_list(conn->param_list); conn->param_list = NULL; } - if (conn->sock) { - if (conn->conn_flags & CONNFLAG_SCTP_STRUCT_FILE) { - kfree(conn->sock->file); - conn->sock->file = NULL; - } + if (conn->sock) sock_release(conn->sock); - } kfree(conn); if (tpg) { diff --git a/drivers/target/iscsi/iscsi_target_tpg.c b/drivers/target/iscsi/iscsi_target_tpg.c index 879d8d0fa3f..c3d7bf54f3d 100644 --- a/drivers/target/iscsi/iscsi_target_tpg.c +++ b/drivers/target/iscsi/iscsi_target_tpg.c @@ -672,6 +672,12 @@ int iscsit_ta_generate_node_acls( pr_debug("iSCSI_TPG[%hu] - Generate Initiator Portal Group ACLs: %s\n", tpg->tpgt, (a->generate_node_acls) ? "Enabled" : "Disabled"); + if (flag == 1 && a->cache_dynamic_acls == 0) { + pr_debug("Explicitly setting cache_dynamic_acls=1 when " + "generate_node_acls=1\n"); + a->cache_dynamic_acls = 1; + } + return 0; } @@ -711,6 +717,12 @@ int iscsit_ta_cache_dynamic_acls( return -EINVAL; } + if (a->generate_node_acls == 1 && flag == 0) { + pr_debug("Skipping cache_dynamic_acls=0 when" + " generate_node_acls=1\n"); + return 0; + } + a->cache_dynamic_acls = flag; pr_debug("iSCSI_TPG[%hu] - Cache Dynamic Initiator Portal Group" " ACLs %s\n", tpg->tpgt, (a->cache_dynamic_acls) ? diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c index 4eba86d2bd8..4c05ed6becc 100644 --- a/drivers/target/iscsi/iscsi_target_util.c +++ b/drivers/target/iscsi/iscsi_target_util.c @@ -656,7 +656,7 @@ void iscsit_add_cmd_to_immediate_queue( atomic_set(&conn->check_immediate_queue, 1); spin_unlock_bh(&conn->immed_queue_lock); - wake_up_process(conn->thread_set->tx_thread); + wake_up(&conn->queues_wq); } struct iscsi_queue_req *iscsit_get_cmd_from_immediate_queue(struct iscsi_conn *conn) @@ -730,7 +730,7 @@ void iscsit_add_cmd_to_response_queue( atomic_inc(&cmd->response_queue_count); spin_unlock_bh(&conn->response_queue_lock); - wake_up_process(conn->thread_set->tx_thread); + wake_up(&conn->queues_wq); } struct iscsi_queue_req *iscsit_get_cmd_from_response_queue(struct iscsi_conn *conn) @@ -784,6 +784,24 @@ static void iscsit_remove_cmd_from_response_queue( } } +bool iscsit_conn_all_queues_empty(struct iscsi_conn *conn) +{ + bool empty; + + spin_lock_bh(&conn->immed_queue_lock); + empty = list_empty(&conn->immed_queue_list); + spin_unlock_bh(&conn->immed_queue_lock); + + if (!empty) + return empty; + + spin_lock_bh(&conn->response_queue_lock); + empty = list_empty(&conn->response_queue_list); + spin_unlock_bh(&conn->response_queue_lock); + + return empty; +} + void iscsit_free_queue_reqs_for_conn(struct iscsi_conn *conn) { struct iscsi_queue_req *qr, *qr_tmp; diff --git a/drivers/target/iscsi/iscsi_target_util.h b/drivers/target/iscsi/iscsi_target_util.h index 835bf7de028..cfac698fb3c 100644 --- a/drivers/target/iscsi/iscsi_target_util.h +++ b/drivers/target/iscsi/iscsi_target_util.h @@ -28,6 +28,7 @@ extern struct iscsi_queue_req *iscsit_get_cmd_from_immediate_queue(struct iscsi_ extern void iscsit_add_cmd_to_response_queue(struct iscsi_cmd *, struct iscsi_conn *, u8); extern struct iscsi_queue_req *iscsit_get_cmd_from_response_queue(struct iscsi_conn *); extern void iscsit_remove_cmd_from_tx_queues(struct iscsi_cmd *, struct iscsi_conn *); +extern bool iscsit_conn_all_queues_empty(struct iscsi_conn *); extern void iscsit_free_queue_reqs_for_conn(struct iscsi_conn *); extern void iscsit_release_cmd(struct iscsi_cmd *); extern void iscsit_free_cmd(struct iscsi_cmd *); diff --git a/drivers/target/target_core_cdb.c b/drivers/target/target_core_cdb.c index 30a67707036..52a5f6208ac 100644 --- a/drivers/target/target_core_cdb.c +++ b/drivers/target/target_core_cdb.c @@ -1022,11 +1022,11 @@ int target_emulate_unmap(struct se_task *task) struct se_cmd *cmd = task->task_se_cmd; struct se_device *dev = cmd->se_dev; unsigned char *buf, *ptr = NULL; - unsigned char *cdb = &cmd->t_task_cdb[0]; sector_t lba; - unsigned int size = cmd->data_length, range; - int ret = 0, offset; - unsigned short dl, bd_dl; + int size = cmd->data_length; + u32 range; + int ret = 0; + int dl, bd_dl; if (!dev->transport->do_discard) { pr_err("UNMAP emulation not supported for: %s\n", @@ -1035,24 +1035,41 @@ int target_emulate_unmap(struct se_task *task) return -ENOSYS; } - /* First UNMAP block descriptor starts at 8 byte offset */ - offset = 8; - size -= 8; - dl = get_unaligned_be16(&cdb[0]); - bd_dl = get_unaligned_be16(&cdb[2]); - buf = transport_kmap_data_sg(cmd); - ptr = &buf[offset]; - pr_debug("UNMAP: Sub: %s Using dl: %hu bd_dl: %hu size: %hu" + dl = get_unaligned_be16(&buf[0]); + bd_dl = get_unaligned_be16(&buf[2]); + + size = min(size - 8, bd_dl); + if (size / 16 > dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count) { + cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; + ret = -EINVAL; + goto err; + } + + /* First UNMAP block descriptor starts at 8 byte offset */ + ptr = &buf[8]; + pr_debug("UNMAP: Sub: %s Using dl: %u bd_dl: %u size: %u" " ptr: %p\n", dev->transport->name, dl, bd_dl, size, ptr); - while (size) { + while (size >= 16) { lba = get_unaligned_be64(&ptr[0]); range = get_unaligned_be32(&ptr[8]); pr_debug("UNMAP: Using lba: %llu and range: %u\n", (unsigned long long)lba, range); + if (range > dev->se_sub_dev->se_dev_attrib.max_unmap_lba_count) { + cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST; + ret = -EINVAL; + goto err; + } + + if (lba + range > dev->transport->get_blocks(dev) + 1) { + cmd->scsi_sense_reason = TCM_ADDRESS_OUT_OF_RANGE; + ret = -EINVAL; + goto err; + } + ret = dev->transport->do_discard(dev, lba, range); if (ret < 0) { pr_err("blkdev_issue_discard() failed: %d\n", @@ -1107,7 +1124,7 @@ int target_emulate_write_same(struct se_task *task) if (num_blocks != 0) range = num_blocks; else - range = (dev->transport->get_blocks(dev) - lba); + range = (dev->transport->get_blocks(dev) - lba) + 1; pr_debug("WRITE_SAME UNMAP: LBA: %llu Range: %llu\n", (unsigned long long)lba, (unsigned long long)range); diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index cbb66537d23..dbcede31ff8 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c @@ -3115,6 +3115,7 @@ static int __init target_core_init_configfs(void) GFP_KERNEL); if (!target_cg->default_groups) { pr_err("Unable to allocate target_cg->default_groups\n"); + ret = -ENOMEM; goto out_global; } @@ -3130,6 +3131,7 @@ static int __init target_core_init_configfs(void) GFP_KERNEL); if (!hba_cg->default_groups) { pr_err("Unable to allocate hba_cg->default_groups\n"); + ret = -ENOMEM; goto out_global; } config_group_init_type_name(&alua_group, @@ -3145,6 +3147,7 @@ static int __init target_core_init_configfs(void) GFP_KERNEL); if (!alua_cg->default_groups) { pr_err("Unable to allocate alua_cg->default_groups\n"); + ret = -ENOMEM; goto out_global; } @@ -3156,14 +3159,17 @@ static int __init target_core_init_configfs(void) * Add core/alua/lu_gps/default_lu_gp */ lu_gp = core_alua_allocate_lu_gp("default_lu_gp", 1); - if (IS_ERR(lu_gp)) + if (IS_ERR(lu_gp)) { + ret = -ENOMEM; goto out_global; + } lu_gp_cg = &alua_lu_gps_group; lu_gp_cg->default_groups = kzalloc(sizeof(struct config_group) * 2, GFP_KERNEL); if (!lu_gp_cg->default_groups) { pr_err("Unable to allocate lu_gp_cg->default_groups\n"); + ret = -ENOMEM; goto out_global; } @@ -3191,7 +3197,8 @@ static int __init target_core_init_configfs(void) if (ret < 0) goto out; - if (core_dev_setup_virtual_lun0() < 0) + ret = core_dev_setup_virtual_lun0(); + if (ret < 0) goto out; return 0; diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index aa626774638..26c62f05975 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -826,20 +826,20 @@ int se_dev_check_shutdown(struct se_device *dev) u32 se_dev_align_max_sectors(u32 max_sectors, u32 block_size) { - u32 tmp, aligned_max_sectors; + u32 aligned_max_sectors; + u32 alignment; /* * Limit max_sectors to a PAGE_SIZE aligned value for modern * transport_allocate_data_tasks() operation. */ - tmp = rounddown((max_sectors * block_size), PAGE_SIZE); - aligned_max_sectors = (tmp / block_size); - if (max_sectors != aligned_max_sectors) { - printk(KERN_INFO "Rounding down aligned max_sectors from %u" - " to %u\n", max_sectors, aligned_max_sectors); - return aligned_max_sectors; - } + alignment = max(1ul, PAGE_SIZE / block_size); + aligned_max_sectors = rounddown(max_sectors, alignment); + + if (max_sectors != aligned_max_sectors) + pr_info("Rounding down aligned max_sectors from %u to %u\n", + max_sectors, aligned_max_sectors); - return max_sectors; + return aligned_max_sectors; } void se_dev_set_default_attribs( @@ -1665,6 +1665,7 @@ int core_dev_setup_virtual_lun0(void) ret = PTR_ERR(dev); goto out; } + dev->dev_link_magic = SE_DEV_LINK_MAGIC; se_dev->se_dev_ptr = dev; g_lun0_dev = dev; diff --git a/drivers/target/target_core_fabric_configfs.c b/drivers/target/target_core_fabric_configfs.c index 405cc98eaed..817ba7c849e 100644 --- a/drivers/target/target_core_fabric_configfs.c +++ b/drivers/target/target_core_fabric_configfs.c @@ -72,6 +72,12 @@ static int target_fabric_mappedlun_link( struct se_portal_group *se_tpg; struct config_item *nacl_ci, *tpg_ci, *tpg_ci_s, *wwn_ci, *wwn_ci_s; int ret = 0, lun_access; + + if (lun->lun_link_magic != SE_LUN_LINK_MAGIC) { + pr_err("Bad lun->lun_link_magic, not a valid lun_ci pointer:" + " %p to struct lun: %p\n", lun_ci, lun); + return -EFAULT; + } /* * Ensure that the source port exists */ @@ -763,6 +769,11 @@ static int target_fabric_port_link( ret = -ENODEV; goto out; } + if (dev->dev_link_magic != SE_DEV_LINK_MAGIC) { + pr_err("Bad dev->dev_link_magic, not a valid se_dev_ci pointer:" + " %p to struct se_device: %p\n", se_dev_ci, dev); + return -EFAULT; + } lun_p = core_dev_add_lun(se_tpg, dev->se_hba, dev, lun->unpacked_lun); diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index c3148b10b4b..89d10e6a82e 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c @@ -2038,7 +2038,7 @@ static int __core_scsi3_write_aptpl_to_file( if (IS_ERR(file) || !file || !file->f_dentry) { pr_err("filp_open(%s) for APTPL metadata" " failed\n", path); - return (PTR_ERR(file) < 0 ? PTR_ERR(file) : -ENOENT); + return IS_ERR(file) ? PTR_ERR(file) : -ENOENT; } iov[0].iov_base = &buf[0]; @@ -3826,7 +3826,7 @@ int target_scsi3_emulate_pr_out(struct se_task *task) " SPC-2 reservation is held, returning" " RESERVATION_CONFLICT\n"); cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT; - ret = EINVAL; + ret = -EINVAL; goto out; } @@ -3836,7 +3836,8 @@ int target_scsi3_emulate_pr_out(struct se_task *task) */ if (!cmd->se_sess) { cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; - return -EINVAL; + ret = -EINVAL; + goto out; } if (cmd->data_length < 24) { diff --git a/drivers/target/target_core_tmr.c b/drivers/target/target_core_tmr.c index f015839aef8..4a5c6d758c4 100644 --- a/drivers/target/target_core_tmr.c +++ b/drivers/target/target_core_tmr.c @@ -140,15 +140,15 @@ void core_tmr_abort_task( printk("ABORT_TASK: Found referenced %s task_tag: %u\n", se_cmd->se_tfo->get_fabric_name(), ref_tag); - spin_lock_irq(&se_cmd->t_state_lock); + spin_lock(&se_cmd->t_state_lock); if (se_cmd->transport_state & CMD_T_COMPLETE) { printk("ABORT_TASK: ref_tag: %u already complete, skipping\n", ref_tag); - spin_unlock_irq(&se_cmd->t_state_lock); + spin_unlock(&se_cmd->t_state_lock); spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); goto out; } se_cmd->transport_state |= CMD_T_ABORTED; - spin_unlock_irq(&se_cmd->t_state_lock); + spin_unlock(&se_cmd->t_state_lock); list_del_init(&se_cmd->se_cmd_list); kref_get(&se_cmd->cmd_kref); diff --git a/drivers/target/target_core_tpg.c b/drivers/target/target_core_tpg.c index e320ec24aa1..ba537b6fd85 100644 --- a/drivers/target/target_core_tpg.c +++ b/drivers/target/target_core_tpg.c @@ -677,6 +677,7 @@ int core_tpg_register( for (i = 0; i < TRANSPORT_MAX_LUNS_PER_TPG; i++) { lun = se_tpg->tpg_lun_list[i]; lun->unpacked_lun = i; + lun->lun_link_magic = SE_LUN_LINK_MAGIC; lun->lun_status = TRANSPORT_LUN_STATUS_FREE; atomic_set(&lun->lun_acl_count, 0); init_completion(&lun->lun_shutdown_comp); diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 843ad54801b..5362428ea9b 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -1341,6 +1341,7 @@ struct se_device *transport_add_device_to_core_hba( dev->se_hba = hba; dev->se_sub_dev = se_dev; dev->transport = transport; + dev->dev_link_magic = SE_DEV_LINK_MAGIC; INIT_LIST_HEAD(&dev->dev_list); INIT_LIST_HEAD(&dev->dev_sep_list); INIT_LIST_HEAD(&dev->dev_tmr_list); @@ -1750,7 +1751,8 @@ static void target_complete_tmr_failure(struct work_struct *work) se_cmd->se_tmr_req->response = TMR_LUN_DOES_NOT_EXIST; se_cmd->se_tfo->queue_tm_rsp(se_cmd); - transport_generic_free_cmd(se_cmd, 0); + + transport_cmd_check_stop_to_fabric(se_cmd); } /** @@ -1978,6 +1980,7 @@ void transport_generic_request_failure(struct se_cmd *cmd) case TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE: case TCM_UNKNOWN_MODE_PAGE: case TCM_WRITE_PROTECTED: + case TCM_ADDRESS_OUT_OF_RANGE: case TCM_CHECK_CONDITION_ABORT_CMD: case TCM_CHECK_CONDITION_UNIT_ATTENTION: case TCM_CHECK_CONDITION_NOT_READY: @@ -3171,15 +3174,20 @@ static int transport_generic_cmd_sequencer( /* Returns CHECK_CONDITION + INVALID_CDB_FIELD */ goto out_invalid_cdb_field; } - + /* + * For the overflow case keep the existing fabric provided + * ->data_length. Otherwise for the underflow case, reset + * ->data_length to the smaller SCSI expected data transfer + * length. + */ if (size > cmd->data_length) { cmd->se_cmd_flags |= SCF_OVERFLOW_BIT; cmd->residual_count = (size - cmd->data_length); } else { cmd->se_cmd_flags |= SCF_UNDERFLOW_BIT; cmd->residual_count = (cmd->data_length - size); + cmd->data_length = size; } - cmd->data_length = size; } if (cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB && @@ -3679,9 +3687,9 @@ transport_generic_get_mem(struct se_cmd *cmd) return 0; out: - while (i >= 0) { - __free_page(sg_page(&cmd->t_data_sg[i])); + while (i > 0) { i--; + __free_page(sg_page(&cmd->t_data_sg[i])); } kfree(cmd->t_data_sg); cmd->t_data_sg = NULL; @@ -4661,6 +4669,15 @@ int transport_send_check_condition_and_sense( /* WRITE PROTECTED */ buffer[offset+SPC_ASC_KEY_OFFSET] = 0x27; break; + case TCM_ADDRESS_OUT_OF_RANGE: + /* CURRENT ERROR */ + buffer[offset] = 0x70; + buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10; + /* ILLEGAL REQUEST */ + buffer[offset+SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST; + /* LOGICAL BLOCK ADDRESS OUT OF RANGE */ + buffer[offset+SPC_ASC_KEY_OFFSET] = 0x21; + break; case TCM_CHECK_CONDITION_UNIT_ATTENTION: /* CURRENT ERROR */ buffer[offset] = 0x70; diff --git a/drivers/target/tcm_fc/tfc_cmd.c b/drivers/target/tcm_fc/tfc_cmd.c index a375f257aab..da90f647695 100644 --- a/drivers/target/tcm_fc/tfc_cmd.c +++ b/drivers/target/tcm_fc/tfc_cmd.c @@ -240,6 +240,8 @@ u32 ft_get_task_tag(struct se_cmd *se_cmd) { struct ft_cmd *cmd = container_of(se_cmd, struct ft_cmd, se_cmd); + if (cmd->aborted) + return ~0; return fc_seq_exch(cmd->seq)->rxid; } diff --git a/drivers/target/tcm_fc/tfc_sess.c b/drivers/target/tcm_fc/tfc_sess.c index 87901fa74dd..9249998a837 100644 --- a/drivers/target/tcm_fc/tfc_sess.c +++ b/drivers/target/tcm_fc/tfc_sess.c @@ -356,11 +356,11 @@ static int ft_prli_locked(struct fc_rport_priv *rdata, u32 spp_len, tport = ft_tport_create(rdata->local_port); if (!tport) - return 0; /* not a target for this local port */ + goto not_target; /* not a target for this local port */ acl = ft_acl_get(tport->tpg, rdata); if (!acl) - return 0; + goto not_target; /* no target for this remote */ if (!rspp) goto fill; @@ -397,12 +397,18 @@ static int ft_prli_locked(struct fc_rport_priv *rdata, u32 spp_len, /* * OR in our service parameters with other provider (initiator), if any. - * TBD XXX - indicate RETRY capability? */ fill: fcp_parm = ntohl(spp->spp_params); + fcp_parm &= ~FCP_SPPF_RETRY; spp->spp_params = htonl(fcp_parm | FCP_SPPF_TARG_FCN); return FC_SPP_RESP_ACK; + +not_target: + fcp_parm = ntohl(spp->spp_params); + fcp_parm &= ~FCP_SPPF_TARG_FCN; + spp->spp_params = htonl(fcp_parm); + return 0; } /** @@ -431,7 +437,6 @@ static void ft_sess_rcu_free(struct rcu_head *rcu) { struct ft_sess *sess = container_of(rcu, struct ft_sess, rcu); - transport_deregister_session(sess->se_sess); kfree(sess); } @@ -439,6 +444,7 @@ static void ft_sess_free(struct kref *kref) { struct ft_sess *sess = container_of(kref, struct ft_sess, kref); + transport_deregister_session(sess->se_sess); call_rcu(&sess->rcu, ft_sess_rcu_free); } diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index c43b683b6eb..90dff8233ef 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -875,7 +875,7 @@ static int gsm_dlci_data_output_framed(struct gsm_mux *gsm, /* dlci->skb is locked by tx_lock */ if (dlci->skb == NULL) { - dlci->skb = skb_dequeue(&dlci->skb_list); + dlci->skb = skb_dequeue_tail(&dlci->skb_list); if (dlci->skb == NULL) return 0; first = 1; @@ -899,8 +899,11 @@ static int gsm_dlci_data_output_framed(struct gsm_mux *gsm, /* FIXME: need a timer or something to kick this so it can't get stuck with no work outstanding and no buffer free */ - if (msg == NULL) + if (msg == NULL) { + skb_queue_tail(&dlci->skb_list, dlci->skb); + dlci->skb = NULL; return -ENOMEM; + } dp = msg->data; if (dlci->adaption == 4) { /* Interruptible framed (Packetised Data) */ @@ -971,16 +974,19 @@ static void gsm_dlci_data_sweep(struct gsm_mux *gsm) static void gsm_dlci_data_kick(struct gsm_dlci *dlci) { unsigned long flags; + int sweep; spin_lock_irqsave(&dlci->gsm->tx_lock, flags); /* If we have nothing running then we need to fire up */ + sweep = (dlci->gsm->tx_bytes < TX_THRESH_LO); if (dlci->gsm->tx_bytes == 0) { if (dlci->net) gsm_dlci_data_output_framed(dlci->gsm, dlci); else gsm_dlci_data_output(dlci->gsm, dlci); - } else if (dlci->gsm->tx_bytes < TX_THRESH_LO) - gsm_dlci_data_sweep(dlci->gsm); + } + if (sweep) + gsm_dlci_data_sweep(dlci->gsm); spin_unlock_irqrestore(&dlci->gsm->tx_lock, flags); } @@ -1190,6 +1196,8 @@ static void gsm_control_message(struct gsm_mux *gsm, unsigned int command, u8 *data, int clen) { u8 buf[1]; + unsigned long flags; + switch (command) { case CMD_CLD: { struct gsm_dlci *dlci = gsm->dlci[0]; @@ -1215,7 +1223,9 @@ static void gsm_control_message(struct gsm_mux *gsm, unsigned int command, gsm->constipated = 0; gsm_control_reply(gsm, CMD_FCOFF, NULL, 0); /* Kick the link in case it is idling */ + spin_lock_irqsave(&gsm->tx_lock, flags); gsm_data_kick(gsm); + spin_unlock_irqrestore(&gsm->tx_lock, flags); break; case CMD_MSC: /* Out of band modem line change indicator for a DLCI */ @@ -2377,12 +2387,12 @@ static void gsmld_write_wakeup(struct tty_struct *tty) /* Queue poll */ clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); + spin_lock_irqsave(&gsm->tx_lock, flags); gsm_data_kick(gsm); if (gsm->tx_bytes < TX_THRESH_LO) { - spin_lock_irqsave(&gsm->tx_lock, flags); gsm_dlci_data_sweep(gsm); - spin_unlock_irqrestore(&gsm->tx_lock, flags); } + spin_unlock_irqrestore(&gsm->tx_lock, flags); } /** @@ -2889,6 +2899,10 @@ static int gsmtty_open(struct tty_struct *tty, struct file *filp) gsm = gsm_mux[mux]; if (gsm->dead) return -EL2HLT; + /* If DLCI 0 is not yet fully open return an error. This is ok from a locking + perspective as we don't have to worry about this if DLCI0 is lost */ + if (gsm->dlci[0] && gsm->dlci[0]->state != DLCI_OPEN) + return -EL2NSYNC; dlci = gsm->dlci[line]; if (dlci == NULL) dlci = gsm_dlci_alloc(gsm, line); diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 94b6eda87af..2303a02e9dc 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -1727,7 +1727,8 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, do_it_again: - BUG_ON(!tty->read_buf); + if (WARN_ON(!tty->read_buf)) + return -EAGAIN; c = job_control(tty, file); if (c < 0) diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index f574eef3075..b6dc908a24c 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -79,7 +79,7 @@ static int dw8250_handle_irq(struct uart_port *p) } else if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY) { /* Clear the USR and write the LCR again. */ (void)p->serial_in(p, UART_USR); - p->serial_out(p, d->last_lcr, UART_LCR); + p->serial_out(p, UART_LCR, d->last_lcr); return 1; } diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index 3614973c999..40747feed34 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -1125,6 +1125,8 @@ pci_xr17c154_setup(struct serial_private *priv, #define PCI_SUBDEVICE_ID_OCTPRO422 0x0208 #define PCI_SUBDEVICE_ID_POCTAL232 0x0308 #define PCI_SUBDEVICE_ID_POCTAL422 0x0408 +#define PCI_SUBDEVICE_ID_SIIG_DUAL_00 0x2500 +#define PCI_SUBDEVICE_ID_SIIG_DUAL_30 0x2530 #define PCI_VENDOR_ID_ADVANTECH 0x13fe #define PCI_DEVICE_ID_INTEL_CE4100_UART 0x2e66 #define PCI_DEVICE_ID_ADVANTECH_PCI3620 0x3620 @@ -3187,8 +3189,11 @@ static struct pci_device_id serial_pci_tbl[] = { * For now just used the hex ID 0x950a. */ { PCI_VENDOR_ID_OXSEMI, 0x950a, - PCI_SUBVENDOR_ID_SIIG, PCI_SUBDEVICE_ID_SIIG_DUAL_SERIAL, 0, 0, - pbn_b0_2_115200 }, + PCI_SUBVENDOR_ID_SIIG, PCI_SUBDEVICE_ID_SIIG_DUAL_00, + 0, 0, pbn_b0_2_115200 }, + { PCI_VENDOR_ID_OXSEMI, 0x950a, + PCI_SUBVENDOR_ID_SIIG, PCI_SUBDEVICE_ID_SIIG_DUAL_30, + 0, 0, pbn_b0_2_115200 }, { PCI_VENDOR_ID_OXSEMI, 0x950a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, pbn_b0_2_1130000 }, diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c index 3d569cd68f5..b69356c227c 100644 --- a/drivers/tty/serial/amba-pl011.c +++ b/drivers/tty/serial/amba-pl011.c @@ -1654,13 +1654,26 @@ pl011_set_termios(struct uart_port *port, struct ktermios *termios, old_cr &= ~ST_UART011_CR_OVSFACT; } + /* + * Workaround for the ST Micro oversampling variants to + * increase the bitrate slightly, by lowering the divisor, + * to avoid delayed sampling of start bit at high speeds, + * else we see data corruption. + */ + if (uap->vendor->oversampling) { + if ((baud >= 3000000) && (baud < 3250000) && (quot > 1)) + quot -= 1; + else if ((baud > 3250000) && (quot > 2)) + quot -= 2; + } /* Set baud rate */ writew(quot & 0x3f, port->membase + UART011_FBRD); writew(quot >> 6, port->membase + UART011_IBRD); /* * ----------v----------v----------v----------v----- - * NOTE: MUST BE WRITTEN AFTER UARTLCR_M & UARTLCR_L + * NOTE: lcrh_tx and lcrh_rx MUST BE WRITTEN AFTER + * UART011_FBRD & UART011_IBRD. * ----------^----------^----------^----------^----- */ writew(lcr_h, port->membase + uap->lcrh_rx); diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c index 144cd3987d4..17f587c5dba 100644 --- a/drivers/tty/serial/ifx6x60.c +++ b/drivers/tty/serial/ifx6x60.c @@ -552,6 +552,7 @@ static void ifx_port_shutdown(struct tty_port *port) container_of(port, struct ifx_spi_device, tty_port); mrdy_set_low(ifx_dev); + del_timer(&ifx_dev->spi_timer); clear_bit(IFX_SPI_STATE_TIMER_PENDING, &ifx_dev->flags); tasklet_kill(&ifx_dev->io_work_tasklet); } diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c index e7feceeebc2..0de7ed78863 100644 --- a/drivers/tty/serial/imx.c +++ b/drivers/tty/serial/imx.c @@ -756,6 +756,7 @@ static int imx_startup(struct uart_port *port) } } + spin_lock_irqsave(&sport->port.lock, flags); /* * Finally, clear and enable interrupts */ @@ -809,7 +810,6 @@ static int imx_startup(struct uart_port *port) /* * Enable modem status interrupts */ - spin_lock_irqsave(&sport->port.lock,flags); imx_enable_ms(&sport->port); spin_unlock_irqrestore(&sport->port.lock,flags); @@ -839,10 +839,13 @@ static void imx_shutdown(struct uart_port *port) { struct imx_port *sport = (struct imx_port *)port; unsigned long temp; + unsigned long flags; + spin_lock_irqsave(&sport->port.lock, flags); temp = readl(sport->port.membase + UCR2); temp &= ~(UCR2_TXEN); writel(temp, sport->port.membase + UCR2); + spin_unlock_irqrestore(&sport->port.lock, flags); if (USE_IRDA(sport)) { struct imxuart_platform_data *pdata; @@ -871,12 +874,14 @@ static void imx_shutdown(struct uart_port *port) * Disable all interrupts, port and break condition. */ + spin_lock_irqsave(&sport->port.lock, flags); temp = readl(sport->port.membase + UCR1); temp &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN); if (USE_IRDA(sport)) temp &= ~(UCR1_IREN); writel(temp, sport->port.membase + UCR1); + spin_unlock_irqrestore(&sport->port.lock, flags); } static void @@ -1219,6 +1224,9 @@ imx_console_write(struct console *co, const char *s, unsigned int count) struct imx_port *sport = imx_ports[co->index]; struct imx_port_ucrs old_ucr; unsigned int ucr1; + unsigned long flags; + + spin_lock_irqsave(&sport->port.lock, flags); /* * First, save UCR1/2/3 and then disable interrupts @@ -1244,6 +1252,8 @@ imx_console_write(struct console *co, const char *s, unsigned int count) while (!(readl(sport->port.membase + USR2) & USR2_TXDC)); imx_port_ucrs_restore(&sport->port, &old_ucr); + + spin_unlock_irqrestore(&sport->port.lock, flags); } /* diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index c2816f49480..7d4751474da 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c @@ -252,6 +252,9 @@ struct eg20t_port { dma_addr_t rx_buf_dma; struct dentry *debugfs; + + /* protect the eg20t_port private structure and io access to membase */ + spinlock_t lock; }; /** @@ -754,7 +757,8 @@ static void pch_dma_rx_complete(void *arg) tty_flip_buffer_push(tty); tty_kref_put(tty); async_tx_ack(priv->desc_rx); - pch_uart_hal_enable_interrupt(priv, PCH_UART_HAL_RX_INT); + pch_uart_hal_enable_interrupt(priv, PCH_UART_HAL_RX_INT | + PCH_UART_HAL_RX_ERR_INT); } static void pch_dma_tx_complete(void *arg) @@ -809,7 +813,8 @@ static int handle_rx_to(struct eg20t_port *priv) int rx_size; int ret; if (!priv->start_rx) { - pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_RX_INT); + pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_RX_INT | + PCH_UART_HAL_RX_ERR_INT); return 0; } buf = &priv->rxbuf; @@ -1056,7 +1061,7 @@ static irqreturn_t pch_uart_interrupt(int irq, void *dev_id) unsigned int iid; unsigned long flags; - spin_lock_irqsave(&priv->port.lock, flags); + spin_lock_irqsave(&priv->lock, flags); handled = 0; while ((iid = pch_uart_hal_get_iid(priv)) > 1) { switch (iid) { @@ -1071,11 +1076,13 @@ static irqreturn_t pch_uart_interrupt(int irq, void *dev_id) case PCH_UART_IID_RDR: /* Received Data Ready */ if (priv->use_dma) { pch_uart_hal_disable_interrupt(priv, - PCH_UART_HAL_RX_INT); + PCH_UART_HAL_RX_INT | + PCH_UART_HAL_RX_ERR_INT); ret = dma_handle_rx(priv); if (!ret) pch_uart_hal_enable_interrupt(priv, - PCH_UART_HAL_RX_INT); + PCH_UART_HAL_RX_INT | + PCH_UART_HAL_RX_ERR_INT); } else { ret = handle_rx(priv); } @@ -1107,7 +1114,7 @@ static irqreturn_t pch_uart_interrupt(int irq, void *dev_id) priv->int_dis_flag = 0; } - spin_unlock_irqrestore(&priv->port.lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); return IRQ_RETVAL(handled); } @@ -1199,7 +1206,8 @@ static void pch_uart_stop_rx(struct uart_port *port) struct eg20t_port *priv; priv = container_of(port, struct eg20t_port, port); priv->start_rx = 0; - pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_RX_INT); + pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_RX_INT | + PCH_UART_HAL_RX_ERR_INT); priv->int_dis_flag = 1; } @@ -1218,9 +1226,9 @@ static void pch_uart_break_ctl(struct uart_port *port, int ctl) unsigned long flags; priv = container_of(port, struct eg20t_port, port); - spin_lock_irqsave(&port->lock, flags); + spin_lock_irqsave(&priv->lock, flags); pch_uart_hal_set_break(priv, ctl); - spin_unlock_irqrestore(&port->lock, flags); + spin_unlock_irqrestore(&priv->lock, flags); } /* Grab any interrupt resources and initialise any low level driver state. */ @@ -1255,6 +1263,7 @@ static int pch_uart_startup(struct uart_port *port) break; case 16: fifo_size = PCH_UART_HAL_FIFO16; + break; case 1: default: fifo_size = PCH_UART_HAL_FIFO_DIS; @@ -1292,7 +1301,8 @@ static int pch_uart_startup(struct uart_port *port) pch_request_dma(port); priv->start_rx = 1; - pch_uart_hal_enable_interrupt(priv, PCH_UART_HAL_RX_INT); + pch_uart_hal_enable_interrupt(priv, PCH_UART_HAL_RX_INT | + PCH_UART_HAL_RX_ERR_INT); uart_update_timeout(port, CS8, default_baud); return 0; @@ -1350,7 +1360,7 @@ static void pch_uart_set_termios(struct uart_port *port, stb = PCH_UART_HAL_STB1; if (termios->c_cflag & PARENB) { - if (!(termios->c_cflag & PARODD)) + if (termios->c_cflag & PARODD) parity = PCH_UART_HAL_PARITY_ODD; else parity = PCH_UART_HAL_PARITY_EVEN; @@ -1368,7 +1378,8 @@ static void pch_uart_set_termios(struct uart_port *port, baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16); - spin_lock_irqsave(&port->lock, flags); + spin_lock_irqsave(&priv->lock, flags); + spin_lock(&port->lock); uart_update_timeout(port, termios->c_cflag, baud); rtn = pch_uart_hal_set_line(priv, baud, parity, bits, stb); @@ -1381,7 +1392,8 @@ static void pch_uart_set_termios(struct uart_port *port, tty_termios_encode_baud_rate(termios, baud, baud); out: - spin_unlock_irqrestore(&port->lock, flags); + spin_unlock(&port->lock); + spin_unlock_irqrestore(&priv->lock, flags); } static const char *pch_uart_type(struct uart_port *port) @@ -1531,8 +1543,9 @@ pch_console_write(struct console *co, const char *s, unsigned int count) { struct eg20t_port *priv; unsigned long flags; + int priv_locked = 1; + int port_locked = 1; u8 ier; - int locked = 1; priv = pch_uart_ports[co->index]; @@ -1540,12 +1553,16 @@ pch_console_write(struct console *co, const char *s, unsigned int count) local_irq_save(flags); if (priv->port.sysrq) { - /* serial8250_handle_port() already took the lock */ - locked = 0; + spin_lock(&priv->lock); + /* serial8250_handle_port() already took the port lock */ + port_locked = 0; } else if (oops_in_progress) { - locked = spin_trylock(&priv->port.lock); - } else + priv_locked = spin_trylock(&priv->lock); + port_locked = spin_trylock(&priv->port.lock); + } else { + spin_lock(&priv->lock); spin_lock(&priv->port.lock); + } /* * First save the IER then disable the interrupts @@ -1563,8 +1580,10 @@ pch_console_write(struct console *co, const char *s, unsigned int count) wait_for_xmitr(priv, BOTH_EMPTY); iowrite8(ier, priv->membase + UART_IER); - if (locked) + if (port_locked) spin_unlock(&priv->port.lock); + if (priv_locked) + spin_unlock(&priv->lock); local_irq_restore(flags); } @@ -1662,6 +1681,8 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev, pci_enable_msi(pdev); pci_set_master(pdev); + spin_lock_init(&priv->lock); + iobase = pci_resource_start(pdev, 0); mapbase = pci_resource_start(pdev, 1); priv->mapbase = mapbase; diff --git a/drivers/tty/serial/pmac_zilog.c b/drivers/tty/serial/pmac_zilog.c index 654755a990d..333c8d012b0 100644 --- a/drivers/tty/serial/pmac_zilog.c +++ b/drivers/tty/serial/pmac_zilog.c @@ -1348,10 +1348,16 @@ static int pmz_verify_port(struct uart_port *port, struct serial_struct *ser) static int pmz_poll_get_char(struct uart_port *port) { struct uart_pmac_port *uap = (struct uart_pmac_port *)port; + int tries = 2; - while ((read_zsreg(uap, R0) & Rx_CH_AV) == 0) - udelay(5); - return read_zsdata(uap); + while (tries) { + if ((read_zsreg(uap, R0) & Rx_CH_AV) != 0) + return read_zsdata(uap); + if (tries--) + udelay(5); + } + + return NO_POLL_CHAR; } static void pmz_poll_put_char(struct uart_port *port, unsigned char c) diff --git a/drivers/tty/vt/keyboard.c b/drivers/tty/vt/keyboard.c index 3b0c4e32ed7..a6d5d51fcbc 100644 --- a/drivers/tty/vt/keyboard.c +++ b/drivers/tty/vt/keyboard.c @@ -1053,13 +1053,10 @@ static int kbd_update_leds_helper(struct input_handle *handle, void *data) */ int vt_get_leds(int console, int flag) { - unsigned long flags; struct kbd_struct * kbd = kbd_table + console; int ret; - spin_lock_irqsave(&kbd_event_lock, flags); ret = vc_kbd_led(kbd, flag); - spin_unlock_irqrestore(&kbd_event_lock, flags); return ret; } diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 2156188db4a..18d06be8c9b 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -3475,6 +3475,19 @@ int con_debug_enter(struct vc_data *vc) kdb_set(2, setargs); } } + if (vc->vc_cols < 999) { + int colcount; + char cols[4]; + const char *setargs[3] = { + "set", + "COLUMNS", + cols, + }; + if (kdbgetintenv(setargs[0], &colcount)) { + snprintf(cols, 4, "%i", vc->vc_cols); + kdb_set(2, setargs); + } + } #endif /* CONFIG_KGDB_KDB */ return ret; } diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 640cf7983b0..3a7a95084cc 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -788,6 +788,10 @@ static int get_serial_info(struct acm *acm, struct serial_struct __user *info) tmp.flags = ASYNC_LOW_LATENCY; tmp.xmit_fifo_size = acm->writesize; tmp.baud_base = le32_to_cpu(acm->line.dwDTERate); + tmp.close_delay = acm->port.close_delay / 10; + tmp.closing_wait = acm->port.closing_wait == ASYNC_CLOSING_WAIT_NONE ? + ASYNC_CLOSING_WAIT_NONE : + acm->port.closing_wait / 10; if (copy_to_user(info, &tmp, sizeof(tmp))) return -EFAULT; @@ -795,6 +799,37 @@ static int get_serial_info(struct acm *acm, struct serial_struct __user *info) return 0; } +static int set_serial_info(struct acm *acm, + struct serial_struct __user *newinfo) +{ + struct serial_struct new_serial; + unsigned int closing_wait, close_delay; + int retval = 0; + + if (copy_from_user(&new_serial, newinfo, sizeof(new_serial))) + return -EFAULT; + + close_delay = new_serial.close_delay * 10; + closing_wait = new_serial.closing_wait == ASYNC_CLOSING_WAIT_NONE ? + ASYNC_CLOSING_WAIT_NONE : new_serial.closing_wait * 10; + + mutex_lock(&acm->port.mutex); + + if (!capable(CAP_SYS_ADMIN)) { + if ((close_delay != acm->port.close_delay) || + (closing_wait != acm->port.closing_wait)) + retval = -EPERM; + else + retval = -EOPNOTSUPP; + } else { + acm->port.close_delay = close_delay; + acm->port.closing_wait = closing_wait; + } + + mutex_unlock(&acm->port.mutex); + return retval; +} + static int acm_tty_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { @@ -805,6 +840,9 @@ static int acm_tty_ioctl(struct tty_struct *tty, case TIOCGSERIAL: /* gets serial port data */ rv = get_serial_info(acm, (struct serial_struct __user *) arg); break; + case TIOCSSERIAL: + rv = set_serial_info(acm, (struct serial_struct __user *) arg); + break; } return rv; @@ -818,10 +856,6 @@ static const __u32 acm_tty_speed[] = { 2500000, 3000000, 3500000, 4000000 }; -static const __u8 acm_tty_size[] = { - 5, 6, 7, 8 -}; - static void acm_tty_set_termios(struct tty_struct *tty, struct ktermios *termios_old) { @@ -835,7 +869,21 @@ static void acm_tty_set_termios(struct tty_struct *tty, newline.bParityType = termios->c_cflag & PARENB ? (termios->c_cflag & PARODD ? 1 : 2) + (termios->c_cflag & CMSPAR ? 2 : 0) : 0; - newline.bDataBits = acm_tty_size[(termios->c_cflag & CSIZE) >> 4]; + switch (termios->c_cflag & CSIZE) { + case CS5: + newline.bDataBits = 5; + break; + case CS6: + newline.bDataBits = 6; + break; + case CS7: + newline.bDataBits = 7; + break; + case CS8: + default: + newline.bDataBits = 8; + break; + } /* FIXME: Needs to clear unsupported bits in the termios */ acm->clocal = ((termios->c_cflag & CLOCAL) != 0); @@ -1104,7 +1152,8 @@ static int acm_probe(struct usb_interface *intf, } - if (data_interface->cur_altsetting->desc.bNumEndpoints < 2) + if (data_interface->cur_altsetting->desc.bNumEndpoints < 2 || + control_interface->cur_altsetting->desc.bNumEndpoints == 0) return -EINVAL; epctrl = &control_interface->cur_altsetting->endpoint[0].desc; @@ -1233,7 +1282,7 @@ static int acm_probe(struct usb_interface *intf, if (usb_endpoint_xfer_int(epwrite)) usb_fill_int_urb(snd->urb, usb_dev, - usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress), + usb_sndintpipe(usb_dev, epwrite->bEndpointAddress), NULL, acm->writesize, acm_write_bulk, snd, epwrite->bInterval); else usb_fill_bulk_urb(snd->urb, usb_dev, @@ -1550,6 +1599,12 @@ static const struct usb_device_id acm_ids[] = { Maybe we should define a new quirk for this. */ }, + { USB_DEVICE(0x0572, 0x1340), /* Conexant CX93010-2x UCMxx */ + .driver_info = NO_UNION_NORMAL, + }, + { USB_DEVICE(0x05f9, 0x4002), /* PSC Scanning, Magellan 800i */ + .driver_info = NO_UNION_NORMAL, + }, { USB_DEVICE(0x1bbb, 0x0003), /* Alcatel OT-I650 */ .driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */ }, diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 01d247e8808..524fe240fcd 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -134,12 +134,14 @@ static struct usb_driver wdm_driver; /* return intfdata if we own the interface, else look up intf in the list */ static struct wdm_device *wdm_find_device(struct usb_interface *intf) { - struct wdm_device *desc = NULL; + struct wdm_device *desc; spin_lock(&wdm_device_list_lock); list_for_each_entry(desc, &wdm_device_list, device_list) if (desc->intf == intf) - break; + goto found; + desc = NULL; +found: spin_unlock(&wdm_device_list_lock); return desc; @@ -147,12 +149,14 @@ static struct wdm_device *wdm_find_device(struct usb_interface *intf) static struct wdm_device *wdm_find_device_by_minor(int minor) { - struct wdm_device *desc = NULL; + struct wdm_device *desc; spin_lock(&wdm_device_list_lock); list_for_each_entry(desc, &wdm_device_list, device_list) if (desc->intf->minor == minor) - break; + goto found; + desc = NULL; +found: spin_unlock(&wdm_device_list_lock); return desc; diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c index d9569658476..3440812b4a8 100644 --- a/drivers/usb/core/devices.c +++ b/drivers/usb/core/devices.c @@ -624,7 +624,7 @@ static ssize_t usb_device_read(struct file *file, char __user *buf, /* print devices for all busses */ list_for_each_entry(bus, &usb_bus_list, bus_list) { /* recurse through all children of the root hub */ - if (!bus->root_hub) + if (!bus_to_hcd(bus)->rh_registered) continue; usb_lock_device(bus->root_hub); ret = usb_device_dump(&buf, &nbytes, &skip_bytes, ppos, diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 4e577728ead..404413b0b93 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -1615,10 +1615,14 @@ static int processcompl_compat(struct async *as, void __user * __user *arg) void __user *addr = as->userurb; unsigned int i; - if (as->userbuffer && urb->actual_length) - if (copy_to_user(as->userbuffer, urb->transfer_buffer, - urb->actual_length)) + if (as->userbuffer && urb->actual_length) { + if (urb->number_of_packets > 0) /* Isochronous */ + i = urb->transfer_buffer_length; + else /* Non-Isoc */ + i = urb->actual_length; + if (copy_to_user(as->userbuffer, urb->transfer_buffer, i)) return -EFAULT; + } if (put_user(as->status, &userurb->status)) return -EFAULT; if (put_user(urb->actual_length, &userurb->actual_length)) diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index b8f9563090c..f4ab5c9c332 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1010,10 +1010,7 @@ static int register_root_hub(struct usb_hcd *hcd) if (retval) { dev_err (parent_dev, "can't register root hub for %s, %d\n", dev_name(&usb_dev->dev), retval); - } - mutex_unlock(&usb_bus_list_lock); - - if (retval == 0) { + } else { spin_lock_irq (&hcd_root_hub_lock); hcd->rh_registered = 1; spin_unlock_irq (&hcd_root_hub_lock); @@ -1022,6 +1019,7 @@ static int register_root_hub(struct usb_hcd *hcd) if (HCD_DEAD(hcd)) usb_hc_died (hcd); /* This time clean up */ } + mutex_unlock(&usb_bus_list_lock); return retval; } diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 67eae2c943a..eb44693970e 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -536,13 +536,16 @@ static void hub_tt_work(struct work_struct *work) int limit = 100; spin_lock_irqsave (&hub->tt.lock, flags); - while (--limit && !list_empty (&hub->tt.clear_list)) { + while (!list_empty(&hub->tt.clear_list)) { struct list_head *next; struct usb_tt_clear *clear; struct usb_device *hdev = hub->hdev; const struct hc_driver *drv; int status; + if (!hub->quiescing && --limit < 0) + break; + next = hub->tt.clear_list.next; clear = list_entry (next, struct usb_tt_clear, clear_list); list_del (&clear->clear_list); @@ -670,6 +673,60 @@ static int hub_hub_status(struct usb_hub *hub, return ret; } +static int hub_set_port_link_state(struct usb_hub *hub, int port1, + unsigned int link_status) +{ + return set_port_feature(hub->hdev, + port1 | (link_status << 3), + USB_PORT_FEAT_LINK_STATE); +} + +/* + * If USB 3.0 ports are placed into the Disabled state, they will no longer + * detect any device connects or disconnects. This is generally not what the + * USB core wants, since it expects a disabled port to produce a port status + * change event when a new device connects. + * + * Instead, set the link state to Disabled, wait for the link to settle into + * that state, clear any change bits, and then put the port into the RxDetect + * state. + */ +static int hub_usb3_port_disable(struct usb_hub *hub, int port1) +{ + int ret; + int total_time; + u16 portchange, portstatus; + + if (!hub_is_superspeed(hub->hdev)) + return -EINVAL; + + ret = hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_SS_DISABLED); + if (ret) { + dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n", + port1, ret); + return ret; + } + + /* Wait for the link to enter the disabled state. */ + for (total_time = 0; ; total_time += HUB_DEBOUNCE_STEP) { + ret = hub_port_status(hub, port1, &portstatus, &portchange); + if (ret < 0) + return ret; + + if ((portstatus & USB_PORT_STAT_LINK_STATE) == + USB_SS_PORT_LS_SS_DISABLED) + break; + if (total_time >= HUB_DEBOUNCE_TIMEOUT) + break; + msleep(HUB_DEBOUNCE_STEP); + } + if (total_time >= HUB_DEBOUNCE_TIMEOUT) + dev_warn(hub->intfdev, "Could not disable port %d after %d ms\n", + port1, total_time); + + return hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_RX_DETECT); +} + static int hub_port_disable(struct usb_hub *hub, int port1, int set_state) { struct usb_device *hdev = hub->hdev; @@ -678,8 +735,13 @@ static int hub_port_disable(struct usb_hub *hub, int port1, int set_state) if (hdev->children[port1-1] && set_state) usb_set_device_state(hdev->children[port1-1], USB_STATE_NOTATTACHED); - if (!hub->error && !hub_is_superspeed(hub->hdev)) - ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE); + if (!hub->error) { + if (hub_is_superspeed(hub->hdev)) + ret = hub_usb3_port_disable(hub, port1); + else + ret = clear_port_feature(hdev, port1, + USB_PORT_FEAT_ENABLE); + } if (ret) dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n", port1, ret); @@ -1016,7 +1078,7 @@ static void hub_quiesce(struct usb_hub *hub, enum hub_quiescing_type type) if (hub->has_indicators) cancel_delayed_work_sync(&hub->leds); if (hub->tt.hub) - cancel_work_sync(&hub->tt.clear_work); + flush_work_sync(&hub->tt.clear_work); } /* caller has locked the hub device */ @@ -2193,7 +2255,7 @@ static unsigned hub_is_wusb(struct usb_hub *hub) #define HUB_SHORT_RESET_TIME 10 #define HUB_BH_RESET_TIME 50 #define HUB_LONG_RESET_TIME 200 -#define HUB_RESET_TIMEOUT 500 +#define HUB_RESET_TIMEOUT 800 static int hub_port_reset(struct usb_hub *hub, int port1, struct usb_device *udev, unsigned int delay, bool warm); @@ -2228,6 +2290,10 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1, if (ret < 0) return ret; + /* The port state is unknown until the reset completes. */ + if ((portstatus & USB_PORT_STAT_RESET)) + goto delay; + /* * Some buggy devices require a warm reset to be issued even * when the port appears not to be connected. @@ -2273,11 +2339,7 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1, if ((portchange & USB_PORT_STAT_C_CONNECTION)) return -ENOTCONN; - /* if we`ve finished resetting, then break out of - * the loop - */ - if (!(portstatus & USB_PORT_STAT_RESET) && - (portstatus & USB_PORT_STAT_ENABLE)) { + if ((portstatus & USB_PORT_STAT_ENABLE)) { if (hub_is_wusb(hub)) udev->speed = USB_SPEED_WIRELESS; else if (hub_is_superspeed(hub->hdev)) @@ -2291,10 +2353,15 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1, return 0; } } else { - if (portchange & USB_PORT_STAT_C_BH_RESET) - return 0; + if (!(portstatus & USB_PORT_STAT_CONNECTION) || + hub_port_warm_reset_required(hub, + portstatus)) + return -ENOTCONN; + + return 0; } +delay: /* switch to the long delay after two short delay failures */ if (delay_time >= 2 * HUB_SHORT_RESET_TIME) delay = HUB_LONG_RESET_TIME; @@ -2318,14 +2385,11 @@ static void hub_port_finish_reset(struct usb_hub *hub, int port1, msleep(10 + 40); update_devnum(udev, 0); hcd = bus_to_hcd(udev->bus); - if (hcd->driver->reset_device) { - *status = hcd->driver->reset_device(hcd, udev); - if (*status < 0) { - dev_err(&udev->dev, "Cannot reset " - "HCD device state\n"); - break; - } - } + /* The xHC may think the device is already reset, + * so ignore the status. + */ + if (hcd->driver->reset_device) + hcd->driver->reset_device(hcd, udev); } /* FALL THROUGH */ case -ENOTCONN: @@ -2333,16 +2397,16 @@ static void hub_port_finish_reset(struct usb_hub *hub, int port1, clear_port_feature(hub->hdev, port1, USB_PORT_FEAT_C_RESET); /* FIXME need disconnect() for NOTATTACHED device */ - if (warm) { + if (hub_is_superspeed(hub->hdev)) { clear_port_feature(hub->hdev, port1, USB_PORT_FEAT_C_BH_PORT_RESET); clear_port_feature(hub->hdev, port1, USB_PORT_FEAT_C_PORT_LINK_STATE); - } else { + } + if (!warm) usb_set_device_state(udev, *status ? USB_STATE_NOTATTACHED : USB_STATE_DEFAULT); - } break; } } @@ -2486,6 +2550,23 @@ static int check_port_resume_type(struct usb_device *udev, } #ifdef CONFIG_USB_SUSPEND +/* + * usb_disable_function_remotewakeup - disable usb3.0 + * device's function remote wakeup + * @udev: target device + * + * Assume there's only one function on the USB 3.0 + * device and disable remote wake for the first + * interface. FIXME if the interface association + * descriptor shows there's more than one function. + */ +static int usb_disable_function_remotewakeup(struct usb_device *udev) +{ + return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + USB_REQ_CLEAR_FEATURE, USB_RECIP_INTERFACE, + USB_INTRF_FUNC_SUSPEND, 0, NULL, 0, + USB_CTRL_SET_TIMEOUT); +} /* * usb_port_suspend - suspend a usb device's upstream port @@ -2608,12 +2689,19 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) dev_dbg(hub->intfdev, "can't suspend port %d, status %d\n", port1, status); /* paranoia: "should not happen" */ - if (udev->do_remote_wakeup) - (void) usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE, - USB_DEVICE_REMOTE_WAKEUP, 0, - NULL, 0, - USB_CTRL_SET_TIMEOUT); + if (udev->do_remote_wakeup) { + if (!hub_is_superspeed(hub->hdev)) { + (void) usb_control_msg(udev, + usb_sndctrlpipe(udev, 0), + USB_REQ_CLEAR_FEATURE, + USB_RECIP_DEVICE, + USB_DEVICE_REMOTE_WAKEUP, 0, + NULL, 0, + USB_CTRL_SET_TIMEOUT); + } else + (void) usb_disable_function_remotewakeup(udev); + + } /* Try to enable USB2 hardware LPM again */ if (udev->usb2_hw_lpm_capable == 1) @@ -2648,7 +2736,7 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) static int finish_port_resume(struct usb_device *udev) { int status = 0; - u16 devstatus; + u16 devstatus = 0; /* caller owns the udev device lock */ dev_dbg(&udev->dev, "%s\n", @@ -2693,21 +2781,37 @@ static int finish_port_resume(struct usb_device *udev) if (status) { dev_dbg(&udev->dev, "gone after usb resume? status %d\n", status); - } else if (udev->actconfig) { - le16_to_cpus(&devstatus); - if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) { - status = usb_control_msg(udev, - usb_sndctrlpipe(udev, 0), - USB_REQ_CLEAR_FEATURE, + /* + * There are a few quirky devices which violate the standard + * by claiming to have remote wakeup enabled after a reset, + * which crash if the feature is cleared, hence check for + * udev->reset_resume + */ + } else if (udev->actconfig && !udev->reset_resume) { + if (!hub_is_superspeed(udev->parent)) { + le16_to_cpus(&devstatus); + if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) + status = usb_control_msg(udev, + usb_sndctrlpipe(udev, 0), + USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE, - USB_DEVICE_REMOTE_WAKEUP, 0, - NULL, 0, - USB_CTRL_SET_TIMEOUT); - if (status) - dev_dbg(&udev->dev, - "disable remote wakeup, status %d\n", - status); + USB_DEVICE_REMOTE_WAKEUP, 0, + NULL, 0, + USB_CTRL_SET_TIMEOUT); + } else { + status = usb_get_status(udev, USB_RECIP_INTERFACE, 0, + &devstatus); + le16_to_cpus(&devstatus); + if (!status && devstatus & (USB_INTRF_STAT_FUNC_RW_CAP + | USB_INTRF_STAT_FUNC_RW)) + status = + usb_disable_function_remotewakeup(udev); } + + if (status) + dev_dbg(&udev->dev, + "disable remote wakeup, status %d\n", + status); status = 0; } return status; @@ -4089,9 +4193,14 @@ static void hub_events(void) * SS.Inactive state. */ if (hub_port_warm_reset_required(hub, portstatus)) { + int status; + dev_dbg(hub_dev, "warm reset port %d\n", i); - hub_port_reset(hub, i, NULL, + status = hub_port_reset(hub, i, NULL, HUB_BH_RESET_TIME, true); + if (status < 0) + hub_port_disable(hub, i, 1); + connect_change = 0; } if (connect_change) { diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 2c9fc0319ac..7e3db8b1ab4 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -1771,31 +1771,8 @@ int usb_set_configuration(struct usb_device *dev, int configuration) goto free_interfaces; } - dev->actconfig = cp; - if (cp) - usb_notify_config_device(dev); - ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - USB_REQ_SET_CONFIGURATION, 0, configuration, 0, - NULL, 0, USB_CTRL_SET_TIMEOUT); - if (ret < 0) { - /* All the old state is gone, so what else can we do? - * The device is probably useless now anyway. - */ - dev->actconfig = cp = NULL; - } - - if (!cp) { - usb_notify_config_device(dev); - usb_set_device_state(dev, USB_STATE_ADDRESS); - usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL); - mutex_unlock(hcd->bandwidth_mutex); - usb_autosuspend_device(dev); - goto free_interfaces; - } - mutex_unlock(hcd->bandwidth_mutex); - usb_set_device_state(dev, USB_STATE_CONFIGURED); - - /* Initialize the new interface structures and the + /* + * Initialize the new interface structures and the * hc/hcd/usbcore interface/endpoint state. */ for (i = 0; i < nintf; ++i) { @@ -1839,6 +1816,35 @@ int usb_set_configuration(struct usb_device *dev, int configuration) } kfree(new_interfaces); + ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + USB_REQ_SET_CONFIGURATION, 0, configuration, 0, + NULL, 0, USB_CTRL_SET_TIMEOUT); + if (ret < 0 && cp) { + /* + * All the old state is gone, so what else can we do? + * The device is probably useless now anyway. + */ + usb_hcd_alloc_bandwidth(dev, NULL, NULL, NULL); + for (i = 0; i < nintf; ++i) { + usb_disable_interface(dev, cp->interface[i], true); + put_device(&cp->interface[i]->dev); + cp->interface[i] = NULL; + } + cp = NULL; + } + + dev->actconfig = cp; + mutex_unlock(hcd->bandwidth_mutex); + + if (!cp) { + usb_set_device_state(dev, USB_STATE_ADDRESS); + + /* Leave LPM disabled while the device is unconfigured. */ + usb_autosuspend_device(dev); + return ret; + } + usb_set_device_state(dev, USB_STATE_CONFIGURED); + if (cp->string == NULL && !(dev->quirks & USB_QUIRK_CONFIG_INTF_STRINGS)) cp->string = usb_cache_string(dev, cp->desc.iConfiguration); diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index 1df3f0683d7..5f650517044 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -96,6 +96,10 @@ static const struct usb_device_id usb_quirk_list[] = { { USB_DEVICE(0x04b4, 0x0526), .driver_info = USB_QUIRK_CONFIG_INTF_STRINGS }, + /* Microchip Joss Optical infrared touchboard device */ + { USB_DEVICE(0x04d8, 0x000c), .driver_info = + USB_QUIRK_CONFIG_INTF_STRINGS }, + /* Samsung Android phone modem - ID conflict with SPH-I500 */ { USB_DEVICE(0x04e8, 0x6601), .driver_info = USB_QUIRK_CONFIG_INTF_STRINGS }, diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index a3f6e58faf2..03b4f650a94 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1504,6 +1504,7 @@ static int __devinit dwc3_gadget_init_endpoints(struct dwc3 *dwc) if (epnum == 0 || epnum == 1) { dep->endpoint.maxpacket = 512; + dep->endpoint.maxburst = 1; dep->endpoint.ops = &dwc3_gadget_ep0_ops; if (!epnum) dwc->gadget.ep0 = &dep->endpoint; diff --git a/drivers/usb/early/ehci-dbgp.c b/drivers/usb/early/ehci-dbgp.c index 1fc8f124980..347bb058e1e 100644 --- a/drivers/usb/early/ehci-dbgp.c +++ b/drivers/usb/early/ehci-dbgp.c @@ -450,7 +450,7 @@ static int dbgp_ehci_startup(void) writel(FLAG_CF, &ehci_regs->configured_flag); /* Wait until the controller is no longer halted */ - loop = 10; + loop = 1000; do { status = readl(&ehci_regs->status); if (!(status & STS_HALT)) diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index 9d7bcd91007..be6952e2fc5 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c @@ -1735,7 +1735,7 @@ static int __devinit at91udc_probe(struct platform_device *pdev) int retval; struct resource *res; - if (!dev->platform_data) { + if (!dev->platform_data && !pdev->dev.of_node) { /* small (so we copy it) but critical! */ DBG("missing platform_data\n"); return -ENODEV; diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index 170cbe89d9f..9a7b436bd92 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -126,10 +126,7 @@ static const char ep0name[] = "ep0"; static const char *const ep_name[] = { ep0name, /* everyone has ep0 */ - /* act like a net2280: high speed, six configurable endpoints */ - "ep-a", "ep-b", "ep-c", "ep-d", "ep-e", "ep-f", - - /* or like pxa250: fifteen fixed function endpoints */ + /* act like a pxa250: fifteen fixed function endpoints */ "ep1in-bulk", "ep2out-bulk", "ep3in-iso", "ep4out-iso", "ep5in-int", "ep6in-bulk", "ep7out-bulk", "ep8in-iso", "ep9out-iso", "ep10in-int", "ep11in-bulk", "ep12out-bulk", "ep13in-iso", "ep14out-iso", @@ -137,6 +134,10 @@ static const char *const ep_name[] = { /* or like sa1100: two fixed function endpoints */ "ep1out-bulk", "ep2in-bulk", + + /* and now some generic EPs so we have enough in multi config */ + "ep3out", "ep4in", "ep5out", "ep6out", "ep7in", "ep8out", "ep9in", + "ep10out", "ep11out", "ep12in", "ep13out", "ep14in", "ep15out", }; #define DUMMY_ENDPOINTS ARRAY_SIZE(ep_name) @@ -2505,10 +2506,8 @@ static int dummy_hcd_probe(struct platform_device *pdev) hs_hcd->has_tt = 1; retval = usb_add_hcd(hs_hcd, 0, 0); - if (retval != 0) { - usb_put_hcd(hs_hcd); - return retval; - } + if (retval) + goto put_usb2_hcd; if (mod_data.is_super_speed) { ss_hcd = usb_create_shared_hcd(&dummy_hcd, &pdev->dev, @@ -2527,6 +2526,8 @@ static int dummy_hcd_probe(struct platform_device *pdev) put_usb3_hcd: usb_put_hcd(ss_hcd); dealloc_usb2_hcd: + usb_remove_hcd(hs_hcd); +put_usb2_hcd: usb_put_hcd(hs_hcd); the_controller.hs_hcd = the_controller.ss_hcd = NULL; return retval; diff --git a/drivers/usb/gadget/f_ecm.c b/drivers/usb/gadget/f_ecm.c index b3eb79ed614..a9af16cfa36 100644 --- a/drivers/usb/gadget/f_ecm.c +++ b/drivers/usb/gadget/f_ecm.c @@ -835,9 +835,9 @@ ecm_bind(struct usb_configuration *c, struct usb_function *f) /* we might as well release our claims on endpoints */ if (ecm->notify) ecm->notify->driver_data = NULL; - if (ecm->port.out_ep->desc) + if (ecm->port.out_ep) ecm->port.out_ep->driver_data = NULL; - if (ecm->port.in_ep->desc) + if (ecm->port.in_ep) ecm->port.in_ep->driver_data = NULL; ERROR(cdev, "%s: can't bind, err %d\n", f->name, status); diff --git a/drivers/usb/gadget/f_eem.c b/drivers/usb/gadget/f_eem.c index 1a7b2dd7d40..a9cf20522ff 100644 --- a/drivers/usb/gadget/f_eem.c +++ b/drivers/usb/gadget/f_eem.c @@ -319,10 +319,9 @@ eem_bind(struct usb_configuration *c, struct usb_function *f) if (f->hs_descriptors) usb_free_descriptors(f->hs_descriptors); - /* we might as well release our claims on endpoints */ - if (eem->port.out_ep->desc) + if (eem->port.out_ep) eem->port.out_ep->driver_data = NULL; - if (eem->port.in_ep->desc) + if (eem->port.in_ep) eem->port.in_ep->driver_data = NULL; ERROR(cdev, "%s: can't bind, err %d\n", f->name, status); diff --git a/drivers/usb/gadget/f_midi.c b/drivers/usb/gadget/f_midi.c index 2f7e8f2930c..1bf95964056 100644 --- a/drivers/usb/gadget/f_midi.c +++ b/drivers/usb/gadget/f_midi.c @@ -416,6 +416,7 @@ static void f_midi_unbind(struct usb_configuration *c, struct usb_function *f) midi->id = NULL; usb_free_descriptors(f->descriptors); + usb_free_descriptors(f->hs_descriptors); kfree(midi); } diff --git a/drivers/usb/gadget/f_ncm.c b/drivers/usb/gadget/f_ncm.c index aab8eded045..d7811ae2972 100644 --- a/drivers/usb/gadget/f_ncm.c +++ b/drivers/usb/gadget/f_ncm.c @@ -1259,9 +1259,9 @@ ncm_bind(struct usb_configuration *c, struct usb_function *f) /* we might as well release our claims on endpoints */ if (ncm->notify) ncm->notify->driver_data = NULL; - if (ncm->port.out_ep->desc) + if (ncm->port.out_ep) ncm->port.out_ep->driver_data = NULL; - if (ncm->port.in_ep->desc) + if (ncm->port.in_ep) ncm->port.in_ep->driver_data = NULL; ERROR(cdev, "%s: can't bind, err %d\n", f->name, status); diff --git a/drivers/usb/gadget/f_phonet.c b/drivers/usb/gadget/f_phonet.c index 965a6293206..16512f921bc 100644 --- a/drivers/usb/gadget/f_phonet.c +++ b/drivers/usb/gadget/f_phonet.c @@ -531,7 +531,7 @@ int pn_bind(struct usb_configuration *c, struct usb_function *f) req = usb_ep_alloc_request(fp->out_ep, GFP_KERNEL); if (!req) - goto err; + goto err_req; req->complete = pn_rx_complete; fp->out_reqv[i] = req; @@ -540,14 +540,18 @@ int pn_bind(struct usb_configuration *c, struct usb_function *f) /* Outgoing USB requests */ fp->in_req = usb_ep_alloc_request(fp->in_ep, GFP_KERNEL); if (!fp->in_req) - goto err; + goto err_req; INFO(cdev, "USB CDC Phonet function\n"); INFO(cdev, "using %s, OUT %s, IN %s\n", cdev->gadget->name, fp->out_ep->name, fp->in_ep->name); return 0; +err_req: + for (i = 0; i < phonet_rxq_size && fp->out_reqv[i]; i++) + usb_ep_free_request(fp->out_ep, fp->out_reqv[i]); err: + if (fp->out_ep) fp->out_ep->driver_data = NULL; if (fp->in_ep) diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c index 6a43d4c0fd7..82ff934232d 100644 --- a/drivers/usb/gadget/f_rndis.c +++ b/drivers/usb/gadget/f_rndis.c @@ -833,9 +833,9 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f) /* we might as well release our claims on endpoints */ if (rndis->notify) rndis->notify->driver_data = NULL; - if (rndis->port.out_ep->desc) + if (rndis->port.out_ep) rndis->port.out_ep->driver_data = NULL; - if (rndis->port.in_ep->desc) + if (rndis->port.in_ep) rndis->port.in_ep->driver_data = NULL; ERROR(cdev, "%s: can't bind, err %d\n", f->name, status); diff --git a/drivers/usb/gadget/f_subset.c b/drivers/usb/gadget/f_subset.c index 21ab474aca0..e5bb9662863 100644 --- a/drivers/usb/gadget/f_subset.c +++ b/drivers/usb/gadget/f_subset.c @@ -370,9 +370,9 @@ geth_bind(struct usb_configuration *c, struct usb_function *f) usb_free_descriptors(f->hs_descriptors); /* we might as well release our claims on endpoints */ - if (geth->port.out_ep->desc) + if (geth->port.out_ep) geth->port.out_ep->driver_data = NULL; - if (geth->port.in_ep->desc) + if (geth->port.in_ep) geth->port.in_ep->driver_data = NULL; ERROR(cdev, "%s: can't bind, err %d\n", f->name, status); diff --git a/drivers/usb/gadget/f_uvc.c b/drivers/usb/gadget/f_uvc.c index 2022fe49214..a0abc65ecbe 100644 --- a/drivers/usb/gadget/f_uvc.c +++ b/drivers/usb/gadget/f_uvc.c @@ -335,7 +335,6 @@ uvc_register_video(struct uvc_device *uvc) return -ENOMEM; video->parent = &cdev->gadget->dev; - video->minor = -1; video->fops = &uvc_v4l2_fops; video->release = video_device_release; strncpy(video->name, cdev->gadget->name, sizeof(video->name)); @@ -462,23 +461,12 @@ uvc_function_unbind(struct usb_configuration *c, struct usb_function *f) INFO(cdev, "uvc_function_unbind\n"); - if (uvc->vdev) { - if (uvc->vdev->minor == -1) - video_device_release(uvc->vdev); - else - video_unregister_device(uvc->vdev); - uvc->vdev = NULL; - } - - if (uvc->control_ep) - uvc->control_ep->driver_data = NULL; - if (uvc->video.ep) - uvc->video.ep->driver_data = NULL; + video_unregister_device(uvc->vdev); + uvc->control_ep->driver_data = NULL; + uvc->video.ep->driver_data = NULL; - if (uvc->control_req) { - usb_ep_free_request(cdev->gadget->ep0, uvc->control_req); - kfree(uvc->control_buf); - } + usb_ep_free_request(cdev->gadget->ep0, uvc->control_req); + kfree(uvc->control_buf); kfree(f->descriptors); kfree(f->hs_descriptors); @@ -563,7 +551,22 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) return 0; error: - uvc_function_unbind(c, f); + if (uvc->vdev) + video_device_release(uvc->vdev); + + if (uvc->control_ep) + uvc->control_ep->driver_data = NULL; + if (uvc->video.ep) + uvc->video.ep->driver_data = NULL; + + if (uvc->control_req) { + usb_ep_free_request(cdev->gadget->ep0, uvc->control_req); + kfree(uvc->control_buf); + } + + kfree(f->descriptors); + kfree(f->hs_descriptors); + kfree(f->ss_descriptors); return ret; } diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c index e745ce27932..65a7d91f666 100644 --- a/drivers/usb/gadget/u_ether.c +++ b/drivers/usb/gadget/u_ether.c @@ -833,6 +833,8 @@ static int eth_stop(struct net_device *net) spin_lock_irqsave(&dev->lock, flags); if (dev->port_usb) { struct gether *link = dev->port_usb; + const struct usb_endpoint_descriptor *in; + const struct usb_endpoint_descriptor *out; if (link->close) link->close(link); @@ -848,6 +850,8 @@ static int eth_stop(struct net_device *net) */ usb_ep_disable(link->in_ep); usb_ep_disable(link->out_ep); + in = link->in_ep->desc; + out = link->out_ep->desc; if (netif_carrier_ok(net)) { if (config_ep_by_speed(dev->gadget, &link->func, link->in_ep) || @@ -858,6 +862,8 @@ static int eth_stop(struct net_device *net) return -EINVAL; } DBG(dev, "host still using in/out endpoints\n"); + link->in_ep->desc = in; + link->out_ep->desc = out; usb_ep_enable(link->in_ep); usb_ep_enable(link->out_ep); } diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index cfdb688386b..a099531091e 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -639,7 +639,11 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf) status = STS_PCD; } } - /* FIXME autosuspend idle root hubs */ + + /* If a resume is in progress, make sure it can finish */ + if (ehci->resuming_ports) + mod_timer(&hcd->rh_timer, jiffies + msecs_to_jiffies(25)); + spin_unlock_irqrestore (&ehci->lock, flags); return status ? retval : 0; } diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index 123481793a4..0909783a034 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c @@ -362,7 +362,8 @@ static bool usb_is_intel_switchable_ehci(struct pci_dev *pdev) pdev->vendor == PCI_VENDOR_ID_INTEL && (pdev->device == 0x1E26 || pdev->device == 0x8C2D || - pdev->device == 0x8C26); + pdev->device == 0x8C26 || + pdev->device == 0x9C26); } static void ehci_enable_xhci_companion(void) diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index a60679cbbf8..14d2d71163f 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -236,7 +236,7 @@ static inline unsigned char tt_start_uframe(struct ehci_hcd *ehci, __hc32 mask) } static const unsigned char -max_tt_usecs[] = { 125, 125, 125, 125, 125, 125, 30, 0 }; +max_tt_usecs[] = { 125, 125, 125, 125, 125, 125, 125, 25 }; /* carryover low/fullspeed bandwidth that crosses uframe boundries */ static inline void carryover_tt_bandwidth(unsigned short tt_usecs[8]) diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index 55d3d641447..7841b0aa407 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -466,7 +466,8 @@ static irqreturn_t ohci_hcd_at91_overcurrent_irq(int irq, void *data) /* From the GPIO notifying the over-current situation, find * out the corresponding port */ at91_for_each_port(port) { - if (gpio_to_irq(pdata->overcurrent_pin[port]) == irq) { + if (gpio_is_valid(pdata->overcurrent_pin[port]) && + gpio_to_irq(pdata->overcurrent_pin[port]) == irq) { gpio = pdata->overcurrent_pin[port]; break; } @@ -569,6 +570,16 @@ static int __devinit ohci_hcd_at91_drv_probe(struct platform_device *pdev) if (pdata) { at91_for_each_port(i) { + /* + * do not configure PIO if not in relation with + * real USB port on board + */ + if (i >= pdata->ports) { + pdata->vbus_pin[i] = -EINVAL; + pdata->overcurrent_pin[i] = -EINVAL; + break; + } + if (!gpio_is_valid(pdata->vbus_pin[i])) continue; gpio = pdata->vbus_pin[i]; diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c index c5a1ea9145f..9d00d4721bc 100644 --- a/drivers/usb/host/ohci-q.c +++ b/drivers/usb/host/ohci-q.c @@ -1128,6 +1128,25 @@ dl_done_list (struct ohci_hcd *ohci) while (td) { struct td *td_next = td->next_dl_td; + struct ed *ed = td->ed; + + /* + * Some OHCI controllers (NVIDIA for sure, maybe others) + * occasionally forget to add TDs to the done queue. Since + * TDs for a given endpoint are always processed in order, + * if we find a TD on the donelist then all of its + * predecessors must be finished as well. + */ + for (;;) { + struct td *td2; + + td2 = list_first_entry(&ed->td_list, struct td, + td_list); + if (td2 == td) + break; + takeback_td(ohci, td2); + } + takeback_td(ohci, td); td = td_next; } diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index df0828cb2aa..5c98ad2aea0 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -75,7 +75,9 @@ #define NB_PIF0_PWRDOWN_1 0x01100013 #define USB_INTEL_XUSB2PR 0xD0 +#define USB_INTEL_USB2PRM 0xD4 #define USB_INTEL_USB3_PSSEN 0xD8 +#define USB_INTEL_USB3PRM 0xDC static struct amd_chipset_info { struct pci_dev *nb_dev; @@ -543,7 +545,14 @@ static const struct dmi_system_id __devinitconst ehci_dmi_nohandoff_table[] = { /* Pegatron Lucid (Ordissimo AIRIS) */ .matches = { DMI_MATCH(DMI_BOARD_NAME, "M11JB"), - DMI_MATCH(DMI_BIOS_VERSION, "Lucid-GE-133"), + DMI_MATCH(DMI_BIOS_VERSION, "Lucid-"), + }, + }, + { + /* Pegatron Lucid (Ordissimo) */ + .matches = { + DMI_MATCH(DMI_BOARD_NAME, "Ordissimo"), + DMI_MATCH(DMI_BIOS_VERSION, "Lucid-"), }, }, { } @@ -714,6 +723,7 @@ static int handshake(void __iomem *ptr, u32 mask, u32 done, } #define PCI_DEVICE_ID_INTEL_LYNX_POINT_XHCI 0x8C31 +#define PCI_DEVICE_ID_INTEL_LYNX_POINT_LP_XHCI 0x9C31 bool usb_is_intel_ppt_switchable_xhci(struct pci_dev *pdev) { @@ -727,7 +737,8 @@ bool usb_is_intel_lpt_switchable_xhci(struct pci_dev *pdev) { return pdev->class == PCI_CLASS_SERIAL_USB_XHCI && pdev->vendor == PCI_VENDOR_ID_INTEL && - pdev->device == PCI_DEVICE_ID_INTEL_LYNX_POINT_XHCI; + (pdev->device == PCI_DEVICE_ID_INTEL_LYNX_POINT_XHCI || + pdev->device == PCI_DEVICE_ID_INTEL_LYNX_POINT_LP_XHCI); } bool usb_is_intel_switchable_xhci(struct pci_dev *pdev) @@ -769,13 +780,22 @@ void usb_enable_xhci_ports(struct pci_dev *xhci_pdev) "defaulting to EHCI.\n"); dev_warn(&xhci_pdev->dev, "USB 3.0 devices will work at USB 2.0 speeds.\n"); + usb_disable_xhci_ports(xhci_pdev); return; } - ports_available = 0xffffffff; + /* Read USB3PRM, the USB 3.0 Port Routing Mask Register + * Indicate the ports that can be changed from OS. + */ + pci_read_config_dword(xhci_pdev, USB_INTEL_USB3PRM, + &ports_available); + + dev_dbg(&xhci_pdev->dev, "Configurable ports to enable SuperSpeed: 0x%x\n", + ports_available); + /* Write USB3_PSSEN, the USB 3.0 Port SuperSpeed Enable - * Register, to turn on SuperSpeed terminations for all - * available ports. + * Register, to turn on SuperSpeed terminations for the + * switchable ports. */ pci_write_config_dword(xhci_pdev, USB_INTEL_USB3_PSSEN, cpu_to_le32(ports_available)); @@ -785,7 +805,16 @@ void usb_enable_xhci_ports(struct pci_dev *xhci_pdev) dev_dbg(&xhci_pdev->dev, "USB 3.0 ports that are now enabled " "under xHCI: 0x%x\n", ports_available); - ports_available = 0xffffffff; + /* Read XUSB2PRM, xHCI USB 2.0 Port Routing Mask Register + * Indicate the USB 2.0 ports to be controlled by the xHCI host. + */ + + pci_read_config_dword(xhci_pdev, USB_INTEL_USB2PRM, + &ports_available); + + dev_dbg(&xhci_pdev->dev, "Configurable USB 2.0 ports to hand over to xCHI: 0x%x\n", + ports_available); + /* Write XUSB2PR, the xHC USB 2.0 Port Routing Register, to * switch the USB 2.0 power and data lines over to the xHCI * host. @@ -815,12 +844,12 @@ static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev) void __iomem *op_reg_base; u32 val; int timeout; + int len = pci_resource_len(pdev, 0); if (!mmio_resource_enabled(pdev, 0)) return; - base = ioremap_nocache(pci_resource_start(pdev, 0), - pci_resource_len(pdev, 0)); + base = ioremap_nocache(pci_resource_start(pdev, 0), len); if (base == NULL) return; @@ -830,9 +859,17 @@ static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev) */ ext_cap_offset = xhci_find_next_cap_offset(base, XHCI_HCC_PARAMS_OFFSET); do { + if ((ext_cap_offset + sizeof(val)) > len) { + /* We're reading garbage from the controller */ + dev_warn(&pdev->dev, + "xHCI controller failing to respond"); + return; + } + if (!ext_cap_offset) /* We've reached the end of the extended capabilities */ goto hc_init; + val = readl(base + ext_cap_offset); if (XHCI_EXT_CAPS_ID(val) == XHCI_EXT_CAPS_LEGACY) break; @@ -863,9 +900,10 @@ static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev) /* Disable any BIOS SMIs and clear all SMI events*/ writel(val, base + ext_cap_offset + XHCI_LEGACY_CONTROL_OFFSET); +hc_init: if (usb_is_intel_switchable_xhci(pdev)) usb_enable_xhci_ports(pdev); -hc_init: + op_reg_base = base + XHCI_HC_LENGTH(readl(base)); /* Wait for the host controller to be ready before writing any diff --git a/drivers/usb/host/pci-quirks.h b/drivers/usb/host/pci-quirks.h index b1002a8ef96..8e2fe2e9558 100644 --- a/drivers/usb/host/pci-quirks.h +++ b/drivers/usb/host/pci-quirks.h @@ -14,6 +14,7 @@ void usb_enable_xhci_ports(struct pci_dev *xhci_pdev); static inline void usb_amd_quirk_pll_disable(void) {} static inline void usb_amd_quirk_pll_enable(void) {} static inline void usb_amd_dev_put(void) {} +static inline void usb_disable_xhci_ports(struct pci_dev *xhci_pdev) {} #endif /* CONFIG_PCI */ #endif /* __LINUX_USB_PCI_QUIRKS_H */ diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index e4db350602b..3fe069f536b 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c @@ -447,6 +447,10 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd) return IRQ_NONE; uhci_writew(uhci, status, USBSTS); /* Clear it */ + spin_lock(&uhci->lock); + if (unlikely(!uhci->is_initialized)) /* not yet configured */ + goto done; + if (status & ~(USBSTS_USBINT | USBSTS_ERROR | USBSTS_RD)) { if (status & USBSTS_HSE) dev_err(uhci_dev(uhci), "host system error, " @@ -455,7 +459,6 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd) dev_err(uhci_dev(uhci), "host controller process " "error, something bad happened!\n"); if (status & USBSTS_HCH) { - spin_lock(&uhci->lock); if (uhci->rh_state >= UHCI_RH_RUNNING) { dev_err(uhci_dev(uhci), "host controller halted, " @@ -473,15 +476,15 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd) * pending unlinks */ mod_timer(&hcd->rh_timer, jiffies); } - spin_unlock(&uhci->lock); } } - if (status & USBSTS_RD) + if (status & USBSTS_RD) { + spin_unlock(&uhci->lock); usb_hcd_poll_rh_status(hcd); - else { - spin_lock(&uhci->lock); + } else { uhci_scan_schedule(uhci); + done: spin_unlock(&uhci->lock); } @@ -662,9 +665,9 @@ static int uhci_start(struct usb_hcd *hcd) */ mb(); + spin_lock_irq(&uhci->lock); configure_hc(uhci); uhci->is_initialized = 1; - spin_lock_irq(&uhci->lock); start_rh(uhci); spin_unlock_irq(&uhci->lock); return 0; diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index f97ab9f9452..4e374b3dd12 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -503,11 +503,48 @@ static void xhci_hub_report_link_state(u32 *status, u32 status_reg) * when this bit is set. */ pls |= USB_PORT_STAT_CONNECTION; + } else { + /* + * If CAS bit isn't set but the Port is already at + * Compliance Mode, fake a connection so the USB core + * notices the Compliance state and resets the port. + * This resolves an issue generated by the SN65LVPE502CP + * in which sometimes the port enters compliance mode + * caused by a delay on the host-device negotiation. + */ + if (pls == USB_SS_PORT_LS_COMP_MOD) + pls |= USB_PORT_STAT_CONNECTION; } + /* update status field */ *status |= pls; } +/* + * Function for Compliance Mode Quirk. + * + * This Function verifies if all xhc USB3 ports have entered U0, if so, + * the compliance mode timer is deleted. A port won't enter + * compliance mode if it has previously entered U0. + */ +void xhci_del_comp_mod_timer(struct xhci_hcd *xhci, u32 status, u16 wIndex) +{ + u32 all_ports_seen_u0 = ((1 << xhci->num_usb3_ports)-1); + bool port_in_u0 = ((status & PORT_PLS_MASK) == XDEV_U0); + + if (!(xhci->quirks & XHCI_COMP_MODE_QUIRK)) + return; + + if ((xhci->port_status_u0 != all_ports_seen_u0) && port_in_u0) { + xhci->port_status_u0 |= 1 << wIndex; + if (xhci->port_status_u0 == all_ports_seen_u0) { + del_timer_sync(&xhci->comp_mode_recovery_timer); + xhci_dbg(xhci, "All USB3 ports have entered U0 already!\n"); + xhci_dbg(xhci, "Compliance Mode Recovery Timer Deleted.\n"); + } + } +} + int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, char *buf, u16 wLength) { @@ -654,6 +691,11 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, /* Update Port Link State for super speed ports*/ if (hcd->speed == HCD_USB3) { xhci_hub_report_link_state(&status, temp); + /* + * Verify if all USB3 Ports Have entered U0 already. + * Delete Compliance Mode Timer if so. + */ + xhci_del_comp_mod_timer(xhci, temp, wIndex); } if (bus_state->port_c_suspend & (1 << wIndex)) status |= 1 << USB_PORT_FEAT_C_SUSPEND; @@ -721,12 +763,39 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, break; case USB_PORT_FEAT_LINK_STATE: temp = xhci_readl(xhci, port_array[wIndex]); + + /* Disable port */ + if (link_state == USB_SS_PORT_LS_SS_DISABLED) { + xhci_dbg(xhci, "Disable port %d\n", wIndex); + temp = xhci_port_state_to_neutral(temp); + /* + * Clear all change bits, so that we get a new + * connection event. + */ + temp |= PORT_CSC | PORT_PEC | PORT_WRC | + PORT_OCC | PORT_RC | PORT_PLC | + PORT_CEC; + xhci_writel(xhci, temp | PORT_PE, + port_array[wIndex]); + temp = xhci_readl(xhci, port_array[wIndex]); + break; + } + + /* Put link in RxDetect (enable port) */ + if (link_state == USB_SS_PORT_LS_RX_DETECT) { + xhci_dbg(xhci, "Enable port %d\n", wIndex); + xhci_set_link_state(xhci, port_array, wIndex, + link_state); + temp = xhci_readl(xhci, port_array[wIndex]); + break; + } + /* Software should not attempt to set - * port link state above '5' (Rx.Detect) and the port + * port link state above '3' (U3) and the port * must be enabled. */ if ((temp & PORT_PE) == 0 || - (link_state > USB_SS_PORT_LS_RX_DETECT)) { + (link_state > USB_SS_PORT_LS_U3)) { xhci_warn(xhci, "Cannot set link state.\n"); goto error; } @@ -887,6 +956,7 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf) int max_ports; __le32 __iomem **port_array; struct xhci_bus_state *bus_state; + bool reset_change = false; max_ports = xhci_get_ports(hcd, &port_array); bus_state = &xhci->bus_state[hcd_index(hcd)]; @@ -918,6 +988,12 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf) buf[(i + 1) / 8] |= 1 << (i + 1) % 8; status = 1; } + if ((temp & PORT_RC)) + reset_change = true; + } + if (!status && !reset_change) { + xhci_dbg(xhci, "%s: stopping port polling.\n", __func__); + clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); } spin_unlock_irqrestore(&xhci->lock, flags); return status ? retval : 0; diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 6b908249b01..b42a6fb45b2 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -205,7 +205,12 @@ static int xhci_alloc_segments_for_ring(struct xhci_hcd *xhci, next = xhci_segment_alloc(xhci, cycle_state, flags); if (!next) { - xhci_free_segments_for_ring(xhci, *first); + prev = *first; + while (prev) { + next = prev->next; + xhci_segment_free(xhci, prev); + prev = next; + } return -ENOMEM; } xhci_link_segments(xhci, prev, next, type); @@ -258,7 +263,7 @@ static struct xhci_ring *xhci_ring_alloc(struct xhci_hcd *xhci, return ring; fail: - xhci_ring_free(xhci, ring); + kfree(ring); return NULL; } @@ -1245,6 +1250,8 @@ static unsigned int xhci_microframes_to_exponent(struct usb_device *udev, static unsigned int xhci_parse_microframe_interval(struct usb_device *udev, struct usb_host_endpoint *ep) { + if (ep->desc.bInterval == 0) + return 0; return xhci_microframes_to_exponent(udev, ep, ep->desc.bInterval, 0, 15); } @@ -1772,6 +1779,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) { struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller); struct dev_info *dev_info, *next; + struct xhci_cd *cur_cd, *next_cd; unsigned long flags; int size; int i, j, num_ports; @@ -1793,6 +1801,11 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) xhci_ring_free(xhci, xhci->cmd_ring); xhci->cmd_ring = NULL; xhci_dbg(xhci, "Freed command ring\n"); + list_for_each_entry_safe(cur_cd, next_cd, + &xhci->cancel_cmd_list, cancel_cmd_list) { + list_del(&cur_cd->cancel_cmd_list); + kfree(cur_cd); + } for (i = 1; i < MAX_HC_SLOTS; ++i) xhci_free_virt_device(xhci, i); @@ -2338,6 +2351,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) xhci->cmd_ring = xhci_ring_alloc(xhci, 1, 1, TYPE_COMMAND, flags); if (!xhci->cmd_ring) goto fail; + INIT_LIST_HEAD(&xhci->cancel_cmd_list); xhci_dbg(xhci, "Allocated command ring at %p\n", xhci->cmd_ring); xhci_dbg(xhci, "First segment DMA is 0x%llx\n", (unsigned long long)xhci->cmd_ring->first_seg->dma); diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 19e89216436..84e82dc7b79 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -29,6 +29,7 @@ /* Device for a quirk */ #define PCI_VENDOR_ID_FRESCO_LOGIC 0x1b73 #define PCI_DEVICE_ID_FRESCO_LOGIC_PDK 0x1000 +#define PCI_DEVICE_ID_FRESCO_LOGIC_FL1400 0x1400 #define PCI_VENDOR_ID_ETRON 0x1b6f #define PCI_DEVICE_ID_ASROCK_P67 0x7023 @@ -58,8 +59,10 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) /* Look for vendor-specific quirks */ if (pdev->vendor == PCI_VENDOR_ID_FRESCO_LOGIC && - pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK) { - if (pdev->revision == 0x0) { + (pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK || + pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_FL1400)) { + if (pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK && + pdev->revision == 0x0) { xhci->quirks |= XHCI_RESET_EP_QUIRK; xhci_dbg(xhci, "QUIRK: Fresco Logic xHC needs configure" " endpoint cmd after reset endpoint\n"); @@ -90,11 +93,22 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) xhci->quirks |= XHCI_EP_LIMIT_QUIRK; xhci->limit_active_eps = 64; xhci->quirks |= XHCI_SW_BW_CHECKING; + /* + * PPT desktop boards DH77EB and DH77DF will power back on after + * a few seconds of being shutdown. The fix for this is to + * switch the ports from xHCI to EHCI on shutdown. We can't use + * DMI information to find those particular boards (since each + * vendor will change the board name), so we have to key off all + * 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) { xhci->quirks |= XHCI_RESET_ON_RESUME; xhci_dbg(xhci, "QUIRK: Resetting on resume\n"); + xhci->quirks |= XHCI_TRUST_TX_LENGTH; } if (pdev->vendor == PCI_VENDOR_ID_VIA) xhci->quirks |= XHCI_RESET_ON_RESUME; diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index d895f27de63..85781e869d2 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -132,7 +132,7 @@ static int xhci_plat_probe(struct platform_device *pdev) goto put_hcd; } - hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); + hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len); if (!hcd->regs) { dev_dbg(&pdev->dev, "error mapping memory\n"); ret = -EFAULT; diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 525a1ee8127..b2b58a5c45e 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -272,12 +272,123 @@ static inline int room_on_ring(struct xhci_hcd *xhci, struct xhci_ring *ring, /* Ring the host controller doorbell after placing a command on the ring */ void xhci_ring_cmd_db(struct xhci_hcd *xhci) { + if (!(xhci->cmd_ring_state & CMD_RING_STATE_RUNNING)) + return; + xhci_dbg(xhci, "// Ding dong!\n"); xhci_writel(xhci, DB_VALUE_HOST, &xhci->dba->doorbell[0]); /* Flush PCI posted writes */ xhci_readl(xhci, &xhci->dba->doorbell[0]); } +static int xhci_abort_cmd_ring(struct xhci_hcd *xhci) +{ + u64 temp_64; + int ret; + + xhci_dbg(xhci, "Abort command ring\n"); + + if (!(xhci->cmd_ring_state & CMD_RING_STATE_RUNNING)) { + xhci_dbg(xhci, "The command ring isn't running, " + "Have the command ring been stopped?\n"); + return 0; + } + + temp_64 = xhci_read_64(xhci, &xhci->op_regs->cmd_ring); + if (!(temp_64 & CMD_RING_RUNNING)) { + xhci_dbg(xhci, "Command ring had been stopped\n"); + return 0; + } + xhci->cmd_ring_state = CMD_RING_STATE_ABORTED; + xhci_write_64(xhci, temp_64 | CMD_RING_ABORT, + &xhci->op_regs->cmd_ring); + + /* Section 4.6.1.2 of xHCI 1.0 spec says software should + * time the completion od all xHCI commands, including + * the Command Abort operation. If software doesn't see + * CRR negated in a timely manner (e.g. longer than 5 + * seconds), then it should assume that the there are + * larger problems with the xHC and assert HCRST. + */ + ret = handshake(xhci, &xhci->op_regs->cmd_ring, + CMD_RING_RUNNING, 0, 5 * 1000 * 1000); + if (ret < 0) { + xhci_err(xhci, "Stopped the command ring failed, " + "maybe the host is dead\n"); + xhci->xhc_state |= XHCI_STATE_DYING; + xhci_quiesce(xhci); + xhci_halt(xhci); + return -ESHUTDOWN; + } + + return 0; +} + +static int xhci_queue_cd(struct xhci_hcd *xhci, + struct xhci_command *command, + union xhci_trb *cmd_trb) +{ + struct xhci_cd *cd; + cd = kzalloc(sizeof(struct xhci_cd), GFP_ATOMIC); + if (!cd) + return -ENOMEM; + INIT_LIST_HEAD(&cd->cancel_cmd_list); + + cd->command = command; + cd->cmd_trb = cmd_trb; + list_add_tail(&cd->cancel_cmd_list, &xhci->cancel_cmd_list); + + return 0; +} + +/* + * Cancel the command which has issue. + * + * Some commands may hang due to waiting for acknowledgement from + * usb device. It is outside of the xHC's ability to control and + * will cause the command ring is blocked. When it occurs software + * should intervene to recover the command ring. + * See Section 4.6.1.1 and 4.6.1.2 + */ +int xhci_cancel_cmd(struct xhci_hcd *xhci, struct xhci_command *command, + union xhci_trb *cmd_trb) +{ + int retval = 0; + unsigned long flags; + + spin_lock_irqsave(&xhci->lock, flags); + + if (xhci->xhc_state & XHCI_STATE_DYING) { + xhci_warn(xhci, "Abort the command ring," + " but the xHCI is dead.\n"); + retval = -ESHUTDOWN; + goto fail; + } + + /* queue the cmd desriptor to cancel_cmd_list */ + retval = xhci_queue_cd(xhci, command, cmd_trb); + if (retval) { + xhci_warn(xhci, "Queuing command descriptor failed.\n"); + goto fail; + } + + /* abort command ring */ + retval = xhci_abort_cmd_ring(xhci); + if (retval) { + xhci_err(xhci, "Abort command ring failed\n"); + if (unlikely(retval == -ESHUTDOWN)) { + spin_unlock_irqrestore(&xhci->lock, flags); + usb_hc_died(xhci_to_hcd(xhci)->primary_hcd); + xhci_dbg(xhci, "xHCI host controller is dead.\n"); + return retval; + } + } + +fail: + spin_unlock_irqrestore(&xhci->lock, flags); + return retval; +} + void xhci_ring_ep_doorbell(struct xhci_hcd *xhci, unsigned int slot_id, unsigned int ep_index, @@ -1040,6 +1151,20 @@ static void handle_reset_ep_completion(struct xhci_hcd *xhci, } } +/* Complete the command and detele it from the devcie's command queue. + */ +static void xhci_complete_cmd_in_cmd_wait_list(struct xhci_hcd *xhci, + struct xhci_command *command, u32 status) +{ + command->status = status; + list_del(&command->cmd_list); + if (command->completion) + complete(command->completion); + else + xhci_free_command(xhci, command); +} + + /* Check to see if a command in the device's command queue matches this one. * Signal the completion or free the command, and return 1. Return 0 if the * completed command isn't at the head of the command list. @@ -1058,15 +1183,155 @@ static int handle_cmd_in_cmd_wait_list(struct xhci_hcd *xhci, if (xhci->cmd_ring->dequeue != command->command_trb) return 0; - command->status = GET_COMP_CODE(le32_to_cpu(event->status)); - list_del(&command->cmd_list); - if (command->completion) - complete(command->completion); - else - xhci_free_command(xhci, command); + xhci_complete_cmd_in_cmd_wait_list(xhci, command, + GET_COMP_CODE(le32_to_cpu(event->status))); return 1; } +/* + * Finding the command trb need to be cancelled and modifying it to + * NO OP command. And if the command is in device's command wait + * list, finishing and freeing it. + * + * If we can't find the command trb, we think it had already been + * executed. + */ +static void xhci_cmd_to_noop(struct xhci_hcd *xhci, struct xhci_cd *cur_cd) +{ + struct xhci_segment *cur_seg; + union xhci_trb *cmd_trb; + u32 cycle_state; + + if (xhci->cmd_ring->dequeue == xhci->cmd_ring->enqueue) + return; + + /* find the current segment of command ring */ + cur_seg = find_trb_seg(xhci->cmd_ring->first_seg, + xhci->cmd_ring->dequeue, &cycle_state); + + if (!cur_seg) { + xhci_warn(xhci, "Command ring mismatch, dequeue = %p %llx (dma)\n", + xhci->cmd_ring->dequeue, + (unsigned long long) + xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg, + xhci->cmd_ring->dequeue)); + xhci_debug_ring(xhci, xhci->cmd_ring); + xhci_dbg_ring_ptrs(xhci, xhci->cmd_ring); + return; + } + + /* find the command trb matched by cd from command ring */ + for (cmd_trb = xhci->cmd_ring->dequeue; + cmd_trb != xhci->cmd_ring->enqueue; + next_trb(xhci, xhci->cmd_ring, &cur_seg, &cmd_trb)) { + /* If the trb is link trb, continue */ + if (TRB_TYPE_LINK_LE32(cmd_trb->generic.field[3])) + continue; + + if (cur_cd->cmd_trb == cmd_trb) { + + /* If the command in device's command list, we should + * finish it and free the command structure. + */ + if (cur_cd->command) + xhci_complete_cmd_in_cmd_wait_list(xhci, + cur_cd->command, COMP_CMD_STOP); + + /* get cycle state from the origin command trb */ + cycle_state = le32_to_cpu(cmd_trb->generic.field[3]) + & TRB_CYCLE; + + /* modify the command trb to NO OP command */ + cmd_trb->generic.field[0] = 0; + cmd_trb->generic.field[1] = 0; + cmd_trb->generic.field[2] = 0; + cmd_trb->generic.field[3] = cpu_to_le32( + TRB_TYPE(TRB_CMD_NOOP) | cycle_state); + break; + } + } +} + +static void xhci_cancel_cmd_in_cd_list(struct xhci_hcd *xhci) +{ + struct xhci_cd *cur_cd, *next_cd; + + if (list_empty(&xhci->cancel_cmd_list)) + return; + + list_for_each_entry_safe(cur_cd, next_cd, + &xhci->cancel_cmd_list, cancel_cmd_list) { + xhci_cmd_to_noop(xhci, cur_cd); + list_del(&cur_cd->cancel_cmd_list); + kfree(cur_cd); + } +} + +/* + * traversing the cancel_cmd_list. If the command descriptor according + * to cmd_trb is found, the function free it and return 1, otherwise + * return 0. + */ +static int xhci_search_cmd_trb_in_cd_list(struct xhci_hcd *xhci, + union xhci_trb *cmd_trb) +{ + struct xhci_cd *cur_cd, *next_cd; + + if (list_empty(&xhci->cancel_cmd_list)) + return 0; + + list_for_each_entry_safe(cur_cd, next_cd, + &xhci->cancel_cmd_list, cancel_cmd_list) { + if (cur_cd->cmd_trb == cmd_trb) { + if (cur_cd->command) + xhci_complete_cmd_in_cmd_wait_list(xhci, + cur_cd->command, COMP_CMD_STOP); + list_del(&cur_cd->cancel_cmd_list); + kfree(cur_cd); + return 1; + } + } + + return 0; +} + +/* + * If the cmd_trb_comp_code is COMP_CMD_ABORT, we just check whether the + * trb pointed by the command ring dequeue pointer is the trb we want to + * cancel or not. And if the cmd_trb_comp_code is COMP_CMD_STOP, we will + * traverse the cancel_cmd_list to trun the all of the commands according + * to command descriptor to NO-OP trb. + */ +static int handle_stopped_cmd_ring(struct xhci_hcd *xhci, + int cmd_trb_comp_code) +{ + int cur_trb_is_good = 0; + + /* Searching the cmd trb pointed by the command ring dequeue + * pointer in command descriptor list. If it is found, free it. + */ + cur_trb_is_good = xhci_search_cmd_trb_in_cd_list(xhci, + xhci->cmd_ring->dequeue); + + if (cmd_trb_comp_code == COMP_CMD_ABORT) + xhci->cmd_ring_state = CMD_RING_STATE_STOPPED; + else if (cmd_trb_comp_code == COMP_CMD_STOP) { + /* traversing the cancel_cmd_list and canceling + * the command according to command descriptor + */ + xhci_cancel_cmd_in_cd_list(xhci); + + xhci->cmd_ring_state = CMD_RING_STATE_RUNNING; + /* + * ring command ring doorbell again to restart the + * command ring + */ + if (xhci->cmd_ring->dequeue != xhci->cmd_ring->enqueue) + xhci_ring_cmd_db(xhci); + } + return cur_trb_is_good; +} + static void handle_cmd_completion(struct xhci_hcd *xhci, struct xhci_event_cmd *event) { @@ -1092,6 +1357,22 @@ static void handle_cmd_completion(struct xhci_hcd *xhci, xhci->error_bitmask |= 1 << 5; return; } + + if ((GET_COMP_CODE(le32_to_cpu(event->status)) == COMP_CMD_ABORT) || + (GET_COMP_CODE(le32_to_cpu(event->status)) == COMP_CMD_STOP)) { + /* If the return value is 0, we think the trb pointed by + * command ring dequeue pointer is a good trb. The good + * trb means we don't want to cancel the trb, but it have + * been stopped by host. So we should handle it normally. + * Otherwise, driver should invoke inc_deq() and return. + */ + if (handle_stopped_cmd_ring(xhci, + GET_COMP_CODE(le32_to_cpu(event->status)))) { + inc_deq(xhci, xhci->cmd_ring); + return; + } + } + switch (le32_to_cpu(xhci->cmd_ring->dequeue->generic.field[3]) & TRB_TYPE_BITMASK) { case TRB_TYPE(TRB_ENABLE_SLOT): @@ -1398,7 +1679,7 @@ static void handle_port_status(struct xhci_hcd *xhci, faked_port_index + 1); if (slot_id && xhci->devs[slot_id]) xhci_ring_device(xhci, slot_id); - if (bus_state->port_remote_wakeup && (1 << faked_port_index)) { + if (bus_state->port_remote_wakeup & (1 << faked_port_index)) { bus_state->port_remote_wakeup &= ~(1 << faked_port_index); xhci_test_and_clear_bit(xhci, port_array, @@ -1425,6 +1706,15 @@ static void handle_port_status(struct xhci_hcd *xhci, if (bogus_port_status) return; + /* + * xHCI port-status-change events occur when the "or" of all the + * status-change bits in the portsc register changes from 0 to 1. + * New status changes won't cause an event if any other change + * bits are still set. When an event occurs, switch over to + * polling to avoid losing status changes. + */ + xhci_dbg(xhci, "%s: starting port polling.\n", __func__); + set_bit(HCD_FLAG_POLL_RH, &hcd->flags); spin_unlock(&xhci->lock); /* Pass this up to the core */ usb_hcd_poll_rh_status(hcd); @@ -2278,6 +2568,8 @@ static int handle_tx_event(struct xhci_hcd *xhci, (trb_comp_code != COMP_STALL && trb_comp_code != COMP_BABBLE)) xhci_urb_free_priv(xhci, urb_priv); + else + kfree(urb_priv); usb_hcd_unlink_urb_from_ep(bus_to_hcd(urb->dev->bus), urb); if ((urb->actual_length != urb->transfer_buffer_length && @@ -2769,11 +3061,11 @@ static u32 xhci_td_remainder(unsigned int remainder) } /* - * For xHCI 1.0 host controllers, TD size is the number of packets remaining in - * the TD (*not* including this TRB). + * For xHCI 1.0 host controllers, TD size is the number of max packet sized + * packets remaining in the TD (*not* including this TRB). * * Total TD packet count = total_packet_count = - * roundup(TD size in bytes / wMaxPacketSize) + * DIV_ROUND_UP(TD size in bytes / wMaxPacketSize) * * Packets transferred up to and including this TRB = packets_transferred = * rounddown(total bytes transferred including this TRB / wMaxPacketSize) @@ -2781,24 +3073,27 @@ static u32 xhci_td_remainder(unsigned int remainder) * TD size = total_packet_count - packets_transferred * * It must fit in bits 21:17, so it can't be bigger than 31. + * The last TRB in a TD must have the TD size set to zero. */ - static u32 xhci_v1_0_td_remainder(int running_total, int trb_buff_len, - unsigned int total_packet_count, struct urb *urb) + unsigned int total_packet_count, struct urb *urb, + unsigned int num_trbs_left) { int packets_transferred; /* One TRB with a zero-length data packet. */ - if (running_total == 0 && trb_buff_len == 0) + if (num_trbs_left == 0 || (running_total == 0 && trb_buff_len == 0)) return 0; /* All the TRB queueing functions don't count the current TRB in * running_total. */ packets_transferred = (running_total + trb_buff_len) / - usb_endpoint_maxp(&urb->ep->desc); + GET_MAX_PACKET(usb_endpoint_maxp(&urb->ep->desc)); - return xhci_td_remainder(total_packet_count - packets_transferred); + if ((total_packet_count - packets_transferred) > 31) + return 31 << 17; + return (total_packet_count - packets_transferred) << 17; } static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, @@ -2825,7 +3120,7 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, num_trbs = count_sg_trbs_needed(xhci, urb); num_sgs = urb->num_mapped_sgs; - total_packet_count = roundup(urb->transfer_buffer_length, + total_packet_count = DIV_ROUND_UP(urb->transfer_buffer_length, usb_endpoint_maxp(&urb->ep->desc)); trb_buff_len = prepare_transfer(xhci, xhci->devs[slot_id], @@ -2908,7 +3203,8 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, running_total); } else { remainder = xhci_v1_0_td_remainder(running_total, - trb_buff_len, total_packet_count, urb); + trb_buff_len, total_packet_count, urb, + num_trbs - 1); } length_field = TRB_LEN(trb_buff_len) | remainder | @@ -3016,7 +3312,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, start_cycle = ep_ring->cycle_state; running_total = 0; - total_packet_count = roundup(urb->transfer_buffer_length, + total_packet_count = DIV_ROUND_UP(urb->transfer_buffer_length, usb_endpoint_maxp(&urb->ep->desc)); /* How much data is in the first TRB? */ addr = (u64) urb->transfer_dma; @@ -3062,7 +3358,8 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, running_total); } else { remainder = xhci_v1_0_td_remainder(running_total, - trb_buff_len, total_packet_count, urb); + trb_buff_len, total_packet_count, urb, + num_trbs - 1); } length_field = TRB_LEN(trb_buff_len) | remainder | @@ -3325,8 +3622,9 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, addr = start_addr + urb->iso_frame_desc[i].offset; td_len = urb->iso_frame_desc[i].length; td_remain_len = td_len; - total_packet_count = roundup(td_len, - usb_endpoint_maxp(&urb->ep->desc)); + total_packet_count = DIV_ROUND_UP(td_len, + GET_MAX_PACKET( + usb_endpoint_maxp(&urb->ep->desc))); /* A zero-length transfer still involves at least one packet. */ if (total_packet_count == 0) total_packet_count++; @@ -3348,9 +3646,11 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, td = urb_priv->td[i]; for (j = 0; j < trbs_per_td; j++) { u32 remainder = 0; - field = TRB_TBC(burst_count) | TRB_TLBPC(residue); + field = 0; if (first_trb) { + field = TRB_TBC(burst_count) | + TRB_TLBPC(residue); /* Queue the isoc TRB */ field |= TRB_TYPE(TRB_ISOC); /* Assume URB_ISO_ASAP is set */ @@ -3381,7 +3681,9 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, } else { td->last_trb = ep_ring->enqueue; field |= TRB_IOC; - if (xhci->hci_version == 0x100) { + if (xhci->hci_version == 0x100 && + !(xhci->quirks & + XHCI_AVOID_BEI)) { /* Set BEI bit except for the last td */ if (i < num_tds - 1) field |= TRB_BEI; @@ -3402,7 +3704,8 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, } else { remainder = xhci_v1_0_td_remainder( running_total, trb_buff_len, - total_packet_count, urb); + total_packet_count, urb, + (trbs_per_td - j - 1)); } length_field = TRB_LEN(trb_buff_len) | remainder | diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index dc1bbc524a5..4b93c39fca5 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "xhci.h" @@ -51,7 +52,7 @@ MODULE_PARM_DESC(link_quirk, "Don't clear the chain bit on a link TRB"); * handshake done). There are two failure modes: "usec" have passed (major * hardware flakeout), or the register reads as all-ones (hardware removed). */ -static int handshake(struct xhci_hcd *xhci, void __iomem *ptr, +int handshake(struct xhci_hcd *xhci, void __iomem *ptr, u32 mask, u32 done, int usec) { u32 result; @@ -104,9 +105,10 @@ int xhci_halt(struct xhci_hcd *xhci) ret = handshake(xhci, &xhci->op_regs->status, STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC); - if (!ret) + if (!ret) { xhci->xhc_state |= XHCI_STATE_HALTED; - else + xhci->cmd_ring_state = CMD_RING_STATE_STOPPED; + } else xhci_warn(xhci, "Host not halted after %u microseconds.\n", XHCI_MAX_HALT_USEC); return ret; @@ -166,7 +168,7 @@ int xhci_reset(struct xhci_hcd *xhci) xhci_writel(xhci, command, &xhci->op_regs->command); ret = handshake(xhci, &xhci->op_regs->command, - CMD_RESET, 0, 250 * 1000); + CMD_RESET, 0, 10 * 1000 * 1000); if (ret) return ret; @@ -175,7 +177,8 @@ int xhci_reset(struct xhci_hcd *xhci) * xHCI cannot write to any doorbells or operational registers other * than status until the "Controller Not Ready" flag is cleared. */ - ret = handshake(xhci, &xhci->op_regs->status, STS_CNR, 0, 250 * 1000); + ret = handshake(xhci, &xhci->op_regs->status, + STS_CNR, 0, 10 * 1000 * 1000); for (i = 0; i < 2; ++i) { xhci->bus_state[i].port_c_suspend = 0; @@ -383,6 +386,98 @@ static void xhci_cleanup_msix(struct xhci_hcd *xhci) #endif /* CONFIG_PCI */ +static void compliance_mode_recovery(unsigned long arg) +{ + struct xhci_hcd *xhci; + struct usb_hcd *hcd; + u32 temp; + int i; + + xhci = (struct xhci_hcd *)arg; + + for (i = 0; i < xhci->num_usb3_ports; i++) { + temp = xhci_readl(xhci, xhci->usb3_ports[i]); + if ((temp & PORT_PLS_MASK) == USB_SS_PORT_LS_COMP_MOD) { + /* + * Compliance Mode Detected. Letting USB Core + * handle the Warm Reset + */ + xhci_dbg(xhci, "Compliance Mode Detected->Port %d!\n", + i + 1); + xhci_dbg(xhci, "Attempting Recovery routine!\n"); + hcd = xhci->shared_hcd; + + if (hcd->state == HC_STATE_SUSPENDED) + usb_hcd_resume_root_hub(hcd); + + usb_hcd_poll_rh_status(hcd); + } + } + + if (xhci->port_status_u0 != ((1 << xhci->num_usb3_ports)-1)) + mod_timer(&xhci->comp_mode_recovery_timer, + jiffies + msecs_to_jiffies(COMP_MODE_RCVRY_MSECS)); +} + +/* + * Quirk to work around issue generated by the SN65LVPE502CP USB3.0 re-driver + * that causes ports behind that hardware to enter compliance mode sometimes. + * The quirk creates a timer that polls every 2 seconds the link state of + * each host controller's port and recovers it by issuing a Warm reset + * if Compliance mode is detected, otherwise the port will become "dead" (no + * device connections or disconnections will be detected anymore). Becasue no + * status event is generated when entering compliance mode (per xhci spec), + * this quirk is needed on systems that have the failing hardware installed. + */ +static void compliance_mode_recovery_timer_init(struct xhci_hcd *xhci) +{ + xhci->port_status_u0 = 0; + init_timer(&xhci->comp_mode_recovery_timer); + + xhci->comp_mode_recovery_timer.data = (unsigned long) xhci; + xhci->comp_mode_recovery_timer.function = compliance_mode_recovery; + xhci->comp_mode_recovery_timer.expires = jiffies + + msecs_to_jiffies(COMP_MODE_RCVRY_MSECS); + + set_timer_slack(&xhci->comp_mode_recovery_timer, + msecs_to_jiffies(COMP_MODE_RCVRY_MSECS)); + add_timer(&xhci->comp_mode_recovery_timer); + xhci_dbg(xhci, "Compliance Mode Recovery Timer Initialized.\n"); +} + +/* + * This function identifies the systems that have installed the SN65LVPE502CP + * USB3.0 re-driver and that need the Compliance Mode Quirk. + * Systems: + * Vendor: Hewlett-Packard -> System Models: Z420, Z620 and Z820 + */ +static bool compliance_mode_recovery_timer_quirk_check(void) +{ + const char *dmi_product_name, *dmi_sys_vendor; + + dmi_product_name = dmi_get_system_info(DMI_PRODUCT_NAME); + dmi_sys_vendor = dmi_get_system_info(DMI_SYS_VENDOR); + if (!dmi_product_name || !dmi_sys_vendor) + return false; + + if (!(strstr(dmi_sys_vendor, "Hewlett-Packard"))) + return false; + + if (strstr(dmi_product_name, "Z420") || + strstr(dmi_product_name, "Z620") || + strstr(dmi_product_name, "Z820") || + strstr(dmi_product_name, "Z1 Workstation")) + return true; + + return false; +} + +static int xhci_all_ports_seen_u0(struct xhci_hcd *xhci) +{ + return (xhci->port_status_u0 == ((1 << xhci->num_usb3_ports)-1)); +} + + /* * Initialize memory for HCD and xHC (one-time init). * @@ -406,6 +501,12 @@ int xhci_init(struct usb_hcd *hcd) retval = xhci_mem_init(xhci, GFP_KERNEL); xhci_dbg(xhci, "Finished xhci_init\n"); + /* Initializing Compliance Mode Recovery Data If Needed */ + if (compliance_mode_recovery_timer_quirk_check()) { + xhci->quirks |= XHCI_COMP_MODE_QUIRK; + compliance_mode_recovery_timer_init(xhci); + } + return retval; } @@ -470,6 +571,7 @@ static int xhci_run_finished(struct xhci_hcd *xhci) return -ENODEV; } xhci->shared_hcd->state = HC_STATE_RUNNING; + xhci->cmd_ring_state = CMD_RING_STATE_RUNNING; if (xhci->quirks & XHCI_NEC_HOST) xhci_ring_cmd_db(xhci); @@ -621,6 +723,11 @@ void xhci_stop(struct usb_hcd *hcd) del_timer_sync(&xhci->event_ring_timer); #endif + /* Deleting Compliance Mode Recovery Timer */ + if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) && + (!(xhci_all_ports_seen_u0(xhci)))) + del_timer_sync(&xhci->comp_mode_recovery_timer); + if (xhci->quirks & XHCI_AMD_PLL_FIX) usb_amd_dev_put(); @@ -651,6 +758,9 @@ void xhci_shutdown(struct usb_hcd *hcd) { struct xhci_hcd *xhci = hcd_to_xhci(hcd); + if (xhci->quirks & XHCI_SPURIOUS_REBOOT) + usb_disable_xhci_ports(to_pci_dev(hcd->self.controller)); + spin_lock_irq(&xhci->lock); xhci_halt(xhci); spin_unlock_irq(&xhci->lock); @@ -780,6 +890,11 @@ int xhci_suspend(struct xhci_hcd *xhci) struct usb_hcd *hcd = xhci_to_hcd(xhci); u32 command; + /* Don't poll the roothubs on bus suspend. */ + xhci_dbg(xhci, "%s: stopping port polling.\n", __func__); + clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); + del_timer_sync(&hcd->rh_timer); + spin_lock_irq(&xhci->lock); clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); clear_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags); @@ -791,7 +906,7 @@ int xhci_suspend(struct xhci_hcd *xhci) command &= ~CMD_RUN; xhci_writel(xhci, command, &xhci->op_regs->command); if (handshake(xhci, &xhci->op_regs->status, - STS_HALT, STS_HALT, 100*100)) { + STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC)) { xhci_warn(xhci, "WARN: xHC CMD_RUN timeout\n"); spin_unlock_irq(&xhci->lock); return -ETIMEDOUT; @@ -812,6 +927,16 @@ int xhci_suspend(struct xhci_hcd *xhci) } spin_unlock_irq(&xhci->lock); + /* + * Deleting Compliance Mode Recovery Timer because the xHCI Host + * is about to be suspended. + */ + if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) && + (!(xhci_all_ports_seen_u0(xhci)))) { + del_timer_sync(&xhci->comp_mode_recovery_timer); + xhci_dbg(xhci, "Compliance Mode Recovery Timer Deleted!\n"); + } + /* step 5: remove core well power */ /* synchronize irq when using MSI-X */ xhci_msix_sync_irqs(xhci); @@ -944,6 +1069,21 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) usb_hcd_resume_root_hub(hcd); usb_hcd_resume_root_hub(xhci->shared_hcd); } + + /* + * If system is subject to the Quirk, Compliance Mode Timer needs to + * be re-initialized Always after a system resume. Ports are subject + * to suffer the Compliance Mode issue again. It doesn't matter if + * ports have entered previously to U0 before system's suspension. + */ + if (xhci->quirks & XHCI_COMP_MODE_QUIRK) + compliance_mode_recovery_timer_init(xhci); + + /* Re-enable port polling. */ + xhci_dbg(xhci, "%s: starting port polling.\n", __func__); + set_bit(HCD_FLAG_POLL_RH, &hcd->flags); + usb_hcd_poll_rh_status(hcd); + return retval; } #endif /* CONFIG_PM */ @@ -2133,7 +2273,7 @@ static bool xhci_is_async_ep(unsigned int ep_type) static bool xhci_is_sync_in_ep(unsigned int ep_type) { - return (ep_type == ISOC_IN_EP || ep_type != INT_IN_EP); + return (ep_type == ISOC_IN_EP || ep_type == INT_IN_EP); } static unsigned int xhci_get_ss_bw_consumed(struct xhci_bw_info *ep_bw) @@ -2406,6 +2546,7 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci, struct completion *cmd_completion; u32 *cmd_status; struct xhci_virt_device *virt_dev; + union xhci_trb *cmd_trb; spin_lock_irqsave(&xhci->lock, flags); virt_dev = xhci->devs[udev->slot_id]; @@ -2451,6 +2592,7 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci, } init_completion(cmd_completion); + cmd_trb = xhci->cmd_ring->dequeue; if (!ctx_change) ret = xhci_queue_configure_endpoint(xhci, in_ctx->dma, udev->slot_id, must_succeed); @@ -2479,7 +2621,10 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci, ctx_change == 0 ? "configure endpoint" : "evaluate context"); - /* FIXME cancel the configure endpoint command */ + /* cancel the configure endpoint command */ + ret = xhci_cancel_cmd(xhci, command, cmd_trb); + if (ret < 0) + return ret; return -ETIME; } @@ -3428,8 +3573,10 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev) unsigned long flags; int timeleft; int ret; + union xhci_trb *cmd_trb; spin_lock_irqsave(&xhci->lock, flags); + cmd_trb = xhci->cmd_ring->dequeue; ret = xhci_queue_slot_control(xhci, TRB_ENABLE_SLOT, 0); if (ret) { spin_unlock_irqrestore(&xhci->lock, flags); @@ -3445,8 +3592,8 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev) if (timeleft <= 0) { xhci_warn(xhci, "%s while waiting for a slot\n", timeleft == 0 ? "Timeout" : "Signal"); - /* FIXME cancel the enable slot request */ - return 0; + /* cancel the enable slot request */ + return xhci_cancel_cmd(xhci, NULL, cmd_trb); } if (!xhci->slot_id) { @@ -3507,6 +3654,7 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) struct xhci_slot_ctx *slot_ctx; struct xhci_input_control_ctx *ctrl_ctx; u64 temp_64; + union xhci_trb *cmd_trb; if (!udev->slot_id) { xhci_dbg(xhci, "Bad Slot ID %d\n", udev->slot_id); @@ -3545,6 +3693,7 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) xhci_dbg_ctx(xhci, virt_dev->in_ctx, 2); spin_lock_irqsave(&xhci->lock, flags); + cmd_trb = xhci->cmd_ring->dequeue; ret = xhci_queue_address_device(xhci, virt_dev->in_ctx->dma, udev->slot_id); if (ret) { @@ -3565,7 +3714,10 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) if (timeleft <= 0) { xhci_warn(xhci, "%s while waiting for address device command\n", timeleft == 0 ? "Timeout" : "Signal"); - /* FIXME cancel the address device command */ + /* cancel the address device command */ + ret = xhci_cancel_cmd(xhci, NULL, cmd_trb); + if (ret < 0) + return ret; return -ETIME; } diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 03fd3965e9f..affb51334b1 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1252,6 +1252,13 @@ struct xhci_td { union xhci_trb *last_trb; }; +/* command descriptor */ +struct xhci_cd { + struct list_head cancel_cmd_list; + struct xhci_command *command; + union xhci_trb *cmd_trb; +}; + struct xhci_dequeue_state { struct xhci_segment *new_deq_seg; union xhci_trb *new_deq_ptr; @@ -1417,6 +1424,11 @@ struct xhci_hcd { /* data structures */ struct xhci_device_context_array *dcbaa; struct xhci_ring *cmd_ring; + unsigned int cmd_ring_state; +#define CMD_RING_STATE_RUNNING (1 << 0) +#define CMD_RING_STATE_ABORTED (1 << 1) +#define CMD_RING_STATE_STOPPED (1 << 2) + struct list_head cancel_cmd_list; unsigned int cmd_ring_reserved_trbs; struct xhci_ring *event_ring; struct xhci_erst erst; @@ -1485,7 +1497,10 @@ struct xhci_hcd { #define XHCI_RESET_ON_RESUME (1 << 7) #define XHCI_SW_BW_CHECKING (1 << 8) #define XHCI_AMD_0x96_HOST (1 << 9) -#define XHCI_TRUST_TX_LENGTH (1 << 10 +#define XHCI_TRUST_TX_LENGTH (1 << 10) +#define XHCI_SPURIOUS_REBOOT (1 << 13) +#define XHCI_COMP_MODE_QUIRK (1 << 14) +#define XHCI_AVOID_BEI (1 << 15) /* * In Synopsis DWC3 controller, PORTSC register access involves multiple clock * domains. When the software does a PORTSC write, handshakes are needed @@ -1517,6 +1532,11 @@ struct xhci_hcd { unsigned sw_lpm_support:1; /* support xHCI 1.0 spec USB2 hardware LPM */ unsigned hw_lpm_support:1; + /* Compliance Mode Recovery Data */ + struct timer_list comp_mode_recovery_timer; + u32 port_status_u0; +/* Compliance Mode Timer Triggered every 2 seconds */ +#define COMP_MODE_RCVRY_MSECS 2000 }; /* convert between an HCD pointer and the corresponding EHCI_HCD */ @@ -1707,6 +1727,8 @@ static inline void xhci_unregister_plat(void) /* xHCI host controller glue */ typedef void (*xhci_get_quirks_t)(struct device *, struct xhci_hcd *); +int handshake(struct xhci_hcd *xhci, void __iomem *ptr, + u32 mask, u32 done, int usec); void xhci_quiesce(struct xhci_hcd *xhci); int xhci_halt(struct xhci_hcd *xhci); int xhci_reset(struct xhci_hcd *xhci); @@ -1797,6 +1819,8 @@ void xhci_queue_config_ep_quirk(struct xhci_hcd *xhci, unsigned int slot_id, unsigned int ep_index, struct xhci_dequeue_state *deq_state); void xhci_stop_endpoint_command_watchdog(unsigned long arg); +int xhci_cancel_cmd(struct xhci_hcd *xhci, struct xhci_command *command, + union xhci_trb *cmd_trb); void xhci_ring_ep_doorbell(struct xhci_hcd *xhci, unsigned int slot_id, unsigned int ep_index, unsigned int stream_id); diff --git a/drivers/usb/misc/emi62.c b/drivers/usb/misc/emi62.c index 4e0f167a6c4..8be96de5f6e 100644 --- a/drivers/usb/misc/emi62.c +++ b/drivers/usb/misc/emi62.c @@ -256,7 +256,7 @@ static int emi62_load_firmware (struct usb_device *dev) return err; } -static const struct usb_device_id id_table[] __devinitconst = { +static const struct usb_device_id id_table[] = { { USB_DEVICE(EMI62_VENDOR_ID, EMI62_PRODUCT_ID) }, { } /* Terminating entry */ }; diff --git a/drivers/usb/musb/cppi_dma.c b/drivers/usb/musb/cppi_dma.c index 66bc376005d..319cfcf372a 100644 --- a/drivers/usb/musb/cppi_dma.c +++ b/drivers/usb/musb/cppi_dma.c @@ -1313,6 +1313,7 @@ irqreturn_t cppi_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } +EXPORT_SYMBOL_GPL(cppi_interrupt); /* Instantiate a software object representing a DMA controller. */ struct dma_controller *__init diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 66aaccf0449..a2b4008dc06 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -2400,10 +2400,7 @@ static int __init musb_init(void) if (usb_disabled()) return 0; - pr_info("%s: version " MUSB_VERSION ", " - "?dma?" - ", " - "otg (peripheral+host)", + pr_info("%s: version " MUSB_VERSION ", ?dma?, otg (peripheral+host)\n", musb_driver_name); return platform_driver_register(&musb_driver); } diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 53e7e692d61..f38a2783146 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -120,6 +120,7 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x10C4, 0x8477) }, /* Balluff RFID */ { USB_DEVICE(0x10C4, 0x85EA) }, /* AC-Services IBUS-IF */ { USB_DEVICE(0x10C4, 0x85EB) }, /* AC-Services CIS-IBUS */ + { USB_DEVICE(0x10C4, 0x85F8) }, /* Virtenio Preon32 */ { USB_DEVICE(0x10C4, 0x8664) }, /* AC-Services CAN-IF */ { USB_DEVICE(0x10C4, 0x8665) }, /* AC-Services OBD-IF */ { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */ diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 53e3e2c5b33..77469442b3f 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -197,6 +197,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_THROTTLE_PID) }, { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_GATEWAY_PID) }, { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_GBM_PID) }, + { USB_DEVICE(NEWPORT_VID, NEWPORT_AGILIS_PID) }, { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) }, { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) }, { USB_DEVICE(FTDI_VID, FTDI_SPROG_II) }, @@ -584,9 +585,12 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_IBS_PEDO_PID) }, { USB_DEVICE(FTDI_VID, FTDI_IBS_PROD_PID) }, { USB_DEVICE(FTDI_VID, FTDI_TAVIR_STK500_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_TIAO_UMPA_PID), + .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, /* * ELV devices: */ + { USB_DEVICE(FTDI_ELV_VID, FTDI_ELV_WS300_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ELV_USR_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ELV_MSM1_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ELV_KL100_PID) }, @@ -673,6 +677,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_5_PID) }, { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_6_PID) }, { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_7_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_OMNI1509) }, { USB_DEVICE(MOBILITY_VID, MOBILITY_USB_SERIAL_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ACTIVE_ROBOTS_PID) }, { USB_DEVICE(FTDI_VID, FTDI_MHAM_KW_PID) }, @@ -704,6 +709,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_PCDJ_DAC2_PID) }, { USB_DEVICE(FTDI_VID, FTDI_RRCIRKITS_LOCOBUFFER_PID) }, { USB_DEVICE(FTDI_VID, FTDI_ASK_RDR400_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_NZR_SEM_USB_PID) }, { USB_DEVICE(ICOM_VID, ICOM_ID_1_PID) }, { USB_DEVICE(ICOM_VID, ICOM_OPC_U_UC_PID) }, { USB_DEVICE(ICOM_VID, ICOM_ID_RP2C1_PID) }, @@ -804,13 +810,33 @@ static struct usb_device_id id_table_combined [] = { .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { USB_DEVICE(ADI_VID, ADI_GNICEPLUS_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, - { USB_DEVICE(MICROCHIP_VID, MICROCHIP_USB_BOARD_PID) }, + { USB_DEVICE_AND_INTERFACE_INFO(MICROCHIP_VID, MICROCHIP_USB_BOARD_PID, + USB_CLASS_VENDOR_SPEC, + USB_SUBCLASS_VENDOR_SPEC, 0x00) }, { USB_DEVICE(JETI_VID, JETI_SPC1201_PID) }, { USB_DEVICE(MARVELL_VID, MARVELL_SHEEVAPLUG_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { USB_DEVICE(LARSENBRUSGAARD_VID, LB_ALTITRACK_PID) }, { USB_DEVICE(GN_OTOMETRICS_VID, AURICAL_USB_PID) }, + { USB_DEVICE(FTDI_VID, PI_C865_PID) }, + { USB_DEVICE(FTDI_VID, PI_C857_PID) }, + { USB_DEVICE(PI_VID, PI_C866_PID) }, + { USB_DEVICE(PI_VID, PI_C663_PID) }, + { USB_DEVICE(PI_VID, PI_C725_PID) }, + { USB_DEVICE(PI_VID, PI_E517_PID) }, + { USB_DEVICE(PI_VID, PI_C863_PID) }, { USB_DEVICE(PI_VID, PI_E861_PID) }, + { USB_DEVICE(PI_VID, PI_C867_PID) }, + { USB_DEVICE(PI_VID, PI_E609_PID) }, + { USB_DEVICE(PI_VID, PI_E709_PID) }, + { USB_DEVICE(PI_VID, PI_100F_PID) }, + { USB_DEVICE(PI_VID, PI_1011_PID) }, + { USB_DEVICE(PI_VID, PI_1012_PID) }, + { USB_DEVICE(PI_VID, PI_1013_PID) }, + { USB_DEVICE(PI_VID, PI_1014_PID) }, + { USB_DEVICE(PI_VID, PI_1015_PID) }, + { USB_DEVICE(PI_VID, PI_1016_PID) }, + { USB_DEVICE(KONDO_VID, KONDO_USB_SERIAL_PID) }, { USB_DEVICE(BAYER_VID, BAYER_CONTOUR_CABLE_PID) }, { USB_DEVICE(FTDI_VID, MARVELL_OPENRD_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, @@ -857,6 +883,8 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_DISTORTEC_JTAG_LOCK_PICK_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { USB_DEVICE(FTDI_VID, FTDI_LUMEL_PD12_PID) }, + /* Crucible Devices */ + { USB_DEVICE(FTDI_VID, FTDI_CT_COMET_PID) }, { }, /* Optional parameter entry */ { } /* Terminating entry */ }; @@ -1787,7 +1815,7 @@ static int ftdi_8u2232c_probe(struct usb_serial *serial) dbg("%s", __func__); if ((udev->manufacturer && !strcmp(udev->manufacturer, "CALAO Systems")) || - (udev->product && !strcmp(udev->product, "BeagleBone/XDS100"))) + (udev->product && !strcmp(udev->product, "BeagleBone/XDS100V2"))) return ftdi_jtag_probe(serial); return 0; diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 5661c7e2d41..9d359e189a6 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -75,6 +75,9 @@ #define FTDI_OPENDCC_GATEWAY_PID 0xBFDB #define FTDI_OPENDCC_GBM_PID 0xBFDC +/* NZR SEM 16+ USB (http://www.nzr.de) */ +#define FTDI_NZR_SEM_USB_PID 0xC1E0 /* NZR SEM-LOG16+ */ + /* * RR-CirKits LocoBuffer USB (http://www.rr-cirkits.com) */ @@ -144,6 +147,11 @@ #define XSENS_CONVERTER_6_PID 0xD38E #define XSENS_CONVERTER_7_PID 0xD38F +/** + * Zolix (www.zolix.com.cb) product ids + */ +#define FTDI_OMNI1509 0xD491 /* Omni1509 embedded USB-serial */ + /* * NDI (www.ndigital.com) product ids */ @@ -201,7 +209,7 @@ /* * ELV USB devices submitted by Christian Abt of ELV (www.elv.de). - * All of these devices use FTDI's vendor ID (0x0403). + * Almost all of these devices use FTDI's vendor ID (0x0403). * Further IDs taken from ELV Windows .inf file. * * The previously included PID for the UO 100 module was incorrect. @@ -209,6 +217,8 @@ * * Armin Laeuger originally sent the PID for the UM 100 module. */ +#define FTDI_ELV_VID 0x1B1F /* ELV AG */ +#define FTDI_ELV_WS300_PID 0xC006 /* eQ3 WS 300 PC II */ #define FTDI_ELV_USR_PID 0xE000 /* ELV Universal-Sound-Recorder */ #define FTDI_ELV_MSM1_PID 0xE001 /* ELV Mini-Sound-Modul */ #define FTDI_ELV_KL100_PID 0xE002 /* ELV Kfz-Leistungsmesser KL 100 */ @@ -514,6 +524,11 @@ */ #define FTDI_TAVIR_STK500_PID 0xFA33 /* STK500 AVR programmer */ +/* + * TIAO product ids (FTDI_VID) + * http://www.tiaowiki.com/w/Main_Page + */ +#define FTDI_TIAO_UMPA_PID 0x8a98 /* TIAO/DIYGADGET USB Multi-Protocol Adapter */ /********************************/ @@ -539,7 +554,10 @@ /* * Microchip Technology, Inc. * - * MICROCHIP_VID (0x04D8) and MICROCHIP_USB_BOARD_PID (0x000A) are also used by: + * MICROCHIP_VID (0x04D8) and MICROCHIP_USB_BOARD_PID (0x000A) are + * used by single function CDC ACM class based firmware demo + * applications. The VID/PID has also been used in firmware + * emulating FTDI serial chips by: * Hornby Elite - Digital Command Control Console * http://www.hornby.com/hornby-dcc/controllers/ */ @@ -741,6 +759,12 @@ #define TTI_VID 0x103E /* Vendor Id */ #define TTI_QL355P_PID 0x03E8 /* TTi QL355P power supply */ +/* + * Newport Cooperation (www.newport.com) + */ +#define NEWPORT_VID 0x104D +#define NEWPORT_AGILIS_PID 0x3000 + /* Interbiometrics USB I/O Board */ /* Developed for Interbiometrics by Rudolf Gugler */ #define INTERBIOMETRICS_VID 0x1209 @@ -791,8 +815,34 @@ * Physik Instrumente * http://www.physikinstrumente.com/en/products/ */ +/* These two devices use the VID of FTDI */ +#define PI_C865_PID 0xe0a0 /* PI C-865 Piezomotor Controller */ +#define PI_C857_PID 0xe0a1 /* PI Encoder Trigger Box */ + #define PI_VID 0x1a72 /* Vendor ID */ -#define PI_E861_PID 0x1008 /* E-861 piezo controller USB connection */ +#define PI_C866_PID 0x1000 /* PI C-866 Piezomotor Controller */ +#define PI_C663_PID 0x1001 /* PI C-663 Mercury-Step */ +#define PI_C725_PID 0x1002 /* PI C-725 Piezomotor Controller */ +#define PI_E517_PID 0x1005 /* PI E-517 Digital Piezo Controller Operation Module */ +#define PI_C863_PID 0x1007 /* PI C-863 */ +#define PI_E861_PID 0x1008 /* PI E-861 Piezomotor Controller */ +#define PI_C867_PID 0x1009 /* PI C-867 Piezomotor Controller */ +#define PI_E609_PID 0x100D /* PI E-609 Digital Piezo Controller */ +#define PI_E709_PID 0x100E /* PI E-709 Digital Piezo Controller */ +#define PI_100F_PID 0x100F /* PI Digital Piezo Controller */ +#define PI_1011_PID 0x1011 /* PI Digital Piezo Controller */ +#define PI_1012_PID 0x1012 /* PI Motion Controller */ +#define PI_1013_PID 0x1013 /* PI Motion Controller */ +#define PI_1014_PID 0x1014 /* PI Device */ +#define PI_1015_PID 0x1015 /* PI Device */ +#define PI_1016_PID 0x1016 /* PI Digital Servo Module */ + +/* + * Kondo Kagaku Co.Ltd. + * http://www.kondo-robot.com/EN + */ +#define KONDO_VID 0x165c +#define KONDO_USB_SERIAL_PID 0x0002 /* * Bayer Ascensia Contour blood glucose meter USB-converter cable. @@ -1216,3 +1266,9 @@ * ATI command output: Cinterion MC55i */ #define FTDI_CINTERION_MC55I_PID 0xA951 + +/* + * Product: Comet Caller ID decoder + * Manufacturer: Crucible Technologies + */ +#define FTDI_CT_COMET_PID 0x8e08 diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index ef4d7adfbd9..d0bf56dba07 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -533,12 +533,14 @@ static void mct_u232_close(struct usb_serial_port *port) { dbg("%s port %d", __func__, port->number); - if (port->serial->dev) { - /* shutdown our urbs */ - usb_kill_urb(port->write_urb); - usb_kill_urb(port->read_urb); - usb_kill_urb(port->interrupt_in_urb); - } + /* + * Must kill the read urb as it is actually an interrupt urb, which + * generic close thus fails to kill. + */ + usb_kill_urb(port->read_urb); + usb_kill_urb(port->interrupt_in_urb); + + usb_serial_generic_close(port); } /* mct_u232_close */ diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 62739ff58c7..c8542356898 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -235,12 +235,10 @@ struct moschip_port { int port_num; /*Actual port number in the device(1,2,etc) */ struct urb *write_urb; /* write URB for this port */ struct urb *read_urb; /* read URB for this port */ - struct urb *int_urb; __u8 shadowLCR; /* last LCR value received */ __u8 shadowMCR; /* last MCR value received */ char open; char open_ports; - char zombie; wait_queue_head_t wait_chase; /* for handling sleeping while waiting for chase to finish */ wait_queue_head_t delta_msr_wait; /* for handling sleeping while waiting for msr change to happen */ int delta_msr_cond; @@ -505,7 +503,6 @@ static void mos7840_control_callback(struct urb *urb) unsigned char *data; struct moschip_port *mos7840_port; __u8 regval = 0x0; - int result = 0; int status = urb->status; mos7840_port = urb->context; @@ -524,7 +521,7 @@ static void mos7840_control_callback(struct urb *urb) default: dbg("%s - nonzero urb status received: %d", __func__, status); - goto exit; + return; } dbg("%s urb buffer size is %d", __func__, urb->actual_length); @@ -537,17 +534,6 @@ static void mos7840_control_callback(struct urb *urb) mos7840_handle_new_msr(mos7840_port, regval); else if (mos7840_port->MsrLsr == 1) mos7840_handle_new_lsr(mos7840_port, regval); - -exit: - spin_lock(&mos7840_port->pool_lock); - if (!mos7840_port->zombie) - result = usb_submit_urb(mos7840_port->int_urb, GFP_ATOMIC); - spin_unlock(&mos7840_port->pool_lock); - if (result) { - dev_err(&urb->dev->dev, - "%s - Error %d submitting interrupt urb\n", - __func__, result); - } } static int mos7840_get_reg(struct moschip_port *mcs, __u16 Wval, __u16 reg, @@ -655,14 +641,7 @@ static void mos7840_interrupt_callback(struct urb *urb) wreg = MODEM_STATUS_REGISTER; break; } - spin_lock(&mos7840_port->pool_lock); - if (!mos7840_port->zombie) { - rv = mos7840_get_reg(mos7840_port, wval, wreg, &Data); - } else { - spin_unlock(&mos7840_port->pool_lock); - return; - } - spin_unlock(&mos7840_port->pool_lock); + rv = mos7840_get_reg(mos7840_port, wval, wreg, &Data); } } } @@ -1189,9 +1168,12 @@ static int mos7840_chars_in_buffer(struct tty_struct *tty) } spin_lock_irqsave(&mos7840_port->pool_lock, flags); - for (i = 0; i < NUM_URBS; ++i) - if (mos7840_port->busy[i]) - chars += URB_TRANSFER_BUFFER_SIZE; + for (i = 0; i < NUM_URBS; ++i) { + if (mos7840_port->busy[i]) { + struct urb *urb = mos7840_port->write_urb_pool[i]; + chars += urb->transfer_buffer_length; + } + } spin_unlock_irqrestore(&mos7840_port->pool_lock, flags); dbg("%s - returns %d", __func__, chars); return chars; @@ -2587,7 +2569,6 @@ static int mos7840_startup(struct usb_serial *serial) kfree(mos7840_port->ctrl_buf); usb_free_urb(mos7840_port->control_urb); kfree(mos7840_port); - serial->port[i] = NULL; } return status; } @@ -2600,7 +2581,6 @@ static int mos7840_startup(struct usb_serial *serial) static void mos7840_disconnect(struct usb_serial *serial) { int i; - unsigned long flags; struct moschip_port *mos7840_port; dbg("%s", " disconnect :entering.........."); @@ -2618,9 +2598,6 @@ static void mos7840_disconnect(struct usb_serial *serial) mos7840_port = mos7840_get_port_private(serial->port[i]); dbg ("mos7840_port %d = %p", i, mos7840_port); if (mos7840_port) { - spin_lock_irqsave(&mos7840_port->pool_lock, flags); - mos7840_port->zombie = 1; - spin_unlock_irqrestore(&mos7840_port->pool_lock, flags); usb_kill_urb(mos7840_port->control_urb); } } @@ -2654,6 +2631,7 @@ static void mos7840_release(struct usb_serial *serial) mos7840_port = mos7840_get_port_private(serial->port[i]); dbg("mos7840_port %d = %p", i, mos7840_port); if (mos7840_port) { + usb_free_urb(mos7840_port->control_urb); kfree(mos7840_port->ctrl_buf); kfree(mos7840_port->dr); kfree(mos7840_port); diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index 82cc9d202b8..1f850065d15 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c @@ -160,7 +160,11 @@ static int send_control_msg(struct usb_serial_port *port, u8 requesttype, { struct usb_serial *serial = port->serial; int retval; - u8 buffer[2]; + u8 *buffer; + + buffer = kzalloc(1, GFP_KERNEL); + if (!buffer) + return -ENOMEM; buffer[0] = val; /* Send the message to the vendor control endpoint @@ -169,6 +173,7 @@ static int send_control_msg(struct usb_serial_port *port, u8 requesttype, requesttype, USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE, 0, 0, buffer, 1, 0); + kfree(buffer); return retval; } @@ -292,7 +297,7 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port, if (!dr) { dev_err(&port->dev, "out of memory\n"); count = -ENOMEM; - goto error; + goto error_no_dr; } dr->bRequestType = USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT; @@ -322,6 +327,8 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port, return count; error: + kfree(dr); +error_no_dr: usb_free_urb(urb); error_no_urb: kfree(buffer); diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 49484b39cc0..6c077a174bf 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -80,85 +80,10 @@ static void option_instat_callback(struct urb *urb); #define OPTION_PRODUCT_GTM380_MODEM 0x7201 #define HUAWEI_VENDOR_ID 0x12D1 -#define HUAWEI_PRODUCT_E600 0x1001 -#define HUAWEI_PRODUCT_E220 0x1003 -#define HUAWEI_PRODUCT_E220BIS 0x1004 -#define HUAWEI_PRODUCT_E1401 0x1401 -#define HUAWEI_PRODUCT_E1402 0x1402 -#define HUAWEI_PRODUCT_E1403 0x1403 -#define HUAWEI_PRODUCT_E1404 0x1404 -#define HUAWEI_PRODUCT_E1405 0x1405 -#define HUAWEI_PRODUCT_E1406 0x1406 -#define HUAWEI_PRODUCT_E1407 0x1407 -#define HUAWEI_PRODUCT_E1408 0x1408 -#define HUAWEI_PRODUCT_E1409 0x1409 -#define HUAWEI_PRODUCT_E140A 0x140A -#define HUAWEI_PRODUCT_E140B 0x140B -#define HUAWEI_PRODUCT_E140C 0x140C -#define HUAWEI_PRODUCT_E140D 0x140D -#define HUAWEI_PRODUCT_E140E 0x140E -#define HUAWEI_PRODUCT_E140F 0x140F -#define HUAWEI_PRODUCT_E1410 0x1410 -#define HUAWEI_PRODUCT_E1411 0x1411 -#define HUAWEI_PRODUCT_E1412 0x1412 -#define HUAWEI_PRODUCT_E1413 0x1413 -#define HUAWEI_PRODUCT_E1414 0x1414 -#define HUAWEI_PRODUCT_E1415 0x1415 -#define HUAWEI_PRODUCT_E1416 0x1416 -#define HUAWEI_PRODUCT_E1417 0x1417 -#define HUAWEI_PRODUCT_E1418 0x1418 -#define HUAWEI_PRODUCT_E1419 0x1419 -#define HUAWEI_PRODUCT_E141A 0x141A -#define HUAWEI_PRODUCT_E141B 0x141B -#define HUAWEI_PRODUCT_E141C 0x141C -#define HUAWEI_PRODUCT_E141D 0x141D -#define HUAWEI_PRODUCT_E141E 0x141E -#define HUAWEI_PRODUCT_E141F 0x141F -#define HUAWEI_PRODUCT_E1420 0x1420 -#define HUAWEI_PRODUCT_E1421 0x1421 -#define HUAWEI_PRODUCT_E1422 0x1422 -#define HUAWEI_PRODUCT_E1423 0x1423 -#define HUAWEI_PRODUCT_E1424 0x1424 -#define HUAWEI_PRODUCT_E1425 0x1425 -#define HUAWEI_PRODUCT_E1426 0x1426 -#define HUAWEI_PRODUCT_E1427 0x1427 -#define HUAWEI_PRODUCT_E1428 0x1428 -#define HUAWEI_PRODUCT_E1429 0x1429 -#define HUAWEI_PRODUCT_E142A 0x142A -#define HUAWEI_PRODUCT_E142B 0x142B -#define HUAWEI_PRODUCT_E142C 0x142C -#define HUAWEI_PRODUCT_E142D 0x142D -#define HUAWEI_PRODUCT_E142E 0x142E -#define HUAWEI_PRODUCT_E142F 0x142F -#define HUAWEI_PRODUCT_E1430 0x1430 -#define HUAWEI_PRODUCT_E1431 0x1431 -#define HUAWEI_PRODUCT_E1432 0x1432 -#define HUAWEI_PRODUCT_E1433 0x1433 -#define HUAWEI_PRODUCT_E1434 0x1434 -#define HUAWEI_PRODUCT_E1435 0x1435 -#define HUAWEI_PRODUCT_E1436 0x1436 -#define HUAWEI_PRODUCT_E1437 0x1437 -#define HUAWEI_PRODUCT_E1438 0x1438 -#define HUAWEI_PRODUCT_E1439 0x1439 -#define HUAWEI_PRODUCT_E143A 0x143A -#define HUAWEI_PRODUCT_E143B 0x143B -#define HUAWEI_PRODUCT_E143C 0x143C -#define HUAWEI_PRODUCT_E143D 0x143D -#define HUAWEI_PRODUCT_E143E 0x143E -#define HUAWEI_PRODUCT_E143F 0x143F +#define HUAWEI_PRODUCT_E173 0x140C #define HUAWEI_PRODUCT_K4505 0x1464 #define HUAWEI_PRODUCT_K3765 0x1465 -#define HUAWEI_PRODUCT_E14AC 0x14AC -#define HUAWEI_PRODUCT_K3806 0x14AE #define HUAWEI_PRODUCT_K4605 0x14C6 -#define HUAWEI_PRODUCT_K5005 0x14C8 -#define HUAWEI_PRODUCT_K3770 0x14C9 -#define HUAWEI_PRODUCT_K3771 0x14CA -#define HUAWEI_PRODUCT_K4510 0x14CB -#define HUAWEI_PRODUCT_K4511 0x14CC -#define HUAWEI_PRODUCT_ETS1220 0x1803 -#define HUAWEI_PRODUCT_E353 0x1506 -#define HUAWEI_PRODUCT_E173S 0x1C05 #define QUANTA_VENDOR_ID 0x0408 #define QUANTA_PRODUCT_Q101 0xEA02 @@ -233,6 +158,7 @@ static void option_instat_callback(struct urb *urb); #define NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_HIGHSPEED 0x8001 #define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_FULLSPEED 0x9000 #define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_HIGHSPEED 0x9001 +#define NOVATELWIRELESS_PRODUCT_E362 0x9010 #define NOVATELWIRELESS_PRODUCT_G1 0xA001 #define NOVATELWIRELESS_PRODUCT_G1_M 0xA002 #define NOVATELWIRELESS_PRODUCT_G2 0xA010 @@ -268,6 +194,9 @@ static void option_instat_callback(struct urb *urb); #define DELL_PRODUCT_5730_MINICARD_TELUS 0x8181 #define DELL_PRODUCT_5730_MINICARD_VZW 0x8182 +#define DELL_PRODUCT_5800_MINICARD_VZW 0x8195 /* Novatel E362 */ +#define DELL_PRODUCT_5800_V2_MINICARD_VZW 0x8196 /* Novatel E362 */ + #define KYOCERA_VENDOR_ID 0x0c88 #define KYOCERA_PRODUCT_KPC650 0x17da #define KYOCERA_PRODUCT_KPC680 0x180a @@ -313,6 +242,7 @@ static void option_instat_callback(struct urb *urb); #define TELIT_PRODUCT_CC864_DUAL 0x1005 #define TELIT_PRODUCT_CC864_SINGLE 0x1006 #define TELIT_PRODUCT_DE910_DUAL 0x1010 +#define TELIT_PRODUCT_LE920 0x1200 /* ZTE PRODUCTS */ #define ZTE_VENDOR_ID 0x19d2 @@ -358,6 +288,8 @@ static void option_instat_callback(struct urb *urb); /* ALCATEL PRODUCTS */ #define ALCATEL_VENDOR_ID 0x1bbb #define ALCATEL_PRODUCT_X060S_X200 0x0000 +#define ALCATEL_PRODUCT_X220_X500D 0x0017 +#define ALCATEL_PRODUCT_L100V 0x011e #define PIRELLI_VENDOR_ID 0x1266 #define PIRELLI_PRODUCT_C100_1 0x1002 @@ -499,9 +431,12 @@ static void option_instat_callback(struct urb *urb); #define MEDIATEK_VENDOR_ID 0x0e8d #define MEDIATEK_PRODUCT_DC_1COM 0x00a0 #define MEDIATEK_PRODUCT_DC_4COM 0x00a5 +#define MEDIATEK_PRODUCT_DC_4COM2 0x00a7 #define MEDIATEK_PRODUCT_DC_5COM 0x00a4 #define MEDIATEK_PRODUCT_7208_1COM 0x7101 #define MEDIATEK_PRODUCT_7208_2COM 0x7102 +#define MEDIATEK_PRODUCT_7103_2COM 0x7103 +#define MEDIATEK_PRODUCT_7106_2COM 0x7106 #define MEDIATEK_PRODUCT_FP_1COM 0x0003 #define MEDIATEK_PRODUCT_FP_2COM 0x0023 #define MEDIATEK_PRODUCT_FPDC_1COM 0x0043 @@ -511,6 +446,18 @@ static void option_instat_callback(struct urb *urb); #define CELLIENT_VENDOR_ID 0x2692 #define CELLIENT_PRODUCT_MEN200 0x9005 +/* Hyundai Petatel Inc. products */ +#define PETATEL_VENDOR_ID 0x1ff4 +#define PETATEL_PRODUCT_NP10T 0x600e + +/* TP-LINK Incorporated products */ +#define TPLINK_VENDOR_ID 0x2357 +#define TPLINK_PRODUCT_MA180 0x0201 + +/* Changhong products */ +#define CHANGHONG_VENDOR_ID 0x2077 +#define CHANGHONG_PRODUCT_CH690 0x7001 + /* some devices interfaces need special handling due to a number of reasons */ enum option_blacklist_reason { OPTION_BLACKLIST_NONE = 0, @@ -579,11 +526,24 @@ static const struct option_blacklist_info net_intf5_blacklist = { .reserved = BIT(5), }; +static const struct option_blacklist_info net_intf6_blacklist = { + .reserved = BIT(6), +}; + static const struct option_blacklist_info zte_mf626_blacklist = { .sendsetup = BIT(0) | BIT(1), .reserved = BIT(4), }; +static const struct option_blacklist_info zte_1255_blacklist = { + .reserved = BIT(3) | BIT(4), +}; + +static const struct option_blacklist_info telit_le920_blacklist = { + .sendsetup = BIT(0), + .reserved = BIT(1) | BIT(5), +}; + static const struct usb_device_id option_ids[] = { { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) }, @@ -615,104 +575,125 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GLX) }, { USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GKE) }, { USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GLE) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E600, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E220BIS, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1401, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1402, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1403, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1404, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1405, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1406, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1407, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1408, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1409, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140A, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140B, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140C, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140D, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140E, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E140F, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1410, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1411, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1412, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1413, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1414, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1415, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1416, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1417, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1418, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1419, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141A, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141B, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141C, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141D, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141E, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E141F, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1420, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1421, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1422, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1423, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1424, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1425, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1426, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1427, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1428, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1429, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142A, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142B, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142C, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142D, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142E, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E142F, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1430, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1431, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1432, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1433, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1434, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1435, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1436, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1437, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1438, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1439, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143A, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143B, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143C, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143D, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143E, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E143F, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E173S, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E173, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t) &net_intf1_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4505, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t) &huawei_cdc12_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3765, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t) &huawei_cdc12_blacklist }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_ETS1220, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E14AC, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3806, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4605, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t) &huawei_cdc12_blacklist }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4605, 0xff, 0x01, 0x31) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4605, 0xff, 0x01, 0x32) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K5005, 0xff, 0x01, 0x31) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K5005, 0xff, 0x01, 0x32) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K5005, 0xff, 0x01, 0x33) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3770, 0xff, 0x02, 0x31) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3770, 0xff, 0x02, 0x32) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3771, 0xff, 0x02, 0x31) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3771, 0xff, 0x02, 0x32) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4510, 0xff, 0x01, 0x31) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4510, 0xff, 0x01, 0x32) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4511, 0xff, 0x01, 0x31) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4511, 0xff, 0x01, 0x32) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x01) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x02) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x03) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x10) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x12) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x01, 0x13) }, - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x02, 0x01) }, /* E398 3G Modem */ - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x02, 0x02) }, /* E398 3G PC UI Interface */ - { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E353, 0xff, 0x02, 0x03) }, /* E398 3G Application Interface */ + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0xff, 0xff) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x01) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x02) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x03) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x04) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x05) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x06) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x0A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x0B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x0D) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x0E) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x0F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x10) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x12) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x13) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x14) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x15) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x17) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x18) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x19) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x1A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x1B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x1C) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x31) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x32) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x33) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x34) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x35) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x36) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x3A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x3B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x3D) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x3E) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x3F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x48) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x49) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x4A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x4B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x4C) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x61) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x62) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x63) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x64) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x65) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x66) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6D) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6E) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x78) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x79) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x7A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x7B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x7C) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x01) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x02) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x03) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x04) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x05) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x06) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x0A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x0B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x0D) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x0E) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x0F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x10) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x12) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x13) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x14) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x15) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x17) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x18) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x19) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x1A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x1B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x1C) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x31) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x32) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x33) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x34) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x35) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x36) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x3A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x3B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x3D) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x3E) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x3F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x48) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x49) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x4A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x4B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x4C) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x61) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x62) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x63) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x64) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x65) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x66) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6D) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6E) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x78) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x79) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x7A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x7B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x7C) }, + + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) }, { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V620) }, { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V740) }, @@ -754,6 +735,7 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_G2) }, /* Novatel Ovation MC551 a.k.a. Verizon USB551L */ { USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC551, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_E362, 0xff, 0xff, 0xff) }, { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01) }, { USB_DEVICE(AMOI_VENDOR_ID, AMOI_PRODUCT_H01A) }, @@ -776,6 +758,8 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_SPRINT) }, /* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */ { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_TELUS) }, /* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */ { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_VZW) }, /* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */ + { USB_DEVICE_AND_INTERFACE_INFO(DELL_VENDOR_ID, DELL_PRODUCT_5800_MINICARD_VZW, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(DELL_VENDOR_ID, DELL_PRODUCT_5800_V2_MINICARD_VZW, 0xff, 0xff, 0xff) }, { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_E100A) }, /* ADU-E100, ADU-310 */ { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_500A) }, { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_620UW) }, @@ -810,6 +794,8 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_DUAL) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_SINGLE) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_DE910_DUAL) }, + { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE920), + .driver_info = (kernel_ulong_t)&telit_le920_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622, 0xff, 0xff, 0xff) }, /* ZTE WCDMA products */ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0002, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf1_blacklist }, @@ -910,14 +896,24 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0113, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf5_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0117, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0118, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0121, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0118, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf5_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0121, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf5_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0122, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0123, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0124, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0125, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0126, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0123, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0124, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf5_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0125, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf6_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0126, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf5_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0128, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0135, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0136, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0137, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0139, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0142, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0143, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0144, 0xff, 0xff, 0xff) }, @@ -927,8 +923,10 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0153, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0155, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0156, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0157, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0158, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0157, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf5_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0158, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0159, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0161, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0162, 0xff, 0xff, 0xff) }, @@ -936,11 +934,38 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0165, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0167, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0189, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0191, 0xff, 0xff, 0xff), /* ZTE EuFi890 */ + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0196, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0197, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0199, 0xff, 0xff, 0xff), /* ZTE MF820S */ + .driver_info = (kernel_ulong_t)&net_intf1_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0200, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0201, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0254, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0257, 0xff, 0xff, 0xff), /* ZTE MF821 */ + .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0265, 0xff, 0xff, 0xff), /* ONDA MT8205 */ + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0284, 0xff, 0xff, 0xff), /* ZTE MF880 */ + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0317, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0326, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0330, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0395, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0414, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0417, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1008, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1010, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1012, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1012, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1018, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1021, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf2_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1057, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1058, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1059, 0xff, 0xff, 0xff) }, @@ -1056,18 +1081,24 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1169, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1170, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1244, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1245, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1245, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1246, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1247, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1247, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1248, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1249, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1250, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1251, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1252, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1252, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1253, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1254, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1255, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1256, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1254, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1255, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&zte_1255_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1256, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1257, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1258, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1259, 0xff, 0xff, 0xff) }, @@ -1112,8 +1143,20 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1298, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1299, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1300, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1301, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1302, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1303, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1333, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1401, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf2_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1402, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf2_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1424, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf2_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1425, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf2_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1426, 0xff, 0xff, 0xff), /* ZTE MF91 */ + .driver_info = (kernel_ulong_t)&net_intf2_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2002, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&zte_k3765_z_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2003, 0xff, 0xff, 0xff) }, @@ -1125,15 +1168,21 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0070, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0073, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0094, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0130, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0133, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0141, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0130, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf1_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0133, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0141, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf5_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0147, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0152, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0168, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0168, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0170, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0176, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0178, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0176, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0178, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710, 0xff, 0xff, 0xff) }, @@ -1145,6 +1194,10 @@ static const struct usb_device_id option_ids[] = { .driver_info = (kernel_ulong_t)&zte_ad3812_z_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MC2716, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&zte_mc2716_z_blacklist }, + { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x02, 0x01) }, + { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x02, 0x05) }, + { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x86, 0x10) }, + { USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) }, { USB_DEVICE(DLINK_VENDOR_ID, DLINK_PRODUCT_DWM_652) }, { USB_DEVICE(ALINK_VENDOR_ID, DLINK_PRODUCT_DWM_652_U5) }, /* Yes, ALINK_VENDOR_ID */ @@ -1162,6 +1215,9 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S_X200), .driver_info = (kernel_ulong_t)&alcatel_x200_blacklist }, + { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X220_X500D) }, + { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_L100V), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) }, { USB_DEVICE(TLAYTECH_VENDOR_ID, TLAYTECH_PRODUCT_TEU800) }, { USB_DEVICE(LONGCHEER_VENDOR_ID, FOUR_G_SYSTEMS_PRODUCT_W14), @@ -1266,7 +1322,15 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FP_2COM, 0x0a, 0x00, 0x00) }, { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FPDC_1COM, 0x0a, 0x00, 0x00) }, { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FPDC_2COM, 0x0a, 0x00, 0x00) }, + { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_7103_2COM, 0xff, 0x00, 0x00) }, + { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_7106_2COM, 0x02, 0x02, 0x01) }, + { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_4COM2, 0xff, 0x02, 0x01) }, + { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_4COM2, 0xff, 0x00, 0x00) }, { USB_DEVICE(CELLIENT_VENDOR_ID, CELLIENT_PRODUCT_MEN200) }, + { USB_DEVICE(PETATEL_VENDOR_ID, PETATEL_PRODUCT_NP10T) }, + { USB_DEVICE(TPLINK_VENDOR_ID, TPLINK_PRODUCT_MA180), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE(CHANGHONG_VENDOR_ID, CHANGHONG_PRODUCT_CH690) }, { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, option_ids); diff --git a/drivers/usb/serial/qcaux.c b/drivers/usb/serial/qcaux.c index 966245680f5..b223381da32 100644 --- a/drivers/usb/serial/qcaux.c +++ b/drivers/usb/serial/qcaux.c @@ -36,8 +36,6 @@ #define UTSTARCOM_PRODUCT_UM175_V1 0x3712 #define UTSTARCOM_PRODUCT_UM175_V2 0x3714 #define UTSTARCOM_PRODUCT_UM175_ALLTEL 0x3715 -#define PANTECH_PRODUCT_UML190_VZW 0x3716 -#define PANTECH_PRODUCT_UML290_VZW 0x3718 /* CMOTECH devices */ #define CMOTECH_VENDOR_ID 0x16d8 @@ -68,11 +66,9 @@ static struct usb_device_id id_table[] = { { USB_DEVICE_AND_INTERFACE_INFO(LG_VENDOR_ID, LG_PRODUCT_VX4400_6000, 0xff, 0xff, 0x00) }, { USB_DEVICE_AND_INTERFACE_INFO(SANYO_VENDOR_ID, SANYO_PRODUCT_KATANA_LX, 0xff, 0xff, 0x00) }, { USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_U520, 0xff, 0x00, 0x00) }, - { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML190_VZW, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML190_VZW, 0xff, 0xfe, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML290_VZW, 0xff, 0xfd, 0xff) }, /* NMEA */ - { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML290_VZW, 0xff, 0xfe, 0xff) }, /* WMC */ - { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML290_VZW, 0xff, 0xff, 0xff) }, /* DIAG */ + { USB_VENDOR_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, 0xff, 0xfd, 0xff) }, /* NMEA */ + { USB_VENDOR_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, 0xff, 0xfe, 0xff) }, /* WMC */ + { USB_VENDOR_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, 0xff, 0xff, 0xff) }, /* DIAG */ { }, }; MODULE_DEVICE_TABLE(usb, id_table); diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index f5b2c9564b2..bd38e0e31e5 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c @@ -55,6 +55,7 @@ static const struct usb_device_id id_table[] = { {DEVICE_G1K(0x05c6, 0x9221)}, /* Generic Gobi QDL device */ {DEVICE_G1K(0x05c6, 0x9231)}, /* Generic Gobi QDL device */ {DEVICE_G1K(0x1f45, 0x0001)}, /* Unknown Gobi QDL device */ + {DEVICE_G1K(0x1bc7, 0x900e)}, /* Telit Gobi QDL device */ /* Gobi 2000 devices */ {USB_DEVICE(0x1410, 0xa010)}, /* Novatel Gobi 2000 QDL device */ diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 449bf6d31e2..b622d695fdb 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -171,7 +171,6 @@ static int sierra_probe(struct usb_serial *serial, { int result = 0; struct usb_device *udev; - struct sierra_intf_private *data; u8 ifnum; udev = serial->dev; @@ -199,11 +198,6 @@ static int sierra_probe(struct usb_serial *serial, return -ENODEV; } - data = serial->private = kzalloc(sizeof(struct sierra_intf_private), GFP_KERNEL); - if (!data) - return -ENOMEM; - spin_lock_init(&data->susp_lock); - return result; } @@ -914,6 +908,7 @@ static void sierra_dtr_rts(struct usb_serial_port *port, int on) static int sierra_startup(struct usb_serial *serial) { struct usb_serial_port *port; + struct sierra_intf_private *intfdata; struct sierra_port_private *portdata; struct sierra_iface_info *himemoryp = NULL; int i; @@ -921,6 +916,14 @@ static int sierra_startup(struct usb_serial *serial) dev_dbg(&serial->dev->dev, "%s\n", __func__); + intfdata = kzalloc(sizeof(*intfdata), GFP_KERNEL); + if (!intfdata) + return -ENOMEM; + + spin_lock_init(&intfdata->susp_lock); + + usb_set_serial_data(serial, intfdata); + /* Set Device mode to D0 */ sierra_set_power_state(serial->dev, 0x0000); @@ -936,7 +939,7 @@ static int sierra_startup(struct usb_serial *serial) dev_dbg(&port->dev, "%s: kmalloc for " "sierra_port_private (%d) failed!\n", __func__, i); - return -ENOMEM; + goto err; } spin_lock_init(&portdata->lock); init_usb_anchor(&portdata->active); @@ -973,6 +976,14 @@ static int sierra_startup(struct usb_serial *serial) } return 0; +err: + for (--i; i >= 0; --i) { + portdata = usb_get_serial_port_data(serial->port[i]); + kfree(portdata); + } + kfree(intfdata); + + return -ENOMEM; } static void sierra_release(struct usb_serial *serial) @@ -992,6 +1003,7 @@ static void sierra_release(struct usb_serial *serial) continue; kfree(portdata); } + kfree(serial->private); } #ifdef CONFIG_PM diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index bcf261778d0..c627ba21b1e 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -768,7 +768,7 @@ int usb_serial_probe(struct usb_interface *interface, if (retval) { dbg("sub driver rejected device"); - kfree(serial); + usb_serial_put(serial); module_put(type->driver.owner); return retval; } @@ -840,7 +840,7 @@ int usb_serial_probe(struct usb_interface *interface, */ if (num_bulk_in == 0 || num_bulk_out == 0) { dev_info(&interface->dev, "PL-2303 hack: descriptors matched but endpoints did not\n"); - kfree(serial); + usb_serial_put(serial); module_put(type->driver.owner); return -ENODEV; } @@ -854,7 +854,7 @@ int usb_serial_probe(struct usb_interface *interface, if (num_ports == 0) { dev_err(&interface->dev, "Generic device with no bulk out, not allowed.\n"); - kfree(serial); + usb_serial_put(serial); module_put(type->driver.owner); return -EIO; } diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index 407e23c8794..171226ab56f 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c @@ -525,6 +525,7 @@ static int whiteheat_attach(struct usb_serial *serial) "%s: please contact support@connecttech.com\n", serial->type->description); kfree(result); + kfree(command); return -ENODEV; no_command_private: diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index 7691c866637..685edc87265 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig @@ -203,7 +203,7 @@ config USB_STORAGE_ENE_UB6250 config USB_UAS tristate "USB Attached SCSI" - depends on USB && SCSI + depends on USB && SCSI && BROKEN help The USB Attached SCSI protocol is supported by some USB storage devices. It permits higher performance by supporting diff --git a/drivers/usb/storage/initializers.c b/drivers/usb/storage/initializers.c index 105d900150c..16b0bf055ee 100644 --- a/drivers/usb/storage/initializers.c +++ b/drivers/usb/storage/initializers.c @@ -92,8 +92,8 @@ int usb_stor_ucr61s2b_init(struct us_data *us) return 0; } -/* This places the HUAWEI E220 devices in multi-port mode */ -int usb_stor_huawei_e220_init(struct us_data *us) +/* This places the HUAWEI usb dongles in multi-port mode */ +static int usb_stor_huawei_feature_init(struct us_data *us) { int result; @@ -104,3 +104,75 @@ int usb_stor_huawei_e220_init(struct us_data *us) US_DEBUGP("Huawei mode set result is %d\n", result); return 0; } + +/* + * It will send a scsi switch command called rewind' to huawei dongle. + * When the dongle receives this command at the first time, + * it will reboot immediately. After rebooted, it will ignore this command. + * So it is unnecessary to read its response. + */ +static int usb_stor_huawei_scsi_init(struct us_data *us) +{ + int result = 0; + int act_len = 0; + struct bulk_cb_wrap *bcbw = (struct bulk_cb_wrap *) us->iobuf; + char rewind_cmd[] = {0x11, 0x06, 0x20, 0x00, 0x00, 0x01, 0x01, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + bcbw->Signature = cpu_to_le32(US_BULK_CB_SIGN); + bcbw->Tag = 0; + bcbw->DataTransferLength = 0; + bcbw->Flags = bcbw->Lun = 0; + bcbw->Length = sizeof(rewind_cmd); + memset(bcbw->CDB, 0, sizeof(bcbw->CDB)); + memcpy(bcbw->CDB, rewind_cmd, sizeof(rewind_cmd)); + + result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, bcbw, + US_BULK_CB_WRAP_LEN, &act_len); + US_DEBUGP("transfer actual length=%d, result=%d\n", act_len, result); + return result; +} + +/* + * It tries to find the supported Huawei USB dongles. + * In Huawei, they assign the following product IDs + * for all of their mobile broadband dongles, + * including the new dongles in the future. + * So if the product ID is not included in this list, + * it means it is not Huawei's mobile broadband dongles. + */ +static int usb_stor_huawei_dongles_pid(struct us_data *us) +{ + struct usb_interface_descriptor *idesc; + int idProduct; + + idesc = &us->pusb_intf->cur_altsetting->desc; + idProduct = us->pusb_dev->descriptor.idProduct; + /* The first port is CDROM, + * means the dongle in the single port mode, + * and a switch command is required to be sent. */ + if (idesc && idesc->bInterfaceNumber == 0) { + if ((idProduct == 0x1001) + || (idProduct == 0x1003) + || (idProduct == 0x1004) + || (idProduct >= 0x1401 && idProduct <= 0x1500) + || (idProduct >= 0x1505 && idProduct <= 0x1600) + || (idProduct >= 0x1c02 && idProduct <= 0x2202)) { + return 1; + } + } + return 0; +} + +int usb_stor_huawei_init(struct us_data *us) +{ + int result = 0; + + if (usb_stor_huawei_dongles_pid(us)) { + if (us->pusb_dev->descriptor.idProduct >= 0x1446) + result = usb_stor_huawei_scsi_init(us); + else + result = usb_stor_huawei_feature_init(us); + } + return result; +} diff --git a/drivers/usb/storage/initializers.h b/drivers/usb/storage/initializers.h index 529327fbb06..5376d4fc76f 100644 --- a/drivers/usb/storage/initializers.h +++ b/drivers/usb/storage/initializers.h @@ -46,5 +46,5 @@ int usb_stor_euscsi_init(struct us_data *us); * flash reader */ int usb_stor_ucr61s2b_init(struct us_data *us); -/* This places the HUAWEI E220 devices in multi-port mode */ -int usb_stor_huawei_e220_init(struct us_data *us); +/* This places the HUAWEI usb dongles in multi-port mode */ +int usb_stor_huawei_init(struct us_data *us); diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index 8ec8a6e66f5..f98ba40352c 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -58,9 +58,6 @@ enum { SUBMIT_DATA_OUT_URB = (1 << 5), ALLOC_CMD_URB = (1 << 6), SUBMIT_CMD_URB = (1 << 7), - COMPLETED_DATA_IN = (1 << 8), - COMPLETED_DATA_OUT = (1 << 9), - DATA_COMPLETES_CMD = (1 << 10), }; /* Overrides scsi_pointer */ @@ -114,7 +111,6 @@ static void uas_sense(struct urb *urb, struct scsi_cmnd *cmnd) { struct sense_iu *sense_iu = urb->transfer_buffer; struct scsi_device *sdev = cmnd->device; - struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; if (urb->actual_length > 16) { unsigned len = be16_to_cpup(&sense_iu->len); @@ -132,15 +128,13 @@ static void uas_sense(struct urb *urb, struct scsi_cmnd *cmnd) } cmnd->result = sense_iu->status; - if (!(cmdinfo->state & DATA_COMPLETES_CMD)) - cmnd->scsi_done(cmnd); + cmnd->scsi_done(cmnd); } static void uas_sense_old(struct urb *urb, struct scsi_cmnd *cmnd) { struct sense_iu_old *sense_iu = urb->transfer_buffer; struct scsi_device *sdev = cmnd->device; - struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; if (urb->actual_length > 8) { unsigned len = be16_to_cpup(&sense_iu->len) - 2; @@ -158,8 +152,7 @@ static void uas_sense_old(struct urb *urb, struct scsi_cmnd *cmnd) } cmnd->result = sense_iu->status; - if (!(cmdinfo->state & DATA_COMPLETES_CMD)) - cmnd->scsi_done(cmnd); + cmnd->scsi_done(cmnd); } static void uas_xfer_data(struct urb *urb, struct scsi_cmnd *cmnd, @@ -184,7 +177,6 @@ static void uas_stat_cmplt(struct urb *urb) struct Scsi_Host *shost = urb->context; struct uas_dev_info *devinfo = (void *)shost->hostdata[0]; struct scsi_cmnd *cmnd; - struct uas_cmd_info *cmdinfo; u16 tag; int ret; @@ -210,32 +202,12 @@ static void uas_stat_cmplt(struct urb *urb) dev_err(&urb->dev->dev, "failed submit status urb\n"); return; } - cmdinfo = (void *)&cmnd->SCp; switch (iu->iu_id) { case IU_ID_STATUS: if (devinfo->cmnd == cmnd) devinfo->cmnd = NULL; - if (!(cmdinfo->state & COMPLETED_DATA_IN) && - cmdinfo->data_in_urb) { - if (devinfo->use_streams) { - cmdinfo->state |= DATA_COMPLETES_CMD; - usb_unlink_urb(cmdinfo->data_in_urb); - } else { - usb_free_urb(cmdinfo->data_in_urb); - } - } - if (!(cmdinfo->state & COMPLETED_DATA_OUT) && - cmdinfo->data_out_urb) { - if (devinfo->use_streams) { - cmdinfo->state |= DATA_COMPLETES_CMD; - usb_unlink_urb(cmdinfo->data_in_urb); - } else { - usb_free_urb(cmdinfo->data_out_urb); - } - } - if (urb->actual_length < 16) devinfo->uas_sense_old = 1; if (devinfo->uas_sense_old) @@ -264,59 +236,27 @@ static void uas_stat_cmplt(struct urb *urb) dev_err(&urb->dev->dev, "failed submit status urb\n"); } -static void uas_data_out_cmplt(struct urb *urb) -{ - struct scsi_cmnd *cmnd = urb->context; - struct scsi_data_buffer *sdb = scsi_out(cmnd); - struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; - - cmdinfo->state |= COMPLETED_DATA_OUT; - - sdb->resid = sdb->length - urb->actual_length; - usb_free_urb(urb); - - if (cmdinfo->state & DATA_COMPLETES_CMD) - cmnd->scsi_done(cmnd); -} - -static void uas_data_in_cmplt(struct urb *urb) +static void uas_data_cmplt(struct urb *urb) { - struct scsi_cmnd *cmnd = urb->context; - struct scsi_data_buffer *sdb = scsi_in(cmnd); - struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; - - cmdinfo->state |= COMPLETED_DATA_IN; - + struct scsi_data_buffer *sdb = urb->context; sdb->resid = sdb->length - urb->actual_length; usb_free_urb(urb); - - if (cmdinfo->state & DATA_COMPLETES_CMD) - cmnd->scsi_done(cmnd); } static struct urb *uas_alloc_data_urb(struct uas_dev_info *devinfo, gfp_t gfp, - unsigned int pipe, struct scsi_cmnd *cmnd, - enum dma_data_direction dir) + unsigned int pipe, u16 stream_id, + struct scsi_data_buffer *sdb, + enum dma_data_direction dir) { - struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; struct usb_device *udev = devinfo->udev; struct urb *urb = usb_alloc_urb(0, gfp); - struct scsi_data_buffer *sdb; - usb_complete_t complete_fn; - u16 stream_id = cmdinfo->stream; if (!urb) goto out; - if (dir == DMA_FROM_DEVICE) { - sdb = scsi_in(cmnd); - complete_fn = uas_data_in_cmplt; - } else { - sdb = scsi_out(cmnd); - complete_fn = uas_data_out_cmplt; - } - usb_fill_bulk_urb(urb, udev, pipe, NULL, sdb->length, - complete_fn, cmnd); - urb->stream_id = stream_id; + usb_fill_bulk_urb(urb, udev, pipe, NULL, sdb->length, uas_data_cmplt, + sdb); + if (devinfo->use_streams) + urb->stream_id = stream_id; urb->num_sgs = udev->bus->sg_tablesize ? sdb->table.nents : 0; urb->sg = sdb->table.sgl; out: @@ -418,8 +358,8 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd, if (cmdinfo->state & ALLOC_DATA_IN_URB) { cmdinfo->data_in_urb = uas_alloc_data_urb(devinfo, gfp, - devinfo->data_in_pipe, cmnd, - DMA_FROM_DEVICE); + devinfo->data_in_pipe, cmdinfo->stream, + scsi_in(cmnd), DMA_FROM_DEVICE); if (!cmdinfo->data_in_urb) return SCSI_MLQUEUE_DEVICE_BUSY; cmdinfo->state &= ~ALLOC_DATA_IN_URB; @@ -436,8 +376,8 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd, if (cmdinfo->state & ALLOC_DATA_OUT_URB) { cmdinfo->data_out_urb = uas_alloc_data_urb(devinfo, gfp, - devinfo->data_out_pipe, cmnd, - DMA_TO_DEVICE); + devinfo->data_out_pipe, cmdinfo->stream, + scsi_out(cmnd), DMA_TO_DEVICE); if (!cmdinfo->data_out_urb) return SCSI_MLQUEUE_DEVICE_BUSY; cmdinfo->state &= ~ALLOC_DATA_OUT_URB; diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 8f3cbb8dc81..27858f9a20e 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1004,6 +1004,12 @@ UNUSUAL_DEV( 0x07cf, 0x1001, 0x1000, 0x9999, USB_SC_8070, USB_PR_CB, NULL, US_FL_NEED_OVERRIDE | US_FL_FIX_INQUIRY ), +/* Submitted by Oleksandr Chumachenko */ +UNUSUAL_DEV( 0x07cf, 0x1167, 0x0100, 0x0100, + "Casio", + "EX-N1 DigitalCamera", + USB_SC_8070, USB_PR_DEVICE, NULL, 0), + /* Submitted by Hartmut Wahl */ UNUSUAL_DEV( 0x0839, 0x000a, 0x0001, 0x0001, "Samsung", @@ -1509,335 +1515,10 @@ UNUSUAL_DEV( 0x1210, 0x0003, 0x0100, 0x0100, /* Reported by fangxiaozhi * This brings the HUAWEI data card devices into multi-port mode */ -UNUSUAL_DEV( 0x12d1, 0x1001, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1003, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1004, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1401, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1402, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1403, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1404, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1405, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1406, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1407, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1408, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1409, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x140A, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x140B, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x140C, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x140D, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x140E, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x140F, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1410, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1411, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1412, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1413, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1414, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1415, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1416, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1417, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1418, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1419, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x141A, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x141B, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x141C, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x141D, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x141E, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x141F, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1420, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1421, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1422, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1423, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1424, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1425, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1426, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1427, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1428, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1429, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x142A, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x142B, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x142C, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x142D, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x142E, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x142F, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1430, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1431, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1432, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1433, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1434, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1435, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1436, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1437, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1438, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x1439, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x143A, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x143B, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x143C, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x143D, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x143E, 0x0000, 0x0000, - "HUAWEI MOBILE", - "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, - 0), -UNUSUAL_DEV( 0x12d1, 0x143F, 0x0000, 0x0000, +UNUSUAL_VENDOR_INTF(0x12d1, 0x08, 0x06, 0x50, "HUAWEI MOBILE", "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_init, 0), /* Reported by Vilius Bilinkevicius currcon != -1) vc = vc_cons[ops->currcon].d; diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c index 4a89f889852..9f8999223f6 100644 --- a/drivers/video/mxsfb.c +++ b/drivers/video/mxsfb.c @@ -366,7 +366,8 @@ static void mxsfb_disable_controller(struct fb_info *fb_info) loop--; } - writel(VDCTRL4_SYNC_SIGNALS_ON, host->base + LCDC_VDCTRL4 + REG_CLR); + reg = readl(host->base + LCDC_VDCTRL4); + writel(reg & ~VDCTRL4_SYNC_SIGNALS_ON, host->base + LCDC_VDCTRL4); clk_disable_unprepare(host->clk); diff --git a/drivers/video/smscufx.c b/drivers/video/smscufx.c index ccbfef5e828..1e1e2d267f4 100644 --- a/drivers/video/smscufx.c +++ b/drivers/video/smscufx.c @@ -904,7 +904,7 @@ static ssize_t ufx_ops_write(struct fb_info *info, const char __user *buf, result = fb_sys_write(info, buf, count, ppos); if (result > 0) { - int start = max((int)(offset / info->fix.line_length) - 1, 0); + int start = max((int)(offset / info->fix.line_length), 0); int lines = min((u32)((result / info->fix.line_length) + 1), (u32)info->var.yres); diff --git a/drivers/video/udlfb.c b/drivers/video/udlfb.c index a159b63e18b..85d81103c1f 100644 --- a/drivers/video/udlfb.c +++ b/drivers/video/udlfb.c @@ -647,7 +647,7 @@ static ssize_t dlfb_ops_write(struct fb_info *info, const char __user *buf, result = fb_sys_write(info, buf, count, ppos); if (result > 0) { - int start = max((int)(offset / info->fix.line_length) - 1, 0); + int start = max((int)(offset / info->fix.line_length), 0); int lines = min((u32)((result / info->fix.line_length) + 1), (u32)info->var.yres); diff --git a/drivers/video/via/via_clock.c b/drivers/video/via/via_clock.c index af8f26b643c..db1e39277e3 100644 --- a/drivers/video/via/via_clock.c +++ b/drivers/video/via/via_clock.c @@ -25,6 +25,7 @@ #include #include +#include #include "via_clock.h" #include "global.h" #include "debug.h" @@ -289,6 +290,10 @@ static void dummy_set_pll(struct via_pll_config config) printk(KERN_INFO "Using undocumented set PLL.\n%s", via_slap); } +static void noop_set_clock_state(u8 state) +{ +} + void via_clock_init(struct via_clock *clock, int gfx_chip) { switch (gfx_chip) { @@ -346,4 +351,18 @@ void via_clock_init(struct via_clock *clock, int gfx_chip) break; } + + if (machine_is_olpc()) { + /* The OLPC XO-1.5 cannot suspend/resume reliably if the + * IGA1/IGA2 clocks are set as on or off (memory rot + * occasionally happens during suspend under such + * configurations). + * + * The only known stable scenario is to leave this bits as-is, + * which in their default states are documented to enable the + * clock only when it is needed. + */ + clock->set_primary_clock_state = noop_set_clock_state; + clock->set_secondary_clock_state = noop_set_clock_state; + } } diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index 7e6fd751701..1391c7a0759 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c @@ -132,6 +132,13 @@ static int vring_add_indirect(struct vring_virtqueue *vq, unsigned head; int i; + /* + * We require lowmem mappings for the descriptors because + * otherwise virt_to_phys will give us bogus addresses in the + * virtqueue. + */ + gfp &= ~(__GFP_HIGHMEM | __GFP_HIGH); + desc = kmalloc((out + in) * sizeof(struct vring_desc), gfp); if (!desc) return -ENOMEM; diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c index 9f13b897fd6..6019929a54a 100644 --- a/drivers/watchdog/hpwdt.c +++ b/drivers/watchdog/hpwdt.c @@ -806,6 +806,9 @@ static int __devinit hpwdt_init_one(struct pci_dev *dev, hpwdt_timer_reg = pci_mem_addr + 0x70; hpwdt_timer_con = pci_mem_addr + 0x72; + /* Make sure that timer is disabled until /dev/watchdog is opened */ + hpwdt_stop(); + /* Make sure that we have a valid soft_margin */ if (hpwdt_change_timer(soft_margin)) hpwdt_change_timer(DEFAULT_MARGIN); diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 6908e4ce2a0..26c47a4c426 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c @@ -1365,8 +1365,8 @@ void xen_evtchn_do_upcall(struct pt_regs *regs) { struct pt_regs *old_regs = set_irq_regs(regs); - exit_idle(); irq_enter(); + exit_idle(); __xen_evtchn_do_upcall(); diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c index 1ffd03bf8e1..9a113b714b4 100644 --- a/drivers/xen/gntdev.c +++ b/drivers/xen/gntdev.c @@ -105,6 +105,21 @@ static void gntdev_print_maps(struct gntdev_priv *priv, #endif } +static void gntdev_free_map(struct grant_map *map) +{ + if (map == NULL) + return; + + if (map->pages) + free_xenballooned_pages(map->count, map->pages); + kfree(map->pages); + kfree(map->grants); + kfree(map->map_ops); + kfree(map->unmap_ops); + kfree(map->kmap_ops); + kfree(map); +} + static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count) { struct grant_map *add; @@ -142,12 +157,7 @@ static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count) return add; err: - kfree(add->pages); - kfree(add->grants); - kfree(add->map_ops); - kfree(add->unmap_ops); - kfree(add->kmap_ops); - kfree(add); + gntdev_free_map(add); return NULL; } @@ -198,17 +208,9 @@ static void gntdev_put_map(struct grant_map *map) evtchn_put(map->notify.event); } - if (map->pages) { - if (!use_ptemod) - unmap_grant_pages(map, 0, map->count); - - free_xenballooned_pages(map->count, map->pages); - } - kfree(map->pages); - kfree(map->grants); - kfree(map->map_ops); - kfree(map->unmap_ops); - kfree(map); + if (map->pages && !use_ptemod) + unmap_grant_pages(map, 0, map->count); + gntdev_free_map(map); } /* ------------------------------------------------------------------ */ @@ -314,8 +316,9 @@ static int __unmap_grant_pages(struct grant_map *map, int offset, int pages) } } - err = gnttab_unmap_refs(map->unmap_ops + offset, map->pages + offset, - pages, true); + err = gnttab_unmap_refs(map->unmap_ops + offset, + use_ptemod ? map->kmap_ops + offset : NULL, map->pages + offset, + pages); if (err) return err; diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c index f100ce20b16..7e34beed9ea 100644 --- a/drivers/xen/grant-table.c +++ b/drivers/xen/grant-table.c @@ -53,10 +53,6 @@ /* External tools reserve first few grant table entries. */ #define NR_RESERVED_ENTRIES 8 #define GNTTAB_LIST_END 0xffffffff -#define GREFS_PER_GRANT_FRAME \ -(grant_table_version == 1 ? \ -(PAGE_SIZE / sizeof(struct grant_entry_v1)) : \ -(PAGE_SIZE / sizeof(union grant_entry_v2))) static grant_ref_t **gnttab_list; static unsigned int nr_grant_frames; @@ -151,6 +147,7 @@ static struct gnttab_ops *gnttab_interface; static grant_status_t *grstatus; static int grant_table_version; +static int grefs_per_grant_frame; static struct gnttab_free_callback *gnttab_free_callback_list; @@ -679,12 +676,14 @@ static int grow_gnttab_list(unsigned int more_frames) unsigned int new_nr_grant_frames, extra_entries, i; unsigned int nr_glist_frames, new_nr_glist_frames; + BUG_ON(grefs_per_grant_frame == 0); + new_nr_grant_frames = nr_grant_frames + more_frames; - extra_entries = more_frames * GREFS_PER_GRANT_FRAME; + extra_entries = more_frames * grefs_per_grant_frame; - nr_glist_frames = (nr_grant_frames * GREFS_PER_GRANT_FRAME + RPP - 1) / RPP; + nr_glist_frames = (nr_grant_frames * grefs_per_grant_frame + RPP - 1) / RPP; new_nr_glist_frames = - (new_nr_grant_frames * GREFS_PER_GRANT_FRAME + RPP - 1) / RPP; + (new_nr_grant_frames * grefs_per_grant_frame + RPP - 1) / RPP; for (i = nr_glist_frames; i < new_nr_glist_frames; i++) { gnttab_list[i] = (grant_ref_t *)__get_free_page(GFP_ATOMIC); if (!gnttab_list[i]) @@ -692,12 +691,12 @@ static int grow_gnttab_list(unsigned int more_frames) } - for (i = GREFS_PER_GRANT_FRAME * nr_grant_frames; - i < GREFS_PER_GRANT_FRAME * new_nr_grant_frames - 1; i++) + for (i = grefs_per_grant_frame * nr_grant_frames; + i < grefs_per_grant_frame * new_nr_grant_frames - 1; i++) gnttab_entry(i) = i + 1; gnttab_entry(i) = gnttab_free_head; - gnttab_free_head = GREFS_PER_GRANT_FRAME * nr_grant_frames; + gnttab_free_head = grefs_per_grant_frame * nr_grant_frames; gnttab_free_count += extra_entries; nr_grant_frames = new_nr_grant_frames; @@ -774,7 +773,8 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops, EXPORT_SYMBOL_GPL(gnttab_map_refs); int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops, - struct page **pages, unsigned int count, bool clear_pte) + struct gnttab_map_grant_ref *kmap_ops, + struct page **pages, unsigned int count) { int i, ret; @@ -786,7 +786,8 @@ int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops, return ret; for (i = 0; i < count; i++) { - ret = m2p_remove_override(pages[i], clear_pte); + ret = m2p_remove_override(pages[i], kmap_ops ? + &kmap_ops[i] : NULL); if (ret) return ret; } @@ -797,7 +798,8 @@ EXPORT_SYMBOL_GPL(gnttab_unmap_refs); static unsigned nr_status_frames(unsigned nr_grant_frames) { - return (nr_grant_frames * GREFS_PER_GRANT_FRAME + SPP - 1) / SPP; + BUG_ON(grefs_per_grant_frame == 0); + return (nr_grant_frames * grefs_per_grant_frame + SPP - 1) / SPP; } static int gnttab_map_frames_v1(unsigned long *frames, unsigned int nr_gframes) @@ -955,6 +957,7 @@ static void gnttab_request_version(void) rc = HYPERVISOR_grant_table_op(GNTTABOP_set_version, &gsv, 1); if (rc == 0 && gsv.version == 2) { grant_table_version = 2; + grefs_per_grant_frame = PAGE_SIZE / sizeof(union grant_entry_v2); gnttab_interface = &gnttab_v2_ops; } else if (grant_table_version == 2) { /* @@ -967,17 +970,17 @@ static void gnttab_request_version(void) panic("we need grant tables version 2, but only version 1 is available"); } else { grant_table_version = 1; + grefs_per_grant_frame = PAGE_SIZE / sizeof(struct grant_entry_v1); gnttab_interface = &gnttab_v1_ops; } printk(KERN_INFO "Grant tables using version %d layout.\n", grant_table_version); } -int gnttab_resume(void) +static int gnttab_setup(void) { unsigned int max_nr_gframes; - gnttab_request_version(); max_nr_gframes = gnttab_max_grant_frames(); if (max_nr_gframes < nr_grant_frames) return -ENOSYS; @@ -1000,6 +1003,12 @@ int gnttab_resume(void) return 0; } +int gnttab_resume(void) +{ + gnttab_request_version(); + return gnttab_setup(); +} + int gnttab_suspend(void) { gnttab_interface->unmap_frames(); @@ -1011,9 +1020,10 @@ static int gnttab_expand(unsigned int req_entries) int rc; unsigned int cur, extra; + BUG_ON(grefs_per_grant_frame == 0); cur = nr_grant_frames; - extra = ((req_entries + (GREFS_PER_GRANT_FRAME-1)) / - GREFS_PER_GRANT_FRAME); + extra = ((req_entries + (grefs_per_grant_frame-1)) / + grefs_per_grant_frame); if (cur + extra > gnttab_max_grant_frames()) return -ENOSPC; @@ -1031,21 +1041,23 @@ int gnttab_init(void) unsigned int nr_init_grefs; int ret; + gnttab_request_version(); nr_grant_frames = 1; boot_max_nr_grant_frames = __max_nr_grant_frames(); /* Determine the maximum number of frames required for the * grant reference free list on the current hypervisor. */ + BUG_ON(grefs_per_grant_frame == 0); max_nr_glist_frames = (boot_max_nr_grant_frames * - GREFS_PER_GRANT_FRAME / RPP); + grefs_per_grant_frame / RPP); gnttab_list = kmalloc(max_nr_glist_frames * sizeof(grant_ref_t *), GFP_KERNEL); if (gnttab_list == NULL) return -ENOMEM; - nr_glist_frames = (nr_grant_frames * GREFS_PER_GRANT_FRAME + RPP - 1) / RPP; + nr_glist_frames = (nr_grant_frames * grefs_per_grant_frame + RPP - 1) / RPP; for (i = 0; i < nr_glist_frames; i++) { gnttab_list[i] = (grant_ref_t *)__get_free_page(GFP_KERNEL); if (gnttab_list[i] == NULL) { @@ -1054,12 +1066,12 @@ int gnttab_init(void) } } - if (gnttab_resume() < 0) { + if (gnttab_setup() < 0) { ret = -ENODEV; goto ini_nomem; } - nr_init_grefs = nr_grant_frames * GREFS_PER_GRANT_FRAME; + nr_init_grefs = nr_grant_frames * grefs_per_grant_frame; for (i = NR_RESERVED_ENTRIES; i < nr_init_grefs - 1; i++) gnttab_entry(i) = i + 1; diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c index 1afb4fba11b..4d519488d30 100644 --- a/drivers/xen/swiotlb-xen.c +++ b/drivers/xen/swiotlb-xen.c @@ -232,7 +232,7 @@ xen_swiotlb_alloc_coherent(struct device *hwdev, size_t size, return ret; if (hwdev && hwdev->coherent_dma_mask) - dma_mask = hwdev->coherent_dma_mask; + dma_mask = dma_alloc_coherent_mask(hwdev, flags); phys = virt_to_phys(ret); dev_addr = xen_phys_to_bus(phys); diff --git a/drivers/xen/xen-pciback/pci_stub.c b/drivers/xen/xen-pciback/pci_stub.c index 097e536e867..03342728bf2 100644 --- a/drivers/xen/xen-pciback/pci_stub.c +++ b/drivers/xen/xen-pciback/pci_stub.c @@ -353,16 +353,16 @@ static int __devinit pcistub_init_device(struct pci_dev *dev) if (err) goto config_release; - dev_dbg(&dev->dev, "reseting (FLR, D3, etc) the device\n"); - __pci_reset_function_locked(dev); - /* We need the device active to save the state. */ dev_dbg(&dev->dev, "save state of device\n"); pci_save_state(dev); dev_data->pci_saved_state = pci_store_saved_state(dev); if (!dev_data->pci_saved_state) dev_err(&dev->dev, "Could not store PCI conf saved state!\n"); - + else { + dev_dbg(&dev->dev, "reseting (FLR, D3, etc) the device\n"); + __pci_reset_function_locked(dev); + } /* Now disable the device (this also ensures some private device * data is setup before we export) */ diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index 75e5f1c8e02..8c4292f89ee 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c @@ -392,10 +392,12 @@ static struct vfsmount *autofs4_d_automount(struct path *path) ino->flags |= AUTOFS_INF_PENDING; spin_unlock(&sbi->fs_lock); status = autofs4_mount_wait(dentry); - if (status) - return ERR_PTR(status); spin_lock(&sbi->fs_lock); ino->flags &= ~AUTOFS_INF_PENDING; + if (status) { + spin_unlock(&sbi->fs_lock); + return ERR_PTR(status); + } } done: if (!(ino->flags & AUTOFS_INF_EXPIRING)) { diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 16f73541707..a009b9e322a 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -1698,30 +1698,19 @@ static int elf_note_info_init(struct elf_note_info *info) return 0; info->psinfo = kmalloc(sizeof(*info->psinfo), GFP_KERNEL); if (!info->psinfo) - goto notes_free; + return 0; info->prstatus = kmalloc(sizeof(*info->prstatus), GFP_KERNEL); if (!info->prstatus) - goto psinfo_free; + return 0; info->fpu = kmalloc(sizeof(*info->fpu), GFP_KERNEL); if (!info->fpu) - goto prstatus_free; + return 0; #ifdef ELF_CORE_COPY_XFPREGS info->xfpu = kmalloc(sizeof(*info->xfpu), GFP_KERNEL); if (!info->xfpu) - goto fpu_free; + return 0; #endif return 1; -#ifdef ELF_CORE_COPY_XFPREGS - fpu_free: - kfree(info->fpu); -#endif - prstatus_free: - kfree(info->prstatus); - psinfo_free: - kfree(info->psinfo); - notes_free: - kfree(info->notes); - return 0; } static int fill_note_info(struct elfhdr *elf, int phdrs, diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c index 613aa061823..e1724392d05 100644 --- a/fs/binfmt_misc.c +++ b/fs/binfmt_misc.c @@ -176,7 +176,10 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs) goto _error; bprm->argc ++; - bprm->interp = iname; /* for binfmt_script */ + /* Update interp in case binfmt_script needs it. */ + retval = bprm_change_interp(iname, bprm); + if (retval < 0) + goto _error; interp_file = open_exec (iname); retval = PTR_ERR (interp_file); diff --git a/fs/binfmt_script.c b/fs/binfmt_script.c index d3b8c1f6315..df49d486b0c 100644 --- a/fs/binfmt_script.c +++ b/fs/binfmt_script.c @@ -82,7 +82,9 @@ static int load_script(struct linux_binprm *bprm,struct pt_regs *regs) retval = copy_strings_kernel(1, &i_name, bprm); if (retval) return retval; bprm->argc++; - bprm->interp = interp; + retval = bprm_change_interp(interp, bprm); + if (retval < 0) + return retval; /* * OK, now restart the process with the interpreter's dentry. diff --git a/fs/btrfs/async-thread.c b/fs/btrfs/async-thread.c index 42704149b72..58b7d14b08e 100644 --- a/fs/btrfs/async-thread.c +++ b/fs/btrfs/async-thread.c @@ -206,10 +206,17 @@ static noinline void run_ordered_completions(struct btrfs_workers *workers, work->ordered_func(work); - /* now take the lock again and call the freeing code */ + /* now take the lock again and drop our item from the list */ spin_lock(&workers->order_lock); list_del(&work->order_list); + spin_unlock(&workers->order_lock); + + /* + * we don't want to call the ordered free functions + * with the lock held though + */ work->ordered_free(work); + spin_lock(&workers->order_lock); } spin_unlock(&workers->order_lock); diff --git a/fs/buffer.c b/fs/buffer.c index badcbc08ac1..347c913e668 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -914,7 +914,7 @@ link_dev_buffers(struct page *page, struct buffer_head *head) /* * Initialise the state of a blockdev page's buffers. */ -static void +static sector_t init_page_buffers(struct page *page, struct block_device *bdev, sector_t block, int size) { @@ -936,33 +936,41 @@ init_page_buffers(struct page *page, struct block_device *bdev, block++; bh = bh->b_this_page; } while (bh != head); + + /* + * Caller needs to validate requested block against end of device. + */ + return end_block; } /* * Create the page-cache page that contains the requested block. * - * This is user purely for blockdev mappings. + * This is used purely for blockdev mappings. */ -static struct page * +static int grow_dev_page(struct block_device *bdev, sector_t block, - pgoff_t index, int size) + pgoff_t index, int size, int sizebits) { struct inode *inode = bdev->bd_inode; struct page *page; struct buffer_head *bh; + sector_t end_block; + int ret = 0; /* Will call free_more_memory() */ page = find_or_create_page(inode->i_mapping, index, (mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS)|__GFP_MOVABLE); if (!page) - return NULL; + return ret; BUG_ON(!PageLocked(page)); if (page_has_buffers(page)) { bh = page_buffers(page); if (bh->b_size == size) { - init_page_buffers(page, bdev, block, size); - return page; + end_block = init_page_buffers(page, bdev, + index << sizebits, size); + goto done; } if (!try_to_free_buffers(page)) goto failed; @@ -982,14 +990,14 @@ grow_dev_page(struct block_device *bdev, sector_t block, */ spin_lock(&inode->i_mapping->private_lock); link_dev_buffers(page, bh); - init_page_buffers(page, bdev, block, size); + end_block = init_page_buffers(page, bdev, index << sizebits, size); spin_unlock(&inode->i_mapping->private_lock); - return page; - +done: + ret = (block < end_block) ? 1 : -ENXIO; failed: unlock_page(page); page_cache_release(page); - return NULL; + return ret; } /* @@ -999,7 +1007,6 @@ grow_dev_page(struct block_device *bdev, sector_t block, static int grow_buffers(struct block_device *bdev, sector_t block, int size) { - struct page *page; pgoff_t index; int sizebits; @@ -1023,22 +1030,14 @@ grow_buffers(struct block_device *bdev, sector_t block, int size) bdevname(bdev, b)); return -EIO; } - block = index << sizebits; + /* Create a page with the proper size buffers.. */ - page = grow_dev_page(bdev, block, index, size); - if (!page) - return 0; - unlock_page(page); - page_cache_release(page); - return 1; + return grow_dev_page(bdev, block, index, size, sizebits); } static struct buffer_head * __getblk_slow(struct block_device *bdev, sector_t block, int size) { - int ret; - struct buffer_head *bh; - /* Size must be multiple of hard sectorsize */ if (unlikely(size & (bdev_logical_block_size(bdev)-1) || (size < 512 || size > PAGE_SIZE))) { @@ -1051,21 +1050,20 @@ __getblk_slow(struct block_device *bdev, sector_t block, int size) return NULL; } -retry: - bh = __find_get_block(bdev, block, size); - if (bh) - return bh; + for (;;) { + struct buffer_head *bh; + int ret; - ret = grow_buffers(bdev, block, size); - if (ret == 0) { - free_more_memory(); - goto retry; - } else if (ret > 0) { bh = __find_get_block(bdev, block, size); if (bh) return bh; + + ret = grow_buffers(bdev, block, size); + if (ret < 0) + return NULL; + if (ret == 0) + free_more_memory(); } - return NULL; } /* @@ -1321,10 +1319,6 @@ EXPORT_SYMBOL(__find_get_block); * which corresponds to the passed block_device, block and size. The * returned buffer has its reference count incremented. * - * __getblk() cannot fail - it just keeps trying. If you pass it an - * illegal block number, __getblk() will happily return a buffer_head - * which represents the non-existent block. Very weird. - * * __getblk() will lock up the machine if grow_dev_page's try_to_free_buffers() * attempt is failing. FIXME, perhaps? */ diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index 173b1d22e59..bb01881cb1f 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c @@ -54,7 +54,12 @@ (CONGESTION_ON_THRESH(congestion_kb) - \ (CONGESTION_ON_THRESH(congestion_kb) >> 2)) - +static inline struct ceph_snap_context *page_snap_context(struct page *page) +{ + if (PagePrivate(page)) + return (void *)page->private; + return NULL; +} /* * Dirty a page. Optimistically adjust accounting, on the assumption @@ -142,10 +147,9 @@ static void ceph_invalidatepage(struct page *page, unsigned long offset) { struct inode *inode; struct ceph_inode_info *ci; - struct ceph_snap_context *snapc = (void *)page->private; + struct ceph_snap_context *snapc = page_snap_context(page); BUG_ON(!PageLocked(page)); - BUG_ON(!page->private); BUG_ON(!PagePrivate(page)); BUG_ON(!page->mapping); @@ -182,7 +186,6 @@ static int ceph_releasepage(struct page *page, gfp_t g) struct inode *inode = page->mapping ? page->mapping->host : NULL; dout("%p releasepage %p idx %lu\n", inode, page, page->index); WARN_ON(PageDirty(page)); - WARN_ON(page->private); WARN_ON(PagePrivate(page)); return 0; } @@ -202,7 +205,7 @@ static int readpage_nounlock(struct file *filp, struct page *page) dout("readpage inode %p file %p page %p index %lu\n", inode, filp, page, page->index); err = ceph_osdc_readpages(osdc, ceph_vino(inode), &ci->i_layout, - page->index << PAGE_CACHE_SHIFT, &len, + (u64) page_offset(page), &len, ci->i_truncate_seq, ci->i_truncate_size, &page, 1, 0); if (err == -ENOENT) @@ -264,6 +267,14 @@ static void finish_read(struct ceph_osd_request *req, struct ceph_msg *msg) kfree(req->r_pages); } +static void ceph_unlock_page_vector(struct page **pages, int num_pages) +{ + int i; + + for (i = 0; i < num_pages; i++) + unlock_page(pages[i]); +} + /* * start an async read(ahead) operation. return nr_pages we submitted * a read for on success, or negative error code. @@ -283,7 +294,7 @@ static int start_read(struct inode *inode, struct list_head *page_list, int max) int nr_pages = 0; int ret; - off = page->index << PAGE_CACHE_SHIFT; + off = (u64) page_offset(page); /* count pages */ next_index = page->index; @@ -305,8 +316,8 @@ static int start_read(struct inode *inode, struct list_head *page_list, int max) NULL, 0, ci->i_truncate_seq, ci->i_truncate_size, NULL, false, 1, 0); - if (!req) - return -ENOMEM; + if (IS_ERR(req)) + return PTR_ERR(req); /* build page vector */ nr_pages = len >> PAGE_CACHE_SHIFT; @@ -344,6 +355,7 @@ static int start_read(struct inode *inode, struct list_head *page_list, int max) return nr_pages; out_pages: + ceph_unlock_page_vector(pages, nr_pages); ceph_release_page_vector(pages, nr_pages); out: ceph_osdc_put_request(req); @@ -423,7 +435,7 @@ static int writepage_nounlock(struct page *page, struct writeback_control *wbc) struct ceph_inode_info *ci; struct ceph_fs_client *fsc; struct ceph_osd_client *osdc; - loff_t page_off = page->index << PAGE_CACHE_SHIFT; + loff_t page_off = page_offset(page); int len = PAGE_CACHE_SIZE; loff_t i_size; int err = 0; @@ -443,7 +455,7 @@ static int writepage_nounlock(struct page *page, struct writeback_control *wbc) osdc = &fsc->client->osdc; /* verify this is a writeable snap context */ - snapc = (void *)page->private; + snapc = page_snap_context(page); if (snapc == NULL) { dout("writepage %p page %p not dirty?\n", inode, page); goto out; @@ -451,7 +463,7 @@ static int writepage_nounlock(struct page *page, struct writeback_control *wbc) oldest = get_oldest_context(inode, &snap_size); if (snapc->seq > oldest->seq) { dout("writepage %p page %p snapc %p not writeable - noop\n", - inode, page, (void *)page->private); + inode, page, snapc); /* we should only noop if called by kswapd */ WARN_ON((current->flags & PF_MEMALLOC) == 0); ceph_put_snap_context(oldest); @@ -591,7 +603,7 @@ static void writepages_finish(struct ceph_osd_request *req, clear_bdi_congested(&fsc->backing_dev_info, BLK_RW_ASYNC); - ceph_put_snap_context((void *)page->private); + ceph_put_snap_context(page_snap_context(page)); page->private = 0; ClearPagePrivate(page); dout("unlocking %d %p\n", i, page); @@ -795,7 +807,7 @@ static int ceph_writepages_start(struct address_space *mapping, } /* only if matching snap context */ - pgsnapc = (void *)page->private; + pgsnapc = page_snap_context(page); if (pgsnapc->seq > snapc->seq) { dout("page snapc %p %lld > oldest %p %lld\n", pgsnapc, pgsnapc->seq, snapc, snapc->seq); @@ -814,8 +826,7 @@ static int ceph_writepages_start(struct address_space *mapping, /* ok */ if (locked_pages == 0) { /* prepare async write request */ - offset = (unsigned long long)page->index - << PAGE_CACHE_SHIFT; + offset = (u64) page_offset(page); len = wsize; req = ceph_osdc_new_request(&fsc->client->osdc, &ci->i_layout, @@ -829,8 +840,8 @@ static int ceph_writepages_start(struct address_space *mapping, ci->i_truncate_size, &inode->i_mtime, true, 1, 0); - if (!req) { - rc = -ENOMEM; + if (IS_ERR(req)) { + rc = PTR_ERR(req); unlock_page(page); break; } @@ -984,7 +995,7 @@ static int ceph_update_writeable_page(struct file *file, BUG_ON(!ci->i_snap_realm); down_read(&mdsc->snap_rwsem); BUG_ON(!ci->i_snap_realm->cached_context); - snapc = (void *)page->private; + snapc = page_snap_context(page); if (snapc && snapc != ci->i_head_snapc) { /* * this page is already dirty in another (older) snap @@ -1177,7 +1188,7 @@ static int ceph_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) struct inode *inode = vma->vm_file->f_dentry->d_inode; struct page *page = vmf->page; struct ceph_mds_client *mdsc = ceph_inode_to_client(inode)->mdsc; - loff_t off = page->index << PAGE_CACHE_SHIFT; + loff_t off = page_offset(page); loff_t size, len; int ret; diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index 620daad201d..e7d40776f58 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c @@ -1349,11 +1349,15 @@ int __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask) if (!ci->i_head_snapc) ci->i_head_snapc = ceph_get_snap_context( ci->i_snap_realm->cached_context); - dout(" inode %p now dirty snapc %p\n", &ci->vfs_inode, - ci->i_head_snapc); + dout(" inode %p now dirty snapc %p auth cap %p\n", + &ci->vfs_inode, ci->i_head_snapc, ci->i_auth_cap); BUG_ON(!list_empty(&ci->i_dirty_item)); spin_lock(&mdsc->cap_dirty_lock); - list_add(&ci->i_dirty_item, &mdsc->cap_dirty); + if (ci->i_auth_cap) + list_add(&ci->i_dirty_item, &mdsc->cap_dirty); + else + list_add(&ci->i_dirty_item, + &mdsc->cap_dirty_migrating); spin_unlock(&mdsc->cap_dirty_lock); if (ci->i_flushing_caps == 0) { ihold(inode); @@ -2388,7 +2392,7 @@ static void handle_cap_grant(struct inode *inode, struct ceph_mds_caps *grant, &atime); /* max size increase? */ - if (max_size != ci->i_max_size) { + if (ci->i_auth_cap == cap && max_size != ci->i_max_size) { dout("max_size %lld -> %llu\n", ci->i_max_size, max_size); ci->i_max_size = max_size; if (max_size >= ci->i_wanted_max_size) { @@ -2745,6 +2749,7 @@ static void handle_cap_import(struct ceph_mds_client *mdsc, /* make sure we re-request max_size, if necessary */ spin_lock(&ci->i_ceph_lock); + ci->i_wanted_max_size = 0; /* reset */ ci->i_requested_max_size = 0; spin_unlock(&ci->i_ceph_lock); } @@ -2840,8 +2845,6 @@ void ceph_handle_caps(struct ceph_mds_session *session, case CEPH_CAP_OP_IMPORT: handle_cap_import(mdsc, inode, h, session, snaptrace, snaptrace_len); - ceph_check_caps(ceph_inode(inode), 0, session); - goto done_unlocked; } /* the rest require a cap */ @@ -2858,6 +2861,7 @@ void ceph_handle_caps(struct ceph_mds_session *session, switch (op) { case CEPH_CAP_OP_REVOKE: case CEPH_CAP_OP_GRANT: + case CEPH_CAP_OP_IMPORT: handle_cap_grant(inode, h, session, cap, msg->middle); goto done_unlocked; diff --git a/fs/ceph/debugfs.c b/fs/ceph/debugfs.c index fb962efdace..6d59006bfa2 100644 --- a/fs/ceph/debugfs.c +++ b/fs/ceph/debugfs.c @@ -201,6 +201,7 @@ int ceph_fs_debugfs_init(struct ceph_fs_client *fsc) int err = -ENOMEM; dout("ceph_fs_debugfs_init\n"); + BUG_ON(!fsc->client->debugfs_dir); fsc->debugfs_congestion_kb = debugfs_create_file("writeback_congestion_kb", 0600, diff --git a/fs/ceph/export.c b/fs/ceph/export.c index fbb2a643ef1..4098ccf8cb9 100644 --- a/fs/ceph/export.c +++ b/fs/ceph/export.c @@ -89,7 +89,7 @@ static int ceph_encode_fh(struct dentry *dentry, u32 *rawfh, int *max_len, * FIXME: we should try harder by querying the mds for the ino. */ static struct dentry *__fh_to_dentry(struct super_block *sb, - struct ceph_nfs_fh *fh) + struct ceph_nfs_fh *fh, int fh_len) { struct ceph_mds_client *mdsc = ceph_sb_to_client(sb)->mdsc; struct inode *inode; @@ -97,6 +97,9 @@ static struct dentry *__fh_to_dentry(struct super_block *sb, struct ceph_vino vino; int err; + if (fh_len < sizeof(*fh) / 4) + return ERR_PTR(-ESTALE); + dout("__fh_to_dentry %llx\n", fh->ino); vino.ino = fh->ino; vino.snap = CEPH_NOSNAP; @@ -140,7 +143,7 @@ static struct dentry *__fh_to_dentry(struct super_block *sb, * convert connectable fh to dentry */ static struct dentry *__cfh_to_dentry(struct super_block *sb, - struct ceph_nfs_confh *cfh) + struct ceph_nfs_confh *cfh, int fh_len) { struct ceph_mds_client *mdsc = ceph_sb_to_client(sb)->mdsc; struct inode *inode; @@ -148,6 +151,9 @@ static struct dentry *__cfh_to_dentry(struct super_block *sb, struct ceph_vino vino; int err; + if (fh_len < sizeof(*cfh) / 4) + return ERR_PTR(-ESTALE); + dout("__cfh_to_dentry %llx (%llx/%x)\n", cfh->ino, cfh->parent_ino, cfh->parent_name_hash); @@ -197,9 +203,11 @@ static struct dentry *ceph_fh_to_dentry(struct super_block *sb, struct fid *fid, int fh_len, int fh_type) { if (fh_type == 1) - return __fh_to_dentry(sb, (struct ceph_nfs_fh *)fid->raw); + return __fh_to_dentry(sb, (struct ceph_nfs_fh *)fid->raw, + fh_len); else - return __cfh_to_dentry(sb, (struct ceph_nfs_confh *)fid->raw); + return __cfh_to_dentry(sb, (struct ceph_nfs_confh *)fid->raw, + fh_len); } /* @@ -220,6 +228,8 @@ static struct dentry *ceph_fh_to_parent(struct super_block *sb, if (fh_type == 1) return ERR_PTR(-ESTALE); + if (fh_len < sizeof(*cfh) / 4) + return ERR_PTR(-ESTALE); pr_debug("fh_to_parent %llx/%d\n", cfh->parent_ino, cfh->parent_name_hash); diff --git a/fs/ceph/file.c b/fs/ceph/file.c index ed72428d9c7..9ce3a4bd4d1 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c @@ -529,8 +529,8 @@ static ssize_t ceph_sync_write(struct file *file, const char __user *data, do_sync, ci->i_truncate_seq, ci->i_truncate_size, &mtime, false, 2, page_align); - if (!req) - return -ENOMEM; + if (IS_ERR(req)) + return PTR_ERR(req); if (file->f_flags & O_DIRECT) { pages = ceph_get_direct_page_vector(data, num_pages, false); diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 9fff9f3b17e..81613bced19 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -992,11 +992,15 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req, if (rinfo->head->is_dentry) { struct inode *dir = req->r_locked_dir; - err = fill_inode(dir, &rinfo->diri, rinfo->dirfrag, - session, req->r_request_started, -1, - &req->r_caps_reservation); - if (err < 0) - return err; + if (dir) { + err = fill_inode(dir, &rinfo->diri, rinfo->dirfrag, + session, req->r_request_started, -1, + &req->r_caps_reservation); + if (err < 0) + return err; + } else { + WARN_ON_ONCE(1); + } } /* @@ -1004,6 +1008,7 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req, * will have trouble splicing in the virtual snapdir later */ if (rinfo->head->is_dentry && !req->r_aborted && + req->r_locked_dir && (rinfo->head->is_target || strncmp(req->r_dentry->d_name.name, fsc->mount_options->snapdir_name, req->r_dentry->d_name.len))) { @@ -1461,7 +1466,7 @@ void __ceph_do_pending_vmtruncate(struct inode *inode) { struct ceph_inode_info *ci = ceph_inode(inode); u64 to; - int wrbuffer_refs, wake = 0; + int wrbuffer_refs, finish = 0; retry: spin_lock(&ci->i_ceph_lock); @@ -1493,15 +1498,18 @@ void __ceph_do_pending_vmtruncate(struct inode *inode) truncate_inode_pages(inode->i_mapping, to); spin_lock(&ci->i_ceph_lock); - ci->i_truncate_pending--; - if (ci->i_truncate_pending == 0) - wake = 1; + if (to == ci->i_truncate_size) { + ci->i_truncate_pending = 0; + finish = 1; + } spin_unlock(&ci->i_ceph_lock); + if (!finish) + goto retry; if (wrbuffer_refs == 0) ceph_check_caps(ci, CHECK_CAPS_AUTHONLY, NULL); - if (wake) - wake_up_all(&ci->i_cap_wq); + + wake_up_all(&ci->i_cap_wq); } diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 89971e137aa..3fd08ad5c47 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -334,10 +334,10 @@ void ceph_put_mds_session(struct ceph_mds_session *s) dout("mdsc put_session %p %d -> %d\n", s, atomic_read(&s->s_ref), atomic_read(&s->s_ref)-1); if (atomic_dec_and_test(&s->s_ref)) { - if (s->s_authorizer) + if (s->s_auth.authorizer) s->s_mdsc->fsc->client->monc.auth->ops->destroy_authorizer( s->s_mdsc->fsc->client->monc.auth, - s->s_authorizer); + s->s_auth.authorizer); kfree(s); } } @@ -394,11 +394,7 @@ static struct ceph_mds_session *register_session(struct ceph_mds_client *mdsc, s->s_seq = 0; mutex_init(&s->s_mutex); - ceph_con_init(mdsc->fsc->client->msgr, &s->s_con); - s->s_con.private = s; - s->s_con.ops = &mds_con_ops; - s->s_con.peer_name.type = CEPH_ENTITY_TYPE_MDS; - s->s_con.peer_name.num = cpu_to_le64(mds); + ceph_con_init(&s->s_con, s, &mds_con_ops, &mdsc->fsc->client->msgr); spin_lock_init(&s->s_gen_ttl_lock); s->s_cap_gen = 0; @@ -440,7 +436,8 @@ static struct ceph_mds_session *register_session(struct ceph_mds_client *mdsc, mdsc->sessions[mds] = s; atomic_inc(&s->s_ref); /* one ref to sessions[], one to caller */ - ceph_con_open(&s->s_con, ceph_mdsmap_get_addr(mdsc->mdsmap, mds)); + ceph_con_open(&s->s_con, CEPH_ENTITY_TYPE_MDS, mds, + ceph_mdsmap_get_addr(mdsc->mdsmap, mds)); return s; @@ -1889,9 +1886,14 @@ static int __do_request(struct ceph_mds_client *mdsc, static void __wake_requests(struct ceph_mds_client *mdsc, struct list_head *head) { - struct ceph_mds_request *req, *nreq; + struct ceph_mds_request *req; + LIST_HEAD(tmp_list); + + list_splice_init(head, &tmp_list); - list_for_each_entry_safe(req, nreq, head, r_wait) { + while (!list_empty(&tmp_list)) { + req = list_entry(tmp_list.next, + struct ceph_mds_request, r_wait); list_del_init(&req->r_wait); __do_request(mdsc, req); } @@ -2531,7 +2533,9 @@ static void send_mds_reconnect(struct ceph_mds_client *mdsc, session->s_state = CEPH_MDS_SESSION_RECONNECTING; session->s_seq = 0; + ceph_con_close(&session->s_con); ceph_con_open(&session->s_con, + CEPH_ENTITY_TYPE_MDS, mds, ceph_mdsmap_get_addr(mdsc->mdsmap, mds)); /* replay unsafe requests */ @@ -2636,7 +2640,8 @@ static void check_new_map(struct ceph_mds_client *mdsc, ceph_mdsmap_is_laggy(newmap, i) ? " (laggy)" : "", session_state_name(s->s_state)); - if (memcmp(ceph_mdsmap_get_addr(oldmap, i), + if (i >= newmap->m_max_mds || + memcmp(ceph_mdsmap_get_addr(oldmap, i), ceph_mdsmap_get_addr(newmap, i), sizeof(struct ceph_entity_addr))) { if (s->s_state == CEPH_MDS_SESSION_OPENING) { @@ -3395,39 +3400,33 @@ static void dispatch(struct ceph_connection *con, struct ceph_msg *msg) /* * authentication */ -static int get_authorizer(struct ceph_connection *con, - void **buf, int *len, int *proto, - void **reply_buf, int *reply_len, int force_new) + +/* + * Note: returned pointer is the address of a structure that's + * managed separately. Caller must *not* attempt to free it. + */ +static struct ceph_auth_handshake *get_authorizer(struct ceph_connection *con, + int *proto, int force_new) { struct ceph_mds_session *s = con->private; struct ceph_mds_client *mdsc = s->s_mdsc; struct ceph_auth_client *ac = mdsc->fsc->client->monc.auth; - int ret = 0; - - if (force_new && s->s_authorizer) { - ac->ops->destroy_authorizer(ac, s->s_authorizer); - s->s_authorizer = NULL; - } - if (s->s_authorizer == NULL) { - if (ac->ops->create_authorizer) { - ret = ac->ops->create_authorizer( - ac, CEPH_ENTITY_TYPE_MDS, - &s->s_authorizer, - &s->s_authorizer_buf, - &s->s_authorizer_buf_len, - &s->s_authorizer_reply_buf, - &s->s_authorizer_reply_buf_len); - if (ret) - return ret; - } - } + struct ceph_auth_handshake *auth = &s->s_auth; + if (force_new && auth->authorizer) { + if (ac->ops && ac->ops->destroy_authorizer) + ac->ops->destroy_authorizer(ac, auth->authorizer); + auth->authorizer = NULL; + } + if (!auth->authorizer && ac->ops && ac->ops->create_authorizer) { + int ret = ac->ops->create_authorizer(ac, CEPH_ENTITY_TYPE_MDS, + auth); + if (ret) + return ERR_PTR(ret); + } *proto = ac->protocol; - *buf = s->s_authorizer_buf; - *len = s->s_authorizer_buf_len; - *reply_buf = s->s_authorizer_reply_buf; - *reply_len = s->s_authorizer_reply_buf_len; - return 0; + + return auth; } @@ -3437,7 +3436,7 @@ static int verify_authorizer_reply(struct ceph_connection *con, int len) struct ceph_mds_client *mdsc = s->s_mdsc; struct ceph_auth_client *ac = mdsc->fsc->client->monc.auth; - return ac->ops->verify_authorizer_reply(ac, s->s_authorizer, len); + return ac->ops->verify_authorizer_reply(ac, s->s_auth.authorizer, len); } static int invalidate_authorizer(struct ceph_connection *con) diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h index 8c7c04ebb59..dd26846dd71 100644 --- a/fs/ceph/mds_client.h +++ b/fs/ceph/mds_client.h @@ -11,6 +11,7 @@ #include #include #include +#include /* * Some lock dependencies: @@ -113,9 +114,7 @@ struct ceph_mds_session { struct ceph_connection s_con; - struct ceph_authorizer *s_authorizer; - void *s_authorizer_buf, *s_authorizer_reply_buf; - size_t s_authorizer_buf_len, s_authorizer_reply_buf_len; + struct ceph_auth_handshake s_auth; /* protected by s_gen_ttl_lock */ spinlock_t s_gen_ttl_lock; diff --git a/fs/ceph/super.c b/fs/ceph/super.c index 1e67dd7305a..f3639181546 100644 --- a/fs/ceph/super.c +++ b/fs/ceph/super.c @@ -387,8 +387,6 @@ static int ceph_show_options(struct seq_file *m, struct dentry *root) seq_printf(m, ",mount_timeout=%d", opt->mount_timeout); if (opt->osd_idle_ttl != CEPH_OSD_IDLE_TTL_DEFAULT) seq_printf(m, ",osd_idle_ttl=%d", opt->osd_idle_ttl); - if (opt->osd_timeout != CEPH_OSD_TIMEOUT_DEFAULT) - seq_printf(m, ",osdtimeout=%d", opt->osd_timeout); if (opt->osd_keepalive_timeout != CEPH_OSD_KEEPALIVE_DEFAULT) seq_printf(m, ",osdkeepalivetimeout=%d", opt->osd_keepalive_timeout); diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c index 6873bb634a9..22631445a4a 100644 --- a/fs/cifs/cifs_dfs_ref.c +++ b/fs/cifs/cifs_dfs_ref.c @@ -226,6 +226,8 @@ char *cifs_compose_mount_options(const char *sb_mountdata, compose_mount_options_err: kfree(mountdata); mountdata = ERR_PTR(rc); + kfree(*devname); + *devname = NULL; goto compose_mount_options_out; } diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c index fbb9da95184..6a8568c6466 100644 --- a/fs/cifs/cifs_unicode.c +++ b/fs/cifs/cifs_unicode.c @@ -203,6 +203,27 @@ cifs_strtoUTF16(__le16 *to, const char *from, int len, int i; wchar_t wchar_to; /* needed to quiet sparse */ + /* special case for utf8 to handle no plane0 chars */ + if (!strcmp(codepage->charset, "utf8")) { + /* + * convert utf8 -> utf16, we assume we have enough space + * as caller should have assumed conversion does not overflow + * in destination len is length in wchar_t units (16bits) + */ + i = utf8s_to_utf16s(from, len, UTF16_LITTLE_ENDIAN, + (wchar_t *) to, len); + + /* if success terminate and exit */ + if (i >= 0) + goto success; + /* + * if fails fall back to UCS encoding as this + * function should not return negative values + * currently can fail only if source contains + * invalid encoded characters + */ + } + for (i = 0; len && *from; i++, from += charlen, len -= charlen) { charlen = codepage->char2uni(from, len, &wchar_to); if (charlen < 1) { @@ -215,6 +236,7 @@ cifs_strtoUTF16(__le16 *to, const char *from, int len, put_unaligned_le16(wchar_to, &to[i]); } +success: put_unaligned_le16(0, &to[i]); return i; } @@ -328,6 +350,6 @@ cifsConvertToUTF16(__le16 *target, const char *source, int srclen, } ctoUTF16_out: - return i; + return j; } diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index 3cc1b251ca0..6ccf176427f 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c @@ -224,6 +224,13 @@ sid_to_str(struct cifs_sid *sidptr, char *sidstr) } } +static void +cifs_copy_sid(struct cifs_sid *dst, const struct cifs_sid *src) +{ + memcpy(dst, src, sizeof(*dst)); + dst->num_subauth = min_t(u8, src->num_subauth, NUM_SUBAUTHS); +} + static void id_rb_insert(struct rb_root *root, struct cifs_sid *sidptr, struct cifs_sid_id **psidid, char *typestr) @@ -248,7 +255,7 @@ id_rb_insert(struct rb_root *root, struct cifs_sid *sidptr, } } - memcpy(&(*psidid)->sid, sidptr, sizeof(struct cifs_sid)); + cifs_copy_sid(&(*psidid)->sid, sidptr); (*psidid)->time = jiffies - (SID_MAP_RETRY + 1); (*psidid)->refcount = 0; @@ -354,7 +361,7 @@ id_to_sid(unsigned long cid, uint sidtype, struct cifs_sid *ssid) * any fields of the node after a reference is put . */ if (test_bit(SID_ID_MAPPED, &psidid->state)) { - memcpy(ssid, &psidid->sid, sizeof(struct cifs_sid)); + cifs_copy_sid(ssid, &psidid->sid); psidid->time = jiffies; /* update ts for accessing */ goto id_sid_out; } @@ -370,14 +377,14 @@ id_to_sid(unsigned long cid, uint sidtype, struct cifs_sid *ssid) if (IS_ERR(sidkey)) { rc = -EINVAL; cFYI(1, "%s: Can't map and id to a SID", __func__); + } else if (sidkey->datalen < sizeof(struct cifs_sid)) { + rc = -EIO; + cFYI(1, "%s: Downcall contained malformed key " + "(datalen=%hu)", __func__, sidkey->datalen); } else { lsid = (struct cifs_sid *)sidkey->payload.data; - memcpy(&psidid->sid, lsid, - sidkey->datalen < sizeof(struct cifs_sid) ? - sidkey->datalen : sizeof(struct cifs_sid)); - memcpy(ssid, &psidid->sid, - sidkey->datalen < sizeof(struct cifs_sid) ? - sidkey->datalen : sizeof(struct cifs_sid)); + cifs_copy_sid(&psidid->sid, lsid); + cifs_copy_sid(ssid, &psidid->sid); set_bit(SID_ID_MAPPED, &psidid->state); key_put(sidkey); kfree(psidid->sidstr); @@ -396,7 +403,7 @@ id_to_sid(unsigned long cid, uint sidtype, struct cifs_sid *ssid) return rc; } if (test_bit(SID_ID_MAPPED, &psidid->state)) - memcpy(ssid, &psidid->sid, sizeof(struct cifs_sid)); + cifs_copy_sid(ssid, &psidid->sid); else rc = -EINVAL; } @@ -675,8 +682,6 @@ int compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid) static void copy_sec_desc(const struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd, __u32 sidsoffset) { - int i; - struct cifs_sid *owner_sid_ptr, *group_sid_ptr; struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr; @@ -692,26 +697,14 @@ static void copy_sec_desc(const struct cifs_ntsd *pntsd, owner_sid_ptr = (struct cifs_sid *)((char *)pntsd + le32_to_cpu(pntsd->osidoffset)); nowner_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset); - - nowner_sid_ptr->revision = owner_sid_ptr->revision; - nowner_sid_ptr->num_subauth = owner_sid_ptr->num_subauth; - for (i = 0; i < 6; i++) - nowner_sid_ptr->authority[i] = owner_sid_ptr->authority[i]; - for (i = 0; i < 5; i++) - nowner_sid_ptr->sub_auth[i] = owner_sid_ptr->sub_auth[i]; + cifs_copy_sid(nowner_sid_ptr, owner_sid_ptr); /* copy group sid */ group_sid_ptr = (struct cifs_sid *)((char *)pntsd + le32_to_cpu(pntsd->gsidoffset)); ngroup_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset + sizeof(struct cifs_sid)); - - ngroup_sid_ptr->revision = group_sid_ptr->revision; - ngroup_sid_ptr->num_subauth = group_sid_ptr->num_subauth; - for (i = 0; i < 6; i++) - ngroup_sid_ptr->authority[i] = group_sid_ptr->authority[i]; - for (i = 0; i < 5; i++) - ngroup_sid_ptr->sub_auth[i] = group_sid_ptr->sub_auth[i]; + cifs_copy_sid(ngroup_sid_ptr, group_sid_ptr); return; } @@ -1120,8 +1113,7 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd, kfree(nowner_sid_ptr); return rc; } - memcpy(owner_sid_ptr, nowner_sid_ptr, - sizeof(struct cifs_sid)); + cifs_copy_sid(owner_sid_ptr, nowner_sid_ptr); kfree(nowner_sid_ptr); *aclflag = CIFS_ACL_OWNER; } @@ -1139,8 +1131,7 @@ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd, kfree(ngroup_sid_ptr); return rc; } - memcpy(group_sid_ptr, ngroup_sid_ptr, - sizeof(struct cifs_sid)); + cifs_copy_sid(group_sid_ptr, ngroup_sid_ptr); kfree(ngroup_sid_ptr); *aclflag = CIFS_ACL_GROUP; } diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 6b79efd7d75..3a75ee5a6b3 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -89,6 +89,32 @@ static struct { /* Forward declarations */ static void cifs_readv_complete(struct work_struct *work); +#ifdef CONFIG_HIGHMEM +/* + * On arches that have high memory, kmap address space is limited. By + * serializing the kmap operations on those arches, we ensure that we don't + * end up with a bunch of threads in writeback with partially mapped page + * arrays, stuck waiting for kmap to come back. That situation prevents + * progress and can deadlock. + */ +static DEFINE_MUTEX(cifs_kmap_mutex); + +static inline void +cifs_kmap_lock(void) +{ + mutex_lock(&cifs_kmap_mutex); +} + +static inline void +cifs_kmap_unlock(void) +{ + mutex_unlock(&cifs_kmap_mutex); +} +#else /* !CONFIG_HIGHMEM */ +#define cifs_kmap_lock() do { ; } while(0) +#define cifs_kmap_unlock() do { ; } while(0) +#endif /* CONFIG_HIGHMEM */ + /* Mark as invalid, all open files on tree connections since they were closed when session to server was lost */ static void mark_open_files_invalid(struct cifs_tcon *pTcon) @@ -1557,6 +1583,7 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid) eof_index = eof ? (eof - 1) >> PAGE_CACHE_SHIFT : 0; cFYI(1, "eof=%llu eof_index=%lu", eof, eof_index); + cifs_kmap_lock(); list_for_each_entry_safe(page, tpage, &rdata->pages, lru) { if (remaining >= PAGE_CACHE_SIZE) { /* enough data to fill the page */ @@ -1606,6 +1633,7 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid) page_cache_release(page); } } + cifs_kmap_unlock(); /* issue the read if we have any iovecs left to fill */ if (rdata->nr_iov > 1) { @@ -2194,7 +2222,9 @@ cifs_async_writev(struct cifs_writedata *wdata) * and set the iov_len properly for each one. It may also set * wdata->bytes too. */ + cifs_kmap_lock(); wdata->marshal_iov(iov, wdata); + cifs_kmap_unlock(); cFYI(1, "async write at %llu %u bytes", wdata->offset, wdata->bytes); diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 402fa0f9bc0..f771e9f98f9 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -70,6 +70,7 @@ enum { /* Mount options that take no arguments */ Opt_user_xattr, Opt_nouser_xattr, Opt_forceuid, Opt_noforceuid, + Opt_forcegid, Opt_noforcegid, Opt_noblocksend, Opt_noautotune, Opt_hard, Opt_soft, Opt_perm, Opt_noperm, Opt_mapchars, Opt_nomapchars, Opt_sfu, @@ -121,6 +122,8 @@ static const match_table_t cifs_mount_option_tokens = { { Opt_nouser_xattr, "nouser_xattr" }, { Opt_forceuid, "forceuid" }, { Opt_noforceuid, "noforceuid" }, + { Opt_forcegid, "forcegid" }, + { Opt_noforcegid, "noforcegid" }, { Opt_noblocksend, "noblocksend" }, { Opt_noautotune, "noautotune" }, { Opt_hard, "hard" }, @@ -238,8 +241,8 @@ static const match_table_t cifs_mount_option_tokens = { enum { Opt_sec_krb5, Opt_sec_krb5i, Opt_sec_krb5p, Opt_sec_ntlmsspi, Opt_sec_ntlmssp, - Opt_ntlm, Opt_sec_ntlmi, Opt_sec_ntlmv2i, - Opt_sec_nontlm, Opt_sec_lanman, + Opt_ntlm, Opt_sec_ntlmi, Opt_sec_ntlmv2, + Opt_sec_ntlmv2i, Opt_sec_lanman, Opt_sec_none, Opt_sec_err @@ -253,8 +256,9 @@ static const match_table_t cifs_secflavor_tokens = { { Opt_sec_ntlmssp, "ntlmssp" }, { Opt_ntlm, "ntlm" }, { Opt_sec_ntlmi, "ntlmi" }, + { Opt_sec_ntlmv2, "nontlm" }, + { Opt_sec_ntlmv2, "ntlmv2" }, { Opt_sec_ntlmv2i, "ntlmv2i" }, - { Opt_sec_nontlm, "nontlm" }, { Opt_sec_lanman, "lanman" }, { Opt_sec_none, "none" }, @@ -1163,7 +1167,7 @@ static int cifs_parse_security_flavors(char *value, case Opt_sec_ntlmi: vol->secFlg |= CIFSSEC_MAY_NTLM | CIFSSEC_MUST_SIGN; break; - case Opt_sec_nontlm: + case Opt_sec_ntlmv2: vol->secFlg |= CIFSSEC_MAY_NTLMV2; break; case Opt_sec_ntlmv2i: @@ -1286,6 +1290,12 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, case Opt_noforceuid: override_uid = 0; break; + case Opt_forcegid: + override_gid = 1; + break; + case Opt_noforcegid: + override_gid = 0; + break; case Opt_noblocksend: vol->noblocksnd = 1; break; @@ -3348,6 +3358,18 @@ void cifs_setup_cifs_sb(struct smb_vol *pvolume_info, #define CIFS_DEFAULT_NON_POSIX_RSIZE (60 * 1024) #define CIFS_DEFAULT_NON_POSIX_WSIZE (65536) +/* + * On hosts with high memory, we can't currently support wsize/rsize that are + * larger than we can kmap at once. Cap the rsize/wsize at + * LAST_PKMAP * PAGE_SIZE. We'll never be able to fill a read or write request + * larger than that anyway. + */ +#ifdef CONFIG_HIGHMEM +#define CIFS_KMAP_SIZE_LIMIT (LAST_PKMAP * PAGE_CACHE_SIZE) +#else /* CONFIG_HIGHMEM */ +#define CIFS_KMAP_SIZE_LIMIT (1<<24) +#endif /* CONFIG_HIGHMEM */ + static unsigned int cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info) { @@ -3378,6 +3400,9 @@ cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info) wsize = min_t(unsigned int, wsize, server->maxBuf - sizeof(WRITE_REQ) + 4); + /* limit to the amount that we can kmap at once */ + wsize = min_t(unsigned int, wsize, CIFS_KMAP_SIZE_LIMIT); + /* hard limit of CIFS_MAX_WSIZE */ wsize = min_t(unsigned int, wsize, CIFS_MAX_WSIZE); @@ -3419,6 +3444,9 @@ cifs_negotiate_rsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info) if (!(server->capabilities & CAP_LARGE_READ_X)) rsize = min_t(unsigned int, CIFSMaxBufSize, rsize); + /* limit to the amount that we can kmap at once */ + rsize = min_t(unsigned int, rsize, CIFS_KMAP_SIZE_LIMIT); + /* hard limit of CIFS_MAX_RSIZE */ rsize = min_t(unsigned int, rsize, CIFS_MAX_RSIZE); diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index 0a8224d1c4c..a4217f02fab 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c @@ -86,9 +86,12 @@ cifs_readdir_lookup(struct dentry *parent, struct qstr *name, dentry = d_lookup(parent, name); if (dentry) { - /* FIXME: check for inode number changes? */ - if (dentry->d_inode != NULL) + inode = dentry->d_inode; + /* update inode in place if i_ino didn't change */ + if (inode && CIFS_I(inode)->uniqueid == fattr->cf_uniqueid) { + cifs_fattr_to_inode(inode, fattr); return dentry; + } d_drop(dentry); dput(dentry); } diff --git a/fs/compat.c b/fs/compat.c index f2944ace7a7..2b371b38911 100644 --- a/fs/compat.c +++ b/fs/compat.c @@ -1160,11 +1160,14 @@ compat_sys_readv(unsigned long fd, const struct compat_iovec __user *vec, struct file *file; int fput_needed; ssize_t ret; + loff_t pos; file = fget_light(fd, &fput_needed); if (!file) return -EBADF; - ret = compat_readv(file, vec, vlen, &file->f_pos); + pos = file->f_pos; + ret = compat_readv(file, vec, vlen, &pos); + file->f_pos = pos; fput_light(file, fput_needed); return ret; } @@ -1226,11 +1229,14 @@ compat_sys_writev(unsigned long fd, const struct compat_iovec __user *vec, struct file *file; int fput_needed; ssize_t ret; + loff_t pos; file = fget_light(fd, &fput_needed); if (!file) return -EBADF; - ret = compat_writev(file, vec, vlen, &file->f_pos); + pos = file->f_pos; + ret = compat_writev(file, vec, vlen, &pos); + file->f_pos = pos; fput_light(file, fput_needed); return ret; } diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index b03bd8e95ac..52a0c20e853 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -211,6 +211,8 @@ static int do_video_set_spu_palette(unsigned int fd, unsigned int cmd, err = get_user(palp, &up->palette); err |= get_user(length, &up->length); + if (err) + return -EFAULT; up_native = compat_alloc_user_space(sizeof(struct video_spu_palette)); err = put_user(compat_ptr(palp), &up_native->palette); diff --git a/fs/dcache.c b/fs/dcache.c index a94b9fdf205..f104945dcc7 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -373,7 +373,7 @@ static struct dentry *d_kill(struct dentry *dentry, struct dentry *parent) * Inform try_to_ascend() that we are no longer attached to the * dentry tree */ - dentry->d_flags |= DCACHE_DISCONNECTED; + dentry->d_flags |= DCACHE_DENTRY_KILLED; if (parent) spin_unlock(&parent->d_lock); dentry_iput(dentry); @@ -1030,7 +1030,7 @@ static struct dentry *try_to_ascend(struct dentry *old, int locked, unsigned seq * or deletion */ if (new != old->d_parent || - (old->d_flags & DCACHE_DISCONNECTED) || + (old->d_flags & DCACHE_DENTRY_KILLED) || (!locked && read_seqretry(&rename_lock, seq))) { spin_unlock(&new->d_lock); new = NULL; diff --git a/fs/eventpoll.c b/fs/eventpoll.c index b163f891bc3..9dba98a0b31 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -1270,10 +1270,30 @@ static int ep_modify(struct eventpoll *ep, struct epitem *epi, struct epoll_even * otherwise we might miss an event that happens between the * f_op->poll() call and the new event set registering. */ - epi->event.events = event->events; + epi->event.events = event->events; /* need barrier below */ pt._key = event->events; epi->event.data = event->data; /* protected by mtx */ + /* + * The following barrier has two effects: + * + * 1) Flush epi changes above to other CPUs. This ensures + * we do not miss events from ep_poll_callback if an + * event occurs immediately after we call f_op->poll(). + * We need this because we did not take ep->lock while + * changing epi above (but ep_poll_callback does take + * ep->lock). + * + * 2) We also need to ensure we do not miss _past_ events + * when calling f_op->poll(). This barrier also + * pairs with the barrier in wq_has_sleeper (see + * comments for wq_has_sleeper). + * + * This barrier will now guarantee ep_poll_callback or f_op->poll + * (or both) will notice the readiness of an item. + */ + smp_mb(); + /* * Get current event bits. We can safely use the file* here because * its usage count has been increased by the caller of this function. diff --git a/fs/exec.c b/fs/exec.c index 29e5f840544..51d86297363 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -1024,7 +1024,7 @@ static void flush_old_files(struct files_struct * files) unsigned long set, i; j++; - i = j * __NFDBITS; + i = j * BITS_PER_LONG; fdt = files_fdtable(files); if (i >= fdt->max_fds) break; @@ -1114,7 +1114,8 @@ int flush_old_exec(struct linux_binprm * bprm) bprm->mm = NULL; /* We're using it now */ set_fs(USER_DS); - current->flags &= ~(PF_RANDOMIZE | PF_FORKNOEXEC | PF_KTHREAD); + current->flags &= + ~(PF_RANDOMIZE | PF_FORKNOEXEC | PF_KTHREAD | PF_NOFREEZE); flush_thread(); current->personality &= ~bprm->per_clear; @@ -1205,9 +1206,24 @@ void free_bprm(struct linux_binprm *bprm) mutex_unlock(¤t->signal->cred_guard_mutex); abort_creds(bprm->cred); } + /* If a binfmt changed the interp, free it. */ + if (bprm->interp != bprm->filename) + kfree(bprm->interp); kfree(bprm); } +int bprm_change_interp(char *interp, struct linux_binprm *bprm) +{ + /* If a binfmt changed the interp, free it first. */ + if (bprm->interp != bprm->filename) + kfree(bprm->interp); + bprm->interp = kstrdup(interp, GFP_KERNEL); + if (!bprm->interp) + return -ENOMEM; + return 0; +} +EXPORT_SYMBOL(bprm_change_interp); + /* * install the new credentials for this executable */ diff --git a/fs/exofs/ore.c b/fs/exofs/ore.c index 49cf230554a..1585db1aa36 100644 --- a/fs/exofs/ore.c +++ b/fs/exofs/ore.c @@ -735,13 +735,7 @@ static int _prepare_for_striping(struct ore_io_state *ios) out: ios->numdevs = devs_in_group; ios->pages_consumed = cur_pg; - if (unlikely(ret)) { - if (length == ios->length) - return ret; - else - ios->length -= length; - } - return 0; + return ret; } int ore_create(struct ore_io_state *ios) @@ -843,11 +837,11 @@ static int _write_mirror(struct ore_io_state *ios, int cur_comp) bio->bi_rw |= REQ_WRITE; } - osd_req_write(or, _ios_obj(ios, dev), per_dev->offset, - bio, per_dev->length); + osd_req_write(or, _ios_obj(ios, cur_comp), + per_dev->offset, bio, per_dev->length); ORE_DBGMSG("write(0x%llx) offset=0x%llx " "length=0x%llx dev=%d\n", - _LLU(_ios_obj(ios, dev)->id), + _LLU(_ios_obj(ios, cur_comp)->id), _LLU(per_dev->offset), _LLU(per_dev->length), dev); } else if (ios->kern_buff) { @@ -859,20 +853,20 @@ static int _write_mirror(struct ore_io_state *ios, int cur_comp) (ios->si.unit_off + ios->length > ios->layout->stripe_unit)); - ret = osd_req_write_kern(or, _ios_obj(ios, per_dev->dev), + ret = osd_req_write_kern(or, _ios_obj(ios, cur_comp), per_dev->offset, ios->kern_buff, ios->length); if (unlikely(ret)) goto out; ORE_DBGMSG2("write_kern(0x%llx) offset=0x%llx " "length=0x%llx dev=%d\n", - _LLU(_ios_obj(ios, dev)->id), + _LLU(_ios_obj(ios, cur_comp)->id), _LLU(per_dev->offset), _LLU(ios->length), per_dev->dev); } else { - osd_req_set_attributes(or, _ios_obj(ios, dev)); + osd_req_set_attributes(or, _ios_obj(ios, cur_comp)); ORE_DBGMSG2("obj(0x%llx) set_attributes=%d dev=%d\n", - _LLU(_ios_obj(ios, dev)->id), + _LLU(_ios_obj(ios, cur_comp)->id), ios->out_attr_len, dev); } diff --git a/fs/exofs/ore_raid.c b/fs/exofs/ore_raid.c index d222c77cfa1..fff2070c675 100644 --- a/fs/exofs/ore_raid.c +++ b/fs/exofs/ore_raid.c @@ -461,16 +461,12 @@ static void _mark_read4write_pages_uptodate(struct ore_io_state *ios, int ret) * ios->sp2d[p][*], xor is calculated the same way. These pages are * allocated/freed and don't go through cache */ -static int _read_4_write(struct ore_io_state *ios) +static int _read_4_write_first_stripe(struct ore_io_state *ios) { - struct ore_io_state *ios_read; struct ore_striping_info read_si; struct __stripe_pages_2d *sp2d = ios->sp2d; u64 offset = ios->si.first_stripe_start; - u64 last_stripe_end; - unsigned bytes_in_stripe = ios->si.bytes_in_stripe; - unsigned i, c, p, min_p = sp2d->pages_in_unit, max_p = -1; - int ret; + unsigned c, p, min_p = sp2d->pages_in_unit, max_p = -1; if (offset == ios->offset) /* Go to start collect $200 */ goto read_last_stripe; @@ -478,6 +474,9 @@ static int _read_4_write(struct ore_io_state *ios) min_p = _sp2d_min_pg(sp2d); max_p = _sp2d_max_pg(sp2d); + ORE_DBGMSG("stripe_start=0x%llx ios->offset=0x%llx min_p=%d max_p=%d\n", + offset, ios->offset, min_p, max_p); + for (c = 0; ; c++) { ore_calc_stripe_info(ios->layout, offset, 0, &read_si); read_si.obj_offset += min_p * PAGE_SIZE; @@ -512,6 +511,18 @@ static int _read_4_write(struct ore_io_state *ios) } read_last_stripe: + return 0; +} + +static int _read_4_write_last_stripe(struct ore_io_state *ios) +{ + struct ore_striping_info read_si; + struct __stripe_pages_2d *sp2d = ios->sp2d; + u64 offset; + u64 last_stripe_end; + unsigned bytes_in_stripe = ios->si.bytes_in_stripe; + unsigned c, p, min_p = sp2d->pages_in_unit, max_p = -1; + offset = ios->offset + ios->length; if (offset % PAGE_SIZE) _add_to_r4w_last_page(ios, &offset); @@ -527,15 +538,15 @@ static int _read_4_write(struct ore_io_state *ios) c = _dev_order(ios->layout->group_width * ios->layout->mirrors_p1, ios->layout->mirrors_p1, read_si.par_dev, read_si.dev); - BUG_ON(ios->si.first_stripe_start + bytes_in_stripe != last_stripe_end); - /* unaligned IO must be within a single stripe */ - if (min_p == sp2d->pages_in_unit) { /* Didn't do it yet */ min_p = _sp2d_min_pg(sp2d); max_p = _sp2d_max_pg(sp2d); } + ORE_DBGMSG("offset=0x%llx stripe_end=0x%llx min_p=%d max_p=%d\n", + offset, last_stripe_end, min_p, max_p); + while (offset < last_stripe_end) { struct __1_page_stripe *_1ps = &sp2d->_1p_stripes[p]; @@ -568,6 +579,15 @@ static int _read_4_write(struct ore_io_state *ios) } read_it: + return 0; +} + +static int _read_4_write_execute(struct ore_io_state *ios) +{ + struct ore_io_state *ios_read; + unsigned i; + int ret; + ios_read = ios->ios_read_4_write; if (!ios_read) return 0; @@ -591,6 +611,8 @@ static int _read_4_write(struct ore_io_state *ios) } _mark_read4write_pages_uptodate(ios_read, ret); + ore_put_io_state(ios_read); + ios->ios_read_4_write = NULL; /* Might need a reuse at last stripe */ return 0; } @@ -626,8 +648,11 @@ int _ore_add_parity_unit(struct ore_io_state *ios, /* If first stripe, Read in all read4write pages * (if needed) before we calculate the first parity. */ - _read_4_write(ios); + _read_4_write_first_stripe(ios); } + if (!cur_len) /* If last stripe r4w pages of last stripe */ + _read_4_write_last_stripe(ios); + _read_4_write_execute(ios); for (i = 0; i < num_pages; i++) { pages[i] = _raid_page_alloc(); @@ -654,34 +679,14 @@ int _ore_add_parity_unit(struct ore_io_state *ios, int _ore_post_alloc_raid_stuff(struct ore_io_state *ios) { - struct ore_layout *layout = ios->layout; - if (ios->parity_pages) { + struct ore_layout *layout = ios->layout; unsigned pages_in_unit = layout->stripe_unit / PAGE_SIZE; - unsigned stripe_size = ios->si.bytes_in_stripe; - u64 last_stripe, first_stripe; if (_sp2d_alloc(pages_in_unit, layout->group_width, layout->parity, &ios->sp2d)) { return -ENOMEM; } - - /* Round io down to last full strip */ - first_stripe = div_u64(ios->offset, stripe_size); - last_stripe = div_u64(ios->offset + ios->length, stripe_size); - - /* If an IO spans more then a single stripe it must end at - * a stripe boundary. The reminder at the end is pushed into the - * next IO. - */ - if (last_stripe != first_stripe) { - ios->length = last_stripe * stripe_size - ios->offset; - - BUG_ON(!ios->length); - ios->nr_pages = (ios->length + PAGE_SIZE - 1) / - PAGE_SIZE; - ios->si.length = ios->length; /*make it consistent */ - } } return 0; } diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index 10d7812f602..075281734fc 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c @@ -3068,6 +3068,8 @@ static int ext3_do_update_inode(handle_t *handle, struct ext3_inode_info *ei = EXT3_I(inode); struct buffer_head *bh = iloc->bh; int err = 0, rc, block; + int need_datasync = 0; + __le32 disksize; again: /* we can't allow multiple procs in here at once, its a bit racey */ @@ -3105,7 +3107,11 @@ static int ext3_do_update_inode(handle_t *handle, raw_inode->i_gid_high = 0; } raw_inode->i_links_count = cpu_to_le16(inode->i_nlink); - raw_inode->i_size = cpu_to_le32(ei->i_disksize); + disksize = cpu_to_le32(ei->i_disksize); + if (disksize != raw_inode->i_size) { + need_datasync = 1; + raw_inode->i_size = disksize; + } raw_inode->i_atime = cpu_to_le32(inode->i_atime.tv_sec); raw_inode->i_ctime = cpu_to_le32(inode->i_ctime.tv_sec); raw_inode->i_mtime = cpu_to_le32(inode->i_mtime.tv_sec); @@ -3121,8 +3127,11 @@ static int ext3_do_update_inode(handle_t *handle, if (!S_ISREG(inode->i_mode)) { raw_inode->i_dir_acl = cpu_to_le32(ei->i_dir_acl); } else { - raw_inode->i_size_high = - cpu_to_le32(ei->i_disksize >> 32); + disksize = cpu_to_le32(ei->i_disksize >> 32); + if (disksize != raw_inode->i_size_high) { + raw_inode->i_size_high = disksize; + need_datasync = 1; + } if (ei->i_disksize > 0x7fffffffULL) { struct super_block *sb = inode->i_sb; if (!EXT3_HAS_RO_COMPAT_FEATURE(sb, @@ -3175,6 +3184,8 @@ static int ext3_do_update_inode(handle_t *handle, ext3_clear_inode_state(inode, EXT3_STATE_NEW); atomic_set(&ei->i_sync_tid, handle->h_transaction->t_tid); + if (need_datasync) + atomic_set(&ei->i_datasync_tid, handle->h_transaction->t_tid); out_brelse: brelse (bh); ext3_std_error(inode->i_sb, err); diff --git a/fs/ext4/acl.c b/fs/ext4/acl.c index a5c29bb3b83..8535c45dfce 100644 --- a/fs/ext4/acl.c +++ b/fs/ext4/acl.c @@ -410,8 +410,10 @@ ext4_xattr_set_acl(struct dentry *dentry, const char *name, const void *value, retry: handle = ext4_journal_start(inode, EXT4_DATA_TRANS_BLOCKS(inode->i_sb)); - if (IS_ERR(handle)) - return PTR_ERR(handle); + if (IS_ERR(handle)) { + error = PTR_ERR(handle); + goto release_and_out; + } error = ext4_set_acl(handle, inode, type, acl); ext4_journal_stop(handle); if (error == -ENOSPC && ext4_should_retry_alloc(inode->i_sb, &retries)) diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index 8da837be0c8..df76291d692 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c @@ -584,7 +584,8 @@ ext4_fsblk_t ext4_count_free_clusters(struct super_block *sb) if (bitmap_bh == NULL) continue; - x = ext4_count_free(bitmap_bh, sb->s_blocksize); + x = ext4_count_free(bitmap_bh->b_data, + EXT4_BLOCKS_PER_GROUP(sb) / 8); printk(KERN_DEBUG "group %u: stored = %d, counted = %u\n", i, ext4_free_group_clusters(sb, gdp), x); bitmap_count += x; diff --git a/fs/ext4/bitmap.c b/fs/ext4/bitmap.c index fa3af81ac56..bbde5d58297 100644 --- a/fs/ext4/bitmap.c +++ b/fs/ext4/bitmap.c @@ -11,21 +11,15 @@ #include #include "ext4.h" -#ifdef EXT4FS_DEBUG - static const int nibblemap[] = {4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0}; -unsigned int ext4_count_free(struct buffer_head *map, unsigned int numchars) +unsigned int ext4_count_free(char *bitmap, unsigned int numchars) { unsigned int i, sum = 0; - if (!map) - return 0; for (i = 0; i < numchars; i++) - sum += nibblemap[map->b_data[i] & 0xf] + - nibblemap[(map->b_data[i] >> 4) & 0xf]; + sum += nibblemap[bitmap[i] & 0xf] + + nibblemap[(bitmap[i] >> 4) & 0xf]; return sum; } -#endif /* EXT4FS_DEBUG */ - diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 0e01e90add8..47d1c8cda0c 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -1140,8 +1140,7 @@ struct ext4_sb_info { unsigned long s_desc_per_block; /* Number of group descriptors per block */ ext4_group_t s_groups_count; /* Number of groups in the fs */ ext4_group_t s_blockfile_groups;/* Groups acceptable for non-extent files */ - unsigned long s_overhead_last; /* Last calculated overhead */ - unsigned long s_blocks_last; /* Last seen block count */ + unsigned long s_overhead; /* # of fs overhead clusters */ unsigned int s_cluster_ratio; /* Number of blocks per cluster */ unsigned int s_cluster_bits; /* log2 of s_cluster_ratio */ loff_t s_bitmap_maxbytes; /* max bytes for bitmap files */ @@ -1783,7 +1782,7 @@ struct mmpd_data { # define NORET_AND noreturn, /* bitmap.c */ -extern unsigned int ext4_count_free(struct buffer_head *, unsigned); +extern unsigned int ext4_count_free(char *bitmap, unsigned numchars); /* balloc.c */ extern unsigned int ext4_block_group(struct super_block *sb, @@ -1950,6 +1949,7 @@ extern int ext4_group_extend(struct super_block *sb, extern int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count); /* super.c */ +extern int ext4_calculate_overhead(struct super_block *sb); extern void *ext4_kvmalloc(size_t size, gfp_t flags); extern void *ext4_kvzalloc(size_t size, gfp_t flags); extern void ext4_kvfree(void *ptr); diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index abcdeab67f5..852d4c257ac 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -52,6 +52,9 @@ #define EXT4_EXT_MARK_UNINIT1 0x2 /* mark first half uninitialized */ #define EXT4_EXT_MARK_UNINIT2 0x4 /* mark second half uninitialized */ +#define EXT4_EXT_DATA_VALID1 0x8 /* first half contains valid data */ +#define EXT4_EXT_DATA_VALID2 0x10 /* second half contains valid data */ + static int ext4_split_extent(handle_t *handle, struct inode *inode, struct ext4_ext_path *path, @@ -2107,13 +2110,14 @@ ext4_ext_in_cache(struct inode *inode, ext4_lblk_t block, * removes index from the index block. */ static int ext4_ext_rm_idx(handle_t *handle, struct inode *inode, - struct ext4_ext_path *path) + struct ext4_ext_path *path, int depth) { int err; ext4_fsblk_t leaf; /* free index block */ - path--; + depth--; + path = path + depth; leaf = ext4_idx_pblock(path->p_idx); if (unlikely(path->p_hdr->eh_entries == 0)) { EXT4_ERROR_INODE(inode, "path->p_hdr->eh_entries == 0"); @@ -2138,6 +2142,19 @@ static int ext4_ext_rm_idx(handle_t *handle, struct inode *inode, ext4_free_blocks(handle, inode, NULL, leaf, 1, EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET); + + while (--depth >= 0) { + if (path->p_idx != EXT_FIRST_INDEX(path->p_hdr)) + break; + path--; + err = ext4_ext_get_access(handle, inode, path); + if (err) + break; + path->p_idx->ei_block = (path+1)->p_idx->ei_block; + err = ext4_ext_dirty(handle, inode, path); + if (err) + break; + } return err; } @@ -2471,7 +2488,7 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode, /* if this leaf is free, then we should * remove it from index block above */ if (err == 0 && eh->eh_entries == 0 && path[depth].p_bh != NULL) - err = ext4_ext_rm_idx(handle, inode, path + depth); + err = ext4_ext_rm_idx(handle, inode, path, depth); out: return err; @@ -2503,10 +2520,10 @@ static int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start, { struct super_block *sb = inode->i_sb; int depth = ext_depth(inode); - struct ext4_ext_path *path; + struct ext4_ext_path *path = NULL; ext4_fsblk_t partial_cluster = 0; handle_t *handle; - int i, err; + int i = 0, err; ext_debug("truncate since %u to %u\n", start, end); @@ -2539,8 +2556,12 @@ static int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start, } depth = ext_depth(inode); ex = path[depth].p_ext; - if (!ex) + if (!ex) { + ext4_ext_drop_refs(path); + kfree(path); + path = NULL; goto cont; + } ee_block = le32_to_cpu(ex->ee_block); @@ -2570,8 +2591,6 @@ static int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start, if (err < 0) goto out; } - ext4_ext_drop_refs(path); - kfree(path); } cont: @@ -2580,19 +2599,28 @@ static int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start, * after i_size and walking into the tree depth-wise. */ depth = ext_depth(inode); - path = kzalloc(sizeof(struct ext4_ext_path) * (depth + 1), GFP_NOFS); - if (path == NULL) { - ext4_journal_stop(handle); - return -ENOMEM; - } - path[0].p_depth = depth; - path[0].p_hdr = ext_inode_hdr(inode); + if (path) { + int k = i = depth; + while (--k > 0) + path[k].p_block = + le16_to_cpu(path[k].p_hdr->eh_entries)+1; + } else { + path = kzalloc(sizeof(struct ext4_ext_path) * (depth + 1), + GFP_NOFS); + if (path == NULL) { + ext4_journal_stop(handle); + return -ENOMEM; + } + path[0].p_depth = depth; + path[0].p_hdr = ext_inode_hdr(inode); + i = 0; - if (ext4_ext_check(inode, path[0].p_hdr, depth)) { - err = -EIO; - goto out; + if (ext4_ext_check(inode, path[0].p_hdr, depth)) { + err = -EIO; + goto out; + } } - i = err = 0; + err = 0; while (i >= 0 && err == 0) { if (i == depth) { @@ -2661,7 +2689,7 @@ static int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start, /* index is empty, remove it; * handle must be already prepared by the * truncatei_leaf() */ - err = ext4_ext_rm_idx(handle, inode, path + i); + err = ext4_ext_rm_idx(handle, inode, path, i); } /* root level has p_bh == NULL, brelse() eats this */ brelse(path[i].p_bh); @@ -2706,8 +2734,10 @@ static int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start, out: ext4_ext_drop_refs(path); kfree(path); - if (err == -EAGAIN) + if (err == -EAGAIN) { + path = NULL; goto again; + } ext4_journal_stop(handle); return err; @@ -2816,6 +2846,9 @@ static int ext4_split_extent_at(handle_t *handle, unsigned int ee_len, depth; int err = 0; + BUG_ON((split_flag & (EXT4_EXT_DATA_VALID1 | EXT4_EXT_DATA_VALID2)) == + (EXT4_EXT_DATA_VALID1 | EXT4_EXT_DATA_VALID2)); + ext_debug("ext4_split_extents_at: inode %lu, logical" "block %llu\n", inode->i_ino, (unsigned long long)split); @@ -2874,7 +2907,14 @@ static int ext4_split_extent_at(handle_t *handle, err = ext4_ext_insert_extent(handle, inode, path, &newex, flags); if (err == -ENOSPC && (EXT4_EXT_MAY_ZEROOUT & split_flag)) { - err = ext4_ext_zeroout(inode, &orig_ex); + if (split_flag & (EXT4_EXT_DATA_VALID1|EXT4_EXT_DATA_VALID2)) { + if (split_flag & EXT4_EXT_DATA_VALID1) + err = ext4_ext_zeroout(inode, ex2); + else + err = ext4_ext_zeroout(inode, ex); + } else + err = ext4_ext_zeroout(inode, &orig_ex); + if (err) goto fix_extent_len; /* update the extent length and mark as initialized */ @@ -2927,12 +2967,13 @@ static int ext4_split_extent(handle_t *handle, uninitialized = ext4_ext_is_uninitialized(ex); if (map->m_lblk + map->m_len < ee_block + ee_len) { - split_flag1 = split_flag & EXT4_EXT_MAY_ZEROOUT ? - EXT4_EXT_MAY_ZEROOUT : 0; + split_flag1 = split_flag & EXT4_EXT_MAY_ZEROOUT; flags1 = flags | EXT4_GET_BLOCKS_PRE_IO; if (uninitialized) split_flag1 |= EXT4_EXT_MARK_UNINIT1 | EXT4_EXT_MARK_UNINIT2; + if (split_flag & EXT4_EXT_DATA_VALID2) + split_flag1 |= EXT4_EXT_DATA_VALID1; err = ext4_split_extent_at(handle, inode, path, map->m_lblk + map->m_len, split_flag1, flags1); if (err) @@ -2945,8 +2986,8 @@ static int ext4_split_extent(handle_t *handle, return PTR_ERR(path); if (map->m_lblk >= ee_block) { - split_flag1 = split_flag & EXT4_EXT_MAY_ZEROOUT ? - EXT4_EXT_MAY_ZEROOUT : 0; + split_flag1 = split_flag & (EXT4_EXT_MAY_ZEROOUT | + EXT4_EXT_DATA_VALID2); if (uninitialized) split_flag1 |= EXT4_EXT_MARK_UNINIT1; if (split_flag & EXT4_EXT_MARK_UNINIT2) @@ -3224,26 +3265,47 @@ static int ext4_split_unwritten_extents(handle_t *handle, split_flag |= ee_block + ee_len <= eof_block ? EXT4_EXT_MAY_ZEROOUT : 0; split_flag |= EXT4_EXT_MARK_UNINIT2; - + if (flags & EXT4_GET_BLOCKS_CONVERT) + split_flag |= EXT4_EXT_DATA_VALID2; flags |= EXT4_GET_BLOCKS_PRE_IO; return ext4_split_extent(handle, inode, path, map, split_flag, flags); } static int ext4_convert_unwritten_extents_endio(handle_t *handle, - struct inode *inode, - struct ext4_ext_path *path) + struct inode *inode, + struct ext4_map_blocks *map, + struct ext4_ext_path *path) { struct ext4_extent *ex; + ext4_lblk_t ee_block; + unsigned int ee_len; int depth; int err = 0; depth = ext_depth(inode); ex = path[depth].p_ext; + ee_block = le32_to_cpu(ex->ee_block); + ee_len = ext4_ext_get_actual_len(ex); ext_debug("ext4_convert_unwritten_extents_endio: inode %lu, logical" "block %llu, max_blocks %u\n", inode->i_ino, - (unsigned long long)le32_to_cpu(ex->ee_block), - ext4_ext_get_actual_len(ex)); + (unsigned long long)ee_block, ee_len); + + /* If extent is larger than requested then split is required */ + if (ee_block != map->m_lblk || ee_len > map->m_len) { + err = ext4_split_unwritten_extents(handle, inode, map, path, + EXT4_GET_BLOCKS_CONVERT); + if (err < 0) + goto out; + ext4_ext_drop_refs(path); + path = ext4_ext_find_extent(inode, map->m_lblk, path); + if (IS_ERR(path)) { + err = PTR_ERR(path); + goto out; + } + depth = ext_depth(inode); + ex = path[depth].p_ext; + } err = ext4_ext_get_access(handle, inode, path + depth); if (err) @@ -3551,7 +3613,7 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode, } /* IO end_io complete, convert the filled extent to written */ if ((flags & EXT4_GET_BLOCKS_CONVERT)) { - ret = ext4_convert_unwritten_extents_endio(handle, inode, + ret = ext4_convert_unwritten_extents_endio(handle, inode, map, path); if (ret >= 0) { ext4_update_inode_fsync_trans(handle, inode, 1); diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index b4a7dd56eb8..858f903818a 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c @@ -697,6 +697,10 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, umode_t mode, "inode=%lu", ino + 1); continue; } + BUFFER_TRACE(inode_bitmap_bh, "get_write_access"); + err = ext4_journal_get_write_access(handle, inode_bitmap_bh); + if (err) + goto fail; ext4_lock_group(sb, group); ret2 = ext4_test_and_set_bit(ino, inode_bitmap_bh->b_data); ext4_unlock_group(sb, group); @@ -725,7 +729,6 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, umode_t mode, BUFFER_TRACE(block_bitmap_bh, "dirty block bitmap"); err = ext4_handle_dirty_metadata(handle, NULL, block_bitmap_bh); - brelse(block_bitmap_bh); /* recheck and clear flag under lock if we still need to */ ext4_lock_group(sb, group); @@ -737,6 +740,7 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, umode_t mode, gdp); } ext4_unlock_group(sb, group); + brelse(block_bitmap_bh); if (err) goto fail; @@ -1016,7 +1020,8 @@ unsigned long ext4_count_free_inodes(struct super_block *sb) if (!bitmap_bh) continue; - x = ext4_count_free(bitmap_bh, EXT4_INODES_PER_GROUP(sb) / 8); + x = ext4_count_free(bitmap_bh->b_data, + EXT4_INODES_PER_GROUP(sb) / 8); printk(KERN_DEBUG "group %lu: stored = %d, counted = %lu\n", (unsigned long) i, ext4_free_inodes_count(sb, gdp), x); bitmap_count += x; diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index e99ad778173..55190932862 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -279,6 +279,15 @@ void ext4_da_update_reserve_space(struct inode *inode, used = ei->i_reserved_data_blocks; } + if (unlikely(ei->i_allocated_meta_blocks > ei->i_reserved_meta_blocks)) { + ext4_msg(inode->i_sb, KERN_NOTICE, "%s: ino %lu, allocated %d " + "with only %d reserved metadata blocks\n", __func__, + inode->i_ino, ei->i_allocated_meta_blocks, + ei->i_reserved_meta_blocks); + WARN_ON(1); + ei->i_allocated_meta_blocks = ei->i_reserved_meta_blocks; + } + /* Update per-inode reservations */ ei->i_reserved_data_blocks -= used; ei->i_reserved_meta_blocks -= ei->i_allocated_meta_blocks; @@ -1104,6 +1113,17 @@ static int ext4_da_reserve_space(struct inode *inode, ext4_lblk_t lblock) struct ext4_inode_info *ei = EXT4_I(inode); unsigned int md_needed; int ret; + ext4_lblk_t save_last_lblock; + int save_len; + + /* + * We will charge metadata quota at writeout time; this saves + * us from metadata over-estimation, though we may go over by + * a small amount in the end. Here we just reserve for data. + */ + ret = dquot_reserve_block(inode, EXT4_C2B(sbi, 1)); + if (ret) + return ret; /* * recalculate the amount of metadata blocks to reserve @@ -1112,32 +1132,31 @@ static int ext4_da_reserve_space(struct inode *inode, ext4_lblk_t lblock) */ repeat: spin_lock(&ei->i_block_reservation_lock); + /* + * ext4_calc_metadata_amount() has side effects, which we have + * to be prepared undo if we fail to claim space. + */ + save_len = ei->i_da_metadata_calc_len; + save_last_lblock = ei->i_da_metadata_calc_last_lblock; md_needed = EXT4_NUM_B2C(sbi, ext4_calc_metadata_amount(inode, lblock)); trace_ext4_da_reserve_space(inode, md_needed); - spin_unlock(&ei->i_block_reservation_lock); - /* - * We will charge metadata quota at writeout time; this saves - * us from metadata over-estimation, though we may go over by - * a small amount in the end. Here we just reserve for data. - */ - ret = dquot_reserve_block(inode, EXT4_C2B(sbi, 1)); - if (ret) - return ret; /* * We do still charge estimated metadata to the sb though; * we cannot afford to run out of free blocks. */ if (ext4_claim_free_clusters(sbi, md_needed + 1, 0)) { - dquot_release_reservation_block(inode, EXT4_C2B(sbi, 1)); + ei->i_da_metadata_calc_len = save_len; + ei->i_da_metadata_calc_last_lblock = save_last_lblock; + spin_unlock(&ei->i_block_reservation_lock); if (ext4_should_retry_alloc(inode->i_sb, &retries)) { yield(); goto repeat; } + dquot_release_reservation_block(inode, EXT4_C2B(sbi, 1)); return -ENOSPC; } - spin_lock(&ei->i_block_reservation_lock); ei->i_reserved_data_blocks++; ei->i_reserved_meta_blocks += md_needed; spin_unlock(&ei->i_block_reservation_lock); @@ -1405,6 +1424,8 @@ static void ext4_da_block_invalidatepages(struct mpage_da_data *mpd) index = mpd->first_page; end = mpd->next_page - 1; + + pagevec_init(&pvec, 0); while (index <= end) { nr_pages = pagevec_lookup(&pvec, mapping, index, PAGEVEC_SIZE); if (nr_pages == 0) diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index 1365903a514..9727522e271 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c @@ -261,7 +261,6 @@ long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) err = ext4_move_extents(filp, donor_filp, me.orig_start, me.donor_start, me.len, &me.moved_len); mnt_drop_write_file(filp); - mnt_drop_write(filp->f_path.mnt); if (copy_to_user((struct move_extent __user *)arg, &me, sizeof(me))) diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 6b0a57eafb5..e77c4fe665a 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -4984,8 +4984,9 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range) end = start + (range->len >> sb->s_blocksize_bits) - 1; minlen = range->minlen >> sb->s_blocksize_bits; - if (unlikely(minlen > EXT4_CLUSTERS_PER_GROUP(sb)) || - unlikely(start >= max_blks)) + if (minlen > EXT4_CLUSTERS_PER_GROUP(sb) || + start >= max_blks || + range->len < sb->s_blocksize) return -EINVAL; if (end >= max_blks) end = max_blks - 1; diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c index c5826c623e7..e2016f34b58 100644 --- a/fs/ext4/move_extent.c +++ b/fs/ext4/move_extent.c @@ -140,56 +140,22 @@ mext_next_extent(struct inode *inode, struct ext4_ext_path *path, return 1; } -/** - * mext_check_null_inode - NULL check for two inodes - * - * If inode1 or inode2 is NULL, return -EIO. Otherwise, return 0. - */ -static int -mext_check_null_inode(struct inode *inode1, struct inode *inode2, - const char *function, unsigned int line) -{ - int ret = 0; - - if (inode1 == NULL) { - __ext4_error(inode2->i_sb, function, line, - "Both inodes should not be NULL: " - "inode1 NULL inode2 %lu", inode2->i_ino); - ret = -EIO; - } else if (inode2 == NULL) { - __ext4_error(inode1->i_sb, function, line, - "Both inodes should not be NULL: " - "inode1 %lu inode2 NULL", inode1->i_ino); - ret = -EIO; - } - return ret; -} - /** * double_down_write_data_sem - Acquire two inodes' write lock of i_data_sem * - * @orig_inode: original inode structure - * @donor_inode: donor inode structure - * Acquire write lock of i_data_sem of the two inodes (orig and donor) by - * i_ino order. + * Acquire write lock of i_data_sem of the two inodes */ static void -double_down_write_data_sem(struct inode *orig_inode, struct inode *donor_inode) +double_down_write_data_sem(struct inode *first, struct inode *second) { - struct inode *first = orig_inode, *second = donor_inode; + if (first < second) { + down_write(&EXT4_I(first)->i_data_sem); + down_write_nested(&EXT4_I(second)->i_data_sem, SINGLE_DEPTH_NESTING); + } else { + down_write(&EXT4_I(second)->i_data_sem); + down_write_nested(&EXT4_I(first)->i_data_sem, SINGLE_DEPTH_NESTING); - /* - * Use the inode number to provide the stable locking order instead - * of its address, because the C language doesn't guarantee you can - * compare pointers that don't come from the same array. - */ - if (donor_inode->i_ino < orig_inode->i_ino) { - first = donor_inode; - second = orig_inode; } - - down_write(&EXT4_I(first)->i_data_sem); - down_write_nested(&EXT4_I(second)->i_data_sem, SINGLE_DEPTH_NESTING); } /** @@ -969,14 +935,6 @@ mext_check_arguments(struct inode *orig_inode, return -EINVAL; } - /* Files should be in the same ext4 FS */ - if (orig_inode->i_sb != donor_inode->i_sb) { - ext4_debug("ext4 move extent: The argument files " - "should be in same FS [ino:orig %lu, donor %lu]\n", - orig_inode->i_ino, donor_inode->i_ino); - return -EINVAL; - } - /* Ext4 move extent supports only extent based file */ if (!(ext4_test_inode_flag(orig_inode, EXT4_INODE_EXTENTS))) { ext4_debug("ext4 move extent: orig file is not extents " @@ -1072,35 +1030,19 @@ mext_check_arguments(struct inode *orig_inode, * @inode1: the inode structure * @inode2: the inode structure * - * Lock two inodes' i_mutex by i_ino order. - * If inode1 or inode2 is NULL, return -EIO. Otherwise, return 0. + * Lock two inodes' i_mutex */ -static int +static void mext_inode_double_lock(struct inode *inode1, struct inode *inode2) { - int ret = 0; - - BUG_ON(inode1 == NULL && inode2 == NULL); - - ret = mext_check_null_inode(inode1, inode2, __func__, __LINE__); - if (ret < 0) - goto out; - - if (inode1 == inode2) { - mutex_lock(&inode1->i_mutex); - goto out; - } - - if (inode1->i_ino < inode2->i_ino) { + BUG_ON(inode1 == inode2); + if (inode1 < inode2) { mutex_lock_nested(&inode1->i_mutex, I_MUTEX_PARENT); mutex_lock_nested(&inode2->i_mutex, I_MUTEX_CHILD); } else { mutex_lock_nested(&inode2->i_mutex, I_MUTEX_PARENT); mutex_lock_nested(&inode1->i_mutex, I_MUTEX_CHILD); } - -out: - return ret; } /** @@ -1109,28 +1051,13 @@ mext_inode_double_lock(struct inode *inode1, struct inode *inode2) * @inode1: the inode that is released first * @inode2: the inode that is released second * - * If inode1 or inode2 is NULL, return -EIO. Otherwise, return 0. */ -static int +static void mext_inode_double_unlock(struct inode *inode1, struct inode *inode2) { - int ret = 0; - - BUG_ON(inode1 == NULL && inode2 == NULL); - - ret = mext_check_null_inode(inode1, inode2, __func__, __LINE__); - if (ret < 0) - goto out; - - if (inode1) - mutex_unlock(&inode1->i_mutex); - - if (inode2 && inode2 != inode1) - mutex_unlock(&inode2->i_mutex); - -out: - return ret; + mutex_unlock(&inode1->i_mutex); + mutex_unlock(&inode2->i_mutex); } /** @@ -1187,16 +1114,23 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, ext4_lblk_t block_end, seq_start, add_blocks, file_end, seq_blocks = 0; ext4_lblk_t rest_blocks; pgoff_t orig_page_offset = 0, seq_end_page; - int ret1, ret2, depth, last_extent = 0; + int ret, depth, last_extent = 0; int blocks_per_page = PAGE_CACHE_SIZE >> orig_inode->i_blkbits; int data_offset_in_page; int block_len_in_page; int uninit; - /* orig and donor should be different file */ - if (orig_inode->i_ino == donor_inode->i_ino) { + if (orig_inode->i_sb != donor_inode->i_sb) { + ext4_debug("ext4 move extent: The argument files " + "should be in same FS [ino:orig %lu, donor %lu]\n", + orig_inode->i_ino, donor_inode->i_ino); + return -EINVAL; + } + + /* orig and donor should be different inodes */ + if (orig_inode == donor_inode) { ext4_debug("ext4 move extent: The argument files should not " - "be same file [ino:orig %lu, donor %lu]\n", + "be same inode [ino:orig %lu, donor %lu]\n", orig_inode->i_ino, donor_inode->i_ino); return -EINVAL; } @@ -1208,18 +1142,21 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, orig_inode->i_ino, donor_inode->i_ino); return -EINVAL; } - + /* TODO: This is non obvious task to swap blocks for inodes with full + jornaling enabled */ + if (ext4_should_journal_data(orig_inode) || + ext4_should_journal_data(donor_inode)) { + return -EINVAL; + } /* Protect orig and donor inodes against a truncate */ - ret1 = mext_inode_double_lock(orig_inode, donor_inode); - if (ret1 < 0) - return ret1; + mext_inode_double_lock(orig_inode, donor_inode); /* Protect extent tree against block allocations via delalloc */ double_down_write_data_sem(orig_inode, donor_inode); /* Check the filesystem environment whether move_extent can be done */ - ret1 = mext_check_arguments(orig_inode, donor_inode, orig_start, + ret = mext_check_arguments(orig_inode, donor_inode, orig_start, donor_start, &len); - if (ret1) + if (ret) goto out; file_end = (i_size_read(orig_inode) - 1) >> orig_inode->i_blkbits; @@ -1227,13 +1164,13 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, if (file_end < block_end) len -= block_end - file_end; - ret1 = get_ext_path(orig_inode, block_start, &orig_path); - if (ret1) + ret = get_ext_path(orig_inode, block_start, &orig_path); + if (ret) goto out; /* Get path structure to check the hole */ - ret1 = get_ext_path(orig_inode, block_start, &holecheck_path); - if (ret1) + ret = get_ext_path(orig_inode, block_start, &holecheck_path); + if (ret) goto out; depth = ext_depth(orig_inode); @@ -1252,13 +1189,13 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, last_extent = mext_next_extent(orig_inode, holecheck_path, &ext_cur); if (last_extent < 0) { - ret1 = last_extent; + ret = last_extent; goto out; } last_extent = mext_next_extent(orig_inode, orig_path, &ext_dummy); if (last_extent < 0) { - ret1 = last_extent; + ret = last_extent; goto out; } seq_start = le32_to_cpu(ext_cur->ee_block); @@ -1272,7 +1209,7 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, if (le32_to_cpu(ext_cur->ee_block) > block_end) { ext4_debug("ext4 move extent: The specified range of file " "may be the hole\n"); - ret1 = -EINVAL; + ret = -EINVAL; goto out; } @@ -1292,7 +1229,7 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, last_extent = mext_next_extent(orig_inode, holecheck_path, &ext_cur); if (last_extent < 0) { - ret1 = last_extent; + ret = last_extent; break; } add_blocks = ext4_ext_get_actual_len(ext_cur); @@ -1349,18 +1286,18 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, orig_page_offset, data_offset_in_page, block_len_in_page, uninit, - &ret1); + &ret); /* Count how many blocks we have exchanged */ *moved_len += block_len_in_page; - if (ret1 < 0) + if (ret < 0) break; if (*moved_len > len) { EXT4_ERROR_INODE(orig_inode, "We replaced blocks too much! " "sum of replaced: %llu requested: %llu", *moved_len, len); - ret1 = -EIO; + ret = -EIO; break; } @@ -1374,22 +1311,22 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, } double_down_write_data_sem(orig_inode, donor_inode); - if (ret1 < 0) + if (ret < 0) break; /* Decrease buffer counter */ if (holecheck_path) ext4_ext_drop_refs(holecheck_path); - ret1 = get_ext_path(orig_inode, seq_start, &holecheck_path); - if (ret1) + ret = get_ext_path(orig_inode, seq_start, &holecheck_path); + if (ret) break; depth = holecheck_path->p_depth; /* Decrease buffer counter */ if (orig_path) ext4_ext_drop_refs(orig_path); - ret1 = get_ext_path(orig_inode, seq_start, &orig_path); - if (ret1) + ret = get_ext_path(orig_inode, seq_start, &orig_path); + if (ret) break; ext_cur = holecheck_path[depth].p_ext; @@ -1412,12 +1349,7 @@ ext4_move_extents(struct file *o_filp, struct file *d_filp, kfree(holecheck_path); } double_up_write_data_sem(orig_inode, donor_inode); - ret2 = mext_inode_double_unlock(orig_inode, donor_inode); - - if (ret1) - return ret1; - else if (ret2) - return ret2; + mext_inode_double_unlock(orig_inode, donor_inode); - return 0; + return ret; } diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 349d7b3671c..ac769399b14 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -1037,6 +1037,12 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, stru EXT4_ERROR_INODE(dir, "bad inode number: %u", ino); return ERR_PTR(-EIO); } + if (unlikely(ino == dir->i_ino)) { + EXT4_ERROR_INODE(dir, "'%.*s' linked to parent dir", + dentry->d_name.len, + dentry->d_name.name); + return ERR_PTR(-EIO); + } inode = ext4_iget(dir->i_sb, ino); if (inode == ERR_PTR(-ESTALE)) { EXT4_ERROR_INODE(dir, @@ -1795,9 +1801,7 @@ static int ext4_mknod(struct inode *dir, struct dentry *dentry, err = PTR_ERR(inode); if (!IS_ERR(inode)) { init_special_inode(inode, inode->i_mode, rdev); -#ifdef CONFIG_EXT4_FS_XATTR inode->i_op = &ext4_special_inode_operations; -#endif err = ext4_add_nondir(handle, dentry, inode); } ext4_journal_stop(handle); diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index 53589ff8824..231cacb8f64 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c @@ -200,8 +200,11 @@ static void free_flex_gd(struct ext4_new_flex_group_data *flex_gd) * be a partial of a flex group. * * @sb: super block of fs to which the groups belongs + * + * Returns 0 on a successful allocation of the metadata blocks in the + * block group. */ -static void ext4_alloc_group_tables(struct super_block *sb, +static int ext4_alloc_group_tables(struct super_block *sb, struct ext4_new_flex_group_data *flex_gd, int flexbg_size) { @@ -226,6 +229,8 @@ static void ext4_alloc_group_tables(struct super_block *sb, (last_group & ~(flexbg_size - 1)))); next_group: group = group_data[0].group; + if (src_group >= group_data[0].group + flex_gd->count) + return -ENOSPC; start_blk = ext4_group_first_block_no(sb, src_group); last_blk = start_blk + group_data[src_group - group].blocks_count; @@ -235,7 +240,6 @@ static void ext4_alloc_group_tables(struct super_block *sb, start_blk += overhead; - BUG_ON(src_group >= group_data[0].group + flex_gd->count); /* We collect contiguous blocks as much as possible. */ src_group++; for (; src_group <= last_group; src_group++) @@ -300,6 +304,7 @@ static void ext4_alloc_group_tables(struct super_block *sb, group_data[i].free_blocks_count); } } + return 0; } static struct buffer_head *bclean(handle_t *handle, struct super_block *sb, @@ -451,6 +456,9 @@ static int setup_new_flex_group_blocks(struct super_block *sb, gdblocks = ext4_bg_num_gdb(sb, group); start = ext4_group_first_block_no(sb, group); + if (!ext4_bg_has_super(sb, group)) + goto handle_itb; + /* Copy all of the GDT blocks into the backup in this group */ for (j = 0, block = start + 1; j < gdblocks; j++, block++) { struct buffer_head *gdb; @@ -493,6 +501,7 @@ static int setup_new_flex_group_blocks(struct super_block *sb, goto out; } +handle_itb: /* Initialize group tables of the grop @group */ if (!(bg_flags[i] & EXT4_BG_INODE_ZEROED)) goto handle_bb; @@ -1141,7 +1150,7 @@ static void ext4_update_super(struct super_block *sb, struct ext4_new_group_data *group_data = flex_gd->groups; struct ext4_sb_info *sbi = EXT4_SB(sb); struct ext4_super_block *es = sbi->s_es; - int i; + int i, ret; BUG_ON(flex_gd->count == 0 || group_data == NULL); /* @@ -1216,6 +1225,11 @@ static void ext4_update_super(struct super_block *sb, &sbi->s_flex_groups[flex_group].free_inodes); } + /* + * Update the fs overhead information + */ + ext4_calculate_overhead(sb); + if (test_opt(sb, DEBUG)) printk(KERN_DEBUG "EXT4-fs: added group %u:" "%llu blocks(%llu free %llu reserved)\n", flex_gd->count, @@ -1288,13 +1302,15 @@ static int ext4_flex_group_add(struct super_block *sb, err = err2; if (!err) { - int i; + int gdb_num = group / EXT4_DESC_PER_BLOCK(sb); + int gdb_num_end = ((group + flex_gd->count - 1) / + EXT4_DESC_PER_BLOCK(sb)); + update_backups(sb, sbi->s_sbh->b_blocknr, (char *)es, sizeof(struct ext4_super_block)); - for (i = 0; i < flex_gd->count; i++, group++) { + for (; gdb_num <= gdb_num_end; gdb_num++) { struct buffer_head *gdb_bh; - int gdb_num; - gdb_num = group / EXT4_BLOCKS_PER_GROUP(sb); + gdb_bh = sbi->s_group_desc[gdb_num]; update_backups(sb, gdb_bh->b_blocknr, gdb_bh->b_data, gdb_bh->b_size); @@ -1671,7 +1687,8 @@ int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count) */ while (ext4_setup_next_flex_gd(sb, flex_gd, n_blocks_count, flexbg_size)) { - ext4_alloc_group_tables(sb, flex_gd, flexbg_size); + if (ext4_alloc_group_tables(sb, flex_gd, flexbg_size) != 0) + break; err = ext4_flex_group_add(sb, resize_inode, flex_gd); if (unlikely(err)) break; diff --git a/fs/ext4/super.c b/fs/ext4/super.c index a68703a5610..288f4c61e97 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -932,6 +932,7 @@ static struct inode *ext4_alloc_inode(struct super_block *sb) ei->i_reserved_meta_blocks = 0; ei->i_allocated_meta_blocks = 0; ei->i_da_metadata_calc_len = 0; + ei->i_da_metadata_calc_last_lblock = 0; spin_lock_init(&(ei->i_block_reservation_lock)); #ifdef CONFIG_QUOTA ei->i_reserved_quota = 0; @@ -1598,9 +1599,7 @@ static int parse_options(char *options, struct super_block *sb, unsigned int *journal_ioprio, int is_remount) { -#ifdef CONFIG_QUOTA struct ext4_sb_info *sbi = EXT4_SB(sb); -#endif char *p; substring_t args[MAX_OPT_ARGS]; int token; @@ -1649,6 +1648,16 @@ static int parse_options(char *options, struct super_block *sb, } } #endif + if (test_opt(sb, DIOREAD_NOLOCK)) { + int blocksize = + BLOCK_SIZE << le32_to_cpu(sbi->s_es->s_log_block_size); + + if (blocksize < PAGE_CACHE_SIZE) { + ext4_msg(sb, KERN_ERR, "can't mount with " + "dioread_nolock if block size != PAGE_SIZE"); + return 0; + } + } return 1; } @@ -1691,7 +1700,7 @@ static inline void ext4_show_quota_options(struct seq_file *seq, static const char *token2str(int token) { - static const struct match_token *t; + const struct match_token *t; for (t = tokens; t->token != Opt_err; t++) if (t->token == token && !strchr(t->pattern, '=')) @@ -2111,7 +2120,9 @@ static void ext4_orphan_cleanup(struct super_block *sb, __func__, inode->i_ino, inode->i_size); jbd_debug(2, "truncating inode %lu to %lld bytes\n", inode->i_ino, inode->i_size); + mutex_lock(&inode->i_mutex); ext4_truncate(inode); + mutex_unlock(&inode->i_mutex); nr_truncates++; } else { ext4_msg(sb, KERN_DEBUG, @@ -2944,6 +2955,118 @@ static void ext4_destroy_lazyinit_thread(void) kthread_stop(ext4_lazyinit_task); } +/* + * Note: calculating the overhead so we can be compatible with + * historical BSD practice is quite difficult in the face of + * clusters/bigalloc. This is because multiple metadata blocks from + * different block group can end up in the same allocation cluster. + * Calculating the exact overhead in the face of clustered allocation + * requires either O(all block bitmaps) in memory or O(number of block + * groups**2) in time. We will still calculate the superblock for + * older file systems --- and if we come across with a bigalloc file + * system with zero in s_overhead_clusters the estimate will be close to + * correct especially for very large cluster sizes --- but for newer + * file systems, it's better to calculate this figure once at mkfs + * time, and store it in the superblock. If the superblock value is + * present (even for non-bigalloc file systems), we will use it. + */ +static int count_overhead(struct super_block *sb, ext4_group_t grp, + char *buf) +{ + struct ext4_sb_info *sbi = EXT4_SB(sb); + struct ext4_group_desc *gdp; + ext4_fsblk_t first_block, last_block, b; + ext4_group_t i, ngroups = ext4_get_groups_count(sb); + int s, j, count = 0; + + if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_BIGALLOC)) + return (ext4_bg_has_super(sb, grp) + ext4_bg_num_gdb(sb, grp) + + sbi->s_itb_per_group + 2); + + first_block = le32_to_cpu(sbi->s_es->s_first_data_block) + + (grp * EXT4_BLOCKS_PER_GROUP(sb)); + last_block = first_block + EXT4_BLOCKS_PER_GROUP(sb) - 1; + for (i = 0; i < ngroups; i++) { + gdp = ext4_get_group_desc(sb, i, NULL); + b = ext4_block_bitmap(sb, gdp); + if (b >= first_block && b <= last_block) { + ext4_set_bit(EXT4_B2C(sbi, b - first_block), buf); + count++; + } + b = ext4_inode_bitmap(sb, gdp); + if (b >= first_block && b <= last_block) { + ext4_set_bit(EXT4_B2C(sbi, b - first_block), buf); + count++; + } + b = ext4_inode_table(sb, gdp); + if (b >= first_block && b + sbi->s_itb_per_group <= last_block) + for (j = 0; j < sbi->s_itb_per_group; j++, b++) { + int c = EXT4_B2C(sbi, b - first_block); + ext4_set_bit(c, buf); + count++; + } + if (i != grp) + continue; + s = 0; + if (ext4_bg_has_super(sb, grp)) { + ext4_set_bit(s++, buf); + count++; + } + for (j = ext4_bg_num_gdb(sb, grp); j > 0; j--) { + ext4_set_bit(EXT4_B2C(sbi, s++), buf); + count++; + } + } + if (!count) + return 0; + return EXT4_CLUSTERS_PER_GROUP(sb) - + ext4_count_free(buf, EXT4_CLUSTERS_PER_GROUP(sb) / 8); +} + +/* + * Compute the overhead and stash it in sbi->s_overhead + */ +int ext4_calculate_overhead(struct super_block *sb) +{ + struct ext4_sb_info *sbi = EXT4_SB(sb); + struct ext4_super_block *es = sbi->s_es; + ext4_group_t i, ngroups = ext4_get_groups_count(sb); + ext4_fsblk_t overhead = 0; + char *buf = (char *) get_zeroed_page(GFP_KERNEL); + + memset(buf, 0, PAGE_SIZE); + if (!buf) + return -ENOMEM; + + /* + * Compute the overhead (FS structures). This is constant + * for a given filesystem unless the number of block groups + * changes so we cache the previous value until it does. + */ + + /* + * All of the blocks before first_data_block are overhead + */ + overhead = EXT4_B2C(sbi, le32_to_cpu(es->s_first_data_block)); + + /* + * Add the overhead found in each block group + */ + for (i = 0; i < ngroups; i++) { + int blks; + + blks = count_overhead(sb, i, buf); + overhead += blks; + if (blks) + memset(buf, 0, PAGE_SIZE); + cond_resched(); + } + sbi->s_overhead = overhead; + smp_wmb(); + free_page((unsigned long) buf); + return 0; +} + static int ext4_fill_super(struct super_block *sb, void *data, int silent) { char *orig_data = kstrdup(data, GFP_KERNEL); @@ -3113,15 +3236,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) clear_opt(sb, DELALLOC); } - blocksize = BLOCK_SIZE << le32_to_cpu(es->s_log_block_size); - if (test_opt(sb, DIOREAD_NOLOCK)) { - if (blocksize < PAGE_SIZE) { - ext4_msg(sb, KERN_ERR, "can't mount with " - "dioread_nolock if block size != PAGE_SIZE"); - goto failed_mount; - } - } - sb->s_flags = (sb->s_flags & ~MS_POSIXACL) | (test_opt(sb, POSIX_ACL) ? MS_POSIXACL : 0); @@ -3163,6 +3277,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) if (!ext4_feature_set_ok(sb, (sb->s_flags & MS_RDONLY))) goto failed_mount; + blocksize = BLOCK_SIZE << le32_to_cpu(es->s_log_block_size); if (blocksize < EXT4_MIN_BLOCK_SIZE || blocksize > EXT4_MAX_BLOCK_SIZE) { ext4_msg(sb, KERN_ERR, @@ -3558,6 +3673,18 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) percpu_counter_set(&sbi->s_dirtyclusters_counter, 0); no_journal: + /* + * Get the # of file system overhead blocks from the + * superblock if present. + */ + if (es->s_overhead_clusters) + sbi->s_overhead = le32_to_cpu(es->s_overhead_clusters); + else { + ret = ext4_calculate_overhead(sb); + if (ret) + goto failed_mount_wq; + } + /* * The maximum number of concurrent works can be high and * concurrency isn't really necessary. Limit it to 1. @@ -4107,6 +4234,7 @@ static void ext4_clear_journal_err(struct super_block *sb, ext4_commit_super(sb, 1); jbd2_journal_clear_err(journal); + jbd2_journal_update_sb_errno(journal); } } @@ -4380,7 +4508,7 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data) } ext4_setup_system_zone(sb); - if (sbi->s_journal == NULL) + if (sbi->s_journal == NULL && !(old_sb_flags & MS_RDONLY)) ext4_commit_super(sb, 1); #ifdef CONFIG_QUOTA @@ -4421,67 +4549,21 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data) return err; } -/* - * Note: calculating the overhead so we can be compatible with - * historical BSD practice is quite difficult in the face of - * clusters/bigalloc. This is because multiple metadata blocks from - * different block group can end up in the same allocation cluster. - * Calculating the exact overhead in the face of clustered allocation - * requires either O(all block bitmaps) in memory or O(number of block - * groups**2) in time. We will still calculate the superblock for - * older file systems --- and if we come across with a bigalloc file - * system with zero in s_overhead_clusters the estimate will be close to - * correct especially for very large cluster sizes --- but for newer - * file systems, it's better to calculate this figure once at mkfs - * time, and store it in the superblock. If the superblock value is - * present (even for non-bigalloc file systems), we will use it. - */ static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf) { struct super_block *sb = dentry->d_sb; struct ext4_sb_info *sbi = EXT4_SB(sb); struct ext4_super_block *es = sbi->s_es; - struct ext4_group_desc *gdp; + ext4_fsblk_t overhead = 0; u64 fsid; s64 bfree; - if (test_opt(sb, MINIX_DF)) { - sbi->s_overhead_last = 0; - } else if (es->s_overhead_clusters) { - sbi->s_overhead_last = le32_to_cpu(es->s_overhead_clusters); - } else if (sbi->s_blocks_last != ext4_blocks_count(es)) { - ext4_group_t i, ngroups = ext4_get_groups_count(sb); - ext4_fsblk_t overhead = 0; - - /* - * Compute the overhead (FS structures). This is constant - * for a given filesystem unless the number of block groups - * changes so we cache the previous value until it does. - */ - - /* - * All of the blocks before first_data_block are - * overhead - */ - overhead = EXT4_B2C(sbi, le32_to_cpu(es->s_first_data_block)); - - /* - * Add the overhead found in each block group - */ - for (i = 0; i < ngroups; i++) { - gdp = ext4_get_group_desc(sb, i, NULL); - overhead += ext4_num_overhead_clusters(sb, i, gdp); - cond_resched(); - } - sbi->s_overhead_last = overhead; - smp_wmb(); - sbi->s_blocks_last = ext4_blocks_count(es); - } + if (!test_opt(sb, MINIX_DF)) + overhead = sbi->s_overhead; buf->f_type = EXT4_SUPER_MAGIC; buf->f_bsize = sb->s_blocksize; - buf->f_blocks = (ext4_blocks_count(es) - - EXT4_C2B(sbi, sbi->s_overhead_last)); + buf->f_blocks = ext4_blocks_count(es) - EXT4_C2B(sbi, sbi->s_overhead); bfree = percpu_counter_sum_positive(&sbi->s_freeclusters_counter) - percpu_counter_sum_positive(&sbi->s_dirtyclusters_counter); /* prevent underflow in case that few free space is available */ diff --git a/fs/fifo.c b/fs/fifo.c index b1a524d798e..cf6f4345ceb 100644 --- a/fs/fifo.c +++ b/fs/fifo.c @@ -14,7 +14,7 @@ #include #include -static void wait_for_partner(struct inode* inode, unsigned int *cnt) +static int wait_for_partner(struct inode* inode, unsigned int *cnt) { int cur = *cnt; @@ -23,6 +23,7 @@ static void wait_for_partner(struct inode* inode, unsigned int *cnt) if (signal_pending(current)) break; } + return cur == *cnt ? -ERESTARTSYS : 0; } static void wake_up_partner(struct inode* inode) @@ -67,8 +68,7 @@ static int fifo_open(struct inode *inode, struct file *filp) * seen a writer */ filp->f_version = pipe->w_counter; } else { - wait_for_partner(inode, &pipe->w_counter); - if(signal_pending(current)) + if (wait_for_partner(inode, &pipe->w_counter)) goto err_rd; } } @@ -90,8 +90,7 @@ static int fifo_open(struct inode *inode, struct file *filp) wake_up_partner(inode); if (!pipe->readers) { - wait_for_partner(inode, &pipe->r_counter); - if (signal_pending(current)) + if (wait_for_partner(inode, &pipe->r_counter)) goto err_wr; } break; diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index ceb3b29c8cd..1f81f70dda6 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -1580,6 +1580,7 @@ static int fuse_retrieve(struct fuse_conn *fc, struct inode *inode, req->pages[req->num_pages] = page; req->num_pages++; + offset = 0; num -= this_num; total_len += this_num; index++; diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 6b8322225a1..d96318baa13 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -1734,7 +1734,7 @@ static int fuse_verify_ioctl_iov(struct iovec *iov, size_t count) size_t n; u32 max = FUSE_MAX_PAGES_PER_REQ << PAGE_SHIFT; - for (n = 0; n < count; n++) { + for (n = 0; n < count; n++, iov++) { if (iov->iov_len > (size_t) max) return -ENOMEM; max -= iov->iov_len; diff --git a/fs/gfs2/export.c b/fs/gfs2/export.c index 70ba891654f..fdef7f0e28a 100644 --- a/fs/gfs2/export.c +++ b/fs/gfs2/export.c @@ -168,6 +168,8 @@ static struct dentry *gfs2_fh_to_dentry(struct super_block *sb, struct fid *fid, case GFS2_SMALL_FH_SIZE: case GFS2_LARGE_FH_SIZE: case GFS2_OLD_FH_SIZE: + if (fh_len < GFS2_SMALL_FH_SIZE) + return NULL; this.no_formal_ino = ((u64)be32_to_cpu(fh[0])) << 32; this.no_formal_ino |= be32_to_cpu(fh[1]); this.no_addr = ((u64)be32_to_cpu(fh[2])) << 32; @@ -187,6 +189,8 @@ static struct dentry *gfs2_fh_to_parent(struct super_block *sb, struct fid *fid, switch (fh_type) { case GFS2_LARGE_FH_SIZE: case GFS2_OLD_FH_SIZE: + if (fh_len < GFS2_LARGE_FH_SIZE) + return NULL; parent.no_formal_ino = ((u64)be32_to_cpu(fh[4])) << 32; parent.no_formal_ino |= be32_to_cpu(fh[5]); parent.no_addr = ((u64)be32_to_cpu(fh[6])) << 32; diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c index 6b1efb594d9..a392e32af48 100644 --- a/fs/gfs2/lops.c +++ b/fs/gfs2/lops.c @@ -258,16 +258,14 @@ static void buf_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le) struct gfs2_meta_header *mh; struct gfs2_trans *tr; - lock_buffer(bd->bd_bh); - gfs2_log_lock(sdp); if (!list_empty(&bd->bd_list_tr)) - goto out; + return; tr = current->journal_info; tr->tr_touched = 1; tr->tr_num_buf++; list_add(&bd->bd_list_tr, &tr->tr_list_buf); if (!list_empty(&le->le_list)) - goto out; + return; set_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags); set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags); gfs2_meta_check(sdp, bd->bd_bh); @@ -278,9 +276,6 @@ static void buf_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le) sdp->sd_log_num_buf++; list_add(&le->le_list, &sdp->sd_log_le_buf); tr->tr_num_buf_new++; -out: - gfs2_log_unlock(sdp); - unlock_buffer(bd->bd_bh); } static void buf_lo_before_commit(struct gfs2_sbd *sdp) @@ -611,11 +606,9 @@ static void databuf_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le) struct address_space *mapping = bd->bd_bh->b_page->mapping; struct gfs2_inode *ip = GFS2_I(mapping->host); - lock_buffer(bd->bd_bh); - gfs2_log_lock(sdp); if (tr) { if (!list_empty(&bd->bd_list_tr)) - goto out; + return; tr->tr_touched = 1; if (gfs2_is_jdata(ip)) { tr->tr_num_buf++; @@ -623,7 +616,7 @@ static void databuf_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le) } } if (!list_empty(&le->le_list)) - goto out; + return; set_bit(GLF_LFLUSH, &bd->bd_gl->gl_flags); set_bit(GLF_DIRTY, &bd->bd_gl->gl_flags); @@ -635,9 +628,6 @@ static void databuf_lo_add(struct gfs2_sbd *sdp, struct gfs2_log_element *le) } else { list_add_tail(&le->le_list, &sdp->sd_log_le_ordered); } -out: - gfs2_log_unlock(sdp); - unlock_buffer(bd->bd_bh); } static void gfs2_check_magic(struct buffer_head *bh) diff --git a/fs/gfs2/trans.c b/fs/gfs2/trans.c index 86ac75d99d3..6ab2a77e772 100644 --- a/fs/gfs2/trans.c +++ b/fs/gfs2/trans.c @@ -145,14 +145,22 @@ void gfs2_trans_add_bh(struct gfs2_glock *gl, struct buffer_head *bh, int meta) struct gfs2_sbd *sdp = gl->gl_sbd; struct gfs2_bufdata *bd; + lock_buffer(bh); + gfs2_log_lock(sdp); bd = bh->b_private; if (bd) gfs2_assert(sdp, bd->bd_gl == gl); else { + gfs2_log_unlock(sdp); + unlock_buffer(bh); gfs2_attach_bufdata(gl, bh, meta); bd = bh->b_private; + lock_buffer(bh); + gfs2_log_lock(sdp); } lops_add(sdp, &bd->bd_le); + gfs2_log_unlock(sdp); + unlock_buffer(bh); } void gfs2_trans_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd) diff --git a/fs/isofs/export.c b/fs/isofs/export.c index dd4687ff30d..516eb21895c 100644 --- a/fs/isofs/export.c +++ b/fs/isofs/export.c @@ -179,7 +179,7 @@ static struct dentry *isofs_fh_to_parent(struct super_block *sb, { struct isofs_fid *ifid = (struct isofs_fid *)fid; - if (fh_type != 2) + if (fh_len < 2 || fh_type != 2) return NULL; return isofs_export_iget(sb, diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c index f2b9a571f4c..9626bc8cbbd 100644 --- a/fs/jbd/commit.c +++ b/fs/jbd/commit.c @@ -86,7 +86,12 @@ static void release_buffer_page(struct buffer_head *bh) static void release_data_buffer(struct buffer_head *bh) { if (buffer_freed(bh)) { + WARN_ON_ONCE(buffer_dirty(bh)); clear_buffer_freed(bh); + clear_buffer_mapped(bh); + clear_buffer_new(bh); + clear_buffer_req(bh); + bh->b_bdev = NULL; release_buffer_page(bh); } else put_bh(bh); @@ -853,17 +858,35 @@ void journal_commit_transaction(journal_t *journal) * there's no point in keeping a checkpoint record for * it. */ - /* A buffer which has been freed while still being - * journaled by a previous transaction may end up still - * being dirty here, but we want to avoid writing back - * that buffer in the future after the "add to orphan" - * operation been committed, That's not only a performance - * gain, it also stops aliasing problems if the buffer is - * left behind for writeback and gets reallocated for another - * use in a different page. */ - if (buffer_freed(bh) && !jh->b_next_transaction) { - clear_buffer_freed(bh); - clear_buffer_jbddirty(bh); + /* + * A buffer which has been freed while still being journaled by + * a previous transaction. + */ + if (buffer_freed(bh)) { + /* + * If the running transaction is the one containing + * "add to orphan" operation (b_next_transaction != + * NULL), we have to wait for that transaction to + * commit before we can really get rid of the buffer. + * So just clear b_modified to not confuse transaction + * credit accounting and refile the buffer to + * BJ_Forget of the running transaction. If the just + * committed transaction contains "add to orphan" + * operation, we can completely invalidate the buffer + * now. We are rather throughout in that since the + * buffer may be still accessible when blocksize < + * pagesize and it is attached to the last partial + * page. + */ + jh->b_modified = 0; + if (!jh->b_next_transaction) { + clear_buffer_freed(bh); + clear_buffer_jbddirty(bh); + clear_buffer_mapped(bh); + clear_buffer_new(bh); + clear_buffer_req(bh); + bh->b_bdev = NULL; + } } if (buffer_jbddirty(bh)) { diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c index b2a7e5244e3..ee959a9fed6 100644 --- a/fs/jbd/transaction.c +++ b/fs/jbd/transaction.c @@ -1845,15 +1845,16 @@ static int __dispose_buffer(struct journal_head *jh, transaction_t *transaction) * We're outside-transaction here. Either or both of j_running_transaction * and j_committing_transaction may be NULL. */ -static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh) +static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh, + int partial_page) { transaction_t *transaction; struct journal_head *jh; int may_free = 1; - int ret; BUFFER_TRACE(bh, "entry"); +retry: /* * It is safe to proceed here without the j_list_lock because the * buffers cannot be stolen by try_to_free_buffers as long as we are @@ -1881,10 +1882,18 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh) * clear the buffer dirty bit at latest at the moment when the * transaction marking the buffer as freed in the filesystem * structures is committed because from that moment on the - * buffer can be reallocated and used by a different page. + * block can be reallocated and used by a different page. * Since the block hasn't been freed yet but the inode has * already been added to orphan list, it is safe for us to add * the buffer to BJ_Forget list of the newest transaction. + * + * Also we have to clear buffer_mapped flag of a truncated buffer + * because the buffer_head may be attached to the page straddling + * i_size (can happen only when blocksize < pagesize) and thus the + * buffer_head can be reused when the file is extended again. So we end + * up keeping around invalidated buffers attached to transactions' + * BJ_Forget list just to stop checkpointing code from cleaning up + * the transaction this buffer was modified in. */ transaction = jh->b_transaction; if (transaction == NULL) { @@ -1911,13 +1920,9 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh) * committed, the buffer won't be needed any * longer. */ JBUFFER_TRACE(jh, "checkpointed: add to BJ_Forget"); - ret = __dispose_buffer(jh, + may_free = __dispose_buffer(jh, journal->j_running_transaction); - journal_put_journal_head(jh); - spin_unlock(&journal->j_list_lock); - jbd_unlock_bh_state(bh); - spin_unlock(&journal->j_state_lock); - return ret; + goto zap_buffer; } else { /* There is no currently-running transaction. So the * orphan record which we wrote for this file must have @@ -1925,13 +1930,9 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh) * the committing transaction, if it exists. */ if (journal->j_committing_transaction) { JBUFFER_TRACE(jh, "give to committing trans"); - ret = __dispose_buffer(jh, + may_free = __dispose_buffer(jh, journal->j_committing_transaction); - journal_put_journal_head(jh); - spin_unlock(&journal->j_list_lock); - jbd_unlock_bh_state(bh); - spin_unlock(&journal->j_state_lock); - return ret; + goto zap_buffer; } else { /* The orphan record's transaction has * committed. We can cleanse this buffer */ @@ -1952,10 +1953,26 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh) } /* * The buffer is committing, we simply cannot touch - * it. So we just set j_next_transaction to the - * running transaction (if there is one) and mark - * buffer as freed so that commit code knows it should - * clear dirty bits when it is done with the buffer. + * it. If the page is straddling i_size we have to wait + * for commit and try again. + */ + if (partial_page) { + tid_t tid = journal->j_committing_transaction->t_tid; + + journal_put_journal_head(jh); + spin_unlock(&journal->j_list_lock); + jbd_unlock_bh_state(bh); + spin_unlock(&journal->j_state_lock); + unlock_buffer(bh); + log_wait_commit(journal, tid); + lock_buffer(bh); + goto retry; + } + /* + * OK, buffer won't be reachable after truncate. We just set + * j_next_transaction to the running transaction (if there is + * one) and mark buffer as freed so that commit code knows it + * should clear dirty bits when it is done with the buffer. */ set_buffer_freed(bh); if (journal->j_running_transaction && buffer_jbddirty(bh)) @@ -1978,6 +1995,14 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh) } zap_buffer: + /* + * This is tricky. Although the buffer is truncated, it may be reused + * if blocksize < pagesize and it is attached to the page straddling + * EOF. Since the buffer might have been added to BJ_Forget list of the + * running transaction, journal_get_write_access() won't clear + * b_modified and credit accounting gets confused. So clear b_modified + * here. */ + jh->b_modified = 0; journal_put_journal_head(jh); zap_buffer_no_jh: spin_unlock(&journal->j_list_lock); @@ -2026,7 +2051,8 @@ void journal_invalidatepage(journal_t *journal, if (offset <= curr_off) { /* This block is wholly outside the truncation point */ lock_buffer(bh); - may_free &= journal_unmap_buffer(journal, bh); + may_free &= journal_unmap_buffer(journal, bh, + offset > 0); unlock_buffer(bh); } curr_off = next_off; diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index 2791a222bd7..d343ac76909 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c @@ -1317,6 +1317,11 @@ static void jbd2_mark_journal_empty(journal_t *journal) BUG_ON(!mutex_is_locked(&journal->j_checkpoint_mutex)); read_lock(&journal->j_state_lock); + /* Is it already empty? */ + if (sb->s_start == 0) { + read_unlock(&journal->j_state_lock); + return; + } jbd_debug(1, "JBD2: Marking journal as empty (seq %d)\n", journal->j_tail_sequence); @@ -1340,7 +1345,7 @@ static void jbd2_mark_journal_empty(journal_t *journal) * Update a journal's errno. Write updated superblock to disk waiting for IO * to complete. */ -static void jbd2_journal_update_sb_errno(journal_t *journal) +void jbd2_journal_update_sb_errno(journal_t *journal) { journal_superblock_t *sb = journal->j_superblock; @@ -1352,6 +1357,7 @@ static void jbd2_journal_update_sb_errno(journal_t *journal) jbd2_write_superblock(journal, WRITE_SYNC); } +EXPORT_SYMBOL(jbd2_journal_update_sb_errno); /* * Read the superblock for a given journal, performing initial diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c index db3889ba881..8608f877914 100644 --- a/fs/jffs2/file.c +++ b/fs/jffs2/file.c @@ -138,33 +138,39 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping, struct page *pg; struct inode *inode = mapping->host; struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); + struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); + struct jffs2_raw_inode ri; + uint32_t alloc_len = 0; pgoff_t index = pos >> PAGE_CACHE_SHIFT; uint32_t pageofs = index << PAGE_CACHE_SHIFT; int ret = 0; + jffs2_dbg(1, "%s()\n", __func__); + + if (pageofs > inode->i_size) { + ret = jffs2_reserve_space(c, sizeof(ri), &alloc_len, + ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); + if (ret) + return ret; + } + + mutex_lock(&f->sem); pg = grab_cache_page_write_begin(mapping, index, flags); - if (!pg) + if (!pg) { + if (alloc_len) + jffs2_complete_reservation(c); + mutex_unlock(&f->sem); return -ENOMEM; + } *pagep = pg; - jffs2_dbg(1, "%s()\n", __func__); - - if (pageofs > inode->i_size) { + if (alloc_len) { /* Make new hole frag from old EOF to new page */ - struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); - struct jffs2_raw_inode ri; struct jffs2_full_dnode *fn; - uint32_t alloc_len; jffs2_dbg(1, "Writing new hole frag 0x%x-0x%x between current EOF and new page\n", (unsigned int)inode->i_size, pageofs); - ret = jffs2_reserve_space(c, sizeof(ri), &alloc_len, - ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); - if (ret) - goto out_page; - - mutex_lock(&f->sem); memset(&ri, 0, sizeof(ri)); ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); @@ -191,7 +197,6 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping, if (IS_ERR(fn)) { ret = PTR_ERR(fn); jffs2_complete_reservation(c); - mutex_unlock(&f->sem); goto out_page; } ret = jffs2_add_full_dnode_to_inode(c, f, fn); @@ -206,12 +211,10 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping, jffs2_mark_node_obsolete(c, fn->raw); jffs2_free_full_dnode(fn); jffs2_complete_reservation(c); - mutex_unlock(&f->sem); goto out_page; } jffs2_complete_reservation(c); inode->i_size = pageofs; - mutex_unlock(&f->sem); } /* @@ -220,18 +223,18 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping, * case of a short-copy. */ if (!PageUptodate(pg)) { - mutex_lock(&f->sem); ret = jffs2_do_readpage_nolock(inode, pg); - mutex_unlock(&f->sem); if (ret) goto out_page; } + mutex_unlock(&f->sem); jffs2_dbg(1, "end write_begin(). pg->flags %lx\n", pg->flags); return ret; out_page: unlock_page(pg); page_cache_release(pg); + mutex_unlock(&f->sem); return ret; } diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c index 6784d1e7a7e..ffa8f12c7a5 100644 --- a/fs/jffs2/nodemgmt.c +++ b/fs/jffs2/nodemgmt.c @@ -375,14 +375,16 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, spin_unlock(&c->erase_completion_lock); ret = jffs2_prealloc_raw_node_refs(c, jeb, 1); - if (ret) - return ret; + /* Just lock it again and continue. Nothing much can change because we hold c->alloc_sem anyway. In fact, it's not entirely clear why we hold c->erase_completion_lock in the majority of this function... but that's a question for another (more caffeine-rich) day. */ spin_lock(&c->erase_completion_lock); + if (ret) + return ret; + waste = jeb->free_size; jffs2_link_node_ref(c, jeb, (jeb->offset + c->sector_size - waste) | REF_OBSOLETE, diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c index 74d9be19df3..6bec5c0bc26 100644 --- a/fs/jffs2/wbuf.c +++ b/fs/jffs2/wbuf.c @@ -1043,10 +1043,10 @@ int jffs2_check_oob_empty(struct jffs2_sb_info *c, ops.datbuf = NULL; ret = mtd_read_oob(c->mtd, jeb->offset, &ops); - if (ret || ops.oobretlen != ops.ooblen) { + if ((ret && !mtd_is_bitflip(ret)) || ops.oobretlen != ops.ooblen) { pr_err("cannot read OOB for EB at %08x, requested %zd bytes, read %zd bytes, error %d\n", jeb->offset, ops.ooblen, ops.oobretlen, ret); - if (!ret) + if (!ret || mtd_is_bitflip(ret)) ret = -EIO; return ret; } @@ -1085,10 +1085,10 @@ int jffs2_check_nand_cleanmarker(struct jffs2_sb_info *c, ops.datbuf = NULL; ret = mtd_read_oob(c->mtd, jeb->offset, &ops); - if (ret || ops.oobretlen != ops.ooblen) { + if ((ret && !mtd_is_bitflip(ret)) || ops.oobretlen != ops.ooblen) { pr_err("cannot read OOB for EB at %08x, requested %zd bytes, read %zd bytes, error %d\n", jeb->offset, ops.ooblen, ops.oobretlen, ret); - if (!ret) + if (!ret || mtd_is_bitflip(ret)) ret = -EIO; return ret; } diff --git a/fs/lockd/clntxdr.c b/fs/lockd/clntxdr.c index d269ada7670..982d2676e1f 100644 --- a/fs/lockd/clntxdr.c +++ b/fs/lockd/clntxdr.c @@ -223,7 +223,7 @@ static void encode_nlm_stat(struct xdr_stream *xdr, { __be32 *p; - BUG_ON(be32_to_cpu(stat) > NLM_LCK_DENIED_GRACE_PERIOD); + WARN_ON_ONCE(be32_to_cpu(stat) > NLM_LCK_DENIED_GRACE_PERIOD); p = xdr_reserve_space(xdr, 4); *p = stat; } diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c index 7ef14b3c5be..606a8dd8818 100644 --- a/fs/lockd/mon.c +++ b/fs/lockd/mon.c @@ -40,6 +40,7 @@ struct nsm_args { u32 proc; char *mon_name; + char *nodename; }; struct nsm_res { @@ -94,6 +95,7 @@ static int nsm_mon_unmon(struct nsm_handle *nsm, u32 proc, struct nsm_res *res, .vers = 3, .proc = NLMPROC_NSM_NOTIFY, .mon_name = nsm->sm_mon_name, + .nodename = utsname()->nodename, }; struct rpc_message msg = { .rpc_argp = &args, @@ -430,7 +432,7 @@ static void encode_my_id(struct xdr_stream *xdr, const struct nsm_args *argp) { __be32 *p; - encode_nsm_string(xdr, utsname()->nodename); + encode_nsm_string(xdr, argp->nodename); p = xdr_reserve_space(xdr, 4 + 4 + 4); *p++ = cpu_to_be32(argp->prog); *p++ = cpu_to_be32(argp->vers); diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c index 3250f280a17..58ddc38cfcc 100644 --- a/fs/lockd/svc.c +++ b/fs/lockd/svc.c @@ -251,10 +251,9 @@ static int make_socks(struct svc_serv *serv, struct net *net) return err; } -static int lockd_up_net(struct net *net) +static int lockd_up_net(struct svc_serv *serv, struct net *net) { struct lockd_net *ln = net_generic(net, lockd_net_id); - struct svc_serv *serv = nlmsvc_rqst->rq_server; int error; if (ln->nlmsvc_users++) @@ -276,10 +275,9 @@ static int lockd_up_net(struct net *net) return error; } -static void lockd_down_net(struct net *net) +static void lockd_down_net(struct svc_serv *serv, struct net *net) { struct lockd_net *ln = net_generic(net, lockd_net_id); - struct svc_serv *serv = nlmsvc_rqst->rq_server; if (ln->nlmsvc_users) { if (--ln->nlmsvc_users == 0) { @@ -307,7 +305,7 @@ int lockd_up(struct net *net) * Check whether we're already up and running. */ if (nlmsvc_rqst) { - error = lockd_up_net(net); + error = lockd_up_net(nlmsvc_rqst->rq_server, net); goto out; } @@ -378,7 +376,7 @@ int lockd_up(struct net *net) return error; err_start: - lockd_down_net(net); + lockd_down_net(serv, net); goto destroy_and_out; } EXPORT_SYMBOL_GPL(lockd_up); @@ -390,7 +388,7 @@ void lockd_down(struct net *net) { mutex_lock(&nlmsvc_mutex); - lockd_down_net(net); + lockd_down_net(nlmsvc_rqst->rq_server, net); if (nlmsvc_users) { if (--nlmsvc_users) goto out; diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c index d27aab11f32..d413af338da 100644 --- a/fs/lockd/svcproc.c +++ b/fs/lockd/svcproc.c @@ -67,7 +67,8 @@ nlmsvc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp, /* Obtain file pointer. Not used by FREE_ALL call. */ if (filp != NULL) { - if ((error = nlm_lookup_file(rqstp, &file, &lock->fh)) != 0) + error = cast_status(nlm_lookup_file(rqstp, &file, &lock->fh)); + if (error != 0) goto no_locks; *filp = file; diff --git a/fs/locks.c b/fs/locks.c index 0d68f1f8179..fcc50ab71cc 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -308,7 +308,7 @@ static int flock_make_lock(struct file *filp, struct file_lock **lock, return 0; } -static int assign_type(struct file_lock *fl, int type) +static int assign_type(struct file_lock *fl, long type) { switch (type) { case F_RDLCK: @@ -445,7 +445,7 @@ static const struct lock_manager_operations lease_manager_ops = { /* * Initialize a lease, use the default lock manager operations */ -static int lease_init(struct file *filp, int type, struct file_lock *fl) +static int lease_init(struct file *filp, long type, struct file_lock *fl) { if (assign_type(fl, type) != 0) return -EINVAL; @@ -463,7 +463,7 @@ static int lease_init(struct file *filp, int type, struct file_lock *fl) } /* Allocate a file_lock initialised to this type of lease */ -static struct file_lock *lease_alloc(struct file *filp, int type) +static struct file_lock *lease_alloc(struct file *filp, long type) { struct file_lock *fl = locks_alloc_lock(); int error = -ENOMEM; @@ -1465,7 +1465,7 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp) case F_WRLCK: return generic_add_lease(filp, arg, flp); default: - BUG(); + return -EINVAL; } } EXPORT_SYMBOL(generic_setlease); diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c index 7f6a23f0244..d16dae2a9b2 100644 --- a/fs/nfs/blocklayout/blocklayout.c +++ b/fs/nfs/blocklayout/blocklayout.c @@ -162,25 +162,39 @@ static struct bio *bl_alloc_init_bio(int npg, sector_t isect, return bio; } -static struct bio *bl_add_page_to_bio(struct bio *bio, int npg, int rw, +static struct bio *do_add_page_to_bio(struct bio *bio, int npg, int rw, sector_t isect, struct page *page, struct pnfs_block_extent *be, void (*end_io)(struct bio *, int err), - struct parallel_io *par) + struct parallel_io *par, + unsigned int offset, int len) { + isect = isect + (offset >> SECTOR_SHIFT); + dprintk("%s: npg %d rw %d isect %llu offset %u len %d\n", __func__, + npg, rw, (unsigned long long)isect, offset, len); retry: if (!bio) { bio = bl_alloc_init_bio(npg, isect, be, end_io, par); if (!bio) return ERR_PTR(-ENOMEM); } - if (bio_add_page(bio, page, PAGE_CACHE_SIZE, 0) < PAGE_CACHE_SIZE) { + if (bio_add_page(bio, page, len, offset) < len) { bio = bl_submit_bio(rw, bio); goto retry; } return bio; } +static struct bio *bl_add_page_to_bio(struct bio *bio, int npg, int rw, + sector_t isect, struct page *page, + struct pnfs_block_extent *be, + void (*end_io)(struct bio *, int err), + struct parallel_io *par) +{ + return do_add_page_to_bio(bio, npg, rw, isect, page, be, + end_io, par, 0, PAGE_CACHE_SIZE); +} + /* This is basically copied from mpage_end_io_read */ static void bl_end_io_read(struct bio *bio, int err) { @@ -443,6 +457,107 @@ map_block(struct buffer_head *bh, sector_t isect, struct pnfs_block_extent *be) return; } +static void +bl_read_single_end_io(struct bio *bio, int error) +{ + struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1; + struct page *page = bvec->bv_page; + + /* Only one page in bvec */ + unlock_page(page); +} + +static int +bl_do_readpage_sync(struct page *page, struct pnfs_block_extent *be, + unsigned int offset, unsigned int len) +{ + struct bio *bio; + struct page *shadow_page; + sector_t isect; + char *kaddr, *kshadow_addr; + int ret = 0; + + dprintk("%s: offset %u len %u\n", __func__, offset, len); + + shadow_page = alloc_page(GFP_NOFS | __GFP_HIGHMEM); + if (shadow_page == NULL) + return -ENOMEM; + + bio = bio_alloc(GFP_NOIO, 1); + if (bio == NULL) + return -ENOMEM; + + isect = (page->index << PAGE_CACHE_SECTOR_SHIFT) + + (offset / SECTOR_SIZE); + + bio->bi_sector = isect - be->be_f_offset + be->be_v_offset; + bio->bi_bdev = be->be_mdev; + bio->bi_end_io = bl_read_single_end_io; + + lock_page(shadow_page); + if (bio_add_page(bio, shadow_page, + SECTOR_SIZE, round_down(offset, SECTOR_SIZE)) == 0) { + unlock_page(shadow_page); + bio_put(bio); + return -EIO; + } + + submit_bio(READ, bio); + wait_on_page_locked(shadow_page); + if (unlikely(!test_bit(BIO_UPTODATE, &bio->bi_flags))) { + ret = -EIO; + } else { + kaddr = kmap_atomic(page); + kshadow_addr = kmap_atomic(shadow_page); + memcpy(kaddr + offset, kshadow_addr + offset, len); + kunmap_atomic(kshadow_addr); + kunmap_atomic(kaddr); + } + __free_page(shadow_page); + bio_put(bio); + + return ret; +} + +static int +bl_read_partial_page_sync(struct page *page, struct pnfs_block_extent *be, + unsigned int dirty_offset, unsigned int dirty_len, + bool full_page) +{ + int ret = 0; + unsigned int start, end; + + if (full_page) { + start = 0; + end = PAGE_CACHE_SIZE; + } else { + start = round_down(dirty_offset, SECTOR_SIZE); + end = round_up(dirty_offset + dirty_len, SECTOR_SIZE); + } + + dprintk("%s: offset %u len %d\n", __func__, dirty_offset, dirty_len); + if (!be) { + zero_user_segments(page, start, dirty_offset, + dirty_offset + dirty_len, end); + if (start == 0 && end == PAGE_CACHE_SIZE && + trylock_page(page)) { + SetPageUptodate(page); + unlock_page(page); + } + return ret; + } + + if (start != dirty_offset) + ret = bl_do_readpage_sync(page, be, start, + dirty_offset - start); + + if (!ret && (dirty_offset + dirty_len < end)) + ret = bl_do_readpage_sync(page, be, dirty_offset + dirty_len, + end - dirty_offset - dirty_len); + + return ret; +} + /* Given an unmapped page, zero it or read in page for COW, page is locked * by caller. */ @@ -476,7 +591,6 @@ init_page_for_write(struct page *page, struct pnfs_block_extent *cow_read) SetPageUptodate(page); cleanup: - bl_put_extent(cow_read); if (bh) free_buffer_head(bh); if (ret) { @@ -547,6 +661,7 @@ bl_write_pagelist(struct nfs_write_data *wdata, int sync) struct parallel_io *par; loff_t offset = wdata->args.offset; size_t count = wdata->args.count; + unsigned int pg_offset, pg_len, saved_len; struct page **pages = wdata->args.pages; struct page *page; pgoff_t index; @@ -651,10 +766,11 @@ bl_write_pagelist(struct nfs_write_data *wdata, int sync) if (!extent_length) { /* We've used up the previous extent */ bl_put_extent(be); + bl_put_extent(cow_read); bio = bl_submit_bio(WRITE, bio); /* Get the next one */ be = bl_find_get_extent(BLK_LSEG2EXT(wdata->lseg), - isect, NULL); + isect, &cow_read); if (!be || !is_writable(be, isect)) { wdata->pnfs_error = -EINVAL; goto out; @@ -671,7 +787,26 @@ bl_write_pagelist(struct nfs_write_data *wdata, int sync) extent_length = be->be_length - (isect - be->be_f_offset); } - if (be->be_state == PNFS_BLOCK_INVALID_DATA) { + + dprintk("%s offset %lld count %Zu\n", __func__, offset, count); + pg_offset = offset & ~PAGE_CACHE_MASK; + if (pg_offset + count > PAGE_CACHE_SIZE) + pg_len = PAGE_CACHE_SIZE - pg_offset; + else + pg_len = count; + + saved_len = pg_len; + if (be->be_state == PNFS_BLOCK_INVALID_DATA && + !bl_is_sector_init(be->be_inval, isect)) { + ret = bl_read_partial_page_sync(pages[i], cow_read, + pg_offset, pg_len, true); + if (ret) { + dprintk("%s bl_read_partial_page_sync fail %d\n", + __func__, ret); + wdata->pnfs_error = ret; + goto out; + } + ret = bl_mark_sectors_init(be->be_inval, isect, PAGE_CACHE_SECTORS); if (unlikely(ret)) { @@ -680,15 +815,33 @@ bl_write_pagelist(struct nfs_write_data *wdata, int sync) wdata->pnfs_error = ret; goto out; } + + /* Expand to full page write */ + pg_offset = 0; + pg_len = PAGE_CACHE_SIZE; + } else if ((pg_offset & (SECTOR_SIZE - 1)) || + (pg_len & (SECTOR_SIZE - 1))) { + /* ahh, nasty case. We have to do sync full sector + * read-modify-write cycles. + */ + unsigned int saved_offset = pg_offset; + ret = bl_read_partial_page_sync(pages[i], be, pg_offset, + pg_len, false); + pg_offset = round_down(pg_offset, SECTOR_SIZE); + pg_len = round_up(saved_offset + pg_len, SECTOR_SIZE) + - pg_offset; } - bio = bl_add_page_to_bio(bio, wdata->npages - i, WRITE, + bio = do_add_page_to_bio(bio, wdata->npages - i, WRITE, isect, pages[i], be, - bl_end_io_write, par); + bl_end_io_write, par, + pg_offset, pg_len); if (IS_ERR(bio)) { wdata->pnfs_error = PTR_ERR(bio); bio = NULL; goto out; } + offset += saved_len; + count -= saved_len; isect += PAGE_CACHE_SECTORS; last_isect = isect; extent_length -= PAGE_CACHE_SECTORS; @@ -706,17 +859,16 @@ bl_write_pagelist(struct nfs_write_data *wdata, int sync) } write_done: - wdata->res.count = (last_isect << SECTOR_SHIFT) - (offset); - if (count < wdata->res.count) { - wdata->res.count = count; - } + wdata->res.count = wdata->args.count; out: bl_put_extent(be); + bl_put_extent(cow_read); bl_submit_bio(WRITE, bio); put_parallel(par); return PNFS_ATTEMPTED; out_mds: bl_put_extent(be); + bl_put_extent(cow_read); kfree(par); return PNFS_NOT_ATTEMPTED; } diff --git a/fs/nfs/blocklayout/blocklayout.h b/fs/nfs/blocklayout/blocklayout.h index 03350690118..39bb51a8dd1 100644 --- a/fs/nfs/blocklayout/blocklayout.h +++ b/fs/nfs/blocklayout/blocklayout.h @@ -41,6 +41,7 @@ #define PAGE_CACHE_SECTORS (PAGE_CACHE_SIZE >> SECTOR_SHIFT) #define PAGE_CACHE_SECTOR_SHIFT (PAGE_CACHE_SHIFT - SECTOR_SHIFT) +#define SECTOR_SIZE (1 << SECTOR_SHIFT) struct block_mount_id { spinlock_t bm_lock; /* protects list */ diff --git a/fs/nfs/client.c b/fs/nfs/client.c index 60f7e4ec842..37f6de36973 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c @@ -694,8 +694,7 @@ static int nfs_create_rpc_client(struct nfs_client *clp, */ static void nfs_destroy_server(struct nfs_server *server) { - if (!(server->flags & NFS_MOUNT_LOCAL_FLOCK) || - !(server->flags & NFS_MOUNT_LOCAL_FCNTL)) + if (server->nlm_host) nlmclnt_done(server->nlm_host); } diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 8789210c690..a0daac7ad50 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -1103,7 +1103,7 @@ static int nfs_lookup_revalidate(struct dentry *dentry, struct nameidata *nd) struct nfs_fattr *fattr = NULL; int error; - if (nd->flags & LOOKUP_RCU) + if (nd && (nd->flags & LOOKUP_RCU)) return -ECHILD; parent = dget_parent(dentry); @@ -1219,11 +1219,14 @@ static int nfs_dentry_delete(const struct dentry *dentry) } +/* Ensure that we revalidate inode->i_nlink */ static void nfs_drop_nlink(struct inode *inode) { spin_lock(&inode->i_lock); - if (inode->i_nlink > 0) - drop_nlink(inode); + /* drop the inode if we're reasonably sure this is the last link */ + if (inode->i_nlink == 1) + clear_nlink(inode); + NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ATTR; spin_unlock(&inode->i_lock); } @@ -1238,8 +1241,8 @@ static void nfs_dentry_iput(struct dentry *dentry, struct inode *inode) NFS_I(inode)->cache_validity |= NFS_INO_INVALID_DATA; if (dentry->d_flags & DCACHE_NFSFS_RENAMED) { - drop_nlink(inode); nfs_complete_unlink(dentry, inode); + nfs_drop_nlink(inode); } iput(inode); } @@ -1502,7 +1505,7 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd) struct iattr attr; int openflags, ret = 0; - if (nd->flags & LOOKUP_RCU) + if (nd && (nd->flags & LOOKUP_RCU)) return -ECHILD; inode = dentry->d_inode; @@ -1800,10 +1803,8 @@ static int nfs_safe_remove(struct dentry *dentry) if (inode != NULL) { nfs_inode_return_delegation(inode); error = NFS_PROTO(dir)->remove(dir, &dentry->d_name); - /* The VFS may want to delete this inode */ if (error == 0) nfs_drop_nlink(inode); - nfs_mark_for_revalidate(inode); } else error = NFS_PROTO(dir)->remove(dir, &dentry->d_name); if (error == -ENOENT) diff --git a/fs/nfs/dns_resolve.c b/fs/nfs/dns_resolve.c index b3924b8a600..786cd653371 100644 --- a/fs/nfs/dns_resolve.c +++ b/fs/nfs/dns_resolve.c @@ -214,7 +214,7 @@ static int nfs_dns_parse(struct cache_detail *cd, char *buf, int buflen) { char buf1[NFS_DNS_HOSTNAME_MAXLEN+1]; struct nfs_dns_ent key, *item; - unsigned long ttl; + unsigned int ttl; ssize_t len; int ret = -EINVAL; @@ -237,7 +237,8 @@ static int nfs_dns_parse(struct cache_detail *cd, char *buf, int buflen) key.namelen = len; memset(&key.h, 0, sizeof(key.h)); - ttl = get_expiry(&buf); + if (get_uint(&buf, &ttl) < 0) + goto out; if (ttl == 0) goto out; key.h.expiry_time = ttl + seconds_since_boot(); diff --git a/fs/nfs/file.c b/fs/nfs/file.c index aa9b709fd32..f0f439dfeaa 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c @@ -451,8 +451,11 @@ static int nfs_release_page(struct page *page, gfp_t gfp) dfprintk(PAGECACHE, "NFS: release_page(%p)\n", page); - /* Only do I/O if gfp is a superset of GFP_KERNEL */ - if (mapping && (gfp & GFP_KERNEL) == GFP_KERNEL) { + /* Only do I/O if gfp is a superset of GFP_KERNEL, and we're not + * doing this memory reclaim for a fs-related allocation. + */ + if (mapping && (gfp & GFP_KERNEL) == GFP_KERNEL && + !(current->flags & PF_FSTRANS)) { int how = FLUSH_SYNC; /* Don't let kswapd deadlock waiting for OOM RPC calls */ diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c index 93aa3a4c4b0..9131b17f3a7 100644 --- a/fs/nfs/idmap.c +++ b/fs/nfs/idmap.c @@ -63,6 +63,12 @@ struct idmap { struct mutex idmap_mutex; }; +struct idmap_legacy_upcalldata { + struct rpc_pipe_msg pipe_msg; + struct idmap_msg idmap_msg; + struct idmap *idmap; +}; + /** * nfs_fattr_init_names - initialise the nfs_fattr owner_name/group_name fields * @fattr: fully initialised struct nfs_fattr @@ -205,12 +211,18 @@ static int nfs_idmap_init_keyring(void) if (ret < 0) goto failed_put_key; + ret = register_key_type(&key_type_id_resolver_legacy); + if (ret < 0) + goto failed_reg_legacy; + set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags); cred->thread_keyring = keyring; cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING; id_resolver_cache = cred; return 0; +failed_reg_legacy: + unregister_key_type(&key_type_id_resolver); failed_put_key: key_put(keyring); failed_put_cred: @@ -222,6 +234,7 @@ static void nfs_idmap_quit_keyring(void) { key_revoke(id_resolver_cache->thread_keyring); unregister_key_type(&key_type_id_resolver); + unregister_key_type(&key_type_id_resolver_legacy); put_cred(id_resolver_cache); } @@ -319,6 +332,7 @@ static ssize_t nfs_idmap_get_key(const char *name, size_t namelen, ret = nfs_idmap_request_key(&key_type_id_resolver_legacy, name, namelen, type, data, data_size, idmap); + idmap->idmap_key_cons = NULL; mutex_unlock(&idmap->idmap_mutex); } return ret; @@ -376,16 +390,18 @@ static const match_table_t nfs_idmap_tokens = { static int nfs_idmap_legacy_upcall(struct key_construction *, const char *, void *); static ssize_t idmap_pipe_downcall(struct file *, const char __user *, size_t); +static void idmap_release_pipe(struct inode *); static void idmap_pipe_destroy_msg(struct rpc_pipe_msg *); static const struct rpc_pipe_ops idmap_upcall_ops = { .upcall = rpc_pipe_generic_upcall, .downcall = idmap_pipe_downcall, + .release_pipe = idmap_release_pipe, .destroy_msg = idmap_pipe_destroy_msg, }; static struct key_type key_type_id_resolver_legacy = { - .name = "id_resolver", + .name = "id_legacy", .instantiate = user_instantiate, .match = user_match, .revoke = user_revoke, @@ -596,7 +612,8 @@ void nfs_idmap_quit(void) nfs_idmap_quit_keyring(); } -static int nfs_idmap_prepare_message(char *desc, struct idmap_msg *im, +static int nfs_idmap_prepare_message(char *desc, struct idmap *idmap, + struct idmap_msg *im, struct rpc_pipe_msg *msg) { substring_t substr; @@ -639,6 +656,7 @@ static int nfs_idmap_legacy_upcall(struct key_construction *cons, const char *op, void *aux) { + struct idmap_legacy_upcalldata *data; struct rpc_pipe_msg *msg; struct idmap_msg *im; struct idmap *idmap = (struct idmap *)aux; @@ -646,33 +664,33 @@ static int nfs_idmap_legacy_upcall(struct key_construction *cons, int ret = -ENOMEM; /* msg and im are freed in idmap_pipe_destroy_msg */ - msg = kmalloc(sizeof(*msg), GFP_KERNEL); - if (!msg) - goto out0; - - im = kmalloc(sizeof(*im), GFP_KERNEL); - if (!im) + data = kmalloc(sizeof(*data), GFP_KERNEL); + if (!data) goto out1; - ret = nfs_idmap_prepare_message(key->description, im, msg); + msg = &data->pipe_msg; + im = &data->idmap_msg; + data->idmap = idmap; + + ret = nfs_idmap_prepare_message(key->description, idmap, im, msg); if (ret < 0) goto out2; + BUG_ON(idmap->idmap_key_cons != NULL); idmap->idmap_key_cons = cons; ret = rpc_queue_upcall(idmap->idmap_pipe, msg); if (ret < 0) - goto out2; + goto out3; return ret; +out3: + idmap->idmap_key_cons = NULL; out2: - kfree(im); + kfree(data); out1: - kfree(msg); -out0: - key_revoke(cons->key); - key_revoke(cons->authkey); + complete_request_key(cons, ret); return ret; } @@ -706,11 +724,18 @@ idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) { struct rpc_inode *rpci = RPC_I(filp->f_path.dentry->d_inode); struct idmap *idmap = (struct idmap *)rpci->private; - struct key_construction *cons = idmap->idmap_key_cons; + struct key_construction *cons; struct idmap_msg im; size_t namelen_in; int ret; + /* If instantiation is successful, anyone waiting for key construction + * will have been woken up and someone else may now have used + * idmap_key_cons - so after this point we may no longer touch it. + */ + cons = ACCESS_ONCE(idmap->idmap_key_cons); + idmap->idmap_key_cons = NULL; + if (mlen != sizeof(im)) { ret = -ENOSPC; goto out; @@ -722,9 +747,8 @@ idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) } if (!(im.im_status & IDMAP_STATUS_SUCCESS)) { - ret = mlen; - complete_request_key(idmap->idmap_key_cons, -ENOKEY); - goto out_incomplete; + ret = -ENOKEY; + goto out; } namelen_in = strnlen(im.im_name, IDMAP_NAMESZ); @@ -740,17 +764,33 @@ idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) } out: - complete_request_key(idmap->idmap_key_cons, ret); -out_incomplete: + complete_request_key(cons, ret); return ret; } static void idmap_pipe_destroy_msg(struct rpc_pipe_msg *msg) { + struct idmap_legacy_upcalldata *data = container_of(msg, + struct idmap_legacy_upcalldata, + pipe_msg); + struct idmap *idmap = data->idmap; + struct key_construction *cons; + if (msg->errno) { + cons = ACCESS_ONCE(idmap->idmap_key_cons); + idmap->idmap_key_cons = NULL; + complete_request_key(cons, msg->errno); + } /* Free memory allocated in nfs_idmap_legacy_upcall() */ - kfree(msg->data); - kfree(msg); + kfree(data); +} + +static void +idmap_release_pipe(struct inode *inode) +{ + struct rpc_inode *rpci = RPC_I(inode); + struct idmap *idmap = (struct idmap *)rpci->private; + idmap->idmap_key_cons = NULL; } int nfs_map_name_to_uid(const struct nfs_server *server, const char *name, size_t namelen, __u32 *uid) diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 2c0c609a45a..a55d0c8a3fd 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -152,7 +152,7 @@ static void nfs_zap_caches_locked(struct inode *inode) nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); nfsi->attrtimeo_timestamp = jiffies; - memset(NFS_COOKIEVERF(inode), 0, sizeof(NFS_COOKIEVERF(inode))); + memset(NFS_I(inode)->cookieverf, 0, sizeof(NFS_I(inode)->cookieverf)); if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)) nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE; else diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index b777bdaba4c..33aa76fec3a 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -277,8 +277,9 @@ extern void nfs_sb_active(struct super_block *sb); extern void nfs_sb_deactive(struct super_block *sb); /* namespace.c */ +#define NFS_PATH_CANONICAL 1 extern char *nfs_path(char **p, struct dentry *dentry, - char *buffer, ssize_t buflen); + char *buffer, ssize_t buflen, unsigned flags); extern struct vfsmount *nfs_d_automount(struct path *path); #ifdef CONFIG_NFS_V4 rpc_authflavor_t nfs_find_best_sec(struct nfs4_secinfo_flavors *); @@ -371,7 +372,7 @@ static inline char *nfs_devname(struct dentry *dentry, char *buffer, ssize_t buflen) { char *dummy; - return nfs_path(&dummy, dentry, buffer, buflen); + return nfs_path(&dummy, dentry, buffer, buflen, NFS_PATH_CANONICAL); } /* diff --git a/fs/nfs/mount_clnt.c b/fs/nfs/mount_clnt.c index 8e65c7f1f87..015f71f8f62 100644 --- a/fs/nfs/mount_clnt.c +++ b/fs/nfs/mount_clnt.c @@ -181,7 +181,7 @@ int nfs_mount(struct nfs_mount_request *info) else msg.rpc_proc = &mnt_clnt->cl_procinfo[MOUNTPROC_MNT]; - status = rpc_call_sync(mnt_clnt, &msg, 0); + status = rpc_call_sync(mnt_clnt, &msg, RPC_TASK_SOFT|RPC_TASK_TIMEOUT); rpc_shutdown_client(mnt_clnt); if (status < 0) diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c index d51868e5683..43275167649 100644 --- a/fs/nfs/namespace.c +++ b/fs/nfs/namespace.c @@ -37,6 +37,7 @@ static struct vfsmount *nfs_do_submount(struct dentry *dentry, * @dentry - pointer to dentry * @buffer - result buffer * @buflen - length of buffer + * @flags - options (see below) * * Helper function for constructing the server pathname * by arbitrary hashed dentry. @@ -44,8 +45,14 @@ static struct vfsmount *nfs_do_submount(struct dentry *dentry, * This is mainly for use in figuring out the path on the * server side when automounting on top of an existing partition * and in generating /proc/mounts and friends. + * + * Supported flags: + * NFS_PATH_CANONICAL: ensure there is exactly one slash after + * the original device (export) name + * (if unset, the original name is returned verbatim) */ -char *nfs_path(char **p, struct dentry *dentry, char *buffer, ssize_t buflen) +char *nfs_path(char **p, struct dentry *dentry, char *buffer, ssize_t buflen, + unsigned flags) { char *end; int namelen; @@ -78,7 +85,7 @@ char *nfs_path(char **p, struct dentry *dentry, char *buffer, ssize_t buflen) rcu_read_unlock(); goto rename_retry; } - if (*end != '/') { + if ((flags & NFS_PATH_CANONICAL) && *end != '/') { if (--buflen < 0) { spin_unlock(&dentry->d_lock); rcu_read_unlock(); @@ -95,9 +102,11 @@ char *nfs_path(char **p, struct dentry *dentry, char *buffer, ssize_t buflen) return end; } namelen = strlen(base); - /* Strip off excess slashes in base string */ - while (namelen > 0 && base[namelen - 1] == '/') - namelen--; + if (flags & NFS_PATH_CANONICAL) { + /* Strip off excess slashes in base string */ + while (namelen > 0 && base[namelen - 1] == '/') + namelen--; + } buflen -= namelen; if (buflen < 0) { spin_unlock(&dentry->d_lock); @@ -244,11 +253,31 @@ struct vfsmount *nfs_d_automount(struct path *path) return mnt; } +static int +nfs_namespace_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) +{ + if (NFS_FH(dentry->d_inode)->size != 0) + return nfs_getattr(mnt, dentry, stat); + generic_fillattr(dentry->d_inode, stat); + return 0; +} + +static int +nfs_namespace_setattr(struct dentry *dentry, struct iattr *attr) +{ + if (NFS_FH(dentry->d_inode)->size != 0) + return nfs_setattr(dentry, attr); + return -EACCES; +} + const struct inode_operations nfs_mountpoint_inode_operations = { .getattr = nfs_getattr, + .setattr = nfs_setattr, }; const struct inode_operations nfs_referral_inode_operations = { + .getattr = nfs_namespace_getattr, + .setattr = nfs_namespace_setattr, }; static void nfs_expire_automounts(struct work_struct *work) diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index 2ab36b4caa6..7374c77aba1 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c @@ -69,7 +69,7 @@ do_proc_get_root(struct rpc_clnt *client, struct nfs_fh *fhandle, nfs_fattr_init(info->fattr); status = rpc_call_sync(client, &msg, 0); dprintk("%s: reply fsinfo: %d\n", __func__, status); - if (!(info->fattr->valid & NFS_ATTR_FATTR)) { + if (status == 0 && !(info->fattr->valid & NFS_ATTR_FATTR)) { msg.rpc_proc = &nfs3_procedures[NFS3PROC_GETATTR]; msg.rpc_resp = info->fattr; status = rpc_call_sync(client, &msg, 0); @@ -644,7 +644,7 @@ nfs3_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, u64 cookie, struct page **pages, unsigned int count, int plus) { struct inode *dir = dentry->d_inode; - __be32 *verf = NFS_COOKIEVERF(dir); + __be32 *verf = NFS_I(dir)->cookieverf; struct nfs3_readdirargs arg = { .fh = NFS_FH(dir), .cookie = cookie, diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c index a7f3dedc4ec..b604be2dae6 100644 --- a/fs/nfs/nfs4namespace.c +++ b/fs/nfs/nfs4namespace.c @@ -81,7 +81,8 @@ static char *nfs_path_component(const char *nfspath, const char *end) static char *nfs4_path(struct dentry *dentry, char *buffer, ssize_t buflen) { char *limit; - char *path = nfs_path(&limit, dentry, buffer, buflen); + char *path = nfs_path(&limit, dentry, buffer, buflen, + NFS_PATH_CANONICAL); if (!IS_ERR(path)) { char *path_component = nfs_path_component(path, limit); if (path_component) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 535f38420ca..3c1b1552917 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -307,8 +307,7 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc dprintk("%s ERROR: %d Reset session\n", __func__, errorcode); nfs4_schedule_session_recovery(clp->cl_session); - exception->retry = 1; - break; + goto wait_on_recovery; #endif /* defined(CONFIG_NFS_V4_1) */ case -NFS4ERR_FILE_OPEN: if (exception->timeout > HZ) { @@ -1478,9 +1477,11 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata) data->timestamp = jiffies; if (nfs4_setup_sequence(data->o_arg.server, &data->o_arg.seq_args, - &data->o_res.seq_res, task)) - return; - rpc_call_start(task); + &data->o_res.seq_res, + task) != 0) + nfs_release_seqid(data->o_arg.seqid); + else + rpc_call_start(task); return; unlock_no_action: rcu_read_unlock(); @@ -2097,9 +2098,10 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) if (nfs4_setup_sequence(NFS_SERVER(calldata->inode), &calldata->arg.seq_args, &calldata->res.seq_res, - task)) - goto out; - rpc_call_start(task); + task) != 0) + nfs_release_seqid(calldata->arg.seqid); + else + rpc_call_start(task); out: dprintk("%s: done!\n", __func__); } @@ -3150,11 +3152,11 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, dentry->d_parent->d_name.name, dentry->d_name.name, (unsigned long long)cookie); - nfs4_setup_readdir(cookie, NFS_COOKIEVERF(dir), dentry, &args); + nfs4_setup_readdir(cookie, NFS_I(dir)->cookieverf, dentry, &args); res.pgbase = args.pgbase; status = nfs4_call_sync(NFS_SERVER(dir)->client, NFS_SERVER(dir), &msg, &args.seq_args, &res.seq_res, 0); if (status >= 0) { - memcpy(NFS_COOKIEVERF(dir), res.verifier.data, NFS4_VERIFIER_SIZE); + memcpy(NFS_I(dir)->cookieverf, res.verifier.data, NFS4_VERIFIER_SIZE); status += args.pgbase; } @@ -4306,6 +4308,7 @@ static void nfs4_locku_done(struct rpc_task *task, void *data) if (nfs4_async_handle_error(task, calldata->server, NULL) == -EAGAIN) rpc_restart_call_prepare(task); } + nfs_release_seqid(calldata->arg.seqid); } static void nfs4_locku_prepare(struct rpc_task *task, void *data) @@ -4322,9 +4325,11 @@ static void nfs4_locku_prepare(struct rpc_task *task, void *data) calldata->timestamp = jiffies; if (nfs4_setup_sequence(calldata->server, &calldata->arg.seq_args, - &calldata->res.seq_res, task)) - return; - rpc_call_start(task); + &calldata->res.seq_res, + task) != 0) + nfs_release_seqid(calldata->arg.seqid); + else + rpc_call_start(task); } static const struct rpc_call_ops nfs4_locku_ops = { @@ -4469,7 +4474,7 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata) /* Do we need to do an open_to_lock_owner? */ if (!(data->arg.lock_seqid->sequence->flags & NFS_SEQID_CONFIRMED)) { if (nfs_wait_on_sequence(data->arg.open_seqid, task) != 0) - return; + goto out_release_lock_seqid; data->arg.open_stateid = &state->stateid; data->arg.new_lock_owner = 1; data->res.open_seqid = data->arg.open_seqid; @@ -4478,10 +4483,15 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata) data->timestamp = jiffies; if (nfs4_setup_sequence(data->server, &data->arg.seq_args, - &data->res.seq_res, task)) + &data->res.seq_res, + task) == 0) { + rpc_call_start(task); return; - rpc_call_start(task); - dprintk("%s: done!, ret = %d\n", __func__, data->rpc_status); + } + nfs_release_seqid(data->arg.open_seqid); +out_release_lock_seqid: + nfs_release_seqid(data->arg.lock_seqid); + dprintk("%s: done!, ret = %d\n", __func__, task->tk_status); } static void nfs4_recover_lock_prepare(struct rpc_task *task, void *calldata) @@ -5729,13 +5739,26 @@ static void nfs41_sequence_prepare(struct rpc_task *task, void *data) rpc_call_start(task); } +static void nfs41_sequence_prepare_privileged(struct rpc_task *task, void *data) +{ + rpc_task_set_priority(task, RPC_PRIORITY_PRIVILEGED); + nfs41_sequence_prepare(task, data); +} + static const struct rpc_call_ops nfs41_sequence_ops = { .rpc_call_done = nfs41_sequence_call_done, .rpc_call_prepare = nfs41_sequence_prepare, .rpc_release = nfs41_sequence_release, }; -static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp, struct rpc_cred *cred) +static const struct rpc_call_ops nfs41_sequence_privileged_ops = { + .rpc_call_done = nfs41_sequence_call_done, + .rpc_call_prepare = nfs41_sequence_prepare_privileged, + .rpc_release = nfs41_sequence_release, +}; + +static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp, struct rpc_cred *cred, + const struct rpc_call_ops *seq_ops) { struct nfs4_sequence_data *calldata; struct rpc_message msg = { @@ -5745,7 +5768,7 @@ static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp, struct rpc_ struct rpc_task_setup task_setup_data = { .rpc_client = clp->cl_rpcclient, .rpc_message = &msg, - .callback_ops = &nfs41_sequence_ops, + .callback_ops = seq_ops, .flags = RPC_TASK_ASYNC | RPC_TASK_SOFT, }; @@ -5772,7 +5795,7 @@ static int nfs41_proc_async_sequence(struct nfs_client *clp, struct rpc_cred *cr if ((renew_flags & NFS4_RENEW_TIMEOUT) == 0) return 0; - task = _nfs41_proc_sequence(clp, cred); + task = _nfs41_proc_sequence(clp, cred, &nfs41_sequence_ops); if (IS_ERR(task)) ret = PTR_ERR(task); else @@ -5786,7 +5809,7 @@ static int nfs4_proc_sequence(struct nfs_client *clp, struct rpc_cred *cred) struct rpc_task *task; int ret; - task = _nfs41_proc_sequence(clp, cred); + task = _nfs41_proc_sequence(clp, cred, &nfs41_sequence_privileged_ops); if (IS_ERR(task)) { ret = PTR_ERR(task); goto out; @@ -5966,11 +5989,58 @@ static void nfs4_layoutget_done(struct rpc_task *task, void *calldata) dprintk("<-- %s\n", __func__); } +static size_t max_response_pages(struct nfs_server *server) +{ + u32 max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz; + return nfs_page_array_len(0, max_resp_sz); +} + +static void nfs4_free_pages(struct page **pages, size_t size) +{ + int i; + + if (!pages) + return; + + for (i = 0; i < size; i++) { + if (!pages[i]) + break; + __free_page(pages[i]); + } + kfree(pages); +} + +static struct page **nfs4_alloc_pages(size_t size, gfp_t gfp_flags) +{ + struct page **pages; + int i; + + pages = kcalloc(size, sizeof(struct page *), gfp_flags); + if (!pages) { + dprintk("%s: can't alloc array of %zu pages\n", __func__, size); + return NULL; + } + + for (i = 0; i < size; i++) { + pages[i] = alloc_page(gfp_flags); + if (!pages[i]) { + dprintk("%s: failed to allocate page\n", __func__); + nfs4_free_pages(pages, size); + return NULL; + } + } + + return pages; +} + static void nfs4_layoutget_release(void *calldata) { struct nfs4_layoutget *lgp = calldata; + struct nfs_server *server = NFS_SERVER(lgp->args.inode); + size_t max_pages = max_response_pages(server); dprintk("--> %s\n", __func__); + nfs4_free_pages(lgp->args.layout.pages, max_pages); put_nfs_open_context(lgp->args.ctx); kfree(calldata); dprintk("<-- %s\n", __func__); @@ -5982,9 +6052,10 @@ static const struct rpc_call_ops nfs4_layoutget_call_ops = { .rpc_release = nfs4_layoutget_release, }; -int nfs4_proc_layoutget(struct nfs4_layoutget *lgp) +int nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags) { struct nfs_server *server = NFS_SERVER(lgp->args.inode); + size_t max_pages = max_response_pages(server); struct rpc_task *task; struct rpc_message msg = { .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_LAYOUTGET], @@ -6002,6 +6073,13 @@ int nfs4_proc_layoutget(struct nfs4_layoutget *lgp) dprintk("--> %s\n", __func__); + lgp->args.layout.pages = nfs4_alloc_pages(max_pages, gfp_flags); + if (!lgp->args.layout.pages) { + nfs4_layoutget_release(lgp); + return -ENOMEM; + } + lgp->args.layout.pglen = max_pages * PAGE_SIZE; + lgp->res.layoutp = &lgp->args.layout; lgp->res.seq_res.sr_slot = NULL; nfs41_init_sequence(&lgp->args.seq_args, &lgp->res.seq_res, 0); @@ -6047,12 +6125,8 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata) return; } spin_lock(&lo->plh_inode->i_lock); - if (task->tk_status == 0) { - if (lrp->res.lrs_present) { - pnfs_set_layout_stateid(lo, &lrp->res.stateid, true); - } else - BUG_ON(!list_empty(&lo->plh_segs)); - } + if (task->tk_status == 0 && lrp->res.lrs_present) + pnfs_set_layout_stateid(lo, &lrp->res.stateid, true); lo->plh_block_lgets--; spin_unlock(&lo->plh_inode->i_lock); dprintk("<-- %s\n", __func__); diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index c54aae364be..c8ac9a1461c 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c @@ -6081,7 +6081,8 @@ static int nfs4_xdr_dec_open(struct rpc_rqst *rqstp, struct xdr_stream *xdr, status = decode_open(xdr, res); if (status) goto out; - if (decode_getfh(xdr, &res->fh) != 0) + status = decode_getfh(xdr, &res->fh); + if (status) goto out; if (decode_getfattr(xdr, res->f_attr, res->server) != 0) goto out; diff --git a/fs/nfs/objlayout/objio_osd.c b/fs/nfs/objlayout/objio_osd.c index 4bff4a3dab4..1afe74c42c8 100644 --- a/fs/nfs/objlayout/objio_osd.c +++ b/fs/nfs/objlayout/objio_osd.c @@ -453,7 +453,10 @@ int objio_read_pagelist(struct nfs_read_data *rdata) objios->ios->done = _read_done; dprintk("%s: offset=0x%llx length=0x%x\n", __func__, rdata->args.offset, rdata->args.count); - return ore_read(objios->ios); + ret = ore_read(objios->ios); + if (unlikely(ret)) + objio_free_result(&objios->oir); + return ret; } /* @@ -484,8 +487,16 @@ static struct page *__r4w_get_page(void *priv, u64 offset, bool *uptodate) struct objio_state *objios = priv; struct nfs_write_data *wdata = objios->oir.rpcdata; pgoff_t index = offset / PAGE_SIZE; - struct page *page = find_get_page(wdata->inode->i_mapping, index); + struct page *page; + loff_t i_size = i_size_read(wdata->inode); + + if (offset >= i_size) { + *uptodate = true; + dprintk("%s: g_zero_page index=0x%lx\n", __func__, index); + return ZERO_PAGE(0); + } + page = find_get_page(wdata->inode->i_mapping, index); if (!page) { page = find_or_create_page(wdata->inode->i_mapping, index, GFP_NOFS); @@ -506,8 +517,10 @@ static struct page *__r4w_get_page(void *priv, u64 offset, bool *uptodate) static void __r4w_put_page(void *priv, struct page *page) { - dprintk("%s: index=0x%lx\n", __func__, page->index); - page_cache_release(page); + dprintk("%s: index=0x%lx\n", __func__, + (page == ZERO_PAGE(0)) ? -1UL : page->index); + if (ZERO_PAGE(0) != page) + page_cache_release(page); return; } @@ -537,8 +550,10 @@ int objio_write_pagelist(struct nfs_write_data *wdata, int how) dprintk("%s: offset=0x%llx length=0x%x\n", __func__, wdata->args.offset, wdata->args.count); ret = ore_write(objios->ios); - if (unlikely(ret)) + if (unlikely(ret)) { + objio_free_result(&objios->oir); return ret; + } if (objios->sync) _write_done(objios->ios, objios); diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 38512bcd2e9..059e2c350ad 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c @@ -574,9 +574,6 @@ send_layoutget(struct pnfs_layout_hdr *lo, struct nfs_server *server = NFS_SERVER(ino); struct nfs4_layoutget *lgp; struct pnfs_layout_segment *lseg = NULL; - struct page **pages = NULL; - int i; - u32 max_resp_sz, max_pages; dprintk("--> %s\n", __func__); @@ -585,20 +582,6 @@ send_layoutget(struct pnfs_layout_hdr *lo, if (lgp == NULL) return NULL; - /* allocate pages for xdr post processing */ - max_resp_sz = server->nfs_client->cl_session->fc_attrs.max_resp_sz; - max_pages = nfs_page_array_len(0, max_resp_sz); - - pages = kcalloc(max_pages, sizeof(struct page *), gfp_flags); - if (!pages) - goto out_err_free; - - for (i = 0; i < max_pages; i++) { - pages[i] = alloc_page(gfp_flags); - if (!pages[i]) - goto out_err_free; - } - lgp->args.minlength = PAGE_CACHE_SIZE; if (lgp->args.minlength > range->length) lgp->args.minlength = range->length; @@ -607,39 +590,19 @@ send_layoutget(struct pnfs_layout_hdr *lo, lgp->args.type = server->pnfs_curr_ld->id; lgp->args.inode = ino; lgp->args.ctx = get_nfs_open_context(ctx); - lgp->args.layout.pages = pages; - lgp->args.layout.pglen = max_pages * PAGE_SIZE; lgp->lsegpp = &lseg; lgp->gfp_flags = gfp_flags; /* Synchronously retrieve layout information from server and * store in lseg. */ - nfs4_proc_layoutget(lgp); + nfs4_proc_layoutget(lgp, gfp_flags); if (!lseg) { /* remember that LAYOUTGET failed and suspend trying */ set_bit(lo_fail_bit(range->iomode), &lo->plh_flags); } - /* free xdr pages */ - for (i = 0; i < max_pages; i++) - __free_page(pages[i]); - kfree(pages); - return lseg; - -out_err_free: - /* free any allocated xdr pages, lgp as it's not used */ - if (pages) { - for (i = 0; i < max_pages; i++) { - if (!pages[i]) - break; - __free_page(pages[i]); - } - kfree(pages); - } - kfree(lgp); - return NULL; } /* Initiates a LAYOUTRETURN(FILE) */ diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index 442ebf68eee..8d95818330c 100644 --- a/fs/nfs/pnfs.h +++ b/fs/nfs/pnfs.h @@ -161,7 +161,7 @@ extern int nfs4_proc_getdevicelist(struct nfs_server *server, struct pnfs_devicelist *devlist); extern int nfs4_proc_getdeviceinfo(struct nfs_server *server, struct pnfs_device *dev); -extern int nfs4_proc_layoutget(struct nfs4_layoutget *lgp); +extern int nfs4_proc_layoutget(struct nfs4_layoutget *lgp, gfp_t gfp_flags); extern int nfs4_proc_layoutreturn(struct nfs4_layoutreturn *lrp); /* pnfs.c */ diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 4ac7fca7e4b..c252161e7b1 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -812,7 +812,7 @@ static int nfs_show_devname(struct seq_file *m, struct dentry *root) int err = 0; if (!page) return -ENOMEM; - devname = nfs_path(&dummy, root, page, PAGE_SIZE); + devname = nfs_path(&dummy, root, page, PAGE_SIZE, 0); if (IS_ERR(devname)) err = PTR_ERR(devname); else @@ -1138,7 +1138,7 @@ static int nfs_get_option_str(substring_t args[], char **option) { kfree(*option); *option = match_strdup(args); - return !option; + return !*option; } static int nfs_get_option_ul(substring_t args[], unsigned long *option) @@ -1886,6 +1886,7 @@ static int nfs_validate_mount_data(void *options, memcpy(sap, &data->addr, sizeof(data->addr)); args->nfs_server.addrlen = sizeof(data->addr); + args->nfs_server.port = ntohs(data->addr.sin_port); if (!nfs_verify_server_address(sap)) goto out_no_address; @@ -2598,6 +2599,7 @@ static int nfs4_validate_mount_data(void *options, return -EFAULT; if (!nfs_verify_server_address(sap)) goto out_no_address; + args->nfs_server.port = ntohs(((struct sockaddr_in *)sap)->sin_port); if (data->auth_flavourlen) { if (data->auth_flavourlen > 1) @@ -3146,4 +3148,6 @@ static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type, return res; } +MODULE_ALIAS("nfs4"); + #endif /* CONFIG_NFS_V4 */ diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index 8e9689abbc0..e9a020f283f 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c @@ -401,7 +401,7 @@ fsloc_parse(char **mesg, char *buf, struct nfsd4_fs_locations *fsloc) int migrated, i, err; /* listsize */ - err = get_int(mesg, &fsloc->locations_count); + err = get_uint(mesg, &fsloc->locations_count); if (err) return err; if (fsloc->locations_count > MAX_FS_LOCATIONS) @@ -459,7 +459,7 @@ static int secinfo_parse(char **mesg, char *buf, struct svc_export *exp) return -EINVAL; for (f = exp->ex_flavors; f < exp->ex_flavors + listsize; f++) { - err = get_int(mesg, &f->pseudoflavor); + err = get_uint(mesg, &f->pseudoflavor); if (err) return err; /* @@ -468,7 +468,7 @@ static int secinfo_parse(char **mesg, char *buf, struct svc_export *exp) * problem at export time instead of when a client fails * to authenticate. */ - err = get_int(mesg, &f->flags); + err = get_uint(mesg, &f->flags); if (err) return err; /* Only some flags are allowed to differ between flavors: */ diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c index 322d11ce06a..01b090d135b 100644 --- a/fs/nfsd/nfs4idmap.c +++ b/fs/nfsd/nfs4idmap.c @@ -581,7 +581,7 @@ numeric_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namel /* Just to make sure it's null-terminated: */ memcpy(buf, name, namelen); buf[namelen] = '\0'; - ret = kstrtouint(name, 10, id); + ret = kstrtouint(buf, 10, id); return ret == 0; } diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 987e719fbae..dd0308d65f6 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c @@ -194,6 +194,7 @@ static __be32 do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open) { struct svc_fh *resfh; + int accmode; __be32 status; resfh = kmalloc(sizeof(struct svc_fh), GFP_KERNEL); @@ -253,9 +254,10 @@ do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_o /* set reply cache */ fh_copy_shallow(&open->op_openowner->oo_owner.so_replay.rp_openfh, &resfh->fh_handle); - if (!open->op_created) - status = do_open_permission(rqstp, resfh, open, - NFSD_MAY_NOP); + accmode = NFSD_MAY_NOP; + if (open->op_created) + accmode |= NFSD_MAY_OWNER_OVERRIDE; + status = do_open_permission(rqstp, resfh, open, accmode); set_change_info(&open->op_cinfo, current_fh); fh_dup2(current_fh, resfh); out: diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index e79c24e232f..537731e4c16 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -2356,7 +2356,7 @@ nfsd4_init_slabs(void) if (openowner_slab == NULL) goto out_nomem; lockowner_slab = kmem_cache_create("nfsd4_lockowners", - sizeof(struct nfs4_openowner), 0, 0, NULL); + sizeof(struct nfs4_lockowner), 0, 0, NULL); if (lockowner_slab == NULL) goto out_nomem; file_slab = kmem_cache_create("nfsd4_files", @@ -3783,6 +3783,7 @@ nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, memcpy(&close->cl_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t)); nfsd4_close_open_stateid(stp); + release_last_closed_stateid(oo); oo->oo_last_closed_stid = stp; /* place unused nfs4_stateowners on so_close_lru list to be diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 74c00bc92b9..967d68eef28 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -2233,7 +2233,7 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, if (bmval0 & FATTR4_WORD0_CASE_INSENSITIVE) { if ((buflen -= 4) < 0) goto out_resource; - WRITE32(1); + WRITE32(0); } if (bmval0 & FATTR4_WORD0_CASE_PRESERVING) { if ((buflen -= 4) < 0) @@ -2920,11 +2920,16 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr, len = maxcount; v = 0; while (len > 0) { - pn = resp->rqstp->rq_resused++; + pn = resp->rqstp->rq_resused; + if (!resp->rqstp->rq_respages[pn]) { /* ran out of pages */ + maxcount -= len; + break; + } resp->rqstp->rq_vec[v].iov_base = page_address(resp->rqstp->rq_respages[pn]); resp->rqstp->rq_vec[v].iov_len = len < PAGE_SIZE ? len : PAGE_SIZE; + resp->rqstp->rq_resused++; v++; len -= PAGE_SIZE; } @@ -2970,6 +2975,8 @@ nfsd4_encode_readlink(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd return nfserr; if (resp->xbuf->page_len) return nfserr_resource; + if (!resp->rqstp->rq_respages[resp->rqstp->rq_resused]) + return nfserr_resource; page = page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused++]); @@ -3019,6 +3026,8 @@ nfsd4_encode_readdir(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4 return nfserr; if (resp->xbuf->page_len) return nfserr_resource; + if (!resp->rqstp->rq_respages[resp->rqstp->rq_resused]) + return nfserr_resource; RESERVE_SPACE(NFS4_VERIFIER_SIZE); savep = p; diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 3ab12eb2967..d014727fc8f 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -663,9 +663,7 @@ static ssize_t __write_ports_addfd(char *buf) err = svc_addsock(nfsd_serv, fd, buf, SIMPLE_TRANSACTION_LIMIT); if (err < 0) { - if (nfsd_serv->sv_nrthreads == 1) - svc_shutdown_net(nfsd_serv, net); - svc_destroy(nfsd_serv); + nfsd_destroy(net); return err; } @@ -734,9 +732,7 @@ static ssize_t __write_ports_addxprt(char *buf) svc_xprt_put(xprt); } out_err: - if (nfsd_serv->sv_nrthreads == 1) - svc_shutdown_net(nfsd_serv, net); - svc_destroy(nfsd_serv); + nfsd_destroy(net); return err; } diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h index 1671429ffa6..1336a6512cd 100644 --- a/fs/nfsd/nfsd.h +++ b/fs/nfsd/nfsd.h @@ -73,6 +73,17 @@ int nfsd_nrpools(void); int nfsd_get_nrthreads(int n, int *); int nfsd_set_nrthreads(int n, int *); +static inline void nfsd_destroy(struct net *net) +{ + int destroy = (nfsd_serv->sv_nrthreads == 1); + + if (destroy) + svc_shutdown_net(nfsd_serv, net); + svc_destroy(nfsd_serv); + if (destroy) + nfsd_serv = NULL; +} + #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) #ifdef CONFIG_NFSD_V2_ACL extern struct svc_version nfsd_acl_version2; diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index bcda12a3f08..53459b055cf 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c @@ -254,8 +254,6 @@ static void nfsd_shutdown(void) static void nfsd_last_thread(struct svc_serv *serv, struct net *net) { - /* When last nfsd thread exits we need to do some clean-up */ - nfsd_serv = NULL; nfsd_shutdown(); svc_rpcb_cleanup(serv, net); @@ -332,6 +330,7 @@ static int nfsd_get_default_max_blksize(void) int nfsd_create_serv(void) { int error; + struct net *net = current->nsproxy->net_ns; WARN_ON(!mutex_is_locked(&nfsd_mutex)); if (nfsd_serv) { @@ -346,7 +345,7 @@ int nfsd_create_serv(void) if (nfsd_serv == NULL) return -ENOMEM; - error = svc_bind(nfsd_serv, current->nsproxy->net_ns); + error = svc_bind(nfsd_serv, net); if (error < 0) { svc_destroy(nfsd_serv); return error; @@ -427,11 +426,7 @@ int nfsd_set_nrthreads(int n, int *nthreads) if (err) break; } - - if (nfsd_serv->sv_nrthreads == 1) - svc_shutdown_net(nfsd_serv, net); - svc_destroy(nfsd_serv); - + nfsd_destroy(net); return err; } @@ -478,9 +473,7 @@ nfsd_svc(unsigned short port, int nrservs) if (error < 0 && !nfsd_up_before) nfsd_shutdown(); out_destroy: - if (nfsd_serv->sv_nrthreads == 1) - svc_shutdown_net(nfsd_serv, net); - svc_destroy(nfsd_serv); /* Release server */ + nfsd_destroy(net); /* Release server */ out: mutex_unlock(&nfsd_mutex); return error; @@ -563,12 +556,13 @@ nfsd(void *vrqstp) nfsdstats.th_cnt --; out: - if (rqstp->rq_server->sv_nrthreads == 1) - svc_shutdown_net(rqstp->rq_server, &init_net); + rqstp->rq_server = NULL; /* Release the thread */ svc_exit_thread(rqstp); + nfsd_destroy(&init_net); + /* Release module */ mutex_unlock(&nfsd_mutex); module_put_and_exit(0); @@ -656,7 +650,7 @@ nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp) } /* Store reply in cache. */ - nfsd_cache_update(rqstp, proc->pc_cachetype, statp + 1); + nfsd_cache_update(rqstp, rqstp->rq_cachetype, statp + 1); return 1; } @@ -682,9 +676,7 @@ int nfsd_pool_stats_release(struct inode *inode, struct file *file) mutex_lock(&nfsd_mutex); /* this function really, really should have been called svc_put() */ - if (nfsd_serv->sv_nrthreads == 1) - svc_shutdown_net(nfsd_serv, net); - svc_destroy(nfsd_serv); + nfsd_destroy(net); mutex_unlock(&nfsd_mutex); return ret; } diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 568666156ea..f03160106b9 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -1477,13 +1477,19 @@ do_nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, case NFS3_CREATE_EXCLUSIVE: if ( dchild->d_inode->i_mtime.tv_sec == v_mtime && dchild->d_inode->i_atime.tv_sec == v_atime - && dchild->d_inode->i_size == 0 ) + && dchild->d_inode->i_size == 0 ) { + if (created) + *created = 1; break; + } case NFS4_CREATE_EXCLUSIVE4_1: if ( dchild->d_inode->i_mtime.tv_sec == v_mtime && dchild->d_inode->i_atime.tv_sec == v_atime - && dchild->d_inode->i_size == 0 ) + && dchild->d_inode->i_size == 0 ) { + if (created) + *created = 1; goto set_attr; + } /* fallthru */ case NFS3_CREATE_GUARDED: err = nfserr_exist; diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c index 2a70fce70c6..37294933891 100644 --- a/fs/nilfs2/ioctl.c +++ b/fs/nilfs2/ioctl.c @@ -182,7 +182,7 @@ static int nilfs_ioctl_change_cpmode(struct inode *inode, struct file *filp, if (copy_from_user(&cpmode, argp, sizeof(cpmode))) goto out; - down_read(&inode->i_sb->s_umount); + mutex_lock(&nilfs->ns_snapshot_mount_mutex); nilfs_transaction_begin(inode->i_sb, &ti, 0); ret = nilfs_cpfile_change_cpmode( @@ -192,7 +192,7 @@ static int nilfs_ioctl_change_cpmode(struct inode *inode, struct file *filp, else nilfs_transaction_commit(inode->i_sb); /* never fails */ - up_read(&inode->i_sb->s_umount); + mutex_unlock(&nilfs->ns_snapshot_mount_mutex); out: mnt_drop_write_file(filp); return ret; @@ -666,8 +666,11 @@ static int nilfs_ioctl_clean_segments(struct inode *inode, struct file *filp, if (ret < 0) printk(KERN_ERR "NILFS: GC failed during preparation: " "cannot read source blocks: err=%d\n", ret); - else + else { + if (nilfs_sb_need_update(nilfs)) + set_nilfs_discontinued(nilfs); ret = nilfs_clean_segments(inode->i_sb, argv, kbufs); + } nilfs_remove_all_gcinodes(nilfs); clear_nilfs_gc_running(nilfs); diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index 1099a76cee5..496904b96b2 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c @@ -948,6 +948,8 @@ static int nilfs_attach_snapshot(struct super_block *s, __u64 cno, struct nilfs_root *root; int ret; + mutex_lock(&nilfs->ns_snapshot_mount_mutex); + down_read(&nilfs->ns_segctor_sem); ret = nilfs_cpfile_is_snapshot(nilfs->ns_cpfile, cno); up_read(&nilfs->ns_segctor_sem); @@ -972,6 +974,7 @@ static int nilfs_attach_snapshot(struct super_block *s, __u64 cno, ret = nilfs_get_root_dentry(s, root, root_dentry); nilfs_put_root(root); out: + mutex_unlock(&nilfs->ns_snapshot_mount_mutex); return ret; } diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c index 501b7f8b739..41e6a04a561 100644 --- a/fs/nilfs2/the_nilfs.c +++ b/fs/nilfs2/the_nilfs.c @@ -76,6 +76,7 @@ struct the_nilfs *alloc_nilfs(struct block_device *bdev) nilfs->ns_bdev = bdev; atomic_set(&nilfs->ns_ndirtyblks, 0); init_rwsem(&nilfs->ns_sem); + mutex_init(&nilfs->ns_snapshot_mount_mutex); INIT_LIST_HEAD(&nilfs->ns_dirty_files); INIT_LIST_HEAD(&nilfs->ns_gc_inodes); spin_lock_init(&nilfs->ns_inode_lock); diff --git a/fs/nilfs2/the_nilfs.h b/fs/nilfs2/the_nilfs.h index 9992b11312f..de7435f0ef5 100644 --- a/fs/nilfs2/the_nilfs.h +++ b/fs/nilfs2/the_nilfs.h @@ -47,6 +47,7 @@ enum { * @ns_flags: flags * @ns_bdev: block device * @ns_sem: semaphore for shared states + * @ns_snapshot_mount_mutex: mutex to protect snapshot mounts * @ns_sbh: buffer heads of on-disk super blocks * @ns_sbp: pointers to super block data * @ns_sbwtime: previous write time of super block @@ -99,6 +100,7 @@ struct the_nilfs { struct block_device *ns_bdev; struct rw_semaphore ns_sem; + struct mutex ns_snapshot_mount_mutex; /* * used for diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c index f35794b97e8..a5063602536 100644 --- a/fs/notify/fanotify/fanotify.c +++ b/fs/notify/fanotify/fanotify.c @@ -21,6 +21,7 @@ static bool should_merge(struct fsnotify_event *old, struct fsnotify_event *new) if ((old->path.mnt == new->path.mnt) && (old->path.dentry == new->path.dentry)) return true; + break; case (FSNOTIFY_EVENT_NONE): return true; default: diff --git a/fs/open.c b/fs/open.c index 3f1108b1914..cf1d34fc5e6 100644 --- a/fs/open.c +++ b/fs/open.c @@ -882,9 +882,10 @@ static inline int build_open_flags(int flags, umode_t mode, struct open_flags *o int lookup_flags = 0; int acc_mode; - if (!(flags & O_CREAT)) - mode = 0; - op->mode = mode; + if (flags & O_CREAT) + op->mode = (mode & S_IALLUGO) | S_IFREG; + else + op->mode = 0; /* Must never be set by userspace */ flags &= ~FMODE_NONOTIFY; diff --git a/fs/proc/page.c b/fs/proc/page.c index 7fcd0d60a96..b8730d9ebae 100644 --- a/fs/proc/page.c +++ b/fs/proc/page.c @@ -115,7 +115,13 @@ u64 stable_page_flags(struct page *page) u |= 1 << KPF_COMPOUND_TAIL; if (PageHuge(page)) u |= 1 << KPF_HUGE; - else if (PageTransCompound(page)) + /* + * PageTransCompound can be true for non-huge compound pages (slab + * pages or pages allocated by drivers with __GFP_COMP) because it + * just checks PG_head/PG_tail, so we need to check PageLRU to make + * sure a given page is a thp, not a non-huge compound page. + */ + else if (PageTransCompound(page) && PageLRU(compound_trans_head(page))) u |= 1 << KPF_THP; /* diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c index 21d836f4029..ab5352101db 100644 --- a/fs/proc/proc_sysctl.c +++ b/fs/proc/proc_sysctl.c @@ -462,9 +462,6 @@ static struct dentry *proc_sys_lookup(struct inode *dir, struct dentry *dentry, err = ERR_PTR(-ENOMEM); inode = proc_sys_make_inode(dir->i_sb, h ? h : head, p); - if (h) - sysctl_head_finish(h); - if (!inode) goto out; @@ -473,6 +470,8 @@ static struct dentry *proc_sys_lookup(struct inode *dir, struct dentry *dentry, d_add(dentry, inode); out: + if (h) + sysctl_head_finish(h); sysctl_head_finish(head); return err; } diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c index 494c315c741..c11db5134b7 100644 --- a/fs/reiserfs/inode.c +++ b/fs/reiserfs/inode.c @@ -1573,8 +1573,10 @@ struct dentry *reiserfs_fh_to_dentry(struct super_block *sb, struct fid *fid, reiserfs_warning(sb, "reiserfs-13077", "nfsd/reiserfs, fhtype=%d, len=%d - odd", fh_type, fh_len); - fh_type = 5; + fh_type = fh_len; } + if (fh_len < 2) + return NULL; return reiserfs_get_dentry(sb, fid->raw[0], fid->raw[1], (fh_type == 3 || fh_type >= 5) ? fid->raw[2] : 0); @@ -1583,6 +1585,8 @@ struct dentry *reiserfs_fh_to_dentry(struct super_block *sb, struct fid *fid, struct dentry *reiserfs_fh_to_parent(struct super_block *sb, struct fid *fid, int fh_len, int fh_type) { + if (fh_type > fh_len) + fh_type = fh_len; if (fh_type < 4) return NULL; @@ -1784,8 +1788,9 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th, BUG_ON(!th->t_trans_id); - dquot_initialize(inode); + reiserfs_write_unlock(inode->i_sb); err = dquot_alloc_inode(inode); + reiserfs_write_lock(inode->i_sb); if (err) goto out_end_trans; if (!dir->i_nlink) { @@ -1981,8 +1986,10 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th, out_end_trans: journal_end(th, th->t_super, th->t_blocks_allocated); + reiserfs_write_unlock(inode->i_sb); /* Drop can be outside and it needs more credits so it's better to have it outside */ dquot_drop(inode); + reiserfs_write_lock(inode->i_sb); inode->i_flags |= S_NOQUOTA; make_bad_inode(inode); @@ -3105,10 +3112,9 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) /* must be turned off for recursive notify_change calls */ ia_valid = attr->ia_valid &= ~(ATTR_KILL_SUID|ATTR_KILL_SGID); - depth = reiserfs_write_lock_once(inode->i_sb); if (is_quota_modification(inode, attr)) dquot_initialize(inode); - + depth = reiserfs_write_lock_once(inode->i_sb); if (attr->ia_valid & ATTR_SIZE) { /* version 2 items will be caught by the s_maxbytes check ** done for us in vmtruncate @@ -3172,7 +3178,9 @@ int reiserfs_setattr(struct dentry *dentry, struct iattr *attr) error = journal_begin(&th, inode->i_sb, jbegin_count); if (error) goto out; + reiserfs_write_unlock_once(inode->i_sb, depth); error = dquot_transfer(inode, attr); + depth = reiserfs_write_lock_once(inode->i_sb); if (error) { journal_end(&th, inode->i_sb, jbegin_count); goto out; diff --git a/fs/reiserfs/stree.c b/fs/reiserfs/stree.c index f8afa4b162b..2f40a4c70a4 100644 --- a/fs/reiserfs/stree.c +++ b/fs/reiserfs/stree.c @@ -1968,7 +1968,9 @@ int reiserfs_paste_into_item(struct reiserfs_transaction_handle *th, struct tree key2type(&(key->on_disk_key))); #endif + reiserfs_write_unlock(inode->i_sb); retval = dquot_alloc_space_nodirty(inode, pasted_size); + reiserfs_write_lock(inode->i_sb); if (retval) { pathrelse(search_path); return retval; @@ -2061,9 +2063,11 @@ int reiserfs_insert_item(struct reiserfs_transaction_handle *th, "reiserquota insert_item(): allocating %u id=%u type=%c", quota_bytes, inode->i_uid, head2type(ih)); #endif + reiserfs_write_unlock(inode->i_sb); /* We can't dirty inode here. It would be immediately written but * appropriate stat item isn't inserted yet... */ retval = dquot_alloc_space_nodirty(inode, quota_bytes); + reiserfs_write_lock(inode->i_sb); if (retval) { pathrelse(path); return retval; diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index 8b7616ef06d..8169be93ac0 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c @@ -256,7 +256,9 @@ static int finish_unfinished(struct super_block *s) retval = remove_save_link_only(s, &save_link_key, 0); continue; } + reiserfs_write_unlock(s); dquot_initialize(inode); + reiserfs_write_lock(s); if (truncate && S_ISDIR(inode->i_mode)) { /* We got a truncate request for a dir which is impossible. @@ -1292,7 +1294,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) kfree(qf_names[i]); #endif err = -EINVAL; - goto out_err; + goto out_unlock; } #ifdef CONFIG_QUOTA handle_quota_files(s, qf_names, &qfmt); @@ -1336,7 +1338,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) if (blocks) { err = reiserfs_resize(s, blocks); if (err != 0) - goto out_err; + goto out_unlock; } if (*mount_flags & MS_RDONLY) { @@ -1346,9 +1348,15 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) /* it is read-only already */ goto out_ok; + /* + * Drop write lock. Quota will retake it when needed and lock + * ordering requires calling dquot_suspend() without it. + */ + reiserfs_write_unlock(s); err = dquot_suspend(s, -1); if (err < 0) goto out_err; + reiserfs_write_lock(s); /* try to remount file system with read-only permissions */ if (sb_umount_state(rs) == REISERFS_VALID_FS @@ -1358,7 +1366,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) err = journal_begin(&th, s, 10); if (err) - goto out_err; + goto out_unlock; /* Mounting a rw partition read-only. */ reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1); @@ -1373,7 +1381,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) if (reiserfs_is_journal_aborted(journal)) { err = journal->j_errno; - goto out_err; + goto out_unlock; } handle_data_mode(s, mount_options); @@ -1382,7 +1390,7 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) s->s_flags &= ~MS_RDONLY; /* now it is safe to call journal_begin */ err = journal_begin(&th, s, 10); if (err) - goto out_err; + goto out_unlock; /* Mount a partition which is read-only, read-write */ reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1); @@ -1399,11 +1407,17 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) SB_JOURNAL(s)->j_must_wait = 1; err = journal_end(&th, s, 10); if (err) - goto out_err; + goto out_unlock; s->s_dirt = 0; if (!(*mount_flags & MS_RDONLY)) { + /* + * Drop write lock. Quota will retake it when needed and lock + * ordering requires calling dquot_resume() without it. + */ + reiserfs_write_unlock(s); dquot_resume(s, -1); + reiserfs_write_lock(s); finish_unfinished(s); reiserfs_xattr_init(s, *mount_flags); } @@ -1413,9 +1427,10 @@ static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) reiserfs_write_unlock(s); return 0; +out_unlock: + reiserfs_write_unlock(s); out_err: kfree(new_opts); - reiserfs_write_unlock(s); return err; } @@ -2049,13 +2064,15 @@ static int reiserfs_write_dquot(struct dquot *dquot) REISERFS_QUOTA_TRANS_BLOCKS(dquot->dq_sb)); if (ret) goto out; + reiserfs_write_unlock(dquot->dq_sb); ret = dquot_commit(dquot); + reiserfs_write_lock(dquot->dq_sb); err = journal_end(&th, dquot->dq_sb, REISERFS_QUOTA_TRANS_BLOCKS(dquot->dq_sb)); if (!ret && err) ret = err; - out: +out: reiserfs_write_unlock(dquot->dq_sb); return ret; } @@ -2071,13 +2088,15 @@ static int reiserfs_acquire_dquot(struct dquot *dquot) REISERFS_QUOTA_INIT_BLOCKS(dquot->dq_sb)); if (ret) goto out; + reiserfs_write_unlock(dquot->dq_sb); ret = dquot_acquire(dquot); + reiserfs_write_lock(dquot->dq_sb); err = journal_end(&th, dquot->dq_sb, REISERFS_QUOTA_INIT_BLOCKS(dquot->dq_sb)); if (!ret && err) ret = err; - out: +out: reiserfs_write_unlock(dquot->dq_sb); return ret; } @@ -2091,19 +2110,21 @@ static int reiserfs_release_dquot(struct dquot *dquot) ret = journal_begin(&th, dquot->dq_sb, REISERFS_QUOTA_DEL_BLOCKS(dquot->dq_sb)); + reiserfs_write_unlock(dquot->dq_sb); if (ret) { /* Release dquot anyway to avoid endless cycle in dqput() */ dquot_release(dquot); goto out; } ret = dquot_release(dquot); + reiserfs_write_lock(dquot->dq_sb); err = journal_end(&th, dquot->dq_sb, REISERFS_QUOTA_DEL_BLOCKS(dquot->dq_sb)); if (!ret && err) ret = err; - out: reiserfs_write_unlock(dquot->dq_sb); +out: return ret; } @@ -2128,11 +2149,13 @@ static int reiserfs_write_info(struct super_block *sb, int type) ret = journal_begin(&th, sb, 2); if (ret) goto out; + reiserfs_write_unlock(sb); ret = dquot_commit_info(sb, type); + reiserfs_write_lock(sb); err = journal_end(&th, sb, 2); if (!ret && err) ret = err; - out: +out: reiserfs_write_unlock(sb); return ret; } @@ -2157,8 +2180,11 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id, struct reiserfs_transaction_handle th; int opt = type == USRQUOTA ? REISERFS_USRQUOTA : REISERFS_GRPQUOTA; - if (!(REISERFS_SB(sb)->s_mount_opt & (1 << opt))) - return -EINVAL; + reiserfs_write_lock(sb); + if (!(REISERFS_SB(sb)->s_mount_opt & (1 << opt))) { + err = -EINVAL; + goto out; + } /* Quotafile not on the same filesystem? */ if (path->dentry->d_sb != sb) { @@ -2200,8 +2226,10 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id, if (err) goto out; } - err = dquot_quota_on(sb, type, format_id, path); + reiserfs_write_unlock(sb); + return dquot_quota_on(sb, type, format_id, path); out: + reiserfs_write_unlock(sb); return err; } @@ -2275,7 +2303,9 @@ static ssize_t reiserfs_quota_write(struct super_block *sb, int type, tocopy = sb->s_blocksize - offset < towrite ? sb->s_blocksize - offset : towrite; tmp_bh.b_state = 0; + reiserfs_write_lock(sb); err = reiserfs_get_block(inode, blk, &tmp_bh, GET_BLOCK_CREATE); + reiserfs_write_unlock(sb); if (err) goto out; if (offset || tocopy != sb->s_blocksize) @@ -2291,10 +2321,12 @@ static ssize_t reiserfs_quota_write(struct super_block *sb, int type, flush_dcache_page(bh->b_page); set_buffer_uptodate(bh); unlock_buffer(bh); + reiserfs_write_lock(sb); reiserfs_prepare_for_journal(sb, bh, 1); journal_mark_dirty(current->journal_info, sb, bh); if (!journal_quota) reiserfs_add_ordered_list(inode, bh); + reiserfs_write_unlock(sb); brelse(bh); offset = 0; towrite -= tocopy; diff --git a/fs/select.c b/fs/select.c index 0f8684a5934..e9799f22e86 100644 --- a/fs/select.c +++ b/fs/select.c @@ -344,8 +344,8 @@ static int max_select_fd(unsigned long n, fd_set_bits *fds) struct fdtable *fdt; /* handle last in-complete long-word first */ - set = ~(~0UL << (n & (__NFDBITS-1))); - n /= __NFDBITS; + set = ~(~0UL << (n & (BITS_PER_LONG-1))); + n /= BITS_PER_LONG; fdt = files_fdtable(current->files); open_fds = fdt->open_fds + n; max = 0; @@ -372,7 +372,7 @@ static int max_select_fd(unsigned long n, fd_set_bits *fds) max++; set >>= 1; } while (set); - max += n * __NFDBITS; + max += n * BITS_PER_LONG; } return max; @@ -434,11 +434,11 @@ int do_select(int n, fd_set_bits *fds, struct timespec *end_time) in = *inp++; out = *outp++; ex = *exp++; all_bits = in | out | ex; if (all_bits == 0) { - i += __NFDBITS; + i += BITS_PER_LONG; continue; } - for (j = 0; j < __NFDBITS; ++j, ++i, bit <<= 1) { + for (j = 0; j < BITS_PER_LONG; ++j, ++i, bit <<= 1) { int fput_needed; if (i >= n) break; diff --git a/fs/splice.c b/fs/splice.c index 060e9e4b8a4..8f89ac50c8f 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -696,8 +696,10 @@ static int pipe_to_sendpage(struct pipe_inode_info *pipe, return -EINVAL; more = (sd->flags & SPLICE_F_MORE) ? MSG_MORE : 0; - if (sd->len < sd->total_len) + + if (sd->len < sd->total_len && pipe->nrbufs > 1) more |= MSG_SENDPAGE_NOTLAST; + return file->f_op->sendpage(file, buf->page, buf->offset, sd->len, &pos, more); } diff --git a/fs/stat.c b/fs/stat.c index c733dc5753a..dc6d0be300c 100644 --- a/fs/stat.c +++ b/fs/stat.c @@ -57,7 +57,7 @@ EXPORT_SYMBOL(vfs_getattr); int vfs_fstat(unsigned int fd, struct kstat *stat) { - struct file *f = fget(fd); + struct file *f = fget_raw(fd); int error = -EBADF; if (f) { diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 35a36d39fa2..a545d819b49 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -457,20 +457,18 @@ int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) /** * sysfs_pathname - return full path to sysfs dirent * @sd: sysfs_dirent whose path we want - * @path: caller allocated buffer + * @path: caller allocated buffer of size PATH_MAX * * Gives the name "/" to the sysfs_root entry; any path returned * is relative to wherever sysfs is mounted. - * - * XXX: does no error checking on @path size */ static char *sysfs_pathname(struct sysfs_dirent *sd, char *path) { if (sd->s_parent) { sysfs_pathname(sd->s_parent, path); - strcat(path, "/"); + strlcat(path, "/", PATH_MAX); } - strcat(path, sd->s_name); + strlcat(path, sd->s_name, PATH_MAX); return path; } @@ -503,9 +501,11 @@ int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) char *path = kzalloc(PATH_MAX, GFP_KERNEL); WARN(1, KERN_WARNING "sysfs: cannot create duplicate filename '%s'\n", - (path == NULL) ? sd->s_name : - strcat(strcat(sysfs_pathname(acxt->parent_sd, path), "/"), - sd->s_name)); + (path == NULL) ? sd->s_name + : (sysfs_pathname(acxt->parent_sd, path), + strlcat(path, "/", PATH_MAX), + strlcat(path, sd->s_name, PATH_MAX), + path)); kfree(path); } diff --git a/fs/ubifs/debug.h b/fs/ubifs/debug.h index 9f717655df1..28e3de1892b 100644 --- a/fs/ubifs/debug.h +++ b/fs/ubifs/debug.h @@ -170,7 +170,7 @@ struct ubifs_global_debug_info { #define ubifs_dbg_msg(type, fmt, ...) \ pr_debug("UBIFS DBG " type ": " fmt "\n", ##__VA_ARGS__) -#define DBG_KEY_BUF_LEN 32 +#define DBG_KEY_BUF_LEN 48 #define ubifs_dbg_msg_key(type, key, fmt, ...) do { \ char __tmp_key_buf[DBG_KEY_BUF_LEN]; \ pr_debug("UBIFS DBG " type ": " fmt "%s\n", ##__VA_ARGS__, \ diff --git a/fs/ubifs/find.c b/fs/ubifs/find.c index 2559d174e00..5dc48cacb5a 100644 --- a/fs/ubifs/find.c +++ b/fs/ubifs/find.c @@ -681,8 +681,16 @@ int ubifs_find_free_leb_for_idx(struct ubifs_info *c) if (!lprops) { lprops = ubifs_fast_find_freeable(c); if (!lprops) { - ubifs_assert(c->freeable_cnt == 0); - if (c->lst.empty_lebs - c->lst.taken_empty_lebs > 0) { + /* + * The first condition means the following: go scan the + * LPT if there are uncategorized lprops, which means + * there may be freeable LEBs there (UBIFS does not + * store the information about freeable LEBs in the + * master node). + */ + if (c->in_a_category_cnt != c->main_lebs || + c->lst.empty_lebs - c->lst.taken_empty_lebs > 0) { + ubifs_assert(c->freeable_cnt == 0); lprops = scan_for_leb_for_idx(c); if (IS_ERR(lprops)) { err = PTR_ERR(lprops); diff --git a/fs/ubifs/lprops.c b/fs/ubifs/lprops.c index f8a181e647c..ea9d49164ff 100644 --- a/fs/ubifs/lprops.c +++ b/fs/ubifs/lprops.c @@ -300,8 +300,11 @@ void ubifs_add_to_cat(struct ubifs_info *c, struct ubifs_lprops *lprops, default: ubifs_assert(0); } + lprops->flags &= ~LPROPS_CAT_MASK; lprops->flags |= cat; + c->in_a_category_cnt += 1; + ubifs_assert(c->in_a_category_cnt <= c->main_lebs); } /** @@ -334,6 +337,9 @@ static void ubifs_remove_from_cat(struct ubifs_info *c, default: ubifs_assert(0); } + + c->in_a_category_cnt -= 1; + ubifs_assert(c->in_a_category_cnt >= 0); } /** diff --git a/fs/ubifs/sb.c b/fs/ubifs/sb.c index 771f7fb6ce9..a7be8e2b4b9 100644 --- a/fs/ubifs/sb.c +++ b/fs/ubifs/sb.c @@ -724,8 +724,12 @@ static int fixup_free_space(struct ubifs_info *c) lnum = ubifs_next_log_lnum(c, lnum); } - /* Fixup the current log head */ - err = fixup_leb(c, c->lhead_lnum, c->lhead_offs); + /* + * Fixup the log head which contains the only a CS node at the + * beginning. + */ + err = fixup_leb(c, c->lhead_lnum, + ALIGN(UBIFS_CS_NODE_SZ, c->min_io_size)); if (err) goto out; diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index 93d59aceaae..4971cb23b6c 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h @@ -1184,6 +1184,8 @@ struct ubifs_debug_info; * @freeable_list: list of freeable non-index LEBs (free + dirty == @leb_size) * @frdi_idx_list: list of freeable index LEBs (free + dirty == @leb_size) * @freeable_cnt: number of freeable LEBs in @freeable_list + * @in_a_category_cnt: count of lprops which are in a certain category, which + * basically meants that they were loaded from the flash * * @ltab_lnum: LEB number of LPT's own lprops table * @ltab_offs: offset of LPT's own lprops table @@ -1413,6 +1415,7 @@ struct ubifs_info { struct list_head freeable_list; struct list_head frdi_idx_list; int freeable_cnt; + int in_a_category_cnt; int ltab_lnum; int ltab_offs; diff --git a/fs/udf/file.c b/fs/udf/file.c index 7f3f7ba3df6..d1c6093fd3d 100644 --- a/fs/udf/file.c +++ b/fs/udf/file.c @@ -39,20 +39,24 @@ #include "udf_i.h" #include "udf_sb.h" -static int udf_adinicb_readpage(struct file *file, struct page *page) +static void __udf_adinicb_readpage(struct page *page) { struct inode *inode = page->mapping->host; char *kaddr; struct udf_inode_info *iinfo = UDF_I(inode); - BUG_ON(!PageLocked(page)); - kaddr = kmap(page); - memset(kaddr, 0, PAGE_CACHE_SIZE); memcpy(kaddr, iinfo->i_ext.i_data + iinfo->i_lenEAttr, inode->i_size); + memset(kaddr + inode->i_size, 0, PAGE_CACHE_SIZE - inode->i_size); flush_dcache_page(page); SetPageUptodate(page); kunmap(page); +} + +static int udf_adinicb_readpage(struct file *file, struct page *page) +{ + BUG_ON(!PageLocked(page)); + __udf_adinicb_readpage(page); unlock_page(page); return 0; @@ -77,6 +81,25 @@ static int udf_adinicb_writepage(struct page *page, return 0; } +static int udf_adinicb_write_begin(struct file *file, + struct address_space *mapping, loff_t pos, + unsigned len, unsigned flags, struct page **pagep, + void **fsdata) +{ + struct page *page; + + if (WARN_ON_ONCE(pos >= PAGE_CACHE_SIZE)) + return -EIO; + page = grab_cache_page_write_begin(mapping, 0, flags); + if (!page) + return -ENOMEM; + *pagep = page; + + if (!PageUptodate(page) && len != PAGE_CACHE_SIZE) + __udf_adinicb_readpage(page); + return 0; +} + static int udf_adinicb_write_end(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned copied, @@ -98,8 +121,8 @@ static int udf_adinicb_write_end(struct file *file, const struct address_space_operations udf_adinicb_aops = { .readpage = udf_adinicb_readpage, .writepage = udf_adinicb_writepage, - .write_begin = simple_write_begin, - .write_end = udf_adinicb_write_end, + .write_begin = udf_adinicb_write_begin, + .write_end = udf_adinicb_write_end, }; static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov, diff --git a/fs/udf/inode.c b/fs/udf/inode.c index 7d752800835..aa70035fb40 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c @@ -574,6 +574,7 @@ static sector_t inode_getblk(struct inode *inode, sector_t block, struct udf_inode_info *iinfo = UDF_I(inode); int goal = 0, pgoal = iinfo->i_location.logicalBlockNum; int lastblock = 0; + bool isBeyondEOF; *err = 0; *new = 0; @@ -653,7 +654,7 @@ static sector_t inode_getblk(struct inode *inode, sector_t block, /* Are we beyond EOF? */ if (etype == -1) { int ret; - + isBeyondEOF = 1; if (count) { if (c) laarr[0] = laarr[1]; @@ -696,6 +697,7 @@ static sector_t inode_getblk(struct inode *inode, sector_t block, endnum = c + 1; lastblock = 1; } else { + isBeyondEOF = 0; endnum = startnum = ((count > 2) ? 2 : count); /* if the current extent is in position 0, @@ -738,10 +740,13 @@ static sector_t inode_getblk(struct inode *inode, sector_t block, goal, err); if (!newblocknum) { brelse(prev_epos.bh); + brelse(cur_epos.bh); + brelse(next_epos.bh); *err = -ENOSPC; return 0; } - iinfo->i_lenExtents += inode->i_sb->s_blocksize; + if (isBeyondEOF) + iinfo->i_lenExtents += inode->i_sb->s_blocksize; } /* if the extent the requsted block is located in contains multiple @@ -768,6 +773,8 @@ static sector_t inode_getblk(struct inode *inode, sector_t block, udf_update_extents(inode, laarr, startnum, endnum, &prev_epos); brelse(prev_epos.bh); + brelse(cur_epos.bh); + brelse(next_epos.bh); newblock = udf_get_pblock(inode->i_sb, newblocknum, iinfo->i_location.partitionReferenceNum, 0); diff --git a/fs/udf/super.c b/fs/udf/super.c index 8d86a8706c0..4988a8afcc8 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -1283,10 +1283,11 @@ static int udf_load_logicalvol(struct super_block *sb, sector_t block, BUG_ON(ident != TAG_IDENT_LVD); lvd = (struct logicalVolDesc *)bh->b_data; table_len = le32_to_cpu(lvd->mapTableLength); - if (sizeof(*lvd) + table_len > sb->s_blocksize) { + if (table_len > sb->s_blocksize - sizeof(*lvd)) { udf_err(sb, "error loading logical volume descriptor: " "Partition table too long (%u > %lu)\n", table_len, sb->s_blocksize - sizeof(*lvd)); + ret = 1; goto out_bh; } @@ -1331,8 +1332,10 @@ static int udf_load_logicalvol(struct super_block *sb, sector_t block, UDF_ID_SPARABLE, strlen(UDF_ID_SPARABLE))) { if (udf_load_sparable_map(sb, map, - (struct sparablePartitionMap *)gpm) < 0) + (struct sparablePartitionMap *)gpm) < 0) { + ret = 1; goto out_bh; + } } else if (!strncmp(upm2->partIdent.ident, UDF_ID_METADATA, strlen(UDF_ID_METADATA))) { diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index 0dbb9e70fe2..7a978c7be84 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c @@ -89,11 +89,11 @@ xfs_destroy_ioend( } if (ioend->io_iocb) { + inode_dio_done(ioend->io_inode); if (ioend->io_isasync) { aio_complete(ioend->io_iocb, ioend->io_error ? ioend->io_error : ioend->io_result, 0); } - inode_dio_done(ioend->io_inode); } mempool_free(ioend, xfs_ioend_pool); diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c index 6819b5163e3..bb76128b5f4 100644 --- a/fs/xfs/xfs_buf.c +++ b/fs/xfs/xfs_buf.c @@ -1165,9 +1165,14 @@ xfs_buf_bio_end_io( { xfs_buf_t *bp = (xfs_buf_t *)bio->bi_private; - xfs_buf_ioerror(bp, -error); + /* + * don't overwrite existing errors - otherwise we can lose errors on + * buffers that require multiple bios to complete. + */ + if (!bp->b_error) + xfs_buf_ioerror(bp, -error); - if (!error && xfs_buf_is_vmapped(bp) && (bp->b_flags & XBF_READ)) + if (!bp->b_error && xfs_buf_is_vmapped(bp) && (bp->b_flags & XBF_READ)) invalidate_kernel_vmap_range(bp->b_addr, xfs_buf_vmap_len(bp)); _xfs_buf_ioend(bp, 1); @@ -1243,6 +1248,11 @@ _xfs_buf_ioapply( if (size) goto next_chunk; } else { + /* + * This is guaranteed not to be the last io reference count + * because the caller (xfs_buf_iorequest) holds a count itself. + */ + atomic_dec(&bp->b_io_remaining); xfs_buf_ioerror(bp, EIO); bio_put(bio); } diff --git a/fs/xfs/xfs_export.c b/fs/xfs/xfs_export.c index 558910f5e3c..5703fb85f6b 100644 --- a/fs/xfs/xfs_export.c +++ b/fs/xfs/xfs_export.c @@ -195,6 +195,9 @@ xfs_fs_fh_to_parent(struct super_block *sb, struct fid *fid, struct xfs_fid64 *fid64 = (struct xfs_fid64 *)fid; struct inode *inode = NULL; + if (fh_len < xfs_fileid_length(fileid_type)) + return NULL; + switch (fileid_type) { case FILEID_INO32_GEN_PARENT: inode = xfs_nfs_get_inode(sb, fid->i32.parent_ino, diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 8ecad5bad66..0abb1623a7c 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -3514,7 +3514,7 @@ xlog_do_recovery_pass( * - order is important. */ error = xlog_bread_offset(log, 0, - bblks - split_bblks, hbp, + bblks - split_bblks, dbp, offset + BBTOB(split_bblks)); if (error) goto bread_err2; diff --git a/include/asm-generic/tlb.h b/include/asm-generic/tlb.h index f96a5b58a97..979ed15724a 100644 --- a/include/asm-generic/tlb.h +++ b/include/asm-generic/tlb.h @@ -78,6 +78,14 @@ struct mmu_gather_batch { #define MAX_GATHER_BATCH \ ((PAGE_SIZE - sizeof(struct mmu_gather_batch)) / sizeof(void *)) +/* + * Limit the maximum number of mmu_gather batches to reduce a risk of soft + * lockups for non-preemptible kernels on huge machines when a lot of memory + * is zapped during unmapping. + * 10K pages freed at once should be safe even without a preemption point. + */ +#define MAX_GATHER_BATCH_COUNT (10000UL/MAX_GATHER_BATCH) + /* struct mmu_gather is an opaque type used by the mm code for passing around * any data needed by arch specific code for tlb_remove_page. */ @@ -94,6 +102,7 @@ struct mmu_gather { struct mmu_gather_batch *active; struct mmu_gather_batch local; struct page *__pages[MMU_GATHER_BUNDLE]; + unsigned int batch_count; }; #define HAVE_GENERIC_MMU_GATHER diff --git a/include/drm/drm_mode.h b/include/drm/drm_mode.h index 4a0aae38e16..9242310b47c 100644 --- a/include/drm/drm_mode.h +++ b/include/drm/drm_mode.h @@ -343,8 +343,9 @@ struct drm_mode_mode_cmd { struct drm_mode_modeinfo mode; }; -#define DRM_MODE_CURSOR_BO (1<<0) -#define DRM_MODE_CURSOR_MOVE (1<<1) +#define DRM_MODE_CURSOR_BO 0x01 +#define DRM_MODE_CURSOR_MOVE 0x02 +#define DRM_MODE_CURSOR_FLAGS 0x03 /* * depending on the value in flags different members are used. diff --git a/include/drm/drm_pciids.h b/include/drm/drm_pciids.h index 81368ab6c61..7207a99bdf8 100644 --- a/include/drm/drm_pciids.h +++ b/include/drm/drm_pciids.h @@ -209,17 +209,24 @@ {0x1002, 0x6788, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ {0x1002, 0x678A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6790, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6791, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6792, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6798, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6799, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ {0x1002, 0x679A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x679B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ {0x1002, 0x679E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ {0x1002, 0x679F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6800, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6801, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6802, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6806, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6808, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6809, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6810, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6811, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6816, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6817, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6818, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6819, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6820, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ diff --git a/include/linux/Kbuild b/include/linux/Kbuild index 183da95aad3..fefa9192309 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -282,6 +282,7 @@ header-y += netfilter_ipv4.h header-y += netfilter_ipv6.h header-y += netlink.h header-y += netrom.h +header-y += nfc.h header-y += nfs.h header-y += nfs2.h header-y += nfs3.h diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h index 366422bc163..eb53e15ede6 100644 --- a/include/linux/binfmts.h +++ b/include/linux/binfmts.h @@ -128,6 +128,7 @@ extern int setup_arg_pages(struct linux_binprm * bprm, unsigned long stack_top, int executable_stack); extern int bprm_mm_init(struct linux_binprm *bprm); +extern int bprm_change_interp(char *interp, struct linux_binprm *bprm); extern int copy_strings_kernel(int argc, const char *const *argv, struct linux_binprm *bprm); extern int prepare_bprm_creds(struct linux_binprm *bprm); diff --git a/include/linux/bug.h b/include/linux/bug.h index 72961c39576..cd141a4a085 100644 --- a/include/linux/bug.h +++ b/include/linux/bug.h @@ -96,4 +96,10 @@ static inline enum bug_trap_type report_bug(unsigned long bug_addr, } #endif /* CONFIG_GENERIC_BUG */ + +#ifdef CONFIG_PANIC_ON_DATA_CORRUPTION +#define PANIC_CORRUPTION 1 +#else +#define PANIC_CORRUPTION 0 +#endif /* CONFIG_PANIC_ON_DATA_CORRUPTION */ #endif /* _LINUX_BUG_H */ diff --git a/include/linux/ceph/auth.h b/include/linux/ceph/auth.h index aa13392a7ef..d4080f309b5 100644 --- a/include/linux/ceph/auth.h +++ b/include/linux/ceph/auth.h @@ -14,6 +14,14 @@ struct ceph_auth_client; struct ceph_authorizer; +struct ceph_auth_handshake { + struct ceph_authorizer *authorizer; + void *authorizer_buf; + size_t authorizer_buf_len; + void *authorizer_reply_buf; + size_t authorizer_reply_buf_len; +}; + struct ceph_auth_client_ops { const char *name; @@ -43,9 +51,7 @@ struct ceph_auth_client_ops { * the response to authenticate the service. */ int (*create_authorizer)(struct ceph_auth_client *ac, int peer_type, - struct ceph_authorizer **a, - void **buf, size_t *len, - void **reply_buf, size_t *reply_len); + struct ceph_auth_handshake *auth); int (*verify_authorizer_reply)(struct ceph_auth_client *ac, struct ceph_authorizer *a, size_t len); void (*destroy_authorizer)(struct ceph_auth_client *ac, diff --git a/include/linux/ceph/libceph.h b/include/linux/ceph/libceph.h index e71d683982a..893420b78d0 100644 --- a/include/linux/ceph/libceph.h +++ b/include/linux/ceph/libceph.h @@ -49,7 +49,6 @@ struct ceph_options { struct ceph_entity_addr my_addr; int mount_timeout; int osd_idle_ttl; - int osd_timeout; int osd_keepalive_timeout; /* @@ -69,7 +68,6 @@ struct ceph_options { * defaults */ #define CEPH_MOUNT_TIMEOUT_DEFAULT 60 -#define CEPH_OSD_TIMEOUT_DEFAULT 60 /* seconds */ #define CEPH_OSD_KEEPALIVE_DEFAULT 5 #define CEPH_OSD_IDLE_TTL_DEFAULT 60 @@ -132,7 +130,7 @@ struct ceph_client { u32 supported_features; u32 required_features; - struct ceph_messenger *msgr; /* messenger instance */ + struct ceph_messenger msgr; /* messenger instance */ struct ceph_mon_client monc; struct ceph_osd_client osdc; diff --git a/include/linux/ceph/messenger.h b/include/linux/ceph/messenger.h index 3bff047f6b0..189ae063763 100644 --- a/include/linux/ceph/messenger.h +++ b/include/linux/ceph/messenger.h @@ -25,15 +25,12 @@ struct ceph_connection_operations { void (*dispatch) (struct ceph_connection *con, struct ceph_msg *m); /* authorize an outgoing connection */ - int (*get_authorizer) (struct ceph_connection *con, - void **buf, int *len, int *proto, - void **reply_buf, int *reply_len, int force_new); + struct ceph_auth_handshake *(*get_authorizer) ( + struct ceph_connection *con, + int *proto, int force_new); int (*verify_authorizer_reply) (struct ceph_connection *con, int len); int (*invalidate_authorizer)(struct ceph_connection *con); - /* protocol version mismatch */ - void (*bad_proto) (struct ceph_connection *con); - /* there was some error on the socket (disconnect, whatever) */ void (*fault) (struct ceph_connection *con); @@ -53,6 +50,7 @@ struct ceph_messenger { struct ceph_entity_inst inst; /* my name+address */ struct ceph_entity_addr my_enc_addr; + atomic_t stopping; bool nocrc; /* @@ -80,7 +78,10 @@ struct ceph_msg { unsigned nr_pages; /* size of page array */ unsigned page_alignment; /* io offset in first page */ struct ceph_pagelist *pagelist; /* instead of pages */ + + struct ceph_connection *con; struct list_head list_head; + struct kref kref; struct bio *bio; /* instead of pages/pagelist */ struct bio *bio_iter; /* bio iterator */ @@ -105,23 +106,6 @@ struct ceph_msg_pos { #define BASE_DELAY_INTERVAL (HZ/2) #define MAX_DELAY_INTERVAL (5 * 60 * HZ) -/* - * ceph_connection state bit flags - */ -#define LOSSYTX 0 /* we can close channel or drop messages on errors */ -#define CONNECTING 1 -#define NEGOTIATING 2 -#define KEEPALIVE_PENDING 3 -#define WRITE_PENDING 4 /* we have data ready to send */ -#define STANDBY 8 /* no outgoing messages, socket closed. we keep - * the ceph_connection around to maintain shared - * state with the peer. */ -#define CLOSED 10 /* we've closed the connection */ -#define SOCK_CLOSED 11 /* socket state changed to closed */ -#define OPENING 13 /* open connection w/ (possibly new) peer */ -#define DEAD 14 /* dead, about to kfree */ -#define BACKOFF 15 - /* * A single connection with another host. * @@ -131,18 +115,22 @@ struct ceph_msg_pos { */ struct ceph_connection { void *private; - atomic_t nref; const struct ceph_connection_operations *ops; struct ceph_messenger *msgr; + + atomic_t sock_state; struct socket *sock; - unsigned long state; /* connection state (see flags above) */ + struct ceph_entity_addr peer_addr; /* peer address */ + struct ceph_entity_addr peer_addr_for_me; + + unsigned long flags; + unsigned long state; const char *error_msg; /* error message, if any */ - struct ceph_entity_addr peer_addr; /* peer address */ struct ceph_entity_name peer_name; /* peer name */ - struct ceph_entity_addr peer_addr_for_me; + unsigned peer_features; u32 connect_seq; /* identify the most recent connection attempt for this connection, client */ @@ -163,16 +151,8 @@ struct ceph_connection { /* connection negotiation temps */ char in_banner[CEPH_BANNER_MAX_LEN]; - union { - struct { /* outgoing connection */ - struct ceph_msg_connect out_connect; - struct ceph_msg_connect_reply in_reply; - }; - struct { /* incoming */ - struct ceph_msg_connect in_connect; - struct ceph_msg_connect_reply out_reply; - }; - }; + struct ceph_msg_connect out_connect; + struct ceph_msg_connect_reply in_reply; struct ceph_entity_addr actual_peer_addr; /* message out temps */ @@ -215,24 +195,26 @@ extern int ceph_msgr_init(void); extern void ceph_msgr_exit(void); extern void ceph_msgr_flush(void); -extern struct ceph_messenger *ceph_messenger_create( - struct ceph_entity_addr *myaddr, - u32 features, u32 required); -extern void ceph_messenger_destroy(struct ceph_messenger *); +extern void ceph_messenger_init(struct ceph_messenger *msgr, + struct ceph_entity_addr *myaddr, + u32 supported_features, + u32 required_features, + bool nocrc); -extern void ceph_con_init(struct ceph_messenger *msgr, - struct ceph_connection *con); +extern void ceph_con_init(struct ceph_connection *con, void *private, + const struct ceph_connection_operations *ops, + struct ceph_messenger *msgr); extern void ceph_con_open(struct ceph_connection *con, + __u8 entity_type, __u64 entity_num, struct ceph_entity_addr *addr); extern bool ceph_con_opened(struct ceph_connection *con); extern void ceph_con_close(struct ceph_connection *con); extern void ceph_con_send(struct ceph_connection *con, struct ceph_msg *msg); -extern void ceph_con_revoke(struct ceph_connection *con, struct ceph_msg *msg); -extern void ceph_con_revoke_message(struct ceph_connection *con, - struct ceph_msg *msg); + +extern void ceph_msg_revoke(struct ceph_msg *msg); +extern void ceph_msg_revoke_incoming(struct ceph_msg *msg); + extern void ceph_con_keepalive(struct ceph_connection *con); -extern struct ceph_connection *ceph_con_get(struct ceph_connection *con); -extern void ceph_con_put(struct ceph_connection *con); extern struct ceph_msg *ceph_msg_new(int type, int front_len, gfp_t flags, bool can_fail); diff --git a/include/linux/ceph/mon_client.h b/include/linux/ceph/mon_client.h index 545f8591778..2113e3850a4 100644 --- a/include/linux/ceph/mon_client.h +++ b/include/linux/ceph/mon_client.h @@ -70,7 +70,7 @@ struct ceph_mon_client { bool hunting; int cur_mon; /* last monitor i contacted */ unsigned long sub_sent, sub_renew_after; - struct ceph_connection *con; + struct ceph_connection con; bool have_fsid; /* pending generic requests */ diff --git a/include/linux/ceph/msgpool.h b/include/linux/ceph/msgpool.h index a362605f936..09fa96b4343 100644 --- a/include/linux/ceph/msgpool.h +++ b/include/linux/ceph/msgpool.h @@ -11,10 +11,11 @@ struct ceph_msgpool { const char *name; mempool_t *pool; + int type; /* preallocated message type */ int front_len; /* preallocated payload size */ }; -extern int ceph_msgpool_init(struct ceph_msgpool *pool, +extern int ceph_msgpool_init(struct ceph_msgpool *pool, int type, int front_len, int size, bool blocking, const char *name); extern void ceph_msgpool_destroy(struct ceph_msgpool *pool); diff --git a/include/linux/ceph/osd_client.h b/include/linux/ceph/osd_client.h index 7c05ac202d9..d9b880e977e 100644 --- a/include/linux/ceph/osd_client.h +++ b/include/linux/ceph/osd_client.h @@ -6,9 +6,10 @@ #include #include -#include "types.h" -#include "osdmap.h" -#include "messenger.h" +#include +#include +#include +#include /* * Maximum object name size @@ -40,9 +41,7 @@ struct ceph_osd { struct list_head o_requests; struct list_head o_linger_requests; struct list_head o_osd_lru; - struct ceph_authorizer *o_authorizer; - void *o_authorizer_buf, *o_authorizer_reply_buf; - size_t o_authorizer_buf_len, o_authorizer_reply_buf_len; + struct ceph_auth_handshake o_auth; unsigned long lru_ttl; int o_marked_for_keepalive; struct list_head o_keepalive_item; @@ -208,7 +207,7 @@ extern void ceph_osdc_handle_reply(struct ceph_osd_client *osdc, extern void ceph_osdc_handle_map(struct ceph_osd_client *osdc, struct ceph_msg *msg); -extern void ceph_calc_raw_layout(struct ceph_osd_client *osdc, +extern int ceph_calc_raw_layout(struct ceph_osd_client *osdc, struct ceph_file_layout *layout, u64 snapid, u64 off, u64 *plen, u64 *bno, diff --git a/include/linux/ceph/osdmap.h b/include/linux/ceph/osdmap.h index ba4c205cbb0..11db454f786 100644 --- a/include/linux/ceph/osdmap.h +++ b/include/linux/ceph/osdmap.h @@ -111,9 +111,9 @@ extern struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end, extern void ceph_osdmap_destroy(struct ceph_osdmap *map); /* calculate mapping of a file extent to an object */ -extern void ceph_calc_file_object_mapping(struct ceph_file_layout *layout, - u64 off, u64 *plen, - u64 *bno, u64 *oxoff, u64 *oxlen); +extern int ceph_calc_file_object_mapping(struct ceph_file_layout *layout, + u64 off, u64 *plen, + u64 *bno, u64 *oxoff, u64 *oxlen); /* calculate mapping of object to a placement group */ extern int ceph_calc_object_layout(struct ceph_object_layout *ol, diff --git a/include/linux/cpu.h b/include/linux/cpu.h index d50d59d8e1b..80227bc090a 100644 --- a/include/linux/cpu.h +++ b/include/linux/cpu.h @@ -75,8 +75,9 @@ enum { /* migration should happen before other stuff but after perf */ CPU_PRI_PERF = 20, CPU_PRI_MIGRATION = 10, - /* prepare workqueues for other notifiers */ - CPU_PRI_WORKQUEUE = 5, + /* bring up workqueues before normal notifiers and down after */ + CPU_PRI_WORKQUEUE_UP = 5, + CPU_PRI_WORKQUEUE_DOWN = -5, }; #define CPU_ONLINE 0x0002 /* CPU (unsigned)v is up */ diff --git a/include/linux/crush/crush.h b/include/linux/crush/crush.h index 97e435b191f..e7a8c9055cb 100644 --- a/include/linux/crush/crush.h +++ b/include/linux/crush/crush.h @@ -168,7 +168,7 @@ struct crush_map { /* crush.c */ -extern int crush_get_bucket_item_weight(struct crush_bucket *b, int pos); +extern int crush_get_bucket_item_weight(const struct crush_bucket *b, int pos); extern void crush_calc_parents(struct crush_map *map); extern void crush_destroy_bucket_uniform(struct crush_bucket_uniform *b); extern void crush_destroy_bucket_list(struct crush_bucket_list *b); @@ -177,4 +177,9 @@ extern void crush_destroy_bucket_straw(struct crush_bucket_straw *b); extern void crush_destroy_bucket(struct crush_bucket *b); extern void crush_destroy(struct crush_map *map); +static inline int crush_calc_tree_node(int i) +{ + return ((i+1) << 1)-1; +} + #endif diff --git a/include/linux/crush/mapper.h b/include/linux/crush/mapper.h index c46b99c18bb..9322ab8bccd 100644 --- a/include/linux/crush/mapper.h +++ b/include/linux/crush/mapper.h @@ -10,11 +10,11 @@ #include "crush.h" -extern int crush_find_rule(struct crush_map *map, int pool, int type, int size); -extern int crush_do_rule(struct crush_map *map, +extern int crush_find_rule(const struct crush_map *map, int ruleset, int type, int size); +extern int crush_do_rule(const struct crush_map *map, int ruleno, int x, int *result, int result_max, int forcefeed, /* -1 for none */ - __u32 *weights); + const __u32 *weights); #endif diff --git a/include/linux/dcache.h b/include/linux/dcache.h index 7e11f141820..1332df02d8f 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h @@ -191,6 +191,8 @@ struct dentry_operations { #define DCACHE_MANAGED_DENTRY \ (DCACHE_MOUNTED|DCACHE_NEED_AUTOMOUNT|DCACHE_MANAGE_TRANSIT) +#define DCACHE_DENTRY_KILLED 0x100000 + extern seqlock_t rename_lock; static inline int dname_external(struct dentry *dentry) diff --git a/include/linux/efi.h b/include/linux/efi.h index ec45ccd8708..5782114f483 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -496,6 +496,11 @@ extern void efi_map_pal_code (void); extern void efi_memmap_walk (efi_freemem_callback_t callback, void *arg); extern void efi_gettimeofday (struct timespec *ts); extern void efi_enter_virtual_mode (void); /* switch EFI to virtual mode, if possible */ +#ifdef CONFIG_X86 +extern void efi_free_boot_services(void); +#else +static inline void efi_free_boot_services(void) {} +#endif extern u64 efi_get_iobase (void); extern u32 efi_mem_type (unsigned long phys_addr); extern u64 efi_mem_attributes (unsigned long phys_addr); diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h index fd0dc30c9f1..cc07d2777bb 100644 --- a/include/linux/hrtimer.h +++ b/include/linux/hrtimer.h @@ -165,6 +165,7 @@ enum hrtimer_base_type { * @lock: lock protecting the base and associated clock bases * and timers * @active_bases: Bitfield to mark bases with active timers + * @clock_was_set: Indicates that clock was set from irq context. * @expires_next: absolute time of the next event which was scheduled * via clock_set_next_event() * @hres_active: State of high resolution mode @@ -177,7 +178,8 @@ enum hrtimer_base_type { */ struct hrtimer_cpu_base { raw_spinlock_t lock; - unsigned long active_bases; + unsigned int active_bases; + unsigned int clock_was_set; #ifdef CONFIG_HIGH_RES_TIMERS ktime_t expires_next; int hres_active; @@ -286,6 +288,8 @@ extern void hrtimer_peek_ahead_timers(void); # define MONOTONIC_RES_NSEC HIGH_RES_NSEC # define KTIME_MONOTONIC_RES KTIME_HIGH_RES +extern void clock_was_set_delayed(void); + #else # define MONOTONIC_RES_NSEC LOW_RES_NSEC @@ -306,6 +310,9 @@ static inline int hrtimer_is_hres_active(struct hrtimer *timer) { return 0; } + +static inline void clock_was_set_delayed(void) { } + #endif extern void clock_was_set(void); @@ -320,6 +327,7 @@ extern ktime_t ktime_get(void); extern ktime_t ktime_get_real(void); extern ktime_t ktime_get_boottime(void); extern ktime_t ktime_get_monotonic_offset(void); +extern ktime_t ktime_get_update_offsets(ktime_t *offs_real, ktime_t *offs_boot); DECLARE_PER_CPU(struct tick_device, tick_cpu_device); diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h index a810987cb80..561e130df0b 100644 --- a/include/linux/if_vlan.h +++ b/include/linux/if_vlan.h @@ -82,6 +82,8 @@ static inline int is_vlan_dev(struct net_device *dev) } #define vlan_tx_tag_present(__skb) ((__skb)->vlan_tci & VLAN_TAG_PRESENT) +#define vlan_tx_nonzero_tag_present(__skb) \ + (vlan_tx_tag_present(__skb) && ((__skb)->vlan_tci & VLAN_VID_MASK)) #define vlan_tx_tag_get(__skb) ((__skb)->vlan_tci & ~VLAN_TAG_PRESENT) #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) @@ -91,7 +93,7 @@ extern struct net_device *__vlan_find_dev_deep(struct net_device *real_dev, extern struct net_device *vlan_dev_real_dev(const struct net_device *dev); extern u16 vlan_dev_vlan_id(const struct net_device *dev); -extern bool vlan_do_receive(struct sk_buff **skb, bool last_handler); +extern bool vlan_do_receive(struct sk_buff **skb); extern struct sk_buff *vlan_untag(struct sk_buff *skb); extern int vlan_vid_add(struct net_device *dev, unsigned short vid); @@ -120,10 +122,8 @@ static inline u16 vlan_dev_vlan_id(const struct net_device *dev) return 0; } -static inline bool vlan_do_receive(struct sk_buff **skb, bool last_handler) +static inline bool vlan_do_receive(struct sk_buff **skb) { - if (((*skb)->vlan_tci & VLAN_VID_MASK) && last_handler) - (*skb)->pkt_type = PACKET_OTHERHOST; return false; } diff --git a/include/linux/init_task.h b/include/linux/init_task.h index e4baff5f7ff..f4d400d8b0d 100644 --- a/include/linux/init_task.h +++ b/include/linux/init_task.h @@ -123,8 +123,17 @@ extern struct group_info init_groups; extern struct cred init_cred; +extern struct task_group root_task_group; + +#ifdef CONFIG_CGROUP_SCHED +# define INIT_CGROUP_SCHED(tsk) \ + .sched_task_group = &root_task_group, +#else +# define INIT_CGROUP_SCHED(tsk) +#endif + #ifdef CONFIG_PERF_EVENTS -# define INIT_PERF_EVENTS(tsk) \ +# define INIT_PERF_EVENTS(tsk) \ .perf_event_mutex = \ __MUTEX_INITIALIZER(tsk.perf_event_mutex), \ .perf_event_list = LIST_HEAD_INIT(tsk.perf_event_list), @@ -160,7 +169,7 @@ extern struct cred init_cred; .nr_cpus_allowed = NR_CPUS, \ }, \ .tasks = LIST_HEAD_INIT(tsk.tasks), \ - INIT_PUSHABLE_TASKS(tsk) \ + INIT_CGROUP_SCHED(tsk) \ .ptraced = LIST_HEAD_INIT(tsk.ptraced), \ .ptrace_entry = LIST_HEAD_INIT(tsk.ptrace_entry), \ .real_parent = &tsk, \ diff --git a/include/linux/input/eeti_ts.h b/include/linux/input/eeti_ts.h index f875b316249..16625d799b6 100644 --- a/include/linux/input/eeti_ts.h +++ b/include/linux/input/eeti_ts.h @@ -2,6 +2,7 @@ #define LINUX_INPUT_EETI_TS_H struct eeti_ts_platform_data { + int irq_gpio; unsigned int irq_active_high; }; diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h index 912c30a8ddb..2ed66ef2e68 100644 --- a/include/linux/jbd2.h +++ b/include/linux/jbd2.h @@ -1091,6 +1091,7 @@ extern int jbd2_journal_destroy (journal_t *); extern int jbd2_journal_recover (journal_t *journal); extern int jbd2_journal_wipe (journal_t *, int); extern int jbd2_journal_skip_recovery (journal_t *); +extern void jbd2_journal_update_sb_errno(journal_t *); extern void jbd2_journal_update_sb_log_tail (journal_t *, tid_t, unsigned long, int); extern void __jbd2_journal_abort_hard (journal_t *); diff --git a/include/linux/kobject.h b/include/linux/kobject.h index fc615a97e2d..1e57449395b 100644 --- a/include/linux/kobject.h +++ b/include/linux/kobject.h @@ -224,7 +224,7 @@ static inline int kobject_uevent_env(struct kobject *kobj, static inline __printf(2, 3) int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...) -{ return 0; } +{ return -ENOMEM; } static inline int kobject_action_type(const char *buf, size_t count, enum kobject_action *type) diff --git a/include/linux/ktime.h b/include/linux/ktime.h index 603bec2913b..06177ba10a1 100644 --- a/include/linux/ktime.h +++ b/include/linux/ktime.h @@ -58,13 +58,6 @@ union ktime { typedef union ktime ktime_t; /* Kill this */ -#define KTIME_MAX ((s64)~((u64)1 << 63)) -#if (BITS_PER_LONG == 64) -# define KTIME_SEC_MAX (KTIME_MAX / NSEC_PER_SEC) -#else -# define KTIME_SEC_MAX LONG_MAX -#endif - /* * ktime_t definitions when using the 64-bit scalar representation: */ diff --git a/include/linux/memblock.h b/include/linux/memblock.h index 224336260a7..281ae756bf1 100644 --- a/include/linux/memblock.h +++ b/include/linux/memblock.h @@ -57,6 +57,7 @@ int memblock_add(phys_addr_t base, phys_addr_t size); int memblock_remove(phys_addr_t base, phys_addr_t size); int memblock_free(phys_addr_t base, phys_addr_t size); int memblock_reserve(phys_addr_t base, phys_addr_t size); +void memblock_trim_memory(phys_addr_t align); #ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP void __next_mem_pfn_range(int *idx, int nid, unsigned long *out_start_pfn, diff --git a/include/linux/memory.h b/include/linux/memory.h index 1ac7f6e405f..ff9a9f8e0ed 100644 --- a/include/linux/memory.h +++ b/include/linux/memory.h @@ -19,7 +19,7 @@ #include #include -#define MIN_MEMORY_BLOCK_SIZE (1 << SECTION_SIZE_BITS) +#define MIN_MEMORY_BLOCK_SIZE (1UL << SECTION_SIZE_BITS) struct memory_block { unsigned long start_section_nr; diff --git a/include/linux/mempolicy.h b/include/linux/mempolicy.h index 7c727a90d70..fe07e5a9056 100644 --- a/include/linux/mempolicy.h +++ b/include/linux/mempolicy.h @@ -137,16 +137,6 @@ static inline void mpol_cond_put(struct mempolicy *pol) __mpol_put(pol); } -extern struct mempolicy *__mpol_cond_copy(struct mempolicy *tompol, - struct mempolicy *frompol); -static inline struct mempolicy *mpol_cond_copy(struct mempolicy *tompol, - struct mempolicy *frompol) -{ - if (!frompol) - return frompol; - return __mpol_cond_copy(tompol, frompol); -} - extern struct mempolicy *__mpol_dup(struct mempolicy *pol); static inline struct mempolicy *mpol_dup(struct mempolicy *pol) { @@ -188,7 +178,7 @@ struct sp_node { struct shared_policy { struct rb_root root; - spinlock_t lock; + struct mutex mutex; }; void mpol_shared_policy_init(struct shared_policy *sp, struct mempolicy *mpol); @@ -270,12 +260,6 @@ static inline void mpol_cond_put(struct mempolicy *pol) { } -static inline struct mempolicy *mpol_cond_copy(struct mempolicy *to, - struct mempolicy *from) -{ - return from; -} - static inline void mpol_get(struct mempolicy *pol) { } diff --git a/include/linux/mfd/ezx-pcap.h b/include/linux/mfd/ezx-pcap.h index 40c372165f3..32a1b5cfeba 100644 --- a/include/linux/mfd/ezx-pcap.h +++ b/include/linux/mfd/ezx-pcap.h @@ -16,6 +16,7 @@ struct pcap_subdev { struct pcap_platform_data { unsigned int irq_base; unsigned int config; + int gpio; void (*init) (void *); /* board specific init */ int num_subdevs; struct pcap_subdev *subdevs; diff --git a/include/linux/mm.h b/include/linux/mm.h index 379fe6a3eb7..cb67f136a6a 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -1599,6 +1599,7 @@ void vmemmap_populate_print_last(void); enum mf_flags { MF_COUNT_INCREASED = 1 << 0, MF_ACTION_REQUIRED = 1 << 1, + MF_MUST_KILL = 1 << 2, }; extern int memory_failure(unsigned long pfn, int trapno, int flags); extern void memory_failure_queue(unsigned long pfn, int trapno, int flags); diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 1482340d3d9..24835134471 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -215,9 +215,6 @@ typedef enum { #define NAND_SUBPAGE_READ(chip) ((chip->ecc.mode == NAND_ECC_SOFT) \ && (chip->page_shift > 9)) -/* Mask to zero out the chip options, which come from the id table */ -#define NAND_CHIPOPTIONS_MSK (0x0000ffff & ~NAND_NO_AUTOINCR) - /* Non chip related options */ /* This option skips the bbt scan during initialization. */ #define NAND_SKIP_BBTSCAN 0x00010000 diff --git a/include/linux/net.h b/include/linux/net.h index be60c7f5e14..95fea1432dd 100644 --- a/include/linux/net.h +++ b/include/linux/net.h @@ -72,6 +72,7 @@ struct net; #define SOCK_NOSPACE 2 #define SOCK_PASSCRED 3 #define SOCK_PASSSEC 4 +#define SOCK_EXTERNALLY_ALLOCATED 5 #ifndef ARCH_HAS_SOCKET_TYPES /** diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 33900a53c99..e517695704c 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1279,6 +1279,8 @@ struct net_device { /* for setting kernel sock attribute on TCP connection setup */ #define GSO_MAX_SIZE 65536 unsigned int gso_max_size; +#define GSO_MAX_SEGS 65535 + u16 gso_max_segs; #ifdef CONFIG_DCB /* Data Center Bridging netlink ops */ @@ -1494,6 +1496,8 @@ struct packet_type { struct sk_buff **(*gro_receive)(struct sk_buff **head, struct sk_buff *skb); int (*gro_complete)(struct sk_buff *skb); + bool (*id_match)(struct packet_type *ptype, + struct sock *sk); void *af_packet_priv; struct list_head list; }; diff --git a/include/linux/netfilter/ipset/ip_set_timeout.h b/include/linux/netfilter/ipset/ip_set_timeout.h index 47923205a4a..41d9cfa0816 100644 --- a/include/linux/netfilter/ipset/ip_set_timeout.h +++ b/include/linux/netfilter/ipset/ip_set_timeout.h @@ -30,6 +30,10 @@ ip_set_timeout_uget(struct nlattr *tb) { unsigned int timeout = ip_set_get_h32(tb); + /* Normalize to fit into jiffies */ + if (timeout > UINT_MAX/MSEC_PER_SEC) + timeout = UINT_MAX/MSEC_PER_SEC; + /* Userspace supplied TIMEOUT parameter: adjust crazy size */ return timeout == IPSET_NO_TIMEOUT ? IPSET_NO_TIMEOUT - 1 : timeout; } diff --git a/include/linux/netlink.h b/include/linux/netlink.h index a2092f582a7..b23e9cd6a88 100644 --- a/include/linux/netlink.h +++ b/include/linux/netlink.h @@ -153,6 +153,7 @@ struct nlattr { #include #include +#include struct net; @@ -226,6 +227,8 @@ struct netlink_callback { struct netlink_callback *cb); int (*done)(struct netlink_callback *cb); void *data; + /* the module that dump function belong to */ + struct module *module; u16 family; u16 min_dump_alloc; unsigned int prev_seq, seq; @@ -251,14 +254,24 @@ __nlmsg_put(struct sk_buff *skb, u32 pid, u32 seq, int type, int len, int flags) struct netlink_dump_control { int (*dump)(struct sk_buff *skb, struct netlink_callback *); - int (*done)(struct netlink_callback*); + int (*done)(struct netlink_callback *); void *data; + struct module *module; u16 min_dump_alloc; }; -extern int netlink_dump_start(struct sock *ssk, struct sk_buff *skb, - const struct nlmsghdr *nlh, - struct netlink_dump_control *control); +extern int __netlink_dump_start(struct sock *ssk, struct sk_buff *skb, + const struct nlmsghdr *nlh, + struct netlink_dump_control *control); +static inline int netlink_dump_start(struct sock *ssk, struct sk_buff *skb, + const struct nlmsghdr *nlh, + struct netlink_dump_control *control) +{ + if (!control->module) + control->module = THIS_MODULE; + + return __netlink_dump_start(ssk, skb, nlh, control); +} #define NL_NONROOT_RECV 0x1 diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index 52a1bdb4ee2..941d688c203 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h @@ -264,11 +264,6 @@ static inline const struct nfs_rpc_ops *NFS_PROTO(const struct inode *inode) return NFS_SERVER(inode)->nfs_client->rpc_ops; } -static inline __be32 *NFS_COOKIEVERF(const struct inode *inode) -{ - return NFS_I(inode)->cookieverf; -} - static inline unsigned NFS_MINATTRTIMEO(const struct inode *inode) { struct nfs_server *nfss = NFS_SERVER(inode); diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h index c88d2a9451a..4dabf0fe527 100644 --- a/include/linux/page-flags.h +++ b/include/linux/page-flags.h @@ -361,7 +361,7 @@ static inline void ClearPageCompound(struct page *page) * pages on the LRU and/or pagecache. */ TESTPAGEFLAG(Compound, compound) -__PAGEFLAG(Head, compound) +__SETPAGEFLAG(Head, compound) __CLEARPAGEFLAG(Head, compound) /* * PG_reclaim is used in combination with PG_compound to mark the @@ -373,8 +373,14 @@ __PAGEFLAG(Head, compound) * PG_compound & PG_reclaim => Tail page * PG_compound & ~PG_reclaim => Head page */ +#define PG_head_mask ((1L << PG_compound)) #define PG_head_tail_mask ((1L << PG_compound) | (1L << PG_reclaim)) +static inline int PageHead(struct page *page) +{ + return ((page->flags & PG_head_tail_mask) == PG_head_mask); +} + static inline int PageTail(struct page *page) { return ((page->flags & PG_head_tail_mask) == PG_head_tail_mask); diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 3329965ed63..d7dbf4ec89d 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1565,6 +1565,7 @@ #define PCI_DEVICE_ID_RICOH_RL5C476 0x0476 #define PCI_DEVICE_ID_RICOH_RL5C478 0x0478 #define PCI_DEVICE_ID_RICOH_R5C822 0x0822 +#define PCI_DEVICE_ID_RICOH_R5CE822 0xe822 #define PCI_DEVICE_ID_RICOH_R5CE823 0xe823 #define PCI_DEVICE_ID_RICOH_R5C832 0x0832 #define PCI_DEVICE_ID_RICOH_R5C843 0x0843 @@ -1846,7 +1847,6 @@ #define PCI_DEVICE_ID_SIIG_8S_20x_650 0x2081 #define PCI_DEVICE_ID_SIIG_8S_20x_850 0x2082 #define PCI_SUBDEVICE_ID_SIIG_QUARTET_SERIAL 0x2050 -#define PCI_SUBDEVICE_ID_SIIG_DUAL_SERIAL 0x2530 #define PCI_VENDOR_ID_RADISYS 0x1331 @@ -2148,7 +2148,7 @@ #define PCI_DEVICE_ID_TIGON3_5704S 0x16a8 #define PCI_DEVICE_ID_NX2_57800_VF 0x16a9 #define PCI_DEVICE_ID_NX2_5706S 0x16aa -#define PCI_DEVICE_ID_NX2_57840_MF 0x16ab +#define PCI_DEVICE_ID_NX2_57840_MF 0x16a4 #define PCI_DEVICE_ID_NX2_5708S 0x16ac #define PCI_DEVICE_ID_NX2_57840_VF 0x16ad #define PCI_DEVICE_ID_NX2_57810_MF 0x16ae diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index bacc7518859..bb2aa878944 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -925,7 +925,7 @@ struct perf_event { struct hw_perf_event hw; struct perf_event_context *ctx; - struct file *filp; + atomic_long_t refcount; /* * These accumulate total time (in nanoseconds) that children diff --git a/include/linux/posix_types.h b/include/linux/posix_types.h index f04c98cf44f..988f76e636e 100644 --- a/include/linux/posix_types.h +++ b/include/linux/posix_types.h @@ -15,26 +15,14 @@ */ /* - * Those macros may have been defined in . But we always - * use the ones here. + * This macro may have been defined in . But we always + * use the one here. */ -#undef __NFDBITS -#define __NFDBITS (8 * sizeof(unsigned long)) - #undef __FD_SETSIZE #define __FD_SETSIZE 1024 -#undef __FDSET_LONGS -#define __FDSET_LONGS (__FD_SETSIZE/__NFDBITS) - -#undef __FDELT -#define __FDELT(d) ((d) / __NFDBITS) - -#undef __FDMASK -#define __FDMASK(d) (1UL << ((d) % __NFDBITS)) - typedef struct { - unsigned long fds_bits [__FDSET_LONGS]; + unsigned long fds_bits[__FD_SETSIZE / (8 * sizeof(long))]; } __kernel_fd_set; /* Type of a signal handler. */ diff --git a/include/linux/sched.h b/include/linux/sched.h index fdd51b1af65..acc142bfe30 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1286,6 +1286,9 @@ struct task_struct { const struct sched_class *sched_class; struct sched_entity se; struct sched_rt_entity rt; +#ifdef CONFIG_CGROUP_SCHED + struct task_group *sched_task_group; +#endif #ifdef CONFIG_PREEMPT_NOTIFIERS /* list of struct preempt_notifier: */ @@ -1943,6 +1946,14 @@ static inline int set_cpus_allowed_ptr(struct task_struct *p, } #endif +#ifdef CONFIG_NO_HZ +void calc_load_enter_idle(void); +void calc_load_exit_idle(void); +#else +static inline void calc_load_enter_idle(void) { } +static inline void calc_load_exit_idle(void) { } +#endif /* CONFIG_NO_HZ */ + #ifndef CONFIG_CPUMASK_OFFSTACK static inline int set_cpus_allowed(struct task_struct *p, cpumask_t new_mask) { @@ -2757,7 +2768,7 @@ extern int sched_group_set_rt_period(struct task_group *tg, extern long sched_group_rt_period(struct task_group *tg); extern int sched_rt_can_attach(struct task_group *tg, struct task_struct *tsk); #endif -#endif +#endif /* CONFIG_CGROUP_SCHED */ extern int task_can_switch_user(struct user_struct *up, struct task_struct *tsk); diff --git a/include/linux/snmp.h b/include/linux/snmp.h index 2e68f5ba038..a33f70fa1bf 100644 --- a/include/linux/snmp.h +++ b/include/linux/snmp.h @@ -208,7 +208,6 @@ enum LINUX_MIB_TCPDSACKOFOSENT, /* TCPDSACKOfoSent */ LINUX_MIB_TCPDSACKRECV, /* TCPDSACKRecv */ LINUX_MIB_TCPDSACKOFORECV, /* TCPDSACKOfoRecv */ - LINUX_MIB_TCPABORTONSYN, /* TCPAbortOnSyn */ LINUX_MIB_TCPABORTONDATA, /* TCPAbortOnData */ LINUX_MIB_TCPABORTONCLOSE, /* TCPAbortOnClose */ LINUX_MIB_TCPABORTONMEMORY, /* TCPAbortOnMemory */ @@ -234,6 +233,8 @@ enum LINUX_MIB_TCPREQQFULLDROP, /* TCPReqQFullDrop */ LINUX_MIB_TCPRETRANSFAIL, /* TCPRetransFail */ LINUX_MIB_TCPRCVCOALESCE, /* TCPRcvCoalesce */ + LINUX_MIB_TCPCHALLENGEACK, /* TCPChallengeACK */ + LINUX_MIB_TCPSYNCHALLENGE, /* TCPSYNChallenge */ __LINUX_MIB_MAX }; diff --git a/include/linux/sunrpc/cache.h b/include/linux/sunrpc/cache.h index f5fd6160dbc..dd2bb84526a 100644 --- a/include/linux/sunrpc/cache.h +++ b/include/linux/sunrpc/cache.h @@ -228,6 +228,22 @@ static inline int get_int(char **bpp, int *anint) return 0; } +static inline int get_uint(char **bpp, unsigned int *anint) +{ + char buf[50]; + int len = qword_get(bpp, buf, sizeof(buf)); + + if (len < 0) + return -EINVAL; + if (len == 0) + return -ENOENT; + + if (kstrtouint(buf, 0, anint)) + return -EINVAL; + + return 0; +} + /* * timestamps kept in the cache are expressed in seconds * since boot. This is the best for measuring differences in diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h index 77d278defa7..005b507d6d7 100644 --- a/include/linux/sunrpc/xprt.h +++ b/include/linux/sunrpc/xprt.h @@ -114,6 +114,7 @@ struct rpc_xprt_ops { void (*set_buffer_size)(struct rpc_xprt *xprt, size_t sndsize, size_t rcvsize); int (*reserve_xprt)(struct rpc_xprt *xprt, struct rpc_task *task); void (*release_xprt)(struct rpc_xprt *xprt, struct rpc_task *task); + void (*alloc_slot)(struct rpc_xprt *xprt, struct rpc_task *task); void (*rpcbind)(struct rpc_task *task); void (*set_port)(struct rpc_xprt *xprt, unsigned short port); void (*connect)(struct rpc_task *task); @@ -279,6 +280,8 @@ void xprt_connect(struct rpc_task *task); void xprt_reserve(struct rpc_task *task); int xprt_reserve_xprt(struct rpc_xprt *xprt, struct rpc_task *task); int xprt_reserve_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task); +void xprt_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task); +void xprt_lock_and_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task); int xprt_prepare_transmit(struct rpc_task *task); void xprt_transmit(struct rpc_task *task); void xprt_end_transmit(struct rpc_task *task); diff --git a/include/linux/time.h b/include/linux/time.h index 33a92ead4d8..03dce74e217 100644 --- a/include/linux/time.h +++ b/include/linux/time.h @@ -107,11 +107,36 @@ static inline struct timespec timespec_sub(struct timespec lhs, return ts_delta; } +#define KTIME_MAX ((s64)~((u64)1 << 63)) +#if (BITS_PER_LONG == 64) +# define KTIME_SEC_MAX (KTIME_MAX / NSEC_PER_SEC) +#else +# define KTIME_SEC_MAX LONG_MAX +#endif + /* * Returns true if the timespec is norm, false if denorm: */ -#define timespec_valid(ts) \ - (((ts)->tv_sec >= 0) && (((unsigned long) (ts)->tv_nsec) < NSEC_PER_SEC)) +static inline bool timespec_valid(const struct timespec *ts) +{ + /* Dates before 1970 are bogus */ + if (ts->tv_sec < 0) + return false; + /* Can't have more nanoseconds then a second */ + if ((unsigned long)ts->tv_nsec >= NSEC_PER_SEC) + return false; + return true; +} + +static inline bool timespec_valid_strict(const struct timespec *ts) +{ + if (!timespec_valid(ts)) + return false; + /* Disallow values that could overflow ktime_t */ + if ((unsigned long long)ts->tv_sec >= KTIME_SEC_MAX) + return false; + return true; +} extern void read_persistent_clock(struct timespec *ts); extern void read_boot_clock(struct timespec *ts); @@ -258,14 +283,6 @@ static __always_inline void timespec_add_ns(struct timespec *a, u64 ns) #endif /* __KERNEL__ */ -#define NFDBITS __NFDBITS - -#define FD_SETSIZE __FD_SETSIZE -#define FD_SET(fd,fdsetp) __FD_SET(fd,fdsetp) -#define FD_CLR(fd,fdsetp) __FD_CLR(fd,fdsetp) -#define FD_ISSET(fd,fdsetp) __FD_ISSET(fd,fdsetp) -#define FD_ZERO(fdsetp) __FD_ZERO(fdsetp) - /* * Names of the interval timers, and structure * defining a timer setting: diff --git a/include/linux/usb.h b/include/linux/usb.h index 70a8c857715..5c9b68367d4 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -839,6 +839,27 @@ static inline int usb_make_path(struct usb_device *dev, char *buf, size_t size) .bInterfaceSubClass = (sc), \ .bInterfaceProtocol = (pr) +/** + * USB_VENDOR_AND_INTERFACE_INFO - describe a specific usb vendor with a class of usb interfaces + * @vend: the 16 bit USB Vendor ID + * @cl: bInterfaceClass value + * @sc: bInterfaceSubClass value + * @pr: bInterfaceProtocol value + * + * This macro is used to create a struct usb_device_id that matches a + * specific vendor with a specific class of interfaces. + * + * This is especially useful when explicitly matching devices that have + * vendor specific bDeviceClass values, but standards-compliant interfaces. + */ +#define USB_VENDOR_AND_INTERFACE_INFO(vend, cl, sc, pr) \ + .match_flags = USB_DEVICE_ID_MATCH_INT_INFO \ + | USB_DEVICE_ID_MATCH_VENDOR, \ + .idVendor = (vend), \ + .bInterfaceClass = (cl), \ + .bInterfaceSubClass = (sc), \ + .bInterfaceProtocol = (pr) + /* ----------------------------------------------------------------------- */ /* Stuff for dynamic usb ids */ diff --git a/include/linux/usb/ch9.h b/include/linux/usb/ch9.h index c918b7465a8..375ad04cb9c 100644 --- a/include/linux/usb/ch9.h +++ b/include/linux/usb/ch9.h @@ -156,6 +156,12 @@ #define USB_INTRF_FUNC_SUSPEND_LP (1 << (8 + 0)) #define USB_INTRF_FUNC_SUSPEND_RW (1 << (8 + 1)) +/* + * Interface status, Figure 9-5 USB 3.0 spec + */ +#define USB_INTRF_STAT_FUNC_RW_CAP 1 +#define USB_INTRF_STAT_FUNC_RW 2 + #define USB_ENDPOINT_HALT 0 /* IN/OUT will STALL */ #define OTG_STATUS_SELECTOR 0xF000 diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h index 22e61fdf75a..28e493b5b94 100644 --- a/include/linux/xfrm.h +++ b/include/linux/xfrm.h @@ -84,6 +84,8 @@ struct xfrm_replay_state { __u32 bitmap; }; +#define XFRMA_REPLAY_ESN_MAX 4096 + struct xfrm_replay_state_esn { unsigned int bmp_len; __u32 oseq; diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 8f33405a19d..bc5c1465ebd 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -2569,6 +2569,15 @@ unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb); */ unsigned int __attribute_const__ ieee80211_hdrlen(__le16 fc); +/** + * ieee80211_get_mesh_hdrlen - get mesh extension header length + * @meshhdr: the mesh extension header, only the flags field + * (first byte) will be accessed + * Returns the length of the extension header, which is always at + * least 6 bytes and at most 18 if address 5 and 6 are present. + */ +unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr); + /** * DOC: Data path helpers * diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h index dbf9aab34c8..e9b05ded948 100644 --- a/include/net/inet_connection_sock.h +++ b/include/net/inet_connection_sock.h @@ -317,6 +317,7 @@ extern void inet_csk_reqsk_queue_prune(struct sock *parent, const unsigned long max_rto); extern void inet_csk_destroy_sock(struct sock *sk); +extern void inet_csk_prepare_forced_close(struct sock *sk); /* * LISTEN is a special case for poll.. diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index 72522f08737..2389959464c 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h @@ -1356,7 +1356,7 @@ static inline void ip_vs_notrack(struct sk_buff *skb) struct nf_conn *ct = nf_ct_get(skb, &ctinfo); if (!ct || !nf_ct_is_untracked(ct)) { - nf_reset(skb); + nf_conntrack_put(skb->nfct); skb->nfct = &nf_ct_untracked_get()->ct_general; skb->nfctinfo = IP_CT_NEW; nf_conntrack_get(skb->nfct); diff --git a/include/net/netfilter/nf_conntrack_ecache.h b/include/net/netfilter/nf_conntrack_ecache.h index a88fb693938..ea6f8a48ffe 100644 --- a/include/net/netfilter/nf_conntrack_ecache.h +++ b/include/net/netfilter/nf_conntrack_ecache.h @@ -18,6 +18,7 @@ struct nf_conntrack_ecache { u16 ctmask; /* bitmask of ct events to be delivered */ u16 expmask; /* bitmask of expect events to be delivered */ u32 pid; /* netlink pid of destroyer */ + struct timer_list timeout; }; static inline struct nf_conntrack_ecache * diff --git a/include/net/sock.h b/include/net/sock.h index 5a0a58ac412..5878118e3ce 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -216,6 +216,7 @@ struct cg_proto; * @sk_route_nocaps: forbidden route capabilities (e.g NETIF_F_GSO_MASK) * @sk_gso_type: GSO type (e.g. %SKB_GSO_TCPV4) * @sk_gso_max_size: Maximum GSO segment size to build + * @sk_gso_max_segs: Maximum number of GSO segments * @sk_lingertime: %SO_LINGER l_linger setting * @sk_backlog: always used with the per-socket spinlock held * @sk_callback_lock: used with the callbacks in the end of this struct @@ -335,6 +336,7 @@ struct sock { netdev_features_t sk_route_nocaps; int sk_gso_type; unsigned int sk_gso_max_size; + u16 sk_gso_max_segs; int sk_rcvlowat; unsigned long sk_lingertime; struct sk_buff_head sk_error_queue; diff --git a/include/net/tcp.h b/include/net/tcp.h index 50660b3e72b..ed5b0c70d86 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -252,6 +252,7 @@ extern int sysctl_tcp_max_ssthresh; extern int sysctl_tcp_cookie_size; extern int sysctl_tcp_thin_linear_timeouts; extern int sysctl_tcp_thin_dupack; +extern int sysctl_tcp_challenge_ack_limit; extern atomic_long_t tcp_memory_allocated; extern struct percpu_counter tcp_sockets_allocated; diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 96239e78e62..9f7e94ba669 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -269,6 +269,9 @@ struct xfrm_replay { int (*check)(struct xfrm_state *x, struct sk_buff *skb, __be32 net_seq); + int (*recheck)(struct xfrm_state *x, + struct sk_buff *skb, + __be32 net_seq); void (*notify)(struct xfrm_state *x, int event); int (*overflow)(struct xfrm_state *x, struct sk_buff *skb); }; diff --git a/include/rdma/rdma_netlink.h b/include/rdma/rdma_netlink.h index 3c5363ab867..bd3d8b24b42 100644 --- a/include/rdma/rdma_netlink.h +++ b/include/rdma/rdma_netlink.h @@ -39,6 +39,7 @@ struct rdma_cm_id_stats { struct ibnl_client_cbs { int (*dump)(struct sk_buff *skb, struct netlink_callback *nlcb); + struct module *module; }; int ibnl_init(void); diff --git a/include/sound/core.h b/include/sound/core.h index bc056687f64..93896ad1fcd 100644 --- a/include/sound/core.h +++ b/include/sound/core.h @@ -132,6 +132,7 @@ struct snd_card { int shutdown; /* this card is going down */ int free_on_last_close; /* free in context of file_release */ wait_queue_head_t shutdown_sleep; + atomic_t refcount; /* refcount for disconnection */ struct device *dev; /* device assigned to this card */ struct device *card_dev; /* cardX object for sysfs */ @@ -189,6 +190,7 @@ struct snd_minor { const struct file_operations *f_ops; /* file operations */ void *private_data; /* private data for f_ops->open */ struct device *dev; /* device for sysfs */ + struct snd_card *card_ptr; /* assigned card instance */ }; /* return a device pointer linked to each sound device as a parent */ @@ -295,6 +297,7 @@ int snd_card_info_done(void); int snd_component_add(struct snd_card *card, const char *component); int snd_card_file_add(struct snd_card *card, struct file *file); int snd_card_file_remove(struct snd_card *card, struct file *file); +void snd_card_unref(struct snd_card *card); #define snd_card_set_dev(card, devptr) ((card)->dev = (devptr)) diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h index 372c60df38d..9d0603c02d6 100644 --- a/include/target/target_core_base.h +++ b/include/target/target_core_base.h @@ -229,6 +229,7 @@ enum tcm_sense_reason_table { TCM_CHECK_CONDITION_UNIT_ATTENTION = 0x0e, TCM_CHECK_CONDITION_NOT_READY = 0x0f, TCM_RESERVATION_CONFLICT = 0x10, + TCM_ADDRESS_OUT_OF_RANGE = 0x11, }; enum target_sc_flags_table { @@ -780,6 +781,8 @@ struct se_subsystem_dev { }; struct se_device { +#define SE_DEV_LINK_MAGIC 0xfeeddeef + u32 dev_link_magic; /* RELATIVE TARGET PORT IDENTIFER Counter */ u16 dev_rpti_counter; /* Used for SAM Task Attribute ordering */ @@ -870,6 +873,8 @@ struct se_port_stat_grps { }; struct se_lun { +#define SE_LUN_LINK_MAGIC 0xffff7771 + u32 lun_link_magic; /* See transport_lun_status_table */ enum transport_lun_status_table lun_status; u32 lun_access; diff --git a/include/trace/events/kmem.h b/include/trace/events/kmem.h index 5f889f16b0c..08fa27244da 100644 --- a/include/trace/events/kmem.h +++ b/include/trace/events/kmem.h @@ -214,7 +214,7 @@ TRACE_EVENT(mm_page_alloc, TP_printk("page=%p pfn=%lu order=%d migratetype=%d gfp_flags=%s", __entry->page, - page_to_pfn(__entry->page), + __entry->page ? page_to_pfn(__entry->page) : 0, __entry->order, __entry->migratetype, show_gfp_flags(__entry->gfp_flags)) @@ -240,7 +240,7 @@ DECLARE_EVENT_CLASS(mm_page, TP_printk("page=%p pfn=%lu order=%u migratetype=%d percpu_refill=%d", __entry->page, - page_to_pfn(__entry->page), + __entry->page ? page_to_pfn(__entry->page) : 0, __entry->order, __entry->migratetype, __entry->order == 0) diff --git a/include/trace/events/random.h b/include/trace/events/random.h new file mode 100644 index 00000000000..422df19de73 --- /dev/null +++ b/include/trace/events/random.h @@ -0,0 +1,134 @@ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM random + +#if !defined(_TRACE_RANDOM_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_RANDOM_H + +#include +#include + +DECLARE_EVENT_CLASS(random__mix_pool_bytes, + TP_PROTO(const char *pool_name, int bytes, unsigned long IP), + + TP_ARGS(pool_name, bytes, IP), + + TP_STRUCT__entry( + __field( const char *, pool_name ) + __field( int, bytes ) + __field(unsigned long, IP ) + ), + + TP_fast_assign( + __entry->pool_name = pool_name; + __entry->bytes = bytes; + __entry->IP = IP; + ), + + TP_printk("%s pool: bytes %d caller %pF", + __entry->pool_name, __entry->bytes, (void *)__entry->IP) +); + +DEFINE_EVENT(random__mix_pool_bytes, mix_pool_bytes, + TP_PROTO(const char *pool_name, int bytes, unsigned long IP), + + TP_ARGS(pool_name, bytes, IP) +); + +DEFINE_EVENT(random__mix_pool_bytes, mix_pool_bytes_nolock, + TP_PROTO(const char *pool_name, int bytes, unsigned long IP), + + TP_ARGS(pool_name, bytes, IP) +); + +TRACE_EVENT(credit_entropy_bits, + TP_PROTO(const char *pool_name, int bits, int entropy_count, + int entropy_total, unsigned long IP), + + TP_ARGS(pool_name, bits, entropy_count, entropy_total, IP), + + TP_STRUCT__entry( + __field( const char *, pool_name ) + __field( int, bits ) + __field( int, entropy_count ) + __field( int, entropy_total ) + __field(unsigned long, IP ) + ), + + TP_fast_assign( + __entry->pool_name = pool_name; + __entry->bits = bits; + __entry->entropy_count = entropy_count; + __entry->entropy_total = entropy_total; + __entry->IP = IP; + ), + + TP_printk("%s pool: bits %d entropy_count %d entropy_total %d " + "caller %pF", __entry->pool_name, __entry->bits, + __entry->entropy_count, __entry->entropy_total, + (void *)__entry->IP) +); + +TRACE_EVENT(get_random_bytes, + TP_PROTO(int nbytes, unsigned long IP), + + TP_ARGS(nbytes, IP), + + TP_STRUCT__entry( + __field( int, nbytes ) + __field(unsigned long, IP ) + ), + + TP_fast_assign( + __entry->nbytes = nbytes; + __entry->IP = IP; + ), + + TP_printk("nbytes %d caller %pF", __entry->nbytes, (void *)__entry->IP) +); + +DECLARE_EVENT_CLASS(random__extract_entropy, + TP_PROTO(const char *pool_name, int nbytes, int entropy_count, + unsigned long IP), + + TP_ARGS(pool_name, nbytes, entropy_count, IP), + + TP_STRUCT__entry( + __field( const char *, pool_name ) + __field( int, nbytes ) + __field( int, entropy_count ) + __field(unsigned long, IP ) + ), + + TP_fast_assign( + __entry->pool_name = pool_name; + __entry->nbytes = nbytes; + __entry->entropy_count = entropy_count; + __entry->IP = IP; + ), + + TP_printk("%s pool: nbytes %d entropy_count %d caller %pF", + __entry->pool_name, __entry->nbytes, __entry->entropy_count, + (void *)__entry->IP) +); + + +DEFINE_EVENT(random__extract_entropy, extract_entropy, + TP_PROTO(const char *pool_name, int nbytes, int entropy_count, + unsigned long IP), + + TP_ARGS(pool_name, nbytes, entropy_count, IP) +); + +DEFINE_EVENT(random__extract_entropy, extract_entropy_user, + TP_PROTO(const char *pool_name, int nbytes, int entropy_count, + unsigned long IP), + + TP_ARGS(pool_name, nbytes, entropy_count, IP) +); + + + +#endif /* _TRACE_RANDOM_H */ + +/* This part must be outside protection */ +#include diff --git a/include/trace/events/workqueue.h b/include/trace/events/workqueue.h index 7d497291c85..82f61f4ce7a 100644 --- a/include/trace/events/workqueue.h +++ b/include/trace/events/workqueue.h @@ -54,7 +54,7 @@ TRACE_EVENT(workqueue_queue_work, __entry->function = work->func; __entry->workqueue = cwq->wq; __entry->req_cpu = req_cpu; - __entry->cpu = cwq->gcwq->cpu; + __entry->cpu = cwq->pool->gcwq->cpu; ), TP_printk("work struct=%p function=%pf workqueue=%p req_cpu=%u cpu=%u", diff --git a/include/trace/events/xen.h b/include/trace/events/xen.h index 92f1a796829..348c4febdcb 100644 --- a/include/trace/events/xen.h +++ b/include/trace/events/xen.h @@ -377,6 +377,14 @@ DECLARE_EVENT_CLASS(xen_mmu_pgd, DEFINE_XEN_MMU_PGD_EVENT(xen_mmu_pgd_pin); DEFINE_XEN_MMU_PGD_EVENT(xen_mmu_pgd_unpin); +TRACE_EVENT(xen_mmu_flush_tlb_all, + TP_PROTO(int x), + TP_ARGS(x), + TP_STRUCT__entry(__array(char, x, 0)), + TP_fast_assign((void)x), + TP_printk("%s", "") + ); + TRACE_EVENT(xen_mmu_flush_tlb, TP_PROTO(int x), TP_ARGS(x), diff --git a/include/xen/grant_table.h b/include/xen/grant_table.h index 15f8a00ff00..f0037a89f7d 100644 --- a/include/xen/grant_table.h +++ b/include/xen/grant_table.h @@ -185,6 +185,7 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops, struct gnttab_map_grant_ref *kmap_ops, struct page **pages, unsigned int count); int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops, - struct page **pages, unsigned int count, bool clear_pte); + struct gnttab_map_grant_ref *kunmap_ops, + struct page **pages, unsigned int count); #endif /* __ASM_GNTTAB_H__ */ diff --git a/init/main.c b/init/main.c index feb0ba56a74..8484f49485d 100644 --- a/init/main.c +++ b/init/main.c @@ -632,6 +632,9 @@ asmlinkage void __init start_kernel(void) acpi_early_init(); /* before LAPIC and SMP init */ sfi_init_late(); + if (efi_enabled) + efi_free_boot_services(); + ftrace_init(); /* Do the rest non-__init'ed, we're now alive */ diff --git a/kernel/async.c b/kernel/async.c index bd0c168a3bb..32d8dc96026 100644 --- a/kernel/async.c +++ b/kernel/async.c @@ -86,6 +86,13 @@ static async_cookie_t __lowest_in_progress(struct list_head *running) { struct async_entry *entry; + if (!running) { /* just check the entry count */ + if (atomic_read(&entry_count)) + return 0; /* smaller than any cookie */ + else + return next_cookie; + } + if (!list_empty(running)) { entry = list_first_entry(running, struct async_entry, list); @@ -236,9 +243,7 @@ EXPORT_SYMBOL_GPL(async_schedule_domain); */ void async_synchronize_full(void) { - do { - async_synchronize_cookie(next_cookie); - } while (!list_empty(&async_running) || !list_empty(&async_pending)); + async_synchronize_cookie_domain(next_cookie, NULL); } EXPORT_SYMBOL_GPL(async_synchronize_full); @@ -258,7 +263,7 @@ EXPORT_SYMBOL_GPL(async_synchronize_full_domain); /** * async_synchronize_cookie_domain - synchronize asynchronous function calls within a certain domain with cookie checkpointing * @cookie: async_cookie_t to use as checkpoint - * @running: running list to synchronize on + * @running: running list to synchronize on, NULL indicates all lists * * This function waits until all asynchronous function calls for the * synchronization domain specified by the running list @list submitted diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c index 5bf0790497e..31fdc480b5c 100644 --- a/kernel/audit_tree.c +++ b/kernel/audit_tree.c @@ -250,7 +250,6 @@ static void untag_chunk(struct node *p) spin_unlock(&hash_lock); spin_unlock(&entry->lock); fsnotify_destroy_mark(entry); - fsnotify_put_mark(entry); goto out; } @@ -259,7 +258,7 @@ static void untag_chunk(struct node *p) fsnotify_duplicate_mark(&new->mark, entry); if (fsnotify_add_mark(&new->mark, new->mark.group, new->mark.i.inode, NULL, 1)) { - free_chunk(new); + fsnotify_put_mark(&new->mark); goto Fallback; } @@ -293,7 +292,6 @@ static void untag_chunk(struct node *p) spin_unlock(&hash_lock); spin_unlock(&entry->lock); fsnotify_destroy_mark(entry); - fsnotify_put_mark(entry); goto out; Fallback: @@ -322,7 +320,7 @@ static int create_chunk(struct inode *inode, struct audit_tree *tree) entry = &chunk->mark; if (fsnotify_add_mark(entry, audit_tree_group, inode, NULL, 0)) { - free_chunk(chunk); + fsnotify_put_mark(entry); return -ENOSPC; } @@ -332,6 +330,7 @@ static int create_chunk(struct inode *inode, struct audit_tree *tree) spin_unlock(&hash_lock); chunk->dead = 1; spin_unlock(&entry->lock); + fsnotify_get_mark(entry); fsnotify_destroy_mark(entry); fsnotify_put_mark(entry); return 0; @@ -396,7 +395,7 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree) fsnotify_duplicate_mark(chunk_entry, old_entry); if (fsnotify_add_mark(chunk_entry, chunk_entry->group, chunk_entry->i.inode, NULL, 1)) { spin_unlock(&old_entry->lock); - free_chunk(chunk); + fsnotify_put_mark(chunk_entry); fsnotify_put_mark(old_entry); return -ENOSPC; } @@ -412,6 +411,7 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree) spin_unlock(&chunk_entry->lock); spin_unlock(&old_entry->lock); + fsnotify_get_mark(chunk_entry); fsnotify_destroy_mark(chunk_entry); fsnotify_put_mark(chunk_entry); @@ -445,7 +445,6 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree) spin_unlock(&old_entry->lock); fsnotify_destroy_mark(old_entry); fsnotify_put_mark(old_entry); /* pair to fsnotify_find mark_entry */ - fsnotify_put_mark(old_entry); /* and kill it */ return 0; } diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 5303ec8591b..dd694f8b09a 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -1871,9 +1871,8 @@ static void cgroup_task_migrate(struct cgroup *cgrp, struct cgroup *oldcgrp, * trading it for newcg is protected by cgroup_mutex, we're safe to drop * it here; it will be freed under RCU. */ - put_css_set(oldcg); - set_bit(CGRP_RELEASABLE, &oldcgrp->flags); + put_css_set(oldcg); } /** @@ -2606,9 +2605,7 @@ static int cgroup_create_dir(struct cgroup *cgrp, struct dentry *dentry, dentry->d_fsdata = cgrp; inc_nlink(parent->d_inode); rcu_assign_pointer(cgrp->dentry, dentry); - dget(dentry); } - dput(dentry); return error; } @@ -4518,31 +4515,20 @@ static const struct file_operations proc_cgroupstats_operations = { * * A pointer to the shared css_set was automatically copied in * fork.c by dup_task_struct(). However, we ignore that copy, since - * it was not made under the protection of RCU, cgroup_mutex or - * threadgroup_change_begin(), so it might no longer be a valid - * cgroup pointer. cgroup_attach_task() might have already changed - * current->cgroups, allowing the previously referenced cgroup - * group to be removed and freed. - * - * Outside the pointer validity we also need to process the css_set - * inheritance between threadgoup_change_begin() and - * threadgoup_change_end(), this way there is no leak in any process - * wide migration performed by cgroup_attach_proc() that could otherwise - * miss a thread because it is too early or too late in the fork stage. + * it was not made under the protection of RCU or cgroup_mutex, so + * might no longer be a valid cgroup pointer. cgroup_attach_task() might + * have already changed current->cgroups, allowing the previously + * referenced cgroup group to be removed and freed. * * At the point that cgroup_fork() is called, 'current' is the parent * task, and the passed argument 'child' points to the child task. */ void cgroup_fork(struct task_struct *child) { - /* - * We don't need to task_lock() current because current->cgroups - * can't be changed concurrently here. The parent obviously hasn't - * exited and called cgroup_exit(), and we are synchronized against - * cgroup migration through threadgroup_change_begin(). - */ + task_lock(current); child->cgroups = current->cgroups; get_css_set(child->cgroups); + task_unlock(current); INIT_LIST_HEAD(&child->cg_list); } @@ -4595,19 +4581,10 @@ void cgroup_post_fork(struct task_struct *child) */ if (use_task_css_set_links) { write_lock(&css_set_lock); - if (list_empty(&child->cg_list)) { - /* - * It's safe to use child->cgroups without task_lock() - * here because we are protected through - * threadgroup_change_begin() against concurrent - * css_set change in cgroup_task_migrate(). Also - * the task can't exit at that point until - * wake_up_new_task() is called, so we are protected - * against cgroup_exit() setting child->cgroup to - * init_css_set. - */ + task_lock(child); + if (list_empty(&child->cg_list)) list_add(&child->cg_list, &child->cgroups->tasks); - } + task_unlock(child); write_unlock(&css_set_lock); } } diff --git a/kernel/cpuset.c b/kernel/cpuset.c index 14f7070b4ba..5fc1570e64c 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c @@ -2065,6 +2065,9 @@ static void scan_for_empty_cpusets(struct cpuset *root) * (of no affect) on systems that are actively using CPU hotplug * but making no active use of cpusets. * + * The only exception to this is suspend/resume, where we don't + * modify cpusets at all. + * * This routine ensures that top_cpuset.cpus_allowed tracks * cpu_active_mask on each CPU hotplug (cpuhp) event. * diff --git a/kernel/debug/kdb/kdb_io.c b/kernel/debug/kdb/kdb_io.c index 18a4cb33c52..81b31bba4ae 100644 --- a/kernel/debug/kdb/kdb_io.c +++ b/kernel/debug/kdb/kdb_io.c @@ -560,6 +560,7 @@ int vkdb_printf(const char *fmt, va_list ap) { int diag; int linecount; + int colcount; int logging, saved_loglevel = 0; int saved_trap_printk; int got_printf_lock = 0; @@ -592,6 +593,10 @@ int vkdb_printf(const char *fmt, va_list ap) if (diag || linecount <= 1) linecount = 24; + diag = kdbgetintenv("COLUMNS", &colcount); + if (diag || colcount <= 1) + colcount = 80; + diag = kdbgetintenv("LOGGING", &logging); if (diag) logging = 0; @@ -698,7 +703,7 @@ int vkdb_printf(const char *fmt, va_list ap) gdbstub_msg_write(kdb_buffer, retlen); } else { if (dbg_io_ops && !dbg_io_ops->is_console) { - len = strlen(kdb_buffer); + len = retlen; cp = kdb_buffer; while (len--) { dbg_io_ops->write_char(*cp); @@ -717,11 +722,29 @@ int vkdb_printf(const char *fmt, va_list ap) printk(KERN_INFO "%s", kdb_buffer); } - if (KDB_STATE(PAGER) && strchr(kdb_buffer, '\n')) - kdb_nextline++; + if (KDB_STATE(PAGER)) { + /* + * Check printed string to decide how to bump the + * kdb_nextline to control when the more prompt should + * show up. + */ + int got = 0; + len = retlen; + while (len--) { + if (kdb_buffer[len] == '\n') { + kdb_nextline++; + got = 0; + } else if (kdb_buffer[len] == '\r') { + got = 0; + } else { + got++; + } + } + kdb_nextline += got / (colcount + 1); + } /* check for having reached the LINES number of printed lines */ - if (kdb_nextline == linecount) { + if (kdb_nextline >= linecount) { char buf1[16] = ""; #if defined(CONFIG_SMP) char buf2[32]; @@ -784,7 +807,7 @@ int vkdb_printf(const char *fmt, va_list ap) kdb_grepping_flag = 0; kdb_printf("\n"); } else if (buf1[0] == ' ') { - kdb_printf("\n"); + kdb_printf("\r"); suspend_grep = 1; /* for this recursion */ } else if (buf1[0] == '\n') { kdb_nextline = linecount - 1; diff --git a/kernel/events/core.c b/kernel/events/core.c index 8b0f750a958..85ee3c8722f 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -2929,12 +2929,12 @@ EXPORT_SYMBOL_GPL(perf_event_release_kernel); /* * Called when the last reference to the file is gone. */ -static int perf_release(struct inode *inode, struct file *file) +static void put_event(struct perf_event *event) { - struct perf_event *event = file->private_data; struct task_struct *owner; - file->private_data = NULL; + if (!atomic_long_dec_and_test(&event->refcount)) + return; rcu_read_lock(); owner = ACCESS_ONCE(event->owner); @@ -2969,7 +2969,13 @@ static int perf_release(struct inode *inode, struct file *file) put_task_struct(owner); } - return perf_event_release_kernel(event); + perf_event_release_kernel(event); +} + +static int perf_release(struct inode *inode, struct file *file) +{ + put_event(file->private_data); + return 0; } u64 perf_event_read_value(struct perf_event *event, u64 *enabled, u64 *running) @@ -3222,7 +3228,7 @@ static int perf_event_period(struct perf_event *event, u64 __user *arg) static const struct file_operations perf_fops; -static struct perf_event *perf_fget_light(int fd, int *fput_needed) +static struct file *perf_fget_light(int fd, int *fput_needed) { struct file *file; @@ -3236,7 +3242,7 @@ static struct perf_event *perf_fget_light(int fd, int *fput_needed) return ERR_PTR(-EBADF); } - return file->private_data; + return file; } static int perf_event_set_output(struct perf_event *event, @@ -3268,19 +3274,21 @@ static long perf_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case PERF_EVENT_IOC_SET_OUTPUT: { + struct file *output_file = NULL; struct perf_event *output_event = NULL; int fput_needed = 0; int ret; if (arg != -1) { - output_event = perf_fget_light(arg, &fput_needed); - if (IS_ERR(output_event)) - return PTR_ERR(output_event); + output_file = perf_fget_light(arg, &fput_needed); + if (IS_ERR(output_file)) + return PTR_ERR(output_file); + output_event = output_file->private_data; } ret = perf_event_set_output(event, output_event); if (output_event) - fput_light(output_event->filp, fput_needed); + fput_light(output_file, fput_needed); return ret; } @@ -5920,6 +5928,7 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu, mutex_init(&event->mmap_mutex); + atomic_long_set(&event->refcount, 1); event->cpu = cpu; event->attr = *attr; event->group_leader = group_leader; @@ -6230,12 +6239,12 @@ SYSCALL_DEFINE5(perf_event_open, return event_fd; if (group_fd != -1) { - group_leader = perf_fget_light(group_fd, &fput_needed); - if (IS_ERR(group_leader)) { - err = PTR_ERR(group_leader); + group_file = perf_fget_light(group_fd, &fput_needed); + if (IS_ERR(group_file)) { + err = PTR_ERR(group_file); goto err_fd; } - group_file = group_leader->filp; + group_leader = group_file->private_data; if (flags & PERF_FLAG_FD_OUTPUT) output_event = group_leader; if (flags & PERF_FLAG_FD_NO_GROUP) @@ -6370,7 +6379,6 @@ SYSCALL_DEFINE5(perf_event_open, put_ctx(gctx); } - event->filp = event_file; WARN_ON_ONCE(ctx->parent_ctx); mutex_lock(&ctx->mutex); @@ -6460,7 +6468,6 @@ perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu, goto err_free; } - event->filp = NULL; WARN_ON_ONCE(ctx->parent_ctx); mutex_lock(&ctx->mutex); perf_install_in_context(ctx, event, cpu); @@ -6509,7 +6516,7 @@ static void sync_child_event(struct perf_event *child_event, * Release the parent event, if this was the last * reference to it. */ - fput(parent_event->filp); + put_event(parent_event); } static void @@ -6585,9 +6592,8 @@ static void perf_event_exit_task_context(struct task_struct *child, int ctxn) * * __perf_event_exit_task() * sync_child_event() - * fput(parent_event->filp) - * perf_release() - * mutex_lock(&ctx->mutex) + * put_event() + * mutex_lock(&ctx->mutex) * * But since its the parent context it won't be the same instance. */ @@ -6655,7 +6661,7 @@ static void perf_free_event(struct perf_event *event, list_del_init(&event->child_list); mutex_unlock(&parent->child_mutex); - fput(parent->filp); + put_event(parent); perf_group_detach(event); list_del_event(event, ctx); @@ -6735,6 +6741,12 @@ inherit_event(struct perf_event *parent_event, NULL, NULL); if (IS_ERR(child_event)) return child_event; + + if (!atomic_long_inc_not_zero(&parent_event->refcount)) { + free_event(child_event); + return NULL; + } + get_ctx(child_ctx); /* @@ -6775,14 +6787,6 @@ inherit_event(struct perf_event *parent_event, add_event_to_ctx(child_event, child_ctx); raw_spin_unlock_irqrestore(&child_ctx->lock, flags); - /* - * Get a reference to the parent filp - we will fput it - * when the child event exits. This is safe to do because - * we are in the parent and we know that the filp still - * exists and has a nonzero count: - */ - atomic_long_inc(&parent_event->filp->f_count); - /* * Link this into the parent event's child list */ diff --git a/kernel/exit.c b/kernel/exit.c index b5109b6367a..7b8aafce7fe 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -471,7 +471,7 @@ static void close_files(struct files_struct * files) rcu_read_unlock(); for (;;) { unsigned long set; - i = j * __NFDBITS; + i = j * BITS_PER_LONG; if (i >= fdt->max_fds) break; set = fdt->open_fds[j++]; diff --git a/kernel/futex.c b/kernel/futex.c index 577deef7166..cf594d34413 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -717,7 +717,7 @@ static int futex_lock_pi_atomic(u32 __user *uaddr, struct futex_hash_bucket *hb, struct futex_pi_state **ps, struct task_struct *task, int set_waiters) { - int lock_taken, ret, ownerdied = 0; + int lock_taken, ret, force_take = 0; u32 uval, newval, curval, vpid = task_pid_vnr(task); retry: @@ -756,17 +756,15 @@ static int futex_lock_pi_atomic(u32 __user *uaddr, struct futex_hash_bucket *hb, newval = curval | FUTEX_WAITERS; /* - * There are two cases, where a futex might have no owner (the - * owner TID is 0): OWNER_DIED. We take over the futex in this - * case. We also do an unconditional take over, when the owner - * of the futex died. - * - * This is safe as we are protected by the hash bucket lock ! + * Should we force take the futex? See below. */ - if (unlikely(ownerdied || !(curval & FUTEX_TID_MASK))) { - /* Keep the OWNER_DIED bit */ + if (unlikely(force_take)) { + /* + * Keep the OWNER_DIED and the WAITERS bit and set the + * new TID value. + */ newval = (curval & ~FUTEX_TID_MASK) | vpid; - ownerdied = 0; + force_take = 0; lock_taken = 1; } @@ -776,7 +774,7 @@ static int futex_lock_pi_atomic(u32 __user *uaddr, struct futex_hash_bucket *hb, goto retry; /* - * We took the lock due to owner died take over. + * We took the lock due to forced take over. */ if (unlikely(lock_taken)) return 1; @@ -791,20 +789,25 @@ static int futex_lock_pi_atomic(u32 __user *uaddr, struct futex_hash_bucket *hb, switch (ret) { case -ESRCH: /* - * No owner found for this futex. Check if the - * OWNER_DIED bit is set to figure out whether - * this is a robust futex or not. + * We failed to find an owner for this + * futex. So we have no pi_state to block + * on. This can happen in two cases: + * + * 1) The owner died + * 2) A stale FUTEX_WAITERS bit + * + * Re-read the futex value. */ if (get_futex_value_locked(&curval, uaddr)) return -EFAULT; /* - * We simply start over in case of a robust - * futex. The code above will take the futex - * and return happy. + * If the owner died or we have a stale + * WAITERS bit the owner TID in the user space + * futex is 0. */ - if (curval & FUTEX_OWNER_DIED) { - ownerdied = 1; + if (!(curval & FUTEX_TID_MASK)) { + force_take = 1; goto retry; } default: @@ -841,6 +844,9 @@ static void wake_futex(struct futex_q *q) { struct task_struct *p = q->task; + if (WARN(q->pi_state || q->rt_waiter, "refusing to wake PI futex\n")) + return; + /* * We set q->lock_ptr = NULL _before_ we wake up the task. If * a non-futex wake up happens on another CPU then the task @@ -1076,6 +1082,10 @@ futex_wake_op(u32 __user *uaddr1, unsigned int flags, u32 __user *uaddr2, plist_for_each_entry_safe(this, next, head, list) { if (match_futex (&this->key, &key1)) { + if (this->pi_state || this->rt_waiter) { + ret = -EINVAL; + goto out_unlock; + } wake_futex(this); if (++ret >= nr_wake) break; @@ -1088,6 +1098,10 @@ futex_wake_op(u32 __user *uaddr1, unsigned int flags, u32 __user *uaddr2, op_ret = 0; plist_for_each_entry_safe(this, next, head, list) { if (match_futex (&this->key, &key2)) { + if (this->pi_state || this->rt_waiter) { + ret = -EINVAL; + goto out_unlock; + } wake_futex(this); if (++op_ret >= nr_wake2) break; @@ -1096,6 +1110,7 @@ futex_wake_op(u32 __user *uaddr1, unsigned int flags, u32 __user *uaddr2, ret += op_ret; } +out_unlock: double_unlock_hb(hb1, hb2); out_put_keys: put_futex_key(&key2); @@ -1385,9 +1400,13 @@ static int futex_requeue(u32 __user *uaddr1, unsigned int flags, /* * FUTEX_WAIT_REQEUE_PI and FUTEX_CMP_REQUEUE_PI should always * be paired with each other and no other futex ops. + * + * We should never be requeueing a futex_q with a pi_state, + * which is awaiting a futex_unlock_pi(). */ if ((requeue_pi && !this->rt_waiter) || - (!requeue_pi && this->rt_waiter)) { + (!requeue_pi && this->rt_waiter) || + this->pi_state) { ret = -EINVAL; break; } @@ -2232,11 +2251,11 @@ int handle_early_requeue_pi_wakeup(struct futex_hash_bucket *hb, * @uaddr2: the pi futex we will take prior to returning to user-space * * The caller will wait on uaddr and will be requeued by futex_requeue() to - * uaddr2 which must be PI aware. Normal wakeup will wake on uaddr2 and - * complete the acquisition of the rt_mutex prior to returning to userspace. - * This ensures the rt_mutex maintains an owner when it has waiters; without - * one, the pi logic wouldn't know which task to boost/deboost, if there was a - * need to. + * uaddr2 which must be PI aware and unique from uaddr. Normal wakeup will wake + * on uaddr2 and complete the acquisition of the rt_mutex prior to returning to + * userspace. This ensures the rt_mutex maintains an owner when it has waiters; + * without one, the pi logic would not know which task to boost/deboost, if + * there was a need to. * * We call schedule in futex_wait_queue_me() when we enqueue and return there * via the following: @@ -2273,6 +2292,9 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags, struct futex_q q = futex_q_init; int res, ret; + if (uaddr == uaddr2) + return -EINVAL; + if (!bitset) return -EINVAL; @@ -2344,7 +2366,7 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags, * signal. futex_unlock_pi() will not destroy the lock_ptr nor * the pi_state. */ - WARN_ON(!&q.pi_state); + WARN_ON(!q.pi_state); pi_mutex = &q.pi_state->pi_mutex; ret = rt_mutex_finish_proxy_lock(pi_mutex, to, &rt_waiter, 1); debug_rt_mutex_free_waiter(&rt_waiter); @@ -2371,7 +2393,7 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags, * fault, unlock the rt_mutex and return the fault to userspace. */ if (ret == -EFAULT) { - if (rt_mutex_owner(pi_mutex) == current) + if (pi_mutex && rt_mutex_owner(pi_mutex) == current) rt_mutex_unlock(pi_mutex); } else if (ret == -EINTR) { /* diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index a2ffb7a85c1..11974dce958 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c @@ -659,6 +659,14 @@ static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer, return 0; } +static inline ktime_t hrtimer_update_base(struct hrtimer_cpu_base *base) +{ + ktime_t *offs_real = &base->clock_base[HRTIMER_BASE_REALTIME].offset; + ktime_t *offs_boot = &base->clock_base[HRTIMER_BASE_BOOTTIME].offset; + + return ktime_get_update_offsets(offs_real, offs_boot); +} + /* * Retrigger next event is called after clock was set * @@ -667,22 +675,12 @@ static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer, static void retrigger_next_event(void *arg) { struct hrtimer_cpu_base *base = &__get_cpu_var(hrtimer_bases); - struct timespec realtime_offset, xtim, wtm, sleep; if (!hrtimer_hres_active()) return; - /* Optimized out for !HIGH_RES */ - get_xtime_and_monotonic_and_sleep_offset(&xtim, &wtm, &sleep); - set_normalized_timespec(&realtime_offset, -wtm.tv_sec, -wtm.tv_nsec); - - /* Adjust CLOCK_REALTIME offset */ raw_spin_lock(&base->lock); - base->clock_base[HRTIMER_BASE_REALTIME].offset = - timespec_to_ktime(realtime_offset); - base->clock_base[HRTIMER_BASE_BOOTTIME].offset = - timespec_to_ktime(sleep); - + hrtimer_update_base(base); hrtimer_force_reprogram(base, 0); raw_spin_unlock(&base->lock); } @@ -712,13 +710,25 @@ static int hrtimer_switch_to_hres(void) base->clock_base[i].resolution = KTIME_HIGH_RES; tick_setup_sched_timer(); - /* "Retrigger" the interrupt to get things going */ retrigger_next_event(NULL); local_irq_restore(flags); return 1; } +/* + * Called from timekeeping code to reprogramm the hrtimer interrupt + * device. If called from the timer interrupt context we defer it to + * softirq context. + */ +void clock_was_set_delayed(void) +{ + struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases); + + cpu_base->clock_was_set = 1; + __raise_softirq_irqoff(HRTIMER_SOFTIRQ); +} + #else static inline int hrtimer_hres_active(void) { return 0; } @@ -1252,11 +1262,10 @@ void hrtimer_interrupt(struct clock_event_device *dev) cpu_base->nr_events++; dev->next_event.tv64 = KTIME_MAX; - entry_time = now = ktime_get(); + raw_spin_lock(&cpu_base->lock); + entry_time = now = hrtimer_update_base(cpu_base); retry: expires_next.tv64 = KTIME_MAX; - - raw_spin_lock(&cpu_base->lock); /* * We set expires_next to KTIME_MAX here with cpu_base->lock * held to prevent that a timer is enqueued in our queue via @@ -1332,8 +1341,12 @@ void hrtimer_interrupt(struct clock_event_device *dev) * We need to prevent that we loop forever in the hrtimer * interrupt routine. We give it 3 attempts to avoid * overreacting on some spurious event. + * + * Acquire base lock for updating the offsets and retrieving + * the current time. */ - now = ktime_get(); + raw_spin_lock(&cpu_base->lock); + now = hrtimer_update_base(cpu_base); cpu_base->nr_retries++; if (++retries < 3) goto retry; @@ -1345,6 +1358,7 @@ void hrtimer_interrupt(struct clock_event_device *dev) */ cpu_base->nr_hangs++; cpu_base->hang_detected = 1; + raw_spin_unlock(&cpu_base->lock); delta = ktime_sub(now, entry_time); if (delta.tv64 > cpu_base->max_hang_time.tv64) cpu_base->max_hang_time = delta; @@ -1397,6 +1411,13 @@ void hrtimer_peek_ahead_timers(void) static void run_hrtimer_softirq(struct softirq_action *h) { + struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases); + + if (cpu_base->clock_was_set) { + cpu_base->clock_was_set = 0; + clock_was_set(); + } + hrtimer_peek_ahead_timers(); } diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 8550d4b3437..5097018f1b3 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -734,6 +734,7 @@ static void irq_thread_check_affinity(struct irq_desc *desc, struct irqaction *action) { cpumask_var_t mask; + bool valid = true; if (!test_and_clear_bit(IRQTF_AFFINITY, &action->thread_flags)) return; @@ -748,10 +749,18 @@ irq_thread_check_affinity(struct irq_desc *desc, struct irqaction *action) } raw_spin_lock_irq(&desc->lock); - cpumask_copy(mask, desc->irq_data.affinity); + /* + * This code is triggered unconditionally. Check the affinity + * mask pointer. For CPU_MASK_OFFSTACK=n this is optimized out. + */ + if (desc->irq_data.affinity) + cpumask_copy(mask, desc->irq_data.affinity); + else + valid = false; raw_spin_unlock_irq(&desc->lock); - set_cpus_allowed_ptr(current, mask); + if (valid) + set_cpus_allowed_ptr(current, mask); free_cpumask_var(mask); } #else @@ -959,6 +968,16 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) */ get_task_struct(t); new->thread = t; + /* + * Tell the thread to set its affinity. This is + * important for shared interrupt handlers as we do + * not invoke setup_affinity() for the secondary + * handlers as everything is already set up. Even for + * interrupts marked with IRQF_NO_BALANCE this is + * correct as we want the thread to move to the cpu(s) + * on which the requesting code placed the interrupt. + */ + set_bit(IRQTF_AFFINITY, &new->thread_flags); } if (!alloc_cpumask_var(&mask, GFP_KERNEL)) { diff --git a/kernel/module.c b/kernel/module.c index b1c79e395de..c5aba98b2db 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -2273,12 +2273,17 @@ static void layout_symtab(struct module *mod, struct load_info *info) src = (void *)info->hdr + symsect->sh_offset; nsrc = symsect->sh_size / sizeof(*src); + /* strtab always starts with a nul, so offset 0 is the empty string. */ + strtab_size = 1; + /* Compute total space required for the core symbols' strtab. */ - for (ndst = i = strtab_size = 1; i < nsrc; ++i, ++src) - if (is_core_symbol(src, info->sechdrs, info->hdr->e_shnum)) { - strtab_size += strlen(&info->strtab[src->st_name]) + 1; + for (ndst = i = 0; i < nsrc; i++) { + if (i == 0 || + is_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum)) { + strtab_size += strlen(&info->strtab[src[i].st_name])+1; ndst++; } + } /* Append room for core symbols at end of core part. */ info->symoffs = ALIGN(mod->core_size, symsect->sh_addralign ?: 1); @@ -2312,15 +2317,15 @@ static void add_kallsyms(struct module *mod, const struct load_info *info) mod->core_symtab = dst = mod->module_core + info->symoffs; mod->core_strtab = s = mod->module_core + info->stroffs; src = mod->symtab; - *dst = *src; *s++ = 0; - for (ndst = i = 1; i < mod->num_symtab; ++i, ++src) { - if (!is_core_symbol(src, info->sechdrs, info->hdr->e_shnum)) - continue; - - dst[ndst] = *src; - dst[ndst++].st_name = s - mod->core_strtab; - s += strlcpy(s, &mod->strtab[src->st_name], KSYM_NAME_LEN) + 1; + for (ndst = i = 0; i < mod->num_symtab; i++) { + if (i == 0 || + is_core_symbol(src+i, info->sechdrs, info->hdr->e_shnum)) { + dst[ndst] = src[i]; + dst[ndst++].st_name = s - mod->core_strtab; + s += strlcpy(s, &mod->strtab[src[i].st_name], + KSYM_NAME_LEN) + 1; + } } mod->core_num_syms = ndst; } @@ -2729,6 +2734,10 @@ static int check_module_license_and_versions(struct module *mod) if (strcmp(mod->name, "driverloader") == 0) add_taint_module(mod, TAINT_PROPRIETARY_MODULE); + /* lve claims to be GPL but upstream won't provide source */ + if (strcmp(mod->name, "lve") == 0) + add_taint_module(mod, TAINT_PROPRIETARY_MODULE); + #ifdef CONFIG_MODVERSIONS if ((mod->num_syms && !mod->crcs) || (mod->num_gpl_syms && !mod->gpl_crcs) diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c index e09dfbfeece..52a18173c84 100644 --- a/kernel/power/hibernate.c +++ b/kernel/power/hibernate.c @@ -352,6 +352,7 @@ int hibernation_snapshot(int platform_mode) } suspend_console(); + ftrace_stop(); pm_restrict_gfp_mask(); error = dpm_suspend(PMSG_FREEZE); @@ -377,6 +378,7 @@ int hibernation_snapshot(int platform_mode) if (error || !in_suspend) pm_restore_gfp_mask(); + ftrace_start(); resume_console(); dpm_complete(msg); @@ -479,6 +481,7 @@ int hibernation_restore(int platform_mode) pm_prepare_console(); suspend_console(); + ftrace_stop(); pm_restrict_gfp_mask(); error = dpm_suspend_start(PMSG_QUIESCE); if (!error) { @@ -486,6 +489,7 @@ int hibernation_restore(int platform_mode) dpm_resume_end(PMSG_RECOVER); } pm_restore_gfp_mask(); + ftrace_start(); resume_console(); pm_restore_console(); return error; @@ -512,6 +516,7 @@ int hibernation_platform_enter(void) entering_platform_hibernation = true; suspend_console(); + ftrace_stop(); error = dpm_suspend_start(PMSG_HIBERNATE); if (error) { if (hibernation_ops->recover) @@ -555,6 +560,7 @@ int hibernation_platform_enter(void) Resume_devices: entering_platform_hibernation = false; dpm_resume_end(PMSG_RESTORE); + ftrace_start(); resume_console(); Close: diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c index dc392c7cc62..4a366dbd3f0 100644 --- a/kernel/power/suspend.c +++ b/kernel/power/suspend.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include "power.h" @@ -216,6 +217,7 @@ int suspend_devices_and_enter(suspend_state_t state) goto Close; } suspend_console(); + ftrace_stop(); suspend_test_start(); error = dpm_suspend_start(PMSG_SUSPEND); if (error) { @@ -235,6 +237,7 @@ int suspend_devices_and_enter(suspend_state_t state) suspend_test_start(); dpm_resume_end(PMSG_RESUME); suspend_test_finish("resume devices"); + ftrace_start(); resume_console(); Close: if (suspend_ops->end) diff --git a/kernel/rcutree.c b/kernel/rcutree.c index d494b93c9f0..b131b7d0f1c 100644 --- a/kernel/rcutree.c +++ b/kernel/rcutree.c @@ -202,13 +202,13 @@ DEFINE_PER_CPU(struct rcu_dynticks, rcu_dynticks) = { .dynticks = ATOMIC_INIT(1), }; -static int blimit = 10; /* Maximum callbacks per rcu_do_batch. */ -static int qhimark = 10000; /* If this many pending, ignore blimit. */ -static int qlowmark = 100; /* Once only this many pending, use blimit. */ +static long blimit = 10; /* Maximum callbacks per rcu_do_batch. */ +static long qhimark = 10000; /* If this many pending, ignore blimit. */ +static long qlowmark = 100; /* Once only this many pending, use blimit. */ -module_param(blimit, int, 0); -module_param(qhimark, int, 0); -module_param(qlowmark, int, 0); +module_param(blimit, long, 0); +module_param(qhimark, long, 0); +module_param(qlowmark, long, 0); int rcu_cpu_stall_suppress __read_mostly; /* 1 = suppress stall warnings. */ int rcu_cpu_stall_timeout __read_mostly = CONFIG_RCU_CPU_STALL_TIMEOUT; @@ -1476,7 +1476,7 @@ static void rcu_do_batch(struct rcu_state *rsp, struct rcu_data *rdp) { unsigned long flags; struct rcu_head *next, *list, **tail; - int bl, count, count_lazy; + long bl, count, count_lazy; /* If no callbacks are ready, just return.*/ if (!cpu_has_callbacks_ready_to_invoke(rdp)) { diff --git a/kernel/sched/auto_group.c b/kernel/sched/auto_group.c index 0984a21076a..15f60d01198 100644 --- a/kernel/sched/auto_group.c +++ b/kernel/sched/auto_group.c @@ -143,15 +143,11 @@ autogroup_move_group(struct task_struct *p, struct autogroup *ag) p->signal->autogroup = autogroup_kref_get(ag); - if (!ACCESS_ONCE(sysctl_sched_autogroup_enabled)) - goto out; - t = p; do { sched_move_task(t); } while_each_thread(p, t); -out: unlock_task_sighand(p, &flags); autogroup_kref_put(prev); } diff --git a/kernel/sched/auto_group.h b/kernel/sched/auto_group.h index 8bd04714281..443232ebbb5 100644 --- a/kernel/sched/auto_group.h +++ b/kernel/sched/auto_group.h @@ -4,11 +4,6 @@ #include struct autogroup { - /* - * reference doesn't mean how many thread attach to this - * autogroup now. It just stands for the number of task - * could use this autogroup. - */ struct kref kref; struct task_group *tg; struct rw_semaphore lock; diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 1dae88fa9ad..45f5393292a 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -1121,7 +1121,7 @@ void set_task_cpu(struct task_struct *p, unsigned int new_cpu) * a task's CPU. ->pi_lock for waking tasks, rq->lock for runnable tasks. * * sched_move_task() holds both and thus holding either pins the cgroup, - * see set_task_rq(). + * see task_group(). * * Furthermore, all task_rq users should acquire both locks, see * task_rq_lock(). @@ -2218,11 +2218,73 @@ unsigned long this_cpu_load(void) } +/* + * Global load-average calculations + * + * We take a distributed and async approach to calculating the global load-avg + * in order to minimize overhead. + * + * The global load average is an exponentially decaying average of nr_running + + * nr_uninterruptible. + * + * Once every LOAD_FREQ: + * + * nr_active = 0; + * for_each_possible_cpu(cpu) + * nr_active += cpu_of(cpu)->nr_running + cpu_of(cpu)->nr_uninterruptible; + * + * avenrun[n] = avenrun[0] * exp_n + nr_active * (1 - exp_n) + * + * Due to a number of reasons the above turns in the mess below: + * + * - for_each_possible_cpu() is prohibitively expensive on machines with + * serious number of cpus, therefore we need to take a distributed approach + * to calculating nr_active. + * + * \Sum_i x_i(t) = \Sum_i x_i(t) - x_i(t_0) | x_i(t_0) := 0 + * = \Sum_i { \Sum_j=1 x_i(t_j) - x_i(t_j-1) } + * + * So assuming nr_active := 0 when we start out -- true per definition, we + * can simply take per-cpu deltas and fold those into a global accumulate + * to obtain the same result. See calc_load_fold_active(). + * + * Furthermore, in order to avoid synchronizing all per-cpu delta folding + * across the machine, we assume 10 ticks is sufficient time for every + * cpu to have completed this task. + * + * This places an upper-bound on the IRQ-off latency of the machine. Then + * again, being late doesn't loose the delta, just wrecks the sample. + * + * - cpu_rq()->nr_uninterruptible isn't accurately tracked per-cpu because + * this would add another cross-cpu cacheline miss and atomic operation + * to the wakeup path. Instead we increment on whatever cpu the task ran + * when it went into uninterruptible state and decrement on whatever cpu + * did the wakeup. This means that only the sum of nr_uninterruptible over + * all cpus yields the correct result. + * + * This covers the NO_HZ=n code, for extra head-aches, see the comment below. + */ + /* Variables and functions for calc_load */ static atomic_long_t calc_load_tasks; static unsigned long calc_load_update; unsigned long avenrun[3]; -EXPORT_SYMBOL(avenrun); +EXPORT_SYMBOL(avenrun); /* should be removed */ + +/** + * get_avenrun - get the load average array + * @loads: pointer to dest load array + * @offset: offset to add + * @shift: shift count to shift the result left + * + * These values are estimates at best, so no need for locking. + */ +void get_avenrun(unsigned long *loads, unsigned long offset, int shift) +{ + loads[0] = (avenrun[0] + offset) << shift; + loads[1] = (avenrun[1] + offset) << shift; + loads[2] = (avenrun[2] + offset) << shift; +} static long calc_load_fold_active(struct rq *this_rq) { @@ -2239,6 +2301,9 @@ static long calc_load_fold_active(struct rq *this_rq) return delta; } +/* + * a1 = a0 * e + a * (1 - e) + */ static unsigned long calc_load(unsigned long load, unsigned long exp, unsigned long active) { @@ -2250,30 +2315,118 @@ calc_load(unsigned long load, unsigned long exp, unsigned long active) #ifdef CONFIG_NO_HZ /* - * For NO_HZ we delay the active fold to the next LOAD_FREQ update. + * Handle NO_HZ for the global load-average. + * + * Since the above described distributed algorithm to compute the global + * load-average relies on per-cpu sampling from the tick, it is affected by + * NO_HZ. + * + * The basic idea is to fold the nr_active delta into a global idle-delta upon + * entering NO_HZ state such that we can include this as an 'extra' cpu delta + * when we read the global state. + * + * Obviously reality has to ruin such a delightfully simple scheme: + * + * - When we go NO_HZ idle during the window, we can negate our sample + * contribution, causing under-accounting. + * + * We avoid this by keeping two idle-delta counters and flipping them + * when the window starts, thus separating old and new NO_HZ load. + * + * The only trick is the slight shift in index flip for read vs write. + * + * 0s 5s 10s 15s + * +10 +10 +10 +10 + * |-|-----------|-|-----------|-|-----------|-| + * r:0 0 1 1 0 0 1 1 0 + * w:0 1 1 0 0 1 1 0 0 + * + * This ensures we'll fold the old idle contribution in this window while + * accumlating the new one. + * + * - When we wake up from NO_HZ idle during the window, we push up our + * contribution, since we effectively move our sample point to a known + * busy state. + * + * This is solved by pushing the window forward, and thus skipping the + * sample, for this cpu (effectively using the idle-delta for this cpu which + * was in effect at the time the window opened). This also solves the issue + * of having to deal with a cpu having been in NOHZ idle for multiple + * LOAD_FREQ intervals. * * When making the ILB scale, we should try to pull this in as well. */ -static atomic_long_t calc_load_tasks_idle; +static atomic_long_t calc_load_idle[2]; +static int calc_load_idx; -void calc_load_account_idle(struct rq *this_rq) +static inline int calc_load_write_idx(void) { + int idx = calc_load_idx; + + /* + * See calc_global_nohz(), if we observe the new index, we also + * need to observe the new update time. + */ + smp_rmb(); + + /* + * If the folding window started, make sure we start writing in the + * next idle-delta. + */ + if (!time_before(jiffies, calc_load_update)) + idx++; + + return idx & 1; +} + +static inline int calc_load_read_idx(void) +{ + return calc_load_idx & 1; +} + +void calc_load_enter_idle(void) +{ + struct rq *this_rq = this_rq(); long delta; + /* + * We're going into NOHZ mode, if there's any pending delta, fold it + * into the pending idle delta. + */ delta = calc_load_fold_active(this_rq); - if (delta) - atomic_long_add(delta, &calc_load_tasks_idle); + if (delta) { + int idx = calc_load_write_idx(); + atomic_long_add(delta, &calc_load_idle[idx]); + } } -static long calc_load_fold_idle(void) +void calc_load_exit_idle(void) { - long delta = 0; + struct rq *this_rq = this_rq(); /* - * Its got a race, we don't care... + * If we're still before the sample window, we're done. */ - if (atomic_long_read(&calc_load_tasks_idle)) - delta = atomic_long_xchg(&calc_load_tasks_idle, 0); + if (time_before(jiffies, this_rq->calc_load_update)) + return; + + /* + * We woke inside or after the sample window, this means we're already + * accounted through the nohz accounting, so skip the entire deal and + * sync up for the next window. + */ + this_rq->calc_load_update = calc_load_update; + if (time_before(jiffies, this_rq->calc_load_update + 10)) + this_rq->calc_load_update += LOAD_FREQ; +} + +static long calc_load_fold_idle(void) +{ + int idx = calc_load_read_idx(); + long delta = 0; + + if (atomic_long_read(&calc_load_idle[idx])) + delta = atomic_long_xchg(&calc_load_idle[idx], 0); return delta; } @@ -2359,66 +2512,39 @@ static void calc_global_nohz(void) { long delta, active, n; - /* - * If we crossed a calc_load_update boundary, make sure to fold - * any pending idle changes, the respective CPUs might have - * missed the tick driven calc_load_account_active() update - * due to NO_HZ. - */ - delta = calc_load_fold_idle(); - if (delta) - atomic_long_add(delta, &calc_load_tasks); - - /* - * It could be the one fold was all it took, we done! - */ - if (time_before(jiffies, calc_load_update + 10)) - return; - - /* - * Catch-up, fold however many we are behind still - */ - delta = jiffies - calc_load_update - 10; - n = 1 + (delta / LOAD_FREQ); + if (!time_before(jiffies, calc_load_update + 10)) { + /* + * Catch-up, fold however many we are behind still + */ + delta = jiffies - calc_load_update - 10; + n = 1 + (delta / LOAD_FREQ); - active = atomic_long_read(&calc_load_tasks); - active = active > 0 ? active * FIXED_1 : 0; + active = atomic_long_read(&calc_load_tasks); + active = active > 0 ? active * FIXED_1 : 0; - avenrun[0] = calc_load_n(avenrun[0], EXP_1, active, n); - avenrun[1] = calc_load_n(avenrun[1], EXP_5, active, n); - avenrun[2] = calc_load_n(avenrun[2], EXP_15, active, n); + avenrun[0] = calc_load_n(avenrun[0], EXP_1, active, n); + avenrun[1] = calc_load_n(avenrun[1], EXP_5, active, n); + avenrun[2] = calc_load_n(avenrun[2], EXP_15, active, n); - calc_load_update += n * LOAD_FREQ; -} -#else -void calc_load_account_idle(struct rq *this_rq) -{ -} + calc_load_update += n * LOAD_FREQ; + } -static inline long calc_load_fold_idle(void) -{ - return 0; + /* + * Flip the idle index... + * + * Make sure we first write the new time then flip the index, so that + * calc_load_write_idx() will see the new time when it reads the new + * index, this avoids a double flip messing things up. + */ + smp_wmb(); + calc_load_idx++; } +#else /* !CONFIG_NO_HZ */ -static void calc_global_nohz(void) -{ -} -#endif +static inline long calc_load_fold_idle(void) { return 0; } +static inline void calc_global_nohz(void) { } -/** - * get_avenrun - get the load average array - * @loads: pointer to dest load array - * @offset: offset to add - * @shift: shift count to shift the result left - * - * These values are estimates at best, so no need for locking. - */ -void get_avenrun(unsigned long *loads, unsigned long offset, int shift) -{ - loads[0] = (avenrun[0] + offset) << shift; - loads[1] = (avenrun[1] + offset) << shift; - loads[2] = (avenrun[2] + offset) << shift; -} +#endif /* CONFIG_NO_HZ */ /* * calc_load - update the avenrun load estimates 10 ticks after the @@ -2426,11 +2552,18 @@ void get_avenrun(unsigned long *loads, unsigned long offset, int shift) */ void calc_global_load(unsigned long ticks) { - long active; + long active, delta; if (time_before(jiffies, calc_load_update + 10)) return; + /* + * Fold the 'old' idle-delta to include all NO_HZ cpus. + */ + delta = calc_load_fold_idle(); + if (delta) + atomic_long_add(delta, &calc_load_tasks); + active = atomic_long_read(&calc_load_tasks); active = active > 0 ? active * FIXED_1 : 0; @@ -2441,12 +2574,7 @@ void calc_global_load(unsigned long ticks) calc_load_update += LOAD_FREQ; /* - * Account one period with whatever state we found before - * folding in the nohz state and ageing the entire idle period. - * - * This avoids loosing a sample when we go idle between - * calc_load_account_active() (10 ticks ago) and now and thus - * under-accounting. + * In case we idled for multiple LOAD_FREQ intervals, catch up in bulk. */ calc_global_nohz(); } @@ -2463,13 +2591,16 @@ static void calc_load_account_active(struct rq *this_rq) return; delta = calc_load_fold_active(this_rq); - delta += calc_load_fold_idle(); if (delta) atomic_long_add(delta, &calc_load_tasks); this_rq->calc_load_update += LOAD_FREQ; } +/* + * End of global load-average stuff + */ + /* * The exact cpuload at various idx values, calculated at every tick would be * load = (2^idx - 1) / 2^idx * load + 1 / 2^idx * cur_load @@ -3009,6 +3140,20 @@ void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t *st) # define nsecs_to_cputime(__nsecs) nsecs_to_jiffies(__nsecs) #endif +static cputime_t scale_utime(cputime_t utime, cputime_t rtime, cputime_t total) +{ + u64 temp = (__force u64) rtime; + + temp *= (__force u64) utime; + + if (sizeof(cputime_t) == 4) + temp = div_u64(temp, (__force u32) total); + else + temp = div64_u64(temp, (__force u64) total); + + return (__force cputime_t) temp; +} + void task_times(struct task_struct *p, cputime_t *ut, cputime_t *st) { cputime_t rtime, utime = p->utime, total = utime + p->stime; @@ -3018,13 +3163,9 @@ void task_times(struct task_struct *p, cputime_t *ut, cputime_t *st) */ rtime = nsecs_to_cputime(p->se.sum_exec_runtime); - if (total) { - u64 temp = (__force u64) rtime; - - temp *= (__force u64) utime; - do_div(temp, (__force u32) total); - utime = (__force cputime_t) temp; - } else + if (total) + utime = scale_utime(utime, rtime, total); + else utime = rtime; /* @@ -3051,13 +3192,9 @@ void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t *st) total = cputime.utime + cputime.stime; rtime = nsecs_to_cputime(cputime.sum_exec_runtime); - if (total) { - u64 temp = (__force u64) rtime; - - temp *= (__force u64) cputime.utime; - do_div(temp, (__force u32) total); - utime = (__force cputime_t) temp; - } else + if (total) + utime = scale_utime(cputime.utime, rtime, total); + else utime = rtime; sig->prev_utime = max(sig->prev_utime, utime); @@ -6884,34 +7021,66 @@ int __init sched_create_sysfs_power_savings_entries(struct device *dev) } #endif /* CONFIG_SCHED_MC || CONFIG_SCHED_SMT */ +static int num_cpus_frozen; /* used to mark begin/end of suspend/resume */ + /* * Update cpusets according to cpu_active mask. If cpusets are * disabled, cpuset_update_active_cpus() becomes a simple wrapper * around partition_sched_domains(). + * + * If we come here as part of a suspend/resume, don't touch cpusets because we + * want to restore it back to its original state upon resume anyway. */ static int cpuset_cpu_active(struct notifier_block *nfb, unsigned long action, void *hcpu) { - switch (action & ~CPU_TASKS_FROZEN) { + switch (action) { + case CPU_ONLINE_FROZEN: + case CPU_DOWN_FAILED_FROZEN: + + /* + * num_cpus_frozen tracks how many CPUs are involved in suspend + * resume sequence. As long as this is not the last online + * operation in the resume sequence, just build a single sched + * domain, ignoring cpusets. + */ + num_cpus_frozen--; + if (likely(num_cpus_frozen)) { + partition_sched_domains(1, NULL, NULL); + break; + } + + /* + * This is the last CPU online operation. So fall through and + * restore the original sched domains by considering the + * cpuset configurations. + */ + case CPU_ONLINE: case CPU_DOWN_FAILED: cpuset_update_active_cpus(); - return NOTIFY_OK; + break; default: return NOTIFY_DONE; } + return NOTIFY_OK; } static int cpuset_cpu_inactive(struct notifier_block *nfb, unsigned long action, void *hcpu) { - switch (action & ~CPU_TASKS_FROZEN) { + switch (action) { case CPU_DOWN_PREPARE: cpuset_update_active_cpus(); - return NOTIFY_OK; + break; + case CPU_DOWN_PREPARE_FROZEN: + num_cpus_frozen++; + partition_sched_domains(1, NULL, NULL); + break; default: return NOTIFY_DONE; } + return NOTIFY_OK; } void __init sched_init_smp(void) @@ -6964,6 +7133,7 @@ int in_sched_functions(unsigned long addr) #ifdef CONFIG_CGROUP_SCHED struct task_group root_task_group; +LIST_HEAD(task_groups); #endif DECLARE_PER_CPU(cpumask_var_t, load_balance_tmpmask); @@ -7385,6 +7555,7 @@ void sched_destroy_group(struct task_group *tg) */ void sched_move_task(struct task_struct *tsk) { + struct task_group *tg; int on_rq, running; unsigned long flags; struct rq *rq; @@ -7399,6 +7570,12 @@ void sched_move_task(struct task_struct *tsk) if (unlikely(running)) tsk->sched_class->put_prev_task(rq, tsk); + tg = container_of(task_subsys_state_check(tsk, cpu_cgroup_subsys_id, + lockdep_is_held(&tsk->sighand->siglock)), + struct task_group, css); + tg = autogroup_task_group(tsk, tg); + tsk->sched_task_group = tg; + #ifdef CONFIG_FAIR_GROUP_SCHED if (tsk->sched_class->task_move_group) tsk->sched_class->task_move_group(tsk, on_rq); diff --git a/kernel/sched/idle_task.c b/kernel/sched/idle_task.c index 91b4c957f28..fdf75227572 100644 --- a/kernel/sched/idle_task.c +++ b/kernel/sched/idle_task.c @@ -25,7 +25,6 @@ static void check_preempt_curr_idle(struct rq *rq, struct task_struct *p, int fl static struct task_struct *pick_next_task_idle(struct rq *rq) { schedstat_inc(rq, sched_goidle); - calc_load_account_idle(rq); return rq->idle; } diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c index 4b2761f093e..badcf2f1088 100644 --- a/kernel/sched/rt.c +++ b/kernel/sched/rt.c @@ -560,7 +560,7 @@ static inline struct rt_bandwidth *sched_rt_bandwidth(struct rt_rq *rt_rq) static int do_balance_runtime(struct rt_rq *rt_rq) { struct rt_bandwidth *rt_b = sched_rt_bandwidth(rt_rq); - struct root_domain *rd = cpu_rq(smp_processor_id())->rd; + struct root_domain *rd = rq_of_rt_rq(rt_rq)->rd; int i, weight, more = 0; u64 rt_period; diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index b9c312a4db7..35e9d2069bb 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -80,7 +80,7 @@ extern struct mutex sched_domains_mutex; struct cfs_rq; struct rt_rq; -static LIST_HEAD(task_groups); +extern struct list_head task_groups; struct cfs_bandwidth { #ifdef CONFIG_CFS_BANDWIDTH @@ -544,22 +544,19 @@ DECLARE_PER_CPU(int, sd_llc_id); /* * Return the group to which this tasks belongs. * - * We use task_subsys_state_check() and extend the RCU verification with - * pi->lock and rq->lock because cpu_cgroup_attach() holds those locks for each - * task it moves into the cgroup. Therefore by holding either of those locks, - * we pin the task to the current cgroup. + * We cannot use task_subsys_state() and friends because the cgroup + * subsystem changes that value before the cgroup_subsys::attach() method + * is called, therefore we cannot pin it and might observe the wrong value. + * + * The same is true for autogroup's p->signal->autogroup->tg, the autogroup + * core changes this before calling sched_move_task(). + * + * Instead we use a 'copy' which is updated from sched_move_task() while + * holding both task_struct::pi_lock and rq::lock. */ static inline struct task_group *task_group(struct task_struct *p) { - struct task_group *tg; - struct cgroup_subsys_state *css; - - css = task_subsys_state_check(p, cpu_cgroup_subsys_id, - lockdep_is_held(&p->pi_lock) || - lockdep_is_held(&task_rq(p)->lock)); - tg = container_of(css, struct task_group, css); - - return autogroup_task_group(p, tg); + return p->sched_task_group; } static inline bool task_notify_on_migrate(struct task_struct *p) @@ -993,8 +990,6 @@ static inline u64 sched_avg_period(void) return (u64)sysctl_sched_time_avg * NSEC_PER_MSEC / 2; } -void calc_load_account_idle(struct rq *this_rq); - #ifdef CONFIG_SCHED_HRTICK /* diff --git a/kernel/sched/stop_task.c b/kernel/sched/stop_task.c index 7b386e86fd2..da5eb5bed84 100644 --- a/kernel/sched/stop_task.c +++ b/kernel/sched/stop_task.c @@ -27,8 +27,10 @@ static struct task_struct *pick_next_task_stop(struct rq *rq) { struct task_struct *stop = rq->stop; - if (stop && stop->on_rq) + if (stop && stop->on_rq) { + stop->se.exec_start = rq->clock_task; return stop; + } return NULL; } @@ -52,6 +54,21 @@ static void yield_task_stop(struct rq *rq) static void put_prev_task_stop(struct rq *rq, struct task_struct *prev) { + struct task_struct *curr = rq->curr; + u64 delta_exec; + + delta_exec = rq->clock_task - curr->se.exec_start; + if (unlikely((s64)delta_exec < 0)) + delta_exec = 0; + + schedstat_set(curr->se.statistics.exec_max, + max(curr->se.statistics.exec_max, delta_exec)); + + curr->se.sum_exec_runtime += delta_exec; + account_group_exec_runtime(curr, delta_exec); + + curr->se.exec_start = rq->clock_task; + cpuacct_charge(curr, delta_exec); } static void task_tick_stop(struct rq *rq, struct task_struct *curr, int queued) @@ -60,6 +77,9 @@ static void task_tick_stop(struct rq *rq, struct task_struct *curr, int queued) static void set_curr_task_stop(struct rq *rq) { + struct task_struct *stop = rq->stop; + + stop->se.exec_start = rq->clock_task; } static void switched_to_stop(struct rq *rq, struct task_struct *p) diff --git a/kernel/smp.c b/kernel/smp.c index da6b76e04e4..b32ac0a2b27 100644 --- a/kernel/smp.c +++ b/kernel/smp.c @@ -33,6 +33,7 @@ struct call_function_data { struct call_single_data csd; atomic_t refs; cpumask_var_t cpumask; + cpumask_var_t cpumask_ipi; }; static DEFINE_PER_CPU_SHARED_ALIGNED(struct call_function_data, cfd_data); @@ -56,6 +57,9 @@ hotplug_cfd(struct notifier_block *nfb, unsigned long action, void *hcpu) if (!zalloc_cpumask_var_node(&cfd->cpumask, GFP_KERNEL, cpu_to_node(cpu))) return notifier_from_errno(-ENOMEM); + if (!zalloc_cpumask_var_node(&cfd->cpumask_ipi, GFP_KERNEL, + cpu_to_node(cpu))) + return notifier_from_errno(-ENOMEM); break; #ifdef CONFIG_HOTPLUG_CPU @@ -65,6 +69,7 @@ hotplug_cfd(struct notifier_block *nfb, unsigned long action, void *hcpu) case CPU_DEAD: case CPU_DEAD_FROZEN: free_cpumask_var(cfd->cpumask); + free_cpumask_var(cfd->cpumask_ipi); break; #endif }; @@ -526,6 +531,12 @@ void smp_call_function_many(const struct cpumask *mask, return; } + /* + * After we put an entry into the list, data->cpumask + * may be cleared again when another CPU sends another IPI for + * a SMP function call, so data->cpumask will be zero. + */ + cpumask_copy(data->cpumask_ipi, data->cpumask); raw_spin_lock_irqsave(&call_function.lock, flags); /* * Place entry at the _HEAD_ of the list, so that any cpu still @@ -549,7 +560,7 @@ void smp_call_function_many(const struct cpumask *mask, smp_mb(); /* Send a message to all CPUs in the map */ - arch_send_call_function_ipi_mask(data->cpumask); + arch_send_call_function_ipi_mask(data->cpumask_ipi); /* Optionally wait for the CPUs to complete */ if (wait) diff --git a/kernel/sys.c b/kernel/sys.c index c2331850308..d9798315069 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -367,6 +367,7 @@ EXPORT_SYMBOL(unregister_reboot_notifier); void kernel_restart(char *cmd) { kernel_restart_prepare(cmd); + disable_nonboot_cpus(); if (!cmd) printk(KERN_EMERG "Restarting system.\n"); else diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c index e8c867173ae..8b707100286 100644 --- a/kernel/time/ntp.c +++ b/kernel/time/ntp.c @@ -409,7 +409,9 @@ int second_overflow(unsigned long secs) time_state = TIME_DEL; break; case TIME_INS: - if (secs % 86400 == 0) { + if (!(time_status & STA_INS)) + time_state = TIME_OK; + else if (secs % 86400 == 0) { leap = -1; time_state = TIME_OOP; time_tai++; @@ -418,7 +420,9 @@ int second_overflow(unsigned long secs) } break; case TIME_DEL: - if ((secs + 1) % 86400 == 0) { + if (!(time_status & STA_DEL)) + time_state = TIME_OK; + else if ((secs + 1) % 86400 == 0) { leap = 1; time_tai--; time_state = TIME_WAIT; diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 30d7bebe94f..4b82d55eaf6 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -151,6 +151,7 @@ static void tick_nohz_update_jiffies(ktime_t now) tick_do_update_jiffies64(now); local_irq_restore(flags); + calc_load_exit_idle(); touch_softlockup_watchdog(); } @@ -407,6 +408,7 @@ static void tick_nohz_stop_sched_tick(struct tick_sched *ts) */ if (!ts->tick_stopped) { select_nohz_load_balancer(1); + calc_load_enter_idle(); ts->idle_tick = hrtimer_get_expires(&ts->sched_timer); ts->tick_stopped = 1; @@ -600,6 +602,7 @@ void tick_nohz_idle_exit(void) account_idle_ticks(ticks); #endif + calc_load_exit_idle(); touch_softlockup_watchdog(); /* * Cancel the scheduled timer and restore the tick diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 2f7b1b42ec2..0a462de7f96 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c @@ -70,6 +70,12 @@ struct timekeeper { /* The raw monotonic time for the CLOCK_MONOTONIC_RAW posix clock. */ struct timespec raw_time; + /* Offset clock monotonic -> clock realtime */ + ktime_t offs_real; + + /* Offset clock monotonic -> clock boottime */ + ktime_t offs_boot; + /* Seqlock for all timekeeper values */ seqlock_t lock; }; @@ -172,6 +178,14 @@ static inline s64 timekeeping_get_ns_raw(void) return clocksource_cyc2ns(cycle_delta, clock->mult, clock->shift); } +static void update_rt_offset(void) +{ + struct timespec tmp, *wtm = &timekeeper.wall_to_monotonic; + + set_normalized_timespec(&tmp, -wtm->tv_sec, -wtm->tv_nsec); + timekeeper.offs_real = timespec_to_ktime(tmp); +} + /* must hold write on timekeeper.lock */ static void timekeeping_update(bool clearntp) { @@ -179,6 +193,7 @@ static void timekeeping_update(bool clearntp) timekeeper.ntp_error = 0; ntp_clear(); } + update_rt_offset(); update_vsyscall(&timekeeper.xtime, &timekeeper.wall_to_monotonic, timekeeper.clock, timekeeper.mult); } @@ -370,7 +385,7 @@ int do_settimeofday(const struct timespec *tv) struct timespec ts_delta; unsigned long flags; - if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) + if (!timespec_valid_strict(tv)) return -EINVAL; write_seqlock_irqsave(&timekeeper.lock, flags); @@ -405,6 +420,8 @@ EXPORT_SYMBOL(do_settimeofday); int timekeeping_inject_offset(struct timespec *ts) { unsigned long flags; + struct timespec tmp; + int ret = 0; if ((unsigned long)ts->tv_nsec >= NSEC_PER_SEC) return -EINVAL; @@ -413,10 +430,17 @@ int timekeeping_inject_offset(struct timespec *ts) timekeeping_forward_now(); + tmp = timespec_add(timekeeper.xtime, *ts); + if (!timespec_valid_strict(&tmp)) { + ret = -EINVAL; + goto error; + } + timekeeper.xtime = timespec_add(timekeeper.xtime, *ts); timekeeper.wall_to_monotonic = timespec_sub(timekeeper.wall_to_monotonic, *ts); +error: /* even if we error out, we forwarded the time, so call update */ timekeeping_update(true); write_sequnlock_irqrestore(&timekeeper.lock, flags); @@ -424,7 +448,7 @@ int timekeeping_inject_offset(struct timespec *ts) /* signal hrtimers about time change */ clock_was_set(); - return 0; + return ret; } EXPORT_SYMBOL(timekeeping_inject_offset); @@ -584,7 +608,20 @@ void __init timekeeping_init(void) struct timespec now, boot; read_persistent_clock(&now); + if (!timespec_valid_strict(&now)) { + pr_warn("WARNING: Persistent clock returned invalid value!\n" + " Check your CMOS/BIOS settings.\n"); + now.tv_sec = 0; + now.tv_nsec = 0; + } + read_boot_clock(&boot); + if (!timespec_valid_strict(&boot)) { + pr_warn("WARNING: Boot clock returned invalid value!\n" + " Check your CMOS/BIOS settings.\n"); + boot.tv_sec = 0; + boot.tv_nsec = 0; + } seqlock_init(&timekeeper.lock); @@ -606,6 +643,7 @@ void __init timekeeping_init(void) } set_normalized_timespec(&timekeeper.wall_to_monotonic, -boot.tv_sec, -boot.tv_nsec); + update_rt_offset(); timekeeper.total_sleep_time.tv_sec = 0; timekeeper.total_sleep_time.tv_nsec = 0; write_sequnlock_irqrestore(&timekeeper.lock, flags); @@ -614,6 +652,12 @@ void __init timekeeping_init(void) /* time in seconds when suspend began */ static struct timespec timekeeping_suspend_time; +static void update_sleep_time(struct timespec t) +{ + timekeeper.total_sleep_time = t; + timekeeper.offs_boot = timespec_to_ktime(t); +} + /** * __timekeeping_inject_sleeptime - Internal function to add sleep interval * @delta: pointer to a timespec delta value @@ -623,7 +667,7 @@ static struct timespec timekeeping_suspend_time; */ static void __timekeeping_inject_sleeptime(struct timespec *delta) { - if (!timespec_valid(delta)) { + if (!timespec_valid_strict(delta)) { printk(KERN_WARNING "__timekeeping_inject_sleeptime: Invalid " "sleep delta value!\n"); return; @@ -632,8 +676,7 @@ static void __timekeeping_inject_sleeptime(struct timespec *delta) timekeeper.xtime = timespec_add(timekeeper.xtime, *delta); timekeeper.wall_to_monotonic = timespec_sub(timekeeper.wall_to_monotonic, *delta); - timekeeper.total_sleep_time = timespec_add( - timekeeper.total_sleep_time, *delta); + update_sleep_time(timespec_add(timekeeper.total_sleep_time, *delta)); } @@ -698,6 +741,7 @@ static void timekeeping_resume(void) timekeeper.clock->cycle_last = timekeeper.clock->read(timekeeper.clock); timekeeper.ntp_error = 0; timekeeping_suspended = 0; + timekeeping_update(false); write_sequnlock_irqrestore(&timekeeper.lock, flags); touch_softlockup_watchdog(); @@ -965,10 +1009,12 @@ static cycle_t logarithmic_accumulation(cycle_t offset, int shift) leap = second_overflow(timekeeper.xtime.tv_sec); timekeeper.xtime.tv_sec += leap; timekeeper.wall_to_monotonic.tv_sec -= leap; + if (leap) + clock_was_set_delayed(); } /* Accumulate raw time */ - raw_nsecs = timekeeper.raw_interval << shift; + raw_nsecs = (u64)timekeeper.raw_interval << shift; raw_nsecs += timekeeper.raw_time.tv_nsec; if (raw_nsecs >= NSEC_PER_SEC) { u64 raw_secs = raw_nsecs; @@ -1011,9 +1057,12 @@ static void update_wall_time(void) #else offset = (clock->read(clock) - clock->cycle_last) & clock->mask; #endif + /* Check if there's really nothing to do */ + if (offset < timekeeper.cycle_interval) + goto out; + timekeeper.xtime_nsec = (s64)timekeeper.xtime.tv_nsec << timekeeper.shift; - /* * With NO_HZ we may have to accumulate many cycle_intervals * (think "ticks") worth of time at once. To do this efficiently, @@ -1081,6 +1130,8 @@ static void update_wall_time(void) leap = second_overflow(timekeeper.xtime.tv_sec); timekeeper.xtime.tv_sec += leap; timekeeper.wall_to_monotonic.tv_sec -= leap; + if (leap) + clock_was_set_delayed(); } timekeeping_update(false); @@ -1248,6 +1299,40 @@ void get_xtime_and_monotonic_and_sleep_offset(struct timespec *xtim, } while (read_seqretry(&timekeeper.lock, seq)); } +#ifdef CONFIG_HIGH_RES_TIMERS +/** + * ktime_get_update_offsets - hrtimer helper + * @offs_real: pointer to storage for monotonic -> realtime offset + * @offs_boot: pointer to storage for monotonic -> boottime offset + * + * Returns current monotonic time and updates the offsets + * Called from hrtimer_interupt() or retrigger_next_event() + */ +ktime_t ktime_get_update_offsets(ktime_t *offs_real, ktime_t *offs_boot) +{ + ktime_t now; + unsigned int seq; + u64 secs, nsecs; + + do { + seq = read_seqbegin(&timekeeper.lock); + + secs = timekeeper.xtime.tv_sec; + nsecs = timekeeper.xtime.tv_nsec; + nsecs += timekeeping_get_ns(); + /* If arch requires, add in gettimeoffset() */ + nsecs += arch_gettimeoffset(); + + *offs_real = timekeeper.offs_real; + *offs_boot = timekeeper.offs_boot; + } while (read_seqretry(&timekeeper.lock, seq)); + + now = ktime_add_ns(ktime_set(secs, 0), nsecs); + now = ktime_sub(now, *offs_real); + return now; +} +#endif + /** * ktime_get_monotonic_offset() - get wall_to_monotonic in ktime_t format */ diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 0fa92f677c9..6b194d842b1 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -2368,7 +2368,7 @@ static void reset_iter_read(struct ftrace_iterator *iter) { iter->pos = 0; iter->func_pos = 0; - iter->flags &= ~(FTRACE_ITER_PRINTALL & FTRACE_ITER_HASH); + iter->flags &= ~(FTRACE_ITER_PRINTALL | FTRACE_ITER_HASH); } static void *t_start(struct seq_file *m, loff_t *pos) @@ -3869,7 +3869,7 @@ static int ftrace_module_notify(struct notifier_block *self, struct notifier_block ftrace_module_nb = { .notifier_call = ftrace_module_notify, - .priority = 0, + .priority = INT_MAX, /* Run before anything that can use kprobes */ }; extern unsigned long __start_mcount_loc[]; diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index cf8d11e91ef..28667834181 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -2708,7 +2708,7 @@ unsigned long ring_buffer_oldest_event_ts(struct ring_buffer *buffer, int cpu) unsigned long flags; struct ring_buffer_per_cpu *cpu_buffer; struct buffer_page *bpage; - unsigned long ret; + unsigned long ret = 0; if (!cpumask_test_cpu(cpu, buffer->cpumask)) return 0; @@ -2723,7 +2723,8 @@ unsigned long ring_buffer_oldest_event_ts(struct ring_buffer *buffer, int cpu) bpage = cpu_buffer->reader_page; else bpage = rb_set_head_page(cpu_buffer); - ret = bpage->page->time_stamp; + if (bpage) + ret = bpage->page->time_stamp; raw_spin_unlock_irqrestore(&cpu_buffer->reader_lock, flags); return ret; @@ -3030,6 +3031,8 @@ rb_get_reader_page(struct ring_buffer_per_cpu *cpu_buffer) * Splice the empty reader page into the list around the head. */ reader = rb_set_head_page(cpu_buffer); + if (!reader) + goto out; cpu_buffer->reader_page->list.next = rb_list_head(reader->list.next); cpu_buffer->reader_page->list.prev = reader->list.prev; diff --git a/kernel/watchdog.c b/kernel/watchdog.c index 6959c6fbeee..aead371e5a3 100644 --- a/kernel/watchdog.c +++ b/kernel/watchdog.c @@ -112,7 +112,7 @@ static unsigned long get_timestamp(int this_cpu) return cpu_clock(this_cpu) >> 30LL; /* 2^30 ~= 10^9 */ } -static unsigned long get_sample_period(void) +static u64 get_sample_period(void) { /* * convert watchdog_thresh from seconds to ns @@ -121,7 +121,7 @@ static unsigned long get_sample_period(void) * and hard thresholds) to increment before the * hardlockup detector generates a warning */ - return get_softlockup_thresh() * (NSEC_PER_SEC / 5); + return get_softlockup_thresh() * ((u64)NSEC_PER_SEC / 5); } /* Commands for resetting the watchdog */ diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 2cbbbb0b14e..657ba28e79a 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -41,16 +41,18 @@ #include #include #include +#include #include "workqueue_sched.h" enum { /* global_cwq flags */ - GCWQ_MANAGE_WORKERS = 1 << 0, /* need to manage workers */ - GCWQ_MANAGING_WORKERS = 1 << 1, /* managing workers */ - GCWQ_DISASSOCIATED = 1 << 2, /* cpu can't serve workers */ - GCWQ_FREEZING = 1 << 3, /* freeze in progress */ - GCWQ_HIGHPRI_PENDING = 1 << 4, /* highpri works on queue */ + GCWQ_DISASSOCIATED = 1 << 0, /* cpu can't serve workers */ + GCWQ_FREEZING = 1 << 1, /* freeze in progress */ + + /* pool flags */ + POOL_MANAGE_WORKERS = 1 << 0, /* need to manage workers */ + POOL_MANAGING_WORKERS = 1 << 1, /* managing workers */ /* worker flags */ WORKER_STARTED = 1 << 0, /* started */ @@ -72,6 +74,8 @@ enum { TRUSTEE_RELEASE = 3, /* release workers */ TRUSTEE_DONE = 4, /* trustee is done */ + NR_WORKER_POOLS = 2, /* # worker pools per gcwq */ + BUSY_WORKER_HASH_ORDER = 6, /* 64 pointers */ BUSY_WORKER_HASH_SIZE = 1 << BUSY_WORKER_HASH_ORDER, BUSY_WORKER_HASH_MASK = BUSY_WORKER_HASH_SIZE - 1, @@ -91,6 +95,7 @@ enum { * all cpus. Give -20. */ RESCUER_NICE_LEVEL = -20, + HIGHPRI_NICE_LEVEL = -20, }; /* @@ -115,6 +120,7 @@ enum { */ struct global_cwq; +struct worker_pool; /* * The poor guys doing the actual heavy lifting. All on-duty workers @@ -131,7 +137,7 @@ struct worker { struct cpu_workqueue_struct *current_cwq; /* L: current_work's cwq */ struct list_head scheduled; /* L: scheduled works */ struct task_struct *task; /* I: worker task */ - struct global_cwq *gcwq; /* I: the associated gcwq */ + struct worker_pool *pool; /* I: the associated pool */ /* 64 bytes boundary on 64bit, 32 on 32bit */ unsigned long last_active; /* L: last active timestamp */ unsigned int flags; /* X: flags */ @@ -139,6 +145,22 @@ struct worker { struct work_struct rebind_work; /* L: rebind worker to cpu */ }; +struct worker_pool { + struct global_cwq *gcwq; /* I: the owning gcwq */ + unsigned int flags; /* X: flags */ + + struct list_head worklist; /* L: list of pending works */ + int nr_workers; /* L: total number of workers */ + int nr_idle; /* L: currently idle ones */ + + struct list_head idle_list; /* X: list of idle workers */ + struct timer_list idle_timer; /* L: worker idle timeout */ + struct timer_list mayday_timer; /* L: SOS timer for workers */ + + struct ida worker_ida; /* L: for worker IDs */ + struct worker *first_idle; /* L: first idle worker */ +}; + /* * Global per-cpu workqueue. There's one and only one for each cpu * and all works are queued and processed here regardless of their @@ -146,27 +168,18 @@ struct worker { */ struct global_cwq { spinlock_t lock; /* the gcwq lock */ - struct list_head worklist; /* L: list of pending works */ unsigned int cpu; /* I: the associated cpu */ unsigned int flags; /* L: GCWQ_* flags */ - int nr_workers; /* L: total number of workers */ - int nr_idle; /* L: currently idle ones */ - - /* workers are chained either in the idle_list or busy_hash */ - struct list_head idle_list; /* X: list of idle workers */ + /* workers are chained either in busy_hash or pool idle_list */ struct hlist_head busy_hash[BUSY_WORKER_HASH_SIZE]; /* L: hash of busy workers */ - struct timer_list idle_timer; /* L: worker idle timeout */ - struct timer_list mayday_timer; /* L: SOS timer for dworkers */ - - struct ida worker_ida; /* L: for worker IDs */ + struct worker_pool pools[2]; /* normal and highpri pools */ struct task_struct *trustee; /* L: for gcwq shutdown */ unsigned int trustee_state; /* L: trustee state */ wait_queue_head_t trustee_wait; /* trustee wait */ - struct worker *first_idle; /* L: first idle worker */ } ____cacheline_aligned_in_smp; /* @@ -175,7 +188,7 @@ struct global_cwq { * aligned at two's power of the number of flag bits. */ struct cpu_workqueue_struct { - struct global_cwq *gcwq; /* I: the associated gcwq */ + struct worker_pool *pool; /* I: the associated pool */ struct workqueue_struct *wq; /* I: the owning workqueue */ int work_color; /* L: current color */ int flush_color; /* L: flushing color */ @@ -264,6 +277,10 @@ EXPORT_SYMBOL_GPL(system_nrt_freezable_wq); #define CREATE_TRACE_POINTS #include +#define for_each_worker_pool(pool, gcwq) \ + for ((pool) = &(gcwq)->pools[0]; \ + (pool) < &(gcwq)->pools[NR_WORKER_POOLS]; (pool)++) + #define for_each_busy_worker(worker, i, pos, gcwq) \ for (i = 0; i < BUSY_WORKER_HASH_SIZE; i++) \ hlist_for_each_entry(worker, pos, &gcwq->busy_hash[i], hentry) @@ -444,7 +461,7 @@ static bool workqueue_freezing; /* W: have wqs started freezing? */ * try_to_wake_up(). Put it in a separate cacheline. */ static DEFINE_PER_CPU(struct global_cwq, global_cwq); -static DEFINE_PER_CPU_SHARED_ALIGNED(atomic_t, gcwq_nr_running); +static DEFINE_PER_CPU_SHARED_ALIGNED(atomic_t, pool_nr_running[NR_WORKER_POOLS]); /* * Global cpu workqueue and nr_running counter for unbound gcwq. The @@ -452,10 +469,17 @@ static DEFINE_PER_CPU_SHARED_ALIGNED(atomic_t, gcwq_nr_running); * workers have WORKER_UNBOUND set. */ static struct global_cwq unbound_global_cwq; -static atomic_t unbound_gcwq_nr_running = ATOMIC_INIT(0); /* always 0 */ +static atomic_t unbound_pool_nr_running[NR_WORKER_POOLS] = { + [0 ... NR_WORKER_POOLS - 1] = ATOMIC_INIT(0), /* always 0 */ +}; static int worker_thread(void *__worker); +static int worker_pool_pri(struct worker_pool *pool) +{ + return pool - pool->gcwq->pools; +} + static struct global_cwq *get_gcwq(unsigned int cpu) { if (cpu != WORK_CPU_UNBOUND) @@ -464,12 +488,15 @@ static struct global_cwq *get_gcwq(unsigned int cpu) return &unbound_global_cwq; } -static atomic_t *get_gcwq_nr_running(unsigned int cpu) +static atomic_t *get_pool_nr_running(struct worker_pool *pool) { + int cpu = pool->gcwq->cpu; + int idx = worker_pool_pri(pool); + if (cpu != WORK_CPU_UNBOUND) - return &per_cpu(gcwq_nr_running, cpu); + return &per_cpu(pool_nr_running, cpu)[idx]; else - return &unbound_gcwq_nr_running; + return &unbound_pool_nr_running[idx]; } static struct cpu_workqueue_struct *get_cwq(unsigned int cpu, @@ -555,7 +582,7 @@ static struct global_cwq *get_work_gcwq(struct work_struct *work) if (data & WORK_STRUCT_CWQ) return ((struct cpu_workqueue_struct *) - (data & WORK_STRUCT_WQ_DATA_MASK))->gcwq; + (data & WORK_STRUCT_WQ_DATA_MASK))->pool->gcwq; cpu = data >> WORK_STRUCT_FLAG_BITS; if (cpu == WORK_CPU_NONE) @@ -566,60 +593,62 @@ static struct global_cwq *get_work_gcwq(struct work_struct *work) } /* - * Policy functions. These define the policies on how the global - * worker pool is managed. Unless noted otherwise, these functions - * assume that they're being called with gcwq->lock held. + * Policy functions. These define the policies on how the global worker + * pools are managed. Unless noted otherwise, these functions assume that + * they're being called with gcwq->lock held. */ -static bool __need_more_worker(struct global_cwq *gcwq) +static bool __need_more_worker(struct worker_pool *pool) { - return !atomic_read(get_gcwq_nr_running(gcwq->cpu)) || - gcwq->flags & GCWQ_HIGHPRI_PENDING; + return !atomic_read(get_pool_nr_running(pool)); } /* * Need to wake up a worker? Called from anything but currently * running workers. + * + * Note that, because unbound workers never contribute to nr_running, this + * function will always return %true for unbound gcwq as long as the + * worklist isn't empty. */ -static bool need_more_worker(struct global_cwq *gcwq) +static bool need_more_worker(struct worker_pool *pool) { - return !list_empty(&gcwq->worklist) && __need_more_worker(gcwq); + return !list_empty(&pool->worklist) && __need_more_worker(pool); } /* Can I start working? Called from busy but !running workers. */ -static bool may_start_working(struct global_cwq *gcwq) +static bool may_start_working(struct worker_pool *pool) { - return gcwq->nr_idle; + return pool->nr_idle; } /* Do I need to keep working? Called from currently running workers. */ -static bool keep_working(struct global_cwq *gcwq) +static bool keep_working(struct worker_pool *pool) { - atomic_t *nr_running = get_gcwq_nr_running(gcwq->cpu); + atomic_t *nr_running = get_pool_nr_running(pool); - return !list_empty(&gcwq->worklist) && - (atomic_read(nr_running) <= 1 || - gcwq->flags & GCWQ_HIGHPRI_PENDING); + return !list_empty(&pool->worklist) && atomic_read(nr_running) <= 1; } /* Do we need a new worker? Called from manager. */ -static bool need_to_create_worker(struct global_cwq *gcwq) +static bool need_to_create_worker(struct worker_pool *pool) { - return need_more_worker(gcwq) && !may_start_working(gcwq); + return need_more_worker(pool) && !may_start_working(pool); } /* Do I need to be the manager? */ -static bool need_to_manage_workers(struct global_cwq *gcwq) +static bool need_to_manage_workers(struct worker_pool *pool) { - return need_to_create_worker(gcwq) || gcwq->flags & GCWQ_MANAGE_WORKERS; + return need_to_create_worker(pool) || + (pool->flags & POOL_MANAGE_WORKERS); } /* Do we have too many workers and should some go away? */ -static bool too_many_workers(struct global_cwq *gcwq) +static bool too_many_workers(struct worker_pool *pool) { - bool managing = gcwq->flags & GCWQ_MANAGING_WORKERS; - int nr_idle = gcwq->nr_idle + managing; /* manager is considered idle */ - int nr_busy = gcwq->nr_workers - nr_idle; + bool managing = pool->flags & POOL_MANAGING_WORKERS; + int nr_idle = pool->nr_idle + managing; /* manager is considered idle */ + int nr_busy = pool->nr_workers - nr_idle; return nr_idle > 2 && (nr_idle - 2) * MAX_IDLE_WORKERS_RATIO >= nr_busy; } @@ -629,26 +658,26 @@ static bool too_many_workers(struct global_cwq *gcwq) */ /* Return the first worker. Safe with preemption disabled */ -static struct worker *first_worker(struct global_cwq *gcwq) +static struct worker *first_worker(struct worker_pool *pool) { - if (unlikely(list_empty(&gcwq->idle_list))) + if (unlikely(list_empty(&pool->idle_list))) return NULL; - return list_first_entry(&gcwq->idle_list, struct worker, entry); + return list_first_entry(&pool->idle_list, struct worker, entry); } /** * wake_up_worker - wake up an idle worker - * @gcwq: gcwq to wake worker for + * @pool: worker pool to wake worker from * - * Wake up the first idle worker of @gcwq. + * Wake up the first idle worker of @pool. * * CONTEXT: * spin_lock_irq(gcwq->lock). */ -static void wake_up_worker(struct global_cwq *gcwq) +static void wake_up_worker(struct worker_pool *pool) { - struct worker *worker = first_worker(gcwq); + struct worker *worker = first_worker(pool); if (likely(worker)) wake_up_process(worker->task); @@ -670,7 +699,7 @@ void wq_worker_waking_up(struct task_struct *task, unsigned int cpu) struct worker *worker = kthread_data(task); if (!(worker->flags & WORKER_NOT_RUNNING)) - atomic_inc(get_gcwq_nr_running(cpu)); + atomic_inc(get_pool_nr_running(worker->pool)); } /** @@ -692,8 +721,8 @@ struct task_struct *wq_worker_sleeping(struct task_struct *task, unsigned int cpu) { struct worker *worker = kthread_data(task), *to_wakeup = NULL; - struct global_cwq *gcwq = get_gcwq(cpu); - atomic_t *nr_running = get_gcwq_nr_running(cpu); + struct worker_pool *pool = worker->pool; + atomic_t *nr_running = get_pool_nr_running(pool); if (worker->flags & WORKER_NOT_RUNNING) return NULL; @@ -712,8 +741,8 @@ struct task_struct *wq_worker_sleeping(struct task_struct *task, * could be manipulating idle_list, so dereferencing idle_list * without gcwq lock is safe. */ - if (atomic_dec_and_test(nr_running) && !list_empty(&gcwq->worklist)) - to_wakeup = first_worker(gcwq); + if (atomic_dec_and_test(nr_running) && !list_empty(&pool->worklist)) + to_wakeup = first_worker(pool); return to_wakeup ? to_wakeup->task : NULL; } @@ -733,7 +762,7 @@ struct task_struct *wq_worker_sleeping(struct task_struct *task, static inline void worker_set_flags(struct worker *worker, unsigned int flags, bool wakeup) { - struct global_cwq *gcwq = worker->gcwq; + struct worker_pool *pool = worker->pool; WARN_ON_ONCE(worker->task != current); @@ -744,12 +773,12 @@ static inline void worker_set_flags(struct worker *worker, unsigned int flags, */ if ((flags & WORKER_NOT_RUNNING) && !(worker->flags & WORKER_NOT_RUNNING)) { - atomic_t *nr_running = get_gcwq_nr_running(gcwq->cpu); + atomic_t *nr_running = get_pool_nr_running(pool); if (wakeup) { if (atomic_dec_and_test(nr_running) && - !list_empty(&gcwq->worklist)) - wake_up_worker(gcwq); + !list_empty(&pool->worklist)) + wake_up_worker(pool); } else atomic_dec(nr_running); } @@ -769,7 +798,7 @@ static inline void worker_set_flags(struct worker *worker, unsigned int flags, */ static inline void worker_clr_flags(struct worker *worker, unsigned int flags) { - struct global_cwq *gcwq = worker->gcwq; + struct worker_pool *pool = worker->pool; unsigned int oflags = worker->flags; WARN_ON_ONCE(worker->task != current); @@ -783,7 +812,7 @@ static inline void worker_clr_flags(struct worker *worker, unsigned int flags) */ if ((flags & WORKER_NOT_RUNNING) && (oflags & WORKER_NOT_RUNNING)) if (!(worker->flags & WORKER_NOT_RUNNING)) - atomic_inc(get_gcwq_nr_running(gcwq->cpu)); + atomic_inc(get_pool_nr_running(pool)); } /** @@ -866,43 +895,6 @@ static struct worker *find_worker_executing_work(struct global_cwq *gcwq, work); } -/** - * gcwq_determine_ins_pos - find insertion position - * @gcwq: gcwq of interest - * @cwq: cwq a work is being queued for - * - * A work for @cwq is about to be queued on @gcwq, determine insertion - * position for the work. If @cwq is for HIGHPRI wq, the work is - * queued at the head of the queue but in FIFO order with respect to - * other HIGHPRI works; otherwise, at the end of the queue. This - * function also sets GCWQ_HIGHPRI_PENDING flag to hint @gcwq that - * there are HIGHPRI works pending. - * - * CONTEXT: - * spin_lock_irq(gcwq->lock). - * - * RETURNS: - * Pointer to inserstion position. - */ -static inline struct list_head *gcwq_determine_ins_pos(struct global_cwq *gcwq, - struct cpu_workqueue_struct *cwq) -{ - struct work_struct *twork; - - if (likely(!(cwq->wq->flags & WQ_HIGHPRI))) - return &gcwq->worklist; - - list_for_each_entry(twork, &gcwq->worklist, entry) { - struct cpu_workqueue_struct *tcwq = get_work_cwq(twork); - - if (!(tcwq->wq->flags & WQ_HIGHPRI)) - break; - } - - gcwq->flags |= GCWQ_HIGHPRI_PENDING; - return &twork->entry; -} - /** * insert_work - insert a work into gcwq * @cwq: cwq @work belongs to @@ -920,7 +912,7 @@ static void insert_work(struct cpu_workqueue_struct *cwq, struct work_struct *work, struct list_head *head, unsigned int extra_flags) { - struct global_cwq *gcwq = cwq->gcwq; + struct worker_pool *pool = cwq->pool; /* we own @work, set data and link */ set_work_cwq(work, cwq, extra_flags); @@ -940,8 +932,8 @@ static void insert_work(struct cpu_workqueue_struct *cwq, */ smp_mb(); - if (__need_more_worker(gcwq)) - wake_up_worker(gcwq); + if (__need_more_worker(pool)) + wake_up_worker(pool); } /* @@ -1040,7 +1032,7 @@ static void __queue_work(unsigned int cpu, struct workqueue_struct *wq, if (likely(cwq->nr_active < cwq->max_active)) { trace_workqueue_activate_work(work); cwq->nr_active++; - worklist = gcwq_determine_ins_pos(gcwq, cwq); + worklist = &cwq->pool->worklist; } else { work_flags |= WORK_STRUCT_DELAYED; worklist = &cwq->delayed_works; @@ -1141,8 +1133,8 @@ int queue_delayed_work_on(int cpu, struct workqueue_struct *wq, if (!test_and_set_bit(WORK_STRUCT_PENDING_BIT, work_data_bits(work))) { unsigned int lcpu; - BUG_ON(timer_pending(timer)); - BUG_ON(!list_empty(&work->entry)); + WARN_ON_ONCE(timer_pending(timer)); + WARN_ON_ONCE(!list_empty(&work->entry)); timer_stats_timer_set_start_info(&dwork->timer); @@ -1189,7 +1181,8 @@ EXPORT_SYMBOL_GPL(queue_delayed_work_on); */ static void worker_enter_idle(struct worker *worker) { - struct global_cwq *gcwq = worker->gcwq; + struct worker_pool *pool = worker->pool; + struct global_cwq *gcwq = pool->gcwq; BUG_ON(worker->flags & WORKER_IDLE); BUG_ON(!list_empty(&worker->entry) && @@ -1197,15 +1190,15 @@ static void worker_enter_idle(struct worker *worker) /* can't use worker_set_flags(), also called from start_worker() */ worker->flags |= WORKER_IDLE; - gcwq->nr_idle++; + pool->nr_idle++; worker->last_active = jiffies; /* idle_list is LIFO */ - list_add(&worker->entry, &gcwq->idle_list); + list_add(&worker->entry, &pool->idle_list); if (likely(!(worker->flags & WORKER_ROGUE))) { - if (too_many_workers(gcwq) && !timer_pending(&gcwq->idle_timer)) - mod_timer(&gcwq->idle_timer, + if (too_many_workers(pool) && !timer_pending(&pool->idle_timer)) + mod_timer(&pool->idle_timer, jiffies + IDLE_WORKER_TIMEOUT); } else wake_up_all(&gcwq->trustee_wait); @@ -1216,8 +1209,8 @@ static void worker_enter_idle(struct worker *worker) * warning may trigger spuriously. Check iff trustee is idle. */ WARN_ON_ONCE(gcwq->trustee_state == TRUSTEE_DONE && - gcwq->nr_workers == gcwq->nr_idle && - atomic_read(get_gcwq_nr_running(gcwq->cpu))); + pool->nr_workers == pool->nr_idle && + atomic_read(get_pool_nr_running(pool))); } /** @@ -1231,11 +1224,11 @@ static void worker_enter_idle(struct worker *worker) */ static void worker_leave_idle(struct worker *worker) { - struct global_cwq *gcwq = worker->gcwq; + struct worker_pool *pool = worker->pool; BUG_ON(!(worker->flags & WORKER_IDLE)); worker_clr_flags(worker, WORKER_IDLE); - gcwq->nr_idle--; + pool->nr_idle--; list_del_init(&worker->entry); } @@ -1272,7 +1265,7 @@ static void worker_leave_idle(struct worker *worker) static bool worker_maybe_bind_and_lock(struct worker *worker) __acquires(&gcwq->lock) { - struct global_cwq *gcwq = worker->gcwq; + struct global_cwq *gcwq = worker->pool->gcwq; struct task_struct *task = worker->task; while (true) { @@ -1314,7 +1307,7 @@ __acquires(&gcwq->lock) static void worker_rebind_fn(struct work_struct *work) { struct worker *worker = container_of(work, struct worker, rebind_work); - struct global_cwq *gcwq = worker->gcwq; + struct global_cwq *gcwq = worker->pool->gcwq; if (worker_maybe_bind_and_lock(worker)) worker_clr_flags(worker, WORKER_REBIND); @@ -1339,10 +1332,10 @@ static struct worker *alloc_worker(void) /** * create_worker - create a new workqueue worker - * @gcwq: gcwq the new worker will belong to + * @pool: pool the new worker will belong to * @bind: whether to set affinity to @cpu or not * - * Create a new worker which is bound to @gcwq. The returned worker + * Create a new worker which is bound to @pool. The returned worker * can be started by calling start_worker() or destroyed using * destroy_worker(). * @@ -1352,16 +1345,18 @@ static struct worker *alloc_worker(void) * RETURNS: * Pointer to the newly created worker. */ -static struct worker *create_worker(struct global_cwq *gcwq, bool bind) +static struct worker *create_worker(struct worker_pool *pool, bool bind) { + struct global_cwq *gcwq = pool->gcwq; bool on_unbound_cpu = gcwq->cpu == WORK_CPU_UNBOUND; + const char *pri = worker_pool_pri(pool) ? "H" : ""; struct worker *worker = NULL; int id = -1; spin_lock_irq(&gcwq->lock); - while (ida_get_new(&gcwq->worker_ida, &id)) { + while (ida_get_new(&pool->worker_ida, &id)) { spin_unlock_irq(&gcwq->lock); - if (!ida_pre_get(&gcwq->worker_ida, GFP_KERNEL)) + if (!ida_pre_get(&pool->worker_ida, GFP_KERNEL)) goto fail; spin_lock_irq(&gcwq->lock); } @@ -1371,20 +1366,22 @@ static struct worker *create_worker(struct global_cwq *gcwq, bool bind) if (!worker) goto fail; - worker->gcwq = gcwq; + worker->pool = pool; worker->id = id; if (!on_unbound_cpu) worker->task = kthread_create_on_node(worker_thread, - worker, - cpu_to_node(gcwq->cpu), - "kworker/%u:%d", gcwq->cpu, id); + worker, cpu_to_node(gcwq->cpu), + "kworker/%u:%d%s", gcwq->cpu, id, pri); else worker->task = kthread_create(worker_thread, worker, - "kworker/u:%d", id); + "kworker/u:%d%s", id, pri); if (IS_ERR(worker->task)) goto fail; + if (worker_pool_pri(pool)) + set_user_nice(worker->task, HIGHPRI_NICE_LEVEL); + /* * A rogue worker will become a regular one if CPU comes * online later on. Make sure every worker has @@ -1402,7 +1399,7 @@ static struct worker *create_worker(struct global_cwq *gcwq, bool bind) fail: if (id >= 0) { spin_lock_irq(&gcwq->lock); - ida_remove(&gcwq->worker_ida, id); + ida_remove(&pool->worker_ida, id); spin_unlock_irq(&gcwq->lock); } kfree(worker); @@ -1421,7 +1418,7 @@ static struct worker *create_worker(struct global_cwq *gcwq, bool bind) static void start_worker(struct worker *worker) { worker->flags |= WORKER_STARTED; - worker->gcwq->nr_workers++; + worker->pool->nr_workers++; worker_enter_idle(worker); wake_up_process(worker->task); } @@ -1437,7 +1434,8 @@ static void start_worker(struct worker *worker) */ static void destroy_worker(struct worker *worker) { - struct global_cwq *gcwq = worker->gcwq; + struct worker_pool *pool = worker->pool; + struct global_cwq *gcwq = pool->gcwq; int id = worker->id; /* sanity check frenzy */ @@ -1445,9 +1443,9 @@ static void destroy_worker(struct worker *worker) BUG_ON(!list_empty(&worker->scheduled)); if (worker->flags & WORKER_STARTED) - gcwq->nr_workers--; + pool->nr_workers--; if (worker->flags & WORKER_IDLE) - gcwq->nr_idle--; + pool->nr_idle--; list_del_init(&worker->entry); worker->flags |= WORKER_DIE; @@ -1458,29 +1456,30 @@ static void destroy_worker(struct worker *worker) kfree(worker); spin_lock_irq(&gcwq->lock); - ida_remove(&gcwq->worker_ida, id); + ida_remove(&pool->worker_ida, id); } -static void idle_worker_timeout(unsigned long __gcwq) +static void idle_worker_timeout(unsigned long __pool) { - struct global_cwq *gcwq = (void *)__gcwq; + struct worker_pool *pool = (void *)__pool; + struct global_cwq *gcwq = pool->gcwq; spin_lock_irq(&gcwq->lock); - if (too_many_workers(gcwq)) { + if (too_many_workers(pool)) { struct worker *worker; unsigned long expires; /* idle_list is kept in LIFO order, check the last one */ - worker = list_entry(gcwq->idle_list.prev, struct worker, entry); + worker = list_entry(pool->idle_list.prev, struct worker, entry); expires = worker->last_active + IDLE_WORKER_TIMEOUT; if (time_before(jiffies, expires)) - mod_timer(&gcwq->idle_timer, expires); + mod_timer(&pool->idle_timer, expires); else { /* it's been idle for too long, wake up manager */ - gcwq->flags |= GCWQ_MANAGE_WORKERS; - wake_up_worker(gcwq); + pool->flags |= POOL_MANAGE_WORKERS; + wake_up_worker(pool); } } @@ -1497,7 +1496,7 @@ static bool send_mayday(struct work_struct *work) return false; /* mayday mayday mayday */ - cpu = cwq->gcwq->cpu; + cpu = cwq->pool->gcwq->cpu; /* WORK_CPU_UNBOUND can't be set in cpumask, use cpu 0 instead */ if (cpu == WORK_CPU_UNBOUND) cpu = 0; @@ -1506,37 +1505,38 @@ static bool send_mayday(struct work_struct *work) return true; } -static void gcwq_mayday_timeout(unsigned long __gcwq) +static void gcwq_mayday_timeout(unsigned long __pool) { - struct global_cwq *gcwq = (void *)__gcwq; + struct worker_pool *pool = (void *)__pool; + struct global_cwq *gcwq = pool->gcwq; struct work_struct *work; spin_lock_irq(&gcwq->lock); - if (need_to_create_worker(gcwq)) { + if (need_to_create_worker(pool)) { /* * We've been trying to create a new worker but * haven't been successful. We might be hitting an * allocation deadlock. Send distress signals to * rescuers. */ - list_for_each_entry(work, &gcwq->worklist, entry) + list_for_each_entry(work, &pool->worklist, entry) send_mayday(work); } spin_unlock_irq(&gcwq->lock); - mod_timer(&gcwq->mayday_timer, jiffies + MAYDAY_INTERVAL); + mod_timer(&pool->mayday_timer, jiffies + MAYDAY_INTERVAL); } /** * maybe_create_worker - create a new worker if necessary - * @gcwq: gcwq to create a new worker for + * @pool: pool to create a new worker for * - * Create a new worker for @gcwq if necessary. @gcwq is guaranteed to + * Create a new worker for @pool if necessary. @pool is guaranteed to * have at least one idle worker on return from this function. If * creating a new worker takes longer than MAYDAY_INTERVAL, mayday is - * sent to all rescuers with works scheduled on @gcwq to resolve + * sent to all rescuers with works scheduled on @pool to resolve * possible allocation deadlock. * * On return, need_to_create_worker() is guaranteed to be false and @@ -1551,52 +1551,54 @@ static void gcwq_mayday_timeout(unsigned long __gcwq) * false if no action was taken and gcwq->lock stayed locked, true * otherwise. */ -static bool maybe_create_worker(struct global_cwq *gcwq) +static bool maybe_create_worker(struct worker_pool *pool) __releases(&gcwq->lock) __acquires(&gcwq->lock) { - if (!need_to_create_worker(gcwq)) + struct global_cwq *gcwq = pool->gcwq; + + if (!need_to_create_worker(pool)) return false; restart: spin_unlock_irq(&gcwq->lock); /* if we don't make progress in MAYDAY_INITIAL_TIMEOUT, call for help */ - mod_timer(&gcwq->mayday_timer, jiffies + MAYDAY_INITIAL_TIMEOUT); + mod_timer(&pool->mayday_timer, jiffies + MAYDAY_INITIAL_TIMEOUT); while (true) { struct worker *worker; - worker = create_worker(gcwq, true); + worker = create_worker(pool, true); if (worker) { - del_timer_sync(&gcwq->mayday_timer); + del_timer_sync(&pool->mayday_timer); spin_lock_irq(&gcwq->lock); start_worker(worker); - BUG_ON(need_to_create_worker(gcwq)); + BUG_ON(need_to_create_worker(pool)); return true; } - if (!need_to_create_worker(gcwq)) + if (!need_to_create_worker(pool)) break; __set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(CREATE_COOLDOWN); - if (!need_to_create_worker(gcwq)) + if (!need_to_create_worker(pool)) break; } - del_timer_sync(&gcwq->mayday_timer); + del_timer_sync(&pool->mayday_timer); spin_lock_irq(&gcwq->lock); - if (need_to_create_worker(gcwq)) + if (need_to_create_worker(pool)) goto restart; return true; } /** * maybe_destroy_worker - destroy workers which have been idle for a while - * @gcwq: gcwq to destroy workers for + * @pool: pool to destroy workers for * - * Destroy @gcwq workers which have been idle for longer than + * Destroy @pool workers which have been idle for longer than * IDLE_WORKER_TIMEOUT. * * LOCKING: @@ -1607,19 +1609,19 @@ __acquires(&gcwq->lock) * false if no action was taken and gcwq->lock stayed locked, true * otherwise. */ -static bool maybe_destroy_workers(struct global_cwq *gcwq) +static bool maybe_destroy_workers(struct worker_pool *pool) { bool ret = false; - while (too_many_workers(gcwq)) { + while (too_many_workers(pool)) { struct worker *worker; unsigned long expires; - worker = list_entry(gcwq->idle_list.prev, struct worker, entry); + worker = list_entry(pool->idle_list.prev, struct worker, entry); expires = worker->last_active + IDLE_WORKER_TIMEOUT; if (time_before(jiffies, expires)) { - mod_timer(&gcwq->idle_timer, expires); + mod_timer(&pool->idle_timer, expires); break; } @@ -1652,23 +1654,24 @@ static bool maybe_destroy_workers(struct global_cwq *gcwq) */ static bool manage_workers(struct worker *worker) { - struct global_cwq *gcwq = worker->gcwq; + struct worker_pool *pool = worker->pool; + struct global_cwq *gcwq = pool->gcwq; bool ret = false; - if (gcwq->flags & GCWQ_MANAGING_WORKERS) + if (pool->flags & POOL_MANAGING_WORKERS) return ret; - gcwq->flags &= ~GCWQ_MANAGE_WORKERS; - gcwq->flags |= GCWQ_MANAGING_WORKERS; + pool->flags &= ~POOL_MANAGE_WORKERS; + pool->flags |= POOL_MANAGING_WORKERS; /* * Destroy and then create so that may_start_working() is true * on return. */ - ret |= maybe_destroy_workers(gcwq); - ret |= maybe_create_worker(gcwq); + ret |= maybe_destroy_workers(pool); + ret |= maybe_create_worker(pool); - gcwq->flags &= ~GCWQ_MANAGING_WORKERS; + pool->flags &= ~POOL_MANAGING_WORKERS; /* * The trustee might be waiting to take over the manager @@ -1725,10 +1728,9 @@ static void cwq_activate_first_delayed(struct cpu_workqueue_struct *cwq) { struct work_struct *work = list_first_entry(&cwq->delayed_works, struct work_struct, entry); - struct list_head *pos = gcwq_determine_ins_pos(cwq->gcwq, cwq); trace_workqueue_activate_work(work); - move_linked_works(work, pos, NULL); + move_linked_works(work, &cwq->pool->worklist, NULL); __clear_bit(WORK_STRUCT_DELAYED_BIT, work_data_bits(work)); cwq->nr_active++; } @@ -1801,7 +1803,8 @@ __releases(&gcwq->lock) __acquires(&gcwq->lock) { struct cpu_workqueue_struct *cwq = get_work_cwq(work); - struct global_cwq *gcwq = cwq->gcwq; + struct worker_pool *pool = worker->pool; + struct global_cwq *gcwq = pool->gcwq; struct hlist_head *bwh = busy_worker_head(gcwq, work); bool cpu_intensive = cwq->wq->flags & WQ_CPU_INTENSIVE; work_func_t f = work->func; @@ -1840,21 +1843,6 @@ __acquires(&gcwq->lock) set_work_cpu(work, gcwq->cpu); list_del_init(&work->entry); - /* - * If HIGHPRI_PENDING, check the next work, and, if HIGHPRI, - * wake up another worker; otherwise, clear HIGHPRI_PENDING. - */ - if (unlikely(gcwq->flags & GCWQ_HIGHPRI_PENDING)) { - struct work_struct *nwork = list_first_entry(&gcwq->worklist, - struct work_struct, entry); - - if (!list_empty(&gcwq->worklist) && - get_work_cwq(nwork)->wq->flags & WQ_HIGHPRI) - wake_up_worker(gcwq); - else - gcwq->flags &= ~GCWQ_HIGHPRI_PENDING; - } - /* * CPU intensive works don't participate in concurrency * management. They're the scheduler's responsibility. @@ -1862,9 +1850,18 @@ __acquires(&gcwq->lock) if (unlikely(cpu_intensive)) worker_set_flags(worker, WORKER_CPU_INTENSIVE, true); + /* + * Unbound gcwq isn't concurrency managed and work items should be + * executed ASAP. Wake up another worker if necessary. + */ + if ((worker->flags & WORKER_UNBOUND) && need_more_worker(pool)) + wake_up_worker(pool); + spin_unlock_irq(&gcwq->lock); + smp_wmb(); /* paired with test_and_set_bit(PENDING) */ work_clear_pending(work); + lock_map_acquire_read(&cwq->wq->lockdep_map); lock_map_acquire(&lockdep_map); trace_workqueue_execute_start(work); @@ -1884,6 +1881,7 @@ __acquires(&gcwq->lock) printk(KERN_ERR " last function: "); print_symbol("%s\n", (unsigned long)f); debug_show_held_locks(current); + BUG_ON(PANIC_CORRUPTION); dump_stack(); } @@ -1934,7 +1932,8 @@ static void process_scheduled_works(struct worker *worker) static int worker_thread(void *__worker) { struct worker *worker = __worker; - struct global_cwq *gcwq = worker->gcwq; + struct worker_pool *pool = worker->pool; + struct global_cwq *gcwq = pool->gcwq; /* tell the scheduler that this is a workqueue worker */ worker->task->flags |= PF_WQ_WORKER; @@ -1951,11 +1950,11 @@ static int worker_thread(void *__worker) worker_leave_idle(worker); recheck: /* no more worker necessary? */ - if (!need_more_worker(gcwq)) + if (!need_more_worker(pool)) goto sleep; /* do we need to manage? */ - if (unlikely(!may_start_working(gcwq)) && manage_workers(worker)) + if (unlikely(!may_start_working(pool)) && manage_workers(worker)) goto recheck; /* @@ -1974,7 +1973,7 @@ static int worker_thread(void *__worker) do { struct work_struct *work = - list_first_entry(&gcwq->worklist, + list_first_entry(&pool->worklist, struct work_struct, entry); if (likely(!(*work_data_bits(work) & WORK_STRUCT_LINKED))) { @@ -1986,11 +1985,11 @@ static int worker_thread(void *__worker) move_linked_works(work, &worker->scheduled, NULL); process_scheduled_works(worker); } - } while (keep_working(gcwq)); + } while (keep_working(pool)); worker_set_flags(worker, WORKER_PREP, false); sleep: - if (unlikely(need_to_manage_workers(gcwq)) && manage_workers(worker)) + if (unlikely(need_to_manage_workers(pool)) && manage_workers(worker)) goto recheck; /* @@ -2038,8 +2037,10 @@ static int rescuer_thread(void *__wq) repeat: set_current_state(TASK_INTERRUPTIBLE); - if (kthread_should_stop()) + if (kthread_should_stop()) { + __set_current_state(TASK_RUNNING); return 0; + } /* * See whether any cpu is asking for help. Unbounded @@ -2048,14 +2049,15 @@ static int rescuer_thread(void *__wq) for_each_mayday_cpu(cpu, wq->mayday_mask) { unsigned int tcpu = is_unbound ? WORK_CPU_UNBOUND : cpu; struct cpu_workqueue_struct *cwq = get_cwq(tcpu, wq); - struct global_cwq *gcwq = cwq->gcwq; + struct worker_pool *pool = cwq->pool; + struct global_cwq *gcwq = pool->gcwq; struct work_struct *work, *n; __set_current_state(TASK_RUNNING); mayday_clear_cpu(cpu, wq->mayday_mask); /* migrate to the target cpu if possible */ - rescuer->gcwq = gcwq; + rescuer->pool = pool; worker_maybe_bind_and_lock(rescuer); /* @@ -2063,7 +2065,7 @@ static int rescuer_thread(void *__wq) * process'em. */ BUG_ON(!list_empty(&rescuer->scheduled)); - list_for_each_entry_safe(work, n, &gcwq->worklist, entry) + list_for_each_entry_safe(work, n, &pool->worklist, entry) if (get_work_cwq(work) == cwq) move_linked_works(work, scheduled, &n); @@ -2074,8 +2076,8 @@ static int rescuer_thread(void *__wq) * regular worker; otherwise, we end up with 0 concurrency * and stalling the execution. */ - if (keep_working(gcwq)) - wake_up_worker(gcwq); + if (keep_working(pool)) + wake_up_worker(pool); spin_unlock_irq(&gcwq->lock); } @@ -2200,7 +2202,7 @@ static bool flush_workqueue_prep_cwqs(struct workqueue_struct *wq, for_each_cwq_cpu(cpu, wq) { struct cpu_workqueue_struct *cwq = get_cwq(cpu, wq); - struct global_cwq *gcwq = cwq->gcwq; + struct global_cwq *gcwq = cwq->pool->gcwq; spin_lock_irq(&gcwq->lock); @@ -2416,9 +2418,9 @@ void drain_workqueue(struct workqueue_struct *wq) struct cpu_workqueue_struct *cwq = get_cwq(cpu, wq); bool drained; - spin_lock_irq(&cwq->gcwq->lock); + spin_lock_irq(&cwq->pool->gcwq->lock); drained = !cwq->nr_active && list_empty(&cwq->delayed_works); - spin_unlock_irq(&cwq->gcwq->lock); + spin_unlock_irq(&cwq->pool->gcwq->lock); if (drained) continue; @@ -2458,7 +2460,7 @@ static bool start_flush_work(struct work_struct *work, struct wq_barrier *barr, */ smp_rmb(); cwq = get_work_cwq(work); - if (unlikely(!cwq || gcwq != cwq->gcwq)) + if (unlikely(!cwq || gcwq != cwq->pool->gcwq)) goto already_gone; } else if (wait_executing) { worker = find_worker_executing_work(gcwq, work); @@ -2976,13 +2978,6 @@ struct workqueue_struct *__alloc_workqueue_key(const char *fmt, if (flags & WQ_MEM_RECLAIM) flags |= WQ_RESCUER; - /* - * Unbound workqueues aren't concurrency managed and should be - * dispatched to workers immediately. - */ - if (flags & WQ_UNBOUND) - flags |= WQ_HIGHPRI; - max_active = max_active ?: WQ_DFL_ACTIVE; max_active = wq_clamp_max_active(max_active, flags, wq->name); @@ -3003,9 +2998,10 @@ struct workqueue_struct *__alloc_workqueue_key(const char *fmt, for_each_cwq_cpu(cpu, wq) { struct cpu_workqueue_struct *cwq = get_cwq(cpu, wq); struct global_cwq *gcwq = get_gcwq(cpu); + int pool_idx = (bool)(flags & WQ_HIGHPRI); BUG_ON((unsigned long)cwq & WORK_STRUCT_FLAG_MASK); - cwq->gcwq = gcwq; + cwq->pool = &gcwq->pools[pool_idx]; cwq->wq = wq; cwq->flush_color = -1; cwq->max_active = max_active; @@ -3309,9 +3305,30 @@ EXPORT_SYMBOL_GPL(work_busy); __ret1 < 0 ? -1 : 0; \ }) +static bool gcwq_is_managing_workers(struct global_cwq *gcwq) +{ + struct worker_pool *pool; + + for_each_worker_pool(pool, gcwq) + if (pool->flags & POOL_MANAGING_WORKERS) + return true; + return false; +} + +static bool gcwq_has_idle_workers(struct global_cwq *gcwq) +{ + struct worker_pool *pool; + + for_each_worker_pool(pool, gcwq) + if (!list_empty(&pool->idle_list)) + return true; + return false; +} + static int trustee_thread(void *__gcwq) { struct global_cwq *gcwq = __gcwq; + struct worker_pool *pool; struct worker *worker; struct work_struct *work; struct hlist_node *pos; @@ -3327,13 +3344,15 @@ static int trustee_thread(void *__gcwq) * cancelled. */ BUG_ON(gcwq->cpu != smp_processor_id()); - rc = trustee_wait_event(!(gcwq->flags & GCWQ_MANAGING_WORKERS)); + rc = trustee_wait_event(!gcwq_is_managing_workers(gcwq)); BUG_ON(rc < 0); - gcwq->flags |= GCWQ_MANAGING_WORKERS; + for_each_worker_pool(pool, gcwq) { + pool->flags |= POOL_MANAGING_WORKERS; - list_for_each_entry(worker, &gcwq->idle_list, entry) - worker->flags |= WORKER_ROGUE; + list_for_each_entry(worker, &pool->idle_list, entry) + worker->flags |= WORKER_ROGUE; + } for_each_busy_worker(worker, i, pos, gcwq) worker->flags |= WORKER_ROGUE; @@ -3354,10 +3373,12 @@ static int trustee_thread(void *__gcwq) * keep_working() are always true as long as the worklist is * not empty. */ - atomic_set(get_gcwq_nr_running(gcwq->cpu), 0); + for_each_worker_pool(pool, gcwq) + atomic_set(get_pool_nr_running(pool), 0); spin_unlock_irq(&gcwq->lock); - del_timer_sync(&gcwq->idle_timer); + for_each_worker_pool(pool, gcwq) + del_timer_sync(&pool->idle_timer); spin_lock_irq(&gcwq->lock); /* @@ -3379,29 +3400,38 @@ static int trustee_thread(void *__gcwq) * may be frozen works in freezable cwqs. Don't declare * completion while frozen. */ - while (gcwq->nr_workers != gcwq->nr_idle || - gcwq->flags & GCWQ_FREEZING || - gcwq->trustee_state == TRUSTEE_IN_CHARGE) { - int nr_works = 0; + while (true) { + bool busy = false; - list_for_each_entry(work, &gcwq->worklist, entry) { - send_mayday(work); - nr_works++; - } + for_each_worker_pool(pool, gcwq) + busy |= pool->nr_workers != pool->nr_idle; - list_for_each_entry(worker, &gcwq->idle_list, entry) { - if (!nr_works--) - break; - wake_up_process(worker->task); - } + if (!busy && !(gcwq->flags & GCWQ_FREEZING) && + gcwq->trustee_state != TRUSTEE_IN_CHARGE) + break; - if (need_to_create_worker(gcwq)) { - spin_unlock_irq(&gcwq->lock); - worker = create_worker(gcwq, false); - spin_lock_irq(&gcwq->lock); - if (worker) { - worker->flags |= WORKER_ROGUE; - start_worker(worker); + for_each_worker_pool(pool, gcwq) { + int nr_works = 0; + + list_for_each_entry(work, &pool->worklist, entry) { + send_mayday(work); + nr_works++; + } + + list_for_each_entry(worker, &pool->idle_list, entry) { + if (!nr_works--) + break; + wake_up_process(worker->task); + } + + if (need_to_create_worker(pool)) { + spin_unlock_irq(&gcwq->lock); + worker = create_worker(pool, false); + spin_lock_irq(&gcwq->lock); + if (worker) { + worker->flags |= WORKER_ROGUE; + start_worker(worker); + } } } @@ -3416,11 +3446,18 @@ static int trustee_thread(void *__gcwq) * all workers till we're canceled. */ do { - rc = trustee_wait_event(!list_empty(&gcwq->idle_list)); - while (!list_empty(&gcwq->idle_list)) - destroy_worker(list_first_entry(&gcwq->idle_list, - struct worker, entry)); - } while (gcwq->nr_workers && rc >= 0); + rc = trustee_wait_event(gcwq_has_idle_workers(gcwq)); + + i = 0; + for_each_worker_pool(pool, gcwq) { + while (!list_empty(&pool->idle_list)) { + worker = list_first_entry(&pool->idle_list, + struct worker, entry); + destroy_worker(worker); + } + i |= pool->nr_workers; + } + } while (i && rc >= 0); /* * At this point, either draining has completed and no worker @@ -3429,18 +3466,22 @@ static int trustee_thread(void *__gcwq) * Tell the remaining busy ones to rebind once it finishes the * currently scheduled works by scheduling the rebind_work. */ - WARN_ON(!list_empty(&gcwq->idle_list)); + for_each_worker_pool(pool, gcwq) + WARN_ON(!list_empty(&pool->idle_list)); for_each_busy_worker(worker, i, pos, gcwq) { struct work_struct *rebind_work = &worker->rebind_work; + unsigned long worker_flags = worker->flags; /* * Rebind_work may race with future cpu hotplug * operations. Use a separate flag to mark that - * rebinding is scheduled. + * rebinding is scheduled. The morphing should + * be atomic. */ - worker->flags |= WORKER_REBIND; - worker->flags &= ~WORKER_ROGUE; + worker_flags |= WORKER_REBIND; + worker_flags &= ~WORKER_ROGUE; + ACCESS_ONCE(worker->flags) = worker_flags; /* queue rebind_work, wq doesn't matter, use the default one */ if (test_and_set_bit(WORK_STRUCT_PENDING_BIT, @@ -3454,7 +3495,8 @@ static int trustee_thread(void *__gcwq) } /* relinquish manager role */ - gcwq->flags &= ~GCWQ_MANAGING_WORKERS; + for_each_worker_pool(pool, gcwq) + pool->flags &= ~POOL_MANAGING_WORKERS; /* notify completion */ gcwq->trustee = NULL; @@ -3496,8 +3538,10 @@ static int workqueue_cpu_callback(struct notifier_block *nfb, unsigned int cpu = (unsigned long)hcpu; struct global_cwq *gcwq = get_gcwq(cpu); struct task_struct *new_trustee = NULL; - struct worker *uninitialized_var(new_worker); + struct worker *new_workers[NR_WORKER_POOLS] = { }; + struct worker_pool *pool; unsigned long flags; + int i; action &= ~CPU_TASKS_FROZEN; @@ -3510,12 +3554,12 @@ static int workqueue_cpu_callback(struct notifier_block *nfb, kthread_bind(new_trustee, cpu); /* fall through */ case CPU_UP_PREPARE: - BUG_ON(gcwq->first_idle); - new_worker = create_worker(gcwq, false); - if (!new_worker) { - if (new_trustee) - kthread_stop(new_trustee); - return NOTIFY_BAD; + i = 0; + for_each_worker_pool(pool, gcwq) { + BUG_ON(pool->first_idle); + new_workers[i] = create_worker(pool, false); + if (!new_workers[i++]) + goto err_destroy; } } @@ -3532,8 +3576,11 @@ static int workqueue_cpu_callback(struct notifier_block *nfb, wait_trustee_state(gcwq, TRUSTEE_IN_CHARGE); /* fall through */ case CPU_UP_PREPARE: - BUG_ON(gcwq->first_idle); - gcwq->first_idle = new_worker; + i = 0; + for_each_worker_pool(pool, gcwq) { + BUG_ON(pool->first_idle); + pool->first_idle = new_workers[i++]; + } break; case CPU_DYING: @@ -3550,8 +3597,10 @@ static int workqueue_cpu_callback(struct notifier_block *nfb, gcwq->trustee_state = TRUSTEE_BUTCHER; /* fall through */ case CPU_UP_CANCELED: - destroy_worker(gcwq->first_idle); - gcwq->first_idle = NULL; + for_each_worker_pool(pool, gcwq) { + destroy_worker(pool->first_idle); + pool->first_idle = NULL; + } break; case CPU_DOWN_FAILED: @@ -3568,35 +3617,83 @@ static int workqueue_cpu_callback(struct notifier_block *nfb, * Put the first_idle in and request a real manager to * take a look. */ - spin_unlock_irq(&gcwq->lock); - kthread_bind(gcwq->first_idle->task, cpu); - spin_lock_irq(&gcwq->lock); - gcwq->flags |= GCWQ_MANAGE_WORKERS; - start_worker(gcwq->first_idle); - gcwq->first_idle = NULL; + for_each_worker_pool(pool, gcwq) { + spin_unlock_irq(&gcwq->lock); + kthread_bind(pool->first_idle->task, cpu); + spin_lock_irq(&gcwq->lock); + pool->flags |= POOL_MANAGE_WORKERS; + start_worker(pool->first_idle); + pool->first_idle = NULL; + } break; } spin_unlock_irqrestore(&gcwq->lock, flags); return notifier_from_errno(0); + +err_destroy: + if (new_trustee) + kthread_stop(new_trustee); + + spin_lock_irqsave(&gcwq->lock, flags); + for (i = 0; i < NR_WORKER_POOLS; i++) + if (new_workers[i]) + destroy_worker(new_workers[i]); + spin_unlock_irqrestore(&gcwq->lock, flags); + + return NOTIFY_BAD; +} + +/* + * Workqueues should be brought up before normal priority CPU notifiers. + * This will be registered high priority CPU notifier. + */ +static int __devinit workqueue_cpu_up_callback(struct notifier_block *nfb, + unsigned long action, + void *hcpu) +{ + switch (action & ~CPU_TASKS_FROZEN) { + case CPU_UP_PREPARE: + case CPU_UP_CANCELED: + case CPU_DOWN_FAILED: + case CPU_ONLINE: + return workqueue_cpu_callback(nfb, action, hcpu); + } + return NOTIFY_OK; +} + +/* + * Workqueues should be brought down after normal priority CPU notifiers. + * This will be registered as low priority CPU notifier. + */ +static int __devinit workqueue_cpu_down_callback(struct notifier_block *nfb, + unsigned long action, + void *hcpu) +{ + switch (action & ~CPU_TASKS_FROZEN) { + case CPU_DOWN_PREPARE: + case CPU_DYING: + case CPU_POST_DEAD: + return workqueue_cpu_callback(nfb, action, hcpu); + } + return NOTIFY_OK; } #ifdef CONFIG_SMP struct work_for_cpu { - struct completion completion; + struct work_struct work; long (*fn)(void *); void *arg; long ret; }; -static int do_work_for_cpu(void *_wfc) +static void work_for_cpu_fn(struct work_struct *work) { - struct work_for_cpu *wfc = _wfc; + struct work_for_cpu *wfc = container_of(work, struct work_for_cpu, work); + wfc->ret = wfc->fn(wfc->arg); - complete(&wfc->completion); - return 0; } /** @@ -3611,19 +3708,11 @@ static int do_work_for_cpu(void *_wfc) */ long work_on_cpu(unsigned int cpu, long (*fn)(void *), void *arg) { - struct task_struct *sub_thread; - struct work_for_cpu wfc = { - .completion = COMPLETION_INITIALIZER_ONSTACK(wfc.completion), - .fn = fn, - .arg = arg, - }; + struct work_for_cpu wfc = { .fn = fn, .arg = arg }; - sub_thread = kthread_create(do_work_for_cpu, &wfc, "work_for_cpu"); - if (IS_ERR(sub_thread)) - return PTR_ERR(sub_thread); - kthread_bind(sub_thread, cpu); - wake_up_process(sub_thread); - wait_for_completion(&wfc.completion); + INIT_WORK_ONSTACK(&wfc.work, work_for_cpu_fn); + schedule_work_on(cpu, &wfc.work); + flush_work(&wfc.work); return wfc.ret; } EXPORT_SYMBOL_GPL(work_on_cpu); @@ -3748,6 +3837,7 @@ void thaw_workqueues(void) for_each_gcwq_cpu(cpu) { struct global_cwq *gcwq = get_gcwq(cpu); + struct worker_pool *pool; struct workqueue_struct *wq; spin_lock_irq(&gcwq->lock); @@ -3769,7 +3859,8 @@ void thaw_workqueues(void) cwq_activate_first_delayed(cwq); } - wake_up_worker(gcwq); + for_each_worker_pool(pool, gcwq) + wake_up_worker(pool); spin_unlock_irq(&gcwq->lock); } @@ -3785,29 +3876,35 @@ static int __init init_workqueues(void) unsigned int cpu; int i; - cpu_notifier(workqueue_cpu_callback, CPU_PRI_WORKQUEUE); + cpu_notifier(workqueue_cpu_up_callback, CPU_PRI_WORKQUEUE_UP); + cpu_notifier(workqueue_cpu_down_callback, CPU_PRI_WORKQUEUE_DOWN); /* initialize gcwqs */ for_each_gcwq_cpu(cpu) { struct global_cwq *gcwq = get_gcwq(cpu); + struct worker_pool *pool; spin_lock_init(&gcwq->lock); - INIT_LIST_HEAD(&gcwq->worklist); gcwq->cpu = cpu; gcwq->flags |= GCWQ_DISASSOCIATED; - INIT_LIST_HEAD(&gcwq->idle_list); for (i = 0; i < BUSY_WORKER_HASH_SIZE; i++) INIT_HLIST_HEAD(&gcwq->busy_hash[i]); - init_timer_deferrable(&gcwq->idle_timer); - gcwq->idle_timer.function = idle_worker_timeout; - gcwq->idle_timer.data = (unsigned long)gcwq; + for_each_worker_pool(pool, gcwq) { + pool->gcwq = gcwq; + INIT_LIST_HEAD(&pool->worklist); + INIT_LIST_HEAD(&pool->idle_list); + + init_timer_deferrable(&pool->idle_timer); + pool->idle_timer.function = idle_worker_timeout; + pool->idle_timer.data = (unsigned long)pool; - setup_timer(&gcwq->mayday_timer, gcwq_mayday_timeout, - (unsigned long)gcwq); + setup_timer(&pool->mayday_timer, gcwq_mayday_timeout, + (unsigned long)pool); - ida_init(&gcwq->worker_ida); + ida_init(&pool->worker_ida); + } gcwq->trustee_state = TRUSTEE_DONE; init_waitqueue_head(&gcwq->trustee_wait); @@ -3816,15 +3913,20 @@ static int __init init_workqueues(void) /* create the initial worker */ for_each_online_gcwq_cpu(cpu) { struct global_cwq *gcwq = get_gcwq(cpu); - struct worker *worker; + struct worker_pool *pool; if (cpu != WORK_CPU_UNBOUND) gcwq->flags &= ~GCWQ_DISASSOCIATED; - worker = create_worker(gcwq, true); - BUG_ON(!worker); - spin_lock_irq(&gcwq->lock); - start_worker(worker); - spin_unlock_irq(&gcwq->lock); + + for_each_worker_pool(pool, gcwq) { + struct worker *worker; + + worker = create_worker(pool, true); + BUG_ON(!worker); + spin_lock_irq(&gcwq->lock); + start_worker(worker); + spin_unlock_irq(&gcwq->lock); + } } system_wq = alloc_workqueue("events", 0, 0); diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 097d70fa02d..b9060a1250c 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -1290,6 +1290,13 @@ config ASYNC_RAID6_TEST If unsure, say N. +config PANIC_ON_DATA_CORRUPTION + bool "Cause a Kernel Panic When Data Corruption is detected" + help + Select this option to upgrade warnings for potentially + recoverable data corruption scenarios to system-halting panics, + for easier detection and debug. + source "samples/Kconfig" source "lib/Kconfig.kgdb" diff --git a/lib/atomic64.c b/lib/atomic64.c index 978537809d8..08a4f068e61 100644 --- a/lib/atomic64.c +++ b/lib/atomic64.c @@ -31,7 +31,11 @@ static union { raw_spinlock_t lock; char pad[L1_CACHE_BYTES]; -} atomic64_lock[NR_LOCKS] __cacheline_aligned_in_smp; +} atomic64_lock[NR_LOCKS] __cacheline_aligned_in_smp = { + [0 ... (NR_LOCKS - 1)] = { + .lock = __RAW_SPIN_LOCK_UNLOCKED(atomic64_lock.lock), + }, +}; static inline raw_spinlock_t *lock_addr(const atomic64_t *v) { @@ -173,14 +177,3 @@ int atomic64_add_unless(atomic64_t *v, long long a, long long u) return ret; } EXPORT_SYMBOL(atomic64_add_unless); - -static int init_atomic64_lock(void) -{ - int i; - - for (i = 0; i < NR_LOCKS; ++i) - raw_spin_lock_init(&atomic64_lock[i].lock); - return 0; -} - -pure_initcall(init_atomic64_lock); diff --git a/lib/digsig.c b/lib/digsig.c index 286d558033e..dc2be7ed176 100644 --- a/lib/digsig.c +++ b/lib/digsig.c @@ -162,10 +162,14 @@ static int digsig_verify_rsa(struct key *key, memset(out1, 0, head); memcpy(out1 + head, p, l); + kfree(p); + err = pkcs_1_v1_5_decode_emsa(out1, len, mblen, out2, &len); + if (err) + goto err; - if (!err && len == hlen) - err = memcmp(out2, h, hlen); + if (len != hlen || memcmp(out2, h, hlen)) + err = -EINVAL; err: mpi_free(in); diff --git a/lib/gcd.c b/lib/gcd.c index cce4f3cd14b..3657f129d7b 100644 --- a/lib/gcd.c +++ b/lib/gcd.c @@ -9,6 +9,9 @@ unsigned long gcd(unsigned long a, unsigned long b) if (a < b) swap(a, b); + + if (!b) + return a; while ((r = a % b) != 0) { a = b; b = r; diff --git a/lib/genalloc.c b/lib/genalloc.c index 9cf1b8b51ac..920d250e410 100644 --- a/lib/genalloc.c +++ b/lib/genalloc.c @@ -177,7 +177,7 @@ int gen_pool_add_virt(struct gen_pool *pool, unsigned long virt, phys_addr_t phy struct gen_pool_chunk *chunk; int nbits = size >> pool->min_alloc_order; int nbytes = sizeof(struct gen_pool_chunk) + - (nbits + BITS_PER_BYTE - 1) / BITS_PER_BYTE; + BITS_TO_LONGS(nbits) * sizeof(long); if (nbytes <= PAGE_SIZE) chunk = kmalloc_node(nbytes, __GFP_ZERO, nid); diff --git a/lib/list_debug.c b/lib/list_debug.c index 982b850d4e7..6a039a62841 100644 --- a/lib/list_debug.c +++ b/lib/list_debug.c @@ -10,6 +10,7 @@ #include #include #include +#include /* * Insert a new entry between two known consecutive entries. @@ -30,6 +31,10 @@ void __list_add(struct list_head *new, "list_add corruption. prev->next should be " "next (%p), but was %p. (prev=%p).\n", next, prev->next, prev); + + BUG_ON(((prev->next != next) || (next->prev != prev)) && + PANIC_CORRUPTION); + next->prev = new; new->next = next; new->prev = prev; @@ -55,8 +60,10 @@ void __list_del_entry(struct list_head *entry) "but was %p\n", entry, prev->next) || WARN(next->prev != entry, "list_del corruption. next->prev should be %p, " - "but was %p\n", entry, next->prev)) + "but was %p\n", entry, next->prev)) { + BUG_ON(PANIC_CORRUPTION); return; + } __list_del(prev, next); } diff --git a/lib/mpi/longlong.h b/lib/mpi/longlong.h index 29f98624ef9..280405b47e7 100644 --- a/lib/mpi/longlong.h +++ b/lib/mpi/longlong.h @@ -703,7 +703,14 @@ do { \ ************** MIPS ***************** ***************************************/ #if defined(__mips__) && W_TYPE_SIZE == 32 -#if __GNUC__ > 2 || __GNUC_MINOR__ >= 7 +#if __GNUC__ >= 4 && __GNUC_MINOR__ >= 4 +#define umul_ppmm(w1, w0, u, v) \ +do { \ + UDItype __ll = (UDItype)(u) * (v); \ + w1 = __ll >> 32; \ + w0 = __ll; \ +} while (0) +#elif __GNUC__ > 2 || __GNUC_MINOR__ >= 7 #define umul_ppmm(w1, w0, u, v) \ __asm__ ("multu %2,%3" \ : "=l" ((USItype)(w0)), \ @@ -728,7 +735,15 @@ do { \ ************** MIPS/64 ************** ***************************************/ #if (defined(__mips) && __mips >= 3) && W_TYPE_SIZE == 64 -#if __GNUC__ > 2 || __GNUC_MINOR__ >= 7 +#if __GNUC__ >= 4 && __GNUC_MINOR__ >= 4 +#define umul_ppmm(w1, w0, u, v) \ +do { \ + typedef unsigned int __ll_UTItype __attribute__((mode(TI))); \ + __ll_UTItype __ll = (__ll_UTItype)(u) * (v); \ + w1 = __ll >> 64; \ + w0 = __ll; \ +} while (0) +#elif __GNUC__ > 2 || __GNUC_MINOR__ >= 7 #define umul_ppmm(w1, w0, u, v) \ __asm__ ("dmultu %2,%3" \ : "=l" ((UDItype)(w0)), \ diff --git a/lib/spinlock_debug.c b/lib/spinlock_debug.c index 1967297aee8..d8cb54489e9 100644 --- a/lib/spinlock_debug.c +++ b/lib/spinlock_debug.c @@ -12,6 +12,7 @@ #include #include #include +#include void __raw_spin_lock_init(raw_spinlock_t *lock, const char *name, struct lock_class_key *key) @@ -64,6 +65,7 @@ static void spin_dump(raw_spinlock_t *lock, const char *msg) owner ? owner->comm : "", owner ? task_pid_nr(owner) : -1, lock->owner_cpu); + BUG_ON(PANIC_CORRUPTION); dump_stack(); } diff --git a/mm/bootmem.c b/mm/bootmem.c index 0131170c9d5..53cf62b186b 100644 --- a/mm/bootmem.c +++ b/mm/bootmem.c @@ -766,13 +766,17 @@ void * __init alloc_bootmem_section(unsigned long size, unsigned long section_nr) { bootmem_data_t *bdata; - unsigned long pfn, goal; + unsigned long pfn, goal, limit; pfn = section_nr_to_pfn(section_nr); goal = pfn << PAGE_SHIFT; + limit = section_nr_to_pfn(section_nr + 1) << PAGE_SHIFT; bdata = &bootmem_node_data[early_pfn_to_nid(pfn)]; - return alloc_bootmem_core(bdata, size, SMP_CACHE_BYTES, goal, 0); + if (goal + size > limit) + limit = 0; + + return alloc_bootmem_core(bdata, size, SMP_CACHE_BYTES, goal, limit); } #endif diff --git a/mm/compaction.c b/mm/compaction.c index 260a4870253..d6ae4dd8f2f 100644 --- a/mm/compaction.c +++ b/mm/compaction.c @@ -846,7 +846,7 @@ static int compact_node(int nid) } /* Compact all nodes in the system */ -static int compact_nodes(void) +static void compact_nodes(void) { int nid; @@ -855,8 +855,6 @@ static int compact_nodes(void) for_each_online_node(nid) compact_node(nid); - - return COMPACT_COMPLETE; } /* The written value is actually unused, all memory is compacted */ @@ -867,7 +865,7 @@ int sysctl_compaction_handler(struct ctl_table *table, int write, void __user *buffer, size_t *length, loff_t *ppos) { if (write) - return compact_nodes(); + compact_nodes(); return 0; } diff --git a/mm/huge_memory.c b/mm/huge_memory.c index f0e5306eeb5..caf15b6fa75 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -950,6 +950,8 @@ int do_huge_pmd_wp_page(struct mm_struct *mm, struct vm_area_struct *vma, count_vm_event(THP_FAULT_FALLBACK); ret = do_huge_pmd_wp_page_fallback(mm, vma, address, pmd, orig_pmd, page, haddr); + if (ret & VM_FAULT_OOM) + split_huge_page(page); put_page(page); goto out; } @@ -957,6 +959,7 @@ int do_huge_pmd_wp_page(struct mm_struct *mm, struct vm_area_struct *vma, if (unlikely(mem_cgroup_newpage_charge(new_page, mm, GFP_KERNEL))) { put_page(new_page); + split_huge_page(page); put_page(page); ret |= VM_FAULT_OOM; goto out; diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 263e17703b3..c384e0901f9 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -2392,6 +2392,22 @@ void unmap_hugepage_range(struct vm_area_struct *vma, unsigned long start, { mutex_lock(&vma->vm_file->f_mapping->i_mmap_mutex); __unmap_hugepage_range(vma, start, end, ref_page); + /* + * Clear this flag so that x86's huge_pmd_share page_table_shareable + * test will fail on a vma being torn down, and not grab a page table + * on its way out. We're lucky that the flag has such an appropriate + * name, and can in fact be safely cleared here. We could clear it + * before the __unmap_hugepage_range above, but all that's necessary + * is to clear it before releasing the i_mmap_mutex below. + * + * This works because in the contexts this is called, the VMA is + * going to be destroyed. It is not vunerable to madvise(DONTNEED) + * because madvise is not supported on hugetlbfs. The same applies + * for direct IO. unmap_hugepage_range() is only being called just + * before free_pgtables() so clearing VM_MAYSHARE will not cause + * surprises later. + */ + vma->vm_flags &= ~VM_MAYSHARE; mutex_unlock(&vma->vm_file->f_mapping->i_mmap_mutex); } @@ -2415,7 +2431,8 @@ static int unmap_ref_private(struct mm_struct *mm, struct vm_area_struct *vma, * from page cache lookup which is in HPAGE_SIZE units. */ address = address & huge_page_mask(h); - pgoff = vma_hugecache_offset(h, vma, address); + pgoff = ((address - vma->vm_start) >> PAGE_SHIFT) + + vma->vm_pgoff; mapping = vma->vm_file->f_dentry->d_inode->i_mapping; /* @@ -2958,9 +2975,14 @@ void hugetlb_change_protection(struct vm_area_struct *vma, } } spin_unlock(&mm->page_table_lock); - mutex_unlock(&vma->vm_file->f_mapping->i_mmap_mutex); - + /* + * Must flush TLB before releasing i_mmap_mutex: x86's huge_pmd_unshare + * may have cleared our pud entry and done put_page on the page table: + * once we release i_mmap_mutex, another task can do the final put_page + * and that page table be reused and filled with junk. + */ flush_tlb_range(vma, start, end); + mutex_unlock(&vma->vm_file->f_mapping->i_mmap_mutex); } int hugetlb_reserve_pages(struct inode *inode, diff --git a/mm/memblock.c b/mm/memblock.c index 85ba00a52d4..b9427fe7e41 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -914,6 +914,30 @@ int __init_memblock memblock_is_region_reserved(phys_addr_t base, phys_addr_t si return memblock_overlaps_region(&memblock.reserved, base, size) >= 0; } +void __init_memblock memblock_trim_memory(phys_addr_t align) +{ + int i; + phys_addr_t start, end, orig_start, orig_end; + struct memblock_type *mem = &memblock.memory; + + for (i = 0; i < mem->cnt; i++) { + orig_start = mem->regions[i].base; + orig_end = mem->regions[i].base + mem->regions[i].size; + start = round_up(orig_start, align); + end = round_down(orig_end, align); + + if (start == orig_start && end == orig_end) + continue; + + if (start < end) { + mem->regions[i].base = start; + mem->regions[i].size = end - start; + } else { + memblock_remove_region(mem, i); + i--; + } + } +} void __init_memblock memblock_set_current_limit(phys_addr_t limit) { diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 33a177ae444..ba1a0339f52 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -1489,17 +1489,26 @@ static int mem_cgroup_count_children(struct mem_cgroup *memcg) u64 mem_cgroup_get_limit(struct mem_cgroup *memcg) { u64 limit; - u64 memsw; limit = res_counter_read_u64(&memcg->res, RES_LIMIT); - limit += total_swap_pages << PAGE_SHIFT; - memsw = res_counter_read_u64(&memcg->memsw, RES_LIMIT); /* - * If memsw is finite and limits the amount of swap space available - * to this memcg, return that limit. + * Do not consider swap space if we cannot swap due to swappiness */ - return min(limit, memsw); + if (mem_cgroup_swappiness(memcg)) { + u64 memsw; + + limit += total_swap_pages << PAGE_SHIFT; + memsw = res_counter_read_u64(&memcg->memsw, RES_LIMIT); + + /* + * If memsw is finite and limits the amount of swap space + * available to this memcg, return that limit. + */ + limit = min(limit, memsw); + } + + return limit; } static unsigned long mem_cgroup_reclaim(struct mem_cgroup *memcg, diff --git a/mm/memory-failure.c b/mm/memory-failure.c index c99ad4e6b88..b68c8f66e4d 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c @@ -345,14 +345,14 @@ static void add_to_kill(struct task_struct *tsk, struct page *p, * Also when FAIL is set do a force kill because something went * wrong earlier. */ -static void kill_procs(struct list_head *to_kill, int doit, int trapno, +static void kill_procs(struct list_head *to_kill, int forcekill, int trapno, int fail, struct page *page, unsigned long pfn, int flags) { struct to_kill *tk, *next; list_for_each_entry_safe (tk, next, to_kill, nd) { - if (doit) { + if (forcekill) { /* * In case something went wrong with munmapping * make sure the process doesn't catch the @@ -858,7 +858,7 @@ static int hwpoison_user_mappings(struct page *p, unsigned long pfn, struct address_space *mapping; LIST_HEAD(tokill); int ret; - int kill = 1; + int kill = 1, forcekill; struct page *hpage = compound_head(p); struct page *ppage; @@ -888,7 +888,7 @@ static int hwpoison_user_mappings(struct page *p, unsigned long pfn, * be called inside page lock (it's recommended but not enforced). */ mapping = page_mapping(hpage); - if (!PageDirty(hpage) && mapping && + if (!(flags & MF_MUST_KILL) && !PageDirty(hpage) && mapping && mapping_cap_writeback_dirty(mapping)) { if (page_mkclean(hpage)) { SetPageDirty(hpage); @@ -965,12 +965,14 @@ static int hwpoison_user_mappings(struct page *p, unsigned long pfn, * Now that the dirty bit has been propagated to the * struct page and all unmaps done we can decide if * killing is needed or not. Only kill when the page - * was dirty, otherwise the tokill list is merely + * was dirty or the process is not restartable, + * otherwise the tokill list is merely * freed. When there was a problem unmapping earlier * use a more force-full uncatchable kill to prevent * any accesses to the poisoned memory. */ - kill_procs(&tokill, !!PageDirty(ppage), trapno, + forcekill = PageDirty(ppage) || (flags & MF_MUST_KILL); + kill_procs(&tokill, forcekill, trapno, ret != SWAP_SUCCESS, p, pfn, flags); return ret; @@ -1431,8 +1433,8 @@ static int soft_offline_huge_page(struct page *page, int flags) /* Keep page count to indicate a given hugepage is isolated. */ list_add(&hpage->lru, &pagelist); - ret = migrate_huge_pages(&pagelist, new_page, MPOL_MF_MOVE_ALL, 0, - true); + ret = migrate_huge_pages(&pagelist, new_page, MPOL_MF_MOVE_ALL, false, + MIGRATE_SYNC); if (ret) { struct page *page1, *page2; list_for_each_entry_safe(page1, page2, &pagelist, lru) @@ -1479,9 +1481,17 @@ int soft_offline_page(struct page *page, int flags) { int ret; unsigned long pfn = page_to_pfn(page); + struct page *hpage = compound_trans_head(page); if (PageHuge(page)) return soft_offline_huge_page(page, flags); + if (PageTransHuge(hpage)) { + if (PageAnon(hpage) && unlikely(split_huge_page(hpage))) { + pr_info("soft offline: %#lx: failed to split THP\n", + pfn); + return -EBUSY; + } + } ret = get_any_page(page, pfn, flags); if (ret < 0) @@ -1561,7 +1571,7 @@ int soft_offline_page(struct page *page, int flags) page_is_file_cache(page)); list_add(&page->lru, &pagelist); ret = migrate_pages(&pagelist, new_page, MPOL_MF_MOVE_ALL, - 0, MIGRATE_SYNC); + false, MIGRATE_SYNC); if (ret) { putback_lru_pages(&pagelist); pr_info("soft offline: %#lx: migration failed %d, type %lx\n", diff --git a/mm/memory.c b/mm/memory.c index a240b04d084..4da9f55df49 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -183,10 +183,14 @@ static int tlb_next_batch(struct mmu_gather *tlb) return 1; } + if (tlb->batch_count == MAX_GATHER_BATCH_COUNT) + return 0; + batch = (void *)__get_free_pages(GFP_NOWAIT | __GFP_NOWARN, 0); if (!batch) return 0; + tlb->batch_count++; batch->next = NULL; batch->nr = 0; batch->max = MAX_GATHER_BATCH; @@ -213,6 +217,7 @@ void tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, bool fullmm) tlb->local.nr = 0; tlb->local.max = ARRAY_SIZE(tlb->__pages); tlb->active = &tlb->local; + tlb->batch_count = 0; #ifdef CONFIG_HAVE_RCU_TABLE_FREE tlb->batch = NULL; @@ -3500,6 +3505,7 @@ int handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma, if (unlikely(is_vm_hugetlb_page(vma))) return hugetlb_fault(mm, vma, address, flags); +retry: pgd = pgd_offset(mm, address); pud = pud_alloc(mm, pgd, address); if (!pud) @@ -3513,13 +3519,24 @@ int handle_mm_fault(struct mm_struct *mm, struct vm_area_struct *vma, pmd, flags); } else { pmd_t orig_pmd = *pmd; + int ret; + barrier(); if (pmd_trans_huge(orig_pmd)) { if (flags & FAULT_FLAG_WRITE && !pmd_write(orig_pmd) && - !pmd_trans_splitting(orig_pmd)) - return do_huge_pmd_wp_page(mm, vma, address, - pmd, orig_pmd); + !pmd_trans_splitting(orig_pmd)) { + ret = do_huge_pmd_wp_page(mm, vma, address, pmd, + orig_pmd); + /* + * If COW results in an oom, the huge pmd will + * have been split, so retry the fault on the + * pte for a smaller charge. + */ + if (unlikely(ret & VM_FAULT_OOM)) + goto retry; + return ret; + } return 0; } } diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index a0e181986a8..87a32b5cc49 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -128,9 +128,6 @@ static void register_page_bootmem_info_section(unsigned long start_pfn) struct page *page, *memmap, *page_page; int memmap_page_valid; - if (!pfn_valid(start_pfn)) - return; - section_nr = pfn_to_section_nr(start_pfn); ms = __nr_to_section(section_nr); @@ -201,9 +198,16 @@ void register_page_bootmem_info_node(struct pglist_data *pgdat) end_pfn = pfn + pgdat->node_spanned_pages; /* register_section info */ - for (; pfn < end_pfn; pfn += PAGES_PER_SECTION) - register_page_bootmem_info_section(pfn); - + for (; pfn < end_pfn; pfn += PAGES_PER_SECTION) { + /* + * Some platforms can assign the same pfn to multiple nodes - on + * node0 as well as nodeN. To avoid registering a pfn against + * multiple nodes we check that this pfn does not already + * reside in some other node. + */ + if (pfn_valid(pfn) && (pfn_to_nid(pfn) == node)) + register_page_bootmem_info_section(pfn); + } } #endif /* !CONFIG_SPARSEMEM_VMEMMAP */ diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 008de5baa82..46cb63b956f 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -607,6 +607,42 @@ check_range(struct mm_struct *mm, unsigned long start, unsigned long end, return first; } +/* + * Apply policy to a single VMA + * This must be called with the mmap_sem held for writing. + */ +static int vma_replace_policy(struct vm_area_struct *vma, + struct mempolicy *pol) +{ + int err; + struct mempolicy *old; + struct mempolicy *new; + + pr_debug("vma %lx-%lx/%lx vm_ops %p vm_file %p set_policy %p\n", + vma->vm_start, vma->vm_end, vma->vm_pgoff, + vma->vm_ops, vma->vm_file, + vma->vm_ops ? vma->vm_ops->set_policy : NULL); + + new = mpol_dup(pol); + if (IS_ERR(new)) + return PTR_ERR(new); + + if (vma->vm_ops && vma->vm_ops->set_policy) { + err = vma->vm_ops->set_policy(vma, new); + if (err) + goto err_out; + } + + old = vma->vm_policy; + vma->vm_policy = new; /* protected by mmap_sem */ + mpol_put(old); + + return 0; + err_out: + mpol_put(new); + return err; +} + /* Step 2: apply policy to a range and do splits. */ static int mbind_range(struct mm_struct *mm, unsigned long start, unsigned long end, struct mempolicy *new_pol) @@ -655,23 +691,9 @@ static int mbind_range(struct mm_struct *mm, unsigned long start, if (err) goto out; } - - /* - * Apply policy to a single VMA. The reference counting of - * policy for vma_policy linkages has already been handled by - * vma_merge and split_vma as necessary. If this is a shared - * policy then ->set_policy will increment the reference count - * for an sp node. - */ - pr_debug("vma %lx-%lx/%lx vm_ops %p vm_file %p set_policy %p\n", - vma->vm_start, vma->vm_end, vma->vm_pgoff, - vma->vm_ops, vma->vm_file, - vma->vm_ops ? vma->vm_ops->set_policy : NULL); - if (vma->vm_ops && vma->vm_ops->set_policy) { - err = vma->vm_ops->set_policy(vma, new_pol); - if (err) - goto out; - } + err = vma_replace_policy(vma, new_pol); + if (err) + goto out; } out: @@ -1510,8 +1532,18 @@ struct mempolicy *get_vma_policy(struct task_struct *task, addr); if (vpol) pol = vpol; - } else if (vma->vm_policy) + } else if (vma->vm_policy) { pol = vma->vm_policy; + + /* + * shmem_alloc_page() passes MPOL_F_SHARED policy with + * a pseudo vma whose vma->vm_ops=NULL. Take a reference + * count on these policies which will be dropped by + * mpol_cond_put() later + */ + if (mpol_needs_cond_ref(pol)) + mpol_get(pol); + } } if (!pol) pol = &default_policy; @@ -1977,28 +2009,6 @@ struct mempolicy *__mpol_dup(struct mempolicy *old) return new; } -/* - * If *frompol needs [has] an extra ref, copy *frompol to *tompol , - * eliminate the * MPOL_F_* flags that require conditional ref and - * [NOTE!!!] drop the extra ref. Not safe to reference *frompol directly - * after return. Use the returned value. - * - * Allows use of a mempolicy for, e.g., multiple allocations with a single - * policy lookup, even if the policy needs/has extra ref on lookup. - * shmem_readahead needs this. - */ -struct mempolicy *__mpol_cond_copy(struct mempolicy *tompol, - struct mempolicy *frompol) -{ - if (!mpol_needs_cond_ref(frompol)) - return frompol; - - *tompol = *frompol; - tompol->flags &= ~MPOL_F_SHARED; /* copy doesn't need unref */ - __mpol_put(frompol); - return tompol; -} - /* Slow path of a mempolicy comparison */ bool __mpol_equal(struct mempolicy *a, struct mempolicy *b) { @@ -2035,7 +2045,7 @@ bool __mpol_equal(struct mempolicy *a, struct mempolicy *b) */ /* lookup first element intersecting start-end */ -/* Caller holds sp->lock */ +/* Caller holds sp->mutex */ static struct sp_node * sp_lookup(struct shared_policy *sp, unsigned long start, unsigned long end) { @@ -2099,36 +2109,50 @@ mpol_shared_policy_lookup(struct shared_policy *sp, unsigned long idx) if (!sp->root.rb_node) return NULL; - spin_lock(&sp->lock); + mutex_lock(&sp->mutex); sn = sp_lookup(sp, idx, idx+1); if (sn) { mpol_get(sn->policy); pol = sn->policy; } - spin_unlock(&sp->lock); + mutex_unlock(&sp->mutex); return pol; } +static void sp_free(struct sp_node *n) +{ + mpol_put(n->policy); + kmem_cache_free(sn_cache, n); +} + static void sp_delete(struct shared_policy *sp, struct sp_node *n) { pr_debug("deleting %lx-l%lx\n", n->start, n->end); rb_erase(&n->nd, &sp->root); - mpol_put(n->policy); - kmem_cache_free(sn_cache, n); + sp_free(n); } static struct sp_node *sp_alloc(unsigned long start, unsigned long end, struct mempolicy *pol) { - struct sp_node *n = kmem_cache_alloc(sn_cache, GFP_KERNEL); + struct sp_node *n; + struct mempolicy *newpol; + n = kmem_cache_alloc(sn_cache, GFP_KERNEL); if (!n) return NULL; + + newpol = mpol_dup(pol); + if (IS_ERR(newpol)) { + kmem_cache_free(sn_cache, n); + return NULL; + } + newpol->flags |= MPOL_F_SHARED; + n->start = start; n->end = end; - mpol_get(pol); - pol->flags |= MPOL_F_SHARED; /* for unref */ - n->policy = pol; + n->policy = newpol; + return n; } @@ -2136,10 +2160,10 @@ static struct sp_node *sp_alloc(unsigned long start, unsigned long end, static int shared_policy_replace(struct shared_policy *sp, unsigned long start, unsigned long end, struct sp_node *new) { - struct sp_node *n, *new2 = NULL; + struct sp_node *n; + int ret = 0; -restart: - spin_lock(&sp->lock); + mutex_lock(&sp->mutex); n = sp_lookup(sp, start, end); /* Take care of old policies in the same range. */ while (n && n->start < end) { @@ -2152,16 +2176,14 @@ static int shared_policy_replace(struct shared_policy *sp, unsigned long start, } else { /* Old policy spanning whole new range. */ if (n->end > end) { + struct sp_node *new2; + new2 = sp_alloc(end, n->end, n->policy); if (!new2) { - spin_unlock(&sp->lock); - new2 = sp_alloc(end, n->end, n->policy); - if (!new2) - return -ENOMEM; - goto restart; + ret = -ENOMEM; + goto out; } n->end = start; sp_insert(sp, new2); - new2 = NULL; break; } else n->end = start; @@ -2172,12 +2194,9 @@ static int shared_policy_replace(struct shared_policy *sp, unsigned long start, } if (new) sp_insert(sp, new); - spin_unlock(&sp->lock); - if (new2) { - mpol_put(new2->policy); - kmem_cache_free(sn_cache, new2); - } - return 0; +out: + mutex_unlock(&sp->mutex); + return ret; } /** @@ -2195,7 +2214,7 @@ void mpol_shared_policy_init(struct shared_policy *sp, struct mempolicy *mpol) int ret; sp->root = RB_ROOT; /* empty tree == default mempolicy */ - spin_lock_init(&sp->lock); + mutex_init(&sp->mutex); if (mpol) { struct vm_area_struct pvma; @@ -2249,7 +2268,7 @@ int mpol_set_shared_policy(struct shared_policy *info, } err = shared_policy_replace(info, vma->vm_pgoff, vma->vm_pgoff+sz, new); if (err && new) - kmem_cache_free(sn_cache, new); + sp_free(new); return err; } @@ -2261,16 +2280,14 @@ void mpol_free_shared_policy(struct shared_policy *p) if (!p->root.rb_node) return; - spin_lock(&p->lock); + mutex_lock(&p->mutex); next = rb_first(&p->root); while (next) { n = rb_entry(next, struct sp_node, nd); next = rb_next(&n->nd); - rb_erase(&n->nd, &p->root); - mpol_put(n->policy); - kmem_cache_free(sn_cache, n); + sp_delete(p, n); } - spin_unlock(&p->lock); + mutex_unlock(&p->mutex); } /* assumes fs == KERNEL_DS */ @@ -2327,8 +2344,7 @@ void numa_default_policy(void) */ /* - * "local" is pseudo-policy: MPOL_PREFERRED with MPOL_F_LOCAL flag - * Used only for mpol_parse_str() and mpol_to_str() + * "local" is implemented internally by MPOL_PREFERRED with MPOL_F_LOCAL flag. */ #define MPOL_LOCAL MPOL_MAX static const char * const policy_modes[] = @@ -2343,28 +2359,21 @@ static const char * const policy_modes[] = #ifdef CONFIG_TMPFS /** - * mpol_parse_str - parse string to mempolicy + * mpol_parse_str - parse string to mempolicy, for tmpfs mpol mount option. * @str: string containing mempolicy to parse * @mpol: pointer to struct mempolicy pointer, returned on success. - * @no_context: flag whether to "contextualize" the mempolicy + * @unused: redundant argument, to be removed later. * * Format of input: * [=][:] * - * if @no_context is true, save the input nodemask in w.user_nodemask in - * the returned mempolicy. This will be used to "clone" the mempolicy in - * a specific context [cpuset] at a later time. Used to parse tmpfs mpol - * mount option. Note that if 'static' or 'relative' mode flags were - * specified, the input nodemask will already have been saved. Saving - * it again is redundant, but safe. - * * On success, returns 0, else 1 */ -int mpol_parse_str(char *str, struct mempolicy **mpol, int no_context) +int mpol_parse_str(char *str, struct mempolicy **mpol, int unused) { struct mempolicy *new = NULL; unsigned short mode; - unsigned short uninitialized_var(mode_flags); + unsigned short mode_flags; nodemask_t nodes; char *nodelist = strchr(str, ':'); char *flags = strchr(str, '='); @@ -2452,24 +2461,23 @@ int mpol_parse_str(char *str, struct mempolicy **mpol, int no_context) if (IS_ERR(new)) goto out; - if (no_context) { - /* save for contextualization */ - new->w.user_nodemask = nodes; - } else { - int ret; - NODEMASK_SCRATCH(scratch); - if (scratch) { - task_lock(current); - ret = mpol_set_nodemask(new, &nodes, scratch); - task_unlock(current); - } else - ret = -ENOMEM; - NODEMASK_SCRATCH_FREE(scratch); - if (ret) { - mpol_put(new); - goto out; - } - } + /* + * Save nodes for mpol_to_str() to show the tmpfs mount options + * for /proc/mounts, /proc/pid/mounts and /proc/pid/mountinfo. + */ + if (mode != MPOL_PREFERRED) + new->v.nodes = nodes; + else if (nodelist) + new->v.preferred_node = first_node(nodes); + else + new->flags |= MPOL_F_LOCAL; + + /* + * Save nodes for contextualization: this will be used to "clone" + * the mempolicy in a specific context [cpuset] at a later time. + */ + new->w.user_nodemask = nodes; + err = 0; out: @@ -2489,13 +2497,13 @@ int mpol_parse_str(char *str, struct mempolicy **mpol, int no_context) * @buffer: to contain formatted mempolicy string * @maxlen: length of @buffer * @pol: pointer to mempolicy to be formatted - * @no_context: "context free" mempolicy - use nodemask in w.user_nodemask + * @unused: redundant argument, to be removed later. * * Convert a mempolicy into a string. * Returns the number of characters in buffer (if positive) * or an error (negative) */ -int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol, int no_context) +int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol, int unused) { char *p = buffer; int l; @@ -2521,7 +2529,7 @@ int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol, int no_context) case MPOL_PREFERRED: nodes_clear(nodes); if (flags & MPOL_F_LOCAL) - mode = MPOL_LOCAL; /* pseudo-policy */ + mode = MPOL_LOCAL; else node_set(pol->v.preferred_node, nodes); break; @@ -2529,14 +2537,11 @@ int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol, int no_context) case MPOL_BIND: /* Fall through */ case MPOL_INTERLEAVE: - if (no_context) - nodes = pol->w.user_nodemask; - else - nodes = pol->v.nodes; + nodes = pol->v.nodes; break; default: - BUG(); + return -EINVAL; } l = strlen(policy_modes[mode]); diff --git a/mm/mmu_notifier.c b/mm/mmu_notifier.c index 9a611d3a184..862b60822d9 100644 --- a/mm/mmu_notifier.c +++ b/mm/mmu_notifier.c @@ -33,6 +33,24 @@ void __mmu_notifier_release(struct mm_struct *mm) { struct mmu_notifier *mn; + struct hlist_node *n; + + /* + * RCU here will block mmu_notifier_unregister until + * ->release returns. + */ + rcu_read_lock(); + hlist_for_each_entry_rcu(mn, n, &mm->mmu_notifier_mm->list, hlist) + /* + * if ->release runs before mmu_notifier_unregister it + * must be handled as it's the only way for the driver + * to flush all existing sptes and stop the driver + * from establishing any more sptes before all the + * pages in the mm are freed. + */ + if (mn->ops->release) + mn->ops->release(mn, mm); + rcu_read_unlock(); spin_lock(&mm->mmu_notifier_mm->lock); while (unlikely(!hlist_empty(&mm->mmu_notifier_mm->list))) { @@ -46,23 +64,6 @@ void __mmu_notifier_release(struct mm_struct *mm) * mmu_notifier_unregister to return. */ hlist_del_init_rcu(&mn->hlist); - /* - * RCU here will block mmu_notifier_unregister until - * ->release returns. - */ - rcu_read_lock(); - spin_unlock(&mm->mmu_notifier_mm->lock); - /* - * if ->release runs before mmu_notifier_unregister it - * must be handled as it's the only way for the driver - * to flush all existing sptes and stop the driver - * from establishing any more sptes before all the - * pages in the mm are freed. - */ - if (mn->ops->release) - mn->ops->release(mn, mm); - rcu_read_unlock(); - spin_lock(&mm->mmu_notifier_mm->lock); } spin_unlock(&mm->mmu_notifier_mm->lock); @@ -284,16 +285,13 @@ void mmu_notifier_unregister(struct mmu_notifier *mn, struct mm_struct *mm) { BUG_ON(atomic_read(&mm->mm_count) <= 0); - spin_lock(&mm->mmu_notifier_mm->lock); if (!hlist_unhashed(&mn->hlist)) { - hlist_del_rcu(&mn->hlist); - /* * RCU here will force exit_mmap to wait ->release to finish * before freeing the pages. */ rcu_read_lock(); - spin_unlock(&mm->mmu_notifier_mm->lock); + /* * exit_mmap will block in mmu_notifier_release to * guarantee ->release is called before freeing the @@ -302,8 +300,11 @@ void mmu_notifier_unregister(struct mmu_notifier *mn, struct mm_struct *mm) if (mn->ops->release) mn->ops->release(mn, mm); rcu_read_unlock(); - } else + + spin_lock(&mm->mmu_notifier_mm->lock); + hlist_del_rcu(&mn->hlist); spin_unlock(&mm->mmu_notifier_mm->lock); + } /* * Wait any running method to finish, of course including diff --git a/mm/page-writeback.c b/mm/page-writeback.c index 102b62f8534..dfe58f4e4fd 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c @@ -186,6 +186,18 @@ static unsigned long highmem_dirtyable_memory(unsigned long total) x += zone_page_state(z, NR_FREE_PAGES) + zone_reclaimable_pages(z) - z->dirty_balance_reserve; } + /* + * Unreclaimable memory (kernel memory or anonymous memory + * without swap) can bring down the dirtyable pages below + * the zone's dirty balance reserve and the above calculation + * will underflow. However we still want to add in nodes + * which are below threshold (negative values) to get a more + * accurate calculation but make sure that the total never + * underflows. + */ + if ((long)x < 0) + x = 0; + /* * Make sure that the number of highmem pages is never larger * than the number of the total dirtyable memory. This can only @@ -208,8 +220,8 @@ unsigned long global_dirtyable_memory(void) { unsigned long x; - x = global_page_state(NR_FREE_PAGES) + global_reclaimable_pages() - - dirty_balance_reserve; + x = global_page_state(NR_FREE_PAGES) + global_reclaimable_pages(); + x -= min(x, dirty_balance_reserve); if (!vm_highmem_is_dirtyable) x -= highmem_dirtyable_memory(x); @@ -276,9 +288,12 @@ static unsigned long zone_dirtyable_memory(struct zone *zone) * highmem zone can hold its share of dirty pages, so we don't * care about vm_highmem_is_dirtyable here. */ - return zone_page_state(zone, NR_FREE_PAGES) + - zone_reclaimable_pages(zone) - - zone->dirty_balance_reserve; + unsigned long nr_pages = zone_page_state(zone, NR_FREE_PAGES) + + zone_reclaimable_pages(zone); + + /* don't allow this to underflow */ + nr_pages -= min(nr_pages, zone->dirty_balance_reserve); + return nr_pages; } /** diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 69b952153ba..932c7bdd01c 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -588,7 +588,7 @@ static inline void __free_one_page(struct page *page, combined_idx = buddy_idx & page_idx; higher_page = page + (combined_idx - page_idx); buddy_idx = __find_buddy_index(combined_idx, order + 1); - higher_buddy = page + (buddy_idx - combined_idx); + higher_buddy = higher_page + (buddy_idx - combined_idx); if (page_is_buddy(higher_page, higher_buddy, order + 1)) { list_add_tail(&page->lru, &zone->free_area[order].free_list[migratetype]); diff --git a/mm/rmap.c b/mm/rmap.c index 5b5ad584ffb..bfca52c9699 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -56,6 +56,7 @@ #include #include #include +#include #include @@ -977,11 +978,8 @@ int page_mkclean(struct page *page) if (page_mapped(page)) { struct address_space *mapping = page_mapping(page); - if (mapping) { + if (mapping) ret = page_mkclean_file(mapping, page); - if (page_test_and_clear_dirty(page_to_pfn(page), 1)) - ret = 1; - } } return ret; @@ -1167,6 +1165,7 @@ void page_add_file_rmap(struct page *page) */ void page_remove_rmap(struct page *page) { + struct address_space *mapping = page_mapping(page); bool anon = PageAnon(page); bool locked; unsigned long flags; @@ -1189,8 +1188,19 @@ void page_remove_rmap(struct page *page) * this if the page is anon, so about to be freed; but perhaps * not if it's in swapcache - there might be another pte slot * containing the swap entry, but page not yet written to swap. + * + * And we can skip it on file pages, so long as the filesystem + * participates in dirty tracking; but need to catch shm and tmpfs + * and ramfs pages which have been modified since creation by read + * fault. + * + * Note that mapping must be decided above, before decrementing + * mapcount (which luckily provides a barrier): once page is unmapped, + * it could be truncated and page->mapping reset to NULL at any moment. + * Note also that we are relying on page_mapping(page) to set mapping + * to &swapper_space when PageSwapCache(page). */ - if ((!anon || PageSwapCache(page)) && + if (mapping && !mapping_cap_account_dirty(mapping) && page_test_and_clear_dirty(page_to_pfn(page), 1)) set_page_dirty(page); /* diff --git a/mm/shmem.c b/mm/shmem.c index 2910f0d58c4..c6acb7ef5e9 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -595,7 +595,7 @@ static void shmem_evict_inode(struct inode *inode) kfree(xattr->name); kfree(xattr); } - BUG_ON(inode->i_blocks); + WARN_ON(inode->i_blocks); shmem_free_inode(inode->i_sb); end_writeback(inode); } @@ -798,24 +798,28 @@ static struct mempolicy *shmem_get_sbmpol(struct shmem_sb_info *sbinfo) static struct page *shmem_swapin(swp_entry_t swap, gfp_t gfp, struct shmem_inode_info *info, pgoff_t index) { - struct mempolicy mpol, *spol; struct vm_area_struct pvma; - - spol = mpol_cond_copy(&mpol, - mpol_shared_policy_lookup(&info->policy, index)); + struct page *page; /* Create a pseudo vma that just contains the policy */ pvma.vm_start = 0; pvma.vm_pgoff = index; pvma.vm_ops = NULL; - pvma.vm_policy = spol; - return swapin_readahead(swap, gfp, &pvma, 0); + pvma.vm_policy = mpol_shared_policy_lookup(&info->policy, index); + + page = swapin_readahead(swap, gfp, &pvma, 0); + + /* Drop reference taken by mpol_shared_policy_lookup() */ + mpol_cond_put(pvma.vm_policy); + + return page; } static struct page *shmem_alloc_page(gfp_t gfp, struct shmem_inode_info *info, pgoff_t index) { struct vm_area_struct pvma; + struct page *page; /* Create a pseudo vma that just contains the policy */ pvma.vm_start = 0; @@ -823,10 +827,12 @@ static struct page *shmem_alloc_page(gfp_t gfp, pvma.vm_ops = NULL; pvma.vm_policy = mpol_shared_policy_lookup(&info->policy, index); - /* - * alloc_page_vma() will drop the shared policy reference - */ - return alloc_page_vma(gfp, &pvma, 0); + page = alloc_page_vma(gfp, &pvma, 0); + + /* Drop reference taken by mpol_shared_policy_lookup() */ + mpol_cond_put(pvma.vm_policy); + + return page; } #else /* !CONFIG_NUMA */ #ifdef CONFIG_TMPFS @@ -2018,12 +2024,14 @@ static struct dentry *shmem_fh_to_dentry(struct super_block *sb, { struct inode *inode; struct dentry *dentry = NULL; - u64 inum = fid->raw[2]; - inum = (inum << 32) | fid->raw[1]; + u64 inum; if (fh_len < 3) return NULL; + inum = fid->raw[2]; + inum = (inum << 32) | fid->raw[1]; + inode = ilookup5(sb, (unsigned long)(inum + fid->raw[0]), shmem_match, fid->raw); if (inode) { diff --git a/mm/slab.c b/mm/slab.c index 10d0d001df8..fb563b520d6 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -1685,9 +1685,6 @@ void __init kmem_cache_init_late(void) g_cpucache_up = LATE; - /* Annotate slab for lockdep -- annotate the malloc caches */ - init_lock_keys(); - /* 6) resize the head arrays to their final sizes */ mutex_lock(&cache_chain_mutex); list_for_each_entry(cachep, &cache_chain, next) @@ -1695,6 +1692,9 @@ void __init kmem_cache_init_late(void) BUG(); mutex_unlock(&cache_chain_mutex); + /* Annotate slab for lockdep -- annotate the malloc caches */ + init_lock_keys(); + /* Done! */ g_cpucache_up = FULL; diff --git a/mm/sparse.c b/mm/sparse.c index 55cda7a9dfd..8123ae9e038 100644 --- a/mm/sparse.c +++ b/mm/sparse.c @@ -621,7 +621,7 @@ static void __kfree_section_memmap(struct page *memmap, unsigned long nr_pages) { return; /* XXX: Not implemented yet */ } -static void free_map_bootmem(struct page *page, unsigned long nr_pages) +static void free_map_bootmem(struct page *memmap, unsigned long nr_pages) { } #else @@ -662,10 +662,11 @@ static void __kfree_section_memmap(struct page *memmap, unsigned long nr_pages) get_order(sizeof(struct page) * nr_pages)); } -static void free_map_bootmem(struct page *page, unsigned long nr_pages) +static void free_map_bootmem(struct page *memmap, unsigned long nr_pages) { unsigned long maps_section_nr, removing_section_nr, i; unsigned long magic; + struct page *page = virt_to_page(memmap); for (i = 0; i < nr_pages; i++, page++) { magic = (unsigned long) page->lru.next; @@ -714,13 +715,10 @@ static void free_section_usemap(struct page *memmap, unsigned long *usemap) */ if (memmap) { - struct page *memmap_page; - memmap_page = virt_to_page(memmap); - nr_pages = PAGE_ALIGN(PAGES_PER_SECTION * sizeof(struct page)) >> PAGE_SHIFT; - free_map_bootmem(memmap_page, nr_pages); + free_map_bootmem(memmap, nr_pages); } } diff --git a/mm/truncate.c b/mm/truncate.c index 61a183b89df..4224627695b 100644 --- a/mm/truncate.c +++ b/mm/truncate.c @@ -394,11 +394,12 @@ invalidate_complete_page2(struct address_space *mapping, struct page *page) if (page_has_private(page) && !try_to_release_page(page, GFP_KERNEL)) return 0; + clear_page_mlock(page); + spin_lock_irq(&mapping->tree_lock); if (PageDirty(page)) goto failed; - clear_page_mlock(page); BUG_ON(page_has_private(page)); __delete_from_page_cache(page); spin_unlock_irq(&mapping->tree_lock); diff --git a/mm/vmscan.c b/mm/vmscan.c index 086613f36f4..81ae3756cb8 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -1983,10 +1983,10 @@ static void get_scan_count(struct mem_cgroup_zone *mz, struct scan_control *sc, * proportional to the fraction of recently scanned pages on * each list that were recently referenced and in active use. */ - ap = (anon_prio + 1) * (reclaim_stat->recent_scanned[0] + 1); + ap = anon_prio * (reclaim_stat->recent_scanned[0] + 1); ap /= reclaim_stat->recent_rotated[0] + 1; - fp = (file_prio + 1) * (reclaim_stat->recent_scanned[1] + 1); + fp = file_prio * (reclaim_stat->recent_scanned[1] + 1); fp /= reclaim_stat->recent_rotated[1] + 1; spin_unlock_irq(&mz->zone->lru_lock); @@ -1999,7 +1999,7 @@ static void get_scan_count(struct mem_cgroup_zone *mz, struct scan_control *sc, unsigned long scan; scan = zone_nr_lru_pages(mz, lru); - if (priority || noswap) { + if (priority || noswap || !vmscan_swappiness(mz, sc)) { scan >>= priority; if (!scan && force_scan) scan = SWAP_CLUSTER_MAX; @@ -3013,7 +3013,10 @@ static void kswapd_try_to_sleep(pg_data_t *pgdat, int order, int classzone_idx) * them before going back to sleep. */ set_pgdat_percpu_threshold(pgdat, calculate_normal_threshold); - schedule(); + + if (!kthread_should_stop()) + schedule(); + set_pgdat_percpu_threshold(pgdat, calculate_pressure_threshold); } else { if (remaining) @@ -3125,6 +3128,8 @@ static int kswapd(void *p) &balanced_classzone_idx); } } + + current->reclaim_state = NULL; return 0; } diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index efea35b02e7..cf4a49c5623 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c @@ -403,6 +403,9 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, break; case NETDEV_DOWN: + if (dev->features & NETIF_F_HW_VLAN_FILTER) + vlan_vid_del(dev, 0); + /* Put all VLANs for this dev in the down state too. */ for (i = 0; i < VLAN_N_VID; i++) { vlandev = vlan_group_get_device(grp, i); diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c index 4d39d802be2..912613c566c 100644 --- a/net/8021q/vlan_core.c +++ b/net/8021q/vlan_core.c @@ -5,7 +5,7 @@ #include #include "vlan.h" -bool vlan_do_receive(struct sk_buff **skbp, bool last_handler) +bool vlan_do_receive(struct sk_buff **skbp) { struct sk_buff *skb = *skbp; u16 vlan_id = skb->vlan_tci & VLAN_VID_MASK; @@ -13,14 +13,8 @@ bool vlan_do_receive(struct sk_buff **skbp, bool last_handler) struct vlan_pcpu_stats *rx_stats; vlan_dev = vlan_find_dev(skb->dev, vlan_id); - if (!vlan_dev) { - /* Only the last call to vlan_do_receive() should change - * pkt_type to PACKET_OTHERHOST - */ - if (vlan_id && last_handler) - skb->pkt_type = PACKET_OTHERHOST; + if (!vlan_dev) return false; - } skb = *skbp = skb_share_check(skb, GFP_ATOMIC); if (unlikely(!skb)) @@ -106,7 +100,6 @@ static struct sk_buff *vlan_reorder_header(struct sk_buff *skb) return NULL; memmove(skb->data - ETH_HLEN, skb->data - VLAN_ETH_HLEN, 2 * ETH_ALEN); skb->mac_header += VLAN_HLEN; - skb_reset_mac_len(skb); return skb; } @@ -140,6 +133,8 @@ struct sk_buff *vlan_untag(struct sk_buff *skb) skb_reset_network_header(skb); skb_reset_transport_header(skb); + skb_reset_mac_len(skb); + return skb; err_free: diff --git a/net/atm/common.c b/net/atm/common.c index b4b44dbed64..0c0ad930a63 100644 --- a/net/atm/common.c +++ b/net/atm/common.c @@ -812,6 +812,7 @@ int vcc_getsockopt(struct socket *sock, int level, int optname, if (!vcc->dev || !test_bit(ATM_VF_ADDR, &vcc->flags)) return -ENOTCONN; + memset(&pvc, 0, sizeof(pvc)); pvc.sap_family = AF_ATMPVC; pvc.sap_addr.itf = vcc->dev->number; pvc.sap_addr.vpi = vcc->vpi; diff --git a/net/atm/pvc.c b/net/atm/pvc.c index 3a734919c36..ae032402140 100644 --- a/net/atm/pvc.c +++ b/net/atm/pvc.c @@ -95,6 +95,7 @@ static int pvc_getname(struct socket *sock, struct sockaddr *sockaddr, return -ENOTCONN; *sockaddr_len = sizeof(struct sockaddr_atmpvc); addr = (struct sockaddr_atmpvc *)sockaddr; + memset(addr, 0, sizeof(*addr)); addr->sap_family = AF_ATMPVC; addr->sap_addr.itf = vcc->dev->number; addr->sap_addr.vpi = vcc->vpi; diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c index a6d5d63fb6a..fa701b6f794 100644 --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c @@ -72,7 +72,7 @@ static unsigned long bat_iv_ogm_emit_send_time(const struct bat_priv *bat_priv) { return jiffies + msecs_to_jiffies( atomic_read(&bat_priv->orig_interval) - - JITTER + (random32() % 2*JITTER)); + JITTER + (random32() % (2*JITTER))); } /* when do we schedule a ogm packet to be sent */ diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 7ecbc70df4c..ddf3fa4dd35 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1574,6 +1574,8 @@ int hci_unregister_dev(struct hci_dev *hdev) for (i = 0; i < NUM_REASSEMBLY; i++) kfree_skb(hdev->reassembly[i]); + cancel_work_sync(&hdev->power_on); + if (!test_bit(HCI_INIT, &hdev->flags) && !test_bit(HCI_SETUP, &hdev->flags) && hdev->dev_type == HCI_BREDR) { diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 198773c1cc7..50dfe0371a5 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1647,6 +1647,7 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s if (conn->type == ACL_LINK) { conn->state = BT_CONFIG; hci_conn_hold(conn); + conn->disc_timeout = HCI_DISCONN_TIMEOUT; mgmt_connected(hdev->id, &ev->bdaddr, 0); } else if (conn->type == LE_LINK) { @@ -2313,7 +2314,7 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk if (ev->opcode != HCI_OP_NOP) del_timer(&hdev->cmd_timer); - if (ev->ncmd) { + if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) { atomic_set(&hdev->cmd_cnt, 1); if (!skb_queue_empty(&hdev->cmd_q)) tasklet_schedule(&hdev->cmd_task); diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index 550f60197a6..41b490669c3 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c @@ -440,6 +440,7 @@ static int hci_sock_getname(struct socket *sock, struct sockaddr *addr, int *add *addr_len = sizeof(*haddr); haddr->hci_family = AF_BLUETOOTH; haddr->hci_dev = hdev->id; + haddr->hci_channel= 0; release_sock(sk); return 0; @@ -732,6 +733,7 @@ static int hci_sock_getsockopt(struct socket *sock, int level, int optname, char { struct hci_filter *f = &hci_pi(sk)->filter; + memset(&uf, 0, sizeof(uf)); uf.type_mask = f->type_mask; uf.opcode = f->opcode; uf.event_mask[0] = *((u32 *) f->event_mask + 0); diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index ba09f4a8199..9252f5e2755 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c @@ -801,7 +801,7 @@ static int hidp_setup_hid(struct hidp_session *session, hid->version = req->version; hid->country = req->country; - strncpy(hid->name, req->name, 128); + strncpy(hid->name, req->name, sizeof(req->name) - 1); strncpy(hid->phys, batostr(&bt_sk(session->ctrl_sock->sk)->src), 64); strncpy(hid->uniq, batostr(&bt_sk(session->ctrl_sock->sk)->dst), 64); diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 83087d10a5a..2c0d3cac2b1 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -404,6 +404,7 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *l BT_DBG("sock %p, sk %p", sock, sk); + memset(la, 0, sizeof(struct sockaddr_l2)); addr->sa_family = AF_BLUETOOTH; *len = sizeof(struct sockaddr_l2); diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index 297729cf078..2578f916d4b 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c @@ -484,7 +484,7 @@ static int rfcomm_sock_accept(struct socket *sock, struct socket *newsock, int f long timeo; int err = 0; - lock_sock(sk); + lock_sock_nested(sk, SINGLE_DEPTH_NESTING); if (sk->sk_state != BT_LISTEN) { err = -EBADFD; @@ -511,7 +511,7 @@ static int rfcomm_sock_accept(struct socket *sock, struct socket *newsock, int f release_sock(sk); timeo = schedule_timeout(timeo); - lock_sock(sk); + lock_sock_nested(sk, SINGLE_DEPTH_NESTING); if (sk->sk_state != BT_LISTEN) { err = -EBADFD; @@ -545,6 +545,7 @@ static int rfcomm_sock_getname(struct socket *sock, struct sockaddr *addr, int * BT_DBG("sock %p, sk %p", sock, sk); + memset(sa, 0, sizeof(*sa)); sa->rc_family = AF_BLUETOOTH; sa->rc_channel = rfcomm_pi(sk)->channel; if (peer) @@ -835,6 +836,7 @@ static int rfcomm_sock_getsockopt(struct socket *sock, int level, int optname, c } sec.level = rfcomm_pi(sk)->sec_level; + sec.key_size = 0; len = min_t(unsigned int, len, sizeof(sec)); if (copy_to_user(optval, (char *) &sec, len)) diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index e18781ce497..435af03aaa6 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c @@ -472,7 +472,7 @@ static int rfcomm_get_dev_list(void __user *arg) size = sizeof(*dl) + dev_num * sizeof(*di); - dl = kmalloc(size, GFP_KERNEL); + dl = kzalloc(size, GFP_KERNEL); if (!dl) return -ENOMEM; diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index b9089969cc5..a37811bfb61 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c @@ -47,6 +47,8 @@ static int smp_distribute_keys(struct l2cap_conn *conn, __u8 force); +#define AUTH_REQ_MASK 0x07 + static inline void swap128(u8 src[16], u8 dst[16]) { int i; @@ -249,6 +251,7 @@ static void build_pairing_cmd(struct l2cap_conn *conn, req->io_capability, req->oob_flag, req->auth_req, req->max_key_size, req->init_key_dist, req->resp_key_dist); + req->auth_req = (authreq & AUTH_REQ_MASK); return; } @@ -268,6 +271,7 @@ static void build_pairing_cmd(struct l2cap_conn *conn, req->io_capability, req->oob_flag, req->auth_req, req->max_key_size, req->init_key_dist, req->resp_key_dist); + rsp->auth_req = (authreq & AUTH_REQ_MASK); } static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size) diff --git a/net/caif/caif_dev.c b/net/caif/caif_dev.c index aa6f716524f..7bf4c21a279 100644 --- a/net/caif/caif_dev.c +++ b/net/caif/caif_dev.c @@ -562,9 +562,9 @@ static int __init caif_device_init(void) static void __exit caif_device_exit(void) { - unregister_pernet_subsys(&caif_net_ops); unregister_netdevice_notifier(&caif_device_notifier); dev_remove_pack(&caif_packet_type); + unregister_pernet_subsys(&caif_net_ops); } module_init(caif_device_init); diff --git a/net/can/bcm.c b/net/can/bcm.c index 151b7730c12..3910c1fefd0 100644 --- a/net/can/bcm.c +++ b/net/can/bcm.c @@ -1084,6 +1084,9 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg, op->sk = sk; op->ifindex = ifindex; + /* ifindex for timeout events w/o previous frame reception */ + op->rx_ifindex = ifindex; + /* initialize uninitialized (kzalloc) structure */ hrtimer_init(&op->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); op->timer.function = bcm_rx_timeout_handler; diff --git a/net/ceph/auth_none.c b/net/ceph/auth_none.c index 214c2bb43d6..925ca583c09 100644 --- a/net/ceph/auth_none.c +++ b/net/ceph/auth_none.c @@ -59,9 +59,7 @@ static int handle_reply(struct ceph_auth_client *ac, int result, */ static int ceph_auth_none_create_authorizer( struct ceph_auth_client *ac, int peer_type, - struct ceph_authorizer **a, - void **buf, size_t *len, - void **reply_buf, size_t *reply_len) + struct ceph_auth_handshake *auth) { struct ceph_auth_none_info *ai = ac->private; struct ceph_none_authorizer *au = &ai->au; @@ -82,11 +80,12 @@ static int ceph_auth_none_create_authorizer( dout("built authorizer len %d\n", au->buf_len); } - *a = (struct ceph_authorizer *)au; - *buf = au->buf; - *len = au->buf_len; - *reply_buf = au->reply_buf; - *reply_len = sizeof(au->reply_buf); + auth->authorizer = (struct ceph_authorizer *) au; + auth->authorizer_buf = au->buf; + auth->authorizer_buf_len = au->buf_len; + auth->authorizer_reply_buf = au->reply_buf; + auth->authorizer_reply_buf_len = sizeof (au->reply_buf); + return 0; bad2: diff --git a/net/ceph/auth_x.c b/net/ceph/auth_x.c index 1587dc6010c..a16bf14eb02 100644 --- a/net/ceph/auth_x.c +++ b/net/ceph/auth_x.c @@ -526,9 +526,7 @@ static int ceph_x_handle_reply(struct ceph_auth_client *ac, int result, static int ceph_x_create_authorizer( struct ceph_auth_client *ac, int peer_type, - struct ceph_authorizer **a, - void **buf, size_t *len, - void **reply_buf, size_t *reply_len) + struct ceph_auth_handshake *auth) { struct ceph_x_authorizer *au; struct ceph_x_ticket_handler *th; @@ -548,11 +546,12 @@ static int ceph_x_create_authorizer( return ret; } - *a = (struct ceph_authorizer *)au; - *buf = au->buf->vec.iov_base; - *len = au->buf->vec.iov_len; - *reply_buf = au->reply_buf; - *reply_len = sizeof(au->reply_buf); + auth->authorizer = (struct ceph_authorizer *) au; + auth->authorizer_buf = au->buf->vec.iov_base; + auth->authorizer_buf_len = au->buf->vec.iov_len; + auth->authorizer_reply_buf = au->reply_buf; + auth->authorizer_reply_buf_len = sizeof (au->reply_buf); + return 0; } diff --git a/net/ceph/ceph_common.c b/net/ceph/ceph_common.c index cc913193d99..b11448f052f 100644 --- a/net/ceph/ceph_common.c +++ b/net/ceph/ceph_common.c @@ -83,7 +83,6 @@ int ceph_check_fsid(struct ceph_client *client, struct ceph_fsid *fsid) return -1; } } else { - pr_info("client%lld fsid %pU\n", ceph_client_id(client), fsid); memcpy(&client->fsid, fsid, sizeof(*fsid)); } return 0; @@ -305,7 +304,6 @@ ceph_parse_options(char *options, const char *dev_name, /* start with defaults */ opt->flags = CEPH_OPT_DEFAULT; - opt->osd_timeout = CEPH_OSD_TIMEOUT_DEFAULT; opt->osd_keepalive_timeout = CEPH_OSD_KEEPALIVE_DEFAULT; opt->mount_timeout = CEPH_MOUNT_TIMEOUT_DEFAULT; /* seconds */ opt->osd_idle_ttl = CEPH_OSD_IDLE_TTL_DEFAULT; /* seconds */ @@ -391,7 +389,7 @@ ceph_parse_options(char *options, const char *dev_name, /* misc */ case Opt_osdtimeout: - opt->osd_timeout = intval; + pr_warning("ignoring deprecated osdtimeout option\n"); break; case Opt_osdkeepalivetimeout: opt->osd_keepalive_timeout = intval; @@ -468,19 +466,15 @@ struct ceph_client *ceph_create_client(struct ceph_options *opt, void *private, /* msgr */ if (ceph_test_opt(client, MYIP)) myaddr = &client->options->my_addr; - client->msgr = ceph_messenger_create(myaddr, - client->supported_features, - client->required_features); - if (IS_ERR(client->msgr)) { - err = PTR_ERR(client->msgr); - goto fail; - } - client->msgr->nocrc = ceph_test_opt(client, NOCRC); + ceph_messenger_init(&client->msgr, myaddr, + client->supported_features, + client->required_features, + ceph_test_opt(client, NOCRC)); /* subsystems */ err = ceph_monc_init(&client->monc, client); if (err < 0) - goto fail_msgr; + goto fail; err = ceph_osdc_init(&client->osdc, client); if (err < 0) goto fail_monc; @@ -489,8 +483,6 @@ struct ceph_client *ceph_create_client(struct ceph_options *opt, void *private, fail_monc: ceph_monc_stop(&client->monc); -fail_msgr: - ceph_messenger_destroy(client->msgr); fail: kfree(client); return ERR_PTR(err); @@ -501,22 +493,15 @@ void ceph_destroy_client(struct ceph_client *client) { dout("destroy_client %p\n", client); + atomic_set(&client->msgr.stopping, 1); + /* unmount */ ceph_osdc_stop(&client->osdc); - /* - * make sure osd connections close out before destroying the - * auth module, which is needed to free those connections' - * ceph_authorizers. - */ - ceph_msgr_flush(); - ceph_monc_stop(&client->monc); ceph_debugfs_client_cleanup(client); - ceph_messenger_destroy(client->msgr); - ceph_destroy_options(client->options); kfree(client); diff --git a/net/ceph/crush/crush.c b/net/ceph/crush/crush.c index d6ebb13a18a..fbda0521a00 100644 --- a/net/ceph/crush/crush.c +++ b/net/ceph/crush/crush.c @@ -26,9 +26,9 @@ const char *crush_bucket_alg_name(int alg) * @b: bucket pointer * @p: item index in bucket */ -int crush_get_bucket_item_weight(struct crush_bucket *b, int p) +int crush_get_bucket_item_weight(const struct crush_bucket *b, int p) { - if (p >= b->size) + if ((__u32)p >= b->size) return 0; switch (b->alg) { @@ -37,9 +37,7 @@ int crush_get_bucket_item_weight(struct crush_bucket *b, int p) case CRUSH_BUCKET_LIST: return ((struct crush_bucket_list *)b)->item_weights[p]; case CRUSH_BUCKET_TREE: - if (p & 1) - return ((struct crush_bucket_tree *)b)->node_weights[p]; - return 0; + return ((struct crush_bucket_tree *)b)->node_weights[crush_calc_tree_node(p)]; case CRUSH_BUCKET_STRAW: return ((struct crush_bucket_straw *)b)->item_weights[p]; } @@ -87,6 +85,8 @@ void crush_destroy_bucket_list(struct crush_bucket_list *b) void crush_destroy_bucket_tree(struct crush_bucket_tree *b) { + kfree(b->h.perm); + kfree(b->h.items); kfree(b->node_weights); kfree(b); } @@ -124,10 +124,9 @@ void crush_destroy_bucket(struct crush_bucket *b) */ void crush_destroy(struct crush_map *map) { - int b; - /* buckets */ if (map->buckets) { + __s32 b; for (b = 0; b < map->max_buckets; b++) { if (map->buckets[b] == NULL) continue; @@ -138,6 +137,7 @@ void crush_destroy(struct crush_map *map) /* rules */ if (map->rules) { + __u32 b; for (b = 0; b < map->max_rules; b++) kfree(map->rules[b]); kfree(map->rules); diff --git a/net/ceph/crush/mapper.c b/net/ceph/crush/mapper.c index b79747c4b64..00baad5d3bd 100644 --- a/net/ceph/crush/mapper.c +++ b/net/ceph/crush/mapper.c @@ -32,9 +32,9 @@ * @type: storage ruleset type (user defined) * @size: output set size */ -int crush_find_rule(struct crush_map *map, int ruleset, int type, int size) +int crush_find_rule(const struct crush_map *map, int ruleset, int type, int size) { - int i; + __u32 i; for (i = 0; i < map->max_rules; i++) { if (map->rules[i] && @@ -72,7 +72,7 @@ static int bucket_perm_choose(struct crush_bucket *bucket, unsigned i, s; /* start a new permutation if @x has changed */ - if (bucket->perm_x != x || bucket->perm_n == 0) { + if (bucket->perm_x != (__u32)x || bucket->perm_n == 0) { dprintk("bucket %d new x=%d\n", bucket->id, x); bucket->perm_x = x; @@ -152,8 +152,8 @@ static int bucket_list_choose(struct crush_bucket_list *bucket, return bucket->h.items[i]; } - BUG_ON(1); - return 0; + dprintk("bad list sums for bucket %d\n", bucket->h.id); + return bucket->h.items[0]; } @@ -219,7 +219,7 @@ static int bucket_tree_choose(struct crush_bucket_tree *bucket, static int bucket_straw_choose(struct crush_bucket_straw *bucket, int x, int r) { - int i; + __u32 i; int high = 0; __u64 high_draw = 0; __u64 draw; @@ -239,6 +239,7 @@ static int bucket_straw_choose(struct crush_bucket_straw *bucket, static int crush_bucket_choose(struct crush_bucket *in, int x, int r) { dprintk(" crush_bucket_choose %d x=%d r=%d\n", in->id, x, r); + BUG_ON(in->size == 0); switch (in->alg) { case CRUSH_BUCKET_UNIFORM: return bucket_uniform_choose((struct crush_bucket_uniform *)in, @@ -253,7 +254,7 @@ static int crush_bucket_choose(struct crush_bucket *in, int x, int r) return bucket_straw_choose((struct crush_bucket_straw *)in, x, r); default: - BUG_ON(1); + dprintk("unknown bucket %d alg %d\n", in->id, in->alg); return in->items[0]; } } @@ -262,7 +263,7 @@ static int crush_bucket_choose(struct crush_bucket *in, int x, int r) * true if device is marked "out" (failed, fully offloaded) * of the cluster */ -static int is_out(struct crush_map *map, __u32 *weight, int item, int x) +static int is_out(const struct crush_map *map, const __u32 *weight, int item, int x) { if (weight[item] >= 0x10000) return 0; @@ -287,16 +288,16 @@ static int is_out(struct crush_map *map, __u32 *weight, int item, int x) * @recurse_to_leaf: true if we want one device under each item of given type * @out2: second output vector for leaf items (if @recurse_to_leaf) */ -static int crush_choose(struct crush_map *map, +static int crush_choose(const struct crush_map *map, struct crush_bucket *bucket, - __u32 *weight, + const __u32 *weight, int x, int numrep, int type, int *out, int outpos, int firstn, int recurse_to_leaf, int *out2) { int rep; - int ftotal, flocal; + unsigned int ftotal, flocal; int retry_descent, retry_bucket, skip_rep; struct crush_bucket *in = bucket; int r; @@ -304,7 +305,7 @@ static int crush_choose(struct crush_map *map, int item = 0; int itemtype; int collide, reject; - const int orig_tries = 5; /* attempts before we fall back to search */ + const unsigned int orig_tries = 5; /* attempts before we fall back to search */ dprintk("CHOOSE%s bucket %d x %d outpos %d numrep %d\n", recurse_to_leaf ? "_LEAF" : "", bucket->id, x, outpos, numrep); @@ -325,7 +326,7 @@ static int crush_choose(struct crush_map *map, r = rep; if (in->alg == CRUSH_BUCKET_UNIFORM) { /* be careful */ - if (firstn || numrep >= in->size) + if (firstn || (__u32)numrep >= in->size) /* r' = r + f_total */ r += ftotal; else if (in->size % numrep == 0) @@ -354,7 +355,11 @@ static int crush_choose(struct crush_map *map, item = bucket_perm_choose(in, x, r); else item = crush_bucket_choose(in, x, r); - BUG_ON(item >= map->max_devices); + if (item >= map->max_devices) { + dprintk(" bad item %d\n", item); + skip_rep = 1; + break; + } /* desired type? */ if (item < 0) @@ -365,8 +370,12 @@ static int crush_choose(struct crush_map *map, /* keep going? */ if (itemtype != type) { - BUG_ON(item >= 0 || - (-1-item) >= map->max_buckets); + if (item >= 0 || + (-1-item) >= map->max_buckets) { + dprintk(" bad item type %d\n", type); + skip_rep = 1; + break; + } in = map->buckets[-1-item]; retry_bucket = 1; continue; @@ -415,7 +424,7 @@ static int crush_choose(struct crush_map *map, if (collide && flocal < 3) /* retry locally a few times */ retry_bucket = 1; - else if (flocal < in->size + orig_tries) + else if (flocal <= in->size + orig_tries) /* exhaustive bucket search */ retry_bucket = 1; else if (ftotal < 20) @@ -425,7 +434,7 @@ static int crush_choose(struct crush_map *map, /* else give up */ skip_rep = 1; dprintk(" reject %d collide %d " - "ftotal %d flocal %d\n", + "ftotal %u flocal %u\n", reject, collide, ftotal, flocal); } @@ -456,9 +465,9 @@ static int crush_choose(struct crush_map *map, * @result_max: maximum result size * @force: force initial replica choice; -1 for none */ -int crush_do_rule(struct crush_map *map, +int crush_do_rule(const struct crush_map *map, int ruleno, int x, int *result, int result_max, - int force, __u32 *weight) + int force, const __u32 *weight) { int result_len; int force_context[CRUSH_MAX_DEPTH]; @@ -473,12 +482,15 @@ int crush_do_rule(struct crush_map *map, int osize; int *tmp; struct crush_rule *rule; - int step; + __u32 step; int i, j; int numrep; int firstn; - BUG_ON(ruleno >= map->max_rules); + if ((__u32)ruleno >= map->max_rules) { + dprintk(" bad ruleno %d\n", ruleno); + return 0; + } rule = map->rules[ruleno]; result_len = 0; @@ -488,7 +500,8 @@ int crush_do_rule(struct crush_map *map, /* * determine hierarchical context of force, if any. note * that this may or may not correspond to the specific types - * referenced by the crush rule. + * referenced by the crush rule. it will also only affect + * the first descent (TAKE). */ if (force >= 0 && force < map->max_devices && @@ -527,7 +540,8 @@ int crush_do_rule(struct crush_map *map, firstn = 1; case CRUSH_RULE_CHOOSE_LEAF_INDEP: case CRUSH_RULE_CHOOSE_INDEP: - BUG_ON(wsize == 0); + if (wsize == 0) + break; recurse_to_leaf = rule->steps[step].op == @@ -596,7 +610,9 @@ int crush_do_rule(struct crush_map *map, break; default: - BUG_ON(1); + dprintk(" unknown op %d at step %d\n", + curstep->op, step); + break; } } return result_len; diff --git a/net/ceph/crypto.c b/net/ceph/crypto.c index b780cb7947d..9da7fdd3cd8 100644 --- a/net/ceph/crypto.c +++ b/net/ceph/crypto.c @@ -466,6 +466,7 @@ void ceph_key_destroy(struct key *key) { struct ceph_crypto_key *ckey = key->payload.data; ceph_crypto_key_destroy(ckey); + kfree(ckey); } struct key_type key_type_ceph = { diff --git a/net/ceph/crypto.h b/net/ceph/crypto.h index 1919d1550d7..3572dc518bc 100644 --- a/net/ceph/crypto.h +++ b/net/ceph/crypto.h @@ -16,7 +16,8 @@ struct ceph_crypto_key { static inline void ceph_crypto_key_destroy(struct ceph_crypto_key *key) { - kfree(key->key); + if (key) + kfree(key->key); } extern int ceph_crypto_key_clone(struct ceph_crypto_key *dst, diff --git a/net/ceph/debugfs.c b/net/ceph/debugfs.c index 27d4ea315d1..680978d0044 100644 --- a/net/ceph/debugfs.c +++ b/net/ceph/debugfs.c @@ -189,6 +189,9 @@ int ceph_debugfs_client_init(struct ceph_client *client) snprintf(name, sizeof(name), "%pU.client%lld", &client->fsid, client->monc.auth->global_id); + dout("ceph_debugfs_client_init %p %s\n", client, name); + + BUG_ON(client->debugfs_dir); client->debugfs_dir = debugfs_create_dir(name, ceph_debugfs_dir); if (!client->debugfs_dir) goto out; @@ -234,6 +237,7 @@ int ceph_debugfs_client_init(struct ceph_client *client) void ceph_debugfs_client_cleanup(struct ceph_client *client) { + dout("ceph_debugfs_client_cleanup %p\n", client); debugfs_remove(client->debugfs_osdmap); debugfs_remove(client->debugfs_monmap); debugfs_remove(client->osdc.debugfs_file); diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index f0993af2ae4..ba1037ceb49 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -29,6 +29,74 @@ * the sender. */ +/* + * We track the state of the socket on a given connection using + * values defined below. The transition to a new socket state is + * handled by a function which verifies we aren't coming from an + * unexpected state. + * + * -------- + * | NEW* | transient initial state + * -------- + * | con_sock_state_init() + * v + * ---------- + * | CLOSED | initialized, but no socket (and no + * ---------- TCP connection) + * ^ \ + * | \ con_sock_state_connecting() + * | ---------------------- + * | \ + * + con_sock_state_closed() \ + * |+--------------------------- \ + * | \ \ \ + * | ----------- \ \ + * | | CLOSING | socket event; \ \ + * | ----------- await close \ \ + * | ^ \ | + * | | \ | + * | + con_sock_state_closing() \ | + * | / \ | | + * | / --------------- | | + * | / \ v v + * | / -------------- + * | / -----------------| CONNECTING | socket created, TCP + * | | / -------------- connect initiated + * | | | con_sock_state_connected() + * | | v + * ------------- + * | CONNECTED | TCP connection established + * ------------- + * + * State values for ceph_connection->sock_state; NEW is assumed to be 0. + */ + +#define CON_SOCK_STATE_NEW 0 /* -> CLOSED */ +#define CON_SOCK_STATE_CLOSED 1 /* -> CONNECTING */ +#define CON_SOCK_STATE_CONNECTING 2 /* -> CONNECTED or -> CLOSING */ +#define CON_SOCK_STATE_CONNECTED 3 /* -> CLOSING or -> CLOSED */ +#define CON_SOCK_STATE_CLOSING 4 /* -> CLOSED */ + +/* + * connection states + */ +#define CON_STATE_CLOSED 1 /* -> PREOPEN */ +#define CON_STATE_PREOPEN 2 /* -> CONNECTING, CLOSED */ +#define CON_STATE_CONNECTING 3 /* -> NEGOTIATING, CLOSED */ +#define CON_STATE_NEGOTIATING 4 /* -> OPEN, CLOSED */ +#define CON_STATE_OPEN 5 /* -> STANDBY, CLOSED */ +#define CON_STATE_STANDBY 6 /* -> PREOPEN, CLOSED */ + +/* + * ceph_connection flag bits + */ +#define CON_FLAG_LOSSYTX 0 /* we can close channel or drop + * messages on errors */ +#define CON_FLAG_KEEPALIVE_PENDING 1 /* we need to send a keepalive */ +#define CON_FLAG_WRITE_PENDING 2 /* we have data ready to send */ +#define CON_FLAG_SOCK_CLOSED 3 /* socket state changed to closed */ +#define CON_FLAG_BACKOFF 4 /* need to retry queuing delayed work */ + /* static tag bytes (protocol control messages) */ static char tag_msg = CEPH_MSGR_TAG_MSG; static char tag_ack = CEPH_MSGR_TAG_ACK; @@ -147,72 +215,130 @@ void ceph_msgr_flush(void) } EXPORT_SYMBOL(ceph_msgr_flush); +/* Connection socket state transition functions */ + +static void con_sock_state_init(struct ceph_connection *con) +{ + int old_state; + + old_state = atomic_xchg(&con->sock_state, CON_SOCK_STATE_CLOSED); + if (WARN_ON(old_state != CON_SOCK_STATE_NEW)) + printk("%s: unexpected old state %d\n", __func__, old_state); + dout("%s con %p sock %d -> %d\n", __func__, con, old_state, + CON_SOCK_STATE_CLOSED); +} + +static void con_sock_state_connecting(struct ceph_connection *con) +{ + int old_state; + + old_state = atomic_xchg(&con->sock_state, CON_SOCK_STATE_CONNECTING); + if (WARN_ON(old_state != CON_SOCK_STATE_CLOSED)) + printk("%s: unexpected old state %d\n", __func__, old_state); + dout("%s con %p sock %d -> %d\n", __func__, con, old_state, + CON_SOCK_STATE_CONNECTING); +} + +static void con_sock_state_connected(struct ceph_connection *con) +{ + int old_state; + + old_state = atomic_xchg(&con->sock_state, CON_SOCK_STATE_CONNECTED); + if (WARN_ON(old_state != CON_SOCK_STATE_CONNECTING)) + printk("%s: unexpected old state %d\n", __func__, old_state); + dout("%s con %p sock %d -> %d\n", __func__, con, old_state, + CON_SOCK_STATE_CONNECTED); +} + +static void con_sock_state_closing(struct ceph_connection *con) +{ + int old_state; + + old_state = atomic_xchg(&con->sock_state, CON_SOCK_STATE_CLOSING); + if (WARN_ON(old_state != CON_SOCK_STATE_CONNECTING && + old_state != CON_SOCK_STATE_CONNECTED && + old_state != CON_SOCK_STATE_CLOSING)) + printk("%s: unexpected old state %d\n", __func__, old_state); + dout("%s con %p sock %d -> %d\n", __func__, con, old_state, + CON_SOCK_STATE_CLOSING); +} + +static void con_sock_state_closed(struct ceph_connection *con) +{ + int old_state; + + old_state = atomic_xchg(&con->sock_state, CON_SOCK_STATE_CLOSED); + if (WARN_ON(old_state != CON_SOCK_STATE_CONNECTED && + old_state != CON_SOCK_STATE_CLOSING && + old_state != CON_SOCK_STATE_CONNECTING && + old_state != CON_SOCK_STATE_CLOSED)) + printk("%s: unexpected old state %d\n", __func__, old_state); + dout("%s con %p sock %d -> %d\n", __func__, con, old_state, + CON_SOCK_STATE_CLOSED); +} /* * socket callback functions */ /* data available on socket, or listen socket received a connect */ -static void ceph_data_ready(struct sock *sk, int count_unused) +static void ceph_sock_data_ready(struct sock *sk, int count_unused) { struct ceph_connection *con = sk->sk_user_data; + if (atomic_read(&con->msgr->stopping)) { + return; + } if (sk->sk_state != TCP_CLOSE_WAIT) { - dout("ceph_data_ready on %p state = %lu, queueing work\n", + dout("%s on %p state = %lu, queueing work\n", __func__, con, con->state); queue_con(con); } } /* socket has buffer space for writing */ -static void ceph_write_space(struct sock *sk) +static void ceph_sock_write_space(struct sock *sk) { struct ceph_connection *con = sk->sk_user_data; /* only queue to workqueue if there is data we want to write, * and there is sufficient space in the socket buffer to accept - * more data. clear SOCK_NOSPACE so that ceph_write_space() + * more data. clear SOCK_NOSPACE so that ceph_sock_write_space() * doesn't get called again until try_write() fills the socket * buffer. See net/ipv4/tcp_input.c:tcp_check_space() * and net/core/stream.c:sk_stream_write_space(). */ - if (test_bit(WRITE_PENDING, &con->state)) { + if (test_bit(CON_FLAG_WRITE_PENDING, &con->flags)) { if (sk_stream_wspace(sk) >= sk_stream_min_wspace(sk)) { - dout("ceph_write_space %p queueing write work\n", con); + dout("%s %p queueing write work\n", __func__, con); clear_bit(SOCK_NOSPACE, &sk->sk_socket->flags); queue_con(con); } } else { - dout("ceph_write_space %p nothing to write\n", con); + dout("%s %p nothing to write\n", __func__, con); } } /* socket's state has changed */ -static void ceph_state_change(struct sock *sk) +static void ceph_sock_state_change(struct sock *sk) { struct ceph_connection *con = sk->sk_user_data; - dout("ceph_state_change %p state = %lu sk_state = %u\n", + dout("%s %p state = %lu sk_state = %u\n", __func__, con, con->state, sk->sk_state); - if (test_bit(CLOSED, &con->state)) - return; - switch (sk->sk_state) { case TCP_CLOSE: - dout("ceph_state_change TCP_CLOSE\n"); + dout("%s TCP_CLOSE\n", __func__); case TCP_CLOSE_WAIT: - dout("ceph_state_change TCP_CLOSE_WAIT\n"); - if (test_and_set_bit(SOCK_CLOSED, &con->state) == 0) { - if (test_bit(CONNECTING, &con->state)) - con->error_msg = "connection failed"; - else - con->error_msg = "socket closed"; - queue_con(con); - } + dout("%s TCP_CLOSE_WAIT\n", __func__); + con_sock_state_closing(con); + set_bit(CON_FLAG_SOCK_CLOSED, &con->flags); + queue_con(con); break; case TCP_ESTABLISHED: - dout("ceph_state_change TCP_ESTABLISHED\n"); + dout("%s TCP_ESTABLISHED\n", __func__); + con_sock_state_connected(con); queue_con(con); break; default: /* Everything else is uninteresting */ @@ -228,9 +354,9 @@ static void set_sock_callbacks(struct socket *sock, { struct sock *sk = sock->sk; sk->sk_user_data = con; - sk->sk_data_ready = ceph_data_ready; - sk->sk_write_space = ceph_write_space; - sk->sk_state_change = ceph_state_change; + sk->sk_data_ready = ceph_sock_data_ready; + sk->sk_write_space = ceph_sock_write_space; + sk->sk_state_change = ceph_sock_state_change; } @@ -262,6 +388,7 @@ static int ceph_tcp_connect(struct ceph_connection *con) dout("connect %s\n", ceph_pr_addr(&con->peer_addr.in_addr)); + con_sock_state_connecting(con); ret = sock->ops->connect(sock, (struct sockaddr *)paddr, sizeof(*paddr), O_NONBLOCK); if (ret == -EINPROGRESS) { @@ -277,7 +404,6 @@ static int ceph_tcp_connect(struct ceph_connection *con) return ret; } con->sock = sock; - return 0; } @@ -333,16 +459,24 @@ static int ceph_tcp_sendpage(struct socket *sock, struct page *page, */ static int con_close_socket(struct ceph_connection *con) { - int rc; + int rc = 0; dout("con_close_socket on %p sock %p\n", con, con->sock); - if (!con->sock) - return 0; - set_bit(SOCK_CLOSED, &con->state); - rc = con->sock->ops->shutdown(con->sock, SHUT_RDWR); - sock_release(con->sock); - con->sock = NULL; - clear_bit(SOCK_CLOSED, &con->state); + if (con->sock) { + rc = con->sock->ops->shutdown(con->sock, SHUT_RDWR); + sock_release(con->sock); + con->sock = NULL; + } + + /* + * Forcibly clear the SOCK_CLOSED flag. It gets set + * independent of the connection mutex, and we could have + * received a socket close event before we had the chance to + * shut the socket down. + */ + clear_bit(CON_FLAG_SOCK_CLOSED, &con->flags); + + con_sock_state_closed(con); return rc; } @@ -353,6 +487,10 @@ static int con_close_socket(struct ceph_connection *con) static void ceph_msg_remove(struct ceph_msg *msg) { list_del_init(&msg->list_head); + BUG_ON(msg->con == NULL); + msg->con->ops->put(msg->con); + msg->con = NULL; + ceph_msg_put(msg); } static void ceph_msg_remove_list(struct list_head *head) @@ -368,12 +506,16 @@ static void reset_connection(struct ceph_connection *con) { /* reset connection, out_queue, msg_ and connect_seq */ /* discard existing out_queue and msg_seq */ + dout("reset_connection %p\n", con); ceph_msg_remove_list(&con->out_queue); ceph_msg_remove_list(&con->out_sent); if (con->in_msg) { + BUG_ON(con->in_msg->con != con); + con->in_msg->con = NULL; ceph_msg_put(con->in_msg); con->in_msg = NULL; + con->ops->put(con); } con->connect_seq = 0; @@ -391,32 +533,44 @@ static void reset_connection(struct ceph_connection *con) */ void ceph_con_close(struct ceph_connection *con) { + mutex_lock(&con->mutex); dout("con_close %p peer %s\n", con, ceph_pr_addr(&con->peer_addr.in_addr)); - set_bit(CLOSED, &con->state); /* in case there's queued work */ - clear_bit(STANDBY, &con->state); /* avoid connect_seq bump */ - clear_bit(LOSSYTX, &con->state); /* so we retry next connect */ - clear_bit(KEEPALIVE_PENDING, &con->state); - clear_bit(WRITE_PENDING, &con->state); - mutex_lock(&con->mutex); + con->state = CON_STATE_CLOSED; + + clear_bit(CON_FLAG_LOSSYTX, &con->flags); /* so we retry next connect */ + clear_bit(CON_FLAG_KEEPALIVE_PENDING, &con->flags); + clear_bit(CON_FLAG_WRITE_PENDING, &con->flags); + clear_bit(CON_FLAG_KEEPALIVE_PENDING, &con->flags); + clear_bit(CON_FLAG_BACKOFF, &con->flags); + reset_connection(con); con->peer_global_seq = 0; cancel_delayed_work(&con->work); + con_close_socket(con); mutex_unlock(&con->mutex); - queue_con(con); } EXPORT_SYMBOL(ceph_con_close); /* * Reopen a closed connection, with a new peer address. */ -void ceph_con_open(struct ceph_connection *con, struct ceph_entity_addr *addr) +void ceph_con_open(struct ceph_connection *con, + __u8 entity_type, __u64 entity_num, + struct ceph_entity_addr *addr) { + mutex_lock(&con->mutex); dout("con_open %p %s\n", con, ceph_pr_addr(&addr->in_addr)); - set_bit(OPENING, &con->state); - clear_bit(CLOSED, &con->state); + + WARN_ON(con->state != CON_STATE_CLOSED); + con->state = CON_STATE_PREOPEN; + + con->peer_name.type = (__u8) entity_type; + con->peer_name.num = cpu_to_le64(entity_num); + memcpy(&con->peer_addr, addr, sizeof(*addr)); con->delay = 0; /* reset backoff memory */ + mutex_unlock(&con->mutex); queue_con(con); } EXPORT_SYMBOL(ceph_con_open); @@ -429,43 +583,27 @@ bool ceph_con_opened(struct ceph_connection *con) return con->connect_seq > 0; } -/* - * generic get/put - */ -struct ceph_connection *ceph_con_get(struct ceph_connection *con) -{ - int nref = __atomic_add_unless(&con->nref, 1, 0); - - dout("con_get %p nref = %d -> %d\n", con, nref, nref + 1); - - return nref ? con : NULL; -} - -void ceph_con_put(struct ceph_connection *con) -{ - int nref = atomic_dec_return(&con->nref); - - BUG_ON(nref < 0); - if (nref == 0) { - BUG_ON(con->sock); - kfree(con); - } - dout("con_put %p nref = %d -> %d\n", con, nref + 1, nref); -} - /* * initialize a new connection. */ -void ceph_con_init(struct ceph_messenger *msgr, struct ceph_connection *con) +void ceph_con_init(struct ceph_connection *con, void *private, + const struct ceph_connection_operations *ops, + struct ceph_messenger *msgr) { dout("con_init %p\n", con); memset(con, 0, sizeof(*con)); - atomic_set(&con->nref, 1); + con->private = private; + con->ops = ops; con->msgr = msgr; + + con_sock_state_init(con); + mutex_init(&con->mutex); INIT_LIST_HEAD(&con->out_queue); INIT_LIST_HEAD(&con->out_sent); INIT_DELAYED_WORK(&con->work, con_work); + + con->state = CON_STATE_CLOSED; } EXPORT_SYMBOL(ceph_con_init); @@ -486,14 +624,14 @@ static u32 get_global_seq(struct ceph_messenger *msgr, u32 gt) return ret; } -static void ceph_con_out_kvec_reset(struct ceph_connection *con) +static void con_out_kvec_reset(struct ceph_connection *con) { con->out_kvec_left = 0; con->out_kvec_bytes = 0; con->out_kvec_cur = &con->out_kvec[0]; } -static void ceph_con_out_kvec_add(struct ceph_connection *con, +static void con_out_kvec_add(struct ceph_connection *con, size_t size, void *data) { int index; @@ -507,6 +645,53 @@ static void ceph_con_out_kvec_add(struct ceph_connection *con, con->out_kvec_bytes += size; } +#ifdef CONFIG_BLOCK +static void init_bio_iter(struct bio *bio, struct bio **iter, int *seg) +{ + if (!bio) { + *iter = NULL; + *seg = 0; + return; + } + *iter = bio; + *seg = bio->bi_idx; +} + +static void iter_bio_next(struct bio **bio_iter, int *seg) +{ + if (*bio_iter == NULL) + return; + + BUG_ON(*seg >= (*bio_iter)->bi_vcnt); + + (*seg)++; + if (*seg == (*bio_iter)->bi_vcnt) + init_bio_iter((*bio_iter)->bi_next, bio_iter, seg); +} +#endif + +static void prepare_write_message_data(struct ceph_connection *con) +{ + struct ceph_msg *msg = con->out_msg; + + BUG_ON(!msg); + BUG_ON(!msg->hdr.data_len); + + /* initialize page iterator */ + con->out_msg_pos.page = 0; + if (msg->pages) + con->out_msg_pos.page_pos = msg->page_alignment; + else + con->out_msg_pos.page_pos = 0; +#ifdef CONFIG_BLOCK + if (msg->bio) + init_bio_iter(msg->bio, &msg->bio_iter, &msg->bio_seg); +#endif + con->out_msg_pos.data_pos = 0; + con->out_msg_pos.did_page_crc = false; + con->out_more = 1; /* data + footer will follow */ +} + /* * Prepare footer for currently outgoing message, and finish things * off. Assumes out_kvec* are already valid.. we just add on to the end. @@ -516,6 +701,8 @@ static void prepare_write_message_footer(struct ceph_connection *con) struct ceph_msg *m = con->out_msg; int v = con->out_kvec_left; + m->footer.flags |= CEPH_MSG_FOOTER_COMPLETE; + dout("prepare_write_message_footer %p\n", con); con->out_kvec_is_msg = true; con->out_kvec[v].iov_base = &m->footer; @@ -534,7 +721,7 @@ static void prepare_write_message(struct ceph_connection *con) struct ceph_msg *m; u32 crc; - ceph_con_out_kvec_reset(con); + con_out_kvec_reset(con); con->out_kvec_is_msg = true; con->out_msg_done = false; @@ -542,14 +729,16 @@ static void prepare_write_message(struct ceph_connection *con) * TCP packet that's a good thing. */ if (con->in_seq > con->in_seq_acked) { con->in_seq_acked = con->in_seq; - ceph_con_out_kvec_add(con, sizeof (tag_ack), &tag_ack); + con_out_kvec_add(con, sizeof (tag_ack), &tag_ack); con->out_temp_ack = cpu_to_le64(con->in_seq_acked); - ceph_con_out_kvec_add(con, sizeof (con->out_temp_ack), + con_out_kvec_add(con, sizeof (con->out_temp_ack), &con->out_temp_ack); } + BUG_ON(list_empty(&con->out_queue)); m = list_first_entry(&con->out_queue, struct ceph_msg, list_head); con->out_msg = m; + BUG_ON(m->con != con); /* put message on sent list */ ceph_msg_get(m); @@ -572,18 +761,18 @@ static void prepare_write_message(struct ceph_connection *con) BUG_ON(le32_to_cpu(m->hdr.front_len) != m->front.iov_len); /* tag + hdr + front + middle */ - ceph_con_out_kvec_add(con, sizeof (tag_msg), &tag_msg); - ceph_con_out_kvec_add(con, sizeof (m->hdr), &m->hdr); - ceph_con_out_kvec_add(con, m->front.iov_len, m->front.iov_base); + con_out_kvec_add(con, sizeof (tag_msg), &tag_msg); + con_out_kvec_add(con, sizeof (m->hdr), &m->hdr); + con_out_kvec_add(con, m->front.iov_len, m->front.iov_base); if (m->middle) - ceph_con_out_kvec_add(con, m->middle->vec.iov_len, + con_out_kvec_add(con, m->middle->vec.iov_len, m->middle->vec.iov_base); /* fill in crc (except data pages), footer */ crc = crc32c(0, &m->hdr, offsetof(struct ceph_msg_header, crc)); con->out_msg->hdr.crc = cpu_to_le32(crc); - con->out_msg->footer.flags = CEPH_MSG_FOOTER_COMPLETE; + con->out_msg->footer.flags = 0; crc = crc32c(0, m->front.iov_base, m->front.iov_len); con->out_msg->footer.front_crc = cpu_to_le32(crc); @@ -593,28 +782,19 @@ static void prepare_write_message(struct ceph_connection *con) con->out_msg->footer.middle_crc = cpu_to_le32(crc); } else con->out_msg->footer.middle_crc = 0; - con->out_msg->footer.data_crc = 0; - dout("prepare_write_message front_crc %u data_crc %u\n", + dout("%s front_crc %u middle_crc %u\n", __func__, le32_to_cpu(con->out_msg->footer.front_crc), le32_to_cpu(con->out_msg->footer.middle_crc)); /* is there a data payload? */ - if (le32_to_cpu(m->hdr.data_len) > 0) { - /* initialize page iterator */ - con->out_msg_pos.page = 0; - if (m->pages) - con->out_msg_pos.page_pos = m->page_alignment; - else - con->out_msg_pos.page_pos = 0; - con->out_msg_pos.data_pos = 0; - con->out_msg_pos.did_page_crc = false; - con->out_more = 1; /* data + footer will follow */ - } else { + con->out_msg->footer.data_crc = 0; + if (m->hdr.data_len) + prepare_write_message_data(con); + else /* no, queue up footer too and be done */ prepare_write_message_footer(con); - } - set_bit(WRITE_PENDING, &con->state); + set_bit(CON_FLAG_WRITE_PENDING, &con->flags); } /* @@ -626,16 +806,16 @@ static void prepare_write_ack(struct ceph_connection *con) con->in_seq_acked, con->in_seq); con->in_seq_acked = con->in_seq; - ceph_con_out_kvec_reset(con); + con_out_kvec_reset(con); - ceph_con_out_kvec_add(con, sizeof (tag_ack), &tag_ack); + con_out_kvec_add(con, sizeof (tag_ack), &tag_ack); con->out_temp_ack = cpu_to_le64(con->in_seq_acked); - ceph_con_out_kvec_add(con, sizeof (con->out_temp_ack), + con_out_kvec_add(con, sizeof (con->out_temp_ack), &con->out_temp_ack); con->out_more = 1; /* more will follow.. eventually.. */ - set_bit(WRITE_PENDING, &con->state); + set_bit(CON_FLAG_WRITE_PENDING, &con->flags); } /* @@ -644,63 +824,60 @@ static void prepare_write_ack(struct ceph_connection *con) static void prepare_write_keepalive(struct ceph_connection *con) { dout("prepare_write_keepalive %p\n", con); - ceph_con_out_kvec_reset(con); - ceph_con_out_kvec_add(con, sizeof (tag_keepalive), &tag_keepalive); - set_bit(WRITE_PENDING, &con->state); + con_out_kvec_reset(con); + con_out_kvec_add(con, sizeof (tag_keepalive), &tag_keepalive); + set_bit(CON_FLAG_WRITE_PENDING, &con->flags); } /* * Connection negotiation. */ -static int prepare_connect_authorizer(struct ceph_connection *con) +static struct ceph_auth_handshake *get_connect_authorizer(struct ceph_connection *con, + int *auth_proto) { - void *auth_buf; - int auth_len = 0; - int auth_protocol = 0; + struct ceph_auth_handshake *auth; + if (!con->ops->get_authorizer) { + con->out_connect.authorizer_protocol = CEPH_AUTH_UNKNOWN; + con->out_connect.authorizer_len = 0; + return NULL; + } + + /* Can't hold the mutex while getting authorizer */ mutex_unlock(&con->mutex); - if (con->ops->get_authorizer) - con->ops->get_authorizer(con, &auth_buf, &auth_len, - &auth_protocol, &con->auth_reply_buf, - &con->auth_reply_buf_len, - con->auth_retry); + auth = con->ops->get_authorizer(con, auth_proto, con->auth_retry); mutex_lock(&con->mutex); - if (test_bit(CLOSED, &con->state) || - test_bit(OPENING, &con->state)) - return -EAGAIN; - - con->out_connect.authorizer_protocol = cpu_to_le32(auth_protocol); - con->out_connect.authorizer_len = cpu_to_le32(auth_len); + if (IS_ERR(auth)) + return auth; + if (con->state != CON_STATE_NEGOTIATING) + return ERR_PTR(-EAGAIN); - if (auth_len) - ceph_con_out_kvec_add(con, auth_len, auth_buf); - - return 0; + con->auth_reply_buf = auth->authorizer_reply_buf; + con->auth_reply_buf_len = auth->authorizer_reply_buf_len; + return auth; } /* * We connected to a peer and are saying hello. */ -static void prepare_write_banner(struct ceph_messenger *msgr, - struct ceph_connection *con) +static void prepare_write_banner(struct ceph_connection *con) { - ceph_con_out_kvec_reset(con); - ceph_con_out_kvec_add(con, strlen(CEPH_BANNER), CEPH_BANNER); - ceph_con_out_kvec_add(con, sizeof (msgr->my_enc_addr), - &msgr->my_enc_addr); + con_out_kvec_add(con, strlen(CEPH_BANNER), CEPH_BANNER); + con_out_kvec_add(con, sizeof (con->msgr->my_enc_addr), + &con->msgr->my_enc_addr); con->out_more = 0; - set_bit(WRITE_PENDING, &con->state); + set_bit(CON_FLAG_WRITE_PENDING, &con->flags); } -static int prepare_write_connect(struct ceph_messenger *msgr, - struct ceph_connection *con, - int include_banner) +static int prepare_write_connect(struct ceph_connection *con) { unsigned global_seq = get_global_seq(con->msgr, 0); int proto; + int auth_proto; + struct ceph_auth_handshake *auth; switch (con->peer_name.type) { case CEPH_ENTITY_TYPE_MON: @@ -719,23 +896,32 @@ static int prepare_write_connect(struct ceph_messenger *msgr, dout("prepare_write_connect %p cseq=%d gseq=%d proto=%d\n", con, con->connect_seq, global_seq, proto); - con->out_connect.features = cpu_to_le64(msgr->supported_features); + con->out_connect.features = cpu_to_le64(con->msgr->supported_features); con->out_connect.host_type = cpu_to_le32(CEPH_ENTITY_TYPE_CLIENT); con->out_connect.connect_seq = cpu_to_le32(con->connect_seq); con->out_connect.global_seq = cpu_to_le32(global_seq); con->out_connect.protocol_version = cpu_to_le32(proto); con->out_connect.flags = 0; - if (include_banner) - prepare_write_banner(msgr, con); - else - ceph_con_out_kvec_reset(con); - ceph_con_out_kvec_add(con, sizeof (con->out_connect), &con->out_connect); + auth_proto = CEPH_AUTH_UNKNOWN; + auth = get_connect_authorizer(con, &auth_proto); + if (IS_ERR(auth)) + return PTR_ERR(auth); + + con->out_connect.authorizer_protocol = cpu_to_le32(auth_proto); + con->out_connect.authorizer_len = auth ? + cpu_to_le32(auth->authorizer_buf_len) : 0; + + con_out_kvec_add(con, sizeof (con->out_connect), + &con->out_connect); + if (auth && auth->authorizer_buf_len) + con_out_kvec_add(con, auth->authorizer_buf_len, + auth->authorizer_buf); con->out_more = 0; - set_bit(WRITE_PENDING, &con->state); + set_bit(CON_FLAG_WRITE_PENDING, &con->flags); - return prepare_connect_authorizer(con); + return 0; } /* @@ -781,30 +967,34 @@ static int write_partial_kvec(struct ceph_connection *con) return ret; /* done! */ } -#ifdef CONFIG_BLOCK -static void init_bio_iter(struct bio *bio, struct bio **iter, int *seg) +static void out_msg_pos_next(struct ceph_connection *con, struct page *page, + size_t len, size_t sent, bool in_trail) { - if (!bio) { - *iter = NULL; - *seg = 0; - return; - } - *iter = bio; - *seg = bio->bi_idx; -} + struct ceph_msg *msg = con->out_msg; -static void iter_bio_next(struct bio **bio_iter, int *seg) -{ - if (*bio_iter == NULL) - return; + BUG_ON(!msg); + BUG_ON(!sent); - BUG_ON(*seg >= (*bio_iter)->bi_vcnt); + con->out_msg_pos.data_pos += sent; + con->out_msg_pos.page_pos += sent; + if (sent < len) + return; - (*seg)++; - if (*seg == (*bio_iter)->bi_vcnt) - init_bio_iter((*bio_iter)->bi_next, bio_iter, seg); -} + BUG_ON(sent != len); + con->out_msg_pos.page_pos = 0; + con->out_msg_pos.page++; + con->out_msg_pos.did_page_crc = false; + if (in_trail) + list_move_tail(&page->lru, + &msg->trail->head); + else if (msg->pagelist) + list_move_tail(&page->lru, + &msg->pagelist->head); +#ifdef CONFIG_BLOCK + else if (msg->bio) + iter_bio_next(&msg->bio_iter, &msg->bio_seg); #endif +} /* * Write as much message data payload as we can. If we finish, queue @@ -821,41 +1011,36 @@ static int write_partial_msg_pages(struct ceph_connection *con) bool do_datacrc = !con->msgr->nocrc; int ret; int total_max_write; - int in_trail = 0; - size_t trail_len = (msg->trail ? msg->trail->length : 0); + bool in_trail = false; + const size_t trail_len = (msg->trail ? msg->trail->length : 0); + const size_t trail_off = data_len - trail_len; dout("write_partial_msg_pages %p msg %p page %d/%d offset %d\n", - con, con->out_msg, con->out_msg_pos.page, con->out_msg->nr_pages, + con, msg, con->out_msg_pos.page, msg->nr_pages, con->out_msg_pos.page_pos); -#ifdef CONFIG_BLOCK - if (msg->bio && !msg->bio_iter) - init_bio_iter(msg->bio, &msg->bio_iter, &msg->bio_seg); -#endif - + /* + * Iterate through each page that contains data to be + * written, and send as much as possible for each. + * + * If we are calculating the data crc (the default), we will + * need to map the page. If we have no pages, they have + * been revoked, so use the zero page. + */ while (data_len > con->out_msg_pos.data_pos) { struct page *page = NULL; int max_write = PAGE_SIZE; int bio_offset = 0; - total_max_write = data_len - trail_len - - con->out_msg_pos.data_pos; - - /* - * if we are calculating the data crc (the default), we need - * to map the page. if our pages[] has been revoked, use the - * zero page. - */ - - /* have we reached the trail part of the data? */ - if (con->out_msg_pos.data_pos >= data_len - trail_len) { - in_trail = 1; + in_trail = in_trail || con->out_msg_pos.data_pos >= trail_off; + if (!in_trail) + total_max_write = trail_off - con->out_msg_pos.data_pos; + if (in_trail) { total_max_write = data_len - con->out_msg_pos.data_pos; page = list_first_entry(&msg->trail->head, struct page, lru); - max_write = PAGE_SIZE; } else if (msg->pages) { page = msg->pages[con->out_msg_pos.page]; } else if (msg->pagelist) { @@ -878,52 +1063,32 @@ static int write_partial_msg_pages(struct ceph_connection *con) if (do_datacrc && !con->out_msg_pos.did_page_crc) { void *base; - u32 crc; - u32 tmpcrc = le32_to_cpu(con->out_msg->footer.data_crc); + u32 crc = le32_to_cpu(msg->footer.data_crc); char *kaddr; kaddr = kmap(page); BUG_ON(kaddr == NULL); base = kaddr + con->out_msg_pos.page_pos + bio_offset; - crc = crc32c(tmpcrc, base, len); - con->out_msg->footer.data_crc = cpu_to_le32(crc); + crc = crc32c(crc, base, len); + kunmap(page); + msg->footer.data_crc = cpu_to_le32(crc); con->out_msg_pos.did_page_crc = true; } ret = ceph_tcp_sendpage(con->sock, page, con->out_msg_pos.page_pos + bio_offset, len, 1); - - if (do_datacrc) - kunmap(page); - if (ret <= 0) goto out; - con->out_msg_pos.data_pos += ret; - con->out_msg_pos.page_pos += ret; - if (ret == len) { - con->out_msg_pos.page_pos = 0; - con->out_msg_pos.page++; - con->out_msg_pos.did_page_crc = false; - if (in_trail) - list_move_tail(&page->lru, - &msg->trail->head); - else if (msg->pagelist) - list_move_tail(&page->lru, - &msg->pagelist->head); -#ifdef CONFIG_BLOCK - else if (msg->bio) - iter_bio_next(&msg->bio_iter, &msg->bio_seg); -#endif - } + out_msg_pos_next(con, page, len, (size_t) ret, in_trail); } dout("write_partial_msg_pages %p msg %p done\n", con, msg); /* prepare and queue up footer, too */ if (!do_datacrc) - con->out_msg->footer.flags |= CEPH_MSG_FOOTER_NOCRC; - ceph_con_out_kvec_reset(con); + msg->footer.flags |= CEPH_MSG_FOOTER_NOCRC; + con_out_kvec_reset(con); prepare_write_message_footer(con); ret = 1; out: @@ -992,11 +1157,10 @@ static int prepare_read_message(struct ceph_connection *con) static int read_partial(struct ceph_connection *con, - int *to, int size, void *object) + int end, int size, void *object) { - *to += size; - while (con->in_base_pos < *to) { - int left = *to - con->in_base_pos; + while (con->in_base_pos < end) { + int left = end - con->in_base_pos; int have = size - left; int ret = ceph_tcp_recvmsg(con->sock, object + have, left); if (ret <= 0) @@ -1012,37 +1176,52 @@ static int read_partial(struct ceph_connection *con, */ static int read_partial_banner(struct ceph_connection *con) { - int ret, to = 0; + int size; + int end; + int ret; dout("read_partial_banner %p at %d\n", con, con->in_base_pos); /* peer's banner */ - ret = read_partial(con, &to, strlen(CEPH_BANNER), con->in_banner); + size = strlen(CEPH_BANNER); + end = size; + ret = read_partial(con, end, size, con->in_banner); if (ret <= 0) goto out; - ret = read_partial(con, &to, sizeof(con->actual_peer_addr), - &con->actual_peer_addr); + + size = sizeof (con->actual_peer_addr); + end += size; + ret = read_partial(con, end, size, &con->actual_peer_addr); if (ret <= 0) goto out; - ret = read_partial(con, &to, sizeof(con->peer_addr_for_me), - &con->peer_addr_for_me); + + size = sizeof (con->peer_addr_for_me); + end += size; + ret = read_partial(con, end, size, &con->peer_addr_for_me); if (ret <= 0) goto out; + out: return ret; } static int read_partial_connect(struct ceph_connection *con) { - int ret, to = 0; + int size; + int end; + int ret; dout("read_partial_connect %p at %d\n", con, con->in_base_pos); - ret = read_partial(con, &to, sizeof(con->in_reply), &con->in_reply); + size = sizeof (con->in_reply); + end = size; + ret = read_partial(con, end, size, &con->in_reply); if (ret <= 0) goto out; - ret = read_partial(con, &to, le32_to_cpu(con->in_reply.authorizer_len), - con->auth_reply_buf); + + size = le32_to_cpu(con->in_reply.authorizer_len); + end += size; + ret = read_partial(con, end, size, con->auth_reply_buf); if (ret <= 0) goto out; @@ -1321,22 +1500,9 @@ static int process_banner(struct ceph_connection *con) ceph_pr_addr(&con->msgr->inst.addr.in_addr)); } - set_bit(NEGOTIATING, &con->state); - prepare_read_connect(con); return 0; } -static void fail_protocol(struct ceph_connection *con) -{ - reset_connection(con); - set_bit(CLOSED, &con->state); /* in case there's queued work */ - - mutex_unlock(&con->mutex); - if (con->ops->bad_proto) - con->ops->bad_proto(con); - mutex_lock(&con->mutex); -} - static int process_connect(struct ceph_connection *con) { u64 sup_feat = con->msgr->supported_features; @@ -1354,7 +1520,7 @@ static int process_connect(struct ceph_connection *con) ceph_pr_addr(&con->peer_addr.in_addr), sup_feat, server_feat, server_feat & ~sup_feat); con->error_msg = "missing required protocol features"; - fail_protocol(con); + reset_connection(con); return -1; case CEPH_MSGR_TAG_BADPROTOVER: @@ -1365,7 +1531,7 @@ static int process_connect(struct ceph_connection *con) le32_to_cpu(con->out_connect.protocol_version), le32_to_cpu(con->in_reply.protocol_version)); con->error_msg = "protocol version mismatch"; - fail_protocol(con); + reset_connection(con); return -1; case CEPH_MSGR_TAG_BADAUTHORIZER: @@ -1377,7 +1543,8 @@ static int process_connect(struct ceph_connection *con) return -1; } con->auth_retry = 1; - ret = prepare_write_connect(con->msgr, con, 0); + con_out_kvec_reset(con); + ret = prepare_write_connect(con); if (ret < 0) return ret; prepare_read_connect(con); @@ -1392,12 +1559,15 @@ static int process_connect(struct ceph_connection *con) * dropped messages. */ dout("process_connect got RESET peer seq %u\n", - le32_to_cpu(con->in_connect.connect_seq)); + le32_to_cpu(con->in_reply.connect_seq)); pr_err("%s%lld %s connection reset\n", ENTITY_NAME(con->peer_name), ceph_pr_addr(&con->peer_addr.in_addr)); reset_connection(con); - prepare_write_connect(con->msgr, con, 0); + con_out_kvec_reset(con); + ret = prepare_write_connect(con); + if (ret < 0) + return ret; prepare_read_connect(con); /* Tell ceph about it. */ @@ -1406,8 +1576,7 @@ static int process_connect(struct ceph_connection *con) if (con->ops->peer_reset) con->ops->peer_reset(con); mutex_lock(&con->mutex); - if (test_bit(CLOSED, &con->state) || - test_bit(OPENING, &con->state)) + if (con->state != CON_STATE_NEGOTIATING) return -EAGAIN; break; @@ -1416,11 +1585,14 @@ static int process_connect(struct ceph_connection *con) * If we sent a smaller connect_seq than the peer has, try * again with a larger value. */ - dout("process_connect got RETRY my seq = %u, peer_seq = %u\n", + dout("process_connect got RETRY_SESSION my seq %u, peer %u\n", le32_to_cpu(con->out_connect.connect_seq), - le32_to_cpu(con->in_connect.connect_seq)); - con->connect_seq = le32_to_cpu(con->in_connect.connect_seq); - prepare_write_connect(con->msgr, con, 0); + le32_to_cpu(con->in_reply.connect_seq)); + con->connect_seq = le32_to_cpu(con->in_reply.connect_seq); + con_out_kvec_reset(con); + ret = prepare_write_connect(con); + if (ret < 0) + return ret; prepare_read_connect(con); break; @@ -1431,10 +1603,13 @@ static int process_connect(struct ceph_connection *con) */ dout("process_connect got RETRY_GLOBAL my %u peer_gseq %u\n", con->peer_global_seq, - le32_to_cpu(con->in_connect.global_seq)); + le32_to_cpu(con->in_reply.global_seq)); get_global_seq(con->msgr, - le32_to_cpu(con->in_connect.global_seq)); - prepare_write_connect(con->msgr, con, 0); + le32_to_cpu(con->in_reply.global_seq)); + con_out_kvec_reset(con); + ret = prepare_write_connect(con); + if (ret < 0) + return ret; prepare_read_connect(con); break; @@ -1446,10 +1621,13 @@ static int process_connect(struct ceph_connection *con) ceph_pr_addr(&con->peer_addr.in_addr), req_feat, server_feat, req_feat & ~server_feat); con->error_msg = "missing required protocol features"; - fail_protocol(con); + reset_connection(con); return -1; } - clear_bit(CONNECTING, &con->state); + + WARN_ON(con->state != CON_STATE_NEGOTIATING); + con->state = CON_STATE_OPEN; + con->peer_global_seq = le32_to_cpu(con->in_reply.global_seq); con->connect_seq++; con->peer_features = server_feat; @@ -1461,7 +1639,9 @@ static int process_connect(struct ceph_connection *con) le32_to_cpu(con->in_reply.connect_seq)); if (con->in_reply.flags & CEPH_MSG_CONNECT_LOSSY) - set_bit(LOSSYTX, &con->state); + set_bit(CON_FLAG_LOSSYTX, &con->flags); + + con->delay = 0; /* reset backoff memory */ prepare_read_tag(con); break; @@ -1491,10 +1671,10 @@ static int process_connect(struct ceph_connection *con) */ static int read_partial_ack(struct ceph_connection *con) { - int to = 0; + int size = sizeof (con->in_temp_ack); + int end = size; - return read_partial(con, &to, sizeof(con->in_temp_ack), - &con->in_temp_ack); + return read_partial(con, end, size, &con->in_temp_ack); } @@ -1547,10 +1727,7 @@ static int read_partial_message_section(struct ceph_connection *con, return 1; } -static struct ceph_msg *ceph_alloc_msg(struct ceph_connection *con, - struct ceph_msg_header *hdr, - int *skip); - +static int ceph_con_in_msg_alloc(struct ceph_connection *con, int *skip); static int read_partial_message_pages(struct ceph_connection *con, struct page **pages, @@ -1593,9 +1770,6 @@ static int read_partial_message_bio(struct ceph_connection *con, void *p; int ret, left; - if (IS_ERR(bv)) - return PTR_ERR(bv); - left = min((int)(data_len - con->in_msg_pos.data_pos), (int)(bv->bv_len - con->in_msg_pos.page_pos)); @@ -1627,26 +1801,22 @@ static int read_partial_message_bio(struct ceph_connection *con, static int read_partial_message(struct ceph_connection *con) { struct ceph_msg *m = con->in_msg; + int size; + int end; int ret; - int to, left; unsigned front_len, middle_len, data_len; bool do_datacrc = !con->msgr->nocrc; - int skip; u64 seq; u32 crc; dout("read_partial_message con %p msg %p\n", con, m); /* header */ - while (con->in_base_pos < sizeof(con->in_hdr)) { - left = sizeof(con->in_hdr) - con->in_base_pos; - ret = ceph_tcp_recvmsg(con->sock, - (char *)&con->in_hdr + con->in_base_pos, - left); - if (ret <= 0) - return ret; - con->in_base_pos += ret; - } + size = sizeof (con->in_hdr); + end = size; + ret = read_partial(con, end, size, &con->in_hdr); + if (ret <= 0) + return ret; crc = crc32c(0, &con->in_hdr, offsetof(struct ceph_msg_header, crc)); if (cpu_to_le32(crc) != con->in_hdr.crc) { @@ -1686,10 +1856,13 @@ static int read_partial_message(struct ceph_connection *con) /* allocate message? */ if (!con->in_msg) { + int skip = 0; + dout("got hdr type %d front %d data %d\n", con->in_hdr.type, con->in_hdr.front_len, con->in_hdr.data_len); - skip = 0; - con->in_msg = ceph_alloc_msg(con, &con->in_hdr, &skip); + ret = ceph_con_in_msg_alloc(con, &skip); + if (ret < 0) + return ret; if (skip) { /* skip this message */ dout("alloc_msg said skip message\n"); @@ -1700,11 +1873,9 @@ static int read_partial_message(struct ceph_connection *con) con->in_seq++; return 0; } - if (!con->in_msg) { - con->error_msg = - "error allocating memory for incoming message"; - return -ENOMEM; - } + + BUG_ON(!con->in_msg); + BUG_ON(con->in_msg->con != con); m = con->in_msg; m->front.iov_len = 0; /* haven't read it yet */ if (m->middle) @@ -1716,6 +1887,11 @@ static int read_partial_message(struct ceph_connection *con) else con->in_msg_pos.page_pos = 0; con->in_msg_pos.data_pos = 0; + +#ifdef CONFIG_BLOCK + if (m->bio) + init_bio_iter(m->bio, &m->bio_iter, &m->bio_seg); +#endif } /* front */ @@ -1732,10 +1908,6 @@ static int read_partial_message(struct ceph_connection *con) if (ret <= 0) return ret; } -#ifdef CONFIG_BLOCK - if (m->bio && !m->bio_iter) - init_bio_iter(m->bio, &m->bio_iter, &m->bio_seg); -#endif /* (page) data */ while (con->in_msg_pos.data_pos < data_len) { @@ -1746,7 +1918,7 @@ static int read_partial_message(struct ceph_connection *con) return ret; #ifdef CONFIG_BLOCK } else if (m->bio) { - + BUG_ON(!m->bio_iter); ret = read_partial_message_bio(con, &m->bio_iter, &m->bio_seg, data_len, do_datacrc); @@ -1759,16 +1931,12 @@ static int read_partial_message(struct ceph_connection *con) } /* footer */ - to = sizeof(m->hdr) + sizeof(m->footer); - while (con->in_base_pos < to) { - left = to - con->in_base_pos; - ret = ceph_tcp_recvmsg(con->sock, (char *)&m->footer + - (con->in_base_pos - sizeof(m->hdr)), - left); - if (ret <= 0) - return ret; - con->in_base_pos += ret; - } + size = sizeof (m->footer); + end += size; + ret = read_partial(con, end, size, &m->footer); + if (ret <= 0) + return ret; + dout("read_partial_message got msg %p %d (%u) + %d (%u) + %d (%u)\n", m, front_len, m->footer.front_crc, middle_len, m->footer.middle_crc, data_len, m->footer.data_crc); @@ -1804,8 +1972,11 @@ static void process_message(struct ceph_connection *con) { struct ceph_msg *msg; + BUG_ON(con->in_msg->con != con); + con->in_msg->con = NULL; msg = con->in_msg; con->in_msg = NULL; + con->ops->put(con); /* if first message, set peer_name */ if (con->peer_name.type == 0) @@ -1825,7 +1996,6 @@ static void process_message(struct ceph_connection *con) con->ops->dispatch(con, msg); mutex_lock(&con->mutex); - prepare_read_tag(con); } @@ -1835,21 +2005,21 @@ static void process_message(struct ceph_connection *con) */ static int try_write(struct ceph_connection *con) { - struct ceph_messenger *msgr = con->msgr; int ret = 1; - dout("try_write start %p state %lu nref %d\n", con, con->state, - atomic_read(&con->nref)); + dout("try_write start %p state %lu\n", con, con->state); more: dout("try_write out_kvec_bytes %d\n", con->out_kvec_bytes); /* open the socket first? */ - if (con->sock == NULL) { - prepare_write_connect(msgr, con, 1); + if (con->state == CON_STATE_PREOPEN) { + BUG_ON(con->sock); + con->state = CON_STATE_CONNECTING; + + con_out_kvec_reset(con); + prepare_write_banner(con); prepare_read_banner(con); - set_bit(CONNECTING, &con->state); - clear_bit(NEGOTIATING, &con->state); BUG_ON(con->in_msg); con->in_tag = CEPH_MSGR_TAG_READY; @@ -1896,7 +2066,7 @@ static int try_write(struct ceph_connection *con) } do_next: - if (!test_bit(CONNECTING, &con->state)) { + if (con->state == CON_STATE_OPEN) { /* is anything else pending? */ if (!list_empty(&con->out_queue)) { prepare_write_message(con); @@ -1906,14 +2076,15 @@ static int try_write(struct ceph_connection *con) prepare_write_ack(con); goto more; } - if (test_and_clear_bit(KEEPALIVE_PENDING, &con->state)) { + if (test_and_clear_bit(CON_FLAG_KEEPALIVE_PENDING, + &con->flags)) { prepare_write_keepalive(con); goto more; } } /* Nothing to do! */ - clear_bit(WRITE_PENDING, &con->state); + clear_bit(CON_FLAG_WRITE_PENDING, &con->flags); dout("try_write nothing else to write.\n"); ret = 0; out: @@ -1930,38 +2101,45 @@ static int try_read(struct ceph_connection *con) { int ret = -1; - if (!con->sock) - return 0; - - if (test_bit(STANDBY, &con->state)) +more: + dout("try_read start on %p state %lu\n", con, con->state); + if (con->state != CON_STATE_CONNECTING && + con->state != CON_STATE_NEGOTIATING && + con->state != CON_STATE_OPEN) return 0; - dout("try_read start on %p\n", con); + BUG_ON(!con->sock); -more: dout("try_read tag %d in_base_pos %d\n", (int)con->in_tag, con->in_base_pos); - /* - * process_connect and process_message drop and re-take - * con->mutex. make sure we handle a racing close or reopen. - */ - if (test_bit(CLOSED, &con->state) || - test_bit(OPENING, &con->state)) { - ret = -EAGAIN; + if (con->state == CON_STATE_CONNECTING) { + dout("try_read connecting\n"); + ret = read_partial_banner(con); + if (ret <= 0) + goto out; + ret = process_banner(con); + if (ret < 0) + goto out; + + con->state = CON_STATE_NEGOTIATING; + + /* + * Received banner is good, exchange connection info. + * Do not reset out_kvec, as sending our banner raced + * with receiving peer banner after connect completed. + */ + ret = prepare_write_connect(con); + if (ret < 0) + goto out; + prepare_read_connect(con); + + /* Send connection info before awaiting response */ goto out; } - if (test_bit(CONNECTING, &con->state)) { - if (!test_bit(NEGOTIATING, &con->state)) { - dout("try_read connecting\n"); - ret = read_partial_banner(con); - if (ret <= 0) - goto out; - ret = process_banner(con); - if (ret < 0) - goto out; - } + if (con->state == CON_STATE_NEGOTIATING) { + dout("try_read negotiating\n"); ret = read_partial_connect(con); if (ret <= 0) goto out; @@ -1971,6 +2149,8 @@ static int try_read(struct ceph_connection *con) goto more; } + WARN_ON(con->state != CON_STATE_OPEN); + if (con->in_base_pos < 0) { /* * skipping + discarding content. @@ -2004,7 +2184,8 @@ static int try_read(struct ceph_connection *con) prepare_read_ack(con); break; case CEPH_MSGR_TAG_CLOSE: - set_bit(CLOSED, &con->state); /* fixme */ + con_close_socket(con); + con->state = CON_STATE_CLOSED; goto out; default: goto bad_tag; @@ -2027,6 +2208,8 @@ static int try_read(struct ceph_connection *con) if (con->in_tag == CEPH_MSGR_TAG_READY) goto more; process_message(con); + if (con->state == CON_STATE_OPEN) + prepare_read_tag(con); goto more; } if (con->in_tag == CEPH_MSGR_TAG_ACK) { @@ -2055,12 +2238,6 @@ static int try_read(struct ceph_connection *con) */ static void queue_con(struct ceph_connection *con) { - if (test_bit(DEAD, &con->state)) { - dout("queue_con %p ignoring: DEAD\n", - con); - return; - } - if (!con->ops->get(con)) { dout("queue_con %p ref count 0\n", con); return; @@ -2074,6 +2251,35 @@ static void queue_con(struct ceph_connection *con) } } +static bool con_sock_closed(struct ceph_connection *con) +{ + if (!test_and_clear_bit(CON_FLAG_SOCK_CLOSED, &con->flags)) + return false; + +#define CASE(x) \ + case CON_STATE_ ## x: \ + con->error_msg = "socket closed (con state " #x ")"; \ + break; + + switch (con->state) { + CASE(CLOSED); + CASE(PREOPEN); + CASE(CONNECTING); + CASE(NEGOTIATING); + CASE(OPEN); + CASE(STANDBY); + default: + pr_warning("%s con %p unrecognized state %lu\n", + __func__, con, con->state); + con->error_msg = "unrecognized con state"; + BUG(); + break; + } +#undef CASE + + return true; +} + /* * Do some work on a connection. Drop a connection ref when we're done. */ @@ -2085,7 +2291,10 @@ static void con_work(struct work_struct *work) mutex_lock(&con->mutex); restart: - if (test_and_clear_bit(BACKOFF, &con->state)) { + if (con_sock_closed(con)) + goto fault; + + if (test_and_clear_bit(CON_FLAG_BACKOFF, &con->flags)) { dout("con_work %p backing off\n", con); if (queue_delayed_work(ceph_msgr_wq, &con->work, round_jiffies_relative(con->delay))) { @@ -2093,41 +2302,42 @@ static void con_work(struct work_struct *work) mutex_unlock(&con->mutex); return; } else { - con->ops->put(con); dout("con_work %p FAILED to back off %lu\n", con, con->delay); + set_bit(CON_FLAG_BACKOFF, &con->flags); } + goto done; } - if (test_bit(STANDBY, &con->state)) { + if (con->state == CON_STATE_STANDBY) { dout("con_work %p STANDBY\n", con); goto done; } - if (test_bit(CLOSED, &con->state)) { /* e.g. if we are replaced */ - dout("con_work CLOSED\n"); - con_close_socket(con); + if (con->state == CON_STATE_CLOSED) { + dout("con_work %p CLOSED\n", con); + BUG_ON(con->sock); goto done; } - if (test_and_clear_bit(OPENING, &con->state)) { - /* reopen w/ new peer */ + if (con->state == CON_STATE_PREOPEN) { dout("con_work OPENING\n"); - con_close_socket(con); + BUG_ON(con->sock); } - if (test_and_clear_bit(SOCK_CLOSED, &con->state)) - goto fault; - ret = try_read(con); if (ret == -EAGAIN) goto restart; - if (ret < 0) + if (ret < 0) { + con->error_msg = "socket error on read"; goto fault; + } ret = try_write(con); if (ret == -EAGAIN) goto restart; - if (ret < 0) + if (ret < 0) { + con->error_msg = "socket error on write"; goto fault; + } done: mutex_unlock(&con->mutex); @@ -2136,7 +2346,6 @@ static void con_work(struct work_struct *work) return; fault: - mutex_unlock(&con->mutex); ceph_fault(con); /* error/fault path */ goto done_unlocked; } @@ -2147,26 +2356,31 @@ static void con_work(struct work_struct *work) * exponential backoff */ static void ceph_fault(struct ceph_connection *con) + __releases(con->mutex) { - pr_err("%s%lld %s %s\n", ENTITY_NAME(con->peer_name), + pr_warning("%s%lld %s %s\n", ENTITY_NAME(con->peer_name), ceph_pr_addr(&con->peer_addr.in_addr), con->error_msg); dout("fault %p state %lu to peer %s\n", con, con->state, ceph_pr_addr(&con->peer_addr.in_addr)); - if (test_bit(LOSSYTX, &con->state)) { - dout("fault on LOSSYTX channel\n"); - goto out; - } - - mutex_lock(&con->mutex); - if (test_bit(CLOSED, &con->state)) - goto out_unlock; + WARN_ON(con->state != CON_STATE_CONNECTING && + con->state != CON_STATE_NEGOTIATING && + con->state != CON_STATE_OPEN); con_close_socket(con); + if (test_bit(CON_FLAG_LOSSYTX, &con->flags)) { + dout("fault on LOSSYTX channel, marking CLOSED\n"); + con->state = CON_STATE_CLOSED; + goto out_unlock; + } + if (con->in_msg) { + BUG_ON(con->in_msg->con != con); + con->in_msg->con = NULL; ceph_msg_put(con->in_msg); con->in_msg = NULL; + con->ops->put(con); } /* Requeue anything that hasn't been acked */ @@ -2175,12 +2389,13 @@ static void ceph_fault(struct ceph_connection *con) /* If there are no messages queued or keepalive pending, place * the connection in a STANDBY state */ if (list_empty(&con->out_queue) && - !test_bit(KEEPALIVE_PENDING, &con->state)) { + !test_bit(CON_FLAG_KEEPALIVE_PENDING, &con->flags)) { dout("fault %p setting STANDBY clearing WRITE_PENDING\n", con); - clear_bit(WRITE_PENDING, &con->state); - set_bit(STANDBY, &con->state); + clear_bit(CON_FLAG_WRITE_PENDING, &con->flags); + con->state = CON_STATE_STANDBY; } else { /* retry after a delay. */ + con->state = CON_STATE_PREOPEN; if (con->delay == 0) con->delay = BASE_DELAY_INTERVAL; else if (con->delay < MAX_DELAY_INTERVAL) @@ -2201,13 +2416,12 @@ static void ceph_fault(struct ceph_connection *con) * that when con_work restarts we schedule the * delay then. */ - set_bit(BACKOFF, &con->state); + set_bit(CON_FLAG_BACKOFF, &con->flags); } } out_unlock: mutex_unlock(&con->mutex); -out: /* * in case we faulted due to authentication, invalidate our * current tickets so that we can get new ones. @@ -2224,18 +2438,14 @@ static void ceph_fault(struct ceph_connection *con) /* - * create a new messenger instance + * initialize a new messenger instance */ -struct ceph_messenger *ceph_messenger_create(struct ceph_entity_addr *myaddr, - u32 supported_features, - u32 required_features) +void ceph_messenger_init(struct ceph_messenger *msgr, + struct ceph_entity_addr *myaddr, + u32 supported_features, + u32 required_features, + bool nocrc) { - struct ceph_messenger *msgr; - - msgr = kzalloc(sizeof(*msgr), GFP_KERNEL); - if (msgr == NULL) - return ERR_PTR(-ENOMEM); - msgr->supported_features = supported_features; msgr->required_features = required_features; @@ -2248,30 +2458,23 @@ struct ceph_messenger *ceph_messenger_create(struct ceph_entity_addr *myaddr, msgr->inst.addr.type = 0; get_random_bytes(&msgr->inst.addr.nonce, sizeof(msgr->inst.addr.nonce)); encode_my_addr(msgr); + msgr->nocrc = nocrc; - dout("messenger_create %p\n", msgr); - return msgr; -} -EXPORT_SYMBOL(ceph_messenger_create); + atomic_set(&msgr->stopping, 0); -void ceph_messenger_destroy(struct ceph_messenger *msgr) -{ - dout("destroy %p\n", msgr); - kfree(msgr); - dout("destroyed messenger %p\n", msgr); + dout("%s %p\n", __func__, msgr); } -EXPORT_SYMBOL(ceph_messenger_destroy); +EXPORT_SYMBOL(ceph_messenger_init); static void clear_standby(struct ceph_connection *con) { /* come back from STANDBY? */ - if (test_and_clear_bit(STANDBY, &con->state)) { - mutex_lock(&con->mutex); + if (con->state == CON_STATE_STANDBY) { dout("clear_standby %p and ++connect_seq\n", con); + con->state = CON_STATE_PREOPEN; con->connect_seq++; - WARN_ON(test_bit(WRITE_PENDING, &con->state)); - WARN_ON(test_bit(KEEPALIVE_PENDING, &con->state)); - mutex_unlock(&con->mutex); + WARN_ON(test_bit(CON_FLAG_WRITE_PENDING, &con->flags)); + WARN_ON(test_bit(CON_FLAG_KEEPALIVE_PENDING, &con->flags)); } } @@ -2280,21 +2483,24 @@ static void clear_standby(struct ceph_connection *con) */ void ceph_con_send(struct ceph_connection *con, struct ceph_msg *msg) { - if (test_bit(CLOSED, &con->state)) { - dout("con_send %p closed, dropping %p\n", con, msg); - ceph_msg_put(msg); - return; - } - /* set src+dst */ msg->hdr.src = con->msgr->inst.name; - BUG_ON(msg->front.iov_len != le32_to_cpu(msg->hdr.front_len)); - msg->needs_out_seq = true; - /* queue */ mutex_lock(&con->mutex); + + if (con->state == CON_STATE_CLOSED) { + dout("con_send %p closed, dropping %p\n", con, msg); + ceph_msg_put(msg); + mutex_unlock(&con->mutex); + return; + } + + BUG_ON(msg->con != NULL); + msg->con = con->ops->get(con); + BUG_ON(msg->con == NULL); + BUG_ON(!list_empty(&msg->list_head)); list_add_tail(&msg->list_head, &con->out_queue); dout("----- %p to %s%lld %d=%s len %d+%d+%d -----\n", msg, @@ -2303,12 +2509,13 @@ void ceph_con_send(struct ceph_connection *con, struct ceph_msg *msg) le32_to_cpu(msg->hdr.front_len), le32_to_cpu(msg->hdr.middle_len), le32_to_cpu(msg->hdr.data_len)); + + clear_standby(con); mutex_unlock(&con->mutex); /* if there wasn't anything waiting to send before, queue * new work */ - clear_standby(con); - if (test_and_set_bit(WRITE_PENDING, &con->state) == 0) + if (test_and_set_bit(CON_FLAG_WRITE_PENDING, &con->flags) == 0) queue_con(con); } EXPORT_SYMBOL(ceph_con_send); @@ -2316,24 +2523,34 @@ EXPORT_SYMBOL(ceph_con_send); /* * Revoke a message that was previously queued for send */ -void ceph_con_revoke(struct ceph_connection *con, struct ceph_msg *msg) +void ceph_msg_revoke(struct ceph_msg *msg) { + struct ceph_connection *con = msg->con; + + if (!con) + return; /* Message not in our possession */ + mutex_lock(&con->mutex); if (!list_empty(&msg->list_head)) { - dout("con_revoke %p msg %p - was on queue\n", con, msg); + dout("%s %p msg %p - was on queue\n", __func__, con, msg); list_del_init(&msg->list_head); - ceph_msg_put(msg); + BUG_ON(msg->con == NULL); + msg->con->ops->put(msg->con); + msg->con = NULL; msg->hdr.seq = 0; + + ceph_msg_put(msg); } if (con->out_msg == msg) { - dout("con_revoke %p msg %p - was sending\n", con, msg); + dout("%s %p msg %p - was sending\n", __func__, con, msg); con->out_msg = NULL; if (con->out_kvec_is_msg) { con->out_skip = con->out_kvec_bytes; con->out_kvec_is_msg = false; } - ceph_msg_put(msg); msg->hdr.seq = 0; + + ceph_msg_put(msg); } mutex_unlock(&con->mutex); } @@ -2341,17 +2558,27 @@ void ceph_con_revoke(struct ceph_connection *con, struct ceph_msg *msg) /* * Revoke a message that we may be reading data into */ -void ceph_con_revoke_message(struct ceph_connection *con, struct ceph_msg *msg) +void ceph_msg_revoke_incoming(struct ceph_msg *msg) { + struct ceph_connection *con; + + BUG_ON(msg == NULL); + if (!msg->con) { + dout("%s msg %p null con\n", __func__, msg); + + return; /* Message not in our possession */ + } + + con = msg->con; mutex_lock(&con->mutex); - if (con->in_msg && con->in_msg == msg) { + if (con->in_msg == msg) { unsigned front_len = le32_to_cpu(con->in_hdr.front_len); unsigned middle_len = le32_to_cpu(con->in_hdr.middle_len); unsigned data_len = le32_to_cpu(con->in_hdr.data_len); /* skip rest of message */ - dout("con_revoke_pages %p msg %p revoked\n", con, msg); - con->in_base_pos = con->in_base_pos - + dout("%s %p msg %p revoked\n", __func__, con, msg); + con->in_base_pos = con->in_base_pos - sizeof(struct ceph_msg_header) - front_len - middle_len - @@ -2362,8 +2589,8 @@ void ceph_con_revoke_message(struct ceph_connection *con, struct ceph_msg *msg) con->in_tag = CEPH_MSGR_TAG_READY; con->in_seq++; } else { - dout("con_revoke_pages %p msg %p pages %p no-op\n", - con, con->in_msg, msg); + dout("%s %p in_msg %p msg %p no-op\n", + __func__, con, con->in_msg, msg); } mutex_unlock(&con->mutex); } @@ -2374,9 +2601,11 @@ void ceph_con_revoke_message(struct ceph_connection *con, struct ceph_msg *msg) void ceph_con_keepalive(struct ceph_connection *con) { dout("con_keepalive %p\n", con); + mutex_lock(&con->mutex); clear_standby(con); - if (test_and_set_bit(KEEPALIVE_PENDING, &con->state) == 0 && - test_and_set_bit(WRITE_PENDING, &con->state) == 0) + mutex_unlock(&con->mutex); + if (test_and_set_bit(CON_FLAG_KEEPALIVE_PENDING, &con->flags) == 0 && + test_and_set_bit(CON_FLAG_WRITE_PENDING, &con->flags) == 0) queue_con(con); } EXPORT_SYMBOL(ceph_con_keepalive); @@ -2395,6 +2624,8 @@ struct ceph_msg *ceph_msg_new(int type, int front_len, gfp_t flags, if (m == NULL) goto out; kref_init(&m->kref); + + m->con = NULL; INIT_LIST_HEAD(&m->list_head); m->hdr.tid = 0; @@ -2490,46 +2721,78 @@ static int ceph_alloc_middle(struct ceph_connection *con, struct ceph_msg *msg) } /* - * Generic message allocator, for incoming messages. + * Allocate a message for receiving an incoming message on a + * connection, and save the result in con->in_msg. Uses the + * connection's private alloc_msg op if available. + * + * Returns 0 on success, or a negative error code. + * + * On success, if we set *skip = 1: + * - the next message should be skipped and ignored. + * - con->in_msg == NULL + * or if we set *skip = 0: + * - con->in_msg is non-null. + * On error (ENOMEM, EAGAIN, ...), + * - con->in_msg == NULL */ -static struct ceph_msg *ceph_alloc_msg(struct ceph_connection *con, - struct ceph_msg_header *hdr, - int *skip) +static int ceph_con_in_msg_alloc(struct ceph_connection *con, int *skip) { + struct ceph_msg_header *hdr = &con->in_hdr; int type = le16_to_cpu(hdr->type); int front_len = le32_to_cpu(hdr->front_len); int middle_len = le32_to_cpu(hdr->middle_len); - struct ceph_msg *msg = NULL; - int ret; + int ret = 0; + + BUG_ON(con->in_msg != NULL); if (con->ops->alloc_msg) { + struct ceph_msg *msg; + mutex_unlock(&con->mutex); msg = con->ops->alloc_msg(con, hdr, skip); mutex_lock(&con->mutex); - if (!msg || *skip) - return NULL; + if (con->state != CON_STATE_OPEN) { + if (msg) + ceph_msg_put(msg); + return -EAGAIN; + } + con->in_msg = msg; + if (con->in_msg) { + con->in_msg->con = con->ops->get(con); + BUG_ON(con->in_msg->con == NULL); + } + if (*skip) { + con->in_msg = NULL; + return 0; + } + if (!con->in_msg) { + con->error_msg = + "error allocating memory for incoming message"; + return -ENOMEM; + } } - if (!msg) { - *skip = 0; - msg = ceph_msg_new(type, front_len, GFP_NOFS, false); - if (!msg) { + if (!con->in_msg) { + con->in_msg = ceph_msg_new(type, front_len, GFP_NOFS, false); + if (!con->in_msg) { pr_err("unable to allocate msg type %d len %d\n", type, front_len); - return NULL; + return -ENOMEM; } - msg->page_alignment = le16_to_cpu(hdr->data_off); + con->in_msg->con = con->ops->get(con); + BUG_ON(con->in_msg->con == NULL); + con->in_msg->page_alignment = le16_to_cpu(hdr->data_off); } - memcpy(&msg->hdr, &con->in_hdr, sizeof(con->in_hdr)); + memcpy(&con->in_msg->hdr, &con->in_hdr, sizeof(con->in_hdr)); - if (middle_len && !msg->middle) { - ret = ceph_alloc_middle(con, msg); + if (middle_len && !con->in_msg->middle) { + ret = ceph_alloc_middle(con, con->in_msg); if (ret < 0) { - ceph_msg_put(msg); - return NULL; + ceph_msg_put(con->in_msg); + con->in_msg = NULL; } } - return msg; + return ret; } diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c index 1845cde2622..89a6409b4e1 100644 --- a/net/ceph/mon_client.c +++ b/net/ceph/mon_client.c @@ -106,9 +106,9 @@ static void __send_prepared_auth_request(struct ceph_mon_client *monc, int len) monc->pending_auth = 1; monc->m_auth->front.iov_len = len; monc->m_auth->hdr.front_len = cpu_to_le32(len); - ceph_con_revoke(monc->con, monc->m_auth); + ceph_msg_revoke(monc->m_auth); ceph_msg_get(monc->m_auth); /* keep our ref */ - ceph_con_send(monc->con, monc->m_auth); + ceph_con_send(&monc->con, monc->m_auth); } /* @@ -117,8 +117,11 @@ static void __send_prepared_auth_request(struct ceph_mon_client *monc, int len) static void __close_session(struct ceph_mon_client *monc) { dout("__close_session closing mon%d\n", monc->cur_mon); - ceph_con_revoke(monc->con, monc->m_auth); - ceph_con_close(monc->con); + ceph_msg_revoke(monc->m_auth); + ceph_msg_revoke_incoming(monc->m_auth_reply); + ceph_msg_revoke(monc->m_subscribe); + ceph_msg_revoke_incoming(monc->m_subscribe_ack); + ceph_con_close(&monc->con); monc->cur_mon = -1; monc->pending_auth = 0; ceph_auth_reset(monc->auth); @@ -142,9 +145,8 @@ static int __open_session(struct ceph_mon_client *monc) monc->want_next_osdmap = !!monc->want_next_osdmap; dout("open_session mon%d opening\n", monc->cur_mon); - monc->con->peer_name.type = CEPH_ENTITY_TYPE_MON; - monc->con->peer_name.num = cpu_to_le64(monc->cur_mon); - ceph_con_open(monc->con, + ceph_con_open(&monc->con, + CEPH_ENTITY_TYPE_MON, monc->cur_mon, &monc->monmap->mon_inst[monc->cur_mon].addr); /* initiatiate authentication handshake */ @@ -226,8 +228,8 @@ static void __send_subscribe(struct ceph_mon_client *monc) msg->front.iov_len = p - msg->front.iov_base; msg->hdr.front_len = cpu_to_le32(msg->front.iov_len); - ceph_con_revoke(monc->con, msg); - ceph_con_send(monc->con, ceph_msg_get(msg)); + ceph_msg_revoke(msg); + ceph_con_send(&monc->con, ceph_msg_get(msg)); monc->sub_sent = jiffies | 1; /* never 0 */ } @@ -247,7 +249,7 @@ static void handle_subscribe_ack(struct ceph_mon_client *monc, if (monc->hunting) { pr_info("mon%d %s session established\n", monc->cur_mon, - ceph_pr_addr(&monc->con->peer_addr.in_addr)); + ceph_pr_addr(&monc->con.peer_addr.in_addr)); monc->hunting = false; } dout("handle_subscribe_ack after %d seconds\n", seconds); @@ -308,6 +310,17 @@ int ceph_monc_open_session(struct ceph_mon_client *monc) } EXPORT_SYMBOL(ceph_monc_open_session); +/* + * We require the fsid and global_id in order to initialize our + * debugfs dir. + */ +static bool have_debugfs_info(struct ceph_mon_client *monc) +{ + dout("have_debugfs_info fsid %d globalid %lld\n", + (int)monc->client->have_fsid, monc->auth->global_id); + return monc->client->have_fsid && monc->auth->global_id > 0; +} + /* * The monitor responds with mount ack indicate mount success. The * included client ticket allows the client to talk to MDSs and OSDs. @@ -318,9 +331,12 @@ static void ceph_monc_handle_map(struct ceph_mon_client *monc, struct ceph_client *client = monc->client; struct ceph_monmap *monmap = NULL, *old = monc->monmap; void *p, *end; + int had_debugfs_info, init_debugfs = 0; mutex_lock(&monc->mutex); + had_debugfs_info = have_debugfs_info(monc); + dout("handle_monmap\n"); p = msg->front.iov_base; end = p + msg->front.iov_len; @@ -342,12 +358,22 @@ static void ceph_monc_handle_map(struct ceph_mon_client *monc, if (!client->have_fsid) { client->have_fsid = true; + if (!had_debugfs_info && have_debugfs_info(monc)) { + pr_info("client%lld fsid %pU\n", + ceph_client_id(monc->client), + &monc->client->fsid); + init_debugfs = 1; + } mutex_unlock(&monc->mutex); - /* - * do debugfs initialization without mutex to avoid - * creating a locking dependency - */ - ceph_debugfs_client_init(client); + + if (init_debugfs) { + /* + * do debugfs initialization without mutex to avoid + * creating a locking dependency + */ + ceph_debugfs_client_init(monc->client); + } + goto out_unlocked; } out: @@ -439,6 +465,7 @@ static struct ceph_msg *get_generic_reply(struct ceph_connection *con, m = NULL; } else { dout("get_generic_reply %lld got %p\n", tid, req->reply); + *skip = 0; m = ceph_msg_get(req->reply); /* * we don't need to track the connection reading into @@ -461,7 +488,7 @@ static int do_generic_request(struct ceph_mon_client *monc, req->request->hdr.tid = cpu_to_le64(req->tid); __insert_generic_request(monc, req); monc->num_generic_requests++; - ceph_con_send(monc->con, ceph_msg_get(req->request)); + ceph_con_send(&monc->con, ceph_msg_get(req->request)); mutex_unlock(&monc->mutex); err = wait_for_completion_interruptible(&req->completion); @@ -684,8 +711,9 @@ static void __resend_generic_request(struct ceph_mon_client *monc) for (p = rb_first(&monc->generic_request_tree); p; p = rb_next(p)) { req = rb_entry(p, struct ceph_mon_generic_request, node); - ceph_con_revoke(monc->con, req->request); - ceph_con_send(monc->con, ceph_msg_get(req->request)); + ceph_msg_revoke(req->request); + ceph_msg_revoke_incoming(req->reply); + ceph_con_send(&monc->con, ceph_msg_get(req->request)); } } @@ -705,7 +733,7 @@ static void delayed_work(struct work_struct *work) __close_session(monc); __open_session(monc); /* continue hunting */ } else { - ceph_con_keepalive(monc->con); + ceph_con_keepalive(&monc->con); __validate_auth(monc); @@ -760,19 +788,12 @@ int ceph_monc_init(struct ceph_mon_client *monc, struct ceph_client *cl) goto out; /* connection */ - monc->con = kmalloc(sizeof(*monc->con), GFP_KERNEL); - if (!monc->con) - goto out_monmap; - ceph_con_init(monc->client->msgr, monc->con); - monc->con->private = monc; - monc->con->ops = &mon_con_ops; - /* authentication */ monc->auth = ceph_auth_init(cl->options->name, cl->options->key); if (IS_ERR(monc->auth)) { err = PTR_ERR(monc->auth); - goto out_con; + goto out_monmap; } monc->auth->want_keys = CEPH_ENTITY_TYPE_AUTH | CEPH_ENTITY_TYPE_MON | @@ -801,6 +822,9 @@ int ceph_monc_init(struct ceph_mon_client *monc, struct ceph_client *cl) if (!monc->m_auth) goto out_auth_reply; + ceph_con_init(&monc->con, monc, &mon_con_ops, + &monc->client->msgr); + monc->cur_mon = -1; monc->hunting = true; monc->sub_renew_after = jiffies; @@ -824,8 +848,6 @@ int ceph_monc_init(struct ceph_mon_client *monc, struct ceph_client *cl) ceph_msg_put(monc->m_subscribe_ack); out_auth: ceph_auth_destroy(monc->auth); -out_con: - monc->con->ops->put(monc->con); out_monmap: kfree(monc->monmap); out: @@ -841,12 +863,16 @@ void ceph_monc_stop(struct ceph_mon_client *monc) mutex_lock(&monc->mutex); __close_session(monc); - monc->con->private = NULL; - monc->con->ops->put(monc->con); - monc->con = NULL; - mutex_unlock(&monc->mutex); + /* + * flush msgr queue before we destroy ourselves to ensure that: + * - any work that references our embedded con is finished. + * - any osd_client or other work that may reference an authorizer + * finishes before we shut down the auth subsystem. + */ + ceph_msgr_flush(); + ceph_auth_destroy(monc->auth); ceph_msg_put(monc->m_auth); @@ -863,8 +889,10 @@ static void handle_auth_reply(struct ceph_mon_client *monc, { int ret; int was_auth = 0; + int had_debugfs_info, init_debugfs = 0; mutex_lock(&monc->mutex); + had_debugfs_info = have_debugfs_info(monc); if (monc->auth->ops) was_auth = monc->auth->ops->is_authenticated(monc->auth); monc->pending_auth = 0; @@ -880,14 +908,29 @@ static void handle_auth_reply(struct ceph_mon_client *monc, } else if (!was_auth && monc->auth->ops->is_authenticated(monc->auth)) { dout("authenticated, starting session\n"); - monc->client->msgr->inst.name.type = CEPH_ENTITY_TYPE_CLIENT; - monc->client->msgr->inst.name.num = + monc->client->msgr.inst.name.type = CEPH_ENTITY_TYPE_CLIENT; + monc->client->msgr.inst.name.num = cpu_to_le64(monc->auth->global_id); __send_subscribe(monc); __resend_generic_request(monc); } + + if (!had_debugfs_info && have_debugfs_info(monc)) { + pr_info("client%lld fsid %pU\n", + ceph_client_id(monc->client), + &monc->client->fsid); + init_debugfs = 1; + } mutex_unlock(&monc->mutex); + + if (init_debugfs) { + /* + * do debugfs initialization without mutex to avoid + * creating a locking dependency + */ + ceph_debugfs_client_init(monc->client); + } } static int __validate_auth(struct ceph_mon_client *monc) @@ -992,6 +1035,8 @@ static struct ceph_msg *mon_alloc_msg(struct ceph_connection *con, case CEPH_MSG_MDS_MAP: case CEPH_MSG_OSD_MAP: m = ceph_msg_new(type, front_len, GFP_NOFS, false); + if (!m) + return NULL; /* ENOMEM--return skip == 0 */ break; } @@ -1021,7 +1066,7 @@ static void mon_fault(struct ceph_connection *con) if (!monc->hunting) pr_info("mon%d %s session lost, " "hunting for new mon\n", monc->cur_mon, - ceph_pr_addr(&monc->con->peer_addr.in_addr)); + ceph_pr_addr(&monc->con.peer_addr.in_addr)); __close_session(monc); if (!monc->hunting) { @@ -1036,9 +1081,23 @@ static void mon_fault(struct ceph_connection *con) mutex_unlock(&monc->mutex); } +/* + * We can ignore refcounting on the connection struct, as all references + * will come from the messenger workqueue, which is drained prior to + * mon_client destruction. + */ +static struct ceph_connection *con_get(struct ceph_connection *con) +{ + return con; +} + +static void con_put(struct ceph_connection *con) +{ +} + static const struct ceph_connection_operations mon_con_ops = { - .get = ceph_con_get, - .put = ceph_con_put, + .get = con_get, + .put = con_put, .dispatch = dispatch, .fault = mon_fault, .alloc_msg = mon_alloc_msg, diff --git a/net/ceph/msgpool.c b/net/ceph/msgpool.c index 11d5f4196a7..ddec1c10ac8 100644 --- a/net/ceph/msgpool.c +++ b/net/ceph/msgpool.c @@ -12,7 +12,7 @@ static void *msgpool_alloc(gfp_t gfp_mask, void *arg) struct ceph_msgpool *pool = arg; struct ceph_msg *msg; - msg = ceph_msg_new(0, pool->front_len, gfp_mask, true); + msg = ceph_msg_new(pool->type, pool->front_len, gfp_mask, true); if (!msg) { dout("msgpool_alloc %s failed\n", pool->name); } else { @@ -32,10 +32,11 @@ static void msgpool_free(void *element, void *arg) ceph_msg_put(msg); } -int ceph_msgpool_init(struct ceph_msgpool *pool, +int ceph_msgpool_init(struct ceph_msgpool *pool, int type, int front_len, int size, bool blocking, const char *name) { dout("msgpool %s init\n", name); + pool->type = type; pool->front_len = front_len; pool->pool = mempool_create(size, msgpool_alloc, msgpool_free, pool); if (!pool->pool) @@ -61,7 +62,7 @@ struct ceph_msg *ceph_msgpool_get(struct ceph_msgpool *pool, WARN_ON(1); /* try to alloc a fresh message */ - return ceph_msg_new(0, front_len, GFP_NOFS, false); + return ceph_msg_new(pool->type, front_len, GFP_NOFS, false); } msg = mempool_alloc(pool->pool, GFP_NOFS); diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index 5e254055c91..b16dfa25e75 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -52,7 +52,7 @@ static int op_has_extent(int op) op == CEPH_OSD_OP_WRITE); } -void ceph_calc_raw_layout(struct ceph_osd_client *osdc, +int ceph_calc_raw_layout(struct ceph_osd_client *osdc, struct ceph_file_layout *layout, u64 snapid, u64 off, u64 *plen, u64 *bno, @@ -62,12 +62,15 @@ void ceph_calc_raw_layout(struct ceph_osd_client *osdc, struct ceph_osd_request_head *reqhead = req->r_request->front.iov_base; u64 orig_len = *plen; u64 objoff, objlen; /* extent in object */ + int r; reqhead->snapid = cpu_to_le64(snapid); /* object extent? */ - ceph_calc_file_object_mapping(layout, off, plen, bno, - &objoff, &objlen); + r = ceph_calc_file_object_mapping(layout, off, plen, bno, + &objoff, &objlen); + if (r < 0) + return r; if (*plen < orig_len) dout(" skipping last %llu, final file extent %llu~%llu\n", orig_len - *plen, off, *plen); @@ -83,7 +86,7 @@ void ceph_calc_raw_layout(struct ceph_osd_client *osdc, dout("calc_layout bno=%llx %llu~%llu (%d pages)\n", *bno, objoff, objlen, req->r_num_pages); - + return 0; } EXPORT_SYMBOL(ceph_calc_raw_layout); @@ -112,20 +115,25 @@ EXPORT_SYMBOL(ceph_calc_raw_layout); * * fill osd op in request message. */ -static void calc_layout(struct ceph_osd_client *osdc, - struct ceph_vino vino, - struct ceph_file_layout *layout, - u64 off, u64 *plen, - struct ceph_osd_request *req, - struct ceph_osd_req_op *op) +static int calc_layout(struct ceph_osd_client *osdc, + struct ceph_vino vino, + struct ceph_file_layout *layout, + u64 off, u64 *plen, + struct ceph_osd_request *req, + struct ceph_osd_req_op *op) { u64 bno; + int r; - ceph_calc_raw_layout(osdc, layout, vino.snap, off, - plen, &bno, req, op); + r = ceph_calc_raw_layout(osdc, layout, vino.snap, off, + plen, &bno, req, op); + if (r < 0) + return r; snprintf(req->r_oid, sizeof(req->r_oid), "%llx.%08llx", vino.ino, bno); req->r_oid_len = strlen(req->r_oid); + + return r; } /* @@ -139,15 +147,14 @@ void ceph_osdc_release_request(struct kref *kref) if (req->r_request) ceph_msg_put(req->r_request); - if (req->r_reply) - ceph_msg_put(req->r_reply); if (req->r_con_filling_msg) { - dout("release_request revoking pages %p from con %p\n", + dout("%s revoking pages %p from con %p\n", __func__, req->r_pages, req->r_con_filling_msg); - ceph_con_revoke_message(req->r_con_filling_msg, - req->r_reply); - ceph_con_put(req->r_con_filling_msg); + ceph_msg_revoke_incoming(req->r_reply); + req->r_con_filling_msg->ops->put(req->r_con_filling_msg); } + if (req->r_reply) + ceph_msg_put(req->r_reply); if (req->r_own_pages) ceph_release_page_vector(req->r_pages, req->r_num_pages); @@ -214,6 +221,7 @@ struct ceph_osd_request *ceph_osdc_alloc_request(struct ceph_osd_client *osdc, kref_init(&req->r_kref); init_completion(&req->r_completion); init_completion(&req->r_safe_completion); + RB_CLEAR_NODE(&req->r_node); INIT_LIST_HEAD(&req->r_unsafe_item); INIT_LIST_HEAD(&req->r_linger_item); INIT_LIST_HEAD(&req->r_linger_osd); @@ -243,6 +251,7 @@ struct ceph_osd_request *ceph_osdc_alloc_request(struct ceph_osd_client *osdc, } ceph_pagelist_init(req->r_trail); } + /* create request message; allow space for oid */ msg_size += MAX_OBJ_NAME_SIZE; if (snapc) @@ -256,7 +265,6 @@ struct ceph_osd_request *ceph_osdc_alloc_request(struct ceph_osd_client *osdc, return NULL; } - msg->hdr.type = cpu_to_le16(CEPH_MSG_OSD_OP); memset(msg->front.iov_base, 0, msg->front.iov_len); req->r_request = msg; @@ -278,7 +286,7 @@ static void osd_req_encode_op(struct ceph_osd_request *req, { dst->op = cpu_to_le16(src->op); - switch (dst->op) { + switch (src->op) { case CEPH_OSD_OP_READ: case CEPH_OSD_OP_WRITE: dst->extent.offset = @@ -454,6 +462,7 @@ struct ceph_osd_request *ceph_osdc_new_request(struct ceph_osd_client *osdc, { struct ceph_osd_req_op ops[3]; struct ceph_osd_request *req; + int r; ops[0].op = opcode; ops[0].extent.truncate_seq = truncate_seq; @@ -472,10 +481,12 @@ struct ceph_osd_request *ceph_osdc_new_request(struct ceph_osd_client *osdc, use_mempool, GFP_NOFS, NULL, NULL); if (!req) - return NULL; + return ERR_PTR(-ENOMEM); /* calculate max write size */ - calc_layout(osdc, vino, layout, off, plen, req, ops); + r = calc_layout(osdc, vino, layout, off, plen, req, ops); + if (r < 0) + return ERR_PTR(r); req->r_file_layout = *layout; /* keep a copy */ /* in case it differs from natural (file) alignment that @@ -568,7 +579,7 @@ static void __kick_osd_requests(struct ceph_osd_client *osdc, dout("__kick_osd_requests osd%d\n", osd->o_osd); err = __reset_osd(osdc, osd); - if (err == -EAGAIN) + if (err) return; list_for_each_entry(req, &osd->o_requests, r_osd_item) { @@ -595,14 +606,6 @@ static void __kick_osd_requests(struct ceph_osd_client *osdc, } } -static void kick_osd_requests(struct ceph_osd_client *osdc, - struct ceph_osd *kickosd) -{ - mutex_lock(&osdc->request_mutex); - __kick_osd_requests(osdc, kickosd); - mutex_unlock(&osdc->request_mutex); -} - /* * If the osd connection drops, we need to resubmit all requests. */ @@ -616,7 +619,9 @@ static void osd_reset(struct ceph_connection *con) dout("osd_reset osd%d\n", osd->o_osd); osdc = osd->o_osdc; down_read(&osdc->map_sem); - kick_osd_requests(osdc, osd); + mutex_lock(&osdc->request_mutex); + __kick_osd_requests(osdc, osd); + mutex_unlock(&osdc->request_mutex); send_queued(osdc); up_read(&osdc->map_sem); } @@ -624,7 +629,7 @@ static void osd_reset(struct ceph_connection *con) /* * Track open sessions with osds. */ -static struct ceph_osd *create_osd(struct ceph_osd_client *osdc) +static struct ceph_osd *create_osd(struct ceph_osd_client *osdc, int onum) { struct ceph_osd *osd; @@ -634,15 +639,14 @@ static struct ceph_osd *create_osd(struct ceph_osd_client *osdc) atomic_set(&osd->o_ref, 1); osd->o_osdc = osdc; + osd->o_osd = onum; + RB_CLEAR_NODE(&osd->o_node); INIT_LIST_HEAD(&osd->o_requests); INIT_LIST_HEAD(&osd->o_linger_requests); INIT_LIST_HEAD(&osd->o_osd_lru); osd->o_incarnation = 1; - ceph_con_init(osdc->client->msgr, &osd->o_con); - osd->o_con.private = osd; - osd->o_con.ops = &osd_con_ops; - osd->o_con.peer_name.type = CEPH_ENTITY_TYPE_OSD; + ceph_con_init(&osd->o_con, osd, &osd_con_ops, &osdc->client->msgr); INIT_LIST_HEAD(&osd->o_keepalive_item); return osd; @@ -664,11 +668,11 @@ static void put_osd(struct ceph_osd *osd) { dout("put_osd %p %d -> %d\n", osd, atomic_read(&osd->o_ref), atomic_read(&osd->o_ref) - 1); - if (atomic_dec_and_test(&osd->o_ref)) { + if (atomic_dec_and_test(&osd->o_ref) && osd->o_auth.authorizer) { struct ceph_auth_client *ac = osd->o_osdc->client->monc.auth; - if (osd->o_authorizer) - ac->ops->destroy_authorizer(ac, osd->o_authorizer); + if (ac->ops && ac->ops->destroy_authorizer) + ac->ops->destroy_authorizer(ac, osd->o_auth.authorizer); kfree(osd); } } @@ -740,6 +744,7 @@ static int __reset_osd(struct ceph_osd_client *osdc, struct ceph_osd *osd) if (list_empty(&osd->o_requests) && list_empty(&osd->o_linger_requests)) { __remove_osd(osdc, osd); + ret = -ENODEV; } else if (memcmp(&osdc->osdmap->osd_addr[osd->o_osd], &osd->o_con.peer_addr, sizeof(osd->o_con.peer_addr)) == 0 && @@ -752,7 +757,8 @@ static int __reset_osd(struct ceph_osd_client *osdc, struct ceph_osd *osd) ret = -EAGAIN; } else { ceph_con_close(&osd->o_con); - ceph_con_open(&osd->o_con, &osdc->osdmap->osd_addr[osd->o_osd]); + ceph_con_open(&osd->o_con, CEPH_ENTITY_TYPE_OSD, osd->o_osd, + &osdc->osdmap->osd_addr[osd->o_osd]); osd->o_incarnation++; } return ret; @@ -841,13 +847,19 @@ static void register_request(struct ceph_osd_client *osdc, static void __unregister_request(struct ceph_osd_client *osdc, struct ceph_osd_request *req) { + if (RB_EMPTY_NODE(&req->r_node)) { + dout("__unregister_request %p tid %lld not registered\n", + req, req->r_tid); + return; + } + dout("__unregister_request %p tid %lld\n", req, req->r_tid); rb_erase(&req->r_node, &osdc->requests); osdc->num_requests--; if (req->r_osd) { /* make sure the original request isn't in flight. */ - ceph_con_revoke(&req->r_osd->o_con, req->r_request); + ceph_msg_revoke(req->r_request); list_del_init(&req->r_osd_item); if (list_empty(&req->r_osd->o_requests) && @@ -859,9 +871,9 @@ static void __unregister_request(struct ceph_osd_client *osdc, req->r_osd = NULL; } + list_del_init(&req->r_req_lru_item); ceph_osdc_put_request(req); - list_del_init(&req->r_req_lru_item); if (osdc->num_requests == 0) { dout(" no requests, canceling timeout\n"); __cancel_osd_timeout(osdc); @@ -874,7 +886,7 @@ static void __unregister_request(struct ceph_osd_client *osdc, static void __cancel_request(struct ceph_osd_request *req) { if (req->r_sent && req->r_osd) { - ceph_con_revoke(&req->r_osd->o_con, req->r_request); + ceph_msg_revoke(req->r_request); req->r_sent = 0; } } @@ -884,15 +896,17 @@ static void __register_linger_request(struct ceph_osd_client *osdc, { dout("__register_linger_request %p\n", req); list_add_tail(&req->r_linger_item, &osdc->req_linger); - list_add_tail(&req->r_linger_osd, &req->r_osd->o_linger_requests); + if (req->r_osd) + list_add_tail(&req->r_linger_osd, + &req->r_osd->o_linger_requests); } static void __unregister_linger_request(struct ceph_osd_client *osdc, struct ceph_osd_request *req) { dout("__unregister_linger_request %p\n", req); + list_del_init(&req->r_linger_item); if (req->r_osd) { - list_del_init(&req->r_linger_item); list_del_init(&req->r_linger_osd); if (list_empty(&req->r_osd->o_requests) && @@ -992,18 +1006,18 @@ static int __map_request(struct ceph_osd_client *osdc, req->r_osd = __lookup_osd(osdc, o); if (!req->r_osd && o >= 0) { err = -ENOMEM; - req->r_osd = create_osd(osdc); + req->r_osd = create_osd(osdc, o); if (!req->r_osd) { list_move(&req->r_req_lru_item, &osdc->req_notarget); goto out; } dout("map_request osd %p is osd%d\n", req->r_osd, o); - req->r_osd->o_osd = o; - req->r_osd->o_con.peer_name.num = cpu_to_le64(o); __insert_osd(osdc, req->r_osd); - ceph_con_open(&req->r_osd->o_con, &osdc->osdmap->osd_addr[o]); + ceph_con_open(&req->r_osd->o_con, + CEPH_ENTITY_TYPE_OSD, o, + &osdc->osdmap->osd_addr[o]); } if (req->r_osd) { @@ -1071,12 +1085,10 @@ static void handle_timeout(struct work_struct *work) { struct ceph_osd_client *osdc = container_of(work, struct ceph_osd_client, timeout_work.work); - struct ceph_osd_request *req, *last_req = NULL; + struct ceph_osd_request *req; struct ceph_osd *osd; - unsigned long timeout = osdc->client->options->osd_timeout * HZ; unsigned long keepalive = osdc->client->options->osd_keepalive_timeout * HZ; - unsigned long last_stamp = 0; struct list_head slow_osds; dout("timeout\n"); down_read(&osdc->map_sem); @@ -1085,37 +1097,6 @@ static void handle_timeout(struct work_struct *work) mutex_lock(&osdc->request_mutex); - /* - * reset osds that appear to be _really_ unresponsive. this - * is a failsafe measure.. we really shouldn't be getting to - * this point if the system is working properly. the monitors - * should mark the osd as failed and we should find out about - * it from an updated osd map. - */ - while (timeout && !list_empty(&osdc->req_lru)) { - req = list_entry(osdc->req_lru.next, struct ceph_osd_request, - r_req_lru_item); - - /* hasn't been long enough since we sent it? */ - if (time_before(jiffies, req->r_stamp + timeout)) - break; - - /* hasn't been long enough since it was acked? */ - if (req->r_request->ack_stamp == 0 || - time_before(jiffies, req->r_request->ack_stamp + timeout)) - break; - - BUG_ON(req == last_req && req->r_stamp == last_stamp); - last_req = req; - last_stamp = req->r_stamp; - - osd = req->r_osd; - BUG_ON(!osd); - pr_warning(" tid %llu timed out on osd%d, will reset osd\n", - req->r_tid, osd->o_osd); - __kick_osd_requests(osdc, osd); - } - /* * ping osds that are a bit slow. this ensures that if there * is a break in the TCP connection we will notice, and reopen @@ -1210,7 +1191,7 @@ static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg, if (req->r_con_filling_msg == con && req->r_reply == msg) { dout(" dropping con_filling_msg ref %p\n", con); req->r_con_filling_msg = NULL; - ceph_con_put(con); + con->ops->put(con); } if (!req->r_got_reply) { @@ -1287,7 +1268,7 @@ static void reset_changed_osds(struct ceph_osd_client *osdc) * Requeue requests whose mapping to an OSD has changed. If requests map to * no osd, request a new map. * - * Caller should hold map_sem for read and request_mutex. + * Caller should hold map_sem for read. */ static void kick_requests(struct ceph_osd_client *osdc, int force_resend) { @@ -1298,8 +1279,27 @@ static void kick_requests(struct ceph_osd_client *osdc, int force_resend) dout("kick_requests %s\n", force_resend ? " (force resend)" : ""); mutex_lock(&osdc->request_mutex); - for (p = rb_first(&osdc->requests); p; p = rb_next(p)) { + for (p = rb_first(&osdc->requests); p; ) { req = rb_entry(p, struct ceph_osd_request, r_node); + p = rb_next(p); + + /* + * For linger requests that have not yet been + * registered, move them to the linger list; they'll + * be sent to the osd in the loop below. Unregister + * the request before re-registering it as a linger + * request to ensure the __map_request() below + * will decide it needs to be sent. + */ + if (req->r_linger && list_empty(&req->r_linger_item)) { + dout("%p tid %llu restart on osd%d\n", + req, req->r_tid, + req->r_osd ? req->r_osd->o_osd : -1); + __unregister_request(osdc, req); + __register_linger_request(osdc, req); + continue; + } + err = __map_request(osdc, req, force_resend); if (err < 0) continue; /* error */ @@ -1307,10 +1307,12 @@ static void kick_requests(struct ceph_osd_client *osdc, int force_resend) dout("%p tid %llu maps to no osd\n", req, req->r_tid); needmap++; /* request a newer map */ } else if (err > 0) { - dout("%p tid %llu requeued on osd%d\n", req, req->r_tid, - req->r_osd ? req->r_osd->o_osd : -1); - if (!req->r_linger) + if (!req->r_linger) { + dout("%p tid %llu requeued on osd%d\n", req, + req->r_tid, + req->r_osd ? req->r_osd->o_osd : -1); req->r_flags |= CEPH_OSD_FLAG_RETRY; + } } } @@ -1319,6 +1321,7 @@ static void kick_requests(struct ceph_osd_client *osdc, int force_resend) dout("linger req=%p req->r_osd=%p\n", req, req->r_osd); err = __map_request(osdc, req, force_resend); + dout("__map_request returned %d\n", err); if (err == 0) continue; /* no change and no osd was specified */ if (err < 0) @@ -1331,8 +1334,8 @@ static void kick_requests(struct ceph_osd_client *osdc, int force_resend) dout("kicking lingering %p tid %llu osd%d\n", req, req->r_tid, req->r_osd ? req->r_osd->o_osd : -1); - __unregister_linger_request(osdc, req); __register_request(osdc, req); + __unregister_linger_request(osdc, req); } mutex_unlock(&osdc->request_mutex); @@ -1340,6 +1343,7 @@ static void kick_requests(struct ceph_osd_client *osdc, int force_resend) dout("%d requests for down osds, need new map\n", needmap); ceph_monc_request_next_osdmap(&osdc->client->monc); } + reset_changed_osds(osdc); } @@ -1385,7 +1389,7 @@ void ceph_osdc_handle_map(struct ceph_osd_client *osdc, struct ceph_msg *msg) epoch, maplen); newmap = osdmap_apply_incremental(&p, next, osdc->osdmap, - osdc->client->msgr); + &osdc->client->msgr); if (IS_ERR(newmap)) { err = PTR_ERR(newmap); goto bad; @@ -1396,7 +1400,6 @@ void ceph_osdc_handle_map(struct ceph_osd_client *osdc, struct ceph_msg *msg) osdc->osdmap = newmap; } kick_requests(osdc, 0); - reset_changed_osds(osdc); } else { dout("ignoring incremental map %u len %d\n", epoch, maplen); @@ -1566,6 +1569,7 @@ int ceph_osdc_create_event(struct ceph_osd_client *osdc, event->data = data; event->osdc = osdc; INIT_LIST_HEAD(&event->osd_node); + RB_CLEAR_NODE(&event->node); kref_init(&event->kref); /* one ref for us */ kref_get(&event->kref); /* one ref for the caller */ init_completion(&event->completion); @@ -1833,11 +1837,12 @@ int ceph_osdc_init(struct ceph_osd_client *osdc, struct ceph_client *client) if (!osdc->req_mempool) goto out; - err = ceph_msgpool_init(&osdc->msgpool_op, OSD_OP_FRONT_LEN, 10, true, + err = ceph_msgpool_init(&osdc->msgpool_op, CEPH_MSG_OSD_OP, + OSD_OP_FRONT_LEN, 10, true, "osd_op"); if (err < 0) goto out_mempool; - err = ceph_msgpool_init(&osdc->msgpool_op_reply, + err = ceph_msgpool_init(&osdc->msgpool_op_reply, CEPH_MSG_OSD_OPREPLY, OSD_OPREPLY_FRONT_LEN, 10, true, "osd_op_reply"); if (err < 0) @@ -1896,8 +1901,8 @@ int ceph_osdc_readpages(struct ceph_osd_client *osdc, CEPH_OSD_OP_READ, CEPH_OSD_FLAG_READ, NULL, 0, truncate_seq, truncate_size, NULL, false, 1, page_align); - if (!req) - return -ENOMEM; + if (IS_ERR(req)) + return PTR_ERR(req); /* it may be a short read due to an object boundary */ req->r_pages = pages; @@ -1939,8 +1944,8 @@ int ceph_osdc_writepages(struct ceph_osd_client *osdc, struct ceph_vino vino, snapc, do_sync, truncate_seq, truncate_size, mtime, nofail, 1, page_align); - if (!req) - return -ENOMEM; + if (IS_ERR(req)) + return PTR_ERR(req); /* it may be a short write due to an object boundary */ req->r_pages = pages; @@ -2019,10 +2024,10 @@ static struct ceph_msg *get_reply(struct ceph_connection *con, } if (req->r_con_filling_msg) { - dout("get_reply revoking msg %p from old con %p\n", + dout("%s revoking msg %p from old con %p\n", __func__, req->r_reply, req->r_con_filling_msg); - ceph_con_revoke_message(req->r_con_filling_msg, req->r_reply); - ceph_con_put(req->r_con_filling_msg); + ceph_msg_revoke_incoming(req->r_reply); + req->r_con_filling_msg->ops->put(req->r_con_filling_msg); req->r_con_filling_msg = NULL; } @@ -2057,7 +2062,7 @@ static struct ceph_msg *get_reply(struct ceph_connection *con, #endif } *skip = 0; - req->r_con_filling_msg = ceph_con_get(con); + req->r_con_filling_msg = con->ops->get(con); dout("get_reply tid %lld %p\n", tid, m); out: @@ -2074,6 +2079,7 @@ static struct ceph_msg *alloc_msg(struct ceph_connection *con, int type = le16_to_cpu(hdr->type); int front = le32_to_cpu(hdr->front_len); + *skip = 0; switch (type) { case CEPH_MSG_OSD_MAP: case CEPH_MSG_WATCH_NOTIFY: @@ -2108,37 +2114,32 @@ static void put_osd_con(struct ceph_connection *con) /* * authentication */ -static int get_authorizer(struct ceph_connection *con, - void **buf, int *len, int *proto, - void **reply_buf, int *reply_len, int force_new) +/* + * Note: returned pointer is the address of a structure that's + * managed separately. Caller must *not* attempt to free it. + */ +static struct ceph_auth_handshake *get_authorizer(struct ceph_connection *con, + int *proto, int force_new) { struct ceph_osd *o = con->private; struct ceph_osd_client *osdc = o->o_osdc; struct ceph_auth_client *ac = osdc->client->monc.auth; - int ret = 0; + struct ceph_auth_handshake *auth = &o->o_auth; - if (force_new && o->o_authorizer) { - ac->ops->destroy_authorizer(ac, o->o_authorizer); - o->o_authorizer = NULL; - } - if (o->o_authorizer == NULL) { - ret = ac->ops->create_authorizer( - ac, CEPH_ENTITY_TYPE_OSD, - &o->o_authorizer, - &o->o_authorizer_buf, - &o->o_authorizer_buf_len, - &o->o_authorizer_reply_buf, - &o->o_authorizer_reply_buf_len); + if (force_new && auth->authorizer) { + if (ac->ops && ac->ops->destroy_authorizer) + ac->ops->destroy_authorizer(ac, auth->authorizer); + auth->authorizer = NULL; + } + if (!auth->authorizer && ac->ops && ac->ops->create_authorizer) { + int ret = ac->ops->create_authorizer(ac, CEPH_ENTITY_TYPE_OSD, + auth); if (ret) - return ret; + return ERR_PTR(ret); } - *proto = ac->protocol; - *buf = o->o_authorizer_buf; - *len = o->o_authorizer_buf_len; - *reply_buf = o->o_authorizer_reply_buf; - *reply_len = o->o_authorizer_reply_buf_len; - return 0; + + return auth; } @@ -2148,7 +2149,11 @@ static int verify_authorizer_reply(struct ceph_connection *con, int len) struct ceph_osd_client *osdc = o->o_osdc; struct ceph_auth_client *ac = osdc->client->monc.auth; - return ac->ops->verify_authorizer_reply(ac, o->o_authorizer, len); + /* + * XXX If ac->ops or ac->ops->verify_authorizer_reply is null, + * XXX which do we do: succeed or fail? + */ + return ac->ops->verify_authorizer_reply(ac, o->o_auth.authorizer, len); } static int invalidate_authorizer(struct ceph_connection *con) @@ -2157,7 +2162,7 @@ static int invalidate_authorizer(struct ceph_connection *con) struct ceph_osd_client *osdc = o->o_osdc; struct ceph_auth_client *ac = osdc->client->monc.auth; - if (ac->ops->invalidate_authorizer) + if (ac->ops && ac->ops->invalidate_authorizer) ac->ops->invalidate_authorizer(ac, CEPH_ENTITY_TYPE_OSD); return ceph_monc_validate_auth(&osdc->client->monc); diff --git a/net/ceph/osdmap.c b/net/ceph/osdmap.c index 29ad46ec9dc..7fbe21030f5 100644 --- a/net/ceph/osdmap.c +++ b/net/ceph/osdmap.c @@ -495,15 +495,16 @@ static int __decode_pool_names(void **p, void *end, struct ceph_osdmap *map) ceph_decode_32_safe(p, end, pool, bad); ceph_decode_32_safe(p, end, len, bad); dout(" pool %d len %d\n", pool, len); + ceph_decode_need(p, end, len, bad); pi = __lookup_pg_pool(&map->pg_pools, pool); if (pi) { + char *name = kstrndup(*p, len, GFP_NOFS); + + if (!name) + return -ENOMEM; kfree(pi->name); - pi->name = kmalloc(len + 1, GFP_NOFS); - if (pi->name) { - memcpy(pi->name, *p, len); - pi->name[len] = '\0'; - dout(" name is %s\n", pi->name); - } + pi->name = name; + dout(" name is %s\n", pi->name); } *p += len; } @@ -612,10 +613,12 @@ struct ceph_osdmap *osdmap_decode(void **p, void *end) ceph_decode_32_safe(p, end, max, bad); while (max--) { ceph_decode_need(p, end, 4 + 1 + sizeof(pi->v), bad); + err = -ENOMEM; pi = kzalloc(sizeof(*pi), GFP_NOFS); if (!pi) goto bad; pi->id = ceph_decode_32(p); + err = -EINVAL; ev = ceph_decode_8(p); /* encoding version */ if (ev > CEPH_PG_POOL_VERSION) { pr_warning("got unknown v %d > %d of ceph_pg_pool\n", @@ -631,8 +634,13 @@ struct ceph_osdmap *osdmap_decode(void **p, void *end) __insert_pg_pool(&map->pg_pools, pi); } - if (version >= 5 && __decode_pool_names(p, end, map) < 0) - goto bad; + if (version >= 5) { + err = __decode_pool_names(p, end, map); + if (err < 0) { + dout("fail to decode pool names"); + goto bad; + } + } ceph_decode_32_safe(p, end, map->pool_max, bad); @@ -673,6 +681,9 @@ struct ceph_osdmap *osdmap_decode(void **p, void *end) ceph_decode_need(p, end, sizeof(u32) + sizeof(u64), bad); ceph_decode_copy(p, &pgid, sizeof(pgid)); n = ceph_decode_32(p); + err = -EINVAL; + if (n > (UINT_MAX - sizeof(*pg)) / sizeof(u32)) + goto bad; ceph_decode_need(p, end, n * sizeof(u32), bad); err = -ENOMEM; pg = kmalloc(sizeof(*pg) + n*sizeof(u32), GFP_NOFS); @@ -709,7 +720,7 @@ struct ceph_osdmap *osdmap_decode(void **p, void *end) return map; bad: - dout("osdmap_decode fail\n"); + dout("osdmap_decode fail err %d\n", err); ceph_osdmap_destroy(map); return ERR_PTR(err); } @@ -803,6 +814,7 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end, if (ev > CEPH_PG_POOL_VERSION) { pr_warning("got unknown v %d > %d of ceph_pg_pool\n", ev, CEPH_PG_POOL_VERSION); + err = -EINVAL; goto bad; } pi = __lookup_pg_pool(&map->pg_pools, pool); @@ -819,8 +831,11 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end, if (err < 0) goto bad; } - if (version >= 5 && __decode_pool_names(p, end, map) < 0) - goto bad; + if (version >= 5) { + err = __decode_pool_names(p, end, map); + if (err < 0) + goto bad; + } /* old_pool */ ceph_decode_32_safe(p, end, len, bad); @@ -890,13 +905,19 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end, pglen = ceph_decode_32(p); if (pglen) { - /* insert */ ceph_decode_need(p, end, pglen*sizeof(u32), bad); + + /* removing existing (if any) */ + (void) __remove_pg_mapping(&map->pg_temp, pgid); + + /* insert */ + err = -EINVAL; + if (pglen > (UINT_MAX - sizeof(*pg)) / sizeof(u32)) + goto bad; + err = -ENOMEM; pg = kmalloc(sizeof(*pg) + sizeof(u32)*pglen, GFP_NOFS); - if (!pg) { - err = -ENOMEM; + if (!pg) goto bad; - } pg->pgid = pgid; pg->len = pglen; for (j = 0; j < pglen; j++) @@ -940,7 +961,7 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end, * for now, we write only a single su, until we can * pass a stride back to the caller. */ -void ceph_calc_file_object_mapping(struct ceph_file_layout *layout, +int ceph_calc_file_object_mapping(struct ceph_file_layout *layout, u64 off, u64 *plen, u64 *ono, u64 *oxoff, u64 *oxlen) @@ -954,11 +975,17 @@ void ceph_calc_file_object_mapping(struct ceph_file_layout *layout, dout("mapping %llu~%llu osize %u fl_su %u\n", off, *plen, osize, su); + if (su == 0 || sc == 0) + goto invalid; su_per_object = osize / su; + if (su_per_object == 0) + goto invalid; dout("osize %u / su %u = su_per_object %u\n", osize, su, su_per_object); - BUG_ON((su & ~PAGE_MASK) != 0); + if ((su & ~PAGE_MASK) != 0) + goto invalid; + /* bl = *off / su; */ t = off; do_div(t, su); @@ -986,6 +1013,14 @@ void ceph_calc_file_object_mapping(struct ceph_file_layout *layout, *plen = *oxlen; dout(" obj extent %llu~%llu\n", *oxoff, *oxlen); + return 0; + +invalid: + dout(" invalid layout\n"); + *ono = 0; + *oxoff = 0; + *oxlen = 0; + return -EINVAL; } EXPORT_SYMBOL(ceph_calc_file_object_mapping); diff --git a/net/compat.c b/net/compat.c index e055708b8ec..ae6d67ad03b 100644 --- a/net/compat.c +++ b/net/compat.c @@ -221,6 +221,8 @@ int put_cmsg_compat(struct msghdr *kmsg, int level, int type, int len, void *dat { struct compat_cmsghdr __user *cm = (struct compat_cmsghdr __user *) kmsg->msg_control; struct compat_cmsghdr cmhdr; + struct compat_timeval ctv; + struct compat_timespec cts[3]; int cmlen; if (cm == NULL || kmsg->msg_controllen < sizeof(*cm)) { @@ -229,8 +231,6 @@ int put_cmsg_compat(struct msghdr *kmsg, int level, int type, int len, void *dat } if (!COMPAT_USE_64BIT_TIME) { - struct compat_timeval ctv; - struct compat_timespec cts[3]; if (level == SOL_SOCKET && type == SCM_TIMESTAMP) { struct timeval *tv = (struct timeval *)data; ctv.tv_sec = tv->tv_sec; diff --git a/net/core/dev.c b/net/core/dev.c index c299416d0e8..eb858dc6ab8 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1056,6 +1056,8 @@ int dev_change_name(struct net_device *dev, const char *newname) */ int dev_set_alias(struct net_device *dev, const char *alias, size_t len) { + char *new_ifalias; + ASSERT_RTNL(); if (len >= IFALIASZ) @@ -1069,9 +1071,10 @@ int dev_set_alias(struct net_device *dev, const char *alias, size_t len) return 0; } - dev->ifalias = krealloc(dev->ifalias, len + 1, GFP_KERNEL); - if (!dev->ifalias) + new_ifalias = krealloc(dev->ifalias, len + 1, GFP_KERNEL); + if (!new_ifalias) return -ENOMEM; + dev->ifalias = new_ifalias; strlcpy(dev->ifalias, alias, len+1); return len; @@ -1638,6 +1641,19 @@ static inline int deliver_skb(struct sk_buff *skb, return pt_prev->func(skb, skb->dev, pt_prev, orig_dev); } +static inline bool skb_loop_sk(struct packet_type *ptype, struct sk_buff *skb) +{ + if (!ptype->af_packet_priv || !skb->sk) + return false; + + if (ptype->id_match) + return ptype->id_match(ptype, skb->sk); + else if ((struct sock *)ptype->af_packet_priv == skb->sk) + return true; + + return false; +} + /* * Support routine. Sends outgoing frames to any network * taps currently in use. @@ -1655,8 +1671,7 @@ static void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev) * they originated from - MvS (miquels@drinkel.ow.org) */ if ((ptype->dev == dev || !ptype->dev) && - (ptype->af_packet_priv == NULL || - (struct sock *)ptype->af_packet_priv != skb->sk)) { + (!skb_loop_sk(ptype, skb))) { if (pt_prev) { deliver_skb(skb2, pt_prev, skb->dev); pt_prev = ptype; @@ -2106,7 +2121,8 @@ static bool can_checksum_protocol(netdev_features_t features, __be16 protocol) static netdev_features_t harmonize_features(struct sk_buff *skb, __be16 protocol, netdev_features_t features) { - if (!can_checksum_protocol(features, protocol)) { + if (skb->ip_summed != CHECKSUM_NONE && + !can_checksum_protocol(features, protocol)) { features &= ~NETIF_F_ALL_CSUM; features &= ~NETIF_F_SG; } else if (illegal_highdma(skb->dev, skb)) { @@ -2121,6 +2137,9 @@ netdev_features_t netif_skb_features(struct sk_buff *skb) __be16 protocol = skb->protocol; netdev_features_t features = skb->dev->features; + if (skb_shinfo(skb)->gso_segs > skb->dev->gso_max_segs) + features &= ~NETIF_F_GSO_MASK; + if (protocol == htons(ETH_P_8021Q)) { struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data; protocol = veh->h_vlan_encapsulated_proto; @@ -2599,15 +2618,16 @@ void __skb_get_rxhash(struct sk_buff *skb) if (!skb_flow_dissect(skb, &keys)) return; - if (keys.ports) { - if ((__force u16)keys.port16[1] < (__force u16)keys.port16[0]) - swap(keys.port16[0], keys.port16[1]); + if (keys.ports) skb->l4_rxhash = 1; - } /* get a consistent hash (same value on both flow directions) */ - if ((__force u32)keys.dst < (__force u32)keys.src) + if (((__force u32)keys.dst < (__force u32)keys.src) || + (((__force u32)keys.dst == (__force u32)keys.src) && + ((__force u16)keys.port16[1] < (__force u16)keys.port16[0]))) { swap(keys.dst, keys.src); + swap(keys.port16[0], keys.port16[1]); + } hash = jhash_3words((__force u32)keys.dst, (__force u32)keys.src, @@ -2743,8 +2763,10 @@ static int get_rps_cpu(struct net_device *dev, struct sk_buff *skb, if (unlikely(tcpu != next_cpu) && (tcpu == RPS_NO_CPU || !cpu_online(tcpu) || ((int)(per_cpu(softnet_data, tcpu).input_queue_head - - rflow->last_qtail)) >= 0)) + rflow->last_qtail)) >= 0)) { + tcpu = next_cpu; rflow = set_rps_cpu(dev, skb, rflow, next_cpu); + } if (tcpu != RPS_NO_CPU && cpu_online(tcpu)) { *rflowp = rflow; @@ -3189,18 +3211,18 @@ static int __netif_receive_skb(struct sk_buff *skb) ncls: #endif - rx_handler = rcu_dereference(skb->dev->rx_handler); if (vlan_tx_tag_present(skb)) { if (pt_prev) { ret = deliver_skb(skb, pt_prev, orig_dev); pt_prev = NULL; } - if (vlan_do_receive(&skb, !rx_handler)) + if (vlan_do_receive(&skb)) goto another_round; else if (unlikely(!skb)) goto out; } + rx_handler = rcu_dereference(skb->dev->rx_handler); if (rx_handler) { if (pt_prev) { ret = deliver_skb(skb, pt_prev, orig_dev); @@ -3220,6 +3242,9 @@ static int __netif_receive_skb(struct sk_buff *skb) } } + if (vlan_tx_nonzero_tag_present(skb)) + skb->pkt_type = PACKET_OTHERHOST; + /* deliver only exact match when indicated */ null_or_dev = deliver_exact ? skb->dev : NULL; @@ -5909,6 +5934,7 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name, dev_net_set(dev, &init_net); dev->gso_max_size = GSO_MAX_SIZE; + dev->gso_max_segs = GSO_MAX_SEGS; INIT_LIST_HEAD(&dev->napi_list); INIT_LIST_HEAD(&dev->unreg_list); @@ -6284,7 +6310,8 @@ static struct hlist_head *netdev_create_hash(void) /* Initialize per network namespace state */ static int __net_init netdev_init(struct net *net) { - INIT_LIST_HEAD(&net->dev_base_head); + if (net != &init_net) + INIT_LIST_HEAD(&net->dev_base_head); net->dev_name_head = netdev_create_hash(); if (net->dev_name_head == NULL) diff --git a/net/core/dev_addr_lists.c b/net/core/dev_addr_lists.c index 626698f0db8..76f6d0b02f2 100644 --- a/net/core/dev_addr_lists.c +++ b/net/core/dev_addr_lists.c @@ -308,7 +308,8 @@ int dev_addr_del(struct net_device *dev, unsigned char *addr, */ ha = list_first_entry(&dev->dev_addrs.list, struct netdev_hw_addr, list); - if (ha->addr == dev->dev_addr && ha->refcount == 1) + if (!memcmp(ha->addr, addr, dev->addr_len) && + ha->type == addr_type && ha->refcount == 1) return -ENOENT; err = __hw_addr_del(&dev->dev_addrs, addr, dev->addr_len, diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 73b90351df5..ac88107d1bc 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -1285,8 +1285,6 @@ int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb) if (!dst) goto discard; - __skb_pull(skb, skb_network_offset(skb)); - if (!neigh_event_send(neigh, skb)) { int err; struct net_device *dev = neigh->dev; @@ -1296,6 +1294,7 @@ int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb) neigh_hh_init(neigh, dst); do { + __skb_pull(skb, skb_network_offset(skb)); seq = read_seqbegin(&neigh->ha_lock); err = dev_hard_header(skb, dev, ntohs(skb->protocol), neigh->ha, NULL, skb->len); @@ -1326,9 +1325,8 @@ int neigh_connected_output(struct neighbour *neigh, struct sk_buff *skb) unsigned int seq; int err; - __skb_pull(skb, skb_network_offset(skb)); - do { + __skb_pull(skb, skb_network_offset(skb)); seq = read_seqbegin(&neigh->ha_lock); err = dev_hard_header(skb, dev, ntohs(skb->protocol), neigh->ha, NULL, skb->len); diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index 31a5ae51a45..dd00b71dd09 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -25,7 +25,9 @@ static DEFINE_MUTEX(net_mutex); LIST_HEAD(net_namespace_list); EXPORT_SYMBOL_GPL(net_namespace_list); -struct net init_net; +struct net init_net = { + .dev_base_head = LIST_HEAD_INIT(init_net.dev_base_head), +}; EXPORT_SYMBOL(init_net); #define INITIAL_NET_GEN_PTRS 13 /* +1 for len +2 for rcu_head */ diff --git a/net/core/pktgen.c b/net/core/pktgen.c index b81369b6ddc..8dae76f481e 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -2932,7 +2932,7 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev, sizeof(struct ipv6hdr) - sizeof(struct udphdr) - pkt_dev->pkt_overhead; - if (datalen < sizeof(struct pktgen_hdr)) { + if (datalen < 0 || datalen < sizeof(struct pktgen_hdr)) { datalen = sizeof(struct pktgen_hdr); if (net_ratelimit()) pr_info("increased datalen to %d\n", datalen); diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index c897d512f2c..900fc6162c4 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -671,6 +671,12 @@ static void set_operstate(struct net_device *dev, unsigned char transition) } } +static unsigned int rtnl_dev_get_flags(const struct net_device *dev) +{ + return (dev->flags & ~(IFF_PROMISC | IFF_ALLMULTI)) | + (dev->gflags & (IFF_PROMISC | IFF_ALLMULTI)); +} + static unsigned int rtnl_dev_combine_flags(const struct net_device *dev, const struct ifinfomsg *ifm) { @@ -679,7 +685,7 @@ static unsigned int rtnl_dev_combine_flags(const struct net_device *dev, /* bugwards compatibility: ifi_change == 0 is treated as ~0 */ if (ifm->ifi_change) flags = (flags & ifm->ifi_change) | - (dev->flags & ~ifm->ifi_change); + (rtnl_dev_get_flags(dev) & ~ifm->ifi_change); return flags; } diff --git a/net/core/sock.c b/net/core/sock.c index 0f8402ea434..4b469e36792 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -644,7 +644,8 @@ int sock_setsockopt(struct socket *sock, int level, int optname, case SO_KEEPALIVE: #ifdef CONFIG_INET - if (sk->sk_protocol == IPPROTO_TCP) + if (sk->sk_protocol == IPPROTO_TCP && + sk->sk_type == SOCK_STREAM) tcp_set_keepalive(sk, valbool); #endif sock_valbool_flag(sk, SOCK_KEEPOPEN, valbool); @@ -1411,6 +1412,7 @@ void sk_setup_caps(struct sock *sk, struct dst_entry *dst) } else { sk->sk_route_caps |= NETIF_F_SG | NETIF_F_HW_CSUM; sk->sk_gso_max_size = dst->dev->gso_max_size; + sk->sk_gso_max_segs = dst->dev->gso_max_segs; } } } diff --git a/net/dccp/ccid.h b/net/dccp/ccid.h index 75c3582a767..fb85d371a8d 100644 --- a/net/dccp/ccid.h +++ b/net/dccp/ccid.h @@ -246,7 +246,7 @@ static inline int ccid_hc_rx_getsockopt(struct ccid *ccid, struct sock *sk, u32 __user *optval, int __user *optlen) { int rc = -ENOPROTOOPT; - if (ccid->ccid_ops->ccid_hc_rx_getsockopt != NULL) + if (ccid != NULL && ccid->ccid_ops->ccid_hc_rx_getsockopt != NULL) rc = ccid->ccid_ops->ccid_hc_rx_getsockopt(sk, optname, len, optval, optlen); return rc; @@ -257,7 +257,7 @@ static inline int ccid_hc_tx_getsockopt(struct ccid *ccid, struct sock *sk, u32 __user *optval, int __user *optlen) { int rc = -ENOPROTOOPT; - if (ccid->ccid_ops->ccid_hc_tx_getsockopt != NULL) + if (ccid != NULL && ccid->ccid_ops->ccid_hc_tx_getsockopt != NULL) rc = ccid->ccid_ops->ccid_hc_tx_getsockopt(sk, optname, len, optval, optlen); return rc; diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index 70bfaf2d196..b658f3b8a23 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -531,6 +531,7 @@ static int ccid3_hc_tx_getsockopt(struct sock *sk, const int optname, int len, case DCCP_SOCKOPT_CCID_TX_INFO: if (len < sizeof(tfrc)) return -EINVAL; + memset(&tfrc, 0, sizeof(tfrc)); tfrc.tfrctx_x = hc->tx_x; tfrc.tfrctx_x_recv = hc->tx_x_recv; tfrc.tfrctx_x_calc = hc->tx_x_calc; diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index caf6e1734b6..c6f6e425b2e 100644 --- a/net/dccp/ipv4.c +++ b/net/dccp/ipv4.c @@ -435,8 +435,8 @@ struct sock *dccp_v4_request_recv_sock(struct sock *sk, struct sk_buff *skb, NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); return NULL; put_and_exit: - bh_unlock_sock(newsk); - sock_put(newsk); + inet_csk_prepare_forced_close(newsk); + dccp_done(newsk); goto exit; } diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 4dc588f520e..aaa8f8bee9e 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c @@ -611,7 +611,8 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk, newinet->inet_rcv_saddr = LOOPBACK4_IPV6; if (__inet_inherit_port(sk, newsk) < 0) { - sock_put(newsk); + inet_csk_prepare_forced_close(newsk); + dccp_done(newsk); goto out; } __inet6_hash(newsk, NULL); diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c index c48adc565e9..667c1d4ca98 100644 --- a/net/ipv4/cipso_ipv4.c +++ b/net/ipv4/cipso_ipv4.c @@ -1725,8 +1725,10 @@ int cipso_v4_validate(const struct sk_buff *skb, unsigned char **option) case CIPSO_V4_TAG_LOCAL: /* This is a non-standard tag that we only allow for * local connections, so if the incoming interface is - * not the loopback device drop the packet. */ - if (!(skb->dev->flags & IFF_LOOPBACK)) { + * not the loopback device drop the packet. Further, + * there is no legitimate reason for setting this from + * userspace so reject it if skb is NULL. */ + if (skb == NULL || !(skb->dev->flags & IFF_LOOPBACK)) { err_offset = opt_iter; goto validate_return_locked; } diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 19d66cefd7d..3f404325854 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -659,6 +659,22 @@ void inet_csk_destroy_sock(struct sock *sk) } EXPORT_SYMBOL(inet_csk_destroy_sock); +/* This function allows to force a closure of a socket after the call to + * tcp/dccp_create_openreq_child(). + */ +void inet_csk_prepare_forced_close(struct sock *sk) +{ + /* sk_clone_lock locked the socket and set refcnt to 2 */ + bh_unlock_sock(sk); + sock_put(sk); + + /* The below has to be done to allow calling inet_csk_destroy_sock */ + sock_set_flag(sk, SOCK_DEAD); + percpu_counter_inc(sk->sk_prot->orphan_count); + inet_sk(sk)->inet_num = 0; +} +EXPORT_SYMBOL(inet_csk_prepare_forced_close); + int inet_csk_listen_start(struct sock *sk, const int nr_table_entries) { struct inet_sock *inet = inet_sk(sk); diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index 8f8db724bfa..d7b862ad4be 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c @@ -44,6 +44,10 @@ struct inet_diag_entry { u16 dport; u16 family; u16 userlocks; +#if IS_ENABLED(CONFIG_IPV6) + struct in6_addr saddr_storage; /* for IPv4-mapped-IPv6 addresses */ + struct in6_addr daddr_storage; /* for IPv4-mapped-IPv6 addresses */ +#endif }; #define INET_DIAG_PUT(skb, attrtype, attrlen) \ @@ -419,25 +423,31 @@ static int inet_diag_bc_run(const struct nlattr *_bc, break; } - if (cond->prefix_len == 0) - break; - if (op->code == INET_DIAG_BC_S_COND) addr = entry->saddr; else addr = entry->daddr; + if (cond->family != AF_UNSPEC && + cond->family != entry->family) { + if (entry->family == AF_INET6 && + cond->family == AF_INET) { + if (addr[0] == 0 && addr[1] == 0 && + addr[2] == htonl(0xffff) && + bitstring_match(addr + 3, + cond->addr, + cond->prefix_len)) + break; + } + yes = 0; + break; + } + + if (cond->prefix_len == 0) + break; if (bitstring_match(addr, cond->addr, cond->prefix_len)) break; - if (entry->family == AF_INET6 && - cond->family == AF_INET) { - if (addr[0] == 0 && addr[1] == 0 && - addr[2] == htonl(0xffff) && - bitstring_match(addr + 3, cond->addr, - cond->prefix_len)) - break; - } yes = 0; break; } @@ -500,6 +510,55 @@ static int valid_cc(const void *bc, int len, int cc) return 0; } +/* Validate an inet_diag_hostcond. */ +static bool valid_hostcond(const struct inet_diag_bc_op *op, int len, + int *min_len) +{ + int addr_len; + struct inet_diag_hostcond *cond; + + /* Check hostcond space. */ + *min_len += sizeof(struct inet_diag_hostcond); + if (len < *min_len) + return false; + cond = (struct inet_diag_hostcond *)(op + 1); + + /* Check address family and address length. */ + switch (cond->family) { + case AF_UNSPEC: + addr_len = 0; + break; + case AF_INET: + addr_len = sizeof(struct in_addr); + break; + case AF_INET6: + addr_len = sizeof(struct in6_addr); + break; + default: + return false; + } + *min_len += addr_len; + if (len < *min_len) + return false; + + /* Check prefix length (in bits) vs address length (in bytes). */ + if (cond->prefix_len > 8 * addr_len) + return false; + + return true; +} + +/* Validate a port comparison operator. */ +static inline bool valid_port_comparison(const struct inet_diag_bc_op *op, + int len, int *min_len) +{ + /* Port comparisons put the port in a follow-on inet_diag_bc_op. */ + *min_len += sizeof(struct inet_diag_bc_op); + if (len < *min_len) + return false; + return true; +} + static int inet_diag_bc_audit(const void *bytecode, int bytecode_len) { const void *bc = bytecode; @@ -507,29 +566,39 @@ static int inet_diag_bc_audit(const void *bytecode, int bytecode_len) while (len > 0) { const struct inet_diag_bc_op *op = bc; + int min_len = sizeof(struct inet_diag_bc_op); //printk("BC: %d %d %d {%d} / %d\n", op->code, op->yes, op->no, op[1].no, len); switch (op->code) { - case INET_DIAG_BC_AUTO: case INET_DIAG_BC_S_COND: case INET_DIAG_BC_D_COND: + if (!valid_hostcond(bc, len, &min_len)) + return -EINVAL; + break; case INET_DIAG_BC_S_GE: case INET_DIAG_BC_S_LE: case INET_DIAG_BC_D_GE: case INET_DIAG_BC_D_LE: - case INET_DIAG_BC_JMP: - if (op->no < 4 || op->no > len + 4 || op->no & 3) - return -EINVAL; - if (op->no < len && - !valid_cc(bytecode, bytecode_len, len - op->no)) + if (!valid_port_comparison(bc, len, &min_len)) return -EINVAL; break; + case INET_DIAG_BC_AUTO: + case INET_DIAG_BC_JMP: case INET_DIAG_BC_NOP: break; default: return -EINVAL; } - if (op->yes < 4 || op->yes > len + 4 || op->yes & 3) + + if (op->code != INET_DIAG_BC_NOP) { + if (op->no < min_len || op->no > len + 4 || op->no & 3) + return -EINVAL; + if (op->no < len && + !valid_cc(bytecode, bytecode_len, len - op->no)) + return -EINVAL; + } + + if (op->yes < min_len || op->yes > len + 4 || op->yes & 3) return -EINVAL; bc += op->yes; len -= op->yes; @@ -586,6 +655,36 @@ static int inet_twsk_diag_dump(struct inet_timewait_sock *tw, cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh); } +/* Get the IPv4, IPv6, or IPv4-mapped-IPv6 local and remote addresses + * from a request_sock. For IPv4-mapped-IPv6 we must map IPv4 to IPv6. + */ +static inline void inet_diag_req_addrs(const struct sock *sk, + const struct request_sock *req, + struct inet_diag_entry *entry) +{ + struct inet_request_sock *ireq = inet_rsk(req); + +#if IS_ENABLED(CONFIG_IPV6) + if (sk->sk_family == AF_INET6) { + if (req->rsk_ops->family == AF_INET6) { + entry->saddr = inet6_rsk(req)->loc_addr.s6_addr32; + entry->daddr = inet6_rsk(req)->rmt_addr.s6_addr32; + } else if (req->rsk_ops->family == AF_INET) { + ipv6_addr_set_v4mapped(ireq->loc_addr, + &entry->saddr_storage); + ipv6_addr_set_v4mapped(ireq->rmt_addr, + &entry->daddr_storage); + entry->saddr = entry->saddr_storage.s6_addr32; + entry->daddr = entry->daddr_storage.s6_addr32; + } + } else +#endif + { + entry->saddr = &ireq->loc_addr; + entry->daddr = &ireq->rmt_addr; + } +} + static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk, struct request_sock *req, u32 pid, u32 seq, const struct nlmsghdr *unlh) @@ -624,8 +723,10 @@ static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk, r->idiag_inode = 0; #if IS_ENABLED(CONFIG_IPV6) if (r->idiag_family == AF_INET6) { - *(struct in6_addr *)r->id.idiag_src = inet6_rsk(req)->loc_addr; - *(struct in6_addr *)r->id.idiag_dst = inet6_rsk(req)->rmt_addr; + struct inet_diag_entry entry; + inet_diag_req_addrs(sk, req, &entry); + memcpy(r->id.idiag_src, entry.saddr, sizeof(struct in6_addr)); + memcpy(r->id.idiag_dst, entry.daddr, sizeof(struct in6_addr)); } #endif nlh->nlmsg_len = skb_tail_pointer(skb) - b; @@ -683,18 +784,7 @@ static int inet_diag_dump_reqs(struct sk_buff *skb, struct sock *sk, continue; if (bc) { - entry.saddr = -#if IS_ENABLED(CONFIG_IPV6) - (entry.family == AF_INET6) ? - inet6_rsk(req)->loc_addr.s6_addr32 : -#endif - &ireq->loc_addr; - entry.daddr = -#if IS_ENABLED(CONFIG_IPV6) - (entry.family == AF_INET6) ? - inet6_rsk(req)->rmt_addr.s6_addr32 : -#endif - &ireq->rmt_addr; + inet_diag_req_addrs(sk, req, &entry); entry.dport = ntohs(ireq->rmt_port); if (!inet_diag_bc_run(bc, &entry)) @@ -875,13 +965,16 @@ static int __inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb, struct inet_diag_req_v2 *r, struct nlattr *bc) { const struct inet_diag_handler *handler; + int err = 0; handler = inet_diag_lock_handler(r->sdiag_protocol); if (!IS_ERR(handler)) handler->dump(skb, cb, r, bc); + else + err = PTR_ERR(handler); inet_diag_unlock_handler(handler); - return skb->len; + return err ? : skb->len; } static int inet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb) diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index 3727e234c88..b7bf6e30adb 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c @@ -685,28 +685,27 @@ EXPORT_SYMBOL(ip_defrag); struct sk_buff *ip_check_defrag(struct sk_buff *skb, u32 user) { - const struct iphdr *iph; + struct iphdr iph; u32 len; if (skb->protocol != htons(ETH_P_IP)) return skb; - if (!pskb_may_pull(skb, sizeof(struct iphdr))) + if (!skb_copy_bits(skb, 0, &iph, sizeof(iph))) return skb; - iph = ip_hdr(skb); - if (iph->ihl < 5 || iph->version != 4) + if (iph.ihl < 5 || iph.version != 4) return skb; - if (!pskb_may_pull(skb, iph->ihl*4)) - return skb; - iph = ip_hdr(skb); - len = ntohs(iph->tot_len); - if (skb->len < len || len < (iph->ihl * 4)) + + len = ntohs(iph.tot_len); + if (skb->len < len || len < (iph.ihl * 4)) return skb; - if (ip_is_fragment(ip_hdr(skb))) { + if (ip_is_fragment(&iph)) { skb = skb_share_check(skb, GFP_ATOMIC); if (skb) { + if (!pskb_may_pull(skb, iph.ihl*4)) + return skb; if (pskb_trim_rcsum(skb, len)) return skb; memset(IPCB(skb), 0, sizeof(struct inet_skb_parm)); diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index 2fd0fba7712..59ef40abf50 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c @@ -456,19 +456,28 @@ static int do_ip_setsockopt(struct sock *sk, int level, struct inet_sock *inet = inet_sk(sk); int val = 0, err; - if (((1<= sizeof(int)) { if (get_user(val, (int __user *) optval)) return -EFAULT; diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 960fbfc3e97..8626b645ec6 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -124,6 +124,8 @@ static DEFINE_SPINLOCK(mfc_unres_lock); static struct kmem_cache *mrt_cachep __read_mostly; static struct mr_table *ipmr_new_table(struct net *net, u32 id); +static void ipmr_free_table(struct mr_table *mrt); + static int ip_mr_forward(struct net *net, struct mr_table *mrt, struct sk_buff *skb, struct mfc_cache *cache, int local); @@ -131,6 +133,7 @@ static int ipmr_cache_report(struct mr_table *mrt, struct sk_buff *pkt, vifi_t vifi, int assert); static int __ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb, struct mfc_cache *c, struct rtmsg *rtm); +static void mroute_clean_tables(struct mr_table *mrt); static void ipmr_expire_process(unsigned long arg); #ifdef CONFIG_IP_MROUTE_MULTIPLE_TABLES @@ -271,7 +274,7 @@ static void __net_exit ipmr_rules_exit(struct net *net) list_for_each_entry_safe(mrt, next, &net->ipv4.mr_tables, list) { list_del(&mrt->list); - kfree(mrt); + ipmr_free_table(mrt); } fib_rules_unregister(net->ipv4.mr_rules_ops); } @@ -299,7 +302,7 @@ static int __net_init ipmr_rules_init(struct net *net) static void __net_exit ipmr_rules_exit(struct net *net) { - kfree(net->ipv4.mrt); + ipmr_free_table(net->ipv4.mrt); } #endif @@ -336,6 +339,13 @@ static struct mr_table *ipmr_new_table(struct net *net, u32 id) return mrt; } +static void ipmr_free_table(struct mr_table *mrt) +{ + del_timer_sync(&mrt->ipmr_expire_timer); + mroute_clean_tables(mrt); + kfree(mrt); +} + /* Service routines creating virtual interfaces: DVMRP tunnels and PIMREG */ static void ipmr_del_tunnel(struct net_device *dev, struct vifctl *v) diff --git a/net/ipv4/netfilter/nf_nat_sip.c b/net/ipv4/netfilter/nf_nat_sip.c index 57932c43960..566be2dd73f 100644 --- a/net/ipv4/netfilter/nf_nat_sip.c +++ b/net/ipv4/netfilter/nf_nat_sip.c @@ -148,7 +148,7 @@ static unsigned int ip_nat_sip(struct sk_buff *skb, unsigned int dataoff, if (ct_sip_parse_header_uri(ct, *dptr, NULL, *datalen, hdr, NULL, &matchoff, &matchlen, &addr, &port) > 0) { - unsigned int matchend, poff, plen, buflen, n; + unsigned int olen, matchend, poff, plen, buflen, n; char buffer[sizeof("nnn.nnn.nnn.nnn:nnnnn")]; /* We're only interested in headers related to this @@ -163,11 +163,12 @@ static unsigned int ip_nat_sip(struct sk_buff *skb, unsigned int dataoff, goto next; } + olen = *datalen; if (!map_addr(skb, dataoff, dptr, datalen, matchoff, matchlen, &addr, port)) return NF_DROP; - matchend = matchoff + matchlen; + matchend = matchoff + matchlen + *datalen - olen; /* The maddr= parameter (RFC 2361) specifies where to send * the reply. */ @@ -501,7 +502,10 @@ static unsigned int ip_nat_sdp_media(struct sk_buff *skb, unsigned int dataoff, ret = nf_ct_expect_related(rtcp_exp); if (ret == 0) break; - else if (ret != -EBUSY) { + else if (ret == -EBUSY) { + nf_ct_unexpect_related(rtp_exp); + continue; + } else if (ret < 0) { nf_ct_unexpect_related(rtp_exp); port = 0; break; diff --git a/net/ipv4/netfilter/nf_nat_standalone.c b/net/ipv4/netfilter/nf_nat_standalone.c index 3828a422982..da4098f0878 100644 --- a/net/ipv4/netfilter/nf_nat_standalone.c +++ b/net/ipv4/netfilter/nf_nat_standalone.c @@ -194,7 +194,8 @@ nf_nat_out(unsigned int hooknum, if ((ct->tuplehash[dir].tuple.src.u3.ip != ct->tuplehash[!dir].tuple.dst.u3.ip) || - (ct->tuplehash[dir].tuple.src.u.all != + (ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP && + ct->tuplehash[dir].tuple.src.u.all != ct->tuplehash[!dir].tuple.dst.u.all) ) return ip_xfrm_me_harder(skb) == 0 ? ret : NF_DROP; @@ -230,7 +231,8 @@ nf_nat_local_fn(unsigned int hooknum, ret = NF_DROP; } #ifdef CONFIG_XFRM - else if (ct->tuplehash[dir].tuple.dst.u.all != + else if (ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP && + ct->tuplehash[dir].tuple.dst.u.all != ct->tuplehash[!dir].tuple.src.u.all) if (ip_xfrm_me_harder(skb)) ret = NF_DROP; diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c index 8af0d44e4e2..212897517b8 100644 --- a/net/ipv4/proc.c +++ b/net/ipv4/proc.c @@ -232,7 +232,6 @@ static const struct snmp_mib snmp4_net_list[] = { SNMP_MIB_ITEM("TCPDSACKOfoSent", LINUX_MIB_TCPDSACKOFOSENT), SNMP_MIB_ITEM("TCPDSACKRecv", LINUX_MIB_TCPDSACKRECV), SNMP_MIB_ITEM("TCPDSACKOfoRecv", LINUX_MIB_TCPDSACKOFORECV), - SNMP_MIB_ITEM("TCPAbortOnSyn", LINUX_MIB_TCPABORTONSYN), SNMP_MIB_ITEM("TCPAbortOnData", LINUX_MIB_TCPABORTONDATA), SNMP_MIB_ITEM("TCPAbortOnClose", LINUX_MIB_TCPABORTONCLOSE), SNMP_MIB_ITEM("TCPAbortOnMemory", LINUX_MIB_TCPABORTONMEMORY), @@ -258,6 +257,8 @@ static const struct snmp_mib snmp4_net_list[] = { SNMP_MIB_ITEM("TCPReqQFullDrop", LINUX_MIB_TCPREQQFULLDROP), SNMP_MIB_ITEM("TCPRetransFail", LINUX_MIB_TCPRETRANSFAIL), SNMP_MIB_ITEM("TCPRcvCoalesce", LINUX_MIB_TCPRCVCOALESCE), + SNMP_MIB_ITEM("TCPChallengeACK", LINUX_MIB_TCPCHALLENGEACK), + SNMP_MIB_ITEM("TCPSYNChallenge", LINUX_MIB_TCPSYNCHALLENGE), SNMP_MIB_SENTINEL }; diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index bbd604c68e6..2fe0dc28ea9 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -131,18 +131,20 @@ static struct sock *__raw_v4_lookup(struct net *net, struct sock *sk, * 0 - deliver * 1 - block */ -static __inline__ int icmp_filter(struct sock *sk, struct sk_buff *skb) +static int icmp_filter(const struct sock *sk, const struct sk_buff *skb) { - int type; + struct icmphdr _hdr; + const struct icmphdr *hdr; - if (!pskb_may_pull(skb, sizeof(struct icmphdr))) + hdr = skb_header_pointer(skb, skb_transport_offset(skb), + sizeof(_hdr), &_hdr); + if (!hdr) return 1; - type = icmp_hdr(skb)->type; - if (type < 32) { + if (hdr->type < 32) { __u32 data = raw_sk(sk)->filter.data; - return ((1 << type) & data) != 0; + return ((1U << hdr->type) & data) != 0; } /* Do not block unknown ICMP types */ diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index 7a7724da9bf..bf7a604c695 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -590,6 +590,13 @@ static struct ctl_table ipv4_table[] = { .mode = 0644, .proc_handler = proc_dointvec }, + { + .procname = "tcp_challenge_ack_limit", + .data = &sysctl_tcp_challenge_ack_limit, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec + }, #ifdef CONFIG_NET_DMA { .procname = "tcp_dma_copybreak", diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 74a286c2c43..89264f8b959 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -742,7 +742,9 @@ static unsigned int tcp_xmit_size_goal(struct sock *sk, u32 mss_now, old_size_goal + mss_now > xmit_size_goal)) { xmit_size_goal = old_size_goal; } else { - tp->xmit_size_goal_segs = xmit_size_goal / mss_now; + tp->xmit_size_goal_segs = + min_t(u16, xmit_size_goal / mss_now, + sk->sk_gso_max_segs); xmit_size_goal = tp->xmit_size_goal_segs * mss_now; } } @@ -1600,8 +1602,14 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, } #ifdef CONFIG_NET_DMA - if (tp->ucopy.dma_chan) - dma_async_memcpy_issue_pending(tp->ucopy.dma_chan); + if (tp->ucopy.dma_chan) { + if (tp->rcv_wnd == 0 && + !skb_queue_empty(&sk->sk_async_wait_queue)) { + tcp_service_net_dma(sk, true); + tcp_cleanup_rbuf(sk, copied); + } else + dma_async_memcpy_issue_pending(tp->ucopy.dma_chan); + } #endif if (copied >= target) { /* Do not sleep, just process backlog. */ @@ -2421,7 +2429,10 @@ static int do_tcp_setsockopt(struct sock *sk, int level, /* Cap the max timeout in ms TCP will retry/retrans * before giving up and aborting (ETIMEDOUT) a connection. */ - icsk->icsk_user_timeout = msecs_to_jiffies(val); + if (val < 0) + err = -EINVAL; + else + icsk->icsk_user_timeout = msecs_to_jiffies(val); break; default: err = -ENOPROTOOPT; diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c index 272a84593c8..69251dde750 100644 --- a/net/ipv4/tcp_cong.c +++ b/net/ipv4/tcp_cong.c @@ -291,7 +291,8 @@ int tcp_is_cwnd_limited(const struct sock *sk, u32 in_flight) left = tp->snd_cwnd - in_flight; if (sk_can_gso(sk) && left * sysctl_tcp_tso_win_divisor < tp->snd_cwnd && - left * tp->mss_cache < sk->sk_gso_max_size) + left * tp->mss_cache < sk->sk_gso_max_size && + left < sk->sk_gso_max_segs) return 1; return left <= tcp_max_tso_deferred_mss(tp); } diff --git a/net/ipv4/tcp_illinois.c b/net/ipv4/tcp_illinois.c index 813b43a76fe..834857f3c87 100644 --- a/net/ipv4/tcp_illinois.c +++ b/net/ipv4/tcp_illinois.c @@ -313,11 +313,13 @@ static void tcp_illinois_info(struct sock *sk, u32 ext, .tcpv_rttcnt = ca->cnt_rtt, .tcpv_minrtt = ca->base_rtt, }; - u64 t = ca->sum_rtt; - do_div(t, ca->cnt_rtt); - info.tcpv_rtt = t; + if (info.tcpv_rttcnt > 0) { + u64 t = ca->sum_rtt; + do_div(t, info.tcpv_rttcnt); + info.tcpv_rtt = t; + } nla_put(skb, INET_DIAG_VEGASINFO, sizeof(info), &info); } } diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 4988e3e436f..c16ce557931 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -88,6 +88,9 @@ int sysctl_tcp_app_win __read_mostly = 31; int sysctl_tcp_adv_win_scale __read_mostly = 1; EXPORT_SYMBOL(sysctl_tcp_adv_win_scale); +/* rfc5961 challenge ack rate limiting */ +int sysctl_tcp_challenge_ack_limit = 100; + int sysctl_tcp_stdurg __read_mostly; int sysctl_tcp_rfc1337 __read_mostly; int sysctl_tcp_max_orphans __read_mostly = NR_FILE; @@ -3037,13 +3040,14 @@ static void tcp_update_cwnd_in_recovery(struct sock *sk, int newly_acked_sacked, * tcp_xmit_retransmit_queue(). */ static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked, - int newly_acked_sacked, bool is_dupack, + int prior_sacked, bool is_dupack, int flag) { struct inet_connection_sock *icsk = inet_csk(sk); struct tcp_sock *tp = tcp_sk(sk); int do_lost = is_dupack || ((flag & FLAG_DATA_SACKED) && (tcp_fackets_out(tp) > tp->reordering)); + int newly_acked_sacked = 0; int fast_rexmit = 0, mib_idx; if (WARN_ON(!tp->packets_out && tp->sacked_out)) @@ -3103,6 +3107,7 @@ static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked, tcp_add_reno_sack(sk); } else do_lost = tcp_try_undo_partial(sk, pkts_acked); + newly_acked_sacked = pkts_acked + tp->sacked_out - prior_sacked; break; case TCP_CA_Loss: if (flag & FLAG_DATA_ACKED) @@ -3124,6 +3129,7 @@ static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked, if (is_dupack) tcp_add_reno_sack(sk); } + newly_acked_sacked = pkts_acked + tp->sacked_out - prior_sacked; if (icsk->icsk_ca_state <= TCP_CA_Disorder) tcp_try_undo_dsack(sk); @@ -3681,6 +3687,24 @@ static int tcp_process_frto(struct sock *sk, int flag) return 0; } +/* RFC 5961 7 [ACK Throttling] */ +static void tcp_send_challenge_ack(struct sock *sk) +{ + /* unprotected vars, we dont care of overwrites */ + static u32 challenge_timestamp; + static unsigned int challenge_count; + u32 now = jiffies / HZ; + + if (now != challenge_timestamp) { + challenge_timestamp = now; + challenge_count = 0; + } + if (++challenge_count <= sysctl_tcp_challenge_ack_limit) { + NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPCHALLENGEACK); + tcp_send_ack(sk); + } +} + /* This routine deals with incoming acks, but not outgoing ones. */ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) { @@ -3695,14 +3719,19 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) int prior_packets; int prior_sacked = tp->sacked_out; int pkts_acked = 0; - int newly_acked_sacked = 0; int frto_cwnd = 0; /* If the ack is older than previous acks * then we can probably ignore it. */ - if (before(ack, prior_snd_una)) + if (before(ack, prior_snd_una)) { + /* RFC 5961 5.2 [Blind Data Injection Attack].[Mitigation] */ + if (before(ack, prior_snd_una - tp->max_window)) { + tcp_send_challenge_ack(sk); + return -1; + } goto old_ack; + } /* If the ack includes data we haven't sent yet, discard * this segment (RFC793 Section 3.9). @@ -3768,8 +3797,6 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) flag |= tcp_clean_rtx_queue(sk, prior_fackets, prior_snd_una); pkts_acked = prior_packets - tp->packets_out; - newly_acked_sacked = (prior_packets - prior_sacked) - - (tp->packets_out - tp->sacked_out); if (tp->frto_counter) frto_cwnd = tcp_process_frto(sk, flag); @@ -3783,7 +3810,7 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) tcp_may_raise_cwnd(sk, flag)) tcp_cong_avoid(sk, ack, prior_in_flight); is_dupack = !(flag & (FLAG_SND_UNA_ADVANCED | FLAG_NOT_DUP)); - tcp_fastretrans_alert(sk, pkts_acked, newly_acked_sacked, + tcp_fastretrans_alert(sk, pkts_acked, prior_sacked, is_dupack, flag); } else { if ((flag & FLAG_DATA_ACKED) && !frto_cwnd) @@ -3798,7 +3825,7 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) no_queue: /* If data was DSACKed, see if we can undo a cwnd reduction. */ if (flag & FLAG_DSACKING_ACK) - tcp_fastretrans_alert(sk, pkts_acked, newly_acked_sacked, + tcp_fastretrans_alert(sk, pkts_acked, prior_sacked, is_dupack, flag); /* If this ack opens up a zero window, clear backoff. It was * being used to time the probes, and is probably far higher than @@ -3818,8 +3845,7 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) */ if (TCP_SKB_CB(skb)->sacked) { flag |= tcp_sacktag_write_queue(sk, skb, prior_snd_una); - newly_acked_sacked = tp->sacked_out - prior_sacked; - tcp_fastretrans_alert(sk, pkts_acked, newly_acked_sacked, + tcp_fastretrans_alert(sk, pkts_acked, prior_sacked, is_dupack, flag); } @@ -5270,8 +5296,8 @@ static int tcp_dma_try_early_copy(struct sock *sk, struct sk_buff *skb, /* Does PAWS and seqno based validation of an incoming segment, flags will * play significant role here. */ -static int tcp_validate_incoming(struct sock *sk, struct sk_buff *skb, - const struct tcphdr *th, int syn_inerr) +static bool tcp_validate_incoming(struct sock *sk, struct sk_buff *skb, + const struct tcphdr *th, int syn_inerr) { const u8 *hash_location; struct tcp_sock *tp = tcp_sk(sk); @@ -5296,38 +5322,48 @@ static int tcp_validate_incoming(struct sock *sk, struct sk_buff *skb, * an acknowledgment should be sent in reply (unless the RST * bit is set, if so drop the segment and return)". */ - if (!th->rst) + if (!th->rst) { + if (th->syn) + goto syn_challenge; tcp_send_dupack(sk, skb); + } goto discard; } /* Step 2: check RST bit */ if (th->rst) { - tcp_reset(sk); + /* RFC 5961 3.2 : + * If sequence number exactly matches RCV.NXT, then + * RESET the connection + * else + * Send a challenge ACK + */ + if (TCP_SKB_CB(skb)->seq == tp->rcv_nxt) + tcp_reset(sk); + else + tcp_send_challenge_ack(sk); goto discard; } - /* ts_recent update must be made after we are sure that the packet - * is in window. - */ - tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq); - /* step 3: check security and precedence [ignored] */ - /* step 4: Check for a SYN in window. */ - if (th->syn && !before(TCP_SKB_CB(skb)->seq, tp->rcv_nxt)) { + /* step 4: Check for a SYN + * RFC 5691 4.2 : Send a challenge ack + */ + if (th->syn) { +syn_challenge: if (syn_inerr) TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_INERRS); - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPABORTONSYN); - tcp_reset(sk); - return -1; + NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPSYNCHALLENGE); + tcp_send_challenge_ack(sk); + goto discard; } - return 1; + return true; discard: __kfree_skb(skb); - return 0; + return false; } /* @@ -5357,7 +5393,6 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb, const struct tcphdr *th, unsigned int len) { struct tcp_sock *tp = tcp_sk(sk); - int res; /* * Header prediction. @@ -5442,7 +5477,9 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb, if (tp->copied_seq == tp->rcv_nxt && len - tcp_header_len <= tp->ucopy.len) { #ifdef CONFIG_NET_DMA - if (tcp_dma_try_early_copy(sk, skb, tcp_header_len)) { + if (tp->ucopy.task == current && + sock_owned_by_user(sk) && + tcp_dma_try_early_copy(sk, skb, tcp_header_len)) { copied_early = 1; eaten = 1; } @@ -5535,14 +5572,18 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb, * Standard slow path. */ - res = tcp_validate_incoming(sk, skb, th, 1); - if (res <= 0) - return -res; + if (!tcp_validate_incoming(sk, skb, th, 1)) + return 0; step5: if (th->ack && tcp_ack(sk, skb, FLAG_SLOWPATH) < 0) goto discard; + /* ts_recent update must be made after we are sure that the packet + * is in window. + */ + tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq); + tcp_rcv_rtt_measure_ts(sk, skb); /* Process urgent data. */ @@ -5847,7 +5888,6 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, struct tcp_sock *tp = tcp_sk(sk); struct inet_connection_sock *icsk = inet_csk(sk); int queued = 0; - int res; tp->rx_opt.saw_tstamp = 0; @@ -5902,9 +5942,8 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, return 0; } - res = tcp_validate_incoming(sk, skb, th, 0); - if (res <= 0) - return -res; + if (!tcp_validate_incoming(sk, skb, th, 0)) + return 0; /* step 5: check the ACK field */ if (th->ack) { @@ -6015,6 +6054,11 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, } else goto discard; + /* ts_recent update must be made after we are sure that the packet + * is in window. + */ + tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq); + /* step 6: check the URG bit */ tcp_urg(sk, skb, th); diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 0cb86ceb652..76f50e1b53a 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -678,10 +678,11 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb) arg.csumoffset = offsetof(struct tcphdr, check) / 2; arg.flags = (sk && inet_sk(sk)->transparent) ? IP_REPLY_ARG_NOSRCCHECK : 0; /* When socket is gone, all binding information is lost. - * routing might fail in this case. using iif for oif to - * make sure we can deliver it + * routing might fail in this case. No choice here, if we choose to force + * input interface, we will misroute in case of asymmetric route. */ - arg.bound_dev_if = sk ? sk->sk_bound_dev_if : inet_iif(skb); + if (sk) + arg.bound_dev_if = sk->sk_bound_dev_if; net = dev_net(skb_dst(skb)->dev); arg.tos = ip_hdr(skb)->tos; @@ -1523,10 +1524,8 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb, NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); return NULL; put_and_exit: - tcp_clear_xmit_timers(newsk); - tcp_cleanup_congestion_control(newsk); - bh_unlock_sock(newsk); - sock_put(newsk); + inet_csk_prepare_forced_close(newsk); + tcp_done(newsk); goto exit; } EXPORT_SYMBOL(tcp_v4_syn_recv_sock); diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 7ac6423117a..2d27e1af930 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -1318,21 +1318,21 @@ static void tcp_cwnd_validate(struct sock *sk) * when we would be allowed to send the split-due-to-Nagle skb fully. */ static unsigned int tcp_mss_split_point(const struct sock *sk, const struct sk_buff *skb, - unsigned int mss_now, unsigned int cwnd) + unsigned int mss_now, unsigned int max_segs) { const struct tcp_sock *tp = tcp_sk(sk); - u32 needed, window, cwnd_len; + u32 needed, window, max_len; window = tcp_wnd_end(tp) - TCP_SKB_CB(skb)->seq; - cwnd_len = mss_now * cwnd; + max_len = mss_now * max_segs; - if (likely(cwnd_len <= window && skb != tcp_write_queue_tail(sk))) - return cwnd_len; + if (likely(max_len <= window && skb != tcp_write_queue_tail(sk))) + return max_len; needed = min(skb->len, window); - if (cwnd_len <= needed) - return cwnd_len; + if (max_len <= needed) + return max_len; return needed - needed % mss_now; } @@ -1560,7 +1560,8 @@ static int tcp_tso_should_defer(struct sock *sk, struct sk_buff *skb) limit = min(send_win, cong_win); /* If a full-sized TSO skb can be sent, do it. */ - if (limit >= sk->sk_gso_max_size) + if (limit >= min_t(unsigned int, sk->sk_gso_max_size, + sk->sk_gso_max_segs * tp->mss_cache)) goto send_now; /* Middle in queue won't get any more data, full sendable already? */ @@ -1786,7 +1787,9 @@ static int tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle, limit = mss_now; if (tso_segs > 1 && !tcp_urg_mode(tp)) limit = tcp_mss_split_point(sk, skb, mss_now, - cwnd_quota); + min_t(unsigned int, + cwnd_quota, + sk->sk_gso_max_segs)); if (skb->len > limit && unlikely(tso_fragment(sk, skb, limit, mss_now, gfp))) diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index f8978419f2d..e76e4520adc 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -493,8 +493,7 @@ static void addrconf_forward_change(struct net *net, __s32 newf) struct net_device *dev; struct inet6_dev *idev; - rcu_read_lock(); - for_each_netdev_rcu(net, dev) { + for_each_netdev(net, dev) { idev = __in6_dev_get(dev); if (idev) { int changed = (!idev->cnf.forwarding) ^ (!newf); @@ -503,7 +502,6 @@ static void addrconf_forward_change(struct net *net, __s32 newf) dev_forward_change(idev); } } - rcu_read_unlock(); } static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int newf) @@ -795,10 +793,16 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp) struct in6_addr prefix; struct rt6_info *rt; struct net *net = dev_net(ifp->idev->dev); + struct flowi6 fl6 = {}; + ipv6_addr_prefix(&prefix, &ifp->addr, ifp->prefix_len); - rt = rt6_lookup(net, &prefix, NULL, ifp->idev->dev->ifindex, 1); + fl6.flowi6_oif = ifp->idev->dev->ifindex; + fl6.daddr = prefix; + rt = (struct rt6_info *)ip6_route_lookup(net, &fl6, + RT6_LOOKUP_F_IFACE); - if (rt && addrconf_is_prefix_route(rt)) { + if (rt != net->ipv6.ip6_null_entry && + addrconf_is_prefix_route(rt)) { if (onlink == 0) { ip6_del_rt(rt); rt = NULL; @@ -3102,14 +3106,15 @@ static struct inet6_ifaddr *if6_get_first(struct seq_file *seq, loff_t pos) struct hlist_node *n; hlist_for_each_entry_rcu_bh(ifa, n, &inet6_addr_lst[state->bucket], addr_lst) { + if (!net_eq(dev_net(ifa->idev->dev), net)) + continue; /* sync with offset */ if (p < state->offset) { p++; continue; } state->offset++; - if (net_eq(dev_net(ifa->idev->dev), net)) - return ifa; + return ifa; } /* prepare for next bucket */ @@ -3127,18 +3132,20 @@ static struct inet6_ifaddr *if6_get_next(struct seq_file *seq, struct hlist_node *n = &ifa->addr_lst; hlist_for_each_entry_continue_rcu_bh(ifa, n, addr_lst) { + if (!net_eq(dev_net(ifa->idev->dev), net)) + continue; state->offset++; - if (net_eq(dev_net(ifa->idev->dev), net)) - return ifa; + return ifa; } while (++state->bucket < IN6_ADDR_HSIZE) { state->offset = 0; hlist_for_each_entry_rcu_bh(ifa, n, &inet6_addr_lst[state->bucket], addr_lst) { + if (!net_eq(dev_net(ifa->idev->dev), net)) + continue; state->offset++; - if (net_eq(dev_net(ifa->idev->dev), net)) - return ifa; + return ifa; } } diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 92bb9cba5c3..c3a007dc37c 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -818,6 +818,10 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info) offsetof(struct rt6_info, rt6i_src), allow_create, replace_required); + if (IS_ERR(sn)) { + err = PTR_ERR(sn); + sn = NULL; + } if (!sn) { /* If it is failed, discard just allocated root, and then (in st_failure) stale node diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index 63dd1f89ed7..34c1109d346 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c @@ -828,6 +828,7 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, if (val < 0 || val > 255) goto e_inval; np->min_hopcount = val; + retv = 0; break; case IPV6_DONTFRAG: np->dontfrag = valbool; diff --git a/net/ipv6/mip6.c b/net/ipv6/mip6.c index 7e1e0fbfef2..740c919e0b6 100644 --- a/net/ipv6/mip6.c +++ b/net/ipv6/mip6.c @@ -84,28 +84,30 @@ static int mip6_mh_len(int type) static int mip6_mh_filter(struct sock *sk, struct sk_buff *skb) { - struct ip6_mh *mh; + struct ip6_mh _hdr; + const struct ip6_mh *mh; - if (!pskb_may_pull(skb, (skb_transport_offset(skb)) + 8) || - !pskb_may_pull(skb, (skb_transport_offset(skb) + - ((skb_transport_header(skb)[1] + 1) << 3)))) + mh = skb_header_pointer(skb, skb_transport_offset(skb), + sizeof(_hdr), &_hdr); + if (!mh) return -1; - mh = (struct ip6_mh *)skb_transport_header(skb); + if (((mh->ip6mh_hdrlen + 1) << 3) > skb->len) + return -1; if (mh->ip6mh_hdrlen < mip6_mh_len(mh->ip6mh_type)) { LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH message too short: %d vs >=%d\n", mh->ip6mh_hdrlen, mip6_mh_len(mh->ip6mh_type)); - mip6_param_prob(skb, 0, ((&mh->ip6mh_hdrlen) - - skb_network_header(skb))); + mip6_param_prob(skb, 0, offsetof(struct ip6_mh, ip6mh_hdrlen) + + skb_network_header_len(skb)); return -1; } if (mh->ip6mh_proto != IPPROTO_NONE) { LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH invalid payload proto = %d\n", mh->ip6mh_proto); - mip6_param_prob(skb, 0, ((&mh->ip6mh_proto) - - skb_network_header(skb))); + mip6_param_prob(skb, 0, offsetof(struct ip6_mh, ip6mh_proto) + + skb_network_header_len(skb)); return -1; } diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 176b469322a..843d6ebc525 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -593,7 +593,7 @@ static void ndisc_send_unsol_na(struct net_device *dev) { struct inet6_dev *idev; struct inet6_ifaddr *ifa; - struct in6_addr mcaddr; + struct in6_addr mcaddr = IN6ADDR_LINKLOCAL_ALLNODES_INIT; idev = in6_dev_get(dev); if (!idev) @@ -601,7 +601,6 @@ static void ndisc_send_unsol_na(struct net_device *dev) read_lock_bh(&idev->lock); list_for_each_entry(ifa, &idev->addr_list, if_list) { - addrconf_addr_solict_mult(&ifa->addr, &mcaddr); ndisc_send_na(dev, NULL, &mcaddr, &ifa->addr, /*router=*/ !!idev->cnf.forwarding, /*solicited=*/ false, /*override=*/ true, diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 5bddea77884..3ee28700de4 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -107,21 +107,20 @@ static struct sock *__raw_v6_lookup(struct net *net, struct sock *sk, * 0 - deliver * 1 - block */ -static __inline__ int icmpv6_filter(struct sock *sk, struct sk_buff *skb) +static int icmpv6_filter(const struct sock *sk, const struct sk_buff *skb) { - struct icmp6hdr *icmph; - struct raw6_sock *rp = raw6_sk(sk); - - if (pskb_may_pull(skb, sizeof(struct icmp6hdr))) { - __u32 *data = &rp->filter.data[0]; - int bit_nr; + struct icmp6hdr *_hdr; + const struct icmp6hdr *hdr; - icmph = (struct icmp6hdr *) skb->data; - bit_nr = icmph->icmp6_type; + hdr = skb_header_pointer(skb, skb_transport_offset(skb), + sizeof(_hdr), &_hdr); + if (hdr) { + const __u32 *data = &raw6_sk(sk)->filter.data[0]; + unsigned int type = hdr->icmp6_type; - return (data[bit_nr >> 5] & (1 << (bit_nr & 31))) != 0; + return (data[type >> 5] & (1U << (type & 31))) != 0; } - return 0; + return 1; } #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 1cc2af65636..d151056dd4a 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -203,7 +203,7 @@ static struct dst_ops ip6_dst_blackhole_ops = { }; static const u32 ip6_template_metrics[RTAX_MAX] = { - [RTAX_HOPLIMIT - 1] = 255, + [RTAX_HOPLIMIT - 1] = 0, }; static struct rt6_info ip6_null_entry_template = { @@ -1135,7 +1135,7 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev, rt->rt6i_dst.addr = fl6->daddr; rt->rt6i_dst.plen = 128; rt->rt6i_idev = idev; - dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 255); + dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 0); spin_lock_bh(&icmp6_dst_lock); rt->dst.next = icmp6_dst_gc_list; @@ -1485,17 +1485,18 @@ static int __ip6_del_rt(struct rt6_info *rt, struct nl_info *info) struct fib6_table *table; struct net *net = dev_net(rt->dst.dev); - if (rt == net->ipv6.ip6_null_entry) - return -ENOENT; + if (rt == net->ipv6.ip6_null_entry) { + err = -ENOENT; + goto out; + } table = rt->rt6i_table; write_lock_bh(&table->tb6_lock); - err = fib6_del(rt, info); - dst_release(&rt->dst); - write_unlock_bh(&table->tb6_lock); +out: + dst_release(&rt->dst); return err; } diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 98256cf72f9..3889e020418 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -896,7 +896,8 @@ static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win, __tcp_v6_send_check(buff, &fl6.saddr, &fl6.daddr); fl6.flowi6_proto = IPPROTO_TCP; - fl6.flowi6_oif = inet6_iif(skb); + if (ipv6_addr_type(&fl6.daddr) & IPV6_ADDR_LINKLOCAL) + fl6.flowi6_oif = inet6_iif(skb); fl6.fl6_dport = t1->dest; fl6.fl6_sport = t1->source; security_skb_classify_flow(skb, flowi6_to_flowi(&fl6)); @@ -1410,7 +1411,8 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, #endif if (__inet_inherit_port(sk, newsk) < 0) { - sock_put(newsk); + inet_csk_prepare_forced_close(newsk); + tcp_done(newsk); goto out; } __inet6_hash(newsk, NULL); diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c index 89ff8c67943..7501b22b9c5 100644 --- a/net/l2tp/l2tp_core.c +++ b/net/l2tp/l2tp_core.c @@ -1253,11 +1253,10 @@ static void l2tp_tunnel_free(struct l2tp_tunnel *tunnel) /* Remove from tunnel list */ spin_lock_bh(&pn->l2tp_tunnel_list_lock); list_del_rcu(&tunnel->list); + kfree_rcu(tunnel, rcu); spin_unlock_bh(&pn->l2tp_tunnel_list_lock); - synchronize_rcu(); atomic_dec(&l2tp_tunnel_count); - kfree(tunnel); } /* Create a socket for the tunnel, if one isn't set up by diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h index a16a48e79fa..439379484bf 100644 --- a/net/l2tp/l2tp_core.h +++ b/net/l2tp/l2tp_core.h @@ -157,6 +157,7 @@ struct l2tp_tunnel_cfg { struct l2tp_tunnel { int magic; /* Should be L2TP_TUNNEL_MAGIC */ + struct rcu_head rcu; rwlock_t hlist_lock; /* protect session_hlist */ struct hlist_head session_hlist[L2TP_HASH_SIZE]; /* hashed list of sessions, diff --git a/net/l2tp/l2tp_eth.c b/net/l2tp/l2tp_eth.c index 7446038e6b4..ab9a293ad03 100644 --- a/net/l2tp/l2tp_eth.c +++ b/net/l2tp/l2tp_eth.c @@ -132,7 +132,7 @@ static void l2tp_eth_dev_recv(struct l2tp_session *session, struct sk_buff *skb, printk("\n"); } - if (!pskb_may_pull(skb, sizeof(ETH_HLEN))) + if (!pskb_may_pull(skb, ETH_HLEN)) goto error; secpath_reset(skb); @@ -269,6 +269,7 @@ static int l2tp_eth_create(struct net *net, u32 tunnel_id, u32 session_id, u32 p out_del_dev: free_netdev(dev); + spriv->dev = NULL; out_del_session: l2tp_session_delete(session); out: diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index b9bef2c7502..df08d7779e1 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c @@ -971,14 +971,13 @@ static int llc_ui_getname(struct socket *sock, struct sockaddr *uaddr, struct sockaddr_llc sllc; struct sock *sk = sock->sk; struct llc_sock *llc = llc_sk(sk); - int rc = 0; + int rc = -EBADF; memset(&sllc, 0, sizeof(sllc)); lock_sock(sk); if (sock_flag(sk, SOCK_ZAPPED)) goto out; *uaddrlen = sizeof(sllc); - memset(uaddr, 0, *uaddrlen); if (peer) { rc = -ENOTCONN; if (sk->sk_state != TCP_ESTABLISHED) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 685553b412b..e38ab651ba1 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -151,7 +151,17 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, sta = sta_info_get(sdata, mac_addr); else sta = sta_info_get_bss(sdata, mac_addr); - if (!sta) { + /* + * The ASSOC test makes sure the driver is ready to + * receive the key. When wpa_supplicant has roamed + * using FT, it attempts to set the key before + * association has completed, this rejects that attempt + * so it will set the key again after assocation. + * + * TODO: accept the key if we have a station entry and + * add it to the device after the station. + */ + if (!sta || !test_sta_flag(sta, WLAN_STA_ASSOC)) { ieee80211_key_free(sdata->local, key); err = -ENOENT; goto out_unlock; diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index cef7c29214a..50191a30207 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -664,8 +664,8 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata) printk(KERN_DEBUG "%s: No active IBSS STAs - trying to scan for other " "IBSS networks with same SSID (merge)\n", sdata->name); - ieee80211_request_internal_scan(sdata, - ifibss->ssid, ifibss->ssid_len, NULL); + ieee80211_request_ibss_scan(sdata, ifibss->ssid, ifibss->ssid_len, + NULL); } static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata) @@ -772,9 +772,8 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) printk(KERN_DEBUG "%s: Trigger new scan to find an IBSS to " "join\n", sdata->name); - ieee80211_request_internal_scan(sdata, - ifibss->ssid, ifibss->ssid_len, - ifibss->fixed_channel ? ifibss->channel : NULL); + ieee80211_request_ibss_scan(sdata, ifibss->ssid, + ifibss->ssid_len, chan); } else { int interval = IEEE80211_SCAN_INTERVAL; @@ -1110,7 +1109,7 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, sdata->u.ibss.state = IEEE80211_IBSS_MLME_SEARCH; sdata->u.ibss.ibss_join_req = jiffies; - memcpy(sdata->u.ibss.ssid, params->ssid, IEEE80211_MAX_SSID_LEN); + memcpy(sdata->u.ibss.ssid, params->ssid, params->ssid_len); sdata->u.ibss.ssid_len = params->ssid_len; mutex_unlock(&sdata->u.ibss.mtx); @@ -1153,10 +1152,6 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) mutex_lock(&sdata->u.ibss.mtx); - sdata->u.ibss.state = IEEE80211_IBSS_MLME_SEARCH; - memset(sdata->u.ibss.bssid, 0, ETH_ALEN); - sdata->u.ibss.ssid_len = 0; - active_ibss = ieee80211_sta_active_ibss(sdata); if (!active_ibss && !is_zero_ether_addr(ifibss->bssid)) { @@ -1177,6 +1172,10 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata) } } + ifibss->state = IEEE80211_IBSS_MLME_SEARCH; + memset(ifibss->bssid, 0, ETH_ALEN); + ifibss->ssid_len = 0; + sta_info_flush(sdata->local, sdata); spin_lock_bh(&ifibss->incomplete_lock); diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index a99a71517c4..1196f36bc36 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -1234,9 +1234,9 @@ void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, /* scan/BSS handling */ void ieee80211_scan_work(struct work_struct *work); -int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, - const u8 *ssid, u8 ssid_len, - struct ieee80211_channel *chan); +int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata, + const u8 *ssid, u8 ssid_len, + struct ieee80211_channel *chan); int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, struct cfg80211_scan_request *req); void ieee80211_scan_cancel(struct ieee80211_local *local); @@ -1265,10 +1265,8 @@ int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata); void ieee80211_sched_scan_stopped_work(struct work_struct *work); /* off-channel helpers */ -void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local, - bool offchannel_ps_enable); -void ieee80211_offchannel_return(struct ieee80211_local *local, - bool offchannel_ps_disable); +void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local); +void ieee80211_offchannel_return(struct ieee80211_local *local); void ieee80211_hw_roc_setup(struct ieee80211_local *local); /* interface handling */ @@ -1298,6 +1296,8 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb, struct net_device *dev); netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, struct net_device *dev); +void ieee80211_purge_tx_queue(struct ieee80211_hw *hw, + struct sk_buff_head *skbs); /* HT */ bool ieee80111_cfg_override_disables_ht40(struct ieee80211_sub_if_data *sdata); diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index e5fbb7cf356..e80fa33b504 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -595,6 +595,7 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) del_timer_sync(&sdata->u.mesh.housekeeping_timer); del_timer_sync(&sdata->u.mesh.mesh_path_root_timer); + del_timer_sync(&sdata->u.mesh.mesh_path_timer); /* * If the timer fired while we waited for it, it will have * requeued the work. Now the work will be running again diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 036a2ca477f..43f0ebeb654 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1837,7 +1837,8 @@ ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, if (status_code != WLAN_STATUS_SUCCESS) { printk(KERN_DEBUG "%s: %pM denied authentication (status %d)\n", sdata->name, mgmt->sa, status_code); - goto out; + ieee80211_destroy_auth_data(sdata, false); + return RX_MGMT_CFG80211_RX_AUTH; } switch (ifmgd->auth_data->algorithm) { @@ -1859,7 +1860,6 @@ ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, } printk(KERN_DEBUG "%s: authenticated\n", sdata->name); - out: ifmgd->auth_data->done = true; ifmgd->auth_data->timeout = jiffies + IEEE80211_AUTH_WAIT_ASSOC; run_again(ifmgd, ifmgd->auth_data->timeout); @@ -2207,15 +2207,13 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, sdata->name, mgmt->sa, status_code); ieee80211_destroy_assoc_data(sdata, false); } else { - printk(KERN_DEBUG "%s: associated\n", sdata->name); - if (!ieee80211_assoc_success(sdata, *bss, mgmt, len)) { /* oops -- internal error -- send timeout for now */ - ieee80211_destroy_assoc_data(sdata, true); - sta_info_destroy_addr(sdata, mgmt->bssid); + ieee80211_destroy_assoc_data(sdata, false); cfg80211_put_bss(*bss); return RX_MGMT_CFG80211_ASSOC_TIMEOUT; } + printk(KERN_DEBUG "%s: associated\n", sdata->name); /* * destroy assoc_data afterwards, as otherwise an idle @@ -3258,6 +3256,8 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata, goto out_unlock; err_clear: + memset(ifmgd->bssid, 0, ETH_ALEN); + ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID); ifmgd->auth_data = NULL; err_free: kfree(auth_data); @@ -3452,6 +3452,8 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, err = 0; goto out; err_clear: + memset(ifmgd->bssid, 0, ETH_ALEN); + ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID); ifmgd->assoc_data = NULL; err_free: kfree(assoc_data); diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index 935aa4b6dee..c22f0748f4f 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c @@ -103,8 +103,7 @@ static void ieee80211_offchannel_ps_disable(struct ieee80211_sub_if_data *sdata) ieee80211_sta_reset_conn_monitor(sdata); } -void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local, - bool offchannel_ps_enable) +void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local) { struct ieee80211_sub_if_data *sdata; @@ -129,8 +128,7 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local, if (sdata->vif.type != NL80211_IFTYPE_MONITOR) { netif_tx_stop_all_queues(sdata->dev); - if (offchannel_ps_enable && - (sdata->vif.type == NL80211_IFTYPE_STATION) && + if (sdata->vif.type == NL80211_IFTYPE_STATION && sdata->u.mgd.associated) ieee80211_offchannel_ps_enable(sdata, true); } @@ -138,8 +136,7 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local, mutex_unlock(&local->iflist_mtx); } -void ieee80211_offchannel_return(struct ieee80211_local *local, - bool offchannel_ps_disable) +void ieee80211_offchannel_return(struct ieee80211_local *local) { struct ieee80211_sub_if_data *sdata; @@ -152,11 +149,9 @@ void ieee80211_offchannel_return(struct ieee80211_local *local, continue; /* Tell AP we're back */ - if (offchannel_ps_disable && - sdata->vif.type == NL80211_IFTYPE_STATION) { - if (sdata->u.mgd.associated) - ieee80211_offchannel_ps_disable(sdata); - } + if (sdata->vif.type == NL80211_IFTYPE_STATION && + sdata->u.mgd.associated) + ieee80211_offchannel_ps_disable(sdata); if (sdata->vif.type != NL80211_IFTYPE_MONITOR) { /* diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index c9b508ea9d6..8ce9feb1301 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -513,6 +513,11 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) if (ieee80211_is_action(hdr->frame_control)) { u8 category; + + /* make sure category field is present */ + if (rx->skb->len < IEEE80211_MIN_ACTION_SIZE) + return RX_DROP_MONITOR; + mgmt = (struct ieee80211_mgmt *)hdr; category = mgmt->u.action.category; if (category != WLAN_CATEGORY_MESH_ACTION && @@ -869,14 +874,16 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx) */ if (rx->sta && rx->sdata->vif.type == NL80211_IFTYPE_STATION && ieee80211_is_data_present(hdr->frame_control)) { - u16 ethertype; - u8 *payload; - - payload = rx->skb->data + - ieee80211_hdrlen(hdr->frame_control); - ethertype = (payload[6] << 8) | payload[7]; - if (cpu_to_be16(ethertype) == - rx->sdata->control_port_protocol) + unsigned int hdrlen; + __be16 ethertype; + + hdrlen = ieee80211_hdrlen(hdr->frame_control); + + if (rx->skb->len < hdrlen + 8) + return RX_DROP_MONITOR; + + skb_copy_bits(rx->skb, hdrlen + 6, ðertype, 2); + if (ethertype == rx->sdata->control_port_protocol) return RX_CONTINUE; } @@ -1465,11 +1472,14 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) hdr = (struct ieee80211_hdr *)rx->skb->data; fc = hdr->frame_control; + + if (ieee80211_is_ctl(fc)) + return RX_CONTINUE; + sc = le16_to_cpu(hdr->seq_ctrl); frag = sc & IEEE80211_SCTL_FRAG; if (likely((!ieee80211_has_morefrags(fc) && frag == 0) || - (rx->skb)->len < 24 || is_multicast_ether_addr(hdr->addr1))) { /* not fragmented */ goto out; @@ -1892,6 +1902,20 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) hdr = (struct ieee80211_hdr *) skb->data; hdrlen = ieee80211_hdrlen(hdr->frame_control); + + /* make sure fixed part of mesh header is there, also checks skb len */ + if (!pskb_may_pull(rx->skb, hdrlen + 6)) + return RX_DROP_MONITOR; + + mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); + + /* make sure full mesh header is there, also checks skb len */ + if (!pskb_may_pull(rx->skb, + hdrlen + ieee80211_get_mesh_hdrlen(mesh_hdr))) + return RX_DROP_MONITOR; + + /* reload pointers */ + hdr = (struct ieee80211_hdr *) skb->data; mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); /* frame is in RMC, don't forward */ @@ -1900,7 +1924,8 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) mesh_rmc_check(hdr->addr3, mesh_hdr, rx->sdata)) return RX_DROP_MONITOR; - if (!ieee80211_is_data(hdr->frame_control)) + if (!ieee80211_is_data(hdr->frame_control) || + !(status->rx_flags & IEEE80211_RX_RA_MATCH)) return RX_CONTINUE; if (!mesh_hdr->ttl) @@ -1914,9 +1939,12 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) if (is_multicast_ether_addr(hdr->addr1)) { mpp_addr = hdr->addr3; proxied_addr = mesh_hdr->eaddr1; - } else { + } else if (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6) { + /* has_a4 already checked in ieee80211_rx_mesh_check */ mpp_addr = hdr->addr4; proxied_addr = mesh_hdr->eaddr2; + } else { + return RX_DROP_MONITOR; } rcu_read_lock(); @@ -1944,9 +1972,6 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) } skb_set_queue_mapping(skb, q); - if (!(status->rx_flags & IEEE80211_RX_RA_MATCH)) - goto out; - if (!--mesh_hdr->ttl) { IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_ttl); return RX_DROP_MONITOR; @@ -2361,6 +2386,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) } break; case WLAN_CATEGORY_SELF_PROTECTED: + if (len < (IEEE80211_MIN_ACTION_SIZE + + sizeof(mgmt->u.action.u.self_prot.action_code))) + break; + switch (mgmt->u.action.u.self_prot.action_code) { case WLAN_SP_MESH_PEERING_OPEN: case WLAN_SP_MESH_PEERING_CLOSE: @@ -2379,6 +2408,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) } break; case WLAN_CATEGORY_MESH_ACTION: + if (len < (IEEE80211_MIN_ACTION_SIZE + + sizeof(mgmt->u.action.u.mesh_action.action_code))) + break; + if (!ieee80211_vif_is_mesh(&sdata->vif)) break; if (mesh_action_is_path_sel(mgmt) && @@ -2927,10 +2960,15 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, test_bit(SCAN_SW_SCANNING, &local->scanning))) status->rx_flags |= IEEE80211_RX_IN_SCAN; - if (ieee80211_is_mgmt(fc)) - err = skb_linearize(skb); - else + if (ieee80211_is_mgmt(fc)) { + /* drop frame if too short for header */ + if (skb->len < ieee80211_hdrlen(fc)) + err = -ENOBUFS; + else + err = skb_linearize(skb); + } else { err = !pskb_may_pull(skb, ieee80211_hdrlen(fc)); + } if (err) { dev_kfree_skb(skb); diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index c70e1767713..bcc57f93adc 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -329,7 +329,7 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted, if (!was_hw_scan) { ieee80211_configure_filter(local); drv_sw_scan_complete(local); - ieee80211_offchannel_return(local, true); + ieee80211_offchannel_return(local); } ieee80211_recalc_idle(local); @@ -374,7 +374,7 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local) local->next_scan_state = SCAN_DECISION; local->scan_channel_idx = 0; - ieee80211_offchannel_stop_vifs(local, true); + ieee80211_offchannel_stop_vifs(local); ieee80211_configure_filter(local); @@ -629,12 +629,8 @@ static void ieee80211_scan_state_suspend(struct ieee80211_local *local, local->scan_channel = NULL; ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); - /* - * Re-enable vifs and beaconing. Leave PS - * in off-channel state..will put that back - * on-channel at the end of scanning. - */ - ieee80211_offchannel_return(local, false); + /* disable PS */ + ieee80211_offchannel_return(local); *next_delay = HZ / 5; /* afterwards, resume scan & go to next channel */ @@ -644,8 +640,7 @@ static void ieee80211_scan_state_suspend(struct ieee80211_local *local, static void ieee80211_scan_state_resume(struct ieee80211_local *local, unsigned long *next_delay) { - /* PS already is in off-channel mode */ - ieee80211_offchannel_stop_vifs(local, false); + ieee80211_offchannel_stop_vifs(local); if (local->ops->flush) { drv_flush(local, false); @@ -761,9 +756,9 @@ int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, return res; } -int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, - const u8 *ssid, u8 ssid_len, - struct ieee80211_channel *chan) +int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata, + const u8 *ssid, u8 ssid_len, + struct ieee80211_channel *chan) { struct ieee80211_local *local = sdata->local; int ret = -EBUSY; @@ -777,22 +772,36 @@ int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, /* fill internal scan request */ if (!chan) { - int i, nchan = 0; + int i, max_n; + int n_ch = 0; for (band = 0; band < IEEE80211_NUM_BANDS; band++) { if (!local->hw.wiphy->bands[band]) continue; - for (i = 0; - i < local->hw.wiphy->bands[band]->n_channels; - i++) { - local->int_scan_req->channels[nchan] = + + max_n = local->hw.wiphy->bands[band]->n_channels; + for (i = 0; i < max_n; i++) { + struct ieee80211_channel *tmp_ch = &local->hw.wiphy->bands[band]->channels[i]; - nchan++; + + if (tmp_ch->flags & (IEEE80211_CHAN_NO_IBSS | + IEEE80211_CHAN_DISABLED)) + continue; + + local->int_scan_req->channels[n_ch] = tmp_ch; + n_ch++; } } - local->int_scan_req->n_channels = nchan; + if (WARN_ON_ONCE(n_ch == 0)) + goto unlock; + + local->int_scan_req->n_channels = n_ch; } else { + if (WARN_ON_ONCE(chan->flags & (IEEE80211_CHAN_NO_IBSS | + IEEE80211_CHAN_DISABLED))) + goto unlock; + local->int_scan_req->channels[0] = chan; local->int_scan_req->n_channels = 1; } diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index d93d39b8434..e2e0e0bc662 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -738,8 +738,8 @@ int __must_check __sta_info_destroy(struct sta_info *sta) for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { local->total_ps_buffered -= skb_queue_len(&sta->ps_tx_buf[ac]); - __skb_queue_purge(&sta->ps_tx_buf[ac]); - __skb_queue_purge(&sta->tx_filtered[ac]); + ieee80211_purge_tx_queue(&local->hw, &sta->ps_tx_buf[ac]); + ieee80211_purge_tx_queue(&local->hw, &sta->tx_filtered[ac]); } #ifdef CONFIG_MAC80211_MESH @@ -774,7 +774,7 @@ int __must_check __sta_info_destroy(struct sta_info *sta) tid_tx = rcu_dereference_raw(sta->ampdu_mlme.tid_tx[i]); if (!tid_tx) continue; - __skb_queue_purge(&tid_tx->pending); + ieee80211_purge_tx_queue(&local->hw, &tid_tx->pending); kfree(tid_tx); } @@ -844,7 +844,7 @@ void sta_info_init(struct ieee80211_local *local) void sta_info_stop(struct ieee80211_local *local) { - del_timer(&local->sta_cleanup); + del_timer_sync(&local->sta_cleanup); sta_info_flush(local, NULL); } @@ -959,6 +959,7 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) struct ieee80211_local *local = sdata->local; struct sk_buff_head pending; int filtered = 0, buffered = 0, ac; + unsigned long flags; clear_sta_flag(sta, WLAN_STA_SP); @@ -974,12 +975,16 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { int count = skb_queue_len(&pending), tmp; + spin_lock_irqsave(&sta->tx_filtered[ac].lock, flags); skb_queue_splice_tail_init(&sta->tx_filtered[ac], &pending); + spin_unlock_irqrestore(&sta->tx_filtered[ac].lock, flags); tmp = skb_queue_len(&pending); filtered += tmp - count; count = tmp; + spin_lock_irqsave(&sta->ps_tx_buf[ac].lock, flags); skb_queue_splice_tail_init(&sta->ps_tx_buf[ac], &pending); + spin_unlock_irqrestore(&sta->ps_tx_buf[ac].lock, flags); tmp = skb_queue_len(&pending); buffered += tmp - count; } diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 5f8f89e89d6..47b117f3f56 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c @@ -660,3 +660,12 @@ void ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb) dev_kfree_skb_any(skb); } EXPORT_SYMBOL(ieee80211_free_txskb); + +void ieee80211_purge_tx_queue(struct ieee80211_hw *hw, + struct sk_buff_head *skbs) +{ + struct sk_buff *skb; + + while ((skb = __skb_dequeue(skbs))) + ieee80211_free_txskb(hw, skb); +} diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index e76facc69e9..eace7664c80 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1357,7 +1357,7 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx) if (tx->skb) dev_kfree_skb(tx->skb); else - __skb_queue_purge(&tx->skbs); + ieee80211_purge_tx_queue(&tx->local->hw, &tx->skbs); return -1; } else if (unlikely(res == TX_QUEUED)) { I802_DEBUG_INC(tx->local->tx_handlers_queued); @@ -2126,10 +2126,13 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, */ void ieee80211_clear_tx_pending(struct ieee80211_local *local) { + struct sk_buff *skb; int i; - for (i = 0; i < local->hw.queues; i++) - skb_queue_purge(&local->pending[i]); + for (i = 0; i < local->hw.queues; i++) { + while ((skb = skb_dequeue(&local->pending[i])) != NULL) + ieee80211_free_txskb(&local->hw, skb); + } } /* diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 70699db0cce..e51684af38b 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -592,13 +592,38 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, break; } - if (id != WLAN_EID_VENDOR_SPECIFIC && - id != WLAN_EID_QUIET && - test_bit(id, seen_elems)) { - elems->parse_error = true; - left -= elen; - pos += elen; - continue; + switch (id) { + case WLAN_EID_SSID: + case WLAN_EID_SUPP_RATES: + case WLAN_EID_FH_PARAMS: + case WLAN_EID_DS_PARAMS: + case WLAN_EID_CF_PARAMS: + case WLAN_EID_TIM: + case WLAN_EID_IBSS_PARAMS: + case WLAN_EID_CHALLENGE: + case WLAN_EID_RSN: + case WLAN_EID_ERP_INFO: + case WLAN_EID_EXT_SUPP_RATES: + case WLAN_EID_HT_CAPABILITY: + case WLAN_EID_MESH_ID: + case WLAN_EID_MESH_CONFIG: + case WLAN_EID_PEER_MGMT: + case WLAN_EID_PREQ: + case WLAN_EID_PREP: + case WLAN_EID_PERR: + case WLAN_EID_RANN: + case WLAN_EID_CHANNEL_SWITCH: + case WLAN_EID_EXT_CHANSWITCH_ANN: + case WLAN_EID_COUNTRY: + case WLAN_EID_PWR_CONSTRAINT: + case WLAN_EID_TIMEOUT_INTERVAL: + if (test_bit(id, seen_elems)) { + elems->parse_error = true; + left -= elen; + pos += elen; + continue; + } + break; } if (calc_crc && id < 64 && (filter & (1ULL << id))) @@ -1319,6 +1344,8 @@ int ieee80211_reconfig(struct ieee80211_local *local) list_for_each_entry(sdata, &local->interfaces, list) { if (sdata->vif.type != NL80211_IFTYPE_STATION) continue; + if (!sdata->u.mgd.associated) + continue; ieee80211_send_nullfunc(local, sdata, 0); } diff --git a/net/mac80211/work.c b/net/mac80211/work.c index c6e230efa04..a74f53894d6 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c @@ -148,7 +148,7 @@ static void ieee80211_work_work(struct work_struct *work) } if (!started && !local->tmp_channel) { - ieee80211_offchannel_stop_vifs(local, true); + ieee80211_offchannel_stop_vifs(local); local->tmp_channel = wk->chan; local->tmp_channel_type = wk->chan_type; @@ -220,7 +220,7 @@ static void ieee80211_work_work(struct work_struct *work) local->tmp_channel = NULL; ieee80211_hw_config(local, 0); - ieee80211_offchannel_return(local, true); + ieee80211_offchannel_return(local); /* give connection some time to breathe */ run_again(local, jiffies + HZ/2); diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 0ae23c60968..ea6d03bd5d5 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c @@ -106,7 +106,8 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) if (status->flag & RX_FLAG_MMIC_ERROR) goto mic_fail; - if (!(status->flag & RX_FLAG_IV_STRIPPED) && rx->key) + if (!(status->flag & RX_FLAG_IV_STRIPPED) && rx->key && + rx->key->conf.cipher == WLAN_CIPHER_SUITE_TKIP) goto update_iv; return RX_CONTINUE; diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index f5589987fc8..cbc5bfd8c8e 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c @@ -1521,11 +1521,12 @@ static int ip_vs_dst_event(struct notifier_block *this, unsigned long event, { struct net_device *dev = ptr; struct net *net = dev_net(dev); + struct netns_ipvs *ipvs = net_ipvs(net); struct ip_vs_service *svc; struct ip_vs_dest *dest; unsigned int idx; - if (event != NETDEV_UNREGISTER) + if (event != NETDEV_UNREGISTER || !ipvs) return NOTIFY_DONE; IP_VS_DBG(3, "%s() dev=%s\n", __func__, dev->name); EnterFunction(2); @@ -1551,7 +1552,7 @@ static int ip_vs_dst_event(struct notifier_block *this, unsigned long event, } } - list_for_each_entry(dest, &net_ipvs(net)->dest_trash, n_list) { + list_for_each_entry(dest, &ipvs->dest_trash, n_list) { __ip_vs_dev_reset(dest, dev); } mutex_unlock(&__ip_vs_mutex); @@ -2713,6 +2714,7 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) { struct ip_vs_timeout_user t; + memset(&t, 0, sizeof(t)); __ip_vs_get_timeouts(net, &t); if (copy_to_user(user, &t, sizeof(t)) != 0) ret = -EFAULT; diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 729f157a0ef..9a171b2445b 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -249,12 +249,15 @@ static void death_by_event(unsigned long ul_conntrack) { struct nf_conn *ct = (void *)ul_conntrack; struct net *net = nf_ct_net(ct); + struct nf_conntrack_ecache *ecache = nf_ct_ecache_find(ct); + + BUG_ON(ecache == NULL); if (nf_conntrack_event(IPCT_DESTROY, ct) < 0) { /* bad luck, let's retry again */ - ct->timeout.expires = jiffies + + ecache->timeout.expires = jiffies + (random32() % net->ct.sysctl_events_retry_timeout); - add_timer(&ct->timeout); + add_timer(&ecache->timeout); return; } /* we've got the event delivered, now it's dying */ @@ -268,6 +271,9 @@ static void death_by_event(unsigned long ul_conntrack) void nf_ct_insert_dying_list(struct nf_conn *ct) { struct net *net = nf_ct_net(ct); + struct nf_conntrack_ecache *ecache = nf_ct_ecache_find(ct); + + BUG_ON(ecache == NULL); /* add this conntrack to the dying list */ spin_lock_bh(&nf_conntrack_lock); @@ -275,10 +281,10 @@ void nf_ct_insert_dying_list(struct nf_conn *ct) &net->ct.dying); spin_unlock_bh(&nf_conntrack_lock); /* set a new timer to retry event delivery */ - setup_timer(&ct->timeout, death_by_event, (unsigned long)ct); - ct->timeout.expires = jiffies + + setup_timer(&ecache->timeout, death_by_event, (unsigned long)ct); + ecache->timeout.expires = jiffies + (random32() % net->ct.sysctl_events_retry_timeout); - add_timer(&ct->timeout); + add_timer(&ecache->timeout); } EXPORT_SYMBOL_GPL(nf_ct_insert_dying_list); diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c index 4147ba3f653..e41ec849120 100644 --- a/net/netfilter/nf_conntrack_expect.c +++ b/net/netfilter/nf_conntrack_expect.c @@ -361,23 +361,6 @@ static void evict_oldest_expect(struct nf_conn *master, } } -static inline int refresh_timer(struct nf_conntrack_expect *i) -{ - struct nf_conn_help *master_help = nfct_help(i->master); - const struct nf_conntrack_expect_policy *p; - - if (!del_timer(&i->timeout)) - return 0; - - p = &rcu_dereference_protected( - master_help->helper, - lockdep_is_held(&nf_conntrack_lock) - )->expect_policy[i->class]; - i->timeout.expires = jiffies + p->timeout * HZ; - add_timer(&i->timeout); - return 1; -} - static inline int __nf_ct_expect_check(struct nf_conntrack_expect *expect) { const struct nf_conntrack_expect_policy *p; @@ -386,7 +369,7 @@ static inline int __nf_ct_expect_check(struct nf_conntrack_expect *expect) struct nf_conn_help *master_help = nfct_help(master); struct nf_conntrack_helper *helper; struct net *net = nf_ct_exp_net(expect); - struct hlist_node *n; + struct hlist_node *n, *next; unsigned int h; int ret = 1; @@ -395,12 +378,12 @@ static inline int __nf_ct_expect_check(struct nf_conntrack_expect *expect) goto out; } h = nf_ct_expect_dst_hash(&expect->tuple); - hlist_for_each_entry(i, n, &net->ct.expect_hash[h], hnode) { + hlist_for_each_entry_safe(i, n, next, &net->ct.expect_hash[h], hnode) { if (expect_matches(i, expect)) { - /* Refresh timer: if it's dying, ignore.. */ - if (refresh_timer(i)) { - ret = 0; - goto out; + if (del_timer(&i->timeout)) { + nf_ct_unlink_expect(i); + nf_ct_expect_put(i); + break; } } else if (expect_clash(i, expect)) { ret = -EBUSY; diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index 0d07a1dcf60..e0221238e74 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c @@ -158,21 +158,18 @@ static const u8 tcp_conntracks[2][6][TCP_CONNTRACK_MAX] = { * sCL -> sSS */ /* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2 */ -/*synack*/ { sIV, sIV, sIG, sIG, sIG, sIG, sIG, sIG, sIG, sSR }, +/*synack*/ { sIV, sIV, sSR, sIV, sIV, sIV, sIV, sIV, sIV, sSR }, /* * sNO -> sIV Too late and no reason to do anything * sSS -> sIV Client can't send SYN and then SYN/ACK * sS2 -> sSR SYN/ACK sent to SYN2 in simultaneous open - * sSR -> sIG - * sES -> sIG Error: SYNs in window outside the SYN_SENT state - * are errors. Receiver will reply with RST - * and close the connection. - * Or we are not in sync and hold a dead connection. - * sFW -> sIG - * sCW -> sIG - * sLA -> sIG - * sTW -> sIG - * sCL -> sIG + * sSR -> sSR Late retransmitted SYN/ACK in simultaneous open + * sES -> sIV Invalid SYN/ACK packets sent by the client + * sFW -> sIV + * sCW -> sIV + * sLA -> sIV + * sTW -> sIV + * sCL -> sIV */ /* sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2 */ /*fin*/ { sIV, sIV, sFW, sFW, sLA, sLA, sLA, sTW, sCL, sIV }, @@ -627,15 +624,9 @@ static bool tcp_in_window(const struct nf_conn *ct, ack = sack = receiver->td_end; } - if (seq == end - && (!tcph->rst - || (seq == 0 && state->state == TCP_CONNTRACK_SYN_SENT))) + if (tcph->rst && seq == 0 && state->state == TCP_CONNTRACK_SYN_SENT) /* - * Packets contains no data: we assume it is valid - * and check the ack value only. - * However RST segments are always validated by their - * SEQ number, except when seq == 0 (reset sent answering - * SYN. + * RST sent answering SYN. */ seq = end = sender->td_end; diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c index d95f9c963cd..2195eb0727a 100644 --- a/net/netfilter/xt_hashlimit.c +++ b/net/netfilter/xt_hashlimit.c @@ -389,8 +389,7 @@ static void htable_put(struct xt_hashlimit_htable *hinfo) #define CREDITS_PER_JIFFY POW2_BELOW32(MAX_CPJ) /* Precision saver. */ -static inline u_int32_t -user2credits(u_int32_t user) +static u32 user2credits(u32 user) { /* If multiplying would overflow... */ if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY)) @@ -400,7 +399,7 @@ user2credits(u_int32_t user) return (user * HZ * CREDITS_PER_JIFFY) / XT_HASHLIMIT_SCALE; } -static inline void rateinfo_recalc(struct dsthash_ent *dh, unsigned long now) +static void rateinfo_recalc(struct dsthash_ent *dh, unsigned long now) { dh->rateinfo.credit += (now - dh->rateinfo.prev) * CREDITS_PER_JIFFY; if (dh->rateinfo.credit > dh->rateinfo.credit_cap) @@ -535,8 +534,7 @@ hashlimit_mt(const struct sk_buff *skb, struct xt_action_param *par) dh->rateinfo.prev = jiffies; dh->rateinfo.credit = user2credits(hinfo->cfg.avg * hinfo->cfg.burst); - dh->rateinfo.credit_cap = user2credits(hinfo->cfg.avg * - hinfo->cfg.burst); + dh->rateinfo.credit_cap = dh->rateinfo.credit; dh->rateinfo.cost = user2credits(hinfo->cfg.avg); } else { /* update expiration timeout */ diff --git a/net/netfilter/xt_limit.c b/net/netfilter/xt_limit.c index 32b7a579a03..a4c1e4528ca 100644 --- a/net/netfilter/xt_limit.c +++ b/net/netfilter/xt_limit.c @@ -88,8 +88,7 @@ limit_mt(const struct sk_buff *skb, struct xt_action_param *par) } /* Precision saver. */ -static u_int32_t -user2credits(u_int32_t user) +static u32 user2credits(u32 user) { /* If multiplying would overflow... */ if (user > 0xFFFFFFFF / (HZ*CREDITS_PER_JIFFY)) @@ -118,12 +117,12 @@ static int limit_mt_check(const struct xt_mtchk_param *par) /* For SMP, we only want to use one set of state. */ r->master = priv; + /* User avg in seconds * XT_LIMIT_SCALE: convert to jiffies * + 128. */ + priv->prev = jiffies; + priv->credit = user2credits(r->avg * r->burst); /* Credits full. */ if (r->cost == 0) { - /* User avg in seconds * XT_LIMIT_SCALE: convert to jiffies * - 128. */ - priv->prev = jiffies; - priv->credit = user2credits(r->avg * r->burst); /* Credits full. */ - r->credit_cap = user2credits(r->avg * r->burst); /* Credits full. */ + r->credit_cap = priv->credit; /* Credits full. */ r->cost = user2credits(r->avg); } return 0; diff --git a/net/netfilter/xt_set.c b/net/netfilter/xt_set.c index 0ec8138aa47..c6f7db720d8 100644 --- a/net/netfilter/xt_set.c +++ b/net/netfilter/xt_set.c @@ -16,6 +16,7 @@ #include #include +#include MODULE_LICENSE("GPL"); MODULE_AUTHOR("Jozsef Kadlecsik "); @@ -44,6 +45,14 @@ const struct ip_set_adt_opt n = { \ .cmdflags = cfs, \ .timeout = t, \ } +#define ADT_MOPT(n, f, d, fs, cfs, t) \ +struct ip_set_adt_opt n = { \ + .family = f, \ + .dim = d, \ + .flags = fs, \ + .cmdflags = cfs, \ + .timeout = t, \ +} /* Revision 0 interface: backward compatible with netfilter/iptables */ @@ -296,11 +305,15 @@ static unsigned int set_target_v2(struct sk_buff *skb, const struct xt_action_param *par) { const struct xt_set_info_target_v2 *info = par->targinfo; - ADT_OPT(add_opt, par->family, info->add_set.dim, - info->add_set.flags, info->flags, info->timeout); + ADT_MOPT(add_opt, par->family, info->add_set.dim, + info->add_set.flags, info->flags, info->timeout); ADT_OPT(del_opt, par->family, info->del_set.dim, info->del_set.flags, 0, UINT_MAX); + /* Normalize to fit into jiffies */ + if (add_opt.timeout != IPSET_NO_TIMEOUT && + add_opt.timeout > UINT_MAX/MSEC_PER_SEC) + add_opt.timeout = UINT_MAX/MSEC_PER_SEC; if (info->add_set.index != IPSET_INVALID_ID) ip_set_add(info->add_set.index, skb, par, &add_opt); if (info->del_set.index != IPSET_INVALID_ID) diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 1a23c350402..a40409053ed 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -156,6 +156,8 @@ static void netlink_sock_destruct(struct sock *sk) if (nlk->cb) { if (nlk->cb->done) nlk->cb->done(nlk->cb); + + module_put(nlk->cb->module); netlink_destroy_callback(nlk->cb); } @@ -1731,6 +1733,7 @@ static int netlink_dump(struct sock *sk) nlk->cb = NULL; mutex_unlock(nlk->cb_mutex); + module_put(cb->module); netlink_destroy_callback(cb); return 0; @@ -1740,9 +1743,9 @@ static int netlink_dump(struct sock *sk) return err; } -int netlink_dump_start(struct sock *ssk, struct sk_buff *skb, - const struct nlmsghdr *nlh, - struct netlink_dump_control *control) +int __netlink_dump_start(struct sock *ssk, struct sk_buff *skb, + const struct nlmsghdr *nlh, + struct netlink_dump_control *control) { struct netlink_callback *cb; struct sock *sk; @@ -1757,6 +1760,7 @@ int netlink_dump_start(struct sock *ssk, struct sk_buff *skb, cb->done = control->done; cb->nlh = nlh; cb->data = control->data; + cb->module = control->module; cb->min_dump_alloc = control->min_dump_alloc; atomic_inc(&skb->users); cb->skb = skb; @@ -1767,19 +1771,28 @@ int netlink_dump_start(struct sock *ssk, struct sk_buff *skb, return -ECONNREFUSED; } nlk = nlk_sk(sk); - /* A dump is in progress... */ + mutex_lock(nlk->cb_mutex); + /* A dump is in progress... */ if (nlk->cb) { mutex_unlock(nlk->cb_mutex); netlink_destroy_callback(cb); - sock_put(sk); - return -EBUSY; + ret = -EBUSY; + goto out; } + /* add reference of module which cb->dump belongs to */ + if (!try_module_get(cb->module)) { + mutex_unlock(nlk->cb_mutex); + netlink_destroy_callback(cb); + ret = -EPROTONOSUPPORT; + goto out; + } + nlk->cb = cb; mutex_unlock(nlk->cb_mutex); ret = netlink_dump(sk); - +out: sock_put(sk); if (ret) @@ -1790,7 +1803,7 @@ int netlink_dump_start(struct sock *ssk, struct sk_buff *skb, */ return -EINTR; } -EXPORT_SYMBOL(netlink_dump_start); +EXPORT_SYMBOL(__netlink_dump_start); void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err) { diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c index 06592d8b4a2..1b9024ee963 100644 --- a/net/netrom/af_netrom.c +++ b/net/netrom/af_netrom.c @@ -1169,7 +1169,12 @@ static int nr_recvmsg(struct kiocb *iocb, struct socket *sock, msg->msg_flags |= MSG_TRUNC; } - skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); + er = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); + if (er < 0) { + skb_free_datagram(sk, skb); + release_sock(sk); + return er; + } if (sax != NULL) { sax->sax25_family = AF_NETROM; diff --git a/net/nfc/llcp/llcp.c b/net/nfc/llcp/llcp.c index 17a578f641f..c40112c39e1 100644 --- a/net/nfc/llcp/llcp.c +++ b/net/nfc/llcp/llcp.c @@ -966,7 +966,7 @@ int nfc_llcp_register_device(struct nfc_dev *ndev) local->remote_lto = LLCP_DEFAULT_LTO; local->remote_rw = LLCP_DEFAULT_RW; - list_add(&llcp_devices, &local->list); + list_add(&local->list, &llcp_devices); return 0; diff --git a/net/openvswitch/vport-internal_dev.c b/net/openvswitch/vport-internal_dev.c index b6b1d7daa3c..ce5348f5f60 100644 --- a/net/openvswitch/vport-internal_dev.c +++ b/net/openvswitch/vport-internal_dev.c @@ -24,6 +24,9 @@ #include #include +#include +#include + #include "datapath.h" #include "vport-internal_dev.h" #include "vport-netdev.h" @@ -209,6 +212,11 @@ static int internal_dev_recv(struct vport *vport, struct sk_buff *skb) int len; len = skb->len; + + skb_dst_drop(skb); + nf_reset(skb); + secpath_reset(skb); + skb->dev = netdev; skb->pkt_type = PACKET_HOST; skb->protocol = eth_type_trans(skb, netdev); diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 4f2c0df7956..078fdffcd55 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -1280,6 +1280,14 @@ static void __fanout_unlink(struct sock *sk, struct packet_sock *po) spin_unlock(&f->lock); } +bool match_fanout_group(struct packet_type *ptype, struct sock * sk) +{ + if (ptype->af_packet_priv == (void*)((struct packet_sock *)sk)->fanout) + return true; + + return false; +} + static int fanout_add(struct sock *sk, u16 id, u16 type_flags) { struct packet_sock *po = pkt_sk(sk); @@ -1332,6 +1340,7 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags) match->prot_hook.dev = po->prot_hook.dev; match->prot_hook.func = packet_rcv_fanout; match->prot_hook.af_packet_priv = match; + match->prot_hook.id_match = match_fanout_group; dev_add_pack(&match->prot_hook); list_add(&match->list, &fanout_list); } @@ -1943,7 +1952,6 @@ static void tpacket_destruct_skb(struct sk_buff *skb) if (likely(po->tx_ring.pg_vec)) { ph = skb_shinfo(skb)->destructor_arg; - BUG_ON(__packet_get_status(po, ph) != TP_STATUS_SENDING); BUG_ON(atomic_read(&po->tx_ring.pending) == 0); atomic_dec(&po->tx_ring.pending); __packet_set_status(po, ph, TP_STATUS_AVAILABLE); diff --git a/net/rds/recv.c b/net/rds/recv.c index 5c6e9f13202..9f0f17cf6bf 100644 --- a/net/rds/recv.c +++ b/net/rds/recv.c @@ -410,6 +410,8 @@ int rds_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, rdsdebug("size %zu flags 0x%x timeo %ld\n", size, msg_flags, timeo); + msg->msg_namelen = 0; + if (msg_flags & MSG_OOB) goto out; @@ -485,6 +487,7 @@ int rds_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, sin->sin_port = inc->i_hdr.h_sport; sin->sin_addr.s_addr = inc->i_saddr; memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); + msg->msg_namelen = sizeof(*sin); } break; } diff --git a/net/rds/send.c b/net/rds/send.c index 96531d4033a..88eace57dd6 100644 --- a/net/rds/send.c +++ b/net/rds/send.c @@ -1122,7 +1122,7 @@ rds_send_pong(struct rds_connection *conn, __be16 dport) rds_stats_inc(s_send_pong); if (!test_bit(RDS_LL_SEND_FULL, &conn->c_flags)) - rds_send_xmit(conn); + queue_delayed_work(rds_wq, &conn->c_send_w, 0); rds_message_put(rm); return 0; diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c index b77f5a06a65..bdacd8df318 100644 --- a/net/sched/act_gact.c +++ b/net/sched/act_gact.c @@ -67,6 +67,9 @@ static int tcf_gact_init(struct nlattr *nla, struct nlattr *est, struct tcf_common *pc; int ret = 0; int err; +#ifdef CONFIG_GACT_PROB + struct tc_gact_p *p_parm = NULL; +#endif if (nla == NULL) return -EINVAL; @@ -82,6 +85,12 @@ static int tcf_gact_init(struct nlattr *nla, struct nlattr *est, #ifndef CONFIG_GACT_PROB if (tb[TCA_GACT_PROB] != NULL) return -EOPNOTSUPP; +#else + if (tb[TCA_GACT_PROB]) { + p_parm = nla_data(tb[TCA_GACT_PROB]); + if (p_parm->ptype >= MAX_RAND) + return -EINVAL; + } #endif pc = tcf_hash_check(parm->index, a, bind, &gact_hash_info); @@ -103,8 +112,7 @@ static int tcf_gact_init(struct nlattr *nla, struct nlattr *est, spin_lock_bh(&gact->tcf_lock); gact->tcf_action = parm->action; #ifdef CONFIG_GACT_PROB - if (tb[TCA_GACT_PROB] != NULL) { - struct tc_gact_p *p_parm = nla_data(tb[TCA_GACT_PROB]); + if (p_parm) { gact->tcfg_paction = p_parm->paction; gact->tcfg_pval = p_parm->pval; gact->tcfg_ptype = p_parm->ptype; @@ -133,7 +141,7 @@ static int tcf_gact(struct sk_buff *skb, const struct tc_action *a, spin_lock(&gact->tcf_lock); #ifdef CONFIG_GACT_PROB - if (gact->tcfg_ptype && gact_rand[gact->tcfg_ptype] != NULL) + if (gact->tcfg_ptype) action = gact_rand[gact->tcfg_ptype](gact); else action = gact->tcf_action; diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c index 24d94c097b3..599f67ada1e 100644 --- a/net/sched/sch_cbq.c +++ b/net/sched/sch_cbq.c @@ -250,10 +250,11 @@ cbq_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr) else if ((cl = defmap[res.classid & TC_PRIO_MAX]) == NULL) cl = defmap[TC_PRIO_BESTEFFORT]; - if (cl == NULL || cl->level >= head->level) + if (cl == NULL) goto fallback; } - + if (cl->level >= head->level) + goto fallback; #ifdef CONFIG_NET_CLS_ACT switch (result) { case TC_ACT_QUEUED: diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index 29b942ce9e8..f08b9166119 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c @@ -876,7 +876,7 @@ static struct sk_buff *htb_dequeue(struct Qdisc *sch) q->now = psched_get_time(); start_at = jiffies; - next_event = q->now + 5 * PSCHED_TICKS_PER_SEC; + next_event = q->now + 5LLU * PSCHED_TICKS_PER_SEC; for (level = 0; level < TC_HTB_MAXDEPTH; level++) { /* common case optimization - skip event handler quickly */ diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index ebd22966f74..992acaac5de 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c @@ -329,29 +329,22 @@ static psched_time_t packet_len_2_sched_time(unsigned int len, struct netem_sche return PSCHED_NS2TICKS(ticks); } -static int tfifo_enqueue(struct sk_buff *nskb, struct Qdisc *sch) +static void tfifo_enqueue(struct sk_buff *nskb, struct Qdisc *sch) { struct sk_buff_head *list = &sch->q; psched_time_t tnext = netem_skb_cb(nskb)->time_to_send; - struct sk_buff *skb; - - if (likely(skb_queue_len(list) < sch->limit)) { - skb = skb_peek_tail(list); - /* Optimize for add at tail */ - if (likely(!skb || tnext >= netem_skb_cb(skb)->time_to_send)) - return qdisc_enqueue_tail(nskb, sch); + struct sk_buff *skb = skb_peek_tail(list); - skb_queue_reverse_walk(list, skb) { - if (tnext >= netem_skb_cb(skb)->time_to_send) - break; - } + /* Optimize for add at tail */ + if (likely(!skb || tnext >= netem_skb_cb(skb)->time_to_send)) + return __skb_queue_tail(list, nskb); - __skb_queue_after(list, skb, nskb); - sch->qstats.backlog += qdisc_pkt_len(nskb); - return NET_XMIT_SUCCESS; + skb_queue_reverse_walk(list, skb) { + if (tnext >= netem_skb_cb(skb)->time_to_send) + break; } - return qdisc_reshape_fail(nskb, sch); + __skb_queue_after(list, skb, nskb); } /* @@ -366,7 +359,6 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch) /* We don't fill cb now as skb_unshare() may invalidate it */ struct netem_skb_cb *cb; struct sk_buff *skb2; - int ret; int count = 1; /* Random duplication */ @@ -414,6 +406,11 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch) skb->data[net_random() % skb_headlen(skb)] ^= 1<<(net_random() % 8); } + if (unlikely(skb_queue_len(&sch->q) >= sch->limit)) + return qdisc_reshape_fail(skb, sch); + + sch->qstats.backlog += qdisc_pkt_len(skb); + cb = netem_skb_cb(skb); if (q->gap == 0 || /* not doing reordering */ q->counter < q->gap - 1 || /* inside last reordering gap */ @@ -445,7 +442,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch) cb->time_to_send = now + delay; ++q->counter; - ret = tfifo_enqueue(skb, sch); + tfifo_enqueue(skb, sch); } else { /* * Do re-ordering by putting one out of N packets at the front @@ -455,16 +452,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch) q->counter = 0; __skb_queue_head(&sch->q, skb); - sch->qstats.backlog += qdisc_pkt_len(skb); sch->qstats.requeues++; - ret = NET_XMIT_SUCCESS; - } - - if (ret != NET_XMIT_SUCCESS) { - if (net_xmit_drop_count(ret)) { - sch->qstats.drops++; - return ret; - } } return NET_XMIT_SUCCESS; diff --git a/net/sched/sch_sfb.c b/net/sched/sch_sfb.c index d7eea99333e..c6a5867d35c 100644 --- a/net/sched/sch_sfb.c +++ b/net/sched/sch_sfb.c @@ -570,6 +570,8 @@ static int sfb_dump(struct Qdisc *sch, struct sk_buff *skb) sch->qstats.backlog = q->qdisc->qstats.backlog; opts = nla_nest_start(skb, TCA_OPTIONS); + if (opts == NULL) + goto nla_put_failure; NLA_PUT(skb, TCA_SFB_PARMS, sizeof(opt), &opt); return nla_nest_end(skb, opts); diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c index 6c8556459a7..0018b653cb1 100644 --- a/net/sctp/chunk.c +++ b/net/sctp/chunk.c @@ -183,7 +183,7 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc, msg = sctp_datamsg_new(GFP_KERNEL); if (!msg) - return NULL; + return ERR_PTR(-ENOMEM); /* Note: Calculate this outside of the loop, so that all fragments * have the same expiration. @@ -280,11 +280,14 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc, chunk = sctp_make_datafrag_empty(asoc, sinfo, len, frag, 0); - if (!chunk) + if (!chunk) { + err = -ENOMEM; goto errout; + } + err = sctp_user_addto_chunk(chunk, offset, len, msgh->msg_iov); if (err < 0) - goto errout; + goto errout_chunk_free; offset += len; @@ -315,8 +318,10 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc, chunk = sctp_make_datafrag_empty(asoc, sinfo, over, frag, 0); - if (!chunk) + if (!chunk) { + err = -ENOMEM; goto errout; + } err = sctp_user_addto_chunk(chunk, offset, over,msgh->msg_iov); @@ -324,7 +329,7 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc, __skb_pull(chunk->skb, (__u8 *)chunk->chunk_hdr - (__u8 *)chunk->skb->data); if (err < 0) - goto errout; + goto errout_chunk_free; sctp_datamsg_assign(msg, chunk); list_add_tail(&chunk->frag_list, &msg->chunks); @@ -332,6 +337,9 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc, return msg; +errout_chunk_free: + sctp_chunk_free(chunk); + errout: list_for_each_safe(pos, temp, &msg->chunks) { list_del_init(pos); @@ -339,7 +347,7 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc, sctp_chunk_free(chunk); } sctp_datamsg_put(msg); - return NULL; + return ERR_PTR(err); } /* Check whether this message has expired. */ diff --git a/net/sctp/input.c b/net/sctp/input.c index 80f71af7138..be772c007db 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c @@ -736,15 +736,12 @@ static void __sctp_unhash_endpoint(struct sctp_endpoint *ep) epb = &ep->base; - if (hlist_unhashed(&epb->node)) - return; - epb->hashent = sctp_ep_hashfn(epb->bind_addr.port); head = &sctp_ep_hashtable[epb->hashent]; sctp_write_lock(&head->lock); - __hlist_del(&epb->node); + hlist_del_init(&epb->node); sctp_write_unlock(&head->lock); } @@ -825,7 +822,7 @@ static void __sctp_unhash_established(struct sctp_association *asoc) head = &sctp_assoc_hashtable[epb->hashent]; sctp_write_lock(&head->lock); - __hlist_del(&epb->node); + hlist_del_init(&epb->node); sctp_write_unlock(&head->lock); } diff --git a/net/sctp/output.c b/net/sctp/output.c index 8fc4dcd294a..32ba8d0e50e 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c @@ -334,6 +334,25 @@ sctp_xmit_t sctp_packet_append_chunk(struct sctp_packet *packet, return retval; } +static void sctp_packet_release_owner(struct sk_buff *skb) +{ + sk_free(skb->sk); +} + +static void sctp_packet_set_owner_w(struct sk_buff *skb, struct sock *sk) +{ + skb_orphan(skb); + skb->sk = sk; + skb->destructor = sctp_packet_release_owner; + + /* + * The data chunks have already been accounted for in sctp_sendmsg(), + * therefore only reserve a single byte to keep socket around until + * the packet has been transmitted. + */ + atomic_inc(&sk->sk_wmem_alloc); +} + /* All packets are sent to the network through this function from * sctp_outq_tail(). * @@ -375,7 +394,7 @@ int sctp_packet_transmit(struct sctp_packet *packet) /* Set the owning socket so that we know where to get the * destination IP address. */ - skb_set_owner_w(nskb, sk); + sctp_packet_set_owner_w(nskb, sk); if (!sctp_transport_dst_check(tp)) { sctp_transport_route(tp, NULL, sctp_sk(sk)); diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index 1ff51c9d18d..2fdb05d8aac 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c @@ -1610,8 +1610,9 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, asoc->outqueue.outstanding_bytes; sackh.num_gap_ack_blocks = 0; sackh.num_dup_tsns = 0; + chunk->subh.sack_hdr = &sackh; sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_SACK, - SCTP_SACKH(&sackh)); + SCTP_CHUNK(chunk)); break; case SCTP_CMD_DISCARD_PACKET: diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 92ba71dfe08..74053554a85 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -1231,8 +1231,14 @@ static int __sctp_connect(struct sock* sk, SCTP_DEBUG_PRINTK("About to exit __sctp_connect() free asoc: %p" " kaddrs: %p err: %d\n", asoc, kaddrs, err); - if (asoc) + if (asoc) { + /* sctp_primitive_ASSOCIATE may have added this association + * To the hash table, try to unhash it, just in case, its a noop + * if it wasn't hashed so we're safe + */ + sctp_unhash_established(asoc); sctp_association_free(asoc); + } return err; } @@ -1902,8 +1908,8 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, /* Break the message into multiple chunks of maximum size. */ datamsg = sctp_datamsg_from_user(asoc, sinfo, msg, msg_len); - if (!datamsg) { - err = -ENOMEM; + if (IS_ERR(datamsg)) { + err = PTR_ERR(datamsg); goto out_free; } @@ -1942,8 +1948,10 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, goto out_unlock; out_free: - if (new_asoc) + if (new_asoc) { + sctp_unhash_established(asoc); sctp_association_free(asoc); + } out_unlock: sctp_release_sock(sk); diff --git a/net/socket.c b/net/socket.c index 5e6e6218684..6d042da3efb 100644 --- a/net/socket.c +++ b/net/socket.c @@ -522,6 +522,9 @@ void sock_release(struct socket *sock) if (rcu_dereference_protected(sock->wq, 1)->fasync_list) printk(KERN_ERR "sock_release: fasync list not empty!\n"); + if (test_bit(SOCK_EXTERNALLY_ALLOCATED, &sock->flags)) + return; + percpu_sub(sockets_in_use, 1); if (!sock->file) { iput(SOCK_INODE(sock)); @@ -2602,7 +2605,7 @@ static int do_siocgstamp(struct net *net, struct socket *sock, err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ktv); set_fs(old_fs); if (!err) - err = compat_put_timeval(up, &ktv); + err = compat_put_timeval(&ktv, up); return err; } @@ -2618,7 +2621,7 @@ static int do_siocgstampns(struct net *net, struct socket *sock, err = sock_do_ioctl(net, sock, cmd, (unsigned long)&kts); set_fs(old_fs); if (!err) - err = compat_put_timespec(up, &kts); + err = compat_put_timespec(&kts, up); return err; } @@ -2655,6 +2658,7 @@ static int dev_ifconf(struct net *net, struct compat_ifconf __user *uifc32) if (copy_from_user(&ifc32, uifc32, sizeof(struct compat_ifconf))) return -EFAULT; + memset(&ifc, 0, sizeof(ifc)); if (ifc32.ifcbuf == 0) { ifc32.ifc_len = 0; ifc.ifc_len = 0; diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index de0b0f39d9d..76cb304f3f1 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -1406,11 +1406,11 @@ static ssize_t read_flush(struct file *file, char __user *buf, size_t count, loff_t *ppos, struct cache_detail *cd) { - char tbuf[20]; + char tbuf[22]; unsigned long p = *ppos; size_t len; - sprintf(tbuf, "%lu\n", convert_to_wallclock(cd->flush_time)); + snprintf(tbuf, sizeof(tbuf), "%lu\n", convert_to_wallclock(cd->flush_time)); len = strlen(tbuf); if (p >= len) return 0; diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 25302c80246..a28a2111297 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c @@ -236,7 +236,7 @@ static struct rpc_clnt *rpc_get_client_for_event(struct net *net, int event) spin_lock(&sn->rpc_client_lock); list_for_each_entry(clnt, &sn->all_clients, cl_clients) { if (clnt->cl_program->pipe_dir_name == NULL) - break; + continue; if (rpc_clnt_skip_event(clnt, event)) continue; if (atomic_inc_not_zero(&clnt->cl_count) == 0) @@ -1846,12 +1846,13 @@ call_timeout(struct rpc_task *task) return; } if (RPC_IS_SOFT(task)) { - if (clnt->cl_chatty) + if (clnt->cl_chatty) { rcu_read_lock(); printk(KERN_NOTICE "%s: server %s not responding, timed out\n", clnt->cl_protname, rcu_dereference(clnt->cl_xprt)->servername); rcu_read_unlock(); + } if (task->tk_flags & RPC_TASK_TIMEOUT) rpc_exit(task, -ETIMEDOUT); else diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index faa078f74b2..b8bda4434c0 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c @@ -1157,14 +1157,19 @@ static void rpc_kill_sb(struct super_block *sb) struct sunrpc_net *sn = net_generic(net, sunrpc_net_id); mutex_lock(&sn->pipefs_sb_lock); + if (sn->pipefs_sb != sb) { + mutex_unlock(&sn->pipefs_sb_lock); + goto out; + } sn->pipefs_sb = NULL; mutex_unlock(&sn->pipefs_sb_lock); - put_net(net); dprintk("RPC: sending pipefs UMOUNT notification for net %p%s\n", net, NET_NAME(net)); blocking_notifier_call_chain(&rpc_pipefs_notifier_list, RPC_PIPEFS_UMOUNT, sb); + put_net(net); +out: kill_litter_super(sb); } diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c index 4c38b33ab8a..4d53ad5220f 100644 --- a/net/sunrpc/rpcb_clnt.c +++ b/net/sunrpc/rpcb_clnt.c @@ -251,7 +251,7 @@ static int rpcb_create_local_unix(struct net *net) if (IS_ERR(clnt)) { dprintk("RPC: failed to create AF_LOCAL rpcbind " "client (errno %ld).\n", PTR_ERR(clnt)); - result = -PTR_ERR(clnt); + result = PTR_ERR(clnt); goto out; } @@ -298,7 +298,7 @@ static int rpcb_create_local_net(struct net *net) if (IS_ERR(clnt)) { dprintk("RPC: failed to create local rpcbind " "client (errno %ld).\n", PTR_ERR(clnt)); - result = -PTR_ERR(clnt); + result = PTR_ERR(clnt); goto out; } diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index 0c20629952c..3d5c9b912c7 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c @@ -790,7 +790,9 @@ void rpc_execute(struct rpc_task *task) static void rpc_async_schedule(struct work_struct *work) { + current->flags |= PF_FSTRANS; __rpc_execute(container_of(work, struct rpc_task, u.tk_work)); + current->flags &= ~PF_FSTRANS; } /** @@ -913,16 +915,35 @@ struct rpc_task *rpc_new_task(const struct rpc_task_setup *setup_data) return task; } +/* + * rpc_free_task - release rpc task and perform cleanups + * + * Note that we free up the rpc_task _after_ rpc_release_calldata() + * in order to work around a workqueue dependency issue. + * + * Tejun Heo states: + * "Workqueue currently considers two work items to be the same if they're + * on the same address and won't execute them concurrently - ie. it + * makes a work item which is queued again while being executed wait + * for the previous execution to complete. + * + * If a work function frees the work item, and then waits for an event + * which should be performed by another work item and *that* work item + * recycles the freed work item, it can create a false dependency loop. + * There really is no reliable way to detect this short of verifying + * every memory free." + * + */ static void rpc_free_task(struct rpc_task *task) { - const struct rpc_call_ops *tk_ops = task->tk_ops; - void *calldata = task->tk_calldata; + unsigned short tk_flags = task->tk_flags; + + rpc_release_calldata(task->tk_ops, task->tk_calldata); - if (task->tk_flags & RPC_TASK_DYNAMIC) { + if (tk_flags & RPC_TASK_DYNAMIC) { dprintk("RPC: %5u freeing task\n", task->tk_pid); mempool_free(task, rpc_task_mempool); } - rpc_release_calldata(tk_ops, calldata); } static void rpc_async_release(struct work_struct *work) @@ -932,8 +953,7 @@ static void rpc_async_release(struct work_struct *work) static void rpc_release_resources_task(struct rpc_task *task) { - if (task->tk_rqstp) - xprt_release(task); + xprt_release(task); if (task->tk_msg.rpc_cred) { put_rpccred(task->tk_msg.rpc_cred); task->tk_msg.rpc_cred = NULL; diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c index 4bda09d7e1a..fd9b2889aa9 100644 --- a/net/sunrpc/svc_xprt.c +++ b/net/sunrpc/svc_xprt.c @@ -316,7 +316,6 @@ static bool svc_xprt_has_something_to_do(struct svc_xprt *xprt) */ void svc_xprt_enqueue(struct svc_xprt *xprt) { - struct svc_serv *serv = xprt->xpt_server; struct svc_pool *pool; struct svc_rqst *rqstp; int cpu; @@ -362,8 +361,6 @@ void svc_xprt_enqueue(struct svc_xprt *xprt) rqstp, rqstp->rq_xprt); rqstp->rq_xprt = xprt; svc_xprt_get(xprt); - rqstp->rq_reserved = serv->sv_max_mesg; - atomic_add(rqstp->rq_reserved, &xprt->xpt_reserved); pool->sp_stats.threads_woken++; wake_up(&rqstp->rq_wait); } else { @@ -643,8 +640,6 @@ int svc_recv(struct svc_rqst *rqstp, long timeout) if (xprt) { rqstp->rq_xprt = xprt; svc_xprt_get(xprt); - rqstp->rq_reserved = serv->sv_max_mesg; - atomic_add(rqstp->rq_reserved, &xprt->xpt_reserved); /* As there is a shortage of threads and this request * had to be queued, don't allow the thread to wait so @@ -741,6 +736,8 @@ int svc_recv(struct svc_rqst *rqstp, long timeout) else len = xprt->xpt_ops->xpo_recvfrom(rqstp); dprintk("svc: got len=%d\n", len); + rqstp->rq_reserved = serv->sv_max_mesg; + atomic_add(rqstp->rq_reserved, &xprt->xpt_reserved); } svc_xprt_received(xprt); @@ -797,7 +794,8 @@ int svc_send(struct svc_rqst *rqstp) /* Grab mutex to serialize outgoing data. */ mutex_lock(&xprt->xpt_mutex); - if (test_bit(XPT_DEAD, &xprt->xpt_flags)) + if (test_bit(XPT_DEAD, &xprt->xpt_flags) + || test_bit(XPT_CLOSE, &xprt->xpt_flags)) len = -ENOTCONN; else len = xprt->xpt_ops->xpo_sendto(rqstp); diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index 824d32fb312..f190ea96f11 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c @@ -1137,9 +1137,9 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp) if (len >= 0) svsk->sk_tcplen += len; if (len != want) { + svc_tcp_save_pages(svsk, rqstp); if (len < 0 && len != -EAGAIN) goto err_other; - svc_tcp_save_pages(svsk, rqstp); dprintk("svc: incomplete TCP record (%d of %d)\n", svsk->sk_tcplen, svsk->sk_reclen); goto err_noclose; diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index da72492360b..feea4741edd 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c @@ -969,11 +969,11 @@ static bool xprt_dynamic_free_slot(struct rpc_xprt *xprt, struct rpc_rqst *req) return false; } -static void xprt_alloc_slot(struct rpc_task *task) +void xprt_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task) { - struct rpc_xprt *xprt = task->tk_xprt; struct rpc_rqst *req; + spin_lock(&xprt->reserve_lock); if (!list_empty(&xprt->free)) { req = list_entry(xprt->free.next, struct rpc_rqst, rq_list); list_del(&req->rq_list); @@ -994,12 +994,29 @@ static void xprt_alloc_slot(struct rpc_task *task) default: task->tk_status = -EAGAIN; } + spin_unlock(&xprt->reserve_lock); return; out_init_req: task->tk_status = 0; task->tk_rqstp = req; xprt_request_init(task, xprt); + spin_unlock(&xprt->reserve_lock); +} +EXPORT_SYMBOL_GPL(xprt_alloc_slot); + +void xprt_lock_and_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task) +{ + /* Note: grabbing the xprt_lock_write() ensures that we throttle + * new slot allocation if the transport is congested (i.e. when + * reconnecting a stream transport or when out of socket write + * buffer space). + */ + if (xprt_lock_write(xprt, task)) { + xprt_alloc_slot(xprt, task); + xprt_release_write(xprt, task); + } } +EXPORT_SYMBOL_GPL(xprt_lock_and_alloc_slot); static void xprt_free_slot(struct rpc_xprt *xprt, struct rpc_rqst *req) { @@ -1083,20 +1100,9 @@ void xprt_reserve(struct rpc_task *task) if (task->tk_rqstp != NULL) return; - /* Note: grabbing the xprt_lock_write() here is not strictly needed, - * but ensures that we throttle new slot allocation if the transport - * is congested (e.g. if reconnecting or if we're out of socket - * write buffer space). - */ task->tk_timeout = 0; task->tk_status = -EAGAIN; - if (!xprt_lock_write(xprt, task)) - return; - - spin_lock(&xprt->reserve_lock); - xprt_alloc_slot(task); - spin_unlock(&xprt->reserve_lock); - xprt_release_write(xprt, task); + xprt->ops->alloc_slot(xprt, task); } static inline __be32 xprt_alloc_xid(struct rpc_xprt *xprt) @@ -1133,10 +1139,18 @@ static void xprt_request_init(struct rpc_task *task, struct rpc_xprt *xprt) void xprt_release(struct rpc_task *task) { struct rpc_xprt *xprt; - struct rpc_rqst *req; + struct rpc_rqst *req = task->tk_rqstp; - if (!(req = task->tk_rqstp)) + if (req == NULL) { + if (task->tk_client) { + rcu_read_lock(); + xprt = rcu_dereference(task->tk_client->cl_xprt); + if (xprt->snd_task == task) + xprt_release_write(xprt, task); + rcu_read_unlock(); + } return; + } xprt = req->rq_xprt; if (task->tk_ops->rpc_count_stats != NULL) diff --git a/net/sunrpc/xprtrdma/transport.c b/net/sunrpc/xprtrdma/transport.c index b446e100286..5d9202dc7cb 100644 --- a/net/sunrpc/xprtrdma/transport.c +++ b/net/sunrpc/xprtrdma/transport.c @@ -200,6 +200,7 @@ xprt_rdma_connect_worker(struct work_struct *work) int rc = 0; if (!xprt->shutdown) { + current->flags |= PF_FSTRANS; xprt_clear_connected(xprt); dprintk("RPC: %s: %sconnect\n", __func__, @@ -212,10 +213,10 @@ xprt_rdma_connect_worker(struct work_struct *work) out: xprt_wake_pending_tasks(xprt, rc); - out_clear: dprintk("RPC: %s: exit\n", __func__); xprt_clear_connecting(xprt); + current->flags &= ~PF_FSTRANS; } /* @@ -712,6 +713,7 @@ static void xprt_rdma_print_stats(struct rpc_xprt *xprt, struct seq_file *seq) static struct rpc_xprt_ops xprt_rdma_procs = { .reserve_xprt = xprt_rdma_reserve_xprt, .release_xprt = xprt_release_xprt_cong, /* sunrpc/xprt.c */ + .alloc_slot = xprt_alloc_slot, .release_request = xprt_release_rqst_cong, /* ditto */ .set_retrans_timeout = xprt_set_retrans_timeout_def, /* ditto */ .rpcbind = rpcb_getport_async, /* sunrpc/rpcb_clnt.c */ diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 890b03f8d87..79064471cd0 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -254,7 +254,6 @@ struct sock_xprt { void (*old_data_ready)(struct sock *, int); void (*old_state_change)(struct sock *); void (*old_write_space)(struct sock *); - void (*old_error_report)(struct sock *); }; /* @@ -737,10 +736,10 @@ static int xs_tcp_send_request(struct rpc_task *task) dprintk("RPC: sendmsg returned unrecognized error %d\n", -status); case -ECONNRESET: - case -EPIPE: xs_tcp_shutdown(xprt); case -ECONNREFUSED: case -ENOTCONN: + case -EPIPE: clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags); } @@ -781,7 +780,6 @@ static void xs_save_old_callbacks(struct sock_xprt *transport, struct sock *sk) transport->old_data_ready = sk->sk_data_ready; transport->old_state_change = sk->sk_state_change; transport->old_write_space = sk->sk_write_space; - transport->old_error_report = sk->sk_error_report; } static void xs_restore_old_callbacks(struct sock_xprt *transport, struct sock *sk) @@ -789,7 +787,6 @@ static void xs_restore_old_callbacks(struct sock_xprt *transport, struct sock *s sk->sk_data_ready = transport->old_data_ready; sk->sk_state_change = transport->old_state_change; sk->sk_write_space = transport->old_write_space; - sk->sk_error_report = transport->old_error_report; } static void xs_reset_transport(struct sock_xprt *transport) @@ -1028,6 +1025,16 @@ static void xs_udp_data_ready(struct sock *sk, int len) read_unlock_bh(&sk->sk_callback_lock); } +/* + * Helper function to force a TCP close if the server is sending + * junk and/or it has put us in CLOSE_WAIT + */ +static void xs_tcp_force_close(struct rpc_xprt *xprt) +{ + set_bit(XPRT_CONNECTION_CLOSE, &xprt->state); + xprt_force_disconnect(xprt); +} + static inline void xs_tcp_read_fraghdr(struct rpc_xprt *xprt, struct xdr_skb_reader *desc) { struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); @@ -1054,7 +1061,7 @@ static inline void xs_tcp_read_fraghdr(struct rpc_xprt *xprt, struct xdr_skb_rea /* Sanity check of the record length */ if (unlikely(transport->tcp_reclen < 8)) { dprintk("RPC: invalid TCP record fragment length\n"); - xprt_force_disconnect(xprt); + xs_tcp_force_close(xprt); return; } dprintk("RPC: reading TCP record fragment of length %d\n", @@ -1135,7 +1142,7 @@ static inline void xs_tcp_read_calldir(struct sock_xprt *transport, break; default: dprintk("RPC: invalid request message type\n"); - xprt_force_disconnect(&transport->xprt); + xs_tcp_force_close(&transport->xprt); } xs_tcp_check_fraghdr(transport); } @@ -1455,12 +1462,19 @@ static void xs_tcp_cancel_linger_timeout(struct rpc_xprt *xprt) xprt_clear_connecting(xprt); } -static void xs_sock_mark_closed(struct rpc_xprt *xprt) +static void xs_sock_reset_connection_flags(struct rpc_xprt *xprt) { smp_mb__before_clear_bit(); + clear_bit(XPRT_CONNECTION_ABORT, &xprt->state); + clear_bit(XPRT_CONNECTION_CLOSE, &xprt->state); clear_bit(XPRT_CLOSE_WAIT, &xprt->state); clear_bit(XPRT_CLOSING, &xprt->state); smp_mb__after_clear_bit(); +} + +static void xs_sock_mark_closed(struct rpc_xprt *xprt) +{ + xs_sock_reset_connection_flags(xprt); /* Mark transport as closed and wake up all pending tasks */ xprt_disconnect_done(xprt); } @@ -1515,8 +1529,9 @@ static void xs_tcp_state_change(struct sock *sk) break; case TCP_CLOSE_WAIT: /* The server initiated a shutdown of the socket */ - xprt_force_disconnect(xprt); xprt->connect_cookie++; + clear_bit(XPRT_CONNECTED, &xprt->state); + xs_tcp_force_close(xprt); case TCP_CLOSING: /* * If the server closed down the connection, make sure that @@ -1540,25 +1555,6 @@ static void xs_tcp_state_change(struct sock *sk) read_unlock_bh(&sk->sk_callback_lock); } -/** - * xs_error_report - callback mainly for catching socket errors - * @sk: socket - */ -static void xs_error_report(struct sock *sk) -{ - struct rpc_xprt *xprt; - - read_lock_bh(&sk->sk_callback_lock); - if (!(xprt = xprt_from_sock(sk))) - goto out; - dprintk("RPC: %s client %p...\n" - "RPC: error %d\n", - __func__, xprt, sk->sk_err); - xprt_wake_pending_tasks(xprt, -EAGAIN); -out: - read_unlock_bh(&sk->sk_callback_lock); -} - static void xs_write_space(struct sock *sk) { struct socket *sock; @@ -1858,7 +1854,6 @@ static int xs_local_finish_connecting(struct rpc_xprt *xprt, sk->sk_user_data = xprt; sk->sk_data_ready = xs_local_data_ready; sk->sk_write_space = xs_udp_write_space; - sk->sk_error_report = xs_error_report; sk->sk_allocation = GFP_ATOMIC; xprt_clear_connected(xprt); @@ -1895,6 +1890,8 @@ static void xs_local_setup_socket(struct work_struct *work) if (xprt->shutdown) goto out; + current->flags |= PF_FSTRANS; + clear_bit(XPRT_CONNECTION_ABORT, &xprt->state); status = __sock_create(xprt->xprt_net, AF_LOCAL, SOCK_STREAM, 0, &sock, 1); @@ -1928,6 +1925,7 @@ static void xs_local_setup_socket(struct work_struct *work) out: xprt_clear_connecting(xprt); xprt_wake_pending_tasks(xprt, status); + current->flags &= ~PF_FSTRANS; } static void xs_udp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) @@ -1944,7 +1942,6 @@ static void xs_udp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) sk->sk_user_data = xprt; sk->sk_data_ready = xs_udp_data_ready; sk->sk_write_space = xs_udp_write_space; - sk->sk_error_report = xs_error_report; sk->sk_no_check = UDP_CSUM_NORCV; sk->sk_allocation = GFP_ATOMIC; @@ -1970,6 +1967,8 @@ static void xs_udp_setup_socket(struct work_struct *work) if (xprt->shutdown) goto out; + current->flags |= PF_FSTRANS; + /* Start by resetting any existing state */ xs_reset_transport(transport); sock = xs_create_sock(xprt, transport, @@ -1988,6 +1987,7 @@ static void xs_udp_setup_socket(struct work_struct *work) out: xprt_clear_connecting(xprt); xprt_wake_pending_tasks(xprt, status); + current->flags &= ~PF_FSTRANS; } /* @@ -2009,10 +2009,8 @@ static void xs_abort_connection(struct sock_xprt *transport) any.sa_family = AF_UNSPEC; result = kernel_connect(transport->sock, &any, sizeof(any), 0); if (!result) - xs_sock_mark_closed(&transport->xprt); - else - dprintk("RPC: AF_UNSPEC connect return code %d\n", - result); + xs_sock_reset_connection_flags(&transport->xprt); + dprintk("RPC: AF_UNSPEC connect return code %d\n", result); } static void xs_tcp_reuse_connection(struct sock_xprt *transport) @@ -2057,7 +2055,6 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) sk->sk_data_ready = xs_tcp_data_ready; sk->sk_state_change = xs_tcp_state_change; sk->sk_write_space = xs_tcp_write_space; - sk->sk_error_report = xs_error_report; sk->sk_allocation = GFP_ATOMIC; /* socket options */ @@ -2113,6 +2110,8 @@ static void xs_tcp_setup_socket(struct work_struct *work) if (xprt->shutdown) goto out; + current->flags |= PF_FSTRANS; + if (!sock) { clear_bit(XPRT_CONNECTION_ABORT, &xprt->state); sock = xs_create_sock(xprt, transport, @@ -2151,8 +2150,7 @@ static void xs_tcp_setup_socket(struct work_struct *work) /* We're probably in TIME_WAIT. Get rid of existing socket, * and retry */ - set_bit(XPRT_CONNECTION_CLOSE, &xprt->state); - xprt_force_disconnect(xprt); + xs_tcp_force_close(xprt); break; case -ECONNREFUSED: case -ECONNRESET: @@ -2162,6 +2160,7 @@ static void xs_tcp_setup_socket(struct work_struct *work) case -EINPROGRESS: case -EALREADY: xprt_clear_connecting(xprt); + current->flags &= ~PF_FSTRANS; return; case -EINVAL: /* Happens, for instance, if the user specified a link @@ -2174,6 +2173,7 @@ static void xs_tcp_setup_socket(struct work_struct *work) out: xprt_clear_connecting(xprt); xprt_wake_pending_tasks(xprt, status); + current->flags &= ~PF_FSTRANS; } /** @@ -2423,6 +2423,7 @@ static void bc_destroy(struct rpc_xprt *xprt) static struct rpc_xprt_ops xs_local_ops = { .reserve_xprt = xprt_reserve_xprt, .release_xprt = xs_tcp_release_xprt, + .alloc_slot = xprt_alloc_slot, .rpcbind = xs_local_rpcbind, .set_port = xs_local_set_port, .connect = xs_connect, @@ -2439,6 +2440,7 @@ static struct rpc_xprt_ops xs_udp_ops = { .set_buffer_size = xs_udp_set_buffer_size, .reserve_xprt = xprt_reserve_xprt_cong, .release_xprt = xprt_release_xprt_cong, + .alloc_slot = xprt_alloc_slot, .rpcbind = rpcb_getport_async, .set_port = xs_set_port, .connect = xs_connect, @@ -2456,6 +2458,7 @@ static struct rpc_xprt_ops xs_udp_ops = { static struct rpc_xprt_ops xs_tcp_ops = { .reserve_xprt = xprt_reserve_xprt, .release_xprt = xs_tcp_release_xprt, + .alloc_slot = xprt_lock_and_alloc_slot, .rpcbind = rpcb_getport_async, .set_port = xs_set_port, .connect = xs_connect, @@ -2475,6 +2478,7 @@ static struct rpc_xprt_ops xs_tcp_ops = { static struct rpc_xprt_ops bc_tcp_ops = { .reserve_xprt = xprt_reserve_xprt, .release_xprt = xprt_release_xprt, + .alloc_slot = xprt_alloc_slot, .rpcbind = xs_local_rpcbind, .buf_alloc = bc_malloc, .buf_free = bc_free, diff --git a/net/wanrouter/wanmain.c b/net/wanrouter/wanmain.c index 788a12c1eb5..2ab785064b7 100644 --- a/net/wanrouter/wanmain.c +++ b/net/wanrouter/wanmain.c @@ -602,36 +602,31 @@ static int wanrouter_device_new_if(struct wan_device *wandev, * successfully, add it to the interface list. */ - if (dev->name == NULL) { - err = -EINVAL; - } else { +#ifdef WANDEBUG + printk(KERN_INFO "%s: registering interface %s...\n", + wanrouter_modname, dev->name); +#endif - #ifdef WANDEBUG - printk(KERN_INFO "%s: registering interface %s...\n", - wanrouter_modname, dev->name); - #endif - - err = register_netdev(dev); - if (!err) { - struct net_device *slave = NULL; - unsigned long smp_flags=0; - - lock_adapter_irq(&wandev->lock, &smp_flags); - - if (wandev->dev == NULL) { - wandev->dev = dev; - } else { - for (slave=wandev->dev; - DEV_TO_SLAVE(slave); - slave = DEV_TO_SLAVE(slave)) - DEV_TO_SLAVE(slave) = dev; - } - ++wandev->ndev; - - unlock_adapter_irq(&wandev->lock, &smp_flags); - err = 0; /* done !!! */ - goto out; + err = register_netdev(dev); + if (!err) { + struct net_device *slave = NULL; + unsigned long smp_flags=0; + + lock_adapter_irq(&wandev->lock, &smp_flags); + + if (wandev->dev == NULL) { + wandev->dev = dev; + } else { + for (slave=wandev->dev; + DEV_TO_SLAVE(slave); + slave = DEV_TO_SLAVE(slave)) + DEV_TO_SLAVE(slave) = dev; } + ++wandev->ndev; + + unlock_adapter_irq(&wandev->lock, &smp_flags); + err = 0; /* done !!! */ + goto out; } if (wandev->del_if) wandev->del_if(wandev, dev); diff --git a/net/wireless/core.c b/net/wireless/core.c index 674c1fa2bd6..52aa3394af2 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -557,8 +557,7 @@ int wiphy_register(struct wiphy *wiphy) for (i = 0; i < sband->n_channels; i++) { sband->channels[i].orig_flags = sband->channels[i].flags; - sband->channels[i].orig_mag = - sband->channels[i].max_antenna_gain; + sband->channels[i].orig_mag = INT_MAX; sband->channels[i].orig_mpwr = sband->channels[i].max_power; sband->channels[i].band = band; @@ -980,6 +979,11 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb, */ synchronize_rcu(); INIT_LIST_HEAD(&wdev->list); + /* + * Ensure that all events have been processed and + * freed. + */ + cfg80211_process_wdev_events(wdev); break; case NETDEV_PRE_UP: if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype))) diff --git a/net/wireless/core.h b/net/wireless/core.h index 036faeed00f..d95937b9726 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -426,6 +426,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, struct net_device *dev, enum nl80211_iftype ntype, u32 *flags, struct vif_params *params); void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev); +void cfg80211_process_wdev_events(struct wireless_dev *wdev); int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, struct wireless_dev *wdev, diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 1078e07da2a..012d2f4eaf5 100755 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -134,9 +134,8 @@ static const struct ieee80211_regdomain world_regdom = { .reg_rules = { /* IEEE 802.11b/g, channels 1..11 */ REG_RULE(2412-10, 2462+10, 40, 6, 20, 0), - /* IEEE 802.11b/g, channels 12..13. No HT40 - * channel fits here. */ - REG_RULE(2467-10, 2472+10, 20, 6, 20, + /* IEEE 802.11b/g, channels 12..13. */ + REG_RULE(2467-10, 2472+10, 40, 6, 20, NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS), /* IEEE 802.11 channel 14 - Only JP enables @@ -340,6 +339,9 @@ static void reg_regdb_search(struct work_struct *work) struct reg_regdb_search_request *request; const struct ieee80211_regdomain *curdom, *regdom; int i, r; + bool set_reg = false; + + mutex_lock(&cfg80211_mutex); mutex_lock(®_regdb_search_mutex); while (!list_empty(®_regdb_search_list)) { @@ -355,9 +357,7 @@ static void reg_regdb_search(struct work_struct *work) r = reg_copy_regd(®dom, curdom); if (r) break; - mutex_lock(&cfg80211_mutex); - set_regdom(regdom); - mutex_unlock(&cfg80211_mutex); + set_reg = true; break; } } @@ -365,6 +365,11 @@ static void reg_regdb_search(struct work_struct *work) kfree(request); } mutex_unlock(®_regdb_search_mutex); + + if (set_reg) + set_regdom(regdom); + + mutex_unlock(&cfg80211_mutex); } static DECLARE_WORK(reg_regdb_work, reg_regdb_search); @@ -891,7 +896,21 @@ static void handle_channel(struct wiphy *wiphy, chan->max_antenna_gain = min(chan->orig_mag, (int) MBI_TO_DBI(power_rule->max_antenna_gain)); chan->max_reg_power = (int) MBM_TO_DBM(power_rule->max_eirp); - chan->max_power = min(chan->max_power, chan->max_reg_power); + if (chan->orig_mpwr) { + /* + * Devices that have their own custom regulatory domain + * but also use WIPHY_FLAG_STRICT_REGULATORY will follow the + * passed country IE power settings. + */ + if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE && + wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY && + wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) + chan->max_power = chan->max_reg_power; + else + chan->max_power = min(chan->orig_mpwr, + chan->max_reg_power); + } else + chan->max_power = chan->max_reg_power; } static void handle_band(struct wiphy *wiphy, diff --git a/net/wireless/util.c b/net/wireless/util.c index 7e8a63e2da5..75e1ad11935 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -294,23 +294,21 @@ unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb) } EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb); -static int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr) +unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr) { int ae = meshhdr->flags & MESH_FLAGS_AE; - /* 7.1.3.5a.2 */ + /* 802.11-2012, 8.2.4.7.3 */ switch (ae) { + default: case 0: return 6; case MESH_FLAGS_AE_A4: return 12; case MESH_FLAGS_AE_A5_A6: return 18; - case (MESH_FLAGS_AE_A4 | MESH_FLAGS_AE_A5_A6): - return 24; - default: - return 6; } } +EXPORT_SYMBOL(ieee80211_get_mesh_hdrlen); int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, enum nl80211_iftype iftype) @@ -358,6 +356,8 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, /* make sure meshdr->flags is on the linear part */ if (!pskb_may_pull(skb, hdrlen + 1)) return -1; + if (meshdr->flags & MESH_FLAGS_AE_A4) + return -1; if (meshdr->flags & MESH_FLAGS_AE_A5_A6) { skb_copy_bits(skb, hdrlen + offsetof(struct ieee80211s_hdr, eaddr1), @@ -382,6 +382,8 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, /* make sure meshdr->flags is on the linear part */ if (!pskb_may_pull(skb, hdrlen + 1)) return -1; + if (meshdr->flags & MESH_FLAGS_AE_A5_A6) + return -1; if (meshdr->flags & MESH_FLAGS_AE_A4) skb_copy_bits(skb, hdrlen + offsetof(struct ieee80211s_hdr, eaddr1), @@ -721,7 +723,7 @@ void cfg80211_upload_connect_keys(struct wireless_dev *wdev) wdev->connect_keys = NULL; } -static void cfg80211_process_wdev_events(struct wireless_dev *wdev) +void cfg80211_process_wdev_events(struct wireless_dev *wdev) { struct cfg80211_event *ev; unsigned long flags; @@ -809,7 +811,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, ntype == NL80211_IFTYPE_P2P_CLIENT)) return -EBUSY; - if (ntype != otype) { + if (ntype != otype && netif_running(dev)) { err = cfg80211_can_change_interface(rdev, dev->ieee80211_ptr, ntype); if (err) @@ -1051,6 +1053,9 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, } mutex_unlock(&rdev->devlist_mtx); + if (total == 1) + return 0; + for (i = 0; i < rdev->wiphy.n_iface_combinations; i++) { const struct ieee80211_iface_combination *c; struct ieee80211_iface_limit *limits; diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c index 54a0dc2e2f8..ab2bb42fe09 100644 --- a/net/xfrm/xfrm_input.c +++ b/net/xfrm/xfrm_input.c @@ -212,7 +212,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) /* only the first xfrm gets the encap type */ encap_type = 0; - if (async && x->repl->check(x, skb, seq)) { + if (async && x->repl->recheck(x, skb, seq)) { XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATESEQERROR); goto drop_unlock; } diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index a15d2a03172..71c80c763d5 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -1761,7 +1761,7 @@ static struct dst_entry *make_blackhole(struct net *net, u16 family, if (!afinfo) { dst_release(dst_orig); - ret = ERR_PTR(-EINVAL); + return ERR_PTR(-EINVAL); } else { ret = afinfo->blackhole_route(net, dst_orig); } diff --git a/net/xfrm/xfrm_replay.c b/net/xfrm/xfrm_replay.c index 2f6d11d04a2..3efb07d3eb2 100644 --- a/net/xfrm/xfrm_replay.c +++ b/net/xfrm/xfrm_replay.c @@ -420,6 +420,18 @@ static int xfrm_replay_check_esn(struct xfrm_state *x, return -EINVAL; } +static int xfrm_replay_recheck_esn(struct xfrm_state *x, + struct sk_buff *skb, __be32 net_seq) +{ + if (unlikely(XFRM_SKB_CB(skb)->seq.input.hi != + htonl(xfrm_replay_seqhi(x, net_seq)))) { + x->stats.replay_window++; + return -EINVAL; + } + + return xfrm_replay_check_esn(x, skb, net_seq); +} + static void xfrm_replay_advance_esn(struct xfrm_state *x, __be32 net_seq) { unsigned int bitnr, nr, i; @@ -479,6 +491,7 @@ static void xfrm_replay_advance_esn(struct xfrm_state *x, __be32 net_seq) static struct xfrm_replay xfrm_replay_legacy = { .advance = xfrm_replay_advance, .check = xfrm_replay_check, + .recheck = xfrm_replay_check, .notify = xfrm_replay_notify, .overflow = xfrm_replay_overflow, }; @@ -486,6 +499,7 @@ static struct xfrm_replay xfrm_replay_legacy = { static struct xfrm_replay xfrm_replay_bmp = { .advance = xfrm_replay_advance_bmp, .check = xfrm_replay_check_bmp, + .recheck = xfrm_replay_check_bmp, .notify = xfrm_replay_notify_bmp, .overflow = xfrm_replay_overflow_bmp, }; @@ -493,6 +507,7 @@ static struct xfrm_replay xfrm_replay_bmp = { static struct xfrm_replay xfrm_replay_esn = { .advance = xfrm_replay_advance_esn, .check = xfrm_replay_check_esn, + .recheck = xfrm_replay_recheck_esn, .notify = xfrm_replay_notify_bmp, .overflow = xfrm_replay_overflow_esn, }; diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 7128dde0fe1..c8b903df943 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -123,9 +123,21 @@ static inline int verify_replay(struct xfrm_usersa_info *p, struct nlattr **attrs) { struct nlattr *rt = attrs[XFRMA_REPLAY_ESN_VAL]; + struct xfrm_replay_state_esn *rs; - if ((p->flags & XFRM_STATE_ESN) && !rt) - return -EINVAL; + if (p->flags & XFRM_STATE_ESN) { + if (!rt) + return -EINVAL; + + rs = nla_data(rt); + + if (rs->bmp_len > XFRMA_REPLAY_ESN_MAX / sizeof(rs->bmp[0]) / 8) + return -EINVAL; + + if (nla_len(rt) < xfrm_replay_state_esn_len(rs) && + nla_len(rt) != sizeof(*rs)) + return -EINVAL; + } if (!rt) return 0; @@ -370,14 +382,15 @@ static inline int xfrm_replay_verify_len(struct xfrm_replay_state_esn *replay_es struct nlattr *rp) { struct xfrm_replay_state_esn *up; + int ulen; if (!replay_esn || !rp) return 0; up = nla_data(rp); + ulen = xfrm_replay_state_esn_len(up); - if (xfrm_replay_state_esn_len(replay_esn) != - xfrm_replay_state_esn_len(up)) + if (nla_len(rp) < ulen || xfrm_replay_state_esn_len(replay_esn) != ulen) return -EINVAL; return 0; @@ -388,22 +401,28 @@ static int xfrm_alloc_replay_state_esn(struct xfrm_replay_state_esn **replay_esn struct nlattr *rta) { struct xfrm_replay_state_esn *p, *pp, *up; + int klen, ulen; if (!rta) return 0; up = nla_data(rta); + klen = xfrm_replay_state_esn_len(up); + ulen = nla_len(rta) >= klen ? klen : sizeof(*up); - p = kmemdup(up, xfrm_replay_state_esn_len(up), GFP_KERNEL); + p = kzalloc(klen, GFP_KERNEL); if (!p) return -ENOMEM; - pp = kmemdup(up, xfrm_replay_state_esn_len(up), GFP_KERNEL); + pp = kzalloc(klen, GFP_KERNEL); if (!pp) { kfree(p); return -ENOMEM; } + memcpy(p, up, ulen); + memcpy(pp, up, ulen); + *replay_esn = p; *preplay_esn = pp; @@ -442,10 +461,11 @@ static void copy_from_user_state(struct xfrm_state *x, struct xfrm_usersa_info * * somehow made shareable and move it to xfrm_state.c - JHS * */ -static void xfrm_update_ae_params(struct xfrm_state *x, struct nlattr **attrs) +static void xfrm_update_ae_params(struct xfrm_state *x, struct nlattr **attrs, + int update_esn) { struct nlattr *rp = attrs[XFRMA_REPLAY_VAL]; - struct nlattr *re = attrs[XFRMA_REPLAY_ESN_VAL]; + struct nlattr *re = update_esn ? attrs[XFRMA_REPLAY_ESN_VAL] : NULL; struct nlattr *lt = attrs[XFRMA_LTIME_VAL]; struct nlattr *et = attrs[XFRMA_ETIMER_THRESH]; struct nlattr *rt = attrs[XFRMA_REPLAY_THRESH]; @@ -555,7 +575,7 @@ static struct xfrm_state *xfrm_state_construct(struct net *net, goto error; /* override default values from above */ - xfrm_update_ae_params(x, attrs); + xfrm_update_ae_params(x, attrs, 0); return x; @@ -689,6 +709,7 @@ static int xfrm_del_sa(struct sk_buff *skb, struct nlmsghdr *nlh, static void copy_to_user_state(struct xfrm_state *x, struct xfrm_usersa_info *p) { + memset(p, 0, sizeof(*p)); memcpy(&p->id, &x->id, sizeof(p->id)); memcpy(&p->sel, &x->sel, sizeof(p->sel)); memcpy(&p->lft, &x->lft, sizeof(p->lft)); @@ -742,7 +763,7 @@ static int copy_to_user_auth(struct xfrm_algo_auth *auth, struct sk_buff *skb) return -EMSGSIZE; algo = nla_data(nla); - strcpy(algo->alg_name, auth->alg_name); + strncpy(algo->alg_name, auth->alg_name, sizeof(algo->alg_name)); memcpy(algo->alg_key, auth->alg_key, (auth->alg_key_len + 7) / 8); algo->alg_key_len = auth->alg_key_len; @@ -862,6 +883,7 @@ static struct sk_buff *xfrm_state_netlink(struct sk_buff *in_skb, { struct xfrm_dump_info info; struct sk_buff *skb; + int err; skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); if (!skb) @@ -872,9 +894,10 @@ static struct sk_buff *xfrm_state_netlink(struct sk_buff *in_skb, info.nlmsg_seq = seq; info.nlmsg_flags = 0; - if (dump_one_state(x, 0, &info)) { + err = dump_one_state(x, 0, &info); + if (err) { kfree_skb(skb); - return NULL; + return ERR_PTR(err); } return skb; @@ -1297,6 +1320,7 @@ static void copy_from_user_policy(struct xfrm_policy *xp, struct xfrm_userpolicy static void copy_to_user_policy(struct xfrm_policy *xp, struct xfrm_userpolicy_info *p, int dir) { + memset(p, 0, sizeof(*p)); memcpy(&p->sel, &xp->selector, sizeof(p->sel)); memcpy(&p->lft, &xp->lft, sizeof(p->lft)); memcpy(&p->curlft, &xp->curlft, sizeof(p->curlft)); @@ -1401,6 +1425,7 @@ static int copy_to_user_tmpl(struct xfrm_policy *xp, struct sk_buff *skb) struct xfrm_user_tmpl *up = &vec[i]; struct xfrm_tmpl *kp = &xp->xfrm_vec[i]; + memset(up, 0, sizeof(*up)); memcpy(&up->id, &kp->id, sizeof(up->id)); up->family = kp->encap_family; memcpy(&up->saddr, &kp->saddr, sizeof(up->saddr)); @@ -1529,6 +1554,7 @@ static struct sk_buff *xfrm_policy_netlink(struct sk_buff *in_skb, { struct xfrm_dump_info info; struct sk_buff *skb; + int err; skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); if (!skb) @@ -1539,9 +1565,10 @@ static struct sk_buff *xfrm_policy_netlink(struct sk_buff *in_skb, info.nlmsg_seq = seq; info.nlmsg_flags = 0; - if (dump_one_policy(xp, dir, 0, &info) < 0) { + err = dump_one_policy(xp, dir, 0, &info); + if (err) { kfree_skb(skb); - return NULL; + return ERR_PTR(err); } return skb; @@ -1794,7 +1821,7 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh, goto out; spin_lock_bh(&x->lock); - xfrm_update_ae_params(x, attrs); + xfrm_update_ae_params(x, attrs, 1); spin_unlock_bh(&x->lock); c.event = nlh->nlmsg_type; diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include index 6a3ee981931..978416dd31c 100644 --- a/scripts/Kbuild.include +++ b/scripts/Kbuild.include @@ -98,24 +98,24 @@ try-run = $(shell set -e; \ # Usage: cflags-y += $(call as-option,-Wa$(comma)-isa=foo,) as-option = $(call try-run,\ - $(CC) $(KBUILD_CFLAGS) $(1) -c -xassembler /dev/null -o "$$TMP",$(1),$(2)) + $(CC) $(KBUILD_CFLAGS) $(1) -c -x assembler /dev/null -o "$$TMP",$(1),$(2)) # as-instr # Usage: cflags-y += $(call as-instr,instr,option1,option2) as-instr = $(call try-run,\ - printf "%b\n" "$(1)" | $(CC) $(KBUILD_AFLAGS) -c -xassembler -o "$$TMP" -,$(2),$(3)) + printf "%b\n" "$(1)" | $(CC) $(KBUILD_AFLAGS) -c -x assembler -o "$$TMP" -,$(2),$(3)) # cc-option # Usage: cflags-y += $(call cc-option,-march=winchip-c6,-march=i586) cc-option = $(call try-run,\ - $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -xc /dev/null -o "$$TMP",$(1),$(2)) + $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -x c /dev/null -o "$$TMP",$(1),$(2)) # cc-option-yn # Usage: flag := $(call cc-option-yn,-march=winchip-c6) cc-option-yn = $(call try-run,\ - $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -xc /dev/null -o "$$TMP",y,n) + $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(1) -c -x c /dev/null -o "$$TMP",y,n) # cc-option-align # Prefix align with either -falign or -malign @@ -125,7 +125,7 @@ cc-option-align = $(subst -functions=0,,\ # cc-disable-warning # Usage: cflags-y += $(call cc-disable-warning,unused-but-set-variable) cc-disable-warning = $(call try-run,\ - $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) -W$(strip $(1)) -c -xc /dev/null -o "$$TMP",-Wno-$(strip $(1))) + $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) -W$(strip $(1)) -c -x c /dev/null -o "$$TMP",-Wno-$(strip $(1))) # cc-version # Usage gcc-ver := $(call cc-version) @@ -143,7 +143,7 @@ cc-ifversion = $(shell [ $(call cc-version, $(CC)) $(1) $(2) ] && echo $(3)) # cc-ldoption # Usage: ldflags += $(call cc-ldoption, -Wl$(comma)--hash-style=both) cc-ldoption = $(call try-run,\ - $(CC) $(1) -nostdlib -xc /dev/null -o "$$TMP",$(1),$(2)) + $(CC) $(1) -nostdlib -x c /dev/null -o "$$TMP",$(1),$(2)) # ld-option # Usage: LDFLAGS += $(call ld-option, -X) @@ -209,7 +209,7 @@ endif # >$< substitution to preserve $ when reloading .cmd file # note: when using inline perl scripts [perl -e '...$$t=1;...'] # in $(cmd_xxx) double $$ your perl vars -make-cmd = $(subst \#,\\\#,$(subst $$,$$$$,$(call escsq,$(cmd_$(1))))) +make-cmd = $(subst \\,\\\\,$(subst \#,\\\#,$(subst $$,$$$$,$(call escsq,$(cmd_$(1)))))) # Find any prerequisites that is newer than target or that does not exist. # PHONY targets skipped in both cases. diff --git a/scripts/gcc-version.sh b/scripts/gcc-version.sh index debecb5561c..7f2126df91f 100644 --- a/scripts/gcc-version.sh +++ b/scripts/gcc-version.sh @@ -22,10 +22,10 @@ if [ ${#compiler} -eq 0 ]; then exit 1 fi -MAJOR=$(echo __GNUC__ | $compiler -E -xc - | tail -n 1) -MINOR=$(echo __GNUC_MINOR__ | $compiler -E -xc - | tail -n 1) +MAJOR=$(echo __GNUC__ | $compiler -E -x c - | tail -n 1) +MINOR=$(echo __GNUC_MINOR__ | $compiler -E -x c - | tail -n 1) if [ "x$with_patchlevel" != "x" ] ; then - PATCHLEVEL=$(echo __GNUC_PATCHLEVEL__ | $compiler -E -xc - | tail -n 1) + PATCHLEVEL=$(echo __GNUC_PATCHLEVEL__ | $compiler -E -x c - | tail -n 1) printf "%02d%02d%02d\\n" $MAJOR $MINOR $PATCHLEVEL else printf "%02d%02d\\n" $MAJOR $MINOR diff --git a/scripts/gcc-x86_32-has-stack-protector.sh b/scripts/gcc-x86_32-has-stack-protector.sh index 29493dc4528..12dbd0b11ea 100644 --- a/scripts/gcc-x86_32-has-stack-protector.sh +++ b/scripts/gcc-x86_32-has-stack-protector.sh @@ -1,6 +1,6 @@ #!/bin/sh -echo "int foo(void) { char X[200]; return 3; }" | $* -S -xc -c -O0 -fstack-protector - -o - 2> /dev/null | grep -q "%gs" +echo "int foo(void) { char X[200]; return 3; }" | $* -S -x c -c -O0 -fstack-protector - -o - 2> /dev/null | grep -q "%gs" if [ "$?" -eq "0" ] ; then echo y else diff --git a/scripts/gcc-x86_64-has-stack-protector.sh b/scripts/gcc-x86_64-has-stack-protector.sh index afaec618b39..973e8c14156 100644 --- a/scripts/gcc-x86_64-has-stack-protector.sh +++ b/scripts/gcc-x86_64-has-stack-protector.sh @@ -1,6 +1,6 @@ #!/bin/sh -echo "int foo(void) { char X[200]; return 3; }" | $* -S -xc -c -O0 -mcmodel=kernel -fstack-protector - -o - 2> /dev/null | grep -q "%gs" +echo "int foo(void) { char X[200]; return 3; }" | $* -S -x c -c -O0 -mcmodel=kernel -fstack-protector - -o - 2> /dev/null | grep -q "%gs" if [ "$?" -eq "0" ] ; then echo y else diff --git a/scripts/kconfig/check.sh b/scripts/kconfig/check.sh index fa59cbf9d62..854d9c7c675 100755 --- a/scripts/kconfig/check.sh +++ b/scripts/kconfig/check.sh @@ -1,6 +1,6 @@ #!/bin/sh # Needed for systems without gettext -$* -xc -o /dev/null - > /dev/null 2>&1 << EOF +$* -x c -o /dev/null - > /dev/null 2>&1 << EOF #include int main() { diff --git a/scripts/kconfig/lxdialog/check-lxdialog.sh b/scripts/kconfig/lxdialog/check-lxdialog.sh index 82cc3a85e7f..50df490fe1d 100644 --- a/scripts/kconfig/lxdialog/check-lxdialog.sh +++ b/scripts/kconfig/lxdialog/check-lxdialog.sh @@ -38,7 +38,7 @@ trap "rm -f $tmp" 0 1 2 3 15 # Check if we can link to ncurses check() { - $cc -xc - -o $tmp 2>/dev/null <<'EOF' + $cc -x c - -o $tmp 2>/dev/null <<'EOF' #include CURSES_LOC main() {} EOF diff --git a/scripts/kconfig/streamline_config.pl b/scripts/kconfig/streamline_config.pl index bccf07ddd0b..3346f4236eb 100644 --- a/scripts/kconfig/streamline_config.pl +++ b/scripts/kconfig/streamline_config.pl @@ -463,6 +463,8 @@ sub parse_config_dep_select if (defined($configs{$1})) { if ($localyesconfig) { $setconfigs{$1} = 'y'; + print "$1=y\n"; + next; } else { $setconfigs{$1} = $2; } diff --git a/scripts/package/buildtar b/scripts/package/buildtar index 8a7b15598ea..d0d748e7291 100644 --- a/scripts/package/buildtar +++ b/scripts/package/buildtar @@ -109,7 +109,7 @@ esac if tar --owner=root --group=root --help >/dev/null 2>&1; then opts="--owner=root --group=root" fi - tar cf - . $opts | ${compress} > "${tarball}${file_ext}" + tar cf - boot/* lib/* $opts | ${compress} > "${tarball}${file_ext}" ) echo "Tarball successfully created in ${tarball}${file_ext}" diff --git a/security/integrity/evm/evm_crypto.c b/security/integrity/evm/evm_crypto.c index 49a464f5595..62fa2c57498 100644 --- a/security/integrity/evm/evm_crypto.c +++ b/security/integrity/evm/evm_crypto.c @@ -205,9 +205,9 @@ int evm_update_evmxattr(struct dentry *dentry, const char *xattr_name, rc = __vfs_setxattr_noperm(dentry, XATTR_NAME_EVM, &xattr_data, sizeof(xattr_data), 0); - } - else if (rc == -ENODATA) + } else if (rc == -ENODATA && inode->i_op->removexattr) { rc = inode->i_op->removexattr(dentry, XATTR_NAME_EVM); + } return rc; } diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index b28b7eb3ca4..1ae096ed7dc 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2223,7 +2223,7 @@ static inline void flush_unauthorized_files(const struct cred *cred, int fd; j++; - i = j * __NFDBITS; + i = j * BITS_PER_LONG; fdt = files_fdtable(files); if (i >= fdt->max_fds) break; diff --git a/security/selinux/netnode.c b/security/selinux/netnode.c index 86365857c08..04aa5c8adf7 100644 --- a/security/selinux/netnode.c +++ b/security/selinux/netnode.c @@ -174,7 +174,8 @@ static void sel_netnode_insert(struct sel_netnode *node) if (sel_netnode_hash[idx].size == SEL_NETNODE_HASH_BKT_LIMIT) { struct sel_netnode *tail; tail = list_entry( - rcu_dereference(sel_netnode_hash[idx].list.prev), + rcu_dereference_protected(sel_netnode_hash[idx].list.prev, + lockdep_is_held(&sel_netnode_lock)), struct sel_netnode, list); list_del_rcu(&tail->list); kfree_rcu(tail, rcu); diff --git a/security/yama/yama_lsm.c b/security/yama/yama_lsm.c index 573723843a0..1d6bf24c117 100644 --- a/security/yama/yama_lsm.c +++ b/security/yama/yama_lsm.c @@ -138,7 +138,7 @@ static int yama_task_prctl(int option, unsigned long arg2, unsigned long arg3, if (arg2 == 0) { yama_ptracer_del(NULL, myself); rc = 0; - } else if (arg2 == PR_SET_PTRACER_ANY) { + } else if (arg2 == PR_SET_PTRACER_ANY || (int)arg2 == -1) { rc = yama_ptracer_add(NULL, myself); } else { struct task_struct *tracer; diff --git a/sound/arm/pxa2xx-ac97-lib.c b/sound/arm/pxa2xx-ac97-lib.c index 48d7c0aa507..bd3ba8812e1 100644 --- a/sound/arm/pxa2xx-ac97-lib.c +++ b/sound/arm/pxa2xx-ac97-lib.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -148,6 +149,8 @@ static inline void pxa_ac97_warm_pxa27x(void) static inline void pxa_ac97_cold_pxa27x(void) { + unsigned int timeout; + GCR &= GCR_COLD_RST; /* clear everything but nCRST */ GCR &= ~GCR_COLD_RST; /* then assert nCRST */ @@ -157,8 +160,10 @@ static inline void pxa_ac97_cold_pxa27x(void) clk_enable(ac97conf_clk); udelay(5); clk_disable(ac97conf_clk); - GCR = GCR_COLD_RST; - udelay(50); + GCR = GCR_COLD_RST | GCR_WARM_RST; + timeout = 100; /* wait for the codec-ready bit to be set */ + while (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)) && timeout--) + mdelay(1); } #endif @@ -340,8 +345,21 @@ int __devinit pxa2xx_ac97_hw_probe(struct platform_device *dev) } if (cpu_is_pxa27x()) { - /* Use GPIO 113 as AC97 Reset on Bulverde */ + /* + * This gpio is needed for a work-around to a bug in the ac97 + * controller during warm reset. The direction and level is set + * here so that it is an output driven high when switching from + * AC97_nRESET alt function to generic gpio. + */ + ret = gpio_request_one(reset_gpio, GPIOF_OUT_INIT_HIGH, + "pxa27x ac97 reset"); + if (ret < 0) { + pr_err("%s: gpio_request_one() failed: %d\n", + __func__, ret); + goto err_conf; + } pxa27x_assert_ac97reset(reset_gpio, 0); + ac97conf_clk = clk_get(&dev->dev, "AC97CONFCLK"); if (IS_ERR(ac97conf_clk)) { ret = PTR_ERR(ac97conf_clk); @@ -384,6 +402,8 @@ EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_probe); void pxa2xx_ac97_hw_remove(struct platform_device *dev) { + if (cpu_is_pxa27x()) + gpio_free(reset_gpio); GCR |= GCR_ACLINK_OFF; free_irq(IRQ_AC97, NULL); if (ac97conf_clk) { diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c index a90d4d3d90f..e7e4b8dea7f 100644 --- a/sound/core/compress_offload.c +++ b/sound/core/compress_offload.c @@ -100,12 +100,15 @@ static int snd_compr_open(struct inode *inode, struct file *f) if (dirn != compr->direction) { pr_err("this device doesn't support this direction\n"); + snd_card_unref(compr->card); return -EINVAL; } data = kzalloc(sizeof(*data), GFP_KERNEL); - if (!data) + if (!data) { + snd_card_unref(compr->card); return -ENOMEM; + } data->stream.ops = compr->ops; data->stream.direction = dirn; data->stream.private_data = compr->private_data; @@ -113,6 +116,7 @@ static int snd_compr_open(struct inode *inode, struct file *f) runtime = kzalloc(sizeof(*runtime), GFP_KERNEL); if (!runtime) { kfree(data); + snd_card_unref(compr->card); return -ENOMEM; } runtime->state = SNDRV_PCM_STATE_OPEN; @@ -126,7 +130,8 @@ static int snd_compr_open(struct inode *inode, struct file *f) kfree(runtime); kfree(data); } - return ret; + snd_card_unref(compr->card); + return 0; } static int snd_compr_free(struct inode *inode, struct file *f) diff --git a/sound/core/control.c b/sound/core/control.c index 2487a6bb1c5..daa4fc8872f 100644 --- a/sound/core/control.c +++ b/sound/core/control.c @@ -86,6 +86,7 @@ static int snd_ctl_open(struct inode *inode, struct file *file) write_lock_irqsave(&card->ctl_files_rwlock, flags); list_add_tail(&ctl->list, &card->ctl_files); write_unlock_irqrestore(&card->ctl_files_rwlock, flags); + snd_card_unref(card); return 0; __error: @@ -93,6 +94,8 @@ static int snd_ctl_open(struct inode *inode, struct file *file) __error2: snd_card_file_remove(card, file); __error1: + if (card) + snd_card_unref(card); return err; } @@ -1433,6 +1436,8 @@ static ssize_t snd_ctl_read(struct file *file, char __user *buffer, spin_unlock_irq(&ctl->read_lock); schedule(); remove_wait_queue(&ctl->change_sleep, &wait); + if (ctl->card->shutdown) + return -ENODEV; if (signal_pending(current)) return -ERESTARTSYS; spin_lock_irq(&ctl->read_lock); diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c index 75ea16f35b1..3f7f6628cf7 100644 --- a/sound/core/hwdep.c +++ b/sound/core/hwdep.c @@ -100,8 +100,10 @@ static int snd_hwdep_open(struct inode *inode, struct file * file) if (hw == NULL) return -ENODEV; - if (!try_module_get(hw->card->module)) + if (!try_module_get(hw->card->module)) { + snd_card_unref(hw->card); return -EFAULT; + } init_waitqueue_entry(&wait, current); add_wait_queue(&hw->open_wait, &wait); @@ -129,6 +131,10 @@ static int snd_hwdep_open(struct inode *inode, struct file * file) mutex_unlock(&hw->open_mutex); schedule(); mutex_lock(&hw->open_mutex); + if (hw->card->shutdown) { + err = -ENODEV; + break; + } if (signal_pending(current)) { err = -ERESTARTSYS; break; @@ -148,6 +154,7 @@ static int snd_hwdep_open(struct inode *inode, struct file * file) mutex_unlock(&hw->open_mutex); if (err < 0) module_put(hw->card->module); + snd_card_unref(hw->card); return err; } @@ -459,12 +466,15 @@ static int snd_hwdep_dev_disconnect(struct snd_device *device) mutex_unlock(®ister_mutex); return -EINVAL; } + mutex_lock(&hwdep->open_mutex); + wake_up(&hwdep->open_wait); #ifdef CONFIG_SND_OSSEMUL if (hwdep->ossreg) snd_unregister_oss_device(hwdep->oss_type, hwdep->card, hwdep->device); #endif snd_unregister_device(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card, hwdep->device); list_del_init(&hwdep->list); + mutex_unlock(&hwdep->open_mutex); mutex_unlock(®ister_mutex); return 0; } diff --git a/sound/core/init.c b/sound/core/init.c index f300bd33d5e..60554ef84cc 100644 --- a/sound/core/init.c +++ b/sound/core/init.c @@ -212,6 +212,7 @@ int snd_card_create(int idx, const char *xid, spin_lock_init(&card->files_lock); INIT_LIST_HEAD(&card->files_list); init_waitqueue_head(&card->shutdown_sleep); + atomic_set(&card->refcount, 0); #ifdef CONFIG_PM mutex_init(&card->power_lock); init_waitqueue_head(&card->power_sleep); @@ -445,21 +446,36 @@ static int snd_card_do_free(struct snd_card *card) return 0; } +/** + * snd_card_unref - release the reference counter + * @card: the card instance + * + * Decrements the reference counter. When it reaches to zero, wake up + * the sleeper and call the destructor if needed. + */ +void snd_card_unref(struct snd_card *card) +{ + if (atomic_dec_and_test(&card->refcount)) { + wake_up(&card->shutdown_sleep); + if (card->free_on_last_close) + snd_card_do_free(card); + } +} +EXPORT_SYMBOL(snd_card_unref); + int snd_card_free_when_closed(struct snd_card *card) { - int free_now = 0; - int ret = snd_card_disconnect(card); - if (ret) - return ret; + int ret; - spin_lock(&card->files_lock); - if (list_empty(&card->files_list)) - free_now = 1; - else - card->free_on_last_close = 1; - spin_unlock(&card->files_lock); + atomic_inc(&card->refcount); + ret = snd_card_disconnect(card); + if (ret) { + atomic_dec(&card->refcount); + return ret; + } - if (free_now) + card->free_on_last_close = 1; + if (atomic_dec_and_test(&card->refcount)) snd_card_do_free(card); return 0; } @@ -473,7 +489,7 @@ int snd_card_free(struct snd_card *card) return ret; /* wait, until all devices are ready for the free operation */ - wait_event(card->shutdown_sleep, list_empty(&card->files_list)); + wait_event(card->shutdown_sleep, !atomic_read(&card->refcount)); snd_card_do_free(card); return 0; } @@ -854,6 +870,7 @@ int snd_card_file_add(struct snd_card *card, struct file *file) return -ENODEV; } list_add(&mfile->list, &card->files_list); + atomic_inc(&card->refcount); spin_unlock(&card->files_lock); return 0; } @@ -876,7 +893,6 @@ EXPORT_SYMBOL(snd_card_file_add); int snd_card_file_remove(struct snd_card *card, struct file *file) { struct snd_monitor_file *mfile, *found = NULL; - int last_close = 0; spin_lock(&card->files_lock); list_for_each_entry(mfile, &card->files_list, list) { @@ -891,19 +907,13 @@ int snd_card_file_remove(struct snd_card *card, struct file *file) break; } } - if (list_empty(&card->files_list)) - last_close = 1; spin_unlock(&card->files_lock); - if (last_close) { - wake_up(&card->shutdown_sleep); - if (card->free_on_last_close) - snd_card_do_free(card); - } if (!found) { snd_printk(KERN_ERR "ALSA card file remove problem (%p)\n", file); return -ENOENT; } kfree(found); + snd_card_unref(card); return 0; } diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c index 18297f7f2c5..c353768854e 100644 --- a/sound/core/oss/mixer_oss.c +++ b/sound/core/oss/mixer_oss.c @@ -52,14 +52,19 @@ static int snd_mixer_oss_open(struct inode *inode, struct file *file) SNDRV_OSS_DEVICE_TYPE_MIXER); if (card == NULL) return -ENODEV; - if (card->mixer_oss == NULL) + if (card->mixer_oss == NULL) { + snd_card_unref(card); return -ENODEV; + } err = snd_card_file_add(card, file); - if (err < 0) + if (err < 0) { + snd_card_unref(card); return err; + } fmixer = kzalloc(sizeof(*fmixer), GFP_KERNEL); if (fmixer == NULL) { snd_card_file_remove(card, file); + snd_card_unref(card); return -ENOMEM; } fmixer->card = card; @@ -68,8 +73,10 @@ static int snd_mixer_oss_open(struct inode *inode, struct file *file) if (!try_module_get(card->module)) { kfree(fmixer); snd_card_file_remove(card, file); + snd_card_unref(card); return -EFAULT; } + snd_card_unref(card); return 0; } diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index 08fde0060fd..4c1cc51772e 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -2441,6 +2441,10 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file) mutex_unlock(&pcm->open_mutex); schedule(); mutex_lock(&pcm->open_mutex); + if (pcm->card->shutdown) { + err = -ENODEV; + break; + } if (signal_pending(current)) { err = -ERESTARTSYS; break; @@ -2450,6 +2454,7 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file) mutex_unlock(&pcm->open_mutex); if (err < 0) goto __error; + snd_card_unref(pcm->card); return err; __error: @@ -2457,6 +2462,8 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file) __error2: snd_card_file_remove(pcm->card, file); __error1: + if (pcm) + snd_card_unref(pcm->card); return err; } diff --git a/sound/core/pcm.c b/sound/core/pcm.c index 09bf06e7cee..bdf30cf3775 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -1176,11 +1176,19 @@ static int snd_pcm_dev_disconnect(struct snd_device *device) if (list_empty(&pcm->list)) goto unlock; + mutex_lock(&pcm->open_mutex); + wake_up(&pcm->open_wait); list_del_init(&pcm->list); for (cidx = 0; cidx < 2; cidx++) - for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) - if (substream->runtime) + for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) { + snd_pcm_stream_lock_irq(substream); + if (substream->runtime) { substream->runtime->status->state = SNDRV_PCM_STATE_DISCONNECTED; + wake_up(&substream->runtime->sleep); + wake_up(&substream->runtime->tsleep); + } + snd_pcm_stream_unlock_irq(substream); + } list_for_each_entry(notify, &snd_pcm_notify_list, list) { notify->n_disconnect(pcm); } @@ -1196,6 +1204,7 @@ static int snd_pcm_dev_disconnect(struct snd_device *device) } snd_unregister_device(devtype, pcm->card, pcm->device); } + mutex_unlock(&pcm->open_mutex); unlock: mutex_unlock(®ister_mutex); return 0; diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 463624733d6..f178b786da8 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -369,6 +369,14 @@ static int period_to_usecs(struct snd_pcm_runtime *runtime) return usecs; } +static void snd_pcm_set_state(struct snd_pcm_substream *substream, int state) +{ + snd_pcm_stream_lock_irq(substream); + if (substream->runtime->status->state != SNDRV_PCM_STATE_DISCONNECTED) + substream->runtime->status->state = state; + snd_pcm_stream_unlock_irq(substream); +} + static int snd_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { @@ -452,7 +460,7 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream, runtime->boundary *= 2; snd_pcm_timer_resolution_change(substream); - runtime->status->state = SNDRV_PCM_STATE_SETUP; + snd_pcm_set_state(substream, SNDRV_PCM_STATE_SETUP); if (pm_qos_request_active(&substream->latency_pm_qos_req)) pm_qos_remove_request(&substream->latency_pm_qos_req); @@ -464,7 +472,7 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream, /* hardware might be unusable from this time, so we force application to retry to set the correct hardware parameter settings */ - runtime->status->state = SNDRV_PCM_STATE_OPEN; + snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN); if (substream->ops->hw_free != NULL) substream->ops->hw_free(substream); return err; @@ -512,7 +520,7 @@ static int snd_pcm_hw_free(struct snd_pcm_substream *substream) return -EBADFD; if (substream->ops->hw_free) result = substream->ops->hw_free(substream); - runtime->status->state = SNDRV_PCM_STATE_OPEN; + snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN); pm_qos_remove_request(&substream->latency_pm_qos_req); return result; } @@ -1321,7 +1329,7 @@ static void snd_pcm_post_prepare(struct snd_pcm_substream *substream, int state) { struct snd_pcm_runtime *runtime = substream->runtime; runtime->control->appl_ptr = runtime->status->hw_ptr; - runtime->status->state = SNDRV_PCM_STATE_PREPARED; + snd_pcm_set_state(substream, SNDRV_PCM_STATE_PREPARED); } static struct action_ops snd_pcm_action_prepare = { @@ -1501,6 +1509,10 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream, down_read(&snd_pcm_link_rwsem); snd_pcm_stream_lock_irq(substream); remove_wait_queue(&to_check->sleep, &wait); + if (card->shutdown) { + result = -ENODEV; + break; + } if (tout == 0) { if (substream->runtime->status->state == SNDRV_PCM_STATE_SUSPENDED) result = -ESTRPIPE; @@ -1637,6 +1649,7 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd) write_unlock_irq(&snd_pcm_link_rwlock); up_write(&snd_pcm_link_rwsem); _nolock: + snd_card_unref(substream1->pcm->card); fput(file); if (res < 0) kfree(group); @@ -2117,7 +2130,10 @@ static int snd_pcm_playback_open(struct inode *inode, struct file *file) return err; pcm = snd_lookup_minor_data(iminor(inode), SNDRV_DEVICE_TYPE_PCM_PLAYBACK); - return snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_PLAYBACK); + err = snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_PLAYBACK); + if (pcm) + snd_card_unref(pcm->card); + return err; } static int snd_pcm_capture_open(struct inode *inode, struct file *file) @@ -2128,7 +2144,10 @@ static int snd_pcm_capture_open(struct inode *inode, struct file *file) return err; pcm = snd_lookup_minor_data(iminor(inode), SNDRV_DEVICE_TYPE_PCM_CAPTURE); - return snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_CAPTURE); + err = snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_CAPTURE); + if (pcm) + snd_card_unref(pcm->card); + return err; } static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream) @@ -2165,6 +2184,10 @@ static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream) mutex_unlock(&pcm->open_mutex); schedule(); mutex_lock(&pcm->open_mutex); + if (pcm->card->shutdown) { + err = -ENODEV; + break; + } if (signal_pending(current)) { err = -ERESTARTSYS; break; diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index ebf6e49ad3d..1bb95aeea08 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -379,8 +379,10 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) if (rmidi == NULL) return -ENODEV; - if (!try_module_get(rmidi->card->module)) + if (!try_module_get(rmidi->card->module)) { + snd_card_unref(rmidi->card); return -ENXIO; + } mutex_lock(&rmidi->open_mutex); card = rmidi->card; @@ -422,6 +424,10 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) mutex_unlock(&rmidi->open_mutex); schedule(); mutex_lock(&rmidi->open_mutex); + if (rmidi->card->shutdown) { + err = -ENODEV; + break; + } if (signal_pending(current)) { err = -ERESTARTSYS; break; @@ -440,6 +446,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) #endif file->private_data = rawmidi_file; mutex_unlock(&rmidi->open_mutex); + snd_card_unref(rmidi->card); return 0; __error: @@ -447,6 +454,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file) __error_card: mutex_unlock(&rmidi->open_mutex); module_put(rmidi->card->module); + snd_card_unref(rmidi->card); return err; } @@ -991,6 +999,8 @@ static ssize_t snd_rawmidi_read(struct file *file, char __user *buf, size_t coun spin_unlock_irq(&runtime->lock); schedule(); remove_wait_queue(&runtime->sleep, &wait); + if (rfile->rmidi->card->shutdown) + return -ENODEV; if (signal_pending(current)) return result > 0 ? result : -ERESTARTSYS; if (!runtime->avail) @@ -1234,6 +1244,8 @@ static ssize_t snd_rawmidi_write(struct file *file, const char __user *buf, spin_unlock_irq(&runtime->lock); timeout = schedule_timeout(30 * HZ); remove_wait_queue(&runtime->sleep, &wait); + if (rfile->rmidi->card->shutdown) + return -ENODEV; if (signal_pending(current)) return result > 0 ? result : -ERESTARTSYS; if (!runtime->avail && !timeout) @@ -1609,9 +1621,20 @@ static int snd_rawmidi_dev_register(struct snd_device *device) static int snd_rawmidi_dev_disconnect(struct snd_device *device) { struct snd_rawmidi *rmidi = device->device_data; + int dir; mutex_lock(®ister_mutex); + mutex_lock(&rmidi->open_mutex); + wake_up(&rmidi->open_wait); list_del_init(&rmidi->list); + for (dir = 0; dir < 2; dir++) { + struct snd_rawmidi_substream *s; + list_for_each_entry(s, &rmidi->streams[dir].substreams, list) { + if (s->runtime) + wake_up(&s->runtime->sleep); + } + } + #ifdef CONFIG_SND_OSSEMUL if (rmidi->ossreg) { if ((int)rmidi->device == midi_map[rmidi->card->number]) { @@ -1626,6 +1649,7 @@ static int snd_rawmidi_dev_disconnect(struct snd_device *device) } #endif /* CONFIG_SND_OSSEMUL */ snd_unregister_device(SNDRV_DEVICE_TYPE_RAWMIDI, rmidi->card, rmidi->device); + mutex_unlock(&rmidi->open_mutex); mutex_unlock(®ister_mutex); return 0; } diff --git a/sound/core/sound.c b/sound/core/sound.c index 28f35593a75..3700d96fb3f 100644 --- a/sound/core/sound.c +++ b/sound/core/sound.c @@ -99,6 +99,10 @@ static void snd_request_other(int minor) * * Checks that a minor device with the specified type is registered, and returns * its user data pointer. + * + * This function increments the reference counter of the card instance + * if an associated instance with the given minor number and type is found. + * The caller must call snd_card_unref() appropriately later. */ void *snd_lookup_minor_data(unsigned int minor, int type) { @@ -109,9 +113,11 @@ void *snd_lookup_minor_data(unsigned int minor, int type) return NULL; mutex_lock(&sound_mutex); mreg = snd_minors[minor]; - if (mreg && mreg->type == type) + if (mreg && mreg->type == type) { private_data = mreg->private_data; - else + if (private_data && mreg->card_ptr) + atomic_inc(&mreg->card_ptr->refcount); + } else private_data = NULL; mutex_unlock(&sound_mutex); return private_data; @@ -276,6 +282,7 @@ int snd_register_device_for_dev(int type, struct snd_card *card, int dev, preg->device = dev; preg->f_ops = f_ops; preg->private_data = private_data; + preg->card_ptr = card; mutex_lock(&sound_mutex); #ifdef CONFIG_SND_DYNAMIC_MINORS minor = snd_find_free_minor(type); diff --git a/sound/core/sound_oss.c b/sound/core/sound_oss.c index c7009204306..ec86009141d 100644 --- a/sound/core/sound_oss.c +++ b/sound/core/sound_oss.c @@ -40,6 +40,9 @@ static struct snd_minor *snd_oss_minors[SNDRV_OSS_MINORS]; static DEFINE_MUTEX(sound_oss_mutex); +/* NOTE: This function increments the refcount of the associated card like + * snd_lookup_minor_data(); the caller must call snd_card_unref() appropriately + */ void *snd_lookup_oss_minor_data(unsigned int minor, int type) { struct snd_minor *mreg; @@ -49,9 +52,11 @@ void *snd_lookup_oss_minor_data(unsigned int minor, int type) return NULL; mutex_lock(&sound_oss_mutex); mreg = snd_oss_minors[minor]; - if (mreg && mreg->type == type) + if (mreg && mreg->type == type) { private_data = mreg->private_data; - else + if (private_data && mreg->card_ptr) + atomic_inc(&mreg->card_ptr->refcount); + } else private_data = NULL; mutex_unlock(&sound_oss_mutex); return private_data; @@ -123,6 +128,7 @@ int snd_register_oss_device(int type, struct snd_card *card, int dev, preg->device = dev; preg->f_ops = f_ops; preg->private_data = private_data; + preg->card_ptr = card; mutex_lock(&sound_oss_mutex); snd_oss_minors[minor] = preg; minor_unit = SNDRV_MINOR_OSS_DEVICE(minor); diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c index ad079b63b8b..bdc963e722a 100644 --- a/sound/drivers/aloop.c +++ b/sound/drivers/aloop.c @@ -119,6 +119,7 @@ struct loopback_pcm { unsigned int period_size_frac; unsigned long last_jiffies; struct timer_list timer; + spinlock_t timer_lock; }; static struct platform_device *devices[SNDRV_CARDS]; @@ -169,6 +170,7 @@ static void loopback_timer_start(struct loopback_pcm *dpcm) unsigned long tick; unsigned int rate_shift = get_rate_shift(dpcm); + spin_lock(&dpcm->timer_lock); if (rate_shift != dpcm->pcm_rate_shift) { dpcm->pcm_rate_shift = rate_shift; dpcm->period_size_frac = frac_pos(dpcm, dpcm->pcm_period_size); @@ -181,12 +183,15 @@ static void loopback_timer_start(struct loopback_pcm *dpcm) tick = (tick + dpcm->pcm_bps - 1) / dpcm->pcm_bps; dpcm->timer.expires = jiffies + tick; add_timer(&dpcm->timer); + spin_unlock(&dpcm->timer_lock); } static inline void loopback_timer_stop(struct loopback_pcm *dpcm) { + spin_lock(&dpcm->timer_lock); del_timer(&dpcm->timer); dpcm->timer.expires = 0; + spin_unlock(&dpcm->timer_lock); } #define CABLE_VALID_PLAYBACK (1 << SNDRV_PCM_STREAM_PLAYBACK) @@ -659,6 +664,7 @@ static int loopback_open(struct snd_pcm_substream *substream) dpcm->substream = substream; setup_timer(&dpcm->timer, loopback_timer_function, (unsigned long)dpcm); + spin_lock_init(&dpcm->timer_lock); cable = loopback->cables[substream->number][dev]; if (!cable) { diff --git a/sound/drivers/mpu401/mpu401_uart.c b/sound/drivers/mpu401/mpu401_uart.c index 1cff331a228..4608c2ca43f 100644 --- a/sound/drivers/mpu401/mpu401_uart.c +++ b/sound/drivers/mpu401/mpu401_uart.c @@ -554,6 +554,7 @@ int snd_mpu401_uart_new(struct snd_card *card, int device, spin_lock_init(&mpu->output_lock); spin_lock_init(&mpu->timer_lock); mpu->hardware = hardware; + mpu->irq = -1; if (! (info_flags & MPU401_INFO_INTEGRATED)) { int res_size = hardware == MPU401_HW_PC98II ? 4 : 2; mpu->res = request_region(port, res_size, "MPU401 UART"); diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index 9473fca9681..8b0f9968830 100644 --- a/sound/pci/ac97/ac97_codec.c +++ b/sound/pci/ac97/ac97_codec.c @@ -1271,6 +1271,8 @@ static int snd_ac97_cvol_new(struct snd_card *card, char *name, int reg, unsigne tmp.index = ac97->num; kctl = snd_ctl_new1(&tmp, ac97); } + if (!kctl) + return -ENOMEM; if (reg >= AC97_PHONE && reg <= AC97_PCM) set_tlv_db_scale(kctl, db_scale_5bit_12db_max); else diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c index 754924081d0..a78fdf466fa 100644 --- a/sound/pci/emu10k1/emu10k1_main.c +++ b/sound/pci/emu10k1/emu10k1_main.c @@ -1416,6 +1416,15 @@ static struct snd_emu_chip_details emu_chip_details[] = { .ca0108_chip = 1, .spk71 = 1, .emu_model = EMU_MODEL_EMU1010B}, /* EMU 1010 new revision */ + /* Tested by Maxim Kachur 17th Oct 2012. */ + /* This is MAEM8986, 0202 is MAEM8980 */ + {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x40071102, + .driver = "Audigy2", .name = "E-mu 1010 PCIe [MAEM8986]", + .id = "EMU1010", + .emu10k2_chip = 1, + .ca0108_chip = 1, + .spk71 = 1, + .emu_model = EMU_MODEL_EMU1010B}, /* EMU 1010 PCIe */ /* Tested by James@superbug.co.uk 8th July 2005. */ /* This is MAEM8810, 0202 is MAEM8820 */ {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x40011102, diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 926b455392c..cec747998e5 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -2279,6 +2279,7 @@ int snd_hda_codec_reset(struct hda_codec *codec) } if (codec->patch_ops.free) codec->patch_ops.free(codec); + memset(&codec->patch_ops, 0, sizeof(codec->patch_ops)); snd_hda_jack_tbl_clear(codec); codec->proc_widget_hook = NULL; codec->spec = NULL; @@ -2292,7 +2293,6 @@ int snd_hda_codec_reset(struct hda_codec *codec) codec->num_pcms = 0; codec->pcm_info = NULL; codec->preset = NULL; - memset(&codec->patch_ops, 0, sizeof(codec->patch_ops)); codec->slave_dig_outs = NULL; codec->spdif_status_reset = 0; module_put(codec->owner); diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c index e59e2f059b6..0074aee6d39 100644 --- a/sound/pci/hda/hda_proc.c +++ b/sound/pci/hda/hda_proc.c @@ -412,7 +412,7 @@ static void print_digital_conv(struct snd_info_buffer *buffer, if (digi1 & AC_DIG1_EMPHASIS) snd_iprintf(buffer, " Preemphasis"); if (digi1 & AC_DIG1_COPYRIGHT) - snd_iprintf(buffer, " Copyright"); + snd_iprintf(buffer, " Non-Copyright"); if (digi1 & AC_DIG1_NONAUDIO) snd_iprintf(buffer, " Non-Audio"); if (digi1 & AC_DIG1_PROFESSIONAL) diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 7143393927d..e23ad3f045f 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -544,6 +544,7 @@ static int ad198x_build_pcms(struct hda_codec *codec) if (spec->multiout.dig_out_nid) { info++; codec->num_pcms++; + codec->spdif_status_reset = 1; info->name = "AD198x Digital"; info->pcm_type = HDA_PCM_TYPE_SPDIF; info->stream[SNDRV_PCM_STREAM_PLAYBACK] = ad198x_pcm_digital_playback; diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 21d91d580da..70b4f02da2c 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -276,6 +276,10 @@ static int _add_switch(struct hda_codec *codec, hda_nid_t nid, const char *pfx, int type = dir ? HDA_INPUT : HDA_OUTPUT; struct snd_kcontrol_new knew = HDA_CODEC_MUTE_MONO(namestr, nid, chan, 0, type); + if ((query_amp_caps(codec, nid, type) & AC_AMPCAP_MUTE) == 0) { + snd_printdd("Skipping '%s %s Switch' (no mute on node 0x%x)\n", pfx, dirstr[dir], nid); + return 0; + } sprintf(namestr, "%s %s Switch", pfx, dirstr[dir]); return snd_hda_ctl_add(codec, nid, snd_ctl_new1(&knew, codec)); } @@ -287,6 +291,10 @@ static int _add_volume(struct hda_codec *codec, hda_nid_t nid, const char *pfx, int type = dir ? HDA_INPUT : HDA_OUTPUT; struct snd_kcontrol_new knew = HDA_CODEC_VOLUME_MONO(namestr, nid, chan, 0, type); + if ((query_amp_caps(codec, nid, type) & AC_AMPCAP_NUM_STEPS) == 0) { + snd_printdd("Skipping '%s %s Volume' (no amp on node 0x%x)\n", pfx, dirstr[dir], nid); + return 0; + } sprintf(namestr, "%s %s Volume", pfx, dirstr[dir]); return snd_hda_ctl_add(codec, nid, snd_ctl_new1(&knew, codec)); } diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index c83ccdba1e5..3605fbb6ef1 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c @@ -95,8 +95,8 @@ enum { #define CS420X_VENDOR_NID 0x11 #define CS_DIG_OUT1_PIN_NID 0x10 #define CS_DIG_OUT2_PIN_NID 0x15 -#define CS_DMIC1_PIN_NID 0x12 -#define CS_DMIC2_PIN_NID 0x0e +#define CS_DMIC1_PIN_NID 0x0e +#define CS_DMIC2_PIN_NID 0x12 /* coef indices */ #define IDX_SPDIF_STAT 0x0000 @@ -460,6 +460,7 @@ static int parse_output(struct hda_codec *codec) memcpy(cfg->speaker_pins, cfg->line_out_pins, sizeof(cfg->speaker_pins)); cfg->line_outs = 0; + memset(cfg->line_out_pins, 0, sizeof(cfg->line_out_pins)); } return 0; @@ -1084,14 +1085,18 @@ static void init_input(struct hda_codec *codec) cs_automic(codec); coef = 0x000a; /* ADC1/2 - Digital and Analog Soft Ramp */ + cs_vendor_coef_set(codec, IDX_ADC_CFG, coef); + + coef = cs_vendor_coef_get(codec, IDX_BEEP_CFG); if (is_active_pin(codec, CS_DMIC2_PIN_NID)) - coef |= 0x0500; /* DMIC2 2 chan on, GPIO1 off */ + coef |= 1 << 4; /* DMIC2 2 chan on, GPIO1 off */ if (is_active_pin(codec, CS_DMIC1_PIN_NID)) - coef |= 0x1800; /* DMIC1 2 chan on, GPIO0 off + coef |= 1 << 3; /* DMIC1 2 chan on, GPIO0 off * No effect if SPDIF_OUT2 is * selected in IDX_SPDIF_CTL. */ - cs_vendor_coef_set(codec, IDX_ADC_CFG, coef); + + cs_vendor_coef_set(codec, IDX_BEEP_CFG, coef); } else { if (spec->mic_detect) cs_automic(codec); @@ -1112,7 +1117,7 @@ static const struct hda_verb cs_coef_init_verbs[] = { | 0x0400 /* Disable Coefficient Auto increment */ )}, /* Beep */ - {0x11, AC_VERB_SET_COEF_INDEX, IDX_DAC_CFG}, + {0x11, AC_VERB_SET_COEF_INDEX, IDX_BEEP_CFG}, {0x11, AC_VERB_SET_PROC_COEF, 0x0007}, /* Enable Beep thru DAC1/2/3 */ {} /* terminator */ @@ -1427,7 +1432,7 @@ static int patch_cs420x(struct hda_codec *codec) return 0; error: - kfree(codec->spec); + cs_free(codec); codec->spec = NULL; return err; } @@ -1984,7 +1989,7 @@ static int patch_cs4210(struct hda_codec *codec) return 0; error: - kfree(codec->spec); + cs_free(codec); codec->spec = NULL; return err; } @@ -2009,7 +2014,7 @@ static int patch_cs4213(struct hda_codec *codec) return 0; error: - kfree(codec->spec); + cs_free(codec); codec->spec = NULL; return err; } diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index d906c5b74cf..389702708ea 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -2975,7 +2975,6 @@ static const struct snd_pci_quirk cxt5066_cfg_tbl[] = { SND_PCI_QUIRK(0x1028, 0x02d8, "Dell Vostro", CXT5066_DELL_VOSTRO), SND_PCI_QUIRK(0x1028, 0x02f5, "Dell Vostro 320", CXT5066_IDEAPAD), SND_PCI_QUIRK(0x1028, 0x0401, "Dell Vostro 1014", CXT5066_DELL_VOSTRO), - SND_PCI_QUIRK(0x1028, 0x0402, "Dell Vostro", CXT5066_DELL_VOSTRO), SND_PCI_QUIRK(0x1028, 0x0408, "Dell Inspiron One 19T", CXT5066_IDEAPAD), SND_PCI_QUIRK(0x1028, 0x050f, "Dell Inspiron", CXT5066_IDEAPAD), SND_PCI_QUIRK(0x1028, 0x0510, "Dell Vostro", CXT5066_IDEAPAD), diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 83f345f3c96..d1b805aefa5 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -876,7 +876,6 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, struct hdmi_spec_per_pin *per_pin; struct hdmi_eld *eld; struct hdmi_spec_per_cvt *per_cvt = NULL; - int pinctl; /* Validate hinfo */ pin_idx = hinfo_to_pin_index(spec, hinfo); @@ -912,11 +911,6 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, snd_hda_codec_write(codec, per_pin->pin_nid, 0, AC_VERB_SET_CONNECT_SEL, mux_idx); - pinctl = snd_hda_codec_read(codec, per_pin->pin_nid, 0, - AC_VERB_GET_PIN_WIDGET_CONTROL, 0); - snd_hda_codec_write(codec, per_pin->pin_nid, 0, - AC_VERB_SET_PIN_WIDGET_CONTROL, - pinctl | PIN_OUT); snd_hda_spdif_ctls_assign(codec, pin_idx, per_cvt->cvt_nid); /* Initially set the converter's capabilities */ @@ -1153,11 +1147,17 @@ static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, struct hdmi_spec *spec = codec->spec; int pin_idx = hinfo_to_pin_index(spec, hinfo); hda_nid_t pin_nid = spec->pins[pin_idx].pin_nid; + int pinctl; hdmi_set_channel_count(codec, cvt_nid, substream->runtime->channels); hdmi_setup_audio_infoframe(codec, pin_idx, substream); + pinctl = snd_hda_codec_read(codec, pin_nid, 0, + AC_VERB_GET_PIN_WIDGET_CONTROL, 0); + snd_hda_codec_write(codec, pin_nid, 0, + AC_VERB_SET_PIN_WIDGET_CONTROL, pinctl | PIN_OUT); + return hdmi_setup_stream(codec, cvt_nid, pin_nid, stream_tag, format); } diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index c43264f5981..f7f877626d8 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -188,6 +188,7 @@ struct alc_spec { unsigned int vol_in_capsrc:1; /* use capsrc volume (ADC has no vol) */ unsigned int parse_flags; /* passed to snd_hda_parse_pin_defcfg() */ unsigned int shared_mic_hp:1; /* HP/Mic-in sharing */ + unsigned int no_primary_hp:1; /* Don't prefer HP pins to speaker pins */ /* auto-mute control */ int automute_mode; @@ -601,6 +602,8 @@ static void alc_line_automute(struct hda_codec *codec) { struct alc_spec *spec = codec->spec; + if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT) + return; /* check LO jack only when it's different from HP */ if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0]) return; @@ -2662,8 +2665,10 @@ static const char *alc_get_line_out_pfx(struct alc_spec *spec, int ch, return "PCM"; break; } - if (snd_BUG_ON(ch >= ARRAY_SIZE(channel_name))) + if (ch >= ARRAY_SIZE(channel_name)) { + snd_BUG(); return "PCM"; + } return channel_name[ch]; } @@ -4317,6 +4322,7 @@ static void alc_auto_init_std(struct hda_codec *codec) ((spec)->beep_amp = HDA_COMPOSE_AMP_VAL(nid, 3, idx, dir)) static const struct snd_pci_quirk beep_white_list[] = { + SND_PCI_QUIRK(0x1043, 0x103c, "ASUS", 1), SND_PCI_QUIRK(0x1043, 0x829f, "ASUS", 1), SND_PCI_QUIRK(0x1043, 0x83ce, "EeePC", 1), SND_PCI_QUIRK(0x1043, 0x831a, "EeePC", 1), @@ -4365,7 +4371,8 @@ static int alc_parse_auto_config(struct hda_codec *codec, return 0; /* can't find valid BIOS pin config */ } - if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT && + if (!spec->no_primary_hp && + cfg->line_out_type == AUTO_PIN_SPEAKER_OUT && cfg->line_outs <= cfg->hp_outs) { /* use HP as primary out */ cfg->speaker_outs = cfg->line_outs; @@ -4734,6 +4741,7 @@ static const struct snd_pci_quirk alc880_fixup_tbl[] = { SND_PCI_QUIRK(0x1584, 0x9077, "Uniwill P53", ALC880_FIXUP_VOL_KNOB), SND_PCI_QUIRK(0x161f, 0x203d, "W810", ALC880_FIXUP_W810), SND_PCI_QUIRK(0x161f, 0x205d, "Medion Rim 2150", ALC880_FIXUP_MEDION_RIM), + SND_PCI_QUIRK(0x1631, 0xe011, "PB 13201056", ALC880_FIXUP_6ST), SND_PCI_QUIRK(0x1734, 0x107c, "FSC F1734", ALC880_FIXUP_F1734), SND_PCI_QUIRK(0x1734, 0x1094, "FSC Amilo M1451G", ALC880_FIXUP_FUJITSU), SND_PCI_QUIRK(0x1734, 0x10ac, "FSC AMILO Xi 1526", ALC880_FIXUP_F1734), @@ -5076,6 +5084,7 @@ enum { ALC889_FIXUP_DAC_ROUTE, ALC889_FIXUP_MBP_VREF, ALC889_FIXUP_IMAC91_VREF, + ALC882_FIXUP_NO_PRIMARY_HP, }; static void alc889_fixup_coef(struct hda_codec *codec, @@ -5199,6 +5208,17 @@ static void alc889_fixup_imac91_vref(struct hda_codec *codec, spec->keep_vref_in_automute = 1; } +/* Don't take HP output as primary + * strangely, the speaker output doesn't work on VAIO Z through DAC 0x05 + */ +static void alc882_fixup_no_primary_hp(struct hda_codec *codec, + const struct alc_fixup *fix, int action) +{ + struct alc_spec *spec = codec->spec; + if (action == ALC_FIXUP_ACT_PRE_PROBE) + spec->no_primary_hp = 1; +} + static const struct alc_fixup alc882_fixups[] = { [ALC882_FIXUP_ABIT_AW9D_MAX] = { .type = ALC_FIXUP_PINS, @@ -5381,6 +5401,10 @@ static const struct alc_fixup alc882_fixups[] = { .chained = true, .chain_id = ALC882_FIXUP_GPIO1, }, + [ALC882_FIXUP_NO_PRIMARY_HP] = { + .type = ALC_FIXUP_FUNC, + .v.func = alc882_fixup_no_primary_hp, + }, }; static const struct snd_pci_quirk alc882_fixup_tbl[] = { @@ -5415,6 +5439,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = { SND_PCI_QUIRK(0x1043, 0x1971, "Asus W2JC", ALC882_FIXUP_ASUS_W2JC), SND_PCI_QUIRK(0x1043, 0x835f, "Asus Eee 1601", ALC888_FIXUP_EEE1601), SND_PCI_QUIRK(0x104d, 0x9047, "Sony Vaio TT", ALC889_FIXUP_VAIO_TT), + SND_PCI_QUIRK(0x104d, 0x905a, "Sony Vaio Z", ALC882_FIXUP_NO_PRIMARY_HP), /* All Apple entries are in codec SSIDs */ SND_PCI_QUIRK(0x106b, 0x00a0, "MacBookPro 3,1", ALC889_FIXUP_MBP_VREF), @@ -5435,6 +5460,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = { SND_PCI_QUIRK(0x106b, 0x4000, "MacbookPro 5,1", ALC889_FIXUP_IMAC91_VREF), SND_PCI_QUIRK(0x106b, 0x4100, "Macmini 3,1", ALC889_FIXUP_IMAC91_VREF), SND_PCI_QUIRK(0x106b, 0x4200, "Mac Pro 5,1", ALC885_FIXUP_MACPRO_GPIO), + SND_PCI_QUIRK(0x106b, 0x4300, "iMac 9,1", ALC889_FIXUP_IMAC91_VREF), SND_PCI_QUIRK(0x106b, 0x4600, "MacbookPro 5,2", ALC889_FIXUP_IMAC91_VREF), SND_PCI_QUIRK(0x106b, 0x4900, "iMac 9,1 Aluminum", ALC889_FIXUP_IMAC91_VREF), SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC889_FIXUP_IMAC91_VREF), @@ -5455,6 +5481,7 @@ static const struct alc_model_fixup alc882_fixup_models[] = { {.id = ALC882_FIXUP_ACER_ASPIRE_4930G, .name = "acer-aspire-4930g"}, {.id = ALC882_FIXUP_ACER_ASPIRE_8930G, .name = "acer-aspire-8930g"}, {.id = ALC883_FIXUP_ACER_EAPD, .name = "acer-aspire"}, + {.id = ALC882_FIXUP_NO_PRIMARY_HP, .name = "no-primary-hp"}, {} }; @@ -5858,6 +5885,15 @@ static int alc269_resume(struct hda_codec *codec) } #endif /* CONFIG_PM */ +static void alc269_fixup_pincfg_no_hp_to_lineout(struct hda_codec *codec, + const struct alc_fixup *fix, int action) +{ + struct alc_spec *spec = codec->spec; + + if (action == ALC_FIXUP_ACT_PRE_PROBE) + spec->parse_flags = HDA_PINCFG_NO_HP_FIXUP; +} + static void alc269_fixup_hweq(struct hda_codec *codec, const struct alc_fixup *fix, int action) { @@ -5984,6 +6020,8 @@ enum { ALC269VB_FIXUP_AMIC, ALC269VB_FIXUP_DMIC, ALC269_FIXUP_MIC2_MUTE_LED, + ALC269_FIXUP_LENOVO_DOCK, + ALC269_FIXUP_PINCFG_NO_HP_TO_LINEOUT, }; static const struct alc_fixup alc269_fixups[] = { @@ -6045,6 +6083,8 @@ static const struct alc_fixup alc269_fixups[] = { [ALC269_FIXUP_PCM_44K] = { .type = ALC_FIXUP_FUNC, .v.func = alc269_fixup_pcm_44k, + .chained = true, + .chain_id = ALC269_FIXUP_QUANTA_MUTE }, [ALC269_FIXUP_STEREO_DMIC] = { .type = ALC_FIXUP_FUNC, @@ -6108,6 +6148,20 @@ static const struct alc_fixup alc269_fixups[] = { .type = ALC_FIXUP_FUNC, .v.func = alc269_fixup_mic2_mute, }, + [ALC269_FIXUP_LENOVO_DOCK] = { + .type = ALC_FIXUP_PINS, + .v.pins = (const struct alc_pincfg[]) { + { 0x19, 0x23a11040 }, /* dock mic */ + { 0x1b, 0x2121103f }, /* dock headphone */ + { } + }, + .chained = true, + .chain_id = ALC269_FIXUP_PINCFG_NO_HP_TO_LINEOUT + }, + [ALC269_FIXUP_PINCFG_NO_HP_TO_LINEOUT] = { + .type = ALC_FIXUP_FUNC, + .v.func = alc269_fixup_pincfg_no_hp_to_lineout, + }, }; static const struct snd_pci_quirk alc269_fixup_tbl[] = { @@ -6131,8 +6185,12 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE), SND_PCI_QUIRK(0x17aa, 0x21ca, "Thinkpad L412", ALC269_FIXUP_SKU_IGNORE), SND_PCI_QUIRK(0x17aa, 0x21e9, "Thinkpad Edge 15", ALC269_FIXUP_SKU_IGNORE), - SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_QUANTA_MUTE), - SND_PCI_QUIRK(0x17aa, 0x3bf8, "Lenovo Ideapd", ALC269_FIXUP_PCM_44K), + SND_PCI_QUIRK(0x17aa, 0x21f6, "Thinkpad T530", ALC269_FIXUP_LENOVO_DOCK), + SND_PCI_QUIRK(0x17aa, 0x21fa, "Thinkpad X230", ALC269_FIXUP_LENOVO_DOCK), + SND_PCI_QUIRK(0x17aa, 0x21f3, "Thinkpad T430", ALC269_FIXUP_LENOVO_DOCK), + SND_PCI_QUIRK(0x17aa, 0x21fb, "Thinkpad T430s", ALC269_FIXUP_LENOVO_DOCK), + SND_PCI_QUIRK(0x17aa, 0x2203, "Thinkpad X230 Tablet", ALC269_FIXUP_LENOVO_DOCK), + SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K), SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD), #if 0 @@ -6189,6 +6247,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { static const struct alc_model_fixup alc269_fixup_models[] = { {.id = ALC269_FIXUP_AMIC, .name = "laptop-amic"}, {.id = ALC269_FIXUP_DMIC, .name = "laptop-dmic"}, + {.id = ALC269_FIXUP_LENOVO_DOCK, .name = "lenovo-dock"}, {} }; @@ -6256,6 +6315,12 @@ static int patch_alc269(struct hda_codec *codec) if (err < 0) goto error; + alc_pick_fixup(codec, alc269_fixup_models, + alc269_fixup_tbl, alc269_fixups); + alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE); + + alc_auto_parse_customize_define(codec); + if (codec->vendor_id == 0x10ec0269) { spec->codec_variant = ALC269_TYPE_ALC269VA; switch (alc_get_coef0(codec) & 0x00f0) { @@ -6280,12 +6345,6 @@ static int patch_alc269(struct hda_codec *codec) alc269_fill_coef(codec); } - alc_pick_fixup(codec, alc269_fixup_models, - alc269_fixup_tbl, alc269_fixups); - alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE); - - alc_auto_parse_customize_define(codec); - /* automatic parse from the BIOS config */ err = alc269_parse_auto_config(codec); if (err < 0) @@ -6462,8 +6521,8 @@ static void alc861vd_fixup_dallas(struct hda_codec *codec, const struct alc_fixup *fix, int action) { if (action == ALC_FIXUP_ACT_PRE_PROBE) { - snd_hda_override_pin_caps(codec, 0x18, 0x00001714); - snd_hda_override_pin_caps(codec, 0x19, 0x0000171c); + snd_hda_override_pin_caps(codec, 0x18, 0x00000734); + snd_hda_override_pin_caps(codec, 0x19, 0x0000073c); } } @@ -6977,6 +7036,10 @@ static const struct hda_codec_preset snd_hda_preset_realtek[] = { { .id = 0x10ec0275, .name = "ALC275", .patch = patch_alc269 }, { .id = 0x10ec0276, .name = "ALC276", .patch = patch_alc269 }, { .id = 0x10ec0280, .name = "ALC280", .patch = patch_alc269 }, + { .id = 0x10ec0282, .name = "ALC282", .patch = patch_alc269 }, + { .id = 0x10ec0283, .name = "ALC283", .patch = patch_alc269 }, + { .id = 0x10ec0290, .name = "ALC290", .patch = patch_alc269 }, + { .id = 0x10ec0292, .name = "ALC292", .patch = patch_alc269 }, { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660", .patch = patch_alc861 }, { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd }, @@ -6990,6 +7053,7 @@ static const struct hda_codec_preset snd_hda_preset_realtek[] = { .patch = patch_alc662 }, { .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 }, { .id = 0x10ec0665, .name = "ALC665", .patch = patch_alc662 }, + { .id = 0x10ec0668, .name = "ALC668", .patch = patch_alc662 }, { .id = 0x10ec0670, .name = "ALC670", .patch = patch_alc662 }, { .id = 0x10ec0680, .name = "ALC680", .patch = patch_alc680 }, { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 }, @@ -7007,6 +7071,7 @@ static const struct hda_codec_preset snd_hda_preset_realtek[] = { { .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc882 }, { .id = 0x10ec0892, .name = "ALC892", .patch = patch_alc662 }, { .id = 0x10ec0899, .name = "ALC898", .patch = patch_alc882 }, + { .id = 0x10ec0900, .name = "ALC1150", .patch = patch_alc882 }, {} /* terminator */ }; diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 7494fbc1f26..137b67f8e69 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -100,6 +100,8 @@ enum { STAC_92HD83XXX_HP_cNB11_INTQUAD, STAC_HP_DV7_4000, STAC_HP_ZEPHYR, + STAC_92HD83XXX_HP_LED, + STAC_92HD83XXX_HP_INV_LED, STAC_92HD83XXX_MODELS }; @@ -1070,7 +1072,7 @@ static struct snd_kcontrol_new stac_smux_mixer = { static const char * const slave_pfxs[] = { "Front", "Surround", "Center", "LFE", "Side", - "Headphone", "Speaker", "IEC958", + "Headphone", "Speaker", "IEC958", "PCM", NULL }; @@ -1672,6 +1674,8 @@ static const char * const stac92hd83xxx_models[STAC_92HD83XXX_MODELS] = { [STAC_92HD83XXX_HP_cNB11_INTQUAD] = "hp_cNB11_intquad", [STAC_HP_DV7_4000] = "hp-dv7-4000", [STAC_HP_ZEPHYR] = "hp-zephyr", + [STAC_92HD83XXX_HP_LED] = "hp-led", + [STAC_92HD83XXX_HP_INV_LED] = "hp-inv-led", }; static const struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = { @@ -1691,7 +1695,7 @@ static const struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = { SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1658, "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1659, - "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), + "HP Pavilion dv7", STAC_HP_DV7_4000), SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x165A, "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x165B, @@ -1726,6 +1730,8 @@ static const struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = { "HP", STAC_92HD83XXX_HP_cNB11_INTQUAD), SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3561, "HP", STAC_HP_ZEPHYR), + SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3660, + "HP Mini", STAC_92HD83XXX_HP_LED), {} /* terminator */ }; @@ -4431,7 +4437,13 @@ static int stac92xx_init(struct hda_codec *codec) snd_hda_jack_report_sync(codec); /* sync mute LED */ - snd_hda_sync_vmaster_hook(&spec->vmaster_mute); + if (spec->gpio_led) { + if (spec->vmaster_mute.hook) + snd_hda_sync_vmaster_hook(&spec->vmaster_mute); + else /* the very first init call doesn't have vmaster yet */ + stac92xx_update_led_status(codec, false); + } + if (spec->dac_list) stac92xx_power_down(codec); return 0; @@ -5528,6 +5540,7 @@ static void stac92hd8x_fill_auto_spec(struct hda_codec *codec) static int patch_stac92hd83xxx(struct hda_codec *codec) { struct sigmatel_spec *spec; + int default_polarity = -1; /* no default cfg */ int err; spec = kzalloc(sizeof(*spec), GFP_KERNEL); @@ -5576,9 +5589,15 @@ static int patch_stac92hd83xxx(struct hda_codec *codec) case STAC_HP_ZEPHYR: spec->init = stac92hd83xxx_hp_zephyr_init; break; + case STAC_92HD83XXX_HP_LED: + default_polarity = 0; + break; + case STAC_92HD83XXX_HP_INV_LED: + default_polarity = 1; + break; } - if (find_mute_led_cfg(codec, -1/*no default cfg*/)) + if (find_mute_led_cfg(codec, default_polarity)) snd_printd("mute LED gpio %d polarity %d\n", spec->gpio_led, spec->gpio_led_polarity); diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 06214fdc948..9dafacdb519 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -1868,11 +1868,11 @@ static int via_auto_fill_dac_nids(struct hda_codec *codec) { struct via_spec *spec = codec->spec; const struct auto_pin_cfg *cfg = &spec->autocfg; - int i, dac_num; + int i; hda_nid_t nid; + spec->multiout.num_dacs = 0; spec->multiout.dac_nids = spec->private_dac_nids; - dac_num = 0; for (i = 0; i < cfg->line_outs; i++) { hda_nid_t dac = 0; nid = cfg->line_out_pins[i]; @@ -1883,16 +1883,13 @@ static int via_auto_fill_dac_nids(struct hda_codec *codec) if (!i && parse_output_path(codec, nid, dac, 1, &spec->out_mix_path)) dac = spec->out_mix_path.path[0]; - if (dac) { - spec->private_dac_nids[i] = dac; - dac_num++; - } + if (dac) + spec->private_dac_nids[spec->multiout.num_dacs++] = dac; } if (!spec->out_path[0].depth && spec->out_mix_path.depth) { spec->out_path[0] = spec->out_mix_path; spec->out_mix_path.depth = 0; } - spec->multiout.num_dacs = dac_num; return 0; } @@ -3233,7 +3230,7 @@ static void set_widgets_power_state_vt1718S(struct hda_codec *codec) { struct via_spec *spec = codec->spec; int imux_is_smixer; - unsigned int parm; + unsigned int parm, parm2; /* MUX6 (1eh) = stereo mixer */ imux_is_smixer = snd_hda_codec_read(codec, 0x1e, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 5; @@ -3256,7 +3253,7 @@ static void set_widgets_power_state_vt1718S(struct hda_codec *codec) parm = AC_PWRST_D3; set_pin_power_state(codec, 0x27, &parm); update_power_state(codec, 0x1a, parm); - update_power_state(codec, 0xb, parm); + parm2 = parm; /* for pin 0x0b */ /* PW2 (26h), AOW2 (ah) */ parm = AC_PWRST_D3; @@ -3271,6 +3268,9 @@ static void set_widgets_power_state_vt1718S(struct hda_codec *codec) if (!spec->hp_independent_mode) /* check for redirected HP */ set_pin_power_state(codec, 0x28, &parm); update_power_state(codec, 0x8, parm); + if (!spec->hp_independent_mode && parm2 != AC_PWRST_D3) + parm = parm2; + update_power_state(codec, 0xb, parm); /* MW9 (21h), Mw2 (1ah), AOW0 (8h) */ update_power_state(codec, 0x21, imux_is_smixer ? AC_PWRST_D0 : parm); @@ -3665,6 +3665,18 @@ static void set_widgets_power_state_vt2002P(struct hda_codec *codec) update_power_state(codec, 0x21, AC_PWRST_D3); } +/* NIDs 0x24 and 0x33 on VT1802 have connections to non-existing NID 0x3e + * Replace this with mixer NID 0x1c + */ +static void fix_vt1802_connections(struct hda_codec *codec) +{ + static hda_nid_t conn_24[] = { 0x14, 0x1c }; + static hda_nid_t conn_33[] = { 0x1c }; + + snd_hda_override_conn_list(codec, 0x24, ARRAY_SIZE(conn_24), conn_24); + snd_hda_override_conn_list(codec, 0x33, ARRAY_SIZE(conn_33), conn_33); +} + /* patch for vt2002P */ static int patch_vt2002P(struct hda_codec *codec) { @@ -3679,6 +3691,8 @@ static int patch_vt2002P(struct hda_codec *codec) spec->aa_mix_nid = 0x21; override_mic_boost(codec, 0x2b, 0, 3, 40); override_mic_boost(codec, 0x29, 0, 3, 40); + if (spec->codec_type == VT1802) + fix_vt1802_connections(codec); add_secret_dac_path(codec); /* automatic parse from the BIOS config */ diff --git a/sound/pci/ice1712/prodigy_hifi.c b/sound/pci/ice1712/prodigy_hifi.c index 764cc93dbca..075d5aa1fee 100644 --- a/sound/pci/ice1712/prodigy_hifi.c +++ b/sound/pci/ice1712/prodigy_hifi.c @@ -297,6 +297,7 @@ static int ak4396_dac_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem } static const DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -12700, 100, 1); +static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0); static struct snd_kcontrol_new prodigy_hd2_controls[] __devinitdata = { { @@ -307,7 +308,7 @@ static struct snd_kcontrol_new prodigy_hd2_controls[] __devinitdata = { .info = ak4396_dac_vol_info, .get = ak4396_dac_vol_get, .put = ak4396_dac_vol_put, - .tlv = { .p = db_scale_wm_dac }, + .tlv = { .p = ak4396_db_scale }, }, }; diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 5ba93701d2e..c72c88b3114 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile @@ -1,8 +1,9 @@ snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o soc-utils.o snd-soc-core-objs += soc-pcm.o soc-compress.o soc-io.o -snd-soc-dmaengine-pcm-objs := soc-dmaengine-pcm.o -obj-$(CONFIG_SND_SOC_DMAENGINE_PCM) += snd-soc-dmaengine-pcm.o +ifneq ($(CONFIG_SND_SOC_DMAENGINE_PCM),) +snd-soc-core-objs += soc-dmaengine-pcm.o +endif obj-$(CONFIG_SND_SOC) += snd-soc-core.o obj-$(CONFIG_SND_SOC) += codecs/ diff --git a/sound/soc/codecs/sigmadsp.c b/sound/soc/codecs/sigmadsp.c index 5be42bf5699..4068f249123 100644 --- a/sound/soc/codecs/sigmadsp.c +++ b/sound/soc/codecs/sigmadsp.c @@ -225,7 +225,7 @@ EXPORT_SYMBOL(process_sigma_firmware); static int sigma_action_write_regmap(void *control_data, const struct sigma_action *sa, size_t len) { - return regmap_raw_write(control_data, le16_to_cpu(sa->addr), + return regmap_raw_write(control_data, be16_to_cpu(sa->addr), sa->payload, len - 2); } diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c index a75c3766aed..bb9f0703748 100644 --- a/sound/soc/codecs/wm2000.c +++ b/sound/soc/codecs/wm2000.c @@ -190,9 +190,9 @@ static int wm2000_power_up(struct i2c_client *i2c, int analogue) ret = wm2000_read(i2c, WM2000_REG_SPEECH_CLARITY); if (wm2000->speech_clarity) - ret &= ~WM2000_SPEECH_CLARITY; - else ret |= WM2000_SPEECH_CLARITY; + else + ret &= ~WM2000_SPEECH_CLARITY; wm2000_write(i2c, WM2000_REG_SPEECH_CLARITY, ret); wm2000_write(i2c, WM2000_REG_SYS_START0, 0x33); @@ -692,7 +692,7 @@ static int wm2000_resume(struct snd_soc_codec *codec) #endif static const struct regmap_config wm2000_regmap = { - .reg_bits = 8, + .reg_bits = 16, .val_bits = 8, }; diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c index 32682c1b7cd..8e0cf146a68 100644 --- a/sound/soc/codecs/wm2200.c +++ b/sound/soc/codecs/wm2200.c @@ -897,8 +897,6 @@ static const char *wm2200_mixer_texts[] = { "EQR", "LHPF1", "LHPF2", - "LHPF3", - "LHPF4", "DSP1.1", "DSP1.2", "DSP1.3", @@ -931,7 +929,6 @@ static int wm2200_mixer_values[] = { 0x25, 0x50, /* EQ */ 0x51, - 0x52, 0x60, /* LHPF1 */ 0x61, /* LHPF2 */ 0x68, /* DSP1 */ @@ -1028,7 +1025,7 @@ SOC_DOUBLE_R_TLV("OUT2 Digital Volume", WM2200_DAC_DIGITAL_VOLUME_2L, WM2200_DAC_DIGITAL_VOLUME_2R, WM2200_OUT2L_VOL_SHIFT, 0x9f, 0, digital_tlv), SOC_DOUBLE("OUT2 Switch", WM2200_PDM_1, WM2200_SPK1L_MUTE_SHIFT, - WM2200_SPK1R_MUTE_SHIFT, 1, 0), + WM2200_SPK1R_MUTE_SHIFT, 1, 1), }; WM2200_MIXER_ENUMS(OUT1L, WM2200_OUT1LMIX_INPUT_1_SOURCE); @@ -1380,15 +1377,9 @@ static int wm2200_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) case SND_SOC_DAIFMT_DSP_A: fmt_val = 0; break; - case SND_SOC_DAIFMT_DSP_B: - fmt_val = 1; - break; case SND_SOC_DAIFMT_I2S: fmt_val = 2; break; - case SND_SOC_DAIFMT_LEFT_J: - fmt_val = 3; - break; default: dev_err(codec->dev, "Unsupported DAI format %d\n", fmt & SND_SOC_DAIFMT_FORMAT_MASK); @@ -1440,7 +1431,7 @@ static int wm2200_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) WM2200_AIF1TX_LRCLK_MSTR | WM2200_AIF1TX_LRCLK_INV, lrclk); snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_5, - WM2200_AIF1_FMT_MASK << 1, fmt_val << 1); + WM2200_AIF1_FMT_MASK, fmt_val); return 0; } @@ -2091,6 +2082,7 @@ static __devinit int wm2200_i2c_probe(struct i2c_client *i2c, switch (wm2200->rev) { case 0: + case 1: ret = regmap_register_patch(wm2200->regmap, wm2200_reva_patch, ARRAY_SIZE(wm2200_reva_patch)); if (ret != 0) { diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c index b9c185ce64e..a8d03ab5ea2 100644 --- a/sound/soc/codecs/wm5100.c +++ b/sound/soc/codecs/wm5100.c @@ -1296,15 +1296,9 @@ static int wm5100_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) case SND_SOC_DAIFMT_DSP_A: mask = 0; break; - case SND_SOC_DAIFMT_DSP_B: - mask = 1; - break; case SND_SOC_DAIFMT_I2S: mask = 2; break; - case SND_SOC_DAIFMT_LEFT_J: - mask = 3; - break; default: dev_err(codec->dev, "Unsupported DAI format %d\n", fmt & SND_SOC_DAIFMT_FORMAT_MASK); diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 15d467ff91b..96f6f9faa82 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -2488,6 +2488,9 @@ static int wm8962_set_bias_level(struct snd_soc_codec *codec, /* VMID 2*250k */ snd_soc_update_bits(codec, WM8962_PWR_MGMT_1, WM8962_VMID_SEL_MASK, 0x100); + + if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) + msleep(100); break; case SND_SOC_BIAS_OFF: @@ -3710,6 +3713,9 @@ static int wm8962_runtime_resume(struct device *dev) } regcache_cache_only(wm8962->regmap, false); + + wm8962_reset(wm8962); + regcache_sync(wm8962->regmap); regmap_update_bits(wm8962->regmap, WM8962_ANTI_POP, diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c index 72d5fdcd3cc..6c37c7c2327 100644 --- a/sound/soc/codecs/wm8978.c +++ b/sound/soc/codecs/wm8978.c @@ -783,7 +783,7 @@ static int wm8978_hw_params(struct snd_pcm_substream *substream, wm8978->mclk_idx = -1; f_sel = wm8978->f_mclk; } else { - if (!wm8978->f_pllout) { + if (!wm8978->f_opclk) { /* We only enter here, if OPCLK is not used */ int ret = wm8978_configure_pll(codec); if (ret < 0) diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index f351b933f5c..4c471a54893 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -2695,7 +2695,7 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } - bclk_rate = params_rate(params) * 2; + bclk_rate = params_rate(params) * 4; switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: bclk_rate *= 16; diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c index b342ae50bcd..757a52aed80 100644 --- a/sound/soc/codecs/wm9712.c +++ b/sound/soc/codecs/wm9712.c @@ -146,7 +146,7 @@ SOC_SINGLE("Playback Attenuate (-6dB) Switch", AC97_MASTER_TONE, 6, 1, 0), SOC_SINGLE("Bass Volume", AC97_MASTER_TONE, 8, 15, 1), SOC_SINGLE("Treble Volume", AC97_MASTER_TONE, 0, 15, 1), -SOC_SINGLE("Capture ADC Switch", AC97_REC_GAIN, 15, 1, 1), +SOC_SINGLE("Capture Switch", AC97_REC_GAIN, 15, 1, 1), SOC_ENUM("Capture Volume Steps", wm9712_enum[6]), SOC_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 63, 1), SOC_SINGLE("Capture ZC Switch", AC97_REC_GAIN, 7, 1, 0), @@ -272,7 +272,7 @@ SOC_DAPM_ENUM("Route", wm9712_enum[9]); /* Mic select */ static const struct snd_kcontrol_new wm9712_mic_src_controls = -SOC_DAPM_ENUM("Route", wm9712_enum[7]); +SOC_DAPM_ENUM("Mic Source Select", wm9712_enum[7]); /* diff select */ static const struct snd_kcontrol_new wm9712_diff_sel_controls = @@ -291,7 +291,9 @@ SND_SOC_DAPM_MUX("Left Capture Select", SND_SOC_NOPM, 0, 0, &wm9712_capture_selectl_controls), SND_SOC_DAPM_MUX("Right Capture Select", SND_SOC_NOPM, 0, 0, &wm9712_capture_selectr_controls), -SND_SOC_DAPM_MUX("Mic Select Source", SND_SOC_NOPM, 0, 0, +SND_SOC_DAPM_MUX("Left Mic Select Source", SND_SOC_NOPM, 0, 0, + &wm9712_mic_src_controls), +SND_SOC_DAPM_MUX("Right Mic Select Source", SND_SOC_NOPM, 0, 0, &wm9712_mic_src_controls), SND_SOC_DAPM_MUX("Differential Source", SND_SOC_NOPM, 0, 0, &wm9712_diff_sel_controls), @@ -319,6 +321,7 @@ SND_SOC_DAPM_PGA("Out 3 PGA", AC97_INT_PAGING, 5, 1, NULL, 0), SND_SOC_DAPM_PGA("Line PGA", AC97_INT_PAGING, 2, 1, NULL, 0), SND_SOC_DAPM_PGA("Phone PGA", AC97_INT_PAGING, 1, 1, NULL, 0), SND_SOC_DAPM_PGA("Mic PGA", AC97_INT_PAGING, 0, 1, NULL, 0), +SND_SOC_DAPM_PGA("Differential Mic", SND_SOC_NOPM, 0, 0, NULL, 0), SND_SOC_DAPM_MICBIAS("Mic Bias", AC97_INT_PAGING, 10, 1), SND_SOC_DAPM_OUTPUT("MONOOUT"), SND_SOC_DAPM_OUTPUT("HPOUTL"), @@ -379,6 +382,18 @@ static const struct snd_soc_dapm_route wm9712_audio_map[] = { {"Mic PGA", NULL, "MIC1"}, {"Mic PGA", NULL, "MIC2"}, + /* microphones */ + {"Differential Mic", NULL, "MIC1"}, + {"Differential Mic", NULL, "MIC2"}, + {"Left Mic Select Source", "Mic 1", "MIC1"}, + {"Left Mic Select Source", "Mic 2", "MIC2"}, + {"Left Mic Select Source", "Stereo", "MIC1"}, + {"Left Mic Select Source", "Differential", "Differential Mic"}, + {"Right Mic Select Source", "Mic 1", "MIC1"}, + {"Right Mic Select Source", "Mic 2", "MIC2"}, + {"Right Mic Select Source", "Stereo", "MIC2"}, + {"Right Mic Select Source", "Differential", "Differential Mic"}, + /* left capture selector */ {"Left Capture Select", "Mic", "MIC1"}, {"Left Capture Select", "Speaker Mixer", "Speaker Mixer"}, diff --git a/sound/soc/omap/mcbsp.c b/sound/soc/omap/mcbsp.c index e5f44440d1b..fb67772130b 100644 --- a/sound/soc/omap/mcbsp.c +++ b/sound/soc/omap/mcbsp.c @@ -691,7 +691,7 @@ int omap_mcbsp_6pin_src_mux(struct omap_mcbsp *mcbsp, u8 mux) { const char *signal, *src; - if (mcbsp->pdata->mux_signal) + if (!mcbsp->pdata->mux_signal) return -EINVAL; switch (mux) { diff --git a/sound/soc/omap/omap-abe-twl6040.c b/sound/soc/omap/omap-abe-twl6040.c index 93bb8eee22b..9c2f090167c 100644 --- a/sound/soc/omap/omap-abe-twl6040.c +++ b/sound/soc/omap/omap-abe-twl6040.c @@ -181,7 +181,7 @@ static int omap_abe_twl6040_init(struct snd_soc_pcm_runtime *rtd) twl6040_disconnect_pin(dapm, pdata->has_hf, "Ext Spk"); twl6040_disconnect_pin(dapm, pdata->has_ep, "Earphone Spk"); twl6040_disconnect_pin(dapm, pdata->has_aux, "Line Out"); - twl6040_disconnect_pin(dapm, pdata->has_vibra, "Vinrator"); + twl6040_disconnect_pin(dapm, pdata->has_vibra, "Vibrator"); twl6040_disconnect_pin(dapm, pdata->has_hsmic, "Headset Mic"); twl6040_disconnect_pin(dapm, pdata->has_mainmic, "Main Handset Mic"); twl6040_disconnect_pin(dapm, pdata->has_submic, "Sub Handset Mic"); diff --git a/sound/soc/samsung/dma.c b/sound/soc/samsung/dma.c index ddc6cde14e2..2526ecada5f 100644 --- a/sound/soc/samsung/dma.c +++ b/sound/soc/samsung/dma.c @@ -34,9 +34,7 @@ static const struct snd_pcm_hardware dma_hardware = { .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_MMAP_VALID | - SNDRV_PCM_INFO_PAUSE | - SNDRV_PCM_INFO_RESUME, + SNDRV_PCM_INFO_MMAP_VALID, .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_U8 | @@ -246,15 +244,11 @@ static int dma_trigger(struct snd_pcm_substream *substream, int cmd) switch (cmd) { case SNDRV_PCM_TRIGGER_START: - case SNDRV_PCM_TRIGGER_RESUME: - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: prtd->state |= ST_RUNNING; prtd->params->ops->trigger(prtd->params->ch); break; case SNDRV_PCM_TRIGGER_STOP: - case SNDRV_PCM_TRIGGER_SUSPEND: - case SNDRV_PCM_TRIGGER_PAUSE_PUSH: prtd->state &= ~ST_RUNNING; prtd->params->ops->stop(prtd->params->ch); break; diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 74ed2dffbff..91b728774db 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -199,7 +200,7 @@ struct fsi_stream { */ struct dma_chan *chan; struct sh_dmae_slave slave; /* see fsi_handler_init() */ - struct tasklet_struct tasklet; + struct work_struct work; dma_addr_t dma; }; @@ -968,9 +969,9 @@ static dma_addr_t fsi_dma_get_area(struct fsi_stream *io) return io->dma + samples_to_bytes(runtime, io->buff_sample_pos); } -static void fsi_dma_do_tasklet(unsigned long data) +static void fsi_dma_do_work(struct work_struct *work) { - struct fsi_stream *io = (struct fsi_stream *)data; + struct fsi_stream *io = container_of(work, struct fsi_stream, work); struct fsi_priv *fsi = fsi_stream_to_priv(io); struct dma_chan *chan; struct snd_soc_dai *dai; @@ -1023,7 +1024,7 @@ static void fsi_dma_do_tasklet(unsigned long data) * FIXME * * In DMAEngine case, codec and FSI cannot be started simultaneously - * since FSI is using tasklet. + * since FSI is using the scheduler work queue. * Therefore, in capture case, probably FSI FIFO will have got * overflow error in this point. * in that case, DMA cannot start transfer until error was cleared. @@ -1047,7 +1048,7 @@ static bool fsi_dma_filter(struct dma_chan *chan, void *param) static int fsi_dma_transfer(struct fsi_priv *fsi, struct fsi_stream *io) { - tasklet_schedule(&io->tasklet); + schedule_work(&io->work); return 0; } @@ -1087,14 +1088,14 @@ static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io) if (!io->chan) return -EIO; - tasklet_init(&io->tasklet, fsi_dma_do_tasklet, (unsigned long)io); + INIT_WORK(&io->work, fsi_dma_do_work); return 0; } static int fsi_dma_remove(struct fsi_priv *fsi, struct fsi_stream *io) { - tasklet_kill(&io->tasklet); + cancel_work_sync(&io->work); fsi_stream_stop(fsi, io); diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 99047178519..c642fce3717 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -1597,7 +1597,15 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event) } list_for_each_entry(w, &card->widgets, list) { - list_del_init(&w->dirty); + switch (w->id) { + case snd_soc_dapm_pre: + case snd_soc_dapm_post: + /* These widgets always need to be powered */ + break; + default: + list_del_init(&w->dirty); + break; + } if (w->power) { d = w->dapm; @@ -3364,7 +3372,7 @@ void snd_soc_dapm_shutdown(struct snd_soc_card *card) { struct snd_soc_codec *codec; - list_for_each_entry(codec, &card->codec_dev_list, list) { + list_for_each_entry(codec, &card->codec_dev_list, card_list) { soc_dapm_shutdown_codec(&codec->dapm); snd_soc_dapm_set_bias_level(&codec->dapm, SND_SOC_BIAS_OFF); } diff --git a/sound/soc/tegra/tegra_alc5632.c b/sound/soc/tegra/tegra_alc5632.c index e45ccd851f6..76d759ec40a 100644 --- a/sound/soc/tegra/tegra_alc5632.c +++ b/sound/soc/tegra/tegra_alc5632.c @@ -95,7 +95,6 @@ static struct snd_soc_jack_gpio tegra_alc5632_hp_jack_gpio = { .name = "Headset detection", .report = SND_JACK_HEADSET, .debounce_time = 150, - .invert = 1, }; static const struct snd_soc_dapm_widget tegra_alc5632_dapm_widgets[] = { diff --git a/sound/usb/caiaq/device.c b/sound/usb/caiaq/device.c index 64aed432ae2..7da0d0aa72c 100644 --- a/sound/usb/caiaq/device.c +++ b/sound/usb/caiaq/device.c @@ -485,7 +485,7 @@ static int __devinit snd_probe(struct usb_interface *intf, const struct usb_device_id *id) { int ret; - struct snd_card *card; + struct snd_card *card = NULL; struct usb_device *device = interface_to_usbdev(intf); ret = create_card(device, intf, &card); diff --git a/sound/usb/card.c b/sound/usb/card.c index 1452312cd69..1e14f6b9996 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -338,7 +338,7 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx, return -ENOMEM; } - mutex_init(&chip->shutdown_mutex); + init_rwsem(&chip->shutdown_rwsem); chip->index = idx; chip->dev = dev; chip->card = card; @@ -558,9 +558,11 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, return; card = chip->card; - mutex_lock(®ister_mutex); - mutex_lock(&chip->shutdown_mutex); + down_write(&chip->shutdown_rwsem); chip->shutdown = 1; + up_write(&chip->shutdown_rwsem); + + mutex_lock(®ister_mutex); chip->num_interfaces--; if (chip->num_interfaces <= 0) { snd_card_disconnect(card); @@ -577,11 +579,9 @@ static void snd_usb_audio_disconnect(struct usb_device *dev, snd_usb_mixer_disconnect(p); } usb_chip[chip->index] = NULL; - mutex_unlock(&chip->shutdown_mutex); mutex_unlock(®ister_mutex); snd_card_free_when_closed(card); } else { - mutex_unlock(&chip->shutdown_mutex); mutex_unlock(®ister_mutex); } switch_set_state(usbaudiosdev, 0); @@ -614,16 +614,20 @@ int snd_usb_autoresume(struct snd_usb_audio *chip) { int err = -ENODEV; + down_read(&chip->shutdown_rwsem); if (!chip->shutdown && !chip->probing) err = usb_autopm_get_interface(chip->pm_intf); + up_read(&chip->shutdown_rwsem); return err; } void snd_usb_autosuspend(struct snd_usb_audio *chip) { + down_read(&chip->shutdown_rwsem); if (!chip->shutdown && !chip->probing) usb_autopm_put_interface(chip->pm_intf); + up_read(&chip->shutdown_rwsem); } static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message) diff --git a/sound/usb/card.h b/sound/usb/card.h index da5fa1ac4ed..7932b2ac0de 100644 --- a/sound/usb/card.h +++ b/sound/usb/card.h @@ -87,6 +87,7 @@ struct snd_usb_substream { struct snd_urb_ctx syncurb[SYNC_URBS]; /* sync urb table */ char *syncbuf; /* sync buffer for all sync URBs */ dma_addr_t sync_dma; /* DMA address of syncbuf */ + unsigned int speed; /* USB_SPEED_XXX */ u64 formats; /* format bitmasks (all or'ed) */ unsigned int num_formats; /* number of supported audio formats (list) */ diff --git a/sound/usb/clock.c b/sound/usb/clock.c index 379baad3d5a..5e634a2eb28 100644 --- a/sound/usb/clock.c +++ b/sound/usb/clock.c @@ -111,7 +111,8 @@ static bool uac_clock_source_is_valid(struct snd_usb_audio *chip, int source_id) return 0; /* If a clock source can't tell us whether it's valid, we assume it is */ - if (!uac2_control_is_readable(cs_desc->bmControls, UAC2_CS_CONTROL_CLOCK_VALID)) + if (!uac2_control_is_readable(cs_desc->bmControls, + UAC2_CS_CONTROL_CLOCK_VALID - 1)) return 1; err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR, diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c index 08dcce53720..9ab2b3e2222 100644 --- a/sound/usb/endpoint.c +++ b/sound/usb/endpoint.c @@ -895,7 +895,8 @@ void snd_usb_init_substream(struct snd_usb_stream *as, subs->dev = as->chip->dev; subs->txfr_quirk = as->chip->txfr_quirk; subs->ops = audio_urb_ops[stream]; - if (snd_usb_get_speed(subs->dev) >= USB_SPEED_HIGH) + subs->speed = snd_usb_get_speed(subs->dev); + if (subs->speed >= USB_SPEED_HIGH) subs->ops.prepare_sync = prepare_capture_sync_urb_hs; snd_usb_set_pcm_ops(as->pcm, stream); diff --git a/sound/usb/midi.c b/sound/usb/midi.c index c83f6143c0e..34b9bb7fe87 100644 --- a/sound/usb/midi.c +++ b/sound/usb/midi.c @@ -116,6 +116,7 @@ struct snd_usb_midi { struct list_head list; struct timer_list error_timer; spinlock_t disc_lock; + struct rw_semaphore disc_rwsem; struct mutex mutex; u32 usb_id; int next_midi_device; @@ -125,8 +126,10 @@ struct snd_usb_midi { struct snd_usb_midi_in_endpoint *in; } endpoints[MIDI_MAX_ENDPOINTS]; unsigned long input_triggered; - unsigned int opened; + bool autopm_reference; + unsigned int opened[2]; unsigned char disconnected; + unsigned char input_running; struct snd_kcontrol *roland_load_ctl; }; @@ -1032,29 +1035,58 @@ static void update_roland_altsetting(struct snd_usb_midi* umidi) snd_usbmidi_input_start(&umidi->list); } -static void substream_open(struct snd_rawmidi_substream *substream, int open) +static int substream_open(struct snd_rawmidi_substream *substream, int dir, + int open) { struct snd_usb_midi* umidi = substream->rmidi->private_data; struct snd_kcontrol *ctl; + int err; + + down_read(&umidi->disc_rwsem); + if (umidi->disconnected) { + up_read(&umidi->disc_rwsem); + return open ? -ENODEV : 0; + } mutex_lock(&umidi->mutex); if (open) { - if (umidi->opened++ == 0 && umidi->roland_load_ctl) { - ctl = umidi->roland_load_ctl; - ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE; - snd_ctl_notify(umidi->card, + if (!umidi->opened[0] && !umidi->opened[1]) { + err = usb_autopm_get_interface(umidi->iface); + umidi->autopm_reference = err >= 0; + if (err < 0 && err != -EACCES) { + mutex_unlock(&umidi->mutex); + up_read(&umidi->disc_rwsem); + return -EIO; + } + if (umidi->roland_load_ctl) { + ctl = umidi->roland_load_ctl; + ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE; + snd_ctl_notify(umidi->card, SNDRV_CTL_EVENT_MASK_INFO, &ctl->id); - update_roland_altsetting(umidi); + update_roland_altsetting(umidi); + } } + umidi->opened[dir]++; + if (umidi->opened[1]) + snd_usbmidi_input_start(&umidi->list); } else { - if (--umidi->opened == 0 && umidi->roland_load_ctl) { - ctl = umidi->roland_load_ctl; - ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; - snd_ctl_notify(umidi->card, + umidi->opened[dir]--; + if (!umidi->opened[1]) + snd_usbmidi_input_stop(&umidi->list); + if (!umidi->opened[0] && !umidi->opened[1]) { + if (umidi->roland_load_ctl) { + ctl = umidi->roland_load_ctl; + ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE; + snd_ctl_notify(umidi->card, SNDRV_CTL_EVENT_MASK_INFO, &ctl->id); + } + if (umidi->autopm_reference) + usb_autopm_put_interface(umidi->iface); } } mutex_unlock(&umidi->mutex); + up_read(&umidi->disc_rwsem); + return 0; } static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream) @@ -1062,7 +1094,6 @@ static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream) struct snd_usb_midi* umidi = substream->rmidi->private_data; struct usbmidi_out_port* port = NULL; int i, j; - int err; for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) if (umidi->endpoints[i].out) @@ -1075,22 +1106,15 @@ static int snd_usbmidi_output_open(struct snd_rawmidi_substream *substream) snd_BUG(); return -ENXIO; } - err = usb_autopm_get_interface(umidi->iface); - if (err < 0) - return -EIO; + substream->runtime->private_data = port; port->state = STATE_UNKNOWN; - substream_open(substream, 1); - return 0; + return substream_open(substream, 0, 1); } static int snd_usbmidi_output_close(struct snd_rawmidi_substream *substream) { - struct snd_usb_midi* umidi = substream->rmidi->private_data; - - substream_open(substream, 0); - usb_autopm_put_interface(umidi->iface); - return 0; + return substream_open(substream, 0, 0); } static void snd_usbmidi_output_trigger(struct snd_rawmidi_substream *substream, int up) @@ -1143,14 +1167,12 @@ static void snd_usbmidi_output_drain(struct snd_rawmidi_substream *substream) static int snd_usbmidi_input_open(struct snd_rawmidi_substream *substream) { - substream_open(substream, 1); - return 0; + return substream_open(substream, 1, 1); } static int snd_usbmidi_input_close(struct snd_rawmidi_substream *substream) { - substream_open(substream, 0); - return 0; + return substream_open(substream, 1, 0); } static void snd_usbmidi_input_trigger(struct snd_rawmidi_substream *substream, int up) @@ -1399,9 +1421,12 @@ void snd_usbmidi_disconnect(struct list_head* p) * a timer may submit an URB. To reliably break the cycle * a flag under lock must be used */ + down_write(&umidi->disc_rwsem); spin_lock_irq(&umidi->disc_lock); umidi->disconnected = 1; spin_unlock_irq(&umidi->disc_lock); + up_write(&umidi->disc_rwsem); + for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) { struct snd_usb_midi_endpoint* ep = &umidi->endpoints[i]; if (ep->out) @@ -2056,12 +2081,15 @@ void snd_usbmidi_input_stop(struct list_head* p) unsigned int i, j; umidi = list_entry(p, struct snd_usb_midi, list); + if (!umidi->input_running) + return; for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) { struct snd_usb_midi_endpoint* ep = &umidi->endpoints[i]; if (ep->in) for (j = 0; j < INPUT_URBS; ++j) usb_kill_urb(ep->in->urbs[j]); } + umidi->input_running = 0; } static void snd_usbmidi_input_start_ep(struct snd_usb_midi_in_endpoint* ep) @@ -2086,8 +2114,11 @@ void snd_usbmidi_input_start(struct list_head* p) int i; umidi = list_entry(p, struct snd_usb_midi, list); + if (umidi->input_running || !umidi->opened[1]) + return; for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) snd_usbmidi_input_start_ep(umidi->endpoints[i].in); + umidi->input_running = 1; } /* @@ -2113,6 +2144,7 @@ int snd_usbmidi_create(struct snd_card *card, umidi->usb_protocol_ops = &snd_usbmidi_standard_ops; init_timer(&umidi->error_timer); spin_lock_init(&umidi->disc_lock); + init_rwsem(&umidi->disc_rwsem); mutex_init(&umidi->mutex); umidi->usb_id = USB_ID(le16_to_cpu(umidi->dev->descriptor.idVendor), le16_to_cpu(umidi->dev->descriptor.idProduct)); @@ -2225,9 +2257,6 @@ int snd_usbmidi_create(struct snd_card *card, } list_add_tail(&umidi->list, midi_list); - - for (i = 0; i < MIDI_MAX_ENDPOINTS; ++i) - snd_usbmidi_input_start_ep(umidi->endpoints[i].in); return 0; } diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 04a09dbb4c4..ff596e3532b 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -287,25 +287,32 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int v unsigned char buf[2]; int val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; int timeout = 10; - int err; + int idx = 0, err; err = snd_usb_autoresume(cval->mixer->chip); if (err < 0) return -EIO; + down_read(&chip->shutdown_rwsem); while (timeout-- > 0) { + if (chip->shutdown) + break; + idx = snd_usb_ctrl_intf(chip) | (cval->id << 8); if (snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), request, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, - validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), - buf, val_len) >= val_len) { + validx, idx, buf, val_len) >= val_len) { *value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len)); - snd_usb_autosuspend(cval->mixer->chip); - return 0; + err = 0; + goto out; } } - snd_usb_autosuspend(cval->mixer->chip); snd_printdd(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", - request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type); - return -EINVAL; + request, validx, idx, cval->val_type); + err = -EINVAL; + + out: + up_read(&chip->shutdown_rwsem); + snd_usb_autosuspend(cval->mixer->chip); + return err; } static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret) @@ -313,7 +320,7 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v struct snd_usb_audio *chip = cval->mixer->chip; unsigned char buf[2 + 3*sizeof(__u16)]; /* enough space for one range */ unsigned char *val; - int ret, size; + int idx = 0, ret, size; __u8 bRequest; if (request == UAC_GET_CUR) { @@ -330,16 +337,22 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v if (ret) goto error; - ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest, + down_read(&chip->shutdown_rwsem); + if (chip->shutdown) + ret = -ENODEV; + else { + idx = snd_usb_ctrl_intf(chip) | (cval->id << 8); + ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, - validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), - buf, size); + validx, idx, buf, size); + } + up_read(&chip->shutdown_rwsem); snd_usb_autosuspend(chip); if (ret < 0) { error: snd_printk(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", - request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type); + request, validx, idx, cval->val_type); return ret; } @@ -417,7 +430,7 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, { struct snd_usb_audio *chip = cval->mixer->chip; unsigned char buf[2]; - int val_len, err, timeout = 10; + int idx = 0, val_len, err, timeout = 10; if (cval->mixer->protocol == UAC_VERSION_1) { val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; @@ -440,19 +453,27 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, err = snd_usb_autoresume(chip); if (err < 0) return -EIO; - while (timeout-- > 0) + down_read(&chip->shutdown_rwsem); + while (timeout-- > 0) { + if (chip->shutdown) + break; + idx = snd_usb_ctrl_intf(chip) | (cval->id << 8); if (snd_usb_ctl_msg(chip->dev, usb_sndctrlpipe(chip->dev, 0), request, USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, - validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), - buf, val_len) >= 0) { - snd_usb_autosuspend(chip); - return 0; + validx, idx, buf, val_len) >= 0) { + err = 0; + goto out; } - snd_usb_autosuspend(chip); + } snd_printdd(KERN_ERR "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n", - request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type, buf[0], buf[1]); - return -EINVAL; + request, validx, idx, cval->val_type, buf[0], buf[1]); + err = -EINVAL; + + out: + up_read(&chip->shutdown_rwsem); + snd_usb_autosuspend(chip); + return err; } static int set_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int value) @@ -1218,16 +1239,23 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void } channels = (hdr->bLength - 7) / csize - 1; bmaControls = hdr->bmaControls; + if (hdr->bLength < 7 + csize) { + snd_printk(KERN_ERR "usbaudio: unit %u: " + "invalid UAC_FEATURE_UNIT descriptor\n", + unitid); + return -EINVAL; + } } else { struct uac2_feature_unit_descriptor *ftr = _ftr; csize = 4; channels = (hdr->bLength - 6) / 4 - 1; bmaControls = ftr->bmaControls; - } - - if (hdr->bLength < 7 || !csize || hdr->bLength < 7 + csize) { - snd_printk(KERN_ERR "usbaudio: unit %u: invalid UAC_FEATURE_UNIT descriptor\n", unitid); - return -EINVAL; + if (hdr->bLength < 6 + csize) { + snd_printk(KERN_ERR "usbaudio: unit %u: " + "invalid UAC_FEATURE_UNIT descriptor\n", + unitid); + return -EINVAL; + } } /* parse the source unit */ @@ -1247,6 +1275,13 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void /* disable non-functional volume control */ master_bits &= ~UAC_CONTROL_BIT(UAC_FU_VOLUME); break; + case USB_ID(0x1130, 0xf211): + snd_printk(KERN_INFO + "usbmixer: volume control quirk for Tenx TP6911 Audio Headset\n"); + /* disable non-functional volume control */ + channels = 0; + break; + } if (channels > 0) first_ch_bits = snd_usb_combine_bytes(bmaControls + csize, csize); diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index ab125ee0b0f..38a607a7ae2 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -186,6 +186,11 @@ static int snd_audigy2nx_led_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e if (value > 1) return -EINVAL; changed = value != mixer->audigy2nx_leds[index]; + down_read(&mixer->chip->shutdown_rwsem); + if (mixer->chip->shutdown) { + err = -ENODEV; + goto out; + } if (mixer->chip->usb_id == USB_ID(0x041e, 0x3042)) err = snd_usb_ctl_msg(mixer->chip->dev, usb_sndctrlpipe(mixer->chip->dev, 0), 0x24, @@ -202,6 +207,8 @@ static int snd_audigy2nx_led_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e usb_sndctrlpipe(mixer->chip->dev, 0), 0x24, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, value, index + 2, NULL, 0); + out: + up_read(&mixer->chip->shutdown_rwsem); if (err < 0) return err; mixer->audigy2nx_leds[index] = value; @@ -295,11 +302,16 @@ static void snd_audigy2nx_proc_read(struct snd_info_entry *entry, for (i = 0; jacks[i].name; ++i) { snd_iprintf(buffer, "%s: ", jacks[i].name); - err = snd_usb_ctl_msg(mixer->chip->dev, + down_read(&mixer->chip->shutdown_rwsem); + if (mixer->chip->shutdown) + err = 0; + else + err = snd_usb_ctl_msg(mixer->chip->dev, usb_rcvctrlpipe(mixer->chip->dev, 0), UAC_GET_MEM, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, jacks[i].unitid << 8, buf, 3); + up_read(&mixer->chip->shutdown_rwsem); if (err == 3 && (buf[0] == 3 || buf[0] == 6)) snd_iprintf(buffer, "%02x %02x\n", buf[1], buf[2]); else @@ -329,10 +341,15 @@ static int snd_xonar_u1_switch_put(struct snd_kcontrol *kcontrol, else new_status = old_status & ~0x02; changed = new_status != old_status; - err = snd_usb_ctl_msg(mixer->chip->dev, + down_read(&mixer->chip->shutdown_rwsem); + if (mixer->chip->shutdown) + err = -ENODEV; + else + err = snd_usb_ctl_msg(mixer->chip->dev, usb_sndctrlpipe(mixer->chip->dev, 0), 0x08, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, 50, 0, &new_status, 1); + up_read(&mixer->chip->shutdown_rwsem); if (err < 0) return err; mixer->xonar_u1_status = new_status; @@ -371,11 +388,17 @@ static int snd_nativeinstruments_control_get(struct snd_kcontrol *kcontrol, u8 bRequest = (kcontrol->private_value >> 16) & 0xff; u16 wIndex = kcontrol->private_value & 0xffff; u8 tmp; + int ret; - int ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), bRequest, + down_read(&mixer->chip->shutdown_rwsem); + if (mixer->chip->shutdown) + ret = -ENODEV; + else + ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), bRequest, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, 0, cpu_to_le16(wIndex), &tmp, sizeof(tmp), 1000); + up_read(&mixer->chip->shutdown_rwsem); if (ret < 0) { snd_printk(KERN_ERR @@ -396,11 +419,17 @@ static int snd_nativeinstruments_control_put(struct snd_kcontrol *kcontrol, u8 bRequest = (kcontrol->private_value >> 16) & 0xff; u16 wIndex = kcontrol->private_value & 0xffff; u16 wValue = ucontrol->value.integer.value[0]; + int ret; - int ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), bRequest, + down_read(&mixer->chip->shutdown_rwsem); + if (mixer->chip->shutdown) + ret = -ENODEV; + else + ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), bRequest, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, cpu_to_le16(wValue), cpu_to_le16(wIndex), NULL, 0, 1000); + up_read(&mixer->chip->shutdown_rwsem); if (ret < 0) { snd_printk(KERN_ERR diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 67a4d6dbb32..4a99f6ca4b6 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -67,6 +67,8 @@ static snd_pcm_uframes_t snd_usb_pcm_pointer(struct snd_pcm_substream *substream unsigned int hwptr_done; subs = (struct snd_usb_substream *)substream->runtime->private_data; + if (subs->stream->chip->shutdown) + return SNDRV_PCM_POS_XRUN; spin_lock(&subs->lock); hwptr_done = subs->hwptr_done; substream->runtime->delay = snd_usb_pcm_delay(subs, @@ -373,8 +375,14 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, changed = subs->cur_audiofmt != fmt || subs->period_bytes != params_period_bytes(hw_params) || subs->cur_rate != rate; + + down_read(&subs->stream->chip->shutdown_rwsem); + if (subs->stream->chip->shutdown) { + ret = -ENODEV; + goto unlock; + } if ((ret = set_format(subs, fmt)) < 0) - return ret; + goto unlock; if (subs->cur_rate != rate) { struct usb_host_interface *alts; @@ -383,12 +391,11 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, alts = &iface->altsetting[fmt->altset_idx]; ret = snd_usb_init_sample_rate(subs->stream->chip, subs->interface, alts, fmt, rate); if (ret < 0) - return ret; + goto unlock; subs->cur_rate = rate; } if (changed) { - mutex_lock(&subs->stream->chip->shutdown_mutex); /* format changed */ snd_usb_release_substream_urbs(subs, 0); /* influenced: period_bytes, channels, rate, format, */ @@ -396,9 +403,10 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream, params_rate(hw_params), snd_pcm_format_physical_width(params_format(hw_params)) * params_channels(hw_params)); - mutex_unlock(&subs->stream->chip->shutdown_mutex); } +unlock: + up_read(&subs->stream->chip->shutdown_rwsem); return ret; } @@ -414,9 +422,9 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream) subs->cur_audiofmt = NULL; subs->cur_rate = 0; subs->period_bytes = 0; - mutex_lock(&subs->stream->chip->shutdown_mutex); + down_read(&subs->stream->chip->shutdown_rwsem); snd_usb_release_substream_urbs(subs, 0); - mutex_unlock(&subs->stream->chip->shutdown_mutex); + up_read(&subs->stream->chip->shutdown_rwsem); return snd_pcm_lib_free_vmalloc_buffer(substream); } @@ -429,12 +437,18 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; struct snd_usb_substream *subs = runtime->private_data; + int ret = 0; if (! subs->cur_audiofmt) { snd_printk(KERN_ERR "usbaudio: no format is specified!\n"); return -ENXIO; } + down_read(&subs->stream->chip->shutdown_rwsem); + if (subs->stream->chip->shutdown) { + ret = -ENODEV; + goto unlock; + } /* some unit conversions in runtime */ subs->maxframesize = bytes_to_frames(runtime, subs->maxpacksize); subs->curframesize = bytes_to_frames(runtime, subs->curpacksize); @@ -447,7 +461,10 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream) subs->last_frame_number = 0; runtime->delay = 0; - return snd_usb_substream_prepare(subs, runtime); + ret = snd_usb_substream_prepare(subs, runtime); + unlock: + up_read(&subs->stream->chip->shutdown_rwsem); + return ret; } static struct snd_pcm_hardware snd_usb_hardware = @@ -500,7 +517,7 @@ static int hw_check_valid_format(struct snd_usb_substream *subs, return 0; } /* check whether the period time is >= the data packet interval */ - if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL) { + if (subs->speed != USB_SPEED_FULL) { ptime = 125 * (1 << fp->datainterval); if (ptime > pt->max || (ptime == pt->max && pt->openmax)) { hwc_debug(" > check: ptime %u > max %u\n", ptime, pt->max); @@ -778,7 +795,7 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre return err; param_period_time_if_needed = SNDRV_PCM_HW_PARAM_PERIOD_TIME; - if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL) + if (subs->speed == USB_SPEED_FULL) /* full speed devices have fixed data packet interval */ ptmin = 1000; if (ptmin == 1000) diff --git a/sound/usb/proc.c b/sound/usb/proc.c index 961c9a25068..aef03db3870 100644 --- a/sound/usb/proc.c +++ b/sound/usb/proc.c @@ -107,7 +107,7 @@ static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct s } snd_iprintf(buffer, "\n"); } - if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL) + if (subs->speed != USB_SPEED_FULL) snd_iprintf(buffer, " Data packet interval: %d us\n", 125 * (1 << fp->datainterval)); // snd_iprintf(buffer, " Max Packet Size = %d\n", fp->maxpacksize); @@ -128,7 +128,7 @@ static void proc_dump_substream_status(struct snd_usb_substream *subs, struct sn snd_iprintf(buffer, "]\n"); snd_iprintf(buffer, " Packet Size = %d\n", subs->curpacksize); snd_iprintf(buffer, " Momentary freq = %u Hz (%#x.%04x)\n", - snd_usb_get_speed(subs->dev) == USB_SPEED_FULL + subs->speed == USB_SPEED_FULL ? get_full_speed_hz(subs->freqm) : get_high_speed_hz(subs->freqm), subs->freqm >> 16, subs->freqm & 0xffff); diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index d89ab4c7d44..63128cd6254 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -2751,6 +2751,59 @@ YAMAHA_DEVICE(0x7010, "UB99"), } }, +/* Microsoft XboxLive Headset/Xbox Communicator */ +{ + USB_DEVICE(0x045e, 0x0283), + .bInterfaceClass = USB_CLASS_PER_INTERFACE, + .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + .vendor_name = "Microsoft", + .product_name = "XboxLive Headset/Xbox Communicator", + .ifnum = QUIRK_ANY_INTERFACE, + .type = QUIRK_COMPOSITE, + .data = &(const struct snd_usb_audio_quirk[]) { + { + /* playback */ + .ifnum = 0, + .type = QUIRK_AUDIO_FIXED_ENDPOINT, + .data = &(const struct audioformat) { + .formats = SNDRV_PCM_FMTBIT_S16_LE, + .channels = 1, + .iface = 0, + .altsetting = 0, + .altset_idx = 0, + .attributes = 0, + .endpoint = 0x04, + .ep_attr = 0x05, + .rates = SNDRV_PCM_RATE_CONTINUOUS, + .rate_min = 22050, + .rate_max = 22050 + } + }, + { + /* capture */ + .ifnum = 1, + .type = QUIRK_AUDIO_FIXED_ENDPOINT, + .data = &(const struct audioformat) { + .formats = SNDRV_PCM_FMTBIT_S16_LE, + .channels = 1, + .iface = 1, + .altsetting = 0, + .altset_idx = 0, + .attributes = 0, + .endpoint = 0x85, + .ep_attr = 0x05, + .rates = SNDRV_PCM_RATE_CONTINUOUS, + .rate_min = 16000, + .rate_max = 16000 + } + }, + { + .ifnum = -1 + } + } + } +}, + { /* * Some USB MIDI devices don't have an audio control interface, diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 27817266867..c46171a2bf2 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -387,11 +387,13 @@ static int snd_usb_fasttrackpro_boot_quirk(struct usb_device *dev) * rules */ err = usb_driver_set_configuration(dev, 2); - if (err < 0) { + if (err < 0) snd_printdd("error usb_driver_set_configuration: %d\n", err); - return -ENODEV; - } + /* Always return an error, so that we stop creating a device + that will just be destroyed and recreated with a new + configuration */ + return -ENODEV; } else snd_printk(KERN_INFO "usb-audio: Fast Track Pro config OK\n"); diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index 3e2b0357793..6c805a51d7d 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h @@ -36,7 +36,7 @@ struct snd_usb_audio { struct snd_card *card; struct usb_interface *pm_intf; u32 usb_id; - struct mutex shutdown_mutex; + struct rw_semaphore shutdown_rwsem; unsigned int shutdown:1; unsigned int probing:1; unsigned int autosuspended:1; diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c index d9834b36294..2984ffb7bac 100644 --- a/tools/hv/hv_kvp_daemon.c +++ b/tools/hv/hv_kvp_daemon.c @@ -106,7 +106,7 @@ static void kvp_acquire_lock(int pool) if (fcntl(kvp_file_info[pool].fd, F_SETLKW, &fl) == -1) { syslog(LOG_ERR, "Failed to acquire the lock pool: %d", pool); - exit(-1); + exit(EXIT_FAILURE); } } @@ -118,7 +118,7 @@ static void kvp_release_lock(int pool) if (fcntl(kvp_file_info[pool].fd, F_SETLK, &fl) == -1) { perror("fcntl"); syslog(LOG_ERR, "Failed to release the lock pool: %d", pool); - exit(-1); + exit(EXIT_FAILURE); } } @@ -137,14 +137,19 @@ static void kvp_update_file(int pool) if (!filep) { kvp_release_lock(pool); syslog(LOG_ERR, "Failed to open file, pool: %d", pool); - exit(-1); + exit(EXIT_FAILURE); } bytes_written = fwrite(kvp_file_info[pool].records, sizeof(struct kvp_record), kvp_file_info[pool].num_records, filep); - fflush(filep); + if (ferror(filep) || fclose(filep)) { + kvp_release_lock(pool); + syslog(LOG_ERR, "Failed to write file, pool: %d", pool); + exit(EXIT_FAILURE); + } + kvp_release_lock(pool); } @@ -163,14 +168,19 @@ static void kvp_update_mem_state(int pool) if (!filep) { kvp_release_lock(pool); syslog(LOG_ERR, "Failed to open file, pool: %d", pool); - exit(-1); + exit(EXIT_FAILURE); } - while (!feof(filep)) { + for (;;) { readp = &record[records_read]; records_read += fread(readp, sizeof(struct kvp_record), ENTRIES_PER_BLOCK * num_blocks, filep); + if (ferror(filep)) { + syslog(LOG_ERR, "Failed to read file, pool: %d", pool); + exit(EXIT_FAILURE); + } + if (!feof(filep)) { /* * We have more data to read. @@ -180,7 +190,7 @@ static void kvp_update_mem_state(int pool) if (record == NULL) { syslog(LOG_ERR, "malloc failed"); - exit(-1); + exit(EXIT_FAILURE); } continue; } @@ -191,6 +201,7 @@ static void kvp_update_mem_state(int pool) kvp_file_info[pool].records = record; kvp_file_info[pool].num_records = records_read; + fclose(filep); kvp_release_lock(pool); } static int kvp_file_init(void) @@ -208,7 +219,7 @@ static int kvp_file_init(void) if (access("/var/opt/hyperv", F_OK)) { if (mkdir("/var/opt/hyperv", S_IRUSR | S_IWUSR | S_IROTH)) { syslog(LOG_ERR, " Failed to create /var/opt/hyperv"); - exit(-1); + exit(EXIT_FAILURE); } } @@ -232,12 +243,18 @@ static int kvp_file_init(void) fclose(filep); return 1; } - while (!feof(filep)) { + for (;;) { readp = &record[records_read]; records_read += fread(readp, sizeof(struct kvp_record), ENTRIES_PER_BLOCK, filep); + if (ferror(filep)) { + syslog(LOG_ERR, "Failed to read file, pool: %d", + i); + exit(EXIT_FAILURE); + } + if (!feof(filep)) { /* * We have more data to read. @@ -657,13 +674,13 @@ int main(void) if (kvp_file_init()) { syslog(LOG_ERR, "Failed to initialize the pools"); - exit(-1); + exit(EXIT_FAILURE); } fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_CONNECTOR); if (fd < 0) { syslog(LOG_ERR, "netlink socket creation failed; error:%d", fd); - exit(-1); + exit(EXIT_FAILURE); } addr.nl_family = AF_NETLINK; addr.nl_pad = 0; @@ -675,7 +692,7 @@ int main(void) if (error < 0) { syslog(LOG_ERR, "bind failed; error:%d", error); close(fd); - exit(-1); + exit(EXIT_FAILURE); } sock_opt = addr.nl_groups; setsockopt(fd, 270, 1, &sock_opt, sizeof(sock_opt)); @@ -695,7 +712,7 @@ int main(void) if (len < 0) { syslog(LOG_ERR, "netlink_send failed; error:%d", len); close(fd); - exit(-1); + exit(EXIT_FAILURE); } pfd.fd = fd; @@ -863,7 +880,7 @@ int main(void) len = netlink_send(fd, incoming_cn_msg); if (len < 0) { syslog(LOG_ERR, "net_link send failed; error:%d", len); - exit(-1); + exit(EXIT_FAILURE); } } diff --git a/tools/lguest/lguest.c b/tools/lguest/lguest.c index f759f4f097c..fd2f9221b24 100644 --- a/tools/lguest/lguest.c +++ b/tools/lguest/lguest.c @@ -1299,6 +1299,7 @@ static struct device *new_device(const char *name, u16 type) dev->feature_len = 0; dev->num_vq = 0; dev->running = false; + dev->next = NULL; /* * Append to device list. Prepending to a single-linked list is diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 80f23c07902..b6835c184cc 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -70,7 +70,7 @@ ifeq ($(ARCH),x86_64) ARCH := x86 IS_X86_64 := 0 ifeq (, $(findstring m32,$(EXTRA_CFLAGS))) - IS_X86_64 := $(shell echo __x86_64__ | ${CC} -E -xc - | tail -n 1) + IS_X86_64 := $(shell echo __x86_64__ | ${CC} -E -x c - | tail -n 1) endif ifeq (${IS_X86_64}, 1) RAW_ARCH := x86_64 diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c index 223ffdcc0fd..3487b4b4211 100644 --- a/tools/perf/builtin-test.c +++ b/tools/perf/builtin-test.c @@ -1154,19 +1154,13 @@ static int test__parse_events(void) return ret; } -static int sched__get_first_possible_cpu(pid_t pid, cpu_set_t **maskp, - size_t *sizep) +static int sched__get_first_possible_cpu(pid_t pid, cpu_set_t *maskp) { - cpu_set_t *mask; - size_t size; int i, cpu = -1, nrcpus = 1024; realloc: - mask = CPU_ALLOC(nrcpus); - size = CPU_ALLOC_SIZE(nrcpus); - CPU_ZERO_S(size, mask); + CPU_ZERO(maskp); - if (sched_getaffinity(pid, size, mask) == -1) { - CPU_FREE(mask); + if (sched_getaffinity(pid, sizeof(*maskp), maskp) == -1) { if (errno == EINVAL && nrcpus < (1024 << 8)) { nrcpus = nrcpus << 2; goto realloc; @@ -1176,19 +1170,14 @@ static int sched__get_first_possible_cpu(pid_t pid, cpu_set_t **maskp, } for (i = 0; i < nrcpus; i++) { - if (CPU_ISSET_S(i, size, mask)) { - if (cpu == -1) { + if (CPU_ISSET(i, maskp)) { + if (cpu == -1) cpu = i; - *maskp = mask; - *sizep = size; - } else - CPU_CLR_S(i, size, mask); + else + CPU_CLR(i, maskp); } } - if (cpu == -1) - CPU_FREE(mask); - return cpu; } @@ -1199,8 +1188,8 @@ static int test__PERF_RECORD(void) .freq = 10, .mmap_pages = 256, }; - cpu_set_t *cpu_mask = NULL; - size_t cpu_mask_size = 0; + cpu_set_t cpu_mask; + size_t cpu_mask_size = sizeof(cpu_mask); struct perf_evlist *evlist = perf_evlist__new(NULL, NULL); struct perf_evsel *evsel; struct perf_sample sample; @@ -1265,8 +1254,7 @@ static int test__PERF_RECORD(void) evsel->attr.sample_type |= PERF_SAMPLE_TIME; perf_evlist__config_attrs(evlist, &opts); - err = sched__get_first_possible_cpu(evlist->workload.pid, &cpu_mask, - &cpu_mask_size); + err = sched__get_first_possible_cpu(evlist->workload.pid, &cpu_mask); if (err < 0) { pr_debug("sched__get_first_possible_cpu: %s\n", strerror(errno)); goto out_delete_evlist; @@ -1277,9 +1265,9 @@ static int test__PERF_RECORD(void) /* * So that we can check perf_sample.cpu on all the samples. */ - if (sched_setaffinity(evlist->workload.pid, cpu_mask_size, cpu_mask) < 0) { + if (sched_setaffinity(evlist->workload.pid, cpu_mask_size, &cpu_mask) < 0) { pr_debug("sched_setaffinity: %s\n", strerror(errno)); - goto out_free_cpu_mask; + goto out_delete_evlist; } /* @@ -1472,8 +1460,6 @@ static int test__PERF_RECORD(void) } out_err: perf_evlist__munmap(evlist); -out_free_cpu_mask: - CPU_FREE(cpu_mask); out_delete_evlist: perf_evlist__delete(evlist); out: diff --git a/tools/power/cpupower/Makefile b/tools/power/cpupower/Makefile index a93e06cfcc2..cf397bd26d0 100644 --- a/tools/power/cpupower/Makefile +++ b/tools/power/cpupower/Makefile @@ -111,7 +111,7 @@ GMO_FILES = ${shell for HLANG in ${LANGUAGES}; do echo $(OUTPUT)po/$$HLANG.gmo; export CROSS CC AR STRIP RANLIB CFLAGS LDFLAGS LIB_OBJS # check if compiler option is supported -cc-supports = ${shell if $(CC) ${1} -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo "$(1)"; fi;} +cc-supports = ${shell if $(CC) ${1} -S -o /dev/null -x c /dev/null > /dev/null 2>&1; then echo "$(1)"; fi;} # use '-Os' optimization if available, else use -O2 OPTIMIZATION := $(call cc-supports,-Os,-O2) diff --git a/usr/gen_init_cpio.c b/usr/gen_init_cpio.c index af0f22fb1ef..aca6edcbbc6 100644 --- a/usr/gen_init_cpio.c +++ b/usr/gen_init_cpio.c @@ -303,7 +303,7 @@ static int cpio_mkfile(const char *name, const char *location, int retval; int rc = -1; int namesize; - int i; + unsigned int i; mode |= S_IFREG; @@ -381,25 +381,28 @@ static int cpio_mkfile(const char *name, const char *location, static char *cpio_replace_env(char *new_location) { - char expanded[PATH_MAX + 1]; - char env_var[PATH_MAX + 1]; - char *start; - char *end; - - for (start = NULL; (start = strstr(new_location, "${")); ) { - end = strchr(start, '}'); - if (start < end) { - *env_var = *expanded = '\0'; - strncat(env_var, start + 2, end - start - 2); - strncat(expanded, new_location, start - new_location); - strncat(expanded, getenv(env_var), PATH_MAX); - strncat(expanded, end + 1, PATH_MAX); - strncpy(new_location, expanded, PATH_MAX); - } else - break; - } - - return new_location; + char expanded[PATH_MAX + 1]; + char env_var[PATH_MAX + 1]; + char *start; + char *end; + + for (start = NULL; (start = strstr(new_location, "${")); ) { + end = strchr(start, '}'); + if (start < end) { + *env_var = *expanded = '\0'; + strncat(env_var, start + 2, end - start - 2); + strncat(expanded, new_location, start - new_location); + strncat(expanded, getenv(env_var), + PATH_MAX - strlen(expanded)); + strncat(expanded, end + 1, + PATH_MAX - strlen(expanded)); + strncpy(new_location, expanded, PATH_MAX); + new_location[PATH_MAX] = 0; + } else + break; + } + + return new_location; } diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 9739b533ca2..71b9036644a 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -693,8 +693,7 @@ int __kvm_set_memory_region(struct kvm *kvm, int r; gfn_t base_gfn; unsigned long npages; - unsigned long i; - struct kvm_memory_slot *memslot; + struct kvm_memory_slot *memslot, *slot; struct kvm_memory_slot old, new; struct kvm_memslots *slots, *old_memslots; @@ -741,13 +740,11 @@ int __kvm_set_memory_region(struct kvm *kvm, /* Check for overlaps */ r = -EEXIST; - for (i = 0; i < KVM_MEMORY_SLOTS; ++i) { - struct kvm_memory_slot *s = &kvm->memslots->memslots[i]; - - if (s == memslot || !s->npages) + kvm_for_each_memslot(slot, kvm->memslots) { + if (slot->id >= KVM_MEMORY_SLOTS || slot == memslot) continue; - if (!((base_gfn + npages <= s->base_gfn) || - (base_gfn >= s->base_gfn + s->npages))) + if (!((base_gfn + npages <= slot->base_gfn) || + (base_gfn >= slot->base_gfn + slot->npages))) goto out_free; } From 58c9f885628a8c1cf7f4fda77cf80539be63540c Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Sat, 21 Dec 2013 22:27:08 +0100 Subject: [PATCH 084/215] sched: LOAD_FREQ (4*HZ+61) avoids loadavg Moire These values are applicable for 100 HZ device. Check http://ripke.com/loadavg/moire for more details. Signed-off-by: Tk-Glitch --- include/linux/sched.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/linux/sched.h b/include/linux/sched.h index acc142bfe30..e449798ae63 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -122,10 +122,10 @@ extern void get_avenrun(unsigned long *loads, unsigned long offset, int shift); #define FSHIFT 11 /* nr of bits of precision */ #define FIXED_1 (1< Date: Sat, 21 Dec 2013 22:27:51 +0100 Subject: [PATCH 085/215] staging: android: Fix three checkpatch issues in binder.c Signed-off-by: Pranav Vashi Signed-off-by: Tk-Glitch --- drivers/staging/android/binder.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c index 65bca1fa684..19403fe9381 100644 --- a/drivers/staging/android/binder.c +++ b/drivers/staging/android/binder.c @@ -3377,7 +3377,7 @@ static void print_binder_proc(struct seq_file *m, m->count = start_pos; } -static const char *binder_return_strings[] = { +static const char * const binder_return_strings[] = { "BR_ERROR", "BR_OK", "BR_TRANSACTION", @@ -3398,7 +3398,7 @@ static const char *binder_return_strings[] = { "BR_FAILED_REPLY" }; -static const char *binder_command_strings[] = { +static const char * const binder_command_strings[] = { "BC_TRANSACTION", "BC_REPLY", "BC_ACQUIRE_RESULT", @@ -3418,7 +3418,7 @@ static const char *binder_command_strings[] = { "BC_DEAD_BINDER_DONE" }; -static const char *binder_objstat_strings[] = { +static const char * const binder_objstat_strings[] = { "proc", "thread", "node", From 626ec0f01bc490a7bb178252cb86728ed1b77fc6 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Sat, 21 Dec 2013 22:28:36 +0100 Subject: [PATCH 086/215] staging: android: Lower reserved logger RAM Signed-off-by: Pranav Vashi Signed-off-by: Tk-Glitch --- drivers/staging/android/logger.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/staging/android/logger.c b/drivers/staging/android/logger.c index eb3d4ca5fef..3ce3a3fae86 100644 --- a/drivers/staging/android/logger.c +++ b/drivers/staging/android/logger.c @@ -728,10 +728,10 @@ static struct logger_log VAR = { \ .size = SIZE, \ }; -DEFINE_LOGGER_DEVICE(log_main, LOGGER_LOG_MAIN, 256*1024) -DEFINE_LOGGER_DEVICE(log_events, LOGGER_LOG_EVENTS, 256*1024) -DEFINE_LOGGER_DEVICE(log_radio, LOGGER_LOG_RADIO, 256*1024) -DEFINE_LOGGER_DEVICE(log_system, LOGGER_LOG_SYSTEM, 256*1024) +DEFINE_LOGGER_DEVICE(log_main, LOGGER_LOG_MAIN, 32*1024) +DEFINE_LOGGER_DEVICE(log_events, LOGGER_LOG_EVENTS, 32*1024) +DEFINE_LOGGER_DEVICE(log_radio, LOGGER_LOG_RADIO, 32*1024) +DEFINE_LOGGER_DEVICE(log_system, LOGGER_LOG_SYSTEM, 32*1024) static struct logger_log *get_log_from_minor(int minor) { From c7c9e747584881a6021ef833a96aaaf6580e8ef0 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Sat, 21 Dec 2013 23:15:15 +0100 Subject: [PATCH 087/215] Linux 3.4.31 - 3.4.60 --- Documentation/kernel-parameters.txt | 5 + MAINTAINERS | 7 +- Makefile | 2 +- arch/alpha/Makefile | 2 +- arch/alpha/kernel/sys_nautilus.c | 5 + arch/arm/configs/at91sam9g45_defconfig | 1 - arch/arm/include/asm/cacheflush.h | 4 +- arch/arm/include/asm/pgtable.h | 9 + arch/arm/include/asm/signal.h | 1 + arch/arm/kernel/perf_event.c | 6 +- arch/arm/kernel/perf_event_v7.c | 2 +- arch/arm/mach-at91/setup.c | 2 +- arch/arm/mach-cns3xxx/core.c | 16 +- arch/arm/mach-cns3xxx/include/mach/cns3xxx.h | 16 +- arch/arm/mach-kirkwood/ts219-setup.c | 2 +- arch/arm/mach-omap2/board-rx51-peripherals.c | 4 +- arch/arm/mach-pxa/include/mach/smemc.h | 1 + arch/arm/mach-pxa/smemc.c | 15 +- .../mach-s3c24xx/include/mach/debug-macro.S | 12 +- .../mach-s3c24xx/include/mach/entry-macro.S | 4 +- arch/arm/mach-s3c24xx/pm-h1940.S | 2 +- arch/arm/mach-s3c24xx/sleep-s3c2410.S | 12 +- arch/arm/mach-s3c24xx/sleep-s3c2412.S | 12 +- arch/arm/mm/alignment.c | 11 +- arch/arm/mm/cache-feroceon-l2.c | 1 + arch/arm/mm/flush.c | 33 ++ arch/arm/mm/nommu.c | 6 + arch/arm/mm/proc-arm920.S | 2 +- arch/arm/mm/proc-arm926.S | 2 +- arch/arm/mm/proc-sa1100.S | 2 +- arch/arm/mm/proc-v6.S | 2 +- arch/arm/mm/proc-xsc3.S | 2 +- arch/arm/mm/proc-xscale.S | 2 +- arch/arm/plat-orion/common.c | 12 +- .../plat-samsung/include/plat/debug-macro.S | 18 +- arch/arm/vfp/vfpmodule.c | 2 +- arch/avr32/configs/favr-32_defconfig | 1 - arch/avr32/configs/merisc_defconfig | 1 - arch/avr32/include/asm/signal.h | 1 + arch/avr32/kernel/module.c | 2 +- arch/cris/arch-v10/lib/Makefile | 3 - arch/cris/include/asm/posix_types.h | 2 + arch/cris/include/asm/signal.h | 1 + arch/cris/kernel/vmlinux.lds.S | 1 + arch/frv/include/asm/thread_info.h | 2 - arch/frv/kernel/process.c | 15 - arch/h8300/include/asm/signal.h | 1 + arch/ia64/include/asm/futex.h | 5 +- arch/ia64/include/asm/mca.h | 1 + arch/ia64/kernel/irq.c | 8 + arch/ia64/kernel/mca.c | 37 +- arch/ia64/kvm/vtlb.c | 2 +- arch/m32r/include/asm/signal.h | 1 + arch/m68k/emu/natfeat.c | 23 +- arch/m68k/include/asm/div64.h | 9 +- arch/m68k/include/asm/signal.h | 1 + arch/m68k/kernel/head.S | 29 +- arch/microblaze/configs/mmu_defconfig | 49 ++- arch/microblaze/configs/nommu_defconfig | 71 ++-- arch/mips/Kconfig | 2 +- arch/mips/include/asm/io.h | 5 + arch/mips/include/asm/page.h | 17 +- arch/mn10300/include/asm/signal.h | 1 + arch/parisc/include/asm/pgtable.h | 13 +- arch/parisc/kernel/cache.c | 18 + arch/powerpc/include/asm/exception-64s.h | 2 +- arch/powerpc/include/asm/module.h | 5 +- arch/powerpc/include/asm/ppc-opcode.h | 4 + arch/powerpc/include/asm/rtas.h | 2 + arch/powerpc/include/asm/signal.h | 1 + arch/powerpc/kernel/cputable.c | 2 +- arch/powerpc/kernel/head_64.S | 1 + arch/powerpc/kernel/irq.c | 2 +- arch/powerpc/kernel/machine_kexec_64.c | 5 + arch/powerpc/kernel/process.c | 4 +- arch/powerpc/kernel/rtas.c | 113 ++++++ arch/powerpc/kernel/traps.c | 10 +- arch/powerpc/kernel/vmlinux.lds.S | 3 - arch/powerpc/mm/hash_utils_64.c | 2 + arch/powerpc/mm/numa.c | 4 +- arch/powerpc/platforms/cell/spufs/inode.c | 1 + arch/powerpc/platforms/pseries/eeh_pseries.c | 12 +- arch/powerpc/platforms/pseries/lpar.c | 8 +- arch/powerpc/platforms/pseries/suspend.c | 22 ++ arch/s390/include/asm/pgtable.h | 4 + arch/s390/include/asm/signal.h | 1 + arch/s390/include/asm/tlbflush.h | 2 - arch/s390/kernel/entry.S | 3 +- arch/s390/kernel/entry64.S | 5 +- arch/s390/kernel/time.c | 3 + arch/s390/kvm/kvm-s390.c | 8 + arch/sparc/include/asm/pgtable_64.h | 1 + arch/sparc/include/asm/signal.h | 1 + arch/sparc/include/asm/switch_to_64.h | 3 +- arch/sparc/include/asm/tlbflush_64.h | 37 +- arch/sparc/kernel/asm-offsets.c | 2 + arch/sparc/kernel/smp_64.c | 41 ++- arch/sparc/lib/Makefile | 2 +- arch/sparc/mm/hypersparc.S | 8 +- arch/sparc/mm/init_64.c | 9 +- arch/sparc/mm/swift.S | 8 +- arch/sparc/mm/tlb.c | 39 +- arch/sparc/mm/tsb.c | 57 ++- arch/sparc/mm/tsunami.S | 6 +- arch/sparc/mm/ultra.S | 119 ++++-- arch/sparc/mm/viking.S | 10 +- arch/tile/kernel/setup.c | 25 +- arch/tile/lib/exports.c | 2 + arch/x86/Kconfig | 4 - arch/x86/boot/compressed/Makefile | 5 +- arch/x86/include/asm/efi.h | 1 + arch/x86/include/asm/kvm_host.h | 4 +- arch/x86/include/asm/mmzone_32.h | 6 - arch/x86/include/asm/paravirt.h | 5 +- arch/x86/include/asm/paravirt_types.h | 2 + arch/x86/include/asm/pgtable.h | 5 + arch/x86/include/asm/signal.h | 2 + arch/x86/include/asm/syscall.h | 4 +- arch/x86/kernel/apic/x2apic_phys.c | 21 +- arch/x86/kernel/cpu/mshyperv.c | 3 +- arch/x86/kernel/cpu/perf_event_intel.c | 15 +- arch/x86/kernel/cpu/perf_event_intel_ds.c | 10 + arch/x86/kernel/cpu/perf_event_intel_lbr.c | 27 +- arch/x86/kernel/head.c | 53 ++- arch/x86/kernel/i387.c | 2 +- arch/x86/kernel/irq.c | 4 - arch/x86/kernel/paravirt.c | 25 +- arch/x86/kernel/reboot.c | 2 +- arch/x86/kernel/relocate_kernel_64.S | 2 +- arch/x86/kernel/setup.c | 28 +- arch/x86/kvm/emulate.c | 4 + arch/x86/kvm/vmx.c | 6 + arch/x86/kvm/x86.c | 48 +-- arch/x86/lguest/boot.c | 1 + arch/x86/lib/usercopy_64.c | 4 +- arch/x86/mm/fault.c | 14 +- arch/x86/mm/init.c | 5 + arch/x86/mm/init_64.c | 3 + arch/x86/mm/numa.c | 32 +- arch/x86/mm/numa_32.c | 161 -------- arch/x86/mm/numa_internal.h | 6 - arch/x86/pci/xen.c | 9 + arch/x86/platform/efi/efi.c | 58 +-- arch/x86/power/cpu.c | 2 + arch/x86/power/hibernate_32.c | 2 - arch/x86/um/sys_call_table_32.c | 4 +- arch/x86/xen/enlighten.c | 30 +- arch/x86/xen/mmu.c | 1 + arch/x86/xen/setup.c | 22 ++ arch/x86/xen/spinlock.c | 1 - arch/x86/xen/time.c | 23 +- arch/x86/xen/xen-asm_32.S | 14 +- arch/xtensa/include/asm/signal.h | 1 + arch/xtensa/kernel/Makefile | 1 + arch/xtensa/kernel/vmlinux.lds.S | 3 +- arch/xtensa/mm/init.c | 6 +- block/genhd.c | 17 +- block/partition-generic.c | 2 +- crypto/ablkcipher.c | 12 +- crypto/aead.c | 9 +- crypto/ahash.c | 2 +- crypto/algapi.c | 3 +- crypto/algif_hash.c | 2 + crypto/algif_skcipher.c | 1 + crypto/blkcipher.c | 6 +- crypto/crypto_user.c | 22 +- crypto/gcm.c | 17 +- crypto/pcompress.c | 3 +- crypto/rng.c | 2 +- crypto/shash.c | 3 +- drivers/acpi/acpi_memhotplug.c | 1 + drivers/acpi/acpica/exfldio.c | 14 +- drivers/acpi/battery.c | 2 + drivers/acpi/ec.c | 8 +- drivers/acpi/osl.c | 2 +- drivers/acpi/pci_root.c | 4 +- drivers/acpi/sleep.c | 8 + drivers/acpi/video.c | 16 + drivers/ata/Kconfig | 2 +- drivers/ata/ahci.c | 1 + drivers/ata/ata_piix.c | 72 +++- drivers/ata/libahci.c | 3 +- drivers/ata/libata-core.c | 10 + drivers/ata/libata-pmp.c | 45 +-- drivers/ata/sata_inic162x.c | 14 + drivers/atm/iphase.h | 146 ++++---- drivers/base/bus.c | 4 +- drivers/base/dd.c | 2 + drivers/base/regmap/regcache-rbtree.c | 2 +- drivers/block/aoe/aoecmd.c | 3 +- drivers/block/brd.c | 4 +- drivers/block/cciss.c | 32 +- drivers/block/drbd/drbd_receiver.c | 1 - drivers/block/loop.c | 33 +- drivers/block/nbd.c | 3 +- drivers/block/sunvdc.c | 2 +- drivers/block/xen-blkback/blkback.c | 51 ++- drivers/block/xen-blkback/common.h | 25 ++ drivers/block/xen-blkback/xenbus.c | 49 ++- drivers/bluetooth/ath3k.c | 14 + drivers/bluetooth/btusb.c | 7 + drivers/cdrom/cdrom.c | 2 +- drivers/char/hpet.c | 14 +- drivers/char/hw_random/core.c | 19 +- drivers/char/hw_random/virtio-rng.c | 13 +- drivers/char/ipmi/ipmi_bt_sm.c | 4 +- drivers/char/ipmi/ipmi_devintf.c | 14 +- drivers/char/virtio_console.c | 50 ++- drivers/clk/clk.c | 1 + drivers/cpufreq/longhaul.c | 10 +- drivers/dca/dca-core.c | 5 + drivers/dma/pch_dma.c | 2 +- drivers/dma/pl330.c | 4 +- drivers/eisa/pci_eisa.c | 67 ++-- drivers/firewire/core-cdev.c | 3 + drivers/firewire/core-device.c | 4 + drivers/firewire/ohci.c | 10 +- drivers/firmware/dmi_scan.c | 7 +- drivers/firmware/efivars.c | 97 ++++- drivers/firmware/iscsi_ibft_find.c | 2 +- drivers/gpu/drm/drm_crtc.c | 3 +- drivers/gpu/drm/drm_edid.c | 6 +- drivers/gpu/drm/drm_irq.c | 6 +- drivers/gpu/drm/drm_mm.c | 34 +- drivers/gpu/drm/drm_usb.c | 2 +- drivers/gpu/drm/gma500/cdv_intel_display.c | 14 + drivers/gpu/drm/gma500/framebuffer.c | 4 +- drivers/gpu/drm/gma500/psb_intel_display.c | 14 + drivers/gpu/drm/i915/i915_debugfs.c | 2 +- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_gem.c | 5 + drivers/gpu/drm/i915/i915_gem_execbuffer.c | 11 +- drivers/gpu/drm/i915/i915_gem_gtt.c | 2 +- drivers/gpu/drm/i915/i915_reg.h | 2 + drivers/gpu/drm/i915/intel_display.c | 41 ++- drivers/gpu/drm/i915/intel_dvo.c | 13 +- drivers/gpu/drm/i915/intel_lvds.c | 23 +- drivers/gpu/drm/i915/intel_opregion.c | 23 +- drivers/gpu/drm/i915/intel_ringbuffer.c | 12 + drivers/gpu/drm/i915/intel_sdvo.c | 12 +- drivers/gpu/drm/radeon/atom.c | 11 +- drivers/gpu/drm/radeon/atombios_crtc.c | 6 +- drivers/gpu/drm/radeon/atombios_dp.c | 43 ++- drivers/gpu/drm/radeon/atombios_encoders.c | 11 +- drivers/gpu/drm/radeon/evergreen.c | 81 ++++- drivers/gpu/drm/radeon/evergreen_reg.h | 2 + drivers/gpu/drm/radeon/ni.c | 27 +- drivers/gpu/drm/radeon/nid.h | 4 + drivers/gpu/drm/radeon/r100.c | 9 +- drivers/gpu/drm/radeon/r300.c | 9 +- drivers/gpu/drm/radeon/r300_cmdbuf.c | 2 +- drivers/gpu/drm/radeon/r420.c | 10 +- drivers/gpu/drm/radeon/r520.c | 9 +- drivers/gpu/drm/radeon/r600.c | 10 +- drivers/gpu/drm/radeon/radeon_atombios.c | 21 +- drivers/gpu/drm/radeon/radeon_benchmark.c | 16 +- drivers/gpu/drm/radeon/radeon_combios.c | 160 +++----- drivers/gpu/drm/radeon/radeon_device.c | 22 +- drivers/gpu/drm/radeon/radeon_pm.c | 6 +- drivers/gpu/drm/radeon/radeon_ttm.c | 2 +- drivers/gpu/drm/radeon/rs400.c | 9 +- drivers/gpu/drm/radeon/rs600.c | 9 +- drivers/gpu/drm/radeon/rs690.c | 9 +- drivers/gpu/drm/radeon/rv515.c | 9 +- drivers/gpu/drm/radeon/rv770.c | 10 +- drivers/gpu/drm/radeon/si.c | 15 +- drivers/gpu/drm/radeon/sid.h | 2 + drivers/gpu/drm/udl/udl_connector.c | 4 + drivers/gpu/drm/udl/udl_drv.h | 2 + drivers/gpu/drm/udl/udl_fb.c | 48 ++- drivers/gpu/vga/vga_switcheroo.c | 3 + drivers/hid/hid-core.c | 1 + drivers/hid/hid-ids.h | 6 + drivers/hid/hid-microsoft.c | 6 +- drivers/hid/hid-wiimote-ext.c | 8 +- drivers/hid/usbhid/hid-quirks.c | 1 + drivers/hwmon/abituguru.c | 16 +- drivers/hwmon/adm1021.c | 58 ++- drivers/hwmon/adt7470.c | 2 +- drivers/hwmon/lineage-pem.c | 2 + drivers/hwmon/pmbus/ltc2978.c | 40 +- drivers/hwmon/sht15.c | 8 +- drivers/hwspinlock/hwspinlock_core.c | 2 + drivers/i2c/busses/i2c-designware-core.c | 3 +- drivers/i2c/busses/i2c-xiic.c | 6 +- drivers/infiniband/ulp/ipoib/ipoib_cm.c | 8 +- drivers/input/touchscreen/cyttsp_core.c | 2 +- drivers/iommu/amd_iommu.c | 59 ++- drivers/iommu/amd_iommu_init.c | 9 +- drivers/iommu/amd_iommu_types.h | 1 + drivers/iommu/intel-iommu.c | 8 +- drivers/isdn/gigaset/capi.c | 2 + drivers/leds/leds-ot200.c | 14 +- drivers/md/dm-snap.c | 1 + drivers/md/dm-thin.c | 2 +- drivers/md/dm-verity.c | 5 +- drivers/md/md.c | 9 +- drivers/md/raid1.c | 34 +- drivers/md/raid10.c | 34 +- drivers/md/raid5.c | 15 +- drivers/md/raid5.h | 1 + drivers/media/dvb/mantis/mantis_dvb.c | 6 +- drivers/media/rc/rc-main.c | 4 +- drivers/mfd/adp5520.c | 8 +- drivers/mmc/core/mmc.c | 2 +- drivers/mmc/host/Kconfig | 10 - drivers/mmc/host/atmel-mci.c | 16 +- drivers/mmc/host/sdhci-esdhc-imx.c | 19 +- drivers/mtd/mtdchar.c | 56 +-- drivers/net/arcnet/arcnet.c | 2 +- drivers/net/bonding/bond_alb.c | 6 + drivers/net/bonding/bond_main.c | 107 ++---- drivers/net/bonding/bond_sysfs.c | 121 +++--- drivers/net/bonding/bonding.h | 13 + drivers/net/can/sja1000/plx_pci.c | 4 +- drivers/net/can/sja1000/sja1000.c | 6 +- drivers/net/can/sja1000/sja1000.h | 2 +- drivers/net/can/sja1000/sja1000_of_platform.c | 31 +- drivers/net/can/usb/peak_usb/pcan_usb.c | 2 +- drivers/net/dummy.c | 4 + drivers/net/ethernet/3com/3c509.c | 2 + drivers/net/ethernet/3com/3c59x.c | 27 +- drivers/net/ethernet/atheros/atl1e/atl1e.h | 3 +- .../net/ethernet/atheros/atl1e/atl1e_main.c | 73 ++-- .../net/ethernet/broadcom/bnx2x/bnx2x_stats.h | 3 +- drivers/net/ethernet/broadcom/tg3.c | 77 ++-- drivers/net/ethernet/calxeda/xgmac.c | 4 + drivers/net/ethernet/davicom/dm9000.c | 214 +++++------ drivers/net/ethernet/davicom/dm9000.h | 11 +- drivers/net/ethernet/emulex/benet/be.h | 5 + drivers/net/ethernet/emulex/benet/be_main.c | 56 ++- drivers/net/ethernet/freescale/gianfar_ptp.c | 4 +- drivers/net/ethernet/ibm/ibmveth.c | 23 +- drivers/net/ethernet/intel/e1000e/netdev.c | 2 +- drivers/net/ethernet/intel/igb/igb_main.c | 8 +- .../ethernet/intel/ixgbe/ixgbe_dcb_82598.c | 3 +- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 10 + drivers/net/ethernet/marvell/sky2.c | 2 +- drivers/net/ethernet/marvell/sky2.h | 2 +- drivers/net/ethernet/mellanox/mlx4/en_tx.c | 13 +- drivers/net/ethernet/mellanox/mlx4/main.c | 11 +- drivers/net/ethernet/micrel/ks8851.c | 2 +- .../ethernet/oki-semi/pch_gbe/pch_gbe_main.c | 4 +- .../ethernet/qlogic/netxen/netxen_nic_init.c | 2 +- .../ethernet/qlogic/netxen/netxen_nic_main.c | 2 + drivers/net/ethernet/realtek/8139cp.c | 49 ++- drivers/net/ethernet/realtek/r8169.c | 83 +++-- drivers/net/ethernet/renesas/sh_eth.c | 17 +- drivers/net/ethernet/renesas/sh_eth.h | 2 +- drivers/net/ethernet/sfc/bitfield.h | 22 +- drivers/net/ethernet/sfc/efx.c | 53 ++- drivers/net/ethernet/sfc/efx.h | 13 + drivers/net/ethernet/sfc/falcon.c | 37 +- drivers/net/ethernet/sfc/mcdi.c | 35 +- drivers/net/ethernet/sfc/mcdi.h | 6 +- drivers/net/ethernet/sfc/net_driver.h | 14 +- drivers/net/ethernet/sfc/nic.c | 65 +++- drivers/net/ethernet/sfc/nic.h | 2 + drivers/net/ethernet/sfc/rx.c | 25 +- drivers/net/ethernet/sfc/selftest.c | 64 +--- drivers/net/ethernet/sfc/siena.c | 44 ++- drivers/net/ethernet/sfc/siena_sriov.c | 13 +- drivers/net/ethernet/sun/sunvnet.c | 2 + drivers/net/ethernet/ti/cpsw.c | 2 +- drivers/net/ethernet/ti/davinci_emac.c | 2 +- drivers/net/ethernet/via/via-rhine.c | 8 +- drivers/net/ifb.c | 8 +- drivers/net/loopback.c | 5 + drivers/net/macvlan.c | 8 +- drivers/net/macvtap.c | 14 +- drivers/net/netconsole.c | 20 +- drivers/net/team/team_mode_roundrobin.c | 2 + drivers/net/tun.c | 2 + drivers/net/usb/qmi_wwan.c | 101 ++++++ drivers/net/usb/smsc75xx.c | 24 +- drivers/net/virtio_net.c | 5 +- drivers/net/wan/dlci.c | 26 +- drivers/net/wireless/ath/ath9k/Kconfig | 10 +- drivers/net/wireless/ath/ath9k/Makefile | 2 +- drivers/net/wireless/ath/ath9k/ar9003_calib.c | 6 + drivers/net/wireless/ath/ath9k/ar9003_phy.c | 2 +- .../wireless/ath/ath9k/ar9580_1p0_initvals.h | 2 +- drivers/net/wireless/ath/ath9k/calib.c | 1 - drivers/net/wireless/ath/ath9k/common.h | 2 +- drivers/net/wireless/ath/ath9k/htc_drv_init.c | 3 +- drivers/net/wireless/ath/ath9k/hw.c | 4 +- drivers/net/wireless/ath/ath9k/hw.h | 1 + drivers/net/wireless/ath/ath9k/init.c | 7 +- drivers/net/wireless/ath/ath9k/main.c | 6 +- drivers/net/wireless/ath/ath9k/rc.h | 2 +- drivers/net/wireless/b43/dma.c | 84 ++++- drivers/net/wireless/b43/dma.h | 6 +- drivers/net/wireless/b43/main.c | 45 +-- drivers/net/wireless/b43/phy_n.c | 11 +- drivers/net/wireless/hostap/hostap_ioctl.c | 4 +- drivers/net/wireless/iwlegacy/4965-mac.c | 16 +- drivers/net/wireless/iwlegacy/common.c | 1 + drivers/net/wireless/mwifiex/cmdevt.c | 1 + drivers/net/wireless/mwifiex/join.c | 7 +- drivers/net/wireless/mwifiex/pcie.c | 6 +- drivers/net/wireless/mwifiex/sdio.c | 4 +- drivers/net/wireless/mwifiex/sta_ioctl.c | 21 +- drivers/net/wireless/p54/p54usb.c | 2 +- drivers/net/wireless/rt2x00/rt2800lib.c | 4 +- drivers/net/wireless/rt2x00/rt2x00dev.c | 2 + drivers/net/wireless/rt2x00/rt2x00pci.c | 4 +- drivers/net/wireless/rt2x00/rt2x00queue.c | 18 +- drivers/net/wireless/rt2x00/rt61pci.c | 3 +- drivers/net/wireless/rt2x00/rt73usb.c | 3 +- drivers/net/wireless/rtlwifi/base.c | 7 +- drivers/net/wireless/rtlwifi/rtl8192cu/hw.c | 89 ++--- drivers/net/wireless/rtlwifi/rtl8192cu/rf.c | 2 +- drivers/net/wireless/rtlwifi/rtl8192cu/sw.c | 2 + drivers/net/wireless/rtlwifi/usb.c | 49 ++- drivers/net/wireless/zd1201.c | 4 +- drivers/net/xen-netback/common.h | 3 + drivers/net/xen-netback/interface.c | 26 +- drivers/net/xen-netback/netback.c | 128 ++++--- drivers/of/fdt.c | 2 + drivers/pci/pci.c | 12 +- drivers/pci/quirks.c | 2 + drivers/pci/remove.c | 2 + drivers/pcmcia/at91_cf.c | 4 +- drivers/pcmcia/vrc4171_card.c | 1 + drivers/platform/x86/asus-laptop.c | 17 +- drivers/platform/x86/hp_accel.c | 3 +- drivers/platform/x86/ibm_rtl.c | 2 +- drivers/platform/x86/samsung-laptop.c | 4 + drivers/platform/x86/thinkpad_acpi.c | 7 + drivers/power/ab8500_btemp.c | 2 +- drivers/power/abx500_chargalg.c | 2 +- drivers/power/charger-manager.c | 2 +- drivers/rtc/rtc-cmos.c | 4 +- drivers/rtc/rtc-pcf2123.c | 1 + drivers/rtc/rtc-rv3029c2.c | 2 +- drivers/rtc/rtc-twl.c | 1 + drivers/s390/char/sclp_cmd.c | 4 +- drivers/s390/kvm/kvm_virtio.c | 38 +- drivers/s390/scsi/zfcp_aux.c | 5 +- drivers/s390/scsi/zfcp_erp.c | 29 +- drivers/s390/scsi/zfcp_fsf.c | 27 +- drivers/s390/scsi/zfcp_qdio.c | 8 +- drivers/s390/scsi/zfcp_scsi.c | 10 +- drivers/scsi/bnx2fc/bnx2fc_io.c | 2 +- drivers/scsi/dc395x.c | 2 +- drivers/scsi/isci/init.c | 2 +- drivers/scsi/libsas/sas_expander.c | 12 + drivers/scsi/megaraid/megaraid_sas_base.c | 30 +- drivers/scsi/mpt2sas/mpt2sas_scsih.c | 6 +- drivers/scsi/nsp32.c | 2 +- drivers/scsi/osd/osd_uld.c | 2 +- drivers/scsi/qla2xxx/qla_iocb.c | 11 +- drivers/scsi/scsi.c | 3 + drivers/scsi/sd.c | 42 ++- drivers/scsi/sd.h | 1 + drivers/scsi/storvsc_drv.c | 1 + drivers/spi/spi-mpc512x-psc.c | 2 +- drivers/spi/spi-s3c64xx.c | 41 ++- drivers/ssb/driver_chipcommon_pmu.c | 29 ++ drivers/staging/comedi/comedi_fops.c | 20 +- drivers/staging/comedi/drivers/ni_labpc.c | 35 +- drivers/staging/comedi/drivers/s626.c | 2 +- drivers/staging/vt6656/hostap.c | 2 +- drivers/staging/vt6656/main_usb.c | 4 - drivers/staging/vt6656/usbpipe.c | 28 +- drivers/target/iscsi/iscsi_target_auth.c | 5 +- drivers/target/iscsi/iscsi_target_configfs.c | 2 +- drivers/target/iscsi/iscsi_target_erl0.c | 4 +- drivers/target/iscsi/iscsi_target_erl1.c | 7 +- .../target/iscsi/iscsi_target_parameters.c | 8 +- .../target/iscsi/iscsi_target_parameters.h | 4 +- drivers/target/target_core_alua.c | 3 + drivers/target/target_core_device.c | 21 +- drivers/target/target_core_fabric_configfs.c | 12 +- drivers/target/target_core_internal.h | 2 +- drivers/target/target_core_pscsi.c | 1 - drivers/target/target_core_tpg.c | 10 +- drivers/thermal/thermal_sys.c | 1 + drivers/tty/n_gsm.c | 42 ++- drivers/tty/n_tty.c | 8 + drivers/tty/pty.c | 4 +- drivers/tty/serial/Kconfig | 2 +- drivers/tty/serial/atmel_serial.c | 11 +- drivers/tty/serial/mxs-auart.c | 38 +- drivers/tty/serial/pch_uart.c | 29 +- drivers/tty/serial/serial_core.c | 4 + drivers/tty/serial/sunsu.c | 21 +- drivers/tty/tty_io.c | 14 +- drivers/tty/tty_ioctl.c | 4 +- drivers/tty/vt/vc_screen.c | 6 +- drivers/tty/vt/vt.c | 134 +++++-- drivers/usb/atm/cxacru.c | 3 +- drivers/usb/class/cdc-acm.c | 3 +- drivers/usb/class/cdc-wdm.c | 23 +- drivers/usb/core/devio.c | 2 + drivers/usb/core/hcd-pci.c | 23 +- drivers/usb/core/hub.c | 190 +++++----- drivers/usb/core/quirks.c | 9 + drivers/usb/dwc3/core.h | 4 +- drivers/usb/dwc3/gadget.c | 1 + drivers/usb/gadget/f_mass_storage.c | 2 + drivers/usb/gadget/udc-core.c | 2 +- drivers/usb/host/ehci-omap.c | 2 +- drivers/usb/host/ehci-sched.c | 2 +- drivers/usb/host/uhci-hub.c | 3 +- drivers/usb/host/xhci-mem.c | 31 +- drivers/usb/host/xhci-pci.c | 1 - drivers/usb/host/xhci-ring.c | 49 +-- drivers/usb/host/xhci.c | 28 +- drivers/usb/host/xhci.h | 8 +- drivers/usb/misc/appledisplay.c | 1 + drivers/usb/misc/sisusbvga/sisusb.c | 1 + drivers/usb/serial/ark3116.c | 2 +- drivers/usb/serial/cp210x.c | 24 ++ drivers/usb/serial/cypress_m8.c | 18 +- drivers/usb/serial/cypress_m8.h | 4 + drivers/usb/serial/ftdi_sio.c | 61 +++- drivers/usb/serial/ftdi_sio_ids.h | 47 ++- drivers/usb/serial/garmin_gps.c | 7 +- drivers/usb/serial/io_ti.c | 4 + drivers/usb/serial/iuu_phoenix.c | 4 +- drivers/usb/serial/keyspan.c | 2 +- drivers/usb/serial/mct_u232.c | 22 +- drivers/usb/serial/mos7720.c | 46 ++- drivers/usb/serial/option.c | 63 +++- drivers/usb/serial/qcaux.c | 1 + drivers/usb/serial/qcserial.c | 8 +- drivers/usb/serial/sierra.c | 8 +- drivers/usb/serial/ssu100.c | 19 +- drivers/usb/serial/ti_usb_3410_5052.c | 5 +- drivers/usb/serial/ti_usb_3410_5052.h | 4 +- drivers/usb/serial/usb-serial.c | 17 +- drivers/usb/serial/usb_wwan.c | 8 +- drivers/usb/serial/visor.c | 9 + drivers/usb/serial/whiteheat.c | 2 +- drivers/usb/storage/cypress_atacb.c | 16 +- drivers/usb/storage/initializers.c | 76 +--- drivers/usb/storage/initializers.h | 4 +- drivers/usb/storage/unusual_cypress.h | 2 +- drivers/usb/storage/unusual_devs.h | 343 +++++++++++++++++- drivers/vhost/net.c | 3 +- drivers/vhost/vhost.c | 2 +- drivers/video/atmel_lcdfb.c | 22 +- drivers/video/backlight/adp8860_bl.c | 2 +- drivers/video/backlight/adp8870_bl.c | 2 +- drivers/video/console/fbcon.c | 60 ++- drivers/video/console/vgacon.c | 22 +- drivers/video/fbmem.c | 11 +- drivers/video/fbsysfs.c | 3 + drivers/video/fsl-diu-fb.c | 6 +- drivers/w1/w1.c | 3 +- drivers/xen/events.c | 21 +- drivers/xen/evtchn.c | 31 +- drivers/xen/xen-pciback/pciback_ops.c | 19 +- fs/aio.c | 2 +- fs/autofs4/expire.c | 9 - fs/binfmt_em86.c | 1 - fs/binfmt_misc.c | 6 - fs/binfmt_script.c | 4 +- fs/block_dev.c | 15 +- fs/btrfs/extent-tree.c | 62 +++- fs/btrfs/extent_io.c | 33 ++ fs/btrfs/extent_io.h | 2 + fs/btrfs/inode.c | 14 + fs/btrfs/ioctl.c | 10 +- fs/btrfs/scrub.c | 3 +- fs/btrfs/tree-log.c | 48 ++- fs/btrfs/volumes.c | 7 + fs/ceph/locks.c | 73 ++-- fs/ceph/mds_client.c | 90 ++--- fs/ceph/super.c | 7 +- fs/ceph/super.h | 11 +- fs/cifs/asn1.c | 53 +-- fs/cifs/cifs_dfs_ref.c | 4 +- fs/cifs/cifs_unicode.h | 8 +- fs/cifs/cifsencrypt.c | 8 +- fs/cifs/cifsfs.c | 5 + fs/cifs/cifsglob.h | 1 + fs/cifs/connect.c | 23 +- fs/cifs/inode.c | 8 +- fs/cifs/sess.c | 6 +- fs/compat.c | 15 +- fs/dcache.c | 6 +- fs/debugfs/inode.c | 69 ++-- fs/direct-io.c | 2 +- fs/exec.c | 30 +- fs/ext3/inode.c | 3 +- fs/ext3/namei.c | 7 +- fs/ext3/super.c | 4 +- fs/ext4/Kconfig | 3 +- fs/ext4/balloc.c | 15 +- fs/ext4/ext4.h | 6 +- fs/ext4/ext4_jbd2.c | 8 +- fs/ext4/ext4_jbd2.h | 6 +- fs/ext4/extents.c | 10 +- fs/ext4/ialloc.c | 14 +- fs/ext4/inode.c | 7 +- fs/ext4/mballoc.c | 49 ++- fs/ext4/namei.c | 7 +- fs/ext4/resize.c | 14 +- fs/ext4/super.c | 28 +- fs/ext4/xattr.c | 7 +- fs/fat/inode.c | 15 +- fs/fscache/stats.c | 2 +- fs/fuse/dir.c | 9 +- fs/hfsplus/extents.c | 2 +- fs/hpfs/map.c | 3 +- fs/hpfs/super.c | 8 +- fs/hugetlbfs/inode.c | 20 +- fs/inode.c | 2 +- fs/isofs/export.c | 1 + fs/jbd2/commit.c | 50 +-- fs/jbd2/transaction.c | 17 +- fs/jfs/inode.c | 2 +- fs/jfs/jfs_logmgr.c | 3 +- fs/lockd/clntlock.c | 3 + fs/lockd/svclock.c | 4 + fs/nfs/blocklayout/blocklayout.c | 1 + fs/nfs/blocklayout/blocklayoutdm.c | 4 +- fs/nfs/nfs4proc.c | 8 +- fs/nfs/objlayout/objio_osd.c | 1 + fs/nfs/unlink.c | 20 +- fs/nfsd/nfs4proc.c | 15 +- fs/nfsd/nfs4state.c | 10 +- fs/nfsd/nfs4xdr.c | 23 +- fs/nilfs2/inode.c | 27 +- fs/nilfs2/segbuf.c | 5 +- fs/notify/fanotify/fanotify_user.c | 1 + fs/notify/inotify/inotify_user.c | 10 +- fs/ocfs2/aops.c | 2 +- fs/ocfs2/dlmglue.c | 5 +- fs/ocfs2/extent_map.c | 2 +- fs/ocfs2/suballoc.c | 7 +- fs/ocfs2/suballoc.h | 2 +- fs/ocfs2/xattr.c | 12 +- fs/pipe.c | 3 + fs/proc/task_mmu.c | 8 +- fs/pstore/platform.c | 35 +- fs/reiserfs/xattr.c | 4 +- fs/super.c | 25 +- fs/sysfs/dir.c | 32 +- fs/ubifs/dir.c | 54 ++- fs/ubifs/super.c | 12 +- fs/udf/namei.c | 1 + fs/udf/udf_sb.h | 2 +- fs/xfs/xfs_iops.c | 47 ++- include/asm-generic/pgtable.h | 10 + include/asm-generic/signal.h | 4 + include/drm/drm_pciids.h | 18 +- include/linux/ata.h | 2 +- include/linux/audit.h | 2 +- include/linux/auto_fs.h | 25 +- include/linux/binfmts.h | 2 - include/linux/ceph/auth.h | 18 + include/linux/console.h | 2 + include/linux/cpu.h | 4 + include/linux/efi.h | 24 +- include/linux/firewire-cdev.h | 4 +- include/linux/firewire.h | 1 + include/linux/ftrace.h | 3 +- include/linux/ftrace_event.h | 4 +- include/linux/hugetlb.h | 25 +- include/linux/if_cablemodem.h | 12 +- include/linux/if_pppox.h | 4 +- include/linux/if_vlan.h | 6 +- include/linux/ipc_namespace.h | 2 +- include/linux/jbd2.h | 1 + include/linux/kvm_host.h | 2 +- include/linux/kvm_types.h | 1 + include/linux/libata.h | 1 + include/linux/mmu_notifier.h | 1 + include/linux/netdevice.h | 2 +- include/linux/perf_event.h | 9 +- include/linux/preempt.h | 22 +- include/linux/pstore.h | 6 + include/linux/quota.h | 1 + include/linux/rculist.h | 17 + include/linux/rculist_nulls.h | 7 +- include/linux/skbuff.h | 14 +- include/linux/socket.h | 6 +- include/linux/spinlock_up.h | 29 +- include/linux/ssb/ssb_driver_chipcommon.h | 2 + include/linux/swapops.h | 3 + include/linux/thermal.h | 2 +- include/linux/unix_diag.h | 4 +- include/linux/usb/audio.h | 6 +- include/linux/vt_kern.h | 3 + include/linux/wait.h | 73 +++- include/net/addrconf.h | 3 + include/net/inet_frag.h | 9 + include/net/ip_fib.h | 12 +- include/net/scm.h | 2 +- include/net/sock.h | 14 +- include/net/tcp.h | 1 + include/net/udp.h | 1 + include/video/atmel_lcdc.h | 1 + include/xen/interface/io/blkif.h | 10 + init/main.c | 4 +- ipc/shm.c | 6 +- kernel/audit_tree.c | 2 +- kernel/cgroup.c | 2 +- kernel/cpu.c | 55 ++- kernel/cpuset.c | 12 +- kernel/events/core.c | 291 +++++++++++---- kernel/events/hw_breakpoint.c | 4 +- kernel/events/internal.h | 4 + kernel/futex.c | 5 +- kernel/futex_compat.c | 2 - kernel/hrtimer.c | 34 +- kernel/irq/manage.c | 6 +- kernel/irq/spurious.c | 7 +- kernel/kmod.c | 5 + kernel/panic.c | 8 + kernel/posix-cpu-timers.c | 23 +- kernel/posix-timers.c | 7 + kernel/resource.c | 50 ++- kernel/sched/clock.c | 26 ++ kernel/sched/fair.c | 2 +- kernel/signal.c | 4 +- kernel/sys.c | 30 +- kernel/sysctl_binary.c | 3 +- kernel/time/tick-broadcast.c | 17 +- kernel/time/tick-common.c | 1 + kernel/time/tick-sched.c | 10 +- kernel/timeconst.pl | 6 +- kernel/timer.c | 8 +- kernel/trace/Kconfig | 24 +- kernel/trace/ftrace.c | 100 ++--- kernel/trace/trace.c | 128 ++++--- kernel/trace/trace.h | 7 + kernel/trace/trace_events_filter.c | 4 + kernel/trace/trace_irqsoff.c | 19 +- kernel/trace/trace_sched_wakeup.c | 18 +- kernel/trace/trace_selftest.c | 9 +- kernel/trace/trace_stack.c | 78 +++- kernel/trace/trace_stat.c | 2 + kernel/trace/trace_syscalls.c | 21 +- kernel/workqueue.c | 67 +++- lib/idr.c | 9 +- lib/kobject.c | 9 +- mm/fadvise.c | 18 +- mm/huge_memory.c | 7 +- mm/hugetlb.c | 39 +- mm/migrate.c | 25 +- mm/mmap.c | 12 +- mm/mmu_notifier.c | 121 +++--- mm/nommu.c | 12 +- mm/page_alloc.c | 19 +- mm/pagewalk.c | 70 ++-- mm/process_vm_access.c | 8 - mm/shmem.c | 10 +- mm/swap_state.c | 18 +- net/8021q/vlan.c | 14 +- net/8021q/vlan_dev.c | 9 +- net/9p/trans_common.c | 10 +- net/atm/common.c | 2 + net/ax25/af_ax25.c | 1 + net/bluetooth/af_bluetooth.c | 4 +- net/bluetooth/rfcomm/sock.c | 1 + net/bluetooth/sco.c | 1 + net/bridge/br_multicast.c | 5 +- net/bridge/br_netfilter.c | 3 + net/bridge/br_stp_bpdu.c | 2 + net/bridge/br_stp_timer.c | 2 +- net/caif/caif_socket.c | 2 + net/can/gw.c | 6 +- net/ceph/auth.c | 117 +++++- net/ceph/auth_none.c | 6 + net/ceph/auth_x.c | 24 +- net/ceph/auth_x.h | 1 + net/ceph/messenger.c | 3 +- net/ceph/mon_client.c | 7 +- net/ceph/osd_client.c | 29 +- net/compat.c | 13 +- net/core/datagram.c | 2 +- net/core/dev.c | 14 +- net/core/dev_addr_lists.c | 6 +- net/core/ethtool.c | 2 +- net/core/neighbour.c | 12 +- net/core/pktgen.c | 9 +- net/core/rtnetlink.c | 7 +- net/core/sock.c | 26 +- net/dcb/dcbnl.c | 7 + net/ieee802154/6lowpan.h | 2 +- net/ipv4/esp4.c | 6 +- net/ipv4/inet_fragment.c | 20 +- net/ipv4/ip_fragment.c | 26 +- net/ipv4/ip_gre.c | 2 +- net/ipv4/ip_options.c | 5 +- net/ipv4/ip_sockglue.c | 2 +- net/ipv4/ipip.c | 2 +- net/ipv4/ping.c | 4 +- net/ipv4/syncookies.c | 4 +- net/ipv4/sysctl_net_ipv4.c | 6 +- net/ipv4/tcp.c | 9 +- net/ipv4/tcp_input.c | 106 +++--- net/ipv4/tcp_ipv4.c | 4 +- net/ipv4/tcp_output.c | 26 +- net/ipv4/udp.c | 3 +- net/ipv6/addrconf.c | 88 +++-- net/ipv6/ip6_input.c | 24 +- net/ipv6/ip6_output.c | 30 +- net/ipv6/ip6mr.c | 5 + net/ipv6/mcast.c | 18 +- net/ipv6/netfilter/nf_conntrack_reasm.c | 11 +- net/ipv6/reassembly.c | 21 +- net/ipv6/route.c | 12 +- net/ipv6/tcp_ipv6.c | 12 + net/ipv6/udp.c | 20 +- net/ipv6/udp_impl.h | 2 + net/ipv6/udplite.c | 2 +- net/ipv6/xfrm6_policy.c | 4 +- net/irda/af_irda.c | 8 +- net/iucv/af_iucv.c | 2 + net/key/af_key.c | 7 + net/l2tp/l2tp_ppp.c | 10 +- net/llc/af_llc.c | 2 + net/mac80211/iface.c | 9 + net/mac80211/rx.c | 10 +- net/netfilter/ipvs/ip_vs_pe_sip.c | 6 +- net/netlabel/netlabel_domainhash.c | 69 ++++ net/netlabel/netlabel_unlabeled.c | 27 +- net/netlink/genetlink.c | 1 + net/netrom/af_netrom.c | 1 + net/nfc/llcp/sock.c | 2 + net/packet/af_packet.c | 69 ++-- net/rds/message.c | 3 + net/rose/af_rose.c | 1 + net/sched/act_ipt.c | 33 +- net/sched/sch_atm.c | 1 + net/sched/sch_cbq.c | 6 +- net/sctp/associola.c | 2 +- net/sctp/auth.c | 2 +- net/sctp/endpointola.c | 5 + net/sctp/outqueue.c | 20 +- net/sctp/sm_statefuns.c | 2 +- net/sctp/socket.c | 8 +- net/socket.c | 67 ++-- net/sunrpc/sched.c | 9 +- net/sunrpc/svc_xprt.c | 15 +- net/sunrpc/xprt.c | 6 +- net/tipc/socket.c | 7 + net/unix/af_unix.c | 9 +- net/wireless/nl80211.c | 7 +- net/wireless/reg.c | 2 +- net/x25/af_x25.c | 15 +- security/keys/compat.c | 4 +- security/keys/keyctl.c | 4 +- security/keys/process_keys.c | 2 +- security/selinux/xfrm.c | 2 +- sound/core/pcm_native.c | 12 +- sound/core/seq/seq_timer.c | 8 +- sound/core/vmaster.c | 5 +- sound/oss/Kconfig | 1 + sound/pci/ali5451/ali5451.c | 2 +- sound/pci/hda/hda_codec.c | 7 +- sound/pci/hda/hda_eld.c | 2 +- sound/pci/hda/patch_conexant.c | 8 +- sound/pci/hda/patch_hdmi.c | 7 +- sound/pci/hda/patch_realtek.c | 5 +- sound/pci/ice1712/ice1712.c | 2 + sound/pci/rme32.c | 2 +- sound/soc/codecs/max98088.c | 4 +- sound/soc/codecs/sgtl5000.h | 2 +- sound/soc/codecs/wm2200.c | 4 +- sound/soc/codecs/wm8903.c | 2 + sound/soc/codecs/wm8962.c | 24 +- sound/soc/codecs/wm8994.c | 1 + sound/soc/sh/dma-sh7760.c | 4 +- sound/usb/6fire/pcm.c | 2 +- sound/usb/card.c | 26 +- sound/usb/midi.c | 13 +- sound/usb/mixer.c | 18 +- sound/usb/mixer_quirks.c | 4 +- sound/usb/quirks-table.h | 16 +- sound/usb/quirks.c | 2 +- sound/usb/stream.c | 8 + tools/hv/hv_kvp_daemon.c | 8 +- tools/perf/Makefile | 4 +- tools/perf/scripts/python/net_dropmonitor.py | 8 +- tools/perf/util/map.c | 3 +- tools/perf/util/parse-events.y | 1 - tools/perf/util/pmu.y | 1 - virt/kvm/ioapic.c | 7 +- virt/kvm/kvm_main.c | 47 ++- 885 files changed, 9032 insertions(+), 4458 deletions(-) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 9a1c759cee0..f1e7e5851e9 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -566,6 +566,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted. UART at the specified I/O port or MMIO address, switching to the matching ttyS device later. The options are the same as for ttyS, above. + hvc Use the hypervisor console device . This is for + both Xen and PowerPC hypervisors. If the device connected to the port is not a TTY but a braille device, prepend "brl," before the device type, for instance @@ -751,6 +753,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted. earlyprintk= [X86,SH,BLACKFIN] earlyprintk=vga + earlyprintk=xen earlyprintk=serial[,ttySn[,baudrate]] earlyprintk=ttySn[,baudrate] earlyprintk=dbgp[debugController#] @@ -768,6 +771,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted. The VGA output is eventually overwritten by the real console. + The xen output can only be used by Xen PV guests. + ekgdboc= [X86,KGDB] Allow early kernel console debugging ekgdboc=kbd diff --git a/MAINTAINERS b/MAINTAINERS index c56bd02248d..b0b614fb3df 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2627,7 +2627,7 @@ S: Maintained F: drivers/net/ethernet/i825xx/eexpress.* ETHERNET BRIDGE -M: Stephen Hemminger +M: Stephen Hemminger L: bridge@lists.linux-foundation.org L: netdev@vger.kernel.org W: http://www.linuxfoundation.org/en/Net:Bridge @@ -4312,7 +4312,7 @@ S: Maintained MARVELL GIGABIT ETHERNET DRIVERS (skge/sky2) M: Mirko Lindner -M: Stephen Hemminger +M: Stephen Hemminger L: netdev@vger.kernel.org S: Maintained F: drivers/net/ethernet/marvell/sk* @@ -4563,7 +4563,7 @@ S: Supported F: drivers/infiniband/hw/nes/ NETEM NETWORK EMULATOR -M: Stephen Hemminger +M: Stephen Hemminger L: netem@lists.linux-foundation.org S: Maintained F: net/sched/sch_netem.c @@ -6390,6 +6390,7 @@ STABLE BRANCH M: Greg Kroah-Hartman L: stable@vger.kernel.org S: Supported +F: Documentation/stable_kernel_rules.txt STAGING SUBSYSTEM M: Greg Kroah-Hartman diff --git a/Makefile b/Makefile index dc49d53a357..ab3cf6f11ef 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 4 -SUBLEVEL = 30 +SUBLEVEL = 60 EXTRAVERSION = NAME = Saber-toothed Squirrel diff --git a/arch/alpha/Makefile b/arch/alpha/Makefile index 4759fe751aa..2cc3cc519c5 100644 --- a/arch/alpha/Makefile +++ b/arch/alpha/Makefile @@ -12,7 +12,7 @@ NM := $(NM) -B LDFLAGS_vmlinux := -static -N #-relax CHECKFLAGS += -D__alpha__ -m64 -cflags-y := -pipe -mno-fp-regs -ffixed-8 -msmall-data +cflags-y := -pipe -mno-fp-regs -ffixed-8 cflags-y += $(call cc-option, -fno-jump-tables) cpuflags-$(CONFIG_ALPHA_EV4) := -mcpu=ev4 diff --git a/arch/alpha/kernel/sys_nautilus.c b/arch/alpha/kernel/sys_nautilus.c index 4d4c046f708..1383f8601a9 100644 --- a/arch/alpha/kernel/sys_nautilus.c +++ b/arch/alpha/kernel/sys_nautilus.c @@ -188,6 +188,10 @@ nautilus_machine_check(unsigned long vector, unsigned long la_ptr) extern void free_reserved_mem(void *, void *); extern void pcibios_claim_one_bus(struct pci_bus *); +static struct resource irongate_io = { + .name = "Irongate PCI IO", + .flags = IORESOURCE_IO, +}; static struct resource irongate_mem = { .name = "Irongate PCI MEM", .flags = IORESOURCE_MEM, @@ -209,6 +213,7 @@ nautilus_init_pci(void) irongate = pci_get_bus_and_slot(0, 0); bus->self = irongate; + bus->resource[0] = &irongate_io; bus->resource[1] = &irongate_mem; pci_bus_size_bridges(bus); diff --git a/arch/arm/configs/at91sam9g45_defconfig b/arch/arm/configs/at91sam9g45_defconfig index 606d48f3b8f..8aab786863d 100644 --- a/arch/arm/configs/at91sam9g45_defconfig +++ b/arch/arm/configs/at91sam9g45_defconfig @@ -173,7 +173,6 @@ CONFIG_MMC=y # CONFIG_MMC_BLOCK_BOUNCE is not set CONFIG_SDIO_UART=m CONFIG_MMC_ATMELMCI=y -CONFIG_MMC_ATMELMCI_DMA=y CONFIG_LEDS_ATMEL_PWM=y CONFIG_LEDS_GPIO=y CONFIG_LEDS_TRIGGER_TIMER=y diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h index 31fd8cc39e6..28b52a7a578 100644 --- a/arch/arm/include/asm/cacheflush.h +++ b/arch/arm/include/asm/cacheflush.h @@ -327,9 +327,7 @@ static inline void flush_anon_page(struct vm_area_struct *vma, } #define ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE -static inline void flush_kernel_dcache_page(struct page *page) -{ -} +extern void flush_kernel_dcache_page(struct page *); #define flush_dcache_mmap_lock(mapping) \ spin_lock_irq(&(mapping)->tree_lock) diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h index 6e7b31a9229..911540d214e 100644 --- a/arch/arm/include/asm/pgtable.h +++ b/arch/arm/include/asm/pgtable.h @@ -60,6 +60,15 @@ extern void __pgd_error(const char *file, int line, pgd_t); */ #define FIRST_USER_ADDRESS PAGE_SIZE +/* + * Use TASK_SIZE as the ceiling argument for free_pgtables() and + * free_pgd_range() to avoid freeing the modules pmd when LPAE is enabled (pmd + * page shared between user and kernel). + */ +#ifdef CONFIG_ARM_LPAE +#define USER_PGTABLES_CEILING TASK_SIZE +#endif + /* * The pgprot_* and protection_map entries will be fixed up in runtime * to include the cachable and bufferable bits based on memory policy, diff --git a/arch/arm/include/asm/signal.h b/arch/arm/include/asm/signal.h index 43ba0fb1c8a..559ee24c956 100644 --- a/arch/arm/include/asm/signal.h +++ b/arch/arm/include/asm/signal.h @@ -127,6 +127,7 @@ struct sigaction { __sigrestore_t sa_restorer; sigset_t sa_mask; /* mask last for extensibility */ }; +#define __ARCH_HAS_SA_RESTORER struct k_sigaction { struct sigaction sa; diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c index eeb9ffe39d4..c14c113308f 100644 --- a/arch/arm/kernel/perf_event.c +++ b/arch/arm/kernel/perf_event.c @@ -341,7 +341,10 @@ validate_event(struct pmu_hw_events *hw_events, if (is_software_event(event)) return 1; - if (event->pmu != leader_pmu || event->state <= PERF_EVENT_STATE_OFF) + if (event->pmu != leader_pmu || event->state < PERF_EVENT_STATE_OFF) + return 1; + + if (event->state == PERF_EVENT_STATE_OFF && !event->attr.enable_on_exec) return 1; return armpmu->get_event_idx(hw_events, &fake_event) >= 0; @@ -1020,6 +1023,7 @@ perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs) struct frame_tail __user *tail; + perf_callchain_store(entry, regs->ARM_pc); tail = (struct frame_tail __user *)regs->ARM_fp - 1; while ((entry->nr < PERF_MAX_STACK_DEPTH) && diff --git a/arch/arm/kernel/perf_event_v7.c b/arch/arm/kernel/perf_event_v7.c index 58e9068cc84..9913b94fe92 100644 --- a/arch/arm/kernel/perf_event_v7.c +++ b/arch/arm/kernel/perf_event_v7.c @@ -775,7 +775,7 @@ static unsigned armv7_a7_perf_cache_map[PERF_COUNT_HW_CACHE_MAX] /* * PMXEVTYPER: Event selection reg */ -#define ARMV7_EVTYPE_MASK 0xc00000ff /* Mask for writable bits */ +#define ARMV7_EVTYPE_MASK 0xc80000ff /* Mask for writable bits */ #define ARMV7_EVTYPE_EVENT 0xff /* Mask for EVENT bits */ /* diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c index 55293a78cfa..5db5174c4a5 100644 --- a/arch/arm/mach-at91/setup.c +++ b/arch/arm/mach-at91/setup.c @@ -326,7 +326,7 @@ static void at91_dt_rstc(void) of_id = of_match_node(rstc_ids, np); if (!of_id) - panic("AT91: rtsc no restart function availlable\n"); + panic("AT91: rtsc no restart function available\n"); arm_pm_restart = of_id->data; diff --git a/arch/arm/mach-cns3xxx/core.c b/arch/arm/mach-cns3xxx/core.c index 031805b1428..7f26faf37da 100644 --- a/arch/arm/mach-cns3xxx/core.c +++ b/arch/arm/mach-cns3xxx/core.c @@ -22,19 +22,9 @@ static struct map_desc cns3xxx_io_desc[] __initdata = { { - .virtual = CNS3XXX_TC11MP_TWD_BASE_VIRT, - .pfn = __phys_to_pfn(CNS3XXX_TC11MP_TWD_BASE), - .length = SZ_4K, - .type = MT_DEVICE, - }, { - .virtual = CNS3XXX_TC11MP_GIC_CPU_BASE_VIRT, - .pfn = __phys_to_pfn(CNS3XXX_TC11MP_GIC_CPU_BASE), - .length = SZ_4K, - .type = MT_DEVICE, - }, { - .virtual = CNS3XXX_TC11MP_GIC_DIST_BASE_VIRT, - .pfn = __phys_to_pfn(CNS3XXX_TC11MP_GIC_DIST_BASE), - .length = SZ_4K, + .virtual = CNS3XXX_TC11MP_SCU_BASE_VIRT, + .pfn = __phys_to_pfn(CNS3XXX_TC11MP_SCU_BASE), + .length = SZ_8K, .type = MT_DEVICE, }, { .virtual = CNS3XXX_TIMER1_2_3_BASE_VIRT, diff --git a/arch/arm/mach-cns3xxx/include/mach/cns3xxx.h b/arch/arm/mach-cns3xxx/include/mach/cns3xxx.h index 191c8e57f28..b1021aafa48 100644 --- a/arch/arm/mach-cns3xxx/include/mach/cns3xxx.h +++ b/arch/arm/mach-cns3xxx/include/mach/cns3xxx.h @@ -94,10 +94,10 @@ #define RTC_INTR_STS_OFFSET 0x34 #define CNS3XXX_MISC_BASE 0x76000000 /* Misc Control */ -#define CNS3XXX_MISC_BASE_VIRT 0xFFF07000 /* Misc Control */ +#define CNS3XXX_MISC_BASE_VIRT 0xFB000000 /* Misc Control */ #define CNS3XXX_PM_BASE 0x77000000 /* Power Management Control */ -#define CNS3XXX_PM_BASE_VIRT 0xFFF08000 +#define CNS3XXX_PM_BASE_VIRT 0xFB001000 #define PM_CLK_GATE_OFFSET 0x00 #define PM_SOFT_RST_OFFSET 0x04 @@ -109,7 +109,7 @@ #define PM_PLL_HM_PD_OFFSET 0x1C #define CNS3XXX_UART0_BASE 0x78000000 /* UART 0 */ -#define CNS3XXX_UART0_BASE_VIRT 0xFFF09000 +#define CNS3XXX_UART0_BASE_VIRT 0xFB002000 #define CNS3XXX_UART1_BASE 0x78400000 /* UART 1 */ #define CNS3XXX_UART1_BASE_VIRT 0xFFF0A000 @@ -130,7 +130,7 @@ #define CNS3XXX_I2S_BASE_VIRT 0xFFF10000 #define CNS3XXX_TIMER1_2_3_BASE 0x7C800000 /* Timer */ -#define CNS3XXX_TIMER1_2_3_BASE_VIRT 0xFFF10800 +#define CNS3XXX_TIMER1_2_3_BASE_VIRT 0xFB003000 #define TIMER1_COUNTER_OFFSET 0x00 #define TIMER1_AUTO_RELOAD_OFFSET 0x04 @@ -227,16 +227,16 @@ * Testchip peripheral and fpga gic regions */ #define CNS3XXX_TC11MP_SCU_BASE 0x90000000 /* IRQ, Test chip */ -#define CNS3XXX_TC11MP_SCU_BASE_VIRT 0xFF000000 +#define CNS3XXX_TC11MP_SCU_BASE_VIRT 0xFB004000 #define CNS3XXX_TC11MP_GIC_CPU_BASE 0x90000100 /* Test chip interrupt controller CPU interface */ -#define CNS3XXX_TC11MP_GIC_CPU_BASE_VIRT 0xFF000100 +#define CNS3XXX_TC11MP_GIC_CPU_BASE_VIRT (CNS3XXX_TC11MP_SCU_BASE_VIRT + 0x100) #define CNS3XXX_TC11MP_TWD_BASE 0x90000600 -#define CNS3XXX_TC11MP_TWD_BASE_VIRT 0xFF000600 +#define CNS3XXX_TC11MP_TWD_BASE_VIRT (CNS3XXX_TC11MP_SCU_BASE_VIRT + 0x600) #define CNS3XXX_TC11MP_GIC_DIST_BASE 0x90001000 /* Test chip interrupt controller distributor */ -#define CNS3XXX_TC11MP_GIC_DIST_BASE_VIRT 0xFF001000 +#define CNS3XXX_TC11MP_GIC_DIST_BASE_VIRT (CNS3XXX_TC11MP_SCU_BASE_VIRT + 0x1000) #define CNS3XXX_TC11MP_L220_BASE 0x92002000 /* L220 registers */ #define CNS3XXX_TC11MP_L220_BASE_VIRT 0xFF002000 diff --git a/arch/arm/mach-kirkwood/ts219-setup.c b/arch/arm/mach-kirkwood/ts219-setup.c index 73e2b6ca956..3a73fc738fd 100644 --- a/arch/arm/mach-kirkwood/ts219-setup.c +++ b/arch/arm/mach-kirkwood/ts219-setup.c @@ -124,7 +124,7 @@ static void __init qnap_ts219_init(void) static int __init ts219_pci_init(void) { if (machine_is_ts219()) - kirkwood_pcie_init(KW_PCIE0); + kirkwood_pcie_init(KW_PCIE1 | KW_PCIE0); return 0; } diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c index d87ee061209..283a8d0d611 100644 --- a/arch/arm/mach-omap2/board-rx51-peripherals.c +++ b/arch/arm/mach-omap2/board-rx51-peripherals.c @@ -63,11 +63,11 @@ #define RX51_TSC2005_RESET_GPIO 104 #define RX51_TSC2005_IRQ_GPIO 100 -/* list all spi devices here */ +/* List all SPI devices here. Note that the list/probe order seems to matter! */ enum { RX51_SPI_WL1251, - RX51_SPI_MIPID, /* LCD panel */ RX51_SPI_TSC2005, /* Touch Controller */ + RX51_SPI_MIPID, /* LCD panel */ }; static struct wl12xx_platform_data wl1251_pdata; diff --git a/arch/arm/mach-pxa/include/mach/smemc.h b/arch/arm/mach-pxa/include/mach/smemc.h index b7de471b273..b802f285fe0 100644 --- a/arch/arm/mach-pxa/include/mach/smemc.h +++ b/arch/arm/mach-pxa/include/mach/smemc.h @@ -37,6 +37,7 @@ #define CSADRCFG1 (SMEMC_VIRT + 0x84) /* Address Configuration Register for CS1 */ #define CSADRCFG2 (SMEMC_VIRT + 0x88) /* Address Configuration Register for CS2 */ #define CSADRCFG3 (SMEMC_VIRT + 0x8C) /* Address Configuration Register for CS3 */ +#define CSMSADRCFG (SMEMC_VIRT + 0xA0) /* Chip Select Configuration Register */ /* * More handy macros for PCMCIA diff --git a/arch/arm/mach-pxa/smemc.c b/arch/arm/mach-pxa/smemc.c index 79923058d10..f38aa890b2c 100644 --- a/arch/arm/mach-pxa/smemc.c +++ b/arch/arm/mach-pxa/smemc.c @@ -40,6 +40,8 @@ static void pxa3xx_smemc_resume(void) __raw_writel(csadrcfg[1], CSADRCFG1); __raw_writel(csadrcfg[2], CSADRCFG2); __raw_writel(csadrcfg[3], CSADRCFG3); + /* CSMSADRCFG wakes up in its default state (0), so we need to set it */ + __raw_writel(0x2, CSMSADRCFG); } static struct syscore_ops smemc_syscore_ops = { @@ -49,8 +51,19 @@ static struct syscore_ops smemc_syscore_ops = { static int __init smemc_init(void) { - if (cpu_is_pxa3xx()) + if (cpu_is_pxa3xx()) { + /* + * The only documentation we have on the + * Chip Select Configuration Register (CSMSADRCFG) is that + * it must be programmed to 0x2. + * Moreover, in the bit definitions, the second bit + * (CSMSADRCFG[1]) is called "SETALWAYS". + * Other bits are reserved in this register. + */ + __raw_writel(0x2, CSMSADRCFG); + register_syscore_ops(&smemc_syscore_ops); + } return 0; } diff --git a/arch/arm/mach-s3c24xx/include/mach/debug-macro.S b/arch/arm/mach-s3c24xx/include/mach/debug-macro.S index 4135de87d1f..13ed33c6911 100644 --- a/arch/arm/mach-s3c24xx/include/mach/debug-macro.S +++ b/arch/arm/mach-s3c24xx/include/mach/debug-macro.S @@ -40,17 +40,17 @@ addeq \rd, \rx, #(S3C24XX_PA_GPIO - S3C24XX_PA_UART) addne \rd, \rx, #(S3C24XX_VA_GPIO - S3C24XX_VA_UART) bic \rd, \rd, #0xff000 - ldr \rd, [ \rd, # S3C2410_GSTATUS1 - S3C2410_GPIOREG(0) ] + ldr \rd, [\rd, # S3C2410_GSTATUS1 - S3C2410_GPIOREG(0)] and \rd, \rd, #0x00ff0000 teq \rd, #0x00440000 @ is it 2440? 1004: - ldr \rd, [ \rx, # S3C2410_UFSTAT ] + ldr \rd, [\rx, # S3C2410_UFSTAT] moveq \rd, \rd, lsr #SHIFT_2440TXF tst \rd, #S3C2410_UFSTAT_TXFULL .endm .macro fifo_full_s3c2410 rd, rx - ldr \rd, [ \rx, # S3C2410_UFSTAT ] + ldr \rd, [\rx, # S3C2410_UFSTAT] tst \rd, #S3C2410_UFSTAT_TXFULL .endm @@ -68,18 +68,18 @@ addeq \rd, \rx, #(S3C24XX_PA_GPIO - S3C24XX_PA_UART) addne \rd, \rx, #(S3C24XX_VA_GPIO - S3C24XX_VA_UART) bic \rd, \rd, #0xff000 - ldr \rd, [ \rd, # S3C2410_GSTATUS1 - S3C2410_GPIOREG(0) ] + ldr \rd, [\rd, # S3C2410_GSTATUS1 - S3C2410_GPIOREG(0)] and \rd, \rd, #0x00ff0000 teq \rd, #0x00440000 @ is it 2440? 10000: - ldr \rd, [ \rx, # S3C2410_UFSTAT ] + ldr \rd, [\rx, # S3C2410_UFSTAT] andne \rd, \rd, #S3C2410_UFSTAT_TXMASK andeq \rd, \rd, #S3C2440_UFSTAT_TXMASK .endm .macro fifo_level_s3c2410 rd, rx - ldr \rd, [ \rx, # S3C2410_UFSTAT ] + ldr \rd, [\rx, # S3C2410_UFSTAT] and \rd, \rd, #S3C2410_UFSTAT_TXMASK .endm diff --git a/arch/arm/mach-s3c24xx/include/mach/entry-macro.S b/arch/arm/mach-s3c24xx/include/mach/entry-macro.S index 7615a14773f..6a21beeba1d 100644 --- a/arch/arm/mach-s3c24xx/include/mach/entry-macro.S +++ b/arch/arm/mach-s3c24xx/include/mach/entry-macro.S @@ -31,10 +31,10 @@ @@ try the interrupt offset register, since it is there - ldr \irqstat, [ \base, #INTPND ] + ldr \irqstat, [\base, #INTPND ] teq \irqstat, #0 beq 1002f - ldr \irqnr, [ \base, #INTOFFSET ] + ldr \irqnr, [\base, #INTOFFSET ] mov \tmp, #1 tst \irqstat, \tmp, lsl \irqnr bne 1001f diff --git a/arch/arm/mach-s3c24xx/pm-h1940.S b/arch/arm/mach-s3c24xx/pm-h1940.S index c93bf2db9f4..6183a688012 100644 --- a/arch/arm/mach-s3c24xx/pm-h1940.S +++ b/arch/arm/mach-s3c24xx/pm-h1940.S @@ -30,4 +30,4 @@ h1940_pm_return: mov r0, #S3C2410_PA_GPIO - ldr pc, [ r0, #S3C2410_GSTATUS3 - S3C24XX_VA_GPIO ] + ldr pc, [r0, #S3C2410_GSTATUS3 - S3C24XX_VA_GPIO] diff --git a/arch/arm/mach-s3c24xx/sleep-s3c2410.S b/arch/arm/mach-s3c24xx/sleep-s3c2410.S index dd5b6388a5a..65200ae72c9 100644 --- a/arch/arm/mach-s3c24xx/sleep-s3c2410.S +++ b/arch/arm/mach-s3c24xx/sleep-s3c2410.S @@ -45,9 +45,9 @@ ENTRY(s3c2410_cpu_suspend) ldr r4, =S3C2410_REFRESH ldr r5, =S3C24XX_MISCCR ldr r6, =S3C2410_CLKCON - ldr r7, [ r4 ] @ get REFRESH (and ensure in TLB) - ldr r8, [ r5 ] @ get MISCCR (and ensure in TLB) - ldr r9, [ r6 ] @ get CLKCON (and ensure in TLB) + ldr r7, [r4] @ get REFRESH (and ensure in TLB) + ldr r8, [r5] @ get MISCCR (and ensure in TLB) + ldr r9, [r6] @ get CLKCON (and ensure in TLB) orr r7, r7, #S3C2410_REFRESH_SELF @ SDRAM sleep command orr r8, r8, #S3C2410_MISCCR_SDSLEEP @ SDRAM power-down signals @@ -61,8 +61,8 @@ ENTRY(s3c2410_cpu_suspend) @@ align next bit of code to cache line .align 5 s3c2410_do_sleep: - streq r7, [ r4 ] @ SDRAM sleep command - streq r8, [ r5 ] @ SDRAM power-down config - streq r9, [ r6 ] @ CPU sleep + streq r7, [r4] @ SDRAM sleep command + streq r8, [r5] @ SDRAM power-down config + streq r9, [r6] @ CPU sleep 1: beq 1b mov pc, r14 diff --git a/arch/arm/mach-s3c24xx/sleep-s3c2412.S b/arch/arm/mach-s3c24xx/sleep-s3c2412.S index c82418ed714..5adaceb7da1 100644 --- a/arch/arm/mach-s3c24xx/sleep-s3c2412.S +++ b/arch/arm/mach-s3c24xx/sleep-s3c2412.S @@ -57,12 +57,12 @@ s3c2412_sleep_enter1: * retry, as simply returning causes the system to lock. */ - ldrne r9, [ r1 ] - strne r9, [ r1 ] - ldrne r9, [ r2 ] - strne r9, [ r2 ] - ldrne r9, [ r3 ] - strne r9, [ r3 ] + ldrne r9, [r1] + strne r9, [r1] + ldrne r9, [r2] + strne r9, [r2] + ldrne r9, [r3] + strne r9, [r3] bne s3c2412_sleep_enter1 mov pc, r14 diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c index 94b1e610aeb..e3cc644947d 100644 --- a/arch/arm/mm/alignment.c +++ b/arch/arm/mm/alignment.c @@ -750,7 +750,6 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs) unsigned long instr = 0, instrptr; int (*handler)(unsigned long addr, unsigned long instr, struct pt_regs *regs); unsigned int type; - mm_segment_t fs; unsigned int fault; u16 tinstr = 0; int isize = 4; @@ -761,16 +760,15 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs) instrptr = instruction_pointer(regs); - fs = get_fs(); - set_fs(KERNEL_DS); if (thumb_mode(regs)) { - fault = __get_user(tinstr, (u16 *)(instrptr & ~1)); + u16 *ptr = (u16 *)(instrptr & ~1); + fault = probe_kernel_address(ptr, tinstr); if (!fault) { if (cpu_architecture() >= CPU_ARCH_ARMv7 && IS_T32(tinstr)) { /* Thumb-2 32-bit */ u16 tinst2 = 0; - fault = __get_user(tinst2, (u16 *)(instrptr+2)); + fault = probe_kernel_address(ptr + 1, tinst2); instr = (tinstr << 16) | tinst2; thumb2_32b = 1; } else { @@ -779,8 +777,7 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs) } } } else - fault = __get_user(instr, (u32 *)instrptr); - set_fs(fs); + fault = probe_kernel_address(instrptr, instr); if (fault) { type = TYPE_FAULT; diff --git a/arch/arm/mm/cache-feroceon-l2.c b/arch/arm/mm/cache-feroceon-l2.c index dd3d59122cc..48bc3c0a87c 100644 --- a/arch/arm/mm/cache-feroceon-l2.c +++ b/arch/arm/mm/cache-feroceon-l2.c @@ -343,6 +343,7 @@ void __init feroceon_l2_init(int __l2_wt_override) outer_cache.inv_range = feroceon_l2_inv_range; outer_cache.clean_range = feroceon_l2_clean_range; outer_cache.flush_range = feroceon_l2_flush_range; + outer_cache.inv_all = l2_inv_all; enable_l2(); diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c index 40ca11ed6e5..8f0d285f8ba 100644 --- a/arch/arm/mm/flush.c +++ b/arch/arm/mm/flush.c @@ -298,6 +298,39 @@ void flush_dcache_page(struct page *page) } EXPORT_SYMBOL(flush_dcache_page); +/* + * Ensure cache coherency for the kernel mapping of this page. We can + * assume that the page is pinned via kmap. + * + * If the page only exists in the page cache and there are no user + * space mappings, this is a no-op since the page was already marked + * dirty at creation. Otherwise, we need to flush the dirty kernel + * cache lines directly. + */ +void flush_kernel_dcache_page(struct page *page) +{ + if (cache_is_vivt() || cache_is_vipt_aliasing()) { + struct address_space *mapping; + + mapping = page_mapping(page); + + if (!mapping || mapping_mapped(mapping)) { + void *addr; + + addr = page_address(page); + /* + * kmap_atomic() doesn't set the page virtual + * address for highmem pages, and + * kunmap_atomic() takes care of cache + * flushing already. + */ + if (!IS_ENABLED(CONFIG_HIGHMEM) || addr) + __cpuc_flush_dcache_area(addr, PAGE_SIZE); + } + } +} +EXPORT_SYMBOL(flush_kernel_dcache_page); + /* * Flush an anonymous page so that users of get_user_pages() * can safely access the data. The expected sequence is: diff --git a/arch/arm/mm/nommu.c b/arch/arm/mm/nommu.c index d51225f90ae..eb5293a69a8 100644 --- a/arch/arm/mm/nommu.c +++ b/arch/arm/mm/nommu.c @@ -57,6 +57,12 @@ void flush_dcache_page(struct page *page) } EXPORT_SYMBOL(flush_dcache_page); +void flush_kernel_dcache_page(struct page *page) +{ + __cpuc_flush_dcache_area(page_address(page), PAGE_SIZE); +} +EXPORT_SYMBOL(flush_kernel_dcache_page); + void copy_to_user_page(struct vm_area_struct *vma, struct page *page, unsigned long uaddr, void *dst, const void *src, unsigned long len) diff --git a/arch/arm/mm/proc-arm920.S b/arch/arm/mm/proc-arm920.S index cb941ae95f6..aeeb1265860 100644 --- a/arch/arm/mm/proc-arm920.S +++ b/arch/arm/mm/proc-arm920.S @@ -383,7 +383,7 @@ ENTRY(cpu_arm920_set_pte_ext) /* Suspend/resume support: taken from arch/arm/plat-s3c24xx/sleep.S */ .globl cpu_arm920_suspend_size .equ cpu_arm920_suspend_size, 4 * 3 -#ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_ARM_CPU_SUSPEND ENTRY(cpu_arm920_do_suspend) stmfd sp!, {r4 - r6, lr} mrc p15, 0, r4, c13, c0, 0 @ PID diff --git a/arch/arm/mm/proc-arm926.S b/arch/arm/mm/proc-arm926.S index 820259b81a1..ee29dc46537 100644 --- a/arch/arm/mm/proc-arm926.S +++ b/arch/arm/mm/proc-arm926.S @@ -398,7 +398,7 @@ ENTRY(cpu_arm926_set_pte_ext) /* Suspend/resume support: taken from arch/arm/plat-s3c24xx/sleep.S */ .globl cpu_arm926_suspend_size .equ cpu_arm926_suspend_size, 4 * 3 -#ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_ARM_CPU_SUSPEND ENTRY(cpu_arm926_do_suspend) stmfd sp!, {r4 - r6, lr} mrc p15, 0, r4, c13, c0, 0 @ PID diff --git a/arch/arm/mm/proc-sa1100.S b/arch/arm/mm/proc-sa1100.S index 3aa0da11fd8..d92dfd08142 100644 --- a/arch/arm/mm/proc-sa1100.S +++ b/arch/arm/mm/proc-sa1100.S @@ -172,7 +172,7 @@ ENTRY(cpu_sa1100_set_pte_ext) .globl cpu_sa1100_suspend_size .equ cpu_sa1100_suspend_size, 4 * 3 -#ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_ARM_CPU_SUSPEND ENTRY(cpu_sa1100_do_suspend) stmfd sp!, {r4 - r6, lr} mrc p15, 0, r4, c3, c0, 0 @ domain ID diff --git a/arch/arm/mm/proc-v6.S b/arch/arm/mm/proc-v6.S index 501397a3d17..37cd896e131 100644 --- a/arch/arm/mm/proc-v6.S +++ b/arch/arm/mm/proc-v6.S @@ -138,7 +138,7 @@ ENTRY(cpu_v6_set_pte_ext) /* Suspend/resume support: taken from arch/arm/mach-s3c64xx/sleep.S */ .globl cpu_v6_suspend_size .equ cpu_v6_suspend_size, 4 * 6 -#ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_ARM_CPU_SUSPEND ENTRY(cpu_v6_do_suspend) stmfd sp!, {r4 - r9, lr} mrc p15, 0, r4, c13, c0, 0 @ FCSE/PID diff --git a/arch/arm/mm/proc-xsc3.S b/arch/arm/mm/proc-xsc3.S index b0d57869da2..a2d1e8646ef 100644 --- a/arch/arm/mm/proc-xsc3.S +++ b/arch/arm/mm/proc-xsc3.S @@ -410,7 +410,7 @@ ENTRY(cpu_xsc3_set_pte_ext) .globl cpu_xsc3_suspend_size .equ cpu_xsc3_suspend_size, 4 * 6 -#ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_ARM_CPU_SUSPEND ENTRY(cpu_xsc3_do_suspend) stmfd sp!, {r4 - r9, lr} mrc p14, 0, r4, c6, c0, 0 @ clock configuration, for turbo mode diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S index 4ffebaa595e..98821530ae7 100644 --- a/arch/arm/mm/proc-xscale.S +++ b/arch/arm/mm/proc-xscale.S @@ -524,7 +524,7 @@ ENTRY(cpu_xscale_set_pte_ext) .globl cpu_xscale_suspend_size .equ cpu_xscale_suspend_size, 4 * 6 -#ifdef CONFIG_PM_SLEEP +#ifdef CONFIG_ARM_CPU_SUSPEND ENTRY(cpu_xscale_do_suspend) stmfd sp!, {r4 - r9, lr} mrc p14, 0, r4, c6, c0, 0 @ clock configuration, for turbo mode diff --git a/arch/arm/plat-orion/common.c b/arch/arm/plat-orion/common.c index 331f8bbded9..4dac6e077ba 100644 --- a/arch/arm/plat-orion/common.c +++ b/arch/arm/plat-orion/common.c @@ -340,7 +340,7 @@ static struct resource orion_ge10_shared_resources[] = { static struct platform_device orion_ge10_shared = { .name = MV643XX_ETH_SHARED_NAME, - .id = 1, + .id = 2, .dev = { .platform_data = &orion_ge10_shared_data, }, @@ -355,8 +355,8 @@ static struct resource orion_ge10_resources[] = { static struct platform_device orion_ge10 = { .name = MV643XX_ETH_NAME, - .id = 1, - .num_resources = 2, + .id = 2, + .num_resources = 1, .resource = orion_ge10_resources, .dev = { .coherent_dma_mask = DMA_BIT_MASK(32), @@ -393,7 +393,7 @@ static struct resource orion_ge11_shared_resources[] = { static struct platform_device orion_ge11_shared = { .name = MV643XX_ETH_SHARED_NAME, - .id = 1, + .id = 3, .dev = { .platform_data = &orion_ge11_shared_data, }, @@ -408,8 +408,8 @@ static struct resource orion_ge11_resources[] = { static struct platform_device orion_ge11 = { .name = MV643XX_ETH_NAME, - .id = 1, - .num_resources = 2, + .id = 3, + .num_resources = 1, .resource = orion_ge11_resources, .dev = { .coherent_dma_mask = DMA_BIT_MASK(32), diff --git a/arch/arm/plat-samsung/include/plat/debug-macro.S b/arch/arm/plat-samsung/include/plat/debug-macro.S index 207e275362a..f3a9cff6d5d 100644 --- a/arch/arm/plat-samsung/include/plat/debug-macro.S +++ b/arch/arm/plat-samsung/include/plat/debug-macro.S @@ -14,12 +14,12 @@ /* The S5PV210/S5PC110 implementations are as belows. */ .macro fifo_level_s5pv210 rd, rx - ldr \rd, [ \rx, # S3C2410_UFSTAT ] + ldr \rd, [\rx, # S3C2410_UFSTAT] and \rd, \rd, #S5PV210_UFSTAT_TXMASK .endm .macro fifo_full_s5pv210 rd, rx - ldr \rd, [ \rx, # S3C2410_UFSTAT ] + ldr \rd, [\rx, # S3C2410_UFSTAT] tst \rd, #S5PV210_UFSTAT_TXFULL .endm @@ -27,7 +27,7 @@ * most widely re-used */ .macro fifo_level_s3c2440 rd, rx - ldr \rd, [ \rx, # S3C2410_UFSTAT ] + ldr \rd, [\rx, # S3C2410_UFSTAT] and \rd, \rd, #S3C2440_UFSTAT_TXMASK .endm @@ -36,7 +36,7 @@ #endif .macro fifo_full_s3c2440 rd, rx - ldr \rd, [ \rx, # S3C2410_UFSTAT ] + ldr \rd, [\rx, # S3C2410_UFSTAT] tst \rd, #S3C2440_UFSTAT_TXFULL .endm @@ -45,11 +45,11 @@ #endif .macro senduart,rd,rx - strb \rd, [\rx, # S3C2410_UTXH ] + strb \rd, [\rx, # S3C2410_UTXH] .endm .macro busyuart, rd, rx - ldr \rd, [ \rx, # S3C2410_UFCON ] + ldr \rd, [\rx, # S3C2410_UFCON] tst \rd, #S3C2410_UFCON_FIFOMODE @ fifo enabled? beq 1001f @ @ FIFO enabled... @@ -60,7 +60,7 @@ 1001: @ busy waiting for non fifo - ldr \rd, [ \rx, # S3C2410_UTRSTAT ] + ldr \rd, [\rx, # S3C2410_UTRSTAT] tst \rd, #S3C2410_UTRSTAT_TXFE beq 1001b @@ -68,7 +68,7 @@ .endm .macro waituart,rd,rx - ldr \rd, [ \rx, # S3C2410_UFCON ] + ldr \rd, [\rx, # S3C2410_UFCON] tst \rd, #S3C2410_UFCON_FIFOMODE @ fifo enabled? beq 1001f @ @ FIFO enabled... @@ -79,7 +79,7 @@ b 1002f 1001: @ idle waiting for non fifo - ldr \rd, [ \rx, # S3C2410_UTRSTAT ] + ldr \rd, [\rx, # S3C2410_UTRSTAT] tst \rd, #S3C2410_UTRSTAT_TXFE beq 1001b diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c index fb540cc60b7..3a5443d452b 100644 --- a/arch/arm/vfp/vfpmodule.c +++ b/arch/arm/vfp/vfpmodule.c @@ -420,7 +420,7 @@ void VFP_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs) * If there isn't a second FP instruction, exit now. Note that * the FPEXC.FP2V bit is valid only if FPEXC.EX is 1. */ - if (fpexc ^ (FPEXC_EX | FPEXC_FP2V)) + if ((fpexc & (FPEXC_EX | FPEXC_FP2V)) != (FPEXC_EX | FPEXC_FP2V)) goto exit; /* diff --git a/arch/avr32/configs/favr-32_defconfig b/arch/avr32/configs/favr-32_defconfig index 19973b06170..59e4cc9ed81 100644 --- a/arch/avr32/configs/favr-32_defconfig +++ b/arch/avr32/configs/favr-32_defconfig @@ -122,7 +122,6 @@ CONFIG_USB_G_SERIAL=m CONFIG_USB_CDC_COMPOSITE=m CONFIG_MMC=y CONFIG_MMC_ATMELMCI=y -CONFIG_MMC_ATMELMCI_DMA=y CONFIG_NEW_LEDS=y CONFIG_LEDS_CLASS=y CONFIG_LEDS_ATMEL_PWM=m diff --git a/arch/avr32/configs/merisc_defconfig b/arch/avr32/configs/merisc_defconfig index 3befab96682..65de4431108 100644 --- a/arch/avr32/configs/merisc_defconfig +++ b/arch/avr32/configs/merisc_defconfig @@ -102,7 +102,6 @@ CONFIG_FRAMEBUFFER_CONSOLE=y CONFIG_LOGO=y CONFIG_MMC=y CONFIG_MMC_ATMELMCI=y -CONFIG_MMC_ATMELMCI_DMA=y CONFIG_NEW_LEDS=y CONFIG_LEDS_CLASS=y CONFIG_LEDS_ATMEL_PWM=y diff --git a/arch/avr32/include/asm/signal.h b/arch/avr32/include/asm/signal.h index 8790dfc10d5..e6952a01c5d 100644 --- a/arch/avr32/include/asm/signal.h +++ b/arch/avr32/include/asm/signal.h @@ -128,6 +128,7 @@ struct sigaction { __sigrestore_t sa_restorer; sigset_t sa_mask; /* mask last for extensibility */ }; +#define __ARCH_HAS_SA_RESTORER struct k_sigaction { struct sigaction sa; diff --git a/arch/avr32/kernel/module.c b/arch/avr32/kernel/module.c index 596f7305d93..2c941290802 100644 --- a/arch/avr32/kernel/module.c +++ b/arch/avr32/kernel/module.c @@ -264,7 +264,7 @@ int apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab, break; case R_AVR32_GOT18SW: if ((relocation & 0xfffe0003) != 0 - && (relocation & 0xfffc0003) != 0xffff0000) + && (relocation & 0xfffc0000) != 0xfffc0000) return reloc_overflow(module, "R_AVR32_GOT18SW", relocation); relocation >>= 2; diff --git a/arch/cris/arch-v10/lib/Makefile b/arch/cris/arch-v10/lib/Makefile index 36e9a9c5239..725153edb76 100644 --- a/arch/cris/arch-v10/lib/Makefile +++ b/arch/cris/arch-v10/lib/Makefile @@ -2,8 +2,5 @@ # Makefile for Etrax-specific library files.. # - -EXTRA_AFLAGS := -traditional - lib-y = checksum.o checksumcopy.o string.o usercopy.o memset.o csumcpfruser.o diff --git a/arch/cris/include/asm/posix_types.h b/arch/cris/include/asm/posix_types.h index 72b3cd6eda0..234891c74e2 100644 --- a/arch/cris/include/asm/posix_types.h +++ b/arch/cris/include/asm/posix_types.h @@ -33,4 +33,6 @@ typedef int __kernel_ptrdiff_t; typedef unsigned short __kernel_old_dev_t; #define __kernel_old_dev_t __kernel_old_dev_t +#include + #endif /* __ARCH_CRIS_POSIX_TYPES_H */ diff --git a/arch/cris/include/asm/signal.h b/arch/cris/include/asm/signal.h index ea6af9aad76..057fea2db9e 100644 --- a/arch/cris/include/asm/signal.h +++ b/arch/cris/include/asm/signal.h @@ -122,6 +122,7 @@ struct sigaction { void (*sa_restorer)(void); sigset_t sa_mask; /* mask last for extensibility */ }; +#define __ARCH_HAS_SA_RESTORER struct k_sigaction { struct sigaction sa; diff --git a/arch/cris/kernel/vmlinux.lds.S b/arch/cris/kernel/vmlinux.lds.S index a6990cb0f09..a68b983dcea 100644 --- a/arch/cris/kernel/vmlinux.lds.S +++ b/arch/cris/kernel/vmlinux.lds.S @@ -52,6 +52,7 @@ SECTIONS EXCEPTION_TABLE(4) + _sdata = .; RODATA . = ALIGN (4); diff --git a/arch/frv/include/asm/thread_info.h b/arch/frv/include/asm/thread_info.h index 92d83ea99ae..aaea388a57d 100644 --- a/arch/frv/include/asm/thread_info.h +++ b/arch/frv/include/asm/thread_info.h @@ -21,8 +21,6 @@ #define THREAD_SIZE 8192 -#define __HAVE_ARCH_TASK_STRUCT_ALLOCATOR - /* * low level task data that entry.S needs immediate access to * - this struct should fit entirely inside of one cache line diff --git a/arch/frv/kernel/process.c b/arch/frv/kernel/process.c index 3941cbc91ff..c4dc7a4d229 100644 --- a/arch/frv/kernel/process.c +++ b/arch/frv/kernel/process.c @@ -44,21 +44,6 @@ asmlinkage void ret_from_fork(void); void (*pm_power_off)(void); EXPORT_SYMBOL(pm_power_off); -struct task_struct *alloc_task_struct_node(int node) -{ - struct task_struct *p = kmalloc_node(THREAD_SIZE, GFP_KERNEL, node); - - if (p) - atomic_set((atomic_t *)(p+1), 1); - return p; -} - -void free_task_struct(struct task_struct *p) -{ - if (atomic_dec_and_test((atomic_t *)(p+1))) - kfree(p); -} - static void core_sleep_idle(void) { #ifdef LED_DEBUG_SLEEP diff --git a/arch/h8300/include/asm/signal.h b/arch/h8300/include/asm/signal.h index fd8b66e40dc..86957072d16 100644 --- a/arch/h8300/include/asm/signal.h +++ b/arch/h8300/include/asm/signal.h @@ -121,6 +121,7 @@ struct sigaction { void (*sa_restorer)(void); sigset_t sa_mask; /* mask last for extensibility */ }; +#define __ARCH_HAS_SA_RESTORER struct k_sigaction { struct sigaction sa; diff --git a/arch/ia64/include/asm/futex.h b/arch/ia64/include/asm/futex.h index d2bf1fd5e44..76acbcd5c06 100644 --- a/arch/ia64/include/asm/futex.h +++ b/arch/ia64/include/asm/futex.h @@ -106,16 +106,15 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, return -EFAULT; { - register unsigned long r8 __asm ("r8"); + register unsigned long r8 __asm ("r8") = 0; unsigned long prev; __asm__ __volatile__( " mf;; \n" - " mov %0=r0 \n" " mov ar.ccv=%4;; \n" "[1:] cmpxchg4.acq %1=[%2],%3,ar.ccv \n" " .xdata4 \"__ex_table\", 1b-., 2f-. \n" "[2:]" - : "=r" (r8), "=r" (prev) + : "+r" (r8), "=&r" (prev) : "r" (uaddr), "r" (newval), "rO" ((long) (unsigned) oldval) : "memory"); diff --git a/arch/ia64/include/asm/mca.h b/arch/ia64/include/asm/mca.h index 43f96ab18fa..8c709616871 100644 --- a/arch/ia64/include/asm/mca.h +++ b/arch/ia64/include/asm/mca.h @@ -143,6 +143,7 @@ extern unsigned long __per_cpu_mca[NR_CPUS]; extern int cpe_vector; extern int ia64_cpe_irq; extern void ia64_mca_init(void); +extern void ia64_mca_irq_init(void); extern void ia64_mca_cpu_init(void *); extern void ia64_os_mca_dispatch(void); extern void ia64_os_mca_dispatch_end(void); diff --git a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c index ad69606613e..f2c41828113 100644 --- a/arch/ia64/kernel/irq.c +++ b/arch/ia64/kernel/irq.c @@ -23,6 +23,8 @@ #include #include +#include + /* * 'what should we do if we get a hw irq event on an illegal vector'. * each architecture has to answer this themselves. @@ -83,6 +85,12 @@ bool is_affinity_mask_valid(const struct cpumask *cpumask) #endif /* CONFIG_SMP */ +int __init arch_early_irq_init(void) +{ + ia64_mca_irq_init(); + return 0; +} + #ifdef CONFIG_HOTPLUG_CPU unsigned int vectors_in_migration[NR_IRQS]; diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c index 41028334289..b8edfa75a83 100644 --- a/arch/ia64/kernel/mca.c +++ b/arch/ia64/kernel/mca.c @@ -2074,22 +2074,16 @@ ia64_mca_init(void) printk(KERN_INFO "MCA related initialization done\n"); } + /* - * ia64_mca_late_init - * - * Opportunity to setup things that require initialization later - * than ia64_mca_init. Setup a timer to poll for CPEs if the - * platform doesn't support an interrupt driven mechanism. - * - * Inputs : None - * Outputs : Status + * These pieces cannot be done in ia64_mca_init() because it is called before + * early_irq_init() which would wipe out our percpu irq registrations. But we + * cannot leave them until ia64_mca_late_init() because by then all the other + * processors have been brought online and have set their own CMC vectors to + * point at a non-existant action. Called from arch_early_irq_init(). */ -static int __init -ia64_mca_late_init(void) +void __init ia64_mca_irq_init(void) { - if (!mca_init) - return 0; - /* * Configure the CMCI/P vector and handler. Interrupts for CMC are * per-processor, so AP CMC interrupts are setup in smp_callin() (smpboot.c). @@ -2108,6 +2102,23 @@ ia64_mca_late_init(void) /* Setup the CPEI/P handler */ register_percpu_irq(IA64_CPEP_VECTOR, &mca_cpep_irqaction); #endif +} + +/* + * ia64_mca_late_init + * + * Opportunity to setup things that require initialization later + * than ia64_mca_init. Setup a timer to poll for CPEs if the + * platform doesn't support an interrupt driven mechanism. + * + * Inputs : None + * Outputs : Status + */ +static int __init +ia64_mca_late_init(void) +{ + if (!mca_init) + return 0; register_hotcpu_notifier(&mca_cpu_notifier); diff --git a/arch/ia64/kvm/vtlb.c b/arch/ia64/kvm/vtlb.c index 4332f7ee520..a7869f8f49a 100644 --- a/arch/ia64/kvm/vtlb.c +++ b/arch/ia64/kvm/vtlb.c @@ -256,7 +256,7 @@ u64 guest_vhpt_lookup(u64 iha, u64 *pte) "srlz.d;;" "ssm psr.i;;" "srlz.d;;" - : "=r"(ret) : "r"(iha), "r"(pte):"memory"); + : "=&r"(ret) : "r"(iha), "r"(pte) : "memory"); return ret; } diff --git a/arch/m32r/include/asm/signal.h b/arch/m32r/include/asm/signal.h index b2eeb0de1c8..802d5616e8e 100644 --- a/arch/m32r/include/asm/signal.h +++ b/arch/m32r/include/asm/signal.h @@ -123,6 +123,7 @@ struct sigaction { __sigrestore_t sa_restorer; sigset_t sa_mask; /* mask last for extensibility */ }; +#define __ARCH_HAS_SA_RESTORER struct k_sigaction { struct sigaction sa; diff --git a/arch/m68k/emu/natfeat.c b/arch/m68k/emu/natfeat.c index 2291a7d69d4..fa277aecfb7 100644 --- a/arch/m68k/emu/natfeat.c +++ b/arch/m68k/emu/natfeat.c @@ -18,9 +18,11 @@ #include #include +extern long nf_get_id2(const char *feature_name); + asm("\n" -" .global nf_get_id,nf_call\n" -"nf_get_id:\n" +" .global nf_get_id2,nf_call\n" +"nf_get_id2:\n" " .short 0x7300\n" " rts\n" "nf_call:\n" @@ -29,12 +31,25 @@ asm("\n" "1: moveq.l #0,%d0\n" " rts\n" " .section __ex_table,\"a\"\n" -" .long nf_get_id,1b\n" +" .long nf_get_id2,1b\n" " .long nf_call,1b\n" " .previous"); -EXPORT_SYMBOL_GPL(nf_get_id); EXPORT_SYMBOL_GPL(nf_call); +long nf_get_id(const char *feature_name) +{ + /* feature_name may be in vmalloc()ed memory, so make a copy */ + char name_copy[32]; + size_t n; + + n = strlcpy(name_copy, feature_name, sizeof(name_copy)); + if (n >= sizeof(name_copy)) + return 0; + + return nf_get_id2(name_copy); +} +EXPORT_SYMBOL_GPL(nf_get_id); + void nfprint(const char *fmt, ...) { static char buf[256]; diff --git a/arch/m68k/include/asm/div64.h b/arch/m68k/include/asm/div64.h index 444ea8a09e9..ef881cfbbca 100644 --- a/arch/m68k/include/asm/div64.h +++ b/arch/m68k/include/asm/div64.h @@ -15,16 +15,17 @@ unsigned long long n64; \ } __n; \ unsigned long __rem, __upper; \ + unsigned long __base = (base); \ \ __n.n64 = (n); \ if ((__upper = __n.n32[0])) { \ asm ("divul.l %2,%1:%0" \ - : "=d" (__n.n32[0]), "=d" (__upper) \ - : "d" (base), "0" (__n.n32[0])); \ + : "=d" (__n.n32[0]), "=d" (__upper) \ + : "d" (__base), "0" (__n.n32[0])); \ } \ asm ("divu.l %2,%1:%0" \ - : "=d" (__n.n32[1]), "=d" (__rem) \ - : "d" (base), "1" (__upper), "0" (__n.n32[1])); \ + : "=d" (__n.n32[1]), "=d" (__rem) \ + : "d" (__base), "1" (__upper), "0" (__n.n32[1])); \ (n) = __n.n64; \ __rem; \ }) diff --git a/arch/m68k/include/asm/signal.h b/arch/m68k/include/asm/signal.h index 93fe83e7ffb..a20ae638b6a 100644 --- a/arch/m68k/include/asm/signal.h +++ b/arch/m68k/include/asm/signal.h @@ -119,6 +119,7 @@ struct sigaction { __sigrestore_t sa_restorer; sigset_t sa_mask; /* mask last for extensibility */ }; +#define __ARCH_HAS_SA_RESTORER struct k_sigaction { struct sigaction sa; diff --git a/arch/m68k/kernel/head.S b/arch/m68k/kernel/head.S index d197e7ff62c..ac85f16534a 100644 --- a/arch/m68k/kernel/head.S +++ b/arch/m68k/kernel/head.S @@ -2752,11 +2752,9 @@ func_return get_new_page #ifdef CONFIG_MAC L(scc_initable_mac): - .byte 9,12 /* Reset */ .byte 4,0x44 /* x16, 1 stopbit, no parity */ .byte 3,0xc0 /* receiver: 8 bpc */ .byte 5,0xe2 /* transmitter: 8 bpc, assert dtr/rts */ - .byte 9,0 /* no interrupts */ .byte 10,0 /* NRZ */ .byte 11,0x50 /* use baud rate generator */ .byte 12,1,13,0 /* 38400 baud */ @@ -2899,6 +2897,7 @@ func_start serial_init,%d0/%d1/%a0/%a1 is_not_mac(L(serial_init_not_mac)) #ifdef SERIAL_DEBUG + /* You may define either or both of these. */ #define MAC_USE_SCC_A /* Modem port */ #define MAC_USE_SCC_B /* Printer port */ @@ -2908,9 +2907,21 @@ func_start serial_init,%d0/%d1/%a0/%a1 #define mac_scc_cha_b_data_offset 0x4 #define mac_scc_cha_a_data_offset 0x6 +#if defined(MAC_USE_SCC_A) || defined(MAC_USE_SCC_B) + movel %pc@(L(mac_sccbase)),%a0 + /* Reset SCC device */ + moveb #9,%a0@(mac_scc_cha_a_ctrl_offset) + moveb #0xc0,%a0@(mac_scc_cha_a_ctrl_offset) + /* Wait for 5 PCLK cycles, which is about 68 CPU cycles */ + /* 5 / 3.6864 MHz = approx. 1.36 us = 68 / 50 MHz */ + movel #35,%d0 +5: + subq #1,%d0 + jne 5b +#endif + #ifdef MAC_USE_SCC_A /* Initialize channel A */ - movel %pc@(L(mac_sccbase)),%a0 lea %pc@(L(scc_initable_mac)),%a1 5: moveb %a1@+,%d0 jmi 6f @@ -2922,9 +2933,6 @@ func_start serial_init,%d0/%d1/%a0/%a1 #ifdef MAC_USE_SCC_B /* Initialize channel B */ -#ifndef MAC_USE_SCC_A /* Load mac_sccbase only if needed */ - movel %pc@(L(mac_sccbase)),%a0 -#endif /* MAC_USE_SCC_A */ lea %pc@(L(scc_initable_mac)),%a1 7: moveb %a1@+,%d0 jmi 8f @@ -2933,6 +2941,7 @@ func_start serial_init,%d0/%d1/%a0/%a1 jra 7b 8: #endif /* MAC_USE_SCC_B */ + #endif /* SERIAL_DEBUG */ jra L(serial_init_done) @@ -3006,17 +3015,17 @@ func_start serial_putc,%d0/%d1/%a0/%a1 #ifdef SERIAL_DEBUG -#ifdef MAC_USE_SCC_A +#if defined(MAC_USE_SCC_A) || defined(MAC_USE_SCC_B) movel %pc@(L(mac_sccbase)),%a1 +#endif + +#ifdef MAC_USE_SCC_A 3: btst #2,%a1@(mac_scc_cha_a_ctrl_offset) jeq 3b moveb %d0,%a1@(mac_scc_cha_a_data_offset) #endif /* MAC_USE_SCC_A */ #ifdef MAC_USE_SCC_B -#ifndef MAC_USE_SCC_A /* Load mac_sccbase only if needed */ - movel %pc@(L(mac_sccbase)),%a1 -#endif /* MAC_USE_SCC_A */ 4: btst #2,%a1@(mac_scc_cha_b_ctrl_offset) jeq 4b moveb %d0,%a1@(mac_scc_cha_b_data_offset) diff --git a/arch/microblaze/configs/mmu_defconfig b/arch/microblaze/configs/mmu_defconfig index b3f5eecff2a..a470f573f29 100644 --- a/arch/microblaze/configs/mmu_defconfig +++ b/arch/microblaze/configs/mmu_defconfig @@ -1,25 +1,22 @@ CONFIG_EXPERIMENTAL=y CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_FHANDLE=y +CONFIG_AUDIT=y +CONFIG_AUDIT_LOGINUID_IMMUTABLE=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y +CONFIG_SYSFS_DEPRECATED=y CONFIG_SYSFS_DEPRECATED_V2=y -CONFIG_BLK_DEV_INITRD=y -CONFIG_INITRAMFS_SOURCE="rootfs.cpio" -CONFIG_INITRAMFS_COMPRESSION_GZIP=y -# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -CONFIG_EXPERT=y CONFIG_KALLSYMS_ALL=y -CONFIG_KALLSYMS_EXTRA_PASS=y -# CONFIG_HOTPLUG is not set # CONFIG_BASE_FULL is not set -# CONFIG_FUTEX is not set -# CONFIG_EPOLL is not set -# CONFIG_SIGNALFD is not set -# CONFIG_SHMEM is not set +CONFIG_EMBEDDED=y CONFIG_SLAB=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y # CONFIG_BLK_DEV_BSG is not set +CONFIG_PARTITION_ADVANCED=y +# CONFIG_EFI_PARTITION is not set CONFIG_OPT_LIB_ASM=y CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR=1 CONFIG_XILINX_MICROBLAZE0_USE_PCMP_INSTR=1 @@ -37,33 +34,53 @@ CONFIG_UNIX=y CONFIG_INET=y # CONFIG_INET_LRO is not set # CONFIG_IPV6 is not set +CONFIG_MTD=y CONFIG_PROC_DEVICETREE=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=8192 CONFIG_NETDEVICES=y -CONFIG_NET_ETHERNET=y CONFIG_XILINX_EMACLITE=y +CONFIG_XILINX_LL_TEMAC=y # CONFIG_INPUT is not set # CONFIG_SERIO is not set # CONFIG_VT is not set +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y CONFIG_SERIAL_UARTLITE=y CONFIG_SERIAL_UARTLITE_CONSOLE=y # CONFIG_HW_RANDOM is not set +CONFIG_XILINX_HWICAP=y +CONFIG_I2C=y +CONFIG_I2C_XILINX=y +CONFIG_SPI=y +CONFIG_SPI_XILINX=y +CONFIG_GPIOLIB=y +CONFIG_GPIO_SYSFS=y +CONFIG_GPIO_XILINX=y # CONFIG_HWMON is not set +CONFIG_WATCHDOG=y +CONFIG_XILINX_WATCHDOG=y +CONFIG_FB=y +CONFIG_FB_XILINX=y # CONFIG_USB_SUPPORT is not set +CONFIG_UIO=y +CONFIG_UIO_PDRV=y +CONFIG_UIO_PDRV_GENIRQ=y +CONFIG_UIO_DMEM_GENIRQ=y CONFIG_EXT2_FS=y # CONFIG_DNOTIFY is not set +CONFIG_CRAMFS=y +CONFIG_ROMFS_FS=y CONFIG_NFS_FS=y -CONFIG_NFS_V3=y CONFIG_CIFS=y CONFIG_CIFS_STATS=y CONFIG_CIFS_STATS2=y -CONFIG_PARTITION_ADVANCED=y -CONFIG_DEBUG_KERNEL=y CONFIG_DETECT_HUNG_TASK=y CONFIG_DEBUG_SLAB=y CONFIG_DEBUG_SPINLOCK=y CONFIG_DEBUG_INFO=y -# CONFIG_RCU_CPU_STALL_DETECTOR is not set CONFIG_EARLY_PRINTK=y +CONFIG_KEYS=y +CONFIG_ENCRYPTED_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y # CONFIG_CRYPTO_ANSI_CPRNG is not set diff --git a/arch/microblaze/configs/nommu_defconfig b/arch/microblaze/configs/nommu_defconfig index 0249e4b7e1d..5454a6de935 100644 --- a/arch/microblaze/configs/nommu_defconfig +++ b/arch/microblaze/configs/nommu_defconfig @@ -1,41 +1,40 @@ CONFIG_EXPERIMENTAL=y CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y +CONFIG_FHANDLE=y +CONFIG_AUDIT=y +CONFIG_AUDIT_LOGINUID_IMMUTABLE=y CONFIG_BSD_PROCESS_ACCT=y CONFIG_BSD_PROCESS_ACCT_V3=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y +CONFIG_SYSFS_DEPRECATED=y CONFIG_SYSFS_DEPRECATED_V2=y -CONFIG_EXPERT=y CONFIG_KALLSYMS_ALL=y -CONFIG_KALLSYMS_EXTRA_PASS=y -# CONFIG_HOTPLUG is not set # CONFIG_BASE_FULL is not set +CONFIG_EMBEDDED=y CONFIG_SLAB=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y # CONFIG_BLK_DEV_BSG is not set -# CONFIG_OPT_LIB_FUNCTION is not set +CONFIG_PARTITION_ADVANCED=y +# CONFIG_EFI_PARTITION is not set CONFIG_XILINX_MICROBLAZE0_USE_MSR_INSTR=1 CONFIG_XILINX_MICROBLAZE0_USE_PCMP_INSTR=1 CONFIG_XILINX_MICROBLAZE0_USE_BARREL=1 CONFIG_XILINX_MICROBLAZE0_USE_DIV=1 CONFIG_XILINX_MICROBLAZE0_USE_HW_MUL=2 CONFIG_XILINX_MICROBLAZE0_USE_FPU=2 -CONFIG_HIGH_RES_TIMERS=y CONFIG_HZ_100=y CONFIG_CMDLINE_BOOL=y -CONFIG_BINFMT_FLAT=y +CONFIG_CMDLINE_FORCE=y CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y CONFIG_INET=y # CONFIG_INET_LRO is not set # CONFIG_IPV6 is not set -# CONFIG_PREVENT_FIRMWARE_BUILD is not set CONFIG_MTD=y -CONFIG_MTD_CONCAT=y -CONFIG_MTD_PARTITIONS=y CONFIG_MTD_CMDLINE_PARTS=y CONFIG_MTD_CHAR=y CONFIG_MTD_BLOCK=y @@ -45,41 +44,55 @@ CONFIG_MTD_CFI_AMDSTD=y CONFIG_MTD_RAM=y CONFIG_MTD_UCLINUX=y CONFIG_PROC_DEVICETREE=y -CONFIG_BLK_DEV_NBD=y CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=8192 CONFIG_NETDEVICES=y -CONFIG_NET_ETHERNET=y +CONFIG_XILINX_EMACLITE=y +CONFIG_XILINX_LL_TEMAC=y # CONFIG_INPUT is not set # CONFIG_SERIO is not set # CONFIG_VT is not set +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y CONFIG_SERIAL_UARTLITE=y CONFIG_SERIAL_UARTLITE_CONSOLE=y -CONFIG_HW_RANDOM=y +# CONFIG_HW_RANDOM is not set +CONFIG_XILINX_HWICAP=y +CONFIG_I2C=y +CONFIG_I2C_XILINX=y +CONFIG_SPI=y +CONFIG_SPI_XILINX=y +CONFIG_GPIOLIB=y +CONFIG_GPIO_SYSFS=y +CONFIG_GPIO_XILINX=y # CONFIG_HWMON is not set -CONFIG_VIDEO_OUTPUT_CONTROL=y +CONFIG_WATCHDOG=y +CONFIG_XILINX_WATCHDOG=y +CONFIG_FB=y +CONFIG_FB_XILINX=y +# CONFIG_USB_SUPPORT is not set +CONFIG_UIO=y +CONFIG_UIO_PDRV=y +CONFIG_UIO_PDRV_GENIRQ=y +CONFIG_UIO_DMEM_GENIRQ=y CONFIG_EXT2_FS=y # CONFIG_DNOTIFY is not set CONFIG_CRAMFS=y CONFIG_ROMFS_FS=y CONFIG_NFS_FS=y -CONFIG_NFS_V3=y CONFIG_NFS_V3_ACL=y -CONFIG_UNUSED_SYMBOLS=y -CONFIG_DEBUG_FS=y -CONFIG_DEBUG_KERNEL=y -CONFIG_DEBUG_SHIRQ=y +CONFIG_NLS=y CONFIG_DETECT_HUNG_TASK=y -CONFIG_SCHEDSTATS=y -CONFIG_TIMER_STATS=y -CONFIG_DEBUG_OBJECTS=y -CONFIG_DEBUG_OBJECTS_SELFTEST=y -CONFIG_DEBUG_OBJECTS_FREE=y -CONFIG_DEBUG_OBJECTS_TIMERS=y +CONFIG_DEBUG_SLAB=y +CONFIG_DEBUG_SPINLOCK=y CONFIG_DEBUG_INFO=y -CONFIG_DEBUG_LIST=y -CONFIG_DEBUG_SG=y -# CONFIG_RCU_CPU_STALL_DETECTOR is not set -CONFIG_SYSCTL_SYSCALL_CHECK=y CONFIG_EARLY_PRINTK=y +CONFIG_KEYS=y +CONFIG_ENCRYPTED_KEYS=y +CONFIG_KEYS_DEBUG_PROC_KEYS=y +CONFIG_CRYPTO_ECB=y +CONFIG_CRYPTO_MD4=y +CONFIG_CRYPTO_MD5=y +CONFIG_CRYPTO_ARC4=y +CONFIG_CRYPTO_DES=y # CONFIG_CRYPTO_ANSI_CPRNG is not set -# CONFIG_CRC32 is not set diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index ce30e2f91d7..7d36f6efe1d 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -24,6 +24,7 @@ config MIPS select HAVE_GENERIC_HARDIRQS select GENERIC_IRQ_PROBE select GENERIC_IRQ_SHOW + select GENERIC_PCI_IOMAP select HAVE_ARCH_JUMP_LABEL select IRQ_FORCED_THREADING select HAVE_MEMBLOCK @@ -2356,7 +2357,6 @@ config PCI bool "Support for PCI controller" depends on HW_HAS_PCI select PCI_DOMAINS - select GENERIC_PCI_IOMAP select NO_GENERIC_PCI_IOPORT_MAP help Find out whether you have a PCI motherboard. PCI is the name of a diff --git a/arch/mips/include/asm/io.h b/arch/mips/include/asm/io.h index a58f22998a8..f7b3e1c1827 100644 --- a/arch/mips/include/asm/io.h +++ b/arch/mips/include/asm/io.h @@ -168,6 +168,11 @@ static inline void * isa_bus_to_virt(unsigned long address) extern void __iomem * __ioremap(phys_t offset, phys_t size, unsigned long flags); extern void __iounmap(const volatile void __iomem *addr); +#ifndef CONFIG_PCI +struct pci_dev; +static inline void pci_iounmap(struct pci_dev *dev, void __iomem *addr) {} +#endif + static inline void __iomem * __ioremap_mode(phys_t offset, unsigned long size, unsigned long flags) { diff --git a/arch/mips/include/asm/page.h b/arch/mips/include/asm/page.h index da9bd7d270d..0913b4f6e32 100644 --- a/arch/mips/include/asm/page.h +++ b/arch/mips/include/asm/page.h @@ -175,14 +175,15 @@ typedef struct { unsigned long pgprot; } pgprot_t; #ifdef CONFIG_FLATMEM -#define pfn_valid(pfn) \ -({ \ - unsigned long __pfn = (pfn); \ - /* avoid include hell */ \ - extern unsigned long min_low_pfn; \ - \ - __pfn >= min_low_pfn && __pfn < max_mapnr; \ -}) +#ifndef __ASSEMBLY__ +static inline int pfn_valid(unsigned long pfn) +{ + /* avoid include hell */ + extern unsigned long max_mapnr; + + return pfn >= ARCH_PFN_OFFSET && pfn < max_mapnr; +} +#endif #elif defined(CONFIG_SPARSEMEM) diff --git a/arch/mn10300/include/asm/signal.h b/arch/mn10300/include/asm/signal.h index 1865d72a86f..eecaa7693ef 100644 --- a/arch/mn10300/include/asm/signal.h +++ b/arch/mn10300/include/asm/signal.h @@ -131,6 +131,7 @@ struct sigaction { __sigrestore_t sa_restorer; sigset_t sa_mask; /* mask last for extensibility */ }; +#define __ARCH_HAS_SA_RESTORER struct k_sigaction { struct sigaction sa; diff --git a/arch/parisc/include/asm/pgtable.h b/arch/parisc/include/asm/pgtable.h index ee99f233935..7df49fad29f 100644 --- a/arch/parisc/include/asm/pgtable.h +++ b/arch/parisc/include/asm/pgtable.h @@ -12,11 +12,10 @@ #include #include +#include #include #include -struct vm_area_struct; - /* * kern_addr_valid(ADDR) tests if ADDR is pointing to valid kernel * memory. For the return value to be meaningful, ADDR must be >= @@ -40,7 +39,14 @@ struct vm_area_struct; do{ \ *(pteptr) = (pteval); \ } while(0) -#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval) + +extern void purge_tlb_entries(struct mm_struct *, unsigned long); + +#define set_pte_at(mm, addr, ptep, pteval) \ + do { \ + set_pte(ptep, pteval); \ + purge_tlb_entries(mm, addr); \ + } while (0) #endif /* !__ASSEMBLY__ */ @@ -466,6 +472,7 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, old = pte_val(*ptep); new = pte_val(pte_wrprotect(__pte (old))); } while (cmpxchg((unsigned long *) ptep, old, new) != old); + purge_tlb_entries(mm, addr); #else pte_t old_pte = *ptep; set_pte_at(mm, addr, ptep, pte_wrprotect(old_pte)); diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c index 9d181890a7e..fa2146341da 100644 --- a/arch/parisc/kernel/cache.c +++ b/arch/parisc/kernel/cache.c @@ -420,6 +420,24 @@ void kunmap_parisc(void *addr) EXPORT_SYMBOL(kunmap_parisc); #endif +void purge_tlb_entries(struct mm_struct *mm, unsigned long addr) +{ + unsigned long flags; + + /* Note: purge_tlb_entries can be called at startup with + no context. */ + + /* Disable preemption while we play with %sr1. */ + preempt_disable(); + mtsp(mm->context, 1); + purge_tlb_start(flags); + pdtlb(addr); + pitlb(addr); + purge_tlb_end(flags); + preempt_enable(); +} +EXPORT_SYMBOL(purge_tlb_entries); + void __flush_tlb_range(unsigned long sid, unsigned long start, unsigned long end) { diff --git a/arch/powerpc/include/asm/exception-64s.h b/arch/powerpc/include/asm/exception-64s.h index d58fc4e4149..6afb13ad161 100644 --- a/arch/powerpc/include/asm/exception-64s.h +++ b/arch/powerpc/include/asm/exception-64s.h @@ -320,7 +320,7 @@ label##_common: \ */ #define STD_EXCEPTION_COMMON_ASYNC(trap, label, hdlr) \ EXCEPTION_COMMON(trap, label, hdlr, ret_from_except_lite, \ - FINISH_NAP;RUNLATCH_ON;DISABLE_INTS) + FINISH_NAP;DISABLE_INTS;RUNLATCH_ON) /* * When the idle code in power4_idle puts the CPU into NAP mode, diff --git a/arch/powerpc/include/asm/module.h b/arch/powerpc/include/asm/module.h index 0192a4ee2bc..80de64b550e 100644 --- a/arch/powerpc/include/asm/module.h +++ b/arch/powerpc/include/asm/module.h @@ -87,10 +87,9 @@ struct exception_table_entry; void sort_ex_table(struct exception_table_entry *start, struct exception_table_entry *finish); -#ifdef CONFIG_MODVERSIONS +#if defined(CONFIG_MODVERSIONS) && defined(CONFIG_PPC64) #define ARCH_RELOCATES_KCRCTAB - -extern const unsigned long reloc_start[]; +#define reloc_start PHYSICAL_START #endif #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_MODULE_H */ diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h index d81f99430fe..762f7a65ff7 100644 --- a/arch/powerpc/include/asm/ppc-opcode.h +++ b/arch/powerpc/include/asm/ppc-opcode.h @@ -45,6 +45,10 @@ #define PPC_INST_MFSPR_DSCR_MASK 0xfc1fffff #define PPC_INST_MTSPR_DSCR 0x7c1103a6 #define PPC_INST_MTSPR_DSCR_MASK 0xfc1fffff +#define PPC_INST_MFSPR_DSCR_USER 0x7c0302a6 +#define PPC_INST_MFSPR_DSCR_USER_MASK 0xfc1fffff +#define PPC_INST_MTSPR_DSCR_USER 0x7c0303a6 +#define PPC_INST_MTSPR_DSCR_USER_MASK 0xfc1fffff #define PPC_INST_SLBFEE 0x7c0007a7 #define PPC_INST_STRING 0x7c00042a diff --git a/arch/powerpc/include/asm/rtas.h b/arch/powerpc/include/asm/rtas.h index b3ca19a7753..c1380742156 100644 --- a/arch/powerpc/include/asm/rtas.h +++ b/arch/powerpc/include/asm/rtas.h @@ -262,6 +262,8 @@ extern void rtas_progress(char *s, unsigned short hex); extern void rtas_initialize(void); extern int rtas_suspend_cpu(struct rtas_suspend_me_data *data); extern int rtas_suspend_last_cpu(struct rtas_suspend_me_data *data); +extern int rtas_online_cpus_mask(cpumask_var_t cpus); +extern int rtas_offline_cpus_mask(cpumask_var_t cpus); extern int rtas_ibm_suspend_me(struct rtas_args *); struct rtc_time; diff --git a/arch/powerpc/include/asm/signal.h b/arch/powerpc/include/asm/signal.h index 3eb13be11d8..ec63a0a4e2c 100644 --- a/arch/powerpc/include/asm/signal.h +++ b/arch/powerpc/include/asm/signal.h @@ -109,6 +109,7 @@ struct sigaction { __sigrestore_t sa_restorer; sigset_t sa_mask; /* mask last for extensibility */ }; +#define __ARCH_HAS_SA_RESTORER struct k_sigaction { struct sigaction sa; diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index 455faa38987..31a3dd020f5 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -269,7 +269,7 @@ static struct cpu_spec __initdata cpu_specs[] = { .cpu_features = CPU_FTRS_PPC970, .cpu_user_features = COMMON_USER_POWER4 | PPC_FEATURE_HAS_ALTIVEC_COMP, - .mmu_features = MMU_FTR_HPTE_TABLE, + .mmu_features = MMU_FTRS_PPC970, .icache_bsize = 128, .dcache_bsize = 128, .num_pmcs = 8, diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 9e07bd038dd..1a3607b9663 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -489,6 +489,7 @@ _GLOBAL(copy_and_flush) sync addi r5,r5,8 addi r6,r6,8 + isync blr .align 8 diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 641da9e868c..7577898b8d8 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c @@ -162,7 +162,7 @@ notrace unsigned int __check_irq_replay(void) * in case we also had a rollover while hard disabled */ local_paca->irq_happened &= ~PACA_IRQ_DEC; - if (decrementer_check_overflow()) + if ((happened & PACA_IRQ_DEC) || decrementer_check_overflow()) return 0x900; /* Finally check if an external interrupt happened */ diff --git a/arch/powerpc/kernel/machine_kexec_64.c b/arch/powerpc/kernel/machine_kexec_64.c index d7f609086a9..39833e0b282 100644 --- a/arch/powerpc/kernel/machine_kexec_64.c +++ b/arch/powerpc/kernel/machine_kexec_64.c @@ -162,6 +162,8 @@ static int kexec_all_irq_disabled = 0; static void kexec_smp_down(void *arg) { local_irq_disable(); + hard_irq_disable(); + mb(); /* make sure our irqs are disabled before we say they are */ get_paca()->kexec_state = KEXEC_STATE_IRQS_OFF; while(kexec_all_irq_disabled == 0) @@ -244,6 +246,8 @@ static void kexec_prepare_cpus(void) wake_offline_cpus(); smp_call_function(kexec_smp_down, NULL, /* wait */0); local_irq_disable(); + hard_irq_disable(); + mb(); /* make sure IRQs are disabled before we say they are */ get_paca()->kexec_state = KEXEC_STATE_IRQS_OFF; @@ -281,6 +285,7 @@ static void kexec_prepare_cpus(void) if (ppc_md.kexec_cpu_down) ppc_md.kexec_cpu_down(0, 0); local_irq_disable(); + hard_irq_disable(); } #endif /* SMP */ diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 94178e55f49..c1aef4070d3 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -1218,7 +1218,7 @@ EXPORT_SYMBOL(dump_stack); #ifdef CONFIG_PPC64 /* Called with hard IRQs off */ -void __ppc64_runlatch_on(void) +void notrace __ppc64_runlatch_on(void) { struct thread_info *ti = current_thread_info(); unsigned long ctrl; @@ -1231,7 +1231,7 @@ void __ppc64_runlatch_on(void) } /* Called with hard IRQs off */ -void __ppc64_runlatch_off(void) +void notrace __ppc64_runlatch_off(void) { struct thread_info *ti = current_thread_info(); unsigned long ctrl; diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 5de4c64202c..1c6267cffa5 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -808,6 +809,95 @@ static void rtas_percpu_suspend_me(void *info) __rtas_suspend_cpu((struct rtas_suspend_me_data *)info, 1); } +enum rtas_cpu_state { + DOWN, + UP, +}; + +#ifndef CONFIG_SMP +static int rtas_cpu_state_change_mask(enum rtas_cpu_state state, + cpumask_var_t cpus) +{ + if (!cpumask_empty(cpus)) { + cpumask_clear(cpus); + return -EINVAL; + } else + return 0; +} +#else +/* On return cpumask will be altered to indicate CPUs changed. + * CPUs with states changed will be set in the mask, + * CPUs with status unchanged will be unset in the mask. */ +static int rtas_cpu_state_change_mask(enum rtas_cpu_state state, + cpumask_var_t cpus) +{ + int cpu; + int cpuret = 0; + int ret = 0; + + if (cpumask_empty(cpus)) + return 0; + + for_each_cpu(cpu, cpus) { + switch (state) { + case DOWN: + cpuret = cpu_down(cpu); + break; + case UP: + cpuret = cpu_up(cpu); + break; + } + if (cpuret) { + pr_debug("%s: cpu_%s for cpu#%d returned %d.\n", + __func__, + ((state == UP) ? "up" : "down"), + cpu, cpuret); + if (!ret) + ret = cpuret; + if (state == UP) { + /* clear bits for unchanged cpus, return */ + cpumask_shift_right(cpus, cpus, cpu); + cpumask_shift_left(cpus, cpus, cpu); + break; + } else { + /* clear bit for unchanged cpu, continue */ + cpumask_clear_cpu(cpu, cpus); + } + } + } + + return ret; +} +#endif + +int rtas_online_cpus_mask(cpumask_var_t cpus) +{ + int ret; + + ret = rtas_cpu_state_change_mask(UP, cpus); + + if (ret) { + cpumask_var_t tmp_mask; + + if (!alloc_cpumask_var(&tmp_mask, GFP_TEMPORARY)) + return ret; + + /* Use tmp_mask to preserve cpus mask from first failure */ + cpumask_copy(tmp_mask, cpus); + rtas_offline_cpus_mask(tmp_mask); + free_cpumask_var(tmp_mask); + } + + return ret; +} +EXPORT_SYMBOL(rtas_online_cpus_mask); + +int rtas_offline_cpus_mask(cpumask_var_t cpus) +{ + return rtas_cpu_state_change_mask(DOWN, cpus); +} +EXPORT_SYMBOL(rtas_offline_cpus_mask); + int rtas_ibm_suspend_me(struct rtas_args *args) { long state; @@ -815,6 +905,8 @@ int rtas_ibm_suspend_me(struct rtas_args *args) unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; struct rtas_suspend_me_data data; DECLARE_COMPLETION_ONSTACK(done); + cpumask_var_t offline_mask; + int cpuret; if (!rtas_service_present("ibm,suspend-me")) return -ENOSYS; @@ -838,11 +930,24 @@ int rtas_ibm_suspend_me(struct rtas_args *args) return 0; } + if (!alloc_cpumask_var(&offline_mask, GFP_TEMPORARY)) + return -ENOMEM; + atomic_set(&data.working, 0); atomic_set(&data.done, 0); atomic_set(&data.error, 0); data.token = rtas_token("ibm,suspend-me"); data.complete = &done; + + /* All present CPUs must be online */ + cpumask_andnot(offline_mask, cpu_present_mask, cpu_online_mask); + cpuret = rtas_online_cpus_mask(offline_mask); + if (cpuret) { + pr_err("%s: Could not bring present CPUs online.\n", __func__); + atomic_set(&data.error, cpuret); + goto out; + } + stop_topology_update(); /* Call function on all CPUs. One of us will make the @@ -858,6 +963,14 @@ int rtas_ibm_suspend_me(struct rtas_args *args) start_topology_update(); + /* Take down CPUs not online prior to suspend */ + cpuret = rtas_offline_cpus_mask(offline_mask); + if (cpuret) + pr_warn("%s: Could not restore CPUs to offline state.\n", + __func__); + +out: + free_cpumask_var(offline_mask); return atomic_read(&data.error); } #else /* CONFIG_PPC_PSERIES */ diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index ae0843fa7a6..3bb7197a7bd 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -960,7 +960,10 @@ static int emulate_instruction(struct pt_regs *regs) #ifdef CONFIG_PPC64 /* Emulate the mfspr rD, DSCR. */ - if (((instword & PPC_INST_MFSPR_DSCR_MASK) == PPC_INST_MFSPR_DSCR) && + if ((((instword & PPC_INST_MFSPR_DSCR_USER_MASK) == + PPC_INST_MFSPR_DSCR_USER) || + ((instword & PPC_INST_MFSPR_DSCR_MASK) == + PPC_INST_MFSPR_DSCR)) && cpu_has_feature(CPU_FTR_DSCR)) { PPC_WARN_EMULATED(mfdscr, regs); rd = (instword >> 21) & 0x1f; @@ -968,7 +971,10 @@ static int emulate_instruction(struct pt_regs *regs) return 0; } /* Emulate the mtspr DSCR, rD. */ - if (((instword & PPC_INST_MTSPR_DSCR_MASK) == PPC_INST_MTSPR_DSCR) && + if ((((instword & PPC_INST_MTSPR_DSCR_USER_MASK) == + PPC_INST_MTSPR_DSCR_USER) || + ((instword & PPC_INST_MTSPR_DSCR_MASK) == + PPC_INST_MTSPR_DSCR)) && cpu_has_feature(CPU_FTR_DSCR)) { PPC_WARN_EMULATED(mtdscr, regs); rd = (instword >> 21) & 0x1f; diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S index 65d1c08cf09..7703569b5d4 100644 --- a/arch/powerpc/kernel/vmlinux.lds.S +++ b/arch/powerpc/kernel/vmlinux.lds.S @@ -38,9 +38,6 @@ jiffies = jiffies_64 + 4; #endif SECTIONS { - . = 0; - reloc_start = .; - . = KERNELBASE; /* diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index a03ea91998e..4b697ebf862 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c @@ -759,6 +759,8 @@ void __init early_init_mmu(void) /* Initialize stab / SLB management */ if (mmu_has_feature(MMU_FTR_SLB)) slb_initialize(); + else + stab_initialize(get_paca()->stab_real); } #ifdef CONFIG_SMP diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index 8c34b7fa51b..13aa781f0e1 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c @@ -201,7 +201,7 @@ int __node_distance(int a, int b) int distance = LOCAL_DISTANCE; if (!form1_affinity) - return distance; + return ((a == b) ? LOCAL_DISTANCE : REMOTE_DISTANCE); for (i = 0; i < distance_ref_points_depth; i++) { if (distance_lookup_table[a][i] == distance_lookup_table[b][i]) @@ -639,7 +639,7 @@ static void __init parse_drconf_memory(struct device_node *memory) unsigned int n, rc, ranges, is_kexec_kdump = 0; unsigned long lmb_size, base, size, sz; int nid; - struct assoc_arrays aa; + struct assoc_arrays aa = { .arrays = NULL }; n = of_get_drconf_memory(memory, &dm); if (!n) diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c index 1d75c92ea8f..ad697f84b94 100644 --- a/arch/powerpc/platforms/cell/spufs/inode.c +++ b/arch/powerpc/platforms/cell/spufs/inode.c @@ -99,6 +99,7 @@ spufs_new_inode(struct super_block *sb, umode_t mode) if (!inode) goto out; + inode->i_ino = get_next_ino(); inode->i_mode = mode; inode->i_uid = current_fsuid(); inode->i_gid = current_fsgid(); diff --git a/arch/powerpc/platforms/pseries/eeh_pseries.c b/arch/powerpc/platforms/pseries/eeh_pseries.c index 8752f79a6af..8a811d98a79 100644 --- a/arch/powerpc/platforms/pseries/eeh_pseries.c +++ b/arch/powerpc/platforms/pseries/eeh_pseries.c @@ -83,7 +83,11 @@ static int pseries_eeh_init(void) ibm_configure_pe = rtas_token("ibm,configure-pe"); ibm_configure_bridge = rtas_token ("ibm,configure-bridge"); - /* necessary sanity check */ + /* + * Necessary sanity check. We needn't check "get-config-addr-info" + * and its variant since the old firmware probably support address + * of domain/bus/slot/function for EEH RTAS operations. + */ if (ibm_set_eeh_option == RTAS_UNKNOWN_SERVICE) { pr_warning("%s: RTAS service invalid\n", __func__); @@ -102,12 +106,6 @@ static int pseries_eeh_init(void) pr_warning("%s: RTAS service invalid\n", __func__); return -EINVAL; - } else if (ibm_get_config_addr_info2 == RTAS_UNKNOWN_SERVICE && - ibm_get_config_addr_info == RTAS_UNKNOWN_SERVICE) { - pr_warning("%s: RTAS service and " - " invalid\n", - __func__); - return -EINVAL; } else if (ibm_configure_pe == RTAS_UNKNOWN_SERVICE && ibm_configure_bridge == RTAS_UNKNOWN_SERVICE) { pr_warning("%s: RTAS service and " diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index 5f3ef876ded..9cfdcc95c57 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c @@ -187,7 +187,13 @@ static long pSeries_lpar_hpte_remove(unsigned long hpte_group) (0x1UL << 4), &dummy1, &dummy2); if (lpar_rc == H_SUCCESS) return i; - BUG_ON(lpar_rc != H_NOT_FOUND); + + /* + * The test for adjunct partition is performed before the + * ANDCOND test. H_RESOURCE may be returned, so we need to + * check for that as well. + */ + BUG_ON(lpar_rc != H_NOT_FOUND && lpar_rc != H_RESOURCE); slot_offset++; slot_offset &= 0x7; diff --git a/arch/powerpc/platforms/pseries/suspend.c b/arch/powerpc/platforms/pseries/suspend.c index 47226e04126..5f997e79d57 100644 --- a/arch/powerpc/platforms/pseries/suspend.c +++ b/arch/powerpc/platforms/pseries/suspend.c @@ -16,6 +16,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include #include #include #include @@ -126,11 +127,15 @@ static ssize_t store_hibernate(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { + cpumask_var_t offline_mask; int rc; if (!capable(CAP_SYS_ADMIN)) return -EPERM; + if (!alloc_cpumask_var(&offline_mask, GFP_TEMPORARY)) + return -ENOMEM; + stream_id = simple_strtoul(buf, NULL, 16); do { @@ -140,15 +145,32 @@ static ssize_t store_hibernate(struct device *dev, } while (rc == -EAGAIN); if (!rc) { + /* All present CPUs must be online */ + cpumask_andnot(offline_mask, cpu_present_mask, + cpu_online_mask); + rc = rtas_online_cpus_mask(offline_mask); + if (rc) { + pr_err("%s: Could not bring present CPUs online.\n", + __func__); + goto out; + } + stop_topology_update(); rc = pm_suspend(PM_SUSPEND_MEM); start_topology_update(); + + /* Take down CPUs not online prior to suspend */ + if (!rtas_offline_cpus_mask(offline_mask)) + pr_warn("%s: Could not restore CPUs to offline " + "state.\n", __func__); } stream_id = 0; if (!rc) rc = count; +out: + free_cpumask_var(offline_mask); return rc; } diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h index 011358c1b18..2f36a66afe7 100644 --- a/arch/s390/include/asm/pgtable.h +++ b/arch/s390/include/asm/pgtable.h @@ -67,6 +67,10 @@ static inline int is_zero_pfn(unsigned long pfn) #define my_zero_pfn(addr) page_to_pfn(ZERO_PAGE(addr)) +/* TODO: s390 cannot support io_remap_pfn_range... */ +#define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \ + remap_pfn_range(vma, vaddr, pfn, size, prot) + #endif /* !__ASSEMBLY__ */ /* diff --git a/arch/s390/include/asm/signal.h b/arch/s390/include/asm/signal.h index cdf5cb2fe03..c872626346e 100644 --- a/arch/s390/include/asm/signal.h +++ b/arch/s390/include/asm/signal.h @@ -131,6 +131,7 @@ struct sigaction { void (*sa_restorer)(void); sigset_t sa_mask; /* mask last for extensibility */ }; +#define __ARCH_HAS_SA_RESTORER struct k_sigaction { struct sigaction sa; diff --git a/arch/s390/include/asm/tlbflush.h b/arch/s390/include/asm/tlbflush.h index 1d8648cf2fe..874302942c3 100644 --- a/arch/s390/include/asm/tlbflush.h +++ b/arch/s390/include/asm/tlbflush.h @@ -74,8 +74,6 @@ static inline void __tlb_flush_idte(unsigned long asce) static inline void __tlb_flush_mm(struct mm_struct * mm) { - if (unlikely(cpumask_empty(mm_cpumask(mm)))) - return; /* * If the machine has IDTE we prefer to do a per mm flush * on all cpus instead of doing a local flush if the mm diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index 74ee563fe62..009518c8955 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -669,7 +669,8 @@ ENTRY(mcck_int_handler) UPDATE_VTIME %r14,%r15,__LC_MCCK_ENTER_TIMER mcck_skip: SWITCH_ASYNC __LC_GPREGS_SAVE_AREA+32,__LC_PANIC_STACK,PAGE_SHIFT - mvc __PT_R0(64,%r11),__LC_GPREGS_SAVE_AREA + stm %r0,%r7,__PT_R0(%r11) + mvc __PT_R8(32,%r11),__LC_GPREGS_SAVE_AREA+32 stm %r8,%r9,__PT_PSW(%r11) xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) l %r1,BASED(.Ldo_machine_check) diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 4e1c292fa7e..b6f3e7c97db 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S @@ -689,8 +689,9 @@ ENTRY(mcck_int_handler) UPDATE_VTIME %r14,__LC_MCCK_ENTER_TIMER LAST_BREAK %r14 mcck_skip: - lghi %r14,__LC_GPREGS_SAVE_AREA - mvc __PT_R0(128,%r11),0(%r14) + lghi %r14,__LC_GPREGS_SAVE_AREA+64 + stmg %r0,%r7,__PT_R0(%r11) + mvc __PT_R8(64,%r11),0(%r14) stmg %r8,%r9,__PT_PSW(%r11) xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) lgr %r2,%r11 # pass pointer to pt_regs diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index c5531dbc8b2..747ab28d0e6 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c @@ -121,6 +121,9 @@ static int s390_next_ktime(ktime_t expires, nsecs = ktime_to_ns(ktime_add(timespec_to_ktime(ts), expires)); do_div(nsecs, 125); S390_lowcore.clock_comparator = sched_clock_base_cc + (nsecs << 9); + /* Program the maximum value if we have an overflow (== year 2042) */ + if (unlikely(S390_lowcore.clock_comparator < sched_clock_base_cc)) + S390_lowcore.clock_comparator = -1ULL; set_clock_comparator(S390_lowcore.clock_comparator); return 0; } diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index 217ce44395a..e00accf9523 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -677,6 +677,14 @@ int kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, unsigned long addr) } else prefix = 0; + /* + * The guest FPRS and ACRS are in the host FPRS/ACRS due to the lazy + * copying in vcpu load/put. Lets update our copies before we save + * it into the save area + */ + save_fp_regs(&vcpu->arch.guest_fpregs); + save_access_regs(vcpu->run->s.regs.acrs); + if (__guestcopy(vcpu, addr + offsetof(struct save_area, fp_regs), vcpu->arch.guest_fpregs.fprs, 128, prefix)) return -EFAULT; diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h index 76e4a52aa85..656de8bc0ed 100644 --- a/arch/sparc/include/asm/pgtable_64.h +++ b/arch/sparc/include/asm/pgtable_64.h @@ -780,6 +780,7 @@ static inline int io_remap_pfn_range(struct vm_area_struct *vma, return remap_pfn_range(vma, from, phys_base >> PAGE_SHIFT, size, prot); } +#include #include /* We provide our own get_unmapped_area to cope with VA holes and diff --git a/arch/sparc/include/asm/signal.h b/arch/sparc/include/asm/signal.h index aa42fe30d5b..d07beb36dcc 100644 --- a/arch/sparc/include/asm/signal.h +++ b/arch/sparc/include/asm/signal.h @@ -192,6 +192,7 @@ struct __old_sigaction { unsigned long sa_flags; void (*sa_restorer)(void); /* not used by Linux/SPARC yet */ }; +#define __ARCH_HAS_SA_RESTORER typedef struct sigaltstack { void __user *ss_sp; diff --git a/arch/sparc/include/asm/switch_to_64.h b/arch/sparc/include/asm/switch_to_64.h index 7923c4a2be3..9c2a92d44d3 100644 --- a/arch/sparc/include/asm/switch_to_64.h +++ b/arch/sparc/include/asm/switch_to_64.h @@ -18,8 +18,7 @@ do { \ * and 2 stores in this critical code path. -DaveM */ #define switch_to(prev, next, last) \ -do { flush_tlb_pending(); \ - save_and_clear_fpu(); \ +do { save_and_clear_fpu(); \ /* If you are tempted to conditionalize the following */ \ /* so that ASI is only written if it changes, think again. */ \ __asm__ __volatile__("wr %%g0, %0, %%asi" \ diff --git a/arch/sparc/include/asm/tlbflush_64.h b/arch/sparc/include/asm/tlbflush_64.h index 2ef46349415..f0d6a9700f4 100644 --- a/arch/sparc/include/asm/tlbflush_64.h +++ b/arch/sparc/include/asm/tlbflush_64.h @@ -11,24 +11,40 @@ struct tlb_batch { struct mm_struct *mm; unsigned long tlb_nr; + unsigned long active; unsigned long vaddrs[TLB_BATCH_NR]; }; extern void flush_tsb_kernel_range(unsigned long start, unsigned long end); extern void flush_tsb_user(struct tlb_batch *tb); +extern void flush_tsb_user_page(struct mm_struct *mm, unsigned long vaddr); /* TLB flush operations. */ -extern void flush_tlb_pending(void); +static inline void flush_tlb_mm(struct mm_struct *mm) +{ +} + +static inline void flush_tlb_page(struct vm_area_struct *vma, + unsigned long vmaddr) +{ +} + +static inline void flush_tlb_range(struct vm_area_struct *vma, + unsigned long start, unsigned long end) +{ +} + +#define __HAVE_ARCH_ENTER_LAZY_MMU_MODE -#define flush_tlb_range(vma,start,end) \ - do { (void)(start); flush_tlb_pending(); } while (0) -#define flush_tlb_page(vma,addr) flush_tlb_pending() -#define flush_tlb_mm(mm) flush_tlb_pending() +extern void flush_tlb_pending(void); +extern void arch_enter_lazy_mmu_mode(void); +extern void arch_leave_lazy_mmu_mode(void); +#define arch_flush_lazy_mmu_mode() do {} while (0) /* Local cpu only. */ extern void __flush_tlb_all(void); - +extern void __flush_tlb_page(unsigned long context, unsigned long vaddr); extern void __flush_tlb_kernel_range(unsigned long start, unsigned long end); #ifndef CONFIG_SMP @@ -38,15 +54,24 @@ do { flush_tsb_kernel_range(start,end); \ __flush_tlb_kernel_range(start,end); \ } while (0) +static inline void global_flush_tlb_page(struct mm_struct *mm, unsigned long vaddr) +{ + __flush_tlb_page(CTX_HWBITS(mm->context), vaddr); +} + #else /* CONFIG_SMP */ extern void smp_flush_tlb_kernel_range(unsigned long start, unsigned long end); +extern void smp_flush_tlb_page(struct mm_struct *mm, unsigned long vaddr); #define flush_tlb_kernel_range(start, end) \ do { flush_tsb_kernel_range(start,end); \ smp_flush_tlb_kernel_range(start, end); \ } while (0) +#define global_flush_tlb_page(mm, vaddr) \ + smp_flush_tlb_page(mm, vaddr) + #endif /* ! CONFIG_SMP */ #endif /* _SPARC64_TLBFLUSH_H */ diff --git a/arch/sparc/kernel/asm-offsets.c b/arch/sparc/kernel/asm-offsets.c index 68f7e1118e9..ce482032deb 100644 --- a/arch/sparc/kernel/asm-offsets.c +++ b/arch/sparc/kernel/asm-offsets.c @@ -34,6 +34,8 @@ int foo(void) DEFINE(AOFF_task_thread, offsetof(struct task_struct, thread)); BLANK(); DEFINE(AOFF_mm_context, offsetof(struct mm_struct, context)); + BLANK(); + DEFINE(VMA_VM_MM, offsetof(struct vm_area_struct, vm_mm)); /* DEFINE(NUM_USER_SEGMENTS, TASK_SIZE>>28); */ return 0; diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c index 67d6426cd1e..66aa4ae32a8 100644 --- a/arch/sparc/kernel/smp_64.c +++ b/arch/sparc/kernel/smp_64.c @@ -856,7 +856,7 @@ void smp_tsb_sync(struct mm_struct *mm) } extern unsigned long xcall_flush_tlb_mm; -extern unsigned long xcall_flush_tlb_pending; +extern unsigned long xcall_flush_tlb_page; extern unsigned long xcall_flush_tlb_kernel_range; extern unsigned long xcall_fetch_glob_regs; extern unsigned long xcall_receive_signal; @@ -1070,23 +1070,56 @@ void smp_flush_tlb_mm(struct mm_struct *mm) put_cpu(); } +struct tlb_pending_info { + unsigned long ctx; + unsigned long nr; + unsigned long *vaddrs; +}; + +static void tlb_pending_func(void *info) +{ + struct tlb_pending_info *t = info; + + __flush_tlb_pending(t->ctx, t->nr, t->vaddrs); +} + void smp_flush_tlb_pending(struct mm_struct *mm, unsigned long nr, unsigned long *vaddrs) { u32 ctx = CTX_HWBITS(mm->context); + struct tlb_pending_info info; int cpu = get_cpu(); + info.ctx = ctx; + info.nr = nr; + info.vaddrs = vaddrs; + if (mm == current->mm && atomic_read(&mm->mm_users) == 1) cpumask_copy(mm_cpumask(mm), cpumask_of(cpu)); else - smp_cross_call_masked(&xcall_flush_tlb_pending, - ctx, nr, (unsigned long) vaddrs, - mm_cpumask(mm)); + smp_call_function_many(mm_cpumask(mm), tlb_pending_func, + &info, 1); __flush_tlb_pending(ctx, nr, vaddrs); put_cpu(); } +void smp_flush_tlb_page(struct mm_struct *mm, unsigned long vaddr) +{ + unsigned long context = CTX_HWBITS(mm->context); + int cpu = get_cpu(); + + if (mm == current->mm && atomic_read(&mm->mm_users) == 1) + cpumask_copy(mm_cpumask(mm), cpumask_of(cpu)); + else + smp_cross_call_masked(&xcall_flush_tlb_page, + context, vaddr, 0, + mm_cpumask(mm)); + __flush_tlb_page(context, vaddr); + + put_cpu(); +} + void smp_flush_tlb_kernel_range(unsigned long start, unsigned long end) { start &= PAGE_MASK; diff --git a/arch/sparc/lib/Makefile b/arch/sparc/lib/Makefile index a3fc4375a15..4961516ecb3 100644 --- a/arch/sparc/lib/Makefile +++ b/arch/sparc/lib/Makefile @@ -40,7 +40,7 @@ lib-$(CONFIG_SPARC64) += copy_in_user.o user_fixup.o memmove.o lib-$(CONFIG_SPARC64) += mcount.o ipcsum.o xor.o hweight.o ffs.o obj-y += iomap.o -obj-$(CONFIG_SPARC32) += atomic32.o +obj-$(CONFIG_SPARC32) += atomic32.o ucmpdi2.o obj-y += ksyms.o obj-$(CONFIG_SPARC64) += PeeCeeI.o obj-y += usercopy.o diff --git a/arch/sparc/mm/hypersparc.S b/arch/sparc/mm/hypersparc.S index 44aad32eeb4..969f96450f6 100644 --- a/arch/sparc/mm/hypersparc.S +++ b/arch/sparc/mm/hypersparc.S @@ -74,7 +74,7 @@ hypersparc_flush_cache_mm_out: /* The things we do for performance... */ hypersparc_flush_cache_range: - ld [%o0 + 0x0], %o0 /* XXX vma->vm_mm, GROSS XXX */ + ld [%o0 + VMA_VM_MM], %o0 #ifndef CONFIG_SMP ld [%o0 + AOFF_mm_context], %g1 cmp %g1, -1 @@ -163,7 +163,7 @@ hypersparc_flush_cache_range_out: */ /* Verified, my ass... */ hypersparc_flush_cache_page: - ld [%o0 + 0x0], %o0 /* XXX vma->vm_mm, GROSS XXX */ + ld [%o0 + VMA_VM_MM], %o0 ld [%o0 + AOFF_mm_context], %g2 #ifndef CONFIG_SMP cmp %g2, -1 @@ -284,7 +284,7 @@ hypersparc_flush_tlb_mm_out: sta %g5, [%g1] ASI_M_MMUREGS hypersparc_flush_tlb_range: - ld [%o0 + 0x00], %o0 /* XXX vma->vm_mm GROSS XXX */ + ld [%o0 + VMA_VM_MM], %o0 mov SRMMU_CTX_REG, %g1 ld [%o0 + AOFF_mm_context], %o3 lda [%g1] ASI_M_MMUREGS, %g5 @@ -307,7 +307,7 @@ hypersparc_flush_tlb_range_out: sta %g5, [%g1] ASI_M_MMUREGS hypersparc_flush_tlb_page: - ld [%o0 + 0x00], %o0 /* XXX vma->vm_mm GROSS XXX */ + ld [%o0 + VMA_VM_MM], %o0 mov SRMMU_CTX_REG, %g1 ld [%o0 + AOFF_mm_context], %o3 andn %o1, (PAGE_SIZE - 1), %o1 diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c index e5ce436ec30..ef4832be3dd 100644 --- a/arch/sparc/mm/init_64.c +++ b/arch/sparc/mm/init_64.c @@ -1067,7 +1067,14 @@ static int __init grab_mblocks(struct mdesc_handle *md) m->size = *val; val = mdesc_get_property(md, node, "address-congruence-offset", NULL); - m->offset = *val; + + /* The address-congruence-offset property is optional. + * Explicity zero it be identifty this. + */ + if (val) + m->offset = *val; + else + m->offset = 0UL; numadbg("MBLOCK[%d]: base[%llx] size[%llx] offset[%llx]\n", count - 1, m->base, m->size, m->offset); diff --git a/arch/sparc/mm/swift.S b/arch/sparc/mm/swift.S index c801c3953a0..5d2b88d3942 100644 --- a/arch/sparc/mm/swift.S +++ b/arch/sparc/mm/swift.S @@ -105,7 +105,7 @@ swift_flush_cache_mm_out: .globl swift_flush_cache_range swift_flush_cache_range: - ld [%o0 + 0x0], %o0 /* XXX vma->vm_mm, GROSS XXX */ + ld [%o0 + VMA_VM_MM], %o0 sub %o2, %o1, %o2 sethi %hi(4096), %o3 cmp %o2, %o3 @@ -116,7 +116,7 @@ swift_flush_cache_range: .globl swift_flush_cache_page swift_flush_cache_page: - ld [%o0 + 0x0], %o0 /* XXX vma->vm_mm, GROSS XXX */ + ld [%o0 + VMA_VM_MM], %o0 70: ld [%o0 + AOFF_mm_context], %g2 cmp %g2, -1 @@ -219,7 +219,7 @@ swift_flush_sig_insns: .globl swift_flush_tlb_range .globl swift_flush_tlb_all swift_flush_tlb_range: - ld [%o0 + 0x00], %o0 /* XXX vma->vm_mm GROSS XXX */ + ld [%o0 + VMA_VM_MM], %o0 swift_flush_tlb_mm: ld [%o0 + AOFF_mm_context], %g2 cmp %g2, -1 @@ -233,7 +233,7 @@ swift_flush_tlb_all_out: .globl swift_flush_tlb_page swift_flush_tlb_page: - ld [%o0 + 0x00], %o0 /* XXX vma->vm_mm GROSS XXX */ + ld [%o0 + VMA_VM_MM], %o0 mov SRMMU_CTX_REG, %g1 ld [%o0 + AOFF_mm_context], %o3 andn %o1, (PAGE_SIZE - 1), %o1 diff --git a/arch/sparc/mm/tlb.c b/arch/sparc/mm/tlb.c index b1f279cd00b..072f5530373 100644 --- a/arch/sparc/mm/tlb.c +++ b/arch/sparc/mm/tlb.c @@ -24,11 +24,17 @@ static DEFINE_PER_CPU(struct tlb_batch, tlb_batch); void flush_tlb_pending(void) { struct tlb_batch *tb = &get_cpu_var(tlb_batch); + struct mm_struct *mm = tb->mm; - if (tb->tlb_nr) { - flush_tsb_user(tb); + if (!tb->tlb_nr) + goto out; - if (CTX_VALID(tb->mm->context)) { + flush_tsb_user(tb); + + if (CTX_VALID(mm->context)) { + if (tb->tlb_nr == 1) { + global_flush_tlb_page(mm, tb->vaddrs[0]); + } else { #ifdef CONFIG_SMP smp_flush_tlb_pending(tb->mm, tb->tlb_nr, &tb->vaddrs[0]); @@ -37,12 +43,30 @@ void flush_tlb_pending(void) tb->tlb_nr, &tb->vaddrs[0]); #endif } - tb->tlb_nr = 0; } + tb->tlb_nr = 0; + +out: put_cpu_var(tlb_batch); } +void arch_enter_lazy_mmu_mode(void) +{ + struct tlb_batch *tb = &__get_cpu_var(tlb_batch); + + tb->active = 1; +} + +void arch_leave_lazy_mmu_mode(void) +{ + struct tlb_batch *tb = &__get_cpu_var(tlb_batch); + + if (tb->tlb_nr) + flush_tlb_pending(); + tb->active = 0; +} + void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr, pte_t *ptep, pte_t orig, int fullmm) { @@ -90,6 +114,12 @@ void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr, nr = 0; } + if (!tb->active) { + flush_tsb_user_page(mm, vaddr); + global_flush_tlb_page(mm, vaddr); + goto out; + } + if (nr == 0) tb->mm = mm; @@ -98,5 +128,6 @@ void tlb_batch_add(struct mm_struct *mm, unsigned long vaddr, if (nr >= TLB_BATCH_NR) flush_tlb_pending(); +out: put_cpu_var(tlb_batch); } diff --git a/arch/sparc/mm/tsb.c b/arch/sparc/mm/tsb.c index c52add79b83..f4e84f3440d 100644 --- a/arch/sparc/mm/tsb.c +++ b/arch/sparc/mm/tsb.c @@ -7,11 +7,10 @@ #include #include #include -#include -#include -#include #include +#include #include +#include #include extern struct tsb swapper_tsb[KERNEL_TSB_NENTRIES]; @@ -46,23 +45,27 @@ void flush_tsb_kernel_range(unsigned long start, unsigned long end) } } -static void __flush_tsb_one(struct tlb_batch *tb, unsigned long hash_shift, - unsigned long tsb, unsigned long nentries) +static void __flush_tsb_one_entry(unsigned long tsb, unsigned long v, + unsigned long hash_shift, + unsigned long nentries) { - unsigned long i; + unsigned long tag, ent, hash; - for (i = 0; i < tb->tlb_nr; i++) { - unsigned long v = tb->vaddrs[i]; - unsigned long tag, ent, hash; + v &= ~0x1UL; + hash = tsb_hash(v, hash_shift, nentries); + ent = tsb + (hash * sizeof(struct tsb)); + tag = (v >> 22UL); - v &= ~0x1UL; + tsb_flush(ent, tag); +} - hash = tsb_hash(v, hash_shift, nentries); - ent = tsb + (hash * sizeof(struct tsb)); - tag = (v >> 22UL); +static void __flush_tsb_one(struct tlb_batch *tb, unsigned long hash_shift, + unsigned long tsb, unsigned long nentries) +{ + unsigned long i; - tsb_flush(ent, tag); - } + for (i = 0; i < tb->tlb_nr; i++) + __flush_tsb_one_entry(tsb, tb->vaddrs[i], hash_shift, nentries); } void flush_tsb_user(struct tlb_batch *tb) @@ -90,6 +93,30 @@ void flush_tsb_user(struct tlb_batch *tb) spin_unlock_irqrestore(&mm->context.lock, flags); } +void flush_tsb_user_page(struct mm_struct *mm, unsigned long vaddr) +{ + unsigned long nentries, base, flags; + + spin_lock_irqsave(&mm->context.lock, flags); + + base = (unsigned long) mm->context.tsb_block[MM_TSB_BASE].tsb; + nentries = mm->context.tsb_block[MM_TSB_BASE].tsb_nentries; + if (tlb_type == cheetah_plus || tlb_type == hypervisor) + base = __pa(base); + __flush_tsb_one_entry(base, vaddr, PAGE_SHIFT, nentries); + +#if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE) + if (mm->context.tsb_block[MM_TSB_HUGE].tsb) { + base = (unsigned long) mm->context.tsb_block[MM_TSB_HUGE].tsb; + nentries = mm->context.tsb_block[MM_TSB_HUGE].tsb_nentries; + if (tlb_type == cheetah_plus || tlb_type == hypervisor) + base = __pa(base); + __flush_tsb_one_entry(base, vaddr, HPAGE_SHIFT, nentries); + } +#endif + spin_unlock_irqrestore(&mm->context.lock, flags); +} + #if defined(CONFIG_SPARC64_PAGE_SIZE_8KB) #define HV_PGSZ_IDX_BASE HV_PGSZ_IDX_8K #define HV_PGSZ_MASK_BASE HV_PGSZ_MASK_8K diff --git a/arch/sparc/mm/tsunami.S b/arch/sparc/mm/tsunami.S index 4e55e8f7664..bf10a345fa8 100644 --- a/arch/sparc/mm/tsunami.S +++ b/arch/sparc/mm/tsunami.S @@ -24,7 +24,7 @@ /* Sliiick... */ tsunami_flush_cache_page: tsunami_flush_cache_range: - ld [%o0 + 0x0], %o0 /* XXX vma->vm_mm, GROSS XXX */ + ld [%o0 + VMA_VM_MM], %o0 tsunami_flush_cache_mm: ld [%o0 + AOFF_mm_context], %g2 cmp %g2, -1 @@ -46,7 +46,7 @@ tsunami_flush_sig_insns: /* More slick stuff... */ tsunami_flush_tlb_range: - ld [%o0 + 0x00], %o0 /* XXX vma->vm_mm GROSS XXX */ + ld [%o0 + VMA_VM_MM], %o0 tsunami_flush_tlb_mm: ld [%o0 + AOFF_mm_context], %g2 cmp %g2, -1 @@ -65,7 +65,7 @@ tsunami_flush_tlb_out: /* This one can be done in a fine grained manner... */ tsunami_flush_tlb_page: - ld [%o0 + 0x00], %o0 /* XXX vma->vm_mm GROSS XXX */ + ld [%o0 + VMA_VM_MM], %o0 mov SRMMU_CTX_REG, %g1 ld [%o0 + AOFF_mm_context], %o3 andn %o1, (PAGE_SIZE - 1), %o1 diff --git a/arch/sparc/mm/ultra.S b/arch/sparc/mm/ultra.S index 874162a11ce..dd10caac010 100644 --- a/arch/sparc/mm/ultra.S +++ b/arch/sparc/mm/ultra.S @@ -52,6 +52,33 @@ __flush_tlb_mm: /* 18 insns */ nop nop + .align 32 + .globl __flush_tlb_page +__flush_tlb_page: /* 22 insns */ + /* %o0 = context, %o1 = vaddr */ + rdpr %pstate, %g7 + andn %g7, PSTATE_IE, %g2 + wrpr %g2, %pstate + mov SECONDARY_CONTEXT, %o4 + ldxa [%o4] ASI_DMMU, %g2 + stxa %o0, [%o4] ASI_DMMU + andcc %o1, 1, %g0 + andn %o1, 1, %o3 + be,pn %icc, 1f + or %o3, 0x10, %o3 + stxa %g0, [%o3] ASI_IMMU_DEMAP +1: stxa %g0, [%o3] ASI_DMMU_DEMAP + membar #Sync + stxa %g2, [%o4] ASI_DMMU + sethi %hi(KERNBASE), %o4 + flush %o4 + retl + wrpr %g7, 0x0, %pstate + nop + nop + nop + nop + .align 32 .globl __flush_tlb_pending __flush_tlb_pending: /* 26 insns */ @@ -203,6 +230,31 @@ __cheetah_flush_tlb_mm: /* 19 insns */ retl wrpr %g7, 0x0, %pstate +__cheetah_flush_tlb_page: /* 22 insns */ + /* %o0 = context, %o1 = vaddr */ + rdpr %pstate, %g7 + andn %g7, PSTATE_IE, %g2 + wrpr %g2, 0x0, %pstate + wrpr %g0, 1, %tl + mov PRIMARY_CONTEXT, %o4 + ldxa [%o4] ASI_DMMU, %g2 + srlx %g2, CTX_PGSZ1_NUC_SHIFT, %o3 + sllx %o3, CTX_PGSZ1_NUC_SHIFT, %o3 + or %o0, %o3, %o0 /* Preserve nucleus page size fields */ + stxa %o0, [%o4] ASI_DMMU + andcc %o1, 1, %g0 + be,pn %icc, 1f + andn %o1, 1, %o3 + stxa %g0, [%o3] ASI_IMMU_DEMAP +1: stxa %g0, [%o3] ASI_DMMU_DEMAP + membar #Sync + stxa %g2, [%o4] ASI_DMMU + sethi %hi(KERNBASE), %o4 + flush %o4 + wrpr %g0, 0, %tl + retl + wrpr %g7, 0x0, %pstate + __cheetah_flush_tlb_pending: /* 27 insns */ /* %o0 = context, %o1 = nr, %o2 = vaddrs[] */ rdpr %pstate, %g7 @@ -269,6 +321,20 @@ __hypervisor_flush_tlb_mm: /* 10 insns */ retl nop +__hypervisor_flush_tlb_page: /* 11 insns */ + /* %o0 = context, %o1 = vaddr */ + mov %o0, %g2 + mov %o1, %o0 /* ARG0: vaddr + IMMU-bit */ + mov %g2, %o1 /* ARG1: mmu context */ + mov HV_MMU_ALL, %o2 /* ARG2: flags */ + srlx %o0, PAGE_SHIFT, %o0 + sllx %o0, PAGE_SHIFT, %o0 + ta HV_MMU_UNMAP_ADDR_TRAP + brnz,pn %o0, __hypervisor_tlb_tl0_error + mov HV_MMU_UNMAP_ADDR_TRAP, %o1 + retl + nop + __hypervisor_flush_tlb_pending: /* 16 insns */ /* %o0 = context, %o1 = nr, %o2 = vaddrs[] */ sllx %o1, 3, %g1 @@ -339,6 +405,13 @@ cheetah_patch_cachetlbops: call tlb_patch_one mov 19, %o2 + sethi %hi(__flush_tlb_page), %o0 + or %o0, %lo(__flush_tlb_page), %o0 + sethi %hi(__cheetah_flush_tlb_page), %o1 + or %o1, %lo(__cheetah_flush_tlb_page), %o1 + call tlb_patch_one + mov 22, %o2 + sethi %hi(__flush_tlb_pending), %o0 or %o0, %lo(__flush_tlb_pending), %o0 sethi %hi(__cheetah_flush_tlb_pending), %o1 @@ -397,10 +470,9 @@ xcall_flush_tlb_mm: /* 21 insns */ nop nop - .globl xcall_flush_tlb_pending -xcall_flush_tlb_pending: /* 21 insns */ - /* %g5=context, %g1=nr, %g7=vaddrs[] */ - sllx %g1, 3, %g1 + .globl xcall_flush_tlb_page +xcall_flush_tlb_page: /* 17 insns */ + /* %g5=context, %g1=vaddr */ mov PRIMARY_CONTEXT, %g4 ldxa [%g4] ASI_DMMU, %g2 srlx %g2, CTX_PGSZ1_NUC_SHIFT, %g4 @@ -408,20 +480,16 @@ xcall_flush_tlb_pending: /* 21 insns */ or %g5, %g4, %g5 mov PRIMARY_CONTEXT, %g4 stxa %g5, [%g4] ASI_DMMU -1: sub %g1, (1 << 3), %g1 - ldx [%g7 + %g1], %g5 - andcc %g5, 0x1, %g0 + andcc %g1, 0x1, %g0 be,pn %icc, 2f - - andn %g5, 0x1, %g5 + andn %g1, 0x1, %g5 stxa %g0, [%g5] ASI_IMMU_DEMAP 2: stxa %g0, [%g5] ASI_DMMU_DEMAP membar #Sync - brnz,pt %g1, 1b - nop stxa %g2, [%g4] ASI_DMMU retry nop + nop .globl xcall_flush_tlb_kernel_range xcall_flush_tlb_kernel_range: /* 25 insns */ @@ -596,15 +664,13 @@ __hypervisor_xcall_flush_tlb_mm: /* 21 insns */ membar #Sync retry - .globl __hypervisor_xcall_flush_tlb_pending -__hypervisor_xcall_flush_tlb_pending: /* 21 insns */ - /* %g5=ctx, %g1=nr, %g7=vaddrs[], %g2,%g3,%g4,g6=scratch */ - sllx %g1, 3, %g1 + .globl __hypervisor_xcall_flush_tlb_page +__hypervisor_xcall_flush_tlb_page: /* 17 insns */ + /* %g5=ctx, %g1=vaddr */ mov %o0, %g2 mov %o1, %g3 mov %o2, %g4 -1: sub %g1, (1 << 3), %g1 - ldx [%g7 + %g1], %o0 /* ARG0: virtual address */ + mov %g1, %o0 /* ARG0: virtual address */ mov %g5, %o1 /* ARG1: mmu context */ mov HV_MMU_ALL, %o2 /* ARG2: flags */ srlx %o0, PAGE_SHIFT, %o0 @@ -613,8 +679,6 @@ __hypervisor_xcall_flush_tlb_pending: /* 21 insns */ mov HV_MMU_UNMAP_ADDR_TRAP, %g6 brnz,a,pn %o0, __hypervisor_tlb_xcall_error mov %o0, %g5 - brnz,pt %g1, 1b - nop mov %g2, %o0 mov %g3, %o1 mov %g4, %o2 @@ -697,6 +761,13 @@ hypervisor_patch_cachetlbops: call tlb_patch_one mov 10, %o2 + sethi %hi(__flush_tlb_page), %o0 + or %o0, %lo(__flush_tlb_page), %o0 + sethi %hi(__hypervisor_flush_tlb_page), %o1 + or %o1, %lo(__hypervisor_flush_tlb_page), %o1 + call tlb_patch_one + mov 11, %o2 + sethi %hi(__flush_tlb_pending), %o0 or %o0, %lo(__flush_tlb_pending), %o0 sethi %hi(__hypervisor_flush_tlb_pending), %o1 @@ -728,12 +799,12 @@ hypervisor_patch_cachetlbops: call tlb_patch_one mov 21, %o2 - sethi %hi(xcall_flush_tlb_pending), %o0 - or %o0, %lo(xcall_flush_tlb_pending), %o0 - sethi %hi(__hypervisor_xcall_flush_tlb_pending), %o1 - or %o1, %lo(__hypervisor_xcall_flush_tlb_pending), %o1 + sethi %hi(xcall_flush_tlb_page), %o0 + or %o0, %lo(xcall_flush_tlb_page), %o0 + sethi %hi(__hypervisor_xcall_flush_tlb_page), %o1 + or %o1, %lo(__hypervisor_xcall_flush_tlb_page), %o1 call tlb_patch_one - mov 21, %o2 + mov 17, %o2 sethi %hi(xcall_flush_tlb_kernel_range), %o0 or %o0, %lo(xcall_flush_tlb_kernel_range), %o0 diff --git a/arch/sparc/mm/viking.S b/arch/sparc/mm/viking.S index 6dfcc13d310..a516372417a 100644 --- a/arch/sparc/mm/viking.S +++ b/arch/sparc/mm/viking.S @@ -109,7 +109,7 @@ viking_mxcc_flush_page: viking_flush_cache_page: viking_flush_cache_range: #ifndef CONFIG_SMP - ld [%o0 + 0x0], %o0 /* XXX vma->vm_mm, GROSS XXX */ + ld [%o0 + VMA_VM_MM], %o0 #endif viking_flush_cache_mm: #ifndef CONFIG_SMP @@ -149,7 +149,7 @@ viking_flush_tlb_mm: #endif viking_flush_tlb_range: - ld [%o0 + 0x00], %o0 /* XXX vma->vm_mm GROSS XXX */ + ld [%o0 + VMA_VM_MM], %o0 mov SRMMU_CTX_REG, %g1 ld [%o0 + AOFF_mm_context], %o3 lda [%g1] ASI_M_MMUREGS, %g5 @@ -174,7 +174,7 @@ viking_flush_tlb_range: #endif viking_flush_tlb_page: - ld [%o0 + 0x00], %o0 /* XXX vma->vm_mm GROSS XXX */ + ld [%o0 + VMA_VM_MM], %o0 mov SRMMU_CTX_REG, %g1 ld [%o0 + AOFF_mm_context], %o3 lda [%g1] ASI_M_MMUREGS, %g5 @@ -240,7 +240,7 @@ sun4dsmp_flush_tlb_range: tst %g5 bne 3f mov SRMMU_CTX_REG, %g1 - ld [%o0 + 0x00], %o0 /* XXX vma->vm_mm GROSS XXX */ + ld [%o0 + VMA_VM_MM], %o0 ld [%o0 + AOFF_mm_context], %o3 lda [%g1] ASI_M_MMUREGS, %g5 sethi %hi(~((1 << SRMMU_PGDIR_SHIFT) - 1)), %o4 @@ -266,7 +266,7 @@ sun4dsmp_flush_tlb_page: tst %g5 bne 2f mov SRMMU_CTX_REG, %g1 - ld [%o0 + 0x00], %o0 /* XXX vma->vm_mm GROSS XXX */ + ld [%o0 + VMA_VM_MM], %o0 ld [%o0 + AOFF_mm_context], %o3 lda [%g1] ASI_M_MMUREGS, %g5 and %o1, PAGE_MASK, %o1 diff --git a/arch/tile/kernel/setup.c b/arch/tile/kernel/setup.c index 7bd2060b1e1..fcda0f8e622 100644 --- a/arch/tile/kernel/setup.c +++ b/arch/tile/kernel/setup.c @@ -912,15 +912,8 @@ void setup_cpu(int boot) #ifdef CONFIG_BLK_DEV_INITRD -/* - * Note that the kernel can potentially support other compression - * techniques than gz, though we don't do so by default. If we ever - * decide to do so we can either look for other filename extensions, - * or just allow a file with this name to be compressed with an - * arbitrary compressor (somewhat counterintuitively). - */ static int __initdata set_initramfs_file; -static char __initdata initramfs_file[128] = "initramfs.cpio.gz"; +static char __initdata initramfs_file[128] = "initramfs"; static int __init setup_initramfs_file(char *str) { @@ -934,9 +927,9 @@ static int __init setup_initramfs_file(char *str) early_param("initramfs_file", setup_initramfs_file); /* - * We look for an "initramfs.cpio.gz" file in the hvfs. - * If there is one, we allocate some memory for it and it will be - * unpacked to the initramfs. + * We look for a file called "initramfs" in the hvfs. If there is one, we + * allocate some memory for it and it will be unpacked to the initramfs. + * If it's compressed, the initd code will uncompress it first. */ static void __init load_hv_initrd(void) { @@ -946,10 +939,16 @@ static void __init load_hv_initrd(void) fd = hv_fs_findfile((HV_VirtAddr) initramfs_file); if (fd == HV_ENOENT) { - if (set_initramfs_file) + if (set_initramfs_file) { pr_warning("No such hvfs initramfs file '%s'\n", initramfs_file); - return; + return; + } else { + /* Try old backwards-compatible name. */ + fd = hv_fs_findfile((HV_VirtAddr)"initramfs.cpio.gz"); + if (fd == HV_ENOENT) + return; + } } BUG_ON(fd < 0); stat = hv_fs_fstat(fd); diff --git a/arch/tile/lib/exports.c b/arch/tile/lib/exports.c index 2a81d32de0d..e51e5cd41f5 100644 --- a/arch/tile/lib/exports.c +++ b/arch/tile/lib/exports.c @@ -90,4 +90,6 @@ uint64_t __ashrdi3(uint64_t, unsigned int); EXPORT_SYMBOL(__ashrdi3); uint64_t __ashldi3(uint64_t, unsigned int); EXPORT_SYMBOL(__ashldi3); +int __ffsdi2(uint64_t); +EXPORT_SYMBOL(__ffsdi2); #endif diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 7cbdfdac3c7..29cf70ff6b4 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -1244,10 +1244,6 @@ config HAVE_ARCH_BOOTMEM def_bool y depends on X86_32 && NUMA -config HAVE_ARCH_ALLOC_REMAP - def_bool y - depends on X86_32 && NUMA - config ARCH_HAVE_MEMORY_PRESENT def_bool y depends on X86_32 && DISCONTIGMEM diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile index 8a84501acb1..5ef205c5f37 100644 --- a/arch/x86/boot/compressed/Makefile +++ b/arch/x86/boot/compressed/Makefile @@ -4,7 +4,7 @@ # create a compressed vmlinux image from the original vmlinux # -targets := vmlinux.lds vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma vmlinux.bin.xz vmlinux.bin.lzo head_$(BITS).o misc.o string.o cmdline.o early_serial_console.o piggy.o +targets := vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma vmlinux.bin.xz vmlinux.bin.lzo KBUILD_CFLAGS := -m$(BITS) -D__KERNEL__ $(LINUX_INCLUDE) -O2 KBUILD_CFLAGS += -fno-strict-aliasing -fPIC @@ -29,7 +29,6 @@ VMLINUX_OBJS = $(obj)/vmlinux.lds $(obj)/head_$(BITS).o $(obj)/misc.o \ $(obj)/piggy.o $(obj)/eboot.o: KBUILD_CFLAGS += -fshort-wchar -mno-red-zone -$(obj)/efi_stub_$(BITS).o: KBUILD_CLFAGS += -fshort-wchar -mno-red-zone ifeq ($(CONFIG_EFI_STUB), y) VMLINUX_OBJS += $(obj)/eboot.o $(obj)/efi_stub_$(BITS).o @@ -43,7 +42,7 @@ OBJCOPYFLAGS_vmlinux.bin := -R .comment -S $(obj)/vmlinux.bin: vmlinux FORCE $(call if_changed,objcopy) -targets += vmlinux.bin.all vmlinux.relocs +targets += $(patsubst $(obj)/%,%,$(VMLINUX_OBJS)) vmlinux.bin.all vmlinux.relocs CMD_RELOCS = arch/x86/tools/relocs quiet_cmd_relocs = RELOCS $@ diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h index 029189db84d..da37433e362 100644 --- a/arch/x86/include/asm/efi.h +++ b/arch/x86/include/asm/efi.h @@ -94,6 +94,7 @@ extern void __iomem *efi_ioremap(unsigned long addr, unsigned long size, #endif /* CONFIG_X86_32 */ extern int add_efi_memmap; +extern unsigned long x86_efi_facility; extern void efi_set_executable(efi_memory_desc_t *md, bool executable); extern int efi_memblock_x86_reserve_range(void); extern void efi_call_phys_prelog(void); diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index e216ba066e7..d57eacb9fcf 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -407,8 +407,8 @@ struct kvm_vcpu_arch { gpa_t time; struct pvclock_vcpu_time_info hv_clock; unsigned int hw_tsc_khz; - unsigned int time_offset; - struct page *time_page; + struct gfn_to_hva_cache pv_time; + bool pv_time_enabled; struct { u64 msr_val; diff --git a/arch/x86/include/asm/mmzone_32.h b/arch/x86/include/asm/mmzone_32.h index 55728e12147..5e0286f8081 100644 --- a/arch/x86/include/asm/mmzone_32.h +++ b/arch/x86/include/asm/mmzone_32.h @@ -14,12 +14,6 @@ extern struct pglist_data *node_data[]; #include -extern void resume_map_numa_kva(pgd_t *pgd); - -#else /* !CONFIG_NUMA */ - -static inline void resume_map_numa_kva(pgd_t *pgd) {} - #endif /* CONFIG_NUMA */ #ifdef CONFIG_DISCONTIGMEM diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h index aa0f9130836..25e97347f61 100644 --- a/arch/x86/include/asm/paravirt.h +++ b/arch/x86/include/asm/paravirt.h @@ -741,7 +741,10 @@ static inline void arch_leave_lazy_mmu_mode(void) PVOP_VCALL0(pv_mmu_ops.lazy_mode.leave); } -void arch_flush_lazy_mmu_mode(void); +static inline void arch_flush_lazy_mmu_mode(void) +{ + PVOP_VCALL0(pv_mmu_ops.lazy_mode.flush); +} static inline void __set_fixmap(unsigned /* enum fixed_addresses */ idx, phys_addr_t phys, pgprot_t flags) diff --git a/arch/x86/include/asm/paravirt_types.h b/arch/x86/include/asm/paravirt_types.h index 8e8b9a4987e..faf2c04cdac 100644 --- a/arch/x86/include/asm/paravirt_types.h +++ b/arch/x86/include/asm/paravirt_types.h @@ -91,6 +91,7 @@ struct pv_lazy_ops { /* Set deferred update mode, used for batching operations. */ void (*enter)(void); void (*leave)(void); + void (*flush)(void); }; struct pv_time_ops { @@ -680,6 +681,7 @@ void paravirt_end_context_switch(struct task_struct *next); void paravirt_enter_lazy_mmu(void); void paravirt_leave_lazy_mmu(void); +void paravirt_flush_lazy_mmu(void); void _paravirt_nop(void); u32 _paravirt_ident_32(u32); diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index c3520d76820..3f3dd526b3b 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -142,6 +142,11 @@ static inline unsigned long pmd_pfn(pmd_t pmd) return (pmd_val(pmd) & PTE_PFN_MASK) >> PAGE_SHIFT; } +static inline unsigned long pud_pfn(pud_t pud) +{ + return (pud_val(pud) & PTE_PFN_MASK) >> PAGE_SHIFT; +} + #define pte_page(pte) pfn_to_page(pte_pfn(pte)) static inline int pmd_large(pmd_t pte) diff --git a/arch/x86/include/asm/signal.h b/arch/x86/include/asm/signal.h index 598457cbd0f..6cbc795b7c5 100644 --- a/arch/x86/include/asm/signal.h +++ b/arch/x86/include/asm/signal.h @@ -125,6 +125,8 @@ typedef unsigned long sigset_t; extern void do_notify_resume(struct pt_regs *, void *, __u32); # endif /* __KERNEL__ */ +#define __ARCH_HAS_SA_RESTORER + #ifdef __i386__ # ifdef __KERNEL__ struct old_sigaction { diff --git a/arch/x86/include/asm/syscall.h b/arch/x86/include/asm/syscall.h index 386b78686c4..1d82a11959a 100644 --- a/arch/x86/include/asm/syscall.h +++ b/arch/x86/include/asm/syscall.h @@ -27,13 +27,13 @@ extern const unsigned long sys_call_table[]; */ static inline int syscall_get_nr(struct task_struct *task, struct pt_regs *regs) { - return regs->orig_ax & __SYSCALL_MASK; + return regs->orig_ax; } static inline void syscall_rollback(struct task_struct *task, struct pt_regs *regs) { - regs->ax = regs->orig_ax & __SYSCALL_MASK; + regs->ax = regs->orig_ax; } static inline long syscall_get_error(struct task_struct *task, diff --git a/arch/x86/kernel/apic/x2apic_phys.c b/arch/x86/kernel/apic/x2apic_phys.c index 991e315f422..db31a2cfc9a 100644 --- a/arch/x86/kernel/apic/x2apic_phys.c +++ b/arch/x86/kernel/apic/x2apic_phys.c @@ -20,18 +20,19 @@ static int set_x2apic_phys_mode(char *arg) } early_param("x2apic_phys", set_x2apic_phys_mode); -static int x2apic_acpi_madt_oem_check(char *oem_id, char *oem_table_id) +static bool x2apic_fadt_phys(void) { - if (x2apic_phys) - return x2apic_enabled(); - else if ((acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID) && - (acpi_gbl_FADT.flags & ACPI_FADT_APIC_PHYSICAL) && - x2apic_enabled()) { + if ((acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID) && + (acpi_gbl_FADT.flags & ACPI_FADT_APIC_PHYSICAL)) { printk(KERN_DEBUG "System requires x2apic physical mode\n"); - return 1; + return true; } - else - return 0; + return false; +} + +static int x2apic_acpi_madt_oem_check(char *oem_id, char *oem_table_id) +{ + return x2apic_enabled() && (x2apic_phys || x2apic_fadt_phys()); } static void @@ -114,7 +115,7 @@ static void init_x2apic_ldr(void) static int x2apic_phys_probe(void) { - if (x2apic_mode && x2apic_phys) + if (x2apic_mode && (x2apic_phys || x2apic_fadt_phys())) return 1; return apic == &apic_x2apic_phys; diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c index 0a630dd4b62..646d192b18a 100644 --- a/arch/x86/kernel/cpu/mshyperv.c +++ b/arch/x86/kernel/cpu/mshyperv.c @@ -68,7 +68,8 @@ static void __init ms_hyperv_init_platform(void) printk(KERN_INFO "HyperV: features 0x%x, hints 0x%x\n", ms_hyperv.features, ms_hyperv.hints); - clocksource_register_hz(&hyperv_cs, NSEC_PER_SEC/100); + if (ms_hyperv.features & HV_X64_MSR_TIME_REF_COUNT_AVAILABLE) + clocksource_register_hz(&hyperv_cs, NSEC_PER_SEC/100); } const __refconst struct hypervisor_x86 x86_hyper_ms_hyperv = { diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c index 26b3e2fef10..268b2455e7b 100644 --- a/arch/x86/kernel/cpu/perf_event_intel.c +++ b/arch/x86/kernel/cpu/perf_event_intel.c @@ -126,8 +126,14 @@ static struct event_constraint intel_gen_event_constraints[] __read_mostly = }; static struct extra_reg intel_snb_extra_regs[] __read_mostly = { - INTEL_EVENT_EXTRA_REG(0xb7, MSR_OFFCORE_RSP_0, 0x3fffffffffull, RSP_0), - INTEL_EVENT_EXTRA_REG(0xbb, MSR_OFFCORE_RSP_1, 0x3fffffffffull, RSP_1), + INTEL_EVENT_EXTRA_REG(0xb7, MSR_OFFCORE_RSP_0, 0x3f807f8fffull, RSP_0), + INTEL_EVENT_EXTRA_REG(0xbb, MSR_OFFCORE_RSP_1, 0x3f807f8fffull, RSP_1), + EVENT_EXTRA_END +}; + +static struct extra_reg intel_snbep_extra_regs[] __read_mostly = { + INTEL_EVENT_EXTRA_REG(0xb7, MSR_OFFCORE_RSP_0, 0x3fffff8fffull, RSP_0), + INTEL_EVENT_EXTRA_REG(0xbb, MSR_OFFCORE_RSP_1, 0x3fffff8fffull, RSP_1), EVENT_EXTRA_END }; @@ -1851,7 +1857,10 @@ __init int intel_pmu_init(void) x86_pmu.event_constraints = intel_snb_event_constraints; x86_pmu.pebs_constraints = intel_snb_pebs_event_constraints; - x86_pmu.extra_regs = intel_snb_extra_regs; + if (boot_cpu_data.x86_model == 45) + x86_pmu.extra_regs = intel_snbep_extra_regs; + else + x86_pmu.extra_regs = intel_snb_extra_regs; /* all extra regs are per-cpu when HT is on */ x86_pmu.er_flags |= ERF_HAS_RSP_1; x86_pmu.er_flags |= ERF_NO_HT_SHARING; diff --git a/arch/x86/kernel/cpu/perf_event_intel_ds.c b/arch/x86/kernel/cpu/perf_event_intel_ds.c index 7f64df19e7d..fca48c4ce94 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_ds.c +++ b/arch/x86/kernel/cpu/perf_event_intel_ds.c @@ -723,3 +723,13 @@ void intel_ds_init(void) } } } + +void perf_restore_debug_store(void) +{ + struct debug_store *ds = __this_cpu_read(cpu_hw_events.ds); + + if (!x86_pmu.bts && !x86_pmu.pebs) + return; + + wrmsrl(MSR_IA32_DS_AREA, (unsigned long)ds); +} diff --git a/arch/x86/kernel/cpu/perf_event_intel_lbr.c b/arch/x86/kernel/cpu/perf_event_intel_lbr.c index 520b4265fcd..fd1a0999043 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_lbr.c +++ b/arch/x86/kernel/cpu/perf_event_intel_lbr.c @@ -310,7 +310,7 @@ void intel_pmu_lbr_read(void) * - in case there is no HW filter * - in case the HW filter has errata or limitations */ -static void intel_pmu_setup_sw_lbr_filter(struct perf_event *event) +static int intel_pmu_setup_sw_lbr_filter(struct perf_event *event) { u64 br_type = event->attr.branch_sample_type; int mask = 0; @@ -318,8 +318,11 @@ static void intel_pmu_setup_sw_lbr_filter(struct perf_event *event) if (br_type & PERF_SAMPLE_BRANCH_USER) mask |= X86_BR_USER; - if (br_type & PERF_SAMPLE_BRANCH_KERNEL) + if (br_type & PERF_SAMPLE_BRANCH_KERNEL) { + if (perf_paranoid_kernel() && !capable(CAP_SYS_ADMIN)) + return -EACCES; mask |= X86_BR_KERNEL; + } /* we ignore BRANCH_HV here */ @@ -339,6 +342,8 @@ static void intel_pmu_setup_sw_lbr_filter(struct perf_event *event) * be used by fixup code for some CPU */ event->hw.branch_reg.reg = mask; + + return 0; } /* @@ -386,7 +391,9 @@ int intel_pmu_setup_lbr_filter(struct perf_event *event) /* * setup SW LBR filter */ - intel_pmu_setup_sw_lbr_filter(event); + ret = intel_pmu_setup_sw_lbr_filter(event); + if (ret) + return ret; /* * setup HW LBR filter, if any @@ -442,8 +449,18 @@ static int branch_type(unsigned long from, unsigned long to) return X86_BR_NONE; addr = buf; - } else - addr = (void *)from; + } else { + /* + * The LBR logs any address in the IP, even if the IP just + * faulted. This means userspace can control the from address. + * Ensure we don't blindy read any address by validating it is + * a known text address. + */ + if (kernel_text_address(from)) + addr = (void *)from; + else + return X86_BR_NONE; + } /* * decoder needs to know the ABI especially diff --git a/arch/x86/kernel/head.c b/arch/x86/kernel/head.c index 48d9d4ea102..992f442ca15 100644 --- a/arch/x86/kernel/head.c +++ b/arch/x86/kernel/head.c @@ -5,8 +5,6 @@ #include #include -#define BIOS_LOWMEM_KILOBYTES 0x413 - /* * The BIOS places the EBDA/XBDA at the top of conventional * memory, and usually decreases the reported amount of @@ -16,17 +14,30 @@ * chipset: reserve a page before VGA to prevent PCI prefetch * into it (errata #56). Usually the page is reserved anyways, * unless you have no PS/2 mouse plugged in. + * + * This functions is deliberately very conservative. Losing + * memory in the bottom megabyte is rarely a problem, as long + * as we have enough memory to install the trampoline. Using + * memory that is in use by the BIOS or by some DMA device + * the BIOS didn't shut down *is* a big problem. */ + +#define BIOS_LOWMEM_KILOBYTES 0x413 +#define LOWMEM_CAP 0x9f000U /* Absolute maximum */ +#define INSANE_CUTOFF 0x20000U /* Less than this = insane */ + void __init reserve_ebda_region(void) { unsigned int lowmem, ebda_addr; - /* To determine the position of the EBDA and the */ - /* end of conventional memory, we need to look at */ - /* the BIOS data area. In a paravirtual environment */ - /* that area is absent. We'll just have to assume */ - /* that the paravirt case can handle memory setup */ - /* correctly, without our help. */ + /* + * To determine the position of the EBDA and the + * end of conventional memory, we need to look at + * the BIOS data area. In a paravirtual environment + * that area is absent. We'll just have to assume + * that the paravirt case can handle memory setup + * correctly, without our help. + */ if (paravirt_enabled()) return; @@ -37,19 +48,23 @@ void __init reserve_ebda_region(void) /* start of EBDA area */ ebda_addr = get_bios_ebda(); - /* Fixup: bios puts an EBDA in the top 64K segment */ - /* of conventional memory, but does not adjust lowmem. */ - if ((lowmem - ebda_addr) <= 0x10000) - lowmem = ebda_addr; + /* + * Note: some old Dells seem to need 4k EBDA without + * reporting so, so just consider the memory above 0x9f000 + * to be off limits (bugzilla 2990). + */ + + /* If the EBDA address is below 128K, assume it is bogus */ + if (ebda_addr < INSANE_CUTOFF) + ebda_addr = LOWMEM_CAP; - /* Fixup: bios does not report an EBDA at all. */ - /* Some old Dells seem to need 4k anyhow (bugzilla 2990) */ - if ((ebda_addr == 0) && (lowmem >= 0x9f000)) - lowmem = 0x9f000; + /* If lowmem is less than 128K, assume it is bogus */ + if (lowmem < INSANE_CUTOFF) + lowmem = LOWMEM_CAP; - /* Paranoia: should never happen, but... */ - if ((lowmem == 0) || (lowmem >= 0x100000)) - lowmem = 0x9f000; + /* Use the lower of the lowmem and EBDA markers as the cutoff */ + lowmem = min(lowmem, ebda_addr); + lowmem = min(lowmem, LOWMEM_CAP); /* Absolute cap */ /* reserve all memory between lowmem and the 1MB mark */ memblock_reserve(lowmem, 0x100000 - lowmem); diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c index 95bc326863e..02b408e6c72 100644 --- a/arch/x86/kernel/i387.c +++ b/arch/x86/kernel/i387.c @@ -132,7 +132,7 @@ static void mxcsr_feature_mask_init(void) clts(); if (cpu_has_fxsr) { memset(&fx_scratch, 0, sizeof(struct i387_fxsave_struct)); - asm volatile("fxsave %0" : : "m" (fx_scratch)); + asm volatile("fxsave %0" : "+m" (fx_scratch)); mask = fx_scratch.mxcsr_mask; if (mask == 0) mask = 0x0000ffbf; diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c index 3dafc6003b7..a14a835c0ed 100644 --- a/arch/x86/kernel/irq.c +++ b/arch/x86/kernel/irq.c @@ -165,10 +165,6 @@ u64 arch_irq_stat_cpu(unsigned int cpu) u64 arch_irq_stat(void) { u64 sum = atomic_read(&irq_err_count); - -#ifdef CONFIG_X86_IO_APIC - sum += atomic_read(&irq_mis_count); -#endif return sum; } diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c index ab137605e69..128323e1fb9 100644 --- a/arch/x86/kernel/paravirt.c +++ b/arch/x86/kernel/paravirt.c @@ -263,6 +263,18 @@ void paravirt_leave_lazy_mmu(void) leave_lazy(PARAVIRT_LAZY_MMU); } +void paravirt_flush_lazy_mmu(void) +{ + preempt_disable(); + + if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_MMU) { + arch_leave_lazy_mmu_mode(); + arch_enter_lazy_mmu_mode(); + } + + preempt_enable(); +} + void paravirt_start_context_switch(struct task_struct *prev) { BUG_ON(preemptible()); @@ -292,18 +304,6 @@ enum paravirt_lazy_mode paravirt_get_lazy_mode(void) return percpu_read(paravirt_lazy_mode); } -void arch_flush_lazy_mmu_mode(void) -{ - preempt_disable(); - - if (paravirt_get_lazy_mode() == PARAVIRT_LAZY_MMU) { - arch_leave_lazy_mmu_mode(); - arch_enter_lazy_mmu_mode(); - } - - preempt_enable(); -} - struct pv_info pv_info = { .name = "bare hardware", .paravirt_enabled = 0, @@ -477,6 +477,7 @@ struct pv_mmu_ops pv_mmu_ops = { .lazy_mode = { .enter = paravirt_nop, .leave = paravirt_nop, + .flush = paravirt_nop, }, .set_fixmap = native_set_fixmap, diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index 3034ee5afb0..df1b604c0c1 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c @@ -619,7 +619,7 @@ static void native_machine_emergency_restart(void) break; case BOOT_EFI: - if (efi_enabled) + if (efi_enabled(EFI_RUNTIME_SERVICES)) efi.reset_system(reboot_mode ? EFI_RESET_WARM : EFI_RESET_COLD, diff --git a/arch/x86/kernel/relocate_kernel_64.S b/arch/x86/kernel/relocate_kernel_64.S index 7a6f3b3be3c..f2bb9c96720 100644 --- a/arch/x86/kernel/relocate_kernel_64.S +++ b/arch/x86/kernel/relocate_kernel_64.S @@ -160,7 +160,7 @@ identity_mapped: xorq %rbp, %rbp xorq %r8, %r8 xorq %r9, %r9 - xorq %r10, %r9 + xorq %r10, %r10 xorq %r11, %r11 xorq %r12, %r12 xorq %r13, %r13 diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 2d68753e39d..839fa1e9871 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -819,15 +819,15 @@ void __init setup_arch(char **cmdline_p) #ifdef CONFIG_EFI if (!strncmp((char *)&boot_params.efi_info.efi_loader_signature, "EL32", 4)) { - efi_enabled = 1; - efi_64bit = false; + set_bit(EFI_BOOT, &x86_efi_facility); } else if (!strncmp((char *)&boot_params.efi_info.efi_loader_signature, "EL64", 4)) { - efi_enabled = 1; - efi_64bit = true; + set_bit(EFI_BOOT, &x86_efi_facility); + set_bit(EFI_64BIT, &x86_efi_facility); } - if (efi_enabled && efi_memblock_x86_reserve_range()) - efi_enabled = 0; + + if (efi_enabled(EFI_BOOT)) + efi_memblock_x86_reserve_range(); #endif x86_init.oem.arch_setup(); @@ -900,7 +900,7 @@ void __init setup_arch(char **cmdline_p) finish_e820_parsing(); - if (efi_enabled) + if (efi_enabled(EFI_BOOT)) efi_init(); dmi_scan_machine(); @@ -983,7 +983,7 @@ void __init setup_arch(char **cmdline_p) * The EFI specification says that boot service code won't be called * after ExitBootServices(). This is, in fact, a lie. */ - if (efi_enabled) + if (efi_enabled(EFI_MEMMAP)) efi_reserve_boot_services(); /* preallocate 4k for mptable mpc */ @@ -1121,7 +1121,7 @@ void __init setup_arch(char **cmdline_p) #ifdef CONFIG_VT #if defined(CONFIG_VGA_CONSOLE) - if (!efi_enabled || (efi_mem_type(0xa0000) != EFI_CONVENTIONAL_MEMORY)) + if (!efi_enabled(EFI_BOOT) || (efi_mem_type(0xa0000) != EFI_CONVENTIONAL_MEMORY)) conswitchp = &vga_con; #elif defined(CONFIG_DUMMY_CONSOLE) conswitchp = &dummy_con; @@ -1138,14 +1138,14 @@ void __init setup_arch(char **cmdline_p) arch_init_ideal_nops(); #ifdef CONFIG_EFI - /* Once setup is done above, disable efi_enabled on mismatched - * firmware/kernel archtectures since there is no support for - * runtime services. + /* Once setup is done above, unmap the EFI memory map on + * mismatched firmware/kernel archtectures since there is no + * support for runtime services. */ - if (efi_enabled && IS_ENABLED(CONFIG_X86_64) != efi_64bit) { + if (efi_enabled(EFI_BOOT) && + IS_ENABLED(CONFIG_X86_64) != efi_enabled(EFI_64BIT)) { pr_info("efi: Setup done, disabling due to 32/64-bit mismatch\n"); efi_unmap_memmap(); - efi_enabled = 0; } #endif } diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 83756223f8a..8c45818c732 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -3737,6 +3737,10 @@ static int decode_operand(struct x86_emulate_ctxt *ctxt, struct operand *op, break; case OpMem8: ctxt->memop.bytes = 1; + if (ctxt->memop.type == OP_REG) { + ctxt->memop.addr.reg = decode_register(ctxt, ctxt->modrm_rm, 1); + fetch_register_operand(&ctxt->memop); + } goto mem_common; case OpMem16: ctxt->memop.bytes = 2; diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 4ff0ab9bc3c..90f5c0ed9d2 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -4889,6 +4889,12 @@ static int handle_invalid_guest_state(struct kvm_vcpu *vcpu) if (err != EMULATE_DONE) return 0; + if (vcpu->arch.halt_request) { + vcpu->arch.halt_request = 0; + ret = kvm_emulate_halt(vcpu); + goto out; + } + if (signal_pending(current)) goto out; if (need_resched()) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index e28fb97a1a8..3663e0b3897 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -555,8 +555,6 @@ int __kvm_set_xcr(struct kvm_vcpu *vcpu, u32 index, u64 xcr) if (index != XCR_XFEATURE_ENABLED_MASK) return 1; xcr0 = xcr; - if (kvm_x86_ops->get_cpl(vcpu) != 0) - return 1; if (!(xcr0 & XSTATE_FP)) return 1; if ((xcr0 & XSTATE_YMM) && !(xcr0 & XSTATE_SSE)) @@ -570,7 +568,8 @@ int __kvm_set_xcr(struct kvm_vcpu *vcpu, u32 index, u64 xcr) int kvm_set_xcr(struct kvm_vcpu *vcpu, u32 index, u64 xcr) { - if (__kvm_set_xcr(vcpu, index, xcr)) { + if (kvm_x86_ops->get_cpl(vcpu) != 0 || + __kvm_set_xcr(vcpu, index, xcr)) { kvm_inject_gp(vcpu, 0); return 1; } @@ -1114,7 +1113,6 @@ static int kvm_guest_time_update(struct kvm_vcpu *v) { unsigned long flags; struct kvm_vcpu_arch *vcpu = &v->arch; - void *shared_kaddr; unsigned long this_tsc_khz; s64 kernel_ns, max_kernel_ns; u64 tsc_timestamp; @@ -1150,7 +1148,7 @@ static int kvm_guest_time_update(struct kvm_vcpu *v) local_irq_restore(flags); - if (!vcpu->time_page) + if (!vcpu->pv_time_enabled) return 0; /* @@ -1208,14 +1206,9 @@ static int kvm_guest_time_update(struct kvm_vcpu *v) */ vcpu->hv_clock.version += 2; - shared_kaddr = kmap_atomic(vcpu->time_page); - - memcpy(shared_kaddr + vcpu->time_offset, &vcpu->hv_clock, - sizeof(vcpu->hv_clock)); - - kunmap_atomic(shared_kaddr); - - mark_page_dirty(v->kvm, vcpu->time >> PAGE_SHIFT); + kvm_write_guest_cached(v->kvm, &vcpu->pv_time, + &vcpu->hv_clock, + sizeof(vcpu->hv_clock)); return 0; } @@ -1494,7 +1487,8 @@ static int kvm_pv_enable_async_pf(struct kvm_vcpu *vcpu, u64 data) return 0; } - if (kvm_gfn_to_hva_cache_init(vcpu->kvm, &vcpu->arch.apf.data, gpa)) + if (kvm_gfn_to_hva_cache_init(vcpu->kvm, &vcpu->arch.apf.data, gpa, + sizeof(u32))) return 1; vcpu->arch.apf.send_user_only = !(data & KVM_ASYNC_PF_SEND_ALWAYS); @@ -1504,10 +1498,7 @@ static int kvm_pv_enable_async_pf(struct kvm_vcpu *vcpu, u64 data) static void kvmclock_reset(struct kvm_vcpu *vcpu) { - if (vcpu->arch.time_page) { - kvm_release_page_dirty(vcpu->arch.time_page); - vcpu->arch.time_page = NULL; - } + vcpu->arch.pv_time_enabled = false; } static void accumulate_steal_time(struct kvm_vcpu *vcpu) @@ -1602,6 +1593,7 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data) break; case MSR_KVM_SYSTEM_TIME_NEW: case MSR_KVM_SYSTEM_TIME: { + u64 gpa_offset; kvmclock_reset(vcpu); vcpu->arch.time = data; @@ -1611,16 +1603,14 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data) if (!(data & 1)) break; - /* ...but clean it before doing the actual write */ - vcpu->arch.time_offset = data & ~(PAGE_MASK | 1); - - vcpu->arch.time_page = - gfn_to_page(vcpu->kvm, data >> PAGE_SHIFT); + gpa_offset = data & ~(PAGE_MASK | 1); - if (is_error_page(vcpu->arch.time_page)) { - kvm_release_page_clean(vcpu->arch.time_page); - vcpu->arch.time_page = NULL; - } + if (kvm_gfn_to_hva_cache_init(vcpu->kvm, + &vcpu->arch.pv_time, data & ~1ULL, + sizeof(struct pvclock_vcpu_time_info))) + vcpu->arch.pv_time_enabled = false; + else + vcpu->arch.pv_time_enabled = true; break; } case MSR_KVM_ASYNC_PF_EN: @@ -1636,7 +1626,8 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data) return 1; if (kvm_gfn_to_hva_cache_init(vcpu->kvm, &vcpu->arch.st.stime, - data & KVM_STEAL_VALID_BITS)) + data & KVM_STEAL_VALID_BITS, + sizeof(struct kvm_steal_time))) return 1; vcpu->arch.st.msr_val = data; @@ -6167,6 +6158,7 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu) if (!zalloc_cpumask_var(&vcpu->arch.wbinvd_dirty_mask, GFP_KERNEL)) goto fail_free_mce_banks; + vcpu->arch.pv_time_enabled = false; kvm_async_pf_hash_reset(vcpu); kvm_pmu_init(vcpu); diff --git a/arch/x86/lguest/boot.c b/arch/x86/lguest/boot.c index 642d8805bc1..53272bd9675 100644 --- a/arch/x86/lguest/boot.c +++ b/arch/x86/lguest/boot.c @@ -1333,6 +1333,7 @@ __init void lguest_init(void) pv_mmu_ops.read_cr3 = lguest_read_cr3; pv_mmu_ops.lazy_mode.enter = paravirt_enter_lazy_mmu; pv_mmu_ops.lazy_mode.leave = lguest_leave_lazy_mmu_mode; + pv_mmu_ops.lazy_mode.flush = paravirt_flush_lazy_mmu; pv_mmu_ops.pte_update = lguest_pte_update; pv_mmu_ops.pte_update_defer = lguest_pte_update; diff --git a/arch/x86/lib/usercopy_64.c b/arch/x86/lib/usercopy_64.c index 0d0326f388c..d70b9a510ec 100644 --- a/arch/x86/lib/usercopy_64.c +++ b/arch/x86/lib/usercopy_64.c @@ -120,10 +120,10 @@ copy_user_handle_tail(char *to, char *from, unsigned len, unsigned zerorest) char c; unsigned zero_len; - for (; len; --len) { + for (; len; --len, to++) { if (__get_user_nocheck(c, from++, sizeof(char))) break; - if (__put_user_nocheck(c, to++, sizeof(char))) + if (__put_user_nocheck(c, to, sizeof(char))) break; } diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index 3ecfd1aaf21..4a0a2e810b4 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c @@ -377,10 +377,12 @@ static noinline __kprobes int vmalloc_fault(unsigned long address) if (pgd_none(*pgd_ref)) return -1; - if (pgd_none(*pgd)) + if (pgd_none(*pgd)) { set_pgd(pgd, *pgd_ref); - else + arch_flush_lazy_mmu_mode(); + } else { BUG_ON(pgd_page_vaddr(*pgd) != pgd_page_vaddr(*pgd_ref)); + } /* * Below here mismatches are bugs because these lower tables @@ -747,13 +749,15 @@ __bad_area_nosemaphore(struct pt_regs *regs, unsigned long error_code, return; } #endif + /* Kernel addresses are always protection faults: */ + if (address >= TASK_SIZE) + error_code |= PF_PROT; - if (unlikely(show_unhandled_signals)) + if (likely(show_unhandled_signals)) show_signal_msg(regs, error_code, address, tsk); - /* Kernel addresses are always protection faults: */ tsk->thread.cr2 = address; - tsk->thread.error_code = error_code | (address >= TASK_SIZE); + tsk->thread.error_code = error_code; tsk->thread.trap_nr = X86_TRAP_PF; force_sig_info_fault(SIGSEGV, si_code, address, tsk, 0); diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c index fae70904ed0..71d37f527c6 100644 --- a/arch/x86/mm/init.c +++ b/arch/x86/mm/init.c @@ -45,11 +45,15 @@ static void __init find_early_table_space(struct map_range *mr, int nr_range) int i; unsigned long puds = 0, pmds = 0, ptes = 0, tables; unsigned long start = 0, good_end; + unsigned long pgd_extra = 0; phys_addr_t base; for (i = 0; i < nr_range; i++) { unsigned long range, extra; + if ((mr[i].end >> PGDIR_SHIFT) - (mr[i].start >> PGDIR_SHIFT)) + pgd_extra++; + range = mr[i].end - mr[i].start; puds += (range + PUD_SIZE - 1) >> PUD_SHIFT; @@ -74,6 +78,7 @@ static void __init find_early_table_space(struct map_range *mr, int nr_range) tables = roundup(puds * sizeof(pud_t), PAGE_SIZE); tables += roundup(pmds * sizeof(pmd_t), PAGE_SIZE); tables += roundup(ptes * sizeof(pte_t), PAGE_SIZE); + tables += (pgd_extra * PAGE_SIZE); #ifdef CONFIG_X86_32 /* for fixmap */ diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index fc18be0f6f2..faf7a6830c0 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c @@ -821,6 +821,9 @@ int kern_addr_valid(unsigned long addr) if (pud_none(*pud)) return 0; + if (pud_large(*pud)) + return pfn_valid(pud_pfn(*pud)); + pmd = pmd_offset(pud, addr); if (pmd_none(*pmd)) return 0; diff --git a/arch/x86/mm/numa.c b/arch/x86/mm/numa.c index 5c276390aca..6900c1cd6a1 100644 --- a/arch/x86/mm/numa.c +++ b/arch/x86/mm/numa.c @@ -193,7 +193,6 @@ int __init numa_add_memblk(int nid, u64 start, u64 end) static void __init setup_node_data(int nid, u64 start, u64 end) { const size_t nd_size = roundup(sizeof(pg_data_t), PAGE_SIZE); - bool remapped = false; u64 nd_pa; void *nd; int tnid; @@ -205,37 +204,28 @@ static void __init setup_node_data(int nid, u64 start, u64 end) if (end && (end - start) < NODE_MIN_SIZE) return; - /* initialize remap allocator before aligning to ZONE_ALIGN */ - init_alloc_remap(nid, start, end); - start = roundup(start, ZONE_ALIGN); printk(KERN_INFO "Initmem setup node %d %016Lx-%016Lx\n", nid, start, end); /* - * Allocate node data. Try remap allocator first, node-local - * memory and then any node. Never allocate in DMA zone. + * Allocate node data. Try node-local memory and then any node. + * Never allocate in DMA zone. */ - nd = alloc_remap(nid, nd_size); - if (nd) { - nd_pa = __pa(nd); - remapped = true; - } else { - nd_pa = memblock_alloc_nid(nd_size, SMP_CACHE_BYTES, nid); - if (!nd_pa) { - pr_err("Cannot find %zu bytes in node %d\n", - nd_size, nid); - return; - } - nd = __va(nd_pa); + nd_pa = memblock_alloc_nid(nd_size, SMP_CACHE_BYTES, nid); + if (!nd_pa) { + pr_err("Cannot find %zu bytes in node %d\n", + nd_size, nid); + return; } + nd = __va(nd_pa); /* report and initialize */ - printk(KERN_INFO " NODE_DATA [%016Lx - %016Lx]%s\n", - nd_pa, nd_pa + nd_size - 1, remapped ? " (remapped)" : ""); + printk(KERN_INFO " NODE_DATA [mem %#010Lx-%#010Lx]\n", + nd_pa, nd_pa + nd_size - 1); tnid = early_pfn_to_nid(nd_pa >> PAGE_SHIFT); - if (!remapped && tnid != nid) + if (tnid != nid) printk(KERN_INFO " NODE_DATA(%d) on node %d\n", nid, tnid); node_data[nid] = nd; diff --git a/arch/x86/mm/numa_32.c b/arch/x86/mm/numa_32.c index 534255a36b6..73a6d7395bd 100644 --- a/arch/x86/mm/numa_32.c +++ b/arch/x86/mm/numa_32.c @@ -73,167 +73,6 @@ unsigned long node_memmap_size_bytes(int nid, unsigned long start_pfn, extern unsigned long highend_pfn, highstart_pfn; -#define LARGE_PAGE_BYTES (PTRS_PER_PTE * PAGE_SIZE) - -static void *node_remap_start_vaddr[MAX_NUMNODES]; -void set_pmd_pfn(unsigned long vaddr, unsigned long pfn, pgprot_t flags); - -/* - * Remap memory allocator - */ -static unsigned long node_remap_start_pfn[MAX_NUMNODES]; -static void *node_remap_end_vaddr[MAX_NUMNODES]; -static void *node_remap_alloc_vaddr[MAX_NUMNODES]; - -/** - * alloc_remap - Allocate remapped memory - * @nid: NUMA node to allocate memory from - * @size: The size of allocation - * - * Allocate @size bytes from the remap area of NUMA node @nid. The - * size of the remap area is predetermined by init_alloc_remap() and - * only the callers considered there should call this function. For - * more info, please read the comment on top of init_alloc_remap(). - * - * The caller must be ready to handle allocation failure from this - * function and fall back to regular memory allocator in such cases. - * - * CONTEXT: - * Single CPU early boot context. - * - * RETURNS: - * Pointer to the allocated memory on success, %NULL on failure. - */ -void *alloc_remap(int nid, unsigned long size) -{ - void *allocation = node_remap_alloc_vaddr[nid]; - - size = ALIGN(size, L1_CACHE_BYTES); - - if (!allocation || (allocation + size) > node_remap_end_vaddr[nid]) - return NULL; - - node_remap_alloc_vaddr[nid] += size; - memset(allocation, 0, size); - - return allocation; -} - -#ifdef CONFIG_HIBERNATION -/** - * resume_map_numa_kva - add KVA mapping to the temporary page tables created - * during resume from hibernation - * @pgd_base - temporary resume page directory - */ -void resume_map_numa_kva(pgd_t *pgd_base) -{ - int node; - - for_each_online_node(node) { - unsigned long start_va, start_pfn, nr_pages, pfn; - - start_va = (unsigned long)node_remap_start_vaddr[node]; - start_pfn = node_remap_start_pfn[node]; - nr_pages = (node_remap_end_vaddr[node] - - node_remap_start_vaddr[node]) >> PAGE_SHIFT; - - printk(KERN_DEBUG "%s: node %d\n", __func__, node); - - for (pfn = 0; pfn < nr_pages; pfn += PTRS_PER_PTE) { - unsigned long vaddr = start_va + (pfn << PAGE_SHIFT); - pgd_t *pgd = pgd_base + pgd_index(vaddr); - pud_t *pud = pud_offset(pgd, vaddr); - pmd_t *pmd = pmd_offset(pud, vaddr); - - set_pmd(pmd, pfn_pmd(start_pfn + pfn, - PAGE_KERNEL_LARGE_EXEC)); - - printk(KERN_DEBUG "%s: %08lx -> pfn %08lx\n", - __func__, vaddr, start_pfn + pfn); - } - } -} -#endif - -/** - * init_alloc_remap - Initialize remap allocator for a NUMA node - * @nid: NUMA node to initizlie remap allocator for - * - * NUMA nodes may end up without any lowmem. As allocating pgdat and - * memmap on a different node with lowmem is inefficient, a special - * remap allocator is implemented which can be used by alloc_remap(). - * - * For each node, the amount of memory which will be necessary for - * pgdat and memmap is calculated and two memory areas of the size are - * allocated - one in the node and the other in lowmem; then, the area - * in the node is remapped to the lowmem area. - * - * As pgdat and memmap must be allocated in lowmem anyway, this - * doesn't waste lowmem address space; however, the actual lowmem - * which gets remapped over is wasted. The amount shouldn't be - * problematic on machines this feature will be used. - * - * Initialization failure isn't fatal. alloc_remap() is used - * opportunistically and the callers will fall back to other memory - * allocation mechanisms on failure. - */ -void __init init_alloc_remap(int nid, u64 start, u64 end) -{ - unsigned long start_pfn = start >> PAGE_SHIFT; - unsigned long end_pfn = end >> PAGE_SHIFT; - unsigned long size, pfn; - u64 node_pa, remap_pa; - void *remap_va; - - /* - * The acpi/srat node info can show hot-add memroy zones where - * memory could be added but not currently present. - */ - printk(KERN_DEBUG "node %d pfn: [%lx - %lx]\n", - nid, start_pfn, end_pfn); - - /* calculate the necessary space aligned to large page size */ - size = node_memmap_size_bytes(nid, start_pfn, end_pfn); - size += ALIGN(sizeof(pg_data_t), PAGE_SIZE); - size = ALIGN(size, LARGE_PAGE_BYTES); - - /* allocate node memory and the lowmem remap area */ - node_pa = memblock_find_in_range(start, end, size, LARGE_PAGE_BYTES); - if (!node_pa) { - pr_warning("remap_alloc: failed to allocate %lu bytes for node %d\n", - size, nid); - return; - } - memblock_reserve(node_pa, size); - - remap_pa = memblock_find_in_range(min_low_pfn << PAGE_SHIFT, - max_low_pfn << PAGE_SHIFT, - size, LARGE_PAGE_BYTES); - if (!remap_pa) { - pr_warning("remap_alloc: failed to allocate %lu bytes remap area for node %d\n", - size, nid); - memblock_free(node_pa, size); - return; - } - memblock_reserve(remap_pa, size); - remap_va = phys_to_virt(remap_pa); - - /* perform actual remap */ - for (pfn = 0; pfn < size >> PAGE_SHIFT; pfn += PTRS_PER_PTE) - set_pmd_pfn((unsigned long)remap_va + (pfn << PAGE_SHIFT), - (node_pa >> PAGE_SHIFT) + pfn, - PAGE_KERNEL_LARGE); - - /* initialize remap allocator parameters */ - node_remap_start_pfn[nid] = node_pa >> PAGE_SHIFT; - node_remap_start_vaddr[nid] = remap_va; - node_remap_end_vaddr[nid] = remap_va + size; - node_remap_alloc_vaddr[nid] = remap_va; - - printk(KERN_DEBUG "remap_alloc: node %d [%08llx-%08llx) -> [%p-%p)\n", - nid, node_pa, node_pa + size, remap_va, remap_va + size); -} - void __init initmem_init(void) { x86_numa_init(); diff --git a/arch/x86/mm/numa_internal.h b/arch/x86/mm/numa_internal.h index 7178c3afe05..ad86ec91e64 100644 --- a/arch/x86/mm/numa_internal.h +++ b/arch/x86/mm/numa_internal.h @@ -21,12 +21,6 @@ void __init numa_reset_distance(void); void __init x86_numa_init(void); -#ifdef CONFIG_X86_64 -static inline void init_alloc_remap(int nid, u64 start, u64 end) { } -#else -void __init init_alloc_remap(int nid, u64 start, u64 end); -#endif - #ifdef CONFIG_NUMA_EMU void __init numa_emulation(struct numa_meminfo *numa_meminfo, int numa_dist_cnt); diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c index 56ab74989cf..94e76620460 100644 --- a/arch/x86/pci/xen.c +++ b/arch/x86/pci/xen.c @@ -162,6 +162,9 @@ static int xen_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) struct msi_desc *msidesc; int *v; + if (type == PCI_CAP_ID_MSI && nvec > 1) + return 1; + v = kzalloc(sizeof(int) * max(1, nvec), GFP_KERNEL); if (!v) return -ENOMEM; @@ -220,6 +223,9 @@ static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) struct msi_desc *msidesc; struct msi_msg msg; + if (type == PCI_CAP_ID_MSI && nvec > 1) + return 1; + list_for_each_entry(msidesc, &dev->msi_list, list) { __read_msi_msg(msidesc, &msg); pirq = MSI_ADDR_EXT_DEST_ID(msg.address_hi) | @@ -263,6 +269,9 @@ static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) int ret = 0; struct msi_desc *msidesc; + if (type == PCI_CAP_ID_MSI && nvec > 1) + return 1; + list_for_each_entry(msidesc, &dev->msi_list, list) { struct physdev_map_pirq map_irq; domid_t domid; diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 6825327d00a..1e406371a68 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -50,9 +50,6 @@ #define EFI_DEBUG 1 -int efi_enabled; -EXPORT_SYMBOL(efi_enabled); - struct efi __read_mostly efi = { .mps = EFI_INVALID_TABLE_ADDR, .acpi = EFI_INVALID_TABLE_ADDR, @@ -68,19 +65,29 @@ EXPORT_SYMBOL(efi); struct efi_memory_map memmap; -bool efi_64bit; - static struct efi efi_phys __initdata; static efi_system_table_t efi_systab __initdata; static inline bool efi_is_native(void) { - return IS_ENABLED(CONFIG_X86_64) == efi_64bit; + return IS_ENABLED(CONFIG_X86_64) == efi_enabled(EFI_64BIT); +} + +unsigned long x86_efi_facility; + +/* + * Returns 1 if 'facility' is enabled, 0 otherwise. + */ +int efi_enabled(int facility) +{ + return test_bit(facility, &x86_efi_facility) != 0; } +EXPORT_SYMBOL(efi_enabled); +static bool disable_runtime = false; static int __init setup_noefi(char *arg) { - efi_enabled = 0; + disable_runtime = true; return 0; } early_param("noefi", setup_noefi); @@ -425,6 +432,7 @@ void __init efi_reserve_boot_services(void) void __init efi_unmap_memmap(void) { + clear_bit(EFI_MEMMAP, &x86_efi_facility); if (memmap.map) { early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size); memmap.map = NULL; @@ -459,7 +467,7 @@ void __init efi_free_boot_services(void) static int __init efi_systab_init(void *phys) { - if (efi_64bit) { + if (efi_enabled(EFI_64BIT)) { efi_system_table_64_t *systab64; u64 tmp = 0; @@ -551,7 +559,7 @@ static int __init efi_config_init(u64 tables, int nr_tables) void *config_tables, *tablep; int i, sz; - if (efi_64bit) + if (efi_enabled(EFI_64BIT)) sz = sizeof(efi_config_table_64_t); else sz = sizeof(efi_config_table_32_t); @@ -571,7 +579,7 @@ static int __init efi_config_init(u64 tables, int nr_tables) efi_guid_t guid; unsigned long table; - if (efi_64bit) { + if (efi_enabled(EFI_64BIT)) { u64 table64; guid = ((efi_config_table_64_t *)tablep)->guid; table64 = ((efi_config_table_64_t *)tablep)->table; @@ -683,7 +691,6 @@ void __init efi_init(void) if (boot_params.efi_info.efi_systab_hi || boot_params.efi_info.efi_memmap_hi) { pr_info("Table located above 4GB, disabling EFI.\n"); - efi_enabled = 0; return; } efi_phys.systab = (efi_system_table_t *)boot_params.efi_info.efi_systab; @@ -693,10 +700,10 @@ void __init efi_init(void) ((__u64)boot_params.efi_info.efi_systab_hi<<32)); #endif - if (efi_systab_init(efi_phys.systab)) { - efi_enabled = 0; + if (efi_systab_init(efi_phys.systab)) return; - } + + set_bit(EFI_SYSTEM_TABLES, &x86_efi_facility); /* * Show what we know for posterity @@ -714,10 +721,10 @@ void __init efi_init(void) efi.systab->hdr.revision >> 16, efi.systab->hdr.revision & 0xffff, vendor); - if (efi_config_init(efi.systab->tables, efi.systab->nr_tables)) { - efi_enabled = 0; + if (efi_config_init(efi.systab->tables, efi.systab->nr_tables)) return; - } + + set_bit(EFI_CONFIG_TABLES, &x86_efi_facility); /* * Note: We currently don't support runtime services on an EFI @@ -726,15 +733,17 @@ void __init efi_init(void) if (!efi_is_native()) pr_info("No EFI runtime due to 32/64-bit mismatch with kernel\n"); - else if (efi_runtime_init()) { - efi_enabled = 0; - return; + else { + if (disable_runtime || efi_runtime_init()) + return; + set_bit(EFI_RUNTIME_SERVICES, &x86_efi_facility); } - if (efi_memmap_init()) { - efi_enabled = 0; + if (efi_memmap_init()) return; - } + + set_bit(EFI_MEMMAP, &x86_efi_facility); + #ifdef CONFIG_X86_32 if (efi_is_native()) { x86_platform.get_wallclock = efi_get_time; @@ -943,6 +952,9 @@ u64 efi_mem_attributes(unsigned long phys_addr) efi_memory_desc_t *md; void *p; + if (!efi_enabled(EFI_MEMMAP)) + return 0; + for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { md = p; if ((md->phys_addr <= phys_addr) && diff --git a/arch/x86/power/cpu.c b/arch/x86/power/cpu.c index 218cdb16163..fcbaac60d93 100644 --- a/arch/x86/power/cpu.c +++ b/arch/x86/power/cpu.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -227,6 +228,7 @@ static void __restore_processor_state(struct saved_context *ctxt) do_fpu_end(); x86_platform.restore_sched_clock_state(); mtrr_bp_restore(); + perf_restore_debug_store(); } /* Needed by apm.c */ diff --git a/arch/x86/power/hibernate_32.c b/arch/x86/power/hibernate_32.c index 74202c1910c..7d28c885d23 100644 --- a/arch/x86/power/hibernate_32.c +++ b/arch/x86/power/hibernate_32.c @@ -129,8 +129,6 @@ static int resume_physical_mapping_init(pgd_t *pgd_base) } } - resume_map_numa_kva(pgd_base); - return 0; } diff --git a/arch/x86/um/sys_call_table_32.c b/arch/x86/um/sys_call_table_32.c index 416bd40c0eb..68d1dc91b37 100644 --- a/arch/x86/um/sys_call_table_32.c +++ b/arch/x86/um/sys_call_table_32.c @@ -39,9 +39,9 @@ #undef __SYSCALL_I386 #define __SYSCALL_I386(nr, sym, compat) [ nr ] = sym, -typedef void (*sys_call_ptr_t)(void); +typedef asmlinkage void (*sys_call_ptr_t)(void); -extern void sys_ni_syscall(void); +extern asmlinkage void sys_ni_syscall(void); const sys_call_ptr_t sys_call_table[] __cacheline_aligned = { /* diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c index 660c036ef4e..5267941b5ec 100644 --- a/arch/x86/xen/enlighten.c +++ b/arch/x86/xen/enlighten.c @@ -64,6 +64,7 @@ #include #include #include +#include #ifdef CONFIG_ACPI #include @@ -138,6 +139,21 @@ static void xen_vcpu_setup(int cpu) BUG_ON(HYPERVISOR_shared_info == &xen_dummy_shared_info); + /* + * This path is called twice on PVHVM - first during bootup via + * smp_init -> xen_hvm_cpu_notify, and then if the VCPU is being + * hotplugged: cpu_up -> xen_hvm_cpu_notify. + * As we can only do the VCPUOP_register_vcpu_info once lets + * not over-write its result. + * + * For PV it is called during restore (xen_vcpu_restore) and bootup + * (xen_setup_vcpu_info_placement). The hotplug mechanism does not + * use this function. + */ + if (xen_hvm_domain()) { + if (per_cpu(xen_vcpu, cpu) == &per_cpu(xen_vcpu_info, cpu)) + return; + } if (cpu < MAX_VIRT_CPUS) per_cpu(xen_vcpu,cpu) = &HYPERVISOR_shared_info->vcpu_info[cpu]; @@ -1355,7 +1371,14 @@ asmlinkage void __init xen_start_kernel(void) */ acpi_numa = -1; #endif - +#ifdef CONFIG_X86_PAT + /* + * For right now disable the PAT. We should remove this once + * git commit 8eaffa67b43e99ae581622c5133e20b0f48bcef1 + * (xen/pat: Disable PAT support for now) is reverted. + */ + pat_enabled = 0; +#endif pgd = (pgd_t *)xen_start_info->pt_base; /* Don't do the full vcpu_info placement stuff until we have a @@ -1507,8 +1530,11 @@ static int xen_hvm_cpu_notify(struct notifier_block *self, switch (action) { case CPU_UP_PREPARE: xen_vcpu_setup(cpu); - if (xen_have_vector_callback) + if (xen_have_vector_callback) { xen_init_lock_cpu(cpu); + if (xen_feature(XENFEAT_hvm_safe_pvclock)) + xen_setup_timer(cpu); + } break; default: break; diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 5cb8e27d43d..cf7fe3617dc 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c @@ -2076,6 +2076,7 @@ static const struct pv_mmu_ops xen_mmu_ops __initconst = { .lazy_mode = { .enter = paravirt_enter_lazy_mmu, .leave = xen_leave_lazy_mmu, + .flush = paravirt_flush_lazy_mmu, }, .set_fixmap = xen_set_fixmap, diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c index 7dfd1a586f5..441dd96542d 100644 --- a/arch/x86/xen/setup.c +++ b/arch/x86/xen/setup.c @@ -213,6 +213,17 @@ static void xen_align_and_add_e820_region(u64 start, u64 size, int type) e820_add_region(start, end - start, type); } +void xen_ignore_unusable(struct e820entry *list, size_t map_size) +{ + struct e820entry *entry; + unsigned int i; + + for (i = 0, entry = list; i < map_size; i++, entry++) { + if (entry->type == E820_UNUSABLE) + entry->type = E820_RAM; + } +} + /** * machine_specific_memory_setup - Hook for machine specific memory setup. **/ @@ -251,6 +262,17 @@ char * __init xen_memory_setup(void) } BUG_ON(rc); + /* + * Xen won't allow a 1:1 mapping to be created to UNUSABLE + * regions, so if we're using the machine memory map leave the + * region as RAM as it is in the pseudo-physical map. + * + * UNUSABLE regions in domUs are not handled and will need + * a patch in the future. + */ + if (xen_initial_domain()) + xen_ignore_unusable(map, memmap.nr_entries); + /* Make sure the Xen-supplied memory map is well-ordered. */ sanitize_e820_map(map, memmap.nr_entries, &memmap.nr_entries); diff --git a/arch/x86/xen/spinlock.c b/arch/x86/xen/spinlock.c index b6eb7d2af60..7e1cc6e0f4f 100644 --- a/arch/x86/xen/spinlock.c +++ b/arch/x86/xen/spinlock.c @@ -328,7 +328,6 @@ static noinline void xen_spin_unlock_slow(struct xen_spinlock *xl) if (per_cpu(lock_spinners, cpu) == xl) { ADD_STATS(released_slow_kicked, 1); xen_send_IPI_one(cpu, XEN_SPIN_UNLOCK_VECTOR); - break; } } } diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c index 0296a952250..d50a821ec89 100644 --- a/arch/x86/xen/time.c +++ b/arch/x86/xen/time.c @@ -36,9 +36,8 @@ static DEFINE_PER_CPU(struct vcpu_runstate_info, xen_runstate); /* snapshots of runstate info */ static DEFINE_PER_CPU(struct vcpu_runstate_info, xen_runstate_snapshot); -/* unused ns of stolen and blocked time */ +/* unused ns of stolen time */ static DEFINE_PER_CPU(u64, xen_residual_stolen); -static DEFINE_PER_CPU(u64, xen_residual_blocked); /* return an consistent snapshot of 64-bit time/counter value */ static u64 get64(const u64 *p) @@ -115,7 +114,7 @@ static void do_stolen_accounting(void) { struct vcpu_runstate_info state; struct vcpu_runstate_info *snap; - s64 blocked, runnable, offline, stolen; + s64 runnable, offline, stolen; cputime_t ticks; get_runstate_snapshot(&state); @@ -125,7 +124,6 @@ static void do_stolen_accounting(void) snap = &__get_cpu_var(xen_runstate_snapshot); /* work out how much time the VCPU has not been runn*ing* */ - blocked = state.time[RUNSTATE_blocked] - snap->time[RUNSTATE_blocked]; runnable = state.time[RUNSTATE_runnable] - snap->time[RUNSTATE_runnable]; offline = state.time[RUNSTATE_offline] - snap->time[RUNSTATE_offline]; @@ -141,17 +139,6 @@ static void do_stolen_accounting(void) ticks = iter_div_u64_rem(stolen, NS_PER_TICK, &stolen); __this_cpu_write(xen_residual_stolen, stolen); account_steal_ticks(ticks); - - /* Add the appropriate number of ticks of blocked time, - including any left-overs from last time. */ - blocked += __this_cpu_read(xen_residual_blocked); - - if (blocked < 0) - blocked = 0; - - ticks = iter_div_u64_rem(blocked, NS_PER_TICK, &blocked); - __this_cpu_write(xen_residual_blocked, blocked); - account_idle_ticks(ticks); } /* Get the TSC speed from Xen */ @@ -497,7 +484,11 @@ static void xen_hvm_setup_cpu_clockevents(void) { int cpu = smp_processor_id(); xen_setup_runstate_info(cpu); - xen_setup_timer(cpu); + /* + * xen_setup_timer(cpu) - snprintf is bad in atomic context. Hence + * doing it xen_hvm_cpu_notify (which gets called by smp_init during + * early bootup and also during CPU hotplug events). + */ xen_setup_cpu_clockevents(); } diff --git a/arch/x86/xen/xen-asm_32.S b/arch/x86/xen/xen-asm_32.S index b040b0e518c..7328f71651e 100644 --- a/arch/x86/xen/xen-asm_32.S +++ b/arch/x86/xen/xen-asm_32.S @@ -88,11 +88,11 @@ ENTRY(xen_iret) */ #ifdef CONFIG_SMP GET_THREAD_INFO(%eax) - movl TI_cpu(%eax), %eax - movl __per_cpu_offset(,%eax,4), %eax - mov xen_vcpu(%eax), %eax + movl %ss:TI_cpu(%eax), %eax + movl %ss:__per_cpu_offset(,%eax,4), %eax + mov %ss:xen_vcpu(%eax), %eax #else - movl xen_vcpu, %eax + movl %ss:xen_vcpu, %eax #endif /* check IF state we're restoring */ @@ -105,11 +105,11 @@ ENTRY(xen_iret) * resuming the code, so we don't have to be worried about * being preempted to another CPU. */ - setz XEN_vcpu_info_mask(%eax) + setz %ss:XEN_vcpu_info_mask(%eax) xen_iret_start_crit: /* check for unmasked and pending */ - cmpw $0x0001, XEN_vcpu_info_pending(%eax) + cmpw $0x0001, %ss:XEN_vcpu_info_pending(%eax) /* * If there's something pending, mask events again so we can @@ -117,7 +117,7 @@ xen_iret_start_crit: * touch XEN_vcpu_info_mask. */ jne 1f - movb $1, XEN_vcpu_info_mask(%eax) + movb $1, %ss:XEN_vcpu_info_mask(%eax) 1: popl %eax diff --git a/arch/xtensa/include/asm/signal.h b/arch/xtensa/include/asm/signal.h index 633ba73bc4d..75edf8a452b 100644 --- a/arch/xtensa/include/asm/signal.h +++ b/arch/xtensa/include/asm/signal.h @@ -133,6 +133,7 @@ struct sigaction { void (*sa_restorer)(void); sigset_t sa_mask; /* mask last for extensibility */ }; +#define __ARCH_HAS_SA_RESTORER struct k_sigaction { struct sigaction sa; diff --git a/arch/xtensa/kernel/Makefile b/arch/xtensa/kernel/Makefile index 2d2728b3e86..491bd9aa39f 100644 --- a/arch/xtensa/kernel/Makefile +++ b/arch/xtensa/kernel/Makefile @@ -24,6 +24,7 @@ obj-$(CONFIG_MODULES) += xtensa_ksyms.o module.o # Replicate rules in scripts/Makefile.build sed-y = -e 's/\*(\(\.[a-z]*it\|\.ref\|\)\.text)/*(\1.literal \1.text)/g' \ + -e 's/\.text\.unlikely/.literal.unlikely .text.unlikely/g' \ -e 's/\*(\(\.text\.[a-z]*\))/*(\1.literal \1)/g' quiet_cmd__cpp_lds_S = LDS $@ diff --git a/arch/xtensa/kernel/vmlinux.lds.S b/arch/xtensa/kernel/vmlinux.lds.S index 88ecea3facb..ee2e2089483 100644 --- a/arch/xtensa/kernel/vmlinux.lds.S +++ b/arch/xtensa/kernel/vmlinux.lds.S @@ -83,7 +83,6 @@ SECTIONS _text = .; _stext = .; - _ftext = .; .text : { @@ -112,7 +111,7 @@ SECTIONS EXCEPTION_TABLE(16) /* Data section */ - _fdata = .; + _sdata = .; RW_DATA_SECTION(XCHAL_ICACHE_LINESIZE, PAGE_SIZE, THREAD_SIZE) _edata = .; diff --git a/arch/xtensa/mm/init.c b/arch/xtensa/mm/init.c index ba150e5de2e..c82af58f60b 100644 --- a/arch/xtensa/mm/init.c +++ b/arch/xtensa/mm/init.c @@ -29,7 +29,7 @@ /* References to section boundaries */ -extern char _ftext, _etext, _fdata, _edata, _rodata_end; +extern char _stext, _etext, _sdata, _edata, _rodata_end; extern char __init_begin, __init_end; /* @@ -197,8 +197,8 @@ void __init mem_init(void) reservedpages++; } - codesize = (unsigned long) &_etext - (unsigned long) &_ftext; - datasize = (unsigned long) &_edata - (unsigned long) &_fdata; + codesize = (unsigned long) &_etext - (unsigned long) &_stext; + datasize = (unsigned long) &_edata - (unsigned long) &_sdata; initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin; printk("Memory: %luk/%luk available (%ldk kernel code, %ldk reserved, " diff --git a/block/genhd.c b/block/genhd.c index 53c3f7e212a..dd448855fec 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -25,7 +25,7 @@ static DEFINE_MUTEX(block_class_lock); struct kobject *block_depr; /* for extended dynamic devt allocation, currently only one major is used */ -#define MAX_EXT_DEVT (1 << MINORBITS) +#define NR_EXT_DEVT (1 << MINORBITS) /* For extended devt allocation. ext_devt_mutex prevents look up * results from going away underneath its user. @@ -420,17 +420,18 @@ int blk_alloc_devt(struct hd_struct *part, dev_t *devt) do { if (!idr_pre_get(&ext_devt_idr, GFP_KERNEL)) return -ENOMEM; + mutex_lock(&ext_devt_mutex); rc = idr_get_new(&ext_devt_idr, part, &idx); + if (!rc && idx >= NR_EXT_DEVT) { + idr_remove(&ext_devt_idr, idx); + rc = -EBUSY; + } + mutex_unlock(&ext_devt_mutex); } while (rc == -EAGAIN); if (rc) return rc; - if (idx > MAX_EXT_DEVT) { - idr_remove(&ext_devt_idr, idx); - return -EBUSY; - } - *devt = MKDEV(BLOCK_EXT_MAJOR, blk_mangle_minor(idx)); return 0; } @@ -517,7 +518,7 @@ static void register_disk(struct gendisk *disk) ddev->parent = disk->driverfs_dev; - dev_set_name(ddev, disk->disk_name); + dev_set_name(ddev, "%s", disk->disk_name); /* delay uevents, until we scanned partition table */ dev_set_uevent_suppress(ddev, 1); @@ -644,7 +645,6 @@ void del_gendisk(struct gendisk *disk) disk_part_iter_exit(&piter); invalidate_partition(disk, 0); - blk_free_devt(disk_to_dev(disk)->devt); set_capacity(disk, 0); disk->flags &= ~GENHD_FL_UP; @@ -662,6 +662,7 @@ void del_gendisk(struct gendisk *disk) if (!sysfs_deprecated) sysfs_remove_link(block_depr, dev_name(disk_to_dev(disk))); device_del(disk_to_dev(disk)); + blk_free_devt(disk_to_dev(disk)->devt); } EXPORT_SYMBOL(del_gendisk); diff --git a/block/partition-generic.c b/block/partition-generic.c index 803d1513f4c..264028c3b8c 100644 --- a/block/partition-generic.c +++ b/block/partition-generic.c @@ -260,11 +260,11 @@ void delete_partition(struct gendisk *disk, int partno) if (!part) return; - blk_free_devt(part_devt(part)); rcu_assign_pointer(ptbl->part[partno], NULL); rcu_assign_pointer(ptbl->last_lookup, NULL); kobject_put(part->holder_dir); device_del(part_to_dev(part)); + blk_free_devt(part_devt(part)); hd_struct_put(part); } diff --git a/crypto/ablkcipher.c b/crypto/ablkcipher.c index 8d3a056ebee..45fe4109698 100644 --- a/crypto/ablkcipher.c +++ b/crypto/ablkcipher.c @@ -388,9 +388,9 @@ static int crypto_ablkcipher_report(struct sk_buff *skb, struct crypto_alg *alg) { struct crypto_report_blkcipher rblkcipher; - snprintf(rblkcipher.type, CRYPTO_MAX_ALG_NAME, "%s", "ablkcipher"); - snprintf(rblkcipher.geniv, CRYPTO_MAX_ALG_NAME, "%s", - alg->cra_ablkcipher.geniv ?: ""); + strncpy(rblkcipher.type, "ablkcipher", sizeof(rblkcipher.type)); + strncpy(rblkcipher.geniv, alg->cra_ablkcipher.geniv ?: "", + sizeof(rblkcipher.geniv)); rblkcipher.blocksize = alg->cra_blocksize; rblkcipher.min_keysize = alg->cra_ablkcipher.min_keysize; @@ -469,9 +469,9 @@ static int crypto_givcipher_report(struct sk_buff *skb, struct crypto_alg *alg) { struct crypto_report_blkcipher rblkcipher; - snprintf(rblkcipher.type, CRYPTO_MAX_ALG_NAME, "%s", "givcipher"); - snprintf(rblkcipher.geniv, CRYPTO_MAX_ALG_NAME, "%s", - alg->cra_ablkcipher.geniv ?: ""); + strncpy(rblkcipher.type, "givcipher", sizeof(rblkcipher.type)); + strncpy(rblkcipher.geniv, alg->cra_ablkcipher.geniv ?: "", + sizeof(rblkcipher.geniv)); rblkcipher.blocksize = alg->cra_blocksize; rblkcipher.min_keysize = alg->cra_ablkcipher.min_keysize; diff --git a/crypto/aead.c b/crypto/aead.c index e4cb35159be..c706d7415de 100644 --- a/crypto/aead.c +++ b/crypto/aead.c @@ -117,9 +117,8 @@ static int crypto_aead_report(struct sk_buff *skb, struct crypto_alg *alg) struct crypto_report_aead raead; struct aead_alg *aead = &alg->cra_aead; - snprintf(raead.type, CRYPTO_MAX_ALG_NAME, "%s", "aead"); - snprintf(raead.geniv, CRYPTO_MAX_ALG_NAME, "%s", - aead->geniv ?: ""); + strncpy(raead.type, "aead", sizeof(raead.type)); + strncpy(raead.geniv, aead->geniv ?: "", sizeof(raead.geniv)); raead.blocksize = alg->cra_blocksize; raead.maxauthsize = aead->maxauthsize; @@ -203,8 +202,8 @@ static int crypto_nivaead_report(struct sk_buff *skb, struct crypto_alg *alg) struct crypto_report_aead raead; struct aead_alg *aead = &alg->cra_aead; - snprintf(raead.type, CRYPTO_MAX_ALG_NAME, "%s", "nivaead"); - snprintf(raead.geniv, CRYPTO_MAX_ALG_NAME, "%s", aead->geniv); + strncpy(raead.type, "nivaead", sizeof(raead.type)); + strncpy(raead.geniv, aead->geniv, sizeof(raead.geniv)); raead.blocksize = alg->cra_blocksize; raead.maxauthsize = aead->maxauthsize; diff --git a/crypto/ahash.c b/crypto/ahash.c index 33bc9b62e9a..0ec05feea43 100644 --- a/crypto/ahash.c +++ b/crypto/ahash.c @@ -404,7 +404,7 @@ static int crypto_ahash_report(struct sk_buff *skb, struct crypto_alg *alg) { struct crypto_report_hash rhash; - snprintf(rhash.type, CRYPTO_MAX_ALG_NAME, "%s", "ahash"); + strncpy(rhash.type, "ahash", sizeof(rhash.type)); rhash.blocksize = alg->cra_blocksize; rhash.digestsize = __crypto_hash_alg_common(alg)->digestsize; diff --git a/crypto/algapi.c b/crypto/algapi.c index 056571b8544..b4c046c3941 100644 --- a/crypto/algapi.c +++ b/crypto/algapi.c @@ -512,7 +512,8 @@ static struct crypto_template *__crypto_lookup_template(const char *name) struct crypto_template *crypto_lookup_template(const char *name) { - return try_then_request_module(__crypto_lookup_template(name), name); + return try_then_request_module(__crypto_lookup_template(name), "%s", + name); } EXPORT_SYMBOL_GPL(crypto_lookup_template); diff --git a/crypto/algif_hash.c b/crypto/algif_hash.c index ef5356cd280..0262210cad3 100644 --- a/crypto/algif_hash.c +++ b/crypto/algif_hash.c @@ -161,6 +161,8 @@ static int hash_recvmsg(struct kiocb *unused, struct socket *sock, else if (len < ds) msg->msg_flags |= MSG_TRUNC; + msg->msg_namelen = 0; + lock_sock(sk); if (ctx->more) { ctx->more = 0; diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c index 6a6dfc062d2..a1c4f0a5558 100644 --- a/crypto/algif_skcipher.c +++ b/crypto/algif_skcipher.c @@ -432,6 +432,7 @@ static int skcipher_recvmsg(struct kiocb *unused, struct socket *sock, long copied = 0; lock_sock(sk); + msg->msg_namelen = 0; for (iov = msg->msg_iov, iovlen = msg->msg_iovlen; iovlen > 0; iovlen--, iov++) { unsigned long seglen = iov->iov_len; diff --git a/crypto/blkcipher.c b/crypto/blkcipher.c index 4dd80c72549..0a1ebea3d6f 100644 --- a/crypto/blkcipher.c +++ b/crypto/blkcipher.c @@ -499,9 +499,9 @@ static int crypto_blkcipher_report(struct sk_buff *skb, struct crypto_alg *alg) { struct crypto_report_blkcipher rblkcipher; - snprintf(rblkcipher.type, CRYPTO_MAX_ALG_NAME, "%s", "blkcipher"); - snprintf(rblkcipher.geniv, CRYPTO_MAX_ALG_NAME, "%s", - alg->cra_blkcipher.geniv ?: ""); + strncpy(rblkcipher.type, "blkcipher", sizeof(rblkcipher.type)); + strncpy(rblkcipher.geniv, alg->cra_blkcipher.geniv ?: "", + sizeof(rblkcipher.geniv)); rblkcipher.blocksize = alg->cra_blocksize; rblkcipher.min_keysize = alg->cra_blkcipher.min_keysize; diff --git a/crypto/crypto_user.c b/crypto/crypto_user.c index f1ea0a06413..910497bd72b 100644 --- a/crypto/crypto_user.c +++ b/crypto/crypto_user.c @@ -75,7 +75,7 @@ static int crypto_report_cipher(struct sk_buff *skb, struct crypto_alg *alg) { struct crypto_report_cipher rcipher; - snprintf(rcipher.type, CRYPTO_MAX_ALG_NAME, "%s", "cipher"); + strncpy(rcipher.type, "cipher", sizeof(rcipher.type)); rcipher.blocksize = alg->cra_blocksize; rcipher.min_keysize = alg->cra_cipher.cia_min_keysize; @@ -94,8 +94,7 @@ static int crypto_report_comp(struct sk_buff *skb, struct crypto_alg *alg) { struct crypto_report_comp rcomp; - snprintf(rcomp.type, CRYPTO_MAX_ALG_NAME, "%s", "compression"); - + strncpy(rcomp.type, "compression", sizeof(rcomp.type)); NLA_PUT(skb, CRYPTOCFGA_REPORT_COMPRESS, sizeof(struct crypto_report_comp), &rcomp); @@ -108,12 +107,14 @@ static int crypto_report_comp(struct sk_buff *skb, struct crypto_alg *alg) static int crypto_report_one(struct crypto_alg *alg, struct crypto_user_alg *ualg, struct sk_buff *skb) { - memcpy(&ualg->cru_name, &alg->cra_name, sizeof(ualg->cru_name)); - memcpy(&ualg->cru_driver_name, &alg->cra_driver_name, - sizeof(ualg->cru_driver_name)); - memcpy(&ualg->cru_module_name, module_name(alg->cra_module), - CRYPTO_MAX_ALG_NAME); - + strncpy(ualg->cru_name, alg->cra_name, sizeof(ualg->cru_name)); + strncpy(ualg->cru_driver_name, alg->cra_driver_name, + sizeof(ualg->cru_driver_name)); + strncpy(ualg->cru_module_name, module_name(alg->cra_module), + sizeof(ualg->cru_module_name)); + + ualg->cru_type = 0; + ualg->cru_mask = 0; ualg->cru_flags = alg->cra_flags; ualg->cru_refcnt = atomic_read(&alg->cra_refcnt); @@ -122,8 +123,7 @@ static int crypto_report_one(struct crypto_alg *alg, if (alg->cra_flags & CRYPTO_ALG_LARVAL) { struct crypto_report_larval rl; - snprintf(rl.type, CRYPTO_MAX_ALG_NAME, "%s", "larval"); - + strncpy(rl.type, "larval", sizeof(rl.type)); NLA_PUT(skb, CRYPTOCFGA_REPORT_LARVAL, sizeof(struct crypto_report_larval), &rl); diff --git a/crypto/gcm.c b/crypto/gcm.c index 1a252639ef9..b97b186d561 100644 --- a/crypto/gcm.c +++ b/crypto/gcm.c @@ -44,6 +44,7 @@ struct crypto_rfc4543_ctx { struct crypto_rfc4543_req_ctx { u8 auth_tag[16]; + u8 assocbuf[32]; struct scatterlist cipher[1]; struct scatterlist payload[2]; struct scatterlist assoc[2]; @@ -1142,9 +1143,19 @@ static struct aead_request *crypto_rfc4543_crypt(struct aead_request *req, scatterwalk_crypto_chain(payload, dst, vdst == req->iv + 8, 2); assoclen += 8 + req->cryptlen - (enc ? 0 : authsize); - sg_init_table(assoc, 2); - sg_set_page(assoc, sg_page(req->assoc), req->assoc->length, - req->assoc->offset); + if (req->assoc->length == req->assoclen) { + sg_init_table(assoc, 2); + sg_set_page(assoc, sg_page(req->assoc), req->assoc->length, + req->assoc->offset); + } else { + BUG_ON(req->assoclen > sizeof(rctx->assocbuf)); + + scatterwalk_map_and_copy(rctx->assocbuf, req->assoc, 0, + req->assoclen, 0); + + sg_init_table(assoc, 2); + sg_set_buf(assoc, rctx->assocbuf, req->assoclen); + } scatterwalk_crypto_chain(assoc, payload, 0, 2); aead_request_set_tfm(subreq, ctx->child); diff --git a/crypto/pcompress.c b/crypto/pcompress.c index 2e458e5482d..6f2a361bb03 100644 --- a/crypto/pcompress.c +++ b/crypto/pcompress.c @@ -53,8 +53,7 @@ static int crypto_pcomp_report(struct sk_buff *skb, struct crypto_alg *alg) { struct crypto_report_comp rpcomp; - snprintf(rpcomp.type, CRYPTO_MAX_ALG_NAME, "%s", "pcomp"); - + strncpy(rpcomp.type, "pcomp", sizeof(rpcomp.type)); NLA_PUT(skb, CRYPTOCFGA_REPORT_COMPRESS, sizeof(struct crypto_report_comp), &rpcomp); diff --git a/crypto/rng.c b/crypto/rng.c index 64f864fa804..1966c1d0d7f 100644 --- a/crypto/rng.c +++ b/crypto/rng.c @@ -65,7 +65,7 @@ static int crypto_rng_report(struct sk_buff *skb, struct crypto_alg *alg) { struct crypto_report_rng rrng; - snprintf(rrng.type, CRYPTO_MAX_ALG_NAME, "%s", "rng"); + strncpy(rrng.type, "rng", sizeof(rrng.type)); rrng.seedsize = alg->cra_rng.seedsize; diff --git a/crypto/shash.c b/crypto/shash.c index 21fc12e2378..3b2a71f6660 100644 --- a/crypto/shash.c +++ b/crypto/shash.c @@ -530,7 +530,8 @@ static int crypto_shash_report(struct sk_buff *skb, struct crypto_alg *alg) struct crypto_report_hash rhash; struct shash_alg *salg = __crypto_shash_alg(alg); - snprintf(rhash.type, CRYPTO_MAX_ALG_NAME, "%s", "shash"); + strncpy(rhash.type, "shash", sizeof(rhash.type)); + rhash.blocksize = alg->cra_blocksize; rhash.digestsize = salg->digestsize; diff --git a/drivers/acpi/acpi_memhotplug.c b/drivers/acpi/acpi_memhotplug.c index d9857138565..f81597f1b91 100644 --- a/drivers/acpi/acpi_memhotplug.c +++ b/drivers/acpi/acpi_memhotplug.c @@ -421,6 +421,7 @@ static int acpi_memory_device_add(struct acpi_device *device) /* Get the range from the _CRS */ result = acpi_memory_get_device_resources(mem_device); if (result) { + device->driver_data = NULL; kfree(mem_device); return result; } diff --git a/drivers/acpi/acpica/exfldio.c b/drivers/acpi/acpica/exfldio.c index 149de45fdad..af9f1f60c94 100644 --- a/drivers/acpi/acpica/exfldio.c +++ b/drivers/acpi/acpica/exfldio.c @@ -722,7 +722,19 @@ acpi_ex_extract_from_field(union acpi_operand_object *obj_desc, if ((obj_desc->common_field.start_field_bit_offset == 0) && (obj_desc->common_field.bit_length == access_bit_width)) { - status = acpi_ex_field_datum_io(obj_desc, 0, buffer, ACPI_READ); + if (buffer_length >= sizeof(u64)) { + status = + acpi_ex_field_datum_io(obj_desc, 0, buffer, + ACPI_READ); + } else { + /* Use raw_datum (u64) to handle buffers < 64 bits */ + + status = + acpi_ex_field_datum_io(obj_desc, 0, &raw_datum, + ACPI_READ); + ACPI_MEMCPY(buffer, &raw_datum, buffer_length); + } + return_ACPI_STATUS(status); } diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 6ea287e2229..9bdfcf50a19 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -117,6 +117,7 @@ struct acpi_battery { struct acpi_device *device; struct notifier_block pm_nb; unsigned long update_time; + int revision; int rate_now; int capacity_now; int voltage_now; @@ -350,6 +351,7 @@ static struct acpi_offsets info_offsets[] = { }; static struct acpi_offsets extended_info_offsets[] = { + {offsetof(struct acpi_battery, revision), 0}, {offsetof(struct acpi_battery, power_unit), 0}, {offsetof(struct acpi_battery, design_capacity), 0}, {offsetof(struct acpi_battery, full_charge_capacity), 0}, diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index a51df968131..3251d4b4ac1 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -217,7 +217,7 @@ static int ec_check_sci_sync(struct acpi_ec *ec, u8 state) static int ec_poll(struct acpi_ec *ec) { unsigned long flags; - int repeat = 2; /* number of command restarts */ + int repeat = 5; /* number of command restarts */ while (repeat--) { unsigned long delay = jiffies + msecs_to_jiffies(ec_delay); @@ -235,8 +235,6 @@ static int ec_poll(struct acpi_ec *ec) } advance_transaction(ec, acpi_ec_read_status(ec)); } while (time_before(jiffies, delay)); - if (acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF) - break; pr_debug(PREFIX "controller reset, restart transaction\n"); spin_lock_irqsave(&ec->curr_lock, flags); start_transaction(ec); @@ -976,6 +974,10 @@ static struct dmi_system_id __initdata ec_dmi_table[] = { ec_enlarge_storm_threshold, "CLEVO hardware", { DMI_MATCH(DMI_SYS_VENDOR, "CLEVO Co."), DMI_MATCH(DMI_PRODUCT_NAME, "M720T/M730T"),}, NULL}, + { + ec_skip_dsdt_scan, "HP Folio 13", { + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP Folio 13"),}, NULL}, {}, }; diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index c3881b2eb8b..f48720cf96f 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -250,7 +250,7 @@ acpi_physical_address __init acpi_os_get_root_pointer(void) return acpi_rsdp; #endif - if (efi_enabled) { + if (efi_enabled(EFI_CONFIG_TABLES)) { if (efi.acpi20 != EFI_INVALID_TABLE_ADDR) return efi.acpi20; else if (efi.acpi != EFI_INVALID_TABLE_ADDR) diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 7aff6312ce7..5b0f0756557 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -247,8 +247,8 @@ static acpi_status acpi_pci_query_osc(struct acpi_pci_root *root, *control &= OSC_PCI_CONTROL_MASKS; capbuf[OSC_CONTROL_TYPE] = *control | root->osc_control_set; } else { - /* Run _OSC query for all possible controls. */ - capbuf[OSC_CONTROL_TYPE] = OSC_PCI_CONTROL_MASKS; + /* Run _OSC query only with existing controls. */ + capbuf[OSC_CONTROL_TYPE] = root->osc_control_set; } status = acpi_pci_run_osc(root->device->handle, capbuf, &result); diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index aa0a904e563..189c704a950 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -186,6 +186,14 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { }, { .callback = init_nvs_nosave, + .ident = "Sony Vaio VGN-FW41E_H", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FW41E_H"), + }, + }, + { + .callback = init_nvs_nosave, .ident = "Sony Vaio VGN-FW21E", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 91357e1a1a8..6d2c49ba47a 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -447,6 +447,22 @@ static struct dmi_system_id video_dmi_table[] __initdata = { DMI_MATCH(DMI_PRODUCT_NAME, "HP Folio 13 - 2000 Notebook PC"), }, }, + { + .callback = video_ignore_initial_backlight, + .ident = "HP Pavilion g6 Notebook PC", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion g6 Notebook PC"), + }, + }, + { + .callback = video_ignore_initial_backlight, + .ident = "HP Pavilion m4", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion m4 Notebook PC"), + }, + }, {} }; diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 6bdedd7cca2..1ad34ed3621 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -93,7 +93,7 @@ config SATA_FSL If unsure, say N. config SATA_INIC162X - tristate "Initio 162x SATA support" + tristate "Initio 162x SATA support (Very Experimental)" depends on PCI help This option enables support for Initio 162x Serial ATA. diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 71a4d040f14..aeb8220072d 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -284,6 +284,7 @@ static const struct pci_device_id ahci_pci_tbl[] = { /* AMD */ { PCI_VDEVICE(AMD, 0x7800), board_ahci }, /* AMD Hudson-2 */ + { PCI_VDEVICE(AMD, 0x7900), board_ahci }, /* AMD CZ */ /* AMD is using RAID class only for ahci controllers */ { PCI_VENDOR_ID_AMD, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_RAID << 8, 0xffffff, board_ahci }, diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index 3c809bfbccf..9dbd3aee087 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -150,6 +150,8 @@ enum piix_controller_ids { tolapai_sata, piix_pata_vmw, /* PIIX4 for VMware, spurious DMA_ERR */ ich8_sata_snb, + ich8_2port_sata_snb, + ich8_2port_sata_byt, }; struct piix_map_db { @@ -326,11 +328,33 @@ static const struct pci_device_id piix_pci_tbl[] = { /* SATA Controller IDE (Lynx Point) */ { 0x8086, 0x8c01, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb }, /* SATA Controller IDE (Lynx Point) */ - { 0x8086, 0x8c08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, + { 0x8086, 0x8c08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata_snb }, /* SATA Controller IDE (Lynx Point) */ { 0x8086, 0x8c09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, /* SATA Controller IDE (DH89xxCC) */ { 0x8086, 0x2326, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, + /* SATA Controller IDE (Avoton) */ + { 0x8086, 0x1f20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb }, + /* SATA Controller IDE (Avoton) */ + { 0x8086, 0x1f21, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb }, + /* SATA Controller IDE (Avoton) */ + { 0x8086, 0x1f30, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, + /* SATA Controller IDE (Avoton) */ + { 0x8086, 0x1f31, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, + /* SATA Controller IDE (Wellsburg) */ + { 0x8086, 0x8d00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb }, + /* SATA Controller IDE (Wellsburg) */ + { 0x8086, 0x8d08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata_snb }, + /* SATA Controller IDE (Wellsburg) */ + { 0x8086, 0x8d60, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb }, + /* SATA Controller IDE (Wellsburg) */ + { 0x8086, 0x8d68, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, + /* SATA Controller IDE (BayTrail) */ + { 0x8086, 0x0F20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata_byt }, + { 0x8086, 0x0F21, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata_byt }, + /* SATA Controller IDE (Coleto Creek) */ + { 0x8086, 0x23a6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, + { } /* terminate list */ }; @@ -494,6 +518,8 @@ static const struct piix_map_db *piix_map_db_table[] = { [ich8m_apple_sata] = &ich8m_apple_map_db, [tolapai_sata] = &tolapai_map_db, [ich8_sata_snb] = &ich8_map_db, + [ich8_2port_sata_snb] = &ich8_2port_map_db, + [ich8_2port_sata_byt] = &ich8_2port_map_db, }; static struct ata_port_info piix_port_info[] = { @@ -635,6 +661,25 @@ static struct ata_port_info piix_port_info[] = { .port_ops = &piix_sata_ops, }, + [ich8_2port_sata_snb] = + { + .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR + | PIIX_FLAG_PIO16, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA6, + .port_ops = &piix_sata_ops, + }, + + [ich8_2port_sata_byt] = + { + .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR | PIIX_FLAG_PIO16, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA6, + .port_ops = &piix_sata_ops, + }, + }; static struct pci_bits piix_enable_bits[] = { @@ -1577,12 +1622,31 @@ static void piix_ignore_devices_quirk(struct ata_host *host) }, { } /* terminate list */ }; - const struct dmi_system_id *dmi = dmi_first_match(ignore_hyperv); + static const struct dmi_system_id allow_virtual_pc[] = { + { + /* In MS Virtual PC guests the DMI ident is nearly + * identical to a Hyper-V guest. One difference is the + * product version which is used here to identify + * a Virtual PC guest. This entry allows ata_piix to + * drive the emulated hardware. + */ + .ident = "MS Virtual PC 2007", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, + "Microsoft Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "Virtual Machine"), + DMI_MATCH(DMI_PRODUCT_VERSION, "VS2005R2"), + }, + }, + { } /* terminate list */ + }; + const struct dmi_system_id *ignore = dmi_first_match(ignore_hyperv); + const struct dmi_system_id *allow = dmi_first_match(allow_virtual_pc); - if (dmi && prefer_ms_hyperv) { + if (ignore && !allow && prefer_ms_hyperv) { host->flags |= ATA_HOST_IGNORE_ATA; dev_info(host->dev, "%s detected, ATA device ignore set\n", - dmi->ident); + ignore->ident); } #endif } diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index f9eaa82311a..47a1fb85ff0 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -1543,8 +1543,7 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat) u32 fbs = readl(port_mmio + PORT_FBS); int pmp = fbs >> PORT_FBS_DWE_OFFSET; - if ((fbs & PORT_FBS_SDE) && (pmp < ap->nr_pmp_links) && - ata_link_online(&ap->pmp_link[pmp])) { + if ((fbs & PORT_FBS_SDE) && (pmp < ap->nr_pmp_links)) { link = &ap->pmp_link[pmp]; fbs_need_dec = true; } diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 4b4caa3db6c..9cf09ae8cf1 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -1599,6 +1599,12 @@ unsigned ata_exec_internal_sg(struct ata_device *dev, qc->tf = *tf; if (cdb) memcpy(qc->cdb, cdb, ATAPI_CDB_LEN); + + /* some SATA bridges need us to indicate data xfer direction */ + if (tf->protocol == ATAPI_PROT_DMA && (dev->flags & ATA_DFLAG_DMADIR) && + dma_dir == DMA_FROM_DEVICE) + qc->tf.feature |= ATAPI_DMADIR; + qc->flags |= ATA_QCFLAG_RESULT_TF; qc->dma_dir = dma_dir; if (dma_dir != DMA_NONE) { @@ -2408,6 +2414,9 @@ int ata_dev_configure(struct ata_device *dev) dev->max_sectors = min_t(unsigned int, ATA_MAX_SECTORS_128, dev->max_sectors); + if (dev->horkage & ATA_HORKAGE_MAX_SEC_LBA48) + dev->max_sectors = ATA_MAX_SECTORS_LBA48; + if (ap->ops->dev_config) ap->ops->dev_config(dev); @@ -4064,6 +4073,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { /* Weird ATAPI devices */ { "TORiSAN DVD-ROM DRD-N216", NULL, ATA_HORKAGE_MAX_SEC_128 }, { "QUANTUM DAT DAT72-000", NULL, ATA_HORKAGE_ATAPI_MOD16_DMA }, + { "Slimtype DVD A DS8A8SH", NULL, ATA_HORKAGE_MAX_SEC_LBA48 }, /* Devices we expect to fail diagnostics */ diff --git a/drivers/ata/libata-pmp.c b/drivers/ata/libata-pmp.c index 21b80c555c6..f5c35beadc6 100644 --- a/drivers/ata/libata-pmp.c +++ b/drivers/ata/libata-pmp.c @@ -289,24 +289,24 @@ static int sata_pmp_configure(struct ata_device *dev, int print_info) /* Disable sending Early R_OK. * With "cached read" HDD testing and multiple ports busy on a SATA - * host controller, 3726 PMP will very rarely drop a deferred + * host controller, 3x26 PMP will very rarely drop a deferred * R_OK that was intended for the host. Symptom will be all * 5 drives under test will timeout, get reset, and recover. */ - if (vendor == 0x1095 && devid == 0x3726) { + if (vendor == 0x1095 && (devid == 0x3726 || devid == 0x3826)) { u32 reg; err_mask = sata_pmp_read(&ap->link, PMP_GSCR_SII_POL, ®); if (err_mask) { rc = -EIO; - reason = "failed to read Sil3726 Private Register"; + reason = "failed to read Sil3x26 Private Register"; goto fail; } reg &= ~0x1; err_mask = sata_pmp_write(&ap->link, PMP_GSCR_SII_POL, reg); if (err_mask) { rc = -EIO; - reason = "failed to write Sil3726 Private Register"; + reason = "failed to write Sil3x26 Private Register"; goto fail; } } @@ -383,15 +383,19 @@ static void sata_pmp_quirks(struct ata_port *ap) u16 devid = sata_pmp_gscr_devid(gscr); struct ata_link *link; - if (vendor == 0x1095 && devid == 0x3726) { - /* sil3726 quirks */ + if (vendor == 0x1095 && (devid == 0x3726 || devid == 0x3826)) { + /* sil3x26 quirks */ ata_for_each_link(link, ap, EDGE) { /* link reports offline after LPM */ link->flags |= ATA_LFLAG_NO_LPM; - /* Class code report is unreliable. */ + /* + * Class code report is unreliable and SRST times + * out under certain configurations. + */ if (link->pmp < 5) - link->flags |= ATA_LFLAG_ASSUME_ATA; + link->flags |= ATA_LFLAG_NO_SRST | + ATA_LFLAG_ASSUME_ATA; /* port 5 is for SEMB device and it doesn't like SRST */ if (link->pmp == 5) @@ -399,20 +403,17 @@ static void sata_pmp_quirks(struct ata_port *ap) ATA_LFLAG_ASSUME_SEMB; } } else if (vendor == 0x1095 && devid == 0x4723) { - /* sil4723 quirks */ - ata_for_each_link(link, ap, EDGE) { - /* link reports offline after LPM */ - link->flags |= ATA_LFLAG_NO_LPM; - - /* class code report is unreliable */ - if (link->pmp < 2) - link->flags |= ATA_LFLAG_ASSUME_ATA; - - /* the config device at port 2 locks up on SRST */ - if (link->pmp == 2) - link->flags |= ATA_LFLAG_NO_SRST | - ATA_LFLAG_ASSUME_ATA; - } + /* + * sil4723 quirks + * + * Link reports offline after LPM. Class code report is + * unreliable. SIMG PMPs never got SRST reliable and the + * config device at port 2 locks up on SRST. + */ + ata_for_each_link(link, ap, EDGE) + link->flags |= ATA_LFLAG_NO_LPM | + ATA_LFLAG_NO_SRST | + ATA_LFLAG_ASSUME_ATA; } else if (vendor == 0x1095 && devid == 0x4726) { /* sil4726 quirks */ ata_for_each_link(link, ap, EDGE) { diff --git a/drivers/ata/sata_inic162x.c b/drivers/ata/sata_inic162x.c index 5c7d70c03bf..3a8b55e4425 100644 --- a/drivers/ata/sata_inic162x.c +++ b/drivers/ata/sata_inic162x.c @@ -6,6 +6,18 @@ * * This file is released under GPL v2. * + * **** WARNING **** + * + * This driver never worked properly and unfortunately data corruption is + * relatively common. There isn't anyone working on the driver and there's + * no support from the vendor. Do not use this driver in any production + * environment. + * + * http://thread.gmane.org/gmane.linux.debian.devel.bugs.rc/378525/focus=54491 + * https://bugzilla.kernel.org/show_bug.cgi?id=60565 + * + * ***************** + * * This controller is eccentric and easily locks up if something isn't * right. Documentation is available at initio's website but it only * documents registers (not programming model). @@ -809,6 +821,8 @@ static int inic_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) ata_print_version_once(&pdev->dev, DRV_VERSION); + dev_alert(&pdev->dev, "inic162x support is broken with common data corruption issues and will be disabled by default, contact linux-ide@vger.kernel.org if in production use\n"); + /* alloc host */ host = ata_host_alloc_pinfo(&pdev->dev, ppi, NR_PORTS); hpriv = devm_kzalloc(&pdev->dev, sizeof(*hpriv), GFP_KERNEL); diff --git a/drivers/atm/iphase.h b/drivers/atm/iphase.h index 6a0955e6d4f..53ecac5a216 100644 --- a/drivers/atm/iphase.h +++ b/drivers/atm/iphase.h @@ -636,82 +636,82 @@ struct rx_buf_desc { #define SEG_BASE IPHASE5575_FRAG_CONTROL_REG_BASE #define REASS_BASE IPHASE5575_REASS_CONTROL_REG_BASE -typedef volatile u_int freg_t; +typedef volatile u_int ffreg_t; typedef u_int rreg_t; typedef struct _ffredn_t { - freg_t idlehead_high; /* Idle cell header (high) */ - freg_t idlehead_low; /* Idle cell header (low) */ - freg_t maxrate; /* Maximum rate */ - freg_t stparms; /* Traffic Management Parameters */ - freg_t abrubr_abr; /* ABRUBR Priority Byte 1, TCR Byte 0 */ - freg_t rm_type; /* */ - u_int filler5[0x17 - 0x06]; - freg_t cmd_reg; /* Command register */ - u_int filler18[0x20 - 0x18]; - freg_t cbr_base; /* CBR Pointer Base */ - freg_t vbr_base; /* VBR Pointer Base */ - freg_t abr_base; /* ABR Pointer Base */ - freg_t ubr_base; /* UBR Pointer Base */ - u_int filler24; - freg_t vbrwq_base; /* VBR Wait Queue Base */ - freg_t abrwq_base; /* ABR Wait Queue Base */ - freg_t ubrwq_base; /* UBR Wait Queue Base */ - freg_t vct_base; /* Main VC Table Base */ - freg_t vcte_base; /* Extended Main VC Table Base */ - u_int filler2a[0x2C - 0x2A]; - freg_t cbr_tab_beg; /* CBR Table Begin */ - freg_t cbr_tab_end; /* CBR Table End */ - freg_t cbr_pointer; /* CBR Pointer */ - u_int filler2f[0x30 - 0x2F]; - freg_t prq_st_adr; /* Packet Ready Queue Start Address */ - freg_t prq_ed_adr; /* Packet Ready Queue End Address */ - freg_t prq_rd_ptr; /* Packet Ready Queue read pointer */ - freg_t prq_wr_ptr; /* Packet Ready Queue write pointer */ - freg_t tcq_st_adr; /* Transmit Complete Queue Start Address*/ - freg_t tcq_ed_adr; /* Transmit Complete Queue End Address */ - freg_t tcq_rd_ptr; /* Transmit Complete Queue read pointer */ - freg_t tcq_wr_ptr; /* Transmit Complete Queue write pointer*/ - u_int filler38[0x40 - 0x38]; - freg_t queue_base; /* Base address for PRQ and TCQ */ - freg_t desc_base; /* Base address of descriptor table */ - u_int filler42[0x45 - 0x42]; - freg_t mode_reg_0; /* Mode register 0 */ - freg_t mode_reg_1; /* Mode register 1 */ - freg_t intr_status_reg;/* Interrupt Status register */ - freg_t mask_reg; /* Mask Register */ - freg_t cell_ctr_high1; /* Total cell transfer count (high) */ - freg_t cell_ctr_lo1; /* Total cell transfer count (low) */ - freg_t state_reg; /* Status register */ - u_int filler4c[0x58 - 0x4c]; - freg_t curr_desc_num; /* Contains the current descriptor num */ - freg_t next_desc; /* Next descriptor */ - freg_t next_vc; /* Next VC */ - u_int filler5b[0x5d - 0x5b]; - freg_t present_slot_cnt;/* Present slot count */ - u_int filler5e[0x6a - 0x5e]; - freg_t new_desc_num; /* New descriptor number */ - freg_t new_vc; /* New VC */ - freg_t sched_tbl_ptr; /* Schedule table pointer */ - freg_t vbrwq_wptr; /* VBR wait queue write pointer */ - freg_t vbrwq_rptr; /* VBR wait queue read pointer */ - freg_t abrwq_wptr; /* ABR wait queue write pointer */ - freg_t abrwq_rptr; /* ABR wait queue read pointer */ - freg_t ubrwq_wptr; /* UBR wait queue write pointer */ - freg_t ubrwq_rptr; /* UBR wait queue read pointer */ - freg_t cbr_vc; /* CBR VC */ - freg_t vbr_sb_vc; /* VBR SB VC */ - freg_t abr_sb_vc; /* ABR SB VC */ - freg_t ubr_sb_vc; /* UBR SB VC */ - freg_t vbr_next_link; /* VBR next link */ - freg_t abr_next_link; /* ABR next link */ - freg_t ubr_next_link; /* UBR next link */ - u_int filler7a[0x7c-0x7a]; - freg_t out_rate_head; /* Out of rate head */ - u_int filler7d[0xca-0x7d]; /* pad out to full address space */ - freg_t cell_ctr_high1_nc;/* Total cell transfer count (high) */ - freg_t cell_ctr_lo1_nc;/* Total cell transfer count (low) */ - u_int fillercc[0x100-0xcc]; /* pad out to full address space */ + ffreg_t idlehead_high; /* Idle cell header (high) */ + ffreg_t idlehead_low; /* Idle cell header (low) */ + ffreg_t maxrate; /* Maximum rate */ + ffreg_t stparms; /* Traffic Management Parameters */ + ffreg_t abrubr_abr; /* ABRUBR Priority Byte 1, TCR Byte 0 */ + ffreg_t rm_type; /* */ + u_int filler5[0x17 - 0x06]; + ffreg_t cmd_reg; /* Command register */ + u_int filler18[0x20 - 0x18]; + ffreg_t cbr_base; /* CBR Pointer Base */ + ffreg_t vbr_base; /* VBR Pointer Base */ + ffreg_t abr_base; /* ABR Pointer Base */ + ffreg_t ubr_base; /* UBR Pointer Base */ + u_int filler24; + ffreg_t vbrwq_base; /* VBR Wait Queue Base */ + ffreg_t abrwq_base; /* ABR Wait Queue Base */ + ffreg_t ubrwq_base; /* UBR Wait Queue Base */ + ffreg_t vct_base; /* Main VC Table Base */ + ffreg_t vcte_base; /* Extended Main VC Table Base */ + u_int filler2a[0x2C - 0x2A]; + ffreg_t cbr_tab_beg; /* CBR Table Begin */ + ffreg_t cbr_tab_end; /* CBR Table End */ + ffreg_t cbr_pointer; /* CBR Pointer */ + u_int filler2f[0x30 - 0x2F]; + ffreg_t prq_st_adr; /* Packet Ready Queue Start Address */ + ffreg_t prq_ed_adr; /* Packet Ready Queue End Address */ + ffreg_t prq_rd_ptr; /* Packet Ready Queue read pointer */ + ffreg_t prq_wr_ptr; /* Packet Ready Queue write pointer */ + ffreg_t tcq_st_adr; /* Transmit Complete Queue Start Address*/ + ffreg_t tcq_ed_adr; /* Transmit Complete Queue End Address */ + ffreg_t tcq_rd_ptr; /* Transmit Complete Queue read pointer */ + ffreg_t tcq_wr_ptr; /* Transmit Complete Queue write pointer*/ + u_int filler38[0x40 - 0x38]; + ffreg_t queue_base; /* Base address for PRQ and TCQ */ + ffreg_t desc_base; /* Base address of descriptor table */ + u_int filler42[0x45 - 0x42]; + ffreg_t mode_reg_0; /* Mode register 0 */ + ffreg_t mode_reg_1; /* Mode register 1 */ + ffreg_t intr_status_reg;/* Interrupt Status register */ + ffreg_t mask_reg; /* Mask Register */ + ffreg_t cell_ctr_high1; /* Total cell transfer count (high) */ + ffreg_t cell_ctr_lo1; /* Total cell transfer count (low) */ + ffreg_t state_reg; /* Status register */ + u_int filler4c[0x58 - 0x4c]; + ffreg_t curr_desc_num; /* Contains the current descriptor num */ + ffreg_t next_desc; /* Next descriptor */ + ffreg_t next_vc; /* Next VC */ + u_int filler5b[0x5d - 0x5b]; + ffreg_t present_slot_cnt;/* Present slot count */ + u_int filler5e[0x6a - 0x5e]; + ffreg_t new_desc_num; /* New descriptor number */ + ffreg_t new_vc; /* New VC */ + ffreg_t sched_tbl_ptr; /* Schedule table pointer */ + ffreg_t vbrwq_wptr; /* VBR wait queue write pointer */ + ffreg_t vbrwq_rptr; /* VBR wait queue read pointer */ + ffreg_t abrwq_wptr; /* ABR wait queue write pointer */ + ffreg_t abrwq_rptr; /* ABR wait queue read pointer */ + ffreg_t ubrwq_wptr; /* UBR wait queue write pointer */ + ffreg_t ubrwq_rptr; /* UBR wait queue read pointer */ + ffreg_t cbr_vc; /* CBR VC */ + ffreg_t vbr_sb_vc; /* VBR SB VC */ + ffreg_t abr_sb_vc; /* ABR SB VC */ + ffreg_t ubr_sb_vc; /* UBR SB VC */ + ffreg_t vbr_next_link; /* VBR next link */ + ffreg_t abr_next_link; /* ABR next link */ + ffreg_t ubr_next_link; /* UBR next link */ + u_int filler7a[0x7c-0x7a]; + ffreg_t out_rate_head; /* Out of rate head */ + u_int filler7d[0xca-0x7d]; /* pad out to full address space */ + ffreg_t cell_ctr_high1_nc;/* Total cell transfer count (high) */ + ffreg_t cell_ctr_lo1_nc;/* Total cell transfer count (low) */ + u_int fillercc[0x100-0xcc]; /* pad out to full address space */ } ffredn_t; typedef struct _rfredn_t { diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 26a06b801b5..b850cecb147 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -294,7 +294,7 @@ int bus_for_each_dev(struct bus_type *bus, struct device *start, struct device *dev; int error = 0; - if (!bus) + if (!bus || !bus->p) return -EINVAL; klist_iter_init_node(&bus->p->klist_devices, &i, @@ -328,7 +328,7 @@ struct device *bus_find_device(struct bus_type *bus, struct klist_iter i; struct device *dev; - if (!bus) + if (!bus || !bus->p) return NULL; klist_iter_init_node(&bus->p->klist_devices, &i, diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 1b1cbb571d3..97fc774e6bc 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -160,6 +160,8 @@ static int deferred_probe_initcall(void) driver_deferred_probe_enable = true; driver_deferred_probe_trigger(); + /* Sort as many dependencies as possible before exiting initcalls */ + flush_workqueue(deferred_wq); return 0; } late_initcall(deferred_probe_initcall); diff --git a/drivers/base/regmap/regcache-rbtree.c b/drivers/base/regmap/regcache-rbtree.c index 92b779ee002..17aa318a1ae 100644 --- a/drivers/base/regmap/regcache-rbtree.c +++ b/drivers/base/regmap/regcache-rbtree.c @@ -392,7 +392,7 @@ static int regcache_rbtree_sync(struct regmap *map, unsigned int min, base = 0; if (max < rbnode->base_reg + rbnode->blklen) - end = rbnode->base_reg + rbnode->blklen - max; + end = max - rbnode->base_reg + 1; else end = rbnode->blklen; diff --git a/drivers/block/aoe/aoecmd.c b/drivers/block/aoe/aoecmd.c index 887f68f6d79..db30542b122 100644 --- a/drivers/block/aoe/aoecmd.c +++ b/drivers/block/aoe/aoecmd.c @@ -30,8 +30,9 @@ new_skb(ulong len) { struct sk_buff *skb; - skb = alloc_skb(len, GFP_ATOMIC); + skb = alloc_skb(len + MAX_HEADER, GFP_ATOMIC); if (skb) { + skb_reserve(skb, MAX_HEADER); skb_reset_mac_header(skb); skb_reset_network_header(skb); skb->protocol = __constant_htons(ETH_P_AOE); diff --git a/drivers/block/brd.c b/drivers/block/brd.c index 531ceb31d0f..4e8213aa02f 100644 --- a/drivers/block/brd.c +++ b/drivers/block/brd.c @@ -117,13 +117,13 @@ static struct page *brd_insert_page(struct brd_device *brd, sector_t sector) spin_lock(&brd->brd_lock); idx = sector >> PAGE_SECTORS_SHIFT; + page->index = idx; if (radix_tree_insert(&brd->brd_pages, idx, page)) { __free_page(page); page = radix_tree_lookup(&brd->brd_pages, idx); BUG_ON(!page); BUG_ON(page->index != idx); - } else - page->index = idx; + } spin_unlock(&brd->brd_lock); radix_tree_preload_end(); diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index b0f553b26d0..d3446f628d5 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -161,8 +161,6 @@ static irqreturn_t do_cciss_msix_intr(int irq, void *dev_id); static int cciss_open(struct block_device *bdev, fmode_t mode); static int cciss_unlocked_open(struct block_device *bdev, fmode_t mode); static int cciss_release(struct gendisk *disk, fmode_t mode); -static int do_ioctl(struct block_device *bdev, fmode_t mode, - unsigned int cmd, unsigned long arg); static int cciss_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg); static int cciss_getgeo(struct block_device *bdev, struct hd_geometry *geo); @@ -229,7 +227,7 @@ static const struct block_device_operations cciss_fops = { .owner = THIS_MODULE, .open = cciss_unlocked_open, .release = cciss_release, - .ioctl = do_ioctl, + .ioctl = cciss_ioctl, .getgeo = cciss_getgeo, #ifdef CONFIG_COMPAT .compat_ioctl = cciss_compat_ioctl, @@ -1140,16 +1138,6 @@ static int cciss_release(struct gendisk *disk, fmode_t mode) return 0; } -static int do_ioctl(struct block_device *bdev, fmode_t mode, - unsigned cmd, unsigned long arg) -{ - int ret; - mutex_lock(&cciss_mutex); - ret = cciss_ioctl(bdev, mode, cmd, arg); - mutex_unlock(&cciss_mutex); - return ret; -} - #ifdef CONFIG_COMPAT static int cciss_ioctl32_passthru(struct block_device *bdev, fmode_t mode, @@ -1176,7 +1164,7 @@ static int cciss_compat_ioctl(struct block_device *bdev, fmode_t mode, case CCISS_REGNEWD: case CCISS_RESCANDISK: case CCISS_GETLUNINFO: - return do_ioctl(bdev, mode, cmd, arg); + return cciss_ioctl(bdev, mode, cmd, arg); case CCISS_PASSTHRU32: return cciss_ioctl32_passthru(bdev, mode, cmd, arg); @@ -1216,7 +1204,7 @@ static int cciss_ioctl32_passthru(struct block_device *bdev, fmode_t mode, if (err) return -EFAULT; - err = do_ioctl(bdev, mode, CCISS_PASSTHRU, (unsigned long)p); + err = cciss_ioctl(bdev, mode, CCISS_PASSTHRU, (unsigned long)p); if (err) return err; err |= @@ -1258,7 +1246,7 @@ static int cciss_ioctl32_big_passthru(struct block_device *bdev, fmode_t mode, if (err) return -EFAULT; - err = do_ioctl(bdev, mode, CCISS_BIG_PASSTHRU, (unsigned long)p); + err = cciss_ioctl(bdev, mode, CCISS_BIG_PASSTHRU, (unsigned long)p); if (err) return err; err |= @@ -1308,11 +1296,14 @@ static int cciss_getpciinfo(ctlr_info_t *h, void __user *argp) static int cciss_getintinfo(ctlr_info_t *h, void __user *argp) { cciss_coalint_struct intinfo; + unsigned long flags; if (!argp) return -EINVAL; + spin_lock_irqsave(&h->lock, flags); intinfo.delay = readl(&h->cfgtable->HostWrite.CoalIntDelay); intinfo.count = readl(&h->cfgtable->HostWrite.CoalIntCount); + spin_unlock_irqrestore(&h->lock, flags); if (copy_to_user (argp, &intinfo, sizeof(cciss_coalint_struct))) return -EFAULT; @@ -1353,12 +1344,15 @@ static int cciss_setintinfo(ctlr_info_t *h, void __user *argp) static int cciss_getnodename(ctlr_info_t *h, void __user *argp) { NodeName_type NodeName; + unsigned long flags; int i; if (!argp) return -EINVAL; + spin_lock_irqsave(&h->lock, flags); for (i = 0; i < 16; i++) NodeName[i] = readb(&h->cfgtable->ServerName[i]); + spin_unlock_irqrestore(&h->lock, flags); if (copy_to_user(argp, NodeName, sizeof(NodeName_type))) return -EFAULT; return 0; @@ -1395,10 +1389,13 @@ static int cciss_setnodename(ctlr_info_t *h, void __user *argp) static int cciss_getheartbeat(ctlr_info_t *h, void __user *argp) { Heartbeat_type heartbeat; + unsigned long flags; if (!argp) return -EINVAL; + spin_lock_irqsave(&h->lock, flags); heartbeat = readl(&h->cfgtable->HeartBeat); + spin_unlock_irqrestore(&h->lock, flags); if (copy_to_user(argp, &heartbeat, sizeof(Heartbeat_type))) return -EFAULT; return 0; @@ -1407,10 +1404,13 @@ static int cciss_getheartbeat(ctlr_info_t *h, void __user *argp) static int cciss_getbustypes(ctlr_info_t *h, void __user *argp) { BusTypes_type BusTypes; + unsigned long flags; if (!argp) return -EINVAL; + spin_lock_irqsave(&h->lock, flags); BusTypes = readl(&h->cfgtable->BusTypes); + spin_unlock_irqrestore(&h->lock, flags); if (copy_to_user(argp, &BusTypes, sizeof(BusTypes_type))) return -EFAULT; return 0; diff --git a/drivers/block/drbd/drbd_receiver.c b/drivers/block/drbd/drbd_receiver.c index 43beaca5317..13cbdd32895 100644 --- a/drivers/block/drbd/drbd_receiver.c +++ b/drivers/block/drbd/drbd_receiver.c @@ -2225,7 +2225,6 @@ static int drbd_asb_recover_1p(struct drbd_conf *mdev) __must_hold(local) if (hg == -1 && mdev->state.role == R_PRIMARY) { enum drbd_state_rv rv2; - drbd_set_role(mdev, R_SECONDARY, 0); /* drbd_change_state() does not sleep while in SS_IN_TRANSIENT_STATE, * we might be here in C_WF_REPORT_PARAMS which is transient. * we do not need to wait for the after state change work either. */ diff --git a/drivers/block/loop.c b/drivers/block/loop.c index bbca966f8f6..179b5b408cb 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -908,6 +908,11 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode, lo->lo_flags |= LO_FLAGS_PARTSCAN; if (lo->lo_flags & LO_FLAGS_PARTSCAN) ioctl_by_bdev(bdev, BLKRRPART, 0); + + /* Grab the block_device to prevent its destruction after we + * put /dev/loopXX inode. Later in loop_clr_fd() we bdput(bdev). + */ + bdgrab(bdev); return 0; out_clr: @@ -1004,8 +1009,10 @@ static int loop_clr_fd(struct loop_device *lo) memset(lo->lo_encrypt_key, 0, LO_KEY_SIZE); memset(lo->lo_crypt_name, 0, LO_NAME_SIZE); memset(lo->lo_file_name, 0, LO_NAME_SIZE); - if (bdev) + if (bdev) { + bdput(bdev); invalidate_bdev(bdev); + } set_capacity(lo->lo_disk, 0); loop_sysfs_exit(lo); if (bdev) { @@ -1263,11 +1270,9 @@ static int loop_set_capacity(struct loop_device *lo, struct block_device *bdev) /* the width of sector_t may be narrow for bit-shift */ sz = sec; sz <<= 9; - mutex_lock(&bdev->bd_mutex); bd_set_size(bdev, sz); /* let user-space know about the new size */ kobject_uevent(&disk_to_dev(bdev->bd_disk)->kobj, KOBJ_CHANGE); - mutex_unlock(&bdev->bd_mutex); out: return err; @@ -1837,11 +1842,15 @@ static int __init loop_init(void) max_part = (1UL << part_shift) - 1; } - if ((1UL << part_shift) > DISK_MAX_PARTS) - return -EINVAL; + if ((1UL << part_shift) > DISK_MAX_PARTS) { + err = -EINVAL; + goto misc_out; + } - if (max_loop > 1UL << (MINORBITS - part_shift)) - return -EINVAL; + if (max_loop > 1UL << (MINORBITS - part_shift)) { + err = -EINVAL; + goto misc_out; + } /* * If max_loop is specified, create that many devices upfront. @@ -1859,8 +1868,10 @@ static int __init loop_init(void) range = 1UL << MINORBITS; } - if (register_blkdev(LOOP_MAJOR, "loop")) - return -EIO; + if (register_blkdev(LOOP_MAJOR, "loop")) { + err = -EIO; + goto misc_out; + } blk_register_region(MKDEV(LOOP_MAJOR, 0), range, THIS_MODULE, loop_probe, NULL, NULL); @@ -1873,6 +1884,10 @@ static int __init loop_init(void) printk(KERN_INFO "loop: module loaded\n"); return 0; + +misc_out: + misc_deregister(&loop_misc); + return err; } static int loop_exit_cb(int id, void *ptr, void *data) diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 3c4c225d198..386d40e3cf4 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -666,7 +666,8 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd, mutex_unlock(&nbd->tx_lock); - thread = kthread_create(nbd_thread, nbd, nbd->disk->disk_name); + thread = kthread_create(nbd_thread, nbd, "%s", + nbd->disk->disk_name); if (IS_ERR(thread)) { mutex_lock(&nbd->tx_lock); return PTR_ERR(thread); diff --git a/drivers/block/sunvdc.c b/drivers/block/sunvdc.c index 9dcf76a10bb..31dd45177a7 100644 --- a/drivers/block/sunvdc.c +++ b/drivers/block/sunvdc.c @@ -461,7 +461,7 @@ static int generic_request(struct vdc_port *port, u8 op, void *buf, int len) int op_len, err; void *req_buf; - if (!(((u64)1 << ((u64)op - 1)) & port->operations)) + if (!(((u64)1 << (u64)op) & port->operations)) return -EOPNOTSUPP; switch (op) { diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index c6decb901e5..4ed7bf9b4fd 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c @@ -399,7 +399,18 @@ static int dispatch_discard_io(struct xen_blkif *blkif, int status = BLKIF_RSP_OKAY; struct block_device *bdev = blkif->vbd.bdev; unsigned long secure; + struct phys_req preq; + + preq.sector_number = req->u.discard.sector_number; + preq.nr_sects = req->u.discard.nr_sectors; + err = xen_vbd_translate(&preq, blkif, WRITE); + if (err) { + pr_warn(DRV_PFX "access denied: DISCARD [%llu->%llu] on dev=%04x\n", + preq.sector_number, + preq.sector_number + preq.nr_sects, blkif->vbd.pdevice); + goto fail_response; + } blkif->st_ds_req++; xen_blkif_get(blkif); @@ -410,7 +421,7 @@ static int dispatch_discard_io(struct xen_blkif *blkif, err = blkdev_issue_discard(bdev, req->u.discard.sector_number, req->u.discard.nr_sectors, GFP_KERNEL, secure); - +fail_response: if (err == -EOPNOTSUPP) { pr_debug(DRV_PFX "discard op failed, not supported\n"); status = BLKIF_RSP_EOPNOTSUPP; @@ -422,6 +433,16 @@ static int dispatch_discard_io(struct xen_blkif *blkif, return err; } +static int dispatch_other_io(struct xen_blkif *blkif, + struct blkif_request *req, + struct pending_req *pending_req) +{ + free_req(pending_req); + make_response(blkif, req->u.other.id, req->operation, + BLKIF_RSP_EOPNOTSUPP); + return -EIO; +} + static void xen_blk_drain_io(struct xen_blkif *blkif) { atomic_set(&blkif->drain, 1); @@ -543,17 +564,30 @@ __do_block_io_op(struct xen_blkif *blkif) /* Apply all sanity checks to /private copy/ of request. */ barrier(); - if (unlikely(req.operation == BLKIF_OP_DISCARD)) { + + switch (req.operation) { + case BLKIF_OP_READ: + case BLKIF_OP_WRITE: + case BLKIF_OP_WRITE_BARRIER: + case BLKIF_OP_FLUSH_DISKCACHE: + if (dispatch_rw_block_io(blkif, &req, pending_req)) + goto done; + break; + case BLKIF_OP_DISCARD: free_req(pending_req); if (dispatch_discard_io(blkif, &req)) - break; - } else if (dispatch_rw_block_io(blkif, &req, pending_req)) + goto done; + break; + default: + if (dispatch_other_io(blkif, &req, pending_req)) + goto done; break; + } /* Yield point for this unbounded loop. */ cond_resched(); } - +done: return more_to_do; } @@ -720,13 +754,7 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif, bio->bi_end_io = end_block_io_op; } - /* - * We set it one so that the last submit_bio does not have to call - * atomic_inc. - */ atomic_set(&pending_req->pendcnt, nbio); - - /* Get a reference count for the disk queue and start sending I/O */ blk_start_plug(&plug); for (i = 0; i < nbio; i++) @@ -754,6 +782,7 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif, fail_put_bio: for (i = 0; i < nbio; i++) bio_put(biolist[i]); + atomic_set(&pending_req->pendcnt, 1); __end_block_io_op(pending_req, -EINVAL); msleep(1); /* back off a bit */ return -EIO; diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h index 9ad3b5ec1dc..fc2a486d4a8 100644 --- a/drivers/block/xen-blkback/common.h +++ b/drivers/block/xen-blkback/common.h @@ -76,11 +76,18 @@ struct blkif_x86_32_request_discard { uint64_t nr_sectors; } __attribute__((__packed__)); +struct blkif_x86_32_request_other { + uint8_t _pad1; + blkif_vdev_t _pad2; + uint64_t id; /* private guest value, echoed in resp */ +} __attribute__((__packed__)); + struct blkif_x86_32_request { uint8_t operation; /* BLKIF_OP_??? */ union { struct blkif_x86_32_request_rw rw; struct blkif_x86_32_request_discard discard; + struct blkif_x86_32_request_other other; } u; } __attribute__((__packed__)); @@ -112,11 +119,19 @@ struct blkif_x86_64_request_discard { uint64_t nr_sectors; } __attribute__((__packed__)); +struct blkif_x86_64_request_other { + uint8_t _pad1; + blkif_vdev_t _pad2; + uint32_t _pad3; /* offsetof(blkif_..,u.discard.id)==8 */ + uint64_t id; /* private guest value, echoed in resp */ +} __attribute__((__packed__)); + struct blkif_x86_64_request { uint8_t operation; /* BLKIF_OP_??? */ union { struct blkif_x86_64_request_rw rw; struct blkif_x86_64_request_discard discard; + struct blkif_x86_64_request_other other; } u; } __attribute__((__packed__)); @@ -262,6 +277,11 @@ static inline void blkif_get_x86_32_req(struct blkif_request *dst, dst->u.discard.nr_sectors = src->u.discard.nr_sectors; break; default: + /* + * Don't know how to translate this op. Only get the + * ID so failure can be reported to the frontend. + */ + dst->u.other.id = src->u.other.id; break; } } @@ -293,6 +313,11 @@ static inline void blkif_get_x86_64_req(struct blkif_request *dst, dst->u.discard.nr_sectors = src->u.discard.nr_sectors; break; default: + /* + * Don't know how to translate this op. Only get the + * ID so failure can be reported to the frontend. + */ + dst->u.other.id = src->u.other.id; break; } } diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c index 4f66171c668..a155254f133 100644 --- a/drivers/block/xen-blkback/xenbus.c +++ b/drivers/block/xen-blkback/xenbus.c @@ -367,6 +367,7 @@ static int xen_blkbk_remove(struct xenbus_device *dev) be->blkif = NULL; } + kfree(be->mode); kfree(be); dev_set_drvdata(&dev->dev, NULL); return 0; @@ -502,6 +503,7 @@ static void backend_changed(struct xenbus_watch *watch, = container_of(watch, struct backend_info, backend_watch); struct xenbus_device *dev = be->dev; int cdrom = 0; + unsigned long handle; char *device_type; DPRINTK(""); @@ -521,10 +523,10 @@ static void backend_changed(struct xenbus_watch *watch, return; } - if ((be->major || be->minor) && - ((be->major != major) || (be->minor != minor))) { - pr_warn(DRV_PFX "changing physical device (from %x:%x to %x:%x) not supported.\n", - be->major, be->minor, major, minor); + if (be->major | be->minor) { + if (be->major != major || be->minor != minor) + pr_warn(DRV_PFX "changing physical device (from %x:%x to %x:%x) not supported.\n", + be->major, be->minor, major, minor); return; } @@ -542,36 +544,33 @@ static void backend_changed(struct xenbus_watch *watch, kfree(device_type); } - if (be->major == 0 && be->minor == 0) { - /* Front end dir is a number, which is used as the handle. */ - - char *p = strrchr(dev->otherend, '/') + 1; - long handle; - err = strict_strtoul(p, 0, &handle); - if (err) - return; + /* Front end dir is a number, which is used as the handle. */ + err = strict_strtoul(strrchr(dev->otherend, '/') + 1, 0, &handle); + if (err) + return; - be->major = major; - be->minor = minor; + be->major = major; + be->minor = minor; - err = xen_vbd_create(be->blkif, handle, major, minor, - (NULL == strchr(be->mode, 'w')), cdrom); - if (err) { - be->major = 0; - be->minor = 0; - xenbus_dev_fatal(dev, err, "creating vbd structure"); - return; - } + err = xen_vbd_create(be->blkif, handle, major, minor, + !strchr(be->mode, 'w'), cdrom); + if (err) + xenbus_dev_fatal(dev, err, "creating vbd structure"); + else { err = xenvbd_sysfs_addif(dev); if (err) { xen_vbd_free(&be->blkif->vbd); - be->major = 0; - be->minor = 0; xenbus_dev_fatal(dev, err, "creating sysfs entries"); - return; } + } + if (err) { + kfree(be->mode); + be->mode = NULL; + be->major = 0; + be->minor = 0; + } else { /* We're potentially connected now */ xen_update_blkif_status(be->blkif); } diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index 98ee436e0f0..72c773dc912 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c @@ -71,7 +71,14 @@ static struct usb_device_id ath3k_table[] = { { USB_DEVICE(0x03F0, 0x311D) }, /* Atheros AR3012 with sflash firmware*/ + { USB_DEVICE(0x0CF3, 0x0036) }, { USB_DEVICE(0x0CF3, 0x3004) }, + { USB_DEVICE(0x0CF3, 0x311D) }, + { USB_DEVICE(0x0CF3, 0x817a) }, + { USB_DEVICE(0x13d3, 0x3375) }, + { USB_DEVICE(0x04CA, 0x3005) }, + { USB_DEVICE(0x13d3, 0x3362) }, + { USB_DEVICE(0x0CF3, 0xE004) }, /* Atheros AR5BBU12 with sflash firmware */ { USB_DEVICE(0x0489, 0xE02C) }, @@ -87,7 +94,14 @@ MODULE_DEVICE_TABLE(usb, ath3k_table); static struct usb_device_id ath3k_blist_tbl[] = { /* Atheros AR3012 with sflash firmware*/ + { USB_DEVICE(0x0CF3, 0x0036), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0CF3, 0x817a), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, { } /* Terminating entry */ }; diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 75f711fe062..09828eabd27 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -136,7 +136,14 @@ static struct usb_device_id blacklist_table[] = { { USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE }, /* Atheros 3012 with sflash firmware */ + { USB_DEVICE(0x0cf3, 0x0036), .driver_info = BTUSB_ATH3012 }, { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0cf3, 0x817a), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 }, + { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, /* Atheros AR5BBU12 with sflash firmware */ { USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE }, diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index d620b449574..8a3aff724d9 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c @@ -2882,7 +2882,7 @@ static noinline int mmc_ioctl_cdrom_read_data(struct cdrom_device_info *cdi, if (lba < 0) return -EINVAL; - cgc->buffer = kmalloc(blocksize, GFP_KERNEL); + cgc->buffer = kzalloc(blocksize, GFP_KERNEL); if (cgc->buffer == NULL) return -ENOMEM; diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index dfd7876f127..0ff5c2ea140 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c @@ -373,26 +373,14 @@ static int hpet_mmap(struct file *file, struct vm_area_struct *vma) struct hpet_dev *devp; unsigned long addr; - if (((vma->vm_end - vma->vm_start) != PAGE_SIZE) || vma->vm_pgoff) - return -EINVAL; - devp = file->private_data; addr = devp->hd_hpets->hp_hpet_phys; if (addr & (PAGE_SIZE - 1)) return -ENOSYS; - vma->vm_flags |= VM_IO; vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); - - if (io_remap_pfn_range(vma, vma->vm_start, addr >> PAGE_SHIFT, - PAGE_SIZE, vma->vm_page_prot)) { - printk(KERN_ERR "%s: io_remap_pfn_range failed\n", - __func__); - return -EAGAIN; - } - - return 0; + return vm_iomap_memory(vma, addr, PAGE_SIZE); #else return -ENOSYS; #endif diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c index 1bafb40ec8a..69ae5972713 100644 --- a/drivers/char/hw_random/core.c +++ b/drivers/char/hw_random/core.c @@ -40,6 +40,7 @@ #include #include #include +#include #include @@ -52,8 +53,12 @@ static struct hwrng *current_rng; static LIST_HEAD(rng_list); static DEFINE_MUTEX(rng_mutex); static int data_avail; -static u8 rng_buffer[SMP_CACHE_BYTES < 32 ? 32 : SMP_CACHE_BYTES] - __cacheline_aligned; +static u8 *rng_buffer; + +static size_t rng_buffer_size(void) +{ + return SMP_CACHE_BYTES < 32 ? 32 : SMP_CACHE_BYTES; +} static inline int hwrng_init(struct hwrng *rng) { @@ -116,7 +121,7 @@ static ssize_t rng_dev_read(struct file *filp, char __user *buf, if (!data_avail) { bytes_read = rng_get_data(current_rng, rng_buffer, - sizeof(rng_buffer), + rng_buffer_size(), !(filp->f_flags & O_NONBLOCK)); if (bytes_read < 0) { err = bytes_read; @@ -307,6 +312,14 @@ int hwrng_register(struct hwrng *rng) mutex_lock(&rng_mutex); + /* kmalloc makes this safe for virt_to_page() in virtio_rng.c */ + err = -ENOMEM; + if (!rng_buffer) { + rng_buffer = kmalloc(rng_buffer_size(), GFP_KERNEL); + if (!rng_buffer) + goto out_unlock; + } + /* Must not register two RNGs with the same name. */ err = -EEXIST; list_for_each_entry(tmp, &rng_list, list) { diff --git a/drivers/char/hw_random/virtio-rng.c b/drivers/char/hw_random/virtio-rng.c index 723725bbb96..171380bd225 100644 --- a/drivers/char/hw_random/virtio-rng.c +++ b/drivers/char/hw_random/virtio-rng.c @@ -89,14 +89,22 @@ static int virtrng_probe(struct virtio_device *vdev) { int err; + if (vq) { + /* We only support one device for now */ + return -EBUSY; + } /* We expect a single virtqueue. */ vq = virtio_find_single_vq(vdev, random_recv_done, "input"); - if (IS_ERR(vq)) - return PTR_ERR(vq); + if (IS_ERR(vq)) { + err = PTR_ERR(vq); + vq = NULL; + return err; + } err = hwrng_register(&virtio_hwrng); if (err) { vdev->config->del_vqs(vdev); + vq = NULL; return err; } @@ -108,6 +116,7 @@ static void __devexit virtrng_remove(struct virtio_device *vdev) vdev->config->reset(vdev); hwrng_unregister(&virtio_hwrng); vdev->config->del_vqs(vdev); + vq = NULL; } static struct virtio_device_id id_table[] = { diff --git a/drivers/char/ipmi/ipmi_bt_sm.c b/drivers/char/ipmi/ipmi_bt_sm.c index cdd4c09fda9..a22a7a50274 100644 --- a/drivers/char/ipmi/ipmi_bt_sm.c +++ b/drivers/char/ipmi/ipmi_bt_sm.c @@ -95,9 +95,9 @@ struct si_sm_data { enum bt_states state; unsigned char seq; /* BT sequence number */ struct si_sm_io *io; - unsigned char write_data[IPMI_MAX_MSG_LENGTH]; + unsigned char write_data[IPMI_MAX_MSG_LENGTH + 2]; /* +2 for memcpy */ int write_count; - unsigned char read_data[IPMI_MAX_MSG_LENGTH]; + unsigned char read_data[IPMI_MAX_MSG_LENGTH + 2]; /* +2 for memcpy */ int read_count; int truncated; long timeout; /* microseconds countdown */ diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c index 9eb360ff8ca..d5a5f020810 100644 --- a/drivers/char/ipmi/ipmi_devintf.c +++ b/drivers/char/ipmi/ipmi_devintf.c @@ -837,13 +837,25 @@ static long compat_ipmi_ioctl(struct file *filep, unsigned int cmd, return ipmi_ioctl(filep, cmd, arg); } } + +static long unlocked_compat_ipmi_ioctl(struct file *filep, unsigned int cmd, + unsigned long arg) +{ + int ret; + + mutex_lock(&ipmi_mutex); + ret = compat_ipmi_ioctl(filep, cmd, arg); + mutex_unlock(&ipmi_mutex); + + return ret; +} #endif static const struct file_operations ipmi_fops = { .owner = THIS_MODULE, .unlocked_ioctl = ipmi_unlocked_ioctl, #ifdef CONFIG_COMPAT - .compat_ioctl = compat_ipmi_ioctl, + .compat_ioctl = unlocked_compat_ipmi_ioctl, #endif .open = ipmi_open, .release = ipmi_release, diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index cdf2f5451c7..0cd2d50f9a5 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -256,9 +256,12 @@ static struct port *find_port_by_devt_in_portdev(struct ports_device *portdev, unsigned long flags; spin_lock_irqsave(&portdev->ports_lock, flags); - list_for_each_entry(port, &portdev->ports, list) - if (port->cdev->dev == dev) + list_for_each_entry(port, &portdev->ports, list) { + if (port->cdev->dev == dev) { + kref_get(&port->kref); goto out; + } + } port = NULL; out: spin_unlock_irqrestore(&portdev->ports_lock, flags); @@ -630,6 +633,10 @@ static ssize_t port_fops_read(struct file *filp, char __user *ubuf, port = filp->private_data; + /* Port is hot-unplugged. */ + if (!port->guest_connected) + return -ENODEV; + if (!port_has_data(port)) { /* * If nothing's connected on the host just return 0 in @@ -646,7 +653,7 @@ static ssize_t port_fops_read(struct file *filp, char __user *ubuf, if (ret < 0) return ret; } - /* Port got hot-unplugged. */ + /* Port got hot-unplugged while we were waiting above. */ if (!port->guest_connected) return -ENODEV; /* @@ -789,14 +796,14 @@ static int port_fops_open(struct inode *inode, struct file *filp) struct port *port; int ret; + /* We get the port with a kref here */ port = find_port_by_devt(cdev->dev); + if (!port) { + /* Port was unplugged before we could proceed */ + return -ENXIO; + } filp->private_data = port; - /* Prevent against a port getting hot-unplugged at the same time */ - spin_lock_irq(&port->portdev->ports_lock); - kref_get(&port->kref); - spin_unlock_irq(&port->portdev->ports_lock); - /* * Don't allow opening of console port devices -- that's done * via /dev/hvc @@ -1254,14 +1261,6 @@ static void remove_port(struct kref *kref) port = container_of(kref, struct port, kref); - sysfs_remove_group(&port->dev->kobj, &port_attribute_group); - device_destroy(pdrvdata.class, port->dev->devt); - cdev_del(port->cdev); - - kfree(port->name); - - debugfs_remove(port->debugfs_file); - kfree(port); } @@ -1291,12 +1290,14 @@ static void unplug_port(struct port *port) spin_unlock_irq(&port->portdev->ports_lock); if (port->guest_connected) { + /* Let the app know the port is going down. */ + send_sigio_to_port(port); + + /* Do this after sigio is actually sent */ port->guest_connected = false; port->host_connected = false; - wake_up_interruptible(&port->waitqueue); - /* Let the app know the port is going down. */ - send_sigio_to_port(port); + wake_up_interruptible(&port->waitqueue); } if (is_console_port(port)) { @@ -1315,6 +1316,14 @@ static void unplug_port(struct port *port) */ port->portdev = NULL; + sysfs_remove_group(&port->dev->kobj, &port_attribute_group); + device_destroy(pdrvdata.class, port->dev->devt); + cdev_del(port->cdev); + + kfree(port->name); + + debugfs_remove(port->debugfs_file); + /* * Locks around here are not necessary - a port can't be * opened after we removed the port struct from ports_list @@ -1808,7 +1817,8 @@ static void virtcons_remove(struct virtio_device *vdev) /* Disable interrupts for vqs */ vdev->config->reset(vdev); /* Finish up work that's lined up */ - cancel_work_sync(&portdev->control_work); + if (use_multiport(portdev)) + cancel_work_sync(&portdev->control_work); list_for_each_entry_safe(port, port2, &portdev->ports, list) unplug_port(port); diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 7f1ea568b44..4c63665a902 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -1453,6 +1453,7 @@ int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb) /* XXX the notifier code should handle this better */ if (!cn->notifier_head.head) { srcu_cleanup_notifier_head(&cn->notifier_head); + list_del(&cn->node); kfree(cn); } diff --git a/drivers/cpufreq/longhaul.c b/drivers/cpufreq/longhaul.c index 07de3922a13..7c89651ec24 100644 --- a/drivers/cpufreq/longhaul.c +++ b/drivers/cpufreq/longhaul.c @@ -77,7 +77,7 @@ static unsigned int longhaul_index; static int scale_voltage; static int disable_acpi_c3; static int revid_errata; - +static int enable; /* Clock ratios multiplied by 10 */ static int mults[32]; @@ -965,6 +965,10 @@ static int __init longhaul_init(void) if (!x86_match_cpu(longhaul_id)) return -ENODEV; + if (!enable) { + printk(KERN_ERR PFX "Option \"enable\" not set. Aborting.\n"); + return -ENODEV; + } #ifdef CONFIG_SMP if (num_online_cpus() > 1) { printk(KERN_ERR PFX "More than 1 CPU detected, " @@ -1021,6 +1025,10 @@ MODULE_PARM_DESC(scale_voltage, "Scale voltage of processor"); * such. */ module_param(revid_errata, int, 0644); MODULE_PARM_DESC(revid_errata, "Ignore CPU Revision ID"); +/* By default driver is disabled to prevent incompatible + * system freeze. */ +module_param(enable, int, 0644); +MODULE_PARM_DESC(enable, "Enable driver"); MODULE_AUTHOR("Dave Jones "); MODULE_DESCRIPTION("Longhaul driver for VIA Cyrix processors."); diff --git a/drivers/dca/dca-core.c b/drivers/dca/dca-core.c index bc6f5faa1e9..819dfda8823 100644 --- a/drivers/dca/dca-core.c +++ b/drivers/dca/dca-core.c @@ -420,6 +420,11 @@ void unregister_dca_provider(struct dca_provider *dca, struct device *dev) raw_spin_lock_irqsave(&dca_lock, flags); + if (list_empty(&dca_domains)) { + raw_spin_unlock_irqrestore(&dca_lock, flags); + return; + } + list_del(&dca->node); pci_rc = dca_pci_rc_from_dev(dev); diff --git a/drivers/dma/pch_dma.c b/drivers/dma/pch_dma.c index 65c0495a6d4..d05669bf7a2 100644 --- a/drivers/dma/pch_dma.c +++ b/drivers/dma/pch_dma.c @@ -476,7 +476,7 @@ static struct pch_dma_desc *pdc_desc_get(struct pch_dma_chan *pd_chan) dev_dbg(chan2dev(&pd_chan->chan), "scanned %d descriptors\n", i); if (!ret) { - ret = pdc_alloc_desc(&pd_chan->chan, GFP_NOIO); + ret = pdc_alloc_desc(&pd_chan->chan, GFP_ATOMIC); if (ret) { spin_lock(&pd_chan->lock); pd_chan->descs_allocated++; diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c index 758122f33a9..15a6af82e94 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c @@ -2469,10 +2469,10 @@ static void pl330_free_chan_resources(struct dma_chan *chan) struct dma_pl330_chan *pch = to_pchan(chan); unsigned long flags; - spin_lock_irqsave(&pch->lock, flags); - tasklet_kill(&pch->task); + spin_lock_irqsave(&pch->lock, flags); + pl330_release_channel(pch->pl330_chid); pch->pl330_chid = NULL; diff --git a/drivers/eisa/pci_eisa.c b/drivers/eisa/pci_eisa.c index cdae207028a..6c3fca97d34 100644 --- a/drivers/eisa/pci_eisa.c +++ b/drivers/eisa/pci_eisa.c @@ -19,10 +19,10 @@ /* There is only *one* pci_eisa device per machine, right ? */ static struct eisa_root_device pci_eisa_root; -static int __init pci_eisa_init(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int __init pci_eisa_init(struct pci_dev *pdev) { - int rc; + int rc, i; + struct resource *res, *bus_res = NULL; if ((rc = pci_enable_device (pdev))) { printk (KERN_ERR "pci_eisa : Could not enable device %s\n", @@ -30,9 +30,30 @@ static int __init pci_eisa_init(struct pci_dev *pdev, return rc; } + /* + * The Intel 82375 PCI-EISA bridge is a subtractive-decode PCI + * device, so the resources available on EISA are the same as those + * available on the 82375 bus. This works the same as a PCI-PCI + * bridge in subtractive-decode mode (see pci_read_bridge_bases()). + * We assume other PCI-EISA bridges are similar. + * + * eisa_root_register() can only deal with a single io port resource, + * so we use the first valid io port resource. + */ + pci_bus_for_each_resource(pdev->bus, res, i) + if (res && (res->flags & IORESOURCE_IO)) { + bus_res = res; + break; + } + + if (!bus_res) { + dev_err(&pdev->dev, "No resources available\n"); + return -1; + } + pci_eisa_root.dev = &pdev->dev; - pci_eisa_root.res = pdev->bus->resource[0]; - pci_eisa_root.bus_base_addr = pdev->bus->resource[0]->start; + pci_eisa_root.res = bus_res; + pci_eisa_root.bus_base_addr = bus_res->start; pci_eisa_root.slots = EISA_MAX_SLOTS; pci_eisa_root.dma_mask = pdev->dma_mask; dev_set_drvdata(pci_eisa_root.dev, &pci_eisa_root); @@ -45,22 +66,26 @@ static int __init pci_eisa_init(struct pci_dev *pdev, return 0; } -static struct pci_device_id pci_eisa_pci_tbl[] = { - { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, - PCI_CLASS_BRIDGE_EISA << 8, 0xffff00, 0 }, - { 0, } -}; +/* + * We have to call pci_eisa_init_early() before pnpacpi_init()/isapnp_init(). + * Otherwise pnp resource will get enabled early and could prevent eisa + * to be initialized. + * Also need to make sure pci_eisa_init_early() is called after + * x86/pci_subsys_init(). + * So need to use subsys_initcall_sync with it. + */ +static int __init pci_eisa_init_early(void) +{ + struct pci_dev *dev = NULL; + int ret; -static struct pci_driver __refdata pci_eisa_driver = { - .name = "pci_eisa", - .id_table = pci_eisa_pci_tbl, - .probe = pci_eisa_init, -}; + for_each_pci_dev(dev) + if ((dev->class >> 8) == PCI_CLASS_BRIDGE_EISA) { + ret = pci_eisa_init(dev); + if (ret) + return ret; + } -static int __init pci_eisa_init_module (void) -{ - return pci_register_driver (&pci_eisa_driver); + return 0; } - -device_initcall(pci_eisa_init_module); -MODULE_DEVICE_TABLE(pci, pci_eisa_pci_tbl); +subsys_initcall_sync(pci_eisa_init_early); diff --git a/drivers/firewire/core-cdev.c b/drivers/firewire/core-cdev.c index b8e4809cae0..b558810b2da 100644 --- a/drivers/firewire/core-cdev.c +++ b/drivers/firewire/core-cdev.c @@ -53,6 +53,7 @@ #define FW_CDEV_KERNEL_VERSION 5 #define FW_CDEV_VERSION_EVENT_REQUEST2 4 #define FW_CDEV_VERSION_ALLOCATE_REGION_END 4 +#define FW_CDEV_VERSION_AUTO_FLUSH_ISO_OVERFLOW 5 struct client { u32 version; @@ -998,6 +999,8 @@ static int ioctl_create_iso_context(struct client *client, union ioctl_arg *arg) a->channel, a->speed, a->header_size, cb, client); if (IS_ERR(context)) return PTR_ERR(context); + if (client->version < FW_CDEV_VERSION_AUTO_FLUSH_ISO_OVERFLOW) + context->drop_overflow_headers = true; /* We only support one context at this time. */ spin_lock_irq(&client->lock); diff --git a/drivers/firewire/core-device.c b/drivers/firewire/core-device.c index 68109e9bb04..04ebeaf8cff 100644 --- a/drivers/firewire/core-device.c +++ b/drivers/firewire/core-device.c @@ -999,6 +999,10 @@ static void fw_device_init(struct work_struct *work) ret = idr_pre_get(&fw_device_idr, GFP_KERNEL) ? idr_get_new(&fw_device_idr, device, &minor) : -ENOMEM; + if (minor >= 1 << MINORBITS) { + idr_remove(&fw_device_idr, minor); + minor = -ENOSPC; + } up_write(&fw_device_rwsem); if (ret < 0) diff --git a/drivers/firewire/ohci.c b/drivers/firewire/ohci.c index 2b5460075a9..c1de4c3a3fe 100644 --- a/drivers/firewire/ohci.c +++ b/drivers/firewire/ohci.c @@ -2694,8 +2694,11 @@ static void copy_iso_headers(struct iso_context *ctx, const u32 *dma_hdr) { u32 *ctx_hdr; - if (ctx->header_length + ctx->base.header_size > PAGE_SIZE) + if (ctx->header_length + ctx->base.header_size > PAGE_SIZE) { + if (ctx->base.drop_overflow_headers) + return; flush_iso_completions(ctx); + } ctx_hdr = ctx->header + ctx->header_length; ctx->last_timestamp = (u16)le32_to_cpu((__force __le32)dma_hdr[0]); @@ -2855,8 +2858,11 @@ static int handle_it_packet(struct context *context, sync_it_packet_for_cpu(context, d); - if (ctx->header_length + 4 > PAGE_SIZE) + if (ctx->header_length + 4 > PAGE_SIZE) { + if (ctx->base.drop_overflow_headers) + return 1; flush_iso_completions(ctx); + } ctx_hdr = ctx->header + ctx->header_length; ctx->last_timestamp = le16_to_cpu(last->res_count); diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index fd3ae6290d7..4cd392dbf11 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c @@ -442,7 +442,6 @@ static int __init dmi_present(const char __iomem *p) static int __init smbios_present(const char __iomem *p) { u8 buf[32]; - int offset = 0; memcpy_fromio(buf, p, 32); if ((buf[5] < 32) && dmi_checksum(buf, buf[5])) { @@ -461,9 +460,9 @@ static int __init smbios_present(const char __iomem *p) dmi_ver = 0x0206; break; } - offset = 16; + return memcmp(p + 16, "_DMI_", 5) || dmi_present(p + 16); } - return dmi_present(buf + offset); + return 1; } void __init dmi_scan_machine(void) @@ -471,7 +470,7 @@ void __init dmi_scan_machine(void) char __iomem *p, *q; int rc; - if (efi_enabled) { + if (efi_enabled(EFI_CONFIG_TABLES)) { if (efi.smbios == EFI_INVALID_TABLE_ADDR) goto error; diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c index d10c9873dd9..2cbb675a66c 100644 --- a/drivers/firmware/efivars.c +++ b/drivers/firmware/efivars.c @@ -122,6 +122,9 @@ struct efivar_attribute { ssize_t (*store)(struct efivar_entry *entry, const char *buf, size_t count); }; +static struct efivars __efivars; +static struct efivar_operations ops; + #define PSTORE_EFI_ATTRIBUTES \ (EFI_VARIABLE_NON_VOLATILE | \ EFI_VARIABLE_BOOTSERVICE_ACCESS | \ @@ -942,6 +945,53 @@ static ssize_t efivar_delete(struct file *filp, struct kobject *kobj, return count; } +static bool variable_is_present(efi_char16_t *variable_name, efi_guid_t *vendor) +{ + struct efivar_entry *entry, *n; + struct efivars *efivars = &__efivars; + unsigned long strsize1, strsize2; + bool found = false; + + strsize1 = utf16_strsize(variable_name, 1024); + list_for_each_entry_safe(entry, n, &efivars->list, list) { + strsize2 = utf16_strsize(entry->var.VariableName, 1024); + if (strsize1 == strsize2 && + !memcmp(variable_name, &(entry->var.VariableName), + strsize2) && + !efi_guidcmp(entry->var.VendorGuid, + *vendor)) { + found = true; + break; + } + } + return found; +} + +/* + * Returns the size of variable_name, in bytes, including the + * terminating NULL character, or variable_name_size if no NULL + * character is found among the first variable_name_size bytes. + */ +static unsigned long var_name_strnsize(efi_char16_t *variable_name, + unsigned long variable_name_size) +{ + unsigned long len; + efi_char16_t c; + + /* + * The variable name is, by definition, a NULL-terminated + * string, so make absolutely sure that variable_name_size is + * the value we expect it to be. If not, return the real size. + */ + for (len = 2; len <= variable_name_size; len += sizeof(c)) { + c = variable_name[(len / sizeof(c)) - 1]; + if (!c) + break; + } + + return min(len, variable_name_size); +} + /* * Let's not leave out systab information that snuck into * the efivars driver @@ -1129,6 +1179,28 @@ void unregister_efivars(struct efivars *efivars) } EXPORT_SYMBOL_GPL(unregister_efivars); +/* + * Print a warning when duplicate EFI variables are encountered and + * disable the sysfs workqueue since the firmware is buggy. + */ +static void dup_variable_bug(efi_char16_t *s16, efi_guid_t *vendor_guid, + unsigned long len16) +{ + size_t i, len8 = len16 / sizeof(efi_char16_t); + char *s8; + + s8 = kzalloc(len8, GFP_KERNEL); + if (!s8) + return; + + for (i = 0; i < len8; i++) + s8[i] = s16[i]; + + printk(KERN_WARNING "efivars: duplicate variable: %s-%pUl\n", + s8, vendor_guid); + kfree(s8); +} + int register_efivars(struct efivars *efivars, const struct efivar_operations *ops, struct kobject *parent_kobj) @@ -1169,6 +1241,24 @@ int register_efivars(struct efivars *efivars, &vendor_guid); switch (status) { case EFI_SUCCESS: + variable_name_size = var_name_strnsize(variable_name, + variable_name_size); + + /* + * Some firmware implementations return the + * same variable name on multiple calls to + * get_next_variable(). Terminate the loop + * immediately as there is no guarantee that + * we'll ever see a different variable name, + * and may end up looping here forever. + */ + if (variable_is_present(variable_name, &vendor_guid)) { + dup_variable_bug(variable_name, &vendor_guid, + variable_name_size); + status = EFI_NOT_FOUND; + break; + } + efivar_create_sysfs_entry(efivars, variable_name_size, variable_name, @@ -1205,9 +1295,6 @@ int register_efivars(struct efivars *efivars, } EXPORT_SYMBOL_GPL(register_efivars); -static struct efivars __efivars; -static struct efivar_operations ops; - /* * For now we register the efi subsystem with the firmware subsystem * and the vars subsystem with the efi subsystem. In the future, it @@ -1224,7 +1311,7 @@ efivars_init(void) printk(KERN_INFO "EFI Variables Facility v%s %s\n", EFIVARS_VERSION, EFIVARS_DATE); - if (!efi_enabled) + if (!efi_enabled(EFI_RUNTIME_SERVICES)) return 0; /* For now we'll register the efi directory at /sys/firmware/efi */ @@ -1262,7 +1349,7 @@ efivars_init(void) static void __exit efivars_exit(void) { - if (efi_enabled) { + if (efi_enabled(EFI_RUNTIME_SERVICES)) { unregister_efivars(&__efivars); kobject_put(efi_kobj); } diff --git a/drivers/firmware/iscsi_ibft_find.c b/drivers/firmware/iscsi_ibft_find.c index 4da4eb9ae92..2224f1dc074 100644 --- a/drivers/firmware/iscsi_ibft_find.c +++ b/drivers/firmware/iscsi_ibft_find.c @@ -99,7 +99,7 @@ unsigned long __init find_ibft_region(unsigned long *sizep) /* iBFT 1.03 section 1.4.3.1 mandates that UEFI machines will * only use ACPI for this */ - if (!efi_enabled) + if (!efi_enabled(EFI_BOOT)) find_ibft_in_mem(); if (ibft_addr) { diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 4fd363f1656..c61e6722216 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -2023,7 +2023,7 @@ uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth) switch (bpp) { case 8: - fmt = DRM_FORMAT_RGB332; + fmt = DRM_FORMAT_C8; break; case 16: if (depth == 15) @@ -3409,6 +3409,7 @@ void drm_fb_get_bpp_depth(uint32_t format, unsigned int *depth, int *bpp) { switch (format) { + case DRM_FORMAT_C8: case DRM_FORMAT_RGB332: case DRM_FORMAT_BGR233: *depth = 8; diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 9d9835a4fee..8b77fd31798 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -836,7 +836,7 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev, unsigned vblank = (pt->vactive_vblank_hi & 0xf) << 8 | pt->vblank_lo; unsigned hsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0xc0) << 2 | pt->hsync_offset_lo; unsigned hsync_pulse_width = (pt->hsync_vsync_offset_pulse_width_hi & 0x30) << 4 | pt->hsync_pulse_width_lo; - unsigned vsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0xc) >> 2 | pt->vsync_offset_pulse_width_lo >> 4; + unsigned vsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0xc) << 2 | pt->vsync_offset_pulse_width_lo >> 4; unsigned vsync_pulse_width = (pt->hsync_vsync_offset_pulse_width_hi & 0x3) << 4 | (pt->vsync_offset_pulse_width_lo & 0xf); /* ignore tiny modes */ @@ -917,6 +917,7 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev, } mode->type = DRM_MODE_TYPE_DRIVER; + mode->vrefresh = drm_mode_vrefresh(mode); drm_mode_set_name(mode); return mode; @@ -1769,7 +1770,8 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid) num_modes += add_cvt_modes(connector, edid); num_modes += add_standard_modes(connector, edid); num_modes += add_established_modes(connector, edid); - num_modes += add_inferred_modes(connector, edid); + if (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF) + num_modes += add_inferred_modes(connector, edid); num_modes += add_cea_modes(connector, edid); if (quirks & (EDID_QUIRK_PREFER_LARGE_60 | EDID_QUIRK_PREFER_LARGE_75)) diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index c869436e238..dc33ba57e33 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -981,7 +981,7 @@ EXPORT_SYMBOL(drm_vblank_off); */ void drm_vblank_pre_modeset(struct drm_device *dev, int crtc) { - /* vblank is not initialized (IRQ not installed ?) */ + /* vblank is not initialized (IRQ not installed ?), or has been freed */ if (!dev->num_crtcs) return; /* @@ -1003,6 +1003,10 @@ void drm_vblank_post_modeset(struct drm_device *dev, int crtc) { unsigned long irqflags; + /* vblank is not initialized (IRQ not installed ?), or has been freed */ + if (!dev->num_crtcs) + return; + if (dev->vblank_inmodeset[crtc]) { spin_lock_irqsave(&dev->vbl_lock, irqflags); dev->vblank_disable_allowed = 1; diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index 961fb54f426..7f88de66c1f 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c @@ -680,33 +680,35 @@ void drm_mm_debug_table(struct drm_mm *mm, const char *prefix) EXPORT_SYMBOL(drm_mm_debug_table); #if defined(CONFIG_DEBUG_FS) -int drm_mm_dump_table(struct seq_file *m, struct drm_mm *mm) +static unsigned long drm_mm_dump_hole(struct seq_file *m, struct drm_mm_node *entry) { - struct drm_mm_node *entry; - unsigned long total_used = 0, total_free = 0, total = 0; unsigned long hole_start, hole_end, hole_size; - hole_start = drm_mm_hole_node_start(&mm->head_node); - hole_end = drm_mm_hole_node_end(&mm->head_node); - hole_size = hole_end - hole_start; - if (hole_size) + if (entry->hole_follows) { + hole_start = drm_mm_hole_node_start(entry); + hole_end = drm_mm_hole_node_end(entry); + hole_size = hole_end - hole_start; seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: free\n", hole_start, hole_end, hole_size); - total_free += hole_size; + return hole_size; + } + + return 0; +} + +int drm_mm_dump_table(struct seq_file *m, struct drm_mm *mm) +{ + struct drm_mm_node *entry; + unsigned long total_used = 0, total_free = 0, total = 0; + + total_free += drm_mm_dump_hole(m, &mm->head_node); drm_mm_for_each_node(entry, mm) { seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: used\n", entry->start, entry->start + entry->size, entry->size); total_used += entry->size; - if (entry->hole_follows) { - hole_start = drm_mm_hole_node_start(entry); - hole_end = drm_mm_hole_node_end(entry); - hole_size = hole_end - hole_start; - seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: free\n", - hole_start, hole_end, hole_size); - total_free += hole_size; - } + total_free += drm_mm_dump_hole(m, entry); } total = total_free + total_used; diff --git a/drivers/gpu/drm/drm_usb.c b/drivers/gpu/drm/drm_usb.c index 37c9a523dd1..767782a96c3 100644 --- a/drivers/gpu/drm/drm_usb.c +++ b/drivers/gpu/drm/drm_usb.c @@ -18,7 +18,7 @@ int drm_get_usb_dev(struct usb_interface *interface, usbdev = interface_to_usbdev(interface); dev->usbdev = usbdev; - dev->dev = &usbdev->dev; + dev->dev = &interface->dev; mutex_lock(&drm_global_mutex); diff --git a/drivers/gpu/drm/gma500/cdv_intel_display.c b/drivers/gpu/drm/gma500/cdv_intel_display.c index be8455919b3..1ee297bb757 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_display.c +++ b/drivers/gpu/drm/gma500/cdv_intel_display.c @@ -1439,6 +1439,19 @@ static void cdv_intel_crtc_destroy(struct drm_crtc *crtc) kfree(psb_intel_crtc); } +static void cdv_intel_crtc_disable(struct drm_crtc *crtc) +{ + struct gtt_range *gt; + struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; + + crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF); + + if (crtc->fb) { + gt = to_psb_fb(crtc->fb)->gtt; + psb_gtt_unpin(gt); + } +} + const struct drm_crtc_helper_funcs cdv_intel_helper_funcs = { .dpms = cdv_intel_crtc_dpms, .mode_fixup = cdv_intel_crtc_mode_fixup, @@ -1446,6 +1459,7 @@ const struct drm_crtc_helper_funcs cdv_intel_helper_funcs = { .mode_set_base = cdv_intel_pipe_set_base, .prepare = cdv_intel_crtc_prepare, .commit = cdv_intel_crtc_commit, + .disable = cdv_intel_crtc_disable, }; const struct drm_crtc_funcs cdv_intel_crtc_funcs = { diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c index 8ea202f1ba5..fa74a865496 100644 --- a/drivers/gpu/drm/gma500/framebuffer.c +++ b/drivers/gpu/drm/gma500/framebuffer.c @@ -782,8 +782,8 @@ void psb_modeset_init(struct drm_device *dev) for (i = 0; i < dev_priv->num_pipe; i++) psb_intel_crtc_init(dev, i, mode_dev); - dev->mode_config.max_width = 2048; - dev->mode_config.max_height = 2048; + dev->mode_config.max_width = 4096; + dev->mode_config.max_height = 4096; psb_setup_outputs(dev); } diff --git a/drivers/gpu/drm/gma500/psb_intel_display.c b/drivers/gpu/drm/gma500/psb_intel_display.c index 2616558457c..454a9d87abc 100644 --- a/drivers/gpu/drm/gma500/psb_intel_display.c +++ b/drivers/gpu/drm/gma500/psb_intel_display.c @@ -1262,6 +1262,19 @@ void psb_intel_crtc_destroy(struct drm_crtc *crtc) kfree(psb_intel_crtc); } +static void psb_intel_crtc_disable(struct drm_crtc *crtc) +{ + struct gtt_range *gt; + struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; + + crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF); + + if (crtc->fb) { + gt = to_psb_fb(crtc->fb)->gtt; + psb_gtt_unpin(gt); + } +} + const struct drm_crtc_helper_funcs psb_intel_helper_funcs = { .dpms = psb_intel_crtc_dpms, .mode_fixup = psb_intel_crtc_mode_fixup, @@ -1269,6 +1282,7 @@ const struct drm_crtc_helper_funcs psb_intel_helper_funcs = { .mode_set_base = psb_intel_pipe_set_base, .prepare = psb_intel_crtc_prepare, .commit = psb_intel_crtc_commit, + .disable = psb_intel_crtc_disable, }; const struct drm_crtc_funcs psb_intel_crtc_funcs = { diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index e6162a1681f..34791fb7aa7 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -122,7 +122,7 @@ static const char *cache_level_str(int type) static void describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) { - seq_printf(m, "%p: %s%s %8zdKiB %04x %04x %d %d%s%s%s", + seq_printf(m, "%pK: %s%s %8zdKiB %04x %04x %d %d%s%s%s", &obj->base, get_pin_flag(obj), get_tiling_flag(obj), diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 45c5cf83fae..232119ac266 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -296,6 +296,7 @@ enum intel_pch { #define QUIRK_PIPEA_FORCE (1<<0) #define QUIRK_LVDS_SSC_DISABLE (1<<1) +#define QUIRK_NO_PCH_PWM_ENABLE (1<<2) struct intel_fbdev; struct intel_fbc_work; diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index a230a93935b..eb339456c11 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1186,6 +1186,11 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) case 0: case -ERESTARTSYS: case -EINTR: + case -EBUSY: + /* + * EBUSY is ok: this just means that another thread + * already did the job. + */ return VM_FAULT_NOPAGE; case -ENOMEM: return VM_FAULT_OOM; diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index d4417e3cc3d..e97ed611d8c 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -957,15 +957,20 @@ validate_exec_list(struct drm_i915_gem_exec_object2 *exec, int count) { int i; + int relocs_total = 0; + int relocs_max = INT_MAX / sizeof(struct drm_i915_gem_relocation_entry); for (i = 0; i < count; i++) { char __user *ptr = (char __user *)(uintptr_t)exec[i].relocs_ptr; int length; /* limited by fault_in_pages_readable() */ - /* First check for malicious input causing overflow */ - if (exec[i].relocation_count > - INT_MAX / sizeof(struct drm_i915_gem_relocation_entry)) + /* First check for malicious input causing overflow in + * the worst case where we need to allocate the entire + * relocation tree as a single array. + */ + if (exec[i].relocation_count > relocs_max - relocs_total) return -EINVAL; + relocs_total += exec[i].relocation_count; length = exec[i].relocation_count * sizeof(struct drm_i915_gem_relocation_entry); diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index a135c61f411..99a7855a69e 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -72,7 +72,7 @@ int i915_gem_init_aliasing_ppgtt(struct drm_device *dev) /* ppgtt PDEs reside in the global gtt pagetable, which has 512*1024 * entries. For aliasing ppgtt support we just steal them at the end for * now. */ - first_pd_entry_in_global_pt = 512*1024 - I915_PPGTT_PD_ENTRIES; + first_pd_entry_in_global_pt = dev_priv->mm.gtt->gtt_total_entries - I915_PPGTT_PD_ENTRIES; ppgtt = kzalloc(sizeof(*ppgtt), GFP_KERNEL); if (!ppgtt) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index dde62bf3b1c..d0319325e39 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -502,6 +502,8 @@ will not assert AGPBUSY# and will only be delivered when out of C3. */ #define INSTPM_FORCE_ORDERING (1<<7) /* GEN6+ */ +#define INSTPM_TLB_INVALIDATE (1<<9) +#define INSTPM_SYNC_FLUSH (1<<5) #define ACTHD 0x020c8 #define FW_BLC 0x020d8 #define FW_BLC2 0x020dc diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 3c9b9c57040..0e359225a19 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -142,8 +142,8 @@ static const intel_limit_t intel_limits_i9xx_sdvo = { .vco = { .min = 1400000, .max = 2800000 }, .n = { .min = 1, .max = 6 }, .m = { .min = 70, .max = 120 }, - .m1 = { .min = 10, .max = 22 }, - .m2 = { .min = 5, .max = 9 }, + .m1 = { .min = 8, .max = 18 }, + .m2 = { .min = 3, .max = 7 }, .p = { .min = 5, .max = 80 }, .p1 = { .min = 1, .max = 8 }, .p2 = { .dot_limit = 200000, @@ -3303,6 +3303,7 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc) struct intel_crtc *intel_crtc = to_intel_crtc(crtc); int pipe = intel_crtc->pipe; int plane = intel_crtc->plane; + u32 pctl; if (!intel_crtc->active) return; @@ -3318,6 +3319,13 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc) intel_disable_plane(dev_priv, plane, pipe); intel_disable_pipe(dev_priv, pipe); + + /* Disable pannel fitter if it is on this pipe. */ + pctl = I915_READ(PFIT_CONTROL); + if ((pctl & PFIT_ENABLE) && + ((pctl & PFIT_PIPE_MASK) >> PFIT_PIPE_SHIFT) == pipe) + I915_WRITE(PFIT_CONTROL, 0); + intel_disable_pll(dev_priv, pipe); intel_crtc->active = false; @@ -7559,8 +7567,8 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, { struct drm_device *dev = crtc->dev; struct drm_i915_private *dev_priv = dev->dev_private; - struct intel_framebuffer *intel_fb; - struct drm_i915_gem_object *obj; + struct drm_framebuffer *old_fb = crtc->fb; + struct drm_i915_gem_object *obj = to_intel_framebuffer(fb)->obj; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); struct intel_unpin_work *work; unsigned long flags; @@ -7572,8 +7580,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, work->event = event; work->dev = crtc->dev; - intel_fb = to_intel_framebuffer(crtc->fb); - work->old_fb_obj = intel_fb->obj; + work->old_fb_obj = to_intel_framebuffer(old_fb)->obj; INIT_WORK(&work->work, intel_unpin_work_fn); ret = drm_vblank_get(dev, intel_crtc->pipe); @@ -7593,9 +7600,6 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, intel_crtc->unpin_work = work; spin_unlock_irqrestore(&dev->event_lock, flags); - intel_fb = to_intel_framebuffer(fb); - obj = intel_fb->obj; - mutex_lock(&dev->struct_mutex); /* Reference the objects for the scheduled work. */ @@ -7626,6 +7630,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, cleanup_pending: atomic_sub(1 << intel_crtc->plane, &work->old_fb_obj->pending_flip); + crtc->fb = old_fb; drm_gem_object_unreference(&work->old_fb_obj->base); drm_gem_object_unreference(&obj->base); mutex_unlock(&dev->struct_mutex); @@ -8356,7 +8361,7 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv) I915_WRITE(GEN6_RC_SLEEP, 0); I915_WRITE(GEN6_RC1e_THRESHOLD, 1000); I915_WRITE(GEN6_RC6_THRESHOLD, 50000); - I915_WRITE(GEN6_RC6p_THRESHOLD, 100000); + I915_WRITE(GEN6_RC6p_THRESHOLD, 150000); I915_WRITE(GEN6_RC6pp_THRESHOLD, 64000); /* unused */ rc6_mode = intel_enable_rc6(dev_priv->dev); @@ -9155,6 +9160,17 @@ static void quirk_ssc_force_disable(struct drm_device *dev) dev_priv->quirks |= QUIRK_LVDS_SSC_DISABLE; } +/* + * Some machines (Dell XPS13) suffer broken backlight controls if + * BLM_PCH_PWM_ENABLE is set. + */ +static void quirk_no_pcm_pwm_enable(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + dev_priv->quirks |= QUIRK_NO_PCH_PWM_ENABLE; + DRM_INFO("applying no-PCH_PWM_ENABLE quirk\n"); +} + struct intel_quirk { int device; int subsystem_vendor; @@ -9187,6 +9203,11 @@ struct intel_quirk intel_quirks[] = { /* Sony Vaio Y cannot use SSC on LVDS */ { 0x0046, 0x104d, 0x9076, quirk_ssc_force_disable }, + + /* Dell XPS13 HD Sandy Bridge */ + { 0x0116, 0x1028, 0x052e, quirk_no_pcm_pwm_enable }, + /* Dell XPS13 HD and XPS13 FHD Ivy Bridge */ + { 0x0166, 0x1028, 0x058b, quirk_no_pcm_pwm_enable }, }; static void intel_init_quirks(struct drm_device *dev) diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c index 020a7d7f744..69bea56e516 100644 --- a/drivers/gpu/drm/i915/intel_dvo.c +++ b/drivers/gpu/drm/i915/intel_dvo.c @@ -370,6 +370,7 @@ void intel_dvo_init(struct drm_device *dev) const struct intel_dvo_device *dvo = &intel_dvo_devices[i]; struct i2c_adapter *i2c; int gpio; + bool dvoinit; /* Allow the I2C driver info to specify the GPIO to be used in * special cases, but otherwise default to what's defined @@ -389,7 +390,17 @@ void intel_dvo_init(struct drm_device *dev) i2c = &dev_priv->gmbus[gpio].adapter; intel_dvo->dev = *dvo; - if (!dvo->dev_ops->init(&intel_dvo->dev, i2c)) + + /* GMBUS NAK handling seems to be unstable, hence let the + * transmitter detection run in bit banging mode for now. + */ + intel_gmbus_force_bit(i2c, true); + + dvoinit = dvo->dev_ops->init(&intel_dvo->dev, i2c); + + intel_gmbus_force_bit(i2c, false); + + if (!dvoinit) continue; intel_encoder->type = INTEL_OUTPUT_DVO; diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index a8b28c493a8..dc7c5f6415a 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -408,13 +408,7 @@ static void intel_lvds_prepare(struct drm_encoder *encoder) { struct intel_lvds *intel_lvds = to_intel_lvds(encoder); - /* - * Prior to Ironlake, we must disable the pipe if we want to adjust - * the panel fitter. However at all other times we can just reset - * the registers regardless. - */ - if (!HAS_PCH_SPLIT(encoder->dev) && intel_lvds->pfit_dirty) - intel_lvds_disable(intel_lvds); + intel_lvds_disable(intel_lvds); } static void intel_lvds_commit(struct drm_encoder *encoder) @@ -747,10 +741,10 @@ static const struct dmi_system_id intel_no_lvds[] = { }, { .callback = intel_no_lvds_dmi_callback, - .ident = "Hewlett-Packard HP t5740e Thin Client", + .ident = "Hewlett-Packard HP t5740", .matches = { DMI_MATCH(DMI_BOARD_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_PRODUCT_NAME, "HP t5740e Thin Client"), + DMI_MATCH(DMI_PRODUCT_NAME, " t5740"), }, }, { @@ -793,6 +787,14 @@ static const struct dmi_system_id intel_no_lvds[] = { DMI_MATCH(DMI_PRODUCT_NAME, "X7SPA-H"), }, }, + { + .callback = intel_no_lvds_dmi_callback, + .ident = "Fujitsu Esprimo Q900", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"), + DMI_MATCH(DMI_PRODUCT_NAME, "ESPRIMO Q900"), + }, + }, { } /* terminating entry */ }; @@ -1089,7 +1091,8 @@ bool intel_lvds_init(struct drm_device *dev) goto failed; out: - if (HAS_PCH_SPLIT(dev)) { + if (HAS_PCH_SPLIT(dev) && + !(dev_priv->quirks & QUIRK_NO_PCH_PWM_ENABLE)) { u32 pwm; pipe = (I915_READ(PCH_LVDS) & LVDS_PIPEB_SELECT) ? 1 : 0; diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c index 289140bc83c..cffb0071f87 100644 --- a/drivers/gpu/drm/i915/intel_opregion.c +++ b/drivers/gpu/drm/i915/intel_opregion.c @@ -419,6 +419,25 @@ static void intel_didl_outputs(struct drm_device *dev) goto end; } +static void intel_setup_cadls(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_opregion *opregion = &dev_priv->opregion; + int i = 0; + u32 disp_id; + + /* Initialize the CADL field by duplicating the DIDL values. + * Technically, this is not always correct as display outputs may exist, + * but not active. This initialization is necessary for some Clevo + * laptops that check this field before processing the brightness and + * display switching hotkeys. Just like DIDL, CADL is NULL-terminated if + * there are less than eight devices. */ + do { + disp_id = ioread32(&opregion->acpi->didl[i]); + iowrite32(disp_id, &opregion->acpi->cadl[i]); + } while (++i < 8 && disp_id != 0); +} + void intel_opregion_init(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -428,8 +447,10 @@ void intel_opregion_init(struct drm_device *dev) return; if (opregion->acpi) { - if (drm_core_check_feature(dev, DRIVER_MODESET)) + if (drm_core_check_feature(dev, DRIVER_MODESET)) { intel_didl_outputs(dev); + intel_setup_cadls(dev); + } /* Notify BIOS we are ready to handle ACPI video ext notifs. * Right now, all the events are handled by the ACPI video module. diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index c17325ce379..99a9df8e7a1 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -767,6 +767,18 @@ void intel_ring_setup_status_page(struct intel_ring_buffer *ring) I915_WRITE(mmio, (u32)ring->status_page.gfx_addr); POSTING_READ(mmio); + + /* Flush the TLB for this page */ + if (INTEL_INFO(dev)->gen >= 6) { + u32 reg = RING_INSTPM(ring->mmio_base); + I915_WRITE(reg, + _MASKED_BIT_ENABLE(INSTPM_TLB_INVALIDATE | + INSTPM_SYNC_FLUSH)); + if (wait_for((I915_READ(reg) & INSTPM_SYNC_FLUSH) == 0, + 1000)) + DRM_ERROR("%s: wait for SyncFlush to complete for TLB invalidation timed out\n", + ring->name); + } } static int diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 1b6b1570f4c..c0ba260cc22 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -1581,11 +1581,14 @@ static void intel_sdvo_get_lvds_modes(struct drm_connector *connector) * Assume that the preferred modes are * arranged in priority order. */ - intel_ddc_get_modes(connector, intel_sdvo->i2c); - if (list_empty(&connector->probed_modes) == false) - goto end; + intel_ddc_get_modes(connector, &intel_sdvo->ddc); - /* Fetch modes from VBT */ + /* + * Fetch modes from VBT. For SDVO prefer the VBT mode since some + * SDVO->LVDS transcoders can't cope with the EDID mode. Since + * drm_mode_probed_add adds the mode at the head of the list we add it + * last. + */ if (dev_priv->sdvo_lvds_vbt_mode != NULL) { newmode = drm_mode_duplicate(connector->dev, dev_priv->sdvo_lvds_vbt_mode); @@ -1597,7 +1600,6 @@ static void intel_sdvo_get_lvds_modes(struct drm_connector *connector) } } -end: list_for_each_entry(newmode, &connector->probed_modes, head) { if (newmode->type & DRM_MODE_TYPE_PREFERRED) { intel_sdvo->sdvo_lvds_fixed_mode = diff --git a/drivers/gpu/drm/radeon/atom.c b/drivers/gpu/drm/radeon/atom.c index 5ce9bf51a8d..daa1e346828 100644 --- a/drivers/gpu/drm/radeon/atom.c +++ b/drivers/gpu/drm/radeon/atom.c @@ -1222,12 +1222,17 @@ int atom_execute_table(struct atom_context *ctx, int index, uint32_t * params) int r; mutex_lock(&ctx->mutex); + /* reset data block */ + ctx->data_block = 0; /* reset reg block */ ctx->reg_block = 0; /* reset fb window */ ctx->fb_base = 0; /* reset io mode */ ctx->io_mode = ATOM_IO_MM; + /* reset divmul */ + ctx->divmul[0] = 0; + ctx->divmul[1] = 0; r = atom_execute_table_locked(ctx, index, params); mutex_unlock(&ctx->mutex); return r; @@ -1389,10 +1394,10 @@ int atom_allocate_fb_scratch(struct atom_context *ctx) firmware_usage = (struct _ATOM_VRAM_USAGE_BY_FIRMWARE *)(ctx->bios + data_offset); DRM_DEBUG("atom firmware requested %08x %dkb\n", - firmware_usage->asFirmwareVramReserveInfo[0].ulStartAddrUsedByFirmware, - firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb); + le32_to_cpu(firmware_usage->asFirmwareVramReserveInfo[0].ulStartAddrUsedByFirmware), + le16_to_cpu(firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb)); - usage_bytes = firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb * 1024; + usage_bytes = le16_to_cpu(firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb) * 1024; } ctx->scratch_size_bytes = 0; if (usage_bytes == 0) diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 15594a30ebd..ebbfbd20173 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -258,8 +258,6 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode) radeon_crtc->enabled = true; /* adjust pm to dpms changes BEFORE enabling crtcs */ radeon_pm_compute_clocks(rdev); - if (ASIC_IS_DCE6(rdev) && !radeon_crtc->in_mode_set) - atombios_powergate_crtc(crtc, ATOM_DISABLE); atombios_enable_crtc(crtc, ATOM_ENABLE); if (ASIC_IS_DCE3(rdev) && !ASIC_IS_DCE6(rdev)) atombios_enable_crtc_memreq(crtc, ATOM_ENABLE); @@ -277,8 +275,6 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode) atombios_enable_crtc_memreq(crtc, ATOM_DISABLE); atombios_enable_crtc(crtc, ATOM_DISABLE); radeon_crtc->enabled = false; - if (ASIC_IS_DCE6(rdev) && !radeon_crtc->in_mode_set) - atombios_powergate_crtc(crtc, ATOM_ENABLE); /* adjust pm to dpms changes AFTER disabling crtcs */ radeon_pm_compute_clocks(rdev); break; @@ -1670,6 +1666,8 @@ static void atombios_crtc_disable(struct drm_crtc *crtc) int i; atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); + if (ASIC_IS_DCE6(rdev)) + atombios_powergate_crtc(crtc, ATOM_ENABLE); for (i = 0; i < rdev->num_crtc; i++) { if (rdev->mode_info.crtcs[i] && diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c index 886b41f44a5..505f27e2c08 100644 --- a/drivers/gpu/drm/radeon/atombios_dp.c +++ b/drivers/gpu/drm/radeon/atombios_dp.c @@ -45,6 +45,41 @@ static char *pre_emph_names[] = { }; /***** radeon AUX functions *****/ + +/* Atom needs data in little endian format + * so swap as appropriate when copying data to + * or from atom. Note that atom operates on + * dw units. + */ +static void radeon_copy_swap(u8 *dst, u8 *src, u8 num_bytes, bool to_le) +{ +#ifdef __BIG_ENDIAN + u8 src_tmp[20], dst_tmp[20]; /* used for byteswapping */ + u32 *dst32, *src32; + int i; + + memcpy(src_tmp, src, num_bytes); + src32 = (u32 *)src_tmp; + dst32 = (u32 *)dst_tmp; + if (to_le) { + for (i = 0; i < ((num_bytes + 3) / 4); i++) + dst32[i] = cpu_to_le32(src32[i]); + memcpy(dst, dst_tmp, num_bytes); + } else { + u8 dws = num_bytes & ~3; + for (i = 0; i < ((num_bytes + 3) / 4); i++) + dst32[i] = le32_to_cpu(src32[i]); + memcpy(dst, dst_tmp, dws); + if (num_bytes % 4) { + for (i = 0; i < (num_bytes % 4); i++) + dst[dws+i] = dst_tmp[dws+i]; + } + } +#else + memcpy(dst, src, num_bytes); +#endif +} + union aux_channel_transaction { PROCESS_AUX_CHANNEL_TRANSACTION_PS_ALLOCATION v1; PROCESS_AUX_CHANNEL_TRANSACTION_PARAMETERS_V2 v2; @@ -66,10 +101,10 @@ static int radeon_process_aux_ch(struct radeon_i2c_chan *chan, base = (unsigned char *)(rdev->mode_info.atom_context->scratch + 1); - memcpy(base, send, send_bytes); + radeon_copy_swap(base, send, send_bytes, true); - args.v1.lpAuxRequest = 0 + 4; - args.v1.lpDataOut = 16 + 4; + args.v1.lpAuxRequest = cpu_to_le16((u16)(0 + 4)); + args.v1.lpDataOut = cpu_to_le16((u16)(16 + 4)); args.v1.ucDataOutLen = 0; args.v1.ucChannelID = chan->rec.i2c_id; args.v1.ucDelay = delay / 10; @@ -103,7 +138,7 @@ static int radeon_process_aux_ch(struct radeon_i2c_chan *chan, recv_bytes = recv_size; if (recv && recv_size) - memcpy(recv, base + 16, recv_bytes); + radeon_copy_swap(recv, base + 16, recv_bytes, false); return recv_bytes; } diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c index 23e3ea6ba14..ced9370ecb7 100644 --- a/drivers/gpu/drm/radeon/atombios_encoders.c +++ b/drivers/gpu/drm/radeon/atombios_encoders.c @@ -396,6 +396,8 @@ atombios_digital_setup(struct drm_encoder *encoder, int action) int atombios_get_encoder_mode(struct drm_encoder *encoder) { + struct drm_device *dev = encoder->dev; + struct radeon_device *rdev = dev->dev_private; struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); struct drm_connector *connector; struct radeon_connector *radeon_connector; @@ -421,7 +423,8 @@ atombios_get_encoder_mode(struct drm_encoder *encoder) case DRM_MODE_CONNECTOR_DVII: case DRM_MODE_CONNECTOR_HDMIB: /* HDMI-B is basically DL-DVI; analog works fine */ if (drm_detect_hdmi_monitor(radeon_connector->edid) && - radeon_audio) + radeon_audio && + !ASIC_IS_DCE6(rdev)) /* remove once we support DCE6 */ return ATOM_ENCODER_MODE_HDMI; else if (radeon_connector->use_digital) return ATOM_ENCODER_MODE_DVI; @@ -432,7 +435,8 @@ atombios_get_encoder_mode(struct drm_encoder *encoder) case DRM_MODE_CONNECTOR_HDMIA: default: if (drm_detect_hdmi_monitor(radeon_connector->edid) && - radeon_audio) + radeon_audio && + !ASIC_IS_DCE6(rdev)) /* remove once we support DCE6 */ return ATOM_ENCODER_MODE_HDMI; else return ATOM_ENCODER_MODE_DVI; @@ -446,7 +450,8 @@ atombios_get_encoder_mode(struct drm_encoder *encoder) (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) return ATOM_ENCODER_MODE_DP; else if (drm_detect_hdmi_monitor(radeon_connector->edid) && - radeon_audio) + radeon_audio && + !ASIC_IS_DCE6(rdev)) /* remove once we support DCE6 */ return ATOM_ENCODER_MODE_HDMI; else return ATOM_ENCODER_MODE_DVI; diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index c62132cecaf..300099d3118 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -445,6 +445,16 @@ void evergreen_hpd_init(struct radeon_device *rdev) list_for_each_entry(connector, &dev->mode_config.connector_list, head) { struct radeon_connector *radeon_connector = to_radeon_connector(connector); + + if (connector->connector_type == DRM_MODE_CONNECTOR_eDP || + connector->connector_type == DRM_MODE_CONNECTOR_LVDS) { + /* don't try to enable hpd on eDP or LVDS avoid breaking the + * aux dp channel on imac and help (but not completely fix) + * https://bugzilla.redhat.com/show_bug.cgi?id=726143 + * also avoid interrupt storms during dpms. + */ + continue; + } switch (radeon_connector->hpd.hpd) { case RADEON_HPD_1: WREG32(DC_HPD1_CONTROL, tmp); @@ -1146,17 +1156,16 @@ void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *sav tmp = RREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i]); if (!(tmp & EVERGREEN_CRTC_BLANK_DATA_EN)) { radeon_wait_for_vblank(rdev, i); - tmp |= EVERGREEN_CRTC_BLANK_DATA_EN; WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1); + tmp |= EVERGREEN_CRTC_BLANK_DATA_EN; WREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i], tmp); - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0); } } else { tmp = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]); if (!(tmp & EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE)) { radeon_wait_for_vblank(rdev, i); - tmp |= EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE; WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1); + tmp |= EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE; WREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i], tmp); WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0); } @@ -1168,6 +1177,15 @@ void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *sav break; udelay(1); } + + /* XXX this is a hack to avoid strange behavior with EFI on certain systems */ + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1); + tmp = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]); + tmp &= ~EVERGREEN_CRTC_MASTER_EN; + WREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i], tmp); + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0); + save->crtc_enabled[i] = false; + /* ***** */ } else { save->crtc_enabled[i] = false; } @@ -1185,6 +1203,22 @@ void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *sav } /* wait for the MC to settle */ udelay(100); + + /* lock double buffered regs */ + for (i = 0; i < rdev->num_crtc; i++) { + if (save->crtc_enabled[i]) { + tmp = RREG32(EVERGREEN_GRPH_UPDATE + crtc_offsets[i]); + if (!(tmp & EVERGREEN_GRPH_UPDATE_LOCK)) { + tmp |= EVERGREEN_GRPH_UPDATE_LOCK; + WREG32(EVERGREEN_GRPH_UPDATE + crtc_offsets[i], tmp); + } + tmp = RREG32(EVERGREEN_MASTER_UPDATE_LOCK + crtc_offsets[i]); + if (!(tmp & 1)) { + tmp |= 1; + WREG32(EVERGREEN_MASTER_UPDATE_LOCK + crtc_offsets[i], tmp); + } + } + } } void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save) @@ -1206,6 +1240,33 @@ void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *s WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS_HIGH, upper_32_bits(rdev->mc.vram_start)); WREG32(EVERGREEN_VGA_MEMORY_BASE_ADDRESS, (u32)rdev->mc.vram_start); + /* unlock regs and wait for update */ + for (i = 0; i < rdev->num_crtc; i++) { + if (save->crtc_enabled[i]) { + tmp = RREG32(EVERGREEN_MASTER_UPDATE_MODE + crtc_offsets[i]); + if ((tmp & 0x3) != 0) { + tmp &= ~0x3; + WREG32(EVERGREEN_MASTER_UPDATE_MODE + crtc_offsets[i], tmp); + } + tmp = RREG32(EVERGREEN_GRPH_UPDATE + crtc_offsets[i]); + if (tmp & EVERGREEN_GRPH_UPDATE_LOCK) { + tmp &= ~EVERGREEN_GRPH_UPDATE_LOCK; + WREG32(EVERGREEN_GRPH_UPDATE + crtc_offsets[i], tmp); + } + tmp = RREG32(EVERGREEN_MASTER_UPDATE_LOCK + crtc_offsets[i]); + if (tmp & 1) { + tmp &= ~1; + WREG32(EVERGREEN_MASTER_UPDATE_LOCK + crtc_offsets[i], tmp); + } + for (j = 0; j < rdev->usec_timeout; j++) { + tmp = RREG32(EVERGREEN_GRPH_UPDATE + crtc_offsets[i]); + if ((tmp & EVERGREEN_GRPH_SURFACE_UPDATE_PENDING) == 0) + break; + udelay(1); + } + } + } + /* unblackout the MC */ tmp = RREG32(MC_SHARED_BLACKOUT_CNTL); tmp &= ~BLACKOUT_MODE_MASK; @@ -2382,8 +2443,8 @@ int evergreen_mc_init(struct radeon_device *rdev) rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE); } else { /* size in MB on evergreen/cayman/tn */ - rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024; - rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024; + rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE) * 1024ULL * 1024ULL; + rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE) * 1024ULL * 1024ULL; } rdev->mc.visible_vram_size = rdev->mc.aper_size; r700_vram_gtt_location(rdev, &rdev->mc); @@ -3197,6 +3258,12 @@ static int evergreen_startup(struct radeon_device *rdev) } /* Enable IRQ */ + if (!rdev->irq.installed) { + r = radeon_irq_kms_init(rdev); + if (r) + return r; + } + r = r600_irq_init(rdev); if (r) { DRM_ERROR("radeon: IH init failed (%d).\n", r); @@ -3348,10 +3415,6 @@ int evergreen_init(struct radeon_device *rdev) if (r) return r; - r = radeon_irq_kms_init(rdev); - if (r) - return r; - rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ring_obj = NULL; r600_ring_init(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX], 1024 * 1024); diff --git a/drivers/gpu/drm/radeon/evergreen_reg.h b/drivers/gpu/drm/radeon/evergreen_reg.h index 34a0e856069..e534e5d17fa 100644 --- a/drivers/gpu/drm/radeon/evergreen_reg.h +++ b/drivers/gpu/drm/radeon/evergreen_reg.h @@ -225,6 +225,8 @@ #define EVERGREEN_CRTC_STATUS_POSITION 0x6e90 #define EVERGREEN_MASTER_UPDATE_MODE 0x6ef8 #define EVERGREEN_CRTC_UPDATE_LOCK 0x6ed4 +#define EVERGREEN_MASTER_UPDATE_LOCK 0x6ef4 +#define EVERGREEN_MASTER_UPDATE_MODE 0x6ef8 #define EVERGREEN_DC_GPIO_HPD_MASK 0x64b0 #define EVERGREEN_DC_GPIO_HPD_A 0x64b4 diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index 9934c9d9e51..f5387b3e699 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c @@ -663,21 +663,32 @@ static void cayman_gpu_init(struct radeon_device *rdev) (rdev->pdev->device == 0x9907) || (rdev->pdev->device == 0x9908) || (rdev->pdev->device == 0x9909) || + (rdev->pdev->device == 0x990B) || + (rdev->pdev->device == 0x990C) || + (rdev->pdev->device == 0x990F) || (rdev->pdev->device == 0x9910) || - (rdev->pdev->device == 0x9917)) { + (rdev->pdev->device == 0x9917) || + (rdev->pdev->device == 0x9999) || + (rdev->pdev->device == 0x999C)) { rdev->config.cayman.max_simds_per_se = 6; rdev->config.cayman.max_backends_per_se = 2; } else if ((rdev->pdev->device == 0x9903) || (rdev->pdev->device == 0x9904) || (rdev->pdev->device == 0x990A) || + (rdev->pdev->device == 0x990D) || + (rdev->pdev->device == 0x990E) || (rdev->pdev->device == 0x9913) || - (rdev->pdev->device == 0x9918)) { + (rdev->pdev->device == 0x9918) || + (rdev->pdev->device == 0x999D)) { rdev->config.cayman.max_simds_per_se = 4; rdev->config.cayman.max_backends_per_se = 2; } else if ((rdev->pdev->device == 0x9919) || (rdev->pdev->device == 0x9990) || (rdev->pdev->device == 0x9991) || (rdev->pdev->device == 0x9994) || + (rdev->pdev->device == 0x9995) || + (rdev->pdev->device == 0x9996) || + (rdev->pdev->device == 0x999A) || (rdev->pdev->device == 0x99A0)) { rdev->config.cayman.max_simds_per_se = 3; rdev->config.cayman.max_backends_per_se = 1; @@ -902,6 +913,8 @@ static void cayman_gpu_init(struct radeon_device *rdev) WREG32(GB_BACKEND_MAP, gb_backend_map); WREG32(GB_ADDR_CONFIG, gb_addr_config); WREG32(DMIF_ADDR_CONFIG, gb_addr_config); + if (ASIC_IS_DCE6(rdev)) + WREG32(DMIF_ADDR_CALC, gb_addr_config); WREG32(HDP_ADDR_CONFIG, gb_addr_config); /* primary versions */ @@ -1601,6 +1614,12 @@ static int cayman_startup(struct radeon_device *rdev) } /* Enable IRQ */ + if (!rdev->irq.installed) { + r = radeon_irq_kms_init(rdev); + if (r) + return r; + } + r = r600_irq_init(rdev); if (r) { DRM_ERROR("radeon: IH init failed (%d).\n", r); @@ -1731,10 +1750,6 @@ int cayman_init(struct radeon_device *rdev) if (r) return r; - r = radeon_irq_kms_init(rdev); - if (r) - return r; - ring->ring_obj = NULL; r600_ring_init(rdev, ring, 1024 * 1024); diff --git a/drivers/gpu/drm/radeon/nid.h b/drivers/gpu/drm/radeon/nid.h index 2aa7046ada5..d90b8b77f9b 100644 --- a/drivers/gpu/drm/radeon/nid.h +++ b/drivers/gpu/drm/radeon/nid.h @@ -42,6 +42,10 @@ #define CAYMAN_MAX_TCC_MASK 0xFF #define DMIF_ADDR_CONFIG 0xBD4 + +/* DCE6 only */ +#define DMIF_ADDR_CALC 0xC00 + #define SRBM_GFX_CNTL 0x0E44 #define RINGID(x) (((x) & 0x3) << 0) #define VMID(x) (((x) & 0x7) << 0) diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index fe33d35dae8..40ed0e5b95a 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -3952,6 +3952,12 @@ static int r100_startup(struct radeon_device *rdev) } /* Enable IRQ */ + if (!rdev->irq.installed) { + r = radeon_irq_kms_init(rdev); + if (r) + return r; + } + r100_irq_set(rdev); rdev->config.r100.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL); /* 1M ring buffer */ @@ -4111,9 +4117,6 @@ int r100_init(struct radeon_device *rdev) r100_mc_init(rdev); /* Fence driver */ r = radeon_fence_driver_init(rdev); - if (r) - return r; - r = radeon_irq_kms_init(rdev); if (r) return r; /* Memory manager */ diff --git a/drivers/gpu/drm/radeon/r300.c b/drivers/gpu/drm/radeon/r300.c index fa14383f9ca..63b53aa9536 100644 --- a/drivers/gpu/drm/radeon/r300.c +++ b/drivers/gpu/drm/radeon/r300.c @@ -1405,6 +1405,12 @@ static int r300_startup(struct radeon_device *rdev) } /* Enable IRQ */ + if (!rdev->irq.installed) { + r = radeon_irq_kms_init(rdev); + if (r) + return r; + } + r100_irq_set(rdev); rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL); /* 1M ring buffer */ @@ -1543,9 +1549,6 @@ int r300_init(struct radeon_device *rdev) r300_mc_init(rdev); /* Fence driver */ r = radeon_fence_driver_init(rdev); - if (r) - return r; - r = radeon_irq_kms_init(rdev); if (r) return r; /* Memory manager */ diff --git a/drivers/gpu/drm/radeon/r300_cmdbuf.c b/drivers/gpu/drm/radeon/r300_cmdbuf.c index 1fe98b421c9..9aa02becf5e 100644 --- a/drivers/gpu/drm/radeon/r300_cmdbuf.c +++ b/drivers/gpu/drm/radeon/r300_cmdbuf.c @@ -74,7 +74,7 @@ static int r300_emit_cliprects(drm_radeon_private_t *dev_priv, OUT_RING(CP_PACKET0(R300_RE_CLIPRECT_TL_0, nr * 2 - 1)); for (i = 0; i < nr; ++i) { - if (DRM_COPY_FROM_USER_UNCHECKED + if (DRM_COPY_FROM_USER (&box, &cmdbuf->boxes[n + i], sizeof(box))) { DRM_ERROR("copy cliprect faulted\n"); return -EFAULT; diff --git a/drivers/gpu/drm/radeon/r420.c b/drivers/gpu/drm/radeon/r420.c index f3fcaacfea0..1a9347fdd15 100644 --- a/drivers/gpu/drm/radeon/r420.c +++ b/drivers/gpu/drm/radeon/r420.c @@ -265,6 +265,12 @@ static int r420_startup(struct radeon_device *rdev) } /* Enable IRQ */ + if (!rdev->irq.installed) { + r = radeon_irq_kms_init(rdev); + if (r) + return r; + } + r100_irq_set(rdev); rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL); /* 1M ring buffer */ @@ -417,10 +423,6 @@ int r420_init(struct radeon_device *rdev) if (r) { return r; } - r = radeon_irq_kms_init(rdev); - if (r) { - return r; - } /* Memory manager */ r = radeon_bo_init(rdev); if (r) { diff --git a/drivers/gpu/drm/radeon/r520.c b/drivers/gpu/drm/radeon/r520.c index ebcc15b03c9..57be78461ab 100644 --- a/drivers/gpu/drm/radeon/r520.c +++ b/drivers/gpu/drm/radeon/r520.c @@ -194,6 +194,12 @@ static int r520_startup(struct radeon_device *rdev) } /* Enable IRQ */ + if (!rdev->irq.installed) { + r = radeon_irq_kms_init(rdev); + if (r) + return r; + } + rs600_irq_set(rdev); rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL); /* 1M ring buffer */ @@ -299,9 +305,6 @@ int r520_init(struct radeon_device *rdev) rv515_debugfs(rdev); /* Fence driver */ r = radeon_fence_driver_init(rdev); - if (r) - return r; - r = radeon_irq_kms_init(rdev); if (r) return r; /* Memory manager */ diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index b1ff9ccd2d6..8c403d946ac 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c @@ -2470,6 +2470,12 @@ int r600_startup(struct radeon_device *rdev) } /* Enable IRQ */ + if (!rdev->irq.installed) { + r = radeon_irq_kms_init(rdev); + if (r) + return r; + } + r = r600_irq_init(rdev); if (r) { DRM_ERROR("radeon: IH init failed (%d).\n", r); @@ -2624,10 +2630,6 @@ int r600_init(struct radeon_device *rdev) if (r) return r; - r = radeon_irq_kms_init(rdev); - if (r) - return r; - rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ring_obj = NULL; r600_ring_init(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX], 1024 * 1024); diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 5e30e126bfe..38d87e17285 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -1998,6 +1998,8 @@ static int radeon_atombios_parse_power_table_1_3(struct radeon_device *rdev) num_modes = power_info->info.ucNumOfPowerModeEntries; if (num_modes > ATOM_MAX_NUMBEROF_POWER_BLOCK) num_modes = ATOM_MAX_NUMBEROF_POWER_BLOCK; + if (num_modes == 0) + return state_index; rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state) * num_modes, GFP_KERNEL); if (!rdev->pm.power_state) return state_index; @@ -2396,6 +2398,8 @@ static int radeon_atombios_parse_power_table_4_5(struct radeon_device *rdev) power_info = (union power_info *)(mode_info->atom_context->bios + data_offset); radeon_atombios_add_pplib_thermal_controller(rdev, &power_info->pplib.sThermalController); + if (power_info->pplib.ucNumStates == 0) + return state_index; rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state) * power_info->pplib.ucNumStates, GFP_KERNEL); if (!rdev->pm.power_state) @@ -2478,6 +2482,7 @@ static int radeon_atombios_parse_power_table_6(struct radeon_device *rdev) int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); u16 data_offset; u8 frev, crev; + u8 *power_state_offset; if (!atom_parse_data_header(mode_info->atom_context, index, NULL, &frev, &crev, &data_offset)) @@ -2494,15 +2499,17 @@ static int radeon_atombios_parse_power_table_6(struct radeon_device *rdev) non_clock_info_array = (struct _NonClockInfoArray *) (mode_info->atom_context->bios + data_offset + le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset)); + if (state_array->ucNumEntries == 0) + return state_index; rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state) * state_array->ucNumEntries, GFP_KERNEL); if (!rdev->pm.power_state) return state_index; + power_state_offset = (u8 *)state_array->states; for (i = 0; i < state_array->ucNumEntries; i++) { mode_index = 0; - power_state = (union pplib_power_state *)&state_array->states[i]; - /* XXX this might be an inagua bug... */ - non_clock_array_index = i; /* power_state->v2.nonClockInfoIndex */ + power_state = (union pplib_power_state *)power_state_offset; + non_clock_array_index = power_state->v2.nonClockInfoIndex; non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *) &non_clock_info_array->nonClockInfo[non_clock_array_index]; rdev->pm.power_state[i].clock_info = kzalloc(sizeof(struct radeon_pm_clock_info) * @@ -2514,9 +2521,6 @@ static int radeon_atombios_parse_power_table_6(struct radeon_device *rdev) if (power_state->v2.ucNumDPMLevels) { for (j = 0; j < power_state->v2.ucNumDPMLevels; j++) { clock_array_index = power_state->v2.clockInfoIndex[j]; - /* XXX this might be an inagua bug... */ - if (clock_array_index >= clock_info_array->ucNumEntries) - continue; clock_info = (union pplib_clock_info *) &clock_info_array->clockInfo[clock_array_index * clock_info_array->ucEntrySize]; valid = radeon_atombios_parse_pplib_clock_info(rdev, @@ -2538,6 +2542,7 @@ static int radeon_atombios_parse_power_table_6(struct radeon_device *rdev) non_clock_info); state_index++; } + power_state_offset += 2 + power_state->v2.ucNumDPMLevels; } /* if multiple clock modes, mark the lowest as no display */ for (i = 0; i < state_index; i++) { @@ -2584,7 +2589,9 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev) default: break; } - } else { + } + + if (state_index == 0) { rdev->pm.power_state = kzalloc(sizeof(struct radeon_power_state), GFP_KERNEL); if (rdev->pm.power_state) { rdev->pm.power_state[0].clock_info = diff --git a/drivers/gpu/drm/radeon/radeon_benchmark.c b/drivers/gpu/drm/radeon/radeon_benchmark.c index fef7b722b05..89a0eeca0e2 100644 --- a/drivers/gpu/drm/radeon/radeon_benchmark.c +++ b/drivers/gpu/drm/radeon/radeon_benchmark.c @@ -141,13 +141,15 @@ static void radeon_benchmark_move(struct radeon_device *rdev, unsigned size, sdomain, ddomain, "dma"); } - time = radeon_benchmark_do_move(rdev, size, saddr, daddr, - RADEON_BENCHMARK_COPY_BLIT, n); - if (time < 0) - goto out_cleanup; - if (time > 0) - radeon_benchmark_log_results(n, size, time, - sdomain, ddomain, "blit"); + if (rdev->asic->copy.blit) { + time = radeon_benchmark_do_move(rdev, size, saddr, daddr, + RADEON_BENCHMARK_COPY_BLIT, n); + if (time < 0) + goto out_cleanup; + if (time > 0) + radeon_benchmark_log_results(n, size, time, + sdomain, ddomain, "blit"); + } out_cleanup: if (sobj) { diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index a2470d96deb..07d0bcd718a 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c @@ -147,7 +147,7 @@ static uint16_t combios_get_table_offset(struct drm_device *dev, enum radeon_combios_table_offset table) { struct radeon_device *rdev = dev->dev_private; - int rev; + int rev, size; uint16_t offset = 0, check_offset; if (!rdev->bios) @@ -156,174 +156,106 @@ static uint16_t combios_get_table_offset(struct drm_device *dev, switch (table) { /* absolute offset tables */ case COMBIOS_ASIC_INIT_1_TABLE: - check_offset = RBIOS16(rdev->bios_header_start + 0xc); - if (check_offset) - offset = check_offset; + check_offset = 0xc; break; case COMBIOS_BIOS_SUPPORT_TABLE: - check_offset = RBIOS16(rdev->bios_header_start + 0x14); - if (check_offset) - offset = check_offset; + check_offset = 0x14; break; case COMBIOS_DAC_PROGRAMMING_TABLE: - check_offset = RBIOS16(rdev->bios_header_start + 0x2a); - if (check_offset) - offset = check_offset; + check_offset = 0x2a; break; case COMBIOS_MAX_COLOR_DEPTH_TABLE: - check_offset = RBIOS16(rdev->bios_header_start + 0x2c); - if (check_offset) - offset = check_offset; + check_offset = 0x2c; break; case COMBIOS_CRTC_INFO_TABLE: - check_offset = RBIOS16(rdev->bios_header_start + 0x2e); - if (check_offset) - offset = check_offset; + check_offset = 0x2e; break; case COMBIOS_PLL_INFO_TABLE: - check_offset = RBIOS16(rdev->bios_header_start + 0x30); - if (check_offset) - offset = check_offset; + check_offset = 0x30; break; case COMBIOS_TV_INFO_TABLE: - check_offset = RBIOS16(rdev->bios_header_start + 0x32); - if (check_offset) - offset = check_offset; + check_offset = 0x32; break; case COMBIOS_DFP_INFO_TABLE: - check_offset = RBIOS16(rdev->bios_header_start + 0x34); - if (check_offset) - offset = check_offset; + check_offset = 0x34; break; case COMBIOS_HW_CONFIG_INFO_TABLE: - check_offset = RBIOS16(rdev->bios_header_start + 0x36); - if (check_offset) - offset = check_offset; + check_offset = 0x36; break; case COMBIOS_MULTIMEDIA_INFO_TABLE: - check_offset = RBIOS16(rdev->bios_header_start + 0x38); - if (check_offset) - offset = check_offset; + check_offset = 0x38; break; case COMBIOS_TV_STD_PATCH_TABLE: - check_offset = RBIOS16(rdev->bios_header_start + 0x3e); - if (check_offset) - offset = check_offset; + check_offset = 0x3e; break; case COMBIOS_LCD_INFO_TABLE: - check_offset = RBIOS16(rdev->bios_header_start + 0x40); - if (check_offset) - offset = check_offset; + check_offset = 0x40; break; case COMBIOS_MOBILE_INFO_TABLE: - check_offset = RBIOS16(rdev->bios_header_start + 0x42); - if (check_offset) - offset = check_offset; + check_offset = 0x42; break; case COMBIOS_PLL_INIT_TABLE: - check_offset = RBIOS16(rdev->bios_header_start + 0x46); - if (check_offset) - offset = check_offset; + check_offset = 0x46; break; case COMBIOS_MEM_CONFIG_TABLE: - check_offset = RBIOS16(rdev->bios_header_start + 0x48); - if (check_offset) - offset = check_offset; + check_offset = 0x48; break; case COMBIOS_SAVE_MASK_TABLE: - check_offset = RBIOS16(rdev->bios_header_start + 0x4a); - if (check_offset) - offset = check_offset; + check_offset = 0x4a; break; case COMBIOS_HARDCODED_EDID_TABLE: - check_offset = RBIOS16(rdev->bios_header_start + 0x4c); - if (check_offset) - offset = check_offset; + check_offset = 0x4c; break; case COMBIOS_ASIC_INIT_2_TABLE: - check_offset = RBIOS16(rdev->bios_header_start + 0x4e); - if (check_offset) - offset = check_offset; + check_offset = 0x4e; break; case COMBIOS_CONNECTOR_INFO_TABLE: - check_offset = RBIOS16(rdev->bios_header_start + 0x50); - if (check_offset) - offset = check_offset; + check_offset = 0x50; break; case COMBIOS_DYN_CLK_1_TABLE: - check_offset = RBIOS16(rdev->bios_header_start + 0x52); - if (check_offset) - offset = check_offset; + check_offset = 0x52; break; case COMBIOS_RESERVED_MEM_TABLE: - check_offset = RBIOS16(rdev->bios_header_start + 0x54); - if (check_offset) - offset = check_offset; + check_offset = 0x54; break; case COMBIOS_EXT_TMDS_INFO_TABLE: - check_offset = RBIOS16(rdev->bios_header_start + 0x58); - if (check_offset) - offset = check_offset; + check_offset = 0x58; break; case COMBIOS_MEM_CLK_INFO_TABLE: - check_offset = RBIOS16(rdev->bios_header_start + 0x5a); - if (check_offset) - offset = check_offset; + check_offset = 0x5a; break; case COMBIOS_EXT_DAC_INFO_TABLE: - check_offset = RBIOS16(rdev->bios_header_start + 0x5c); - if (check_offset) - offset = check_offset; + check_offset = 0x5c; break; case COMBIOS_MISC_INFO_TABLE: - check_offset = RBIOS16(rdev->bios_header_start + 0x5e); - if (check_offset) - offset = check_offset; + check_offset = 0x5e; break; case COMBIOS_CRT_INFO_TABLE: - check_offset = RBIOS16(rdev->bios_header_start + 0x60); - if (check_offset) - offset = check_offset; + check_offset = 0x60; break; case COMBIOS_INTEGRATED_SYSTEM_INFO_TABLE: - check_offset = RBIOS16(rdev->bios_header_start + 0x62); - if (check_offset) - offset = check_offset; + check_offset = 0x62; break; case COMBIOS_COMPONENT_VIDEO_INFO_TABLE: - check_offset = RBIOS16(rdev->bios_header_start + 0x64); - if (check_offset) - offset = check_offset; + check_offset = 0x64; break; case COMBIOS_FAN_SPEED_INFO_TABLE: - check_offset = RBIOS16(rdev->bios_header_start + 0x66); - if (check_offset) - offset = check_offset; + check_offset = 0x66; break; case COMBIOS_OVERDRIVE_INFO_TABLE: - check_offset = RBIOS16(rdev->bios_header_start + 0x68); - if (check_offset) - offset = check_offset; + check_offset = 0x68; break; case COMBIOS_OEM_INFO_TABLE: - check_offset = RBIOS16(rdev->bios_header_start + 0x6a); - if (check_offset) - offset = check_offset; + check_offset = 0x6a; break; case COMBIOS_DYN_CLK_2_TABLE: - check_offset = RBIOS16(rdev->bios_header_start + 0x6c); - if (check_offset) - offset = check_offset; + check_offset = 0x6c; break; case COMBIOS_POWER_CONNECTOR_INFO_TABLE: - check_offset = RBIOS16(rdev->bios_header_start + 0x6e); - if (check_offset) - offset = check_offset; + check_offset = 0x6e; break; case COMBIOS_I2C_INFO_TABLE: - check_offset = RBIOS16(rdev->bios_header_start + 0x70); - if (check_offset) - offset = check_offset; + check_offset = 0x70; break; /* relative offset tables */ case COMBIOS_ASIC_INIT_3_TABLE: /* offset from misc info */ @@ -439,11 +371,16 @@ static uint16_t combios_get_table_offset(struct drm_device *dev, } break; default: + check_offset = 0; break; } - return offset; + size = RBIOS8(rdev->bios_header_start + 0x6); + /* check absolute offset tables */ + if (table < COMBIOS_ASIC_INIT_3_TABLE && check_offset && check_offset < size) + offset = RBIOS16(rdev->bios_header_start + check_offset); + return offset; } bool radeon_combios_check_hardcoded_edid(struct radeon_device *rdev) @@ -953,11 +890,22 @@ struct radeon_encoder_primary_dac *radeon_combios_get_primary_dac_info(struct dac = RBIOS8(dac_info + 0x3) & 0xf; p_dac->ps2_pdac_adj = (bg << 8) | (dac); } - /* if the values are all zeros, use the table */ - if (p_dac->ps2_pdac_adj) + /* if the values are zeros, use the table */ + if ((dac == 0) || (bg == 0)) + found = 0; + else found = 1; } + /* quirks */ + /* Radeon 9100 (R200) */ + if ((dev->pdev->device == 0x514D) && + (dev->pdev->subsystem_vendor == 0x174B) && + (dev->pdev->subsystem_device == 0x7149)) { + /* vbios value is bad, use the default */ + found = 0; + } + if (!found) /* fallback to defaults */ radeon_legacy_get_primary_dac_info_from_table(rdev, p_dac); diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index de5e0b51dc6..1209f150d40 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -358,22 +358,22 @@ bool radeon_card_posted(struct radeon_device *rdev) { uint32_t reg; - if (efi_enabled && rdev->pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE) + if (efi_enabled(EFI_BOOT) && + rdev->pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE) return false; /* first check CRTCs */ - if (ASIC_IS_DCE41(rdev)) { + if (ASIC_IS_DCE4(rdev)) { reg = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET) | RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET); - if (reg & EVERGREEN_CRTC_MASTER_EN) - return true; - } else if (ASIC_IS_DCE4(rdev)) { - reg = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET) | - RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET) | - RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET) | - RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET) | - RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET) | - RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET); + if (rdev->num_crtc >= 4) { + reg |= RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET) | + RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET); + } + if (rdev->num_crtc >= 6) { + reg |= RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET) | + RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET); + } if (reg & EVERGREEN_CRTC_MASTER_EN) return true; } else if (ASIC_IS_AVIVO(rdev)) { diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index b8459bdce42..bf6ca2d8a28 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c @@ -872,7 +872,11 @@ static int radeon_debugfs_pm_info(struct seq_file *m, void *data) struct radeon_device *rdev = dev->dev_private; seq_printf(m, "default engine clock: %u0 kHz\n", rdev->pm.default_sclk); - seq_printf(m, "current engine clock: %u0 kHz\n", radeon_get_engine_clock(rdev)); + /* radeon_get_engine_clock is not reliable on APUs so just print the current clock */ + if ((rdev->family >= CHIP_PALM) && (rdev->flags & RADEON_IS_IGP)) + seq_printf(m, "current engine clock: %u0 kHz\n", rdev->pm.current_sclk); + else + seq_printf(m, "current engine clock: %u0 kHz\n", radeon_get_engine_clock(rdev)); seq_printf(m, "default memory clock: %u0 kHz\n", rdev->pm.default_mclk); if (rdev->asic->pm.get_memory_clock) seq_printf(m, "current memory clock: %u0 kHz\n", radeon_get_memory_clock(rdev)); diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index f493c6403af..49b55edc55b 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -744,7 +744,7 @@ int radeon_ttm_init(struct radeon_device *rdev) return r; } DRM_INFO("radeon: %uM of VRAM memory ready\n", - (unsigned)rdev->mc.real_vram_size / (1024 * 1024)); + (unsigned) (rdev->mc.real_vram_size / (1024 * 1024))); r = ttm_bo_init_mm(&rdev->mman.bdev, TTM_PL_TT, rdev->mc.gtt_size >> PAGE_SHIFT); if (r) { diff --git a/drivers/gpu/drm/radeon/rs400.c b/drivers/gpu/drm/radeon/rs400.c index 4cf381b3a6d..5099bd32e19 100644 --- a/drivers/gpu/drm/radeon/rs400.c +++ b/drivers/gpu/drm/radeon/rs400.c @@ -417,6 +417,12 @@ static int rs400_startup(struct radeon_device *rdev) } /* Enable IRQ */ + if (!rdev->irq.installed) { + r = radeon_irq_kms_init(rdev); + if (r) + return r; + } + r100_irq_set(rdev); rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL); /* 1M ring buffer */ @@ -539,9 +545,6 @@ int rs400_init(struct radeon_device *rdev) rs400_mc_init(rdev); /* Fence driver */ r = radeon_fence_driver_init(rdev); - if (r) - return r; - r = radeon_irq_kms_init(rdev); if (r) return r; /* Memory manager */ diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index d25cf869d08..52480010156 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c @@ -864,6 +864,12 @@ static int rs600_startup(struct radeon_device *rdev) } /* Enable IRQ */ + if (!rdev->irq.installed) { + r = radeon_irq_kms_init(rdev); + if (r) + return r; + } + rs600_irq_set(rdev); rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL); /* 1M ring buffer */ @@ -992,9 +998,6 @@ int rs600_init(struct radeon_device *rdev) rs600_debugfs(rdev); /* Fence driver */ r = radeon_fence_driver_init(rdev); - if (r) - return r; - r = radeon_irq_kms_init(rdev); if (r) return r; /* Memory manager */ diff --git a/drivers/gpu/drm/radeon/rs690.c b/drivers/gpu/drm/radeon/rs690.c index f2c3b9d75f1..c46900c2c1a 100644 --- a/drivers/gpu/drm/radeon/rs690.c +++ b/drivers/gpu/drm/radeon/rs690.c @@ -628,6 +628,12 @@ static int rs690_startup(struct radeon_device *rdev) } /* Enable IRQ */ + if (!rdev->irq.installed) { + r = radeon_irq_kms_init(rdev); + if (r) + return r; + } + rs600_irq_set(rdev); rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL); /* 1M ring buffer */ @@ -757,9 +763,6 @@ int rs690_init(struct radeon_device *rdev) rv515_debugfs(rdev); /* Fence driver */ r = radeon_fence_driver_init(rdev); - if (r) - return r; - r = radeon_irq_kms_init(rdev); if (r) return r; /* Memory manager */ diff --git a/drivers/gpu/drm/radeon/rv515.c b/drivers/gpu/drm/radeon/rv515.c index 43af363ead3..0532bbee9f9 100644 --- a/drivers/gpu/drm/radeon/rv515.c +++ b/drivers/gpu/drm/radeon/rv515.c @@ -386,6 +386,12 @@ static int rv515_startup(struct radeon_device *rdev) } /* Enable IRQ */ + if (!rdev->irq.installed) { + r = radeon_irq_kms_init(rdev); + if (r) + return r; + } + rs600_irq_set(rdev); rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL); /* 1M ring buffer */ @@ -518,9 +524,6 @@ int rv515_init(struct radeon_device *rdev) rv515_debugfs(rdev); /* Fence driver */ r = radeon_fence_driver_init(rdev); - if (r) - return r; - r = radeon_irq_kms_init(rdev); if (r) return r; /* Memory manager */ diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index 591040b9466..4a3937fa2dc 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -1099,6 +1099,12 @@ static int rv770_startup(struct radeon_device *rdev) } /* Enable IRQ */ + if (!rdev->irq.installed) { + r = radeon_irq_kms_init(rdev); + if (r) + return r; + } + r = r600_irq_init(rdev); if (r) { DRM_ERROR("radeon: IH init failed (%d).\n", r); @@ -1237,10 +1243,6 @@ int rv770_init(struct radeon_device *rdev) if (r) return r; - r = radeon_irq_kms_init(rdev); - if (r) - return r; - rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ring_obj = NULL; r600_ring_init(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX], 1024 * 1024); diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 1197f2187d7..e22b460a4f0 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -1799,6 +1799,7 @@ static void si_gpu_init(struct radeon_device *rdev) rdev->config.si.backend_map = gb_backend_map; WREG32(GB_ADDR_CONFIG, gb_addr_config); WREG32(DMIF_ADDR_CONFIG, gb_addr_config); + WREG32(DMIF_ADDR_CALC, gb_addr_config); WREG32(HDP_ADDR_CONFIG, gb_addr_config); /* primary versions */ @@ -2463,8 +2464,8 @@ static int si_mc_init(struct radeon_device *rdev) rdev->mc.aper_base = pci_resource_start(rdev->pdev, 0); rdev->mc.aper_size = pci_resource_len(rdev->pdev, 0); /* size in MB on si */ - rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024; - rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE) * 1024 * 1024; + rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE) * 1024ULL * 1024ULL; + rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE) * 1024ULL * 1024ULL; rdev->mc.visible_vram_size = rdev->mc.aper_size; si_vram_gtt_location(rdev, &rdev->mc); radeon_update_bandwidth_info(rdev); @@ -3875,6 +3876,12 @@ static int si_startup(struct radeon_device *rdev) } /* Enable IRQ */ + if (!rdev->irq.installed) { + r = radeon_irq_kms_init(rdev); + if (r) + return r; + } + r = si_irq_init(rdev); if (r) { DRM_ERROR("radeon: IH init failed (%d).\n", r); @@ -4043,10 +4050,6 @@ int si_init(struct radeon_device *rdev) if (r) return r; - r = radeon_irq_kms_init(rdev); - if (r) - return r; - ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; ring->ring_obj = NULL; r600_ring_init(rdev, ring, 1024 * 1024); diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h index 2c2bc63d6da..45e240d0906 100644 --- a/drivers/gpu/drm/radeon/sid.h +++ b/drivers/gpu/drm/radeon/sid.h @@ -55,6 +55,8 @@ #define DMIF_ADDR_CONFIG 0xBD4 +#define DMIF_ADDR_CALC 0xC00 + #define SRBM_STATUS 0xE50 #define CC_SYS_RB_BACKEND_DISABLE 0xe80 diff --git a/drivers/gpu/drm/udl/udl_connector.c b/drivers/gpu/drm/udl/udl_connector.c index 32342247d91..b8e6463bd14 100644 --- a/drivers/gpu/drm/udl/udl_connector.c +++ b/drivers/gpu/drm/udl/udl_connector.c @@ -61,6 +61,10 @@ static int udl_get_modes(struct drm_connector *connector) int ret; edid = (struct edid *)udl_get_edid(udl); + if (!edid) { + drm_mode_connector_update_edid_property(connector, NULL); + return 0; + } connector->display_info.raw_edid = (char *)edid; diff --git a/drivers/gpu/drm/udl/udl_drv.h b/drivers/gpu/drm/udl/udl_drv.h index e7605758661..2b8c4fdda97 100644 --- a/drivers/gpu/drm/udl/udl_drv.h +++ b/drivers/gpu/drm/udl/udl_drv.h @@ -74,6 +74,8 @@ struct udl_framebuffer { struct drm_framebuffer base; struct udl_gem_object *obj; bool active_16; /* active on the 16-bit channel */ + int x1, y1, x2, y2; /* dirty rect */ + spinlock_t dirty_lock; }; #define to_udl_fb(x) container_of(x, struct udl_framebuffer, base) diff --git a/drivers/gpu/drm/udl/udl_fb.c b/drivers/gpu/drm/udl/udl_fb.c index b9282cf7aea..f02d223d394 100644 --- a/drivers/gpu/drm/udl/udl_fb.c +++ b/drivers/gpu/drm/udl/udl_fb.c @@ -22,9 +22,9 @@ #include "drm_fb_helper.h" -#define DL_DEFIO_WRITE_DELAY 5 /* fb_deferred_io.delay in jiffies */ +#define DL_DEFIO_WRITE_DELAY (HZ/20) /* fb_deferred_io.delay in jiffies */ -static int fb_defio = 1; /* Optionally enable experimental fb_defio mmap support */ +static int fb_defio = 0; /* Optionally enable experimental fb_defio mmap support */ static int fb_bpp = 16; module_param(fb_bpp, int, S_IWUSR | S_IRUSR | S_IWGRP | S_IRGRP); @@ -153,6 +153,9 @@ int udl_handle_damage(struct udl_framebuffer *fb, int x, int y, struct urb *urb; int aligned_x; int bpp = (fb->base.bits_per_pixel / 8); + int x2, y2; + bool store_for_later = false; + unsigned long flags; if (!fb->active_16) return 0; @@ -160,8 +163,6 @@ int udl_handle_damage(struct udl_framebuffer *fb, int x, int y, if (!fb->obj->vmapping) udl_gem_vmap(fb->obj); - start_cycles = get_cycles(); - aligned_x = DL_ALIGN_DOWN(x, sizeof(unsigned long)); width = DL_ALIGN_UP(width + (x-aligned_x), sizeof(unsigned long)); x = aligned_x; @@ -171,19 +172,53 @@ int udl_handle_damage(struct udl_framebuffer *fb, int x, int y, (y + height > fb->base.height)) return -EINVAL; + /* if we are in atomic just store the info + can't test inside spin lock */ + if (in_atomic()) + store_for_later = true; + + x2 = x + width - 1; + y2 = y + height - 1; + + spin_lock_irqsave(&fb->dirty_lock, flags); + + if (fb->y1 < y) + y = fb->y1; + if (fb->y2 > y2) + y2 = fb->y2; + if (fb->x1 < x) + x = fb->x1; + if (fb->x2 > x2) + x2 = fb->x2; + + if (store_for_later) { + fb->x1 = x; + fb->x2 = x2; + fb->y1 = y; + fb->y2 = y2; + spin_unlock_irqrestore(&fb->dirty_lock, flags); + return 0; + } + + fb->x1 = fb->y1 = INT_MAX; + fb->x2 = fb->y2 = 0; + + spin_unlock_irqrestore(&fb->dirty_lock, flags); + start_cycles = get_cycles(); + urb = udl_get_urb(dev); if (!urb) return 0; cmd = urb->transfer_buffer; - for (i = y; i < y + height ; i++) { + for (i = y; i <= y2 ; i++) { const int line_offset = fb->base.pitches[0] * i; const int byte_offset = line_offset + (x * bpp); const int dev_byte_offset = (fb->base.width * bpp * i) + (x * bpp); if (udl_render_hline(dev, bpp, &urb, (char *) fb->obj->vmapping, &cmd, byte_offset, dev_byte_offset, - width * bpp, + (x2 - x + 1) * bpp, &bytes_identical, &bytes_sent)) goto error; } @@ -408,6 +443,7 @@ udl_framebuffer_init(struct drm_device *dev, { int ret; + spin_lock_init(&ufb->dirty_lock); ufb->obj = obj; ret = drm_framebuffer_init(dev, &ufb->base, &udlfb_funcs); drm_helper_mode_fill_fb_struct(&ufb->base, mode_cmd); diff --git a/drivers/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c index 58434e804d9..37fe2463f9b 100644 --- a/drivers/gpu/vga/vga_switcheroo.c +++ b/drivers/gpu/vga/vga_switcheroo.c @@ -26,6 +26,7 @@ #include #include +#include #include struct vga_switcheroo_client { @@ -256,8 +257,10 @@ static int vga_switchto_stage2(struct vga_switcheroo_client *new_client) if (new_client->fb_info) { struct fb_event event; + console_lock(); event.info = new_client->fb_info; fb_notifier_call_chain(FB_EVENT_REMAP_ALL_CONSOLE, &event); + console_unlock(); } ret = vgasr_priv.handler->switchto(new_client->id); diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 1a92a271adb..ff73d60cfc7 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1922,6 +1922,7 @@ static const struct hid_device_id hid_ignore_list[] = { { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_HYBRID) }, { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_HEATCONTROL) }, { HID_USB_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_BEATPAD) }, + { HID_USB_DEVICE(USB_VENDOR_ID_MASTERKIT, USB_DEVICE_ID_MASTERKIT_MA901RADIO) }, { HID_USB_DEVICE(USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1024LS) }, { HID_USB_DEVICE(USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1208LS) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICKIT1) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 72b7b97fe6a..2072b3220e0 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -520,6 +520,9 @@ #define USB_VENDOR_ID_MADCATZ 0x0738 #define USB_DEVICE_ID_MADCATZ_BEATPAD 0x4540 +#define USB_VENDOR_ID_MASTERKIT 0x16c0 +#define USB_DEVICE_ID_MASTERKIT_MA901RADIO 0x05df + #define USB_VENDOR_ID_MCC 0x09db #define USB_DEVICE_ID_MCC_PMD1024LS 0x0076 #define USB_DEVICE_ID_MCC_PMD1208LS 0x007a @@ -641,6 +644,9 @@ #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008 0x3008 #define USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN 0x3001 +#define USB_VENDOR_ID_REALTEK 0x0bda +#define USB_DEVICE_ID_REALTEK_READER 0x0152 + #define USB_VENDOR_ID_ROCCAT 0x1e7d #define USB_DEVICE_ID_ROCCAT_ARVO 0x30d4 #define USB_DEVICE_ID_ROCCAT_ISKU 0x319c diff --git a/drivers/hid/hid-microsoft.c b/drivers/hid/hid-microsoft.c index 38999898d04..259b9f44e12 100644 --- a/drivers/hid/hid-microsoft.c +++ b/drivers/hid/hid-microsoft.c @@ -47,9 +47,9 @@ static __u8 *ms_report_fixup(struct hid_device *hdev, __u8 *rdesc, rdesc[559] = 0x45; } /* the same as above (s/usage/physical/) */ - if ((quirks & MS_RDESC_3K) && *rsize == 106 && - !memcmp((char []){ 0x19, 0x00, 0x29, 0xff }, - &rdesc[94], 4)) { + if ((quirks & MS_RDESC_3K) && *rsize == 106 && rdesc[94] == 0x19 && + rdesc[95] == 0x00 && rdesc[96] == 0x29 && + rdesc[97] == 0xff) { rdesc[94] = 0x35; rdesc[96] = 0x45; } diff --git a/drivers/hid/hid-wiimote-ext.c b/drivers/hid/hid-wiimote-ext.c index aa958706c0e..9e572850201 100644 --- a/drivers/hid/hid-wiimote-ext.c +++ b/drivers/hid/hid-wiimote-ext.c @@ -378,14 +378,14 @@ static void handler_nunchuck(struct wiimote_ext *ext, const __u8 *payload) if (ext->motionp) { input_report_key(ext->input, - wiiext_keymap[WIIEXT_KEY_Z], !!(payload[5] & 0x04)); + wiiext_keymap[WIIEXT_KEY_Z], !(payload[5] & 0x04)); input_report_key(ext->input, - wiiext_keymap[WIIEXT_KEY_C], !!(payload[5] & 0x08)); + wiiext_keymap[WIIEXT_KEY_C], !(payload[5] & 0x08)); } else { input_report_key(ext->input, - wiiext_keymap[WIIEXT_KEY_Z], !!(payload[5] & 0x01)); + wiiext_keymap[WIIEXT_KEY_Z], !(payload[5] & 0x01)); input_report_key(ext->input, - wiiext_keymap[WIIEXT_KEY_C], !!(payload[5] & 0x02)); + wiiext_keymap[WIIEXT_KEY_C], !(payload[5] & 0x02)); } input_sync(ext->input); diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 9fea98f7c37..5c4112e650b 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -77,6 +77,7 @@ static const struct hid_blacklist { { USB_VENDOR_ID_PRODIGE, USB_DEVICE_ID_PRODIGE_CORDLESS, HID_QUIRK_NOGET }, { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NOGET }, { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008, HID_QUIRK_NOGET }, + { USB_VENDOR_ID_REALTEK, USB_DEVICE_ID_REALTEK_READER, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_SENNHEISER, USB_DEVICE_ID_SENNHEISER_BTD500USB, HID_QUIRK_NOGET }, { USB_VENDOR_ID_SIGMATEL, USB_DEVICE_ID_SIGMATEL_STMP3780, HID_QUIRK_NOGET }, { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET }, diff --git a/drivers/hwmon/abituguru.c b/drivers/hwmon/abituguru.c index a72bf25601a..56b178a56e6 100644 --- a/drivers/hwmon/abituguru.c +++ b/drivers/hwmon/abituguru.c @@ -1410,14 +1410,18 @@ static int __devinit abituguru_probe(struct platform_device *pdev) pr_info("found Abit uGuru\n"); /* Register sysfs hooks */ - for (i = 0; i < sysfs_attr_i; i++) - if (device_create_file(&pdev->dev, - &data->sysfs_attr[i].dev_attr)) + for (i = 0; i < sysfs_attr_i; i++) { + res = device_create_file(&pdev->dev, + &data->sysfs_attr[i].dev_attr); + if (res) goto abituguru_probe_error; - for (i = 0; i < ARRAY_SIZE(abituguru_sysfs_attr); i++) - if (device_create_file(&pdev->dev, - &abituguru_sysfs_attr[i].dev_attr)) + } + for (i = 0; i < ARRAY_SIZE(abituguru_sysfs_attr); i++) { + res = device_create_file(&pdev->dev, + &abituguru_sysfs_attr[i].dev_attr); + if (res) goto abituguru_probe_error; + } data->hwmon_dev = hwmon_device_register(&pdev->dev); if (!IS_ERR(data->hwmon_dev)) diff --git a/drivers/hwmon/adm1021.c b/drivers/hwmon/adm1021.c index 4394e7e99c4..5653461db66 100644 --- a/drivers/hwmon/adm1021.c +++ b/drivers/hwmon/adm1021.c @@ -332,26 +332,68 @@ static int adm1021_detect(struct i2c_client *client, man_id = i2c_smbus_read_byte_data(client, ADM1021_REG_MAN_ID); dev_id = i2c_smbus_read_byte_data(client, ADM1021_REG_DEV_ID); + if (man_id < 0 || dev_id < 0) + return -ENODEV; + if (man_id == 0x4d && dev_id == 0x01) type_name = "max1617a"; else if (man_id == 0x41) { if ((dev_id & 0xF0) == 0x30) type_name = "adm1023"; - else + else if ((dev_id & 0xF0) == 0x00) type_name = "adm1021"; + else + return -ENODEV; } else if (man_id == 0x49) type_name = "thmc10"; else if (man_id == 0x23) type_name = "gl523sm"; else if (man_id == 0x54) type_name = "mc1066"; - /* LM84 Mfr ID in a different place, and it has more unused bits */ - else if (conv_rate == 0x00 - && (config & 0x7F) == 0x00 - && (status & 0xAB) == 0x00) - type_name = "lm84"; - else - type_name = "max1617"; + else { + int lte, rte, lhi, rhi, llo, rlo; + + /* extra checks for LM84 and MAX1617 to avoid misdetections */ + + llo = i2c_smbus_read_byte_data(client, ADM1021_REG_THYST_R(0)); + rlo = i2c_smbus_read_byte_data(client, ADM1021_REG_THYST_R(1)); + + /* fail if any of the additional register reads failed */ + if (llo < 0 || rlo < 0) + return -ENODEV; + + lte = i2c_smbus_read_byte_data(client, ADM1021_REG_TEMP(0)); + rte = i2c_smbus_read_byte_data(client, ADM1021_REG_TEMP(1)); + lhi = i2c_smbus_read_byte_data(client, ADM1021_REG_TOS_R(0)); + rhi = i2c_smbus_read_byte_data(client, ADM1021_REG_TOS_R(1)); + + /* + * Fail for negative temperatures and negative high limits. + * This check also catches read errors on the tested registers. + */ + if ((s8)lte < 0 || (s8)rte < 0 || (s8)lhi < 0 || (s8)rhi < 0) + return -ENODEV; + + /* fail if all registers hold the same value */ + if (lte == rte && lte == lhi && lte == rhi && lte == llo + && lte == rlo) + return -ENODEV; + + /* + * LM84 Mfr ID is in a different place, + * and it has more unused bits. + */ + if (conv_rate == 0x00 + && (config & 0x7F) == 0x00 + && (status & 0xAB) == 0x00) { + type_name = "lm84"; + } else { + /* fail if low limits are larger than high limits */ + if ((s8)llo > lhi || (s8)rlo > rhi) + return -ENODEV; + type_name = "max1617"; + } + } pr_debug("adm1021: Detected chip %s at adapter %d, address 0x%02x.\n", type_name, i2c_adapter_id(adapter), client->addr); diff --git a/drivers/hwmon/adt7470.c b/drivers/hwmon/adt7470.c index 54ec890521f..034085d991e 100644 --- a/drivers/hwmon/adt7470.c +++ b/drivers/hwmon/adt7470.c @@ -215,7 +215,7 @@ static inline int adt7470_write_word_data(struct i2c_client *client, u8 reg, u16 value) { return i2c_smbus_write_byte_data(client, reg, value & 0xFF) - && i2c_smbus_write_byte_data(client, reg + 1, value >> 8); + || i2c_smbus_write_byte_data(client, reg + 1, value >> 8); } static void adt7470_init_client(struct i2c_client *client) diff --git a/drivers/hwmon/lineage-pem.c b/drivers/hwmon/lineage-pem.c index d264937c7f5..22249f4d887 100644 --- a/drivers/hwmon/lineage-pem.c +++ b/drivers/hwmon/lineage-pem.c @@ -421,6 +421,7 @@ static struct attribute *pem_input_attributes[] = { &sensor_dev_attr_in2_input.dev_attr.attr, &sensor_dev_attr_curr1_input.dev_attr.attr, &sensor_dev_attr_power1_input.dev_attr.attr, + NULL }; static const struct attribute_group pem_input_group = { @@ -431,6 +432,7 @@ static struct attribute *pem_fan_attributes[] = { &sensor_dev_attr_fan1_input.dev_attr.attr, &sensor_dev_attr_fan2_input.dev_attr.attr, &sensor_dev_attr_fan3_input.dev_attr.attr, + NULL }; static const struct attribute_group pem_fan_group = { diff --git a/drivers/hwmon/pmbus/ltc2978.c b/drivers/hwmon/pmbus/ltc2978.c index 9652a2c92a2..6d6130752f9 100644 --- a/drivers/hwmon/pmbus/ltc2978.c +++ b/drivers/hwmon/pmbus/ltc2978.c @@ -59,10 +59,10 @@ enum chips { ltc2978, ltc3880 }; struct ltc2978_data { enum chips id; int vin_min, vin_max; - int temp_min, temp_max; + int temp_min, temp_max[2]; int vout_min[8], vout_max[8]; int iout_max[2]; - int temp2_max[2]; + int temp2_max; struct pmbus_driver_info info; }; @@ -113,9 +113,10 @@ static int ltc2978_read_word_data_common(struct i2c_client *client, int page, ret = pmbus_read_word_data(client, page, LTC2978_MFR_TEMPERATURE_PEAK); if (ret >= 0) { - if (lin11_to_val(ret) > lin11_to_val(data->temp_max)) - data->temp_max = ret; - ret = data->temp_max; + if (lin11_to_val(ret) + > lin11_to_val(data->temp_max[page])) + data->temp_max[page] = ret; + ret = data->temp_max[page]; } break; case PMBUS_VIRT_RESET_VOUT_HISTORY: @@ -204,10 +205,9 @@ static int ltc3880_read_word_data(struct i2c_client *client, int page, int reg) ret = pmbus_read_word_data(client, page, LTC3880_MFR_TEMPERATURE2_PEAK); if (ret >= 0) { - if (lin11_to_val(ret) - > lin11_to_val(data->temp2_max[page])) - data->temp2_max[page] = ret; - ret = data->temp2_max[page]; + if (lin11_to_val(ret) > lin11_to_val(data->temp2_max)) + data->temp2_max = ret; + ret = data->temp2_max; } break; case PMBUS_VIRT_READ_VIN_MIN: @@ -248,11 +248,11 @@ static int ltc2978_write_word_data(struct i2c_client *client, int page, switch (reg) { case PMBUS_VIRT_RESET_IOUT_HISTORY: - data->iout_max[page] = 0x7fff; + data->iout_max[page] = 0x7c00; ret = ltc2978_clear_peaks(client, page, data->id); break; case PMBUS_VIRT_RESET_TEMP2_HISTORY: - data->temp2_max[page] = 0x7fff; + data->temp2_max = 0x7c00; ret = ltc2978_clear_peaks(client, page, data->id); break; case PMBUS_VIRT_RESET_VOUT_HISTORY: @@ -262,12 +262,12 @@ static int ltc2978_write_word_data(struct i2c_client *client, int page, break; case PMBUS_VIRT_RESET_VIN_HISTORY: data->vin_min = 0x7bff; - data->vin_max = 0; + data->vin_max = 0x7c00; ret = ltc2978_clear_peaks(client, page, data->id); break; case PMBUS_VIRT_RESET_TEMP_HISTORY: data->temp_min = 0x7bff; - data->temp_max = 0x7fff; + data->temp_max[page] = 0x7c00; ret = ltc2978_clear_peaks(client, page, data->id); break; default: @@ -321,12 +321,14 @@ static int ltc2978_probe(struct i2c_client *client, info = &data->info; info->write_word_data = ltc2978_write_word_data; - data->vout_min[0] = 0xffff; data->vin_min = 0x7bff; + data->vin_max = 0x7c00; data->temp_min = 0x7bff; - data->temp_max = 0x7fff; + for (i = 0; i < ARRAY_SIZE(data->temp_max); i++) + data->temp_max[i] = 0x7c00; + data->temp2_max = 0x7c00; - switch (id->driver_data) { + switch (data->id) { case ltc2978: info->read_word_data = ltc2978_read_word_data; info->pages = 8; @@ -336,7 +338,6 @@ static int ltc2978_probe(struct i2c_client *client, for (i = 1; i < 8; i++) { info->func[i] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT; - data->vout_min[i] = 0xffff; } break; case ltc3880: @@ -352,11 +353,14 @@ static int ltc2978_probe(struct i2c_client *client, | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | PMBUS_HAVE_POUT | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP; - data->vout_min[1] = 0xffff; + data->iout_max[0] = 0x7c00; + data->iout_max[1] = 0x7c00; break; default: return -ENODEV; } + for (i = 0; i < info->pages; i++) + data->vout_min[i] = 0xffff; return pmbus_do_probe(client, id, info); } diff --git a/drivers/hwmon/sht15.c b/drivers/hwmon/sht15.c index 8b011d01662..c68963023ca 100644 --- a/drivers/hwmon/sht15.c +++ b/drivers/hwmon/sht15.c @@ -926,7 +926,13 @@ static int __devinit sht15_probe(struct platform_device *pdev) if (voltage) data->supply_uV = voltage; - regulator_enable(data->reg); + ret = regulator_enable(data->reg); + if (ret != 0) { + dev_err(&pdev->dev, + "failed to enable regulator: %d\n", ret); + goto err_free_data; + } + /* * Setup a notifier block to update this if another device * causes the voltage to change diff --git a/drivers/hwspinlock/hwspinlock_core.c b/drivers/hwspinlock/hwspinlock_core.c index 1201a15784c..08e7e72dfa1 100644 --- a/drivers/hwspinlock/hwspinlock_core.c +++ b/drivers/hwspinlock/hwspinlock_core.c @@ -416,6 +416,8 @@ static int __hwspin_lock_request(struct hwspinlock *hwlock) ret = pm_runtime_get_sync(dev); if (ret < 0) { dev_err(dev, "%s: can't power on device\n", __func__); + pm_runtime_put_noidle(dev); + module_put(dev->driver->owner); return ret; } diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c index 619334994df..3c2812f13d9 100644 --- a/drivers/i2c/busses/i2c-designware-core.c +++ b/drivers/i2c/busses/i2c-designware-core.c @@ -349,7 +349,8 @@ static void i2c_dw_xfer_init(struct dw_i2c_dev *dev) /* Enable the adapter */ dw_writel(dev, 1, DW_IC_ENABLE); - /* Enable interrupts */ + /* Clear and enable interrupts */ + i2c_dw_clear_int(dev); dw_writel(dev, DW_IC_INTR_DEFAULT_MASK, DW_IC_INTR_MASK); } diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c index 2bded7647ef..d70106e5711 100644 --- a/drivers/i2c/busses/i2c-xiic.c +++ b/drivers/i2c/busses/i2c-xiic.c @@ -311,10 +311,8 @@ static void xiic_fill_tx_fifo(struct xiic_i2c *i2c) /* last message in transfer -> STOP */ data |= XIIC_TX_DYN_STOP_MASK; dev_dbg(i2c->adap.dev.parent, "%s TX STOP\n", __func__); - - xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET, data); - } else - xiic_setreg8(i2c, XIIC_DTR_REG_OFFSET, data); + } + xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET, data); } } diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c index 014504d8e43..37678536442 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c @@ -755,9 +755,13 @@ void ipoib_cm_send(struct net_device *dev, struct sk_buff *skb, struct ipoib_cm_ if (++priv->tx_outstanding == ipoib_sendq_size) { ipoib_dbg(priv, "TX ring 0x%x full, stopping kernel net queue\n", tx->qp->qp_num); - if (ib_req_notify_cq(priv->send_cq, IB_CQ_NEXT_COMP)) - ipoib_warn(priv, "request notify on send CQ failed\n"); netif_stop_queue(dev); + rc = ib_req_notify_cq(priv->send_cq, + IB_CQ_NEXT_COMP | IB_CQ_REPORT_MISSED_EVENTS); + if (rc < 0) + ipoib_warn(priv, "request notify on send CQ failed\n"); + else if (rc) + ipoib_send_comp_handler(priv->send_cq, dev); } } } diff --git a/drivers/input/touchscreen/cyttsp_core.c b/drivers/input/touchscreen/cyttsp_core.c index f030d9ec795..3f505d5e848 100644 --- a/drivers/input/touchscreen/cyttsp_core.c +++ b/drivers/input/touchscreen/cyttsp_core.c @@ -133,7 +133,7 @@ static int cyttsp_exit_bl_mode(struct cyttsp *ts) memcpy(bl_cmd, bl_command, sizeof(bl_command)); if (ts->pdata->bl_keys) memcpy(&bl_cmd[sizeof(bl_command) - CY_NUM_BL_KEYS], - ts->pdata->bl_keys, sizeof(bl_command)); + ts->pdata->bl_keys, CY_NUM_BL_KEYS); error = ttsp_write_block_data(ts, CY_REG_BASE, sizeof(bl_cmd), bl_cmd); diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 57ed244cf99..c0536eda58e 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -531,11 +531,23 @@ static void iommu_print_event(struct amd_iommu *iommu, void *__evt) static void iommu_poll_events(struct amd_iommu *iommu) { - u32 head, tail; + u32 head, tail, status; unsigned long flags; spin_lock_irqsave(&iommu->lock, flags); + /* enable event interrupts again */ + do { + /* + * Workaround for Erratum ERBT1312 + * Clearing the EVT_INT bit may race in the hardware, so read + * it again and make sure it was really cleared + */ + status = readl(iommu->mmio_base + MMIO_STATUS_OFFSET); + writel(MMIO_STATUS_EVT_INT_MASK, + iommu->mmio_base + MMIO_STATUS_OFFSET); + } while (status & MMIO_STATUS_EVT_INT_MASK); + head = readl(iommu->mmio_base + MMIO_EVT_HEAD_OFFSET); tail = readl(iommu->mmio_base + MMIO_EVT_TAIL_OFFSET); @@ -572,16 +584,25 @@ static void iommu_handle_ppr_entry(struct amd_iommu *iommu, u64 *raw) static void iommu_poll_ppr_log(struct amd_iommu *iommu) { unsigned long flags; - u32 head, tail; + u32 head, tail, status; if (iommu->ppr_log == NULL) return; - /* enable ppr interrupts again */ - writel(MMIO_STATUS_PPR_INT_MASK, iommu->mmio_base + MMIO_STATUS_OFFSET); - spin_lock_irqsave(&iommu->lock, flags); + /* enable ppr interrupts again */ + do { + /* + * Workaround for Erratum ERBT1312 + * Clearing the PPR_INT bit may race in the hardware, so read + * it again and make sure it was really cleared + */ + status = readl(iommu->mmio_base + MMIO_STATUS_OFFSET); + writel(MMIO_STATUS_PPR_INT_MASK, + iommu->mmio_base + MMIO_STATUS_OFFSET); + } while (status & MMIO_STATUS_PPR_INT_MASK); + head = readl(iommu->mmio_base + MMIO_PPR_HEAD_OFFSET); tail = readl(iommu->mmio_base + MMIO_PPR_TAIL_OFFSET); @@ -1288,6 +1309,10 @@ static unsigned long iommu_unmap_page(struct protection_domain *dom, /* Large PTE found which maps this address */ unmap_size = PTE_PAGE_SIZE(*pte); + + /* Only unmap from the first pte in the page */ + if ((unmap_size - 1) & bus_addr) + break; count = PAGE_SIZE_PTE_COUNT(unmap_size); for (i = 0; i < count; i++) pte[i] = 0ULL; @@ -1297,7 +1322,7 @@ static unsigned long iommu_unmap_page(struct protection_domain *dom, unmapped += unmap_size; } - BUG_ON(!is_power_of_2(unmapped)); + BUG_ON(unmapped && !is_power_of_2(unmapped)); return unmapped; } @@ -2270,18 +2295,16 @@ static int device_change_notifier(struct notifier_block *nb, /* allocate a protection domain if a device is added */ dma_domain = find_protection_domain(devid); - if (dma_domain) - goto out; - dma_domain = dma_ops_domain_alloc(); - if (!dma_domain) - goto out; - dma_domain->target_dev = devid; - - spin_lock_irqsave(&iommu_pd_list_lock, flags); - list_add_tail(&dma_domain->list, &iommu_pd_list); - spin_unlock_irqrestore(&iommu_pd_list_lock, flags); - - dev_data = get_dev_data(dev); + if (!dma_domain) { + dma_domain = dma_ops_domain_alloc(); + if (!dma_domain) + goto out; + dma_domain->target_dev = devid; + + spin_lock_irqsave(&iommu_pd_list_lock, flags); + list_add_tail(&dma_domain->list, &iommu_pd_list); + spin_unlock_irqrestore(&iommu_pd_list_lock, flags); + } dev->archdata.dma_ops = &amd_iommu_dma_ops; diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index ef0ae93500f..b573f803d84 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c @@ -1572,8 +1572,6 @@ int __init amd_iommu_init_hardware(void) if (amd_iommu_pd_alloc_bitmap == NULL) goto free; - /* init the device table */ - init_device_table(); /* * let all alias entries point to itself @@ -1655,6 +1653,7 @@ static int amd_iommu_enable_interrupts(void) */ static int __init amd_iommu_init(void) { + struct amd_iommu *iommu; int ret = 0; ret = amd_iommu_init_hardware(); @@ -1673,6 +1672,12 @@ static int __init amd_iommu_init(void) if (ret) goto free; + /* init the device table */ + init_device_table(); + + for_each_iommu(iommu) + iommu_flush_all_caches(iommu); + amd_iommu_init_api(); x86_platform.iommu_shutdown = disable_iommus; diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h index 24355559a2a..c4ffacb033f 100644 --- a/drivers/iommu/amd_iommu_types.h +++ b/drivers/iommu/amd_iommu_types.h @@ -99,6 +99,7 @@ #define PASID_MASK 0x000fffff /* MMIO status bits */ +#define MMIO_STATUS_EVT_INT_MASK (1 << 1) #define MMIO_STATUS_COM_WAIT_INT_MASK (1 << 2) #define MMIO_STATUS_PPR_INT_MASK (1 << 6) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 5d71873c6f6..17119247ac4 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -4212,13 +4212,19 @@ static void __devinit quirk_iommu_rwbf(struct pci_dev *dev) { /* * Mobile 4 Series Chipset neglects to set RWBF capability, - * but needs it: + * but needs it. Same seems to hold for the desktop versions. */ printk(KERN_INFO "DMAR: Forcing write-buffer flush capability\n"); rwbf_quirk = 1; } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_rwbf); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e00, quirk_iommu_rwbf); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e10, quirk_iommu_rwbf); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e20, quirk_iommu_rwbf); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e30, quirk_iommu_rwbf); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e40, quirk_iommu_rwbf); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e90, quirk_iommu_rwbf); #define GGC 0x52 #define GGC_MEMORY_SIZE_MASK (0xf << 8) diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c index 579aa021a65..be22d5ee8e0 100644 --- a/drivers/isdn/gigaset/capi.c +++ b/drivers/isdn/gigaset/capi.c @@ -264,6 +264,8 @@ static inline void dump_rawmsg(enum debuglevel level, const char *tag, CAPIMSG_APPID(data), CAPIMSG_MSGID(data), l, CAPIMSG_CONTROL(data)); l -= 12; + if (l <= 0) + return; dbgline = kmalloc(3 * l, GFP_ATOMIC); if (!dbgline) return; diff --git a/drivers/leds/leds-ot200.c b/drivers/leds/leds-ot200.c index c4646825a62..676e729fe47 100644 --- a/drivers/leds/leds-ot200.c +++ b/drivers/leds/leds-ot200.c @@ -47,37 +47,37 @@ static struct ot200_led leds[] = { { .name = "led_1", .port = 0x49, - .mask = BIT(7), + .mask = BIT(6), }, { .name = "led_2", .port = 0x49, - .mask = BIT(6), + .mask = BIT(5), }, { .name = "led_3", .port = 0x49, - .mask = BIT(5), + .mask = BIT(4), }, { .name = "led_4", .port = 0x49, - .mask = BIT(4), + .mask = BIT(3), }, { .name = "led_5", .port = 0x49, - .mask = BIT(3), + .mask = BIT(2), }, { .name = "led_6", .port = 0x49, - .mask = BIT(2), + .mask = BIT(1), }, { .name = "led_7", .port = 0x49, - .mask = BIT(1), + .mask = BIT(0), } }; diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index 6f758870fc1..ff62ddc660d 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c @@ -1117,6 +1117,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) s->pending_pool = mempool_create_slab_pool(MIN_IOS, pending_cache); if (!s->pending_pool) { ti->error = "Could not allocate mempool for pending exceptions"; + r = -ENOMEM; goto bad_pending_pool; } diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c index eb3d138ff55..79b7b715e6c 100644 --- a/drivers/md/dm-thin.c +++ b/drivers/md/dm-thin.c @@ -2023,6 +2023,7 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv) * thin devices' discard limits consistent). */ ti->discards_supported = 1; + ti->discard_zeroes_data_unsupported = 1; } ti->private = pt; @@ -2439,7 +2440,6 @@ static void set_discard_limits(struct pool *pool, struct queue_limits *limits) * bios that overlap 2 blocks. */ limits->discard_granularity = pool->sectors_per_block << SECTOR_SHIFT; - limits->discard_zeroes_data = pool->pf.zero_new_blocks; } static void pool_io_hints(struct dm_target *ti, struct queue_limits *limits) diff --git a/drivers/md/dm-verity.c b/drivers/md/dm-verity.c index fa365d39b61..1f1b4a47ee4 100644 --- a/drivers/md/dm-verity.c +++ b/drivers/md/dm-verity.c @@ -813,9 +813,8 @@ static int verity_ctr(struct dm_target *ti, unsigned argc, char **argv) for (i = v->levels - 1; i >= 0; i--) { sector_t s; v->hash_level_block[i] = hash_position; - s = verity_position_at_level(v, v->data_blocks, i); - s = (s >> v->hash_per_block_bits) + - !!(s & ((1 << v->hash_per_block_bits) - 1)); + s = (v->data_blocks + ((sector_t)1 << ((i + 1) * v->hash_per_block_bits)) - 1) + >> ((i + 1) * v->hash_per_block_bits); if (hash_position + s < hash_position) { ti->error = "Hash device offset overflow"; r = -E2BIG; diff --git a/drivers/md/md.c b/drivers/md/md.c index 2b30ffdb81b..69c616f2ae5 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -1580,8 +1580,8 @@ static int super_1_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor_ sector, count, 1) == 0) return -EINVAL; } - } else if (sb->bblog_offset == 0) - rdev->badblocks.shift = -1; + } else if (sb->bblog_offset != 0) + rdev->badblocks.shift = 0; if (!refdev) { ret = 1; @@ -3097,7 +3097,7 @@ int md_rdev_init(struct md_rdev *rdev) * be used - I wonder if that matters */ rdev->badblocks.count = 0; - rdev->badblocks.shift = 0; + rdev->badblocks.shift = -1; /* disabled until explicitly enabled */ rdev->badblocks.page = kmalloc(PAGE_SIZE, GFP_KERNEL); seqlock_init(&rdev->badblocks.lock); if (rdev->badblocks.page == NULL) @@ -3169,9 +3169,6 @@ static struct md_rdev *md_import_device(dev_t newdev, int super_format, int supe goto abort_free; } } - if (super_format == -1) - /* hot-add for 0.90, or non-persistent: so no badblocks */ - rdev->badblocks.shift = -1; return rdev; diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 15dd59b84e9..ce36dee6b16 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -413,7 +413,17 @@ static void raid1_end_write_request(struct bio *bio, int error) r1_bio->bios[mirror] = NULL; to_put = bio; - set_bit(R1BIO_Uptodate, &r1_bio->state); + /* + * Do not set R1BIO_Uptodate if the current device is + * rebuilding or Faulty. This is because we cannot use + * such device for properly reading the data back (we could + * potentially use it, if the current write would have felt + * before rdev->recovery_offset, but for simplicity we don't + * check this here. + */ + if (test_bit(In_sync, &conf->mirrors[mirror].rdev->flags) && + !test_bit(Faulty, &conf->mirrors[mirror].rdev->flags)) + set_bit(R1BIO_Uptodate, &r1_bio->state); /* Maybe we can clear some bad blocks. */ if (is_badblock(conf->mirrors[mirror].rdev, @@ -802,17 +812,17 @@ static void allow_barrier(struct r1conf *conf) wake_up(&conf->wait_barrier); } -static void freeze_array(struct r1conf *conf) +static void freeze_array(struct r1conf *conf, int extra) { /* stop syncio and normal IO and wait for everything to * go quite. * We increment barrier and nr_waiting, and then - * wait until nr_pending match nr_queued+1 + * wait until nr_pending match nr_queued+extra * This is called in the context of one normal IO request * that has failed. Thus any sync request that might be pending * will be blocked by nr_pending, and we need to wait for * pending IO requests to complete or be queued for re-try. - * Thus the number queued (nr_queued) plus this request (1) + * Thus the number queued (nr_queued) plus this request (extra) * must match the number of pending IOs (nr_pending) before * we continue. */ @@ -820,7 +830,7 @@ static void freeze_array(struct r1conf *conf) conf->barrier++; conf->nr_waiting++; wait_event_lock_irq(conf->wait_barrier, - conf->nr_pending == conf->nr_queued+1, + conf->nr_pending == conf->nr_queued+extra, conf->resync_lock, flush_pending_writes(conf)); spin_unlock_irq(&conf->resync_lock); @@ -1422,8 +1432,8 @@ static int raid1_add_disk(struct mddev *mddev, struct md_rdev *rdev) * we wait for all outstanding requests to complete. */ synchronize_sched(); - raise_barrier(conf); - lower_barrier(conf); + freeze_array(conf, 0); + unfreeze_array(conf); clear_bit(Unmerged, &rdev->flags); } md_integrity_add_rdev(rdev, mddev); @@ -1471,11 +1481,11 @@ static int raid1_remove_disk(struct mddev *mddev, struct md_rdev *rdev) */ struct md_rdev *repl = conf->mirrors[conf->raid_disks + number].rdev; - raise_barrier(conf); + freeze_array(conf, 0); clear_bit(Replacement, &repl->flags); p->rdev = repl; conf->mirrors[conf->raid_disks + number].rdev = NULL; - lower_barrier(conf); + unfreeze_array(conf); clear_bit(WantReplacement, &rdev->flags); } else clear_bit(WantReplacement, &rdev->flags); @@ -2084,7 +2094,7 @@ static void handle_read_error(struct r1conf *conf, struct r1bio *r1_bio) * frozen */ if (mddev->ro == 0) { - freeze_array(conf); + freeze_array(conf, 1); fix_read_error(conf, r1_bio->read_disk, r1_bio->sector, r1_bio->sectors); unfreeze_array(conf); @@ -2831,7 +2841,7 @@ static int raid1_reshape(struct mddev *mddev) return -ENOMEM; } - raise_barrier(conf); + freeze_array(conf, 0); /* ok, everything is stopped */ oldpool = conf->r1bio_pool; @@ -2863,7 +2873,7 @@ static int raid1_reshape(struct mddev *mddev) mddev->delta_disks = 0; conf->last_used = 0; /* just make sure it is in-range */ - lower_barrier(conf); + unfreeze_array(conf); set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); md_wakeup_thread(mddev->thread); diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 3f91c2e1dfe..dd6d1faaa03 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -452,7 +452,17 @@ static void raid10_end_write_request(struct bio *bio, int error) sector_t first_bad; int bad_sectors; - set_bit(R10BIO_Uptodate, &r10_bio->state); + /* + * Do not set R10BIO_Uptodate if the current device is + * rebuilding or Faulty. This is because we cannot use + * such device for properly reading the data back (we could + * potentially use it, if the current write would have felt + * before rdev->recovery_offset, but for simplicity we don't + * check this here. + */ + if (test_bit(In_sync, &rdev->flags) && + !test_bit(Faulty, &rdev->flags)) + set_bit(R10BIO_Uptodate, &r10_bio->state); /* Maybe we can clear some bad blocks. */ if (is_badblock(rdev, @@ -938,17 +948,17 @@ static void allow_barrier(struct r10conf *conf) wake_up(&conf->wait_barrier); } -static void freeze_array(struct r10conf *conf) +static void freeze_array(struct r10conf *conf, int extra) { /* stop syncio and normal IO and wait for everything to * go quiet. * We increment barrier and nr_waiting, and then - * wait until nr_pending match nr_queued+1 + * wait until nr_pending match nr_queued+extra * This is called in the context of one normal IO request * that has failed. Thus any sync request that might be pending * will be blocked by nr_pending, and we need to wait for * pending IO requests to complete or be queued for re-try. - * Thus the number queued (nr_queued) plus this request (1) + * Thus the number queued (nr_queued) plus this request (extra) * must match the number of pending IOs (nr_pending) before * we continue. */ @@ -956,7 +966,7 @@ static void freeze_array(struct r10conf *conf) conf->barrier++; conf->nr_waiting++; wait_event_lock_irq(conf->wait_barrier, - conf->nr_pending == conf->nr_queued+1, + conf->nr_pending == conf->nr_queued+extra, conf->resync_lock, flush_pending_writes(conf)); @@ -1599,8 +1609,8 @@ static int raid10_add_disk(struct mddev *mddev, struct md_rdev *rdev) * we wait for all outstanding requests to complete. */ synchronize_sched(); - raise_barrier(conf, 0); - lower_barrier(conf); + freeze_array(conf, 0); + unfreeze_array(conf); clear_bit(Unmerged, &rdev->flags); } md_integrity_add_rdev(rdev, mddev); @@ -2009,12 +2019,18 @@ static void recovery_request_write(struct mddev *mddev, struct r10bio *r10_bio) d = r10_bio->devs[1].devnum; wbio = r10_bio->devs[1].bio; wbio2 = r10_bio->devs[1].repl_bio; + /* Need to test wbio2->bi_end_io before we call + * generic_make_request as if the former is NULL, + * the latter is free to free wbio2. + */ + if (wbio2 && !wbio2->bi_end_io) + wbio2 = NULL; if (wbio->bi_end_io) { atomic_inc(&conf->mirrors[d].rdev->nr_pending); md_sync_acct(conf->mirrors[d].rdev->bdev, wbio->bi_size >> 9); generic_make_request(wbio); } - if (wbio2 && wbio2->bi_end_io) { + if (wbio2) { atomic_inc(&conf->mirrors[d].replacement->nr_pending); md_sync_acct(conf->mirrors[d].replacement->bdev, wbio2->bi_size >> 9); @@ -2384,7 +2400,7 @@ static void handle_read_error(struct mddev *mddev, struct r10bio *r10_bio) r10_bio->devs[slot].bio = NULL; if (mddev->ro == 0) { - freeze_array(conf); + freeze_array(conf, 1); fix_read_error(conf, mddev, r10_bio); unfreeze_array(conf); } else diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index f351422938e..946c5978596 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -3314,6 +3314,7 @@ static void handle_stripe(struct stripe_head *sh) if (test_and_clear_bit(STRIPE_SYNC_REQUESTED, &sh->state)) { set_bit(STRIPE_SYNCING, &sh->state); clear_bit(STRIPE_INSYNC, &sh->state); + clear_bit(STRIPE_REPLACED, &sh->state); } clear_bit(STRIPE_DELAYED, &sh->state); @@ -3453,19 +3454,23 @@ static void handle_stripe(struct stripe_head *sh) handle_parity_checks5(conf, sh, &s, disks); } - if (s.replacing && s.locked == 0 - && !test_bit(STRIPE_INSYNC, &sh->state)) { + if ((s.replacing || s.syncing) && s.locked == 0 + && !test_bit(STRIPE_COMPUTE_RUN, &sh->state) + && !test_bit(STRIPE_REPLACED, &sh->state)) { /* Write out to replacement devices where possible */ for (i = 0; i < conf->raid_disks; i++) - if (test_bit(R5_UPTODATE, &sh->dev[i].flags) && - test_bit(R5_NeedReplace, &sh->dev[i].flags)) { + if (test_bit(R5_NeedReplace, &sh->dev[i].flags)) { + WARN_ON(!test_bit(R5_UPTODATE, &sh->dev[i].flags)); set_bit(R5_WantReplace, &sh->dev[i].flags); set_bit(R5_LOCKED, &sh->dev[i].flags); s.locked++; } - set_bit(STRIPE_INSYNC, &sh->state); + if (s.replacing) + set_bit(STRIPE_INSYNC, &sh->state); + set_bit(STRIPE_REPLACED, &sh->state); } if ((s.syncing || s.replacing) && s.locked == 0 && + !test_bit(STRIPE_COMPUTE_RUN, &sh->state) && test_bit(STRIPE_INSYNC, &sh->state)) { md_done_sync(conf->mddev, STRIPE_SECTORS, 1); clear_bit(STRIPE_SYNCING, &sh->state); diff --git a/drivers/md/raid5.h b/drivers/md/raid5.h index 8d8e13934a4..f1ed18e54db 100644 --- a/drivers/md/raid5.h +++ b/drivers/md/raid5.h @@ -306,6 +306,7 @@ enum { STRIPE_SYNC_REQUESTED, STRIPE_SYNCING, STRIPE_INSYNC, + STRIPE_REPLACED, STRIPE_PREREAD_ACTIVE, STRIPE_DELAYED, STRIPE_DEGRADED, diff --git a/drivers/media/dvb/mantis/mantis_dvb.c b/drivers/media/dvb/mantis/mantis_dvb.c index e5180e45d31..5d15c6b74d9 100644 --- a/drivers/media/dvb/mantis/mantis_dvb.c +++ b/drivers/media/dvb/mantis/mantis_dvb.c @@ -248,8 +248,10 @@ int __devinit mantis_dvb_init(struct mantis_pci *mantis) err5: tasklet_kill(&mantis->tasklet); dvb_net_release(&mantis->dvbnet); - dvb_unregister_frontend(mantis->fe); - dvb_frontend_detach(mantis->fe); + if (mantis->fe) { + dvb_unregister_frontend(mantis->fe); + dvb_frontend_detach(mantis->fe); + } err4: mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem); diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c index cabc19c1051..cec1f8c05e6 100644 --- a/drivers/media/rc/rc-main.c +++ b/drivers/media/rc/rc-main.c @@ -778,8 +778,10 @@ static ssize_t show_protocols(struct device *device, } else if (dev->raw) { enabled = dev->raw->enabled_protocols; allowed = ir_raw_get_allowed_protocols(); - } else + } else { + mutex_unlock(&dev->lock); return -ENODEV; + } IR_dprintk(1, "allowed - 0x%llx, enabled - 0x%llx\n", (long long)allowed, diff --git a/drivers/mfd/adp5520.c b/drivers/mfd/adp5520.c index 8d816cce832..105f820826c 100644 --- a/drivers/mfd/adp5520.c +++ b/drivers/mfd/adp5520.c @@ -36,6 +36,7 @@ struct adp5520_chip { struct blocking_notifier_head notifier_list; int irq; unsigned long id; + uint8_t mode; }; static int __adp5520_read(struct i2c_client *client, @@ -326,7 +327,10 @@ static int adp5520_suspend(struct device *dev) struct i2c_client *client = to_i2c_client(dev); struct adp5520_chip *chip = dev_get_drvdata(&client->dev); - adp5520_clr_bits(chip->dev, ADP5520_MODE_STATUS, ADP5520_nSTNBY); + adp5520_read(chip->dev, ADP5520_MODE_STATUS, &chip->mode); + /* All other bits are W1C */ + chip->mode &= ADP5520_BL_EN | ADP5520_DIM_EN | ADP5520_nSTNBY; + adp5520_write(chip->dev, ADP5520_MODE_STATUS, 0); return 0; } @@ -335,7 +339,7 @@ static int adp5520_resume(struct device *dev) struct i2c_client *client = to_i2c_client(dev); struct adp5520_chip *chip = dev_get_drvdata(&client->dev); - adp5520_set_bits(chip->dev, ADP5520_MODE_STATUS, ADP5520_nSTNBY); + adp5520_write(chip->dev, ADP5520_MODE_STATUS, chip->mode); return 0; } #endif diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index dc4b1255ca3..ae7cd4438af 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -369,13 +369,13 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) ext_csd[EXT_CSD_SEC_FEATURE_SUPPORT]; card->ext_csd.raw_trim_mult = ext_csd[EXT_CSD_TRIM_MULT]; + card->ext_csd.raw_partition_support = ext_csd[EXT_CSD_PARTITION_SUPPORT]; if (card->ext_csd.rev >= 4) { /* * Enhanced area feature support -- check whether the eMMC * card has the Enhanced area enabled. If so, export enhanced * area offset and size to user by adding sysfs interface. */ - card->ext_csd.raw_partition_support = ext_csd[EXT_CSD_PARTITION_SUPPORT]; if ((ext_csd[EXT_CSD_PARTITION_SUPPORT] & 0x2) && (ext_csd[EXT_CSD_PARTITION_ATTRIBUTE] & 0x1)) { hc_erase_grp_sz = diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index da3812266aa..73359a1e89d 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -297,16 +297,6 @@ config MMC_ATMELMCI endchoice -config MMC_ATMELMCI_DMA - bool "Atmel MCI DMA support" - depends on MMC_ATMELMCI && (AVR32 || ARCH_AT91SAM9G45) && DMA_ENGINE - help - Say Y here to have the Atmel MCI driver use a DMA engine to - do data transfers and thus increase the throughput and - reduce the CPU utilization. - - If unsure, say N. - config MMC_IMX tristate "Motorola i.MX Multimedia Card Interface support" depends on ARCH_MX1 diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index e94476beca1..2a822d9e468 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -165,6 +165,7 @@ struct atmel_mci { void __iomem *regs; struct scatterlist *sg; + unsigned int sg_len; unsigned int pio_offset; struct atmel_mci_slot *cur_slot; @@ -754,6 +755,7 @@ static u32 atmci_prepare_data(struct atmel_mci *host, struct mmc_data *data) data->error = -EINPROGRESS; host->sg = data->sg; + host->sg_len = data->sg_len; host->data = data; host->data_chan = NULL; @@ -1592,7 +1594,8 @@ static void atmci_read_data_pio(struct atmel_mci *host) if (offset == sg->length) { flush_dcache_page(sg_page(sg)); host->sg = sg = sg_next(sg); - if (!sg) + host->sg_len--; + if (!sg || !host->sg_len) goto done; offset = 0; @@ -1605,7 +1608,8 @@ static void atmci_read_data_pio(struct atmel_mci *host) flush_dcache_page(sg_page(sg)); host->sg = sg = sg_next(sg); - if (!sg) + host->sg_len--; + if (!sg || !host->sg_len) goto done; offset = 4 - remaining; @@ -1659,7 +1663,8 @@ static void atmci_write_data_pio(struct atmel_mci *host) nbytes += 4; if (offset == sg->length) { host->sg = sg = sg_next(sg); - if (!sg) + host->sg_len--; + if (!sg || !host->sg_len) goto done; offset = 0; @@ -1673,7 +1678,8 @@ static void atmci_write_data_pio(struct atmel_mci *host) nbytes += remaining; host->sg = sg = sg_next(sg); - if (!sg) { + host->sg_len--; + if (!sg || !host->sg_len) { atmci_writel(host, ATMCI_TDR, value); goto done; } @@ -2190,10 +2196,8 @@ static int __exit atmci_remove(struct platform_device *pdev) atmci_readl(host, ATMCI_SR); clk_disable(host->mck); -#ifdef CONFIG_MMC_ATMELMCI_DMA if (host->dma.chan) dma_release_channel(host->dma.chan); -#endif free_irq(platform_get_irq(pdev, 0), host); iounmap(host->regs); diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c index 8abdaf6697a..be46052228b 100644 --- a/drivers/mmc/host/sdhci-esdhc-imx.c +++ b/drivers/mmc/host/sdhci-esdhc-imx.c @@ -232,15 +232,18 @@ static void esdhc_writel_le(struct sdhci_host *host, u32 val, int reg) static u16 esdhc_readw_le(struct sdhci_host *host, int reg) { + struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct pltfm_imx_data *imx_data = pltfm_host->priv; + if (unlikely(reg == SDHCI_HOST_VERSION)) { - u16 val = readw(host->ioaddr + (reg ^ 2)); - /* - * uSDHC supports SDHCI v3.0, but it's encoded as value - * 0x3 in host controller version register, which violates - * SDHCI_SPEC_300 definition. Work it around here. - */ - if ((val & SDHCI_SPEC_VER_MASK) == 3) - return --val; + reg ^= 2; + if (is_imx6q_usdhc(imx_data)) { + /* + * The usdhc register returns a wrong host version. + * Correct it here. + */ + return SDHCI_SPEC_300; + } } return readw(host->ioaddr + reg); diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c index 4e12bb7e317..529c08c4baf 100644 --- a/drivers/mtd/mtdchar.c +++ b/drivers/mtd/mtdchar.c @@ -1127,6 +1127,33 @@ static unsigned long mtdchar_get_unmapped_area(struct file *file, } #endif +static inline unsigned long get_vm_size(struct vm_area_struct *vma) +{ + return vma->vm_end - vma->vm_start; +} + +static inline resource_size_t get_vm_offset(struct vm_area_struct *vma) +{ + return (resource_size_t) vma->vm_pgoff << PAGE_SHIFT; +} + +/* + * Set a new vm offset. + * + * Verify that the incoming offset really works as a page offset, + * and that the offset and size fit in a resource_size_t. + */ +static inline int set_vm_offset(struct vm_area_struct *vma, resource_size_t off) +{ + pgoff_t pgoff = off >> PAGE_SHIFT; + if (off != (resource_size_t) pgoff << PAGE_SHIFT) + return -EINVAL; + if (off + get_vm_size(vma) - 1 < off) + return -EINVAL; + vma->vm_pgoff = pgoff; + return 0; +} + /* * set up a mapping for shared memory segments */ @@ -1136,32 +1163,17 @@ static int mtdchar_mmap(struct file *file, struct vm_area_struct *vma) struct mtd_file_info *mfi = file->private_data; struct mtd_info *mtd = mfi->mtd; struct map_info *map = mtd->priv; - unsigned long start; - unsigned long off; - u32 len; - - if (mtd->type == MTD_RAM || mtd->type == MTD_ROM) { - off = vma->vm_pgoff << PAGE_SHIFT; - start = map->phys; - len = PAGE_ALIGN((start & ~PAGE_MASK) + map->size); - start &= PAGE_MASK; - if ((vma->vm_end - vma->vm_start + off) > len) - return -EINVAL; - - off += start; - vma->vm_pgoff = off >> PAGE_SHIFT; - vma->vm_flags |= VM_IO | VM_RESERVED; + /* This is broken because it assumes the MTD device is map-based + and that mtd->priv is a valid struct map_info. It should be + replaced with something that uses the mtd_get_unmapped_area() + operation properly. */ + if (0 /*mtd->type == MTD_RAM || mtd->type == MTD_ROM*/) { #ifdef pgprot_noncached - if (file->f_flags & O_DSYNC || off >= __pa(high_memory)) + if (file->f_flags & O_DSYNC || map->phys >= __pa(high_memory)) vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); #endif - if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, - vma->vm_end - vma->vm_start, - vma->vm_page_prot)) - return -EAGAIN; - - return 0; + return vm_iomap_memory(vma, map->phys, map->size); } return -ENOSYS; #else diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c index a746ba272f0..a956053608f 100644 --- a/drivers/net/arcnet/arcnet.c +++ b/drivers/net/arcnet/arcnet.c @@ -1007,7 +1007,7 @@ static void arcnet_rx(struct net_device *dev, int bufnum) soft = &pkt.soft.rfc1201; - lp->hw.copy_from_card(dev, bufnum, 0, &pkt, sizeof(ARC_HDR_SIZE)); + lp->hw.copy_from_card(dev, bufnum, 0, &pkt, ARC_HDR_SIZE); if (pkt.hard.offset[0]) { ofs = pkt.hard.offset[0]; length = 256 - ofs; diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index 2e1f8066f1a..b6ed7e9bbb8 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c @@ -704,6 +704,12 @@ static struct slave *rlb_arp_xmit(struct sk_buff *skb, struct bonding *bond) struct arp_pkt *arp = arp_pkt(skb); struct slave *tx_slave = NULL; + /* Don't modify or load balance ARPs that do not originate locally + * (e.g.,arrive via a bridge). + */ + if (!bond_slave_has_mac(bond, arp->mac_src)) + return NULL; + if (arp->op_code == htons(ARPOP_REPLY)) { /* the arp must be sent on the selected * rx channel diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 6df52c9ba49..d9f83582997 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1737,6 +1737,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) bond_compute_features(bond); + bond_update_speed_duplex(new_slave); + read_lock(&bond->lock); new_slave->last_arp_rx = jiffies; @@ -1780,8 +1782,6 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) new_slave->link = BOND_LINK_DOWN; } - bond_update_speed_duplex(new_slave); - if (USES_PRIMARY(bond->params.mode) && bond->params.primary[0]) { /* if there is a primary slave, remember it */ if (strcmp(bond->params.primary, new_slave->dev->name) == 0) { @@ -1888,6 +1888,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) write_unlock_bh(&bond->lock); err_close: + slave_dev->priv_flags &= ~IFF_BONDING; dev_close(slave_dev); err_unset_master: @@ -1956,12 +1957,11 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) return -EINVAL; } + write_unlock_bh(&bond->lock); /* unregister rx_handler early so bond_handle_frame wouldn't be called * for this slave anymore. */ netdev_rx_handler_unregister(slave_dev); - write_unlock_bh(&bond->lock); - synchronize_net(); write_lock_bh(&bond->lock); if (!bond->params.fail_over_mac) { @@ -2462,8 +2462,6 @@ static void bond_miimon_commit(struct bonding *bond) bond_set_backup_slave(slave); } - bond_update_speed_duplex(slave); - pr_info("%s: link status definitely up for interface %s, %u Mbps %s duplex.\n", bond->dev->name, slave->dev->name, slave->speed, slave->duplex ? "full" : "half"); @@ -3400,6 +3398,28 @@ static int bond_xmit_hash_policy_l2(struct sk_buff *skb, int count) /*-------------------------- Device entry points ----------------------------*/ +static void bond_work_init_all(struct bonding *bond) +{ + INIT_DELAYED_WORK(&bond->mcast_work, + bond_resend_igmp_join_requests_delayed); + INIT_DELAYED_WORK(&bond->alb_work, bond_alb_monitor); + INIT_DELAYED_WORK(&bond->mii_work, bond_mii_monitor); + if (bond->params.mode == BOND_MODE_ACTIVEBACKUP) + INIT_DELAYED_WORK(&bond->arp_work, bond_activebackup_arp_mon); + else + INIT_DELAYED_WORK(&bond->arp_work, bond_loadbalance_arp_mon); + INIT_DELAYED_WORK(&bond->ad_work, bond_3ad_state_machine_handler); +} + +static void bond_work_cancel_all(struct bonding *bond) +{ + cancel_delayed_work_sync(&bond->mii_work); + cancel_delayed_work_sync(&bond->arp_work); + cancel_delayed_work_sync(&bond->alb_work); + cancel_delayed_work_sync(&bond->ad_work); + cancel_delayed_work_sync(&bond->mcast_work); +} + static int bond_open(struct net_device *bond_dev) { struct bonding *bond = netdev_priv(bond_dev); @@ -3422,41 +3442,27 @@ static int bond_open(struct net_device *bond_dev) } read_unlock(&bond->lock); - INIT_DELAYED_WORK(&bond->mcast_work, bond_resend_igmp_join_requests_delayed); + bond_work_init_all(bond); if (bond_is_lb(bond)) { /* bond_alb_initialize must be called before the timer * is started. */ - if (bond_alb_initialize(bond, (bond->params.mode == BOND_MODE_ALB))) { - /* something went wrong - fail the open operation */ + if (bond_alb_initialize(bond, (bond->params.mode == BOND_MODE_ALB))) return -ENOMEM; - } - - INIT_DELAYED_WORK(&bond->alb_work, bond_alb_monitor); queue_delayed_work(bond->wq, &bond->alb_work, 0); } - if (bond->params.miimon) { /* link check interval, in milliseconds. */ - INIT_DELAYED_WORK(&bond->mii_work, bond_mii_monitor); + if (bond->params.miimon) /* link check interval, in milliseconds. */ queue_delayed_work(bond->wq, &bond->mii_work, 0); - } if (bond->params.arp_interval) { /* arp interval, in milliseconds. */ - if (bond->params.mode == BOND_MODE_ACTIVEBACKUP) - INIT_DELAYED_WORK(&bond->arp_work, - bond_activebackup_arp_mon); - else - INIT_DELAYED_WORK(&bond->arp_work, - bond_loadbalance_arp_mon); - queue_delayed_work(bond->wq, &bond->arp_work, 0); if (bond->params.arp_validate) bond->recv_probe = bond_arp_rcv; } if (bond->params.mode == BOND_MODE_8023AD) { - INIT_DELAYED_WORK(&bond->ad_work, bond_3ad_state_machine_handler); queue_delayed_work(bond->wq, &bond->ad_work, 0); /* register to receive LACPDUs */ bond->recv_probe = bond_3ad_lacpdu_recv; @@ -3471,34 +3477,10 @@ static int bond_close(struct net_device *bond_dev) struct bonding *bond = netdev_priv(bond_dev); write_lock_bh(&bond->lock); - bond->send_peer_notif = 0; - write_unlock_bh(&bond->lock); - if (bond->params.miimon) { /* link check interval, in milliseconds. */ - cancel_delayed_work_sync(&bond->mii_work); - } - - if (bond->params.arp_interval) { /* arp interval, in milliseconds. */ - cancel_delayed_work_sync(&bond->arp_work); - } - - switch (bond->params.mode) { - case BOND_MODE_8023AD: - cancel_delayed_work_sync(&bond->ad_work); - break; - case BOND_MODE_TLB: - case BOND_MODE_ALB: - cancel_delayed_work_sync(&bond->alb_work); - break; - default: - break; - } - - if (delayed_work_pending(&bond->mcast_work)) - cancel_delayed_work_sync(&bond->mcast_work); - + bond_work_cancel_all(bond); if (bond_is_lb(bond)) { /* Must be called only after all * slaves have been released @@ -4377,26 +4359,6 @@ static void bond_setup(struct net_device *bond_dev) bond_dev->features |= bond_dev->hw_features; } -static void bond_work_cancel_all(struct bonding *bond) -{ - if (bond->params.miimon && delayed_work_pending(&bond->mii_work)) - cancel_delayed_work_sync(&bond->mii_work); - - if (bond->params.arp_interval && delayed_work_pending(&bond->arp_work)) - cancel_delayed_work_sync(&bond->arp_work); - - if (bond->params.mode == BOND_MODE_ALB && - delayed_work_pending(&bond->alb_work)) - cancel_delayed_work_sync(&bond->alb_work); - - if (bond->params.mode == BOND_MODE_8023AD && - delayed_work_pending(&bond->ad_work)) - cancel_delayed_work_sync(&bond->ad_work); - - if (delayed_work_pending(&bond->mcast_work)) - cancel_delayed_work_sync(&bond->mcast_work); -} - /* * Destroy a bonding device. * Must be under rtnl_lock when this function is called. @@ -4903,9 +4865,18 @@ static int __net_init bond_net_init(struct net *net) static void __net_exit bond_net_exit(struct net *net) { struct bond_net *bn = net_generic(net, bond_net_id); + struct bonding *bond, *tmp_bond; + LIST_HEAD(list); bond_destroy_sysfs(bn); bond_destroy_proc_dir(bn); + + /* Kill off any bonds created after unregistering bond rtnl ops */ + rtnl_lock(); + list_for_each_entry_safe(bond, tmp_bond, &bn->dev_list, bond_list) + unregister_netdevice_queue(bond->dev, &list); + unregister_netdevice_many(&list); + rtnl_unlock(); } static struct pernet_operations bond_net_ops = { diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index 6734737c953..c40c0a87181 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -183,6 +183,11 @@ int bond_create_slave_symlinks(struct net_device *master, sprintf(linkname, "slave_%s", slave->name); ret = sysfs_create_link(&(master->dev.kobj), &(slave->dev.kobj), linkname); + + /* free the master link created earlier in case of error */ + if (ret) + sysfs_remove_link(&(slave->dev.kobj), "master"); + return ret; } @@ -513,6 +518,8 @@ static ssize_t bonding_store_arp_interval(struct device *d, int new_value, ret = count; struct bonding *bond = to_bond(d); + if (!rtnl_trylock()) + return restart_syscall(); if (sscanf(buf, "%d", &new_value) != 1) { pr_err("%s: no arp_interval value specified.\n", bond->dev->name); @@ -520,7 +527,7 @@ static ssize_t bonding_store_arp_interval(struct device *d, goto out; } if (new_value < 0) { - pr_err("%s: Invalid arp_interval value %d not in range 1-%d; rejected.\n", + pr_err("%s: Invalid arp_interval value %d not in range 0-%d; rejected.\n", bond->dev->name, new_value, INT_MAX); ret = -EINVAL; goto out; @@ -535,18 +542,15 @@ static ssize_t bonding_store_arp_interval(struct device *d, pr_info("%s: Setting ARP monitoring interval to %d.\n", bond->dev->name, new_value); bond->params.arp_interval = new_value; - if (bond->params.miimon) { - pr_info("%s: ARP monitoring cannot be used with MII monitoring. %s Disabling MII monitoring.\n", - bond->dev->name, bond->dev->name); - bond->params.miimon = 0; - if (delayed_work_pending(&bond->mii_work)) { - cancel_delayed_work(&bond->mii_work); - flush_workqueue(bond->wq); + if (new_value) { + if (bond->params.miimon) { + pr_info("%s: ARP monitoring cannot be used with MII monitoring. %s Disabling MII monitoring.\n", + bond->dev->name, bond->dev->name); + bond->params.miimon = 0; } - } - if (!bond->params.arp_targets[0]) { - pr_info("%s: ARP monitoring has been set up, but no ARP targets have been specified.\n", - bond->dev->name); + if (!bond->params.arp_targets[0]) + pr_info("%s: ARP monitoring has been set up, but no ARP targets have been specified.\n", + bond->dev->name); } if (bond->dev->flags & IFF_UP) { /* If the interface is up, we may need to fire off @@ -554,19 +558,15 @@ static ssize_t bonding_store_arp_interval(struct device *d, * timer will get fired off when the open function * is called. */ - if (!delayed_work_pending(&bond->arp_work)) { - if (bond->params.mode == BOND_MODE_ACTIVEBACKUP) - INIT_DELAYED_WORK(&bond->arp_work, - bond_activebackup_arp_mon); - else - INIT_DELAYED_WORK(&bond->arp_work, - bond_loadbalance_arp_mon); - + if (!new_value) { + cancel_delayed_work_sync(&bond->arp_work); + } else { + cancel_delayed_work_sync(&bond->mii_work); queue_delayed_work(bond->wq, &bond->arp_work, 0); } } - out: + rtnl_unlock(); return ret; } static DEVICE_ATTR(arp_interval, S_IRUGO | S_IWUSR, @@ -706,7 +706,7 @@ static ssize_t bonding_store_downdelay(struct device *d, } if (new_value < 0) { pr_err("%s: Invalid down delay value %d not in range %d-%d; rejected.\n", - bond->dev->name, new_value, 1, INT_MAX); + bond->dev->name, new_value, 0, INT_MAX); ret = -EINVAL; goto out; } else { @@ -761,8 +761,8 @@ static ssize_t bonding_store_updelay(struct device *d, goto out; } if (new_value < 0) { - pr_err("%s: Invalid down delay value %d not in range %d-%d; rejected.\n", - bond->dev->name, new_value, 1, INT_MAX); + pr_err("%s: Invalid up delay value %d not in range %d-%d; rejected.\n", + bond->dev->name, new_value, 0, INT_MAX); ret = -EINVAL; goto out; } else { @@ -962,6 +962,8 @@ static ssize_t bonding_store_miimon(struct device *d, int new_value, ret = count; struct bonding *bond = to_bond(d); + if (!rtnl_trylock()) + return restart_syscall(); if (sscanf(buf, "%d", &new_value) != 1) { pr_err("%s: no miimon value specified.\n", bond->dev->name); @@ -970,50 +972,43 @@ static ssize_t bonding_store_miimon(struct device *d, } if (new_value < 0) { pr_err("%s: Invalid miimon value %d not in range %d-%d; rejected.\n", - bond->dev->name, new_value, 1, INT_MAX); + bond->dev->name, new_value, 0, INT_MAX); ret = -EINVAL; goto out; - } else { - pr_info("%s: Setting MII monitoring interval to %d.\n", - bond->dev->name, new_value); - bond->params.miimon = new_value; - if (bond->params.updelay) - pr_info("%s: Note: Updating updelay (to %d) since it is a multiple of the miimon value.\n", - bond->dev->name, - bond->params.updelay * bond->params.miimon); - if (bond->params.downdelay) - pr_info("%s: Note: Updating downdelay (to %d) since it is a multiple of the miimon value.\n", - bond->dev->name, - bond->params.downdelay * bond->params.miimon); - if (bond->params.arp_interval) { - pr_info("%s: MII monitoring cannot be used with ARP monitoring. Disabling ARP monitoring...\n", - bond->dev->name); - bond->params.arp_interval = 0; - if (bond->params.arp_validate) { - bond->params.arp_validate = - BOND_ARP_VALIDATE_NONE; - } - if (delayed_work_pending(&bond->arp_work)) { - cancel_delayed_work(&bond->arp_work); - flush_workqueue(bond->wq); - } - } - - if (bond->dev->flags & IFF_UP) { - /* If the interface is up, we may need to fire off - * the MII timer. If the interface is down, the - * timer will get fired off when the open function - * is called. - */ - if (!delayed_work_pending(&bond->mii_work)) { - INIT_DELAYED_WORK(&bond->mii_work, - bond_mii_monitor); - queue_delayed_work(bond->wq, - &bond->mii_work, 0); - } + } + pr_info("%s: Setting MII monitoring interval to %d.\n", + bond->dev->name, new_value); + bond->params.miimon = new_value; + if (bond->params.updelay) + pr_info("%s: Note: Updating updelay (to %d) since it is a multiple of the miimon value.\n", + bond->dev->name, + bond->params.updelay * bond->params.miimon); + if (bond->params.downdelay) + pr_info("%s: Note: Updating downdelay (to %d) since it is a multiple of the miimon value.\n", + bond->dev->name, + bond->params.downdelay * bond->params.miimon); + if (new_value && bond->params.arp_interval) { + pr_info("%s: MII monitoring cannot be used with ARP monitoring. Disabling ARP monitoring...\n", + bond->dev->name); + bond->params.arp_interval = 0; + if (bond->params.arp_validate) + bond->params.arp_validate = BOND_ARP_VALIDATE_NONE; + } + if (bond->dev->flags & IFF_UP) { + /* If the interface is up, we may need to fire off + * the MII timer. If the interface is down, the + * timer will get fired off when the open function + * is called. + */ + if (!new_value) { + cancel_delayed_work_sync(&bond->mii_work); + } else { + cancel_delayed_work_sync(&bond->arp_work); + queue_delayed_work(bond->wq, &bond->mii_work, 0); } } out: + rtnl_unlock(); return ret; } static DEVICE_ATTR(miimon, S_IRUGO | S_IWUSR, diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h index 4581aa5ccab..51f1766d05b 100644 --- a/drivers/net/bonding/bonding.h +++ b/drivers/net/bonding/bonding.h @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -450,6 +451,18 @@ static inline void bond_destroy_proc_dir(struct bond_net *bn) } #endif +static inline struct slave *bond_slave_has_mac(struct bonding *bond, + const u8 *mac) +{ + int i = 0; + struct slave *tmp; + + bond_for_each_slave(bond, tmp, i) + if (!compare_ether_addr_64bits(mac, tmp->dev->dev_addr)) + return tmp; + + return NULL; +} /* exported from bond_main.c */ extern int bond_net_id; diff --git a/drivers/net/can/sja1000/plx_pci.c b/drivers/net/can/sja1000/plx_pci.c index a227586ddd5..ee280b21857 100644 --- a/drivers/net/can/sja1000/plx_pci.c +++ b/drivers/net/can/sja1000/plx_pci.c @@ -329,7 +329,7 @@ static inline int plx_pci_check_sja1000(const struct sja1000_priv *priv) */ if ((priv->read_reg(priv, REG_CR) & REG_CR_BASICCAN_INITIAL_MASK) == REG_CR_BASICCAN_INITIAL && - (priv->read_reg(priv, REG_SR) == REG_SR_BASICCAN_INITIAL) && + (priv->read_reg(priv, SJA1000_REG_SR) == REG_SR_BASICCAN_INITIAL) && (priv->read_reg(priv, REG_IR) == REG_IR_BASICCAN_INITIAL)) flag = 1; @@ -341,7 +341,7 @@ static inline int plx_pci_check_sja1000(const struct sja1000_priv *priv) * See states on p. 23 of the Datasheet. */ if (priv->read_reg(priv, REG_MOD) == REG_MOD_PELICAN_INITIAL && - priv->read_reg(priv, REG_SR) == REG_SR_PELICAN_INITIAL && + priv->read_reg(priv, SJA1000_REG_SR) == REG_SR_PELICAN_INITIAL && priv->read_reg(priv, REG_IR) == REG_IR_PELICAN_INITIAL) return flag; diff --git a/drivers/net/can/sja1000/sja1000.c b/drivers/net/can/sja1000/sja1000.c index 5e10472371e..c2309ec7136 100644 --- a/drivers/net/can/sja1000/sja1000.c +++ b/drivers/net/can/sja1000/sja1000.c @@ -91,7 +91,7 @@ static void sja1000_write_cmdreg(struct sja1000_priv *priv, u8 val) */ spin_lock_irqsave(&priv->cmdreg_lock, flags); priv->write_reg(priv, REG_CMR, val); - priv->read_reg(priv, REG_SR); + priv->read_reg(priv, SJA1000_REG_SR); spin_unlock_irqrestore(&priv->cmdreg_lock, flags); } @@ -496,7 +496,7 @@ irqreturn_t sja1000_interrupt(int irq, void *dev_id) while ((isrc = priv->read_reg(priv, REG_IR)) && (n < SJA1000_MAX_IRQ)) { n++; - status = priv->read_reg(priv, REG_SR); + status = priv->read_reg(priv, SJA1000_REG_SR); /* check for absent controller due to hw unplug */ if (status == 0xFF && sja1000_is_absent(priv)) return IRQ_NONE; @@ -515,7 +515,7 @@ irqreturn_t sja1000_interrupt(int irq, void *dev_id) /* receive interrupt */ while (status & SR_RBS) { sja1000_rx(dev); - status = priv->read_reg(priv, REG_SR); + status = priv->read_reg(priv, SJA1000_REG_SR); /* check for absent controller */ if (status == 0xFF && sja1000_is_absent(priv)) return IRQ_NONE; diff --git a/drivers/net/can/sja1000/sja1000.h b/drivers/net/can/sja1000/sja1000.h index 23fff06875f..2a79543f34c 100644 --- a/drivers/net/can/sja1000/sja1000.h +++ b/drivers/net/can/sja1000/sja1000.h @@ -56,7 +56,7 @@ /* SJA1000 registers - manual section 6.4 (Pelican Mode) */ #define REG_MOD 0x00 #define REG_CMR 0x01 -#define REG_SR 0x02 +#define SJA1000_REG_SR 0x02 #define REG_IR 0x03 #define REG_IER 0x04 #define REG_ALC 0x0B diff --git a/drivers/net/can/sja1000/sja1000_of_platform.c b/drivers/net/can/sja1000/sja1000_of_platform.c index f2683eb6a3d..c505b559bbe 100644 --- a/drivers/net/can/sja1000/sja1000_of_platform.c +++ b/drivers/net/can/sja1000/sja1000_of_platform.c @@ -94,8 +94,8 @@ static int __devinit sja1000_ofp_probe(struct platform_device *ofdev) struct net_device *dev; struct sja1000_priv *priv; struct resource res; - const u32 *prop; - int err, irq, res_size, prop_size; + u32 prop; + int err, irq, res_size; void __iomem *base; err = of_address_to_resource(np, 0, &res); @@ -136,27 +136,27 @@ static int __devinit sja1000_ofp_probe(struct platform_device *ofdev) priv->read_reg = sja1000_ofp_read_reg; priv->write_reg = sja1000_ofp_write_reg; - prop = of_get_property(np, "nxp,external-clock-frequency", &prop_size); - if (prop && (prop_size == sizeof(u32))) - priv->can.clock.freq = *prop / 2; + err = of_property_read_u32(np, "nxp,external-clock-frequency", &prop); + if (!err) + priv->can.clock.freq = prop / 2; else priv->can.clock.freq = SJA1000_OFP_CAN_CLOCK; /* default */ - prop = of_get_property(np, "nxp,tx-output-mode", &prop_size); - if (prop && (prop_size == sizeof(u32))) - priv->ocr |= *prop & OCR_MODE_MASK; + err = of_property_read_u32(np, "nxp,tx-output-mode", &prop); + if (!err) + priv->ocr |= prop & OCR_MODE_MASK; else priv->ocr |= OCR_MODE_NORMAL; /* default */ - prop = of_get_property(np, "nxp,tx-output-config", &prop_size); - if (prop && (prop_size == sizeof(u32))) - priv->ocr |= (*prop << OCR_TX_SHIFT) & OCR_TX_MASK; + err = of_property_read_u32(np, "nxp,tx-output-config", &prop); + if (!err) + priv->ocr |= (prop << OCR_TX_SHIFT) & OCR_TX_MASK; else priv->ocr |= OCR_TX0_PULLDOWN; /* default */ - prop = of_get_property(np, "nxp,clock-out-frequency", &prop_size); - if (prop && (prop_size == sizeof(u32)) && *prop) { - u32 divider = priv->can.clock.freq * 2 / *prop; + err = of_property_read_u32(np, "nxp,clock-out-frequency", &prop); + if (!err && prop) { + u32 divider = priv->can.clock.freq * 2 / prop; if (divider > 1) priv->cdr |= divider / 2 - 1; @@ -166,8 +166,7 @@ static int __devinit sja1000_ofp_probe(struct platform_device *ofdev) priv->cdr |= CDR_CLK_OFF; /* default */ } - prop = of_get_property(np, "nxp,no-comparator-bypass", NULL); - if (!prop) + if (!of_property_read_bool(np, "nxp,no-comparator-bypass")) priv->cdr |= CDR_CBP; /* default */ priv->irq_flags = IRQF_SHARED; diff --git a/drivers/net/can/usb/peak_usb/pcan_usb.c b/drivers/net/can/usb/peak_usb/pcan_usb.c index 25723d8ee20..925ab8ec932 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb.c +++ b/drivers/net/can/usb/peak_usb/pcan_usb.c @@ -649,7 +649,7 @@ static int pcan_usb_decode_data(struct pcan_usb_msg_context *mc, u8 status_len) if ((mc->ptr + rec_len) > mc->end) goto decode_failed; - memcpy(cf->data, mc->ptr, rec_len); + memcpy(cf->data, mc->ptr, cf->can_dlc); mc->ptr += rec_len; } diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c index bab0158f1cc..b33ad1228da 100644 --- a/drivers/net/dummy.c +++ b/drivers/net/dummy.c @@ -186,6 +186,8 @@ static int __init dummy_init_module(void) rtnl_lock(); err = __rtnl_link_register(&dummy_link_ops); + if (err < 0) + goto out; for (i = 0; i < numdummies && !err; i++) { err = dummy_init_one(); @@ -193,6 +195,8 @@ static int __init dummy_init_module(void) } if (err < 0) __rtnl_link_unregister(&dummy_link_ops); + +out: rtnl_unlock(); return err; diff --git a/drivers/net/ethernet/3com/3c509.c b/drivers/net/ethernet/3com/3c509.c index 41719da2e17..9040a62bee7 100644 --- a/drivers/net/ethernet/3com/3c509.c +++ b/drivers/net/ethernet/3com/3c509.c @@ -309,6 +309,7 @@ static int __devinit el3_isa_match(struct device *pdev, if (!dev) return -ENOMEM; + SET_NETDEV_DEV(dev, pdev); netdev_boot_setup_check(dev); if (!request_region(ioaddr, EL3_IO_EXTENT, "3c509-isa")) { @@ -704,6 +705,7 @@ static int __init el3_eisa_probe (struct device *device) return -ENOMEM; } + SET_NETDEV_DEV(dev, device); netdev_boot_setup_check(dev); el3_dev_fill(dev, phys_addr, ioaddr, irq, if_port, EL3_EISA); diff --git a/drivers/net/ethernet/3com/3c59x.c b/drivers/net/ethernet/3com/3c59x.c index e463d103682..5673d6e68da 100644 --- a/drivers/net/ethernet/3com/3c59x.c +++ b/drivers/net/ethernet/3com/3c59x.c @@ -632,7 +632,6 @@ struct vortex_private { pm_state_valid:1, /* pci_dev->saved_config_space has sane contents */ open:1, medialock:1, - must_free_region:1, /* Flag: if zero, Cardbus owns the I/O region */ large_frames:1, /* accept large frames */ handling_irq:1; /* private in_irq indicator */ /* {get|set}_wol operations are already serialized by rtnl. @@ -951,7 +950,7 @@ static int __devexit vortex_eisa_remove(struct device *device) unregister_netdev(dev); iowrite16(TotalReset|0x14, ioaddr + EL3_CMD); - release_region(dev->base_addr, VORTEX_TOTAL_SIZE); + release_region(edev->base_addr, VORTEX_TOTAL_SIZE); free_netdev(dev); return 0; @@ -1012,6 +1011,12 @@ static int __devinit vortex_init_one(struct pci_dev *pdev, if (rc < 0) goto out; + rc = pci_request_regions(pdev, DRV_NAME); + if (rc < 0) { + pci_disable_device(pdev); + goto out; + } + unit = vortex_cards_found; if (global_use_mmio < 0 && (unit >= MAX_UNITS || use_mmio[unit] < 0)) { @@ -1027,6 +1032,7 @@ static int __devinit vortex_init_one(struct pci_dev *pdev, if (!ioaddr) /* If mapping fails, fall-back to BAR 0... */ ioaddr = pci_iomap(pdev, 0, 0); if (!ioaddr) { + pci_release_regions(pdev); pci_disable_device(pdev); rc = -ENOMEM; goto out; @@ -1036,6 +1042,7 @@ static int __devinit vortex_init_one(struct pci_dev *pdev, ent->driver_data, unit); if (rc < 0) { pci_iounmap(pdev, ioaddr); + pci_release_regions(pdev); pci_disable_device(pdev); goto out; } @@ -1179,11 +1186,6 @@ static int __devinit vortex_probe1(struct device *gendev, /* PCI-only startup logic */ if (pdev) { - /* EISA resources already marked, so only PCI needs to do this here */ - /* Ignore return value, because Cardbus drivers already allocate for us */ - if (request_region(dev->base_addr, vci->io_size, print_name) != NULL) - vp->must_free_region = 1; - /* enable bus-mastering if necessary */ if (vci->flags & PCI_USES_MASTER) pci_set_master(pdev); @@ -1221,7 +1223,7 @@ static int __devinit vortex_probe1(struct device *gendev, &vp->rx_ring_dma); retval = -ENOMEM; if (!vp->rx_ring) - goto free_region; + goto free_device; vp->tx_ring = (struct boom_tx_desc *)(vp->rx_ring + RX_RING_SIZE); vp->tx_ring_dma = vp->rx_ring_dma + sizeof(struct boom_rx_desc) * RX_RING_SIZE; @@ -1486,9 +1488,7 @@ static int __devinit vortex_probe1(struct device *gendev, + sizeof(struct boom_tx_desc) * TX_RING_SIZE, vp->rx_ring, vp->rx_ring_dma); -free_region: - if (vp->must_free_region) - release_region(dev->base_addr, vci->io_size); +free_device: free_netdev(dev); pr_err(PFX "vortex_probe1 fails. Returns %d\n", retval); out: @@ -3256,8 +3256,9 @@ static void __devexit vortex_remove_one(struct pci_dev *pdev) + sizeof(struct boom_tx_desc) * TX_RING_SIZE, vp->rx_ring, vp->rx_ring_dma); - if (vp->must_free_region) - release_region(dev->base_addr, vp->io_size); + + pci_release_regions(pdev); + free_netdev(dev); } diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e.h b/drivers/net/ethernet/atheros/atl1e/atl1e.h index 829b5ad71d0..b5fd934585e 100644 --- a/drivers/net/ethernet/atheros/atl1e/atl1e.h +++ b/drivers/net/ethernet/atheros/atl1e/atl1e.h @@ -186,7 +186,7 @@ struct atl1e_tpd_desc { /* how about 0x2000 */ #define MAX_TX_BUF_LEN 0x2000 #define MAX_TX_BUF_SHIFT 13 -/*#define MAX_TX_BUF_LEN 0x3000 */ +#define MAX_TSO_SEG_SIZE 0x3c00 /* rrs word 1 bit 0:31 */ #define RRS_RX_CSUM_MASK 0xFFFF @@ -438,7 +438,6 @@ struct atl1e_adapter { struct atl1e_hw hw; struct atl1e_hw_stats hw_stats; - bool have_msi; u32 wol; u16 link_speed; u16 link_duplex; diff --git a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c index 93ff2b23128..d4a747a1203 100644 --- a/drivers/net/ethernet/atheros/atl1e/atl1e_main.c +++ b/drivers/net/ethernet/atheros/atl1e/atl1e_main.c @@ -1688,8 +1688,8 @@ static int atl1e_tso_csum(struct atl1e_adapter *adapter, return 0; } -static void atl1e_tx_map(struct atl1e_adapter *adapter, - struct sk_buff *skb, struct atl1e_tpd_desc *tpd) +static int atl1e_tx_map(struct atl1e_adapter *adapter, + struct sk_buff *skb, struct atl1e_tpd_desc *tpd) { struct atl1e_tpd_desc *use_tpd = NULL; struct atl1e_tx_buffer *tx_buffer = NULL; @@ -1700,6 +1700,8 @@ static void atl1e_tx_map(struct atl1e_adapter *adapter, u16 nr_frags; u16 f; int segment; + int ring_start = adapter->tx_ring.next_to_use; + int ring_end; nr_frags = skb_shinfo(skb)->nr_frags; segment = (tpd->word3 >> TPD_SEGMENT_EN_SHIFT) & TPD_SEGMENT_EN_MASK; @@ -1712,6 +1714,9 @@ static void atl1e_tx_map(struct atl1e_adapter *adapter, tx_buffer->length = map_len; tx_buffer->dma = pci_map_single(adapter->pdev, skb->data, hdr_len, PCI_DMA_TODEVICE); + if (dma_mapping_error(&adapter->pdev->dev, tx_buffer->dma)) + return -ENOSPC; + ATL1E_SET_PCIMAP_TYPE(tx_buffer, ATL1E_TX_PCIMAP_SINGLE); mapped_len += map_len; use_tpd->buffer_addr = cpu_to_le64(tx_buffer->dma); @@ -1738,6 +1743,22 @@ static void atl1e_tx_map(struct atl1e_adapter *adapter, tx_buffer->dma = pci_map_single(adapter->pdev, skb->data + mapped_len, map_len, PCI_DMA_TODEVICE); + + if (dma_mapping_error(&adapter->pdev->dev, tx_buffer->dma)) { + /* We need to unwind the mappings we've done */ + ring_end = adapter->tx_ring.next_to_use; + adapter->tx_ring.next_to_use = ring_start; + while (adapter->tx_ring.next_to_use != ring_end) { + tpd = atl1e_get_tpd(adapter); + tx_buffer = atl1e_get_tx_buffer(adapter, tpd); + pci_unmap_single(adapter->pdev, tx_buffer->dma, + tx_buffer->length, PCI_DMA_TODEVICE); + } + /* Reset the tx rings next pointer */ + adapter->tx_ring.next_to_use = ring_start; + return -ENOSPC; + } + ATL1E_SET_PCIMAP_TYPE(tx_buffer, ATL1E_TX_PCIMAP_SINGLE); mapped_len += map_len; use_tpd->buffer_addr = cpu_to_le64(tx_buffer->dma); @@ -1773,6 +1794,23 @@ static void atl1e_tx_map(struct atl1e_adapter *adapter, (i * MAX_TX_BUF_LEN), tx_buffer->length, DMA_TO_DEVICE); + + if (dma_mapping_error(&adapter->pdev->dev, tx_buffer->dma)) { + /* We need to unwind the mappings we've done */ + ring_end = adapter->tx_ring.next_to_use; + adapter->tx_ring.next_to_use = ring_start; + while (adapter->tx_ring.next_to_use != ring_end) { + tpd = atl1e_get_tpd(adapter); + tx_buffer = atl1e_get_tx_buffer(adapter, tpd); + dma_unmap_page(&adapter->pdev->dev, tx_buffer->dma, + tx_buffer->length, DMA_TO_DEVICE); + } + + /* Reset the ring next to use pointer */ + adapter->tx_ring.next_to_use = ring_start; + return -ENOSPC; + } + ATL1E_SET_PCIMAP_TYPE(tx_buffer, ATL1E_TX_PCIMAP_PAGE); use_tpd->buffer_addr = cpu_to_le64(tx_buffer->dma); use_tpd->word2 = (use_tpd->word2 & (~TPD_BUFLEN_MASK)) | @@ -1790,6 +1828,7 @@ static void atl1e_tx_map(struct atl1e_adapter *adapter, /* The last buffer info contain the skb address, so it will be free after unmap */ tx_buffer->skb = skb; + return 0; } static void atl1e_tx_queue(struct atl1e_adapter *adapter, u16 count, @@ -1857,10 +1896,15 @@ static netdev_tx_t atl1e_xmit_frame(struct sk_buff *skb, return NETDEV_TX_OK; } - atl1e_tx_map(adapter, skb, tpd); + if (atl1e_tx_map(adapter, skb, tpd)) { + dev_kfree_skb_any(skb); + goto out; + } + atl1e_tx_queue(adapter, tpd_req, tpd); netdev->trans_start = jiffies; /* NETIF_F_LLTX driver :( */ +out: spin_unlock_irqrestore(&adapter->tx_lock, flags); return NETDEV_TX_OK; } @@ -1870,37 +1914,19 @@ static void atl1e_free_irq(struct atl1e_adapter *adapter) struct net_device *netdev = adapter->netdev; free_irq(adapter->pdev->irq, netdev); - - if (adapter->have_msi) - pci_disable_msi(adapter->pdev); } static int atl1e_request_irq(struct atl1e_adapter *adapter) { struct pci_dev *pdev = adapter->pdev; struct net_device *netdev = adapter->netdev; - int flags = 0; int err = 0; - adapter->have_msi = true; - err = pci_enable_msi(adapter->pdev); - if (err) { - netdev_dbg(adapter->netdev, - "Unable to allocate MSI interrupt Error: %d\n", err); - adapter->have_msi = false; - } else - netdev->irq = pdev->irq; - - - if (!adapter->have_msi) - flags |= IRQF_SHARED; - err = request_irq(adapter->pdev->irq, atl1e_intr, flags, - netdev->name, netdev); + err = request_irq(pdev->irq, atl1e_intr, IRQF_SHARED, + netdev->name, netdev); if (err) { netdev_dbg(adapter->netdev, "Unable to allocate interrupt Error: %d\n", err); - if (adapter->have_msi) - pci_disable_msi(adapter->pdev); return err; } netdev_dbg(adapter->netdev, "atl1e_request_irq OK\n"); @@ -2372,6 +2398,7 @@ static int __devinit atl1e_probe(struct pci_dev *pdev, INIT_WORK(&adapter->reset_task, atl1e_reset_task); INIT_WORK(&adapter->link_chg_task, atl1e_link_chg_task); + netif_set_gso_max_size(netdev, MAX_TSO_SEG_SIZE); err = register_netdev(netdev); if (err) { netdev_err(netdev, "register netdevice failed\n"); diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h index 2b46e1eb7fd..5905caa7523 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h @@ -439,8 +439,9 @@ struct bnx2x_fw_port_stats_old { #define UPDATE_QSTAT(s, t) \ do { \ - qstats->t##_hi = qstats_old->t##_hi + le32_to_cpu(s.hi); \ qstats->t##_lo = qstats_old->t##_lo + le32_to_cpu(s.lo); \ + qstats->t##_hi = qstats_old->t##_hi + le32_to_cpu(s.hi) \ + + ((qstats->t##_lo < qstats_old->t##_lo) ? 1 : 0); \ } while (0) #define UPDATE_QSTAT_OLD(f) \ diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index 689d2a1935b..3551ad82ba8 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -1136,14 +1136,26 @@ static int tg3_phy_auxctl_write(struct tg3 *tp, int reg, u32 set) return tg3_writephy(tp, MII_TG3_AUX_CTRL, set | reg); } -#define TG3_PHY_AUXCTL_SMDSP_ENABLE(tp) \ - tg3_phy_auxctl_write((tp), MII_TG3_AUXCTL_SHDWSEL_AUXCTL, \ - MII_TG3_AUXCTL_ACTL_SMDSP_ENA | \ - MII_TG3_AUXCTL_ACTL_TX_6DB) +static int tg3_phy_toggle_auxctl_smdsp(struct tg3 *tp, bool enable) +{ + u32 val; + int err; -#define TG3_PHY_AUXCTL_SMDSP_DISABLE(tp) \ - tg3_phy_auxctl_write((tp), MII_TG3_AUXCTL_SHDWSEL_AUXCTL, \ - MII_TG3_AUXCTL_ACTL_TX_6DB); + err = tg3_phy_auxctl_read(tp, MII_TG3_AUXCTL_SHDWSEL_AUXCTL, &val); + + if (err) + return err; + if (enable) + + val |= MII_TG3_AUXCTL_ACTL_SMDSP_ENA; + else + val &= ~MII_TG3_AUXCTL_ACTL_SMDSP_ENA; + + err = tg3_phy_auxctl_write((tp), MII_TG3_AUXCTL_SHDWSEL_AUXCTL, + val | MII_TG3_AUXCTL_ACTL_TX_6DB); + + return err; +} static int tg3_bmcr_reset(struct tg3 *tp) { @@ -2076,7 +2088,7 @@ static void tg3_phy_apply_otp(struct tg3 *tp) otp = tp->phy_otp; - if (TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) + if (tg3_phy_toggle_auxctl_smdsp(tp, true)) return; phy = ((otp & TG3_OTP_AGCTGT_MASK) >> TG3_OTP_AGCTGT_SHIFT); @@ -2101,7 +2113,7 @@ static void tg3_phy_apply_otp(struct tg3 *tp) ((otp & TG3_OTP_RCOFF_MASK) >> TG3_OTP_RCOFF_SHIFT); tg3_phydsp_write(tp, MII_TG3_DSP_EXP97, phy); - TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); + tg3_phy_toggle_auxctl_smdsp(tp, false); } static void tg3_phy_eee_adjust(struct tg3 *tp, u32 current_link_up) @@ -2137,9 +2149,9 @@ static void tg3_phy_eee_adjust(struct tg3 *tp, u32 current_link_up) if (!tp->setlpicnt) { if (current_link_up == 1 && - !TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) { + !tg3_phy_toggle_auxctl_smdsp(tp, true)) { tg3_phydsp_write(tp, MII_TG3_DSP_TAP26, 0x0000); - TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); + tg3_phy_toggle_auxctl_smdsp(tp, false); } val = tr32(TG3_CPMU_EEE_MODE); @@ -2155,11 +2167,11 @@ static void tg3_phy_eee_enable(struct tg3 *tp) (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || tg3_flag(tp, 57765_CLASS)) && - !TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) { + !tg3_phy_toggle_auxctl_smdsp(tp, true)) { val = MII_TG3_DSP_TAP26_ALNOKO | MII_TG3_DSP_TAP26_RMRXSTO; tg3_phydsp_write(tp, MII_TG3_DSP_TAP26, val); - TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); + tg3_phy_toggle_auxctl_smdsp(tp, false); } val = tr32(TG3_CPMU_EEE_MODE); @@ -2303,7 +2315,7 @@ static int tg3_phy_reset_5703_4_5(struct tg3 *tp) tg3_writephy(tp, MII_CTRL1000, CTL1000_AS_MASTER | CTL1000_ENABLE_MASTER); - err = TG3_PHY_AUXCTL_SMDSP_ENABLE(tp); + err = tg3_phy_toggle_auxctl_smdsp(tp, true); if (err) return err; @@ -2324,7 +2336,7 @@ static int tg3_phy_reset_5703_4_5(struct tg3 *tp) tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8200); tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0000); - TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); + tg3_phy_toggle_auxctl_smdsp(tp, false); tg3_writephy(tp, MII_CTRL1000, phy9_orig); @@ -2413,10 +2425,10 @@ static int tg3_phy_reset(struct tg3 *tp) out: if ((tp->phy_flags & TG3_PHYFLG_ADC_BUG) && - !TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) { + !tg3_phy_toggle_auxctl_smdsp(tp, true)) { tg3_phydsp_write(tp, 0x201f, 0x2aaa); tg3_phydsp_write(tp, 0x000a, 0x0323); - TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); + tg3_phy_toggle_auxctl_smdsp(tp, false); } if (tp->phy_flags & TG3_PHYFLG_5704_A0_BUG) { @@ -2425,14 +2437,14 @@ static int tg3_phy_reset(struct tg3 *tp) } if (tp->phy_flags & TG3_PHYFLG_BER_BUG) { - if (!TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) { + if (!tg3_phy_toggle_auxctl_smdsp(tp, true)) { tg3_phydsp_write(tp, 0x000a, 0x310b); tg3_phydsp_write(tp, 0x201f, 0x9506); tg3_phydsp_write(tp, 0x401f, 0x14e2); - TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); + tg3_phy_toggle_auxctl_smdsp(tp, false); } } else if (tp->phy_flags & TG3_PHYFLG_JITTER_BUG) { - if (!TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) { + if (!tg3_phy_toggle_auxctl_smdsp(tp, true)) { tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x000a); if (tp->phy_flags & TG3_PHYFLG_ADJUST_TRIM) { tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x110b); @@ -2441,7 +2453,7 @@ static int tg3_phy_reset(struct tg3 *tp) } else tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x010b); - TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); + tg3_phy_toggle_auxctl_smdsp(tp, false); } } @@ -3858,7 +3870,7 @@ static int tg3_phy_autoneg_cfg(struct tg3 *tp, u32 advertise, u32 flowctrl) tw32(TG3_CPMU_EEE_MODE, tr32(TG3_CPMU_EEE_MODE) & ~TG3_CPMU_EEEMD_LPI_ENABLE); - err = TG3_PHY_AUXCTL_SMDSP_ENABLE(tp); + err = tg3_phy_toggle_auxctl_smdsp(tp, true); if (!err) { u32 err2; @@ -3891,7 +3903,7 @@ static int tg3_phy_autoneg_cfg(struct tg3 *tp, u32 advertise, u32 flowctrl) MII_TG3_DSP_CH34TP2_HIBW01); } - err2 = TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); + err2 = tg3_phy_toggle_auxctl_smdsp(tp, false); if (!err) err = err2; } @@ -3934,6 +3946,14 @@ static void tg3_phy_copper_begin(struct tg3 *tp) tp->link_config.active_speed = tp->link_config.speed; tp->link_config.active_duplex = tp->link_config.duplex; + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714) { + /* With autoneg disabled, 5715 only links up when the + * advertisement register has the configured speed + * enabled. + */ + tg3_writephy(tp, MII_ADVERTISE, ADVERTISE_ALL); + } + bmcr = 0; switch (tp->link_config.speed) { default: @@ -6574,6 +6594,9 @@ static void tg3_poll_controller(struct net_device *dev) int i; struct tg3 *tp = netdev_priv(dev); + if (tg3_irq_sync(tp)) + return; + for (i = 0; i < tp->irq_cnt; i++) tg3_interrupt(tp->napi[i].irq_vec, &tp->napi[i]); } @@ -13567,8 +13590,11 @@ static void __devinit tg3_read_vpd(struct tg3 *tp) if (j + len > block_end) goto partno; - memcpy(tp->fw_ver, &vpd_data[j], len); - strncat(tp->fw_ver, " bc ", vpdlen - len - 1); + if (len >= sizeof(tp->fw_ver)) + len = sizeof(tp->fw_ver) - 1; + memset(tp->fw_ver, 0, sizeof(tp->fw_ver)); + snprintf(tp->fw_ver, sizeof(tp->fw_ver), "%.*s bc ", len, + &vpd_data[j]); } partno: @@ -15529,6 +15555,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, tp->pm_cap = pm_cap; tp->rx_mode = TG3_DEF_RX_MODE; tp->tx_mode = TG3_DEF_TX_MODE; + tp->irq_sync = 1; if (tg3_debug > 0) tp->msg_enable = tg3_debug; diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c index 11f667f6131..4ebbe6f609d 100644 --- a/drivers/net/ethernet/calxeda/xgmac.c +++ b/drivers/net/ethernet/calxeda/xgmac.c @@ -547,6 +547,10 @@ static int desc_get_rx_status(struct xgmac_priv *priv, struct xgmac_dma_desc *p) return -1; } + /* All frames should fit into a single buffer */ + if (!(status & RXDESC_FIRST_SEG) || !(status & RXDESC_LAST_SEG)) + return -1; + /* Check if packet has checksum already */ if ((status & RXDESC_FRAME_TYPE) && (status & RXDESC_EXT_STATUS) && !(ext_status & RXDESC_IP_PAYLOAD_MASK)) diff --git a/drivers/net/ethernet/davicom/dm9000.c b/drivers/net/ethernet/davicom/dm9000.c index 36499d5edd9..a9628b62df6 100644 --- a/drivers/net/ethernet/davicom/dm9000.c +++ b/drivers/net/ethernet/davicom/dm9000.c @@ -257,6 +257,107 @@ static void dm9000_dumpblk_32bit(void __iomem *reg, int count) tmp = readl(reg); } +/* + * Sleep, either by using msleep() or if we are suspending, then + * use mdelay() to sleep. + */ +static void dm9000_msleep(board_info_t *db, unsigned int ms) +{ + if (db->in_suspend) + mdelay(ms); + else + msleep(ms); +} + +/* Read a word from phyxcer */ +static int +dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg) +{ + board_info_t *db = netdev_priv(dev); + unsigned long flags; + unsigned int reg_save; + int ret; + + mutex_lock(&db->addr_lock); + + spin_lock_irqsave(&db->lock, flags); + + /* Save previous register address */ + reg_save = readb(db->io_addr); + + /* Fill the phyxcer register into REG_0C */ + iow(db, DM9000_EPAR, DM9000_PHY | reg); + + /* Issue phyxcer read command */ + iow(db, DM9000_EPCR, EPCR_ERPRR | EPCR_EPOS); + + writeb(reg_save, db->io_addr); + spin_unlock_irqrestore(&db->lock, flags); + + dm9000_msleep(db, 1); /* Wait read complete */ + + spin_lock_irqsave(&db->lock, flags); + reg_save = readb(db->io_addr); + + iow(db, DM9000_EPCR, 0x0); /* Clear phyxcer read command */ + + /* The read data keeps on REG_0D & REG_0E */ + ret = (ior(db, DM9000_EPDRH) << 8) | ior(db, DM9000_EPDRL); + + /* restore the previous address */ + writeb(reg_save, db->io_addr); + spin_unlock_irqrestore(&db->lock, flags); + + mutex_unlock(&db->addr_lock); + + dm9000_dbg(db, 5, "phy_read[%02x] -> %04x\n", reg, ret); + return ret; +} + +/* Write a word to phyxcer */ +static void +dm9000_phy_write(struct net_device *dev, + int phyaddr_unused, int reg, int value) +{ + board_info_t *db = netdev_priv(dev); + unsigned long flags; + unsigned long reg_save; + + dm9000_dbg(db, 5, "phy_write[%02x] = %04x\n", reg, value); + mutex_lock(&db->addr_lock); + + spin_lock_irqsave(&db->lock, flags); + + /* Save previous register address */ + reg_save = readb(db->io_addr); + + /* Fill the phyxcer register into REG_0C */ + iow(db, DM9000_EPAR, DM9000_PHY | reg); + + /* Fill the written data into REG_0D & REG_0E */ + iow(db, DM9000_EPDRL, value); + iow(db, DM9000_EPDRH, value >> 8); + + /* Issue phyxcer write command */ + iow(db, DM9000_EPCR, EPCR_EPOS | EPCR_ERPRW); + + writeb(reg_save, db->io_addr); + spin_unlock_irqrestore(&db->lock, flags); + + dm9000_msleep(db, 1); /* Wait write complete */ + + spin_lock_irqsave(&db->lock, flags); + reg_save = readb(db->io_addr); + + iow(db, DM9000_EPCR, 0x0); /* Clear phyxcer write command */ + + /* restore the previous address */ + writeb(reg_save, db->io_addr); + + spin_unlock_irqrestore(&db->lock, flags); + mutex_unlock(&db->addr_lock); +} + /* dm9000_set_io * * select the specified set of io routines to use with the @@ -794,6 +895,9 @@ dm9000_init_dm9000(struct net_device *dev) iow(db, DM9000_GPCR, GPCR_GEP_CNTL); /* Let GPIO0 output */ + dm9000_phy_write(dev, 0, MII_BMCR, BMCR_RESET); /* PHY RESET */ + dm9000_phy_write(dev, 0, MII_DM_DSPCR, DSPCR_INIT_PARAM); /* Init */ + ncr = (db->flags & DM9000_PLATF_EXT_PHY) ? NCR_EXT_PHY : 0; /* if wol is needed, then always set NCR_WAKEEN otherwise we end @@ -1200,109 +1304,6 @@ dm9000_open(struct net_device *dev) return 0; } -/* - * Sleep, either by using msleep() or if we are suspending, then - * use mdelay() to sleep. - */ -static void dm9000_msleep(board_info_t *db, unsigned int ms) -{ - if (db->in_suspend) - mdelay(ms); - else - msleep(ms); -} - -/* - * Read a word from phyxcer - */ -static int -dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg) -{ - board_info_t *db = netdev_priv(dev); - unsigned long flags; - unsigned int reg_save; - int ret; - - mutex_lock(&db->addr_lock); - - spin_lock_irqsave(&db->lock,flags); - - /* Save previous register address */ - reg_save = readb(db->io_addr); - - /* Fill the phyxcer register into REG_0C */ - iow(db, DM9000_EPAR, DM9000_PHY | reg); - - iow(db, DM9000_EPCR, EPCR_ERPRR | EPCR_EPOS); /* Issue phyxcer read command */ - - writeb(reg_save, db->io_addr); - spin_unlock_irqrestore(&db->lock,flags); - - dm9000_msleep(db, 1); /* Wait read complete */ - - spin_lock_irqsave(&db->lock,flags); - reg_save = readb(db->io_addr); - - iow(db, DM9000_EPCR, 0x0); /* Clear phyxcer read command */ - - /* The read data keeps on REG_0D & REG_0E */ - ret = (ior(db, DM9000_EPDRH) << 8) | ior(db, DM9000_EPDRL); - - /* restore the previous address */ - writeb(reg_save, db->io_addr); - spin_unlock_irqrestore(&db->lock,flags); - - mutex_unlock(&db->addr_lock); - - dm9000_dbg(db, 5, "phy_read[%02x] -> %04x\n", reg, ret); - return ret; -} - -/* - * Write a word to phyxcer - */ -static void -dm9000_phy_write(struct net_device *dev, - int phyaddr_unused, int reg, int value) -{ - board_info_t *db = netdev_priv(dev); - unsigned long flags; - unsigned long reg_save; - - dm9000_dbg(db, 5, "phy_write[%02x] = %04x\n", reg, value); - mutex_lock(&db->addr_lock); - - spin_lock_irqsave(&db->lock,flags); - - /* Save previous register address */ - reg_save = readb(db->io_addr); - - /* Fill the phyxcer register into REG_0C */ - iow(db, DM9000_EPAR, DM9000_PHY | reg); - - /* Fill the written data into REG_0D & REG_0E */ - iow(db, DM9000_EPDRL, value); - iow(db, DM9000_EPDRH, value >> 8); - - iow(db, DM9000_EPCR, EPCR_EPOS | EPCR_ERPRW); /* Issue phyxcer write command */ - - writeb(reg_save, db->io_addr); - spin_unlock_irqrestore(&db->lock, flags); - - dm9000_msleep(db, 1); /* Wait write complete */ - - spin_lock_irqsave(&db->lock,flags); - reg_save = readb(db->io_addr); - - iow(db, DM9000_EPCR, 0x0); /* Clear phyxcer write command */ - - /* restore the previous address */ - writeb(reg_save, db->io_addr); - - spin_unlock_irqrestore(&db->lock, flags); - mutex_unlock(&db->addr_lock); -} - static void dm9000_shutdown(struct net_device *dev) { @@ -1501,7 +1502,12 @@ dm9000_probe(struct platform_device *pdev) db->flags |= DM9000_PLATF_SIMPLE_PHY; #endif - dm9000_reset(db); + /* Fixing bug on dm9000_probe, takeover dm9000_reset(db), + * Need 'NCR_MAC_LBK' bit to indeed stable our DM9000 fifo + * while probe stage. + */ + + iow(db, DM9000_NCR, NCR_MAC_LBK | NCR_RST); /* try multiple times, DM9000 sometimes gets the read wrong */ for (i = 0; i < 8; i++) { diff --git a/drivers/net/ethernet/davicom/dm9000.h b/drivers/net/ethernet/davicom/dm9000.h index 55688bd1a3e..9ce058adaba 100644 --- a/drivers/net/ethernet/davicom/dm9000.h +++ b/drivers/net/ethernet/davicom/dm9000.h @@ -69,7 +69,9 @@ #define NCR_WAKEEN (1<<6) #define NCR_FCOL (1<<4) #define NCR_FDX (1<<3) -#define NCR_LBK (3<<1) + +#define NCR_RESERVED (3<<1) +#define NCR_MAC_LBK (1<<1) #define NCR_RST (1<<0) #define NSR_SPEED (1<<7) @@ -167,5 +169,12 @@ #define ISR_LNKCHNG (1<<5) #define ISR_UNDERRUN (1<<4) +/* Davicom MII registers. + */ + +#define MII_DM_DSPCR 0x1b /* DSP Control Register */ + +#define DSPCR_INIT_PARAM 0xE100 /* DSP init parameter */ + #endif /* _DM9000X_H_ */ diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h index 9576ac002c2..dcb02c219dd 100644 --- a/drivers/net/ethernet/emulex/benet/be.h +++ b/drivers/net/ethernet/emulex/benet/be.h @@ -536,6 +536,11 @@ static inline void be_check_sriov_fn_type(struct be_adapter *adapter) adapter->is_virtfn = (sli_intf & SLI_INTF_FT_MASK) ? 1 : 0; } +static inline bool is_ipv4_pkt(struct sk_buff *skb) +{ + return skb->protocol == ntohs(ETH_P_IP) && ip_hdr(skb)->version == 4; +} + static inline void be_vf_eth_addr_generate(struct be_adapter *adapter, u8 *mac) { u32 addr; diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 1bbf6b3eca9..ef1f9400b96 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -571,6 +571,11 @@ static inline u16 be_get_tx_vlan_tag(struct be_adapter *adapter, return vlan_tag; } +static int be_vlan_tag_chk(struct be_adapter *adapter, struct sk_buff *skb) +{ + return vlan_tx_tag_present(skb) || adapter->pvid; +} + static void wrb_fill_hdr(struct be_adapter *adapter, struct be_eth_hdr_wrb *hdr, struct sk_buff *skb, u32 wrb_cnt, u32 len) { @@ -698,33 +703,56 @@ static int make_tx_wrbs(struct be_adapter *adapter, struct be_queue_info *txq, return 0; } +static struct sk_buff *be_insert_vlan_in_pkt(struct be_adapter *adapter, + struct sk_buff *skb) +{ + u16 vlan_tag = 0; + + skb = skb_share_check(skb, GFP_ATOMIC); + if (unlikely(!skb)) + return skb; + + if (vlan_tx_tag_present(skb)) { + vlan_tag = be_get_tx_vlan_tag(adapter, skb); + __vlan_put_tag(skb, vlan_tag); + skb->vlan_tci = 0; + } + + return skb; +} + static netdev_tx_t be_xmit(struct sk_buff *skb, struct net_device *netdev) { struct be_adapter *adapter = netdev_priv(netdev); struct be_tx_obj *txo = &adapter->tx_obj[skb_get_queue_mapping(skb)]; struct be_queue_info *txq = &txo->q; + struct iphdr *ip = NULL; u32 wrb_cnt = 0, copied = 0; - u32 start = txq->head; + u32 start = txq->head, eth_hdr_len; bool dummy_wrb, stopped = false; - /* For vlan tagged pkts, BE - * 1) calculates checksum even when CSO is not requested - * 2) calculates checksum wrongly for padded pkt less than - * 60 bytes long. - * As a workaround disable TX vlan offloading in such cases. + eth_hdr_len = ntohs(skb->protocol) == ETH_P_8021Q ? + VLAN_ETH_HLEN : ETH_HLEN; + + /* HW has a bug which considers padding bytes as legal + * and modifies the IPv4 hdr's 'tot_len' field */ - if (unlikely(vlan_tx_tag_present(skb) && - (skb->ip_summed != CHECKSUM_PARTIAL || skb->len <= 60))) { - skb = skb_share_check(skb, GFP_ATOMIC); - if (unlikely(!skb)) - goto tx_drop; + if (skb->len <= 60 && be_vlan_tag_chk(adapter, skb) && + is_ipv4_pkt(skb)) { + ip = (struct iphdr *)ip_hdr(skb); + pskb_trim(skb, eth_hdr_len + ntohs(ip->tot_len)); + } - skb = __vlan_put_tag(skb, be_get_tx_vlan_tag(adapter, skb)); + /* HW has a bug wherein it will calculate CSUM for VLAN + * pkts even though it is disabled. + * Manually insert VLAN in pkt. + */ + if (skb->ip_summed != CHECKSUM_PARTIAL && + be_vlan_tag_chk(adapter, skb)) { + skb = be_insert_vlan_in_pkt(adapter, skb); if (unlikely(!skb)) goto tx_drop; - - skb->vlan_tci = 0; } wrb_cnt = wrb_cnt_for_skb(adapter, skb, &dummy_wrb); diff --git a/drivers/net/ethernet/freescale/gianfar_ptp.c b/drivers/net/ethernet/freescale/gianfar_ptp.c index 5fd620bec15..8de54e5ea37 100644 --- a/drivers/net/ethernet/freescale/gianfar_ptp.c +++ b/drivers/net/ethernet/freescale/gianfar_ptp.c @@ -127,7 +127,6 @@ struct gianfar_ptp_registers { #define DRIVER "gianfar_ptp" #define DEFAULT_CKSEL 1 -#define N_ALARM 1 /* first alarm is used internally to reset fipers */ #define N_EXT_TS 2 #define REG_SIZE sizeof(struct gianfar_ptp_registers) @@ -410,7 +409,7 @@ static struct ptp_clock_info ptp_gianfar_caps = { .owner = THIS_MODULE, .name = "gianfar clock", .max_adj = 512000, - .n_alarm = N_ALARM, + .n_alarm = 0, .n_ext_ts = N_EXT_TS, .n_per_out = 0, .pps = 1, @@ -521,6 +520,7 @@ static int gianfar_ptp_probe(struct platform_device *dev) return 0; no_clock: + iounmap(etsects->regs); no_ioremap: release_resource(etsects->rsrc); no_resource: diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c index b68d28a130e..33a17609dd0 100644 --- a/drivers/net/ethernet/ibm/ibmveth.c +++ b/drivers/net/ethernet/ibm/ibmveth.c @@ -1327,7 +1327,7 @@ static const struct net_device_ops ibmveth_netdev_ops = { static int __devinit ibmveth_probe(struct vio_dev *dev, const struct vio_device_id *id) { - int rc, i; + int rc, i, mac_len; struct net_device *netdev; struct ibmveth_adapter *adapter; unsigned char *mac_addr_p; @@ -1337,11 +1337,19 @@ static int __devinit ibmveth_probe(struct vio_dev *dev, dev->unit_address); mac_addr_p = (unsigned char *)vio_get_attribute(dev, VETH_MAC_ADDR, - NULL); + &mac_len); if (!mac_addr_p) { dev_err(&dev->dev, "Can't find VETH_MAC_ADDR attribute\n"); return -EINVAL; } + /* Workaround for old/broken pHyp */ + if (mac_len == 8) + mac_addr_p += 2; + else if (mac_len != 6) { + dev_err(&dev->dev, "VETH_MAC_ADDR attribute wrong len %d\n", + mac_len); + return -EINVAL; + } mcastFilterSize_p = (unsigned int *)vio_get_attribute(dev, VETH_MCAST_FILTER_SIZE, NULL); @@ -1366,17 +1374,6 @@ static int __devinit ibmveth_probe(struct vio_dev *dev, netif_napi_add(netdev, &adapter->napi, ibmveth_poll, 16); - /* - * Some older boxes running PHYP non-natively have an OF that returns - * a 8-byte local-mac-address field (and the first 2 bytes have to be - * ignored) while newer boxes' OF return a 6-byte field. Note that - * IEEE 1275 specifies that local-mac-address must be a 6-byte field. - * The RPA doc specifies that the first byte must be 10b, so we'll - * just look for it to solve this 8 vs. 6 byte field issue - */ - if ((*mac_addr_p & 0x3) != 0x02) - mac_addr_p += 2; - adapter->mac_addr = 0; memcpy(&adapter->mac_addr, mac_addr_p, 6); diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index 7e88aaff6ec..c80b4b4e657 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@ -5535,7 +5535,7 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake, */ e1000e_release_hw_control(adapter); - pci_disable_device(pdev); + pci_clear_master(pdev); return 0; } diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index 6b4f0148ee6..1fb180dbc7b 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -4649,11 +4649,13 @@ void igb_update_stats(struct igb_adapter *adapter, bytes = 0; packets = 0; for (i = 0; i < adapter->num_rx_queues; i++) { - u32 rqdpc_tmp = rd32(E1000_RQDPC(i)) & 0x0FFF; + u32 rqdpc = rd32(E1000_RQDPC(i)); struct igb_ring *ring = adapter->rx_ring[i]; - ring->rx_stats.drops += rqdpc_tmp; - net_stats->rx_fifo_errors += rqdpc_tmp; + if (rqdpc) { + ring->rx_stats.drops += rqdpc; + net_stats->rx_fifo_errors += rqdpc; + } do { start = u64_stats_fetch_begin_bh(&ring->rx_syncp); diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82598.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82598.c index d3695edfcb8..a061e37b132 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82598.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_82598.c @@ -108,9 +108,8 @@ s32 ixgbe_dcb_config_tx_desc_arbiter_82598(struct ixgbe_hw *hw, /* Enable arbiter */ reg &= ~IXGBE_DPMCS_ARBDIS; - /* Enable DFP and Recycle mode */ - reg |= (IXGBE_DPMCS_TDPAC | IXGBE_DPMCS_TRM); reg |= IXGBE_DPMCS_TSOEF; + /* Configure Max TSO packet size 34KB including payload and headers */ reg |= (0x4 << IXGBE_DPMCS_MTSOS_SHIFT); diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 6d1f6c51262..8f9554596c1 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -2263,6 +2263,16 @@ static irqreturn_t ixgbe_msix_other(int irq, void *data) * with the write to EICR. */ eicr = IXGBE_READ_REG(hw, IXGBE_EICS); + + /* The lower 16bits of the EICR register are for the queue interrupts + * which should be masked here in order to not accidently clear them if + * the bits are high when ixgbe_msix_other is called. There is a race + * condition otherwise which results in possible performance loss + * especially if the ixgbe_msix_other interrupt is triggering + * consistently (as it would when PPS is turned on for the X540 device) + */ + eicr &= 0xFFFF0000; + IXGBE_WRITE_REG(hw, IXGBE_EICR, eicr); if (eicr & IXGBE_EICR_LSC) diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c index 2b78ddd5d63..0dc9a35e73a 100644 --- a/drivers/net/ethernet/marvell/sky2.c +++ b/drivers/net/ethernet/marvell/sky2.c @@ -1066,7 +1066,7 @@ static void sky2_ramset(struct sky2_hw *hw, u16 q, u32 start, u32 space) sky2_write32(hw, RB_ADDR(q, RB_RX_UTHP), tp); sky2_write32(hw, RB_ADDR(q, RB_RX_LTHP), space/2); - tp = space - 2048/8; + tp = space - 8192/8; sky2_write32(hw, RB_ADDR(q, RB_RX_UTPP), tp); sky2_write32(hw, RB_ADDR(q, RB_RX_LTPP), space/4); } else { diff --git a/drivers/net/ethernet/marvell/sky2.h b/drivers/net/ethernet/marvell/sky2.h index 3c896ce80b7..a0f229ee9eb 100644 --- a/drivers/net/ethernet/marvell/sky2.h +++ b/drivers/net/ethernet/marvell/sky2.h @@ -2069,7 +2069,7 @@ enum { GM_IS_RX_FF_OR = 1<<1, /* Receive FIFO Overrun */ GM_IS_RX_COMPL = 1<<0, /* Frame Reception Complete */ -#define GMAC_DEF_MSK GM_IS_TX_FF_UR +#define GMAC_DEF_MSK (GM_IS_TX_FF_UR | GM_IS_RX_FF_OR) }; /* GMAC_LINK_CTRL 16 bit GMAC Link Control Reg (YUKON only) */ diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c index 17968244c39..efa3a13f8b1 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c @@ -683,10 +683,15 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev) ring->tx_csum++; } - /* Copy dst mac address to wqe */ - ethh = (struct ethhdr *)skb->data; - tx_desc->ctrl.srcrb_flags16[0] = get_unaligned((__be16 *)ethh->h_dest); - tx_desc->ctrl.imm = get_unaligned((__be32 *)(ethh->h_dest + 2)); + if (mlx4_is_mfunc(mdev->dev) || priv->validate_loopback) { + /* Copy dst mac address to wqe. This allows loopback in eSwitch, + * so that VFs and PF can communicate with each other + */ + ethh = (struct ethhdr *)skb->data; + tx_desc->ctrl.srcrb_flags16[0] = get_unaligned((__be16 *)ethh->h_dest); + tx_desc->ctrl.imm = get_unaligned((__be32 *)(ethh->h_dest + 2)); + } + /* Handle LSO (TSO) packets */ if (lso_header_size) { /* Mark opcode as LSO */ diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index 8bb05b46db8..1995cb05acf 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c @@ -1526,15 +1526,8 @@ static void mlx4_enable_msi_x(struct mlx4_dev *dev) int i; if (msi_x) { - /* In multifunction mode each function gets 2 msi-X vectors - * one for data path completions anf the other for asynch events - * or command completions */ - if (mlx4_is_mfunc(dev)) { - nreq = 2; - } else { - nreq = min_t(int, dev->caps.num_eqs - - dev->caps.reserved_eqs, nreq); - } + nreq = min_t(int, dev->caps.num_eqs - dev->caps.reserved_eqs, + nreq); entries = kcalloc(nreq, sizeof *entries, GFP_KERNEL); if (!entries) diff --git a/drivers/net/ethernet/micrel/ks8851.c b/drivers/net/ethernet/micrel/ks8851.c index a80735490cb..af22f9c4828 100644 --- a/drivers/net/ethernet/micrel/ks8851.c +++ b/drivers/net/ethernet/micrel/ks8851.c @@ -556,7 +556,7 @@ static void ks8851_rx_pkts(struct ks8851_net *ks) for (; rxfc != 0; rxfc--) { rxh = ks8851_rdreg32(ks, KS_RXFHSR); rxstat = rxh & 0xffff; - rxlen = rxh >> 16; + rxlen = (rxh >> 16) & 0xfff; netif_dbg(ks, rx_status, ks->netdev, "rx: stat 0x%04x, len 0x%04x\n", rxstat, rxlen); diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c index 1e38d502a06..8b1c2eb4c11 100644 --- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c +++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c @@ -1740,9 +1740,9 @@ pch_gbe_clean_rx(struct pch_gbe_adapter *adapter, skb->protocol = eth_type_trans(skb, netdev); if (tcp_ip_status & PCH_GBE_RXD_ACC_STAT_TCPIPOK) - skb->ip_summed = CHECKSUM_NONE; - else skb->ip_summed = CHECKSUM_UNNECESSARY; + else + skb->ip_summed = CHECKSUM_NONE; napi_gro_receive(&adapter->napi, skb); (*work_done)++; diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c index 718b2744035..83538ccddeb 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c @@ -144,7 +144,7 @@ void netxen_release_tx_buffers(struct netxen_adapter *adapter) buffrag->length, PCI_DMA_TODEVICE); buffrag->dma = 0ULL; } - for (j = 0; j < cmd_buf->frag_count; j++) { + for (j = 1; j < cmd_buf->frag_count; j++) { buffrag++; if (buffrag->dma) { pci_unmap_page(adapter->pdev, buffrag->dma, diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c index 22b399a9db9..7ee9c740085 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c @@ -1956,10 +1956,12 @@ netxen_map_tx_skb(struct pci_dev *pdev, while (--i >= 0) { nf = &pbuf->frag_array[i+1]; pci_unmap_page(pdev, nf->dma, nf->length, PCI_DMA_TODEVICE); + nf->dma = 0ULL; } nf = &pbuf->frag_array[0]; pci_unmap_single(pdev, nf->dma, skb_headlen(skb), PCI_DMA_TODEVICE); + nf->dma = 0ULL; out_err: return -ENOMEM; diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c index b3287c0fe27..2205db73bc5 100644 --- a/drivers/net/ethernet/realtek/8139cp.c +++ b/drivers/net/ethernet/realtek/8139cp.c @@ -478,7 +478,7 @@ static int cp_rx_poll(struct napi_struct *napi, int budget) while (1) { u32 status, len; - dma_addr_t mapping; + dma_addr_t mapping, new_mapping; struct sk_buff *skb, *new_skb; struct cp_desc *desc; const unsigned buflen = cp->rx_buf_sz; @@ -520,6 +520,13 @@ static int cp_rx_poll(struct napi_struct *napi, int budget) goto rx_next; } + new_mapping = dma_map_single(&cp->pdev->dev, new_skb->data, buflen, + PCI_DMA_FROMDEVICE); + if (dma_mapping_error(&cp->pdev->dev, new_mapping)) { + dev->stats.rx_dropped++; + goto rx_next; + } + dma_unmap_single(&cp->pdev->dev, mapping, buflen, PCI_DMA_FROMDEVICE); @@ -531,12 +538,11 @@ static int cp_rx_poll(struct napi_struct *napi, int budget) skb_put(skb, len); - mapping = dma_map_single(&cp->pdev->dev, new_skb->data, buflen, - PCI_DMA_FROMDEVICE); cp->rx_skb[rx_tail] = new_skb; cp_rx_skb(cp, skb, desc); rx++; + mapping = new_mapping; rx_next: cp->rx_ring[rx_tail].opts2 = 0; @@ -704,6 +710,22 @@ static inline u32 cp_tx_vlan_tag(struct sk_buff *skb) TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00; } +static void unwind_tx_frag_mapping(struct cp_private *cp, struct sk_buff *skb, + int first, int entry_last) +{ + int frag, index; + struct cp_desc *txd; + skb_frag_t *this_frag; + for (frag = 0; frag+first < entry_last; frag++) { + index = first+frag; + cp->tx_skb[index] = NULL; + txd = &cp->tx_ring[index]; + this_frag = &skb_shinfo(skb)->frags[frag]; + dma_unmap_single(&cp->pdev->dev, le64_to_cpu(txd->addr), + skb_frag_size(this_frag), PCI_DMA_TODEVICE); + } +} + static netdev_tx_t cp_start_xmit (struct sk_buff *skb, struct net_device *dev) { @@ -737,6 +759,9 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb, len = skb->len; mapping = dma_map_single(&cp->pdev->dev, skb->data, len, PCI_DMA_TODEVICE); + if (dma_mapping_error(&cp->pdev->dev, mapping)) + goto out_dma_error; + txd->opts2 = opts2; txd->addr = cpu_to_le64(mapping); wmb(); @@ -774,6 +799,9 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb, first_len = skb_headlen(skb); first_mapping = dma_map_single(&cp->pdev->dev, skb->data, first_len, PCI_DMA_TODEVICE); + if (dma_mapping_error(&cp->pdev->dev, first_mapping)) + goto out_dma_error; + cp->tx_skb[entry] = skb; entry = NEXT_TX(entry); @@ -787,6 +815,11 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb, mapping = dma_map_single(&cp->pdev->dev, skb_frag_address(this_frag), len, PCI_DMA_TODEVICE); + if (dma_mapping_error(&cp->pdev->dev, mapping)) { + unwind_tx_frag_mapping(cp, skb, first_entry, entry); + goto out_dma_error; + } + eor = (entry == (CP_TX_RING_SIZE - 1)) ? RingEnd : 0; ctrl = eor | len | DescOwn; @@ -845,11 +878,16 @@ static netdev_tx_t cp_start_xmit (struct sk_buff *skb, if (TX_BUFFS_AVAIL(cp) <= (MAX_SKB_FRAGS + 1)) netif_stop_queue(dev); +out_unlock: spin_unlock_irqrestore(&cp->lock, intr_flags); cpw8(TxPoll, NormalTxPoll); return NETDEV_TX_OK; +out_dma_error: + kfree_skb(skb); + cp->dev->stats.tx_dropped++; + goto out_unlock; } /* Set or clear the multicast filter for this adaptor. @@ -1020,6 +1058,10 @@ static int cp_refill_rx(struct cp_private *cp) mapping = dma_map_single(&cp->pdev->dev, skb->data, cp->rx_buf_sz, PCI_DMA_FROMDEVICE); + if (dma_mapping_error(&cp->pdev->dev, mapping)) { + kfree_skb(skb); + goto err_out; + } cp->rx_skb[i] = skb; cp->rx_ring[i].opts2 = 0; @@ -1097,6 +1139,7 @@ static void cp_clean_rings (struct cp_private *cp) cp->dev->stats.tx_dropped++; } } + netdev_reset_queue(cp->dev); memset(cp->rx_ring, 0, sizeof(struct cp_desc) * CP_RX_RING_SIZE); memset(cp->tx_ring, 0, sizeof(struct cp_desc) * CP_TX_RING_SIZE); diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index 06ee243d41a..2a59e7a7106 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -1690,8 +1690,6 @@ static void rtl8169_rx_vlan_tag(struct RxDesc *desc, struct sk_buff *skb) if (opts2 & RxVlanTag) __vlan_hwaccel_put_tag(skb, swab16(opts2 & 0xffff)); - - desc->opts2 = 0; } static int rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd) @@ -3483,6 +3481,30 @@ static void __devinit rtl_init_mdio_ops(struct rtl8169_private *tp) } } +static void rtl_speed_down(struct rtl8169_private *tp) +{ + u32 adv; + int lpa; + + rtl_writephy(tp, 0x1f, 0x0000); + lpa = rtl_readphy(tp, MII_LPA); + + if (lpa & (LPA_10HALF | LPA_10FULL)) + adv = ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full; + else if (lpa & (LPA_100HALF | LPA_100FULL)) + adv = ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | + ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full; + else + adv = ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | + ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | + (tp->mii.supports_gmii ? + ADVERTISED_1000baseT_Half | + ADVERTISED_1000baseT_Full : 0); + + rtl8169_set_speed(tp->dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL, + adv); +} + static void rtl_wol_suspend_quirk(struct rtl8169_private *tp) { void __iomem *ioaddr = tp->mmio_addr; @@ -3508,9 +3530,7 @@ static bool rtl_wol_pll_power_down(struct rtl8169_private *tp) if (!(__rtl8169_get_wol(tp) & WAKE_ANY)) return false; - rtl_writephy(tp, 0x1f, 0x0000); - rtl_writephy(tp, MII_BMCR, 0x0000); - + rtl_speed_down(tp); rtl_wol_suspend_quirk(tp); return true; @@ -5106,7 +5126,20 @@ static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb, return -EIO; } -static inline void rtl8169_tso_csum(struct rtl8169_private *tp, +static bool rtl_skb_pad(struct sk_buff *skb) +{ + if (skb_padto(skb, ETH_ZLEN)) + return false; + skb_put(skb, ETH_ZLEN - skb->len); + return true; +} + +static bool rtl_test_hw_pad_bug(struct rtl8169_private *tp, struct sk_buff *skb) +{ + return skb->len < ETH_ZLEN && tp->mac_version == RTL_GIGA_MAC_VER_34; +} + +static inline bool rtl8169_tso_csum(struct rtl8169_private *tp, struct sk_buff *skb, u32 *opts) { const struct rtl_tx_desc_info *info = tx_desc_info + tp->txd_version; @@ -5119,13 +5152,20 @@ static inline void rtl8169_tso_csum(struct rtl8169_private *tp, } else if (skb->ip_summed == CHECKSUM_PARTIAL) { const struct iphdr *ip = ip_hdr(skb); + if (unlikely(rtl_test_hw_pad_bug(tp, skb))) + return skb_checksum_help(skb) == 0 && rtl_skb_pad(skb); + if (ip->protocol == IPPROTO_TCP) opts[offset] |= info->checksum.tcp; else if (ip->protocol == IPPROTO_UDP) opts[offset] |= info->checksum.udp; else WARN_ON_ONCE(1); + } else { + if (unlikely(rtl_test_hw_pad_bug(tp, skb))) + return rtl_skb_pad(skb); } + return true; } static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, @@ -5149,6 +5189,12 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, if (unlikely(le32_to_cpu(txd->opts1) & DescOwn)) goto err_stop_0; + opts[1] = cpu_to_le32(rtl8169_tx_vlan_tag(tp, skb)); + opts[0] = DescOwn; + + if (!rtl8169_tso_csum(tp, skb, opts)) + goto err_update_stats; + len = skb_headlen(skb); mapping = dma_map_single(d, skb->data, len, DMA_TO_DEVICE); if (unlikely(dma_mapping_error(d, mapping))) { @@ -5160,11 +5206,6 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, tp->tx_skb[entry].len = len; txd->addr = cpu_to_le64(mapping); - opts[1] = cpu_to_le32(rtl8169_tx_vlan_tag(tp, skb)); - opts[0] = DescOwn; - - rtl8169_tso_csum(tp, skb, opts); - frags = rtl8169_xmit_frags(tp, skb, opts); if (frags < 0) goto err_dma_1; @@ -5217,6 +5258,7 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, rtl8169_unmap_tx_skb(d, tp->tx_skb + entry, txd); err_dma_0: dev_kfree_skb(skb); +err_update_stats: dev->stats.tx_dropped++; return NETDEV_TX_OK; @@ -5403,8 +5445,6 @@ static int rtl_rx(struct net_device *dev, struct rtl8169_private *tp, u32 budget !(status & (RxRWT | RxFOVF)) && (dev->features & NETIF_F_RXALL)) goto process_pkt; - - rtl8169_mark_to_asic(desc, rx_buf_sz); } else { struct sk_buff *skb; dma_addr_t addr; @@ -5425,16 +5465,14 @@ static int rtl_rx(struct net_device *dev, struct rtl8169_private *tp, u32 budget if (unlikely(rtl8169_fragmented_frame(status))) { dev->stats.rx_dropped++; dev->stats.rx_length_errors++; - rtl8169_mark_to_asic(desc, rx_buf_sz); - continue; + goto release_descriptor; } skb = rtl8169_try_rx_copy(tp->Rx_databuff[entry], tp, pkt_size, addr); - rtl8169_mark_to_asic(desc, rx_buf_sz); if (!skb) { dev->stats.rx_dropped++; - continue; + goto release_descriptor; } rtl8169_rx_csum(skb, status); @@ -5450,13 +5488,10 @@ static int rtl_rx(struct net_device *dev, struct rtl8169_private *tp, u32 budget tp->rx_stats.bytes += pkt_size; u64_stats_update_end(&tp->rx_stats.syncp); } - - /* Work around for AMD plateform. */ - if ((desc->opts2 & cpu_to_le32(0xfffe000)) && - (tp->mac_version == RTL_GIGA_MAC_VER_05)) { - desc->opts2 = 0; - cur_rx++; - } +release_descriptor: + desc->opts2 = 0; + wmb(); + rtl8169_mark_to_asic(desc, rx_buf_sz); } count = cur_rx - tp->cur_rx; diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index d63e09b29a9..16caebaec00 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -137,8 +137,9 @@ static struct sh_eth_cpu_data sh_eth_my_cpu_data = { .rmcr_value = 0x00000001, .tx_check = EESR_FTC | EESR_CND | EESR_DLC | EESR_CD | EESR_RTO, - .eesr_err_check = EESR_TWB | EESR_TABT | EESR_RABT | EESR_RDE | - EESR_RFRMER | EESR_TFE | EESR_TDE | EESR_ECI, + .eesr_err_check = EESR_TWB | EESR_TABT | EESR_RABT | EESR_RFE | + EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE | + EESR_ECI, .tx_error_check = EESR_TWB | EESR_TABT | EESR_TDE | EESR_TFE, .apr = 1, @@ -252,9 +253,9 @@ static struct sh_eth_cpu_data sh_eth_my_cpu_data_giga = { .eesipr_value = DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff, .tx_check = EESR_TC1 | EESR_FTC, - .eesr_err_check = EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT | \ - EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE | \ - EESR_ECI, + .eesr_err_check = EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT | + EESR_RFE | EESR_RDE | EESR_RFRMER | EESR_TFE | + EESR_TDE | EESR_ECI, .tx_error_check = EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_TDE | \ EESR_TFE, .fdr_value = 0x0000072f, @@ -361,9 +362,9 @@ static struct sh_eth_cpu_data sh_eth_my_cpu_data = { .eesipr_value = DMAC_M_RFRMER | DMAC_M_ECI | 0x003fffff, .tx_check = EESR_TC1 | EESR_FTC, - .eesr_err_check = EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT | \ - EESR_RDE | EESR_RFRMER | EESR_TFE | EESR_TDE | \ - EESR_ECI, + .eesr_err_check = EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT | + EESR_RFE | EESR_RDE | EESR_RFRMER | EESR_TFE | + EESR_TDE | EESR_ECI, .tx_error_check = EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_TDE | \ EESR_TFE, diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h index 0fa14afce23..c49097f8e3c 100644 --- a/drivers/net/ethernet/renesas/sh_eth.h +++ b/drivers/net/ethernet/renesas/sh_eth.h @@ -467,7 +467,7 @@ enum EESR_BIT { #define DEFAULT_TX_CHECK (EESR_FTC | EESR_CND | EESR_DLC | EESR_CD | \ EESR_RTO) -#define DEFAULT_EESR_ERR_CHECK (EESR_TWB | EESR_TABT | EESR_RABT | \ +#define DEFAULT_EESR_ERR_CHECK (EESR_TWB | EESR_TABT | EESR_RABT | EESR_RFE | \ EESR_RDE | EESR_RFRMER | EESR_ADE | \ EESR_TFE | EESR_TDE | EESR_ECI) #define DEFAULT_TX_ERROR_CHECK (EESR_TWB | EESR_TABT | EESR_ADE | EESR_TDE | \ diff --git a/drivers/net/ethernet/sfc/bitfield.h b/drivers/net/ethernet/sfc/bitfield.h index b26a954c27f..5400a33f254 100644 --- a/drivers/net/ethernet/sfc/bitfield.h +++ b/drivers/net/ethernet/sfc/bitfield.h @@ -120,10 +120,10 @@ typedef union efx_oword { * [0,high-low), with garbage in bits [high-low+1,...). */ #define EFX_EXTRACT_NATIVE(native_element, min, max, low, high) \ - (((low > max) || (high < min)) ? 0 : \ - ((low > min) ? \ - ((native_element) >> (low - min)) : \ - ((native_element) << (min - low)))) + ((low) > (max) || (high) < (min) ? 0 : \ + (low) > (min) ? \ + (native_element) >> ((low) - (min)) : \ + (native_element) << ((min) - (low))) /* * Extract bit field portion [low,high) from the 64-bit little-endian @@ -142,27 +142,27 @@ typedef union efx_oword { #define EFX_EXTRACT_OWORD64(oword, low, high) \ ((EFX_EXTRACT64((oword).u64[0], 0, 63, low, high) | \ EFX_EXTRACT64((oword).u64[1], 64, 127, low, high)) & \ - EFX_MASK64(high + 1 - low)) + EFX_MASK64((high) + 1 - (low))) #define EFX_EXTRACT_QWORD64(qword, low, high) \ (EFX_EXTRACT64((qword).u64[0], 0, 63, low, high) & \ - EFX_MASK64(high + 1 - low)) + EFX_MASK64((high) + 1 - (low))) #define EFX_EXTRACT_OWORD32(oword, low, high) \ ((EFX_EXTRACT32((oword).u32[0], 0, 31, low, high) | \ EFX_EXTRACT32((oword).u32[1], 32, 63, low, high) | \ EFX_EXTRACT32((oword).u32[2], 64, 95, low, high) | \ EFX_EXTRACT32((oword).u32[3], 96, 127, low, high)) & \ - EFX_MASK32(high + 1 - low)) + EFX_MASK32((high) + 1 - (low))) #define EFX_EXTRACT_QWORD32(qword, low, high) \ ((EFX_EXTRACT32((qword).u32[0], 0, 31, low, high) | \ EFX_EXTRACT32((qword).u32[1], 32, 63, low, high)) & \ - EFX_MASK32(high + 1 - low)) + EFX_MASK32((high) + 1 - (low))) #define EFX_EXTRACT_DWORD(dword, low, high) \ (EFX_EXTRACT32((dword).u32[0], 0, 31, low, high) & \ - EFX_MASK32(high + 1 - low)) + EFX_MASK32((high) + 1 - (low))) #define EFX_OWORD_FIELD64(oword, field) \ EFX_EXTRACT_OWORD64(oword, EFX_LOW_BIT(field), \ @@ -442,10 +442,10 @@ typedef union efx_oword { cpu_to_le32(EFX_INSERT_NATIVE(min, max, low, high, value)) #define EFX_INPLACE_MASK64(min, max, low, high) \ - EFX_INSERT64(min, max, low, high, EFX_MASK64(high + 1 - low)) + EFX_INSERT64(min, max, low, high, EFX_MASK64((high) + 1 - (low))) #define EFX_INPLACE_MASK32(min, max, low, high) \ - EFX_INSERT32(min, max, low, high, EFX_MASK32(high + 1 - low)) + EFX_INSERT32(min, max, low, high, EFX_MASK32((high) + 1 - (low))) #define EFX_SET_OWORD64(oword, low, high, value) do { \ (oword).u64[0] = (((oword).u64[0] \ diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index 954b8854b25..a87f3510741 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -656,25 +656,30 @@ static void efx_stop_datapath(struct efx_nic *efx) struct efx_channel *channel; struct efx_tx_queue *tx_queue; struct efx_rx_queue *rx_queue; + struct pci_dev *dev = efx->pci_dev; int rc; EFX_ASSERT_RESET_SERIALISED(efx); BUG_ON(efx->port_enabled); - rc = efx_nic_flush_queues(efx); - if (rc && EFX_WORKAROUND_7803(efx)) { - /* Schedule a reset to recover from the flush failure. The - * descriptor caches reference memory we're about to free, - * but falcon_reconfigure_mac_wrapper() won't reconnect - * the MACs because of the pending reset. */ - netif_err(efx, drv, efx->net_dev, - "Resetting to recover from flush failure\n"); - efx_schedule_reset(efx, RESET_TYPE_ALL); - } else if (rc) { - netif_err(efx, drv, efx->net_dev, "failed to flush queues\n"); - } else { - netif_dbg(efx, drv, efx->net_dev, - "successfully flushed all queues\n"); + /* Only perform flush if dma is enabled */ + if (dev->is_busmaster) { + rc = efx_nic_flush_queues(efx); + + if (rc && EFX_WORKAROUND_7803(efx)) { + /* Schedule a reset to recover from the flush failure. The + * descriptor caches reference memory we're about to free, + * but falcon_reconfigure_mac_wrapper() won't reconnect + * the MACs because of the pending reset. */ + netif_err(efx, drv, efx->net_dev, + "Resetting to recover from flush failure\n"); + efx_schedule_reset(efx, RESET_TYPE_ALL); + } else if (rc) { + netif_err(efx, drv, efx->net_dev, "failed to flush queues\n"); + } else { + netif_dbg(efx, drv, efx->net_dev, + "successfully flushed all queues\n"); + } } efx_for_each_channel(channel, efx) { @@ -749,6 +754,7 @@ efx_realloc_channels(struct efx_nic *efx, u32 rxq_entries, u32 txq_entries) tx_queue->txd.entries); } + efx_device_detach_sync(efx); efx_stop_all(efx); efx_stop_interrupts(efx, true); @@ -802,6 +808,7 @@ efx_realloc_channels(struct efx_nic *efx, u32 rxq_entries, u32 txq_entries) efx_start_interrupts(efx, true); efx_start_all(efx); + netif_device_attach(efx->net_dev); return rc; rollback: @@ -1596,8 +1603,12 @@ static void efx_stop_all(struct efx_nic *efx) /* Flush efx_mac_work(), refill_workqueue, monitor_work */ efx_flush_all(efx); - /* Stop the kernel transmit interface late, so the watchdog - * timer isn't ticking over the flush */ + /* Stop the kernel transmit interface. This is only valid if + * the device is stopped or detached; otherwise the watchdog + * may fire immediately. + */ + WARN_ON(netif_running(efx->net_dev) && + netif_device_present(efx->net_dev)); netif_tx_disable(efx->net_dev); efx_stop_datapath(efx); @@ -1916,10 +1927,11 @@ static int efx_change_mtu(struct net_device *net_dev, int new_mtu) if (new_mtu > EFX_MAX_MTU) return -EINVAL; - efx_stop_all(efx); - netif_dbg(efx, drv, efx->net_dev, "changing MTU to %d\n", new_mtu); + efx_device_detach_sync(efx); + efx_stop_all(efx); + mutex_lock(&efx->mac_lock); /* Reconfigure the MAC before enabling the dma queues so that * the RX buffers don't overflow */ @@ -1928,6 +1940,7 @@ static int efx_change_mtu(struct net_device *net_dev, int new_mtu) mutex_unlock(&efx->mac_lock); efx_start_all(efx); + netif_device_attach(efx->net_dev); return 0; } @@ -2219,7 +2232,7 @@ int efx_reset(struct efx_nic *efx, enum reset_type method) netif_info(efx, drv, efx->net_dev, "resetting (%s)\n", RESET_TYPE(method)); - netif_device_detach(efx->net_dev); + efx_device_detach_sync(efx); efx_reset_down(efx, method); rc = efx->type->reset(efx, method); @@ -2713,7 +2726,7 @@ static int efx_pm_freeze(struct device *dev) efx->state = STATE_FINI; - netif_device_detach(efx->net_dev); + efx_device_detach_sync(efx); efx_stop_all(efx); efx_stop_interrupts(efx, false); diff --git a/drivers/net/ethernet/sfc/efx.h b/drivers/net/ethernet/sfc/efx.h index 70755c97251..7db0e5bfc9e 100644 --- a/drivers/net/ethernet/sfc/efx.h +++ b/drivers/net/ethernet/sfc/efx.h @@ -162,4 +162,17 @@ extern void efx_link_status_changed(struct efx_nic *efx); extern void efx_link_set_advertising(struct efx_nic *efx, u32); extern void efx_link_set_wanted_fc(struct efx_nic *efx, u8); +static inline void efx_device_detach_sync(struct efx_nic *efx) +{ + struct net_device *dev = efx->net_dev; + + /* Lock/freeze all TX queues so that we can be sure the + * TX scheduler is stopped when we're done and before + * netif_device_present() becomes false. + */ + netif_tx_lock_bh(dev); + netif_device_detach(dev); + netif_tx_unlock_bh(dev); +} + #endif /* EFX_EFX_H */ diff --git a/drivers/net/ethernet/sfc/falcon.c b/drivers/net/ethernet/sfc/falcon.c index 3a1ca2bd154..49bcd196e10 100644 --- a/drivers/net/ethernet/sfc/falcon.c +++ b/drivers/net/ethernet/sfc/falcon.c @@ -25,9 +25,12 @@ #include "io.h" #include "phy.h" #include "workarounds.h" +#include "selftest.h" /* Hardware control for SFC4000 (aka Falcon). */ +static int falcon_reset_hw(struct efx_nic *efx, enum reset_type method); + static const unsigned int /* "Large" EEPROM device: Atmel AT25640 or similar * 8 KB, 16-bit address, 32 B write block */ @@ -1034,10 +1037,34 @@ static const struct efx_nic_register_test falcon_b0_register_tests[] = { EFX_OWORD32(0x0003FF0F, 0x00000000, 0x00000000, 0x00000000) }, }; -static int falcon_b0_test_registers(struct efx_nic *efx) +static int +falcon_b0_test_chip(struct efx_nic *efx, struct efx_self_tests *tests) { - return efx_nic_test_registers(efx, falcon_b0_register_tests, - ARRAY_SIZE(falcon_b0_register_tests)); + enum reset_type reset_method = RESET_TYPE_INVISIBLE; + int rc, rc2; + + mutex_lock(&efx->mac_lock); + if (efx->loopback_modes) { + /* We need the 312 clock from the PHY to test the XMAC + * registers, so move into XGMII loopback if available */ + if (efx->loopback_modes & (1 << LOOPBACK_XGMII)) + efx->loopback_mode = LOOPBACK_XGMII; + else + efx->loopback_mode = __ffs(efx->loopback_modes); + } + __efx_reconfigure_port(efx); + mutex_unlock(&efx->mac_lock); + + efx_reset_down(efx, reset_method); + + tests->registers = + efx_nic_test_registers(efx, falcon_b0_register_tests, + ARRAY_SIZE(falcon_b0_register_tests)) + ? -1 : 1; + + rc = falcon_reset_hw(efx, reset_method); + rc2 = efx_reset_up(efx, reset_method, rc == 0); + return rc ? rc : rc2; } /************************************************************************** @@ -1765,6 +1792,7 @@ const struct efx_nic_type falcon_a1_nic_type = { .remove_port = falcon_remove_port, .handle_global_event = falcon_handle_global_event, .prepare_flush = falcon_prepare_flush, + .finish_flush = efx_port_dummy_op_void, .update_stats = falcon_update_nic_stats, .start_stats = falcon_start_nic_stats, .stop_stats = falcon_stop_nic_stats, @@ -1807,6 +1835,7 @@ const struct efx_nic_type falcon_b0_nic_type = { .remove_port = falcon_remove_port, .handle_global_event = falcon_handle_global_event, .prepare_flush = falcon_prepare_flush, + .finish_flush = efx_port_dummy_op_void, .update_stats = falcon_update_nic_stats, .start_stats = falcon_start_nic_stats, .stop_stats = falcon_stop_nic_stats, @@ -1818,7 +1847,7 @@ const struct efx_nic_type falcon_b0_nic_type = { .get_wol = falcon_get_wol, .set_wol = falcon_set_wol, .resume_wol = efx_port_dummy_op_void, - .test_registers = falcon_b0_test_registers, + .test_chip = falcon_b0_test_chip, .test_nvram = falcon_test_nvram, .revision = EFX_REV_FALCON_B0, diff --git a/drivers/net/ethernet/sfc/mcdi.c b/drivers/net/ethernet/sfc/mcdi.c index 17b6463e459..192026f0e8d 100644 --- a/drivers/net/ethernet/sfc/mcdi.c +++ b/drivers/net/ethernet/sfc/mcdi.c @@ -22,7 +22,7 @@ ************************************************************************** */ -#define MCDI_RPC_TIMEOUT 10 /*seconds */ +#define MCDI_RPC_TIMEOUT (10 * HZ) #define MCDI_PDU(efx) \ (efx_port_num(efx) ? MC_SMEM_P1_PDU_OFST : MC_SMEM_P0_PDU_OFST) @@ -120,7 +120,7 @@ static void efx_mcdi_copyout(struct efx_nic *efx, u8 *outbuf, size_t outlen) static int efx_mcdi_poll(struct efx_nic *efx) { struct efx_mcdi_iface *mcdi = efx_mcdi(efx); - unsigned int time, finish; + unsigned long time, finish; unsigned int respseq, respcmd, error; unsigned int pdu = FR_CZ_MC_TREG_SMEM + MCDI_PDU(efx); unsigned int rc, spins; @@ -136,7 +136,7 @@ static int efx_mcdi_poll(struct efx_nic *efx) * and poll once a jiffy (approximately) */ spins = TICK_USEC; - finish = get_seconds() + MCDI_RPC_TIMEOUT; + finish = jiffies + MCDI_RPC_TIMEOUT; while (1) { if (spins != 0) { @@ -146,7 +146,7 @@ static int efx_mcdi_poll(struct efx_nic *efx) schedule_timeout_uninterruptible(1); } - time = get_seconds(); + time = jiffies; rmb(); efx_readd(efx, ®, pdu); @@ -158,7 +158,7 @@ static int efx_mcdi_poll(struct efx_nic *efx) EFX_DWORD_FIELD(reg, MCDI_HEADER_RESPONSE)) break; - if (time >= finish) + if (time_after(time, finish)) return -ETIMEDOUT; } @@ -250,7 +250,7 @@ static int efx_mcdi_await_completion(struct efx_nic *efx) if (wait_event_timeout( mcdi->wq, atomic_read(&mcdi->state) == MCDI_STATE_COMPLETED, - msecs_to_jiffies(MCDI_RPC_TIMEOUT * 1000)) == 0) + MCDI_RPC_TIMEOUT) == 0) return -ETIMEDOUT; /* Check if efx_mcdi_set_mode() switched us back to polled completions. @@ -640,10 +640,9 @@ int efx_mcdi_drv_attach(struct efx_nic *efx, bool driver_operating, int efx_mcdi_get_board_cfg(struct efx_nic *efx, u8 *mac_address, u16 *fw_subtype_list, u32 *capabilities) { - uint8_t outbuf[MC_CMD_GET_BOARD_CFG_OUT_LENMIN]; - size_t outlen; + uint8_t outbuf[MC_CMD_GET_BOARD_CFG_OUT_LENMAX]; + size_t outlen, offset, i; int port_num = efx_port_num(efx); - int offset; int rc; BUILD_BUG_ON(MC_CMD_GET_BOARD_CFG_IN_LEN != 0); @@ -663,11 +662,16 @@ int efx_mcdi_get_board_cfg(struct efx_nic *efx, u8 *mac_address, : MC_CMD_GET_BOARD_CFG_OUT_MAC_ADDR_BASE_PORT0_OFST; if (mac_address) memcpy(mac_address, outbuf + offset, ETH_ALEN); - if (fw_subtype_list) - memcpy(fw_subtype_list, - outbuf + MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_OFST, - MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_MINNUM * - sizeof(fw_subtype_list[0])); + if (fw_subtype_list) { + offset = MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_OFST; + for (i = 0; + i < MC_CMD_GET_BOARD_CFG_OUT_FW_SUBTYPE_LIST_MINNUM; + i++) { + fw_subtype_list[i] = + le16_to_cpup((__le16 *)(outbuf + offset)); + offset += 2; + } + } if (capabilities) { if (port_num) *capabilities = MCDI_DWORD(outbuf, @@ -1164,6 +1168,9 @@ int efx_mcdi_flush_rxqs(struct efx_nic *efx) __le32 *qid; int rc, count; + BUILD_BUG_ON(EFX_MAX_CHANNELS > + MC_CMD_FLUSH_RX_QUEUES_IN_QID_OFST_MAXNUM); + qid = kmalloc(EFX_MAX_CHANNELS * sizeof(*qid), GFP_KERNEL); if (qid == NULL) return -ENOMEM; diff --git a/drivers/net/ethernet/sfc/mcdi.h b/drivers/net/ethernet/sfc/mcdi.h index 0bdf3e33183..96f43d2179c 100644 --- a/drivers/net/ethernet/sfc/mcdi.h +++ b/drivers/net/ethernet/sfc/mcdi.h @@ -107,11 +107,13 @@ extern void efx_mcdi_sensor_event(struct efx_nic *efx, efx_qword_t *ev); #define MCDI_EVENT_FIELD(_ev, _field) \ EFX_QWORD_FIELD(_ev, MCDI_EVENT_ ## _field) #define MCDI_ARRAY_FIELD(_buf, _field1, _type, _index, _field2) \ - EFX_DWORD_FIELD( \ + EFX_EXTRACT_DWORD( \ *((efx_dword_t *) \ (MCDI_ARRAY_PTR(_buf, _field1, _type, _index) + \ (MC_CMD_ ## _type ## _TYPEDEF_ ## _field2 ## _OFST & ~3))), \ - MC_CMD_ ## _type ## _TYPEDEF_ ## _field2) + MC_CMD_ ## _type ## _TYPEDEF_ ## _field2 ## _LBN & 0x1f, \ + (MC_CMD_ ## _type ## _TYPEDEF_ ## _field2 ## _LBN & 0x1f) + \ + MC_CMD_ ## _type ## _TYPEDEF_ ## _field2 ## _WIDTH - 1) extern void efx_mcdi_print_fwver(struct efx_nic *efx, char *buf, size_t len); extern int efx_mcdi_drv_attach(struct efx_nic *efx, bool driver_operating, diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index f0385e1fb2d..b71ef140085 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h @@ -68,6 +68,8 @@ #define EFX_TXQ_TYPES 4 #define EFX_MAX_TX_QUEUES (EFX_TXQ_TYPES * EFX_MAX_CHANNELS) +struct efx_self_tests; + /** * struct efx_special_buffer - An Efx special buffer * @addr: CPU base address of the buffer @@ -194,6 +196,7 @@ struct efx_tx_queue { /* Members shared between paths and sometimes updated */ unsigned int empty_read_count ____cacheline_aligned_in_smp; #define EFX_EMPTY_COUNT_VALID 0x80000000 + atomic_t flush_outstanding; }; /** @@ -203,6 +206,7 @@ struct efx_tx_queue { * Will be %NULL if the buffer slot is currently free. * @page: The associated page buffer. Valif iff @flags & %EFX_RX_BUF_PAGE. * Will be %NULL if the buffer slot is currently free. + * @page_offset: Offset within page. Valid iff @flags & %EFX_RX_BUF_PAGE. * @len: Buffer length, in bytes. * @flags: Flags for buffer and packet state. */ @@ -212,7 +216,8 @@ struct efx_rx_buffer { struct sk_buff *skb; struct page *page; } u; - unsigned int len; + u16 page_offset; + u16 len; u16 flags; }; #define EFX_RX_BUF_PAGE 0x0001 @@ -887,6 +892,7 @@ static inline unsigned int efx_port_num(struct efx_nic *efx) * @remove_port: Free resources allocated by probe_port() * @handle_global_event: Handle a "global" event (may be %NULL) * @prepare_flush: Prepare the hardware for flushing the DMA queues + * @finish_flush: Clean up after flushing the DMA queues * @update_stats: Update statistics not provided by event handling * @start_stats: Start the regular fetching of statistics * @stop_stats: Stop the regular fetching of statistics @@ -899,7 +905,8 @@ static inline unsigned int efx_port_num(struct efx_nic *efx) * @get_wol: Get WoL configuration from driver state * @set_wol: Push WoL configuration to the NIC * @resume_wol: Synchronise WoL state between driver and MC (e.g. after resume) - * @test_registers: Test read/write functionality of control registers + * @test_chip: Test registers. Should use efx_nic_test_registers(), and is + * expected to reset the NIC. * @test_nvram: Test validity of NVRAM contents * @revision: Hardware architecture revision * @mem_map_size: Memory BAR mapped size @@ -933,6 +940,7 @@ struct efx_nic_type { void (*remove_port)(struct efx_nic *efx); bool (*handle_global_event)(struct efx_channel *channel, efx_qword_t *); void (*prepare_flush)(struct efx_nic *efx); + void (*finish_flush)(struct efx_nic *efx); void (*update_stats)(struct efx_nic *efx); void (*start_stats)(struct efx_nic *efx); void (*stop_stats)(struct efx_nic *efx); @@ -944,7 +952,7 @@ struct efx_nic_type { void (*get_wol)(struct efx_nic *efx, struct ethtool_wolinfo *wol); int (*set_wol)(struct efx_nic *efx, u32 type); void (*resume_wol)(struct efx_nic *efx); - int (*test_registers)(struct efx_nic *efx); + int (*test_chip)(struct efx_nic *efx, struct efx_self_tests *tests); int (*test_nvram)(struct efx_nic *efx); int revision; diff --git a/drivers/net/ethernet/sfc/nic.c b/drivers/net/ethernet/sfc/nic.c index 4a9a5beec8f..578e52a6eff 100644 --- a/drivers/net/ethernet/sfc/nic.c +++ b/drivers/net/ethernet/sfc/nic.c @@ -73,6 +73,8 @@ _EFX_CHANNEL_MAGIC(_EFX_CHANNEL_MAGIC_TX_DRAIN, \ (_tx_queue)->queue) +static void efx_magic_event(struct efx_channel *channel, u32 magic); + /************************************************************************** * * Solarstorm hardware access @@ -124,9 +126,6 @@ int efx_nic_test_registers(struct efx_nic *efx, unsigned address = 0, i, j; efx_oword_t mask, imask, original, reg, buf; - /* Falcon should be in loopback to isolate the XMAC from the PHY */ - WARN_ON(!LOOPBACK_INTERNAL(efx)); - for (i = 0; i < n_regs; ++i) { address = regs[i].address; mask = imask = regs[i].mask; @@ -380,7 +379,8 @@ efx_may_push_tx_desc(struct efx_tx_queue *tx_queue, unsigned int write_count) return false; tx_queue->empty_read_count = 0; - return ((empty_read_count ^ write_count) & ~EFX_EMPTY_COUNT_VALID) == 0; + return ((empty_read_count ^ write_count) & ~EFX_EMPTY_COUNT_VALID) == 0 + && tx_queue->write_count - write_count == 1; } /* For each entry inserted into the software descriptor ring, create a @@ -495,6 +495,9 @@ static void efx_flush_tx_queue(struct efx_tx_queue *tx_queue) struct efx_nic *efx = tx_queue->efx; efx_oword_t tx_flush_descq; + WARN_ON(atomic_read(&tx_queue->flush_outstanding)); + atomic_set(&tx_queue->flush_outstanding, 1); + EFX_POPULATE_OWORD_2(tx_flush_descq, FRF_AZ_TX_FLUSH_DESCQ_CMD, 1, FRF_AZ_TX_FLUSH_DESCQ, tx_queue->queue); @@ -670,6 +673,47 @@ static bool efx_flush_wake(struct efx_nic *efx) && atomic_read(&efx->rxq_flush_pending) > 0)); } +static bool efx_check_tx_flush_complete(struct efx_nic *efx) +{ + bool i = true; + efx_oword_t txd_ptr_tbl; + struct efx_channel *channel; + struct efx_tx_queue *tx_queue; + + efx_for_each_channel(channel, efx) { + efx_for_each_channel_tx_queue(tx_queue, channel) { + efx_reado_table(efx, &txd_ptr_tbl, + FR_BZ_TX_DESC_PTR_TBL, tx_queue->queue); + if (EFX_OWORD_FIELD(txd_ptr_tbl, + FRF_AZ_TX_DESCQ_FLUSH) || + EFX_OWORD_FIELD(txd_ptr_tbl, + FRF_AZ_TX_DESCQ_EN)) { + netif_dbg(efx, hw, efx->net_dev, + "flush did not complete on TXQ %d\n", + tx_queue->queue); + i = false; + } else if (atomic_cmpxchg(&tx_queue->flush_outstanding, + 1, 0)) { + /* The flush is complete, but we didn't + * receive a flush completion event + */ + netif_dbg(efx, hw, efx->net_dev, + "flush complete on TXQ %d, so drain " + "the queue\n", tx_queue->queue); + /* Don't need to increment drain_pending as it + * has already been incremented for the queues + * which did not drain + */ + efx_magic_event(channel, + EFX_CHANNEL_MAGIC_TX_DRAIN( + tx_queue)); + } + } + } + + return i; +} + /* Flush all the transmit queues, and continue flushing receive queues until * they're all flushed. Wait for the DRAIN events to be recieved so that there * are no more RX and TX events left on any channel. */ @@ -681,7 +725,6 @@ int efx_nic_flush_queues(struct efx_nic *efx) struct efx_tx_queue *tx_queue; int rc = 0; - efx->fc_disable++; efx->type->prepare_flush(efx); efx_for_each_channel(channel, efx) { @@ -731,7 +774,8 @@ int efx_nic_flush_queues(struct efx_nic *efx) timeout); } - if (atomic_read(&efx->drain_pending)) { + if (atomic_read(&efx->drain_pending) && + !efx_check_tx_flush_complete(efx)) { netif_err(efx, hw, efx->net_dev, "failed to flush %d queues " "(rx %d+%d)\n", atomic_read(&efx->drain_pending), atomic_read(&efx->rxq_flush_outstanding), @@ -743,7 +787,7 @@ int efx_nic_flush_queues(struct efx_nic *efx) atomic_set(&efx->rxq_flush_outstanding, 0); } - efx->fc_disable--; + efx->type->finish_flush(efx); return rc; } @@ -1018,9 +1062,10 @@ efx_handle_tx_flush_done(struct efx_nic *efx, efx_qword_t *event) if (qid < EFX_TXQ_TYPES * efx->n_tx_channels) { tx_queue = efx_get_tx_queue(efx, qid / EFX_TXQ_TYPES, qid % EFX_TXQ_TYPES); - - efx_magic_event(tx_queue->channel, - EFX_CHANNEL_MAGIC_TX_DRAIN(tx_queue)); + if (atomic_cmpxchg(&tx_queue->flush_outstanding, 1, 0)) { + efx_magic_event(tx_queue->channel, + EFX_CHANNEL_MAGIC_TX_DRAIN(tx_queue)); + } } } diff --git a/drivers/net/ethernet/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h index f48ccf6bb3b..bbdfcd62619 100644 --- a/drivers/net/ethernet/sfc/nic.h +++ b/drivers/net/ethernet/sfc/nic.h @@ -316,6 +316,8 @@ static inline int efx_nic_irq_test_irq_cpu(struct efx_nic *efx) /* Global Resources */ extern int efx_nic_flush_queues(struct efx_nic *efx); +extern void siena_prepare_flush(struct efx_nic *efx); +extern void siena_finish_flush(struct efx_nic *efx); extern void falcon_start_nic_stats(struct efx_nic *efx); extern void falcon_stop_nic_stats(struct efx_nic *efx); extern void falcon_setup_xaui(struct efx_nic *efx); diff --git a/drivers/net/ethernet/sfc/rx.c b/drivers/net/ethernet/sfc/rx.c index 763fa2fe1a3..7b3c068a9f5 100644 --- a/drivers/net/ethernet/sfc/rx.c +++ b/drivers/net/ethernet/sfc/rx.c @@ -95,11 +95,7 @@ static unsigned int rx_refill_limit = 95; static inline unsigned int efx_rx_buf_offset(struct efx_nic *efx, struct efx_rx_buffer *buf) { - /* Offset is always within one page, so we don't need to consider - * the page order. - */ - return ((unsigned int) buf->dma_addr & (PAGE_SIZE - 1)) + - efx->type->rx_buffer_hash_size; + return buf->page_offset + efx->type->rx_buffer_hash_size; } static inline unsigned int efx_rx_buf_size(struct efx_nic *efx) { @@ -193,6 +189,7 @@ static int efx_init_rx_buffers_page(struct efx_rx_queue *rx_queue) struct efx_rx_buffer *rx_buf; struct page *page; void *page_addr; + unsigned int page_offset; struct efx_rx_page_state *state; dma_addr_t dma_addr; unsigned index, count; @@ -219,12 +216,14 @@ static int efx_init_rx_buffers_page(struct efx_rx_queue *rx_queue) page_addr += sizeof(struct efx_rx_page_state); dma_addr += sizeof(struct efx_rx_page_state); + page_offset = sizeof(struct efx_rx_page_state); split: index = rx_queue->added_count & rx_queue->ptr_mask; rx_buf = efx_rx_buffer(rx_queue, index); rx_buf->dma_addr = dma_addr + EFX_PAGE_IP_ALIGN; rx_buf->u.page = page; + rx_buf->page_offset = page_offset + EFX_PAGE_IP_ALIGN; rx_buf->len = efx->rx_buffer_len - EFX_PAGE_IP_ALIGN; rx_buf->flags = EFX_RX_BUF_PAGE; ++rx_queue->added_count; @@ -236,6 +235,7 @@ static int efx_init_rx_buffers_page(struct efx_rx_queue *rx_queue) get_page(page); dma_addr += (PAGE_SIZE >> 1); page_addr += (PAGE_SIZE >> 1); + page_offset += (PAGE_SIZE >> 1); ++count; goto split; } @@ -245,7 +245,8 @@ static int efx_init_rx_buffers_page(struct efx_rx_queue *rx_queue) } static void efx_unmap_rx_buffer(struct efx_nic *efx, - struct efx_rx_buffer *rx_buf) + struct efx_rx_buffer *rx_buf, + unsigned int used_len) { if ((rx_buf->flags & EFX_RX_BUF_PAGE) && rx_buf->u.page) { struct efx_rx_page_state *state; @@ -256,6 +257,10 @@ static void efx_unmap_rx_buffer(struct efx_nic *efx, state->dma_addr, efx_rx_buf_size(efx), PCI_DMA_FROMDEVICE); + } else if (used_len) { + dma_sync_single_for_cpu(&efx->pci_dev->dev, + rx_buf->dma_addr, used_len, + DMA_FROM_DEVICE); } } else if (!(rx_buf->flags & EFX_RX_BUF_PAGE) && rx_buf->u.skb) { pci_unmap_single(efx->pci_dev, rx_buf->dma_addr, @@ -278,7 +283,7 @@ static void efx_free_rx_buffer(struct efx_nic *efx, static void efx_fini_rx_buffer(struct efx_rx_queue *rx_queue, struct efx_rx_buffer *rx_buf) { - efx_unmap_rx_buffer(rx_queue->efx, rx_buf); + efx_unmap_rx_buffer(rx_queue->efx, rx_buf, 0); efx_free_rx_buffer(rx_queue->efx, rx_buf); } @@ -544,10 +549,10 @@ void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index, goto out; } - /* Release card resources - assumes all RX buffers consumed in-order - * per RX queue + /* Release and/or sync DMA mapping - assumes all RX buffers + * consumed in-order per RX queue */ - efx_unmap_rx_buffer(efx, rx_buf); + efx_unmap_rx_buffer(efx, rx_buf, len); /* Prefetch nice and early so data will (hopefully) be in cache by * the time we look at it. diff --git a/drivers/net/ethernet/sfc/selftest.c b/drivers/net/ethernet/sfc/selftest.c index de4c0069f5b..4a51ea34271 100644 --- a/drivers/net/ethernet/sfc/selftest.c +++ b/drivers/net/ethernet/sfc/selftest.c @@ -120,19 +120,6 @@ static int efx_test_nvram(struct efx_nic *efx, struct efx_self_tests *tests) return rc; } -static int efx_test_chip(struct efx_nic *efx, struct efx_self_tests *tests) -{ - int rc = 0; - - /* Test register access */ - if (efx->type->test_registers) { - rc = efx->type->test_registers(efx); - tests->registers = rc ? -1 : 1; - } - - return rc; -} - /************************************************************************** * * Interrupt and event queue testing @@ -699,8 +686,7 @@ int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests, { enum efx_loopback_mode loopback_mode = efx->loopback_mode; int phy_mode = efx->phy_mode; - enum reset_type reset_method = RESET_TYPE_INVISIBLE; - int rc_test = 0, rc_reset = 0, rc; + int rc_test = 0, rc_reset, rc; efx_selftest_async_cancel(efx); @@ -735,46 +721,28 @@ int efx_selftest(struct efx_nic *efx, struct efx_self_tests *tests, /* Detach the device so the kernel doesn't transmit during the * loopback test and the watchdog timeout doesn't fire. */ - netif_device_detach(efx->net_dev); + efx_device_detach_sync(efx); + + if (efx->type->test_chip) { + rc_reset = efx->type->test_chip(efx, tests); + if (rc_reset) { + netif_err(efx, hw, efx->net_dev, + "Unable to recover from chip test\n"); + efx_schedule_reset(efx, RESET_TYPE_DISABLE); + return rc_reset; + } - mutex_lock(&efx->mac_lock); - if (efx->loopback_modes) { - /* We need the 312 clock from the PHY to test the XMAC - * registers, so move into XGMII loopback if available */ - if (efx->loopback_modes & (1 << LOOPBACK_XGMII)) - efx->loopback_mode = LOOPBACK_XGMII; - else - efx->loopback_mode = __ffs(efx->loopback_modes); + if ((tests->registers < 0) && !rc_test) + rc_test = -EIO; } - __efx_reconfigure_port(efx); - mutex_unlock(&efx->mac_lock); - - /* free up all consumers of SRAM (including all the queues) */ - efx_reset_down(efx, reset_method); - - rc = efx_test_chip(efx, tests); - if (rc && !rc_test) - rc_test = rc; - - /* reset the chip to recover from the register test */ - rc_reset = efx->type->reset(efx, reset_method); - /* Ensure that the phy is powered and out of loopback * for the bist and loopback tests */ + mutex_lock(&efx->mac_lock); efx->phy_mode &= ~PHY_MODE_LOW_POWER; efx->loopback_mode = LOOPBACK_NONE; - - rc = efx_reset_up(efx, reset_method, rc_reset == 0); - if (rc && !rc_reset) - rc_reset = rc; - - if (rc_reset) { - netif_err(efx, drv, efx->net_dev, - "Unable to recover from chip test\n"); - efx_schedule_reset(efx, RESET_TYPE_DISABLE); - return rc_reset; - } + __efx_reconfigure_port(efx); + mutex_unlock(&efx->mac_lock); rc = efx_test_phy(efx, tests, flags); if (rc && !rc_test) diff --git a/drivers/net/ethernet/sfc/siena.c b/drivers/net/ethernet/sfc/siena.c index 9f8d7cea396..b09ff7982b1 100644 --- a/drivers/net/ethernet/sfc/siena.c +++ b/drivers/net/ethernet/sfc/siena.c @@ -25,10 +25,12 @@ #include "workarounds.h" #include "mcdi.h" #include "mcdi_pcol.h" +#include "selftest.h" /* Hardware control for SFC9000 family including SFL9021 (aka Siena). */ static void siena_init_wol(struct efx_nic *efx); +static int siena_reset_hw(struct efx_nic *efx, enum reset_type method); static void siena_push_irq_moderation(struct efx_channel *channel) @@ -125,6 +127,18 @@ static void siena_remove_port(struct efx_nic *efx) efx_nic_free_buffer(efx, &efx->stats_buffer); } +void siena_prepare_flush(struct efx_nic *efx) +{ + if (efx->fc_disable++ == 0) + efx_mcdi_set_mac(efx); +} + +void siena_finish_flush(struct efx_nic *efx) +{ + if (--efx->fc_disable == 0) + efx_mcdi_set_mac(efx); +} + static const struct efx_nic_register_test siena_register_tests[] = { { FR_AZ_ADR_REGION, EFX_OWORD32(0x0003FFFF, 0x0003FFFF, 0x0003FFFF, 0x0003FFFF) }, @@ -154,10 +168,29 @@ static const struct efx_nic_register_test siena_register_tests[] = { EFX_OWORD32(0xFFFFFFFF, 0xFFFFFFFF, 0x00000007, 0x00000000) }, }; -static int siena_test_registers(struct efx_nic *efx) +static int siena_test_chip(struct efx_nic *efx, struct efx_self_tests *tests) { - return efx_nic_test_registers(efx, siena_register_tests, - ARRAY_SIZE(siena_register_tests)); + enum reset_type reset_method = RESET_TYPE_ALL; + int rc, rc2; + + efx_reset_down(efx, reset_method); + + /* Reset the chip immediately so that it is completely + * quiescent regardless of what any VF driver does. + */ + rc = siena_reset_hw(efx, reset_method); + if (rc) + goto out; + + tests->registers = + efx_nic_test_registers(efx, siena_register_tests, + ARRAY_SIZE(siena_register_tests)) + ? -1 : 1; + + rc = siena_reset_hw(efx, reset_method); +out: + rc2 = efx_reset_up(efx, reset_method, rc == 0); + return rc ? rc : rc2; } /************************************************************************** @@ -637,7 +670,8 @@ const struct efx_nic_type siena_a0_nic_type = { .reset = siena_reset_hw, .probe_port = siena_probe_port, .remove_port = siena_remove_port, - .prepare_flush = efx_port_dummy_op_void, + .prepare_flush = siena_prepare_flush, + .finish_flush = siena_finish_flush, .update_stats = siena_update_nic_stats, .start_stats = siena_start_nic_stats, .stop_stats = siena_stop_nic_stats, @@ -649,7 +683,7 @@ const struct efx_nic_type siena_a0_nic_type = { .get_wol = siena_get_wol, .set_wol = siena_set_wol, .resume_wol = siena_init_wol, - .test_registers = siena_test_registers, + .test_chip = siena_test_chip, .test_nvram = efx_mcdi_nvram_test_all, .revision = EFX_REV_SIENA_A0, diff --git a/drivers/net/ethernet/sfc/siena_sriov.c b/drivers/net/ethernet/sfc/siena_sriov.c index 9cb3b84ecae..4ad8082d6f8 100644 --- a/drivers/net/ethernet/sfc/siena_sriov.c +++ b/drivers/net/ethernet/sfc/siena_sriov.c @@ -21,6 +21,9 @@ /* Number of longs required to track all the VIs in a VF */ #define VI_MASK_LENGTH BITS_TO_LONGS(1 << EFX_VI_SCALE_MAX) +/* Maximum number of RX queues supported */ +#define VF_MAX_RX_QUEUES 63 + /** * enum efx_vf_tx_filter_mode - TX MAC filtering behaviour * @VF_TX_FILTER_OFF: Disabled @@ -578,6 +581,7 @@ static int efx_vfdi_init_rxq(struct efx_vf *vf) efx_oword_t reg; if (bad_vf_index(efx, vf_evq) || bad_vf_index(efx, vf_rxq) || + vf_rxq >= VF_MAX_RX_QUEUES || bad_buf_count(buf_count, EFX_MAX_DMAQ_SIZE)) { if (net_ratelimit()) netif_err(efx, hw, efx->net_dev, @@ -683,13 +687,15 @@ static int efx_vfdi_fini_all_queues(struct efx_vf *vf) __le32 *rxqs; int rc; + BUILD_BUG_ON(VF_MAX_RX_QUEUES > + MC_CMD_FLUSH_RX_QUEUES_IN_QID_OFST_MAXNUM); + rxqs = kmalloc(count * sizeof(*rxqs), GFP_KERNEL); if (rxqs == NULL) return VFDI_RC_ENOMEM; rtnl_lock(); - if (efx->fc_disable++ == 0) - efx_mcdi_set_mac(efx); + siena_prepare_flush(efx); rtnl_unlock(); /* Flush all the initialized queues */ @@ -726,8 +732,7 @@ static int efx_vfdi_fini_all_queues(struct efx_vf *vf) } rtnl_lock(); - if (--efx->fc_disable == 0) - efx_mcdi_set_mac(efx); + siena_finish_flush(efx); rtnl_unlock(); /* Irrespective of success/failure, fini the queues */ diff --git a/drivers/net/ethernet/sun/sunvnet.c b/drivers/net/ethernet/sun/sunvnet.c index 38e3ae9155b..8e2ac643a77 100644 --- a/drivers/net/ethernet/sun/sunvnet.c +++ b/drivers/net/ethernet/sun/sunvnet.c @@ -1243,6 +1243,8 @@ static int vnet_port_remove(struct vio_dev *vdev) dev_set_drvdata(&vdev->dev, NULL); kfree(port); + + unregister_netdev(vp->dev); } return 0; } diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c index 6685bbb5705..310e353950e 100644 --- a/drivers/net/ethernet/ti/cpsw.c +++ b/drivers/net/ethernet/ti/cpsw.c @@ -249,7 +249,7 @@ void cpsw_tx_handler(void *token, int len, int status) struct cpsw_priv *priv = netdev_priv(ndev); if (unlikely(netif_queue_stopped(ndev))) - netif_start_queue(ndev); + netif_wake_queue(ndev); priv->stats.tx_packets++; priv->stats.tx_bytes += len; dev_kfree_skb_any(skb); diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c index 08aff1a2087..43fada57259 100644 --- a/drivers/net/ethernet/ti/davinci_emac.c +++ b/drivers/net/ethernet/ti/davinci_emac.c @@ -1052,7 +1052,7 @@ static void emac_tx_handler(void *token, int len, int status) atomic_dec(&priv->cur_tx); if (unlikely(netif_queue_stopped(ndev))) - netif_start_queue(ndev); + netif_wake_queue(ndev); ndev->stats.tx_packets++; ndev->stats.tx_bytes += len; dev_kfree_skb_any(skb); diff --git a/drivers/net/ethernet/via/via-rhine.c b/drivers/net/ethernet/via/via-rhine.c index fcfa01f7ceb..4c76db4f058 100644 --- a/drivers/net/ethernet/via/via-rhine.c +++ b/drivers/net/ethernet/via/via-rhine.c @@ -1802,7 +1802,7 @@ static void rhine_tx(struct net_device *dev) rp->tx_skbuff[entry]->len, PCI_DMA_TODEVICE); } - dev_kfree_skb_irq(rp->tx_skbuff[entry]); + dev_kfree_skb(rp->tx_skbuff[entry]); rp->tx_skbuff[entry] = NULL; entry = (++rp->dirty_tx) % TX_RING_SIZE; } @@ -2011,11 +2011,7 @@ static void rhine_slow_event_task(struct work_struct *work) if (intr_status & IntrPCIErr) netif_warn(rp, hw, dev, "PCI error\n"); - napi_disable(&rp->napi); - rhine_irq_disable(rp); - /* Slow and safe. Consider __napi_schedule as a replacement ? */ - napi_enable(&rp->napi); - napi_schedule(&rp->napi); + iowrite16(RHINE_EVENT & 0xffff, rp->base + IntrEnable); out_unlock: mutex_unlock(&rp->task_lock); diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c index 344dceb1aaf..635d01cf302 100644 --- a/drivers/net/ifb.c +++ b/drivers/net/ifb.c @@ -290,11 +290,17 @@ static int __init ifb_init_module(void) rtnl_lock(); err = __rtnl_link_register(&ifb_link_ops); + if (err < 0) + goto out; - for (i = 0; i < numifbs && !err; i++) + for (i = 0; i < numifbs && !err; i++) { err = ifb_init_one(i); + cond_resched(); + } if (err) __rtnl_link_unregister(&ifb_link_ops); + +out: rtnl_unlock(); return err; diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index 32eb94ece6c..a3d4707505a 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c @@ -77,6 +77,11 @@ static netdev_tx_t loopback_xmit(struct sk_buff *skb, skb_orphan(skb); + /* Before queueing this packet to netif_rx(), + * make sure dst is refcounted. + */ + skb_dst_force(skb); + skb->protocol = eth_type_trans(skb, dev); /* it's OK to use per_cpu_ptr() because BHs are off */ diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index 025367a94ad..71605231bcb 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -205,7 +205,8 @@ static rx_handler_result_t macvlan_handle_frame(struct sk_buff **pskb) } if (port->passthru) - vlan = list_first_entry(&port->vlans, struct macvlan_dev, list); + vlan = list_first_or_null_rcu(&port->vlans, + struct macvlan_dev, list); else vlan = macvlan_hash_lookup(port, eth->h_dest); if (vlan == NULL) @@ -584,6 +585,7 @@ void macvlan_common_setup(struct net_device *dev) ether_setup(dev); dev->priv_flags &= ~(IFF_XMIT_DST_RELEASE | IFF_TX_SKB_SHARING); + dev->priv_flags |= IFF_UNICAST_FLT; dev->netdev_ops = &macvlan_netdev_ops; dev->destructor = free_netdev; dev->header_ops = &macvlan_hard_header_ops, @@ -723,7 +725,7 @@ int macvlan_common_newlink(struct net *src_net, struct net_device *dev, if (err < 0) goto destroy_port; - list_add_tail(&vlan->list, &port->vlans); + list_add_tail_rcu(&vlan->list, &port->vlans); netif_stacked_transfer_operstate(lowerdev, dev); return 0; @@ -749,7 +751,7 @@ void macvlan_dellink(struct net_device *dev, struct list_head *head) { struct macvlan_dev *vlan = netdev_priv(dev); - list_del(&vlan->list); + list_del_rcu(&vlan->list); unregister_netdevice_queue(dev, head); } EXPORT_SYMBOL_GPL(macvlan_dellink); diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index b99c418d6b2..5151f06c59c 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -534,8 +534,10 @@ static int zerocopy_sg_from_iovec(struct sk_buff *skb, const struct iovec *from, return -EMSGSIZE; num_pages = get_user_pages_fast(base, size, 0, &page[i]); if (num_pages != size) { - for (i = 0; i < num_pages; i++) - put_page(page[i]); + int j; + + for (j = 0; j < num_pages; j++) + put_page(page[i + j]); } truesize = size * PAGE_SIZE; skb->data_len += len; @@ -654,6 +656,7 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, int vnet_hdr_len = 0; int copylen = 0; bool zerocopy = false; + size_t linear; if (q->flags & IFF_VNET_HDR) { vnet_hdr_len = q->vnet_hdr_sz; @@ -708,11 +711,14 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, copylen = vnet_hdr.hdr_len; if (!copylen) copylen = GOODCOPY_LEN; - } else + linear = copylen; + } else { copylen = len; + linear = vnet_hdr.hdr_len; + } skb = macvtap_alloc_skb(&q->sk, NET_IP_ALIGN, copylen, - vnet_hdr.hdr_len, noblock, &err); + linear, noblock, &err); if (!skb) goto err; diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c index 63ffbdfe36c..dfffe8d8d69 100644 --- a/drivers/net/netconsole.c +++ b/drivers/net/netconsole.c @@ -626,6 +626,7 @@ static int netconsole_netdev_event(struct notifier_block *this, goto done; spin_lock_irqsave(&target_list_lock, flags); +restart: list_for_each_entry(nt, &target_list, list) { netconsole_target_get(nt); if (nt->np.dev == dev) { @@ -637,21 +638,18 @@ static int netconsole_netdev_event(struct notifier_block *this, case NETDEV_JOIN: case NETDEV_UNREGISTER: /* + * we might sleep in __netpoll_cleanup() * rtnl_lock already held */ - if (nt->np.dev) { - spin_unlock_irqrestore( - &target_list_lock, - flags); - __netpoll_cleanup(&nt->np); - spin_lock_irqsave(&target_list_lock, - flags); - dev_put(nt->np.dev); - nt->np.dev = NULL; - } + spin_unlock_irqrestore(&target_list_lock, flags); + __netpoll_cleanup(&nt->np); + spin_lock_irqsave(&target_list_lock, flags); + dev_put(nt->np.dev); + nt->np.dev = NULL; nt->enabled = 0; stopped = true; - break; + netconsole_target_put(nt); + goto restart; } } netconsole_target_put(nt); diff --git a/drivers/net/team/team_mode_roundrobin.c b/drivers/net/team/team_mode_roundrobin.c index a0e8f806331..bf6a818c3d0 100644 --- a/drivers/net/team/team_mode_roundrobin.c +++ b/drivers/net/team/team_mode_roundrobin.c @@ -52,6 +52,8 @@ static bool rr_transmit(struct team *team, struct sk_buff *skb) port_index = rr_priv(team)->sent_packets++ % team->port_count; port = team_get_port_by_index_rcu(team, port_index); + if (unlikely(!port)) + goto drop; port = __get_first_port_up(team, port); if (unlikely(!port)) goto drop; diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 279d860ee90..dd2f8210ec1 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -417,6 +417,8 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev) * for indefinite time. */ skb_orphan(skb); + nf_reset(skb); + /* Enqueue packet */ skb_queue_tail(&tun->socket.sk->sk_receive_queue, skb); diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 8669c77fa7c..3b6e932890b 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -174,6 +175,93 @@ static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf) return status; } +/* default ethernet address used by the modem */ +static const u8 default_modem_addr[ETH_ALEN] = {0x02, 0x50, 0xf3}; + +/* Make up an ethernet header if the packet doesn't have one. + * + * A firmware bug common among several devices cause them to send raw + * IP packets under some circumstances. There is no way for the + * driver/host to know when this will happen. And even when the bug + * hits, some packets will still arrive with an intact header. + * + * The supported devices are only capably of sending IPv4, IPv6 and + * ARP packets on a point-to-point link. Any packet with an ethernet + * header will have either our address or a broadcast/multicast + * address as destination. ARP packets will always have a header. + * + * This means that this function will reliably add the appropriate + * header iff necessary, provided our hardware address does not start + * with 4 or 6. + * + * Another common firmware bug results in all packets being addressed + * to 00:a0:c6:00:00:00 despite the host address being different. + * This function will also fixup such packets. + */ +static int qmi_wwan_rx_fixup(struct usbnet *dev, struct sk_buff *skb) +{ + __be16 proto; + + /* usbnet rx_complete guarantees that skb->len is at least + * hard_header_len, so we can inspect the dest address without + * checking skb->len + */ + switch (skb->data[0] & 0xf0) { + case 0x40: + proto = htons(ETH_P_IP); + break; + case 0x60: + proto = htons(ETH_P_IPV6); + break; + case 0x00: + if (is_multicast_ether_addr(skb->data)) + return 1; + /* possibly bogus destination - rewrite just in case */ + skb_reset_mac_header(skb); + goto fix_dest; + default: + /* pass along other packets without modifications */ + return 1; + } + if (skb_headroom(skb) < ETH_HLEN) + return 0; + skb_push(skb, ETH_HLEN); + skb_reset_mac_header(skb); + eth_hdr(skb)->h_proto = proto; + memset(eth_hdr(skb)->h_source, 0, ETH_ALEN); +fix_dest: + memcpy(eth_hdr(skb)->h_dest, dev->net->dev_addr, ETH_ALEN); + return 1; +} + +/* very simplistic detection of IPv4 or IPv6 headers */ +static bool possibly_iphdr(const char *data) +{ + return (data[0] & 0xd0) == 0x40; +} + +/* disallow addresses which may be confused with IP headers */ +static int qmi_wwan_mac_addr(struct net_device *dev, void *p) +{ + struct sockaddr *addr = p; + + if (!is_valid_ether_addr(addr->sa_data) || + possibly_iphdr(addr->sa_data)) + return -EADDRNOTAVAIL; + memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); + return 0; +} + +static const struct net_device_ops qmi_wwan_netdev_ops = { + .ndo_open = usbnet_open, + .ndo_stop = usbnet_stop, + .ndo_start_xmit = usbnet_start_xmit, + .ndo_tx_timeout = usbnet_tx_timeout, + .ndo_change_mtu = usbnet_change_mtu, + .ndo_set_mac_address = qmi_wwan_mac_addr, + .ndo_validate_addr = eth_validate_addr, +}; + /* using a counter to merge subdriver requests with our own into a combined state */ static int qmi_wwan_manage_power(struct usbnet *dev, int on) { @@ -257,6 +345,18 @@ static int qmi_wwan_bind_shared(struct usbnet *dev, struct usb_interface *intf) /* save subdriver struct for suspend/resume wrappers */ dev->data[0] = (unsigned long)subdriver; + /* Never use the same address on both ends of the link, even + * if the buggy firmware told us to. + */ + if (!compare_ether_addr(dev->net->dev_addr, default_modem_addr)) + eth_hw_addr_random(dev->net); + + /* make MAC addr easily distinguishable from an IP header */ + if (possibly_iphdr(dev->net->dev_addr)) { + dev->net->dev_addr[0] |= 0x02; /* set local assignment bit */ + dev->net->dev_addr[0] &= 0xbf; /* clear "IP" bit */ + } + dev->net->netdev_ops = &qmi_wwan_netdev_ops; err: return rv; } @@ -326,6 +426,7 @@ static const struct driver_info qmi_wwan_shared = { .bind = qmi_wwan_bind_shared, .unbind = qmi_wwan_unbind_shared, .manage_power = qmi_wwan_manage_power, + .rx_fixup = qmi_wwan_rx_fixup, }; static const struct driver_info qmi_wwan_force_int0 = { diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c index 00103a8c5e0..d89747aa3c4 100644 --- a/drivers/net/usb/smsc75xx.c +++ b/drivers/net/usb/smsc75xx.c @@ -43,7 +43,6 @@ #define EEPROM_MAC_OFFSET (0x01) #define DEFAULT_TX_CSUM_ENABLE (true) #define DEFAULT_RX_CSUM_ENABLE (true) -#define DEFAULT_TSO_ENABLE (true) #define SMSC75XX_INTERNAL_PHY_ID (1) #define SMSC75XX_TX_OVERHEAD (8) #define MAX_RX_FIFO_SIZE (20 * 1024) @@ -725,8 +724,12 @@ static int smsc75xx_set_rx_max_frame_length(struct usbnet *dev, int size) static int smsc75xx_change_mtu(struct net_device *netdev, int new_mtu) { struct usbnet *dev = netdev_priv(netdev); + int ret; + + if (new_mtu > MAX_SINGLE_PACKET_SIZE) + return -EINVAL; - int ret = smsc75xx_set_rx_max_frame_length(dev, new_mtu); + ret = smsc75xx_set_rx_max_frame_length(dev, new_mtu + ETH_HLEN); check_warn_return(ret, "Failed to set mac rx frame length"); return usbnet_change_mtu(netdev, new_mtu); @@ -979,7 +982,7 @@ static int smsc75xx_reset(struct usbnet *dev) netif_dbg(dev, ifup, dev->net, "FCT_TX_CTL set to 0x%08x", buf); - ret = smsc75xx_set_rx_max_frame_length(dev, 1514); + ret = smsc75xx_set_rx_max_frame_length(dev, dev->net->mtu + ETH_HLEN); check_warn_return(ret, "Failed to set max rx frame length"); ret = smsc75xx_read_reg(dev, MAC_RX, &buf); @@ -1045,17 +1048,14 @@ static int smsc75xx_bind(struct usbnet *dev, struct usb_interface *intf) INIT_WORK(&pdata->set_multicast, smsc75xx_deferred_multicast_write); - if (DEFAULT_TX_CSUM_ENABLE) { + if (DEFAULT_TX_CSUM_ENABLE) dev->net->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; - if (DEFAULT_TSO_ENABLE) - dev->net->features |= NETIF_F_SG | - NETIF_F_TSO | NETIF_F_TSO6; - } + if (DEFAULT_RX_CSUM_ENABLE) dev->net->features |= NETIF_F_RXCSUM; dev->net->hw_features = NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | - NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_RXCSUM; + NETIF_F_RXCSUM; /* Init all registers */ ret = smsc75xx_reset(dev); @@ -1123,8 +1123,8 @@ static int smsc75xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) else if (rx_cmd_a & (RX_CMD_A_LONG | RX_CMD_A_RUNT)) dev->net->stats.rx_frame_errors++; } else { - /* ETH_FRAME_LEN + 4(CRC) + 2(COE) + 4(Vlan) */ - if (unlikely(size > (ETH_FRAME_LEN + 12))) { + /* MAX_SINGLE_PACKET_SIZE + 4(CRC) + 2(COE) + 4(Vlan) */ + if (unlikely(size > (MAX_SINGLE_PACKET_SIZE + ETH_HLEN + 12))) { netif_dbg(dev, rx_err, dev->net, "size err rx_cmd_a=0x%08x", rx_cmd_a); return 0; @@ -1180,8 +1180,6 @@ static struct sk_buff *smsc75xx_tx_fixup(struct usbnet *dev, { u32 tx_cmd_a, tx_cmd_b; - skb_linearize(skb); - if (skb_headroom(skb) < SMSC75XX_TX_OVERHEAD) { struct sk_buff *skb2 = skb_copy_expand(skb, SMSC75XX_TX_OVERHEAD, 0, flags); diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 3c7991717da..795b80e8199 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -518,7 +518,7 @@ static int virtnet_poll(struct napi_struct *napi, int budget) { struct virtnet_info *vi = container_of(napi, struct virtnet_info, napi); void *buf; - unsigned int len, received = 0; + unsigned int r, len, received = 0; again: while (received < budget && @@ -535,8 +535,9 @@ static int virtnet_poll(struct napi_struct *napi, int budget) /* Out of packets? */ if (received < budget) { + r = virtqueue_enable_cb_prepare(vi->rvq); napi_complete(napi); - if (unlikely(!virtqueue_enable_cb(vi->rvq)) && + if (unlikely(virtqueue_poll(vi->rvq, r)) && napi_schedule_prep(napi)) { virtqueue_disable_cb(vi->rvq); __napi_schedule(napi); diff --git a/drivers/net/wan/dlci.c b/drivers/net/wan/dlci.c index 147614ed86a..6a8a382c5f4 100644 --- a/drivers/net/wan/dlci.c +++ b/drivers/net/wan/dlci.c @@ -384,21 +384,37 @@ static int dlci_del(struct dlci_add *dlci) struct frad_local *flp; struct net_device *master, *slave; int err; + bool found = false; + + rtnl_lock(); /* validate slave device */ master = __dev_get_by_name(&init_net, dlci->devname); - if (!master) - return -ENODEV; + if (!master) { + err = -ENODEV; + goto out; + } + + list_for_each_entry(dlp, &dlci_devs, list) { + if (dlp->master == master) { + found = true; + break; + } + } + if (!found) { + err = -ENODEV; + goto out; + } if (netif_running(master)) { - return -EBUSY; + err = -EBUSY; + goto out; } dlp = netdev_priv(master); slave = dlp->slave; flp = netdev_priv(slave); - rtnl_lock(); err = (*flp->deassoc)(slave, master); if (!err) { list_del(&dlp->list); @@ -407,8 +423,8 @@ static int dlci_del(struct dlci_add *dlci) dev_put(slave); } +out: rtnl_unlock(); - return err; } diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig index e507e78398f..3b8c9306d84 100644 --- a/drivers/net/wireless/ath/ath9k/Kconfig +++ b/drivers/net/wireless/ath/ath9k/Kconfig @@ -89,13 +89,17 @@ config ATH9K_MAC_DEBUG This option enables collection of statistics for Rx/Tx status data and some other MAC related statistics -config ATH9K_RATE_CONTROL +config ATH9K_LEGACY_RATE_CONTROL bool "Atheros ath9k rate control" depends on ATH9K - default y + default n ---help--- Say Y, if you want to use the ath9k specific rate control - module instead of minstrel_ht. + module instead of minstrel_ht. Be warned that there are various + issues with the ath9k RC and minstrel is a more robust algorithm. + Note that even if this option is selected, "ath9k_rate_control" + has to be passed to mac80211 using the module parameter, + ieee80211_default_rc_algo. config ATH9K_HTC tristate "Atheros HTC based wireless cards support" diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index 27d95fe5ade..24ae2e6a570 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile @@ -6,7 +6,7 @@ ath9k-y += beacon.o \ xmit.o ath9k-$(CONFIG_ATH9K_BTCOEX_SUPPORT) += mci.o -ath9k-$(CONFIG_ATH9K_RATE_CONTROL) += rc.o +ath9k-$(CONFIG_ATH9K_LEGACY_RATE_CONTROL) += rc.o ath9k-$(CONFIG_ATH9K_PCI) += pci.o ath9k-$(CONFIG_ATH9K_AHB) += ahb.o ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index 63089cc1faf..7c8641505e6 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c @@ -938,6 +938,9 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, AR_PHY_CL_TAB_1, AR_PHY_CL_TAB_2 }; + /* Use chip chainmask only for calibration */ + ar9003_hw_set_chain_masks(ah, ah->caps.rx_chainmask, ah->caps.tx_chainmask); + if (rtt) { if (!ar9003_hw_rtt_restore(ah, chan)) run_rtt_cal = true; @@ -1083,6 +1086,9 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, ar9003_hw_rtt_disable(ah); } + /* Revert chainmask to runtime parameters */ + ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask); + /* Initialize list pointers */ ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL; ah->supp_cals = IQ_MISMATCH_CAL; diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index 600aca9fe6b..f86ee0c7f31 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -543,7 +543,7 @@ static void ar9003_hw_init_bb(struct ath_hw *ah, udelay(synthDelay + BASE_ACTIVATE_DELAY); } -static void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx) +void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx) { switch (rx) { case 0x5: diff --git a/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h index 06b3f0df9fa..c16bea40cf3 100644 --- a/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h @@ -648,7 +648,7 @@ static const u32 ar9580_1p0_mac_core[][2] = { {0x00008258, 0x00000000}, {0x0000825c, 0x40000000}, {0x00008260, 0x00080922}, - {0x00008264, 0x9bc00010}, + {0x00008264, 0x9d400010}, {0x00008268, 0xffffffff}, {0x0000826c, 0x0000ffff}, {0x00008270, 0x00000000}, diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index bbd249df23e..85e745366c4 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c @@ -389,7 +389,6 @@ bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan) if (!caldata) { chan->noisefloor = nf; - ah->noise = ath9k_hw_getchan_noise(ah, chan); return false; } diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h index ad14fecc76c..f1c32a52906 100644 --- a/drivers/net/wireless/ath/ath9k/common.h +++ b/drivers/net/wireless/ath/ath9k/common.h @@ -35,7 +35,7 @@ #define WME_AC_BK 3 #define WME_NUM_AC 4 -#define ATH_RSSI_DUMMY_MARKER 0x127 +#define ATH_RSSI_DUMMY_MARKER 127 #define ATH_RSSI_LPF_LEN 10 #define RSSI_LPF_THRESHOLD -20 #define ATH_RSSI_EP_MULTIPLIER (1<<7) diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index de5ee15ee63..2b8406a8e8f 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c @@ -771,7 +771,7 @@ static int ath9k_init_firmware_version(struct ath9k_htc_priv *priv) * required version. */ if (priv->fw_version_major != MAJOR_VERSION_REQ || - priv->fw_version_minor != MINOR_VERSION_REQ) { + priv->fw_version_minor < MINOR_VERSION_REQ) { dev_err(priv->dev, "ath9k_htc: Please upgrade to FW version %d.%d\n", MAJOR_VERSION_REQ, MINOR_VERSION_REQ); return -EINVAL; @@ -821,6 +821,7 @@ static int ath9k_init_device(struct ath9k_htc_priv *priv, if (error != 0) goto err_rx; + ath9k_hw_disable(priv->ah); #ifdef CONFIG_MAC80211_LEDS /* must be initialized before ieee80211_register_hw */ priv->led_cdev.default_trigger = ieee80211_create_tpt_led_trigger(priv->hw, diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 28a0edd57f0..20baf70624d 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1404,7 +1404,9 @@ static bool ath9k_hw_chip_reset(struct ath_hw *ah, reset_type = ATH9K_RESET_POWER_ON; else reset_type = ATH9K_RESET_COLD; - } + } else if (ah->chip_fullsleep || REG_READ(ah, AR_Q_TXE) || + (REG_READ(ah, AR_CR) & AR_CR_RXE)) + reset_type = ATH9K_RESET_COLD; if (!ath9k_hw_set_reset_reg(ah, reset_type)) return false; diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index f8e1fbbbfc5..d5c5dca3d36 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -1014,6 +1014,7 @@ int ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain); int ar9003_paprd_init_table(struct ath_hw *ah); bool ar9003_paprd_is_done(struct ath_hw *ah); void ar9003_hw_set_paprd_txdesc(struct ath_hw *ah, void *ds, u8 chains); +void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx); /* Hardware family op attach helpers */ void ar5008_hw_attach_phy_ops(struct ath_hw *ah); diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index cb006458fc4..cac5b256a1c 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -671,8 +671,7 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_MESH_POINT); - if (AR_SREV_5416(sc->sc_ah)) - hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; + hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS; @@ -695,10 +694,6 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) sc->ant_rx = hw->wiphy->available_antennas_rx; sc->ant_tx = hw->wiphy->available_antennas_tx; -#ifdef CONFIG_ATH9K_RATE_CONTROL - hw->rate_control_algorithm = "ath9k_rate_control"; -#endif - if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_2GHZ) hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &sc->sbands[IEEE80211_BAND_2GHZ]; diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 91e2c4f53d1..f6a095f8ffc 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1711,6 +1711,7 @@ static int ath9k_sta_add(struct ieee80211_hw *hw, struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath_node *an = (struct ath_node *) sta->drv_priv; struct ieee80211_key_conf ps_key = { }; + int key; ath_node_attach(sc, sta, vif); @@ -1718,7 +1719,9 @@ static int ath9k_sta_add(struct ieee80211_hw *hw, vif->type != NL80211_IFTYPE_AP_VLAN) return 0; - an->ps_key = ath_key_config(common, vif, sta, &ps_key); + key = ath_key_config(common, vif, sta, &ps_key); + if (key > 0) + an->ps_key = key; return 0; } @@ -1735,6 +1738,7 @@ static void ath9k_del_ps_key(struct ath_softc *sc, return; ath_key_delete(common, &ps_key); + an->ps_key = 0; } static int ath9k_sta_remove(struct ieee80211_hw *hw, diff --git a/drivers/net/wireless/ath/ath9k/rc.h b/drivers/net/wireless/ath/ath9k/rc.h index 75f8e9b06b2..12cf1225652 100644 --- a/drivers/net/wireless/ath/ath9k/rc.h +++ b/drivers/net/wireless/ath/ath9k/rc.h @@ -219,7 +219,7 @@ struct ath_rate_priv { struct ath_rc_stats rcstats[RATE_TABLE_SIZE]; }; -#ifdef CONFIG_ATH9K_RATE_CONTROL +#ifdef CONFIG_ATH9K_LEGACY_RATE_CONTROL int ath_rate_control_register(void); void ath_rate_control_unregister(void); #else diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c index 65f831faf2a..448f545ffd1 100644 --- a/drivers/net/wireless/b43/dma.c +++ b/drivers/net/wireless/b43/dma.c @@ -1487,8 +1487,12 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev, const struct b43_dma_ops *ops; struct b43_dmaring *ring; struct b43_dmadesc_meta *meta; + static const struct b43_txstatus fake; /* filled with 0 */ + const struct b43_txstatus *txstat; int slot, firstused; bool frame_succeed; + int skip; + static u8 err_out1, err_out2; ring = parse_cookie(dev, status->cookie, &slot); if (unlikely(!ring)) @@ -1501,13 +1505,36 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev, firstused = ring->current_slot - ring->used_slots + 1; if (firstused < 0) firstused = ring->nr_slots + firstused; + + skip = 0; if (unlikely(slot != firstused)) { /* This possibly is a firmware bug and will result in - * malfunction, memory leaks and/or stall of DMA functionality. */ - b43dbg(dev->wl, "Out of order TX status report on DMA ring %d. " - "Expected %d, but got %d\n", - ring->index, firstused, slot); - return; + * malfunction, memory leaks and/or stall of DMA functionality. + */ + if (slot == next_slot(ring, next_slot(ring, firstused))) { + /* If a single header/data pair was missed, skip over + * the first two slots in an attempt to recover. + */ + slot = firstused; + skip = 2; + if (!err_out1) { + /* Report the error once. */ + b43dbg(dev->wl, + "Skip on DMA ring %d slot %d.\n", + ring->index, slot); + err_out1 = 1; + } + } else { + /* More than a single header/data pair were missed. + * Report this error once. + */ + if (!err_out2) + b43dbg(dev->wl, + "Out of order TX status report on DMA ring %d. Expected %d, but got %d\n", + ring->index, firstused, slot); + err_out2 = 1; + return; + } } ops = ring->ops; @@ -1522,11 +1549,13 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev, slot, firstused, ring->index); break; } + if (meta->skb) { struct b43_private_tx_info *priv_info = - b43_get_priv_tx_info(IEEE80211_SKB_CB(meta->skb)); + b43_get_priv_tx_info(IEEE80211_SKB_CB(meta->skb)); - unmap_descbuffer(ring, meta->dmaaddr, meta->skb->len, 1); + unmap_descbuffer(ring, meta->dmaaddr, + meta->skb->len, 1); kfree(priv_info->bouncebuffer); priv_info->bouncebuffer = NULL; } else { @@ -1538,8 +1567,9 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev, struct ieee80211_tx_info *info; if (unlikely(!meta->skb)) { - /* This is a scatter-gather fragment of a frame, so - * the skb pointer must not be NULL. */ + /* This is a scatter-gather fragment of a frame, + * so the skb pointer must not be NULL. + */ b43dbg(dev->wl, "TX status unexpected NULL skb " "at slot %d (first=%d) on ring %d\n", slot, firstused, ring->index); @@ -1550,9 +1580,18 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev, /* * Call back to inform the ieee80211 subsystem about - * the status of the transmission. + * the status of the transmission. When skipping over + * a missed TX status report, use a status structure + * filled with zeros to indicate that the frame was not + * sent (frame_count 0) and not acknowledged */ - frame_succeed = b43_fill_txstatus_report(dev, info, status); + if (unlikely(skip)) + txstat = &fake; + else + txstat = status; + + frame_succeed = b43_fill_txstatus_report(dev, info, + txstat); #ifdef CONFIG_B43_DEBUG if (frame_succeed) ring->nr_succeed_tx_packets++; @@ -1580,12 +1619,14 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev, /* Everything unmapped and free'd. So it's not used anymore. */ ring->used_slots--; - if (meta->is_last_fragment) { + if (meta->is_last_fragment && !skip) { /* This is the last scatter-gather * fragment of the frame. We are done. */ break; } slot = next_slot(ring, slot); + if (skip > 0) + --skip; } if (ring->stopped) { B43_WARN_ON(free_slots(ring) < TX_SLOTS_PER_FRAME); @@ -1692,6 +1733,25 @@ static void dma_rx(struct b43_dmaring *ring, int *slot) sync_descbuffer_for_device(ring, dmaaddr, ring->rx_buffersize); } +void b43_dma_handle_rx_overflow(struct b43_dmaring *ring) +{ + int current_slot, previous_slot; + + B43_WARN_ON(ring->tx); + + /* Device has filled all buffers, drop all packets and let TCP + * decrease speed. + * Decrement RX index by one will let the device to see all slots + * as free again + */ + /* + *TODO: How to increase rx_drop in mac80211? + */ + current_slot = ring->ops->get_current_rxslot(ring); + previous_slot = prev_slot(ring, current_slot); + ring->ops->set_current_rxslot(ring, previous_slot); +} + void b43_dma_rx(struct b43_dmaring *ring) { const struct b43_dma_ops *ops = ring->ops; diff --git a/drivers/net/wireless/b43/dma.h b/drivers/net/wireless/b43/dma.h index 315b96ed1d9..df8c8cdcbdb 100644 --- a/drivers/net/wireless/b43/dma.h +++ b/drivers/net/wireless/b43/dma.h @@ -9,7 +9,7 @@ /* DMA-Interrupt reasons. */ #define B43_DMAIRQ_FATALMASK ((1 << 10) | (1 << 11) | (1 << 12) \ | (1 << 14) | (1 << 15)) -#define B43_DMAIRQ_NONFATALMASK (1 << 13) +#define B43_DMAIRQ_RDESC_UFLOW (1 << 13) #define B43_DMAIRQ_RX_DONE (1 << 16) /*** 32-bit DMA Engine. ***/ @@ -169,7 +169,7 @@ struct b43_dmadesc_generic { /* DMA engine tuning knobs */ #define B43_TXRING_SLOTS 256 -#define B43_RXRING_SLOTS 64 +#define B43_RXRING_SLOTS 256 #define B43_DMA0_RX_FW598_BUFSIZE (B43_DMA0_RX_FW598_FO + IEEE80211_MAX_FRAME_LEN) #define B43_DMA0_RX_FW351_BUFSIZE (B43_DMA0_RX_FW351_FO + IEEE80211_MAX_FRAME_LEN) @@ -295,6 +295,8 @@ int b43_dma_tx(struct b43_wldev *dev, void b43_dma_handle_txstatus(struct b43_wldev *dev, const struct b43_txstatus *status); +void b43_dma_handle_rx_overflow(struct b43_dmaring *ring); + void b43_dma_rx(struct b43_dmaring *ring); void b43_dma_direct_fifo_rx(struct b43_wldev *dev, diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 14fd2caa1f9..f8c4499cf64 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -1895,30 +1895,18 @@ static void b43_do_interrupt_thread(struct b43_wldev *dev) } } - if (unlikely(merged_dma_reason & (B43_DMAIRQ_FATALMASK | - B43_DMAIRQ_NONFATALMASK))) { - if (merged_dma_reason & B43_DMAIRQ_FATALMASK) { - b43err(dev->wl, "Fatal DMA error: " - "0x%08X, 0x%08X, 0x%08X, " - "0x%08X, 0x%08X, 0x%08X\n", - dma_reason[0], dma_reason[1], - dma_reason[2], dma_reason[3], - dma_reason[4], dma_reason[5]); - b43err(dev->wl, "This device does not support DMA " + if (unlikely(merged_dma_reason & (B43_DMAIRQ_FATALMASK))) { + b43err(dev->wl, + "Fatal DMA error: 0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X\n", + dma_reason[0], dma_reason[1], + dma_reason[2], dma_reason[3], + dma_reason[4], dma_reason[5]); + b43err(dev->wl, "This device does not support DMA " "on your system. It will now be switched to PIO.\n"); - /* Fall back to PIO transfers if we get fatal DMA errors! */ - dev->use_pio = true; - b43_controller_restart(dev, "DMA error"); - return; - } - if (merged_dma_reason & B43_DMAIRQ_NONFATALMASK) { - b43err(dev->wl, "DMA error: " - "0x%08X, 0x%08X, 0x%08X, " - "0x%08X, 0x%08X, 0x%08X\n", - dma_reason[0], dma_reason[1], - dma_reason[2], dma_reason[3], - dma_reason[4], dma_reason[5]); - } + /* Fall back to PIO transfers if we get fatal DMA errors! */ + dev->use_pio = true; + b43_controller_restart(dev, "DMA error"); + return; } if (unlikely(reason & B43_IRQ_UCODE_DEBUG)) @@ -1937,6 +1925,11 @@ static void b43_do_interrupt_thread(struct b43_wldev *dev) handle_irq_noise(dev); /* Check the DMA reason registers for received data. */ + if (dma_reason[0] & B43_DMAIRQ_RDESC_UFLOW) { + if (B43_DEBUG) + b43warn(dev->wl, "RX descriptor underrun\n"); + b43_dma_handle_rx_overflow(dev->dma.rx_ring); + } if (dma_reason[0] & B43_DMAIRQ_RX_DONE) { if (b43_using_pio_transfers(dev)) b43_pio_rx(dev->pio.rx_queue); @@ -1994,7 +1987,7 @@ static irqreturn_t b43_do_interrupt(struct b43_wldev *dev) return IRQ_NONE; dev->dma_reason[0] = b43_read32(dev, B43_MMIO_DMA0_REASON) - & 0x0001DC00; + & 0x0001FC00; dev->dma_reason[1] = b43_read32(dev, B43_MMIO_DMA1_REASON) & 0x0000DC00; dev->dma_reason[2] = b43_read32(dev, B43_MMIO_DMA2_REASON) @@ -2456,7 +2449,7 @@ static void b43_request_firmware(struct work_struct *work) for (i = 0; i < B43_NR_FWTYPES; i++) { errmsg = ctx->errors[i]; if (strlen(errmsg)) - b43err(dev->wl, errmsg); + b43err(dev->wl, "%s", errmsg); } b43_print_fw_helptext(dev->wl, 1); goto out; @@ -3122,7 +3115,7 @@ static int b43_chip_init(struct b43_wldev *dev) b43_write32(dev, 0x018C, 0x02000000); } b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, 0x00004000); - b43_write32(dev, B43_MMIO_DMA0_IRQ_MASK, 0x0001DC00); + b43_write32(dev, B43_MMIO_DMA0_IRQ_MASK, 0x0001FC00); b43_write32(dev, B43_MMIO_DMA1_IRQ_MASK, 0x0000DC00); b43_write32(dev, B43_MMIO_DMA2_IRQ_MASK, 0x0000DC00); b43_write32(dev, B43_MMIO_DMA3_IRQ_MASK, 0x0001DC00); diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c index 108118820b3..4ce3e1f036c 100644 --- a/drivers/net/wireless/b43/phy_n.c +++ b/drivers/net/wireless/b43/phy_n.c @@ -1320,7 +1320,7 @@ static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev) u16 clip_off[2] = { 0xFFFF, 0xFFFF }; u8 vcm_final = 0; - s8 offset[4]; + s32 offset[4]; s32 results[8][4] = { }; s32 results_min[4] = { }; s32 poll_results[4] = { }; @@ -1371,7 +1371,7 @@ static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev) } for (i = 0; i < 4; i++) { s32 curr; - s32 mind = 40; + s32 mind = 0x100000; s32 minpoll = 249; u8 minvcm = 0; if (2 * core != i) @@ -1487,7 +1487,7 @@ static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type) u8 regs_save_radio[2]; u16 regs_save_phy[2]; - s8 offset[4]; + s32 offset[4]; u8 core; u8 rail; @@ -1554,7 +1554,7 @@ static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type) } for (i = 0; i < 4; i++) { - s32 mind = 40; + s32 mind = 0x100000; u8 minvcm = 0; s32 minpoll = 249; s32 curr; @@ -4582,7 +4582,8 @@ static void b43_nphy_pmu_spur_avoid(struct b43_wldev *dev, bool avoid) #endif #ifdef CONFIG_B43_SSB case B43_BUS_SSB: - /* FIXME */ + ssb_pmu_spuravoid_pllupdate(&dev->dev->sdev->bus->chipco, + avoid); break; #endif } diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c index 18054d9c668..dbec2ff8a53 100644 --- a/drivers/net/wireless/hostap/hostap_ioctl.c +++ b/drivers/net/wireless/hostap/hostap_ioctl.c @@ -522,9 +522,9 @@ static int prism2_ioctl_giwaplist(struct net_device *dev, data->length = prism2_ap_get_sta_qual(local, addr, qual, IW_MAX_AP, 1); - memcpy(extra, &addr, sizeof(struct sockaddr) * data->length); + memcpy(extra, addr, sizeof(struct sockaddr) * data->length); data->flags = 1; /* has quality information */ - memcpy(extra + sizeof(struct sockaddr) * data->length, &qual, + memcpy(extra + sizeof(struct sockaddr) * data->length, qual, sizeof(struct iw_quality) * data->length); kfree(addr); diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c index 9aa48074ee2..409ed06d5f5 100644 --- a/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/iwlegacy/4965-mac.c @@ -4411,12 +4411,12 @@ il4965_irq_tasklet(struct il_priv *il) * is killed. Hence update the killswitch state here. The * rfkill handler will care about restarting if needed. */ - if (!test_bit(S_ALIVE, &il->status)) { - if (hw_rf_kill) - set_bit(S_RFKILL, &il->status); - else - clear_bit(S_RFKILL, &il->status); + if (hw_rf_kill) { + set_bit(S_RFKILL, &il->status); + } else { + clear_bit(S_RFKILL, &il->status); wiphy_rfkill_set_hw_state(il->hw->wiphy, hw_rf_kill); + il_force_reset(il, true); } handled |= CSR_INT_BIT_RF_KILL; @@ -5285,6 +5285,9 @@ il4965_alive_start(struct il_priv *il) il->active_rate = RATES_MASK; + il_power_update_mode(il, true); + D_INFO("Updated power mode\n"); + if (il_is_associated(il)) { struct il_rxon_cmd *active_rxon = (struct il_rxon_cmd *)&il->active; @@ -5315,9 +5318,6 @@ il4965_alive_start(struct il_priv *il) D_INFO("ALIVE processing complete.\n"); wake_up(&il->wait_command_queue); - il_power_update_mode(il, true); - D_INFO("Updated power mode\n"); - return; restart: diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c index 2ab6b968c5f..ae4befacfc3 100644 --- a/drivers/net/wireless/iwlegacy/common.c +++ b/drivers/net/wireless/iwlegacy/common.c @@ -4659,6 +4659,7 @@ il_force_reset(struct il_priv *il, bool external) return 0; } +EXPORT_SYMBOL(il_force_reset); int il_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c index 2977a12410c..3050b6a2559 100644 --- a/drivers/net/wireless/mwifiex/cmdevt.c +++ b/drivers/net/wireless/mwifiex/cmdevt.c @@ -1084,6 +1084,7 @@ mwifiex_process_hs_config(struct mwifiex_adapter *adapter) adapter->if_ops.wakeup(adapter); adapter->hs_activated = false; adapter->is_hs_configured = false; + adapter->is_suspended = false; mwifiex_hs_activated_event(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY), false); diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c index 8f9382b9c3c..b968b3564f4 100644 --- a/drivers/net/wireless/mwifiex/join.c +++ b/drivers/net/wireless/mwifiex/join.c @@ -1049,10 +1049,9 @@ mwifiex_cmd_802_11_ad_hoc_join(struct mwifiex_private *priv, adhoc_join->bss_descriptor.bssid, adhoc_join->bss_descriptor.ssid); - for (i = 0; bss_desc->supported_rates[i] && - i < MWIFIEX_SUPPORTED_RATES; - i++) - ; + for (i = 0; i < MWIFIEX_SUPPORTED_RATES && + bss_desc->supported_rates[i]; i++) + ; rates_size = i; /* Copy Data Rates from the Rates recorded in scan response */ diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c index 6ca3d8a3e0e..59e946ac464 100644 --- a/drivers/net/wireless/mwifiex/pcie.c +++ b/drivers/net/wireless/mwifiex/pcie.c @@ -288,7 +288,7 @@ static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter) i++; usleep_range(10, 20); /* 50ms max wait */ - if (i == 50000) + if (i == 5000) break; } @@ -1828,9 +1828,9 @@ static void mwifiex_pcie_cleanup(struct mwifiex_adapter *adapter) if (pdev) { pci_iounmap(pdev, card->pci_mmap); pci_iounmap(pdev, card->pci_mmap1); - - pci_release_regions(pdev); pci_disable_device(pdev); + pci_release_region(pdev, 2); + pci_release_region(pdev, 0); pci_set_drvdata(pdev, NULL); } } diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c index 7d00a87e9a1..4be8ccc8e9a 100644 --- a/drivers/net/wireless/mwifiex/sdio.c +++ b/drivers/net/wireless/mwifiex/sdio.c @@ -1449,8 +1449,8 @@ static int mwifiex_sdio_host_to_card(struct mwifiex_adapter *adapter, /* Allocate buffer and copy payload */ blk_size = MWIFIEX_SDIO_BLOCK_SIZE; buf_block_len = (pkt_len + blk_size - 1) / blk_size; - *(u16 *) &payload[0] = (u16) pkt_len; - *(u16 *) &payload[2] = type; + *(__le16 *)&payload[0] = cpu_to_le16((u16)pkt_len); + *(__le16 *)&payload[2] = cpu_to_le16(type); /* * This is SDIO specific header diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index 4fb146a8fac..dc70c0f842e 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c @@ -105,7 +105,7 @@ int mwifiex_request_set_multicast_list(struct mwifiex_private *priv, } else { /* Multicast */ priv->curr_pkt_filter &= ~HostCmd_ACT_MAC_PROMISCUOUS_ENABLE; - if (mcast_list->mode == MWIFIEX_MULTICAST_MODE) { + if (mcast_list->mode == MWIFIEX_ALL_MULTI_MODE) { dev_dbg(priv->adapter->dev, "info: Enabling All Multicast!\n"); priv->curr_pkt_filter |= @@ -117,20 +117,11 @@ int mwifiex_request_set_multicast_list(struct mwifiex_private *priv, dev_dbg(priv->adapter->dev, "info: Set multicast list=%d\n", mcast_list->num_multicast_addr); - /* Set multicast addresses to firmware */ - if (old_pkt_filter == priv->curr_pkt_filter) { - /* Send request to firmware */ - ret = mwifiex_send_cmd_async(priv, - HostCmd_CMD_MAC_MULTICAST_ADR, - HostCmd_ACT_GEN_SET, 0, - mcast_list); - } else { - /* Send request to firmware */ - ret = mwifiex_send_cmd_async(priv, - HostCmd_CMD_MAC_MULTICAST_ADR, - HostCmd_ACT_GEN_SET, 0, - mcast_list); - } + /* Send multicast addresses to firmware */ + ret = mwifiex_send_cmd_async(priv, + HostCmd_CMD_MAC_MULTICAST_ADR, + HostCmd_ACT_GEN_SET, 0, + mcast_list); } } } diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index be20cf765bc..af30777ce31 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c @@ -84,8 +84,8 @@ static struct usb_device_id p54u_table[] = { {USB_DEVICE(0x06b9, 0x0121)}, /* Thomson SpeedTouch 121g */ {USB_DEVICE(0x0707, 0xee13)}, /* SMC 2862W-G version 2 */ {USB_DEVICE(0x0803, 0x4310)}, /* Zoom 4410a */ - {USB_DEVICE(0x083a, 0x4503)}, /* T-Com Sinus 154 data II */ {USB_DEVICE(0x083a, 0x4521)}, /* Siemens Gigaset USB Adapter 54 version 2 */ + {USB_DEVICE(0x083a, 0x4531)}, /* T-Com Sinus 154 data II */ {USB_DEVICE(0x083a, 0xc501)}, /* Zoom Wireless-G 4410 */ {USB_DEVICE(0x083a, 0xf503)}, /* Accton FD7050E ver 1010ec */ {USB_DEVICE(0x0846, 0x4240)}, /* Netgear WG111 (v2) */ diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 2ce6bf5b671..72cb1217837 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -4627,8 +4627,8 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev) default_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A2); for (i = 14; i < spec->num_channels; i++) { - info[i].default_power1 = default_power1[i]; - info[i].default_power2 = default_power2[i]; + info[i].default_power1 = default_power1[i - 14]; + info[i].default_power2 = default_power2[i - 14]; } } diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 12b1ff5a6a3..8f2c88e2c33 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -1157,7 +1157,9 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) rt2x00dev->hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP) | +#ifdef CONFIG_MAC80211_MESH BIT(NL80211_IFTYPE_MESH_POINT) | +#endif BIT(NL80211_IFTYPE_WDS); /* diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index 17148bb2442..10fe07d96ea 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c @@ -52,8 +52,8 @@ int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev, udelay(REGISTER_BUSY_DELAY); } - ERROR(rt2x00dev, "Indirect register access failed: " - "offset=0x%.08x, value=0x%.08x\n", offset, *reg); + printk_once(KERN_ERR "%s() Indirect register access failed: " + "offset=0x%.08x, value=0x%.08x\n", __func__, offset, *reg); *reg = ~0; return 0; diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 50f92d5a2bd..4d792a242c5 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c @@ -856,13 +856,8 @@ void rt2x00queue_index_inc(struct queue_entry *entry, enum queue_index index) spin_unlock_irqrestore(&queue->index_lock, irqflags); } -void rt2x00queue_pause_queue(struct data_queue *queue) +void rt2x00queue_pause_queue_nocheck(struct data_queue *queue) { - if (!test_bit(DEVICE_STATE_PRESENT, &queue->rt2x00dev->flags) || - !test_bit(QUEUE_STARTED, &queue->flags) || - test_and_set_bit(QUEUE_PAUSED, &queue->flags)) - return; - switch (queue->qid) { case QID_AC_VO: case QID_AC_VI: @@ -878,6 +873,15 @@ void rt2x00queue_pause_queue(struct data_queue *queue) break; } } +void rt2x00queue_pause_queue(struct data_queue *queue) +{ + if (!test_bit(DEVICE_STATE_PRESENT, &queue->rt2x00dev->flags) || + !test_bit(QUEUE_STARTED, &queue->flags) || + test_and_set_bit(QUEUE_PAUSED, &queue->flags)) + return; + + rt2x00queue_pause_queue_nocheck(queue); +} EXPORT_SYMBOL_GPL(rt2x00queue_pause_queue); void rt2x00queue_unpause_queue(struct data_queue *queue) @@ -939,7 +943,7 @@ void rt2x00queue_stop_queue(struct data_queue *queue) return; } - rt2x00queue_pause_queue(queue); + rt2x00queue_pause_queue_nocheck(queue); queue->rt2x00dev->ops->lib->stop_queue(queue); diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index bdaba3fddd9..0cb0eecf94e 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -2822,7 +2822,8 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A_START); for (i = 14; i < spec->num_channels; i++) { info[i].max_power = MAX_TXPOWER; - info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]); + info[i].default_power1 = + TXPOWER_FROM_DEV(tx_power[i - 14]); } } diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index fda8671474d..ffdd32e74b0 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -2167,7 +2167,8 @@ static int rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A_START); for (i = 14; i < spec->num_channels; i++) { info[i].max_power = MAX_TXPOWER; - info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]); + info[i].default_power1 = + TXPOWER_FROM_DEV(tx_power[i - 14]); } } diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/rtlwifi/base.c index e54488db0e1..18d9eb3ad7a 100644 --- a/drivers/net/wireless/rtlwifi/base.c +++ b/drivers/net/wireless/rtlwifi/base.c @@ -980,7 +980,8 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) is_tx ? "Tx" : "Rx"); if (is_tx) { - rtl_lps_leave(hw); + schedule_work(&rtlpriv-> + works.lps_leave_work); ppsc->last_delaylps_stamp_jiffies = jiffies; } @@ -990,7 +991,7 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) } } else if (ETH_P_ARP == ether_type) { if (is_tx) { - rtl_lps_leave(hw); + schedule_work(&rtlpriv->works.lps_leave_work); ppsc->last_delaylps_stamp_jiffies = jiffies; } @@ -1000,7 +1001,7 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) "802.1X %s EAPOL pkt!!\n", is_tx ? "Tx" : "Rx"); if (is_tx) { - rtl_lps_leave(hw); + schedule_work(&rtlpriv->works.lps_leave_work); ppsc->last_delaylps_stamp_jiffies = jiffies; } diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c index 0c74d4f2eeb..91d2e28db4d 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c @@ -1376,75 +1376,58 @@ void rtl92cu_card_disable(struct ieee80211_hw *hw) } void rtl92cu_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid) -{ - /* dummy routine needed for callback from rtl_op_configure_filter() */ -} - -/*========================================================================== */ - -static void _rtl92cu_set_check_bssid(struct ieee80211_hw *hw, - enum nl80211_iftype type) { struct rtl_priv *rtlpriv = rtl_priv(hw); - u32 reg_rcr = rtl_read_dword(rtlpriv, REG_RCR); struct rtl_hal *rtlhal = rtl_hal(rtlpriv); - struct rtl_phy *rtlphy = &(rtlpriv->phy); - u8 filterout_non_associated_bssid = false; + u32 reg_rcr = rtl_read_dword(rtlpriv, REG_RCR); - switch (type) { - case NL80211_IFTYPE_ADHOC: - case NL80211_IFTYPE_STATION: - filterout_non_associated_bssid = true; - break; - case NL80211_IFTYPE_UNSPECIFIED: - case NL80211_IFTYPE_AP: - default: - break; - } - if (filterout_non_associated_bssid) { + if (rtlpriv->psc.rfpwr_state != ERFON) + return; + + if (check_bssid) { + u8 tmp; if (IS_NORMAL_CHIP(rtlhal->version)) { - switch (rtlphy->current_io_type) { - case IO_CMD_RESUME_DM_BY_SCAN: - reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN); - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_RCR, (u8 *)(®_rcr)); - /* enable update TSF */ - _rtl92cu_set_bcn_ctrl_reg(hw, 0, BIT(4)); - break; - case IO_CMD_PAUSE_DM_BY_SCAN: - reg_rcr &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN); - rtlpriv->cfg->ops->set_hw_reg(hw, - HW_VAR_RCR, (u8 *)(®_rcr)); - /* disable update TSF */ - _rtl92cu_set_bcn_ctrl_reg(hw, BIT(4), 0); - break; - } + reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN); + tmp = BIT(4); } else { - reg_rcr |= (RCR_CBSSID); - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, - (u8 *)(®_rcr)); - _rtl92cu_set_bcn_ctrl_reg(hw, 0, (BIT(4)|BIT(5))); + reg_rcr |= RCR_CBSSID; + tmp = BIT(4) | BIT(5); } - } else if (filterout_non_associated_bssid == false) { + rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, + (u8 *) (®_rcr)); + _rtl92cu_set_bcn_ctrl_reg(hw, 0, tmp); + } else { + u8 tmp; if (IS_NORMAL_CHIP(rtlhal->version)) { - reg_rcr &= (~(RCR_CBSSID_DATA | RCR_CBSSID_BCN)); - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, - (u8 *)(®_rcr)); - _rtl92cu_set_bcn_ctrl_reg(hw, BIT(4), 0); + reg_rcr &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN); + tmp = BIT(4); } else { - reg_rcr &= (~RCR_CBSSID); - rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, - (u8 *)(®_rcr)); - _rtl92cu_set_bcn_ctrl_reg(hw, (BIT(4)|BIT(5)), 0); + reg_rcr &= ~RCR_CBSSID; + tmp = BIT(4) | BIT(5); } + reg_rcr &= (~(RCR_CBSSID_DATA | RCR_CBSSID_BCN)); + rtlpriv->cfg->ops->set_hw_reg(hw, + HW_VAR_RCR, (u8 *) (®_rcr)); + _rtl92cu_set_bcn_ctrl_reg(hw, tmp, 0); } } +/*========================================================================== */ + int rtl92cu_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type) { + struct rtl_priv *rtlpriv = rtl_priv(hw); + if (_rtl92cu_set_media_status(hw, type)) return -EOPNOTSUPP; - _rtl92cu_set_check_bssid(hw, type); + + if (rtlpriv->mac80211.link_state == MAC80211_LINKED) { + if (type != NL80211_IFTYPE_AP) + rtl92cu_set_check_bssid(hw, true); + } else { + rtl92cu_set_check_bssid(hw, false); + } + return 0; } @@ -2059,8 +2042,6 @@ void rtl92cu_update_hal_rate_table(struct ieee80211_hw *hw, (shortgi_rate << 4) | (shortgi_rate); } rtl_write_dword(rtlpriv, REG_ARFR0 + ratr_index * 4, ratr_value); - RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, "%x\n", - rtl_read_dword(rtlpriv, REG_ARFR0)); } void rtl92cu_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level) diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c b/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c index 506b9a078ed..47634264758 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c @@ -104,7 +104,7 @@ void rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw, tx_agc[RF90_PATH_A] = 0x10101010; tx_agc[RF90_PATH_B] = 0x10101010; } else if (rtlpriv->dm.dynamic_txhighpower_lvl == - TXHIGHPWRLEVEL_LEVEL1) { + TXHIGHPWRLEVEL_LEVEL2) { tx_agc[RF90_PATH_A] = 0x00000000; tx_agc[RF90_PATH_B] = 0x00000000; } else{ diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c index 61e57689a05..3f869c9f71e 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c @@ -285,6 +285,7 @@ static struct usb_device_id rtl8192c_usb_ids[] = { {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x817f, rtl92cu_hal_cfg)}, /* RTL8188CUS-VL */ {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x818a, rtl92cu_hal_cfg)}, + {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x819a, rtl92cu_hal_cfg)}, /* 8188 Combo for BC4 */ {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8754, rtl92cu_hal_cfg)}, @@ -356,6 +357,7 @@ static struct usb_device_id rtl8192c_usb_ids[] = { {RTL_USB_DEVICE(0x2001, 0x330a, rtl92cu_hal_cfg)}, /*D-Link-Alpha*/ {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*/ {RTL_USB_DEVICE(0x7392, 0x7822, rtl92cu_hal_cfg)}, /*Edimax -Edimax*/ {} }; diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c index 8fa144fa0c9..2b6faa069e9 100644 --- a/drivers/net/wireless/rtlwifi/usb.c +++ b/drivers/net/wireless/rtlwifi/usb.c @@ -42,8 +42,12 @@ static void usbctrl_async_callback(struct urb *urb) { - if (urb) - kfree(urb->context); + if (urb) { + /* free dr */ + kfree(urb->setup_packet); + /* free databuf */ + kfree(urb->transfer_buffer); + } } static int _usbctrl_vendorreq_async_write(struct usb_device *udev, u8 request, @@ -55,39 +59,47 @@ static int _usbctrl_vendorreq_async_write(struct usb_device *udev, u8 request, u8 reqtype; struct usb_ctrlrequest *dr; struct urb *urb; - struct rtl819x_async_write_data { - u8 data[REALTEK_USB_VENQT_MAX_BUF_SIZE]; - struct usb_ctrlrequest dr; - } *buf; + const u16 databuf_maxlen = REALTEK_USB_VENQT_MAX_BUF_SIZE; + u8 *databuf; + + if (WARN_ON_ONCE(len > databuf_maxlen)) + len = databuf_maxlen; pipe = usb_sndctrlpipe(udev, 0); /* write_out */ reqtype = REALTEK_USB_VENQT_WRITE; - buf = kmalloc(sizeof(*buf), GFP_ATOMIC); - if (!buf) + dr = kmalloc(sizeof(*dr), GFP_ATOMIC); + if (!dr) + return -ENOMEM; + + databuf = kmalloc(databuf_maxlen, GFP_ATOMIC); + if (!databuf) { + kfree(dr); return -ENOMEM; + } urb = usb_alloc_urb(0, GFP_ATOMIC); if (!urb) { - kfree(buf); + kfree(databuf); + kfree(dr); return -ENOMEM; } - dr = &buf->dr; - dr->bRequestType = reqtype; dr->bRequest = request; dr->wValue = cpu_to_le16(value); dr->wIndex = cpu_to_le16(index); dr->wLength = cpu_to_le16(len); /* data are already in little-endian order */ - memcpy(buf, pdata, len); + memcpy(databuf, pdata, len); usb_fill_control_urb(urb, udev, pipe, - (unsigned char *)dr, buf, len, - usbctrl_async_callback, buf); + (unsigned char *)dr, databuf, len, + usbctrl_async_callback, NULL); rc = usb_submit_urb(urb, GFP_ATOMIC); - if (rc < 0) - kfree(buf); + if (rc < 0) { + kfree(databuf); + kfree(dr); + } usb_free_urb(urb); return rc; } @@ -542,8 +554,8 @@ static void _rtl_rx_pre_process(struct ieee80211_hw *hw, struct sk_buff *skb) WARN_ON(skb_queue_empty(&rx_queue)); while (!skb_queue_empty(&rx_queue)) { _skb = skb_dequeue(&rx_queue); - _rtl_usb_rx_process_agg(hw, skb); - ieee80211_rx_irqsafe(hw, skb); + _rtl_usb_rx_process_agg(hw, _skb); + ieee80211_rx_irqsafe(hw, _skb); } } @@ -841,6 +853,7 @@ static void _rtl_usb_transmit(struct ieee80211_hw *hw, struct sk_buff *skb, if (unlikely(!_urb)) { RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Can't allocate urb. Drop skb!\n"); + kfree_skb(skb); return; } urb_list = &rtlusb->tx_pending[ep_num]; diff --git a/drivers/net/wireless/zd1201.c b/drivers/net/wireless/zd1201.c index a66b93b7ff9..1662fcc41eb 100644 --- a/drivers/net/wireless/zd1201.c +++ b/drivers/net/wireless/zd1201.c @@ -98,10 +98,12 @@ static int zd1201_fw_upload(struct usb_device *dev, int apfw) goto exit; err = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), 0x4, - USB_DIR_IN | 0x40, 0,0, &ret, sizeof(ret), ZD1201_FW_TIMEOUT); + USB_DIR_IN | 0x40, 0, 0, buf, sizeof(ret), ZD1201_FW_TIMEOUT); if (err < 0) goto exit; + memcpy(&ret, buf, sizeof(ret)); + if (ret & 0x80) { err = -EIO; goto exit; diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h index 94b79c3338c..9d7f1723dd8 100644 --- a/drivers/net/xen-netback/common.h +++ b/drivers/net/xen-netback/common.h @@ -151,6 +151,9 @@ void xen_netbk_queue_tx_skb(struct xenvif *vif, struct sk_buff *skb); /* Notify xenvif that ring now has space to send an skb to the frontend */ void xenvif_notify_tx_completion(struct xenvif *vif); +/* Prevent the device from generating any further traffic. */ +void xenvif_carrier_off(struct xenvif *vif); + /* Returns number of ring slots required to send an skb to the frontend */ unsigned int xen_netbk_count_skb_slots(struct xenvif *vif, struct sk_buff *skb); diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index b7d41f8c338..221f4265f7d 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c @@ -132,6 +132,7 @@ static void xenvif_up(struct xenvif *vif) static void xenvif_down(struct xenvif *vif) { disable_irq(vif->irq); + del_timer_sync(&vif->credit_timeout); xen_netbk_deschedule_xenvif(vif); xen_netbk_remove_xenvif(vif); } @@ -343,23 +344,26 @@ int xenvif_connect(struct xenvif *vif, unsigned long tx_ring_ref, return err; } -void xenvif_disconnect(struct xenvif *vif) +void xenvif_carrier_off(struct xenvif *vif) { struct net_device *dev = vif->dev; - if (netif_carrier_ok(dev)) { - rtnl_lock(); - netif_carrier_off(dev); /* discard queued packets */ - if (netif_running(dev)) - xenvif_down(vif); - rtnl_unlock(); - xenvif_put(vif); - } + + rtnl_lock(); + netif_carrier_off(dev); /* discard queued packets */ + if (netif_running(dev)) + xenvif_down(vif); + rtnl_unlock(); + xenvif_put(vif); +} + +void xenvif_disconnect(struct xenvif *vif) +{ + if (netif_carrier_ok(vif->dev)) + xenvif_carrier_off(vif); atomic_dec(&vif->refcnt); wait_event(vif->waiting_to_free, atomic_read(&vif->refcnt) == 0); - del_timer_sync(&vif->credit_timeout); - if (vif->irq) unbind_from_irqhandler(vif->irq, vif); diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index 2596401308a..0d22cff02de 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c @@ -146,7 +146,8 @@ void xen_netbk_remove_xenvif(struct xenvif *vif) atomic_dec(&netbk->netfront_count); } -static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx); +static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx, + u8 status); static void make_tx_response(struct xenvif *vif, struct xen_netif_tx_request *txp, s8 st); @@ -851,7 +852,7 @@ static void netbk_tx_err(struct xenvif *vif, do { make_tx_response(vif, txp, XEN_NETIF_RSP_ERROR); - if (cons >= end) + if (cons == end) break; txp = RING_GET_REQUEST(&vif->tx, cons++); } while (1); @@ -860,6 +861,13 @@ static void netbk_tx_err(struct xenvif *vif, xenvif_put(vif); } +static void netbk_fatal_tx_err(struct xenvif *vif) +{ + netdev_err(vif->dev, "fatal error; disabling device\n"); + xenvif_carrier_off(vif); + xenvif_put(vif); +} + static int netbk_count_requests(struct xenvif *vif, struct xen_netif_tx_request *first, struct xen_netif_tx_request *txp, @@ -873,36 +881,39 @@ static int netbk_count_requests(struct xenvif *vif, do { if (frags >= work_to_do) { - netdev_dbg(vif->dev, "Need more frags\n"); - return -frags; + netdev_err(vif->dev, "Need more frags\n"); + netbk_fatal_tx_err(vif); + return -ENODATA; } if (unlikely(frags >= MAX_SKB_FRAGS)) { - netdev_dbg(vif->dev, "Too many frags\n"); - return -frags; + netdev_err(vif->dev, "Too many frags\n"); + netbk_fatal_tx_err(vif); + return -E2BIG; } memcpy(txp, RING_GET_REQUEST(&vif->tx, cons + frags), sizeof(*txp)); if (txp->size > first->size) { - netdev_dbg(vif->dev, "Frags galore\n"); - return -frags; + netdev_err(vif->dev, "Frag is bigger than frame.\n"); + netbk_fatal_tx_err(vif); + return -EIO; } first->size -= txp->size; frags++; if (unlikely((txp->offset + txp->size) > PAGE_SIZE)) { - netdev_dbg(vif->dev, "txp->offset: %x, size: %u\n", + netdev_err(vif->dev, "txp->offset: %x, size: %u\n", txp->offset, txp->size); - return -frags; + netbk_fatal_tx_err(vif); + return -EINVAL; } } while ((txp++)->flags & XEN_NETTXF_more_data); return frags; } static struct page *xen_netbk_alloc_page(struct xen_netbk *netbk, - struct sk_buff *skb, u16 pending_idx) { struct page *page; @@ -936,9 +947,9 @@ static struct gnttab_copy *xen_netbk_get_requests(struct xen_netbk *netbk, index = pending_index(netbk->pending_cons++); pending_idx = netbk->pending_ring[index]; - page = xen_netbk_alloc_page(netbk, skb, pending_idx); + page = xen_netbk_alloc_page(netbk, pending_idx); if (!page) - return NULL; + goto err; gop->source.u.ref = txp->gref; gop->source.domid = vif->domid; @@ -960,6 +971,17 @@ static struct gnttab_copy *xen_netbk_get_requests(struct xen_netbk *netbk, } return gop; +err: + /* Unwind, freeing all pages and sending error responses. */ + while (i-- > start) { + xen_netbk_idx_release(netbk, frag_get_pending_idx(&frags[i]), + XEN_NETIF_RSP_ERROR); + } + /* The head too, if necessary. */ + if (start) + xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_ERROR); + + return NULL; } static int xen_netbk_tx_check_gop(struct xen_netbk *netbk, @@ -968,30 +990,20 @@ static int xen_netbk_tx_check_gop(struct xen_netbk *netbk, { struct gnttab_copy *gop = *gopp; u16 pending_idx = *((u16 *)skb->data); - struct pending_tx_info *pending_tx_info = netbk->pending_tx_info; - struct xenvif *vif = pending_tx_info[pending_idx].vif; - struct xen_netif_tx_request *txp; struct skb_shared_info *shinfo = skb_shinfo(skb); int nr_frags = shinfo->nr_frags; int i, err, start; /* Check status of header. */ err = gop->status; - if (unlikely(err)) { - pending_ring_idx_t index; - index = pending_index(netbk->pending_prod++); - txp = &pending_tx_info[pending_idx].req; - make_tx_response(vif, txp, XEN_NETIF_RSP_ERROR); - netbk->pending_ring[index] = pending_idx; - xenvif_put(vif); - } + if (unlikely(err)) + xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_ERROR); /* Skip first skb fragment if it is on same page as header fragment. */ start = (frag_get_pending_idx(&shinfo->frags[0]) == pending_idx); for (i = start; i < nr_frags; i++) { int j, newerr; - pending_ring_idx_t index; pending_idx = frag_get_pending_idx(&shinfo->frags[i]); @@ -1000,16 +1012,12 @@ static int xen_netbk_tx_check_gop(struct xen_netbk *netbk, if (likely(!newerr)) { /* Had a previous error? Invalidate this fragment. */ if (unlikely(err)) - xen_netbk_idx_release(netbk, pending_idx); + xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_OKAY); continue; } /* Error on this fragment: respond to client with an error. */ - txp = &netbk->pending_tx_info[pending_idx].req; - make_tx_response(vif, txp, XEN_NETIF_RSP_ERROR); - index = pending_index(netbk->pending_prod++); - netbk->pending_ring[index] = pending_idx; - xenvif_put(vif); + xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_ERROR); /* Not the first error? Preceding frags already invalidated. */ if (err) @@ -1017,10 +1025,10 @@ static int xen_netbk_tx_check_gop(struct xen_netbk *netbk, /* First error: invalidate header and preceding fragments. */ pending_idx = *((u16 *)skb->data); - xen_netbk_idx_release(netbk, pending_idx); + xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_OKAY); for (j = start; j < i; j++) { pending_idx = frag_get_pending_idx(&shinfo->frags[j]); - xen_netbk_idx_release(netbk, pending_idx); + xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_OKAY); } /* Remember the error: invalidate all subsequent fragments. */ @@ -1054,7 +1062,7 @@ static void xen_netbk_fill_frags(struct xen_netbk *netbk, struct sk_buff *skb) /* Take an extra reference to offset xen_netbk_idx_release */ get_page(netbk->mmap_pages[pending_idx]); - xen_netbk_idx_release(netbk, pending_idx); + xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_OKAY); } } @@ -1067,7 +1075,8 @@ static int xen_netbk_get_extras(struct xenvif *vif, do { if (unlikely(work_to_do-- <= 0)) { - netdev_dbg(vif->dev, "Missing extra info\n"); + netdev_err(vif->dev, "Missing extra info\n"); + netbk_fatal_tx_err(vif); return -EBADR; } @@ -1076,8 +1085,9 @@ static int xen_netbk_get_extras(struct xenvif *vif, if (unlikely(!extra.type || extra.type >= XEN_NETIF_EXTRA_TYPE_MAX)) { vif->tx.req_cons = ++cons; - netdev_dbg(vif->dev, + netdev_err(vif->dev, "Invalid extra type: %d\n", extra.type); + netbk_fatal_tx_err(vif); return -EINVAL; } @@ -1093,13 +1103,15 @@ static int netbk_set_skb_gso(struct xenvif *vif, struct xen_netif_extra_info *gso) { if (!gso->u.gso.size) { - netdev_dbg(vif->dev, "GSO size must not be zero.\n"); + netdev_err(vif->dev, "GSO size must not be zero.\n"); + netbk_fatal_tx_err(vif); return -EINVAL; } /* Currently only TCPv4 S.O. is supported. */ if (gso->u.gso.type != XEN_NETIF_GSO_TYPE_TCPV4) { - netdev_dbg(vif->dev, "Bad GSO type %d.\n", gso->u.gso.type); + netdev_err(vif->dev, "Bad GSO type %d.\n", gso->u.gso.type); + netbk_fatal_tx_err(vif); return -EINVAL; } @@ -1236,9 +1248,25 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk) /* Get a netif from the list with work to do. */ vif = poll_net_schedule_list(netbk); + /* This can sometimes happen because the test of + * list_empty(net_schedule_list) at the top of the + * loop is unlocked. Just go back and have another + * look. + */ if (!vif) continue; + if (vif->tx.sring->req_prod - vif->tx.req_cons > + XEN_NETIF_TX_RING_SIZE) { + netdev_err(vif->dev, + "Impossible number of requests. " + "req_prod %d, req_cons %d, size %ld\n", + vif->tx.sring->req_prod, vif->tx.req_cons, + XEN_NETIF_TX_RING_SIZE); + netbk_fatal_tx_err(vif); + continue; + } + RING_FINAL_CHECK_FOR_REQUESTS(&vif->tx, work_to_do); if (!work_to_do) { xenvif_put(vif); @@ -1266,17 +1294,14 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk) work_to_do = xen_netbk_get_extras(vif, extras, work_to_do); idx = vif->tx.req_cons; - if (unlikely(work_to_do < 0)) { - netbk_tx_err(vif, &txreq, idx); + if (unlikely(work_to_do < 0)) continue; - } } ret = netbk_count_requests(vif, &txreq, txfrags, work_to_do); - if (unlikely(ret < 0)) { - netbk_tx_err(vif, &txreq, idx - ret); + if (unlikely(ret < 0)) continue; - } + idx += ret; if (unlikely(txreq.size < ETH_HLEN)) { @@ -1288,11 +1313,11 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk) /* No crossing a page as the payload mustn't fragment. */ if (unlikely((txreq.offset + txreq.size) > PAGE_SIZE)) { - netdev_dbg(vif->dev, + netdev_err(vif->dev, "txreq.offset: %x, size: %u, end: %lu\n", txreq.offset, txreq.size, (txreq.offset&~PAGE_MASK) + txreq.size); - netbk_tx_err(vif, &txreq, idx); + netbk_fatal_tx_err(vif); continue; } @@ -1320,14 +1345,14 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk) gso = &extras[XEN_NETIF_EXTRA_TYPE_GSO - 1]; if (netbk_set_skb_gso(vif, skb, gso)) { + /* Failure in netbk_set_skb_gso is fatal. */ kfree_skb(skb); - netbk_tx_err(vif, &txreq, idx); continue; } } /* XXX could copy straight to head */ - page = xen_netbk_alloc_page(netbk, skb, pending_idx); + page = xen_netbk_alloc_page(netbk, pending_idx); if (!page) { kfree_skb(skb); netbk_tx_err(vif, &txreq, idx); @@ -1420,7 +1445,7 @@ static void xen_netbk_tx_submit(struct xen_netbk *netbk) txp->size -= data_len; } else { /* Schedule a response immediately. */ - xen_netbk_idx_release(netbk, pending_idx); + xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_OKAY); } if (txp->flags & XEN_NETTXF_csum_blank) @@ -1475,7 +1500,8 @@ static void xen_netbk_tx_action(struct xen_netbk *netbk) } -static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx) +static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx, + u8 status) { struct xenvif *vif; struct pending_tx_info *pending_tx_info; @@ -1489,7 +1515,7 @@ static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx) vif = pending_tx_info->vif; - make_tx_response(vif, &pending_tx_info->req, XEN_NETIF_RSP_OKAY); + make_tx_response(vif, &pending_tx_info->req, status); index = pending_index(netbk->pending_prod++); netbk->pending_ring[index] = pending_idx; diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index 91a375fb6ae..17fad3bcd0b 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -390,6 +390,8 @@ static void __unflatten_device_tree(struct boot_param_header *blob, mem = (unsigned long) dt_alloc(size + 4, __alignof__(struct device_node)); + memset((void *)mem, 0, size); + ((__be32 *)mem)[size / 4] = cpu_to_be32(0xdeadbeef); pr_debug(" unflattening %lx...\n", mem); diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 111569ccab4..d08c0d8ec22 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -673,15 +673,11 @@ static int pci_platform_power_transition(struct pci_dev *dev, pci_power_t state) error = platform_pci_set_power_state(dev, state); if (!error) pci_update_current_state(dev, state); - /* Fall back to PCI_D0 if native PM is not supported */ - if (!dev->pm_cap) - dev->current_state = PCI_D0; - } else { + } else error = -ENODEV; - /* Fall back to PCI_D0 if native PM is not supported */ - if (!dev->pm_cap) - dev->current_state = PCI_D0; - } + + if (error && !dev->pm_cap) /* Fall back to PCI_D0 */ + dev->current_state = PCI_D0; return error; } diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 680dbfa1b61..103c95e300f 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -1062,6 +1062,8 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP700_SATA, quirk DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP700_SATA, quirk_amd_ide_mode); DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_HUDSON2_SATA_IDE, quirk_amd_ide_mode); DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_HUDSON2_SATA_IDE, quirk_amd_ide_mode); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x7900, quirk_amd_ide_mode); +DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_AMD, 0x7900, quirk_amd_ide_mode); /* * Serverworks CSB5 IDE does not fully support native mode diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c index fd77e2bde2e..eae55c7b647 100644 --- a/drivers/pci/remove.c +++ b/drivers/pci/remove.c @@ -19,6 +19,8 @@ static void pci_free_resources(struct pci_dev *dev) static void pci_stop_dev(struct pci_dev *dev) { + pci_pme_active(dev, false); + if (dev->is_added) { pci_proc_detach_device(dev); pci_remove_sysfs_dev_files(dev); diff --git a/drivers/pcmcia/at91_cf.c b/drivers/pcmcia/at91_cf.c index 9694c1e783a..fc50168ec8f 100644 --- a/drivers/pcmcia/at91_cf.c +++ b/drivers/pcmcia/at91_cf.c @@ -100,9 +100,9 @@ static int at91_cf_get_status(struct pcmcia_socket *s, u_int *sp) int vcc = gpio_is_valid(cf->board->vcc_pin); *sp = SS_DETECT | SS_3VCARD; - if (!rdy || gpio_get_value(rdy)) + if (!rdy || gpio_get_value(cf->board->irq_pin)) *sp |= SS_READY; - if (!vcc || gpio_get_value(vcc)) + if (!vcc || gpio_get_value(cf->board->vcc_pin)) *sp |= SS_POWERON; } else *sp = 0; diff --git a/drivers/pcmcia/vrc4171_card.c b/drivers/pcmcia/vrc4171_card.c index 86e4a1a3c64..6bb02ab5dd9 100644 --- a/drivers/pcmcia/vrc4171_card.c +++ b/drivers/pcmcia/vrc4171_card.c @@ -246,6 +246,7 @@ static int pccard_init(struct pcmcia_socket *sock) socket = &vrc4171_sockets[slot]; socket->csc_irq = search_nonuse_irq(); socket->io_irq = search_nonuse_irq(); + spin_lock_init(&socket->lock); return 0; } diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index 110c7778cbf..12da8102121 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -860,8 +860,10 @@ static ssize_t show_infos(struct device *dev, /* * The HWRS method return informations about the hardware. * 0x80 bit is for WLAN, 0x100 for Bluetooth. + * 0x40 for WWAN, 0x10 for WIMAX. * The significance of others is yet to be found. - * If we don't find the method, we assume the device are present. + * We don't currently use this for device detection, and it + * takes several seconds to run on some systems. */ rv = acpi_evaluate_integer(asus->handle, "HWRS", NULL, &temp); if (!ACPI_FAILURE(rv)) @@ -1682,7 +1684,7 @@ static int asus_laptop_get_info(struct asus_laptop *asus) { struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; union acpi_object *model = NULL; - unsigned long long bsts_result, hwrs_result; + unsigned long long bsts_result; char *string = NULL; acpi_status status; @@ -1744,17 +1746,6 @@ static int asus_laptop_get_info(struct asus_laptop *asus) if (*string) pr_notice(" %s model detected\n", string); - /* - * The HWRS method return informations about the hardware. - * 0x80 bit is for WLAN, 0x100 for Bluetooth, - * 0x40 for WWAN, 0x10 for WIMAX. - * The significance of others is yet to be found. - */ - status = - acpi_evaluate_integer(asus->handle, "HWRS", NULL, &hwrs_result); - if (!ACPI_FAILURE(status)) - pr_notice(" HWRS returned %x", (int)hwrs_result); - if (!acpi_check_handle(asus->handle, METHOD_WL_STATUS, NULL)) asus->have_rsts = true; diff --git a/drivers/platform/x86/hp_accel.c b/drivers/platform/x86/hp_accel.c index 22b2dfa7314..fdacfcebd17 100644 --- a/drivers/platform/x86/hp_accel.c +++ b/drivers/platform/x86/hp_accel.c @@ -362,7 +362,8 @@ static int lis3lv02d_suspend(struct acpi_device *device, pm_message_t state) static int lis3lv02d_resume(struct acpi_device *device) { - return lis3lv02d_poweron(&lis3_dev); + lis3lv02d_poweron(&lis3_dev); + return 0; } #else #define lis3lv02d_suspend NULL diff --git a/drivers/platform/x86/ibm_rtl.c b/drivers/platform/x86/ibm_rtl.c index 7481146a5b4..97c2be195ef 100644 --- a/drivers/platform/x86/ibm_rtl.c +++ b/drivers/platform/x86/ibm_rtl.c @@ -244,7 +244,7 @@ static int __init ibm_rtl_init(void) { if (force) pr_warn("module loaded by force\n"); /* first ensure that we are running on IBM HW */ - else if (efi_enabled || !dmi_check_system(ibm_rtl_dmi_table)) + else if (efi_enabled(EFI_BOOT) || !dmi_check_system(ibm_rtl_dmi_table)) return -ENODEV; /* Get the address for the Extended BIOS Data Area */ diff --git a/drivers/platform/x86/samsung-laptop.c b/drivers/platform/x86/samsung-laptop.c index 1afbe5e0a34..de9f432cf22 100644 --- a/drivers/platform/x86/samsung-laptop.c +++ b/drivers/platform/x86/samsung-laptop.c @@ -26,6 +26,7 @@ #include #include #include +#include #if (defined CONFIG_ACPI_VIDEO || defined CONFIG_ACPI_VIDEO_MODULE) #include #endif @@ -1527,6 +1528,9 @@ static int __init samsung_init(void) struct samsung_laptop *samsung; int ret; + if (efi_enabled(EFI_BOOT)) + return -ENODEV; + quirks = &samsung_unknown; if (!force && !dmi_check_system(samsung_dmi_table)) return -ENODEV; diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index d68c0002f4a..f08aee680f0 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -8662,6 +8662,13 @@ static int __must_check __init get_thinkpad_model_data( tp->model_str = kstrdup(s, GFP_KERNEL); if (!tp->model_str) return -ENOMEM; + } else { + s = dmi_get_system_info(DMI_BIOS_VENDOR); + if (s && !(strnicmp(s, "Lenovo", 6))) { + tp->model_str = kstrdup(s, GFP_KERNEL); + if (!tp->model_str) + return -ENOMEM; + } } s = dmi_get_system_info(DMI_PRODUCT_NAME); diff --git a/drivers/power/ab8500_btemp.c b/drivers/power/ab8500_btemp.c index d8bb99394ac..2a6bf76baac 100644 --- a/drivers/power/ab8500_btemp.c +++ b/drivers/power/ab8500_btemp.c @@ -1115,7 +1115,7 @@ static void __exit ab8500_btemp_exit(void) platform_driver_unregister(&ab8500_btemp_driver); } -subsys_initcall_sync(ab8500_btemp_init); +device_initcall(ab8500_btemp_init); module_exit(ab8500_btemp_exit); MODULE_LICENSE("GPL v2"); diff --git a/drivers/power/abx500_chargalg.c b/drivers/power/abx500_chargalg.c index 804b88c760d..d8cd1517c84 100644 --- a/drivers/power/abx500_chargalg.c +++ b/drivers/power/abx500_chargalg.c @@ -1698,7 +1698,7 @@ static ssize_t abx500_chargalg_sysfs_charger(struct kobject *kobj, static struct attribute abx500_chargalg_en_charger = \ { .name = "chargalg", - .mode = S_IWUGO, + .mode = S_IWUSR, }; static struct attribute *abx500_chargalg_chg[] = { diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c index 9eca9f1ff0e..4c449b26de4 100644 --- a/drivers/power/charger-manager.c +++ b/drivers/power/charger-manager.c @@ -330,7 +330,7 @@ static void uevent_notify(struct charger_manager *cm, const char *event) strncpy(env_str, event, UEVENT_BUF_SIZE); kobject_uevent(&cm->dev->kobj, KOBJ_CHANGE); - dev_info(cm->dev, event); + dev_info(cm->dev, "%s", event); } /** diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index 7d5f56edb8e..5f8844c1eaa 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c @@ -805,9 +805,8 @@ static int cmos_suspend(struct device *dev) mask = RTC_IRQMASK; tmp &= ~mask; CMOS_WRITE(tmp, RTC_CONTROL); + hpet_mask_rtc_irq_bit(mask); - /* shut down hpet emulation - we don't need it for alarm */ - hpet_mask_rtc_irq_bit(RTC_PIE|RTC_AIE|RTC_UIE); cmos_checkintr(cmos, tmp); } spin_unlock_irq(&rtc_lock); @@ -872,6 +871,7 @@ static int cmos_resume(struct device *dev) rtc_update_irq(cmos->rtc, 1, mask); tmp &= ~RTC_AIE; hpet_mask_rtc_irq_bit(RTC_AIE); + hpet_rtc_timer_init(); } while (mask & RTC_AIE); spin_unlock_irq(&rtc_lock); } diff --git a/drivers/rtc/rtc-pcf2123.c b/drivers/rtc/rtc-pcf2123.c index 836118795c0..9ea255573d9 100644 --- a/drivers/rtc/rtc-pcf2123.c +++ b/drivers/rtc/rtc-pcf2123.c @@ -264,6 +264,7 @@ static int __devinit pcf2123_probe(struct spi_device *spi) if (!(rxbuf[0] & 0x20)) { dev_err(&spi->dev, "chip not found\n"); + ret = -ENODEV; goto kfree_exit; } diff --git a/drivers/rtc/rtc-rv3029c2.c b/drivers/rtc/rtc-rv3029c2.c index 0fbe57b2f6d..21d63d1fe88 100644 --- a/drivers/rtc/rtc-rv3029c2.c +++ b/drivers/rtc/rtc-rv3029c2.c @@ -310,7 +310,7 @@ static int rv3029c2_rtc_i2c_set_alarm(struct i2c_client *client, dev_dbg(&client->dev, "alarm IRQ armed\n"); } else { /* disable AIE irq */ - ret = rv3029c2_rtc_i2c_alarm_set_irq(client, 1); + ret = rv3029c2_rtc_i2c_alarm_set_irq(client, 0); if (ret) return ret; diff --git a/drivers/rtc/rtc-twl.c b/drivers/rtc/rtc-twl.c index 63ccc0f9427..c5ce19574d8 100644 --- a/drivers/rtc/rtc-twl.c +++ b/drivers/rtc/rtc-twl.c @@ -523,6 +523,7 @@ static int __devinit twl_rtc_probe(struct platform_device *pdev) } platform_set_drvdata(pdev, rtc); + device_init_wakeup(&pdev->dev, 1); return 0; out2: diff --git a/drivers/s390/char/sclp_cmd.c b/drivers/s390/char/sclp_cmd.c index 231a1d85127..e73b2191f67 100644 --- a/drivers/s390/char/sclp_cmd.c +++ b/drivers/s390/char/sclp_cmd.c @@ -509,6 +509,8 @@ static void __init sclp_add_standby_memory(void) add_memory_merged(0); } +#define MEM_SCT_SIZE (1UL << SECTION_SIZE_BITS) + static void __init insert_increment(u16 rn, int standby, int assigned) { struct memory_increment *incr, *new_incr; @@ -521,7 +523,7 @@ static void __init insert_increment(u16 rn, int standby, int assigned) new_incr->rn = rn; new_incr->standby = standby; if (!standby) - new_incr->usecount = 1; + new_incr->usecount = rzm > MEM_SCT_SIZE ? rzm/MEM_SCT_SIZE : 1; last_rn = 0; prev = &sclp_mem_list; list_for_each_entry(incr, &sclp_mem_list, list) { diff --git a/drivers/s390/kvm/kvm_virtio.c b/drivers/s390/kvm/kvm_virtio.c index d74e9ae6dfb..f97b2aa65f4 100644 --- a/drivers/s390/kvm/kvm_virtio.c +++ b/drivers/s390/kvm/kvm_virtio.c @@ -417,6 +417,26 @@ static void kvm_extint_handler(struct ext_code ext_code, } } +/* + * For s390-virtio, we expect a page above main storage containing + * the virtio configuration. Try to actually load from this area + * in order to figure out if the host provides this page. + */ +static int __init test_devices_support(unsigned long addr) +{ + int ret = -EIO; + + asm volatile( + "0: lura 0,%1\n" + "1: xgr %0,%0\n" + "2:\n" + EX_TABLE(0b,2b) + EX_TABLE(1b,2b) + : "+d" (ret) + : "a" (addr) + : "0", "cc"); + return ret; +} /* * Init function for virtio * devices are in a single page above top of "normal" mem @@ -428,21 +448,23 @@ static int __init kvm_devices_init(void) if (!MACHINE_IS_KVM) return -ENODEV; + if (test_devices_support(real_memory_size) < 0) + return -ENODEV; + + rc = vmem_add_mapping(real_memory_size, PAGE_SIZE); + if (rc) + return rc; + + kvm_devices = (void *) real_memory_size; + kvm_root = root_device_register("kvm_s390"); if (IS_ERR(kvm_root)) { rc = PTR_ERR(kvm_root); printk(KERN_ERR "Could not register kvm_s390 root device"); + vmem_remove_mapping(real_memory_size, PAGE_SIZE); return rc; } - rc = vmem_add_mapping(real_memory_size, PAGE_SIZE); - if (rc) { - root_device_unregister(kvm_root); - return rc; - } - - kvm_devices = (void *) real_memory_size; - INIT_WORK(&hotplug_work, hotplug_devices); service_subclass_irq_register(); diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index 4f1b10b7dea..3743ac93123 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c @@ -3,7 +3,7 @@ * * Module interface and handling of zfcp data structures. * - * Copyright IBM Corporation 2002, 2010 + * Copyright IBM Corp. 2002, 2013 */ /* @@ -23,6 +23,7 @@ * Christof Schmitt * Martin Petermann * Sven Schuetz + * Steffen Maier */ #define KMSG_COMPONENT "zfcp" @@ -415,6 +416,8 @@ struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *ccw_device) adapter->dma_parms.max_segment_size = ZFCP_QDIO_SBALE_LEN; adapter->ccw_device->dev.dma_parms = &adapter->dma_parms; + adapter->stat_read_buf_num = FSF_STATUS_READS_RECOM; + if (!zfcp_scsi_adapter_register(adapter)) return adapter; diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index e1b4f800e22..5c872708a57 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -102,10 +102,13 @@ static void zfcp_erp_action_dismiss_port(struct zfcp_port *port) if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_ERP_INUSE) zfcp_erp_action_dismiss(&port->erp_action); - else - shost_for_each_device(sdev, port->adapter->scsi_host) + else { + spin_lock(port->adapter->scsi_host->host_lock); + __shost_for_each_device(sdev, port->adapter->scsi_host) if (sdev_to_zfcp(sdev)->port == port) zfcp_erp_action_dismiss_lun(sdev); + spin_unlock(port->adapter->scsi_host->host_lock); + } } static void zfcp_erp_action_dismiss_adapter(struct zfcp_adapter *adapter) @@ -592,9 +595,11 @@ static void _zfcp_erp_lun_reopen_all(struct zfcp_port *port, int clear, { struct scsi_device *sdev; - shost_for_each_device(sdev, port->adapter->scsi_host) + spin_lock(port->adapter->scsi_host->host_lock); + __shost_for_each_device(sdev, port->adapter->scsi_host) if (sdev_to_zfcp(sdev)->port == port) _zfcp_erp_lun_reopen(sdev, clear, id, 0); + spin_unlock(port->adapter->scsi_host->host_lock); } static void zfcp_erp_strategy_followup_failed(struct zfcp_erp_action *act) @@ -1435,8 +1440,10 @@ void zfcp_erp_set_adapter_status(struct zfcp_adapter *adapter, u32 mask) atomic_set_mask(common_mask, &port->status); read_unlock_irqrestore(&adapter->port_list_lock, flags); - shost_for_each_device(sdev, adapter->scsi_host) + spin_lock_irqsave(adapter->scsi_host->host_lock, flags); + __shost_for_each_device(sdev, adapter->scsi_host) atomic_set_mask(common_mask, &sdev_to_zfcp(sdev)->status); + spin_unlock_irqrestore(adapter->scsi_host->host_lock, flags); } /** @@ -1470,11 +1477,13 @@ void zfcp_erp_clear_adapter_status(struct zfcp_adapter *adapter, u32 mask) } read_unlock_irqrestore(&adapter->port_list_lock, flags); - shost_for_each_device(sdev, adapter->scsi_host) { + spin_lock_irqsave(adapter->scsi_host->host_lock, flags); + __shost_for_each_device(sdev, adapter->scsi_host) { atomic_clear_mask(common_mask, &sdev_to_zfcp(sdev)->status); if (clear_counter) atomic_set(&sdev_to_zfcp(sdev)->erp_counter, 0); } + spin_unlock_irqrestore(adapter->scsi_host->host_lock, flags); } /** @@ -1488,16 +1497,19 @@ void zfcp_erp_set_port_status(struct zfcp_port *port, u32 mask) { struct scsi_device *sdev; u32 common_mask = mask & ZFCP_COMMON_FLAGS; + unsigned long flags; atomic_set_mask(mask, &port->status); if (!common_mask) return; - shost_for_each_device(sdev, port->adapter->scsi_host) + spin_lock_irqsave(port->adapter->scsi_host->host_lock, flags); + __shost_for_each_device(sdev, port->adapter->scsi_host) if (sdev_to_zfcp(sdev)->port == port) atomic_set_mask(common_mask, &sdev_to_zfcp(sdev)->status); + spin_unlock_irqrestore(port->adapter->scsi_host->host_lock, flags); } /** @@ -1512,6 +1524,7 @@ void zfcp_erp_clear_port_status(struct zfcp_port *port, u32 mask) struct scsi_device *sdev; u32 common_mask = mask & ZFCP_COMMON_FLAGS; u32 clear_counter = mask & ZFCP_STATUS_COMMON_ERP_FAILED; + unsigned long flags; atomic_clear_mask(mask, &port->status); @@ -1521,13 +1534,15 @@ void zfcp_erp_clear_port_status(struct zfcp_port *port, u32 mask) if (clear_counter) atomic_set(&port->erp_counter, 0); - shost_for_each_device(sdev, port->adapter->scsi_host) + spin_lock_irqsave(port->adapter->scsi_host->host_lock, flags); + __shost_for_each_device(sdev, port->adapter->scsi_host) if (sdev_to_zfcp(sdev)->port == port) { atomic_clear_mask(common_mask, &sdev_to_zfcp(sdev)->status); if (clear_counter) atomic_set(&sdev_to_zfcp(sdev)->erp_counter, 0); } + spin_unlock_irqrestore(port->adapter->scsi_host->host_lock, flags); } /** diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 2136fc2178e..961e327b692 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -3,7 +3,7 @@ * * Implementation of FSF commands. * - * Copyright IBM Corporation 2002, 2010 + * Copyright IBM Corp. 2002, 2013 */ #define KMSG_COMPONENT "zfcp" @@ -483,12 +483,8 @@ static int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req) fc_host_port_name(shost) = nsp->fl_wwpn; fc_host_node_name(shost) = nsp->fl_wwnn; - fc_host_port_id(shost) = ntoh24(bottom->s_id); - fc_host_speed(shost) = - zfcp_fsf_convert_portspeed(bottom->fc_link_speed); fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3; - adapter->hydra_version = bottom->adapter_type; adapter->timer_ticks = bottom->timer_interval & ZFCP_FSF_TIMER_INT_MASK; adapter->stat_read_buf_num = max(bottom->status_read_buf_num, (u16)FSF_STATUS_READS_RECOM); @@ -496,6 +492,19 @@ static int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req) if (fc_host_permanent_port_name(shost) == -1) fc_host_permanent_port_name(shost) = fc_host_port_name(shost); + zfcp_scsi_set_prot(adapter); + + /* no error return above here, otherwise must fix call chains */ + /* do not evaluate invalid fields */ + if (req->qtcb->header.fsf_status == FSF_EXCHANGE_CONFIG_DATA_INCOMPLETE) + return 0; + + fc_host_port_id(shost) = ntoh24(bottom->s_id); + fc_host_speed(shost) = + zfcp_fsf_convert_portspeed(bottom->fc_link_speed); + + adapter->hydra_version = bottom->adapter_type; + switch (bottom->fc_topology) { case FSF_TOPO_P2P: adapter->peer_d_id = ntoh24(bottom->peer_d_id); @@ -517,8 +526,6 @@ static int zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *req) return -EIO; } - zfcp_scsi_set_prot(adapter); - return 0; } @@ -563,8 +570,14 @@ static void zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *req) fc_host_port_type(shost) = FC_PORTTYPE_UNKNOWN; adapter->hydra_version = 0; + /* avoids adapter shutdown to be able to recognize + * events such as LINK UP */ + atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK, + &adapter->status); zfcp_fsf_link_down_info_eval(req, &qtcb->header.fsf_status_qual.link_down_info); + if (zfcp_fsf_exchange_config_evaluate(req)) + return; break; default: zfcp_erp_adapter_shutdown(adapter, 0, "fsecdh3"); diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c index e76d003ebdb..52c6b5930ff 100644 --- a/drivers/s390/scsi/zfcp_qdio.c +++ b/drivers/s390/scsi/zfcp_qdio.c @@ -224,11 +224,9 @@ int zfcp_qdio_sbals_from_sg(struct zfcp_qdio *qdio, struct zfcp_qdio_req *q_req, static int zfcp_qdio_sbal_check(struct zfcp_qdio *qdio) { - spin_lock_irq(&qdio->req_q_lock); if (atomic_read(&qdio->req_q_free) || !(atomic_read(&qdio->adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP)) return 1; - spin_unlock_irq(&qdio->req_q_lock); return 0; } @@ -246,9 +244,8 @@ int zfcp_qdio_sbal_get(struct zfcp_qdio *qdio) { long ret; - spin_unlock_irq(&qdio->req_q_lock); - ret = wait_event_interruptible_timeout(qdio->req_q_wq, - zfcp_qdio_sbal_check(qdio), 5 * HZ); + ret = wait_event_interruptible_lock_irq_timeout(qdio->req_q_wq, + zfcp_qdio_sbal_check(qdio), qdio->req_q_lock, 5 * HZ); if (!(atomic_read(&qdio->adapter->status) & ZFCP_STATUS_ADAPTER_QDIOUP)) return -EIO; @@ -262,7 +259,6 @@ int zfcp_qdio_sbal_get(struct zfcp_qdio *qdio) zfcp_erp_adapter_reopen(qdio->adapter, 0, "qdsbg_1"); } - spin_lock_irq(&qdio->req_q_lock); return -EIO; } diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index b79576b64f4..7b353647cb9 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -3,7 +3,7 @@ * * Interface to Linux SCSI midlayer. * - * Copyright IBM Corporation 2002, 2010 + * Copyright IBM Corp. 2002, 2013 */ #define KMSG_COMPONENT "zfcp" @@ -311,8 +311,12 @@ static struct scsi_host_template zfcp_scsi_host_template = { .proc_name = "zfcp", .can_queue = 4096, .this_id = -1, - .sg_tablesize = 1, /* adjusted later */ - .max_sectors = 8, /* adjusted later */ + .sg_tablesize = (((QDIO_MAX_ELEMENTS_PER_BUFFER - 1) + * ZFCP_QDIO_MAX_SBALS_PER_REQ) - 2), + /* GCD, adjusted later */ + .max_sectors = (((QDIO_MAX_ELEMENTS_PER_BUFFER - 1) + * ZFCP_QDIO_MAX_SBALS_PER_REQ) - 2) * 8, + /* GCD, adjusted later */ .dma_boundary = ZFCP_QDIO_SBALE_LEN - 1, .cmd_per_lun = 1, .use_clustering = 1, diff --git a/drivers/scsi/bnx2fc/bnx2fc_io.c b/drivers/scsi/bnx2fc/bnx2fc_io.c index e897ce975bb..f8a2d123a8a 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_io.c +++ b/drivers/scsi/bnx2fc/bnx2fc_io.c @@ -1786,7 +1786,7 @@ static void bnx2fc_parse_fcp_rsp(struct bnx2fc_cmd *io_req, fcp_sns_len = SCSI_SENSE_BUFFERSIZE; } - memset(sc_cmd->sense_buffer, 0, sizeof(sc_cmd->sense_buffer)); + memset(sc_cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); if (fcp_sns_len) memcpy(sc_cmd->sense_buffer, rq_data, fcp_sns_len); diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c index 13aeca3d51f..48105fcb5ee 100644 --- a/drivers/scsi/dc395x.c +++ b/drivers/scsi/dc395x.c @@ -3747,13 +3747,13 @@ static struct DeviceCtlBlk *device_alloc(struct AdapterCtlBlk *acb, dcb->max_command = 1; dcb->target_id = target; dcb->target_lun = lun; + dcb->dev_mode = eeprom->target[target].cfg0; #ifndef DC395x_NO_DISCONNECT dcb->identify_msg = IDENTIFY(dcb->dev_mode & NTC_DO_DISCONNECT, lun); #else dcb->identify_msg = IDENTIFY(0, lun); #endif - dcb->dev_mode = eeprom->target[target].cfg0; dcb->inquiry7 = 0; dcb->sync_mode = 0; dcb->min_nego_period = clock_period[period_index]; diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index 4c150dffb1a..5a1bd0ca2bb 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -470,7 +470,7 @@ static int __devinit isci_pci_probe(struct pci_dev *pdev, const struct pci_devic return -ENOMEM; pci_set_drvdata(pdev, pci_info); - if (efi_enabled) + if (efi_enabled(EFI_RUNTIME_SERVICES)) orom = isci_get_efi_var(pdev); if (!orom) diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c index 101b28e61c6..58e61834ddd 100644 --- a/drivers/scsi/libsas/sas_expander.c +++ b/drivers/scsi/libsas/sas_expander.c @@ -235,6 +235,17 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id, void *rsp) linkrate = phy->linkrate; memcpy(sas_addr, phy->attached_sas_addr, SAS_ADDR_SIZE); + /* Handle vacant phy - rest of dr data is not valid so skip it */ + if (phy->phy_state == PHY_VACANT) { + memset(phy->attached_sas_addr, 0, SAS_ADDR_SIZE); + phy->attached_dev_type = NO_DEVICE; + if (!test_bit(SAS_HA_ATA_EH_ACTIVE, &ha->state)) { + phy->phy_id = phy_id; + goto skip; + } else + goto out; + } + phy->attached_dev_type = to_dev_type(dr); if (test_bit(SAS_HA_ATA_EH_ACTIVE, &ha->state)) goto out; @@ -272,6 +283,7 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id, void *rsp) phy->phy->maximum_linkrate = dr->pmax_linkrate; phy->phy->negotiated_linkrate = phy->linkrate; + skip: if (new_phy) if (sas_phy_add(phy->phy)) { sas_phy_free(phy->phy); diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index 6308a8ddf6f..79261628d06 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -3493,11 +3493,21 @@ static int megasas_init_fw(struct megasas_instance *instance) break; } - /* - * We expect the FW state to be READY - */ - if (megasas_transition_to_ready(instance, 0)) - goto fail_ready_state; + if (megasas_transition_to_ready(instance, 0)) { + atomic_set(&instance->fw_reset_no_pci_access, 1); + instance->instancet->adp_reset + (instance, instance->reg_set); + atomic_set(&instance->fw_reset_no_pci_access, 0); + dev_info(&instance->pdev->dev, + "megasas: FW restarted successfully from %s!\n", + __func__); + + /*waitting for about 30 second before retry*/ + ssleep(30); + + if (megasas_transition_to_ready(instance, 0)) + goto fail_ready_state; + } /* Check if MSI-X is supported while in ready state */ msix_enable = (instance->instancet->read_fw_status_reg(reg_set) & @@ -4817,10 +4827,12 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance, sense, sense_handle); } - for (i = 0; i < ioc->sge_count && kbuff_arr[i]; i++) { - dma_free_coherent(&instance->pdev->dev, - kern_sge32[i].length, - kbuff_arr[i], kern_sge32[i].phys_addr); + for (i = 0; i < ioc->sge_count; i++) { + if (kbuff_arr[i]) + dma_free_coherent(&instance->pdev->dev, + kern_sge32[i].length, + kbuff_arr[i], + kern_sge32[i].phys_addr); } megasas_return_cmd(instance, cmd); diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index d953a57e779..35a05d1df9c 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c @@ -3963,11 +3963,7 @@ _scsih_qcmd_lck(struct scsi_cmnd *scmd, void (*done)(struct scsi_cmnd *)) else mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ; } else -/* MPI Revision I (UNIT = 0xA) - removed MPI2_SCSIIO_CONTROL_UNTAGGED */ -/* mpi_control |= MPI2_SCSIIO_CONTROL_UNTAGGED; - */ - mpi_control |= (0x500); - + mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ; } else mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ; /* Make sure Device is not raid volume. diff --git a/drivers/scsi/nsp32.c b/drivers/scsi/nsp32.c index 62b616891a3..e705ed333f4 100644 --- a/drivers/scsi/nsp32.c +++ b/drivers/scsi/nsp32.c @@ -2926,7 +2926,7 @@ static void nsp32_do_bus_reset(nsp32_hw_data *data) * reset SCSI bus */ nsp32_write1(base, SCSI_BUS_CONTROL, BUSCTL_RST); - udelay(RESET_HOLD_TIME); + mdelay(RESET_HOLD_TIME / 1000); nsp32_write1(base, SCSI_BUS_CONTROL, 0); for(i = 0; i < 5; i++) { intrdat = nsp32_read2(base, IRQ_STATUS); /* dummy read */ diff --git a/drivers/scsi/osd/osd_uld.c b/drivers/scsi/osd/osd_uld.c index d4ed9eb5265..caac1b28465 100644 --- a/drivers/scsi/osd/osd_uld.c +++ b/drivers/scsi/osd/osd_uld.c @@ -465,7 +465,7 @@ static int osd_probe(struct device *dev) oud->class_dev.class = &osd_uld_class; oud->class_dev.parent = dev; oud->class_dev.release = __remove; - error = dev_set_name(&oud->class_dev, disk->disk_name); + error = dev_set_name(&oud->class_dev, "%s", disk->disk_name); if (error) { OSD_ERR("dev_set_name failed => %d\n", error); goto err_put_cdev; diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index eac95092449..d99d4a0c38a 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -423,6 +423,8 @@ qla2x00_start_scsi(srb_t *sp) __constant_cpu_to_le16(CF_SIMPLE_TAG); break; } + } else { + cmd_pkt->control_flags = __constant_cpu_to_le16(CF_SIMPLE_TAG); } /* Load SCSI command packet. */ @@ -1331,11 +1333,11 @@ qla24xx_build_scsi_crc_2_iocbs(srb_t *sp, struct cmd_type_crc_2 *cmd_pkt, fcp_cmnd->task_attribute = TSK_ORDERED; break; default: - fcp_cmnd->task_attribute = 0; + fcp_cmnd->task_attribute = TSK_SIMPLE; break; } } else { - fcp_cmnd->task_attribute = 0; + fcp_cmnd->task_attribute = TSK_SIMPLE; } cmd_pkt->fcp_rsp_dseg_len = 0; /* Let response come in status iocb */ @@ -1541,7 +1543,12 @@ qla24xx_start_scsi(srb_t *sp) case ORDERED_QUEUE_TAG: cmd_pkt->task = TSK_ORDERED; break; + default: + cmd_pkt->task = TSK_SIMPLE; + break; } + } else { + cmd_pkt->task = TSK_SIMPLE; } /* Load SCSI command packet. */ diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 07322ecff90..29fabffd699 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -1025,6 +1025,9 @@ int scsi_get_vpd_page(struct scsi_device *sdev, u8 page, unsigned char *buf, { int i, result; + if (sdev->skip_vpd_pages) + goto fail; + /* Ask for all the pages supported by this device */ result = scsi_vpd_inquiry(sdev, buf, 0, buf_len); if (result) diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 5b3cadbffcf..105fff2ecd5 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -140,6 +140,7 @@ sd_store_cache_type(struct device *dev, struct device_attribute *attr, char *buffer_data; struct scsi_mode_data data; struct scsi_sense_hdr sshdr; + static const char temp[] = "temporary "; int len; if (sdp->type != TYPE_DISK) @@ -148,6 +149,13 @@ sd_store_cache_type(struct device *dev, struct device_attribute *attr, * it's not worth the risk */ return -EINVAL; + if (strncmp(buf, temp, sizeof(temp) - 1) == 0) { + buf += sizeof(temp) - 1; + sdkp->cache_override = 1; + } else { + sdkp->cache_override = 0; + } + for (i = 0; i < ARRAY_SIZE(sd_cache_types); i++) { len = strlen(sd_cache_types[i]); if (strncmp(sd_cache_types[i], buf, len) == 0 && @@ -160,6 +168,13 @@ sd_store_cache_type(struct device *dev, struct device_attribute *attr, return -EINVAL; rcd = ct & 0x01 ? 1 : 0; wce = ct & 0x02 ? 1 : 0; + + if (sdkp->cache_override) { + sdkp->WCE = wce; + sdkp->RCD = rcd; + return count; + } + if (scsi_mode_sense(sdp, 0x08, 8, buffer, sizeof(buffer), SD_TIMEOUT, SD_MAX_RETRIES, &data, NULL)) return -EINVAL; @@ -657,10 +672,17 @@ static int scsi_setup_flush_cmnd(struct scsi_device *sdp, struct request *rq) static void sd_unprep_fn(struct request_queue *q, struct request *rq) { + struct scsi_cmnd *SCpnt = rq->special; + if (rq->cmd_flags & REQ_DISCARD) { free_page((unsigned long)rq->buffer); rq->buffer = NULL; } + if (SCpnt->cmnd != rq->cmd) { + mempool_free(SCpnt->cmnd, sd_cdb_pool); + SCpnt->cmnd = NULL; + SCpnt->cmd_len = 0; + } } /** @@ -1524,21 +1546,6 @@ static int sd_done(struct scsi_cmnd *SCpnt) if (rq_data_dir(SCpnt->request) == READ && scsi_prot_sg_count(SCpnt)) sd_dif_complete(SCpnt, good_bytes); - if (scsi_host_dif_capable(sdkp->device->host, sdkp->protection_type) - == SD_DIF_TYPE2_PROTECTION && SCpnt->cmnd != SCpnt->request->cmd) { - - /* We have to print a failed command here as the - * extended CDB gets freed before scsi_io_completion() - * is called. - */ - if (result) - scsi_print_command(SCpnt); - - mempool_free(SCpnt->cmnd, sd_cdb_pool); - SCpnt->cmnd = NULL; - SCpnt->cmd_len = 0; - } - return good_bytes; } @@ -2126,6 +2133,10 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer) int old_rcd = sdkp->RCD; int old_dpofua = sdkp->DPOFUA; + + if (sdkp->cache_override) + return; + first_len = 4; if (sdp->skip_ms_page_8) { if (sdp->type == TYPE_RBC) @@ -2607,6 +2618,7 @@ static void sd_probe_async(void *data, async_cookie_t cookie) sdkp->capacity = 0; sdkp->media_present = 1; sdkp->write_prot = 0; + sdkp->cache_override = 0; sdkp->WCE = 0; sdkp->RCD = 0; sdkp->ATO = 0; diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h index f703f4827b6..e2b29568166 100644 --- a/drivers/scsi/sd.h +++ b/drivers/scsi/sd.h @@ -67,6 +67,7 @@ struct scsi_disk { u8 protection_type;/* Data Integrity Field */ u8 provisioning_mode; unsigned ATO : 1; /* state of disk ATO bit */ + unsigned cache_override : 1; /* temp override of WCE,RCD */ unsigned WCE : 1; /* state of disk WCE bit */ unsigned RCD : 1; /* state of disk RCD bit, unused */ unsigned DPOFUA : 1; /* state of disk DPOFUA bit */ diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 40a45700c8d..f9986ccbd80 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -467,6 +467,7 @@ static struct scatterlist *create_bounce_buffer(struct scatterlist *sgl, if (!bounce_sgl) return NULL; + sg_init_table(bounce_sgl, num_pages); for (i = 0; i < num_pages; i++) { page_buf = alloc_page(GFP_ATOMIC); if (!page_buf) diff --git a/drivers/spi/spi-mpc512x-psc.c b/drivers/spi/spi-mpc512x-psc.c index 4c63f772780..2e2b04fc065 100644 --- a/drivers/spi/spi-mpc512x-psc.c +++ b/drivers/spi/spi-mpc512x-psc.c @@ -164,7 +164,7 @@ static int mpc512x_psc_spi_transfer_rxtx(struct spi_device *spi, for (i = count; i > 0; i--) { data = tx_buf ? *tx_buf++ : 0; - if (len == EOFBYTE) + if (len == EOFBYTE && t->cs_change) setbits32(&fifo->txcmd, MPC512x_PSC_FIFO_EOF); out_8(&fifo->txdata_8, data); len--; diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 972a94c58be..486e8648402 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -889,25 +889,30 @@ static irqreturn_t s3c64xx_spi_irq(int irq, void *data) { struct s3c64xx_spi_driver_data *sdd = data; struct spi_master *spi = sdd->master; - unsigned int val; + unsigned int val, clr = 0; - val = readl(sdd->regs + S3C64XX_SPI_PENDING_CLR); + val = readl(sdd->regs + S3C64XX_SPI_STATUS); - val &= S3C64XX_SPI_PND_RX_OVERRUN_CLR | - S3C64XX_SPI_PND_RX_UNDERRUN_CLR | - S3C64XX_SPI_PND_TX_OVERRUN_CLR | - S3C64XX_SPI_PND_TX_UNDERRUN_CLR; - - writel(val, sdd->regs + S3C64XX_SPI_PENDING_CLR); - - if (val & S3C64XX_SPI_PND_RX_OVERRUN_CLR) + if (val & S3C64XX_SPI_ST_RX_OVERRUN_ERR) { + clr = S3C64XX_SPI_PND_RX_OVERRUN_CLR; dev_err(&spi->dev, "RX overrun\n"); - if (val & S3C64XX_SPI_PND_RX_UNDERRUN_CLR) + } + if (val & S3C64XX_SPI_ST_RX_UNDERRUN_ERR) { + clr |= S3C64XX_SPI_PND_RX_UNDERRUN_CLR; dev_err(&spi->dev, "RX underrun\n"); - if (val & S3C64XX_SPI_PND_TX_OVERRUN_CLR) + } + if (val & S3C64XX_SPI_ST_TX_OVERRUN_ERR) { + clr |= S3C64XX_SPI_PND_TX_OVERRUN_CLR; dev_err(&spi->dev, "TX overrun\n"); - if (val & S3C64XX_SPI_PND_TX_UNDERRUN_CLR) + } + if (val & S3C64XX_SPI_ST_TX_UNDERRUN_ERR) { + clr |= S3C64XX_SPI_PND_TX_UNDERRUN_CLR; dev_err(&spi->dev, "TX underrun\n"); + } + + /* Clear the pending irq by setting and then clearing it */ + writel(clr, sdd->regs + S3C64XX_SPI_PENDING_CLR); + writel(0, sdd->regs + S3C64XX_SPI_PENDING_CLR); return IRQ_HANDLED; } @@ -931,9 +936,13 @@ static void s3c64xx_spi_hwinit(struct s3c64xx_spi_driver_data *sdd, int channel) writel(0, regs + S3C64XX_SPI_MODE_CFG); writel(0, regs + S3C64XX_SPI_PACKET_CNT); - /* Clear any irq pending bits */ - writel(readl(regs + S3C64XX_SPI_PENDING_CLR), - regs + S3C64XX_SPI_PENDING_CLR); + /* Clear any irq pending bits, should set and clear the bits */ + val = S3C64XX_SPI_PND_RX_OVERRUN_CLR | + S3C64XX_SPI_PND_RX_UNDERRUN_CLR | + S3C64XX_SPI_PND_TX_OVERRUN_CLR | + S3C64XX_SPI_PND_TX_UNDERRUN_CLR; + writel(val, regs + S3C64XX_SPI_PENDING_CLR); + writel(0, regs + S3C64XX_SPI_PENDING_CLR); writel(0, regs + S3C64XX_SPI_SWAP_CFG); diff --git a/drivers/ssb/driver_chipcommon_pmu.c b/drivers/ssb/driver_chipcommon_pmu.c index b58fef780ea..1fb9b223116 100644 --- a/drivers/ssb/driver_chipcommon_pmu.c +++ b/drivers/ssb/driver_chipcommon_pmu.c @@ -645,3 +645,32 @@ u32 ssb_pmu_get_controlclock(struct ssb_chipcommon *cc) return 0; } } + +void ssb_pmu_spuravoid_pllupdate(struct ssb_chipcommon *cc, int spuravoid) +{ + u32 pmu_ctl = 0; + + switch (cc->dev->bus->chip_id) { + case 0x4322: + ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL0, 0x11100070); + ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL1, 0x1014140a); + ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL5, 0x88888854); + if (spuravoid == 1) + ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL2, 0x05201828); + else + ssb_chipco_pll_write(cc, SSB_PMU1_PLLCTL2, 0x05001828); + pmu_ctl = SSB_CHIPCO_PMU_CTL_PLL_UPD; + break; + case 43222: + /* TODO: BCM43222 requires updating PLLs too */ + return; + default: + ssb_printk(KERN_ERR PFX + "Unknown spuravoidance settings for chip 0x%04X, not changing PLL\n", + cc->dev->bus->chip_id); + return; + } + + chipco_set32(cc, SSB_CHIPCO_PMU_CTL, pmu_ctl); +} +EXPORT_SYMBOL_GPL(ssb_pmu_spuravoid_pllupdate); diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index b67c1070df7..50dc93e2a22 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c @@ -136,6 +136,11 @@ static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd, /* Device config is special, because it must work on * an unconfigured device. */ if (cmd == COMEDI_DEVCONFIG) { + if (minor >= COMEDI_NUM_BOARD_MINORS) { + /* Device config not appropriate on non-board minors. */ + rc = -ENOTTY; + goto done; + } rc = do_devconfig_ioctl(dev, (struct comedi_devconfig __user *)arg); if (rc == 0) @@ -1365,6 +1370,7 @@ static int do_cancel_ioctl(struct comedi_device *dev, unsigned int arg, void *file) { struct comedi_subdevice *s; + int ret; if (arg >= dev->n_subdevices) return -EINVAL; @@ -1381,7 +1387,11 @@ static int do_cancel_ioctl(struct comedi_device *dev, unsigned int arg, if (s->busy != file) return -EBUSY; - return do_cancel(dev, s); + ret = do_cancel(dev, s); + if (comedi_get_subdevice_runflags(s) & SRF_USER) + wake_up_interruptible(&s->async->wait_head); + + return ret; } /* @@ -1572,7 +1582,7 @@ static unsigned int comedi_poll(struct file *file, poll_table * wait) mask = 0; read_subdev = comedi_get_read_subdevice(dev_file_info); - if (read_subdev) { + if (read_subdev && read_subdev->async) { poll_wait(file, &read_subdev->async->wait_head, wait); if (!read_subdev->busy || comedi_buf_read_n_available(read_subdev->async) > 0 @@ -1582,7 +1592,7 @@ static unsigned int comedi_poll(struct file *file, poll_table * wait) } } write_subdev = comedi_get_write_subdevice(dev_file_info); - if (write_subdev) { + if (write_subdev && write_subdev->async) { poll_wait(file, &write_subdev->async->wait_head, wait); comedi_buf_write_alloc(write_subdev->async, write_subdev->async->prealloc_bufsz); @@ -1624,7 +1634,7 @@ static ssize_t comedi_write(struct file *file, const char __user *buf, } s = comedi_get_write_subdevice(dev_file_info); - if (s == NULL) { + if (s == NULL || s->async == NULL) { retval = -EIO; goto done; } @@ -1735,7 +1745,7 @@ static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes, } s = comedi_get_read_subdevice(dev_file_info); - if (s == NULL) { + if (s == NULL || s->async == NULL) { retval = -EIO; goto done; } diff --git a/drivers/staging/comedi/drivers/ni_labpc.c b/drivers/staging/comedi/drivers/ni_labpc.c index 721b2be2250..0517a2315ef 100644 --- a/drivers/staging/comedi/drivers/ni_labpc.c +++ b/drivers/staging/comedi/drivers/ni_labpc.c @@ -1264,7 +1264,9 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) else channel = CR_CHAN(cmd->chanlist[0]); /* munge channel bits for differential / scan disabled mode */ - if (labpc_ai_scan_mode(cmd) != MODE_SINGLE_CHAN && aref == AREF_DIFF) + if ((labpc_ai_scan_mode(cmd) == MODE_SINGLE_CHAN || + labpc_ai_scan_mode(cmd) == MODE_SINGLE_CHAN_INTERVAL) && + aref == AREF_DIFF) channel *= 2; devpriv->command1_bits |= ADC_CHAN_BITS(channel); devpriv->command1_bits |= thisboard->ai_range_code[range]; @@ -1280,21 +1282,6 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->write_byte(devpriv->command1_bits, dev->iobase + COMMAND1_REG); } - /* setup any external triggering/pacing (command4 register) */ - devpriv->command4_bits = 0; - if (cmd->convert_src != TRIG_EXT) - devpriv->command4_bits |= EXT_CONVERT_DISABLE_BIT; - /* XXX should discard first scan when using interval scanning - * since manual says it is not synced with scan clock */ - if (labpc_use_continuous_mode(cmd) == 0) { - devpriv->command4_bits |= INTERVAL_SCAN_EN_BIT; - if (cmd->scan_begin_src == TRIG_EXT) - devpriv->command4_bits |= EXT_SCAN_EN_BIT; - } - /* single-ended/differential */ - if (aref == AREF_DIFF) - devpriv->command4_bits |= ADC_DIFF_BIT; - devpriv->write_byte(devpriv->command4_bits, dev->iobase + COMMAND4_REG); devpriv->write_byte(cmd->chanlist_len, dev->iobase + INTERVAL_COUNT_REG); @@ -1374,6 +1361,22 @@ static int labpc_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) devpriv->command3_bits &= ~ADC_FNE_INTR_EN_BIT; devpriv->write_byte(devpriv->command3_bits, dev->iobase + COMMAND3_REG); + /* setup any external triggering/pacing (command4 register) */ + devpriv->command4_bits = 0; + if (cmd->convert_src != TRIG_EXT) + devpriv->command4_bits |= EXT_CONVERT_DISABLE_BIT; + /* XXX should discard first scan when using interval scanning + * since manual says it is not synced with scan clock */ + if (labpc_use_continuous_mode(cmd) == 0) { + devpriv->command4_bits |= INTERVAL_SCAN_EN_BIT; + if (cmd->scan_begin_src == TRIG_EXT) + devpriv->command4_bits |= EXT_SCAN_EN_BIT; + } + /* single-ended/differential */ + if (aref == AREF_DIFF) + devpriv->command4_bits |= ADC_DIFF_BIT; + devpriv->write_byte(devpriv->command4_bits, dev->iobase + COMMAND4_REG); + /* startup acquisition */ /* command2 reg */ diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c index c72128f30f1..42cad5c0729 100644 --- a/drivers/staging/comedi/drivers/s626.c +++ b/drivers/staging/comedi/drivers/s626.c @@ -1882,7 +1882,7 @@ static int s626_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) case TRIG_NONE: /* continous acquisition */ devpriv->ai_continous = 1; - devpriv->ai_sample_count = 0; + devpriv->ai_sample_count = 1; break; } diff --git a/drivers/staging/vt6656/hostap.c b/drivers/staging/vt6656/hostap.c index 51b5adf3657..df8ea25c5c6 100644 --- a/drivers/staging/vt6656/hostap.c +++ b/drivers/staging/vt6656/hostap.c @@ -153,7 +153,7 @@ static int hostap_disable_hostapd(PSDevice pDevice, int rtnl_locked) DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "%s: Netdevice %s unregistered\n", pDevice->dev->name, pDevice->apdev->name); } - kfree(pDevice->apdev); + free_netdev(pDevice->apdev); pDevice->apdev = NULL; pDevice->bEnable8021x = FALSE; pDevice->bEnableHostWEP = FALSE; diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c index 87394541d71..628545d261d 100644 --- a/drivers/staging/vt6656/main_usb.c +++ b/drivers/staging/vt6656/main_usb.c @@ -718,8 +718,6 @@ static int vt6656_suspend(struct usb_interface *intf, pm_message_t message) if (device->flags & DEVICE_FLAGS_OPENED) device_close(device->dev); - usb_put_dev(interface_to_usbdev(intf)); - return 0; } @@ -730,8 +728,6 @@ static int vt6656_resume(struct usb_interface *intf) if (!device || !device->dev) return -ENODEV; - usb_get_dev(interface_to_usbdev(intf)); - if (!(device->flags & DEVICE_FLAGS_OPENED)) device_open(device->dev); diff --git a/drivers/staging/vt6656/usbpipe.c b/drivers/staging/vt6656/usbpipe.c index c612ab58f38..f759352a268 100644 --- a/drivers/staging/vt6656/usbpipe.c +++ b/drivers/staging/vt6656/usbpipe.c @@ -168,6 +168,11 @@ int PIPEnsControlOut( if (pDevice->Flags & fMP_CONTROL_WRITES) return STATUS_FAILURE; + if (pDevice->Flags & fMP_CONTROL_READS) + return STATUS_FAILURE; + + MP_SET_FLAG(pDevice, fMP_CONTROL_WRITES); + pDevice->sUsbCtlRequest.bRequestType = 0x40; pDevice->sUsbCtlRequest.bRequest = byRequest; pDevice->sUsbCtlRequest.wValue = cpu_to_le16p(&wValue); @@ -182,12 +187,13 @@ int PIPEnsControlOut( ntStatus = usb_submit_urb(pDevice->pControlURB, GFP_ATOMIC); if (ntStatus != 0) { - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"control send request submission failed: %d\n", ntStatus); + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO + "control send request submission failed: %d\n", + ntStatus); + MP_CLEAR_FLAG(pDevice, fMP_CONTROL_WRITES); return STATUS_FAILURE; } - else { - MP_SET_FLAG(pDevice, fMP_CONTROL_WRITES); - } + spin_unlock_irq(&pDevice->lock); for (ii = 0; ii <= USB_CTL_WAIT; ii ++) { @@ -227,6 +233,11 @@ int PIPEnsControlIn( if (pDevice->Flags & fMP_CONTROL_READS) return STATUS_FAILURE; + if (pDevice->Flags & fMP_CONTROL_WRITES) + return STATUS_FAILURE; + + MP_SET_FLAG(pDevice, fMP_CONTROL_READS); + pDevice->sUsbCtlRequest.bRequestType = 0xC0; pDevice->sUsbCtlRequest.bRequest = byRequest; pDevice->sUsbCtlRequest.wValue = cpu_to_le16p(&wValue); @@ -240,10 +251,11 @@ int PIPEnsControlIn( ntStatus = usb_submit_urb(pDevice->pControlURB, GFP_ATOMIC); if (ntStatus != 0) { - DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"control request submission failed: %d\n", ntStatus); - }else { - MP_SET_FLAG(pDevice, fMP_CONTROL_READS); - } + DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO + "control request submission failed: %d\n", ntStatus); + MP_CLEAR_FLAG(pDevice, fMP_CONTROL_READS); + return STATUS_FAILURE; + } spin_unlock_irq(&pDevice->lock); for (ii = 0; ii <= USB_CTL_WAIT; ii ++) { diff --git a/drivers/target/iscsi/iscsi_target_auth.c b/drivers/target/iscsi/iscsi_target_auth.c index db0cf7c8add..a0fc7b9eea6 100644 --- a/drivers/target/iscsi/iscsi_target_auth.c +++ b/drivers/target/iscsi/iscsi_target_auth.c @@ -166,6 +166,7 @@ static int chap_server_compute_md5( { char *endptr; unsigned long id; + unsigned char id_as_uchar; unsigned char digest[MD5_SIGNATURE_SIZE]; unsigned char type, response[MD5_SIGNATURE_SIZE * 2 + 2]; unsigned char identifier[10], *challenge = NULL; @@ -355,7 +356,9 @@ static int chap_server_compute_md5( goto out; } - sg_init_one(&sg, &id, 1); + /* To handle both endiannesses */ + id_as_uchar = id; + sg_init_one(&sg, &id_as_uchar, 1); ret = crypto_hash_update(&desc, &sg, 1); if (ret < 0) { pr_err("crypto_hash_update() failed for id\n"); diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c index 00c58cc82c8..facb3ad3d26 100644 --- a/drivers/target/iscsi/iscsi_target_configfs.c +++ b/drivers/target/iscsi/iscsi_target_configfs.c @@ -415,7 +415,7 @@ static ssize_t __iscsi_##prefix##_store_##name( \ if (!capable(CAP_SYS_ADMIN)) \ return -EPERM; \ \ - snprintf(auth->name, PAGE_SIZE, "%s", page); \ + snprintf(auth->name, sizeof(auth->name), "%s", page); \ if (!strncmp("NULL", auth->name, 4)) \ auth->naf_flags &= ~flags; \ else \ diff --git a/drivers/target/iscsi/iscsi_target_erl0.c b/drivers/target/iscsi/iscsi_target_erl0.c index 1ab0560b092..a7c4324697a 100644 --- a/drivers/target/iscsi/iscsi_target_erl0.c +++ b/drivers/target/iscsi/iscsi_target_erl0.c @@ -831,11 +831,11 @@ extern int iscsit_stop_time2retain_timer(struct iscsi_session *sess) return 0; sess->time2retain_timer_flags |= ISCSI_TF_STOP; - spin_unlock_bh(&se_tpg->session_lock); + spin_unlock(&se_tpg->session_lock); del_timer_sync(&sess->time2retain_timer); - spin_lock_bh(&se_tpg->session_lock); + spin_lock(&se_tpg->session_lock); sess->time2retain_timer_flags &= ~ISCSI_TF_RUNNING; pr_debug("Stopped Time2Retain Timer for SID: %u\n", sess->sid); diff --git a/drivers/target/iscsi/iscsi_target_erl1.c b/drivers/target/iscsi/iscsi_target_erl1.c index 006f605edb0..fd669b5a045 100644 --- a/drivers/target/iscsi/iscsi_target_erl1.c +++ b/drivers/target/iscsi/iscsi_target_erl1.c @@ -824,7 +824,7 @@ static int iscsit_attach_ooo_cmdsn( /* * CmdSN is greater than the tail of the list. */ - if (ooo_tail->cmdsn < ooo_cmdsn->cmdsn) + if (iscsi_sna_lt(ooo_tail->cmdsn, ooo_cmdsn->cmdsn)) list_add_tail(&ooo_cmdsn->ooo_list, &sess->sess_ooo_cmdsn_list); else { @@ -834,11 +834,12 @@ static int iscsit_attach_ooo_cmdsn( */ list_for_each_entry(ooo_tmp, &sess->sess_ooo_cmdsn_list, ooo_list) { - if (ooo_tmp->cmdsn < ooo_cmdsn->cmdsn) + if (iscsi_sna_lt(ooo_tmp->cmdsn, ooo_cmdsn->cmdsn)) continue; + /* Insert before this entry */ list_add(&ooo_cmdsn->ooo_list, - &ooo_tmp->ooo_list); + ooo_tmp->ooo_list.prev); break; } } diff --git a/drivers/target/iscsi/iscsi_target_parameters.c b/drivers/target/iscsi/iscsi_target_parameters.c index eb05c9d751e..8a8ff238c23 100644 --- a/drivers/target/iscsi/iscsi_target_parameters.c +++ b/drivers/target/iscsi/iscsi_target_parameters.c @@ -713,9 +713,9 @@ static int iscsi_add_notunderstood_response( } INIT_LIST_HEAD(&extra_response->er_list); - strncpy(extra_response->key, key, strlen(key) + 1); - strncpy(extra_response->value, NOTUNDERSTOOD, - strlen(NOTUNDERSTOOD) + 1); + strlcpy(extra_response->key, key, sizeof(extra_response->key)); + strlcpy(extra_response->value, NOTUNDERSTOOD, + sizeof(extra_response->value)); list_add_tail(&extra_response->er_list, ¶m_list->extra_response_list); @@ -1571,8 +1571,6 @@ int iscsi_decode_text_input( if (phase & PHASE_SECURITY) { if (iscsi_check_for_auth_key(key) > 0) { - char *tmpptr = key + strlen(key); - *tmpptr = '='; kfree(tmpbuf); return 1; } diff --git a/drivers/target/iscsi/iscsi_target_parameters.h b/drivers/target/iscsi/iscsi_target_parameters.h index 6a37fd6f128..83eed654002 100644 --- a/drivers/target/iscsi/iscsi_target_parameters.h +++ b/drivers/target/iscsi/iscsi_target_parameters.h @@ -1,8 +1,10 @@ #ifndef ISCSI_PARAMETERS_H #define ISCSI_PARAMETERS_H +#include + struct iscsi_extra_response { - char key[64]; + char key[KEY_MAXLEN]; char value[32]; struct list_head er_list; } ____cacheline_aligned; diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c index f30e124874b..aa3c1062157 100644 --- a/drivers/target/target_core_alua.c +++ b/drivers/target/target_core_alua.c @@ -392,6 +392,7 @@ static inline int core_alua_state_standby( case REPORT_LUNS: case RECEIVE_DIAGNOSTIC: case SEND_DIAGNOSTIC: + return 0; case MAINTENANCE_IN: switch (cdb[1]) { case MI_REPORT_TARGET_PGS: @@ -434,6 +435,7 @@ static inline int core_alua_state_unavailable( switch (cdb[0]) { case INQUIRY: case REPORT_LUNS: + return 0; case MAINTENANCE_IN: switch (cdb[1]) { case MI_REPORT_TARGET_PGS: @@ -474,6 +476,7 @@ static inline int core_alua_state_transition( switch (cdb[0]) { case INQUIRY: case REPORT_LUNS: + return 0; case MAINTENANCE_IN: switch (cdb[1]) { case MI_REPORT_TARGET_PGS: diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index 26c62f05975..79d9865a127 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -1230,6 +1230,8 @@ int se_dev_set_max_sectors(struct se_device *dev, u32 max_sectors) int se_dev_set_fabric_max_sectors(struct se_device *dev, u32 fabric_max_sectors) { + int block_size = dev->se_sub_dev->se_dev_attrib.block_size; + if (atomic_read(&dev->dev_export_obj.obj_access_count)) { pr_err("dev[%p]: Unable to change SE Device" " fabric_max_sectors while dev_export_obj: %d count exists\n", @@ -1267,8 +1269,12 @@ int se_dev_set_fabric_max_sectors(struct se_device *dev, u32 fabric_max_sectors) /* * Align max_sectors down to PAGE_SIZE to follow transport_allocate_data_tasks() */ + if (!block_size) { + block_size = 512; + pr_warn("Defaulting to 512 for zero block_size\n"); + } fabric_max_sectors = se_dev_align_max_sectors(fabric_max_sectors, - dev->se_sub_dev->se_dev_attrib.block_size); + block_size); dev->se_sub_dev->se_dev_attrib.fabric_max_sectors = fabric_max_sectors; pr_debug("dev[%p]: SE Device max_sectors changed to %u\n", @@ -1477,24 +1483,18 @@ static struct se_lun *core_dev_get_lun(struct se_portal_group *tpg, u32 unpacked struct se_lun_acl *core_dev_init_initiator_node_lun_acl( struct se_portal_group *tpg, + struct se_node_acl *nacl, u32 mapped_lun, - char *initiatorname, int *ret) { struct se_lun_acl *lacl; - struct se_node_acl *nacl; - if (strlen(initiatorname) >= TRANSPORT_IQN_LEN) { + if (strlen(nacl->initiatorname) >= TRANSPORT_IQN_LEN) { pr_err("%s InitiatorName exceeds maximum size.\n", tpg->se_tpg_tfo->get_fabric_name()); *ret = -EOVERFLOW; return NULL; } - nacl = core_tpg_get_initiator_node_acl(tpg, initiatorname); - if (!nacl) { - *ret = -EINVAL; - return NULL; - } lacl = kzalloc(sizeof(struct se_lun_acl), GFP_KERNEL); if (!lacl) { pr_err("Unable to allocate memory for struct se_lun_acl.\n"); @@ -1505,7 +1505,8 @@ struct se_lun_acl *core_dev_init_initiator_node_lun_acl( INIT_LIST_HEAD(&lacl->lacl_list); lacl->mapped_lun = mapped_lun; lacl->se_lun_nacl = nacl; - snprintf(lacl->initiatorname, TRANSPORT_IQN_LEN, "%s", initiatorname); + snprintf(lacl->initiatorname, TRANSPORT_IQN_LEN, "%s", + nacl->initiatorname); return lacl; } diff --git a/drivers/target/target_core_fabric_configfs.c b/drivers/target/target_core_fabric_configfs.c index 817ba7c849e..6b79ee71152 100644 --- a/drivers/target/target_core_fabric_configfs.c +++ b/drivers/target/target_core_fabric_configfs.c @@ -356,9 +356,17 @@ static struct config_group *target_fabric_make_mappedlun( ret = -EINVAL; goto out; } + if (mapped_lun > (TRANSPORT_MAX_LUNS_PER_TPG-1)) { + pr_err("Mapped LUN: %lu exceeds TRANSPORT_MAX_LUNS_PER_TPG" + "-1: %u for Target Portal Group: %u\n", mapped_lun, + TRANSPORT_MAX_LUNS_PER_TPG-1, + se_tpg->se_tpg_tfo->tpg_get_tag(se_tpg)); + ret = -EINVAL; + goto out; + } - lacl = core_dev_init_initiator_node_lun_acl(se_tpg, mapped_lun, - config_item_name(acl_ci), &ret); + lacl = core_dev_init_initiator_node_lun_acl(se_tpg, se_nacl, + mapped_lun, &ret); if (!lacl) { ret = -EINVAL; goto out; diff --git a/drivers/target/target_core_internal.h b/drivers/target/target_core_internal.h index 21c05638f15..17179b1af54 100644 --- a/drivers/target/target_core_internal.h +++ b/drivers/target/target_core_internal.h @@ -61,7 +61,7 @@ struct se_lun *core_dev_add_lun(struct se_portal_group *, struct se_hba *, int core_dev_del_lun(struct se_portal_group *, u32); struct se_lun *core_get_lun_from_tpg(struct se_portal_group *, u32); struct se_lun_acl *core_dev_init_initiator_node_lun_acl(struct se_portal_group *, - u32, char *, int *); + struct se_node_acl *, u32, int *); int core_dev_add_initiator_node_lun_acl(struct se_portal_group *, struct se_lun_acl *, u32, u32); int core_dev_del_initiator_node_lun_acl(struct se_portal_group *, diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c index 94c905fcbce..d084ba328af 100644 --- a/drivers/target/target_core_pscsi.c +++ b/drivers/target/target_core_pscsi.c @@ -1042,7 +1042,6 @@ static int pscsi_map_sg(struct se_task *task, struct scatterlist *task_sg, bio = NULL; } - page++; len -= bytes; data_len -= bytes; off = 0; diff --git a/drivers/target/target_core_tpg.c b/drivers/target/target_core_tpg.c index ba537b6fd85..0e17fa3da01 100644 --- a/drivers/target/target_core_tpg.c +++ b/drivers/target/target_core_tpg.c @@ -114,16 +114,10 @@ struct se_node_acl *core_tpg_get_initiator_node_acl( struct se_node_acl *acl; spin_lock_irq(&tpg->acl_node_lock); - list_for_each_entry(acl, &tpg->acl_node_list, acl_list) { - if (!strcmp(acl->initiatorname, initiatorname) && - !acl->dynamic_node_acl) { - spin_unlock_irq(&tpg->acl_node_lock); - return acl; - } - } + acl = __core_tpg_get_initiator_node_acl(tpg, initiatorname); spin_unlock_irq(&tpg->acl_node_lock); - return NULL; + return acl; } /* core_tpg_add_node_to_devs(): diff --git a/drivers/thermal/thermal_sys.c b/drivers/thermal/thermal_sys.c index fd1a2fc664a..0c0a3faf716 100644 --- a/drivers/thermal/thermal_sys.c +++ b/drivers/thermal/thermal_sys.c @@ -1488,6 +1488,7 @@ static int __init thermal_init(void) idr_destroy(&thermal_cdev_idr); mutex_destroy(&thermal_idr_lock); mutex_destroy(&thermal_list_lock); + return result; } result = genetlink_init(); return result; diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c index 90dff8233ef..4a418e44d56 100644 --- a/drivers/tty/n_gsm.c +++ b/drivers/tty/n_gsm.c @@ -1692,6 +1692,8 @@ static inline void dlci_put(struct gsm_dlci *dlci) kref_put(&dlci->ref, gsm_dlci_free); } +static void gsm_destroy_network(struct gsm_dlci *dlci); + /** * gsm_dlci_release - release DLCI * @dlci: DLCI to destroy @@ -1705,9 +1707,19 @@ static void gsm_dlci_release(struct gsm_dlci *dlci) { struct tty_struct *tty = tty_port_tty_get(&dlci->port); if (tty) { + mutex_lock(&dlci->mutex); + gsm_destroy_network(dlci); + mutex_unlock(&dlci->mutex); + + /* tty_vhangup needs the tty_lock, so unlock and + relock after doing the hangup. */ + tty_unlock(); tty_vhangup(tty); + tty_lock(); + tty_port_tty_set(&dlci->port, NULL); tty_kref_put(tty); } + dlci->state = DLCI_CLOSED; dlci_put(dlci); } @@ -2933,6 +2945,8 @@ static void gsmtty_close(struct tty_struct *tty, struct file *filp) if (dlci == NULL) return; + if (dlci->state == DLCI_CLOSED) + return; mutex_lock(&dlci->mutex); gsm_destroy_network(dlci); mutex_unlock(&dlci->mutex); @@ -2951,6 +2965,8 @@ static void gsmtty_close(struct tty_struct *tty, struct file *filp) static void gsmtty_hangup(struct tty_struct *tty) { struct gsm_dlci *dlci = tty->driver_data; + if (dlci->state == DLCI_CLOSED) + return; tty_port_hangup(&dlci->port); gsm_dlci_begin_close(dlci); } @@ -2958,9 +2974,12 @@ static void gsmtty_hangup(struct tty_struct *tty) static int gsmtty_write(struct tty_struct *tty, const unsigned char *buf, int len) { + int sent; struct gsm_dlci *dlci = tty->driver_data; + if (dlci->state == DLCI_CLOSED) + return -EINVAL; /* Stuff the bytes into the fifo queue */ - int sent = kfifo_in_locked(dlci->fifo, buf, len, &dlci->lock); + sent = kfifo_in_locked(dlci->fifo, buf, len, &dlci->lock); /* Need to kick the channel */ gsm_dlci_data_kick(dlci); return sent; @@ -2969,18 +2988,24 @@ static int gsmtty_write(struct tty_struct *tty, const unsigned char *buf, static int gsmtty_write_room(struct tty_struct *tty) { struct gsm_dlci *dlci = tty->driver_data; + if (dlci->state == DLCI_CLOSED) + return -EINVAL; return TX_SIZE - kfifo_len(dlci->fifo); } static int gsmtty_chars_in_buffer(struct tty_struct *tty) { struct gsm_dlci *dlci = tty->driver_data; + if (dlci->state == DLCI_CLOSED) + return -EINVAL; return kfifo_len(dlci->fifo); } static void gsmtty_flush_buffer(struct tty_struct *tty) { struct gsm_dlci *dlci = tty->driver_data; + if (dlci->state == DLCI_CLOSED) + return; /* Caution needed: If we implement reliable transport classes then the data being transmitted can't simply be junked once it has first hit the stack. Until then we can just blow it @@ -2999,6 +3024,8 @@ static void gsmtty_wait_until_sent(struct tty_struct *tty, int timeout) static int gsmtty_tiocmget(struct tty_struct *tty) { struct gsm_dlci *dlci = tty->driver_data; + if (dlci->state == DLCI_CLOSED) + return -EINVAL; return dlci->modem_rx; } @@ -3008,6 +3035,8 @@ static int gsmtty_tiocmset(struct tty_struct *tty, struct gsm_dlci *dlci = tty->driver_data; unsigned int modem_tx = dlci->modem_tx; + if (dlci->state == DLCI_CLOSED) + return -EINVAL; modem_tx &= ~clear; modem_tx |= set; @@ -3026,6 +3055,8 @@ static int gsmtty_ioctl(struct tty_struct *tty, struct gsm_netconfig nc; int index; + if (dlci->state == DLCI_CLOSED) + return -EINVAL; switch (cmd) { case GSMIOC_ENABLE_NET: if (copy_from_user(&nc, (void __user *)arg, sizeof(nc))) @@ -3052,6 +3083,9 @@ static int gsmtty_ioctl(struct tty_struct *tty, static void gsmtty_set_termios(struct tty_struct *tty, struct ktermios *old) { + struct gsm_dlci *dlci = tty->driver_data; + if (dlci->state == DLCI_CLOSED) + return; /* For the moment its fixed. In actual fact the speed information for the virtual channel can be propogated in both directions by the RPN control message. This however rapidly gets nasty as we @@ -3063,6 +3097,8 @@ static void gsmtty_set_termios(struct tty_struct *tty, struct ktermios *old) static void gsmtty_throttle(struct tty_struct *tty) { struct gsm_dlci *dlci = tty->driver_data; + if (dlci->state == DLCI_CLOSED) + return; if (tty->termios->c_cflag & CRTSCTS) dlci->modem_tx &= ~TIOCM_DTR; dlci->throttled = 1; @@ -3073,6 +3109,8 @@ static void gsmtty_throttle(struct tty_struct *tty) static void gsmtty_unthrottle(struct tty_struct *tty) { struct gsm_dlci *dlci = tty->driver_data; + if (dlci->state == DLCI_CLOSED) + return; if (tty->termios->c_cflag & CRTSCTS) dlci->modem_tx |= TIOCM_DTR; dlci->throttled = 0; @@ -3084,6 +3122,8 @@ static int gsmtty_break_ctl(struct tty_struct *tty, int state) { struct gsm_dlci *dlci = tty->driver_data; int encode = 0; /* Off */ + if (dlci->state == DLCI_CLOSED) + return -EINVAL; if (state == -1) /* "On indefinitely" - we can't encode this properly */ diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 2303a02e9dc..37818fbfbb0 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -1529,6 +1529,14 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old) tty->real_raw = 0; } n_tty_set_room(tty); + /* + * Fix tty hang when I_IXON(tty) is cleared, but the tty + * been stopped by STOP_CHAR(tty) before it. + */ + if (!I_IXON(tty) && old && (old->c_iflag & IXON) && !tty->flow_stopped) { + start_tty(tty); + } + /* The termios change make the tty ready for I/O */ wake_up_interruptible(&tty->write_wait); wake_up_interruptible(&tty->read_wait); diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c index eeae7fafe9a..cf9a1911d4a 100644 --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c @@ -47,7 +47,6 @@ static void pty_close(struct tty_struct *tty, struct file *filp) tty->packet = 0; if (!tty->link) return; - tty->link->packet = 0; set_bit(TTY_OTHER_CLOSED, &tty->link->flags); wake_up_interruptible(&tty->link->read_wait); wake_up_interruptible(&tty->link->write_wait); @@ -608,6 +607,9 @@ static int ptmx_open(struct inode *inode, struct file *filp) nonseekable_open(inode, filp); + /* We refuse fsnotify events on ptmx, since it's a shared resource */ + filp->f_mode |= FMODE_NONOTIFY; + retval = tty_alloc_file(filp); if (retval) return retval; diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 5c8645a84ef..680a8c0fce8 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -197,7 +197,7 @@ config SERIAL_SAMSUNG_UARTS_4 config SERIAL_SAMSUNG_UARTS int depends on ARM && PLAT_SAMSUNG - default 6 if ARCH_S5P6450 + default 6 if CPU_S5P6450 default 4 if SERIAL_SAMSUNG_UARTS_4 || CPU_S3C2416 default 3 help diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index 3d7e1ee2fa5..ed7cd378b83 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c @@ -159,7 +159,7 @@ struct atmel_uart_port { }; static struct atmel_uart_port atmel_ports[ATMEL_MAX_UART]; -static unsigned long atmel_ports_in_use; +static DECLARE_BITMAP(atmel_ports_in_use, ATMEL_MAX_UART); #ifdef SUPPORT_SYSRQ static struct console atmel_console; @@ -1785,15 +1785,14 @@ static int __devinit atmel_serial_probe(struct platform_device *pdev) if (ret < 0) /* port id not found in platform data nor device-tree aliases: * auto-enumerate it */ - ret = find_first_zero_bit(&atmel_ports_in_use, - sizeof(atmel_ports_in_use)); + ret = find_first_zero_bit(atmel_ports_in_use, ATMEL_MAX_UART); - if (ret > ATMEL_MAX_UART) { + if (ret >= ATMEL_MAX_UART) { ret = -ENODEV; goto err; } - if (test_and_set_bit(ret, &atmel_ports_in_use)) { + if (test_and_set_bit(ret, atmel_ports_in_use)) { /* port already in use */ ret = -EBUSY; goto err; @@ -1867,7 +1866,7 @@ static int __devexit atmel_serial_remove(struct platform_device *pdev) /* "port" is allocated statically, so we shouldn't free it */ - clear_bit(port->line, &atmel_ports_in_use); + clear_bit(port->line, atmel_ports_in_use); clk_put(atmel_port->clk); diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c index 039c054349e..c75b27bcd21 100644 --- a/drivers/tty/serial/mxs-auart.c +++ b/drivers/tty/serial/mxs-auart.c @@ -375,11 +375,18 @@ static void mxs_auart_settermios(struct uart_port *u, static irqreturn_t mxs_auart_irq_handle(int irq, void *context) { - u32 istatus, istat; + u32 istat; struct mxs_auart_port *s = context; u32 stat = readl(s->port.membase + AUART_STAT); - istatus = istat = readl(s->port.membase + AUART_INTR); + istat = readl(s->port.membase + AUART_INTR); + + /* ack irq */ + writel(istat & (AUART_INTR_RTIS + | AUART_INTR_TXIS + | AUART_INTR_RXIS + | AUART_INTR_CTSMIS), + s->port.membase + AUART_INTR_CLR); if (istat & AUART_INTR_CTSMIS) { uart_handle_cts_change(&s->port, stat & AUART_STAT_CTS); @@ -398,12 +405,6 @@ static irqreturn_t mxs_auart_irq_handle(int irq, void *context) istat &= ~AUART_INTR_TXIS; } - writel(istatus & (AUART_INTR_RTIS - | AUART_INTR_TXIS - | AUART_INTR_RXIS - | AUART_INTR_CTSMIS), - s->port.membase + AUART_INTR_CLR); - return IRQ_HANDLED; } @@ -543,7 +544,7 @@ auart_console_write(struct console *co, const char *str, unsigned int count) struct mxs_auart_port *s; struct uart_port *port; unsigned int old_ctrl0, old_ctrl2; - unsigned int to = 1000; + unsigned int to = 20000; if (co->index > MXS_AUART_PORTS || co->index < 0) return; @@ -564,18 +565,23 @@ auart_console_write(struct console *co, const char *str, unsigned int count) uart_console_write(port, str, count, mxs_auart_console_putchar); - /* - * Finally, wait for transmitter to become empty - * and restore the TCR - */ + /* Finally, wait for transmitter to become empty ... */ while (readl(port->membase + AUART_STAT) & AUART_STAT_BUSY) { + udelay(1); if (!to--) break; - udelay(1); } - writel(old_ctrl0, port->membase + AUART_CTRL0); - writel(old_ctrl2, port->membase + AUART_CTRL2); + /* + * ... and restore the TCR if we waited long enough for the transmitter + * to be idle. This might keep the transmitter enabled although it is + * unused, but that is better than to disable it while it is still + * transmitting. + */ + if (!(readl(port->membase + AUART_STAT) & AUART_STAT_BUSY)) { + writel(old_ctrl0, port->membase + AUART_CTRL0); + writel(old_ctrl2, port->membase + AUART_CTRL2); + } clk_disable(s->clk); } diff --git a/drivers/tty/serial/pch_uart.c b/drivers/tty/serial/pch_uart.c index 7d4751474da..2e99f7959b9 100644 --- a/drivers/tty/serial/pch_uart.c +++ b/drivers/tty/serial/pch_uart.c @@ -1034,22 +1034,37 @@ static unsigned int dma_handle_tx(struct eg20t_port *priv) static void pch_uart_err_ir(struct eg20t_port *priv, unsigned int lsr) { u8 fcr = ioread8(priv->membase + UART_FCR); + struct uart_port *port = &priv->port; + struct tty_struct *tty = tty_port_tty_get(&port->state->port); + char *error_msg[5] = {}; + int i = 0; /* Reset FIFO */ fcr |= UART_FCR_CLEAR_RCVR; iowrite8(fcr, priv->membase + UART_FCR); if (lsr & PCH_UART_LSR_ERR) - dev_err(&priv->pdev->dev, "Error data in FIFO\n"); + error_msg[i++] = "Error data in FIFO\n"; - if (lsr & UART_LSR_FE) - dev_err(&priv->pdev->dev, "Framing Error\n"); + if (lsr & UART_LSR_FE) { + port->icount.frame++; + error_msg[i++] = " Framing Error\n"; + } - if (lsr & UART_LSR_PE) - dev_err(&priv->pdev->dev, "Parity Error\n"); + if (lsr & UART_LSR_PE) { + port->icount.parity++; + error_msg[i++] = " Parity Error\n"; + } - if (lsr & UART_LSR_OE) - dev_err(&priv->pdev->dev, "Overrun Error\n"); + if (lsr & UART_LSR_OE) { + port->icount.overrun++; + error_msg[i++] = " Overrun Error\n"; + } + + if (tty == NULL) { + for (i = 0; error_msg[i] != NULL; i++) + dev_err(&priv->pdev->dev, error_msg[i]); + } } static irqreturn_t pch_uart_interrupt(int irq, void *dev_id) diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 450c891e12f..7ffdbeeee57 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -1880,6 +1880,8 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport) mutex_unlock(&port->mutex); return 0; } + put_device(tty_dev); + if (console_suspend_enabled || !uart_console(uport)) uport->suspended = 1; @@ -1945,9 +1947,11 @@ int uart_resume_port(struct uart_driver *drv, struct uart_port *uport) disable_irq_wake(uport->irq); uport->irq_wake = 0; } + put_device(tty_dev); mutex_unlock(&port->mutex); return 0; } + put_device(tty_dev); uport->suspended = 0; /* diff --git a/drivers/tty/serial/sunsu.c b/drivers/tty/serial/sunsu.c index 675303b8ed8..76fa1fa41ef 100644 --- a/drivers/tty/serial/sunsu.c +++ b/drivers/tty/serial/sunsu.c @@ -968,6 +968,7 @@ static struct uart_ops sunsu_pops = { #define UART_NR 4 static struct uart_sunsu_port sunsu_ports[UART_NR]; +static int nr_inst; /* Number of already registered ports */ #ifdef CONFIG_SERIO @@ -1337,13 +1338,8 @@ static int __init sunsu_console_setup(struct console *co, char *options) printk("Console: ttyS%d (SU)\n", (sunsu_reg.minor - 64) + co->index); - /* - * Check whether an invalid uart number has been specified, and - * if so, search for the first available port that does have - * console support. - */ - if (co->index >= UART_NR) - co->index = 0; + if (co->index > nr_inst) + return -ENODEV; port = &sunsu_ports[co->index].port; /* @@ -1408,7 +1404,6 @@ static enum su_type __devinit su_get_type(struct device_node *dp) static int __devinit su_probe(struct platform_device *op) { - static int inst; struct device_node *dp = op->dev.of_node; struct uart_sunsu_port *up; struct resource *rp; @@ -1418,16 +1413,16 @@ static int __devinit su_probe(struct platform_device *op) type = su_get_type(dp); if (type == SU_PORT_PORT) { - if (inst >= UART_NR) + if (nr_inst >= UART_NR) return -EINVAL; - up = &sunsu_ports[inst]; + up = &sunsu_ports[nr_inst]; } else { up = kzalloc(sizeof(*up), GFP_KERNEL); if (!up) return -ENOMEM; } - up->port.line = inst; + up->port.line = nr_inst; spin_lock_init(&up->port.lock); @@ -1461,6 +1456,8 @@ static int __devinit su_probe(struct platform_device *op) } dev_set_drvdata(&op->dev, up); + nr_inst++; + return 0; } @@ -1488,7 +1485,7 @@ static int __devinit su_probe(struct platform_device *op) dev_set_drvdata(&op->dev, up); - inst++; + nr_inst++; return 0; diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index a2034723717..1cd48ba25a4 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -938,6 +938,14 @@ void start_tty(struct tty_struct *tty) EXPORT_SYMBOL(start_tty); +/* We limit tty time update visibility to every 8 seconds or so. */ +static void tty_update_time(struct timespec *time) +{ + unsigned long sec = get_seconds() & ~7; + if ((long)(sec - time->tv_sec) > 0) + time->tv_sec = sec; +} + /** * tty_read - read method for tty device files * @file: pointer to tty file @@ -974,8 +982,10 @@ static ssize_t tty_read(struct file *file, char __user *buf, size_t count, else i = -EIO; tty_ldisc_deref(ld); + if (i > 0) - inode->i_atime = current_fs_time(inode->i_sb); + tty_update_time(&inode->i_atime); + return i; } @@ -1078,7 +1088,7 @@ static inline ssize_t do_tty_write( } if (written) { struct inode *inode = file->f_path.dentry->d_inode; - inode->i_mtime = current_fs_time(inode->i_sb); + tty_update_time(&inode->i_mtime); ret = written; } out: diff --git a/drivers/tty/tty_ioctl.c b/drivers/tty/tty_ioctl.c index a1b9a2f6856..f8d03da536d 100644 --- a/drivers/tty/tty_ioctl.c +++ b/drivers/tty/tty_ioctl.c @@ -617,7 +617,7 @@ static int set_termios(struct tty_struct *tty, void __user *arg, int opt) if (opt & TERMIOS_WAIT) { tty_wait_until_sent(tty, 0); if (signal_pending(current)) - return -EINTR; + return -ERESTARTSYS; } tty_set_termios(tty, &tmp_termios); @@ -684,7 +684,7 @@ static int set_termiox(struct tty_struct *tty, void __user *arg, int opt) if (opt & TERMIOS_WAIT) { tty_wait_until_sent(tty, 0); if (signal_pending(current)) - return -EINTR; + return -ERESTARTSYS; } mutex_lock(&tty->termios_mutex); diff --git a/drivers/tty/vt/vc_screen.c b/drivers/tty/vt/vc_screen.c index fa7268a93c0..6abb92c22c2 100644 --- a/drivers/tty/vt/vc_screen.c +++ b/drivers/tty/vt/vc_screen.c @@ -93,7 +93,7 @@ vcs_poll_data_free(struct vcs_poll_data *poll) static struct vcs_poll_data * vcs_poll_data_get(struct file *file) { - struct vcs_poll_data *poll = file->private_data; + struct vcs_poll_data *poll = file->private_data, *kill = NULL; if (poll) return poll; @@ -122,10 +122,12 @@ vcs_poll_data_get(struct file *file) file->private_data = poll; } else { /* someone else raced ahead of us */ - vcs_poll_data_free(poll); + kill = poll; poll = file->private_data; } spin_unlock(&file->f_lock); + if (kill) + vcs_poll_data_free(kill); return poll; } diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 18d06be8c9b..02b7236de6a 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -656,7 +656,7 @@ static inline void save_screen(struct vc_data *vc) * Redrawing of screen */ -static void clear_buffer_attributes(struct vc_data *vc) +void clear_buffer_attributes(struct vc_data *vc) { unsigned short *p = (unsigned short *)vc->vc_origin; int count = vc->vc_screenbuf_size / 2; @@ -3017,7 +3017,7 @@ int __init vty_init(const struct file_operations *console_fops) static struct class *vtconsole_class; -static int bind_con_driver(const struct consw *csw, int first, int last, +static int do_bind_con_driver(const struct consw *csw, int first, int last, int deflt) { struct module *owner = csw->owner; @@ -3028,7 +3028,7 @@ static int bind_con_driver(const struct consw *csw, int first, int last, if (!try_module_get(owner)) return -ENODEV; - console_lock(); + WARN_CONSOLE_UNLOCKED(); /* check if driver is registered */ for (i = 0; i < MAX_NR_CON_DRIVER; i++) { @@ -3113,11 +3113,22 @@ static int bind_con_driver(const struct consw *csw, int first, int last, retval = 0; err: - console_unlock(); module_put(owner); return retval; }; + +static int bind_con_driver(const struct consw *csw, int first, int last, + int deflt) +{ + int ret; + + console_lock(); + ret = do_bind_con_driver(csw, first, last, deflt); + console_unlock(); + return ret; +} + #ifdef CONFIG_VT_HW_CONSOLE_BINDING static int con_is_graphics(const struct consw *csw, int first, int last) { @@ -3153,6 +3164,18 @@ static int con_is_graphics(const struct consw *csw, int first, int last) * or 0 on success. */ int unbind_con_driver(const struct consw *csw, int first, int last, int deflt) +{ + int retval; + + console_lock(); + retval = do_unbind_con_driver(csw, first, last, deflt); + console_unlock(); + return retval; +} +EXPORT_SYMBOL(unbind_con_driver); + +/* unlocked version of unbind_con_driver() */ +int do_unbind_con_driver(const struct consw *csw, int first, int last, int deflt) { struct module *owner = csw->owner; const struct consw *defcsw = NULL; @@ -3162,7 +3185,7 @@ int unbind_con_driver(const struct consw *csw, int first, int last, int deflt) if (!try_module_get(owner)) return -ENODEV; - console_lock(); + WARN_CONSOLE_UNLOCKED(); /* check if driver is registered and if it is unbindable */ for (i = 0; i < MAX_NR_CON_DRIVER; i++) { @@ -3175,10 +3198,8 @@ int unbind_con_driver(const struct consw *csw, int first, int last, int deflt) } } - if (retval) { - console_unlock(); + if (retval) goto err; - } retval = -ENODEV; @@ -3194,15 +3215,11 @@ int unbind_con_driver(const struct consw *csw, int first, int last, int deflt) } } - if (retval) { - console_unlock(); + if (retval) goto err; - } - if (!con_is_bound(csw)) { - console_unlock(); + if (!con_is_bound(csw)) goto err; - } first = max(first, con_driver->first); last = min(last, con_driver->last); @@ -3229,15 +3246,14 @@ int unbind_con_driver(const struct consw *csw, int first, int last, int deflt) if (!con_is_bound(csw)) con_driver->flag &= ~CON_DRIVER_FLAG_INIT; - console_unlock(); /* ignore return value, binding should not fail */ - bind_con_driver(defcsw, first, last, deflt); + do_bind_con_driver(defcsw, first, last, deflt); err: module_put(owner); return retval; } -EXPORT_SYMBOL(unbind_con_driver); +EXPORT_SYMBOL_GPL(do_unbind_con_driver); static int vt_bind(struct con_driver *con) { @@ -3522,28 +3538,18 @@ int con_debug_leave(void) } EXPORT_SYMBOL_GPL(con_debug_leave); -/** - * register_con_driver - register console driver to console layer - * @csw: console driver - * @first: the first console to take over, minimum value is 0 - * @last: the last console to take over, maximum value is MAX_NR_CONSOLES -1 - * - * DESCRIPTION: This function registers a console driver which can later - * bind to a range of consoles specified by @first and @last. It will - * also initialize the console driver by calling con_startup(). - */ -int register_con_driver(const struct consw *csw, int first, int last) +static int do_register_con_driver(const struct consw *csw, int first, int last) { struct module *owner = csw->owner; struct con_driver *con_driver; const char *desc; int i, retval = 0; + WARN_CONSOLE_UNLOCKED(); + if (!try_module_get(owner)) return -ENODEV; - console_lock(); - for (i = 0; i < MAX_NR_CON_DRIVER; i++) { con_driver = ®istered_con_driver[i]; @@ -3596,10 +3602,29 @@ int register_con_driver(const struct consw *csw, int first, int last) } err: - console_unlock(); module_put(owner); return retval; } + +/** + * register_con_driver - register console driver to console layer + * @csw: console driver + * @first: the first console to take over, minimum value is 0 + * @last: the last console to take over, maximum value is MAX_NR_CONSOLES -1 + * + * DESCRIPTION: This function registers a console driver which can later + * bind to a range of consoles specified by @first and @last. It will + * also initialize the console driver by calling con_startup(). + */ +int register_con_driver(const struct consw *csw, int first, int last) +{ + int retval; + + console_lock(); + retval = do_register_con_driver(csw, first, last); + console_unlock(); + return retval; +} EXPORT_SYMBOL(register_con_driver); /** @@ -3615,9 +3640,18 @@ EXPORT_SYMBOL(register_con_driver); */ int unregister_con_driver(const struct consw *csw) { - int i, retval = -ENODEV; + int retval; console_lock(); + retval = do_unregister_con_driver(csw); + console_unlock(); + return retval; +} +EXPORT_SYMBOL(unregister_con_driver); + +int do_unregister_con_driver(const struct consw *csw) +{ + int i, retval = -ENODEV; /* cannot unregister a bound driver */ if (con_is_bound(csw)) @@ -3643,27 +3677,53 @@ int unregister_con_driver(const struct consw *csw) } } err: - console_unlock(); return retval; } -EXPORT_SYMBOL(unregister_con_driver); +EXPORT_SYMBOL_GPL(do_unregister_con_driver); /* * If we support more console drivers, this function is used * when a driver wants to take over some existing consoles * and become default driver for newly opened ones. * - * take_over_console is basically a register followed by unbind + * take_over_console is basically a register followed by unbind + */ +int do_take_over_console(const struct consw *csw, int first, int last, int deflt) +{ + int err; + + err = do_register_con_driver(csw, first, last); + /* + * If we get an busy error we still want to bind the console driver + * and return success, as we may have unbound the console driver + * but not unregistered it. + */ + if (err == -EBUSY) + err = 0; + if (!err) + do_bind_con_driver(csw, first, last, deflt); + + return err; +} +EXPORT_SYMBOL_GPL(do_take_over_console); + +/* + * If we support more console drivers, this function is used + * when a driver wants to take over some existing consoles + * and become default driver for newly opened ones. + * + * take_over_console is basically a register followed by unbind */ int take_over_console(const struct consw *csw, int first, int last, int deflt) { int err; err = register_con_driver(csw, first, last); - /* if we get an busy error we still want to bind the console driver + /* + * If we get an busy error we still want to bind the console driver * and return success, as we may have unbound the console driver  * but not unregistered it. - */ + */ if (err == -EBUSY) err = 0; if (!err) diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c index 98b89fe1986..c8dbb970c08 100644 --- a/drivers/usb/atm/cxacru.c +++ b/drivers/usb/atm/cxacru.c @@ -686,7 +686,8 @@ static int cxacru_cm_get_array(struct cxacru_data *instance, enum cxacru_cm_requ { int ret, len; __le32 *buf; - int offb, offd; + int offb; + unsigned int offd; const int stride = CMD_PACKET_SIZE / (4 * 2) - 1; int buflen = ((size - 1) / stride + 1 + size * 2) * 4; diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 3a7a95084cc..e411f186529 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -601,7 +601,6 @@ static void acm_port_destruct(struct tty_port *port) dev_dbg(&acm->control->dev, "%s\n", __func__); - tty_unregister_device(acm_tty_driver, acm->minor); acm_release_minor(acm); usb_put_intf(acm->control); kfree(acm->country_codes); @@ -1418,6 +1417,8 @@ static void acm_disconnect(struct usb_interface *intf) stop_data_traffic(acm); + tty_unregister_device(acm_tty_driver, acm->minor); + usb_free_urb(acm->ctrlurb); for (i = 0; i < ACM_NW; i++) usb_free_urb(acm->wb[i].urb); diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 524fe240fcd..9dd51f7fb64 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -81,6 +81,7 @@ MODULE_DEVICE_TABLE (usb, wdm_ids); #define WDM_RESPONDING 7 #define WDM_SUSPENDING 8 #define WDM_RESETTING 9 +#define WDM_OVERFLOW 10 #define WDM_MAX 16 @@ -180,6 +181,7 @@ static void wdm_in_callback(struct urb *urb) { struct wdm_device *desc = urb->context; int status = urb->status; + int length = urb->actual_length; spin_lock(&desc->iuspin); clear_bit(WDM_RESPONDING, &desc->flags); @@ -210,9 +212,17 @@ static void wdm_in_callback(struct urb *urb) } desc->rerr = status; - desc->reslength = urb->actual_length; - memmove(desc->ubuf + desc->length, desc->inbuf, desc->reslength); - desc->length += desc->reslength; + if (length + desc->length > desc->wMaxCommand) { + /* The buffer would overflow */ + set_bit(WDM_OVERFLOW, &desc->flags); + } else { + /* we may already be in overflow */ + if (!test_bit(WDM_OVERFLOW, &desc->flags)) { + memmove(desc->ubuf + desc->length, desc->inbuf, length); + desc->length += length; + desc->reslength = length; + } + } skip_error: wake_up(&desc->wait); @@ -457,6 +467,11 @@ static ssize_t wdm_read rv = -ENODEV; goto err; } + if (test_bit(WDM_OVERFLOW, &desc->flags)) { + clear_bit(WDM_OVERFLOW, &desc->flags); + rv = -ENOBUFS; + goto err; + } i++; if (file->f_flags & O_NONBLOCK) { if (!test_bit(WDM_READ, &desc->flags)) { @@ -500,6 +515,7 @@ static ssize_t wdm_read spin_unlock_irq(&desc->iuspin); goto retry; } + if (!desc->reslength) { /* zero length read */ dev_dbg(&desc->intf->dev, "%s: zero length - clearing WDM_READ\n", __func__); clear_bit(WDM_READ, &desc->flags); @@ -1023,6 +1039,7 @@ static int wdm_post_reset(struct usb_interface *intf) struct wdm_device *desc = wdm_find_device(intf); int rv; + clear_bit(WDM_OVERFLOW, &desc->flags); clear_bit(WDM_RESETTING, &desc->flags); rv = recover_from_urb_loss(desc); mutex_unlock(&desc->wlock); diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 404413b0b93..336b82da377 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -681,6 +681,8 @@ static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype, index &= 0xff; switch (requesttype & USB_RECIP_MASK) { case USB_RECIP_ENDPOINT: + if ((index & ~USB_DIR_IN) == 0) + return 0; ret = findintfep(ps->dev, index); if (ret >= 0) ret = checkintf(ps, ret); diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index 622b4a48e73..2b487d4797b 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c @@ -173,6 +173,7 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) struct hc_driver *driver; struct usb_hcd *hcd; int retval; + int hcd_irq = 0; if (usb_disabled()) return -ENODEV; @@ -187,15 +188,19 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) return -ENODEV; dev->current_state = PCI_D0; - /* The xHCI driver supports MSI and MSI-X, - * so don't fail if the BIOS doesn't provide a legacy IRQ. + /* + * The xHCI driver has its own irq management + * make sure irq setup is not touched for xhci in generic hcd code */ - if (!dev->irq && (driver->flags & HCD_MASK) != HCD_USB3) { - dev_err(&dev->dev, - "Found HC with no IRQ. Check BIOS/PCI %s setup!\n", - pci_name(dev)); - retval = -ENODEV; - goto disable_pci; + if ((driver->flags & HCD_MASK) != HCD_USB3) { + if (!dev->irq) { + dev_err(&dev->dev, + "Found HC with no IRQ. Check BIOS/PCI %s setup!\n", + pci_name(dev)); + retval = -ENODEV; + goto disable_pci; + } + hcd_irq = dev->irq; } hcd = usb_create_hcd(driver, &dev->dev, pci_name(dev)); @@ -245,7 +250,7 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) pci_set_master(dev); - retval = usb_add_hcd(hcd, dev->irq, IRQF_SHARED); + retval = usb_add_hcd(hcd, hcd_irq, IRQF_SHARED); if (retval != 0) goto unmap_registers; set_hs_companion(dev, hcd); diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index eb44693970e..965b1771e0f 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -517,6 +517,15 @@ static void hub_irq(struct urb *urb) static inline int hub_clear_tt_buffer (struct usb_device *hdev, u16 devinfo, u16 tt) { + /* Need to clear both directions for control ep */ + if (((devinfo >> 11) & USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_CONTROL) { + int status = usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0), + HUB_CLEAR_TT_BUFFER, USB_RT_PORT, + devinfo ^ 0x8000, tt, NULL, 0, 1000); + if (status) + return status; + } return usb_control_msg(hdev, usb_sndctrlpipe(hdev, 0), HUB_CLEAR_TT_BUFFER, USB_RT_PORT, devinfo, tt, NULL, 0, 1000); @@ -2294,70 +2303,35 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1, if ((portstatus & USB_PORT_STAT_RESET)) goto delay; - /* - * Some buggy devices require a warm reset to be issued even - * when the port appears not to be connected. + if (hub_port_warm_reset_required(hub, portstatus)) + return -ENOTCONN; + + /* Device went away? */ + if (!(portstatus & USB_PORT_STAT_CONNECTION)) + return -ENOTCONN; + + /* bomb out completely if the connection bounced. A USB 3.0 + * connection may bounce if multiple warm resets were issued, + * but the device may have successfully re-connected. Ignore it. */ - if (!warm) { - /* - * Some buggy devices can cause an NEC host controller - * to transition to the "Error" state after a hot port - * reset. This will show up as the port state in - * "Inactive", and the port may also report a - * disconnect. Forcing a warm port reset seems to make - * the device work. - * - * See https://bugzilla.kernel.org/show_bug.cgi?id=41752 - */ - if (hub_port_warm_reset_required(hub, portstatus)) { - int ret; - - if ((portchange & USB_PORT_STAT_C_CONNECTION)) - clear_port_feature(hub->hdev, port1, - USB_PORT_FEAT_C_CONNECTION); - if (portchange & USB_PORT_STAT_C_LINK_STATE) - clear_port_feature(hub->hdev, port1, - USB_PORT_FEAT_C_PORT_LINK_STATE); - if (portchange & USB_PORT_STAT_C_RESET) - clear_port_feature(hub->hdev, port1, - USB_PORT_FEAT_C_RESET); - dev_dbg(hub->intfdev, "hot reset failed, warm reset port %d\n", - port1); - ret = hub_port_reset(hub, port1, - udev, HUB_BH_RESET_TIME, - true); - if ((portchange & USB_PORT_STAT_C_CONNECTION)) - clear_port_feature(hub->hdev, port1, - USB_PORT_FEAT_C_CONNECTION); - return ret; - } - /* Device went away? */ - if (!(portstatus & USB_PORT_STAT_CONNECTION)) - return -ENOTCONN; - - /* bomb out completely if the connection bounced */ - if ((portchange & USB_PORT_STAT_C_CONNECTION)) - return -ENOTCONN; - - if ((portstatus & USB_PORT_STAT_ENABLE)) { - if (hub_is_wusb(hub)) - udev->speed = USB_SPEED_WIRELESS; - else if (hub_is_superspeed(hub->hdev)) - udev->speed = USB_SPEED_SUPER; - else if (portstatus & USB_PORT_STAT_HIGH_SPEED) - udev->speed = USB_SPEED_HIGH; - else if (portstatus & USB_PORT_STAT_LOW_SPEED) - udev->speed = USB_SPEED_LOW; - else - udev->speed = USB_SPEED_FULL; + if (!hub_is_superspeed(hub->hdev) && + (portchange & USB_PORT_STAT_C_CONNECTION)) + return -ENOTCONN; + + if ((portstatus & USB_PORT_STAT_ENABLE)) { + if (!udev) return 0; - } - } else { - if (!(portstatus & USB_PORT_STAT_CONNECTION) || - hub_port_warm_reset_required(hub, - portstatus)) - return -ENOTCONN; + if (hub_is_wusb(hub)) + udev->speed = USB_SPEED_WIRELESS; + else if (hub_is_superspeed(hub->hdev)) + udev->speed = USB_SPEED_SUPER; + else if (portstatus & USB_PORT_STAT_HIGH_SPEED) + udev->speed = USB_SPEED_HIGH; + else if (portstatus & USB_PORT_STAT_LOW_SPEED) + udev->speed = USB_SPEED_LOW; + else + udev->speed = USB_SPEED_FULL; return 0; } @@ -2375,16 +2349,16 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1, } static void hub_port_finish_reset(struct usb_hub *hub, int port1, - struct usb_device *udev, int *status, bool warm) + struct usb_device *udev, int *status) { switch (*status) { case 0: - if (!warm) { - struct usb_hcd *hcd; - /* TRSTRCY = 10 ms; plus some extra */ - msleep(10 + 40); + /* TRSTRCY = 10 ms; plus some extra */ + msleep(10 + 40); + if (udev) { + struct usb_hcd *hcd = bus_to_hcd(udev->bus); + update_devnum(udev, 0); - hcd = bus_to_hcd(udev->bus); /* The xHC may think the device is already reset, * so ignore the status. */ @@ -2396,14 +2370,15 @@ static void hub_port_finish_reset(struct usb_hub *hub, int port1, case -ENODEV: clear_port_feature(hub->hdev, port1, USB_PORT_FEAT_C_RESET); - /* FIXME need disconnect() for NOTATTACHED device */ if (hub_is_superspeed(hub->hdev)) { clear_port_feature(hub->hdev, port1, USB_PORT_FEAT_C_BH_PORT_RESET); clear_port_feature(hub->hdev, port1, USB_PORT_FEAT_C_PORT_LINK_STATE); + clear_port_feature(hub->hdev, port1, + USB_PORT_FEAT_C_CONNECTION); } - if (!warm) + if (udev) usb_set_device_state(udev, *status ? USB_STATE_NOTATTACHED : USB_STATE_DEFAULT); @@ -2416,18 +2391,30 @@ static int hub_port_reset(struct usb_hub *hub, int port1, struct usb_device *udev, unsigned int delay, bool warm) { int i, status; + u16 portchange, portstatus; - if (!warm) { - /* Block EHCI CF initialization during the port reset. - * Some companion controllers don't like it when they mix. - */ - down_read(&ehci_cf_port_reset_rwsem); - } else { - if (!hub_is_superspeed(hub->hdev)) { + if (!hub_is_superspeed(hub->hdev)) { + if (warm) { dev_err(hub->intfdev, "only USB3 hub support " "warm reset\n"); return -EINVAL; } + /* Block EHCI CF initialization during the port reset. + * Some companion controllers don't like it when they mix. + */ + down_read(&ehci_cf_port_reset_rwsem); + } else if (!warm) { + /* + * If the caller hasn't explicitly requested a warm reset, + * double check and see if one is needed. + */ + status = hub_port_status(hub, port1, + &portstatus, &portchange); + if (status < 0) + goto done; + + if (hub_port_warm_reset_required(hub, portstatus)) + warm = true; } /* Reset the port */ @@ -2448,10 +2435,33 @@ static int hub_port_reset(struct usb_hub *hub, int port1, status); } - /* return on disconnect or reset */ + /* Check for disconnect or reset */ if (status == 0 || status == -ENOTCONN || status == -ENODEV) { - hub_port_finish_reset(hub, port1, udev, &status, warm); - goto done; + hub_port_finish_reset(hub, port1, udev, &status); + + if (!hub_is_superspeed(hub->hdev)) + goto done; + + /* + * If a USB 3.0 device migrates from reset to an error + * state, re-issue the warm reset. + */ + if (hub_port_status(hub, port1, + &portstatus, &portchange) < 0) + goto done; + + if (!hub_port_warm_reset_required(hub, portstatus)) + goto done; + + /* + * If the port is in SS.Inactive or Compliance Mode, the + * hot or warm reset failed. Try another warm reset. + */ + if (!warm) { + dev_dbg(hub->intfdev, "hot reset failed, warm reset port %d\n", + port1); + warm = true; + } } dev_dbg (hub->intfdev, @@ -2465,7 +2475,7 @@ static int hub_port_reset(struct usb_hub *hub, int port1, port1); done: - if (!warm) + if (!hub_is_superspeed(hub->hdev)) up_read(&ehci_cf_port_reset_rwsem); return status; @@ -4194,13 +4204,23 @@ static void hub_events(void) */ if (hub_port_warm_reset_required(hub, portstatus)) { int status; + struct usb_device *udev = + hub->hdev->children[i - 1]; dev_dbg(hub_dev, "warm reset port %d\n", i); - status = hub_port_reset(hub, i, NULL, - HUB_BH_RESET_TIME, true); - if (status < 0) - hub_port_disable(hub, i, 1); - connect_change = 0; + if (!udev || !(portstatus & + USB_PORT_STAT_CONNECTION)) { + status = hub_port_reset(hub, i, + NULL, HUB_BH_RESET_TIME, + true); + if (status < 0) + hub_port_disable(hub, i, 1); + } else { + usb_lock_device(udev); + status = usb_reset_device(udev); + usb_unlock_device(udev); + connect_change = 0; + } } if (connect_change) { diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index 5f650517044..5e88ccea05f 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -100,6 +100,12 @@ static const struct usb_device_id usb_quirk_list[] = { { USB_DEVICE(0x04d8, 0x000c), .driver_info = USB_QUIRK_CONFIG_INTF_STRINGS }, + /* CarrolTouch 4000U */ + { USB_DEVICE(0x04e7, 0x0009), .driver_info = USB_QUIRK_RESET_RESUME }, + + /* CarrolTouch 4500U */ + { USB_DEVICE(0x04e7, 0x0030), .driver_info = USB_QUIRK_RESET_RESUME }, + /* Samsung Android phone modem - ID conflict with SPH-I500 */ { USB_DEVICE(0x04e8, 0x6601), .driver_info = USB_QUIRK_CONFIG_INTF_STRINGS }, @@ -110,6 +116,9 @@ static const struct usb_device_id usb_quirk_list[] = { /* Edirol SD-20 */ { USB_DEVICE(0x0582, 0x0027), .driver_info = USB_QUIRK_RESET_RESUME }, + /* Alcor Micro Corp. Hub */ + { USB_DEVICE(0x058f, 0x9254), .driver_info = USB_QUIRK_RESET_RESUME }, + /* appletouch */ { USB_DEVICE(0x05ac, 0x021a), .driver_info = USB_QUIRK_RESET_RESUME }, diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 92e28f5216f..2540af04638 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -701,8 +701,8 @@ struct dwc3 { struct dwc3_event_type { u32 is_devspec:1; - u32 type:6; - u32 reserved8_31:25; + u32 type:7; + u32 reserved8_31:24; } __packed; #define DWC3_DEPEVT_XFERCOMPLETE 0x01 diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 03b4f650a94..c4df80cda53 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1443,6 +1443,7 @@ static int dwc3_gadget_start(struct usb_gadget *g, __dwc3_gadget_ep_disable(dwc->eps[0]); err0: + dwc->gadget_driver = NULL; spin_unlock_irqrestore(&dwc->lock, flags); return ret; diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c index 165f252b63d..5fe3b40b194 100644 --- a/drivers/usb/gadget/f_mass_storage.c +++ b/drivers/usb/gadget/f_mass_storage.c @@ -515,6 +515,7 @@ static int fsg_set_halt(struct fsg_dev *fsg, struct usb_ep *ep) /* Caller must hold fsg->lock */ static void wakeup_thread(struct fsg_common *common) { + smp_wmb(); /* ensure the write of bh->state is complete */ /* Tell the main thread that something has happened */ common->thread_wakeup_needed = 1; if (common->thread_task) @@ -734,6 +735,7 @@ static int sleep_thread(struct fsg_common *common) } __set_current_state(TASK_RUNNING); common->thread_wakeup_needed = 0; + smp_rmb(); /* ensure the latest bh->state is visible */ return rc; } diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c index c16ff97cc44..5c887020b44 100644 --- a/drivers/usb/gadget/udc-core.c +++ b/drivers/usb/gadget/udc-core.c @@ -265,7 +265,7 @@ static void usb_gadget_remove_driver(struct usb_udc *udc) udc->driver->disconnect(udc->gadget); usb_gadget_disconnect(udc->gadget); udc->driver->unbind(udc->gadget); - usb_gadget_udc_stop(udc->gadget, udc->driver); + usb_gadget_udc_stop(udc->gadget, NULL); } else { usb_gadget_stop(udc->gadget, udc->driver); } diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c index e669c6a7e91..12d3f284998 100644 --- a/drivers/usb/host/ehci-omap.c +++ b/drivers/usb/host/ehci-omap.c @@ -371,7 +371,7 @@ static const struct hc_driver ehci_omap_hc_driver = { .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, }; -MODULE_ALIAS("platform:omap-ehci"); +MODULE_ALIAS("platform:ehci-omap"); MODULE_AUTHOR("Texas Instruments, Inc."); MODULE_AUTHOR("Felipe Balbi "); diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 14d2d71163f..a60679cbbf8 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -236,7 +236,7 @@ static inline unsigned char tt_start_uframe(struct ehci_hcd *ehci, __hc32 mask) } static const unsigned char -max_tt_usecs[] = { 125, 125, 125, 125, 125, 125, 125, 25 }; +max_tt_usecs[] = { 125, 125, 125, 125, 125, 125, 30, 0 }; /* carryover low/fullspeed bandwidth that crosses uframe boundries */ static inline void carryover_tt_bandwidth(unsigned short tt_usecs[8]) diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c index 768d54295a2..c9946556512 100644 --- a/drivers/usb/host/uhci-hub.c +++ b/drivers/usb/host/uhci-hub.c @@ -222,7 +222,8 @@ static int uhci_hub_status_data(struct usb_hcd *hcd, char *buf) /* auto-stop if nothing connected for 1 second */ if (any_ports_active(uhci)) uhci->rh_state = UHCI_RH_RUNNING; - else if (time_after_eq(jiffies, uhci->auto_stop_time)) + else if (time_after_eq(jiffies, uhci->auto_stop_time) && + !uhci->wait_for_hp) suspend_rh(uhci, UHCI_RH_AUTO_STOPPED); break; diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index b42a6fb45b2..3347e9be9a6 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -369,6 +369,10 @@ static struct xhci_container_ctx *xhci_alloc_container_ctx(struct xhci_hcd *xhci ctx->size += CTX_SIZE(xhci->hcc_params); ctx->bytes = dma_pool_alloc(xhci->device_pool, flags, &ctx->dma); + if (!ctx->bytes) { + kfree(ctx); + return NULL; + } memset(ctx->bytes, 0, ctx->size); return ctx; } @@ -1443,15 +1447,17 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, ep_ctx->ep_info2 |= cpu_to_le32(xhci_get_endpoint_type(udev, ep)); /* Set the max packet size and max burst */ + max_packet = GET_MAX_PACKET(usb_endpoint_maxp(&ep->desc)); + max_burst = 0; switch (udev->speed) { case USB_SPEED_SUPER: - max_packet = usb_endpoint_maxp(&ep->desc); - ep_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(max_packet)); /* dig out max burst from ep companion desc */ - max_packet = ep->ss_ep_comp.bMaxBurst; - ep_ctx->ep_info2 |= cpu_to_le32(MAX_BURST(max_packet)); + max_burst = ep->ss_ep_comp.bMaxBurst; break; case USB_SPEED_HIGH: + /* Some devices get this wrong */ + if (usb_endpoint_xfer_bulk(&ep->desc)) + max_packet = 512; /* bits 11:12 specify the number of additional transaction * opportunities per microframe (USB 2.0, section 9.6.6) */ @@ -1459,17 +1465,16 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, usb_endpoint_xfer_int(&ep->desc)) { max_burst = (usb_endpoint_maxp(&ep->desc) & 0x1800) >> 11; - ep_ctx->ep_info2 |= cpu_to_le32(MAX_BURST(max_burst)); } - /* Fall through */ + break; case USB_SPEED_FULL: case USB_SPEED_LOW: - max_packet = GET_MAX_PACKET(usb_endpoint_maxp(&ep->desc)); - ep_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(max_packet)); break; default: BUG(); } + ep_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(max_packet) | + MAX_BURST(max_burst)); max_esit_payload = xhci_get_max_esit_payload(xhci, udev, ep); ep_ctx->tx_info = cpu_to_le32(MAX_ESIT_PAYLOAD_FOR_EP(max_esit_payload)); @@ -1844,6 +1849,9 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) } spin_unlock_irqrestore(&xhci->lock, flags); + if (!xhci->rh_bw) + goto no_bw; + num_ports = HCS_MAX_PORTS(xhci->hcs_params1); for (i = 0; i < num_ports; i++) { struct xhci_interval_bw_table *bwt = &xhci->rh_bw[i].bw_table; @@ -1862,6 +1870,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) } } +no_bw: xhci->num_usb2_ports = 0; xhci->num_usb3_ports = 0; xhci->num_active_eps = 0; @@ -2273,6 +2282,9 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) u32 page_size, temp; int i; + INIT_LIST_HEAD(&xhci->lpm_failed_devs); + INIT_LIST_HEAD(&xhci->cancel_cmd_list); + page_size = xhci_readl(xhci, &xhci->op_regs->page_size); xhci_dbg(xhci, "Supported page size register = 0x%x\n", page_size); for (i = 0; i < 16; i++) { @@ -2351,7 +2363,6 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) xhci->cmd_ring = xhci_ring_alloc(xhci, 1, 1, TYPE_COMMAND, flags); if (!xhci->cmd_ring) goto fail; - INIT_LIST_HEAD(&xhci->cancel_cmd_list); xhci_dbg(xhci, "Allocated command ring at %p\n", xhci->cmd_ring); xhci_dbg(xhci, "First segment DMA is 0x%llx\n", (unsigned long long)xhci->cmd_ring->first_seg->dma); @@ -2452,8 +2463,6 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) if (xhci_setup_port_arrays(xhci, flags)) goto fail; - INIT_LIST_HEAD(&xhci->lpm_failed_devs); - /* Enable USB 3.0 device notifications for function remote wake, which * is necessary for allowing USB 3.0 devices to do remote wakeup from * U3 (device suspend). diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 84e82dc7b79..8b1c27f9302 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -89,7 +89,6 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) xhci->quirks |= XHCI_AMD_PLL_FIX; if (pdev->vendor == PCI_VENDOR_ID_INTEL && pdev->device == PCI_DEVICE_ID_INTEL_PANTHERPOINT_XHCI) { - xhci->quirks |= XHCI_SPURIOUS_SUCCESS; xhci->quirks |= XHCI_EP_LIMIT_QUIRK; xhci->limit_active_eps = 64; xhci->quirks |= XHCI_SW_BW_CHECKING; diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index b2b58a5c45e..39679b14c4a 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -426,7 +426,7 @@ static void ring_doorbell_for_active_rings(struct xhci_hcd *xhci, /* A ring has pending URBs if its TD list is not empty */ if (!(ep->ep_state & EP_HAS_STREAMS)) { - if (!(list_empty(&ep->ring->td_list))) + if (ep->ring && !(list_empty(&ep->ring->td_list))) xhci_ring_ep_doorbell(xhci, slot_id, ep_index, 0); return; } @@ -2008,8 +2008,8 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td, if (event_trb != ep_ring->dequeue && event_trb != td->last_trb) td->urb->actual_length = - td->urb->transfer_buffer_length - - TRB_LEN(le32_to_cpu(event->transfer_len)); + td->urb->transfer_buffer_length - + EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)); else td->urb->actual_length = 0; @@ -2041,7 +2041,7 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td, /* Maybe the event was for the data stage? */ td->urb->actual_length = td->urb->transfer_buffer_length - - TRB_LEN(le32_to_cpu(event->transfer_len)); + EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)); xhci_dbg(xhci, "Waiting for status " "stage event\n"); return 0; @@ -2077,7 +2077,7 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td, /* handle completion code */ switch (trb_comp_code) { case COMP_SUCCESS: - if (TRB_LEN(le32_to_cpu(event->transfer_len)) == 0) { + if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) == 0) { frame->status = 0; break; } @@ -2122,7 +2122,7 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td, len += TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])); } len += TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])) - - TRB_LEN(le32_to_cpu(event->transfer_len)); + EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)); if (trb_comp_code != COMP_STOP_INVAL) { frame->actual_length = len; @@ -2180,7 +2180,7 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td, case COMP_SUCCESS: /* Double check that the HW transferred everything. */ if (event_trb != td->last_trb || - TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) { + EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) { xhci_warn(xhci, "WARN Successful completion " "on short TX\n"); if (td->urb->transfer_flags & URB_SHORT_NOT_OK) @@ -2208,18 +2208,18 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td, "%d bytes untransferred\n", td->urb->ep->desc.bEndpointAddress, td->urb->transfer_buffer_length, - TRB_LEN(le32_to_cpu(event->transfer_len))); + EVENT_TRB_LEN(le32_to_cpu(event->transfer_len))); /* Fast path - was this the last TRB in the TD for this URB? */ if (event_trb == td->last_trb) { - if (TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) { + if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) { td->urb->actual_length = td->urb->transfer_buffer_length - - TRB_LEN(le32_to_cpu(event->transfer_len)); + EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)); if (td->urb->transfer_buffer_length < td->urb->actual_length) { xhci_warn(xhci, "HC gave bad length " "of %d bytes left\n", - TRB_LEN(le32_to_cpu(event->transfer_len))); + EVENT_TRB_LEN(le32_to_cpu(event->transfer_len))); td->urb->actual_length = 0; if (td->urb->transfer_flags & URB_SHORT_NOT_OK) *status = -EREMOTEIO; @@ -2261,7 +2261,7 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td, if (trb_comp_code != COMP_STOP_INVAL) td->urb->actual_length += TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])) - - TRB_LEN(le32_to_cpu(event->transfer_len)); + EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)); } return finish_td(xhci, td, event_trb, event, ep, status, false); @@ -2347,7 +2347,7 @@ static int handle_tx_event(struct xhci_hcd *xhci, * transfer type */ case COMP_SUCCESS: - if (TRB_LEN(le32_to_cpu(event->transfer_len)) == 0) + if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) == 0) break; if (xhci->quirks & XHCI_TRUST_TX_LENGTH) trb_comp_code = COMP_SHORT_TX; @@ -2440,14 +2440,21 @@ static int handle_tx_event(struct xhci_hcd *xhci, * TD list. */ if (list_empty(&ep_ring->td_list)) { - xhci_warn(xhci, "WARN Event TRB for slot %d ep %d " - "with no TDs queued?\n", - TRB_TO_SLOT_ID(le32_to_cpu(event->flags)), - ep_index); - xhci_dbg(xhci, "Event TRB with TRB type ID %u\n", - (le32_to_cpu(event->flags) & - TRB_TYPE_BITMASK)>>10); - xhci_print_trb_offsets(xhci, (union xhci_trb *) event); + /* + * A stopped endpoint may generate an extra completion + * event if the device was suspended. Don't print + * warnings. + */ + if (!(trb_comp_code == COMP_STOP || + trb_comp_code == COMP_STOP_INVAL)) { + xhci_warn(xhci, "WARN Event TRB for slot %d ep %d with no TDs queued?\n", + TRB_TO_SLOT_ID(le32_to_cpu(event->flags)), + ep_index); + xhci_dbg(xhci, "Event TRB with TRB type ID %u\n", + (le32_to_cpu(event->flags) & + TRB_TYPE_BITMASK)>>10); + xhci_print_trb_offsets(xhci, (union xhci_trb *) event); + } if (ep->skip) { ep->skip = false; xhci_dbg(xhci, "td_list is empty while skip " diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 4b93c39fca5..be1f63ae1d6 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -340,7 +340,7 @@ static int xhci_try_enable_msi(struct usb_hcd *hcd) * generate interrupts. Don't even try to enable MSI. */ if (xhci->quirks & XHCI_BROKEN_MSI) - return 0; + goto legacy_irq; /* unregister the legacy interrupt */ if (hcd->irq) @@ -361,6 +361,7 @@ static int xhci_try_enable_msi(struct usb_hcd *hcd) return -EINVAL; } + legacy_irq: /* fall back to legacy interrupt*/ ret = request_irq(pdev->irq, &usb_hcd_irq, IRQF_SHARED, hcd->irq_descr, hcd); @@ -956,6 +957,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) struct usb_hcd *hcd = xhci_to_hcd(xhci); struct usb_hcd *secondary_hcd; int retval = 0; + bool comp_timer_running = false; /* Wait a bit if either of the roothubs need to settle from the * transition into bus suspend. @@ -993,6 +995,13 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) /* If restore operation fails, re-initialize the HC during resume */ if ((temp & STS_SRE) || hibernated) { + + if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) && + !(xhci_all_ports_seen_u0(xhci))) { + del_timer_sync(&xhci->comp_mode_recovery_timer); + xhci_dbg(xhci, "Compliance Mode Recovery Timer deleted!\n"); + } + /* Let the USB core know _both_ roothubs lost power. */ usb_root_hub_lost_power(xhci->main_hcd->self.root_hub); usb_root_hub_lost_power(xhci->shared_hcd->self.root_hub); @@ -1035,6 +1044,8 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) retval = xhci_init(hcd->primary_hcd); if (retval) return retval; + comp_timer_running = true; + xhci_dbg(xhci, "Start the primary HCD\n"); retval = xhci_run(hcd->primary_hcd); if (!retval) { @@ -1076,7 +1087,7 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) * to suffer the Compliance Mode issue again. It doesn't matter if * ports have entered previously to U0 before system's suspension. */ - if (xhci->quirks & XHCI_COMP_MODE_QUIRK) + if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) && !comp_timer_running) compliance_mode_recovery_timer_init(xhci); /* Re-enable port polling. */ @@ -1161,9 +1172,6 @@ static int xhci_check_args(struct usb_hcd *hcd, struct usb_device *udev, } xhci = hcd_to_xhci(hcd); - if (xhci->xhc_state & XHCI_STATE_HALTED) - return -ENODEV; - if (check_virt_dev) { if (!udev->slot_id || !xhci->devs[udev->slot_id]) { printk(KERN_DEBUG "xHCI %s called with unaddressed " @@ -1179,6 +1187,9 @@ static int xhci_check_args(struct usb_hcd *hcd, struct usb_device *udev, } } + if (xhci->xhc_state & XHCI_STATE_HALTED) + return -ENODEV; + return 1; } @@ -4205,6 +4216,13 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks) get_quirks(dev, xhci); + /* In xhci controllers which follow xhci 1.0 spec gives a spurious + * success event after a short transfer. This quirk will ignore such + * spurious event. + */ + if (xhci->hci_version > 0x96) + xhci->quirks |= XHCI_SPURIOUS_SUCCESS; + /* Make sure the HC is halted. */ retval = xhci_halt(xhci); if (retval) diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index affb51334b1..8f11fc9335b 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -206,8 +206,8 @@ struct xhci_op_regs { /* bits 12:31 are reserved (and should be preserved on writes). */ /* IMAN - Interrupt Management Register */ -#define IMAN_IP (1 << 1) -#define IMAN_IE (1 << 0) +#define IMAN_IE (1 << 1) +#define IMAN_IP (1 << 0) /* USBSTS - USB status - status bitmasks */ /* HC not running - set to 1 when run/stop bit is cleared. */ @@ -968,6 +968,10 @@ struct xhci_transfer_event { __le32 flags; }; +/* Transfer event TRB length bit mask */ +/* bits 0:23 */ +#define EVENT_TRB_LEN(p) ((p) & 0xffffff) + /** Transfer Event bit fields **/ #define TRB_TO_EP_ID(p) (((p) >> 16) & 0x1f) diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c index ac0d75a9005..9f7003e714c 100644 --- a/drivers/usb/misc/appledisplay.c +++ b/drivers/usb/misc/appledisplay.c @@ -63,6 +63,7 @@ static const struct usb_device_id appledisplay_table[] = { { APPLEDISPLAY_DEVICE(0x9219) }, { APPLEDISPLAY_DEVICE(0x921c) }, { APPLEDISPLAY_DEVICE(0x921d) }, + { APPLEDISPLAY_DEVICE(0x9236) }, /* Terminating entry */ { } diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c index dd573abd2d1..7af163da9a7 100644 --- a/drivers/usb/misc/sisusbvga/sisusb.c +++ b/drivers/usb/misc/sisusbvga/sisusb.c @@ -3247,6 +3247,7 @@ static const struct usb_device_id sisusb_table[] = { { USB_DEVICE(0x0711, 0x0903) }, { USB_DEVICE(0x0711, 0x0918) }, { USB_DEVICE(0x0711, 0x0920) }, + { USB_DEVICE(0x0711, 0x0950) }, { USB_DEVICE(0x182d, 0x021c) }, { USB_DEVICE(0x182d, 0x0269) }, { } diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c index f99f47100dd..31bfe604a38 100644 --- a/drivers/usb/serial/ark3116.c +++ b/drivers/usb/serial/ark3116.c @@ -49,7 +49,7 @@ static bool debug; #define DRIVER_NAME "ark3116" /* usb timeout of 1 second */ -#define ARK_TIMEOUT (1*HZ) +#define ARK_TIMEOUT 1000 static const struct usb_device_id id_table[] = { { USB_DEVICE(0x6547, 0x0232) }, diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index f38a2783146..b53065b53fc 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -60,6 +60,7 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x0489, 0xE000) }, /* Pirelli Broadband S.p.A, DP-L10 SIP/GSM Mobile */ { USB_DEVICE(0x0489, 0xE003) }, /* Pirelli Broadband S.p.A, DP-L10 SIP/GSM Mobile */ { USB_DEVICE(0x0745, 0x1000) }, /* CipherLab USB CCD Barcode Scanner 1000 */ + { USB_DEVICE(0x0846, 0x1100) }, /* NetGear Managed Switch M4100 series, M5300 series, M7100 series */ { USB_DEVICE(0x08e6, 0x5501) }, /* Gemalto Prox-PU/CU contactless smartcard reader */ { USB_DEVICE(0x08FD, 0x000A) }, /* Digianswer A/S , ZigBee/802.15.4 MAC Device */ { USB_DEVICE(0x0BED, 0x1100) }, /* MEI (TM) Cashflow-SC Bill/Voucher Acceptor */ @@ -91,6 +92,7 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x10C4, 0x813F) }, /* Tams Master Easy Control */ { USB_DEVICE(0x10C4, 0x814A) }, /* West Mountain Radio RIGblaster P&P */ { USB_DEVICE(0x10C4, 0x814B) }, /* West Mountain Radio RIGtalk */ + { USB_DEVICE(0x2405, 0x0003) }, /* West Mountain Radio RIGblaster Advantage */ { USB_DEVICE(0x10C4, 0x8156) }, /* B&G H3000 link cable */ { USB_DEVICE(0x10C4, 0x815E) }, /* Helicomm IP-Link 1220-DVM */ { USB_DEVICE(0x10C4, 0x815F) }, /* Timewave HamLinkUSB */ @@ -123,6 +125,8 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x10C4, 0x85F8) }, /* Virtenio Preon32 */ { USB_DEVICE(0x10C4, 0x8664) }, /* AC-Services CAN-IF */ { USB_DEVICE(0x10C4, 0x8665) }, /* AC-Services OBD-IF */ + { USB_DEVICE(0x10C4, 0x88A4) }, /* MMB Networks ZigBee USB Device */ + { USB_DEVICE(0x10C4, 0x88A5) }, /* Planet Innovation Ingeni ZigBee USB Device */ { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */ { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */ { USB_DEVICE(0x10C4, 0xEA70) }, /* Silicon Labs factory default */ @@ -153,9 +157,29 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x17F4, 0xAAAA) }, /* Wavesense Jazz blood glucose meter */ { USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */ { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */ + { USB_DEVICE(0x1ADB, 0x0001) }, /* Schweitzer Engineering C662 Cable */ { USB_DEVICE(0x1BE3, 0x07A6) }, /* WAGO 750-923 USB Service Cable */ { USB_DEVICE(0x1E29, 0x0102) }, /* Festo CPX-USB */ { USB_DEVICE(0x1E29, 0x0501) }, /* Festo CMSP */ + { USB_DEVICE(0x1FB9, 0x0100) }, /* Lake Shore Model 121 Current Source */ + { USB_DEVICE(0x1FB9, 0x0200) }, /* Lake Shore Model 218A Temperature Monitor */ + { USB_DEVICE(0x1FB9, 0x0201) }, /* Lake Shore Model 219 Temperature Monitor */ + { USB_DEVICE(0x1FB9, 0x0202) }, /* Lake Shore Model 233 Temperature Transmitter */ + { USB_DEVICE(0x1FB9, 0x0203) }, /* Lake Shore Model 235 Temperature Transmitter */ + { USB_DEVICE(0x1FB9, 0x0300) }, /* Lake Shore Model 335 Temperature Controller */ + { USB_DEVICE(0x1FB9, 0x0301) }, /* Lake Shore Model 336 Temperature Controller */ + { USB_DEVICE(0x1FB9, 0x0302) }, /* Lake Shore Model 350 Temperature Controller */ + { USB_DEVICE(0x1FB9, 0x0303) }, /* Lake Shore Model 371 AC Bridge */ + { USB_DEVICE(0x1FB9, 0x0400) }, /* Lake Shore Model 411 Handheld Gaussmeter */ + { USB_DEVICE(0x1FB9, 0x0401) }, /* Lake Shore Model 425 Gaussmeter */ + { USB_DEVICE(0x1FB9, 0x0402) }, /* Lake Shore Model 455A Gaussmeter */ + { USB_DEVICE(0x1FB9, 0x0403) }, /* Lake Shore Model 475A Gaussmeter */ + { USB_DEVICE(0x1FB9, 0x0404) }, /* Lake Shore Model 465 Three Axis Gaussmeter */ + { USB_DEVICE(0x1FB9, 0x0600) }, /* Lake Shore Model 625A Superconducting MPS */ + { USB_DEVICE(0x1FB9, 0x0601) }, /* Lake Shore Model 642A Magnet Power Supply */ + { USB_DEVICE(0x1FB9, 0x0602) }, /* Lake Shore Model 648 Magnet Power Supply */ + { USB_DEVICE(0x1FB9, 0x0700) }, /* Lake Shore Model 737 VSM Controller */ + { USB_DEVICE(0x1FB9, 0x0701) }, /* Lake Shore Model 776 Hall Matrix */ { USB_DEVICE(0x3195, 0xF190) }, /* Link Instruments MSO-19 */ { USB_DEVICE(0x3195, 0xF280) }, /* Link Instruments MSO-28 */ { USB_DEVICE(0x3195, 0xF281) }, /* Link Instruments MSO-28 */ diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index afc886c75d2..270bda809d8 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c @@ -70,6 +70,7 @@ static const struct usb_device_id id_table_earthmate[] = { static const struct usb_device_id id_table_cyphidcomrs232[] = { { USB_DEVICE(VENDOR_ID_CYPRESS, PRODUCT_ID_CYPHIDCOM) }, { USB_DEVICE(VENDOR_ID_POWERCOM, PRODUCT_ID_UPS) }, + { USB_DEVICE(VENDOR_ID_FRWD, PRODUCT_ID_CYPHIDCOM_FRWD) }, { } /* Terminating entry */ }; @@ -83,6 +84,7 @@ static const struct usb_device_id id_table_combined[] = { { USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB_LT20) }, { USB_DEVICE(VENDOR_ID_CYPRESS, PRODUCT_ID_CYPHIDCOM) }, { USB_DEVICE(VENDOR_ID_POWERCOM, PRODUCT_ID_UPS) }, + { USB_DEVICE(VENDOR_ID_FRWD, PRODUCT_ID_CYPHIDCOM_FRWD) }, { USB_DEVICE(VENDOR_ID_DAZZLE, PRODUCT_ID_CA42) }, { } /* Terminating entry */ }; @@ -243,6 +245,12 @@ static struct usb_serial_driver * const serial_drivers[] = { * Cypress serial helper functions *****************************************************************************/ +/* FRWD Dongle hidcom needs to skip reset and speed checks */ +static inline bool is_frwd(struct usb_device *dev) +{ + return ((le16_to_cpu(dev->descriptor.idVendor) == VENDOR_ID_FRWD) && + (le16_to_cpu(dev->descriptor.idProduct) == PRODUCT_ID_CYPHIDCOM_FRWD)); +} static int analyze_baud_rate(struct usb_serial_port *port, speed_t new_rate) { @@ -252,6 +260,10 @@ static int analyze_baud_rate(struct usb_serial_port *port, speed_t new_rate) if (unstable_bauds) return new_rate; + /* FRWD Dongle uses 115200 bps */ + if (is_frwd(port->serial->dev)) + return new_rate; + /* * The general purpose firmware for the Cypress M8 allows for * a maximum speed of 57600bps (I have no idea whether DeLorme @@ -465,7 +477,11 @@ static int generic_startup(struct usb_serial *serial) } init_waitqueue_head(&priv->delta_msr_wait); - usb_reset_configuration(serial->dev); + /* Skip reset for FRWD device. It is a workaound: + device hangs if it receives SET_CONFIGURE in Configured + state. */ + if (!is_frwd(serial->dev)) + usb_reset_configuration(serial->dev); priv->cmd_ctrl = 0; priv->line_control = 0; diff --git a/drivers/usb/serial/cypress_m8.h b/drivers/usb/serial/cypress_m8.h index 67cf6082688..b461311a2ae 100644 --- a/drivers/usb/serial/cypress_m8.h +++ b/drivers/usb/serial/cypress_m8.h @@ -24,6 +24,10 @@ #define VENDOR_ID_CYPRESS 0x04b4 #define PRODUCT_ID_CYPHIDCOM 0x5500 +/* FRWD Dongle - a GPS sports watch */ +#define VENDOR_ID_FRWD 0x6737 +#define PRODUCT_ID_CYPHIDCOM_FRWD 0x0001 + /* Powercom UPS, chip CY7C63723 */ #define VENDOR_ID_POWERCOM 0x0d9f #define PRODUCT_ID_UPS 0x0002 diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 77469442b3f..3e4c27dd159 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -197,7 +197,10 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_THROTTLE_PID) }, { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_GATEWAY_PID) }, { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_GBM_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_GBM_BOOST_PID) }, { USB_DEVICE(NEWPORT_VID, NEWPORT_AGILIS_PID) }, + { USB_DEVICE(NEWPORT_VID, NEWPORT_CONEX_CC_PID) }, + { USB_DEVICE(NEWPORT_VID, NEWPORT_CONEX_AGP_PID) }, { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) }, { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) }, { USB_DEVICE(FTDI_VID, FTDI_SPROG_II) }, @@ -648,6 +651,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_RM_CANVIEW_PID) }, { USB_DEVICE(ACTON_VID, ACTON_SPECTRAPRO_PID) }, { USB_DEVICE(CONTEC_VID, CONTEC_COM1USBH_PID) }, + { USB_DEVICE(MITSUBISHI_VID, MITSUBISHI_FXUSB_PID) }, { USB_DEVICE(BANDB_VID, BANDB_USOTL4_PID) }, { USB_DEVICE(BANDB_VID, BANDB_USTL4_PID) }, { USB_DEVICE(BANDB_VID, BANDB_USO9ML2_PID) }, @@ -741,9 +745,34 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_NDI_AURORA_SCU_PID), .driver_info = (kernel_ulong_t)&ftdi_NDI_device_quirk }, { USB_DEVICE(TELLDUS_VID, TELLDUS_TELLSTICK_PID) }, - { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_SERIAL_VX7_PID) }, - { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_CT29B_PID) }, - { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_RTS01_PID) }, + { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_S03_PID) }, + { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_59_PID) }, + { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_57A_PID) }, + { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_57B_PID) }, + { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_29A_PID) }, + { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_29B_PID) }, + { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_29F_PID) }, + { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_62B_PID) }, + { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_S01_PID) }, + { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_63_PID) }, + { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_29C_PID) }, + { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_81B_PID) }, + { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_82B_PID) }, + { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_K5D_PID) }, + { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_K4Y_PID) }, + { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_K5G_PID) }, + { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_S05_PID) }, + { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_60_PID) }, + { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_61_PID) }, + { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_62_PID) }, + { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_63B_PID) }, + { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_64_PID) }, + { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_65_PID) }, + { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_92_PID) }, + { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_92D_PID) }, + { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_W5R_PID) }, + { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_A5R_PID) }, + { USB_DEVICE(RTSYSTEMS_VID, RTSYSTEMS_USB_PW1_PID) }, { USB_DEVICE(FTDI_VID, FTDI_MAXSTREAM_PID) }, { USB_DEVICE(FTDI_VID, FTDI_PHI_FISCO_PID) }, { USB_DEVICE(TML_VID, TML_USB_SERIAL_PID) }, @@ -877,7 +906,9 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_DOTEC_PID) }, { USB_DEVICE(QIHARDWARE_VID, MILKYMISTONE_JTAGSERIAL_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, - { USB_DEVICE(ST_VID, ST_STMCLT1030_PID), + { USB_DEVICE(ST_VID, ST_STMCLT_2232_PID), + .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, + { USB_DEVICE(ST_VID, ST_STMCLT_4232_PID), .driver_info = (kernel_ulong_t)&ftdi_stmclite_quirk }, { USB_DEVICE(FTDI_VID, FTDI_RF_R106) }, { USB_DEVICE(FTDI_VID, FTDI_DISTORTEC_JTAG_LOCK_PICK_PID), @@ -1919,24 +1950,22 @@ static void ftdi_dtr_rts(struct usb_serial_port *port, int on) { struct ftdi_private *priv = usb_get_serial_port_data(port); - mutex_lock(&port->serial->disc_mutex); - if (!port->serial->disconnected) { - /* Disable flow control */ - if (!on && usb_control_msg(port->serial->dev, + /* Disable flow control */ + if (!on) { + if (usb_control_msg(port->serial->dev, usb_sndctrlpipe(port->serial->dev, 0), FTDI_SIO_SET_FLOW_CTRL_REQUEST, FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, 0, priv->interface, NULL, 0, WDR_TIMEOUT) < 0) { - dev_err(&port->dev, "error from flowcontrol urb\n"); + dev_err(&port->dev, "error from flowcontrol urb\n"); } - /* drop RTS and DTR */ - if (on) - set_mctrl(port, TIOCM_DTR | TIOCM_RTS); - else - clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); } - mutex_unlock(&port->serial->disc_mutex); + /* drop RTS and DTR */ + if (on) + set_mctrl(port, TIOCM_DTR | TIOCM_RTS); + else + clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); } /* @@ -2169,7 +2198,7 @@ static void ftdi_set_termios(struct tty_struct *tty, cflag = termios->c_cflag; - if (old_termios == 0) + if (!old_termios) goto no_skip; if (old_termios->c_cflag == termios->c_cflag diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 9d359e189a6..1b8af461b52 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -74,6 +74,7 @@ #define FTDI_OPENDCC_THROTTLE_PID 0xBFDA #define FTDI_OPENDCC_GATEWAY_PID 0xBFDB #define FTDI_OPENDCC_GBM_PID 0xBFDC +#define FTDI_OPENDCC_GBM_BOOST_PID 0xBFDD /* NZR SEM 16+ USB (http://www.nzr.de) */ #define FTDI_NZR_SEM_USB_PID 0xC1E0 /* NZR SEM-LOG16+ */ @@ -583,6 +584,13 @@ #define CONTEC_VID 0x06CE /* Vendor ID */ #define CONTEC_COM1USBH_PID 0x8311 /* COM-1(USB)H */ +/* + * Mitsubishi Electric Corp. (http://www.meau.com) + * Submitted by Konstantin Holoborodko + */ +#define MITSUBISHI_VID 0x06D3 +#define MITSUBISHI_FXUSB_PID 0x0284 /* USB/RS422 converters: FX-USB-AW/-BD */ + /* * Definitions for B&B Electronics products. */ @@ -764,6 +772,8 @@ */ #define NEWPORT_VID 0x104D #define NEWPORT_AGILIS_PID 0x3000 +#define NEWPORT_CONEX_CC_PID 0x3002 +#define NEWPORT_CONEX_AGP_PID 0x3006 /* Interbiometrics USB I/O Board */ /* Developed for Interbiometrics by Rudolf Gugler */ @@ -805,11 +815,35 @@ /* * RT Systems programming cables for various ham radios */ -#define RTSYSTEMS_VID 0x2100 /* Vendor ID */ -#define RTSYSTEMS_SERIAL_VX7_PID 0x9e52 /* Serial converter for VX-7 Radios using FT232RL */ -#define RTSYSTEMS_CT29B_PID 0x9e54 /* CT29B Radio Cable */ -#define RTSYSTEMS_RTS01_PID 0x9e57 /* USB-RTS01 Radio Cable */ - +#define RTSYSTEMS_VID 0x2100 /* Vendor ID */ +#define RTSYSTEMS_USB_S03_PID 0x9001 /* RTS-03 USB to Serial Adapter */ +#define RTSYSTEMS_USB_59_PID 0x9e50 /* USB-59 USB to 8 pin plug */ +#define RTSYSTEMS_USB_57A_PID 0x9e51 /* USB-57A USB to 4pin 3.5mm plug */ +#define RTSYSTEMS_USB_57B_PID 0x9e52 /* USB-57B USB to extended 4pin 3.5mm plug */ +#define RTSYSTEMS_USB_29A_PID 0x9e53 /* USB-29A USB to 3.5mm stereo plug */ +#define RTSYSTEMS_USB_29B_PID 0x9e54 /* USB-29B USB to 6 pin mini din */ +#define RTSYSTEMS_USB_29F_PID 0x9e55 /* USB-29F USB to 6 pin modular plug */ +#define RTSYSTEMS_USB_62B_PID 0x9e56 /* USB-62B USB to 8 pin mini din plug*/ +#define RTSYSTEMS_USB_S01_PID 0x9e57 /* USB-RTS01 USB to 3.5 mm stereo plug*/ +#define RTSYSTEMS_USB_63_PID 0x9e58 /* USB-63 USB to 9 pin female*/ +#define RTSYSTEMS_USB_29C_PID 0x9e59 /* USB-29C USB to 4 pin modular plug*/ +#define RTSYSTEMS_USB_81B_PID 0x9e5A /* USB-81 USB to 8 pin mini din plug*/ +#define RTSYSTEMS_USB_82B_PID 0x9e5B /* USB-82 USB to 2.5 mm stereo plug*/ +#define RTSYSTEMS_USB_K5D_PID 0x9e5C /* USB-K5D USB to 8 pin modular plug*/ +#define RTSYSTEMS_USB_K4Y_PID 0x9e5D /* USB-K4Y USB to 2.5/3.5 mm plugs*/ +#define RTSYSTEMS_USB_K5G_PID 0x9e5E /* USB-K5G USB to 8 pin modular plug*/ +#define RTSYSTEMS_USB_S05_PID 0x9e5F /* USB-RTS05 USB to 2.5 mm stereo plug*/ +#define RTSYSTEMS_USB_60_PID 0x9e60 /* USB-60 USB to 6 pin din*/ +#define RTSYSTEMS_USB_61_PID 0x9e61 /* USB-61 USB to 6 pin mini din*/ +#define RTSYSTEMS_USB_62_PID 0x9e62 /* USB-62 USB to 8 pin mini din*/ +#define RTSYSTEMS_USB_63B_PID 0x9e63 /* USB-63 USB to 9 pin female*/ +#define RTSYSTEMS_USB_64_PID 0x9e64 /* USB-64 USB to 9 pin male*/ +#define RTSYSTEMS_USB_65_PID 0x9e65 /* USB-65 USB to 9 pin female null modem*/ +#define RTSYSTEMS_USB_92_PID 0x9e66 /* USB-92 USB to 12 pin plug*/ +#define RTSYSTEMS_USB_92D_PID 0x9e67 /* USB-92D USB to 12 pin plug data*/ +#define RTSYSTEMS_USB_W5R_PID 0x9e68 /* USB-W5R USB to 8 pin modular plug*/ +#define RTSYSTEMS_USB_A5R_PID 0x9e69 /* USB-A5R USB to 8 pin modular plug*/ +#define RTSYSTEMS_USB_PW1_PID 0x9e6A /* USB-PW1 USB to 8 pin modular plug*/ /* * Physik Instrumente @@ -1143,7 +1177,8 @@ * STMicroelectonics */ #define ST_VID 0x0483 -#define ST_STMCLT1030_PID 0x3747 /* ST Micro Connect Lite STMCLT1030 */ +#define ST_STMCLT_2232_PID 0x3746 +#define ST_STMCLT_4232_PID 0x3747 /* * Papouch products (http://www.papouch.com/) diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c index e8eb6347bf3..ba5b527957e 100644 --- a/drivers/usb/serial/garmin_gps.c +++ b/drivers/usb/serial/garmin_gps.c @@ -971,10 +971,7 @@ static void garmin_close(struct usb_serial_port *port) if (!serial) return; - mutex_lock(&port->serial->disc_mutex); - - if (!port->serial->disconnected) - garmin_clear(garmin_data_p); + garmin_clear(garmin_data_p); /* shutdown our urbs */ usb_kill_urb(port->read_urb); @@ -983,8 +980,6 @@ static void garmin_close(struct usb_serial_port *port) /* keep reset state so we know that we must start a new session */ if (garmin_data_p->state != STATE_RESET) garmin_data_p->state = STATE_DISCONNECTED; - - mutex_unlock(&port->serial->disc_mutex); } diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index 40a95a7fe38..b68efdc38ef 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -550,6 +550,9 @@ static void chase_port(struct edgeport_port *port, unsigned long timeout, wait_queue_t wait; unsigned long flags; + if (!tty) + return; + if (!timeout) timeout = (HZ * EDGE_CLOSING_WAIT)/100; @@ -2770,6 +2773,7 @@ static struct usb_serial_driver edgeport_2port_device = { .set_termios = edge_set_termios, .tiocmget = edge_tiocmget, .tiocmset = edge_tiocmset, + .get_icount = edge_get_icount, .write = edge_write, .write_room = edge_write_room, .chars_in_buffer = edge_chars_in_buffer, diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c index f2192d527db..53c639c261c 100644 --- a/drivers/usb/serial/iuu_phoenix.c +++ b/drivers/usb/serial/iuu_phoenix.c @@ -326,7 +326,7 @@ static int bulk_immediate(struct usb_serial_port *port, u8 *buf, u8 count) usb_bulk_msg(serial->dev, usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress), buf, - count, &actual, HZ * 1); + count, &actual, 1000); if (status != IUU_OPERATION_OK) dbg("%s - error = %2x", __func__, status); @@ -349,7 +349,7 @@ static int read_immediate(struct usb_serial_port *port, u8 *buf, u8 count) usb_bulk_msg(serial->dev, usb_rcvbulkpipe(serial->dev, port->bulk_in_endpointAddress), buf, - count, &actual, HZ * 1); + count, &actual, 1000); if (status != IUU_OPERATION_OK) dbg("%s - error = %2x", __func__, status); diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index a39ddd1b0dc..253bff67db0 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -1705,7 +1705,7 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial, d_details = s_priv->device_details; device_port = port->number - port->serial->minor; - outcont_urb = d_details->outcont_endpoints[port->number]; + outcont_urb = d_details->outcont_endpoints[device_port]; this_urb = p_priv->outcont_urb; dbg("%s - endpoint %d", __func__, usb_pipeendpoint(this_urb->pipe)); diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index d0bf56dba07..933dd07aa08 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -514,19 +514,15 @@ static void mct_u232_dtr_rts(struct usb_serial_port *port, int on) unsigned int control_state; struct mct_u232_private *priv = usb_get_serial_port_data(port); - mutex_lock(&port->serial->disc_mutex); - if (!port->serial->disconnected) { - /* drop DTR and RTS */ - spin_lock_irq(&priv->lock); - if (on) - priv->control_state |= TIOCM_DTR | TIOCM_RTS; - else - priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS); - control_state = priv->control_state; - spin_unlock_irq(&priv->lock); - mct_u232_set_modem_ctrl(port->serial, control_state); - } - mutex_unlock(&port->serial->disc_mutex); + spin_lock_irq(&priv->lock); + if (on) + priv->control_state |= TIOCM_DTR | TIOCM_RTS; + else + priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS); + control_state = priv->control_state; + spin_unlock_irq(&priv->lock); + + mct_u232_set_modem_ctrl(port->serial, control_state); } static void mct_u232_close(struct usb_serial_port *port) diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index bdce8203412..cdde45dee67 100644 --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c @@ -44,7 +44,7 @@ #define DRIVER_DESC "Moschip USB Serial Driver" /* default urb timeout */ -#define MOS_WDR_TIMEOUT (HZ * 5) +#define MOS_WDR_TIMEOUT 5000 #define MOS_MAX_PORT 0x02 #define MOS_WRITE 0x0E @@ -97,6 +97,7 @@ struct urbtracker { struct list_head urblist_entry; struct kref ref_count; struct urb *urb; + struct usb_ctrlrequest *setup; }; enum mos7715_pp_modes { @@ -234,11 +235,22 @@ static int read_mos_reg(struct usb_serial *serial, unsigned int serial_portnum, __u8 requesttype = (__u8)0xc0; __u16 index = get_reg_index(reg); __u16 value = get_reg_value(reg, serial_portnum); - int status = usb_control_msg(usbdev, pipe, request, requesttype, value, - index, data, 1, MOS_WDR_TIMEOUT); - if (status < 0) + u8 *buf; + int status; + + buf = kmalloc(1, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + status = usb_control_msg(usbdev, pipe, request, requesttype, value, + index, buf, 1, MOS_WDR_TIMEOUT); + if (status == 1) + *data = *buf; + else if (status < 0) dev_err(&usbdev->dev, "mos7720: usb_control_msg() failed: %d", status); + kfree(buf); + return status; } @@ -268,6 +280,7 @@ static void destroy_urbtracker(struct kref *kref) struct mos7715_parport *mos_parport = urbtrack->mos_parport; dbg("%s called", __func__); usb_free_urb(urbtrack->urb); + kfree(urbtrack->setup); kfree(urbtrack); kref_put(&mos_parport->ref_count, destroy_mos_parport); } @@ -352,7 +365,6 @@ static int write_parport_reg_nonblock(struct mos7715_parport *mos_parport, struct urbtracker *urbtrack; int ret_val; unsigned long flags; - struct usb_ctrlrequest setup; struct usb_serial *serial = mos_parport->serial; struct usb_device *usbdev = serial->dev; dbg("%s called", __func__); @@ -371,14 +383,20 @@ static int write_parport_reg_nonblock(struct mos7715_parport *mos_parport, kfree(urbtrack); return -ENOMEM; } - setup.bRequestType = (__u8)0x40; - setup.bRequest = (__u8)0x0e; - setup.wValue = get_reg_value(reg, dummy); - setup.wIndex = get_reg_index(reg); - setup.wLength = 0; + urbtrack->setup = kmalloc(sizeof(*urbtrack->setup), GFP_KERNEL); + if (!urbtrack->setup) { + usb_free_urb(urbtrack->urb); + kfree(urbtrack); + return -ENOMEM; + } + urbtrack->setup->bRequestType = (__u8)0x40; + urbtrack->setup->bRequest = (__u8)0x0e; + urbtrack->setup->wValue = get_reg_value(reg, dummy); + urbtrack->setup->wIndex = get_reg_index(reg); + urbtrack->setup->wLength = 0; usb_fill_control_urb(urbtrack->urb, usbdev, usb_sndctrlpipe(usbdev, 0), - (unsigned char *)&setup, + (unsigned char *)urbtrack->setup, NULL, 0, async_complete, urbtrack); kref_init(&urbtrack->ref_count); INIT_LIST_HEAD(&urbtrack->urblist_entry); @@ -1690,7 +1708,7 @@ static void change_port_settings(struct tty_struct *tty, mos7720_port->shadowMCR |= (UART_MCR_XONANY); /* To set hardware flow control to the specified * * serial port, in SP1/2_CONTROL_REG */ - if (port->number) + if (port_number) write_mos_reg(serial, dummy, SP_CONTROL_REG, 0x01); else write_mos_reg(serial, dummy, SP_CONTROL_REG, 0x02); @@ -2094,7 +2112,7 @@ static int mos7720_startup(struct usb_serial *serial) /* setting configuration feature to one */ usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), - (__u8)0x03, 0x00, 0x01, 0x00, NULL, 0x00, 5*HZ); + (__u8)0x03, 0x00, 0x01, 0x00, NULL, 0x00, 5000); /* start the interrupt urb */ ret_val = usb_submit_urb(serial->port[0]->interrupt_in_urb, GFP_KERNEL); @@ -2139,7 +2157,7 @@ static void mos7720_release(struct usb_serial *serial) /* wait for synchronous usb calls to return */ if (mos_parport->msg_pending) wait_for_completion_timeout(&mos_parport->syncmsg_compl, - MOS_WDR_TIMEOUT); + msecs_to_jiffies(MOS_WDR_TIMEOUT)); parport_remove_port(mos_parport->pp); usb_set_serial_data(serial, NULL); diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 6c077a174bf..a37f14ce52f 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -159,8 +159,6 @@ static void option_instat_callback(struct urb *urb); #define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_FULLSPEED 0x9000 #define NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_HIGHSPEED 0x9001 #define NOVATELWIRELESS_PRODUCT_E362 0x9010 -#define NOVATELWIRELESS_PRODUCT_G1 0xA001 -#define NOVATELWIRELESS_PRODUCT_G1_M 0xA002 #define NOVATELWIRELESS_PRODUCT_G2 0xA010 #define NOVATELWIRELESS_PRODUCT_MC551 0xB001 @@ -196,6 +194,7 @@ static void option_instat_callback(struct urb *urb); #define DELL_PRODUCT_5800_MINICARD_VZW 0x8195 /* Novatel E362 */ #define DELL_PRODUCT_5800_V2_MINICARD_VZW 0x8196 /* Novatel E362 */ +#define DELL_PRODUCT_5804_MINICARD_ATT 0x819b /* Novatel E371 */ #define KYOCERA_VENDOR_ID 0x0c88 #define KYOCERA_PRODUCT_KPC650 0x17da @@ -341,21 +340,19 @@ static void option_instat_callback(struct urb *urb); #define CINTERION_PRODUCT_EU3_E 0x0051 #define CINTERION_PRODUCT_EU3_P 0x0052 #define CINTERION_PRODUCT_PH8 0x0053 +#define CINTERION_PRODUCT_AHXX 0x0055 +#define CINTERION_PRODUCT_PLXX 0x0060 /* Olivetti products */ #define OLIVETTI_VENDOR_ID 0x0b3c #define OLIVETTI_PRODUCT_OLICARD100 0xc000 +#define OLIVETTI_PRODUCT_OLICARD145 0xc003 +#define OLIVETTI_PRODUCT_OLICARD200 0xc005 /* Celot products */ #define CELOT_VENDOR_ID 0x211f #define CELOT_PRODUCT_CT680M 0x6801 -/* ONDA Communication vendor id */ -#define ONDA_VENDOR_ID 0x1ee8 - -/* ONDA MT825UP HSDPA 14.2 modem */ -#define ONDA_MT825UP 0x000b - /* Samsung products */ #define SAMSUNG_VENDOR_ID 0x04e8 #define SAMSUNG_PRODUCT_GT_B3730 0x6889 @@ -448,7 +445,8 @@ static void option_instat_callback(struct urb *urb); /* Hyundai Petatel Inc. products */ #define PETATEL_VENDOR_ID 0x1ff4 -#define PETATEL_PRODUCT_NP10T 0x600e +#define PETATEL_PRODUCT_NP10T_600A 0x600a +#define PETATEL_PRODUCT_NP10T_600E 0x600e /* TP-LINK Incorporated products */ #define TPLINK_VENDOR_ID 0x2357 @@ -479,6 +477,7 @@ static const struct option_blacklist_info four_g_w14_blacklist = { static const struct option_blacklist_info alcatel_x200_blacklist = { .sendsetup = BIT(0) | BIT(1), + .reserved = BIT(4), }; static const struct option_blacklist_info zte_0037_blacklist = { @@ -575,12 +574,21 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GLX) }, { USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GKE) }, { USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GLE) }, + { USB_DEVICE(QUANTA_VENDOR_ID, 0xea42), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x1c05, USB_CLASS_COMM, 0x02, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x1c1f, USB_CLASS_COMM, 0x02, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x1c23, USB_CLASS_COMM, 0x02, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E173, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t) &net_intf1_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x1441, USB_CLASS_COMM, 0x02, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x1442, USB_CLASS_COMM, 0x02, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4505, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t) &huawei_cdc12_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K3765, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t) &huawei_cdc12_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x14ac, 0xff, 0xff, 0xff), /* Huawei E1820 */ + .driver_info = (kernel_ulong_t) &net_intf1_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4605, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t) &huawei_cdc12_blacklist }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0xff, 0xff) }, @@ -730,8 +738,6 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC547) }, { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_HIGHSPEED) }, { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_EMBEDDED_HIGHSPEED) }, - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_G1) }, - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_G1_M) }, { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_G2) }, /* Novatel Ovation MC551 a.k.a. Verizon USB551L */ { USB_DEVICE_AND_INTERFACE_INFO(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC551, 0xff, 0xff, 0xff) }, @@ -760,6 +766,7 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_VZW) }, /* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */ { USB_DEVICE_AND_INTERFACE_INFO(DELL_VENDOR_ID, DELL_PRODUCT_5800_MINICARD_VZW, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(DELL_VENDOR_ID, DELL_PRODUCT_5800_V2_MINICARD_VZW, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(DELL_VENDOR_ID, DELL_PRODUCT_5804_MINICARD_ATT, 0xff, 0xff, 0xff) }, { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_E100A) }, /* ADU-E100, ADU-310 */ { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_500A) }, { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_620UW) }, @@ -786,6 +793,7 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC680) }, { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6000)}, /* ZTE AC8700 */ { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */ + { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x0023)}, /* ONYX 3G device */ { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x9000)}, /* SIMCom SIM5218 */ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6280) }, /* BP3-USB & BP3-EXT HSDPA */ { USB_DEVICE(CMOTECH_VENDOR_ID, CMOTECH_PRODUCT_6008) }, @@ -821,7 +829,8 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0017, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0018, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0019, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0019, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0020, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0021, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, @@ -955,6 +964,8 @@ static const struct usb_device_id option_ids[] = { .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0330, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0395, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0412, 0xff, 0xff, 0xff), /* Telewell TW-LTE 4G */ + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0414, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0417, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1008, 0xff, 0xff, 0xff), @@ -1215,7 +1226,14 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S_X200), .driver_info = (kernel_ulong_t)&alcatel_x200_blacklist }, - { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X220_X500D) }, + { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X220_X500D), + .driver_info = (kernel_ulong_t)&net_intf6_blacklist }, + { USB_DEVICE(ALCATEL_VENDOR_ID, 0x0052), + .driver_info = (kernel_ulong_t)&net_intf6_blacklist }, + { USB_DEVICE(ALCATEL_VENDOR_ID, 0x00b6), + .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, + { USB_DEVICE(ALCATEL_VENDOR_ID, 0x00b7), + .driver_info = (kernel_ulong_t)&net_intf5_blacklist }, { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_L100V), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) }, @@ -1246,6 +1264,9 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_E) }, { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_P) }, { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PH8) }, + { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_AHXX) }, + { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PLXX), + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_HC28_MDM) }, { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_HC28_MDMNET) }, { USB_DEVICE(SIEMENS_VENDOR_ID, CINTERION_PRODUCT_HC25_MDM) }, @@ -1254,8 +1275,9 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(SIEMENS_VENDOR_ID, CINTERION_PRODUCT_HC28_MDMNET) }, { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD100) }, + { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD145) }, + { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD200) }, { USB_DEVICE(CELOT_VENDOR_ID, CELOT_PRODUCT_CT680M) }, /* CT-650 CDMA 450 1xEVDO modem */ - { USB_DEVICE(ONDA_VENDOR_ID, ONDA_MT825UP) }, /* ONDA MT825UP modem */ { USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_GT_B3730, USB_CLASS_CDC_DATA, 0x00, 0x00) }, /* Samsung GT-B3730 LTE USB modem.*/ { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEM600) }, { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEM610) }, @@ -1327,10 +1349,21 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_4COM2, 0xff, 0x02, 0x01) }, { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_4COM2, 0xff, 0x00, 0x00) }, { USB_DEVICE(CELLIENT_VENDOR_ID, CELLIENT_PRODUCT_MEN200) }, - { USB_DEVICE(PETATEL_VENDOR_ID, PETATEL_PRODUCT_NP10T) }, + { USB_DEVICE(PETATEL_VENDOR_ID, PETATEL_PRODUCT_NP10T_600A) }, + { USB_DEVICE(PETATEL_VENDOR_ID, PETATEL_PRODUCT_NP10T_600E) }, { USB_DEVICE(TPLINK_VENDOR_ID, TPLINK_PRODUCT_MA180), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, + { USB_DEVICE(TPLINK_VENDOR_ID, 0x9000), /* TP-Link MA260 */ + .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE(CHANGHONG_VENDOR_ID, CHANGHONG_PRODUCT_CH690) }, + { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d01, 0xff, 0x02, 0x01) }, /* D-Link DWM-156 (variant) */ + { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d01, 0xff, 0x00, 0x00) }, /* D-Link DWM-156 (variant) */ + { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d02, 0xff, 0x02, 0x01) }, + { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d02, 0xff, 0x00, 0x00) }, + { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d03, 0xff, 0x02, 0x01) }, + { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d03, 0xff, 0x00, 0x00) }, + { USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3e01, 0xff, 0xff, 0xff) }, /* D-Link DWM-152/C1 */ + { USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3e02, 0xff, 0xff, 0xff) }, /* D-Link DWM-156/C1 */ { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, option_ids); diff --git a/drivers/usb/serial/qcaux.c b/drivers/usb/serial/qcaux.c index b223381da32..018f1030d78 100644 --- a/drivers/usb/serial/qcaux.c +++ b/drivers/usb/serial/qcaux.c @@ -69,6 +69,7 @@ static struct usb_device_id id_table[] = { { USB_VENDOR_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, 0xff, 0xfd, 0xff) }, /* NMEA */ { USB_VENDOR_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, 0xff, 0xfe, 0xff) }, /* WMC */ { USB_VENDOR_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, 0xff, 0xff, 0xff) }, /* DIAG */ + { USB_DEVICE_AND_INTERFACE_INFO(0x1fac, 0x0151, 0xff, 0xff, 0xff) }, { }, }; MODULE_DEVICE_TABLE(usb, id_table); diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index bd38e0e31e5..b4ac0e62494 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c @@ -37,7 +37,13 @@ static const struct usb_device_id id_table[] = { {DEVICE_G1K(0x04da, 0x250c)}, /* Panasonic Gobi QDL device */ {DEVICE_G1K(0x413c, 0x8172)}, /* Dell Gobi Modem device */ {DEVICE_G1K(0x413c, 0x8171)}, /* Dell Gobi QDL device */ - {DEVICE_G1K(0x1410, 0xa001)}, /* Novatel Gobi Modem device */ + {DEVICE_G1K(0x1410, 0xa001)}, /* Novatel/Verizon USB-1000 */ + {DEVICE_G1K(0x1410, 0xa002)}, /* Novatel Gobi Modem device */ + {DEVICE_G1K(0x1410, 0xa003)}, /* Novatel Gobi Modem device */ + {DEVICE_G1K(0x1410, 0xa004)}, /* Novatel Gobi Modem device */ + {DEVICE_G1K(0x1410, 0xa005)}, /* Novatel Gobi Modem device */ + {DEVICE_G1K(0x1410, 0xa006)}, /* Novatel Gobi Modem device */ + {DEVICE_G1K(0x1410, 0xa007)}, /* Novatel Gobi Modem device */ {DEVICE_G1K(0x1410, 0xa008)}, /* Novatel Gobi QDL device */ {DEVICE_G1K(0x0b05, 0x1776)}, /* Asus Gobi Modem device */ {DEVICE_G1K(0x0b05, 0x1774)}, /* Asus Gobi QDL device */ diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index b622d695fdb..8ec15c2540b 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -890,19 +890,13 @@ static int sierra_open(struct tty_struct *tty, struct usb_serial_port *port) static void sierra_dtr_rts(struct usb_serial_port *port, int on) { - struct usb_serial *serial = port->serial; struct sierra_port_private *portdata; portdata = usb_get_serial_port_data(port); portdata->rts_state = on; portdata->dtr_state = on; - if (serial->dev) { - mutex_lock(&serial->disc_mutex); - if (!serial->disconnected) - sierra_send_setup(port); - mutex_unlock(&serial->disc_mutex); - } + sierra_send_setup(port); } static int sierra_startup(struct usb_serial *serial) diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c index 3cdc8a52de4..b8db69d96df 100644 --- a/drivers/usb/serial/ssu100.c +++ b/drivers/usb/serial/ssu100.c @@ -532,19 +532,16 @@ static void ssu100_dtr_rts(struct usb_serial_port *port, int on) dbg("%s\n", __func__); - mutex_lock(&port->serial->disc_mutex); - if (!port->serial->disconnected) { - /* Disable flow control */ - if (!on && - ssu100_setregister(dev, 0, UART_MCR, 0) < 0) + /* Disable flow control */ + if (!on) { + if (ssu100_setregister(dev, 0, UART_MCR, 0) < 0) dev_err(&port->dev, "error from flowcontrol urb\n"); - /* drop RTS and DTR */ - if (on) - set_mctrl(dev, TIOCM_DTR | TIOCM_RTS); - else - clear_mctrl(dev, TIOCM_DTR | TIOCM_RTS); } - mutex_unlock(&port->serial->disc_mutex); + /* drop RTS and DTR */ + if (on) + set_mctrl(dev, TIOCM_DTR | TIOCM_RTS); + else + clear_mctrl(dev, TIOCM_DTR | TIOCM_RTS); } static void ssu100_update_msr(struct usb_serial_port *port, u8 msr) diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index 3377437550d..a7492ba5371 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -179,7 +179,8 @@ static struct usb_device_id ti_id_table_3410[15+TI_EXTRA_VID_PID_COUNT+1] = { { USB_DEVICE(IBM_VENDOR_ID, IBM_4543_PRODUCT_ID) }, { USB_DEVICE(IBM_VENDOR_ID, IBM_454B_PRODUCT_ID) }, { USB_DEVICE(IBM_VENDOR_ID, IBM_454C_PRODUCT_ID) }, - { USB_DEVICE(ABBOTT_VENDOR_ID, ABBOTT_PRODUCT_ID) }, + { USB_DEVICE(ABBOTT_VENDOR_ID, ABBOTT_STEREO_PLUG_ID) }, + { USB_DEVICE(ABBOTT_VENDOR_ID, ABBOTT_STRIP_PORT_ID) }, { USB_DEVICE(TI_VENDOR_ID, FRI2_PRODUCT_ID) }, }; @@ -389,7 +390,7 @@ static int ti_startup(struct usb_serial *serial) usb_set_serial_data(serial, tdev); /* determine device type */ - if (usb_match_id(serial->interface, ti_id_table_3410)) + if (serial->type == &ti_1port_device) tdev->td_is_3410 = 1; dbg("%s - device type is %s", __func__, tdev->td_is_3410 ? "3410" : "5052"); diff --git a/drivers/usb/serial/ti_usb_3410_5052.h b/drivers/usb/serial/ti_usb_3410_5052.h index b353e7e3d48..4a2423e84d5 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.h +++ b/drivers/usb/serial/ti_usb_3410_5052.h @@ -52,7 +52,9 @@ /* Abbott Diabetics vendor and product ids */ #define ABBOTT_VENDOR_ID 0x1a61 -#define ABBOTT_PRODUCT_ID 0x3410 +#define ABBOTT_STEREO_PLUG_ID 0x3410 +#define ABBOTT_PRODUCT_ID ABBOTT_STEREO_PLUG_ID +#define ABBOTT_STRIP_PORT_ID 0x3420 /* Commands */ #define TI_GET_VERSION 0x01 diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index c627ba21b1e..810695b3b4e 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -168,6 +168,7 @@ static void destroy_serial(struct kref *kref) } } + usb_put_intf(serial->interface); usb_put_dev(serial->dev); kfree(serial); } @@ -625,7 +626,7 @@ static struct usb_serial *create_serial(struct usb_device *dev, } serial->dev = usb_get_dev(dev); serial->type = driver; - serial->interface = interface; + serial->interface = usb_get_intf(interface); kref_init(&serial->kref); mutex_init(&serial->disc_mutex); serial->minor = SERIAL_TTY_NO_MINOR; @@ -699,10 +700,20 @@ static int serial_carrier_raised(struct tty_port *port) static void serial_dtr_rts(struct tty_port *port, int on) { struct usb_serial_port *p = container_of(port, struct usb_serial_port, port); - struct usb_serial_driver *drv = p->serial->type; + struct usb_serial *serial = p->serial; + struct usb_serial_driver *drv = serial->type; - if (drv->dtr_rts) + if (!drv->dtr_rts) + return; + /* + * Work-around bug in the tty-layer which can result in dtr_rts + * being called after a disconnect (and tty_unregister_device + * has returned). Remove once bug has been squashed. + */ + mutex_lock(&serial->disc_mutex); + if (!serial->disconnected) drv->dtr_rts(p, on); + mutex_unlock(&serial->disc_mutex); } static const struct tty_port_operations serial_port_ops = { diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c index 0d05e2f238e..c0f782e27e1 100644 --- a/drivers/usb/serial/usb_wwan.c +++ b/drivers/usb/serial/usb_wwan.c @@ -41,7 +41,6 @@ static bool debug; void usb_wwan_dtr_rts(struct usb_serial_port *port, int on) { - struct usb_serial *serial = port->serial; struct usb_wwan_port_private *portdata; struct usb_wwan_intf_private *intfdata; @@ -54,12 +53,11 @@ void usb_wwan_dtr_rts(struct usb_serial_port *port, int on) return; portdata = usb_get_serial_port_data(port); - mutex_lock(&serial->disc_mutex); + /* FIXME: locking */ portdata->rts_state = on; portdata->dtr_state = on; - if (serial->dev) - intfdata->send_setup(port); - mutex_unlock(&serial->disc_mutex); + + intfdata->send_setup(port); } EXPORT_SYMBOL(usb_wwan_dtr_rts); diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c index 71d696474f2..b3afd19341f 100644 --- a/drivers/usb/serial/visor.c +++ b/drivers/usb/serial/visor.c @@ -596,10 +596,19 @@ static int treo_attach(struct usb_serial *serial) */ #define COPY_PORT(dest, src) \ do { \ + int i; \ + \ + for (i = 0; i < ARRAY_SIZE(src->read_urbs); ++i) { \ + dest->read_urbs[i] = src->read_urbs[i]; \ + dest->read_urbs[i]->context = dest; \ + dest->bulk_in_buffers[i] = src->bulk_in_buffers[i]; \ + } \ dest->read_urb = src->read_urb; \ dest->bulk_in_endpointAddress = src->bulk_in_endpointAddress;\ dest->bulk_in_buffer = src->bulk_in_buffer; \ + dest->bulk_in_size = src->bulk_in_size; \ dest->interrupt_in_urb = src->interrupt_in_urb; \ + dest->interrupt_in_urb->context = dest; \ dest->interrupt_in_endpointAddress = \ src->interrupt_in_endpointAddress;\ dest->interrupt_in_buffer = src->interrupt_in_buffer; \ diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index 171226ab56f..0d06d7ca86f 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c @@ -1154,7 +1154,7 @@ static void firm_setup_port(struct tty_struct *tty) struct whiteheat_port_settings port_settings; unsigned int cflag = tty->termios->c_cflag; - port_settings.port = port->number + 1; + port_settings.port = port->number - port->serial->minor + 1; /* get the byte size */ switch (cflag & CSIZE) { diff --git a/drivers/usb/storage/cypress_atacb.c b/drivers/usb/storage/cypress_atacb.c index 5fe451d16e6..c1f67515b59 100644 --- a/drivers/usb/storage/cypress_atacb.c +++ b/drivers/usb/storage/cypress_atacb.c @@ -248,14 +248,26 @@ static int cypress_probe(struct usb_interface *intf, { struct us_data *us; int result; + struct usb_device *device; result = usb_stor_probe1(&us, intf, id, (id - cypress_usb_ids) + cypress_unusual_dev_list); if (result) return result; - us->protocol_name = "Transparent SCSI with Cypress ATACB"; - us->proto_handler = cypress_atacb_passthrough; + /* Among CY7C68300 chips, the A revision does not support Cypress ATACB + * Filter out this revision from EEPROM default descriptor values + */ + device = interface_to_usbdev(intf); + if (device->descriptor.iManufacturer != 0x38 || + device->descriptor.iProduct != 0x4e || + device->descriptor.iSerialNumber != 0x64) { + us->protocol_name = "Transparent SCSI with Cypress ATACB"; + us->proto_handler = cypress_atacb_passthrough; + } else { + us->protocol_name = "Transparent SCSI"; + us->proto_handler = usb_stor_transparent_scsi_command; + } result = usb_stor_probe2(us); return result; diff --git a/drivers/usb/storage/initializers.c b/drivers/usb/storage/initializers.c index 16b0bf055ee..105d900150c 100644 --- a/drivers/usb/storage/initializers.c +++ b/drivers/usb/storage/initializers.c @@ -92,8 +92,8 @@ int usb_stor_ucr61s2b_init(struct us_data *us) return 0; } -/* This places the HUAWEI usb dongles in multi-port mode */ -static int usb_stor_huawei_feature_init(struct us_data *us) +/* This places the HUAWEI E220 devices in multi-port mode */ +int usb_stor_huawei_e220_init(struct us_data *us) { int result; @@ -104,75 +104,3 @@ static int usb_stor_huawei_feature_init(struct us_data *us) US_DEBUGP("Huawei mode set result is %d\n", result); return 0; } - -/* - * It will send a scsi switch command called rewind' to huawei dongle. - * When the dongle receives this command at the first time, - * it will reboot immediately. After rebooted, it will ignore this command. - * So it is unnecessary to read its response. - */ -static int usb_stor_huawei_scsi_init(struct us_data *us) -{ - int result = 0; - int act_len = 0; - struct bulk_cb_wrap *bcbw = (struct bulk_cb_wrap *) us->iobuf; - char rewind_cmd[] = {0x11, 0x06, 0x20, 0x00, 0x00, 0x01, 0x01, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - - bcbw->Signature = cpu_to_le32(US_BULK_CB_SIGN); - bcbw->Tag = 0; - bcbw->DataTransferLength = 0; - bcbw->Flags = bcbw->Lun = 0; - bcbw->Length = sizeof(rewind_cmd); - memset(bcbw->CDB, 0, sizeof(bcbw->CDB)); - memcpy(bcbw->CDB, rewind_cmd, sizeof(rewind_cmd)); - - result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, bcbw, - US_BULK_CB_WRAP_LEN, &act_len); - US_DEBUGP("transfer actual length=%d, result=%d\n", act_len, result); - return result; -} - -/* - * It tries to find the supported Huawei USB dongles. - * In Huawei, they assign the following product IDs - * for all of their mobile broadband dongles, - * including the new dongles in the future. - * So if the product ID is not included in this list, - * it means it is not Huawei's mobile broadband dongles. - */ -static int usb_stor_huawei_dongles_pid(struct us_data *us) -{ - struct usb_interface_descriptor *idesc; - int idProduct; - - idesc = &us->pusb_intf->cur_altsetting->desc; - idProduct = us->pusb_dev->descriptor.idProduct; - /* The first port is CDROM, - * means the dongle in the single port mode, - * and a switch command is required to be sent. */ - if (idesc && idesc->bInterfaceNumber == 0) { - if ((idProduct == 0x1001) - || (idProduct == 0x1003) - || (idProduct == 0x1004) - || (idProduct >= 0x1401 && idProduct <= 0x1500) - || (idProduct >= 0x1505 && idProduct <= 0x1600) - || (idProduct >= 0x1c02 && idProduct <= 0x2202)) { - return 1; - } - } - return 0; -} - -int usb_stor_huawei_init(struct us_data *us) -{ - int result = 0; - - if (usb_stor_huawei_dongles_pid(us)) { - if (us->pusb_dev->descriptor.idProduct >= 0x1446) - result = usb_stor_huawei_scsi_init(us); - else - result = usb_stor_huawei_feature_init(us); - } - return result; -} diff --git a/drivers/usb/storage/initializers.h b/drivers/usb/storage/initializers.h index 5376d4fc76f..529327fbb06 100644 --- a/drivers/usb/storage/initializers.h +++ b/drivers/usb/storage/initializers.h @@ -46,5 +46,5 @@ int usb_stor_euscsi_init(struct us_data *us); * flash reader */ int usb_stor_ucr61s2b_init(struct us_data *us); -/* This places the HUAWEI usb dongles in multi-port mode */ -int usb_stor_huawei_init(struct us_data *us); +/* This places the HUAWEI E220 devices in multi-port mode */ +int usb_stor_huawei_e220_init(struct us_data *us); diff --git a/drivers/usb/storage/unusual_cypress.h b/drivers/usb/storage/unusual_cypress.h index 2c855302622..65a6a75066a 100644 --- a/drivers/usb/storage/unusual_cypress.h +++ b/drivers/usb/storage/unusual_cypress.h @@ -31,7 +31,7 @@ UNUSUAL_DEV( 0x04b4, 0x6831, 0x0000, 0x9999, "Cypress ISD-300LP", USB_SC_CYP_ATACB, USB_PR_DEVICE, NULL, 0), -UNUSUAL_DEV( 0x14cd, 0x6116, 0x0000, 0x9999, +UNUSUAL_DEV( 0x14cd, 0x6116, 0x0000, 0x0219, "Super Top", "USB 2.0 SATA BRIDGE", USB_SC_CYP_ATACB, USB_PR_DEVICE, NULL, 0), diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 27858f9a20e..cf442e012da 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -488,6 +488,13 @@ UNUSUAL_DEV( 0x04e8, 0x5122, 0x0000, 0x9999, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_MAX_SECTORS_64 | US_FL_BULK_IGNORE_TAG), +/* Added by Dmitry Artamonow */ +UNUSUAL_DEV( 0x04e8, 0x5136, 0x0000, 0x9999, + "Samsung", + "YP-Z3", + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_MAX_SECTORS_64), + /* Entry and supporting patch by Theodore Kilgore . * Device uses standards-violating 32-byte Bulk Command Block Wrappers and * reports itself as "Proprietary SCSI Bulk." Cf. device entry 0x084d:0x0011. @@ -650,6 +657,13 @@ UNUSUAL_DEV( 0x054c, 0x016a, 0x0000, 0x9999, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_FIX_INQUIRY ), +/* Submitted by Ren Bigcren */ +UNUSUAL_DEV( 0x054c, 0x02a5, 0x0100, 0x0100, + "Sony Corp.", + "MicroVault Flash Drive", + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_NO_READ_CAPACITY_16 ), + /* floppy reports multiple luns */ UNUSUAL_DEV( 0x055d, 0x2020, 0x0000, 0x0210, "SAMSUNG", @@ -1515,10 +1529,335 @@ UNUSUAL_DEV( 0x1210, 0x0003, 0x0100, 0x0100, /* Reported by fangxiaozhi * This brings the HUAWEI data card devices into multi-port mode */ -UNUSUAL_VENDOR_INTF(0x12d1, 0x08, 0x06, 0x50, +UNUSUAL_DEV( 0x12d1, 0x1001, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x1003, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x1004, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x1401, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x1402, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x1403, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x1404, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x1405, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x1406, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x1407, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x1408, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x1409, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x140A, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x140B, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x140C, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x140D, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x140E, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x140F, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x1410, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x1411, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x1412, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x1413, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x1414, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x1415, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x1416, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x1417, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x1418, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x1419, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x141A, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x141B, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x141C, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x141D, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x141E, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x141F, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x1420, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x1421, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x1422, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x1423, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x1424, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x1425, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x1426, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x1427, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x1428, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x1429, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x142A, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x142B, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x142C, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x142D, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x142E, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x142F, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x1430, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x1431, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x1432, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x1433, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x1434, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x1435, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x1436, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x1437, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x1438, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x1439, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x143A, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x143B, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x143C, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x143D, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x143E, 0x0000, 0x0000, + "HUAWEI MOBILE", + "Mass Storage", + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, + 0), +UNUSUAL_DEV( 0x12d1, 0x143F, 0x0000, 0x0000, "HUAWEI MOBILE", "Mass Storage", - USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_init, + USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, 0), /* Reported by Vilius Bilinkevicius ubuf_info[head]; + struct ubuf_info *ubuf; + ubuf = vq->ubuf_info + vq->upend_idx; vq->heads[vq->upend_idx].len = len; ubuf->callback = vhost_zerocopy_callback; diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index 51e4c1eeec4..1a9e2a9b856 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -1074,7 +1074,7 @@ static int translate_desc(struct vhost_dev *dev, u64 addr, u32 len, } _iov = iov + ret; size = reg->memory_size - addr + reg->guest_phys_addr; - _iov->iov_len = min((u64)len, size); + _iov->iov_len = min((u64)len - s, size); _iov->iov_base = (void __user *)(unsigned long) (reg->userspace_addr + addr - reg->guest_phys_addr); s += size; diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c index d99505b1637..78506ebeaa1 100644 --- a/drivers/video/atmel_lcdfb.c +++ b/drivers/video/atmel_lcdfb.c @@ -422,17 +422,22 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var, = var->bits_per_pixel; break; case 16: + /* Older SOCs use IBGR:555 rather than BGR:565. */ + if (sinfo->have_intensity_bit) + var->green.length = 5; + else + var->green.length = 6; + if (sinfo->lcd_wiring_mode == ATMEL_LCDC_WIRING_RGB) { - /* RGB:565 mode */ - var->red.offset = 11; + /* RGB:5X5 mode */ + var->red.offset = var->green.length + 5; var->blue.offset = 0; } else { - /* BGR:565 mode */ + /* BGR:5X5 mode */ var->red.offset = 0; - var->blue.offset = 11; + var->blue.offset = var->green.length + 5; } var->green.offset = 5; - var->green.length = 6; var->red.length = var->blue.length = 5; break; case 32: @@ -679,8 +684,7 @@ static int atmel_lcdfb_setcolreg(unsigned int regno, unsigned int red, case FB_VISUAL_PSEUDOCOLOR: if (regno < 256) { - if (cpu_is_at91sam9261() || cpu_is_at91sam9263() - || cpu_is_at91sam9rl()) { + if (sinfo->have_intensity_bit) { /* old style I+BGR:555 */ val = ((red >> 11) & 0x001f); val |= ((green >> 6) & 0x03e0); @@ -870,6 +874,10 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev) } sinfo->info = info; sinfo->pdev = pdev; + if (cpu_is_at91sam9261() || cpu_is_at91sam9263() || + cpu_is_at91sam9rl()) { + sinfo->have_intensity_bit = true; + } strcpy(info->fix.id, sinfo->pdev->name); info->flags = ATMEL_LCDFB_FBINFO_DEFAULT; diff --git a/drivers/video/backlight/adp8860_bl.c b/drivers/video/backlight/adp8860_bl.c index 550dbf0bb89..feda482d4af 100644 --- a/drivers/video/backlight/adp8860_bl.c +++ b/drivers/video/backlight/adp8860_bl.c @@ -791,7 +791,7 @@ static int adp8860_i2c_suspend(struct i2c_client *client, pm_message_t message) static int adp8860_i2c_resume(struct i2c_client *client) { - adp8860_set_bits(client, ADP8860_MDCR, NSTBY); + adp8860_set_bits(client, ADP8860_MDCR, NSTBY | BLEN); return 0; } diff --git a/drivers/video/backlight/adp8870_bl.c b/drivers/video/backlight/adp8870_bl.c index 9be58c6f18f..c7a2c35abdd 100644 --- a/drivers/video/backlight/adp8870_bl.c +++ b/drivers/video/backlight/adp8870_bl.c @@ -965,7 +965,7 @@ static int adp8870_i2c_suspend(struct i2c_client *client, pm_message_t message) static int adp8870_i2c_resume(struct i2c_client *client) { - adp8870_set_bits(client, ADP8870_MDCR, NSTBY); + adp8870_set_bits(client, ADP8870_MDCR, NSTBY | BLEN); return 0; } diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 88e92041d8f..a01317c9c07 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -529,6 +529,33 @@ static int search_for_mapped_con(void) return retval; } +static int do_fbcon_takeover(int show_logo) +{ + int err, i; + + if (!num_registered_fb) + return -ENODEV; + + if (!show_logo) + logo_shown = FBCON_LOGO_DONTSHOW; + + for (i = first_fb_vc; i <= last_fb_vc; i++) + con2fb_map[i] = info_idx; + + err = do_take_over_console(&fb_con, first_fb_vc, last_fb_vc, + fbcon_is_default); + + if (err) { + for (i = first_fb_vc; i <= last_fb_vc; i++) + con2fb_map[i] = -1; + info_idx = -1; + } else { + fbcon_has_console_bind = 1; + } + + return err; +} + static int fbcon_takeover(int show_logo) { int err, i; @@ -815,6 +842,8 @@ static void con2fb_init_display(struct vc_data *vc, struct fb_info *info, * * Maps a virtual console @unit to a frame buffer device * @newidx. + * + * This should be called with the console lock held. */ static int set_con2fb_map(int unit, int newidx, int user) { @@ -832,7 +861,7 @@ static int set_con2fb_map(int unit, int newidx, int user) if (!search_for_mapped_con() || !con_is_bound(&fb_con)) { info_idx = newidx; - return fbcon_takeover(0); + return do_fbcon_takeover(0); } if (oldidx != -1) @@ -840,7 +869,6 @@ static int set_con2fb_map(int unit, int newidx, int user) found = search_fb_in_map(newidx); - console_lock(); con2fb_map[unit] = newidx; if (!err && !found) err = con2fb_acquire_newinfo(vc, info, unit, oldidx); @@ -867,7 +895,6 @@ static int set_con2fb_map(int unit, int newidx, int user) if (!search_fb_in_map(info_idx)) info_idx = newidx; - console_unlock(); return err; } @@ -990,7 +1017,7 @@ static const char *fbcon_startup(void) } /* Setup default font */ - if (!p->fontdata) { + if (!p->fontdata && !vc->vc_font.data) { if (!fontname[0] || !(font = find_font(fontname))) font = get_default_font(info->var.xres, info->var.yres, @@ -1000,6 +1027,8 @@ static const char *fbcon_startup(void) vc->vc_font.height = font->height; vc->vc_font.data = (void *)(p->fontdata = font->data); vc->vc_font.charcount = 256; /* FIXME Need to support more fonts */ + } else { + p->fontdata = vc->vc_font.data; } cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres); @@ -1159,9 +1188,9 @@ static void fbcon_init(struct vc_data *vc, int init) ops->p = &fb_display[fg_console]; } -static void fbcon_free_font(struct display *p) +static void fbcon_free_font(struct display *p, bool freefont) { - if (p->userfont && p->fontdata && (--REFCOUNT(p->fontdata) == 0)) + if (freefont && p->userfont && p->fontdata && (--REFCOUNT(p->fontdata) == 0)) kfree(p->fontdata - FONT_EXTRA_WORDS * sizeof(int)); p->fontdata = NULL; p->userfont = 0; @@ -1173,8 +1202,8 @@ static void fbcon_deinit(struct vc_data *vc) struct fb_info *info; struct fbcon_ops *ops; int idx; + bool free_font = true; - fbcon_free_font(p); idx = con2fb_map[vc->vc_num]; if (idx == -1) @@ -1185,6 +1214,8 @@ static void fbcon_deinit(struct vc_data *vc) if (!info) goto finished; + if (info->flags & FBINFO_MISC_FIRMWARE) + free_font = false; ops = info->fbcon_par; if (!ops) @@ -1196,6 +1227,10 @@ static void fbcon_deinit(struct vc_data *vc) ops->flags &= ~FBCON_FLAGS_INIT; finished: + fbcon_free_font(p, free_font); + if (free_font) + vc->vc_font.data = NULL; + if (!con_is_bound(&fb_con)) fbcon_exit(); @@ -2977,7 +3012,7 @@ static int fbcon_unbind(void) { int ret; - ret = unbind_con_driver(&fb_con, first_fb_vc, last_fb_vc, + ret = do_unbind_con_driver(&fb_con, first_fb_vc, last_fb_vc, fbcon_is_default); if (!ret) @@ -2992,6 +3027,7 @@ static inline int fbcon_unbind(void) } #endif /* CONFIG_VT_HW_CONSOLE_BINDING */ +/* called with console_lock held */ static int fbcon_fb_unbind(int idx) { int i, new_idx = -1, ret = 0; @@ -3018,6 +3054,7 @@ static int fbcon_fb_unbind(int idx) return ret; } +/* called with console_lock held */ static int fbcon_fb_unregistered(struct fb_info *info) { int i, idx; @@ -3050,11 +3087,12 @@ static int fbcon_fb_unregistered(struct fb_info *info) primary_device = -1; if (!num_registered_fb) - unregister_con_driver(&fb_con); + do_unregister_con_driver(&fb_con); return 0; } +/* called with console_lock held */ static void fbcon_remap_all(int idx) { int i; @@ -3099,6 +3137,7 @@ static inline void fbcon_select_primary(struct fb_info *info) } #endif /* CONFIG_FRAMEBUFFER_DETECT_PRIMARY */ +/* called with console_lock held */ static int fbcon_fb_registered(struct fb_info *info) { int ret = 0, i, idx; @@ -3115,7 +3154,7 @@ static int fbcon_fb_registered(struct fb_info *info) } if (info_idx != -1) - ret = fbcon_takeover(1); + ret = do_fbcon_takeover(1); } else { for (i = first_fb_vc; i <= last_fb_vc; i++) { if (con2fb_map_boot[i] == idx) @@ -3251,6 +3290,7 @@ static int fbcon_event_notify(struct notifier_block *self, ret = fbcon_fb_unregistered(info); break; case FB_EVENT_SET_CONSOLE_MAP: + /* called with console lock held */ con2fb = event->data; ret = set_con2fb_map(con2fb->console - 1, con2fb->framebuffer, 1); diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index d449a74d4a3..5855d17d19a 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c @@ -1064,7 +1064,7 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512) unsigned short video_port_status = vga_video_port_reg + 6; int font_select = 0x00, beg, i; char *charmap; - + bool clear_attribs = false; if (vga_video_type != VIDEO_TYPE_EGAM) { charmap = (char *) VGA_MAP_MEM(colourmap, 0); beg = 0x0e; @@ -1169,12 +1169,6 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512) /* if 512 char mode is already enabled don't re-enable it. */ if ((set) && (ch512 != vga_512_chars)) { - /* attribute controller */ - for (i = 0; i < MAX_NR_CONSOLES; i++) { - struct vc_data *c = vc_cons[i].d; - if (c && c->vc_sw == &vga_con) - c->vc_hi_font_mask = ch512 ? 0x0800 : 0; - } vga_512_chars = ch512; /* 256-char: enable intensity bit 512-char: disable intensity bit */ @@ -1185,8 +1179,22 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512) it means, but it works, and it appears necessary */ inb_p(video_port_status); vga_wattr(state->vgabase, VGA_AR_ENABLE_DISPLAY, 0); + clear_attribs = true; } raw_spin_unlock_irq(&vga_lock); + + if (clear_attribs) { + for (i = 0; i < MAX_NR_CONSOLES; i++) { + struct vc_data *c = vc_cons[i].d; + if (c && c->vc_sw == &vga_con) { + /* force hi font mask to 0, so we always clear + the bit on either transition */ + c->vc_hi_font_mask = 0x00; + clear_buffer_attributes(c); + c->vc_hi_font_mask = ch512 ? 0x0800 : 0; + } + } + } return 0; } diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index d6a664a168b..c060fcc905f 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -1168,8 +1168,10 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd, event.data = &con2fb; if (!lock_fb_info(info)) return -ENODEV; + console_lock(); event.info = info; ret = fb_notifier_call_chain(FB_EVENT_SET_CONSOLE_MAP, &event); + console_unlock(); unlock_fb_info(info); break; case FBIOBLANK: @@ -1639,7 +1641,9 @@ static int do_register_framebuffer(struct fb_info *fb_info) event.info = fb_info; if (!lock_fb_info(fb_info)) return -ENODEV; + console_lock(); fb_notifier_call_chain(FB_EVENT_FB_REGISTERED, &event); + console_unlock(); unlock_fb_info(fb_info); return 0; } @@ -1655,8 +1659,10 @@ static int do_unregister_framebuffer(struct fb_info *fb_info) if (!lock_fb_info(fb_info)) return -ENODEV; + console_lock(); event.info = fb_info; ret = fb_notifier_call_chain(FB_EVENT_FB_UNBIND, &event); + console_unlock(); unlock_fb_info(fb_info); if (ret) @@ -1671,7 +1677,9 @@ static int do_unregister_framebuffer(struct fb_info *fb_info) num_registered_fb--; fb_cleanup_device(fb_info); event.info = fb_info; + console_lock(); fb_notifier_call_chain(FB_EVENT_FB_UNREGISTERED, &event); + console_unlock(); /* this may free fb info */ put_fb_info(fb_info); @@ -1842,11 +1850,8 @@ int fb_new_modelist(struct fb_info *info) err = 1; if (!list_empty(&info->modelist)) { - if (!lock_fb_info(info)) - return -ENODEV; event.info = info; err = fb_notifier_call_chain(FB_EVENT_NEW_MODELIST, &event); - unlock_fb_info(info); } return err; diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c index 67afa9c2289..303fb9f35b2 100644 --- a/drivers/video/fbsysfs.c +++ b/drivers/video/fbsysfs.c @@ -175,6 +175,8 @@ static ssize_t store_modes(struct device *device, if (i * sizeof(struct fb_videomode) != count) return -EINVAL; + if (!lock_fb_info(fb_info)) + return -ENODEV; console_lock(); list_splice(&fb_info->modelist, &old_list); fb_videomode_to_modelist((const struct fb_videomode *)buf, i, @@ -186,6 +188,7 @@ static ssize_t store_modes(struct device *device, fb_destroy_modelist(&old_list); console_unlock(); + unlock_fb_info(fb_info); return 0; } diff --git a/drivers/video/fsl-diu-fb.c b/drivers/video/fsl-diu-fb.c index 6af3f16754f..d02a538518c 100644 --- a/drivers/video/fsl-diu-fb.c +++ b/drivers/video/fsl-diu-fb.c @@ -923,7 +923,7 @@ static u32 fsl_diu_get_pixel_format(unsigned int bits_per_pixel) #define PF_COMP_0_MASK 0x0000000F #define PF_COMP_0_SHIFT 0 -#define MAKE_PF(alpha, red, blue, green, size, c0, c1, c2, c3) \ +#define MAKE_PF(alpha, red, green, blue, size, c0, c1, c2, c3) \ cpu_to_le32(PF_BYTE_F | (alpha << PF_ALPHA_C_SHIFT) | \ (blue << PF_BLUE_C_SHIFT) | (green << PF_GREEN_C_SHIFT) | \ (red << PF_RED_C_SHIFT) | (c3 << PF_COMP_3_SHIFT) | \ @@ -933,10 +933,10 @@ static u32 fsl_diu_get_pixel_format(unsigned int bits_per_pixel) switch (bits_per_pixel) { case 32: /* 0x88883316 */ - return MAKE_PF(3, 2, 0, 1, 3, 8, 8, 8, 8); + return MAKE_PF(3, 2, 1, 0, 3, 8, 8, 8, 8); case 24: /* 0x88082219 */ - return MAKE_PF(4, 0, 1, 2, 2, 0, 8, 8, 8); + return MAKE_PF(4, 0, 1, 2, 2, 8, 8, 8, 0); case 16: /* 0x65053118 */ return MAKE_PF(4, 2, 1, 0, 1, 5, 6, 5, 0); diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index 9761950697b..c9bc19f4ab1 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c @@ -928,7 +928,8 @@ void w1_search(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb tmp64 = (triplet_ret >> 2); rn |= (tmp64 << i); - if (kthread_should_stop()) { + /* ensure we're called from kthread and not by netlink callback */ + if (!dev->priv && kthread_should_stop()) { dev_dbg(&dev->dev, "Abort w1_search\n"); return; } diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 26c47a4c426..33dcad6371f 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c @@ -324,7 +324,7 @@ static void init_evtchn_cpu_bindings(void) for_each_possible_cpu(i) memset(per_cpu(cpu_evtchn_mask, i), - (i == 0) ? ~0 : 0, sizeof(*per_cpu(cpu_evtchn_mask, i))); + (i == 0) ? ~0 : 0, NR_EVENT_CHANNELS/8); } static inline void clear_evtchn(int port) @@ -1258,7 +1258,7 @@ static void __xen_evtchn_do_upcall(void) { int start_word_idx, start_bit_idx; int word_idx, bit_idx; - int i; + int i, irq; int cpu = get_cpu(); struct shared_info *s = HYPERVISOR_shared_info; struct vcpu_info *vcpu_info = __this_cpu_read(xen_vcpu); @@ -1266,6 +1266,8 @@ static void __xen_evtchn_do_upcall(void) do { unsigned long pending_words; + unsigned long pending_bits; + struct irq_desc *desc; vcpu_info->evtchn_upcall_pending = 0; @@ -1276,6 +1278,17 @@ static void __xen_evtchn_do_upcall(void) /* Clear master flag /before/ clearing selector flag. */ wmb(); #endif + if ((irq = per_cpu(virq_to_irq, cpu)[VIRQ_TIMER]) != -1) { + int evtchn = evtchn_from_irq(irq); + word_idx = evtchn / BITS_PER_LONG; + pending_bits = evtchn % BITS_PER_LONG; + if (active_evtchns(cpu, s, word_idx) & (1ULL << pending_bits)) { + desc = irq_to_desc(irq); + if (desc) + generic_handle_irq_desc(irq, desc); + } + } + pending_words = xchg(&vcpu_info->evtchn_pending_sel, 0); start_word_idx = __this_cpu_read(current_word_idx); @@ -1284,7 +1297,6 @@ static void __xen_evtchn_do_upcall(void) word_idx = start_word_idx; for (i = 0; pending_words != 0; i++) { - unsigned long pending_bits; unsigned long words; words = MASK_LSBS(pending_words, word_idx); @@ -1313,8 +1325,7 @@ static void __xen_evtchn_do_upcall(void) do { unsigned long bits; - int port, irq; - struct irq_desc *desc; + int port; bits = MASK_LSBS(pending_bits, bit_idx); diff --git a/drivers/xen/evtchn.c b/drivers/xen/evtchn.c index b1f60a0c0be..82b27d4477f 100644 --- a/drivers/xen/evtchn.c +++ b/drivers/xen/evtchn.c @@ -269,6 +269,14 @@ static int evtchn_bind_to_user(struct per_user_data *u, int port) u->name, (void *)(unsigned long)port); if (rc >= 0) rc = evtchn_make_refcounted(port); + else { + /* bind failed, should close the port now */ + struct evtchn_close close; + close.port = port; + if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close) != 0) + BUG(); + set_port_user(port, NULL); + } return rc; } @@ -277,6 +285,8 @@ static void evtchn_unbind_from_user(struct per_user_data *u, int port) { int irq = irq_from_evtchn(port); + BUG_ON(irq < 0); + unbind_from_irqhandler(irq, (void *)(unsigned long)port); set_port_user(port, NULL); @@ -367,18 +377,12 @@ static long evtchn_ioctl(struct file *file, if (unbind.port >= NR_EVENT_CHANNELS) break; - spin_lock_irq(&port_user_lock); - rc = -ENOTCONN; - if (get_port_user(unbind.port) != u) { - spin_unlock_irq(&port_user_lock); + if (get_port_user(unbind.port) != u) break; - } disable_irq(irq_from_evtchn(unbind.port)); - spin_unlock_irq(&port_user_lock); - evtchn_unbind_from_user(u, unbind.port); rc = 0; @@ -478,26 +482,15 @@ static int evtchn_release(struct inode *inode, struct file *filp) int i; struct per_user_data *u = filp->private_data; - spin_lock_irq(&port_user_lock); - - free_page((unsigned long)u->ring); - for (i = 0; i < NR_EVENT_CHANNELS; i++) { if (get_port_user(i) != u) continue; disable_irq(irq_from_evtchn(i)); - } - - spin_unlock_irq(&port_user_lock); - - for (i = 0; i < NR_EVENT_CHANNELS; i++) { - if (get_port_user(i) != u) - continue; - evtchn_unbind_from_user(get_port_user(i), i); } + free_page((unsigned long)u->ring); kfree(u->name); kfree(u); diff --git a/drivers/xen/xen-pciback/pciback_ops.c b/drivers/xen/xen-pciback/pciback_ops.c index 97f5d264c31..d52703c5821 100644 --- a/drivers/xen/xen-pciback/pciback_ops.c +++ b/drivers/xen/xen-pciback/pciback_ops.c @@ -9,6 +9,8 @@ #include #include #include "pciback.h" +#include +#include int verbose_request; module_param(verbose_request, int, 0644); @@ -113,7 +115,8 @@ void xen_pcibk_reset_device(struct pci_dev *dev) if (dev->msi_enabled) pci_disable_msi(dev); #endif - pci_disable_device(dev); + if (pci_is_enabled(dev)) + pci_disable_device(dev); pci_write_config_word(dev, PCI_COMMAND, 0); @@ -135,7 +138,6 @@ int xen_pcibk_enable_msi(struct xen_pcibk_device *pdev, struct pci_dev *dev, struct xen_pci_op *op) { struct xen_pcibk_dev_data *dev_data; - int otherend = pdev->xdev->otherend_id; int status; if (unlikely(verbose_request)) @@ -144,8 +146,9 @@ int xen_pcibk_enable_msi(struct xen_pcibk_device *pdev, status = pci_enable_msi(dev); if (status) { - printk(KERN_ERR "error enable msi for guest %x status %x\n", - otherend, status); + pr_warn_ratelimited(DRV_NAME ": %s: error enabling MSI for guest %u: err %d\n", + pci_name(dev), pdev->xdev->otherend_id, + status); op->value = 0; return XEN_PCI_ERR_op_failed; } @@ -223,10 +226,10 @@ int xen_pcibk_enable_msix(struct xen_pcibk_device *pdev, pci_name(dev), i, op->msix_entries[i].vector); } - } else { - printk(KERN_WARNING DRV_NAME ": %s: failed to enable MSI-X: err %d!\n", - pci_name(dev), result); - } + } else + pr_warn_ratelimited(DRV_NAME ": %s: error enabling MSI-X for guest %u: err %d!\n", + pci_name(dev), pdev->xdev->otherend_id, + result); kfree(entries); op->value = result; diff --git a/fs/aio.c b/fs/aio.c index c4ee8a72e7b..01be7f60a8a 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -1094,9 +1094,9 @@ static int aio_read_evt(struct kioctx *ioctx, struct io_event *ent) spin_unlock(&info->ring_lock); out: - kunmap_atomic(ring); dprintk("leaving aio_read_evt: %d h%lu t%lu\n", ret, (unsigned long)ring->head, (unsigned long)ring->tail); + kunmap_atomic(ring); return ret; } diff --git a/fs/autofs4/expire.c b/fs/autofs4/expire.c index 1feb68ecef9..b1cdb0ae5ca 100644 --- a/fs/autofs4/expire.c +++ b/fs/autofs4/expire.c @@ -61,15 +61,6 @@ static int autofs4_mount_busy(struct vfsmount *mnt, struct dentry *dentry) /* This is an autofs submount, we can't expire it */ if (autofs_type_indirect(sbi->type)) goto done; - - /* - * Otherwise it's an offset mount and we need to check - * if we can umount its mount, if there is one. - */ - if (!d_mountpoint(path.dentry)) { - status = 0; - goto done; - } } /* Update the expiry counter if fs is busy */ diff --git a/fs/binfmt_em86.c b/fs/binfmt_em86.c index 2790c7e1912..575796ae3d8 100644 --- a/fs/binfmt_em86.c +++ b/fs/binfmt_em86.c @@ -42,7 +42,6 @@ static int load_em86(struct linux_binprm *bprm,struct pt_regs *regs) return -ENOEXEC; } - bprm->recursion_depth++; /* Well, the bang-shell is implicit... */ allow_write_access(bprm->file); fput(bprm->file); bprm->file = NULL; diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c index e1724392d05..87fa90d5863 100644 --- a/fs/binfmt_misc.c +++ b/fs/binfmt_misc.c @@ -117,10 +117,6 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs) if (!enabled) goto _ret; - retval = -ENOEXEC; - if (bprm->recursion_depth > BINPRM_MAX_RECURSION) - goto _ret; - /* to keep locking time low, we copy the interpreter string */ read_lock(&entries_lock); fmt = check_file(bprm); @@ -200,8 +196,6 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs) if (retval < 0) goto _error; - bprm->recursion_depth++; - retval = search_binary_handler (bprm, regs); if (retval < 0) goto _error; diff --git a/fs/binfmt_script.c b/fs/binfmt_script.c index df49d486b0c..8ae4be199fb 100644 --- a/fs/binfmt_script.c +++ b/fs/binfmt_script.c @@ -22,15 +22,13 @@ static int load_script(struct linux_binprm *bprm,struct pt_regs *regs) char interp[BINPRM_BUF_SIZE]; int retval; - if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!') || - (bprm->recursion_depth > BINPRM_MAX_RECURSION)) + if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!')) return -ENOEXEC; /* * This section does the #! interpretation. * Sorta complicated, but hopefully it will work. -TYT */ - bprm->recursion_depth++; allow_write_access(bprm->file); fput(bprm->file); bprm->file = NULL; diff --git a/fs/block_dev.c b/fs/block_dev.c index ba11c30f302..319d9c74c4d 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -57,17 +57,24 @@ static void bdev_inode_switch_bdi(struct inode *inode, struct backing_dev_info *dst) { struct backing_dev_info *old = inode->i_data.backing_dev_info; + bool wakeup_bdi = false; if (unlikely(dst == old)) /* deadlock avoidance */ return; bdi_lock_two(&old->wb, &dst->wb); spin_lock(&inode->i_lock); inode->i_data.backing_dev_info = dst; - if (inode->i_state & I_DIRTY) + if (inode->i_state & I_DIRTY) { + if (bdi_cap_writeback_dirty(dst) && !wb_has_dirty_io(&dst->wb)) + wakeup_bdi = true; list_move(&inode->i_wb_list, &dst->wb.b_dirty); + } spin_unlock(&inode->i_lock); spin_unlock(&old->wb.list_lock); spin_unlock(&dst->wb.list_lock); + + if (wakeup_bdi) + bdi_wakeup_thread_delayed(dst); } sector_t blkdev_max_block(struct block_device *bdev) @@ -604,6 +611,7 @@ struct block_device *bdgrab(struct block_device *bdev) ihold(bdev->bd_inode); return bdev; } +EXPORT_SYMBOL(bdgrab); long nr_blockdev_pages(void) { @@ -1047,6 +1055,7 @@ int revalidate_disk(struct gendisk *disk) mutex_lock(&bdev->bd_mutex); check_disk_size_change(disk, bdev); + bdev->bd_invalidated = 0; mutex_unlock(&bdev->bd_mutex); bdput(bdev); return ret; @@ -1085,7 +1094,9 @@ void bd_set_size(struct block_device *bdev, loff_t size) { unsigned bsize = bdev_logical_block_size(bdev); - bdev->bd_inode->i_size = size; + mutex_lock(&bdev->bd_inode->i_mutex); + i_size_write(bdev->bd_inode, size); + mutex_unlock(&bdev->bd_inode->i_mutex); while (bsize < PAGE_CACHE_SIZE) { if (size & bsize) break; diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 49fd7b66d57..c4f0a9936f8 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -4217,7 +4217,7 @@ static void update_global_block_rsv(struct btrfs_fs_info *fs_info) spin_lock(&sinfo->lock); spin_lock(&block_rsv->lock); - block_rsv->size = num_bytes; + block_rsv->size = min_t(u64, num_bytes, 512 * 1024 * 1024); num_bytes = sinfo->bytes_used + sinfo->bytes_pinned + sinfo->bytes_reserved + sinfo->bytes_readonly + @@ -4486,14 +4486,49 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes) * If the inodes csum_bytes is the same as the original * csum_bytes then we know we haven't raced with any free()ers * so we can just reduce our inodes csum bytes and carry on. - * Otherwise we have to do the normal free thing to account for - * the case that the free side didn't free up its reserve - * because of this outstanding reservation. */ - if (BTRFS_I(inode)->csum_bytes == csum_bytes) + if (BTRFS_I(inode)->csum_bytes == csum_bytes) { calc_csum_metadata_size(inode, num_bytes, 0); - else - to_free = calc_csum_metadata_size(inode, num_bytes, 0); + } else { + u64 orig_csum_bytes = BTRFS_I(inode)->csum_bytes; + u64 bytes; + + /* + * This is tricky, but first we need to figure out how much we + * free'd from any free-ers that occured during this + * reservation, so we reset ->csum_bytes to the csum_bytes + * before we dropped our lock, and then call the free for the + * number of bytes that were freed while we were trying our + * reservation. + */ + bytes = csum_bytes - BTRFS_I(inode)->csum_bytes; + BTRFS_I(inode)->csum_bytes = csum_bytes; + to_free = calc_csum_metadata_size(inode, bytes, 0); + + + /* + * Now we need to see how much we would have freed had we not + * been making this reservation and our ->csum_bytes were not + * artificially inflated. + */ + BTRFS_I(inode)->csum_bytes = csum_bytes - num_bytes; + bytes = csum_bytes - orig_csum_bytes; + bytes = calc_csum_metadata_size(inode, bytes, 0); + + /* + * Now reset ->csum_bytes to what it should be. If bytes is + * more than to_free then we would have free'd more space had we + * not had an artificially high ->csum_bytes, so we need to free + * the remainder. If bytes is the same or less then we don't + * need to do anything, the other free-ers did the correct + * thing. + */ + BTRFS_I(inode)->csum_bytes = orig_csum_bytes - num_bytes; + if (bytes > to_free) + to_free = bytes - to_free; + else + to_free = 0; + } spin_unlock(&BTRFS_I(inode)->lock); if (dropped) to_free += btrfs_calc_trans_metadata_size(root, dropped); @@ -6811,6 +6846,7 @@ int btrfs_drop_snapshot(struct btrfs_root *root, int err = 0; int ret; int level; + bool root_dropped = false; path = btrfs_alloc_path(); if (!path) { @@ -6868,6 +6904,7 @@ int btrfs_drop_snapshot(struct btrfs_root *root, while (1) { btrfs_tree_lock(path->nodes[level]); btrfs_set_lock_blocking(path->nodes[level]); + path->locks[level] = BTRFS_WRITE_LOCK_BLOCKING; ret = btrfs_lookup_extent_info(trans, root, path->nodes[level]->start, @@ -6884,6 +6921,7 @@ int btrfs_drop_snapshot(struct btrfs_root *root, break; btrfs_tree_unlock(path->nodes[level]); + path->locks[level] = 0; WARN_ON(wc->refs[level] != 1); level--; } @@ -6979,12 +7017,22 @@ int btrfs_drop_snapshot(struct btrfs_root *root, free_extent_buffer(root->commit_root); kfree(root); } + root_dropped = true; out_end_trans: btrfs_end_transaction_throttle(trans, tree_root); out_free: kfree(wc); btrfs_free_path(path); out: + /* + * So if we need to stop dropping the snapshot for whatever reason we + * need to make sure to add it back to the dead root list so that we + * keep trying to do the work later. This also cleans up roots if we + * don't have it in the radix (like when we recover after a power fail + * or unmount) so we don't leak memory. + */ + if (root_dropped == false) + btrfs_add_dead_root(root); if (err) btrfs_std_error(root->fs_info, err); return err; diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index c9018a05036..d64fda54148 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -1238,6 +1238,39 @@ int unlock_extent(struct extent_io_tree *tree, u64 start, u64 end) GFP_NOFS); } +int extent_range_clear_dirty_for_io(struct inode *inode, u64 start, u64 end) +{ + unsigned long index = start >> PAGE_CACHE_SHIFT; + unsigned long end_index = end >> PAGE_CACHE_SHIFT; + struct page *page; + + while (index <= end_index) { + page = find_get_page(inode->i_mapping, index); + BUG_ON(!page); /* Pages should be in the extent_io_tree */ + clear_page_dirty_for_io(page); + page_cache_release(page); + index++; + } + return 0; +} + +int extent_range_redirty_for_io(struct inode *inode, u64 start, u64 end) +{ + unsigned long index = start >> PAGE_CACHE_SHIFT; + unsigned long end_index = end >> PAGE_CACHE_SHIFT; + struct page *page; + + while (index <= end_index) { + page = find_get_page(inode->i_mapping, index); + BUG_ON(!page); /* Pages should be in the extent_io_tree */ + account_page_redirty(page); + __set_page_dirty_nobuffers(page); + page_cache_release(page); + index++; + } + return 0; +} + /* * helper function to set both pages and extents in the tree writeback */ diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h index b516c3b8dec..2edf9120aae 100644 --- a/fs/btrfs/extent_io.h +++ b/fs/btrfs/extent_io.h @@ -312,6 +312,8 @@ int map_private_extent_buffer(struct extent_buffer *eb, unsigned long offset, unsigned long *map_len); int extent_range_uptodate(struct extent_io_tree *tree, u64 start, u64 end); +int extent_range_clear_dirty_for_io(struct inode *inode, u64 start, u64 end); +int extent_range_redirty_for_io(struct inode *inode, u64 start, u64 end); int extent_clear_unlock_delalloc(struct inode *inode, struct extent_io_tree *tree, u64 start, u64 end, struct page *locked_page, diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 0df0d1fd4fe..9e51325828b 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -349,6 +349,7 @@ static noinline int compress_file_range(struct inode *inode, int i; int will_compress; int compress_type = root->fs_info->compress_type; + int redirty = 0; /* if this is a small write inside eof, kick off a defrag */ if ((end - start + 1) < 16 * 1024 && @@ -411,6 +412,17 @@ static noinline int compress_file_range(struct inode *inode, if (BTRFS_I(inode)->force_compress) compress_type = BTRFS_I(inode)->force_compress; + /* + * we need to call clear_page_dirty_for_io on each + * page in the range. Otherwise applications with the file + * mmap'd can wander in and change the page contents while + * we are compressing them. + * + * If the compression fails for any reason, we set the pages + * dirty again later on. + */ + extent_range_clear_dirty_for_io(inode, start, end); + redirty = 1; ret = btrfs_compress_pages(compress_type, inode->i_mapping, start, total_compressed, pages, @@ -552,6 +564,8 @@ static noinline int compress_file_range(struct inode *inode, __set_page_dirty_nobuffers(locked_page); /* unlocked later on in the async handlers */ } + if (redirty) + extent_range_redirty_for_io(inode, start, end); add_async_extent(async_cow, start, end - start + 1, 0, NULL, 0, BTRFS_COMPRESS_NONE); *num_added += 1; diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 0825321522c..0b2d99315aa 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -1653,7 +1653,11 @@ static noinline int copy_to_sk(struct btrfs_root *root, item_off = btrfs_item_ptr_offset(leaf, i); item_len = btrfs_item_size_nr(leaf, i); - if (item_len > BTRFS_SEARCH_ARGS_BUFSIZE) + btrfs_item_key_to_cpu(leaf, key, i); + if (!key_in_sk(key, sk)) + continue; + + if (sizeof(sh) + item_len > BTRFS_SEARCH_ARGS_BUFSIZE) item_len = 0; if (sizeof(sh) + item_len + *sk_offset > @@ -1662,10 +1666,6 @@ static noinline int copy_to_sk(struct btrfs_root *root, goto overflow; } - btrfs_item_key_to_cpu(leaf, key, i); - if (!key_in_sk(key, sk)) - continue; - sh.objectid = key->objectid; sh.offset = key->offset; sh.type = key->type; diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c index 2f3d6f917fb..682e5da3143 100644 --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c @@ -383,7 +383,6 @@ static void scrub_print_warning(const char *errstr, struct scrub_block *sblock) eb = path->nodes[0]; ei = btrfs_item_ptr(eb, path->slots[0], struct btrfs_extent_item); item_size = btrfs_item_size_nr(eb, path->slots[0]); - btrfs_release_path(path); if (ret & BTRFS_EXTENT_FLAG_TREE_BLOCK) { do { @@ -398,7 +397,9 @@ static void scrub_print_warning(const char *errstr, struct scrub_block *sblock) ret < 0 ? -1 : ref_level, ret < 0 ? -1 : ref_root); } while (ret != 1); + btrfs_release_path(path); } else { + btrfs_release_path(path); swarn.path = path; iterate_extent_inodes(fs_info, found_key.objectid, extent_item_pos, 1, diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index dce89da9c86..3ef7f386e26 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c @@ -315,6 +315,7 @@ static noinline int overwrite_item(struct btrfs_trans_handle *trans, unsigned long src_ptr; unsigned long dst_ptr; int overwrite_root = 0; + bool inode_item = key->type == BTRFS_INODE_ITEM_KEY; if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID) overwrite_root = 1; @@ -324,6 +325,9 @@ static noinline int overwrite_item(struct btrfs_trans_handle *trans, /* look for the key in the destination tree */ ret = btrfs_search_slot(NULL, root, key, path, 0, 0); + if (ret < 0) + return ret; + if (ret == 0) { char *src_copy; char *dst_copy; @@ -365,6 +369,30 @@ static noinline int overwrite_item(struct btrfs_trans_handle *trans, return 0; } + /* + * We need to load the old nbytes into the inode so when we + * replay the extents we've logged we get the right nbytes. + */ + if (inode_item) { + struct btrfs_inode_item *item; + u64 nbytes; + + item = btrfs_item_ptr(path->nodes[0], path->slots[0], + struct btrfs_inode_item); + nbytes = btrfs_inode_nbytes(path->nodes[0], item); + item = btrfs_item_ptr(eb, slot, + struct btrfs_inode_item); + btrfs_set_inode_nbytes(eb, item, nbytes); + } + } else if (inode_item) { + struct btrfs_inode_item *item; + + /* + * New inode, set nbytes to 0 so that the nbytes comes out + * properly when we replay the extents. + */ + item = btrfs_item_ptr(eb, slot, struct btrfs_inode_item); + btrfs_set_inode_nbytes(eb, item, 0); } insert: btrfs_release_path(path); @@ -486,7 +514,7 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans, u64 extent_end; u64 alloc_hint; u64 start = key->offset; - u64 saved_nbytes; + u64 nbytes = 0; struct btrfs_file_extent_item *item; struct inode *inode = NULL; unsigned long size; @@ -496,10 +524,19 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans, found_type = btrfs_file_extent_type(eb, item); if (found_type == BTRFS_FILE_EXTENT_REG || - found_type == BTRFS_FILE_EXTENT_PREALLOC) - extent_end = start + btrfs_file_extent_num_bytes(eb, item); - else if (found_type == BTRFS_FILE_EXTENT_INLINE) { + found_type == BTRFS_FILE_EXTENT_PREALLOC) { + nbytes = btrfs_file_extent_num_bytes(eb, item); + extent_end = start + nbytes; + + /* + * We don't add to the inodes nbytes if we are prealloc or a + * hole. + */ + if (btrfs_file_extent_disk_bytenr(eb, item) == 0) + nbytes = 0; + } else if (found_type == BTRFS_FILE_EXTENT_INLINE) { size = btrfs_file_extent_inline_len(eb, item); + nbytes = btrfs_file_extent_ram_bytes(eb, item); extent_end = (start + size + mask) & ~mask; } else { ret = 0; @@ -548,7 +585,6 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans, } btrfs_release_path(path); - saved_nbytes = inode_get_bytes(inode); /* drop any overlapping extents */ ret = btrfs_drop_extents(trans, inode, start, extent_end, &alloc_hint, 1); @@ -636,7 +672,7 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans, BUG_ON(ret); } - inode_set_bytes(inode, saved_nbytes); + inode_add_bytes(inode, nbytes); btrfs_update_inode(trans, root, inode); out: if (inode) diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 1411b99555a..06744f1e91f 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -557,6 +557,7 @@ static int __btrfs_close_devices(struct btrfs_fs_devices *fs_devices) new_device->writeable = 0; new_device->in_fs_metadata = 0; new_device->can_discard = 0; + spin_lock_init(&new_device->io_lock); list_replace_rcu(&device->dev_list, &new_device->dev_list); call_rcu(&device->rcu, free_device); @@ -590,6 +591,12 @@ int btrfs_close_devices(struct btrfs_fs_devices *fs_devices) __btrfs_close_devices(fs_devices); free_fs_devices(fs_devices); } + /* + * Wait for rcu kworkers under __btrfs_close_devices + * to finish all blkdev_puts so device is really + * free when umount is done. + */ + rcu_barrier(); return ret; } diff --git a/fs/ceph/locks.c b/fs/ceph/locks.c index 80576d05d68..bb5fb3d46e8 100644 --- a/fs/ceph/locks.c +++ b/fs/ceph/locks.c @@ -191,27 +191,23 @@ void ceph_count_locks(struct inode *inode, int *fcntl_count, int *flock_count) } /** - * Encode the flock and fcntl locks for the given inode into the pagelist. - * Format is: #fcntl locks, sequential fcntl locks, #flock locks, - * sequential flock locks. - * Must be called with lock_flocks() already held. - * If we encounter more of a specific lock type than expected, - * we return the value 1. + * Encode the flock and fcntl locks for the given inode into the ceph_filelock + * array. Must be called with lock_flocks() already held. + * If we encounter more of a specific lock type than expected, return -ENOSPC. */ -int ceph_encode_locks(struct inode *inode, struct ceph_pagelist *pagelist, - int num_fcntl_locks, int num_flock_locks) +int ceph_encode_locks_to_buffer(struct inode *inode, + struct ceph_filelock *flocks, + int num_fcntl_locks, int num_flock_locks) { struct file_lock *lock; - struct ceph_filelock cephlock; int err = 0; int seen_fcntl = 0; int seen_flock = 0; + int l = 0; dout("encoding %d flock and %d fcntl locks", num_flock_locks, num_fcntl_locks); - err = ceph_pagelist_append(pagelist, &num_fcntl_locks, sizeof(u32)); - if (err) - goto fail; + for (lock = inode->i_flock; lock != NULL; lock = lock->fl_next) { if (lock->fl_flags & FL_POSIX) { ++seen_fcntl; @@ -219,19 +215,12 @@ int ceph_encode_locks(struct inode *inode, struct ceph_pagelist *pagelist, err = -ENOSPC; goto fail; } - err = lock_to_ceph_filelock(lock, &cephlock); + err = lock_to_ceph_filelock(lock, &flocks[l]); if (err) goto fail; - err = ceph_pagelist_append(pagelist, &cephlock, - sizeof(struct ceph_filelock)); + ++l; } - if (err) - goto fail; } - - err = ceph_pagelist_append(pagelist, &num_flock_locks, sizeof(u32)); - if (err) - goto fail; for (lock = inode->i_flock; lock != NULL; lock = lock->fl_next) { if (lock->fl_flags & FL_FLOCK) { ++seen_flock; @@ -239,19 +228,51 @@ int ceph_encode_locks(struct inode *inode, struct ceph_pagelist *pagelist, err = -ENOSPC; goto fail; } - err = lock_to_ceph_filelock(lock, &cephlock); + err = lock_to_ceph_filelock(lock, &flocks[l]); if (err) goto fail; - err = ceph_pagelist_append(pagelist, &cephlock, - sizeof(struct ceph_filelock)); + ++l; } - if (err) - goto fail; } fail: return err; } +/** + * Copy the encoded flock and fcntl locks into the pagelist. + * Format is: #fcntl locks, sequential fcntl locks, #flock locks, + * sequential flock locks. + * Returns zero on success. + */ +int ceph_locks_to_pagelist(struct ceph_filelock *flocks, + struct ceph_pagelist *pagelist, + int num_fcntl_locks, int num_flock_locks) +{ + int err = 0; + __le32 nlocks; + + nlocks = cpu_to_le32(num_fcntl_locks); + err = ceph_pagelist_append(pagelist, &nlocks, sizeof(nlocks)); + if (err) + goto out_fail; + + err = ceph_pagelist_append(pagelist, flocks, + num_fcntl_locks * sizeof(*flocks)); + if (err) + goto out_fail; + + nlocks = cpu_to_le32(num_flock_locks); + err = ceph_pagelist_append(pagelist, &nlocks, sizeof(nlocks)); + if (err) + goto out_fail; + + err = ceph_pagelist_append(pagelist, + &flocks[num_fcntl_locks], + num_flock_locks * sizeof(*flocks)); +out_fail: + return err; +} + /* * Given a pointer to a lock, convert it to a ceph filelock */ diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 3fd08ad5c47..cf1b9e043b0 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -335,9 +335,9 @@ void ceph_put_mds_session(struct ceph_mds_session *s) atomic_read(&s->s_ref), atomic_read(&s->s_ref)-1); if (atomic_dec_and_test(&s->s_ref)) { if (s->s_auth.authorizer) - s->s_mdsc->fsc->client->monc.auth->ops->destroy_authorizer( - s->s_mdsc->fsc->client->monc.auth, - s->s_auth.authorizer); + ceph_auth_destroy_authorizer( + s->s_mdsc->fsc->client->monc.auth, + s->s_auth.authorizer); kfree(s); } } @@ -2455,39 +2455,44 @@ static int encode_caps_cb(struct inode *inode, struct ceph_cap *cap, if (recon_state->flock) { int num_fcntl_locks, num_flock_locks; - struct ceph_pagelist_cursor trunc_point; - - ceph_pagelist_set_cursor(pagelist, &trunc_point); - do { - lock_flocks(); - ceph_count_locks(inode, &num_fcntl_locks, - &num_flock_locks); - rec.v2.flock_len = (2*sizeof(u32) + - (num_fcntl_locks+num_flock_locks) * - sizeof(struct ceph_filelock)); - unlock_flocks(); - - /* pre-alloc pagelist */ - ceph_pagelist_truncate(pagelist, &trunc_point); - err = ceph_pagelist_append(pagelist, &rec, reclen); - if (!err) - err = ceph_pagelist_reserve(pagelist, - rec.v2.flock_len); - - /* encode locks */ - if (!err) { - lock_flocks(); - err = ceph_encode_locks(inode, - pagelist, - num_fcntl_locks, - num_flock_locks); - unlock_flocks(); - } - } while (err == -ENOSPC); + struct ceph_filelock *flocks; + +encode_again: + lock_flocks(); + ceph_count_locks(inode, &num_fcntl_locks, &num_flock_locks); + unlock_flocks(); + flocks = kmalloc((num_fcntl_locks+num_flock_locks) * + sizeof(struct ceph_filelock), GFP_NOFS); + if (!flocks) { + err = -ENOMEM; + goto out_free; + } + lock_flocks(); + err = ceph_encode_locks_to_buffer(inode, flocks, + num_fcntl_locks, + num_flock_locks); + unlock_flocks(); + if (err) { + kfree(flocks); + if (err == -ENOSPC) + goto encode_again; + goto out_free; + } + /* + * number of encoded locks is stable, so copy to pagelist + */ + rec.v2.flock_len = cpu_to_le32(2*sizeof(u32) + + (num_fcntl_locks+num_flock_locks) * + sizeof(struct ceph_filelock)); + err = ceph_pagelist_append(pagelist, &rec, reclen); + if (!err) + err = ceph_locks_to_pagelist(flocks, pagelist, + num_fcntl_locks, + num_flock_locks); + kfree(flocks); } else { err = ceph_pagelist_append(pagelist, &rec, reclen); } - out_free: kfree(path); out_dput: @@ -3414,13 +3419,17 @@ static struct ceph_auth_handshake *get_authorizer(struct ceph_connection *con, struct ceph_auth_handshake *auth = &s->s_auth; if (force_new && auth->authorizer) { - if (ac->ops && ac->ops->destroy_authorizer) - ac->ops->destroy_authorizer(ac, auth->authorizer); + ceph_auth_destroy_authorizer(ac, auth->authorizer); auth->authorizer = NULL; } - if (!auth->authorizer && ac->ops && ac->ops->create_authorizer) { - int ret = ac->ops->create_authorizer(ac, CEPH_ENTITY_TYPE_MDS, - auth); + if (!auth->authorizer) { + int ret = ceph_auth_create_authorizer(ac, CEPH_ENTITY_TYPE_MDS, + auth); + if (ret) + return ERR_PTR(ret); + } else { + int ret = ceph_auth_update_authorizer(ac, CEPH_ENTITY_TYPE_MDS, + auth); if (ret) return ERR_PTR(ret); } @@ -3436,7 +3445,7 @@ static int verify_authorizer_reply(struct ceph_connection *con, int len) struct ceph_mds_client *mdsc = s->s_mdsc; struct ceph_auth_client *ac = mdsc->fsc->client->monc.auth; - return ac->ops->verify_authorizer_reply(ac, s->s_auth.authorizer, len); + return ceph_auth_verify_authorizer_reply(ac, s->s_auth.authorizer, len); } static int invalidate_authorizer(struct ceph_connection *con) @@ -3445,8 +3454,7 @@ static int invalidate_authorizer(struct ceph_connection *con) struct ceph_mds_client *mdsc = s->s_mdsc; struct ceph_auth_client *ac = mdsc->fsc->client->monc.auth; - if (ac->ops->invalidate_authorizer) - ac->ops->invalidate_authorizer(ac, CEPH_ENTITY_TYPE_MDS); + ceph_auth_invalidate_authorizer(ac, CEPH_ENTITY_TYPE_MDS); return ceph_monc_validate_auth(&mdsc->fsc->client->monc); } diff --git a/fs/ceph/super.c b/fs/ceph/super.c index f3639181546..f4fa5cf0cdf 100644 --- a/fs/ceph/super.c +++ b/fs/ceph/super.c @@ -70,8 +70,14 @@ static int ceph_statfs(struct dentry *dentry, struct kstatfs *buf) /* * express utilization in terms of large blocks to avoid * overflow on 32-bit machines. + * + * NOTE: for the time being, we make bsize == frsize to humor + * not-yet-ancient versions of glibc that are broken. + * Someday, we will probably want to report a real block + * size... whatever that may mean for a network file system! */ buf->f_bsize = 1 << CEPH_BLOCK_SHIFT; + buf->f_frsize = 1 << CEPH_BLOCK_SHIFT; buf->f_blocks = le64_to_cpu(st.kb) >> (CEPH_BLOCK_SHIFT-10); buf->f_bfree = le64_to_cpu(st.kb_avail) >> (CEPH_BLOCK_SHIFT-10); buf->f_bavail = le64_to_cpu(st.kb_avail) >> (CEPH_BLOCK_SHIFT-10); @@ -79,7 +85,6 @@ static int ceph_statfs(struct dentry *dentry, struct kstatfs *buf) buf->f_files = le64_to_cpu(st.num_objects); buf->f_ffree = -1; buf->f_namelen = NAME_MAX; - buf->f_frsize = PAGE_CACHE_SIZE; /* leave fsid little-endian, regardless of host endianness */ fsid = *(u64 *)(&monmap->fsid) ^ *((u64 *)&monmap->fsid + 1); diff --git a/fs/ceph/super.h b/fs/ceph/super.h index fc35036d258..d2e01a61f9d 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h @@ -21,7 +21,7 @@ /* large granularity for statfs utilization stats to facilitate * large volume sizes on 32-bit machines. */ -#define CEPH_BLOCK_SHIFT 20 /* 1 MB */ +#define CEPH_BLOCK_SHIFT 22 /* 4 MB */ #define CEPH_BLOCK (1 << CEPH_BLOCK_SHIFT) #define CEPH_MOUNT_OPT_DIRSTAT (1<<4) /* `cat dirname` for stats */ @@ -847,8 +847,13 @@ extern const struct export_operations ceph_export_ops; extern int ceph_lock(struct file *file, int cmd, struct file_lock *fl); extern int ceph_flock(struct file *file, int cmd, struct file_lock *fl); extern void ceph_count_locks(struct inode *inode, int *p_num, int *f_num); -extern int ceph_encode_locks(struct inode *i, struct ceph_pagelist *p, - int p_locks, int f_locks); +extern int ceph_encode_locks_to_buffer(struct inode *inode, + struct ceph_filelock *flocks, + int num_fcntl_locks, + int num_flock_locks); +extern int ceph_locks_to_pagelist(struct ceph_filelock *flocks, + struct ceph_pagelist *pagelist, + int num_fcntl_locks, int num_flock_locks); extern int lock_to_ceph_filelock(struct file_lock *fl, struct ceph_filelock *c); /* debugfs.c */ diff --git a/fs/cifs/asn1.c b/fs/cifs/asn1.c index cfd1ce34e0b..1d36db11477 100644 --- a/fs/cifs/asn1.c +++ b/fs/cifs/asn1.c @@ -614,53 +614,10 @@ decode_negTokenInit(unsigned char *security_blob, int length, } } - /* mechlistMIC */ - if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { - /* Check if we have reached the end of the blob, but with - no mechListMic (e.g. NTLMSSP instead of KRB5) */ - if (ctx.error == ASN1_ERR_DEC_EMPTY) - goto decode_negtoken_exit; - cFYI(1, "Error decoding last part negTokenInit exit3"); - return 0; - } else if ((cls != ASN1_CTX) || (con != ASN1_CON)) { - /* tag = 3 indicating mechListMIC */ - cFYI(1, "Exit 4 cls = %d con = %d tag = %d end = %p (%d)", - cls, con, tag, end, *end); - return 0; - } - - /* sequence */ - if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { - cFYI(1, "Error decoding last part negTokenInit exit5"); - return 0; - } else if ((cls != ASN1_UNI) || (con != ASN1_CON) - || (tag != ASN1_SEQ)) { - cFYI(1, "cls = %d con = %d tag = %d end = %p (%d)", - cls, con, tag, end, *end); - } - - /* sequence of */ - if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { - cFYI(1, "Error decoding last part negTokenInit exit 7"); - return 0; - } else if ((cls != ASN1_CTX) || (con != ASN1_CON)) { - cFYI(1, "Exit 8 cls = %d con = %d tag = %d end = %p (%d)", - cls, con, tag, end, *end); - return 0; - } - - /* general string */ - if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { - cFYI(1, "Error decoding last part negTokenInit exit9"); - return 0; - } else if ((cls != ASN1_UNI) || (con != ASN1_PRI) - || (tag != ASN1_GENSTR)) { - cFYI(1, "Exit10 cls = %d con = %d tag = %d end = %p (%d)", - cls, con, tag, end, *end); - return 0; - } - cFYI(1, "Need to call asn1_octets_decode() function for %s", - ctx.pointer); /* is this UTF-8 or ASCII? */ -decode_negtoken_exit: + /* + * We currently ignore anything at the end of the SPNEGO blob after + * the mechTypes have been parsed, since none of that info is + * used at the moment. + */ return 1; } diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c index 22631445a4a..d0e5fc57bfa 100644 --- a/fs/cifs/cifs_dfs_ref.c +++ b/fs/cifs/cifs_dfs_ref.c @@ -18,6 +18,7 @@ #include #include #include +#include #include "cifsglob.h" #include "cifsproto.h" #include "cifsfs.h" @@ -150,7 +151,8 @@ char *cifs_compose_mount_options(const char *sb_mountdata, * assuming that we have 'unc=' and 'ip=' in * the original sb_mountdata */ - md_len = strlen(sb_mountdata) + rc + strlen(ref->node_name) + 12; + md_len = strlen(sb_mountdata) + rc + strlen(ref->node_name) + 12 + + INET6_ADDRSTRLEN; mountdata = kzalloc(md_len+1, GFP_KERNEL); if (mountdata == NULL) { rc = -ENOMEM; diff --git a/fs/cifs/cifs_unicode.h b/fs/cifs/cifs_unicode.h index a513a546700..f2b2ffd452c 100644 --- a/fs/cifs/cifs_unicode.h +++ b/fs/cifs/cifs_unicode.h @@ -323,14 +323,14 @@ UniToupper(register wchar_t uc) /* * UniStrupr: Upper case a unicode string */ -static inline wchar_t * -UniStrupr(register wchar_t *upin) +static inline __le16 * +UniStrupr(register __le16 *upin) { - register wchar_t *up; + register __le16 *up; up = upin; while (*up) { /* For all characters */ - *up = UniToupper(*up); + *up = cpu_to_le16(UniToupper(le16_to_cpu(*up))); up++; } return upin; /* Return input pointer */ diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c index 63c460e503b..6dd3b61ea57 100644 --- a/fs/cifs/cifsencrypt.c +++ b/fs/cifs/cifsencrypt.c @@ -369,7 +369,7 @@ find_domain_name(struct cifs_ses *ses, const struct nls_table *nls_cp) if (blobptr + attrsize > blobend) break; if (type == NTLMSSP_AV_NB_DOMAIN_NAME) { - if (!attrsize) + if (!attrsize || attrsize >= CIFS_MAX_DOMAINNAME_LEN) break; if (!ses->domainName) { ses->domainName = @@ -394,7 +394,7 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash, int rc = 0; int len; char nt_hash[CIFS_NTHASH_SIZE]; - wchar_t *user; + __le16 *user; wchar_t *domain; wchar_t *server; @@ -419,7 +419,7 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash, return rc; } - /* convert ses->user_name to unicode and uppercase */ + /* convert ses->user_name to unicode */ len = ses->user_name ? strlen(ses->user_name) : 0; user = kmalloc(2 + (len * 2), GFP_KERNEL); if (user == NULL) { @@ -429,7 +429,7 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash, } if (len) { - len = cifs_strtoUTF16((__le16 *)user, ses->user_name, len, nls_cp); + len = cifs_strtoUTF16(user, ses->user_name, len, nls_cp); UniStrupr(user); } else { memset(user, '\0', 2); diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 541ef81f6ae..d7561e03870 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -557,6 +557,11 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb) dentry = ERR_PTR(-ENOENT); break; } + if (!S_ISDIR(dir->i_mode)) { + dput(dentry); + dentry = ERR_PTR(-ENOTDIR); + break; + } /* skip separators */ while (*s == sep) diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 73fea285b84..a5fcf1957cb 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -38,6 +38,7 @@ #define MAX_TREE_SIZE (2 + MAX_SERVER_SIZE + 1 + MAX_SHARE_SIZE + 1) #define MAX_SERVER_SIZE 15 #define MAX_SHARE_SIZE 80 +#define CIFS_MAX_DOMAINNAME_LEN 256 /* max domain name length */ #define MAX_USERNAME_SIZE 256 /* reasonable maximum for current servers */ #define MAX_PASSWORD_SIZE 512 /* max for windows seems to be 256 wide chars */ diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index f771e9f98f9..e7fe81d3a56 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -1576,14 +1576,24 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, } break; case Opt_blank_pass: - vol->password = NULL; - break; - case Opt_pass: /* passwords have to be handled differently * to allow the character used for deliminator * to be passed within them */ + /* + * Check if this is a case where the password + * starts with a delimiter + */ + tmp_end = strchr(data, '='); + tmp_end++; + if (!(tmp_end < end && tmp_end[1] == delim)) { + /* No it is not. Set the password to NULL */ + vol->password = NULL; + break; + } + /* Yes it is. Drop down to Opt_pass below.*/ + case Opt_pass: /* Obtain the value string */ value = strchr(data, '='); value++; @@ -1688,7 +1698,8 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, if (string == NULL) goto out_nomem; - if (strnlen(string, 256) == 256) { + if (strnlen(string, CIFS_MAX_DOMAINNAME_LEN) + == CIFS_MAX_DOMAINNAME_LEN) { printk(KERN_WARNING "CIFS: domain name too" " long\n"); goto cifs_parse_mount_err; @@ -2346,8 +2357,8 @@ cifs_put_smb_ses(struct cifs_ses *ses) #ifdef CONFIG_KEYS -/* strlen("cifs:a:") + INET6_ADDRSTRLEN + 1 */ -#define CIFSCREDS_DESC_SIZE (7 + INET6_ADDRSTRLEN + 1) +/* strlen("cifs:a:") + CIFS_MAX_DOMAINNAME_LEN + 1 */ +#define CIFSCREDS_DESC_SIZE (7 + CIFS_MAX_DOMAINNAME_LEN + 1) /* Populate username and pw fields from keyring if possible */ static int diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 745da3d0653..43944c6d7b4 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -173,7 +173,8 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr) if (fattr->cf_flags & CIFS_FATTR_DFS_REFERRAL) inode->i_flags |= S_AUTOMOUNT; - cifs_set_ops(inode); + if (inode->i_state & I_NEW) + cifs_set_ops(inode); } void @@ -548,6 +549,11 @@ cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info, fattr->cf_mode &= ~(S_IWUGO); fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks); + if (fattr->cf_nlink < 1) { + cFYI(1, "replacing bogus file nlink value %u\n", + fattr->cf_nlink); + fattr->cf_nlink = 1; + } } fattr->cf_uid = cifs_sb->mnt_uid; diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index 551d0c2b973..de9b1c1a4fb 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c @@ -198,7 +198,7 @@ static void unicode_domain_string(char **pbcc_area, struct cifs_ses *ses, bytes_ret = 0; } else bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, ses->domainName, - 256, nls_cp); + CIFS_MAX_DOMAINNAME_LEN, nls_cp); bcc_ptr += 2 * bytes_ret; bcc_ptr += 2; /* account for null terminator */ @@ -256,8 +256,8 @@ static void ascii_ssetup_strings(char **pbcc_area, struct cifs_ses *ses, /* copy domain */ if (ses->domainName != NULL) { - strncpy(bcc_ptr, ses->domainName, 256); - bcc_ptr += strnlen(ses->domainName, 256); + strncpy(bcc_ptr, ses->domainName, CIFS_MAX_DOMAINNAME_LEN); + bcc_ptr += strnlen(ses->domainName, CIFS_MAX_DOMAINNAME_LEN); } /* else we will send a null domain name so the server will default to its own domain */ *bcc_ptr = 0; diff --git a/fs/compat.c b/fs/compat.c index 2b371b38911..56acdcb84fb 100644 --- a/fs/compat.c +++ b/fs/compat.c @@ -558,6 +558,10 @@ ssize_t compat_rw_copy_check_uvector(int type, } *ret_pointer = iov; + ret = -EFAULT; + if (!access_ok(VERIFY_READ, uvector, nr_segs*sizeof(*uvector))) + goto out; + /* * Single unix specification: * We should -EINVAL if an element length is not >= 0 and fitting an @@ -1089,17 +1093,12 @@ static ssize_t compat_do_readv_writev(int type, struct file *file, if (!file->f_op) goto out; - ret = -EFAULT; - if (!access_ok(VERIFY_READ, uvector, nr_segs*sizeof(*uvector))) - goto out; - - tot_len = compat_rw_copy_check_uvector(type, uvector, nr_segs, + ret = compat_rw_copy_check_uvector(type, uvector, nr_segs, UIO_FASTIOV, iovstack, &iov, 1); - if (tot_len == 0) { - ret = 0; + if (ret <= 0) goto out; - } + tot_len = ret; ret = rw_verify_area(type, file, pos, tot_len); if (ret < 0) goto out; diff --git a/fs/dcache.c b/fs/dcache.c index f104945dcc7..9d39de40909 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -1238,8 +1238,10 @@ void shrink_dcache_parent(struct dentry * parent) LIST_HEAD(dispose); int found; - while ((found = select_parent(parent, &dispose)) != 0) + while ((found = select_parent(parent, &dispose)) != 0) { shrink_dentry_list(&dispose); + cond_resched(); + } } EXPORT_SYMBOL(shrink_dcache_parent); @@ -1554,7 +1556,7 @@ EXPORT_SYMBOL(d_find_any_alias); */ struct dentry *d_obtain_alias(struct inode *inode) { - static const struct qstr anonstring = { .name = "" }; + static const struct qstr anonstring = { .name = "/", .len = 1 }; struct dentry *tmp; struct dentry *res; diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index b80bc846a15..9dc6e76b7a9 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c @@ -527,8 +527,7 @@ EXPORT_SYMBOL_GPL(debugfs_remove); */ void debugfs_remove_recursive(struct dentry *dentry) { - struct dentry *child; - struct dentry *parent; + struct dentry *child, *next, *parent; if (!dentry) return; @@ -538,61 +537,37 @@ void debugfs_remove_recursive(struct dentry *dentry) return; parent = dentry; + down: mutex_lock(&parent->d_inode->i_mutex); + list_for_each_entry_safe(child, next, &parent->d_subdirs, d_u.d_child) { + if (!debugfs_positive(child)) + continue; - while (1) { - /* - * When all dentries under "parent" has been removed, - * walk up the tree until we reach our starting point. - */ - if (list_empty(&parent->d_subdirs)) { - mutex_unlock(&parent->d_inode->i_mutex); - if (parent == dentry) - break; - parent = parent->d_parent; - mutex_lock(&parent->d_inode->i_mutex); - } - child = list_entry(parent->d_subdirs.next, struct dentry, - d_u.d_child); - next_sibling: - - /* - * If "child" isn't empty, walk down the tree and - * remove all its descendants first. - */ + /* perhaps simple_empty(child) makes more sense */ if (!list_empty(&child->d_subdirs)) { mutex_unlock(&parent->d_inode->i_mutex); parent = child; - mutex_lock(&parent->d_inode->i_mutex); - continue; + goto down; } - __debugfs_remove(child, parent); - if (parent->d_subdirs.next == &child->d_u.d_child) { - /* - * Try the next sibling. - */ - if (child->d_u.d_child.next != &parent->d_subdirs) { - child = list_entry(child->d_u.d_child.next, - struct dentry, - d_u.d_child); - goto next_sibling; - } - - /* - * Avoid infinite loop if we fail to remove - * one dentry. - */ - mutex_unlock(&parent->d_inode->i_mutex); - break; - } - simple_release_fs(&debugfs_mount, &debugfs_mount_count); + up: + if (!__debugfs_remove(child, parent)) + simple_release_fs(&debugfs_mount, &debugfs_mount_count); } - parent = dentry->d_parent; + mutex_unlock(&parent->d_inode->i_mutex); + child = parent; + parent = parent->d_parent; mutex_lock(&parent->d_inode->i_mutex); - __debugfs_remove(dentry, parent); + + if (child != dentry) { + next = list_entry(child->d_u.d_child.next, struct dentry, + d_u.d_child); + goto up; + } + + if (!__debugfs_remove(child, parent)) + simple_release_fs(&debugfs_mount, &debugfs_mount_count); mutex_unlock(&parent->d_inode->i_mutex); - simple_release_fs(&debugfs_mount, &debugfs_mount_count); } EXPORT_SYMBOL_GPL(debugfs_remove_recursive); diff --git a/fs/direct-io.c b/fs/direct-io.c index f4aadd15b61..29c4fdab29d 100644 --- a/fs/direct-io.c +++ b/fs/direct-io.c @@ -305,9 +305,9 @@ static ssize_t dio_complete(struct dio *dio, loff_t offset, ssize_t ret, bool is dio->end_io(dio->iocb, offset, transferred, dio->private, ret, is_async); } else { + inode_dio_done(dio->inode); if (is_async) aio_complete(dio->iocb, ret, 0); - inode_dio_done(dio->inode); } return ret; diff --git a/fs/exec.c b/fs/exec.c index 51d86297363..0ea0b4c476d 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -627,7 +627,7 @@ static int shift_arg_pages(struct vm_area_struct *vma, unsigned long shift) * when the old and new regions overlap clear from new_end. */ free_pgd_range(&tlb, new_end, old_end, new_end, - vma->vm_next ? vma->vm_next->vm_start : 0); + vma->vm_next ? vma->vm_next->vm_start : USER_PGTABLES_CEILING); } else { /* * otherwise, clean from old_start; this is done to not touch @@ -636,7 +636,7 @@ static int shift_arg_pages(struct vm_area_struct *vma, unsigned long shift) * for the others its just a little faster. */ free_pgd_range(&tlb, old_start, old_end, new_end, - vma->vm_next ? vma->vm_next->vm_start : 0); + vma->vm_next ? vma->vm_next->vm_start : USER_PGTABLES_CEILING); } tlb_finish_mmu(&tlb, new_end, old_end); @@ -1163,13 +1163,6 @@ void setup_new_exec(struct linux_binprm * bprm) set_dumpable(current->mm, suid_dumpable); } - /* - * Flush performance counters when crossing a - * security domain: - */ - if (!get_dumpable(current->mm)) - perf_event_exit_task(current); - /* An exec changes our domain. We are no longer part of the thread group */ @@ -1233,6 +1226,15 @@ void install_exec_creds(struct linux_binprm *bprm) commit_creds(bprm->cred); bprm->cred = NULL; + + /* + * Disable monitoring for regular users + * when executing setuid binaries. Must + * wait until new credentials are committed + * by commit_creds() above + */ + if (get_dumpable(current->mm) != SUID_DUMP_USER) + perf_event_exit_task(current); /* * cred_guard_mutex must be held at least to this point to prevent * ptrace_attach() from altering our determination of the task's @@ -1389,6 +1391,10 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) struct linux_binfmt *fmt; pid_t old_pid, old_vpid; + /* This allows 4 levels of binfmt rewrites before failing hard. */ + if (depth > 5) + return -ELOOP; + retval = security_bprm_check(bprm); if (retval) return retval; @@ -1413,12 +1419,8 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) if (!try_module_get(fmt->module)) continue; read_unlock(&binfmt_lock); + bprm->recursion_depth = depth + 1; retval = fn(bprm, regs); - /* - * Restore the depth counter to its starting value - * in this call, so we don't have to rely on every - * load_binary function to restore it on return. - */ bprm->recursion_depth = depth; if (retval >= 0) { if (depth == 0) { diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index 075281734fc..aad0f3989e5 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c @@ -218,7 +218,8 @@ void ext3_evict_inode (struct inode *inode) */ if (inode->i_nlink && ext3_should_journal_data(inode) && EXT3_SB(inode->i_sb)->s_journal && - (S_ISLNK(inode->i_mode) || S_ISREG(inode->i_mode))) { + (S_ISLNK(inode->i_mode) || S_ISREG(inode->i_mode)) && + inode->i_ino != EXT3_JOURNAL_INO) { tid_t commit_tid = atomic_read(&ei->i_datasync_tid); journal_t *journal = EXT3_SB(inode->i_sb)->s_journal; diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c index d7940b24cf6..fbb9b82b59c 100644 --- a/fs/ext3/namei.c +++ b/fs/ext3/namei.c @@ -573,11 +573,8 @@ static int htree_dirblock_to_tree(struct file *dir_file, if (!ext3_check_dir_entry("htree_dirblock_to_tree", dir, de, bh, (block<i_sb)) +((char *)de - bh->b_data))) { - /* On error, skip the f_pos to the next block. */ - dir_file->f_pos = (dir_file->f_pos | - (dir->i_sb->s_blocksize - 1)) + 1; - brelse (bh); - return count; + /* silently ignore the rest of the block */ + break; } ext3fs_dirhash(de->name, de->name_len, hinfo); if ((hinfo->hash < start_hash) || diff --git a/fs/ext3/super.c b/fs/ext3/super.c index cf0b5921cf0..ef4c812c7a6 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c @@ -364,7 +364,7 @@ static struct block_device *ext3_blkdev_get(dev_t dev, struct super_block *sb) return bdev; fail: - ext3_msg(sb, "error: failed to open journal device %s: %ld", + ext3_msg(sb, KERN_ERR, "error: failed to open journal device %s: %ld", __bdevname(dev, b), PTR_ERR(bdev)); return NULL; @@ -891,7 +891,7 @@ static ext3_fsblk_t get_sb_block(void **data, struct super_block *sb) /*todo: use simple_strtoll with >32bit ext3 */ sb_block = simple_strtoul(options, &options, 0); if (*options && *options != ',') { - ext3_msg(sb, "error: invalid sb specification: %s", + ext3_msg(sb, KERN_ERR, "error: invalid sb specification: %s", (char *) *data); return 1; } diff --git a/fs/ext4/Kconfig b/fs/ext4/Kconfig index 9ed1bb1f319..5459168d9db 100644 --- a/fs/ext4/Kconfig +++ b/fs/ext4/Kconfig @@ -82,4 +82,5 @@ config EXT4_DEBUG Enables run-time debugging support for the ext4 filesystem. If you select Y here, then you will be able to turn on debugging - with a command such as "echo 1 > /sys/kernel/debug/ext4/mballoc-debug" + with a command such as: + echo 1 > /sys/module/ext4/parameters/mballoc_debug diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index df76291d692..d33733eaa1b 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c @@ -326,7 +326,7 @@ static int ext4_valid_block_bitmap(struct super_block *sb, return 0; } /** - * ext4_read_block_bitmap() + * ext4_read_block_bitmap_nowait() * @sb: super block * @block_group: given block group * @@ -422,6 +422,8 @@ ext4_read_block_bitmap(struct super_block *sb, ext4_group_t block_group) struct buffer_head *bh; bh = ext4_read_block_bitmap_nowait(sb, block_group); + if (!bh) + return NULL; if (ext4_wait_block_bitmap(sb, block_group, bh)) { put_bh(bh); return NULL; @@ -447,11 +449,16 @@ static int ext4_has_free_clusters(struct ext4_sb_info *sbi, free_clusters = percpu_counter_read_positive(fcc); dirty_clusters = percpu_counter_read_positive(dcc); - root_clusters = EXT4_B2C(sbi, ext4_r_blocks_count(sbi->s_es)); + + /* + * r_blocks_count should always be multiple of the cluster ratio so + * we are safe to do a plane bit shift only. + */ + root_clusters = ext4_r_blocks_count(sbi->s_es) >> sbi->s_cluster_bits; if (free_clusters - (nclusters + root_clusters + dirty_clusters) < EXT4_FREECLUSTERS_WATERMARK) { - free_clusters = EXT4_C2B(sbi, percpu_counter_sum_positive(fcc)); + free_clusters = percpu_counter_sum_positive(fcc); dirty_clusters = percpu_counter_sum_positive(dcc); } /* Check whether we have space after accounting for current @@ -593,7 +600,7 @@ ext4_fsblk_t ext4_count_free_clusters(struct super_block *sb) brelse(bitmap_bh); printk(KERN_DEBUG "ext4_count_free_clusters: stored = %llu" ", computed = %llu, %llu\n", - EXT4_B2C(EXT4_SB(sb), ext4_free_blocks_count(es)), + EXT4_NUM_B2C(EXT4_SB(sb), ext4_free_blocks_count(es)), desc_count, bitmap_count); return bitmap_count; #else diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 47d1c8cda0c..d918b55f009 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -316,9 +316,9 @@ struct ext4_group_desc */ struct flex_groups { - atomic_t free_inodes; - atomic_t free_clusters; - atomic_t used_dirs; + atomic64_t free_clusters; + atomic_t free_inodes; + atomic_t used_dirs; }; #define EXT4_BG_INODE_UNINIT 0x0001 /* Inode table/bitmap not in use */ diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c index aca17901758..d0b8f9838e8 100644 --- a/fs/ext4/ext4_jbd2.c +++ b/fs/ext4/ext4_jbd2.c @@ -109,10 +109,10 @@ int __ext4_handle_dirty_metadata(const char *where, unsigned int line, if (ext4_handle_valid(handle)) { err = jbd2_journal_dirty_metadata(handle, bh); - if (err) { - /* Errors can only happen if there is a bug */ - handle->h_err = err; - __ext4_journal_stop(where, line, handle); + /* Errors can only happen if there is a bug */ + if (WARN_ON_ONCE(err)) { + ext4_journal_abort_handle(where, line, __func__, bh, + handle, err); } } else { if (inode) diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h index 83b20fcf940..6b23a96e809 100644 --- a/fs/ext4/ext4_jbd2.h +++ b/fs/ext4/ext4_jbd2.h @@ -164,16 +164,20 @@ static inline void ext4_journal_callback_add(handle_t *handle, * ext4_journal_callback_del: delete a registered callback * @handle: active journal transaction handle on which callback was registered * @jce: registered journal callback entry to unregister + * Return true if object was sucessfully removed */ -static inline void ext4_journal_callback_del(handle_t *handle, +static inline bool ext4_journal_callback_try_del(handle_t *handle, struct ext4_journal_cb_entry *jce) { + bool deleted; struct ext4_sb_info *sbi = EXT4_SB(handle->h_transaction->t_journal->j_private); spin_lock(&sbi->s_md_lock); + deleted = !list_empty(&jce->jce_list); list_del_init(&jce->jce_list); spin_unlock(&sbi->s_md_lock); + return deleted; } int diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 852d4c257ac..b9a3726ea04 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -2959,6 +2959,7 @@ static int ext4_split_extent(handle_t *handle, int err = 0; int uninitialized; int split_flag1, flags1; + int allocated = map->m_len; depth = ext_depth(inode); ex = path[depth].p_ext; @@ -2978,6 +2979,8 @@ static int ext4_split_extent(handle_t *handle, map->m_lblk + map->m_len, split_flag1, flags1); if (err) goto out; + } else { + allocated = ee_len - (map->m_lblk - ee_block); } ext4_ext_drop_refs(path); @@ -3000,7 +3003,7 @@ static int ext4_split_extent(handle_t *handle, ext4_ext_show_leaf(inode, path); out: - return err ? err : map->m_len; + return err ? err : allocated; } #define EXT4_EXT_ZERO_LEN 7 @@ -3668,6 +3671,7 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode, allocated - map->m_len); allocated = map->m_len; } + map->m_len = allocated; /* * If we have done fallocate with the offset that is already @@ -4709,7 +4713,7 @@ static int ext4_xattr_fiemap(struct inode *inode, error = ext4_get_inode_loc(inode, &iloc); if (error) return error; - physical = iloc.bh->b_blocknr << blockbits; + physical = (__u64)iloc.bh->b_blocknr << blockbits; offset = EXT4_GOOD_OLD_INODE_SIZE + EXT4_I(inode)->i_extra_isize; physical += offset; @@ -4717,7 +4721,7 @@ static int ext4_xattr_fiemap(struct inode *inode, flags |= FIEMAP_EXTENT_DATA_INLINE; brelse(iloc.bh); } else { /* external block */ - physical = EXT4_I(inode)->i_file_acl << blockbits; + physical = (__u64)EXT4_I(inode)->i_file_acl << blockbits; length = inode->i_sb->s_blocksize; } diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index 858f903818a..789e071d6dd 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c @@ -305,8 +305,8 @@ void ext4_free_inode(handle_t *handle, struct inode *inode) } struct orlov_stats { + __u64 free_clusters; __u32 free_inodes; - __u32 free_clusters; __u32 used_dirs; }; @@ -323,7 +323,7 @@ static void get_orlov_stats(struct super_block *sb, ext4_group_t g, if (flex_size > 1) { stats->free_inodes = atomic_read(&flex_group[g].free_inodes); - stats->free_clusters = atomic_read(&flex_group[g].free_clusters); + stats->free_clusters = atomic64_read(&flex_group[g].free_clusters); stats->used_dirs = atomic_read(&flex_group[g].used_dirs); return; } @@ -687,11 +687,8 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, umode_t mode, ino = ext4_find_next_zero_bit((unsigned long *) inode_bitmap_bh->b_data, EXT4_INODES_PER_GROUP(sb), ino); - if (ino >= EXT4_INODES_PER_GROUP(sb)) { - if (++group == ngroups) - group = 0; - continue; - } + if (ino >= EXT4_INODES_PER_GROUP(sb)) + goto next_group; if (group == 0 && (ino+1) < EXT4_FIRST_INO(sb)) { ext4_error(sb, "reserved inode found cleared - " "inode=%lu", ino + 1); @@ -709,6 +706,9 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, umode_t mode, goto got; /* we grabbed the inode! */ if (ino < EXT4_INODES_PER_GROUP(sb)) goto repeat_in_this_group; +next_group: + if (++group == ngroups) + group = 0; } err = -ENOSPC; goto out; diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 55190932862..1af3664690b 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -144,7 +144,8 @@ void ext4_evict_inode(struct inode *inode) * don't use page cache. */ if (ext4_should_journal_data(inode) && - (S_ISLNK(inode->i_mode) || S_ISREG(inode->i_mode))) { + (S_ISLNK(inode->i_mode) || S_ISREG(inode->i_mode)) && + inode->i_ino != EXT4_JOURNAL_INO) { journal_t *journal = EXT4_SB(inode->i_sb)->s_journal; tid_t commit_tid = EXT4_I(inode)->i_datasync_tid; @@ -4216,7 +4217,7 @@ int ext4_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) { struct inode *inode; - unsigned long delalloc_blocks; + unsigned long long delalloc_blocks; inode = dentry->d_inode; generic_fillattr(inode, stat); @@ -4233,7 +4234,7 @@ int ext4_getattr(struct vfsmount *mnt, struct dentry *dentry, */ delalloc_blocks = EXT4_I(inode)->i_reserved_data_blocks; - stat->blocks += (delalloc_blocks << inode->i_sb->s_blocksize_bits)>>9; + stat->blocks += delalloc_blocks << (inode->i_sb->s_blocksize_bits-9); return 0; } diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index e77c4fe665a..878484256a6 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -1980,7 +1980,11 @@ ext4_mb_regular_allocator(struct ext4_allocation_context *ac) group = ac->ac_g_ex.fe_group; for (i = 0; i < ngroups; group++, i++) { - if (group == ngroups) + /* + * Artificially restricted ngroups for non-extent + * files makes group > ngroups possible on first loop. + */ + if (group >= ngroups) group = 0; /* This now checks without needing the buddy page */ @@ -2813,8 +2817,8 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac, if (sbi->s_log_groups_per_flex) { ext4_group_t flex_group = ext4_flex_group(sbi, ac->ac_b_ex.fe_group); - atomic_sub(ac->ac_b_ex.fe_len, - &sbi->s_flex_groups[flex_group].free_clusters); + atomic64_sub(ac->ac_b_ex.fe_len, + &sbi->s_flex_groups[flex_group].free_clusters); } err = ext4_handle_dirty_metadata(handle, NULL, bitmap_bh); @@ -3433,7 +3437,7 @@ ext4_mb_new_inode_pa(struct ext4_allocation_context *ac) win = offs; ac->ac_b_ex.fe_logical = ac->ac_o_ex.fe_logical - - EXT4_B2C(sbi, win); + EXT4_NUM_B2C(sbi, win); BUG_ON(ac->ac_o_ex.fe_logical < ac->ac_b_ex.fe_logical); BUG_ON(ac->ac_o_ex.fe_len > ac->ac_b_ex.fe_len); } @@ -4126,7 +4130,7 @@ static void ext4_mb_add_n_trim(struct ext4_allocation_context *ac) /* The max size of hash table is PREALLOC_TB_SIZE */ order = PREALLOC_TB_SIZE - 1; /* Add the prealloc space to lg */ - rcu_read_lock(); + spin_lock(&lg->lg_prealloc_lock); list_for_each_entry_rcu(tmp_pa, &lg->lg_prealloc_list[order], pa_inode_list) { spin_lock(&tmp_pa->pa_lock); @@ -4150,12 +4154,12 @@ static void ext4_mb_add_n_trim(struct ext4_allocation_context *ac) if (!added) list_add_tail_rcu(&pa->pa_inode_list, &lg->lg_prealloc_list[order]); - rcu_read_unlock(); + spin_unlock(&lg->lg_prealloc_lock); /* Now trim the list to be not more than 8 elements */ if (lg_prealloc_count > 8) { ext4_mb_discard_lg_preallocations(sb, lg, - order, lg_prealloc_count); + order, lg_prealloc_count); return; } return ; @@ -4436,11 +4440,11 @@ ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b, node = rb_prev(new_node); if (node) { entry = rb_entry(node, struct ext4_free_data, efd_node); - if (can_merge(entry, new_entry)) { + if (can_merge(entry, new_entry) && + ext4_journal_callback_try_del(handle, &entry->efd_jce)) { new_entry->efd_start_cluster = entry->efd_start_cluster; new_entry->efd_count += entry->efd_count; rb_erase(node, &(db->bb_free_root)); - ext4_journal_callback_del(handle, &entry->efd_jce); kmem_cache_free(ext4_free_data_cachep, entry); } } @@ -4448,10 +4452,10 @@ ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b, node = rb_next(new_node); if (node) { entry = rb_entry(node, struct ext4_free_data, efd_node); - if (can_merge(new_entry, entry)) { + if (can_merge(new_entry, entry) && + ext4_journal_callback_try_del(handle, &entry->efd_jce)) { new_entry->efd_count += entry->efd_count; rb_erase(node, &(db->bb_free_root)); - ext4_journal_callback_del(handle, &entry->efd_jce); kmem_cache_free(ext4_free_data_cachep, entry); } } @@ -4577,7 +4581,7 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode, EXT4_BLOCKS_PER_GROUP(sb); count -= overflow; } - count_clusters = EXT4_B2C(sbi, count); + count_clusters = EXT4_NUM_B2C(sbi, count); bitmap_bh = ext4_read_block_bitmap(sb, block_group); if (!bitmap_bh) { err = -EIO; @@ -4635,11 +4639,16 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode, * blocks being freed are metadata. these blocks shouldn't * be used until this transaction is committed */ + retry: new_entry = kmem_cache_alloc(ext4_free_data_cachep, GFP_NOFS); if (!new_entry) { - ext4_mb_unload_buddy(&e4b); - err = -ENOMEM; - goto error_return; + /* + * We use a retry loop because + * ext4_free_blocks() is not allowed to fail. + */ + cond_resched(); + congestion_wait(BLK_RW_ASYNC, HZ/50); + goto retry; } new_entry->efd_start_cluster = bit; new_entry->efd_group = block_group; @@ -4667,8 +4676,8 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode, if (sbi->s_log_groups_per_flex) { ext4_group_t flex_group = ext4_flex_group(sbi, block_group); - atomic_add(count_clusters, - &sbi->s_flex_groups[flex_group].free_clusters); + atomic64_add(count_clusters, + &sbi->s_flex_groups[flex_group].free_clusters); } ext4_mb_unload_buddy(&e4b); @@ -4808,12 +4817,12 @@ int ext4_group_add_blocks(handle_t *handle, struct super_block *sb, desc->bg_checksum = ext4_group_desc_csum(sbi, block_group, desc); ext4_unlock_group(sb, block_group); percpu_counter_add(&sbi->s_freeclusters_counter, - EXT4_B2C(sbi, blocks_freed)); + EXT4_NUM_B2C(sbi, blocks_freed)); if (sbi->s_log_groups_per_flex) { ext4_group_t flex_group = ext4_flex_group(sbi, block_group); - atomic_add(EXT4_B2C(sbi, blocks_freed), - &sbi->s_flex_groups[flex_group].free_clusters); + atomic64_add(EXT4_NUM_B2C(sbi, blocks_freed), + &sbi->s_flex_groups[flex_group].free_clusters); } ext4_mb_unload_buddy(&e4b); diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index ac769399b14..9fb3fae4898 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -585,11 +585,8 @@ static int htree_dirblock_to_tree(struct file *dir_file, if (ext4_check_dir_entry(dir, NULL, de, bh, (block<i_sb)) + ((char *)de - bh->b_data))) { - /* On error, skip the f_pos to the next block. */ - dir_file->f_pos = (dir_file->f_pos | - (dir->i_sb->s_blocksize - 1)) + 1; - brelse(bh); - return count; + /* silently ignore the rest of the block */ + break; } ext4fs_dirhash(de->name, de->name_len, hinfo); if ((hinfo->hash < start_hash) || diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index 231cacb8f64..86a8c88dc29 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c @@ -1112,7 +1112,7 @@ static int ext4_setup_new_descs(handle_t *handle, struct super_block *sb, ext4_inode_bitmap_set(sb, gdp, group_data->inode_bitmap); ext4_inode_table_set(sb, gdp, group_data->inode_table); ext4_free_group_clusters_set(sb, gdp, - EXT4_B2C(sbi, group_data->free_blocks_count)); + EXT4_NUM_B2C(sbi, group_data->free_blocks_count)); ext4_free_inodes_set(sb, gdp, EXT4_INODES_PER_GROUP(sb)); gdp->bg_flags = cpu_to_le16(*bg_flags); gdp->bg_checksum = ext4_group_desc_csum(sbi, group, gdp); @@ -1202,6 +1202,8 @@ static void ext4_update_super(struct super_block *sb, /* Update the global fs size fields */ sbi->s_groups_count += flex_gd->count; + sbi->s_blockfile_groups = min_t(ext4_group_t, sbi->s_groups_count, + (EXT4_MAX_BLOCK_FILE_PHYS / EXT4_BLOCKS_PER_GROUP(sb))); /* Update the reserved block counts only once the new group is * active. */ @@ -1210,7 +1212,7 @@ static void ext4_update_super(struct super_block *sb, /* Update the free space counts */ percpu_counter_add(&sbi->s_freeclusters_counter, - EXT4_B2C(sbi, free_blocks)); + EXT4_NUM_B2C(sbi, free_blocks)); percpu_counter_add(&sbi->s_freeinodes_counter, EXT4_INODES_PER_GROUP(sb) * flex_gd->count); @@ -1219,8 +1221,8 @@ static void ext4_update_super(struct super_block *sb, sbi->s_log_groups_per_flex) { ext4_group_t flex_group; flex_group = ext4_flex_group(sbi, group_data[0].group); - atomic_add(EXT4_B2C(sbi, free_blocks), - &sbi->s_flex_groups[flex_group].free_clusters); + atomic64_add(EXT4_NUM_B2C(sbi, free_blocks), + &sbi->s_flex_groups[flex_group].free_clusters); atomic_add(EXT4_INODES_PER_GROUP(sb) * flex_gd->count, &sbi->s_flex_groups[flex_group].free_inodes); } @@ -1628,6 +1630,10 @@ int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count) return 0; ext4_get_group_no_and_offset(sb, n_blocks_count - 1, &n_group, &offset); + if (n_group > (0xFFFFFFFFUL / EXT4_INODES_PER_GROUP(sb))) { + ext4_warning(sb, "resize would cause inodes_count overflow"); + return -EINVAL; + } ext4_get_group_no_and_offset(sb, o_blocks_count - 1, &o_group, &offset); n_desc_blocks = (n_group + EXT4_DESC_PER_BLOCK(sb)) / diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 288f4c61e97..8bbb14c5f77 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -437,10 +437,13 @@ static void ext4_journal_commit_callback(journal_t *journal, transaction_t *txn) struct super_block *sb = journal->j_private; struct ext4_sb_info *sbi = EXT4_SB(sb); int error = is_journal_aborted(journal); - struct ext4_journal_cb_entry *jce, *tmp; + struct ext4_journal_cb_entry *jce; + BUG_ON(txn->t_state == T_FINISHED); spin_lock(&sbi->s_md_lock); - list_for_each_entry_safe(jce, tmp, &txn->t_private_list, jce_list) { + while (!list_empty(&txn->t_private_list)) { + jce = list_entry(txn->t_private_list.next, + struct ext4_journal_cb_entry, jce_list); list_del_init(&jce->jce_list); spin_unlock(&sbi->s_md_lock); jce->jce_func(sb, jce, error); @@ -1907,8 +1910,8 @@ static int ext4_fill_flex_info(struct super_block *sb) flex_group = ext4_flex_group(sbi, i); atomic_add(ext4_free_inodes_count(sb, gdp), &sbi->s_flex_groups[flex_group].free_inodes); - atomic_add(ext4_free_group_clusters(sb, gdp), - &sbi->s_flex_groups[flex_group].free_clusters); + atomic64_add(ext4_free_group_clusters(sb, gdp), + &sbi->s_flex_groups[flex_group].free_clusters); atomic_add(ext4_used_dirs_count(sb, gdp), &sbi->s_flex_groups[flex_group].used_dirs); } @@ -3229,7 +3232,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) } if (test_opt(sb, DIOREAD_NOLOCK)) { ext4_msg(sb, KERN_ERR, "can't mount with " - "both data=journal and delalloc"); + "both data=journal and dioread_nolock"); goto failed_mount; } if (test_opt(sb, DELALLOC)) @@ -4394,6 +4397,21 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data) goto restore_opts; } + if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA) { + if (test_opt2(sb, EXPLICIT_DELALLOC)) { + ext4_msg(sb, KERN_ERR, "can't mount with " + "both data=journal and delalloc"); + err = -EINVAL; + goto restore_opts; + } + if (test_opt(sb, DIOREAD_NOLOCK)) { + ext4_msg(sb, KERN_ERR, "can't mount with " + "both data=journal and dioread_nolock"); + err = -EINVAL; + goto restore_opts; + } + } + if (sbi->s_mount_flags & EXT4_MF_FS_ABORTED) ext4_abort(sb, "Abort forced by user"); diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c index e88748e55c0..e712a8cb165 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c @@ -495,7 +495,7 @@ ext4_xattr_release_block(handle_t *handle, struct inode *inode, error = ext4_handle_dirty_metadata(handle, inode, bh); if (IS_SYNC(inode)) ext4_handle_sync(handle); - dquot_free_block(inode, 1); + dquot_free_block(inode, EXT4_C2B(EXT4_SB(inode->i_sb), 1)); ea_bdebug(bh, "refcount now=%d; releasing", le32_to_cpu(BHDR(bh)->h_refcount)); } @@ -784,7 +784,8 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode, else { /* The old block is released after updating the inode. */ - error = dquot_alloc_block(inode, 1); + error = dquot_alloc_block(inode, + EXT4_C2B(EXT4_SB(sb), 1)); if (error) goto cleanup; error = ext4_journal_get_write_access(handle, @@ -880,7 +881,7 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode, return error; cleanup_dquot: - dquot_free_block(inode, 1); + dquot_free_block(inode, EXT4_C2B(EXT4_SB(sb), 1)); goto cleanup; bad_block: diff --git a/fs/fat/inode.c b/fs/fat/inode.c index d403f76c5a6..fe6d3400045 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -1237,6 +1237,19 @@ static int fat_read_root(struct inode *inode) return 0; } +static unsigned long calc_fat_clusters(struct super_block *sb) +{ + struct msdos_sb_info *sbi = MSDOS_SB(sb); + + /* Divide first to avoid overflow */ + if (sbi->fat_bits != 12) { + unsigned long ent_per_sec = sb->s_blocksize * 8 / sbi->fat_bits; + return ent_per_sec * sbi->fat_length; + } + + return sbi->fat_length * sb->s_blocksize * 8 / sbi->fat_bits; +} + /* * Read the super block of an MS-DOS FS. */ @@ -1442,7 +1455,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat, sbi->fat_bits = (total_clusters > MAX_FAT12) ? 16 : 12; /* check that FAT table does not overflow */ - fat_clusters = sbi->fat_length * sb->s_blocksize * 8 / sbi->fat_bits; + fat_clusters = calc_fat_clusters(sb); total_clusters = min(total_clusters, fat_clusters - FAT_START_ENT); if (total_clusters > MAX_FAT(sb)) { if (!silent) diff --git a/fs/fscache/stats.c b/fs/fscache/stats.c index 4765190d537..73c0bd7f742 100644 --- a/fs/fscache/stats.c +++ b/fs/fscache/stats.c @@ -276,5 +276,5 @@ const struct file_operations fscache_stats_fops = { .open = fscache_stats_open, .read = seq_read, .llseek = seq_lseek, - .release = seq_release, + .release = single_release, }; diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index bc438320cac..d48478a864b 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -645,7 +645,14 @@ static int fuse_unlink(struct inode *dir, struct dentry *entry) spin_lock(&fc->lock); fi->attr_version = ++fc->attr_version; - drop_nlink(inode); + /* + * If i_nlink == 0 then unlink doesn't make sense, yet this can + * happen if userspace filesystem is careless. It would be + * difficult to enforce correct nlink usage so just ignore this + * condition here + */ + if (inode->i_nlink > 0) + drop_nlink(inode); spin_unlock(&fc->lock); fuse_invalidate_attr(inode); fuse_invalidate_attr(dir); diff --git a/fs/hfsplus/extents.c b/fs/hfsplus/extents.c index 5849e3ef35c..32b12e5e33c 100644 --- a/fs/hfsplus/extents.c +++ b/fs/hfsplus/extents.c @@ -517,7 +517,7 @@ void hfsplus_file_truncate(struct inode *inode) struct address_space *mapping = inode->i_mapping; struct page *page; void *fsdata; - u32 size = inode->i_size; + loff_t size = inode->i_size; res = pagecache_write_begin(NULL, mapping, size, 0, AOP_FLAG_UNINTERRUPTIBLE, diff --git a/fs/hpfs/map.c b/fs/hpfs/map.c index a790821366a..ea3d1ca43e1 100644 --- a/fs/hpfs/map.c +++ b/fs/hpfs/map.c @@ -17,7 +17,8 @@ unsigned int *hpfs_map_bitmap(struct super_block *s, unsigned bmp_block, struct quad_buffer_head *qbh, char *id) { secno sec; - if (hpfs_sb(s)->sb_chk) if (bmp_block * 16384 > hpfs_sb(s)->sb_fs_size) { + unsigned n_bands = (hpfs_sb(s)->sb_fs_size + 0x3fff) >> 14; + if (hpfs_sb(s)->sb_chk) if (bmp_block >= n_bands) { hpfs_error(s, "hpfs_map_bitmap called with bad parameter: %08x at %s", bmp_block, id); return NULL; } diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c index 54f6eccb79d..0bf578dbfce 100644 --- a/fs/hpfs/super.c +++ b/fs/hpfs/super.c @@ -552,7 +552,13 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent) sbi->sb_cp_table = NULL; sbi->sb_c_bitmap = -1; sbi->sb_max_fwd_alloc = 0xffffff; - + + if (sbi->sb_fs_size >= 0x80000000) { + hpfs_error(s, "invalid size in superblock: %08x", + (unsigned)sbi->sb_fs_size); + goto bail4; + } + /* Load bitmap directory */ if (!(sbi->sb_bmp_dir = hpfs_load_bitmap_directory(s, le32_to_cpu(superblock->bitmaps)))) goto bail4; diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index 001ef01d2fe..36ad5b4aae6 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c @@ -927,9 +927,13 @@ static int can_do_hugetlb_shm(void) return capable(CAP_IPC_LOCK) || in_group_p(sysctl_hugetlb_shm_group); } -struct file *hugetlb_file_setup(const char *name, unsigned long addr, - size_t size, vm_flags_t acctflag, - struct user_struct **user, int creat_flags) +/* + * Note that size should be aligned to proper hugepage size in caller side, + * otherwise hugetlb_reserve_pages reserves one less hugepages than intended. + */ +struct file *hugetlb_file_setup(const char *name, size_t size, + vm_flags_t acctflag, struct user_struct **user, + int creat_flags) { int error = -ENOMEM; struct file *file; @@ -937,8 +941,6 @@ struct file *hugetlb_file_setup(const char *name, unsigned long addr, struct path path; struct dentry *root; struct qstr quick_string; - struct hstate *hstate; - unsigned long num_pages; *user = NULL; if (!hugetlbfs_vfsmount) @@ -972,12 +974,10 @@ struct file *hugetlb_file_setup(const char *name, unsigned long addr, if (!inode) goto out_dentry; - hstate = hstate_inode(inode); - size += addr & ~huge_page_mask(hstate); - num_pages = ALIGN(size, huge_page_size(hstate)) >> - huge_page_shift(hstate); error = -ENOMEM; - if (hugetlb_reserve_pages(inode, 0, num_pages, NULL, acctflag)) + if (hugetlb_reserve_pages(inode, 0, + size >> huge_page_shift(hstate_inode(inode)), NULL, + acctflag)) goto out_inode; d_instantiate(path.dentry, inode); diff --git a/fs/inode.c b/fs/inode.c index 9f4f5fecc09..8de457e8ed0 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -705,7 +705,7 @@ void prune_icache_sb(struct super_block *sb, int nr_to_scan) * inode to the back of the list so we don't spin on it. */ if (!spin_trylock(&inode->i_lock)) { - list_move_tail(&inode->i_lru, &sb->s_inode_lru); + list_move(&inode->i_lru, &sb->s_inode_lru); continue; } diff --git a/fs/isofs/export.c b/fs/isofs/export.c index 516eb21895c..fd88add6ca4 100644 --- a/fs/isofs/export.c +++ b/fs/isofs/export.c @@ -135,6 +135,7 @@ isofs_export_encode_fh(struct dentry *dentry, len = 3; fh32[0] = ei->i_iget5_block; fh16[2] = (__u16)ei->i_iget5_offset; /* fh16 [sic] */ + fh16[3] = 0; /* avoid leaking uninitialized data */ fh32[2] = inode->i_generation; if (connectable && !S_ISDIR(inode->i_mode)) { struct inode *parent; diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c index 840f70f5079..a0dcbd62b18 100644 --- a/fs/jbd2/commit.c +++ b/fs/jbd2/commit.c @@ -325,7 +325,7 @@ void jbd2_journal_commit_transaction(journal_t *journal) int space_left = 0; int first_tag = 0; int tag_flag; - int i, to_free = 0; + int i; int tag_bytes = journal_tag_bytes(journal); struct buffer_head *cbh = NULL; /* For transactional checksums */ __u32 crc32_sum = ~0; @@ -1044,7 +1044,7 @@ void jbd2_journal_commit_transaction(journal_t *journal) journal->j_stats.run.rs_blocks_logged += stats.run.rs_blocks_logged; spin_unlock(&journal->j_history_lock); - commit_transaction->t_state = T_FINISHED; + commit_transaction->t_state = T_COMMIT_CALLBACK; J_ASSERT(commit_transaction == journal->j_committing_transaction); journal->j_commit_sequence = commit_transaction->t_tid; journal->j_committing_transaction = NULL; @@ -1059,38 +1059,44 @@ void jbd2_journal_commit_transaction(journal_t *journal) journal->j_average_commit_time*3) / 4; else journal->j_average_commit_time = commit_time; + write_unlock(&journal->j_state_lock); - if (commit_transaction->t_checkpoint_list == NULL && - commit_transaction->t_checkpoint_io_list == NULL) { - __jbd2_journal_drop_transaction(journal, commit_transaction); - to_free = 1; + if (journal->j_checkpoint_transactions == NULL) { + journal->j_checkpoint_transactions = commit_transaction; + commit_transaction->t_cpnext = commit_transaction; + commit_transaction->t_cpprev = commit_transaction; } else { - if (journal->j_checkpoint_transactions == NULL) { - journal->j_checkpoint_transactions = commit_transaction; - commit_transaction->t_cpnext = commit_transaction; - commit_transaction->t_cpprev = commit_transaction; - } else { - commit_transaction->t_cpnext = - journal->j_checkpoint_transactions; - commit_transaction->t_cpprev = - commit_transaction->t_cpnext->t_cpprev; - commit_transaction->t_cpnext->t_cpprev = - commit_transaction; - commit_transaction->t_cpprev->t_cpnext = + commit_transaction->t_cpnext = + journal->j_checkpoint_transactions; + commit_transaction->t_cpprev = + commit_transaction->t_cpnext->t_cpprev; + commit_transaction->t_cpnext->t_cpprev = + commit_transaction; + commit_transaction->t_cpprev->t_cpnext = commit_transaction; - } } spin_unlock(&journal->j_list_lock); - + /* Drop all spin_locks because commit_callback may be block. + * __journal_remove_checkpoint() can not destroy transaction + * under us because it is not marked as T_FINISHED yet */ if (journal->j_commit_callback) journal->j_commit_callback(journal, commit_transaction); trace_jbd2_end_commit(journal, commit_transaction); jbd_debug(1, "JBD2: commit %d complete, head %d\n", journal->j_commit_sequence, journal->j_tail_sequence); - if (to_free) - jbd2_journal_free_transaction(commit_transaction); + write_lock(&journal->j_state_lock); + spin_lock(&journal->j_list_lock); + commit_transaction->t_state = T_FINISHED; + /* Recheck checkpoint lists after j_list_lock was dropped */ + if (commit_transaction->t_checkpoint_list == NULL && + commit_transaction->t_checkpoint_io_list == NULL) { + __jbd2_journal_drop_transaction(journal, commit_transaction); + jbd2_journal_free_transaction(commit_transaction); + } + spin_unlock(&journal->j_list_lock); + write_unlock(&journal->j_state_lock); wake_up(&journal->j_wait_done_commit); } diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c index ddcd3549c6c..b1631dd3d04 100644 --- a/fs/jbd2/transaction.c +++ b/fs/jbd2/transaction.c @@ -499,10 +499,10 @@ int jbd2__journal_restart(handle_t *handle, int nblocks, gfp_t gfp_mask) &transaction->t_outstanding_credits); if (atomic_dec_and_test(&transaction->t_updates)) wake_up(&journal->j_wait_updates); + tid = transaction->t_tid; spin_unlock(&transaction->t_handle_lock); jbd_debug(2, "restarting handle %p\n", handle); - tid = transaction->t_tid; need_to_start = !tid_geq(journal->j_commit_request, tid); read_unlock(&journal->j_state_lock); if (need_to_start) @@ -1046,9 +1046,12 @@ int jbd2_journal_get_undo_access(handle_t *handle, struct buffer_head *bh) void jbd2_journal_set_triggers(struct buffer_head *bh, struct jbd2_buffer_trigger_type *type) { - struct journal_head *jh = bh2jh(bh); + struct journal_head *jh = jbd2_journal_grab_journal_head(bh); + if (WARN_ON(!jh)) + return; jh->b_triggers = type; + jbd2_journal_put_journal_head(jh); } void jbd2_buffer_frozen_trigger(struct journal_head *jh, void *mapped_data, @@ -1100,17 +1103,18 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh) { transaction_t *transaction = handle->h_transaction; journal_t *journal = transaction->t_journal; - struct journal_head *jh = bh2jh(bh); + struct journal_head *jh; int ret = 0; - jbd_debug(5, "journal_head %p\n", jh); - JBUFFER_TRACE(jh, "entry"); if (is_handle_aborted(handle)) goto out; - if (!buffer_jbd(bh)) { + jh = jbd2_journal_grab_journal_head(bh); + if (!jh) { ret = -EUCLEAN; goto out; } + jbd_debug(5, "journal_head %p\n", jh); + JBUFFER_TRACE(jh, "entry"); jbd_lock_bh_state(bh); @@ -1201,6 +1205,7 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh) spin_unlock(&journal->j_list_lock); out_unlock_bh: jbd_unlock_bh_state(bh); + jbd2_journal_put_journal_head(jh); out: JBUFFER_TRACE(jh, "exit"); WARN_ON(ret); /* All errors are bugs, so dump the stack */ diff --git a/fs/jfs/inode.c b/fs/jfs/inode.c index 77b69b27f82..13fc88561da 100644 --- a/fs/jfs/inode.c +++ b/fs/jfs/inode.c @@ -125,7 +125,7 @@ int jfs_write_inode(struct inode *inode, struct writeback_control *wbc) { int wait = wbc->sync_mode == WB_SYNC_ALL; - if (test_cflag(COMMIT_Nolink, inode)) + if (inode->i_nlink == 0) return 0; /* * If COMMIT_DIRTY is not set, the inode isn't really dirty. diff --git a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c index 2eb952c41a6..cbe48ea9318 100644 --- a/fs/jfs/jfs_logmgr.c +++ b/fs/jfs/jfs_logmgr.c @@ -1058,7 +1058,8 @@ static int lmLogSync(struct jfs_log * log, int hard_sync) */ void jfs_syncpt(struct jfs_log *log, int hard_sync) { LOG_LOCK(log); - lmLogSync(log, hard_sync); + if (!test_bit(log_QUIESCE, &log->flag)) + lmLogSync(log, hard_sync); LOG_UNLOCK(log); } diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c index ca0a0800144..193f04cc97b 100644 --- a/fs/lockd/clntlock.c +++ b/fs/lockd/clntlock.c @@ -144,6 +144,9 @@ int nlmclnt_block(struct nlm_wait *block, struct nlm_rqst *req, long timeout) timeout); if (ret < 0) return -ERESTARTSYS; + /* Reset the lock status after a server reboot so we resend */ + if (block->b_status == nlm_lck_denied_grace_period) + block->b_status = nlm_lck_blocked; req->a_res.status = block->b_status; return 0; } diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c index e46353f41a4..aff1c616aed 100644 --- a/fs/lockd/svclock.c +++ b/fs/lockd/svclock.c @@ -941,6 +941,7 @@ nlmsvc_retry_blocked(void) unsigned long timeout = MAX_SCHEDULE_TIMEOUT; struct nlm_block *block; + spin_lock(&nlm_blocked_lock); while (!list_empty(&nlm_blocked) && !kthread_should_stop()) { block = list_entry(nlm_blocked.next, struct nlm_block, b_list); @@ -950,6 +951,7 @@ nlmsvc_retry_blocked(void) timeout = block->b_when - jiffies; break; } + spin_unlock(&nlm_blocked_lock); dprintk("nlmsvc_retry_blocked(%p, when=%ld)\n", block, block->b_when); @@ -959,7 +961,9 @@ nlmsvc_retry_blocked(void) retry_deferred_block(block); } else nlmsvc_grant_blocked(block); + spin_lock(&nlm_blocked_lock); } + spin_unlock(&nlm_blocked_lock); return timeout; } diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c index d16dae2a9b2..3a9c2470e4f 100644 --- a/fs/nfs/blocklayout/blocklayout.c +++ b/fs/nfs/blocklayout/blocklayout.c @@ -1155,6 +1155,7 @@ static const struct nfs_pageio_ops bl_pg_write_ops = { static struct pnfs_layoutdriver_type blocklayout_type = { .id = LAYOUT_BLOCK_VOLUME, .name = "LAYOUT_BLOCK_VOLUME", + .owner = THIS_MODULE, .read_pagelist = bl_read_pagelist, .write_pagelist = bl_write_pagelist, .alloc_layout_hdr = bl_alloc_layout_hdr, diff --git a/fs/nfs/blocklayout/blocklayoutdm.c b/fs/nfs/blocklayout/blocklayoutdm.c index 737d839bc17..6fc7b5cae92 100644 --- a/fs/nfs/blocklayout/blocklayoutdm.c +++ b/fs/nfs/blocklayout/blocklayoutdm.c @@ -55,7 +55,8 @@ static void dev_remove(struct net *net, dev_t dev) bl_pipe_msg.bl_wq = &nn->bl_wq; memset(msg, 0, sizeof(*msg)); - msg->data = kzalloc(1 + sizeof(bl_umount_request), GFP_NOFS); + msg->len = sizeof(bl_msg) + bl_msg.totallen; + msg->data = kzalloc(msg->len, GFP_NOFS); if (!msg->data) goto out; @@ -66,7 +67,6 @@ static void dev_remove(struct net *net, dev_t dev) memcpy(msg->data, &bl_msg, sizeof(bl_msg)); dataptr = (uint8_t *) msg->data; memcpy(&dataptr[sizeof(bl_msg)], &bl_umount_request, sizeof(bl_umount_request)); - msg->len = sizeof(bl_msg) + bl_msg.totallen; add_wait_queue(&nn->bl_wq, &wq); if (rpc_queue_upcall(nn->bl_device_pipe, msg) < 0) { diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 3c1b1552917..7c97bd89df3 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -1053,7 +1053,7 @@ static struct nfs4_state *nfs4_try_open_cached(struct nfs4_opendata *opendata) struct nfs4_state *state = opendata->state; struct nfs_inode *nfsi = NFS_I(state->inode); struct nfs_delegation *delegation; - int open_mode = opendata->o_arg.open_flags & (O_EXCL|O_TRUNC); + int open_mode = opendata->o_arg.open_flags; fmode_t fmode = opendata->o_arg.fmode; nfs4_stateid stateid; int ret = -EAGAIN; @@ -1362,6 +1362,12 @@ int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state case -ENOMEM: err = 0; goto out; + case -NFS4ERR_DELAY: + case -NFS4ERR_GRACE: + set_bit(NFS_DELEGATED_STATE, &state->flags); + ssleep(1); + err = -EAGAIN; + goto out; } err = nfs4_handle_exception(server, err, &exception); } while (exception.retry); diff --git a/fs/nfs/objlayout/objio_osd.c b/fs/nfs/objlayout/objio_osd.c index 1afe74c42c8..65538f569f4 100644 --- a/fs/nfs/objlayout/objio_osd.c +++ b/fs/nfs/objlayout/objio_osd.c @@ -589,6 +589,7 @@ static struct pnfs_layoutdriver_type objlayout_type = { .flags = PNFS_LAYOUTRET_ON_SETATTR | PNFS_LAYOUTRET_ON_ERROR, + .owner = THIS_MODULE, .alloc_layout_hdr = objlayout_alloc_layout_hdr, .free_layout_hdr = objlayout_free_layout_hdr, diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c index 3210a03342f..2781563ed54 100644 --- a/fs/nfs/unlink.c +++ b/fs/nfs/unlink.c @@ -336,20 +336,14 @@ static void nfs_async_rename_done(struct rpc_task *task, void *calldata) struct inode *old_dir = data->old_dir; struct inode *new_dir = data->new_dir; struct dentry *old_dentry = data->old_dentry; - struct dentry *new_dentry = data->new_dentry; if (!NFS_PROTO(old_dir)->rename_done(task, old_dir, new_dir)) { rpc_restart_call_prepare(task); return; } - if (task->tk_status != 0) { + if (task->tk_status != 0) nfs_cancel_async_unlink(old_dentry); - return; - } - - d_drop(old_dentry); - d_drop(new_dentry); } /** @@ -550,6 +544,18 @@ nfs_sillyrename(struct inode *dir, struct dentry *dentry) error = rpc_wait_for_completion_task(task); if (error == 0) error = task->tk_status; + switch (error) { + case 0: + /* The rename succeeded */ + nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); + d_move(dentry, sdentry); + break; + case -ERESTARTSYS: + /* The result of the rename is unknown. Play it safe by + * forcing a new lookup */ + d_drop(dentry); + d_drop(sdentry); + } rpc_put_task(task); out_dput: dput(sdentry); diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index dd0308d65f6..64198ed1d64 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c @@ -270,6 +270,7 @@ static __be32 do_open_fhandle(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open) { __be32 status; + int accmode = 0; /* We don't know the target directory, and therefore can not * set the change info @@ -283,9 +284,19 @@ do_open_fhandle(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_ open->op_truncate = (open->op_iattr.ia_valid & ATTR_SIZE) && (open->op_iattr.ia_size == 0); + /* + * In the delegation case, the client is telling us about an + * open that it *already* performed locally, some time ago. We + * should let it succeed now if possible. + * + * In the case of a CLAIM_FH open, on the other hand, the client + * may be counting on us to enforce permissions (the Linux 4.1 + * client uses this for normal opens, for example). + */ + if (open->op_claim_type == NFS4_OPEN_CLAIM_DELEG_CUR_FH) + accmode = NFSD_MAY_OWNER_OVERRIDE; - status = do_open_permission(rqstp, current_fh, open, - NFSD_MAY_OWNER_OVERRIDE); + status = do_open_permission(rqstp, current_fh, open, accmode); return status; } diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 537731e4c16..f90b197ceff 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -213,13 +213,7 @@ static void __nfs4_file_put_access(struct nfs4_file *fp, int oflag) { if (atomic_dec_and_test(&fp->fi_access[oflag])) { nfs4_file_put_fd(fp, oflag); - /* - * It's also safe to get rid of the RDWR open *if* - * we no longer have need of the other kind of access - * or if we already have the other kind of open: - */ - if (fp->fi_fds[1-oflag] - || atomic_read(&fp->fi_access[1 - oflag]) == 0) + if (atomic_read(&fp->fi_access[1 - oflag]) == 0) nfs4_file_put_fd(fp, O_RDWR); } } @@ -1053,6 +1047,8 @@ free_client(struct nfs4_client *clp) put_group_info(clp->cl_cred.cr_group_info); kfree(clp->cl_principal); kfree(clp->cl_name.data); + idr_remove_all(&clp->cl_stateids); + idr_destroy(&clp->cl_stateids); kfree(clp); } diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 967d68eef28..cb997b1bb39 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -161,8 +161,8 @@ static __be32 *read_buf(struct nfsd4_compoundargs *argp, u32 nbytes) */ memcpy(p, argp->p, avail); /* step to next page */ - argp->p = page_address(argp->pagelist[0]); argp->pagelist++; + argp->p = page_address(argp->pagelist[0]); if (argp->pagelen < PAGE_SIZE) { argp->end = argp->p + (argp->pagelen>>2); argp->pagelen = 0; @@ -263,7 +263,7 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, iattr->ia_valid |= ATTR_SIZE; } if (bmval[0] & FATTR4_WORD0_ACL) { - int nace; + u32 nace; struct nfs4_ace *ace; READ_BUF(4); len += 4; @@ -343,10 +343,7 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, all 32 bits of 'nseconds'. */ READ_BUF(12); len += 12; - READ32(dummy32); - if (dummy32) - return nfserr_inval; - READ32(iattr->ia_atime.tv_sec); + READ64(iattr->ia_atime.tv_sec); READ32(iattr->ia_atime.tv_nsec); if (iattr->ia_atime.tv_nsec >= (u32)1000000000) return nfserr_inval; @@ -369,10 +366,7 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, all 32 bits of 'nseconds'. */ READ_BUF(12); len += 12; - READ32(dummy32); - if (dummy32) - return nfserr_inval; - READ32(iattr->ia_mtime.tv_sec); + READ64(iattr->ia_mtime.tv_sec); READ32(iattr->ia_mtime.tv_nsec); if (iattr->ia_mtime.tv_nsec >= (u32)1000000000) return nfserr_inval; @@ -2371,8 +2365,7 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, if (bmval1 & FATTR4_WORD1_TIME_ACCESS) { if ((buflen -= 12) < 0) goto out_resource; - WRITE32(0); - WRITE32(stat.atime.tv_sec); + WRITE64((s64)stat.atime.tv_sec); WRITE32(stat.atime.tv_nsec); } if (bmval1 & FATTR4_WORD1_TIME_DELTA) { @@ -2385,15 +2378,13 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, if (bmval1 & FATTR4_WORD1_TIME_METADATA) { if ((buflen -= 12) < 0) goto out_resource; - WRITE32(0); - WRITE32(stat.ctime.tv_sec); + WRITE64((s64)stat.ctime.tv_sec); WRITE32(stat.ctime.tv_nsec); } if (bmval1 & FATTR4_WORD1_TIME_MODIFY) { if ((buflen -= 12) < 0) goto out_resource; - WRITE32(0); - WRITE32(stat.mtime.tv_sec); + WRITE64((s64)stat.mtime.tv_sec); WRITE32(stat.mtime.tv_nsec); } if (bmval1 & FATTR4_WORD1_MOUNTED_ON_FILEID) { diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c index 8f7b95ac1f7..aa526bebee3 100644 --- a/fs/nilfs2/inode.c +++ b/fs/nilfs2/inode.c @@ -195,13 +195,32 @@ static int nilfs_writepage(struct page *page, struct writeback_control *wbc) static int nilfs_set_page_dirty(struct page *page) { - int ret = __set_page_dirty_buffers(page); + int ret = __set_page_dirty_nobuffers(page); - if (ret) { + if (page_has_buffers(page)) { struct inode *inode = page->mapping->host; - unsigned nr_dirty = 1 << (PAGE_SHIFT - inode->i_blkbits); + unsigned nr_dirty = 0; + struct buffer_head *bh, *head; - nilfs_set_file_dirty(inode, nr_dirty); + /* + * This page is locked by callers, and no other thread + * concurrently marks its buffers dirty since they are + * only dirtied through routines in fs/buffer.c in + * which call sites of mark_buffer_dirty are protected + * by page lock. + */ + bh = head = page_buffers(page); + do { + /* Do not mark hole blocks dirty */ + if (buffer_dirty(bh) || !buffer_mapped(bh)) + continue; + + set_buffer_dirty(bh); + nr_dirty++; + } while (bh = bh->b_this_page, bh != head); + + if (nr_dirty) + nilfs_set_file_dirty(inode, nr_dirty); } return ret; } diff --git a/fs/nilfs2/segbuf.c b/fs/nilfs2/segbuf.c index dc9a913784a..2d8be51f90d 100644 --- a/fs/nilfs2/segbuf.c +++ b/fs/nilfs2/segbuf.c @@ -345,8 +345,7 @@ static void nilfs_end_bio_write(struct bio *bio, int err) if (err == -EOPNOTSUPP) { set_bit(BIO_EOPNOTSUPP, &bio->bi_flags); - bio_put(bio); - /* to be detected by submit_seg_bio() */ + /* to be detected by nilfs_segbuf_submit_bio() */ } if (!uptodate) @@ -377,12 +376,12 @@ static int nilfs_segbuf_submit_bio(struct nilfs_segment_buffer *segbuf, bio->bi_private = segbuf; bio_get(bio); submit_bio(mode, bio); + segbuf->sb_nbio++; if (bio_flagged(bio, BIO_EOPNOTSUPP)) { bio_put(bio); err = -EOPNOTSUPP; goto failed; } - segbuf->sb_nbio++; bio_put(bio); wi->bio = NULL; diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c index 3568c8a8b13..48bc91d60fc 100644 --- a/fs/notify/fanotify/fanotify_user.c +++ b/fs/notify/fanotify/fanotify_user.c @@ -120,6 +120,7 @@ static int fill_event_metadata(struct fsnotify_group *group, metadata->event_len = FAN_EVENT_METADATA_LEN; metadata->metadata_len = FAN_EVENT_METADATA_LEN; metadata->vers = FANOTIFY_METADATA_VERSION; + metadata->reserved = 0; metadata->mask = event->mask & FAN_ALL_OUTGOING_EVENTS; metadata->pid = pid_vnr(event->tgid); if (unlikely(event->mask & FAN_Q_OVERFLOW)) diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c index 8445fbc8985..f255d372a5d 100644 --- a/fs/notify/inotify/inotify_user.c +++ b/fs/notify/inotify/inotify_user.c @@ -577,10 +577,7 @@ static int inotify_update_existing_watch(struct fsnotify_group *group, int add = (arg & IN_MASK_ADD); int ret; - /* don't allow invalid bits: we don't want flags set */ mask = inotify_arg_to_mask(arg); - if (unlikely(!(mask & IN_ALL_EVENTS))) - return -EINVAL; fsn_mark = fsnotify_find_inode_mark(group, inode); if (!fsn_mark) @@ -630,10 +627,7 @@ static int inotify_new_watch(struct fsnotify_group *group, struct idr *idr = &group->inotify_data.idr; spinlock_t *idr_lock = &group->inotify_data.idr_lock; - /* don't allow invalid bits: we don't want flags set */ mask = inotify_arg_to_mask(arg); - if (unlikely(!(mask & IN_ALL_EVENTS))) - return -EINVAL; tmp_i_mark = kmem_cache_alloc(inotify_inode_mark_cachep, GFP_KERNEL); if (unlikely(!tmp_i_mark)) @@ -761,6 +755,10 @@ SYSCALL_DEFINE3(inotify_add_watch, int, fd, const char __user *, pathname, int ret, fput_needed; unsigned flags = 0; + /* don't allow invalid bits: we don't want flags set */ + if (unlikely(!(mask & ALL_INOTIFY_BITS))) + return -EINVAL; + filp = fget_light(fd, &fput_needed); if (unlikely(!filp)) return -EBADF; diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index 657743254eb..340bd02839b 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c @@ -593,9 +593,9 @@ static void ocfs2_dio_end_io(struct kiocb *iocb, level = ocfs2_iocb_rw_locked_level(iocb); ocfs2_rw_unlock(inode, level); + inode_dio_done(inode); if (is_async) aio_complete(iocb, ret, 0); - inode_dio_done(inode); } /* diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index 81a4cd22f80..231eab2b2d0 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c @@ -2545,6 +2545,7 @@ int ocfs2_super_lock(struct ocfs2_super *osb, * everything is up to the caller :) */ status = ocfs2_should_refresh_lock_res(lockres); if (status < 0) { + ocfs2_cluster_unlock(osb, lockres, level); mlog_errno(status); goto bail; } @@ -2553,8 +2554,10 @@ int ocfs2_super_lock(struct ocfs2_super *osb, ocfs2_complete_lock_res_refresh(lockres, status); - if (status < 0) + if (status < 0) { + ocfs2_cluster_unlock(osb, lockres, level); mlog_errno(status); + } ocfs2_track_lock_refresh(lockres); } bail: diff --git a/fs/ocfs2/extent_map.c b/fs/ocfs2/extent_map.c index 2f5b92ef0e5..7eb1c0c7c16 100644 --- a/fs/ocfs2/extent_map.c +++ b/fs/ocfs2/extent_map.c @@ -791,7 +791,7 @@ int ocfs2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, &hole_size, &rec, &is_last); if (ret) { mlog_errno(ret); - goto out; + goto out_unlock; } if (rec.e_blkno == 0ULL) { diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c index f169da4624f..b7e74b580c0 100644 --- a/fs/ocfs2/suballoc.c +++ b/fs/ocfs2/suballoc.c @@ -642,7 +642,7 @@ ocfs2_block_group_alloc_discontig(handle_t *handle, * cluster groups will be staying in cache for the duration of * this operation. */ - ac->ac_allow_chain_relink = 0; + ac->ac_disable_chain_relink = 1; /* Claim the first region */ status = ocfs2_block_group_claim_bits(osb, handle, ac, min_bits, @@ -1823,7 +1823,7 @@ static int ocfs2_search_chain(struct ocfs2_alloc_context *ac, * Do this *after* figuring out how many bits we're taking out * of our target group. */ - if (ac->ac_allow_chain_relink && + if (!ac->ac_disable_chain_relink && (prev_group_bh) && (ocfs2_block_group_reasonably_empty(bg, res->sr_bits))) { status = ocfs2_relink_block_group(handle, alloc_inode, @@ -1928,7 +1928,6 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_alloc_context *ac, victim = ocfs2_find_victim_chain(cl); ac->ac_chain = victim; - ac->ac_allow_chain_relink = 1; status = ocfs2_search_chain(ac, handle, bits_wanted, min_bits, res, &bits_left); @@ -1947,7 +1946,7 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_alloc_context *ac, * searching each chain in order. Don't allow chain relinking * because we only calculate enough journal credits for one * relink per alloc. */ - ac->ac_allow_chain_relink = 0; + ac->ac_disable_chain_relink = 1; for (i = 0; i < le16_to_cpu(cl->cl_next_free_rec); i ++) { if (i == victim) continue; diff --git a/fs/ocfs2/suballoc.h b/fs/ocfs2/suballoc.h index b8afabfeede..a36d0aa5091 100644 --- a/fs/ocfs2/suballoc.h +++ b/fs/ocfs2/suballoc.h @@ -49,7 +49,7 @@ struct ocfs2_alloc_context { /* these are used by the chain search */ u16 ac_chain; - int ac_allow_chain_relink; + int ac_disable_chain_relink; group_search_t *ac_group_search; u64 ac_last_group; diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index 0ba9ea1e796..5b8d9443610 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c @@ -6499,6 +6499,16 @@ static int ocfs2_reflink_xattr_inline(struct ocfs2_xattr_reflink *args) } new_oi = OCFS2_I(args->new_inode); + /* + * Adjust extent record count to reserve space for extended attribute. + * Inline data count had been adjusted in ocfs2_duplicate_inline_data(). + */ + if (!(new_oi->ip_dyn_features & OCFS2_INLINE_DATA_FL) && + !(ocfs2_inode_is_fast_symlink(args->new_inode))) { + struct ocfs2_extent_list *el = &new_di->id2.i_list; + le16_add_cpu(&el->l_count, -(inline_size / + sizeof(struct ocfs2_extent_rec))); + } spin_lock(&new_oi->ip_lock); new_oi->ip_dyn_features |= OCFS2_HAS_XATTR_FL | OCFS2_INLINE_XATTR_FL; new_di->i_dyn_features = cpu_to_le16(new_oi->ip_dyn_features); @@ -7189,7 +7199,7 @@ int ocfs2_init_security_and_acl(struct inode *dir, struct buffer_head *dir_bh = NULL; ret = ocfs2_init_security_get(inode, dir, qstr, NULL); - if (!ret) { + if (ret) { mlog_errno(ret); goto leave; } diff --git a/fs/pipe.c b/fs/pipe.c index fec5e4ad071..1667e6fe041 100644 --- a/fs/pipe.c +++ b/fs/pipe.c @@ -860,6 +860,9 @@ pipe_rdwr_open(struct inode *inode, struct file *filp) { int ret = -ENOENT; + if (!(filp->f_mode & (FMODE_READ|FMODE_WRITE))) + return -EINVAL; + mutex_lock(&inode->i_mutex); if (inode->i_pipe) { diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 03d41ed9bb1..b9416eca5e5 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -741,14 +741,14 @@ typedef struct { } pagemap_entry_t; struct pagemapread { - int pos, len; + int pos, len; /* units: PM_ENTRY_BYTES, not bytes */ pagemap_entry_t *buffer; }; #define PAGEMAP_WALK_SIZE (PMD_SIZE) #define PAGEMAP_WALK_MASK (PMD_MASK) -#define PM_ENTRY_BYTES sizeof(u64) +#define PM_ENTRY_BYTES sizeof(pagemap_entry_t) #define PM_STATUS_BITS 3 #define PM_STATUS_OFFSET (64 - PM_STATUS_BITS) #define PM_STATUS_MASK (((1LL << PM_STATUS_BITS) - 1) << PM_STATUS_OFFSET) @@ -975,8 +975,8 @@ static ssize_t pagemap_read(struct file *file, char __user *buf, if (!count) goto out_task; - pm.len = PM_ENTRY_BYTES * (PAGEMAP_WALK_SIZE >> PAGE_SHIFT); - pm.buffer = kmalloc(pm.len, GFP_TEMPORARY); + pm.len = (PAGEMAP_WALK_SIZE >> PAGE_SHIFT); + pm.buffer = kmalloc(pm.len * PM_ENTRY_BYTES, GFP_TEMPORARY); ret = -ENOMEM; if (!pm.buffer) goto out_task; diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c index 82c585f715e..4a66a5c4a63 100644 --- a/fs/pstore/platform.c +++ b/fs/pstore/platform.c @@ -88,6 +88,27 @@ static const char *get_reason_str(enum kmsg_dump_reason reason) } } +bool pstore_cannot_block_path(enum kmsg_dump_reason reason) +{ + /* + * In case of NMI path, pstore shouldn't be blocked + * regardless of reason. + */ + if (in_nmi()) + return true; + + switch (reason) { + /* In panic case, other cpus are stopped by smp_send_stop(). */ + case KMSG_DUMP_PANIC: + /* Emergency restart shouldn't be blocked by spin lock. */ + case KMSG_DUMP_EMERG: + return true; + default: + return false; + } +} +EXPORT_SYMBOL_GPL(pstore_cannot_block_path); + /* * callback from kmsg_dump. (s2,l2) has the most recently * written bytes, older bytes are in (s1,l1). Save as much @@ -111,10 +132,12 @@ static void pstore_dump(struct kmsg_dumper *dumper, why = get_reason_str(reason); - if (in_nmi()) { - is_locked = spin_trylock(&psinfo->buf_lock); - if (!is_locked) - pr_err("pstore dump routine blocked in NMI, may corrupt error record\n"); + if (pstore_cannot_block_path(reason)) { + is_locked = spin_trylock_irqsave(&psinfo->buf_lock, flags); + if (!is_locked) { + pr_err("pstore dump routine blocked in %s path, may corrupt error record\n" + , in_nmi() ? "NMI" : why); + } } else spin_lock_irqsave(&psinfo->buf_lock, flags); oopscount++; @@ -145,9 +168,9 @@ static void pstore_dump(struct kmsg_dumper *dumper, total += l1_cpy + l2_cpy; part++; } - if (in_nmi()) { + if (pstore_cannot_block_path(reason)) { if (is_locked) - spin_unlock(&psinfo->buf_lock); + spin_unlock_irqrestore(&psinfo->buf_lock, flags); } else spin_unlock_irqrestore(&psinfo->buf_lock, flags); } diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c index 46fc1c20a6b..048d9900910 100644 --- a/fs/reiserfs/xattr.c +++ b/fs/reiserfs/xattr.c @@ -187,8 +187,8 @@ fill_with_dentries(void *buf, const char *name, int namelen, loff_t offset, if (dbuf->count == ARRAY_SIZE(dbuf->dentries)) return -ENOSPC; - if (name[0] == '.' && (name[1] == '\0' || - (name[1] == '.' && name[2] == '\0'))) + if (name[0] == '.' && (namelen < 2 || + (namelen == 2 && name[1] == '.'))) return 0; dentry = lookup_one_len(name, dbuf->xadir, namelen); diff --git a/fs/super.c b/fs/super.c index cf001775617..3c520a5ed71 100644 --- a/fs/super.c +++ b/fs/super.c @@ -298,19 +298,19 @@ EXPORT_SYMBOL(deactivate_super); * and want to turn it into a full-blown active reference. grab_super() * is called with sb_lock held and drops it. Returns 1 in case of * success, 0 if we had failed (superblock contents was already dead or - * dying when grab_super() had been called). + * dying when grab_super() had been called). Note that this is only + * called for superblocks not in rundown mode (== ones still on ->fs_supers + * of their type), so increment of ->s_count is OK here. */ static int grab_super(struct super_block *s) __releases(sb_lock) { - if (atomic_inc_not_zero(&s->s_active)) { - spin_unlock(&sb_lock); - return 1; - } - /* it's going away */ s->s_count++; spin_unlock(&sb_lock); - /* wait for it to die */ down_write(&s->s_umount); + if ((s->s_flags & MS_BORN) && atomic_inc_not_zero(&s->s_active)) { + put_super(s); + return 1; + } up_write(&s->s_umount); put_super(s); return 0; @@ -440,11 +440,6 @@ struct super_block *sget(struct file_system_type *type, destroy_super(s); s = NULL; } - down_write(&old->s_umount); - if (unlikely(!(old->s_flags & MS_BORN))) { - deactivate_locked_super(old); - goto retry; - } return old; } } @@ -677,10 +672,10 @@ struct super_block *get_active_super(struct block_device *bdev) if (hlist_unhashed(&sb->s_instances)) continue; if (sb->s_bdev == bdev) { - if (grab_super(sb)) /* drops sb_lock */ - return sb; - else + if (!grab_super(sb)) goto restart; + up_write(&sb->s_umount); + return sb; } } spin_unlock(&sb_lock); diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index a545d819b49..9a5f07d962a 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c @@ -994,6 +994,7 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir) enum kobj_ns_type type; const void *ns; ino_t ino; + loff_t off; type = sysfs_ns_type(parent_sd); ns = sysfs_info(dentry->d_sb)->ns[type]; @@ -1002,6 +1003,8 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir) ino = parent_sd->s_ino; if (filldir(dirent, ".", 1, filp->f_pos, ino, DT_DIR) == 0) filp->f_pos++; + else + return 0; } if (filp->f_pos == 1) { if (parent_sd->s_parent) @@ -1010,8 +1013,11 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir) ino = parent_sd->s_ino; if (filldir(dirent, "..", 2, filp->f_pos, ino, DT_DIR) == 0) filp->f_pos++; + else + return 0; } mutex_lock(&sysfs_mutex); + off = filp->f_pos; for (pos = sysfs_dir_pos(ns, parent_sd, filp->f_pos, pos); pos; pos = sysfs_dir_next_pos(ns, parent_sd, filp->f_pos, pos)) { @@ -1023,27 +1029,43 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir) len = strlen(name); ino = pos->s_ino; type = dt_type(pos); - filp->f_pos = pos->s_hash; + off = filp->f_pos = pos->s_hash; filp->private_data = sysfs_get(pos); mutex_unlock(&sysfs_mutex); - ret = filldir(dirent, name, len, filp->f_pos, ino, type); + ret = filldir(dirent, name, len, off, ino, type); mutex_lock(&sysfs_mutex); if (ret < 0) break; } mutex_unlock(&sysfs_mutex); - if ((filp->f_pos > 1) && !pos) { /* EOF */ - filp->f_pos = INT_MAX; + + /* don't reference last entry if its refcount is dropped */ + if (!pos) { filp->private_data = NULL; + + /* EOF and not changed as 0 or 1 in read/write path */ + if (off == filp->f_pos && off > 1) + filp->f_pos = INT_MAX; } return 0; } +static loff_t sysfs_dir_llseek(struct file *file, loff_t offset, int whence) +{ + struct inode *inode = file->f_path.dentry->d_inode; + loff_t ret; + + mutex_lock(&inode->i_mutex); + ret = generic_file_llseek(file, offset, whence); + mutex_unlock(&inode->i_mutex); + + return ret; +} const struct file_operations sysfs_dir_operations = { .read = generic_read_dir, .readdir = sysfs_readdir, .release = sysfs_dir_release, - .llseek = generic_file_llseek, + .llseek = sysfs_dir_llseek, }; diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c index 4358a92f4eb..d5a84819ecf 100644 --- a/fs/ubifs/dir.c +++ b/fs/ubifs/dir.c @@ -357,31 +357,50 @@ static unsigned int vfs_dent_type(uint8_t type) static int ubifs_readdir(struct file *file, void *dirent, filldir_t filldir) { int err, over = 0; + loff_t pos = file->f_pos; struct qstr nm; union ubifs_key key; struct ubifs_dent_node *dent; struct inode *dir = file->f_path.dentry->d_inode; struct ubifs_info *c = dir->i_sb->s_fs_info; - dbg_gen("dir ino %lu, f_pos %#llx", dir->i_ino, file->f_pos); + dbg_gen("dir ino %lu, f_pos %#llx", dir->i_ino, pos); - if (file->f_pos > UBIFS_S_KEY_HASH_MASK || file->f_pos == 2) + if (pos > UBIFS_S_KEY_HASH_MASK || pos == 2) /* * The directory was seek'ed to a senseless position or there * are no more entries. */ return 0; + if (file->f_version == 0) { + /* + * The file was seek'ed, which means that @file->private_data + * is now invalid. This may also be just the first + * 'ubifs_readdir()' invocation, in which case + * @file->private_data is NULL, and the below code is + * basically a no-op. + */ + kfree(file->private_data); + file->private_data = NULL; + } + + /* + * 'generic_file_llseek()' unconditionally sets @file->f_version to + * zero, and we use this for detecting whether the file was seek'ed. + */ + file->f_version = 1; + /* File positions 0 and 1 correspond to "." and ".." */ - if (file->f_pos == 0) { + if (pos == 0) { ubifs_assert(!file->private_data); over = filldir(dirent, ".", 1, 0, dir->i_ino, DT_DIR); if (over) return 0; - file->f_pos = 1; + file->f_pos = pos = 1; } - if (file->f_pos == 1) { + if (pos == 1) { ubifs_assert(!file->private_data); over = filldir(dirent, "..", 2, 1, parent_ino(file->f_path.dentry), DT_DIR); @@ -397,7 +416,7 @@ static int ubifs_readdir(struct file *file, void *dirent, filldir_t filldir) goto out; } - file->f_pos = key_hash_flash(c, &dent->key); + file->f_pos = pos = key_hash_flash(c, &dent->key); file->private_data = dent; } @@ -405,17 +424,16 @@ static int ubifs_readdir(struct file *file, void *dirent, filldir_t filldir) if (!dent) { /* * The directory was seek'ed to and is now readdir'ed. - * Find the entry corresponding to @file->f_pos or the - * closest one. + * Find the entry corresponding to @pos or the closest one. */ - dent_key_init_hash(c, &key, dir->i_ino, file->f_pos); + dent_key_init_hash(c, &key, dir->i_ino, pos); nm.name = NULL; dent = ubifs_tnc_next_ent(c, &key, &nm); if (IS_ERR(dent)) { err = PTR_ERR(dent); goto out; } - file->f_pos = key_hash_flash(c, &dent->key); + file->f_pos = pos = key_hash_flash(c, &dent->key); file->private_data = dent; } @@ -427,7 +445,7 @@ static int ubifs_readdir(struct file *file, void *dirent, filldir_t filldir) ubifs_inode(dir)->creat_sqnum); nm.len = le16_to_cpu(dent->nlen); - over = filldir(dirent, dent->name, nm.len, file->f_pos, + over = filldir(dirent, dent->name, nm.len, pos, le64_to_cpu(dent->inum), vfs_dent_type(dent->type)); if (over) @@ -443,9 +461,17 @@ static int ubifs_readdir(struct file *file, void *dirent, filldir_t filldir) } kfree(file->private_data); - file->f_pos = key_hash_flash(c, &dent->key); + file->f_pos = pos = key_hash_flash(c, &dent->key); file->private_data = dent; cond_resched(); + + if (file->f_version == 0) + /* + * The file was seek'ed meanwhile, lets return and start + * reading direntries from the new position on the next + * invocation. + */ + return 0; } out: @@ -456,15 +482,13 @@ static int ubifs_readdir(struct file *file, void *dirent, filldir_t filldir) kfree(file->private_data); file->private_data = NULL; + /* 2 is a special value indicating that there are no more direntries */ file->f_pos = 2; return 0; } -/* If a directory is seeked, we have to free saved readdir() state */ static loff_t ubifs_dir_llseek(struct file *file, loff_t offset, int origin) { - kfree(file->private_data); - file->private_data = NULL; return generic_file_llseek(file, offset, origin); } diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 76e4e0566ad..d867bd97bc6 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -1582,6 +1582,12 @@ static int ubifs_remount_rw(struct ubifs_info *c) c->remounting_rw = 1; c->ro_mount = 0; + if (c->space_fixup) { + err = ubifs_fixup_free_space(c); + if (err) + return err; + } + err = check_free_space(c); if (err) goto out; @@ -1698,12 +1704,6 @@ static int ubifs_remount_rw(struct ubifs_info *c) err = dbg_check_space_info(c); } - if (c->space_fixup) { - err = ubifs_fixup_free_space(c); - if (err) - goto out; - } - mutex_unlock(&c->umount_mutex); return err; diff --git a/fs/udf/namei.c b/fs/udf/namei.c index 38de8f234b9..78bff11169e 100644 --- a/fs/udf/namei.c +++ b/fs/udf/namei.c @@ -1280,6 +1280,7 @@ static int udf_encode_fh(struct dentry *de, __u32 *fh, int *lenp, *lenp = 3; fid->udf.block = location.logicalBlockNum; fid->udf.partref = location.partitionReferenceNum; + fid->udf.parent_partref = 0; fid->udf.generation = inode->i_generation; if (connectable && !S_ISDIR(inode->i_mode)) { diff --git a/fs/udf/udf_sb.h b/fs/udf/udf_sb.h index 42ad69ac957..9e8e08ef246 100644 --- a/fs/udf/udf_sb.h +++ b/fs/udf/udf_sb.h @@ -82,7 +82,7 @@ struct udf_virtual_data { struct udf_bitmap { __u32 s_extLength; __u32 s_extPosition; - __u16 s_nr_groups; + int s_nr_groups; struct buffer_head **s_block_bitmap; }; diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index 3011b879f85..23c79cab08d 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c @@ -457,6 +457,28 @@ xfs_vn_getattr( return 0; } +static void +xfs_setattr_mode( + struct xfs_trans *tp, + struct xfs_inode *ip, + struct iattr *iattr) +{ + struct inode *inode = VFS_I(ip); + umode_t mode = iattr->ia_mode; + + ASSERT(tp); + ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); + + if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID)) + mode &= ~S_ISGID; + + ip->i_d.di_mode &= S_IFMT; + ip->i_d.di_mode |= mode & ~S_IFMT; + + inode->i_mode &= S_IFMT; + inode->i_mode |= mode & ~S_IFMT; +} + int xfs_setattr_nonsize( struct xfs_inode *ip, @@ -608,18 +630,8 @@ xfs_setattr_nonsize( /* * Change file access modes. */ - if (mask & ATTR_MODE) { - umode_t mode = iattr->ia_mode; - - if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID)) - mode &= ~S_ISGID; - - ip->i_d.di_mode &= S_IFMT; - ip->i_d.di_mode |= mode & ~S_IFMT; - - inode->i_mode &= S_IFMT; - inode->i_mode |= mode & ~S_IFMT; - } + if (mask & ATTR_MODE) + xfs_setattr_mode(tp, ip, iattr); /* * Change file access or modified times. @@ -716,9 +728,8 @@ xfs_setattr_size( return XFS_ERROR(error); ASSERT(S_ISREG(ip->i_d.di_mode)); - ASSERT((mask & (ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_ATIME|ATTR_ATIME_SET| - ATTR_MTIME_SET|ATTR_KILL_SUID|ATTR_KILL_SGID| - ATTR_KILL_PRIV|ATTR_TIMES_SET)) == 0); + ASSERT((mask & (ATTR_UID|ATTR_GID|ATTR_ATIME|ATTR_ATIME_SET| + ATTR_MTIME_SET|ATTR_KILL_PRIV|ATTR_TIMES_SET)) == 0); lock_flags = XFS_ILOCK_EXCL; if (!(flags & XFS_ATTR_NOLOCK)) @@ -861,6 +872,12 @@ xfs_setattr_size( xfs_iflags_set(ip, XFS_ITRUNCATED); } + /* + * Change file access modes. + */ + if (mask & ATTR_MODE) + xfs_setattr_mode(tp, ip, iattr); + if (mask & ATTR_CTIME) { inode->i_ctime = iattr->ia_ctime; ip->i_d.di_ctime.t_sec = iattr->ia_ctime.tv_sec; diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h index c7ec2cdc904..9a6eb25b90e 100644 --- a/include/asm-generic/pgtable.h +++ b/include/asm-generic/pgtable.h @@ -7,6 +7,16 @@ #include #include +/* + * On almost all architectures and configurations, 0 can be used as the + * upper ceiling to free_pgtables(): on many architectures it has the same + * effect as using TASK_SIZE. However, there is one configuration which + * must impose a more careful limit, to avoid freeing kernel pgtables. + */ +#ifndef USER_PGTABLES_CEILING +#define USER_PGTABLES_CEILING 0UL +#endif + #ifndef __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS extern int ptep_set_access_flags(struct vm_area_struct *vma, unsigned long address, pte_t *ptep, diff --git a/include/asm-generic/signal.h b/include/asm-generic/signal.h index 555c0aee8a4..743f7a5dc9a 100644 --- a/include/asm-generic/signal.h +++ b/include/asm-generic/signal.h @@ -99,6 +99,10 @@ typedef unsigned long old_sigset_t; #include +#ifdef SA_RESTORER +#define __ARCH_HAS_SA_RESTORER +#endif + struct sigaction { __sighandler_t sa_handler; unsigned long sa_flags; diff --git a/include/drm/drm_pciids.h b/include/drm/drm_pciids.h index 7207a99bdf8..1a13caac89d 100644 --- a/include/drm/drm_pciids.h +++ b/include/drm/drm_pciids.h @@ -231,6 +231,7 @@ {0x1002, 0x6819, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_PITCAIRN|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6820, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6821, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6822, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6823, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6824, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6825, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ @@ -238,11 +239,13 @@ {0x1002, 0x6827, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6828, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6829, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x682A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x682B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x682D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x682F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6830, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6831, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP}, \ + {0x1002, 0x6835, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6837, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6838, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_NEW_MEMMAP}, \ {0x1002, 0x6839, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VERDE|RADEON_NEW_MEMMAP}, \ @@ -572,7 +575,11 @@ {0x1002, 0x9908, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x9909, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x990A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ - {0x1002, 0x990F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x990B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x990C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x990D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x990E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x990F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x9910, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x9913, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x9917, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ @@ -583,6 +590,15 @@ {0x1002, 0x9992, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x9993, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x9994, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x9995, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x9996, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x9997, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x9998, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x9999, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x999A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x999B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x999C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ + {0x1002, 0x999D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x99A0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x99A2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x99A4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ diff --git a/include/linux/ata.h b/include/linux/ata.h index 32df2b6ef0e..5856c9e0219 100644 --- a/include/linux/ata.h +++ b/include/linux/ata.h @@ -937,7 +937,7 @@ static inline int atapi_cdb_len(const u16 *dev_id) } } -static inline bool atapi_command_packet_set(const u16 *dev_id) +static inline int atapi_command_packet_set(const u16 *dev_id) { return (dev_id[ATA_ID_CONFIG] >> 8) & 0x1f; } diff --git a/include/linux/audit.h b/include/linux/audit.h index ed3ef197249..4f334d51b38 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -480,7 +480,7 @@ static inline void audit_syscall_entry(int arch, int major, unsigned long a0, unsigned long a1, unsigned long a2, unsigned long a3) { - if (unlikely(!audit_dummy_context())) + if (unlikely(current->audit_context)) __audit_syscall_entry(arch, major, a0, a1, a2, a3); } static inline void audit_syscall_exit(void *pt_regs) diff --git a/include/linux/auto_fs.h b/include/linux/auto_fs.h index da64e15004b..6cdabb422de 100644 --- a/include/linux/auto_fs.h +++ b/include/linux/auto_fs.h @@ -31,25 +31,16 @@ #define AUTOFS_MIN_PROTO_VERSION AUTOFS_PROTO_VERSION /* - * Architectures where both 32- and 64-bit binaries can be executed - * on 64-bit kernels need this. This keeps the structure format - * uniform, and makes sure the wait_queue_token isn't too big to be - * passed back down to the kernel. - * - * This assumes that on these architectures: - * mode 32 bit 64 bit - * ------------------------- - * int 32 bit 32 bit - * long 32 bit 64 bit - * - * If so, 32-bit user-space code should be backwards compatible. + * The wait_queue_token (autofs_wqt_t) is part of a structure which is passed + * back to the kernel via ioctl from userspace. On architectures where 32- and + * 64-bit userspace binaries can be executed it's important that the size of + * autofs_wqt_t stays constant between 32- and 64-bit Linux kernels so that we + * do not break the binary ABI interface by changing the structure size. */ - -#if defined(__sparc__) || defined(__mips__) || defined(__x86_64__) \ - || defined(__powerpc__) || defined(__s390__) -typedef unsigned int autofs_wqt_t; -#else +#if defined(__ia64__) || defined(__alpha__) /* pure 64bit architectures */ typedef unsigned long autofs_wqt_t; +#else +typedef unsigned int autofs_wqt_t; #endif /* Packet types */ diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h index eb53e15ede6..5bab59b1034 100644 --- a/include/linux/binfmts.h +++ b/include/linux/binfmts.h @@ -68,8 +68,6 @@ struct linux_binprm { #define BINPRM_FLAGS_EXECFD_BIT 1 #define BINPRM_FLAGS_EXECFD (1 << BINPRM_FLAGS_EXECFD_BIT) -#define BINPRM_MAX_RECURSION 4 - /* Function parameter for binfmt->coredump */ struct coredump_params { long signr; diff --git a/include/linux/ceph/auth.h b/include/linux/ceph/auth.h index d4080f309b5..5f338684413 100644 --- a/include/linux/ceph/auth.h +++ b/include/linux/ceph/auth.h @@ -52,6 +52,9 @@ struct ceph_auth_client_ops { */ int (*create_authorizer)(struct ceph_auth_client *ac, int peer_type, struct ceph_auth_handshake *auth); + /* ensure that an existing authorizer is up to date */ + int (*update_authorizer)(struct ceph_auth_client *ac, int peer_type, + struct ceph_auth_handshake *auth); int (*verify_authorizer_reply)(struct ceph_auth_client *ac, struct ceph_authorizer *a, size_t len); void (*destroy_authorizer)(struct ceph_auth_client *ac, @@ -75,6 +78,8 @@ struct ceph_auth_client { u64 global_id; /* our unique id in system */ const struct ceph_crypto_key *key; /* our secret key */ unsigned want_keys; /* which services we want */ + + struct mutex mutex; }; extern struct ceph_auth_client *ceph_auth_init(const char *name, @@ -94,5 +99,18 @@ extern int ceph_build_auth(struct ceph_auth_client *ac, void *msg_buf, size_t msg_len); extern int ceph_auth_is_authenticated(struct ceph_auth_client *ac); +extern int ceph_auth_create_authorizer(struct ceph_auth_client *ac, + int peer_type, + struct ceph_auth_handshake *auth); +extern void ceph_auth_destroy_authorizer(struct ceph_auth_client *ac, + struct ceph_authorizer *a); +extern int ceph_auth_update_authorizer(struct ceph_auth_client *ac, + int peer_type, + struct ceph_auth_handshake *a); +extern int ceph_auth_verify_authorizer_reply(struct ceph_auth_client *ac, + struct ceph_authorizer *a, + size_t len); +extern void ceph_auth_invalidate_authorizer(struct ceph_auth_client *ac, + int peer_type); #endif diff --git a/include/linux/console.h b/include/linux/console.h index dffe4772a53..b6192e9372c 100644 --- a/include/linux/console.h +++ b/include/linux/console.h @@ -77,7 +77,9 @@ extern const struct consw prom_con; /* SPARC PROM console */ int con_is_bound(const struct consw *csw); int register_con_driver(const struct consw *csw, int first, int last); int unregister_con_driver(const struct consw *csw); +int do_unregister_con_driver(const struct consw *csw); int take_over_console(const struct consw *sw, int first, int last, int deflt); +int do_take_over_console(const struct consw *sw, int first, int last, int deflt); void give_up_console(const struct consw *sw); #ifdef CONFIG_HW_CONSOLE int con_debug_enter(struct vc_data *vc); diff --git a/include/linux/cpu.h b/include/linux/cpu.h index 80227bc090a..66b0dbd2d64 100644 --- a/include/linux/cpu.h +++ b/include/linux/cpu.h @@ -177,6 +177,8 @@ extern struct bus_type cpu_subsys; extern void get_online_cpus(void); 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 register_hotcpu_notifier(nb) register_cpu_notifier(nb) #define unregister_hotcpu_notifier(nb) unregister_cpu_notifier(nb) @@ -199,6 +201,8 @@ static inline void cpu_hotplug_driver_unlock(void) #define get_online_cpus() do { } while (0) #define put_online_cpus() do { } while (0) +#define cpu_hotplug_disable() do { } while (0) +#define cpu_hotplug_enable() do { } 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; }) diff --git a/include/linux/efi.h b/include/linux/efi.h index 5782114f483..eee8b0b190e 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -539,18 +539,30 @@ extern int __init efi_setup_pcdp_console(char *); #endif /* - * We play games with efi_enabled so that the compiler will, if possible, remove - * EFI-related code altogether. + * We play games with efi_enabled so that the compiler will, if + * possible, remove EFI-related code altogether. */ +#define EFI_BOOT 0 /* Were we booted from EFI? */ +#define EFI_SYSTEM_TABLES 1 /* Can we use EFI system tables? */ +#define EFI_CONFIG_TABLES 2 /* Can we use EFI config tables? */ +#define EFI_RUNTIME_SERVICES 3 /* Can we use runtime services? */ +#define EFI_MEMMAP 4 /* Can we use EFI memory map? */ +#define EFI_64BIT 5 /* Is the firmware 64-bit? */ + #ifdef CONFIG_EFI # ifdef CONFIG_X86 - extern int efi_enabled; - extern bool efi_64bit; +extern int efi_enabled(int facility); # else -# define efi_enabled 1 +static inline int efi_enabled(int facility) +{ + return 1; +} # endif #else -# define efi_enabled 0 +static inline int efi_enabled(int facility) +{ + return 0; +} #endif /* diff --git a/include/linux/firewire-cdev.h b/include/linux/firewire-cdev.h index d5003695349..1db453e4b55 100644 --- a/include/linux/firewire-cdev.h +++ b/include/linux/firewire-cdev.h @@ -215,8 +215,8 @@ struct fw_cdev_event_request2 { * with the %FW_CDEV_ISO_INTERRUPT bit set, when explicitly requested with * %FW_CDEV_IOC_FLUSH_ISO, or when there have been so many completed packets * without the interrupt bit set that the kernel's internal buffer for @header - * is about to overflow. (In the last case, kernels with ABI version < 5 drop - * header data up to the next interrupt packet.) + * is about to overflow. (In the last case, ABI versions < 5 drop header data + * up to the next interrupt packet.) * * Isochronous transmit events (context type %FW_CDEV_ISO_CONTEXT_TRANSMIT): * diff --git a/include/linux/firewire.h b/include/linux/firewire.h index cdc9b719e9c..4d259fc7722 100644 --- a/include/linux/firewire.h +++ b/include/linux/firewire.h @@ -409,6 +409,7 @@ struct fw_iso_context { int type; int channel; int speed; + bool drop_overflow_headers; size_t header_size; union { fw_iso_callback_t sc; diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h index 72a6cabb4d5..f80ca4a6ed9 100644 --- a/include/linux/ftrace.h +++ b/include/linux/ftrace.h @@ -299,7 +299,6 @@ ssize_t ftrace_filter_write(struct file *file, const char __user *ubuf, size_t cnt, loff_t *ppos); ssize_t ftrace_notrace_write(struct file *file, const char __user *ubuf, size_t cnt, loff_t *ppos); -loff_t ftrace_regex_lseek(struct file *file, loff_t offset, int origin); int ftrace_regex_release(struct inode *inode, struct file *file); void __init @@ -420,6 +419,8 @@ static inline int ftrace_regex_release(struct inode *inode, struct file *file) { return -ENODEV; } #endif /* CONFIG_DYNAMIC_FTRACE */ +loff_t ftrace_filter_lseek(struct file *file, loff_t offset, int whence); + /* totally disable ftrace - can not re-enable after this */ void ftrace_kill(void); diff --git a/include/linux/ftrace_event.h b/include/linux/ftrace_event.h index 176a939d154..16cad53020d 100644 --- a/include/linux/ftrace_event.h +++ b/include/linux/ftrace_event.h @@ -71,6 +71,8 @@ struct trace_iterator { /* trace_seq for __print_flags() and __print_symbolic() etc. */ struct trace_seq tmp_seq; + cpumask_var_t started; + /* The below is zeroed out in pipe_read */ struct trace_seq seq; struct trace_entry *ent; @@ -83,7 +85,7 @@ struct trace_iterator { loff_t pos; long idx; - cpumask_var_t started; + /* All new field here will be zeroed out in pipe_read */ }; diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h index 000837e126e..6baa73dcfce 100644 --- a/include/linux/hugetlb.h +++ b/include/linux/hugetlb.h @@ -152,8 +152,7 @@ static inline struct hugetlbfs_sb_info *HUGETLBFS_SB(struct super_block *sb) extern const struct file_operations hugetlbfs_file_operations; extern const struct vm_operations_struct hugetlb_vm_ops; -struct file *hugetlb_file_setup(const char *name, unsigned long addr, - size_t size, vm_flags_t acct, +struct file *hugetlb_file_setup(const char *name, size_t size, vm_flags_t acct, struct user_struct **user, int creat_flags); static inline int is_file_hugepages(struct file *file) @@ -170,8 +169,8 @@ static inline int is_file_hugepages(struct file *file) #define is_file_hugepages(file) 0 static inline struct file * -hugetlb_file_setup(const char *name, unsigned long addr, size_t size, - vm_flags_t acctflag, struct user_struct **user, int creat_flags) +hugetlb_file_setup(const char *name, size_t size, vm_flags_t acctflag, + struct user_struct **user, int creat_flags) { return ERR_PTR(-ENOSYS); } @@ -294,7 +293,18 @@ static inline unsigned hstate_index_to_shift(unsigned index) return hstates[index].order + PAGE_SHIFT; } -#else +pgoff_t __basepage_index(struct page *page); + +/* Return page->index in PAGE_SIZE units */ +static inline pgoff_t basepage_index(struct page *page) +{ + if (!PageCompound(page)) + return page->index; + + return __basepage_index(page); +} + +#else /* CONFIG_HUGETLB_PAGE */ struct hstate {}; #define alloc_huge_page_node(h, nid) NULL #define alloc_bootmem_huge_page(h) NULL @@ -312,6 +322,11 @@ static inline unsigned int pages_per_huge_page(struct hstate *h) return 1; } #define hstate_index_to_shift(index) 0 + +static inline pgoff_t basepage_index(struct page *page) +{ + return page->index; +} #endif #endif /* _LINUX_HUGETLB_H */ diff --git a/include/linux/if_cablemodem.h b/include/linux/if_cablemodem.h index 9ca1007edd9..ee6b3c442ba 100644 --- a/include/linux/if_cablemodem.h +++ b/include/linux/if_cablemodem.h @@ -12,11 +12,11 @@ */ /* some useful defines for sb1000.c e cmconfig.c - fv */ -#define SIOCGCMSTATS SIOCDEVPRIVATE+0 /* get cable modem stats */ -#define SIOCGCMFIRMWARE SIOCDEVPRIVATE+1 /* get cm firmware version */ -#define SIOCGCMFREQUENCY SIOCDEVPRIVATE+2 /* get cable modem frequency */ -#define SIOCSCMFREQUENCY SIOCDEVPRIVATE+3 /* set cable modem frequency */ -#define SIOCGCMPIDS SIOCDEVPRIVATE+4 /* get cable modem PIDs */ -#define SIOCSCMPIDS SIOCDEVPRIVATE+5 /* set cable modem PIDs */ +#define SIOCGCMSTATS (SIOCDEVPRIVATE+0) /* get cable modem stats */ +#define SIOCGCMFIRMWARE (SIOCDEVPRIVATE+1) /* get cm firmware version */ +#define SIOCGCMFREQUENCY (SIOCDEVPRIVATE+2) /* get cable modem frequency */ +#define SIOCSCMFREQUENCY (SIOCDEVPRIVATE+3) /* set cable modem frequency */ +#define SIOCGCMPIDS (SIOCDEVPRIVATE+4) /* get cable modem PIDs */ +#define SIOCSCMPIDS (SIOCDEVPRIVATE+5) /* set cable modem PIDs */ #endif diff --git a/include/linux/if_pppox.h b/include/linux/if_pppox.h index 1597b8bc5fe..87eedc13eaf 100644 --- a/include/linux/if_pppox.h +++ b/include/linux/if_pppox.h @@ -132,11 +132,11 @@ struct pppoe_tag { struct pppoe_hdr { #if defined(__LITTLE_ENDIAN_BITFIELD) - __u8 ver : 4; __u8 type : 4; + __u8 ver : 4; #elif defined(__BIG_ENDIAN_BITFIELD) - __u8 type : 4; __u8 ver : 4; + __u8 type : 4; #else #error "Please fix " #endif diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h index 561e130df0b..9b0c6142eae 100644 --- a/include/linux/if_vlan.h +++ b/include/linux/if_vlan.h @@ -327,7 +327,7 @@ static inline void vlan_set_encap_proto(struct sk_buff *skb, struct vlan_hdr *vhdr) { __be16 proto; - unsigned char *rawp; + unsigned short *rawp; /* * Was a VLAN packet, grab the encapsulated protocol, which the layer @@ -340,8 +340,8 @@ static inline void vlan_set_encap_proto(struct sk_buff *skb, return; } - rawp = skb->data; - if (*(unsigned short *) rawp == 0xFFFF) + rawp = (unsigned short *)(vhdr + 1); + if (*rawp == 0xFFFF) /* * This is a magic hack to spot IPX packets. Older Novell * breaks the protocol design and runs IPX over 802.3 without diff --git a/include/linux/ipc_namespace.h b/include/linux/ipc_namespace.h index 8a297a5e794..497c6cc8848 100644 --- a/include/linux/ipc_namespace.h +++ b/include/linux/ipc_namespace.h @@ -42,8 +42,8 @@ struct ipc_namespace { size_t shm_ctlmax; size_t shm_ctlall; + unsigned long shm_tot; int shm_ctlmni; - int shm_tot; /* * Defines whether IPC_RMID is forced for _all_ shm segments regardless * of shmctl() diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h index 2ed66ef2e68..dd6444f67ed 100644 --- a/include/linux/jbd2.h +++ b/include/linux/jbd2.h @@ -470,6 +470,7 @@ struct transaction_s T_COMMIT, T_COMMIT_DFLUSH, T_COMMIT_JFLUSH, + T_COMMIT_CALLBACK, T_FINISHED } t_state; diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 72cbf08d45f..c6fb815280d 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -427,7 +427,7 @@ int kvm_write_guest(struct kvm *kvm, gpa_t gpa, const void *data, int kvm_write_guest_cached(struct kvm *kvm, struct gfn_to_hva_cache *ghc, void *data, unsigned long len); int kvm_gfn_to_hva_cache_init(struct kvm *kvm, struct gfn_to_hva_cache *ghc, - gpa_t gpa); + gpa_t gpa, unsigned long len); int kvm_clear_guest_page(struct kvm *kvm, gfn_t gfn, int offset, int len); int kvm_clear_guest(struct kvm *kvm, gpa_t gpa, unsigned long len); struct kvm_memory_slot *gfn_to_memslot(struct kvm *kvm, gfn_t gfn); diff --git a/include/linux/kvm_types.h b/include/linux/kvm_types.h index fa7cc7244cb..b0bcce0ddc9 100644 --- a/include/linux/kvm_types.h +++ b/include/linux/kvm_types.h @@ -71,6 +71,7 @@ struct gfn_to_hva_cache { u64 generation; gpa_t gpa; unsigned long hva; + unsigned long len; struct kvm_memory_slot *memslot; }; diff --git a/include/linux/libata.h b/include/linux/libata.h index 6e887c742a2..7e13eb428cb 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -393,6 +393,7 @@ enum { ATA_HORKAGE_NOSETXFER = (1 << 14), /* skip SETXFER, SATA only */ ATA_HORKAGE_BROKEN_FPDMA_AA = (1 << 15), /* skip AA */ ATA_HORKAGE_DUMP_ID = (1 << 16), /* dump IDENTIFY data */ + ATA_HORKAGE_MAX_SEC_LBA48 = (1 << 17), /* Set max sects to 65535 */ /* DMA mask for user DMA control: User visible values; DO NOT renumber */ diff --git a/include/linux/mmu_notifier.h b/include/linux/mmu_notifier.h index 1d1b1e13f79..ee2baf034fc 100644 --- a/include/linux/mmu_notifier.h +++ b/include/linux/mmu_notifier.h @@ -4,6 +4,7 @@ #include #include #include +#include struct mmu_notifier; struct mmu_notifier_ops; diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index e517695704c..dc6c6878700 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -232,9 +232,9 @@ struct netdev_hw_addr { #define NETDEV_HW_ADDR_T_SLAVE 3 #define NETDEV_HW_ADDR_T_UNICAST 4 #define NETDEV_HW_ADDR_T_MULTICAST 5 - bool synced; bool global_use; int refcount; + int synced; struct rcu_head rcu_head; }; diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index bb2aa878944..e2080481d6c 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -950,8 +950,7 @@ struct perf_event { /* mmap bits */ struct mutex mmap_mutex; atomic_t mmap_count; - int mmap_locked; - struct user_struct *mmap_user; + struct ring_buffer *rb; struct list_head rb_entry; @@ -1330,6 +1329,12 @@ static inline void perf_event_disable(struct perf_event *event) { } static inline void perf_event_task_tick(void) { } #endif +#if defined(CONFIG_PERF_EVENTS) && defined(CONFIG_CPU_SUP_INTEL) +extern void perf_restore_debug_store(void); +#else +static inline void perf_restore_debug_store(void) { } +#endif + #define perf_output_put(handle, x) perf_output_copy((handle), &(x), sizeof(x)) /* diff --git a/include/linux/preempt.h b/include/linux/preempt.h index 5a710b9c578..87a03c746f1 100644 --- a/include/linux/preempt.h +++ b/include/linux/preempt.h @@ -93,14 +93,20 @@ do { \ #else /* !CONFIG_PREEMPT_COUNT */ -#define preempt_disable() do { } while (0) -#define sched_preempt_enable_no_resched() do { } while (0) -#define preempt_enable_no_resched() do { } while (0) -#define preempt_enable() do { } while (0) - -#define preempt_disable_notrace() do { } while (0) -#define preempt_enable_no_resched_notrace() do { } while (0) -#define preempt_enable_notrace() do { } while (0) +/* + * Even if we don't have any preemption, we need preempt disable/enable + * to be barriers, so that we don't have things like get_user/put_user + * that can cause faults and scheduling migrate into our preempt-protected + * region. + */ +#define preempt_disable() barrier() +#define sched_preempt_enable_no_resched() barrier() +#define preempt_enable_no_resched() barrier() +#define preempt_enable() barrier() + +#define preempt_disable_notrace() barrier() +#define preempt_enable_no_resched_notrace() barrier() +#define preempt_enable_notrace() barrier() #endif /* CONFIG_PREEMPT_COUNT */ diff --git a/include/linux/pstore.h b/include/linux/pstore.h index e1461e143be..318cca1dee9 100644 --- a/include/linux/pstore.h +++ b/include/linux/pstore.h @@ -54,12 +54,18 @@ struct pstore_info { #ifdef CONFIG_PSTORE extern int pstore_register(struct pstore_info *); +extern bool pstore_cannot_block_path(enum kmsg_dump_reason reason); #else static inline int pstore_register(struct pstore_info *psi) { return -ENODEV; } +static inline bool +pstore_cannot_block_path(enum kmsg_dump_reason reason) +{ + return false; +} #endif #endif /*_LINUX_PSTORE_H*/ diff --git a/include/linux/quota.h b/include/linux/quota.h index c09fa042b5e..ffd8607ca4b 100644 --- a/include/linux/quota.h +++ b/include/linux/quota.h @@ -417,6 +417,7 @@ struct quota_module_name { #define INIT_QUOTA_MODULE_NAMES {\ {QFMT_VFS_OLD, "quota_v1"},\ {QFMT_VFS_V0, "quota_v2"},\ + {QFMT_VFS_V1, "quota_v2"},\ {0, NULL}} #endif /* __KERNEL__ */ diff --git a/include/linux/rculist.h b/include/linux/rculist.h index d079290843a..6f95e241ed6 100644 --- a/include/linux/rculist.h +++ b/include/linux/rculist.h @@ -241,6 +241,23 @@ static inline void list_splice_init_rcu(struct list_head *list, #define list_first_entry_rcu(ptr, type, member) \ list_entry_rcu((ptr)->next, type, member) +/** + * list_first_or_null_rcu - get the first element from a list + * @ptr: the list head to take the element from. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_struct within the struct. + * + * Note that if the list is empty, it returns NULL. + * + * This primitive may safely run concurrently with the _rcu list-mutation + * primitives such as list_add_rcu() as long as it's guarded by rcu_read_lock(). + */ +#define list_first_or_null_rcu(ptr, type, member) \ + ({struct list_head *__ptr = (ptr); \ + struct list_head __rcu *__next = list_next_rcu(__ptr); \ + likely(__ptr != __next) ? container_of(__next, type, member) : NULL; \ + }) + /** * list_for_each_entry_rcu - iterate over rcu list of given type * @pos: the type * to use as a loop cursor. diff --git a/include/linux/rculist_nulls.h b/include/linux/rculist_nulls.h index 2ae13714828..1c33dd7da4a 100644 --- a/include/linux/rculist_nulls.h +++ b/include/linux/rculist_nulls.h @@ -105,9 +105,14 @@ static inline void hlist_nulls_add_head_rcu(struct hlist_nulls_node *n, * @head: the head for your list. * @member: the name of the hlist_nulls_node within the struct. * + * The barrier() is needed to make sure compiler doesn't cache first element [1], + * as this loop can be restarted [2] + * [1] Documentation/atomic_ops.txt around line 114 + * [2] Documentation/RCU/rculist_nulls.txt around line 146 */ #define hlist_nulls_for_each_entry_rcu(tpos, pos, head, member) \ - for (pos = rcu_dereference_raw(hlist_nulls_first_rcu(head)); \ + for (({barrier();}), \ + pos = rcu_dereference_raw(hlist_nulls_first_rcu(head)); \ (!is_a_nulls(pos)) && \ ({ tpos = hlist_nulls_entry(pos, typeof(*tpos), member); 1; }); \ pos = rcu_dereference_raw(hlist_nulls_next_rcu(pos))) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index c1bae8dff77..dc4d49a0c07 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -479,7 +479,7 @@ struct sk_buff { union { __u32 mark; __u32 dropcount; - __u32 avail_size; + __u32 reserved_tailroom; }; sk_buff_data_t transport_header; @@ -1373,7 +1373,10 @@ static inline int skb_tailroom(const struct sk_buff *skb) */ static inline int skb_availroom(const struct sk_buff *skb) { - return skb_is_nonlinear(skb) ? 0 : skb->avail_size - skb->len; + if (skb_is_nonlinear(skb)) + return 0; + + return skb->end - skb->tail - skb->reserved_tailroom; } /** @@ -2389,6 +2392,13 @@ static inline void nf_reset(struct sk_buff *skb) #endif } +static inline void nf_reset_trace(struct sk_buff *skb) +{ +#if IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TRACE) + skb->nf_trace = 0; +#endif +} + /* Note: This doesn't put any conntrack and bridge info in dst. */ static inline void __nf_copy(struct sk_buff *dst, const struct sk_buff *src) { diff --git a/include/linux/socket.h b/include/linux/socket.h index b84bbd48b87..9b54ebef173 100644 --- a/include/linux/socket.h +++ b/include/linux/socket.h @@ -316,7 +316,8 @@ struct ucred { /* IPX options */ #define IPX_TYPE 1 -extern void cred_to_ucred(struct pid *pid, const struct cred *cred, struct ucred *ucred); +extern void cred_to_ucred(struct pid *pid, const struct cred *cred, struct ucred *ucred, + bool use_effective); extern int memcpy_fromiovec(unsigned char *kdata, struct iovec *iov, int len); extern int memcpy_fromiovecend(unsigned char *kdata, const struct iovec *iov, @@ -335,6 +336,9 @@ extern int put_cmsg(struct msghdr*, int level, int type, int len, void *data); struct timespec; +/* The __sys_...msg variants allow MSG_CMSG_COMPAT */ +extern long __sys_recvmsg(int fd, struct msghdr __user *msg, unsigned flags); +extern long __sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags); extern int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, unsigned int flags, struct timespec *timeout); extern int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, diff --git a/include/linux/spinlock_up.h b/include/linux/spinlock_up.h index a26e2fb604e..e2369c167db 100644 --- a/include/linux/spinlock_up.h +++ b/include/linux/spinlock_up.h @@ -16,7 +16,10 @@ * In the debug case, 1 means unlocked, 0 means locked. (the values * are inverted, to catch initialization bugs) * - * No atomicity anywhere, we are on UP. + * No atomicity anywhere, we are on UP. However, we still need + * the compiler barriers, because we do not want the compiler to + * move potentially faulting instructions (notably user accesses) + * into the locked sequence, resulting in non-atomic execution. */ #ifdef CONFIG_DEBUG_SPINLOCK @@ -25,6 +28,7 @@ static inline void arch_spin_lock(arch_spinlock_t *lock) { lock->slock = 0; + barrier(); } static inline void @@ -32,6 +36,7 @@ arch_spin_lock_flags(arch_spinlock_t *lock, unsigned long flags) { local_irq_save(flags); lock->slock = 0; + barrier(); } static inline int arch_spin_trylock(arch_spinlock_t *lock) @@ -39,32 +44,34 @@ static inline int arch_spin_trylock(arch_spinlock_t *lock) char oldval = lock->slock; lock->slock = 0; + barrier(); return oldval > 0; } static inline void arch_spin_unlock(arch_spinlock_t *lock) { + barrier(); lock->slock = 1; } /* * Read-write spinlocks. No debug version. */ -#define arch_read_lock(lock) do { (void)(lock); } while (0) -#define arch_write_lock(lock) do { (void)(lock); } while (0) -#define arch_read_trylock(lock) ({ (void)(lock); 1; }) -#define arch_write_trylock(lock) ({ (void)(lock); 1; }) -#define arch_read_unlock(lock) do { (void)(lock); } while (0) -#define arch_write_unlock(lock) do { (void)(lock); } while (0) +#define arch_read_lock(lock) do { barrier(); (void)(lock); } while (0) +#define arch_write_lock(lock) do { barrier(); (void)(lock); } while (0) +#define arch_read_trylock(lock) ({ barrier(); (void)(lock); 1; }) +#define arch_write_trylock(lock) ({ barrier(); (void)(lock); 1; }) +#define arch_read_unlock(lock) do { barrier(); (void)(lock); } while (0) +#define arch_write_unlock(lock) do { barrier(); (void)(lock); } while (0) #else /* DEBUG_SPINLOCK */ #define arch_spin_is_locked(lock) ((void)(lock), 0) /* for sched.c and kernel_lock.c: */ -# define arch_spin_lock(lock) do { (void)(lock); } while (0) -# define arch_spin_lock_flags(lock, flags) do { (void)(lock); } while (0) -# define arch_spin_unlock(lock) do { (void)(lock); } while (0) -# define arch_spin_trylock(lock) ({ (void)(lock); 1; }) +# define arch_spin_lock(lock) do { barrier(); (void)(lock); } while (0) +# define arch_spin_lock_flags(lock, flags) do { barrier(); (void)(lock); } while (0) +# define arch_spin_unlock(lock) do { barrier(); (void)(lock); } while (0) +# define arch_spin_trylock(lock) ({ barrier(); (void)(lock); 1; }) #endif /* DEBUG_SPINLOCK */ #define arch_spin_is_contended(lock) (((void)(lock), 0)) diff --git a/include/linux/ssb/ssb_driver_chipcommon.h b/include/linux/ssb/ssb_driver_chipcommon.h index 1a6b0045b06..29ce7e4648c 100644 --- a/include/linux/ssb/ssb_driver_chipcommon.h +++ b/include/linux/ssb/ssb_driver_chipcommon.h @@ -219,6 +219,7 @@ #define SSB_CHIPCO_PMU_CTL 0x0600 /* PMU control */ #define SSB_CHIPCO_PMU_CTL_ILP_DIV 0xFFFF0000 /* ILP div mask */ #define SSB_CHIPCO_PMU_CTL_ILP_DIV_SHIFT 16 +#define SSB_CHIPCO_PMU_CTL_PLL_UPD 0x00000400 #define SSB_CHIPCO_PMU_CTL_NOILPONW 0x00000200 /* No ILP on wait */ #define SSB_CHIPCO_PMU_CTL_HTREQEN 0x00000100 /* HT req enable */ #define SSB_CHIPCO_PMU_CTL_ALPREQEN 0x00000080 /* ALP req enable */ @@ -661,5 +662,6 @@ enum ssb_pmu_ldo_volt_id { void ssb_pmu_set_ldo_voltage(struct ssb_chipcommon *cc, enum ssb_pmu_ldo_volt_id id, u32 voltage); void ssb_pmu_set_ldo_paref(struct ssb_chipcommon *cc, bool on); +void ssb_pmu_spuravoid_pllupdate(struct ssb_chipcommon *cc, int spuravoid); #endif /* LINUX_SSB_CHIPCO_H_ */ diff --git a/include/linux/swapops.h b/include/linux/swapops.h index 47ead515c81..c5fd30d2a41 100644 --- a/include/linux/swapops.h +++ b/include/linux/swapops.h @@ -137,6 +137,7 @@ static inline void make_migration_entry_read(swp_entry_t *entry) extern void migration_entry_wait(struct mm_struct *mm, pmd_t *pmd, unsigned long address); +extern void migration_entry_wait_huge(struct mm_struct *mm, pte_t *pte); #else #define make_migration_entry(page, write) swp_entry(0, 0) @@ -148,6 +149,8 @@ static inline int is_migration_entry(swp_entry_t swp) static inline void make_migration_entry_read(swp_entry_t *entryp) { } static inline void migration_entry_wait(struct mm_struct *mm, pmd_t *pmd, unsigned long address) { } +static inline void migration_entry_wait_huge(struct mm_struct *mm, + pte_t *pte) { } static inline int is_write_migration_entry(swp_entry_t entry) { return 0; diff --git a/include/linux/thermal.h b/include/linux/thermal.h index f740640b32d..6092ffc327b 100644 --- a/include/linux/thermal.h +++ b/include/linux/thermal.h @@ -120,7 +120,7 @@ struct thermal_zone_device { /* Adding event notification support elements */ #define THERMAL_GENL_FAMILY_NAME "thermal_event" #define THERMAL_GENL_VERSION 0x01 -#define THERMAL_GENL_MCAST_GROUP_NAME "thermal_mc_group" +#define THERMAL_GENL_MCAST_GROUP_NAME "thermal_mc_grp" enum events { THERMAL_AUX0, diff --git a/include/linux/unix_diag.h b/include/linux/unix_diag.h index b1d2bf16b33..0ff4d32a118 100644 --- a/include/linux/unix_diag.h +++ b/include/linux/unix_diag.h @@ -38,9 +38,11 @@ enum { UNIX_DIAG_RQLEN, UNIX_DIAG_MEMINFO, - UNIX_DIAG_MAX, + __UNIX_DIAG_MAX, }; +#define UNIX_DIAG_MAX (__UNIX_DIAG_MAX - 1) + struct unix_diag_vfs { __u32 udiag_vfs_ino; __u32 udiag_vfs_dev; diff --git a/include/linux/usb/audio.h b/include/linux/usb/audio.h index a54b8255d75..6f8b026b339 100644 --- a/include/linux/usb/audio.h +++ b/include/linux/usb/audio.h @@ -384,14 +384,16 @@ static inline __u8 uac_processing_unit_iProcessing(struct uac_processing_unit_de int protocol) { __u8 control_size = uac_processing_unit_bControlSize(desc, protocol); - return desc->baSourceID[desc->bNrInPins + control_size]; + return *(uac_processing_unit_bmControls(desc, protocol) + + control_size); } static inline __u8 *uac_processing_unit_specific(struct uac_processing_unit_descriptor *desc, int protocol) { __u8 control_size = uac_processing_unit_bControlSize(desc, protocol); - return &desc->baSourceID[desc->bNrInPins + control_size + 1]; + return uac_processing_unit_bmControls(desc, protocol) + + control_size + 1; } /* 4.5.2 Class-Specific AS Interface Descriptor */ diff --git a/include/linux/vt_kern.h b/include/linux/vt_kern.h index e33d77f15bd..57eeb145455 100644 --- a/include/linux/vt_kern.h +++ b/include/linux/vt_kern.h @@ -47,6 +47,7 @@ int con_set_cmap(unsigned char __user *cmap); int con_get_cmap(unsigned char __user *cmap); void scrollback(struct vc_data *vc, int lines); void scrollfront(struct vc_data *vc, int lines); +void clear_buffer_attributes(struct vc_data *vc); void update_region(struct vc_data *vc, unsigned long start, int count); void redraw_screen(struct vc_data *vc, int is_switch); #define update_screen(x) redraw_screen(x, 0) @@ -131,6 +132,8 @@ void vt_event_post(unsigned int event, unsigned int old, unsigned int new); int vt_waitactive(int n); void change_console(struct vc_data *new_vc); void reset_vc(struct vc_data *vc); +extern int do_unbind_con_driver(const struct consw *csw, int first, int last, + int deflt); extern int unbind_con_driver(const struct consw *csw, int first, int last, int deflt); int vty_init(const struct file_operations *console_fops); diff --git a/include/linux/wait.h b/include/linux/wait.h index e2094acf2b9..c6b24990470 100644 --- a/include/linux/wait.h +++ b/include/linux/wait.h @@ -233,6 +233,8 @@ do { \ if (!ret) \ break; \ } \ + if (!ret && (condition)) \ + ret = 1; \ finish_wait(&wq, &__wait); \ } while (0) @@ -249,8 +251,9 @@ do { \ * wake_up() has to be called after changing any variable that could * change the result of the wait condition. * - * The function returns 0 if the @timeout elapsed, and the remaining - * jiffies if the condition evaluated to true before the timeout elapsed. + * The function returns 0 if the @timeout elapsed, or the remaining + * jiffies (at least 1) if the @condition evaluated to %true before + * the @timeout elapsed. */ #define wait_event_timeout(wq, condition, timeout) \ ({ \ @@ -318,6 +321,8 @@ do { \ ret = -ERESTARTSYS; \ break; \ } \ + if (!ret && (condition)) \ + ret = 1; \ finish_wait(&wq, &__wait); \ } while (0) @@ -334,9 +339,10 @@ do { \ * wake_up() has to be called after changing any variable that could * change the result of the wait condition. * - * The function returns 0 if the @timeout elapsed, -ERESTARTSYS if it - * was interrupted by a signal, and the remaining jiffies otherwise - * if the condition evaluated to true before the timeout elapsed. + * Returns: + * 0 if the @timeout elapsed, -%ERESTARTSYS if it was interrupted by + * a signal, or the remaining jiffies (at least 1) if the @condition + * evaluated to %true before the @timeout elapsed. */ #define wait_event_interruptible_timeout(wq, condition, timeout) \ ({ \ @@ -611,6 +617,63 @@ do { \ ? 0 : __wait_event_interruptible_locked(wq, condition, 1, 1)) +#define __wait_event_interruptible_lock_irq_timeout(wq, condition, \ + lock, ret) \ +do { \ + DEFINE_WAIT(__wait); \ + \ + for (;;) { \ + prepare_to_wait(&wq, &__wait, TASK_INTERRUPTIBLE); \ + if (condition) \ + break; \ + if (signal_pending(current)) { \ + ret = -ERESTARTSYS; \ + break; \ + } \ + spin_unlock_irq(&lock); \ + ret = schedule_timeout(ret); \ + spin_lock_irq(&lock); \ + if (!ret) \ + break; \ + } \ + finish_wait(&wq, &__wait); \ +} while (0) + +/** + * wait_event_interruptible_lock_irq_timeout - sleep until a condition gets true or a timeout elapses. + * The condition is checked under the lock. This is expected + * to be called with the lock taken. + * @wq: the waitqueue to wait on + * @condition: a C expression for the event to wait for + * @lock: a locked spinlock_t, which will be released before schedule() + * and reacquired afterwards. + * @timeout: timeout, in jiffies + * + * The process is put to sleep (TASK_INTERRUPTIBLE) until the + * @condition evaluates to true or signal is received. The @condition is + * checked each time the waitqueue @wq is woken up. + * + * wake_up() has to be called after changing any variable that could + * change the result of the wait condition. + * + * This is supposed to be called while holding the lock. The lock is + * dropped before going to sleep and is reacquired afterwards. + * + * The function returns 0 if the @timeout elapsed, -ERESTARTSYS if it + * was interrupted by a signal, and the remaining jiffies otherwise + * if the condition evaluated to true before the timeout elapsed. + */ +#define wait_event_interruptible_lock_irq_timeout(wq, condition, lock, \ + timeout) \ +({ \ + int __ret = timeout; \ + \ + if (!(condition)) \ + __wait_event_interruptible_lock_irq_timeout( \ + wq, condition, lock, __ret); \ + __ret; \ +}) + #define __wait_event_killable(wq, condition, ret) \ do { \ diff --git a/include/net/addrconf.h b/include/net/addrconf.h index 757a17638b1..1a77dbb2c9e 100644 --- a/include/net/addrconf.h +++ b/include/net/addrconf.h @@ -81,6 +81,9 @@ extern int ipv6_dev_get_saddr(struct net *net, const struct in6_addr *daddr, unsigned int srcprefs, struct in6_addr *saddr); +extern int __ipv6_get_lladdr(struct inet6_dev *idev, + struct in6_addr *addr, + unsigned char banned_flags); extern int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr, unsigned char banned_flags); diff --git a/include/net/inet_frag.h b/include/net/inet_frag.h index 16ff29a7bb3..b289bd286d7 100644 --- a/include/net/inet_frag.h +++ b/include/net/inet_frag.h @@ -33,6 +33,13 @@ struct inet_frag_queue { #define INETFRAGS_HASHSZ 64 +/* averaged: + * max_depth = default ipfrag_high_thresh / INETFRAGS_HASHSZ / + * rounded up (SKB_TRUELEN(0) + sizeof(struct ipq or + * struct frag_queue)) + */ +#define INETFRAGS_MAXDEPTH 128 + struct inet_frags { struct hlist_head hash[INETFRAGS_HASHSZ]; rwlock_t lock; @@ -64,6 +71,8 @@ int inet_frag_evictor(struct netns_frags *nf, struct inet_frags *f); struct inet_frag_queue *inet_frag_find(struct netns_frags *nf, struct inet_frags *f, void *key, unsigned int hash) __releases(&f->lock); +void inet_frag_maybe_warn_overflow(struct inet_frag_queue *q, + const char *prefix); static inline void inet_frag_put(struct inet_frag_queue *q, struct inet_frags *f) { diff --git a/include/net/ip_fib.h b/include/net/ip_fib.h index 10422ef14e2..2124004da62 100644 --- a/include/net/ip_fib.h +++ b/include/net/ip_fib.h @@ -129,18 +129,16 @@ struct fib_result_nl { }; #ifdef CONFIG_IP_ROUTE_MULTIPATH - #define FIB_RES_NH(res) ((res).fi->fib_nh[(res).nh_sel]) - -#define FIB_TABLE_HASHSZ 2 - #else /* CONFIG_IP_ROUTE_MULTIPATH */ - #define FIB_RES_NH(res) ((res).fi->fib_nh[0]) +#endif /* CONFIG_IP_ROUTE_MULTIPATH */ +#ifdef CONFIG_IP_MULTIPLE_TABLES #define FIB_TABLE_HASHSZ 256 - -#endif /* CONFIG_IP_ROUTE_MULTIPATH */ +#else +#define FIB_TABLE_HASHSZ 2 +#endif extern __be32 fib_info_update_nh_saddr(struct net *net, struct fib_nh *nh); diff --git a/include/net/scm.h b/include/net/scm.h index 0c0017ce23b..9f211cff93b 100644 --- a/include/net/scm.h +++ b/include/net/scm.h @@ -50,7 +50,7 @@ static __inline__ void scm_set_cred(struct scm_cookie *scm, { scm->pid = get_pid(pid); scm->cred = cred ? get_cred(cred) : NULL; - cred_to_ucred(pid, cred, &scm->creds); + cred_to_ucred(pid, cred, &scm->creds, false); } static __inline__ void scm_destroy_cred(struct scm_cookie *scm) diff --git a/include/net/sock.h b/include/net/sock.h index 5878118e3ce..f673ba5b6b1 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -793,6 +793,18 @@ struct inet_hashinfo; struct raw_hashinfo; struct module; +/* + * caches using SLAB_DESTROY_BY_RCU should let .next pointer from nulls nodes + * un-modified. Special care is taken when initializing object to zero. + */ +static inline void sk_prot_clear_nulls(struct sock *sk, int size) +{ + if (offsetof(struct sock, sk_node.next) != 0) + memset(sk, 0, offsetof(struct sock, sk_node.next)); + memset(&sk->sk_node.pprev, 0, + size - offsetof(struct sock, sk_node.pprev)); +} + /* Networking protocol blocks we attach to sockets. * socket layer -> transport layer interface * transport -> network interface is defined by struct inet_proto @@ -944,7 +956,7 @@ static inline void sk_refcnt_debug_dec(struct sock *sk) sk->sk_prot->name, sk, atomic_read(&sk->sk_prot->socks)); } -inline void sk_refcnt_debug_release(const struct sock *sk) +static inline void sk_refcnt_debug_release(const struct sock *sk) { if (atomic_read(&sk->sk_refcnt) != 1) printk(KERN_DEBUG "Destruction of the %s socket %p delayed, refcnt=%d\n", diff --git a/include/net/tcp.h b/include/net/tcp.h index ed5b0c70d86..269e99f2a02 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -948,6 +948,7 @@ static inline int tcp_prequeue(struct sock *sk, struct sk_buff *skb) if (sysctl_tcp_low_latency || !tp->ucopy.task) return 0; + skb_dst_force(skb); __skb_queue_tail(&tp->ucopy.prequeue, skb); tp->ucopy.memory += skb->truesize; if (tp->ucopy.memory > sk->sk_rcvbuf) { diff --git a/include/net/udp.h b/include/net/udp.h index 5d606d9da9e..d0bf5b659e0 100644 --- a/include/net/udp.h +++ b/include/net/udp.h @@ -181,6 +181,7 @@ extern int udp_get_port(struct sock *sk, unsigned short snum, extern void udp_err(struct sk_buff *, u32); extern int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, size_t len); +extern int udp_push_pending_frames(struct sock *sk); extern void udp_flush_pending_frames(struct sock *sk); extern int udp_rcv(struct sk_buff *skb); extern int udp_ioctl(struct sock *sk, int cmd, unsigned long arg); diff --git a/include/video/atmel_lcdc.h b/include/video/atmel_lcdc.h index 28447f1594f..5f0e234026c 100644 --- a/include/video/atmel_lcdc.h +++ b/include/video/atmel_lcdc.h @@ -62,6 +62,7 @@ struct atmel_lcdfb_info { void (*atmel_lcdfb_power_control)(int on); struct fb_monspecs *default_monspecs; u32 pseudo_palette[16]; + bool have_intensity_bit; }; #define ATMEL_LCDC_DMABADDR1 0x00 diff --git a/include/xen/interface/io/blkif.h b/include/xen/interface/io/blkif.h index ee338bfde18..2af8fdb4987 100644 --- a/include/xen/interface/io/blkif.h +++ b/include/xen/interface/io/blkif.h @@ -138,11 +138,21 @@ struct blkif_request_discard { uint8_t _pad3; } __attribute__((__packed__)); +struct blkif_request_other { + uint8_t _pad1; + blkif_vdev_t _pad2; /* only for read/write requests */ +#ifdef CONFIG_X86_64 + uint32_t _pad3; /* offsetof(blkif_req..,u.other.id)==8*/ +#endif + uint64_t id; /* private guest value, echoed in resp */ +} __attribute__((__packed__)); + struct blkif_request { uint8_t operation; /* BLKIF_OP_??? */ union { struct blkif_request_rw rw; struct blkif_request_discard discard; + struct blkif_request_other other; } u; } __attribute__((__packed__)); diff --git a/init/main.c b/init/main.c index 8484f49485d..5633c12372b 100644 --- a/init/main.c +++ b/init/main.c @@ -604,7 +604,7 @@ asmlinkage void __init start_kernel(void) pidmap_init(); anon_vma_init(); #ifdef CONFIG_X86 - if (efi_enabled) + if (efi_enabled(EFI_RUNTIME_SERVICES)) efi_enter_virtual_mode(); #endif thread_info_cache_init(); @@ -632,7 +632,7 @@ asmlinkage void __init start_kernel(void) acpi_early_init(); /* before LAPIC and SMP init */ sfi_init_late(); - if (efi_enabled) + if (efi_enabled(EFI_RUNTIME_SERVICES)) efi_free_boot_services(); ftrace_init(); diff --git a/ipc/shm.c b/ipc/shm.c index cb4c16cf374..fed7e93b5d6 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -450,7 +450,7 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params) size_t size = params->u.size; int error; struct shmid_kernel *shp; - int numpages = (size + PAGE_SIZE -1) >> PAGE_SHIFT; + size_t numpages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; struct file * file; char name[13]; int id; @@ -479,10 +479,12 @@ static int newseg(struct ipc_namespace *ns, struct ipc_params *params) sprintf (name, "SYSV%08x", key); if (shmflg & SHM_HUGETLB) { + size_t hugesize = ALIGN(size, huge_page_size(&default_hstate)); + /* hugetlb_file_setup applies strict accounting */ if (shmflg & SHM_NORESERVE) acctflag = VM_NORESERVE; - file = hugetlb_file_setup(name, 0, size, acctflag, + file = hugetlb_file_setup(name, hugesize, acctflag, &shp->mlock_user, HUGETLB_SHMFS_INODE); } else { /* diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c index 31fdc480b5c..0caf1f8de0f 100644 --- a/kernel/audit_tree.c +++ b/kernel/audit_tree.c @@ -608,9 +608,9 @@ void audit_trim_trees(void) } spin_unlock(&hash_lock); trim_marked(tree); - put_tree(tree); drop_collected_mounts(root_mnt); skip_it: + put_tree(tree); mutex_lock(&audit_filter_mutex); } list_del(&cursor); diff --git a/kernel/cgroup.c b/kernel/cgroup.c index dd694f8b09a..0f9b92ea2f3 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -2022,7 +2022,7 @@ static int cgroup_attach_proc(struct cgroup *cgrp, struct task_struct *leader) if (!group) return -ENOMEM; /* pre-allocate to guarantee space while iterating in rcu read-side. */ - retval = flex_array_prealloc(group, 0, group_size - 1, GFP_KERNEL); + retval = flex_array_prealloc(group, 0, group_size, GFP_KERNEL); if (retval) goto out_free_group_list; diff --git a/kernel/cpu.c b/kernel/cpu.c index d947ab08cf1..12a5c0f1c0d 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -126,6 +126,27 @@ static void cpu_hotplug_done(void) mutex_unlock(&cpu_hotplug.lock); } +/* + * Wait for currently running CPU hotplug operations to complete (if any) and + * disable future CPU hotplug (from sysfs). The 'cpu_add_remove_lock' protects + * the 'cpu_hotplug_disabled' flag. The same lock is also acquired by the + * hotplug path before performing hotplug operations. So acquiring that lock + * guarantees mutual exclusion from any currently running hotplug operations. + */ +void cpu_hotplug_disable(void) +{ + cpu_maps_update_begin(); + cpu_hotplug_disabled = 1; + cpu_maps_update_done(); +} + +void cpu_hotplug_enable(void) +{ + cpu_maps_update_begin(); + cpu_hotplug_disabled = 0; + cpu_maps_update_done(); +} + #else /* #if CONFIG_HOTPLUG_CPU */ static void cpu_hotplug_begin(void) {} static void cpu_hotplug_done(void) {} @@ -501,36 +522,6 @@ static int __init alloc_frozen_cpus(void) } core_initcall(alloc_frozen_cpus); -/* - * Prevent regular CPU hotplug from racing with the freezer, by disabling CPU - * hotplug when tasks are about to be frozen. Also, don't allow the freezer - * to continue until any currently running CPU hotplug operation gets - * completed. - * To modify the 'cpu_hotplug_disabled' flag, we need to acquire the - * 'cpu_add_remove_lock'. And this same lock is also taken by the regular - * CPU hotplug path and released only after it is complete. Thus, we - * (and hence the freezer) will block here until any currently running CPU - * hotplug operation gets completed. - */ -void cpu_hotplug_disable_before_freeze(void) -{ - cpu_maps_update_begin(); - cpu_hotplug_disabled = 1; - cpu_maps_update_done(); -} - - -/* - * When tasks have been thawed, re-enable regular CPU hotplug (which had been - * disabled while beginning to freeze tasks). - */ -void cpu_hotplug_enable_after_thaw(void) -{ - cpu_maps_update_begin(); - cpu_hotplug_disabled = 0; - cpu_maps_update_done(); -} - /* * When callbacks for CPU hotplug notifications are being executed, we must * ensure that the state of the system with respect to the tasks being frozen @@ -550,12 +541,12 @@ cpu_hotplug_pm_callback(struct notifier_block *nb, case PM_SUSPEND_PREPARE: case PM_HIBERNATION_PREPARE: - cpu_hotplug_disable_before_freeze(); + cpu_hotplug_disable(); break; case PM_POST_SUSPEND: case PM_POST_HIBERNATION: - cpu_hotplug_enable_after_thaw(); + cpu_hotplug_enable(); break; default: diff --git a/kernel/cpuset.c b/kernel/cpuset.c index 5fc1570e64c..8fe6f6b6500 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c @@ -2479,8 +2479,16 @@ void cpuset_print_task_mems_allowed(struct task_struct *tsk) dentry = task_cs(tsk)->css.cgroup->dentry; spin_lock(&cpuset_buffer_lock); - snprintf(cpuset_name, CPUSET_NAME_LEN, - dentry ? (const char *)dentry->d_name.name : "/"); + + if (!dentry) { + strcpy(cpuset_name, "/"); + } else { + spin_lock(&dentry->d_lock); + strlcpy(cpuset_name, (const char *)dentry->d_name.name, + CPUSET_NAME_LEN); + spin_unlock(&dentry->d_lock); + } + nodelist_scnprintf(cpuset_nodelist, CPUSET_NODELIST_LEN, tsk->mems_allowed); printk(KERN_INFO "%s cpuset=%s mems_allowed=%s\n", diff --git a/kernel/events/core.c b/kernel/events/core.c index 85ee3c8722f..ab5bf2714ed 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -193,9 +193,6 @@ static void cpu_ctx_sched_in(struct perf_cpu_context *cpuctx, static void update_context_time(struct perf_event_context *ctx); static u64 perf_event_time(struct perf_event *event); -static void ring_buffer_attach(struct perf_event *event, - struct ring_buffer *rb); - void __weak perf_event_print_debug(void) { } extern __weak const char *perf_pmu_name(void) @@ -253,9 +250,9 @@ perf_cgroup_match(struct perf_event *event) return !event->cgrp || event->cgrp == cpuctx->cgrp; } -static inline void perf_get_cgroup(struct perf_event *event) +static inline bool perf_tryget_cgroup(struct perf_event *event) { - css_get(&event->cgrp->css); + return css_tryget(&event->cgrp->css); } static inline void perf_put_cgroup(struct perf_event *event) @@ -484,7 +481,11 @@ static inline int perf_cgroup_connect(int fd, struct perf_event *event, event->cgrp = cgrp; /* must be done before we fput() the file */ - perf_get_cgroup(event); + if (!perf_tryget_cgroup(event)) { + event->cgrp = NULL; + ret = -ENOENT; + goto out; + } /* * all events in a group must monitor @@ -722,8 +723,18 @@ perf_lock_task_context(struct task_struct *task, int ctxn, unsigned long *flags) { struct perf_event_context *ctx; - rcu_read_lock(); retry: + /* + * One of the few rules of preemptible RCU is that one cannot do + * rcu_read_unlock() while holding a scheduler (or nested) lock when + * part of the read side critical section was preemptible -- see + * rcu_read_unlock_special(). + * + * Since ctx->lock nests under rq->lock we must ensure the entire read + * side critical section is non-preemptible. + */ + preempt_disable(); + rcu_read_lock(); ctx = rcu_dereference(task->perf_event_ctxp[ctxn]); if (ctx) { /* @@ -739,6 +750,8 @@ perf_lock_task_context(struct task_struct *task, int ctxn, unsigned long *flags) raw_spin_lock_irqsave(&ctx->lock, *flags); if (ctx != rcu_dereference(task->perf_event_ctxp[ctxn])) { raw_spin_unlock_irqrestore(&ctx->lock, *flags); + rcu_read_unlock(); + preempt_enable(); goto retry; } @@ -748,6 +761,7 @@ perf_lock_task_context(struct task_struct *task, int ctxn, unsigned long *flags) } } rcu_read_unlock(); + preempt_enable(); return ctx; } @@ -900,6 +914,15 @@ list_add_event(struct perf_event *event, struct perf_event_context *ctx) ctx->nr_stat++; } +/* + * Initialize event state based on the perf_event_attr::disabled. + */ +static inline void perf_event__state_init(struct perf_event *event) +{ + event->state = event->attr.disabled ? PERF_EVENT_STATE_OFF : + PERF_EVENT_STATE_INACTIVE; +} + /* * Called at perf_event creation and when events are attached/detached from a * group. @@ -1705,7 +1728,16 @@ static int __perf_event_enable(void *info) struct perf_cpu_context *cpuctx = __get_cpu_context(ctx); int err; - if (WARN_ON_ONCE(!ctx->is_active)) + /* + * There's a time window between 'ctx->is_active' check + * in perf_event_enable function and this place having: + * - IRQs on + * - ctx->lock unlocked + * + * where the task could be killed and 'ctx' deactivated + * by perf_event_exit_task. + */ + if (!ctx->is_active) return -EINVAL; raw_spin_lock(&ctx->lock); @@ -2849,6 +2881,7 @@ static void free_event_rcu(struct rcu_head *head) } static void ring_buffer_put(struct ring_buffer *rb); +static void ring_buffer_detach(struct perf_event *event, struct ring_buffer *rb); static void free_event(struct perf_event *event) { @@ -2873,15 +2906,30 @@ static void free_event(struct perf_event *event) if (has_branch_stack(event)) { static_key_slow_dec_deferred(&perf_sched_events); /* is system-wide event */ - if (!(event->attach_state & PERF_ATTACH_TASK)) + if (!(event->attach_state & PERF_ATTACH_TASK)) { atomic_dec(&per_cpu(perf_branch_stack_events, event->cpu)); + } } } if (event->rb) { - ring_buffer_put(event->rb); - event->rb = NULL; + struct ring_buffer *rb; + + /* + * Can happen when we close an event with re-directed output. + * + * Since we have a 0 refcount, perf_mmap_close() will skip + * over us; possibly making our ring_buffer_put() the last. + */ + mutex_lock(&event->mmap_mutex); + rb = event->rb; + if (rb) { + rcu_assign_pointer(event->rb, NULL); + ring_buffer_detach(event, rb); + ring_buffer_put(rb); /* could be last */ + } + mutex_unlock(&event->mmap_mutex); } if (is_cgroup_event(event)) @@ -3119,30 +3167,13 @@ static unsigned int perf_poll(struct file *file, poll_table *wait) unsigned int events = POLL_HUP; /* - * Race between perf_event_set_output() and perf_poll(): perf_poll() - * grabs the rb reference but perf_event_set_output() overrides it. - * Here is the timeline for two threads T1, T2: - * t0: T1, rb = rcu_dereference(event->rb) - * t1: T2, old_rb = event->rb - * t2: T2, event->rb = new rb - * t3: T2, ring_buffer_detach(old_rb) - * t4: T1, ring_buffer_attach(rb1) - * t5: T1, poll_wait(event->waitq) - * - * To avoid this problem, we grab mmap_mutex in perf_poll() - * thereby ensuring that the assignment of the new ring buffer - * and the detachment of the old buffer appear atomic to perf_poll() + * Pin the event->rb by taking event->mmap_mutex; otherwise + * perf_event_set_output() can swizzle our rb and make us miss wakeups. */ mutex_lock(&event->mmap_mutex); - - rcu_read_lock(); - rb = rcu_dereference(event->rb); - if (rb) { - ring_buffer_attach(event, rb); + rb = event->rb; + if (rb) events = atomic_xchg(&rb->poll, 0); - } - rcu_read_unlock(); - mutex_unlock(&event->mmap_mutex); poll_wait(file, &event->waitq, wait); @@ -3459,16 +3490,12 @@ static void ring_buffer_attach(struct perf_event *event, return; spin_lock_irqsave(&rb->event_lock, flags); - if (!list_empty(&event->rb_entry)) - goto unlock; - - list_add(&event->rb_entry, &rb->event_list); -unlock: + if (list_empty(&event->rb_entry)) + list_add(&event->rb_entry, &rb->event_list); spin_unlock_irqrestore(&rb->event_lock, flags); } -static void ring_buffer_detach(struct perf_event *event, - struct ring_buffer *rb) +static void ring_buffer_detach(struct perf_event *event, struct ring_buffer *rb) { unsigned long flags; @@ -3487,13 +3514,10 @@ static void ring_buffer_wakeup(struct perf_event *event) rcu_read_lock(); rb = rcu_dereference(event->rb); - if (!rb) - goto unlock; - - list_for_each_entry_rcu(event, &rb->event_list, rb_entry) - wake_up_all(&event->waitq); - -unlock: + if (rb) { + list_for_each_entry_rcu(event, &rb->event_list, rb_entry) + wake_up_all(&event->waitq); + } rcu_read_unlock(); } @@ -3522,18 +3546,10 @@ static struct ring_buffer *ring_buffer_get(struct perf_event *event) static void ring_buffer_put(struct ring_buffer *rb) { - struct perf_event *event, *n; - unsigned long flags; - if (!atomic_dec_and_test(&rb->refcount)) return; - spin_lock_irqsave(&rb->event_lock, flags); - list_for_each_entry_safe(event, n, &rb->event_list, rb_entry) { - list_del_init(&event->rb_entry); - wake_up_all(&event->waitq); - } - spin_unlock_irqrestore(&rb->event_lock, flags); + WARN_ON_ONCE(!list_empty(&rb->event_list)); call_rcu(&rb->rcu_head, rb_free_rcu); } @@ -3543,26 +3559,100 @@ static void perf_mmap_open(struct vm_area_struct *vma) struct perf_event *event = vma->vm_file->private_data; atomic_inc(&event->mmap_count); + atomic_inc(&event->rb->mmap_count); } +/* + * A buffer can be mmap()ed multiple times; either directly through the same + * event, or through other events by use of perf_event_set_output(). + * + * In order to undo the VM accounting done by perf_mmap() we need to destroy + * the buffer here, where we still have a VM context. This means we need + * to detach all events redirecting to us. + */ static void perf_mmap_close(struct vm_area_struct *vma) { struct perf_event *event = vma->vm_file->private_data; - if (atomic_dec_and_mutex_lock(&event->mmap_count, &event->mmap_mutex)) { - unsigned long size = perf_data_size(event->rb); - struct user_struct *user = event->mmap_user; - struct ring_buffer *rb = event->rb; + struct ring_buffer *rb = event->rb; + struct user_struct *mmap_user = rb->mmap_user; + int mmap_locked = rb->mmap_locked; + unsigned long size = perf_data_size(rb); + + atomic_dec(&rb->mmap_count); + + if (!atomic_dec_and_mutex_lock(&event->mmap_count, &event->mmap_mutex)) + return; + + /* Detach current event from the buffer. */ + rcu_assign_pointer(event->rb, NULL); + ring_buffer_detach(event, rb); + mutex_unlock(&event->mmap_mutex); - atomic_long_sub((size >> PAGE_SHIFT) + 1, &user->locked_vm); - vma->vm_mm->pinned_vm -= event->mmap_locked; - rcu_assign_pointer(event->rb, NULL); - ring_buffer_detach(event, rb); + /* If there's still other mmap()s of this buffer, we're done. */ + if (atomic_read(&rb->mmap_count)) { + ring_buffer_put(rb); /* can't be last */ + return; + } + + /* + * No other mmap()s, detach from all other events that might redirect + * into the now unreachable buffer. Somewhat complicated by the + * fact that rb::event_lock otherwise nests inside mmap_mutex. + */ +again: + rcu_read_lock(); + list_for_each_entry_rcu(event, &rb->event_list, rb_entry) { + if (!atomic_long_inc_not_zero(&event->refcount)) { + /* + * This event is en-route to free_event() which will + * detach it and remove it from the list. + */ + continue; + } + rcu_read_unlock(); + + mutex_lock(&event->mmap_mutex); + /* + * Check we didn't race with perf_event_set_output() which can + * swizzle the rb from under us while we were waiting to + * acquire mmap_mutex. + * + * If we find a different rb; ignore this event, a next + * iteration will no longer find it on the list. We have to + * still restart the iteration to make sure we're not now + * iterating the wrong list. + */ + if (event->rb == rb) { + rcu_assign_pointer(event->rb, NULL); + ring_buffer_detach(event, rb); + ring_buffer_put(rb); /* can't be last, we still have one */ + } mutex_unlock(&event->mmap_mutex); + put_event(event); - ring_buffer_put(rb); - free_uid(user); + /* + * Restart the iteration; either we're on the wrong list or + * destroyed its integrity by doing a deletion. + */ + goto again; } + rcu_read_unlock(); + + /* + * It could be there's still a few 0-ref events on the list; they'll + * get cleaned up by free_event() -- they'll also still have their + * ref on the rb and will free it whenever they are done with it. + * + * Aside from that, this buffer is 'fully' detached and unmapped, + * undo the VM accounting. + */ + + atomic_long_sub((size >> PAGE_SHIFT) + 1, &mmap_user->locked_vm); + vma->vm_mm->pinned_vm -= mmap_locked; + free_uid(mmap_user); + + ring_buffer_put(rb); /* could be last */ } static const struct vm_operations_struct perf_mmap_vmops = { @@ -3612,12 +3702,24 @@ static int perf_mmap(struct file *file, struct vm_area_struct *vma) return -EINVAL; WARN_ON_ONCE(event->ctx->parent_ctx); +again: mutex_lock(&event->mmap_mutex); if (event->rb) { - if (event->rb->nr_pages == nr_pages) - atomic_inc(&event->rb->refcount); - else + if (event->rb->nr_pages != nr_pages) { ret = -EINVAL; + goto unlock; + } + + if (!atomic_inc_not_zero(&event->rb->mmap_count)) { + /* + * Raced against perf_mmap_close() through + * perf_event_set_output(). Try again, hope for better + * luck. + */ + mutex_unlock(&event->mmap_mutex); + goto again; + } + goto unlock; } @@ -3658,12 +3760,16 @@ static int perf_mmap(struct file *file, struct vm_area_struct *vma) ret = -ENOMEM; goto unlock; } - rcu_assign_pointer(event->rb, rb); + + atomic_set(&rb->mmap_count, 1); + rb->mmap_locked = extra; + rb->mmap_user = get_current_user(); atomic_long_add(user_extra, &user->locked_vm); - event->mmap_locked = extra; - event->mmap_user = get_current_user(); - vma->vm_mm->pinned_vm += event->mmap_locked; + vma->vm_mm->pinned_vm += extra; + + ring_buffer_attach(event, rb); + rcu_assign_pointer(event->rb, rb); perf_event_update_userpage(event); @@ -3672,7 +3778,11 @@ static int perf_mmap(struct file *file, struct vm_area_struct *vma) atomic_inc(&event->mmap_count); mutex_unlock(&event->mmap_mutex); - vma->vm_flags |= VM_RESERVED; + /* + * Since pinned accounting is per vm we cannot allow fork() to copy our + * vma. + */ + vma->vm_flags |= VM_DONTCOPY | VM_RESERVED; vma->vm_ops = &perf_mmap_vmops; return ret; @@ -5961,8 +6071,7 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu, event->overflow_handler = overflow_handler; event->overflow_handler_context = context; - if (attr->disabled) - event->state = PERF_EVENT_STATE_OFF; + perf_event__state_init(event); pmu = NULL; @@ -6161,6 +6270,8 @@ perf_event_set_output(struct perf_event *event, struct perf_event *output_event) if (atomic_read(&event->mmap_count)) goto unlock; + old_rb = event->rb; + if (output_event) { /* get the rb we want to redirect to */ rb = ring_buffer_get(output_event); @@ -6168,16 +6279,28 @@ perf_event_set_output(struct perf_event *event, struct perf_event *output_event) goto unlock; } - old_rb = event->rb; - rcu_assign_pointer(event->rb, rb); if (old_rb) ring_buffer_detach(event, old_rb); + + if (rb) + ring_buffer_attach(event, rb); + + rcu_assign_pointer(event->rb, rb); + + if (old_rb) { + ring_buffer_put(old_rb); + /* + * Since we detached before setting the new rb, so that we + * could attach the new rb, we could have missed a wakeup. + * Provide it now. + */ + wake_up_all(&event->waitq); + } + ret = 0; unlock: mutex_unlock(&event->mmap_mutex); - if (old_rb) - ring_buffer_put(old_rb); out: return ret; } @@ -6370,9 +6493,17 @@ SYSCALL_DEFINE5(perf_event_open, mutex_lock(&gctx->mutex); perf_remove_from_context(group_leader); + + /* + * Removing from the context ends up with disabled + * event. What we want here is event in the initial + * startup state, ready to be add into new context. + */ + perf_event__state_init(group_leader); list_for_each_entry(sibling, &group_leader->sibling_list, group_entry) { perf_remove_from_context(sibling); + perf_event__state_init(sibling); put_ctx(gctx); } mutex_unlock(&gctx->mutex); @@ -6844,7 +6975,7 @@ inherit_task_group(struct perf_event *event, struct task_struct *parent, * child. */ - child_ctx = alloc_perf_context(event->pmu, child); + child_ctx = alloc_perf_context(parent_ctx->pmu, child); if (!child_ctx) return -ENOMEM; diff --git a/kernel/events/hw_breakpoint.c b/kernel/events/hw_breakpoint.c index bb38c4d3ee1..fc8bfcf3a3d 100644 --- a/kernel/events/hw_breakpoint.c +++ b/kernel/events/hw_breakpoint.c @@ -147,7 +147,7 @@ fetch_bp_busy_slots(struct bp_busy_slots *slots, struct perf_event *bp, return; } - for_each_online_cpu(cpu) { + for_each_possible_cpu(cpu) { unsigned int nr; nr = per_cpu(nr_cpu_bp_pinned[type], cpu); @@ -233,7 +233,7 @@ toggle_bp_slot(struct perf_event *bp, bool enable, enum bp_type_idx type, if (cpu >= 0) { toggle_bp_task_slot(bp, cpu, enable, type, weight); } else { - for_each_online_cpu(cpu) + for_each_possible_cpu(cpu) toggle_bp_task_slot(bp, cpu, enable, type, weight); } diff --git a/kernel/events/internal.h b/kernel/events/internal.h index b0b107f90af..b400e6429c0 100644 --- a/kernel/events/internal.h +++ b/kernel/events/internal.h @@ -30,6 +30,10 @@ struct ring_buffer { spinlock_t event_lock; struct list_head event_list; + atomic_t mmap_count; + unsigned long mmap_locked; + struct user_struct *mmap_user; + struct perf_event_mmap_page *user_page; void *data_pages[0]; }; diff --git a/kernel/futex.c b/kernel/futex.c index cf594d34413..6a8253de6ad 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -61,6 +61,7 @@ #include #include #include +#include #include @@ -364,7 +365,7 @@ get_futex_key(u32 __user *uaddr, int fshared, union futex_key *key, int rw) } else { key->both.offset |= FUT_OFF_INODE; /* inode-based key */ key->shared.inode = page_head->mapping->host; - key->shared.pgoff = page_head->index; + key->shared.pgoff = basepage_index(page); } get_futex_key_refs(key); @@ -2472,8 +2473,6 @@ SYSCALL_DEFINE3(get_robust_list, int, pid, if (!futex_cmpxchg_enabled) return -ENOSYS; - WARN_ONCE(1, "deprecated: get_robust_list will be deleted in 2013.\n"); - rcu_read_lock(); ret = -ESRCH; diff --git a/kernel/futex_compat.c b/kernel/futex_compat.c index 83e368b005f..a9642d52863 100644 --- a/kernel/futex_compat.c +++ b/kernel/futex_compat.c @@ -142,8 +142,6 @@ compat_sys_get_robust_list(int pid, compat_uptr_t __user *head_ptr, if (!futex_cmpxchg_enabled) return -ENOSYS; - WARN_ONCE(1, "deprecated: get_robust_list will be deleted in 2013.\n"); - rcu_read_lock(); ret = -ESRCH; diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index 11974dce958..86a0218949c 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c @@ -299,6 +299,10 @@ ktime_t ktime_sub_ns(const ktime_t kt, u64 nsec) } else { unsigned long rem = do_div(nsec, NSEC_PER_SEC); + /* Make sure nsec fits into long */ + if (unlikely(nsec > KTIME_SEC_MAX)) + return (ktime_t){ .tv64 = KTIME_MAX }; + tmp = ktime_set((long)nsec, rem); } @@ -716,17 +720,20 @@ static int hrtimer_switch_to_hres(void) return 1; } +static void clock_was_set_work(struct work_struct *work) +{ + clock_was_set(); +} + +static DECLARE_WORK(hrtimer_work, clock_was_set_work); + /* - * Called from timekeeping code to reprogramm the hrtimer interrupt - * device. If called from the timer interrupt context we defer it to - * softirq context. + * Called from timekeeping and resume code to reprogramm the hrtimer + * interrupt device on all cpus. */ void clock_was_set_delayed(void) { - struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases); - - cpu_base->clock_was_set = 1; - __raise_softirq_irqoff(HRTIMER_SOFTIRQ); + schedule_work(&hrtimer_work); } #else @@ -776,8 +783,10 @@ void hrtimers_resume(void) WARN_ONCE(!irqs_disabled(), KERN_INFO "hrtimers_resume() called with IRQs enabled!"); + /* Retrigger on the local CPU */ retrigger_next_event(NULL); - timerfd_clock_was_set(); + /* And schedule a retrigger for all others */ + clock_was_set_delayed(); } static inline void timer_stats_hrtimer_set_start_info(struct hrtimer *timer) @@ -1309,6 +1318,8 @@ void hrtimer_interrupt(struct clock_event_device *dev) expires = ktime_sub(hrtimer_get_expires(timer), base->offset); + if (expires.tv64 < 0) + expires.tv64 = KTIME_MAX; if (expires.tv64 < expires_next.tv64) expires_next = expires; break; @@ -1411,13 +1422,6 @@ void hrtimer_peek_ahead_timers(void) static void run_hrtimer_softirq(struct softirq_action *h) { - struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases); - - if (cpu_base->clock_was_set) { - cpu_base->clock_was_set = 0; - clock_was_set(); - } - hrtimer_peek_ahead_timers(); } diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 5097018f1b3..c77dd8c0b5a 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -572,9 +572,9 @@ int can_request_irq(unsigned int irq, unsigned long irqflags) return 0; if (irq_settings_can_request(desc)) { - if (desc->action) - if (irqflags & desc->action->flags & IRQF_SHARED) - canrequest =1; + if (!desc->action || + irqflags & desc->action->flags & IRQF_SHARED) + canrequest = 1; } irq_put_desc_unlock(desc, flags); return canrequest; diff --git a/kernel/irq/spurious.c b/kernel/irq/spurious.c index 611cd6003c4..7b5f012bde9 100644 --- a/kernel/irq/spurious.c +++ b/kernel/irq/spurious.c @@ -80,13 +80,11 @@ static int try_one_irq(int irq, struct irq_desc *desc, bool force) /* * All handlers must agree on IRQF_SHARED, so we test just the - * first. Check for action->next as well. + * first. */ action = desc->action; if (!action || !(action->flags & IRQF_SHARED) || - (action->flags & __IRQF_TIMER) || - (action->handler(irq, action->dev_id) == IRQ_HANDLED) || - !action->next) + (action->flags & __IRQF_TIMER)) goto out; /* Already running on another processor */ @@ -104,6 +102,7 @@ static int try_one_irq(int irq, struct irq_desc *desc, bool force) do { if (handle_irq_event(desc) == IRQ_HANDLED) ret = IRQ_HANDLED; + /* Make sure that there is still a valid action */ action = desc->action; } while ((desc->istate & IRQS_PENDING) && action); desc->istate &= ~IRQS_POLL_INPROGRESS; diff --git a/kernel/kmod.c b/kernel/kmod.c index 05698a7415f..f2490e1dd51 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c @@ -541,6 +541,11 @@ int call_usermodehelper_exec(struct subprocess_info *sub_info, int wait) int retval = 0; helper_lock(); + if (!sub_info->path) { + retval = -EINVAL; + goto out; + } + if (sub_info->path[0] == '\0') goto out; diff --git a/kernel/panic.c b/kernel/panic.c index 4931ce33305..cf894c5726e 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -91,6 +91,14 @@ void panic(const char *fmt, ...) */ local_irq_disable(); + /* + * Disable local interrupts. This will prevent panic_smp_self_stop + * from deadlocking the first cpu that invokes the panic, since + * there is nothing to prevent an interrupt handler (that runs + * after the panic_lock is acquired) from invoking panic again. + */ + local_irq_disable(); + /* * It's possible to come here directly from a panic-assertion and * not have preempt disabled. Some functions called from here want diff --git a/kernel/posix-cpu-timers.c b/kernel/posix-cpu-timers.c index 125cb67daa2..acbb79c9092 100644 --- a/kernel/posix-cpu-timers.c +++ b/kernel/posix-cpu-timers.c @@ -1422,8 +1422,10 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags, while (!signal_pending(current)) { if (timer.it.cpu.expires.sched == 0) { /* - * Our timer fired and was reset. + * Our timer fired and was reset, below + * deletion can not fail. */ + posix_cpu_timer_del(&timer); spin_unlock_irq(&timer.it_lock); return 0; } @@ -1441,9 +1443,26 @@ static int do_cpu_nanosleep(const clockid_t which_clock, int flags, * We were interrupted by a signal. */ sample_to_timespec(which_clock, timer.it.cpu.expires, rqtp); - posix_cpu_timer_set(&timer, 0, &zero_it, it); + error = posix_cpu_timer_set(&timer, 0, &zero_it, it); + if (!error) { + /* + * Timer is now unarmed, deletion can not fail. + */ + posix_cpu_timer_del(&timer); + } spin_unlock_irq(&timer.it_lock); + while (error == TIMER_RETRY) { + /* + * We need to handle case when timer was or is in the + * middle of firing. In other cases we already freed + * resources. + */ + spin_lock_irq(&timer.it_lock); + error = posix_cpu_timer_del(&timer); + spin_unlock_irq(&timer.it_lock); + } + if ((it->it_value.tv_sec | it->it_value.tv_nsec) == 0) { /* * It actually did fire already. diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c index 69185ae6b70..e885be1e8a1 100644 --- a/kernel/posix-timers.c +++ b/kernel/posix-timers.c @@ -639,6 +639,13 @@ static struct k_itimer *__lock_timer(timer_t timer_id, unsigned long *flags) { struct k_itimer *timr; + /* + * timer_t could be any type >= int and we want to make sure any + * @timer_id outside positive int range fails lookup. + */ + if ((unsigned long long)timer_id > INT_MAX) + return NULL; + rcu_read_lock(); timr = idr_find(&posix_timers_id, (int)timer_id); if (timr) { diff --git a/kernel/resource.c b/kernel/resource.c index 7203c06273a..411723db84f 100644 --- a/kernel/resource.c +++ b/kernel/resource.c @@ -782,6 +782,7 @@ static void __init __reserve_region_with_split(struct resource *root, struct resource *parent = root; struct resource *conflict; struct resource *res = kzalloc(sizeof(*res), GFP_ATOMIC); + struct resource *next_res = NULL; if (!res) return; @@ -791,21 +792,46 @@ static void __init __reserve_region_with_split(struct resource *root, res->end = end; res->flags = IORESOURCE_BUSY; - conflict = __request_resource(parent, res); - if (!conflict) - return; + while (1) { - /* failed, split and try again */ - kfree(res); + conflict = __request_resource(parent, res); + if (!conflict) { + if (!next_res) + break; + res = next_res; + next_res = NULL; + continue; + } - /* conflict covered whole area */ - if (conflict->start <= start && conflict->end >= end) - return; + /* conflict covered whole area */ + if (conflict->start <= res->start && + conflict->end >= res->end) { + kfree(res); + WARN_ON(next_res); + break; + } + + /* failed, split and try again */ + if (conflict->start > res->start) { + end = res->end; + res->end = conflict->start - 1; + if (conflict->end < end) { + next_res = kzalloc(sizeof(*next_res), + GFP_ATOMIC); + if (!next_res) { + kfree(res); + break; + } + next_res->name = name; + next_res->start = conflict->end + 1; + next_res->end = end; + next_res->flags = IORESOURCE_BUSY; + } + } else { + res->start = conflict->end + 1; + } + } - if (conflict->start > start) - __reserve_region_with_split(root, start, conflict->start-1, name); - if (conflict->end < end) - __reserve_region_with_split(root, conflict->end+1, end, name); } void __init reserve_region_with_split(struct resource *root, diff --git a/kernel/sched/clock.c b/kernel/sched/clock.c index c685e31492d..c3ae1446461 100644 --- a/kernel/sched/clock.c +++ b/kernel/sched/clock.c @@ -176,10 +176,36 @@ static u64 sched_clock_remote(struct sched_clock_data *scd) u64 this_clock, remote_clock; u64 *ptr, old_val, val; +#if BITS_PER_LONG != 64 +again: + /* + * Careful here: The local and the remote clock values need to + * be read out atomic as we need to compare the values and + * then update either the local or the remote side. So the + * cmpxchg64 below only protects one readout. + * + * We must reread via sched_clock_local() in the retry case on + * 32bit as an NMI could use sched_clock_local() via the + * tracer and hit between the readout of + * the low32bit and the high 32bit portion. + */ + this_clock = sched_clock_local(my_scd); + /* + * We must enforce atomic readout on 32bit, otherwise the + * update on the remote cpu can hit inbetween the readout of + * the low32bit and the high 32bit portion. + */ + remote_clock = cmpxchg64(&scd->clock, 0, 0); +#else + /* + * On 64bit the read of [my]scd->clock is atomic versus the + * update, so we can avoid the above 32bit dance. + */ sched_clock_local(my_scd); again: this_clock = my_scd->clock; remote_clock = scd->clock; +#endif /* * Use the opportunity that we have both locks diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 6172320383b..1ee70baf12c 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -5573,7 +5573,7 @@ static unsigned int get_rr_interval_fair(struct rq *rq, struct task_struct *task * idle runqueue: */ if (rq->cfs.load.weight) - rr_interval = NS_TO_JIFFIES(sched_slice(&rq->cfs, se)); + rr_interval = NS_TO_JIFFIES(sched_slice(cfs_rq_of(se), se)); return rr_interval; } diff --git a/kernel/signal.c b/kernel/signal.c index cd0e615b558..54dc68a9f73 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -482,7 +482,7 @@ flush_signal_handlers(struct task_struct *t, int force_default) if (force_default || ka->sa.sa_handler != SIG_IGN) ka->sa.sa_handler = SIG_DFL; ka->sa.sa_flags = 0; -#ifdef SA_RESTORER +#ifdef __ARCH_HAS_SA_RESTORER ka->sa.sa_restorer = NULL; #endif sigemptyset(&ka->sa.sa_mask); @@ -2867,7 +2867,7 @@ do_send_specific(pid_t tgid, pid_t pid, int sig, struct siginfo *info) static int do_tkill(pid_t tgid, pid_t pid, int sig) { - struct siginfo info; + struct siginfo info = {}; info.si_signo = sig; info.si_errno = 0; diff --git a/kernel/sys.c b/kernel/sys.c index d9798315069..4c9ad73719a 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -322,7 +322,6 @@ void kernel_restart_prepare(char *cmd) system_state = SYSTEM_RESTART; usermodehelper_disable(); device_shutdown(); - syscore_shutdown(); } /** @@ -356,6 +355,29 @@ int unregister_reboot_notifier(struct notifier_block *nb) } EXPORT_SYMBOL(unregister_reboot_notifier); +/* Add backwards compatibility for stable trees. */ +#ifndef PF_NO_SETAFFINITY +#define PF_NO_SETAFFINITY PF_THREAD_BOUND +#endif + +static void migrate_to_reboot_cpu(void) +{ + /* The boot cpu is always logical cpu 0 */ + int cpu = 0; + + cpu_hotplug_disable(); + + /* Make certain the cpu I'm about to reboot on is online */ + if (!cpu_online(cpu)) + cpu = cpumask_first(cpu_online_mask); + + /* Prevent races with other tasks migrating this task */ + current->flags |= PF_NO_SETAFFINITY; + + /* Make certain I only run on the appropriate processor */ + set_cpus_allowed_ptr(current, cpumask_of(cpu)); +} + /** * kernel_restart - reboot the system * @cmd: pointer to buffer containing command to execute for restart @@ -367,7 +389,8 @@ EXPORT_SYMBOL(unregister_reboot_notifier); void kernel_restart(char *cmd) { kernel_restart_prepare(cmd); - disable_nonboot_cpus(); + migrate_to_reboot_cpu(); + syscore_shutdown(); if (!cmd) printk(KERN_EMERG "Restarting system.\n"); else @@ -393,6 +416,7 @@ static void kernel_shutdown_prepare(enum system_states state) void kernel_halt(void) { kernel_shutdown_prepare(SYSTEM_HALT); + migrate_to_reboot_cpu(); syscore_shutdown(); printk(KERN_EMERG "System halted.\n"); kmsg_dump(KMSG_DUMP_HALT); @@ -411,7 +435,7 @@ void kernel_power_off(void) kernel_shutdown_prepare(SYSTEM_POWER_OFF); if (pm_power_off_prepare) pm_power_off_prepare(); - disable_nonboot_cpus(); + migrate_to_reboot_cpu(); syscore_shutdown(); printk(KERN_EMERG "Power down.\n"); kmsg_dump(KMSG_DUMP_POWEROFF); diff --git a/kernel/sysctl_binary.c b/kernel/sysctl_binary.c index d42c279db29..4db093105dd 100644 --- a/kernel/sysctl_binary.c +++ b/kernel/sysctl_binary.c @@ -1195,9 +1195,10 @@ static ssize_t bin_dn_node_address(struct file *file, /* Convert the decnet address to binary */ result = -EIO; - nodep = strchr(buf, '.') + 1; + nodep = strchr(buf, '.'); if (!nodep) goto out; + ++nodep; area = simple_strtoul(buf, NULL, 10); node = simple_strtoul(nodep, NULL, 10); diff --git a/kernel/time/tick-broadcast.c b/kernel/time/tick-broadcast.c index d6d0d4127d7..edb173f3c91 100644 --- a/kernel/time/tick-broadcast.c +++ b/kernel/time/tick-broadcast.c @@ -66,12 +66,17 @@ static void tick_broadcast_start_periodic(struct clock_event_device *bc) */ int tick_check_broadcast_device(struct clock_event_device *dev) { - if ((tick_broadcast_device.evtdev && + struct clock_event_device *cur = tick_broadcast_device.evtdev; + + if ((dev->features & CLOCK_EVT_FEAT_DUMMY) || + (tick_broadcast_device.evtdev && tick_broadcast_device.evtdev->rating >= dev->rating) || (dev->features & CLOCK_EVT_FEAT_C3STOP)) return 0; clockevents_exchange_device(tick_broadcast_device.evtdev, dev); + if (cur) + cur->event_handler = clockevents_handle_noop; tick_broadcast_device.evtdev = dev; if (!cpumask_empty(tick_get_broadcast_mask())) tick_broadcast_start_periodic(dev); @@ -415,7 +420,15 @@ void tick_check_oneshot_broadcast(int cpu) if (cpumask_test_cpu(cpu, to_cpumask(tick_broadcast_oneshot_mask))) { struct tick_device *td = &per_cpu(tick_cpu_device, cpu); - clockevents_set_mode(td->evtdev, CLOCK_EVT_MODE_ONESHOT); + /* + * We might be in the middle of switching over from + * periodic to oneshot. If the CPU has not yet + * switched over, leave the device alone. + */ + if (td->mode == TICKDEV_MODE_ONESHOT) { + clockevents_set_mode(td->evtdev, + CLOCK_EVT_MODE_ONESHOT); + } } } diff --git a/kernel/time/tick-common.c b/kernel/time/tick-common.c index da6c9ecad4e..ead79bce125 100644 --- a/kernel/time/tick-common.c +++ b/kernel/time/tick-common.c @@ -323,6 +323,7 @@ static void tick_shutdown(unsigned int *cpup) */ dev->mode = CLOCK_EVT_MODE_UNUSED; clockevents_exchange_device(dev, NULL); + dev->event_handler = clockevents_handle_noop; td->evtdev = NULL; } raw_spin_unlock_irqrestore(&tick_device_lock, flags); diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 4b82d55eaf6..fb3970e15a1 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -151,7 +151,6 @@ static void tick_nohz_update_jiffies(ktime_t now) tick_do_update_jiffies64(now); local_irq_restore(flags); - calc_load_exit_idle(); touch_softlockup_watchdog(); } @@ -501,14 +500,19 @@ void tick_nohz_idle_enter(void) */ void tick_nohz_irq_exit(void) { + unsigned long flags; struct tick_sched *ts = &__get_cpu_var(tick_cpu_sched); if (!ts->inidle) return; - + + local_irq_save(flags); + /* Cancel the timer because CPU already waken up from the C-states*/ menu_hrtimer_cancel(); tick_nohz_stop_sched_tick(ts); + + local_irq_restore(flags); } /** @@ -927,7 +931,7 @@ void tick_cancel_sched_timer(int cpu) hrtimer_cancel(&ts->sched_timer); # endif - ts->nohz_mode = NOHZ_MODE_INACTIVE; + memset(ts, 0, sizeof(*ts)); } #endif diff --git a/kernel/timeconst.pl b/kernel/timeconst.pl index eb51d76e058..3f42652a6a3 100644 --- a/kernel/timeconst.pl +++ b/kernel/timeconst.pl @@ -369,10 +369,8 @@ (@) die "Usage: $0 HZ\n"; } - @val = @{$canned_values{$hz}}; - if (!defined(@val)) { - @val = compute_values($hz); - } + $cv = $canned_values{$hz}; + @val = defined($cv) ? @$cv : compute_values($hz); output($hz, @val); } exit 0; diff --git a/kernel/timer.c b/kernel/timer.c index e2e6145486e..29477c4aa56 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -145,9 +145,11 @@ static unsigned long round_jiffies_common(unsigned long j, int cpu, /* now that we have rounded, subtract the extra skew again */ j -= cpu * 3; - if (j <= jiffies) /* rounding ate our timeout entirely; */ - return original; - return j; + /* + * Make sure j is still in the future. Otherwise return the + * unmodified value. + */ + return time_is_after_jiffies(j) ? j : original; } /** diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig index 00586680b93..64de72f1a6b 100644 --- a/kernel/trace/Kconfig +++ b/kernel/trace/Kconfig @@ -391,24 +391,28 @@ config KPROBE_EVENT If you want to use perf tools, this option is strongly recommended. config DYNAMIC_FTRACE - bool "enable/disable ftrace tracepoints dynamically" + bool "enable/disable function tracing dynamically" depends on FUNCTION_TRACER depends on HAVE_DYNAMIC_FTRACE default n help - This option will modify all the calls to ftrace dynamically - (will patch them out of the binary image and replace them - with a No-Op instruction) as they are called. A table is - created to dynamically enable them again. + This option will modify all the calls to function tracing + dynamically (will patch them out of the binary image and + replace them with a No-Op instruction) on boot up. During + compile time, a table is made of all the locations that ftrace + can function trace, and this table is linked into the kernel + image. When this is enabled, functions can be individually + enabled, and the functions not enabled will not affect + performance of the system. + + See the files in /sys/kernel/debug/tracing: + available_filter_functions + set_ftrace_filter + set_ftrace_notrace This way a CONFIG_FUNCTION_TRACER kernel is slightly larger, but otherwise has native performance as long as no tracing is active. - The changes to the code are done by a kernel thread that - wakes up once a second and checks to see if any ftrace calls - were made. If so, it runs stop_machine (stops all CPUS) - and modifies the code to jump over the call to ftrace. - config FUNCTION_PROFILER bool "Kernel function profiler" depends on FUNCTION_TRACER diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 6b194d842b1..e101cf9acc0 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -624,7 +624,7 @@ int ftrace_profile_pages_init(struct ftrace_profile_stat *stat) pages = DIV_ROUND_UP(functions, PROFILES_PER_PAGE); - for (i = 0; i < pages; i++) { + for (i = 1; i < pages; i++) { pg->next = (void *)get_zeroed_page(GFP_KERNEL); if (!pg->next) goto out_free; @@ -642,7 +642,6 @@ int ftrace_profile_pages_init(struct ftrace_profile_stat *stat) free_page(tmp); } - free_page((unsigned long)stat->pages); stat->pages = NULL; stat->start = NULL; @@ -1000,6 +999,19 @@ static __init void ftrace_profile_debugfs(struct dentry *d_tracer) static struct pid * const ftrace_swapper_pid = &init_struct_pid; +loff_t +ftrace_filter_lseek(struct file *file, loff_t offset, int whence) +{ + loff_t ret; + + if (file->f_mode & FMODE_READ) + ret = seq_lseek(file, offset, whence); + else + file->f_pos = ret = 1; + + return ret; +} + #ifdef CONFIG_DYNAMIC_FTRACE #ifndef CONFIG_FTRACE_MCOUNT_RECORD @@ -2542,7 +2554,7 @@ static void ftrace_filter_reset(struct ftrace_hash *hash) * routine, you can use ftrace_filter_write() for the write * routine if @flag has FTRACE_ITER_FILTER set, or * ftrace_notrace_write() if @flag has FTRACE_ITER_NOTRACE set. - * ftrace_regex_lseek() should be used as the lseek routine, and + * ftrace_filter_lseek() should be used as the lseek routine, and * release must call ftrace_regex_release(). */ int @@ -2626,19 +2638,6 @@ ftrace_notrace_open(struct inode *inode, struct file *file) inode, file); } -loff_t -ftrace_regex_lseek(struct file *file, loff_t offset, int origin) -{ - loff_t ret; - - if (file->f_mode & FMODE_READ) - ret = seq_lseek(file, offset, origin); - else - file->f_pos = ret = 1; - - return ret; -} - static int ftrace_match(char *str, char *regex, int len, int type) { int matched = 0; @@ -3034,8 +3033,8 @@ __unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops, continue; } - hlist_del(&entry->node); - call_rcu(&entry->rcu, ftrace_free_entry_rcu); + hlist_del_rcu(&entry->node); + call_rcu_sched(&entry->rcu, ftrace_free_entry_rcu); } } __disable_ftrace_function_probe(); @@ -3446,7 +3445,7 @@ static const struct file_operations ftrace_filter_fops = { .open = ftrace_filter_open, .read = seq_read, .write = ftrace_filter_write, - .llseek = ftrace_regex_lseek, + .llseek = ftrace_filter_lseek, .release = ftrace_regex_release, }; @@ -3454,7 +3453,7 @@ static const struct file_operations ftrace_notrace_fops = { .open = ftrace_notrace_open, .read = seq_read, .write = ftrace_notrace_write, - .llseek = ftrace_regex_lseek, + .llseek = ftrace_filter_lseek, .release = ftrace_regex_release, }; @@ -3612,7 +3611,8 @@ ftrace_set_func(unsigned long *array, int *idx, char *buffer) if (fail) return -EINVAL; - ftrace_graph_filter_enabled = 1; + ftrace_graph_filter_enabled = !!(*idx); + return 0; } @@ -3659,8 +3659,8 @@ static const struct file_operations ftrace_graph_fops = { .open = ftrace_graph_open, .read = seq_read, .write = ftrace_graph_write, + .llseek = ftrace_filter_lseek, .release = ftrace_graph_release, - .llseek = seq_lseek, }; #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ @@ -3841,37 +3841,51 @@ static void ftrace_init_module(struct module *mod, ftrace_process_locs(mod, start, end); } -static int ftrace_module_notify(struct notifier_block *self, - unsigned long val, void *data) +static int ftrace_module_notify_enter(struct notifier_block *self, + unsigned long val, void *data) { struct module *mod = data; - switch (val) { - case MODULE_STATE_COMING: + if (val == MODULE_STATE_COMING) ftrace_init_module(mod, mod->ftrace_callsites, mod->ftrace_callsites + mod->num_ftrace_callsites); - break; - case MODULE_STATE_GOING: + return 0; +} + +static int ftrace_module_notify_exit(struct notifier_block *self, + unsigned long val, void *data) +{ + struct module *mod = data; + + if (val == MODULE_STATE_GOING) ftrace_release_mod(mod); - break; - } return 0; } #else -static int ftrace_module_notify(struct notifier_block *self, - unsigned long val, void *data) +static int ftrace_module_notify_enter(struct notifier_block *self, + unsigned long val, void *data) +{ + return 0; +} +static int ftrace_module_notify_exit(struct notifier_block *self, + unsigned long val, void *data) { return 0; } #endif /* CONFIG_MODULES */ -struct notifier_block ftrace_module_nb = { - .notifier_call = ftrace_module_notify, +struct notifier_block ftrace_module_enter_nb = { + .notifier_call = ftrace_module_notify_enter, .priority = INT_MAX, /* Run before anything that can use kprobes */ }; +struct notifier_block ftrace_module_exit_nb = { + .notifier_call = ftrace_module_notify_exit, + .priority = INT_MIN, /* Run after anything that can remove kprobes */ +}; + extern unsigned long __start_mcount_loc[]; extern unsigned long __stop_mcount_loc[]; @@ -3903,9 +3917,13 @@ void __init ftrace_init(void) __start_mcount_loc, __stop_mcount_loc); - ret = register_module_notifier(&ftrace_module_nb); + ret = register_module_notifier(&ftrace_module_enter_nb); + if (ret) + pr_warning("Failed to register trace ftrace module enter notifier\n"); + + ret = register_module_notifier(&ftrace_module_exit_nb); if (ret) - pr_warning("Failed to register trace ftrace module notifier\n"); + pr_warning("Failed to register trace ftrace module exit notifier\n"); set_ftrace_early_filters(); @@ -4243,7 +4261,7 @@ static const struct file_operations ftrace_pid_fops = { .open = ftrace_pid_open, .write = ftrace_pid_write, .read = seq_read, - .llseek = seq_lseek, + .llseek = ftrace_filter_lseek, .release = ftrace_pid_release, }; @@ -4363,12 +4381,8 @@ ftrace_enable_sysctl(struct ctl_table *table, int write, ftrace_startup_sysctl(); /* we are starting ftrace again */ - if (ftrace_ops_list != &ftrace_list_end) { - if (ftrace_ops_list->next == &ftrace_list_end) - ftrace_trace_function = ftrace_ops_list->func; - else - ftrace_trace_function = ftrace_ops_list_func; - } + if (ftrace_ops_list != &ftrace_list_end) + update_ftrace_function(); } else { /* stopping ftrace calls (just send to ftrace_stub) */ diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 8da07dd9227..d3a66a67abb 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -688,7 +688,15 @@ __update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu) memcpy(max_data->comm, tsk->comm, TASK_COMM_LEN); max_data->pid = tsk->pid; - max_data->uid = task_uid(tsk); + /* + * If tsk == current, then use current_uid(), as that does not use + * RCU. The irq tracer can be called out of RCU scope. + */ + if (tsk == current) + max_data->uid = current_uid(); + else + max_data->uid = task_uid(tsk); + max_data->nice = tsk->static_prio - 20 - MAX_RT_PRIO; max_data->policy = tsk->policy; max_data->rt_priority = tsk->rt_priority; @@ -709,7 +717,7 @@ __update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu) void update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu) { - struct ring_buffer *buf = tr->buffer; + struct ring_buffer *buf; if (trace_stop_count) return; @@ -721,6 +729,7 @@ update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu) } arch_spin_lock(&ftrace_max_lock); + buf = tr->buffer; tr->buffer = max_tr.buffer; max_tr.buffer = buf; @@ -2744,11 +2753,25 @@ static int set_tracer_option(struct tracer *trace, char *cmp, int neg) return -EINVAL; } -static void set_tracer_flags(unsigned int mask, int enabled) +/* Some tracers require overwrite to stay enabled */ +int trace_keep_overwrite(struct tracer *tracer, u32 mask, int set) +{ + if (tracer->enabled && (mask & TRACE_ITER_OVERWRITE) && !set) + return -1; + + return 0; +} + +int set_tracer_flag(unsigned int mask, int enabled) { /* do nothing if flag is already set */ if (!!(trace_flags & mask) == !!enabled) - return; + return 0; + + /* Give the tracer a chance to approve the change */ + if (current_trace->flag_changed) + if (current_trace->flag_changed(current_trace, mask, !!enabled)) + return -EINVAL; if (enabled) trace_flags |= mask; @@ -2760,6 +2783,8 @@ static void set_tracer_flags(unsigned int mask, int enabled) if (mask == TRACE_ITER_OVERWRITE) ring_buffer_change_overwrite(global_trace.buffer, enabled); + + return 0; } static ssize_t @@ -2769,7 +2794,7 @@ tracing_trace_options_write(struct file *filp, const char __user *ubuf, char buf[64]; char *cmp; int neg = 0; - int ret; + int ret = -ENODEV; int i; if (cnt >= sizeof(buf)) @@ -2786,21 +2811,23 @@ tracing_trace_options_write(struct file *filp, const char __user *ubuf, cmp += 2; } + mutex_lock(&trace_types_lock); + for (i = 0; trace_options[i]; i++) { if (strcmp(cmp, trace_options[i]) == 0) { - set_tracer_flags(1 << i, !neg); + ret = set_tracer_flag(1 << i, !neg); break; } } /* If no option could be set, test the specific tracer options */ - if (!trace_options[i]) { - mutex_lock(&trace_types_lock); + if (!trace_options[i]) ret = set_tracer_option(current_trace, cmp, neg); - mutex_unlock(&trace_types_lock); - if (ret) - return ret; - } + + mutex_unlock(&trace_types_lock); + + if (ret < 0) + return ret; *ppos += cnt; @@ -3124,6 +3151,9 @@ static int tracing_set_tracer(const char *buf) goto out; trace_branch_disable(); + + current_trace->enabled = false; + if (current_trace && current_trace->reset) current_trace->reset(tr); if (current_trace && current_trace->use_max_tr) { @@ -3153,6 +3183,7 @@ static int tracing_set_tracer(const char *buf) goto out; } + current_trace->enabled = true; trace_branch_enable(tr); out: mutex_unlock(&trace_types_lock); @@ -3449,6 +3480,7 @@ tracing_read_pipe(struct file *filp, char __user *ubuf, memset(&iter->seq, 0, sizeof(struct trace_iterator) - offsetof(struct trace_iterator, seq)); + cpumask_clear(iter->started); iter->pos = -1; trace_event_read_lock(); @@ -4489,7 +4521,13 @@ trace_options_core_write(struct file *filp, const char __user *ubuf, size_t cnt, if (val != 0 && val != 1) return -EINVAL; - set_tracer_flags(1 << index, val); + + mutex_lock(&trace_types_lock); + ret = set_tracer_flag(1 << index, val); + mutex_unlock(&trace_types_lock); + + if (ret < 0) + return ret; *ppos += cnt; @@ -4692,6 +4730,8 @@ static __init int tracer_init_debugfs(void) trace_access_lock_init(); d_tracer = tracing_init_dentry(); + if (!d_tracer) + return 0; trace_create_file("tracing_enabled", 0644, d_tracer, &global_trace, &tracing_ctrl_fops); @@ -4828,36 +4868,32 @@ void trace_init_global_iter(struct trace_iterator *iter) iter->cpu_file = TRACE_PIPE_ALL_CPU; } -static void -__ftrace_dump(bool disable_tracing, enum ftrace_dump_mode oops_dump_mode) +void ftrace_dump(enum ftrace_dump_mode oops_dump_mode) { - static arch_spinlock_t ftrace_dump_lock = - (arch_spinlock_t)__ARCH_SPIN_LOCK_UNLOCKED; /* use static because iter can be a bit big for the stack */ static struct trace_iterator iter; + static atomic_t dump_running; unsigned int old_userobj; - static int dump_ran; unsigned long flags; int cnt = 0, cpu; - /* only one dump */ - local_irq_save(flags); - arch_spin_lock(&ftrace_dump_lock); - if (dump_ran) - goto out; - - dump_ran = 1; + /* Only allow one dump user at a time. */ + if (atomic_inc_return(&dump_running) != 1) { + atomic_dec(&dump_running); + return; + } + /* + * Always turn off tracing when we dump. + * We don't need to show trace output of what happens + * between multiple crashes. + * + * If the user does a sysrq-z, then they can re-enable + * tracing with echo 1 > tracing_on. + */ tracing_off(); - /* Did function tracer already get disabled? */ - if (ftrace_is_dead()) { - printk("# WARNING: FUNCTION TRACING IS CORRUPTED\n"); - printk("# MAY BE MISSING FUNCTION EVENTS\n"); - } - - if (disable_tracing) - ftrace_kill(); + local_irq_save(flags); trace_init_global_iter(&iter); @@ -4890,6 +4926,12 @@ __ftrace_dump(bool disable_tracing, enum ftrace_dump_mode oops_dump_mode) printk(KERN_TRACE "Dumping ftrace buffer:\n"); + /* Did function tracer already get disabled? */ + if (ftrace_is_dead()) { + printk("# WARNING: FUNCTION TRACING IS CORRUPTED\n"); + printk("# MAY BE MISSING FUNCTION EVENTS\n"); + } + /* * We need to stop all tracing on all CPUS to read the * the next buffer. This is a bit expensive, but is @@ -4929,26 +4971,14 @@ __ftrace_dump(bool disable_tracing, enum ftrace_dump_mode oops_dump_mode) printk(KERN_TRACE "---------------------------------\n"); out_enable: - /* Re-enable tracing if requested */ - if (!disable_tracing) { - trace_flags |= old_userobj; + trace_flags |= old_userobj; - for_each_tracing_cpu(cpu) { - atomic_dec(&iter.tr->data[cpu]->disabled); - } - tracing_on(); + for_each_tracing_cpu(cpu) { + atomic_dec(&iter.tr->data[cpu]->disabled); } - - out: - arch_spin_unlock(&ftrace_dump_lock); + atomic_dec(&dump_running); local_irq_restore(flags); } - -/* By default: disable tracing after the dump */ -void ftrace_dump(enum ftrace_dump_mode oops_dump_mode) -{ - __ftrace_dump(true, oops_dump_mode); -} EXPORT_SYMBOL_GPL(ftrace_dump); __init static int tracer_alloc_buffers(void) diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index f95d65da6db..7360674ea04 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h @@ -278,10 +278,14 @@ struct tracer { enum print_line_t (*print_line)(struct trace_iterator *iter); /* If you handled the flag setting, return 0 */ int (*set_flag)(u32 old_flags, u32 bit, int set); + /* Return 0 if OK with change, else return non-zero */ + int (*flag_changed)(struct tracer *tracer, + u32 mask, int set); struct tracer *next; struct tracer_flags *flags; int print_max; int use_max_tr; + bool enabled; }; @@ -826,6 +830,9 @@ extern struct list_head ftrace_events; extern const char *__start___trace_bprintk_fmt[]; extern const char *__stop___trace_bprintk_fmt[]; +int trace_keep_overwrite(struct tracer *tracer, u32 mask, int set); +int set_tracer_flag(unsigned int mask, int enabled); + #undef FTRACE_ENTRY #define FTRACE_ENTRY(call, struct_name, id, tstruct, print, filter) \ extern struct ftrace_event_call \ diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c index 006d5c9b261..4d7cd25aeec 100644 --- a/kernel/trace/trace_events_filter.c +++ b/kernel/trace/trace_events_filter.c @@ -777,7 +777,11 @@ static int filter_set_pred(struct event_filter *filter, static void __free_preds(struct event_filter *filter) { + int i; + if (filter->preds) { + for (i = 0; i < filter->n_preds; i++) + kfree(filter->preds[i].ops); kfree(filter->preds); filter->preds = NULL; } diff --git a/kernel/trace/trace_irqsoff.c b/kernel/trace/trace_irqsoff.c index 99d20e92036..8dd139a3f6c 100644 --- a/kernel/trace/trace_irqsoff.c +++ b/kernel/trace/trace_irqsoff.c @@ -32,7 +32,7 @@ enum { static int trace_type __read_mostly; -static int save_lat_flag; +static int save_flags; static void stop_irqsoff_tracer(struct trace_array *tr, int graph); static int start_irqsoff_tracer(struct trace_array *tr, int graph); @@ -557,8 +557,11 @@ static void stop_irqsoff_tracer(struct trace_array *tr, int graph) static void __irqsoff_tracer_init(struct trace_array *tr) { - save_lat_flag = trace_flags & TRACE_ITER_LATENCY_FMT; - trace_flags |= TRACE_ITER_LATENCY_FMT; + save_flags = trace_flags; + + /* non overwrite screws up the latency tracers */ + set_tracer_flag(TRACE_ITER_OVERWRITE, 1); + set_tracer_flag(TRACE_ITER_LATENCY_FMT, 1); tracing_max_latency = 0; irqsoff_trace = tr; @@ -572,10 +575,13 @@ static void __irqsoff_tracer_init(struct trace_array *tr) static void irqsoff_tracer_reset(struct trace_array *tr) { + int lat_flag = save_flags & TRACE_ITER_LATENCY_FMT; + int overwrite_flag = save_flags & TRACE_ITER_OVERWRITE; + stop_irqsoff_tracer(tr, is_graph()); - if (!save_lat_flag) - trace_flags &= ~TRACE_ITER_LATENCY_FMT; + set_tracer_flag(TRACE_ITER_LATENCY_FMT, lat_flag); + set_tracer_flag(TRACE_ITER_OVERWRITE, overwrite_flag); } static void irqsoff_tracer_start(struct trace_array *tr) @@ -608,6 +614,7 @@ static struct tracer irqsoff_tracer __read_mostly = .print_line = irqsoff_print_line, .flags = &tracer_flags, .set_flag = irqsoff_set_flag, + .flag_changed = trace_keep_overwrite, #ifdef CONFIG_FTRACE_SELFTEST .selftest = trace_selftest_startup_irqsoff, #endif @@ -641,6 +648,7 @@ static struct tracer preemptoff_tracer __read_mostly = .print_line = irqsoff_print_line, .flags = &tracer_flags, .set_flag = irqsoff_set_flag, + .flag_changed = trace_keep_overwrite, #ifdef CONFIG_FTRACE_SELFTEST .selftest = trace_selftest_startup_preemptoff, #endif @@ -676,6 +684,7 @@ static struct tracer preemptirqsoff_tracer __read_mostly = .print_line = irqsoff_print_line, .flags = &tracer_flags, .set_flag = irqsoff_set_flag, + .flag_changed = trace_keep_overwrite, #ifdef CONFIG_FTRACE_SELFTEST .selftest = trace_selftest_startup_preemptirqsoff, #endif diff --git a/kernel/trace/trace_sched_wakeup.c b/kernel/trace/trace_sched_wakeup.c index ff791ea48b5..9eadedc9b4a 100644 --- a/kernel/trace/trace_sched_wakeup.c +++ b/kernel/trace/trace_sched_wakeup.c @@ -36,7 +36,7 @@ static void __wakeup_reset(struct trace_array *tr); static int wakeup_graph_entry(struct ftrace_graph_ent *trace); static void wakeup_graph_return(struct ftrace_graph_ret *trace); -static int save_lat_flag; +static int save_flags; #define TRACE_DISPLAY_GRAPH 1 @@ -539,8 +539,11 @@ static void stop_wakeup_tracer(struct trace_array *tr) static int __wakeup_tracer_init(struct trace_array *tr) { - save_lat_flag = trace_flags & TRACE_ITER_LATENCY_FMT; - trace_flags |= TRACE_ITER_LATENCY_FMT; + save_flags = trace_flags; + + /* non overwrite screws up the latency tracers */ + set_tracer_flag(TRACE_ITER_OVERWRITE, 1); + set_tracer_flag(TRACE_ITER_LATENCY_FMT, 1); tracing_max_latency = 0; wakeup_trace = tr; @@ -562,12 +565,15 @@ static int wakeup_rt_tracer_init(struct trace_array *tr) static void wakeup_tracer_reset(struct trace_array *tr) { + int lat_flag = save_flags & TRACE_ITER_LATENCY_FMT; + int overwrite_flag = save_flags & TRACE_ITER_OVERWRITE; + stop_wakeup_tracer(tr); /* make sure we put back any tasks we are tracing */ wakeup_reset(tr); - if (!save_lat_flag) - trace_flags &= ~TRACE_ITER_LATENCY_FMT; + set_tracer_flag(TRACE_ITER_LATENCY_FMT, lat_flag); + set_tracer_flag(TRACE_ITER_OVERWRITE, overwrite_flag); } static void wakeup_tracer_start(struct trace_array *tr) @@ -593,6 +599,7 @@ static struct tracer wakeup_tracer __read_mostly = .print_line = wakeup_print_line, .flags = &tracer_flags, .set_flag = wakeup_set_flag, + .flag_changed = trace_keep_overwrite, #ifdef CONFIG_FTRACE_SELFTEST .selftest = trace_selftest_startup_wakeup, #endif @@ -614,6 +621,7 @@ static struct tracer wakeup_rt_tracer __read_mostly = .print_line = wakeup_print_line, .flags = &tracer_flags, .set_flag = wakeup_set_flag, + .flag_changed = trace_keep_overwrite, #ifdef CONFIG_FTRACE_SELFTEST .selftest = trace_selftest_startup_wakeup, #endif diff --git a/kernel/trace/trace_selftest.c b/kernel/trace/trace_selftest.c index 288541f977f..09fd98afd26 100644 --- a/kernel/trace/trace_selftest.c +++ b/kernel/trace/trace_selftest.c @@ -461,8 +461,6 @@ trace_selftest_startup_function(struct tracer *trace, struct trace_array *tr) /* Maximum number of functions to trace before diagnosing a hang */ #define GRAPH_MAX_FUNC_TEST 100000000 -static void -__ftrace_dump(bool disable_tracing, enum ftrace_dump_mode oops_dump_mode); static unsigned int graph_hang_thresh; /* Wrap the real function entry probe to avoid possible hanging */ @@ -472,8 +470,11 @@ static int trace_graph_entry_watchdog(struct ftrace_graph_ent *trace) if (unlikely(++graph_hang_thresh > GRAPH_MAX_FUNC_TEST)) { ftrace_graph_stop(); printk(KERN_WARNING "BUG: Function graph tracer hang!\n"); - if (ftrace_dump_on_oops) - __ftrace_dump(false, DUMP_ALL); + if (ftrace_dump_on_oops) { + ftrace_dump(DUMP_ALL); + /* ftrace_dump() disables tracing */ + tracing_on(); + } return 0; } diff --git a/kernel/trace/trace_stack.c b/kernel/trace/trace_stack.c index d4545f49242..8298997c248 100644 --- a/kernel/trace/trace_stack.c +++ b/kernel/trace/trace_stack.c @@ -20,13 +20,24 @@ #define STACK_TRACE_ENTRIES 500 +#ifdef CC_USING_FENTRY +# define fentry 1 +#else +# define fentry 0 +#endif + static unsigned long stack_dump_trace[STACK_TRACE_ENTRIES+1] = { [0 ... (STACK_TRACE_ENTRIES)] = ULONG_MAX }; static unsigned stack_dump_index[STACK_TRACE_ENTRIES]; +/* + * Reserve one entry for the passed in ip. This will allow + * us to remove most or all of the stack size overhead + * added by the stack tracer itself. + */ static struct stack_trace max_stack_trace = { - .max_entries = STACK_TRACE_ENTRIES, - .entries = stack_dump_trace, + .max_entries = STACK_TRACE_ENTRIES - 1, + .entries = &stack_dump_trace[1], }; static unsigned long max_stack_size; @@ -40,25 +51,34 @@ static DEFINE_MUTEX(stack_sysctl_mutex); int stack_tracer_enabled; static int last_stack_tracer_enabled; -static inline void check_stack(void) +static inline void +check_stack(unsigned long ip, unsigned long *stack) { unsigned long this_size, flags; unsigned long *p, *top, *start; + static int tracer_frame; + int frame_size = ACCESS_ONCE(tracer_frame); int i; - this_size = ((unsigned long)&this_size) & (THREAD_SIZE-1); + this_size = ((unsigned long)stack) & (THREAD_SIZE-1); this_size = THREAD_SIZE - this_size; + /* Remove the frame of the tracer */ + this_size -= frame_size; if (this_size <= max_stack_size) return; /* we do not handle interrupt stacks yet */ - if (!object_is_on_stack(&this_size)) + if (!object_is_on_stack(stack)) return; local_irq_save(flags); arch_spin_lock(&max_stack_lock); + /* In case another CPU set the tracer_frame on us */ + if (unlikely(!frame_size)) + this_size -= tracer_frame; + /* a race could have already updated it */ if (this_size <= max_stack_size) goto out; @@ -70,11 +90,19 @@ static inline void check_stack(void) save_stack_trace(&max_stack_trace); + /* + * Add the passed in ip from the function tracer. + * Searching for this on the stack will skip over + * most of the overhead from the stack tracer itself. + */ + stack_dump_trace[0] = ip; + max_stack_trace.nr_entries++; + /* * Now find where in the stack these are. */ i = 0; - start = &this_size; + start = stack; top = (unsigned long *) (((unsigned long)start & ~(THREAD_SIZE-1)) + THREAD_SIZE); @@ -98,6 +126,18 @@ static inline void check_stack(void) found = 1; /* Start the search from here */ start = p + 1; + /* + * We do not want to show the overhead + * of the stack tracer stack in the + * max stack. If we haven't figured + * out what that is, then figure it out + * now. + */ + if (unlikely(!tracer_frame) && i == 1) { + tracer_frame = (p - stack) * + sizeof(unsigned long); + max_stack_size -= tracer_frame; + } } } @@ -113,6 +153,7 @@ static inline void check_stack(void) static void stack_trace_call(unsigned long ip, unsigned long parent_ip) { + unsigned long stack; int cpu; if (unlikely(!ftrace_enabled || stack_trace_disabled)) @@ -125,7 +166,26 @@ stack_trace_call(unsigned long ip, unsigned long parent_ip) if (per_cpu(trace_active, cpu)++ != 0) goto out; - check_stack(); + /* + * When fentry is used, the traced function does not get + * its stack frame set up, and we lose the parent. + * The ip is pretty useless because the function tracer + * was called before that function set up its stack frame. + * In this case, we use the parent ip. + * + * By adding the return address of either the parent ip + * or the current ip we can disregard most of the stack usage + * caused by the stack tracer itself. + * + * The function tracer always reports the address of where the + * mcount call was, but the stack will hold the return address. + */ + if (fentry) + ip = parent_ip; + else + ip += MCOUNT_INSN_SIZE; + + check_stack(ip, &stack); out: per_cpu(trace_active, cpu)--; @@ -324,7 +384,7 @@ static const struct file_operations stack_trace_filter_fops = { .open = stack_trace_filter_open, .read = seq_read, .write = ftrace_filter_write, - .llseek = ftrace_regex_lseek, + .llseek = ftrace_filter_lseek, .release = ftrace_regex_release, }; @@ -373,6 +433,8 @@ static __init int stack_trace_init(void) struct dentry *d_tracer; d_tracer = tracing_init_dentry(); + if (!d_tracer) + return 0; trace_create_file("stack_max_size", 0644, d_tracer, &max_stack_size, &stack_max_size_fops); diff --git a/kernel/trace/trace_stat.c b/kernel/trace/trace_stat.c index 96cffb269e7..847f88a6194 100644 --- a/kernel/trace/trace_stat.c +++ b/kernel/trace/trace_stat.c @@ -307,6 +307,8 @@ static int tracing_stat_init(void) struct dentry *d_tracing; d_tracing = tracing_init_dentry(); + if (!d_tracing) + return 0; stat_dir = debugfs_create_dir("trace_stat", d_tracing); if (!stat_dir) diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c index 96fc7336909..c9ce09addac 100644 --- a/kernel/trace/trace_syscalls.c +++ b/kernel/trace/trace_syscalls.c @@ -305,6 +305,8 @@ void ftrace_syscall_enter(void *ignore, struct pt_regs *regs, long id) struct ring_buffer *buffer; int size; int syscall_nr; + unsigned long irq_flags; + int pc; syscall_nr = syscall_get_nr(current, regs); if (syscall_nr < 0) @@ -318,8 +320,11 @@ void ftrace_syscall_enter(void *ignore, struct pt_regs *regs, long id) size = sizeof(*entry) + sizeof(unsigned long) * sys_data->nb_args; + local_save_flags(irq_flags); + pc = preempt_count(); + event = trace_current_buffer_lock_reserve(&buffer, - sys_data->enter_event->event.type, size, 0, 0); + sys_data->enter_event->event.type, size, irq_flags, pc); if (!event) return; @@ -329,7 +334,8 @@ void ftrace_syscall_enter(void *ignore, struct pt_regs *regs, long id) if (!filter_current_check_discard(buffer, sys_data->enter_event, entry, event)) - trace_current_buffer_unlock_commit(buffer, event, 0, 0); + trace_current_buffer_unlock_commit(buffer, event, + irq_flags, pc); } void ftrace_syscall_exit(void *ignore, struct pt_regs *regs, long ret) @@ -339,6 +345,8 @@ void ftrace_syscall_exit(void *ignore, struct pt_regs *regs, long ret) struct ring_buffer_event *event; struct ring_buffer *buffer; int syscall_nr; + unsigned long irq_flags; + int pc; syscall_nr = syscall_get_nr(current, regs); if (syscall_nr < 0) @@ -350,8 +358,12 @@ void ftrace_syscall_exit(void *ignore, struct pt_regs *regs, long ret) if (!sys_data) return; + local_save_flags(irq_flags); + pc = preempt_count(); + event = trace_current_buffer_lock_reserve(&buffer, - sys_data->exit_event->event.type, sizeof(*entry), 0, 0); + sys_data->exit_event->event.type, sizeof(*entry), + irq_flags, pc); if (!event) return; @@ -361,7 +373,8 @@ void ftrace_syscall_exit(void *ignore, struct pt_regs *regs, long ret) if (!filter_current_check_discard(buffer, sys_data->exit_event, entry, event)) - trace_current_buffer_unlock_commit(buffer, event, 0, 0); + trace_current_buffer_unlock_commit(buffer, event, + irq_flags, pc); } int reg_event_syscall_enter(struct ftrace_event_call *call) diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 657ba28e79a..7aaf3c25d6a 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -134,6 +134,7 @@ struct worker { }; struct work_struct *current_work; /* L: work being processed */ + work_func_t current_func; /* L: current_work's fn */ struct cpu_workqueue_struct *current_cwq; /* L: current_work's cwq */ struct list_head scheduled; /* L: scheduled works */ struct task_struct *task; /* I: worker task */ @@ -867,7 +868,8 @@ static struct worker *__find_worker_executing_work(struct global_cwq *gcwq, struct hlist_node *tmp; hlist_for_each_entry(worker, tmp, bwh, hentry) - if (worker->current_work == work) + if (worker->current_work == work && + worker->current_func == work->func) return worker; return NULL; } @@ -877,9 +879,27 @@ static struct worker *__find_worker_executing_work(struct global_cwq *gcwq, * @gcwq: gcwq of interest * @work: work to find worker for * - * Find a worker which is executing @work on @gcwq. This function is - * identical to __find_worker_executing_work() except that this - * function calculates @bwh itself. + * Find a worker which is executing @work on @gcwq by searching + * @gcwq->busy_hash which is keyed by the address of @work. For a worker + * to match, its current execution should match the address of @work and + * its work function. This is to avoid unwanted dependency between + * unrelated work executions through a work item being recycled while still + * being executed. + * + * This is a bit tricky. A work item may be freed once its execution + * starts and nothing prevents the freed area from being recycled for + * another work item. If the same work item address ends up being reused + * before the original execution finishes, workqueue will identify the + * recycled work item as currently executing and make it wait until the + * current execution finishes, introducing an unwanted dependency. + * + * This function checks the work item address, work function and workqueue + * to avoid false positives. Note that this isn't complete as one may + * construct a work function which can introduce dependency onto itself + * through a recycled work item. Well, if somebody wants to shoot oneself + * in the foot that badly, there's only so much we can do, and if such + * deadlock actually occurs, it should be easy to locate the culprit work + * function. * * CONTEXT: * spin_lock_irq(gcwq->lock). @@ -1724,10 +1744,9 @@ static void move_linked_works(struct work_struct *work, struct list_head *head, *nextp = n; } -static void cwq_activate_first_delayed(struct cpu_workqueue_struct *cwq) +static void cwq_activate_delayed_work(struct work_struct *work) { - struct work_struct *work = list_first_entry(&cwq->delayed_works, - struct work_struct, entry); + struct cpu_workqueue_struct *cwq = get_work_cwq(work); trace_workqueue_activate_work(work); move_linked_works(work, &cwq->pool->worklist, NULL); @@ -1735,6 +1754,14 @@ static void cwq_activate_first_delayed(struct cpu_workqueue_struct *cwq) cwq->nr_active++; } +static void cwq_activate_first_delayed(struct cpu_workqueue_struct *cwq) +{ + struct work_struct *work = list_first_entry(&cwq->delayed_works, + struct work_struct, entry); + + cwq_activate_delayed_work(work); +} + /** * cwq_dec_nr_in_flight - decrement cwq's nr_in_flight * @cwq: cwq of interest @@ -1807,7 +1834,6 @@ __acquires(&gcwq->lock) struct global_cwq *gcwq = pool->gcwq; struct hlist_head *bwh = busy_worker_head(gcwq, work); bool cpu_intensive = cwq->wq->flags & WQ_CPU_INTENSIVE; - work_func_t f = work->func; int work_color; struct worker *collision; #ifdef CONFIG_LOCKDEP @@ -1836,6 +1862,7 @@ __acquires(&gcwq->lock) debug_work_deactivate(work); hlist_add_head(&worker->hentry, bwh); worker->current_work = work; + worker->current_func = work->func; worker->current_cwq = cwq; work_color = get_work_color(work); @@ -1865,7 +1892,7 @@ __acquires(&gcwq->lock) lock_map_acquire_read(&cwq->wq->lockdep_map); lock_map_acquire(&lockdep_map); trace_workqueue_execute_start(work); - f(work); + worker->current_func(work); /* * While we must be careful to not use "work" after this, the trace * point will only record its address. @@ -1875,11 +1902,10 @@ __acquires(&gcwq->lock) lock_map_release(&cwq->wq->lockdep_map); if (unlikely(in_atomic() || lockdep_depth(current) > 0)) { - printk(KERN_ERR "BUG: workqueue leaked lock or atomic: " - "%s/0x%08x/%d\n", - current->comm, preempt_count(), task_pid_nr(current)); - printk(KERN_ERR " last function: "); - print_symbol("%s\n", (unsigned long)f); + pr_err("BUG: workqueue leaked lock or atomic: %s/0x%08x/%d\n" + " last function: %pf\n", + current->comm, preempt_count(), task_pid_nr(current), + worker->current_func); debug_show_held_locks(current); BUG_ON(PANIC_CORRUPTION); dump_stack(); @@ -1894,6 +1920,7 @@ __acquires(&gcwq->lock) /* we're done with it, release */ hlist_del_init(&worker->hentry); worker->current_work = NULL; + worker->current_func = NULL; worker->current_cwq = NULL; cwq_dec_nr_in_flight(cwq, work_color, false); } @@ -2623,6 +2650,18 @@ static int try_to_grab_pending(struct work_struct *work) smp_rmb(); if (gcwq == get_work_gcwq(work)) { debug_work_deactivate(work); + + /* + * A delayed work item cannot be grabbed directly + * because it might have linked NO_COLOR work items + * which, if left on the delayed_list, will confuse + * cwq->nr_active management later on and cause + * stall. Make sure the work item is activated + * before grabbing. + */ + if (*work_data_bits(work) & WORK_STRUCT_DELAYED) + cwq_activate_delayed_work(work); + list_del_init(&work->entry); cwq_dec_nr_in_flight(get_work_cwq(work), get_work_color(work), diff --git a/lib/idr.c b/lib/idr.c index 4046e29c0a9..e90d2d05d78 100644 --- a/lib/idr.c +++ b/lib/idr.c @@ -625,7 +625,14 @@ void *idr_get_next(struct idr *idp, int *nextidp) return p; } - id += 1 << n; + /* + * Proceed to the next layer at the current level. Unlike + * idr_for_each(), @id isn't guaranteed to be aligned to + * layer boundary at this point and adding 1 << n may + * incorrectly skip IDs. Make sure we jump to the + * beginning of the next layer using round_up(). + */ + id = round_up(id + 1, 1 << n); while (n < fls(id)) { n += IDR_BITS; p = *--paa; diff --git a/lib/kobject.c b/lib/kobject.c index aeefa8bc8b1..d90c69286ba 100644 --- a/lib/kobject.c +++ b/lib/kobject.c @@ -531,6 +531,13 @@ struct kobject *kobject_get(struct kobject *kobj) return kobj; } +static struct kobject *kobject_get_unless_zero(struct kobject *kobj) +{ + if (!kref_get_unless_zero(&kobj->kref)) + kobj = NULL; + return kobj; +} + /* * kobject_cleanup - free kobject resources. * @kobj: object to cleanup @@ -753,7 +760,7 @@ struct kobject *kset_find_obj(struct kset *kset, const char *name) list_for_each_entry(k, &kset->list, entry) { if (kobject_name(k) && !strcmp(kobject_name(k), name)) { - ret = kobject_get(k); + ret = kobject_get_unless_zero(k); break; } } diff --git a/mm/fadvise.c b/mm/fadvise.c index 469491e0af7..dcb98722a22 100644 --- a/mm/fadvise.c +++ b/mm/fadvise.c @@ -17,6 +17,7 @@ #include #include #include +#include #include @@ -124,9 +125,22 @@ SYSCALL_DEFINE(fadvise64_64)(int fd, loff_t offset, loff_t len, int advice) start_index = (offset+(PAGE_CACHE_SIZE-1)) >> PAGE_CACHE_SHIFT; end_index = (endbyte >> PAGE_CACHE_SHIFT); - if (end_index >= start_index) - invalidate_mapping_pages(mapping, start_index, + if (end_index >= start_index) { + unsigned long count = invalidate_mapping_pages(mapping, + start_index, end_index); + + /* + * If fewer pages were invalidated than expected then + * it is possible that some of the pages were on + * a per-cpu pagevec for a remote CPU. Drain all + * pagevecs and try again. + */ + if (count < (end_index - start_index + 1)) { + lru_add_drain_all(); + invalidate_mapping_pages(mapping, start_index, end_index); + } + } break; default: ret = -EINVAL; diff --git a/mm/huge_memory.c b/mm/huge_memory.c index caf15b6fa75..ef99c15fa36 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -1949,7 +1949,12 @@ static void collapse_huge_page(struct mm_struct *mm, pte_unmap(pte); spin_lock(&mm->page_table_lock); BUG_ON(!pmd_none(*pmd)); - set_pmd_at(mm, address, pmd, _pmd); + /* + * We can only use set_pmd_at when establishing + * hugepmds and never for establishing regular pmds that + * points to regular pagetables. Use pmd_populate for that + */ + pmd_populate(mm, pmd, pmd_pgtable(_pmd)); spin_unlock(&mm->page_table_lock); anon_vma_unlock(vma->anon_vma); goto out; diff --git a/mm/hugetlb.c b/mm/hugetlb.c index c384e0901f9..af20b77a624 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -679,6 +679,23 @@ int PageHuge(struct page *page) } EXPORT_SYMBOL_GPL(PageHuge); +pgoff_t __basepage_index(struct page *page) +{ + struct page *page_head = compound_head(page); + pgoff_t index = page_index(page_head); + unsigned long compound_idx; + + if (!PageHuge(page_head)) + return page_index(page); + + if (compound_order(page_head) >= MAX_ORDER) + compound_idx = page_to_pfn(page) - page_to_pfn(page_head); + else + compound_idx = page - page_head; + + return (index << compound_order(page_head)) + compound_idx; +} + static struct page *alloc_fresh_huge_page_node(struct hstate *h, int nid) { struct page *page; @@ -2096,8 +2113,12 @@ int hugetlb_report_node_meminfo(int nid, char *buf) /* Return the number pages of memory we physically have, in PAGE_SIZE units. */ unsigned long hugetlb_total_pages(void) { - struct hstate *h = &default_hstate; - return h->nr_huge_pages * pages_per_huge_page(h); + struct hstate *h; + unsigned long nr_total_pages = 0; + + for_each_hstate(h) + nr_total_pages += h->nr_huge_pages * pages_per_huge_page(h); + return nr_total_pages; } static int hugetlb_acct_memory(struct hstate *h, long delta) @@ -2764,7 +2785,7 @@ int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma, if (ptep) { entry = huge_ptep_get(ptep); if (unlikely(is_hugetlb_entry_migration(entry))) { - migration_entry_wait(mm, (pmd_t *)ptep, address); + migration_entry_wait_huge(mm, ptep); return 0; } else if (unlikely(is_hugetlb_entry_hwpoisoned(entry))) return VM_FAULT_HWPOISON_LARGE | @@ -2902,7 +2923,17 @@ int follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma, break; } - if (absent || + /* + * We need call hugetlb_fault for both hugepages under migration + * (in which case hugetlb_fault waits for the migration,) and + * hwpoisoned hugepages (in which case we need to prevent the + * caller from accessing to them.) In order to do this, we use + * here is_swap_pte instead of is_hugetlb_entry_migration and + * is_hugetlb_entry_hwpoisoned. This is because it simply covers + * both cases, and because we can't follow correct pages + * directly from any kind of swap entries. + */ + if (absent || is_swap_pte(huge_ptep_get(pte)) || ((flags & FOLL_WRITE) && !pte_write(huge_ptep_get(pte)))) { int ret; diff --git a/mm/migrate.c b/mm/migrate.c index 11072383ae1..5f588b1f2f6 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -145,7 +145,7 @@ static int remove_migration_pte(struct page *new, struct vm_area_struct *vma, if (PageHuge(new)) pte = pte_mkhuge(pte); #endif - flush_cache_page(vma, addr, pte_pfn(pte)); + flush_dcache_page(new); set_pte_at(mm, addr, ptep, pte); if (PageHuge(new)) { @@ -180,15 +180,14 @@ static void remove_migration_ptes(struct page *old, struct page *new) * get to the page and wait until migration is finished. * When we return from this function the fault will be retried. */ -void migration_entry_wait(struct mm_struct *mm, pmd_t *pmd, - unsigned long address) +static void __migration_entry_wait(struct mm_struct *mm, pte_t *ptep, + spinlock_t *ptl) { - pte_t *ptep, pte; - spinlock_t *ptl; + pte_t pte; swp_entry_t entry; struct page *page; - ptep = pte_offset_map_lock(mm, pmd, address, &ptl); + spin_lock(ptl); pte = *ptep; if (!is_swap_pte(pte)) goto out; @@ -216,6 +215,20 @@ void migration_entry_wait(struct mm_struct *mm, pmd_t *pmd, pte_unmap_unlock(ptep, ptl); } +void migration_entry_wait(struct mm_struct *mm, pmd_t *pmd, + unsigned long address) +{ + spinlock_t *ptl = pte_lockptr(mm, pmd); + pte_t *ptep = pte_offset_map(pmd, address); + __migration_entry_wait(mm, ptep, ptl); +} + +void migration_entry_wait_huge(struct mm_struct *mm, pte_t *pte) +{ + spinlock_t *ptl = &(mm)->page_table_lock; + __migration_entry_wait(mm, pte, ptl); +} + #ifdef CONFIG_BLOCK /* Returns true if all buffers are successfully locked */ static bool buffer_migrate_lock_buffers(struct buffer_head *head, diff --git a/mm/mmap.c b/mm/mmap.c index ded6fe9f144..d8e55886494 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -1136,15 +1136,19 @@ SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len, file = fget(fd); if (!file) goto out; + if (is_file_hugepages(file)) + len = ALIGN(len, huge_page_size(hstate_file(file))); } else if (flags & MAP_HUGETLB) { struct user_struct *user = NULL; + + len = ALIGN(len, huge_page_size(&default_hstate)); /* * VM_NORESERVE is used because the reservations will be * taken when vm_ops->mmap() is called * A dummy user value is used because we are not locking * memory so no accounting is necessary */ - file = hugetlb_file_setup(HUGETLB_ANON_FILE, addr, len, + file = hugetlb_file_setup(HUGETLB_ANON_FILE, len, VM_NORESERVE, &user, HUGETLB_ANONHUGE_INODE); if (IS_ERR(file)) @@ -1626,7 +1630,7 @@ struct vm_area_struct *find_vma(struct mm_struct *mm, unsigned long addr) if (mm) { /* Check the cache first. */ /* (Cache hit rate is typically around 35%.) */ - vma = mm->mmap_cache; + vma = ACCESS_ONCE(mm->mmap_cache); if (!(vma && vma->vm_end > addr && vma->vm_start <= addr)) { struct rb_node * rb_node; @@ -1927,7 +1931,7 @@ static void unmap_region(struct mm_struct *mm, unmap_vmas(&tlb, vma, start, end, &nr_accounted, NULL); vm_unacct_memory(nr_accounted); free_pgtables(&tlb, vma, prev ? prev->vm_end : FIRST_USER_ADDRESS, - next ? next->vm_start : 0); + next ? next->vm_start : USER_PGTABLES_CEILING); tlb_finish_mmu(&tlb, start, end); } @@ -2315,7 +2319,7 @@ void exit_mmap(struct mm_struct *mm) unmap_vmas(&tlb, vma, 0, -1, &nr_accounted, NULL); vm_unacct_memory(nr_accounted); - free_pgtables(&tlb, vma, FIRST_USER_ADDRESS, 0); + free_pgtables(&tlb, vma, FIRST_USER_ADDRESS, USER_PGTABLES_CEILING); tlb_finish_mmu(&tlb, 0, -1); /* diff --git a/mm/mmu_notifier.c b/mm/mmu_notifier.c index 862b60822d9..c1f947b4f61 100644 --- a/mm/mmu_notifier.c +++ b/mm/mmu_notifier.c @@ -14,10 +14,14 @@ #include #include #include +#include #include #include #include +/* global SRCU for all MMs */ +static struct srcu_struct srcu; + /* * This function can't run concurrently against mmu_notifier_register * because mm->mm_users > 0 during mmu_notifier_register and exit_mmap @@ -25,32 +29,32 @@ * in parallel despite there being no task using this mm any more, * through the vmas outside of the exit_mmap context, such as with * vmtruncate. This serializes against mmu_notifier_unregister with - * the mmu_notifier_mm->lock in addition to RCU and it serializes - * against the other mmu notifiers with RCU. struct mmu_notifier_mm + * the mmu_notifier_mm->lock in addition to SRCU and it serializes + * against the other mmu notifiers with SRCU. struct mmu_notifier_mm * can't go away from under us as exit_mmap holds an mm_count pin * itself. */ void __mmu_notifier_release(struct mm_struct *mm) { struct mmu_notifier *mn; - struct hlist_node *n; + struct hlist_node *node; + int id; /* - * RCU here will block mmu_notifier_unregister until + * SRCU here will block mmu_notifier_unregister until * ->release returns. */ - rcu_read_lock(); - hlist_for_each_entry_rcu(mn, n, &mm->mmu_notifier_mm->list, hlist) + id = srcu_read_lock(&srcu); + hlist_for_each_entry_rcu(mn, node, &mm->mmu_notifier_mm->list, hlist) /* - * if ->release runs before mmu_notifier_unregister it - * must be handled as it's the only way for the driver - * to flush all existing sptes and stop the driver - * from establishing any more sptes before all the - * pages in the mm are freed. + * If ->release runs before mmu_notifier_unregister it must be + * handled, as it's the only way for the driver to flush all + * existing sptes and stop the driver from establishing any more + * sptes before all the pages in the mm are freed. */ if (mn->ops->release) mn->ops->release(mn, mm); - rcu_read_unlock(); + srcu_read_unlock(&srcu, id); spin_lock(&mm->mmu_notifier_mm->lock); while (unlikely(!hlist_empty(&mm->mmu_notifier_mm->list))) { @@ -59,24 +63,24 @@ void __mmu_notifier_release(struct mm_struct *mm) hlist); /* * We arrived before mmu_notifier_unregister so - * mmu_notifier_unregister will do nothing other than - * to wait ->release to finish and - * mmu_notifier_unregister to return. + * mmu_notifier_unregister will do nothing other than to wait + * for ->release to finish and for mmu_notifier_unregister to + * return. */ hlist_del_init_rcu(&mn->hlist); } spin_unlock(&mm->mmu_notifier_mm->lock); /* - * synchronize_rcu here prevents mmu_notifier_release to - * return to exit_mmap (which would proceed freeing all pages - * in the mm) until the ->release method returns, if it was - * invoked by mmu_notifier_unregister. + * synchronize_srcu here prevents mmu_notifier_release from returning to + * exit_mmap (which would proceed with freeing all pages in the mm) + * until the ->release method returns, if it was invoked by + * mmu_notifier_unregister. * - * The mmu_notifier_mm can't go away from under us because one - * mm_count is hold by exit_mmap. + * The mmu_notifier_mm can't go away from under us because one mm_count + * is held by exit_mmap. */ - synchronize_rcu(); + synchronize_srcu(&srcu); } /* @@ -89,14 +93,14 @@ int __mmu_notifier_clear_flush_young(struct mm_struct *mm, { struct mmu_notifier *mn; struct hlist_node *n; - int young = 0; + int young = 0, id; - rcu_read_lock(); + id = srcu_read_lock(&srcu); hlist_for_each_entry_rcu(mn, n, &mm->mmu_notifier_mm->list, hlist) { if (mn->ops->clear_flush_young) young |= mn->ops->clear_flush_young(mn, mm, address); } - rcu_read_unlock(); + srcu_read_unlock(&srcu, id); return young; } @@ -106,9 +110,9 @@ int __mmu_notifier_test_young(struct mm_struct *mm, { struct mmu_notifier *mn; struct hlist_node *n; - int young = 0; + int young = 0, id; - rcu_read_lock(); + id = srcu_read_lock(&srcu); hlist_for_each_entry_rcu(mn, n, &mm->mmu_notifier_mm->list, hlist) { if (mn->ops->test_young) { young = mn->ops->test_young(mn, mm, address); @@ -116,7 +120,7 @@ int __mmu_notifier_test_young(struct mm_struct *mm, break; } } - rcu_read_unlock(); + srcu_read_unlock(&srcu, id); return young; } @@ -126,8 +130,9 @@ void __mmu_notifier_change_pte(struct mm_struct *mm, unsigned long address, { struct mmu_notifier *mn; struct hlist_node *n; + int id; - rcu_read_lock(); + id = srcu_read_lock(&srcu); hlist_for_each_entry_rcu(mn, n, &mm->mmu_notifier_mm->list, hlist) { if (mn->ops->change_pte) mn->ops->change_pte(mn, mm, address, pte); @@ -138,7 +143,7 @@ void __mmu_notifier_change_pte(struct mm_struct *mm, unsigned long address, else if (mn->ops->invalidate_page) mn->ops->invalidate_page(mn, mm, address); } - rcu_read_unlock(); + srcu_read_unlock(&srcu, id); } void __mmu_notifier_invalidate_page(struct mm_struct *mm, @@ -146,13 +151,14 @@ void __mmu_notifier_invalidate_page(struct mm_struct *mm, { struct mmu_notifier *mn; struct hlist_node *n; + int id; - rcu_read_lock(); + id = srcu_read_lock(&srcu); hlist_for_each_entry_rcu(mn, n, &mm->mmu_notifier_mm->list, hlist) { if (mn->ops->invalidate_page) mn->ops->invalidate_page(mn, mm, address); } - rcu_read_unlock(); + srcu_read_unlock(&srcu, id); } void __mmu_notifier_invalidate_range_start(struct mm_struct *mm, @@ -160,13 +166,14 @@ void __mmu_notifier_invalidate_range_start(struct mm_struct *mm, { struct mmu_notifier *mn; struct hlist_node *n; + int id; - rcu_read_lock(); + id = srcu_read_lock(&srcu); hlist_for_each_entry_rcu(mn, n, &mm->mmu_notifier_mm->list, hlist) { if (mn->ops->invalidate_range_start) mn->ops->invalidate_range_start(mn, mm, start, end); } - rcu_read_unlock(); + srcu_read_unlock(&srcu, id); } void __mmu_notifier_invalidate_range_end(struct mm_struct *mm, @@ -174,13 +181,14 @@ void __mmu_notifier_invalidate_range_end(struct mm_struct *mm, { struct mmu_notifier *mn; struct hlist_node *n; + int id; - rcu_read_lock(); + id = srcu_read_lock(&srcu); hlist_for_each_entry_rcu(mn, n, &mm->mmu_notifier_mm->list, hlist) { if (mn->ops->invalidate_range_end) mn->ops->invalidate_range_end(mn, mm, start, end); } - rcu_read_unlock(); + srcu_read_unlock(&srcu, id); } static int do_mmu_notifier_register(struct mmu_notifier *mn, @@ -192,6 +200,12 @@ static int do_mmu_notifier_register(struct mmu_notifier *mn, BUG_ON(atomic_read(&mm->mm_users) <= 0); + /* + * Verify that mmu_notifier_init() already run and the global srcu is + * initialized. + */ + BUG_ON(!srcu.per_cpu_ref); + ret = -ENOMEM; mmu_notifier_mm = kmalloc(sizeof(struct mmu_notifier_mm), GFP_KERNEL); if (unlikely(!mmu_notifier_mm)) @@ -274,8 +288,8 @@ void __mmu_notifier_mm_destroy(struct mm_struct *mm) /* * This releases the mm_count pin automatically and frees the mm * structure if it was the last user of it. It serializes against - * running mmu notifiers with RCU and against mmu_notifier_unregister - * with the unregister lock + RCU. All sptes must be dropped before + * running mmu notifiers with SRCU and against mmu_notifier_unregister + * with the unregister lock + SRCU. All sptes must be dropped before * calling mmu_notifier_unregister. ->release or any other notifier * method may be invoked concurrently with mmu_notifier_unregister, * and only after mmu_notifier_unregister returned we're guaranteed @@ -287,33 +301,44 @@ void mmu_notifier_unregister(struct mmu_notifier *mn, struct mm_struct *mm) if (!hlist_unhashed(&mn->hlist)) { /* - * RCU here will force exit_mmap to wait ->release to finish - * before freeing the pages. + * SRCU here will force exit_mmap to wait for ->release to + * finish before freeing the pages. */ - rcu_read_lock(); + int id; + id = srcu_read_lock(&srcu); /* - * exit_mmap will block in mmu_notifier_release to - * guarantee ->release is called before freeing the - * pages. + * exit_mmap will block in mmu_notifier_release to guarantee + * that ->release is called before freeing the pages. */ if (mn->ops->release) mn->ops->release(mn, mm); - rcu_read_unlock(); + srcu_read_unlock(&srcu, id); spin_lock(&mm->mmu_notifier_mm->lock); - hlist_del_rcu(&mn->hlist); + /* + * Can not use list_del_rcu() since __mmu_notifier_release + * can delete it before we hold the lock. + */ + hlist_del_init_rcu(&mn->hlist); spin_unlock(&mm->mmu_notifier_mm->lock); } /* - * Wait any running method to finish, of course including + * Wait for any running method to finish, of course including * ->release if it was run by mmu_notifier_relase instead of us. */ - synchronize_rcu(); + synchronize_srcu(&srcu); BUG_ON(atomic_read(&mm->mm_count) <= 0); mmdrop(mm); } EXPORT_SYMBOL_GPL(mmu_notifier_unregister); + +static int __init mmu_notifier_init(void) +{ + return init_srcu_struct(&srcu); +} + +module_init(mmu_notifier_init); diff --git a/mm/nommu.c b/mm/nommu.c index bb8f4f004a8..d3afb4765c8 100644 --- a/mm/nommu.c +++ b/mm/nommu.c @@ -807,7 +807,7 @@ struct vm_area_struct *find_vma(struct mm_struct *mm, unsigned long addr) struct vm_area_struct *vma; /* check the cache first */ - vma = mm->mmap_cache; + vma = ACCESS_ONCE(mm->mmap_cache); if (vma && vma->vm_start <= addr && vma->vm_end > addr) return vma; @@ -1856,6 +1856,16 @@ int remap_pfn_range(struct vm_area_struct *vma, unsigned long addr, } EXPORT_SYMBOL(remap_pfn_range); +int vm_iomap_memory(struct vm_area_struct *vma, phys_addr_t start, unsigned long len) +{ + unsigned long pfn = start >> PAGE_SHIFT; + unsigned long vm_len = vma->vm_end - vma->vm_start; + + pfn += vma->vm_pgoff; + return io_remap_pfn_range(vma, vma->vm_start, pfn, vm_len, vma->vm_page_prot); +} +EXPORT_SYMBOL(vm_iomap_memory); + int remap_vmalloc_range(struct vm_area_struct *vma, void *addr, unsigned long pgoff) { diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 932c7bdd01c..350c6a4bcf5 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -4388,10 +4388,11 @@ static void __meminit calculate_node_totalpages(struct pglist_data *pgdat, * round what is now in bits to nearest long in bits, then return it in * bytes. */ -static unsigned long __init usemap_size(unsigned long zonesize) +static unsigned long __init usemap_size(unsigned long zone_start_pfn, unsigned long zonesize) { unsigned long usemapsize; + zonesize += zone_start_pfn & (pageblock_nr_pages-1); usemapsize = roundup(zonesize, pageblock_nr_pages); usemapsize = usemapsize >> pageblock_order; usemapsize *= NR_PAGEBLOCK_BITS; @@ -4401,17 +4402,19 @@ static unsigned long __init usemap_size(unsigned long zonesize) } static void __init setup_usemap(struct pglist_data *pgdat, - struct zone *zone, unsigned long zonesize) + struct zone *zone, + unsigned long zone_start_pfn, + unsigned long zonesize) { - unsigned long usemapsize = usemap_size(zonesize); + unsigned long usemapsize = usemap_size(zone_start_pfn, zonesize); zone->pageblock_flags = NULL; if (usemapsize) zone->pageblock_flags = alloc_bootmem_node_nopanic(pgdat, usemapsize); } #else -static inline void setup_usemap(struct pglist_data *pgdat, - struct zone *zone, unsigned long zonesize) {} +static inline void setup_usemap(struct pglist_data *pgdat, struct zone *zone, + unsigned long zone_start_pfn, unsigned long zonesize) {} #endif /* CONFIG_SPARSEMEM */ #ifdef CONFIG_HUGETLB_PAGE_SIZE_VARIABLE @@ -4539,7 +4542,7 @@ static void __paginginit free_area_init_core(struct pglist_data *pgdat, continue; set_pageblock_order(pageblock_default_order()); - setup_usemap(pgdat, zone, size); + setup_usemap(pgdat, zone, zone_start_pfn, size); ret = init_currently_empty_zone(zone, zone_start_pfn, size, MEMMAP_EARLY); BUG_ON(ret); @@ -6040,6 +6043,10 @@ __offline_isolated_pages(unsigned long start_pfn, unsigned long end_pfn) zone->free_area[order].nr_free--; __mod_zone_page_state(zone, NR_FREE_PAGES, - (1UL << order)); +#ifdef CONFIG_HIGHMEM + if (PageHighMem(page)) + totalhigh_pages -= 1 << order; +#endif for (i = 0; i < (1 << order); i++) SetPageReserved((page+i)); pfn += (1 << order); diff --git a/mm/pagewalk.c b/mm/pagewalk.c index aa9701e1271..1090e772a26 100644 --- a/mm/pagewalk.c +++ b/mm/pagewalk.c @@ -127,28 +127,7 @@ static int walk_hugetlb_range(struct vm_area_struct *vma, return 0; } -static struct vm_area_struct* hugetlb_vma(unsigned long addr, struct mm_walk *walk) -{ - struct vm_area_struct *vma; - - /* We don't need vma lookup at all. */ - if (!walk->hugetlb_entry) - return NULL; - - VM_BUG_ON(!rwsem_is_locked(&walk->mm->mmap_sem)); - vma = find_vma(walk->mm, addr); - if (vma && vma->vm_start <= addr && is_vm_hugetlb_page(vma)) - return vma; - - return NULL; -} - #else /* CONFIG_HUGETLB_PAGE */ -static struct vm_area_struct* hugetlb_vma(unsigned long addr, struct mm_walk *walk) -{ - return NULL; -} - static int walk_hugetlb_range(struct vm_area_struct *vma, unsigned long addr, unsigned long end, struct mm_walk *walk) @@ -199,30 +178,53 @@ int walk_page_range(unsigned long addr, unsigned long end, if (!walk->mm) return -EINVAL; + VM_BUG_ON(!rwsem_is_locked(&walk->mm->mmap_sem)); + pgd = pgd_offset(walk->mm, addr); do { - struct vm_area_struct *vma; + struct vm_area_struct *vma = NULL; next = pgd_addr_end(addr, end); /* - * handle hugetlb vma individually because pagetable walk for - * the hugetlb page is dependent on the architecture and - * we can't handled it in the same manner as non-huge pages. + * This function was not intended to be vma based. + * But there are vma special cases to be handled: + * - hugetlb vma's + * - VM_PFNMAP vma's */ - vma = hugetlb_vma(addr, walk); + vma = find_vma(walk->mm, addr); if (vma) { - if (vma->vm_end < next) + /* + * There are no page structures backing a VM_PFNMAP + * range, so do not allow split_huge_page_pmd(). + */ + if ((vma->vm_start <= addr) && + (vma->vm_flags & VM_PFNMAP)) { next = vma->vm_end; + pgd = pgd_offset(walk->mm, next); + continue; + } /* - * Hugepage is very tightly coupled with vma, so - * walk through hugetlb entries within a given vma. + * Handle hugetlb vma individually because pagetable + * walk for the hugetlb page is dependent on the + * architecture and we can't handled it in the same + * manner as non-huge pages. */ - err = walk_hugetlb_range(vma, addr, next, walk); - if (err) - break; - pgd = pgd_offset(walk->mm, next); - continue; + if (walk->hugetlb_entry && (vma->vm_start <= addr) && + is_vm_hugetlb_page(vma)) { + if (vma->vm_end < next) + next = vma->vm_end; + /* + * Hugepage is very tightly coupled with vma, + * so walk through hugetlb entries within a + * given vma. + */ + err = walk_hugetlb_range(vma, addr, next, walk); + if (err) + break; + pgd = pgd_offset(walk->mm, next); + continue; + } } if (pgd_none_or_clear_bad(pgd)) { diff --git a/mm/process_vm_access.c b/mm/process_vm_access.c index c20ff48994c..b63e84a7fa8 100644 --- a/mm/process_vm_access.c +++ b/mm/process_vm_access.c @@ -429,12 +429,6 @@ compat_process_vm_rw(compat_pid_t pid, if (flags != 0) return -EINVAL; - if (!access_ok(VERIFY_READ, lvec, liovcnt * sizeof(*lvec))) - goto out; - - if (!access_ok(VERIFY_READ, rvec, riovcnt * sizeof(*rvec))) - goto out; - if (vm_write) rc = compat_rw_copy_check_uvector(WRITE, lvec, liovcnt, UIO_FASTIOV, iovstack_l, @@ -459,8 +453,6 @@ compat_process_vm_rw(compat_pid_t pid, kfree(iov_r); if (iov_l != iovstack_l) kfree(iov_l); - -out: return rc; } diff --git a/mm/shmem.c b/mm/shmem.c index c6acb7ef5e9..448956691e6 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -2177,6 +2177,7 @@ static int shmem_remount_fs(struct super_block *sb, int *flags, char *data) unsigned long inodes; int error = -EINVAL; + config.mpol = NULL; if (shmem_parse_options(data, &config, true)) return error; @@ -2201,8 +2202,13 @@ static int shmem_remount_fs(struct super_block *sb, int *flags, char *data) sbinfo->max_inodes = config.max_inodes; sbinfo->free_inodes = config.max_inodes - inodes; - mpol_put(sbinfo->mpol); - sbinfo->mpol = config.mpol; /* transfers initial ref */ + /* + * Preserve previous mempolicy unless mpol remount option was specified. + */ + if (config.mpol) { + mpol_put(sbinfo->mpol); + sbinfo->mpol = config.mpol; /* transfers initial ref */ + } out: spin_unlock(&sbinfo->stat_lock); return error; diff --git a/mm/swap_state.c b/mm/swap_state.c index 4c5ff7f284d..1fa92206829 100644 --- a/mm/swap_state.c +++ b/mm/swap_state.c @@ -313,8 +313,24 @@ struct page *read_swap_cache_async(swp_entry_t entry, gfp_t gfp_mask, * Swap entry may have been freed since our caller observed it. */ err = swapcache_prepare(entry); - if (err == -EEXIST) { /* seems racy */ + if (err == -EEXIST) { radix_tree_preload_end(); + /* + * We might race against get_swap_page() and stumble + * across a SWAP_HAS_CACHE swap_map entry whose page + * has not been brought into the swapcache yet, while + * the other end is scheduled away waiting on discard + * I/O completion at scan_swap_map(). + * + * In order to avoid turning this transitory state + * into a permanent loop around this -EEXIST case + * if !CONFIG_PREEMPT and the I/O completion happens + * to be waiting on the CPU waitqueue where we are now + * busy looping, we just conditionally invoke the + * scheduler here, if there are some more important + * tasks to run. + */ + cond_resched(); continue; } if (err) { /* swp entry is obsolete ? */ diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index cf4a49c5623..e22b8ada799 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c @@ -86,13 +86,6 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head) grp = &vlan_info->grp; - /* Take it out of our own structures, but be sure to interlock with - * HW accelerating devices or SW vlan input packet processing if - * VLAN is not 0 (leave it there for 802.1p). - */ - if (vlan_id) - vlan_vid_del(real_dev, vlan_id); - grp->nr_vlan_devs--; if (vlan->flags & VLAN_FLAG_GVRP) @@ -108,6 +101,13 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head) if (grp->nr_vlan_devs == 0) vlan_gvrp_uninit_applicant(real_dev); + /* Take it out of our own structures, but be sure to interlock with + * HW accelerating devices or SW vlan input packet processing if + * VLAN is not 0 (leave it there for 802.1p). + */ + if (vlan_id) + vlan_vid_del(real_dev, vlan_id); + /* Get rid of the vlan's reference to real_dev */ dev_put(real_dev); } diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 9757c193c86..8f453927cc5 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -73,6 +73,8 @@ vlan_dev_get_egress_qos_mask(struct net_device *dev, struct sk_buff *skb) { struct vlan_priority_tci_mapping *mp; + smp_rmb(); /* coupled with smp_wmb() in vlan_dev_set_egress_priority() */ + mp = vlan_dev_priv(dev)->egress_priority_map[(skb->priority & 0xF)]; while (mp) { if (mp->priority == skb->priority) { @@ -235,6 +237,11 @@ int vlan_dev_set_egress_priority(const struct net_device *dev, np->next = mp; np->priority = skb_prio; np->vlan_qos = vlan_qos; + /* Before inserting this element in hash table, make sure all its fields + * are committed to memory. + * coupled with smp_rmb() in vlan_dev_get_egress_qos_mask() + */ + smp_wmb(); vlan->egress_priority_map[skb_prio & 0xF] = np; if (vlan_qos) vlan->nr_egress_mappings++; @@ -598,7 +605,7 @@ static netdev_features_t vlan_dev_fix_features(struct net_device *dev, netdev_features_t features) { struct net_device *real_dev = vlan_dev_priv(dev)->real_dev; - u32 old_features = features; + netdev_features_t old_features = features; features &= real_dev->vlan_features; features |= NETIF_F_RXCSUM; diff --git a/net/9p/trans_common.c b/net/9p/trans_common.c index de8df957867..2ee3879161b 100644 --- a/net/9p/trans_common.c +++ b/net/9p/trans_common.c @@ -24,11 +24,11 @@ */ void p9_release_pages(struct page **pages, int nr_pages) { - int i = 0; - while (pages[i] && nr_pages--) { - put_page(pages[i]); - i++; - } + int i; + + for (i = 0; i < nr_pages; i++) + if (pages[i]) + put_page(pages[i]); } EXPORT_SYMBOL(p9_release_pages); diff --git a/net/atm/common.c b/net/atm/common.c index 0c0ad930a63..f0a9b7eb373 100644 --- a/net/atm/common.c +++ b/net/atm/common.c @@ -520,6 +520,8 @@ int vcc_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, struct sk_buff *skb; int copied, error = -EINVAL; + msg->msg_namelen = 0; + if (sock->state != SS_CONNECTED) return -ENOTCONN; diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index 9d9a6a3edbd..68b39927ecd 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c @@ -1646,6 +1646,7 @@ static int ax25_recvmsg(struct kiocb *iocb, struct socket *sock, ax25_address src; const unsigned char *mac = skb_mac_header(skb); + memset(sax, 0, sizeof(struct full_sockaddr_ax25)); ax25_addr_parse(mac + 1, skb->data - mac - 1, &src, NULL, &digi, NULL, NULL); sax->sax25_family = AF_AX25; diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index 219df5ca811..0d16fddee38 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c @@ -283,6 +283,8 @@ int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock, if (flags & (MSG_OOB)) return -EOPNOTSUPP; + msg->msg_namelen = 0; + skb = skb_recv_datagram(sk, flags, noblock, &err); if (!skb) { if (sk->sk_shutdown & RCV_SHUTDOWN) @@ -290,8 +292,6 @@ int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock, return err; } - msg->msg_namelen = 0; - copied = skb->len; if (len < copied) { msg->msg_flags |= MSG_TRUNC; diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index 2578f916d4b..40d3ea37b96 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c @@ -625,6 +625,7 @@ static int rfcomm_sock_recvmsg(struct kiocb *iocb, struct socket *sock, if (test_and_clear_bit(RFCOMM_DEFER_SETUP, &d->flags)) { rfcomm_dlc_accept(d); + msg->msg_namelen = 0; return 0; } diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 3170190f83c..ba178d6402b 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -405,6 +405,7 @@ static void __sco_sock_close(struct sock *sk) sco_chan_del(sk, ECONNRESET); break; + case BT_CONNECT2: case BT_CONNECT: case BT_DISCONN: sco_chan_del(sk, ECONNRESET); diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 27ca25ed702..9069071b68b 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -467,8 +467,9 @@ static struct sk_buff *br_ip6_multicast_alloc_query(struct net_bridge *br, skb_set_transport_header(skb, skb->len); mldq = (struct mld_msg *) icmp6_hdr(skb); - interval = ipv6_addr_any(group) ? br->multicast_last_member_interval : - br->multicast_query_response_interval; + interval = ipv6_addr_any(group) ? + br->multicast_query_response_interval : + br->multicast_last_member_interval; mldq->mld_type = ICMPV6_MGM_QUERY; mldq->mld_code = 0; diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index d7f49b63ab0..e54ef82fdad 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c @@ -254,6 +254,9 @@ static int br_parse_ip_options(struct sk_buff *skb) struct net_device *dev = skb->dev; u32 len; + if (!pskb_may_pull(skb, sizeof(struct iphdr))) + goto inhdr_error; + iph = ip_hdr(skb); opt = &(IPCB(skb)->opt); diff --git a/net/bridge/br_stp_bpdu.c b/net/bridge/br_stp_bpdu.c index e16aade51ae..718cbe8ad42 100644 --- a/net/bridge/br_stp_bpdu.c +++ b/net/bridge/br_stp_bpdu.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -40,6 +41,7 @@ static void br_send_bpdu(struct net_bridge_port *p, skb->dev = p->dev; skb->protocol = htons(ETH_P_802_2); + skb->priority = TC_PRIO_CONTROL; skb_reserve(skb, LLC_RESERVE); memcpy(__skb_put(skb, length), data, length); diff --git a/net/bridge/br_stp_timer.c b/net/bridge/br_stp_timer.c index 58de2a0f997..c83ee7915fb 100644 --- a/net/bridge/br_stp_timer.c +++ b/net/bridge/br_stp_timer.c @@ -107,7 +107,7 @@ static void br_tcn_timer_expired(unsigned long arg) br_debug(br, "tcn timer expired\n"); spin_lock(&br->lock); - if (br->dev->flags & IFF_UP) { + if (!br_is_root_bridge(br) && (br->dev->flags & IFF_UP)) { br_transmit_tcn(br); mod_timer(&br->tcn_timer,jiffies + br->bridge_hello_time); diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c index 5016fa57b62..24a68861881 100644 --- a/net/caif/caif_socket.c +++ b/net/caif/caif_socket.c @@ -287,6 +287,8 @@ static int caif_seqpkt_recvmsg(struct kiocb *iocb, struct socket *sock, if (m->msg_flags&MSG_OOB) goto read_error; + m->msg_namelen = 0; + skb = skb_recv_datagram(sk, flags, 0 , &ret); if (!skb) goto read_error; diff --git a/net/can/gw.c b/net/can/gw.c index 3d79b127881..f78f8985e08 100644 --- a/net/can/gw.c +++ b/net/can/gw.c @@ -436,7 +436,7 @@ static int cgw_notifier(struct notifier_block *nb, if (gwj->src.dev == dev || gwj->dst.dev == dev) { hlist_del(&gwj->list); cgw_unregister_filter(gwj); - kfree(gwj); + kmem_cache_free(cgw_cache, gwj); } } } @@ -850,7 +850,7 @@ static void cgw_remove_all_jobs(void) hlist_for_each_entry_safe(gwj, n, nx, &cgw_list, list) { hlist_del(&gwj->list); cgw_unregister_filter(gwj); - kfree(gwj); + kmem_cache_free(cgw_cache, gwj); } } @@ -903,7 +903,7 @@ static int cgw_remove_job(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) hlist_del(&gwj->list); cgw_unregister_filter(gwj); - kfree(gwj); + kmem_cache_free(cgw_cache, gwj); err = 0; break; } diff --git a/net/ceph/auth.c b/net/ceph/auth.c index b4bf4ac090f..6b923bcaa2a 100644 --- a/net/ceph/auth.c +++ b/net/ceph/auth.c @@ -47,6 +47,7 @@ struct ceph_auth_client *ceph_auth_init(const char *name, const struct ceph_cryp if (!ac) goto out; + mutex_init(&ac->mutex); ac->negotiating = true; if (name) ac->name = name; @@ -73,10 +74,12 @@ void ceph_auth_destroy(struct ceph_auth_client *ac) */ void ceph_auth_reset(struct ceph_auth_client *ac) { + mutex_lock(&ac->mutex); dout("auth_reset %p\n", ac); if (ac->ops && !ac->negotiating) ac->ops->reset(ac); ac->negotiating = true; + mutex_unlock(&ac->mutex); } int ceph_entity_name_encode(const char *name, void **p, void *end) @@ -102,6 +105,7 @@ int ceph_auth_build_hello(struct ceph_auth_client *ac, void *buf, size_t len) int i, num; int ret; + mutex_lock(&ac->mutex); dout("auth_build_hello\n"); monhdr->have_version = 0; monhdr->session_mon = cpu_to_le16(-1); @@ -122,15 +126,19 @@ int ceph_auth_build_hello(struct ceph_auth_client *ac, void *buf, size_t len) ret = ceph_entity_name_encode(ac->name, &p, end); if (ret < 0) - return ret; + goto out; ceph_decode_need(&p, end, sizeof(u64), bad); ceph_encode_64(&p, ac->global_id); ceph_encode_32(&lenp, p - lenp - sizeof(u32)); - return p - buf; + ret = p - buf; +out: + mutex_unlock(&ac->mutex); + return ret; bad: - return -ERANGE; + ret = -ERANGE; + goto out; } static int ceph_build_auth_request(struct ceph_auth_client *ac, @@ -151,11 +159,13 @@ static int ceph_build_auth_request(struct ceph_auth_client *ac, if (ret < 0) { pr_err("error %d building auth method %s request\n", ret, ac->ops->name); - return ret; + goto out; } dout(" built request %d bytes\n", ret); ceph_encode_32(&p, ret); - return p + ret - msg_buf; + ret = p + ret - msg_buf; +out: + return ret; } /* @@ -176,6 +186,7 @@ int ceph_handle_auth_reply(struct ceph_auth_client *ac, int result_msg_len; int ret = -EINVAL; + mutex_lock(&ac->mutex); dout("handle_auth_reply %p %p\n", p, end); ceph_decode_need(&p, end, sizeof(u32) * 3 + sizeof(u64), bad); protocol = ceph_decode_32(&p); @@ -227,33 +238,103 @@ int ceph_handle_auth_reply(struct ceph_auth_client *ac, ret = ac->ops->handle_reply(ac, result, payload, payload_end); if (ret == -EAGAIN) { - return ceph_build_auth_request(ac, reply_buf, reply_len); + ret = ceph_build_auth_request(ac, reply_buf, reply_len); } else if (ret) { pr_err("auth method '%s' error %d\n", ac->ops->name, ret); - return ret; } - return 0; -bad: - pr_err("failed to decode auth msg\n"); out: + mutex_unlock(&ac->mutex); return ret; + +bad: + pr_err("failed to decode auth msg\n"); + ret = -EINVAL; + goto out; } int ceph_build_auth(struct ceph_auth_client *ac, void *msg_buf, size_t msg_len) { + int ret = 0; + + mutex_lock(&ac->mutex); if (!ac->protocol) - return ceph_auth_build_hello(ac, msg_buf, msg_len); - BUG_ON(!ac->ops); - if (ac->ops->should_authenticate(ac)) - return ceph_build_auth_request(ac, msg_buf, msg_len); - return 0; + ret = ceph_auth_build_hello(ac, msg_buf, msg_len); + else if (ac->ops->should_authenticate(ac)) + ret = ceph_build_auth_request(ac, msg_buf, msg_len); + mutex_unlock(&ac->mutex); + return ret; } int ceph_auth_is_authenticated(struct ceph_auth_client *ac) { - if (!ac->ops) - return 0; - return ac->ops->is_authenticated(ac); + int ret = 0; + + mutex_lock(&ac->mutex); + if (ac->ops) + ret = ac->ops->is_authenticated(ac); + mutex_unlock(&ac->mutex); + return ret; +} +EXPORT_SYMBOL(ceph_auth_is_authenticated); + +int ceph_auth_create_authorizer(struct ceph_auth_client *ac, + int peer_type, + struct ceph_auth_handshake *auth) +{ + int ret = 0; + + mutex_lock(&ac->mutex); + if (ac->ops && ac->ops->create_authorizer) + ret = ac->ops->create_authorizer(ac, peer_type, auth); + mutex_unlock(&ac->mutex); + return ret; +} +EXPORT_SYMBOL(ceph_auth_create_authorizer); + +void ceph_auth_destroy_authorizer(struct ceph_auth_client *ac, + struct ceph_authorizer *a) +{ + mutex_lock(&ac->mutex); + if (ac->ops && ac->ops->destroy_authorizer) + ac->ops->destroy_authorizer(ac, a); + mutex_unlock(&ac->mutex); +} +EXPORT_SYMBOL(ceph_auth_destroy_authorizer); + +int ceph_auth_update_authorizer(struct ceph_auth_client *ac, + int peer_type, + struct ceph_auth_handshake *a) +{ + int ret = 0; + + mutex_lock(&ac->mutex); + if (ac->ops && ac->ops->update_authorizer) + ret = ac->ops->update_authorizer(ac, peer_type, a); + mutex_unlock(&ac->mutex); + return ret; +} +EXPORT_SYMBOL(ceph_auth_update_authorizer); + +int ceph_auth_verify_authorizer_reply(struct ceph_auth_client *ac, + struct ceph_authorizer *a, size_t len) +{ + int ret = 0; + + mutex_lock(&ac->mutex); + if (ac->ops && ac->ops->verify_authorizer_reply) + ret = ac->ops->verify_authorizer_reply(ac, a, len); + mutex_unlock(&ac->mutex); + return ret; +} +EXPORT_SYMBOL(ceph_auth_verify_authorizer_reply); + +void ceph_auth_invalidate_authorizer(struct ceph_auth_client *ac, int peer_type) +{ + mutex_lock(&ac->mutex); + if (ac->ops && ac->ops->invalidate_authorizer) + ac->ops->invalidate_authorizer(ac, peer_type); + mutex_unlock(&ac->mutex); } +EXPORT_SYMBOL(ceph_auth_invalidate_authorizer); diff --git a/net/ceph/auth_none.c b/net/ceph/auth_none.c index 925ca583c09..8c93fa8d81b 100644 --- a/net/ceph/auth_none.c +++ b/net/ceph/auth_none.c @@ -39,6 +39,11 @@ static int should_authenticate(struct ceph_auth_client *ac) return xi->starting; } +static int build_request(struct ceph_auth_client *ac, void *buf, void *end) +{ + return 0; +} + /* * the generic auth code decode the global_id, and we carry no actual * authenticate state, so nothing happens here. @@ -106,6 +111,7 @@ static const struct ceph_auth_client_ops ceph_auth_none_ops = { .destroy = destroy, .is_authenticated = is_authenticated, .should_authenticate = should_authenticate, + .build_request = build_request, .handle_reply = handle_reply, .create_authorizer = ceph_auth_none_create_authorizer, .destroy_authorizer = ceph_auth_none_destroy_authorizer, diff --git a/net/ceph/auth_x.c b/net/ceph/auth_x.c index a16bf14eb02..96238ba95f2 100644 --- a/net/ceph/auth_x.c +++ b/net/ceph/auth_x.c @@ -298,6 +298,7 @@ static int ceph_x_build_authorizer(struct ceph_auth_client *ac, return -ENOMEM; } au->service = th->service; + au->secret_id = th->secret_id; msg_a = au->buf->vec.iov_base; msg_a->struct_v = 1; @@ -555,6 +556,26 @@ static int ceph_x_create_authorizer( return 0; } +static int ceph_x_update_authorizer( + struct ceph_auth_client *ac, int peer_type, + struct ceph_auth_handshake *auth) +{ + struct ceph_x_authorizer *au; + struct ceph_x_ticket_handler *th; + + th = get_ticket_handler(ac, peer_type); + if (IS_ERR(th)) + return PTR_ERR(th); + + au = (struct ceph_x_authorizer *)auth->authorizer; + if (au->secret_id < th->secret_id) { + dout("ceph_x_update_authorizer service %u secret %llu < %llu\n", + au->service, au->secret_id, th->secret_id); + return ceph_x_build_authorizer(ac, th, au); + } + return 0; +} + static int ceph_x_verify_authorizer_reply(struct ceph_auth_client *ac, struct ceph_authorizer *a, size_t len) { @@ -630,7 +651,7 @@ static void ceph_x_invalidate_authorizer(struct ceph_auth_client *ac, th = get_ticket_handler(ac, peer_type); if (!IS_ERR(th)) - remove_ticket_handler(ac, th); + memset(&th->validity, 0, sizeof(th->validity)); } @@ -641,6 +662,7 @@ static const struct ceph_auth_client_ops ceph_x_ops = { .build_request = ceph_x_build_request, .handle_reply = ceph_x_handle_reply, .create_authorizer = ceph_x_create_authorizer, + .update_authorizer = ceph_x_update_authorizer, .verify_authorizer_reply = ceph_x_verify_authorizer_reply, .destroy_authorizer = ceph_x_destroy_authorizer, .invalidate_authorizer = ceph_x_invalidate_authorizer, diff --git a/net/ceph/auth_x.h b/net/ceph/auth_x.h index e02da7a5c5a..5c2ad4e12c5 100644 --- a/net/ceph/auth_x.h +++ b/net/ceph/auth_x.h @@ -29,6 +29,7 @@ struct ceph_x_authorizer { struct ceph_buffer *buf; unsigned service; u64 nonce; + u64 secret_id; char reply_buf[128]; /* big enough for encrypted blob */ }; diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index ba1037ceb49..7f703ae081c 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -1542,7 +1542,6 @@ static int process_connect(struct ceph_connection *con) con->error_msg = "connect authorization failure"; return -1; } - con->auth_retry = 1; con_out_kvec_reset(con); ret = prepare_write_connect(con); if (ret < 0) @@ -1627,7 +1626,7 @@ static int process_connect(struct ceph_connection *con) WARN_ON(con->state != CON_STATE_NEGOTIATING); con->state = CON_STATE_OPEN; - + con->auth_retry = 0; /* we authenticated; clear flag */ con->peer_global_seq = le32_to_cpu(con->in_reply.global_seq); con->connect_seq++; con->peer_features = server_feat; diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c index 89a6409b4e1..6765da36f78 100644 --- a/net/ceph/mon_client.c +++ b/net/ceph/mon_client.c @@ -737,7 +737,7 @@ static void delayed_work(struct work_struct *work) __validate_auth(monc); - if (monc->auth->ops->is_authenticated(monc->auth)) + if (ceph_auth_is_authenticated(monc->auth)) __send_subscribe(monc); } __schedule_delayed(monc); @@ -893,8 +893,7 @@ static void handle_auth_reply(struct ceph_mon_client *monc, mutex_lock(&monc->mutex); had_debugfs_info = have_debugfs_info(monc); - if (monc->auth->ops) - was_auth = monc->auth->ops->is_authenticated(monc->auth); + was_auth = ceph_auth_is_authenticated(monc->auth); monc->pending_auth = 0; ret = ceph_handle_auth_reply(monc->auth, msg->front.iov_base, msg->front.iov_len, @@ -905,7 +904,7 @@ static void handle_auth_reply(struct ceph_mon_client *monc, wake_up_all(&monc->client->auth_wq); } else if (ret > 0) { __send_prepared_auth_request(monc, ret); - } else if (!was_auth && monc->auth->ops->is_authenticated(monc->auth)) { + } else if (!was_auth && ceph_auth_is_authenticated(monc->auth)) { dout("authenticated, starting session\n"); monc->client->msgr.inst.name.type = CEPH_ENTITY_TYPE_CLIENT; diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index b16dfa25e75..8e3aa4dc5be 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -671,8 +671,7 @@ static void put_osd(struct ceph_osd *osd) if (atomic_dec_and_test(&osd->o_ref) && osd->o_auth.authorizer) { struct ceph_auth_client *ac = osd->o_osdc->client->monc.auth; - if (ac->ops && ac->ops->destroy_authorizer) - ac->ops->destroy_authorizer(ac, osd->o_auth.authorizer); + ceph_auth_destroy_authorizer(ac, osd->o_auth.authorizer); kfree(osd); } } @@ -1337,13 +1336,13 @@ static void kick_requests(struct ceph_osd_client *osdc, int force_resend) __register_request(osdc, req); __unregister_linger_request(osdc, req); } + reset_changed_osds(osdc); mutex_unlock(&osdc->request_mutex); if (needmap) { dout("%d requests for down osds, need new map\n", needmap); ceph_monc_request_next_osdmap(&osdc->client->monc); } - reset_changed_osds(osdc); } @@ -2127,13 +2126,17 @@ static struct ceph_auth_handshake *get_authorizer(struct ceph_connection *con, struct ceph_auth_handshake *auth = &o->o_auth; if (force_new && auth->authorizer) { - if (ac->ops && ac->ops->destroy_authorizer) - ac->ops->destroy_authorizer(ac, auth->authorizer); + ceph_auth_destroy_authorizer(ac, auth->authorizer); auth->authorizer = NULL; } - if (!auth->authorizer && ac->ops && ac->ops->create_authorizer) { - int ret = ac->ops->create_authorizer(ac, CEPH_ENTITY_TYPE_OSD, - auth); + if (!auth->authorizer) { + int ret = ceph_auth_create_authorizer(ac, CEPH_ENTITY_TYPE_OSD, + auth); + if (ret) + return ERR_PTR(ret); + } else { + int ret = ceph_auth_update_authorizer(ac, CEPH_ENTITY_TYPE_OSD, + auth); if (ret) return ERR_PTR(ret); } @@ -2149,11 +2152,7 @@ static int verify_authorizer_reply(struct ceph_connection *con, int len) struct ceph_osd_client *osdc = o->o_osdc; struct ceph_auth_client *ac = osdc->client->monc.auth; - /* - * XXX If ac->ops or ac->ops->verify_authorizer_reply is null, - * XXX which do we do: succeed or fail? - */ - return ac->ops->verify_authorizer_reply(ac, o->o_auth.authorizer, len); + return ceph_auth_verify_authorizer_reply(ac, o->o_auth.authorizer, len); } static int invalidate_authorizer(struct ceph_connection *con) @@ -2162,9 +2161,7 @@ static int invalidate_authorizer(struct ceph_connection *con) struct ceph_osd_client *osdc = o->o_osdc; struct ceph_auth_client *ac = osdc->client->monc.auth; - if (ac->ops && ac->ops->invalidate_authorizer) - ac->ops->invalidate_authorizer(ac, CEPH_ENTITY_TYPE_OSD); - + ceph_auth_invalidate_authorizer(ac, CEPH_ENTITY_TYPE_OSD); return ceph_monc_validate_auth(&osdc->client->monc); } diff --git a/net/compat.c b/net/compat.c index ae6d67ad03b..014e1c78ecc 100644 --- a/net/compat.c +++ b/net/compat.c @@ -743,19 +743,25 @@ static unsigned char nas[21] = { asmlinkage long compat_sys_sendmsg(int fd, struct compat_msghdr __user *msg, unsigned flags) { - return sys_sendmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT); + if (flags & MSG_CMSG_COMPAT) + return -EINVAL; + return __sys_sendmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT); } asmlinkage long compat_sys_sendmmsg(int fd, struct compat_mmsghdr __user *mmsg, unsigned vlen, unsigned int flags) { + if (flags & MSG_CMSG_COMPAT) + return -EINVAL; return __sys_sendmmsg(fd, (struct mmsghdr __user *)mmsg, vlen, flags | MSG_CMSG_COMPAT); } asmlinkage long compat_sys_recvmsg(int fd, struct compat_msghdr __user *msg, unsigned int flags) { - return sys_recvmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT); + if (flags & MSG_CMSG_COMPAT) + return -EINVAL; + return __sys_recvmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT); } asmlinkage long compat_sys_recv(int fd, void __user *buf, size_t len, unsigned flags) @@ -777,6 +783,9 @@ asmlinkage long compat_sys_recvmmsg(int fd, struct compat_mmsghdr __user *mmsg, int datagrams; struct timespec ktspec; + if (flags & MSG_CMSG_COMPAT) + return -EINVAL; + if (COMPAT_USE_64BIT_TIME) return __sys_recvmmsg(fd, (struct mmsghdr __user *)mmsg, vlen, flags | MSG_CMSG_COMPAT, diff --git a/net/core/datagram.c b/net/core/datagram.c index e4fbfd6e2bd..da7e0c867cc 100644 --- a/net/core/datagram.c +++ b/net/core/datagram.c @@ -187,7 +187,7 @@ struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned flags, skb_queue_walk(queue, skb) { *peeked = skb->peeked; if (flags & MSG_PEEK) { - if (*off >= skb->len) { + if (*off >= skb->len && skb->len) { *off -= skb->len; continue; } diff --git a/net/core/dev.c b/net/core/dev.c index eb858dc6ab8..7db83d64e4f 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1482,7 +1482,6 @@ void net_enable_timestamp(void) return; } #endif - WARN_ON(in_interrupt()); static_key_slow_inc(&netstamp_needed); } EXPORT_SYMBOL(net_enable_timestamp); @@ -1629,6 +1628,7 @@ int dev_forward_skb(struct net_device *dev, struct sk_buff *skb) skb->mark = 0; secpath_reset(skb); nf_reset(skb); + nf_reset_trace(skb); return netif_rx(skb); } EXPORT_SYMBOL_GPL(dev_forward_skb); @@ -1895,6 +1895,9 @@ static void skb_warn_bad_offload(const struct sk_buff *skb) struct net_device *dev = skb->dev; const char *driver = ""; + if (!net_ratelimit()) + return; + if (dev && dev->dev.parent) driver = dev_driver_string(dev->dev.parent); @@ -2167,7 +2170,7 @@ EXPORT_SYMBOL(netif_skb_features); * support DMA from it. */ static inline int skb_needs_linearize(struct sk_buff *skb, - int features) + netdev_features_t features) { return skb_is_nonlinear(skb) && ((skb_has_frag_list(skb) && @@ -3125,6 +3128,7 @@ int netdev_rx_handler_register(struct net_device *dev, if (dev->rx_handler) return -EBUSY; + /* Note: rx_handler_data must be set before rx_handler */ rcu_assign_pointer(dev->rx_handler_data, rx_handler_data); rcu_assign_pointer(dev->rx_handler, rx_handler); @@ -3145,6 +3149,11 @@ void netdev_rx_handler_unregister(struct net_device *dev) ASSERT_RTNL(); RCU_INIT_POINTER(dev->rx_handler, NULL); + /* a reader seeing a non NULL rx_handler in a rcu_read_lock() + * section has a guarantee to see a non NULL rx_handler_data + * as well. + */ + synchronize_net(); RCU_INIT_POINTER(dev->rx_handler_data, NULL); } EXPORT_SYMBOL_GPL(netdev_rx_handler_unregister); @@ -3230,6 +3239,7 @@ static int __netif_receive_skb(struct sk_buff *skb) } switch (rx_handler(&skb)) { case RX_HANDLER_CONSUMED: + ret = NET_RX_SUCCESS; goto out; case RX_HANDLER_ANOTHER: goto another_round; diff --git a/net/core/dev_addr_lists.c b/net/core/dev_addr_lists.c index 76f6d0b02f2..0346e590190 100644 --- a/net/core/dev_addr_lists.c +++ b/net/core/dev_addr_lists.c @@ -57,7 +57,7 @@ static int __hw_addr_add_ex(struct netdev_hw_addr_list *list, ha->type = addr_type; ha->refcount = 1; ha->global_use = global; - ha->synced = false; + ha->synced = 0; list_add_tail_rcu(&ha->list, &list->list); list->count++; return 0; @@ -155,7 +155,7 @@ int __hw_addr_sync(struct netdev_hw_addr_list *to_list, addr_len, ha->type); if (err) break; - ha->synced = true; + ha->synced++; ha->refcount++; } else if (ha->refcount == 1) { __hw_addr_del(to_list, ha->addr, addr_len, ha->type); @@ -176,7 +176,7 @@ void __hw_addr_unsync(struct netdev_hw_addr_list *to_list, if (ha->synced) { __hw_addr_del(to_list, ha->addr, addr_len, ha->type); - ha->synced = false; + ha->synced--; __hw_addr_del(from_list, ha->addr, addr_len, ha->type); } diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 6d6d7d25caa..7becb3f9ef6 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -1286,7 +1286,7 @@ int dev_ethtool(struct net *net, struct ifreq *ifr) void __user *useraddr = ifr->ifr_data; u32 ethcmd; int rc; - u32 old_features; + netdev_features_t old_features; if (!dev || !netif_device_present(dev)) return -ENODEV; diff --git a/net/core/neighbour.c b/net/core/neighbour.c index ac88107d1bc..69b7ca35c46 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -237,7 +237,7 @@ static void neigh_flush_dev(struct neigh_table *tbl, struct net_device *dev) we must kill timers etc. and move it to safe state. */ - skb_queue_purge(&n->arp_queue); + __skb_queue_purge(&n->arp_queue); n->arp_queue_len_bytes = 0; n->output = neigh_blackhole; if (n->nud_state & NUD_VALID) @@ -300,7 +300,7 @@ static struct neighbour *neigh_alloc(struct neigh_table *tbl, struct net_device if (!n) goto out_entries; - skb_queue_head_init(&n->arp_queue); + __skb_queue_head_init(&n->arp_queue); rwlock_init(&n->lock); seqlock_init(&n->ha_lock); n->updated = n->used = now; @@ -721,7 +721,9 @@ void neigh_destroy(struct neighbour *neigh) if (neigh_del_timer(neigh)) printk(KERN_WARNING "Impossible event.\n"); - skb_queue_purge(&neigh->arp_queue); + write_lock_bh(&neigh->lock); + __skb_queue_purge(&neigh->arp_queue); + write_unlock_bh(&neigh->lock); neigh->arp_queue_len_bytes = 0; if (dev->netdev_ops->ndo_neigh_destroy) @@ -867,7 +869,7 @@ static void neigh_invalidate(struct neighbour *neigh) neigh->ops->error_report(neigh, skb); write_lock(&neigh->lock); } - skb_queue_purge(&neigh->arp_queue); + __skb_queue_purge(&neigh->arp_queue); neigh->arp_queue_len_bytes = 0; } @@ -1206,7 +1208,7 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new, write_lock_bh(&neigh->lock); } - skb_queue_purge(&neigh->arp_queue); + __skb_queue_purge(&neigh->arp_queue); neigh->arp_queue_len_bytes = 0; } out: diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 8dae76f481e..114d8a9e857 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -1802,10 +1802,13 @@ static ssize_t pktgen_thread_write(struct file *file, return -EFAULT; i += len; mutex_lock(&pktgen_thread_lock); - pktgen_add_device(t, f); + ret = pktgen_add_device(t, f); mutex_unlock(&pktgen_thread_lock); - ret = count; - sprintf(pg_result, "OK: add_device=%s", f); + if (!ret) { + ret = count; + sprintf(pg_result, "OK: add_device=%s", f); + } else + sprintf(pg_result, "ERROR: can not add device %s", f); goto out; } diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 900fc6162c4..a1334275a7d 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -975,6 +975,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, * report anything. */ ivi.spoofchk = -1; + memset(ivi.mac, 0, sizeof(ivi.mac)); if (dev->netdev_ops->ndo_get_vf_config(dev, i, &ivi)) break; vf_mac.vf = @@ -1065,7 +1066,7 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) rcu_read_lock(); cb->seq = net->dev_base_seq; - if (nlmsg_parse(cb->nlh, sizeof(struct rtgenmsg), tb, IFLA_MAX, + if (nlmsg_parse(cb->nlh, sizeof(struct ifinfomsg), tb, IFLA_MAX, ifla_policy) >= 0) { if (tb[IFLA_EXT_MASK]) @@ -1909,7 +1910,7 @@ static u16 rtnl_calcit(struct sk_buff *skb, struct nlmsghdr *nlh) u32 ext_filter_mask = 0; u16 min_ifinfo_dump_size = 0; - if (nlmsg_parse(nlh, sizeof(struct rtgenmsg), tb, IFLA_MAX, + if (nlmsg_parse(nlh, sizeof(struct ifinfomsg), tb, IFLA_MAX, ifla_policy) >= 0) { if (tb[IFLA_EXT_MASK]) ext_filter_mask = nla_get_u32(tb[IFLA_EXT_MASK]); @@ -2049,7 +2050,7 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) struct rtattr *attr = (void *)nlh + NLMSG_ALIGN(min_len); while (RTA_OK(attr, attrlen)) { - unsigned flavor = attr->rta_type; + unsigned int flavor = attr->rta_type & NLA_TYPE_MASK; if (flavor) { if (flavor > rta_max[sz_idx]) return -EINVAL; diff --git a/net/core/sock.c b/net/core/sock.c index 4b469e36792..561eb57f590 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -815,15 +815,20 @@ EXPORT_SYMBOL(sock_setsockopt); void cred_to_ucred(struct pid *pid, const struct cred *cred, - struct ucred *ucred) + struct ucred *ucred, bool use_effective) { ucred->pid = pid_vnr(pid); ucred->uid = ucred->gid = -1; if (cred) { struct user_namespace *current_ns = current_user_ns(); - ucred->uid = user_ns_map_uid(current_ns, cred, cred->euid); - ucred->gid = user_ns_map_gid(current_ns, cred, cred->egid); + if (use_effective) { + ucred->uid = user_ns_map_uid(current_ns, cred, cred->euid); + ucred->gid = user_ns_map_gid(current_ns, cred, cred->egid); + } else { + ucred->uid = user_ns_map_uid(current_ns, cred, cred->uid); + ucred->gid = user_ns_map_gid(current_ns, cred, cred->gid); + } } } EXPORT_SYMBOL_GPL(cred_to_ucred); @@ -984,7 +989,8 @@ int sock_getsockopt(struct socket *sock, int level, int optname, struct ucred peercred; if (len > sizeof(peercred)) len = sizeof(peercred); - cred_to_ucred(sk->sk_peer_pid, sk->sk_peer_cred, &peercred); + cred_to_ucred(sk->sk_peer_pid, sk->sk_peer_cred, + &peercred, true); if (copy_to_user(optval, &peercred, len)) return -EFAULT; goto lenout; @@ -1087,18 +1093,6 @@ static void sock_copy(struct sock *nsk, const struct sock *osk) #endif } -/* - * caches using SLAB_DESTROY_BY_RCU should let .next pointer from nulls nodes - * un-modified. Special care is taken when initializing object to zero. - */ -static inline void sk_prot_clear_nulls(struct sock *sk, int size) -{ - if (offsetof(struct sock, sk_node.next) != 0) - memset(sk, 0, offsetof(struct sock, sk_node.next)); - memset(&sk->sk_node.pprev, 0, - size - offsetof(struct sock, sk_node.pprev)); -} - void sk_prot_clear_portaddr_nulls(struct sock *sk, int size) { unsigned long nulls1, nulls2; diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c index d86053002c1..2f9517ddb60 100644 --- a/net/dcb/dcbnl.c +++ b/net/dcb/dcbnl.c @@ -336,6 +336,7 @@ static int dcbnl_getperm_hwaddr(struct net_device *netdev, struct nlattr **tb, dcb->dcb_family = AF_UNSPEC; dcb->cmd = DCB_CMD_GPERM_HWADDR; + memset(perm_addr, 0, sizeof(perm_addr)); netdev->dcbnl_ops->getpermhwaddr(netdev, perm_addr); ret = nla_put(dcbnl_skb, DCB_ATTR_PERM_HWADDR, sizeof(perm_addr), @@ -1238,6 +1239,7 @@ static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev) if (ops->ieee_getets) { struct ieee_ets ets; + memset(&ets, 0, sizeof(ets)); err = ops->ieee_getets(netdev, &ets); if (!err) NLA_PUT(skb, DCB_ATTR_IEEE_ETS, sizeof(ets), &ets); @@ -1245,6 +1247,7 @@ static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev) if (ops->ieee_getpfc) { struct ieee_pfc pfc; + memset(&pfc, 0, sizeof(pfc)); err = ops->ieee_getpfc(netdev, &pfc); if (!err) NLA_PUT(skb, DCB_ATTR_IEEE_PFC, sizeof(pfc), &pfc); @@ -1277,6 +1280,7 @@ static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev) /* get peer info if available */ if (ops->ieee_peer_getets) { struct ieee_ets ets; + memset(&ets, 0, sizeof(ets)); err = ops->ieee_peer_getets(netdev, &ets); if (!err) NLA_PUT(skb, DCB_ATTR_IEEE_PEER_ETS, sizeof(ets), &ets); @@ -1284,6 +1288,7 @@ static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev) if (ops->ieee_peer_getpfc) { struct ieee_pfc pfc; + memset(&pfc, 0, sizeof(pfc)); err = ops->ieee_peer_getpfc(netdev, &pfc); if (!err) NLA_PUT(skb, DCB_ATTR_IEEE_PEER_PFC, sizeof(pfc), &pfc); @@ -1463,6 +1468,7 @@ static int dcbnl_cee_fill(struct sk_buff *skb, struct net_device *netdev) /* peer info if available */ if (ops->cee_peer_getpg) { struct cee_pg pg; + memset(&pg, 0, sizeof(pg)); err = ops->cee_peer_getpg(netdev, &pg); if (!err) NLA_PUT(skb, DCB_ATTR_CEE_PEER_PG, sizeof(pg), &pg); @@ -1470,6 +1476,7 @@ static int dcbnl_cee_fill(struct sk_buff *skb, struct net_device *netdev) if (ops->cee_peer_getpfc) { struct cee_pfc pfc; + memset(&pfc, 0, sizeof(pfc)); err = ops->cee_peer_getpfc(netdev, &pfc); if (!err) NLA_PUT(skb, DCB_ATTR_CEE_PEER_PFC, sizeof(pfc), &pfc); diff --git a/net/ieee802154/6lowpan.h b/net/ieee802154/6lowpan.h index aeff3f31048..60b5ef5f64d 100644 --- a/net/ieee802154/6lowpan.h +++ b/net/ieee802154/6lowpan.h @@ -87,7 +87,7 @@ (memcmp(addr1, addr2, length >> 3) == 0) /* local link, i.e. FE80::/10 */ -#define is_addr_link_local(a) (((a)->s6_addr16[0]) == 0x80FE) +#define is_addr_link_local(a) (((a)->s6_addr16[0]) == htons(0xFE80)) /* * check whether we can compress the IID to 16 bits, diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c index cb982a61536..e814e2a9fa6 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c @@ -139,8 +139,6 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb) /* skb is pure payload to encrypt */ - err = -ENOMEM; - esp = x->data; aead = esp->aead; alen = crypto_aead_authsize(aead); @@ -176,8 +174,10 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb) } tmp = esp_alloc_tmp(aead, nfrags + sglists, seqhilen); - if (!tmp) + if (!tmp) { + err = -ENOMEM; goto error; + } seqhi = esp_tmp_seqhi(tmp); iv = esp_tmp_iv(aead, tmp, seqhilen); diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c index 5ff2a51b6d0..210b7102cc4 100644 --- a/net/ipv4/inet_fragment.c +++ b/net/ipv4/inet_fragment.c @@ -21,6 +21,7 @@ #include #include +#include #include static void inet_frag_secret_rebuild(unsigned long dummy) @@ -271,6 +272,7 @@ struct inet_frag_queue *inet_frag_find(struct netns_frags *nf, { struct inet_frag_queue *q; struct hlist_node *n; + int depth = 0; hlist_for_each_entry(q, n, &f->hash[hash], list) { if (q->net == nf && f->match(q, key)) { @@ -278,9 +280,25 @@ struct inet_frag_queue *inet_frag_find(struct netns_frags *nf, read_unlock(&f->lock); return q; } + depth++; } read_unlock(&f->lock); - return inet_frag_create(nf, f, key); + if (depth <= INETFRAGS_MAXDEPTH) + return inet_frag_create(nf, f, key); + else + return ERR_PTR(-ENOBUFS); } EXPORT_SYMBOL(inet_frag_find); + +void inet_frag_maybe_warn_overflow(struct inet_frag_queue *q, + const char *prefix) +{ + static const char msg[] = "inet_frag_find: Fragment hash bucket" + " list length grew over limit " __stringify(INETFRAGS_MAXDEPTH) + ". Dropping fragment.\n"; + + if (PTR_ERR(q) == -ENOBUFS) + LIMIT_NETDEBUG(KERN_WARNING "%s%s", prefix, msg); +} +EXPORT_SYMBOL(inet_frag_maybe_warn_overflow); diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index b7bf6e30adb..4a40457d8d1 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c @@ -251,8 +251,7 @@ static void ip_expire(unsigned long arg) if (!head->dev) goto out_rcu_unlock; - /* skb dst is stale, drop it, and perform route lookup again */ - skb_dst_drop(head); + /* skb has no dst, perform route lookup again */ iph = ip_hdr(head); err = ip_route_input_noref(head, iph->daddr, iph->saddr, iph->tos, head->dev); @@ -295,14 +294,11 @@ static inline struct ipq *ip_find(struct net *net, struct iphdr *iph, u32 user) hash = ipqhashfn(iph->id, iph->saddr, iph->daddr, iph->protocol); q = inet_frag_find(&net->ipv4.frags, &ip4_frags, &arg, hash); - if (q == NULL) - goto out_nomem; - + if (IS_ERR_OR_NULL(q)) { + inet_frag_maybe_warn_overflow(q, pr_fmt()); + return NULL; + } return container_of(q, struct ipq, q); - -out_nomem: - LIMIT_NETDEBUG(KERN_ERR pr_fmt("ip_frag_create: no memory left !\n")); - return NULL; } /* Is the fragment too far ahead to be part of ipq? */ @@ -520,8 +516,16 @@ static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb) qp->q.last_in |= INET_FRAG_FIRST_IN; if (qp->q.last_in == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) && - qp->q.meat == qp->q.len) - return ip_frag_reasm(qp, prev, dev); + qp->q.meat == qp->q.len) { + unsigned long orefdst = skb->_skb_refdst; + + skb->_skb_refdst = 0UL; + err = ip_frag_reasm(qp, prev, dev); + skb->_skb_refdst = orefdst; + return err; + } + + skb_dst_drop(skb); write_lock(&ip4_frags.lock); list_move_tail(&qp->q.lru_list, &qp->q.net->lru_list); diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index b57532d4742..a16509cba75 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -722,6 +722,7 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev tiph = &tunnel->parms.iph; } + memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); if ((dst = tiph->daddr) == 0) { /* NBMA tunnel */ @@ -865,7 +866,6 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev skb_reset_transport_header(skb); skb_push(skb, gre_hlen); skb_reset_network_header(skb); - memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED | IPSKB_REROUTED); skb_dst_drop(skb); diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c index a0d0d9d9b87..b69a3700642 100644 --- a/net/ipv4/ip_options.c +++ b/net/ipv4/ip_options.c @@ -360,7 +360,6 @@ int ip_options_compile(struct net *net, } switch (optptr[3]&0xF) { case IPOPT_TS_TSONLY: - opt->ts = optptr - iph; if (skb) timeptr = &optptr[optptr[2]-1]; opt->ts_needtime = 1; @@ -371,7 +370,6 @@ int ip_options_compile(struct net *net, pp_ptr = optptr + 2; goto error; } - opt->ts = optptr - iph; if (rt) { memcpy(&optptr[optptr[2]-1], &rt->rt_spec_dst, 4); timeptr = &optptr[optptr[2]+3]; @@ -385,7 +383,6 @@ int ip_options_compile(struct net *net, pp_ptr = optptr + 2; goto error; } - opt->ts = optptr - iph; { __be32 addr; memcpy(&addr, &optptr[optptr[2]-1], 4); @@ -418,12 +415,12 @@ int ip_options_compile(struct net *net, pp_ptr = optptr + 3; goto error; } - opt->ts = optptr - iph; if (skb) { optptr[3] = (optptr[3]&0xF)|((overflow+1)<<4); opt->is_changed = 1; } } + opt->ts = optptr - iph; break; case IPOPT_RA: if (optlen < 4) { diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index 59ef40abf50..37482848700 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c @@ -589,7 +589,7 @@ static int do_ip_setsockopt(struct sock *sk, int level, case IP_TTL: if (optlen < 1) goto e_inval; - if (val != -1 && (val < 0 || val > 255)) + if (val != -1 && (val < 1 || val > 255)) goto e_inval; inet->uc_ttl = val; break; diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index ae1413e3f2f..d2f634880bd 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c @@ -448,6 +448,7 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) if (tos & 1) tos = old_iph->tos; + memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); if (!dst) { /* NBMA tunnel */ if ((rt = skb_rtable(skb)) == NULL) { @@ -530,7 +531,6 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) skb->transport_header = skb->network_header; skb_push(skb, sizeof(struct iphdr)); skb_reset_network_header(skb); - memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED | IPSKB_REROUTED); skb_dst_drop(skb); diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index a8d7ed06234..b4c71ed0fc7 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c @@ -459,8 +459,8 @@ void ping_err(struct sk_buff *skb, int offset, u32 info) int family; struct icmphdr *icmph; struct inet_sock *inet_sock; - int type; - int code; + int type = icmp_hdr(skb)->type; + int code = icmp_hdr(skb)->code; struct net *net = dev_net(skb->dev); struct sock *sk; int harderr; diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c index eab2a7fb15d..550aa2a9d32 100644 --- a/net/ipv4/syncookies.c +++ b/net/ipv4/syncookies.c @@ -347,8 +347,8 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, * hasn't changed since we received the original syn, but I see * no easy way to do this. */ - flowi4_init_output(&fl4, 0, sk->sk_mark, RT_CONN_FLAGS(sk), - RT_SCOPE_UNIVERSE, IPPROTO_TCP, + flowi4_init_output(&fl4, sk->sk_bound_dev_if, sk->sk_mark, + RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE, IPPROTO_TCP, inet_sk_flowi_flags(sk), (opt && opt->srr) ? opt->faddr : ireq->rmt_addr, ireq->loc_addr, th->source, th->dest); diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index bf7a604c695..086c97327b9 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -34,6 +34,8 @@ static int tcp_adv_win_scale_min = -31; static int tcp_adv_win_scale_max = 31; static int ip_ttl_min = 1; static int ip_ttl_max = 255; +static int tcp_syn_retries_min = 1; +static int tcp_syn_retries_max = MAX_TCP_SYNCNT; static int ip_ping_group_range_min[] = { 0, 0 }; static int ip_ping_group_range_max[] = { GID_T_MAX, GID_T_MAX }; @@ -276,7 +278,9 @@ static struct ctl_table ipv4_table[] = { .data = &sysctl_tcp_syn_retries, .maxlen = sizeof(int), .mode = 0644, - .proc_handler = proc_dointvec + .proc_handler = proc_dointvec_minmax, + .extra1 = &tcp_syn_retries_min, + .extra2 = &tcp_syn_retries_max }, { .procname = "tcp_synack_retries", diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 89264f8b959..2024cb85beb 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -708,7 +708,7 @@ struct sk_buff *sk_stream_alloc_skb(struct sock *sk, int size, gfp_t gfp) * Make sure that we have exactly size bytes * available to the caller, no more, no less. */ - skb->avail_size = size; + skb->reserved_tailroom = skb->end - skb->tail - size; return skb; } __kfree_skb(skb); @@ -3076,8 +3076,11 @@ int tcp_md5_hash_skb_data(struct tcp_md5sig_pool *hp, for (i = 0; i < shi->nr_frags; ++i) { const struct skb_frag_struct *f = &shi->frags[i]; - struct page *page = skb_frag_page(f); - sg_set_page(&sg, page, skb_frag_size(f), f->page_offset); + unsigned int offset = f->page_offset; + struct page *page = skb_frag_page(f) + (offset >> PAGE_SHIFT); + + sg_set_page(&sg, page, skb_frag_size(f), + offset_in_page(offset)); if (crypto_hash_update(desc, &sg, skb_frag_size(f))) return 1; } diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index c16ce557931..8b53df66155 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -116,6 +116,7 @@ int sysctl_tcp_abc __read_mostly; #define FLAG_DSACKING_ACK 0x800 /* SACK blocks contained D-SACK info */ #define FLAG_NONHEAD_RETRANS_ACKED 0x1000 /* Non-head rexmitted data was ACKed */ #define FLAG_SACK_RENEGING 0x2000 /* snd_una advanced to a sacked seq */ +#define FLAG_UPDATE_TS_RECENT 0x4000 /* tcp_replace_ts_recent() */ #define FLAG_ACKED (FLAG_DATA_ACKED|FLAG_SYN_ACKED) #define FLAG_NOT_DUP (FLAG_DATA|FLAG_WIN_UPDATE|FLAG_ACKED) @@ -2260,11 +2261,8 @@ void tcp_enter_loss(struct sock *sk, int how) if (tcp_is_reno(tp)) tcp_reset_reno_sack(tp); - if (!how) { - /* Push undo marker, if it was plain RTO and nothing - * was retransmitted. */ - tp->undo_marker = tp->snd_una; - } else { + tp->undo_marker = tp->snd_una; + if (how) { tp->sacked_out = 0; tp->fackets_out = 0; } @@ -3040,8 +3038,8 @@ static void tcp_update_cwnd_in_recovery(struct sock *sk, int newly_acked_sacked, * tcp_xmit_retransmit_queue(). */ static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked, - int prior_sacked, bool is_dupack, - int flag) + int prior_sacked, int prior_packets, + bool is_dupack, int flag) { struct inet_connection_sock *icsk = inet_csk(sk); struct tcp_sock *tp = tcp_sk(sk); @@ -3107,7 +3105,8 @@ static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked, tcp_add_reno_sack(sk); } else do_lost = tcp_try_undo_partial(sk, pkts_acked); - newly_acked_sacked = pkts_acked + tp->sacked_out - prior_sacked; + newly_acked_sacked = prior_packets - tp->packets_out + + tp->sacked_out - prior_sacked; break; case TCP_CA_Loss: if (flag & FLAG_DATA_ACKED) @@ -3129,7 +3128,8 @@ static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked, if (is_dupack) tcp_add_reno_sack(sk); } - newly_acked_sacked = pkts_acked + tp->sacked_out - prior_sacked; + newly_acked_sacked = prior_packets - tp->packets_out + + tp->sacked_out - prior_sacked; if (icsk->icsk_ca_state <= TCP_CA_Disorder) tcp_try_undo_dsack(sk); @@ -3639,6 +3639,11 @@ static int tcp_process_frto(struct sock *sk, int flag) } } else { if (!(flag & FLAG_DATA_ACKED) && (tp->frto_counter == 1)) { + if (!tcp_packets_in_flight(tp)) { + tcp_enter_frto_loss(sk, 2, flag); + return true; + } + /* Prevent sending of new data. */ tp->snd_cwnd = min(tp->snd_cwnd, tcp_packets_in_flight(tp)); @@ -3705,6 +3710,27 @@ static void tcp_send_challenge_ack(struct sock *sk) } } +static void tcp_store_ts_recent(struct tcp_sock *tp) +{ + tp->rx_opt.ts_recent = tp->rx_opt.rcv_tsval; + tp->rx_opt.ts_recent_stamp = get_seconds(); +} + +static void tcp_replace_ts_recent(struct tcp_sock *tp, u32 seq) +{ + if (tp->rx_opt.saw_tstamp && !after(seq, tp->rcv_wup)) { + /* PAWS bug workaround wrt. ACK frames, the PAWS discard + * extra check below makes sure this can only happen + * for pure ACK frames. -DaveM + * + * Not only, also it occurs for expired timestamps. + */ + + if (tcp_paws_check(&tp->rx_opt, 0)) + tcp_store_ts_recent(tp); + } +} + /* This routine deals with incoming acks, but not outgoing ones. */ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) { @@ -3716,9 +3742,10 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) bool is_dupack = false; u32 prior_in_flight; u32 prior_fackets; - int prior_packets; + int prior_packets = tp->packets_out; int prior_sacked = tp->sacked_out; int pkts_acked = 0; + int previous_packets_out = 0; int frto_cwnd = 0; /* If the ack is older than previous acks @@ -3754,6 +3781,12 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) prior_fackets = tp->fackets_out; prior_in_flight = tcp_packets_in_flight(tp); + /* ts_recent update must be made after we are sure that the packet + * is in window. + */ + if (flag & FLAG_UPDATE_TS_RECENT) + tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq); + if (!(flag & FLAG_SLOWPATH) && after(ack, prior_snd_una)) { /* Window is constant, pure forward advance. * No more checks are required. @@ -3789,14 +3822,14 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) sk->sk_err_soft = 0; icsk->icsk_probes_out = 0; tp->rcv_tstamp = tcp_time_stamp; - prior_packets = tp->packets_out; if (!prior_packets) goto no_queue; /* See if we can take anything off of the retransmit queue. */ + previous_packets_out = tp->packets_out; flag |= tcp_clean_rtx_queue(sk, prior_fackets, prior_snd_una); - pkts_acked = prior_packets - tp->packets_out; + pkts_acked = previous_packets_out - tp->packets_out; if (tp->frto_counter) frto_cwnd = tcp_process_frto(sk, flag); @@ -3811,7 +3844,7 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) tcp_cong_avoid(sk, ack, prior_in_flight); is_dupack = !(flag & (FLAG_SND_UNA_ADVANCED | FLAG_NOT_DUP)); tcp_fastretrans_alert(sk, pkts_acked, prior_sacked, - is_dupack, flag); + prior_packets, is_dupack, flag); } else { if ((flag & FLAG_DATA_ACKED) && !frto_cwnd) tcp_cong_avoid(sk, ack, prior_in_flight); @@ -3826,7 +3859,7 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) /* If data was DSACKed, see if we can undo a cwnd reduction. */ if (flag & FLAG_DSACKING_ACK) tcp_fastretrans_alert(sk, pkts_acked, prior_sacked, - is_dupack, flag); + prior_packets, is_dupack, flag); /* If this ack opens up a zero window, clear backoff. It was * being used to time the probes, and is probably far higher than * it needs to be for normal retransmission. @@ -3846,7 +3879,7 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) if (TCP_SKB_CB(skb)->sacked) { flag |= tcp_sacktag_write_queue(sk, skb, prior_snd_una); tcp_fastretrans_alert(sk, pkts_acked, prior_sacked, - is_dupack, flag); + prior_packets, is_dupack, flag); } SOCK_DEBUG(sk, "Ack %u before %u:%u\n", ack, tp->snd_una, tp->snd_nxt); @@ -4051,27 +4084,6 @@ const u8 *tcp_parse_md5sig_option(const struct tcphdr *th) EXPORT_SYMBOL(tcp_parse_md5sig_option); #endif -static inline void tcp_store_ts_recent(struct tcp_sock *tp) -{ - tp->rx_opt.ts_recent = tp->rx_opt.rcv_tsval; - tp->rx_opt.ts_recent_stamp = get_seconds(); -} - -static inline void tcp_replace_ts_recent(struct tcp_sock *tp, u32 seq) -{ - if (tp->rx_opt.saw_tstamp && !after(seq, tp->rcv_wup)) { - /* PAWS bug workaround wrt. ACK frames, the PAWS discard - * extra check below makes sure this can only happen - * for pure ACK frames. -DaveM - * - * Not only, also it occurs for expired timestamps. - */ - - if (tcp_paws_check(&tp->rx_opt, 0)) - tcp_store_ts_recent(tp); - } -} - /* Sorry, PAWS as specified is broken wrt. pure-ACKs -DaveM * * It is not fatal. If this ACK does _not_ change critical state (seqs, window) @@ -5515,6 +5527,9 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb, if (tcp_checksum_complete_user(sk, skb)) goto csum_error; + if ((int)skb->truesize > sk->sk_forward_alloc) + goto step5; + /* Predicted packet is in window by definition. * seq == rcv_nxt and rcv_wup <= rcv_nxt. * Hence, check seq<=rcv_wup reduces to: @@ -5526,9 +5541,6 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb, tcp_rcv_rtt_measure_ts(sk, skb); - if ((int)skb->truesize > sk->sk_forward_alloc) - goto step5; - NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPHPHITS); /* Bulk data transfer: receiver */ @@ -5576,14 +5588,10 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb, return 0; step5: - if (th->ack && tcp_ack(sk, skb, FLAG_SLOWPATH) < 0) + if (th->ack && + tcp_ack(sk, skb, FLAG_SLOWPATH | FLAG_UPDATE_TS_RECENT) < 0) goto discard; - /* ts_recent update must be made after we are sure that the packet - * is in window. - */ - tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq); - tcp_rcv_rtt_measure_ts(sk, skb); /* Process urgent data. */ @@ -5947,7 +5955,8 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, /* step 5: check the ACK field */ if (th->ack) { - int acceptable = tcp_ack(sk, skb, FLAG_SLOWPATH) > 0; + int acceptable = tcp_ack(sk, skb, FLAG_SLOWPATH | + FLAG_UPDATE_TS_RECENT) > 0; switch (sk->sk_state) { case TCP_SYN_RECV: @@ -6054,11 +6063,6 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, } else goto discard; - /* ts_recent update must be made after we are sure that the packet - * is in window. - */ - tcp_replace_ts_recent(tp, TCP_SKB_CB(skb)->seq); - /* step 6: check the URG bit */ tcp_urg(sk, skb, th); diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 76f50e1b53a..ae03b7b75af 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -974,7 +974,7 @@ int tcp_md5_do_add(struct sock *sk, const union tcp_md5_addr *addr, struct tcp_sock *tp = tcp_sk(sk); struct tcp_md5sig_info *md5sig; - key = tcp_md5_do_lookup(sk, (union tcp_md5_addr *)&addr, AF_INET); + key = tcp_md5_do_lookup(sk, addr, family); if (key) { /* Pre-existing entry - just update that one. */ memcpy(key->key, newkey, newkeylen); @@ -1019,7 +1019,7 @@ int tcp_md5_do_del(struct sock *sk, const union tcp_md5_addr *addr, int family) struct tcp_md5sig_key *key; struct tcp_md5sig_info *md5sig; - key = tcp_md5_do_lookup(sk, (union tcp_md5_addr *)&addr, AF_INET); + key = tcp_md5_do_lookup(sk, addr, family); if (!key) return -ENOENT; hlist_del_rcu(&key->node); diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 2d27e1af930..12999a3aaf9 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -835,11 +835,13 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, &md5); tcp_header_size = tcp_options_size + sizeof(struct tcphdr); - if (tcp_packets_in_flight(tp) == 0) { + if (tcp_packets_in_flight(tp) == 0) tcp_ca_event(sk, CA_EVENT_TX_START); - skb->ooo_okay = 1; - } else - skb->ooo_okay = 0; + + /* if no packet is in qdisc/device queue, then allow XPS to select + * another queue. + */ + skb->ooo_okay = sk_wmem_alloc_get(sk) == 0; skb_push(skb, tcp_header_size); skb_reset_transport_header(skb); @@ -1096,7 +1098,6 @@ static void __pskb_trim_head(struct sk_buff *skb, int len) eat = min_t(int, len, skb_headlen(skb)); if (eat) { __skb_pull(skb, eat); - skb->avail_size -= eat; len -= eat; if (!len) return; @@ -1588,8 +1589,11 @@ static int tcp_tso_should_defer(struct sock *sk, struct sk_buff *skb) goto send_now; } - /* Ok, it looks like it is advisable to defer. */ - tp->tso_deferred = 1 | (jiffies << 1); + /* Ok, it looks like it is advisable to defer. + * Do not rearm the timer if already set to not break TCP ACK clocking. + */ + if (!tp->tso_deferred) + tp->tso_deferred = 1 | (jiffies << 1); return 1; @@ -2152,8 +2156,12 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) */ TCP_SKB_CB(skb)->when = tcp_time_stamp; - /* make sure skb->data is aligned on arches that require it */ - if (unlikely(NET_IP_ALIGN && ((unsigned long)skb->data & 3))) { + /* make sure skb->data is aligned on arches that require it + * and check if ack-trimming & collapsing extended the headroom + * beyond what csum_start can cover. + */ + if (unlikely((NET_IP_ALIGN && ((unsigned long)skb->data & 3)) || + skb_headroom(skb) >= 0xFFFF)) { struct sk_buff *nskb = __pskb_copy(skb, MAX_TCP_HEADER, GFP_ATOMIC); err = nskb ? tcp_transmit_skb(sk, nskb, 0, GFP_ATOMIC) : diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index fe141052a1b..0b6136d578f 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -768,7 +768,7 @@ static int udp_send_skb(struct sk_buff *skb, struct flowi4 *fl4) /* * Push out all pending data as one UDP datagram. Socket is locked. */ -static int udp_push_pending_frames(struct sock *sk) +int udp_push_pending_frames(struct sock *sk) { struct udp_sock *up = udp_sk(sk); struct inet_sock *inet = inet_sk(sk); @@ -787,6 +787,7 @@ static int udp_push_pending_frames(struct sock *sk) up->pending = 0; return err; } +EXPORT_SYMBOL(udp_push_pending_frames); int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, size_t len) diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index e76e4520adc..1ec8fb6586f 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -1233,6 +1233,23 @@ int ipv6_dev_get_saddr(struct net *net, struct net_device *dst_dev, } EXPORT_SYMBOL(ipv6_dev_get_saddr); +int __ipv6_get_lladdr(struct inet6_dev *idev, struct in6_addr *addr, + unsigned char banned_flags) +{ + struct inet6_ifaddr *ifp; + int err = -EADDRNOTAVAIL; + + list_for_each_entry(ifp, &idev->addr_list, if_list) { + if (ifp->scope == IFA_LINK && + !(ifp->flags & banned_flags)) { + *addr = ifp->addr; + err = 0; + break; + } + } + return err; +} + int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr, unsigned char banned_flags) { @@ -1242,17 +1259,8 @@ int ipv6_get_lladdr(struct net_device *dev, struct in6_addr *addr, rcu_read_lock(); idev = __in6_dev_get(dev); if (idev) { - struct inet6_ifaddr *ifp; - read_lock_bh(&idev->lock); - list_for_each_entry(ifp, &idev->addr_list, if_list) { - if (ifp->scope == IFA_LINK && - !(ifp->flags & banned_flags)) { - *addr = ifp->addr; - err = 0; - break; - } - } + err = __ipv6_get_lladdr(idev, addr, banned_flags); read_unlock_bh(&idev->lock); } rcu_read_unlock(); @@ -1746,7 +1754,7 @@ static struct rt6_info *addrconf_get_prefix_route(const struct in6_addr *pfx, continue; if ((rt->rt6i_flags & flags) != flags) continue; - if ((noflags != 0) && ((rt->rt6i_flags & flags) != 0)) + if ((rt->rt6i_flags & noflags) != 0) continue; dst_hold(&rt->dst); break; @@ -2409,6 +2417,9 @@ static void sit_add_v4_addrs(struct inet6_dev *idev) static void init_loopback(struct net_device *dev) { struct inet6_dev *idev; + struct net_device *sp_dev; + struct inet6_ifaddr *sp_ifa; + struct rt6_info *sp_rt; /* ::1 */ @@ -2420,6 +2431,35 @@ static void init_loopback(struct net_device *dev) } add_addr(idev, &in6addr_loopback, 128, IFA_HOST); + + /* Add routes to other interface's IPv6 addresses */ + for_each_netdev(dev_net(dev), sp_dev) { + if (!strcmp(sp_dev->name, dev->name)) + continue; + + idev = __in6_dev_get(sp_dev); + if (!idev) + continue; + + read_lock_bh(&idev->lock); + list_for_each_entry(sp_ifa, &idev->addr_list, if_list) { + + if (sp_ifa->flags & (IFA_F_DADFAILED | IFA_F_TENTATIVE)) + continue; + + if (sp_ifa->rt) + continue; + + sp_rt = addrconf_dst_alloc(idev, &sp_ifa->addr, 0); + + /* Failure cases are ignored */ + if (!IS_ERR(sp_rt)) { + sp_ifa->rt = sp_rt; + ip6_ins_rt(sp_rt); + } + } + read_unlock_bh(&idev->lock); + } } static void addrconf_add_linklocal(struct inet6_dev *idev, const struct in6_addr *addr) @@ -4697,26 +4737,20 @@ static void addrconf_sysctl_unregister(struct inet6_dev *idev) static int __net_init addrconf_init_net(struct net *net) { - int err; + int err = -ENOMEM; struct ipv6_devconf *all, *dflt; - err = -ENOMEM; - all = &ipv6_devconf; - dflt = &ipv6_devconf_dflt; + all = kmemdup(&ipv6_devconf, sizeof(ipv6_devconf), GFP_KERNEL); + if (all == NULL) + goto err_alloc_all; - if (!net_eq(net, &init_net)) { - all = kmemdup(all, sizeof(ipv6_devconf), GFP_KERNEL); - if (all == NULL) - goto err_alloc_all; + dflt = kmemdup(&ipv6_devconf_dflt, sizeof(ipv6_devconf_dflt), GFP_KERNEL); + if (dflt == NULL) + goto err_alloc_dflt; - dflt = kmemdup(dflt, sizeof(ipv6_devconf_dflt), GFP_KERNEL); - if (dflt == NULL) - goto err_alloc_dflt; - } else { - /* these will be inherited by all namespaces */ - dflt->autoconf = ipv6_defaults.autoconf; - dflt->disable_ipv6 = ipv6_defaults.disable_ipv6; - } + /* these will be inherited by all namespaces */ + dflt->autoconf = ipv6_defaults.autoconf; + dflt->disable_ipv6 = ipv6_defaults.disable_ipv6; net->ipv6.devconf_all = all; net->ipv6.devconf_dflt = dflt; diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index 1ca5d45a12e..37aceed4c06 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c @@ -111,6 +111,27 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt ipv6_addr_loopback(&hdr->daddr)) goto err; + /* RFC4291 Errata ID: 3480 + * Interface-Local scope spans only a single interface on a + * node and is useful only for loopback transmission of + * multicast. Packets with interface-local scope received + * from another node must be discarded. + */ + if (!(skb->pkt_type == PACKET_LOOPBACK || + dev->flags & IFF_LOOPBACK) && + ipv6_addr_is_multicast(&hdr->daddr) && + IPV6_ADDR_MC_SCOPE(&hdr->daddr) == 1) + goto err; + + /* RFC4291 2.7 + * Nodes must not originate a packet to a multicast address whose scope + * field contains the reserved value 0; if such a packet is received, it + * must be silently dropped. + */ + if (ipv6_addr_is_multicast(&hdr->daddr) && + IPV6_ADDR_MC_SCOPE(&hdr->daddr) == 0) + goto err; + /* * RFC4291 2.7 * Multicast addresses must not be used as source addresses in IPv6 @@ -265,7 +286,8 @@ int ip6_mc_input(struct sk_buff *skb) * IPv6 multicast router mode is now supported ;) */ if (dev_net(skb->dev)->ipv6.devconf_all->mc_forwarding && - !(ipv6_addr_type(&hdr->daddr) & IPV6_ADDR_LINKLOCAL) && + !(ipv6_addr_type(&hdr->daddr) & + (IPV6_ADDR_LOOPBACK|IPV6_ADDR_LINKLOCAL)) && likely(!(IP6CB(skb)->flags & IP6SKB_FORWARDED))) { /* * Okay, we try to forward - split and duplicate diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index ec329a3c5b5..f741f1cc8f7 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -913,11 +913,17 @@ static struct dst_entry *ip6_sk_dst_check(struct sock *sk, const struct flowi6 *fl6) { struct ipv6_pinfo *np = inet6_sk(sk); - struct rt6_info *rt = (struct rt6_info *)dst; + struct rt6_info *rt; if (!dst) goto out; + if (dst->ops->family != AF_INET6) { + dst_release(dst); + return NULL; + } + + rt = (struct rt6_info *)dst; /* Yes, checking route validity in not connected * case is not very simple. Take into account, * that we do not support routing by source, TOS, @@ -1182,11 +1188,12 @@ static inline struct ipv6_rt_hdr *ip6_rthdr_dup(struct ipv6_rt_hdr *src, return src ? kmemdup(src, (src->hdrlen + 1) * 8, gfp) : NULL; } -static void ip6_append_data_mtu(int *mtu, +static void ip6_append_data_mtu(unsigned int *mtu, int *maxfraglen, unsigned int fragheaderlen, struct sk_buff *skb, - struct rt6_info *rt) + struct rt6_info *rt, + bool pmtuprobe) { if (!(rt->dst.flags & DST_XFRM_TUNNEL)) { if (skb == NULL) { @@ -1198,7 +1205,9 @@ static void ip6_append_data_mtu(int *mtu, * this fragment is not first, the headers * space is regarded as data space. */ - *mtu = dst_mtu(rt->dst.path); + *mtu = min(*mtu, pmtuprobe ? + rt->dst.dev->mtu : + dst_mtu(rt->dst.path)); } *maxfraglen = ((*mtu - fragheaderlen) & ~7) + fragheaderlen - sizeof(struct frag_hdr); @@ -1215,11 +1224,10 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, struct ipv6_pinfo *np = inet6_sk(sk); struct inet_cork *cork; struct sk_buff *skb, *skb_prev = NULL; - unsigned int maxfraglen, fragheaderlen; + unsigned int maxfraglen, fragheaderlen, mtu; int exthdrlen; int dst_exthdrlen; int hh_len; - int mtu; int copy; int err; int offset = 0; @@ -1237,7 +1245,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, if (WARN_ON(np->cork.opt)) return -EINVAL; - np->cork.opt = kmalloc(opt->tot_len, sk->sk_allocation); + np->cork.opt = kzalloc(opt->tot_len, sk->sk_allocation); if (unlikely(np->cork.opt == NULL)) return -ENOBUFS; @@ -1288,10 +1296,10 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, cork->length = 0; sk->sk_sndmsg_page = NULL; sk->sk_sndmsg_off = 0; - exthdrlen = (opt ? opt->opt_flen : 0) - rt->rt6i_nfheader_len; + exthdrlen = (opt ? opt->opt_flen : 0); length += exthdrlen; transhdrlen += exthdrlen; - dst_exthdrlen = rt->dst.header_len; + dst_exthdrlen = rt->dst.header_len - rt->rt6i_nfheader_len; } else { rt = (struct rt6_info *)cork->dst; fl6 = &inet->cork.fl.u.ip6; @@ -1382,7 +1390,9 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, /* update mtu and maxfraglen if necessary */ if (skb == NULL || skb_prev == NULL) ip6_append_data_mtu(&mtu, &maxfraglen, - fragheaderlen, skb, rt); + fragheaderlen, skb, rt, + np->pmtudisc == + IPV6_PMTUDISC_PROBE); skb_prev = skb; diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index 8110362e0af..d5e4615e52c 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c @@ -256,10 +256,12 @@ static void __net_exit ip6mr_rules_exit(struct net *net) { struct mr6_table *mrt, *next; + rtnl_lock(); list_for_each_entry_safe(mrt, next, &net->ipv6.mr6_tables, list) { list_del(&mrt->list); ip6mr_free_table(mrt); } + rtnl_unlock(); fib_rules_unregister(net->ipv6.mr6_rules_ops); } #else @@ -286,7 +288,10 @@ static int __net_init ip6mr_rules_init(struct net *net) static void __net_exit ip6mr_rules_exit(struct net *net) { + rtnl_lock(); ip6mr_free_table(net->ipv6.mrt6); + net->ipv6.mrt6 = NULL; + rtnl_unlock(); } #endif diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index b2869cab209..6a4ab24a5d6 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c @@ -1334,8 +1334,9 @@ mld_scount(struct ifmcaddr6 *pmc, int type, int gdeleted, int sdeleted) return scount; } -static struct sk_buff *mld_newpack(struct net_device *dev, int size) +static struct sk_buff *mld_newpack(struct inet6_dev *idev, int size) { + struct net_device *dev = idev->dev; struct net *net = dev_net(dev); struct sock *sk = net->ipv6.igmp_sk; struct sk_buff *skb; @@ -1360,7 +1361,7 @@ static struct sk_buff *mld_newpack(struct net_device *dev, int size) skb_reserve(skb, hlen); - if (ipv6_get_lladdr(dev, &addr_buf, IFA_F_TENTATIVE)) { + if (__ipv6_get_lladdr(idev, &addr_buf, IFA_F_TENTATIVE)) { /* : * use unspecified address as the source address * when a valid link-local address is not available. @@ -1456,7 +1457,7 @@ static struct sk_buff *add_grhead(struct sk_buff *skb, struct ifmcaddr6 *pmc, struct mld2_grec *pgr; if (!skb) - skb = mld_newpack(dev, dev->mtu); + skb = mld_newpack(pmc->idev, dev->mtu); if (!skb) return NULL; pgr = (struct mld2_grec *)skb_put(skb, sizeof(struct mld2_grec)); @@ -1476,7 +1477,8 @@ static struct sk_buff *add_grhead(struct sk_buff *skb, struct ifmcaddr6 *pmc, static struct sk_buff *add_grec(struct sk_buff *skb, struct ifmcaddr6 *pmc, int type, int gdeleted, int sdeleted) { - struct net_device *dev = pmc->idev->dev; + struct inet6_dev *idev = pmc->idev; + struct net_device *dev = idev->dev; struct mld2_report *pmr; struct mld2_grec *pgr = NULL; struct ip6_sf_list *psf, *psf_next, *psf_prev, **psf_list; @@ -1505,7 +1507,7 @@ static struct sk_buff *add_grec(struct sk_buff *skb, struct ifmcaddr6 *pmc, AVAILABLE(skb) < grec_size(pmc, type, gdeleted, sdeleted)) { if (skb) mld_sendpack(skb); - skb = mld_newpack(dev, dev->mtu); + skb = mld_newpack(idev, dev->mtu); } } first = 1; @@ -1532,7 +1534,7 @@ static struct sk_buff *add_grec(struct sk_buff *skb, struct ifmcaddr6 *pmc, pgr->grec_nsrcs = htons(scount); if (skb) mld_sendpack(skb); - skb = mld_newpack(dev, dev->mtu); + skb = mld_newpack(idev, dev->mtu); first = 1; scount = 0; } @@ -1587,8 +1589,8 @@ static void mld_send_report(struct inet6_dev *idev, struct ifmcaddr6 *pmc) struct sk_buff *skb = NULL; int type; + read_lock_bh(&idev->lock); if (!pmc) { - read_lock_bh(&idev->lock); for (pmc=idev->mc_list; pmc; pmc=pmc->next) { if (pmc->mca_flags & MAF_NOREPORT) continue; @@ -1600,7 +1602,6 @@ static void mld_send_report(struct inet6_dev *idev, struct ifmcaddr6 *pmc) skb = add_grec(skb, pmc, type, 0, 0); spin_unlock_bh(&pmc->mca_lock); } - read_unlock_bh(&idev->lock); } else { spin_lock_bh(&pmc->mca_lock); if (pmc->mca_sfcount[MCAST_EXCLUDE]) @@ -1610,6 +1611,7 @@ static void mld_send_report(struct inet6_dev *idev, struct ifmcaddr6 *pmc) skb = add_grec(skb, pmc, type, 0, 0); spin_unlock_bh(&pmc->mca_lock); } + read_unlock_bh(&idev->lock); if (skb) mld_sendpack(skb); } diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index 38f00b0298d..52e2f65ff3a 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c @@ -14,6 +14,8 @@ * 2 of the License, or (at your option) any later version. */ +#define pr_fmt(fmt) "IPv6-nf: " fmt + #include #include #include @@ -176,13 +178,12 @@ fq_find(__be32 id, u32 user, struct in6_addr *src, struct in6_addr *dst) q = inet_frag_find(&nf_init_frags, &nf_frags, &arg, hash); local_bh_enable(); - if (q == NULL) - goto oom; + if (IS_ERR_OR_NULL(q)) { + inet_frag_maybe_warn_overflow(q, pr_fmt()); + return NULL; + } return container_of(q, struct nf_ct_frag6_queue, q); - -oom: - return NULL; } diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index 9447bd69873..6bda7aa551b 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c @@ -26,6 +26,9 @@ * YOSHIFUJI,H. @USAGI Always remove fragment header to * calculate ICV correctly. */ + +#define pr_fmt(fmt) "IPv6: " fmt + #include #include #include @@ -240,9 +243,10 @@ fq_find(struct net *net, __be32 id, const struct in6_addr *src, const struct in6 hash = inet6_hash_frag(id, src, dst, ip6_frags.rnd); q = inet_frag_find(&net->ipv6.frags, &ip6_frags, &arg, hash); - if (q == NULL) + if (IS_ERR_OR_NULL(q)) { + inet_frag_maybe_warn_overflow(q, pr_fmt()); return NULL; - + } return container_of(q, struct frag_queue, q); } @@ -381,8 +385,17 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, } if (fq->q.last_in == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) && - fq->q.meat == fq->q.len) - return ip6_frag_reasm(fq, prev, dev); + fq->q.meat == fq->q.len) { + int res; + unsigned long orefdst = skb->_skb_refdst; + + skb->_skb_refdst = 0UL; + res = ip6_frag_reasm(fq, prev, dev); + skb->_skb_refdst = orefdst; + return res; + } + + skb_dst_drop(skb); write_lock(&ip6_frags.lock); list_move_tail(&fq->q.lru_list, &fq->q.net->lru_list); diff --git a/net/ipv6/route.c b/net/ipv6/route.c index d151056dd4a..016ed7c22fc 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -846,7 +846,8 @@ static struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table, dst_hold(&rt->dst); read_unlock_bh(&table->tb6_lock); - if (!dst_get_neighbour_noref_raw(&rt->dst) && !(rt->rt6i_flags & RTF_NONEXTHOP)) + if (!dst_get_neighbour_noref_raw(&rt->dst) && + !(rt->rt6i_flags & (RTF_NONEXTHOP | RTF_LOCAL))) nrt = rt6_alloc_cow(rt, &fl6->daddr, &fl6->saddr); else if (!(rt->dst.flags & DST_HOST)) nrt = rt6_alloc_clone(rt, &fl6->daddr); @@ -1031,10 +1032,13 @@ static void ip6_link_failure(struct sk_buff *skb) rt = (struct rt6_info *) skb_dst(skb); if (rt) { - if (rt->rt6i_flags & RTF_CACHE) - rt6_update_expires(rt, 0); - else if (rt->rt6i_node && (rt->rt6i_flags & RTF_DEFAULT)) + if (rt->rt6i_flags & RTF_CACHE) { + dst_hold(&rt->dst); + if (ip6_del_rt(rt)) + dst_free(&rt->dst); + } else if (rt->rt6i_node && (rt->rt6i_flags & RTF_DEFAULT)) { rt->rt6i_node->fn_sernum = -1; + } } } diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 3889e020418..7ee71216773 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -2079,6 +2079,17 @@ void tcp6_proc_exit(struct net *net) } #endif +static void tcp_v6_clear_sk(struct sock *sk, int size) +{ + struct inet_sock *inet = inet_sk(sk); + + /* we do not want to clear pinet6 field, because of RCU lookups */ + sk_prot_clear_nulls(sk, offsetof(struct inet_sock, pinet6)); + + size -= offsetof(struct inet_sock, pinet6) + sizeof(inet->pinet6); + memset(&inet->pinet6 + 1, 0, size); +} + struct proto tcpv6_prot = { .name = "TCPv6", .owner = THIS_MODULE, @@ -2120,6 +2131,7 @@ struct proto tcpv6_prot = { #ifdef CONFIG_CGROUP_MEM_RES_CTLR_KMEM .proto_cgroup = tcp_proto_cgroup, #endif + .clear_sk = tcp_v6_clear_sk, }; static const struct inet6_protocol tcpv6_protocol = { diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 37b0699e95e..f79bfdbc247 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -895,11 +895,16 @@ static int udp_v6_push_pending_frames(struct sock *sk) struct udphdr *uh; struct udp_sock *up = udp_sk(sk); struct inet_sock *inet = inet_sk(sk); - struct flowi6 *fl6 = &inet->cork.fl.u.ip6; + struct flowi6 *fl6; int err = 0; int is_udplite = IS_UDPLITE(sk); __wsum csum = 0; + if (up->pending == AF_INET) + return udp_push_pending_frames(sk); + + fl6 = &inet->cork.fl.u.ip6; + /* Grab the skbuff where UDP header space exists. */ if ((skb = skb_peek(&sk->sk_write_queue)) == NULL) goto out; @@ -1457,6 +1462,17 @@ void udp6_proc_exit(struct net *net) { } #endif /* CONFIG_PROC_FS */ +void udp_v6_clear_sk(struct sock *sk, int size) +{ + struct inet_sock *inet = inet_sk(sk); + + /* we do not want to clear pinet6 field, because of RCU lookups */ + sk_prot_clear_portaddr_nulls(sk, offsetof(struct inet_sock, pinet6)); + + size -= offsetof(struct inet_sock, pinet6) + sizeof(inet->pinet6); + memset(&inet->pinet6 + 1, 0, size); +} + /* ------------------------------------------------------------------------ */ struct proto udpv6_prot = { @@ -1487,7 +1503,7 @@ struct proto udpv6_prot = { .compat_setsockopt = compat_udpv6_setsockopt, .compat_getsockopt = compat_udpv6_getsockopt, #endif - .clear_sk = sk_prot_clear_portaddr_nulls, + .clear_sk = udp_v6_clear_sk, }; static struct inet_protosw udpv6_protosw = { diff --git a/net/ipv6/udp_impl.h b/net/ipv6/udp_impl.h index d7571046bfc..4691ed50a92 100644 --- a/net/ipv6/udp_impl.h +++ b/net/ipv6/udp_impl.h @@ -31,6 +31,8 @@ extern int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk, extern int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb); extern void udpv6_destroy_sock(struct sock *sk); +extern void udp_v6_clear_sk(struct sock *sk, int size); + #ifdef CONFIG_PROC_FS extern int udp6_seq_show(struct seq_file *seq, void *v); #endif diff --git a/net/ipv6/udplite.c b/net/ipv6/udplite.c index 1d08e21d9f6..dfcc4be4689 100644 --- a/net/ipv6/udplite.c +++ b/net/ipv6/udplite.c @@ -56,7 +56,7 @@ struct proto udplitev6_prot = { .compat_setsockopt = compat_udpv6_setsockopt, .compat_getsockopt = compat_udpv6_getsockopt, #endif - .clear_sk = sk_prot_clear_portaddr_nulls, + .clear_sk = udp_v6_clear_sk, }; static struct inet_protosw udplite6_protosw = { diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index 8ea65e03273..808fd080eb3 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c @@ -96,8 +96,10 @@ static int xfrm6_fill_dst(struct xfrm_dst *xdst, struct net_device *dev, dev_hold(dev); xdst->u.rt6.rt6i_idev = in6_dev_get(dev); - if (!xdst->u.rt6.rt6i_idev) + if (!xdst->u.rt6.rt6i_idev) { + dev_put(dev); return -ENODEV; + } xdst->u.rt6.rt6i_peer = rt->rt6i_peer; if (rt->rt6i_peer) diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c index bb14c347768..bd25678b1d5 100644 --- a/net/irda/af_irda.c +++ b/net/irda/af_irda.c @@ -1386,6 +1386,8 @@ static int irda_recvmsg_dgram(struct kiocb *iocb, struct socket *sock, IRDA_DEBUG(4, "%s()\n", __func__); + msg->msg_namelen = 0; + skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, flags & MSG_DONTWAIT, &err); if (!skb) @@ -2584,8 +2586,10 @@ static int irda_getsockopt(struct socket *sock, int level, int optname, NULL, NULL, NULL); /* Check if the we got some results */ - if (!self->cachedaddr) - return -EAGAIN; /* Didn't find any devices */ + if (!self->cachedaddr) { + err = -EAGAIN; /* Didn't find any devices */ + goto out; + } daddr = self->cachedaddr; /* Cleanup */ self->cachedaddr = 0; diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index cd6f7a991d8..625bc50391c 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c @@ -1331,6 +1331,8 @@ static int iucv_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct sk_buff *skb, *rskb, *cskb; int err = 0; + msg->msg_namelen = 0; + if ((sk->sk_state == IUCV_DISCONN) && skb_queue_empty(&iucv->backlog_skb_q) && skb_queue_empty(&sk->sk_receive_queue) && diff --git a/net/key/af_key.c b/net/key/af_key.c index 7e5d927b576..2f3ce93d3fc 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -1705,6 +1705,7 @@ static int key_notify_sa_flush(const struct km_event *c) hdr->sadb_msg_version = PF_KEY_V2; hdr->sadb_msg_errno = (uint8_t) 0; hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t)); + hdr->sadb_msg_reserved = 0; pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ALL, NULL, c->net); @@ -2072,6 +2073,7 @@ static int pfkey_xfrm_policy2msg(struct sk_buff *skb, const struct xfrm_policy * pol->sadb_x_policy_type = IPSEC_POLICY_NONE; } pol->sadb_x_policy_dir = dir+1; + pol->sadb_x_policy_reserved = 0; pol->sadb_x_policy_id = xp->index; pol->sadb_x_policy_priority = xp->priority; @@ -2685,7 +2687,9 @@ static int key_notify_policy_flush(const struct km_event *c) hdr->sadb_msg_pid = c->pid; hdr->sadb_msg_version = PF_KEY_V2; hdr->sadb_msg_errno = (uint8_t) 0; + hdr->sadb_msg_satype = SADB_SATYPE_UNSPEC; hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t)); + hdr->sadb_msg_reserved = 0; pfkey_broadcast(skb_out, GFP_ATOMIC, BROADCAST_ALL, NULL, c->net); return 0; @@ -3106,7 +3110,9 @@ static int pfkey_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *t, struct pol->sadb_x_policy_exttype = SADB_X_EXT_POLICY; pol->sadb_x_policy_type = IPSEC_POLICY_IPSEC; pol->sadb_x_policy_dir = dir+1; + pol->sadb_x_policy_reserved = 0; pol->sadb_x_policy_id = xp->index; + pol->sadb_x_policy_priority = xp->priority; /* Set sadb_comb's. */ if (x->id.proto == IPPROTO_AH) @@ -3494,6 +3500,7 @@ static int pfkey_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type, pol->sadb_x_policy_exttype = SADB_X_EXT_POLICY; pol->sadb_x_policy_type = IPSEC_POLICY_IPSEC; pol->sadb_x_policy_dir = dir + 1; + pol->sadb_x_policy_reserved = 0; pol->sadb_x_policy_id = 0; pol->sadb_x_policy_priority = 0; diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c index 1addd9f3f40..b2982f4214d 100644 --- a/net/l2tp/l2tp_ppp.c +++ b/net/l2tp/l2tp_ppp.c @@ -350,18 +350,19 @@ static int pppol2tp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msgh skb_put(skb, 2); /* Copy user data into skb */ - error = memcpy_fromiovec(skb->data, m->msg_iov, total_len); + error = memcpy_fromiovec(skb_put(skb, total_len), m->msg_iov, + total_len); if (error < 0) { kfree_skb(skb); goto error_put_sess_tun; } - skb_put(skb, total_len); l2tp_xmit_skb(session, skb, session->hdr_len); sock_put(ps->tunnel_sock); + sock_put(sk); - return error; + return total_len; error_put_sess_tun: sock_put(ps->tunnel_sock); @@ -1777,7 +1778,8 @@ static const struct proto_ops pppol2tp_ops = { static const struct pppox_proto pppol2tp_proto = { .create = pppol2tp_create, - .ioctl = pppol2tp_ioctl + .ioctl = pppol2tp_ioctl, + .owner = THIS_MODULE, }; #ifdef CONFIG_L2TP_V3 diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index df08d7779e1..e4d2fbb59a7 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c @@ -721,6 +721,8 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock, int target; /* Read at least this many bytes */ long timeo; + msg->msg_namelen = 0; + lock_sock(sk); copied = -ENOTCONN; if (unlikely(sk->sk_type == SOCK_STREAM && sk->sk_state == TCP_LISTEN)) diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 48f937e1ecf..95a04f02f30 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -1257,6 +1257,15 @@ void ieee80211_remove_interfaces(struct ieee80211_local *local) ASSERT_RTNL(); + /* + * Close all AP_VLAN interfaces first, as otherwise they + * might be closed while the AP interface they belong to + * is closed, causing unregister_netdevice_many() to crash. + */ + list_for_each_entry(sdata, &local->interfaces, list) + if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) + dev_close(sdata->dev); + mutex_lock(&local->iflist_mtx); list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) { list_del(&sdata->list); diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 8ce9feb1301..067aa2a2305 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -831,8 +831,14 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx) struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); - /* Drop duplicate 802.11 retransmissions (IEEE 802.11 Chap. 9.2.9) */ - if (rx->sta && !is_multicast_ether_addr(hdr->addr1)) { + /* + * Drop duplicate 802.11 retransmissions + * (IEEE 802.11-2012: 9.3.2.10 "Duplicate detection and recovery") + */ + if (rx->skb->len >= 24 && rx->sta && + !ieee80211_is_ctl(hdr->frame_control) && + !ieee80211_is_qos_nullfunc(hdr->frame_control) && + !is_multicast_ether_addr(hdr->addr1)) { if (unlikely(ieee80211_has_retry(hdr->frame_control) && rx->sta->last_seq_ctrl[rx->seqno_idx] == hdr->seq_ctrl)) { diff --git a/net/netfilter/ipvs/ip_vs_pe_sip.c b/net/netfilter/ipvs/ip_vs_pe_sip.c index 1aa5cac748c..55add932542 100644 --- a/net/netfilter/ipvs/ip_vs_pe_sip.c +++ b/net/netfilter/ipvs/ip_vs_pe_sip.c @@ -37,14 +37,10 @@ static int get_callid(const char *dptr, unsigned int dataoff, if (ret > 0) break; if (!ret) - return 0; + return -EINVAL; dataoff += *matchoff; } - /* Empty callid is useless */ - if (!*matchlen) - return -EINVAL; - /* Too large is useless */ if (*matchlen > IP_VS_PEDATA_MAXLEN) return -EINVAL; diff --git a/net/netlabel/netlabel_domainhash.c b/net/netlabel/netlabel_domainhash.c index d8d42433755..6bb1d42f0fa 100644 --- a/net/netlabel/netlabel_domainhash.c +++ b/net/netlabel/netlabel_domainhash.c @@ -245,6 +245,71 @@ static void netlbl_domhsh_audit_add(struct netlbl_dom_map *entry, } } +/** + * netlbl_domhsh_validate - Validate a new domain mapping entry + * @entry: the entry to validate + * + * This function validates the new domain mapping entry to ensure that it is + * a valid entry. Returns zero on success, negative values on failure. + * + */ +static int netlbl_domhsh_validate(const struct netlbl_dom_map *entry) +{ + struct netlbl_af4list *iter4; + struct netlbl_domaddr4_map *map4; +#if IS_ENABLED(CONFIG_IPV6) + struct netlbl_af6list *iter6; + struct netlbl_domaddr6_map *map6; +#endif /* IPv6 */ + + if (entry == NULL) + return -EINVAL; + + switch (entry->type) { + case NETLBL_NLTYPE_UNLABELED: + if (entry->type_def.cipsov4 != NULL || + entry->type_def.addrsel != NULL) + return -EINVAL; + break; + case NETLBL_NLTYPE_CIPSOV4: + if (entry->type_def.cipsov4 == NULL) + return -EINVAL; + break; + case NETLBL_NLTYPE_ADDRSELECT: + netlbl_af4list_foreach(iter4, &entry->type_def.addrsel->list4) { + map4 = netlbl_domhsh_addr4_entry(iter4); + switch (map4->type) { + case NETLBL_NLTYPE_UNLABELED: + if (map4->type_def.cipsov4 != NULL) + return -EINVAL; + break; + case NETLBL_NLTYPE_CIPSOV4: + if (map4->type_def.cipsov4 == NULL) + return -EINVAL; + break; + default: + return -EINVAL; + } + } +#if IS_ENABLED(CONFIG_IPV6) + netlbl_af6list_foreach(iter6, &entry->type_def.addrsel->list6) { + map6 = netlbl_domhsh_addr6_entry(iter6); + switch (map6->type) { + case NETLBL_NLTYPE_UNLABELED: + break; + default: + return -EINVAL; + } + } +#endif /* IPv6 */ + break; + default: + return -EINVAL; + } + + return 0; +} + /* * Domain Hash Table Functions */ @@ -311,6 +376,10 @@ int netlbl_domhsh_add(struct netlbl_dom_map *entry, struct netlbl_af6list *tmp6; #endif /* IPv6 */ + ret_val = netlbl_domhsh_validate(entry); + if (ret_val != 0) + return ret_val; + /* XXX - we can remove this RCU read lock as the spinlock protects the * entire function, but before we do we need to fixup the * netlbl_af[4,6]list RCU functions to do "the right thing" with diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c index e7ff694f104..7fe20d068dd 100644 --- a/net/netlabel/netlabel_unlabeled.c +++ b/net/netlabel/netlabel_unlabeled.c @@ -1189,8 +1189,6 @@ static int netlbl_unlabel_staticlist(struct sk_buff *skb, struct netlbl_unlhsh_walk_arg cb_arg; u32 skip_bkt = cb->args[0]; u32 skip_chain = cb->args[1]; - u32 skip_addr4 = cb->args[2]; - u32 skip_addr6 = cb->args[3]; u32 iter_bkt; u32 iter_chain = 0, iter_addr4 = 0, iter_addr6 = 0; struct netlbl_unlhsh_iface *iface; @@ -1215,7 +1213,7 @@ static int netlbl_unlabel_staticlist(struct sk_buff *skb, continue; netlbl_af4list_foreach_rcu(addr4, &iface->addr4_list) { - if (iter_addr4++ < skip_addr4) + if (iter_addr4++ < cb->args[2]) continue; if (netlbl_unlabel_staticlist_gen( NLBL_UNLABEL_C_STATICLIST, @@ -1231,7 +1229,7 @@ static int netlbl_unlabel_staticlist(struct sk_buff *skb, #if IS_ENABLED(CONFIG_IPV6) netlbl_af6list_foreach_rcu(addr6, &iface->addr6_list) { - if (iter_addr6++ < skip_addr6) + if (iter_addr6++ < cb->args[3]) continue; if (netlbl_unlabel_staticlist_gen( NLBL_UNLABEL_C_STATICLIST, @@ -1250,10 +1248,10 @@ static int netlbl_unlabel_staticlist(struct sk_buff *skb, unlabel_staticlist_return: rcu_read_unlock(); - cb->args[0] = skip_bkt; - cb->args[1] = skip_chain; - cb->args[2] = skip_addr4; - cb->args[3] = skip_addr6; + cb->args[0] = iter_bkt; + cb->args[1] = iter_chain; + cb->args[2] = iter_addr4; + cb->args[3] = iter_addr6; return skb->len; } @@ -1273,12 +1271,9 @@ static int netlbl_unlabel_staticlistdef(struct sk_buff *skb, { struct netlbl_unlhsh_walk_arg cb_arg; struct netlbl_unlhsh_iface *iface; - u32 skip_addr4 = cb->args[0]; - u32 skip_addr6 = cb->args[1]; - u32 iter_addr4 = 0; + u32 iter_addr4 = 0, iter_addr6 = 0; struct netlbl_af4list *addr4; #if IS_ENABLED(CONFIG_IPV6) - u32 iter_addr6 = 0; struct netlbl_af6list *addr6; #endif @@ -1292,7 +1287,7 @@ static int netlbl_unlabel_staticlistdef(struct sk_buff *skb, goto unlabel_staticlistdef_return; netlbl_af4list_foreach_rcu(addr4, &iface->addr4_list) { - if (iter_addr4++ < skip_addr4) + if (iter_addr4++ < cb->args[0]) continue; if (netlbl_unlabel_staticlist_gen(NLBL_UNLABEL_C_STATICLISTDEF, iface, @@ -1305,7 +1300,7 @@ static int netlbl_unlabel_staticlistdef(struct sk_buff *skb, } #if IS_ENABLED(CONFIG_IPV6) netlbl_af6list_foreach_rcu(addr6, &iface->addr6_list) { - if (iter_addr6++ < skip_addr6) + if (iter_addr6++ < cb->args[1]) continue; if (netlbl_unlabel_staticlist_gen(NLBL_UNLABEL_C_STATICLISTDEF, iface, @@ -1320,8 +1315,8 @@ static int netlbl_unlabel_staticlistdef(struct sk_buff *skb, unlabel_staticlistdef_return: rcu_read_unlock(); - cb->args[0] = skip_addr4; - cb->args[1] = skip_addr6; + cb->args[0] = iter_addr4; + cb->args[1] = iter_addr6; return skb->len; } diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c index 9f40441d7a7..73d3f0c84ce 100644 --- a/net/netlink/genetlink.c +++ b/net/netlink/genetlink.c @@ -142,6 +142,7 @@ int genl_register_mc_group(struct genl_family *family, int err = 0; BUG_ON(grp->name[0] == '\0'); + BUG_ON(memchr(grp->name, '\0', GENL_NAMSIZ) == NULL); genl_lock(); diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c index 1b9024ee963..7ed9b1d0c10 100644 --- a/net/netrom/af_netrom.c +++ b/net/netrom/af_netrom.c @@ -1177,6 +1177,7 @@ static int nr_recvmsg(struct kiocb *iocb, struct socket *sock, } if (sax != NULL) { + memset(sax, 0, sizeof(*sax)); sax->sax25_family = AF_NETROM; skb_copy_from_linear_data_offset(skb, 7, sax->sax25_call.ax25_call, AX25_ADDR_LEN); diff --git a/net/nfc/llcp/sock.c b/net/nfc/llcp/sock.c index c13e02ebdef..0c2115f31c8 100644 --- a/net/nfc/llcp/sock.c +++ b/net/nfc/llcp/sock.c @@ -514,6 +514,8 @@ static int llcp_sock_recvmsg(struct kiocb *iocb, struct socket *sock, pr_debug("%p %zu\n", sk, len); + msg->msg_namelen = 0; + lock_sock(sk); if (sk->sk_state == LLCP_CLOSED && diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 078fdffcd55..8ed5d9302e8 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -812,37 +812,27 @@ static void prb_open_block(struct tpacket_kbdq_core *pkc1, smp_rmb(); - if (likely(TP_STATUS_KERNEL == BLOCK_STATUS(pbd1))) { - - /* We could have just memset this but we will lose the - * flexibility of making the priv area sticky - */ - BLOCK_SNUM(pbd1) = pkc1->knxt_seq_num++; - BLOCK_NUM_PKTS(pbd1) = 0; - BLOCK_LEN(pbd1) = BLK_PLUS_PRIV(pkc1->blk_sizeof_priv); - getnstimeofday(&ts); - h1->ts_first_pkt.ts_sec = ts.tv_sec; - h1->ts_first_pkt.ts_nsec = ts.tv_nsec; - pkc1->pkblk_start = (char *)pbd1; - pkc1->nxt_offset = (char *)(pkc1->pkblk_start + - BLK_PLUS_PRIV(pkc1->blk_sizeof_priv)); - BLOCK_O2FP(pbd1) = (__u32)BLK_PLUS_PRIV(pkc1->blk_sizeof_priv); - BLOCK_O2PRIV(pbd1) = BLK_HDR_LEN; - pbd1->version = pkc1->version; - pkc1->prev = pkc1->nxt_offset; - pkc1->pkblk_end = pkc1->pkblk_start + pkc1->kblk_size; - prb_thaw_queue(pkc1); - _prb_refresh_rx_retire_blk_timer(pkc1); - - smp_wmb(); - - return; - } + /* We could have just memset this but we will lose the + * flexibility of making the priv area sticky + */ + BLOCK_SNUM(pbd1) = pkc1->knxt_seq_num++; + BLOCK_NUM_PKTS(pbd1) = 0; + BLOCK_LEN(pbd1) = BLK_PLUS_PRIV(pkc1->blk_sizeof_priv); + getnstimeofday(&ts); + h1->ts_first_pkt.ts_sec = ts.tv_sec; + h1->ts_first_pkt.ts_nsec = ts.tv_nsec; + pkc1->pkblk_start = (char *)pbd1; + pkc1->nxt_offset = (char *)(pkc1->pkblk_start + + BLK_PLUS_PRIV(pkc1->blk_sizeof_priv)); + BLOCK_O2FP(pbd1) = (__u32)BLK_PLUS_PRIV(pkc1->blk_sizeof_priv); + BLOCK_O2PRIV(pbd1) = BLK_HDR_LEN; + pbd1->version = pkc1->version; + pkc1->prev = pkc1->nxt_offset; + pkc1->pkblk_end = pkc1->pkblk_start + pkc1->kblk_size; + prb_thaw_queue(pkc1); + _prb_refresh_rx_retire_blk_timer(pkc1); - WARN(1, "ERROR block:%p is NOT FREE status:%d kactive_blk_num:%d\n", - pbd1, BLOCK_STATUS(pbd1), pkc1->kactive_blk_num); - dump_stack(); - BUG(); + smp_wmb(); } /* @@ -933,10 +923,6 @@ static void prb_retire_current_block(struct tpacket_kbdq_core *pkc, prb_close_block(pkc, pbd, po, status); return; } - - WARN(1, "ERROR-pbd[%d]:%p\n", pkc->kactive_blk_num, pbd); - dump_stack(); - BUG(); } static int prb_curr_blk_in_use(struct tpacket_kbdq_core *pkc, @@ -2450,13 +2436,15 @@ static int packet_release(struct socket *sock) packet_flush_mclist(sk); - memset(&req_u, 0, sizeof(req_u)); - - if (po->rx_ring.pg_vec) + if (po->rx_ring.pg_vec) { + memset(&req_u, 0, sizeof(req_u)); packet_set_ring(sk, &req_u, 1, 0); + } - if (po->tx_ring.pg_vec) + if (po->tx_ring.pg_vec) { + memset(&req_u, 0, sizeof(req_u)); packet_set_ring(sk, &req_u, 1, 1); + } fanout_release(sk); @@ -2860,12 +2848,11 @@ static int packet_getname_spkt(struct socket *sock, struct sockaddr *uaddr, return -EOPNOTSUPP; uaddr->sa_family = AF_PACKET; + memset(uaddr->sa_data, 0, sizeof(uaddr->sa_data)); rcu_read_lock(); dev = dev_get_by_index_rcu(sock_net(sk), pkt_sk(sk)->ifindex); if (dev) - strncpy(uaddr->sa_data, dev->name, 14); - else - memset(uaddr->sa_data, 0, 14); + strlcpy(uaddr->sa_data, dev->name, sizeof(uaddr->sa_data)); rcu_read_unlock(); *uaddr_len = sizeof(*uaddr); diff --git a/net/rds/message.c b/net/rds/message.c index f0a4658f327..aff589cc022 100644 --- a/net/rds/message.c +++ b/net/rds/message.c @@ -197,6 +197,9 @@ struct rds_message *rds_message_alloc(unsigned int extra_len, gfp_t gfp) { struct rds_message *rm; + if (extra_len > KMALLOC_MAX_SIZE - sizeof(struct rds_message)) + return NULL; + rm = kzalloc(sizeof(struct rds_message) + extra_len, gfp); if (!rm) goto out; diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index c4719ce604c..7f645d11579 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c @@ -1257,6 +1257,7 @@ static int rose_recvmsg(struct kiocb *iocb, struct socket *sock, skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); if (srose != NULL) { + memset(srose, 0, msg->msg_namelen); srose->srose_family = AF_ROSE; srose->srose_addr = rose->dest_addr; srose->srose_call = rose->dest_call; diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c index 60f8f616e8f..57827bf0682 100644 --- a/net/sched/act_ipt.c +++ b/net/sched/act_ipt.c @@ -8,7 +8,7 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * - * Copyright: Jamal Hadi Salim (2002-4) + * Copyright: Jamal Hadi Salim (2002-13) */ #include @@ -299,17 +299,44 @@ static struct tc_action_ops act_ipt_ops = { .walk = tcf_generic_walker }; -MODULE_AUTHOR("Jamal Hadi Salim(2002-4)"); +static struct tc_action_ops act_xt_ops = { + .kind = "xt", + .hinfo = &ipt_hash_info, + .type = TCA_ACT_IPT, + .capab = TCA_CAP_NONE, + .owner = THIS_MODULE, + .act = tcf_ipt, + .dump = tcf_ipt_dump, + .cleanup = tcf_ipt_cleanup, + .lookup = tcf_hash_search, + .init = tcf_ipt_init, + .walk = tcf_generic_walker +}; + +MODULE_AUTHOR("Jamal Hadi Salim(2002-13)"); MODULE_DESCRIPTION("Iptables target actions"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("act_xt"); static int __init ipt_init_module(void) { - return tcf_register_action(&act_ipt_ops); + int ret1, ret2; + ret1 = tcf_register_action(&act_xt_ops); + if (ret1 < 0) + printk("Failed to load xt action\n"); + ret2 = tcf_register_action(&act_ipt_ops); + if (ret2 < 0) + printk("Failed to load ipt action\n"); + + if (ret1 < 0 && ret2 < 0) + return ret1; + else + return 0; } static void __exit ipt_cleanup_module(void) { + tcf_unregister_action(&act_xt_ops); tcf_unregister_action(&act_ipt_ops); } diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c index e25e49061a0..6e38ef0040b 100644 --- a/net/sched/sch_atm.c +++ b/net/sched/sch_atm.c @@ -606,6 +606,7 @@ static int atm_tc_dump_class(struct Qdisc *sch, unsigned long cl, struct sockaddr_atmpvc pvc; int state; + memset(&pvc, 0, sizeof(pvc)); pvc.sap_family = AF_ATMPVC; pvc.sap_addr.itf = flow->vcc->dev ? flow->vcc->dev->number : -1; pvc.sap_addr.vpi = flow->vcc->vpi; diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c index 599f67ada1e..7f599447b3c 100644 --- a/net/sched/sch_cbq.c +++ b/net/sched/sch_cbq.c @@ -963,8 +963,11 @@ cbq_dequeue(struct Qdisc *sch) cbq_update(q); if ((incr -= incr2) < 0) incr = 0; + q->now += incr; + } else { + if (now > q->now) + q->now = now; } - q->now += incr; q->now_rt = now; for (;;) { @@ -1464,6 +1467,7 @@ static int cbq_dump_wrr(struct sk_buff *skb, struct cbq_class *cl) unsigned char *b = skb_tail_pointer(skb); struct tc_cbq_wrropt opt; + memset(&opt, 0, sizeof(opt)); opt.flags = 0; opt.allot = cl->allot; opt.priority = cl->priority + 1; diff --git a/net/sctp/associola.c b/net/sctp/associola.c index acd2edbc073..3c04692d699 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -1050,7 +1050,7 @@ struct sctp_transport *sctp_assoc_lookup_tsn(struct sctp_association *asoc, transports) { if (transport == active) - break; + continue; list_for_each_entry(chunk, &transport->transmitted, transmitted_list) { if (key == chunk->subh.data_hdr->tsn) { diff --git a/net/sctp/auth.c b/net/sctp/auth.c index bf812048cf6..333926d4d35 100644 --- a/net/sctp/auth.c +++ b/net/sctp/auth.c @@ -71,7 +71,7 @@ void sctp_auth_key_put(struct sctp_auth_bytes *key) return; if (atomic_dec_and_test(&key->refcnt)) { - kfree(key); + kzfree(key); SCTP_DBG_OBJCNT_DEC(keys); } } diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c index 68a385d7c3b..58cd035dcd2 100644 --- a/net/sctp/endpointola.c +++ b/net/sctp/endpointola.c @@ -248,6 +248,8 @@ void sctp_endpoint_free(struct sctp_endpoint *ep) /* Final destructor for endpoint. */ static void sctp_endpoint_destroy(struct sctp_endpoint *ep) { + int i; + SCTP_ASSERT(ep->base.dead, "Endpoint is not dead", return); /* Free up the HMAC transform. */ @@ -270,6 +272,9 @@ static void sctp_endpoint_destroy(struct sctp_endpoint *ep) sctp_inq_free(&ep->base.inqueue); sctp_bind_addr_free(&ep->base.bind_addr); + for (i = 0; i < SCTP_HOW_MANY_SECRETS; ++i) + memset(&ep->secret_key[i], 0, SCTP_SECRET_SIZE); + /* Remove and free the port */ if (sctp_sk(ep->base.sk)->bind_hash) sctp_put_port(ep->base.sk); diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index cfeb1d4a1ee..3dd7207d33a 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c @@ -205,6 +205,8 @@ static inline int sctp_cacc_skip(struct sctp_transport *primary, */ void sctp_outq_init(struct sctp_association *asoc, struct sctp_outq *q) { + memset(q, 0, sizeof(struct sctp_outq)); + q->asoc = asoc; INIT_LIST_HEAD(&q->out_chunk_list); INIT_LIST_HEAD(&q->control_chunk_list); @@ -212,18 +214,12 @@ void sctp_outq_init(struct sctp_association *asoc, struct sctp_outq *q) INIT_LIST_HEAD(&q->sacked); INIT_LIST_HEAD(&q->abandoned); - q->fast_rtx = 0; - q->outstanding_bytes = 0; q->empty = 1; - q->cork = 0; - - q->malloced = 0; - q->out_qlen = 0; } /* Free the outqueue structure and any related pending chunks. */ -void sctp_outq_teardown(struct sctp_outq *q) +static void __sctp_outq_teardown(struct sctp_outq *q) { struct sctp_transport *transport; struct list_head *lchunk, *temp; @@ -276,8 +272,6 @@ void sctp_outq_teardown(struct sctp_outq *q) sctp_chunk_free(chunk); } - q->error = 0; - /* Throw away any leftover control chunks. */ list_for_each_entry_safe(chunk, tmp, &q->control_chunk_list, list) { list_del_init(&chunk->list); @@ -285,11 +279,17 @@ void sctp_outq_teardown(struct sctp_outq *q) } } +void sctp_outq_teardown(struct sctp_outq *q) +{ + __sctp_outq_teardown(q); + sctp_outq_init(q->asoc, q); +} + /* Free the outqueue structure and any related pending chunks. */ void sctp_outq_free(struct sctp_outq *q) { /* Throw away leftover chunks. */ - sctp_outq_teardown(q); + __sctp_outq_teardown(q); /* If we were kmalloc()'d, free the memory. */ if (q->malloced) diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 891f5db8cc3..cb1c4303a07 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -2044,7 +2044,7 @@ sctp_disposition_t sctp_sf_do_5_2_4_dupcook(const struct sctp_endpoint *ep, } /* Delete the tempory new association. */ - sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, SCTP_ASOC(new_asoc)); + sctp_add_cmd_sf(commands, SCTP_CMD_SET_ASOC, SCTP_ASOC(new_asoc)); sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL()); /* Restore association pointer to provide SCTP command interpeter diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 74053554a85..4bc6e0bbf97 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -3375,7 +3375,7 @@ static int sctp_setsockopt_auth_key(struct sock *sk, ret = sctp_auth_set_key(sctp_sk(sk)->ep, asoc, authkey); out: - kfree(authkey); + kzfree(authkey); return ret; } @@ -3929,6 +3929,12 @@ SCTP_STATIC void sctp_destroy_sock(struct sock *sk) /* Release our hold on the endpoint. */ sp = sctp_sk(sk); + /* This could happen during socket init, thus we bail out + * early, since the rest of the below is not setup either. + */ + if (sp->ep == NULL) + return; + if (sp->do_auto_asconf) { sp->do_auto_asconf = 0; list_del(&sp->auto_asconf_list); diff --git a/net/socket.c b/net/socket.c index 6d042da3efb..eb0f15d6b81 100644 --- a/net/socket.c +++ b/net/socket.c @@ -1899,9 +1899,9 @@ struct used_address { unsigned int name_len; }; -static int __sys_sendmsg(struct socket *sock, struct msghdr __user *msg, - struct msghdr *msg_sys, unsigned flags, - struct used_address *used_address) +static int ___sys_sendmsg(struct socket *sock, struct msghdr __user *msg, + struct msghdr *msg_sys, unsigned flags, + struct used_address *used_address) { struct compat_msghdr __user *msg_compat = (struct compat_msghdr __user *)msg; @@ -2017,22 +2017,30 @@ static int __sys_sendmsg(struct socket *sock, struct msghdr __user *msg, * BSD sendmsg interface */ -SYSCALL_DEFINE3(sendmsg, int, fd, struct msghdr __user *, msg, unsigned, flags) +long __sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags) { int fput_needed, err; struct msghdr msg_sys; - struct socket *sock = sockfd_lookup_light(fd, &err, &fput_needed); + struct socket *sock; + sock = sockfd_lookup_light(fd, &err, &fput_needed); if (!sock) goto out; - err = __sys_sendmsg(sock, msg, &msg_sys, flags, NULL); + err = ___sys_sendmsg(sock, msg, &msg_sys, flags, NULL); fput_light(sock->file, fput_needed); out: return err; } +SYSCALL_DEFINE3(sendmsg, int, fd, struct msghdr __user *, msg, unsigned int, flags) +{ + if (flags & MSG_CMSG_COMPAT) + return -EINVAL; + return __sys_sendmsg(fd, msg, flags); +} + /* * Linux sendmmsg interface */ @@ -2063,15 +2071,16 @@ int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, while (datagrams < vlen) { if (MSG_CMSG_COMPAT & flags) { - err = __sys_sendmsg(sock, (struct msghdr __user *)compat_entry, - &msg_sys, flags, &used_address); + err = ___sys_sendmsg(sock, (struct msghdr __user *)compat_entry, + &msg_sys, flags, &used_address); if (err < 0) break; err = __put_user(err, &compat_entry->msg_len); ++compat_entry; } else { - err = __sys_sendmsg(sock, (struct msghdr __user *)entry, - &msg_sys, flags, &used_address); + err = ___sys_sendmsg(sock, + (struct msghdr __user *)entry, + &msg_sys, flags, &used_address); if (err < 0) break; err = put_user(err, &entry->msg_len); @@ -2095,11 +2104,13 @@ int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg, unsigned int, vlen, unsigned int, flags) { + if (flags & MSG_CMSG_COMPAT) + return -EINVAL; return __sys_sendmmsg(fd, mmsg, vlen, flags); } -static int __sys_recvmsg(struct socket *sock, struct msghdr __user *msg, - struct msghdr *msg_sys, unsigned flags, int nosec) +static int ___sys_recvmsg(struct socket *sock, struct msghdr __user *msg, + struct msghdr *msg_sys, unsigned flags, int nosec) { struct compat_msghdr __user *msg_compat = (struct compat_msghdr __user *)msg; @@ -2192,23 +2203,31 @@ static int __sys_recvmsg(struct socket *sock, struct msghdr __user *msg, * BSD recvmsg interface */ -SYSCALL_DEFINE3(recvmsg, int, fd, struct msghdr __user *, msg, - unsigned int, flags) +long __sys_recvmsg(int fd, struct msghdr __user *msg, unsigned flags) { int fput_needed, err; struct msghdr msg_sys; - struct socket *sock = sockfd_lookup_light(fd, &err, &fput_needed); + struct socket *sock; + sock = sockfd_lookup_light(fd, &err, &fput_needed); if (!sock) goto out; - err = __sys_recvmsg(sock, msg, &msg_sys, flags, 0); + err = ___sys_recvmsg(sock, msg, &msg_sys, flags, 0); fput_light(sock->file, fput_needed); out: return err; } +SYSCALL_DEFINE3(recvmsg, int, fd, struct msghdr __user *, msg, + unsigned int, flags) +{ + if (flags & MSG_CMSG_COMPAT) + return -EINVAL; + return __sys_recvmsg(fd, msg, flags); +} + /* * Linux recvmmsg interface */ @@ -2246,17 +2265,18 @@ int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, * No need to ask LSM for more than the first datagram. */ if (MSG_CMSG_COMPAT & flags) { - err = __sys_recvmsg(sock, (struct msghdr __user *)compat_entry, - &msg_sys, flags & ~MSG_WAITFORONE, - datagrams); + err = ___sys_recvmsg(sock, (struct msghdr __user *)compat_entry, + &msg_sys, flags & ~MSG_WAITFORONE, + datagrams); if (err < 0) break; err = __put_user(err, &compat_entry->msg_len); ++compat_entry; } else { - err = __sys_recvmsg(sock, (struct msghdr __user *)entry, - &msg_sys, flags & ~MSG_WAITFORONE, - datagrams); + err = ___sys_recvmsg(sock, + (struct msghdr __user *)entry, + &msg_sys, flags & ~MSG_WAITFORONE, + datagrams); if (err < 0) break; err = put_user(err, &entry->msg_len); @@ -2323,6 +2343,9 @@ SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg, int datagrams; struct timespec timeout_sys; + if (flags & MSG_CMSG_COMPAT) + return -EINVAL; + if (!timeout) return __sys_recvmmsg(fd, mmsg, vlen, flags, NULL); diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index 3d5c9b912c7..202db75ee8f 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c @@ -143,6 +143,8 @@ static void __rpc_add_wait_queue(struct rpc_wait_queue *queue, list_add_tail(&task->u.tk_wait.list, &queue->tasks[0]); task->tk_waitqueue = queue; queue->qlen++; + /* barrier matches the read in rpc_wake_up_task_queue_locked() */ + smp_wmb(); rpc_set_queued(task); dprintk("RPC: %5u added to queue %p \"%s\"\n", @@ -399,8 +401,11 @@ static void __rpc_do_wake_up_task(struct rpc_wait_queue *queue, struct rpc_task */ static void rpc_wake_up_task_queue_locked(struct rpc_wait_queue *queue, struct rpc_task *task) { - if (RPC_IS_QUEUED(task) && task->tk_waitqueue == queue) - __rpc_do_wake_up_task(queue, task); + if (RPC_IS_QUEUED(task)) { + smp_rmb(); + if (task->tk_waitqueue == queue) + __rpc_do_wake_up_task(queue, task); + } } /* diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c index fd9b2889aa9..aec7dbb9d3d 100644 --- a/net/sunrpc/svc_xprt.c +++ b/net/sunrpc/svc_xprt.c @@ -817,7 +817,6 @@ static void svc_age_temp_xprts(unsigned long closure) struct svc_serv *serv = (struct svc_serv *)closure; struct svc_xprt *xprt; struct list_head *le, *next; - LIST_HEAD(to_be_aged); dprintk("svc_age_temp_xprts\n"); @@ -838,25 +837,15 @@ static void svc_age_temp_xprts(unsigned long closure) if (atomic_read(&xprt->xpt_ref.refcount) > 1 || test_bit(XPT_BUSY, &xprt->xpt_flags)) continue; - svc_xprt_get(xprt); - list_move(le, &to_be_aged); + list_del_init(le); set_bit(XPT_CLOSE, &xprt->xpt_flags); set_bit(XPT_DETACHED, &xprt->xpt_flags); - } - spin_unlock_bh(&serv->sv_lock); - - while (!list_empty(&to_be_aged)) { - le = to_be_aged.next; - /* fiddling the xpt_list node is safe 'cos we're XPT_DETACHED */ - list_del_init(le); - xprt = list_entry(le, struct svc_xprt, xpt_list); - dprintk("queuing xprt %p for closing\n", xprt); /* a thread will dequeue and close it soon */ svc_xprt_enqueue(xprt); - svc_xprt_put(xprt); } + spin_unlock_bh(&serv->sv_lock); mod_timer(&serv->sv_temptimer, jiffies + svc_conn_age_period * HZ); } diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index feea4741edd..f1a63c1885d 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c @@ -485,13 +485,17 @@ EXPORT_SYMBOL_GPL(xprt_wake_pending_tasks); * xprt_wait_for_buffer_space - wait for transport output buffer to clear * @task: task to be put to sleep * @action: function pointer to be executed after wait + * + * Note that we only set the timer for the case of RPC_IS_SOFT(), since + * we don't in general want to force a socket disconnection due to + * an incomplete RPC call transmission. */ void xprt_wait_for_buffer_space(struct rpc_task *task, rpc_action action) { struct rpc_rqst *req = task->tk_rqstp; struct rpc_xprt *xprt = req->rq_xprt; - task->tk_timeout = req->rq_timeout; + task->tk_timeout = RPC_IS_SOFT(task) ? req->rq_timeout : 0; rpc_sleep_on(&xprt->pending, task, action); } EXPORT_SYMBOL_GPL(xprt_wait_for_buffer_space); diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 29e957f6445..1441ab70b98 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -829,6 +829,7 @@ static void set_orig_addr(struct msghdr *m, struct tipc_msg *msg) if (addr) { addr->family = AF_TIPC; addr->addrtype = TIPC_ADDR_ID; + memset(&addr->addr, 0, sizeof(addr->addr)); addr->addr.id.ref = msg_origport(msg); addr->addr.id.node = msg_orignode(msg); addr->addr.name.domain = 0; /* could leave uninitialized */ @@ -948,6 +949,9 @@ static int recv_msg(struct kiocb *iocb, struct socket *sock, goto exit; } + /* will be updated in set_orig_addr() if needed */ + m->msg_namelen = 0; + timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT); restart: @@ -1074,6 +1078,9 @@ static int recv_stream(struct kiocb *iocb, struct socket *sock, goto exit; } + /* will be updated in set_orig_addr() if needed */ + m->msg_namelen = 0; + target = sock_rcvlowat(sk, flags & MSG_WAITALL, buf_len); timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT); restart: diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index a3fe72ad969..7b5f7751201 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -375,7 +375,7 @@ static void unix_sock_destructor(struct sock *sk) #endif } -static int unix_release_sock(struct sock *sk, int embrion) +static void unix_release_sock(struct sock *sk, int embrion) { struct unix_sock *u = unix_sk(sk); struct path path; @@ -444,8 +444,6 @@ static int unix_release_sock(struct sock *sk, int embrion) if (unix_tot_inflight) unix_gc(); /* Garbage collect fds */ - - return 0; } static void init_peercred(struct sock *sk) @@ -695,9 +693,10 @@ static int unix_release(struct socket *sock) if (!sk) return 0; + unix_release_sock(sk, 0); sock->sk = NULL; - return unix_release_sock(sk, 0); + return 0; } static int unix_autobind(struct socket *sock) @@ -1988,7 +1987,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, if ((UNIXCB(skb).pid != siocb->scm->pid) || (UNIXCB(skb).cred != siocb->scm->cred)) break; - } else { + } else if (test_bit(SOCK_PASSCRED, &sock->flags)) { /* Copy credentials */ scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).cred); check_creds = 1; diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 13fcc641e13..d4be61444b5 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -5368,12 +5368,14 @@ EXPORT_SYMBOL(cfg80211_testmode_alloc_event_skb); void cfg80211_testmode_event(struct sk_buff *skb, gfp_t gfp) { + struct cfg80211_registered_device *rdev = ((void **)skb->cb)[0]; void *hdr = ((void **)skb->cb)[1]; struct nlattr *data = ((void **)skb->cb)[2]; nla_nest_end(skb, data); genlmsg_end(skb, hdr); - genlmsg_multicast(skb, 0, nl80211_testmode_mcgrp.id, gfp); + genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), skb, 0, + nl80211_testmode_mcgrp.id, gfp); } EXPORT_SYMBOL(cfg80211_testmode_event); #endif @@ -8092,7 +8094,8 @@ void nl80211_send_mgmt_tx_status(struct cfg80211_registered_device *rdev, genlmsg_end(msg, hdr); - genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, gfp); + genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, + nl80211_mlme_mcgrp.id, gfp); return; nla_put_failure: diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 012d2f4eaf5..75e423f1da9 100755 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -862,7 +862,7 @@ static void handle_channel(struct wiphy *wiphy, return; REG_DBG_PRINT("Disabling freq %d MHz\n", chan->center_freq); - chan->flags = IEEE80211_CHAN_DISABLED; + chan->flags |= IEEE80211_CHAN_DISABLED; return; } diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c index a306bc66000..b943e3e71bd 100644 --- a/net/x25/af_x25.c +++ b/net/x25/af_x25.c @@ -1586,11 +1586,11 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) case SIOCX25CALLACCPTAPPRV: { rc = -EINVAL; lock_sock(sk); - if (sk->sk_state != TCP_CLOSE) - break; - clear_bit(X25_ACCPT_APPRV_FLAG, &x25->flags); + if (sk->sk_state == TCP_CLOSE) { + clear_bit(X25_ACCPT_APPRV_FLAG, &x25->flags); + rc = 0; + } release_sock(sk); - rc = 0; break; } @@ -1598,14 +1598,15 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) rc = -EINVAL; lock_sock(sk); if (sk->sk_state != TCP_ESTABLISHED) - break; + goto out_sendcallaccpt_release; /* must call accptapprv above */ if (test_bit(X25_ACCPT_APPRV_FLAG, &x25->flags)) - break; + goto out_sendcallaccpt_release; x25_write_internal(sk, X25_CALL_ACCEPTED); x25->state = X25_STATE_3; - release_sock(sk); rc = 0; +out_sendcallaccpt_release: + release_sock(sk); break; } diff --git a/security/keys/compat.c b/security/keys/compat.c index 4c48e13448f..1b0b7bfe63f 100644 --- a/security/keys/compat.c +++ b/security/keys/compat.c @@ -40,12 +40,12 @@ long compat_keyctl_instantiate_key_iov( ARRAY_SIZE(iovstack), iovstack, &iov, 1); if (ret < 0) - return ret; + goto err; if (ret == 0) goto no_payload_free; ret = keyctl_instantiate_key_common(id, iov, ioc, ret, ringid); - +err: if (iov != iovstack) kfree(iov); return ret; diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index fb767c6cd99..dfc8c229e35 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c @@ -1081,12 +1081,12 @@ long keyctl_instantiate_key_iov(key_serial_t id, ret = rw_copy_check_uvector(WRITE, _payload_iov, ioc, ARRAY_SIZE(iovstack), iovstack, &iov, 1); if (ret < 0) - return ret; + goto err; if (ret == 0) goto no_payload_free; ret = keyctl_instantiate_key_common(id, iov, ioc, ret, ringid); - +err: if (iov != iovstack) kfree(iov); return ret; diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index be7ecb2018d..adbfddd7e00 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c @@ -54,7 +54,7 @@ int install_user_keyrings(void) kenter("%p{%u}", user, user->uid); - if (user->uid_keyring) { + if (user->uid_keyring && user->session_keyring) { kleave(" = 0 [exist]"); return 0; } diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c index 48665ecd119..8ab29515451 100644 --- a/security/selinux/xfrm.c +++ b/security/selinux/xfrm.c @@ -310,7 +310,7 @@ int selinux_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx, if (old_ctx) { new_ctx = kmalloc(sizeof(*old_ctx) + old_ctx->ctx_len, - GFP_KERNEL); + GFP_ATOMIC); if (!new_ctx) return -ENOMEM; diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index f178b786da8..efb6f6e20e0 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -3247,18 +3247,10 @@ EXPORT_SYMBOL_GPL(snd_pcm_lib_default_mmap); int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream, struct vm_area_struct *area) { - long size; - unsigned long offset; + struct snd_pcm_runtime *runtime = substream->runtime;; area->vm_page_prot = pgprot_noncached(area->vm_page_prot); - area->vm_flags |= VM_IO; - size = area->vm_end - area->vm_start; - offset = area->vm_pgoff << PAGE_SHIFT; - if (io_remap_pfn_range(area, area->vm_start, - (substream->runtime->dma_addr + offset) >> PAGE_SHIFT, - size, area->vm_page_prot)) - return -EAGAIN; - return 0; + return vm_iomap_memory(area, runtime->dma_addr, runtime->dma_bytes); } EXPORT_SYMBOL(snd_pcm_lib_mmap_iomem); diff --git a/sound/core/seq/seq_timer.c b/sound/core/seq/seq_timer.c index 160b1bd0cd6..24d44b2f61a 100644 --- a/sound/core/seq/seq_timer.c +++ b/sound/core/seq/seq_timer.c @@ -290,10 +290,10 @@ int snd_seq_timer_open(struct snd_seq_queue *q) tid.device = SNDRV_TIMER_GLOBAL_SYSTEM; err = snd_timer_open(&t, str, &tid, q->queue); } - if (err < 0) { - snd_printk(KERN_ERR "seq fatal error: cannot create timer (%i)\n", err); - return err; - } + } + if (err < 0) { + snd_printk(KERN_ERR "seq fatal error: cannot create timer (%i)\n", err); + return err; } t->callback = snd_seq_timer_interrupt; t->callback_data = q; diff --git a/sound/core/vmaster.c b/sound/core/vmaster.c index 857586135d1..0097f3619fa 100644 --- a/sound/core/vmaster.c +++ b/sound/core/vmaster.c @@ -213,7 +213,10 @@ static int slave_put(struct snd_kcontrol *kcontrol, } if (!changed) return 0; - return slave_put_val(slave, ucontrol); + err = slave_put_val(slave, ucontrol); + if (err < 0) + return err; + return 1; } static int slave_tlv_cmd(struct snd_kcontrol *kcontrol, diff --git a/sound/oss/Kconfig b/sound/oss/Kconfig index 5849b129e50..1a964025443 100644 --- a/sound/oss/Kconfig +++ b/sound/oss/Kconfig @@ -250,6 +250,7 @@ config MSND_FIFOSIZE menuconfig SOUND_OSS tristate "OSS sound modules" depends on ISA_DMA_API && VIRT_TO_BUS + depends on !GENERIC_ISA_DMA_SUPPORT_BROKEN help OSS is the Open Sound System suite of sound card drivers. They make sound programming easier since they provide a common API. Say Y or diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c index bdd6164e9c7..131fd1f5db0 100644 --- a/sound/pci/ali5451/ali5451.c +++ b/sound/pci/ali5451/ali5451.c @@ -1435,7 +1435,7 @@ static snd_pcm_uframes_t snd_ali_pointer(struct snd_pcm_substream *substream) spin_lock(&codec->reg_lock); if (!pvoice->running) { - spin_unlock_irq(&codec->reg_lock); + spin_unlock(&codec->reg_lock); return 0; } outb(pvoice->number, ALI_REG(codec, ALI_GC_CIR)); diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index cec747998e5..c74a044284b 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -165,7 +165,7 @@ const char *snd_hda_get_jack_type(u32 cfg) "Line Out", "Speaker", "HP Out", "CD", "SPDIF Out", "Digital Out", "Modem Line", "Modem Hand", "Line In", "Aux", "Mic", "Telephony", - "SPDIF In", "Digitial In", "Reserved", "Other" + "SPDIF In", "Digital In", "Reserved", "Other" }; return jack_types[(cfg & AC_DEFCFG_DEVICE) @@ -617,6 +617,9 @@ int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex) struct hda_bus_unsolicited *unsol; unsigned int wp; + if (!bus || !bus->workq) + return 0; + trace_hda_unsol_event(bus, res, res_ex); unsol = bus->unsol; if (!unsol) @@ -2910,7 +2913,7 @@ static unsigned int convert_to_spdif_status(unsigned short val) if (val & AC_DIG1_PROFESSIONAL) sbits |= IEC958_AES0_PROFESSIONAL; if (sbits & IEC958_AES0_PROFESSIONAL) { - if (sbits & AC_DIG1_EMPHASIS) + if (val & AC_DIG1_EMPHASIS) sbits |= IEC958_AES0_PRO_EMPHASIS_5015; } else { if (val & AC_DIG1_EMPHASIS) diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c index 4c054f4486b..86f6468cb23 100644 --- a/sound/pci/hda/hda_eld.c +++ b/sound/pci/hda/hda_eld.c @@ -322,7 +322,7 @@ int snd_hdmi_get_eld(struct hdmi_eld *eld, struct hda_codec *codec, hda_nid_t nid) { int i; - int ret; + int ret = 0; int size; unsigned char *buf; diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 389702708ea..033c4c5977d 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -1177,7 +1177,7 @@ static int patch_cxt5045(struct hda_codec *codec) } if (spec->beep_amp) - snd_hda_attach_beep_device(codec, spec->beep_amp); + snd_hda_attach_beep_device(codec, get_amp_nid_(spec->beep_amp)); return 0; } @@ -1960,7 +1960,7 @@ static int patch_cxt5051(struct hda_codec *codec) } if (spec->beep_amp) - snd_hda_attach_beep_device(codec, spec->beep_amp); + snd_hda_attach_beep_device(codec, get_amp_nid_(spec->beep_amp)); return 0; } @@ -3151,7 +3151,7 @@ static int patch_cxt5066(struct hda_codec *codec) } if (spec->beep_amp) - snd_hda_attach_beep_device(codec, spec->beep_amp); + snd_hda_attach_beep_device(codec, get_amp_nid_(spec->beep_amp)); return 0; } @@ -4501,7 +4501,7 @@ static int patch_conexant_auto(struct hda_codec *codec) spec->capture_stream = &cx_auto_pcm_analog_capture; codec->patch_ops = cx_auto_patch_ops; if (spec->beep_amp) - snd_hda_attach_beep_device(codec, spec->beep_amp); + snd_hda_attach_beep_device(codec, get_amp_nid_(spec->beep_amp)); /* Some laptops with Conexant chips show stalls in S3 resume, * which falls into the single-cmd mode. diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index d1b805aefa5..02a6e3f481e 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -924,8 +924,12 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, if (!static_hdmi_pcm && eld->eld_valid) { snd_hdmi_eld_update_pcm_info(eld, hinfo); if (hinfo->channels_min > hinfo->channels_max || - !hinfo->rates || !hinfo->formats) + !hinfo->rates || !hinfo->formats) { + per_cvt->assigned = 0; + hinfo->nid = 0; + snd_hda_spdif_ctls_unassign(codec, pin_idx); return -ENODEV; + } } /* Store the updated parameters */ @@ -989,6 +993,7 @@ static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll) "HDMI status: Codec=%d Pin=%d Presence_Detect=%d ELD_Valid=%d\n", codec->addr, pin_nid, eld->monitor_present, eld_valid); + eld->eld_valid = false; if (eld_valid) { if (!snd_hdmi_get_eld(eld, codec, pin_nid)) snd_hdmi_show_eld(eld); diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index f7f877626d8..353b32a34b1 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -5440,6 +5440,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = { SND_PCI_QUIRK(0x1043, 0x835f, "Asus Eee 1601", ALC888_FIXUP_EEE1601), SND_PCI_QUIRK(0x104d, 0x9047, "Sony Vaio TT", ALC889_FIXUP_VAIO_TT), SND_PCI_QUIRK(0x104d, 0x905a, "Sony Vaio Z", ALC882_FIXUP_NO_PRIMARY_HP), + SND_PCI_QUIRK(0x104d, 0x9043, "Sony Vaio VGC-LN51JGB", ALC882_FIXUP_NO_PRIMARY_HP), /* All Apple entries are in codec SSIDs */ SND_PCI_QUIRK(0x106b, 0x00a0, "MacBookPro 3,1", ALC889_FIXUP_MBP_VREF), @@ -6628,7 +6629,8 @@ static int alc662_parse_auto_config(struct hda_codec *codec) const hda_nid_t *ssids; if (codec->vendor_id == 0x10ec0272 || codec->vendor_id == 0x10ec0663 || - codec->vendor_id == 0x10ec0665 || codec->vendor_id == 0x10ec0670) + codec->vendor_id == 0x10ec0665 || codec->vendor_id == 0x10ec0670 || + codec->vendor_id == 0x10ec0671) ssids = alc663_ssids; else ssids = alc662_ssids; @@ -7055,6 +7057,7 @@ static const struct hda_codec_preset snd_hda_preset_realtek[] = { { .id = 0x10ec0665, .name = "ALC665", .patch = patch_alc662 }, { .id = 0x10ec0668, .name = "ALC668", .patch = patch_alc662 }, { .id = 0x10ec0670, .name = "ALC670", .patch = patch_alc662 }, + { .id = 0x10ec0671, .name = "ALC671", .patch = patch_alc662 }, { .id = 0x10ec0680, .name = "ALC680", .patch = patch_alc680 }, { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 }, { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 }, diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c index 132a86e09d0..08c7f3a91a8 100644 --- a/sound/pci/ice1712/ice1712.c +++ b/sound/pci/ice1712/ice1712.c @@ -2595,6 +2595,8 @@ static int __devinit snd_ice1712_create(struct snd_card *card, snd_ice1712_proc_init(ice); synchronize_irq(pci->irq); + card->private_data = ice; + err = pci_request_regions(pci, "ICE1712"); if (err < 0) { kfree(ice); diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c index b4819d5e41d..64da910ac34 100644 --- a/sound/pci/rme32.c +++ b/sound/pci/rme32.c @@ -1017,7 +1017,7 @@ static int snd_rme32_capture_close(struct snd_pcm_substream *substream) spin_lock_irq(&rme32->lock); rme32->capture_substream = NULL; rme32->capture_periodsize = 0; - spin_unlock(&rme32->lock); + spin_unlock_irq(&rme32->lock); return 0; } diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c index af7324b79dd..8df4597ceca 100644 --- a/sound/soc/codecs/max98088.c +++ b/sound/soc/codecs/max98088.c @@ -1594,7 +1594,7 @@ static int max98088_dai2_digital_mute(struct snd_soc_dai *codec_dai, int mute) static void max98088_sync_cache(struct snd_soc_codec *codec) { - u16 *reg_cache = codec->reg_cache; + u8 *reg_cache = codec->reg_cache; int i; if (!codec->cache_sync) @@ -2006,7 +2006,7 @@ static int max98088_probe(struct snd_soc_codec *codec) ret); goto err_access; } - dev_info(codec->dev, "revision %c\n", ret + 'A'); + dev_info(codec->dev, "revision %c\n", ret - 0x40 + 'A'); snd_soc_write(codec, M98088_REG_51_PWR_SYS, M98088_PWRSV); diff --git a/sound/soc/codecs/sgtl5000.h b/sound/soc/codecs/sgtl5000.h index 8a9f43534b7..d3a68bbfea0 100644 --- a/sound/soc/codecs/sgtl5000.h +++ b/sound/soc/codecs/sgtl5000.h @@ -347,7 +347,7 @@ #define SGTL5000_PLL_INT_DIV_MASK 0xf800 #define SGTL5000_PLL_INT_DIV_SHIFT 11 #define SGTL5000_PLL_INT_DIV_WIDTH 5 -#define SGTL5000_PLL_FRAC_DIV_MASK 0x0700 +#define SGTL5000_PLL_FRAC_DIV_MASK 0x07ff #define SGTL5000_PLL_FRAC_DIV_SHIFT 0 #define SGTL5000_PLL_FRAC_DIV_WIDTH 11 diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c index 8e0cf146a68..9932aacaa5b 100644 --- a/sound/soc/codecs/wm2200.c +++ b/sound/soc/codecs/wm2200.c @@ -990,9 +990,9 @@ SOC_DOUBLE_R_TLV("IN3 Volume", WM2200_IN3L_CONTROL, WM2200_IN3R_CONTROL, SOC_DOUBLE_R("IN1 Digital Switch", WM2200_ADC_DIGITAL_VOLUME_1L, WM2200_ADC_DIGITAL_VOLUME_1R, WM2200_IN1L_MUTE_SHIFT, 1, 1), -SOC_DOUBLE_R("IN2 Digital Switch", WM2200_ADC_DIGITAL_VOLUME_1L, +SOC_DOUBLE_R("IN2 Digital Switch", WM2200_ADC_DIGITAL_VOLUME_2L, WM2200_ADC_DIGITAL_VOLUME_2R, WM2200_IN2L_MUTE_SHIFT, 1, 1), -SOC_DOUBLE_R("IN3 Digital Switch", WM2200_ADC_DIGITAL_VOLUME_1L, +SOC_DOUBLE_R("IN3 Digital Switch", WM2200_ADC_DIGITAL_VOLUME_3L, WM2200_ADC_DIGITAL_VOLUME_3R, WM2200_IN3L_MUTE_SHIFT, 1, 1), SOC_DOUBLE_R_TLV("IN1 Digital Volume", WM2200_ADC_DIGITAL_VOLUME_1L, diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index c91fb2f99c1..7775854212f 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c @@ -1082,6 +1082,8 @@ static const struct snd_soc_dapm_route wm8903_intercon[] = { { "ROP", NULL, "Right Speaker PGA" }, { "RON", NULL, "Right Speaker PGA" }, + { "Charge Pump", NULL, "CLK_DSP" }, + { "Left Headphone Output PGA", NULL, "Charge Pump" }, { "Right Headphone Output PGA", NULL, "Charge Pump" }, { "Left Line Output PGA", NULL, "Charge Pump" }, diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 96f6f9faa82..e96c6ede7fd 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -1599,7 +1599,6 @@ static int wm8962_put_hp_sw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); - u16 *reg_cache = codec->reg_cache; int ret; /* Apply the update (if any) */ @@ -1608,16 +1607,19 @@ static int wm8962_put_hp_sw(struct snd_kcontrol *kcontrol, return 0; /* If the left PGA is enabled hit that VU bit... */ - if (snd_soc_read(codec, WM8962_PWR_MGMT_2) & WM8962_HPOUTL_PGA_ENA) - return snd_soc_write(codec, WM8962_HPOUTL_VOLUME, - reg_cache[WM8962_HPOUTL_VOLUME]); + ret = snd_soc_read(codec, WM8962_PWR_MGMT_2); + if (ret & WM8962_HPOUTL_PGA_ENA) { + snd_soc_write(codec, WM8962_HPOUTL_VOLUME, + snd_soc_read(codec, WM8962_HPOUTL_VOLUME)); + return 1; + } /* ...otherwise the right. The VU is stereo. */ - if (snd_soc_read(codec, WM8962_PWR_MGMT_2) & WM8962_HPOUTR_PGA_ENA) - return snd_soc_write(codec, WM8962_HPOUTR_VOLUME, - reg_cache[WM8962_HPOUTR_VOLUME]); + if (ret & WM8962_HPOUTR_PGA_ENA) + snd_soc_write(codec, WM8962_HPOUTR_VOLUME, + snd_soc_read(codec, WM8962_HPOUTR_VOLUME)); - return 0; + return 1; } /* The VU bits for the speakers are in a different register to the mute @@ -3363,7 +3365,6 @@ static int wm8962_probe(struct snd_soc_codec *codec) int ret; struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); struct wm8962_pdata *pdata = dev_get_platdata(codec->dev); - u16 *reg_cache = codec->reg_cache; int i, trigger, irq_pol; bool dmicclk, dmicdat; @@ -3421,8 +3422,9 @@ static int wm8962_probe(struct snd_soc_codec *codec) /* Put the speakers into mono mode? */ if (pdata->spk_mono) - reg_cache[WM8962_CLASS_D_CONTROL_2] - |= WM8962_SPK_MONO; + snd_soc_update_bits(codec, WM8962_CLASS_D_CONTROL_2, + WM8962_SPK_MONO_MASK, WM8962_SPK_MONO); + /* Micbias setup, detection enable and detection * threasholds. */ diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 4c471a54893..d9924d76f71 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c @@ -2824,6 +2824,7 @@ static int wm8994_aif3_hw_params(struct snd_pcm_substream *substream, default: return 0; } + break; default: return 0; } diff --git a/sound/soc/sh/dma-sh7760.c b/sound/soc/sh/dma-sh7760.c index 7da20186b19..312715ffa21 100644 --- a/sound/soc/sh/dma-sh7760.c +++ b/sound/soc/sh/dma-sh7760.c @@ -342,8 +342,8 @@ static int camelot_pcm_new(struct snd_soc_pcm_runtime *rtd) return 0; } -static struct snd_soc_platform sh7760_soc_platform = { - .pcm_ops = &camelot_pcm_ops, +static struct snd_soc_platform_driver sh7760_soc_platform = { + .ops = &camelot_pcm_ops, .pcm_new = camelot_pcm_new, .pcm_free = camelot_pcm_free, }; diff --git a/sound/usb/6fire/pcm.c b/sound/usb/6fire/pcm.c index c97d05f0e96..4da9ca9c81b 100644 --- a/sound/usb/6fire/pcm.c +++ b/sound/usb/6fire/pcm.c @@ -540,7 +540,7 @@ static snd_pcm_uframes_t usb6fire_pcm_pointer( snd_pcm_uframes_t ret; if (rt->panic || !sub) - return SNDRV_PCM_STATE_XRUN; + return SNDRV_PCM_POS_XRUN; spin_lock_irqsave(&sub->lock, flags); ret = sub->dma_off; diff --git a/sound/usb/card.c b/sound/usb/card.c index 1e14f6b9996..9530bba56e4 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -151,14 +151,32 @@ static int snd_usb_create_stream(struct snd_usb_audio *chip, int ctrlif, int int return -EINVAL; } + alts = &iface->altsetting[0]; + altsd = get_iface_desc(alts); + + /* + * Android with both accessory and audio interfaces enabled gets the + * interface numbers wrong. + */ + if ((chip->usb_id == USB_ID(0x18d1, 0x2d04) || + chip->usb_id == USB_ID(0x18d1, 0x2d05)) && + interface == 0 && + altsd->bInterfaceClass == USB_CLASS_VENDOR_SPEC && + altsd->bInterfaceSubClass == USB_SUBCLASS_VENDOR_SPEC) { + interface = 2; + iface = usb_ifnum_to_if(dev, interface); + if (!iface) + return -EINVAL; + alts = &iface->altsetting[0]; + altsd = get_iface_desc(alts); + } + if (usb_interface_claimed(iface)) { snd_printdd(KERN_INFO "%d:%d:%d: skipping, already claimed\n", dev->devnum, ctrlif, interface); return -EINVAL; } - alts = &iface->altsetting[0]; - altsd = get_iface_desc(alts); if ((altsd->bInterfaceClass == USB_CLASS_AUDIO || altsd->bInterfaceClass == USB_CLASS_VENDOR_SPEC) && altsd->bInterfaceSubClass == USB_SUBCLASS_MIDISTREAMING) { @@ -615,7 +633,9 @@ int snd_usb_autoresume(struct snd_usb_audio *chip) int err = -ENODEV; down_read(&chip->shutdown_rwsem); - if (!chip->shutdown && !chip->probing) + if (chip->probing) + err = 0; + else if (!chip->shutdown) err = usb_autopm_get_interface(chip->pm_intf); up_read(&chip->shutdown_rwsem); diff --git a/sound/usb/midi.c b/sound/usb/midi.c index 34b9bb7fe87..e5fee1800a4 100644 --- a/sound/usb/midi.c +++ b/sound/usb/midi.c @@ -126,7 +126,6 @@ struct snd_usb_midi { struct snd_usb_midi_in_endpoint *in; } endpoints[MIDI_MAX_ENDPOINTS]; unsigned long input_triggered; - bool autopm_reference; unsigned int opened[2]; unsigned char disconnected; unsigned char input_running; @@ -1040,7 +1039,6 @@ static int substream_open(struct snd_rawmidi_substream *substream, int dir, { struct snd_usb_midi* umidi = substream->rmidi->private_data; struct snd_kcontrol *ctl; - int err; down_read(&umidi->disc_rwsem); if (umidi->disconnected) { @@ -1051,13 +1049,6 @@ static int substream_open(struct snd_rawmidi_substream *substream, int dir, mutex_lock(&umidi->mutex); if (open) { if (!umidi->opened[0] && !umidi->opened[1]) { - err = usb_autopm_get_interface(umidi->iface); - umidi->autopm_reference = err >= 0; - if (err < 0 && err != -EACCES) { - mutex_unlock(&umidi->mutex); - up_read(&umidi->disc_rwsem); - return -EIO; - } if (umidi->roland_load_ctl) { ctl = umidi->roland_load_ctl; ctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE; @@ -1080,8 +1071,6 @@ static int substream_open(struct snd_rawmidi_substream *substream, int dir, snd_ctl_notify(umidi->card, SNDRV_CTL_EVENT_MASK_INFO, &ctl->id); } - if (umidi->autopm_reference) - usb_autopm_put_interface(umidi->iface); } } mutex_unlock(&umidi->mutex); @@ -2256,6 +2245,8 @@ int snd_usbmidi_create(struct snd_card *card, return err; } + usb_autopm_get_interface_no_resume(umidi->iface); + list_add_tail(&umidi->list, midi_list); return 0; } diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index ff596e3532b..2ca7c27bdab 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -711,8 +711,9 @@ static int check_input_term(struct mixer_build *state, int id, struct usb_audio_ case UAC2_CLOCK_SELECTOR: { struct uac_selector_unit_descriptor *d = p1; /* call recursively to retrieve the channel info */ - if (check_input_term(state, d->baSourceID[0], term) < 0) - return -ENODEV; + err = check_input_term(state, d->baSourceID[0], term); + if (err < 0) + return err; term->type = d->bDescriptorSubtype << 16; /* virtual type */ term->id = id; term->name = uac_selector_unit_iSelector(d); @@ -820,7 +821,9 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval, case USB_ID(0x046d, 0x0808): case USB_ID(0x046d, 0x0809): + case USB_ID(0x046d, 0x081b): /* HD Webcam c310 */ case USB_ID(0x046d, 0x081d): /* HD Webcam c510 */ + case USB_ID(0x046d, 0x0825): /* HD Webcam c270 */ case USB_ID(0x046d, 0x0991): /* Most audio usb devices lie about volume resolution. * Most Logitech webcams have res = 384. @@ -1263,8 +1266,9 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void return err; /* determine the input source type and name */ - if (check_input_term(state, hdr->bSourceID, &iterm) < 0) - return -EINVAL; + err = check_input_term(state, hdr->bSourceID, &iterm); + if (err < 0) + return err; master_bits = snd_usb_combine_bytes(bmaControls, csize); /* master configuration quirks */ @@ -2025,7 +2029,7 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer) state.oterm.type = le16_to_cpu(desc->wTerminalType); state.oterm.name = desc->iTerminal; err = parse_audio_unit(&state, desc->bSourceID); - if (err < 0) + if (err < 0 && err != -EINVAL) return err; } else { /* UAC_VERSION_2 */ struct uac2_output_terminal_descriptor *desc = p; @@ -2037,12 +2041,12 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer) state.oterm.type = le16_to_cpu(desc->wTerminalType); state.oterm.name = desc->iTerminal; err = parse_audio_unit(&state, desc->bSourceID); - if (err < 0) + if (err < 0 && err != -EINVAL) return err; /* for UAC2, use the same approach to also add the clock selectors */ err = parse_audio_unit(&state, desc->bCSourceID); - if (err < 0) + if (err < 0 && err != -EINVAL) return err; } } diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index 38a607a7ae2..fb95069c043 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -396,7 +396,7 @@ static int snd_nativeinstruments_control_get(struct snd_kcontrol *kcontrol, else ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), bRequest, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, - 0, cpu_to_le16(wIndex), + 0, wIndex, &tmp, sizeof(tmp), 1000); up_read(&mixer->chip->shutdown_rwsem); @@ -427,7 +427,7 @@ static int snd_nativeinstruments_control_put(struct snd_kcontrol *kcontrol, else ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), bRequest, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, - cpu_to_le16(wValue), cpu_to_le16(wIndex), + wValue, wIndex, NULL, 0, 1000); up_read(&mixer->chip->shutdown_rwsem); diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index 63128cd6254..915bc2cf73d 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -157,7 +157,13 @@ .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL }, { - USB_DEVICE(0x046d, 0x0990), + .match_flags = USB_DEVICE_ID_MATCH_DEVICE | + USB_DEVICE_ID_MATCH_INT_CLASS | + USB_DEVICE_ID_MATCH_INT_SUBCLASS, + .idVendor = 0x046d, + .idProduct = 0x0990, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL, .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { .vendor_name = "Logitech, Inc.", .product_name = "QuickCam Pro 9000", @@ -1622,7 +1628,11 @@ YAMAHA_DEVICE(0x7010, "UB99"), USB_DEVICE_VENDOR_SPEC(0x0582, 0x0108), .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { .ifnum = 0, - .type = QUIRK_MIDI_STANDARD_INTERFACE + .type = QUIRK_MIDI_FIXED_ENDPOINT, + .data = & (const struct snd_usb_midi_endpoint_info) { + .out_cables = 0x0007, + .in_cables = 0x0007 + } } }, { @@ -1658,7 +1668,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { /* .vendor_name = "Roland", */ /* .product_name = "A-PRO", */ - .ifnum = 1, + .ifnum = 0, .type = QUIRK_MIDI_FIXED_ENDPOINT, .data = & (const struct snd_usb_midi_endpoint_info) { .out_cables = 0x0003, diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index c46171a2bf2..b7fa802f5ed 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -486,7 +486,7 @@ static int snd_usb_nativeinstruments_boot_quirk(struct usb_device *dev) { int ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 0xaf, USB_TYPE_VENDOR | USB_RECIP_DEVICE, - cpu_to_le16(1), 0, NULL, 0, 1000); + 1, 0, NULL, 0, 1000); if (ret < 0) return ret; diff --git a/sound/usb/stream.c b/sound/usb/stream.c index 5ff8010b2d6..33a335b8a1b 100644 --- a/sound/usb/stream.c +++ b/sound/usb/stream.c @@ -168,6 +168,14 @@ static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip, if (!csep && altsd->bNumEndpoints >= 2) csep = snd_usb_find_desc(alts->endpoint[1].extra, alts->endpoint[1].extralen, NULL, USB_DT_CS_ENDPOINT); + /* + * If we can't locate the USB_DT_CS_ENDPOINT descriptor in the extra + * bytes after the first endpoint, go search the entire interface. + * Some devices have it directly *before* the standard endpoint. + */ + if (!csep) + csep = snd_usb_find_desc(alts->extra, alts->extralen, NULL, USB_DT_CS_ENDPOINT); + if (!csep || csep->bLength < 7 || csep->bDescriptorSubtype != UAC_EP_GENERAL) { snd_printk(KERN_WARNING "%d:%u:%d : no or invalid" diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c index 2984ffb7bac..60a8e29c4fa 100644 --- a/tools/hv/hv_kvp_daemon.c +++ b/tools/hv/hv_kvp_daemon.c @@ -727,13 +727,19 @@ int main(void) len = recvfrom(fd, kvp_recv_buffer, sizeof(kvp_recv_buffer), 0, addr_p, &addr_l); - if (len < 0 || addr.nl_pid) { + if (len < 0) { syslog(LOG_ERR, "recvfrom failed; pid:%u error:%d %s", addr.nl_pid, errno, strerror(errno)); close(fd); return -1; } + if (addr.nl_pid) { + syslog(LOG_WARNING, "Received packet from untrusted pid:%u", + addr.nl_pid); + continue; + } + incoming_msg = (struct nlmsghdr *)kvp_recv_buffer; incoming_cn_msg = (struct cn_msg *)NLMSG_DATA(incoming_msg); hv_msg = (struct hv_kvp_msg *)incoming_cn_msg->data; diff --git a/tools/perf/Makefile b/tools/perf/Makefile index b6835c184cc..07e4699916e 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile @@ -241,13 +241,13 @@ $(OUTPUT)util/parse-events-flex.c: util/parse-events.l $(QUIET_FLEX)$(FLEX) --header-file=$(OUTPUT)util/parse-events-flex.h -t util/parse-events.l > $(OUTPUT)util/parse-events-flex.c $(OUTPUT)util/parse-events-bison.c: util/parse-events.y - $(QUIET_BISON)$(BISON) -v util/parse-events.y -d -o $(OUTPUT)util/parse-events-bison.c + $(QUIET_BISON)$(BISON) -v util/parse-events.y -d -o $(OUTPUT)util/parse-events-bison.c -p parse_events_ $(OUTPUT)util/pmu-flex.c: util/pmu.l $(QUIET_FLEX)$(FLEX) --header-file=$(OUTPUT)util/pmu-flex.h -t util/pmu.l > $(OUTPUT)util/pmu-flex.c $(OUTPUT)util/pmu-bison.c: util/pmu.y - $(QUIET_BISON)$(BISON) -v util/pmu.y -d -o $(OUTPUT)util/pmu-bison.c + $(QUIET_BISON)$(BISON) -v util/pmu.y -d -o $(OUTPUT)util/pmu-bison.c -p perf_pmu_ $(OUTPUT)util/parse-events.o: $(OUTPUT)util/parse-events-flex.c $(OUTPUT)util/parse-events-bison.c $(OUTPUT)util/pmu.o: $(OUTPUT)util/pmu-flex.c $(OUTPUT)util/pmu-bison.c diff --git a/tools/perf/scripts/python/net_dropmonitor.py b/tools/perf/scripts/python/net_dropmonitor.py index a4ffc950002..4c116056091 100755 --- a/tools/perf/scripts/python/net_dropmonitor.py +++ b/tools/perf/scripts/python/net_dropmonitor.py @@ -40,9 +40,9 @@ def get_kallsyms_table(): def get_sym(sloc): loc = int(sloc) - for i in kallsyms: - if (i['loc'] >= loc): - return (i['name'], i['loc']-loc) + for i in kallsyms[::-1]: + if loc >= i['loc']: + return (i['name'], loc - i['loc']) return (None, 0) def print_drop_table(): @@ -64,7 +64,7 @@ def trace_end(): # called from perf, when it finds a correspoinding event def skb__kfree_skb(name, context, cpu, sec, nsec, pid, comm, - skbaddr, protocol, location): + skbaddr, location, protocol): slocation = str(location) try: drop_log[slocation] = drop_log[slocation] + 1 diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index 35ae56864e4..9593f2772c6 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c @@ -15,7 +15,8 @@ const char *map_type__name[MAP__NR_TYPES] = { static inline int is_anon_memory(const char *filename) { - return strcmp(filename, "//anon") == 0; + return !strcmp(filename, "//anon") || + !strcmp(filename, "/anon_hugepage (deleted)"); } static inline int is_no_dso_memory(const char *filename) diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y index 581cd942a45..936faa5fcc3 100644 --- a/tools/perf/util/parse-events.y +++ b/tools/perf/util/parse-events.y @@ -1,5 +1,4 @@ -%name-prefix "parse_events_" %parse-param {struct list_head *list_all} %parse-param {struct list_head *list_event} %parse-param {int *idx} diff --git a/tools/perf/util/pmu.y b/tools/perf/util/pmu.y index 20ea77e9316..522943f7bfd 100644 --- a/tools/perf/util/pmu.y +++ b/tools/perf/util/pmu.y @@ -1,5 +1,4 @@ -%name-prefix "perf_pmu_" %parse-param {struct list_head *format} %parse-param {char *name} diff --git a/virt/kvm/ioapic.c b/virt/kvm/ioapic.c index dcaf272c26c..9f477f67163 100644 --- a/virt/kvm/ioapic.c +++ b/virt/kvm/ioapic.c @@ -73,9 +73,12 @@ static unsigned long ioapic_read_indirect(struct kvm_ioapic *ioapic, u32 redir_index = (ioapic->ioregsel - 0x10) >> 1; u64 redir_content; - ASSERT(redir_index < IOAPIC_NUM_PINS); + if (redir_index < IOAPIC_NUM_PINS) + redir_content = + ioapic->redirtbl[redir_index].bits; + else + redir_content = ~0ULL; - redir_content = ioapic->redirtbl[redir_index].bits; result = (ioapic->ioregsel & 0x1) ? (redir_content >> 32) & 0xffffffff : redir_content & 0xffffffff; diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 71b9036644a..bdfbc1be740 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -1382,21 +1382,38 @@ int kvm_write_guest(struct kvm *kvm, gpa_t gpa, const void *data, } int kvm_gfn_to_hva_cache_init(struct kvm *kvm, struct gfn_to_hva_cache *ghc, - gpa_t gpa) + gpa_t gpa, unsigned long len) { struct kvm_memslots *slots = kvm_memslots(kvm); int offset = offset_in_page(gpa); - gfn_t gfn = gpa >> PAGE_SHIFT; + gfn_t start_gfn = gpa >> PAGE_SHIFT; + gfn_t end_gfn = (gpa + len - 1) >> PAGE_SHIFT; + gfn_t nr_pages_needed = end_gfn - start_gfn + 1; + gfn_t nr_pages_avail; ghc->gpa = gpa; ghc->generation = slots->generation; - ghc->memslot = gfn_to_memslot(kvm, gfn); - ghc->hva = gfn_to_hva_many(ghc->memslot, gfn, NULL); - if (!kvm_is_error_hva(ghc->hva)) + 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 += offset; - else - return -EFAULT; - + } else { + /* + * If the requested region crosses two memslots, we still + * verify that the entire region is valid here. + */ + while (start_gfn <= end_gfn) { + 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)) + return -EFAULT; + start_gfn += nr_pages_avail; + } + /* Use the slow path for cross page reads and writes. */ + ghc->memslot = NULL; + } return 0; } EXPORT_SYMBOL_GPL(kvm_gfn_to_hva_cache_init); @@ -1407,8 +1424,13 @@ int kvm_write_guest_cached(struct kvm *kvm, struct gfn_to_hva_cache *ghc, struct kvm_memslots *slots = kvm_memslots(kvm); int r; + BUG_ON(len > ghc->len); + if (slots->generation != ghc->generation) - kvm_gfn_to_hva_cache_init(kvm, ghc, ghc->gpa); + kvm_gfn_to_hva_cache_init(kvm, ghc, ghc->gpa, ghc->len); + + if (unlikely(!ghc->memslot)) + return kvm_write_guest(kvm, ghc->gpa, data, len); if (kvm_is_error_hva(ghc->hva)) return -EFAULT; @@ -1428,8 +1450,13 @@ int kvm_read_guest_cached(struct kvm *kvm, struct gfn_to_hva_cache *ghc, struct kvm_memslots *slots = kvm_memslots(kvm); int r; + BUG_ON(len > ghc->len); + if (slots->generation != ghc->generation) - kvm_gfn_to_hva_cache_init(kvm, ghc, ghc->gpa); + kvm_gfn_to_hva_cache_init(kvm, ghc, ghc->gpa, ghc->len); + + if (unlikely(!ghc->memslot)) + return kvm_read_guest(kvm, ghc->gpa, data, len); if (kvm_is_error_hva(ghc->hva)) return -EFAULT; From 615893698a4f49d25022715c1fe340cdc8f2c016 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Sun, 22 Dec 2013 00:08:25 +0100 Subject: [PATCH 088/215] Fix derp --- drivers/usb/host/pci-quirks.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index 5c98ad2aea0..ec6e14e1790 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -780,7 +780,6 @@ void usb_enable_xhci_ports(struct pci_dev *xhci_pdev) "defaulting to EHCI.\n"); dev_warn(&xhci_pdev->dev, "USB 3.0 devices will work at USB 2.0 speeds.\n"); - usb_disable_xhci_ports(xhci_pdev); return; } From f9d0191675202a29aee235eeca632a4ee5e803ac Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Sun, 22 Dec 2013 00:40:38 +0100 Subject: [PATCH 089/215] kgsl : remove simple governor, add FranciscoFranco's interactive governor tweaks --- drivers/gpu/msm/Kconfig | 8 - drivers/gpu/msm/kgsl_pwrscale_trustzone.c | 277 ++++++++++------------ 2 files changed, 126 insertions(+), 159 deletions(-) diff --git a/drivers/gpu/msm/Kconfig b/drivers/gpu/msm/Kconfig index 96a935dcb3e..ba63fbcbbb4 100644 --- a/drivers/gpu/msm/Kconfig +++ b/drivers/gpu/msm/Kconfig @@ -96,11 +96,3 @@ config MSM_KGSL_DISABLE_SHADOW_WRITES bool "Disable register shadow writes for context switches" default n depends on MSM_KGSL - -config MSM_KGSL_SIMPLE_GOV - bool "Simple KGSL GPU govenor for Qualcomm Adreno xxx devices" - default n - depends on MSM_KGSL - ---help--- - A simple KGSL GPU govenor for Qualcom Adreno XXX devices - diff --git a/drivers/gpu/msm/kgsl_pwrscale_trustzone.c b/drivers/gpu/msm/kgsl_pwrscale_trustzone.c index 5e4f6b1620b..378575f8d73 100644 --- a/drivers/gpu/msm/kgsl_pwrscale_trustzone.c +++ b/drivers/gpu/msm/kgsl_pwrscale_trustzone.c @@ -8,7 +8,6 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * */ #include @@ -18,25 +17,22 @@ #include #include #include +#include +#include #include "kgsl.h" #include "kgsl_pwrscale.h" #include "kgsl_device.h" -#ifdef CONFIG_MSM_KGSL_SIMPLE_GOV -#include -#endif - #define TZ_GOVERNOR_PERFORMANCE 0 #define TZ_GOVERNOR_ONDEMAND 1 -#ifdef CONFIG_MSM_KGSL_SIMPLE_GOV -#define TZ_GOVERNOR_SIMPLE 2 -#endif +#define TZ_GOVERNOR_INTERACTIVE 2 struct tz_priv { int governor; + unsigned int no_switch_cnt; + unsigned int skip_cnt; struct kgsl_power_stats bin; - unsigned int idle_dcvs; }; spinlock_t tz_lock; @@ -48,34 +44,52 @@ spinlock_t tz_lock; * frame length, but less than the idle timer. */ #define CEILING 50000 + #define TZ_RESET_ID 0x3 #define TZ_UPDATE_ID 0x4 -#define TZ_INIT_ID 0x6 +#if 0 +#ifdef CONFIG_MSM_SCM /* Trap into the TrustZone, and call funcs there. */ -static int __secure_tz_entry2(u32 cmd, u32 val1, u32 val2) +static int __secure_tz_entry(u32 cmd, u32 val, u32 id) { int ret; spin_lock(&tz_lock); - /* sync memory before sending the commands to tz*/ __iowmb(); - ret = scm_call_atomic2(SCM_SVC_IO, cmd, val1, val2); + ret = scm_call_atomic2(SCM_SVC_IO, cmd, val, id); spin_unlock(&tz_lock); return ret; } - -static int __secure_tz_entry3(u32 cmd, u32 val1, u32 val2, - u32 val3) +#else +static int __secure_tz_entry(u32 cmd, u32 val, u32 id) { - int ret; - spin_lock(&tz_lock); - /* sync memory before sending the commands to tz*/ - __iowmb(); - ret = scm_call_atomic3(SCM_SVC_IO, cmd, val1, val2, - val3); - spin_unlock(&tz_lock); - return ret; + return 0; } +#endif /* CONFIG_MSM_SCM */ +#endif + +unsigned long window_time = 0; +unsigned long sample_time_ms = 100; +unsigned int up_threshold = 60; +unsigned int down_threshold = 25; +unsigned int up_differential = 10; +bool debug = 0; +unsigned long gpu_pref_counter; + +module_param(sample_time_ms, long, 0664); +module_param(up_threshold, int, 0664); +module_param(down_threshold, int, 0664); +module_param(debug, bool, 0664); + +static struct clk_scaling_stats { + unsigned long total_time_ms; + unsigned long busy_time_ms; + unsigned long threshold; +} gpu_stats = { + .total_time_ms = 0, + .busy_time_ms = 0, + .threshold = 0, +}; static ssize_t tz_governor_show(struct kgsl_device *device, struct kgsl_pwrscale *pwrscale, @@ -86,10 +100,8 @@ static ssize_t tz_governor_show(struct kgsl_device *device, if (priv->governor == TZ_GOVERNOR_ONDEMAND) ret = snprintf(buf, 10, "ondemand\n"); -#ifdef CONFIG_MSM_KGSL_SIMPLE_GOV - else if (priv->governor == TZ_GOVERNOR_SIMPLE) - ret = snprintf(buf, 8, "simple\n"); -#endif + else if (priv->governor == TZ_GOVERNOR_INTERACTIVE) + ret = snprintf(buf, 13, "interactive\n"); else ret = snprintf(buf, 13, "performance\n"); @@ -113,10 +125,8 @@ static ssize_t tz_governor_store(struct kgsl_device *device, if (!strncmp(str, "ondemand", 8)) priv->governor = TZ_GOVERNOR_ONDEMAND; -#ifdef CONFIG_MSM_KGSL_SIMPLE_GOV - else if (!strncmp(str, "simple", 6)) - priv->governor = TZ_GOVERNOR_SIMPLE; -#endif + else if (!strncmp(str, "interactive", 11)) + priv->governor = TZ_GOVERNOR_INTERACTIVE; else if (!strncmp(str, "performance", 11)) priv->governor = TZ_GOVERNOR_PERFORMANCE; @@ -144,67 +154,14 @@ static struct attribute_group tz_attr_group = { static void tz_wake(struct kgsl_device *device, struct kgsl_pwrscale *pwrscale) { - struct tz_priv *priv = pwrscale->priv; - if (device->state != KGSL_STATE_NAP && -#ifdef CONFIG_MSM_KGSL_SIMPLE_GOV - (priv->governor == TZ_GOVERNOR_ONDEMAND || - priv->governor == TZ_GOVERNOR_SIMPLE)) -#else - priv->governor == TZ_GOVERNOR_ONDEMAND) -#endif - kgsl_pwrctrl_pwrlevel_change(device, - device->pwrctrl.default_pwrlevel); + return; } -#ifdef CONFIG_MSM_KGSL_SIMPLE_GOV -/* KGSL Simple GPU Governor */ -/* Copyright (c) 2011-2013, Paul Reioux (Faux123). All rights reserved. */ -static int default_laziness = 5; -module_param_named(simple_laziness, default_laziness, int, 0664); - -static int ramp_up_threshold = 6000; -module_param_named(simple_ramp_threshold, ramp_up_threshold, int, 0664); - -static int laziness; - -static int simple_governor(struct kgsl_device *device, int idle_stat) -{ - int val = 0; - struct kgsl_pwrctrl *pwr = &device->pwrctrl; - - /* it's currently busy */ - if (idle_stat < ramp_up_threshold) { - if (pwr->active_pwrlevel == 0) - val = 0; /* already maxed, so do nothing */ - else if ((pwr->active_pwrlevel > 0) && - (pwr->active_pwrlevel <= (pwr->num_pwrlevels - 1))) - val = -1; /* bump up to next pwrlevel */ - /* idle case */ - } else { - if ((pwr->active_pwrlevel >= 0) && - (pwr->active_pwrlevel < (pwr->num_pwrlevels - 1))) - if (laziness > 0) { - /* hold off for a while */ - laziness--; - val = 0; /* don't change anything yet */ - } else { - val = 1; /* above min, lower it */ - /* reset laziness count */ - laziness = default_laziness; - } - else if (pwr->active_pwrlevel == (pwr->num_pwrlevels - 1)) - val = 0; /* already @ min, so do nothing */ - } - return val; -} -#endif - static void tz_idle(struct kgsl_device *device, struct kgsl_pwrscale *pwrscale) { struct kgsl_pwrctrl *pwr = &device->pwrctrl; struct tz_priv *priv = pwrscale->priv; struct kgsl_power_stats stats; - int val, idle; /* In "performance" mode the clock speed always stays the same */ @@ -212,60 +169,73 @@ static void tz_idle(struct kgsl_device *device, struct kgsl_pwrscale *pwrscale) return; device->ftbl->power_stats(device, &stats); + priv->bin.total_time += stats.total_time; priv->bin.busy_time += stats.busy_time; - /* Do not waste CPU cycles running this algorithm if - * the GPU just started, or if less than FLOOR time - * has passed since the last run. - */ - if ((stats.total_time == 0) || - (priv->bin.total_time < FLOOR)) + + if (time_is_after_jiffies(window_time + msecs_to_jiffies(sample_time_ms))) + return; + + gpu_stats.total_time_ms = jiffies_to_msecs(jiffies - window_time); + do_div(priv->bin.busy_time, USEC_PER_MSEC); + gpu_stats.busy_time_ms = priv->bin.busy_time; + + /* if busy time is 0 and we're already on the lowest pwrlevel, bail early */ + if (!gpu_stats.busy_time_ms && pwr->active_pwrlevel == pwr->min_pwrlevel) return; - /* If there is an extended block of busy processing, - * increase frequency. Otherwise run the normal algorithm. + if (debug) + { + pr_info("GPU current load: %lu\n", gpu_stats.busy_time_ms); + pr_info("GPU total time load: %lu\n", gpu_stats.total_time_ms); + pr_info("GPU frequency: %d\n", + pwr->pwrlevels[pwr->active_pwrlevel].gpu_freq); + } + + /* + * Scale the up_threshold value based on the active_pwrlevel. We have + * 4 different levels: + * 3 = 128MHz + * 2 = 200MHz + * 1 = 320MHz + * 0 = 400MHz + * + * Making the up_threshold value lower if the active level is 2 or 3 will + * possibly improve smoothness while scrolling or open applications with + * a lot of images and what not. With a Full HD panel like Flo/Deb I could + * notice a few frame drops while this algorithm didn't scale past 128MHz + * on simple operations. This is fixed with up_threshold being scaled */ - if (priv->bin.busy_time > CEILING) { - val = -1; - } else if (priv->idle_dcvs) { - idle = priv->bin.total_time - priv->bin.busy_time; - idle = (idle > 0) ? idle : 0; - val = __secure_tz_entry2(TZ_UPDATE_ID, idle, device->id); - } else { - if (pwr->step_mul > 1) - val = __secure_tz_entry3(TZ_UPDATE_ID, - (pwr->active_pwrlevel + 1)/2, - priv->bin.total_time, priv->bin.busy_time); - else -#ifdef CONFIG_MSM_KGSL_SIMPLE_GOV - { - idle = priv->bin.total_time - priv->bin.busy_time; - idle = (idle > 0) ? idle : 0; - if (priv->governor == TZ_GOVERNOR_SIMPLE) - val = simple_governor(device, idle); - else - val = __secure_tz_entry3(TZ_UPDATE_ID, - pwr->active_pwrlevel, - priv->bin.total_time, priv->bin.busy_time); - } -#else - val = __secure_tz_entry3(TZ_UPDATE_ID, - pwr->active_pwrlevel, - priv->bin.total_time, priv->bin.busy_time); -#endif + + if (pwr->active_pwrlevel == pwr->min_pwrlevel) + gpu_stats.threshold = up_threshold / pwr->active_pwrlevel; + else if (pwr->active_pwrlevel > 0) + gpu_stats.threshold = up_threshold - up_differential; + else + gpu_stats.threshold = up_threshold; + + if ((gpu_stats.busy_time_ms * 100) > (gpu_stats.total_time_ms * gpu_stats.threshold)) + { + if (gpu_pref_counter < 100) + ++gpu_pref_counter; + + if (pwr->active_pwrlevel > pwr->max_pwrlevel) + kgsl_pwrctrl_pwrlevel_change(device, + pwr->active_pwrlevel - 1); + } + else if ((gpu_stats.busy_time_ms * 100) < (gpu_stats.total_time_ms * down_threshold)) + { + if (gpu_pref_counter > 0) + --gpu_pref_counter; + + if (pwr->active_pwrlevel < pwr->max_pwrlevel) + kgsl_pwrctrl_pwrlevel_change(device, + pwr->active_pwrlevel + 1); } priv->bin.total_time = 0; priv->bin.busy_time = 0; - - /* If the decision is to move to a lower level, make sure the GPU - * frequency drops. - */ - if (val > 0) - val *= pwr->step_mul; - if (val) - kgsl_pwrctrl_pwrlevel_change(device, - pwr->active_pwrlevel + val); + window_time = jiffies; } static void tz_busy(struct kgsl_device *device, @@ -278,41 +248,46 @@ static void tz_sleep(struct kgsl_device *device, struct kgsl_pwrscale *pwrscale) { struct tz_priv *priv = pwrscale->priv; + struct kgsl_pwrctrl *pwr = &device->pwrctrl; + + /* + * We don't want the GPU to go to sleep if the busy_time_ms calculated on + * idle routine is not below down_threshold. This is just a measure of + * precaution + */ + if ((gpu_stats.busy_time_ms * 100) < + (gpu_stats.total_time_ms * down_threshold)) + { + kgsl_pwrctrl_pwrlevel_change(device, pwr->min_pwrlevel); + } + + if (debug) + { + pr_info("GPU frequency: %d\n", + pwr->pwrlevels[pwr->active_pwrlevel].gpu_freq); + } - __secure_tz_entry2(TZ_RESET_ID, 0, 0); + gpu_pref_counter = 0; priv->bin.total_time = 0; priv->bin.busy_time = 0; + window_time = jiffies; + + return; } #ifdef CONFIG_MSM_SCM static int tz_init(struct kgsl_device *device, struct kgsl_pwrscale *pwrscale) { - int i = 0, j = 1, ret = 0; struct tz_priv *priv; - struct kgsl_pwrctrl *pwr = &device->pwrctrl; - unsigned int tz_pwrlevels[KGSL_MAX_PWRLEVELS + 1]; priv = pwrscale->priv = kzalloc(sizeof(struct tz_priv), GFP_KERNEL); if (pwrscale->priv == NULL) return -ENOMEM; - priv->idle_dcvs = 0; - priv->governor = TZ_GOVERNOR_ONDEMAND; + + priv->governor = TZ_GOVERNOR_INTERACTIVE; spin_lock_init(&tz_lock); kgsl_pwrscale_policy_add_files(device, pwrscale, &tz_attr_group); - for (i = 0; i < pwr->num_pwrlevels - 1; i++) { - if (i == 0) - tz_pwrlevels[j] = pwr->pwrlevels[i].gpu_freq; - else if (pwr->pwrlevels[i].gpu_freq != - pwr->pwrlevels[i - 1].gpu_freq) { - j++; - tz_pwrlevels[j] = pwr->pwrlevels[i].gpu_freq; - } - } - tz_pwrlevels[0] = j; - ret = scm_call(SCM_SVC_DCVS, TZ_INIT_ID, tz_pwrlevels, - sizeof(tz_pwrlevels), NULL, 0); - if (ret) - priv->idle_dcvs = 1; + return 0; } #else From 86ebb910cf4848d56f46348694a99f26d25d14d0 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Sun, 22 Dec 2013 00:42:16 +0100 Subject: [PATCH 090/215] defconfig : update defconfig --- arch/arm/configs/flo_defconfig | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/arm/configs/flo_defconfig b/arch/arm/configs/flo_defconfig index 2e12f55da20..21c413b02d1 100644 --- a/arch/arm/configs/flo_defconfig +++ b/arch/arm/configs/flo_defconfig @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/arm 3.4.5 Kernel Configuration +# Linux/arm 3.4.60 Kernel Configuration # CONFIG_ARM=y CONFIG_ARM_HAS_SG_CHAIN=y @@ -610,6 +610,7 @@ CONFIG_MULTI_IRQ_HANDLER=y # CONFIG_ARM_ERRATA_754327 is not set # CONFIG_ARM_ERRATA_764369 is not set # CONFIG_KSAPI is not set +# CONFIG_ARM_ERRATA_775420 is not set CONFIG_ARM_GIC=y # CONFIG_FIQ_DEBUGGER is not set @@ -3136,7 +3137,6 @@ CONFIG_USB_STORAGE_ONETOUCH=y CONFIG_USB_STORAGE_KARMA=y CONFIG_USB_STORAGE_CYPRESS_ATACB=y # CONFIG_USB_STORAGE_ENE_UB6250 is not set -# CONFIG_USB_UAS is not set # CONFIG_USB_LIBUSUAL is not set # @@ -3816,6 +3816,7 @@ CONFIG_TRACING_SUPPORT=y CONFIG_DYNAMIC_DEBUG=y # CONFIG_DMA_API_DEBUG is not set # CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_PANIC_ON_DATA_CORRUPTION is not set # CONFIG_SAMPLES is not set # CONFIG_TEST_KSTRTOX is not set # CONFIG_STRICT_DEVMEM is not set From 8c738992ccbc4082236b3d1687dd0028d849c45b Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Sun, 22 Dec 2013 02:44:47 +0100 Subject: [PATCH 091/215] Aroma : Add GPU clock settings and Gentle Fair Sleepers switch, replace Simple GPU gov with Interactive. Signed-off-by: Tk-Glitch --- .../META-INF/com/google/android/aroma-config | 19 ++++-- .../com/google/android/aroma/changelog.txt | 3 +- .../com/google/android/updater-script | 60 +++++++++++++++++-- release/aroma/config/buildconfig.sh | 29 ++++++++- release/aroma/system/etc/init.d/99glitch | 34 ++++++++++- 5 files changed, 131 insertions(+), 14 deletions(-) diff --git a/release/aroma/META-INF/com/google/android/aroma-config b/release/aroma/META-INF/com/google/android/aroma-config index c3026389104..7b24d0420cd 100755 --- a/release/aroma/META-INF/com/google/android/aroma-config +++ b/release/aroma/META-INF/com/google/android/aroma-config @@ -230,13 +230,23 @@ selectbox( ); selectbox( - "Select GPU governor","\n","@personalize","gpugov.prop", + "GPU max frequency","Select the GPU's max frequency\n","@personalize","gpuclock.prop", + "320MHz","(powersaving)",0, + "450MHz","(improved)",1, + "504MHz","(balanced)",0, + "545MHz","(fast)",0, + "600MHz","(extreme)",0, + "627MHz","(glitchy)",0 +); + +selectbox( + "GPU governor","Select the GPU frequency scaling technique\n","@personalize","gpugov.prop", "Ondemand","(stock)",1, - "Simple","",0 + "Interactive","",0 ); selectbox( - "Select Battery life eXtender settings","Sets the charge voltage of the battery to extend its lifespan\n","@personalize","ble.prop", + "Battery life eXtender settings","Sets the charge voltage of the battery to extend its lifespan\n","@personalize","ble.prop", "4.3V","(100% - stock)",1, "4.2V","(93% - balanced)",0, "4.1V","(83% - conservative)",0, @@ -252,7 +262,8 @@ checkbox( "DoubleTap2Wake","Double tap screen to wake device",1, "Disable magnetic on/off","",0, "Enable USB OTG+Charge mode","Allows charging in USB host mode (disables self-powered OTG)",0, - "Enable input-boost","Improves smoothness with kernel-side hotplug drivers",1 + "Enable input-boost","Improves smoothness with kernel-side hotplug drivers",1, + "Enable Gentle Fair Sleepers","Disable for UI smoothness, but more battery consumption (enabled by default)",1 ); if file_getprop("/tmp/aroma/mods.prop","item.0.1") == "1" && file_getprop("/tmp/aroma/mods.prop","item.0.2") == "1" diff --git a/release/aroma/META-INF/com/google/android/aroma/changelog.txt b/release/aroma/META-INF/com/google/android/aroma/changelog.txt index 5e27738a9ac..100c969c405 100755 --- a/release/aroma/META-INF/com/google/android/aroma/changelog.txt +++ b/release/aroma/META-INF/com/google/android/aroma/changelog.txt @@ -1,10 +1,9 @@ Glitch kernel "AOSP" for N7 2013 -- Based on AOSP 3.4.0 kernel source for MSM devices updated to linux 3.4.1 +- Based on AOSP 3.4.0 kernel source for MSM devices updated to linux 3.4.60 - CPU OC up to 2.3Ghz with OV/UV support - L2/bus speed OC up to 1.49GHz / 4.96GBPS - GPU OC up to 627 MHz - - Faux Simple GPU governor support - CPU governors : Faux's intellidemand, interactive, ondemand - I/O schedulers: noop, deadline, row, cfq, fiops, sio diff --git a/release/aroma/META-INF/com/google/android/updater-script b/release/aroma/META-INF/com/google/android/updater-script index 3fed90cfda7..2dfb0145c56 100755 --- a/release/aroma/META-INF/com/google/android/updater-script +++ b/release/aroma/META-INF/com/google/android/updater-script @@ -132,10 +132,52 @@ if ui_print("run hot"); endif; +if + file_getprop("/tmp/aroma/gpuclock.prop","selected.0") == "1" + then + ui_print("320 MHz GPU Clock"); +endif; + +if + file_getprop("/tmp/aroma/gpuclock.prop","selected.0") == "2" + then + ui_print("450 MHz GPU Clock"); +endif; + +if + file_getprop("/tmp/aroma/gpuclock.prop","selected.0") == "3" + then + ui_print("504 MHz GPU Clock"); +endif; + +if + file_getprop("/tmp/aroma/gpuclock.prop","selected.0") == "4" + then + ui_print("545 MHz GPU Clock"); +endif; + +if + file_getprop("/tmp/aroma/gpuclock.prop","selected.0") == "5" + then + ui_print("600 MHz GPU Clock"); +endif; + +if + file_getprop("/tmp/aroma/gpuclock.prop","selected.0") == "6" + then + ui_print("627 MHz GPU Clock"); +endif; + +if + file_getprop("/tmp/aroma/gpugov.prop","selected.0") == "1" + then + ui_print("Ondemand GPU Governor"); +endif; + if file_getprop("/tmp/aroma/gpugov.prop","selected.0") == "2" then - ui_print("Simple GPU Governor"); + ui_print("Interactive GPU Governor"); endif; if @@ -207,6 +249,12 @@ if ui_print("Input-boost enabled"); endif; +if + file_getprop("/tmp/aroma/mods.prop","item.0.9") == "1" + then + ui_print("Gentle Fair Sleepers enabled"); +endif; + set_progress(0.3); @@ -259,7 +307,7 @@ ui_print(" /system/bin/thermald -> thermald_bck"); run_program("/tmp/compatibility.sh"); endif; -ui_print("Installing system files"); +ui_print("Installing system files for real"); package_extract_dir("system", "/system"); set_perm_recursive(0, 2000, 0777, 0777, "/system/etc/init.d/99glitch"); set_perm_recursive(0, 0, 0644, 0644, "/system/lib/modules"); @@ -283,14 +331,16 @@ set_perm(0, 0, 0777, "/tmp/busybox"); set_perm(0, 0, 0777, "/tmp/compatibility.sh"); run_program("/tmp/busybox", "mount", "/system"); -ui_print("Installing system files"); +ui_print("Installing system files to be a good boy"); package_extract_dir("system", "/system"); set_perm_recursive(0, 0, 0644, 0644, "/system/lib/modules"); -ui_print("Cleaning up"); +ui_print("Do some useless cleaning in case something didn't went wrong"); delete("/system/lib/modules/cpufreq_limit.ko"); delete("/system/lib/modules/scsi_wait_scan.ko"); +ui_print("Try not to destroy your old settings.. too much"); + set_perm(0, 0, 0777, "/tmp/systemcheck.sh"); run_program("/tmp/systemcheck.sh"); @@ -309,7 +359,7 @@ run_program("/tmp/max_oc.sh"); run_program("/tmp/edit_ramdisk.sh"); run_program("/tmp/abootimg", "-u", "/tmp/boot.img", "-f", "/tmp/cmdline.cfg", "-k", "/tmp/glitch.zImage", "-r", "/tmp/initrd.img"); -ui_print("@Installing Kernel"); +ui_print("@Glitching your device"); run_program("/tmp/busybox", "dd", "if=/tmp/boot.img", "of=/dev/block/mmcblk0p14"); ui_print(""); diff --git a/release/aroma/config/buildconfig.sh b/release/aroma/config/buildconfig.sh index ede46eb43a8..5d65895efd8 100755 --- a/release/aroma/config/buildconfig.sh +++ b/release/aroma/config/buildconfig.sh @@ -114,6 +114,15 @@ else echo "INPUTBOOST=0" >> $CONFIGFILE; fi +#Gentle Fair Sleepers +GFSLEEPERS=`grep "item.0.9" /tmp/aroma/mods.prop | cut -d '=' -f2` +echo -e "\n\n##### Gentle Fair Sleepers Settings ######\n# 1 to enable\n# 0 to disable\n" >> $CONFIGFILE +if [ $GFSLEEPERS = 1 ]; then + echo "GFSLEEPERS=1" >> $CONFIGFILE; +else + echo "GFSLEEPERS=0" >> $CONFIGFILE; +fi + #THERMAL THERM=`cat /tmp/aroma/thermal.prop | cut -d '=' -f2` echo -e "\n\n##### Thermal Settings #####\n# 0 for default thermal throttling" >> $CONFIGFILE @@ -126,10 +135,28 @@ else echo "THERM=0" >> $CONFIGFILE; fi +#GPU Clock +GPU_OC=`cat /tmp/aroma/gpuclock.prop | cut -d '=' -f2` +echo -e "\n\n##### Max GPU Clock #####\n# 1 320 MHz" >> $CONFIGFILE +echo -e "\n# 2 450 MHz\n# 3 504MHz\n# 4 545 MHz\n# 5 600 MHz\n# 6 627 MHz\n" >> $CONFIGFILE +if [ $GPU_OC = 1 ]; then + echo "GPU_OC=1" >> $CONFIGFILE; +elif [ $GPU_OC = 3 ]; then + echo "GPU_OC=3" >> $CONFIGFILE; +elif [ $GPU_OC = 4 ]; then + echo "GPU_OC=4" >> $CONFIGFILE; +elif [ $GPU_OC = 5 ]; then + echo "GPU_OC=5" >> $CONFIGFILE; +elif [ $GPU_OC = 6 ]; then + echo "GPU_OC=6" >> $CONFIGFILE; +else + echo "GPU_OC=2" >> $CONFIGFILE; +fi + #GPU Governor GPU_GOV=`cat /tmp/aroma/gpugov.prop | cut -d '=' -f2` echo -e "\n\n##### GPU Governor #####\n# 1 Ondemand (default)" >> $CONFIGFILE -echo -e "\n# 2 Simple\n# 3 Performance\n" >> $CONFIGFILE +echo -e "\n# 2 Interactive\n# 3 Performance\n" >> $CONFIGFILE if [ $GPU_GOV = 2 ]; then echo "GPU_GOV=2" >> $CONFIGFILE; else diff --git a/release/aroma/system/etc/init.d/99glitch b/release/aroma/system/etc/init.d/99glitch index fb2d58fd384..3dfa54fd4b4 100755 --- a/release/aroma/system/etc/init.d/99glitch +++ b/release/aroma/system/etc/init.d/99glitch @@ -138,6 +138,15 @@ else echo Input-Boost enabled >> $KERNEL_LOGFILE; fi +#Gentle Fair Sleepers +if [ "`grep GFSLEEPERS=0 $KERNEL_CONF`" ]; then + echo 0 > /sys/kernel/sched/gentle_fair_sleepers; + echo Gentle Fair Sleepers disabled >> $KERNEL_LOGFILE; +else + echo 1 > /sys/kernel/sched/gentle_fair_sleepers; + echo Gentle Fair Sleepers enabled >> $KERNEL_LOGFILE; +fi + #fstrim fstrim -v /cache | tee -a $KERNEL_LOGFILE; fstrim -v /data | tee -a $KERNEL_LOGFILE; @@ -151,10 +160,31 @@ elif [ "`grep THERM=2 $KERNEL_CONF`" ]; then echo run hot >> $KERNEL_LOGFILE; fi +#GPU Clock settings +if [ "`grep GPU_OC=1 $KERNEL_CONF`" ]; then + echo 320000000 > /sys/devices/platform/kgsl-3d0.0/kgsl/kgsl-3d0/max_gpuclk; + echo 320MHz GPU >> $KERNEL_LOGFILE; +elif [ "`grep GPU_OC=3 $KERNEL_CONF`" ]; then + echo 504000000 > /sys/devices/platform/kgsl-3d0.0/kgsl/kgsl-3d0/max_gpuclk; + echo 504MHz GPU >> $KERNEL_LOGFILE; +elif [ "`grep GPU_OC=4 $KERNEL_CONF`" ]; then + echo 545000000 > /sys/devices/platform/kgsl-3d0.0/kgsl/kgsl-3d0/max_gpuclk; + echo 545MHz GPU >> $KERNEL_LOGFILE; +elif [ "`grep GPU_OC=5 $KERNEL_CONF`" ]; then + echo 600000000 > /sys/devices/platform/kgsl-3d0.0/kgsl/kgsl-3d0/max_gpuclk; + echo 600MHz GPU >> $KERNEL_LOGFILE; +elif [ "`grep GPU_OC=6 $KERNEL_CONF`" ]; then + echo 627000000 > /sys/devices/platform/kgsl-3d0.0/kgsl/kgsl-3d0/max_gpuclk; + echo 627MHz GPU >> $KERNEL_LOGFILE; +else + echo 450000000 > /sys/devices/platform/kgsl-3d0.0/kgsl/kgsl-3d0/max_gpuclk; + echo 450MHz GPU >> $KERNEL_LOGFILE; +fi + #GPU Governor settings if [ "`grep GPU_GOV=2 $KERNEL_CONF`" ]; then - echo simple > /sys/devices/platform/kgsl-3d0.0/kgsl/kgsl-3d0/pwrscale/trustzone/governor; - echo Simple GPU Governor >> $KERNEL_LOGFILE; + echo interactive > /sys/devices/platform/kgsl-3d0.0/kgsl/kgsl-3d0/pwrscale/trustzone/governor; + echo Interactive GPU Governor >> $KERNEL_LOGFILE; elif [ "`grep GPU_GOV=3 $KERNEL_CONF`" ]; then echo performance > /sys/devices/platform/kgsl-3d0.0/kgsl/kgsl-3d0/pwrscale/trustzone/governor; echo Performance GPU Governor >> $KERNEL_LOGFILE; From 402519ff2fd8057dc1d3a38f2c88ce1e85b8b3e7 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Sun, 22 Dec 2013 02:47:31 +0100 Subject: [PATCH 092/215] Defconfig : remove Simple GPU gov --- arch/arm/configs/flo_defconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm/configs/flo_defconfig b/arch/arm/configs/flo_defconfig index 21c413b02d1..a7eabb9791e 100644 --- a/arch/arm/configs/flo_defconfig +++ b/arch/arm/configs/flo_defconfig @@ -2663,7 +2663,6 @@ CONFIG_MSM_KGSL_PAGE_TABLE_SIZE=0xFFF0000 CONFIG_MSM_KGSL_PAGE_TABLE_COUNT=24 CONFIG_MSM_KGSL_MMU_PAGE_FAULT=y # CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES is not set -CONFIG_MSM_KGSL_SIMPLE_GOV=y # CONFIG_VGASTATE is not set # CONFIG_VIDEO_OUTPUT_CONTROL is not set CONFIG_FB=y From bc0a9e6b080598eafeeaff27274007a76476d383 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Sun, 22 Dec 2013 15:56:45 +0100 Subject: [PATCH 093/215] Fix derp --- kernel/workqueue.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 7aaf3c25d6a..a032953e45e 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -3570,7 +3570,7 @@ __acquires(&gcwq->lock) } } -static int workqueue_cpu_callback(struct notifier_block *nfb, +static int __devinit workqueue_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { @@ -3788,12 +3788,7 @@ void freeze_workqueues_begin(void) gcwq->flags |= GCWQ_FREEZING; list_for_each_entry(wq, &workqueues, list) { - - struct cpu_workqueue_struct *cwq; - if (cpu < CONFIG_NR_CPUS) - cwq = get_cwq(cpu, wq); - else - continue; + struct cpu_workqueue_struct *cwq = get_cwq(cpu, wq); if (cwq && wq->flags & WQ_FREEZABLE) cwq->max_active = 0; @@ -3834,12 +3829,7 @@ bool freeze_workqueues_busy(void) * to peek without lock. */ list_for_each_entry(wq, &workqueues, list) { - - struct cpu_workqueue_struct *cwq; - if (cpu < CONFIG_NR_CPUS) - cwq = get_cwq(cpu, wq); - else - continue; + struct cpu_workqueue_struct *cwq = get_cwq(cpu, wq); if (!cwq || !(wq->flags & WQ_FREEZABLE)) continue; From d6bd73d26e872a21ef25a08a8f030e1823392d04 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Sun, 22 Dec 2013 16:57:52 +0100 Subject: [PATCH 094/215] OTG+charge hack: restore peripherals on power loss (partly working) Signed-off-by: flar2 --- drivers/usb/otg/msm_otg.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c index 77cbd6fcbd8..16e2dfede71 100755 --- a/drivers/usb/otg/msm_otg.c +++ b/drivers/usb/otg/msm_otg.c @@ -10,7 +10,7 @@ * GNU General Public License for more details. * */ - +#define DEBUG #include #include #include @@ -3166,6 +3166,11 @@ static void msm_otg_set_vbus_state(int online) pr_debug("PMIC: BSV set\n"); //printk("connected charger\n"); set_bit(B_SESS_VLD, &motg->inputs); + if (otg->phy->state >= OTG_STATE_A_IDLE && usbhost_charge_mode) { + printk("[usbhost_charge_mode]: already in host mode, restart chg_work"); + msm_chg_detect_work(&motg->chg_work.work); + } + } else { pr_debug("PMIC: BSV clear\n"); //printk("disconnected charger\n"); @@ -3179,7 +3184,6 @@ static void msm_otg_set_vbus_state(int online) motg->chg_type = USB_INVALID_CHARGER; asus_chg_set_chg_mode(USB_INVALID_CHARGER); msm_otg_notify_charger(motg, 0); - msm_otg_reset(otg->phy); } } @@ -3228,7 +3232,7 @@ static void id_pin_irq_work_function(struct work_struct *work) if (gpio == 0 && otg_host_on == 0) { //otg+charge: this needs a slight delay or else it doesn't start charging if (usbhost_charge_mode) - msleep(20); + msleep(40); pr_info("%s: APQ_OTG_ID_PIN is low : Host mode\n", __func__); set_bit(A_BUS_REQ, &motg->inputs); clear_bit(ID, &motg->inputs); From 44c42667cd22884ef7068d12752ecb4f1f661606 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Sun, 22 Dec 2013 17:00:51 +0100 Subject: [PATCH 095/215] drivers/input/touchscreen/ektf3k: auto retry 10 times on i2c reads The i2c devices we are connecting to may not be ready yet, or just busy. Retry with a 10ms pause in order to still obtain i2c data. This improves overall i2c data robustness Signed-off-by: Dennis Rassmann --- drivers/input/touchscreen/ektf3k.c | 73 ++++++++++++++++++------------ 1 file changed, 45 insertions(+), 28 deletions(-) diff --git a/drivers/input/touchscreen/ektf3k.c b/drivers/input/touchscreen/ektf3k.c index f85ccb45f53..a51f1d586cf 100755 --- a/drivers/input/touchscreen/ektf3k.c +++ b/drivers/input/touchscreen/ektf3k.c @@ -142,6 +142,8 @@ static atomic_t touch_char_available = ATOMIC_INIT(1); static struct proc_dir_entry *dbgProcFile; #endif +#define ELAN_I2C_RETRY 10 + struct elan_ktf3k_ts_data { struct i2c_client *client; struct input_dev *input_dev; @@ -1123,11 +1125,11 @@ static int elan_ktf3k_ts_get_data(struct i2c_client *client, uint8_t *cmd, static int elan_ktf3k_ts_read_command(struct i2c_client *client, u8* cmd, u16 cmd_length, u8 *value, u16 value_length){ - struct i2c_adapter *adapter = client->adapter; + struct i2c_adapter *adapter = client->adapter; struct i2c_msg msg[2]; //__le16 le_addr; struct elan_ktf3k_ts_data *ts; - int length = 0; + int retry = 0; ts = i2c_get_clientdata(client); @@ -1136,23 +1138,28 @@ static int elan_ktf3k_ts_read_command(struct i2c_client *client, msg[0].len = cmd_length; msg[0].buf = cmd; - down(&pSem); - length = i2c_transfer(adapter, msg, 1); - up(&pSem); - - if (length == 1) // only send on packet - return value_length; - else - return -EIO; + for (retry = 0; retry <= ELAN_I2C_RETRY; retry++) { + down(&pSem); + if (i2c_transfer(adapter, msg, 1) == 1) { + up(&pSem); + return value_length; + } + up(&pSem); + if (retry == ELAN_I2C_RETRY) { + return -EIO; + } else + msleep(10); + } + return 0; } static int elan_ktf3k_i2c_read_packet(struct i2c_client *client, u8 *value, u16 value_length){ - struct i2c_adapter *adapter = client->adapter; + struct i2c_adapter *adapter = client->adapter; struct i2c_msg msg[1]; //__le16 le_addr; struct elan_ktf3k_ts_data *ts; - int length = 0; + int retry = 0; ts = i2c_get_clientdata(client); @@ -1160,14 +1167,20 @@ static int elan_ktf3k_i2c_read_packet(struct i2c_client *client, msg[0].flags = I2C_M_RD; msg[0].len = value_length; msg[0].buf = (u8 *) value; - down(&pSem); - length = i2c_transfer(adapter, msg, 1); - up(&pSem); - - if (length == 1) // only send on packet - return value_length; - else - return -EIO; + + for (retry = 0; retry <= ELAN_I2C_RETRY; retry++) { + down(&pSem); + if (i2c_transfer(adapter, msg, 1) == 1) { + up(&pSem); + return value_length; + } + up(&pSem); + if (retry == ELAN_I2C_RETRY) { + return -EIO; + } else + msleep(10); + } + return 0; } static int __hello_packet_handler(struct i2c_client *client) @@ -1483,22 +1496,26 @@ void touch_callback(unsigned cable_status){ static int elan_ktf3k_ts_recv_data(struct i2c_client *client, uint8_t *buf, int size) { - int rc, bytes_to_recv = size; + int retry = 0, bytes_to_recv = size; if (buf == NULL) return -EINVAL; memset(buf, 0, bytes_to_recv); - rc = i2c_master_recv(client, buf, bytes_to_recv); - if (rc != bytes_to_recv) { - dev_err(&client->dev, - "[elan] %s: i2c_master_recv error?! \n", __func__); - rc = i2c_master_recv(client, buf, bytes_to_recv); - return -EINVAL; + for (retry = 0; retry <= ELAN_I2C_RETRY; retry++) { + if (i2c_master_recv(client, buf, bytes_to_recv) == bytes_to_recv) + return bytes_to_recv; + if (retry == ELAN_I2C_RETRY) { + dev_err(&client->dev, + "[elan] %s: i2c_master_recv error?! \n", __func__); + (void) i2c_master_recv(client, buf, bytes_to_recv); + return -EINVAL; + } else + msleep(10); } - return rc; + return -EINVAL; } static void elan_ktf3k_ts_report_data(struct i2c_client *client, uint8_t *buf) From 4c83e60267493a13dcc4c3e4dbd6b8573a11d825 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Sun, 22 Dec 2013 17:12:49 +0100 Subject: [PATCH 096/215] Add LCDC LUT and initial code for generic MSM LCD temperature calibrations from Faux123 Signed-off-by: Tk-Glitch --- arch/arm/mach-msm/Kconfig | 12 + arch/arm/mach-msm/Makefile | 5 + .../mach-msm/asustek/flo/board-flo-display.c | 10 + arch/arm/mach-msm/include/mach/board.h | 2 + arch/arm/mach-msm/msm_kcal_ctrl.c | 309 ++++++++++++++++++ drivers/video/msm/mdp.c | 29 +- drivers/video/msm/mdp.h | 2 - drivers/video/msm/msm_fb.c | 5 + 8 files changed, 352 insertions(+), 22 deletions(-) create mode 100644 arch/arm/mach-msm/msm_kcal_ctrl.c diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig index 93669196fa5..4a15791163b 100644 --- a/arch/arm/mach-msm/Kconfig +++ b/arch/arm/mach-msm/Kconfig @@ -2652,4 +2652,16 @@ config FORCE_FAST_CHARGE A simple sysfs interface to force adapters that are detected as USB to charge as AC. +config UPDATE_LCDC_LUT + bool "Set initial Qualcomm LCDC lut" + default y + help + Set initial Qualcomm LCDC Look Up Table. + +config LCD_KCAL + tristate "MSM generic LCDC Calibration" + default y + help + Enable MSM generic LCDC temperature Calibration. + endif diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile index 2783612867f..34cda636653 100644 --- a/arch/arm/mach-msm/Makefile +++ b/arch/arm/mach-msm/Makefile @@ -321,6 +321,9 @@ obj-$(CONFIG_HTC_HEADSET) += htc_headset.o obj-$(CONFIG_MSM_RMT_STORAGE_CLIENT) += rmt_storage_client.o obj-$(CONFIG_MSM_SDIO_SMEM) += sdio_smem.o obj-$(CONFIG_MSM_RPM) += rpm.o + +obj-$(CONFIG_LCD_KCAL) += msm_kcal_ctrl.o + ifdef CONFIG_MSM_RPM obj-$(CONFIG_ARCH_APQ8064) += rpm_resources.o obj-$(CONFIG_ARCH_MSM8960) += rpm_resources.o @@ -396,3 +399,5 @@ ifdef CONFIG_MSM_CPR obj-$(CONFIG_DEBUG_FS) += msm_cpr-debug.o endif obj-$(CONFIG_MSM_CPU_PWRCTL) += msm_cpu_pwrctl.o + + diff --git a/arch/arm/mach-msm/asustek/flo/board-flo-display.c b/arch/arm/mach-msm/asustek/flo/board-flo-display.c index 26450db8568..cf9a33d8d12 100644 --- a/arch/arm/mach-msm/asustek/flo/board-flo-display.c +++ b/arch/arm/mach-msm/asustek/flo/board-flo-display.c @@ -152,8 +152,18 @@ static int msm_fb_detect_panel(const char *name) return -ENODEV; } +#ifdef CONFIG_UPDATE_LCDC_LUT +int update_preset_lcdc_lut(void) +{ + return 0; +} +#endif + static struct msm_fb_platform_data msm_fb_pdata = { .detect_client = msm_fb_detect_panel, +#ifdef CONFIG_UPDATE_LCDC_LUT + .update_lcdc_lut = update_preset_lcdc_lut, +#endif }; static struct platform_device msm_fb_device = { diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h index 31510a87149..d6f13b12609 100644 --- a/arch/arm/mach-msm/include/mach/board.h +++ b/arch/arm/mach-msm/include/mach/board.h @@ -499,7 +499,9 @@ struct msm_fb_platform_data { int (*allow_set_offset)(void); char prim_panel_name[PANEL_NAME_MAX_LEN]; char ext_panel_name[PANEL_NAME_MAX_LEN]; +#ifdef CONFIG_UPDATE_LCDC_LUT int (*update_lcdc_lut)(void); +#endif }; struct msm_hdmi_platform_data { diff --git a/arch/arm/mach-msm/msm_kcal_ctrl.c b/arch/arm/mach-msm/msm_kcal_ctrl.c new file mode 100644 index 00000000000..06fcf88399e --- /dev/null +++ b/arch/arm/mach-msm/msm_kcal_ctrl.c @@ -0,0 +1,309 @@ +/* arch/arm/mach-msm/msm_kcal_ctrl.c + * + * Interface to calibrate display color temperature. + * + * Copyright (C) 2012 LGE + * Copyright (C) 2013 Paul Reioux + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include +#include +#include + +#include "../../../drivers/video/msm/mdp.h" + +#define KCAL_CTRL_MAJOR_VERSION 1 +#define KCAL_CTRL_MINOR_VERSION 0 +#define KCAL_PLATFORM_NAME "DIAG0" + +struct kcal_data { + int red; + int green; + int blue; +}; + +struct kcal_platform_data { + int (*set_values) (int r, int g, int b); + int (*get_values) (int *r, int *g, int *b); + int (*refresh_display) (void); +}; + +static struct kcal_platform_data *kcal_ctrl_pdata; +static int last_status_kcal_ctrl; + +/* pixel order : RBG */ +static unsigned int lcd_color_preset_lut[256] = { + /* default linear qlut */ + 0x00000000, 0x00010101, 0x00020202, 0x00030303, + 0x00040404, 0x00050505, 0x00060606, 0x00070707, + 0x00080808, 0x00090909, 0x000a0a0a, 0x000b0b0b, + 0x000c0c0c, 0x000d0d0d, 0x000e0e0e, 0x000f0f0f, + 0x00101010, 0x00111111, 0x00121212, 0x00131313, + 0x00141414, 0x00151515, 0x00161616, 0x00171717, + 0x00181818, 0x00191919, 0x001a1a1a, 0x001b1b1b, + 0x001c1c1c, 0x001d1d1d, 0x001e1e1e, 0x001f1f1f, + 0x00202020, 0x00212121, 0x00222222, 0x00232323, + 0x00242424, 0x00252525, 0x00262626, 0x00272727, + 0x00282828, 0x00292929, 0x002a2a2a, 0x002b2b2b, + 0x002c2c2c, 0x002d2d2d, 0x002e2e2e, 0x002f2f2f, + 0x00303030, 0x00313131, 0x00323232, 0x00333333, + 0x00343434, 0x00353535, 0x00363636, 0x00373737, + 0x00383838, 0x00393939, 0x003a3a3a, 0x003b3b3b, + 0x003c3c3c, 0x003d3d3d, 0x003e3e3e, 0x003f3f3f, + 0x00404040, 0x00414141, 0x00424242, 0x00434343, + 0x00444444, 0x00454545, 0x00464646, 0x00474747, + 0x00484848, 0x00494949, 0x004a4a4a, 0x004b4b4b, + 0x004c4c4c, 0x004d4d4d, 0x004e4e4e, 0x004f4f4f, + 0x00505050, 0x00515151, 0x00525252, 0x00535353, + 0x00545454, 0x00555555, 0x00565656, 0x00575757, + 0x00585858, 0x00595959, 0x005a5a5a, 0x005b5b5b, + 0x005c5c5c, 0x005d5d5d, 0x005e5e5e, 0x005f5f5f, + 0x00606060, 0x00616161, 0x00626262, 0x00636363, + 0x00646464, 0x00656565, 0x00666666, 0x00676767, + 0x00686868, 0x00696969, 0x006a6a6a, 0x006b6b6b, + 0x006c6c6c, 0x006d6d6d, 0x006e6e6e, 0x006f6f6f, + 0x00707070, 0x00717171, 0x00727272, 0x00737373, + 0x00747474, 0x00757575, 0x00767676, 0x00777777, + 0x00787878, 0x00797979, 0x007a7a7a, 0x007b7b7b, + 0x007c7c7c, 0x007d7d7d, 0x007e7e7e, 0x007f7f7f, + 0x00808080, 0x00818181, 0x00828282, 0x00838383, + 0x00848484, 0x00858585, 0x00868686, 0x00878787, + 0x00888888, 0x00898989, 0x008a8a8a, 0x008b8b8b, + 0x008c8c8c, 0x008d8d8d, 0x008e8e8e, 0x008f8f8f, + 0x00909090, 0x00919191, 0x00929292, 0x00939393, + 0x00949494, 0x00959595, 0x00969696, 0x00979797, + 0x00989898, 0x00999999, 0x009a9a9a, 0x009b9b9b, + 0x009c9c9c, 0x009d9d9d, 0x009e9e9e, 0x009f9f9f, + 0x00a0a0a0, 0x00a1a1a1, 0x00a2a2a2, 0x00a3a3a3, + 0x00a4a4a4, 0x00a5a5a5, 0x00a6a6a6, 0x00a7a7a7, + 0x00a8a8a8, 0x00a9a9a9, 0x00aaaaaa, 0x00ababab, + 0x00acacac, 0x00adadad, 0x00aeaeae, 0x00afafaf, + 0x00b0b0b0, 0x00b1b1b1, 0x00b2b2b2, 0x00b3b3b3, + 0x00b4b4b4, 0x00b5b5b5, 0x00b6b6b6, 0x00b7b7b7, + 0x00b8b8b8, 0x00b9b9b9, 0x00bababa, 0x00bbbbbb, + 0x00bcbcbc, 0x00bdbdbd, 0x00bebebe, 0x00bfbfbf, + 0x00c0c0c0, 0x00c1c1c1, 0x00c2c2c2, 0x00c3c3c3, + 0x00c4c4c4, 0x00c5c5c5, 0x00c6c6c6, 0x00c7c7c7, + 0x00c8c8c8, 0x00c9c9c9, 0x00cacaca, 0x00cbcbcb, + 0x00cccccc, 0x00cdcdcd, 0x00cecece, 0x00cfcfcf, + 0x00d0d0d0, 0x00d1d1d1, 0x00d2d2d2, 0x00d3d3d3, + 0x00d4d4d4, 0x00d5d5d5, 0x00d6d6d6, 0x00d7d7d7, + 0x00d8d8d8, 0x00d9d9d9, 0x00dadada, 0x00dbdbdb, + 0x00dcdcdc, 0x00dddddd, 0x00dedede, 0x00dfdfdf, + 0x00e0e0e0, 0x00e1e1e1, 0x00e2e2e2, 0x00e3e3e3, + 0x00e4e4e4, 0x00e5e5e5, 0x00e6e6e6, 0x00e7e7e7, + 0x00e8e8e8, 0x00e9e9e9, 0x00eaeaea, 0x00ebebeb, + 0x00ececec, 0x00ededed, 0x00eeeeee, 0x00efefef, + 0x00f0f0f0, 0x00f1f1f1, 0x00f2f2f2, 0x00f3f3f3, + 0x00f4f4f4, 0x00f5f5f5, 0x00f6f6f6, 0x00f7f7f7, + 0x00f8f8f8, 0x00f9f9f9, 0x00fafafa, 0x00fbfbfb, + 0x00fcfcfc, 0x00fdfdfd, 0x00fefefe, 0x00ffffff +}; + +static struct kcal_data kcal_value = {255, 255, 255}; + +static int update_lcdc_lut(void) +{ + struct fb_cmap cmap; + int ret = 0; + + cmap.start = 0; + cmap.len = 256; + cmap.transp = NULL; + + cmap.red = (uint16_t *)&(kcal_value.red); + cmap.green = (uint16_t *)&(kcal_value.green); + cmap.blue = (uint16_t *)&(kcal_value.blue); + + ret = mdp_preset_lut_update_lcdc(&cmap, lcd_color_preset_lut); + + //if (ret) + // pr_err("%s: failed to set lut! %d\n", __func__, ret); + + return ret; +} + +static int kcal_set_values(int kcal_r, int kcal_g, int kcal_b) +{ + kcal_value.red = kcal_r; + kcal_value.green = kcal_g; + kcal_value.blue = kcal_b; + return 0; +} + +static int kcal_get_values(int *kcal_r, int *kcal_g, int *kcal_b) +{ + *kcal_r = kcal_value.red; + *kcal_g = kcal_value.green; + *kcal_b = kcal_value.blue; + return 0; +} + +static int kcal_refresh_values(void) +{ + return update_lcdc_lut(); +} + +static ssize_t kcal_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + int kcal_r = 0; + int kcal_g = 0; + int kcal_b = 0; + + if (!count) + return -EINVAL; + + sscanf(buf, "%d %d %d", &kcal_r, &kcal_g, &kcal_b); + kcal_ctrl_pdata->set_values(kcal_r, kcal_g, kcal_b); + return count; +} + +static ssize_t kcal_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int kcal_r = 0; + int kcal_g = 0; + int kcal_b = 0; + + kcal_ctrl_pdata->get_values(&kcal_r, &kcal_g, &kcal_b); + + return sprintf(buf, "%d %d %d\n", kcal_r, kcal_g, kcal_b); +} + +static ssize_t kcal_ctrl_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int cmd = 0; + if (!count) + return last_status_kcal_ctrl = -EINVAL; + + sscanf(buf, "%d", &cmd); + + if(cmd != 1) + return last_status_kcal_ctrl = -EINVAL; + + last_status_kcal_ctrl = kcal_ctrl_pdata->refresh_display(); + + if(last_status_kcal_ctrl) + return -EINVAL; + else + return count; +} + +static ssize_t kcal_ctrl_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + if(last_status_kcal_ctrl) + return sprintf(buf, "NG\n"); + else + return sprintf(buf, "OK\n"); +} + +static ssize_t kcal_version_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return sprintf(buf, "%d.%d\n", + KCAL_CTRL_MAJOR_VERSION, + KCAL_CTRL_MINOR_VERSION); +} + +static DEVICE_ATTR(power_rail, 0644, kcal_show, kcal_store); +static DEVICE_ATTR(power_rail_ctrl, 0644, kcal_ctrl_show, kcal_ctrl_store); +static DEVICE_ATTR(power_rail_version, 0444, kcal_version_show, NULL); + +static int kcal_ctrl_probe(struct platform_device *pdev) +{ + int rc = 0; + kcal_ctrl_pdata = pdev->dev.platform_data; + + if(!kcal_ctrl_pdata->set_values || !kcal_ctrl_pdata->get_values || + !kcal_ctrl_pdata->refresh_display) { + //pr_err("kcal function not registered\n"); + return -1; + } + + rc = device_create_file(&pdev->dev, &dev_attr_power_rail); + if(rc !=0) + return -1; + rc = device_create_file(&pdev->dev, &dev_attr_power_rail_ctrl); + if(rc !=0) + return -1; + rc = device_create_file(&pdev->dev, &dev_attr_power_rail_version); + if(rc !=0) + return -1; + + return 0; +} + +static struct kcal_platform_data kcal_pdata = { + .set_values = kcal_set_values, + .get_values = kcal_get_values, + .refresh_display = kcal_refresh_values +}; + +static struct platform_device kcal_platform_device = { + .name = KCAL_PLATFORM_NAME, + .dev = { + .platform_data = &kcal_pdata, + } +}; + +static struct platform_device *msm_panel_devices[] __initdata = { + &kcal_platform_device, +}; + +static struct platform_driver this_driver = { + .probe = kcal_ctrl_probe, + .driver = { + .name = KCAL_PLATFORM_NAME, + }, +}; + +typedef int (*funcPtr)(void); + +int __init kcal_ctrl_init(void) +{ +#if 0 + struct kcal_platform_data *kcalPtr; + + addr = kallsyms_lookup_name("klcd_pdata"); + kcalPtr = (struct kcal_platform_data *)addr; + kcalPtr->set_values = kcal_set_values; + kcalPtr->get_values = kcal_get_values; + kcalPtr->refresh_display = kcal_refresh_values; + +#endif + unsigned int addr; + + addr = kallsyms_lookup_name("update_preset_lcdc_lut"); + *(funcPtr *)addr = (funcPtr)update_lcdc_lut; + + platform_add_devices(msm_panel_devices, + ARRAY_SIZE(msm_panel_devices)); + + //pr_info("generic kcal ctrl initialized\n"); + //pr_info("generic kcal ctrl version %d.%d\n", + // KCAL_CTRL_MAJOR_VERSION, + // KCAL_CTRL_MINOR_VERSION); + return platform_driver_register(&this_driver); +} + +device_initcall(kcal_ctrl_init); + +//MODULE_DESCRIPTION("Generic MSM KCAL driver"); +MODULE_LICENSE("GPL and additional rights"); + diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c index a9e9af582ea..9c6b1778f81 100644 --- a/drivers/video/msm/mdp.c +++ b/drivers/video/msm/mdp.c @@ -171,10 +171,8 @@ static u32 mdp_irq; static uint32 mdp_prim_panel_type = NO_PANEL; #ifndef CONFIG_FB_MSM_MDP22 -#define MDP_HIST_LUT_SIZE (256) struct list_head mdp_hist_lut_list; DEFINE_MUTEX(mdp_hist_lut_list_mutex); -uint32_t last_lut[MDP_HIST_LUT_SIZE]; uint32_t mdp_block2base(uint32_t block) { @@ -301,15 +299,11 @@ static int mdp_hist_lut_destroy(void) static int mdp_hist_lut_init(void) { - int i; struct mdp_hist_lut_mgmt *temp; if (mdp_pp_initialized) return -EEXIST; - for (i = 0; i < MDP_HIST_LUT_SIZE; i++) - last_lut[i] = i | (i << 8) | (i << 16); - INIT_LIST_HEAD(&mdp_hist_lut_list); if (mdp_rev >= MDP_REV_30) { @@ -369,6 +363,7 @@ static int mdp_hist_lut_block2mgmt(uint32_t block, return ret; } +#define MDP_HIST_LUT_SIZE (256) static int mdp_hist_lut_write_off(struct mdp_hist_lut_data *data, struct mdp_hist_lut_info *info, uint32_t offset) { @@ -390,11 +385,9 @@ static int mdp_hist_lut_write_off(struct mdp_hist_lut_data *data, } mdp_clk_ctrl(1); mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE); - for (i = 0; i < MDP_HIST_LUT_SIZE; i++) { - last_lut[i] = element[i]; + for (i = 0; i < MDP_HIST_LUT_SIZE; i++) MDP_OUTP(MDP_BASE + base + offset + (0x400*(sel)) + (4*i), element[i]); - } mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); mdp_clk_ctrl(0); @@ -565,14 +558,15 @@ static int mdp_lut_hw_update(struct fb_cmap *cmap) copy_from_user(&b, cmap->blue++, sizeof(b))) return -EFAULT; - last_lut[i] = ((g & 0xff) | ((b & 0xff) << 8) | - ((r & 0xff) << 16)); #ifdef CONFIG_FB_MSM_MDP40 MDP_OUTP(MDP_BASE + 0x94800 + #else MDP_OUTP(MDP_BASE + 0x93800 + #endif - (0x400*mdp_lut_i) + cmap->start*4 + i*4, last_lut[i]); + (0x400*mdp_lut_i) + cmap->start*4 + i*4, + ((g & 0xff) | + ((b & 0xff) << 8) | + ((r & 0xff) << 16))); } return 0; @@ -664,11 +658,11 @@ int mdp_preset_lut_update_lcdc(struct fb_cmap *cmap, uint32_t *internal_lut) r = lut2r(internal_lut[i]); g = lut2g(internal_lut[i]); b = lut2b(internal_lut[i]); -#ifdef CONFIG_LCD_KCAL + r = scaled_by_kcal(r, *(cmap->red)); g = scaled_by_kcal(g, *(cmap->green)); b = scaled_by_kcal(b, *(cmap->blue)); -#endif + MDP_OUTP(MDP_BASE + 0x94800 + (0x400*mdp_lut_i) + cmap->start*4 + i*4, ((g & 0xff) | @@ -685,6 +679,7 @@ int mdp_preset_lut_update_lcdc(struct fb_cmap *cmap, uint32_t *internal_lut) return 0; } +EXPORT_SYMBOL(mdp_preset_lut_update_lcdc); #endif static void mdp_lut_enable(void) @@ -2426,7 +2421,6 @@ static int mdp_on(struct platform_device *pdev) { int ret = 0; struct msm_fb_data_type *mfd; - int i; mfd = platform_get_drvdata(pdev); pr_debug("%s:+\n", __func__); @@ -2452,11 +2446,6 @@ static int mdp_on(struct platform_device *pdev) mdp_clk_ctrl(1); mdp_bus_scale_restore_request(); mdp4_hw_init(); - /* Initialize HistLUT to last LUT */ - for (i = 0; i < MDP_HIST_LUT_SIZE; i++) { - MDP_OUTP(MDP_BASE + 0x94800 + i*4, last_lut[i]); - MDP_OUTP(MDP_BASE + 0x94C00 + i*4, last_lut[i]); - } mdp_lut_status_restore(); outpdw(MDP_BASE + 0x0038, mdp4_display_intf); if (mfd->panel.type == MIPI_CMD_PANEL) { diff --git a/drivers/video/msm/mdp.h b/drivers/video/msm/mdp.h index 4e6ab16c736..fffb67c6ac7 100644 --- a/drivers/video/msm/mdp.h +++ b/drivers/video/msm/mdp.h @@ -938,13 +938,11 @@ static inline void mdp_vid_quant_set(void) #define lut2g(lut) ((lut & G_MASK) >> G_SHIFT) #define lut2b(lut) ((lut & B_MASK) >> B_SHIFT) -#ifdef CONFIG_LCD_KCAL #define NUM_QLUT 256 #define MAX_KCAL_V (NUM_QLUT-1) #define scaled_by_kcal(rgb, kcal) \ (((((unsigned int)(rgb) * (unsigned int)(kcal)) << 16) / \ (unsigned int)MAX_KCAL_V) >> 16) -#endif int mdp_preset_lut_update_lcdc(struct fb_cmap *cmap, uint32_t *internal_lut); #endif #endif /* MDP_H */ diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c index b6094b45081..f325ee74347 100644 --- a/drivers/video/msm/msm_fb.c +++ b/drivers/video/msm/msm_fb.c @@ -1604,6 +1604,11 @@ static int msm_fb_register(struct msm_fb_data_type *mfd) ("FrameBuffer[%d] %dx%d size=%d bytes is registered successfully!\n", mfd->index, fbi->var.xres, fbi->var.yres, fbi->fix.smem_len); +#ifdef CONFIG_UPDATE_LCDC_LUT + if (msm_fb_pdata->update_lcdc_lut) + msm_fb_pdata->update_lcdc_lut(); +#endif + #ifdef CONFIG_FB_MSM_LOGO /* Flip buffer */ if (!load_565rle_image(INIT_IMAGE_FILE, bf_supported)) From 2ae054e6711b4619a5638ca20936a8f655302e84 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Sun, 22 Dec 2013 18:09:51 +0100 Subject: [PATCH 097/215] Cleanup and update Makefile/defconfig Signed-off-by: Tk-Glitch --- Makefile | 4 ++-- arch/arm/configs/flo_defconfig | 2 ++ arch/arm/mach-msm/lge/Kconfig | 14 -------------- 3 files changed, 4 insertions(+), 16 deletions(-) diff --git a/Makefile b/Makefile index ab3cf6f11ef..d15a9689027 100644 --- a/Makefile +++ b/Makefile @@ -366,10 +366,10 @@ CFLAGS_MODULE = $(MODFLAGS) AFLAGS_MODULE = $(MODFLAGS) LDFLAGS_MODULE = -T $(srctree)/scripts/module-common.lds ifdef CONFIG_CC_OPTIMIZE_ALOT -CFLAGS_KERNEL = -O3 -fgcse-lm -fgcse-sm -fsched-spec-load -fforce-addr -ffast-math -fsingle-precision-constant -mtune=cortex-a15 -marm -mfpu=neon-vfpv4 -funswitch-loops -mvectorize-with-neon-quad +CFLAGS_KERNEL = -O3 -munaligned-access -fgcse-lm -fgcse-sm -fsched-spec-load -fforce-addr -ffast-math -fsingle-precision-constant -mtune=cortex-a15 -marm -mfpu=neon-vfpv4 -funswitch-loops -mvectorize-with-neon-quad AFLAGS_KERNEL = -O3 -fgcse-lm -fgcse-sm -fsched-spec-load -fforce-addr -ffast-math -fsingle-precision-constant -mtune=cortex-a15 -marm -mfpu=neon-vfpv4 -funswitch-loops -mvectorize-with-neon-quad else -CFLAGS_KERNEL = -O2 -fgcse-lm -fgcse-sm -fsched-spec-load -fforce-addr -ffast-math -fsingle-precision-constant -mtune=cortex-a15 -marm -mfpu=neon-vfpv4 -funswitch-loops -mvectorize-with-neon-quad +CFLAGS_KERNEL = -O2 -munaligned-access -fgcse-lm -fgcse-sm -fsched-spec-load -fforce-addr -ffast-math -fsingle-precision-constant -mtune=cortex-a15 -marm -mfpu=neon-vfpv4 -funswitch-loops -mvectorize-with-neon-quad AFLAGS_KERNEL = CFLAGS_GCOV = -fprofile-arcs -ftest-coverage endif diff --git a/arch/arm/configs/flo_defconfig b/arch/arm/configs/flo_defconfig index a7eabb9791e..e9cc13aaa9a 100644 --- a/arch/arm/configs/flo_defconfig +++ b/arch/arm/configs/flo_defconfig @@ -557,6 +557,8 @@ CONFIG_MSM_HSIC_SYSMON=y # CONFIG_MSM_HSIC_SYSMON_TEST is not set CONFIG_MSM_CPU_PWRCTL=y CONFIG_FORCE_FAST_CHARGE=y +CONFIG_UPDATE_LCDC_LUT=y +CONFIG_LCD_KCAL=y # # System MMU diff --git a/arch/arm/mach-msm/lge/Kconfig b/arch/arm/mach-msm/lge/Kconfig index 8916d9ac0d9..908c370c576 100644 --- a/arch/arm/mach-msm/lge/Kconfig +++ b/arch/arm/mach-msm/lge/Kconfig @@ -15,20 +15,6 @@ config LGE_QFPROM_INTERFACE help LGE QFPROM DRIVER. -config UPDATE_LCDC_LUT - bool "Set initial Qualcomm LCDC lut" - default n - depends on MACH_LGE - help - Set initial Qualcomm LCDC Look Up Table. - -config LCD_KCAL - bool "Interface to calibrate LCD color temperature" - default n - depends on MACH_LGE && UPDATE_LCDC_LUT - help - Interface to calibrate LCD color temperature - config EARJACK_DEBUGGER bool "Earjack UART debugger support" depends on MACH_APQ8064_MAKO From e8da89a00c5b7184a7fb39e7f6f4937e91ca72c9 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Sun, 22 Dec 2013 18:29:58 +0100 Subject: [PATCH 098/215] Update aroma "changelog" --- .../aroma/META-INF/com/google/android/aroma/changelog.txt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/release/aroma/META-INF/com/google/android/aroma/changelog.txt b/release/aroma/META-INF/com/google/android/aroma/changelog.txt index 100c969c405..aa78f3b7c50 100755 --- a/release/aroma/META-INF/com/google/android/aroma/changelog.txt +++ b/release/aroma/META-INF/com/google/android/aroma/changelog.txt @@ -5,18 +5,20 @@ - L2/bus speed OC up to 1.49GHz / 4.96GBPS - GPU OC up to 627 MHz -- CPU governors : Faux's intellidemand, interactive, ondemand +- CPU governors : Faux's intellidemand, interactive, ondemand, smartmax - I/O schedulers: noop, deadline, row, cfq, fiops, sio - Kernel based thermal control by crpalmer and flar2 -- Kernel based msm_mpdecision hotplug driver by Showp1984's - - Faux123 Intelli-plug hotplug driver support +- Kernel based msm_mpdecision hotplug driver by Showp1984 +- Kernel based Intelli-plug hotplug driver by Faux123 +- Kernel based Input-Boost by Showp1984 - tni.andro's battery life extender support - Sweep2wake/Sweep2sleep/Doubletap2wake support by flar2 - Magnetic on/off - FauxSound support +- Panel color tweaking by Faux123 - Dynamic Fsync by Faux123 - USB fast charging support - USB OTG charge hack support by flar2 From ce950c4cc13196f1ef4d3220bbfaf8c72ffefc81 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Mon, 6 Jan 2014 19:12:32 +0100 Subject: [PATCH 099/215] Add back 400 MHz as selectable GPU speed. Also update Aroma settings. --- drivers/gpu/msm/kgsl_pwrctrl.c | 7 ++++++- .../aroma/META-INF/com/google/android/aroma-config | 1 + .../META-INF/com/google/android/updater-script | 14 ++++++++++---- release/aroma/config/buildconfig.sh | 4 +++- release/aroma/system/etc/init.d/99glitch | 13 ++++++++----- 5 files changed, 28 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c index e4f381857c2..1d808195efe 100644 --- a/drivers/gpu/msm/kgsl_pwrctrl.c +++ b/drivers/gpu/msm/kgsl_pwrctrl.c @@ -414,7 +414,11 @@ static int kgsl_pwrctrl_max_gpuclk_store(struct device *dev, if (ret != 1) return count; - if (val == 450000000) + if (val == 400000000) + { + SetGPUpll_config(0x1D, val); + } + else if (val == 450000000) { SetGPUpll_config(0x21, val); } @@ -665,6 +669,7 @@ static int kgsl_pwrctrl_gpu_available_frequencies_show( num_chars += snprintf(buf + num_chars, PAGE_SIZE, "%d ",545000000); num_chars += snprintf(buf + num_chars, PAGE_SIZE, "%d ",504000000); num_chars += snprintf(buf + num_chars, PAGE_SIZE, "%d ",450000000); + num_chars += snprintf(buf + num_chars, PAGE_SIZE, "%d ",400000000); } else num_chars += snprintf(buf + num_chars, PAGE_SIZE, "%d ",pwr->pwrlevels[index].gpu_freq); diff --git a/release/aroma/META-INF/com/google/android/aroma-config b/release/aroma/META-INF/com/google/android/aroma-config index 7b24d0420cd..8e16b212771 100755 --- a/release/aroma/META-INF/com/google/android/aroma-config +++ b/release/aroma/META-INF/com/google/android/aroma-config @@ -232,6 +232,7 @@ selectbox( selectbox( "GPU max frequency","Select the GPU's max frequency\n","@personalize","gpuclock.prop", "320MHz","(powersaving)",0, + "400MHz","(stock)",0, "450MHz","(improved)",1, "504MHz","(balanced)",0, "545MHz","(fast)",0, diff --git a/release/aroma/META-INF/com/google/android/updater-script b/release/aroma/META-INF/com/google/android/updater-script index 2dfb0145c56..164d1762227 100755 --- a/release/aroma/META-INF/com/google/android/updater-script +++ b/release/aroma/META-INF/com/google/android/updater-script @@ -141,30 +141,36 @@ endif; if file_getprop("/tmp/aroma/gpuclock.prop","selected.0") == "2" then - ui_print("450 MHz GPU Clock"); + ui_print("400 MHz GPU Clock"); endif; if file_getprop("/tmp/aroma/gpuclock.prop","selected.0") == "3" then - ui_print("504 MHz GPU Clock"); + ui_print("450 MHz GPU Clock"); endif; if file_getprop("/tmp/aroma/gpuclock.prop","selected.0") == "4" then - ui_print("545 MHz GPU Clock"); + ui_print("504 MHz GPU Clock"); endif; if file_getprop("/tmp/aroma/gpuclock.prop","selected.0") == "5" then - ui_print("600 MHz GPU Clock"); + ui_print("545 MHz GPU Clock"); endif; if file_getprop("/tmp/aroma/gpuclock.prop","selected.0") == "6" then + ui_print("600 MHz GPU Clock"); +endif; + +if + file_getprop("/tmp/aroma/gpuclock.prop","selected.0") == "7" + then ui_print("627 MHz GPU Clock"); endif; diff --git a/release/aroma/config/buildconfig.sh b/release/aroma/config/buildconfig.sh index 5d65895efd8..941d7aca68a 100755 --- a/release/aroma/config/buildconfig.sh +++ b/release/aroma/config/buildconfig.sh @@ -138,7 +138,7 @@ fi #GPU Clock GPU_OC=`cat /tmp/aroma/gpuclock.prop | cut -d '=' -f2` echo -e "\n\n##### Max GPU Clock #####\n# 1 320 MHz" >> $CONFIGFILE -echo -e "\n# 2 450 MHz\n# 3 504MHz\n# 4 545 MHz\n# 5 600 MHz\n# 6 627 MHz\n" >> $CONFIGFILE +echo -e "\n# 2 400 MHz\n# 3 450 MHz\n# 4 504MHz\n# 5 545 MHz\n# 6 600 MHz\n# 7 627 MHz\n" >> $CONFIGFILE if [ $GPU_OC = 1 ]; then echo "GPU_OC=1" >> $CONFIGFILE; elif [ $GPU_OC = 3 ]; then @@ -149,6 +149,8 @@ elif [ $GPU_OC = 5 ]; then echo "GPU_OC=5" >> $CONFIGFILE; elif [ $GPU_OC = 6 ]; then echo "GPU_OC=6" >> $CONFIGFILE; +elif [ $GPU_OC = 7 ]; then + echo "GPU_OC=7" >> $CONFIGFILE; else echo "GPU_OC=2" >> $CONFIGFILE; fi diff --git a/release/aroma/system/etc/init.d/99glitch b/release/aroma/system/etc/init.d/99glitch index 3dfa54fd4b4..a4294c060d0 100755 --- a/release/aroma/system/etc/init.d/99glitch +++ b/release/aroma/system/etc/init.d/99glitch @@ -165,20 +165,23 @@ if [ "`grep GPU_OC=1 $KERNEL_CONF`" ]; then echo 320000000 > /sys/devices/platform/kgsl-3d0.0/kgsl/kgsl-3d0/max_gpuclk; echo 320MHz GPU >> $KERNEL_LOGFILE; elif [ "`grep GPU_OC=3 $KERNEL_CONF`" ]; then + echo 450000000 > /sys/devices/platform/kgsl-3d0.0/kgsl/kgsl-3d0/max_gpuclk; + echo 450MHz GPU >> $KERNEL_LOGFILE; +elif [ "`grep GPU_OC=4 $KERNEL_CONF`" ]; then echo 504000000 > /sys/devices/platform/kgsl-3d0.0/kgsl/kgsl-3d0/max_gpuclk; echo 504MHz GPU >> $KERNEL_LOGFILE; -elif [ "`grep GPU_OC=4 $KERNEL_CONF`" ]; then +elif [ "`grep GPU_OC=5 $KERNEL_CONF`" ]; then echo 545000000 > /sys/devices/platform/kgsl-3d0.0/kgsl/kgsl-3d0/max_gpuclk; echo 545MHz GPU >> $KERNEL_LOGFILE; -elif [ "`grep GPU_OC=5 $KERNEL_CONF`" ]; then +elif [ "`grep GPU_OC=6 $KERNEL_CONF`" ]; then echo 600000000 > /sys/devices/platform/kgsl-3d0.0/kgsl/kgsl-3d0/max_gpuclk; echo 600MHz GPU >> $KERNEL_LOGFILE; -elif [ "`grep GPU_OC=6 $KERNEL_CONF`" ]; then +elif [ "`grep GPU_OC=7 $KERNEL_CONF`" ]; then echo 627000000 > /sys/devices/platform/kgsl-3d0.0/kgsl/kgsl-3d0/max_gpuclk; echo 627MHz GPU >> $KERNEL_LOGFILE; else - echo 450000000 > /sys/devices/platform/kgsl-3d0.0/kgsl/kgsl-3d0/max_gpuclk; - echo 450MHz GPU >> $KERNEL_LOGFILE; + echo 400000000 > /sys/devices/platform/kgsl-3d0.0/kgsl/kgsl-3d0/max_gpuclk; + echo 400MHz GPU >> $KERNEL_LOGFILE; fi #GPU Governor settings From f60084bc6a49de5299aaf06ac1f4bad67fda6c8d Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Mon, 6 Jan 2014 19:15:10 +0100 Subject: [PATCH 100/215] readahead: make context readahead more conservative This helps performance on moderately dense random reads on SSD. Transaction-Per-Second numbers provided by Taobao: QPS case ------------------------------------------------------- 7536 disable context readahead totally w/ patch: 7129 slower size rampup and start RA on the 3rd read 6717 slower size rampup w/o patch: 5581 unmodified context readahead Before, readahead will be started whenever reading page N+1 when it happen to read N recently. After patch, we'll only start readahead when *three* random reads happen to access pages N, N+1, N+2. The probability of this happening is extremely low for pure random reads, unless they are very dense, which actually deserves some readahead. Also start with a smaller readahead window. The impact to interleaved sequential reads should be small, because for a long run stream, the the small readahead window rampup phase is negletable. The context readahead actually benefits clustered random reads on HDD whose seek cost is pretty high. However as SSD is increasingly used for random read workloads it's better for the context readahead to concentrate on interleaved sequential reads. Another SSD rand read test from Miao # file size: 2GB # read IO amount: 625MB sysbench --test=fileio \ --max-requests=10000 \ --num-threads=1 \ --file-num=1 \ --file-block-size=64K \ --file-test-mode=rndrd \ --file-fsync-freq=0 \ --file-fsync-end=off run shows the performance of btrfs grows up from 69MB/s to 121MB/s, ext4 from 104MB/s to 121MB/s. Signed-off-by: Wu Fengguang Tested-by: Tao Ma Tested-by: Miao Xie Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/readahead.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mm/readahead.c b/mm/readahead.c index cbcbb02f3e2..d3a19647b3f 100644 --- a/mm/readahead.c +++ b/mm/readahead.c @@ -369,10 +369,10 @@ static int try_context_readahead(struct address_space *mapping, size = count_history_pages(mapping, ra, offset, max); /* - * no history pages: + * not enough history pages: * it could be a random read */ - if (!size) + if (size <= req_size) return 0; /* @@ -383,8 +383,8 @@ static int try_context_readahead(struct address_space *mapping, size *= 2; ra->start = offset; - ra->size = get_init_ra_size(size + req_size, max); - ra->async_size = ra->size; + ra->size = min(size + req_size, max); + ra->async_size = 1; return 1; } From a9c092a86b212b5cae80d91d2496d59b9d29c9ad Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Mon, 6 Jan 2014 19:16:53 +0100 Subject: [PATCH 101/215] block: Reserve only one queue tag for sync IO if only 3 tags are available In case a device has three tags available we still reserve two of them for sync IO. That leaves only a single tag for async IO such as writeback from flusher thread which results in poor performance. Allow async IO to consume two tags in case queue has three tag availabe to get a decent async write performance. This patch improves streaming write performance on a machine with such disk from ~21 MB/s to ~52 MB/s. Also postmark throughput in presence of streaming writer improves from 8 to 12 transactions per second so sync IO doesn't seem to be harmed in presence of heavy async writer. Signed-off-by: Jan Kara Signed-off-by: Jens Axboe --- block/blk-tag.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/block/blk-tag.c b/block/blk-tag.c index 4af6f5cc116..bc25b6e2d06 100644 --- a/block/blk-tag.c +++ b/block/blk-tag.c @@ -350,9 +350,16 @@ int blk_queue_start_tag(struct request_queue *q, struct request *rq) */ max_depth = bqt->max_depth; if (!rq_is_sync(rq) && max_depth > 1) { - max_depth -= 2; - if (!max_depth) + switch (max_depth) { + case 2: max_depth = 1; + break; + case 3: + max_depth = 2; + break; + default: + max_depth -= 2; + } if (q->in_flight[BLK_RW_ASYNC] > max_depth) return 1; } From f1a599b885cc8f08a25fe6f9f10cd70f2b47b7ce Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Mon, 6 Jan 2014 19:17:55 +0100 Subject: [PATCH 102/215] mm, vmalloc: use well-defined find_last_bit() func Our intention in here is to find last_bit within the region to flush. There is well-defined function, find_last_bit() for this purpose and its performance may be slightly better than current implementation. So change it. Signed-off-by: Joonsoo Kim Reviewed-by: Wanpeng Li Acked-by: Johannes Weiner Acked-by: Zhang Yanfei Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/vmalloc.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 07a3858a9c1..23b5aed77b0 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -1022,15 +1022,16 @@ void vm_unmap_aliases(void) rcu_read_lock(); list_for_each_entry_rcu(vb, &vbq->free, free_list) { - int i; + int i, j; spin_lock(&vb->lock); i = find_first_bit(vb->dirty_map, VMAP_BBMAP_BITS); - while (i < VMAP_BBMAP_BITS) { + if (i < VMAP_BBMAP_BITS) { unsigned long s, e; - int j; - j = find_next_zero_bit(vb->dirty_map, - VMAP_BBMAP_BITS, i); + + j = find_last_bit(vb->dirty_map, + VMAP_BBMAP_BITS); + j = j + 1; /* need exclusive index */ s = vb->va->va_start + (i << PAGE_SHIFT); e = vb->va->va_start + (j << PAGE_SHIFT); @@ -1040,10 +1041,6 @@ void vm_unmap_aliases(void) start = s; if (e > end) end = e; - - i = j; - i = find_next_bit(vb->dirty_map, - VMAP_BBMAP_BITS, i); } spin_unlock(&vb->lock); } From ba15006d41383726683d9a335b8379d7ff8be99c Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Mon, 6 Jan 2014 19:18:38 +0100 Subject: [PATCH 103/215] mm, vmalloc: remove useless variable in vmap_block vbq in vmap_block isn't used. So remove it. Signed-off-by: Joonsoo Kim Reviewed-by: Wanpeng Li Acked-by: Johannes Weiner Acked-by: Zhang Yanfei Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/vmalloc.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 23b5aed77b0..58b1232cda7 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -742,7 +742,6 @@ struct vmap_block_queue { struct vmap_block { spinlock_t lock; struct vmap_area *va; - struct vmap_block_queue *vbq; unsigned long free, dirty; DECLARE_BITMAP(alloc_map, VMAP_BBMAP_BITS); DECLARE_BITMAP(dirty_map, VMAP_BBMAP_BITS); @@ -822,7 +821,6 @@ static struct vmap_block *new_vmap_block(gfp_t gfp_mask) radix_tree_preload_end(); vbq = &get_cpu_var(vmap_block_queue); - vb->vbq = vbq; spin_lock(&vbq->lock); list_add_rcu(&vb->free_list, &vbq->free); spin_unlock(&vbq->lock); From 219841096e26aafbdab8791ab12ded9131f94f52 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Mon, 6 Jan 2014 19:20:17 +0100 Subject: [PATCH 104/215] alarmtimer: implement minimum alarm interval for allowing suspend alarmtimer suspend return -EBUSY if the next alarm will fire in less than 2 seconds. This allows one RTC seconds tick to occur subsequent to this check before the alarm wakeup time is set, ensuring the wakeup time is still in the future (assuming the RTC does not tick one more second prior to setting the alarm). If suspend is rejected, hold a wakeup source for 2 seconds to process the alarm prior to reattempting suspend. Signed-off-by: Todd Poynor --- kernel/time/alarmtimer.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c index aa27d391bfc..f979d852f81 100644 --- a/kernel/time/alarmtimer.c +++ b/kernel/time/alarmtimer.c @@ -46,6 +46,8 @@ static struct alarm_base { static ktime_t freezer_delta; static DEFINE_SPINLOCK(freezer_delta_lock); +static struct wakeup_source *ws; + #ifdef CONFIG_RTC_CLASS /* rtc timer and device for setting alarm wakeups at suspend */ static struct rtc_timer rtctimer; @@ -250,6 +252,7 @@ static int alarmtimer_suspend(struct device *dev) unsigned long flags; struct rtc_device *rtc; int i; + int ret; spin_lock_irqsave(&freezer_delta_lock, flags); min = freezer_delta; @@ -279,8 +282,10 @@ static int alarmtimer_suspend(struct device *dev) if (min.tv64 == 0) return 0; - /* XXX - Should we enforce a minimum sleep time? */ - WARN_ON(min.tv64 < NSEC_PER_SEC); + if (ktime_to_ns(min) < 2 * NSEC_PER_SEC) { + __pm_wakeup_event(ws, 2 * MSEC_PER_SEC); + return -EBUSY; + } /* Setup an rtc timer to fire that far in the future */ rtc_timer_cancel(rtc, &rtctimer); @@ -288,9 +293,11 @@ static int alarmtimer_suspend(struct device *dev) now = rtc_tm_to_ktime(tm); now = ktime_add(now, min); - rtc_timer_start(rtc, &rtctimer, now, ktime_set(0, 0)); - - return 0; + /* Set alarm, if in the past reject suspend briefly to handle */ + ret = rtc_timer_start(rtc, &rtctimer, now, ktime_set(0, 0)); + if (ret < 0) + __pm_wakeup_event(ws, 1 * MSEC_PER_SEC); + return ret; } #else static int alarmtimer_suspend(struct device *dev) @@ -821,6 +828,7 @@ static int __init alarmtimer_init(void) error = PTR_ERR(pdev); goto out_drv; } + ws = wakeup_source_register("alarmtimer"); return 0; out_drv: From ecd6bdcdc1518cebe2edbaaa42e6b1c649081083 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Mon, 6 Jan 2014 19:21:00 +0100 Subject: [PATCH 105/215] alarmtimer: Use hrtimer per-alarm instead of per-base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Arve HjønnevÃ¥g reported numerous crashes from the "BUG_ON(timer->state != HRTIMER_STATE_CALLBACK)" check in __run_hrtimer after it called alarmtimer_fired. It ends up the alarmtimer code was not properly handling possible failures of hrtimer_try_to_cancel, and because these faulres occur when the underlying base hrtimer is being run, this limits the ability to properly handle modifications to any alarmtimers on that base. Because much of the logic duplicates the hrtimer logic, it seems that we might as well have a per-alarmtimer hrtimer, and avoid the extra complextity of trying to multiplex many alarmtimers off of one hrtimer. Thus this patch moves the hrtimer to the alarm structure and simplifies the management logic. Cc: Arve HjønnevÃ¥g Cc: Colin Cross Cc: Thomas Gleixner Reported-by: Arve HjønnevÃ¥g Signed-off-by: John Stultz --- include/linux/alarmtimer.h | 3 +- kernel/time/alarmtimer.c | 94 +++++++++++--------------------------- 2 files changed, 29 insertions(+), 68 deletions(-) diff --git a/include/linux/alarmtimer.h b/include/linux/alarmtimer.h index 96c5c249b08..f122c9fbf8c 100644 --- a/include/linux/alarmtimer.h +++ b/include/linux/alarmtimer.h @@ -35,6 +35,7 @@ enum alarmtimer_restart { */ struct alarm { struct timerqueue_node node; + struct hrtimer timer; enum alarmtimer_restart (*function)(struct alarm *, ktime_t now); enum alarmtimer_type type; int state; @@ -43,7 +44,7 @@ struct alarm { void alarm_init(struct alarm *alarm, enum alarmtimer_type type, enum alarmtimer_restart (*function)(struct alarm *, ktime_t)); -void alarm_start(struct alarm *alarm, ktime_t start); +int alarm_start(struct alarm *alarm, ktime_t start); int alarm_try_to_cancel(struct alarm *alarm); int alarm_cancel(struct alarm *alarm); diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c index f979d852f81..b07241cc809 100644 --- a/kernel/time/alarmtimer.c +++ b/kernel/time/alarmtimer.c @@ -37,7 +37,6 @@ static struct alarm_base { spinlock_t lock; struct timerqueue_head timerqueue; - struct hrtimer timer; ktime_t (*gettime)(void); clockid_t base_clockid; } alarm_bases[ALARM_NUMTYPE]; @@ -132,21 +131,17 @@ static inline void alarmtimer_rtc_timer_init(void) { } * @base: pointer to the base where the timer is being run * @alarm: pointer to alarm being enqueued. * - * Adds alarm to a alarm_base timerqueue and if necessary sets - * an hrtimer to run. + * Adds alarm to a alarm_base timerqueue * * Must hold base->lock when calling. */ static void alarmtimer_enqueue(struct alarm_base *base, struct alarm *alarm) { + if (alarm->state & ALARMTIMER_STATE_ENQUEUED) + timerqueue_del(&base->timerqueue, &alarm->node); + timerqueue_add(&base->timerqueue, &alarm->node); alarm->state |= ALARMTIMER_STATE_ENQUEUED; - - if (&alarm->node == timerqueue_getnext(&base->timerqueue)) { - hrtimer_try_to_cancel(&base->timer); - hrtimer_start(&base->timer, alarm->node.expires, - HRTIMER_MODE_ABS); - } } /** @@ -154,28 +149,17 @@ static void alarmtimer_enqueue(struct alarm_base *base, struct alarm *alarm) * @base: pointer to the base where the timer is running * @alarm: pointer to alarm being removed * - * Removes alarm to a alarm_base timerqueue and if necessary sets - * a new timer to run. + * Removes alarm to a alarm_base timerqueue * * Must hold base->lock when calling. */ static void alarmtimer_remove(struct alarm_base *base, struct alarm *alarm) { - struct timerqueue_node *next = timerqueue_getnext(&base->timerqueue); - if (!(alarm->state & ALARMTIMER_STATE_ENQUEUED)) return; timerqueue_del(&base->timerqueue, &alarm->node); alarm->state &= ~ALARMTIMER_STATE_ENQUEUED; - - if (next == &alarm->node) { - hrtimer_try_to_cancel(&base->timer); - next = timerqueue_getnext(&base->timerqueue); - if (!next) - return; - hrtimer_start(&base->timer, next->expires, HRTIMER_MODE_ABS); - } } @@ -190,42 +174,23 @@ static void alarmtimer_remove(struct alarm_base *base, struct alarm *alarm) */ static enum hrtimer_restart alarmtimer_fired(struct hrtimer *timer) { - struct alarm_base *base = container_of(timer, struct alarm_base, timer); - struct timerqueue_node *next; + struct alarm *alarm = container_of(timer, struct alarm, timer); + struct alarm_base *base = &alarm_bases[alarm->type]; unsigned long flags; - ktime_t now; int ret = HRTIMER_NORESTART; int restart = ALARMTIMER_NORESTART; spin_lock_irqsave(&base->lock, flags); - now = base->gettime(); - while ((next = timerqueue_getnext(&base->timerqueue))) { - struct alarm *alarm; - ktime_t expired = next->expires; - - if (expired.tv64 > now.tv64) - break; - - alarm = container_of(next, struct alarm, node); - - timerqueue_del(&base->timerqueue, &alarm->node); - alarm->state &= ~ALARMTIMER_STATE_ENQUEUED; - - alarm->state |= ALARMTIMER_STATE_CALLBACK; - spin_unlock_irqrestore(&base->lock, flags); - if (alarm->function) - restart = alarm->function(alarm, now); - spin_lock_irqsave(&base->lock, flags); - alarm->state &= ~ALARMTIMER_STATE_CALLBACK; + alarmtimer_remove(base, alarm); + spin_unlock_irqrestore(&base->lock, flags); - if (restart != ALARMTIMER_NORESTART) { - timerqueue_add(&base->timerqueue, &alarm->node); - alarm->state |= ALARMTIMER_STATE_ENQUEUED; - } - } + if (alarm->function) + restart = alarm->function(alarm, base->gettime()); - if (next) { - hrtimer_set_expires(&base->timer, next->expires); + spin_lock_irqsave(&base->lock, flags); + if (restart != ALARMTIMER_NORESTART) { + hrtimer_set_expires(&alarm->timer, alarm->node.expires); + alarmtimer_enqueue(base, alarm); ret = HRTIMER_RESTART; } spin_unlock_irqrestore(&base->lock, flags); @@ -331,6 +296,9 @@ void alarm_init(struct alarm *alarm, enum alarmtimer_type type, enum alarmtimer_restart (*function)(struct alarm *, ktime_t)) { timerqueue_init(&alarm->node); + hrtimer_init(&alarm->timer, alarm_bases[type].base_clockid, + HRTIMER_MODE_ABS); + alarm->timer.function = alarmtimer_fired; alarm->function = function; alarm->type = type; alarm->state = ALARMTIMER_STATE_INACTIVE; @@ -341,17 +309,19 @@ void alarm_init(struct alarm *alarm, enum alarmtimer_type type, * @alarm: ptr to alarm to set * @start: time to run the alarm */ -void alarm_start(struct alarm *alarm, ktime_t start) +int alarm_start(struct alarm *alarm, ktime_t start) { struct alarm_base *base = &alarm_bases[alarm->type]; unsigned long flags; + int ret; spin_lock_irqsave(&base->lock, flags); - if (alarmtimer_active(alarm)) - alarmtimer_remove(base, alarm); alarm->node.expires = start; alarmtimer_enqueue(base, alarm); + ret = hrtimer_start(&alarm->timer, alarm->node.expires, + HRTIMER_MODE_ABS); spin_unlock_irqrestore(&base->lock, flags); + return ret; } /** @@ -365,18 +335,12 @@ int alarm_try_to_cancel(struct alarm *alarm) { struct alarm_base *base = &alarm_bases[alarm->type]; unsigned long flags; - int ret = -1; - spin_lock_irqsave(&base->lock, flags); - - if (alarmtimer_callback_running(alarm)) - goto out; + int ret; - if (alarmtimer_is_queued(alarm)) { + spin_lock_irqsave(&base->lock, flags); + ret = hrtimer_try_to_cancel(&alarm->timer); + if (ret >= 0) alarmtimer_remove(base, alarm); - ret = 1; - } else - ret = 0; -out: spin_unlock_irqrestore(&base->lock, flags); return ret; } @@ -809,10 +773,6 @@ static int __init alarmtimer_init(void) for (i = 0; i < ALARM_NUMTYPE; i++) { timerqueue_init_head(&alarm_bases[i].timerqueue); spin_lock_init(&alarm_bases[i].lock); - hrtimer_init(&alarm_bases[i].timer, - alarm_bases[i].base_clockid, - HRTIMER_MODE_ABS); - alarm_bases[i].timer.function = alarmtimer_fired; } error = alarmtimer_rtc_interface_setup(); From ef3b87527942a83add88982e73c76e0ae69ce6c0 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Mon, 6 Jan 2014 20:21:12 +0100 Subject: [PATCH 106/215] [sweep2wake]: adjust shortsweep distance Signed-off-by: flar2 --- drivers/input/touchscreen/ektf3k.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/touchscreen/ektf3k.c b/drivers/input/touchscreen/ektf3k.c index a51f1d586cf..0ce615955cb 100755 --- a/drivers/input/touchscreen/ektf3k.c +++ b/drivers/input/touchscreen/ektf3k.c @@ -866,7 +866,7 @@ static ssize_t elan_ktf3k_shortsweep_dump(struct device *dev, s2w_begin_v = 400 ; s2w_end_v = 950; s2w_begin_h = 650; - s2w_end_h = 1600; + s2w_end_h = 1750; } else { s2w_begin_v = 150; s2w_end_v = 1200; From 9d8e626407686a7e40134c448e4de7c92dd633d5 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Mon, 6 Jan 2014 20:23:52 +0100 Subject: [PATCH 107/215] nohz: Reduce overhead under high-freq idling patterns One testbox of mine (Intel Nehalem, 16-way) uses MWAIT for its idle routine, which apparently can break out of its idle loop rather frequently, with high frequency. In that case NO_HZ_FULL=y kernels show high ksoftirqd overhead and constant context switching, because tick_nohz_stop_sched_tick() will, if delta_jiffies == 0, mis-identify this as a timer event - activating the TIMER_SOFTIRQ, which wakes up ksoftirqd. Fix this by treating delta_jiffies == 0 the same way we treat other short wakeups, delta_jiffies == 1. Cc: Frederic Weisbecker Cc: Chris Metcalf Cc: Christoph Lameter Cc: Geoff Levand Cc: Gilad Ben Yossef Cc: Hakan Akkan Cc: Kevin Hilman Cc: Li Zhong Cc: Oleg Nesterov Cc: Paul E. McKenney Cc: Paul Gortmaker Cc: Peter Zijlstra Cc: Steven Rostedt Signed-off-by: Ingo Molnar Signed-off-by: franciscofranco --- kernel/time/tick-sched.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index fb3970e15a1..7b8e6455feb 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -337,11 +337,12 @@ static void tick_nohz_stop_sched_tick(struct tick_sched *ts) next_jiffies = get_next_timer_interrupt(last_jiffies); delta_jiffies = next_jiffies - last_jiffies; } + /* - * Do not stop the tick, if we are only one off - * or if the cpu is required for rcu + * Do not stop the tick, if we are only one off (or less) + * or if the cpu is required for RCU: */ - if (!ts->tick_stopped && delta_jiffies == 1) + if (!ts->tick_stopped && delta_jiffies <= 1) goto out; /* Schedule the tick, if we are at least one jiffie off */ From 45fa55be13ac1932cc09459debcfeaf5525dd60d Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Mon, 6 Jan 2014 20:34:35 +0100 Subject: [PATCH 108/215] msm: kgsl: change the load calculation equation & fix a couple of bugs, one of 'em was keeping the GPU on 320MHz if the GPU was not sleeping. Signed-off-by: franciscofranco --- drivers/gpu/msm/kgsl_pwrscale_trustzone.c | 62 ++++++++--------------- 1 file changed, 22 insertions(+), 40 deletions(-) diff --git a/drivers/gpu/msm/kgsl_pwrscale_trustzone.c b/drivers/gpu/msm/kgsl_pwrscale_trustzone.c index 378575f8d73..ba9d53a83b8 100644 --- a/drivers/gpu/msm/kgsl_pwrscale_trustzone.c +++ b/drivers/gpu/msm/kgsl_pwrscale_trustzone.c @@ -85,10 +85,12 @@ static struct clk_scaling_stats { unsigned long total_time_ms; unsigned long busy_time_ms; unsigned long threshold; + unsigned int load; } gpu_stats = { .total_time_ms = 0, .busy_time_ms = 0, .threshold = 0, + .load = 0, }; static ssize_t tz_governor_show(struct kgsl_device *device, @@ -173,48 +175,37 @@ static void tz_idle(struct kgsl_device *device, struct kgsl_pwrscale *pwrscale) priv->bin.total_time += stats.total_time; priv->bin.busy_time += stats.busy_time; + if (stats.total_time == 0 || priv->bin.busy_time < FLOOR) + return; + if (time_is_after_jiffies(window_time + msecs_to_jiffies(sample_time_ms))) return; - gpu_stats.total_time_ms = jiffies_to_msecs(jiffies - window_time); - do_div(priv->bin.busy_time, USEC_PER_MSEC); - gpu_stats.busy_time_ms = priv->bin.busy_time; + if (stats.busy_time >= 1 << 24 || stats.total_time >= 1 << 24) + { + stats.busy_time >>= 7; + stats.total_time >>= 7; + } - /* if busy time is 0 and we're already on the lowest pwrlevel, bail early */ - if (!gpu_stats.busy_time_ms && pwr->active_pwrlevel == pwr->min_pwrlevel) - return; + gpu_stats.load = (100 * priv->bin.busy_time); + do_div(gpu_stats.load, priv->bin.total_time); if (debug) { - pr_info("GPU current load: %lu\n", gpu_stats.busy_time_ms); - pr_info("GPU total time load: %lu\n", gpu_stats.total_time_ms); + pr_info("GPU load: %u\n", gpu_stats.load); pr_info("GPU frequency: %d\n", pwr->pwrlevels[pwr->active_pwrlevel].gpu_freq); } - /* - * Scale the up_threshold value based on the active_pwrlevel. We have - * 4 different levels: - * 3 = 128MHz - * 2 = 200MHz - * 1 = 320MHz - * 0 = 400MHz - * - * Making the up_threshold value lower if the active level is 2 or 3 will - * possibly improve smoothness while scrolling or open applications with - * a lot of images and what not. With a Full HD panel like Flo/Deb I could - * notice a few frame drops while this algorithm didn't scale past 128MHz - * on simple operations. This is fixed with up_threshold being scaled - */ + gpu_stats.threshold = up_threshold; if (pwr->active_pwrlevel == pwr->min_pwrlevel) gpu_stats.threshold = up_threshold / pwr->active_pwrlevel; - else if (pwr->active_pwrlevel > 0) + else if (pwr->active_pwrlevel < pwr->min_pwrlevel && + pwr->active_pwrlevel > pwr->max_pwrlevel) gpu_stats.threshold = up_threshold - up_differential; - else - gpu_stats.threshold = up_threshold; - if ((gpu_stats.busy_time_ms * 100) > (gpu_stats.total_time_ms * gpu_stats.threshold)) + if (gpu_stats.load > gpu_stats.threshold) { if (gpu_pref_counter < 100) ++gpu_pref_counter; @@ -223,12 +214,12 @@ static void tz_idle(struct kgsl_device *device, struct kgsl_pwrscale *pwrscale) kgsl_pwrctrl_pwrlevel_change(device, pwr->active_pwrlevel - 1); } - else if ((gpu_stats.busy_time_ms * 100) < (gpu_stats.total_time_ms * down_threshold)) + else if (gpu_stats.load < down_threshold) { if (gpu_pref_counter > 0) --gpu_pref_counter; - if (pwr->active_pwrlevel < pwr->max_pwrlevel) + if (pwr->active_pwrlevel < pwr->min_pwrlevel) kgsl_pwrctrl_pwrlevel_change(device, pwr->active_pwrlevel + 1); } @@ -250,21 +241,12 @@ static void tz_sleep(struct kgsl_device *device, struct tz_priv *priv = pwrscale->priv; struct kgsl_pwrctrl *pwr = &device->pwrctrl; - /* - * We don't want the GPU to go to sleep if the busy_time_ms calculated on - * idle routine is not below down_threshold. This is just a measure of - * precaution - */ - if ((gpu_stats.busy_time_ms * 100) < - (gpu_stats.total_time_ms * down_threshold)) - { - kgsl_pwrctrl_pwrlevel_change(device, pwr->min_pwrlevel); - } + kgsl_pwrctrl_pwrlevel_change(device, pwr->min_pwrlevel); if (debug) { - pr_info("GPU frequency: %d\n", - pwr->pwrlevels[pwr->active_pwrlevel].gpu_freq); + pr_info("GPU sleep frequency: %d\n", + pwr->pwrlevels[pwr->active_pwrlevel].gpu_freq); } gpu_pref_counter = 0; From 4c6b22e682892ec0abde03d3a26d576ce74b313e Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Mon, 6 Jan 2014 20:35:30 +0100 Subject: [PATCH 109/215] msm: kgsl: don't forcefully ramp down on sleep if there's still load higher than down_threshold. Signed-off-by: franciscofranco --- drivers/gpu/msm/kgsl_pwrscale_trustzone.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/msm/kgsl_pwrscale_trustzone.c b/drivers/gpu/msm/kgsl_pwrscale_trustzone.c index ba9d53a83b8..4e448823c0c 100644 --- a/drivers/gpu/msm/kgsl_pwrscale_trustzone.c +++ b/drivers/gpu/msm/kgsl_pwrscale_trustzone.c @@ -70,7 +70,7 @@ static int __secure_tz_entry(u32 cmd, u32 val, u32 id) unsigned long window_time = 0; unsigned long sample_time_ms = 100; -unsigned int up_threshold = 60; +unsigned int up_threshold = 50; unsigned int down_threshold = 25; unsigned int up_differential = 10; bool debug = 0; @@ -241,7 +241,9 @@ static void tz_sleep(struct kgsl_device *device, struct tz_priv *priv = pwrscale->priv; struct kgsl_pwrctrl *pwr = &device->pwrctrl; - kgsl_pwrctrl_pwrlevel_change(device, pwr->min_pwrlevel); + /* Do not ramp down forcelfully if the load is still above down_threshold */ + if (gpu_stats.load < down_threshold) + kgsl_pwrctrl_pwrlevel_change(device, pwr->min_pwrlevel); if (debug) { From 88774f03aa33d702cb128b90989a0d2899e3e5f5 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Mon, 6 Jan 2014 20:36:14 +0100 Subject: [PATCH 110/215] msm: kgsl: remove the sample_time_ms and let the governor run its idle_check freely like Qualcomm intends. I was seeing some frames being lost because the sample_time_ms was too big. Signed-off-by: franciscofranco --- drivers/gpu/msm/kgsl_pwrscale_trustzone.c | 29 ++++++++++------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/msm/kgsl_pwrscale_trustzone.c b/drivers/gpu/msm/kgsl_pwrscale_trustzone.c index 4e448823c0c..cdb56315150 100644 --- a/drivers/gpu/msm/kgsl_pwrscale_trustzone.c +++ b/drivers/gpu/msm/kgsl_pwrscale_trustzone.c @@ -68,27 +68,20 @@ static int __secure_tz_entry(u32 cmd, u32 val, u32 id) #endif /* CONFIG_MSM_SCM */ #endif -unsigned long window_time = 0; -unsigned long sample_time_ms = 100; unsigned int up_threshold = 50; unsigned int down_threshold = 25; unsigned int up_differential = 10; bool debug = 0; unsigned long gpu_pref_counter; -module_param(sample_time_ms, long, 0664); module_param(up_threshold, int, 0664); module_param(down_threshold, int, 0664); module_param(debug, bool, 0664); static struct clk_scaling_stats { - unsigned long total_time_ms; - unsigned long busy_time_ms; unsigned long threshold; unsigned int load; } gpu_stats = { - .total_time_ms = 0, - .busy_time_ms = 0, .threshold = 0, .load = 0, }; @@ -178,15 +171,22 @@ static void tz_idle(struct kgsl_device *device, struct kgsl_pwrscale *pwrscale) if (stats.total_time == 0 || priv->bin.busy_time < FLOOR) return; - if (time_is_after_jiffies(window_time + msecs_to_jiffies(sample_time_ms))) - return; - if (stats.busy_time >= 1 << 24 || stats.total_time >= 1 << 24) { stats.busy_time >>= 7; stats.total_time >>= 7; } + /* + * If there is an extended block of busy processing, + * increase frequency. Otherwise run the normal algorithm. + */ + if (priv->bin.busy_time > CEILING) + { + kgsl_pwrctrl_pwrlevel_change(device, pwr->max_pwrlevel); + goto clear; + } + gpu_stats.load = (100 * priv->bin.busy_time); do_div(gpu_stats.load, priv->bin.total_time); @@ -224,9 +224,9 @@ static void tz_idle(struct kgsl_device *device, struct kgsl_pwrscale *pwrscale) pwr->active_pwrlevel + 1); } +clear: priv->bin.total_time = 0; priv->bin.busy_time = 0; - window_time = jiffies; } static void tz_busy(struct kgsl_device *device, @@ -241,9 +241,7 @@ static void tz_sleep(struct kgsl_device *device, struct tz_priv *priv = pwrscale->priv; struct kgsl_pwrctrl *pwr = &device->pwrctrl; - /* Do not ramp down forcelfully if the load is still above down_threshold */ - if (gpu_stats.load < down_threshold) - kgsl_pwrctrl_pwrlevel_change(device, pwr->min_pwrlevel); + kgsl_pwrctrl_pwrlevel_change(device, pwr->min_pwrlevel); if (debug) { @@ -254,9 +252,6 @@ static void tz_sleep(struct kgsl_device *device, gpu_pref_counter = 0; priv->bin.total_time = 0; priv->bin.busy_time = 0; - window_time = jiffies; - - return; } #ifdef CONFIG_MSM_SCM From c5c4b8aac7e3dd4f8cf1da84859ba6d8657e57b8 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Mon, 6 Jan 2014 20:42:07 +0100 Subject: [PATCH 111/215] Optimize deadline iosched for our devices Signed-off-by: Tk-Glitch --- block/deadline-iosched.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/block/deadline-iosched.c b/block/deadline-iosched.c index 7bf12d793fc..3158890bb44 100644 --- a/block/deadline-iosched.c +++ b/block/deadline-iosched.c @@ -17,10 +17,10 @@ /* * See Documentation/block/deadline-iosched.txt */ -static const int read_expire = HZ / 2; /* max time before a read is submitted. */ -static const int write_expire = 5 * HZ; /* ditto for writes, these limits are SOFT! */ -static const int writes_starved = 2; /* max times reads can starve a write */ -static const int fifo_batch = 16; /* # of sequential requests treated as one +static const int read_expire = 350; /* max time before a read is submitted. */ +static const int write_expire = 75; /* ditto for writes, these limits are SOFT! */ +static const int writes_starved = 1; /* max times reads can starve a write */ +static const int fifo_batch = 1; /* # of sequential requests treated as one by the above parameters. For throughput. */ struct deadline_data { @@ -230,7 +230,7 @@ static inline int deadline_check_fifo(struct deadline_data *dd, int ddir) /* * rq is expired! */ - if (time_after(jiffies, rq_fifo_time(rq))) + if (time_after_eq(jiffies, rq_fifo_time(rq))) return 1; return 0; From ff85a43af883dc4fbfad1b3aaf177e306f6396d5 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Mon, 6 Jan 2014 21:11:42 +0100 Subject: [PATCH 112/215] Aroma : Update binary --- .../META-INF/com/google/android/aroma-config | 2 +- .../META-INF/com/google/android/update-binary | Bin 627620 -> 627580 bytes .../google/android/update-binary-installer | Bin 232504 -> 258772 bytes 3 files changed, 1 insertion(+), 1 deletion(-) diff --git a/release/aroma/META-INF/com/google/android/aroma-config b/release/aroma/META-INF/com/google/android/aroma-config index 8e16b212771..eccff5237c3 100755 --- a/release/aroma/META-INF/com/google/android/aroma-config +++ b/release/aroma/META-INF/com/google/android/aroma-config @@ -21,7 +21,7 @@ # amarullz - xda-developers # http://www.amarullz.com/ # -# Binary Version : 2.70B6 +# Binary Version : 2.70B # Binary Codename : Flamboyan # ### INFO: diff --git a/release/aroma/META-INF/com/google/android/update-binary b/release/aroma/META-INF/com/google/android/update-binary index 2e5e77dd925af713380748417ef9a9eb435e17ef..177f535597e5976cb5f8634de7020c81a3d21f44 100755 GIT binary patch literal 627580 zcmb@v3tUvy+CRS5-g{;?GXo5Qi3m7=7jEj{C8;cjaoAo(9ZFaftO56&zbSk3#CUib&Sc_;2>L2=J#EDz^wD0_y7BS{x6@; zn!Wd0>$$FHJ?mMQy;+_J zFAxb!8kT1w{_8x>o1gOJIXV!y)=j2{`OBTM<(d!OnzQVCcFJfatNsnv9RQ5w8t7F;d=2336lwIzXM_VtHip1IO z^PNMgLAroMI_Qd^D-y%CPWbQ+9vFO&Y}!hIgD0Tn9D9YVK6GQ#dun^!7f}xG_oInq z`~Yo#L~z|lh@M#1U!&Dc*C@%jLaTqc*5>m?5KG>*3PS2x8Am2w=B+jhXB}ZCWYQ0R z0Sv{}fGdY4Nem2|6!7I@R z>Upn;Sg%m)q$?_I@I@^nIPjn;L^-WKdX@2Z7knZA3gZp9>M8We@C6Ioy;fu8t^XT* z%T#=4RD29Cqt}V^Y2_ud7Jw`;F|p#Tvp@W`~1E2 zKgc`jf57?VgE)1uUV&s>R{7KMxVP5*mcO+B0oS9y!DR|DH~rt}FZqAK+5179`Um)f zy#F14-Twz%T^_*2_(DI1oy2+{v=zu3@nCzvpTJiB`?i&X58a6N4Y*9I-@8W0^dCYw zX2a8efDeETPygXvTzOni;40wyC?$Fn)SF1ZA9bd@EANMtU8dD#mkG(d%N{Yc z=zv9=tFX*2v?zZ8R}t66xV{E?m>fyCH$7Y36s(`^W&OXr_lc(M@z$ow|Htc}o^NXU zAUv(9V#tZ69jR$ed;TAt*&JMnRef<}{{_qQ5KX&lN zfv*I{7yA8uzIt`=CHVP@0bfS+;rr$Bzmz`--WBj3jyi$=T^-Sn14C225&i5wj=r&e z*-`!$=r9~QhU34hqvKTl_`tJ?_-(JOOSx)09PB7iALk7mgOr%;4V;(kwLz!SD4{7( z&mo`lnwdW|WnQ@j8fL&TJ7qAziLq*3R!{YrsKfXu3+d=1I@Iap6Fi8(W9}>ycX)$4 z^#B>rC$E&5I^YD9J)lDlWvp+h{+Xccfp)i3QvYC|c(5-(r)odygDdMt597-Ef*n`Z z7npw=40zR+U{`^r9o`W7_AO>l{n6*{>l*Y}8MQiYg@wP}L`6=ux!aJnS0_B$KQOEV z9_CJvO|6QB*1s>)bSsSu8eGXUFrVduDL~@&%Z@S7Tn^?@^6iLBjVPi9S=24IvUDdckKt+jtDzZG#gs3|C(Ya&RYA#o~xH~25@q}^c;D(znR-l7L-4+d?N|F6*o zenxwFC+!Yf>ZJW7WJk<%Uv^_E=%dd6CVfWZI(T^Y0UlIaW4e#e_fCF*e&GK$ec)&E z5AUSiVZ*BYD0>U~NqvC6acG=37GApF&y!5DV&E!p7QX#wVt<{KF=9Rs`~vX2am7s5}`4!sO02eE<-X%8x>MLGq*H% zj(wxT7YZJovF8$_M{C%qXdFh5pfz{`gpG=}TI(?cpwuwVerZXKJ$mU5`!PTS6xP_E zw~HR5Ve8T_x^Gkrj+yofyH15SR*$pKe6`kIW-onpoLW1$yv$!)_@cYJyJ-+`3aD$O zsf^MP`#u--=p!Dj(0e!0$QXeo1*q$?s^>n0B-Yp+}f}!)gqi#~51eAt^T_ zh=+DL;t`DF>NVCwH{{@)ks+;)MrdadF>bM~sCvJ7d0OKm`f%jr>p=I%KiR4OfG3 z&AN2+(3_WTeo>+{Tz|^p+i5hVl>6#plY3a3f+Hd8GhW}3K6$=BiC$mzaaMm$I%#^t z5f>0e`%4bs+1Z0On#i1nNom_|e%d4BreMgp$@SQFbN6E=3oy;5kNu(HN_Mp`ZSK}8n)UB2qa=(;)xn;6%S>4Wt zrJDY}`uN!m))PBwNb+#+j8Av|Y#RHg==DDd^O^j!8;+d}>_?hL=W%5jO7Dz#I~iGk zNzQ9XuOKZ%nve8*q?t%lkR~EMi8K=F70i|2!S!vV@m|MbQ``_~u^X7{E|y!4*2sg3f0#ou}K~s7vIAY5^r>mu^n=T)H`}t-Yb%K9rT1 z<%T0XtFi6o#H4LECq35GU>%XjN`UPc$F7%dJ~{T%&8Mb$8;;qcSV@-LaGbL1rJK_H zOE*V?gX3u?cTm!6HB8pHEDL1442SX+(kDn8k(MCMM0$i0g2@N@3h5K1jYvz7W+G`I zb2_fo4H*u(;YKj7;J6<+?$0>cOEJjx2(oHisjseHj z?rr)84%P=`G?g1qTHh4f+64 zr_~5NNB_T`fv-$%sMk5b<;DaGUV80s5euegH_~qN!FQ>3y+RT1~o7itq!!=Sx6HR-KlEFz5 zOwQm$p|)pYK#l2hUrWzJ>{t0bAeUYLs6M@ah?<#qXTCkZoNOQoL|&9vJ>sK^H+9{e z`^FihWp=JEROW+2oS_PxMju^SPmJBAnXT)ZC!sH_tT&k(T-77Ea=+gMhT@)y)+SBf zM`Obzy+qf)Y7faa4|_WMj3O3}vYt_lj^mXy=!{~j);3#TslKI4oT$WP>6^)`6P3O> zcuu3uj-?ZoBr;J+G`&%;H9Rx-&3cVy^ITBYJLj&gr_?-fW@}zsV348NikiJM4&Txx zp>~-8Sa6>P=yG6LxVB!S2X@oi`T)(!dV}Fjzyk74U{Js>kO>SjpqVW3Lnah5NI#TD zzqVckB!i~n%+}R+#@C1cp242DrHcV&)Fr5!Scd0OfXNW=!v+MbsW%$efpfqbp)X~8 zedO=OX6uqueprVeHlYyD;~1>519nZlD6X#8>0Yw}Qa7{pjk}Kr8Jn%SU-{vx{c!OP zJdb2>x(>M2Dm|@sRlP>{Mm^OwRt^a|eoNPvHd~iXRFbQ8DzCkBkS8%XZ3o;s(8{$s z>NSA$(|dx^dzsNgvQAX`eSOh)T435lbglHs=vpORv_WqYHU=j5JT zoZOQq8_a`FhLaLLX-MskMnUK^W_1x)>fw#c?5xk_*AsqL`gfI+lvqmvY}V`Ad0mutTrYiHOP)otEz^>JzN*E_ ziah?Ea;FmM2>Z(mUdOV0NtjDxg^gnKKcD8ayGeq_7%(fMMzL6Hlu3kd^gR~z&UcE@ zQlm`H;5TutM6OW=Tj^s{!f7hks%ffG;xjaxcu#=Qu%14u*&@E9D-75$Dw;1Aw|u7v zS%HNa;rtd&vF3>yCE055Xf?rwtHZVL7&o0(#OfL)6?BGW)F|V!YLtvZQ{hGQn{kTp z_-R~&`UTaLDAcTJ6lsaVSqzPw0W@XP5WbZ*<%Q1)zonR`)DRCBCZrbWk zBF;pF@;1btECf^?4%+w#qFIT`S)>Hd?6XjYbdQw4Qum zi3JuwQ@|NdR>H3DT34U5eiA{FF1x4{T4ak1-H?`ZQ3awx;i@`B9u4 zsV)7J=dk8$#Ym|6u*bj=a9a_fNudL2>elqlRez91ufU74qO8*|xyz=jg%%(^HSn#PyW)^Jc3mrJ>K8Fl<@}g+mR-L- zsGqf|)NxVirRpO9w$dH?7{eqXqgPi~GOffPWHLdbCKfG~Izl#!5?4q1Tje6AiQ9`9 zKB^Dz4jlwQ7pfk#45qQtx*Bk|85WXo%^6ZkB_0v-N4Bnvw`#NyUu-L?Vmullb5T{4 zB-k0>T(xNkYd2#nf9q95rq zw^VzKB+n+C2`Y)mX8dk&@LNbix=Sn$ED4F28m`}xXEW6r5Ydq!{YF|s>OxB)2HOLxI&9hA!gDS30vA*p7^P^o0rYnTa{<`KQd;iJ*v;wO1SxiLb5_jSR3|q zLk_~^U_3L9(RNLyA>g|)BfM95rrQw1>H)$OS|Yj=fa8KY&t^FjT+D-?qu?U2$Of(! zrhi%ccMs(^+y8s6_+ouYv8~^kq6kfizR*+@TAUdfx*lUsj{;jJxZdHW#f)dhdwa_j z&&li69vYtW(q$R76{{F6( zD4%JhV{?O~tobB9&ADUVWBX^#qj4lQ_PHyw(VK4Vn4K_paYU)D`$AUtU#afC zH+^u`^U_dheUC?_iSkE3-|i9S^kfeNjx9YV%G-Z_e;zUSdG7LT<pbjW)ivDx8?zC?jU&5a{6?EbV$+275Mc&_-l@1DExhsfVwm@{7X4eFmYKPv}g{|hoDt+LL?M`O}%pBh*+QUji1oWL z1;@lnEG{Z%dKkZ@JWmQ(kIh2))qFM@?1M+7a-GAe7^|6gr1E*(lk$VOC-Rw9H43p9 zl8F47pt62EBqy^p%3yb772<%lwc0t%(s%e#zx;TeZ7%#o;+}>y) z-Bh^`GP!SwgNyCIh1vnAA8XjGAZ=BMEF&s-e3fbA%ij|NAtNiGy?y8+kyUuK(D|D;cK@KY$h_Sc^Q=_mm1^Tb?MjQ z$dy|q#E5aGLX0jgOQNAcK6rgxtFh&gaOe*(F)9r7srwwGA+y)lRv;RH)=n#<9HE;p zD#H-ZSPT8ylUYm7XVkU#TT-Mktwx!60)E8>?=fmWurck~p*>(Kh5QqC_IM`yp{T@G zV{7o{=j}wk_c?r|z;EJjQ>h)%yU0<*|yHt!r`G- z4%p_c6wD!B#~jut#H#HQk*^n!Ubq7D&4NzMHwu6m+W3KK1HL6Vc?0|!!wjn^>rru3 z31j@3LcHW9t6aNsyF|T?EREWWC+}f4@gCNf`b*JLdj+Gvp~5uRQIR=!!`!2YHKs^f zPY|DD-)LJ`^>;)e12Ou4T+i^W28Yixn=*gWV~>4f4^Trtx5{M&td#W8f_E|-xmk>V ztK8^dJTXrYlK0&#<>%orGUI3BPtyG3A_81k3^A0hL;Y7})yMevCKP z?#ad)j4x*G*6lV(ziO1E-QsI0ZX@wl`R^+*0uffK*`_V6RYX&*5@vZkVsFH#?h)Nj zDk3?lgqdrUNK*~$UhIBCi6n1Utf+uDHN{Hc7JfaP1oU9MEh=blY49xA>8Zuhk0 zrxW=WG;Yo!=;bC$p9(}aDJjn}j9=@ljSE(cuh(b6l9JP!R&qvPkbUTzfh5%I0BLUywO+O5)LHA`1tw zID+Rlz5vcgfpe=ISWtV7wK21!i^x@NYxZz&@Tbf&%koJd@JMp%b?f5lHM#}RzwC^Wk){CBYkwRP}O!=ADBqwZTSrQ zLO*tkAN$0LDf9f;Oa3kPwZI;KAA6>XUF-unv)c)Ee$Tptlb7EnyG^QQo&pU6Xe__oYxm&m zowS1P(+Xg;(0faM)qCL)WVCRZh?wkF!Cy!Jdero_EI5eq-^fP(p2^IQ`D2|Q@;d$1 zKl9+P;Gg$&_~)L<`TkgEL{Ipd0z^3ZvXA}|J!xM-*}q8hIHa*=1)EvFCH;x~Q=YKx zGpy(Lm%gyYS3M!Iyif9`NTZ~IQWc{Aoi{qYfbedGo%NUX%o~_|E#WGr3+})UOW$yx z!?zfR(D9xQ9S5pjOOJJwuW#8O`ubLZnazn8MsiU>!}c`4z5Ildg;=Qg(G$uXL^jjS zr0LcC=mgS~n@{?N^mz;(H#>*5siv+5r8P>nrPyY!y`=0qJURNV-RQBB&PXgH50Myj zgOLl-&jGtd;d;_R{4l+&(~htIPM?~x(H5_S!2e`huAc3Z6kH>2Lo`%MVssvB&=U$b zAa&qh)8mycCdCzsewd9h^@CZuSg~=EPHY~w_=K{+M4-EICb4k=e?pmL78`SDXe@b` zZYJ{CyL=&wwEtXSAMNjT9kGzv*OGSteCO0CS%CacZH+R=V%i+Mo~`RVkJ#!R_|-{S zG!Bsu;Sni3g$PZ{5l=opC3ouTb+&HmxOv&pX~h>DY#zxh3zDiaC+bt;$>TC}C#-(o z_ESx8B5C>|PuG}A=+Jn0PZsUXiC~&M4ohZzeYjWri?8M40il$&`5p(_*%W4`PwjtNxL3(N#wZiTm~{ z8}V69OU2<^))*Rlcs3gW20lm3RN|!emZH0ufy6Lb4U#$sLBE^6e?&H07fk#Rkqzb7 z`&!ncC;F-7eKKP9vTN-vv+urn)u2X;z7{)pv6_y00(empis@tP(cATsuqD9586B_) zD|tIYco+6G0Ii;MIsJ|c^({T1d168P?+@$1W8S~c77ROl&pA_~n00MoZE0X_iKyo` zn`>0sZ>e()s|9n778Z@piO6Mh4K1_2TWC?M1#=Dans7GPz}(kwTfKyB+a>M0JygH_ zXvb{G*K%VYRwr}z+X|`>F_5o36gDu}a@eEOZ9opYBcw+-cqK(u-*?Z0_oC7t-7E%t zDC(K);LX9M6eGGXoUMbgXnJVY)d-R}+&lF{cn;04M@3&t#XeJqoP(jSa54q{uf3(F zjp_dHS9PV`5R)8NjD;3y;4DPtE zGvb%C*_>Fcg52;0ukPE5*<~Q4@1(O+r8EEPB_*u)Z^xfG`%JJ%V_pb;hvuD#TA|MR zhI_x;?e_-5z2|qM^^%x3;8bt0!iFgEEOg#9{`Q@v|G4d2%E`;gVUL~~;AhW7%n2v4 z)!nnOtI6lDuQV0w8i(pc&q&M+thzXO%!9TzmyUT|QhtrfX1=D9#LsmGZ!^TO)t1My z3@9ULzi#{3DnzuI-|Y7lPaa_LNw*J~TwLs1%Jj0glo{3SEkoLv{WDGaT2>rDyk5=X zbryg4S{e>qQhJ5`y8pDd)K>-cxulpd_nnj#8W&KiiNXA`SFRnNmuUN+P$rv};+|Me zU~aSAJ8jn~iFtR1kss!3`SL)^sNc5lXjoIHwr{rjd3pN)EJWLc)#Ksbr$6-k2BsbB zJ&>nA60k?iVes8PWKs!`ZART&%ClK-DKo9@EnjxvYuF#KEvQ#VWMgHs-syR)hmX7( z;msQVn)B>$M&tID#f(Cq2Q@YxYZJhpH3`$T{|+~-?Ounq=~QdunYHPewS9$n$!ra)`1%%!iOGUgmJ&_cIns+$XDZv# z8;0y}Z_%}Oxz;gr=o{IGe-|wbssFj(Z;M^jm}SOQ*4Ltvp77S}-lycuCjFPWUjG-p ze*MKMNhoFZ!1d+d_0K>|S^imwkkQ$5eJ$R7O#i>MEVJ4fS?w(s?l244?IyiWN!!)A z%x7-YjHpq1Wg)tzVhZU$#C1aHWum>XUV@bswqkSwGn4j~op*Gl5ni&~SY?O{h-2-^ za82_2Zhl239QP}?ZY?YRQi_fC@Hx^)e>gq@aJDt*iP0OwnfG1 zN`+y6W05IxpZNmONfu%gE+7u^h!zpbD~M1C>m@8MLGQ6pGubdm3NEJaVhsi-TTWCA z{!MJs-ZJP5V=252uz#V(yzMQCU;HAuuO$i|G0P%0PUf^R99m(riEm6b4#LQ_AWQU& z1D%Ylw{EN;h-%D4&Hxn>|Ad!(8nn&t%T#_zdyDT7=5iT>C5<|dd%4G0Hh;qy^XUG- zZBa40(x^DKrV0K3P}y27$wGQ|wU)@Mv?ODtmK42#*aB%W?)xLJe1(>TBXudz5);;9 zb1@&8TQOqZw2CqFV=F==2Ub&`n|FC`8Lq@!H_L=oRZ2{U*dB3NdBS_7m$*K#@d>Kk z7})qMAER*Nx4`q|SBRy1F*CO5hACW+z($8CdeVf!igm%l$j{SzDb~m)SNyiX#w=rS zui@FK^B;fTPlvU-*iMnP7e@P7QDW<2kvV*$sEJ${zjbQP6vxzswT@E?$%xG|ckD2K zj&ZoJM3S#KX|lEHK;9w6rmoIf<%4;FjW*0hseTsbjwuTFLiB!pBh_zDS6q@rV`v?y zzVNLljgrQpd0W$4T$vS4>>Q@D6*a7CkHAVAo2@70kr;#Yi89+n>poXFhlo8F@C|u* zEjOrV>$=9sB({cyXJduqrfWMSCvg?gjN-Eue#s^6!;1M7_9eyMh9&t*5ctEeF!$tDcbxBDhxFZOywgZ8Osh z+193s!yb|TkdD>A7>f8sht*?YBb#~Na151JMd#RZ(yUG6`veyL&4xO#CyF=1?Xyv?ujdRWs&9=KPk_?k{%!(GRq&u{PJ;gE5l6Bbh==Ur8z&=LrKZ1yJ zJ-n!~Oe{U1aOQ`VE@hgMiRsUuF>KXuA@u^c);7y2lyW7S_pqla?8oZ6SoNWFB>kjE zuMsvSNZ|8s_cP<`$7s!;9_&6yv5q^29YvB9d=V{X{DWOn_prkK1FNyf(_ExOrjY=T zMzE*fI;-0X*xSaEo!z19hxalq#__NS-6oPW#1&Wq?e_ire(rMzncZ$8`VE>ASZ$6@ ziOs;({7`qHco9~HNzS)DbU0DA*YvT%S;xAeeam~-L;D236ZB5NW`i62Qmfl6Ep?MV zWbDR)*M(u>`Vc2o1}>jRz|kKN}1W0-BcZeMEupoxpy-o(WOZwy-h)Aigv7nLwa z5In4@jIF=W-Z-0}Fl`KQ8n)=S;yo08t1ZE)-3C7zpeY_J{g*<@MoRQib1U!Fv~suf zo)wh0>4ANG&QlJ~IZX^l3-zd&9&NT(hu6BaTM1UBFDhk@zS%m@Do(R47LgmtdF=XF z33FGp9_werlqcTGyw2`e&l`80R9%4Yi9m9||2%<2+c(w^!x-;beXeU+TJdxDlj8YT)qJKY%wNQxERmzfo_fxs;oMKsMI6Kno2sKN` z6ibS>P18u^YU@zqh=1cu!)V-ExQ1cu$9b$QfN?i)} zR>{%I`4zyM!h5Yb<;~XR2Io1{x!01`Q5R*D*LcqZN`)iYj*5!r!sXhtBxby~@Wn$n zOxD?QT@{hPyT_r2SKTvbHM&iQ$Y;D%P@Yr4na?W5(6fpdN8~r|(Zcu&x(jd%eJwRU zTEv%=L!^qthgXq=em^QBj8ZqLNYYASRiroVP2?{eE@hvY^EyU6W(#xfYxE7rnt$G# z^A}Z&uNS+s6AYMxm>#Jh@}+y*=X0I_lAd)A5IQfJ7;3Z1;dxxW&N#FFREDkU{p=X8 zBkldHnf1n5q;aD|C!36s^<1!3{u1|Q8e)s;pb(!29hfT_jjk3ca|)5m?;*!zk*G%l zilPbY0xXA+xDlDGZf5s4v%XbQLlY`2SpD6C7C5e?^5De6d&#oMdR;KiEvei`0Qcuu zyA?gFH5Ta;!g(}7|5P!)4ve1zBLNMz?$4lgvPio_j`tlpuVZ>-Jr8czfLkjGx5c8R z6jN=*bC^MzE|T6KN|{P;@QA%MU{cIB1t)=qWM#8jyKM3WRx%DH`z$2p81lAf$9jpi zEX&VVp~E*~q<2MHnr!CydQNvt*_U(ZhEi}&DN}I{0OZH&T_WzvO{DiRr7Yu^@^Qw= zicQLA=KP9Z=yz9Zq^a~#Mp*q_wg#00!#xsrOets5nOO_GpUv6;Et6H2HQf8yr{|Po zDwUSI7U`UF0-A2R`+hcwWA%?I$1JFs;cu;D$_WdD8S!bH+akrxCGy3)W!WT_NfB#Q)}X!Eta*B&#U4*AgLg_Q5lC-S>@{XFk@ zF7CO%T|cMPU`72QrvdF`j!gno4C3U1cI2DskdIU-W?|Uby-OhHIdV*?AM-(_yz=W+?}!2XYR@ zFUdI+j(d4;AWmzqsU$|BP1B-jBX?<=;H7Qko?6uEoGLB z^fBLm*?csmEaiRMHp!JwLPdehhjoA1u zk`rkc(lVq|NK8KkGkIqJ>|;oIl?v(dobF5C#upA zBa#HWt3Eozmf_)e22q3d8?>M67hWawd&RY{Q5USakb#km_GKEZymPRT25T-pc|YgF zI}|61UUq@s7^lFWKc{%{YV}Jl7H3R=NAwPyqT|l*Z?p!Fa9TS?#JBIT+GmCTJomVo z!?X4qPvr0SJ$fJSYj^gzhu(i$e24VU`)=_4=l{IJ^iXws*{7EKd2{akqLbyf7k`?B z62|l7J1@8s?$^q^lj#QakgtWmo$DMN5q3;Lsv3zkjq&xN;Y0UC;QV2PBIZyI9r$(a%NO3tku zq2Kqe?)iUMTikp7yp427mlVtUYoxX1W5>4Irz$+5*#Ya>i5R^TYmJ#*z19KISp6g^ zp%qqXv{W>53ubI_{oy+NcrS2{ET=$ABe|&irF=j95aVy$70|{-NwyJ#4_(5Zr+n-T* z>>d!aW`hE+Z%GM-9t|$1BBUIwz?r9FwqjFkd(x$4eJD?#8oPHb@nr(AW5xpDC(7tU^(=|^!=m_lEO%6({(x!*%hY6(XB>ZNc**Ib=m>W1qj zWqS29iqY!VQ*ei#y7`W|S410=Z`5c%48qx25=6{FN~m$z6yxY!gO}KuPVcn)bxM7^ z-7(TGMAOHWM`!wFb>?Zw2_z=-VqC?sddc$HyXCrZ8tGMgk13JaT{oF4=EC2vYLA!L z)!9DoSwF0?qpm@%8#yH|yX!`O-JFiPvwdBQ&Dr@j>grZ*Ig}xf*@fFpI7*ef} zm}=+_V`lT%Wv*S?5)SuxA z=R1^k$}-BsApE$AD`zC5DDC$@i=PRgWQyxjQ8-dOBpy0+L$vx@eyn11G(pN>7MYoj z`A;=0)7SE;4>O<4)I-2lB}ySugfv^;2AMkV-@(1w4ybR8t5!^daz^HSR$9JsoM!zp zyLQ7{H$q5kQQVfoF&s_~@#}X^)@|%n(kq)Q7B)t0^0f@`iG^YjiC^dxw_;q36SrVw z#&kMNGv*{l%-|L`9BI0Y9?FdvkvYP&F*(@1Yv#ruum-7tllZ@1bCit zzVa0Ob;;H#WQ%5oe)>nYo>gM;8O0Kk<|QddaHST~Pj-o=-$K3;e%ATSxU zm7El@=(u7}Ij_8wa!eVOLgb&@#iC3(@kfgDi|jyXgOl&>iCal* z8hAm=#4vsm?uqXqQq2@g#UiofOXa1I$Htw-FY9OYz0}y_N)ElGT&V6pMJ%GAR;^5) zHBm8UG42m5(`SiADWi`mS(&7HYt9n;y_Q97`BB=$H)^=|GnH6#h+Tx8;vILQ!Mi_E zzqtk@FSbK3*Y3XPHh0`#y1T$FmXKc14){3IE|v&e#3HWvsFH(|p|jh~Qm#8CUhA~P zm$^vE*4)(Otu;0`d9Nb(9h@^>m%iLP?9+{yxo>RGz>J<$WlZ<`iyQDU;mhG`kWS$I z{#B%(kS8OZ!u?L9kC9BDkzOmx$tJpqgO&ZYT|kV@VmN;vxTGZSEht}&6^S-P6RCNH zSc}kMRq@q4O|$$Gc2bTZ%|Qx7+Bps5>@=L|L$kD4)~)ZUY(l+w8o?45w+y+ zKgTl+DI;Wo19Z$lDPBqgm0NAF<}D1*=YX}!E(dDOl4OoYt&{_9R%@Un$dBFIi&Z6m z&0Q)Lr=t^hnfk0a&LDOXVj+boL*A_B9m6hf>JR?hAmpx9bE}XWf7G9AM6N^4J>d9q ztUr%O-eNWHua3hH;9Q{QRRY?3Jk?CG5XSUwH-q{Y{-;=L*>isI}E%*Mo8!Z-c0%wvwaJ-{nfiC_P zr#~|7gt>S3+YWe*eEP2QKCWQj*Z1$w-aB@`&hmR-+`oUmec%22AMRD&zprio_&THe zwQl-(P>tae2RhSafqbbrXEEzM)L}VVS+Bf%{aB-@6&lSn%{~w-7_Z(H8_hZ~4l8si zsjyVGvpb~SQo$!rsLkvceHvQ1GAH- zZCpPNiH+rgRE|;DKFCm^m1p{}Iv4_9q768&MFfX&zSS%xNQZ8uTCr|(P%A&> zyX{UrbY`iRz*h}sK2DG}majqNRVamLV^77%H}=wQRD?3&Q^O}*;paDkv43VP3;t^B z4IOy{DfsWfUv9>AB@$b!7qEV22^p)kHV(_%q_|_wVD)lvN|ElN^P7|#R2$!==F$z5 zyolz}jr4EyPgI9Dl+P)jDxcH|Gk^`EYDigRIDogjaS68j>Q zhCY&IMxPzgs*|`6Eht@7GrQ8NOozQ-UvMrg`p-=x%MGTApNKVQ}* zY*IXjS16}YdMsvz^7qRtl+$?rN63QOZ$z$*Z-l0>dUztlluP3O0}^aaVe3a9htNU3 zmdD#L|BlVTDacLA-7Z$FJCuOW!89EFSYk3c?z~yz@e3&<`N~3!UW2sqN^nsgvjUW~^5uI~*C%%9_ixID>&*Hz@zGcdA;AVGo-PMA zjxsVSjGjMo6O`0st^CFvChKNanu5|GCUcOdz&KrrL}~7wH7e#+trs9cc?#&}Oo`;> zwZ7?i-WBqVZg}&~-DXLZd%RY*eU4n3rW@|vvYSzDRCOj4YvqY|JPaacf=)mStxFM- zhTncet#e7Oqd}dtJGHD1&c^Dffb(OosOA4~j?kS(D`9j;odI{g>ZpVB^QiNCway`D zp6;MpM?{^dJD;hv3Oi_Vpp~iC`%tB&Lmk7N9d5>9nVJ)T9PUmr<_GPsXh}AFLw}@m zOWJOMs_8`hL_LdY}!U3@Lys&{*F=Th(Dad%3+OUB(->YW95N6lLM+a(V(oPxY24I3%(*U%;^aHbT9P$sZ4E)%wZ-JkIeX$|&&Nc=pfHk!tB5;jMPT+YNmnr}+X8Edg@m5=*Vw7*LF^fP*>KLIHC~z`O+Z85w#zlS`|0rSTo&fbS~e?|4r-5p zA9l(EI|pxDqz~u&T2?FdkeSVCyGl6~A~Y4A!q%LW_FXou)4!9)M$z_`HD9D2a=gUG zUO~dlIHjvJ2(xhbdOoc?#-h;FLu`k#z2)V0uR9C%*xuegtUZK>e1u;UTGmLjDh#7Z zENe+4=43dV;}ccS)!xGS*j|vSi|LRs_EkITr(6eL3xMYXq!$niWMi}+9K%+EY%*Dx zhDa(-w(`};V{>rKr}rAb*WegIa-j#Ub40y9<#m&`>-iX2&0`GZ2ALxs7n~8hE^N&Qu`+>J4la(et`~*|mIv z;G{S!&)zQ1aM9SQuV6%?Hf|Jfv{5Px#!*#M7PHfZB(axk>T=MaCNCM!IYZ=o!H+r* za|VoQ@gX1DR#$ajyh%x*QLh)`n=70&`4z5B(-fZVs?;THd1Yt~X`{{cQRl^r>RXJH zm)j!GR8D>6TlbXL`GjO=x$;jMU-1rQvIty=G<9**>$-kijTqZiidam{HTg`sXYrNG z$*+9k&WJn$Sd|yqu{@f=_~oU4b^9SUxKE0V;#Y294p~#7jh(t!>`ly3i)-?yyv}f? zy2aj6s?KJ(`Isq-9d54ojKx2>M=Z_Rt4j*1;gW>xK&Ox-IcZW~XWmjV*7l;%M!nyV zqc7T38Lmanj`ob8o(&ov?-#5IpN2TB-Wk+`)>YW9JKs@AwKi#7E8oO7a(Ks{H&TV3 zY;@rby11X+*P{HeX8@}MEJ;4y0eMn|)OA2oK+<19&W;X~@yQv_1P#{A;)FN``zc_# zIw7vY_K^zBsN$PHDjZ2_ax$8->PzG_qr@*=QO+lgbMmknr$QX3D+`r?YSK?~{Z}sS z^OeU)$$DNE_)C=|E4nNZKGAqqQTp%^oXkj5Ov6a;K+h`Oe0Udp4Iqgmo~s(62$8h+ zLECLt*F7IY)}W+l#G1UkAZkKXRFsIs{`wPbo7nPp1?e4+c;s36?>_}LnvAn&7(ID3 z6L@W{yqxtk9dgL_vrABYXt!Lx&(pczp7Ji`)+;B$Wkz!k;>$0#B3gw6VI@e`#81Hs(wO=Jh;4uQrw{<Y5I>7X{F#Wf4Cobh@49HK)B7i)^kSM6`Bn{hlC=k%z@ zuA?|{6jp2a4X4;cIR#EnbyK+0to3Bq4sx_nFwU~?B+wwN1U4RP?!bt5emw#mSAjEK zT0aLJb^5iq=8(f~&;idYj4xH-O`2tN&<-1dB4E{bCpqU9P?t%l zHTLX~uv_i%M*cwwr!%|44p}5PjEq!xRbpXAgP%vbJbb4rao0N57V9eT-7LlxplAma zcOQyJuF$Uml(ACSA&t@fJb40dTS(f*?%w+xLn6j8`U-dIA+#I%4W0!&3wYMB{)1=j zYv@1Fjuy{izdF}d;I+o&zjzq^z7A^@wx#l3ZMH7aR*M(HWlp$SNs@=T9zQ5zj|~(l zeS~^e@j-jmMaN3-=F%ZOb6_)Q33}??Tu2Se@VCpmx!j|E3!=+nByJe9BJE?J*{-@Y zOKnSOozTyMkt|*2G@2LRjI6DM2fCa0A{*UxiAP@4)Vf4%8@-J~Rj_Am8+ZFw)IY@* z_o8U_29MDr@udGHC-f$4#g1WA4z!oRtZOUQCc#A{|Jcs-M%PKVn3&+)LuN*w?EXzS z>3`g*&!vMS7{{uvna4tHcpg3(EtQOCrtRr?Mn3aM9P+iu=cfyg!0xAukL|TxaJ}bV zbRXx|f5FM*XEw`!2IN5-;H4VwQD59($(bw+1v(Gp0XTE=fn$rJ$I!`fYZTF35RG>P+UVUi$b-%rbqQ+} zgDJ3<6#G{IXc6B0G>L5N!po=7yo+6VX?u@aEh4wx8Pd@!(vGyPS52zl~nca za2`?LPj8&UE)q#_mz1jmCoVcDi9)t8jNT z-l7=QDkxKx*utrJ+jFWC?|4M%mNQW4n!y*RDi39GZMwU{HeH+ch^7=L>UuXAS}XB| zq2A#6MO&-jeFpJAYMaCK=mp87n0+q={a_rIvN3%pP6|gBZoz3SCbc$cxp(TPO!g!9 zWf$+u&gYS0c7|v4r(7}Vby^883}rHxL1xD`NX!>P>T-OeuzFOzK4x^i4(BKHTGv#L zt2aRAm3KbDmxw}=A$1$1RtD&&Kvbp5DSjWVWH(>S_Sb7z_o zQ#MVBH%(I#3LnLHcTylPzlF(9+u(J!&^Fy08vJS(w;1qECk1l%VR8dU^D~%bqP{6m zpP54kcg@+dWPMKU5^<0#M;J)9th1G|Q_}Zkzj)oLB&%)wC?vK_VDEqq>1ge&JZ>A4 zmn&HsS=F8N!CBgBy19a#6vesPurgZ5AfSu#XLGma@`Jj<-geLEH^bOQ+bV2KO0kMl z=s1H@Y}5V~bh@z9Hu^Tr?{6AL&p=7!0UOsyx$j-46#?(U`nh_WaisEb6s=*wIVEa+rrtIA7en9?r-`wVc{u5!VKmeT)DzPc#BAG5ZUra+jr2BSO~7FJ8fk2b=Cuh zd!^m50yCpex3Uwnq2M8`9DEc;=TgfI*aL^&z*qNNl3uTkd3H$vqWp2_4^q9ZkG{?L z^enV~1$dyn3~k!X(}pk6a!=uj|y zTBt3W+adYMPq^ZtOykwq3r8!M92-G7tPHxgJe|8Km$f=;ai(F~M{Lu42K{E9GC;fI ze$nne+jSS++$mM*HBvlp4_ER#CPOvp&1Bl8YIJJkw(j(u?zuBm%L4A(e%yYG5}nM7 z(2k;^O_+4mz^sf8JOJEiGk8VOvfvus{KBVF zL!2e-twX#wF33JjSOp)S?3}ts8y{T5)}pg$5P1{n7LG0qB;c>Sqc%NV`DI0k5@0S- z^cFMbpl{+^MU$fsv+=6wO+{}yTd7NWQ!!WqYH3j|o9Es7MiDIP$qVLriwM?Zzm7U9 z-okf~0?Z;>)vzM8q{~)TKD%gi|d?;fCEuU=jF)#52+A-iTSq+6&(9Hbp60*?`RR%1_kcK+5S z8x>u-!6U?szwLWzP38N@O)DS?E@!wRetx)lxqW7?Z}5MvK8+rZHDR+sPfHC^Qp0qYCesMm-@?iZQg5ec>;F@#Xy;zW6p+ z34uY}TVS|X|EVYiMx91)<5GC^Gw3T9eyBVctst7a zV1(h4*_{m@R~W=ugdtqY^mHOO6qK?Nq8eYZjonabL(abZBhAalk;E&`pi+EU#W*wf z;WbRJ!sf1uuz+k9FqRqbvhTG)rt0Z_O;-<9BD1({_~za?tePL;JYA%L&~^UZF8Xn; z0k_#3W7F|NoJ+Pg0Z8vYd802jE0Vp_SBK%@s9@F_;%>Xdp=(S z@4vEpmX7}Bxii1>`W(s`RuMM(T7DPUCXpXnLEj_&hIV^p}Yrx%O%x{)! zJo?_BR33yc*p+_JrS<6g9E7#}wQ^7TUXuLOIQ5v|A zUH=bj?*bN8wf>Lqy=TvbnE{523OM2bUJ%d#Nf9k!fGr>?n0CxdjoO8@Q-gJCB##bC zg`$O*3`G>J)A3RYq=}aTFO`~}Gt)ss(1cn3%`>i3Aeur91Q6#)h&HrZXc8?S0^jKGnSJ+ zlV{IL?E_M!>S*PxLQUZ=FBIPVM8S;#9H`${!rx%uQ{(%;tOO?Ekbbd6|DPwk8uo9+_m4NY<_m3z1)N$aw!tN726c#87P*bLp(yP1WBhfqkAa#nk&ZZcx zwvYmip{n#f^Ak4g7=NJ4ux{^2{3QElf|-e{J@c0S3F)m&M~z6oH+k89&fnD7E@Q!8 zb_`e}Z)Fuz+!QZ&N!XF}$NDL)C34EuZ62A9Zv*Dd|A!AG{v8?cp$XZvncU{t&2)lH zM~{0dlkf=C{kEA)b)@Z%k5xYhinKdpHRwES&)HApT$z^A!P>Ubw`HCX4eB!>bvV`n zGcVUj$HO=F*n0is4(rFcrXV~UxF*Bx11&G}II4F) zVO?P(`_tr(jUQKFUy?^nxwrClwW$uh$bg4K8LVTU%amF6AEguIQFMH2rpr42*6DV+ zbPDXM;7O8I1Je|FQn#chL;OX>{$img{$hK|MD`!7=8nJ}px5AL2W!-156R8PdXUs? zC)A+*2_XV+f>WD}5!m&>f7fW2{o%Qn!WZ8HUNsWh3QBpG%)&hAA0-L{A5hBSKeNeO zY)o>njm$BDp&H}OYGpBAsqI+~PaE$)9iHxMTrSSQ_r)IU3jSDX&y-!zD!4VFs+Rfl zS)2>2=4TqO&wtY>iI*gmVs3xhAB?AU0@KKuKF$njc-z!!eZTaG{%zB3Yn>o#Jdt@5 z^UO4&>;2pykU6kQ&JVj1RdW&iQ*xtE zXfUV2I%I03g5(5Q*?HnxE;mXN*(7$HL3-^ z4y*7QMYmiSEclcwU~}oyO|2Q~#@W&yGV0uK@@V2ADpXLIQTsYjO7mucF8AiIL4F@q zH&ua^+YMe|6!O-PGK0Y>gU*zLmX>cuOW?b~8)S&}n8$;L8O@M_YIN|>sv9g&RJn1F z4ShKgB&aB~qedIp15_9ZN{iphjqm>fF4>T&O|f`jGJgMa+8pgV?V3=(9SXofkw>^$ zI*~~t!T&`8e%sg2E05FSS>e}xf76y~p=ArpAiu3*k90&LL4!kB zgdO0!eegyU*B=vTIo00JQZY`82EFlHBkyK9%@4EPvKjBeu3|vsfIyU*_md58MH$5p zHc$Nx`($z0ooyD`c}4h-C3JY^&G5}ekX<``F*wi%DwJo8kvZx>fKB(Q>QA$xrm zATeVf_W5;mJa+uXS*7oq{$*0z6~i_F$2QJI6DvXZx#O3Cx< zWaWqyQZ|o#%f+bKyg21L@$({q0p9wO{WmqY@GEZ*ChQ{;yR%wI5FxW;TO?y8;*9uV zMkMoQmi|NEX?@bP8D3o4tvgIjr60lCmefu`E==m5FV?%=coX%>bl6v3uZ9)zSXlUw$H{$a-$n-2O1UoS_o`}`jikn&Q%JD@|qV0Kv@==19}@B{?vu~%&x zfL(#q=r20}{gevS2pWtU+fm~o)X1u*xYeC;sUk%s^s6&2U2SZ&vB`EXjc(i<&M^sr zRgxAa;V>{^>t0B*meUVo_gELaMq!sjLb1+OqW=}+RKyP@JMD6OGh-)N_p=w@cI+L` ztt0!*T+n!MRxH_Z@{nWRF8y!l$;;5&C1}|mqx3%vIU{As+1MU#suI@C3CTw zX`0oVP>KOP`?s0J|AS_7Pj-@FlcGsR8c8?+1_rwzGox`*Vt zY#gWD0{_!-C^N|LMBzB)z(PghKlGQZC&iXzXz7Fnt7~}8kVI}HI1_XOqmb79^ zvgNY>4=u^iQWI_z$e0?;RNUJZXbJ1s#6aL29Uq82D$~;rIO2gu2CMH8B?H+bn^+BL zq0vS#?4^T%gYK9XerPX{G7R=Lx|4X)Mj4UbjYb(}9wU}{LM$`$AZ%}}&I`ml+$~Y5tpl`}&u{KDPY_FvKS-o4)QIsMQ!d#AxoSB( z-p3U$^Kq#qKCVW}$0d+#6YU^97?AA9!vs%j)Ijxegsqng< z-758&+B$F`ek-$DDFxp9;JqfNb(8YF`9bpn1s_A8prk%gM7btQ(p$F#NnP<$%IAbW zy;X{P3bhoU>tR2&(xMnX#gMu5%cW%J z{{VM2Z!6THu;F?*JJkPEdV*~*G%3{B)t)@8|EyvD{9^RzG2^o)a3s=Mp`Vz1AAJ9- ziL6rZ8$gDE?D~ZMN2?-A7n#0P7QsfHS_*pyGre^6(mLq;DEtpvmxrIWEf1HwXen)< z=|gUB5SQVh!xr3kDq&%R)vIWL?aBlqx0Hg9RKWHZ+@k`sw5BQ3VXe0HYL|yQa09*B zM+!V4HT)GdY<^IK>`yf?-WntiYFKIO9pb5>iL|ejy5v&A$-a8<unznJl36~Q_$~GHP})w5bvI?+vCgu|?Ng+x(3is3gx;vVF<5KD?7}0c zn*GqEHU{AiTy4)~5xGQ-dxKO!EtkwQc@|9ImMfWX9QPH9$dD-gQYJzYd3tH4fnK_5 z=^(Exzodr6T_F`0Z5_lhwS(4V6v^XM%}m@QxG|+%Kbj$lcGa2{!_o~IOV2D_Tbog& zh?{TG#Jz4=fLj-4>4iEbqIju1?#$AmS8gdJ-LSJV+^3369H?RpZ^rD zkXpy}*UiHHjh?w*IvC!1m^JpdKSCs zdei4PORfU72Zw3CWBmmqmWm^O1|z2B*M>a8z^i`pE#P3Y`q#k?b)^~b>&KEa%cBQ> zNGB@^E6ArN1C-6c!GqR7oLPb!-UPq;l2Hzyk_3m?cA5ol52GK+%xtwr*ydwR_^X4U z<)F5!2Z6U^Y5OcSv>k@C!%58n2T$8sg`|ZYo&nBAdC*h0RNTF}R@p$@$HO1?uNG1_ zHN4H1QGjRzviD6J$@+Vgp0p91vQH?1!4`dD0Gci-ow4c;Fzb~W!=pC^d!j^(x+U@`k~aY zF&yS+BwZff^1kse#+qexlI&3p>4_RWQKMCSlKXlIJ|*~M@yX&-svgD39%1mQz$|`& z{z=uTnb*)i=<#GW<5Qx}%WT3Yqn@2Z)93z)dE7FnF!g8MvcP_4d55i>=+5vO9hE$Kyy zSiwq-&bFwz?9eEV>=snxP7^!!o@RP$oBB1HYh4$Y+xnes3r=?Ql6BZS^hJ^gI*L$A zax0nGECshtG>0+`|FKaqRtgtDL zq$8N6VO%k8z^w`?ZW1ooZa^O!DHwan^!IDt$gn`OmF4Eoj)jdIxgWSzOf;m@pl3Z6 z-;xrpvVqWmx&U2$_!lfbB>WIT^i!d06%bfk3EwsK#qjx_(9iFJo@P9Br_7R6SFufNP-v}{o5S#?%3Oi}ADOS9^g;7gCKA2XCX9uqXAQK8 zi54&oukX+TqwgGr1{k!EFVgM!_OAePTMEAg5$HW)zCc?#;jt^t&`YL%gEn!(fNi4+ z*21FdvEo7G&h%YU7FyM?gl@4w!#d!G%>#!jD;X;T9j~+S(Y6J*x@dU;dsh~Nv2KJe z-7A3JDh~|ePZer0>N>VF7&@EDH=zTHPwhgS;j76Vn0yN)zh+1o8;O)3^5z!V`_Q3< zes)qqKJ=X>u9HK)Q5+;Kh)~5j!1XP(`I8b}CeOUO$5K}#bfuFL7Cy*#NVpq;`Awh` zdigf^4@gP~ldSAq1g{PE%k=W=#OD=wK8HLP@g!f{%d_J1E3%cH`Q-V7c8kPzIom=} zC$WduxWBsn$NJ6!qmmNlpj^;{a(ExvBpga47#ELv&qh!&%Yh@X1VBFK5B*_Xfnxok z@|B%k2gG*oW=0Yyk}ReKm^DeuNjA z{v|>iGt*MrNex}uvHn1UcNCvMvo$H9gw!C8G~H!p2$a+NUlnU5Js?o|o7lVKe;V-; z@!4M=lm&h)fSxQMpNkO_obPi_y-ntxjQ>t|=IsIAR+n}yx0MTb79>UlceWjJ{#4oS)VQhN=wfO(HSF{~*WX0n z7==Cj_wGa7S3)$i)A3drHS#kjRVm|I;CB+fAQ#fk@}gJ{rU!3Ca&J3J-^gzpq{?<_ zf30z5tJ2z%RSIXRs>j(F8|W-g`E3?G{z#{JKy>+dM^aL<%4GM)t zCE)sydx{VPUr~yYsFR80VmS)XtalnF<_Rj}YNujqep@i0`I-~ZoSW7*P$hFJ=Jq(h zTr$vEetsl;MJeD5tR4`(hF%b_WHc-xS7j2<*z`uC;e~pa(v^+2Ekb%C1?`5#2l1rP zB%R$L*+jLs7E89%!zJ5bp{0VuogXfl z)i!Qw=WPbw8-`xTNPNm5XQCR`I}TU#U)3NqH2zv%P8C1;e@&f~4Zj6wo!}4|>(Q<$ z!YB$h_dZuL?^-k4LZ`xqb}Zmr25yFuY@?Q~q;U+-K{nd)Y`0L8Ld zZDXe*w&A`=;MvWovD~Z9(z(w%*DlF#8wcpzcBHk9SB-Lxe51$t^+d!a3_Ge1{ts%8 z8tPu%H?38vCK3(wB~jk$<2TZ+xJ!>es()M<6CWi6Qg^>4a61MVUbG(1EN#Gjj!}KZ zo0~@N9(w%KnTTwqi-Zr{yH>mj@L(>D=ud>t`|!YJM`=zx2Y6LVxAM+gYtK3N?4Q+^ zGPQ>{bTQiqu1sR6n5oxcQMihVkW{P%hEzYm5M4aIf!#!J`vZmmVu*h9BaaEIR4(vJ5RQDIDfT!=zx^0gc#m=Dr{C;!qj+9y0wQF1Tvar zhT!~4e&m50LQ^d~nr+*L5iKd}7IA*A5UHUzNjA_G_eVr908zL?$@)1g{63;&aYXlV zo{Z>sobPG-zrgveo)Jm5ttBI(=<>-O*FS+Dr=^Xy`!p=-cC({2C6&z1{t4(M=cQo0 z^QUd+oqLbZYMY38S}YI>7tgf7>Xy*8_=T*OuHE`3lDpt6{XW0#5x}{I^lETg+oLK! zXX)S`=gGMP{zTVOVR75Trwh%XFC1Enjx9mGaSUjTyTf^^n?N@I8hWJUoh>38oL><-5OendRekE` zSkCmb6n-uhN*(SALF?Y1juW3`QyBLqV)&7`gJgYDlo8={_46-#WdWz`3dnKW-dZ9h%J?)RfS}OlFR#a^O4G%1mqzB%_JV z0XV1;X9OAi8Yu%$2$beS!4KY!ZkdTyI(86R(n>QawXi=>b~;m)A{BRO!JjIc!eBih z8U3;a{(jmN;=UpoEm*M|=VLd9?Ofl2%>uO)_X(${(KDfW9L6bHzM5Go(8f}MX`~Y+ zW8c$r*NGJjWtS+{%%evAYUv+!vc2Dj{3cR*Nwu<@Za2e|n@=ciNXU&xgiqkfnUb-j zR0U306#`R@b4>ZU_I_H0J6RvxkI1{}4MPzz(8nH%+-Ofja+6$iBFU%p=7YA&hBbB2 zT|ln)^yrhO{u<#*qFiPQHnFh$ND5HN-vwWv8n{_Vo3UBYFFYh%OMup``b$_goq+rX z6b)j&uV90#7+p#vGh^_71fg569(+2SiaJ)8r={R)nD8god1;94VVOz3TSC&HQ!c%$ zHxgK#3XzQ6U^=c(bIV-iMj|}{FH47W_h$@t=?h_#7_qV=>L6xVQuA=tLl@$oVyEj3VGefjtHP4GYl!fX`uH-Os;3_-tAuYDNzi$3U-w zU1cE+8_SM-8Xh!X31>ztoSKw+XI2^I+9l?3uUZdn1tk zs7Z|Ad}iX~ZDFyeou$~=DSNk7gx zOZVrurJ$Z%v`x)OYn!M-yDIXYc53Db&a`h-*g*)zJ0Wsyn)4qDic=oymxwYka7xPOp6U!pw7zusr65?lMG{(1%Q)E2aiA6p@6P)! zorj;Q3O#?#b0$l|Nm-;#Bmavwd3G64r3)W_iV^&zX*g8wDO zH2yCy9_q*}L*FZbult{NaNitqwv~x{QM#bTG;LwX?Jgya&PN)~DU?Kue5j%m*fC zy9{^I+9rTHFbvAYlDt07(pYd4SOw|(&pS(x_c%|fG!M$LC^r%1GEi=kN)3vFl`u6J zE5TaFY=Hkb?21RZ?ObpR;1`KI4rBjAL6)!E`<3ugbX2kvH}huPHk7|>gjZsD&1^*iWJ(HSI6_V=JCpIRS_bnkbC!$kPgQNK%@8<)Dq7Ss-F)TDN{WNy}`YC4ZRipfu0iW zLV3A(Zw>k#x0LL~L_;~?C7`I$rJ&6qcL9+^wYM!KBYG#NW%U%*hucV&;a zg%aw0927SU6!-g!&Qg0msBo66;8zcxOa`7zor<#)@MOVYe^5wL=A?KQI780fMUdqR z`JlvEu4yR4oFb=5l$lHNNkDz;or{29in(7q6|p#B0td>A`s?yRfwNrWekD97!D8^8 zz@TqLzSCMK*-&{KYj!Q<2m99H+lp;~4^9kJ9Gpa2m19U1LDj`8HI7JF(KnF?5Y@8KFV-QtQbkf!LBOmv1RmF+;W<;Owb%?TnjCN z)K-NqvsDf4Yi9VE5K=mx4P<5N0cy%G&~KXY1HHniEPSkRLPm@A3!7xb8JlcmvyJeu zmE8Ep-i6mq_%AX&Je3;p_l)a;p?Vf{?;7Eipb_2)t_T$6TMjGjd}4=fj7a5R*P9PN z6cGZ?LK2h}Ku6GS(4a+Y!`5&G;;?C6OLO8tO8YSH7|<8AR%(JYEm>z}rEt z>*Kb2q10$AMnvkIlpyeNee`IVh4`gd0K0l>L^n@&`EHBn&k#dld4^K7u znl6~unnH1>A$^fpA_du*VRRGm{3U_CayLH&5-H-hs~Y)@@GBCGlT&JK4`0^hvGD%< zjxp8E?>i39p$+k{X(s-PSJx1a#n6xb6szEY$KoLt;^&BlbnCBORf06WN?`M<1bJhX zAk&1gu!v89k6l9v=A4e09R{6podmwxP(wt3^hfwHp!c$oJ+P0bba!$0M*J>YgjW{~ z;@;6e{B0uVixbuF{vP}wg0T$?DeI5vM#@t^sG{G=^_yzAsZwqQFvwWW&z?{au)%=aUdlh(l9rPg!R|@tiZZ6T7Q;6kySJMU7NWTY z+HT1FWUw(GR(na9859YusJ2IQ4yI1ASDsR3Ij7HrkevU>b#Sde4j zU{DitBA3qjg!c0leXC)c-(+Dzqq%&oWMen~aMvn48E3g)^Q(69O^Ml#7BxE)#d6F0 zB$cx>qd6sL{Xh%x^ylWk>PH=1H|+mEh7U{f{PS%-6E zTmZ{GE->cva^lBOwP{6@?`YPNF3yUZ{|_X|aSMDS<$HA;hkHM8^o5AM+DAbK+|Q5e zC(rx&@;=30_}#;|vc4)|m`=h~L2IH)7y*nM*-|A$SDz8qEjR;DFeQRLqC~LmD#6*c zMCiF$A`Ck%8=VFX7O87eYVxF*RF;DN4Ob#KY1mKkLY+LiL~zi8W1$j7nP#AFRaBp&P#9Jfn*4+hhwAb3EyNGPG|keEX6-d&Dv?*wo^$UA^mVN^j}( zzJCZm?E2Ey0a!0bIyMeImyix2k?(Ct0+Pq~LmYfRNL*4{I!aI9rEA!&Q*4RKxZ+Vprb72lAC@-zA_`^(j58Vrb>Ba)5Ep< z3R3UU6p^RXqh7GEV}@8B_15U@^?27g)GLAC`Uzs|lX`!)C5zu~c;Eh`_g7nz_~df$ zcQzWUB@r{A!CNW<{xIO}>W0-bUo6&&oWi`djAaq~b74S8fZcDz1k2&tJq46B=+Z}> z52c@-_-SX+O5ZCH-adTXJ2Wei8=9Rw8@^QIA9MBf)Z66F^2IvHxokzFAO{Oje(j`) zWK4Mm(wxWJ;$s=t(>(+hiJ1L;J=IjhanJj5cg@tK#F z%Cnk2l|R`usJ6bqET1agXX-dfOh^M(U<5n5qTxL~?)*p4BYZ5QMc5^yZ=(RWz8(T= zg6S_~3}o$e!dkz>>bWarnE%vOeu@RW0;0MSA@x*=kj9h7? z1YWR-c>6GL3@{mnZhZSIxL#x2s$lIY%B_>l_IVf8;jmq2-pN1q$i1OW{tmAhK^$rH- z%+YZ;)h*_o=OBYTyEcjBoQs@GmStRYux~uxmK^(-Yqz`d_CsFG)&m;}W-Gck+~(1S z4)+Wf=S;x=3puC(XQA_9s0}pjm&K_6*hSQL(ZS$!HZB%5PQ2)l#jbZKj$d>r2VZok zRTqUxjg0G@0Ke~zI_{!_UONH*nSJC`2$;rzd#DB^Q=k=4e$gR4&$uRc&AgrC8q-7Q z-c5yP|Bu5OuErX!L#jvmcC3f?wcztIQVP(GvelgpO@+6Uvq+uFX*QFScpow-esCtK7fZrg}@%d7qiw&>i0E*-!4klNDLP zFS)7ct60ITK{Dp0Yt-lkmi+}+8*& z=7+kd=;>CHyL1-$uQZYS^>Xu6Z3sN%NlnyfxAm29JuDR@>V=svf17T4Q%l9ZZvAVR zWG}UW%v&PvAp7~vU6P77_4&=IgC)_^uAru#**ya_MB#4DnkFTt1yHs*9WZCdf|8{Q{rT|ayIy`^1$g-I77$kC9kz%&06H03QxpFSOmd0+_Y<@DF9@QvR2T-ny#KSIqN}k$YXHLZo9>(vP zLDA^N({9|<(&XDPw*)&~H0BOxCd^$P&VgjTAeN=5YlRX~jG&N&3F zJ8R+RGS&65nLL~0T6ib>-qs*V`APh*&@XAGVD1*pWm9f`u$w_dIpT8yclI%7;2G18 zi@Ek%3tB*;8vX3*I2~j)n+2w&#YEZt;ywUAY!=uS18f}0FBZRKEw`4jc0XM+^z*64 z&01*Kx6tF12`C*IRxGLfRR7p@rUJB~B|QXD+?g-X=ZoN+sK&@4p4#aa)Z0>RsxaR& zT{C|V&#MHIZvHsr0DzlB)RldEw8*J<;k=q-i}iBt1%M}^*<*w@+eq)Tr-a+K;UW$_ z>3us?xQ;rrF&`Vdh5|pL#n~YEktJBjxi+2ng_;1b{?XiGE?3Yz#<;e2-|vN~i=1B2 zk055Nn=kA-;;rk&E?;23_(sJ3NMWBXmmB%uOdKZc2A(NF3&N0QAf0#!yerZdNIxJg zCTHTbLEH;Dr8pCRMb5+vSgvYzyF9iab5k7n)v-V=O@BRNG_kllh1TAVa?sEaSxIW!~rc{kv_Fy(t*MDV*Td6dh3|_{M(-4{G4E zBFPO0p;UeRBmG&>PQdeowYCxBitgfH=s#+M=9Ljr>V!0oDwpmfH0KHTGFu8K*^4-z zq(&p^1OMd@-pbEVg?On|LO?tP+ZcKzW0&brVhJ`{9*ZWC_Jp*?A^ z46LmwFw35AlEe(QFt}g+rjCkLH!zX1$oKREEV$&gy?|XI29O($yaY!3`(XP=&Lr?1J;OqDu1MXJELDihR)uw3gVD@pa;N#bRJ||Z9La%`Oiutc=Cq}5 zEfv#fS*zDz7iy+ydzxA!s9V6FOVGm~pERL=f!pw(iTuPS_qO(Y-%GZRF*3@86oM3n z6p3_aG?|BBaUMSDlt5zQ&s~+LTzXReNYgfX#-%~EM+>IPvYQU$2Iw>UO#cY$XTas~ z<}HZNC}UapTw+Ao24cw)*@ljs>?k`EHw@7M59wWq`9L6kx7TI4xNK|k(-en>YBy7Y=%+Z0f{rocy**W~li zP|FxE%r4@rNodBVUTMXsf>M2s)e}Kvq}cAjUZ014u_{_TGknCG_wT*1W7|u79{2GM zoa)HvUx5_iI=DU`qYiR6-}p5ASEORi8B%bzQZ)|7f29$27YniefOUSU61xniFpXhz z#tz7U<&o4DKRX*myPoPh3P}vXsFmLKGJ9)m*{(f(uoM^9-5!khQKVd?j=2B(v7eLv zdF<1@^$++T$6nF%$FWcF=I!tKeeC4?PsUEp|Kix;CHleGvC7n`iDcA`;rQ>@!r0}{ zW9;!VJNpbE0xZ%P|3&J2p@y7-X3cy)TP1U9!O`8Q}`DVeV#%JSE*jz;}QCx~5kv|WN2o!}T_XCiVGOOacF<9LRWIx0HHO1@KfcbI=H zQYHCsj;M`;zr`pM73+p?*XgZmXgPdS=o-8DLx^6#io1^QWQ-fl)u;>lGJb>?Bc5e* zEQ_=inW+LhS^b}9!5u$h`9RCG49B+#mNLDTlOWP7Z%s$6FM@{?0T}|pF5c8jMaDz( zYi3kF7eIE_>0SIwpQiv@33Nw3$oCAQ=^@uxG0(eWMQk>9PqZb9--3{Dl(&2zfB86K zr?u05|H?e{y>hGHb`|TpRmY;ebfRGj*>X8$r(g1^P;DhV7*2@Q*bNt{p%)j)skehx zkD-%x5smm&G5e3{gKEgpTmDLg8M!F?l{XuijmJea3W*7*iE1$-!=;o_B>;h z^{P<{z5n3%lE;qc0@sYOIKv>Fih&FiX))49q$Z>mB*MWAgl-s9#&U0gQzmkytMZpF z&6O86iMR-z{?%s5nAE##%sQ?Rc-YbdzFow_wZKDivgzZ`;H*XPFsECJ`vyHZ)kvg! z-z4Xns61_+>vE5@GOaB{6$(6@M&3pZz`VU;d0af}&?0tbYO$ZIAI*LixEbCY%}Mv> zxsLTnw-KF{lx*;(=4Ba#o6?B2zZH5|@6&wP*(l!ZvsXHujVf}-Keag?^QFVgrg+aT zUHt2aABaAW1(j@Lh@7i9TAb5j_j}+)2tTa_|d8usJgYthNBYymbZHSoH z&zrZ&ec2Y~&C7b9op)dG#uV$~-Qsz>k8gCJvT3+?ZH#FGU0i_+qcieb1>p-yUE#Ys5l0quO651v+X_ya!Wju_VJ4$2e4yDpjrr3q#G0PUuI4vw#L8}Rx}c&LS!npNj>i0%yP`!rlwlmxtSI|R@~o85WD^xV+p*RHjkyIj*A;GeC^ezGs9UwsF4}1nFC(TS$Owx(BXrBJRx~@40vL zAI`mN$hkMdB7f~tzMQ}maSRwzvj|w(l+)&N}^eG>PLyWI-Itq2Zl7<$aH{jb(lAW(*d}Od0XjgG}1a7v;9K3@*l0J9w zYe+9QeRWifBe^=l3-?KYJ2}gD@yj4-K#m}%&2tOY#lIzx@tZ+s$-Pq-zd~pcrTI8d zp-+UbvI*be2FmkxP?y!F@qP~=wT`WT1j+Nx=fRwCq!;NYY~kE0;Q4Eqhk;0+AvKSb zQ7k@_k@AoT-m}~++(8o#pgLhi#zavvvF5=Ht$#g_OT-b94wOWvndh2Zz_JGqS zvY{^i7`{^t!R>O2#BMnNnCBurfwT}wWkQriX70oZF^I1iNk>Y-xdd@~7cE(Gbn5^5 zZg8!qC+q6V{?|NIY@79*X&0$|!h_mJ-LIXBy^fe{R6`j0Fkq@8(slUFn&8J+$O`Da zRHy5;`A^0cNH)3oBLb1f_VPach*g4UUoEr_qdn^;x)=%gc2V3(`uWO!c-iEL1spBL zyv}wZH1V$<9J ztMH@8+*N?4d7}Nyb-i_rwB+$}zit6NKCr`_%r?ACJehBjShgb`HT)EoQ)4b!;H5}s zjwBwB6Dyc2b1 zwyNL@C_Qsg#tkbyo=%`Ezqi4M-`)QVxvDs9BU4Zk@2D|l7HYUTlK7)i{IN$56VDtg4w62}sBAao`g5Nsu}^Tq24Cc< zttv`kT$Guf@q@QdS4mIcOO(K5-2%kkj;EqMJ&}t&0o6lKm9=1R6gQt;j##17g7JF$cke9O0J_BIP=@@e}zrb764;S3=< zmw8Cq&AO!JGc7DMFd0z~bB|eCIlc8eA8C7k0^RMicuu%aH}hQPr{~&XEjp6q2d`{q z$`w(*d-Ay)F5C4=4;ANky@tg6Ri$#idviGAA2!G3{N;npJsF)=X6tJq^fr3@zKm~$ zGYQ8LBVr@kFNZaZ{GqeLnE=g|ZUx;f;m-2)n=Cl^R_bGVjmrZX?^?8K?zNo1Yz!McU z`g;p7qzF-3-^cxr8Gc9OG^SMe3MAJ2gRfJOObea3TOVWrwn+U=@Ez+?09)m$pTdus z6lbGF849Dr3N85wyY+K9yH!$k39zh%2dW=4eBgWJFWS%b^!wj7Uq|f(y5%-z=M~Nr z&Xl`s(u&3C@wZG`IO#L9QD(Pd4>)F)w#ylLJmZr4AOekq;1TJq9K9{E0Ehm^-qQco zTlxPly`AuX^mc})w_{0f^XX}pbS*qTFcR4GBT51FDK)*-tO9*dQo0k^2_|>M9VBoi zbfJYKP$m!_XyV)|K-gdXM+p0y?o$ahJexg~x*8CcNkbYQ&+vT!;dBCFM1VY#zZww! z4}tKG*Z&K`H*PaKPjf}#%tpjJfCuye#ESr-46qSoRq#Hb4rtiU9pjR@iClOC`CP>9 zwaGX@o%(Ia%dHgiLpp)I46r}J$w#EyfI~7#{OR9I60qm>I5enaqV`N zOWXI<02x)@=AqqL1?P(9xY|VhG?x3vv|TljXDfZ%;}j(BQRpWtaDxpm5bau3Eq5GI zy=3jl@|ojq2*y+U@T(`I5~~txsqs2;t;P4Fc)AB^E54T^`TzT4{6d7Hg!l35X)USk zjIgJ09eMYMm|#u9X8LV?BfOfBs8Zw(f<)?xFFXn>?(MLtWMMtB{q-9H1q*7|->&1f z0(wM@kU{IZGKh{PbS-IEPbW~Z9L{JK+Hm}}X>$abfq~W^g0dbbcRsy*au34YD^V1+z9);M2z2NPMHV_+`?Mgyqz8^%sMBw*8o7e)0_Z4s%uM!Q< zfK__%IB1zfrDDKYOhP@q{Bn{n0DXxlBXOw^4w_V-v~+1OoIAa54x z+-3FLlnVS1a6WM;9gh|)3280`rFZFQoU4%H1IRsCRz%QIGSaBp$sz|L@RA+SiZ^d7*0#Q9pH75M4Bh+wr~srGUm)$$xC8{^w<_Vcs9 zB~5Qew5h^b!c6Tf!8pkjt`D(<&2|Z`(1V7>>lxugx>O#3yTegzQ2$Z1ofQ#-kxxn>J-5IXKhWFrj|i+1&~MCLd_<~CL1VO} z{{bYb+1oZ!zWa840L~b|mvEhok|7a3t6(VjETp1vaxR6|&a`)HUgqSVVC|?^03#-y z1kU<>0o?QddI!q>cMLim?DJ}SfNN+yDWBL6zX^OR57;BmYQP8rQrrItOuR$;wkP`m z8VmgFW_a8{gfHzpA$d|>NFzpTY$dRGL5}Ea2_#mUJwQIHqCpWgpu?Q!XYt6};Wgb% z#iY9aVa82EfFiaY@9EmP)PN2u&G$i`I^>~{hl!C`b+H#3QloTHi&+J3OMZYwJZ#b+ zlh?#PdrcSB$|%rMbUyJuFaZ7v7G>5qEaK$jRV|x`Xh@X*5{fm zI=CSOquFgE9*$98!sE91C|UG2Yid-5SZi>Qz~Aa7F#rk2nQ~m<|A{pjEYZa;0WRe( zIwRE3yRDvR=>lSf?Xod3D?6S(NZ?5!n%SI#l@zoM=RwW)dqi&6odyn^6@vVxPsQ`AXe zPHNy95@)Z}unRGcNSqW;zVx=l*uPtDI8p~!IVe??gT<#Tw#uQHSmjVot#YX6UUx8+ z_h7%~avI8z-auM{G#6h2@X#y83ec<0SGpi8m@`Ycn^5pnZ~vklh!j@Tnk=inpG zUsb)%J4m*{z0TXQz0RK}_BwA({oMJ}++Jtv+|QjYOHMj;Ma7PYqLYru#l?=OoMOkY zlw!y5m}19>uwutZQd-zahd$<{BR%D$BLjId=bUtKbBY~P7MB{x+2Vm6>0%+( z0~Z(KV82~6kQ>6$Ryi=re`f;cyUnkXd0(>=qCXCt`1=7n)s^h~Jdaq)(QOutNm=Fa z4Xbhlq+ECS;nP3nxlI3l5^7&YgNV;DY%FD?NL&p1XFtq|>`U>ZeH58$IYoDOY9H5Uck z89cbd`J*T|9CGc3L$u3Nk(q6IgL3Xx!G=|p?xJZTSKMVdgNRzakTRZeOjb&*_EXM`T?9JHjwp$z-Lp!vKlzdro1(3E<= zKYPFYCwD9qd;pR-k0Sn)IOb9=Skz+-wooxa-(wzN-Dewo!x4nuorF$Kv9p@=3~Pc% zk4`$2Ni-LG(4leYgW^y9 z82w9gS~)ZdsB$9f25IQP{1|btj7+1q8?kz82~k>eJe_Pu50p z$$~^jC!LzXjQvaqZu|~!KFsX6R$FjcsE>C&p9X3NIVDqL_)4hPeSW98m}pMpGfm(P z^=x)BPV}B%PokeYLZE|=a-8JuDENX@$?30oTvW^OKCybb5v!{bFgDty4Fw(ZAar2 zaxQzbrjqlk^yJbUAQ&Lo6im2KoDXRQbkNGT+-YQUEgE>w&vAu8r=3^dVw3*Z*wJT=2EsZ8cdghS=nKWe~t#Fq$%4LPoEH%j{ujS7M960my! zy0a}4xYxA}6gh{DgH;2Ox7hKn2JccVDUb?fy8_#&F=re8!UbO2RnR2VQ;1-!i&zyp6UXUW2Zx_B)LFal{+1S!wAI(WewZu2#djI3_ervnNs4=fl@~(LAgPx zqryrY!(u?WV?en<(MP6WUx>iIfIUG`i@jkN_KFSIABwR*6rK^Z3w9acp$6Rb*T?QW zIzFuW(VC@u9#wu9HTiVso=0H^ixfH;>Ctyj{q2zlb2xpq2#tZJ@1 z;~{ZQ;m3_uCSrxyM&(H5Cw+16DdaRUe z*LFOO;53nsfA>K?y zw?qEt5M~OBIM^b^+`d*1&vS|ZA3LqUot{O4JKM+Psh{M4w zUKD`VH}&mV)KZ(kMbg=>raNp!0${nU&t#)@EjG!vF^d>PKwGjX6ggKQCl!4c_e}M~ zdqdinn3HF0o)U&WT6fk~^8nT=L%n}a$*RJk zXQ=kj;jQl>fU~xgzvkRY%Uh|9MLw6$oOj>M}DIZ zy=1+7Eu1jKT_2uR%b7Cha<*l!fgTr}^i*afDVY~hAcI$PwSAqR!v2mlOBkbhQ((() z7PK0!0)t~;{jq==^|K`ptD>)m;r1A6YIhaT<8BrNCuO-N{rVKVKB5*4__cVnW2WsY zf@Q|9(I;?s)NWfI2cN~Di0k1~{*K|Kjm^#j4DM5@RmUqZb`42~Bt>(NrWPdE($IQU zn*KwgFHT&L*<~fCw;J#$uux$(XAZKY-DM@)GvRv_-dSB1Hi1N{1T`U%D&rc{zePD# z4bQ%DY{GVZd-DxjY5^5}%|b<;pZ9J0`I!v72Xr+z*))d`MKku#F*K<--ol9W!G|#F zgJ))Vu7tPP3rxZX@Qi&2JXv~?JXX<6$Lb4$EQsA|QD(8RrVPenoZ^!O_}UpY;%SBj&n51N$Y6SAtl4YylICI7l64X^2IJm_g*5#`5^l)kREf zvSoN}IYu3a2&s~#BvKw5+X)YsU6x;MxFL~tTHY#R$K0_J&zG-S0>ORcT0qq#vIIIV z;0hgyC{~Gn#-~ivj5|#47=JMR%NV}QuMiPN#!f4gCF~~APvH$YKI-(+XQ&K=By!c# zuMo*ofqOwxSCF+#JG1s3)B!)rFaFEKCcyvki_F;F`VPcY)I^Yof;7r}Y*P)P<2tV> z5@^KEL_9*0{{m*>#otTZwf<~Vaa7z_mK|cBen6kXm%U?rYT3VxJJ2T*E$e=t4%vca zBbwH6s!$~tSNnvCNmRpI=XO9*5s_gyx%7-JP!`!Vl3QN;JpAP=IXV3MF35Po6mHyN zddheivA=e}fAdy&eV-H>BKC3vJWID&%Cvr=@C)kMM`q3Oz>MjPZGZ!V_cNkX+42l$1EgXkFQvp47JJT$^KBAOstLE zbKXD{BG)0}0o-R;PX_!hOdLkDo#t0Rs6`CRJbD~!9}v8{RT`uf*wpXq(p%piM8)B% zpjKgEY6lvUIf8-YS0H{-Bk$P;aUHfs;Bq6Cd+%cUg?ks$Kj@|+)++L}h)I1I9Iwuo zd)%ezVY!-GBm5Mlw&pP(7#10VBlN8s)x#I$wraztwTA0bTQ%vkwK~J&F25d{YcVKb z7jOJrhduFeS9iBSZ1~e;98+)x(QpS|r-q}oDT<^E_s);s!+~FzbX*_8Ni4Co2`|vK zrBgBlc3olt{jefwpZ?ctl+I|V@$$eL$QrY1`}yzsTM8a`{R?_D)dh8=Op$y zGztpVf;U3_+>ZqnTxK{diOZF(QU+~}qwS~Q_qtJ4P++XB`G078^Z2H!?R|Kkb27C} z+WZ zrp$xrO^RGQYEfylaX6`ko=~9gvs1kHet+-h`+k1^ynkdkjO`w)@b*uHXNJwT zG}S*TJpn`tWMszxwCxVmk^DhsFkdX@D#)_;GNm_Kc(iX<{Zmv3cn{(;r6oVJ@u(~0 z6zmm0lXxX$So%Nv=fgq!-w}Lc{WmZMm3we+ts8OI&5s7#KoflPqxT?UBRx7lQkys8NAF?b=iS-wr~A2z7I?3HP^t zjGpy_m133X+wXWYq`FQba@*L73~5m(#m#Z>T}{9WI0+a9qwupg0_o(UPdLOIsH;q= z`_IIvswW8_;XU9yNV?_8J(VH-18@0Q{87x1CU$aoM-nhY%b{t=HBXY3pB#dBj6TAl zuj=6K5szB<{HN`_QV4fvNac7kLmGmol$mirFwm5ryNjszrx<*Q%YkQ6x7bz0P5$&2 zd16(iTIl!qL&A#mFU4>~OPV2b+q?Ct1D0B2ef0RCChRMAO%f_Is+@y+C%TW^B2!ac zDO8gJTtK`qTEx2l6W5!i2&IH4Tii>V-Qh@=rkaRU=^MNC2^H}^Q#r4KbslG)Kr6h% z7$nrzZ}RAWcG;DLV40MH2Bn%Pk&a|BpT{a0Gy0S$QXJA~^K9wJXT-&dVItxgyWKIl z8D?>!I9uBD*=YDTKPg5D4A?!x>UCl=Y9!egFJg--PLF<~_v)V#3CbQUKgteCXV#QY zZ#f<s*?L6;wx50Y-nqDV{XwL%I`D7 z{a7Y?NGh$D(vFAij9~|_aTCM5SfzW+gZf$rY!yv2edKVFY#j#V#B6Xf;LM{`n(el) zR#22Wjvqw}9CjTF<`rB9Bu6|G| zCH=L+rb3luYRg~TxMz4(E5~oZ9M>eq0Bh0N z-uvE7EAo*>`5!*&>|WN**?m`Mdkm2DUF^;oQsX`F_7D2StrW@N-`p+UkNgiQCq+L} z{f+=T`@=>2$Qs@9EMve^xcn*b5OGyXg{4JhFiTm8q@i8ZX8FZa#3$BFTd`i&HGQ*U zBYs1wG;H@brnIORm|Ilir?+UqMZ+l7g^YVI|4Z#Bj}Z>976MtQqcUE10H>|N>|w&3nZVw05&S_hlaTK9MIy7}tT z?&WW#_b7|pIHB)%vSa?t=DSG6+ns4JmcVc2@@ zM$HDLe~5N&>^X~a18My=&%S)f@?FbI;0F@Q@+~A?Xo;|eZ5`jDAeBHnT+d5cSt2Lv zUc~p{?IrRcLy4Tyl-{BqSR(f;9N!X}vkzC|NO!hGHt2ZxXamR3rniJ77Fs5?L_~~l zp%DZ1O&EoRRqzcr-|k%c0Z&?s^A0#mu%r0UZ(yHICaq5bDKR)A8&X?@Le+%GC;f1R zJZmJaLf#HU>QDwFu8qvol$Hq*C1gMo&~BRTGhs&`DyW*OT5BB&#HpBKA%8racfl7D zF&=2>Z(maRvf;b2ntNIvk)`&XC1!D^CDnyKNTd8!O_x-_xnJ=q8K5Jo8ayPas`ZGY z&J(faxbU=aMfgxqmc#c>u>tvwLN3gR#6b6k-;z+Did*%QL$~CwCD2Ik{_8J)9gezV z1Vm1NXCzR1)rUE$&mX<+epDO3=&pos&&ki{OPm zxhh-F`uj#OKCR{gJPJDUH|nmMYj+L$)e6hnIa89lCYM@G>4qZiHG`*|r0$v=!j6 z#&^*WK~upDl+y$07#-rA*_=-qS|=+^)ats{0nS)08;4jQzSF+(-R4=Arpun`0@*Zy z&Nm(T78a5rxKOW5l6J`IQf8zvt&*>+*$msVE|v6Ojo%+`YBp~c!@N&C$n$S+xBK|3Bih6QAGkk&dXL+t9#1lqp@iU+PTLj}U_G_c(38 zy?h+nPx&~BmqoIEI1rDW?Zbnf>TKK}-q+eYI|u(|O7ezDt^9_O(ZB?*tC4@`w5Z4lv^9G?L@gc;IHaMTl)%azy{6}-UUBTP!lkM8Q6q99b?2Qtj-tS zu1u|E{90`RqyZ*`?m$e?uxWMkgt@XdC0!`uV;i0qrV7lbswQCew0*(Bq>U}$yEPO8 zVZn@h8{Zr7S%uFhel16_dla?ziC?d1_E64mE#B_2X#85uKfAPg>f8)^j-H`uUi3QvcU!VhG3aCHD&V!Ixp<7UT zNQ%~F1yYLYT#O^=lUw*7YiM~-KhFtQ?8GqVdDtmnt2pgD%~1K{?2@-Di7zh<7Kf#? za_SKcEX(DeZH9YHiQJ(AaueZ=#xo&vN9PeBSQ{_j(gO z9~BsSb*JAHnkEk!n<@{f=;qT#M&4N^r+6aotO;DQ80%64DOb}1DY0pRW$FBH#uFL%m~hc|k;@dAQA*z`hRz_2KSl9XcEr4i3)RvSflsWNLbG*%&1P3iLVz9m zysg=jDeTTsgX818Y;LPff&1LAhx~n_ z^QN`G&1zRjs*VM=(Ns?{fm)Cf+>mgwK4umwgk8dOO9JUPM2#@bIa3ZXJZTSemS$j2 zD*#;z3omSKX^K?c;9or?ezfqCb(nC_I-KtJC#a=Aj&-G}JEbOPd}la1rl#gV*N{$p ztCUmQ_T*BmHgr4bN{p*jl~kj?vqPO#FGpEfzfn6)))qpdP$Ie!V-5kEYxjxJ$15c4 z%r+a0yIcm~wzu+6R9}~Cs%YD%BlaJyw{+p0?;KHrlfWalnHYaVL=8N524BYrGxU&D zksAZy+qFR*!g>pI324DWzOVaefK;^#lf*Fl8K0J%^=TuB@tDiZQ|-qw*H?ZLk!v~U zVt|6og_T+%6~bqurs^0*jaqQS$7HAFY>=&wabG}+s`NB&R7Frj8waY#7pt1Z*dGdCpelv@!wmwjAVH}@xYmG81r>H9);gb%IO_;v6R8Y5`Zl+xT zECc6#Y(%$h(fid~Lj8u&$bT|v>XOI{(YsU3^9hoOHEw zj9?a&5()gzKC-gy*Zp^!VPS!l#h}ZL>AtmBVV!I;)X9mt*Lv%VogychI(rrBOZ_6+ z7HHt4PUKvtFQf?DRe9Itod#N$%kxY^^lqi}lH9vAc60Q$n62YX<3?aEWd=&)Sj?Q< z0L-2r#Pp4cULRA~yC}B!imcDQA{z`>J=e+B=q$c0FEgQ5GjIysdDaOLy+xF^eCqO<=MoHL~LN1nA?aJR`Q zDkQUPgw{zV{d5=Ju|}W=_a})MU1p4~T&En>v`1dllq_CbyGLGPf{%;+ikxd0B-Y~h zWnHq^Bj<{oiT5ry@y(h-b91PF5m;9$bl2tW2Bj1u-)sI%US!C29u7oVyB|Cp7+v)t z+Fy&^4R8_sxZBKuI#MU+>Y5g2NEd#ly`fHCuCp$hPBNs=f38Cs=tBm>q73Qi&!5Rl zbhdZ#K4N$`$L_Ny+0Ubm&I3O~Yk`v{-nZLZ>}LIWAZO0Yl?K}TD2spVr`@-W5x=lM z;#8tvDg2|EhlSFN>$ody+Z(9=Mec=*S{5;b%zuyF6>D6YM-I|a62W0beJTBOf3HZK8%}E%YbmqZ5{I6Fd?5$>bczNtlx;MR zrpJ|H9^_3rlj6)UdKEoP_eBg^%tZ5&kAE957C5QCv-BoPluP3`_C7$b;m)iHy=jYe z_l9nvHu)qwCwcBIwC}cG&|{RN^jGfvZa0iXU({Ab6XXQ>i0Iu+d$I4u>#{?4O>Y=6 zp7uM=FswYLE0_Cp$Qk-*p#iBFbTkL#ly@3$f;_K~9_h?$#`sgy(P6@DqmW+e?6r&j zPU?Iy_-3S|MX%;i8WSx&-pZB7eC?$*-`(4@zoul=&7PQ>Q*Q=!Sp&|AZ&y0tS+BGg z3Eakg{G)Yl?E7IQFpRYi=~gXvv@H+h-&RpE@6B+$~Xvi%J#0u!>& zX0MvJYW{=;Y>qQPvJQ(}QCM*aZx;RH2)hb8Ol6U}I8`LAujX;(2Lr6>C3{(H5g%3S zw}*{LKorlgy-YE@@rnis#yFKU;Z9hYWTP`wcpg{!imeh)aHVYgAsf|HRR)OerTHVC zUz)9yDgumAQO3GV&%X#6GIu^nP?j#W9<)nVRhhbU#0yTV$+ql;e?dZ`bIDEA4tCO^ z8sC+$(_)RqBIb+8FBnGF(R12G)hzTv8oyD|D93Ksq(PhNctHr+cuCL{KQBZ!G4WF@ zunet8l#MADWkcaqVI*ufA6XQBBY{<@cBZTuyVGwBQIsXhv14aqf08K2XmM7{NsI5Q z%6Pr9EM3;8q|1pZ^eQK1-zC0KE?tfqn=Tv1>SZQUCvnUbH=9J$ftDt2iUp~~cBOX7 z!AN9<1ZSy ze@b78iyZBlesJoYb$7EZN$yx5i#??=mA?HW3)S())K0bxa~}?9ft-Bz?%_a0lSUqJ zH6iCvK%09g5RvtH@2`AH<$nHT<7@mWzE}Mq>LEJNOArP8o>R z)$OKfPib@H8fByQvX|x-eM9|;cU}%ng{FXa7vkNz%RUu3jdi*J``QftILa7K%Q%*+ zr;IP~(u0(69ua1bxmNNV+BJuCm3R|>)rGa{E_`&ffA?DW-TX&*QcZWwTBUH(6-iUn zHhB-_aA{$?`qSvDg^DT5ZytTLM<@jbx4n_^7Wc5sM0 z^Ej*Yu|2rrRP@o|e4K}EGp{%aq+qO@8G0lDu4GqgAZA@^Aa>mh*$_KJPK>?eC2aHa*Ir584fU->iysB`JlJ4~5IU+68c=o{z6Zm|5b;XCiH zXFXW?kaAO*NDA5Yr;#G{V`7T0qE~Q|?+&wBZ)3}Aybf_0{D`sV(C)+Dj_#kZt69c% zuzwgwfI%~aB){O9D%Q%A<2=|Yea64wzAR5(dRflOyO>og*O1Gy!a~8z22^e5AOVc;|nqGv^3{#_ciBo(vUkJ+39-O z&j^&bM93u?YL-&Q0hcCC2{xb1+hZ!++zEVix4XL_0Zg1w-?#JvzObA zHK+LVutQw*u^|c}(S6}&CGY?H>23kCIm|~M z-18k$45q~1t_!Bjwl@A4bUYM28GZ`m%nDRLmWwlPovopc>-g%&ni5Cv?%Ia=^iv*Iu zIQ$?VxQ5*{d570tJ185gln>tAt7#D49OW^l?Z=yU@P$IEdn4bYhAG|7U#ZR%uwpSh zY}%degFEXi`)kg4KgJo#?%2OGS@_aBEO@P7XS0_nn{7E={hs}Cn{n8CmXo!A{<~Fk z)H~av5meP`J1@R#JM*CQ=7B4{>+LmitnMIYg$?f0mdNT_Io5#rfw?T}bs?BjFIjHY zD4NdNAseyzctp%lfO#M6&{wI1A7k#}TbP%RLE^?9OB4Q_asb&lOpN9h1(nOI+?G ziI4{|_L)>AM!$sTpOHT~Le>l)lv= zwU~)QFmJKay-ssF<|x>7n?zQ+-HG`I<1ZfbR<#6qCNn7A8)x zzGpvc>ukRoWKW~>)o9FD=Rfb#;h;CY=9U)~s-P7w7g{q(0!5`FV%sLJczL>U)Z@~A zFp&_c*zwCmZqMuKnbNs?+?M%+=hhruGWhs1^^EJAfJG%qSgkJIZ)vsKiH~7igT40l@PU{i-`-_jRNgkwaJnx@RGF$siCmo8m^R2$_ z$_~wh9UUAqIpiDJZJIymuxl$;r1=pV@FRWg7?D!rI_FO%VGR+`R^vJN!}(&@b+C-P zSC!A!_vQ5YgH(;7xc8i6TnZu@JIsl6Z6@ydyg}$%&*%3iDMy!d<(4b?d)<7#E60#) z!n$(3Gsw6<*?kbKVSjhT3si@3T)f|Iya#RL;0n*U6qLhi{^PvExmcH)D2-D*V&5ga zzh;g-G!W2Tixy(KzUA43gUW0b~ej`>GKj%)9GfO4N7L(3a9 znjtH1KXhQKWY%=|_DdPp{_ufw*jFce>G?+wq^2Bmr6!K{MwB|#>g%o)jQ0c$R(cwz zwQYY4>>JUZ(YR-H;^*R&6STf6QI?{`@2~MS4^#KNKF&z%Jgo8P;^1fr*7(sijm=Zh zBg~0EdXFyNh5OBkN7r0y9%>xWKx@NnO4rerp*3=;`4M|lOqULHpfRLj=pg#Ofei;2 z)Bb2m+_>f+&90RG4GL&>LXw9BpQl#}7QeG*PxDG+d;{@6#L#Cj`)SSvd-JO;Izw+Ysy@&fvNC*SsA(SK;lKj9#OSq^Vf7{!j%?=^%3X zO7qZ^?u`e7W!bo9Npo5o~jl=wfr~{9yTxu9=N<4$Ull z-`C7U4EVykO7aOl<_;xc@wszHNm}t~!ACk0D?BUqgoH9(9Qfv-HxI^;O`YxXy}hDd z54j4cu;ARlxn;5H?2=eX5y``cBRF0{7S?C>75Jxo@R_3!1OP%0bJ$ra1Y!+0Hky$tNk#hc+tEWKU zmgych_?%1W*Rk=q;B$hs4L7BkZ1-fy1UGDQZlE_PJsN zQ~XcfwB!cY8UIL*_03~%G`f<%YXEOJ2{G0;_B7&s+8P&Xoc+2n$ynW(W~4_W*)P4* zd5r%MaEL*E>`7NRZs-WQ*XzpBQBSO-f&4OVaCn0`{wVkd%@AXq#a_?vkH@*;>7%5a{&KvM5OrqQ^KfhlY6`d9zXd?Dg(%ehvOD2K%9@(lB_& zj0%P4M%G*69z^XK2dn6=XyS7(Q~17K8itbW@Yy&Ht92~O5*5_)_rMxKtuzc9b7F_( zwBH<|tY6KKY0R}eTW98Dnm+T7i;QTP2G8k#Sq{^=Sxa|rNp)4odlt@4w@j|1y}e&@ zT*F4oC08LdHN-&cTH$$73TF$^9y+17{sSZ}|WwO;)V>6D}!r!jZY_5RT_FoR@l?FnSM0tEd&jPy% zjnY7T`YSgmHmORc$%;3XMX%=oy(67)6a_d#e#`eS@AQ5Dayo1ovI86;ZQO*h!ar|! zE!Aw7%t+IKK%o>Ii#24@_D&~E4 zUst(IbdV01wfOzP{;Pd2AKiE!R?uXD#(Lg^xpEJpc>O7e3ZL+`6~zCZn=rN zzPWU~r6+b|i8-geF4tL~lEes(gM);f7%c=|J5=_b3qKWhC2j#{`OdB*G&xGk{66?%l-ILq{>*XX|reAeKzR%Wap zLAPu)(=x>fr@V@?wS0U7x0&_r2ve1!UX#Q8iZIk?a+w&mcMkM(t1L|MCD%1UT}q1n z0u7x~s+2i!R)&?HK`xBPtC8Lr@IM~)nhnvx-MMC~vh00mpT`^sDdo0W#6z&DTc8$BpV32olDwk)SE=c>Jk zciV5fC+4i?FWZ~y*YPeqeGWUYuBW@_RO9K>uIM%B+brYDW@Ca+H`NfsQSYVz7qr}U zS#8fjTD!l$OP9i1LOmbwtrH=DobD?ZSSlt3gjRl-cSY^uiO( z&_0eQ1M{J24Hq60Oo`a-r#_sbcgMktjg@}s1UrH8mfI+pZ*wfOmy@2re&JWoQ%-p1 z3^>96-|#~^8rTGDwU$hI8s@d+DE-nwc%B9C$Ni_`yqv; zC!jG028TR!m>*VcN~K;xz>lwpl1+1+u)ZGWmC}8pkWE^R#D(>Ahvmc+fQKdG*_JR? z;|Xu-oztg42~MhKTeM6wb{*S*1c3dU!4t7TYrI-jI~IDDkiwACt|)HGt*Q!jxwJ%8 zrr7qe_@wB8tyjn);5z!op)5TOjKl=C$^b1$6f3R2^D!S<=#V@P6`~VE8K5${ zrU-grWcMUtpAc4j0oqJxVTPGZ>-gEVf6KX&Q^L2qb%CK3U%?wjQ$7z`>oR@F zVCczSzOcx#p5cKZi%fwbb6@Q}@@rEdW!>;V%05#ddByNRa>W_UVQ%5LH3QwZb{Cvce_~^hRVqk^Q(W&#SJ0q_9-6MYY)~ zDz`Bm%2v!Lm8#7o?(Pyq(IStE#^H)>JN3{`bPp}5wW`;Xp=N1#o^s1#F-g#rd@Wxk zhzAtVVWq}@2l>O8r>^+OGOzkMa95dBijAtx--=`il~(_PIUc>X95ogOl-(Q3O=#H^ z4!xK~?H%IN+{J&0qF%kSEDEs@h6U(;w<~j-arWT zC&tn4B0Cv8%Hwn%43J7_{~U(`tQj^2>m^?pq<4w}xa23A!_e|x@F^7MfG5PNRd-qp zKjg6$0fRXO{?3|Zz3oLg@9`HsFQE66q4~0QJJZM*bjz**_grKTah`z?0?obLrn|sPbV`ndW&I^y&t>I1I z!WQiGCLC_IbL zqjWx=x(2+k5zresJGerF3W|xJHZxQpl&eO(R|gid(%m3!a#Y&G*|Q(K3|DhqjCwErXd3n99Fr zd$UphDcQ?_+|n9o8d`M)BfZ?IF0)!67vHm5WW$Qx7R<&GQMIptSM`QyHp~~5U|#+V zrEv&F-twHT>$o$eCP!`iF1w`$`PLz)2Fx-ctS=i4wO#<)+z3v*_MP+jofgvA)%!JXn*XcsU-EnoS&a<&-~0aInvQ?>{R>`Z)FJf#CNFIT zTL06$T%iwpGTL`aD!-HOj>;24*MBF=1K&*76n!VRsmo?9PY)B-MLmiqNw?)pK~siU z4*?Zy_-2XZ)ynftHPA%p^2_i&CZEm%u!$J1LHi7wh(Wnt3zh&~&?ACKt&ScN8)BBO zI22pH0LBEGHzsA+3Fy_Xic{<%Mbtv8@^L-QQj23hWZX@8slau2Ybq5d1F6<+S)sL` z^G!PeKA~_G)lz7n*EOYnj8&%&Oi@}OQxs|$aTD7-^X&1$-*M*+4;lKan?BP5E=g_G z!@@w}8*f;}v%(ibLM-*L>3R>e@En~HANOd>cJ*e#6UZWly-H!_vwRBnq+iQ;uv2)} z$0%mBu*_(;%5T-G{8ehFkbGR_H-)JDl2&!A<~8hybq&B+yaC(2ndCj#SE`fxH8em1 zt_51=xP6Du9CAzq4`Kw33Ug7`G(|htidQL8!AerhQp&2aZ+>P6ri~f1EXJurdn*)C z%P2lcmlsmeU)&y)A`#6Xx@!*4&daputIvrQ&Q&=Vay}LhL8pC)f5tXhaxl>jjk|Zw z4zW+cR(_7n50DgnrjrLv!S1H-0AwAa#vZ(qD?)(nCl8P@O{1q4(re@nz-*| zseiX!dl$Zuo*~`n_)h*w*=;uyPZ7y00_ut$WvbEyL_0N0jrl!;vrR4Zx0MdX)|8PU z8$-%&p=BZUD!`%NlS$Z*oh%7;wM~RBhJ=!Vu&8sj0%}kZw&{=%S%+dkJb4Kzk~C*qoxaopoBM9V@&*jxV?JVQQ&zU!JhRY z_*c*_`=6BzyX9OS``Xh!CHIlf3Y?vlNtcato$yvq)Sj@Qjg=_l++lA5lgW)(R!|*T z`h`!SngM&B3cX}5?%jj^7=7jqtXlJyD9b53=FC`SNmg^%<~gxp>z8=12>T(e|GJ;{ z$WQ!6^<)9{t4(W~0qZsa!}c5zbrGBOK+`nUC^nReYhoto@z$||WeRYU$U};%dNl4c z#^!aUr`?Blp51@dr`90$Uc^>l_EG1EPdeH;OAgWD&av-77lC)gno>=pP@Z4VE*jJ! zR|k|>m3trGdTmED(EDYb?VsMYLVq^jRHhzx>*r4mO^3vo7(AKsrZ*F^#nJue#0|k- zOndAhJ_bG3{6G5epJ%%Iu(zfH?`7a~1Fk#x&#MZLHq%zmbnoM_@20tr{o{$W;|mYl@?usS%OvCMHk#SJU+SW#4z=^ykAM*5~B20g(HZ10zH z6n1#m)X~?goQp+jZ{BCw7i5Jv#Yeh$X6c*zTqmSz5La)GkWoEj@$8zVX)-#BL=o)*)=)I?Xp-POr zr62ojN^>-7eQqTkZ*zeuEu~!Kp9vPs9_aJGU`@OC)lG*uJq9~~rm(`W%}7a0=LK`j zSy-YO>GL~b<+N{iqwN_>XNd*PxM$tO;4Fd`H{j}6H*bQlt65RX#L+qQse2E<2}Cp* zy==jc|B?&F|4Y`#Uxmhjt~VFtf^HXNJ$vED2~u^(8x>vth0CFb+3>THti^}Q1)tt} z@vjPD%93zlc|3^|g>*^#J4tvEQMD50os&-vgCDPSE4bUw@FXlGgGPF6Il~R4gSn+_ z?R+b(rN7eXdPVSc7g}FfRMYE1>+_4gmQQvAParsPWD~r1XeJS!z{@troo0HbntFKtULz&>K!7!ulw*Ppa1@o~cYh2re1C>D= z`C7p#r<-U9Dy9Ib= z0H++f37pwmc4LqJks}(ufb_nt4w}Z#_o)_0qUoU>DmsX<#iOh^99ROo+|9w67c8YcSQcfv+2exNLAy+sCyW*EELmIo*_1zA#nS&(w zu|wngDr^~WgCt(l^s2a@XX>JbG(^48Kxfgdo+O3&SXFD?tKuK9w}w=#mJK9J2rpx# z=uTot3Q8=;;c0>Bx*O<7Wlai1cClJ6LUM$bqp%VAISJir0g!9JBv$0{3>d9zT=3QM zoo1gBm-U|0Cp4L(H@;$axhu`z} zLMqs8;00yJ$5#2Ow1|)1UEy2Dakmm)>d}V`UFdmL7w+E<{LedJS2Im+u+FfO@^~P& zNfJ0rw~@Fq8#i=@TfI#+)aWK)(^hZNY?&5IinKzA_dhim(p8g<|EbB&+lvl#)ukVG z+3Hma>{go6%dto+g55Ahw$8oVOa_<|(*!Q42^`m!aUf2hy`cFX?FDV<1ymOpxtEnP zFsgn52g+ma$jwauLwvJ)nD^o{@N;09j5fDX?+c^=IUy!S=N`mkz1MmyS!cRwFTe%G|JIvooSutW%~c<{k%a*s%~`6gKBu) zd{9{?>{v{ap8^YwzD!dbQmidL{Rd|WEebAK=nRD!{l&fZK~6RNO5%VoRtg2j^`#`9te+$pAh%M>>-aXZU_90~ zhP&Ioyc50fA>89f^EuM>7Tstn0=2| zVI@d6-o7%fO4c9_&!*VEY|i@5j@ zqQ6$seTfmA&9l+=KiyRonw`rKYg$>Y2VdAqcpz!8vd@NZp9*o;n(nR=RHas@U3||H zQbX_a|Bw4xyg+Zd=o|m#Vc{vjgaWr2$(9h~MUM#*0W><&(Ys8V*|`+4&>nLk4V_I| z$si5g!-IeGP-|H0 z93~cKs0wqP!1kKLoLOk0S(srtDZW#+g)*E+9THFAb6sX4tMNV*1 z&GD}F`pN%ey-xL!1n~Mz>sql_2UqM^@F)=D|NV-+`u}6aF8CiS_T+!B*jfKxu`{RN zZ6AYZdQbjeuGsI&|J#b48eFljw*2oa_A;PCx>oEx|I3OUf9HQ&vH#KW|L=+&*74sf zc9-5IQn<9bxKCfOYk$29h|oNU@14B1L2~^v*43qq@yTG(Uj)pLT2f zD?*h`Zp(D{te`|N1>V(&Wk(sMjepSp@r-mnXs=<)oPj0q5%{Um8CYZreG$9jKR$DK z6U=jC-4=GkJ`dTpJeD<* z!ZJjG;L4}9u!@I0s?CZ)uew#+n2{kBZ^WwBuZG9sUogY`pDFxN_vL?IfpqX^+JDql z;mUvI>%XqG)*bY6rQx?Wyfr?St~6ZHWZ5x!0j$Z%Sck#XR~m}nd(eO|LpHb+w?1D1 zgf3?98WUIXTr5yqp%fK%)0hcWQg9y z4T0?(YuCrT(mfvBaGuwe>$0ph)^Crqi50fBUdR^Ssjxmm(t#!ae*3sPw-CGFz;UjE z=JExsUhiT(bi_`x;#*r|{U_LHxgq7Ym2Ei(6me69GU)xd($^s$7$csQ<8+huWgsVt zuBUMSKQR9!Usr-lM;q*kN}+4EZ(dA$<3jYsn!so$?6M1}KADjaTgi}niZWkzwx5Lz zY`}VSzr8K+`vcqf-zxJ3MNt&w;60s`LDMWf3H)D|zHnV0)fblLL01@u_@Nsa>oS3(X>JGX0;qUkr(0_fLB6LGUa^_JfvP*yX2@eZt{|iC^&fTI(;zu1m2E3{_db}33aPB?||p`IB2XL ztv4OJu?{&}Z#WhPHI-h+LUERmjoodgq|j8y+-u)<|5I@_-er#7ZZ!dGT3z#ma8d}_ zHu!{kb6fAYZd?b`TG%h0pW!3iK}h@0DO z7_*G+U7#fTD|}Xg=v<7)oXLGJCI5oABdC1alMOk795YY>kEF2HcMs_YtuWv z&iRNBhmMmBZgtPHL-*NqE_#aOAafsF^Lx763*hB_!($q@*78lwEO(nc6o!ZZqGih0|Y@xIHV?O&@Sa~Rr2^8sq z-U00WayKcSg>jIKH&4IMA)cnT33!&!&<)V3aS6+k-rOTXuSZntjmwl?y4s)HpM(B6 zuB~c67)7e~3;l&X&Gi@?SG-w}n(nv1DN}vcD&R~|AEwR7!}0^nfLC#qL7c@!xGH(F zkRlU*w_SaQj;h(sUFCewU7VwCnk<>sv9^A}+G$1YP@V8Pu;{e9p%qro#TCDIA^K!C z`X=p{G`F;GPP^CDH^)b-iaxX+Xx;|&!oUOD_}rRV(1*+sH;Z{Ovw*~k^+Ll@*i~k3 z^S$fcRouhENZ{OvmP&<>?SH7bv;B=zV29Mcf6#F-M62jf-GW}^$$pBd zEj=ca4pr_Jew_=NhY=(}(ZQV7STu5|(fyD8AvB+E*D=PLsb8KlFNfv8+%&NZ^y ze%h{Dq4Z@af7GwlpPR?dx6B{n%*#2Gb6I~)e|kQ*fIdU#@b^Te@Q@JZ)IbK6#M28y zz{gjR@nKFk=N{3BeFRA`3Lj<1340*1f+x)-9nQ;P4q0+A>p#Q|#GLs^O$IfhD}lR$I*+Hht8T>p{w07Hit?})-1W+)!r z4aCwQagMkH&*j97OTN``7WcJaji6jrj93Lb?JBVpY!C)mQn%Z5r>NijS&K9byoRC8Xg*TGK0m81FEIAP#_CI#+&KVC>Ka-l1vjcv1yHU;) z@SUe`-jyw8%cr=4(1K!UU^WEN+_@Q$TPVY~>rWK4>G0nUrnkO5gA-^=DW%76|J)t; z#9M3!qaCbOqV*TR!(f4+)0XgPEmGhjw-C__I!7~aLb*+c89^zgi@-K5`^a~5+3J=b zU)tgO@g=^6BP5~nmSY@KPoi`QokpgSbk~fCq`%!1BRKpzbl|fzUUD%bdJhU|?EQ!Z zQKQoDaBZ{raO-3%efwE|Z=$?IZYl1NHhQj&>U$W6z=^y_3}jGxJxLzbXy%36vtQwS zJX6&=PPqfPl=SGnQ%J&F>1lmP@_0l_+U3IjDU83vwV$B>7UJC9%hB2C$6XiEr>V95 zf{$er^~{J~gKh#jt*)mi;(m&PpSlxh+nC&pb6^xRNd4Fue4F>8dt&R~6(1qJf8MTo znMHbv=nLMz@IWlKrII7wbdQoyz6wJkc%>rEWFoP&OyG+7MAsP~$5GY^W^Aj6mXC7e zE9%KDGC>dL+1!k(Tg1$0Lls$k*EPMXh|dL+%RqNt3sL2@+<4_<-;Gzgw9b#WDxUlk z-L?hn5~ch*Evzc4alSK2$boe7*nP5@Ddl|gnfLet7h~GaM_qeSB4#p#wjEoUdur0{ zZA$l24RoxlI$jmI0dbpGU(k31we78g3}Rg+yAcC~$uGh85v zM$sHky$E32=se6@P`BWAHOQwD@u6j+`8FL{RT)e3t)w~a%5xXG`p;aK1#|s&3#$xm zSm%T$Q;HL&N%McFnqM=|RhmwvI%!F2!K+Nlw)1Q-|Gx+GHnr2|rRg})!%TRv<+m>#t~wf&$~EIk;j<$!q6c91``9f}kV^{w^k%rswJ z{TZ=nTG?QGw0Y@#@;>I1%78$qhtb8(aVA8ek;aiG>ybbv#^2|iIAX!RZ95W}gyW-~ z29r(1Ic^@#Ovaf{aR$fChql~P$RqN0<0ah@VQB=X_%7ol4@BA9F5Q5@D zdyxs93Ha|i2gh(8Rf3)}W3Ea<%)`$1Q=Mi$3H}mh{QpNMkN-Qspb6|mC$tLSb))=0 zB%#UL^-Nb=k|d0}4C=oy(*2MkL?q&H+*f)3Lop9tks=Ukd+yuBJVaA8;{VS3H$=yS z^IPx7i4L6Kh4ZDjUybuW;s1KvKTh9uejV=5e{lYt`&sE=!3STw!tr-7^j+at%qx_*}&?sUKm4p2G-bOw7anuJMUk9lXcr2dgXTx{`E!77rP?UN0yxehkO6 zc#;&T(+Ta~gyWe!N&cf=Blx}X$IUz$^lP0_@Oh(yV{!Rib`RY@bhaxU7@u5$KPZ z&QBWcI*jcK-883BREmh;^@_@UP&83# zCJwQ*bh)QAsLL7j9#bFK7Ajz8@VkHY(h`c!31ak;Ig9@$^3Fn@^F%eR<`r&MCgtpD~yZ}+<3 z8`#Tog0{q1;ey?eY8XZRFTnbtCPQKxNe)S*`gEP?Fycy{7lXVS%2U9s=7~X@pAs=? z-~;iin?_MN?2fe(gVWo~Z~&SO4QvqCy&qs!{K`97>@S?~o)N*84*uo7_4?onJo`AX zs|wiLY_QAOc96UdcJkM~&iVE+to@6a)j+mhTXxzu8;tbTEAnhReTx+7HXTL^wXXIM zzQei@!mv3iVfEsf`n{rIL}|C}dA{IpQ{Ex52lmcd59C{u!DhAnB>rIAZkzV(S|&bw zuQ)F|_ta52T}S6bgfz0z|8zcVy{o{U*J?9irp`5ET%4pj&2V9rxC%T6s~6*)4DJXG zaVLw4gbA4$e^5 z>x|E!CrP8-qrq>4^$O)@G5X1%Eca}|jJPA6?Mv=jZAl_i&LNsxK7ZJiZ8P9_r?*m0 zFRb#?b@*r?Gxws8gw+ZyBK1)?<^rZDglfuvpzP=^Jhwqqk+kVmyp^e zuhlji+-{TbR4Sfw2y?vsj@xX?{ zJ5#U1kz&dB;*2FxPRHWy8FVGDyKfM5r%V{9t13&KuRAB9mulfHPFURzYzaCt*>xjscZGt4>-9IbHKzPl_||yzjUC`F@=CoSf}B z&w4M{eciFk9>5)Ya^TV6s8p1QRcRe!H(3et_PK+Bn}{TA_aV#K{$L=5W;gS|KLFfG zL(u2be)vj#rwftth;5j8r|gT z?%~J=Iah>H3#}{~TG^x3mN@q-g~=Qlb;~Uj%3O@&FgSXp8QZdNT%>y5Cg^M1 z22UDs`$`M+wI6(mT(hqTE5|QKl^=4hrlnffN#PP^Z{-O;bh35z_wYwurgPU_=whlAt_h(yE*;9Ia>+64{u6$t6uv&^7azAwF5FxA zluI!c9Mcsmt@T)099l%F*D775`8RyeVm8{C|Gn>{Q?d|G^4j`R7b~oC>6S5qs&F3e zTWNLXWa2kF%2bu3ZD6V-XmKiubfGT)g8L{R{s8`lYklEy=+(i%WsPw4TtNvzVsnojYeS>gO^OLE$u&-%RGo=ApK z*7IsawvVEmX;xwYuhR;qe5WPV&Fl*XUPa6p8IkIyGpEuUodSDPSe(bT1ojb}sdN3j zIGwkk)=45ADa^i1{^lVvvLzHkz@jP!$h9h za>Sx+jOQg~Z21J2w1U|yt85hpErV|nV_`~CBE}5zi1|z(zFN-;@ymV`1}|IeB8hJ> z(u#6MhU`vhO@xKTD4vHbZ2v50YkD{8^ZG2hzjKxxQ}ux%$bnL6VU-K8vVypwb=hLigk zvXV5vhePe?hf3Ef+c9rd+=d(=0fxLD~G%t=^@wHS>};DHHFlw_JZC6kyj1=-tpTm%2#en@+Ipwbv%c6^>K zmfx-j3F|B|n9bmO`_~vQ!ipfJBRH8!W-xk-PW0z-==79=VH2?g++^f2IYTV|hg)_E zhz#QP2p0d8mLp*KxhmWc=HZOFMQ=CpX?8tgZ&~PGGk|SRfpx}&ye*h3?&^lr+Ckrt zc|vW!tcW~6RR{~|Z9B1Q*=)aSyjKNcc;{b7M6Y)!`8-Fz=Bo$eDda&H!K{3)QBP;( z(6jwVM!Bt}WW-3fMMyeC^RvYY67Y#W1{6rzMM;~M)r~pXrcfmFq*b9A&5!Uahy)0p zXdn}n8LuMpLBVf;CL-gvV1FQAiTxOG@BZeAu)Se>*!E4xem;y(2I~L!UvB%7!9gED zJr*4~>Owu4vHBveU710W9z_-(W-K_H=kGrBqV5A-7LLKrHD3wFGfD3I;5(;n_pdoL zWP{PU6+#&7%zc3e`W8VNwnH233)}|_jKfNQ9RvG|0#>QMz{tK#9hLX~ZGWM2F>S{I zZY$*h>>7TLHP`1&UV6@ek=_YwzhO8vV`^ zB_hxrDz1?JH!FAA;~Q)EDt?~@`i}B-Sm8LwDN$EP{HhX#Un^5|KqrUy_f<#!V)XL` z`3oAP?74d3Q+O@k3wea4p6~EwEm%Q|J(NS@se?PIq%;GP(uln5Nga4SRTJRsJCn7!MehQ3%CWvzC}X%vT4H3C1=EKMC+2<-?S)@RTEeQ=uqpr5W$U% zNN#vYM-7p+#jtwVJO3e$$fa#1Z8O8VOs{*WkFCw~eYn(Ys9OvU%8EYNz_4H7U2L}_ zE~MLAz}8OnorMI!(K2Vz_P&C=Sl&>J@ATBs`ksvX)|Wz#q9xtxN%GNOmrOS{jiXE;{FcPTj~n(A%%MOSw%Z)YLxakj-=I%mQ? zFlSDZ?99(EIDWmq}`{Vq5TwcuVqP@gc&;(c%{1RaEd#C zP7n+%2a@!hr)Vh|{hNnfQZ4xvn(8-Lp}z`ws7)cwVFK^X(Yh4ICeImPx8lS(6Ko%; zm?c7G$?6M49rK6m4phe)%DY_>yOx6`0F2W96N$?%2=0HC@sMJG=kw6m3UiaKbe?7m z87Re{;2%oluKWJ|TmKuIJ+0uwxpa=>;UmJ8p*NcQ0vC~Y3H27Sww@R#(A64##0Q(H zob9Igjg)(vsip)8p=GlAVaOqjlc^cg8RpoNJx|O;K9et`3xt7}X|#a~{D_FNRm^NT zts#jmx|?$z5tJDP*`$?GD0y(TGa=5TMQvdJmxMvykzLHb;9;Qqv(2IC`-q|(#v?%l zKH=`bo+sn2_HbnEBZg?cE{Ai?hGdb2_^z%C2VhzJeJ$EhkDSyFk`#`t$XIdeB+gHG zw!F(4<_!j#gHsR(BeeA0&5TqJL>?Ghe})8{YD z-x2qo4O%92*q_{x^YnTgt%GN`!s0pO9#mra_JRSmuoGUXv$`ka5^)FgamZi)@R>Ou z%1`avvFL}cpspdYFwMs0+wwy)7k&q;+&k(^fe|o&<&@NlMZ>O+bRB%*w>wne&Sc_mU#FcZw zWve*D+aGtu!FnJ`tk01cBi)3XZAi7zr%42l4!C1p>Q*9471J~Wd5$C*yKH{nE`iw_ z@}dg6tNuaJv{$ zhg!Xik>EP6HV)Z(MhrogT4=t=I|E)sw}dIcp0Q|-6&S)y?OJ>rAt)j&NV0{!3zy8gG`z}&m0 zMe$m+}ASiYNai;=U23S|9S%}A#w`dgOYt2WVXdL?4iD#B%ruM>x&6zgMs5XLq>FX zOuQB`f|tRN#-Npc!7)AC+{bKlz$%4Yp2n+gZ}Tu-f!XVeyH{QGWM_YOiP=m2z*Tq- z%PaM`ZyXu%jYpE!;-OF26hw|>)X7a8(d*U+ks&wbn&&k9whcZdIDAP>oXve<9~M5s#S{@uUb`5Fn|7Ik6Eqv-8XQcS{);@BkYAcbZ=T-zMwO{?9Sk& zW3Tz1DpmpyC25K)W;5hnk~@5hW(M+I$v;ty6(t&L;}-M4$@ESMEaeYA^0QkC%Q{2% zAN#@mV6JrRCwHGfnyUZX6PkTHiV2?0I{W91d!^D0z9noC-k`x7lK+M~>3M?lEbjgd z$67-i=9kGW^5lb`FLwtn)R7){zXY1mS#nl^_-bbo>1Hbf=k(y?E0^*pum>!$e+$Hnh zq-`9Ed;H0_)I#tJ)z7J}wvK;e%4S%yW1y+={&}5po;yrgGpG1feWI&$stFnzaCh)f z5X8D~xO?1#@kAr6*4{nt2pwN?thsxPGT{6f2bI`~|C|H-TPtL(=U-T$U8*(kVVhI4 zRFy2yC;gVZIp~pp>y{V?IEnvj$1&*rm$CAawD2vzHeUjAWk8!*6Se1Wn42Pi7{_{E zuiZl#55jk(cMjG*E{^5ot*2zlGEKR1M|jO*Xy%`Xt1Hwy9ud<`!1if1HO~z?J1DYD z3weERkXixP@w>sr^14H|S@X7fJFw@QGrVgo;MYa{9q3C3U#$vzd;3^OiQ4+GD#Xij z)Cx#i)#0k@KU!r~7IAFRei~5;&IM{Alr||%w{$Y6WC!d5;mlY>XgR-yU58r6z$@UO zc130NPRq>8Gz(WKTFX&qk=A_C2wPZF)E>6>R3jqqp(AOWpSCKQldWO$sIq9_=&b(biH z7xpd0tw83+GjNXU4Q%ckP>raClnrj)vfc+Du9UXZnvM|%<=i-5#I}#n0?Hk>_z35U z_;r>^0sdf$53Pb|#7P~=xF!*O=k)_J@(#8g*tTG!$1h`3p)JpX7ZZN=gjinPY=Jx? z<>w$SU<^OmZ^as6gsf3?LgpC@NlS!OK$33zAW0;(Qy&%N^Luy)FL@vRHF*FJX7i;M ze?TmOAJ5{yB?86B7^vSd9XWH*l2V5>#C10m7Vy#fDgLn-cSl{YyoIIkFT{gmO9HtD z{kNy*HIZ?E_ZVfU>Y~!{WPc_8_s_vxQJZfpEG?0|68W^^k&%Vw)H)h8x+Jy409lG3 z1bNB~Um$7xcE61L=XJaPx7QuQb@-mi3atEEc=0+{41}hB8X4;>{WYb@YTV>S=)uqL=${fmCtgJ=xwjX`-`=6gh zvzyW9|N38^|MY)6zyBL$ZBYz;Lk8YZf;Y6|4Pg(bf>BzgnCy4nc-b29?Y*T_MHyLX z`^eU9dvL9azRMYJYxWVmi_SqBNGvwJ3@xk;GPThSG8xWZ(0(yx=Q(S9=`s4D+{Z6YTuzai?90F8aaQ)MK!42Kvwrl zi&fZn=FmRPx_80KG8aCw1lKzuFP}4qts?q}+BjRkt%&0%>RFWb&(Pz6{ZG5>`5csU z;})%0^tmWF9$5U4D;#6z5#)9wPBXltEY{^OJtn;Acvmv@QD9@8O`eEqwkq64jAz{+ zK{t_xFeGd1!+A3hrP<5eiuoaq!Fe|M`JGFDw?tAbi4oc`t*vMJ>K0Nj9@Sey`4T1% zM9&$(>yx5wUY9({11}tL7*Vs-E1rwGRq*Q@nqbpF?h!@A`9d(VOY^OHjvMi0eI8TQ z)NmT-?!#E??_cv2gU;200n})(a^26@+@asiW}XbEt>N{_ z^-NiZ?t$uq#8_Uk7xF7+)IIQv3GhG`xu}GYiU?FHKa_Ms zhCxmD26*_()#xD{KP%}Du!)hp94$GNA27|t({U#4qj(%@yOGxb?}I2nW5Y!Fj>Qw^ zkVnhJA4Wcws+^FIt8vF38Tp^jxCUA1-_Q8q|M85%|LrrH{^J=N{~ymt#WQHXq#osP zVEWi)&%1!Vb`_ZH%N>DUsQKYp|(`eRH9TRyCJ(19a>7HCqIQqX|zMk1~<^}ZL#Mv$9 zURYP}RXhvYR@>C-qG}34^ZnK1AuDjQj&Qp176i^mu3%$CEfsWe$JuD7vNXdvZ_`Qd*BC9}QM^%ZU>C&dmO! zzp>R6w?%O!iHpgw4fW=w*93MmG6rZkA^4!I(z zzqt`vzuBsS0?J%ySp2gM$ZBBle4#b<9-v_dn$R!s)cVfx9FON#>5$vq5vFqiEstD8 z$gY)XdPksG{z{jx+Rc9QD_1zPWtt?V(CqK}C2{rihTV7y z$M42ddIIZ^#elN88dnozyL)fpJiZRsUH`?4y_?v(_KOemrj!r+Vgu~d><6S=sb@An zK@bbj2kS)DJNZ)@3IqmrbUl#iCneYNdmyK>RkW??9HW6m@@jn~c;L!;?b|Hg+ZR{^ z*;EGRG##&?ed#UO;P>_gz6i={p(&=_@(jT-T^%87)XGEq&_FKB6wt?+oFAIhzrcA0Qu!G!-QjxTuJO+x-YL40_8H!BJ;YkTPs)CFWMB+m1`3t|$-zK>PGB-Q6a3)PWFq2s>N%T|AZJYyu~ zN921-;>@DK`Di@N0hMI(`jj8`>$m+Flz|DG$q6j~x=!Ma6`AQHTrB=p057jY<`|O57AcFH27ybB3)%Xh|B5^!KZS5SznWj* z+6ffxGeWp)8tkC`80U#7D;eDmP4z3-d%wb3hH?H1>VI-Lq%%Z{x=G4-H$zc663UGc z1GeiiXRLPQBWXlFP3dq?{LqII&_a3Ai@5^&oVpVBY51yuVtQUUB8(FTLu#ngzG<23 zHe!^oQ>2`0QrvUyCaeP{tn?iJ4(iJZyQI<^3&xP|-McIXc%P)wzy$->FWKo~vouc4 z;13CM#JjA7L{$+SBSZ_;vdib{?Y#j*=l8xp3f}{1^*wq;T*J4%sTiYQyEh6ufZg)b z+;$`K~_pmK&%Z8ddk48ai1v4z-hyka$ z#)vGb4Y92MXr?_m7#JPAh$j$(De0rOp%IXva!I-Sf)R3!R7+!1z`Y9`BpLC!rwOai z23r&Ah4LJ{u9(wk;m4nwqOdf63BJrRLZtAef<51E(+cZkOV1;l8oVFRfawIi!f9*3 zTeQ>S!Cw^)R!qn{T5h|KjGpcx&apzGZ~@-QYS|O#YrxdsPHWkU8eB1}aHr)D?)TBt zpr1o7Tkn$zlt1bq5E`V8%2jlv+C)XjUUw1xSyKOd3xRFo6d;A_>k6@1|PQmiaG47ne1e$NgBLgRZN-=;i^KH}{S zl!~^c#MtGDotlbXy@X`I+5{c7Prn!#jfG**9qAZI!Mgv4o|hMg`Ivj%Cdk$kzM%ip9`mG4twtZz)}gO)E3IsWq-+)t)U>B3y2IL( zWC^dBi_8#mGVF0tIumm^T3bnmLSHlcr~D!`T!vNsq9W|P!9L#Q1VW`OXn^Ow6C*%d z$BdiB@5{b+f%>ExkWK4sh*ePKR<@RC%`za@jPy1KHOpgUz;*T-%g9O%>HmsJAB=2z2)L#Id(deAruyGCo~$5_-1z))OTpF~SQwAJA=0 z?K4YY?F;SkC7LQG;}c}kHs6|BLJH#;>pb{HH8CAzrVm+HtdINz&OR-A5%EWtFiG-C zMddR-<&N#5k)zqNXQis#vs0CBb(NyJC-6p}22$DDK2_C&z>AFtWs_bAt_*^R?1D~6 zYN)?}qw|misEnXP0)*4-l*iqwt(2?zACBN5$!PfZwqC%xuPssnf2zETKmGd|^n*jn zE!|eBSCVS>pLP7%a-5=3)p8+S_*M~sjtale0d+N6L=tKbE;`g6%ob9f3W;t|P|nkO zB>uw=+^3m~sL(3RhY+nz@H0lls7$QUR|BaD{F~=X{g4D|4qlI zhnjq|hvQ9TvSRo7S7r>|Z`=#1B^(xE*fdDRYAaI)-n@!|`{k7@Fy2VLWcc62v0loV z)fc!e!j9{l08Z@t(C?D!9)g8e=ahRXPUasDW|(wr(ugVUFl1a>F1QmIWBWytd#BXEX3QRJQ_L0s_`^xdkFkC zXFNj>C~L>eHG|QMY(-g`i2rIQwJA&Z0aa{y9_Ba~B)~^qbc9g$=>{LishqK3cbb)W z*f*3P2+b08HaNwFS;003Gam^)3xFtfvvUSqpto0nIU#~9|?;__+=$f!vjUmh^ozPKJ%by9fAr_9U04lf}P zJ0AG>1~SC>H~jw$J@-quKJD~{?INousV6-HZtq?VZ8JPUT)Uc#K89;_&zbq{;ys^C z#os~tH2jU5JV{EnjuiY{rW6Roj6U)Uw_bl8n*C5 ze5y~5bhXs4XRVSE`4|P2Ie^oC9eEPVA>&aSnmmc5q`S??9?D<_*x$p1WPuSLg)M&i zdKYz(cIw zI|p9fDt@?tHqPw}0B?b;4W@>i_H7|6WQ%FhsECPQJ4DPIjY)G5Q6qYd=y`T~3>gCj?SHT$fGxo_aOf%lV9*2@euuy4Wo ztQ)7pF@IU+JPr0KwevOneUsbZJHUepZu{%JavSi$4q})Co=O>`E(iB-pVFnSdI9;# zX7OsY=%?KZJfHUQB?sp~+Ia-Fumz#-U(-==FmkHA<@)oos+Cq{Lj?R>q>RHnAcb#$ z+5m3!<@#QS)uR7x{qK^Mo&IlcmpMQ7Su174f{nJ_*7~7*)P4tWMWiBfKl)gGUm#6f z&+A+^{+`gPm)-uDDf+-??K4Tt2gIqT9*ixL&5<=x=sn>gITpR0F<_>$701Vx%QwTD zU#HkI%}qv6am%+=!iI?6z|BE9W148BBJ~*2dFAgOZab5hBB*U&fyZD4Vx&&DFG|N; zTc+pxpN{b!T#xboktb$5^@Km{@4Mk@3r>n@42OROZ!G%I5?y@(^A)4H_saeBJ-}+y z_f-AsE!)6$Yi_yoz1!D zLc8Wr?<4wR53=w@Q&drG1?9Hh#z$AlVSlOg%@UJyschF9i0fO=$A(q~mm?ZI^qA*U zpDSJg=F`5w<*sJ&G2|zt-+R^L&@%@5ex}G$C;%Yd@0_@ar9YrLj>Aog@#b;aMrOkgI)Iu?0p$$A4l!PpvD|FNcRcJ%*} zh+pXO8xA(=VK>F3A44q97mfSdB$9$`X=AxHoj2ik4$skfZ)Hzyp4pO$46CWrvDsu| zc%3Zmfb~rvINlT`^>2zSS&XYkG#$wv+x)D54JqgM%$Bvv!{u!fwQC4T#+4>22gyXW z4Oe56Vw2gFI~Xq3>9WLKIl@1#Ta+Dph2!lySq1uiudF84DKvzYt7_>;tj-<}lq+S) z>J1e2()x7bjhXd|9VxJ&Q=Ns@hY(XsaRcufVfA1J8Y|DaBWbwKKDRpii^qTxgHRMND*PwjHsYx+1T2 zaI7IE&N%z9Wm?hkOEX(W=w)av{I_6R0Jci647SY#ev`;(Q~1<}%-CbiB$3GIL3TmZrbtmRW8CjSyQGW|FIw1cdAlWB>t^>-9$%&`3v*W=;?=!2 zc1Hp%2>o_udiQ94Hy`o$_mNS^!f%BydK0!H{uIvK6ejtdE$j}TuRlX8OV;C@*EgAG zQIGfGSyX?g^BhTft-cICxFNivQg0wetNZoUav?WCX3V-MHz>+w#__;-X#MBNU&#wZ zj=z5;+F{VoZF@y+E@qo1YEh>nIk_3Sxanyv8Ew85Q?fsP4Brul2#UdsADNNDV71Y( zz)?st-hpgGuLO&X;<7?=KB`z7mRW@LREzi*4UH@bw+^vh@F;4ue18TBNh0*SpQczVm`fPz6bu7_)l+zAkTAEp7@T&@$y-hFPY^YDFE?h39$6Jz zO(mvvV5fdvS7T+%vl65g4IYheH0Gx6>u14#`2%uw-_I`&MYSm4X@Ip=PoVAH=~C3d zvI!k-Qb*ds4&;lVvAw0P=Md5HC2~(5=_QFj!egCiqdAik*X~;J?#;q6Y8! zl;G1VgRfi9Ep^RxeJMa8swT*uv_)QF5w*H$kD=UJVr9uAbxy7)v8p_^drmrj{V5gMJSV=fial< zBTH~buIZNhuM739pG7#@HnQj-dImuhq49|Z-rGR=>TW|t;@-`-M9{+j6I4?=fxIFxI z{4!rBN=O7U%o}y@3_^&2dDH%XCGa?>3tO6K=pFY8hSpve%N(_C$4?mve0_7Z;_vX!p>6kpFTf@R)( z_-UYUn_&rIIHp^hpMyBb+w(p1Q?fjdF&W1&{&xzDX->A^bBvePzNj+@lxarleDg{k z5Vq_NWWQz)=?ZKHTm5xr65h1>DB}0e0c=HU;~KW|9gmK$FzW)*j&5nyZ3r3(!Li6L?9tI$z!zrW(zc@WbGb zUBs_IEOv_!8TV7%7|f^-`j`AOMWE71E-$IQWPL5$e_6I;C^7(K@>enbI=btG>p)3N zxqJ%krx%9$X#D?_1T}C=DxUL!H5ctHMLQ!4UrVlf@pV-jD~CL%k<$#pU7GIv>$SYp zS2E;e{1oK;tJS`JJ&L>k`eh|a{aZ6yS94X^hq6hxnh-lB+cFGZkp*CRZUH7t#e4)- z8(Ovp{W_GA|2_)vTf;u&zE&BXh&SfVM=oaY4j45ud>;Eg(Kk(*6vMy^1mQ1g;*ZcxPZ>_&67? zCOv_9y%SxCB_T8tnlj<`1R}vzLT!``SXhXV!5`@ysD*cw>kELHgXbE+&Voo2_yc>4 zp;)(~4^aZk#w94ha>Tm2U|P&UeUm5m(7;7|rrMZAOv3-fC2yYfsxmLEPw8tJw1>R{kW_}Ys;B#CPw zZ&x9pWX%6u|UIEy$vY1<4$B*n`k{!WHPd`_hkik8E9GMUyWn`OJ^qvt7Z=*e!% zBRqo{Lp`o$@L`~wnV|^7BE(b|xSp_QA$EC~3(Ok`W$g+4sfQpQFbW%u3+%_A&v7|n z=esP#3X}nc&VIBl;FJ3(GvsfT@eTEadks9XtaG7jl<>G~%MB-@=5>v)LIZ|vM}@ga zCG}85$NiyI;0H0u)opz`JKx;}i)_1l7GG!3?qM(7W+M$*B-_~%vfdwx+y)qa`zxzy~0mv!T6Z?gvO~bB3 zom1&$m?zanlFEGW022=;>F_5~+?jml8tacf`WJYnqz)eg%V=+(-xrnioA1E{1(}1*kN&d`))(e5NmScz zxN?LaATRX4XQA2E-Mnh%iI-$xo-ku5+KV{)TmM>hBMo~V=6jkCs z!Bo-gW?%Ht7yvp4$fql&t+Fa+RL@y$HA1gl*#%qPP?92o&&Qn()^4nU;iDALC1kuJ ziTKxnS2`0OQt)*4NO=yjJn@%_6gg>x<^Q`N-P3+(bV)I*p6o_F`Pagxu05gTr~0cg zCg}f-_^*S_YN~(tF)j6jK+^wHNCGObCE6%&Q9P_o(G6L`MoYxmwZdn}62nqIB;=7F zyQoZMxa(;(``EzDbKeK&8C|5sRdi&16??mvn9 z&3om-D0WKBt~kZ;3Fd3ZJ(CE<)a)@ z#4s-ugF>G|pHp$L{AmoLdM!SShpEOaWfA- z<@m|RJiy#P#4*>=>Z9LYI(8SR=AtfWrkw&Zb_~9Bf$K1&d%|tXmU>j)3{f)rbwo8# zzCzJMbtqaZB*eq^(*_wq#345b(XmIPnA_a)LC|_B#*q#E52n;Kvi1xylJwWL3M}|) zTVJaB0&&f_J@4_Sd;k1HqC01rm{&wu@`pDBjw4PXiv zCfnyM>kU-H&u0Ux5!Da0xL-Y$K0&u^CEiy$-7Itm43LoF@gD(ZGCiYb-Fifxm*&vX zNbh-UZNHsR&VQ1>uAbofqZl3FNDQvUygtD_Mj*q#6OHu~_;fpJX)U$1Ew^6~i)NFp zK$wGt;DRXROgyY?U9VKPu2(DDm#jq2UuCq{WbX=m-Z!3K2Yt2(`%S>xki6p6{|P>2ZT)gPm`%A5{_U-z4<*8eLcH0s*%b`DiBVhx zrdp#=3SJr^$Lf-`u9r#29Twny9{|7Y#7<8?A6(Ymnk;?dNpRE1r<#S8*6zTzUd{z( zY23TbG$)^qIZMg!-%o@M(5%)8weXi=gpOhNodvfHMf%Nfn<&dbdK-9Ny94t=^)vPV zOa0vYU+Ty7f3BYaDSXcVs2^Eqb;pbjW~PK7oy)1M2T~O3;q#bJ^FkoI=>ec;?%;|; z+MUbuTn`i3?b79;D>R7X4PEiRI5Bj^VeQrBb3<3`ei=-UI{2bS(?&w_f~{?I~K;+y7Wi60hn)SKvK6#TvY4v)I9`7hlFxiQ$xZlshl>MCRFwfc*}w zo*#g#j5n+zLQmlRZeqx7NM0r3A9S(2g#QIv&|!(JbQ%o7XMjBU*$`&!zWulJ%N_8C$Oc9 z)X-<{^}tsL8LF^*w~x`khCWAaZ`F`cqOk_TmSrNtXWaQZ>p}h~{{SydYP$1HR*Z`= zm0I{SPRzjssEO0!h6 zR%=?P$&`&x@)zCAecyu}jZvQS)xtWgiOBLW;1n1gQSBXV?5$~#-)+Ozt z?^5|AzqQLCL4lJ(POd6NnC=&uXF1 z`fue9i)ainyhC~&ISZ>28Fs^WyiMKz91R$)9p!Nn;6|y3{!urqYto=jHe%S7oIAmy z4VGnB$mkcEADJo}eWY;$FH4Lc92~ULItwT@%9Fgo64neRL0c=$++}lg%VL@PPPV=) zGfGjrMYQ$aahol5z8^%*&P79we3x~em~2buXZZcC^}xPHUzScZ^7F(bt#ndX;I|%n z*N;AB+J(m1*{D@@#T6z)(>h)D7Em?mybRY|30>py1$D2s_+ZiXJts@~qHzj8DX{Dy z8GRC^&$z4_0U3A1_~swPZB0hL$2wn3GVAfqzl7e|cxMi5czV7o@Ryzsd@4Ok6>#<3 zKX_U^-p=jzO&a{RkEyPO{bN$c@`K;B5zR6mzHvbd{l*3ByJZPsNuRbJko_HHig@TH z%TIBCvd$I_+8O>=T4j8bPd#OUrPzuQX9Cx5n+snFas8lD`bSu;nTp``RLtRihm5So zHVB&%8;#{9g41;kT$+QRamAw-|FzS|?*wuv*iGlioq3#r>Q)c?zx+6)TV;{N!(e44 z&}`;~a-B_dj~2}B(#eH<@v`s5qsw~&*Wh&^j*?JZ4-1b(2AzY~DcVQm(n!Why+*{r zW(d=GGx(w$h{~XGlHX&U`o*PaUC%J>Oa4f_$6bHGT1BrPj_bo(*Gn>R7c-IGL+|*_ zjV#4J`W~z~V_NdR_I(C607RCDWOWH-5Dkzn6PvWldaP#n*QVQU3VGR4ZZ$jrWtMQa z3ZBF6!0@iH(Eo?JjNsQA9ExEGv43ODo1;?@9kvB8$wC{(@Z<=7&{W7mkQ*RBJklLV z?{e_Q!@mg$he=YT_q@o-N-U}~=f$LPkBWLO6OwzB>p}mtmO9sO0)zYu5f{%x(tNh# z&18zGXc4wFAd9kCXXVO@6P9wHNZvE_0h?52A}-_|BQc*fF{<1JORvJ zA++~mCj&(CbVLg5ML%inqERAy^ZK!jWK@@%0rs~i@IWVxQ2oVo^3c2lHdS&_$uZ8K zee!O0qFp#(OM9NYI3{?{JFNTz)Y)WwhP$qDe6<)tJZkG3l6} zd)OT^KH0@Bo`aUAT*6GXq~-yC`>&GP-yQ?68@SzUb_Tgt#)-cHYfgD^2zt^z{Hs7b zN-Iv;)wV-+1EMJ?X2kDU>m4V!1X=lcG2Tg1mbw{ajFRmq<%lb&km?`hkzW!y9?k}3 zHT8KU^-0fjzznkK-GQ}18NPM4N7b$FGQ#KG6Htrvml>Y4Lh7SDWM^UPigzDtVPfzzEmK7V*B*~c363+Es({c8nh;e1S6`iE1 z3bC^@Tf#>@9E!gE{VD%E`wx0W6Yj3NKqKnCQd~vjb5%VHj{j2E z6Zo!MT2sQST#tAg_z&$x_6|E(NAE91Tm;b%ZIDzg)X8kDS5gz!%CONky2b!y z08BHZ+Qp}NkJuj*Q@O_yHdz#B$GVE_h`+p01Ezdfw7eRAXoDKrChfLpuM~FFO%|GK zwa}(<8-=-6%Dxpf=mCGvFLqd3l|_q%dGUodn&V44P7m+uquK5=!16dGKtvO5gp0;i zORM^k`BZ;oi{sN`+(Xjtao@ozv8!z(Q8%xR?@AkbrOcu}>qI^7Y74Ny!*EMNy3@({ zYRjNAVBYgthLl;l&aN+>jCgZt)5&5^YHnfj5pR!pbC$c|E3>qoom_mft($z(O1LGN zKltd=9L44qjX`_p0^(^f;|P-CgjA_}E-VKPK_Z1tVwfvLW2Vr;g64+4OpxIdJcY=P z1if_@Y>H=g>Xkg~Wo=qQc`~{J8$@9twMA0fLs#HsaSx7kIQlz|{wUtSQ9O>mz)=wx zmW+$&-9@2y58&qt(&B^>VX!5=6qIAeoFxv!I!ydT3iKqT=6?R%O~>9@8PXGSNE_fS zC=KOI=r51-%ucX7h31G?8E%7UCY(LbPQPj~o;ou~S7imSzx;!E#UV=;t#ia=@~Wla zGIOtL6xB#&${)m2b(x`++~}N&RaJ9?-ebKieJ~R%d9s$-(glnkQ_FgZo=DX^Q#RLP zEC@?s$}|@VHxtMw#*k95r-0>!f|~_<7Tj1+xZp!ye~oNJH2oehXw&-GfPDe`v^LgY z{|5Fs?60KPEReR*3=q!;>Dq#Iwfe>ay3Xsl!Ub=IJl7P7(iQkjWNI6I%zgsC2Bw>- zZScLdjBj0owH4=T4lY5 z2gl}44L{jNDh}B`v3=sLgxqx;80oQ)5eG%2U;Iw2WX$brBEJH&4|rvo<=kQK@wS8r zvnZYZInHT41@Xr$@nBga+(W1S1KH0A{kr5s~8eY{B*M5#VVVTZX+M*prUk zguOcv=JwYd%-C1F^c_^Ll-lH>r+sr~VR1a4-QigMomizO)!=s1Fm3VdGu~OEEu z>i;|*nc!#QdeYzby8Av8OR-P;-t9i3|4iIO=-8uUTK9i>#t(gap6P$WCEO)EL+??3 z2$QJ60Zjl>DrH$8gh^0H@7L#PTqMj&ExW!Fs&SkMH@m;W=aMXrkf(;c` zGRwO9Q?7GjeJq{?3$E5Z1V@!>hs$UiguN>D9>f()z~0eeunF0yWhR7-05dsO0I=aw zE)4LgsgVbx<|lahj>P`{dp&-y3jN*;IgMK6sAUS4BOsgKX@smZ9KXT7f+*#!Pr1Gm zolnem^&=W0fM|#ynIWz7KEBImUd93Y*Aw_aWZs6XGP(^tY(y-z$h;ghA}a7Z(G*K_ zGYFymOzbZY?g{Nr#Qu`tjnKXs`-_6cyzj&*=WP+KGUJQii8EsD>%J3nhwWSU zIm&P%WHX4Rbt6f@-%Zn(z>fHPxp`zG)rK8vih6`b`# z$>MFrI;`H-7Fp6xi}GwT|F)&$0zu9K?aOBn@ji;*J$PW=V|m&azlNQ!3Cw=uIYbJY zk;f5imEbjyz-xo+L)JWl_IOX=!m%(|h;G8VOl^47Ry|-!IG7{40+i!V34DIh2{N+V zEr6+BbW@(mbLrV!^++*tvMZDcn|qUW9Xy?FYo;*#m7#iHpwz>U&hb+LFZjuwTE;&G(Q z?g37To=d_}JdWmsj*K`;!qKeW)1onZ4v^JH@lDfuzrwhq@rUSRuxTGjlDLX;&Wcsi z?tuRzx&n~ltyoD*`3iVXUf40S!@XRxry9|z5BOK#l<&WvuQxnX!69$7<58gkseXC?kci;+8 z=Hp;*+4*dDKQqw%3X|KavM@{B)uK}9Js)6Eb(H#@s0zMVsXf_ z*l*j}RnIy#@HW=)%4I)@^9N_cj!O0WxbAfr8R=lkoH3Y#*4P!$b%Pmma0%|GM`6&h zF_+ywGwaly$DXgT5dUq5 zWcbga`0GD-)Wf~L`*BZq;E~X?h!Nat$x5eU%c5oGJKNGDz}g@~jYaoGyp8cX`b!VH z<9^`Bj!JNL%y+;nJm7!)M%32mtub3;w+`HT&sN>mxUFo}>o?5G?!fBKA4KP%NBA(5 zmTJz|y0uPILk;2!7>sboS_!9hM(yc?Y^i-a0&xg69{G0k#FxJkH`RV6mOg=YMC6A? ztIxXxAI$UFyWKV7l7$a8D7Me+cxm~7h9jaC5qd?#E{VbmWc1O-HI~03$B@}SaP1|r zSoTrpi?JjI=brfrM_-96V#z4t{{WV%SHi+zOILbtEI}?H6NzCSys=>a0^)z$0gL&Q zn?*Bl>(lAGUI@4@iAAwY%AAYOE@4K`zW5e2XvCSf&woPJW@6^>ok}age9E;PdENAFfQ&4e1kn>!5-|L#@?O+0ehd) zvjsP>cLIAi3ijZRqx9^88`wMC{jTrs+rw+Ix~bY%pd?c?Z(_d|{z>Yi#M_4zF8IX9 z4BzLY8gTH=KMyc&`S8~3eEWjPb7IeP9HRObGHgv2e-u50M%;W*GNOw5m(h37R=@+p zgFyQh#fi8Nz=!PsdK|ucdhe-rKAo*0iT}Q$@c^S&mi>HPfegZw9|#d=9NO`Z1{>Nf zwgG+aPiPURl#fr&`>1p6Y*?rk!#=fmVZle8uMB&q;F4GxOLIO&bZzo8x7XwZ@0$?w zBYxeqP=0$&c5qx;OyYv-L-?*2!Vm2hr!?&rd2JI=w7W%X(NG|EG_5np29nGFFWTNT zuBmHp8{R{95<-BWs01E}4ATC@`#38>XpdkTVZTu|4O$@Avuro-fabm6biMz4n^df4Htq zeO&I>ciyA@j=pUC*v%iZ8-4-^`efl$&tt=POX<2(J@b-wOY`(tV@swCG6NZrw+VyD z+VR!CW!ZA{vZ;=f_i4R6dPqyNG-VJKV{n8OQ6r)085LvE=feW{*r@z^e3fsJ4*H*w zD8J7OVG-olY1{WoT+FXlI*N+ufb2VYQcMk-1k=Yp@sHH#uzVfkZdT;LFiJ`Ju) zN%?7yRWac!n~yWq`$x=4iv(h!e$Qp@t;81DMhl~U?(!`&b_QNlL_yI`;r(mPD) zXkpWnfDAEcsFwJQz*e@8Xm5U$;)lGFI@J+>o1o`L4k0K`Qyn92D^D6740k{=@XCkT z@8ODi$ON~AYnlT#UpS_4%)#O{&9O)F+mg<8Lu-fKTf>*Q1z8%22i4oP`=gxQad%1;g6?=1wE9g^1Mg=|Ba^z4fE zD>gU^3fopv;eK04&21=*6a3U?La ze@MxXk`8Yo>E@%9pX%`|RtTn>6G?yNdR$!ZL;<4-*DNi;(Ssgxv;;>>apZCzEya-u zM-KOq2}dH1Zo7{}9KC>}pWR0<;3ywQH+oLrgh!+fRtdlj|FcI$9im4lwms2a342vG zuHf!#hbpCkI$7+ryDuGr?qOK3>pC=68h7t|?vM&=9=75EaK8RLx9pIr`~Br?1wm~# zJn-DN_z=*fDv0g;_=jia;mP@Ua+2U(`~Wujp8L{ppQ1^ zu^#*@j{}j%QWMGdANM_Xs&J=!hww5P5ypdS*OJ7RJMmP&Ur$K~*@|Gy2v_g_`K^B( z)K(E4u%VMFBv+d5Y202OzZ}GS-F@?YGmD%y|EdE=@yJme5JabSjXF&F6g8@#>+!>+ zS3!;>Ezibk1bzE!c#4od{$<|=o)y-#I)ZKo(&1d2Mxy_TUi^EPQM5u90u-t4=APg= zq10$o>z%*p;#8Jn&XK-9I4LR}$nwD_pTYV(F77caJ?(efPIwqnt9OuIlLYLnu9b(E zwbMytOt^Kk8NQPd8AUhA2r~mKkHAKF!``I9k(Jt+62*k0Z4N;j)rGu&xV>4r<{pWX zdPx3>Z``!5&O=-|;Vpd;tD2>0W@fI$($~~)qSq1_cid@DClw=*48qZ z!7#ro*xJ*)(sE8(5yf=-t&xp!+3=L&W;+$dZqt^l>>GS13Bmiu2pf0>uxZVX?+U%j z-@O$^{eb-d)_}dF#dcWOZ5P@}J*aR^rexrq*5{HVCmUt{cw@2k#Thy9yr1Iut;45w z6jos|f~pd{*Z2I3fz1|ewrYyYZBLDycK6jI|4xOZ@#{Tz8jy4sbgeqF^kFJrb==l{g7@K0GoT^!~2hRoU@UBw>prNeXnaZ-b-4C(fvGIz7T84 zt@oRbqLkhFE$EtXgo31BRUSud$LjlBb)IzHr5AgI!Mtq_piqB_g-pye=z-`F>N4+b zQv|lwd;1yQ&>3E+2dY-DtN6aZ8~MZF7*rSzACrXw14)oqVXy0N_x&rHj*=NuS=iKF zzn5Zph@DK^5tw8ti20lz?mYq=ct8A7bcQJv3n)NcqE5tGkxXu($QDEaoR(_mtc}-A_<)^;U8$+tTYgk26h2WtCLi2Vmf!^_vK{fUvP~ zqiJqP4yCH`DdFtNz83<0$`9}?tmZY}_Q!Z%Q&(XBK~?aDjdj?UoD>tFpTR#c=rM`6 zZQhlSYrWwWgLzTIZfn5k$zDe(K93yfkxz=1Q_j6+|Lq#Axuo@p z0X5u;G9+zj$r0EWN2qG_Ic%+0B|#;sgw2?`QVUz>N?v)Lv(Kh?AP1*J@c1?1A9BzE z>pvE9RsVYzZN08n@qI+*FCC7;S#@>yO;5b6opVw=b}OL^sb1Hfhwrl;Vr!F$6xr7MHHYB840UyT{$PA|#t^A=L;_Fq*_ zGi=@Wn-|Q$zHbfbq1xMEe+kFeLBFQ1=mbXl3ilHQUG~FtgrSojy#H^;Vt;2eN8_nkiqoXI9CZnl-2?{)o( zbDlFPRu#MnQhg7@t3h3{2{w^ONeOET`N6P6?{=>kJ#BC|p84`96<1_^M_Tb3`ugM{ z$Jo&-3k!T~|1B@uROOT>okTk6Q&@MB_tfJVlE3UD3drLNQS133Y`N<03yD~@g!H}V&*TtV_PaLYF{ecYDWn$dkf#N$^I(SHMi#5qBA(^9s<#G!W$MlCqL|Hso?`5 z-69%ESiWiKaI<89I&R@HB5Mk0tM8eRUMRkpN+-R`2Vc`~WR6m?^47eKPlVnPlVPPc zNCTq=ZK4?xKzKDB2FfWF{k@ggfbs$zaUYlv7F!TT(RbZ;&Re--lLvvBxp-~Iha;{?3pn2rI`U-$6?Xcls`!G`HDJBu z;Jx8*yKYSO3eK5M`EKXBH@^V844tAxS*EZvUjC)ZO14T-0rbM~3sOJ=(MDW=_wofv zTXI3ttp+ZCJ#>0?{tYF!yr}ZDIYzUi-u$D~Hgo3P0}*HM?vIdf^@5i=R~FO;OaRAG z^IiBz>@Y_OnAP39>=0KABfLc@^E z&$UzRuvo%53tS}6FPDQB;hbQe^O z|Dx^mE&3+CnSPso3s=@6nCUm@SLv7O7wFaWDms@I>18;ZNk2m`q2*{V#6#8(wz$)+ z@^U$9jTRPoy%C&T;bzU$4t@j%v+ zm(vj^Qj>A~Qs3(AI2M}?=zZwGT$7mbnn<*U@D+)V+dkFq zK^Ic{-mRpVC2x4>+1;>qoz?DkM*p7Uk!kb@p-OsU|xYzGBh@*uexSxpEDB zu{noX%{lzIXL>g~S0AHdqgzWQ2NQklgfq}D9JWNvaJpA{uc=cSq=pv=*>h|F4#eyv z%Bk9*b*N#t!Z;Yp$6{(=Yc5N_4JehI%tt*;`i!7+(yajmafO~lK_qE;x}A52)_fA1MoXm>1QK#zqRm{{7<#RvDW$iFjEIDM|yNBm39Z^ z!=k(jk-t9jAK&VYFc2XGAp#)|VGP1#gcO8X2#+HyM#w_QMR*=z&;9=X*ATBo*o07u zP=!Fw??QY4;TXbcgmVbwJPBXp|7C<52)`iM5#~6?D37(zaU{S6YK|jGc?iD><$nCi zl^^1lQ|`vEOt}NUtg^OUFQR2dd$)oesZB3V#p+aYmG-6tEz&-vA^faKCci4#IJRa@ zNR-eRi(Zvc;QGg*BG{4)bW0N(#7-dGpKW|z9D_UAO4+z5;b`z}+mxZCPr1ye^GSbG zRZMtgsH``ii3w=bL{gE)4s{lXeg^g%*!^v}37C0vc~s-wA%0bf zA?s})_sG)|#9>%*zj1_fex_z?QlxlIl&~h`Wm_Whi;^)Z$E^v;vt5>UGc4wVI{vlm zKy`DfxpUI)dCILvgVQD1>*E)>IcQ4NUY0h)VpL7flXSWc6OLHeUm0>T;$iPG%d(T7VPUr;{Q=67&XB8;ruYwW zv~66EJbtT|j0~I^LxVoFebYBQn$Hpxfnc11Sc2nC z`%}p~KI>l%i=?CA{@9d?FXtA*3*(;aSbwKTa%#M_F)+sP=-atp!dBb!Q%zKV5|LD=H1m(B;P z#mQ)s|C#2k2c%X=nx#lHF?%7>^xS>p!4(_%66WxKwi4b`{|D?3Tgknm-oIMO5aFbT zwkM;N40C^}c)(q|a}T4HEIuILo*>S1w-QgD4?H;Pu7L^2-2vo}eD#h8yaj%8#c6J=rX=t;QxQ3^ z$^Liw&jX7cB<=t0-1G-AXd5}Ou?|FQ`?IE|KA@-lV3lEa6<=JQDz{&huf}&Jp|!p9 z*SE&u%V61bio>_0<6B6Z!k4J!r$x5o<^^QCD=l09Xvo*k6aOe2b{eD%*vjROZ z>=Z`lL;K~m6OpqwARF2AS8MLOe-h_!Cyx?uRC?Z$*EhMl;SD78t_K_cl!@c>k303B)NortUFiv$W;uaWzp_jtwyfM zsx!du(iRrPAOFx$k;_m3=|i;{9}l9x0I;{t$15rDGClz2u9E z_+OBNlv8p@QIFl1R}vicBA`-ZL{qPY7JQuh$_Mv>3=@G}k$&)PIptSH%D&$feM%7t z+p)iTq}`pf$o*i2SS>G~p}Ft+*8TpF{WMB_D@HMlHl!tUWHeikd@J^2Bt^de97QI; zeu0c5f0k4F!*Z(Ue?u-ECrK_%f8_;veBH0=6ms&*Nj>KD)grWB!I(oP9}On8z4mkx z&b}Z<2mO0yfe!aH#-h=Uch?_yg-^iRryq-*k9&L#fx@<1z7$pVanAsQyoN5L9NxV$ z;g;xv{a3#$>ohg;TH|HxCI_@C%AeDuH$11o*RUVh*RmHx*q33R*_%dcwQImDf#>l1 z)lixJXKK2!u`B(cM|bvP;R)vuKgtnVsMsDZyp}xyxO|=`-1o|0U3O9dc^&2Wun=YV z@(Jfa>@iL_2l-)cfe(^KEcol4SO4REWM$9=?X>CSXhB}Xj;8KhFcUk6ukR_UH#cNw z16@~a=wUR(C#Rsx>!70CuPQrxUH1MJ6uf=P$JC|Wf|Z2J<&W?D1NH4`buxEtPTfal z-uuv5kY~s3BV)hZsaM7cZvih&`8xP2waPIm#?Mlfz@JcWvw%^Ri}ER3BK*DMUu$;S z|Fy>4(f0fd|sYF9bFd^w_cB{H}H}IZh zH4QmF)$4im(MHVQDy+OPhm-x{J?LfOx^u!)>n_)4_uOkgtQ`_V!1sKLtVq|0Y{gsf z&`^%UiXyn*^}72kTfK-!3yDj_IuSNNr~J!_&EVcfTCX?xmp65r6I`zM?ylrkOgM|H@Zml6+4#q$D9pkYr(Q-Ig=2i zVscB|EkdH+fU1DBLqdcN_Z)o%cexEt~3wZ;F=z^zMs&do;)$f5u^mN zFXDK_MTkcteiQL1#IGWrfcPcE6A`aL9E*4r;$Xx%h(i!BN32DhiFhdDrxC{?UW7Ol zF?r8u#Pbl3L;M)x@rY+4jzBCRjz-KQjzRngVm;zXh=(B_hggR=5pfveQHY}u$0CkI zJOc4>#NmiXAPz-532`uDKg5F(`yw8IScBLXu|HzfiOSUco9In>X&SMe4#&z9do7ug z@Re;j^;D?bzMho>3vss)Jd7SWRt#(ePmyJT2>Fb6Dc@_Q6Q-CttxIut)hQW9-@}a_ z8PrC|!>R{vf(?#Q3~Q)^C98*%>#B5OCv5DB({chTfS0g^F1_bU>l*|-`E;~yzAwE) zPOlZ1O1kRTD`gT-dBM_zE$I)Wq8D1*FxDjBM+!`WAlnbSap>6Yxt;|7N%2WKTvoA8 zs*V7TC$tc+Kfr(3t;+VnIv%)DzX7$Miu=@xeVkM0MesXh&S*8*R-A#Vi+0A>$Ei~i zL=Wx&;jWSGACb8{6a0>CwhX*&%|@JC2y3caM~USXL6f-W3W3LlvI%y^(T`Xvah(c( z8^7fU#0ud&?%kR3bH-YN*-^)YL0hN$7WUE8A%EN`k*5l}UOK{-PYk#YZ#HQ6fTE>) zjL}&$!96;6unFv=2|FcOQ>p2)=`8TJir1Z$qT3+f1UJH1{a4a-4YVHme@OGG7i?hG zCSMNRa<0;YbaDUwfB*WG_3g@uw~bxj zUV&}#Y}UsqdQ)4{QExLLEmqc#0g|g|ZX$j!(QVc$_#F|Hg(~!Ag0oO1(dkt^tgcFu zwaw|+5cD2h)guRv#`@r@9xgp9^L@HXQq(`2Ij7_A!0lPD-L>??%nkIMj!hwVsT!4w_kBZaI~Mr!)h__|oY)am7G|57%u8+cL5= zd`rZZ$SuRSTwmE!f?YFrzxcAWAc>AsTXMr2x~ra3UN&^*8m4#VPEUrPAp`p|idR+i z;Z0P4lVh&Z5${S1$56T%!n@LbO1&TXXM7&^#F9QzM+IF2j)YVapI&(I4pDZ-KTR}Z zZxsF@=@Lg)O5k6IRbt7vkVDgueUug+!&{pixrKP|Y`m8*<;xng$a_r`~7AXmQ^~-y`efg0AMnXte=z8|F$eu$MkQ-=~TX-3K=3jT-P4 z>$Nq;hE^%RZAH>&s3E@#KS&T&ng#=na=s7r>LMoxYQVV|>FU9r`GB@KK z9YJt8NWYF-^I`i8fxEjxf8Vvg7cF84cqK2-47D8P>}Kf6CIIb1+eTW3MOv}ps+4y@ z>D04I=X77cudhj|=0DrUd84AT2}l|-34addQ;f2xgVeNNHvRE*AbAaR(0)EvA2Aio zTXIW;n*(4tPytdLEK3k?dOxMYddYkM>m0R^(q+y!uKc+{2|hPk#X2-zvPZZ!doDe8 zz7cD}X?~V)*p8fBNf;jftAD{sQsaME5Bzog4|qsmG~Yl1D>{xB0R=nm+t2Nv)9->A z9y>TmqaWyy$-}HE4w>wdq%ow5boM3S$iLq3)I!gH;+CLO zy!r<2&=d5UQeO5glf6*OOA$@UZuWS3ip}aI`ByOF-$fsBtvIs**0E!Qva2(~U@aDu zp#^dk?9WC%W1+&{7F5D!!5gyJSzv!!tf3RN9WpgRe6w{;_13^#HChX^bu>yU}kD%v&DMq(W9OmWhpNO^%e`CsTqnIU(xG__tflwe9 zQw73X;NSAIz!7V(7)~6FW3L;;cZ!~z27jzYTAis9CH{vM?7-?|;ga!&6{V)gO9P_W z*XBq=M7@n%A?aN*;=1(@o6$u0HTB2&Y#F|Do_M7J9N0RqHo}7aw@i4?FHt7eWa`Jz zQ+zCe8G)Hpj1v+^nfsdZuWL@Lp5Rmv|7yQ=_2)%(4O5m1xpT7R0{mz93O?D>a|Ssy ze&ehqJpm@cNI6cKmm9}fN_qylkB*s-8%J9PIShWoEhpf4=U#)qGRI-|3TQNsz?$Ht zpbpM!s^xeCQ%gnd7i5n#KuZkE(r4)Lqr|ts@B0PNujtmr#$_!Z@|{*6w>{l@vp#{I z)MRyIH~QtJkutpm&)_>2W;@E*i{1Jm{7cZoo+Gu9B&LPDC>DgA=D&1OD!TP?pTOS#A4DbIxKRMC;B+11YYjPWjPg<$?Pb^Gr(y;vkxQIqn z2#dhLK#!X$?&aAVuZh10?&V`zKY#}*dEYFdpljKYo$xSz0{%R*7nPYl8RUEs&M!Q& z4Lawef^Vjwt7w_$d_mV^M>YYG=YO6}IbsGgieKid@X%G)owE^)>Dfo9c;ea2!1@^9 z??pwS9R29=a`6khN?z+J$>znzvnWZ_E8Yr=v?EJwOZC8BLD-Bybkly|VKxhe;s*`1 zQzIjY+Dh#N*zSIKKNW2!Rnj1+5oAj=W9df-BBN46uD=i5oQuGlgr^UJOpg{?Nc^9{ zuI%=`vG&IRmr9Mj+@*eaK#M(u|0`mbi6GFxj}E>PGT{rNhk@R9__GO^*EXkv^QGUz zBu}tFhG*OamI4a|9V(m>gM>w^UipDFW`GU+*eS- z+q%a!{k|UfYI|URe>0;8`+}SBP$7AkavxTjrs1&6hhGM1=g`f6AX3m{%XCC!tYS!}h<&zvaw};N6!iLV_g`tnhoSUiF zQingA^=v_E@T@meKYSKz3!wM>@@(L&*HU5quOH%$*XbuY9=kng1~@)v4gz8ie0uWE zOU0U3QwPo<_myLnT&*YPcbm?G0fm$YDbqnvW8Z=9lHmXB7z$n6Fp7HF4?08W5{+8u zHKF6&fb)AoDC&(+=;08gk1j>Z`e@lQam3K?fNIX2l+NSh$%Q-lLk zwW-sh8#`Z8tI4%f_Zmb#*n{j@5PK0;wKVQTE6|dA(E`-!vGi1%RdQp3$+1VcNUa3| zntJ<2*rR=A{zAH_(FWPQ;2ydBT3q@1Pq6@-6ApnD3l(D#*JNXKVDS`JJvRX6>D$}*vGzM!~F#-6}NRi}C>ZB=y_E*&90b}SO#8K@>t z3-=}j#t7tl=1T$UyRJv>O?DqEr_7ghI39OzlKWT_KVQ<~c+|c5l17VOpw=aXxl2N$ z)}b$aXC+>+CxDrI#!8K#f%%JfJsaA9oV<>AKieWvrYDc7osnJ&jMU(osZSLMI-|@Q z(xw{=KV+*vQXPR`&6G_1s^jTL zys$@wCql(^EfY-_t1NWwS*%D0*NIFPJ4|;s=InxLe`ZN6H++*#A4I<}MQnCX&aGasERZ4J5 z%MNM6Xt0}6@AtTTdf19OQ#vpfezBg%+(&S6H6In#p97;wYBrEvw6pOQ{(@RhFv^89^lS|a>C#ntXR#fzuhnXqA?GbITSKVXI)|h;s@BdWmo3soms9; zz>4I2zvkp9Fi{haGLH;mNa%)ov*0UKLxyfBCODgv%6NmUT38EK31fgFp@%O{IvMY% zk$Lb&hr&COZKKDk^#^$`V6mvhYyvnZ6dGXn#GV3CRZmG|r1D<;~4_ZmEY(u2l_BPXBxC*HRj&{Ip*74(`!V9W+y!;%B9& zYNq6BEx-kp)oC6fxjEB+Z)WJ|{g#zGcDq5NNYKsbu2==WhGN$Jpnb!fr9J9$H|uX7{V zTa-GPla>`VT9)WKXxcjeAm3qqSVw+u)q_1U#WO&0RIuh?v zbCpchC0Jw9WrK%OCI7IomFZfxxW#tPer}oEo)R>t!x%_KdD#^*-L&0K9hYYOPoLCI z>t|qJ$`h%0_C_85dGiaVMq3?!rq#UMj(iPW3YX+JKXgDRk2>Qjsa( z>Y-pt7jGgQiO==Zx`~1YUOd!RrBeot@$!E3WkW2|m2C-cRXQV?Fj(X57U-BS?F_y;N`P#jy$0eP%yb&JGp7fTGe~*T&=g)(+GDXrZF$AW-n>z(F zkPf?$pRIE`1aBsSDW&2QEIq)lW6N~HY4M$qUelCg3a3srNth3<@p0jzT_$It>5|)3 z+!Ip3igWPxfn6KzYyaVuJ3vr=-^ALp*>4+-Qh*j=N~sBG&12~arQ%N*50=BOj2}`F zbkf9BaoZP!GR2J5Gup_iKex$}m{k#gMpYGr0XS?Aoh(6&Pix z=x3}`Odm=4`Y)v``mNIIz;ZG*D4f5^IOm&mLJu<<^JP5N3lj+9*XyR|wO@ks=_Bb? z!>6XL(i^5kVL9&B0RybuYhn*G%pj??m?a(|cfX+n&RyhdCe9h{yXrYb_cyP^ygFUT zeHAhohTcYS-5H?ByB@51j&m+x_TifSRoJ|TGg~<46x;zl>Vw;>xbiQhgF$i6eJRyX z%)#$P!RkQ++I+)isbV?HP<%4{`=RGjC!^Ou*A=fGlZ><4 z1bXTpR#yX7M0IDxi;^ynjFE$ZMx*gsC~00_2=A|_8mJLtg(Tr7&@)$R68KOn!3A)E z!;4mV;l2*!gv`w{{Q-D0Ol_bd-5ergAGoaj2Z1ujR&KV1NOZ0_%rHEGZ?llAzy)7Iz)faz)yIIUzhUeT)7VbM5NUu#r5 zRVubMDVqEnr($YI`W$9G4k#x&eYj&9t;2mYLoNV6tf=GXygK{Od0)YzeRIcez~=gG z^+x_$W0|llb&p9_Gw9ea;!bfIxVz4obz{iRfMDz>8{15S+z2}Z+z2~FhB>Fhq}D(d z&}M?oDQ$2xnBD7V_7dcJJ59Q5ctWrd8PjbQQofFFr~oP-v4(&0NSg^-i{dA2VcDLN zNOmYG+@CQ9cfJC~sZL9U^qSkEbe-8<`o-bm`_iXg8Nd!wbX(Raiocht6EH>r8GwqT z9RD(ZFCFv;mexr~@Mz#`Q-wSj$~%9+`Moso_Iq7XPXJ$u@@L^0_(UMueNgFk0yuAH43l z?yK>X?M~CQF8&C?FB`z$Tm`80U*n}s7 zquqmVydLWeS<|U@wqmDgV{n@(#0KtRQ%vv<(`2yM4D-{sGWHzx9EU*_kLQ`v-`hQJ zr@}vj#38T_GTf8jOUEZ};s-Y?D%mZiLIKW`{CSlqDl<>xT98+HAs^MEsN4f-BzcA{ ztrAw){IiM20$cK|nFm!^d?%T$KFznR>$Iv%z}`)5BEQw_D$MbF!X=>+GjZ! z@8Im$Y)mDCy(n56$84=_R|#tfR%h{AVX}?9XTrmE>xKH+8-2j1rr6?zd33y`p@)J; zeW1XV8r|a^6=n{P+&dBY|B7-deBi!_qd@L1(SsdVT@17{*Ph;i)gy|zvfmnfoCkfA zuu29u&X(wEZ+HMdaDCG+cgJ7#>x2;%l56mN9c+Z6Dn>v)t+~&YU$SwSv;ScmxbGvp zHymqos!SQCE|-99Jg_pVn1dJBw^rCV>v7%GDwWqomJZ)WjhYGen1D9QsZ<{j9Kss- zr>pg_!lDj3m2#RM(-YXHveUBJl5(~$0(z zq8yit!XS6iD`@B#=t<|X8lhtqc3%n>oKp;vUK=FTnjF?u(A^50%+3v%ZyH`r_OWWb zf2L4pY`jcz_BSE2YL(m4^b<3z^y8?gukP-TQ#tiAwBP#6!hRqvn%d?|kw6}#X|5P{ zLtez64r87EI<#$1N)xDW?5x+Fg>QG}8U32|VPypr$-5ozFwMuPA6 zslCW=TI-+Z+$sAaWuzMNTf#A}A{qAPsmO6;6`iCXs~lg$r+rKI0`nz3BmwbSv}hps zaK&HSDe7xG&Cvb>{e8hP^GwG-R{Qp`og1#uVR&B4m29wmVVu*u(Rtk}L%$!ij;l&> zFbuB6TWs*SW^c&T9m~oXJ`up&6kDcIbR7M54q{y~CIXl25@Dkpe zj=ghy6VZN?v%BE~NvzDju=~pY2uT#4>X54^3%4xYuFsL`PZnk6*Ftdz;}>y-Xy!Pp zviOwHfUgRy|JpXZoU6{#uI0JXcQ30d(fiau4Z^-Qu!+GQivjviziV?JS3Iz|9DVbO zyB#F9%d4)7@cU+(O^d}UFr^S36gkG8O?L?+RCHU?UUijsu`l>oeVqoRk%Kgd7IM(x z*cwH}RjCX*{EG&wR7WQW>TSMd-LCO{L_Wp|7;EJ9gtd5-!Ev*QtMuCf&Z|0lgco?V z73Dt8bT90Sl!}^qqiV}$d^d#}q?Js3V52Oa>i%YRKqIB2b;s>;Z?0Q>o}hiw-kK7B zX!A71?@G#ycO@?bRpGmmH~p@pZiw8gf=6)Zy;iBLEwbh%;WL!cI7`%aDtxd|2DTiv z>M87Jfncl&I~FfQLT5ucn$1}`V$NFLWmyJXxPiiAu?AR03v%Y>Y~&@&(wxn_ta&3Z zyP*|>g+FW?`QBCyW?cjApD_Z5Z*#cENfy8*dix9gYQQ1tdf0TwS_^e97TMNy>NTI=~Do2VIkiXV#=#;1Z!3=`-_ zG-J_=d=0`WenR6A;S%iE$qG^3I--iT`-VJl4eEn+=2in*?JSJTd;20Q=~15wZCDfP zGzMWr_1hx5<$()`YPcs1yKQpU*1pJ^5!EXjVg;Qb&l%UiW`mQ{FU6sum5p?UUQbWD zV^x(Ct@GZ=11?-kcy=-8yfT-QT`d=Hh@S`k zl=+*@loKQxFpC-PL>4U)i{Y_yws5;>4sHg{Ph()W%e!|%V0d<0=J&S98hYFeTey&X zGqzk+jdJ56!4pH7(s;d&($86)JYh+dP zce5t0yfNS))j6mLyx~!*Y>PbPs?5GYz0?@+?Gi{gXXWrYrMz!*JNhl~k*CbeS&&oA z%UkhZ{g@>4dcoKwbY7;%!?skTPxw3RnqLVe&&$Bu4L*h@MX7h&RxoeKfRwkjXAtc6 zDaX}9ebQlG0Pd!yEfnSFvf9N;h5d>S7FU$xnWF3*pkg&;VC9rsSO?tvLP6dJ*^8e6 zEt0zPx58lIap0u^^PpFDZGrk-!>W?Zx%M^bYwo}(6MnDAEBpfnwA<_FfWH;Co{7Lf>lkmB{{>`LxjBmNba!>T4;1IZG5vGE^3X(U#X zb6`26bn|hs*l$elA$aFNzp7GhW5F{s3e4<^wrl?>XDeL z$chn_OT-#*P$WPjs;c!C2DF*dHQCApePWYbd3BJ)wo#+hjk+j9R9c5Gb!&bkSbEn2 znbDF%jk;}lHZb30vuW^N;ON=C*u%EKMxX6#EW3=b$wDr>Vc+z5&`+8Av3pROr)_>1 z0St~pc#+Q1GI6TXX0h-ZXZt-jUMJBOuT=(KBmYkwMI?vojJ*oO~<3M+z+q)KDU{V)%2=%a1| znHswEU59gW7DDq8Z-yj|>UQZQLn`SDw=z$(qek-*uzHKc`2cBJu+RHNw$o^}Uz)3^ z>h=-UgM@Ex&JesSyIreclRT~K^Z~Md;$Y|a<7q0=w}L8*5Y&~i;QF1@_oB_W;*4!O z#*Qx6zrboe5o64$n+07phaxLC-E6`8HwItN!CH{HXs78e*X;g3^YKDEuIlZXdF`Rt zdok7pih}Opha(&eecKe*PU!|71QKT$T?VOrxXTrPe_$2#X4rSN9?EJb_5mLq(v%;@ zyq;E6mKn?tbymV~T8xq@DhK z$a4NOUeOxT_M`ac@h5!1jas0n$yM`=>Xu?jH(h(uA_a<{@!SpH?CNa6p_gCE^v!@Q zZ0avoSfBCBLX~#oK-rkz8n%mr+I|qvVRNwe-&$jwzxBUCr$y0GJJ(aw(F?c!u z3I9v8KH)Pb?OTl*YMC$_ICf7lp5YOl*>=vP8kNow$R=Jz+r*yU?$ygT~P zX2|`3>GHCt6|MOd{0y;>_RQH;Uj&b3x+Jj`GBND=PdGJLzkQDX8m~DWGvw4LpH?bz zxG;Gkom7>&0B>0RfC^ytDd)<@egrK60}RUrB9lnwiUlU+7-$e~poi<@PQs?GVy3_x zc;LG7;2(A+^h)3}ZSkO2kvGdBq1seG>tvJYku`k>=?NVzv&eOMCXc*=NS$DN!f6G_ zo)}GHiNJ1A9D&ua8aU7jdTf^~?tvLzCo*-HYs7;&9nr~50QLTKtot6o@05yewkng@ z_?y^ys_T6)-!6b^-VO0Re4oQ~VxJ(@Wkw_w|(saHC{ zUFT4!j|nNgU?T2S-@{t9PF6dh?W|FDeU~^;^3}8aKX3 zvw+#X?kVG~Z+D4{mki{8CHtYer!h}YguODb(vY{!@UTsGAF()EkE0pxqkHi2nATNr zAXcSK$d%~S*(o?<#{Vl&QVtj$cxVwavX{>!h#}!Z!>D->VF3)^paciR>zc*vzi2FBXzc%CpmQiEY*CpbGG>cyi^B zbrHd+#lF8d7Q9!myzN&um`s1zsN!Vo3&*;z5S<#~wV|-NX-|ZI7_8}WjWBJs zxpAZokgZY;d1rpf9s$i@W)6e>DiBn)u(JgZ*8|rDce#bF2y582g0<5`Yq$i~p14Mk za38onIz=_IqDqW#P=;^^mAsKxHp1TL+E}crft>+18F1*JF7?M#vYG63Xmpy?S;qKl zK*Q#u{U4X~2AttG^Fu9^E}$*T7-HGMZ)}7vjis;c!5o-n#GTBXj_^Ug*B+OWaQ6k= zEw@BEsMO7TyEV%gEp%AH1Jp(}7(};?jGM~^^+9hGd|;a#i;5Dk(pz@i$*NrNuoo&UU#hpA9}OC)fpkRAlm; zu_JzzWI!ySiVIQ|PDU*O|Cv#Z30kaC+fx{=G%$UOMAy#(?&hn1dn1T(04miOYLT}t z(H`gRH{5n#&=FPh&_zo^EQ1aF(?cSW{={9Q$5T8d~ z2TER(S%{cTPrR4%bkge!DXu9k}a# z3O&{xyzBamhRv{V)1fac={KO=N@uVe!?A~@Z5|K`q%(Z}s@P$cKX^ z;T7X`og2N=IiBXOGb61nYZ^wyegh;2Fc8@(4M$ilN8cj)V5GPv{|}pVrZ7J{rp0WJ-Oum1^sF?HC<9HJFJ7;@6xXoa- z6AqcC*8z3L>CyaMd%!(gX2Y$JSs=`pG}$-3cI zGNl|JT{WCHrUxltD&1GI-JIU{mBc97HqgBr<9G#@iKih zMrT<~c6LECyD(pQN=4bYOZUBvD)9mz z>r6ozHd!E7pO>IFjGzUt()5fb+e~36+SYl0IaTf_r()G|DiU!`Uw=O^(uJax>vD=k zU9ee0MYGLWVYKdgW=xybqRB{Zs9b3k!LZqwj2&#ULq}Upl{w`rAtj|NmsMm^Vg4DF zD=TtJOqDCoW*mbrK(cn1G+$Gmvj}@Y_Ht%8t!vK2Y96TOYo(_&ZbVy*pFrfyrE(q* z-9njz!KI+4+6b#b_zmnQAKlDLErHEJZO~*G=*bJnC><0gxU2))GLf^}nSE3O`4w162RsU?u&Don1JgkV%$-I5-SDVMy&~aRzy$-xm=ftF- zG*O-jZ<810;#Yw;z-IF88rFXK`IVY^n&eEZ9o1yKX?bCN#@URensX-3E>o{FT?xdw z7iIPZ98IC_~7}+9Gp3R9H$g0#_7G#ms#q)wvvK2_lC@$B!Z736!c9x!% z>SgC-bOJq=9y1TCnicAokk$;%VvQoJ$n<{D^38EwG+o z)a9_&1lI<1S$ReL8!g-U*KRBmiM^$|L*cyumJMr#N`CN-+|cx(V1qGKbCl~)bLNv} z(o_17hJCR7TPHn5Eszp4aRO|HLNdieflS*_%vEthne-$zp&<+i{X18t^wM`8&sc{u z2aGdsghQL;t2jAJz7v!E#~`Ov--z1;EX2d z-w^lPgWTSaZQzc|RD^iva$dQLW+o-!{e$W&?4W-Nx} z`*$lVRy8aVIl;G0EBcF@dA4Qf(8c1Ilgc*m*$Z>Ug{H?%thfmFvHyB#H_JY^2n9h3t0%ALZ#u zpF@hyba3=>V{)&o^NYqfLqzgGvO~K;zxNJ5rFjz{-tqIAy^XU%3x>0>cVe*ahP_jF zeNV07Tg?qk|A^mHcJlQ-b%ql_z^c^=y=o_r(@no0-NirCTX^px&erLxgU{ts@rkJ{ zcCi7iwM*#u+3>BZnD1rbL)QrdgZjhNu!pHO_F3sER1lv(D8-mZ`c?T7v_4vyQa;~> zaSQF4O%*=~T*lLnupOLYl;JZzvV|2xlS8kt@73}l&7B(Ls|mT$%N+`N+0n40n~fv~ zwT4YR$zPqp9ERK(l6&R%nsNsOy|qN>P|M$%@98hU20@c#KF&ky+|+GV1JeV(zJ88t zew|8aila>psngT8QWOOgQ0jZwN0Kn@;W3^phU5}@7H#ok#);TdXdfO2;@ANDWEyNB zmjjE$r=bh^ZZ%`iVDSyu!Lj0r#t}m3je2Q9lhDg{W*YZ4J|fV~AMgPdZF2Dy`n}Ek zyUm~H!d8bv-gV}vG_3Jy`>(PcOJaDlrOx(k*dDFr&?DLi1woKa3$)G*95yQ z^_vF-Ek!$tFa#K?dD=ooQAWIw8<5;{W$mhJ{%$k%9B2QDqoQSfn)yuYqEN^|Qz4IO zq8$p_9D#Ab0X`BYJntv6pZH((7us?z7k4t|NKQ=cW$v-|pJ-tG+#8kbi}Y)GZ=_E} z%lkBgnbw7&G=^Ra4T$K?Ir*V&=}t2#6Ok2;&}uCsCfuCvz}`-+Ek#<}Y(_Qu*( zLNC`@31kdUje(sSwuG=iXL#^UpUq{T!+xym86e{__%13=);Dkn+gh}Wp2YOAFH`ZG zkU}-Tv3XLy7MhB6mNL}kf1xgK{6}3LbJyjDzv}V;>daG@huw8K4YD+MJ*$r!_cX&_ zq|t4koJMRT&x$ExS*{@$xG9>;@QT|7FJ?-oflZ?FqjRDmw<`Ar&Jg~9ypQBqmB9uw zEI`nNk9X+p2Ua9zm-3V)?+ge2V#3jzXMn!q1mPt%i+5e$d`9LMj_?s@Z>=9JyuG3j z9F+1AdSQ@zJ;RLZ5DAXklR%*-($sf}pN>}qcxXzoLh5$SmtZNfuiND-$zU5Kuk>j5 z6;-0wzh5=HLBW*l=R47#UgPA&pT*lk%_BX#CN%R`pb|8VL(=vKx$pgM60%q zw(hD~R*45;ySHQIU03h}l9%(+g8D^bxPzt^n6}vH z5vpzHZ7WX7slg}6zDa_-Mzvinc-Ne@E0jmz-$CR#m;NdlB3Wjz8zm_9>WX*xo|gSQ zbhRo~^S;L)ZfXj9q2gh zCpn6?#er!+bDN#IgviL*$Utf&=j>0q0~^mz-0#wZvkP(<6Id+v2ZnKwEiVFdjMvHa zCLQ>8310@;_n%uCcXDkG>(t5CE<3kuUFN!+l$>hMIyd5M=ES!3E3xK|v76Sd%*t55 zGA?7?%Jn&W$PvOX8EaP-OUDf@CdfKs23oz_)~;+3QyofKi>at#?aF46Xn>kcs(#as98z=#3rwbepPg`0hq_#Zo!Lyt zj4oTaHXU?t{jNihV>>OhF0hR%X2M`6Dg3emdfMLU4PB5oku!vs*KBxAI%A zlNDZS@rO(QT;F+h_xIBXo^qP~S2@N1RZbT*61*ZV;khQgPldY5w~~~Z1!Z;xWp*At z@dV24Q=KXI9Lg*?`>c4HC*^jv@l%vpm2g@p;lFF#BD@0+ub+){%OZFA{n3+=8~9iG z1wJglD<}#2|6%#<2NJ};%g^UO%8&i4{C?~4lpi_cDZe)$AM=#o=KocG6TABR6A(~- z@MRHJt*iI@|7d#`@TRJ?ZFucN&Y?{YV0r-3w1t);loqrqN=TbsPD(kbsHkZ{O%a)b zj*|j2rUkVeWI|gYJwd_4a1z=ABUQ9T5gBEiqy=pOHRwn*QAtA~yDhZ;z0&H;JMa5_ z*Z2L`|6g38$v&*T_FB(c>silpKlcM45i=pl$+oi-9&+91Ubno$IQ+uX7A9ejg#%jj zMPpdkz*MzYDg|~l)Xzju^D`_)-R?tgu5{n?m0)2LN-fNNQb@wj9$Lbrucm{|oVhE; zuodz`88y)VB1yU8dK%a6S*{aa$MqS8YI-(Q-sJw{jbDcDjk;j8K)=z>hn^@!HX~Tu z!nQ!Z220t9Qa*CMjuH-f%qtkAx?)p+7*Wx5UP`J!783 z{wR!|-?RK4y34V>Xq;(;71GUYpKoNh=HtqHZ_yc7>crXfxaQr@%_>}AoDEyW7Q`Vw zv-HiSp$G@$1*CFk6Dk@MTY-}R$8T%kopt_6*p0y&Rl>ug46k;4I!Qj-!xrhXl-t-o zS@#(+&ydxV&_EK-h$+BBjt3rcah?j=ei`Q1GK~L^fJaUOGBO=!<^U#M^+KTyKW0y=YkZLt>^z>T6{m!u?X;M?6rK zW?A`s3)3s>lJv^N*Wx7QlBxoWYTIe}5^+>ydu2EAojDC;uwtir$Asq1@c*gmR6Eq$ zo`O%RO!viNSY72(KhV%kw>7?~*d!h`w=d?f4zutkk1n~`tXWJDug^@7!UGWB3iJ_B z7V)i0x4K%jYlBvTeF@`pJx_Prk7%CL$fwebvZ`(Bt!jsA=VxLL`AnQ){@Lw-J&*5_ z%YZ3T%Xd%&M6jCte3PNGVrP0i2XTMQ4`g?ADGjJ1PO4E zQg~ab^+D;ouo}^z6X$xDDU~j=eUU&*PZOR&EhBD`l$B2AGMV@%7o@L#ASlNXgTKet z2;bQ|9#!okT&u2mMj${e_W}iD@cV2Vzm?U&j?TPhT+;3kS%Ow)S>!WB4b6xrmhGYM zns?cvD_l}2-@*1ugG{fqe|4N<7r`!x>y=*n7_9}YCV4DwV)IT!t#W9$BD5SuFv)g( zV2bPT6rMxNt9zy0vR>(prE$NHQ|uhkJV8hnCL@ogwW-|d zU8>s9`5pB9l+gKd+oW&lK1^OKt2>C?Tw#Y7fhky3JrMjjbiUM<@NKlNL-9MuKi&SiNyXNdewbW zSf(clm=8I|`Oqi{GJ8G}pPx^BTi88jiX2|mzcRk4*&s0Yf*-kmM)TWEOD*Jfm#gVA zodXtY4qfg5&T71-Al2ZnD#1)LnIvIeFmPRdi8M{_dzsDZNp782rtU5ABi8(dx!$Fc zgH7zEF-=dKq!*%fL=THTy@PDM%yoeR@m{%avy{n9K^ZG;587~c@*#LG7X$Z-us!+& z14-@>=a@T?xg&g=W}ASRr-*IFUcT#X@$Ob+uh3+J*XI46EOU;fy6KUa*`tOxjqY7{ zGrZ=I@%^5=&1YJ0jShK50^$3%V=qqcB4eax-W>~z26rh2whjV&YqnW#2F`K(m#z*m zT^HLNjoEBGx$km^_(qXI2-`QT>uwggQfl58vx<24BZX(<>YE%P3yMhZFwo;}o0MF=r{e1BHc0x?WiYBc!&VPmFZo-};wrn}|v>hRtTJrmp&g%4VQi{LBsr@j~N z2;V1lmqN=~fXuUqz#3@)Gv*DK(-L_w!a`)q^FY<#%e%Ff5@XoK_@R0$fKKFxj&i>p zU0~Lmfv15*U9%VUQT8K_AOg7)y8CHeQ9E7!C}kh-k6MH}X)eW$?p=@EE9-jbJa)f3 z0;m$An&M8hj01j(y);6Ig^vwug$BF&u$89K7va59&oHVXQLL9p!@LB!$)cUxjgii$ zP3)x&G5MxpV5%Y5iLZ%@9|O)4Q{+vcIny~t6t)bbo6Rz7jj z-2$>H+-VS6nmUkisVq0EX$G_y4Qjq4RR7BU@ZMK@HMO6b4qgm*BNwD)Q8Snn_DkKh zXt$-7XtY~wsAa%2h2H$x6;U1TjwsBtJklId6M^kZl)H? zv`soJP{9d@c{g(>twBpu8Mq?u*4*7>fOge=VT4;#M{5wVGt9lea6a;K8-xS-^XS^W zy+b^R$eT<{eeQFX7cpvnaaDOBzkK#6D%IKlB)Z$&jBYq)j?H<)YJsUC7sVO6v?r&J zdOSYDFs=KGw|$WO6s*HZ=?=_4YY)x5GRVVppEiqjdL}@6Na8-wU?AL!&vYYW?O9 z^2f+v_5Rap^8>wHSF`!y^Q`_=@u=>O2iA9!qUIGue``hSHN*Hn<*Y?S%Nyp|qb5C& zCHzJFFf&4URXo=ECuCnENuNM=#y{{Eu{H7DSO1iAa|z;L%&8C1a}8$jd-ZW49+u}0 z?+}lnU8Z$g@a-sJ;YVL`_~wc%>|jvJWZa)wFe-iyN>5yid*3j`&Y^$z8e&3!4;r+g zzYPYob@o8;vG+)#(G%_0kO(KAj9TZtDcy4pB_s9+ztU?x(q!EjHsN0Lefh=UKEg3V zISaP=1_m1OdF-cwfqg#@4EzzFVthWvC;95Yz@kRO4KACcYFny}=Rz!@+$GMOZT`p% zukZDeB^$MEv7Fh6?47Wa9a9U^LaDB_;kD(*U>l>+F&T(!Urr*x7}On1L>^HsY^ed{ zP+Lx@)#DoC%!$s6dZZuiY9!aUubi{Fw(i~P*15+xyuEB$WE?X!U5q4J z+w5hTVv>ffO|WrpwuxHCvs2lI_b;wx33z^bmbO%e6!Y;~0Fs)xxR^s#b< z1F6+5k7&z^2Y+jhsw{jVlR1z^J)@Eidof7~I#p&3^az(@ErDb>CV#P%S|ThN5xX>dg~{+lAS>F>{8#VU6k0= zEdgX zHBTN>KrI2Gwhm{39@90HHju(iriVH)|4Tj_`5Yoi2PV(;&X&R7D3$oKqLG%#p1`Sfc58KSHf;iZSe9*=L#yY-(7?p#|oXjAgV`ZhZb&| z;Z>x5D5l$^M5&$4tQ|a(LeV5MP3PP5Ozp0PCYMWNf#%GseZ0acc29STB1890yi=#0 zVfwI*NsL-Tbb0v9D`4EzZWD@9gE!w0%17VjR3mos7syc&a;5e^zaE){YK;>*)-7Wu z*8;s8FZ{5q@YxB^t~W+>TyFd}mhlA_*l=hWmppr7Dw>vruIXv}3Epp@J`(ok|CnF&{=t0TZ~sGX7ImnL+h^1H<7@*HlWOT^)3ng4bg~< zGAc+{m=v}#BHs?{nC|cJNg?X_F4;DP9U6fALwM()5!ml@NA;-lVg=;=wxb6cszs(A zk~tRgl?pD&9d8NrP;UyJFD>xTorhe%nT3|)j3~?-N?);=9ARtoloRE zWSZZ`07=a#kh7aWClIx;l2Pt2V9)K@UIiQJ9|+HYEYKO?PN%YlB*`4|YQ)Nm>>5Oc zDkH29S=kKaYl0tz8N*bWys~6|d!v!vwi#AFX6!z+CmBm7?r}+WF_YQM6UNJ^Q#Jf2PGjTCuHwy?)32M!c^=WlOP|rJuD273Pp86o>Zf)QS`K=rx%1Oh8 z;;LdmjlBpF@?+=Lk|P+MT-99fBA%_pD(+%KsPQjLAhn8U%xw~Py9p8GWNK%9o*S>;!EB|mX6s8f<1KR}QDU^gf^p9$ zy>0?VFHl-CcjO%4pK?hUSlLqQRj`RiH-rPp&0+RLPW!AmUT&h?P|Mn+c3{=;|osKp|0DD+)|~sU#LVANVFNKYPANfL}kigrO{B3 zsAL0HXSL&iNwQ70y`UYDWHNb$!k5b;4;bDBGgU*i_HSTFUV=I&*~8uEACD52TFbF! z(Ak2@q_j@(D#jc$YTG5-WtHd)1zNsA0hx$Ftm+fib1_(R^5B~t&+asNRcYr;n3V)3 z{S{+J2jr|lRe{}GgB)xUNp@Ksvvt@`CTk0LM`VW?#EQ+l5)BIlt&8c3s%F1{IEyM- z1x23gS|!z)9#xg3T3NeakZom9LtU$)(uVw952F8I(P&j}mz00uQ6TO_QjYj2%y!Bh z^th^=srnRbNwk&1owC{oab7N{D$ia~JD9qcjdEd_Q&vTfsi5o~Yuzdp zP>sA$VN`Y)3){dARtoQ&%E{>8{~^mT5UfBR@T~WL{nZ3MwG}trg(T&gb9Z5?IqQAQ zc>gOsqOha5t~h@6qpJP|5$I#;|yEKUMGud#bHF{Kmo+_xn8wlLoD9-nftN@ zjEWgCL;5X83Y8WzSTn;=&CE;&>W2D-ktCEUMcpL)LN7_ma6WE*qIk3wHL<6J>QraF z1Ak?$DA~NL7~|w=gI7)}zv(qT-fA74EO^I|F1R#w=xS`*u3tPoYLbG;H1t)Z;L z>p}eHMTW|1E%6EaBg}*X&&^M7af)Bsh&T}{KV>!t1qpt5S6W&Jo1<7;f9XW*TknrRUd{ug&qwd90wz(Nak$ zTUHC1N)&Rv?AZ7?WYLoR#TeJA0iI!hyah5P)rGmfj$tzIjFbH;S!Wlc-(;>#;R(e5 zbh}ja&CzE%y2lBPsiLFG|D!f2`c2Qie@)n$vuif2xt))F5&IJ=U3hmUp{k$=@Agq4 z)dnAl&voW5V=|q<7`TY~O7wIDUkT~EgWqF)YV~xl zGN1Nxr6_Btgzh}u3w50Ou)S=;?Y!VsNh?K_Z4-K1CG1&E=S`DW`P5D$dRb!fvdPN! zM`P#5u+Cxb`LQaDrJY8^bFpF@bEkUpGp3K)p;5iax>D}TF6&&cbPgoC{&tM3IbOx`3cS}GuUt)Q4yhbJ zCHp&*3HyaF+MHjp!gXjE+DHif_=q_-FxL#pVu>>WDv)RG(9` zjHLYFY{R((H`R?AJzNcwQEmJuP^*uxK8sZ}es$++$LcglG`}P!o2i+OdCQCi_;V-N zW)f+sK#RRNtAM1qobm#;<|DKKos$XXV;V65)~S&(*cm=M5SojDqu_;)3QHRvjgN4$ ze~N5W!Wt(9HyHL4sIdmK??WvN_{VSc>;A-4Y49eLc}j*aIkoFZw*h+H~08!@(Hfvd}yW%@@u zylF2&p1>1%GGA6;ED%Gw_5UAoMQ6yt*_v&o@4(}YzQG$Po}zL^#{qP=r||~K_hlb2 zVTAl&$kk*2gItaNALQ!aWNJB6GY9-gRH{gt^S{Yd`)@J@rnLViQ_uY$%haNfOsNL` zcQQ5X|5B#@Uc9Av&T7T#+xZLmu?7ES7R#rz80xFT|2lcd#z6PIVTmQkqBm$iqVu<8 zq+mrvvh|d8oi!b+tc=csQo+lO;oOnht;T7ckAmkdqq8z*iCp4aCm${*5?BWe@H`bc zAcc^qq#Q4q14)D3Bc%mC{I+W3(`5O%-i7=K@R+Ta4u>yuyU4V@W8EIQLp?_D5<^yY znNiu92z2VNSO3ud>so9SMhTJHMA(K~Iv5?$04@Hbp_(SitRMbcP1#UQ-!i6l{v~D& z>>2CGIPGv~$9dKrR>DHtAF5Y$8_*m+J`_DLAJG%IQs#{rj#c@;URh@Jc9a0gx;XwV z^s-EX)g?V<1az1j>#NpZua)te zjfzg>XQk~Fx|+5Vt=VXSOHUI%#5fhR%LGYb3}TJ;jvNRc7;rXbTY0Mh3m9*Y5DgFfQ$F2bX zuUB3`p9`H#jS-i;zzZ&9S6!nyhH~tM;eO;XqqZ5Uk(HRW^yu4o_Rl~S&?EF5{i``j z-|nO}jxUA1lCEwH1B+pz%1OFZEYU^M*q{vHvG0-Rh%OCUN-Ok1hA2iZ7N{A;vfdR^l-3fN@3#v;Z3r&uR~}Q7M=n zbG`Dh&?Mw1d^5s7Ku#pJt*lS|>R)_6{oxMfB+1-~woMXltqdQB#3a zn#oMl3-Q8_u9<|%;+*?Oju*;Jb#1)kS01*9;y*CXY&#KCKs5mc=bH(OZ%k_?>{3*} z!LtkL+s^bVXU_D>x1^X_&LAavrk3~1)$l7`%Wg(ow#}Y{2tnIhz)wckzwY77 zcY7*&cmuVZ^7mqIe}@6P096UtsOCLj))nbd6j*f~XH zfA$`%rCp5=iY2eC#hxizh#BOEw#hPOUrjoCez+eCKfE0R8Xl&$`;%Q4W@We=A z1z1N2qK9I3ADL+y-v(wFaBnUW)7LH%$Ip@ZUPbKtN!j|w6UMN%%gDCW9o*OReLigQ z%esSa^duLgOa>Qo2fdcs=evW|Jts{w#PN&4V$aSH(-$+HcHv88RJKIYdpGrvL}U~P z`}C*cQWm5ARnkIZrR?Gh8N!Nt@b2drWQ~~?;cU3Bo5sNlv0i+E72iK6t_|J)Y!Bts zS{wO>XpQtEUot)39W?hG6<6y?GS1A$nfV(VC*q7PBVAY^CTqHbc|G{W7RDQp+x@jB zdhLGWFYqVeDDIw)I)RBd;|+0j#%atWm^-H11a1Xd2NrMhyj_;s#>c@pmQa|5HyGD5 zCVxyxG-6Y4z=Lg>o)vm)l=*eXy`TKlbW5TkC z#_pgT?UogauTl%27rqLX+)^PoV8zpJu54@63!em@%au4d3|p&w{<`G`{#Nc><+BTw+S(By>R-*bIiZr_219s}Y?FKDQOFPry{j@6&nRYiQQ^$Aol& zO}G|J=m%S5wbo34N}uh9?rNQfImWyc;kv57QZ<+pE-DhRr485h<8NP49ED^F-u&xUyXJs(g-1bzdv&hidABew_4lE_-2Ej)!V5T+0QCWeH~yBMT_&*gPgKp z#@!$h$QU3?4={*=%K#R6iT3uwYv8-)YHFI_XdGvaY>sk!7td;HWMA%EBgzJ#EqGOyO*&v5!b$tUF!|i9vGlb+`<~rFPU-+!{ zTCfmhUu(YAIL5j=p3b(5z0&bASByJCWM|{ee|o~pk5@Vm0^JHEe&EURzdo_f_;UwV zv)`VWh9@q;6N`=w!~TfiX^2tWitOmvb85lqTlBtk8J}P*&AC_M z@$!AXH>8WG1smc?w_^1kck^lM^!Tw>gYcbomhh&PpL_>)z_O>IUt<23Bo74tHsEgt zZo>R_;}UCzptJ6_dT>=73)_?d5mVVRpm&hfGLD(F(u9ma_d;@{Kf36=N3nGwJp{Ue zxK2E#9(li2CLluE{ke6MHI<+44O@=MBsA8?VxkLHQ6zKQQo6bAP|C4#IF{D`nY9*3SoW5x+I1EV#&m`}yj%tob+#yS$<=H9g3)ZQj? z4NI&tpIo}znl50abjR{WuL^Y!Q_Y5_m8n1msXnHP6B?|yiSi=o&<)V0ZLFQ7E_af& z)lQ~*2E1P5guiJAf(fC>Y08Q**DE)zEH;BbpHae(V;Nh#UF6*=cDpET<#rI3t3p08 zS++OKG{dXnZorlybz{#ZfmS$!t?ESU@?8q`3~!j+MJ@Gd&&N1Sah(fCkp$vfA2ufj z`c=jjBbZ?3ifxoR|1;Bz?SDk(TH=1s+Hd9WOl8pnrjgn7zVABVOEQ5EQn|jxAnI*Q z#ynGIJ8Y0{F#N*8$7*TKj>;4<^>xxFn9r(v3!?`SGqjS%)J-E*GsLmD3uH%sxN|tlc};nlKjBc z{^W!dB@hQ}S{Ne=7E$+U#QrUEgJ{y3s*ad}U?wog7o3zC`)iMQOewqq4=!K0GF0P> zx9Xcymc7;Z&cBT~)&F+H-H8!L=eua(v$E0#MVhp8QyH74ZIPr+baIJmcVmyVl}VQL zs;@riojo2tt!r;@ic+pNa#<;J3+Aro7^zrP&iNw1+=+!vyGC0B!8 z13_LJ)m*QQ=ewlJPjfDqn9i;GOCEOLY0;cu5a>F5j}VPj_=#S&`ZU!z#{C`K0|_X7 zSMOkHAEPwObTTo^`Hg6`i8&JYHB(Hx+YFs$T1+Sp%XD0Q{3dGJKY^ys$qa-ruCuk^lmTeK8dY< zOI$Rm%yYL8@Vtd~RpLY2H8=1AtX((rKMDNqe`r_lZ|%DB1Zl}ZyNbucgxniN3~fiW z>O8EliIPx!xV%w^nE2$GlIx{^NC(3hm4JtCf}JKM;5skzlin1S%$uT`p1>y2{(^7AH#LiQrHed0`7=7hCH5gZ}hD_ zCh8{@n95pE+R3G9&7DhiB#GXA)WZu+kfqgMN=QNIoud$8B@u)`{yh5L#>P(qmV71HlfL%+RUA{w?Io39vIJvLmXHlyA-adFg;oiFZwhvbWlSLW;84k@ zU8lvARdj6}=9EJEnL7f(cY3lG(5D>fxhsaB++dnv3v|%mTT#j(v?<;rcbKrgK`L;_ z#b+0ODhvc$dbw&mVccD=hJ0GuU0}vGD2bjs@EX{2b($H<=86O8ishm(*aA` z=^IZer4>t|!%c8&9LybmZOVglP$qM35k^v_H5-0h;WM)_}VvL#Vf zp{$^FA@m96J^yx&6T1HGm(Npr4s!rLbe)k24dSAC8^FY27Yr+8l{^@XG4F$=?ytao z4BUYX=iKYyes6?zfU~nZB#`mwOkk6H_nX4oGR3g9e+H*sCNh*jx}2Hdl;=`@hD8I3 z;TJwKp}A{d8s}hl-R3-jZ?l9EF4kAd%(|Z-zU7ZO;LLB-7m{&H;6LH3_T~cTMr4k` z{0j8?Eazk1wl&`a=Y^b)zV-Z)GG*FbofI=k&&u#L4QyJkV$W%RSTV5)wTM(JQx0`x z_Cy|JbcO(zOL~=lnSo4vgI=qC1M`OM;kn)&c@13(nbnx*lc{!iXeplN-9ou%j9~Z7 zi+|hoeEeCb{(frDfnJAt?)M-92Uuy8IGgPyT?}+ylJ>4M_WnQS)Z+d~yt}+bFRb*) z4kd12!0F3u=N(^)%ku-l=6*)d<;xuD%`_`eSFo^OX3uL(DC8a2sQ#nZ=W7IgNr@)~ zyvDF`6zVs01>12A<(7Kku-BuyHZbsBU|?VuKD58KH6+y8kQ1{?I|4Hu^a6WVa9TgI zWQOM5!D!nQj14_vB#Qg!ak_>jI^50rs!`Rmtx-=YtgfXFaRM=pl8qyQTH7~2MEc(& zjij3F!-xK>C8HeJ%VPbbcelIx$`olN@Tx7o3H#DszJHYeO1Qzl*Y>1$%L2u@C%vC9 zw4P5979@2AXF$(<&lQf@FMMBDFn1t4G-Efp!uN&d@~tyMvsxfHp+CH~6m$8TnEjeb zSFos`J}J*dCKCViCCoG>vOOGcdQwpOY`lDOiqIAONB>yt=IOWAe#9JwzP*QUjGDjm zFUFryPFL`Ca7}M+l~!VJFB|C|RW-WyE78_Uw#N0aKWVDMd^`uasEF%fexlhVB5Js8 zS8`yzLZpz~JrK+r2)A3CrPUQCwNtY{;=nz4-gLxYu>Bll-ynozbe(fzw}dqSxq#hV zlHeIt%j!l|FL|mIalqhM=pv~vb>|-ruf5AN3hacBY4{|Y_=F+*DL-tG*47L06&fyS zGme}U7p7nFjH;GpUequ;diR2-zV?jXg?=%UiLHU%n4QX6M>((u(6G;~)mDPRa)(W~ zi=L~nVOKzCdDFC)5aG20=Qh|z^fBGCG&qBYU7>L59bwchELFa*Jv?6eToj*Jxm9%Ib@so4AbYlisMtQ&d}3)uXD&xJ}Q| zI;p^VY-?rv)cs+;D-7mZCEd-I+Q6@%lJ9)7chgOhIBc8zzO!9&xpaF#F0Fd9x2)$W zL0M@NcKbe*#t2M?V!NzdUM(Bf(UK=*e1%;dD|JM|Q_uXA)2q5U!piq5y0Lo=o1D$! zSagwsmEXf;$g?&yY0t^hKB7@o9k+?dO`jRo%ioxeeKK%TU1}w{{gMl%P?SIzz4Kd- zH0i}Fm`$qla>%%(ud0oTuW;Y9C_ydHl=iBD-woq;Hw^$=Ou)6kcGtvS$)07BdLxpU zUbYLhxv`T^`nl7_yO z;DD7ten7S#c`?fs2lUYNB6s!&b?70gQz@xO{MDSm!s+K>$x9JV1&q*O6NTf*4!#r~ z7=rP)<>qtGv9QSkuedF`PEsj%D5_*N+;$$BN!+2H2Gd?mg*cI%l#M!H0VXaX@XWG` zo`}}dfv1;6?*!Hd8AKi+Q>@QhO9*1U*o}S6!85l#rlE{Dj~M4`R<3OI9psu;UR$XJ z$Kw%a)Xu2tDHgwFJ9NgFuU?@nE{Z=G!+;L%HmN(~MVTh`Jwyg_uys#j-9SB0^fqro zerCGszas22{pgC?iTG&U^X5$R5p%-}8$Ckcg@{DVZ1f#Z2bLlW({bpPR7U@Z40ZRL zu7sGYiT`^rDM}=gKB=halQKpj(?9;|S7KiMlf4_RMLU*_BDd3?J!!2Lr36u*i2MYO z2}eExD`}KtqbN<^i2WR6X+^XT!$qN2qzaWe?JI>(3O;2LcE%LesTF0=iwt0FJ&Wu` z$Vudm7nx~TWnJe?JuYyfhn)td`;ZCokMb+7XvgP6HDauvgT)(V7O5;}z^>0phMB(- z=hR<-PYozT^?K7Yof7Lf>4bBoF;N2N-q}OrM8;mMHSH8KbAla(q`6BT{`aP$ul98* zILws3cCaV`HL}oPz_C7_`43q~8t` zHZTbt%vDFU%9VMMeeMpAD zYm{|9ky^gst4n0 zxLvRIg&_yVFGVEf6X!N~?j&8&vTb6RjmeVi*d|7};RVYbw-#Q&XTX9B?=d?e*}3eG z+mQR?D*hi~pX+6TrcuLpCxeeok$lMXdYhy=!u@42{Cn{6Dd6LiyQLY^fT>czPAEqi zVPg*)?-l;s$z=Il?5W+%9_+-aU!C7o z1+U7#?X+z+N^jdQAHa$|>M>)7%YULPc*nas z;ogux?F~z044L?gYrOCal>@|-W7IpHV)QCu#k9sXzvCJmxrk)aC@>qA+&ZPHJpNt*x`sxLH1-uu|M&qMh z5CA@so~y+V0$mk+(JWKC2V#xglfR9)0pc{EEP@ zh4a=U^D+=7$Idqpy99QkZic{z(k6-#u@=TYt})hP(6aW3k!41mRbd5Ccm>gc!k~YMvcofx$8FjQTbL1-RKYA1n^?qrU>Odgqh3)@4m&&26 zHs*ih`Sf`yc8*k|f2~0xlnEmoE-|{ma7`>B`rN?N40vL~z9G@@gq*(dOawlo)-BqE zNDdmI!8)G@dY?&>XS@quU+g7|u+t%U5!4O=h*p5U4DP zwQR&rxC7Cv*OAkKQD!VNAW9!BHPE}qy4DHD#U_nh7jYz22;$7~+#}17L)C5o%OU;S z^sE8b{^8ldW5VMOTcs?gaQoYjWxB6pQi7LyLjrR(n~$@Xg{ zcf#{@E}`kVVVbrjyIcDE4$&O}axFhEafm659N%;jl%1)d;4aM1{l`m~L-F z4@F1N9(sXwYbI?rC3VUz^{~8shDgsFP9d-=boRxigJ*~T=h=wUffrZeTt=ly)~T_S z;m-EZou+Qv?`chuO)HQ1mz5kB&uSPyOCpeOyR?Z$)Ub)l#%%a5k&P?efL8nd7L9Es zX=9~etzrNHVE-fGIqxWp^WosZ|kkeJW&j8~<{4-IvqDJ)e z+V4WSJCNbCg&9kI#!Q6Z|Kx+{$XM z#vZ{|r-@4PK4L&reVlGO`2Q^MUu}wbUmQX9nb$FMOg{6oX5ycS$aP% zB>N#bllSJ{C8&H#36-5MoO`b11a$eQ0s?eZ&7JR>6rJ~2HlcNU5tsf__mV^O*!7O* zpQHY_$dX?ro7%EeC8f|Z7}cX!o)3+zM?*5d7cvjtr$ZfLCCLpuHSd$aDliE1z~*Qg zE(lT1KkEt+;jvqYzd{ntu!NVPPg22lu9IKrsSAnOnvJ$uC>CgTd^6_Lww%|;pDV(>GB=2&Z$tv-KTyaZ`TUk68NEm|*00)X9D(uqSLV2Qd=hPsZSYYV{N=Xe;t3r4AOZK0dBFLQFx;)d z-FW)9I*b+I8RqCn>I1m@4qW;5Wz-H=KY%CAcZc_Gxyd`g`|S^1VUOV0`xn zOZ#a%zSMo-?ZNT?QujaKzVQ9K0yFmgD+VDVG-vb&e;2xHT6gE$+ws&{zEJr%mu-(x4Cobf#!2MNx>nW{gSJyh=Lx0ijt zKzPe@TzvN=Z6DgM=A4gW(K_kB^PIq(%7$v2Hgx^_Z_oej4HAalU>1D?Ff%xvJ8>=| zbbZv&xv4m(#n^tSyZ&vkkhffDm5>g6uyX2t1wnN#KQS2k>SM@QuVc zsg#=nbB$EePu*C!stjlBMiY)t;ywu!XH)!*w#8wb>SXo5TD%=bJSF{Z=iF}FBnD3| z(_nXt=kW>L{;ps>Y~#?&2pM<9)hd#D4pDfQq3v%@Px1cnd#V0_@xoVBuS*wzdD8f) z?+JRN)Ac24u7e-g4qq8bITN~L{SPVRBkVArPDiZ`cq%#N88?&fT90=v&hdjUIb_XG zX$)PxsadW+=t-QZ#ks3NZNEwn??B4yPH1JT?y~4sKm&|;%2Q-H;>#P&bSm}8s=kl< z(5T;|D|q7Oul3$YOVgzbTZuo|huTqZh%NL4l6D3R+bUXrJ8jh!w`Kyj#Z1BVteH_CNKJ+dlUYA@{hM!f4^!Bf)>k6V1U ztma$o$D%IL4F5FWngFCE<7Ro_3>vtt(CW+-OL)1MV)uZ7M0^Yb@3<-r2+;{ZL9~v- zeiBh)h!9k_zSkuScYv!HDD7t6aR6D25z(M;^6d<#d%fwx3_MqV6W-4Rtv=2D!#W-#P2g|zD9~T!PQ--p5A8|!_9)>p~x}F2( z4Y(@&&lf3&j0M5ClJPN~lCL6k-+usc}kGt6nozWu}r2{GeCrT*21kF2CiDIbPCDUA@dS!4KT zEw!RdS1U?@4B^e#)0k^TX;CDv%dQm_np#nApuLDaxEgX>0A`f!uo587iBBQ{IL3kU z;C<7H648aN{%>tmm-N%4GOReotpSaK_vK2NB(9S3C-dbFU}~UuraMHL28j07xn7w7 zgu715J48~1IOt^#QE7JI$=JCpcZkyTNY;V6&GJf>h=wJo!<<<(7QKqb(E=BrPRchU z=7PqXaZ(#H+f(VL){0gea|gGbj2FO6%GWDl%Z?R!%_3|3$P3n;)@LmQh;k-hnGKZi zINrArtcibYr(B5>pzYKApwYG`guOHh(S5-rL!?Yh`yu2cD6lejK#E&m4X(B0o$nvK|C=_jFem&H z{CoceSXb${GyQ9azJ1iM9s2e`Kbi0Wkgf7AmAnj$nNgw>4SdcxyX9K&$hgb3>H%1b;wPHt*AHyh^b)>UBw)KtoTmE zQL)P@uiIR&YPNq3YR@&|m?UvFVkXMtXoOXT5&f6;Xot!-o7qS-*i9~Mr#q}AwEq;_ zMNR#xwf76##mLs+TAe#Jp3ZJ_ff)cs82KNvu~U(2w0xsr@G6(w)rfsIG(Sy*0sG|5 zCR5wvrfHbv!+@n$*B7kutWi&Xx;TO}XM*iD1@VO7g zbWt7bmtfzmqaLu|ytR-p(iIykej5D9ekIPIpLcgu5CX8KJw`1 z2sbk|+&NriRbN21knLeStTu_8jMv&V3F#Pz5x1DBu%3kCEz(1ME5CJlsF%50CqlMe z#KJC|Z2>3)?P`@T3bp3R%3|1laU=)_mfV@@`-)62FB|B}B5NE>&wuH5G9xPaU z0Vv7HR@>NruBCghZKA}k;kSu=gAc1alfSnZu@5uV*@(1B8n+sJ8im`S6KxZf4Kux* z!iOUyb&jd9gLkYqg4F^{lyr`j;~Pnx7m^*43OyEc=+Nkcg_XnVqS7nCcFx6ZGOlgY zsZU}4{VZnz^68TBL?^#(nEOXL7`@fGz3Kon`FZ3a8bfpK0;v^kh;&|76R>@QVfWgb zO+|~fK#UBIwnuM%HzX?$-h9Es*GZ}o2*8H?aJq2%R-!ydH^qcLW zZyfL?RNMF^n1!5=@>ZsXtFHf#Gikq_Df2w(jWOI7Vglok35eG0jPumBvkdA?kQ1ae zx0j&al(pKAJq{hy>YKiyXUc9O%g@mKIymzC`~Em26Fq(G&{f@i;~=-V!i0|y6(k!QKGA>-fU7L-m{Oyptr1!24E~iR zzqd?`qj*V~tqD3ANoB^3?%i;m>qM5;BGNU#p?^bNxURPi^Dau1n_R;wZopGv3(2wBa`*d7fkceL5m5DKj0t3O+G4GM=BMIt=CQM1Ih~W?S9R2%&onIzp-% z2ipmYBpW|oMn_J|NOI<5;t>>$N8=|}BJm(S1R>bQrcPbn+ zOp1<=p_PI$h@shE6<~f^V&Xan->$8<$uj@Qo5qwjsUr=#Nqnnxn{3CO!t|ywh+D#% zs|Po&8%+A0F_^)a$uW4Fd1xUTA#HC8IKRZ4R%ZMKb6FPVvID(uA)artAg#MkknNJx zP%cl0Dc(svTZz~e+$~g#T%Hn4I?Ft$@5&9PpIqpnacqauVK6=Dl!s=-vff|s{MIFR z3|d8LZRra63vx5l)pMCgSv4J*6oE-b<8)~6o&%dtsxR%8iAyeOnOo@@*YV9DhSjwuQGKOcun?ou^jTQC}x=W z4z5b!o2{5>lC`A^iiE+d4~MQk0&8j}_=9GvI!qHOcbEU9fVFNMgQ)i?DnFk=ddAO( zcLDjaIY-kq;QKTQ@Er`TgqwRlGx<7Bf$xR6Q!zCOd(TbrhmCkHzYX}M!Pxe}KKVnB z*~8qKBOErCb#@K4|8qSh9%-rsdp*W4m8+sh#E%X|-PWfgBJFxy@Len5C}Phg0^;|9izefv5#h_|SXc%q zw)5S_W5Bs>F)|%nbT>Tb#agq1d2!JQGrs9qV0SOUz7k?CjQcmKd%EGd|#j&paFVOUU{I5>k#&I^HRig$KyftHJfRm>RcvcC(bC!MikgCu(cr zsD_Wo8Ok#M^}fOVu3FgCK*r|W$eyl;_b#~R5k#>_J6R!rx z-js#@2K)Ycon)XsdYWYcaoV6;Q8sc3=RNX}y=#$>4y>v_nB6C@k_sP-7M7%b;sV~B z{TMaV2@%ZI;7g%eP;?lz{?97;Ms$35TzG3X{_eSnI8AlK8XB!>@6EXk-gK?|YH&Lc z_)=uwru^^nitn1Q24BMw#QA{#U0(4ze!qN6Znrh3-$Ct8YG;NpGgRBvq5CvL_mQ+t zpbN2!Zoo=q=XYEU+WXFMpp+8J#mSHarTg(xf$!s9_SH##UAOS_r2*G=0ia6%P6ftFd1?)HK!(gpa z@d>a7aYSztHB;XK>P2xt10%GttVUziO2-)o{c(2436Hi1u2K=b|*? z4*ie1(kFcGqWVCNQ??x?C~d-h$nz>kZ+G?56_&(+Z%|Z`4B+e@6xC}V6m@fe^;VGy zKf7k&EzkD)fa0Zfz7-q=MzQA^c;W{=v`r2EpKV_^R`(Ft`db6v+jbfchS*A}2j*+rgM!jMyoZ_S z)V@NGW6v_r>s)C-6dL7+>AJK}v=;nLT)U^q<13_f;wr8Nm!VEJ)M+oR6SSh&FDdq; zHsvfNUJo?BKX`wS#6DP?-SD=}P^Dm0UJY&@s?QD^?PcQs(zZtc!m{?Pa8fvq+|>^W z-=cl427lQ$ldrvsH5z@_O7!<3w>2{=S2!cMgmPgjbgkcY+lm$lD^2no z{;NFGsg}{bHelJ=j0!|R5k1Xs$HQC5Is8GsM^OW>PTHf$Jwd|nbwU%h1;MJQMkZ|O zXlW&VZol}daq(B7mJhb|oNA(Pu+sGx{apZIJ+_J(vtYWlBvIjl>38UibZB* z%>zdLG1OO&E7{O{E_7j3Fb|3R#L>MaeeEXAgJ)e*U{2$05(i&{b}ii}uHJ*TW&ef< zU=}@2lCB0%hv%io;H%(Q>EnQ$@CTFo6tzEI;gS@US?Ftj za3p?TzH-4dSpMgoB$=h`gGGO9V-gg5Rj_~(J=sRv!6x!Gs27_prh&(?v`>L~=|?BO z3oMdT_BD|)caNMZaJyJvi6p_2g_8ZfIU@h;L1WPMK5BS1NO}|pkfpi8h+P4(Wec>- zheSmc+BWr|>qB6q(~l)0FA6W{C{yjEO-8OmGqh46ukw6ZBDp>2OarGB_yWt3W2pN7 zq3m72qN>*T;kD<^Fv6gy2xP-WS4kOf)UDP7H|Vtr{*W zHlrctj1A?;^h3~gESe^g#|Gww>c%H@Hv)0<{@~(HS z^{#il7qy`Qn%7Jby&>|2?lp;dTF}5|>PWz^wgSus5*l4s$!CbN^j(*sbu9`_Q9oe7 zQDjJ82_!&m_`znuytsWiG)2MQqhE>kS@6xTE8`mJH)A7t4|o~P%A8Ogn)2Hfs(oG7 zmGv$Om<^lZYC}0@H*HU^b4U+U1g>RJGiv|z&sf*~*b|5?1l>V>zsXY8!=nWWcW-p7 zBZ1T>ZV*-xQ?KSYW@S-?BldSM3j-Oa_Ihfim3nxi^h!4TA2A1>Le6EqfDz=rnW7ND zdDTN`kbu|SN7Jw!=^m7>Ip47yGH#^n(VI_bn;`7%ya!~DR{h}&haO!QS_GM+h;*vc zjeEN~$OUCrJY@+&X;dN<^81Y8D72`kjf+XM9AcNHSe>jLj7uzJ78PP$hszAu&K~Ot zx&3Ut_fL_$$X6D8zus>%3BFh7XPh3FRL2B!ke-+Ll3<)G;5{r1w;|AxOy}U^=sfDH zwY}pzu@3tB($#N>4#1|og7|45Gona`e(h6hu{-_H%@jj>Im8D2u(Vv*`%q8ADXOCf zco{SkYd7+O7Js*w{*J9*r+|*A?)$n=eZyE-!&OZ<4#`m8r-Q}U6|x1@68I4nMKaOt z^(O>L|5H>0K;BpL`w9~9XU)&in$6u=EK@ka@*=w*viK6;*^nm~%5KD6ZQ94Q9r0*K zIofdzey*oOw~KQIpcQ4uU3fXUWh0}4u>(AZ@kx8I5B;Imc2()%-ry!N=>g!awfm}(*@-G4&g)7=*ZR!CR}L7rSSp{A zb*+DkX|9B&KAebrD37}cRv{?Yxy|`zcO_(bU}@qM%|KQK0KoVA^)?;T;ap+wJ*^aF%)ezwJLih7{ZiqZSZ zIBDI}!L`*B*xDQBr+%~zT6<7`zg|`}#cQsKmh%74CmF+9jSgpV)!%(GdBP_X#{VJp z$#l-}mro|#gOM&yr)=lc50BxAb4~ygK!4%QPmI$TX3}I6JGxE1)xjBBS>rh)tY&aJ z@O0h)7muWqF)4L>+F~9u&+lm)|NWk}2?zJIO>F#%BPGW;a^g#lY$f4yu_gq)2JEi0 zw)cvTan@E^gF9yqsp9@n&a8HFmy`(J2F_jiLUlT~+11H4Bc|DVEoTUwS)IU@x$3!( zX>7NXxS_fY`nDu!VD1 zy;XpIz#q25_lRj7+4|_ApNo#djF5Dl@MvCvr|DUm&f~0dg?9|P!gnSCkGegUNE)y3 zcOn-IC*8~vGCH8C;3=H)eSfh;@shBp2QrmB#QPc(9qA&ZQb$ z|7)vVoRAJ%?N-=oKMRgBlMv=`XT*l@T_zjW8|ZnM(svXSBwN3NmVO=X*2rOCfZCJ2 z$yX?gFz;0wJM@N>BWJa43An)5s4wtU21Vq^)GzGf0UxJk#9n}Zs0+Nc?gH%1U*K!i z;~f8bptaoOS9{Cb8*rK%>&Sl$-jd%<-iXmB>oQ``w2^h=9H|dv?1G~=`FY-JW5+v& z;ofsBbZTdMQ%QvJ4iEe$4wvkkpbz?D6haI^jJ7|f7xrBtQh>9Rra$KXcdTgPq!E&_V z+Asrq0n}J@!rIsq31b|e_xwm{v!KTMo4gfiYh%YaO8evL5m(V4m)9S60dZyhahv+% zP9e_RANO8=+)>1t`r}sj$L&X4dVgGMPjt$Ol)k!Q`yk6Dq`2uOzW}Mx2`A7t+Qu=C zfBczCVQ~xDj2sjG%rV9>O-NN+28Cog-#u(dfgb|M$`Hpt0W;5Gw1;CH&j7BOoy!m3 z_2CRn zbi%WaMLfJMkXfDYPX3WU6c1V;iUj-zdjg|LGlUrq8SWZ_6P6_$gw65|yhfXrxPkZ6 zZh%ELv?5&R7@1wQ7~es{Ljwru97D2y<^$n9)Y_50Avus40h`p5Pb~q=Y3YU?ygy-t zJ4i*ygQQI7rE+KuT2*KV3G@u9rBbS@3y68v;m-4mRhnlVu6)K)`jn%U+X#IV;mw4% zXvgDTIxf@j#`nrt`t0n@VLdUcfQ1gO*AMt;Mms4kNSc4-t?_Yupqh#Lk*|tBggqr= z#Y-K%jJ2a{_T#0`EhPaMv3SOivEoPGqzi@Y-$BgFLIY-X{Ez%a_-|Nm_z`UgFeDj1 zHTbeFSU2HgLVIGV37!tuBX2>)1-`Tl{wC0ZP1Xy1j+yF19$5b)v^{Z)q+H?XRUKvL zvcItU;XTVQz?-gnvk$KnbYG6yp|pT{?zNcsEx+xb5^Mk7b(;Q!6B@qcpomix9q-V$(Bi2y0B zs9TZ@oAGz&#<|&Dm;}gaHUNTqwX+(j#X~l00Y*?-(FzJ z$kRf7gV~-~hftrYTb9E-vl%=ZI?Ft*;~h&L_F?mcYfh2U0=(V z!=IaLb6?qXor^To*~;0)skMmz!SL3Pd4gL z;~r05r^TssM%ZuY&zC4))eKtX%$ID`$Xc}bkfsQw%eo~sNvVSp3SaE2kB-w@e~uF! zrL4cz^L>9k+T+2r9?ggP_yl=f1Zt6mwbWl?wf(htozbF}OSG2wziL^QU;^B3@+6y# zr1i7|a#EI$?dy>Ya!sHsVW0m=uL}BWqr1>%lfTfj?fNX>gta5fWJuirPxZAp;TEyX zNW>bJ&7>toC%hZ00Zy%X5S?N;9zef}FVX+Kz#3+r2ENeN z^u!KEd;Y{1p*0ihp0wqq{18Lj1^kpm&#x- zIuySJ?Fi6H8k18$fe%%>=OR|8Nl|y1R=71$duYAR(I=v!6yYZzwOXO;>m3PesBg6) zCwAKawX1L+aAI-Tt*EGQ_!2f8{(H{M&UX*z+DMs{+}$H3KO@k09#0OT8R0TQ4#Haq zsR*wlyo@jd;dz8ugb;*Jc0zBD{`ZM0goNRf_Tv93@h69-$JU7-7=_ z8HryaBl`I=@^hSwm=Fq=$;b?Z1+U1+JcNO1GNMLMA!t%%fJC9892m37`X>GtRA8Sh zi@@7H&0_q|F|)jzR%UmT%)}GEa)?{Ims=9{@b3+-30@I)Lui86xNq90xwisxwehk* ztlpr|gG?9rs0vB9)PcF9+X`+4c6Bw*exX&>VyskUpgUkMv1=21BIyFJEyI4V0SzC& znC(ft06zj~31-}0!x6oy<960JSSyGNs158&y<>mmCzM@cBaGO$u?p8}A1sjtH&hSP zcxrmyKCy@DeFeH)2PHHyQGVH!M1p zZES4;f1+j0dvBabo{%i~rjG0r)Mr^M}~wV3wB z2Rxrw79Y2! z@i(I%sFgD4S}?A!$4PEb%H^9b^$Oz+T4ot2k0jJoYsNQ*8LW%_`nzIynh#2;(5ru< zu+lj;Y{Zx-LJe;iS`Fa|z*N{?deay9t^KrRf2su-dw(P4rv@8!9leVdc=y30J}#mO z_hjJ7|F%)r(X{a@PJEDp{agF5#Q8SuUq)|XuEH|Pz7K*Ee~0u_c*QY3wro4kHp3-o z>Sugd*#(q_6QtYSgstu3>sh)uQtZU{4y0B9yRGeK>}LiPsueH&rV9kVQ+t}GD= zN7r;2bRGZQ2=6IsQ4p-`#&6`qwU|Td8#s*|1BJ0yjn=E%F(!M}D-&<SV2sHA^D0gKpmyDRP``GwJ`oDTAQQ&oDW0#UQ-{G_TrmT zE$v%h%hx2GN864jAqOo@+l9AH@t>oGfJgi`eMr+W#C%XLLOEp9&z-8^ZX>V zx>g4`=xERJ4N5`#bSOm|k<^LzQr&qzs<|R5DiN*Jp>603t6iOl9_uPM(9uANDB+Mg z7nB7Z;ek11w9et4qYTmAQ{{lZMtj~hg>S@*9^!Mqtl2od88IQE$}~$A$GY_c!ZN z0*Or_VbGddA7#9UouwA-sZ^^1kkX9XClhRo+{1aHnQGiaii8=)nYX}iADI&SX_qde ztV@^vahGl-I8cDeMYV!cZ?Sgxt{)DqKj{4V&FZuwtw#OWg59xsR;O-d9}NzRDC9ZE z*KL+AYvv}lj}|v|yu3ldu5h?A&pC8$ls4&$XK(`c+5iizrer^ym$09DS~s=c!CHPN zT@!S%dJ3xv5Os?kSU2xZ*3%Q!rZ`i_)ohfYW=88eskRt#)K$Pj>xFL?U{tJH zv{zZhot@F_jXF^NZ!5@`OsHjmTw2;ckMbp!& zGPjK^%JJUQ_R%^(ZN_45!y=w*@s7uHC3jod324yTgDKBEl>}t9kyK!UmIt@Q(>l@N z)|;_nqQkY9o=PV=&EHcjCf~H6Lj`=o!Z1Mx6yH-JQzBL z$$n?yv5TJ9f8@O)a$0Y_S8l)c9<3oguBsY0aXHXnbOMb+Y*8D-sbecsIvk#WOn%-9t>{e@WZ-i z=|~Q<0RuvAwyCzFkBpN$Q(VjKKe&#&bHd5lmsv61AKG&CHPwK3E3vyNSn%`deF72w z;&ph$5@JTsfv&@O9-8S^_#5*S=C}x>1pXJ`!gJrQtKxnIp91rR=NTzFe5$7p8lzCeNJzs zGlk-bskIrn-~1lIiQ^Uh?zrmv%gX864N4KS{Z8@H7D_YH`siAEx&^Cix{9vhWzRWg z3Z*pKOmVf<^qWz)Jwn)~AKS*xxY<_g!*jP>JGoz6Dg2&kkTvdUJBQy^;rE1wJ#A-v zu;vKAXqq*&lRG2)(!l3%t@f|IM%-mhf6g%kQn<9uwH-u6Ao&a)WvKY41;Y)vlY7Az zxzh>o`~}b!HQImQ!g`&KH}VO6!@RC(-gOIoP~go}cnkfGPxea&&)#!3=KiWr?6+2- z{W?v^#p=&lSbTA#u#zB8qjLe93y5p+jZhqWd{UNlUeFw(2wQ4~3j- zrqlCK)e0}aKraU8Pl>(ZO=jGyYQ`_pD=Pjh?1mMsVMb@(7afW+9!)9LTbtUAl?lFV zq~RXuw~OkPsp&@8LQ17AqJ0N7qOLF=HBe}N$$NrQ8)5*8_@d0 z2brKu=b?iV^p+U``a9#E;n!$}PZARB7N~x^@ zEm#_V4FC5E6d~<{rocT`{6* zUy2o4et(@kPa>Aw+hz(*y^1sBzAgI=DMnb#DLcl8nQ_i({ypJ$BP_6*H}FGnzVWJn z_Ng@`ao+}Q=cI&)A`K){V9L{9lpP+T?C1IdPWOPdLyYdsXVdQ8E`y! z*=fi{(=%IDH9R)D90$A-ZtP$7e?lu3(4wcoze7t4Xic#Gc^WKRViUnW`>L-6ibKG_ z=!6BBNki^Xx|U*LmVN?e(2oa@Lvy6d{7>9e8~|O>3R;PA>(aeh3#t4gc4kb>{c{Ig zagTB4K&`N5O>%VpL1!*4qu2S>*L^El-)x=aX!$cO8eXM8`8EgjF?|J>it{pBpHosm+b!+&bU_ED>?&%Q~O86ydM}?sJ@eM$G9K!FGo$W0_WYb z;Ka3W;LK|Vwpi(C858#dlP^{PQ!0Lko-5tw{=fZ!-*x&t{6GDH-*whM=<^58A6uUq za9o-?Idy(3q%LtYKG|5uJ4Q&18&l@s)()~;s?V`+M6sdA<;}zD;FU|&XdDD9KcDEG zO;eXimmSs*`RRP>M27e?huBi;OQ0+hx$DdU!1~ zz-E2dE(7Bi?jUyRr)on5s{-Y@^1*iJtN^o-OO=Iw` zs#%JY$@ivgl&fYB7{0-CJR6=+q`%5HC!d68z26PVaacRVHPy+GX7;o;`y5QTlMum9 za(v0j%(7zTaYln@(a2z?X;gqLANox@T?(j$BU$k|{+1*c^_G|@=S+Ff#KNYuL6k2x z%Zs)QQ{>4Cr6rSx7wN@yiei_-Y(3NDQliM07c2KG3MIM9JXf;>IwAS`H?BxZB}G^H zJL3#SmGKH)QV7IYvvs5c@2y75^j-dCpd2u!9Swrkh=p@&9l3*#?a6=+4z6yycNB|cqCP>U9 zY=ZjsBcekY&RFi3OL=Ba4{TpMj<%(c1< z(Aod3n}GjU>Znzl|I~dezk8MVVO8+F$V)umfi)~e)CBxjN&H|xkhmlonShJfBUN2% zGA{CW24Cdwj=0D>@YI?w@=*vHgg}HKt^1{Ycif5ANGQ~rvYBVaNKj=IrV~k=v8UE#zoa-G8W<6O$cXf?*CDBty}G0GvI}tu&Mt} zY!3e8>nMC%(`=j7Nv1&BEgkn|Z=$slv>hoD1eIhj&KYYPdwbK5LH4>G!h*(x+Wq>5 zYO9@*T49}WhfiGV?KKDWgX%s>{n|n_nnXk5Zz(x<3}m-ncKPF!5A>DQWCSzfGuTS+ z`=4O6=-ZH+$~J01b!Z>|hB~O+(EHFS&{>~ihYs{8WpY2U!#{OvSdbX@i4NHn0n&VN z$u7*1J*KJP{(NK-7oN0>l;@zK^j^bxNChzdOt(w-tWMLLBu|pR08+k_92@V>X0zA@ zcyrv96kEVm4oI!4hE>Ihka?`W5-WoY6WPrazZmP%t$MzC*pk$Vu#}={mcf&C5_a*N z-l=hu>coY!+3z5=ulK<{t!x(T9cWSF0-6@W_UYNf(qlKheI{L>F zPX+i)XY6tpMLuzCG*Jr3+VLNgq6nk33Nyfs!D-C&ChVOzyPDyhz$wq40Ljlujtcv9 z_*R;LH?O;{CGNu)VvHbV9eoBjktMP65 zkEZE}QwSrp3FVn^n~Kr5yY9y5tG>0%32sg>N*ePVlumsK?MI!|u8DXTc=c`zF*YtG zM`OM1QsumA#jf-4UgRbxI~P>byAAlmhUM4&Jrf5mLcU(->YnSc0rE@z*Q~S{7G;Yd z)1Eg6a?uNswxb7nrn_Xj{gM|af1cc@t2nDQXcUDO1w0b9gA3Ljc zib4ZR(^SrWZ#5v4p{H7x%~W%H39xpBqgSzr-3MD&8WTJjibtj5;l)2`~yJb#!?iic2gi3qsu{#g}@Dj6lB0`7#sbp0c(U>BCC8R* zA%$^cmymnknsCR&nmTGssy$5U+LTW~sZj5=lPYqTFX15AFx-K7lEg~TSjjBRD zFmXW7fFgP6$9i>L85>{(x7^@0X#wx$E6QhfEZ{x2CE8Sl(_t^D*U3L78h3$Sm;x^@ zQ`qsqiwo$hXcu})q^0PGNVXg2g?LIEp=a@cf=-O~h<1zjBzPSfhTjIpUcVCO^wn#I zO;=0pSKmrjPvKqFYt%P~y)uOXN)s`K5Sp?=)UjlS63_S*D_vIC#Yw&8f8*DqhJl`Uc_Ga7UEZ9*NRU- zO^8>`H^9!>s!O;VnAMs{G7Rt%x99r8o)*|+mfj6?v&Z>Ly5(n|9;gPLz|Znz-Hf94 znbJXN|493i{5M&Kv+fLI9`RocxhH7kY+@1?>x{oG9<^jWfei;{TJ=SHEdvX|s*~`@ z_vvE#dkWbE{8X?pK?7kQJMcyoWdAikC8V6h9q~!vYuFfBlV8dSpQDXVt-#1ZcH`a;O9k>&;d7?7|u3`EoBF>(B2F%shLP!Q1=Zo3RX%Z zA@Ocz#{X_)o&|MYfiD%t6ne_t;^ks@RlXhz4>2xE`%mj|>$wt8e~a3jp4FPFd`mrD zJ%^sY%8taAW3)t1a;^P6fu_%n(n@0nrz1Ix|4?cbBlQ{W}C;2*r)IV$vZfbuXoag8tYITCksW>*eO|%tU`K^?j zT+3-fdDOk9&CRC*a^_CX=FM=YLucO|=sNfA*wA2y7dQFtAlC`plo$52$zKWNq+1_z zwXSN^e(J7hD--A> z3IYp86pSnwRS;AVTo6(aS`bz+x*)t@Oo6uGgSH6e*n+W+>kr}613GQQQJYgD*j%j1 zDcUT{r8jMr*(K8>;oD@4<5o{(p@>Syz;^7;X&I2WKJ^gxNm=dD0$8()a-=~EhaAnD zJ^_-;QI5s%Ye^ilvOnto{hIK5YWBAN-}8mvG1;5@f4|rZiE0TXsslF)WqM70-|PQ9M)>WM{Z9YyQNr&**%|%6pQdHYQTC`cLfHuq zb(S}$j}>~gwr6ZfGQ2L_%1Rf~<~}r8-k2UHq%G?SD@+a|_s(Tep81(9{cx8M=9+6j zSpHHW?{g1nABSfrPY)3C&+Q2)PR5O7RaUZJKyDbU*EY2U;8q4FSxrqxZ2)d=l<;l> zJjFS_hvLO4?t=FRZ2{i%h4Kaq<+W$cnI0&V7upkuw(0I|$x8MQ%TP9EU7fO@#_zSIj52g9Tdap9r zwMo>?biguw8m!W%ZR-{dzcTc!yp)QF5^E z-aM2Nk~dmNKaTX!>7hb;{o_!;Om{B^FbK^ZC8Y0%|1sjo%?g|zEaa(v94x@qSAc8z z`sbVb=FU&6q~t>c6T;^RWe9}`+Yo5nErb~eu?Uk8vv($6xemMcmTvLB>qAf5jlNWhb*}oeX~Fpv z*QY)J#c26dz(yzZ0d$UW>u0EjiOi3F)4XM+qad&y*Z6DnC<5zl-$urUwb>lE*>9$m~XXQ2tsW z{RYxArjHiVJ0FcMG-2enn@s+r^WGHFFCu-_^l%~l)}!ze6Rzxmx3 zCh)>-X4JjgbQH%4B~F2rvJvJOSSGB#|Ked1FfxC-jRaTU|HonCKPqpoZ4|UTtM41| zD=6<(o4Vb^oCF1)$&AijZ1ZS0iG*JwZQcjALG30Y{37AzrM7|XCb95KJSIQg7Ko9E zae9_}wgd=owl8eA2bkyH4lV{BE&v{SiMmCOP2FVMSq1m&X1Qd{4RuQ~|F~ zu7La?p5b`r;pv8FF`nETQgQ^(OL%^VXE~mi@%#|apYVJG&!6#p3D0ZOF&od8#c=ZxTj-U&nolOZ!aG zz&-noI^zu=dEUQ0+;h*sDv(#UqLjb}p+~mTK0~Q&7b}7sVv#D(rO3qsnqQ7PFjC^- zQ93xk4xH;xJUsK5ql!{!h>~|L9z}XJvFpUeu^-#BJ@KtLz#(Ql3Oq|yxu1A@=DC#2 zwG1qstR7r~TrkSI*Pb?>{J;m5ea#Nqajs+jf<0~D6cd~y>EgDtd18Bwimp~KWkDkFGB~~x zal6{Brd=)yU}0mB@q^VVH=N&Lc^Y!)dNPHl9$mIV55%Qpy#@Ig=naefVNc5q(tz`L z$t3uoW}xHjtBA@$uGsyJ`~+Pi9|b3uLaiD_(Ks`>)KpK>@pRUD{b*XN8){WuLalGI zSzbfTs8vGk4$)dSb&Di>?Z2i!sksw14=K#IAUC7;Ld`{Pj- z%n#%4)ysZ)M1eytJ0dDnKff`J$BV&y9yW0Gs0rN;Q>N#*Eg4t(xKE{3Yq@B#DLAXhQ?c`1> zD*_pjMQ?I(Gm>#beiAYbLpb$!@R`#=y@^KWw>mo>q4ZSj1nWAvrGm_W&JmFn#A=F& zf2;HT$4#Kdpt`h*w!kpHWMKZpk}J0*?L+al1;VqnXd{vsopk?uQQhX1Dw@anWC@7;BA z;1ByV{+Z#0cqUq0iZg>YRcD6CuPb*m;n%968*_sJ9XcdORh$`CfO7*AI0xrx5}0OD zmS)0ZcV?L4y320wA|ZD$a)Y)Rn*&aunHdMW4X)t3D#0^D?O6fx1DFo!ZP+} z(A8W5t`62l<+nINpMl3BQG4&CzwUeglEn6PnA~GJ-#(l<_VST`g;=gp$kbL-h#b7( zQtZ831n*s<@Q@oq{{Rb7P%U6F@Tjs_=wHZF*Hyb;j`RMBayN$*4lRX6TY)v(moMV{-Z| zo4oLOcF?Z3Ste$^5f7orP+r{T?0Mi-=u_0@JkZ_6Sp}*% zwh1fafl4k_`1M>J=7rkANs8sgo0iWrRzRNPGVl_*TCF^nQryXXTTEBE;Km`wJocHR z6oV@`#erLv3Ea0zGGZN9n~HOGh=EfoH*#g(evlAKfP|q7&P_Nkt@GlgWFj~bLA(NQ z%(z4Ft@sme(3s~7V{g>^gT|W+4cGXy^5RFa^NdvM48Gtrc_(nj@@6zV_iN}N_Ga7Z z7lzXR%f5T*`xnn}dtbTPW_|X(*lk!T{}nre`~2BQ+}UTbLwNu5Vb&w;5YdoVdglW7 z>DD0b(^npG=U(u{iS6`}gt)Nk*>iW!Wg74#tY;TcEo)0CWx^&wnA`?X&$Ua}c}Q z_+MC~ZF5FHkQY5w=mY4-JeXYcU!GXKbE(t@xbs=Q#lKOWvT5n?Av@2s_lkeu-!%`< zhqR5syTrRRUGKf;DKFr=+jaKiVan}_oiE3_|;Hi8nyf->qMY!#yax zNmV=}&aF;alI-WZE58rlBvR;UMmzL>pf!xLaB{k07gCGq?1N+8|SOcg$9PwWqaSM zu%N6CtHP`-c`1CBE4`sR>2FklW`los4VB)TP7z}S?U=J)HYxR0i1JoMQL$d$l;rLLyE*G&xht!T#%PO(elB`-FndjM`R z(AI9kdN!+b$4cK4_!!ecHxapVI7oJ?;9<=As;!S7wNNKKt^e$M!mhz;?B6|0aV}4V zUK5__2=N2uM5C4yZ-mS4a@f>&%l85gbD0hOgr`p`QzwP&=us$dPx(3 z^!ZuSV0KhqGO*+;Q}T#W+XsM>(mAHmRR#LD7j>Q%d7;>^Y-$r=)LSSMpwI@ryyMG{z(g~Z`F-Ido;~sl;VFrAEKPqcgT_g^T|H=gSvO-@?($mtbeE!Zapc$f#w%E% zwD7~D93FeQ9-fK5rgUvgXZeBtwhENczYoy%7EbMTe)6@jQ>L-qm> zCjF8PZFf#PJOJnEn9ga3=?+LnLZ5Se)ClX$St)!h^f|j_x{2&REs>66k96>iqyaB5 z9~_cDvM9glZWi;5qCH9>4sWdoM|jIk{vvcikG>cc$jAOGR?;nt@B4P=|9pE>`1Z!% zzJ;6(b|%Q?rrvBTQ_2gmlPb@1Wy)@+0;l%O&WGh_TY83IRpCNbDR^R`j;W7jls7z5 zv4g_?`9t#E)EZ!!X+WM&!P~+Pbl3Ud@qj`~S>AQ_P#fD8N(s%Wi-Zl(S#`jbS3z5u znHb=SFSI?!Ou9Z7H_NbIhePIT8J@6T#4J0eFU0*{$aU-n&E;_;FT+>atLLzKy=cLW z=lw(7vKFcR<-rVMkvr`?Xd(DNyQ}Dybsg%KE_SoeAHwjWH2U?%j7wM*6y4IEL)~t- zW%l`lH^7w-qh%ugt-o+hUV>TWQfSPMT_1ZKHtGY-@?xK&0fl#+A3yGUzStXC`cxPw zSJ-(YVbty}rHe;o4G)YgknJM=u70x|@6DBJ$o3xR;qK}8iw8nmL>c8r0)}h8zh9I{ z3VNKMcEdwTBKCH_v-evPAu+5RuA%WeyK##ExEnd54B~>}va>rxMtvB9LQxvF@B*>JKcN5BwU8btC<= zZqaX(*$-j+vUdWgcJl(4^G61lU3Of+-R&awpRr89l(>+~)Ox@Wc4Y=U_q|dEA3MIh zn7o|fSxxLF*otLf+ZCq-Gfp!uS$YrnG~En4w*#8gqv3BR*riDwE^qS27XxWqc725Apbk{k&r}y^W_Ti%8Au;!-eDU8F z@99yRJ#Aj8Yhyv%58vJ9vW4m|Y~VI-QMGu!80Gh`Sjc+3oSy36qA)+-GH-aG%mcDU z!*Yk_dgV$WHF){Nan=X^`e+@xM>3&~yN?G8UXy;{4Q0Jf{}UA6JEpYy%1Fmh8EmIY z0@uS*55>oCAF7Yb0yglkYpIn~*q}Wo{xj_a(xiV&Qy(LN*%eF(W`sZe_TWQNg&N;X zIOYqhKb~{IqlGH)VDMzIkY0dg=dd>BU2bake{?;7DiNU-_x)e96 zQhTh#?WtT)8TMa{X28dVCJHx&uu<-(Bh!(;W^AE;^mPyy25~ddh*=-+L4v2t z!MvYUYR^I$Ig)7^u`H?5ttK7S)z!lKu%q(*BOe|io>b1j#Z%TTzAwT) z_-H6J-yHXb%I%^!iQRvu*shr@vlIO(eOUEUmiqZVf;TtzCEt0&rrKpP$57EQ7XEz) zc9Ge$T63eKs!LgFKP0wwo6dn+NOc`=ikQp$ktgp{ct6dPcN(AV)fc0#H1kXKzLq*z zB{a#UR~0Go{8-&@UOIlPc2i2$tCJlH@%njcp-gq9B85Q874j0ufjj;F9P0iY-x_E0 zW64>s$@rGm^{tVypAp3y&w9-@(BCB3r4hH<1iE^#Q#Poz?oDv0(5g+|q_r8Ao7I&P zw(>zxgaZDdD<6#XQ=ja0F0F?BG$B5)Ki*%6e+BUhSbA0?h*@ft*~nbsSNmPz(>$`h zw&>6DMnCmWSNP=FH>s}mtB+!RA4tf0K7BF?I?JzSTp9;@X&Io;99HPF(Y(LgNVRnlXy{6*aTl-BZRacJY`2*C@Y!T^Xx-TrbNPt) z1Au3QCJb=QAyZzR;!ue6^U_gj#eE1i3X%OZg>}4LfHevGFMM6)5dEuqhgv*k-hZeZCG7dv z@!Et972=fLdR3#DkMKX2LPB)#SjuQdB-Zd+rq2pDF`D^G@D-NV4=`3f2=Sm69*cS^ zAB1^i!BT0jGruPraxJ%01e->#${ROfc``yoDbK?u=6Mp1k`k^qeVoEPcRQhyU#*1? zvh=4PzRypIYlZFqrO3GmmMy~~Na)PE<41m7(Exn<5211xdNKN7z0pv>8xu+R>yRy+ z3$7Qbm<+oqRKBa%Ik%U7Nxy&%d>=!Ooz}VsmX91I`-O z*nVAc{0Q1H=Raf)A7MRq{C0}j_N2TSXcuI1`pe3Jy+3UNXQOqWuFn!xH*_E-L$pCW zwBd~G5PGBaUw6EL&oQigm2s%0t?`#B%4wIqA9m5Xi8 z&R$0{cF2H@{Agw)O658l4Ux#N5l*0feG!(ET~C}O4|X6}<17=ilg!3@OAKuiS9BZ*4>>cLFJ zOh(Mn4-mt2e6TWkpG{5WRgHd2*BcwGof3M z6w+!Ozx3HjfRu)>HIUKnaV>=aqBN{Fv>ek*Ojq8!rFaCuDUutMF*RzQT{HHfAHhXHs`$_7f7s5 z<;Q6(DKET+HHl1{Pg{^}8K3f`1# z>1e;1eTv;$@vVG%HE9oYm9$TDJpl=3ru-k(O!*O(z8_&{R#)=FPgnAq(+BXI#(}O) zr|+l075@(JNpY%cSXca&7K-(r#nd00+T_)5TiX57tk#Q4@VT2Md)&{tK|1&ASocfr z=QQjyM$h7K!zVnk{)3;Sex09WfMt$&aLhF;y&L#RV-I*2PW3a&*j%j4Yb;m=A|fI4 z40$+%7>_7NOwcLJIiQI0;sYT9o3e|-I zRB7&Pwt%0+1X-A(+*VijX@Uh1Kx<{D1+Da-D{{T+-L8Ws)xmbPtF-Yz`(*Jz@V;Ez zHLifcO1VQqP9LEsvvN}U#(~5 z4u!1aNS=i$(P5TgWIPBges`K|&drb4$H{)`i_`hroLP_8vt`S%1Fb@<5{TVJfiswi zj9FDzF0^o`*!8Ny?kfHcHbBrS+^WWqTHG9{fL*k%p$;!_2+K{tXn6>vb0JSI)}Y2| zi4{{nrRDmIVFPTs(I2*EGsX_;BmIM@on$E)CqXX!)#Wuzow`5b;ccJcL(qCvAwg4ec-E=kK52(tmb zR`xnKJw#hQMlF-~Q6d_(7knm?gyo+uXOLbDZ3X0$zmF&F(D&q9R6#pw?49>-*Ow^A{Mv)_KqFUiwEwI{3?poz#CFxXrX;w(IV(Y7_;H&XuWZe zLnL(t?c_O!IdB#Fn1xfN>@|x9S|7b*{g+0t!ro@gGJYo)HBf8Q>8CW1QVx^#I-?#* zS@%n-DEFEj{rfOSEom3^I!lmp2XvtWI%EUje~kDQu*%Y>+0XQ%D+*Q$8`(Za@c|}} z@sonfMDk&4>|U#LFQ@C{byLkQxM-RR*qgjoNp{I+ya zVGX}`NGGgJuyVMor8yp4aZ>8_4E;!*zpEB14A8e+_}hJ zVriCGBR} zUcQj*<%`jZX$tpCh*8!9C(=}aw4Cbx^l1Q%r5Zq*ukoA0@X0d*8bCySoaVaF_g`zA zV94R`%sx)X9CEm3J}|j~c$#4|b{%U$BadnNUwg0{$yw{V@_4jRHl8<5v!zbulVGuLSLW4bOde!v5s9n=qQC2y|5Q5a=jtsRmP)_Kh0c-G5PE z1pN*ATcoMslhKYew8Mxt8JO+p5eYpGtLPP&{S~m^UTLFqP-eVuAtSWxFDZ~&=+?3y zr`%3xb%x;0FXc15jlkP4#u0eabl)~;*#zYC>0X>LBI`5L;;h@I5r*_rJjxN{{1WK* z`Wyb(*K6Q;K8FuvXu1CnWp4r(RoVUz-)H8`0*o*$Dj@320Lo%HEGjNf4kH{iO$W6n zN-IFkL9I~h$+U71H8U#~7Zy`2dva${OEhClGd1fsqgIHTlL~`SJp-cWu+ICvXR!45 z_j&*C`{8q#bMABR=U%S+x~}haT@u=q!?`A&>AWO#!8h_Lp$((VVSvt32Yc6)4d2Cv zoq}L+@<(8GXiC44P^?eTAa4|g8YcZ3kZ|(^w z>x@&pH3z;jrdm^M33$$?d38vkFP_9CaGnm6!xL<#{!3g7co zCJ_$}dQb1u$=W&+4zB|7xB2G;ujXViGveuFY0?X(wkshvce*5+Zx_;S(sy8g;UpTn+h!x3o6G-iHvKk+EvMxVn6W^e=Gyt za1OXSar2W3v2B+VczdXhQUERw`kvqi<4iK}O~}g!d9_*#_pVJfb_iy|eD3l{%f@O+Y|!5K#G@+W{t`YVx}S<#b>v&jvU0x8OfjVfKfGvRl^SMgtdTWU+s!Od5{e;$Mz>ZMn^_ z>yhU9LyoL48?d6&d>e6Y@-KGf99eAn&hGE>-NLF3@LdvTybZth{>5@vT}WiT)qgMY zDKx-mx%+K;k4JBQK#E!;FtdD}63FWt!2^(NAKK>Bv)eU}l?v#P-JxZCM`<|VTBr{} zO64c!C<-M-Vo6XR68(~8S_q@@-9muZ~Q?R2g|RGd}B`^SB|&fYfIJU)L~q? z@*~kNSYnM!Dy5}l=%+2LJc46JHS*RTrfMCTD6l@U#-sYSTDHwJb#TXrcflQI4I>pV%XeY#W&wwcyh#-(Y1v?X5DCVr$=`fV_ZW=-9#D z;w02!cuzpF3EZdq&qI4;7y%0`ms%JCw1A34%yoHD%CIo;T1x=5LS|d0b6%Uz0rhZ# zi^hCC!ij96_)7hP%aV_ok&n&VlgwY9C5*^U}NvVV!-pi!(K>;v958Prw4N1o;QrW(xARMz{BM<<`Jo zcFIZ<0-R!^EJm$`@iZeL-Te%WWvUPrl z#3I30GH?=%=Uq+%xLCLOo%od%-{#AlY-yyiPmywKaG*~RTQEE`)_w-3ZY$@ttpGlp z*ph(Vxq%T}G!Qs`-I6?(OS4BC`|ggyToS{Q2@pm$VAe4{DNl{*R^&w(qZbg2+Th^G zOtyf2w|_UtRqikBpQq@hKcySiRDhdahLs`Pr(><~Eo?B53d%hRupDj=&>n72Q0_5` zf!u`SCudK$3?#{cWn0Apu3C$3oce$!dhv8}O zaQhhL0%KaBcpydkZA@NPyTeE{9xWop{Nxj`3SDM2gD&2Bu^9APvB2aV69&ahYGNWM zCwpAzr^>fuY^wG6Mw{V9e!X>-{d}`b^kg!%@R%d(d+AeS26&h!g$;R^VA1kZ^xHb- zBy4x$NqZ6Z;4GS>93f5cv2BiAqyS!zdL-Y;G0mPH3T{WTuJs4gb0J&w&bHa*LCbKi z0I!`0%z!IZxz%EBa&okViG2=QAWxNpI~;{YLX}|0zU67*R-g^?78VvVZu4`7YZbgo-G+G#h?0fOo__jN1jYd6y(uNfkI$> z#6{2Hdk(q)T^2$dA`fsqJYVd1ul*wTV#oWPFLtc&pxSr8SW7}EB_Oxbd~Y6roF;D; zywG|?Ua|*s7oa02Dr#ED0u9qZ z>?hBBMQJKw0_@jEECt>ERV;i#npVF;PnQ1R!W|J6rSz@5ZPaq>QYv1N-W|QTkpBBodpBA>_ z-DL1UrFVxQ7q0VX;k^E|umNv2PA9`+;D0y+HCo%f!>9xOcpH3>jI7VnD{-n_R=Jz| z57BYVh;u=yi1S+aoUH3X-wAA<%9xS0M(?-??>FJMd1Lpy3?26ysH59_W;gO%P@e&M zsC!-}^&EGbPwOV?)53W_$_aGSlGG>D`Km(riaMV~M?@m}pe%MyCD*#d7e1a+Pq+Rn zW(=p?yDKG!^T{i#B%uSrr7Y%r3aJO7+t692eEZvcG=3xTJG9%U$lpbOByh^&M*cTo z&V2Gz@Nk6vGw%#{(>{7Z0xW^S#&donKeMv}ezp2olIdI1Zs5_e|94vL&(r6MTJAEu zPx|bkl61_Z0?a)V>zccZI($CP;rdi2!zbR~?!iM2=(t9 z25sC3lLCItK;NKc^w-t_Dj+F`3j<H8VUt+gKDcyFi*Ip}}TvxvrJ|BCxXhp4KM#vPBi%2dS7sr33^ad!S6alC*m_9*cz zC3$JEIXJaTmKRv*fj#?^D$Ox?Pi~frBn9%V%!tqQ+g$n=kdm9cK2~g*?JO!(E?#f=s` z)2T;{vgy)NS#eyuC&4b_IYQ{CW%11wW>H}SFY6MO_y&dx{gl2%EcB)o<}&?_+GO}( zv~m48imATM-|kctNwMqJcS=eUjD1Q)u&^lEcp`9gW-jdcI>$F#|FplydBd`7nO<5N zF9emvwFeRG|D9CxF-!A*Ae$GLASPV!}%Ko^%tw3oocW&#JgK|M>3cd@s5|8`L+Vu(oe@77D`p$Kjg zBq`I|;SUhKbOT{!nFwDZ1v2JqSo5Hi=E3$M@b>(rUZ|x{1??M!Ga`AlsPudAt0K|E zgL}l>x2U7*OgIGly{-bjSuKz@U{0%G1*w4QR8DlwPadaAo#Pu5DOC@AU%&9;Wg#v5 zSWs4VehnC!(H7_!*fxaZw}VC)dW@S2 zufx-ta=c&XL=Khcq@c9JV3X;rFwn%J>=;PvEzw;~{|sqOf91Q*A|J7qhRDWO@s&?eT?dxt zIPFd3RhEz5$w&K>kz+oz56-?x^F)6QOM#!~X-yks?sDGu+E3nv-51jc1+4TO;BsI~ zr_@EKt)pvi>_-&@zQESLlJp7-s(Pt~Qa%e|J?Ok2IF@_P8XNhyyI_%sBf~SS2%Wy$ z*aW^M}jDrQufQEfb;hs`a~-P(Hi zUHOOQ#ANQ?YtriidoZQdI2D?3pQf}fA9Y>mDp-+(HyKQ!lIu+BNNP`#fcHi;-?h&F z*LSUR-#L9R`;G5f7eW6(K6`=?s5lJ2+xXq;ZFwC&>u|Tv!*bjm_7!XSK+o1NA0u>j zxRHsKXanOm>3^#QUronuPvG2E4|;c)#h6v_YAoJ+Bn8N4%!NO#^bI(RizDca%Xsje z&8meg?@i~%NjaQk5A`jD^|#%f?t)cPM0XR$A|HC*eq0DviK5!A$Av-KfatsU4be`x z*R%M2{eNnY3mWr_AzwAW>vJ37D%f!AnRe^KaUswapb~F~6~~+KZWB|jud9uKr$BZO z_%ogCb_N`l^CB{Q8%>iv%^~rmdD8cuonpwO#h&6$Sr_h?Dq18mS@Q&7xHgEthu7)z ze)KDrAP>mnhp%jVryOA#(h|UcyAhX{j(iAs@Kl;c0#&p|=LCiF9CV`b#*Akz=~Vch zgQhyue3IF&_o}NClq$V2O3946AA@P$z_b8~u$F5`rZ(?oh@;3JZIHy!7=hY5=#ju| z_zG{9F?N1+kGs!Swk4D!o;jELxXAwjQkGp@I5(GTPeLkfV7wN4yvLr>WUA3Utgexd zYNuc58DPd{3W0CotTfKEIM_Q$2ng{iO@e=2MRAg#2sti{)MD=%Hzu3LiWj8Amg7zy zf~Rplp4(|C?&ZVI(YtYhi_h3;dxmkzI9su>Jw`ye%019-vI_E%Hx8gKsQH^A?-4s+ z{a4Me9H3)C?VJRB8odjl9AC4Ro1g4a_pBiQ%Fc&7CksOfGpZFc?qmbqg*}k3o&Tf9 zV*mLGV487#fomVGk}(pZ8SVC&OF}U(Ge4?;oB%RXDe#GN^Gw2-Sn@b$sW7s}uk@@% zs!{fivgSOV5g12v}ZMMJ;z8}_D%fx*OG(`3S6MS8=E)8D-Y|PF| zstJeG+9JKqam@4vc0`)?8KgyepB#i%nA~YUfref-R`N*4ug#2Rjc`UIEjezF!7fnO zErQJ;67dCH9WoEV`?;~~p&7JTzIQr&BZO2O!Hz{w<2$TWBK~vt+DRUJBzXqcEcyq0 z3e$ImR*&N2LKGOZT5Tm})0Y`>nSHinPHEQKD~-p62%CJ}+GO4;>-C-uZ>w>Q{LXG! zNp>cQTG{qm`Eel@yaq{0+=39;@a~@k9VX@_3;lLiP*YmQ%C?O1Q#k9F;mrT~0s|0( z;J=vd{8K$Ag52J*vt*m$&o2JqKZP^+l_!L<--@y< z$-mPv%bv*5o~5y3X)M3qSnyFbwR|G-``QUyGUk4nhNj>XreUiuMpDKDM_#8})x&-i(uedx%b^}cYxs{}n*S{!HxhVp)& zeRrTL3%UsS0;z;*cH8;5ziLo@0DKV08p^oCS>^h`3z$P*3R_ziowwqAw!jYm`DS*H)VI>%U~4}$lrReHtMd_BBckZ(Z4W4Dd@%~H?L?xCr# z+fBhVq$IeWpV5=3N0{;_yEN3R@H6`)ZYt(bLYEiD?*ur z84XM*T2)0?1Vw?4`#lSLs_*-PQX9qf*(=>xD|986r6|z)_28HGDYoV|i6r6U5*R+xaKE7Td1?D-eV)c+aZXrGX!3AUrohBet}WFYQ#6 zd=FUxiE6aUH^Z78+mC}KrtM$qjqqWuD7W)TT~sGC410)NEiHmC_AQOPsT2E#LQxub zEFSv>b8s-E6cs?YYB_M{X0zb@MRt*@4w4HQRx;I!7=`eV4=_&#B77BDkdAcc+0yyR z^;br498Rjx-j6?NkH^XiJ?tlTaUR>JHJxJR+lc0M&fj)L2+-mb1Fv1I(tXxwzD9CU0;W{%4DoZjeI3e(`cje4ZD1s$M)CYTbcz$N0{6S zLv^UJP&g#gQN0y4)ia=SQ^HVP-$U&Yz9jOl<&ZEW=2&H56_s{PYcuKVc}X|CCo3f! zeL^gzp6}{n@{EvfV4v%u>3@aXU2x@e8FN&5xI*XxI^v|0ffVU@qf%GTFNLf~INTrg zFeUauuc^~vYZ&hnxO)D0w-)@&a6;u@*@ye}#(`a8yw~FW{%-n~%By-cO_BGe2l7rv zIx#nKkSIcXD5#cc840VMrzDGv?1)2^M$AC3+LOZEM50<`q?(#1g>>JO!lFc~hncHk zRCVd?_SLT6yY}^JMs+zI^a|=qIS@P5Q;dd?)q2B)pM?#nkb%bR(m!R9G_QedW{qU8 zUVKqv3yAwzFS=ZZ6{p?0S3lMg_!fysuxy4l$LzO)D+4MS)mq_o(a*v@HRP4dD*ebh zIo6o4Yog{=2t9;c(-&*G0#a^}zzQgQPNy;>V6n>JVf;~$E1$!Eg{m0;l}egNYRG9} zpD(q!V(D1={a1(3b&*8D6MUEy7i3r%-;kgwg5O2a1}ABB1H& zYc4$+ghDD#^@Z>LxisPXhykjcunmWYVN;ERizDOQ-oh zIE^y0^;Fg?a+t;1L%Qe}Eu*fPqUTx6(a(V^chy(q(2AAO36`X*BzmgF&*3Bbhb3Sz zylmcW9yp>YToO?;kZV%Xc7xL@0r$5Ti5AJlHUa2dlgWAbiGhdn^NVW=6-U&Ba%SW@ zz|Sn)Qk#*=)dSIItqg3+(Xu8fmC-cDY3uhP{!MCe0_+Qatfb{4cIpZ1lY`FKRna~c zZS)bONtFB^;;uzFw^vE?+i$0-KeZ#j*B8-{#GRm=XjrjbY}6jY3h758wU&zZA-fZ72~oHk7PIilMU&0KIKSmdE0WB@M2%UP5?j%(Iq?zv{e;C6l4&qx@hc7ONB5j@sKO-MpFe!sSt*w z`UAT+tg3IP$gdDJjE|-7pGM6h)Y$Q+Ew@Z{ zu4-K6xENf+apmAzfon0YXK=m$KThXQxDpOaI3_HD>w>$v*I)p1dk%@f|cC7cQlMGB4PFiY6 zkG-*f=ps1ZpdUd+Jh+dzcaN94ps#`5BjI?yo>J5b?!AiskaHSpzcH5RpStWO(#5R$po_x=lgDKCn8fQWoPV`DMvz^#tjnkjaOZLJFgZ$^Z|~FMDH7v+DcQ^J>E{0pOJ^0)!ay4_pWP$gE!o@6 zzlhrW32VVGRmOsHTcI!-^{w-n{GboTGh=gTY8(lLU=BQ zMBB0U4T@Rw0b1|-vA+H?a}1i@i!Vdd(_ls~ndUA0Dp}slNc$wsx}5Q{ic1sXwA3a6 zG>{=j{EpJe+1B8t#*ScUdoDSWLh@p570BTVset8K3-IE}3y&mYHssct_h(I;VW!#OIm%{S5O(|+VPxMAQ7JUS&+bn|4sfsH? zIiI37H0}c93}}mso6mbk8)Hd4G=>;C8Om%STS(N+tW!16@bf&u zt>l-M|2;}lg;0|z*~9hCNkoSA{z&@c>WePVe@WI$s5xq+x&%yJzWyK3?3mVcMm9r8 zAg173(Bnb4Dwn%oYZ=wchVh46ptYanM9>w}#nO7`LOV^xMZ?A@1Juk}oDLtXv5cFb zr)Ns6U?u*X=dr;Z>sp~{3+>lbXieYDqAjYlfBI@~$;wzG{6aO$yqD6JSG*TYwQXrh zw48G;%n55xgCzA9Z|gZZ;1_xdgysNiqH?ok_7i{get*mXioc*5aPwnB|I&Xy0Nxwp zp&LR+!v`3JA?kg}qRXFtP^kB(qf2D0hIaJ{=)kL~-n#;brMfE5N~#A>5fW7U|4%zK z!WUE9S({Dwwb}Dcz;yJWFCjy}s{C{z^xEb2mvi*60O1A8Ri4zQ-!sA!*)xP#)e-cd zpA%~!N!gezsiV^9Lp9JT_M}?w*}jZ} z6<@C+!{=KWXs6S+R6m_+rkh*Wny?be+&a~e#52mKUzVJ!0=+hLOr=gkHU8p#Z}DS# zj_8+PMQ_BYxR;<~|4*#Y;Il&;U#^&r^Dn+>I=)A*eti}6>!Y}_7?V_E8k(j|1=V9# zXJBqG(}>#0Jn|UT2WLE>6YddEqZ<-Egu^?n8NJj&=Nu&Wm?N>-iso;;8OZFW1A#Y& z>icWY4nQv~xe$B=8vJkD(H@tcJ=^@DB9)trc|x_sUE20BGENL+2-VX6#6sJ=rS9+c zTK)%L&ReAzAI-m=s01gw`3 ztHjrV2US+}rfVgjb)sMQ7HrO~;)eH*FUmiSaCrZbaB%Fh=!4gV*?AOupH?xg?MY*M zQfCq{Cs>KrFX#AZ- z{9$EWmT{Spvd6FXTFG6sKuQ+iqT||K?uFm~Z{>dT|D)V}50xwVyIcXbIB?N&S8V7xU;7zvT&7^C>nY;jF8pjq4-RKoo&-d$sUREW_S2yshJ6LXFB@253LyO~##o#lK zTovh(t6{Ck({dE^9tjEU3=V!Gpc!!+yycC`O7OP>YbaM(W=UzCXZWsli7rRaSVUo$ z?R$-6_=Gl+xhMUi%X0b!QX3l|I5G)#4$bf;uQlQ!wPtWZL!joaGU9$kcAvWDW9AAv=|h#F>Az8 zH?4i3m6uTA1ItgkvTLZ-ZewB_nXxyWySFSAlCOJnnOM$$FP~*j@yiRW_Ai#f_RJ5a z-NrLA-A^g^UZN7RL@FU$1nHUNZp_lMln*2DtsHxDjMZFgMojPfd#@(ae9BTNvZyR4 zFRU?(9E2YaO;aVjcx3)uNrpZFUTY$_eExg7_?v=%v2W!&)hX~$j`y)tf?SmRpNk_a z$#9)xZq6Q~2L8@=1FKb$9_zAPOxG9XHQ;As7gndVW_V-$BHy*X^1`#w0h7lqhIEk8 zU?q;&Nk3pj(rFJ<)Y>IukeF4?96WkR zN<+uDy#Rha)r8pd%2>{vvJ5rv%9#N=(ct|8b_spRRP^agJ5XluNL8c^gbZXWp>hy6 zc1U5OT6qn8DQLIfFwew3UYAcoCw6ZO>(#*fbsR&8Ea_gY9A2epd40g+4fHY~MPvIn zRq)d#7j<~G?1gQ6pQJmGoiy<0+mG8BShG{)w>2;-kw%{9Xpr0;vrG%i?v#7oz?ZlC zfrqMdtiz~i{KmgzE7l0;Qkk}b)4f%YDKUmjgxxBLO}ZxUbXmbxL8_wO2ABz31(8i& zl-MMSpq3ycC4nu>V8l_cs{wr=Nb>bf;!sJ6GpeYDL}TxwHq6i_X7G!b#i4%C?v@re z@PX}qrPMRa@6b0G-&TJhgp)T&w$fhvzTtn5J9)8JQRy_Ik!(D`DYmXml5Uo@1c+sK ze}3auWx)RZX$jSk`7Rn#&5WRgoZI5ht7aMZR6y`otP4Z6`>_#Sy^JwFDT5i8ra9Qat+2nTMZt;k+TwF z>v1}j;S%Dhkq{0Sf5GV#f8%scy6kk0`pxO=d(r6>21&@zgMq!r`P^rsH@7SabOWRg z@=6uZ66CQ?ixHe#!QufvL_J@G@6&1#8`EGL=TD0$D+Vi79(E;H+?v_duwRY*=$=Rs zCAmOeQO>)m(gr*DiEYMTG;U{z%l2sO*v_|Yo?st)i ze&gEbS)#Eogxt*7@xe2~ko0GS(7Z3Js`Xb~R5OWa!p?t6P*m(nZoCkh={}b!<9-5m zZ>rkE;R8INoTSz4Zjlit)WnE8L@gs7wnpF-{eaDg)B%0BEH+p+j^fjS$)9SaSVa;w z)q?%1Cw(Es;De_2B%s|ui;}@WT9C)5;siq}&@ot#h?yy#4E#>|LRZS(cvORxM3uU7 zFBZ*oA@WnLxzYlJ(3DK^7>dUS+V4Hkr}sl>J~?*ur=Le<4$zJi&$7`D^rgt3qrLhO zT19JDZ>6=%_^Wm?!V_j_q7w4>__oY)9q@ZfpBlt5b(M-Y3a|Mk*399GDWcvZ(lOp+ zV$I2B4-XP~z9zx^jx*|J*v(MQhS;4>V8eyTAsL z$I>htf$||L@|Xd=;J_JVkke*|L5W%LC(}- zgam``SNPVFL?I3-6}}8?^ntU3d!;W8W8&x?LS51!nkrXckJN%{I#LHAbr;cr3&F%8 z%(gW7-o?X{k~A!ETyG`~b-?HjW_}l6-=(Z(G(aP%-F}52H=?I6&nPZHUF*^}cq|pR zN_HH9ci@TKr}K{p!HehhBAVQ2Cg6;+YoRd)WK{MMq2J=w!plH7y<(`J7yi<`mp*$5 z2&rtciQUg^YTz$*vn96qV=%wEczrjERg~JHJ7H({139Oi2nlU~n#MCD9xzOxwQpPL zJBRBXWc+wn<$BkKcUSNZZF}I|&TbakZC!*!|6n}=pQb=*tq9`6G-;6S4|TlqJ7ib+ z>W~r^M03oR27X<)1m!81%xY3F5g~GQGbVkh4>rJ>HJy5Qd@ zpG0o6&Y47ea;G3qO~ML2)RER)E2L+yFkTe)8O{h5)2TJ41DNk&zC)q!G!J7r0v0{y zT1EpuLb->-I|;S*9II1Y-aCz_}2knZO%+G{c?Po%r7VmM{ zaNmVr7VinXtmgT_KRVqJ@cfnUw}KhDox%NiT$UKT!#sV?3d|)Vx%=xo5{lQO7*62$ zSm5^3=d(cV{RGY=5Ne=rcQQbzfnM1K>{y;*8xVSrLhWsANOkQKiFUO zU9=Yi&|fRtjOEeznzS!d(UY}Z5`33HhD5Jyn^i8t+V=r`eoVxh@6n^D;Qg3Hu7sWg zQDJ9F-6=?!$@Xu7{-gWYTwkj7um~+nM~f=_)`5aNVclqF!TCi`Yo^%O^_P%@eiHIo ze?r&a2@3AAbPcp-LM|PxR1}MvS&u#~-g583KM4U#G;|#@5w&=41hjv*W;5|eQjQDW z+9}CEcaHx9r#KhpAeTh7TVRjdomM6tEVaSErILw9tie-~o5A;u!0OTlUTwe)P+(gk z@Lk1we-*ZxZ8Se6wd>+IOzy6n0G|85oN?w>Mw(l3P|xBl+LvQ%nY$}>PHlxg?XnSl zkw@zJ*POt+K@&F?JIYOdLJz%XffPx=)3_eeNm|GdGK}qH{l{K`{iTQzS6+2wPnnY} zyXIrV+a4w!?{3aXmR~J{XF>+LTBOGva_`!Nd(OotS_$*MUUtK8|u`UJ=Ql}T}Iz6K~ZJ(=WhM4U>qA=0@S_h%lbY~H{ z>P~Ck&`oO|VRF~}dbiPZ1$~iyc=gNXS7!>b=`6L|1FJTq`2;i5IMKLxfF^i)6KwX? zz&}izNyl1hWzWI>jxT4>vn5V`wv(u`VW)$xtrf6Q;|;zw5U48g;2p;4LY%=0L@~VI zDTX=5dw)%(YK}2EWcVbkxMhYUO@>hd{P4b*p^mk;$>S3-56h@kjyOnvw76G&gE@5w z*vv~nsUlZp6B+7QavLE^Jdy7Q8L-l-VyRUX9m={NK6wynK1p}E-gndo5gGoHb)%4I z7=VLSciNG8!0xErx%;!hR-NF?V z1MTx8{ja46XhN~i2XNj0jfKRVsA%1MzH|Slqc9GLoCt1g`e%@4eI}&s_)K^X*KAyv zy}+Um@r^dZKye>szo6 z*aaz2J+N+f`3pf4(>Hv(UVJ%%Q@gky+ALi%Q>zTWXIE$S+lw{Tr034av|MUU2DLym z!gG_?rWb4aES$8^Ym;X_3EwZI86vs;!feCOSdaD#1_LP!*t=htZorCU*p;#wk~~mw zjuScXG_8^&=5!@utB$uD498*XoVIb^oE>w3B8FDSA=M0Mlb-~i5aC2sNi9r~$EZd7 zje^ebST#~;8P#e*M{ds1;zY}~gorwM&vy8L1P4iXCpahbWqCM>+G2qv;^`EZk(sm$ zb`eO#hrn>lp-;Rnh3am>j$DL^F{j@8)lmP&O#vU%szRU zMrsva-29^$=*7G~`P8Z}MY2P?6*j^XOy0mv7Q6@TtZeTVu}2;BsK5g$GN#!q+SeiyD_~oZBKbeWMPnu4E-?0#Dq?oQfG{(J! z(&jUwKHF#tY8yh8rF4iGaMNbo^In=g>XIDeGF~hhZ>;3nBLO*&G$P3+H?&JaR zAUPJiHewPLMu5|}Z|n+qgq#6<$=dFON;*zq0nHDbD@e3m;}$5nWg>=6`-y0Bp_{X# zfrQV?tk3)`Gkgvmdn)V?723>&u5qLcH$J0Z6+C}#TJR}hV%`mmBSRj>7Ot-_p3L|? zMK)2L&1juNSf$SLbubdfLc%XJconBFy2*ES;CHSKcYKFuv2E@p;VW{JZ^1osz&dye zPfZ;(m+A)0(AfU_$tFE`ung9it%g1=)5W_|j<-)I$1x}48{jJ-N~{*;QzSAm&ES?N zc@#4R@{%6-R&ce|)ixdYUznqQ@Dngbq!AUkW3Qlb(JwT1d)EU!;}D5x&s-PYief@( zAO7#WZ#)#66(e>myeIsZyuW`aw!Am*h^Rh~%=^$ov6a1flQABTtoO$c#n$!aeJN7( z$h_A+6x-CB_rB5KM?IoXUVSijn`w!=PfU@LN9LXOP;9c)-6v`PCGW(CVw*DEc@O(9 z^^STdHksqjn;p$Qvflm=#WqcM=Up4YKC<3joez9@aC6;xS0p@ooYX%Qo9cwnak4r> z{>Z$4d^k2JDLPJOCp@~pzkE2h#+|n|;?ZNU?4j5s)Sb8dzvTVi!?AnE$zrQ@{9ZTy?cXzrPDskR?#&S`})`UhWEukv9$7hS^+h>hA z-~ixGrOq-K8Hb7K;ftKAtX1#=b!D)XCB3LHKHqrdp$bSfiy}IF$(x9qX;XK zI7cvoyHTdh7v_I6#ld*z2=i}fvI=3___w_nB_kuauyEHZzUjf0YG((fo-BKjlH>_l zeu+RknuM%xoc!rysIOmWhIcqZbvzy3-*BUuYspq+2*tFn9$Fx;*JRcs-FdA zEOubCqJY|BqFhe04|ZsjDqvyRSnvEIP($t=)E7JGMYOOr*RRdAh&ZO_(7i~}vBSvS z%Ql>DeO0?|u9F{eECLiv-#u*TtFLtOxjpVYf8N`-B!Qd1=(9!sMqjQoaL(LkjLkvz zMW41-N<(qRa8ao3o2}iO+=lN&RyRWh-#WKTnZ^r#s+Ctn@s^vn~e*B&? z)br<@KL|7P&fmH&#D^;$IU@SFzp>JaZ>noEiBGs@pnQbSBS*wN7w>prIsGcG6hOQo zg~s2W4U0Ja_jr{43O-LK->+xcG1z&C9B{3FNi-yfVYV`^WnnF>S;nbSg*e?Ou;WF! zPA#Cv`j;?C&@WU>F;Y&SDrsW+?W>?8xcgS{#35XY`2 zO;#R8(Rz%cu+5Ta*1Q@|G#`Gmxe2%}vCanGC;Y>EQ{=ZMDFb zx>gSPrUBHc-AXBnM!b6*?{48;lFFyZm(x_<jw7pFjF7M z8Y4_TK&-0FzMK8F+~hwM{5Q!z_9|Kf+289qpm)LjnWCW7W}lXHcuzhe4KDZG9I~ID z9S0qt^qX=MJ!e89XruO;Jd0(UuL-I$@!38l$J+a)Q+jR_4Tnw;B$zgMu@3etA)z!} zg__0NUJyK~WXbI0b77q&z)WW$Q%?Pbtx7tIQ#14rmKIm-s4hkd%44D@RpoZ{qv`&+ z75SR)bD!wh73CTZ>peFmSdgC78%GYnA|`;D5W(?6m1qI^wz+&ZzCBLZ5?9)c8oCG4gMa` zFm=$}mln{c|8z@B0|RgH66b1)eIm3bH2kJ3R$yTwO$ARA%c5qp~ph$rW!tLU{$< z=o>TeHV#&lhZdf+fXl+jTU27$Ih4RBpZuu(rR0_Ovdi~pJuQsWN}A8hCCw+GIT)ja z++L+KJ|7HwsPfP4H&Ue}T`eUc`=zAq8e}um@Ej>6GZFS$jFi+Gq$C32w-B#Q1N-EA zq(pdJO12_=T(p#wAuN43;v?PfPfCdnzs9Q)5+9B@lM#QClq^9!J<=2mmJ;bGDVaS+ zNvtgk`1|1l0#p-0znv+8`{R$3dVIIj44-%Ux3OarE@c9Di~ps)ALPF8wEbM3!1ddGix2JW zR{~C5)H`iIl&g)E!XTys_H~Bk+=OlCC-{?ecOa_Wj0RSqPY_tJBbyV2updmu4%h^v zI|n_P^vgRTtX9)p_tN;<1aK!|iv+q!Asz10w$t!z5x0Y$MNPlJP6^Jywi8(0Av5mU zVT3Oi}CyV}WP@Y)uJ%01F zC(vfOnC=W@0d@v6X`Tv>b&(P|nz7#ycsBHAV%Ng6&zGi4&=c_$yot&YC}zOl{oPJa zYB%_yUG9_G4PMiA|D<+<55fKYliCfwZq_6!sHUdnFD(Kp%Nte)d+}7JV{zhVX<<^YRzqhD@6EIT&+R1Y zzVI@z;Fv1wr0ku$=gZ+w;0Q(OjOiU=pB-4%ARfp7p-gx69zLqOhcEq_JifB+j{`mY z=C9p$0am$m{B~4?Rua{E;Wg2EU}TO8wJM@MD%9zKIQIPnyVEDot!W&K%L`ZZilk*p z=LAFSa{QkuIwz!Q43Je15lV!FMAVclYrlyv)bwZ74Ia~f$LZ&EMneHg2urn*=G5cI$($9 z%noc9qn_C@BdSTgOim3M3ByC<`L=<64_5jVUuyaUVMcKT`#1@j5QWZq(7AiK}=vJgPuSSBL0Y{LIt4j?f zF1~W2WAN$#E~647MQaF|AZT=}s!A~Wf-uIanw5iFFA{Yh4&zLDzJc}ziQZL%IT2G? zhdL3I&eS2d99Ymb`j*?_8z>Ez5!bS}ljv+POkYXoP$uTklG)%d9Z6V0=Sb`#+*d54 z?-G{0g!^4-Z`1qf>9{Woe3Rb$J%{_EiEq(+{Y>2FMbP<}pqYyMb#gjG6GRgm>cB52 zQERT{YB0i8=mXy%&{Hgdj|=plg1iY_8s3l=dxtOLUUw^{!_FD8-tbgU&P~@cb*tSOq$=Cy{tF*Tt zD>p@-wAR7?XdO@%@Zcg611<4B5PL`L0dd9p!8!ocZ;$8{oTw9+rjgq?>Dp=S_9VLl7#gF;z?|4J3bRdn%3JIml- zx#s|FB|XJT%2xu#jIX5Z=Dh`kY7gMKi~q(+?|0Gm>nTc*u7XF~OH}kM@Z*6ivO4IB zCAQpNjruF6IpipLr?!7yV17{HQJjE+3*qC|5rDVL{M>0h#EC5mJS(*C&^-N6qKZT^ zj+?9Q_v^2#5IeKqU;T<+HE*ig2hGB9IsQ1S_XEuupIum0Cydh@?%V68y7j6u*uaQ` zW?CJ-`Dpx?!zb9u0d>Me#Ph^SDhm3T=>1gmek!fOKR_GrgU#^7JGW4yL%#Y!z^bt4 z=$OzjKqx{ZSerHoy-1D|IT< z!a0uX7-i`(jQU1;D6~cBoKe3v=QT!~j=gZF?|OJtIS2fwfota_@K&DaIK7sRlgF^$ zB(Huiim?ofa#-JUjl7Q<=r$oHxJg0Q&7>){G^LV6imvU}C*E1Jn$BQ4Uq9Wy zR!#T9+x2*l^(^tur#XA|%$>5F#^8Tqy&dhUg)dF5J1Q8ID~z8*lj-_p)Iqhas!Csn zRUzI$?bFu@X{w!c496O{r-dh!5>V9B@lMoy${Uo7j*jO^13rO1JZZKp^@Juo9oG}} z&nw4J+Yc!V^?#4+SUl5O|5Q&f=2V2CwNt+7s>}EEo?uP${f%c`bNL*!|IIWMag)@| zw{QpBDY}>jdZ$!Z53FA8TJuI5G1}Dc2g2SLbQ(^yp21o}XN%Xhzvc>IFov(C7FbNB6>`cAseno(EX+s5LmuZ`ogGI0KRy!>cYCVr#J z(eLKn@L^ih7FJ&63R5BMHS-RPftB}y%ZsXNs`jJj(^Ou0oy4p7iz-<8tnw~wMlZ#i z9przAN8xl~gwkh=PpS9zKKT@#>X(P_p;R=>NQ%*;NSR*;%HKcGcZ;~t=XtME-(u00 z*+N{lvUEDUQd|=z+GYidi~S2XC+RekjeTG@RBIC#>Vkb?c{Rc&D)ud!Ej*#c8N;0D z2xP7d!1uN(3X!L|PpJasoCMlMSt{P{kCaMSS@rh5KHvxNCzM-$!}(UHk#P!me*2Bz z&^+Gap&;3dNF3~KjLAoeBg=)kE# z9v`=cjBFYrji~9zRVe+oO#q(*X|s`5i#SSIvqW(;$Y(p{l~G@oO!Fz`Y2&X!ON?`p zW*K!su=J*wlT;VtM#K7ZMaqfk^m`ZFqTZR|cS7?V)|$sLVi?E89GBiu;vUGZ_W(0m zCk(-wbq=`FF22|`SKpwiz(qZTdB#BR*PRkrk2cc;5;`^=&yWQx=(C<^+_U}phtdrC z|CDCJtF#PjZ^C119)*z49|Cc4X=MQe*P7{}rqLOsGvMQwjWZ87t@c+OSJuv?_2 z`+KMJI{1)VJM>t@Mn{C@cZu$Q=wAv|@P(>V)Q2CkfQPG=>qNk~(StNX0e zxdYc(gv~qUbV_i63P_|>Krc2PYp&;o1Y;dmTd`GQqrV~xU4h%-`HOLcuNrN1Ml!7# zrpxJ!n$A>1NE-S-T^;mVa60Hi*f7u4udcaLbxzn7L-&WfH~}Vt&v<`-z}WzMc+0+F zQU9_2L1&(d?#HlUCKg*lu{PET*|8gCETv8p6_pblCb7Zw6wJsgC$yQC`Z-iAYbgjy%vU^oC^&{8k#DNKo0Z#A`gZ|gkJN5Us>QBX47<8dgR(>o^nw_ z%UBTWRXL@NOevHkw!FKlL|6!HGvipbY6`So!Xu=X>8@Cd;3oy?qpYU`0l?{S?$^-u|}`tC+xZ3bLOMyIqebSa^tb|W$D;K(MPl{hg{*Hl46|v zuhrG-Xm8T7u>thghbHtiDX7ZR>sr^DFo#|PZ+c@lzX(1!6CKM}q19T7N>8P&23?)# z*lof*(xDaV`}63N-kO?@dfqL3jm||4=bnitv0Dr|fjqDyXigMhCAdE$i9>kz{)}|B z+0}b*_vSR~=!3N!i@nxe$B~z53GNyWaMdtol^XMcV7JrwqMn-Rw4RvpiH=#l^^8JK zyT8rU-rR>BrTu%|HT#`>IG#phE`8to-lIZDBKAM+r|<}T2v5}K4Fk)BBU#W0!0v?E=*~70ba=eY0E^-ywIc9a zUl8Jz-p!|2jQ8|R1;?%s;@_r*1_-A z;D6Y=U*f;v-STK%EB7wtJC~1TVvDQ%gNyYwZIgF1q2OUK&xg>pY&JC2L<-8Q*jrVs zPZ7e1i8#y!GpwUaj;q2rrs zK7{-gZ(?t}NTWJE0r8$=octmhPvzO1tC%h98b_kct;g4jn#GJ;8sgVvT>?a-+D&`l z`&ZM^u%vfv401g!?0xD_Ylae6w&m?&!sv=SPGIoeN56|+V$yIIwE9{6H?AHK@gM6U z@K&$FU)yw-H*&kh-MYI+;QvWO&oAz?SXqkFvC=2N)o%N8C#RD}gah;xuQdStzmkgyV zW8tsTfbV-$n2qtJbJ+2{-cn-xsu)lOlsEiz5S4GZ>r>+DLzDu}hS~8ZrItm3;7hE< zI;2n~q`PCi>-r+gj6uPuAM&EB&D*Z9<;J2wg!SgO)K%v_!c^ZL{^J_jr+b7cG4MfK zgR!a^gE{+}pBlTIjXMTb=)_KbE@H*Yq^_NV#&UB=diZ@cbj3uU>fH85 zh~t-B__q-6)$8v3fwe6rHV`()D1S63R04{QdNm8dnx-N>{D2`}M>#9lw1EXpZEA&kY z@p{345%J;I(rsebc>-hkxg51J}uy_LiMe^Ccuh;7X{FvvMQO z2LZd^uPQ`6l)JYk_p}|xd3Bd6E#%VdBnQJ@nweX*HTkY<)#>3Q(FEz?H@8m8 zCDGnjiR1j&?lpg9TiY&XEIlV_V{~`=u6A)w|ACUsv@d8o@~T!RH(o~mhUnS3*z2Qk z%B1;)7;e}fsFjx1>g=vkSFOI?MQgQy)=HTca(;FgYIXjhTK)Pp&6`pKOIF=q3&VQX zxM*W&`e>|iX_!SF#}SVl6)yR%!~8tG3bl4=g%CYMPU4wM?NoNqv3A4T{ z{4H>*%nlE_DuAY2+4jON_i9SN53N7;3v~~_>o{HgnOMvvU-UD~GR<9fA$X(y>$WEj zh`_@%`Vyc-|7Xp-K_qlf)zcySiP+|jJC_lGbH*rWoDg_+4uOwnNcq+BD#5@)o3+_W z+X!wbxb`@k`YOR+prdm;L$i z>?8rgo?yhV$*M-hic2-ba73jA*P^w((QeUtTdZwA)D@7n_SW`>MGT8bTW>GgR>7)Q zaRHUObi1M3wN@)#1ZylkP-;#RNWSk0+V*q5-`DStAH1H-S?0|0%*-=0&pZp}T?1MU ztDV}CD^k)|`C=bi{eGt z*)M?ij=x&gMpKV`pkSfnTkd+yHNYn^qaUV^UZ>Mv2H*=^!&3w2U|Dn#Xf$Z!?BO=* zq3`vy6<@{sBM0cXxfE;UpXe#WzaVzuu*c7a+ar~C4M+TInmS6Z@xW2$Ip|lKT`U~N%~~vpPtnJSG#4a|B80o zffBBKFO7Wf|v&X4^!5GsSXdNG=Eo1OHpSe?$ zl4wee|0wO_ehd^@qND%!Jm+;T^}i{AZNlMM#OuuW*Lm1O?tSLTj)62S^A=X&Vm%;35xBR6LDfp{)m@&5-SDpvof(ipgks^eVDhUH_rYeMz}v; zoHYyZOgG$ea(}M0We)vU%M8(6z$Jn&=l^OM?!>D)uXE}NCd23a`uHEz=izVYdW&*E z%-IE>k+ci&8IdEU)acxaVQRE_;Jy8SP^0YMsZqY_E;Xt?*kYvAs6bEqEYibVf%T#R zXK^^W`&7AzpQIN#J`iBFn7_z!(Z5oV1dCKIg{Pl6d;m>on51aiMp3&~XPcWEo4g2Mgx<7QC!8!0$dM$qCI%XxxEdWKCIk0)}@Gi^1Z7Ln!Z={Z=>v*4Y z?Xf%Y{3~-ajptv_WR+r1!VJevM!bc`T46POi4CZh!{$JGGxdCc6_ueC9)8Uave6Cjlk#xPzi>wR zO)2I^GM!cNu#4-ED%3Xv;7MB3HG*emhTW6}hj%g=hm6jzlUOy~jWEkP-4Mh^E8pOb6-G~(5G}%%8oZlS1j8pP_=r!E^ z`uSEn^?Sb7=bU{E+zo&Ed`{_6y65Jdr!mXYTpyu(aEr%z@16SxTkr1Ayw1g~+wM>l z4Pwpb6I7JLVx=a0m>EkI>oK@6l^}O^v8f_6VUR?FV);KWs38;t47?Z`v8HV$J9VzEO1M9``Mhf3-ELKlh z!J>@gpm~@B%%B%~U9gB!w&_Yyh0}T2C#uQvbD{P6A4w}tYLeM#_WVkG4H(9M4YRI({lMUTC`))JYbbf?v7|pNN@G%sLSB?kQqG?eJ-f*Qq%s z6TuR^@@@2QrG6oP^{RVBShwjhCoA)AE|~#J)1C_NMjfJcrYe+`YR%9&BG&@V*SSl z)(D~DuSfsva(445tx8k}j6rUAQvOn$j~Kxnp{+u(2rdcLoJ2qB5E#_?z!NR$NYF4E zYVL#)cfydPB;M-`1`VZel7eUtldT>wWkQqc&g} z<$rL(pQw8o^7H3$3UE;<_%c2YS8<3NkjcKxud0}j-_;dy_#u;pF$6{Pn4aB9?o0aBxWYr349{+t>q@u&6` zQhV-BYVRYp{L|oSK9kiJP(xeb;z3!t5?K52;MA6DyewP_9bKwNAI}|f$m(9k3M_Lc zqzBhd*-0%7U4{=1$}OcfhNQJeVP8lJ`$CYzgdCpyfE4F; z&+cDikT#I`bGM%>jAol2&0-}sc&61mo(S7X?JtE?h3<%~9&}FhAT99aP8aWA1F8Q7 zkouoc4N0`;OTrqUeH!o~B;m`t!tV+Gl=_;VXo(*nYkzv;6l87<+?o=3-PU87HRYIx z3@x4fqF8aN2vTVRu1P8s9(>R7^eosi`{{|$2BiFOxD9E~fQ6;@gKOHQ)Y{Ubwkv$N z6_jYoGmu+PDv|W9AY`&QIKH#V-NmA@ao78)HTGWg!O=KR6e3M+Pb zw|yH4PJ}gWt*#>_t*)aXt*$G@t*&oXryVj`yF(_IJ1#$ycXOru93&6JYdfU@U*!A0 zf6_OHErn$9HRt2LV)p&j<5!=9R^>TpJqjJ47rx;z3;I`58-!a1V)y^>N>tj++ave? z^fYv73U53S)qV46Bd3$}KC!f?_h}aP{v1y%>cLx1Pi{Ps*R%C0abKh zt$IgLDXE;uwmo$ewgR>cXkb$(3%--q&DzDA3eWYgir?ij>UQx4m2_v`%~zv#xn@}p ztk}uy;%B$N!t8QoH;-E>-M!1jLb82(^iM1DZoUGo;EcvqE04kUs;H5E^AG+h@()l4 z_}WqZveGG;-3GnoX6P_?t$rN8*1ao}A9?3d%zt`F+DK;(9C;7)!b)Q8aS~fRm+YYZ z`fi_|i+OBtE$!En?fLI#Q7z$ki4C?nTv~W^oNl|fj&fy2)tq%G1vekr`^ew1Dlx16 zz3LLA6cVka-60rf9@xyFJ$dH9`S-S5uSwc;UGq+0pFSw~qu0@IFL&p#-#KFk6RqKX z>tnR{f5I17FZ7VO#EOBQFq;56=fye}zh&l1#QwC8FjMhO3ctO3X5AcC9evIDop)wU zF#Pgn*-DJDS3r+siXH_kt(8Gu)d-&WH~ZnGb1U=@`()G-wSY=Cb?%qd2vWrM%-Ra* z_0T=$h5a~<(AP2tSDxvXMbo}@7^if_{Pk|`D-q#fi>G7Ni_I@t!eJ$Z`Z^cDzfRsj z;@a<>@C{OnI;Qq_zGT+L>sjIc^L+F8a9HtRs=s%>?Ge_UhjrX_$NtG59sf_hb^L}E z=iznxIDWT{pJv`*p3eTV;)|Y4tbp@9Lf9U;ZU3Z4cG&0q0G95QZ8bWglTkYZ!P}a} z)=IXePpA~v;$%T+uq?znBGe*G7FcaKK@e6DSi=_AeQkj)kksXN2`e0%*(Mw*YO_|KT;Ipkqm@*#9W9++85@Lx`ZB?N$8Ofp+~Hh zcF{P)U()y&3hVd|_^xE+Oa;d4H28?iLVS@-X)qdYhQ#8#b^$Nc;@f(fmSFb-*;g;c zDTT`U#=pRBLe|aj1WDcOn<^ax3m8JBk{9HP>t%)iwAeMU0c(9AM!55zoiaL01{co8 z`Ru4+PLME}){vz2*~Rq&+dnNoSYW{v_8rbU&Of)2#Hd%3r7_Z~Eyi^*lAZ7fUoNf` z*#xmDH_Ch7tm2u!qwMWWy>u7q(JF@se8kKaDIYbOP!D`jCfJQ{Z1%;B&7V$PsQOjox0iIv6y+@A9HRu* z$|4eHq2{8RFBgX|64#a+4|Hy)Hfw`vYi_l?)NH*W5;2vuRcV{H_6dSX#c+)??H^bw z-k)_ld|Fn2%j9|e(<5QQB(9QY+UMSWH^o-8ce%o&9KcAF1$dN$QV*FU@eqUY_B#m@ z4^t!Z$Ue@yshK17FpQWNSo3ab4Z;Zl%7Vh0LgB=U?8}!(EmM~tGtxw?pLI&^;Ju|! zM9;36`6!EkT2ce%IeWWBXr)?84m(qavP?%=MwCM9F1+z!>IZk=H}%s-Q59OTMp&P( zZZrz4WoC8>j^=3e7mz*JH18*|0I zu~WI>`(@d05B()|(n|w(_S~?ePAG zv_IC<^gHoIX8X0Dg?DQBTF=CZ@diS+%zFKE5!ncM9PnnLgj5dse31y>^7wq4KNFEn z2-}~Q5Ml|iOyt&|qBhCRElS-Ou4@P$V%T_dG8@nB^ZvtZHtX2TlOopBL;b~PwiH{& zaF^g!llt`-!+m}dsvw6)vRX?ps~b7m5_q9`wxPx6{K>c4GKE!*4962#jXTN1e}L?8 zD!0>p@`lXdbDnR*{UPpfS#!WUQdX^7gT18a$=4u3E36#DH4Lfdh}mW`&b;6Jf@zg` z47XzlGQ#W)v-~RPtu2}*T|Zem3YZBWgBNhn$agX}Qe#<>%%-dm(XnJ;nhR%d?i3N~ z$0KxJAR7u>^%UpfmNH|=Wfl6I4D!&^+gE4}e1rEf&eh&jX8ulb^LqVHV4?9=3E?p&An)H&)q*Bg9MIZ=16 zpYuiLMBcf6+82=%ap!uKFFYsQe?8nrE6_&k?XY-@Zt^_B>taHlL70W`DTJ%=d^N%r zunOpX4V0+p{Z9xVr_Y(;`xga-1fi`-kdfyyID>Dv677 zH=%Fs8$4hpI)T3xg=j@;FJHkbEwHoCsz=h^1U-rtfrUvGb-sxB6@$s>pOQJr@H9&? z^Px|Nz4BgItjRnnW;xKMGyfJ*JGirg*|VaBqXvz@FYdBgBxLo z$0C&h-=6pB=fetaXLifvQ6k7ei-MVqG2Fw0@1mdSp;tGCD;U(H|5IPJ%0rkrd(x?`aQ35UncVEMP4(I*OEJV zCHwQrL`mZZ;fqf%?4sB3B?S9R=-smfe!LVO7Nm~LeF^k-qiIa1j1}!Af~*l% zFnQm|N#E!G|9q>p7f_a{}@f{ zf!9sR0;O%eq30XD#ZR-8ys_+Q?#fHWuF&9+trZ zvBnaE_Ppj5v3yH1yVimeALwiA*uyO;pl(4oijFD#-{$fXJRQTW@g(DSm4~)&A*j@| zCq;PQ+cSpyi-%gBB5g-L5s?bOpVL3^r}X#!o_-wn?Jq?w!|7}9q(9xC{*>R-H~pSI z?7#WbUxKtJ{8##0{*?X;NWZxymQCd*@I@_3lrDw)88)|Q=>z?#%YRQj;-uJLdiu`i z9!`JYV-dLoPys(0;A6hm(jqDv!~NoxAg=Nl{UU|y@KNgSa}JzPq0a9j{+obIe51ry zBZ1RN-oh59NYiriMkeBQofyM?>b6*7S;0t=CGf+>*_kKt|EKsPhvOd`j(-91kNjWp z=@>l-zuzHw+t@9psH-DKk%WM*;CZfsMdRbSJw83^QRmLhmfNA%I*N|e{vl}dVwZEP zla9vWvOkWp^Rs-;>Jw#85BIH`AN^6^uZKizKJ<9xaVeZ*FrB*yzt_Wc-R!UH-7;)r z!>?*VQN&$RV8`q}&~jh4!X66`*rVa?+UGnxB+4Mk9C*+)=SV-+Qtsru^n~8Rtjb>X z*JyEHIHItSBG2e`5`geh%p)N9@FvUEys6- zhr?OH)IgR=jbSyHhQEGbh+(&3Wk%9QbPCgj_Tj$nJwArJN6R$IwX^8CT3Mx(d6pvB~i6 zB^ps?^mLMhw}3x!S3I}LEy_4$+-gd+F9X%hL0c+^n0v&qJ%qY~9+t9AeIf}-xJwat zyZ&k9uNaVWtqa};Z}53O=Rb}QgJjjdwLM^vb zFUoY>*YR|1Gu?eGTVz5D#>ugEyV%3%#&9cLB)*gt7Jk^nUqrp;jh#C-XM>6E7wQU1 zn~O}ahS?ZxNu9GGo30;BpQYqhu_^bZ+)pi>?`hs-VyZTqzT^q4E)lqlOT2G%?&$lI z@-~^0=52)D)fV^&B9)J@kfTT=sVR1*CWMdEO>;qu44icvt8Rn$*sgnADl#GYLR%Ex zO>(L9b?OXPn5x9s-$`s=Wb0jFui?MD0tAuXb#LBG?Ar3Gv4b$pl3o<>Y@Pn>w!mCcsF_p z={*b>d=j?k5gGv*09rN^LfK&fE1o9-h9z^<1$16OzZeqek~kx8!#DnU!9RC%S#kGo zHchfT^nPq!+`KKO=~!Q>Eh}S6jm+1W4`IVVCQF8gf^7`ej=bJ%c%L}R7!qgT6LggO zFxQ;Ri_-oZP+r}6;Le`{TK^GzSpfcHdY59J*v#m>XfIfiBO}c;h7@B9ea=VP`qx13 z9MBFZ11tlWP|iZEkA2Q2UlcGf!V>>}BrH;f!Y@c17*wU?4P&(Zm6p)^!rfWapvq#N)tKy~P7i_t>j19OEd!V0r28%=Q*CSe|~I#!%rSz02fB|Xc z4yUEd=i^A3QD|qN;T5}b<;oo`fjJ`zG?w|t4!eR#I=36vk|Bu!>6ykAld-y{BXE+Z zANHve%_I#=rxv6hw(%uU*KuF7XNXF}>l$3C)x`j_30 zbzb2~#@{NJz2BpcN6y1Yg^f(wH_R>Jz+iY4xhzJCRSrEGKnqXV~qJ4KL8!%$?!x#xX!KD_*<{?CRj@Z zog-WzG@QHYT&AyiQb^yQ$NMkdahs@YAnY|8sEonMtv>j#z)6<%8h--%%O{|}eBzy@ z7;RK{`OrM7;|xH)haRMq=up~b{5F5&p}7=pGD*wVo0jr&J@zG40oBy{MRK!ZhZ1K6 z@E~amsDa+*JJilEY&_M;i`=HOup1Iy>;i{DX5EG{qJT#LeY@N?8rEG%zTOpu@oz@1 zW(8mb;8mLI@{j0lB(Q?V{s-Ix>l9a%6*33l9w@CE(6YdaAlNwxtW~$+G`?*HEA2u` zg%ie&M|v09!V#lRJ=GOvJ(dlxS+1}`dh$LU@3PW__Bxazu;O#9A_xBlmOQ9W)hdNazt$U4bPL$vx04cFYyn`8!g)PRKcQqXf1C-zcy1&Y0x87 zq7>!J_z*C4iz#!Mis&|&kS}^=LhD36RPTZBRnq)AU3u3EN2B*Z`U5={xKn*dv804X zgL2K}nXpgA?GD&XyDs}h{=axjDYA)azvq}4q7Ir)h(8;YH|<5LMi<=^lj#<;kq)!oF^T3HU-ZfwYUE=^ z*;Vp{WxOKaKb{KHEJB`{mu9X)84Hd9_DW#RP*mfln9$F_=_<)bol|T`!|=+p8q|uQ zR)&DY*9(SIm`GE2aH4q~Qqb*XlfbR_`4Xj(!vUJG0k&dY5IJB&Z z87-twFBl%jaTWp3jEFPmBb6K5mLruPFGy_gEmAk=ACY1@jtm%Ww)IHi%-)@DV97scK9*Z=ZZ;aXptX+`WP!_8f;|utPRR*F5Rt#eBF{;#)H9xAGD9#IC zpltxj0Rc{oRL$3TZ89*{G^*x7USRgql|p|lM@%#mr2VLkwx#(fpvh&D)*{71e+dv5 zEj_tNE84vl(t{))*ir%G#9I)K95c6#wKK`OT%$QvkI2i%?C9h|NB3&zDo4?mAMR`tXQq2@^O7mRvRn+F_1BU*9FpOCLm*1i9HzTbVk=DEZCztSK z58@~gr_ul9-*{601fWL(?5eDkatnlda>%Tivf1E%$`J!Jh(6K)<-&o`qCWV{)8 z&QIaSyMUo{v@eV5v9r~w%ylTkBIHs7T(k+d$+5@pd^UPYY6e3HHcp2NhBmu2}e zU#}ivB`HffLu=KmLh3^-Oq|ZFG1EAgSJGc#Z1m^6sGZL7N(T{bhmQ5rTcx#(KGLeP zMAoh}!M9ug{;jpEN$NeFifF93xeJ(UW!-PFUb?Eot~J;#t;HPjK@@u6bnL~%JDoq0 z_+#jSA7_Z_zb}|zPW}<=0Z^<ZMiSKEjsp1bN1vdgsBD6X&`GH~H&v$7xkyl~a4ubln07}f<1oVX-~y~Y=I z02U2mPDe}V##tWV;|f8?%6Qm;C#oqcsLoX@YO|;V`#~8-WCGnWAufrq5cqE%XL(fZ zvDBlVd|F(DHS;xI-vN&`!NSFT)esY0tLnx}s|omfBYYoIyI}Ag$LM z#kB23XIT2<ZDL)_e>*`K{C3=yj`+5qz*O9`{5x1yxm9`;|$1a|xG7~$CB;5iF zJObb>RSeIONrml@L%Ik1f=?~5MTSrbaDz!6iST=bbl>|K!hD1s2+sg+d;tCq!Z!iM z7eu7=9Q;P%SubD^*Uuw-{5($T@)ZtcdJKSPNK$vJ?Ow#q~>n!I=iG7a@$py%Au>z58M8EguJe0B{J` z+YnNC3fD%26jE{ReQX%Me@H@((reV`O@!NVUx08u!UYItAXFh#0zQ2dHr|#?NEO0X zgrx|Z5Ede=Mz|c|W`rt)_aO8>0;UkcTL?oDUPed|olH4D4(=C1TPUhKj!zme03k(vt|KJ6P#87`G> z(6m@P-4#)I)TppyJ=Wzl%>bu~zL}5bA^A;^e2&e{*ZN~)UzTc@VvLKeWZcYwHG8oN zDW*FzO6~mgwfXPYqcHNkPOT3s?Jh{F$%aoX!MotYus6tU55uS)#JI)?!l(`bEiD$C zu1jk}EaGyX(|FAGFA-@)+Z+OP;dsjhB$S|BZ7REEncO28}(zvbQ7T{!P1`~VEJlp)TIeUfJELrj5iqk7zT=@aC*v5fl zfOE(M`b+r+kkj;@K_2|!ziTD15vpX$&0a$-ver0R#SNgCftMo@l?f+f0TMMP1mR)A^>8aw>kb>sX{Sj?t4;cjwifILL64^sntCK7P?xJ+(!GiOW;3 z*{}Qk_3mnZVxGwQ1o&?1g2(3xtQ$-ZFJUZ1C+Q0oTGK|9lm1=B2Y-8cOFL#6LEK;N zBf4jekR1xxWLgZmd9JTiOtE0|p>K>W$Z3Kv`-m}3Z4rsmokgZuF=&rbd8`z>7m{M& zUM_wY)|6f^&YMSj2v)q`y~^H?J?Qk)8$gdCq1d?IB&-}XJ#P|pF&Xa~)9m^O8nISl z(w+9Bed1t?eL0_?*Y0H;+hDwpdi~R|_w$RUGnf}iyU)4U$JDAEayeZOCAZCklqUSk z>mheC^A*gGSd~CiL0J2)@$=4Iu#FncrnNwtYJ#$?;h?!OP;SN;)2v^NX}T_=bI_ zC_ycl)B~GDg4z)^VbD9$bdIEFb$^e@-DrAq`GY;jSZ4A;{62+wlGgh*eje;PF|vcy zKVajlEWLiWXB79@psrxpU)fRgqi63I6JtBhga9W_ipbyaEE>-?wuuNsIjxq$+26zd z<=yMgaGiNLj1A9GvY|yqCi$^2#G<3ozspiF}h zWvMn6e#Has%UUYEPfq!{I>S=geFDoSQ>yu9&x|Eve;JM-k4HfpEr5L})AP8ee6aU^ zD|rYzqUw_7z}xjt#P7!{XEce&t`b)C0)H!BvXmDX0)LZk)LJhj2JY0}qq79wUXDI- z^!btH#j$$xd0j|V4681We>Y&qn=JK_X()z{N;{}k<=#7sD(|xeqZTaGD}+vZJ22Al+OeNR0O~uZxIR7r*ZRP z?|^W^dfQ1wfvt3VWIJrKQ*t7_7lN17W$~6!Ob# z*SaKyQGKf5Xgl>pL8om=ynG&pb;1yCF1S=<1&M-aLAW45;AMVgZZKcK=3)(blPP0LU_a2pfX9R~sFwg& zzs8oR`a*-%@a;jpxhi*4F6TL{%DDvLxT}0l`*L2OQdlzVMmCn!!0M`{UD_p^`nT-K z_DYNF-VB#ujbO?Mm&B}OBT@H0d!e=@x%bkHCCpeyr`AQxWNgn>%yJ@O5=~7uNx4&i z(*W?0o)u&)$38%Kk?PYg=cT05Jj?RA+1Gs+dnEZx+Y>DM5wyYDuAJ&*5~Pr868PKc ziNQdWMc4iW?laMDe;K4bSjTGb8E*+`81_xemjpE9=|gmsH#yD)^bueTzHnsvImXCx z_$v>Hu!dKfd%|l2`^sbyH3F=4MIu_t*owGvlufsom)%;-tCgcFY&Rt2wHu6Klx@hl z&MRQ|I9O3+LwHR9>LP|!m52sdOVh!-q__`!ZTmw}yBqr=gs|^bi1BmwA}<4PMrj^2 z9deOEtxKru)Rd%%FWtbr#4b67eb%#BjoZ!&G6qd}Yu@C?0g1&3SKY*Qt~HZY>>kfz zcdm!UvWejHK(qg+!K=Kvy@Wjho9gPevg{F`!7E97-c19fm33W5VId8)bMgQ%WCn)d z2LQjPJtSFHD{CuGQtzZ+%i2_IpjFdHq*#w9eV4r*`ixRgT6j3@)HX>k;Jjpr?(?!s zj?M*UU@2NqIL*R$L(desr?*q?#OvM4hM<m(T z&S@89tX(Q$?`4G-sg>$IITXXxzX;V05p^r-#h?4) z$0LB9F||@$G2~Qv#kDGMDb&*`l{j6z5Z5wgc#YK@VZ)jA^pF+#D?T@?dctdB_eI!* z@&3M0zF|(B72j-M&NGDe2+4<|aGwlsGO{l835NEGRglFP=nk(#PYQ~tc{T@M7ROdH z@p0t^sAaNcR7C@N5V6v@3laC*Zk$7Q(SEl&M-U%g6Hyym9#=v0qdg6nAv6z_vZFh^ z#@{<@1@ZI?8tdVln?2#SyM5OG)EZa5EazHJg#T&yow#w<*owtDU!XSsox=Q_i#@59 z@VW?F7;0?$f8;SI=O{2QOD}-+>97^xJ!|K$DC?$A!fg?Csuc@YZ0c5n;)_bsz%%x@ zE>=X#(a%H75jANRtJ!W2w=Fc!U!huI=}v=v;lg6SaCp!(QtG`s4*Wa*Vqv`(Jo7Tsb=G>k?=gs2#ZhM}1v&7V&92d8h zy)9nwL&==m3D3W|HTU)lD}UH(>=&uuD%;xp$ct=$`oukac$XMfm(#msZ2U`eZhwCN z%9r3nByJBM*S-g9o;|Q!RK`!$m+_gpGJXnRx@r%0iF%`Jtd4c9Ro!kM4NvQj~+9zgTGhQ!DodBe~K6)y#;Z?@h+i* z|3q~3hLjxPMa4&6KrAt0MV!F5_$p%$-&t11fBt9(pPg8bk=yTNQtZC06)`u3^ek*yYCrRl=%ti>PXiMO+oeNkK!2P72vHk|3yJ z5`=hG=emt^?tz}tTmV1%Uih3#wOqHWMc6?5;AiwCAAJZ64t#SbguA-VA8%J@P*pP(D? z`omkB8LOfHW`>fx&NFo+F1k?ImC9v#nCXd-%g-Bd7iw0Ml;5sgfkm=zg;o#vH46>2sh;G zT4mIJzk;SH(uHte`WnFv8GwEZ!wQRp$7JYLvhe~|2prT5QhDEC?vvxxFQ*vqgV=Q~ zXI7C^|DxXgvOvY(TK+Cq-H&?xhTqMV6uf%GMp(#-LF(vmrteZgA661&N1<7bT zukG5|{5O_~)xB539?6!hWC|h4S+V0rBcr?e40{wB4Z_Z-F6N$t#;~hj^J@J9bSct_CirCd^lUe|`ks3tGXw zC)_v1emxFu9PWj7hcB3$?+M{b_$dEw{S->od6kTQ z2Kfw^C~H*;>P^cb`n??7mA0N>$gc$U<;X~E4t8o8#Xjc>pAvGE)I&zUI}3d+(3W>o zqE>Q;-Ab<04ZZ{VT%b+Kedm!n{#7Uhj20E2W%(_gSp` z0~A%TaB98akm;7PW4Sm-$H9;~8TcD3WqCJ=M&uE@ja)J82nP_cNBL_CbZ#k!MCp;< z&byhKIwJI*(11!M_Z-$wnOzdcSA|S_rZtRWTqq6O8825FUO zhp<|_Q^9@cmDj|viiQszVqr)<^^Yy6B-SukM-|~KrdqgD$=z_D&2G7@sDIdBr^Rk& zM(7vv-IJJ*ns}50l0Gx$Xq4QOo{-vnjp|+{XL1Kak7KR2w=)F&^F4SNg)d%z|6A$_ z=Kk)U4!#I&kyBnJx4?~d&6kW2L-XQj@AdW4Uh6Wxw`cXsy`$yM-uCGEx5g{9T*A*; zw5!_#TxFGQM}>QCqT)iyFYLc1=XBVayqxbN^}pR9s;x(u`*RZ zYlPKGt`udvpXRAwn0@`SvIg?!{*ozCGNbz!=)XY++l%)YtEXH&-51dZPj%DshVJ({ zA47>?>++Pjqtr^rf%(xpZl-gj%D+2MWE#8Ze`tyM9I(1 z`{ZZ&TqXB~i&C!txKjMRM#z8iH6qCVjX>}}|~&i4@o zta%haj1-z(6WBoDpRUdbYRXhGlOW~O_^?UIsn81>Arp`cySGI41fJBmj1&{rc(m3q zHfUTW=Wzvd=Uob$6+D4`#?LR)KKqz!w7-35eSaQOawVv*bcB-oA6nadiNChp{&u1s zCeQa0v{RRS{w+Ofn~&Otpth$+g!EeXDY=LIwKe}<+eFkh>rb_vPiqV7TXffox+)g4 z%;-C{ZB}wKT&e$E$9rghY(y%0SGz;3Sd6-*xs)}_fQLWoM&rDWnk}OxZa%ecjkFW1sBJXf_8lq#qq7~?o$ zXm}it;*7my>{>fUvHX43?jOgrH!7;`j^i0W{RRHzhez_qzkz**u`Gcu8C?Ygkl``h z@vAg7@8&Y-p%*LZ*v6P1hzV74f9K^k0?Q+THG&-pp~R}N33oEq5L*uFJjx}n!zh1- zREr#6Yz%2&ssxpadOFU7>Vg}DSdA!a-g2xIh<3c~SR)ie?^)d_tx|BG4_?Y{z8YwI zm{ru1L?!n$k6uz7QZtS*LNkNtF5<*i$-U$Xv9)7FoB3d@2@V^3zlrXqqb<-zYp3KE z@uA(p+&ldLriuR=FKYPv{8HLlBj|k2!vv(yN8PKbylIx!#>KyoM`l4u@7gR&uO@JLZ$(_k@q^gjXvoR#!Xp zXfL00=Ad5(szk-PPmn&fu<%gPM+KS^YNITXNvts*MVQRq+oIQ$(q}qG_a=R&E5x}2 zm0{K4{9`1fpp&tBRAKG#FOL}cltRlu!M*4k4;qz>tGPY}_qZ<(S~>B!$NUeeYRIY{ zR_V%`Nn!|B?-3!^6aKGO`@hoRejL7<=Y!=A*jm@&s|R@nx7Z)2z(=fybSZ2qR-^(e zvxB}p5C@N?YVaI`Unv@o-!?`FQUGbE8V(F|CFJKv7HjS=p z#_&PhBR&DNs7Q(j9?6BQ;9Vsbho=QTtjhuwoZE|26YdGmE&sX54&YW{t!0(vffb_~ zbh{`8YAvRmoV~@%!9}m+r#Dlbbi!2?({GE>vlLNG0==evTh*lC+EC(eyu-AD-aCAh zR?tytbc=q?a*O&i*?>wpR&vn1jGf8`TSsxJx8R$tvBLpx66_N(W4N)uv>yzvoyjm6 z?Z1(=jEDSc*Ng`a&JNQAA+;DS@d%+eEB-a_W=cxl&G=-rk5>lD5K|Mz3aW`U*v6C# zceHB)YZP3VFW4q?Tv{iq4RCzDky3iq-gZsQZb3yrt#GG&H+JmBZ#vcpMAhOQ|8zVe zq_(U;8L$pG=YA{u;AK@4_ypezO1l9=FoQp!ceL zy*)l>pwH2>-r(=^c{|`C``tW(8IMsw?$^6-o*)k1d05#_$lMkxxOlXLf}7wi!S5t* z9(O2c9%gr0S1MNcnB#XC&=>wbq~OMQ;WL4h5P7+ROY#!80(~#uE8i`J=R&1h(NAs4 zz(R~XxI*rbNfoHS%v*{y72dNW_BnE(>8z{_Di5?OxWOTsmv3m!omTHa>Rm&_y_&W< z=LHY6PO|@PHIo_W7|*h>4h||to^kcB}CQqzrNx=7*aL)oTV;VZ5AuvUCIX53HmpU z73_HJMzJA}Qv}TgCX`(a_oQ29%j1IJ0V<)L#w7hiI@rW_1PDMmcINwI33f2t16V8S z+TqosCV029|6~}RRf^+DxfC(8SYc&g9sFOo^Vy|r5WGTCJs4P5g3SE~2Um{@NaZgD z_sfDF=Htjq;86V!A*2VqtN(`ic%B0I2Cx%=6cT;T`&|@s<00E>Z`Z-{&7f&Jq%nL> z88rEZd(3dWss4B)htlSa2L;(+8d>Ork3Ahq5#mc`f5HhIO)beEOFk4gm!`Ge6oFVj z3?;K)-+3S9fA1c|x%U6ct#e2{Psgg~5cnfyb_o0Loe&9)&J8B`qH;AE!`lS9WcFWo z()f+1CB8HmG?$iSIFA;8Npet@r>Za#894~_}bq~b1nX2me<$Ta?vpfMkNJe7%n=a&Rs%EQpBq(HAL5pDrI z2B3KU75Mx&-~iyi@&5n!{sp9kGfL}U+^-B=NSAgBZOO+bLVE~%m103!k^SPY(pV-% zU?=Hs+Shd@qgQ|@pI&eOYgf~1qt<5Mw`u{eBU>S1RAE=dGW%?^OIVuLrJknMS=w#( zy{qQqeVOGAHlan1_l>hV4wm3N)Hh+@%5yz8u%F)IeEz_JRi+s53vqfUYlI|$QrH#V z=gaU7tU9oq7u{=HrCEJ#)w0!D>N(lN79Vr6rSJiN0p|@Q7$_ zAIRgx0XeMHPsg5IU7(#gF!})9C&&A1Idfpt0r8!Bb{u@HM+mw1Edvn;EWpOhfsh05 zu3E%nvbB)(r*O7J>)ZaTG^+$V-Yo;`5R2lb8E4Bgf6F-l+ahvd*N8sfG~Ynhfp=Cd zJE1+W%Y68*DAW4t_=q`nmQ_Uw`kn#hV}-mR-mG z4c40IS>d-08%@w|s8v^gSHL7_Dxg8JIM@@)ZkX z*;+EI=^afZ?BN7*J6za#vw_%q$sGjemR3<%IhEx|!<>RsW#s8~Cc^&@;T|lBV<+y# z`6r~~2)C#t3^JHktjU@wy8>Xr3NomIunNl4klGDw8ayY4aFYp!y)o=qN;E4XHN2z{oFhJH8Q{C=ZBMQK?sA{af3!`eHtJbKfMB6r#(qWeD zahSz2hg7KDF|u-FOdN1n?56YHRyUpZlA3UGJw*Xsbp^N59lndiMKsVIQc{x`_FoQb zqZ;0aB;%T91@vj{IZ3c%M2fLm+%XT}>f?NJ;~7mz%{Q8)CIR*@qQ)T3z#r#R^|PS+oYWLu z%T!XIF)?*PoQaRcxHE9C7r&pkaDQkWc98NBwk=5IUsxL~(+1Sc(qdL^Ou~#R>I&kt z{J)?Nv#=?kCbV`$9kKeKx6>FwTnwMoTSvGfUPw`*^seGa8%YACkjLR2v1)AEIsx`-dOFuOVm|RwjOc-p`K(}P94uUV zoh!Y1j40>e*@NP=M7t!-*~uj7@w|N~2{X-Gu6VX2SFnRnkJ(m?80@@6#X&W}wTT!P z4er2(O!o8I@s__C4czC&ff!}jgJ8u(12ESFa(&;ws| zDe9)Mq#ElorLtiGT~%O*MLp{vrE1zf@Ldau3w3jN9nOQWcYn$if%I~b9@1$(#b+SR z2?V>HuEg>Lq`2Ib&_Fzj!B}=KMm4m(tCN}%8?!gaB2c^TBmQXhdsR$IA=e> z%XJE@rWM>w7x73uikb);%F)1-qg<$upql2aM9zJli`~<9DZm$KcaX5dj#<*sfe`-yQ?M-pDj*(Q$$2q|6X_lI+_4WBhCr|?t36F z2e^$j#O6s7G8V8PV|Wem-f#0jS8qJ}3R}lUuwT@mT_6W>C1bNmXALdyFM#a2Dbf;I zvC(v~+UJzJw4kaNK;eqf58=hrMf>1Lt1dRHNyoKdXP4%ut8;L-54*P4`7&~jbl@ak z>Xx|_+VciRS7~gm`v`j=neyUpRDFszs z?x(8jAt^w(%n~Cz9#nNVyl=xgUdg1opxVI7z#2&0kjZrnwNwPk8dTBhr>yyGil4G> zLu>;VLn&)!boEkp3i|4~!C|`kR!J#4XK%1Akb7Y$x^62*+oO%3sEum$#5IjUHAg`U zBW$uZdhWtF6hT1_5)j$eVyZEnHYvCW9($y9prOw!g$=WnG6g5$DQALG)xeqpcoX|_ z9jGQ~{amfQP390uvP@CcK@IA*sPbhh86-876-tMQY&Bt@07?pK+b-vR^ns(`uonh4 zFpkc32SFF}8<(lhILyqbayfYOTUj}G$+r|#HL*#~?efX7w;$d^CSu%Q@?-D&Vo{%OD!3oh-q8m135cpP#2VC)xVJqg4x?w*9eT=mFw+COZxtWE zFKd68jY){YxZMOwco^J3fo6mzu}J_A z(9*S?>IRbdPHwpE8SR|?8}a?;RaN(Aj3 z?+JySQc61mN+N6|K|Fd?O$?}Fs7+aiT&x&j)r3)_P#u;$Z)IAI>GIsu9ZT0|6}hyhkPH|PzhiyfwjL5c<=E3dyp5xWv8 zMFft+yM&c#Xh$_Tv|3QS>)s5c_vm-~X!}W26(QBMMZG54rl5^_&`Hq93>cmYCL8}3rdBJg_CDWwFJl%b?@cwa*~@%>(W zAIr+?6o?Bhu}9z)R5I0xO-77(`n3`~(r+LY^dsU{dO@qS#~iuAldnvvjfDisjYc`Q zjXn))1r<%aGPPDy5nDHBFRU+jkvJ;9C3J`sA31^oln#ZEo{dbms*J_f-nc+18!5oJd72{ ztwMJZ@hI1TO76LFrA4dC8lfuyilZx5>~x!6!)i{6Cu=Y-U}nVCqyDRKT$%k>>P8*s z2EQ|69w|>|!{-F<+W-k}pEGjkwOXCuM_C|BikbXnE$nhcj~TA>Gdm&gKNdO!2)k_} zqDQzA@GY(>gx|UT5!Z3JmO#@&GMC^K^99%-ppq@!gN#ntOmIG2fjDmh=sxs(^Yz?7 z;F$?fRsI001=@-c|A)3Ofp4lx-@Z4wNp6x-0xi&%Qd4$X(6CxIEu~ypbO0S^K%JSw zsH8=u;Kl%sX$y)JnRJ6LAjK8Xk%G&B$Pfes5ogMXBML}mD-wvOvfP`k`JVSCU08Ky z{-6Fr(z~4HJ^OQ>^SsXQrJC?*?eE7y+AdSWN&^e&TZp40s z*(lFe@}+(1ug7p&oMT*Gzjfm!3oBCR-(JU2WtS7!2tTmgh<6reHjN2AFeX^opYc>W z`@zvm>ayGf9D(}qmtg^Ye8?WH?f$Y*?la7MSFnQt*cle#_i^L$iEd{H~JlM4Yb8_~mK ztWam;S$qO|_A`Mz^z7~c&6ktWW7WVy`vc*go&G)&6jvv&Tc-Bb10^2(Y52=l^ZtPY zH5l{jIZ101+ZIvk0^;1TsKXLPHJDtqle+D zyHs?nGGLBkL66U|j~$j*blqdh6Ds)ST+jH*DD>>TfiP-IIqca)qql3bdOYx2?D&^( z@axzpb6)D9%R)Og>H36w>uCz*H8T*sa)Q)$Rhvpp>HT-(Fmw+dGm*~aoiJYX$ZeGG z2*$1+Q$Aentrt1&QrFfrcQx0iRQ0V$U41-mN?e!X)P#;DZP8=Kg?nK1ZIK=rvq0*B zhX;%_?};{7A}xChph>Q@lL*&{$R-2HXWCaq5t%iFFX zn>XSVJNn+-f<*MZG~=~Imn5yYr8wLJo0u_RgaT&L>b8~W-2?oJ=<-`u14|>ldbIzj zx@4?P%xrVxRsFA3?SG3+><7Pb^#I9SWvbx(2B5Y)Mg&a}#tmmO)*?}LW>(oK)}v31 zwUpjjpU6H7a@!kI!|i?n=6cTM;FaO?8+?9MCUCdn^RHArH(&tHz@*?lK9&#o?w{o3 zEB(`V*cXF&01SNlCplcQ_yMk2cEb0G2z?$Mn2UWUT2V)z_6rRb4s8|RR(wB>F?SoZ zecG}^+jrz>CC*-?46ur}2euR`{jCXGDzgt~o7jSnE3>Wr=@)!bWLwlXv!eqm!0`G0&mnmrfd;UWG7_;5IZw9sAEkLA<2V$<(~>bgH} z<8sBurQ>O^LW2 z$JtCfmY)|*sB@jnX`Z`MC*dyb{MHQ* zdOpDuG3GDMTM`mjzK7nQZNa{90``R`OgZK%>cxIKdG8eo!tqoXqSJW`i! zDAxnwrat&oUQpiS?@?i?YPXszdLYrUWPW1Q>gZyzBDylXnr(}*{m)8JexIJIY*)n< z)nNA^s$7H$yHKscdN+Lkb-$y~$OZ@VrJ($Zf3lR0zdj7M$2vMj>VPzX@zE+xTX5>u ziJ^-FONlRyQPZ?4lBO7>={dv}UD;NREwL^VTb;(4j@WKTY99CZsES&RKCGlhNphu2 z*lnfsxHK!m_kRcLBshZdRDWJ!I;`_zBqdX&Jc)Y9nAL5{!`68UDG}9_#2_VYD#$uh zf(}?G9o|%fn2TmCdmSj*ZMPV~0PgS4TV_JfFMA7+&lJD0Y7{&C0K`Hhupl1x>kiO45wN=)jzZzqM{ zj>7y9Apl)jh!8IOMim;1g7Qy3MnvI#3-t{U^Ld3>=+(v%Eum4REia-C&haTqsnm#9LNLRdn{zLwq<$2wG#}|+VMlt z8s}$@oIXEmUgjGUKFWFn`i*H>{;bz0%*z}$Ev9mQ=7Q<-r?s#0O>3OKbsE?0MewzQ z@U@mE#n)^*rzs@lBPi$iGM4pH%jFSY!LmNLbSg5T#q{x-VeN-topG22Q!mXIV+=#- zaHW(-?CATWfX+}){FOf_-{lLJ&uHI{B~-RX_5Bfee+>}nzOJ{E!ewNt)I_Wl4k5ZB zG$L%5O$epCZ*(EWepaE_yZG=l&H?qU!)T1RXx@mptJ9@URVIIQ040On?x<=rEA^XL zEoMeRS?imAYCZ1h$~t~>oS9zUsu{U(?RYm$tWFP||{T`qn* zDV*kT=%~xX!g)IQtC#piZ>y5JKYZ)2Zo8g0X4ZM&z!BQ3Yxf)Vl8O5e6d=E5n&ZBW;1%ThlMbL9j{ zZ-1#~caAtDKYM33_4Fq8PsIpa0Hct}=lOA-3{FjWB=Y?*J!fY2sB;$ZXt&? zKB&ai&CL|uS`(~P{F&RNHMpZSLHV>VAAQ_Y2kZ-|r>k+S$v&Q)x&Y^sqQ1hOC3)-? z-5OqS>WgS6s0cmbdrEqt4s~IJqN6^iMyTLR^p!Q>0it%-JqUY8Roj3cr~0b1C!W2_ zbUd3-ubJ7H%|{_DF3N4<_mNIGymUiJ8YleXT<{~U?0m@pPr(ZnL!}O_H4d$ndiChK z>5@>PqN%{mMYPqBckP0@jVH3#WIvXT{ODfF)VWP!P@bWTDSX{MUYLlUdz!+P{uVoX zL#0K9#BM>FYJlRFVgJ@^4DaVGFmDZ8Y39cKxZcecdb~bAu4nUKkK(Ux&42x&J}0}s z6t-o494To2=87wwapj)+pxjm2xkQJ&Bq=(YpOS@&$wIMpkJpoZ$+Bc&SVKz|)|Uvd zr$Nap)S-9RUiDT&-M#fmFAH4vr2_YDA^6PreiPsO@iF#ELyg;=(-m{D_O&zvBbC4s zd+OHp3uZp`FX-f@VIOSmQ&#DF%nvaq%T2=!Z01w?eL?vYR#HFJu3ymdl)FC38qHqw zk^0umr)V}7euJ)-`}pMSr@qA=&(56k1#~Wf){#ll^n3nVD9$LR_yh8-;N*;x3`?*> zGQe16rF&qX`TaD)S$s(t;gZIu!}k)Y&&|)gLmlNhW0dQRQEm@*^ZZ%y>NuyvIERsK z()?-qs*k1xru(O1jQ1KUaMG$0dJq}W2l}aX)>y`Od#~QeJ`U>nhw!~Q2p&}D$@QJt z+aa7+=@MQ$e7i*8PN1*42YLYK@x2wFH}E07wcR zDSVWLY*Z)0*Qgfe-bL3JXLyf(sW`#;O@>E%7uWKP7VoLo;qkf-oc!Fo!tb_R|57=5 zgX?G1>s0^RU`-$t7S`;_={9#!s!(gjtUyp_1qapGFCXRlTs(YGaawzIIjA@s&?w3J zx3ahT-^zYxK>ii&%~X$;sF&fA$Ky;V=8kn3TLR0KItT6YrL#_X0eM(s4e9I1Lr|N_ zEj3E}nsqp9=gvE*thBw2U*F?bDK{$VW%xGzJN$X1o5Jrd$U{7Y`HTNn4%yPAgUVvp zL1iKK-n7{15S*Af48*92voxZE!>-47K6*Y48lp#Rc-9$t7PBs{8qW#9riI=N%~CfoYvD0`>yueLW_lE9FtLgvB1j_LQ0yXEuDCF zf({mSmH>&fx^@H6F#&%K$iEG`Ueco!?+fZHi8;i9V_?N7^MG3ZY0@;jOCyYl{i6|i z01x-hi(kJRkcS7chH$QRkI}Es49J6mh-cVj>4A6-n4jPrh!KWj)s&gorpCXYrkcg| zpt=To)&%54ylt%x$ZDIf!RwNAgzNo&j@kp&WTeIFiW7?r z#Z(GT#EUtDD-E8943&D!Bm@_=gD5t^OZ6YAg&nSb>uJnUxoVnggx{k#)OUeq-{!sR zbU=PMfYuCqX9Xs89fcLK$nI=JSS~_~P$E_?8D(SRooUi^)DNzXA7%pgyZdR>Nv`)+ zhZIjGSYu=+*lTY!o^=*rw9xu9(2uWor$_x|EY%#EoUUp(M-BvJEka2^4nkP7Qu_N*`fKtq&bgYxvY63s z48=N(upj!6Dy>)&kn8Oez(66t=suAql_|cSqP06e73A_>ecL(N- zl7PXA1{IG(9I&s^Z&FuRCe|~UTTd-L19ir9nrcrvejTG4O)~k7k=(x( zXgJ;XMS-hX1bAT~G=BjgRF6uItVmLHZKjtO}HOtQ&z%>%d*Awv}Y? zM?>;Uf$!~BY4Kfz?_mvc#k1oR&FYg}s^%zZ;y)P(&-Qq$WgCsb@OX2SOWui)-Swb& zar{t>oTCgn4mOE%F2Ci#Jv3V53>JPuL4O7o0uu%$x2L&luThg+}3x8Gk%V z7NR&_o8imOwnHZuXPFTXcBaLsjuelL>ydEFy^3%rW<-|BTfRhpy>yKJ@R!QoEZ(h; zzKGaHS+QRX>#Ve^!86O-?lZ1v`UdLvIHq>JW9ifU>gqrN9 zbRf@`aBaZ}H_QWFt|LI#)5t$wbb;ckqx4hRu7r2lG?Yy=n}xXUyjb^ck6Bzl*H1q< z9-Z|;M*4;04y541F~|IzPr=cm8PU?S=jOcXJ~!vs`Gw|hy5QVO%D}VTw7ua8ZL{aJ z>5v7dSLQ_!+ys}0Pmn#|Cyescng8agOP%4-r2GwMdI;5xXD82Uan5M7=fs3j=LVaf z^7NP)^qi&>E~Z`Q6BFj=e3OWfHNCf+q+-jx8TlE;qu+FCitCUiJ;OR9@=SE^?aL&+ z``xI8W42!&vf;nUwEkMPgc|Xah49eoEZEqG|c6Nh6NfOdmHDd9zLCh z*1ZtD)Jl|ZNPgazCNG;>4mXr*1R3E+!maX6b~!r7$xlh56b z{Mg(ye-j#3YDb+LYQ`uyi%RO{Grc**bG&e_=ZCkqdCm@x!FaA?>5WupTtD$#&(kO! zt`?^&)Y1`AIu5Ec<56SQg=x0i) z^a$^$b!#T-Law9ibb7pX#&7Dm-rFz7ZuoP~%#35_JERI8=P>j$o|8G7w;P7&kdvP* zif8u&RHBOK^t=~5y?~nR88+H;JQZbTe#GOT6G`JIpBsd{>d*2X3(9WCghyxH0(*ww zTWu?R=g@yA?xbE&j~+0;hSm<6+VCk=YN1?jh58bxW?wwoqf2j$!QWth=CJg}41TFq zWG?zES7Zvt?0}rAV7#+v(T@tk5-J9Oouzc4lPJC`E)Y$vQ)1 z--0<4klWC^Rv}rN(&Z5EH$3!Y4&t|d?ACH)iNBhXHN$w6>(K{Den@^1GrLkNKX`q{ z9H>QG)HU4*;6qjFAg=#8k=aSwMw6& z+@M$Jr8OHvO3E7ZI75+${nzEnJGr|#?l#bv^Pp7M(49Y#osQfu2(8Jk&o-39o0M5( z&tX22TYYDo$mTY7%bA`7Mx}8#a3x)_$YwR_a2^Y}Rd>kOU}l0`IQw_emZZZDBHPjU z>@4m!aYg!tHhG8*Ya`x-&}z7pbe59G^~*hqwr@n~K44t_D+wiBxkg%jen;i%^M5Z) zuEY6I=&p3P;>@Py8^vmSAL9yz=F>8(> zZpn4P_{!ZiapcY_K<}9E z5Y@e^GwV}4ebm-6`P@LXj=7OH%7TMuJvpoNywPMr`#Ouhkb5xy?D5=c_wn3g=dh(!{o>(YN-k-PN9*l+_W10V&vTX9WuI+I$G#{|Rh0C{`oqZn8lY9Y zUR}lO8)Erav%|G;Xd|~GUFwz7zstZ`uV(KCYi~vl*vwHUvS}`g-3g-sXI$WgXCROv z=SQfYOM-h&i>wFcjt5Tng0-zds##=l)U4Ds* ziBgv;A>BDc;)P`cuye(i8d=}KhI*0t14CftgXfJYu-4WW&Yp&~PQzLq4)@H7^tTB< z&p%W0Jg*LuJv-OW_niIwG0$J!+dLl3W{(73%O+ceEk#!97ca5{0kV$Jh!|5SZnDrU zv}a7&IIeD1I)_sP8!m7TwC~Z2(Qg&h&?$fG+(o^$z*|)1g90d46rBTFcR&GeTJl2E zfEUM0I_xoi>>m!qZ9H<3gmdT|kT$HYfZKF5;%oy>WsZ_|E47%7E#%Cs*1KCd$cb#R ziXiO9+EZltfv=QWc#d{xzK+|i96|5*CtNvb!4)9IwH)uhTYC%c?8TkO0!Bag(~697 zhZiZXEUqW@sk@b32>o^2ZsjD#{k2dd+@-9w>{iZL7AbXE=oPuIug;H8BD{u|;H;NI{opR3Rhu%Rj)G572@eMroR7Eg1L+RNL#{I80?x>H z#Tof%Hj|#W@K$r&E?`|bD7{2VUjx!=dADAGwT3Aanhx4$Npn?x%&4~NxX`iLx=mxl z>$W>m0%{UM?&X9Bs>0A=ljId^w$WEy%@nOLG_3pc2 z-DI+EE?FDx-%m(M*un?=up=QSTmf0wCc?iGEDW2clZDlpk`^J1CM&~+rLf*EjQp=d z#cWr^vaqQYHns9yVO7*}TB{Dw9kObLYE@DmXoLL?T($Dn7}cszz>aO$@=(~04fUI!3G<8!;Zrk7(qqjp zvT6ROZ6AN>Vbm+Mi3aOQ-7kaQJj4m&K7Ejy!IT`es_ zpDrq~!_%eMO7V6P436$bv_oHPWq%;JB}v8-kzMqO;Qznrc0o7OQ6sY6{#mRYkCSzO z6IoZkfIj;EfKZ7&C0CSRbKx!bXxL$)1#3;*6XBn;0PQa`fcv>Al2D#1^_V7t&*_Rz zmkfS$J@zu9^s9FP!{b&MR%@2?D`Hn`SBUJle!tu&z^x!uX8=y44MZCYkM|vYei?PG zvJai2E9SdmK7c)H>aC1S^chyCNP5H~R!~Tsb1d;~5Z-MFkB@|x;GpovO16o33;57^ zuV21^-DV!`7aVtZyQMh>vF~Vp@tqfI48F&VH8UQWu}fJ{jncpztQ4Pe{9aitvemwP zw5V!ad3}-%ZD=VzYpdI^EsgOL91=7CeF|7G##X6;qF=Pm|@y;td*PJMj3gkBuGv*`bQ93Sh{ z)%QCa3LS0;g=XOMwj2t*h;N#MIU=aE$a?w+l}1_l!l?AEK&5+0giF84L7f79jXvrC z{2|6kB^%qYHI2Aqy;teZxomAP7oq3qsU3>T`LtxB^hhC$4EOd6Db_Cc005zv3v2kTd&ubWLPj>V}2awwZyR@P*8|B z(@BvDSFl>*SPJgYtf2&WzsqWHifE@Vd&z_LHqU2Ov(YE-&mvrvb8DjYG$8RPdwx%JvMIO|J27J9EN9nc}Y`N1(`kA99lKdee}M_GU< zgB|nza9Ux-u`|#Oh{ZnVuGIF>fk5ABCdS|0@Vc&I=ccc&!Opp|Xv9LuIX|4*1xEd9 z6T1^}99%qUyl<$RRxE0E6WFw$vaA2sIImn!Qx+PS^+;^}u07TWek z1u3pUiXHixB3rKjP45a+ENUSkjgI@&erIkb)(rkIV(CO}`~v&=Ne-HY?~rytOKv}U z&6g=0Cxru)(Ii6CheBG1ke<9Mq`hiLhY$GWbzVoI0cW!E(1X6_CCtviw&D~3W(h>;V$Xi&%kl z^^PtymZ1D$6`j+7a{>8CNhdF{ghZTO!YZNIP^kg)9kBw9Z9-y=tcdbeV_=_C=qk$F zk}m_s+ycbBO%07HlrI&F{keRhoi<^yM) zT))lRAJ15O1?o69f;!qFsAEFVCN&@>HoIS*=YIrP5qF_W9;qQT&Er~d#|shM@yDYR z2^Y+zm9`IlKM7@lZ%q86kZAS;EaYiiB|JnoCkIOK4)kUV4q+|^%q7e))?f{Xe)ssy z$>)ZkXPbAn{QSUSVXP(1Y-`3^76WV9IsaL#oPwSofVDV>30SLah~Sv(3455t^?UQ^ z#H0@*cwP13Fj}|r=r$FrBNd!G@(6v2;B^C<^1d<<=3Yjz?S#YFY*IW~1xVgs0u8|H z7T-0$ex8bZzB=PicJPC}&mqLp+y=ruZ`+}sany3p%XZ*{PAk`~!!1q7r?VCEnF}oP zl7k<(70Bnk5#)13?R@)=guJugKmCUL`=<>oTiuagpJ6*nvl3uDt~E2las8Cd-S&xF zhrTk3i&5wHT#xu$CM&{i|ANQka>Vm5^u1b)ITVlI!4KYsc(`68p;1b>Cx3YQnC{=& zRE$wzBZEnGge=DsCaL?Ay*IdlE7X%im5y$NNu~;iOEQjZH$XGgcr^SL*Gpi@!I2VQ zN1j+W2Xsi z3geJur4g{w6ZLc@j74%i1om)X>gju0p}K0_Lk;^q<~D@tzHS+dyA@%~SFM?^V=rK$ zdKVTQ9FG`i#X=ZiNFEJOrqsqtm9;7lI8{Xgi%|0k*KWoaZ&zc<4aunp=XJ}(mOBH( zp@rlmiotR<@ZGd`)$Gu5b=tg-FZ!XnND*1n$4&#r{0)GTnU?Tj{ z*M;!M+t2ng^xobHXjJO|z3J1i3Q~&3v-?3ApI)9GgpdF~9%$~wcKwLi z4lu~?C(M}D1$GR{pZhk~(>nfoIHdEYIHZA<0f%qGAq{K+{grEA?*|-`4_sbC09$ZK zpZp!|IbVZAifkXe(1vkH16v+2;N8#Y-Cu}9&P2a*B@XGsSzf#k9MUJhuBPJVIOOC*J}O>(}CtA{*(yIS$#0{r<=Q9*6YFCj!^vkRsFgZ;V44Sc$*-7vYed z*h8M1;gFr!-75RUz;gV*42SH*21VYO?EhbJNCVc+H^LzeEZN^0hxEx412@AVMV9Tm z9u8?>m;C=34rySLf6r+H`yPAfghLwG5#P;lNCW1cI<(1|QILnGFxb)~>s;=aj&f{n#Jt2p1Q{_BN6>X>M&3dTC_yaelT1xiqpTLxfzS z{rg4%^*UrR08_w96f?AR4KOvUfhFPZgITmX)dRT%?yCoymSte=eH>QWAG*`qrX9xI z8~tMwzP6O`GY)@aWLs+CQcanJn+&3Pi$z7xilSINc7(#1B$pCJnw>YrB%@d|J>QH; zK7o?_mlyHJJb<|NT3z+J2Fh=ABP@{hBCs{+Fb2ce+VT4Je+*-5FV`4=t%*fOtUccI zc8p+aK8FDupcZV+z}}$0BG_6K+ZAlV))H8q#{g{2*^I4q1h!^Uu{HF=-i{G$&0K;y z>@_fl7uXu`BL}bu1N#%s5g6DrUcD3jzwdLmc@80G`tr}+niyTB!EfoWagQ=~RTxQ~_*FcDd7&z@~TKWfloxtKn7{RfMf05Hsjfn~JVk7GiFJ`A2mW6NB;a z3>H6OloUU4UZw%39)Pw1JyTJ(@r1KQ0cYz7oDGN@uE*M-<5d+#+2XE?vian?0M5av zD4T(8QaHY&lf&B1a6T0J@uv`0kfG2le6PT#h5Km$SD#Qe1N8sGDBG3X&nV~w;(9ap zGm3p4=-tJ@rYKF^&nWiE$JF+}z7F^E>y#UDKco02?&po4sZ;r(clHqvg~JyPXx(}I z0Wh<2?+W)Y;p;6N(Gujki97mrioS_c+RP7KqMjKG^FzOm;CbOwBWQnMr?&7zdv>9@ z6!@XQ^UgTGQqDPi@*Q5xpPa+hT185Q#6lP93@jy7rf{=4_%rCA=aW-`5x@&3w5Xbp zy~$%Z_IN(ch3~_!`|yh}y(L)7ROiuK7xHus)+k*=meyE;m~w$7nZHutxCSecFm7cC z<5n(Wh>Bpy3l1J5TjDTH+4=?{W> z_Qo~m3p%lV*y)Tj>)8sNBZzQBxsMXT5B(Eq%w%7|4ei7_x?vOBJWFeKD5)BN9aF(cC#G?Kb$<92?9iZRH?44&=;3n-I~j=ccd%YmfBdFX3pkF8XNKLv&)uTdCocj=i*%6MZ3ueyPC(dv zELf`(&yEK>)aoM6kOrkRMfqe2_?|UFu}=oarpk!Z!rY1sX&lP5yNfTO)5FBjA1-NE zP&voCK8OD;+D{bOr|2)zlpQY_ihS}QoKM&XwH(xp8mMJ~KT3U$O)^$Yhi)420_lyv z0#6nAuauJ(QindMyko1#c>bd6U7s8a)lI7_v+(=Ox7>Fdd~%dR9CEsbJ(tpjg*HjV zZZ;vRno^Oy#bSqQw+8n1jVBtS<2C0;WDJ>XE()vid5 z7IlEqk*%^p_3X9A2(Pr-h&_3Ii5_Q95u!B@^++Kuli4fp39WN~M)`6OJJkku{Ai87 z;z6j^sO(bgS^OF6jfK^EwxB7rbdx*Xq-Rf2Si~*WBD6_@d$e(U{QXH@`IQibHd$J@ z6z8sB)l_u{b!K2V@+1IXCF|rzQ<;CKT8OlOsPvyARQ!t4pOrT}&PPnadawK>avqJG z&k7M@J4Mp7U%}evT*UBHZIuigf#C_fCBpE;+9H^7+AIGCI-OS6&L#WZ20ZP07GqjvdAq*CE z8T^quFYf!R2%K24QAK;ZQIM%; zbArRbUjj;OC{a;jsCwX>yHEa5J-g1aVux2=4jz4ygYUINdiqp2jNe`n#-!#j3a$vF zR1M?1177)Qgphz7&u%0{laF z@_vAjbUo~HDmbc8EYh>Lkv1>Z|9Ysqh*XOl5%w!`XTZE7%5RS3a0=znp=ZS^vOqaZ z2m3Xg!^LV27Xe-H%A13f! zzT@!S7T>Y>j>fm;6u14>-wWL32Z2rFlktGS?VAeU9Qbhfi1>`30{@x#EW?L>fBIXT zi^u0G4sG()99r3bBP{!!^uK|!k=9g;clkc zebBiH^Jl@6im*LsUO_$OFXPW*ri8I@Sst-p{~P{n`28oY%bztfC#`6HmOpzg!k<0U z%%2^36@Qjve{r;C(CXP3l_{`MWimxLw3gRqDA_si5DVPS>B8yAy_ub8Jyyr{xK;YS zq63$dOTHHj+H+Q?%Ah^Nf%OnohZ)%K^7tXb;AI)^16x!qIs5SVF*6RMe^e3Rd%>aY z&c*}bx{^ct4Y-y~9NP2869hkeyuUmb&wsR($Qc zx^TLhV{7J+4^v~KSSYrpm_Dy1Ms8p49+mU^`MY7xZ*1!S!ujpUqRzE&e*b;?MmYP| zH^tfY?0ay=ns9bK+e?4t>KO;G0bY3^@Qc}+d|y3Vr4Y`pXB7$aAzsK3V z@@?L0adxalLN~_Qb?jK^m*MOk+1j%=!`VBs^0Typ*Rc;nzYJ$bzZ7|6Rp@`k*>%8O zZ-le!*yEwrIJ;M_Qf`K`>)8j5*TdQMY!p_;{|Vn$$BILHPV3*MTtHmGq!y^d)^|2@vGV<#K0#o2Y>011daO8GgQo%sAEU`%kqEaa3+QJ z^MOw*_&pyhenxCyejnJV0jrM9!Ig`2MZ_I$krFjq>mCbyofE-Fb?CskGlO%xc+CCa z1QXx46kOkvHm)1-S9b#|0Vfz^8h2aVcJ5YUu`W`${<{?sYk6V@p8?mER=!Iy>hka| zx72pa_6UZ6`BA>+6W|9l|KxhBTwzN_qLb4?|NkD^tHh2lPPX?UTwdGCmloZj@v@24 zs)YvU{q%e@t92quUQg-%i8!^d0*5!V?!GV%f42VD_oz7h6$;2O~ld?-`&5QCmhv≪rFh~A2zdcjPYShZw#}tZ(?a4maeAfn=So_YTIYL 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%0DtKRoE8~q=qSHd5O27IxqJipy}P)9)cyh% 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

        &o+TLF#N|MxPOwaYa8pj1W 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 AUH||9 literal 627620 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

        @7jFIr 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 diff --git a/release/aroma/META-INF/com/google/android/update-binary-installer b/release/aroma/META-INF/com/google/android/update-binary-installer index 2afb7f6cd734600eb9ae172c2bed738a50c9170a..43a2d461d556a0b60f0737e66f0aa2169ea9772a 100755 GIT binary patch literal 258772 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�R_f^Bc_?M%yW|Pp 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 z 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 XQaC@?PN;8if1zK6vF9K7x$gc4fXU@q literal 232504 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

        L+WIYOwnE)<_it&54it+ z^4owx5Y`MQHce_XZDkjU!N+}RI_`@x$3fq7r^Q*uM;5Klkr$OGEw~#TOK8sX5v<|< z2R>(cQ%~gkEG-UgXqdFUe*}@Bd|{c;QYa^S%=dh7HHkfp}G}w9eKX? z^~3#Mj82b_KBY3ShdjjhsxR`>CfQ+1jA>4-tj zmDw!*u0#97u%VMLddxj=Qh{8&F-&&kr^96NyH{8s164m4*iDeZa->U;a*(DXjr>wz z67pF{6!ZM#Ig*k4x|XdpG~HP`S)L}#GGc__;&LaX!O+1RY1$74uZLVxd|@3DnuHEW zL;f{A{8IY`PQ(YMM-WF3Nw7nvo_VY0t%k>w#n!t@?=HPWr5NY7VWzB572k0GyJv|9 z4(;2++$YRV?y>od&BVubBd|BJQU=e^F~^f3A95PO1OK4SC$tUs*MW0sC+t2W_PgYl$Oi zTIO(q&ZoY)BC7;H<|18=q{o0qi60d63Fl(IV}pqKD0=U7tl~>0ndh)sMB#K*0n8%& zixzW_;@be}WRB_DB|~V>GX(9xz5sC(V)y|CQSd*8y!idMAz_iZNJP{ZIZ3gf;RI{P z8CcF%k3;JnqBt--1bD$D1#3LSvp2dW?+&lqYfxjp^_k%`?N>t-<#n&PA9lr!_4|{K z^L@ZsY8K*g>bD0ua2A4>1H&D#Z_~AkvCAqYS$46x;)&8SzDz3NMI~h=VI={XRezAFm9%Cn)BlK`ZY+@?wG#9Z}1GtABRL3LWA%B#3_y|{Lz)VglQ zouwvuvYamSIi`=kt!u^-*&(MQX1_|^vLa)?p;gFV7i6uF8oShPLd5X90hY&3Jfb>% zruI^wB2U3y6S%`ySCub;o$z@o%MUq;^GO5K)bes8{P}e4)u?esD!lodgT{UCRiqoQ z4IQp=mmeyO#S~U~34FodqAWW>RpiNzzg{c0Pti8PS2T}TfheeYR;?faR)zJTnHA=Mw-8Q)Gn-BO z{y?G(nT#H0|X90dxHDh`PROJe=SN!6{nD09S|mpX*~CCGL{t z`2T`U{2hn3W`Hju+j&O!eH8)EGj9@FGG#?h zz)mz(`}4V-=zppSk1a(EAq4BeN26-)FtkuyWDMSfZv~M~s`kgx7gbZI)S9WsGd|S+ z^|Y_tpi`dp7nWBMv})cVQ(Ln3CH7p2!HrcL5f$du(Akx#bGkM(`W;B#{c5rn9i@nM z{pzdH-gmD3%xDeTZ&$fpk=MABwO>ZLb24IJtL7M3UAB&3L1$yI-XE<--|JvMtXld2 zb_cNc-|e{!ea3ClbnL0i(Ptg(5}g$e_rC!jJS}K!o2hLX5M;!RZCv~AfN39eDX+R` z;cC}8Y}nrE+QHF_F}g@y79V{Wqf>)Yn^oIA5*xFyXLiNHa<=!7j#VKf@4nIb7?Y(I z#>X`2Gt!u@5yH`gnWp#1RddR*Z_w#3l$T=MO`~}jXV+#9NOGc@UYSFfcnrGbSt^t5 zxq1}Vvdyk7jGFO#e$>>q-Axhmg;517lNODg1$~htvS(rQ$?hLUdI>3vM7HO3;u@#`;lwM9950j3y?p>~T% zCjwgu{D{|H7{{5N*sUgX&P0rl7zp}iP|a<^R*Gyd zJExTj7!BYu!Bw2+DBtDe-(H?6+UYSb}$|J z9HbZFzy87*D@K{tLqnFi z_Tm1kKeHa!j;$|Wzw*}7^{c9C)>j-WRebBK>Pqh@6`FB|mSgp@IhjHKtmm0sTLP;o z1))|UEcU)_qmOtYzpH!VgiCUqFFgIPStWhpN=2ur8bmM*L?*DtIjd8tFh zO(U)K8TCs2PG6!Af3@k{>6O~{W!SVAMisB2&8Gcw)ax}Oe{MA3H6ed?RP{24Nfq13 zUY17(PV@QCxD7pjzuGc)Fqnqu`sYEW7*u67%e}kwH(s9Ob0@A69!n~Jv8J}v;&b@0 z%kPoYzhwO*gD>P4e|p-c&5cf3`O{L`ORQC5esM4U!Pn*l#{RKdWQUQKVf~{f{3Si| z3y`wWMt^+w1X4BBfjg88Dy7lI?msv8A31*w=4o|ZvFB4 z%ez--$L@mc+*NjG=_6eidXm7iE1b-BXyJ66VLKrM!o$kO@JWb%Q7dhrm!D8wm;qY`hyf}eTjlpQJ{Y!Zg@VRbH0`#iJbTzg}1R=E|NwrP!{xmCI6 z?jCG7^`EZ&YLM<8Y}yY;1)LB3JvbAi#rEl1@1PYHX6LX;Nl~YlbDVt=*B*youxob? z*TWw0o++AfuozL<4{;JO4L1Ll8KQ1mK6*xA?<0BOmwJ)^5$V5>hLBDpy@d1t($h$9 zA$d}Iu)be6~=5YTNXJ^aB8N>b6XT>gG$%>Mv zHfYB$ltqTWA&feY?dcMakcG;&TUQSCTfS6nWehho_9wmeAFA8zGPhyxpa|OAQD&pl z0D~-OuSX-b8Q#z?`~92l&#q&81&xnQ>dKRy$A693fzBFCGIky#E$a2Ld7lJ@{TqGxUa|e4&(M|Vb^7c+Q{u(ql#&Hr?fA#DMD{1_ zx3pu=biK4Pq4lN8J4+K=UaGJ(-&T6oGy7?CQ3;Z{o6X`n!F|sB75KvZIx37NXTs!z0)c z&oZ@MD8H}Tp&tZs^C*Cfzs)NvAr{S~`(pWWrTui}vNw$ksabGA4( z%&E;V@JXR<`8U}&9;#IuKdar)n1H*OX+2ubY{6fV=-QtF%kQpTp7%^%)2yc4rdfv- zA8XBhCfYAX^V&n(W_8#bbN64@s5z|rrwe}D9G69Cb@L#1OjiB)&x@^YLr}2UerVXo ziwt{Rsz2v2>V%-^aQtww+O7BCLCMj7+Hb2s3lAC`U!CsG$=9J69cNDm6anSr;5C&d z!1>w(KElubW>EDW_Hmgn@%o1PZ#$EwUS8qANky0E3Z1^oS7vG5(fS$*ew_yw$d{a! zI{BqI`)cKjq|VuGkGa{2#i#As?!m-1soe-~CunQO*sKNeWvdL2T(0%hoqUcV2v1+j9D?@F=nPeuW5l=3Cw3%sM*CkMo1&WLNT><<1a0Z)WHr0e)V>5! zyu)|MnWfzkb(H0MQm`Xr!J$u?5~?+ObL(RI#2yy3^@zigd#0_LT|T?wP|aE~<*}^|r0Txq!W~W*=^sS?)^r!^^XLR(ZWI z&y^wDuW^GhDzu(@1(^k&Z$wFJrU@UZF)-g0r@M$ZRzxE~E}zzyD?Hb(nD9a)bV#hmv& z%>LAF+wR9VPAbXSu555C&XT}(5B%D6t!wC8Wp>{tAC>nGU0HTOFFiPPMOjEM?HXEJ zW~-&v9Ybr%Hs~e)(CV^~Ub=l~RavNxT7NXewA)5NIo@l%gEv=)YtPnB*S6r5R;}KC z{Se+|>7@-rT)Q2;FM^M>*qAnNj60_U#dc?vtHQO?T;nRg4f}VT7Zzq|e;XC|U0>sb zjg^AAu#5p%M)&7AtHk|>YD#vmH}MY`&NpopVrRRjYIn#;-?t9oEI;4aW0j5V%x;3- zSw^`U?SE*5Ir7Wlt6Bx^80LQm{+xU^*Xr^0!jSl=Tvq6Dl%;|0EMI2rHNKC1YqI7{ zr=7KFDEZOJof7VWAo(ZV`4amEoU^h`o$&cjVvm9J zH>6RdNoczOX%^A~Br|lW5cxtRH&S>-Oy`!OOnVa=OM3`&d0G*junhHY{XBN6XY7&m zUE)xG{pTe!+Ll|7KY+e>>ix}C=JGpAi|t+yvkmpnJ!`CFHkVxm?{d#_ZQYRdxG_EE z=V^ZJ*u7mzRVM6_XCQ7>qZaHHxE(@eE0!3xAyVo={VY7PW-YSORh{t93#nX9&z^x zQ~C#dZt6#hEZU;|A0duRqP-N#@98n6BAZZtCrUJ8*RNQQUmu@$;8<$;O!*buf=TjJ z8E=c;`!#$>qwnW#;g5=sI~8x@N>gW9%?@APjM;Ke2JLV09>NC=FR*#tCBMx0&hn?c zr@i!!O#c6d+4XN>zL6T^&;JHb%fH}x&%cFvOB^P>X`r3lV*`d6DJPkOW#`G3^12mR zrM))IjT53gd9c6m3$hP*)vyot2Yp0HtPRl^WHwduYsdC?2}f))ZyN0X%@;FPQWS?B zZeBr9E}P@Y@_iexH>%z3%l~WI&@`i*ENc#>cB*Td%WuQ;Wmh6@_=TW-%cdh3+F3$`^4ipJqu-Xb6bzu1G z8afrQ2eT@5fLhTjD+9%YNZi@8`AIFGw5w*&8KcvwOp~ z4c4+{_5#F^i{(kqs57r%u)q6DIx9M5jqMu>zz_HuUC-vBT#qvOWb(oOhG?{V>EgB+ zO^^qi^VwHo1)EF?(~jVEg`sC=rBcCiKlkvKS?Y{cGb?76AF7#IbsKi&hn#bPd&%(Z z8j4_ZgVR@YTVKskf6Hf1Sb=$nrYH6A4qNTPx;HYO@o?t}-_0cr869=3Z9Z1vG=Lp)pW6S(^HZpkaSBHs)$)JI78@G$UT#mO|uul{5*N&xCr6De8 z?E2K>&q=N5^8JPJmP2mqM;x~V>IiS&iet? zr8Y%-RX;Ow*>^gJ`dxiC`Hcc*pX@ajJX<%}FD$my^8!n~Z@1edevm7x3(YwTymt9i zA?~%kQem!4zXe;G*IGEbFr}U=E6bhre4&!Fz<;M_owwEdp7+_@zFM*Q`}pUoa_-NR z*6ZH8?)tUM*>lSEYge$JWB<4A`h)9oWyjiqg}4{DIdAy>4eM@r!Er5n(NTkczWVr; zODeC&E`aufPVe`<3~x!lgPX9~wU>BU+h4)?br}Nu2YjcE<<0NG+rrs1dhTbnKHmC9 zhM|euy0D}9blA{g_44*DzUO=%j}0qc`~`2X^Z8b+^9VcF&(HF2@d+Is&ru)KnxZ0J znqA`gl}G5{&G-9`)^+)KVND6s8u3E!xw?DmnlpKU*oJ%jNAJs6;`sr8*!NX+lW&#W zogoyg@ILI*G8(+iKBey6jIM@eUjR9?X$>vD_cAiKu}Aqr_VAWE*52;!d@ttnMkfDL zrq|&g=PZ1J_O(~9x*Gd{tINKw@!Q^JKf~?#i|)0{i#+#tVPD*0-;n34#qNB#|M}0h z)Eb*i&BiuUdtgIoLtgEzGtAAN5_864c+TBtKZCr9t+}rMiKE8ZkcRuWeP(D&c#Ibdi-eYF|3cU{sps*!XX-x4;0x}~6gpmTTmQ)NC-=-kyj1TI z+Dq&BveJ#)YhSC~ob}Lh8{VijYBBhVpGr+z8uZxmp5&U~IYU!|6@s`E1*nt@y5^=`IwR?vRGg5mJ%M#0zD(L0G zZFu=ab~&LkPp0|cU$v!C@@c=(-;F+idGOAXU5)q_9pF{v>)#v_KFX2?ezf@aQ)Z*cMZn+zh!rD>&6Pq&}tiPPT1$Djeq|cwh<_w{xd&SGXM&ErICe$_~!piWO z@oxL1@4hTH=j$N1mAUmkwT-p^Q=dlPbYG&k5pUOD@x7Im=B07lAo)SxE8YftNtFh8 z{&r81y}INrUq%M2tG~P~A*OeYK9Ae8y#8{I{tez&^s(RU???ZPc>e*sMZ=pg+<8X( z&qfacZ`xnws6`Hw?b?#G3g+0oB1Jvm`GfDbnFDpd#mQKA#!Kc~Gj3Q>?BcWTbrs9W zTlxIr5_A1C?z8V5^nB=R$b6&jqKrRm{Mh$Y=5uvdPCvGh;>RI#48QtgNmWTCWjUXE zk`T9W#IDDqC9eR%;O|JZV+&W^hrd9eXnrH^H|DQi?%U>j+O2$4WczzfMM(tlU`NKfI=(bf zy{h(Ob5W*g)=U@A{f%qZR$joD{zu8I`lsDry_a6MrtXH!%IVWKuG{GLT{-z@uK1(R(6X`gTXnpNU;5$-hIeQ;tk}20s;;XYFi(f18d|}9N2ANo z#xG@C+e!?b8TCf|C4sTY*m*zJVOkw;yE|jr#&6YaT5)UEnvKhSH$e)awe}NUQFVAX z;e|)Ui~EEDHm@T{FD%|Q#nwlIJ}p=Y8`>h)(O(F3xWDru%QelKq|5ZQsPg@1@@|^8Q`*v`3~l-V3RDPCpeW*`t)VR~tvoa!yEg@aw6IuLRD6e0 z9%7O7od9j3ySli`?p8%txw<#%>bfp!t5**Co=HtJn-Ud^faa~wOU_p zsE9_o?<-BOG=%RT%3q;E+#xIbMXVL#$W?yHq|AXxMHT8QkCah+WmG3TA z^xvXizZ&~Kb83nupHUU{8E@-G?pu+JDa7$8ju#Kem{uG|{4SdBWnsRjfn3O2h9e7y zUM!yR0beHHSC~D)T2XQi)OkT~;_s}#7S@Gke79jHHuhv{MH-?GUTbQ_b$oP&&dp>x z4amn&UNm669&y*i{-kmnyrT=4lb*qD5v#t@e%!FrrsyuT=NmB6i4Db3I~q{N=mDO8 z0OR{&?&$Fut6r~r5I!Mzcj}yeWYEoETYT_RwS5`Y;})M@@$?F|$65bq{a^L$++-kat@K!qL~zHO_XA-hVUDg^CgRt zarSxpyn1$D9sGv%lIQBPSYqQNnIv06a}yKB7}`hno~z_Azuwln*19mWh@VndI5C-L zTQ5X@d)`tKUzTSL+Fgd>$o^qJJk@3c>%I{A_I!PvSSRnjsYK9|pZb*Is{Lws9y=%a zCOa#BVgEV@4awC{ej}s zAJ9sv&(bO%kw=f>cIII{M59n^0En^Iz`-uDyo`)klAQP$m*h4lk5s{AJ$P*N~ z=wqfK*No!^m&8=gm{w$;8~%i*`-$eomzf$V8j-*DtBaGt_eYHLCb zvRC2f=Pg$7^U59qWoILYHHn{EFGJqyP-JjOv>}(Om9kD}RvfH<#wy?UX#E@TL!Z{m zTCTyDyJo|~G=@)JCJg+}{;K}*S{ZT%R@+Y7|7pFi#89^c>s&cDX0oEs4G;DmJh{Y> zRZjDF%u28~kIDU&?JN75)!D1_>)0Ic>cDCvzZ$k|I5G&oH}zy%)!6c}6%B}|uaV;E zOqU`2ryo)f3rq*kDf*K^0~2VVI;}0&AXa*pb(Zxjdr#e7{gH9l;obL02GRfhOT;$~ zY?O~j=DbgJ0sphE;=kef^s02MHx(MsT5Ic#;oE7Y8~Z@8w`u}%Y{MnUd&mk4LrKUm zp;@{H8Y{6ZA6~E_{EHtFz!#)leP0EzcH@MOS&B9OLd?Xwi@*DTzFBNh`FDz%Vsi@Reh}M@%pLO{h0T& zrZIZh8rKHvWGiFbZ;z{|xmElHb}selDgOKevOD47XdE-@zi^B0NA#3-x3TtAOh#oV z8f*2o6cOGoEHrO_yqNhYg;zrx*Vy){$!mI`+yrs#|v0HLXs=44y5z5P9LOdcR(;cKYqQ7G`ov-?i}gnOust zzI-~-Bja_hcD{$yYtdUpu9T7dm7(E8YnD7{DY z6wzbw`7~JieB%SqIcdP%IO2F%#-vNcXS&OY6-g4GrGn2A%8U}9&AX_B?;*nXXg*bp zQA9PwtG51ow$=_u5{F4&4_?OpV3Ukd?YYWhgU^rsQD31SqJ5n}CVN)+*rgGk&X;&P z+L!!dLaeWwPnDuCZcezt5|GuU}N}nChV2 z2(;tiV&u?Qx*WSrXFO=jt~c_FAos3?@Pt0jsasR`WF2FqC^kEr#{Fb1JgiAuifMk_ zb151#B>7KkM-DN@KEfBTzfCd!BG{rL@rSE8=xzi3rpcJ6 zP=15+5nOC=(E4O{)i(Qsr8^{lv#?L7hqv1&f0|#!Cs#0?b}MOc<4p2I4B@?li4}ja zM%S@)l6D!yx?(OU+HF6$P=(AzpXJy^?5hWDyf_lwetQkpky@{gm3yAC4@SyPNA0PC zH`g(Bw^U`ppP)U?FBQu_dZ{=W_)j{qbP-XKFn!v3)1p-Vriz1w_apvLh+VD*K2O|> zx_gT?{X2?PCr0D9b7&zf%shS@GU1hN8PGx(BO6a;lqB{os3oq^2yzMP6l^}scsY`-6Q-c&d9t^!*Os5zdJ3FU#4Wx)7A#9#ak|RDwi{FC|Jm^6>^+}xncL8$6 zQQjIwpI1S+tG&?56?x8fEpgn%Km(DUVOa#Vn&=x=25n` z7?6vu%!*G(WSq@mbJ?yzrvMjrbNum=0o5GNA9kGIn`No~@{#(L$x8|^RY zDRVq3$3@6U9E>D>C38U=o{C;+q^qN+NUzxkugdhBE%;jIR2ef39#{fJp zn@Jh)`tY+uV`JXM5JQEP=h-gAP>15hiGXj0eHUO;O1!FZFSW<* zb1jV8kfHCdj@{$5TaH`eBtJ|=LI9JiC z*moiFz&VodlJbQWiUW45<;U%|>%%jLek|Yfsuxt;a7DiDGxeDN&##28hb3Ftf34)9 z4r2a4uT0^wmm-tKK6lZ>dWCy&@myif;v#-i=`6=DA?2y3X7CL*&e&@ssa|T=<&fOY z1KzHICSPi=D^*B$OdqeSXQmnZ)UHX3cGx$RKC3ZcFGk$&Uc+8j+3Rh^m-=(c>MeHo zwRtmDc15eYMI)-+Vja6+gH_?)2T8x{5@dhcw}^X@v?C7xlhQt>`W0k{9z{&Q40Iy> zyBPF2@mQ2*-{;GiH*o$gj;C-Ou^*Kj!@LH$&%?0{B_E{_1@^VFXz{%2CrdY#-VUmo z>o@y!0*n11a&LmaB=TW>)QAAHN<$h$+i;`lPf z)ArK!7RRewfj3xE*f8SOq?2jlZ2r&1?5B?0pRq&_88|npNi`qeJ&v+m?3UYE&IC;} z?W=xW<&(hGS>TG`EkIfQ?N#1B3ZHQ0q^mgM@O!F+lkL6sD(n_F%J7~Mwk<3C-$S$; zMUgqSKMVVD7-X@&K3rQ-E9IXZwAv(F!-2!Xmwq0TL8k9_;#zT4*>vlR&`O7gR$_*r z#|(;EcyefYHMQ~ha83Dg=s!-m=4{_pezUkCihOVqr%6nH98-APcAe@Hko< z-gl&pTUB$oyu|CNs{pftOuP4yYYV%K0)Y|rD1iR9sazA9Kx6H6@uyDJw#@AbV9rN(gooDWFtqR{^ z;uGEMK8-07`SrO;7)4y~ONiWOBg@%m={?F z#WS#4O#Ti1W5uD!=1a=V^nPPmUPWHH$$DSub=dJkb@k!oi;RPeyq&3U5hs;eOF;`{Q4^F?h7j3 z%#Z1>FWXSD0WfVqT%9y9QGe2fzzQi(x$hP6SE6iUe5Z*Yig+*3|J#9yIAmelV97;b zBC5A%@di=1@7~N^$VeEBj6H)aytaiU`Pe_gbTQ%Ti#p6<;`^%?FRxf$?v2eJ^JZQL z5B!_KUx<#Jn-=x6lN|}JfK_I)Z<}1-SHHoc0k>3EmCj0NL)KFVwAln5B4o38wqrPw zF(gA~*LBr5mfu(*N_*DsE47Fvi*znzm9-_fU-8lG2}EonM}RWjtif8VA$La;=%*j--BFgo@em}ocMi15zl3IKa-6;XDxaI z?KH#AWY-HB9`ohMmv}eV{1RCod2q-3LTt0*2Gei-q|@lkseg=1UQHoOzA zrS}}>f{gJQJH3-jgE+C&Dptp$GeZsX^vN@)yMvK)=jA**ONU*D@mQ(Y^Mg7wvH#9R zcUEjJKV{v#_`cG3ycvLGJRN&d53R_x{}St7mm@2NRZe-n;uE}SFncJnY)~t*$fO;L zOuvY{wd~80UkuZ`fw=zL@WvZ`Zq9Zi|MQjkCML(?kY`Wiw>lbauQ>|ms9V>Ft15Ew zuEU(|a?HzJj+G9j`=rB-9do)_wl(T~@L-IFtt)NTt&};H6)wjc4=CcA6*gWdmpozq zVr4~@aE@qpZ2Sh2yPpQv^GW2Jn*E?ZZ$(lHpx|4QD& z7@f)p~=T$0Nm2C<8v1%@Hjjjhd%E%uD#;dX_jODf!if&~O z$$lktB-6omria^x##JyAqIP0JKQF=)m@unkd|weF9&$uQs)v-A{UlY4DMxOWbxdp( zu##r=ZRz37L*#K$K7gWMhxm%PA`*G+EWwd7tj4~o@GFPDjPm%K8F=^7wkQmkRPS+W)pH6AXFZ_%|Tv=tzB0E~hjGlmlOC%T5L&)FyP zB_&wL>^}f`%;b~ykA?Q53^Jy3C{lchF{(P%PRb>tdzwy)Z86z#(%vqTA*Jir8QqZ5 zl%a|IG)O6Bmre}XPAk2Hyr46?u)4IrE&cZ zy)4SJ(BhL&cVHezuhJ5IW6&FSA~xEwk}*TnrD2ehuc0 zUf|)#8CqLjhW4rL2hjHS`q3~?ubN&-E6!6_sQE{F-S)Cf2S$GLd0l?oi7Dk%Ds;Ja z>y+5+s&M9btf{lvnc>`FiYaO&9na6yL&HmN25p}vW`@5R;xU&SAO3ond>!KVLTDFh zPu$}4aK>d?%ZNlaohjnwZUuNseOb9*V4UO^^bUm&75&E19WBU z<;bN=B-_k%f4?mDUX+W$t8&^7xUL6$D{*w+8^zz?^O;h9*I3|i#jrXvxqn>6I0Xv<%4L3_P`ISP5(=AZ9-cvptI0lTN3np1%|yv&@)h z#<)%as4hpA;SFVjuVi3sg!88zGUm_eQJn9_@z=PH^4ng#zl7GhFGp^<5mM2C!ht*P#Ja;jt?t_E6b~5Ekt({{;J*!?P@Jyoz(l#4=mmSrg05LKDba? z!DP!?bnS7ibHq4k0jx~Bo9el7k;p^mbeZf)cK;XpZ0tLQ&iz4#H_fy$Y|dLXY^xr% zS=5$q(74u=u-Ccuk1|U4Yx;y%w6MRizKCC0l5DsfdFzJ+w+1V7EZ!f>?vKZcZQuhL z_6Ew@b;#%4R?oKWD}L<*-9D9z$%9sF??P5E-h~A{NA{amPzNL5pZUA8RLhqv(xOk7 zvaQ}4zdw0{cGk7Lxx}ic_1eM67iYBHskz^+mGAqucB5tH>e+nOt(#{j^-gy**uGgu zKE*EsS9wqc`Yr{1C|zug0Ui}Pq6e%hiWJ`K^N{k=c4s(9Irvts>p4@cLaro{SDRjA9=i)1#lO^vf{ zHYWEq8(X^#IUmTq%)N2_Bfop+{Lm*yTz4;<$%Xyzzm6CDEE-1i{F&Zv>sY6dQ(zz8 zF}*ztJBYuJSkI5`8SBdGo@*bhP;|X&pN2ia`s{bjV+Bplhvsi9#_mrOrj`7MJ-HM0 zx{LT{?K14SIA1ZX?j!T_dSpBI+$_xGuN7F&eZn8~$@?@Dx(qK{6rOQ8$Ia`pvsTfw z-u{{SJ+r!V0sndR0%5)Vy!o@L>B8I+UDu~otmh#E<56@k6s8MI_w9nNJ7PFzIBZe& zC_SH-VtJWUvbGtGo^=Dw=qbk)7Sbau&@4yNaws=Ey89#w}$pl8-vrU|NU zi|~8Hn4Uux>=xzMmL4~36X*QgtnON0=cy{<-!kV5O_u9< zd>5kn4b-+-@=KDOn(lpN)Ah=3mFq4cUr=`2h3oZ6SiiVNf82b^@MK*}^*hvZ$CGuM zNtex!RjZuTPn>IdiKa{0{b=<^=JOc6vMbJW7ci;pzDGEZQGIPVWKnrk-N((Jf)?72 zP+ff2LsCmhoKs5=R9`PBJ=06>uTplYJ$D;apv3ip8W7xLPjruq6Z71}VB=$&yr*Oi&{>Yh00`b~mKQ1@7bIM-o| zir2f=mCn%@@qK2KUIiWdkr`S48>TIO%WM)RZfLSlJ5yura87m4WVEC0iSp2!2F|7O z%mMwvz(EQ)AiZn-hODv$d~_5V;{u+qe$%`_8imX`rYG5D0PbY2hX6s=q#;O5qARIK zk9+DX_wcS^Pg-Zv;)R0B^?P8uNN5mbo@x5;3@JUD>SN}EhH=i6ZtsRq&8iM1PdtPD zUzXO-qxxx>8AjZX8Ft^>xKcB5xH@bu5|kyH9)l~*(;(P|Ekf4BuvzCxb|$*ACTFAf*jWk7~7zk@6mX4PR@0YAn#cy+#_UxE~#CdC$&fCx*gXG(Ne^$ z=^7~0dKT#8TEvT3x%*@A+*Fe&$yn?&Bx3sT>~4|m1aOn-!*?+h8!M2 zGx2y?1T>#lq69~!qMzzmn~7axT)Zc1;zA(-?Nkd9GY5JlMll3>#CImSl(-{vS%il$ zt~bp|owA-J*J5Bb9{1=D*J*GippF{XNwIqgoqCrH_tJ2k5W9!B-E=1R+=xu)yM!A7 z(RXHT$FpT|-P82xknS6WaW18h?z&O9%OLMbbp1lVSkSmF!eXh9xXuiBde3jl`ptFv z*?N^L1#M@zRG^zh_yc4$!F9LcLA1)@`7Glb<}n=!{Do}=Pj`Q0z8)hs3u{a7g;b^X)Rx|@KWs^Mr}o?-Xi(HBSrfl8 zr?yPy`^^jZb=9AlYfDuvFI&>xbNPkPv(2S1mnOLrJ!T|$*07?Qh_-GU*ZyGqcyF-nxI?03w`9V+))%ZI3U!dzLUYPkb? zY@OvnjCipjvHK2ab6xjcLR`;XLMjT;F%i=7p}ERnE?;N)8|3pd^F2bd1w7?mU-~yg zvnAe>0QjnfF&I%&Y*Yzd>CWkVA#j$CT1^&}>kgr*RKwc^o!eF#r*F3Cu%`PdFrs#u zg=Ca0VW z4+2@H@|17wVW`kTEgXV;Phq-IMZzxqBt4j z(gG)CLNZ3HjEz_eUD{_3mD@_wox7l;n}CxzNbtJSt%f+48aN_+Xe61=^JtSpOWb&g0Wvb->A(80N>gQru?9tr_wZ#rqgQ&<}otq_(^byp$W1{DYwJU4q)Z zwzM2HPU}_!Lsg(&l$(f?)E)nYw?+QV@S%Ba>0G`U7$F^#661NbN?eR5RPK~6 zg8bR?={&)H+}t3nFSVnewAjd!Txk;g1pAm6{Am*WPyPu0)ENA!(6r4K(j)3C@TUTP z_fNu~bfuR>z)!HJ#NbaF1^@0J!Jiz1KLN5t@N3-$lK3mK^e`~+E-+y5tSyBVgnmzS z-vg-LH6*%qp2L>7o@yZ#cZfGg%bzgcxj3D8+hypAXfi0~T<7 zX*{?h!9Av@4ARs9x{=mO02U1HKJ#shZKa=@_27gBe7bvD$qZm`9>2~qS(s6x>oMya z^g6c^JVN+Lz9J{O&YR29-JhE^dc9i(`!ug)vQQ*wN>pxrk47KwK4y;7uao-K05gP@ z#29AcM=;Z(cijlgKtJ=!lIsQX7*#Dwq1KXsR)86U(oKBAbt_}KCLxBSx#h}^d-ds_ z^zOMOYJqqKI?bbMnTuzW@a%gA4Wy>oqV;INC#fj97{8>uHQ<-@mPz0jGpxvQbAE{l zxNWi!pXTFvg5Xm?#konN#JM=|OcF|bjCVMRchbQ-dS?T)@B&0|W(fE%B$jC1I}E!F zTHv|Kk_>DqW7tY}ziHN%{S>aWoxopDTnt+Z=mpXRpS(P7ZyYG52IdHBni%HdMqzH~ z-(qfzgt?UNF~AsMjf-LKoANRL3+B`k=F&Xs7}m5`FsGIs(JmI+Sj8 zPja^zwyI7@@2RgMoZV&6yHp(+-5;4VdUP$yk_`9t@L{Hv^qW=Pwa`ZKJ%>sY_`{_n zbLkx!JwL1Z%>1Asi6=RH*^R3UrRq-N7ePK|=pPi;!9pyC@2>BjgV~z}??b-Zu-5XanJn>S%n0s< z_R>P@YV_&ObT?UEvmRq^xegTmn?cRPtFhbzOh)|(m1lPOXRtk_17}P2hu4ZI0@Y^kvHqkUCZdP{D#${jY;VSFi`I|Pe9 z3>_2S^BWu0PlP{wukei-tH$nrvqi5jtFYN5|ljbcd_@2p8(T zr{+0$qeL0zE~<_>dL6uj*?QY*O^?>q0B3SO1^^%b~3(4Bh6dZmoCs7*UrS@WC}yx~B6SuD-|3U!T`i|;TffpyYV4+#!K9Oh9w3>wT=qVoZz zG#@}4xFfDfT|A%Ph_N_T^OwWU;l5j-e zOOn{RFY6E0`jn2uS$byD4O7RR5OSvTsTus-9L&~P_jeHlWR%XlX z@`FmO|8hCIIls{-@;xQ@*}rH0A-uMXou!%jO@F48Q^n>CM}9TTFBXlLvP&3z zEfDX|S747AW}Wz@b9hZ1v+p{gP5N?&{AmsD;oCwU?3VAt&Z-=jW(SkZn^w3>*q-;8 zK_QH`Q?a*8RjoX58d*>D4GbQ87o+@W{-&K>z@U0uoB45e_m!Al*@1eL=b|`-?*{B=up3C$`h-o7Z({{*tW(jc?7}ye zE~iyR-v(nmiMXok3G9hTF2|b=@rHEzJ^6CdBCG+QJcZqqiO3M5-R)z;`~@~wgZC`b zddSGVG1z|3inYJl?m7?;SJveqas0JI>nZTcb5WSq;7`iTahM_KuG#WB46yD)C*z z2H}-cXC7isOYr!_pj_N5)`(4^N}n{2Q#LQY$$&!NQ6GVa`ukTnj!EN)!NGZhm0Xkb zz4b7CZ{1cCU;(?VfxaDyZ+Qb=`X+QUj&IX*LQUWTz8B4yyg`}P8)S@PFctWiZ)^$) zCbWZ6gThGVIPkPI*a}$1Cp;ms(GyZQy%;y1_0hK*y+M<)B=Ae_{Fia~Ha*(txC!5Q zo@y!yRN^`LH+!8`_&#PM$|95slya0Zl!Yi3lp9e>QA$vXQOqa;$_*$BP_9Rrk8&N# zwJ7sYicsdF%t4urQiw7OWhTlUC?=HYDAQ1`LBTh@Pftaef-)H;A7v8CM3glsc__Ik zIVjmEMwBd+OceUAI9TlTI20iBv;jqrl8&+jB@KnXQ=WnXRzAHH1?jD)6JrH@avHA< zJ{^yuMZxP~Pis)rC@K`fhXO^80nmFUaawil&CM$d*v9j_9){C^@$!DqyH%QK9Tb# z)7buE^n_+%TrATNr0>}(Fs{!41IgAT+^04tNaK$3CgW`iy^fSp2K8RWQ4pI#|3yb< zQ|J{s;{Jcq?~bO>OLPR!lWej^Z?OKq@y%Swq0|??HClkW1%R(m(iu1T-;!_#UIl!G zzNSzSV9LWWABFm&vB)qM`nE5@`OLixLpsH*pd3~i^8yHhe*6q41}CC^RM$YpB-s*! z&>5$gn)c9bQh&?+kgbeL=mUniIfz#ZXD9%30mi378#iFAG|n)|AMPue8px=$NzpFYgD(gQQ3+QA`_Jpi#lrEroa)id@i}KI6IA@t9 z!G8=7?`Ck+G3`oajSV|R8Eu)7>MRMC8r#!kHQPB3?LZGg&X@YjY)v8XFvh(+2su0Q zEoe-9&kr#Rujwy?cRbM3pM!7*aY8R@c~m)Xfw(dl=;A8 zBF3!o?FrEsihSN+7V0W$_Jnk}$B27E`(-rVn&4Q#n2LUQA7sJ^JOkGpjy4?W8{a09 zmzYh<8#N{Xsg(gIS-3YJyhZqt8TW#2Vo(J<0SCczfRkVzi#j}LMs?U&oy(V_bwa4) zb0bd&1z)LRIFmCJHp4DL_mNFyZC?Mf8b`p6{%!;Bk(|n*J7FhNU}M0?OM}TcDvUP= zK&KQIW5u|VS*8&pQWHdl43b0Au?ypvGstES-WY334IY{iYlGVS8vH~&XlsBBG~6P> z9>Ihx4RTyNUa{V;v_Z}wGwf|#6V98I^o$X>`Vue@KakGIA)Y|Luy03HkQua}5gqr^ zAU%&kWpIE4?Lh|t&v<^M9U3PCej6VfCv2DmGmR5=NK5tTo9(0%q;c9XPTS4mY4AGq zHO6o=!HYlW>8-DvqA{s4rpxa~#{_;pqQ;nD-=s1970*zgud&1n(Pzp=(UJu%+hTO0 z_6|Kj^_(H;h~F5rO*Gv-s!n-K{@O4`dgg&H8Dj-aB|S_ut%=e!Tf*(lK^8g)_E^ga z9iZ*9AnY>mw#*NjzD>A?jfNiT2P*{1%Z%GYR$+T+1YdWcPm%?ad$OI1 zC{83_N|JB1qY}LSv!oM%Uj@dkN1LxezYhQhbk7zW_X&)fc$c0VZ97Kmisn(eqO68^ za(NIwMuvjg20p6Lma@hnlI-2X#N;2iljNUph>_#HvX zc7iq|c8_cz)37`MKkW!?pcecNm~IMQi~40gI$srptYvUE@|&0YL6d8(7%TBP`4t2+ zjVmdJL&&t2bpJ9(Q%GrQ1kIX4{hWoMBfp|*BXK<+a?isQZ9p? z0{)ar=4QXr=FKMAN`yVw0r|4}pz|?Cm9be=nYN0mn&qMuazy=rr>~6X4D^u7u}dVr zfF01%_=D)Lv;n#Z{Hum8`uGy+GX z?-QN?1V19vg4fR(ouSm4Harh|UgL#mFDLoYa2SUYbkjj+=s`Dvi8ID*JhxWlIM^5? z>i8hnKJ@QfD-y5Kb7TWkecM7BUz<`1Ux4I^aR`+WH3T5qGM^==gvrd=T|LwxFz#`G=ZjAvXSJ>Vce`%d5={!tL} z3g6oWesqO4W2{PXo2c|{6*azHu$#L=%9=)G*(?uk#yH|JcPjF=hc==f$-^=ZzKikF zKpgN;W~BMRC!sOET#?21XXzS#*lzM86`WI|IqZv;e9eu(%Y3xKayvy?&06s5Qa|}U z(AQHK2kK)y#7ppZ@n*2)emQVlM9+EKr7?nrxqlfRo|Me=)!&=<*#igSoB z0^SCC2K}r;f2?nvD08fXkF`$R=x7S9Vlc18{RSWS9nT4Ub7uIjE>_| z@B#VWxBkK#oZo=oOzi_?qi`>OqmTTt?a*0E{lL$ZgV2@ghP7gm*p8UMEq-}}H(SX( zCX&7&+oY`7Dc%a+P}MXIP@62jJs>k~4N&|5*DkhTO+Y3#29!0AiRy+mBH>#N9H@Z< z;w?GTEVWfZZ7}Tv4Ei2vOA8(_fyPwtQZ{qO#Ow;~1YSnpXLF+W@jBMiN@!Ub%1_F3 z4axIzNuG_s6VU^Hx;BrA>Ot6Kt<2~R7J$xVt27+hvn4^2FUGj~*;Lpqj@ypdNK;6I zqNifq{yhAHBX?jPgn1&eewPFls7HK3x(7J&lZ|}`V~0%$nn0s`Th#8^w9J`GQwQcM z9iUf7NcCz-U>oe?R@5ilKFgK(=fh5t95mye4ESk6JsE!62zhq01)|KfSF~YFJWKs- z6MKDa{%4u@{V$l__a8RC?{_fUL(RVJAt%~-0OKmNZ4YfkS%tD0Wec9Q5`cuIM&EE>F51Z?b|P-yPDRk2vrF z9-ZHU`6iyDv5btNfZGS%Mf2Jp->;0_7yjiw1Ny0qI|H{~kN(C0UR=jCwpNsgGSz99`kmHMW1rx?tv!T?$9pB?vN7vDDh48E2rYY6U%%a_zQc* zJn+SXxGuwWKC@lAXT-g`aIXmWibRT+;90JHKq2mijJBYFzu_0i!C$wc9{&>d+hEdk z0Oi*xrHdJ+2t|*4aI%XdHc1CNv?~Yg)!Z0pnn`nSNpEju8vwt}8{7;XLU!kuupt{c z=w#>-*0c@sur#<4x?!`eDHN6e?XU-uZSuo@z$L2*${njk=>I42`*RGp)w|iz1ig;> zkUyExCMp2KRxYZyH=!%lLhwlowa=WB%RZdGc% z4l&ic3+**33ARG?NA_+NU@pMeNCL;No=UFeI!1RUr9mz)7ium!0mz{E9+@_&Ix2Y5LKFrls%w(|;1 z9AM%IrsgP2Tok59Nw&d@WWQ*T3ALj5H{2W-YF z5jGikAm5iUZj$IqZ6t!O3VIInBNlog0kD&8CI4ZSuPM|+b1vYJGqycV?^FjuI+dJr-S?RwWK9}5B9N=J6erY`a zrOOUk^z{$4@AAMlwh!Fqh1@wy0_+3L0Uc8onBdzPh-;`9HO}^dtzO8gqkTa4YLj?R z!|<0!8XiIXZ)<>sf4P~SGrl#TVwwgH8$a>W@58`9%QXfLb4UGJ$gWv8%ZgT}<-v?GxYK3LmFAAbT9XbG|2ZglqS+zO8{Hz9#=>4mk9-4{QNW=pO5> z2F(n@MiP)UDL2<0(+=Dz&DVe1pQc07trH(8F)p_tnjOy-fUSzBkt`1 z{ZZf89m+>t6Fn=SAJd)?`4aHYvA)5IjIBH5;Jp54IG10=+~m)O?6Afq0j#NL)o5Q1 zTq=5jPw))euv28bkPFjs@cvT2%H&Os7re=UF&XjU3`W=~vcfX7z05yyAMt<;2K-pi z3!l%1_@nLPkOJo_=2k!S2*o52-}?W@fqBMmjexP6xVpq-3<|d%_Hl<~AJvk5+yVQz{wM4sp8pB^sBVCLY}j$d zKGwk|kW5X6ud&$&*dTMPu`}Qw})Q@Vg{fVK;R?z>NF! zjNFIcFh?i3Ab2>~NrEXAKEPDaUL&?jb6mnVCpL!i0UOOl$@a6_CBas>PNY+aZc6ah zV}Okv#V_nAez_Cv6@XtA;A2_ujsWo{D|{T1n~sO%;JMv2kHWPgcHM((Ij)tl>rS$h zxK_okAH%g0*Xr2y4qU5nt%+Sfgljdf<6_r$<64Vzjqn5Ha3^%eGQSM>Qo*C~;2YT9 z-3st5b>yyQC|!EHz1~gFw$>Ls0-fqtFZ>HHXR#a zg_=-0@MNzc`Yy+sFLWQyY5xA-SSyk>Y#00d(0{&LLWuDV=xmDvd0cZK5js#+1AUg< zBsMyM8_bAB1@7OakPF#=#IjbwF-9qH<$vg*-!UY$P`~2ccWw<17tAMl*DPR{`0Cu9819 zG@OBQS_hmcm|L&-Cx>t^%72*48Zl>mm*gzkz7BI-xo@4w`Dp%3{a|g#v`&&S9sGFm zLpfh-hdCD{zgqrz_9PasAM!YZ7ZBhaF295`49~QSl@*%KS6#P zXjSBdf6xFr8y^v^Ch`y7m;8fLu|1T&4gP^iBa*MM%?G_jXB1i!R>U^DPx1AfTYWPKPX<+1qSgZsR4 z(ye6U$q(2J+e1DJ&EHt~b~fOJ{4T=tGB120N7VNs{7U|W4>ldTTyA?rEJNF*$7Q}_ zSpR`fW|NEDxB^iNAB}vCt&G=CIPdlK0Pjnrc>fE&UGS5eLcONPXdMIj1&9TpJ!*$! z7x61C%^?|@A7TzTBF8j8Bs)N|dr23wdBF7*o7WJv1^>?GJ^c=35%!L3q|OLiz`*7) z(C?-LAvM8t;#{B7kQr*xPwRv2#B#%o79?YLc ze5oSfg!rO2m3*`J2M+zk6WV4ZzVrrl;0M+RKaX<+p0z#ZXKR~8Rs>#|qXSCPZ>D2@ z2c9Fp?J)Bu_@sS+@J}+q!iQ#U<^bVM$Nc;XU1_dOc%+!VBrE8jf&UJh8nkiI-{iJ` z4A43S)+Iu;zReon4~@;tK^;~k|C!d73CAlg4xjmU4dzeiPY)RCc-|L_c|J#y^u}Eu13Jxw#AEe5!;>)@&`4Jbq?|;*^Q0>e9M5w zv1hy1(Fi|srC-(ih{&PN18A$jxF@6)y?(9j{QC82kUxr5zqTaj{)nRyLq7--EM%u)>spLyAfRlU)`b};;9+F`m0Dm$=hHFLa8a6sZj%#J?8gieZ zz_luNy#d!sT&rW(x8YiaYfbF>XSi15Ixcn%KQ%*(bB!(PM^K;SM{q{+BbG>h1cUP* z`w%~ud zo{$~&?VCNJ$&fqAegFq@pVtrFsH9j3t?jVL<&%jHQP$fxz&bw*F-G$D9t*@{4)`GI z$iV}oN43zIc}!zq8=glF zf0Gpj*z#3=MuZ&{5l@1>W1%-F-$aT#VtxguFN6F)=)LVK=mqM7^qkGv6nYmjN;;k3 z!1}tRCzCE9M#f>S2y}|-$R%y#F=o<{cr|6lXr3isF*>&y&9k>&@k=fLN1pA%7>Sph zIO;^=&!0;?%SiotgOu+=YYnR!NdF`51)pbRUL`Y1a~w%trci&VLvdT)*ahC}LOc^P z;%G&j3O=xdd|>OSxnmdffY*Qg@5J+{@9TnHL*eY0EA5ncUL(yNcY^2bB8~CKu~j^e z`PCI3hi^-Mt;PY~ckCozS4q#@4!j*DKJEPsG>h>8?v1{_m#z!o1DP5@cZbNDJ`2gg zFQmU@v2*w~8S>aU;%6C(*m*t9m9g`+I9J8aZ8%rQ&TqxJ#xx|g2~o&Mgf7GUe>XdS zHTndvIUf^Q^cTl@TZlJcU$+yVfOlJTCU474m60NpqLcIxa@%|4+w(-jzgW(3td?8po$_RN?q*9F;hd9#i1x z#Ziu94~{Y%NskpEikS~jfCYg@<{PB5uFN@VY66!YfbRtzrG}1TZLsa2B|B<8ju)_w zW!fBooXk>!e(vSG3gIpWwd`VD=^Itb3|H4G;;KU?(?PA0Xr=b0OCuFmR)F39bTxQ7bbavaa1&aF5y z=wm&O$RpOKLPn{*4>5j)sRQd_H~TTp59D+W`ziH>oUS?OO936FIZ8g~62A#;5j^wJ z#x9JNas%$iJvokF;MfG75ywSy+M2~?kp-R-XY3SJoYzllYML}1$vDIl;X8fEGP^Y*AFOKBAY{wWV_C)<7uNU;ZIXH;E&t4mi^B%!Hg^6&tl=4zD^cWMJ z!vcPAH(ujSxLN=jn8XgLZNy_k(~d&^Oo(Uud;=P^JuM&CfI)6N8XYh0(eDi1XSM}$ z&f+K@9U$0p^t5L1?m#Mod?Lo{|BuM<8R|3D80{Bpxvyb8{SB7+C2-=MwH)K8Jirez zHWp)Fim@P%Ch5^m^rQ_P{`m7ys#HEcYy8zzH5SSVO_;2K8D=3_E2kPBl1U(lWAHl z-XVH}zcMz83eX`3>!z&H5!gDjR?Gq}Sm@;JFF-GX8}((}(E)0cat5f)6pY^lnIfDJ zt+RE&3-j)P2Dr$63vF@m<$bUJdwinZC_ax$_$1ySz98S>IRkRg&=&Cm#ps%FPHU9N z`#Fhxj-X)jegK@Dgq;sMuqNfh+SIG4M>M(k{Z+g{&eACEhg?93m$?`({{i?roc#fO zD8K|fLLUHrZ%Yov1bl=GFZubWIo|>JLiGD5(BZES7#*;)(pYu{$nQusHo@O-3LW11 zfuEj(t@S6P4ISzs+t7aweHWNWeuyV&-5NtAQpC- zVCKCCLaf6PAliau5ck*?Fgl{NrTHtt1!2=-Ebs%Uucdy-dm8ye1ñ~~=zoyPDt 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 x`+ Date: Mon, 6 Jan 2014 21:43:45 +0100 Subject: [PATCH 113/215] Aroma : Hello 2014 ! --- release/aroma/META-INF/com/google/android/aroma-config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release/aroma/META-INF/com/google/android/aroma-config b/release/aroma/META-INF/com/google/android/aroma-config index eccff5237c3..deb50b8b370 100755 --- a/release/aroma/META-INF/com/google/android/aroma-config +++ b/release/aroma/META-INF/com/google/android/aroma-config @@ -34,7 +34,7 @@ ini_set("rom_name", "Glitch kernel"); ini_set("rom_version", "N7-AOSP"); ini_set("rom_author", "Tk-Glitch"); ini_set("rom_device", "Nexus 7 (2013)"); -ini_set("rom_date", "December 2013"); +ini_set("rom_date", "January 2014"); ini_set("force_colorspace","rgba"); #ini_set("dp","6"); From 889ddfcf0e4565c351d2180bd0d23245aa150128 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Wed, 8 Jan 2014 10:14:53 +0100 Subject: [PATCH 114/215] Aroma : Updater-script changes. Fix compatbility2.sh permissions. --- .../aroma/META-INF/com/google/android/updater-script | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/release/aroma/META-INF/com/google/android/updater-script b/release/aroma/META-INF/com/google/android/updater-script index 164d1762227..343a18856c5 100755 --- a/release/aroma/META-INF/com/google/android/updater-script +++ b/release/aroma/META-INF/com/google/android/updater-script @@ -268,6 +268,7 @@ set_progress(0.3); package_extract_dir("config", "/tmp"); set_perm(0, 0, 0777, "/tmp/busybox"); set_perm(0, 0, 0777, "/tmp/compatibility.sh"); +set_perm(0, 0, 0777, "/tmp/compatibility2.sh"); run_program("/tmp/busybox", "mount", "/system"); ui_print("Cleaning up"); @@ -313,7 +314,7 @@ ui_print(" /system/bin/thermald -> thermald_bck"); run_program("/tmp/compatibility.sh"); endif; -ui_print("Installing system files for real"); +ui_print("Installing system files for real."); package_extract_dir("system", "/system"); set_perm_recursive(0, 2000, 0777, 0777, "/system/etc/init.d/99glitch"); set_perm_recursive(0, 0, 0644, 0644, "/system/lib/modules"); @@ -334,18 +335,17 @@ set_progress(0.3); package_extract_dir("config", "/tmp"); set_perm(0, 0, 0777, "/tmp/busybox"); -set_perm(0, 0, 0777, "/tmp/compatibility.sh"); run_program("/tmp/busybox", "mount", "/system"); -ui_print("Installing system files to be a good boy"); +ui_print("Installing system files to be a good boy."); package_extract_dir("system", "/system"); set_perm_recursive(0, 0, 0644, 0644, "/system/lib/modules"); -ui_print("Do some useless cleaning in case something didn't went wrong"); +ui_print("Do some useless cleaning in case something didn't went wrong..."); delete("/system/lib/modules/cpufreq_limit.ko"); delete("/system/lib/modules/scsi_wait_scan.ko"); -ui_print("Try not to destroy your old settings.. too much"); +ui_print("Try not to destroy your old settings.. too much."); set_perm(0, 0, 0777, "/tmp/systemcheck.sh"); run_program("/tmp/systemcheck.sh"); @@ -365,7 +365,7 @@ run_program("/tmp/max_oc.sh"); run_program("/tmp/edit_ramdisk.sh"); run_program("/tmp/abootimg", "-u", "/tmp/boot.img", "-f", "/tmp/cmdline.cfg", "-k", "/tmp/glitch.zImage", "-r", "/tmp/initrd.img"); -ui_print("@Glitching your device"); +ui_print("@Glitching your device..."); run_program("/tmp/busybox", "dd", "if=/tmp/boot.img", "of=/dev/block/mmcblk0p14"); ui_print(""); From 3606227e619d8809bc2ea65afd8b4310e1df50bc Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Wed, 8 Jan 2014 11:20:28 +0100 Subject: [PATCH 115/215] Sync with exp_codeaurora from cb93e880ce6c0411127cbc3b39a1fe5ab7cf622e to 43c515720ea5bc5de49dad9a62fb00c154710985 Signed-off-by: Tk-Glitch --- block/blk-core.c | 13 ++-- block/cfq-iosched.c | 122 +++++++++++++++++++++++++++++++++++++ block/elevator.c | 1 - block/row-iosched.c | 51 +++++++++------- include/linux/page-flags.h | 1 + mm/page_alloc.c | 1 + mm/readahead.c | 3 + 7 files changed, 162 insertions(+), 30 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index b57ea48cb45..cd37dea6772 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -1086,7 +1086,7 @@ void blk_requeue_request(struct request_queue *q, struct request *rq) * urgent requests. We want to be able to track this * down. */ - pr_err("%s(): requeueing an URGENT request", __func__); + pr_debug("%s(): requeueing an URGENT request", __func__); WARN_ON(!q->dispatched_urgent); q->dispatched_urgent = false; } @@ -1123,7 +1123,7 @@ int blk_reinsert_request(struct request_queue *q, struct request *rq) * urgent requests. We want to be able to track this * down. */ - pr_err("%s(): requeueing an URGENT request", __func__); + pr_debug("%s(): reinserting an URGENT request", __func__); WARN_ON(!q->dispatched_urgent); q->dispatched_urgent = false; } @@ -2018,6 +2018,8 @@ struct request *blk_peek_request(struct request_queue *q) * not be passed by new incoming requests */ rq->cmd_flags |= REQ_STARTED; + if (rq->cmd_flags & REQ_URGENT) + q->dispatched_urgent = true; trace_block_rq_issue(q, rq); } @@ -2151,13 +2153,8 @@ struct request *blk_fetch_request(struct request_queue *q) struct request *rq; rq = blk_peek_request(q); - if (rq) { - if (rq->cmd_flags & REQ_URGENT) { - WARN_ON(q->dispatched_urgent); - q->dispatched_urgent = true; - } + if (rq) blk_start_request(rq); - } return rq; } EXPORT_SYMBOL(blk_fetch_request); diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 3c38536bd52..830fe67fa9d 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -239,6 +239,9 @@ struct cfq_data { unsigned long workload_expires; struct cfq_group *serving_group; + unsigned int nr_urgent_pending; + unsigned int nr_urgent_in_flight; + /* * Each priority tree is sorted by next_request position. These * trees are used when determining if two or more queues are @@ -2091,6 +2094,14 @@ static void cfq_dispatch_insert(struct request_queue *q, struct request *rq) (RQ_CFQG(rq))->dispatched++; elv_dispatch_sort(q, rq); + if (rq->cmd_flags & REQ_URGENT) { + if (!cfqd->nr_urgent_pending) + WARN_ON(1); + else + cfqd->nr_urgent_pending--; + cfqd->nr_urgent_in_flight++; + } + cfqd->rq_in_flight[cfq_cfqq_sync(cfqq)]++; cfqq->nr_sectors += blk_rq_sectors(rq); cfq_blkiocg_update_dispatch_stats(&cfqq->cfqg->blkg, blk_rq_bytes(rq), @@ -3191,6 +3202,69 @@ cfq_rq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq, } } +/* + * Called when a request (rq) is reinserted (to cfqq). Check if there's + * something we should do about it + */ +static void +cfq_rq_requeued(struct cfq_data *cfqd, struct cfq_queue *cfqq, + struct request *rq) +{ + struct cfq_io_cq *cic = RQ_CIC(rq); + + cfqd->rq_queued++; + if (rq->cmd_flags & REQ_PRIO) + cfqq->prio_pending++; + + cfqq->dispatched--; + (RQ_CFQG(rq))->dispatched--; + + cfqd->rq_in_flight[cfq_cfqq_sync(cfqq)]--; + + cfq_update_io_thinktime(cfqd, cfqq, cic); + cfq_update_io_seektime(cfqd, cfqq, rq); + cfq_update_idle_window(cfqd, cfqq, cic); + + cfqq->last_request_pos = blk_rq_pos(rq) + blk_rq_sectors(rq); + + if (cfqq == cfqd->active_queue) { + if (cfq_cfqq_wait_request(cfqq)) { + if (blk_rq_bytes(rq) > PAGE_CACHE_SIZE || + cfqd->busy_queues > 1) { + cfq_del_timer(cfqd, cfqq); + cfq_clear_cfqq_wait_request(cfqq); + } else { + cfq_blkiocg_update_idle_time_stats( + &cfqq->cfqg->blkg); + cfq_mark_cfqq_must_dispatch(cfqq); + } + } + } else if (cfq_should_preempt(cfqd, cfqq, rq)) { + cfq_preempt_queue(cfqd, cfqq); + } +} + +static int cfq_reinsert_request(struct request_queue *q, struct request *rq) +{ + struct cfq_data *cfqd = q->elevator->elevator_data; + struct cfq_queue *cfqq = RQ_CFQQ(rq); + + if (!cfqq || cfqq->cfqd != cfqd) + return -EIO; + + cfq_log_cfqq(cfqd, cfqq, "re-insert_request"); + list_add(&rq->queuelist, &cfqq->fifo); + cfq_add_rq_rb(rq); + + cfq_rq_requeued(cfqd, cfqq, rq); + if (rq->cmd_flags & REQ_URGENT) { + if (cfqd->nr_urgent_in_flight) + cfqd->nr_urgent_in_flight--; + cfqd->nr_urgent_pending++; + } + return 0; +} + static void cfq_insert_request(struct request_queue *q, struct request *rq) { struct cfq_data *cfqd = q->elevator->elevator_data; @@ -3205,7 +3279,45 @@ static void cfq_insert_request(struct request_queue *q, struct request *rq) cfq_blkiocg_update_io_add_stats(&(RQ_CFQG(rq))->blkg, &cfqd->serving_group->blkg, rq_data_dir(rq), rq_is_sync(rq)); + cfq_rq_enqueued(cfqd, cfqq, rq); + + if (rq->cmd_flags & REQ_URGENT) { + WARN_ON(1); + blk_dump_rq_flags(rq, ""); + rq->cmd_flags &= ~REQ_URGENT; + } + + /* Request is considered URGENT if: + * 1. The queue being served is of a lower IO priority then the new + * request + * OR: + * 2. The workload being performed is ASYNC + * Only READ requests may be considered as URGENT + */ + if ((cfqd->active_queue && + cfqq->ioprio_class < cfqd->active_queue->ioprio_class) || + (cfqd->serving_type == ASYNC_WORKLOAD && + rq_data_dir(rq) == READ)) { + rq->cmd_flags |= REQ_URGENT; + cfqd->nr_urgent_pending++; + } +} + + +/** + * cfq_urgent_pending() - Return TRUE if there is an urgent + * request on scheduler + * @q: requests queue + */ +static bool cfq_urgent_pending(struct request_queue *q) +{ + struct cfq_data *cfqd = q->elevator->elevator_data; + + if (cfqd->nr_urgent_pending && !cfqd->nr_urgent_in_flight) + return true; + + return false; } /* @@ -3289,6 +3401,14 @@ static void cfq_completed_request(struct request_queue *q, struct request *rq) const int sync = rq_is_sync(rq); unsigned long now; + if (rq->cmd_flags & REQ_URGENT) { + if (!cfqd->nr_urgent_in_flight) + WARN_ON(1); + else + cfqd->nr_urgent_in_flight--; + rq->cmd_flags &= ~REQ_URGENT; + } + now = jiffies; cfq_log_cfqq(cfqd, cfqq, "complete rqnoidle %d", !!(rq->cmd_flags & REQ_NOIDLE)); @@ -3856,6 +3976,8 @@ static struct elevator_type iosched_cfq = { .elevator_bio_merged_fn = cfq_bio_merged, .elevator_dispatch_fn = cfq_dispatch_requests, .elevator_add_req_fn = cfq_insert_request, + .elevator_reinsert_req_fn = cfq_reinsert_request, + .elevator_is_urgent_fn = cfq_urgent_pending, .elevator_activate_req_fn = cfq_activate_request, .elevator_deactivate_req_fn = cfq_deactivate_request, .elevator_completed_req_fn = cfq_completed_request, diff --git a/block/elevator.c b/block/elevator.c index 27adf7c0372..4368180a8df 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -816,7 +816,6 @@ void elv_completed_request(struct request_queue *q, struct request *rq) if (rq->cmd_flags & REQ_URGENT) { q->notified_urgent = false; - WARN_ON(!q->dispatched_urgent); q->dispatched_urgent = false; } /* diff --git a/block/row-iosched.c b/block/row-iosched.c index f08806246b2..bb845bfafb8 100644 --- a/block/row-iosched.c +++ b/block/row-iosched.c @@ -96,8 +96,8 @@ static const struct row_queue_params row_queues_def[] = { }; /* Default values for idling on read queues (in msec) */ -#define ROW_IDLE_TIME_MSEC 10 -#define ROW_READ_FREQ_MSEC 25 +#define ROW_IDLE_TIME_MSEC 5 +#define ROW_READ_FREQ_MSEC 5 /** * struct rowq_idling_data - parameters for idling on the queue @@ -331,6 +331,10 @@ static void row_add_request(struct request_queue *q, struct row_queue *rqueue = RQ_ROWQ(rq); s64 diff_ms; bool queue_was_empty = list_empty(&rqueue->fifo); + unsigned long bv_page_flags = 0; + + if (rq->bio && rq->bio->bi_io_vec && rq->bio->bi_io_vec->bv_page) + bv_page_flags = rq->bio->bi_io_vec->bv_page->flags; list_add_tail(&rq->queuelist, &rqueue->fifo); rd->nr_reqs[rq_data_dir(rq)]++; @@ -346,11 +350,14 @@ static void row_add_request(struct request_queue *q, if (row_queues_def[rqueue->prio].idling_enabled) { if (rd->rd_idle_data.idling_queue_idx == rqueue->prio && hrtimer_active(&rd->rd_idle_data.hr_timer)) { - (void)hrtimer_cancel(&rd->rd_idle_data.hr_timer); - row_log_rowq(rd, rqueue->prio, - "Canceled delayed work on %d", - rd->rd_idle_data.idling_queue_idx); - rd->rd_idle_data.idling_queue_idx = ROWQ_MAX_PRIO; + if (hrtimer_try_to_cancel( + &rd->rd_idle_data.hr_timer) >= 0) { + row_log_rowq(rd, rqueue->prio, + "Canceled delayed work on %d", + rd->rd_idle_data.idling_queue_idx); + rd->rd_idle_data.idling_queue_idx = + ROWQ_MAX_PRIO; + } } diff_ms = ktime_to_ms(ktime_sub(ktime_get(), rqueue->idle_data.last_insert_time)); @@ -360,7 +367,9 @@ static void row_add_request(struct request_queue *q, rqueue->idle_data.begin_idling = false; return; } - if (diff_ms < rd->rd_idle_data.freq_ms) { + + if ((bv_page_flags & (1L << PG_readahead)) || + (diff_ms < rd->rd_idle_data.freq_ms)) { rqueue->idle_data.begin_idling = true; row_log_rowq(rd, rqueue->prio, "Enable idling"); } else { @@ -387,7 +396,6 @@ static void row_add_request(struct request_queue *q, "added urgent request (total on queue=%d)", rqueue->nr_req); rq->cmd_flags |= REQ_URGENT; - WARN_ON(rqueue->nr_req > 1); rd->pending_urgent_rq = rq; } } else @@ -577,14 +585,14 @@ static int row_get_ioprio_class_to_serve(struct row_data *rd, int force) for (i = 0; i < ROWQ_REG_PRIO_IDX; i++) { if (!list_empty(&rd->row_queues[i].fifo)) { if (hrtimer_active(&rd->rd_idle_data.hr_timer)) { - (void)hrtimer_cancel( - &rd->rd_idle_data.hr_timer); - row_log_rowq(rd, - rd->rd_idle_data.idling_queue_idx, + if (hrtimer_try_to_cancel( + &rd->rd_idle_data.hr_timer) >= 0) { + row_log(rd->dispatch_queue, "Canceling delayed work on %d. RT pending", - rd->rd_idle_data.idling_queue_idx); - rd->rd_idle_data.idling_queue_idx = - ROWQ_MAX_PRIO; + rd->rd_idle_data.idling_queue_idx); + rd->rd_idle_data.idling_queue_idx = + ROWQ_MAX_PRIO; + } } if (row_regular_req_pending(rd) && @@ -720,11 +728,12 @@ static int row_dispatch_requests(struct request_queue *q, int force) int ret = 0, currq, ioprio_class_to_serve, start_idx, end_idx; if (force && hrtimer_active(&rd->rd_idle_data.hr_timer)) { - (void)hrtimer_cancel(&rd->rd_idle_data.hr_timer); - row_log_rowq(rd, rd->rd_idle_data.idling_queue_idx, - "Canceled delayed work on %d - forced dispatch", - rd->rd_idle_data.idling_queue_idx); - rd->rd_idle_data.idling_queue_idx = ROWQ_MAX_PRIO; + if (hrtimer_try_to_cancel(&rd->rd_idle_data.hr_timer) >= 0) { + row_log(rd->dispatch_queue, + "Canceled delayed work on %d - forced dispatch", + rd->rd_idle_data.idling_queue_idx); + rd->rd_idle_data.idling_queue_idx = ROWQ_MAX_PRIO; + } } if (rd->pending_urgent_rq) { diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h index 4dabf0fe527..5bc4fa5c6f1 100644 --- a/include/linux/page-flags.h +++ b/include/linux/page-flags.h @@ -108,6 +108,7 @@ enum pageflags { #ifdef CONFIG_TRANSPARENT_HUGEPAGE PG_compound_lock, #endif + PG_readahead, /* page in a readahead window */ __NR_PAGEFLAGS, /* Filesystems */ diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 350c6a4bcf5..830ae0dccb3 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -6111,6 +6111,7 @@ static struct trace_print_flags pageflag_names[] = { #ifdef CONFIG_MEMORY_FAILURE {1UL << PG_hwpoison, "hwpoison" }, #endif + {1UL << PG_readahead, "PG_readahead" }, {-1UL, NULL }, }; diff --git a/mm/readahead.c b/mm/readahead.c index d3a19647b3f..cae9a44ab22 100644 --- a/mm/readahead.c +++ b/mm/readahead.c @@ -184,6 +184,9 @@ __do_page_cache_readahead(struct address_space *mapping, struct file *filp, if (!page) break; page->index = page_offset; + + page->flags |= (1L << PG_readahead); + list_add(&page->lru, &page_pool); if (page_idx == nr_to_read - lookahead_size) SetPageReadahead(page); From e506fa878dd701f1e2d0ce8560faad4880de70b3 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Wed, 8 Jan 2014 11:26:17 +0100 Subject: [PATCH 116/215] sched,rt: disable rt_runtime borrowing by default Make the default RT_RUNTIME_SHARE setting reflect the most common throttle role, that of safety mechanism to protect the box. Bug 1269903 Change-Id: Id4ccf0095ea254f2e15fddc7ab02069f7f60a7c0 Signed-off-by: Mike Galbraith Reviewed-on: http://git-master/r/234274 (cherry picked from commit be74a12c8d8b987f569cdd0eec2aead3dcbdfa31) Reviewed-on: http://git-master/r/237266 Tested-by: Peter Boonstoppel Reviewed-by: Peter Boonstoppel Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Diwakar Tundlam Reviewed-by: Paul Walmsley GVS: Gerrit_Virtual_Submit --- kernel/sched/features.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/sched/features.h b/kernel/sched/features.h index d98ae909e32..d8853f5f62c 100644 --- a/kernel/sched/features.h +++ b/kernel/sched/features.h @@ -67,5 +67,5 @@ SCHED_FEAT(NONTASK_POWER, true) SCHED_FEAT(TTWU_QUEUE, true) SCHED_FEAT(FORCE_SD_OVERLAP, false) -SCHED_FEAT(RT_RUNTIME_SHARE, true) +SCHED_FEAT(RT_RUNTIME_SHARE, false) SCHED_FEAT(LB_MIN, false) From ca29479cc69881ca7006a6d30dde36e26d84f177 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Wed, 8 Jan 2014 11:27:03 +0100 Subject: [PATCH 117/215] sched: remove redundant update_runtime notifier migration_call() will do all the things that update_runtime() does. So it seems update_runtime() is a redundant notifier, remove it. Furthermore, there is potential risk that the current code will catch BUG_ON at line 687 of rt.c when do cpu hotplug while there are realtime threads running because of enable runtime twice. Change-Id: I0fdad8d5a1cebb845d3f308b205dbd6517c3e4de Cc: bitbucket@online.de Signed-off-by: Neil Zhang Reviewed-on: http://git-master/r/215596 (cherry picked from commit 8f646de983f24361814d9a6ca679845fb2265807) Reviewed-on: http://git-master/r/223067 Reviewed-by: Peter Boonstoppel Tested-by: Peter Boonstoppel Reviewed-by: Paul Walmsley Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Diwakar Tundlam --- kernel/sched/core.c | 3 --- kernel/sched/rt.c | 40 ---------------------------------------- kernel/sched/sched.h | 1 - 3 files changed, 44 deletions(-) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 45f5393292a..25900a90cc4 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -7102,9 +7102,6 @@ void __init sched_init_smp(void) hotcpu_notifier(cpuset_cpu_active, CPU_PRI_CPUSET_ACTIVE); hotcpu_notifier(cpuset_cpu_inactive, CPU_PRI_CPUSET_INACTIVE); - /* RT runtime code needs to handle some hotplug events */ - hotcpu_notifier(update_runtime, 0); - init_hrtick(); /* Move init over to a non-isolated CPU */ diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c index badcf2f1088..29bcc83b3db 100644 --- a/kernel/sched/rt.c +++ b/kernel/sched/rt.c @@ -690,15 +690,6 @@ static void __disable_runtime(struct rq *rq) } } -static void disable_runtime(struct rq *rq) -{ - unsigned long flags; - - raw_spin_lock_irqsave(&rq->lock, flags); - __disable_runtime(rq); - raw_spin_unlock_irqrestore(&rq->lock, flags); -} - static void __enable_runtime(struct rq *rq) { rt_rq_iter_t iter; @@ -723,37 +714,6 @@ static void __enable_runtime(struct rq *rq) } } -static void enable_runtime(struct rq *rq) -{ - unsigned long flags; - - raw_spin_lock_irqsave(&rq->lock, flags); - __enable_runtime(rq); - raw_spin_unlock_irqrestore(&rq->lock, flags); -} - -int update_runtime(struct notifier_block *nfb, unsigned long action, void *hcpu) -{ - int cpu = (int)(long)hcpu; - - switch (action) { - case CPU_DOWN_PREPARE: - case CPU_DOWN_PREPARE_FROZEN: - disable_runtime(cpu_rq(cpu)); - return NOTIFY_OK; - - case CPU_DOWN_FAILED: - case CPU_DOWN_FAILED_FROZEN: - case CPU_ONLINE: - case CPU_ONLINE_FROZEN: - enable_runtime(cpu_rq(cpu)); - return NOTIFY_OK; - - default: - return NOTIFY_DONE; - } -} - static int balance_runtime(struct rt_rq *rt_rq) { int more = 0; diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index 35e9d2069bb..762f52a0397 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -879,7 +879,6 @@ extern void sysrq_sched_debug_show(void); extern void sched_init_granularity(void); extern void update_max_interval(void); extern void update_group_power(struct sched_domain *sd, int cpu); -extern int update_runtime(struct notifier_block *nfb, unsigned long action, void *hcpu); extern void init_sched_rt_class(void); extern void init_sched_fair_class(void); From 23b59620fc6566b95c183492f5e85185f6ccd4ef Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Wed, 8 Jan 2014 11:27:46 +0100 Subject: [PATCH 118/215] sched: reinitialize rq->next_balance when a CPU is hot-added Reinitialize rq->next_balance when a CPU is hot-added. Otherwise, scheduler domain rebalancing may be skipped if rq->next_balance was set to a future time when the CPU was last active, and the newly-re-added CPU is in idle_balance(). As a result, the newly-re-added CPU will remain idle with no tasks scheduled until the softlockup watchdog runs - potentially 4 seconds later. This can waste energy and reduce performance. This behavior can be observed in some SoC kernels, which use CPU hotplug to dynamically remove and add CPUs in response to load. In one case that triggered this behavior, 0. the system started with all cores enabled, running multi-threaded CPU-bound code; 1. the system entered some single-threaded code; 2. a CPU went idle and was hot-removed; 3. the system started executing a multi-threaded CPU-bound task; 4. the CPU from event 2 was re-added, to respond to the load. The time interval between events 2 and 4 was approximately 300 milliseconds. Of course, ideally CPU hotplug would not be used in this manner, but this patch does appear to fix a real bug. Nvidia folks: this patch is submitted as at least a partial fix for bug 1243368 ("[sched] Load-balancing not happening correctly after cores brought online") Change-Id: Iabac21e110402bb581b7db40c42babc951d378d0 Signed-off-by: Paul Walmsley Cc: Peter Boonstoppel Reviewed-on: http://git-master/r/208927 Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Peter Zu Reviewed-by: Peter Boonstoppel GVS: Gerrit_Virtual_Submit Tested-by: Peter Zu Reviewed-by: Yu-Huan Hsu --- kernel/sched/core.c | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 25900a90cc4..478875b1bc9 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -5617,6 +5617,7 @@ migration_call(struct notifier_block *nfb, unsigned long action, void *hcpu) case CPU_UP_PREPARE: rq->calc_load_update = calc_load_update; + rq->next_balance = jiffies; break; case CPU_ONLINE: From e4309994272b714499bbfe0f7d78dc4b6f6109b5 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Wed, 8 Jan 2014 11:37:42 +0100 Subject: [PATCH 119/215] Aroma : Force disable input-boost if Qualcomm MPDEC is selected --- release/aroma/config/buildconfig.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/release/aroma/config/buildconfig.sh b/release/aroma/config/buildconfig.sh index 941d7aca68a..d5c32096abc 100755 --- a/release/aroma/config/buildconfig.sh +++ b/release/aroma/config/buildconfig.sh @@ -108,7 +108,9 @@ fi #Input-boost INPUTBOOST=`grep "item.0.8" /tmp/aroma/mods.prop | cut -d '=' -f2` echo -e "\n\n##### Input-booster Settings ######\n# 1 to enable Input-boost\n# 0 to disable Input-boost\n" >> $CONFIGFILE -if [ $INPUTBOOST = 1 ]; then +if [ $HOTPLUGDRV = 1 ]; then + echo "INPUTBOOST=0" >> $CONFIGFILE; +elif [ $INPUTBOOST = 1 ]; then echo "INPUTBOOST=1" >> $CONFIGFILE; else echo "INPUTBOOST=0" >> $CONFIGFILE; From dfcd6009c5c1307a63068fc68e326b4707cb693d Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Wed, 8 Jan 2014 18:16:26 +0100 Subject: [PATCH 120/215] Squash a lot of slab, slob and slub commits from Faux123 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit aio: convert the ioctx list to radix tree Date Wed, 3 Apr 2013 16:20:48 +0300 When using a large number of threads performing AIO operations the IOCTX list may get a significant number of entries which will cause significant overhead. For example, when running this fio script: rw=randrw; size=256k ;directory=/mnt/fio; ioengine=libaio; iodepth=1 blocksize=1024; numjobs=512; thread; loops=100 on an EXT2 filesystem mounted on top of a ramdisk we can observe up to 30% CPU time spent by lookup_ioctx: 32.51% [guest.kernel] [g] lookup_ioctx 9.19% [guest.kernel] [g] __lock_acquire.isra.28 4.40% [guest.kernel] [g] lock_release 4.19% [guest.kernel] [g] sched_clock_local 3.86% [guest.kernel] [g] local_clock 3.68% [guest.kernel] [g] native_sched_clock 3.08% [guest.kernel] [g] sched_clock_cpu 2.64% [guest.kernel] [g] lock_release_holdtime.part.11 2.60% [guest.kernel] [g] memcpy 2.33% [guest.kernel] [g] lock_acquired 2.25% [guest.kernel] [g] lock_acquire 1.84% [guest.kernel] [g] do_io_submit This patchs converts the ioctx list to a radix tree. For a performance comparison the above FIO script was run on a 2 sockets 8 core machine. This are the results for the original list based implementation and for the radix tree based implementation: cores 1 2 4 8 16 32 list 111025 ms 62219 ms 34193 ms 22998 ms 19335 ms 15956 ms radix 75400 ms 42668 ms 23923 ms 17206 ms 15820 ms 13295 ms % of radix relative 68% 69% 70% 75% 82% 83% to list To consider the impact of the patch on the typical case of having only one ctx per process the following FIO script was run: rw=randrw; size=100m ;directory=/mnt/fio; ioengine=libaio; iodepth=1 blocksize=1024; numjobs=1; thread; loops=100 on the same system and the results are the following: list 65241 ms radix 65402 ms % of radix relative 100.25% to list Cc: Andi Kleen Signed-off-by: Octavian Purdila modified for Mako hybrid from LKML Signed-off-by: Paul Reioux slob: Define page struct fields used in mm_types.h Define the fields used by slob in mm_types.h and use struct page instead of struct slob_page in slob. This cleans up numerous of typecasts in slob.c and makes readers aware of slob's use of page struct fields. [Also cleans up some bitrot in slob.c. The page struct field layout in slob.c is an old layout and does not match the one in mm_types.h] Reviewed-by: Glauber Costa Acked-by: David Rientjes Reviewed-by: Joonsoo Kim Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg slab: Use page struct fields instead of casting Add fields to the page struct so that it is properly documented that slab overlays the lru fields. This cleans up some casts in slab. Reviewed-by: Glauber Costa Reviewed-by: Joonsoo Kim Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg slab: Remove some accessors Those are rather trivial now and its better to see inline what is really going on. Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg mm, sl[aou]b: Extract common fields from struct kmem_cache Define a struct that describes common fields used in all slab allocators. A slab allocator either uses the common definition (like SLOB) or is required to provide members of kmem_cache with the definition given. After that it will be possible to share code that only operates on those fields of kmem_cache. The patch basically takes the slob definition of kmem cache and uses the field namees for the other allocators. It also standardizes the names used for basic object lengths in allocators: object_size Struct size specified at kmem_cache_create. Basically the payload expected to be used by the subsystem. size The size of memory allocator for each object. This size is larger than object_size and includes padding, alignment and extra metadata for each object (f.e. for debugging and rcu). Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg mm, sl[aou]b: Extract common code for kmem_cache_create() Kmem_cache_create() does a variety of sanity checks but those vary depending on the allocator. Use the strictest tests and put them into a slab_common file. Make the tests conditional on CONFIG_DEBUG_VM. This patch has the effect of adding sanity checks for SLUB and SLOB under CONFIG_DEBUG_VM and removes the checks in SLAB for !CONFIG_DEBUG_VM. Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg slab: Get rid of obj_size macro The size of the slab object is frequently needed. Since we now have a size field directly in the kmem_cache structure there is no need anymore of the obj_size macro/function. Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg slab/mempolicy: always use local policy from interrupt context slab_node() could access current->mempolicy from interrupt context. However there's a race condition during exit where the mempolicy is first freed and then the pointer zeroed. Using this from interrupts seems bogus anyways. The interrupt will interrupt a random process and therefore get a random mempolicy. Many times, this will be idle's, which noone can change. Just disable this here and always use local for slab from interrupts. I also cleaned up the callers of slab_node a bit which always passed the same argument. I believe the original mempolicy code did that in fact, so it's likely a regression. v2: send version with correct logic v3: simplify. fix typo. Reported-by: Arun Sharma Cc: penberg@kernel.org Cc: cl@linux.com Signed-off-by: Andi Kleen [tdmackey@twitter.com: Rework control flow based on feedback from cl@linux.com, fix logic, and cleanup current task_struct reference] Acked-by: David Rientjes Acked-by: Christoph Lameter Acked-by: KOSAKI Motohiro Signed-off-by: David Mackey Signed-off-by: Pekka Enberg slab: rename gfpflags to allocflags A consistent name with slub saves us an acessor function. In both caches, this field represents the same thing. We would like to use it from the mem_cgroup code. Signed-off-by: Glauber Costa Acked-by: Christoph Lameter CC: Pekka Enberg Signed-off-by: Pekka Enberg mm, slab: Build fix for recent kmem_cache changes Commit 3b0efdf ("mm, sl[aou]b: Extract common fields from struct kmem_cache") renamed the kmem_cache structure's "next" field to "list" but forgot to update one instance in leaks_show(). Signed-off-by: Thierry Reding Signed-off-by: Pekka Enberg slab: Fix a typo in commit 8c138b "slab: Get rid of obj_size macro" Commit 8c138b only sits in Pekka's and linux-next tree now, which tries to replace obj_size(cachep) with cachep->object_size, but has a typo in kmem_cache_free() by using "size" instead of "object_size", which casues some regressions. Reported-and-tested-by: Fengguang Wu Signed-off-by: Feng Tang Cc: Christoph Lameter Acked-by: Glauber Costa Signed-off-by: Pekka Enberg slab: move FULL state transition to an initcall During kmem_cache_init_late(), we transition to the LATE state, and after some more work, to the FULL state, its last state This is quite different from slub, that will only transition to its last state (previously SYSFS), in a (late)initcall, after a lot more of the kernel is ready. This means that in slab, we have no way to taking actions dependent on the initialization of other pieces of the kernel that are supposed to start way after kmem_init_late(), such as cgroups initialization. To achieve more consistency in this behavior, that patch only transitions to the UP state in kmem_init_late. In my analysis, setup_cpu_cache() should be happy to test for >= UP, instead of == FULL. It also has passed some tests I've made. We then only mark FULL state after the reap timers are in place, meaning that no further setup is expected. Signed-off-by: Glauber Costa Acked-by: Christoph Lameter Acked-by: David Rientjes Signed-off-by: Pekka Enberg mm, sl[aou]b: Common definition for boot state of the slab allocators All allocators have some sort of support for the bootstrap status. Setup a common definition for the boot states and make all slab allocators use that definition. Reviewed-by: Glauber Costa Reviewed-by: Joonsoo Kim Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg mm, sl[aou]b: Use a common mutex definition Use the mutex definition from SLAB and make it the common way to take a sleeping lock. This has the effect of using a mutex instead of a rw semaphore for SLUB. SLOB gains the use of a mutex for kmem_cache_create serialization. Not needed now but SLOB may acquire some more features later (like slabinfo / sysfs support) through the expansion of the common code that will need this. Reviewed-by: Glauber Costa Reviewed-by: Joonsoo Kim Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg mm, sl[aou]b: Move kmem_cache_create mutex handling to common code Move the mutex handling into the common kmem_cache_create() function. Then we can also move more checks out of SLAB's kmem_cache_create() into the common code. Reviewed-by: Glauber Costa Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg slub: use __SetPageSlab function to set PG_slab flag To set page-flag, using SetPageXXXX() and __SetPageXXXX() is more understandable and maintainable. So change it. Signed-off-by: Joonsoo Kim Signed-off-by: Pekka Enberg slub: Use freelist instead of "object" in __slab_alloc The variable "object" really refers to a list of objects that we are handling. Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg slub: Add frozen check in __slab_alloc Verify that objects returned from __slab_alloc come from slab pages in the correct state. Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg slub: Acquire_slab() avoid loop Avoid the loop in acquire slab and simply fail if there is a conflict. This will cause the next page on the list to be considered. Acked-by: David Rientjes Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg Signed-off-by: Paul Reioux Conflicts: mm/slub.c slub: Simplify control flow in __slab_alloc() Simplify control flow a bit avoiding nesting. Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg slub: new_slab_objects() can also get objects from partial list Moving the attempt to get a slab page from the partial lists simplifies __slab_alloc which is rather complicated. Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg slub: Get rid of the node field The node field is always page_to_nid(c->page). So its rather easy to replace. Note that there maybe slightly more overhead in various hot paths due to the need to shift the bits from page->flags. However, that is mostly compensated for by a smaller footprint of the kmem_cache_cpu structure (this patch reduces that to 3 words per cache) which allows better caching. Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg slub: Separate out kmem_cache_cpu processing from deactivate_slab Processing on fields of kmem_cache_cpu is cleaner if code working on fields of this struct is taken out of deactivate_slab(). Acked-by: David Rientjes Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg slub: Use page variable instead of c->page. Store the value of c->page to avoid additional fetches from per cpu data. Acked-by: David Rientjes Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg slub: pass page to node_match() instead of kmem_cache_cpu structure Avoid passing the kmem_cache_cpu pointer to node_match. This makes the node_match function more generic and easier to understand. Acked-by: David Rientjes Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg Signed-off-by: Paul Reioux slub: use __cmpxchg_double_slab() at interrupt disabled place get_freelist(), unfreeze_partials() are only called with interrupt disabled, so __cmpxchg_double_slab() is suitable. Acked-by: Christoph Lameter Signed-off-by: Joonsoo Kim Signed-off-by: Pekka Enberg slub: refactoring unfreeze_partials() Current implementation of unfreeze_partials() is so complicated, but benefit from it is insignificant. In addition many code in do {} while loop have a bad influence to a fail rate of cmpxchg_double_slab. Under current implementation which test status of cpu partial slab and acquire list_lock in do {} while loop, we don't need to acquire a list_lock and gain a little benefit when front of the cpu partial slab is to be discarded, but this is a rare case. In case that add_partial is performed and cmpxchg_double_slab is failed, remove_partial should be called case by case. I think that these are disadvantages of current implementation, so I do refactoring unfreeze_partials(). Minimizing code in do {} while loop introduce a reduced fail rate of cmpxchg_double_slab. Below is output of 'slabinfo -r kmalloc-256' when './perf stat -r 33 hackbench 50 process 4000 > /dev/null' is done. ** before ** Cmpxchg_double Looping ------------------------ Locked Cmpxchg Double redos 182685 Unlocked Cmpxchg Double redos 0 ** after ** Cmpxchg_double Looping ------------------------ Locked Cmpxchg Double redos 177995 Unlocked Cmpxchg Double redos 1 We can see cmpxchg_double_slab fail rate is improved slightly. Bolow is output of './perf stat -r 30 hackbench 50 process 4000 > /dev/null'. ** before ** Performance counter stats for './hackbench 50 process 4000' (30 runs): 108517.190463 task-clock # 7.926 CPUs utilized ( +- 0.24% ) 2,919,550 context-switches # 0.027 M/sec ( +- 3.07% ) 100,774 CPU-migrations # 0.929 K/sec ( +- 4.72% ) 124,201 page-faults # 0.001 M/sec ( +- 0.15% ) 401,500,234,387 cycles # 3.700 GHz ( +- 0.24% ) stalled-cycles-frontend stalled-cycles-backend 250,576,913,354 instructions # 0.62 insns per cycle ( +- 0.13% ) 45,934,956,860 branches # 423.297 M/sec ( +- 0.14% ) 188,219,787 branch-misses # 0.41% of all branches ( +- 0.56% ) 13.691837307 seconds time elapsed ( +- 0.24% ) ** after ** Performance counter stats for './hackbench 50 process 4000' (30 runs): 107784.479767 task-clock # 7.928 CPUs utilized ( +- 0.22% ) 2,834,781 context-switches # 0.026 M/sec ( +- 2.33% ) 93,083 CPU-migrations # 0.864 K/sec ( +- 3.45% ) 123,967 page-faults # 0.001 M/sec ( +- 0.15% ) 398,781,421,836 cycles # 3.700 GHz ( +- 0.22% ) stalled-cycles-frontend stalled-cycles-backend 250,189,160,419 instructions # 0.63 insns per cycle ( +- 0.09% ) 45,855,370,128 branches # 425.436 M/sec ( +- 0.10% ) 169,881,248 branch-misses # 0.37% of all branches ( +- 0.43% ) 13.596272341 seconds time elapsed ( +- 0.22% ) No regression is found, but rather we can see slightly better result. Acked-by: Christoph Lameter Signed-off-by: Joonsoo Kim Signed-off-by: Pekka Enberg slub: remove invalid reference to list iterator variable If list_for_each_entry, etc complete a traversal of the list, the iterator variable ends up pointing to an address at an offset from the list head, and not a meaningful structure. Thus this value should not be used after the end of the iterator. The patch replaces s->name by al->name, which is referenced nearby. This problem was found using Coccinelle (http://coccinelle.lip6.fr/). Signed-off-by: Julia Lawall Signed-off-by: Pekka Enberg mm, slub: ensure irqs are enabled for kmemcheck kmemcheck_alloc_shadow() requires irqs to be enabled, so wait to disable them until after its called for __GFP_WAIT allocations. This fixes a warning for such allocations: WARNING: at kernel/lockdep.c:2739 lockdep_trace_alloc+0x14e/0x1c0() Acked-by: Fengguang Wu Acked-by: Steven Rostedt Tested-by: Fengguang Wu Signed-off-by: David Rientjes Signed-off-by: Pekka Enberg mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages When a user or administrator requires swap for their application, they create a swap partition and file, format it with mkswap and activate it with swapon. Swap over the network is considered as an option in diskless systems. The two likely scenarios are when blade servers are used as part of a cluster where the form factor or maintenance costs do not allow the use of disks and thin clients. The Linux Terminal Server Project recommends the use of the Network Block Device (NBD) for swap according to the manual at https://sourceforge.net/projects/ltsp/files/Docs-Admin-Guide/LTSPManual.pdf/download There is also documentation and tutorials on how to setup swap over NBD at places like https://help.ubuntu.com/community/UbuntuLTSP/EnableNBDSWAP The nbd-client also documents the use of NBD as swap. Despite this, the fact is that a machine using NBD for swap can deadlock within minutes if swap is used intensively. This patch series addresses the problem. The core issue is that network block devices do not use mempools like normal block devices do. As the host cannot control where they receive packets from, they cannot reliably work out in advance how much memory they might need. Some years ago, Peter Zijlstra developed a series of patches that supported swap over an NFS that at least one distribution is carrying within their kernels. This patch series borrows very heavily from Peter's work to support swapping over NBD as a pre-requisite to supporting swap-over-NFS. The bulk of the complexity is concerned with preserving memory that is allocated from the PFMEMALLOC reserves for use by the network layer which is needed for both NBD and NFS. Patch 1 adds knowledge of the PFMEMALLOC reserves to SLAB and SLUB to preserve access to pages allocated under low memory situations to callers that are freeing memory. Patch 2 optimises the SLUB fast path to avoid pfmemalloc checks Patch 3 introduces __GFP_MEMALLOC to allow access to the PFMEMALLOC reserves without setting PFMEMALLOC. Patch 4 opens the possibility for softirqs to use PFMEMALLOC reserves for later use by network packet processing. Patch 5 only sets page->pfmemalloc when ALLOC_NO_WATERMARKS was required Patch 6 ignores memory policies when ALLOC_NO_WATERMARKS is set. Patches 7-12 allows network processing to use PFMEMALLOC reserves when the socket has been marked as being used by the VM to clean pages. If packets are received and stored in pages that were allocated under low-memory situations and are unrelated to the VM, the packets are dropped. Patch 11 reintroduces __skb_alloc_page which the networking folk may object to but is needed in some cases to propogate pfmemalloc from a newly allocated page to an skb. If there is a strong objection, this patch can be dropped with the impact being that swap-over-network will be slower in some cases but it should not fail. Patch 13 is a micro-optimisation to avoid a function call in the common case. Patch 14 tags NBD sockets as being SOCK_MEMALLOC so they can use PFMEMALLOC if necessary. Patch 15 notes that it is still possible for the PFMEMALLOC reserve to be depleted. To prevent this, direct reclaimers get throttled on a waitqueue if 50% of the PFMEMALLOC reserves are depleted. It is expected that kswapd and the direct reclaimers already running will clean enough pages for the low watermark to be reached and the throttled processes are woken up. Patch 16 adds a statistic to track how often processes get throttled Some basic performance testing was run using kernel builds, netperf on loopback for UDP and TCP, hackbench (pipes and sockets), iozone and sysbench. Each of them were expected to use the sl*b allocators reasonably heavily but there did not appear to be significant performance variances. For testing swap-over-NBD, a machine was booted with 2G of RAM with a swapfile backed by NBD. 8*NUM_CPU processes were started that create anonymous memory mappings and read them linearly in a loop. The total size of the mappings were 4*PHYSICAL_MEMORY to use swap heavily under memory pressure. Without the patches and using SLUB, the machine locks up within minutes and runs to completion with them applied. With SLAB, the story is different as an unpatched kernel run to completion. However, the patched kernel completed the test 45% faster. MICRO 3.5.0-rc2 3.5.0-rc2 vanilla swapnbd Unrecognised test vmscan-anon-mmap-write MMTests Statistics: duration Sys Time Running Test (seconds) 197.80 173.07 User+Sys Time Running Test (seconds) 206.96 182.03 Total Elapsed Time (seconds) 3240.70 1762.09 This patch: mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages Allocations of pages below the min watermark run a risk of the machine hanging due to a lack of memory. To prevent this, only callers who have PF_MEMALLOC or TIF_MEMDIE set and are not processing an interrupt are allowed to allocate with ALLOC_NO_WATERMARKS. Once they are allocated to a slab though, nothing prevents other callers consuming free objects within those slabs. This patch limits access to slab pages that were alloced from the PFMEMALLOC reserves. When this patch is applied, pages allocated from below the low watermark are returned with page->pfmemalloc set and it is up to the caller to determine how the page should be protected. SLAB restricts access to any page with page->pfmemalloc set to callers which are known to able to access the PFMEMALLOC reserve. If one is not available, an attempt is made to allocate a new page rather than use a reserve. SLUB is a bit more relaxed in that it only records if the current per-CPU page was allocated from PFMEMALLOC reserve and uses another partial slab if the caller does not have the necessary GFP or process flags. This was found to be sufficient in tests to avoid hangs due to SLUB generally maintaining smaller lists than SLAB. In low-memory conditions it does mean that !PFMEMALLOC allocators can fail a slab allocation even though free objects are available because they are being preserved for callers that are freeing pages. [a.p.zijlstra@chello.nl: Original implementation] [sebastian@breakpoint.cc: Correct order of page flag clearing] Signed-off-by: Mel Gorman Cc: David Miller Cc: Neil Brown Cc: Peter Zijlstra Cc: Mike Christie Cc: Eric B Munson Cc: Eric Dumazet Cc: Sebastian Andrzej Siewior Cc: Mel Gorman Cc: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds backported for Android Linux 3.4 by faux123 Signed-off-by: Paul Reioux Conflicts: mm/page_alloc.c mm: introduce __GFP_MEMALLOC to allow access to emergency reserves __GFP_MEMALLOC will allow the allocation to disregard the watermarks, much like PF_MEMALLOC. It allows one to pass along the memalloc state in object related allocation flags as opposed to task related flags, such as sk->sk_allocation. This removes the need for ALLOC_PFMEMALLOC as callers using __GFP_MEMALLOC can get the ALLOC_NO_WATERMARK flag which is now enough to identify allocations related to page reclaim. Signed-off-by: Peter Zijlstra Signed-off-by: Mel Gorman Cc: David Miller Cc: Neil Brown Cc: Mike Christie Cc: Eric B Munson Cc: Eric Dumazet Cc: Sebastian Andrzej Siewior Cc: Mel Gorman Cc: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds backported to Android Linux 3.4 by faux123 Signed-off-by: Paul Reioux Conflicts: include/linux/gfp.h mm/page_alloc.c mm: micro-optimise slab to avoid a function call Getting and putting objects in SLAB currently requires a function call but the bulk of the work is related to PFMEMALLOC reserves which are only consumed when network-backed storage is critical. Use an inline function to determine if the function call is required. Signed-off-by: Mel Gorman Cc: David Miller Cc: Neil Brown Cc: Peter Zijlstra Cc: Mike Christie Cc: Eric B Munson Cc: Eric Dumazet Cc: Sebastian Andrzej Siewior Cc: Mel Gorman Cc: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds slab: do not call compound_head() in page_get_cache() page_get_cache() does not need to call compound_head(), as its unique caller virt_to_slab() already makes sure to return a head page. Additionally, removing the compound_head() call makes page_get_cache() consistent with page_get_slab(). Signed-off-by: Michel Lespinasse Cc: Christoph Lameter Cc: Pekka Enberg Acked-by: David Rientjes Signed-off-by: Andrew Morton Signed-off-by: Pekka Enberg mm, slab: remove page_get_cache page_get_cache() isn't called from anything, so remove it. Signed-off-by: David Rientjes Signed-off-by: Pekka Enberg mm, slab: lock the correct nodelist after reenabling irqs cache_grow() can reenable irqs so the cpu (and node) can change, so ensure that we take list_lock on the correct nodelist. This fixes an issue with commit 072bb0aa5e06 ("mm: sl[au]b: add knowledge of PFMEMALLOC reserve pages") where list_lock for the wrong node was taken after growing the cache. Reported-and-tested-by: Haggai Eran Signed-off-by: David Rientjes Signed-off-by: Linus Torvalds mm: Fix build warning in kmem_cache_create() The label oops is used in CONFIG_DEBUG_VM ifdef block and is defined outside ifdef CONFIG_DEBUG_VM block. This results in the following build warning when built with CONFIG_DEBUG_VM disabled. Fix to move label oops definition to inside a CONFIG_DEBUG_VM block. mm/slab_common.c: In function ‘kmem_cache_create’: mm/slab_common.c:101:1: warning: label ‘oops’ defined but not used [-Wunused-label] Signed-off-by: Shuah Khan Signed-off-by: Pekka Enberg Signed-off-by: Paul Reioux Conflicts: mm/slab_common.c mm/slab_common.c: cleanup Eliminate an ifdef and a label by moving all the CONFIG_DEBUG_VM checking inside the locked region. Cc: Pekka Enberg Signed-off-by: Andrew Morton Signed-off-by: Pekka Enberg Revert "mm/slab_common.c: cleanup" This reverts commit 455ce9eb1cfa083da0def023094190aeb133855a. Andrew sent a better version. Signed-off-by: Pekka Enberg mm/slab: restructure kmem_cache_create() debug checks kmem_cache_create() does cache integrity checks when CONFIG_DEBUG_VM is defined. These checks interspersed with the regular code path has lead to compile time warnings when compiled without CONFIG_DEBUG_VM defined. Restructuring the code to move the integrity checks in to a new function would eliminate the current compile warning problem and also will allow for future changes to the debug only code to evolve without introducing new warnings in the regular path. This restructuring work is based on the discussion in the following thread: https://lkml.org/lkml/2012/7/13/424 [akpm@linux-foundation.org: fix build, cleanup] Signed-off-by: Shuah Khan Acked-by: Christoph Lameter Signed-off-by: Andrew Morton Signed-off-by: Pekka Enberg mm/slab_common: Improve error handling in kmem_cache_create Instead of using s == NULL use an errorcode. This allows much more detailed diagnostics as to what went wrong. As we add more functionality from the slab allocators to the common kmem_cache_create() function we will also add more error conditions. Print the error code during the panic as well as in a warning if the module can handle failure. The API for kmem_cache_create() currently does not allow the returning of an error code. Return NULL but log the cause of the problem in the syslog. Reviewed-by: Glauber Costa Acked-by: David Rientjes Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg mm/sl[aou]b: Move list_add() to slab_common.c Move the code to append the new kmem_cache to the list of slab caches to the kmem_cache_create code in the shared code. This is possible now since the acquisition of the mutex was moved into kmem_cache_create(). Acked-by: David Rientjes Reviewed-by: Glauber Costa Reviewed-by: Joonsoo Kim Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg mm/sl[aou]b: Use "kmem_cache" name for slab cache with kmem_cache struct Make all allocators use the "kmem_cache" slabname for the "kmem_cache" structure. Reviewed-by: Glauber Costa Reviewed-by: Joonsoo Kim Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg mm/sl[aou]b: Extract a common function for kmem_cache_destroy kmem_cache_destroy does basically the same in all allocators. Extract common code which is easy since we already have common mutex handling. Reviewed-by: Glauber Costa Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg mm: slub: optimise the SLUB fast path to avoid pfmemalloc checks This patch removes the check for pfmemalloc from the alloc hotpath and puts the logic after the election of a new per cpu slab. For a pfmemalloc page we do not use the fast path but force the use of the slow path which is also used for the debug case. This has the side-effect of weakening pfmemalloc processing in the following way; 1. A process that is allocating for network swap calls __slab_alloc. pfmemalloc_match is true so the freelist is loaded and c->freelist is now pointing to a pfmemalloc page. 2. A process that is attempting normal allocations calls slab_alloc, finds the pfmemalloc page on the freelist and uses it because it did not check pfmemalloc_match() The patch allows non-pfmemalloc allocations to use pfmemalloc pages with the kmalloc slabs being the most vunerable caches on the grounds they are most likely to have a mix of pfmemalloc and !pfmemalloc requests. A later patch will still protect the system as processes will get throttled if the pfmemalloc reserves get depleted but performance will not degrade as smoothly. [mgorman@suse.de: Expanded changelog] Signed-off-by: Christoph Lameter Signed-off-by: Mel Gorman Cc: David Miller Cc: Neil Brown Cc: Peter Zijlstra Cc: Mike Christie Cc: Eric B Munson Cc: Eric Dumazet Cc: Sebastian Andrzej Siewior Cc: Mel Gorman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds slub: use free_page instead of put_page for freeing kmalloc allocation When freeing objects, the slub allocator will most of the time free empty pages by calling __free_pages(). But high-order kmalloc will be diposed by means of put_page() instead. It makes no sense to call put_page() in kernel pages that are provided by the object allocators, so we shouldn't be doing this ourselves. Aside from the consistency change, we don't change the flow too much. put_page()'s would call its dtor function, which is __free_pages. We also already do all of the Compound page tests ourselves, and the Mlock test we lose don't really matter. Signed-off-by: Glauber Costa Acked-by: Christoph Lameter CC: David Rientjes CC: Pekka Enberg Signed-off-by: Pekka Enberg slub: Take node lock during object free checks Only applies to scenarios where debugging is on: Validation of slabs can currently occur while debugging information is updated from the fast paths of the allocator. This results in various races where we get false reports about slab metadata not being in order. This patch makes the fast paths take the node lock so that serialization with slab validation will occur. Causes additional slowdown in debug scenarios. Reported-by: Waiman Long Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg slub: reduce failure of this_cpu_cmpxchg in put_cpu_partial() after unfreezing In current implementation, after unfreezing, we doesn't touch oldpage, so it remain 'NOT NULL'. When we call this_cpu_cmpxchg() with this old oldpage, this_cpu_cmpxchg() is mostly be failed. We can change value of oldpage to NULL after unfreezing, because unfreeze_partial() ensure that all the cpu partial slabs is removed from cpu partial list. In this time, we could expect that this_cpu_cmpxchg is mostly succeed. Acked-by: Christoph Lameter Signed-off-by: Joonsoo Kim Signed-off-by: Pekka Enberg mm/slub: Add debugging to verify correct cache use on kmem_cache_free() Add additional debugging to check that the objects is actually from the cache the caller claims. Doing so currently trips up some other debugging code. It takes a lot to infer from that what was happening. Reviewed-by: Glauber Costa Signed-off-by: Christoph Lameter [ penberg@kernel.org: Use pr_err() ] Signed-off-by: Pekka Enberg mm/slub: Use kmem_cache for the kmem_cache structure Do not use kmalloc() but kmem_cache_alloc() for the allocation of the kmem_cache structures in slub. Reviewed-by: Glauber Costa Acked-by: David Rientjes Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg mm/sl[aou]b: Move freeing of kmem_cache structure to common code The freeing action is basically the same in all slab allocators. Move to the common kmem_cache_destroy() function. Reviewed-by: Glauber Costa Reviewed-by: Joonsoo Kim Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg mm/sl[aou]b: Get rid of __kmem_cache_destroy What is done there can be done in __kmem_cache_shutdown. This affects RCU handling somewhat. On rcu free all slab allocators do not refer to other management structures than the kmem_cache structure. Therefore these other structures can be freed before the rcu deferred free to the page allocator occurs. Reviewed-by: Joonsoo Kim Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg mm/sl[aou]b: Move duping of slab name to slab_common.c Duping of the slabname has to be done by each slab. Moving this code to slab_common avoids duplicate implementations. With this patch we have common string handling for all slab allocators. Strings passed to kmem_cache_create() are copied internally. Subsystems can create temporary strings to create slab caches. Slabs allocated in early states of bootstrap will never be freed (and those can never be freed since they are essential to slab allocator operations). During bootstrap we therefore do not have to worry about duping names. Reviewed-by: Glauber Costa Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg mm/sl[aou]b: Do slab aliasing call from common code The slab aliasing logic causes some strange contortions in slub. So add a call to deal with aliases to slab_common.c but disable it for other slab allocators by providng stubs that fail to create aliases. Full general support for aliases will require additional cleanup passes and more standardization of fields in kmem_cache. Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg mm/sl[aou]b: Move sysfs_slab_add to common Simplify locking by moving the slab_add_sysfs after all locks have been dropped. Eases the upcoming move to provide sysfs support for all allocators. Reviewed-by: Glauber Costa Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg slob: No need to zero mapping since it is no longer in use Reviewed-by: Joonsoo Kim Acked-by: David Rientjes Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg slob: Remove various small accessors Those have become so simple that they are no longer needed. Reviewed-by: Joonsoo Kim Acked-by: David Rientjes signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg slob: Fix early boot kernel crash Commit fd3142a59af2012a7c5dc72ec97a4935ff1c5fc6 broke slob since a piece of a change for a later patch slipped into it. Fengguang Wu writes: The commit crashes the kernel w/o any dmesg output (the attached one is created by the script as a summary for that run). This is very reproducible in kvm for the attached config. Reported-by: Fengguang Wu Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg mm/sl[aou]b: Move kmem_cache allocations into common code Shift the allocations to common code. That way the allocation and freeing of the kmem_cache structures is handled by common code. Reviewed-by: Glauber Costa Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg mm/sl[aou]b: Shrink __kmem_cache_create() parameter lists Do the initial settings of the fields in common code. This will allow us to push more processing into common code later and improve readability. Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg mm/sl[aou]b: Move kmem_cache refcounting to common code Get rid of the refcount stuff in the allocators and do that part of kmem_cache management in the common code. Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg slab: fix the DEADLOCK issue on l3 alien lock DEADLOCK will be report while running a kernel with NUMA and LOCKDEP enabled, the process of this fake report is: kmem_cache_free() //free obj in cachep -> cache_free_alien() //acquire cachep's l3 alien lock -> __drain_alien_cache() -> free_block() -> slab_destroy() -> kmem_cache_free() //free slab in cachep->slabp_cache -> cache_free_alien() //acquire cachep->slabp_cache's l3 alien lock Since the cachep and cachep->slabp_cache's l3 alien are in the same lock class, fake report generated. This should not happen since we already have init_lock_keys() which will reassign the lock class for both l3 list and l3 alien. However, init_lock_keys() was invoked at a wrong position which is before we invoke enable_cpucache() on each cache. Since until set slab_state to be FULL, we won't invoke enable_cpucache() on caches to build their l3 alien while creating them, so although we invoked init_lock_keys(), the l3 alien lock class won't change since we don't have them until invoked enable_cpucache() later. This patch will invoke init_lock_keys() after we done enable_cpucache() instead of before to avoid the fake DEADLOCK report. Michael traced the problem back to a commit in release 3.0.0: commit 30765b92ada267c5395fc788623cb15233276f5c Author: Peter Zijlstra Date: Thu Jul 28 23:22:56 2011 +0200 slab, lockdep: Annotate the locks before using them Fernando found we hit the regular OFF_SLAB 'recursion' before we annotate the locks, cure this. The relevant portion of the stack-trace: > [ 0.000000] [] rt_spin_lock+0x50/0x56 > [ 0.000000] [] __cache_free+0x43/0xc3 > [ 0.000000] [] kmem_cache_free+0x6c/0xdc > [ 0.000000] [] slab_destroy+0x4f/0x53 > [ 0.000000] [] free_block+0x94/0xc1 > [ 0.000000] [] do_tune_cpucache+0x10b/0x2bb > [ 0.000000] [] enable_cpucache+0x7b/0xa7 > [ 0.000000] [] kmem_cache_init_late+0x1f/0x61 > [ 0.000000] [] start_kernel+0x24c/0x363 > [ 0.000000] [] i386_start_kernel+0xa9/0xaf Reported-by: Fernando Lopez-Lezcano Acked-by: Pekka Enberg Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/1311888176.2617.379.camel@laptop Signed-off-by: Ingo Molnar The commit moved init_lock_keys() before we build up the alien, so we failed to reclass it. Cc: # 3.0+ Acked-by: Christoph Lameter Tested-by: Paul E. McKenney Signed-off-by: Michael Wang Signed-off-by: Pekka Enberg slab: do ClearSlabPfmemalloc() for all pages of slab Right now, we call ClearSlabPfmemalloc() for first page of slab when we clear SlabPfmemalloc flag. This is fine for most swap-over-network use cases as it is expected that order-0 pages are in use. Unfortunately it is possible that that __ac_put_obj() checks SlabPfmemalloc on a tail page and while this is harmless, it is sloppy. This patch ensures that the head page is always used. This problem was originally identified by Joonsoo Kim. [js1304@gmail.com: Original implementation and problem identification] Signed-off-by: Mel Gorman Cc: David Miller Cc: Chuck Lever Cc: Joonsoo Kim Cc: David Rientjes Cc: Pekka Enberg Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds slab: fix starting index for finding another object In array cache, there is a object at index 0, check it. Signed-off-by: Joonsoo Kim Signed-off-by: Mel Gorman Cc: David Miller Cc: Chuck Lever Cc: David Rientjes Cc: Pekka Enberg Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds slab: Only define slab_error for DEBUG On Tue, 11 Sep 2012, Stephen Rothwell wrote: > After merging the final tree, today's linux-next build (sparc64 defconfig) > produced this warning: > > mm/slab.c:808:13: warning: '__slab_error' defined but not used [-Wunused-function] > > Introduced by commit 945cf2b6199b ("mm/sl[aou]b: Extract a common > function for kmem_cache_destroy"). All uses of slab_error() are now > guarded by DEBUG. There is no use case left for slab builds without DEBUG. Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg mm, sl[au]b: Taint kernel when we detect a corrupted slab It doesn't seem worth adding a new taint flag for this, so just re-use the one from 'bad page' Acked-by: Christoph Lameter # SLUB Acked-by: David Rientjes Signed-off-by: Dave Jones Signed-off-by: Pekka Enberg mm, slab: Remove silly function slab_buffer_size() This function is seldom used, and can be simply replaced with cachep->size. Acked-by: David Rientjes Signed-off-by: Ezequiel Garcia Signed-off-by: Pekka Enberg mm, slab: Replace 'caller' type, void* -> unsigned long This allows to use _RET_IP_ instead of builtin_address(0), thus achiveing implementation consistency in all three allocators. Though maybe a nitpick, the real goal behind this patch is to be able to obtain common code between SLAB and SLUB. Signed-off-by: Ezequiel Garcia Signed-off-by: Pekka Enberg mm, slab: Match SLAB and SLUB kmem_cache_alloc_xxx_trace() prototype This long (seemingly unnecessary) patch does not fix anything and its only goal is to produce common code between SLAB and SLUB. Cc: Christoph Lameter Signed-off-by: Ezequiel Garcia Signed-off-by: Pekka Enberg mm, slab: Rename __cache_alloc() -> slab_alloc() This patch does not fix anything and its only goal is to produce common code between SLAB and SLUB. Cc: Christoph Lameter Signed-off-by: Ezequiel Garcia Signed-off-by: Pekka Enberg mm/slab: Fix typo _RET_IP -> _RET_IP_ The bug was introduced by commit 7c0cb9c64f83 ("mm, slab: Replace 'caller' type, void* -> unsigned long"). Reported-by: Fengguang Wu Signed-off-by: Ezequiel Garcia Signed-off-by: Pekka Enberg mm/slab: Fix kmem_cache_alloc_node_trace() declaration The bug was introduced in commit 4052147c0afa ("mm, slab: Match SLAB and SLUB kmem_cache_alloc_xxx_trace() prototype"). Reported-by: Fengguang Wu Signed-off-by: Ezequiel Garcia Signed-off-by: Pekka Enberg Revert "mm/slab: Fix kmem_cache_alloc_node_trace() declaration" This reverts commit 1e5965bf1f018cc30a4659fa3f1a40146e4276f6. Ezequiel Garcia has a better fix. slab: Fix build failure in __kmem_cache_create() Fix build failure with CONFIG_DEBUG_SLAB=y && CONFIG_DEBUG_PAGEALLOC=y caused by commit 8a13a4cc "mm/sl[aou]b: Shrink __kmem_cache_create() parameter lists". mm/slab.c: In function '__kmem_cache_create': mm/slab.c:2474: error: 'align' undeclared (first use in this function) mm/slab.c:2474: error: (Each undeclared identifier is reported only once mm/slab.c:2474: error: for each function it appears in.) make[1]: *** [mm/slab.o] Error 1 make: *** [mm] Error 2 Acked-by: Christoph Lameter Signed-off-by: Tetsuo Handa Signed-off-by: Pekka Enberg mm/sl[au]b: Move slabinfo processing to slab_common.c This patch moves all the common machinery to slabinfo processing to slab_common.c. We can do better by noticing that the output is heavily common, and having the allocators to just provide finished information about this. But after this first step, this can be done easier. Signed-off-by: Glauber Costa Acked-by: Christoph Lameter CC: David Rientjes Signed-off-by: Pekka Enberg mm/sl[au]b: Move print_slabinfo_header to slab_common.c The header format is highly similar between slab and slub. The main difference lays in the fact that slab may optionally have statistics added here in case of CONFIG_SLAB_DEBUG, while the slub will stick them somewhere else. By making sure that information conditionally lives inside a globally-visible CONFIG_DEBUG_SLAB switch, we can move the header printing to a common location. Signed-off-by: Glauber Costa Acked-by: Christoph Lameter CC: David Rientjes Signed-off-by: Pekka Enberg sl[au]b: Process slabinfo_show in common code With all the infrastructure in place, we can now have slabinfo_show done from slab_common.c. A cache-specific function is called to grab information about the cache itself, since that is still heavily dependent on the implementation. But with the values produced by it, all the printing and handling is done from common code. Signed-off-by: Glauber Costa CC: Christoph Lameter CC: David Rientjes Signed-off-by: Pekka Enberg mm, slob: Use NUMA_NO_NODE instead of -1 Acked-by: David Rientjes Signed-off-by: Ezequiel Garcia Signed-off-by: Pekka Enberg Signed-off-by: Paul Reioux Conflicts: mm/slob.c mm, slob: Add support for kmalloc_track_caller() Currently slob falls back to regular kmalloc for this case. With this patch kmalloc_track_caller() is correctly implemented, thus tracing the specified caller. This is important to trace accurately allocations performed by krealloc, kstrdup, kmemdup, etc. Signed-off-by: Ezequiel Garcia Signed-off-by: Pekka Enberg mm, slob: fix build breakage in __kmalloc_node_track_caller On Sat, 8 Sep 2012, Ezequiel Garcia wrote: > @@ -454,15 +455,35 @@ void *__kmalloc_node(size_t size, gfp_t gfp, int node) > gfp |= __GFP_COMP; > ret = slob_new_pages(gfp, order, node); > > - trace_kmalloc_node(_RET_IP_, ret, > + trace_kmalloc_node(caller, ret, > size, PAGE_SIZE << order, gfp, node); > } > > kmemleak_alloc(ret, size, 1, gfp); > return ret; > } > + > +void *__kmalloc_node(size_t size, gfp_t gfp, int node) > +{ > + return __do_kmalloc_node(size, gfp, node, _RET_IP_); > +} > EXPORT_SYMBOL(__kmalloc_node); > > +#ifdef CONFIG_TRACING > +void *__kmalloc_track_caller(size_t size, gfp_t gfp, unsigned long caller) > +{ > + return __do_kmalloc_node(size, gfp, NUMA_NO_NODE, caller); > +} > + > +#ifdef CONFIG_NUMA > +void *__kmalloc_node_track_caller(size_t size, gfp_t gfpflags, > + int node, unsigned long caller) > +{ > + return __do_kmalloc_node(size, gfp, node, caller); > +} > +#endif This breaks Pekka's slab/next tree with this: mm/slob.c: In function '__kmalloc_node_track_caller': mm/slob.c:488: error: 'gfp' undeclared (first use in this function) mm/slob.c:488: error: (Each undeclared identifier is reported only once mm/slob.c:488: error: for each function it appears in.) mm, slob: fix build breakage in __kmalloc_node_track_caller "mm, slob: Add support for kmalloc_track_caller()" breaks the build because gfp is undeclared. Fix it. Acked-by: Ezequiel Garcia Signed-off-by: David Rientjes Signed-off-by: Pekka Enberg mm/slob: Drop usage of page->private for storing page-sized allocations This field was being used to store size allocation so it could be retrieved by ksize(). However, it is a bad practice to not mark a page as a slab page and then use fields for special purposes. There is no need to store the allocated size and ksize() can simply return PAGE_SIZE << compound_order(page). Cc: Pekka Enberg Cc: Matt Mackall Acked-by: Christoph Lameter Signed-off-by: Ezequiel Garcia Signed-off-by: Pekka Enberg mm/slob: Use object_size field in kmem_cache_size() Fields object_size and size are not the same: the latter might include slab metadata. Return object_size field in kmem_cache_size(). Also, improve trace accuracy by correctly tracing reported size. Cc: Pekka Enberg Cc: Matt Mackall Acked-by: Christoph Lameter Acked-by: David Rientjes Signed-off-by: Ezequiel Garcia Signed-off-by: Pekka Enberg mm/sl[aou]b: Move common kmem_cache_size() to slab.h This function is identically defined in all three allocators and it's trivial to move it to slab.h Since now it's static, inline, header-defined function this patch also drops the EXPORT_SYMBOL tag. Cc: Pekka Enberg Cc: Matt Mackall Acked-by: Christoph Lameter Signed-off-by: Ezequiel Garcia Signed-off-by: Pekka Enberg slab: Ignore internal flags in cache creation Some flags are used internally by the allocators for management purposes. One example of that is the CFLGS_OFF_SLAB flag that slab uses to mark that the metadata for that cache is stored outside of the slab. No cache should ever pass those as a creation flags. We can just ignore this bit if it happens to be passed (such as when duplicating a cache in the kmem memcg patches). Because such flags can vary from allocator to allocator, we allow them to make their own decisions on that, defining SLAB_AVAILABLE_FLAGS with all flags that are valid at creation time. Allocators that doesn't have any specific flag requirement should define that to mean all flags. Common code will mask out all flags not belonging to that set. Acked-by: Christoph Lameter Acked-by: David Rientjes Signed-off-by: Glauber Costa Signed-off-by: Pekka Enberg mm: fix slab.c kernel-doc warnings Fix new kernel-doc warnings in mm/slab.c: Warning(mm/slab.c:2358): No description found for parameter 'cachep' Warning(mm/slab.c:2358): Excess function parameter 'name' description in '__kmem_cache_create' Warning(mm/slab.c:2358): Excess function parameter 'size' description in '__kmem_cache_create' Warning(mm/slab.c:2358): Excess function parameter 'align' description in '__kmem_cache_create' Warning(mm/slab.c:2358): Excess function parameter 'ctor' description in '__kmem_cache_create' Signed-off-by: Randy Dunlap Cc: Christoph Lameter Cc: Pekka Enberg Cc: Matt Mackall Signed-off-by: Pekka Enberg slab: Simplify bootstrap The nodelists field in kmem_cache is pointing to the first unused object in the array field when bootstrap is complete. A problem with the current approach is that the statically sized kmem_cache structure use on boot can only contain NR_CPUS entries. If the number of nodes plus the number of cpus is greater then we would overwrite memory following the kmem_cache_boot definition. Increase the size of the array field to ensure that also the node pointers fit into the array field. Once we do that we no longer need the kmem_cache_nodelists array and we can then also use that structure elsewhere. Acked-by: Glauber Costa Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg Revert "mm/sl[aou]b: Move sysfs_slab_add to common" This reverts commit 96d17b7be0a9849d381442030886211dbb2a7061 which caused the following errors at boot: [ 1.114885] kobject (ffff88001a802578): tried to init an initialized object, something is seriously wrong. [ 1.114885] Pid: 1, comm: swapper/0 Tainted: G W 3.6.0-rc1+ #6 [ 1.114885] Call Trace: [ 1.114885] [] kobject_init+0x87/0xa0 [ 1.115555] [] kobject_init_and_add+0x2a/0x90 [ 1.115555] [] ? sprintf+0x40/0x50 [ 1.115555] [] sysfs_slab_add+0x80/0x210 [ 1.115555] [] kmem_cache_create+0xa5/0x250 [ 1.115555] [] ? md_init+0x144/0x144 [ 1.115555] [] local_init+0xa4/0x11b [ 1.115555] [] dm_init+0x14/0x45 [ 1.115836] [] do_one_initcall+0x3a/0x160 [ 1.116834] [] kernel_init+0x133/0x1b7 [ 1.117835] [] ? do_early_param+0x86/0x86 [ 1.117835] [] kernel_thread_helper+0x4/0x10 [ 1.118401] [] ? start_kernel+0x33f/0x33f [ 1.119832] [] ? gs_change+0xb/0xb [ 1.120325] ------------[ cut here ]------------ [ 1.120835] WARNING: at fs/sysfs/dir.c:536 sysfs_add_one+0xc1/0xf0() [ 1.121437] sysfs: cannot create duplicate filename '/kernel/slab/:t-0000016' [ 1.121831] Modules linked in: [ 1.122138] Pid: 1, comm: swapper/0 Tainted: G W 3.6.0-rc1+ #6 [ 1.122831] Call Trace: [ 1.123074] [] ? sysfs_add_one+0xc1/0xf0 [ 1.123833] [] warn_slowpath_common+0x7a/0xb0 [ 1.124405] [] warn_slowpath_fmt+0x41/0x50 [ 1.124832] [] sysfs_add_one+0xc1/0xf0 [ 1.125337] [] create_dir+0x73/0xd0 [ 1.125832] [] sysfs_create_dir+0x81/0xe0 [ 1.126363] [] kobject_add_internal+0x9d/0x210 [ 1.126832] [] kobject_init_and_add+0x63/0x90 [ 1.127406] [] sysfs_slab_add+0x80/0x210 [ 1.127832] [] kmem_cache_create+0xa5/0x250 [ 1.128384] [] ? md_init+0x144/0x144 [ 1.128833] [] local_init+0xa4/0x11b [ 1.129831] [] dm_init+0x14/0x45 [ 1.130305] [] do_one_initcall+0x3a/0x160 [ 1.130831] [] kernel_init+0x133/0x1b7 [ 1.131351] [] ? do_early_param+0x86/0x86 [ 1.131830] [] kernel_thread_helper+0x4/0x10 [ 1.132392] [] ? start_kernel+0x33f/0x33f [ 1.132830] [] ? gs_change+0xb/0xb [ 1.133315] ---[ end trace 2703540871c8fab7 ]--- [ 1.133830] ------------[ cut here ]------------ [ 1.134274] WARNING: at lib/kobject.c:196 kobject_add_internal+0x1f5/0x210() [ 1.134829] kobject_add_internal failed for :t-0000016 with -EEXIST, don't try to register things with the same name in the same directory. [ 1.135829] Modules linked in: [ 1.136135] Pid: 1, comm: swapper/0 Tainted: G W 3.6.0-rc1+ #6 [ 1.136828] Call Trace: [ 1.137071] [] ? kobject_add_internal+0x1f5/0x210 [ 1.137830] [] warn_slowpath_common+0x7a/0xb0 [ 1.138402] [] warn_slowpath_fmt+0x41/0x50 [ 1.138830] [] ? release_sysfs_dirent+0x73/0xf0 [ 1.139419] [] kobject_add_internal+0x1f5/0x210 [ 1.139830] [] kobject_init_and_add+0x63/0x90 [ 1.140429] [] sysfs_slab_add+0x80/0x210 [ 1.140830] [] kmem_cache_create+0xa5/0x250 [ 1.141829] [] ? md_init+0x144/0x144 [ 1.142307] [] local_init+0xa4/0x11b [ 1.142829] [] dm_init+0x14/0x45 [ 1.143307] [] do_one_initcall+0x3a/0x160 [ 1.143829] [] kernel_init+0x133/0x1b7 [ 1.144352] [] ? do_early_param+0x86/0x86 [ 1.144829] [] kernel_thread_helper+0x4/0x10 [ 1.145405] [] ? start_kernel+0x33f/0x33f [ 1.145828] [] ? gs_change+0xb/0xb [ 1.146313] ---[ end trace 2703540871c8fab8 ]--- Conflicts: mm/slub.c Signed-off-by: Pekka Enberg mm/slub.c: android kernel compatibility fixup underp the failed patch @ slub: Acquire_slab() avoid loop Signed-off-by: Paul Reioux slub: Zero initial memory segment for kmem_cache and kmem_cache_node Tony Luck reported the following problem on IA-64: Worked fine yesterday on next-20120905, crashes today. First sign of trouble was an unaligned access, then a NULL dereference. SL*B related bits of my config: CONFIG_SLUB_DEBUG=y # CONFIG_SLAB is not set CONFIG_SLUB=y CONFIG_SLABINFO=y # CONFIG_SLUB_DEBUG_ON is not set # CONFIG_SLUB_STATS is not set And he console log. PID hash table entries: 4096 (order: 1, 32768 bytes) Dentry cache hash table entries: 262144 (order: 7, 2097152 bytes) Inode-cache hash table entries: 131072 (order: 6, 1048576 bytes) Memory: 2047920k/2086064k available (13992k code, 38144k reserved, 6012k data, 880k init) kernel unaligned access to 0xca2ffc55fb373e95, ip=0xa0000001001be550 swapper[0]: error during unaligned kernel access -1 [1] Modules linked in: Pid: 0, CPU 0, comm: swapper psr : 00001010084a2018 ifs : 800000000000060f ip : [] Not tainted (3.6.0-rc4-zx1-smp-next-20120906) ip is at new_slab+0x90/0x680 unat: 0000000000000000 pfs : 000000000000060f rsc : 0000000000000003 rnat: 9666960159966a59 bsps: a0000001001441c0 pr : 9666960159965a59 ldrs: 0000000000000000 ccv : 0000000000000000 fpsr: 0009804c8a70433f csd : 0000000000000000 ssd : 0000000000000000 b0 : a0000001001be500 b6 : a00000010112cb20 b7 : a0000001011660a0 f6 : 0fff7f0f0f0f0e54f0000 f7 : 0ffe8c5c1000000000000 f8 : 1000d8000000000000000 f9 : 100068800000000000000 f10 : 10005f0f0f0f0e54f0000 f11 : 1003e0000000000000078 r1 : a00000010155eef0 r2 : 0000000000000000 r3 : fffffffffffc1638 r8 : e0000040600081b8 r9 : ca2ffc55fb373e95 r10 : 0000000000000000 r11 : e000004040001646 r12 : a000000101287e20 r13 : a000000101280000 r14 : 0000000000004000 r15 : 0000000000000078 r16 : ca2ffc55fb373e75 r17 : e000004040040000 r18 : fffffffffffc1646 r19 : e000004040001646 r20 : fffffffffffc15f8 r21 : 000000000000004d r22 : a00000010132fa68 r23 : 00000000000000ed r24 : 0000000000000000 r25 : 0000000000000000 r26 : 0000000000000001 r27 : a0000001012b8500 r28 : a00000010135f4a0 r29 : 0000000000000000 r30 : 0000000000000000 r31 : 0000000000000001 Unable to handle kernel NULL pointer dereference (address 0000000000000018) swapper[0]: Oops 11003706212352 [2] Modules linked in: Pid: 0, CPU 0, comm: swapper psr : 0000121008022018 ifs : 800000000000cc18 ip : [] Not tainted (3.6.0-rc4-zx1-smp-next-20120906) ip is at __copy_user+0x891/0x960 unat: 0000000000000000 pfs : 0000000000000813 rsc : 0000000000000003 rnat: 0000000000000000 bsps: 0000000000000000 pr : 9666960159961765 ldrs: 0000000000000000 ccv : 0000000000000000 fpsr: 0009804c0270033f csd : 0000000000000000 ssd : 0000000000000000 b0 : a00000010004b550 b6 : a00000010004b740 b7 : a00000010000c750 f6 : 000000000000000000000 f7 : 1003e9e3779b97f4a7c16 f8 : 1003e0a00000010001550 f9 : 100068800000000000000 f10 : 10005f0f0f0f0e54f0000 f11 : 1003e0000000000000078 r1 : a00000010155eef0 r2 : a0000001012870b0 r3 : a0000001012870b8 r8 : 0000000000000298 r9 : 0000000000000013 r10 : 0000000000000000 r11 : 9666960159961a65 r12 : a000000101287010 r13 : a000000101280000 r14 : a000000101287068 r15 : a000000101287080 r16 : 0000000000000298 r17 : 0000000000000010 r18 : 0000000000000018 r19 : a000000101287310 r20 : 0000000000000290 r21 : 0000000000000000 r22 : 0000000000000000 r23 : a000000101386f58 r24 : 0000000000000000 r25 : 000000007fffffff r26 : a000000101287078 r27 : a0000001013c69b0 r28 : 0000000000000000 r29 : 0000000000000014 r30 : 0000000000000000 r31 : 0000000000000813 Sedat Dilek and Hugh Dickins reported similar problems as well. Earlier patches in the common set moved the zeroing of the kmem_cache structure into common code. See "Move allocation of kmem_cache into common code". The allocation for the two special structures is still done from SLUB specific code but no zeroing is done since the cache creation functions used to zero. This now needs to be updated so that the structures are zeroed during allocation in kmem_cache_init(). Otherwise random pointer values may be followed. Reported-by: Tony Luck Reported-by: Sedat Dilek Tested-by: Sedat Dilek Reported-by: Hugh Dickins Tested-by: Sedat Dilek Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg slub: consider pfmemalloc_match() in get_partial_node() get_partial() is currently not checking pfmemalloc_match() meaning that it is possible for pfmemalloc pages to leak to non-pfmemalloc users. This is a problem in the following situation. Assume that there is a request from normal allocation and there are no objects in the per-cpu cache and no node-partial slab. In this case, slab_alloc enters the slow path and new_slab_objects() is called which may return a PFMEMALLOC page. As the current user is not allowed to access PFMEMALLOC page, deactivate_slab() is called ([5091b74a: mm: slub: optimise the SLUB fast path to avoid pfmemalloc checks]) and returns an object from PFMEMALLOC page. Next time, when we get another request from normal allocation, slab_alloc() enters the slow-path and calls new_slab_objects(). In new_slab_objects(), we call get_partial() and get a partial slab which was just deactivated but is a pfmemalloc page. We extract one object from it and re-deactivate. "deactivate -> re-get in get_partial -> re-deactivate" occures repeatedly. As a result, access to PFMEMALLOC page is not properly restricted and it can cause a performance degradation due to frequent deactivation. deactivation frequently. This patch changes get_partial_node() to take pfmemalloc_match() into account and prevents the "deactivate -> re-get in get_partial() scenario. Instead, new_slab() is called. Signed-off-by: Joonsoo Kim Acked-by: David Rientjes Signed-off-by: Mel Gorman Cc: David Miller Cc: Chuck Lever Cc: Pekka Enberg Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds mm, slub: Rename slab_alloc() -> slab_alloc_node() to match SLAB This patch does not fix anything, and its only goal is to enable us to obtain some common code between SLAB and SLUB. Neither behavior nor produced code is affected. Cc: Christoph Lameter Signed-off-by: Ezequiel Garcia Signed-off-by: Pekka Enberg slub: init_kmem_cache_cpus() and put_cpu_partial() can be static Acked-by: Glauber Costa Acked-by: Christoph Lameter Acked-by: David Rientjes Signed-off-by: Fengguang Wu Signed-off-by: Pekka Enberg slub: remove one code path and reduce lock contention in __slab_free() When we try to free object, there is some of case that we need to take a node lock. This is the necessary step for preventing a race. After taking a lock, then we try to cmpxchg_double_slab(). But, there is a possible scenario that cmpxchg_double_slab() is failed with taking a lock. Following example explains it. CPU A CPU B need lock ... need lock ... lock!! lock..but spin free success spin... unlock lock!! free fail In this case, retry with taking a lock is occured in CPU A. I think that in this case for CPU A, "release a lock first, and re-take a lock if necessary" is preferable way. There are two reasons for this. First, this makes __slab_free()'s logic somehow simple. With this patch, 'was_frozen = 1' is "always" handled without taking a lock. So we can remove one code path. Second, it may reduce lock contention. When we do retrying, status of slab is already changed, so we don't need a lock anymore in almost every case. "release a lock first, and re-take a lock if necessary" policy is helpful to this. Signed-off-by: Joonsoo Kim Acked-by: Christoph Lameter Signed-off-by: Pekka Enberg slub: Commonize slab_cache field in struct page Right now, slab and slub have fields in struct page to derive which cache a page belongs to, but they do it slightly differently. slab uses a field called slab_cache, that lives in the third double word. slub, uses a field called "slab", living outside of the doublewords area. Ideally, we could use the same field for this. Since slub heavily makes use of the doubleword region, there isn't really much room to move slub's slab_cache field around. Since slab does not have such strict placement restrictions, we can move it outside the doubleword area. The naming used by slab, "slab_cache", is less confusing, and it is preferred over slub's generic "slab". Signed-off-by: Glauber Costa Acked-by: Christoph Lameter CC: David Rientjes Signed-off-by: Pekka Enberg slub: Use correct cpu_slab on dead cpu Pass a kmem_cache_cpu pointer into unfreeze partials so that a different kmem_cache_cpu structure than the local one can be specified. Acked-by: David Rientjes Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg mm, sl[au]b: create common functions for boot slab creation Use a special function to create kmalloc caches and use that function in SLAB and SLUB. Acked-by: Joonsoo Kim Reviewed-by: Glauber Costa Acked-by: David Rientjes Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg slab: Use the new create_boot_cache function to simplify bootstrap Simplify setup and reduce code in kmem_cache_init(). This allows us to get rid of initarray_cache as well as the manual setup code for the kmem_cache and kmem_cache_node arrays during bootstrap. We introduce a new bootstrap state "PARTIAL" for slab that signals the creation of a kmem_cache boot cache. Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg mm/sl[aou]b: Common alignment code Extract the code to do object alignment from the allocators. Do the alignment calculations in slab_common so that the __kmem_cache_create functions of the allocators do not have to deal with alignment. Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg slab: annotate on-slab caches nodelist locks We currently provide lockdep annotation for kmalloc caches, and also caches that have SLAB_DEBUG_OBJECTS enabled. The reason for this is that we can quite frequently nest in the l3->list_lock lock, which is not something trivial to avoid. My proposal with this patch, is to extend this to caches whose slab management object lives within the slab as well ("on_slab"). The need for this arose in the context of testing kmemcg-slab patches. With such patchset, we can have per-memcg kmalloc caches. So the same path that led to nesting between kmalloc caches will could then lead to in-memcg nesting. Because they are not annotated, lockdep will trigger. Signed-off-by: Glauber Costa Cc: Christoph Lameter Cc: David Rientjes Cc: Frederic Weisbecker Cc: Greg Thelen Cc: Johannes Weiner Cc: JoonSoo Kim Cc: KAMEZAWA Hiroyuki Cc: Mel Gorman Cc: Michal Hocko Cc: Pekka Enberg Cc: Rik van Riel Cc: Suleiman Souhlal Cc: Tejun Heo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds sl[au]b: always get the cache from its page in kmem_cache_free() struct page already has this information. If we start chaining caches, this information will always be more trustworthy than whatever is passed into the function. Signed-off-by: Glauber Costa Cc: Christoph Lameter Cc: David Rientjes Cc: Frederic Weisbecker Cc: Greg Thelen Cc: Johannes Weiner Cc: JoonSoo Kim Cc: KAMEZAWA Hiroyuki Cc: Mel Gorman Cc: Michal Hocko Cc: Pekka Enberg Cc: Rik van Riel Cc: Suleiman Souhlal Cc: Tejun Heo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds backported to Android Linux 3.4 by faux123 Signed-off-by: Paul Reioux Conflicts: include/linux/memcontrol.h mm/slab.h Revert "mm: micro-optimise slab to avoid a function call" This reverts commit 381760eadc393bcb1bb328510ad75cf13431806d. slub: Use statically allocated kmem_cache boot structure for bootstrap Simplify bootstrap by statically allocated two kmem_cache structures. These are freed after bootup is complete. Allows us to no longer worry about calculations of sizes of kmem_cache structures during bootstrap. Reviewed-by: Glauber Costa Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg slub, hotplug: ignore unrelated node's hot-adding and hot-removing SLUB only focuses on the nodes which have normal memory and it ignores the other node's hot-adding and hot-removing. Aka: if some memory of a node which has no onlined memory is online, but this new memory onlined is not normal memory (for example, highmem), we should not allocate kmem_cache_node for SLUB. And if the last normal memory is offlined, but the node still has memory, we should remove kmem_cache_node for that node. (The current code delays it when all of the memory is offlined) So we only do something when marg->status_change_nid_normal > 0. marg->status_change_nid is not suitable here. The same problem doesn't exist in SLAB, because SLAB allocates kmem_list3 for every node even the node don't have normal memory, SLAB tolerates kmem_list3 on alien nodes. SLUB only focuses on the nodes which have normal memory, it don't tolerate alien kmem_cache_node. The patch makes SLUB become self-compatible and avoids WARNs and BUGs in rare conditions. Change-Id: I4b52332042b62c804de44023f0ce1cb358432401 Signed-off-by: Lai Jiangshan Cc: David Rientjes Cc: Minchan Kim Cc: KOSAKI Motohiro Cc: Yasuaki Ishimatsu Cc: Rob Landley Cc: Andrew Morton Cc: Jiang Liu Cc: Kay Sievers Cc: Greg Kroah-Hartman Cc: Mel Gorman Cc: Wen Congyang Acked-by: Christoph Lameter Cc: Pekka Enberg Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: poondog --- arch/s390/mm/pgtable.c | 4 +- fs/aio.c | 96 +-- include/linux/aio.h | 1 - include/linux/gfp.h | 10 +- include/linux/mempolicy.h | 2 +- include/linux/mm_types.h | 22 +- include/linux/page-flags.h | 29 + include/linux/slab.h | 39 +- include/linux/slab_def.h | 30 +- include/linux/slob_def.h | 6 +- include/linux/slub_def.h | 3 +- include/trace/events/gfpflags.h | 1 + kernel/fork.c | 2 +- mm/Makefile | 3 +- mm/internal.h | 4 + mm/mempolicy.c | 8 +- mm/page_alloc.c | 23 +- mm/slab.c | 1118 ++++++++++++++----------------- mm/slab.h | 128 ++++ mm/slab_common.c | 371 ++++++++++ mm/slob.c | 253 +++---- mm/slub.c | 917 ++++++++++--------------- 22 files changed, 1656 insertions(+), 1414 deletions(-) create mode 100644 mm/slab.h create mode 100644 mm/slab_common.c diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c index 87f0efd0e77..4674105db03 100644 --- a/arch/s390/mm/pgtable.c +++ b/arch/s390/mm/pgtable.c @@ -807,7 +807,7 @@ int s390_enable_sie(void) task_lock(tsk); if (!tsk->mm || atomic_read(&tsk->mm->mm_users) > 1 || #ifdef CONFIG_AIO - !hlist_empty(&tsk->mm->ioctx_list) || + tsk->mm->ioctx_rtree.rnode || #endif tsk->mm != tsk->active_mm) { task_unlock(tsk); @@ -826,7 +826,7 @@ int s390_enable_sie(void) task_lock(tsk); if (!tsk->mm || atomic_read(&tsk->mm->mm_users) > 1 || #ifdef CONFIG_AIO - !hlist_empty(&tsk->mm->ioctx_list) || + tsk->mm->ioctx_rtree.rnode || #endif tsk->mm != tsk->active_mm) { mmput(mm); diff --git a/fs/aio.c b/fs/aio.c index 01be7f60a8a..59ceb9291b3 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -285,10 +286,18 @@ static struct kioctx *ioctx_alloc(unsigned nr_events) aio_nr += ctx->max_reqs; spin_unlock(&aio_nr_lock); - /* now link into global list. */ + /* now insert into the radix tree */ + err = radix_tree_preload(GFP_KERNEL); + if (err) + goto out_cleanup; spin_lock(&mm->ioctx_lock); - hlist_add_head_rcu(&ctx->list, &mm->ioctx_list); + err = radix_tree_insert(&mm->ioctx_rtree, ctx->user_id, ctx); spin_unlock(&mm->ioctx_lock); + radix_tree_preload_end(); + if (err) { + WARN_ONCE(1, "aio: insert into ioctx tree failed: %d", err); + goto out_cleanup; + } dprintk("aio: allocated ioctx %p[%ld]: mm=%p mask=0x%x\n", ctx, ctx->user_id, current->mm, ctx->ring_info.nr); @@ -366,6 +375,32 @@ ssize_t wait_on_sync_kiocb(struct kiocb *iocb) } EXPORT_SYMBOL(wait_on_sync_kiocb); +static inline void exit_aio_ctx(struct mm_struct *mm, struct kioctx *ctx) +{ + void *ret; + + ret = radix_tree_delete(&mm->ioctx_rtree, ctx->user_id); + BUG_ON(!ret || ret != ctx); + + kill_ctx(ctx); + + if (1 != atomic_read(&ctx->users)) + pr_debug("exit_aio:ioctx still alive: %d %d %d\n", + atomic_read(&ctx->users), ctx->dead, ctx->reqs_active); + /* + * We don't need to bother with munmap() here - + * exit_mmap(mm) is coming and it'll unmap everything. + * Since aio_free_ring() uses non-zero ->mmap_size + * as indicator that it needs to unmap the area, + * just set it to 0; aio_free_ring() is the only + * place that uses ->mmap_size, so it's safe. + * That way we get all munmap done to current->mm - + * all other callers have ctx->mm == current->mm. + */ + ctx->ring_info.mmap_size = 0; + put_ioctx(ctx); +} + /* exit_aio: called when the last user of mm goes away. At this point, * there is no way for any new requests to be submited or any of the * io_* syscalls to be called on the context. However, there may be @@ -375,32 +410,17 @@ EXPORT_SYMBOL(wait_on_sync_kiocb); */ void exit_aio(struct mm_struct *mm) { - struct kioctx *ctx; + struct kioctx *ctx[16]; + int count; - while (!hlist_empty(&mm->ioctx_list)) { - ctx = hlist_entry(mm->ioctx_list.first, struct kioctx, list); - hlist_del_rcu(&ctx->list); - - kill_ctx(ctx); + do { + int i; - if (1 != atomic_read(&ctx->users)) - printk(KERN_DEBUG - "exit_aio:ioctx still alive: %d %d %d\n", - atomic_read(&ctx->users), ctx->dead, - ctx->reqs_active); - /* - * We don't need to bother with munmap() here - - * exit_mmap(mm) is coming and it'll unmap everything. - * Since aio_free_ring() uses non-zero ->mmap_size - * as indicator that it needs to unmap the area, - * just set it to 0; aio_free_ring() is the only - * place that uses ->mmap_size, so it's safe. - * That way we get all munmap done to current->mm - - * all other callers have ctx->mm == current->mm. - */ - ctx->ring_info.mmap_size = 0; - put_ioctx(ctx); - } + count = radix_tree_gang_lookup(&mm->ioctx_rtree, (void **)ctx, + 0, ARRAY_SIZE(ctx)); + for (i = 0; i < count; i++) + exit_aio_ctx(mm, ctx[i]); + } while (count); } /* aio_get_req @@ -655,22 +675,18 @@ static struct kioctx *lookup_ioctx(unsigned long ctx_id) { struct mm_struct *mm = current->mm; struct kioctx *ctx, *ret = NULL; - struct hlist_node *n; rcu_read_lock(); - hlist_for_each_entry_rcu(ctx, n, &mm->ioctx_list, list) { - /* - * RCU protects us against accessing freed memory but - * we have to be careful not to get a reference when the - * reference count already dropped to 0 (ctx->dead test - * is unreliable because of races). - */ - if (ctx->user_id == ctx_id && !ctx->dead && try_get_ioctx(ctx)){ - ret = ctx; - break; - } - } + ctx = radix_tree_lookup(&mm->ioctx_rtree, ctx_id); + /* + * RCU protects us against accessing freed memory but + * we have to be careful not to get a reference when the + * reference count already dropped to 0 (ctx->dead test + * is unreliable because of races). + */ + if (ctx && !ctx->dead && try_get_ioctx(ctx)) + ret = ctx; rcu_read_unlock(); return ret; @@ -1265,7 +1281,7 @@ static void io_destroy(struct kioctx *ioctx) spin_lock(&mm->ioctx_lock); was_dead = ioctx->dead; ioctx->dead = 1; - hlist_del_rcu(&ioctx->list); + radix_tree_delete(&mm->ioctx_rtree, ioctx->user_id); spin_unlock(&mm->ioctx_lock); dprintk("aio_release(%p)\n", ioctx); diff --git a/include/linux/aio.h b/include/linux/aio.h index b1a520ec8b5..42830d7465f 100644 --- a/include/linux/aio.h +++ b/include/linux/aio.h @@ -184,7 +184,6 @@ struct kioctx { /* This needs improving */ unsigned long user_id; - struct hlist_node list; wait_queue_head_t wait; diff --git a/include/linux/gfp.h b/include/linux/gfp.h index 7b3823e213e..55acab018be 100644 --- a/include/linux/gfp.h +++ b/include/linux/gfp.h @@ -30,6 +30,7 @@ struct vm_area_struct; #define ___GFP_HARDWALL 0x20000u #define ___GFP_THISNODE 0x40000u #define ___GFP_RECLAIMABLE 0x80000u +#define ___GFP_MEMALLOC 0x100000u #ifdef CONFIG_KMEMCHECK #define ___GFP_NOTRACK 0x200000u #else @@ -79,9 +80,14 @@ struct vm_area_struct; #define __GFP_REPEAT ((__force gfp_t)___GFP_REPEAT) /* See above */ #define __GFP_NOFAIL ((__force gfp_t)___GFP_NOFAIL) /* See above */ #define __GFP_NORETRY ((__force gfp_t)___GFP_NORETRY) /* See above */ +#define __GFP_MEMALLOC ((__force gfp_t)___GFP_MEMALLOC)/* Allow access to emergency reserves */ #define __GFP_COMP ((__force gfp_t)___GFP_COMP) /* Add compound page metadata */ #define __GFP_ZERO ((__force gfp_t)___GFP_ZERO) /* Return zeroed page on success */ -#define __GFP_NOMEMALLOC ((__force gfp_t)___GFP_NOMEMALLOC) /* Don't use emergency reserves */ +#define __GFP_NOMEMALLOC ((__force gfp_t)___GFP_NOMEMALLOC) /* Don't use emergency reserves. + * This takes precedence over the + * __GFP_MEMALLOC flag if both are + * set + */ #define __GFP_HARDWALL ((__force gfp_t)___GFP_HARDWALL) /* Enforce hardwall cpuset memory allocs */ #define __GFP_THISNODE ((__force gfp_t)___GFP_THISNODE)/* No fallback, no policies */ #define __GFP_RECLAIMABLE ((__force gfp_t)___GFP_RECLAIMABLE) /* Page is reclaimable */ @@ -132,7 +138,7 @@ struct vm_area_struct; /* Control page allocator reclaim behavior */ #define GFP_RECLAIM_MASK (__GFP_WAIT|__GFP_HIGH|__GFP_IO|__GFP_FS|\ __GFP_NOWARN|__GFP_REPEAT|__GFP_NOFAIL|\ - __GFP_NORETRY|__GFP_NOMEMALLOC) + __GFP_NORETRY|__GFP_MEMALLOC|__GFP_NOMEMALLOC) /* Control slab gfp mask during early boot */ #define GFP_BOOT_MASK (__GFP_BITS_MASK & ~(__GFP_WAIT|__GFP_IO|__GFP_FS)) diff --git a/include/linux/mempolicy.h b/include/linux/mempolicy.h index fe07e5a9056..cc49b232b6e 100644 --- a/include/linux/mempolicy.h +++ b/include/linux/mempolicy.h @@ -205,7 +205,7 @@ extern struct zonelist *huge_zonelist(struct vm_area_struct *vma, extern bool init_nodemask_of_mempolicy(nodemask_t *mask); extern bool mempolicy_nodemask_intersects(struct task_struct *tsk, const nodemask_t *mask); -extern unsigned slab_node(struct mempolicy *policy); +extern unsigned slab_node(void); extern enum zone_type policy_zone; diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h index 4fc12b203f0..476e00d745e 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -52,7 +53,16 @@ struct page { struct { union { pgoff_t index; /* Our offset within mapping. */ - void *freelist; /* slub first free object */ + void *freelist; /* slub/slob first free object */ + bool pfmemalloc; /* If set by the page allocator, + * ALLOC_NO_WATERMARKS was set + * and the low watermark was not + * met implying that the system + * is under some pressure. The + * caller should try ensure + * this page is only used to + * free other pages. + */ }; union { @@ -90,11 +100,12 @@ struct page { */ atomic_t _mapcount; - struct { + struct { /* SLUB */ unsigned inuse:16; unsigned objects:15; unsigned frozen:1; }; + int units; /* SLOB */ }; atomic_t _count; /* Usage count, see below. */ }; @@ -116,6 +127,9 @@ struct page { short int pobjects; #endif }; + + struct list_head list; /* slobs list of pages */ + struct slab *slab_page; /* slab fields */ }; /* Remainder is not double word aligned */ @@ -130,7 +144,7 @@ struct page { #if USE_SPLIT_PTLOCKS spinlock_t ptl; #endif - struct kmem_cache *slab; /* SLUB: Pointer to slab */ + struct kmem_cache *slab_cache; /* SL[AU]B: Pointer to slab */ struct page *first_page; /* Compound tail pages */ }; @@ -375,7 +389,7 @@ struct mm_struct { struct core_state *core_state; /* coredumping support */ #ifdef CONFIG_AIO spinlock_t ioctx_lock; - struct hlist_head ioctx_list; + struct radix_tree_root ioctx_rtree; #endif #ifdef CONFIG_MM_OWNER /* diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h index 5bc4fa5c6f1..d10f1a57389 100644 --- a/include/linux/page-flags.h +++ b/include/linux/page-flags.h @@ -7,6 +7,7 @@ #include #include +#include #ifndef __GENERATING_BOUNDS_H #include #include @@ -460,6 +461,34 @@ static inline int PageTransTail(struct page *page) } #endif +/* + * If network-based swap is enabled, sl*b must keep track of whether pages + * were allocated from pfmemalloc reserves. + */ +static inline int PageSlabPfmemalloc(struct page *page) +{ + VM_BUG_ON(!PageSlab(page)); + return PageActive(page); +} + +static inline void SetPageSlabPfmemalloc(struct page *page) +{ + VM_BUG_ON(!PageSlab(page)); + SetPageActive(page); +} + +static inline void __ClearPageSlabPfmemalloc(struct page *page) +{ + VM_BUG_ON(!PageSlab(page)); + __ClearPageActive(page); +} + +static inline void ClearPageSlabPfmemalloc(struct page *page) +{ + VM_BUG_ON(!PageSlab(page)); + ClearPageActive(page); +} + #ifdef CONFIG_MMU #define __PG_MLOCKED (1 << PG_mlocked) #else diff --git a/include/linux/slab.h b/include/linux/slab.h index a595dce6b0c..2085d04b1c7 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -92,6 +92,30 @@ #define ZERO_OR_NULL_PTR(x) ((unsigned long)(x) <= \ (unsigned long)ZERO_SIZE_PTR) +/* + * Common fields provided in kmem_cache by all slab allocators + * This struct is either used directly by the allocator (SLOB) + * or the allocator must include definitions for all fields + * provided in kmem_cache_common in their definition of kmem_cache. + * + * Once we can do anonymous structs (C11 standard) we could put a + * anonymous struct definition in these allocators so that the + * separate allocations in the kmem_cache structure of SLAB and + * SLUB is no longer needed. + */ +#ifdef CONFIG_SLOB +struct kmem_cache { + unsigned int object_size;/* The original size of the object */ + unsigned int size; /* The aligned/padded/added on size */ + unsigned int align; /* Alignment as calculated */ + unsigned long flags; /* Active flags on the slab */ + const char *name; /* Slab name for sysfs */ + int refcount; /* Use counter */ + void (*ctor)(void *); /* Called on object slot creation */ + struct list_head list; /* List of all slab caches on the system */ +}; +#endif + /* * struct kmem_cache related prototypes */ @@ -104,7 +128,6 @@ struct kmem_cache *kmem_cache_create(const char *, size_t, size_t, void kmem_cache_destroy(struct kmem_cache *); int kmem_cache_shrink(struct kmem_cache *); void kmem_cache_free(struct kmem_cache *, void *); -unsigned int kmem_cache_size(struct kmem_cache *); /* * Please use this macro to create slab caches. Simply specify the @@ -297,7 +320,8 @@ static inline void *kmem_cache_alloc_node(struct kmem_cache *cachep, * request comes from. */ #if defined(CONFIG_DEBUG_SLAB) || defined(CONFIG_SLUB) || \ - (defined(CONFIG_SLAB) && defined(CONFIG_TRACING)) + (defined(CONFIG_SLAB) && defined(CONFIG_TRACING)) || \ + (defined(CONFIG_SLOB) && defined(CONFIG_TRACING)) extern void *__kmalloc_track_caller(size_t, gfp_t, unsigned long); #define kmalloc_track_caller(size, flags) \ __kmalloc_track_caller(size, flags, _RET_IP_) @@ -316,7 +340,8 @@ extern void *__kmalloc_track_caller(size_t, gfp_t, unsigned long); * allocation request comes from. */ #if defined(CONFIG_DEBUG_SLAB) || defined(CONFIG_SLUB) || \ - (defined(CONFIG_SLAB) && defined(CONFIG_TRACING)) + (defined(CONFIG_SLAB) && defined(CONFIG_TRACING)) || \ + (defined(CONFIG_SLOB) && defined(CONFIG_TRACING)) extern void *__kmalloc_node_track_caller(size_t, gfp_t, int, unsigned long); #define kmalloc_node_track_caller(size, flags, node) \ __kmalloc_node_track_caller(size, flags, node, \ @@ -362,6 +387,14 @@ static inline void *kzalloc_node(size_t size, gfp_t flags, int node) return kmalloc_node(size, flags | __GFP_ZERO, node); } +/* + * Determine the size of a slab object + */ +static inline unsigned int kmem_cache_size(struct kmem_cache *s) +{ + return s->object_size; +} + void __init kmem_cache_init_late(void); #endif /* _LINUX_SLAB_H */ diff --git a/include/linux/slab_def.h b/include/linux/slab_def.h index fbd1117fdfd..b91c69ffb52 100644 --- a/include/linux/slab_def.h +++ b/include/linux/slab_def.h @@ -27,7 +27,7 @@ struct kmem_cache { unsigned int limit; unsigned int shared; - unsigned int buffer_size; + unsigned int size; u32 reciprocal_buffer_size; /* 2) touched by every alloc & free from the backend */ @@ -39,7 +39,7 @@ struct kmem_cache { unsigned int gfporder; /* force GFP flags, e.g. GFP_DMA */ - gfp_t gfpflags; + gfp_t allocflags; size_t colour; /* cache colouring range */ unsigned int colour_off; /* colour offset */ @@ -52,7 +52,10 @@ struct kmem_cache { /* 4) cache creation/removal */ const char *name; - struct list_head next; + struct list_head list; + int refcount; + int object_size; + int align; /* 5) statistics */ #ifdef CONFIG_DEBUG_SLAB @@ -73,12 +76,11 @@ struct kmem_cache { /* * If debugging is enabled, then the allocator can add additional - * fields and/or padding to every object. buffer_size contains the total + * fields and/or padding to every object. size contains the total * object size including these internal fields, the following two * variables contain the offset to the user object and its size. */ int obj_offset; - int obj_size; #endif /* CONFIG_DEBUG_SLAB */ /* 6) per-cpu/per-node data, touched during every alloc/free */ @@ -88,9 +90,13 @@ struct kmem_cache { * (see kmem_cache_init()) * We still use [NR_CPUS] and not [1] or [0] because cache_cache * is statically defined, so we reserve the max number of cpus. + * + * We also need to guarantee that the list is able to accomodate a + * pointer for each node since "nodelists" uses the remainder of + * available pointers. */ struct kmem_list3 **nodelists; - struct array_cache *array[NR_CPUS]; + struct array_cache *array[NR_CPUS + MAX_NUMNODES]; /* * Do not add fields after array[] */ @@ -110,19 +116,13 @@ void *kmem_cache_alloc(struct kmem_cache *, gfp_t); void *__kmalloc(size_t size, gfp_t flags); #ifdef CONFIG_TRACING -extern void *kmem_cache_alloc_trace(size_t size, - struct kmem_cache *cachep, gfp_t flags); -extern size_t slab_buffer_size(struct kmem_cache *cachep); +extern void *kmem_cache_alloc_trace(struct kmem_cache *, gfp_t, size_t); #else static __always_inline void * -kmem_cache_alloc_trace(size_t size, struct kmem_cache *cachep, gfp_t flags) +kmem_cache_alloc_trace(struct kmem_cache *cachep, gfp_t flags, size_t size) { return kmem_cache_alloc(cachep, flags); } -static inline size_t slab_buffer_size(struct kmem_cache *cachep) -{ - return 0; -} #endif static __always_inline void *kmalloc(size_t size, gfp_t flags) @@ -152,7 +152,7 @@ static __always_inline void *kmalloc(size_t size, gfp_t flags) #endif cachep = malloc_sizes[i].cs_cachep; - ret = kmem_cache_alloc_trace(size, cachep, flags); + ret = kmem_cache_alloc_trace(cachep, flags, size); return ret; } diff --git a/include/linux/slob_def.h b/include/linux/slob_def.h index 0ec00b39d00..f28e14a12e3 100644 --- a/include/linux/slob_def.h +++ b/include/linux/slob_def.h @@ -1,12 +1,14 @@ #ifndef __LINUX_SLOB_DEF_H #define __LINUX_SLOB_DEF_H +#include + void *kmem_cache_alloc_node(struct kmem_cache *, gfp_t flags, int node); static __always_inline void *kmem_cache_alloc(struct kmem_cache *cachep, gfp_t flags) { - return kmem_cache_alloc_node(cachep, flags, -1); + return kmem_cache_alloc_node(cachep, flags, NUMA_NO_NODE); } void *__kmalloc_node(size_t size, gfp_t flags, int node); @@ -26,7 +28,7 @@ static __always_inline void *kmalloc_node(size_t size, gfp_t flags, int node) */ static __always_inline void *kmalloc(size_t size, gfp_t flags) { - return __kmalloc_node(size, flags, -1); + return __kmalloc_node(size, flags, NUMA_NO_NODE); } static __always_inline void *__kmalloc(size_t size, gfp_t flags) diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h index c2f8c8bc56e..df448adb728 100644 --- a/include/linux/slub_def.h +++ b/include/linux/slub_def.h @@ -48,7 +48,6 @@ struct kmem_cache_cpu { unsigned long tid; /* Globally unique transaction id */ struct page *page; /* The slab from which we are allocating */ struct page *partial; /* Partially allocated frozen slabs */ - int node; /* The node of the page (or -1 for debug) */ #ifdef CONFIG_SLUB_STATS unsigned stat[NR_SLUB_STAT_ITEMS]; #endif @@ -83,7 +82,7 @@ struct kmem_cache { unsigned long flags; unsigned long min_partial; int size; /* The size of an object including meta data */ - int objsize; /* The size of an object without meta data */ + int object_size; /* The size of an object without meta data */ int offset; /* Free pointer offset. */ int cpu_partial; /* Number of per cpu partial objects to keep around */ struct kmem_cache_order_objects oo; diff --git a/include/trace/events/gfpflags.h b/include/trace/events/gfpflags.h index 9fe3a36646e..d6fd8e5b14b 100644 --- a/include/trace/events/gfpflags.h +++ b/include/trace/events/gfpflags.h @@ -30,6 +30,7 @@ {(unsigned long)__GFP_COMP, "GFP_COMP"}, \ {(unsigned long)__GFP_ZERO, "GFP_ZERO"}, \ {(unsigned long)__GFP_NOMEMALLOC, "GFP_NOMEMALLOC"}, \ + {(unsigned long)__GFP_MEMALLOC, "GFP_MEMALLOC"}, \ {(unsigned long)__GFP_HARDWALL, "GFP_HARDWALL"}, \ {(unsigned long)__GFP_THISNODE, "GFP_THISNODE"}, \ {(unsigned long)__GFP_RECLAIMABLE, "GFP_RECLAIMABLE"}, \ diff --git a/kernel/fork.c b/kernel/fork.c index e775c328172..26b20382302 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -499,7 +499,7 @@ static void mm_init_aio(struct mm_struct *mm) { #ifdef CONFIG_AIO spin_lock_init(&mm->ioctx_lock); - INIT_HLIST_HEAD(&mm->ioctx_list); + INIT_RADIX_TREE(&mm->ioctx_rtree, GFP_KERNEL); #endif } diff --git a/mm/Makefile b/mm/Makefile index 8aada89efbb..90be6c3c921 100644 --- a/mm/Makefile +++ b/mm/Makefile @@ -13,7 +13,8 @@ obj-y := filemap.o mempool.o oom_kill.o fadvise.o \ readahead.o swap.o truncate.o vmscan.o shmem.o \ prio_tree.o util.o mmzone.o vmstat.o backing-dev.o \ page_isolation.o mm_init.o mmu_context.o percpu.o \ - compaction.o $(mmu-y) + compaction.o slab_common.o $(mmu-y) + obj-y += init-mm.o ifdef CONFIG_NO_BOOTMEM diff --git a/mm/internal.h b/mm/internal.h index 8c6fd44d83b..aeac5c7da89 100644 --- a/mm/internal.h +++ b/mm/internal.h @@ -272,6 +272,9 @@ static inline struct page *mem_map_next(struct page *iter, #define __paginginit __init #endif +/* Returns true if the gfp_mask allows use of ALLOC_NO_WATERMARK */ +bool gfp_pfmemalloc_allowed(gfp_t gfp_mask); + /* Memory initialisation debug and verification */ enum mminit_level { MMINIT_WARNING, @@ -356,3 +359,4 @@ extern u32 hwpoison_filter_enable; #define ALLOC_HIGH 0x20 /* __GFP_HIGH set */ #define ALLOC_CPUSET 0x40 /* check for correct cpuset */ #define ALLOC_CMA 0x80 /* allow allocations from CMA areas */ + diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 46cb63b956f..9efb806b6fd 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -1614,8 +1614,14 @@ static unsigned interleave_nodes(struct mempolicy *policy) * task can change it's policy. The system default policy requires no * such protection. */ -unsigned slab_node(struct mempolicy *policy) +unsigned slab_node(void) { + struct mempolicy *policy; + + if (in_interrupt()) + return numa_node_id(); + + policy = current->mempolicy; if (!policy || policy->flags & MPOL_F_LOCAL) return numa_node_id(); diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 830ae0dccb3..ffa73b550f7 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -2331,9 +2331,9 @@ gfp_to_alloc_flags(gfp_t gfp_mask) alloc_flags |= ALLOC_HARDER; if (likely(!(gfp_mask & __GFP_NOMEMALLOC))) { - if (!in_interrupt() && - ((current->flags & PF_MEMALLOC) || - unlikely(test_thread_flag(TIF_MEMDIE)))) + if (gfp_mask & __GFP_MEMALLOC) + alloc_flags |= ALLOC_NO_WATERMARKS; + else if (likely(!(gfp_mask & __GFP_NOMEMALLOC)) && !in_interrupt()) alloc_flags |= ALLOC_NO_WATERMARKS; } #ifdef CONFIG_CMA @@ -2343,6 +2343,11 @@ gfp_to_alloc_flags(gfp_t gfp_mask) return alloc_flags; } +bool gfp_pfmemalloc_allowed(gfp_t gfp_mask) +{ + return !!(gfp_to_alloc_flags(gfp_mask) & ALLOC_NO_WATERMARKS); +} + static inline struct page * __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order, struct zonelist *zonelist, enum zone_type high_zoneidx, @@ -2530,10 +2535,18 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order, warn_alloc_failed(gfp_mask, order, NULL); return page; got_pg: + /* + * page->pfmemalloc is set when the caller had PFMEMALLOC set, is + * been OOM killed or specified __GFP_MEMALLOC. The expectation is + * that the caller is taking steps that will free more memory. The + * caller should avoid the page being used for !PFMEMALLOC purposes. + */ + page->pfmemalloc = !!(alloc_flags & ALLOC_NO_WATERMARKS); + if (kmemcheck_enabled) kmemcheck_pagealloc_alloc(page, order, gfp_mask); - return page; + return page; } /* @@ -2589,6 +2602,8 @@ __alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order, page = __alloc_pages_slowpath(gfp_mask, order, zonelist, high_zoneidx, nodemask, preferred_zone, migratetype); + else + page->pfmemalloc = false; trace_mm_page_alloc(page, order, gfp_mask, migratetype); diff --git a/mm/slab.c b/mm/slab.c index fb563b520d6..09e4899bbaa 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -68,7 +68,7 @@ * Further notes from the original documentation: * * 11 April '97. Started multi-threading - markhe - * The global cache-chain is protected by the mutex 'cache_chain_mutex'. + * The global cache-chain is protected by the mutex 'slab_mutex'. * The sem is only needed when accessing/extending the cache-chain, which * can never happen inside an interrupt (kmem_cache_create(), * kmem_cache_shrink() and kmem_cache_reap()). @@ -123,6 +123,10 @@ #include +#include "internal.h" + +#include "slab.h" + /* * DEBUG - 1 for kmem_cache_create() to honour; SLAB_RED_ZONE & SLAB_POISON. * 0 for faster, smaller code (especially in the critical paths). @@ -151,22 +155,11 @@ #define ARCH_KMALLOC_FLAGS SLAB_HWCACHE_ALIGN #endif -/* Legal flag mask for kmem_cache_create(). */ -#if DEBUG -# define CREATE_MASK (SLAB_RED_ZONE | \ - SLAB_POISON | SLAB_HWCACHE_ALIGN | \ - SLAB_CACHE_DMA | \ - SLAB_STORE_USER | \ - SLAB_RECLAIM_ACCOUNT | SLAB_PANIC | \ - SLAB_DESTROY_BY_RCU | SLAB_MEM_SPREAD | \ - SLAB_DEBUG_OBJECTS | SLAB_NOLEAKTRACE | SLAB_NOTRACK) -#else -# define CREATE_MASK (SLAB_HWCACHE_ALIGN | \ - SLAB_CACHE_DMA | \ - SLAB_RECLAIM_ACCOUNT | SLAB_PANIC | \ - SLAB_DESTROY_BY_RCU | SLAB_MEM_SPREAD | \ - SLAB_DEBUG_OBJECTS | SLAB_NOLEAKTRACE | SLAB_NOTRACK) -#endif +/* + * true if a page was allocated from pfmemalloc reserves for network-based + * swap + */ +static bool pfmemalloc_active __read_mostly; /* * kmem_bufctl_t: @@ -256,9 +249,30 @@ struct array_cache { * Must have this definition in here for the proper * alignment of array_cache. Also simplifies accessing * the entries. + * + * Entries should not be directly dereferenced as + * entries belonging to slabs marked pfmemalloc will + * have the lower bits set SLAB_OBJ_PFMEMALLOC */ }; +#define SLAB_OBJ_PFMEMALLOC 1 +static inline bool is_obj_pfmemalloc(void *objp) +{ + return (unsigned long)objp & SLAB_OBJ_PFMEMALLOC; +} + +static inline void set_obj_pfmemalloc(void **objp) +{ + *objp = (void *)((unsigned long)*objp | SLAB_OBJ_PFMEMALLOC); + return; +} + +static inline void clear_obj_pfmemalloc(void **objp) +{ + *objp = (void *)((unsigned long)*objp & ~SLAB_OBJ_PFMEMALLOC); +} + /* * bootstrap: The caches do not work without cpuarrays anymore, but the * cpuarrays are allocated from the generic caches... @@ -424,8 +438,8 @@ static void kmem_list3_init(struct kmem_list3 *parent) * cachep->obj_offset - BYTES_PER_WORD .. cachep->obj_offset - 1: * redzone word. * cachep->obj_offset: The real object. - * cachep->buffer_size - 2* BYTES_PER_WORD: redzone word [BYTES_PER_WORD long] - * cachep->buffer_size - 1* BYTES_PER_WORD: last caller address + * cachep->size - 2* BYTES_PER_WORD: redzone word [BYTES_PER_WORD long] + * cachep->size - 1* BYTES_PER_WORD: last caller address * [BYTES_PER_WORD long] */ static int obj_offset(struct kmem_cache *cachep) @@ -433,11 +447,6 @@ static int obj_offset(struct kmem_cache *cachep) return cachep->obj_offset; } -static int obj_size(struct kmem_cache *cachep) -{ - return cachep->obj_size; -} - static unsigned long long *dbg_redzone1(struct kmem_cache *cachep, void *objp) { BUG_ON(!(cachep->flags & SLAB_RED_ZONE)); @@ -449,37 +458,28 @@ static unsigned long long *dbg_redzone2(struct kmem_cache *cachep, void *objp) { BUG_ON(!(cachep->flags & SLAB_RED_ZONE)); if (cachep->flags & SLAB_STORE_USER) - return (unsigned long long *)(objp + cachep->buffer_size - + return (unsigned long long *)(objp + cachep->size - sizeof(unsigned long long) - REDZONE_ALIGN); - return (unsigned long long *) (objp + cachep->buffer_size - + return (unsigned long long *) (objp + cachep->size - sizeof(unsigned long long)); } static void **dbg_userword(struct kmem_cache *cachep, void *objp) { BUG_ON(!(cachep->flags & SLAB_STORE_USER)); - return (void **)(objp + cachep->buffer_size - BYTES_PER_WORD); + return (void **)(objp + cachep->size - BYTES_PER_WORD); } #else #define obj_offset(x) 0 -#define obj_size(cachep) (cachep->buffer_size) #define dbg_redzone1(cachep, objp) ({BUG(); (unsigned long long *)NULL;}) #define dbg_redzone2(cachep, objp) ({BUG(); (unsigned long long *)NULL;}) #define dbg_userword(cachep, objp) ({BUG(); (void **)NULL;}) #endif -#ifdef CONFIG_TRACING -size_t slab_buffer_size(struct kmem_cache *cachep) -{ - return cachep->buffer_size; -} -EXPORT_SYMBOL(slab_buffer_size); -#endif - /* * Do not go above this order unless 0 objects fit into the slab or * overridden on the command line. @@ -489,56 +489,30 @@ EXPORT_SYMBOL(slab_buffer_size); static int slab_max_order = SLAB_MAX_ORDER_LO; static bool slab_max_order_set __initdata; -/* - * Functions for storing/retrieving the cachep and or slab from the page - * allocator. These are used to find the slab an obj belongs to. With kfree(), - * these are used to find the cache which an obj belongs to. - */ -static inline void page_set_cache(struct page *page, struct kmem_cache *cache) -{ - page->lru.next = (struct list_head *)cache; -} - -static inline struct kmem_cache *page_get_cache(struct page *page) -{ - page = compound_head(page); - BUG_ON(!PageSlab(page)); - return (struct kmem_cache *)page->lru.next; -} - -static inline void page_set_slab(struct page *page, struct slab *slab) -{ - page->lru.prev = (struct list_head *)slab; -} - -static inline struct slab *page_get_slab(struct page *page) -{ - BUG_ON(!PageSlab(page)); - return (struct slab *)page->lru.prev; -} - static inline struct kmem_cache *virt_to_cache(const void *obj) { struct page *page = virt_to_head_page(obj); - return page_get_cache(page); + return page->slab_cache; } static inline struct slab *virt_to_slab(const void *obj) { struct page *page = virt_to_head_page(obj); - return page_get_slab(page); + + VM_BUG_ON(!PageSlab(page)); + return page->slab_page; } static inline void *index_to_obj(struct kmem_cache *cache, struct slab *slab, unsigned int idx) { - return slab->s_mem + cache->buffer_size * idx; + return slab->s_mem + cache->size * idx; } /* - * We want to avoid an expensive divide : (offset / cache->buffer_size) - * Using the fact that buffer_size is a constant for a particular cache, - * we can replace (offset / cache->buffer_size) by + * We want to avoid an expensive divide : (offset / cache->size) + * Using the fact that size is a constant for a particular cache, + * we can replace (offset / cache->size) by * reciprocal_divide(offset, cache->reciprocal_buffer_size) */ static inline unsigned int obj_to_index(const struct kmem_cache *cache, @@ -572,45 +546,20 @@ static struct cache_names __initdata cache_names[] = { #undef CACHE }; -static struct arraycache_init initarray_cache __initdata = - { {0, BOOT_CPUCACHE_ENTRIES, 1, 0} }; static struct arraycache_init initarray_generic = { {0, BOOT_CPUCACHE_ENTRIES, 1, 0} }; /* internal cache of cache description objs */ -static struct kmem_list3 *cache_cache_nodelists[MAX_NUMNODES]; -static struct kmem_cache cache_cache = { - .nodelists = cache_cache_nodelists, +static struct kmem_cache kmem_cache_boot = { .batchcount = 1, .limit = BOOT_CPUCACHE_ENTRIES, .shared = 1, - .buffer_size = sizeof(struct kmem_cache), + .size = sizeof(struct kmem_cache), .name = "kmem_cache", }; #define BAD_ALIEN_MAGIC 0x01020304ul -/* - * chicken and egg problem: delay the per-cpu array allocation - * until the general caches are up. - */ -static enum { - NONE, - PARTIAL_AC, - PARTIAL_L3, - EARLY, - LATE, - FULL -} g_cpucache_up; - -/* - * used by boot code to determine if it can use slab based allocator - */ -int slab_is_available(void) -{ - return g_cpucache_up >= EARLY; -} - #ifdef CONFIG_LOCKDEP /* @@ -676,7 +625,7 @@ static void init_node_lock_keys(int q) { struct cache_sizes *s = malloc_sizes; - if (g_cpucache_up < LATE) + if (slab_state < UP) return; for (s = malloc_sizes; s->cs_size != ULONG_MAX; s++) { @@ -691,6 +640,26 @@ static void init_node_lock_keys(int q) } } +static void on_slab_lock_classes_node(struct kmem_cache *cachep, int q) +{ + struct kmem_list3 *l3; + l3 = cachep->nodelists[q]; + if (!l3) + return; + + slab_set_lock_classes(cachep, &on_slab_l3_key, + &on_slab_alc_key, q); +} + +static inline void on_slab_lock_classes(struct kmem_cache *cachep) +{ + int node; + + VM_BUG_ON(OFF_SLAB(cachep)); + for_each_node(node) + on_slab_lock_classes_node(cachep, node); +} + static inline void init_lock_keys(void) { int node; @@ -707,6 +676,14 @@ static inline void init_lock_keys(void) { } +static inline void on_slab_lock_classes(struct kmem_cache *cachep) +{ +} + +static inline void on_slab_lock_classes_node(struct kmem_cache *cachep, int node) +{ +} + static void slab_set_debugobj_lock_classes_node(struct kmem_cache *cachep, int node) { } @@ -716,12 +693,6 @@ static void slab_set_debugobj_lock_classes(struct kmem_cache *cachep) } #endif -/* - * Guard access to the cache-chain. - */ -static DEFINE_MUTEX(cache_chain_mutex); -static struct list_head cache_chain; - static DEFINE_PER_CPU(struct delayed_work, slab_reap_work); static inline struct array_cache *cpu_cache_get(struct kmem_cache *cachep) @@ -830,6 +801,7 @@ static void cache_estimate(unsigned long gfporder, size_t buffer_size, *left_over = slab_size - nr_objs*buffer_size - mgmt_size; } +#if DEBUG #define slab_error(cachep, msg) __slab_error(__func__, cachep, msg) static void __slab_error(const char *function, struct kmem_cache *cachep, @@ -838,7 +810,9 @@ static void __slab_error(const char *function, struct kmem_cache *cachep, printk(KERN_ERR "slab error in %s(): cache `%s': %s\n", function, cachep->name, msg); dump_stack(); + add_taint(TAINT_BAD_PAGE); } +#endif /* * By default on NUMA we use alien caches to stage the freeing of @@ -951,6 +925,102 @@ static struct array_cache *alloc_arraycache(int node, int entries, return nc; } +static inline bool is_slab_pfmemalloc(struct slab *slabp) +{ + struct page *page = virt_to_page(slabp->s_mem); + + return PageSlabPfmemalloc(page); +} + +/* Clears pfmemalloc_active if no slabs have pfmalloc set */ +static void recheck_pfmemalloc_active(struct kmem_cache *cachep, + struct array_cache *ac) +{ + struct kmem_list3 *l3 = cachep->nodelists[numa_mem_id()]; + struct slab *slabp; + unsigned long flags; + + if (!pfmemalloc_active) + return; + + spin_lock_irqsave(&l3->list_lock, flags); + list_for_each_entry(slabp, &l3->slabs_full, list) + if (is_slab_pfmemalloc(slabp)) + goto out; + + list_for_each_entry(slabp, &l3->slabs_partial, list) + if (is_slab_pfmemalloc(slabp)) + goto out; + + list_for_each_entry(slabp, &l3->slabs_free, list) + if (is_slab_pfmemalloc(slabp)) + goto out; + + pfmemalloc_active = false; +out: + spin_unlock_irqrestore(&l3->list_lock, flags); +} + +static void *ac_get_obj(struct kmem_cache *cachep, struct array_cache *ac, + gfp_t flags, bool force_refill) +{ + int i; + void *objp = ac->entry[--ac->avail]; + + /* Ensure the caller is allowed to use objects from PFMEMALLOC slab */ + if (unlikely(is_obj_pfmemalloc(objp))) { + struct kmem_list3 *l3; + + if (gfp_pfmemalloc_allowed(flags)) { + clear_obj_pfmemalloc(&objp); + return objp; + } + + /* The caller cannot use PFMEMALLOC objects, find another one */ + for (i = 0; i < ac->avail; i++) { + /* If a !PFMEMALLOC object is found, swap them */ + if (!is_obj_pfmemalloc(ac->entry[i])) { + objp = ac->entry[i]; + ac->entry[i] = ac->entry[ac->avail]; + ac->entry[ac->avail] = objp; + return objp; + } + } + + /* + * If there are empty slabs on the slabs_free list and we are + * being forced to refill the cache, mark this one !pfmemalloc. + */ + l3 = cachep->nodelists[numa_mem_id()]; + if (!list_empty(&l3->slabs_free) && force_refill) { + struct slab *slabp = virt_to_slab(objp); + ClearPageSlabPfmemalloc(virt_to_head_page(slabp->s_mem)); + clear_obj_pfmemalloc(&objp); + recheck_pfmemalloc_active(cachep, ac); + return objp; + } + + /* No !PFMEMALLOC objects available */ + ac->avail++; + objp = NULL; + } + + return objp; +} + +static void ac_put_obj(struct kmem_cache *cachep, struct array_cache *ac, + void *objp) +{ + if (unlikely(pfmemalloc_active)) { + /* Some pfmemalloc slabs exist, check if this is one */ + struct page *page = virt_to_head_page(objp); + if (PageSlabPfmemalloc(page)) + set_obj_pfmemalloc(&objp); + } + + ac->entry[ac->avail++] = objp; +} + /* * Transfer objects in one arraycache to another. * Locking must be handled by the caller. @@ -1127,7 +1197,7 @@ static inline int cache_free_alien(struct kmem_cache *cachep, void *objp) STATS_INC_ACOVERFLOW(cachep); __drain_alien_cache(cachep, alien, nodeid); } - alien->entry[alien->avail++] = objp; + ac_put_obj(cachep, alien, objp); spin_unlock(&alien->lock); } else { spin_lock(&(cachep->nodelists[nodeid])->list_lock); @@ -1145,7 +1215,7 @@ static inline int cache_free_alien(struct kmem_cache *cachep, void *objp) * When hotplugging memory or a cpu, existing nodelists are not replaced if * already in use. * - * Must hold cache_chain_mutex. + * Must hold slab_mutex. */ static int init_cache_nodelists_node(int node) { @@ -1153,7 +1223,7 @@ static int init_cache_nodelists_node(int node) struct kmem_list3 *l3; const int memsize = sizeof(struct kmem_list3); - list_for_each_entry(cachep, &cache_chain, next) { + list_for_each_entry(cachep, &slab_caches, list) { /* * Set up the size64 kmemlist for cpu before we can * begin anything. Make sure some other cpu on this @@ -1169,7 +1239,7 @@ static int init_cache_nodelists_node(int node) /* * The l3s don't come and go as CPUs come and - * go. cache_chain_mutex is sufficient + * go. slab_mutex is sufficient * protection here. */ cachep->nodelists[node] = l3; @@ -1191,7 +1261,7 @@ static void cpuup_canceled(long cpu) int node = cpu_to_mem(cpu); const struct cpumask *mask = cpumask_of_node(node); - list_for_each_entry(cachep, &cache_chain, next) { + list_for_each_entry(cachep, &slab_caches, list) { struct array_cache *nc; struct array_cache *shared; struct array_cache **alien; @@ -1241,7 +1311,7 @@ static void cpuup_canceled(long cpu) * the respective cache's slabs, now we can go ahead and * shrink each nodelist to its limit. */ - list_for_each_entry(cachep, &cache_chain, next) { + list_for_each_entry(cachep, &slab_caches, list) { l3 = cachep->nodelists[node]; if (!l3) continue; @@ -1270,7 +1340,7 @@ static int cpuup_prepare(long cpu) * Now we can go ahead with allocating the shared arrays and * array caches */ - list_for_each_entry(cachep, &cache_chain, next) { + list_for_each_entry(cachep, &slab_caches, list) { struct array_cache *nc; struct array_cache *shared = NULL; struct array_cache **alien = NULL; @@ -1320,6 +1390,9 @@ static int cpuup_prepare(long cpu) free_alien_cache(alien); if (cachep->flags & SLAB_DEBUG_OBJECTS) slab_set_debugobj_lock_classes_node(cachep, node); + else if (!OFF_SLAB(cachep) && + !(cachep->flags & SLAB_DESTROY_BY_RCU)) + on_slab_lock_classes_node(cachep, node); } init_node_lock_keys(node); @@ -1338,9 +1411,9 @@ static int cpuup_callback(struct notifier_block *nfb, switch (action) { case CPU_UP_PREPARE: case CPU_UP_PREPARE_FROZEN: - mutex_lock(&cache_chain_mutex); + mutex_lock(&slab_mutex); err = cpuup_prepare(cpu); - mutex_unlock(&cache_chain_mutex); + mutex_unlock(&slab_mutex); break; case CPU_ONLINE: case CPU_ONLINE_FROZEN: @@ -1350,7 +1423,7 @@ static int cpuup_callback(struct notifier_block *nfb, case CPU_DOWN_PREPARE: case CPU_DOWN_PREPARE_FROZEN: /* - * Shutdown cache reaper. Note that the cache_chain_mutex is + * Shutdown cache reaper. Note that the slab_mutex is * held so that if cache_reap() is invoked it cannot do * anything expensive but will only modify reap_work * and reschedule the timer. @@ -1377,9 +1450,9 @@ static int cpuup_callback(struct notifier_block *nfb, #endif case CPU_UP_CANCELED: case CPU_UP_CANCELED_FROZEN: - mutex_lock(&cache_chain_mutex); + mutex_lock(&slab_mutex); cpuup_canceled(cpu); - mutex_unlock(&cache_chain_mutex); + mutex_unlock(&slab_mutex); break; } return notifier_from_errno(err); @@ -1395,14 +1468,14 @@ static struct notifier_block cpucache_notifier = { * Returns -EBUSY if all objects cannot be drained so that the node is not * removed. * - * Must hold cache_chain_mutex. + * Must hold slab_mutex. */ static int __meminit drain_cache_nodelists_node(int node) { struct kmem_cache *cachep; int ret = 0; - list_for_each_entry(cachep, &cache_chain, next) { + list_for_each_entry(cachep, &slab_caches, list) { struct kmem_list3 *l3; l3 = cachep->nodelists[node]; @@ -1433,14 +1506,14 @@ static int __meminit slab_memory_callback(struct notifier_block *self, switch (action) { case MEM_GOING_ONLINE: - mutex_lock(&cache_chain_mutex); + mutex_lock(&slab_mutex); ret = init_cache_nodelists_node(nid); - mutex_unlock(&cache_chain_mutex); + mutex_unlock(&slab_mutex); break; case MEM_GOING_OFFLINE: - mutex_lock(&cache_chain_mutex); + mutex_lock(&slab_mutex); ret = drain_cache_nodelists_node(nid); - mutex_unlock(&cache_chain_mutex); + mutex_unlock(&slab_mutex); break; case MEM_ONLINE: case MEM_OFFLINE: @@ -1490,28 +1563,35 @@ static void __init set_up_list3s(struct kmem_cache *cachep, int index) } } +/* + * The memory after the last cpu cache pointer is used for the + * the nodelists pointer. + */ +static void setup_nodelists_pointer(struct kmem_cache *cachep) +{ + cachep->nodelists = (struct kmem_list3 **)&cachep->array[nr_cpu_ids]; +} + /* * Initialisation. Called after the page allocator have been initialised and * before smp_init(). */ void __init kmem_cache_init(void) { - size_t left_over; struct cache_sizes *sizes; struct cache_names *names; int i; - int order; - int node; + + kmem_cache = &kmem_cache_boot; + setup_nodelists_pointer(kmem_cache); if (num_possible_nodes() == 1) use_alien_caches = 0; - for (i = 0; i < NUM_INIT_LISTS; i++) { + for (i = 0; i < NUM_INIT_LISTS; i++) kmem_list3_init(&initkmem_list3[i]); - if (i < MAX_NUMNODES) - cache_cache.nodelists[i] = NULL; - } - set_up_list3s(&cache_cache, CACHE_CACHE); + + set_up_list3s(kmem_cache, CACHE_CACHE); /* * Fragmentation resistance on low memory - only use bigger @@ -1523,9 +1603,9 @@ void __init kmem_cache_init(void) /* Bootstrap is tricky, because several objects are allocated * from caches that do not exist yet: - * 1) initialize the cache_cache cache: it contains the struct - * kmem_cache structures of all caches, except cache_cache itself: - * cache_cache is statically allocated. + * 1) initialize the kmem_cache cache: it contains the struct + * kmem_cache structures of all caches, except kmem_cache itself: + * kmem_cache is statically allocated. * Initially an __init data area is used for the head array and the * kmem_list3 structures, it's replaced with a kmalloc allocated * array at the end of the bootstrap. @@ -1534,46 +1614,23 @@ void __init kmem_cache_init(void) * An __init data area is used for the head array. * 3) Create the remaining kmalloc caches, with minimally sized * head arrays. - * 4) Replace the __init data head arrays for cache_cache and the first + * 4) Replace the __init data head arrays for kmem_cache and the first * kmalloc cache with kmalloc allocated arrays. - * 5) Replace the __init data for kmem_list3 for cache_cache and + * 5) Replace the __init data for kmem_list3 for kmem_cache and * the other cache's with kmalloc allocated memory. * 6) Resize the head arrays of the kmalloc caches to their final sizes. */ - node = numa_mem_id(); - - /* 1) create the cache_cache */ - INIT_LIST_HEAD(&cache_chain); - list_add(&cache_cache.next, &cache_chain); - cache_cache.colour_off = cache_line_size(); - cache_cache.array[smp_processor_id()] = &initarray_cache.cache; - cache_cache.nodelists[node] = &initkmem_list3[CACHE_CACHE + node]; + /* 1) create the kmem_cache */ /* * struct kmem_cache size depends on nr_node_ids & nr_cpu_ids */ - cache_cache.buffer_size = offsetof(struct kmem_cache, array[nr_cpu_ids]) + - nr_node_ids * sizeof(struct kmem_list3 *); -#if DEBUG - cache_cache.obj_size = cache_cache.buffer_size; -#endif - cache_cache.buffer_size = ALIGN(cache_cache.buffer_size, - cache_line_size()); - cache_cache.reciprocal_buffer_size = - reciprocal_value(cache_cache.buffer_size); - - for (order = 0; order < MAX_ORDER; order++) { - cache_estimate(order, cache_cache.buffer_size, - cache_line_size(), 0, &left_over, &cache_cache.num); - if (cache_cache.num) - break; - } - BUG_ON(!cache_cache.num); - cache_cache.gfporder = order; - cache_cache.colour = left_over / cache_cache.colour_off; - cache_cache.slab_size = ALIGN(cache_cache.num * sizeof(kmem_bufctl_t) + - sizeof(struct slab), cache_line_size()); + create_boot_cache(kmem_cache, "kmem_cache", + offsetof(struct kmem_cache, array[nr_cpu_ids]) + + nr_node_ids * sizeof(struct kmem_list3 *), + SLAB_HWCACHE_ALIGN); + list_add(&kmem_cache->list, &slab_caches); /* 2+3) create the kmalloc caches */ sizes = malloc_sizes; @@ -1585,20 +1642,13 @@ void __init kmem_cache_init(void) * bug. */ - sizes[INDEX_AC].cs_cachep = kmem_cache_create(names[INDEX_AC].name, - sizes[INDEX_AC].cs_size, - ARCH_KMALLOC_MINALIGN, - ARCH_KMALLOC_FLAGS|SLAB_PANIC, - NULL); + sizes[INDEX_AC].cs_cachep = create_kmalloc_cache(names[INDEX_AC].name, + sizes[INDEX_AC].cs_size, ARCH_KMALLOC_FLAGS); - if (INDEX_AC != INDEX_L3) { + if (INDEX_AC != INDEX_L3) sizes[INDEX_L3].cs_cachep = - kmem_cache_create(names[INDEX_L3].name, - sizes[INDEX_L3].cs_size, - ARCH_KMALLOC_MINALIGN, - ARCH_KMALLOC_FLAGS|SLAB_PANIC, - NULL); - } + create_kmalloc_cache(names[INDEX_L3].name, + sizes[INDEX_L3].cs_size, ARCH_KMALLOC_FLAGS); slab_early_init = 0; @@ -1610,21 +1660,14 @@ void __init kmem_cache_init(void) * Note for systems short on memory removing the alignment will * allow tighter packing of the smaller caches. */ - if (!sizes->cs_cachep) { - sizes->cs_cachep = kmem_cache_create(names->name, - sizes->cs_size, - ARCH_KMALLOC_MINALIGN, - ARCH_KMALLOC_FLAGS|SLAB_PANIC, - NULL); - } + if (!sizes->cs_cachep) + sizes->cs_cachep = create_kmalloc_cache(names->name, + sizes->cs_size, ARCH_KMALLOC_FLAGS); + #ifdef CONFIG_ZONE_DMA - sizes->cs_dmacachep = kmem_cache_create( - names->name_dma, - sizes->cs_size, - ARCH_KMALLOC_MINALIGN, - ARCH_KMALLOC_FLAGS|SLAB_CACHE_DMA| - SLAB_PANIC, - NULL); + sizes->cs_dmacachep = create_kmalloc_cache( + names->name_dma, sizes->cs_size, + SLAB_CACHE_DMA|ARCH_KMALLOC_FLAGS); #endif sizes++; names++; @@ -1635,15 +1678,14 @@ void __init kmem_cache_init(void) ptr = kmalloc(sizeof(struct arraycache_init), GFP_NOWAIT); - BUG_ON(cpu_cache_get(&cache_cache) != &initarray_cache.cache); - memcpy(ptr, cpu_cache_get(&cache_cache), + memcpy(ptr, cpu_cache_get(kmem_cache), sizeof(struct arraycache_init)); /* * Do not assume that spinlocks can be initialized via memcpy: */ spin_lock_init(&ptr->lock); - cache_cache.array[smp_processor_id()] = ptr; + kmem_cache->array[smp_processor_id()] = ptr; ptr = kmalloc(sizeof(struct arraycache_init), GFP_NOWAIT); @@ -1664,7 +1706,7 @@ void __init kmem_cache_init(void) int nid; for_each_online_node(nid) { - init_list(&cache_cache, &initkmem_list3[CACHE_CACHE + nid], nid); + init_list(kmem_cache, &initkmem_list3[CACHE_CACHE + nid], nid); init_list(malloc_sizes[INDEX_AC].cs_cachep, &initkmem_list3[SIZE_AC + nid], nid); @@ -1676,33 +1718,33 @@ void __init kmem_cache_init(void) } } - g_cpucache_up = EARLY; + slab_state = UP; } void __init kmem_cache_init_late(void) { struct kmem_cache *cachep; - g_cpucache_up = LATE; + slab_state = UP; - /* 6) resize the head arrays to their final sizes */ - mutex_lock(&cache_chain_mutex); - list_for_each_entry(cachep, &cache_chain, next) - if (enable_cpucache(cachep, GFP_NOWAIT)) - BUG(); - mutex_unlock(&cache_chain_mutex); + /* 6) resize the head arrays to their final sizes */ + mutex_lock(&slab_mutex); + list_for_each_entry(cachep, &slab_caches, list) + if (enable_cpucache(cachep, GFP_NOWAIT)) + BUG(); + mutex_unlock(&slab_mutex); - /* Annotate slab for lockdep -- annotate the malloc caches */ - init_lock_keys(); + /* Annotate slab for lockdep -- annotate the malloc caches */ + init_lock_keys(); - /* Done! */ - g_cpucache_up = FULL; + /* Done! */ + slab_state = FULL; - /* - * Register a cpu startup notifier callback that initializes - * cpu_cache_get for all new cpus - */ - register_cpu_notifier(&cpucache_notifier); + /* + * Register a cpu startup notifier callback that initializes + * cpu_cache_get for all new cpus + */ + register_cpu_notifier(&cpucache_notifier); #ifdef CONFIG_NUMA /* @@ -1727,6 +1769,9 @@ static int __init cpucache_init(void) */ for_each_online_cpu(cpu) start_cpu_timer(cpu); + + /* Done! */ + slab_state = FULL; return 0; } __initcall(cpucache_init); @@ -1743,7 +1788,7 @@ slab_out_of_memory(struct kmem_cache *cachep, gfp_t gfpflags, int nodeid) "SLAB: Unable to allocate memory on node %d (gfp=0x%x)\n", nodeid, gfpflags); printk(KERN_WARNING " cache: %s, object size: %d, order: %d\n", - cachep->name, cachep->buffer_size, cachep->gfporder); + cachep->name, cachep->size, cachep->gfporder); for_each_online_node(node) { unsigned long active_objs = 0, num_objs = 0, free_objects = 0; @@ -1798,7 +1843,7 @@ static void *kmem_getpages(struct kmem_cache *cachep, gfp_t flags, int nodeid) flags |= __GFP_COMP; #endif - flags |= cachep->gfpflags; + flags |= cachep->allocflags; if (cachep->flags & SLAB_RECLAIM_ACCOUNT) flags |= __GFP_RECLAIMABLE; @@ -1809,6 +1854,10 @@ static void *kmem_getpages(struct kmem_cache *cachep, gfp_t flags, int nodeid) return NULL; } + /* Record if ALLOC_NO_WATERMARKS was set when allocating the slab */ + if (unlikely(page->pfmemalloc)) + pfmemalloc_active = true; + nr_pages = (1 << cachep->gfporder); if (cachep->flags & SLAB_RECLAIM_ACCOUNT) add_zone_page_state(page_zone(page), @@ -1816,9 +1865,13 @@ static void *kmem_getpages(struct kmem_cache *cachep, gfp_t flags, int nodeid) else add_zone_page_state(page_zone(page), NR_SLAB_UNRECLAIMABLE, nr_pages); - for (i = 0; i < nr_pages; i++) + for (i = 0; i < nr_pages; i++) { __SetPageSlab(page + i); + if (page->pfmemalloc) + SetPageSlabPfmemalloc(page + i); + } + if (kmemcheck_enabled && !(cachep->flags & SLAB_NOTRACK)) { kmemcheck_alloc_shadow(page, cachep->gfporder, flags, nodeid); @@ -1850,6 +1903,7 @@ static void kmem_freepages(struct kmem_cache *cachep, void *addr) NR_SLAB_UNRECLAIMABLE, nr_freed); while (i--) { BUG_ON(!PageSlab(page)); + __ClearPageSlabPfmemalloc(page); __ClearPageSlab(page); page++; } @@ -1874,7 +1928,7 @@ static void kmem_rcu_free(struct rcu_head *head) static void store_stackinfo(struct kmem_cache *cachep, unsigned long *addr, unsigned long caller) { - int size = obj_size(cachep); + int size = cachep->object_size; addr = (unsigned long *)&((char *)addr)[obj_offset(cachep)]; @@ -1906,7 +1960,7 @@ static void store_stackinfo(struct kmem_cache *cachep, unsigned long *addr, static void poison_obj(struct kmem_cache *cachep, void *addr, unsigned char val) { - int size = obj_size(cachep); + int size = cachep->object_size; addr = &((char *)addr)[obj_offset(cachep)]; memset(addr, val, size); @@ -1966,7 +2020,7 @@ static void print_objinfo(struct kmem_cache *cachep, void *objp, int lines) printk("\n"); } realobj = (char *)objp + obj_offset(cachep); - size = obj_size(cachep); + size = cachep->object_size; for (i = 0; i < size && lines; i += 16, lines--) { int limit; limit = 16; @@ -1983,7 +2037,7 @@ static void check_poison_obj(struct kmem_cache *cachep, void *objp) int lines = 0; realobj = (char *)objp + obj_offset(cachep); - size = obj_size(cachep); + size = cachep->object_size; for (i = 0; i < size; i++) { char exp = POISON_FREE; @@ -2047,10 +2101,10 @@ static void slab_destroy_debugcheck(struct kmem_cache *cachep, struct slab *slab if (cachep->flags & SLAB_POISON) { #ifdef CONFIG_DEBUG_PAGEALLOC - if (cachep->buffer_size % PAGE_SIZE == 0 && + if (cachep->size % PAGE_SIZE == 0 && OFF_SLAB(cachep)) kernel_map_pages(virt_to_page(objp), - cachep->buffer_size / PAGE_SIZE, 1); + cachep->size / PAGE_SIZE, 1); else check_poison_obj(cachep, objp); #else @@ -2101,27 +2155,6 @@ static void slab_destroy(struct kmem_cache *cachep, struct slab *slabp) } } -static void __kmem_cache_destroy(struct kmem_cache *cachep) -{ - int i; - struct kmem_list3 *l3; - - for_each_online_cpu(i) - kfree(cachep->array[i]); - - /* NUMA: free the list3 structures */ - for_each_online_node(i) { - l3 = cachep->nodelists[i]; - if (l3) { - kfree(l3->shared); - free_alien_cache(l3->alien); - kfree(l3); - } - } - kmem_cache_free(&cache_cache, cachep); -} - - /** * calculate_slab_order - calculate size (page order) of slabs * @cachep: pointer to the cache that is being created @@ -2194,12 +2227,20 @@ static size_t calculate_slab_order(struct kmem_cache *cachep, static int __init_refok setup_cpu_cache(struct kmem_cache *cachep, gfp_t gfp) { - if (g_cpucache_up == FULL) + if (slab_state >= FULL) return enable_cpucache(cachep, gfp); - if (g_cpucache_up == NONE) { + if (slab_state == DOWN) { + /* + * Note: Creation of first cache (kmem_cache). + * The setup_list3s is taken care + * of by the caller of __kmem_cache_create + */ + cachep->array[smp_processor_id()] = &initarray_generic.cache; + slab_state = PARTIAL; + } else if (slab_state == PARTIAL) { /* - * Note: the first kmem_cache_create must create the cache + * Note: the second kmem_cache_create must create the cache * that's used by kmalloc(24), otherwise the creation of * further caches will BUG(). */ @@ -2207,21 +2248,22 @@ static int __init_refok setup_cpu_cache(struct kmem_cache *cachep, gfp_t gfp) /* * If the cache that's used by kmalloc(sizeof(kmem_list3)) is - * the first cache, then we need to set up all its list3s, + * the second cache, then we need to set up all its list3s, * otherwise the creation of further caches will BUG(). */ set_up_list3s(cachep, SIZE_AC); if (INDEX_AC == INDEX_L3) - g_cpucache_up = PARTIAL_L3; + slab_state = PARTIAL_L3; else - g_cpucache_up = PARTIAL_AC; + slab_state = PARTIAL_ARRAYCACHE; } else { + /* Remaining boot caches */ cachep->array[smp_processor_id()] = kmalloc(sizeof(struct arraycache_init), gfp); - if (g_cpucache_up == PARTIAL_AC) { + if (slab_state == PARTIAL_ARRAYCACHE) { set_up_list3s(cachep, SIZE_L3); - g_cpucache_up = PARTIAL_L3; + slab_state = PARTIAL_L3; } else { int node; for_each_online_node(node) { @@ -2247,20 +2289,14 @@ static int __init_refok setup_cpu_cache(struct kmem_cache *cachep, gfp_t gfp) } /** - * kmem_cache_create - Create a cache. - * @name: A string which is used in /proc/slabinfo to identify this cache. - * @size: The size of objects to be created in this cache. - * @align: The required alignment for the objects. + * __kmem_cache_create - Create a cache. + * @cachep: cache management descriptor * @flags: SLAB flags - * @ctor: A constructor for the objects. * * Returns a ptr to the cache on success, NULL on failure. * Cannot be called within a int, but can be interrupted. * The @ctor is run when new pages are allocated by the cache. * - * @name must be valid until the cache is destroyed. This implies that - * the module calling this has to destroy the cache before getting unloaded. - * * The flags are * * %SLAB_POISON - Poison the slab with a known test pattern (a5a5a5a5) @@ -2273,60 +2309,15 @@ static int __init_refok setup_cpu_cache(struct kmem_cache *cachep, gfp_t gfp) * cacheline. This can be beneficial if you're counting cycles as closely * as davem. */ -struct kmem_cache * -kmem_cache_create (const char *name, size_t size, size_t align, - unsigned long flags, void (*ctor)(void *)) +int +__kmem_cache_create (struct kmem_cache *cachep, unsigned long flags) { size_t left_over, slab_size, ralign; - struct kmem_cache *cachep = NULL, *pc; gfp_t gfp; - - /* - * Sanity checks... these are all serious usage bugs. - */ - if (!name || in_interrupt() || (size < BYTES_PER_WORD) || - size > KMALLOC_MAX_SIZE) { - printk(KERN_ERR "%s: Early error in slab %s\n", __func__, - name); - BUG(); - } - - /* - * We use cache_chain_mutex to ensure a consistent view of - * cpu_online_mask as well. Please see cpuup_callback - */ - if (slab_is_available()) { - get_online_cpus(); - mutex_lock(&cache_chain_mutex); - } - - list_for_each_entry(pc, &cache_chain, next) { - char tmp; - int res; - - /* - * This happens when the module gets unloaded and doesn't - * destroy its slab cache and no-one else reuses the vmalloc - * area of the module. Print a warning. - */ - res = probe_kernel_address(pc->name, tmp); - if (res) { - printk(KERN_ERR - "SLAB: cache with size %d has lost its name\n", - pc->buffer_size); - continue; - } - - if (!strcmp(pc->name, name)) { - printk(KERN_ERR - "kmem_cache_create: duplicate cache %s\n", name); - dump_stack(); - goto oops; - } - } + int err; + size_t size = cachep->size; #if DEBUG - WARN_ON(strchr(name, ' ')); /* It confuses parsers */ #if FORCED_DEBUG /* * Enable redzoning and last user accounting, except for caches with @@ -2343,11 +2334,6 @@ kmem_cache_create (const char *name, size_t size, size_t align, if (flags & SLAB_DESTROY_BY_RCU) BUG_ON(flags & SLAB_POISON); #endif - /* - * Always checks flags, a caller might be expecting debug support which - * isn't available. - */ - BUG_ON(flags & ~CREATE_MASK); /* * Check that size is in terms of words. This is needed to avoid @@ -2359,22 +2345,6 @@ kmem_cache_create (const char *name, size_t size, size_t align, size &= ~(BYTES_PER_WORD - 1); } - /* calculate the final buffer alignment: */ - - /* 1) arch recommendation: can be overridden for debug */ - if (flags & SLAB_HWCACHE_ALIGN) { - /* - * Default alignment: as specified by the arch code. Except if - * an object is really small, then squeeze multiple objects into - * one cacheline. - */ - ralign = cache_line_size(); - while (size <= ralign / 2) - ralign /= 2; - } else { - ralign = BYTES_PER_WORD; - } - /* * Redzoning and user store require word alignment or possibly larger. * Note this will be overridden by architecture or caller mandated @@ -2391,13 +2361,9 @@ kmem_cache_create (const char *name, size_t size, size_t align, size &= ~(REDZONE_ALIGN - 1); } - /* 2) arch mandated alignment */ - if (ralign < ARCH_SLAB_MINALIGN) { - ralign = ARCH_SLAB_MINALIGN; - } /* 3) caller mandated alignment */ - if (ralign < align) { - ralign = align; + if (ralign < cachep->align) { + ralign = cachep->align; } /* disable debug if necessary */ if (ralign > __alignof__(unsigned long long)) @@ -2405,21 +2371,15 @@ kmem_cache_create (const char *name, size_t size, size_t align, /* * 4) Store it. */ - align = ralign; + cachep->align = ralign; if (slab_is_available()) gfp = GFP_KERNEL; else gfp = GFP_NOWAIT; - /* Get cache's description obj. */ - cachep = kmem_cache_zalloc(&cache_cache, gfp); - if (!cachep) - goto oops; - - cachep->nodelists = (struct kmem_list3 **)&cachep->array[nr_cpu_ids]; + setup_nodelists_pointer(cachep); #if DEBUG - cachep->obj_size = size; /* * Both debugging options require word-alignment which is calculated @@ -2442,8 +2402,9 @@ kmem_cache_create (const char *name, size_t size, size_t align, } #if FORCED_DEBUG && defined(CONFIG_DEBUG_PAGEALLOC) if (size >= malloc_sizes[INDEX_L3 + 1].cs_size - && cachep->obj_size > cache_line_size() && ALIGN(size, align) < PAGE_SIZE) { - cachep->obj_offset += PAGE_SIZE - ALIGN(size, align); + && cachep->object_size > cache_line_size() + && ALIGN(size, cachep->align) < PAGE_SIZE) { + cachep->obj_offset += PAGE_SIZE - ALIGN(size, cachep->align); size = PAGE_SIZE; } #endif @@ -2463,19 +2424,15 @@ kmem_cache_create (const char *name, size_t size, size_t align, */ flags |= CFLGS_OFF_SLAB; - size = ALIGN(size, align); + size = ALIGN(size, cachep->align); - left_over = calculate_slab_order(cachep, size, align, flags); + left_over = calculate_slab_order(cachep, size, cachep->align, flags); + + if (!cachep->num) + return -E2BIG; - if (!cachep->num) { - printk(KERN_ERR - "kmem_cache_create: couldn't create cache %s.\n", name); - kmem_cache_free(&cache_cache, cachep); - cachep = NULL; - goto oops; - } slab_size = ALIGN(cachep->num * sizeof(kmem_bufctl_t) - + sizeof(struct slab), align); + + sizeof(struct slab), cachep->align); /* * If the slab has been placed off-slab, and we have enough space then @@ -2503,15 +2460,15 @@ kmem_cache_create (const char *name, size_t size, size_t align, cachep->colour_off = cache_line_size(); /* Offset must be a multiple of the alignment. */ - if (cachep->colour_off < align) - cachep->colour_off = align; + if (cachep->colour_off < cachep->align) + cachep->colour_off = cachep->align; cachep->colour = left_over / cachep->colour_off; cachep->slab_size = slab_size; cachep->flags = flags; - cachep->gfpflags = 0; + cachep->allocflags = 0; if (CONFIG_ZONE_DMA_FLAG && (flags & SLAB_CACHE_DMA)) - cachep->gfpflags |= GFP_DMA; - cachep->buffer_size = size; + cachep->allocflags |= GFP_DMA; + cachep->size = size; cachep->reciprocal_buffer_size = reciprocal_value(size); if (flags & CFLGS_OFF_SLAB) { @@ -2525,13 +2482,11 @@ kmem_cache_create (const char *name, size_t size, size_t align, */ BUG_ON(ZERO_OR_NULL_PTR(cachep->slabp_cache)); } - cachep->ctor = ctor; - cachep->name = name; - if (setup_cpu_cache(cachep, gfp)) { - __kmem_cache_destroy(cachep); - cachep = NULL; - goto oops; + err = setup_cpu_cache(cachep, gfp); + if (err) { + __kmem_cache_shutdown(cachep); + return err; } if (flags & SLAB_DEBUG_OBJECTS) { @@ -2542,21 +2497,11 @@ kmem_cache_create (const char *name, size_t size, size_t align, WARN_ON_ONCE(flags & SLAB_DESTROY_BY_RCU); slab_set_debugobj_lock_classes(cachep); - } + } else if (!OFF_SLAB(cachep) && !(flags & SLAB_DESTROY_BY_RCU)) + on_slab_lock_classes(cachep); - /* cache setup completed, link it into the list */ - list_add(&cachep->next, &cache_chain); -oops: - if (!cachep && (flags & SLAB_PANIC)) - panic("kmem_cache_create(): failed to create slab `%s'\n", - name); - if (slab_is_available()) { - mutex_unlock(&cache_chain_mutex); - put_online_cpus(); - } - return cachep; + return 0; } -EXPORT_SYMBOL(kmem_cache_create); #if DEBUG static void check_irq_off(void) @@ -2671,7 +2616,7 @@ static int drain_freelist(struct kmem_cache *cache, return nr_freed; } -/* Called with cache_chain_mutex held to protect against cpu hotplug */ +/* Called with slab_mutex held to protect against cpu hotplug */ static int __cache_shrink(struct kmem_cache *cachep) { int ret = 0, i = 0; @@ -2706,57 +2651,37 @@ int kmem_cache_shrink(struct kmem_cache *cachep) BUG_ON(!cachep || in_interrupt()); get_online_cpus(); - mutex_lock(&cache_chain_mutex); + mutex_lock(&slab_mutex); ret = __cache_shrink(cachep); - mutex_unlock(&cache_chain_mutex); + mutex_unlock(&slab_mutex); put_online_cpus(); return ret; } EXPORT_SYMBOL(kmem_cache_shrink); -/** - * kmem_cache_destroy - delete a cache - * @cachep: the cache to destroy - * - * Remove a &struct kmem_cache object from the slab cache. - * - * It is expected this function will be called by a module when it is - * unloaded. This will remove the cache completely, and avoid a duplicate - * cache being allocated each time a module is loaded and unloaded, if the - * module doesn't have persistent in-kernel storage across loads and unloads. - * - * The cache must be empty before calling this function. - * - * The caller must guarantee that no one will allocate memory from the cache - * during the kmem_cache_destroy(). - */ -void kmem_cache_destroy(struct kmem_cache *cachep) +int __kmem_cache_shutdown(struct kmem_cache *cachep) { - BUG_ON(!cachep || in_interrupt()); + int i; + struct kmem_list3 *l3; + int rc = __cache_shrink(cachep); - /* Find the cache in the chain of caches. */ - get_online_cpus(); - mutex_lock(&cache_chain_mutex); - /* - * the chain is never empty, cache_cache is never destroyed - */ - list_del(&cachep->next); - if (__cache_shrink(cachep)) { - slab_error(cachep, "Can't free all objects"); - list_add(&cachep->next, &cache_chain); - mutex_unlock(&cache_chain_mutex); - put_online_cpus(); - return; - } + if (rc) + return rc; - if (unlikely(cachep->flags & SLAB_DESTROY_BY_RCU)) - rcu_barrier(); + for_each_online_cpu(i) + kfree(cachep->array[i]); - __kmem_cache_destroy(cachep); - mutex_unlock(&cache_chain_mutex); - put_online_cpus(); + /* NUMA: free the list3 structures */ + for_each_online_node(i) { + l3 = cachep->nodelists[i]; + if (l3) { + kfree(l3->shared); + free_alien_cache(l3->alien); + kfree(l3); + } + } + return 0; } -EXPORT_SYMBOL(kmem_cache_destroy); /* * Get the memory for a slab management obj. @@ -2840,10 +2765,10 @@ static void cache_init_objs(struct kmem_cache *cachep, slab_error(cachep, "constructor overwrote the" " start of an object"); } - if ((cachep->buffer_size % PAGE_SIZE) == 0 && + if ((cachep->size % PAGE_SIZE) == 0 && OFF_SLAB(cachep) && cachep->flags & SLAB_POISON) kernel_map_pages(virt_to_page(objp), - cachep->buffer_size / PAGE_SIZE, 0); + cachep->size / PAGE_SIZE, 0); #else if (cachep->ctor) cachep->ctor(objp); @@ -2857,9 +2782,9 @@ static void kmem_flagcheck(struct kmem_cache *cachep, gfp_t flags) { if (CONFIG_ZONE_DMA_FLAG) { if (flags & GFP_DMA) - BUG_ON(!(cachep->gfpflags & GFP_DMA)); + BUG_ON(!(cachep->allocflags & GFP_DMA)); else - BUG_ON(cachep->gfpflags & GFP_DMA); + BUG_ON(cachep->allocflags & GFP_DMA); } } @@ -2918,8 +2843,8 @@ static void slab_map_pages(struct kmem_cache *cache, struct slab *slab, nr_pages <<= cache->gfporder; do { - page_set_cache(page, cache); - page_set_slab(page, slab); + page->slab_cache = cache; + page->slab_page = slab; page++; } while (--nr_pages); } @@ -3045,7 +2970,7 @@ static inline void verify_redzone_free(struct kmem_cache *cache, void *obj) } static void *cache_free_debugcheck(struct kmem_cache *cachep, void *objp, - void *caller) + unsigned long caller) { struct page *page; unsigned int objnr; @@ -3057,7 +2982,7 @@ static void *cache_free_debugcheck(struct kmem_cache *cachep, void *objp, kfree_debugcheck(objp); page = virt_to_head_page(objp); - slabp = page_get_slab(page); + slabp = page->slab_page; if (cachep->flags & SLAB_RED_ZONE) { verify_redzone_free(cachep, objp); @@ -3065,7 +2990,7 @@ static void *cache_free_debugcheck(struct kmem_cache *cachep, void *objp, *dbg_redzone2(cachep, objp) = RED_INACTIVE; } if (cachep->flags & SLAB_STORE_USER) - *dbg_userword(cachep, objp) = caller; + *dbg_userword(cachep, objp) = (void *)caller; objnr = obj_to_index(cachep, slabp, objp); @@ -3077,10 +3002,10 @@ static void *cache_free_debugcheck(struct kmem_cache *cachep, void *objp, #endif if (cachep->flags & SLAB_POISON) { #ifdef CONFIG_DEBUG_PAGEALLOC - if ((cachep->buffer_size % PAGE_SIZE)==0 && OFF_SLAB(cachep)) { - store_stackinfo(cachep, objp, (unsigned long)caller); + if ((cachep->size % PAGE_SIZE)==0 && OFF_SLAB(cachep)) { + store_stackinfo(cachep, objp, caller); kernel_map_pages(virt_to_page(objp), - cachep->buffer_size / PAGE_SIZE, 0); + cachep->size / PAGE_SIZE, 0); } else { poison_obj(cachep, objp, POISON_FREE); } @@ -3120,16 +3045,19 @@ static void check_slabp(struct kmem_cache *cachep, struct slab *slabp) #define check_slabp(x,y) do { } while(0) #endif -static void *cache_alloc_refill(struct kmem_cache *cachep, gfp_t flags) +static void *cache_alloc_refill(struct kmem_cache *cachep, gfp_t flags, + bool force_refill) { int batchcount; struct kmem_list3 *l3; struct array_cache *ac; int node; -retry: check_irq_off(); node = numa_mem_id(); + if (unlikely(force_refill)) + goto force_grow; +retry: ac = cpu_cache_get(cachep); batchcount = ac->batchcount; if (!ac->touched && batchcount > BATCHREFILL_LIMIT) { @@ -3179,8 +3107,8 @@ static void *cache_alloc_refill(struct kmem_cache *cachep, gfp_t flags) STATS_INC_ACTIVE(cachep); STATS_SET_HIGH(cachep); - ac->entry[ac->avail++] = slab_get_obj(cachep, slabp, - node); + ac_put_obj(cachep, ac, slab_get_obj(cachep, slabp, + node)); } check_slabp(cachep, slabp); @@ -3199,18 +3127,23 @@ static void *cache_alloc_refill(struct kmem_cache *cachep, gfp_t flags) if (unlikely(!ac->avail)) { int x; +force_grow: x = cache_grow(cachep, flags | GFP_THISNODE, node, NULL); /* cache_grow can reenable interrupts, then ac could change. */ ac = cpu_cache_get(cachep); - if (!x && ac->avail == 0) /* no objects in sight? abort */ + node = numa_mem_id(); + + /* no objects in sight? abort */ + if (!x && (ac->avail == 0 || force_refill)) return NULL; if (!ac->avail) /* objects refilled by interrupt? */ goto retry; } ac->touched = 1; - return ac->entry[--ac->avail]; + + return ac_get_obj(cachep, ac, flags, force_refill); } static inline void cache_alloc_debugcheck_before(struct kmem_cache *cachep, @@ -3224,15 +3157,15 @@ static inline void cache_alloc_debugcheck_before(struct kmem_cache *cachep, #if DEBUG static void *cache_alloc_debugcheck_after(struct kmem_cache *cachep, - gfp_t flags, void *objp, void *caller) + gfp_t flags, void *objp, unsigned long caller) { if (!objp) return objp; if (cachep->flags & SLAB_POISON) { #ifdef CONFIG_DEBUG_PAGEALLOC - if ((cachep->buffer_size % PAGE_SIZE) == 0 && OFF_SLAB(cachep)) + if ((cachep->size % PAGE_SIZE) == 0 && OFF_SLAB(cachep)) kernel_map_pages(virt_to_page(objp), - cachep->buffer_size / PAGE_SIZE, 1); + cachep->size / PAGE_SIZE, 1); else check_poison_obj(cachep, objp); #else @@ -3241,7 +3174,7 @@ static void *cache_alloc_debugcheck_after(struct kmem_cache *cachep, poison_obj(cachep, objp, POISON_INUSE); } if (cachep->flags & SLAB_STORE_USER) - *dbg_userword(cachep, objp) = caller; + *dbg_userword(cachep, objp) = (void *)caller; if (cachep->flags & SLAB_RED_ZONE) { if (*dbg_redzone1(cachep, objp) != RED_INACTIVE || @@ -3261,8 +3194,8 @@ static void *cache_alloc_debugcheck_after(struct kmem_cache *cachep, struct slab *slabp; unsigned objnr; - slabp = page_get_slab(virt_to_head_page(objp)); - objnr = (unsigned)(objp - slabp->s_mem) / cachep->buffer_size; + slabp = virt_to_head_page(objp)->slab_page; + objnr = (unsigned)(objp - slabp->s_mem) / cachep->size; slab_bufctl(slabp)[objnr] = BUFCTL_ACTIVE; } #endif @@ -3282,33 +3215,45 @@ static void *cache_alloc_debugcheck_after(struct kmem_cache *cachep, static bool slab_should_failslab(struct kmem_cache *cachep, gfp_t flags) { - if (cachep == &cache_cache) + if (cachep == kmem_cache) return false; - return should_failslab(obj_size(cachep), flags, cachep->flags); + return should_failslab(cachep->object_size, flags, cachep->flags); } static inline void *____cache_alloc(struct kmem_cache *cachep, gfp_t flags) { void *objp; struct array_cache *ac; + bool force_refill = false; check_irq_off(); ac = cpu_cache_get(cachep); if (likely(ac->avail)) { - STATS_INC_ALLOCHIT(cachep); ac->touched = 1; - objp = ac->entry[--ac->avail]; - } else { - STATS_INC_ALLOCMISS(cachep); - objp = cache_alloc_refill(cachep, flags); + objp = ac_get_obj(cachep, ac, flags, false); + /* - * the 'ac' may be updated by cache_alloc_refill(), - * and kmemleak_erase() requires its correct value. + * Allow for the possibility all avail objects are not allowed + * by the current flags */ - ac = cpu_cache_get(cachep); + if (objp) { + STATS_INC_ALLOCHIT(cachep); + goto out; + } + force_refill = true; } + + STATS_INC_ALLOCMISS(cachep); + objp = cache_alloc_refill(cachep, flags, force_refill); + /* + * the 'ac' may be updated by cache_alloc_refill(), + * and kmemleak_erase() requires its correct value. + */ + ac = cpu_cache_get(cachep); + +out: /* * To avoid a false negative, if an object that is in one of the * per-CPU caches is leaked, we need to make sure kmemleak doesn't @@ -3336,7 +3281,7 @@ static void *alternate_node_alloc(struct kmem_cache *cachep, gfp_t flags) if (cpuset_do_slab_mem_spread() && (cachep->flags & SLAB_MEM_SPREAD)) nid_alloc = cpuset_slab_spread_node(); else if (current->mempolicy) - nid_alloc = slab_node(current->mempolicy); + nid_alloc = slab_node(); if (nid_alloc != nid_here) return ____cache_alloc_node(cachep, flags, nid_alloc); return NULL; @@ -3368,7 +3313,7 @@ static void *fallback_alloc(struct kmem_cache *cache, gfp_t flags) retry_cpuset: cpuset_mems_cookie = get_mems_allowed(); - zonelist = node_zonelist(slab_node(current->mempolicy), flags); + zonelist = node_zonelist(slab_node(), flags); retry: /* @@ -3503,8 +3448,8 @@ static void *____cache_alloc_node(struct kmem_cache *cachep, gfp_t flags, * Fallback to other node is possible if __GFP_THISNODE is not set. */ static __always_inline void * -__cache_alloc_node(struct kmem_cache *cachep, gfp_t flags, int nodeid, - void *caller) +slab_alloc_node(struct kmem_cache *cachep, gfp_t flags, int nodeid, + unsigned long caller) { unsigned long save_flags; void *ptr; @@ -3545,14 +3490,14 @@ __cache_alloc_node(struct kmem_cache *cachep, gfp_t flags, int nodeid, out: local_irq_restore(save_flags); ptr = cache_alloc_debugcheck_after(cachep, flags, ptr, caller); - kmemleak_alloc_recursive(ptr, obj_size(cachep), 1, cachep->flags, + kmemleak_alloc_recursive(ptr, cachep->object_size, 1, cachep->flags, flags); if (likely(ptr)) - kmemcheck_slab_alloc(cachep, flags, ptr, obj_size(cachep)); + kmemcheck_slab_alloc(cachep, flags, ptr, cachep->object_size); if (unlikely((flags & __GFP_ZERO) && ptr)) - memset(ptr, 0, obj_size(cachep)); + memset(ptr, 0, cachep->object_size); return ptr; } @@ -3590,7 +3535,7 @@ __do_cache_alloc(struct kmem_cache *cachep, gfp_t flags) #endif /* CONFIG_NUMA */ static __always_inline void * -__cache_alloc(struct kmem_cache *cachep, gfp_t flags, void *caller) +slab_alloc(struct kmem_cache *cachep, gfp_t flags, unsigned long caller) { unsigned long save_flags; void *objp; @@ -3607,15 +3552,15 @@ __cache_alloc(struct kmem_cache *cachep, gfp_t flags, void *caller) objp = __do_cache_alloc(cachep, flags); local_irq_restore(save_flags); objp = cache_alloc_debugcheck_after(cachep, flags, objp, caller); - kmemleak_alloc_recursive(objp, obj_size(cachep), 1, cachep->flags, + kmemleak_alloc_recursive(objp, cachep->object_size, 1, cachep->flags, flags); prefetchw(objp); if (likely(objp)) - kmemcheck_slab_alloc(cachep, flags, objp, obj_size(cachep)); + kmemcheck_slab_alloc(cachep, flags, objp, cachep->object_size); if (unlikely((flags & __GFP_ZERO) && objp)) - memset(objp, 0, obj_size(cachep)); + memset(objp, 0, cachep->object_size); return objp; } @@ -3630,9 +3575,12 @@ static void free_block(struct kmem_cache *cachep, void **objpp, int nr_objects, struct kmem_list3 *l3; for (i = 0; i < nr_objects; i++) { - void *objp = objpp[i]; + void *objp; struct slab *slabp; + clear_obj_pfmemalloc(&objpp[i]); + objp = objpp[i]; + slabp = virt_to_slab(objp); l3 = cachep->nodelists[node]; list_del(&slabp->list); @@ -3723,7 +3671,7 @@ static void cache_flusharray(struct kmem_cache *cachep, struct array_cache *ac) * be in this state _before_ it is released. Called with disabled ints. */ static inline void __cache_free(struct kmem_cache *cachep, void *objp, - void *caller) + unsigned long caller) { struct array_cache *ac = cpu_cache_get(cachep); @@ -3731,7 +3679,7 @@ static inline void __cache_free(struct kmem_cache *cachep, void *objp, kmemleak_free_recursive(objp, cachep->flags); objp = cache_free_debugcheck(cachep, objp, caller); - kmemcheck_slab_free(cachep, objp, obj_size(cachep)); + kmemcheck_slab_free(cachep, objp, cachep->object_size); /* * Skip calling cache_free_alien() when the platform is not numa. @@ -3750,7 +3698,7 @@ static inline void __cache_free(struct kmem_cache *cachep, void *objp, cache_flusharray(cachep, ac); } - ac->entry[ac->avail++] = objp; + ac_put_obj(cachep, ac, objp); } /** @@ -3763,10 +3711,10 @@ static inline void __cache_free(struct kmem_cache *cachep, void *objp, */ void *kmem_cache_alloc(struct kmem_cache *cachep, gfp_t flags) { - void *ret = __cache_alloc(cachep, flags, __builtin_return_address(0)); + void *ret = slab_alloc(cachep, flags, _RET_IP_); trace_kmem_cache_alloc(_RET_IP_, ret, - obj_size(cachep), cachep->buffer_size, flags); + cachep->object_size, cachep->size, flags); return ret; } @@ -3774,14 +3722,14 @@ EXPORT_SYMBOL(kmem_cache_alloc); #ifdef CONFIG_TRACING void * -kmem_cache_alloc_trace(size_t size, struct kmem_cache *cachep, gfp_t flags) +kmem_cache_alloc_trace(struct kmem_cache *cachep, gfp_t flags, size_t size) { void *ret; - ret = __cache_alloc(cachep, flags, __builtin_return_address(0)); + ret = slab_alloc(cachep, flags, _RET_IP_); trace_kmalloc(_RET_IP_, ret, - size, slab_buffer_size(cachep), flags); + size, cachep->size, flags); return ret; } EXPORT_SYMBOL(kmem_cache_alloc_trace); @@ -3790,11 +3738,10 @@ EXPORT_SYMBOL(kmem_cache_alloc_trace); #ifdef CONFIG_NUMA void *kmem_cache_alloc_node(struct kmem_cache *cachep, gfp_t flags, int nodeid) { - void *ret = __cache_alloc_node(cachep, flags, nodeid, - __builtin_return_address(0)); + void *ret = slab_alloc_node(cachep, flags, nodeid, _RET_IP_); trace_kmem_cache_alloc_node(_RET_IP_, ret, - obj_size(cachep), cachep->buffer_size, + cachep->object_size, cachep->size, flags, nodeid); return ret; @@ -3802,17 +3749,17 @@ void *kmem_cache_alloc_node(struct kmem_cache *cachep, gfp_t flags, int nodeid) EXPORT_SYMBOL(kmem_cache_alloc_node); #ifdef CONFIG_TRACING -void *kmem_cache_alloc_node_trace(size_t size, - struct kmem_cache *cachep, +void *kmem_cache_alloc_node_trace(struct kmem_cache *cachep, gfp_t flags, - int nodeid) + int nodeid, + size_t size) { void *ret; - ret = __cache_alloc_node(cachep, flags, nodeid, - __builtin_return_address(0)); + ret = slab_alloc_node(cachep, flags, nodeid, _RET_IP_); + trace_kmalloc_node(_RET_IP_, ret, - size, slab_buffer_size(cachep), + size, cachep->size, flags, nodeid); return ret; } @@ -3820,34 +3767,33 @@ EXPORT_SYMBOL(kmem_cache_alloc_node_trace); #endif static __always_inline void * -__do_kmalloc_node(size_t size, gfp_t flags, int node, void *caller) +__do_kmalloc_node(size_t size, gfp_t flags, int node, unsigned long caller) { struct kmem_cache *cachep; cachep = kmem_find_general_cachep(size, flags); if (unlikely(ZERO_OR_NULL_PTR(cachep))) return cachep; - return kmem_cache_alloc_node_trace(size, cachep, flags, node); + return kmem_cache_alloc_node_trace(cachep, flags, node, size); } #if defined(CONFIG_DEBUG_SLAB) || defined(CONFIG_TRACING) void *__kmalloc_node(size_t size, gfp_t flags, int node) { - return __do_kmalloc_node(size, flags, node, - __builtin_return_address(0)); + return __do_kmalloc_node(size, flags, node, _RET_IP_); } EXPORT_SYMBOL(__kmalloc_node); void *__kmalloc_node_track_caller(size_t size, gfp_t flags, int node, unsigned long caller) { - return __do_kmalloc_node(size, flags, node, (void *)caller); + return __do_kmalloc_node(size, flags, node, caller); } EXPORT_SYMBOL(__kmalloc_node_track_caller); #else void *__kmalloc_node(size_t size, gfp_t flags, int node) { - return __do_kmalloc_node(size, flags, node, NULL); + return __do_kmalloc_node(size, flags, node, 0); } EXPORT_SYMBOL(__kmalloc_node); #endif /* CONFIG_DEBUG_SLAB || CONFIG_TRACING */ @@ -3860,7 +3806,7 @@ EXPORT_SYMBOL(__kmalloc_node); * @caller: function caller for debug tracking of the caller */ static __always_inline void *__do_kmalloc(size_t size, gfp_t flags, - void *caller) + unsigned long caller) { struct kmem_cache *cachep; void *ret; @@ -3873,10 +3819,10 @@ static __always_inline void *__do_kmalloc(size_t size, gfp_t flags, cachep = __find_general_cachep(size, flags); if (unlikely(ZERO_OR_NULL_PTR(cachep))) return cachep; - ret = __cache_alloc(cachep, flags, caller); + ret = slab_alloc(cachep, flags, caller); - trace_kmalloc((unsigned long) caller, ret, - size, cachep->buffer_size, flags); + trace_kmalloc(caller, ret, + size, cachep->size, flags); return ret; } @@ -3885,20 +3831,20 @@ static __always_inline void *__do_kmalloc(size_t size, gfp_t flags, #if defined(CONFIG_DEBUG_SLAB) || defined(CONFIG_TRACING) void *__kmalloc(size_t size, gfp_t flags) { - return __do_kmalloc(size, flags, __builtin_return_address(0)); + return __do_kmalloc(size, flags, _RET_IP_); } EXPORT_SYMBOL(__kmalloc); void *__kmalloc_track_caller(size_t size, gfp_t flags, unsigned long caller) { - return __do_kmalloc(size, flags, (void *)caller); + return __do_kmalloc(size, flags, caller); } EXPORT_SYMBOL(__kmalloc_track_caller); #else void *__kmalloc(size_t size, gfp_t flags) { - return __do_kmalloc(size, flags, NULL); + return __do_kmalloc(size, flags, 0); } EXPORT_SYMBOL(__kmalloc); #endif @@ -3914,12 +3860,15 @@ EXPORT_SYMBOL(__kmalloc); void kmem_cache_free(struct kmem_cache *cachep, void *objp) { unsigned long flags; + cachep = cache_from_obj(cachep, objp); + if (!cachep) + return; local_irq_save(flags); - debug_check_no_locks_freed(objp, obj_size(cachep)); + debug_check_no_locks_freed(objp, cachep->object_size); if (!(cachep->flags & SLAB_DEBUG_OBJECTS)) - debug_check_no_obj_freed(objp, obj_size(cachep)); - __cache_free(cachep, objp, __builtin_return_address(0)); + debug_check_no_obj_freed(objp, cachep->object_size); + __cache_free(cachep, objp, _RET_IP_); local_irq_restore(flags); trace_kmem_cache_free(_RET_IP_, objp); @@ -3947,19 +3896,14 @@ void kfree(const void *objp) local_irq_save(flags); kfree_debugcheck(objp); c = virt_to_cache(objp); - debug_check_no_locks_freed(objp, obj_size(c)); - debug_check_no_obj_freed(objp, obj_size(c)); - __cache_free(c, (void *)objp, __builtin_return_address(0)); + debug_check_no_locks_freed(objp, c->object_size); + + debug_check_no_obj_freed(objp, c->object_size); + __cache_free(c, (void *)objp, _RET_IP_); local_irq_restore(flags); } EXPORT_SYMBOL(kfree); -unsigned int kmem_cache_size(struct kmem_cache *cachep) -{ - return obj_size(cachep); -} -EXPORT_SYMBOL(kmem_cache_size); - /* * This initializes kmem_list3 or resizes various caches for all nodes. */ @@ -4030,7 +3974,7 @@ static int alloc_kmemlist(struct kmem_cache *cachep, gfp_t gfp) return 0; fail: - if (!cachep->next.next) { + if (!cachep->list.next) { /* Cache is not active yet. Roll back what we did */ node--; while (node >= 0) { @@ -4065,7 +4009,7 @@ static void do_ccupdate_local(void *info) new->new[smp_processor_id()] = old; } -/* Always called with the cache_chain_mutex held */ +/* Always called with the slab_mutex held */ static int do_tune_cpucache(struct kmem_cache *cachep, int limit, int batchcount, int shared, gfp_t gfp) { @@ -4109,7 +4053,7 @@ static int do_tune_cpucache(struct kmem_cache *cachep, int limit, return alloc_kmemlist(cachep, gfp); } -/* Called with cache_chain_mutex held always */ +/* Called with slab_mutex held always */ static int enable_cpucache(struct kmem_cache *cachep, gfp_t gfp) { int err; @@ -4124,13 +4068,13 @@ static int enable_cpucache(struct kmem_cache *cachep, gfp_t gfp) * The numbers are guessed, we should auto-tune as described by * Bonwick. */ - if (cachep->buffer_size > 131072) + if (cachep->size > 131072) limit = 1; - else if (cachep->buffer_size > PAGE_SIZE) + else if (cachep->size > PAGE_SIZE) limit = 8; - else if (cachep->buffer_size > 1024) + else if (cachep->size > 1024) limit = 24; - else if (cachep->buffer_size > 256) + else if (cachep->size > 256) limit = 54; else limit = 120; @@ -4145,7 +4089,7 @@ static int enable_cpucache(struct kmem_cache *cachep, gfp_t gfp) * to a larger limit. Thus disabled by default. */ shared = 0; - if (cachep->buffer_size <= PAGE_SIZE && num_possible_cpus() > 1) + if (cachep->size <= PAGE_SIZE && num_possible_cpus() > 1) shared = 8; #if DEBUG @@ -4211,11 +4155,11 @@ static void cache_reap(struct work_struct *w) int node = numa_mem_id(); struct delayed_work *work = to_delayed_work(w); - if (!mutex_trylock(&cache_chain_mutex)) + if (!mutex_trylock(&slab_mutex)) /* Give up. Setup the next iteration. */ goto out; - list_for_each_entry(searchp, &cache_chain, next) { + list_for_each_entry(searchp, &slab_caches, list) { check_irq_on(); /* @@ -4253,7 +4197,7 @@ static void cache_reap(struct work_struct *w) cond_resched(); } check_irq_on(); - mutex_unlock(&cache_chain_mutex); + mutex_unlock(&slab_mutex); next_reap_node(); out: /* Set up the next iteration */ @@ -4261,54 +4205,8 @@ static void cache_reap(struct work_struct *w) } #ifdef CONFIG_SLABINFO - -static void print_slabinfo_header(struct seq_file *m) +void get_slabinfo(struct kmem_cache *cachep, struct slabinfo *sinfo) { - /* - * Output format version, so at least we can change it - * without _too_ many complaints. - */ -#if STATS - seq_puts(m, "slabinfo - version: 2.1 (statistics)\n"); -#else - seq_puts(m, "slabinfo - version: 2.1\n"); -#endif - seq_puts(m, "# name " - " "); - seq_puts(m, " : tunables "); - seq_puts(m, " : slabdata "); -#if STATS - seq_puts(m, " : globalstat " - " "); - seq_puts(m, " : cpustat "); -#endif - seq_putc(m, '\n'); -} - -static void *s_start(struct seq_file *m, loff_t *pos) -{ - loff_t n = *pos; - - mutex_lock(&cache_chain_mutex); - if (!n) - print_slabinfo_header(m); - - return seq_list_start(&cache_chain, *pos); -} - -static void *s_next(struct seq_file *m, void *p, loff_t *pos) -{ - return seq_list_next(p, &cache_chain, pos); -} - -static void s_stop(struct seq_file *m, void *p) -{ - mutex_unlock(&cache_chain_mutex); -} - -static int s_show(struct seq_file *m, void *p) -{ - struct kmem_cache *cachep = list_entry(p, struct kmem_cache, next); struct slab *slabp; unsigned long active_objs; unsigned long num_objs; @@ -4363,13 +4261,20 @@ static int s_show(struct seq_file *m, void *p) if (error) printk(KERN_ERR "slab: cache %s error: %s\n", name, error); - seq_printf(m, "%-17s %6lu %6lu %6u %4u %4d", - name, active_objs, num_objs, cachep->buffer_size, - cachep->num, (1 << cachep->gfporder)); - seq_printf(m, " : tunables %4u %4u %4u", - cachep->limit, cachep->batchcount, cachep->shared); - seq_printf(m, " : slabdata %6lu %6lu %6lu", - active_slabs, num_slabs, shared_avail); + sinfo->active_objs = active_objs; + sinfo->num_objs = num_objs; + sinfo->active_slabs = active_slabs; + sinfo->num_slabs = num_slabs; + sinfo->shared_avail = shared_avail; + sinfo->limit = cachep->limit; + sinfo->batchcount = cachep->batchcount; + sinfo->shared = cachep->shared; + sinfo->objects_per_slab = cachep->num; + sinfo->cache_order = cachep->gfporder; +} + +void slabinfo_show_stats(struct seq_file *m, struct kmem_cache *cachep) +{ #if STATS { /* list3 stats */ unsigned long high = cachep->high_mark; @@ -4399,31 +4304,8 @@ static int s_show(struct seq_file *m, void *p) allochit, allocmiss, freehit, freemiss); } #endif - seq_putc(m, '\n'); - return 0; } -/* - * slabinfo_op - iterator that generates /proc/slabinfo - * - * Output layout: - * cache-name - * num-active-objs - * total-objs - * object size - * num-active-slabs - * total-slabs - * num-pages-per-slab - * + further values on SMP and with statistics enabled - */ - -static const struct seq_operations slabinfo_op = { - .start = s_start, - .next = s_next, - .stop = s_stop, - .show = s_show, -}; - #define MAX_SLABINFO_WRITE 128 /** * slabinfo_write - Tuning for the slab allocator @@ -4432,7 +4314,7 @@ static const struct seq_operations slabinfo_op = { * @count: data length * @ppos: unused */ -static ssize_t slabinfo_write(struct file *file, const char __user *buffer, +ssize_t slabinfo_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) { char kbuf[MAX_SLABINFO_WRITE + 1], *tmp; @@ -4454,9 +4336,9 @@ static ssize_t slabinfo_write(struct file *file, const char __user *buffer, return -EINVAL; /* Find the cache in the chain of caches. */ - mutex_lock(&cache_chain_mutex); + mutex_lock(&slab_mutex); res = -EINVAL; - list_for_each_entry(cachep, &cache_chain, next) { + list_for_each_entry(cachep, &slab_caches, list) { if (!strcmp(cachep->name, kbuf)) { if (limit < 1 || batchcount < 1 || batchcount > limit || shared < 0) { @@ -4469,31 +4351,18 @@ static ssize_t slabinfo_write(struct file *file, const char __user *buffer, break; } } - mutex_unlock(&cache_chain_mutex); + mutex_unlock(&slab_mutex); if (res >= 0) res = count; return res; } -static int slabinfo_open(struct inode *inode, struct file *file) -{ - return seq_open(file, &slabinfo_op); -} - -static const struct file_operations proc_slabinfo_operations = { - .open = slabinfo_open, - .read = seq_read, - .write = slabinfo_write, - .llseek = seq_lseek, - .release = seq_release, -}; - #ifdef CONFIG_DEBUG_SLAB_LEAK static void *leaks_start(struct seq_file *m, loff_t *pos) { - mutex_lock(&cache_chain_mutex); - return seq_list_start(&cache_chain, *pos); + mutex_lock(&slab_mutex); + return seq_list_start(&slab_caches, *pos); } static inline int add_caller(unsigned long *n, unsigned long v) @@ -4532,7 +4401,7 @@ static void handle_slab(unsigned long *n, struct kmem_cache *c, struct slab *s) int i; if (n[0] == n[1]) return; - for (i = 0, p = s->s_mem; i < c->num; i++, p += c->buffer_size) { + for (i = 0, p = s->s_mem; i < c->num; i++, p += c->size) { if (slab_bufctl(s)[i] != BUFCTL_ACTIVE) continue; if (!add_caller(n, (unsigned long)*dbg_userword(c, p))) @@ -4558,7 +4427,7 @@ static void show_symbol(struct seq_file *m, unsigned long address) static int leaks_show(struct seq_file *m, void *p) { - struct kmem_cache *cachep = list_entry(p, struct kmem_cache, next); + struct kmem_cache *cachep = list_entry(p, struct kmem_cache, list); struct slab *slabp; struct kmem_list3 *l3; const char *name; @@ -4592,17 +4461,17 @@ static int leaks_show(struct seq_file *m, void *p) name = cachep->name; if (n[0] == n[1]) { /* Increase the buffer size */ - mutex_unlock(&cache_chain_mutex); + mutex_unlock(&slab_mutex); m->private = kzalloc(n[0] * 4 * sizeof(unsigned long), GFP_KERNEL); if (!m->private) { /* Too bad, we are really out */ m->private = n; - mutex_lock(&cache_chain_mutex); + mutex_lock(&slab_mutex); return -ENOMEM; } *(unsigned long *)m->private = n[0] * 2; kfree(n); - mutex_lock(&cache_chain_mutex); + mutex_lock(&slab_mutex); /* Now make sure this entry will be retried */ m->count = m->size; return 0; @@ -4616,6 +4485,16 @@ static int leaks_show(struct seq_file *m, void *p) return 0; } +static void *s_next(struct seq_file *m, void *p, loff_t *pos) +{ + return seq_list_next(p, &slab_caches, pos); +} + +static void s_stop(struct seq_file *m, void *p) +{ + mutex_unlock(&slab_mutex); +} + static const struct seq_operations slabstats_op = { .start = leaks_start, .next = s_next, @@ -4650,7 +4529,6 @@ static const struct file_operations proc_slabstats_operations = { static int __init slab_proc_init(void) { - proc_create("slabinfo",S_IWUSR|S_IRUSR,NULL,&proc_slabinfo_operations); #ifdef CONFIG_DEBUG_SLAB_LEAK proc_create("slab_allocators", 0, NULL, &proc_slabstats_operations); #endif @@ -4677,6 +4555,6 @@ size_t ksize(const void *objp) if (unlikely(objp == ZERO_SIZE_PTR)) return 0; - return obj_size(virt_to_cache(objp)); + return virt_to_cache(objp)->object_size; } EXPORT_SYMBOL(ksize); diff --git a/mm/slab.h b/mm/slab.h new file mode 100644 index 00000000000..d6d8456b556 --- /dev/null +++ b/mm/slab.h @@ -0,0 +1,128 @@ +#ifndef MM_SLAB_H +#define MM_SLAB_H +/* + * Internal slab definitions + */ + +/* + * State of the slab allocator. + * + * This is used to describe the states of the allocator during bootup. + * Allocators use this to gradually bootstrap themselves. Most allocators + * have the problem that the structures used for managing slab caches are + * allocated from slab caches themselves. + */ +enum slab_state { + DOWN, /* No slab functionality yet */ + PARTIAL, /* SLUB: kmem_cache_node available */ + PARTIAL_ARRAYCACHE, /* SLAB: kmalloc size for arraycache available */ + PARTIAL_L3, /* SLAB: kmalloc size for l3 struct available */ + UP, /* Slab caches usable but not all extras yet */ + FULL /* Everything is working */ +}; + +extern enum slab_state slab_state; + +/* The slab cache mutex protects the management structures during changes */ +extern struct mutex slab_mutex; + +/* The list of all slab caches on the system */ +extern struct list_head slab_caches; + +/* The slab cache that manages slab cache information */ +extern struct kmem_cache *kmem_cache; + +unsigned long calculate_alignment(unsigned long flags, + unsigned long align, unsigned long size); + +/* Functions provided by the slab allocators */ +extern int __kmem_cache_create(struct kmem_cache *, unsigned long flags); + +extern struct kmem_cache *create_kmalloc_cache(const char *name, size_t size, + unsigned long flags); +extern void create_boot_cache(struct kmem_cache *, const char *name, + size_t size, unsigned long flags); + +#ifdef CONFIG_SLUB +struct kmem_cache *__kmem_cache_alias(const char *name, size_t size, + size_t align, unsigned long flags, void (*ctor)(void *)); +#else +static inline struct kmem_cache *__kmem_cache_alias(const char *name, size_t size, + size_t align, unsigned long flags, void (*ctor)(void *)) +{ return NULL; } +#endif + + +/* Legal flag mask for kmem_cache_create(), for various configurations */ +#define SLAB_CORE_FLAGS (SLAB_HWCACHE_ALIGN | SLAB_CACHE_DMA | SLAB_PANIC | \ + SLAB_DESTROY_BY_RCU | SLAB_DEBUG_OBJECTS ) + +#if defined(CONFIG_DEBUG_SLAB) +#define SLAB_DEBUG_FLAGS (SLAB_RED_ZONE | SLAB_POISON | SLAB_STORE_USER) +#elif defined(CONFIG_SLUB_DEBUG) +#define SLAB_DEBUG_FLAGS (SLAB_RED_ZONE | SLAB_POISON | SLAB_STORE_USER | \ + SLAB_TRACE | SLAB_DEBUG_FREE) +#else +#define SLAB_DEBUG_FLAGS (0) +#endif + +#if defined(CONFIG_SLAB) +#define SLAB_CACHE_FLAGS (SLAB_MEM_SPREAD | SLAB_NOLEAKTRACE | \ + SLAB_RECLAIM_ACCOUNT | SLAB_TEMPORARY | SLAB_NOTRACK) +#elif defined(CONFIG_SLUB) +#define SLAB_CACHE_FLAGS (SLAB_NOLEAKTRACE | SLAB_RECLAIM_ACCOUNT | \ + SLAB_TEMPORARY | SLAB_NOTRACK) +#else +#define SLAB_CACHE_FLAGS (0) +#endif + +#define CACHE_CREATE_MASK (SLAB_CORE_FLAGS | SLAB_DEBUG_FLAGS | SLAB_CACHE_FLAGS) + +int __kmem_cache_shutdown(struct kmem_cache *); + +struct seq_file; +struct file; + +struct slabinfo { + unsigned long active_objs; + unsigned long num_objs; + unsigned long active_slabs; + unsigned long num_slabs; + unsigned long shared_avail; + unsigned int limit; + unsigned int batchcount; + unsigned int shared; + unsigned int objects_per_slab; + unsigned int cache_order; +}; + +void get_slabinfo(struct kmem_cache *s, struct slabinfo *sinfo); +void slabinfo_show_stats(struct seq_file *m, struct kmem_cache *s); +ssize_t slabinfo_write(struct file *file, const char __user *buffer, + size_t count, loff_t *ppos); + +static inline bool slab_equal_or_root(struct kmem_cache *s, + struct kmem_cache *p) +{ + return true; +} + +static inline struct kmem_cache *cache_from_obj(struct kmem_cache *s, void *x) +{ + struct kmem_cache *cachep; + struct page *page; + + if (!unlikely(s->flags & SLAB_DEBUG_FREE)) + return s; + + page = virt_to_head_page(x); + cachep = page->slab_cache; + if (slab_equal_or_root(cachep, s)) + return cachep; + + pr_err("%s: Wrong slab cache. %s but object is from %s\n", + __FUNCTION__, cachep->name, s->name); + WARN_ON_ONCE(1); + return s; +} +#endif diff --git a/mm/slab_common.c b/mm/slab_common.c new file mode 100644 index 00000000000..7e0cdca704e --- /dev/null +++ b/mm/slab_common.c @@ -0,0 +1,371 @@ +/* + * Slab allocator functions that are independent of the allocator strategy + * + * (C) 2012 Christoph Lameter + */ +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "slab.h" + +enum slab_state slab_state; +LIST_HEAD(slab_caches); +DEFINE_MUTEX(slab_mutex); +struct kmem_cache *kmem_cache; + +#ifdef CONFIG_DEBUG_VM +static int kmem_cache_sanity_check(const char *name, size_t size) +{ + struct kmem_cache *s = NULL; + + if (!name || in_interrupt() || size < sizeof(void *) || + size > KMALLOC_MAX_SIZE) { + pr_err("kmem_cache_create(%s) integrity check failed\n", name); + return -EINVAL; + } + + list_for_each_entry(s, &slab_caches, list) { + char tmp; + int res; + + /* + * This happens when the module gets unloaded and doesn't + * destroy its slab cache and no-one else reuses the vmalloc + * area of the module. Print a warning. + */ + res = probe_kernel_address(s->name, tmp); + if (res) { + pr_err("Slab cache with size %d has lost its name\n", + s->object_size); + continue; + } + + if (!strcmp(s->name, name)) { + pr_err("%s (%s): Cache name already exists.\n", + __func__, name); + dump_stack(); + s = NULL; + return -EINVAL; + } + } + + WARN_ON(strchr(name, ' ')); /* It confuses parsers */ + return 0; +} +#else +static inline int kmem_cache_sanity_check(const char *name, size_t size) +{ + return 0; +} +#endif + +/* + * Figure out what the alignment of the objects will be given a set of + * flags, a user specified alignment and the size of the objects. + */ +unsigned long calculate_alignment(unsigned long flags, + unsigned long align, unsigned long size) +{ + /* + * If the user wants hardware cache aligned objects then follow that + * suggestion if the object is sufficiently large. + * + * The hardware cache alignment cannot override the specified + * alignment though. If that is greater then use it. + */ + if (flags & SLAB_HWCACHE_ALIGN) { + unsigned long ralign = cache_line_size(); + while (size <= ralign / 2) + ralign /= 2; + align = max(align, ralign); + } + + if (align < ARCH_SLAB_MINALIGN) + align = ARCH_SLAB_MINALIGN; + + return ALIGN(align, sizeof(void *)); +} + + +/* + * kmem_cache_create - Create a cache. + * @name: A string which is used in /proc/slabinfo to identify this cache. + * @size: The size of objects to be created in this cache. + * @align: The required alignment for the objects. + * @flags: SLAB flags + * @ctor: A constructor for the objects. + * + * Returns a ptr to the cache on success, NULL on failure. + * Cannot be called within a interrupt, but can be interrupted. + * The @ctor is run when new pages are allocated by the cache. + * + * The flags are + * + * %SLAB_POISON - Poison the slab with a known test pattern (a5a5a5a5) + * to catch references to uninitialised memory. + * + * %SLAB_RED_ZONE - Insert `Red' zones around the allocated memory to check + * for buffer overruns. + * + * %SLAB_HWCACHE_ALIGN - Align the objects in this cache to a hardware + * cacheline. This can be beneficial if you're counting cycles as closely + * as davem. + */ + +struct kmem_cache *kmem_cache_create(const char *name, size_t size, size_t align, + unsigned long flags, void (*ctor)(void *)) +{ + struct kmem_cache *s = NULL; + int err = 0; + + get_online_cpus(); + mutex_lock(&slab_mutex); + + if (!kmem_cache_sanity_check(name, size) == 0) + goto out_locked; + + /* + * Some allocators will constraint the set of valid flags to a subset + * of all flags. We expect them to define CACHE_CREATE_MASK in this + * case, and we'll just provide them with a sanitized version of the + * passed flags. + */ + flags &= CACHE_CREATE_MASK; + + s = __kmem_cache_alias(name, size, align, flags, ctor); + if (s) + goto out_locked; + + s = kmem_cache_zalloc(kmem_cache, GFP_KERNEL); + if (s) { + s->object_size = s->size = size; + s->align = calculate_alignment(flags, align, size); + s->ctor = ctor; + s->name = kstrdup(name, GFP_KERNEL); + if (!s->name) { + kmem_cache_free(kmem_cache, s); + err = -ENOMEM; + goto out_locked; + } + + err = __kmem_cache_create(s, flags); + if (!err) { + + s->refcount = 1; + list_add(&s->list, &slab_caches); + + } else { + kfree(s->name); + kmem_cache_free(kmem_cache, s); + } + } else + err = -ENOMEM; + +out_locked: + mutex_unlock(&slab_mutex); + put_online_cpus(); + + if (err) { + + if (flags & SLAB_PANIC) + panic("kmem_cache_create: Failed to create slab '%s'. Error %d\n", + name, err); + else { + printk(KERN_WARNING "kmem_cache_create(%s) failed with error %d", + name, err); + dump_stack(); + } + + return NULL; + } + + return s; +} +EXPORT_SYMBOL(kmem_cache_create); + +void kmem_cache_destroy(struct kmem_cache *s) +{ + get_online_cpus(); + mutex_lock(&slab_mutex); + s->refcount--; + if (!s->refcount) { + list_del(&s->list); + + if (!__kmem_cache_shutdown(s)) { + if (s->flags & SLAB_DESTROY_BY_RCU) + rcu_barrier(); + + kfree(s->name); + kmem_cache_free(kmem_cache, s); + } else { + list_add(&s->list, &slab_caches); + printk(KERN_ERR "kmem_cache_destroy %s: Slab cache still has objects\n", + s->name); + dump_stack(); + } + } + mutex_unlock(&slab_mutex); + put_online_cpus(); +} +EXPORT_SYMBOL(kmem_cache_destroy); + +int slab_is_available(void) +{ + return slab_state >= UP; +} + +#ifndef CONFIG_SLOB +/* Create a cache during boot when no slab services are available yet */ +void __init create_boot_cache(struct kmem_cache *s, const char *name, size_t size, + unsigned long flags) +{ + int err; + + s->name = name; + s->size = s->object_size = size; + s->align = calculate_alignment(flags, ARCH_KMALLOC_MINALIGN, size); + err = __kmem_cache_create(s, flags); + + if (err) + panic("Creation of kmalloc slab %s size=%zd failed. Reason %d\n", + name, size, err); + + s->refcount = -1; /* Exempt from merging for now */ +} + +struct kmem_cache *__init create_kmalloc_cache(const char *name, size_t size, + unsigned long flags) +{ + struct kmem_cache *s = kmem_cache_zalloc(kmem_cache, GFP_NOWAIT); + + if (!s) + panic("Out of memory when creating slab %s\n", name); + + create_boot_cache(s, name, size, flags); + list_add(&s->list, &slab_caches); + s->refcount = 1; + return s; +} + +#endif /* !CONFIG_SLOB */ + + +#ifdef CONFIG_SLABINFO +static void print_slabinfo_header(struct seq_file *m) +{ + /* + * Output format version, so at least we can change it + * without _too_ many complaints. + */ +#ifdef CONFIG_DEBUG_SLAB + seq_puts(m, "slabinfo - version: 2.1 (statistics)\n"); +#else + seq_puts(m, "slabinfo - version: 2.1\n"); +#endif + seq_puts(m, "# name " + " "); + seq_puts(m, " : tunables "); + seq_puts(m, " : slabdata "); +#ifdef CONFIG_DEBUG_SLAB + seq_puts(m, " : globalstat " + " "); + seq_puts(m, " : cpustat "); +#endif + seq_putc(m, '\n'); +} + +static void *s_start(struct seq_file *m, loff_t *pos) +{ + loff_t n = *pos; + + mutex_lock(&slab_mutex); + if (!n) + print_slabinfo_header(m); + + return seq_list_start(&slab_caches, *pos); +} + +static void *s_next(struct seq_file *m, void *p, loff_t *pos) +{ + return seq_list_next(p, &slab_caches, pos); +} + +static void s_stop(struct seq_file *m, void *p) +{ + mutex_unlock(&slab_mutex); +} + +static int s_show(struct seq_file *m, void *p) +{ + struct kmem_cache *s = list_entry(p, struct kmem_cache, list); + struct slabinfo sinfo; + + memset(&sinfo, 0, sizeof(sinfo)); + get_slabinfo(s, &sinfo); + + seq_printf(m, "%-17s %6lu %6lu %6u %4u %4d", + s->name, sinfo.active_objs, sinfo.num_objs, s->size, + sinfo.objects_per_slab, (1 << sinfo.cache_order)); + + seq_printf(m, " : tunables %4u %4u %4u", + sinfo.limit, sinfo.batchcount, sinfo.shared); + seq_printf(m, " : slabdata %6lu %6lu %6lu", + sinfo.active_slabs, sinfo.num_slabs, sinfo.shared_avail); + slabinfo_show_stats(m, s); + seq_putc(m, '\n'); + return 0; +} + +/* + * slabinfo_op - iterator that generates /proc/slabinfo + * + * Output layout: + * cache-name + * num-active-objs + * total-objs + * object size + * num-active-slabs + * total-slabs + * num-pages-per-slab + * + further values on SMP and with statistics enabled + */ +static const struct seq_operations slabinfo_op = { + .start = s_start, + .next = s_next, + .stop = s_stop, + .show = s_show, +}; + +static int slabinfo_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &slabinfo_op); +} + +static const struct file_operations proc_slabinfo_operations = { + .open = slabinfo_open, + .read = seq_read, + .write = slabinfo_write, + .llseek = seq_lseek, + .release = seq_release, +}; + +static int __init slab_proc_init(void) +{ + proc_create("slabinfo", S_IRUSR, NULL, &proc_slabinfo_operations); + return 0; +} +module_init(slab_proc_init); +#endif /* CONFIG_SLABINFO */ diff --git a/mm/slob.c b/mm/slob.c index 8105be42cad..4eb5eca47f2 100644 --- a/mm/slob.c +++ b/mm/slob.c @@ -28,9 +28,8 @@ * from kmalloc are prepended with a 4-byte header with the kmalloc size. * If kmalloc is asked for objects of PAGE_SIZE or larger, it calls * alloc_pages() directly, allocating compound pages so the page order - * does not have to be separately tracked, and also stores the exact - * allocation size in page->private so that it can be used to accurately - * provide ksize(). These objects are detected in kfree() because slob_page() + * does not have to be separately tracked. + * These objects are detected in kfree() because PageSlab() * is false for them. * * SLAB is emulated on top of SLOB by simply calling constructors and @@ -59,6 +58,7 @@ #include #include + #include #include /* struct reclaim_state */ #include @@ -72,6 +72,7 @@ #include +#include "slab.h" /* * slob_block has a field 'units', which indicates size of block if +ve, * or offset of next block if -ve (in SLOB_UNITs). @@ -91,36 +92,6 @@ struct slob_block { }; typedef struct slob_block slob_t; -/* - * We use struct page fields to manage some slob allocation aspects, - * however to avoid the horrible mess in include/linux/mm_types.h, we'll - * just define our own struct page type variant here. - */ -struct slob_page { - union { - struct { - unsigned long flags; /* mandatory */ - atomic_t _count; /* mandatory */ - slobidx_t units; /* free units left in page */ - unsigned long pad[2]; - slob_t *free; /* first free slob_t in page */ - struct list_head list; /* linked list of free pages */ - }; - struct page page; - }; -}; -static inline void struct_slob_page_wrong_size(void) -{ BUILD_BUG_ON(sizeof(struct slob_page) != sizeof(struct page)); } - -/* - * free_slob_page: call before a slob_page is returned to the page allocator. - */ -static inline void free_slob_page(struct slob_page *sp) -{ - reset_page_mapcount(&sp->page); - sp->page.mapping = NULL; -} - /* * All partially free slob pages go on these lists. */ @@ -130,52 +101,28 @@ static LIST_HEAD(free_slob_small); static LIST_HEAD(free_slob_medium); static LIST_HEAD(free_slob_large); -/* - * is_slob_page: True for all slob pages (false for bigblock pages) - */ -static inline int is_slob_page(struct slob_page *sp) -{ - return PageSlab((struct page *)sp); -} - -static inline void set_slob_page(struct slob_page *sp) -{ - __SetPageSlab((struct page *)sp); -} - -static inline void clear_slob_page(struct slob_page *sp) -{ - __ClearPageSlab((struct page *)sp); -} - -static inline struct slob_page *slob_page(const void *addr) -{ - return (struct slob_page *)virt_to_page(addr); -} - /* * slob_page_free: true for pages on free_slob_pages list. */ -static inline int slob_page_free(struct slob_page *sp) +static inline int slob_page_free(struct page *sp) { - return PageSlobFree((struct page *)sp); + return PageSlobFree(sp); } -static void set_slob_page_free(struct slob_page *sp, struct list_head *list) +static void set_slob_page_free(struct page *sp, struct list_head *list) { list_add(&sp->list, list); - __SetPageSlobFree((struct page *)sp); + __SetPageSlobFree(sp); } -static inline void clear_slob_page_free(struct slob_page *sp) +static inline void clear_slob_page_free(struct page *sp) { list_del(&sp->list); - __ClearPageSlobFree((struct page *)sp); + __ClearPageSlobFree(sp); } #define SLOB_UNIT sizeof(slob_t) #define SLOB_UNITS(size) (((size) + SLOB_UNIT - 1)/SLOB_UNIT) -#define SLOB_ALIGN L1_CACHE_BYTES /* * struct slob_rcu is inserted at the tail of allocated slob blocks, which @@ -245,7 +192,7 @@ static void *slob_new_pages(gfp_t gfp, int order, int node) void *page; #ifdef CONFIG_NUMA - if (node != -1) + if (node != NUMA_NO_NODE) page = alloc_pages_exact_node(node, gfp, order); else #endif @@ -267,12 +214,12 @@ static void slob_free_pages(void *b, int order) /* * Allocate a slob block within a given slob_page sp. */ -static void *slob_page_alloc(struct slob_page *sp, size_t size, int align) +static void *slob_page_alloc(struct page *sp, size_t size, int align) { slob_t *prev, *cur, *aligned = NULL; int delta = 0, units = SLOB_UNITS(size); - for (prev = NULL, cur = sp->free; ; prev = cur, cur = slob_next(cur)) { + for (prev = NULL, cur = sp->freelist; ; prev = cur, cur = slob_next(cur)) { slobidx_t avail = slob_units(cur); if (align) { @@ -296,12 +243,12 @@ static void *slob_page_alloc(struct slob_page *sp, size_t size, int align) if (prev) set_slob(prev, slob_units(prev), next); else - sp->free = next; + sp->freelist = next; } else { /* fragment */ if (prev) set_slob(prev, slob_units(prev), cur + units); else - sp->free = cur + units; + sp->freelist = cur + units; set_slob(cur + units, avail - units, next); } @@ -320,7 +267,7 @@ static void *slob_page_alloc(struct slob_page *sp, size_t size, int align) */ static void *slob_alloc(size_t size, gfp_t gfp, int align, int node) { - struct slob_page *sp; + struct page *sp; struct list_head *prev; struct list_head *slob_list; slob_t *b = NULL; @@ -341,7 +288,7 @@ static void *slob_alloc(size_t size, gfp_t gfp, int align, int node) * If there's a node specification, search for a partial * page with a matching node id in the freelist. */ - if (node != -1 && page_to_nid(&sp->page) != node) + if (node != NUMA_NO_NODE && page_to_nid(sp) != node) continue; #endif /* Enough room on this page? */ @@ -369,12 +316,12 @@ static void *slob_alloc(size_t size, gfp_t gfp, int align, int node) b = slob_new_pages(gfp & ~__GFP_ZERO, 0, node); if (!b) return NULL; - sp = slob_page(b); - set_slob_page(sp); + sp = virt_to_page(b); + __SetPageSlab(sp); spin_lock_irqsave(&slob_lock, flags); sp->units = SLOB_UNITS(PAGE_SIZE); - sp->free = b; + sp->freelist = b; INIT_LIST_HEAD(&sp->list); set_slob(b, SLOB_UNITS(PAGE_SIZE), b + SLOB_UNITS(PAGE_SIZE)); set_slob_page_free(sp, slob_list); @@ -392,7 +339,7 @@ static void *slob_alloc(size_t size, gfp_t gfp, int align, int node) */ static void slob_free(void *block, int size) { - struct slob_page *sp; + struct page *sp; slob_t *prev, *next, *b = (slob_t *)block; slobidx_t units; unsigned long flags; @@ -402,7 +349,7 @@ static void slob_free(void *block, int size) return; BUG_ON(!size); - sp = slob_page(block); + sp = virt_to_page(block); units = SLOB_UNITS(size); spin_lock_irqsave(&slob_lock, flags); @@ -412,8 +359,8 @@ static void slob_free(void *block, int size) if (slob_page_free(sp)) clear_slob_page_free(sp); spin_unlock_irqrestore(&slob_lock, flags); - clear_slob_page(sp); - free_slob_page(sp); + __ClearPageSlab(sp); + reset_page_mapcount(sp); slob_free_pages(b, 0); return; } @@ -421,7 +368,7 @@ static void slob_free(void *block, int size) if (!slob_page_free(sp)) { /* This slob page is about to become partially free. Easy! */ sp->units = units; - sp->free = b; + sp->freelist = b; set_slob(b, units, (void *)((unsigned long)(b + SLOB_UNITS(PAGE_SIZE)) & PAGE_MASK)); @@ -441,15 +388,15 @@ static void slob_free(void *block, int size) */ sp->units += units; - if (b < sp->free) { - if (b + units == sp->free) { - units += slob_units(sp->free); - sp->free = slob_next(sp->free); + if (b < (slob_t *)sp->freelist) { + if (b + units == sp->freelist) { + units += slob_units(sp->freelist); + sp->freelist = slob_next(sp->freelist); } - set_slob(b, units, sp->free); - sp->free = b; + set_slob(b, units, sp->freelist); + sp->freelist = b; } else { - prev = sp->free; + prev = sp->freelist; next = slob_next(prev); while (b > next) { prev = next; @@ -476,7 +423,8 @@ static void slob_free(void *block, int size) * End of slob allocator proper. Begin kmem_cache_alloc and kmalloc frontend. */ -void *__kmalloc_node(size_t size, gfp_t gfp, int node) +static __always_inline void * +__do_kmalloc_node(size_t size, gfp_t gfp, int node, unsigned long caller) { unsigned int *m; int align = max(ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN); @@ -497,7 +445,7 @@ void *__kmalloc_node(size_t size, gfp_t gfp, int node) *m = size; ret = (void *)m + align; - trace_kmalloc_node(_RET_IP_, ret, + trace_kmalloc_node(caller, ret, size, size + align, gfp, node); } else { unsigned int order = get_order(size); @@ -505,24 +453,39 @@ void *__kmalloc_node(size_t size, gfp_t gfp, int node) if (likely(order)) gfp |= __GFP_COMP; ret = slob_new_pages(gfp, order, node); - if (ret) { - struct page *page; - page = virt_to_page(ret); - page->private = size; - } - trace_kmalloc_node(_RET_IP_, ret, + trace_kmalloc_node(caller, ret, size, PAGE_SIZE << order, gfp, node); } kmemleak_alloc(ret, size, 1, gfp); return ret; } + +void *__kmalloc_node(size_t size, gfp_t gfp, int node) +{ + return __do_kmalloc_node(size, gfp, node, _RET_IP_); +} EXPORT_SYMBOL(__kmalloc_node); +#ifdef CONFIG_TRACING +void *__kmalloc_track_caller(size_t size, gfp_t gfp, unsigned long caller) +{ + return __do_kmalloc_node(size, gfp, NUMA_NO_NODE, caller); +} + +#ifdef CONFIG_NUMA +void *__kmalloc_node_track_caller(size_t size, gfp_t gfp, + int node, unsigned long caller) +{ + return __do_kmalloc_node(size, gfp, node, caller); +} +#endif +#endif + void kfree(const void *block) { - struct slob_page *sp; + struct page *sp; trace_kfree(_RET_IP_, block); @@ -530,81 +493,46 @@ void kfree(const void *block) return; kmemleak_free(block); - sp = slob_page(block); - if (is_slob_page(sp)) { + sp = virt_to_page(block); + if (PageSlab(sp)) { int align = max(ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN); unsigned int *m = (unsigned int *)(block - align); slob_free(m, *m + align); } else - put_page(&sp->page); + put_page(sp); } EXPORT_SYMBOL(kfree); /* can't use ksize for kmem_cache_alloc memory, only kmalloc */ size_t ksize(const void *block) { - struct slob_page *sp; + struct page *sp; + int align; + unsigned int *m; BUG_ON(!block); if (unlikely(block == ZERO_SIZE_PTR)) return 0; - sp = slob_page(block); - if (is_slob_page(sp)) { - int align = max(ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN); - unsigned int *m = (unsigned int *)(block - align); - return SLOB_UNITS(*m) * SLOB_UNIT; - } else - return sp->page.private; -} -EXPORT_SYMBOL(ksize); - -struct kmem_cache { - unsigned int size, align; - unsigned long flags; - const char *name; - void (*ctor)(void *); -}; - -struct kmem_cache *kmem_cache_create(const char *name, size_t size, - size_t align, unsigned long flags, void (*ctor)(void *)) -{ - struct kmem_cache *c; - - c = slob_alloc(sizeof(struct kmem_cache), - GFP_KERNEL, ARCH_KMALLOC_MINALIGN, -1); + sp = virt_to_page(block); + if (unlikely(!PageSlab(sp))) + return PAGE_SIZE << compound_order(sp); - if (c) { - c->name = name; - c->size = size; - if (flags & SLAB_DESTROY_BY_RCU) { - /* leave room for rcu footer at the end of object */ - c->size += sizeof(struct slob_rcu); - } - c->flags = flags; - c->ctor = ctor; - /* ignore alignment unless it's forced */ - c->align = (flags & SLAB_HWCACHE_ALIGN) ? SLOB_ALIGN : 0; - if (c->align < ARCH_SLAB_MINALIGN) - c->align = ARCH_SLAB_MINALIGN; - if (c->align < align) - c->align = align; - } else if (flags & SLAB_PANIC) - panic("Cannot create slab cache %s\n", name); - - kmemleak_alloc(c, sizeof(struct kmem_cache), 1, GFP_KERNEL); - return c; + align = max(ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN); + m = (unsigned int *)(block - align); + return SLOB_UNITS(*m) * SLOB_UNIT; } -EXPORT_SYMBOL(kmem_cache_create); +EXPORT_SYMBOL(ksize); -void kmem_cache_destroy(struct kmem_cache *c) +int __kmem_cache_create(struct kmem_cache *c, unsigned long flags) { - kmemleak_free(c); - if (c->flags & SLAB_DESTROY_BY_RCU) - rcu_barrier(); - slob_free(c, sizeof(struct kmem_cache)); + if (flags & SLAB_DESTROY_BY_RCU) { + /* leave room for rcu footer at the end of object */ + c->size += sizeof(struct slob_rcu); + } + c->flags = flags; + return 0; } -EXPORT_SYMBOL(kmem_cache_destroy); void *kmem_cache_alloc_node(struct kmem_cache *c, gfp_t flags, int node) { @@ -616,12 +544,12 @@ void *kmem_cache_alloc_node(struct kmem_cache *c, gfp_t flags, int node) if (c->size < PAGE_SIZE) { b = slob_alloc(c->size, flags, c->align, node); - trace_kmem_cache_alloc_node(_RET_IP_, b, c->size, + trace_kmem_cache_alloc_node(_RET_IP_, b, c->object_size, SLOB_UNITS(c->size) * SLOB_UNIT, flags, node); } else { b = slob_new_pages(flags, get_order(c->size), node); - trace_kmem_cache_alloc_node(_RET_IP_, b, c->size, + trace_kmem_cache_alloc_node(_RET_IP_, b, c->object_size, PAGE_SIZE << get_order(c->size), flags, node); } @@ -666,11 +594,11 @@ void kmem_cache_free(struct kmem_cache *c, void *b) } EXPORT_SYMBOL(kmem_cache_free); -unsigned int kmem_cache_size(struct kmem_cache *c) +int __kmem_cache_shutdown(struct kmem_cache *c) { - return c->size; + /* No way to check for remaining objects */ + return 0; } -EXPORT_SYMBOL(kmem_cache_size); int kmem_cache_shrink(struct kmem_cache *d) { @@ -678,19 +606,20 @@ int kmem_cache_shrink(struct kmem_cache *d) } EXPORT_SYMBOL(kmem_cache_shrink); -static unsigned int slob_ready __read_mostly; - -int slab_is_available(void) -{ - return slob_ready; -} +struct kmem_cache kmem_cache_boot = { + .name = "kmem_cache", + .size = sizeof(struct kmem_cache), + .flags = SLAB_PANIC, + .align = ARCH_KMALLOC_MINALIGN, +}; void __init kmem_cache_init(void) { - slob_ready = 1; + kmem_cache = &kmem_cache_boot; + slab_state = UP; } void __init kmem_cache_init_late(void) { - /* Nothing to do */ + slab_state = FULL; } diff --git a/mm/slub.c b/mm/slub.c index 4941dc9cf72..5a4128830cb 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -16,6 +16,7 @@ #include #include #include +#include "slab.h" #include #include #include @@ -33,15 +34,17 @@ #include +#include "internal.h" + /* * Lock order: - * 1. slub_lock (Global Semaphore) + * 1. slab_mutex (Global Mutex) * 2. node->list_lock * 3. slab_lock(page) (Only on some arches and for debugging) * - * slub_lock + * slab_mutex * - * The role of the slub_lock is to protect the list of all the slabs + * The role of the slab_mutex is to protect the list of all the slabs * and to synchronize major metadata changes to slab cache structures. * * The slab_lock is only used for debugging and on arches that do not @@ -109,9 +112,6 @@ * the fast path and disables lockless freelists. */ -#define SLAB_DEBUG_FLAGS (SLAB_RED_ZONE | SLAB_POISON | SLAB_STORE_USER | \ - SLAB_TRACE | SLAB_DEBUG_FREE) - static inline int kmem_cache_debug(struct kmem_cache *s) { #ifdef CONFIG_SLUB_DEBUG @@ -176,23 +176,10 @@ static inline int kmem_cache_debug(struct kmem_cache *s) #define __OBJECT_POISON 0x80000000UL /* Poison object */ #define __CMPXCHG_DOUBLE 0x40000000UL /* Use cmpxchg_double */ -static int kmem_size = sizeof(struct kmem_cache); - #ifdef CONFIG_SMP static struct notifier_block slab_notifier; #endif -static enum { - DOWN, /* No slab functionality available */ - PARTIAL, /* Kmem_cache_node works */ - UP, /* Everything works but does not show up in sysfs */ - SYSFS /* Sysfs up */ -} slab_state = DOWN; - -/* A list of all slab caches on the system */ -static DECLARE_RWSEM(slub_lock); -static LIST_HEAD(slab_caches); - /* * Tracking user of a slab. */ @@ -218,11 +205,7 @@ static void sysfs_slab_remove(struct kmem_cache *); static inline int sysfs_slab_add(struct kmem_cache *s) { return 0; } static inline int sysfs_slab_alias(struct kmem_cache *s, const char *p) { return 0; } -static inline void sysfs_slab_remove(struct kmem_cache *s) -{ - kfree(s->name); - kfree(s); -} +static inline void sysfs_slab_remove(struct kmem_cache *s) { } #endif @@ -237,11 +220,6 @@ static inline void stat(const struct kmem_cache *s, enum stat_item si) * Core slab cache functions *******************************************************************/ -int slab_is_available(void) -{ - return slab_state >= UP; -} - static inline struct kmem_cache_node *get_node(struct kmem_cache *s, int node) { return s->node[node]; @@ -311,7 +289,7 @@ static inline size_t slab_ksize(const struct kmem_cache *s) * and whatever may come after it. */ if (s->flags & (SLAB_RED_ZONE | SLAB_POISON)) - return s->objsize; + return s->object_size; #endif /* @@ -581,6 +559,8 @@ static void slab_bug(struct kmem_cache *s, char *fmt, ...) printk(KERN_ERR "BUG %s (%s): %s\n", s->name, print_tainted(), buf); printk(KERN_ERR "----------------------------------------" "-------------------------------------\n\n"); + + add_taint(TAINT_BAD_PAGE); } static void slab_fix(struct kmem_cache *s, char *fmt, ...) @@ -609,11 +589,11 @@ static void print_trailer(struct kmem_cache *s, struct page *page, u8 *p) if (p > addr + 16) print_section("Bytes b4 ", p - 16, 16); - print_section("Object ", p, min_t(unsigned long, s->objsize, + print_section("Object ", p, min_t(unsigned long, s->object_size, PAGE_SIZE)); if (s->flags & SLAB_RED_ZONE) - print_section("Redzone ", p + s->objsize, - s->inuse - s->objsize); + print_section("Redzone ", p + s->object_size, + s->inuse - s->object_size); if (s->offset) off = s->offset + sizeof(void *); @@ -637,7 +617,7 @@ static void object_err(struct kmem_cache *s, struct page *page, print_trailer(s, page, object); } -static void slab_err(struct kmem_cache *s, struct page *page, char *fmt, ...) +static void slab_err(struct kmem_cache *s, struct page *page, const char *fmt, ...) { va_list args; char buf[100]; @@ -655,12 +635,12 @@ static void init_object(struct kmem_cache *s, void *object, u8 val) u8 *p = object; if (s->flags & __OBJECT_POISON) { - memset(p, POISON_FREE, s->objsize - 1); - p[s->objsize - 1] = POISON_END; + memset(p, POISON_FREE, s->object_size - 1); + p[s->object_size - 1] = POISON_END; } if (s->flags & SLAB_RED_ZONE) - memset(p + s->objsize, val, s->inuse - s->objsize); + memset(p + s->object_size, val, s->inuse - s->object_size); } static void restore_bytes(struct kmem_cache *s, char *message, u8 data, @@ -705,10 +685,10 @@ static int check_bytes_and_report(struct kmem_cache *s, struct page *page, * Poisoning uses 0x6b (POISON_FREE) and the last byte is * 0xa5 (POISON_END) * - * object + s->objsize + * object + s->object_size * Padding to reach word boundary. This is also used for Redzoning. * Padding is extended by another word if Redzoning is enabled and - * objsize == inuse. + * object_size == inuse. * * We fill with 0xbb (RED_INACTIVE) for inactive objects and with * 0xcc (RED_ACTIVE) for objects in use. @@ -727,7 +707,7 @@ static int check_bytes_and_report(struct kmem_cache *s, struct page *page, * object + s->size * Nothing is used beyond s->size. * - * If slabcaches are merged then the objsize and inuse boundaries are mostly + * If slabcaches are merged then the object_size and inuse boundaries are mostly * ignored. And therefore no slab options that rely on these boundaries * may be used with merged slabcaches. */ @@ -787,25 +767,25 @@ static int check_object(struct kmem_cache *s, struct page *page, void *object, u8 val) { u8 *p = object; - u8 *endobject = object + s->objsize; + u8 *endobject = object + s->object_size; if (s->flags & SLAB_RED_ZONE) { if (!check_bytes_and_report(s, page, object, "Redzone", - endobject, val, s->inuse - s->objsize)) + endobject, val, s->inuse - s->object_size)) return 0; } else { - if ((s->flags & SLAB_POISON) && s->objsize < s->inuse) { + if ((s->flags & SLAB_POISON) && s->object_size < s->inuse) { check_bytes_and_report(s, page, p, "Alignment padding", - endobject, POISON_INUSE, s->inuse - s->objsize); + endobject, POISON_INUSE, s->inuse - s->object_size); } } if (s->flags & SLAB_POISON) { if (val != SLUB_RED_ACTIVE && (s->flags & __OBJECT_POISON) && (!check_bytes_and_report(s, page, p, "Poison", p, - POISON_FREE, s->objsize - 1) || + POISON_FREE, s->object_size - 1) || !check_bytes_and_report(s, page, p, "Poison", - p + s->objsize - 1, POISON_END, 1))) + p + s->object_size - 1, POISON_END, 1))) return 0; /* * check_pad_bytes cleans up on its own. @@ -926,7 +906,7 @@ static void trace(struct kmem_cache *s, struct page *page, void *object, page->freelist); if (!alloc) - print_section("Object ", (void *)object, s->objsize); + print_section("Object ", (void *)object, s->object_size); dump_stack(); } @@ -942,14 +922,14 @@ static inline int slab_pre_alloc_hook(struct kmem_cache *s, gfp_t flags) lockdep_trace_alloc(flags); might_sleep_if(flags & __GFP_WAIT); - return should_failslab(s->objsize, flags, s->flags); + return should_failslab(s->object_size, flags, s->flags); } static inline void slab_post_alloc_hook(struct kmem_cache *s, gfp_t flags, void *object) { flags &= gfp_allowed_mask; kmemcheck_slab_alloc(s, flags, object, slab_ksize(s)); - kmemleak_alloc_recursive(object, s->objsize, 1, s->flags, flags); + kmemleak_alloc_recursive(object, s->object_size, 1, s->flags, flags); } static inline void slab_free_hook(struct kmem_cache *s, void *x) @@ -966,13 +946,13 @@ static inline void slab_free_hook(struct kmem_cache *s, void *x) unsigned long flags; local_irq_save(flags); - kmemcheck_slab_free(s, x, s->objsize); - debug_check_no_locks_freed(x, s->objsize); + kmemcheck_slab_free(s, x, s->object_size); + debug_check_no_locks_freed(x, s->object_size); local_irq_restore(flags); } #endif if (!(s->flags & SLAB_DEBUG_OBJECTS)) - debug_check_no_obj_freed(x, s->objsize); + debug_check_no_obj_freed(x, s->object_size); } /* @@ -1082,13 +1062,13 @@ static noinline int alloc_debug_processing(struct kmem_cache *s, struct page *pa return 0; } -static noinline int free_debug_processing(struct kmem_cache *s, - struct page *page, void *object, unsigned long addr) +static noinline struct kmem_cache_node *free_debug_processing( + struct kmem_cache *s, struct page *page, void *object, + unsigned long addr, unsigned long *flags) { - unsigned long flags; - int rc = 0; + struct kmem_cache_node *n = get_node(s, page_to_nid(page)); - local_irq_save(flags); + spin_lock_irqsave(&n->list_lock, *flags); slab_lock(page); if (!check_slab(s, page)) @@ -1107,11 +1087,11 @@ static noinline int free_debug_processing(struct kmem_cache *s, if (!check_object(s, page, object, SLUB_RED_ACTIVE)) goto out; - if (unlikely(s != page->slab)) { + if (unlikely(s != page->slab_cache)) { if (!PageSlab(page)) { slab_err(s, page, "Attempt to free object(0x%p) " "outside of slab", object); - } else if (!page->slab) { + } else if (!page->slab_cache) { printk(KERN_ERR "SLUB : no slab for object 0x%p.\n", object); @@ -1126,15 +1106,19 @@ static noinline int free_debug_processing(struct kmem_cache *s, set_track(s, object, TRACK_FREE, addr); trace(s, page, object, 0); init_object(s, object, SLUB_RED_INACTIVE); - rc = 1; out: slab_unlock(page); - local_irq_restore(flags); - return rc; + /* + * Keep node_lock to preserve integrity + * until the object is actually freed + */ + return n; fail: + slab_unlock(page); + spin_unlock_irqrestore(&n->list_lock, *flags); slab_fix(s, "Object at 0x%p not freed", object); - goto out; + return NULL; } static int __init setup_slub_debug(char *str) @@ -1207,7 +1191,7 @@ static int __init setup_slub_debug(char *str) __setup("slub_debug", setup_slub_debug); -static unsigned long kmem_cache_flags(unsigned long objsize, +static unsigned long kmem_cache_flags(unsigned long object_size, unsigned long flags, const char *name, void (*ctor)(void *)) { @@ -1227,8 +1211,9 @@ static inline void setup_object_debug(struct kmem_cache *s, static inline int alloc_debug_processing(struct kmem_cache *s, struct page *page, void *object, unsigned long addr) { return 0; } -static inline int free_debug_processing(struct kmem_cache *s, - struct page *page, void *object, unsigned long addr) { return 0; } +static inline struct kmem_cache_node *free_debug_processing( + struct kmem_cache *s, struct page *page, void *object, + unsigned long addr, unsigned long *flags) { return NULL; } static inline int slab_pad_check(struct kmem_cache *s, struct page *page) { return 1; } @@ -1237,7 +1222,7 @@ static inline int check_object(struct kmem_cache *s, struct page *page, static inline void add_full(struct kmem_cache *s, struct kmem_cache_node *n, struct page *page) {} static inline void remove_full(struct kmem_cache *s, struct page *page) {} -static inline unsigned long kmem_cache_flags(unsigned long objsize, +static inline unsigned long kmem_cache_flags(unsigned long object_size, unsigned long flags, const char *name, void (*ctor)(void *)) { @@ -1314,13 +1299,7 @@ static struct page *allocate_slab(struct kmem_cache *s, gfp_t flags, int node) stat(s, ORDER_FALLBACK); } - if (flags & __GFP_WAIT) - local_irq_disable(); - - if (!page) - return NULL; - - if (kmemcheck_enabled + if (kmemcheck_enabled && page && !(s->flags & (SLAB_NOTRACK | DEBUG_DEFAULT_FLAGS))) { int pages = 1 << oo_order(oo); @@ -1336,6 +1315,11 @@ static struct page *allocate_slab(struct kmem_cache *s, gfp_t flags, int node) kmemcheck_mark_unallocated_pages(page, pages); } + if (flags & __GFP_WAIT) + local_irq_disable(); + if (!page) + return NULL; + page->objects = oo_objects(oo); mod_zone_page_state(page_zone(page), (s->flags & SLAB_RECLAIM_ACCOUNT) ? @@ -1368,8 +1352,10 @@ static struct page *new_slab(struct kmem_cache *s, gfp_t flags, int node) goto out; inc_slabs_node(s, page_to_nid(page), page->objects); - page->slab = s; - page->flags |= 1 << PG_slab; + page->slab_cache = s; + __SetPageSlab(page); + if (page->pfmemalloc) + SetPageSlabPfmemalloc(page); start = page_address(page); @@ -1413,6 +1399,7 @@ static void __free_slab(struct kmem_cache *s, struct page *page) NR_SLAB_RECLAIMABLE : NR_SLAB_UNRECLAIMABLE, -pages); + __ClearPageSlabPfmemalloc(page); __ClearPageSlab(page); reset_page_mapcount(page); if (current->reclaim_state) @@ -1432,7 +1419,7 @@ static void rcu_free_slab(struct rcu_head *h) else page = container_of((struct list_head *)h, struct page, lru); - __free_slab(page->slab, page); + __free_slab(page->slab_cache, page); } static void free_slab(struct kmem_cache *s, struct page *page) @@ -1490,12 +1477,12 @@ static inline void remove_partial(struct kmem_cache_node *n, } /* - * Lock slab, remove from the partial list and put the object into the - * per cpu freelist. + * Remove slab from the partial list, freeze it and + * return the pointer to the freelist. * * Returns a list of objects or NULL if it fails. * - * Must hold list_lock. + * Must hold list_lock since we modify the partial list. */ static inline void *acquire_slab(struct kmem_cache *s, struct kmem_cache_node *n, struct page *page, @@ -1510,36 +1497,38 @@ static inline void *acquire_slab(struct kmem_cache *s, * The old freelist is the list of objects for the * per cpu allocation list. */ - do { - freelist = page->freelist; - counters = page->counters; - new.counters = counters; - if (mode) { - new.inuse = page->objects; - new.freelist = NULL; - } else { - new.freelist = freelist; - } - - VM_BUG_ON(new.frozen); - new.frozen = 1; + freelist = page->freelist; + counters = page->counters; + new.counters = counters; + if (mode) { + new.inuse = page->objects; + new.freelist = NULL; + } else { + new.freelist = freelist; + } + VM_BUG_ON(new.frozen); + new.frozen = 1; - } while (!__cmpxchg_double_slab(s, page, + if (!__cmpxchg_double_slab(s, page, freelist, counters, new.freelist, new.counters, - "lock and freeze")); + "acquire_slab")) + + return NULL; remove_partial(n, page); + WARN_ON(!freelist); return freelist; } static int put_cpu_partial(struct kmem_cache *s, struct page *page, int drain); +static inline bool pfmemalloc_match(struct page *page, gfp_t gfpflags); /* * Try to allocate a partial slab from a specific node. */ -static void *get_partial_node(struct kmem_cache *s, - struct kmem_cache_node *n, struct kmem_cache_cpu *c) +static void *get_partial_node(struct kmem_cache *s, struct kmem_cache_node *n, + struct kmem_cache_cpu *c, gfp_t flags) { struct page *page, *page2; void *object = NULL; @@ -1555,15 +1544,18 @@ static void *get_partial_node(struct kmem_cache *s, spin_lock(&n->list_lock); list_for_each_entry_safe(page, page2, &n->partial, lru) { - void *t = acquire_slab(s, n, page, object == NULL); + void *t; int available; + if (!pfmemalloc_match(page, flags)) + continue; + + t = acquire_slab(s, n, page, object == NULL); if (!t) break; if (!object) { c->page = page; - c->node = page_to_nid(page); stat(s, ALLOC_FROM_PARTIAL); object = t; available = page->objects - page->inuse; @@ -1617,7 +1609,7 @@ static struct page *get_any_partial(struct kmem_cache *s, gfp_t flags, do { cpuset_mems_cookie = get_mems_allowed(); - zonelist = node_zonelist(slab_node(current->mempolicy), flags); + zonelist = node_zonelist(slab_node(), flags); for_each_zone_zonelist(zone, z, zonelist, high_zoneidx) { struct kmem_cache_node *n; @@ -1625,7 +1617,7 @@ static struct page *get_any_partial(struct kmem_cache *s, gfp_t flags, if (n && cpuset_zone_allowed_hardwall(zone, flags) && n->nr_partial > s->min_partial) { - object = get_partial_node(s, n, c); + object = get_partial_node(s, n, c, flags); if (object) { /* * Return the object even if @@ -1654,7 +1646,7 @@ static void *get_partial(struct kmem_cache *s, gfp_t flags, int node, void *object; int searchnode = (node == NUMA_NO_NODE) ? numa_node_id() : node; - object = get_partial_node(s, get_node(s, searchnode), c); + object = get_partial_node(s, get_node(s, searchnode), c, flags); if (object || node != NUMA_NO_NODE) return object; @@ -1720,7 +1712,7 @@ static inline void note_cmpxchg_failure(const char *n, stat(s, CMPXCHG_DOUBLE_CPU_FAIL); } -void init_kmem_cache_cpus(struct kmem_cache *s) +static void init_kmem_cache_cpus(struct kmem_cache *s) { int cpu; @@ -1731,14 +1723,12 @@ void init_kmem_cache_cpus(struct kmem_cache *s) /* * Remove the cpu slab */ -static void deactivate_slab(struct kmem_cache *s, struct kmem_cache_cpu *c) +static void deactivate_slab(struct kmem_cache *s, struct page *page, void *freelist) { enum slab_modes { M_NONE, M_PARTIAL, M_FULL, M_FREE }; - struct page *page = c->page; struct kmem_cache_node *n = get_node(s, page_to_nid(page)); int lock = 0; enum slab_modes l = M_NONE, m = M_NONE; - void *freelist; void *nextfree; int tail = DEACTIVATE_TO_HEAD; struct page new; @@ -1749,11 +1739,6 @@ static void deactivate_slab(struct kmem_cache *s, struct kmem_cache_cpu *c) tail = DEACTIVATE_TO_TAIL; } - c->tid = next_tid(c->tid); - c->page = NULL; - freelist = c->freelist; - c->freelist = NULL; - /* * Stage one: Free all available per cpu objects back * to the page freelist while it is still frozen. Leave the @@ -1879,21 +1864,33 @@ static void deactivate_slab(struct kmem_cache *s, struct kmem_cache_cpu *c) } } -/* Unfreeze all the cpu partial slabs */ -static void unfreeze_partials(struct kmem_cache *s) +/* + * Unfreeze all the cpu partial slabs. + * + * This function must be called with interrupts disabled + * for the cpu using c (or some other guarantee must be there + * to guarantee no concurrent accesses). + */ +static void unfreeze_partials(struct kmem_cache *s, + struct kmem_cache_cpu *c) { - struct kmem_cache_node *n = NULL; - struct kmem_cache_cpu *c = this_cpu_ptr(s->cpu_slab); + struct kmem_cache_node *n = NULL, *n2 = NULL; struct page *page, *discard_page = NULL; while ((page = c->partial)) { - enum slab_modes { M_PARTIAL, M_FREE }; - enum slab_modes l, m; struct page new; struct page old; c->partial = page->next; - l = M_FREE; + + n2 = get_node(s, page_to_nid(page)); + if (n != n2) { + if (n) + spin_unlock(&n->list_lock); + + n = n2; + spin_lock(&n->list_lock); + } do { @@ -1906,43 +1903,17 @@ static void unfreeze_partials(struct kmem_cache *s) new.frozen = 0; - if (!new.inuse && (!n || n->nr_partial > s->min_partial)) - m = M_FREE; - else { - struct kmem_cache_node *n2 = get_node(s, - page_to_nid(page)); - - m = M_PARTIAL; - if (n != n2) { - if (n) - spin_unlock(&n->list_lock); - - n = n2; - spin_lock(&n->list_lock); - } - } - - if (l != m) { - if (l == M_PARTIAL) { - remove_partial(n, page); - stat(s, FREE_REMOVE_PARTIAL); - } else { - add_partial(n, page, - DEACTIVATE_TO_TAIL); - stat(s, FREE_ADD_PARTIAL); - } - - l = m; - } - - } while (!cmpxchg_double_slab(s, page, + } while (!__cmpxchg_double_slab(s, page, old.freelist, old.counters, new.freelist, new.counters, "unfreezing slab")); - if (m == M_FREE) { + if (unlikely(!new.inuse && n->nr_partial > s->min_partial)) { page->next = discard_page; discard_page = page; + } else { + add_partial(n, page, DEACTIVATE_TO_TAIL); + stat(s, FREE_ADD_PARTIAL); } } @@ -1968,7 +1939,7 @@ static void unfreeze_partials(struct kmem_cache *s) * If we did not find a slot then simply move all the partials to the * per node partial list. */ -int put_cpu_partial(struct kmem_cache *s, struct page *page, int drain) +static int put_cpu_partial(struct kmem_cache *s, struct page *page, int drain) { struct page *oldpage; int pages; @@ -1989,8 +1960,9 @@ int put_cpu_partial(struct kmem_cache *s, struct page *page, int drain) * set to the per node partial list. */ local_irq_save(flags); - unfreeze_partials(s); + unfreeze_partials(s, this_cpu_ptr(s->cpu_slab)); local_irq_restore(flags); + oldpage = NULL; pobjects = 0; pages = 0; stat(s, CPU_PARTIAL_DRAIN); @@ -2011,7 +1983,11 @@ int put_cpu_partial(struct kmem_cache *s, struct page *page, int drain) static inline void flush_slab(struct kmem_cache *s, struct kmem_cache_cpu *c) { stat(s, CPUSLAB_FLUSH); - deactivate_slab(s, c); + deactivate_slab(s, c->page, c->freelist); + + c->tid = next_tid(c->tid); + c->page = NULL; + c->freelist = NULL; } /* @@ -2027,7 +2003,7 @@ static inline void __flush_cpu_slab(struct kmem_cache *s, int cpu) if (c->page) flush_slab(s, c); - unfreeze_partials(s); + unfreeze_partials(s, c); } } @@ -2055,10 +2031,10 @@ static void flush_all(struct kmem_cache *s) * Check if the objects in a per cpu structure fit numa * locality expectations. */ -static inline int node_match(struct kmem_cache_cpu *c, int node) +static inline int node_match(struct page *page, int node) { #ifdef CONFIG_NUMA - if (node != NUMA_NO_NODE && c->node != node) + if (node != NUMA_NO_NODE && page_to_nid(page) != node) return 0; #endif return 1; @@ -2101,10 +2077,10 @@ slab_out_of_memory(struct kmem_cache *s, gfp_t gfpflags, int nid) "SLUB: Unable to allocate memory on node %d (gfp=0x%x)\n", nid, gfpflags); printk(KERN_WARNING " cache: %s, object size: %d, buffer size: %d, " - "default order: %d, min order: %d\n", s->name, s->objsize, + "default order: %d, min order: %d\n", s->name, s->object_size, s->size, oo_order(s->oo), oo_order(s->min)); - if (oo_order(s->min) > get_order(s->objsize)) + if (oo_order(s->min) > get_order(s->object_size)) printk(KERN_WARNING " %s debugging increased min order, use " "slub_debug=O to disable.\n", s->name); @@ -2130,10 +2106,16 @@ slab_out_of_memory(struct kmem_cache *s, gfp_t gfpflags, int nid) static inline void *new_slab_objects(struct kmem_cache *s, gfp_t flags, int node, struct kmem_cache_cpu **pc) { - void *object; - struct kmem_cache_cpu *c; - struct page *page = new_slab(s, flags, node); + void *freelist; + struct kmem_cache_cpu *c = *pc; + struct page *page; + + freelist = get_partial(s, flags, node, c); + if (freelist) + return freelist; + + page = new_slab(s, flags, node); if (page) { c = __this_cpu_ptr(s->cpu_slab); if (c->page) @@ -2143,17 +2125,24 @@ static inline void *new_slab_objects(struct kmem_cache *s, gfp_t flags, * No other reference to the page yet so we can * muck around with it freely without cmpxchg */ - object = page->freelist; + freelist = page->freelist; page->freelist = NULL; stat(s, ALLOC_SLAB); - c->node = page_to_nid(page); c->page = page; *pc = c; } else - object = NULL; + freelist = NULL; - return object; + return freelist; +} + +static inline bool pfmemalloc_match(struct page *page, gfp_t gfpflags) +{ + if (unlikely(PageSlabPfmemalloc(page))) + return gfp_pfmemalloc_allowed(gfpflags); + + return true; } /* @@ -2163,6 +2152,8 @@ static inline void *new_slab_objects(struct kmem_cache *s, gfp_t flags, * The page is still frozen if the return value is not NULL. * * If this function returns NULL then the page has been unfrozen. + * + * This function must be called with interrupt disabled. */ static inline void *get_freelist(struct kmem_cache *s, struct page *page) { @@ -2173,13 +2164,14 @@ static inline void *get_freelist(struct kmem_cache *s, struct page *page) do { freelist = page->freelist; counters = page->counters; + new.counters = counters; VM_BUG_ON(!new.frozen); new.inuse = page->objects; new.frozen = freelist != NULL; - } while (!cmpxchg_double_slab(s, page, + } while (!__cmpxchg_double_slab(s, page, freelist, counters, NULL, new.counters, "get_freelist")); @@ -2206,7 +2198,8 @@ static inline void *get_freelist(struct kmem_cache *s, struct page *page) static void *__slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node, unsigned long addr, struct kmem_cache_cpu *c) { - void **object; + void *freelist; + struct page *page; unsigned long flags; local_irq_save(flags); @@ -2219,25 +2212,41 @@ static void *__slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node, c = this_cpu_ptr(s->cpu_slab); #endif - if (!c->page) + page = c->page; + if (!page) goto new_slab; redo: - if (unlikely(!node_match(c, node))) { + + if (unlikely(!node_match(page, node))) { stat(s, ALLOC_NODE_MISMATCH); - deactivate_slab(s, c); + deactivate_slab(s, page, c->freelist); + c->page = NULL; + c->freelist = NULL; + goto new_slab; + } + + /* + * By rights, we should be searching for a slab page that was + * PFMEMALLOC but right now, we are losing the pfmemalloc + * information when the page leaves the per-cpu allocator + */ + if (unlikely(!pfmemalloc_match(page, gfpflags))) { + deactivate_slab(s, page, c->freelist); + c->page = NULL; + c->freelist = NULL; goto new_slab; } /* must check again c->freelist in case of cpu migration or IRQ */ - object = c->freelist; - if (object) + freelist = c->freelist; + if (freelist) goto load_freelist; stat(s, ALLOC_SLOWPATH); - object = get_freelist(s, c->page); + freelist = get_freelist(s, page); - if (!object) { + if (!freelist) { c->page = NULL; stat(s, DEACTIVATE_BYPASS); goto new_slab; @@ -2246,50 +2255,50 @@ static void *__slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node, stat(s, ALLOC_REFILL); load_freelist: - c->freelist = get_freepointer(s, object); + /* + * freelist is pointing to the list of objects to be used. + * page is pointing to the page from which the objects are obtained. + * That page must be frozen for per cpu allocations to work. + */ + VM_BUG_ON(!c->page->frozen); + c->freelist = get_freepointer(s, freelist); c->tid = next_tid(c->tid); local_irq_restore(flags); - return object; + return freelist; new_slab: if (c->partial) { - c->page = c->partial; - c->partial = c->page->next; - c->node = page_to_nid(c->page); + page = c->page = c->partial; + c->partial = page->next; stat(s, CPU_PARTIAL_ALLOC); c->freelist = NULL; goto redo; } - /* Then do expensive stuff like retrieving pages from the partial lists */ - object = get_partial(s, gfpflags, node, c); + freelist = new_slab_objects(s, gfpflags, node, &c); - if (unlikely(!object)) { + if (unlikely(!freelist)) { + if (!(gfpflags & __GFP_NOWARN) && printk_ratelimit()) + slab_out_of_memory(s, gfpflags, node); - object = new_slab_objects(s, gfpflags, node, &c); - - if (unlikely(!object)) { - if (!(gfpflags & __GFP_NOWARN) && printk_ratelimit()) - slab_out_of_memory(s, gfpflags, node); - - local_irq_restore(flags); - return NULL; - } + local_irq_restore(flags); + return NULL; } - if (likely(!kmem_cache_debug(s))) + page = c->page; + if (likely(!kmem_cache_debug(s) && pfmemalloc_match(page, gfpflags))) goto load_freelist; /* Only entered in the debug case */ - if (!alloc_debug_processing(s, c->page, object, addr)) + if (kmem_cache_debug(s) && !alloc_debug_processing(s, page, freelist, addr)) goto new_slab; /* Slab failed checks. Next slab needed */ - c->freelist = get_freepointer(s, object); - deactivate_slab(s, c); - c->node = NUMA_NO_NODE; + deactivate_slab(s, page, get_freepointer(s, freelist)); + c->page = NULL; + c->freelist = NULL; local_irq_restore(flags); - return object; + return freelist; } /* @@ -2302,11 +2311,12 @@ static void *__slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node, * * Otherwise we can simply pick the next object from the lockless free list. */ -static __always_inline void *slab_alloc(struct kmem_cache *s, +static __always_inline void *slab_alloc_node(struct kmem_cache *s, gfp_t gfpflags, int node, unsigned long addr) { void **object; struct kmem_cache_cpu *c; + struct page *page; unsigned long tid; if (slab_pre_alloc_hook(s, gfpflags)) @@ -2332,8 +2342,8 @@ static __always_inline void *slab_alloc(struct kmem_cache *s, barrier(); object = c->freelist; - if (unlikely(!object || !node_match(c, node))) - + page = c->page; + if (unlikely(!object || !node_match(page, node))) object = __slab_alloc(s, gfpflags, node, addr, c); else { @@ -2364,18 +2374,24 @@ static __always_inline void *slab_alloc(struct kmem_cache *s, } if (unlikely(gfpflags & __GFP_ZERO) && object) - memset(object, 0, s->objsize); + memset(object, 0, s->object_size); slab_post_alloc_hook(s, gfpflags, object); return object; } +static __always_inline void *slab_alloc(struct kmem_cache *s, + gfp_t gfpflags, unsigned long addr) +{ + return slab_alloc_node(s, gfpflags, NUMA_NO_NODE, addr); +} + void *kmem_cache_alloc(struct kmem_cache *s, gfp_t gfpflags) { - void *ret = slab_alloc(s, gfpflags, NUMA_NO_NODE, _RET_IP_); + void *ret = slab_alloc(s, gfpflags, _RET_IP_); - trace_kmem_cache_alloc(_RET_IP_, ret, s->objsize, s->size, gfpflags); + trace_kmem_cache_alloc(_RET_IP_, ret, s->object_size, s->size, gfpflags); return ret; } @@ -2384,7 +2400,7 @@ EXPORT_SYMBOL(kmem_cache_alloc); #ifdef CONFIG_TRACING void *kmem_cache_alloc_trace(struct kmem_cache *s, gfp_t gfpflags, size_t size) { - void *ret = slab_alloc(s, gfpflags, NUMA_NO_NODE, _RET_IP_); + void *ret = slab_alloc(s, gfpflags, _RET_IP_); trace_kmalloc(_RET_IP_, ret, size, s->size, gfpflags); return ret; } @@ -2402,10 +2418,10 @@ EXPORT_SYMBOL(kmalloc_order_trace); #ifdef CONFIG_NUMA void *kmem_cache_alloc_node(struct kmem_cache *s, gfp_t gfpflags, int node) { - void *ret = slab_alloc(s, gfpflags, node, _RET_IP_); + void *ret = slab_alloc_node(s, gfpflags, node, _RET_IP_); trace_kmem_cache_alloc_node(_RET_IP_, ret, - s->objsize, s->size, gfpflags, node); + s->object_size, s->size, gfpflags, node); return ret; } @@ -2416,7 +2432,7 @@ void *kmem_cache_alloc_node_trace(struct kmem_cache *s, gfp_t gfpflags, int node, size_t size) { - void *ret = slab_alloc(s, gfpflags, node, _RET_IP_); + void *ret = slab_alloc_node(s, gfpflags, node, _RET_IP_); trace_kmalloc_node(_RET_IP_, ret, size, s->size, gfpflags, node); @@ -2440,7 +2456,6 @@ static void __slab_free(struct kmem_cache *s, struct page *page, void *prior; void **object = (void *)x; int was_frozen; - int inuse; struct page new; unsigned long counters; struct kmem_cache_node *n = NULL; @@ -2448,17 +2463,22 @@ static void __slab_free(struct kmem_cache *s, struct page *page, stat(s, FREE_SLOWPATH); - if (kmem_cache_debug(s) && !free_debug_processing(s, page, x, addr)) + if (kmem_cache_debug(s) && + !(n = free_debug_processing(s, page, x, addr, &flags))) return; do { + if (unlikely(n)) { + spin_unlock_irqrestore(&n->list_lock, flags); + n = NULL; + } prior = page->freelist; counters = page->counters; set_freepointer(s, object, prior); new.counters = counters; was_frozen = new.frozen; new.inuse--; - if ((!new.inuse || !prior) && !was_frozen && !n) { + if ((!new.inuse || !prior) && !was_frozen) { if (!kmem_cache_debug(s) && !prior) @@ -2483,7 +2503,6 @@ static void __slab_free(struct kmem_cache *s, struct page *page, } } - inuse = new.inuse; } while (!cmpxchg_double_slab(s, page, prior, counters, @@ -2509,25 +2528,17 @@ static void __slab_free(struct kmem_cache *s, struct page *page, return; } + if (unlikely(!new.inuse && n->nr_partial > s->min_partial)) + goto slab_empty; + /* - * was_frozen may have been set after we acquired the list_lock in - * an earlier loop. So we need to check it here again. + * Objects left in the slab. If it was not on the partial list before + * then add it. */ - if (was_frozen) - stat(s, FREE_FROZEN); - else { - if (unlikely(!inuse && n->nr_partial > s->min_partial)) - goto slab_empty; - - /* - * Objects left in the slab. If it was not on the partial list before - * then add it. - */ - if (unlikely(!prior)) { - remove_full(s, page); - add_partial(n, page, DEACTIVATE_TO_TAIL); - stat(s, FREE_ADD_PARTIAL); - } + if (kmem_cache_debug(s) && unlikely(!prior)) { + remove_full(s, page); + add_partial(n, page, DEACTIVATE_TO_TAIL); + stat(s, FREE_ADD_PARTIAL); } spin_unlock_irqrestore(&n->list_lock, flags); return; @@ -2599,12 +2610,10 @@ static __always_inline void slab_free(struct kmem_cache *s, void kmem_cache_free(struct kmem_cache *s, void *x) { - struct page *page; - - page = virt_to_head_page(x); - - slab_free(s, page, x, _RET_IP_); - + s = cache_from_obj(s, x); + if (!s) + return; + slab_free(s, virt_to_head_page(x), x, _RET_IP_); trace_kmem_cache_free(_RET_IP_, x); } EXPORT_SYMBOL(kmem_cache_free); @@ -2742,32 +2751,6 @@ static inline int calculate_order(int size, int reserved) return -ENOSYS; } -/* - * Figure out what the alignment of the objects will be. - */ -static unsigned long calculate_alignment(unsigned long flags, - unsigned long align, unsigned long size) -{ - /* - * If the user wants hardware cache aligned objects then follow that - * suggestion if the object is sufficiently large. - * - * The hardware cache alignment cannot override the specified - * alignment though. If that is greater then use it. - */ - if (flags & SLAB_HWCACHE_ALIGN) { - unsigned long ralign = cache_line_size(); - while (size <= ralign / 2) - ralign /= 2; - align = max(align, ralign); - } - - if (align < ARCH_SLAB_MINALIGN) - align = ARCH_SLAB_MINALIGN; - - return ALIGN(align, sizeof(void *)); -} - static void init_kmem_cache_node(struct kmem_cache_node *n, struct kmem_cache *s) { @@ -2900,8 +2883,7 @@ static void set_min_partial(struct kmem_cache *s, unsigned long min) static int calculate_sizes(struct kmem_cache *s, int forced_order) { unsigned long flags = s->flags; - unsigned long size = s->objsize; - unsigned long align = s->align; + unsigned long size = s->object_size; int order; /* @@ -2929,7 +2911,7 @@ static int calculate_sizes(struct kmem_cache *s, int forced_order) * end of the object and the free pointer. If not then add an * additional word to have some bytes to store Redzone information. */ - if ((flags & SLAB_RED_ZONE) && size == s->objsize) + if ((flags & SLAB_RED_ZONE) && size == s->object_size) size += sizeof(void *); #endif @@ -2972,20 +2954,12 @@ static int calculate_sizes(struct kmem_cache *s, int forced_order) size += sizeof(void *); #endif - /* - * Determine the alignment based on various parameters that the - * user specified and the dynamic determination of cache line size - * on bootup. - */ - align = calculate_alignment(flags, align, s->objsize); - s->align = align; - /* * SLUB stores one object immediately after another beginning from * offset 0. In order to align the objects we have to simply size * each object to conform to the alignment. */ - size = ALIGN(size, align); + size = ALIGN(size, s->align); s->size = size; if (forced_order >= 0) order = forced_order; @@ -3014,20 +2988,11 @@ static int calculate_sizes(struct kmem_cache *s, int forced_order) s->max = s->oo; return !!oo_objects(s->oo); - } -static int kmem_cache_open(struct kmem_cache *s, - const char *name, size_t size, - size_t align, unsigned long flags, - void (*ctor)(void *)) +static int kmem_cache_open(struct kmem_cache *s, unsigned long flags) { - memset(s, 0, kmem_size); - s->name = name; - s->ctor = ctor; - s->objsize = size; - s->align = align; - s->flags = kmem_cache_flags(size, flags, name, ctor); + s->flags = kmem_cache_flags(s->size, flags, s->name, s->ctor); s->reserved = 0; if (need_reserve_slab_rcu && (s->flags & SLAB_DESTROY_BY_RCU)) @@ -3040,7 +3005,7 @@ static int kmem_cache_open(struct kmem_cache *s, * Disable debugging flags that store metadata if the min slab * order increased. */ - if (get_order(s->size) > get_order(s->objsize)) { + if (get_order(s->size) > get_order(s->object_size)) { s->flags &= ~DEBUG_METADATA_FLAGS; s->offset = 0; if (!calculate_sizes(s, -1)) @@ -3089,7 +3054,6 @@ static int kmem_cache_open(struct kmem_cache *s, else s->cpu_partial = 30; - s->refcount = 1; #ifdef CONFIG_NUMA s->remote_node_defrag_ratio = 1000; #endif @@ -3097,26 +3061,17 @@ static int kmem_cache_open(struct kmem_cache *s, goto error; if (alloc_kmem_cache_cpus(s)) - return 1; + return 0; free_kmem_cache_nodes(s); error: if (flags & SLAB_PANIC) panic("Cannot create slab %s size=%lu realsize=%u " "order=%u offset=%u flags=%lx\n", - s->name, (unsigned long)size, s->size, oo_order(s->oo), + s->name, (unsigned long)s->size, s->size, oo_order(s->oo), s->offset, flags); - return 0; -} - -/* - * Determine the size of a slab object - */ -unsigned int kmem_cache_size(struct kmem_cache *s) -{ - return s->objsize; + return -EINVAL; } -EXPORT_SYMBOL(kmem_cache_size); static void list_slab_objects(struct kmem_cache *s, struct page *page, const char *text) @@ -3128,7 +3083,7 @@ static void list_slab_objects(struct kmem_cache *s, struct page *page, sizeof(long), GFP_ATOMIC); if (!map) return; - slab_err(s, page, "%s", text); + slab_err(s, page, text, s->name); slab_lock(page); get_map(s, page, map); @@ -3160,7 +3115,7 @@ static void free_partial(struct kmem_cache *s, struct kmem_cache_node *n) discard_slab(s, page); } else { list_slab_objects(s, page, - "Objects remaining on kmem_cache_close()"); + "Objects remaining in %s on kmem_cache_close()"); } } } @@ -3173,7 +3128,6 @@ static inline int kmem_cache_close(struct kmem_cache *s) int node; flush_all(s); - free_percpu(s->cpu_slab); /* Attempt to free all objects */ for_each_node_state(node, N_NORMAL_MEMORY) { struct kmem_cache_node *n = get_node(s, node); @@ -3182,33 +3136,20 @@ static inline int kmem_cache_close(struct kmem_cache *s) if (n->nr_partial || slabs_node(s, node)) return 1; } + free_percpu(s->cpu_slab); free_kmem_cache_nodes(s); return 0; } -/* - * Close a cache and release the kmem_cache structure - * (must be used for caches created using kmem_cache_create) - */ -void kmem_cache_destroy(struct kmem_cache *s) -{ - down_write(&slub_lock); - s->refcount--; - if (!s->refcount) { - list_del(&s->list); - up_write(&slub_lock); - if (kmem_cache_close(s)) { - printk(KERN_ERR "SLUB %s: %s called for cache that " - "still has objects.\n", s->name, __func__); - dump_stack(); - } - if (s->flags & SLAB_DESTROY_BY_RCU) - rcu_barrier(); +int __kmem_cache_shutdown(struct kmem_cache *s) +{ + int rc = kmem_cache_close(s); + + if (!rc) sysfs_slab_remove(s); - } else - up_write(&slub_lock); + + return rc; } -EXPORT_SYMBOL(kmem_cache_destroy); /******************************************************************** * Kmalloc subsystem @@ -3217,8 +3158,6 @@ EXPORT_SYMBOL(kmem_cache_destroy); struct kmem_cache *kmalloc_caches[SLUB_PAGE_SHIFT]; EXPORT_SYMBOL(kmalloc_caches); -static struct kmem_cache *kmem_cache; - #ifdef CONFIG_ZONE_DMA static struct kmem_cache *kmalloc_dma_caches[SLUB_PAGE_SHIFT]; #endif @@ -3259,29 +3198,6 @@ static int __init setup_slub_nomerge(char *str) __setup("slub_nomerge", setup_slub_nomerge); -static struct kmem_cache *__init create_kmalloc_cache(const char *name, - int size, unsigned int flags) -{ - struct kmem_cache *s; - - s = kmem_cache_alloc(kmem_cache, GFP_NOWAIT); - - /* - * This function is called with IRQs disabled during early-boot on - * single CPU so there's no need to take slub_lock here. - */ - if (!kmem_cache_open(s, name, size, ARCH_KMALLOC_MINALIGN, - flags, NULL)) - goto panic; - - list_add(&s->list, &slab_caches); - return s; - -panic: - panic("Creation of kmalloc slab %s size=%d failed.\n", name, size); - return NULL; -} - /* * Conversion table for small slabs sizes / 8 to the index in the * kmalloc array. This is necessary for slabs < 192 since we have non power @@ -3353,7 +3269,7 @@ void *__kmalloc(size_t size, gfp_t flags) if (unlikely(ZERO_OR_NULL_PTR(s))) return s; - ret = slab_alloc(s, flags, NUMA_NO_NODE, _RET_IP_); + ret = slab_alloc(s, flags, _RET_IP_); trace_kmalloc(_RET_IP_, ret, size, s->size, flags); @@ -3396,7 +3312,7 @@ void *__kmalloc_node(size_t size, gfp_t flags, int node) if (unlikely(ZERO_OR_NULL_PTR(s))) return s; - ret = slab_alloc(s, flags, node, _RET_IP_); + ret = slab_alloc_node(s, flags, node, _RET_IP_); trace_kmalloc_node(_RET_IP_, ret, size, s->size, flags, node); @@ -3419,7 +3335,7 @@ size_t ksize(const void *object) return PAGE_SIZE << compound_order(page); } - return slab_ksize(page->slab); + return slab_ksize(page->slab_cache); } EXPORT_SYMBOL(ksize); @@ -3444,8 +3360,8 @@ bool verify_mem_not_deleted(const void *x) } slab_lock(page); - if (on_freelist(page->slab, page, object)) { - object_err(page->slab, page, object, "Object is on free-list"); + if (on_freelist(page->slab_cache, page, object)) { + object_err(page->slab_cache, page, object, "Object is on free-list"); rv = false; } else { rv = true; @@ -3473,10 +3389,10 @@ void kfree(const void *x) if (unlikely(!PageSlab(page))) { BUG_ON(!PageCompound(page)); kmemleak_free(x); - put_page(page); + __free_pages(page, compound_order(page)); return; } - slab_free(page->slab, page, object, _RET_IP_); + slab_free(page->slab_cache, page, object, _RET_IP_); } EXPORT_SYMBOL(kfree); @@ -3553,10 +3469,10 @@ static int slab_mem_going_offline_callback(void *arg) { struct kmem_cache *s; - down_read(&slub_lock); + mutex_lock(&slab_mutex); list_for_each_entry(s, &slab_caches, list) kmem_cache_shrink(s); - up_read(&slub_lock); + mutex_unlock(&slab_mutex); return 0; } @@ -3568,7 +3484,7 @@ static void slab_mem_offline_callback(void *arg) struct memory_notify *marg = arg; int offline_node; - offline_node = marg->status_change_nid; + offline_node = marg->status_change_nid_normal; /* * If the node still has available memory. we need kmem_cache_node @@ -3577,7 +3493,7 @@ static void slab_mem_offline_callback(void *arg) if (offline_node < 0) return; - down_read(&slub_lock); + mutex_lock(&slab_mutex); list_for_each_entry(s, &slab_caches, list) { n = get_node(s, offline_node); if (n) { @@ -3593,7 +3509,7 @@ static void slab_mem_offline_callback(void *arg) kmem_cache_free(kmem_cache_node, n); } } - up_read(&slub_lock); + mutex_unlock(&slab_mutex); } static int slab_mem_going_online_callback(void *arg) @@ -3601,7 +3517,7 @@ static int slab_mem_going_online_callback(void *arg) struct kmem_cache_node *n; struct kmem_cache *s; struct memory_notify *marg = arg; - int nid = marg->status_change_nid; + int nid = marg->status_change_nid_normal; int ret = 0; /* @@ -3616,7 +3532,7 @@ static int slab_mem_going_online_callback(void *arg) * allocate a kmem_cache_node structure in order to bring the node * online. */ - down_read(&slub_lock); + mutex_lock(&slab_mutex); list_for_each_entry(s, &slab_caches, list) { /* * XXX: kmem_cache_alloc_node will fallback to other nodes @@ -3632,7 +3548,7 @@ static int slab_mem_going_online_callback(void *arg) s->node[nid] = n; } out: - up_read(&slub_lock); + mutex_unlock(&slab_mutex); return ret; } @@ -3671,15 +3587,16 @@ static int slab_memory_callback(struct notifier_block *self, /* * Used for early kmem_cache structures that were allocated using - * the page allocator + * the page allocator. Allocate them properly then fix up the pointers + * that may be pointing to the wrong kmem_cache structure. */ -static void __init kmem_cache_bootstrap_fixup(struct kmem_cache *s) +static struct kmem_cache * __init bootstrap(struct kmem_cache *static_cache) { int node; + struct kmem_cache *s = kmem_cache_zalloc(kmem_cache, GFP_NOWAIT); - list_add(&s->list, &slab_caches); - s->refcount = -1; + memcpy(s, static_cache, kmem_cache->object_size); for_each_node_state(node, N_NORMAL_MEMORY) { struct kmem_cache_node *n = get_node(s, node); @@ -3687,75 +3604,52 @@ static void __init kmem_cache_bootstrap_fixup(struct kmem_cache *s) if (n) { list_for_each_entry(p, &n->partial, lru) - p->slab = s; + p->slab_cache = s; #ifdef CONFIG_SLUB_DEBUG list_for_each_entry(p, &n->full, lru) - p->slab = s; + p->slab_cache = s; #endif } } + list_add(&s->list, &slab_caches); + return s; } void __init kmem_cache_init(void) { + static __initdata struct kmem_cache boot_kmem_cache, + boot_kmem_cache_node; int i; - int caches = 0; - struct kmem_cache *temp_kmem_cache; - int order; - struct kmem_cache *temp_kmem_cache_node; - unsigned long kmalloc_size; + int caches = 2; if (debug_guardpage_minorder()) slub_max_order = 0; - kmem_size = offsetof(struct kmem_cache, node) + - nr_node_ids * sizeof(struct kmem_cache_node *); - - /* Allocate two kmem_caches from the page allocator */ - kmalloc_size = ALIGN(kmem_size, cache_line_size()); - order = get_order(2 * kmalloc_size); - kmem_cache = (void *)__get_free_pages(GFP_NOWAIT, order); - - /* - * Must first have the slab cache available for the allocations of the - * struct kmem_cache_node's. There is special bootstrap code in - * kmem_cache_open for slab_state == DOWN. - */ - kmem_cache_node = (void *)kmem_cache + kmalloc_size; + kmem_cache_node = &boot_kmem_cache_node; + kmem_cache = &boot_kmem_cache; - kmem_cache_open(kmem_cache_node, "kmem_cache_node", - sizeof(struct kmem_cache_node), - 0, SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL); + create_boot_cache(kmem_cache_node, "kmem_cache_node", + sizeof(struct kmem_cache_node), SLAB_HWCACHE_ALIGN); hotplug_memory_notifier(slab_memory_callback, SLAB_CALLBACK_PRI); /* Able to allocate the per node structures */ slab_state = PARTIAL; - temp_kmem_cache = kmem_cache; - kmem_cache_open(kmem_cache, "kmem_cache", kmem_size, - 0, SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL); - kmem_cache = kmem_cache_alloc(kmem_cache, GFP_NOWAIT); - memcpy(kmem_cache, temp_kmem_cache, kmem_size); + create_boot_cache(kmem_cache, "kmem_cache", + offsetof(struct kmem_cache, node) + + nr_node_ids * sizeof(struct kmem_cache_node *), + SLAB_HWCACHE_ALIGN); + + kmem_cache = bootstrap(&boot_kmem_cache); /* * Allocate kmem_cache_node properly from the kmem_cache slab. * kmem_cache_node is separately allocated so no need to * update any list pointers. */ - temp_kmem_cache_node = kmem_cache_node; - - kmem_cache_node = kmem_cache_alloc(kmem_cache, GFP_NOWAIT); - memcpy(kmem_cache_node, temp_kmem_cache_node, kmem_size); - - kmem_cache_bootstrap_fixup(kmem_cache_node); - - caches++; - kmem_cache_bootstrap_fixup(kmem_cache); - caches++; - /* Free temporary boot structure */ - free_pages((unsigned long)temp_kmem_cache, order); + kmem_cache_node = bootstrap(&boot_kmem_cache_node); /* Now we can use the kmem_cache to allocate kmalloc slabs */ @@ -3843,11 +3737,11 @@ void __init kmem_cache_init(void) if (s && s->size) { char *name = kasprintf(GFP_NOWAIT, - "dma-kmalloc-%d", s->objsize); + "dma-kmalloc-%d", s->object_size); BUG_ON(!name); kmalloc_dma_caches[i] = create_kmalloc_cache(name, - s->objsize, SLAB_CACHE_DMA); + s->object_size, SLAB_CACHE_DMA); } } #endif @@ -3924,16 +3818,11 @@ static struct kmem_cache *find_mergeable(size_t size, return NULL; } -struct kmem_cache *kmem_cache_create(const char *name, size_t size, +struct kmem_cache *__kmem_cache_alias(const char *name, size_t size, size_t align, unsigned long flags, void (*ctor)(void *)) { struct kmem_cache *s; - char *n; - if (WARN_ON(!name)) - return NULL; - - down_write(&slub_lock); s = find_mergeable(size, align, flags, name, ctor); if (s) { s->refcount++; @@ -3941,49 +3830,39 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size, * Adjust the object sizes so that we clear * the complete object on kzalloc. */ - s->objsize = max(s->objsize, (int)size); + s->object_size = max(s->object_size, (int)size); s->inuse = max_t(int, s->inuse, ALIGN(size, sizeof(void *))); if (sysfs_slab_alias(s, name)) { s->refcount--; - goto err; + s = NULL; } - up_write(&slub_lock); - return s; } - n = kstrdup(name, GFP_KERNEL); - if (!n) - goto err; + return s; +} - s = kmalloc(kmem_size, GFP_KERNEL); - if (s) { - if (kmem_cache_open(s, n, - size, align, flags, ctor)) { - list_add(&s->list, &slab_caches); - up_write(&slub_lock); - if (sysfs_slab_add(s)) { - down_write(&slub_lock); - list_del(&s->list); - kfree(n); - kfree(s); - goto err; - } - return s; - } - kfree(s); - } - kfree(n); -err: - up_write(&slub_lock); +int __kmem_cache_create(struct kmem_cache *s, unsigned long flags) +{ + int err; - if (flags & SLAB_PANIC) - panic("Cannot create slabcache %s\n", name); - else - s = NULL; - return s; + err = kmem_cache_open(s, flags); + if (err) + return err; + + /* Mutex is not taken during early boot */ + if (slab_state <= UP) + return 0; + + mutex_unlock(&slab_mutex); + err = sysfs_slab_add(s); + mutex_lock(&slab_mutex); + + if (err) + kmem_cache_close(s); + + return err; } -EXPORT_SYMBOL(kmem_cache_create); #ifdef CONFIG_SMP /* @@ -4002,13 +3881,13 @@ static int slab_cpuup_callback(struct notifier_block *nfb, case CPU_UP_CANCELED_FROZEN: case CPU_DEAD: case CPU_DEAD_FROZEN: - down_read(&slub_lock); + mutex_lock(&slab_mutex); list_for_each_entry(s, &slab_caches, list) { local_irq_save(flags); __flush_cpu_slab(s, cpu); local_irq_restore(flags); } - up_read(&slub_lock); + mutex_unlock(&slab_mutex); break; default: break; @@ -4035,7 +3914,7 @@ void *__kmalloc_track_caller(size_t size, gfp_t gfpflags, unsigned long caller) if (unlikely(ZERO_OR_NULL_PTR(s))) return s; - ret = slab_alloc(s, gfpflags, NUMA_NO_NODE, caller); + ret = slab_alloc(s, gfpflags, caller); /* Honor the call site pointer we received. */ trace_kmalloc(caller, ret, size, s->size, gfpflags); @@ -4065,7 +3944,7 @@ void *__kmalloc_node_track_caller(size_t size, gfp_t gfpflags, if (unlikely(ZERO_OR_NULL_PTR(s))) return s; - ret = slab_alloc(s, gfpflags, node, caller); + ret = slab_alloc_node(s, gfpflags, node, caller); /* Honor the call site pointer we received. */ trace_kmalloc_node(caller, ret, size, s->size, gfpflags, node); @@ -4500,30 +4379,31 @@ static ssize_t show_slab_objects(struct kmem_cache *s, for_each_possible_cpu(cpu) { struct kmem_cache_cpu *c = per_cpu_ptr(s->cpu_slab, cpu); - int node = ACCESS_ONCE(c->node); + int node; struct page *page; - if (node < 0) - continue; page = ACCESS_ONCE(c->page); - if (page) { - if (flags & SO_TOTAL) - x = page->objects; - else if (flags & SO_OBJECTS) - x = page->inuse; - else - x = 1; + if (!page) + continue; - total += x; - nodes[node] += x; - } - page = c->partial; + node = page_to_nid(page); + if (flags & SO_TOTAL) + x = page->objects; + else if (flags & SO_OBJECTS) + x = page->inuse; + else + x = 1; + + total += x; + nodes[node] += x; + page = ACCESS_ONCE(c->partial); if (page) { x = page->pobjects; total += x; nodes[node] += x; } + per_cpu[node]++; } } @@ -4623,7 +4503,7 @@ SLAB_ATTR_RO(align); static ssize_t object_size_show(struct kmem_cache *s, char *buf) { - return sprintf(buf, "%d\n", s->objsize); + return sprintf(buf, "%d\n", s->object_size); } SLAB_ATTR_RO(object_size); @@ -5211,14 +5091,6 @@ static ssize_t slab_attr_store(struct kobject *kobj, return err; } -static void kmem_cache_release(struct kobject *kobj) -{ - struct kmem_cache *s = to_slab(kobj); - - kfree(s->name); - kfree(s); -} - static const struct sysfs_ops slab_sysfs_ops = { .show = slab_attr_show, .store = slab_attr_store, @@ -5226,7 +5098,6 @@ static const struct sysfs_ops slab_sysfs_ops = { static struct kobj_type slab_ktype = { .sysfs_ops = &slab_sysfs_ops, - .release = kmem_cache_release }; static int uevent_filter(struct kset *kset, struct kobject *kobj) @@ -5284,13 +5155,8 @@ static int sysfs_slab_add(struct kmem_cache *s) { int err; const char *name; - int unmergeable; - - if (slab_state < SYSFS) - /* Defer until later */ - return 0; + int unmergeable = slab_unmergeable(s); - unmergeable = slab_unmergeable(s); if (unmergeable) { /* * Slabcache can never be merged so we can use the name proper. @@ -5331,7 +5197,7 @@ static int sysfs_slab_add(struct kmem_cache *s) static void sysfs_slab_remove(struct kmem_cache *s) { - if (slab_state < SYSFS) + if (slab_state < FULL) /* * Sysfs has not been setup yet so no need to remove the * cache from sysfs. @@ -5359,7 +5225,7 @@ static int sysfs_slab_alias(struct kmem_cache *s, const char *name) { struct saved_alias *al; - if (slab_state == SYSFS) { + if (slab_state == FULL) { /* * If we have a leftover link then remove it. */ @@ -5383,16 +5249,16 @@ static int __init slab_sysfs_init(void) struct kmem_cache *s; int err; - down_write(&slub_lock); + mutex_lock(&slab_mutex); slab_kset = kset_create_and_add("slab", &slab_uevent_ops, kernel_kobj); if (!slab_kset) { - up_write(&slub_lock); + mutex_unlock(&slab_mutex); printk(KERN_ERR "Cannot register slab subsystem.\n"); return -ENOSYS; } - slab_state = SYSFS; + slab_state = FULL; list_for_each_entry(s, &slab_caches, list) { err = sysfs_slab_add(s); @@ -5408,11 +5274,11 @@ static int __init slab_sysfs_init(void) err = sysfs_slab_alias(al->s, al->name); if (err) printk(KERN_ERR "SLUB: Unable to add boot slab alias" - " %s to sysfs\n", s->name); + " %s to sysfs\n", al->name); kfree(al); } - up_write(&slub_lock); + mutex_unlock(&slab_mutex); resiliency_test(); return 0; } @@ -5424,49 +5290,14 @@ __initcall(slab_sysfs_init); * The /proc/slabinfo ABI */ #ifdef CONFIG_SLABINFO -static void print_slabinfo_header(struct seq_file *m) -{ - seq_puts(m, "slabinfo - version: 2.1\n"); - seq_puts(m, "# name " - " "); - seq_puts(m, " : tunables "); - seq_puts(m, " : slabdata "); - seq_putc(m, '\n'); -} - -static void *s_start(struct seq_file *m, loff_t *pos) -{ - loff_t n = *pos; - - down_read(&slub_lock); - if (!n) - print_slabinfo_header(m); - - return seq_list_start(&slab_caches, *pos); -} - -static void *s_next(struct seq_file *m, void *p, loff_t *pos) -{ - return seq_list_next(p, &slab_caches, pos); -} - -static void s_stop(struct seq_file *m, void *p) -{ - up_read(&slub_lock); -} - -static int s_show(struct seq_file *m, void *p) +void get_slabinfo(struct kmem_cache *s, struct slabinfo *sinfo) { unsigned long nr_partials = 0; unsigned long nr_slabs = 0; - unsigned long nr_inuse = 0; unsigned long nr_objs = 0; unsigned long nr_free = 0; - struct kmem_cache *s; int node; - s = list_entry(p, struct kmem_cache, list); - for_each_online_node(node) { struct kmem_cache_node *n = get_node(s, node); @@ -5479,41 +5310,21 @@ static int s_show(struct seq_file *m, void *p) nr_free += count_partial(n, count_free); } - nr_inuse = nr_objs - nr_free; - - seq_printf(m, "%-17s %6lu %6lu %6u %4u %4d", s->name, nr_inuse, - nr_objs, s->size, oo_objects(s->oo), - (1 << oo_order(s->oo))); - seq_printf(m, " : tunables %4u %4u %4u", 0, 0, 0); - seq_printf(m, " : slabdata %6lu %6lu %6lu", nr_slabs, nr_slabs, - 0UL); - seq_putc(m, '\n'); - return 0; + sinfo->active_objs = nr_objs - nr_free; + sinfo->num_objs = nr_objs; + sinfo->active_slabs = nr_slabs; + sinfo->num_slabs = nr_slabs; + sinfo->objects_per_slab = oo_objects(s->oo); + sinfo->cache_order = oo_order(s->oo); } -static const struct seq_operations slabinfo_op = { - .start = s_start, - .next = s_next, - .stop = s_stop, - .show = s_show, -}; - -static int slabinfo_open(struct inode *inode, struct file *file) +void slabinfo_show_stats(struct seq_file *m, struct kmem_cache *s) { - return seq_open(file, &slabinfo_op); } -static const struct file_operations proc_slabinfo_operations = { - .open = slabinfo_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, -}; - -static int __init slab_proc_init(void) +ssize_t slabinfo_write(struct file *file, const char __user *buffer, + size_t count, loff_t *ppos) { - proc_create("slabinfo", S_IRUSR, NULL, &proc_slabinfo_operations); - return 0; + return -EIO; } -module_init(slab_proc_init); #endif /* CONFIG_SLABINFO */ From 0f398b59f3cf177477784f036f0ee15671dd9d52 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Wed, 8 Jan 2014 18:20:43 +0100 Subject: [PATCH 121/215] buildscript : Use updated SM toolchain --- glitch.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glitch.sh b/glitch.sh index 0477018e431..ffca2dac8f1 100755 --- a/glitch.sh +++ b/glitch.sh @@ -13,7 +13,7 @@ repo=~/android/system export ARCH="arm" #export CROSS_PREFIX="$repo/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi-" #export CROSS_PREFIX="$repo/prebuilts/gcc/linux-x86/arm/linaro_4.8.2-2013.09/bin/arm-gnueabi-" -export CROSS_PREFIX="$repo/prebuilts/gcc/linux-x86/arm/sabermod-androideabi-4.8/bin/arm-linux-androideabi-" +export CROSS_PREFIX="$repo/prebuilts/gcc/linux-x86/arm/sabermod-androideabi-4.8.3/bin/arm-linux-androideabi-" setup () { From 13b9ef3366682a7fafa88cf20248124260318784 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Wed, 8 Jan 2014 18:22:17 +0100 Subject: [PATCH 122/215] vfp : Use vfpv4 with neon --- arch/arm/vfp/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/vfp/Makefile b/arch/arm/vfp/Makefile index e7b053cf8b1..407c44b421e 100644 --- a/arch/arm/vfp/Makefile +++ b/arch/arm/vfp/Makefile @@ -7,7 +7,7 @@ # ccflags-y := -DDEBUG # asflags-y := -DDEBUG -KBUILD_AFLAGS :=$(KBUILD_AFLAGS:-msoft-float=-Wa,-mfpu=neon -mfloat-abi=hard) +KBUILD_AFLAGS :=$(KBUILD_AFLAGS:-msoft-float=-Wa,-mfpu=neon-vfpv4 -mfloat-abi=hard) LDFLAGS +=--no-warn-mismatch obj-y += vfp.o From 7ac14d509e3c161147b21602e255033cb76327eb Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Wed, 8 Jan 2014 19:46:27 +0100 Subject: [PATCH 123/215] Add GPU voltage control Signed-off-by: Tk-Glitch --- arch/arm/configs/flo_defconfig | 1 + arch/arm/mach-msm/Kconfig | 7 +++++ arch/arm/mach-msm/clock-8960.c | 57 +++++++++++++++++++++++++++++----- drivers/cpufreq/cpufreq.c | 28 +++++++++++++++++ 4 files changed, 85 insertions(+), 8 deletions(-) diff --git a/arch/arm/configs/flo_defconfig b/arch/arm/configs/flo_defconfig index e9cc13aaa9a..175d09c3633 100644 --- a/arch/arm/configs/flo_defconfig +++ b/arch/arm/configs/flo_defconfig @@ -467,6 +467,7 @@ CONFIG_MSM_CPU_FREQ_MAX=2322000 CONFIG_MSM_CPU_FREQ_MIN=162000 CONFIG_INTELLI_PLUG=y CONFIG_CPU_VOLTAGE_TABLE=y +CONFIG_GPU_VOLTAGE_TABLE=y CONFIG_MSM_AVS_HW=y # CONFIG_MSM_HW3D is not set CONFIG_AMSS_7X25_VERSION_2009=y diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig index 4a15791163b..9890b16292c 100644 --- a/arch/arm/mach-msm/Kconfig +++ b/arch/arm/mach-msm/Kconfig @@ -1656,6 +1656,13 @@ config CPU_VOLTAGE_TABLE help Krait User Votlage Control +config GPU_VOLTAGE_TABLE + bool "Enable GPU Voltage Table via sysfs for adjustements" + depends on CPU_VOLTAGE_TABLE + default n + help + Adreno GPU User Voltage Control + config MSM_AVS_HW bool "Enable Adaptive Voltage Scaling (AVS)" default n diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c index f78acdd1948..b3648959f4e 100644 --- a/arch/arm/mach-msm/clock-8960.c +++ b/arch/arm/mach-msm/clock-8960.c @@ -380,16 +380,57 @@ enum vdd_dig_levels { VDD_DIG_NUM }; +#ifdef CONFIG_GPU_VOLTAGE_TABLE +static int vdd_uv[] = { + [VDD_DIG_NONE] = 0, + [VDD_DIG_LOW] = 945000, + [VDD_DIG_NOMINAL] = 1050000, + [VDD_DIG_HIGH] = 1150000 +}; + +ssize_t get_gpu_vdd_levels_str(char *buf) +{ + int i, len = 0; + + if (buf) + { + for (i = 1; i <= 3; i++) + { + len += sprintf(buf + len, "%d\n", vdd_uv[i]); + } + } + return len; +} + +void set_gpu_vdd_levels(int uv_tbl[]) +{ + int i; + for (i = 1; i <= 3; i++) + { + vdd_uv[i] = uv_tbl[i - 1]; + } +} + +#endif + static int set_vdd_dig_8960(struct clk_vdd_class *vdd_class, int level) { - static const int vdd_uv[] = { - [VDD_DIG_NONE] = 0, - [VDD_DIG_LOW] = 945000, - [VDD_DIG_NOMINAL] = 1050000, - [VDD_DIG_HIGH] = 1150000 - }; - return rpm_vreg_set_voltage(RPM_VREG_ID_PM8921_S3, RPM_VREG_VOTER3, - vdd_uv[level], 1150000, 1); +#ifdef CONFIG_GPU_VOLTAGE_TABLE + int ret; + ret = rpm_vreg_set_voltage(RPM_VREG_ID_PM8921_S3, RPM_VREG_VOTER3, + vdd_uv[level], vdd_uv[VDD_DIG_HIGH], 1); + //pr_alert("GPU VOLTAGE - %d - %d", vdd_uv[level], ret); + return ret; +#else +static const int vdd_uv[] = { + [VDD_DIG_NONE] = 0, + [VDD_DIG_LOW] = 945000, + [VDD_DIG_NOMINAL] = 1050000, + [VDD_DIG_HIGH] = 1150000 +}; +return rpm_vreg_set_voltage(RPM_VREG_ID_PM8921_S3, RPM_VREG_VOTER3, + vdd_uv[level], 1150000, 1); +#endif } static DEFINE_VDD_CLASS(vdd_dig, set_vdd_dig_8960, VDD_DIG_NUM); diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 03424d28d44..5ed2e84cd11 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -706,6 +706,28 @@ static ssize_t store_vdd_levels(struct kobject *a, struct attribute *b, const ch #endif /* CONFIG_CPU_VOLTAGE_TABLE */ +#ifdef CONFIG_GPU_VOLTAGE_TABLE + +extern ssize_t get_gpu_vdd_levels_str(char *buf); +extern void set_gpu_vdd_levels(int uv_tbl[]); + +ssize_t show_vdd_levels_GPU(struct kobject *a, struct attribute *b, char *buf) +{ + int modu = 0; + return get_gpu_vdd_levels_str(buf); +} + +ssize_t store_vdd_levels_GPU(struct kobject *a, struct attribute *b, const char *buf, size_t count) +{ + unsigned int ret = -EINVAL; + unsigned int u[3]; + ret = sscanf(buf, "%d %d %d", &u[0], &u[1], &u[2]); + set_gpu_vdd_levels(u); + return count; +} + +#endif + cpufreq_freq_attr_ro_perm(cpuinfo_cur_freq, 0400); cpufreq_freq_attr_ro(cpuinfo_min_freq); cpufreq_freq_attr_ro(cpuinfo_max_freq); @@ -725,6 +747,9 @@ cpufreq_freq_attr_rw(dvfs_test); #ifdef CONFIG_CPU_VOLTAGE_TABLE define_one_global_rw(vdd_levels); #endif +#ifdef CONFIG_GPU_VOLTAGE_TABLE +define_one_global_rw(vdd_levels_GPU); +#endif static struct attribute *default_attrs[] = { &cpuinfo_min_freq.attr, @@ -746,6 +771,9 @@ static struct attribute *default_attrs[] = { #ifdef CONFIG_CPU_VOLTAGE_TABLE static struct attribute *vddtbl_attrs[] = { &vdd_levels.attr, +#ifdef CONFIG_GPU_VOLTAGE_TABLE + &vdd_levels_GPU.attr, +#endif NULL }; From 5f3d061532491e47dc5bbe1e2d98d49ad12d0dca Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Wed, 8 Jan 2014 20:49:47 +0100 Subject: [PATCH 124/215] Aroma : Add GPU uV presets from -25 to -150mV --- .../META-INF/com/google/android/aroma-config | 11 ++++++ .../com/google/android/updater-script | 36 +++++++++++++++++++ release/aroma/config/buildconfig.sh | 20 +++++++++++ release/aroma/system/etc/init.d/99glitch | 24 +++++++++++++ 4 files changed, 91 insertions(+) diff --git a/release/aroma/META-INF/com/google/android/aroma-config b/release/aroma/META-INF/com/google/android/aroma-config index deb50b8b370..54b772d0866 100755 --- a/release/aroma/META-INF/com/google/android/aroma-config +++ b/release/aroma/META-INF/com/google/android/aroma-config @@ -246,6 +246,17 @@ selectbox( "Interactive","",0 ); +selectbox( + "GPU Undervolting","Lowers the GPU voltage for all steps. Undervolting may cause instability.\n","@personalize","gpuuv.prop", + "No undervolting","(stock)",1, + "Undervolt -25mV","",0, + "Undervolt -50mV","",0, + "Undervolt -75mV","",0, + "Undervolt -100mV","",0, + "Undervolt -125mV","",0, + "Undervolt -150mV","",0 +); + selectbox( "Battery life eXtender settings","Sets the charge voltage of the battery to extend its lifespan\n","@personalize","ble.prop", "4.3V","(100% - stock)",1, diff --git a/release/aroma/META-INF/com/google/android/updater-script b/release/aroma/META-INF/com/google/android/updater-script index 343a18856c5..569732a1620 100755 --- a/release/aroma/META-INF/com/google/android/updater-script +++ b/release/aroma/META-INF/com/google/android/updater-script @@ -186,6 +186,42 @@ if ui_print("Interactive GPU Governor"); endif; +if + file_getprop("/tmp/aroma/gpuuv.prop","selected.0") == "2" + then + ui_print("-25mV GPU uV"); +endif; + +if + file_getprop("/tmp/aroma/gpuuv.prop","selected.0") == "3" + then + ui_print("-50mV GPU uV"); +endif; + +if + file_getprop("/tmp/aroma/gpuuv.prop","selected.0") == "4" + then + ui_print("-75mV GPU uV"); +endif; + +if + file_getprop("/tmp/aroma/gpuuv.prop","selected.0") == "5" + then + ui_print("-100mV GPU uV"); +endif; + +if + file_getprop("/tmp/aroma/gpuuv.prop","selected.0") == "6" + then + ui_print("-125mV GPU uV"); +endif; + +if + file_getprop("/tmp/aroma/gpuuv.prop","selected.0") == "7" + then + ui_print("-150mV GPU uV"); +endif; + if file_getprop("/tmp/aroma/ble.prop","selected.0") == "1" then diff --git a/release/aroma/config/buildconfig.sh b/release/aroma/config/buildconfig.sh index d5c32096abc..fcbccfba125 100755 --- a/release/aroma/config/buildconfig.sh +++ b/release/aroma/config/buildconfig.sh @@ -167,6 +167,26 @@ else echo "GPU_GOV=1" >> $CONFIGFILE; fi +#GPU UV +GPU_UV=`cat /tmp/aroma/gpuuv.prop | cut -d '=' -f2` +echo -e "\n\n##### GPU Undervolting #####\n# 1 Stock\n# 2 -25mV" >> $CONFIGFILE +echo -e "\n# 3 -50mV\n# 4 -75mV\n# 5 -100mV\n# 6 -125mV\n# 7 -150mV\n" >> $CONFIGFILE +if [ $GPU_UV = 2 ]; then + echo "GPU_UV=2" >> $CONFIGFILE; +elif [ $GPU_UV = 3 ]; then + echo "GPU_UV=3" >> $CONFIGFILE; +elif [ $GPU_UV = 4 ]; then + echo "GPU_UV=4" >> $CONFIGFILE; +elif [ $GPU_UV = 5 ]; then + echo "GPU_UV=5" >> $CONFIGFILE; +elif [ $GPU_UV = 6 ]; then + echo "GPU_UV=6" >> $CONFIGFILE; +elif [ $GPU_UV = 7 ]; then + echo "GPU_UV=7" >> $CONFIGFILE; +else + echo "GPU_UV=1" >> $CONFIGFILE; +fi + #Battery life extender BLE=`cat /tmp/aroma/ble.prop | cut -d '=' -f2` echo -e "\n\n##### Battery life eXtender #####\n# 1 4.3V (stock - 100%)" >> $CONFIGFILE diff --git a/release/aroma/system/etc/init.d/99glitch b/release/aroma/system/etc/init.d/99glitch index a4294c060d0..1e0cbd5189d 100755 --- a/release/aroma/system/etc/init.d/99glitch +++ b/release/aroma/system/etc/init.d/99glitch @@ -196,6 +196,30 @@ else echo Ondemand GPU Governor >> $KERNEL_LOGFILE; fi +#GPU uV settings +if [ "`grep GPU_UV=2 $KERNEL_CONF`" ]; then + printf "920000\n1025000\n1125000\n" > /sys/devices/system/cpu/cpufreq/vdd_table/vdd_levels_GPU; + echo -25mV GPU uV >> $KERNEL_LOGFILE; +elif [ "`grep GPU_UV=3 $KERNEL_CONF`" ]; then + printf "895000\n1000000\n1100000\n" > /sys/devices/system/cpu/cpufreq/vdd_table/vdd_levels_GPU; + echo -50mV GPU uV >> $KERNEL_LOGFILE; +elif [ "`grep GPU_UV=4 $KERNEL_CONF`" ]; then + printf "870000\n975000\n1075000\n" > /sys/devices/system/cpu/cpufreq/vdd_table/vdd_levels_GPU; + echo -75mV GPU uV >> $KERNEL_LOGFILE; +elif [ "`grep GPU_UV=5 $KERNEL_CONF`" ]; then + printf "845000\n950000\n1050000\n" > /sys/devices/system/cpu/cpufreq/vdd_table/vdd_levels_GPU; + echo -100mV GPU uV >> $KERNEL_LOGFILE; +elif [ "`grep GPU_UV=6 $KERNEL_CONF`" ]; then + printf "820000\n925000\n1025000\n" > /sys/devices/system/cpu/cpufreq/vdd_table/vdd_levels_GPU; + echo -125mV GPU uV >> $KERNEL_LOGFILE; +elif [ "`grep GPU_UV=7 $KERNEL_CONF`" ]; then + printf "795000\n900000\n1000000\n" > /sys/devices/system/cpu/cpufreq/vdd_table/vdd_levels_GPU; + echo -150mV GPU uV >> $KERNEL_LOGFILE; +else + printf "945000\n1050000\n1150000\n" > /sys/devices/system/cpu/cpufreq/vdd_table/vdd_levels_GPU; + echo Stock GPU voltage >> $KERNEL_LOGFILE; +fi + #Battery life extender if [ "`grep BLE=2 $KERNEL_CONF`" ]; then echo 4200 > /sys/devices/i2c-0/0-006a/float_voltage From cbfcee39f99f7c65a73cbcc665d81aa882d35f4c Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Wed, 8 Jan 2014 23:38:08 +0100 Subject: [PATCH 125/215] Make the L2 frequency jumps more linear between cpufreq steps Signed-off-by: Tk-Glitch --- arch/arm/mach-msm/acpuclock-8064.c | 112 ++++++++++++++--------------- 1 file changed, 56 insertions(+), 56 deletions(-) diff --git a/arch/arm/mach-msm/acpuclock-8064.c b/arch/arm/mach-msm/acpuclock-8064.c index 1b3770798ab..6ad0d01ef8f 100644 --- a/arch/arm/mach-msm/acpuclock-8064.c +++ b/arch/arm/mach-msm/acpuclock-8064.c @@ -343,15 +343,15 @@ static struct acpu_level tbl_PVS0_1512MHz[] __initdata = { { 1, { 162000, HFPLL, 2, 0x0C }, L2(0), 950000 }, { 1, { 270000, HFPLL, 2, 0x14 }, L2(0), 950000 }, { 1, { 384000, PLL_8, 0, 0x00 }, L2(0), 950000 }, - { 1, { 486000, HFPLL, 2, 0x24 }, L2(5), 950000 }, + { 1, { 486000, HFPLL, 2, 0x24 }, L2(4), 950000 }, { 1, { 594000, HFPLL, 1, 0x16 }, L2(5), 950000 }, - { 1, { 702000, HFPLL, 1, 0x1A }, L2(5), 962500 }, - { 1, { 810000, HFPLL, 1, 0x1E }, L2(5), 1000000 }, - { 1, { 918000, HFPLL, 1, 0x22 }, L2(5), 1025000 }, - { 1, { 1026000, HFPLL, 1, 0x26 }, L2(5), 1037500 }, - { 1, { 1134000, HFPLL, 1, 0x2A }, L2(13), 1075000 }, - { 1, { 1242000, HFPLL, 1, 0x2E }, L2(13), 1087500 }, - { 1, { 1350000, HFPLL, 1, 0x32 }, L2(13), 1125000 }, + { 1, { 702000, HFPLL, 1, 0x1A }, L2(6), 962500 }, + { 1, { 810000, HFPLL, 1, 0x1E }, L2(7), 1000000 }, + { 1, { 918000, HFPLL, 1, 0x22 }, L2(8), 1025000 }, + { 1, { 1026000, HFPLL, 1, 0x26 }, L2(9), 1037500 }, + { 1, { 1134000, HFPLL, 1, 0x2A }, L2(10), 1075000 }, + { 1, { 1242000, HFPLL, 1, 0x2E }, L2(11), 1087500 }, + { 1, { 1350000, HFPLL, 1, 0x32 }, L2(12), 1125000 }, { 1, { 1458000, HFPLL, 1, 0x36 }, L2(13), 1150000 }, { 1, { 1512000, HFPLL, 1, 0x38 }, L2(14), 1162500 }, { 1, { 1620000, HFPLL, 1, 0x3C }, L2(14), 1187500 }, @@ -373,15 +373,15 @@ static struct acpu_level tbl_PVS1_1512MHz[] __initdata = { { 1, { 162000, HFPLL, 2, 0x0C }, L2(0), 950000 }, { 1, { 270000, HFPLL, 2, 0x14 }, L2(0), 950000 }, { 1, { 384000, PLL_8, 0, 0x00 }, L2(0), 950000 }, - { 1, { 486000, HFPLL, 2, 0x24 }, L2(5), 950000 }, + { 1, { 486000, HFPLL, 2, 0x24 }, L2(4), 950000 }, { 1, { 594000, HFPLL, 1, 0x16 }, L2(5), 950000 }, - { 1, { 702000, HFPLL, 1, 0x1A }, L2(5), 962500 }, - { 1, { 810000, HFPLL, 1, 0x1E }, L2(5), 975000 }, - { 1, { 918000, HFPLL, 1, 0x22 }, L2(5), 1000000 }, - { 1, { 1026000, HFPLL, 1, 0x26 }, L2(5), 1012500 }, - { 1, { 1134000, HFPLL, 1, 0x2A }, L2(13), 1037500 }, - { 1, { 1242000, HFPLL, 1, 0x2E }, L2(13), 1050000 }, - { 1, { 1350000, HFPLL, 1, 0x32 }, L2(13), 1087500 }, + { 1, { 702000, HFPLL, 1, 0x1A }, L2(6), 962500 }, + { 1, { 810000, HFPLL, 1, 0x1E }, L2(7), 975000 }, + { 1, { 918000, HFPLL, 1, 0x22 }, L2(8), 1000000 }, + { 1, { 1026000, HFPLL, 1, 0x26 }, L2(9), 1012500 }, + { 1, { 1134000, HFPLL, 1, 0x2A }, L2(10), 1037500 }, + { 1, { 1242000, HFPLL, 1, 0x2E }, L2(11), 1050000 }, + { 1, { 1350000, HFPLL, 1, 0x32 }, L2(12), 1087500 }, { 1, { 1458000, HFPLL, 1, 0x36 }, L2(13), 1112500 }, { 1, { 1512000, HFPLL, 1, 0x38 }, L2(14), 1125000 }, { 1, { 1620000, HFPLL, 1, 0x3C }, L2(14), 1150000 }, @@ -403,15 +403,15 @@ static struct acpu_level tbl_PVS2_1512MHz[] __initdata = { { 1, { 162000, HFPLL, 2, 0x0C }, L2(0), 925000 }, { 1, { 270000, HFPLL, 2, 0x14 }, L2(0), 925000 }, { 1, { 384000, PLL_8, 0, 0x00 }, L2(0), 925000 }, - { 1, { 486000, HFPLL, 2, 0x24 }, L2(5), 925000 }, + { 1, { 486000, HFPLL, 2, 0x24 }, L2(4), 925000 }, { 1, { 594000, HFPLL, 1, 0x16 }, L2(5), 925000 }, - { 1, { 702000, HFPLL, 1, 0x1A }, L2(5), 925000 }, - { 1, { 810000, HFPLL, 1, 0x1E }, L2(5), 937500 }, - { 1, { 918000, HFPLL, 1, 0x22 }, L2(5), 950000 }, - { 1, { 1026000, HFPLL, 1, 0x26 }, L2(5), 975000 }, - { 1, { 1134000, HFPLL, 1, 0x2A }, L2(13), 1000000 }, - { 1, { 1242000, HFPLL, 1, 0x2E }, L2(13), 1012500 }, - { 1, { 1350000, HFPLL, 1, 0x32 }, L2(13), 1037500 }, + { 1, { 702000, HFPLL, 1, 0x1A }, L2(6), 925000 }, + { 1, { 810000, HFPLL, 1, 0x1E }, L2(7), 937500 }, + { 1, { 918000, HFPLL, 1, 0x22 }, L2(8), 950000 }, + { 1, { 1026000, HFPLL, 1, 0x26 }, L2(9), 975000 }, + { 1, { 1134000, HFPLL, 1, 0x2A }, L2(10), 1000000 }, + { 1, { 1242000, HFPLL, 1, 0x2E }, L2(11), 1012500 }, + { 1, { 1350000, HFPLL, 1, 0x32 }, L2(12), 1037500 }, { 1, { 1458000, HFPLL, 1, 0x36 }, L2(13), 1075000 }, { 1, { 1512000, HFPLL, 1, 0x38 }, L2(14), 1087500 }, { 1, { 1620000, HFPLL, 1, 0x3C }, L2(14), 1112500 }, @@ -433,15 +433,15 @@ static struct acpu_level tbl_PVS3_1512MHz[] __initdata = { { 1, { 162000, HFPLL, 2, 0x0C }, L2(0), 900000 }, { 1, { 270000, HFPLL, 2, 0x14 }, L2(0), 900000 }, { 1, { 384000, PLL_8, 0, 0x00 }, L2(0), 900000 }, - { 1, { 486000, HFPLL, 2, 0x24 }, L2(5), 900000 }, + { 1, { 486000, HFPLL, 2, 0x24 }, L2(4), 900000 }, { 1, { 594000, HFPLL, 1, 0x16 }, L2(5), 900000 }, - { 1, { 702000, HFPLL, 1, 0x1A }, L2(5), 900000 }, - { 1, { 810000, HFPLL, 1, 0x1E }, L2(5), 900000 }, - { 1, { 918000, HFPLL, 1, 0x22 }, L2(5), 925000 }, - { 1, { 1026000, HFPLL, 1, 0x26 }, L2(5), 950000 }, - { 1, { 1134000, HFPLL, 1, 0x2A }, L2(13), 975000 }, - { 1, { 1242000, HFPLL, 1, 0x2E }, L2(13), 987500 }, - { 1, { 1350000, HFPLL, 1, 0x32 }, L2(13), 1000000 }, + { 1, { 702000, HFPLL, 1, 0x1A }, L2(6), 900000 }, + { 1, { 810000, HFPLL, 1, 0x1E }, L2(7), 900000 }, + { 1, { 918000, HFPLL, 1, 0x22 }, L2(8), 925000 }, + { 1, { 1026000, HFPLL, 1, 0x26 }, L2(9), 950000 }, + { 1, { 1134000, HFPLL, 1, 0x2A }, L2(10), 975000 }, + { 1, { 1242000, HFPLL, 1, 0x2E }, L2(11), 987500 }, + { 1, { 1350000, HFPLL, 1, 0x32 }, L2(12), 1000000 }, { 1, { 1458000, HFPLL, 1, 0x36 }, L2(13), 1037500 }, { 1, { 1512000, HFPLL, 1, 0x38 }, L2(14), 1050000 }, { 1, { 1620000, HFPLL, 1, 0x3C }, L2(14), 1075000 }, @@ -463,15 +463,15 @@ static struct acpu_level tbl_PVS4_1512MHz[] __initdata = { { 1, { 162000, HFPLL, 2, 0x0C }, L2(0), 875000 }, { 1, { 270000, HFPLL, 2, 0x14 }, L2(0), 875000 }, { 1, { 384000, PLL_8, 0, 0x00 }, L2(0), 875000 }, - { 1, { 486000, HFPLL, 2, 0x24 }, L2(5), 875000 }, + { 1, { 486000, HFPLL, 2, 0x24 }, L2(4), 875000 }, { 1, { 594000, HFPLL, 1, 0x16 }, L2(5), 875000 }, - { 1, { 702000, HFPLL, 1, 0x1A }, L2(5), 875000 }, - { 1, { 810000, HFPLL, 1, 0x1E }, L2(5), 887500 }, - { 1, { 918000, HFPLL, 1, 0x22 }, L2(5), 900000 }, - { 1, { 1026000, HFPLL, 1, 0x26 }, L2(5), 925000 }, - { 1, { 1134000, HFPLL, 1, 0x2A }, L2(13), 950000 }, - { 1, { 1242000, HFPLL, 1, 0x2E }, L2(13), 962500 }, - { 1, { 1350000, HFPLL, 1, 0x32 }, L2(13), 975000 }, + { 1, { 702000, HFPLL, 1, 0x1A }, L2(6), 875000 }, + { 1, { 810000, HFPLL, 1, 0x1E }, L2(7), 887500 }, + { 1, { 918000, HFPLL, 1, 0x22 }, L2(8), 900000 }, + { 1, { 1026000, HFPLL, 1, 0x26 }, L2(9), 925000 }, + { 1, { 1134000, HFPLL, 1, 0x2A }, L2(10), 950000 }, + { 1, { 1242000, HFPLL, 1, 0x2E }, L2(11), 962500 }, + { 1, { 1350000, HFPLL, 1, 0x32 }, L2(12), 975000 }, { 1, { 1458000, HFPLL, 1, 0x36 }, L2(13), 1000000 }, { 1, { 1512000, HFPLL, 1, 0x38 }, L2(14), 1012500 }, { 1, { 1620000, HFPLL, 1, 0x3C }, L2(14), 1037500 }, @@ -493,15 +493,15 @@ static struct acpu_level tbl_PVS5_1512MHz[] __initdata = { { 1, { 162000, HFPLL, 2, 0x0C }, L2(0), 875000 }, { 1, { 270000, HFPLL, 2, 0x14 }, L2(0), 875000 }, { 1, { 384000, PLL_8, 0, 0x00 }, L2(0), 875000 }, - { 1, { 486000, HFPLL, 2, 0x24 }, L2(5), 875000 }, + { 1, { 486000, HFPLL, 2, 0x24 }, L2(4), 875000 }, { 1, { 594000, HFPLL, 1, 0x16 }, L2(5), 875000 }, - { 1, { 702000, HFPLL, 1, 0x1A }, L2(5), 875000 }, - { 1, { 810000, HFPLL, 1, 0x1E }, L2(5), 887500 }, - { 1, { 918000, HFPLL, 1, 0x22 }, L2(5), 900000 }, - { 1, { 1026000, HFPLL, 1, 0x26 }, L2(5), 925000 }, - { 1, { 1134000, HFPLL, 1, 0x2A }, L2(13), 937500 }, - { 1, { 1242000, HFPLL, 1, 0x2E }, L2(13), 950000 }, - { 1, { 1350000, HFPLL, 1, 0x32 }, L2(13), 962500 }, + { 1, { 702000, HFPLL, 1, 0x1A }, L2(6), 875000 }, + { 1, { 810000, HFPLL, 1, 0x1E }, L2(7), 887500 }, + { 1, { 918000, HFPLL, 1, 0x22 }, L2(8), 900000 }, + { 1, { 1026000, HFPLL, 1, 0x26 }, L2(9), 925000 }, + { 1, { 1134000, HFPLL, 1, 0x2A }, L2(10), 937500 }, + { 1, { 1242000, HFPLL, 1, 0x2E }, L2(11), 950000 }, + { 1, { 1350000, HFPLL, 1, 0x32 }, L2(12), 962500 }, { 1, { 1458000, HFPLL, 1, 0x36 }, L2(13), 987500 }, { 1, { 1512000, HFPLL, 1, 0x38 }, L2(14), 1000000 }, { 1, { 1620000, HFPLL, 1, 0x3C }, L2(14), 1025000 }, @@ -523,15 +523,15 @@ static struct acpu_level tbl_PVS6_1512MHz[] __initdata = { { 1, { 162000, HFPLL, 2, 0x0C }, L2(0), 875000 }, { 1, { 270000, HFPLL, 2, 0x14 }, L2(0), 875000 }, { 1, { 384000, PLL_8, 0, 0x00 }, L2(0), 875000 }, - { 1, { 486000, HFPLL, 2, 0x24 }, L2(5), 875000 }, + { 1, { 486000, HFPLL, 2, 0x24 }, L2(4), 875000 }, { 1, { 594000, HFPLL, 1, 0x16 }, L2(5), 875000 }, - { 1, { 702000, HFPLL, 1, 0x1A }, L2(5), 875000 }, - { 1, { 810000, HFPLL, 1, 0x1E }, L2(5), 887500 }, - { 1, { 918000, HFPLL, 1, 0x22 }, L2(5), 900000 }, - { 1, { 1026000, HFPLL, 1, 0x26 }, L2(5), 925000 }, - { 1, { 1134000, HFPLL, 1, 0x2A }, L2(13), 937500 }, - { 1, { 1242000, HFPLL, 1, 0x2E }, L2(13), 950000 }, - { 1, { 1350000, HFPLL, 1, 0x32 }, L2(13), 962500 }, + { 1, { 702000, HFPLL, 1, 0x1A }, L2(6), 875000 }, + { 1, { 810000, HFPLL, 1, 0x1E }, L2(7), 887500 }, + { 1, { 918000, HFPLL, 1, 0x22 }, L2(8), 900000 }, + { 1, { 1026000, HFPLL, 1, 0x26 }, L2(9), 925000 }, + { 1, { 1134000, HFPLL, 1, 0x2A }, L2(10), 937500 }, + { 1, { 1242000, HFPLL, 1, 0x2E }, L2(11), 950000 }, + { 1, { 1350000, HFPLL, 1, 0x32 }, L2(12), 962500 }, { 1, { 1458000, HFPLL, 1, 0x36 }, L2(13), 975000 }, { 1, { 1512000, HFPLL, 1, 0x38 }, L2(14), 987500 }, { 1, { 1620000, HFPLL, 1, 0x3C }, L2(14), 1012500 }, From f2e8e540fc1656e821181374c52776644ff4fe83 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Wed, 8 Jan 2014 23:38:59 +0100 Subject: [PATCH 126/215] DRIVERS: SLIMBUS: initial overclocking of slimbus .Increase root freq from 11 (24.526MHz) to 31 max (27+MHz) which is the largest it will take .Increase clock gear from 7 to 10 (max again) This means SLIMbus will use its maximum potential to give the best audio quality for the hardware. Takes advantage of both hardware and the mods from zeroinfinity, also opening the door for more things that were previously limited by this. Researched and experimented by ZeroInfinity and Poondog Signed-off-by: poondog --- drivers/slimbus/slim-msm-ctrl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/slimbus/slim-msm-ctrl.c b/drivers/slimbus/slim-msm-ctrl.c index b7081333e07..87401d08cfe 100644 --- a/drivers/slimbus/slim-msm-ctrl.c +++ b/drivers/slimbus/slim-msm-ctrl.c @@ -232,8 +232,8 @@ enum mgr_intr { enum frm_cfg { FRM_ACTIVE = 1, - CLK_GEAR = 7, - ROOT_FREQ = 11, + CLK_GEAR = 10, + ROOT_FREQ = 31, REF_CLK_GEAR = 15, INTR_WAKE = 19, }; From 6c121f6d52f63043c36141c2b6e67cbd2efdb414 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Thu, 9 Jan 2014 01:09:26 +0100 Subject: [PATCH 127/215] msm_mpdecision : Hardcode minfreq and disable MSM_CPU_FREQ_SET_MIN_MAX --- arch/arm/configs/flo_defconfig | 6 +++--- arch/arm/mach-msm/msm_mpdecision.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/configs/flo_defconfig b/arch/arm/configs/flo_defconfig index 175d09c3633..c8466a2b1c1 100644 --- a/arch/arm/configs/flo_defconfig +++ b/arch/arm/configs/flo_defconfig @@ -462,9 +462,9 @@ CONFIG_MSM_IPC_ROUTER_SECURITY=y # CONFIG_MSM_DALRPC is not set CONFIG_MSM_MPDEC=y CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN=y -CONFIG_MSM_CPU_FREQ_SET_MIN_MAX=y -CONFIG_MSM_CPU_FREQ_MAX=2322000 -CONFIG_MSM_CPU_FREQ_MIN=162000 +# CONFIG_MSM_CPU_FREQ_SET_MIN_MAX is not set +# CONFIG_MSM_CPU_FREQ_MAX is not set +# CONFIG_MSM_CPU_FREQ_MIN is not set CONFIG_INTELLI_PLUG=y CONFIG_CPU_VOLTAGE_TABLE=y CONFIG_GPU_VOLTAGE_TABLE=y diff --git a/arch/arm/mach-msm/msm_mpdecision.c b/arch/arm/mach-msm/msm_mpdecision.c index 241bc470b89..0f59298e248 100644 --- a/arch/arm/mach-msm/msm_mpdecision.c +++ b/arch/arm/mach-msm/msm_mpdecision.c @@ -1127,7 +1127,7 @@ static int __init msm_mpdec_init(void) { per_cpu(msm_mpdec_cpudata, cpu).times_cpu_unplugged = 0; per_cpu(msm_mpdec_cpudata, cpu).times_cpu_hotplugged = 0; #ifdef CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN - per_cpu(msm_mpdec_cpudata, cpu).norm_min_freq = CONFIG_MSM_CPU_FREQ_MIN; + per_cpu(msm_mpdec_cpudata, cpu).norm_min_freq = 162000; switch (cpu) { case 0: case 1: From aee9bac9872e70379d225af07da68b543178f7bc Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Thu, 9 Jan 2014 01:36:29 +0100 Subject: [PATCH 128/215] Touchscreen : More patches from Showp1984. --- drivers/input/touchscreen/ektf3k.c | 45 ++++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 8 deletions(-) diff --git a/drivers/input/touchscreen/ektf3k.c b/drivers/input/touchscreen/ektf3k.c index 0ce615955cb..658f678b766 100755 --- a/drivers/input/touchscreen/ektf3k.c +++ b/drivers/input/touchscreen/ektf3k.c @@ -149,6 +149,8 @@ struct elan_ktf3k_ts_data { struct input_dev *input_dev; struct workqueue_struct *elan_wq; struct work_struct work; + struct workqueue_struct *touch_release_work_wq; + struct work_struct touch_release_work; int (*power)(int on); struct early_suspend early_suspend; int intr_gpio; @@ -176,6 +178,7 @@ static int __fw_packet_handler(struct i2c_client *client, int imediate); static int elan_ktf3k_ts_rough_calibrate(struct i2c_client *client); static int elan_ktf3k_ts_hw_reset(struct i2c_client *client, unsigned int time); static int elan_ktf3k_ts_resume(struct i2c_client *client); +void force_release_pos(struct i2c_client *client); #ifdef FIRMWARE_UPDATE_WITH_HEADER static int firmware_update_header(struct i2c_client *client, unsigned char *firmware, unsigned int page_number); @@ -635,7 +638,7 @@ static long elan_iap_ioctl(/*struct inode *inode,*/ struct file *filp, unsign case IOCTL_MINOR_FW_VER: break; case IOCTL_RESET: - return elan_ktf3k_ts_hw_reset(private_ts->client, 0); + return elan_ktf3k_ts_hw_reset(private_ts->client, 250); case IOCTL_IAP_MODE_LOCK: work_lock=1; disable_irq(private_ts->client->irq); @@ -1431,7 +1434,6 @@ static int elan_ktf3k_ts_hw_reset(struct i2c_client *client, unsigned int time) return 0; } - static int elan_ktf3k_ts_set_power_source(struct i2c_client *client, u8 state) { uint8_t cmd[] = {CMD_W_PKT, 0x40, 0x00, 0x01}; @@ -1673,6 +1675,15 @@ static void process_resp_message(struct elan_ktf3k_ts_data *ts, const unsigned c } } +static void touch_release_work_func(struct work_struct *work) +{ + struct elan_ktf3k_ts_data *ts = container_of(work, struct elan_ktf3k_ts_data, touch_release_work); + if (ts) + force_release_pos(ts->client); + else + touch_debug(DEBUG_INFO, "[elan] %s: ts == null, aborting touch release.\n", __func__); +} + static void elan_ktf3k_ts_work_func(struct work_struct *work) { int rc; @@ -1758,7 +1769,12 @@ static void elan_ktf3k_ts_work_func(struct work_struct *work) break; default: up(&pSem); - touch_debug(DEBUG_INFO, "[elan] Get unknow packet {0x%02X, 0x%02X, 0x%02X, 0x%02X}\n", buf[0], buf[1], buf[2], buf[3]); + if (((buf[0] == 0xFF) || (buf[0] == 0x7F) || (buf[0] == 0x55)) && ((buf[1] == 0x55) || (buf[1] == 0xFF)) && ((buf[2] == 0x55) || (buf[2] == 0xFF)) && ((buf[3] == 0x55) || (buf[3] == 0xFF))) { + touch_debug(DEBUG_INFO, "[elan] GND issue detected, forcing touch release. {0x%02X, 0x%02X, 0x%02X, 0x%02X}\n", buf[0], buf[1], buf[2], buf[3]); + queue_work(ts->touch_release_work_wq, &ts->touch_release_work); + } else { + touch_debug(DEBUG_INFO, "[elan] Get unknow packet {0x%02X, 0x%02X, 0x%02X, 0x%02X}\n", buf[0], buf[1], buf[2], buf[3]); + } } #endif enable_irq(ts->client->irq); @@ -1781,8 +1797,8 @@ static int elan_ktf3k_ts_register_interrupt(struct i2c_client *client) struct elan_ktf3k_ts_data *ts = i2c_get_clientdata(client); int err = 0; - err = request_irq(client->irq, elan_ktf3k_ts_irq_handler, - IRQF_TRIGGER_LOW, client->name, ts); + err = request_threaded_irq(client->irq, NULL, elan_ktf3k_ts_irq_handler, + IRQF_TRIGGER_LOW | IRQF_ONESHOT | IRQF_IRQPOLL, client->name, ts); if (err) dev_err(&client->dev, "[elan] %s: request_irq %d failed\n", __func__, client->irq); @@ -1939,7 +1955,7 @@ static int firmware_update_header(struct i2c_client *client, unsigned char *firm wake_lock(&ts->wakelock); work_lock = 1; /*add delay for waiting bootcode initial*/ - elan_ktf3k_ts_hw_reset(client, 20); + elan_ktf3k_ts_hw_reset(client, 250); touch_debug(DEBUG_INFO, "Send command into IAP mode\n"); /*get into IAP mode*/ if (sendI2CPacket(client, nb_isp_cmd, sizeof(nb_isp_cmd)) < 0) @@ -1985,7 +2001,7 @@ static int firmware_update_header(struct i2c_client *client, unsigned char *firm cursor += FIRMWARE_PAGE_SIZE; } - elan_ktf3k_ts_hw_reset(client, 0); + elan_ktf3k_ts_hw_reset(client, 250); /*check irq*/ wait_for_IRQ_Low(client, 500000);/*500ms * 10*/ @@ -2114,7 +2130,7 @@ static int elan_ktf3k_ts_probe(struct i2c_client *client, goto err_alloc_data_failed; } - ts->elan_wq = create_singlethread_workqueue("elan_wq"); + ts->elan_wq = alloc_workqueue("elan_wq", WQ_UNBOUND | WQ_RESCUER | WQ_HIGHPRI, 1); if (!ts->elan_wq) { touch_debug(DEBUG_ERROR, "[elan] %s: create workqueue failed\n", __func__); err = -ENOMEM; @@ -2122,6 +2138,16 @@ static int elan_ktf3k_ts_probe(struct i2c_client *client, } INIT_WORK(&ts->work, elan_ktf3k_ts_work_func); + + ts->touch_release_work_wq = alloc_workqueue("pos_rel", WQ_UNBOUND | WQ_RESCUER | WQ_HIGHPRI, 1); + if (!ts->touch_release_work_wq) { + touch_debug(DEBUG_ERROR, "[elan] %s: create workqueue failed\n", __func__); + err = -ENOMEM; + goto err_create_wq_failed; + } + + INIT_WORK(&ts->touch_release_work, touch_release_work_func); + ts->client = client; i2c_set_clientdata(client, ts); pdata = client->dev.platform_data; @@ -2289,6 +2315,8 @@ static int elan_ktf3k_ts_remove(struct i2c_client *client) unregister_early_suspend(&ts->early_suspend); free_irq(client->irq, ts); + if (ts->touch_release_work_wq) + destroy_workqueue(ts->touch_release_work_wq); if (ts->elan_wq) destroy_workqueue(ts->elan_wq); input_unregister_device(ts->input_dev); @@ -2300,6 +2328,7 @@ static int elan_ktf3k_ts_remove(struct i2c_client *client) #ifdef _ENABLE_DBG_LEVEL remove_proc_entry(PROC_FS_NAME, NULL); #endif + elan_touch_sysfs_deinit(); return 0; } From 0042ceb1ddbdb7cdd8aa0c893e1ca2d1e7ff8847 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 7 Sep 2013 21:58:39 -0700 Subject: [PATCH 129/215] Linux 3.4.61 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit jfs: fix readdir cookie incompatibility with NFSv4 commit 44512449c0ab368889dd13ae0031fba74ee7e1d2 upstream. NFSv4 reserves readdir cookie values 0-2 for special entries (. and ..), but jfs allows a value of 2 for a non-special entry. This incompatibility can result in the nfs client reporting a readdir loop. This patch doesn't change the value stored internally, but adds one to the value exposed to the iterate method. Signed-off-by: Dave Kleikamp [bwh: Backported to 3.2: - Adjust context - s/ctx->pos/filp->f_pos/] Tested-by: Christian Kujau Signed-off-by: Ben Hutchings Signed-off-by: Greg Kroah-Hartman ALSA: opti9xx: Fix conflicting driver object name commit fb615499f0ad28ed74201c1cdfddf9e64e205424 upstream. The recent commit to delay the release of kobject triggered NULL dereferences of opti9xx drivers. The cause is that all snd-opti92x-ad1848, snd-opti92x-cs4231 and snd-opti93x drivers register the PnP card driver with the very same name, and also snd-opti92x-ad1848 and -cs4231 drivers register the ISA driver with the same name, too. When these drivers are built in, quick "register-release-and-re-register" actions occur, and this results in Oops because of the same name is assigned to the kobject. The fix is simply to assign individual names. As a bonus, by using KBUILD_MODNAME, the patch reduces more lines than it adds. The fix is based on the suggestion by Russell King. Reported-and-tested-by: Fengguang Wu Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman powerpc: Work around gcc miscompilation of __pa() on 64-bit commit bdbc29c19b2633b1d9c52638fb732bcde7a2031a upstream. On 64-bit, __pa(&static_var) gets miscompiled by recent versions of gcc as something like: addis 3,2,.LANCHOR1+4611686018427387904@toc@ha addi 3,3,.LANCHOR1+4611686018427387904@toc@l This ends up effectively ignoring the offset, since its bottom 32 bits are zero, and means that the result of __pa() still has 0xC in the top nibble. This happens with gcc 4.8.1, at least. To work around this, for 64-bit we make __pa() use an AND operator, and for symmetry, we make __va() use an OR operator. Using an AND operator rather than a subtraction ends up with slightly shorter code since it can be done with a single clrldi instruction, whereas it takes three instructions to form the constant (-PAGE_OFFSET) and add it on. (Note that MEMORY_START is always 0 on 64-bit.) Signed-off-by: Paul Mackerras Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Greg Kroah-Hartman powerpc/hvsi: Increase handshake timeout from 200ms to 400ms. commit d220980b701d838560a70de691b53be007e99e78 upstream. This solves a problem observed in kexec'ed kernel where 200ms timeout is too short and bootconsole fails to initialize. Console did eventually become workable but much later into the boot process. Observed timeout was around 260ms, but I decided to make it a little bigger for more reliability. This has been tested on Power7 machine with Petitboot as a primary bootloader and PowerNV firmware. Signed-off-by: Eugene Surovegin Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Greg Kroah-Hartman regmap: silence GCC warning commit a8f28cfad8cd44d7c34b166d0e5ace1125dbee1f upstream. Building regmap.o triggers this GCC warning: drivers/base/regmap/regmap.c: In function ‘regmap_raw_read’: drivers/base/regmap/regmap.c:1172:6: warning: ‘ret’ may be used uninitialized in this function [-Wmaybe-uninitialized] Long story short: Jakub Jelinek pointed out that there is a type mismatch between 'num' in regmap_volatile_range() and 'val_count' in regmap_raw_read(). And indeed, converting 'num' to the type of 'val_count' (ie, size_t) makes this warning go away. Signed-off-by: Paul Bolle Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman drivers/base/memory.c: fix show_mem_removable() to handle missing sections commit 21ea9f5ace3a7317cc3ba1fbc749758021a83136 upstream. "cat /sys/devices/system/memory/memory*/removable" crashed the system. The problem is that show_mem_removable() is passing a bad pfn to is_mem_section_removable(), which causes if (!node_online(page_to_nid(page))) to blow up. Why is it passing in a bad pfn? The reason is that show_mem_removable() will loop sections_per_block times. sections_per_block is 16, but mem->section_count is 8, indicating holes in this memory block. Checking that the memory section is present before checking to see if the memory section is removable fixes the problem. harp5-sys:~ # cat /sys/devices/system/memory/memory*/removable 0 1 1 1 1 1 1 1 1 1 1 1 1 1 BUG: unable to handle kernel paging request at ffffea00c3200000 IP: [] is_pageblock_removable_nolock+0x1/0x90 PGD 83ffd4067 PUD 37bdfce067 PMD 0 Oops: 0000 [#1] SMP Modules linked in: autofs4 binfmt_misc rdma_ucm rdma_cm iw_cm ib_addr ib_srp scsi_transport_srp scsi_tgt ib_ipoib ib_cm ib_uverbs ib_umad iw_cxgb3 cxgb3 mdio mlx4_en mlx4_ib ib_sa mlx4_core ib_mthca ib_mad ib_core fuse nls_iso8859_1 nls_cp437 vfat fat joydev loop hid_generic usbhid hid hwperf(O) numatools(O) dm_mod iTCO_wdt ipv6 iTCO_vendor_support igb i2c_i801 ioatdma i2c_algo_bit ehci_pci pcspkr lpc_ich i2c_core ehci_hcd ptp sg mfd_core dca rtc_cmos pps_core mperf button xhci_hcd sd_mod crc_t10dif usbcore usb_common scsi_dh_emc scsi_dh_hp_sw scsi_dh_alua scsi_dh_rdac scsi_dh gru(O) xvma(O) xfs crc32c libcrc32c thermal sata_nv processor piix mptsas mptscsih scsi_transport_sas mptbase megaraid_sas fan thermal_sys hwmon ext3 jbd ata_piix ahci libahci libata scsi_mod CPU: 4 PID: 5991 Comm: cat Tainted: G O 3.11.0-rc5-rja-uv+ #10 Hardware name: SGI UV2000/ROMLEY, BIOS SGI UV 2000/3000 series BIOS 01/15/2013 task: ffff88081f034580 ti: ffff880820022000 task.ti: ffff880820022000 RIP: 0010:[] [] is_pageblock_removable_nolock+0x1/0x90 RSP: 0018:ffff880820023df8 EFLAGS: 00010287 RAX: 0000000000040000 RBX: ffffea00c3200000 RCX: 0000000000000004 RDX: ffffea00c30b0000 RSI: 00000000001c0000 RDI: ffffea00c3200000 RBP: ffff880820023e38 R08: 0000000000000000 R09: 0000000000000001 R10: 0000000000000000 R11: 0000000000000001 R12: ffffea00c33c0000 R13: 0000160000000000 R14: 6db6db6db6db6db7 R15: 0000000000000001 FS: 00007ffff7fb2700(0000) GS:ffff88083fc80000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: ffffea00c3200000 CR3: 000000081b954000 CR4: 00000000000407e0 Call Trace: show_mem_removable+0x41/0x70 dev_attr_show+0x2a/0x60 sysfs_read_file+0xf7/0x1c0 vfs_read+0xc8/0x130 SyS_read+0x5d/0xa0 system_call_fastpath+0x16/0x1b Signed-off-by: Russ Anderson Cc: "Rafael J. Wysocki" Cc: Yinghai Lu Reviewed-by: Yasuaki Ishimatsu Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman drm/vmwgfx: Split GMR2_REMAP commands if they are to large commit 6e4dcff3adbf25acb87e74500a58e3c07bdec40f upstream. This fixes the piglit test texturing/max-texture-size causing the VM to die due to a too large SVGA command. Signed-off-by: Jakob Bornecrantz Reviewed-by: Biran Paul Reviewed-by: Zack Rusin Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman drm/i915: ivb: fix edp voltage swing reg val commit 77fa4cbd5fa389e28419bbe8ac491b5fdd54840d upstream. Fix the typo introduced in commit 1a2eb4604b85c5efb343da8a4dcf41288fcfca85 Author: Keith Packard Date: Wed Nov 16 16:26:07 2011 -0800 drm/i915: Hook up Ivybridge eDP This fixes eDP link-training failures and cases where all voltage swing /pre-emphasis levels were tried and failed during clock recovery and - as a fallback - we go on to do channel equalization with the last voltage swing/pre-emphasis level which will succeed. Both issues can lead to a blank screen. v2: - improve commit message Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=64880 Tested-by: Jeremy Moles Signed-off-by: Imre Deak Reviewed-by: Paulo Zanoni Signed-off-by: Daniel Vetter Signed-off-by: Greg Kroah-Hartman SUNRPC: Fix memory corruption issue on 32-bit highmem systems commit 347e2233b7667e336d9f671f1a52dfa3f0416e2c upstream. Some architectures, such as ARM-32 do not return the same base address when you call kmap_atomic() twice on the same page. This causes problems for the memmove() call in the XDR helper routine "_shift_data_right_pages()", since it defeats the detection of overlapping memory ranges, and has been seen to corrupt memory. The fix is to distinguish between the case where we're doing an inter-page copy or not. In the former case of we know that the memory ranges cannot possibly overlap, so we can additionally micro-optimise by replacing memmove() with memcpy(). Reported-by: Mark Young Reported-by: Matt Craighead Cc: Bruce Fields Signed-off-by: Trond Myklebust Tested-by: Matt Craighead Signed-off-by: Greg Kroah-Hartman ath9k_htc: Restore skb headroom when returning skb to mac80211 commit d2e9fc141e2aa21f4b35ee27072d84e9aa6e2ba0 upstream. ath9k_htc adds padding between the 802.11 header and the payload during TX by moving the header. When handing the frame back to mac80211 for TX status handling the header is not moved back into its original position. This can result in a too small skb headroom when entering ath9k_htc again (due to a soft retransmission for example) causing an skb_under_panic oops. Fix this by moving the 802.11 header back into its original position before returning the frame to mac80211 as other drivers like rt2x00 or ath5k do. Reported-by: Marc Kleine-Budde Signed-off-by: Helmut Schaa Tested-by: Marc Kleine-Budde Signed-off-by: Marc Kleine-Budde Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman iwl4965: fix rfkill set state regression commit b2fcc0aee58a3435566dd6d8501a0b355552f28b upstream. My current 3.11 fix: commit 788f7a56fce1bcb2067b62b851a086fca48a0056 Author: Stanislaw Gruszka Date: Thu Aug 1 12:07:55 2013 +0200 iwl4965: reset firmware after rfkill off broke rfkill notification to user-space . I missed that bug, because I compiled without CONFIG_RFKILL, sorry about that. Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman ACPI / EC: Add ASUSTEK L4R to quirk list in order to validate ECDT commit 524f42fab787a9510be826ce3d736b56d454ac6d upstream. The ECDT of ASUSTEK L4R doesn't provide correct command and data I/O ports. The DSDT provides the correct information instead. For this reason, add this machine to quirk list for ECDT validation and use the EC information from the DSDT. [rjw: Changelog] References: https://bugzilla.kernel.org/show_bug.cgi?id=60765 Reported-and-tested-by: Daniele Esposti Signed-off-by: Lan Tianyu Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman target: Fix trailing ASCII space usage in INQUIRY vendor+model commit ee60bddba5a5f23e39598195d944aa0eb2d455e5 upstream. This patch fixes spc_emulate_inquiry_std() to add trailing ASCII spaces for INQUIRY vendor + model fields following SPC-4 text: "ASCII data fields described as being left-aligned shall have any unused bytes at the end of the field (i.e., highest offset) and the unused bytes shall be filled with ASCII space characters (20h)." This addresses a problem with Falconstor NSS multipathing. Reported-by: Tomas Molota Signed-off-by: Nicholas Bellinger Signed-off-by: Greg Kroah-Hartman SCSI: sg: Fix user memory corruption when SG_IO is interrupted by a signal commit 35dc248383bbab0a7203fca4d722875bc81ef091 upstream. There is a nasty bug in the SCSI SG_IO ioctl that in some circumstances leads to one process writing data into the address space of some other random unrelated process if the ioctl is interrupted by a signal. What happens is the following: - A process issues an SG_IO ioctl with direction DXFER_FROM_DEV (ie the underlying SCSI command will transfer data from the SCSI device to the buffer provided in the ioctl) - Before the command finishes, a signal is sent to the process waiting in the ioctl. This will end up waking up the sg_ioctl() code: result = wait_event_interruptible(sfp->read_wait, (srp_done(sfp, srp) || sdp->detached)); but neither srp_done() nor sdp->detached is true, so we end up just setting srp->orphan and returning to userspace: srp->orphan = 1; write_unlock_irq(&sfp->rq_list_lock); return result; /* -ERESTARTSYS because signal hit process */ At this point the original process is done with the ioctl and blithely goes ahead handling the signal, reissuing the ioctl, etc. - Eventually, the SCSI command issued by the first ioctl finishes and ends up in sg_rq_end_io(). At the end of that function, we run through: write_lock_irqsave(&sfp->rq_list_lock, iflags); if (unlikely(srp->orphan)) { if (sfp->keep_orphan) srp->sg_io_owned = 0; else done = 0; } srp->done = done; write_unlock_irqrestore(&sfp->rq_list_lock, iflags); if (likely(done)) { /* Now wake up any sg_read() that is waiting for this * packet. */ wake_up_interruptible(&sfp->read_wait); kill_fasync(&sfp->async_qp, SIGPOLL, POLL_IN); kref_put(&sfp->f_ref, sg_remove_sfp); } else { INIT_WORK(&srp->ew.work, sg_rq_end_io_usercontext); schedule_work(&srp->ew.work); } Since srp->orphan *is* set, we set done to 0 (assuming the userspace app has not set keep_orphan via an SG_SET_KEEP_ORPHAN ioctl), and therefore we end up scheduling sg_rq_end_io_usercontext() to run in a workqueue. - In workqueue context we go through sg_rq_end_io_usercontext() -> sg_finish_rem_req() -> blk_rq_unmap_user() -> ... -> bio_uncopy_user() -> __bio_copy_iov() -> copy_to_user(). The key point here is that we are doing copy_to_user() on a workqueue -- that is, we're on a kernel thread with current->mm equal to whatever random previous user process was scheduled before this kernel thread. So we end up copying whatever data the SCSI command returned to the virtual address of the buffer passed into the original ioctl, but it's quite likely we do this copying into a different address space! As suggested by James Bottomley , add a check for current->mm (which is NULL if we're on a kernel thread without a real userspace address space) in bio_uncopy_user(), and skip the copy if we're on a kernel thread. There's no reason that I can think of for any caller of bio_uncopy_user() to want to do copying on a kernel thread with a random active userspace address space. Huge thanks to Costa Sapuntzakis for the original pointer to this bug in the sg code. Signed-off-by: Roland Dreier Tested-by: David Milburn Cc: Jens Axboe Signed-off-by: James Bottomley [lizf: backported to 3.4: - Use __bio_for_each_segment() instead of bio_for_each_segment_all()] Signed-off-by: Li Zefan Signed-off-by: Greg Kroah-Hartman --- Makefile | 2 +- arch/powerpc/Kconfig | 1 + arch/powerpc/include/asm/page.h | 10 ++++ drivers/acpi/ec.c | 4 ++ drivers/base/memory.c | 2 + drivers/base/regmap/regmap.c | 2 +- drivers/gpu/drm/i915/i915_reg.h | 2 +- drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c | 58 +++++++++++++------ drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 10 ++++ drivers/net/wireless/iwlegacy/4965-mac.c | 2 +- drivers/target/target_core_cdb.c | 9 ++- drivers/tty/hvc/hvsi_lib.c | 4 +- fs/bio.c | 20 +++++-- fs/jfs/jfs_dtree.c | 31 +++++++--- net/sunrpc/xdr.c | 9 ++- sound/isa/opti9xx/opti92x-ad1848.c | 8 +-- 16 files changed, 124 insertions(+), 50 deletions(-) diff --git a/Makefile b/Makefile index d15a9689027..efff231e759 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 4 -SUBLEVEL = 60 +SUBLEVEL = 61 EXTRAVERSION = NAME = Saber-toothed Squirrel diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index feab3bad6d0..b17dd693f74 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -979,6 +979,7 @@ config RELOCATABLE must live at a different physical address than the primary kernel. +# This value must have zeroes in the bottom 60 bits otherwise lots will break config PAGE_OFFSET hex default "0xc000000000000000" diff --git a/arch/powerpc/include/asm/page.h b/arch/powerpc/include/asm/page.h index f072e974f8a..2e6c4e5a88b 100644 --- a/arch/powerpc/include/asm/page.h +++ b/arch/powerpc/include/asm/page.h @@ -211,9 +211,19 @@ extern long long virt_phys_offset; #define __va(x) ((void *)(unsigned long)((phys_addr_t)(x) + VIRT_PHYS_OFFSET)) #define __pa(x) ((unsigned long)(x) - VIRT_PHYS_OFFSET) #else +#ifdef CONFIG_PPC64 +/* + * gcc miscompiles (unsigned long)(&static_var) - PAGE_OFFSET + * with -mcmodel=medium, so we use & and | instead of - and + on 64-bit. + */ +#define __va(x) ((void *)(unsigned long)((phys_addr_t)(x) | PAGE_OFFSET)) +#define __pa(x) ((unsigned long)(x) & 0x0fffffffffffffffUL) + +#else /* 32-bit, non book E */ #define __va(x) ((void *)(unsigned long)((phys_addr_t)(x) + PAGE_OFFSET - MEMORY_START)) #define __pa(x) ((unsigned long)(x) - PAGE_OFFSET + MEMORY_START) #endif +#endif /* * Unfortunately the PLT is in the BSS in the PPC32 ELF ABI, diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index 3251d4b4ac1..d1a967459fe 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -978,6 +978,10 @@ static struct dmi_system_id __initdata ec_dmi_table[] = { ec_skip_dsdt_scan, "HP Folio 13", { DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), DMI_MATCH(DMI_PRODUCT_NAME, "HP Folio 13"),}, NULL}, + { + ec_validate_ecdt, "ASUS hardware", { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTek Computer Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "L4R"),}, NULL}, {}, }; diff --git a/drivers/base/memory.c b/drivers/base/memory.c index 7dda4f790f0..d63a06be875 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c @@ -154,6 +154,8 @@ static ssize_t show_mem_removable(struct device *dev, container_of(dev, struct memory_block, dev); for (i = 0; i < sections_per_block; i++) { + if (!present_section_nr(mem->start_section_nr + i)) + continue; pfn = section_nr_to_pfn(mem->start_section_nr + i); ret &= is_mem_section_removable(pfn, PAGES_PER_SECTION); } diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index bb80853ff27..ca72d1f6728 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -69,7 +69,7 @@ bool regmap_precious(struct regmap *map, unsigned int reg) } static bool regmap_volatile_range(struct regmap *map, unsigned int reg, - unsigned int num) + size_t num) { unsigned int i; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index d0319325e39..6884d01cf1c 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -3741,7 +3741,7 @@ #define EDP_LINK_TRAIN_600MV_0DB_IVB (0x30 <<22) #define EDP_LINK_TRAIN_600MV_3_5DB_IVB (0x36 <<22) #define EDP_LINK_TRAIN_800MV_0DB_IVB (0x38 <<22) -#define EDP_LINK_TRAIN_800MV_3_5DB_IVB (0x33 <<22) +#define EDP_LINK_TRAIN_800MV_3_5DB_IVB (0x3e <<22) /* legacy values */ #define EDP_LINK_TRAIN_500MV_0DB_IVB (0x00 <<22) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c b/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c index 21ee7822656..e1978a2a498 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_gmr.c @@ -29,7 +29,9 @@ #include "drmP.h" #include "ttm/ttm_bo_driver.h" -#define VMW_PPN_SIZE sizeof(unsigned long) +#define VMW_PPN_SIZE (sizeof(unsigned long)) +/* A future safe maximum remap size. */ +#define VMW_PPN_PER_REMAP ((31 * 1024) / VMW_PPN_SIZE) static int vmw_gmr2_bind(struct vmw_private *dev_priv, struct page *pages[], @@ -38,43 +40,61 @@ static int vmw_gmr2_bind(struct vmw_private *dev_priv, { SVGAFifoCmdDefineGMR2 define_cmd; SVGAFifoCmdRemapGMR2 remap_cmd; - uint32_t define_size = sizeof(define_cmd) + 4; - uint32_t remap_size = VMW_PPN_SIZE * num_pages + sizeof(remap_cmd) + 4; uint32_t *cmd; uint32_t *cmd_orig; + uint32_t define_size = sizeof(define_cmd) + sizeof(*cmd); + uint32_t remap_num = num_pages / VMW_PPN_PER_REMAP + ((num_pages % VMW_PPN_PER_REMAP) > 0); + uint32_t remap_size = VMW_PPN_SIZE * num_pages + (sizeof(remap_cmd) + sizeof(*cmd)) * remap_num; + uint32_t remap_pos = 0; + uint32_t cmd_size = define_size + remap_size; uint32_t i; - cmd_orig = cmd = vmw_fifo_reserve(dev_priv, define_size + remap_size); + cmd_orig = cmd = vmw_fifo_reserve(dev_priv, cmd_size); if (unlikely(cmd == NULL)) return -ENOMEM; define_cmd.gmrId = gmr_id; define_cmd.numPages = num_pages; + *cmd++ = SVGA_CMD_DEFINE_GMR2; + memcpy(cmd, &define_cmd, sizeof(define_cmd)); + cmd += sizeof(define_cmd) / sizeof(*cmd); + + /* + * Need to split the command if there are too many + * pages that goes into the gmr. + */ + remap_cmd.gmrId = gmr_id; remap_cmd.flags = (VMW_PPN_SIZE > sizeof(*cmd)) ? SVGA_REMAP_GMR2_PPN64 : SVGA_REMAP_GMR2_PPN32; - remap_cmd.offsetPages = 0; - remap_cmd.numPages = num_pages; - *cmd++ = SVGA_CMD_DEFINE_GMR2; - memcpy(cmd, &define_cmd, sizeof(define_cmd)); - cmd += sizeof(define_cmd) / sizeof(uint32); + while (num_pages > 0) { + unsigned long nr = min(num_pages, (unsigned long)VMW_PPN_PER_REMAP); + + remap_cmd.offsetPages = remap_pos; + remap_cmd.numPages = nr; - *cmd++ = SVGA_CMD_REMAP_GMR2; - memcpy(cmd, &remap_cmd, sizeof(remap_cmd)); - cmd += sizeof(remap_cmd) / sizeof(uint32); + *cmd++ = SVGA_CMD_REMAP_GMR2; + memcpy(cmd, &remap_cmd, sizeof(remap_cmd)); + cmd += sizeof(remap_cmd) / sizeof(*cmd); - for (i = 0; i < num_pages; ++i) { - if (VMW_PPN_SIZE <= 4) - *cmd = page_to_pfn(*pages++); - else - *((uint64_t *)cmd) = page_to_pfn(*pages++); + for (i = 0; i < nr; ++i) { + if (VMW_PPN_SIZE <= 4) + *cmd = page_to_pfn(*pages++); + else + *((uint64_t *)cmd) = page_to_pfn(*pages++); - cmd += VMW_PPN_SIZE / sizeof(*cmd); + cmd += VMW_PPN_SIZE / sizeof(*cmd); + } + + num_pages -= nr; + remap_pos += nr; } - vmw_fifo_commit(dev_priv, define_size + remap_size); + BUG_ON(cmd != cmd_orig + cmd_size / sizeof(*cmd)); + + vmw_fifo_commit(dev_priv, cmd_size); return 0; } diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index 3e40a646151..b290a8ecfdb 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c @@ -448,6 +448,7 @@ static void ath9k_htc_tx_process(struct ath9k_htc_priv *priv, struct ieee80211_conf *cur_conf = &priv->hw->conf; bool txok; int slot; + int hdrlen, padsize; slot = strip_drv_header(priv, skb); if (slot < 0) { @@ -504,6 +505,15 @@ static void ath9k_htc_tx_process(struct ath9k_htc_priv *priv, ath9k_htc_tx_clear_slot(priv, slot); + /* Remove padding before handing frame back to mac80211 */ + hdrlen = ieee80211_get_hdrlen_from_skb(skb); + + padsize = hdrlen & 3; + if (padsize && skb->len > hdrlen + padsize) { + memmove(skb->data + padsize, skb->data, hdrlen); + skb_pull(skb, padsize); + } + /* Send status to mac80211 */ ieee80211_tx_status(priv->hw, skb); } diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c index 409ed06d5f5..3223daa07c9 100644 --- a/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/iwlegacy/4965-mac.c @@ -4415,9 +4415,9 @@ il4965_irq_tasklet(struct il_priv *il) set_bit(S_RFKILL, &il->status); } else { clear_bit(S_RFKILL, &il->status); - wiphy_rfkill_set_hw_state(il->hw->wiphy, hw_rf_kill); il_force_reset(il, true); } + wiphy_rfkill_set_hw_state(il->hw->wiphy, hw_rf_kill); handled |= CSR_INT_BIT_RF_KILL; } diff --git a/drivers/target/target_core_cdb.c b/drivers/target/target_core_cdb.c index 52a5f6208ac..2d88ce8025d 100644 --- a/drivers/target/target_core_cdb.c +++ b/drivers/target/target_core_cdb.c @@ -97,9 +97,12 @@ target_emulate_inquiry_std(struct se_cmd *cmd, char *buf) buf[7] = 0x2; /* CmdQue=1 */ - snprintf(&buf[8], 8, "LIO-ORG"); - snprintf(&buf[16], 16, "%s", dev->se_sub_dev->t10_wwn.model); - snprintf(&buf[32], 4, "%s", dev->se_sub_dev->t10_wwn.revision); + memcpy(&buf[8], "LIO-ORG ", 8); + memset(&buf[16], 0x20, 16); + memcpy(&buf[16], dev->se_sub_dev->t10_wwn.model, + min_t(size_t, strlen(dev->se_sub_dev->t10_wwn.model), 16)); + memcpy(&buf[32], dev->se_sub_dev->t10_wwn.revision, + min_t(size_t, strlen(dev->se_sub_dev->t10_wwn.revision), 4)); buf[4] = 31; /* Set additional length to 31 */ return 0; diff --git a/drivers/tty/hvc/hvsi_lib.c b/drivers/tty/hvc/hvsi_lib.c index 6f4dd83d869..3749688cc05 100644 --- a/drivers/tty/hvc/hvsi_lib.c +++ b/drivers/tty/hvc/hvsi_lib.c @@ -341,8 +341,8 @@ void hvsilib_establish(struct hvsi_priv *pv) pr_devel("HVSI@%x: ... waiting handshake\n", pv->termno); - /* Try for up to 200s */ - for (timeout = 0; timeout < 20; timeout++) { + /* Try for up to 400ms */ + for (timeout = 0; timeout < 40; timeout++) { if (pv->established) goto established; if (!hvsi_get_packet(pv)) diff --git a/fs/bio.c b/fs/bio.c index 84da8853904..c0e5a4e7c51 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -787,12 +787,22 @@ static int __bio_copy_iov(struct bio *bio, struct bio_vec *iovecs, int bio_uncopy_user(struct bio *bio) { struct bio_map_data *bmd = bio->bi_private; - int ret = 0; + struct bio_vec *bvec; + int ret = 0, i; - if (!bio_flagged(bio, BIO_NULL_MAPPED)) - ret = __bio_copy_iov(bio, bmd->iovecs, bmd->sgvecs, - bmd->nr_sgvecs, bio_data_dir(bio) == READ, - 0, bmd->is_our_pages); + if (!bio_flagged(bio, BIO_NULL_MAPPED)) { + /* + * if we're in a workqueue, the request is orphaned, so + * don't copy into a random user address space, just free. + */ + if (current->mm) + ret = __bio_copy_iov(bio, bmd->iovecs, bmd->sgvecs, + bmd->nr_sgvecs, bio_data_dir(bio) == READ, + 0, bmd->is_our_pages); + else if (bmd->is_our_pages) + __bio_for_each_segment(bvec, bio, i, 0) + __free_page(bvec->bv_page); + } bio_free_map_data(bmd); bio_put(bio); return ret; diff --git a/fs/jfs/jfs_dtree.c b/fs/jfs/jfs_dtree.c index 9197a1b0d02..b6f17c0b771 100644 --- a/fs/jfs/jfs_dtree.c +++ b/fs/jfs/jfs_dtree.c @@ -3047,6 +3047,14 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir) dir_index = (u32) filp->f_pos; + /* + * NFSv4 reserves cookies 1 and 2 for . and .. so we add + * the value we return to the vfs is one greater than the + * one we use internally. + */ + if (dir_index) + dir_index--; + if (dir_index > 1) { struct dir_table_slot dirtab_slot; @@ -3086,7 +3094,7 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir) if (p->header.flag & BT_INTERNAL) { jfs_err("jfs_readdir: bad index table"); DT_PUTPAGE(mp); - filp->f_pos = -1; + filp->f_pos = DIREND; return 0; } } else { @@ -3094,7 +3102,7 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir) /* * self "." */ - filp->f_pos = 0; + filp->f_pos = 1; if (filldir(dirent, ".", 1, 0, ip->i_ino, DT_DIR)) return 0; @@ -3102,7 +3110,7 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir) /* * parent ".." */ - filp->f_pos = 1; + filp->f_pos = 2; if (filldir(dirent, "..", 2, 1, PARENT(ip), DT_DIR)) return 0; @@ -3123,24 +3131,25 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir) /* * Legacy filesystem - OS/2 & Linux JFS < 0.3.6 * - * pn = index = 0: First entry "." - * pn = 0; index = 1: Second entry ".." + * pn = 0; index = 1: First entry "." + * pn = 0; index = 2: Second entry ".." * pn > 0: Real entries, pn=1 -> leftmost page * pn = index = -1: No more entries */ dtpos = filp->f_pos; - if (dtpos == 0) { + if (dtpos < 2) { /* build "." entry */ + filp->f_pos = 1; if (filldir(dirent, ".", 1, filp->f_pos, ip->i_ino, DT_DIR)) return 0; - dtoffset->index = 1; + dtoffset->index = 2; filp->f_pos = dtpos; } if (dtoffset->pn == 0) { - if (dtoffset->index == 1) { + if (dtoffset->index == 2) { /* build ".." entry */ if (filldir(dirent, "..", 2, filp->f_pos, @@ -3233,6 +3242,12 @@ int jfs_readdir(struct file *filp, void *dirent, filldir_t filldir) } jfs_dirent->position = unique_pos++; } + /* + * We add 1 to the index because we may + * use a value of 2 internally, and NFSv4 + * doesn't like that. + */ + jfs_dirent->position++; } else { jfs_dirent->position = dtpos; len = min(d_namleft, DTLHDRDATALEN_LEGACY); diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c index a95081721c2..4549c2ca9fb 100644 --- a/net/sunrpc/xdr.c +++ b/net/sunrpc/xdr.c @@ -233,10 +233,13 @@ _shift_data_right_pages(struct page **pages, size_t pgto_base, pgfrom_base -= copy; vto = kmap_atomic(*pgto); - vfrom = kmap_atomic(*pgfrom); - memmove(vto + pgto_base, vfrom + pgfrom_base, copy); + if (*pgto != *pgfrom) { + vfrom = kmap_atomic(*pgfrom); + memcpy(vto + pgto_base, vfrom + pgfrom_base, copy); + kunmap_atomic(vfrom); + } else + memmove(vto + pgto_base, vto + pgfrom_base, copy); flush_dcache_page(*pgto); - kunmap_atomic(vfrom); kunmap_atomic(vto); } while ((len -= copy) != 0); diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c index d7ccf28bd66..4589acd82c1 100644 --- a/sound/isa/opti9xx/opti92x-ad1848.c +++ b/sound/isa/opti9xx/opti92x-ad1848.c @@ -173,11 +173,7 @@ MODULE_DEVICE_TABLE(pnp_card, snd_opti9xx_pnpids); #endif /* CONFIG_PNP */ -#ifdef OPTi93X -#define DEV_NAME "opti93x" -#else -#define DEV_NAME "opti92x" -#endif +#define DEV_NAME KBUILD_MODNAME static char * snd_opti9xx_names[] = { "unknown", @@ -1126,7 +1122,7 @@ static void __devexit snd_opti9xx_pnp_remove(struct pnp_card_link * pcard) static struct pnp_card_driver opti9xx_pnpc_driver = { .flags = PNP_DRIVER_RES_DISABLE, - .name = "opti9xx", + .name = DEV_NAME, .id_table = snd_opti9xx_pnpids, .probe = snd_opti9xx_pnp_probe, .remove = __devexit_p(snd_opti9xx_pnp_remove), From c7030316f0dc6e70a70d856ae423d651729dbda3 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Thu, 1 Aug 2013 22:32:07 -0700 Subject: [PATCH 130/215] htb: fix sign extension bug [ Upstream commit cbd375567f7e4811b1c721f75ec519828ac6583f ] When userspace passes a large priority value the assignment of the unsigned value hopt->prio to signed int cl->prio causes cl->prio to become negative and the comparison is with TC_HTB_NUMPRIO is always false. The result is that HTB crashes by referencing outside the array when processing packets. With this patch the large value wraps around like other values outside the normal range. See: https://bugzilla.kernel.org/show_bug.cgi?id=60669 Signed-off-by: Stephen Hemminger Acked-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- net/sched/sch_htb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index f08b9166119..caa5affa4b2 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c @@ -86,7 +86,7 @@ struct htb_class { unsigned int children; struct htb_class *parent; /* parent class */ - int prio; /* these two are used only by leaves... */ + u32 prio; /* these two are used only by leaves... */ int quantum; /* but stored for parent-to-leaf return */ union { From 461857df1f715c468c3814ee72b0d33b42f3ca7c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 14 Sep 2013 06:02:37 -0700 Subject: [PATCH 131/215] Linux 3.4.62 - commits squashed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit net: check net.core.somaxconn sysctl values [ Upstream commit 5f671d6b4ec3e6d66c2a868738af2cdea09e7509 ] It's possible to assign an invalid value to the net.core.somaxconn sysctl variable, because there is no checks at all. The sk_max_ack_backlog field of the sock structure is defined as unsigned short. Therefore, the backlog argument in inet_listen() shouldn't exceed USHRT_MAX. The backlog argument in the listen() syscall is truncated to the somaxconn value. So, the somaxconn value shouldn't exceed 65535 (USHRT_MAX). Also, negative values of somaxconn are meaningless. before: $ sysctl -w net.core.somaxconn=256 net.core.somaxconn = 256 $ sysctl -w net.core.somaxconn=65536 net.core.somaxconn = 65536 $ sysctl -w net.core.somaxconn=-100 net.core.somaxconn = -100 after: $ sysctl -w net.core.somaxconn=256 net.core.somaxconn = 256 $ sysctl -w net.core.somaxconn=65536 error: "Invalid argument" setting key "net.core.somaxconn" $ sysctl -w net.core.somaxconn=-100 error: "Invalid argument" setting key "net.core.somaxconn" Based on a prior patch from Changli Gao. Signed-off-by: Roman Gushchin Reported-by: Changli Gao Suggested-by: Eric Dumazet Acked-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman neighbour: populate neigh_parms on alloc before calling ndo_neigh_setup [ Upstream commit 63134803a6369dcf7dddf7f0d5e37b9566b308d2 ] dev->ndo_neigh_setup() might need some of the values of neigh_parms, so populate them before calling it. Signed-off-by: Veaceslav Falico Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman bonding: modify only neigh_parms owned by us [ Upstream commit 9918d5bf329d0dc5bb2d9d293bcb772bdb626e65 ] Otherwise, on neighbour creation, bond_neigh_init() will be called with a foreign netdev. Signed-off-by: Veaceslav Falico Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman fib_trie: remove potential out of bound access [ Upstream commit aab515d7c32a34300312416c50314e755ea6f765 ] AddressSanitizer [1] dynamic checker pointed a potential out of bound access in leaf_walk_rcu() We could allocate one more slot in tnode_new() to leave the prefetch() in-place but it looks not worth the pain. Bug added in commit 82cfbb008572b ("[IPV4] fib_trie: iterator recode") [1] : https://code.google.com/p/address-sanitizer/wiki/AddressSanitizerForKernel Reported-by: Andrey Konovalov Signed-off-by: Eric Dumazet Cc: Dmitry Vyukov Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman tcp: cubic: fix overflow error in bictcp_update() [ Upstream commit 2ed0edf9090bf4afa2c6fc4f38575a85a80d4b20 ] commit 17a6e9f1aa9 ("tcp_cubic: fix clock dependency") added an overflow error in bictcp_update() in following code : /* change the unit from HZ to bictcp_HZ */ t = ((tcp_time_stamp + msecs_to_jiffies(ca->delay_min>>3) - ca->epoch_start) << BICTCP_HZ) / HZ; Because msecs_to_jiffies() being unsigned long, compiler does implicit type promotion. We really want to constrain (tcp_time_stamp - ca->epoch_start) to a signed 32bit value, or else 't' has unexpected high values. This bugs triggers an increase of retransmit rates ~24 days after boot [1], as the high order bit of tcp_time_stamp flips. [1] for hosts with HZ=1000 Big thanks to Van Jacobson for spotting this problem. Diagnosed-by: Van Jacobson Signed-off-by: Eric Dumazet Cc: Neal Cardwell Cc: Yuchung Cheng Cc: Stephen Hemminger Acked-by: Neal Cardwell Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman tcp: cubic: fix bug in bictcp_acked() [ Upstream commit cd6b423afd3c08b27e1fed52db828ade0addbc6b ] While investigating about strange increase of retransmit rates on hosts ~24 days after boot, Van found hystart was disabled if ca->epoch_start was 0, as following condition is true when tcp_time_stamp high order bit is set. (s32)(tcp_time_stamp - ca->epoch_start) < HZ Quoting Van : At initialization & after every loss ca->epoch_start is set to zero so I believe that the above line will turn off hystart as soon as the 2^31 bit is set in tcp_time_stamp & hystart will stay off for 24 days. I think we've observed that cubic's restart is too aggressive without hystart so this might account for the higher drop rate we observe. Diagnosed-by: Van Jacobson Signed-off-by: Eric Dumazet Cc: Neal Cardwell Cc: Yuchung Cheng Acked-by: Neal Cardwell Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman ipv6: don't stop backtracking in fib6_lookup_1 if subtree does not match [ Upstream commit 3e3be275851bc6fc90bfdcd732cd95563acd982b ] In case a subtree did not match we currently stop backtracking and return NULL (root table from fib_lookup). This could yield in invalid routing table lookups when using subtrees. Instead continue to backtrack until a valid subtree or node is found and return this match. Also remove unneeded NULL check. Reported-by: Teco Boot Cc: YOSHIFUJI Hideaki Cc: David Lamparter Cc: Signed-off-by: Hannes Frederic Sowa Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman 8139cp: Fix skb leak in rx_status_loop failure path. [ Upstream commit d06f5187469eee1b2932c02fd093d113cfc60d5e ] Introduced in cf3c4c03060b688cbc389ebc5065ebcce5653e96 ("8139cp: Add dma_mapping_error checking") Signed-off-by: Dave Jones Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman tun: signedness bug in tun_get_user() [ Upstream commit 15718ea0d844e4816dbd95d57a8a0e3e264ba90e ] The recent fix d9bf5f1309 "tun: compare with 0 instead of total_len" is not totally correct. Because "len" and "sizeof()" are size_t type, that means they are never less than zero. Signed-off-by: Dan Carpenter Acked-by: Michael S. Tsirkin Acked-by: Neil Horman Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman ipv6: remove max_addresses check from ipv6_create_tempaddr [ Upstream commit 4b08a8f1bd8cb4541c93ec170027b4d0782dab52 ] Because of the max_addresses check attackers were able to disable privacy extensions on an interface by creating enough autoconfigured addresses: But the check is not actually needed: max_addresses protects the kernel to install too many ipv6 addresses on an interface and guards addrconf_prefix_rcv to install further addresses as soon as this limit is reached. We only generate temporary addresses in direct response of a new address showing up. As soon as we filled up the maximum number of addresses of an interface, we stop installing more addresses and thus also stop generating more temp addresses. Even if the attacker tries to generate a lot of temporary addresses by announcing a prefix and removing it again (lifetime == 0) we won't install more temp addresses, because the temporary addresses do count to the maximum number of addresses, thus we would stop installing new autoconfigured addresses when the limit is reached. This patch fixes CVE-2013-0343 (but other layer-2 attacks are still possible). Thanks to Ding Tianhong to bring this topic up again. Signed-off-by: Hannes Frederic Sowa Cc: Ding Tianhong Cc: George Kargiotakis Cc: P J P Cc: YOSHIFUJI Hideaki Acked-by: Ding Tianhong Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman ipv6: drop packets with multiple fragmentation headers [ Upstream commit f46078cfcd77fa5165bf849f5e568a7ac5fa569c ] It is not allowed for an ipv6 packet to contain multiple fragmentation headers. So discard packets which were already reassembled by fragmentation logic and send back a parameter problem icmp. The updates for RFC 6980 will come in later, I have to do a bit more research here. Cc: YOSHIFUJI Hideaki Signed-off-by: Hannes Frederic Sowa Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman ipv6: Don't depend on per socket memory for neighbour discovery messages [ Upstream commit 25a6e6b84fba601eff7c28d30da8ad7cfbef0d43 ] Allocating skbs when sending out neighbour discovery messages currently uses sock_alloc_send_skb() based on a per net namespace socket and thus share a socket wmem buffer space. If a netdevice is temporarily unable to transmit due to carrier loss or for other reasons, the queued up ndisc messages will cosnume all of the wmem space and will thus prevent from any more skbs to be allocated even for netdevices that are able to transmit packets. The number of neighbour discovery messages sent is very limited, use of alloc_skb() bypasses the socket wmem buffer size enforcement while the manual call to skb_set_owner_w() maintains the socket reference needed for the IPv6 output path. This patch has orginally been posted by Eric Dumazet in a modified form. Signed-off-by: Thomas Graf Cc: Eric Dumazet Cc: Hannes Frederic Sowa Cc: Stephen Warren Cc: Fabio Estevam Tested-by: Fabio Estevam Tested-by: Stephen Warren Acked-by: Hannes Frederic Sowa Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman net: bridge: convert MLDv2 Query MRC into msecs_to_jiffies for max_delay [ Upstream commit 2d98c29b6fb3de44d9eaa73c09f9cf7209346383 ] While looking into MLDv1/v2 code, I noticed that bridging code does not convert it's max delay into jiffies for MLDv2 messages as we do in core IPv6' multicast code. RFC3810, 5.1.3. Maximum Response Code says: The Maximum Response Code field specifies the maximum time allowed before sending a responding Report. The actual time allowed, called the Maximum Response Delay, is represented in units of milliseconds, and is derived from the Maximum Response Code as follows: [...] As we update timers that work with jiffies, we need to convert it. Signed-off-by: Daniel Borkmann Cc: Linus Lüssing Cc: Hannes Frederic Sowa Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman ICMPv6: treat dest unreachable codes 5 and 6 as EACCES, not EPROTO [ Upstream commit 61e76b178dbe7145e8d6afa84bb4ccea71918994 ] RFC 4443 has defined two additional codes for ICMPv6 type 1 (destination unreachable) messages: 5 - Source address failed ingress/egress policy 6 - Reject route to destination Now they are treated as protocol error and icmpv6_err_convert() converts them to EPROTO. RFC 4443 says: "Codes 5 and 6 are more informative subsets of code 1." Treat codes 5 and 6 as code 1 (EACCES) Btw, connect() returning -EPROTO confuses firefox, so that fallback to other/IPv4 addresses does not work: https://bugzilla.mozilla.org/show_bug.cgi?id=910773 Signed-off-by: Jiri Bohac Acked-by: Hannes Frederic Sowa Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman net: ipv6: tcp: fix potential use after free in tcp_v6_do_rcv [ Upstream commit 3a1c756590633c0e86df606e5c618c190926a0df ] In tcp_v6_do_rcv() code, when processing pkt options, we soley work on our skb clone opt_skb that we've created earlier before entering tcp_rcv_established() on our way. However, only in condition ... if (np->rxopt.bits.rxtclass) np->rcv_tclass = ipv6_get_dsfield(ipv6_hdr(skb)); ... we work on skb itself. As we extract every other information out of opt_skb in ipv6_pktoptions path, this seems wrong, since skb can already be released by tcp_rcv_established() earlier on. When we try to access it in ipv6_hdr(), we will dereference freed skb. [ Bug added by commit 4c507d2897bd9b ("net: implement IP_RECVTOS for IP_PKTOPTIONS") ] Signed-off-by: Daniel Borkmann Cc: Eric Dumazet Acked-by: Eric Dumazet Acked-by: Jiri Benc Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman vhost: zerocopy: poll vq in zerocopy callback commit c70aa540c7a9f67add11ad3161096fb95233aa2e upstream. We add used and signal guest in worker thread but did not poll the virtqueue during the zero copy callback. This may lead the missing of adding and signalling during zerocopy. Solve this by polling the virtqueue and let it wakeup the worker during callback. Signed-off-by: Jason Wang Signed-off-by: Michael S. Tsirkin Signed-off-by: Greg Kroah-Hartman macvtap: do not zerocopy if iov needs more pages than MAX_SKB_FRAGS commit ece793fcfc417b3925844be88a6a6dc82ae8f7c6 upstream. We try to linearize part of the skb when the number of iov is greater than MAX_SKB_FRAGS. This is not enough since each single vector may occupy more than one pages, so zerocopy_sg_fromiovec() may still fail and may break the guest network. Solve this problem by calculate the pages needed for iov before trying to do zerocopy and switch to use copy instead of zerocopy if it needs more than MAX_SKB_FRAGS. This is done through introducing a new helper to count the pages for iov, and call uarg->callback() manually when switching from zerocopy to copy to notify vhost. We can do further optimization on top. This bug were introduced from b92946e2919134ebe2a4083e4302236295ea2a73 (macvtap: zerocopy: validate vectors before building skb). Cc: Michael S. Tsirkin Signed-off-by: Jason Wang Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman tipc: fix lockdep warning during bearer initialization [ Upstream commit 4225a398c1352a7a5c14dc07277cb5cc4473983b ] When the lockdep validator is enabled, it will report the below warning when we enable a TIPC bearer: [ INFO: possible irq lock inversion dependency detected ] --------------------------------------------------------- Possible interrupt unsafe locking scenario: CPU0 CPU1 ---- ---- lock(ptype_lock); local_irq_disable(); lock(tipc_net_lock); lock(ptype_lock); lock(tipc_net_lock); *** DEADLOCK *** the shortest dependencies between 2nd lock and 1st lock: -> (ptype_lock){+.+...} ops: 10 { [...] SOFTIRQ-ON-W at: [] __lock_acquire+0x528/0x13e0 [] lock_acquire+0x90/0x100 [] _raw_spin_lock+0x38/0x50 [] dev_add_pack+0x3a/0x60 [] arp_init+0x1a/0x48 [] inet_init+0x181/0x27e [] do_one_initcall+0x34/0x170 [] kernel_init+0x110/0x1b2 [] kernel_thread_helper+0x6/0x10 [...] ... key at: [] ptype_lock+0x10/0x20 ... acquired at: [] lock_acquire+0x90/0x100 [] _raw_spin_lock+0x38/0x50 [] dev_add_pack+0x3a/0x60 [] enable_bearer+0xf2/0x140 [tipc] [] tipc_enable_bearer+0x1ba/0x450 [tipc] [] tipc_cfg_do_cmd+0x5c4/0x830 [tipc] [] handle_cmd+0x42/0xd0 [tipc] [] genl_rcv_msg+0x232/0x280 [] netlink_rcv_skb+0x86/0xb0 [] genl_rcv+0x1c/0x30 [] netlink_unicast+0x174/0x1f0 [] netlink_sendmsg+0x1eb/0x2d0 [] sock_aio_write+0x161/0x170 [] do_sync_write+0xac/0xf0 [] vfs_write+0x156/0x170 [] sys_write+0x42/0x70 [] sysenter_do_call+0x12/0x38 [...] } -> (tipc_net_lock){+..-..} ops: 4 { [...] IN-SOFTIRQ-R at: [] __lock_acquire+0x64a/0x13e0 [] lock_acquire+0x90/0x100 [] _raw_read_lock_bh+0x3d/0x50 [] tipc_recv_msg+0x1d/0x830 [tipc] [] recv_msg+0x3f/0x50 [tipc] [] __netif_receive_skb+0x22a/0x590 [] netif_receive_skb+0x2b/0xf0 [] pcnet32_poll+0x292/0x780 [] net_rx_action+0xfa/0x1e0 [] __do_softirq+0xae/0x1e0 [...] } >From the log, we can see three different call chains between CPU0 and CPU1: Time 0 on CPU0: kernel_init()->inet_init()->dev_add_pack() At time 0, the ptype_lock is held by CPU0 in dev_add_pack(); Time 1 on CPU1: tipc_enable_bearer()->enable_bearer()->dev_add_pack() At time 1, tipc_enable_bearer() first holds tipc_net_lock, and then wants to take ptype_lock to register TIPC protocol handler into the networking stack. But the ptype_lock has been taken by dev_add_pack() on CPU0, so at this time the dev_add_pack() running on CPU1 has to be busy looping. Time 2 on CPU0: netif_receive_skb()->recv_msg()->tipc_recv_msg() At time 2, an incoming TIPC packet arrives at CPU0, hence tipc_recv_msg() will be invoked. In tipc_recv_msg(), it first wants to hold tipc_net_lock. At the moment, below scenario happens: On CPU0, below is our sequence of taking locks: lock(ptype_lock)->lock(tipc_net_lock) On CPU1, our sequence of taking locks looks like: lock(tipc_net_lock)->lock(ptype_lock) Obviously deadlock may happen in this case. But please note the deadlock possibly doesn't occur at all when the first TIPC bearer is enabled. Before enable_bearer() -- running on CPU1 does not hold ptype_lock, so the TIPC receive handler (i.e. recv_msg()) is not registered successfully via dev_add_pack(), so the tipc_recv_msg() cannot be called by recv_msg() even if a TIPC message comes to CPU0. But when the second TIPC bearer is registered, the deadlock can perhaps really happen. To fix it, we will push the work of registering TIPC protocol handler into workqueue context. After the change, both paths taking ptype_lock are always in process contexts, thus, the deadlock should never occur. Signed-off-by: Ying Xue Signed-off-by: Jon Maloy Signed-off-by: Paul Gortmaker Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman m32r: consistently use "suffix-$(...)" commit df12aef6a19bb2d69859a94936bda0e6ccaf3327 upstream. Commit a556bec9955c ("m32r: fix arch/m32r/boot/compressed/Makefile") changed "$(suffix_y)" to "$(suffix-y)", but didn't update any location where "suffix_y" is set, causing: make[5]: *** No rule to make target `arch/m32r/boot/compressed/vmlinux.bin.', needed by `arch/m32r/boot/compressed/piggy.o'. Stop. make[4]: *** [arch/m32r/boot/compressed/vmlinux] Error 2 make[3]: *** [zImage] Error 2 Correct the other locations to fix this. Signed-off-by: Geert Uytterhoeven Cc: Hirokazu Takata Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Cc: Ben Hutchings Signed-off-by: Greg Kroah-Hartman m32r: add memcpy() for CONFIG_KERNEL_GZIP=y commit a8abbca6617e1caa2344d2d38d0a35f3e5928b79 upstream. Fix the m32r link error: LD arch/m32r/boot/compressed/vmlinux arch/m32r/boot/compressed/misc.o: In function `zlib_updatewindow': misc.c:(.text+0x190): undefined reference to `memcpy' misc.c:(.text+0x190): relocation truncated to fit: R_M32R_26_PLTREL against undefined symbol `memcpy' make[5]: *** [arch/m32r/boot/compressed/vmlinux] Error 1 by adding our own implementation of memcpy(). Signed-off-by: Geert Uytterhoeven Cc: Hirokazu Takata Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Cc: Ben Hutchings Signed-off-by: Greg Kroah-Hartman m32r: make memset() global for CONFIG_KERNEL_BZIP2=y commit 9a75c6e5240f7edc5955e8da5b94bde6f96070b3 upstream. Fix the m32r compile error: arch/m32r/boot/compressed/misc.c:31:14: error: static declaration of 'memset' follows non-static declaration make[5]: *** [arch/m32r/boot/compressed/misc.o] Error 1 make[4]: *** [arch/m32r/boot/compressed/vmlinux] Error 2 by removing the static keyword. Signed-off-by: Geert Uytterhoeven Cc: Hirokazu Takata Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Cc: Ben Hutchings Signed-off-by: Greg Kroah-Hartman Revert "KVM: X86 emulator: fix source operand decoding for 8bit mov[zs]x instructions" This reverts commit 5b5b30580218eae22609989546bac6e44d0eda6e, which was commit 660696d1d16a71e15549ce1bf74953be1592bcd3 upstream. Paul Gortmaker writes: [this patch] introduces the following: arch/x86/kvm/emulate.c: In function ‘decode_operand’: arch/x86/kvm/emulate.c:3974:4: warning: passing argument 1 of ‘decode_register’ makes integer from pointer +without a cast [enabled by default] arch/x86/kvm/emulate.c:789:14: note: expected ‘u8’ but argument is of type ‘struct x86_emulate_ctxt *’ arch/x86/kvm/emulate.c:3974:4: warning: passing argument 2 of ‘decode_register’ makes pointer from integer +without a cast [enabled by default] arch/x86/kvm/emulate.c:789:14: note: expected ‘long unsigned int *’ but argument is of type ‘u8’ Based on the severity of the warnings above, I'm reasonably sure there will be some kind of runtime regressions due to this, but I stopped to investigate the warnings as soon as I saw them, before any run time testing. It happens because mainline v3.7-rc1~113^2~40 (dd856efafe60) does this: -static void *decode_register(u8 modrm_reg, unsigned long *regs, +static void *decode_register(struct x86_emulate_ctxt *ctxt, u8 modrm_reg, Since 660696d1d16a71e1 was only applied to stable 3.4, 3.8, and 3.9 -- and the prerequisite above is in 3.7+, the issue should be limited to 3.4.44+ Reported-by: Paul Gortmaker Acked-by: Paolo Bonzini Cc: Gleb Natapov Signed-off-by: Greg Kroah-Hartman --- Makefile | 2 +- arch/m32r/boot/compressed/Makefile | 6 +-- arch/m32r/boot/compressed/misc.c | 12 +++++- arch/x86/kvm/emulate.c | 4 -- drivers/net/bonding/bond_main.c | 8 +++- drivers/net/ethernet/realtek/8139cp.c | 1 + drivers/net/macvtap.c | 62 ++++++++++++++++----------- drivers/net/tun.c | 6 ++- drivers/vhost/vhost.c | 1 + include/linux/icmpv6.h | 2 + include/linux/ipv6.h | 1 + net/bridge/br_multicast.c | 3 +- net/core/neighbour.c | 10 +++-- net/core/sysctl_net_core.c | 7 ++- net/ipv4/fib_trie.c | 5 +-- net/ipv4/tcp_cubic.c | 12 +++--- net/ipv6/addrconf.c | 10 ++--- net/ipv6/icmp.c | 10 ++++- net/ipv6/ip6_fib.c | 16 +++++-- net/ipv6/ndisc.c | 16 ++++--- net/ipv6/reassembly.c | 5 +++ net/ipv6/tcp_ipv6.c | 2 +- net/tipc/eth_media.c | 15 ++++++- 23 files changed, 144 insertions(+), 72 deletions(-) diff --git a/Makefile b/Makefile index efff231e759..9aba296cf68 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 4 -SUBLEVEL = 61 +SUBLEVEL = 62 EXTRAVERSION = NAME = Saber-toothed Squirrel diff --git a/arch/m32r/boot/compressed/Makefile b/arch/m32r/boot/compressed/Makefile index 177716b1d61..01729c2979b 100644 --- a/arch/m32r/boot/compressed/Makefile +++ b/arch/m32r/boot/compressed/Makefile @@ -43,9 +43,9 @@ endif OBJCOPYFLAGS += -R .empty_zero_page -suffix_$(CONFIG_KERNEL_GZIP) = gz -suffix_$(CONFIG_KERNEL_BZIP2) = bz2 -suffix_$(CONFIG_KERNEL_LZMA) = lzma +suffix-$(CONFIG_KERNEL_GZIP) = gz +suffix-$(CONFIG_KERNEL_BZIP2) = bz2 +suffix-$(CONFIG_KERNEL_LZMA) = lzma $(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.$(suffix-y) FORCE $(call if_changed,ld) diff --git a/arch/m32r/boot/compressed/misc.c b/arch/m32r/boot/compressed/misc.c index 370d6088197..28a09529f20 100644 --- a/arch/m32r/boot/compressed/misc.c +++ b/arch/m32r/boot/compressed/misc.c @@ -28,7 +28,7 @@ static unsigned long free_mem_ptr; static unsigned long free_mem_end_ptr; #ifdef CONFIG_KERNEL_BZIP2 -static void *memset(void *s, int c, size_t n) +void *memset(void *s, int c, size_t n) { char *ss = s; @@ -39,6 +39,16 @@ static void *memset(void *s, int c, size_t n) #endif #ifdef CONFIG_KERNEL_GZIP +void *memcpy(void *dest, const void *src, size_t n) +{ + char *d = dest; + const char *s = src; + while (n--) + *d++ = *s++; + + return dest; +} + #define BOOT_HEAP_SIZE 0x10000 #include "../../../../lib/decompress_inflate.c" #endif diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 8c45818c732..83756223f8a 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -3737,10 +3737,6 @@ static int decode_operand(struct x86_emulate_ctxt *ctxt, struct operand *op, break; case OpMem8: ctxt->memop.bytes = 1; - if (ctxt->memop.type == OP_REG) { - ctxt->memop.addr.reg = decode_register(ctxt, ctxt->modrm_rm, 1); - fetch_register_operand(&ctxt->memop); - } goto mem_common; case OpMem16: ctxt->memop.bytes = 2; diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index d9f83582997..80103bb47ca 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -3750,11 +3750,17 @@ static int bond_neigh_init(struct neighbour *n) * The bonding ndo_neigh_setup is called at init time beofre any * slave exists. So we must declare proxy setup function which will * be used at run time to resolve the actual slave neigh param setup. + * + * It's also called by master devices (such as vlans) to setup their + * underlying devices. In that case - do nothing, we're already set up from + * our init. */ static int bond_neigh_setup(struct net_device *dev, struct neigh_parms *parms) { - parms->neigh_setup = bond_neigh_init; + /* modify only our neigh_parms */ + if (parms->dev == dev) + parms->neigh_setup = bond_neigh_init; return 0; } diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c index 2205db73bc5..1b4404725b8 100644 --- a/drivers/net/ethernet/realtek/8139cp.c +++ b/drivers/net/ethernet/realtek/8139cp.c @@ -524,6 +524,7 @@ static int cp_rx_poll(struct napi_struct *napi, int budget) PCI_DMA_FROMDEVICE); if (dma_mapping_error(&cp->pdev->dev, new_mapping)) { dev->stats.rx_dropped++; + kfree_skb(new_skb); goto rx_next; } diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index 5151f06c59c..77ce8b2bee6 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -642,6 +642,28 @@ static int macvtap_skb_to_vnet_hdr(const struct sk_buff *skb, return 0; } +static unsigned long iov_pages(const struct iovec *iv, int offset, + unsigned long nr_segs) +{ + unsigned long seg, base; + int pages = 0, len, size; + + while (nr_segs && (offset >= iv->iov_len)) { + offset -= iv->iov_len; + ++iv; + --nr_segs; + } + + for (seg = 0; seg < nr_segs; seg++) { + base = (unsigned long)iv[seg].iov_base + offset; + len = iv[seg].iov_len - offset; + size = ((base & ~PAGE_MASK) + len + ~PAGE_MASK) >> PAGE_SHIFT; + pages += size; + offset = 0; + } + + return pages; +} /* Get packet from user space buffer */ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, @@ -688,31 +710,15 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, if (unlikely(count > UIO_MAXIOV)) goto err; - if (m && m->msg_control && sock_flag(&q->sk, SOCK_ZEROCOPY)) - zerocopy = true; - - if (zerocopy) { - /* Userspace may produce vectors with count greater than - * MAX_SKB_FRAGS, so we need to linearize parts of the skb - * to let the rest of data to be fit in the frags. - */ - if (count > MAX_SKB_FRAGS) { - copylen = iov_length(iv, count - MAX_SKB_FRAGS); - if (copylen < vnet_hdr_len) - copylen = 0; - else - copylen -= vnet_hdr_len; - } - /* There are 256 bytes to be copied in skb, so there is enough - * room for skb expand head in case it is used. - * The rest buffer is mapped from userspace. - */ - if (copylen < vnet_hdr.hdr_len) - copylen = vnet_hdr.hdr_len; - if (!copylen) - copylen = GOODCOPY_LEN; + if (m && m->msg_control && sock_flag(&q->sk, SOCK_ZEROCOPY)) { + copylen = vnet_hdr.hdr_len ? vnet_hdr.hdr_len : GOODCOPY_LEN; linear = copylen; - } else { + if (iov_pages(iv, vnet_hdr_len + copylen, count) + <= MAX_SKB_FRAGS) + zerocopy = true; + } + + if (!zerocopy) { copylen = len; linear = vnet_hdr.hdr_len; } @@ -724,9 +730,15 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m, if (zerocopy) err = zerocopy_sg_from_iovec(skb, iv, vnet_hdr_len, count); - else + else { err = skb_copy_datagram_from_iovec(skb, 0, iv, vnet_hdr_len, len); + if (!err && m && m->msg_control) { + struct ubuf_info *uarg = m->msg_control; + uarg->callback(uarg); + } + } + if (err) goto err_kfree; diff --git a/drivers/net/tun.c b/drivers/net/tun.c index dd2f8210ec1..b463b84dcd6 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -615,8 +615,9 @@ static ssize_t tun_get_user(struct tun_struct *tun, int offset = 0; if (!(tun->flags & TUN_NO_PI)) { - if ((len -= sizeof(pi)) > count) + if (len < sizeof(pi)) return -EINVAL; + len -= sizeof(pi); if (memcpy_fromiovecend((void *)&pi, iv, 0, sizeof(pi))) return -EFAULT; @@ -624,8 +625,9 @@ static ssize_t tun_get_user(struct tun_struct *tun, } if (tun->flags & TUN_VNET_HDR) { - if ((len -= tun->vnet_hdr_sz) > count) + if (len < tun->vnet_hdr_sz) return -EINVAL; + len -= tun->vnet_hdr_sz; if (memcpy_fromiovecend((void *)&gso, iv, offset, sizeof(gso))) return -EFAULT; diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index 1a9e2a9b856..a50cb9c28f7 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -1603,6 +1603,7 @@ void vhost_zerocopy_callback(struct ubuf_info *ubuf) struct vhost_ubuf_ref *ubufs = ubuf->ctx; struct vhost_virtqueue *vq = ubufs->vq; + vhost_poll_queue(&vq->poll); /* set len = 1 to mark this desc buffers done DMA */ vq->heads[ubuf->desc].len = VHOST_DMA_DONE_LEN; kref_put(&ubufs->kref, vhost_zerocopy_done_signal); diff --git a/include/linux/icmpv6.h b/include/linux/icmpv6.h index ba45e6bc076..f5a21d0a22b 100644 --- a/include/linux/icmpv6.h +++ b/include/linux/icmpv6.h @@ -123,6 +123,8 @@ static inline struct icmp6hdr *icmp6_hdr(const struct sk_buff *skb) #define ICMPV6_NOT_NEIGHBOUR 2 #define ICMPV6_ADDR_UNREACH 3 #define ICMPV6_PORT_UNREACH 4 +#define ICMPV6_POLICY_FAIL 5 +#define ICMPV6_REJECT_ROUTE 6 /* * Codes for Time Exceeded diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h index 8260ef77976..e6412ee0a76 100644 --- a/include/linux/ipv6.h +++ b/include/linux/ipv6.h @@ -260,6 +260,7 @@ struct inet6_skb_parm { #define IP6SKB_XFRM_TRANSFORMED 1 #define IP6SKB_FORWARDED 2 #define IP6SKB_REROUTED 4 +#define IP6SKB_FRAGMENTED 16 }; #define IP6CB(skb) ((struct inet6_skb_parm*)((skb)->cb)) diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 9069071b68b..ca670d96bae 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -1155,7 +1155,8 @@ static int br_ip6_multicast_query(struct net_bridge *br, mld2q = (struct mld2_query *)icmp6_hdr(skb); if (!mld2q->mld2q_nsrcs) group = &mld2q->mld2q_mca; - max_delay = mld2q->mld2q_mrc ? MLDV2_MRC(mld2q->mld2q_mrc) : 1; + + max_delay = max(msecs_to_jiffies(MLDV2_MRC(ntohs(mld2q->mld2q_mrc))), 1UL); } if (!group) diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 69b7ca35c46..ebd4b21cb9d 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -1442,16 +1442,18 @@ struct neigh_parms *neigh_parms_alloc(struct net_device *dev, atomic_set(&p->refcnt, 1); p->reachable_time = neigh_rand_reach_time(p->base_reachable_time); + dev_hold(dev); + p->dev = dev; + write_pnet(&p->net, hold_net(net)); + p->sysctl_table = NULL; if (ops->ndo_neigh_setup && ops->ndo_neigh_setup(dev, p)) { + release_net(net); + dev_put(dev); kfree(p); return NULL; } - dev_hold(dev); - p->dev = dev; - write_pnet(&p->net, hold_net(net)); - p->sysctl_table = NULL; write_lock_bh(&tbl->lock); p->next = tbl->parms.next; tbl->parms.next = p; diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c index 0c285087425..77d1550b19f 100644 --- a/net/core/sysctl_net_core.c +++ b/net/core/sysctl_net_core.c @@ -19,6 +19,9 @@ #include #include +static int zero = 0; +static int ushort_max = USHRT_MAX; + #ifdef CONFIG_RPS static int rps_sock_flow_sysctl(ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) @@ -197,7 +200,9 @@ static struct ctl_table netns_core_table[] = { .data = &init_net.core.sysctl_somaxconn, .maxlen = sizeof(int), .mode = 0644, - .proc_handler = proc_dointvec + .extra1 = &zero, + .extra2 = &ushort_max, + .proc_handler = proc_dointvec_minmax }, { } }; diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index 30b88d7b4bd..424704aee18 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c @@ -71,7 +71,6 @@ #include #include #include -#include #include #include #include @@ -1772,10 +1771,8 @@ static struct leaf *leaf_walk_rcu(struct tnode *p, struct rt_trie_node *c) if (!c) continue; - if (IS_LEAF(c)) { - prefetch(rcu_dereference_rtnl(p->child[idx])); + if (IS_LEAF(c)) return (struct leaf *) c; - } /* Rescan start scanning in new node */ p = (struct tnode *) c; diff --git a/net/ipv4/tcp_cubic.c b/net/ipv4/tcp_cubic.c index a9077f441cb..b6ae92a51f5 100644 --- a/net/ipv4/tcp_cubic.c +++ b/net/ipv4/tcp_cubic.c @@ -206,8 +206,8 @@ static u32 cubic_root(u64 a) */ static inline void bictcp_update(struct bictcp *ca, u32 cwnd) { - u64 offs; - u32 delta, t, bic_target, max_cnt; + u32 delta, bic_target, max_cnt; + u64 offs, t; ca->ack_cnt++; /* count the number of ACKs */ @@ -250,9 +250,11 @@ static inline void bictcp_update(struct bictcp *ca, u32 cwnd) * if the cwnd < 1 million packets !!! */ + t = (s32)(tcp_time_stamp - ca->epoch_start); + t += msecs_to_jiffies(ca->delay_min >> 3); /* change the unit from HZ to bictcp_HZ */ - t = ((tcp_time_stamp + msecs_to_jiffies(ca->delay_min>>3) - - ca->epoch_start) << BICTCP_HZ) / HZ; + t <<= BICTCP_HZ; + do_div(t, HZ); if (t < ca->bic_K) /* t - K */ offs = ca->bic_K - t; @@ -414,7 +416,7 @@ static void bictcp_acked(struct sock *sk, u32 cnt, s32 rtt_us) return; /* Discard delay samples right after fast recovery */ - if ((s32)(tcp_time_stamp - ca->epoch_start) < HZ) + if (ca->epoch_start && (s32)(tcp_time_stamp - ca->epoch_start) < HZ) return; delay = (rtt_us << 3) / USEC_PER_MSEC; diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 1ec8fb6586f..aae161f2d98 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -910,12 +910,10 @@ static int ipv6_create_tempaddr(struct inet6_ifaddr *ifp, struct inet6_ifaddr *i if (ifp->flags & IFA_F_OPTIMISTIC) addr_flags |= IFA_F_OPTIMISTIC; - ift = !max_addresses || - ipv6_count_addresses(idev) < max_addresses ? - ipv6_add_addr(idev, &addr, tmp_plen, - ipv6_addr_type(&addr)&IPV6_ADDR_SCOPE_MASK, - addr_flags) : NULL; - if (!ift || IS_ERR(ift)) { + ift = ipv6_add_addr(idev, &addr, tmp_plen, + ipv6_addr_type(&addr)&IPV6_ADDR_SCOPE_MASK, + addr_flags); + if (IS_ERR(ift)) { in6_ifa_put(ifp); in6_dev_put(idev); printk(KERN_INFO diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index ba0c1479ba0..6262aacbcc4 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -932,6 +932,14 @@ static const struct icmp6_err { .err = ECONNREFUSED, .fatal = 1, }, + { /* POLICY_FAIL */ + .err = EACCES, + .fatal = 1, + }, + { /* REJECT_ROUTE */ + .err = EACCES, + .fatal = 1, + }, }; int icmpv6_err_convert(u8 type, u8 code, int *err) @@ -943,7 +951,7 @@ int icmpv6_err_convert(u8 type, u8 code, int *err) switch (type) { case ICMPV6_DEST_UNREACH: fatal = 1; - if (code <= ICMPV6_PORT_UNREACH) { + if (code < ARRAY_SIZE(tab_unreach)) { *err = tab_unreach[code].err; fatal = tab_unreach[code].fatal; } diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index c3a007dc37c..5bb77a69132 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -949,14 +949,22 @@ static struct fib6_node * fib6_lookup_1(struct fib6_node *root, if (ipv6_prefix_equal(&key->addr, args->addr, key->plen)) { #ifdef CONFIG_IPV6_SUBTREES - if (fn->subtree) - fn = fib6_lookup_1(fn->subtree, args + 1); + if (fn->subtree) { + struct fib6_node *sfn; + sfn = fib6_lookup_1(fn->subtree, + args + 1); + if (!sfn) + goto backtrack; + fn = sfn; + } #endif - if (!fn || fn->fn_flags & RTN_RTINFO) + if (fn->fn_flags & RTN_RTINFO) return fn; } } - +#ifdef CONFIG_IPV6_SUBTREES +backtrack: +#endif if (fn->fn_flags & RTN_ROOT) break; diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 843d6ebc525..5cc78e6930b 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -441,7 +441,6 @@ struct sk_buff *ndisc_build_skb(struct net_device *dev, int hlen = LL_RESERVED_SPACE(dev); int tlen = dev->needed_tailroom; int len; - int err; u8 *opt; if (!dev->addr_len) @@ -451,14 +450,12 @@ struct sk_buff *ndisc_build_skb(struct net_device *dev, if (llinfo) len += ndisc_opt_addr_space(dev); - skb = sock_alloc_send_skb(sk, - (MAX_HEADER + sizeof(struct ipv6hdr) + - len + hlen + tlen), - 1, &err); + skb = alloc_skb((MAX_HEADER + sizeof(struct ipv6hdr) + + len + hlen + tlen), GFP_ATOMIC); if (!skb) { ND_PRINTK0(KERN_ERR - "ICMPv6 ND: %s() failed to allocate an skb, err=%d.\n", - __func__, err); + "ICMPv6 ND: %s() failed to allocate an skb.\n", + __func__); return NULL; } @@ -486,6 +483,11 @@ struct sk_buff *ndisc_build_skb(struct net_device *dev, csum_partial(hdr, len, 0)); + /* Manually assign socket ownership as we avoid calling + * sock_alloc_send_pskb() to bypass wmem buffer limits + */ + skb_set_owner_w(skb, sk); + return skb; } diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index 6bda7aa551b..ff900ac7792 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c @@ -516,6 +516,7 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev, head->tstamp = fq->q.stamp; ipv6_hdr(head)->payload_len = htons(payload_len); IP6CB(head)->nhoff = nhoff; + IP6CB(head)->flags |= IP6SKB_FRAGMENTED; /* Yes, and fold redundant checksum back. 8) */ if (head->ip_summed == CHECKSUM_COMPLETE) @@ -551,6 +552,9 @@ static int ipv6_frag_rcv(struct sk_buff *skb) const struct ipv6hdr *hdr = ipv6_hdr(skb); struct net *net = dev_net(skb_dst(skb)->dev); + if (IP6CB(skb)->flags & IP6SKB_FRAGMENTED) + goto fail_hdr; + IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_REASMREQDS); /* Jumbo payload inhibits frag. header */ @@ -571,6 +575,7 @@ static int ipv6_frag_rcv(struct sk_buff *skb) ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_REASMOKS); IP6CB(skb)->nhoff = (u8 *)fhdr - skb_network_header(skb); + IP6CB(skb)->flags |= IP6SKB_FRAGMENTED; return 1; } diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 7ee71216773..c4717e8e81c 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -1571,7 +1571,7 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) if (np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) np->mcast_hops = ipv6_hdr(opt_skb)->hop_limit; if (np->rxopt.bits.rxtclass) - np->rcv_tclass = ipv6_tclass(ipv6_hdr(skb)); + np->rcv_tclass = ipv6_tclass(ipv6_hdr(opt_skb)); if (ipv6_opt_accepted(sk, opt_skb)) { skb_set_owner_r(opt_skb, sk); opt_skb = xchg(&np->pktoptions, opt_skb); diff --git a/net/tipc/eth_media.c b/net/tipc/eth_media.c index 527e3f0e165..dd625af7167 100644 --- a/net/tipc/eth_media.c +++ b/net/tipc/eth_media.c @@ -53,6 +53,7 @@ struct eth_bearer { struct tipc_bearer *bearer; struct net_device *dev; struct packet_type tipc_packet_type; + struct work_struct setup; struct work_struct cleanup; }; @@ -137,6 +138,17 @@ static int recv_msg(struct sk_buff *buf, struct net_device *dev, return 0; } +/** + * setup_bearer - setup association between Ethernet bearer and interface + */ +static void setup_bearer(struct work_struct *work) +{ + struct eth_bearer *eb_ptr = + container_of(work, struct eth_bearer, setup); + + dev_add_pack(&eb_ptr->tipc_packet_type); +} + /** * enable_bearer - attach TIPC bearer to an Ethernet interface */ @@ -181,7 +193,8 @@ static int enable_bearer(struct tipc_bearer *tb_ptr) eb_ptr->tipc_packet_type.func = recv_msg; eb_ptr->tipc_packet_type.af_packet_priv = eb_ptr; INIT_LIST_HEAD(&(eb_ptr->tipc_packet_type.list)); - dev_add_pack(&eb_ptr->tipc_packet_type); + INIT_WORK(&eb_ptr->setup, setup_bearer); + schedule_work(&eb_ptr->setup); /* Associate TIPC bearer with Ethernet bearer */ From da4ebf61118aaaa1b55085e92b4db20bbbd3b8d7 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 26 Sep 2013 17:16:10 -0700 Subject: [PATCH 132/215] Linux 3.4.63 - 40 commits squashed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SCSI: sd: Fix potential out-of-bounds access commit 984f1733fcee3fbc78d47e26c5096921c5d9946a upstream. This patch fixes an out-of-bounds error in sd_read_cache_type(), found by Google's AddressSanitizer tool. When the loop ends, we know that "offset" lies beyond the end of the data in the buffer, so no Caching mode page was found. In theory it may be present, but the buffer size is limited to 512 bytes. Signed-off-by: Alan Stern Reported-by: Dmitry Vyukov Signed-off-by: James Bottomley Signed-off-by: Greg Kroah-Hartman crypto: api - Fix race condition in larval lookup commit 77dbd7a95e4a4f15264c333a9e9ab97ee27dc2aa upstream. crypto_larval_lookup should only return a larval if it created one. Any larval created by another entity must be processed through crypto_larval_wait before being returned. Otherwise this will lead to a larval being killed twice, which will most likely lead to a crash. Reported-by: Kees Cook Tested-by: Kees Cook Signed-off-by: Herbert Xu Signed-off-by: Greg Kroah-Hartman powerpc: Handle unaligned ldbrx/stdbrx commit 230aef7a6a23b6166bd4003bfff5af23c9bd381f upstream. Normally when we haven't implemented an alignment handler for a load or store instruction the process will be terminated. The alignment handler uses the DSISR (or a pseudo one) to locate the right handler. Unfortunately ldbrx and stdbrx overlap lfs and stfs so we incorrectly think ldbrx is an lfs and stdbrx is an stfs. This bug is particularly nasty - instead of terminating the process we apply an incorrect fixup and continue on. With more and more overlapping instructions we should stop creating a pseudo DSISR and index using the instruction directly, but for now add a special case to catch ldbrx/stdbrx. Signed-off-by: Anton Blanchard Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Greg Kroah-Hartman xen-gnt: prevent adding duplicate gnt callbacks commit 5f338d9001094a56cf87bd8a280b4e7ff953bb59 upstream. With the current implementation, the callback in the tail of the list can be added twice, because the check done in gnttab_request_free_callback is bogus, callback->next can be NULL if it is the last callback in the list. If we add the same callback twice we end up with an infinite loop, were callback == callback->next. Replace this check with a proper one that iterates over the list to see if the callback has already been added. Signed-off-by: Roger Pau Monné Cc: Konrad Rzeszutek Wilk Cc: David Vrabel Signed-off-by: Konrad Rzeszutek Wilk Acked-by: Matt Wilson Reviewed-by: David Vrabel Signed-off-by: Greg Kroah-Hartman ARM: PCI: versatile: Fix SMAP register offsets commit 99f2b130370b904ca5300079243fdbcafa2c708b upstream. The SMAP register offsets in the versatile PCI controller code were all off by four. (This didn't have any observable bad effects because on this board PHYS_OFFSET is zero, and (a) writing zero to the flags register at offset 0x10 has no effect and (b) the reset value of the SMAP register is zero anyway, so failing to write SMAP2 didn't matter.) Signed-off-by: Peter Maydell Reviewed-by: Linus Walleij Signed-off-by: Kevin Hilman Signed-off-by: Greg Kroah-Hartman xhci-plat: Don't enable legacy PCI interrupts. commit 52fb61250a7a132b0cfb9f4a1060a1f3c49e5a25 upstream. The xHCI platform driver calls into usb_add_hcd to register the irq for its platform device. It does not want the xHCI generic driver to register an interrupt for it at all. The original code did that by setting the XHCI_BROKEN_MSI quirk, which tells the xHCI driver to not enable MSI or MSI-X for a PCI host. Unfortunately, if CONFIG_PCI is enabled, and CONFIG_USB_DW3 is enabled, the xHCI generic driver will attempt to register a legacy PCI interrupt for the xHCI platform device in xhci_try_enable_msi(). This will result in a bogus irq being registered, since the underlying device is a platform_device, not a pci_device, and thus the pci_device->irq pointer will be bogus. Add a new quirk, XHCI_PLAT, so that the xHCI generic driver can distinguish between a PCI device that can't handle MSI or MSI-X, and a platform device that should not have its interrupts touched at all. This quirk may be useful in the future, in case other corner cases like this arise. This patch should be backported to kernels as old as 3.9, that contain the commit 00eed9c814cb8f281be6f0f5d8f45025dc0a97eb "USB: xhci: correctly enable interrupts". Signed-off-by: Sarah Sharp Reported-by: Yu Y Wang Tested-by: Yu Y Wang Reviewed-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman Conflicts: drivers/usb/host/xhci-plat.c drivers/usb/host/xhci.h usb: xhci: Disable runtime PM suspend for quirky controllers commit c8476fb855434c733099079063990e5bfa7ecad6 upstream. If a USB controller with XHCI_RESET_ON_RESUME goes to runtime suspend, a reset will be performed upon runtime resume. Any previously suspended devices attached to the controller will be re-enumerated at this time. This will cause problems, for example, if an open system call on the device triggered the resume (the open call will fail). Note that this change is only relevant when persist_enabled is not set for USB devices. This patch should be backported to kernels as old as 3.0, that contain the commit c877b3b2ad5cb9d4fe523c5496185cc328ff3ae9 "xhci: Add reset on resume quirk for asrock p67 host". Signed-off-by: Shawn Nematbakhsh Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman cifs: ensure that srv_mutex is held when dealing with ssocket pointer commit 73e216a8a42c0ef3d08071705c946c38fdbe12b0 upstream. Oleksii reported that he had seen an oops similar to this: BUG: unable to handle kernel NULL pointer dereference at 0000000000000088 IP: [] sock_sendmsg+0x93/0xd0 PGD 0 Oops: 0000 [#1] PREEMPT SMP Modules linked in: ipt_MASQUERADE xt_REDIRECT xt_tcpudp iptable_nat nf_conntrack_ipv4 nf_defrag_ipv4 nf_nat_ipv4 nf_nat nf_conntrack ip_tables x_tables carl9170 ath usb_storage f2fs nfnetlink_log nfnetlink md4 cifs dns_resolver hid_generic usbhid hid af_packet uvcvideo videobuf2_vmalloc videobuf2_memops videobuf2_core videodev rfcomm btusb bnep bluetooth qmi_wwan qcserial cdc_wdm usb_wwan usbnet usbserial mii snd_hda_codec_hdmi snd_hda_codec_realtek iwldvm mac80211 coretemp intel_powerclamp kvm_intel kvm iwlwifi snd_hda_intel cfg80211 snd_hda_codec xhci_hcd e1000e ehci_pci snd_hwdep sdhci_pci snd_pcm ehci_hcd microcode psmouse sdhci thinkpad_acpi mmc_core i2c_i801 pcspkr usbcore hwmon snd_timer snd_page_alloc snd ptp rfkill pps_core soundcore evdev usb_common vboxnetflt(O) vboxdrv(O)Oops#2 Part8 loop tun binfmt_misc fuse msr acpi_call(O) ipv6 autofs4 CPU: 0 PID: 21612 Comm: kworker/0:1 Tainted: G W O 3.10.1SIGN #28 Hardware name: LENOVO 2306CTO/2306CTO, BIOS G2ET92WW (2.52 ) 02/22/2013 Workqueue: cifsiod cifs_echo_request [cifs] task: ffff8801e1f416f0 ti: ffff880148744000 task.ti: ffff880148744000 RIP: 0010:[] [] sock_sendmsg+0x93/0xd0 RSP: 0000:ffff880148745b00 EFLAGS: 00010246 RAX: 0000000000000000 RBX: ffff880148745b78 RCX: 0000000000000048 RDX: ffff880148745c90 RSI: ffff880181864a00 RDI: ffff880148745b78 RBP: ffff880148745c48 R08: 0000000000000048 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000000 R12: ffff880181864a00 R13: ffff880148745c90 R14: 0000000000000048 R15: 0000000000000048 FS: 0000000000000000(0000) GS:ffff88021e200000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000000000088 CR3: 000000020c42c000 CR4: 00000000001407b0 Oops#2 Part7 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Stack: ffff880148745b30 ffffffff810c4af9 0000004848745b30 ffff880181864a00 ffffffff81ffbc40 0000000000000000 ffff880148745c90 ffffffff810a5aab ffff880148745bc0 ffffffff81ffbc40 ffff880148745b60 ffffffff815a9fb8 Call Trace: [] ? finish_task_switch+0x49/0xe0 [] ? lock_timer_base.isra.36+0x2b/0x50 [] ? _raw_spin_unlock_irqrestore+0x18/0x40 [] ? try_to_del_timer_sync+0x4f/0x70 [] ? _raw_spin_unlock_bh+0x1f/0x30 [] kernel_sendmsg+0x37/0x50 [] smb_send_kvec+0xd0/0x1d0 [cifs] [] smb_send_rqst+0x83/0x1f0 [cifs] [] cifs_call_async+0xec/0x1b0 [cifs] [] ? free_rsp_buf+0x40/0x40 [cifs] Oops#2 Part6 [] SMB2_echo+0x8e/0xb0 [cifs] [] cifs_echo_request+0x79/0xa0 [cifs] [] process_one_work+0x173/0x4a0 [] worker_thread+0x121/0x3a0 [] ? manage_workers.isra.27+0x2b0/0x2b0 [] kthread+0xc0/0xd0 [] ? kthread_create_on_node+0x120/0x120 [] ret_from_fork+0x7c/0xb0 [] ? kthread_create_on_node+0x120/0x120 Code: 84 24 b8 00 00 00 4c 89 f1 4c 89 ea 4c 89 e6 48 89 df 4c 89 60 18 48 c7 40 28 00 00 00 00 4c 89 68 30 44 89 70 14 49 8b 44 24 28 90 88 00 00 00 3d ef fd ff ff 74 10 48 8d 65 e0 5b 41 5c 41 RIP [] sock_sendmsg+0x93/0xd0 RSP CR2: 0000000000000088 The client was in the middle of trying to send a frame when the server->ssocket pointer got zeroed out. In most places, that we access that pointer, the srv_mutex is held. There's only one spot that I see that the server->ssocket pointer gets set and the srv_mutex isn't held. This patch corrects that. The upstream bug report was here: https://bugzilla.kernel.org/show_bug.cgi?id=60557 Reported-by: Oleksii Shevchuk Signed-off-by: Jeff Layton Signed-off-by: Steve French Signed-off-by: Greg Kroah-Hartman staging: comedi: dt282x: dt282x_ai_insn_read() always fails commit 2c4283ca7cdcc6605859c836fc536fcd83a4525f upstream. In dt282x_ai_insn_read() we call this macro like: wait_for(!mux_busy(), comedi_error(dev, "timeout\n"); return -ETIME;); Because the if statement doesn't have curly braces it means we always return -ETIME and the function never succeeds. Signed-off-by: Dan Carpenter Acked-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman USB: mos7720: use GFP_ATOMIC under spinlock commit d0bd9a41186e076ea543c397ad8a67a6cf604b55 upstream. The write_parport_reg_nonblock() function shouldn't sleep because it's called with spinlocks held. Signed-off-by: Dan Carpenter Acked-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman USB: mos7720: fix big-endian control requests commit 3b716caf190ccc6f2a09387210e0e6a26c1d81a4 upstream. Fix endianess bugs in parallel-port code which caused corrupt control-requests to be issued on big-endian machines. Reported-by: kbuild test robot Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman usb: ehci-mxc: check for pdata before dereferencing commit f375fc520d4df0cd9fcb570f33c103c6c0311f9e upstream. Commit 7e8d5cd93fac ("USB: Add EHCI support for MX27 and MX31 based boards") introduced code that could potentially lead to a NULL pointer dereference on driver removal. Fix this by checking for the value of pdata before dereferencing it. Signed-off-by: Daniel Mack Reported-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman USB: cdc-wdm: fix race between interrupt handler and tasklet commit 6dd433e6cf2475ce8abec1b467720858c24450eb upstream. Both could want to submit the same URB. Some checks of the flag intended to prevent that were missing. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman usb: config->desc.bLength may not exceed amount of data returned by the device commit b4f17a488ae2e09bfcf95c0e0b4219c246f1116a upstream. While reading the config parsing code I noticed this check is missing, without this check config->desc.wTotalLength can end up with a value larger then the dev->rawdescriptors length for the config, and when userspace then tries to get the rawdescriptors bad things may happen. Signed-off-by: Hans de Goede Signed-off-by: Greg Kroah-Hartman rculist: list_first_or_null_rcu() should use list_entry_rcu() commit c34ac00caefbe49d40058ae7200bd58725cebb45 upstream. list_first_or_null() should test whether the list is empty and return pointer to the first entry if not in a RCU safe manner. It's broken in several ways. * It compares __kernel @__ptr with __rcu @__next triggering the following sparse warning. net/core/dev.c:4331:17: error: incompatible types in comparison expression (different address spaces) * It doesn't perform rcu_dereference*() and computes the entry address using container_of() directly from the __rcu pointer which is inconsitent with other rculist interface. As a result, all three in-kernel users - net/core/dev.c, macvlan, cgroup - are buggy. They dereference the pointer w/o going through read barrier. * While ->next dereference passes through list_next_rcu(), the compiler is still free to fetch ->next more than once and thus nullify the "__ptr != __next" condition check. Fix it by making list_first_or_null_rcu() dereference ->next directly using ACCESS_ONCE() and then use list_entry_rcu() on it like other rculist accessors. v2: Paul pointed out that the compiler may fetch the pointer more than once nullifying the condition check. ACCESS_ONCE() added on ->next dereference. v3: Restored () around macro param which was accidentally removed. Spotted by Paul. Signed-off-by: Tejun Heo Reported-by: Fengguang Wu Cc: Dipankar Sarma Cc: "Paul E. McKenney" Cc: "David S. Miller" Cc: Li Zefan Cc: Patrick McHardy Signed-off-by: Paul E. McKenney Reviewed-by: Josh Triplett Signed-off-by: Greg Kroah-Hartman ASoC: wm8960: Fix PLL register writes commit 85fa532b6ef920b32598df86b194571a7059a77c upstream. Bit 9 of PLL2,3 and 4 is reserved as '0'. The 24bit fractional part should be split across each register in 8bit chunks. Signed-off-by: Mike Dyer Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman ALSA: hda - Add Toshiba Satellite C870 to MSI blacklist commit 83f72151352791836a1b9c1542614cc9bf71ac61 upstream. Toshiba Satellite C870 shows interrupt problems occasionally when certain mixer controls like "Mic Switch" is toggled. This seems worked around by not using MSI. Bugzilla: https://bugzilla.novell.com/show_bug.cgi?id=833585 Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman brcmsmac: Fix WARNING caused by lack of calls to dma_mapping_error() commit 67d0cf50bd32b66eab709871714e55725ee30ce4 upstream. The driver fails to check the results of DMA mapping in twp places, which results in the following warning: [ 28.078515] ------------[ cut here ]------------ [ 28.078529] WARNING: at lib/dma-debug.c:937 check_unmap+0x47e/0x930() [ 28.078533] bcma-pci-bridge 0000:0e:00.0: DMA-API: device driver failed to check map error[device address=0x00000000b5d60d6c] [size=1876 bytes] [mapped as single] [ 28.078536] Modules linked in: bnep bluetooth vboxpci(O) vboxnetadp(O) vboxnetflt(O) vboxdrv(O) ipv6 b43 brcmsmac rtl8192cu rtl8192c_common rtlwifi mac802 11 brcmutil cfg80211 snd_hda_codec_conexant rng_core snd_hda_intel kvm_amd snd_hda_codec ssb kvm mmc_core snd_pcm snd_seq snd_timer snd_seq_device snd k8temp cordic joydev serio_raw hwmon sr_mod sg pcmcia pcmcia_core soundcore cdrom i2c_nforce2 i2c_core forcedeth bcma snd_page_alloc autofs4 ext4 jbd2 mbcache crc1 6 scsi_dh_alua scsi_dh_hp_sw scsi_dh_rdac scsi_dh_emc scsi_dh ata_generic pata_amd [ 28.078602] CPU: 1 PID: 2570 Comm: NetworkManager Tainted: G O 3.10.0-rc7-wl+ #42 [ 28.078605] Hardware name: Hewlett-Packard HP Pavilion dv2700 Notebook PC/30D6, BIOS F.27 11/27/2008 [ 28.078607] 0000000000000009 ffff8800bbb03ad8 ffffffff8144f898 ffff8800bbb03b18 [ 28.078612] ffffffff8103e1eb 0000000000000002 ffff8800b719f480 ffff8800b7b9c010 [ 28.078617] ffffffff824204c0 ffffffff81754d57 0000000000000754 ffff8800bbb03b78 [ 28.078622] Call Trace: [ 28.078624] [] dump_stack+0x19/0x1b [ 28.078634] [] warn_slowpath_common+0x6b/0xa0 [ 28.078638] [] warn_slowpath_fmt+0x41/0x50 [ 28.078650] [] check_unmap+0x47e/0x930 [ 28.078655] [] debug_dma_unmap_page+0x5c/0x70 [ 28.078679] [] dma64_getnextrxp+0x10c/0x190 [brcmsmac] [ 28.078691] [] dma_rx+0x62/0x240 [brcmsmac] [ 28.078707] [] brcms_c_dpc+0x211/0x9d0 [brcmsmac] [ 28.078717] [] ? brcms_dpc+0x27/0xf0 [brcmsmac] [ 28.078731] [] brcms_dpc+0x47/0xf0 [brcmsmac] [ 28.078736] [] tasklet_action+0x6c/0xf0 --snip-- [ 28.078974] [] SyS_sendmsg+0xd/0x20 [ 28.078979] [] tracesys+0xdd/0xe2 [ 28.078982] ---[ end trace 6164d1a08148e9c8 ]--- [ 28.078984] Mapped at: [ 28.078985] [] debug_dma_map_page+0x9d/0x150 [ 28.078989] [] dma_rxfill+0x102/0x3d0 [brcmsmac] [ 28.079001] [] brcms_c_init+0x87d/0x1100 [brcmsmac] [ 28.079010] [] brcms_init+0x21/0x30 [brcmsmac] [ 28.079018] [] brcms_c_up+0x150/0x430 [brcmsmac] As the patch adds a new failure mechanism to dma_rxfill(). When I changed the comment at the start of the routine to add that information, I also polished the wording. Signed-off-by: Larry Finger Cc: Brett Rudley Cc: Franky (Zhenhui) Lin Cc: Hante Meuleman Cc: brcm80211-dev-list@broadcom.com Acked-by: Arend van Spriel Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman ath9k: always clear ps filter bit on new assoc commit 026d5b07c03458f9c0ccd19c3850564a5409c325 upstream. Otherwise in some cases, EAPOL frames might be filtered during the initial handshake, causing delays and assoc failures. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman ath9k: fix rx descriptor related race condition commit e96542e55a2aacf4bdeccfe2f17b77c4895b4df2 upstream. Similar to a race condition that exists in the tx path, the hardware might re-read the 'next' pointer of a descriptor of the last completed frame. This only affects non-EDMA (pre-AR93xx) devices. To deal with this race, defer clearing and re-linking a completed rx descriptor until the next one has been processed. Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman ath9k: avoid accessing MRC registers on single-chain devices commit a1c781bb20ac1e03280e420abd47a99eb8bbdd3b upstream. They are not implemented, and accessing them might trigger errors Signed-off-by: Felix Fietkau Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman HID: pantherlord: validate output report details commit 412f30105ec6735224535791eed5cdc02888ecb4 upstream. A HID device could send a malicious output report that would cause the pantherlord HID driver to write beyond the output report allocation during initialization, causing a heap overflow: [ 310.939483] usb 1-1: New USB device found, idVendor=0e8f, idProduct=0003 ... [ 315.980774] BUG kmalloc-192 (Tainted: G W ): Redzone overwritten CVE-2013-2892 Signed-off-by: Kees Cook Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman HID: Fix Speedlink VAD Cezanne support for some devices commit 06bb5219118fb098f4b0c7dcb484b28a52bf1c14 upstream. Some devices of the "Speedlink VAD Cezanne" model need more aggressive fixing than already done. I made sure through testing that this patch would not interfere with the proper working of a device that is bug-free. (The driver drops EV_REL events with abs(val) >= 256, which are not achievable even on the highest laser resolution hardware setting.) Signed-off-by: Stefan Kriwanek Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman HID: validate HID report id size commit 43622021d2e2b82ea03d883926605bdd0525e1d1 upstream. The "Report ID" field of a HID report is used to build indexes of reports. The kernel's index of these is limited to 256 entries, so any malicious device that sets a Report ID greater than 255 will trigger memory corruption on the host: [ 1347.156239] BUG: unable to handle kernel paging request at ffff88094958a878 [ 1347.156261] IP: [] hid_register_report+0x2a/0x8b CVE-2013-2888 Signed-off-by: Kees Cook Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman HID: ntrig: validate feature report details commit 875b4e3763dbc941f15143dd1a18d10bb0be303b upstream. A HID device could send a malicious feature report that would cause the ntrig HID driver to trigger a NULL dereference during initialization: [57383.031190] usb 3-1: New USB device found, idVendor=1b96, idProduct=0001 ... [57383.315193] BUG: unable to handle kernel NULL pointer dereference at 0000000000000030 [57383.315308] IP: [] ntrig_probe+0x25e/0x420 [hid_ntrig] CVE-2013-2896 Signed-off-by: Kees Cook Signed-off-by: Rafi Rubin Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman HID: battery: don't do DMA from stack commit 6c2794a2984f4c17a58117a68703cc7640f01c5a upstream. Instead of using data from stack for DMA in hidinput_get_battery_property(), allocate the buffer dynamically. Reported-by: Richard Ryniker Reported-by: Alan Stern Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman HID: check for NULL field when setting values commit be67b68d52fa28b9b721c47bb42068f0c1214855 upstream. Defensively check that the field to be worked on is not NULL. Signed-off-by: Kees Cook Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman HID: usbhid: quirk for N-Trig DuoSense Touch Screen commit 9e0bf92c223dabe0789714f8f85f6e26f8f9cda4 upstream. The DuoSense touchscreen device causes a 10 second timeout. This fix removes the delay. Signed-off-by: Vasily Titskiy Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman media: v4l2: added missing mutex.h include to v4l2-ctrls.h commit a19dec6ea94c036af68c31930c1c92681f55af41 upstream. This patch fixes following error: include/media/v4l2-ctrls.h:193:15: error: field ‘_lock’ has incomplete type include/media/v4l2-ctrls.h: In function ‘v4l2_ctrl_lock’: include/media/v4l2-ctrls.h:570:2: error: implicit declaration of function ‘mutex_lock’ [-Werror=implicit-function-declaration] include/media/v4l2-ctrls.h: In function ‘v4l2_ctrl_unlock’: include/media/v4l2-ctrls.h:579:2: error: implicit declaration of function ‘mutex_unlock’ [-Werror=implicit-function-declaration] Signed-off-by: Andrzej Hajda Signed-off-by: Kyungmin Park Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman MIPS: ath79: Fix ar933x watchdog clock commit a1191927ace7e6f827132aa9e062779eb3f11fa5 upstream. The watchdog device on the AR933x is connected to the AHB clock, however the current code uses the reference clock. Due to the wrong rate, the watchdog driver can't calculate correct register values for a given timeout value and the watchdog unexpectedly restarts the system. The code uses the wrong value since the initial commit 04225e1d227c8e68d685936ecf42ac175fec0e54 (MIPS: ath79: add AR933X specific clock init) The patch fixes the code to use the correct clock rate to avoid the problem. Signed-off-by: Felix Fietkau Signed-off-by: Gabor Juhos Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/5777/ Signed-off-by: Ralf Baechle Signed-off-by: Greg Kroah-Hartman intel-iommu: Fix leaks in pagetable freeing commit 3269ee0bd6686baf86630300d528500ac5b516d7 upstream. At best the current code only seems to free the leaf pagetables and the root. If you're unlucky enough to have a large gap (like any QEMU guest with more than 3G of memory), only the first chunk of leaf pagetables are freed (plus the root). This is a massive memory leak. This patch re-writes the pagetable freeing function to use a recursive algorithm and manages to not only free all the pagetables, but does it without any apparent performance loss versus the current broken version. Signed-off-by: Alex Williamson Reviewed-by: Marcelo Tosatti Signed-off-by: Joerg Roedel Signed-off-by: Greg Kroah-Hartman ocfs2: fix the end cluster offset of FIEMAP commit 28e8be31803b19d0d8f76216cb11b480b8a98bec upstream. Call fiemap ioctl(2) with given start offset as well as an desired mapping range should show extents if possible. However, we somehow figure out the end offset of mapping via 'mapping_end -= cpos' before iterating the extent records which would cause problems if the given fiemap length is too small to a cluster size, e.g, Cluster size 4096: debugfs.ocfs2 1.6.3 Block Size Bits: 12 Cluster Size Bits: 12 The extended fiemap test utility From David: https://gist.github.com/anonymous/6172331 start: 4096, length: 10 File /ocfs2/test_file has 0 extents: ^^^^^ <-- No extent is shown In this case, at ocfs2_fiemap(): cpos == mapping_end == 1. Hence the loop of searching extent records was not executed at all. This patch remove the in question 'mapping_end -= cpos', and loops until the cpos is larger than the mapping_end as usual. start: 4096, length: 10 File /ocfs2/test_file has 1 extents: 0: 0000000000000000 0000000056a01000 0000000006a00000 0000 Signed-off-by: Jie Liu Reported-by: David Weber Tested-by: David Weber Cc: Sunil Mushran Cc: Mark Fashen Cc: Joel Becker Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman memcg: fix multiple large threshold notifications commit 2bff24a3707093c435ab3241c47dcdb5f16e432b upstream. A memory cgroup with (1) multiple threshold notifications and (2) at least one threshold >=2G was not reliable. Specifically the notifications would either not fire or would not fire in the proper order. The __mem_cgroup_threshold() signaling logic depends on keeping 64 bit thresholds in sorted order. mem_cgroup_usage_register_event() sorts them with compare_thresholds(), which returns the difference of two 64 bit thresholds as an int. If the difference is positive but has bit[31] set, then sort() treats the difference as negative and breaks sort order. This fix compares the two arbitrary 64 bit thresholds returning the classic -1, 0, 1 result. The test below sets two notifications (at 0x1000 and 0x81001000): cd /sys/fs/cgroup/memory mkdir x for x in 4096 2164264960; do cgroup_event_listener x/memory.usage_in_bytes $x | sed "s/^/$x listener:/" & done echo $$ > x/cgroup.procs anon_leaker 500M v3.11-rc7 fails to signal the 4096 event listener: Leaking... Done leaking pages. Patched v3.11-rc7 properly notifies: Leaking... 4096 listener:2013:8:31:14:13:36 Done leaking pages. The fixed bug is old. It appears to date back to the introduction of memcg threshold notifications in v2.6.34-rc1-116-g2e72b6347c94 "memcg: implement memory thresholds" Signed-off-by: Greg Thelen Acked-by: Michal Hocko Acked-by: Kirill A. Shutemov Acked-by: Johannes Weiner Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman mm/huge_memory.c: fix potential NULL pointer dereference commit a8f531ebc33052642b4bd7b812eedf397108ce64 upstream. In collapse_huge_page() there is a race window between releasing the mmap_sem read lock and taking the mmap_sem write lock, so find_vma() may return NULL. So check the return value to avoid NULL pointer dereference. collapse_huge_page khugepaged_alloc_page up_read(&mm->mmap_sem) down_write(&mm->mmap_sem) vma = find_vma(mm, address) Signed-off-by: Libin Acked-by: Kirill A. Shutemov Reviewed-by: Wanpeng Li Reviewed-by: Michal Hocko Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman isofs: Refuse RW mount of the filesystem instead of making it RO commit 17b7f7cf58926844e1dd40f5eb5348d481deca6a upstream. Refuse RW mount of isofs filesystem. So far we just silently changed it to RO mount but when the media is writeable, block layer won't notice this change and thus will think device is used RW and will block eject button of the drive. That is unexpected by users because for non-writeable media eject button works just fine. Userspace mount(8) command handles this just fine and retries mounting with MS_RDONLY set so userspace shouldn't see any regression. Plus any tool mounting isofs is likely confronted with the case of read-only media where block layer already refuses to mount the filesystem without MS_RDONLY set so our behavior shouldn't be anything new for it. Reported-by: Hui Wang Signed-off-by: Jan Kara Signed-off-by: Greg Kroah-Hartman drm/edid: add quirk for Medion MD30217PG commit 118bdbd86b39dbb843155054021d2c59058f1e05 upstream. This LCD monitor (1280x1024 native) has a completely bogus detailed timing (640x350@70hz). User reports that 1280x1024@60 has waves so prefer 1280x1024@75. Manufacturer: MED Model: 7b8 Serial#: 99188 Year: 2005 Week: 5 EDID Version: 1.3 Analog Display Input, Input Voltage Level: 0.700/0.700 V Sync: Separate Max Image Size [cm]: horiz.: 34 vert.: 27 Gamma: 2.50 DPMS capabilities: Off; RGB/Color Display First detailed timing is preferred mode redX: 0.645 redY: 0.348 greenX: 0.280 greenY: 0.605 blueX: 0.142 blueY: 0.071 whiteX: 0.313 whiteY: 0.329 Supported established timings: 720x400@70Hz 640x480@60Hz 640x480@72Hz 640x480@75Hz 800x600@56Hz 800x600@60Hz 800x600@72Hz 800x600@75Hz 1024x768@60Hz 1024x768@70Hz 1024x768@75Hz 1280x1024@75Hz Manufacturer's mask: 0 Supported standard timings: Supported detailed timing: clock: 25.2 MHz Image Size: 337 x 270 mm h_active: 640 h_sync: 688 h_sync_end 784 h_blank_end 800 h_border: 0 v_active: 350 v_sync: 350 v_sync_end 352 v_blanking: 449 v_border: 0 Monitor name: MD30217PG Ranges: V min: 56 V max: 76 Hz, H min: 30 H max: 83 kHz, PixClock max 145 MHz Serial No: 501099188 EDID (in hex): 00ffffffffffff0034a4b80774830100 050f010368221b962a0c55a559479b24 125054afcf00310a0101010101018180 000000000000d60980a0205e63103060 0200510e1100001e000000fc004d4433 3032313750470a202020000000fd0038 4c1e530e000a202020202020000000ff 003530313039393138380a2020200078 Signed-off-by: Alex Deucher Reported-by: friedrich@mailstation.de Signed-off-by: Greg Kroah-Hartman mmc: tmio_mmc_dma: fix PIO fallback on SDHI commit f936f9b67b7f8c2eae01dd303a0e90bd777c4679 upstream. I'm testing SH-Mobile SDHI driver in DMA mode with a new DMA controller using 'bonnie++' and getting DMA error after which the tmio_mmc_dma.c code falls back to PIO but all commands time out after that. It turned out that the fallback code calls tmio_mmc_enable_dma() with RX/TX channels already freed and pointers to them cleared, so that the function bails out early instead of clearing the DMA bit in the CTL_DMA_ENABLE register. The regression was introduced by commit 162f43e31c5a376ec16336e5d0ac973373d54c89 (mmc: tmio: fix a deadlock). Moving tmio_mmc_enable_dma() calls to the top of the PIO fallback code in tmio_mmc_start_dma_{rx|tx}() helps. Signed-off-by: Sergei Shtylyov Acked-by: Guennadi Liakhovetski Signed-off-by: Chris Ball Signed-off-by: Greg Kroah-Hartman of: Fix missing memory initialization on FDT unflattening commit 0640332e073be9207f0784df43595c0c39716e42 upstream. Any calls to dt_alloc() need to be zeroed. This is a temporary fix, but the allocation function itself needs to zero memory before returning it. This is a follow up to patch 9e4012752, "of: fdt: fix memory initialization for expanded DT" which fixed one call site but missed another. Signed-off-by: Grant Likely Acked-by: Wladislav Wiebe Signed-off-by: Greg Kroah-Hartman fuse: postpone end_page_writeback() in fuse_writepage_locked() commit 4a4ac4eba1010ef9a804569058ab29e3450c0315 upstream. The patch fixes a race between ftruncate(2), mmap-ed write and write(2): 1) An user makes a page dirty via mmap-ed write. 2) The user performs shrinking truncate(2) intended to purge the page. 3) Before fuse_do_setattr calls truncate_pagecache, the page goes to writeback. fuse_writepage_locked fills FUSE_WRITE request and releases the original page by end_page_writeback. 4) fuse_do_setattr() completes and successfully returns. Since now, i_mutex is free. 5) Ordinary write(2) extends i_size back to cover the page. Note that fuse_send_write_pages do wait for fuse writeback, but for another page->index. 6) fuse_writepage_locked proceeds by queueing FUSE_WRITE request. fuse_send_writepage is supposed to crop inarg->size of the request, but it doesn't because i_size has already been extended back. Moving end_page_writeback to the end of fuse_writepage_locked fixes the race because now the fact that truncate_pagecache is successfully returned infers that fuse_writepage_locked has already called end_page_writeback. And this, in turn, infers that fuse_flush_writepages has already called fuse_send_writepage, and the latter used valid (shrunk) i_size. write(2) could not extend it because of i_mutex held by ftruncate(2). Signed-off-by: Maxim Patlasov Signed-off-by: Miklos Szeredi Signed-off-by: Greg Kroah-Hartman fuse: invalidate inode attributes on xattr modification commit d331a415aef98717393dda0be69b7947da08eba3 upstream. Calls like setxattr and removexattr result in updation of ctime. Therefore invalidate inode attributes to force a refresh. Signed-off-by: Anand Avati Reviewed-by: Brian Foster Signed-off-by: Miklos Szeredi Signed-off-by: Greg Kroah-Hartman --- Makefile | 2 +- arch/arm/mach-versatile/pci.c | 6 +- arch/mips/ath79/clock.c | 2 +- arch/powerpc/kernel/align.c | 10 +++ crypto/api.c | 7 +- drivers/gpu/drm/drm_edid.c | 3 + drivers/hid/hid-core.c | 17 +++-- drivers/hid/hid-ids.h | 1 + drivers/hid/hid-input.c | 12 +++- drivers/hid/hid-ntrig.c | 3 +- drivers/hid/hid-pl.c | 10 ++- drivers/hid/hid-speedlink.c | 11 ++- drivers/hid/usbhid/hid-quirks.c | 2 + drivers/iommu/intel-iommu.c | 72 +++++++++---------- drivers/mmc/host/tmio_mmc_dma.c | 4 +- drivers/net/wireless/ath/ath9k/ar9003_phy.c | 4 ++ drivers/net/wireless/ath/ath9k/ath9k.h | 5 +- drivers/net/wireless/ath/ath9k/recv.c | 17 +++-- drivers/net/wireless/ath/ath9k/xmit.c | 1 + drivers/net/wireless/brcm80211/brcmsmac/dma.c | 15 ++-- drivers/of/base.c | 1 + drivers/scsi/sd.c | 11 +-- drivers/staging/comedi/drivers/dt282x.c | 3 +- drivers/usb/class/cdc-wdm.c | 13 ++-- drivers/usb/core/config.c | 3 +- drivers/usb/host/ehci-mxc.c | 2 +- drivers/usb/host/xhci-plat.c | 2 +- drivers/usb/host/xhci.c | 29 +++++++- drivers/usb/host/xhci.h | 1 + drivers/usb/serial/mos7720.c | 6 +- drivers/xen/grant-table.c | 13 +++- fs/cifs/connect.c | 2 + fs/fuse/dir.c | 4 ++ fs/fuse/file.c | 3 +- fs/isofs/inode.c | 16 ++--- fs/ocfs2/extent_map.c | 1 - include/linux/hid.h | 4 +- include/linux/rculist.h | 5 +- include/media/v4l2-ctrls.h | 1 + mm/huge_memory.c | 2 + mm/memcontrol.c | 8 ++- sound/pci/hda/hda_intel.c | 1 + sound/soc/codecs/wm8960.c | 6 +- 43 files changed, 230 insertions(+), 111 deletions(-) diff --git a/Makefile b/Makefile index 9aba296cf68..568cabdfe56 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 4 -SUBLEVEL = 62 +SUBLEVEL = 63 EXTRAVERSION = NAME = Saber-toothed Squirrel diff --git a/arch/arm/mach-versatile/pci.c b/arch/arm/mach-versatile/pci.c index d2268be8c34..709beb1d396 100644 --- a/arch/arm/mach-versatile/pci.c +++ b/arch/arm/mach-versatile/pci.c @@ -42,9 +42,9 @@ #define PCI_IMAP0 __IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x0) #define PCI_IMAP1 __IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x4) #define PCI_IMAP2 __IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x8) -#define PCI_SMAP0 __IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x10) -#define PCI_SMAP1 __IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x14) -#define PCI_SMAP2 __IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x18) +#define PCI_SMAP0 __IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x14) +#define PCI_SMAP1 __IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x18) +#define PCI_SMAP2 __IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0x1c) #define PCI_SELFID __IO_ADDRESS(VERSATILE_PCI_CORE_BASE+0xc) #define DEVICE_ID_OFFSET 0x00 diff --git a/arch/mips/ath79/clock.c b/arch/mips/ath79/clock.c index 54d0eb4db98..89276a2fd86 100644 --- a/arch/mips/ath79/clock.c +++ b/arch/mips/ath79/clock.c @@ -159,7 +159,7 @@ static void __init ar933x_clocks_init(void) ath79_ahb_clk.rate = freq / t; } - ath79_wdt_clk.rate = ath79_ref_clk.rate; + ath79_wdt_clk.rate = ath79_ahb_clk.rate; ath79_uart_clk.rate = ath79_ref_clk.rate; } diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c index ee5b690a0be..52e5758ea36 100644 --- a/arch/powerpc/kernel/align.c +++ b/arch/powerpc/kernel/align.c @@ -764,6 +764,16 @@ int fix_alignment(struct pt_regs *regs) nb = aligninfo[instr].len; flags = aligninfo[instr].flags; + /* ldbrx/stdbrx overlap lfs/stfs in the DSISR unfortunately */ + if (IS_XFORM(instruction) && ((instruction >> 1) & 0x3ff) == 532) { + nb = 8; + flags = LD+SW; + } else if (IS_XFORM(instruction) && + ((instruction >> 1) & 0x3ff) == 660) { + nb = 8; + flags = ST+SW; + } + /* Byteswap little endian loads and stores */ swiz = 0; if (regs->msr & MSR_LE) { diff --git a/crypto/api.c b/crypto/api.c index 033a7147e5e..4f98dd5b191 100644 --- a/crypto/api.c +++ b/crypto/api.c @@ -40,6 +40,8 @@ static inline struct crypto_alg *crypto_alg_get(struct crypto_alg *alg) return alg; } +static struct crypto_alg *crypto_larval_wait(struct crypto_alg *alg); + struct crypto_alg *crypto_mod_get(struct crypto_alg *alg) { return try_module_get(alg->cra_module) ? crypto_alg_get(alg) : NULL; @@ -150,8 +152,11 @@ static struct crypto_alg *crypto_larval_add(const char *name, u32 type, } up_write(&crypto_alg_sem); - if (alg != &larval->alg) + if (alg != &larval->alg) { kfree(larval); + if (crypto_is_larval(alg)) + alg = crypto_larval_wait(alg); + } return alg; } diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 8b77fd31798..efe172f3360 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -125,6 +125,9 @@ static struct edid_quirk { /* ViewSonic VA2026w */ { "VSC", 5020, EDID_QUIRK_FORCE_REDUCED_BLANKING }, + + /* Medion MD 30217 PG */ + { "MED", 0x7b8, EDID_QUIRK_PREFER_LARGE_75 }, }; /*** DDC fetch and block validation ***/ diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index ff73d60cfc7..ab59fdf0623 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -63,6 +63,8 @@ struct hid_report *hid_register_report(struct hid_device *device, unsigned type, struct hid_report_enum *report_enum = device->report_enum + type; struct hid_report *report; + if (id >= HID_MAX_IDS) + return NULL; if (report_enum->report_id_hash[id]) return report_enum->report_id_hash[id]; @@ -385,8 +387,10 @@ static int hid_parser_global(struct hid_parser *parser, struct hid_item *item) case HID_GLOBAL_ITEM_TAG_REPORT_ID: parser->global.report_id = item_udata(item); - if (parser->global.report_id == 0) { - hid_err(parser->device, "report_id 0 is invalid\n"); + if (parser->global.report_id == 0 || + parser->global.report_id >= HID_MAX_IDS) { + hid_err(parser->device, "report_id %u is invalid\n", + parser->global.report_id); return -1; } return 0; @@ -557,7 +561,7 @@ static void hid_device_release(struct device *dev) for (i = 0; i < HID_REPORT_TYPES; i++) { struct hid_report_enum *report_enum = device->report_enum + i; - for (j = 0; j < 256; j++) { + for (j = 0; j < HID_MAX_IDS; j++) { struct hid_report *report = report_enum->report_id_hash[j]; if (report) hid_free_report(report); @@ -995,7 +999,12 @@ EXPORT_SYMBOL_GPL(hid_output_report); int hid_set_field(struct hid_field *field, unsigned offset, __s32 value) { - unsigned size = field->report_size; + unsigned size; + + if (!field) + return -1; + + size = field->report_size; hid_dump_input(field->report->device, field->usage + offset, value); diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 2072b3220e0..617b10e8d5f 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -595,6 +595,7 @@ #define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_16 0x0012 #define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_17 0x0013 #define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_18 0x0014 +#define USB_DEVICE_ID_NTRIG_DUOSENSE 0x1500 #define USB_VENDOR_ID_ONTRAK 0x0a07 #define USB_DEVICE_ID_ONTRAK_ADU100 0x0064 diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index 43669731afc..847ca88bc1b 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -314,7 +314,7 @@ static int hidinput_get_battery_property(struct power_supply *psy, { struct hid_device *dev = container_of(psy, struct hid_device, battery); int ret = 0; - __u8 buf[2] = {}; + __u8 *buf; switch (prop) { case POWER_SUPPLY_PROP_PRESENT: @@ -323,13 +323,20 @@ static int hidinput_get_battery_property(struct power_supply *psy, break; case POWER_SUPPLY_PROP_CAPACITY: + + buf = kmalloc(2 * sizeof(__u8), GFP_KERNEL); + if (!buf) { + ret = -ENOMEM; + break; + } ret = dev->hid_get_raw_report(dev, dev->battery_report_id, - buf, sizeof(buf), + buf, 2, dev->battery_report_type); if (ret != 2) { if (ret >= 0) ret = -EINVAL; + kfree(buf); break; } @@ -338,6 +345,7 @@ static int hidinput_get_battery_property(struct power_supply *psy, buf[1] <= dev->battery_max) val->intval = (100 * (buf[1] - dev->battery_min)) / (dev->battery_max - dev->battery_min); + kfree(buf); break; case POWER_SUPPLY_PROP_MODEL_NAME: diff --git a/drivers/hid/hid-ntrig.c b/drivers/hid/hid-ntrig.c index 9fae2ebdd75..48cba857046 100644 --- a/drivers/hid/hid-ntrig.c +++ b/drivers/hid/hid-ntrig.c @@ -115,7 +115,8 @@ static inline int ntrig_get_mode(struct hid_device *hdev) struct hid_report *report = hdev->report_enum[HID_FEATURE_REPORT]. report_id_hash[0x0d]; - if (!report) + if (!report || report->maxfield < 1 || + report->field[0]->report_count < 1) return -EINVAL; usbhid_submit_report(hdev, report, USB_DIR_IN); diff --git a/drivers/hid/hid-pl.c b/drivers/hid/hid-pl.c index 47ed74c46b6..00cd2f8bc04 100644 --- a/drivers/hid/hid-pl.c +++ b/drivers/hid/hid-pl.c @@ -129,8 +129,14 @@ static int plff_init(struct hid_device *hid) strong = &report->field[0]->value[2]; weak = &report->field[0]->value[3]; debug("detected single-field device"); - } else if (report->maxfield >= 4 && report->field[0]->maxusage == 1 && - report->field[0]->usage[0].hid == (HID_UP_LED | 0x43)) { + } else if (report->field[0]->maxusage == 1 && + report->field[0]->usage[0].hid == + (HID_UP_LED | 0x43) && + report->maxfield >= 4 && + report->field[0]->report_count >= 1 && + report->field[1]->report_count >= 1 && + report->field[2]->report_count >= 1 && + report->field[3]->report_count >= 1) { report->field[0]->value[0] = 0x00; report->field[1]->value[0] = 0x00; strong = &report->field[2]->value[0]; diff --git a/drivers/hid/hid-speedlink.c b/drivers/hid/hid-speedlink.c index 60201374171..2b03c9baac3 100644 --- a/drivers/hid/hid-speedlink.c +++ b/drivers/hid/hid-speedlink.c @@ -3,7 +3,7 @@ * Fixes "jumpy" cursor and removes nonexistent keyboard LEDS from * the HID descriptor. * - * Copyright (c) 2011 Stefan Kriwanek + * Copyright (c) 2011, 2013 Stefan Kriwanek */ /* @@ -48,8 +48,13 @@ static int speedlink_event(struct hid_device *hdev, struct hid_field *field, struct hid_usage *usage, __s32 value) { /* No other conditions due to usage_table. */ - /* Fix "jumpy" cursor (invalid events sent by device). */ - if (value == 256) + + /* This fixes the "jumpy" cursor occuring due to invalid events sent + * by the device. Some devices only send them with value==+256, others + * don't. However, catching abs(value)>=256 is restrictive enough not + * to interfere with devices that were bug-free (has been tested). + */ + if (abs(value) >= 256) return 1; /* Drop useless distance 0 events (on button clicks etc.) as well */ if (value == 0) diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 5c4112e650b..d712294b340 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -103,6 +103,8 @@ static const struct hid_blacklist { { USB_VENDOR_ID_SIGMA_MICRO, USB_DEVICE_ID_SIGMA_MICRO_KEYBOARD, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_MOUSEPEN_I608X, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M610X, HID_QUIRK_MULTI_INPUT }, + { USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_DUOSENSE, HID_QUIRK_NO_INIT_REPORTS }, + { 0, 0 } }; diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 17119247ac4..a60a54d8593 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -886,56 +886,54 @@ static int dma_pte_clear_range(struct dmar_domain *domain, return order; } +static void dma_pte_free_level(struct dmar_domain *domain, int level, + struct dma_pte *pte, unsigned long pfn, + unsigned long start_pfn, unsigned long last_pfn) +{ + pfn = max(start_pfn, pfn); + pte = &pte[pfn_level_offset(pfn, level)]; + + do { + unsigned long level_pfn; + struct dma_pte *level_pte; + + if (!dma_pte_present(pte) || dma_pte_superpage(pte)) + goto next; + + level_pfn = pfn & level_mask(level - 1); + level_pte = phys_to_virt(dma_pte_addr(pte)); + + if (level > 2) + dma_pte_free_level(domain, level - 1, level_pte, + level_pfn, start_pfn, last_pfn); + + /* If range covers entire pagetable, free it */ + if (!(start_pfn > level_pfn || + last_pfn < level_pfn + level_size(level))) { + dma_clear_pte(pte); + domain_flush_cache(domain, pte, sizeof(*pte)); + free_pgtable_page(level_pte); + } +next: + pfn += level_size(level); + } while (!first_pte_in_page(++pte) && pfn <= last_pfn); +} + /* free page table pages. last level pte should already be cleared */ static void dma_pte_free_pagetable(struct dmar_domain *domain, unsigned long start_pfn, unsigned long last_pfn) { int addr_width = agaw_to_width(domain->agaw) - VTD_PAGE_SHIFT; - struct dma_pte *first_pte, *pte; - int total = agaw_to_level(domain->agaw); - int level; - unsigned long tmp; - int large_page = 2; BUG_ON(addr_width < BITS_PER_LONG && start_pfn >> addr_width); BUG_ON(addr_width < BITS_PER_LONG && last_pfn >> addr_width); BUG_ON(start_pfn > last_pfn); /* We don't need lock here; nobody else touches the iova range */ - level = 2; - while (level <= total) { - tmp = align_to_level(start_pfn, level); - - /* If we can't even clear one PTE at this level, we're done */ - if (tmp + level_size(level) - 1 > last_pfn) - return; - - do { - large_page = level; - first_pte = pte = dma_pfn_level_pte(domain, tmp, level, &large_page); - if (large_page > level) - level = large_page + 1; - if (!pte) { - tmp = align_to_level(tmp + 1, level + 1); - continue; - } - do { - if (dma_pte_present(pte)) { - free_pgtable_page(phys_to_virt(dma_pte_addr(pte))); - dma_clear_pte(pte); - } - pte++; - tmp += level_size(level); - } while (!first_pte_in_page(pte) && - tmp + level_size(level) - 1 <= last_pfn); + dma_pte_free_level(domain, agaw_to_level(domain->agaw), + domain->pgd, 0, start_pfn, last_pfn); - domain_flush_cache(domain, first_pte, - (void *)pte - (void *)first_pte); - - } while (tmp && tmp + level_size(level) - 1 <= last_pfn); - level++; - } /* free pgd */ if (start_pfn == 0 && last_pfn == DOMAIN_MAX_PFN(domain->gaw)) { free_pgtable_page(domain->pgd); diff --git a/drivers/mmc/host/tmio_mmc_dma.c b/drivers/mmc/host/tmio_mmc_dma.c index fff92860485..491e9ecc92c 100644 --- a/drivers/mmc/host/tmio_mmc_dma.c +++ b/drivers/mmc/host/tmio_mmc_dma.c @@ -104,6 +104,7 @@ static void tmio_mmc_start_dma_rx(struct tmio_mmc_host *host) pio: if (!desc) { /* DMA failed, fall back to PIO */ + tmio_mmc_enable_dma(host, false); if (ret >= 0) ret = -EIO; host->chan_rx = NULL; @@ -116,7 +117,6 @@ static void tmio_mmc_start_dma_rx(struct tmio_mmc_host *host) } dev_warn(&host->pdev->dev, "DMA failed: %d, falling back to PIO\n", ret); - tmio_mmc_enable_dma(host, false); } dev_dbg(&host->pdev->dev, "%s(): desc %p, cookie %d, sg[%d]\n", __func__, @@ -185,6 +185,7 @@ static void tmio_mmc_start_dma_tx(struct tmio_mmc_host *host) pio: if (!desc) { /* DMA failed, fall back to PIO */ + tmio_mmc_enable_dma(host, false); if (ret >= 0) ret = -EIO; host->chan_tx = NULL; @@ -197,7 +198,6 @@ static void tmio_mmc_start_dma_tx(struct tmio_mmc_host *host) } dev_warn(&host->pdev->dev, "DMA failed: %d, falling back to PIO\n", ret); - tmio_mmc_enable_dma(host, false); } dev_dbg(&host->pdev->dev, "%s(): desc %p, cookie %d\n", __func__, diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index f86ee0c7f31..503ff9f632f 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -1030,6 +1030,10 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah, * is_on == 0 means MRC CCK is OFF (more noise imm) */ bool is_on = param ? 1 : 0; + + if (ah->caps.rx_chainmask == 1) + break; + REG_RMW_FIELD(ah, AR_PHY_MRC_CCK_CTRL, AR_PHY_MRC_CCK_ENABLE, is_on); REG_RMW_FIELD(ah, AR_PHY_MRC_CCK_CTRL, diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 4bfb44a094d..e2ab182dca5 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -78,10 +78,6 @@ struct ath_config { sizeof(struct ath_buf_state)); \ } while (0) -#define ATH_RXBUF_RESET(_bf) do { \ - (_bf)->bf_stale = false; \ - } while (0) - /** * enum buffer_type - Buffer type flags * @@ -314,6 +310,7 @@ struct ath_rx { struct ath_buf *rx_bufptr; struct ath_rx_edma rx_edma[ATH9K_RX_QUEUE_MAX]; + struct ath_buf *buf_hold; struct sk_buff *frag; }; diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 039bac7e0c6..2e6583d3af8 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -78,8 +78,6 @@ static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf) struct ath_desc *ds; struct sk_buff *skb; - ATH_RXBUF_RESET(bf); - ds = bf->bf_desc; ds->ds_link = 0; /* link to null */ ds->ds_data = bf->bf_buf_addr; @@ -106,6 +104,14 @@ static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf) sc->rx.rxlink = &ds->ds_link; } +static void ath_rx_buf_relink(struct ath_softc *sc, struct ath_buf *bf) +{ + if (sc->rx.buf_hold) + ath_rx_buf_link(sc, sc->rx.buf_hold); + + sc->rx.buf_hold = bf; +} + static void ath_setdefantenna(struct ath_softc *sc, u32 antenna) { /* XXX block beacon interrupts */ @@ -153,7 +159,6 @@ static bool ath_rx_edma_buf_link(struct ath_softc *sc, skb = bf->bf_mpdu; - ATH_RXBUF_RESET(bf); memset(skb->data, 0, ah->caps.rx_status_len); dma_sync_single_for_device(sc->dev, bf->bf_buf_addr, ah->caps.rx_status_len, DMA_TO_DEVICE); @@ -485,6 +490,7 @@ int ath_startrecv(struct ath_softc *sc) if (list_empty(&sc->rx.rxbuf)) goto start_recv; + sc->rx.buf_hold = NULL; sc->rx.rxlink = NULL; list_for_each_entry_safe(bf, tbf, &sc->rx.rxbuf, list) { ath_rx_buf_link(sc, bf); @@ -734,6 +740,9 @@ static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc, } bf = list_first_entry(&sc->rx.rxbuf, struct ath_buf, list); + if (bf == sc->rx.buf_hold) + return NULL; + ds = bf->bf_desc; /* @@ -1974,7 +1983,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) if (edma) { ath_rx_edma_buf_link(sc, qtype); } else { - ath_rx_buf_link(sc, bf); + ath_rx_buf_relink(sc, bf); ath9k_hw_rxena(ah); } } while (1); diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 12a42f2c1e8..3d0aa4723ff 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -2479,6 +2479,7 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an) for (acno = 0, ac = &an->ac[acno]; acno < WME_NUM_AC; acno++, ac++) { ac->sched = false; + ac->clear_ps_filter = true; ac->txq = sc->tx.txq_map[acno]; INIT_LIST_HEAD(&ac->tid_q); } diff --git a/drivers/net/wireless/brcm80211/brcmsmac/dma.c b/drivers/net/wireless/brcm80211/brcmsmac/dma.c index 11054ae9d4f..9a18405865b 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/dma.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/dma.c @@ -1013,9 +1013,10 @@ static bool dma64_rxidle(struct dma_info *di) /* * post receive buffers - * return false is refill failed completely and ring is empty this will stall - * the rx dma and user might want to call rxfill again asap. This unlikely - * happens on memory-rich NIC, but often on memory-constrained dongle + * Return false if refill failed completely or dma mapping failed. The ring + * is empty, which will stall the rx dma and user might want to call rxfill + * again asap. This is unlikely to happen on a memory-rich NIC, but often on + * memory-constrained dongle. */ bool dma_rxfill(struct dma_pub *pub) { @@ -1074,6 +1075,8 @@ bool dma_rxfill(struct dma_pub *pub) pa = dma_map_single(di->dmadev, p->data, di->rxbufsize, DMA_FROM_DEVICE); + if (dma_mapping_error(di->dmadev, pa)) + return false; /* save the free packet pointer */ di->rxp[rxout] = p; @@ -1294,7 +1297,11 @@ int dma_txfast(struct dma_pub *pub, struct sk_buff *p, bool commit) /* get physical address of buffer start */ pa = dma_map_single(di->dmadev, data, len, DMA_TO_DEVICE); - + /* if mapping failed, free skb */ + if (dma_mapping_error(di->dmadev, pa)) { + brcmu_pkt_buf_free_skb(p); + return; + } /* With a DMA segment list, Descriptor table is filled * using the segment list instead of looping over * buffers in multi-chain DMA. Therefore, EOF for SGLIST diff --git a/drivers/of/base.c b/drivers/of/base.c index 58064498694..1c207f23b11 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -1227,6 +1227,7 @@ void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align)) ap = dt_alloc(sizeof(*ap) + len + 1, 4); if (!ap) continue; + memset(ap, 0, sizeof(*ap) + len + 1); ap->alias = start; of_alias_add(ap, np, id, start, len); } diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 105fff2ecd5..05973a49131 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -2225,14 +2225,9 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer) } } - if (modepage == 0x3F) { - sd_printk(KERN_ERR, sdkp, "No Caching mode page " - "present\n"); - goto defaults; - } else if ((buffer[offset] & 0x3f) != modepage) { - sd_printk(KERN_ERR, sdkp, "Got wrong page\n"); - goto defaults; - } + sd_printk(KERN_ERR, sdkp, "No Caching mode page found\n"); + goto defaults; + Page_found: if (modepage == 8) { sdkp->WCE = ((buffer[offset + 2] & 0x04) != 0); diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c index 95ebc267bb7..e3adb382d72 100644 --- a/drivers/staging/comedi/drivers/dt282x.c +++ b/drivers/staging/comedi/drivers/dt282x.c @@ -407,8 +407,9 @@ struct dt282x_private { } \ udelay(5); \ } \ - if (_i) \ + if (_i) { \ b \ + } \ } while (0) static int dt282x_attach(struct comedi_device *dev, diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 9dd51f7fb64..1434ee9ecb3 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -233,6 +233,7 @@ static void wdm_in_callback(struct urb *urb) static void wdm_int_callback(struct urb *urb) { int rv = 0; + int responding; int status = urb->status; struct wdm_device *desc; struct usb_cdc_notification *dr; @@ -286,8 +287,8 @@ static void wdm_int_callback(struct urb *urb) spin_lock(&desc->iuspin); clear_bit(WDM_READ, &desc->flags); - set_bit(WDM_RESPONDING, &desc->flags); - if (!test_bit(WDM_DISCONNECTING, &desc->flags) + responding = test_and_set_bit(WDM_RESPONDING, &desc->flags); + if (!responding && !test_bit(WDM_DISCONNECTING, &desc->flags) && !test_bit(WDM_SUSPENDING, &desc->flags)) { rv = usb_submit_urb(desc->response, GFP_ATOMIC); dev_dbg(&desc->intf->dev, "%s: usb_submit_urb %d", @@ -687,16 +688,20 @@ static void wdm_rxwork(struct work_struct *work) { struct wdm_device *desc = container_of(work, struct wdm_device, rxwork); unsigned long flags; - int rv; + int rv = 0; + int responding; spin_lock_irqsave(&desc->iuspin, flags); if (test_bit(WDM_DISCONNECTING, &desc->flags)) { spin_unlock_irqrestore(&desc->iuspin, flags); } else { + responding = test_and_set_bit(WDM_RESPONDING, &desc->flags); spin_unlock_irqrestore(&desc->iuspin, flags); - rv = usb_submit_urb(desc->response, GFP_KERNEL); + if (!responding) + rv = usb_submit_urb(desc->response, GFP_KERNEL); if (rv < 0 && rv != -EPERM) { spin_lock_irqsave(&desc->iuspin, flags); + clear_bit(WDM_RESPONDING, &desc->flags); if (!test_bit(WDM_DISCONNECTING, &desc->flags)) schedule_work(&desc->rxwork); spin_unlock_irqrestore(&desc->iuspin, flags); diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c index f4bdd0ce8d5..78609d30262 100644 --- a/drivers/usb/core/config.c +++ b/drivers/usb/core/config.c @@ -424,7 +424,8 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx, memcpy(&config->desc, buffer, USB_DT_CONFIG_SIZE); if (config->desc.bDescriptorType != USB_DT_CONFIG || - config->desc.bLength < USB_DT_CONFIG_SIZE) { + config->desc.bLength < USB_DT_CONFIG_SIZE || + config->desc.bLength > size) { dev_err(ddev, "invalid descriptor for config index %d: " "type = 0x%X, length = %d\n", cfgidx, config->desc.bDescriptorType, config->desc.bLength); diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c index a797d51ecbe..77477ca5cfa 100644 --- a/drivers/usb/host/ehci-mxc.c +++ b/drivers/usb/host/ehci-mxc.c @@ -298,7 +298,7 @@ static int __exit ehci_mxc_drv_remove(struct platform_device *pdev) if (pdata && pdata->exit) pdata->exit(pdev); - if (pdata->otg) + if (pdata && pdata->otg) usb_phy_shutdown(pdata->otg); usb_remove_hcd(hcd); diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index 85781e869d2..99e6207f9c4 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -32,7 +32,7 @@ static void xhci_plat_quirks(struct device *dev, struct xhci_hcd *xhci) * here that the generic code does not try to make a pci_dev from our * dev struct in order to setup MSI */ - xhci->quirks |= XHCI_BROKEN_MSI; + xhci->quirks |= XHCI_PLAT; if (!pdata) return; diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index be1f63ae1d6..488a32f4b4e 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -332,9 +332,14 @@ static void xhci_cleanup_msix(struct xhci_hcd *xhci) static int xhci_try_enable_msi(struct usb_hcd *hcd) { struct xhci_hcd *xhci = hcd_to_xhci(hcd); - struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller); + struct pci_dev *pdev; int ret; + /* The xhci platform device has set up IRQs through usb_add_hcd. */ + if (xhci->quirks & XHCI_PLAT) + return 0; + + pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller); /* * Some Fresco Logic host controllers advertise MSI, but fail to * generate interrupts. Don't even try to enable MSI. @@ -3506,10 +3511,21 @@ void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev) { struct xhci_hcd *xhci = hcd_to_xhci(hcd); struct xhci_virt_device *virt_dev; + struct device *dev = hcd->self.controller; unsigned long flags; u32 state; int i, ret; +#ifndef CONFIG_USB_DEFAULT_PERSIST + /* + * We called pm_runtime_get_noresume when the device was attached. + * Decrement the counter here to allow controller to runtime suspend + * if no devices remain. + */ + if (xhci->quirks & XHCI_RESET_ON_RESUME) + pm_runtime_put_noidle(dev); +#endif + ret = xhci_check_args(hcd, udev, NULL, 0, true, __func__); /* If the host is halted due to driver unload, we still need to free the * device. @@ -3581,6 +3597,7 @@ static int xhci_reserve_host_control_ep_resources(struct xhci_hcd *xhci) int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev) { struct xhci_hcd *xhci = hcd_to_xhci(hcd); + struct device *dev = hcd->self.controller; unsigned long flags; int timeleft; int ret; @@ -3633,6 +3650,16 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev) goto disable_slot; } udev->slot_id = xhci->slot_id; + +#ifndef CONFIG_USB_DEFAULT_PERSIST + /* + * If resetting upon resume, we can't put the controller into runtime + * suspend if there is a device attached. + */ + if (xhci->quirks & XHCI_RESET_ON_RESUME) + pm_runtime_get_noresume(dev); +#endif + /* Is this a LS or FS device under a HS hub? */ /* Hub or peripherial? */ return 1; diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 8f11fc9335b..7b717576017 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1505,6 +1505,7 @@ struct xhci_hcd { #define XHCI_SPURIOUS_REBOOT (1 << 13) #define XHCI_COMP_MODE_QUIRK (1 << 14) #define XHCI_AVOID_BEI (1 << 15) +#define XHCI_PLAT (1 << 16) /* * In Synopsis DWC3 controller, PORTSC register access involves multiple clock * domains. When the software does a PORTSC write, handshakes are needed diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index cdde45dee67..4491830bc8f 100644 --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c @@ -383,7 +383,7 @@ static int write_parport_reg_nonblock(struct mos7715_parport *mos_parport, kfree(urbtrack); return -ENOMEM; } - urbtrack->setup = kmalloc(sizeof(*urbtrack->setup), GFP_KERNEL); + urbtrack->setup = kmalloc(sizeof(*urbtrack->setup), GFP_ATOMIC); if (!urbtrack->setup) { usb_free_urb(urbtrack->urb); kfree(urbtrack); @@ -391,8 +391,8 @@ static int write_parport_reg_nonblock(struct mos7715_parport *mos_parport, } urbtrack->setup->bRequestType = (__u8)0x40; urbtrack->setup->bRequest = (__u8)0x0e; - urbtrack->setup->wValue = get_reg_value(reg, dummy); - urbtrack->setup->wIndex = get_reg_index(reg); + urbtrack->setup->wValue = cpu_to_le16(get_reg_value(reg, dummy)); + urbtrack->setup->wIndex = cpu_to_le16(get_reg_index(reg)); urbtrack->setup->wLength = 0; usb_fill_control_urb(urbtrack->urb, usbdev, usb_sndctrlpipe(usbdev, 0), diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c index 7e34beed9ea..3275bde6ad7 100644 --- a/drivers/xen/grant-table.c +++ b/drivers/xen/grant-table.c @@ -641,9 +641,18 @@ void gnttab_request_free_callback(struct gnttab_free_callback *callback, void (*fn)(void *), void *arg, u16 count) { unsigned long flags; + struct gnttab_free_callback *cb; + spin_lock_irqsave(&gnttab_list_lock, flags); - if (callback->next) - goto out; + + /* Check if the callback is already on the list */ + cb = gnttab_free_callback_list; + while (cb) { + if (cb == callback) + goto out; + cb = cb->next; + } + callback->fn = fn; callback->arg = arg; callback->count = count; diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index e7fe81d3a56..4ac06b0896c 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -362,6 +362,7 @@ cifs_reconnect(struct TCP_Server_Info *server) try_to_freeze(); /* we should try only the port we connected to before */ + mutex_lock(&server->srv_mutex); rc = generic_ip_connect(server); if (rc) { cFYI(1, "reconnect error %d", rc); @@ -373,6 +374,7 @@ cifs_reconnect(struct TCP_Server_Info *server) server->tcpStatus = CifsNeedNegotiate; spin_unlock(&GlobalMid_Lock); } + mutex_unlock(&server->srv_mutex); } while (server->tcpStatus == CifsNeedReconnect); return rc; diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index d48478a864b..373b25145e0 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -1503,6 +1503,8 @@ static int fuse_setxattr(struct dentry *entry, const char *name, fc->no_setxattr = 1; err = -EOPNOTSUPP; } + if (!err) + fuse_invalidate_attr(inode); return err; } @@ -1632,6 +1634,8 @@ static int fuse_removexattr(struct dentry *entry, const char *name) fc->no_removexattr = 1; err = -EOPNOTSUPP; } + if (!err) + fuse_invalidate_attr(inode); return err; } diff --git a/fs/fuse/file.c b/fs/fuse/file.c index d96318baa13..34d906edc69 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -1330,7 +1330,6 @@ static int fuse_writepage_locked(struct page *page) inc_bdi_stat(mapping->backing_dev_info, BDI_WRITEBACK); inc_zone_page_state(tmp_page, NR_WRITEBACK_TEMP); - end_page_writeback(page); spin_lock(&fc->lock); list_add(&req->writepages_entry, &fi->writepages); @@ -1338,6 +1337,8 @@ static int fuse_writepage_locked(struct page *page) fuse_flush_writepages(inode); spin_unlock(&fc->lock); + end_page_writeback(page); + return 0; err_free: diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c index 29037c365ba..e92a342f14e 100644 --- a/fs/isofs/inode.c +++ b/fs/isofs/inode.c @@ -119,8 +119,8 @@ static void destroy_inodecache(void) static int isofs_remount(struct super_block *sb, int *flags, char *data) { - /* we probably want a lot more here */ - *flags |= MS_RDONLY; + if (!(*flags & MS_RDONLY)) + return -EROFS; return 0; } @@ -769,15 +769,6 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent) */ s->s_maxbytes = 0x80000000000LL; - /* - * The CDROM is read-only, has no nodes (devices) on it, and since - * all of the files appear to be owned by root, we really do not want - * to allow suid. (suid or devices will not show up unless we have - * Rock Ridge extensions) - */ - - s->s_flags |= MS_RDONLY /* | MS_NODEV | MS_NOSUID */; - /* Set this for reference. Its not currently used except on write which we don't have .. */ @@ -1536,6 +1527,9 @@ struct inode *isofs_iget(struct super_block *sb, static struct dentry *isofs_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) { + /* We don't support read-write mounts */ + if (!(flags & MS_RDONLY)) + return ERR_PTR(-EACCES); return mount_bdev(fs_type, flags, dev_name, data, isofs_fill_super); } diff --git a/fs/ocfs2/extent_map.c b/fs/ocfs2/extent_map.c index 7eb1c0c7c16..cf228479879 100644 --- a/fs/ocfs2/extent_map.c +++ b/fs/ocfs2/extent_map.c @@ -782,7 +782,6 @@ int ocfs2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, cpos = map_start >> osb->s_clustersize_bits; mapping_end = ocfs2_clusters_for_bytes(inode->i_sb, map_start + map_len); - mapping_end -= cpos; is_last = 0; while (cpos < mapping_end && !is_last) { u32 fe_flags; diff --git a/include/linux/hid.h b/include/linux/hid.h index 773b4acf344..a11ec22abb6 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -420,10 +420,12 @@ struct hid_report { struct hid_device *device; /* associated device */ }; +#define HID_MAX_IDS 256 + struct hid_report_enum { unsigned numbered; struct list_head report_list; - struct hid_report *report_id_hash[256]; + struct hid_report *report_id_hash[HID_MAX_IDS]; }; #define HID_REPORT_TYPES 3 diff --git a/include/linux/rculist.h b/include/linux/rculist.h index 6f95e241ed6..3863352656e 100644 --- a/include/linux/rculist.h +++ b/include/linux/rculist.h @@ -254,8 +254,9 @@ static inline void list_splice_init_rcu(struct list_head *list, */ #define list_first_or_null_rcu(ptr, type, member) \ ({struct list_head *__ptr = (ptr); \ - struct list_head __rcu *__next = list_next_rcu(__ptr); \ - likely(__ptr != __next) ? container_of(__next, type, member) : NULL; \ + struct list_head *__next = ACCESS_ONCE(__ptr->next); \ + likely(__ptr != __next) ? \ + list_entry_rcu(__next, type, member) : NULL; \ }) /** diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h index 3a44b62ef3b..e3f6e193631 100644 --- a/include/media/v4l2-ctrls.h +++ b/include/media/v4l2-ctrls.h @@ -22,6 +22,7 @@ #define _V4L2_CTRLS_H #include +#include #include /* forward references */ diff --git a/mm/huge_memory.c b/mm/huge_memory.c index ef99c15fa36..3da5c0bff3b 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -1894,6 +1894,8 @@ static void collapse_huge_page(struct mm_struct *mm, goto out; vma = find_vma(mm, address); + if (!vma) + goto out; hstart = (vma->vm_start + ~HPAGE_PMD_MASK) & HPAGE_PMD_MASK; hend = vma->vm_end & HPAGE_PMD_MASK; if (address < hstart || address + HPAGE_PMD_SIZE > hend) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index ba1a0339f52..3d914da3f1f 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -4349,7 +4349,13 @@ static int compare_thresholds(const void *a, const void *b) const struct mem_cgroup_threshold *_a = a; const struct mem_cgroup_threshold *_b = b; - return _a->threshold - _b->threshold; + if (_a->threshold > _b->threshold) + return 1; + + if (_a->threshold < _b->threshold) + return -1; + + return 0; } static int mem_cgroup_oom_notify_cb(struct mem_cgroup *memcg) diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 1f350522bed..e6083c1459b 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -2602,6 +2602,7 @@ static struct snd_pci_quirk msi_black_list[] __devinitdata = { SND_PCI_QUIRK(0x1043, 0x81f2, "ASUS", 0), /* Athlon64 X2 + nvidia */ SND_PCI_QUIRK(0x1043, 0x81f6, "ASUS", 0), /* nvidia */ SND_PCI_QUIRK(0x1043, 0x822d, "ASUS", 0), /* Athlon64 X2 + nvidia MCP55 */ + SND_PCI_QUIRK(0x1179, 0xfb44, "Toshiba Satellite C870", 0), /* AMD Hudson */ SND_PCI_QUIRK(0x1849, 0x0888, "ASRock", 0), /* Athlon64 X2 + nvidia */ SND_PCI_QUIRK(0xa0a0, 0x0575, "Aopen MZ915-M", 0), /* ICH6 */ {} diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index 840d72086d0..ddb0d904a35 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c @@ -790,9 +790,9 @@ static int wm8960_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, if (pll_div.k) { reg |= 0x20; - snd_soc_write(codec, WM8960_PLL2, (pll_div.k >> 18) & 0x3f); - snd_soc_write(codec, WM8960_PLL3, (pll_div.k >> 9) & 0x1ff); - snd_soc_write(codec, WM8960_PLL4, pll_div.k & 0x1ff); + snd_soc_write(codec, WM8960_PLL2, (pll_div.k >> 16) & 0xff); + snd_soc_write(codec, WM8960_PLL3, (pll_div.k >> 8) & 0xff); + snd_soc_write(codec, WM8960_PLL4, pll_div.k & 0xff); } snd_soc_write(codec, WM8960_PLL1, reg); From 2c8f3aa0c569d363eaa9f23d86b1b001f23a9363 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 1 Oct 2013 09:12:49 -0700 Subject: [PATCH 133/215] Linux 3.4.64 - 21 commits squashed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Revert "sctp: fix call to SCTP_CMD_PROCESS_SACK in sctp_cmd_interpreter()" This reverts commit c2f5b7507ac5d808f29287d77ee6148358d7fbfe which is commit f6e80abeab928b7c47cc1fbf53df13b4398a2bec. Michal writes: Mainline commit f6e80abe was introduced in v3.7-rc2 as a follow-up fix to commit edfee033 sctp: check src addr when processing SACK to update transport state (from v3.7-rc1) which changed the interpretation of third argument to sctp_cmd_process_sack() and sctp_outq_sack(). But as commit edfee033 has never been backported to stable branches, backport of commit f6e80abe actually breaks the code rather than fixing it. Reported-by: Michal Kubecek Cc: Zijie Pan Cc: Nicolas Dichtel Cc: Vlad Yasevich Acked-by: David S. Miller Signed-off-by: Greg Kroah-Hartman net: usb: cdc_ether: Use wwan interface for Telit modules commit 0092820407901a0b2c4e343e85f96bb7abfcded1 upstream. Signed-off-by: Fabio Porcedda Acked-by: Oliver Neukum Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman rt2800: fix wrong TX power compensation commit 6e956da2027c767859128b9bfef085cf2a8e233b upstream. We should not do temperature compensation on devices without EXTERNAL_TX_ALC bit set (called DynamicTxAgcControl on vendor driver). Such devices can have totally bogus TSSI parameters on the EEPROM, but still threaded by us as valid and result doing wrong TX power calculations. This fix inability to connect to AP on slightly longer distance on some Ralink chips/devices. Reported-and-tested-by: Fabien ADAM Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman sched/fair: Fix small race where child->se.parent,cfs_rq might point to invalid ones commit 6c9a27f5da9609fca46cb2b183724531b48f71ad upstream. There is a small race between copy_process() and cgroup_attach_task() where child->se.parent,cfs_rq points to invalid (old) ones. parent doing fork() | someone moving the parent to another cgroup -------------------------------+--------------------------------------------- copy_process() + dup_task_struct() -> parent->se is copied to child->se. se.parent,cfs_rq of them point to old ones. cgroup_attach_task() + cgroup_task_migrate() -> parent->cgroup is updated. + cpu_cgroup_attach() + sched_move_task() + task_move_group_fair() +- set_task_rq() -> se.parent,cfs_rq of parent are updated. + cgroup_fork() -> parent->cgroup is copied to child->cgroup. (*1) + sched_fork() + task_fork_fair() -> se.parent,cfs_rq of child are accessed while they point to old ones. (*2) In the worst case, this bug can lead to "use-after-free" and cause a panic, because it's new cgroup's refcount that is incremented at (*1), so the old cgroup(and related data) can be freed before (*2). In fact, a panic caused by this bug was originally caught in RHEL6.4. BUG: unable to handle kernel NULL pointer dereference at (null) IP: [] sched_slice+0x6e/0xa0 [...] Call Trace: [] place_entity+0x75/0xa0 [] task_fork_fair+0xaa/0x160 [] sched_fork+0x6b/0x140 [] copy_process+0x5b2/0x1450 [] ? wake_up_new_task+0xd9/0x130 [] do_fork+0x94/0x460 [] ? sys_wait4+0xae/0x100 [] sys_clone+0x28/0x30 [] stub_clone+0x13/0x20 [] ? system_call_fastpath+0x16/0x1b Signed-off-by: Daisuke Nishimura Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/039601ceae06$733d3130$59b79390$@mxp.nes.nec.co.jp Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman HID: provide a helper for validating hid reports commit 331415ff16a12147d57d5c953f3a961b7ede348b upstream. Many drivers need to validate the characteristics of their HID report during initialization to avoid misusing the reports. This adds a common helper to perform validation of the report exisitng, the field existing, and the expected number of values within the field. Signed-off-by: Kees Cook Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman HID: zeroplus: validate output report details commit 78214e81a1bf43740ce89bb5efda78eac2f8ef83 upstream. The zeroplus HID driver was not checking the size of allocated values in fields it used. A HID device could send a malicious output report that would cause the driver to write beyond the output report allocation during initialization, causing a heap overflow: [ 1442.728680] usb 1-1: New USB device found, idVendor=0c12, idProduct=0005 ... [ 1466.243173] BUG kmalloc-192 (Tainted: G W ): Redzone overwritten CVE-2013-2889 Signed-off-by: Kees Cook Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman drm/ttm: fix the tt_populated check in ttm_tt_destroy() commit 182b17c8dc4e83aab000ce86587b6810e515da87 upstream. After a vmalloc failure in ttm_dma_tt_alloc_page_directory(), ttm_dma_tt_init() will call ttm_tt_destroy() to cleanup, and end up inside the driver's unpopulate() hook when populate() has never yet been called. On nouveau, the first issue to be hit because of this is that dma_address[] may be a NULL pointer. After working around this, ttm_pool_unpopulate() may potentially hit the same issue with the pages[] array. It seems to make more sense to avoid calling unpopulate on already unpopulated TTMs than to add checks to all the implementations. Signed-off-by: Ben Skeggs Reviewed-by: Thomas Hellstrom Cc: Jerome Glisse Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman drm/radeon: fix LCD record parsing commit 95663948ba22a4be8b99acd67fbf83e86ddffba4 upstream. If the LCD table contains an EDID record, properly account for the edid size when walking through the records. This should fix error messages about unknown LCD records. Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman drm/radeon: fix endian bugs in hw i2c atom routines commit 4543eda52113d1e2cc0e9bf416f79597e6ef1ec7 upstream. Need to swap the data fetched over i2c properly. This is the same fix as the endian fix for aux channel transactions. Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman drm/radeon: update line buffer allocation for dce4.1/5 commit 0b31e02363b0db4e7931561bc6c141436e729d9f upstream. We need to allocate line buffer to each display when setting up the watermarks. Failure to do so can lead to a blank screen. This fixes blank screen problems on dce4.1/5 asics. Based on an initial fix from: Jay Cornwall Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman drm/radeon: update line buffer allocation for dce6 commit 290d24576ccf1aa0373d2185cedfe262d0d4952a upstream. We need to allocate line buffer to each display when setting up the watermarks. Failure to do so can lead to a blank screen. This fixes blank screen problems on dce6 asics. Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=64850 Based on an initial fix from: Jay Cornwall Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman drm/radeon: fix resume on some rs4xx boards (v2) commit acf88deb8ddbb73acd1c3fa32fde51af9153227f upstream. Setting MC_MISC_CNTL.GART_INDEX_REG_EN causes hangs on some boards on resume. The systems seem to work fine without touching this bit so leave it as is. v2: read-modify-write the GART_INDEX_REG_EN bit. I suspect the problem is that we are losing the other settings in the register. fixes: https://bugs.freedesktop.org/show_bug.cgi?id=52952 Reported-by: Ondrej Zary Tested-by: Daniel Tobias Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman drm/radeon: fix handling of variable sized arrays for router objects commit fb93df1c2d8b3b1fb16d6ee9e32554e0c038815d upstream. The table has the following format: typedef struct _ATOM_SRC_DST_TABLE_FOR_ONE_OBJECT //usSrcDstTableOffset pointing to this structure { UCHAR ucNumberOfSrc; USHORT usSrcObjectID[1]; UCHAR ucNumberOfDst; USHORT usDstObjectID[1]; }ATOM_SRC_DST_TABLE_FOR_ONE_OBJECT; usSrcObjectID[] and usDstObjectID[] are variably sized, so we can't access them directly. Use pointers and update the offset appropriately when accessing the Dst members. Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman drm/radeon/atom: workaround vbios bug in transmitter table on rs880 (v2) commit 91f3a6aaf280294b07c05dfe606e6c27b7ba3c72 upstream. The OUTPUT_ENABLE action jumps past the point in the coder where the data_offset is set on certain rs780 cards. This worked previously because the OUTPUT_ENABLE action is always called immediately after the ENABLE action so the data_offset remained set. In 6f8bbaf568c7f2c497558bfd04654c0b9841ad57 (drm/radeon/atom: initialize more atom interpretor elements to 0), we explictly reset data_offset to 0 between atom calls which then caused this to fail. The fix is to just skip calling the OUTPUT_ENABLE action on the problematic chipsets. The ENABLE action does the same thing and more. Ultimately, we could probably drop the OUTPUT_ENABLE action all together on DCE3 asics. fixes: https://bugzilla.kernel.org/show_bug.cgi?id=60791 v2: only rs880 seems to be affected Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman cgroup: fail if monitored file and event_control are in different cgroup commit f169007b2773f285e098cb84c74aac0154d65ff7 upstream. If we pass fd of memory.usage_in_bytes of cgroup A to cgroup.event_control of cgroup B, then we won't get memory usage notification from A but B! What's worse, if A and B are in different mount hierarchy, we'll end up accessing NULL pointer! Disallow this kind of invalid usage. Signed-off-by: Li Zefan Acked-by: Kirill A. Shutemov Signed-off-by: Tejun Heo Cc: Weng Meiling Signed-off-by: Greg Kroah-Hartman perf: Clarify perf_cpu_context::active_pmu usage by renaming it to ::unique_pmu commit 3f1f33206c16c7b3839d71372bc2ac3f305aa802 upstream. Stephane thought the perf_cpu_context::active_pmu name confusing and suggested using 'unique_pmu' instead. This pointer is a pointer to a 'random' pmu sharing the cpuctx instance, therefore limiting a for_each_pmu loop to those where cpuctx->unique_pmu matches the pmu we get a loop over unique cpuctx instances. Suggested-by: Stephane Eranian Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/n/tip-kxyjqpfj2fn9gt7kwu5ag9ks@git.kernel.org Signed-off-by: Ingo Molnar Cc: Li Zefan Signed-off-by: Greg Kroah-Hartman perf: Fix perf_cgroup_switch for sw-events commit 95cf59ea72331d0093010543b8951bb43f262cac upstream. Jiri reported that he could trigger the WARN_ON_ONCE() in perf_cgroup_switch() using sw-events. This is because sw-events share a cpuctx with multiple PMUs. Use the ->unique_pmu pointer to limit the pmu iteration to unique cpuctx instances. Reported-and-Tested-by: Jiri Olsa Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/n/tip-so7wi2zf3jjzrwcutm2mkz0j@git.kernel.org Signed-off-by: Ingo Molnar Cc: Li Zefan Signed-off-by: Greg Kroah-Hartman fanotify: dont merge permission events commit 03a1cec1f17ac1a6041996b3e40f96b5a2f90e1b upstream. Boyd Yang reported a problem for the case that multiple threads of the same thread group are waiting for a reponse for a permission event. In this case it is possible that some of the threads are never woken up, even if the response for the event has been received (see http://marc.info/?l=linux-kernel&m=131822913806350&w=2). The reason is that we are currently merging permission events if they belong to the same thread group. But we are not prepared to wake up more than one waiter for each event. We do wait_event(group->fanotify_data.access_waitq, event->response || atomic_read(&group->fanotify_data.bypass_perm)); and after that event->response = 0; which is the reason that even if we woke up all waiters for the same event some of them may see event->response being already set 0 again, then go back to sleep and block forever. With this patch we avoid that more than one thread is waiting for a response by not merging permission events for the same thread group any more. Reported-by: Boyd Yang Signed-off-by: Lino Sanfilippo Signed-off-by: Eric Paris Cc: Mihai DonÈ›u Signed-off-by: Greg Kroah-Hartman perf tools: Handle JITed code in shared memory commit 89365e6c9ad4c0e090e4c6a4b67a3ce319381d89 upstream. Need to check for /dev/zero. Most likely more strings are missing too. Signed-off-by: Andi Kleen Link: http://lkml.kernel.org/r/1366848182-30449-1-git-send-email-andi@firstfloor.org Signed-off-by: Arnaldo Carvalho de Melo Cc: Vinson Lee Signed-off-by: Greg Kroah-Hartman sfc: Fix efx_rx_buf_offset() for recycled pages This bug fix is only for stable branches older than 3.10. The bug was fixed upstream by commit 2768935a4660 ('sfc: reuse pages to avoid DMA mapping/unmapping costs'), but that change is totally unsuitable for stable. Commit b590ace09d51 ('sfc: Fix efx_rx_buf_offset() in the presence of swiotlb') added an explicit page_offset member to struct efx_rx_buffer, which must be set consistently with the u.page and dma_addr fields. However, it failed to add the necessary assignment in efx_resurrect_rx_buffer(). It also did not correct the calculation of efx_rx_buffer::dma_addr in efx_resurrect_rx_buffer(), which assumes that DMA-mapping a page will result in a page-aligned DMA address (exactly what swiotlb violates). Add the assignment of efx_rx_buffer::page_offset and change the calculation of dma_addr to make use of it. Signed-off-by: Ben Hutchings Acked-by: David Miller Signed-off-by: Greg Kroah-Hartman kernel-doc: bugfix - multi-line macros commit 654784284430bf2739985914b65e09c7c35a7273 upstream. Prior to this patch the following code breaks: /** * multiline_example - this breaks kernel-doc */ #define multiline_example( \ myparam) Producing this error: Error(somefile.h:983): cannot understand prototype: 'multiline_example( \ ' This patch fixes the issue by appending all lines ending in a blackslash (optionally followed by whitespace), removing the backslash and any whitespace after it prior to appending (just like the C pre-processor would). This fixes a break in kerel-doc introduced by the additions to rbtree.h. Signed-off-by: Daniel Santos Cc: Randy Dunlap Cc: Michal Marek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Cc: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- Makefile | 2 +- drivers/gpu/drm/radeon/atombios_dp.c | 6 +-- drivers/gpu/drm/radeon/atombios_encoders.c | 8 ++- drivers/gpu/drm/radeon/atombios_i2c.c | 4 +- drivers/gpu/drm/radeon/evergreen.c | 25 ++++++++-- drivers/gpu/drm/radeon/evergreend.h | 4 ++ drivers/gpu/drm/radeon/radeon_atombios.c | 13 +++-- drivers/gpu/drm/radeon/rs400.c | 9 ++-- drivers/gpu/drm/radeon/si.c | 23 +++++++-- drivers/gpu/drm/radeon/sid.h | 4 ++ drivers/gpu/drm/ttm/ttm_tt.c | 2 +- drivers/hid/hid-core.c | 58 ++++++++++++++++++++++ drivers/hid/hid-zpff.c | 18 ++----- drivers/net/ethernet/sfc/rx.c | 3 +- drivers/net/usb/cdc_ether.c | 5 ++ drivers/net/wireless/rt2x00/rt2800lib.c | 7 +++ fs/notify/fanotify/fanotify.c | 6 +++ include/linux/hid.h | 4 ++ include/linux/perf_event.h | 2 +- kernel/cgroup.c | 11 ++++ kernel/events/core.c | 21 ++++---- kernel/sched/fair.c | 14 ++++-- net/sctp/sm_sideeffect.c | 3 +- scripts/kernel-doc | 3 ++ tools/perf/util/map.c | 1 + 25 files changed, 202 insertions(+), 54 deletions(-) diff --git a/Makefile b/Makefile index 568cabdfe56..057218555ef 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 4 -SUBLEVEL = 63 +SUBLEVEL = 64 EXTRAVERSION = NAME = Saber-toothed Squirrel diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c index 505f27e2c08..8d1724c42b6 100644 --- a/drivers/gpu/drm/radeon/atombios_dp.c +++ b/drivers/gpu/drm/radeon/atombios_dp.c @@ -51,7 +51,7 @@ static char *pre_emph_names[] = { * or from atom. Note that atom operates on * dw units. */ -static void radeon_copy_swap(u8 *dst, u8 *src, u8 num_bytes, bool to_le) +void radeon_atom_copy_swap(u8 *dst, u8 *src, u8 num_bytes, bool to_le) { #ifdef __BIG_ENDIAN u8 src_tmp[20], dst_tmp[20]; /* used for byteswapping */ @@ -101,7 +101,7 @@ static int radeon_process_aux_ch(struct radeon_i2c_chan *chan, base = (unsigned char *)(rdev->mode_info.atom_context->scratch + 1); - radeon_copy_swap(base, send, send_bytes, true); + radeon_atom_copy_swap(base, send, send_bytes, true); args.v1.lpAuxRequest = cpu_to_le16((u16)(0 + 4)); args.v1.lpDataOut = cpu_to_le16((u16)(16 + 4)); @@ -138,7 +138,7 @@ static int radeon_process_aux_ch(struct radeon_i2c_chan *chan, recv_bytes = recv_size; if (recv && recv_size) - radeon_copy_swap(recv, base + 16, recv_bytes, false); + radeon_atom_copy_swap(recv, base + 16, recv_bytes, false); return recv_bytes; } diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c index ced9370ecb7..2f755e2aeb8 100644 --- a/drivers/gpu/drm/radeon/atombios_encoders.c +++ b/drivers/gpu/drm/radeon/atombios_encoders.c @@ -1425,8 +1425,12 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode) atombios_dig_encoder_setup(encoder, ATOM_ENABLE, 0); atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0); atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0); - /* some early dce3.2 boards have a bug in their transmitter control table */ - if ((rdev->family != CHIP_RV710) && (rdev->family != CHIP_RV730)) + /* some dce3.x boards have a bug in their transmitter control table. + * ACTION_ENABLE_OUTPUT can probably be dropped since ACTION_ENABLE + * does the same thing and more. + */ + if ((rdev->family != CHIP_RV710) && (rdev->family != CHIP_RV730) && + (rdev->family != CHIP_RS880)) atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); } if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) { diff --git a/drivers/gpu/drm/radeon/atombios_i2c.c b/drivers/gpu/drm/radeon/atombios_i2c.c index 44d87b6b422..9ed94a84d72 100644 --- a/drivers/gpu/drm/radeon/atombios_i2c.c +++ b/drivers/gpu/drm/radeon/atombios_i2c.c @@ -27,6 +27,8 @@ #include "radeon.h" #include "atom.h" +extern void radeon_atom_copy_swap(u8 *dst, u8 *src, u8 num_bytes, bool to_le); + #define TARGET_HW_I2C_CLOCK 50 /* these are a limitation of ProcessI2cChannelTransaction not the hw */ @@ -77,7 +79,7 @@ static int radeon_process_i2c_ch(struct radeon_i2c_chan *chan, } if (!(flags & HW_I2C_WRITE)) - memcpy(buf, base, num); + radeon_atom_copy_swap(buf, base, num, false); return 0; } diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 300099d3118..15d1f08b81e 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -534,7 +534,8 @@ static u32 evergreen_line_buffer_adjust(struct radeon_device *rdev, struct drm_display_mode *mode, struct drm_display_mode *other_mode) { - u32 tmp; + u32 tmp, buffer_alloc, i; + u32 pipe_offset = radeon_crtc->crtc_id * 0x20; /* * Line Buffer Setup * There are 3 line buffers, each one shared by 2 display controllers. @@ -557,18 +558,34 @@ static u32 evergreen_line_buffer_adjust(struct radeon_device *rdev, * non-linked crtcs for maximum line buffer allocation. */ if (radeon_crtc->base.enabled && mode) { - if (other_mode) + if (other_mode) { tmp = 0; /* 1/2 */ - else + buffer_alloc = 1; + } else { tmp = 2; /* whole */ - } else + buffer_alloc = 2; + } + } else { tmp = 0; + buffer_alloc = 0; + } /* second controller of the pair uses second half of the lb */ if (radeon_crtc->crtc_id % 2) tmp += 4; WREG32(DC_LB_MEMORY_SPLIT + radeon_crtc->crtc_offset, tmp); + if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) { + WREG32(PIPE0_DMIF_BUFFER_CONTROL + pipe_offset, + DMIF_BUFFERS_ALLOCATED(buffer_alloc)); + for (i = 0; i < rdev->usec_timeout; i++) { + if (RREG32(PIPE0_DMIF_BUFFER_CONTROL + pipe_offset) & + DMIF_BUFFERS_ALLOCATED_COMPLETED) + break; + udelay(1); + } + } + if (radeon_crtc->base.enabled && mode) { switch (tmp) { case 0: diff --git a/drivers/gpu/drm/radeon/evergreend.h b/drivers/gpu/drm/radeon/evergreend.h index 81e744fab31..52aabf24d96 100644 --- a/drivers/gpu/drm/radeon/evergreend.h +++ b/drivers/gpu/drm/radeon/evergreend.h @@ -472,6 +472,10 @@ # define LATENCY_LOW_WATERMARK(x) ((x) << 0) # define LATENCY_HIGH_WATERMARK(x) ((x) << 16) +#define PIPE0_DMIF_BUFFER_CONTROL 0x0ca0 +# define DMIF_BUFFERS_ALLOCATED(x) ((x) << 0) +# define DMIF_BUFFERS_ALLOCATED_COMPLETED (1 << 4) + #define IH_RB_CNTL 0x3e00 # define IH_RB_ENABLE (1 << 0) # define IH_IB_SIZE(x) ((x) << 1) /* log2 */ diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 38d87e17285..c54d295c6be 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -715,13 +715,16 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) (ATOM_SRC_DST_TABLE_FOR_ONE_OBJECT *) (ctx->bios + data_offset + le16_to_cpu(router_obj->asObjects[k].usSrcDstTableOffset)); + u8 *num_dst_objs = (u8 *) + ((u8 *)router_src_dst_table + 1 + + (router_src_dst_table->ucNumberOfSrc * 2)); + u16 *dst_objs = (u16 *)(num_dst_objs + 1); int enum_id; router.router_id = router_obj_id; - for (enum_id = 0; enum_id < router_src_dst_table->ucNumberOfDst; - enum_id++) { + for (enum_id = 0; enum_id < (*num_dst_objs); enum_id++) { if (le16_to_cpu(path->usConnObjectId) == - le16_to_cpu(router_src_dst_table->usDstObjectID[enum_id])) + le16_to_cpu(dst_objs[enum_id])) break; } @@ -1622,7 +1625,9 @@ struct radeon_encoder_atom_dig *radeon_atombios_get_lvds_info(struct kfree(edid); } } - record += sizeof(ATOM_FAKE_EDID_PATCH_RECORD); + record += fake_edid_record->ucFakeEDIDLength ? + fake_edid_record->ucFakeEDIDLength + 2 : + sizeof(ATOM_FAKE_EDID_PATCH_RECORD); break; case LCD_PANEL_RESOLUTION_RECORD_TYPE: panel_res_record = (ATOM_PANEL_RESOLUTION_PATCH_RECORD *)record; diff --git a/drivers/gpu/drm/radeon/rs400.c b/drivers/gpu/drm/radeon/rs400.c index 5099bd32e19..b367d1d46fd 100644 --- a/drivers/gpu/drm/radeon/rs400.c +++ b/drivers/gpu/drm/radeon/rs400.c @@ -174,10 +174,13 @@ int rs400_gart_enable(struct radeon_device *rdev) /* FIXME: according to doc we should set HIDE_MMCFG_BAR=0, * AGPMODE30=0 & AGP30ENHANCED=0 in NB_CNTL */ if ((rdev->family == CHIP_RS690) || (rdev->family == CHIP_RS740)) { - WREG32_MC(RS480_MC_MISC_CNTL, - (RS480_GART_INDEX_REG_EN | RS690_BLOCK_GFX_D3_EN)); + tmp = RREG32_MC(RS480_MC_MISC_CNTL); + tmp |= RS480_GART_INDEX_REG_EN | RS690_BLOCK_GFX_D3_EN; + WREG32_MC(RS480_MC_MISC_CNTL, tmp); } else { - WREG32_MC(RS480_MC_MISC_CNTL, RS480_GART_INDEX_REG_EN); + tmp = RREG32_MC(RS480_MC_MISC_CNTL); + tmp |= RS480_GART_INDEX_REG_EN; + WREG32_MC(RS480_MC_MISC_CNTL, tmp); } /* Enable gart */ WREG32_MC(RS480_AGP_ADDRESS_SPACE_SIZE, (RS480_GART_EN | size_reg)); diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index e22b460a4f0..bd1f18c341d 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -411,7 +411,8 @@ static u32 dce6_line_buffer_adjust(struct radeon_device *rdev, struct drm_display_mode *mode, struct drm_display_mode *other_mode) { - u32 tmp; + u32 tmp, buffer_alloc, i; + u32 pipe_offset = radeon_crtc->crtc_id * 0x20; /* * Line Buffer Setup * There are 3 line buffers, each one shared by 2 display controllers. @@ -426,16 +427,30 @@ static u32 dce6_line_buffer_adjust(struct radeon_device *rdev, * non-linked crtcs for maximum line buffer allocation. */ if (radeon_crtc->base.enabled && mode) { - if (other_mode) + if (other_mode) { tmp = 0; /* 1/2 */ - else + buffer_alloc = 1; + } else { tmp = 2; /* whole */ - } else + buffer_alloc = 2; + } + } else { tmp = 0; + buffer_alloc = 0; + } WREG32(DC_LB_MEMORY_SPLIT + radeon_crtc->crtc_offset, DC_LB_MEMORY_CONFIG(tmp)); + WREG32(PIPE0_DMIF_BUFFER_CONTROL + pipe_offset, + DMIF_BUFFERS_ALLOCATED(buffer_alloc)); + for (i = 0; i < rdev->usec_timeout; i++) { + if (RREG32(PIPE0_DMIF_BUFFER_CONTROL + pipe_offset) & + DMIF_BUFFERS_ALLOCATED_COMPLETED) + break; + udelay(1); + } + if (radeon_crtc->base.enabled && mode) { switch (tmp) { case 0: diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h index 45e240d0906..1767ae7f76c 100644 --- a/drivers/gpu/drm/radeon/sid.h +++ b/drivers/gpu/drm/radeon/sid.h @@ -57,6 +57,10 @@ #define DMIF_ADDR_CALC 0xC00 +#define PIPE0_DMIF_BUFFER_CONTROL 0x0ca0 +# define DMIF_BUFFERS_ALLOCATED(x) ((x) << 0) +# define DMIF_BUFFERS_ALLOCATED_COMPLETED (1 << 4) + #define SRBM_STATUS 0xE50 #define CC_SYS_RB_BACKEND_DISABLE 0xe80 diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c index fa09daf9a50..ea10bbe60ed 100644 --- a/drivers/gpu/drm/ttm/ttm_tt.c +++ b/drivers/gpu/drm/ttm/ttm_tt.c @@ -170,7 +170,7 @@ void ttm_tt_destroy(struct ttm_tt *ttm) ttm_tt_unbind(ttm); } - if (likely(ttm->pages != NULL)) { + if (ttm->state == tt_unbound) { ttm->bdev->driver->ttm_tt_unpopulate(ttm); } diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index ab59fdf0623..e937a5847bf 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -821,6 +821,64 @@ static int search(__s32 *array, __s32 value, unsigned n) return -1; } +static const char * const hid_report_names[] = { + "HID_INPUT_REPORT", + "HID_OUTPUT_REPORT", + "HID_FEATURE_REPORT", +}; +/** + * hid_validate_values - validate existing device report's value indexes + * + * @device: hid device + * @type: which report type to examine + * @id: which report ID to examine (0 for first) + * @field_index: which report field to examine + * @report_counts: expected number of values + * + * Validate the number of values in a given field of a given report, after + * parsing. + */ +struct hid_report *hid_validate_values(struct hid_device *hid, + unsigned int type, unsigned int id, + unsigned int field_index, + unsigned int report_counts) +{ + struct hid_report *report; + + if (type > HID_FEATURE_REPORT) { + hid_err(hid, "invalid HID report type %u\n", type); + return NULL; + } + + if (id >= HID_MAX_IDS) { + hid_err(hid, "invalid HID report id %u\n", id); + return NULL; + } + + /* + * Explicitly not using hid_get_report() here since it depends on + * ->numbered being checked, which may not always be the case when + * drivers go to access report values. + */ + report = hid->report_enum[type].report_id_hash[id]; + if (!report) { + hid_err(hid, "missing %s %u\n", hid_report_names[type], id); + return NULL; + } + if (report->maxfield <= field_index) { + hid_err(hid, "not enough fields in %s %u\n", + hid_report_names[type], id); + return NULL; + } + if (report->field[field_index]->report_count < report_counts) { + hid_err(hid, "not enough values in %s %u field %u\n", + hid_report_names[type], id, field_index); + return NULL; + } + return report; +} +EXPORT_SYMBOL_GPL(hid_validate_values); + /** * hid_match_report - check if driver's raw_event should be called * diff --git a/drivers/hid/hid-zpff.c b/drivers/hid/hid-zpff.c index f6ba81df71b..f348f7f6526 100644 --- a/drivers/hid/hid-zpff.c +++ b/drivers/hid/hid-zpff.c @@ -70,21 +70,13 @@ static int zpff_init(struct hid_device *hid) struct hid_report *report; struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); - struct list_head *report_list = - &hid->report_enum[HID_OUTPUT_REPORT].report_list; struct input_dev *dev = hidinput->input; - int error; + int i, error; - if (list_empty(report_list)) { - hid_err(hid, "no output report found\n"); - return -ENODEV; - } - - report = list_entry(report_list->next, struct hid_report, list); - - if (report->maxfield < 4) { - hid_err(hid, "not enough fields in report\n"); - return -ENODEV; + for (i = 0; i < 4; i++) { + report = hid_validate_values(hid, HID_OUTPUT_REPORT, 0, i, 1); + if (!report) + return -ENODEV; } zpff = kzalloc(sizeof(struct zpff_device), GFP_KERNEL); diff --git a/drivers/net/ethernet/sfc/rx.c b/drivers/net/ethernet/sfc/rx.c index 7b3c068a9f5..62311ad398e 100644 --- a/drivers/net/ethernet/sfc/rx.c +++ b/drivers/net/ethernet/sfc/rx.c @@ -311,8 +311,9 @@ static void efx_resurrect_rx_buffer(struct efx_rx_queue *rx_queue, index = rx_queue->added_count & rx_queue->ptr_mask; new_buf = efx_rx_buffer(rx_queue, index); - new_buf->dma_addr = rx_buf->dma_addr ^ (PAGE_SIZE >> 1); new_buf->u.page = rx_buf->u.page; + new_buf->page_offset = rx_buf->page_offset ^ (PAGE_SIZE >> 1); + new_buf->dma_addr = state->dma_addr + new_buf->page_offset; new_buf->len = rx_buf->len; new_buf->flags = EFX_RX_BUF_PAGE; ++rx_queue->added_count; diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index 425e201f597..1db819b922e 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c @@ -617,6 +617,11 @@ static const struct usb_device_id products [] = { .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET, .bInterfaceProtocol = USB_CDC_PROTO_NONE, .driver_info = (unsigned long)&wwan_info, +}, { + /* Telit modules */ + USB_VENDOR_AND_INTERFACE_INFO(0x1bc7, USB_CLASS_COMM, + USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), + .driver_info = (kernel_ulong_t) &wwan_info, }, { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 72cb1217837..8ff177d92ff 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -2160,6 +2160,13 @@ static int rt2800_get_gain_calibration_delta(struct rt2x00_dev *rt2x00dev) u8 step; int i; + /* + * First check if temperature compensation is supported. + */ + rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom); + if (!rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_EXTERNAL_TX_ALC)) + return 0; + /* * Read TSSI boundaries for temperature compensation from * the EEPROM. diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c index a5063602536..0c2f9122b26 100644 --- a/fs/notify/fanotify/fanotify.c +++ b/fs/notify/fanotify/fanotify.c @@ -18,6 +18,12 @@ static bool should_merge(struct fsnotify_event *old, struct fsnotify_event *new) old->tgid == new->tgid) { switch (old->data_type) { case (FSNOTIFY_EVENT_PATH): +#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS + /* dont merge two permission events */ + if ((old->mask & FAN_ALL_PERM_EVENTS) && + (new->mask & FAN_ALL_PERM_EVENTS)) + return false; +#endif if ((old->path.mnt == new->path.mnt) && (old->path.dentry == new->path.dentry)) return true; diff --git a/include/linux/hid.h b/include/linux/hid.h index a11ec22abb6..310ea592abd 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -741,6 +741,10 @@ void hid_output_report(struct hid_report *report, __u8 *data); struct hid_device *hid_allocate_device(void); struct hid_report *hid_register_report(struct hid_device *device, unsigned type, unsigned id); int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size); +struct hid_report *hid_validate_values(struct hid_device *hid, + unsigned int type, unsigned int id, + unsigned int field_index, + unsigned int report_counts); int hid_check_keys_pressed(struct hid_device *hid); int hid_connect(struct hid_device *hid, unsigned int connect_mask); void hid_disconnect(struct hid_device *hid); diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index e2080481d6c..57d80922277 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -1063,7 +1063,7 @@ struct perf_cpu_context { int exclusive; struct list_head rotation_list; int jiffies_interval; - struct pmu *active_pmu; + struct pmu *unique_pmu; struct perf_cgroup *cgrp; }; diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 0f9b92ea2f3..ffbd03d5aac 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -3507,6 +3507,7 @@ static int cgroup_write_event_control(struct cgroup *cgrp, struct cftype *cft, const char *buffer) { struct cgroup_event *event = NULL; + struct cgroup *cgrp_cfile; unsigned int efd, cfd; struct file *efile = NULL; struct file *cfile = NULL; @@ -3562,6 +3563,16 @@ static int cgroup_write_event_control(struct cgroup *cgrp, struct cftype *cft, goto fail; } + /* + * The file to be monitored must be in the same cgroup as + * cgroup.event_control is. + */ + cgrp_cfile = __d_cgrp(cfile->f_dentry->d_parent); + if (cgrp_cfile != cgrp) { + ret = -EINVAL; + goto fail; + } + if (!event->cft->register_event || !event->cft->unregister_event) { ret = -EINVAL; goto fail; diff --git a/kernel/events/core.c b/kernel/events/core.c index ab5bf2714ed..d41ff2747a7 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -368,6 +368,8 @@ void perf_cgroup_switch(struct task_struct *task, int mode) list_for_each_entry_rcu(pmu, &pmus, entry) { cpuctx = this_cpu_ptr(pmu->pmu_cpu_context); + if (cpuctx->unique_pmu != pmu) + continue; /* ensure we process each cpuctx once */ /* * perf_cgroup_events says at least one @@ -391,9 +393,10 @@ void perf_cgroup_switch(struct task_struct *task, int mode) if (mode & PERF_CGROUP_SWIN) { WARN_ON_ONCE(cpuctx->cgrp); - /* set cgrp before ctxsw in to - * allow event_filter_match() to not - * have to pass task around + /* + * set cgrp before ctxsw in to allow + * event_filter_match() to not have to pass + * task around */ cpuctx->cgrp = perf_cgroup_from_task(task); cpu_ctx_sched_in(cpuctx, EVENT_ALL, task); @@ -4332,7 +4335,7 @@ static void perf_event_task_event(struct perf_task_event *task_event) rcu_read_lock(); list_for_each_entry_rcu(pmu, &pmus, entry) { cpuctx = get_cpu_ptr(pmu->pmu_cpu_context); - if (cpuctx->active_pmu != pmu) + if (cpuctx->unique_pmu != pmu) goto next; perf_event_task_ctx(&cpuctx->ctx, task_event); @@ -4478,7 +4481,7 @@ static void perf_event_comm_event(struct perf_comm_event *comm_event) rcu_read_lock(); list_for_each_entry_rcu(pmu, &pmus, entry) { cpuctx = get_cpu_ptr(pmu->pmu_cpu_context); - if (cpuctx->active_pmu != pmu) + if (cpuctx->unique_pmu != pmu) goto next; perf_event_comm_ctx(&cpuctx->ctx, comm_event); @@ -4674,7 +4677,7 @@ static void perf_event_mmap_event(struct perf_mmap_event *mmap_event) rcu_read_lock(); list_for_each_entry_rcu(pmu, &pmus, entry) { cpuctx = get_cpu_ptr(pmu->pmu_cpu_context); - if (cpuctx->active_pmu != pmu) + if (cpuctx->unique_pmu != pmu) goto next; perf_event_mmap_ctx(&cpuctx->ctx, mmap_event, vma->vm_flags & VM_EXEC); @@ -5750,8 +5753,8 @@ static void update_pmu_context(struct pmu *pmu, struct pmu *old_pmu) cpuctx = per_cpu_ptr(pmu->pmu_cpu_context, cpu); - if (cpuctx->active_pmu == old_pmu) - cpuctx->active_pmu = pmu; + if (cpuctx->unique_pmu == old_pmu) + cpuctx->unique_pmu = pmu; } } @@ -5886,7 +5889,7 @@ int perf_pmu_register(struct pmu *pmu, char *name, int type) cpuctx->ctx.pmu = pmu; cpuctx->jiffies_interval = 1; INIT_LIST_HEAD(&cpuctx->rotation_list); - cpuctx->active_pmu = pmu; + cpuctx->unique_pmu = pmu; } got_cpu_context: diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 1ee70baf12c..5c5722a1993 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -5252,11 +5252,15 @@ static void task_fork_fair(struct task_struct *p) cfs_rq = task_cfs_rq(current); curr = cfs_rq->curr; - if (unlikely(task_cpu(p) != this_cpu)) { - rcu_read_lock(); - __set_task_cpu(p, this_cpu); - rcu_read_unlock(); - } + /* + * Not only the cpu but also the task_group of the parent might have + * been changed after parent->se.parent,cfs_rq were copied to + * child->se.parent,cfs_rq. So call __set_task_cpu() to make those + * of child point to valid ones. + */ + rcu_read_lock(); + __set_task_cpu(p, this_cpu); + rcu_read_unlock(); update_curr(cfs_rq); diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index 2fdb05d8aac..1ff51c9d18d 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c @@ -1610,9 +1610,8 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, asoc->outqueue.outstanding_bytes; sackh.num_gap_ack_blocks = 0; sackh.num_dup_tsns = 0; - chunk->subh.sack_hdr = &sackh; sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_SACK, - SCTP_CHUNK(chunk)); + SCTP_SACKH(&sackh)); break; case SCTP_CMD_DISCARD_PACKET: diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 9b0c0b8b4ab..55ab5e48196 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -2045,6 +2045,9 @@ sub process_file($) { $section_counter = 0; while () { + while (s/\\\s*$//) { + $_ .= ; + } if ($state == 0) { if (/$doc_start/o) { $state = 1; # next line is always the function name diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c index 9593f2772c6..5f5080f2e56 100644 --- a/tools/perf/util/map.c +++ b/tools/perf/util/map.c @@ -16,6 +16,7 @@ const char *map_type__name[MAP__NR_TYPES] = { static inline int is_anon_memory(const char *filename) { return !strcmp(filename, "//anon") || + !strcmp(filename, "/dev/zero (deleted)") || !strcmp(filename, "/anon_hugepage (deleted)"); } From 42b4c983bde68fbfddeeb9997653a1d9e1a7a5e7 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 5 Oct 2013 07:07:13 -0700 Subject: [PATCH 134/215] Linux 3.4.65 - 16 commits squashed x86/reboot: Add quirk to make Dell C6100 use reboot=pci automatically commit 4f0acd31c31f03ba42494c8baf6c0465150e2621 upstream. Dell PowerEdge C6100 machines fail to completely reboot about 20% of the time. Signed-off-by: Masoud Sharbiani Signed-off-by: Vinson Lee Cc: Robin Holt Cc: Russell King Cc: Guan Xuetao Link: http://lkml.kernel.org/r/1379717947-18042-1-git-send-email-vlee@freedesktop.org Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman x86, efi: Don't map Boot Services on i386 commit 700870119f49084da004ab588ea2b799689efaf7 upstream. Add patch to fix 32bit EFI service mapping (rhbz 726701) Multiple people are reporting hitting the following WARNING on i386, WARNING: at arch/x86/mm/ioremap.c:102 __ioremap_caller+0x3d3/0x440() Modules linked in: Pid: 0, comm: swapper Not tainted 3.9.0-rc7+ #95 Call Trace: [] warn_slowpath_common+0x5f/0x80 [] ? __ioremap_caller+0x3d3/0x440 [] ? __ioremap_caller+0x3d3/0x440 [] warn_slowpath_null+0x1d/0x20 [] __ioremap_caller+0x3d3/0x440 [] ? get_usage_chars+0xfb/0x110 [] ? vprintk_emit+0x147/0x480 [] ? efi_enter_virtual_mode+0x1e4/0x3de [] ioremap_cache+0x1a/0x20 [] ? efi_enter_virtual_mode+0x1e4/0x3de [] efi_enter_virtual_mode+0x1e4/0x3de [] start_kernel+0x286/0x2f4 [] ? repair_env_string+0x51/0x51 [] i386_start_kernel+0x12c/0x12f Due to the workaround described in commit 916f676f8 ("x86, efi: Retain boot service code until after switching to virtual mode") EFI Boot Service regions are mapped for a period during boot. Unfortunately, with the limited size of the i386 direct kernel map it's possible that some of the Boot Service regions will not be directly accessible, which causes them to be ioremap()'d, triggering the above warning as the regions are marked as E820_RAM in the e820 memmap. There are currently only two situations where we need to map EFI Boot Service regions, 1. To workaround the firmware bug described in 916f676f8 2. To access the ACPI BGRT image but since we haven't seen an i386 implementation that requires either, this simple fix should suffice for now. [ Added to changelog - Matt ] Reported-by: Bryan O'Donoghue Acked-by: Tom Zanussi Acked-by: Darren Hart Cc: Josh Triplett Cc: Matthew Garrett Cc: H. Peter Anvin Cc: Ingo Molnar Cc: Thomas Gleixner Cc: Greg Kroah-Hartman Signed-off-by: Josh Boyer Signed-off-by: Matt Fleming Signed-off-by: Greg Kroah-Hartman staging: vt6656: [BUG] main_usb.c oops on device_close move flag earlier. commit e3eb270fab7734427dd8171a93e4946fe28674bc upstream. The vt6656 is prone to resetting on the usb bus. It seems there is a race condition and wpa supplicant is trying to open the device via iw_handlers before its actually closed at a stage that the buffers are being removed. The device is longer considered open when the buffers are being removed. So move ~DEVICE_FLAGS_OPENED flag to before freeing the device buffers. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman xhci: Ensure a command structure points to the correct trb on the command ring commit ec7e43e2d98173483866fe2e4e690143626b659c upstream. If a command on the command ring needs to be cancelled before it is handled it can be turned to a no-op operation when the ring is stopped. We want to store the command ring enqueue pointer in the command structure when the command in enqueued for the cancellation case. Some commands used to store the command ring dequeue pointers instead of enqueue (these often worked because enqueue happends to equal dequeue quite often) Other commands correctly used the enqueue pointer but did not check if it pointed to a valid trb or a link trb, this caused for example stop endpoint command to timeout in xhci_stop_device() in about 2% of suspend/resume cases. This should also solve some weird behavior happening in command cancellation cases. This patch is based on a patch submitted by Sarah Sharp to linux-usb, but then forgotten: http://marc.info/?l=linux-usb&m=136269803207465&w=2 This patch should be backported to kernels as old as 3.7, that contain the commit b92cc66c047ff7cf587b318fe377061a353c120f "xHCI: add aborting command ring function" Signed-off-by: Mathias Nyman Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman xhci: Fix oops happening after address device timeout commit 284d20552461466b04d6bfeafeb1c47a8891b591 upstream. When a command times out, the command ring is first aborted, and then stopped. If the command ring is empty when it is stopped the stop event will point to next command which is not yet set. xHCI tries to handle this next event often causing an oops. Don't handle command completion events on stopped cmd ring if ring is empty. This patch should be backported to kernels as old as 3.7, that contain the commit b92cc66c047ff7cf587b318fe377061a353c120f "xHCI: add aborting command ring function" Signed-off-by: Mathias Nyman Reported-by: Giovanni Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman xhci: Fix race between ep halt and URB cancellation commit 526867c3ca0caa2e3e846cb993b0f961c33c2abb upstream. The halted state of a endpoint cannot be cleared over CLEAR_HALT from a user process, because the stopped_td variable was overwritten in the handle_stopped_endpoint() function. So the xhci_endpoint_reset() function will refuse the reset and communication with device can not run over this endpoint. https://bugzilla.kernel.org/show_bug.cgi?id=60699 Signed-off-by: Florian Wolter Signed-off-by: Sarah Sharp Cc: Jonghwan Choi Signed-off-by: Greg Kroah-Hartman usb/core/devio.c: Don't reject control message to endpoint with wrong direction bit commit 831abf76643555a99b80a3b54adfa7e4fa0a3259 upstream. Trying to read data from the Pegasus Technologies NoteTaker (0e20:0101) [1] with the Windows App (EasyNote) works natively but fails when Windows is running under KVM (and the USB device handed to KVM). The reason is a USB control message usb 4-2.2: control urb: bRequestType=22 bRequest=09 wValue=0200 wIndex=0001 wLength=0008 This goes to endpoint address 0x01 (wIndex); however, endpoint address 0x01 does not exist. There is an endpoint 0x81 though (same number, but other direction); the app may have meant that endpoint instead. The kernel thus rejects the IO and thus we see the failure. Apparently, Linux is more strict here than Windows ... we can't change the Win app easily, so that's a problem. It seems that the Win app/driver is buggy here and the driver does not behave fully according to the USB HID class spec that it claims to belong to. The device seems to happily deal with that though (and seems to not really care about this value much). So the question is whether the Linux kernel should filter here. Rejecting has the risk that somewhat non-compliant userspace apps/ drivers (most likely in a virtual machine) are prevented from working. Not rejecting has the risk of confusing an overly sensitive device with such a transfer. Given the fact that Windows does not filter it makes this risk rather small though. The patch makes the kernel more tolerant: If the endpoint address in wIndex does not exist, but an endpoint with toggled direction bit does, it will let the transfer through. (It does NOT change the message.) With attached patch, the app in Windows in KVM works. usb 4-2.2: check_ctrlrecip: process 13073 (qemu-kvm) requesting ep 01 but needs 81 I suspect this will mostly affect apps in virtual environments; as on Linux the apps would have been adapted to the stricter handling of the kernel. I have done that for mine[2]. [1] http://www.pegatech.com/ [2] https://sourceforge.net/projects/notetakerpen/ Signed-off-by: Kurt Garloff Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman dm snapshot: workaround for a false positive lockdep warning commit 5ea330a75bd86b2b2a01d7b85c516983238306fb upstream. The kernel reports a lockdep warning if a snapshot is invalidated because it runs out of space. The lockdep warning was triggered by commit 0976dfc1d0cd80a4e9dfaf87bd87 ("workqueue: Catch more locking problems with flush_work()") in v3.5. The warning is false positive. The real cause for the warning is that the lockdep engine treats different instances of md->lock as a single lock. This patch is a workaround - we use flush_workqueue instead of flush_work. This code path is not performance sensitive (it is called only on initialization or invalidation), thus it doesn't matter that we flush the whole workqueue. The real fix for the problem would be to teach the lockdep engine to treat different instances of md->lock as separate locks. Signed-off-by: Mikulas Patocka Acked-by: Alasdair G Kergon Signed-off-by: Mike Snitzer Signed-off-by: Greg Kroah-Hartman dm-snapshot: fix performance degradation due to small hash size commit 60e356f381954d79088d0455e357db48cfdd6857 upstream. LVM2, since version 2.02.96, creates origin with zero size, then loads the snapshot driver and then loads the origin. Consequently, the snapshot driver sees the origin size zero and sets the hash size to the lower bound 64. Such small hash table causes performance degradation. This patch changes it so that the hash size is determined by the size of snapshot volume, not minimum of origin and snapshot size. It doesn't make sense to set the snapshot size significantly larger than the origin size, so we do not need to take origin size into account when calculating the hash size. Signed-off-by: Mikulas Patocka Signed-off-by: Mike Snitzer Signed-off-by: Greg Kroah-Hartman drm/i915/dp: increase i2c-over-aux retry interval on AUX DEFER commit 8d16f258217f2f583af1fd57c5144aa4bbe73e48 upstream. There is no clear cut rules or specs for the retry interval, as there are many factors that affect overall response time. Increase the interval, and even more so on branch devices which may have limited i2c bit rates. Signed-off-by: Jani Nikula Reference: https://bugs.freedesktop.org/show_bug.cgi?id=60263 Tested-by: Nicolas Suzor Reviewed-by: Todd Previte Signed-off-by: Daniel Vetter Signed-off-by: Greg Kroah-Hartman drm/radeon: disable tests/benchmarks if accel is disabled commit 4a1132a023eb48cf10522d84c5908d43b612c041 upstream. The tests are only usable if the acceleration engines have been successfully initialized. Based on an initial patch from: Alex Ivanov Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman hwmon: (applesmc) Check key count before proceeding commit 5f4513864304672e6ea9eac60583eeac32e679f2 upstream. After reports from Chris and Josh Boyer of a rare crash in applesmc, Guenter pointed at the initialization problem fixed below. The patch has not been verified to fix the crash, but should be applied regardless. Reported-by: Suggested-by: Guenter Roeck Signed-off-by: Henrik Rydberg Signed-off-by: Guenter Roeck Signed-off-by: Greg Kroah-Hartman ALSA: compress: Fix compress device unregister. commit 4028b6c4c03f213260e9290ff3a6b5439aad07ce upstream. snd_unregister_device() should return the device type and not stream direction. Signed-off-by: Liam Girdwood Acked-by: Vinod Koul Tested-by: Vinod Koul Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman mm, memcg: give exiting processes access to memory reserves commit 465adcf1ea7b2e49b2e0899366624f5532b64012 A memcg may livelock when oom if the process that grabs the hierarchy's oom lock is never the first process with PF_EXITING set in the memcg's task iteration. The oom killer, both global and memcg, will defer if it finds an eligible process that is in the process of exiting and it is not being ptraced. The idea is to allow it to exit without using memory reserves before needlessly killing another process. This normally works fine except in the memcg case with a large number of threads attached to the oom memcg. In this case, the memcg oom killer only gets called for the process that grabs the hierarchy's oom lock; all others end up blocked on the memcg's oom waitqueue. Thus, if the process that grabs the hierarchy's oom lock is never the first PF_EXITING process in the memcg's task iteration, the oom killer is constantly deferred without anything making progress. The fix is to give PF_EXITING processes access to memory reserves so that we've marked them as oom killed without any iteration. This allows __mem_cgroup_try_charge() to succeed so that the process may exit. This makes the memcg oom killer exemption for TIF_MEMDIE tasks, now immediately granted for processes with pending SIGKILLs and those in the exit path, to be equivalent to what is done for the global oom killer. Signed-off-by: David Rientjes Acked-by: Michal Hocko Acked-by: KAMEZAWA Hiroyuki Acked-by: Johannes Weiner Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds [Qiang: backported to 3.4: - move the changes from memcontrol.c to oom_kill.c] Signed-off-by: Qiang Huang Signed-off-by: Greg Kroah-Hartman HID: LG: validate HID output report details commit 0fb6bd06e06792469acc15bbe427361b56ada528 upstream. A HID device could send a malicious output report that would cause the lg, lg3, and lg4 HID drivers to write beyond the output report allocation during an event, causing a heap overflow: [ 325.245240] usb 1-1: New USB device found, idVendor=046d, idProduct=c287 ... [ 414.518960] BUG kmalloc-4096 (Not tainted): Redzone overwritten Additionally, while lg2 did correctly validate the report details, it was cleaned up and shortened. CVE-2013-2893 Signed-off-by: Kees Cook Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- Makefile | 2 +- arch/x86/kernel/reboot.c | 16 ++++++++++++++ arch/x86/platform/efi/efi.c | 11 ++++++---- drivers/gpu/drm/i915/intel_dp.c | 13 +++++++++++- drivers/gpu/drm/radeon/radeon_device.c | 15 ++++++++++--- drivers/hid/hid-lg2ff.c | 19 +++-------------- drivers/hid/hid-lg3ff.c | 29 ++++++-------------------- drivers/hid/hid-lg4ff.c | 20 +----------------- drivers/hid/hid-lgff.c | 17 ++------------- drivers/hwmon/applesmc.c | 11 +++++++++- drivers/md/dm-snap-persistent.c | 2 +- drivers/md/dm-snap.c | 5 ++--- drivers/staging/vt6656/main_usb.c | 3 ++- drivers/usb/core/devio.c | 16 ++++++++++++++ drivers/usb/host/xhci-hub.c | 2 +- drivers/usb/host/xhci-ring.c | 24 +++++++++++++++++++-- drivers/usb/host/xhci.c | 25 +++++----------------- drivers/usb/host/xhci.h | 1 + mm/oom_kill.c | 8 +++---- sound/core/compress_offload.c | 3 ++- 20 files changed, 126 insertions(+), 116 deletions(-) diff --git a/Makefile b/Makefile index 057218555ef..3464e548208 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 4 -SUBLEVEL = 64 +SUBLEVEL = 65 EXTRAVERSION = NAME = Saber-toothed Squirrel diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index df1b604c0c1..bd70df6162f 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c @@ -479,6 +479,22 @@ static struct dmi_system_id __initdata pci_reboot_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Precision M6600"), }, }, + { /* Handle problems with rebooting on the Dell PowerEdge C6100. */ + .callback = set_pci_reboot, + .ident = "Dell PowerEdge C6100", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "C6100"), + }, + }, + { /* Some C6100 machines were shipped with vendor being 'Dell'. */ + .callback = set_pci_reboot, + .ident = "Dell PowerEdge C6100", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell"), + DMI_MATCH(DMI_PRODUCT_NAME, "C6100"), + }, + }, { } }; diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 1e406371a68..454548c309f 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -845,10 +845,13 @@ void __init efi_enter_virtual_mode(void) for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { md = p; - if (!(md->attribute & EFI_MEMORY_RUNTIME) && - md->type != EFI_BOOT_SERVICES_CODE && - md->type != EFI_BOOT_SERVICES_DATA) - continue; + if (!(md->attribute & EFI_MEMORY_RUNTIME)) { +#ifdef CONFIG_X86_64 + if (md->type != EFI_BOOT_SERVICES_CODE && + md->type != EFI_BOOT_SERVICES_DATA) +#endif + continue; + } size = md->num_pages << EFI_PAGE_SHIFT; end = md->phys_addr + size; diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 069725c5c1a..eee6cd39199 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -625,7 +625,18 @@ intel_dp_i2c_aux_ch(struct i2c_adapter *adapter, int mode, DRM_DEBUG_KMS("aux_ch native nack\n"); return -EREMOTEIO; case AUX_NATIVE_REPLY_DEFER: - udelay(100); + /* + * For now, just give more slack to branch devices. We + * could check the DPCD for I2C bit rate capabilities, + * and if available, adjust the interval. We could also + * be more careful with DP-to-Legacy adapters where a + * long legacy cable may force very low I2C bit rates. + */ + if (intel_dp->dpcd[DP_DOWNSTREAMPORT_PRESENT] & + DP_DWN_STRM_PORT_PRESENT) + usleep_range(500, 600); + else + usleep_range(300, 400); continue; default: DRM_ERROR("aux_ch invalid native reply 0x%02x\n", diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 1209f150d40..2f555d78224 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -835,13 +835,22 @@ int radeon_device_init(struct radeon_device *rdev, return r; } if ((radeon_testing & 1)) { - radeon_test_moves(rdev); + if (rdev->accel_working) + radeon_test_moves(rdev); + else + DRM_INFO("radeon: acceleration disabled, skipping move tests\n"); } if ((radeon_testing & 2)) { - radeon_test_syncing(rdev); + if (rdev->accel_working) + radeon_test_syncing(rdev); + else + DRM_INFO("radeon: acceleration disabled, skipping sync tests\n"); } if (radeon_benchmarking) { - radeon_benchmark(rdev, radeon_benchmarking); + if (rdev->accel_working) + radeon_benchmark(rdev, radeon_benchmarking); + else + DRM_INFO("radeon: acceleration disabled, skipping benchmarks\n"); } return 0; } diff --git a/drivers/hid/hid-lg2ff.c b/drivers/hid/hid-lg2ff.c index 3c31bc650e5..128f0117c7a 100644 --- a/drivers/hid/hid-lg2ff.c +++ b/drivers/hid/hid-lg2ff.c @@ -66,26 +66,13 @@ int lg2ff_init(struct hid_device *hid) struct hid_report *report; struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); - struct list_head *report_list = - &hid->report_enum[HID_OUTPUT_REPORT].report_list; struct input_dev *dev = hidinput->input; int error; - if (list_empty(report_list)) { - hid_err(hid, "no output report found\n"); + /* Check that the report looks ok */ + report = hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7); + if (!report) return -ENODEV; - } - - report = list_entry(report_list->next, struct hid_report, list); - - if (report->maxfield < 1) { - hid_err(hid, "output report is empty\n"); - return -ENODEV; - } - if (report->field[0]->report_count < 7) { - hid_err(hid, "not enough values in the field\n"); - return -ENODEV; - } lg2ff = kmalloc(sizeof(struct lg2ff_device), GFP_KERNEL); if (!lg2ff) diff --git a/drivers/hid/hid-lg3ff.c b/drivers/hid/hid-lg3ff.c index f98644c26c1..91f981ff560 100644 --- a/drivers/hid/hid-lg3ff.c +++ b/drivers/hid/hid-lg3ff.c @@ -68,10 +68,11 @@ static int hid_lg3ff_play(struct input_dev *dev, void *data, int x, y; /* - * Maxusage should always be 63 (maximum fields) - * likely a better way to ensure this data is clean + * Available values in the field should always be 63, but we only use up to + * 35. Instead, clear the entire area, however big it is. */ - memset(report->field[0]->value, 0, sizeof(__s32)*report->field[0]->maxusage); + memset(report->field[0]->value, 0, + sizeof(__s32) * report->field[0]->report_count); switch (effect->type) { case FF_CONSTANT: @@ -131,32 +132,14 @@ static const signed short ff3_joystick_ac[] = { int lg3ff_init(struct hid_device *hid) { struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); - struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; struct input_dev *dev = hidinput->input; - struct hid_report *report; - struct hid_field *field; const signed short *ff_bits = ff3_joystick_ac; int error; int i; - /* Find the report to use */ - if (list_empty(report_list)) { - hid_err(hid, "No output report found\n"); - return -1; - } - /* Check that the report looks ok */ - report = list_entry(report_list->next, struct hid_report, list); - if (!report) { - hid_err(hid, "NULL output report\n"); - return -1; - } - - field = report->field[0]; - if (!field) { - hid_err(hid, "NULL field\n"); - return -1; - } + if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 35)) + return -ENODEV; /* Assume single fixed device G940 */ for (i = 0; ff_bits[i] >= 0; i++) diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c index 6ecc9e22044..44bb0a52041 100644 --- a/drivers/hid/hid-lg4ff.c +++ b/drivers/hid/hid-lg4ff.c @@ -339,33 +339,15 @@ static ssize_t lg4ff_range_store(struct device *dev, struct device_attribute *at int lg4ff_init(struct hid_device *hid) { struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); - struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; struct input_dev *dev = hidinput->input; - struct hid_report *report; - struct hid_field *field; struct lg4ff_device_entry *entry; struct usb_device_descriptor *udesc; int error, i, j; __u16 bcdDevice, rev_maj, rev_min; - /* Find the report to use */ - if (list_empty(report_list)) { - hid_err(hid, "No output report found\n"); - return -1; - } - /* Check that the report looks ok */ - report = list_entry(report_list->next, struct hid_report, list); - if (!report) { - hid_err(hid, "NULL output report\n"); + if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7)) return -1; - } - - field = report->field[0]; - if (!field) { - hid_err(hid, "NULL field\n"); - return -1; - } /* Check what wheel has been connected */ for (i = 0; i < ARRAY_SIZE(lg4ff_devices); i++) { diff --git a/drivers/hid/hid-lgff.c b/drivers/hid/hid-lgff.c index 27bc54f92f4..1d978daa70d 100644 --- a/drivers/hid/hid-lgff.c +++ b/drivers/hid/hid-lgff.c @@ -130,27 +130,14 @@ static void hid_lgff_set_autocenter(struct input_dev *dev, u16 magnitude) int lgff_init(struct hid_device* hid) { struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); - struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; struct input_dev *dev = hidinput->input; - struct hid_report *report; - struct hid_field *field; const signed short *ff_bits = ff_joystick; int error; int i; - /* Find the report to use */ - if (list_empty(report_list)) { - hid_err(hid, "No output report found\n"); - return -1; - } - /* Check that the report looks ok */ - report = list_entry(report_list->next, struct hid_report, list); - field = report->field[0]; - if (!field) { - hid_err(hid, "NULL field\n"); - return -1; - } + if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7)) + return -ENODEV; for (i = 0; i < ARRAY_SIZE(devices); i++) { if (dev->id.vendor == devices[i].idVendor && diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c index 70d62f5bc90..73bea4983d5 100644 --- a/drivers/hwmon/applesmc.c +++ b/drivers/hwmon/applesmc.c @@ -489,16 +489,25 @@ static int applesmc_init_smcreg_try(void) { struct applesmc_registers *s = &smcreg; bool left_light_sensor, right_light_sensor; + unsigned int count; u8 tmp[1]; int ret; if (s->init_complete) return 0; - ret = read_register_count(&s->key_count); + ret = read_register_count(&count); if (ret) return ret; + if (s->cache && s->key_count != count) { + pr_warn("key count changed from %d to %d\n", + s->key_count, count); + kfree(s->cache); + s->cache = NULL; + } + s->key_count = count; + if (!s->cache) s->cache = kcalloc(s->key_count, sizeof(*s->cache), GFP_KERNEL); if (!s->cache) diff --git a/drivers/md/dm-snap-persistent.c b/drivers/md/dm-snap-persistent.c index 3ac415675b6..4caa8e6d59d 100644 --- a/drivers/md/dm-snap-persistent.c +++ b/drivers/md/dm-snap-persistent.c @@ -256,7 +256,7 @@ static int chunk_io(struct pstore *ps, void *area, chunk_t chunk, int rw, */ INIT_WORK_ONSTACK(&req.work, do_metadata); queue_work(ps->metadata_wq, &req.work); - flush_work(&req.work); + flush_workqueue(ps->metadata_wq); return req.result; } diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index ff62ddc660d..448050c87be 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c @@ -721,17 +721,16 @@ static int calc_max_buckets(void) */ static int init_hash_tables(struct dm_snapshot *s) { - sector_t hash_size, cow_dev_size, origin_dev_size, max_buckets; + sector_t hash_size, cow_dev_size, max_buckets; /* * Calculate based on the size of the original volume or * the COW volume... */ cow_dev_size = get_dev_size(s->cow->bdev); - origin_dev_size = get_dev_size(s->origin->bdev); max_buckets = calc_max_buckets(); - hash_size = min(origin_dev_size, cow_dev_size) >> s->store->chunk_shift; + hash_size = cow_dev_size >> s->store->chunk_shift; hash_size = min(hash_size, max_buckets); if (hash_size < 64) diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c index 628545d261d..1f34a345f4e 100644 --- a/drivers/staging/vt6656/main_usb.c +++ b/drivers/staging/vt6656/main_usb.c @@ -1220,6 +1220,8 @@ device_release_WPADEV(pDevice); memset(pMgmt->abyCurrBSSID, 0, 6); pMgmt->eCurrState = WMAC_STATE_IDLE; + pDevice->flags &= ~DEVICE_FLAGS_OPENED; + device_free_tx_bufs(pDevice); device_free_rx_bufs(pDevice); device_free_int_bufs(pDevice); @@ -1231,7 +1233,6 @@ device_release_WPADEV(pDevice); usb_free_urb(pDevice->pInterruptURB); BSSvClearNodeDBTable(pDevice, 0); - pDevice->flags &=(~DEVICE_FLAGS_OPENED); DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_close2 \n"); diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 336b82da377..371fe69caba 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -684,6 +684,22 @@ static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype, if ((index & ~USB_DIR_IN) == 0) return 0; ret = findintfep(ps->dev, index); + if (ret < 0) { + /* + * Some not fully compliant Win apps seem to get + * index wrong and have the endpoint number here + * rather than the endpoint address (with the + * correct direction). Win does let this through, + * so we'll not reject it here but leave it to + * the device to not break KVM. But we warn. + */ + ret = findintfep(ps->dev, index ^ 0x80); + if (ret >= 0) + dev_info(&ps->dev->dev, + "%s: process %i (%s) requesting ep %02x but needs %02x\n", + __func__, task_pid_nr(current), + current->comm, index, index ^ 0x80); + } if (ret >= 0) ret = checkintf(ps, ret); break; diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 4e374b3dd12..9f7b09cd0c5 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -287,7 +287,7 @@ static int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend) if (virt_dev->eps[i].ring && virt_dev->eps[i].ring->dequeue) xhci_queue_stop_endpoint(xhci, slot_id, i, suspend); } - cmd->command_trb = xhci->cmd_ring->enqueue; + cmd->command_trb = xhci_find_next_enqueue(xhci->cmd_ring); list_add_tail(&cmd->cmd_list, &virt_dev->cmd_list); xhci_queue_stop_endpoint(xhci, slot_id, 0, suspend); xhci_ring_cmd_db(xhci); diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 39679b14c4a..0b08ac15988 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -122,6 +122,16 @@ static int enqueue_is_link_trb(struct xhci_ring *ring) return TRB_TYPE_LINK_LE32(link->control); } +union xhci_trb *xhci_find_next_enqueue(struct xhci_ring *ring) +{ + /* Enqueue pointer can be left pointing to the link TRB, + * we must handle that + */ + if (TRB_TYPE_LINK_LE32(ring->enqueue->link.control)) + return ring->enq_seg->next->trbs; + return ring->enqueue; +} + /* Updates trb to point to the next TRB in the ring, and updates seg if the next * TRB is in a new segment. This does not skip over link TRBs, and it does not * effect the ring dequeue or enqueue pointers. @@ -839,8 +849,12 @@ static void handle_stopped_endpoint(struct xhci_hcd *xhci, /* Otherwise ring the doorbell(s) to restart queued transfers */ ring_doorbell_for_active_rings(xhci, slot_id, ep_index); } - ep->stopped_td = NULL; - ep->stopped_trb = NULL; + + /* Clear stopped_td and stopped_trb if endpoint is not halted */ + if (!(ep->ep_state & EP_HALTED)) { + ep->stopped_td = NULL; + ep->stopped_trb = NULL; + } /* * Drop the lock and complete the URBs in the cancelled TD list. @@ -1371,6 +1385,12 @@ static void handle_cmd_completion(struct xhci_hcd *xhci, inc_deq(xhci, xhci->cmd_ring); return; } + /* There is no command to handle if we get a stop event when the + * command ring is empty, event->cmd_trb points to the next + * unset command + */ + if (xhci->cmd_ring->dequeue == xhci->cmd_ring->enqueue) + return; } switch (le32_to_cpu(xhci->cmd_ring->dequeue->generic.field[3]) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 488a32f4b4e..572d79a95b8 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -2592,15 +2592,7 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci, if (command) { cmd_completion = command->completion; cmd_status = &command->status; - command->command_trb = xhci->cmd_ring->enqueue; - - /* Enqueue pointer can be left pointing to the link TRB, - * we must handle that - */ - if (TRB_TYPE_LINK_LE32(command->command_trb->link.control)) - command->command_trb = - xhci->cmd_ring->enq_seg->next->trbs; - + command->command_trb = xhci_find_next_enqueue(xhci->cmd_ring); list_add_tail(&command->cmd_list, &virt_dev->cmd_list); } else { cmd_completion = &virt_dev->cmd_completion; @@ -2608,7 +2600,7 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci, } init_completion(cmd_completion); - cmd_trb = xhci->cmd_ring->dequeue; + cmd_trb = xhci_find_next_enqueue(xhci->cmd_ring); if (!ctx_change) ret = xhci_queue_configure_endpoint(xhci, in_ctx->dma, udev->slot_id, must_succeed); @@ -3393,14 +3385,7 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev) /* Attempt to submit the Reset Device command to the command ring */ spin_lock_irqsave(&xhci->lock, flags); - reset_device_cmd->command_trb = xhci->cmd_ring->enqueue; - - /* Enqueue pointer can be left pointing to the link TRB, - * we must handle that - */ - if (TRB_TYPE_LINK_LE32(reset_device_cmd->command_trb->link.control)) - reset_device_cmd->command_trb = - xhci->cmd_ring->enq_seg->next->trbs; + reset_device_cmd->command_trb = xhci_find_next_enqueue(xhci->cmd_ring); list_add_tail(&reset_device_cmd->cmd_list, &virt_dev->cmd_list); ret = xhci_queue_reset_device(xhci, slot_id); @@ -3604,7 +3589,7 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev) union xhci_trb *cmd_trb; spin_lock_irqsave(&xhci->lock, flags); - cmd_trb = xhci->cmd_ring->dequeue; + cmd_trb = xhci_find_next_enqueue(xhci->cmd_ring); ret = xhci_queue_slot_control(xhci, TRB_ENABLE_SLOT, 0); if (ret) { spin_unlock_irqrestore(&xhci->lock, flags); @@ -3731,7 +3716,7 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) xhci_dbg_ctx(xhci, virt_dev->in_ctx, 2); spin_lock_irqsave(&xhci->lock, flags); - cmd_trb = xhci->cmd_ring->dequeue; + cmd_trb = xhci_find_next_enqueue(xhci->cmd_ring); ret = xhci_queue_address_device(xhci, virt_dev->in_ctx->dma, udev->slot_id); if (ret) { diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 7b717576017..592ee93f29b 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1828,6 +1828,7 @@ int xhci_cancel_cmd(struct xhci_hcd *xhci, struct xhci_command *command, union xhci_trb *cmd_trb); void xhci_ring_ep_doorbell(struct xhci_hcd *xhci, unsigned int slot_id, unsigned int ep_index, unsigned int stream_id); +union xhci_trb *xhci_find_next_enqueue(struct xhci_ring *ring); /* xHCI roothub code */ void xhci_set_link_state(struct xhci_hcd *xhci, __le32 __iomem **port_array, diff --git a/mm/oom_kill.c b/mm/oom_kill.c index 46bf2ed5594..597ecac5731 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c @@ -562,11 +562,11 @@ void mem_cgroup_out_of_memory(struct mem_cgroup *memcg, gfp_t gfp_mask, struct task_struct *p; /* - * If current has a pending SIGKILL, then automatically select it. The - * goal is to allow it to allocate so that it may quickly exit and free - * its memory. + * If current has a pending SIGKILL or is exiting, then automatically + * select it. The goal is to allow it to allocate so that it may + * quickly exit and free its memory. */ - if (fatal_signal_pending(current)) { + if (fatal_signal_pending(current) || current->flags & PF_EXITING) { set_thread_flag(TIF_MEMDIE); return; } diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c index e7e4b8dea7f..a0f6dc6d519 100644 --- a/sound/core/compress_offload.c +++ b/sound/core/compress_offload.c @@ -791,7 +791,8 @@ static int snd_compress_dev_disconnect(struct snd_device *device) struct snd_compr *compr; compr = device->device_data; - snd_unregister_device(compr->direction, compr->card, compr->device); + snd_unregister_device(SNDRV_DEVICE_TYPE_COMPRESS, compr->card, + compr->device); return 0; } From 2e2a4d359b0c84306aa8fa5ff1b0963807f04ac4 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Mon, 13 Jan 2014 03:22:11 +0100 Subject: [PATCH 135/215] Missed __cpuinit removal. --- arch/arm/mach-msm/intelli_plug.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-msm/intelli_plug.c b/arch/arm/mach-msm/intelli_plug.c index ffaa9a8cc0b..94998e1a5e1 100644 --- a/arch/arm/mach-msm/intelli_plug.c +++ b/arch/arm/mach-msm/intelli_plug.c @@ -167,7 +167,7 @@ static unsigned int calculate_thread_stats(void) return nr_run; } -static void __cpuinit intelli_plug_work_fn(struct work_struct *work) +static void intelli_plug_work_fn(struct work_struct *work) { unsigned int nr_run_stat; unsigned int cpu_count = 0; @@ -304,7 +304,7 @@ static void intelli_plug_early_suspend(struct early_suspend *handler) } } -static void __cpuinit intelli_plug_late_resume(struct early_suspend *handler) +static void intelli_plug_late_resume(struct early_suspend *handler) { int num_of_active_cores; int i; From e2c7e48881aa2092aaf462c2cf051c86ecdb5dcf Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Mon, 13 Jan 2014 03:23:01 +0100 Subject: [PATCH 136/215] Revert "Squash a lot of slab, slob and slub commits from Faux123" This reverts commit dfcd6009c5c1307a63068fc68e326b4707cb693d. --- arch/s390/mm/pgtable.c | 4 +- fs/aio.c | 96 ++- include/linux/aio.h | 1 + include/linux/gfp.h | 10 +- include/linux/mempolicy.h | 2 +- include/linux/mm_types.h | 22 +- include/linux/page-flags.h | 29 - include/linux/slab.h | 39 +- include/linux/slab_def.h | 30 +- include/linux/slob_def.h | 6 +- include/linux/slub_def.h | 3 +- include/trace/events/gfpflags.h | 1 - kernel/fork.c | 2 +- mm/Makefile | 3 +- mm/internal.h | 4 - mm/mempolicy.c | 8 +- mm/page_alloc.c | 23 +- mm/slab.c | 1118 +++++++++++++++++-------------- mm/slab.h | 128 ---- mm/slab_common.c | 371 ---------- mm/slob.c | 253 ++++--- mm/slub.c | 917 +++++++++++++++---------- 22 files changed, 1414 insertions(+), 1656 deletions(-) delete mode 100644 mm/slab.h delete mode 100644 mm/slab_common.c diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c index 4674105db03..87f0efd0e77 100644 --- a/arch/s390/mm/pgtable.c +++ b/arch/s390/mm/pgtable.c @@ -807,7 +807,7 @@ int s390_enable_sie(void) task_lock(tsk); if (!tsk->mm || atomic_read(&tsk->mm->mm_users) > 1 || #ifdef CONFIG_AIO - tsk->mm->ioctx_rtree.rnode || + !hlist_empty(&tsk->mm->ioctx_list) || #endif tsk->mm != tsk->active_mm) { task_unlock(tsk); @@ -826,7 +826,7 @@ int s390_enable_sie(void) task_lock(tsk); if (!tsk->mm || atomic_read(&tsk->mm->mm_users) > 1 || #ifdef CONFIG_AIO - tsk->mm->ioctx_rtree.rnode || + !hlist_empty(&tsk->mm->ioctx_list) || #endif tsk->mm != tsk->active_mm) { mmput(mm); diff --git a/fs/aio.c b/fs/aio.c index 59ceb9291b3..01be7f60a8a 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -35,7 +35,6 @@ #include #include #include -#include #include #include @@ -286,18 +285,10 @@ static struct kioctx *ioctx_alloc(unsigned nr_events) aio_nr += ctx->max_reqs; spin_unlock(&aio_nr_lock); - /* now insert into the radix tree */ - err = radix_tree_preload(GFP_KERNEL); - if (err) - goto out_cleanup; + /* now link into global list. */ spin_lock(&mm->ioctx_lock); - err = radix_tree_insert(&mm->ioctx_rtree, ctx->user_id, ctx); + hlist_add_head_rcu(&ctx->list, &mm->ioctx_list); spin_unlock(&mm->ioctx_lock); - radix_tree_preload_end(); - if (err) { - WARN_ONCE(1, "aio: insert into ioctx tree failed: %d", err); - goto out_cleanup; - } dprintk("aio: allocated ioctx %p[%ld]: mm=%p mask=0x%x\n", ctx, ctx->user_id, current->mm, ctx->ring_info.nr); @@ -375,32 +366,6 @@ ssize_t wait_on_sync_kiocb(struct kiocb *iocb) } EXPORT_SYMBOL(wait_on_sync_kiocb); -static inline void exit_aio_ctx(struct mm_struct *mm, struct kioctx *ctx) -{ - void *ret; - - ret = radix_tree_delete(&mm->ioctx_rtree, ctx->user_id); - BUG_ON(!ret || ret != ctx); - - kill_ctx(ctx); - - if (1 != atomic_read(&ctx->users)) - pr_debug("exit_aio:ioctx still alive: %d %d %d\n", - atomic_read(&ctx->users), ctx->dead, ctx->reqs_active); - /* - * We don't need to bother with munmap() here - - * exit_mmap(mm) is coming and it'll unmap everything. - * Since aio_free_ring() uses non-zero ->mmap_size - * as indicator that it needs to unmap the area, - * just set it to 0; aio_free_ring() is the only - * place that uses ->mmap_size, so it's safe. - * That way we get all munmap done to current->mm - - * all other callers have ctx->mm == current->mm. - */ - ctx->ring_info.mmap_size = 0; - put_ioctx(ctx); -} - /* exit_aio: called when the last user of mm goes away. At this point, * there is no way for any new requests to be submited or any of the * io_* syscalls to be called on the context. However, there may be @@ -410,17 +375,32 @@ static inline void exit_aio_ctx(struct mm_struct *mm, struct kioctx *ctx) */ void exit_aio(struct mm_struct *mm) { - struct kioctx *ctx[16]; - int count; + struct kioctx *ctx; - do { - int i; + while (!hlist_empty(&mm->ioctx_list)) { + ctx = hlist_entry(mm->ioctx_list.first, struct kioctx, list); + hlist_del_rcu(&ctx->list); + + kill_ctx(ctx); - count = radix_tree_gang_lookup(&mm->ioctx_rtree, (void **)ctx, - 0, ARRAY_SIZE(ctx)); - for (i = 0; i < count; i++) - exit_aio_ctx(mm, ctx[i]); - } while (count); + if (1 != atomic_read(&ctx->users)) + printk(KERN_DEBUG + "exit_aio:ioctx still alive: %d %d %d\n", + atomic_read(&ctx->users), ctx->dead, + ctx->reqs_active); + /* + * We don't need to bother with munmap() here - + * exit_mmap(mm) is coming and it'll unmap everything. + * Since aio_free_ring() uses non-zero ->mmap_size + * as indicator that it needs to unmap the area, + * just set it to 0; aio_free_ring() is the only + * place that uses ->mmap_size, so it's safe. + * That way we get all munmap done to current->mm - + * all other callers have ctx->mm == current->mm. + */ + ctx->ring_info.mmap_size = 0; + put_ioctx(ctx); + } } /* aio_get_req @@ -675,18 +655,22 @@ static struct kioctx *lookup_ioctx(unsigned long ctx_id) { struct mm_struct *mm = current->mm; struct kioctx *ctx, *ret = NULL; + struct hlist_node *n; rcu_read_lock(); - ctx = radix_tree_lookup(&mm->ioctx_rtree, ctx_id); - /* - * RCU protects us against accessing freed memory but - * we have to be careful not to get a reference when the - * reference count already dropped to 0 (ctx->dead test - * is unreliable because of races). - */ - if (ctx && !ctx->dead && try_get_ioctx(ctx)) - ret = ctx; + hlist_for_each_entry_rcu(ctx, n, &mm->ioctx_list, list) { + /* + * RCU protects us against accessing freed memory but + * we have to be careful not to get a reference when the + * reference count already dropped to 0 (ctx->dead test + * is unreliable because of races). + */ + if (ctx->user_id == ctx_id && !ctx->dead && try_get_ioctx(ctx)){ + ret = ctx; + break; + } + } rcu_read_unlock(); return ret; @@ -1281,7 +1265,7 @@ static void io_destroy(struct kioctx *ioctx) spin_lock(&mm->ioctx_lock); was_dead = ioctx->dead; ioctx->dead = 1; - radix_tree_delete(&mm->ioctx_rtree, ioctx->user_id); + hlist_del_rcu(&ioctx->list); spin_unlock(&mm->ioctx_lock); dprintk("aio_release(%p)\n", ioctx); diff --git a/include/linux/aio.h b/include/linux/aio.h index 42830d7465f..b1a520ec8b5 100644 --- a/include/linux/aio.h +++ b/include/linux/aio.h @@ -184,6 +184,7 @@ struct kioctx { /* This needs improving */ unsigned long user_id; + struct hlist_node list; wait_queue_head_t wait; diff --git a/include/linux/gfp.h b/include/linux/gfp.h index 55acab018be..7b3823e213e 100644 --- a/include/linux/gfp.h +++ b/include/linux/gfp.h @@ -30,7 +30,6 @@ struct vm_area_struct; #define ___GFP_HARDWALL 0x20000u #define ___GFP_THISNODE 0x40000u #define ___GFP_RECLAIMABLE 0x80000u -#define ___GFP_MEMALLOC 0x100000u #ifdef CONFIG_KMEMCHECK #define ___GFP_NOTRACK 0x200000u #else @@ -80,14 +79,9 @@ struct vm_area_struct; #define __GFP_REPEAT ((__force gfp_t)___GFP_REPEAT) /* See above */ #define __GFP_NOFAIL ((__force gfp_t)___GFP_NOFAIL) /* See above */ #define __GFP_NORETRY ((__force gfp_t)___GFP_NORETRY) /* See above */ -#define __GFP_MEMALLOC ((__force gfp_t)___GFP_MEMALLOC)/* Allow access to emergency reserves */ #define __GFP_COMP ((__force gfp_t)___GFP_COMP) /* Add compound page metadata */ #define __GFP_ZERO ((__force gfp_t)___GFP_ZERO) /* Return zeroed page on success */ -#define __GFP_NOMEMALLOC ((__force gfp_t)___GFP_NOMEMALLOC) /* Don't use emergency reserves. - * This takes precedence over the - * __GFP_MEMALLOC flag if both are - * set - */ +#define __GFP_NOMEMALLOC ((__force gfp_t)___GFP_NOMEMALLOC) /* Don't use emergency reserves */ #define __GFP_HARDWALL ((__force gfp_t)___GFP_HARDWALL) /* Enforce hardwall cpuset memory allocs */ #define __GFP_THISNODE ((__force gfp_t)___GFP_THISNODE)/* No fallback, no policies */ #define __GFP_RECLAIMABLE ((__force gfp_t)___GFP_RECLAIMABLE) /* Page is reclaimable */ @@ -138,7 +132,7 @@ struct vm_area_struct; /* Control page allocator reclaim behavior */ #define GFP_RECLAIM_MASK (__GFP_WAIT|__GFP_HIGH|__GFP_IO|__GFP_FS|\ __GFP_NOWARN|__GFP_REPEAT|__GFP_NOFAIL|\ - __GFP_NORETRY|__GFP_MEMALLOC|__GFP_NOMEMALLOC) + __GFP_NORETRY|__GFP_NOMEMALLOC) /* Control slab gfp mask during early boot */ #define GFP_BOOT_MASK (__GFP_BITS_MASK & ~(__GFP_WAIT|__GFP_IO|__GFP_FS)) diff --git a/include/linux/mempolicy.h b/include/linux/mempolicy.h index cc49b232b6e..fe07e5a9056 100644 --- a/include/linux/mempolicy.h +++ b/include/linux/mempolicy.h @@ -205,7 +205,7 @@ extern struct zonelist *huge_zonelist(struct vm_area_struct *vma, extern bool init_nodemask_of_mempolicy(nodemask_t *mask); extern bool mempolicy_nodemask_intersects(struct task_struct *tsk, const nodemask_t *mask); -extern unsigned slab_node(void); +extern unsigned slab_node(struct mempolicy *policy); extern enum zone_type policy_zone; diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h index 476e00d745e..4fc12b203f0 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h @@ -5,7 +5,6 @@ #include #include #include -#include #include #include #include @@ -53,16 +52,7 @@ struct page { struct { union { pgoff_t index; /* Our offset within mapping. */ - void *freelist; /* slub/slob first free object */ - bool pfmemalloc; /* If set by the page allocator, - * ALLOC_NO_WATERMARKS was set - * and the low watermark was not - * met implying that the system - * is under some pressure. The - * caller should try ensure - * this page is only used to - * free other pages. - */ + void *freelist; /* slub first free object */ }; union { @@ -100,12 +90,11 @@ struct page { */ atomic_t _mapcount; - struct { /* SLUB */ + struct { unsigned inuse:16; unsigned objects:15; unsigned frozen:1; }; - int units; /* SLOB */ }; atomic_t _count; /* Usage count, see below. */ }; @@ -127,9 +116,6 @@ struct page { short int pobjects; #endif }; - - struct list_head list; /* slobs list of pages */ - struct slab *slab_page; /* slab fields */ }; /* Remainder is not double word aligned */ @@ -144,7 +130,7 @@ struct page { #if USE_SPLIT_PTLOCKS spinlock_t ptl; #endif - struct kmem_cache *slab_cache; /* SL[AU]B: Pointer to slab */ + struct kmem_cache *slab; /* SLUB: Pointer to slab */ struct page *first_page; /* Compound tail pages */ }; @@ -389,7 +375,7 @@ struct mm_struct { struct core_state *core_state; /* coredumping support */ #ifdef CONFIG_AIO spinlock_t ioctx_lock; - struct radix_tree_root ioctx_rtree; + struct hlist_head ioctx_list; #endif #ifdef CONFIG_MM_OWNER /* diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h index d10f1a57389..5bc4fa5c6f1 100644 --- a/include/linux/page-flags.h +++ b/include/linux/page-flags.h @@ -7,7 +7,6 @@ #include #include -#include #ifndef __GENERATING_BOUNDS_H #include #include @@ -461,34 +460,6 @@ static inline int PageTransTail(struct page *page) } #endif -/* - * If network-based swap is enabled, sl*b must keep track of whether pages - * were allocated from pfmemalloc reserves. - */ -static inline int PageSlabPfmemalloc(struct page *page) -{ - VM_BUG_ON(!PageSlab(page)); - return PageActive(page); -} - -static inline void SetPageSlabPfmemalloc(struct page *page) -{ - VM_BUG_ON(!PageSlab(page)); - SetPageActive(page); -} - -static inline void __ClearPageSlabPfmemalloc(struct page *page) -{ - VM_BUG_ON(!PageSlab(page)); - __ClearPageActive(page); -} - -static inline void ClearPageSlabPfmemalloc(struct page *page) -{ - VM_BUG_ON(!PageSlab(page)); - ClearPageActive(page); -} - #ifdef CONFIG_MMU #define __PG_MLOCKED (1 << PG_mlocked) #else diff --git a/include/linux/slab.h b/include/linux/slab.h index 2085d04b1c7..a595dce6b0c 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -92,30 +92,6 @@ #define ZERO_OR_NULL_PTR(x) ((unsigned long)(x) <= \ (unsigned long)ZERO_SIZE_PTR) -/* - * Common fields provided in kmem_cache by all slab allocators - * This struct is either used directly by the allocator (SLOB) - * or the allocator must include definitions for all fields - * provided in kmem_cache_common in their definition of kmem_cache. - * - * Once we can do anonymous structs (C11 standard) we could put a - * anonymous struct definition in these allocators so that the - * separate allocations in the kmem_cache structure of SLAB and - * SLUB is no longer needed. - */ -#ifdef CONFIG_SLOB -struct kmem_cache { - unsigned int object_size;/* The original size of the object */ - unsigned int size; /* The aligned/padded/added on size */ - unsigned int align; /* Alignment as calculated */ - unsigned long flags; /* Active flags on the slab */ - const char *name; /* Slab name for sysfs */ - int refcount; /* Use counter */ - void (*ctor)(void *); /* Called on object slot creation */ - struct list_head list; /* List of all slab caches on the system */ -}; -#endif - /* * struct kmem_cache related prototypes */ @@ -128,6 +104,7 @@ struct kmem_cache *kmem_cache_create(const char *, size_t, size_t, void kmem_cache_destroy(struct kmem_cache *); int kmem_cache_shrink(struct kmem_cache *); void kmem_cache_free(struct kmem_cache *, void *); +unsigned int kmem_cache_size(struct kmem_cache *); /* * Please use this macro to create slab caches. Simply specify the @@ -320,8 +297,7 @@ static inline void *kmem_cache_alloc_node(struct kmem_cache *cachep, * request comes from. */ #if defined(CONFIG_DEBUG_SLAB) || defined(CONFIG_SLUB) || \ - (defined(CONFIG_SLAB) && defined(CONFIG_TRACING)) || \ - (defined(CONFIG_SLOB) && defined(CONFIG_TRACING)) + (defined(CONFIG_SLAB) && defined(CONFIG_TRACING)) extern void *__kmalloc_track_caller(size_t, gfp_t, unsigned long); #define kmalloc_track_caller(size, flags) \ __kmalloc_track_caller(size, flags, _RET_IP_) @@ -340,8 +316,7 @@ extern void *__kmalloc_track_caller(size_t, gfp_t, unsigned long); * allocation request comes from. */ #if defined(CONFIG_DEBUG_SLAB) || defined(CONFIG_SLUB) || \ - (defined(CONFIG_SLAB) && defined(CONFIG_TRACING)) || \ - (defined(CONFIG_SLOB) && defined(CONFIG_TRACING)) + (defined(CONFIG_SLAB) && defined(CONFIG_TRACING)) extern void *__kmalloc_node_track_caller(size_t, gfp_t, int, unsigned long); #define kmalloc_node_track_caller(size, flags, node) \ __kmalloc_node_track_caller(size, flags, node, \ @@ -387,14 +362,6 @@ static inline void *kzalloc_node(size_t size, gfp_t flags, int node) return kmalloc_node(size, flags | __GFP_ZERO, node); } -/* - * Determine the size of a slab object - */ -static inline unsigned int kmem_cache_size(struct kmem_cache *s) -{ - return s->object_size; -} - void __init kmem_cache_init_late(void); #endif /* _LINUX_SLAB_H */ diff --git a/include/linux/slab_def.h b/include/linux/slab_def.h index b91c69ffb52..fbd1117fdfd 100644 --- a/include/linux/slab_def.h +++ b/include/linux/slab_def.h @@ -27,7 +27,7 @@ struct kmem_cache { unsigned int limit; unsigned int shared; - unsigned int size; + unsigned int buffer_size; u32 reciprocal_buffer_size; /* 2) touched by every alloc & free from the backend */ @@ -39,7 +39,7 @@ struct kmem_cache { unsigned int gfporder; /* force GFP flags, e.g. GFP_DMA */ - gfp_t allocflags; + gfp_t gfpflags; size_t colour; /* cache colouring range */ unsigned int colour_off; /* colour offset */ @@ -52,10 +52,7 @@ struct kmem_cache { /* 4) cache creation/removal */ const char *name; - struct list_head list; - int refcount; - int object_size; - int align; + struct list_head next; /* 5) statistics */ #ifdef CONFIG_DEBUG_SLAB @@ -76,11 +73,12 @@ struct kmem_cache { /* * If debugging is enabled, then the allocator can add additional - * fields and/or padding to every object. size contains the total + * fields and/or padding to every object. buffer_size contains the total * object size including these internal fields, the following two * variables contain the offset to the user object and its size. */ int obj_offset; + int obj_size; #endif /* CONFIG_DEBUG_SLAB */ /* 6) per-cpu/per-node data, touched during every alloc/free */ @@ -90,13 +88,9 @@ struct kmem_cache { * (see kmem_cache_init()) * We still use [NR_CPUS] and not [1] or [0] because cache_cache * is statically defined, so we reserve the max number of cpus. - * - * We also need to guarantee that the list is able to accomodate a - * pointer for each node since "nodelists" uses the remainder of - * available pointers. */ struct kmem_list3 **nodelists; - struct array_cache *array[NR_CPUS + MAX_NUMNODES]; + struct array_cache *array[NR_CPUS]; /* * Do not add fields after array[] */ @@ -116,13 +110,19 @@ void *kmem_cache_alloc(struct kmem_cache *, gfp_t); void *__kmalloc(size_t size, gfp_t flags); #ifdef CONFIG_TRACING -extern void *kmem_cache_alloc_trace(struct kmem_cache *, gfp_t, size_t); +extern void *kmem_cache_alloc_trace(size_t size, + struct kmem_cache *cachep, gfp_t flags); +extern size_t slab_buffer_size(struct kmem_cache *cachep); #else static __always_inline void * -kmem_cache_alloc_trace(struct kmem_cache *cachep, gfp_t flags, size_t size) +kmem_cache_alloc_trace(size_t size, struct kmem_cache *cachep, gfp_t flags) { return kmem_cache_alloc(cachep, flags); } +static inline size_t slab_buffer_size(struct kmem_cache *cachep) +{ + return 0; +} #endif static __always_inline void *kmalloc(size_t size, gfp_t flags) @@ -152,7 +152,7 @@ static __always_inline void *kmalloc(size_t size, gfp_t flags) #endif cachep = malloc_sizes[i].cs_cachep; - ret = kmem_cache_alloc_trace(cachep, flags, size); + ret = kmem_cache_alloc_trace(size, cachep, flags); return ret; } diff --git a/include/linux/slob_def.h b/include/linux/slob_def.h index f28e14a12e3..0ec00b39d00 100644 --- a/include/linux/slob_def.h +++ b/include/linux/slob_def.h @@ -1,14 +1,12 @@ #ifndef __LINUX_SLOB_DEF_H #define __LINUX_SLOB_DEF_H -#include - void *kmem_cache_alloc_node(struct kmem_cache *, gfp_t flags, int node); static __always_inline void *kmem_cache_alloc(struct kmem_cache *cachep, gfp_t flags) { - return kmem_cache_alloc_node(cachep, flags, NUMA_NO_NODE); + return kmem_cache_alloc_node(cachep, flags, -1); } void *__kmalloc_node(size_t size, gfp_t flags, int node); @@ -28,7 +26,7 @@ static __always_inline void *kmalloc_node(size_t size, gfp_t flags, int node) */ static __always_inline void *kmalloc(size_t size, gfp_t flags) { - return __kmalloc_node(size, flags, NUMA_NO_NODE); + return __kmalloc_node(size, flags, -1); } static __always_inline void *__kmalloc(size_t size, gfp_t flags) diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h index df448adb728..c2f8c8bc56e 100644 --- a/include/linux/slub_def.h +++ b/include/linux/slub_def.h @@ -48,6 +48,7 @@ struct kmem_cache_cpu { unsigned long tid; /* Globally unique transaction id */ struct page *page; /* The slab from which we are allocating */ struct page *partial; /* Partially allocated frozen slabs */ + int node; /* The node of the page (or -1 for debug) */ #ifdef CONFIG_SLUB_STATS unsigned stat[NR_SLUB_STAT_ITEMS]; #endif @@ -82,7 +83,7 @@ struct kmem_cache { unsigned long flags; unsigned long min_partial; int size; /* The size of an object including meta data */ - int object_size; /* The size of an object without meta data */ + int objsize; /* The size of an object without meta data */ int offset; /* Free pointer offset. */ int cpu_partial; /* Number of per cpu partial objects to keep around */ struct kmem_cache_order_objects oo; diff --git a/include/trace/events/gfpflags.h b/include/trace/events/gfpflags.h index d6fd8e5b14b..9fe3a36646e 100644 --- a/include/trace/events/gfpflags.h +++ b/include/trace/events/gfpflags.h @@ -30,7 +30,6 @@ {(unsigned long)__GFP_COMP, "GFP_COMP"}, \ {(unsigned long)__GFP_ZERO, "GFP_ZERO"}, \ {(unsigned long)__GFP_NOMEMALLOC, "GFP_NOMEMALLOC"}, \ - {(unsigned long)__GFP_MEMALLOC, "GFP_MEMALLOC"}, \ {(unsigned long)__GFP_HARDWALL, "GFP_HARDWALL"}, \ {(unsigned long)__GFP_THISNODE, "GFP_THISNODE"}, \ {(unsigned long)__GFP_RECLAIMABLE, "GFP_RECLAIMABLE"}, \ diff --git a/kernel/fork.c b/kernel/fork.c index 26b20382302..e775c328172 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -499,7 +499,7 @@ static void mm_init_aio(struct mm_struct *mm) { #ifdef CONFIG_AIO spin_lock_init(&mm->ioctx_lock); - INIT_RADIX_TREE(&mm->ioctx_rtree, GFP_KERNEL); + INIT_HLIST_HEAD(&mm->ioctx_list); #endif } diff --git a/mm/Makefile b/mm/Makefile index 90be6c3c921..8aada89efbb 100644 --- a/mm/Makefile +++ b/mm/Makefile @@ -13,8 +13,7 @@ obj-y := filemap.o mempool.o oom_kill.o fadvise.o \ readahead.o swap.o truncate.o vmscan.o shmem.o \ prio_tree.o util.o mmzone.o vmstat.o backing-dev.o \ page_isolation.o mm_init.o mmu_context.o percpu.o \ - compaction.o slab_common.o $(mmu-y) - + compaction.o $(mmu-y) obj-y += init-mm.o ifdef CONFIG_NO_BOOTMEM diff --git a/mm/internal.h b/mm/internal.h index aeac5c7da89..8c6fd44d83b 100644 --- a/mm/internal.h +++ b/mm/internal.h @@ -272,9 +272,6 @@ static inline struct page *mem_map_next(struct page *iter, #define __paginginit __init #endif -/* Returns true if the gfp_mask allows use of ALLOC_NO_WATERMARK */ -bool gfp_pfmemalloc_allowed(gfp_t gfp_mask); - /* Memory initialisation debug and verification */ enum mminit_level { MMINIT_WARNING, @@ -359,4 +356,3 @@ extern u32 hwpoison_filter_enable; #define ALLOC_HIGH 0x20 /* __GFP_HIGH set */ #define ALLOC_CPUSET 0x40 /* check for correct cpuset */ #define ALLOC_CMA 0x80 /* allow allocations from CMA areas */ - diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 9efb806b6fd..46cb63b956f 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -1614,14 +1614,8 @@ static unsigned interleave_nodes(struct mempolicy *policy) * task can change it's policy. The system default policy requires no * such protection. */ -unsigned slab_node(void) +unsigned slab_node(struct mempolicy *policy) { - struct mempolicy *policy; - - if (in_interrupt()) - return numa_node_id(); - - policy = current->mempolicy; if (!policy || policy->flags & MPOL_F_LOCAL) return numa_node_id(); diff --git a/mm/page_alloc.c b/mm/page_alloc.c index ffa73b550f7..830ae0dccb3 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -2331,9 +2331,9 @@ gfp_to_alloc_flags(gfp_t gfp_mask) alloc_flags |= ALLOC_HARDER; if (likely(!(gfp_mask & __GFP_NOMEMALLOC))) { - if (gfp_mask & __GFP_MEMALLOC) - alloc_flags |= ALLOC_NO_WATERMARKS; - else if (likely(!(gfp_mask & __GFP_NOMEMALLOC)) && !in_interrupt()) + if (!in_interrupt() && + ((current->flags & PF_MEMALLOC) || + unlikely(test_thread_flag(TIF_MEMDIE)))) alloc_flags |= ALLOC_NO_WATERMARKS; } #ifdef CONFIG_CMA @@ -2343,11 +2343,6 @@ gfp_to_alloc_flags(gfp_t gfp_mask) return alloc_flags; } -bool gfp_pfmemalloc_allowed(gfp_t gfp_mask) -{ - return !!(gfp_to_alloc_flags(gfp_mask) & ALLOC_NO_WATERMARKS); -} - static inline struct page * __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order, struct zonelist *zonelist, enum zone_type high_zoneidx, @@ -2535,18 +2530,10 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order, warn_alloc_failed(gfp_mask, order, NULL); return page; got_pg: - /* - * page->pfmemalloc is set when the caller had PFMEMALLOC set, is - * been OOM killed or specified __GFP_MEMALLOC. The expectation is - * that the caller is taking steps that will free more memory. The - * caller should avoid the page being used for !PFMEMALLOC purposes. - */ - page->pfmemalloc = !!(alloc_flags & ALLOC_NO_WATERMARKS); - if (kmemcheck_enabled) kmemcheck_pagealloc_alloc(page, order, gfp_mask); - return page; + } /* @@ -2602,8 +2589,6 @@ __alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order, page = __alloc_pages_slowpath(gfp_mask, order, zonelist, high_zoneidx, nodemask, preferred_zone, migratetype); - else - page->pfmemalloc = false; trace_mm_page_alloc(page, order, gfp_mask, migratetype); diff --git a/mm/slab.c b/mm/slab.c index 09e4899bbaa..fb563b520d6 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -68,7 +68,7 @@ * Further notes from the original documentation: * * 11 April '97. Started multi-threading - markhe - * The global cache-chain is protected by the mutex 'slab_mutex'. + * The global cache-chain is protected by the mutex 'cache_chain_mutex'. * The sem is only needed when accessing/extending the cache-chain, which * can never happen inside an interrupt (kmem_cache_create(), * kmem_cache_shrink() and kmem_cache_reap()). @@ -123,10 +123,6 @@ #include -#include "internal.h" - -#include "slab.h" - /* * DEBUG - 1 for kmem_cache_create() to honour; SLAB_RED_ZONE & SLAB_POISON. * 0 for faster, smaller code (especially in the critical paths). @@ -155,11 +151,22 @@ #define ARCH_KMALLOC_FLAGS SLAB_HWCACHE_ALIGN #endif -/* - * true if a page was allocated from pfmemalloc reserves for network-based - * swap - */ -static bool pfmemalloc_active __read_mostly; +/* Legal flag mask for kmem_cache_create(). */ +#if DEBUG +# define CREATE_MASK (SLAB_RED_ZONE | \ + SLAB_POISON | SLAB_HWCACHE_ALIGN | \ + SLAB_CACHE_DMA | \ + SLAB_STORE_USER | \ + SLAB_RECLAIM_ACCOUNT | SLAB_PANIC | \ + SLAB_DESTROY_BY_RCU | SLAB_MEM_SPREAD | \ + SLAB_DEBUG_OBJECTS | SLAB_NOLEAKTRACE | SLAB_NOTRACK) +#else +# define CREATE_MASK (SLAB_HWCACHE_ALIGN | \ + SLAB_CACHE_DMA | \ + SLAB_RECLAIM_ACCOUNT | SLAB_PANIC | \ + SLAB_DESTROY_BY_RCU | SLAB_MEM_SPREAD | \ + SLAB_DEBUG_OBJECTS | SLAB_NOLEAKTRACE | SLAB_NOTRACK) +#endif /* * kmem_bufctl_t: @@ -249,30 +256,9 @@ struct array_cache { * Must have this definition in here for the proper * alignment of array_cache. Also simplifies accessing * the entries. - * - * Entries should not be directly dereferenced as - * entries belonging to slabs marked pfmemalloc will - * have the lower bits set SLAB_OBJ_PFMEMALLOC */ }; -#define SLAB_OBJ_PFMEMALLOC 1 -static inline bool is_obj_pfmemalloc(void *objp) -{ - return (unsigned long)objp & SLAB_OBJ_PFMEMALLOC; -} - -static inline void set_obj_pfmemalloc(void **objp) -{ - *objp = (void *)((unsigned long)*objp | SLAB_OBJ_PFMEMALLOC); - return; -} - -static inline void clear_obj_pfmemalloc(void **objp) -{ - *objp = (void *)((unsigned long)*objp & ~SLAB_OBJ_PFMEMALLOC); -} - /* * bootstrap: The caches do not work without cpuarrays anymore, but the * cpuarrays are allocated from the generic caches... @@ -438,8 +424,8 @@ static void kmem_list3_init(struct kmem_list3 *parent) * cachep->obj_offset - BYTES_PER_WORD .. cachep->obj_offset - 1: * redzone word. * cachep->obj_offset: The real object. - * cachep->size - 2* BYTES_PER_WORD: redzone word [BYTES_PER_WORD long] - * cachep->size - 1* BYTES_PER_WORD: last caller address + * cachep->buffer_size - 2* BYTES_PER_WORD: redzone word [BYTES_PER_WORD long] + * cachep->buffer_size - 1* BYTES_PER_WORD: last caller address * [BYTES_PER_WORD long] */ static int obj_offset(struct kmem_cache *cachep) @@ -447,6 +433,11 @@ static int obj_offset(struct kmem_cache *cachep) return cachep->obj_offset; } +static int obj_size(struct kmem_cache *cachep) +{ + return cachep->obj_size; +} + static unsigned long long *dbg_redzone1(struct kmem_cache *cachep, void *objp) { BUG_ON(!(cachep->flags & SLAB_RED_ZONE)); @@ -458,28 +449,37 @@ static unsigned long long *dbg_redzone2(struct kmem_cache *cachep, void *objp) { BUG_ON(!(cachep->flags & SLAB_RED_ZONE)); if (cachep->flags & SLAB_STORE_USER) - return (unsigned long long *)(objp + cachep->size - + return (unsigned long long *)(objp + cachep->buffer_size - sizeof(unsigned long long) - REDZONE_ALIGN); - return (unsigned long long *) (objp + cachep->size - + return (unsigned long long *) (objp + cachep->buffer_size - sizeof(unsigned long long)); } static void **dbg_userword(struct kmem_cache *cachep, void *objp) { BUG_ON(!(cachep->flags & SLAB_STORE_USER)); - return (void **)(objp + cachep->size - BYTES_PER_WORD); + return (void **)(objp + cachep->buffer_size - BYTES_PER_WORD); } #else #define obj_offset(x) 0 +#define obj_size(cachep) (cachep->buffer_size) #define dbg_redzone1(cachep, objp) ({BUG(); (unsigned long long *)NULL;}) #define dbg_redzone2(cachep, objp) ({BUG(); (unsigned long long *)NULL;}) #define dbg_userword(cachep, objp) ({BUG(); (void **)NULL;}) #endif +#ifdef CONFIG_TRACING +size_t slab_buffer_size(struct kmem_cache *cachep) +{ + return cachep->buffer_size; +} +EXPORT_SYMBOL(slab_buffer_size); +#endif + /* * Do not go above this order unless 0 objects fit into the slab or * overridden on the command line. @@ -489,30 +489,56 @@ static void **dbg_userword(struct kmem_cache *cachep, void *objp) static int slab_max_order = SLAB_MAX_ORDER_LO; static bool slab_max_order_set __initdata; +/* + * Functions for storing/retrieving the cachep and or slab from the page + * allocator. These are used to find the slab an obj belongs to. With kfree(), + * these are used to find the cache which an obj belongs to. + */ +static inline void page_set_cache(struct page *page, struct kmem_cache *cache) +{ + page->lru.next = (struct list_head *)cache; +} + +static inline struct kmem_cache *page_get_cache(struct page *page) +{ + page = compound_head(page); + BUG_ON(!PageSlab(page)); + return (struct kmem_cache *)page->lru.next; +} + +static inline void page_set_slab(struct page *page, struct slab *slab) +{ + page->lru.prev = (struct list_head *)slab; +} + +static inline struct slab *page_get_slab(struct page *page) +{ + BUG_ON(!PageSlab(page)); + return (struct slab *)page->lru.prev; +} + static inline struct kmem_cache *virt_to_cache(const void *obj) { struct page *page = virt_to_head_page(obj); - return page->slab_cache; + return page_get_cache(page); } static inline struct slab *virt_to_slab(const void *obj) { struct page *page = virt_to_head_page(obj); - - VM_BUG_ON(!PageSlab(page)); - return page->slab_page; + return page_get_slab(page); } static inline void *index_to_obj(struct kmem_cache *cache, struct slab *slab, unsigned int idx) { - return slab->s_mem + cache->size * idx; + return slab->s_mem + cache->buffer_size * idx; } /* - * We want to avoid an expensive divide : (offset / cache->size) - * Using the fact that size is a constant for a particular cache, - * we can replace (offset / cache->size) by + * We want to avoid an expensive divide : (offset / cache->buffer_size) + * Using the fact that buffer_size is a constant for a particular cache, + * we can replace (offset / cache->buffer_size) by * reciprocal_divide(offset, cache->reciprocal_buffer_size) */ static inline unsigned int obj_to_index(const struct kmem_cache *cache, @@ -546,20 +572,45 @@ static struct cache_names __initdata cache_names[] = { #undef CACHE }; +static struct arraycache_init initarray_cache __initdata = + { {0, BOOT_CPUCACHE_ENTRIES, 1, 0} }; static struct arraycache_init initarray_generic = { {0, BOOT_CPUCACHE_ENTRIES, 1, 0} }; /* internal cache of cache description objs */ -static struct kmem_cache kmem_cache_boot = { +static struct kmem_list3 *cache_cache_nodelists[MAX_NUMNODES]; +static struct kmem_cache cache_cache = { + .nodelists = cache_cache_nodelists, .batchcount = 1, .limit = BOOT_CPUCACHE_ENTRIES, .shared = 1, - .size = sizeof(struct kmem_cache), + .buffer_size = sizeof(struct kmem_cache), .name = "kmem_cache", }; #define BAD_ALIEN_MAGIC 0x01020304ul +/* + * chicken and egg problem: delay the per-cpu array allocation + * until the general caches are up. + */ +static enum { + NONE, + PARTIAL_AC, + PARTIAL_L3, + EARLY, + LATE, + FULL +} g_cpucache_up; + +/* + * used by boot code to determine if it can use slab based allocator + */ +int slab_is_available(void) +{ + return g_cpucache_up >= EARLY; +} + #ifdef CONFIG_LOCKDEP /* @@ -625,7 +676,7 @@ static void init_node_lock_keys(int q) { struct cache_sizes *s = malloc_sizes; - if (slab_state < UP) + if (g_cpucache_up < LATE) return; for (s = malloc_sizes; s->cs_size != ULONG_MAX; s++) { @@ -640,26 +691,6 @@ static void init_node_lock_keys(int q) } } -static void on_slab_lock_classes_node(struct kmem_cache *cachep, int q) -{ - struct kmem_list3 *l3; - l3 = cachep->nodelists[q]; - if (!l3) - return; - - slab_set_lock_classes(cachep, &on_slab_l3_key, - &on_slab_alc_key, q); -} - -static inline void on_slab_lock_classes(struct kmem_cache *cachep) -{ - int node; - - VM_BUG_ON(OFF_SLAB(cachep)); - for_each_node(node) - on_slab_lock_classes_node(cachep, node); -} - static inline void init_lock_keys(void) { int node; @@ -676,14 +707,6 @@ static inline void init_lock_keys(void) { } -static inline void on_slab_lock_classes(struct kmem_cache *cachep) -{ -} - -static inline void on_slab_lock_classes_node(struct kmem_cache *cachep, int node) -{ -} - static void slab_set_debugobj_lock_classes_node(struct kmem_cache *cachep, int node) { } @@ -693,6 +716,12 @@ static void slab_set_debugobj_lock_classes(struct kmem_cache *cachep) } #endif +/* + * Guard access to the cache-chain. + */ +static DEFINE_MUTEX(cache_chain_mutex); +static struct list_head cache_chain; + static DEFINE_PER_CPU(struct delayed_work, slab_reap_work); static inline struct array_cache *cpu_cache_get(struct kmem_cache *cachep) @@ -801,7 +830,6 @@ static void cache_estimate(unsigned long gfporder, size_t buffer_size, *left_over = slab_size - nr_objs*buffer_size - mgmt_size; } -#if DEBUG #define slab_error(cachep, msg) __slab_error(__func__, cachep, msg) static void __slab_error(const char *function, struct kmem_cache *cachep, @@ -810,9 +838,7 @@ static void __slab_error(const char *function, struct kmem_cache *cachep, printk(KERN_ERR "slab error in %s(): cache `%s': %s\n", function, cachep->name, msg); dump_stack(); - add_taint(TAINT_BAD_PAGE); } -#endif /* * By default on NUMA we use alien caches to stage the freeing of @@ -925,102 +951,6 @@ static struct array_cache *alloc_arraycache(int node, int entries, return nc; } -static inline bool is_slab_pfmemalloc(struct slab *slabp) -{ - struct page *page = virt_to_page(slabp->s_mem); - - return PageSlabPfmemalloc(page); -} - -/* Clears pfmemalloc_active if no slabs have pfmalloc set */ -static void recheck_pfmemalloc_active(struct kmem_cache *cachep, - struct array_cache *ac) -{ - struct kmem_list3 *l3 = cachep->nodelists[numa_mem_id()]; - struct slab *slabp; - unsigned long flags; - - if (!pfmemalloc_active) - return; - - spin_lock_irqsave(&l3->list_lock, flags); - list_for_each_entry(slabp, &l3->slabs_full, list) - if (is_slab_pfmemalloc(slabp)) - goto out; - - list_for_each_entry(slabp, &l3->slabs_partial, list) - if (is_slab_pfmemalloc(slabp)) - goto out; - - list_for_each_entry(slabp, &l3->slabs_free, list) - if (is_slab_pfmemalloc(slabp)) - goto out; - - pfmemalloc_active = false; -out: - spin_unlock_irqrestore(&l3->list_lock, flags); -} - -static void *ac_get_obj(struct kmem_cache *cachep, struct array_cache *ac, - gfp_t flags, bool force_refill) -{ - int i; - void *objp = ac->entry[--ac->avail]; - - /* Ensure the caller is allowed to use objects from PFMEMALLOC slab */ - if (unlikely(is_obj_pfmemalloc(objp))) { - struct kmem_list3 *l3; - - if (gfp_pfmemalloc_allowed(flags)) { - clear_obj_pfmemalloc(&objp); - return objp; - } - - /* The caller cannot use PFMEMALLOC objects, find another one */ - for (i = 0; i < ac->avail; i++) { - /* If a !PFMEMALLOC object is found, swap them */ - if (!is_obj_pfmemalloc(ac->entry[i])) { - objp = ac->entry[i]; - ac->entry[i] = ac->entry[ac->avail]; - ac->entry[ac->avail] = objp; - return objp; - } - } - - /* - * If there are empty slabs on the slabs_free list and we are - * being forced to refill the cache, mark this one !pfmemalloc. - */ - l3 = cachep->nodelists[numa_mem_id()]; - if (!list_empty(&l3->slabs_free) && force_refill) { - struct slab *slabp = virt_to_slab(objp); - ClearPageSlabPfmemalloc(virt_to_head_page(slabp->s_mem)); - clear_obj_pfmemalloc(&objp); - recheck_pfmemalloc_active(cachep, ac); - return objp; - } - - /* No !PFMEMALLOC objects available */ - ac->avail++; - objp = NULL; - } - - return objp; -} - -static void ac_put_obj(struct kmem_cache *cachep, struct array_cache *ac, - void *objp) -{ - if (unlikely(pfmemalloc_active)) { - /* Some pfmemalloc slabs exist, check if this is one */ - struct page *page = virt_to_head_page(objp); - if (PageSlabPfmemalloc(page)) - set_obj_pfmemalloc(&objp); - } - - ac->entry[ac->avail++] = objp; -} - /* * Transfer objects in one arraycache to another. * Locking must be handled by the caller. @@ -1197,7 +1127,7 @@ static inline int cache_free_alien(struct kmem_cache *cachep, void *objp) STATS_INC_ACOVERFLOW(cachep); __drain_alien_cache(cachep, alien, nodeid); } - ac_put_obj(cachep, alien, objp); + alien->entry[alien->avail++] = objp; spin_unlock(&alien->lock); } else { spin_lock(&(cachep->nodelists[nodeid])->list_lock); @@ -1215,7 +1145,7 @@ static inline int cache_free_alien(struct kmem_cache *cachep, void *objp) * When hotplugging memory or a cpu, existing nodelists are not replaced if * already in use. * - * Must hold slab_mutex. + * Must hold cache_chain_mutex. */ static int init_cache_nodelists_node(int node) { @@ -1223,7 +1153,7 @@ static int init_cache_nodelists_node(int node) struct kmem_list3 *l3; const int memsize = sizeof(struct kmem_list3); - list_for_each_entry(cachep, &slab_caches, list) { + list_for_each_entry(cachep, &cache_chain, next) { /* * Set up the size64 kmemlist for cpu before we can * begin anything. Make sure some other cpu on this @@ -1239,7 +1169,7 @@ static int init_cache_nodelists_node(int node) /* * The l3s don't come and go as CPUs come and - * go. slab_mutex is sufficient + * go. cache_chain_mutex is sufficient * protection here. */ cachep->nodelists[node] = l3; @@ -1261,7 +1191,7 @@ static void cpuup_canceled(long cpu) int node = cpu_to_mem(cpu); const struct cpumask *mask = cpumask_of_node(node); - list_for_each_entry(cachep, &slab_caches, list) { + list_for_each_entry(cachep, &cache_chain, next) { struct array_cache *nc; struct array_cache *shared; struct array_cache **alien; @@ -1311,7 +1241,7 @@ static void cpuup_canceled(long cpu) * the respective cache's slabs, now we can go ahead and * shrink each nodelist to its limit. */ - list_for_each_entry(cachep, &slab_caches, list) { + list_for_each_entry(cachep, &cache_chain, next) { l3 = cachep->nodelists[node]; if (!l3) continue; @@ -1340,7 +1270,7 @@ static int cpuup_prepare(long cpu) * Now we can go ahead with allocating the shared arrays and * array caches */ - list_for_each_entry(cachep, &slab_caches, list) { + list_for_each_entry(cachep, &cache_chain, next) { struct array_cache *nc; struct array_cache *shared = NULL; struct array_cache **alien = NULL; @@ -1390,9 +1320,6 @@ static int cpuup_prepare(long cpu) free_alien_cache(alien); if (cachep->flags & SLAB_DEBUG_OBJECTS) slab_set_debugobj_lock_classes_node(cachep, node); - else if (!OFF_SLAB(cachep) && - !(cachep->flags & SLAB_DESTROY_BY_RCU)) - on_slab_lock_classes_node(cachep, node); } init_node_lock_keys(node); @@ -1411,9 +1338,9 @@ static int cpuup_callback(struct notifier_block *nfb, switch (action) { case CPU_UP_PREPARE: case CPU_UP_PREPARE_FROZEN: - mutex_lock(&slab_mutex); + mutex_lock(&cache_chain_mutex); err = cpuup_prepare(cpu); - mutex_unlock(&slab_mutex); + mutex_unlock(&cache_chain_mutex); break; case CPU_ONLINE: case CPU_ONLINE_FROZEN: @@ -1423,7 +1350,7 @@ static int cpuup_callback(struct notifier_block *nfb, case CPU_DOWN_PREPARE: case CPU_DOWN_PREPARE_FROZEN: /* - * Shutdown cache reaper. Note that the slab_mutex is + * Shutdown cache reaper. Note that the cache_chain_mutex is * held so that if cache_reap() is invoked it cannot do * anything expensive but will only modify reap_work * and reschedule the timer. @@ -1450,9 +1377,9 @@ static int cpuup_callback(struct notifier_block *nfb, #endif case CPU_UP_CANCELED: case CPU_UP_CANCELED_FROZEN: - mutex_lock(&slab_mutex); + mutex_lock(&cache_chain_mutex); cpuup_canceled(cpu); - mutex_unlock(&slab_mutex); + mutex_unlock(&cache_chain_mutex); break; } return notifier_from_errno(err); @@ -1468,14 +1395,14 @@ static struct notifier_block cpucache_notifier = { * Returns -EBUSY if all objects cannot be drained so that the node is not * removed. * - * Must hold slab_mutex. + * Must hold cache_chain_mutex. */ static int __meminit drain_cache_nodelists_node(int node) { struct kmem_cache *cachep; int ret = 0; - list_for_each_entry(cachep, &slab_caches, list) { + list_for_each_entry(cachep, &cache_chain, next) { struct kmem_list3 *l3; l3 = cachep->nodelists[node]; @@ -1506,14 +1433,14 @@ static int __meminit slab_memory_callback(struct notifier_block *self, switch (action) { case MEM_GOING_ONLINE: - mutex_lock(&slab_mutex); + mutex_lock(&cache_chain_mutex); ret = init_cache_nodelists_node(nid); - mutex_unlock(&slab_mutex); + mutex_unlock(&cache_chain_mutex); break; case MEM_GOING_OFFLINE: - mutex_lock(&slab_mutex); + mutex_lock(&cache_chain_mutex); ret = drain_cache_nodelists_node(nid); - mutex_unlock(&slab_mutex); + mutex_unlock(&cache_chain_mutex); break; case MEM_ONLINE: case MEM_OFFLINE: @@ -1563,35 +1490,28 @@ static void __init set_up_list3s(struct kmem_cache *cachep, int index) } } -/* - * The memory after the last cpu cache pointer is used for the - * the nodelists pointer. - */ -static void setup_nodelists_pointer(struct kmem_cache *cachep) -{ - cachep->nodelists = (struct kmem_list3 **)&cachep->array[nr_cpu_ids]; -} - /* * Initialisation. Called after the page allocator have been initialised and * before smp_init(). */ void __init kmem_cache_init(void) { + size_t left_over; struct cache_sizes *sizes; struct cache_names *names; int i; - - kmem_cache = &kmem_cache_boot; - setup_nodelists_pointer(kmem_cache); + int order; + int node; if (num_possible_nodes() == 1) use_alien_caches = 0; - for (i = 0; i < NUM_INIT_LISTS; i++) + for (i = 0; i < NUM_INIT_LISTS; i++) { kmem_list3_init(&initkmem_list3[i]); - - set_up_list3s(kmem_cache, CACHE_CACHE); + if (i < MAX_NUMNODES) + cache_cache.nodelists[i] = NULL; + } + set_up_list3s(&cache_cache, CACHE_CACHE); /* * Fragmentation resistance on low memory - only use bigger @@ -1603,9 +1523,9 @@ void __init kmem_cache_init(void) /* Bootstrap is tricky, because several objects are allocated * from caches that do not exist yet: - * 1) initialize the kmem_cache cache: it contains the struct - * kmem_cache structures of all caches, except kmem_cache itself: - * kmem_cache is statically allocated. + * 1) initialize the cache_cache cache: it contains the struct + * kmem_cache structures of all caches, except cache_cache itself: + * cache_cache is statically allocated. * Initially an __init data area is used for the head array and the * kmem_list3 structures, it's replaced with a kmalloc allocated * array at the end of the bootstrap. @@ -1614,23 +1534,46 @@ void __init kmem_cache_init(void) * An __init data area is used for the head array. * 3) Create the remaining kmalloc caches, with minimally sized * head arrays. - * 4) Replace the __init data head arrays for kmem_cache and the first + * 4) Replace the __init data head arrays for cache_cache and the first * kmalloc cache with kmalloc allocated arrays. - * 5) Replace the __init data for kmem_list3 for kmem_cache and + * 5) Replace the __init data for kmem_list3 for cache_cache and * the other cache's with kmalloc allocated memory. * 6) Resize the head arrays of the kmalloc caches to their final sizes. */ - /* 1) create the kmem_cache */ + node = numa_mem_id(); + + /* 1) create the cache_cache */ + INIT_LIST_HEAD(&cache_chain); + list_add(&cache_cache.next, &cache_chain); + cache_cache.colour_off = cache_line_size(); + cache_cache.array[smp_processor_id()] = &initarray_cache.cache; + cache_cache.nodelists[node] = &initkmem_list3[CACHE_CACHE + node]; /* * struct kmem_cache size depends on nr_node_ids & nr_cpu_ids */ - create_boot_cache(kmem_cache, "kmem_cache", - offsetof(struct kmem_cache, array[nr_cpu_ids]) + - nr_node_ids * sizeof(struct kmem_list3 *), - SLAB_HWCACHE_ALIGN); - list_add(&kmem_cache->list, &slab_caches); + cache_cache.buffer_size = offsetof(struct kmem_cache, array[nr_cpu_ids]) + + nr_node_ids * sizeof(struct kmem_list3 *); +#if DEBUG + cache_cache.obj_size = cache_cache.buffer_size; +#endif + cache_cache.buffer_size = ALIGN(cache_cache.buffer_size, + cache_line_size()); + cache_cache.reciprocal_buffer_size = + reciprocal_value(cache_cache.buffer_size); + + for (order = 0; order < MAX_ORDER; order++) { + cache_estimate(order, cache_cache.buffer_size, + cache_line_size(), 0, &left_over, &cache_cache.num); + if (cache_cache.num) + break; + } + BUG_ON(!cache_cache.num); + cache_cache.gfporder = order; + cache_cache.colour = left_over / cache_cache.colour_off; + cache_cache.slab_size = ALIGN(cache_cache.num * sizeof(kmem_bufctl_t) + + sizeof(struct slab), cache_line_size()); /* 2+3) create the kmalloc caches */ sizes = malloc_sizes; @@ -1642,13 +1585,20 @@ void __init kmem_cache_init(void) * bug. */ - sizes[INDEX_AC].cs_cachep = create_kmalloc_cache(names[INDEX_AC].name, - sizes[INDEX_AC].cs_size, ARCH_KMALLOC_FLAGS); + sizes[INDEX_AC].cs_cachep = kmem_cache_create(names[INDEX_AC].name, + sizes[INDEX_AC].cs_size, + ARCH_KMALLOC_MINALIGN, + ARCH_KMALLOC_FLAGS|SLAB_PANIC, + NULL); - if (INDEX_AC != INDEX_L3) + if (INDEX_AC != INDEX_L3) { sizes[INDEX_L3].cs_cachep = - create_kmalloc_cache(names[INDEX_L3].name, - sizes[INDEX_L3].cs_size, ARCH_KMALLOC_FLAGS); + kmem_cache_create(names[INDEX_L3].name, + sizes[INDEX_L3].cs_size, + ARCH_KMALLOC_MINALIGN, + ARCH_KMALLOC_FLAGS|SLAB_PANIC, + NULL); + } slab_early_init = 0; @@ -1660,14 +1610,21 @@ void __init kmem_cache_init(void) * Note for systems short on memory removing the alignment will * allow tighter packing of the smaller caches. */ - if (!sizes->cs_cachep) - sizes->cs_cachep = create_kmalloc_cache(names->name, - sizes->cs_size, ARCH_KMALLOC_FLAGS); - + if (!sizes->cs_cachep) { + sizes->cs_cachep = kmem_cache_create(names->name, + sizes->cs_size, + ARCH_KMALLOC_MINALIGN, + ARCH_KMALLOC_FLAGS|SLAB_PANIC, + NULL); + } #ifdef CONFIG_ZONE_DMA - sizes->cs_dmacachep = create_kmalloc_cache( - names->name_dma, sizes->cs_size, - SLAB_CACHE_DMA|ARCH_KMALLOC_FLAGS); + sizes->cs_dmacachep = kmem_cache_create( + names->name_dma, + sizes->cs_size, + ARCH_KMALLOC_MINALIGN, + ARCH_KMALLOC_FLAGS|SLAB_CACHE_DMA| + SLAB_PANIC, + NULL); #endif sizes++; names++; @@ -1678,14 +1635,15 @@ void __init kmem_cache_init(void) ptr = kmalloc(sizeof(struct arraycache_init), GFP_NOWAIT); - memcpy(ptr, cpu_cache_get(kmem_cache), + BUG_ON(cpu_cache_get(&cache_cache) != &initarray_cache.cache); + memcpy(ptr, cpu_cache_get(&cache_cache), sizeof(struct arraycache_init)); /* * Do not assume that spinlocks can be initialized via memcpy: */ spin_lock_init(&ptr->lock); - kmem_cache->array[smp_processor_id()] = ptr; + cache_cache.array[smp_processor_id()] = ptr; ptr = kmalloc(sizeof(struct arraycache_init), GFP_NOWAIT); @@ -1706,7 +1664,7 @@ void __init kmem_cache_init(void) int nid; for_each_online_node(nid) { - init_list(kmem_cache, &initkmem_list3[CACHE_CACHE + nid], nid); + init_list(&cache_cache, &initkmem_list3[CACHE_CACHE + nid], nid); init_list(malloc_sizes[INDEX_AC].cs_cachep, &initkmem_list3[SIZE_AC + nid], nid); @@ -1718,33 +1676,33 @@ void __init kmem_cache_init(void) } } - slab_state = UP; + g_cpucache_up = EARLY; } void __init kmem_cache_init_late(void) { struct kmem_cache *cachep; - slab_state = UP; + g_cpucache_up = LATE; - /* 6) resize the head arrays to their final sizes */ - mutex_lock(&slab_mutex); - list_for_each_entry(cachep, &slab_caches, list) - if (enable_cpucache(cachep, GFP_NOWAIT)) - BUG(); - mutex_unlock(&slab_mutex); + /* 6) resize the head arrays to their final sizes */ + mutex_lock(&cache_chain_mutex); + list_for_each_entry(cachep, &cache_chain, next) + if (enable_cpucache(cachep, GFP_NOWAIT)) + BUG(); + mutex_unlock(&cache_chain_mutex); - /* Annotate slab for lockdep -- annotate the malloc caches */ - init_lock_keys(); + /* Annotate slab for lockdep -- annotate the malloc caches */ + init_lock_keys(); - /* Done! */ - slab_state = FULL; + /* Done! */ + g_cpucache_up = FULL; - /* - * Register a cpu startup notifier callback that initializes - * cpu_cache_get for all new cpus - */ - register_cpu_notifier(&cpucache_notifier); + /* + * Register a cpu startup notifier callback that initializes + * cpu_cache_get for all new cpus + */ + register_cpu_notifier(&cpucache_notifier); #ifdef CONFIG_NUMA /* @@ -1769,9 +1727,6 @@ static int __init cpucache_init(void) */ for_each_online_cpu(cpu) start_cpu_timer(cpu); - - /* Done! */ - slab_state = FULL; return 0; } __initcall(cpucache_init); @@ -1788,7 +1743,7 @@ slab_out_of_memory(struct kmem_cache *cachep, gfp_t gfpflags, int nodeid) "SLAB: Unable to allocate memory on node %d (gfp=0x%x)\n", nodeid, gfpflags); printk(KERN_WARNING " cache: %s, object size: %d, order: %d\n", - cachep->name, cachep->size, cachep->gfporder); + cachep->name, cachep->buffer_size, cachep->gfporder); for_each_online_node(node) { unsigned long active_objs = 0, num_objs = 0, free_objects = 0; @@ -1843,7 +1798,7 @@ static void *kmem_getpages(struct kmem_cache *cachep, gfp_t flags, int nodeid) flags |= __GFP_COMP; #endif - flags |= cachep->allocflags; + flags |= cachep->gfpflags; if (cachep->flags & SLAB_RECLAIM_ACCOUNT) flags |= __GFP_RECLAIMABLE; @@ -1854,10 +1809,6 @@ static void *kmem_getpages(struct kmem_cache *cachep, gfp_t flags, int nodeid) return NULL; } - /* Record if ALLOC_NO_WATERMARKS was set when allocating the slab */ - if (unlikely(page->pfmemalloc)) - pfmemalloc_active = true; - nr_pages = (1 << cachep->gfporder); if (cachep->flags & SLAB_RECLAIM_ACCOUNT) add_zone_page_state(page_zone(page), @@ -1865,13 +1816,9 @@ static void *kmem_getpages(struct kmem_cache *cachep, gfp_t flags, int nodeid) else add_zone_page_state(page_zone(page), NR_SLAB_UNRECLAIMABLE, nr_pages); - for (i = 0; i < nr_pages; i++) { + for (i = 0; i < nr_pages; i++) __SetPageSlab(page + i); - if (page->pfmemalloc) - SetPageSlabPfmemalloc(page + i); - } - if (kmemcheck_enabled && !(cachep->flags & SLAB_NOTRACK)) { kmemcheck_alloc_shadow(page, cachep->gfporder, flags, nodeid); @@ -1903,7 +1850,6 @@ static void kmem_freepages(struct kmem_cache *cachep, void *addr) NR_SLAB_UNRECLAIMABLE, nr_freed); while (i--) { BUG_ON(!PageSlab(page)); - __ClearPageSlabPfmemalloc(page); __ClearPageSlab(page); page++; } @@ -1928,7 +1874,7 @@ static void kmem_rcu_free(struct rcu_head *head) static void store_stackinfo(struct kmem_cache *cachep, unsigned long *addr, unsigned long caller) { - int size = cachep->object_size; + int size = obj_size(cachep); addr = (unsigned long *)&((char *)addr)[obj_offset(cachep)]; @@ -1960,7 +1906,7 @@ static void store_stackinfo(struct kmem_cache *cachep, unsigned long *addr, static void poison_obj(struct kmem_cache *cachep, void *addr, unsigned char val) { - int size = cachep->object_size; + int size = obj_size(cachep); addr = &((char *)addr)[obj_offset(cachep)]; memset(addr, val, size); @@ -2020,7 +1966,7 @@ static void print_objinfo(struct kmem_cache *cachep, void *objp, int lines) printk("\n"); } realobj = (char *)objp + obj_offset(cachep); - size = cachep->object_size; + size = obj_size(cachep); for (i = 0; i < size && lines; i += 16, lines--) { int limit; limit = 16; @@ -2037,7 +1983,7 @@ static void check_poison_obj(struct kmem_cache *cachep, void *objp) int lines = 0; realobj = (char *)objp + obj_offset(cachep); - size = cachep->object_size; + size = obj_size(cachep); for (i = 0; i < size; i++) { char exp = POISON_FREE; @@ -2101,10 +2047,10 @@ static void slab_destroy_debugcheck(struct kmem_cache *cachep, struct slab *slab if (cachep->flags & SLAB_POISON) { #ifdef CONFIG_DEBUG_PAGEALLOC - if (cachep->size % PAGE_SIZE == 0 && + if (cachep->buffer_size % PAGE_SIZE == 0 && OFF_SLAB(cachep)) kernel_map_pages(virt_to_page(objp), - cachep->size / PAGE_SIZE, 1); + cachep->buffer_size / PAGE_SIZE, 1); else check_poison_obj(cachep, objp); #else @@ -2155,6 +2101,27 @@ static void slab_destroy(struct kmem_cache *cachep, struct slab *slabp) } } +static void __kmem_cache_destroy(struct kmem_cache *cachep) +{ + int i; + struct kmem_list3 *l3; + + for_each_online_cpu(i) + kfree(cachep->array[i]); + + /* NUMA: free the list3 structures */ + for_each_online_node(i) { + l3 = cachep->nodelists[i]; + if (l3) { + kfree(l3->shared); + free_alien_cache(l3->alien); + kfree(l3); + } + } + kmem_cache_free(&cache_cache, cachep); +} + + /** * calculate_slab_order - calculate size (page order) of slabs * @cachep: pointer to the cache that is being created @@ -2227,20 +2194,12 @@ static size_t calculate_slab_order(struct kmem_cache *cachep, static int __init_refok setup_cpu_cache(struct kmem_cache *cachep, gfp_t gfp) { - if (slab_state >= FULL) + if (g_cpucache_up == FULL) return enable_cpucache(cachep, gfp); - if (slab_state == DOWN) { - /* - * Note: Creation of first cache (kmem_cache). - * The setup_list3s is taken care - * of by the caller of __kmem_cache_create - */ - cachep->array[smp_processor_id()] = &initarray_generic.cache; - slab_state = PARTIAL; - } else if (slab_state == PARTIAL) { + if (g_cpucache_up == NONE) { /* - * Note: the second kmem_cache_create must create the cache + * Note: the first kmem_cache_create must create the cache * that's used by kmalloc(24), otherwise the creation of * further caches will BUG(). */ @@ -2248,22 +2207,21 @@ static int __init_refok setup_cpu_cache(struct kmem_cache *cachep, gfp_t gfp) /* * If the cache that's used by kmalloc(sizeof(kmem_list3)) is - * the second cache, then we need to set up all its list3s, + * the first cache, then we need to set up all its list3s, * otherwise the creation of further caches will BUG(). */ set_up_list3s(cachep, SIZE_AC); if (INDEX_AC == INDEX_L3) - slab_state = PARTIAL_L3; + g_cpucache_up = PARTIAL_L3; else - slab_state = PARTIAL_ARRAYCACHE; + g_cpucache_up = PARTIAL_AC; } else { - /* Remaining boot caches */ cachep->array[smp_processor_id()] = kmalloc(sizeof(struct arraycache_init), gfp); - if (slab_state == PARTIAL_ARRAYCACHE) { + if (g_cpucache_up == PARTIAL_AC) { set_up_list3s(cachep, SIZE_L3); - slab_state = PARTIAL_L3; + g_cpucache_up = PARTIAL_L3; } else { int node; for_each_online_node(node) { @@ -2289,14 +2247,20 @@ static int __init_refok setup_cpu_cache(struct kmem_cache *cachep, gfp_t gfp) } /** - * __kmem_cache_create - Create a cache. - * @cachep: cache management descriptor + * kmem_cache_create - Create a cache. + * @name: A string which is used in /proc/slabinfo to identify this cache. + * @size: The size of objects to be created in this cache. + * @align: The required alignment for the objects. * @flags: SLAB flags + * @ctor: A constructor for the objects. * * Returns a ptr to the cache on success, NULL on failure. * Cannot be called within a int, but can be interrupted. * The @ctor is run when new pages are allocated by the cache. * + * @name must be valid until the cache is destroyed. This implies that + * the module calling this has to destroy the cache before getting unloaded. + * * The flags are * * %SLAB_POISON - Poison the slab with a known test pattern (a5a5a5a5) @@ -2309,15 +2273,60 @@ static int __init_refok setup_cpu_cache(struct kmem_cache *cachep, gfp_t gfp) * cacheline. This can be beneficial if you're counting cycles as closely * as davem. */ -int -__kmem_cache_create (struct kmem_cache *cachep, unsigned long flags) +struct kmem_cache * +kmem_cache_create (const char *name, size_t size, size_t align, + unsigned long flags, void (*ctor)(void *)) { size_t left_over, slab_size, ralign; + struct kmem_cache *cachep = NULL, *pc; gfp_t gfp; - int err; - size_t size = cachep->size; + + /* + * Sanity checks... these are all serious usage bugs. + */ + if (!name || in_interrupt() || (size < BYTES_PER_WORD) || + size > KMALLOC_MAX_SIZE) { + printk(KERN_ERR "%s: Early error in slab %s\n", __func__, + name); + BUG(); + } + + /* + * We use cache_chain_mutex to ensure a consistent view of + * cpu_online_mask as well. Please see cpuup_callback + */ + if (slab_is_available()) { + get_online_cpus(); + mutex_lock(&cache_chain_mutex); + } + + list_for_each_entry(pc, &cache_chain, next) { + char tmp; + int res; + + /* + * This happens when the module gets unloaded and doesn't + * destroy its slab cache and no-one else reuses the vmalloc + * area of the module. Print a warning. + */ + res = probe_kernel_address(pc->name, tmp); + if (res) { + printk(KERN_ERR + "SLAB: cache with size %d has lost its name\n", + pc->buffer_size); + continue; + } + + if (!strcmp(pc->name, name)) { + printk(KERN_ERR + "kmem_cache_create: duplicate cache %s\n", name); + dump_stack(); + goto oops; + } + } #if DEBUG + WARN_ON(strchr(name, ' ')); /* It confuses parsers */ #if FORCED_DEBUG /* * Enable redzoning and last user accounting, except for caches with @@ -2334,6 +2343,11 @@ __kmem_cache_create (struct kmem_cache *cachep, unsigned long flags) if (flags & SLAB_DESTROY_BY_RCU) BUG_ON(flags & SLAB_POISON); #endif + /* + * Always checks flags, a caller might be expecting debug support which + * isn't available. + */ + BUG_ON(flags & ~CREATE_MASK); /* * Check that size is in terms of words. This is needed to avoid @@ -2345,6 +2359,22 @@ __kmem_cache_create (struct kmem_cache *cachep, unsigned long flags) size &= ~(BYTES_PER_WORD - 1); } + /* calculate the final buffer alignment: */ + + /* 1) arch recommendation: can be overridden for debug */ + if (flags & SLAB_HWCACHE_ALIGN) { + /* + * Default alignment: as specified by the arch code. Except if + * an object is really small, then squeeze multiple objects into + * one cacheline. + */ + ralign = cache_line_size(); + while (size <= ralign / 2) + ralign /= 2; + } else { + ralign = BYTES_PER_WORD; + } + /* * Redzoning and user store require word alignment or possibly larger. * Note this will be overridden by architecture or caller mandated @@ -2361,9 +2391,13 @@ __kmem_cache_create (struct kmem_cache *cachep, unsigned long flags) size &= ~(REDZONE_ALIGN - 1); } + /* 2) arch mandated alignment */ + if (ralign < ARCH_SLAB_MINALIGN) { + ralign = ARCH_SLAB_MINALIGN; + } /* 3) caller mandated alignment */ - if (ralign < cachep->align) { - ralign = cachep->align; + if (ralign < align) { + ralign = align; } /* disable debug if necessary */ if (ralign > __alignof__(unsigned long long)) @@ -2371,15 +2405,21 @@ __kmem_cache_create (struct kmem_cache *cachep, unsigned long flags) /* * 4) Store it. */ - cachep->align = ralign; + align = ralign; if (slab_is_available()) gfp = GFP_KERNEL; else gfp = GFP_NOWAIT; - setup_nodelists_pointer(cachep); + /* Get cache's description obj. */ + cachep = kmem_cache_zalloc(&cache_cache, gfp); + if (!cachep) + goto oops; + + cachep->nodelists = (struct kmem_list3 **)&cachep->array[nr_cpu_ids]; #if DEBUG + cachep->obj_size = size; /* * Both debugging options require word-alignment which is calculated @@ -2402,9 +2442,8 @@ __kmem_cache_create (struct kmem_cache *cachep, unsigned long flags) } #if FORCED_DEBUG && defined(CONFIG_DEBUG_PAGEALLOC) if (size >= malloc_sizes[INDEX_L3 + 1].cs_size - && cachep->object_size > cache_line_size() - && ALIGN(size, cachep->align) < PAGE_SIZE) { - cachep->obj_offset += PAGE_SIZE - ALIGN(size, cachep->align); + && cachep->obj_size > cache_line_size() && ALIGN(size, align) < PAGE_SIZE) { + cachep->obj_offset += PAGE_SIZE - ALIGN(size, align); size = PAGE_SIZE; } #endif @@ -2424,15 +2463,19 @@ __kmem_cache_create (struct kmem_cache *cachep, unsigned long flags) */ flags |= CFLGS_OFF_SLAB; - size = ALIGN(size, cachep->align); - - left_over = calculate_slab_order(cachep, size, cachep->align, flags); + size = ALIGN(size, align); - if (!cachep->num) - return -E2BIG; + left_over = calculate_slab_order(cachep, size, align, flags); + if (!cachep->num) { + printk(KERN_ERR + "kmem_cache_create: couldn't create cache %s.\n", name); + kmem_cache_free(&cache_cache, cachep); + cachep = NULL; + goto oops; + } slab_size = ALIGN(cachep->num * sizeof(kmem_bufctl_t) - + sizeof(struct slab), cachep->align); + + sizeof(struct slab), align); /* * If the slab has been placed off-slab, and we have enough space then @@ -2460,15 +2503,15 @@ __kmem_cache_create (struct kmem_cache *cachep, unsigned long flags) cachep->colour_off = cache_line_size(); /* Offset must be a multiple of the alignment. */ - if (cachep->colour_off < cachep->align) - cachep->colour_off = cachep->align; + if (cachep->colour_off < align) + cachep->colour_off = align; cachep->colour = left_over / cachep->colour_off; cachep->slab_size = slab_size; cachep->flags = flags; - cachep->allocflags = 0; + cachep->gfpflags = 0; if (CONFIG_ZONE_DMA_FLAG && (flags & SLAB_CACHE_DMA)) - cachep->allocflags |= GFP_DMA; - cachep->size = size; + cachep->gfpflags |= GFP_DMA; + cachep->buffer_size = size; cachep->reciprocal_buffer_size = reciprocal_value(size); if (flags & CFLGS_OFF_SLAB) { @@ -2482,11 +2525,13 @@ __kmem_cache_create (struct kmem_cache *cachep, unsigned long flags) */ BUG_ON(ZERO_OR_NULL_PTR(cachep->slabp_cache)); } + cachep->ctor = ctor; + cachep->name = name; - err = setup_cpu_cache(cachep, gfp); - if (err) { - __kmem_cache_shutdown(cachep); - return err; + if (setup_cpu_cache(cachep, gfp)) { + __kmem_cache_destroy(cachep); + cachep = NULL; + goto oops; } if (flags & SLAB_DEBUG_OBJECTS) { @@ -2497,11 +2542,21 @@ __kmem_cache_create (struct kmem_cache *cachep, unsigned long flags) WARN_ON_ONCE(flags & SLAB_DESTROY_BY_RCU); slab_set_debugobj_lock_classes(cachep); - } else if (!OFF_SLAB(cachep) && !(flags & SLAB_DESTROY_BY_RCU)) - on_slab_lock_classes(cachep); + } - return 0; + /* cache setup completed, link it into the list */ + list_add(&cachep->next, &cache_chain); +oops: + if (!cachep && (flags & SLAB_PANIC)) + panic("kmem_cache_create(): failed to create slab `%s'\n", + name); + if (slab_is_available()) { + mutex_unlock(&cache_chain_mutex); + put_online_cpus(); + } + return cachep; } +EXPORT_SYMBOL(kmem_cache_create); #if DEBUG static void check_irq_off(void) @@ -2616,7 +2671,7 @@ static int drain_freelist(struct kmem_cache *cache, return nr_freed; } -/* Called with slab_mutex held to protect against cpu hotplug */ +/* Called with cache_chain_mutex held to protect against cpu hotplug */ static int __cache_shrink(struct kmem_cache *cachep) { int ret = 0, i = 0; @@ -2651,37 +2706,57 @@ int kmem_cache_shrink(struct kmem_cache *cachep) BUG_ON(!cachep || in_interrupt()); get_online_cpus(); - mutex_lock(&slab_mutex); + mutex_lock(&cache_chain_mutex); ret = __cache_shrink(cachep); - mutex_unlock(&slab_mutex); + mutex_unlock(&cache_chain_mutex); put_online_cpus(); return ret; } EXPORT_SYMBOL(kmem_cache_shrink); -int __kmem_cache_shutdown(struct kmem_cache *cachep) +/** + * kmem_cache_destroy - delete a cache + * @cachep: the cache to destroy + * + * Remove a &struct kmem_cache object from the slab cache. + * + * It is expected this function will be called by a module when it is + * unloaded. This will remove the cache completely, and avoid a duplicate + * cache being allocated each time a module is loaded and unloaded, if the + * module doesn't have persistent in-kernel storage across loads and unloads. + * + * The cache must be empty before calling this function. + * + * The caller must guarantee that no one will allocate memory from the cache + * during the kmem_cache_destroy(). + */ +void kmem_cache_destroy(struct kmem_cache *cachep) { - int i; - struct kmem_list3 *l3; - int rc = __cache_shrink(cachep); + BUG_ON(!cachep || in_interrupt()); - if (rc) - return rc; + /* Find the cache in the chain of caches. */ + get_online_cpus(); + mutex_lock(&cache_chain_mutex); + /* + * the chain is never empty, cache_cache is never destroyed + */ + list_del(&cachep->next); + if (__cache_shrink(cachep)) { + slab_error(cachep, "Can't free all objects"); + list_add(&cachep->next, &cache_chain); + mutex_unlock(&cache_chain_mutex); + put_online_cpus(); + return; + } - for_each_online_cpu(i) - kfree(cachep->array[i]); + if (unlikely(cachep->flags & SLAB_DESTROY_BY_RCU)) + rcu_barrier(); - /* NUMA: free the list3 structures */ - for_each_online_node(i) { - l3 = cachep->nodelists[i]; - if (l3) { - kfree(l3->shared); - free_alien_cache(l3->alien); - kfree(l3); - } - } - return 0; + __kmem_cache_destroy(cachep); + mutex_unlock(&cache_chain_mutex); + put_online_cpus(); } +EXPORT_SYMBOL(kmem_cache_destroy); /* * Get the memory for a slab management obj. @@ -2765,10 +2840,10 @@ static void cache_init_objs(struct kmem_cache *cachep, slab_error(cachep, "constructor overwrote the" " start of an object"); } - if ((cachep->size % PAGE_SIZE) == 0 && + if ((cachep->buffer_size % PAGE_SIZE) == 0 && OFF_SLAB(cachep) && cachep->flags & SLAB_POISON) kernel_map_pages(virt_to_page(objp), - cachep->size / PAGE_SIZE, 0); + cachep->buffer_size / PAGE_SIZE, 0); #else if (cachep->ctor) cachep->ctor(objp); @@ -2782,9 +2857,9 @@ static void kmem_flagcheck(struct kmem_cache *cachep, gfp_t flags) { if (CONFIG_ZONE_DMA_FLAG) { if (flags & GFP_DMA) - BUG_ON(!(cachep->allocflags & GFP_DMA)); + BUG_ON(!(cachep->gfpflags & GFP_DMA)); else - BUG_ON(cachep->allocflags & GFP_DMA); + BUG_ON(cachep->gfpflags & GFP_DMA); } } @@ -2843,8 +2918,8 @@ static void slab_map_pages(struct kmem_cache *cache, struct slab *slab, nr_pages <<= cache->gfporder; do { - page->slab_cache = cache; - page->slab_page = slab; + page_set_cache(page, cache); + page_set_slab(page, slab); page++; } while (--nr_pages); } @@ -2970,7 +3045,7 @@ static inline void verify_redzone_free(struct kmem_cache *cache, void *obj) } static void *cache_free_debugcheck(struct kmem_cache *cachep, void *objp, - unsigned long caller) + void *caller) { struct page *page; unsigned int objnr; @@ -2982,7 +3057,7 @@ static void *cache_free_debugcheck(struct kmem_cache *cachep, void *objp, kfree_debugcheck(objp); page = virt_to_head_page(objp); - slabp = page->slab_page; + slabp = page_get_slab(page); if (cachep->flags & SLAB_RED_ZONE) { verify_redzone_free(cachep, objp); @@ -2990,7 +3065,7 @@ static void *cache_free_debugcheck(struct kmem_cache *cachep, void *objp, *dbg_redzone2(cachep, objp) = RED_INACTIVE; } if (cachep->flags & SLAB_STORE_USER) - *dbg_userword(cachep, objp) = (void *)caller; + *dbg_userword(cachep, objp) = caller; objnr = obj_to_index(cachep, slabp, objp); @@ -3002,10 +3077,10 @@ static void *cache_free_debugcheck(struct kmem_cache *cachep, void *objp, #endif if (cachep->flags & SLAB_POISON) { #ifdef CONFIG_DEBUG_PAGEALLOC - if ((cachep->size % PAGE_SIZE)==0 && OFF_SLAB(cachep)) { - store_stackinfo(cachep, objp, caller); + if ((cachep->buffer_size % PAGE_SIZE)==0 && OFF_SLAB(cachep)) { + store_stackinfo(cachep, objp, (unsigned long)caller); kernel_map_pages(virt_to_page(objp), - cachep->size / PAGE_SIZE, 0); + cachep->buffer_size / PAGE_SIZE, 0); } else { poison_obj(cachep, objp, POISON_FREE); } @@ -3045,19 +3120,16 @@ static void check_slabp(struct kmem_cache *cachep, struct slab *slabp) #define check_slabp(x,y) do { } while(0) #endif -static void *cache_alloc_refill(struct kmem_cache *cachep, gfp_t flags, - bool force_refill) +static void *cache_alloc_refill(struct kmem_cache *cachep, gfp_t flags) { int batchcount; struct kmem_list3 *l3; struct array_cache *ac; int node; +retry: check_irq_off(); node = numa_mem_id(); - if (unlikely(force_refill)) - goto force_grow; -retry: ac = cpu_cache_get(cachep); batchcount = ac->batchcount; if (!ac->touched && batchcount > BATCHREFILL_LIMIT) { @@ -3107,8 +3179,8 @@ static void *cache_alloc_refill(struct kmem_cache *cachep, gfp_t flags, STATS_INC_ACTIVE(cachep); STATS_SET_HIGH(cachep); - ac_put_obj(cachep, ac, slab_get_obj(cachep, slabp, - node)); + ac->entry[ac->avail++] = slab_get_obj(cachep, slabp, + node); } check_slabp(cachep, slabp); @@ -3127,23 +3199,18 @@ static void *cache_alloc_refill(struct kmem_cache *cachep, gfp_t flags, if (unlikely(!ac->avail)) { int x; -force_grow: x = cache_grow(cachep, flags | GFP_THISNODE, node, NULL); /* cache_grow can reenable interrupts, then ac could change. */ ac = cpu_cache_get(cachep); - node = numa_mem_id(); - - /* no objects in sight? abort */ - if (!x && (ac->avail == 0 || force_refill)) + if (!x && ac->avail == 0) /* no objects in sight? abort */ return NULL; if (!ac->avail) /* objects refilled by interrupt? */ goto retry; } ac->touched = 1; - - return ac_get_obj(cachep, ac, flags, force_refill); + return ac->entry[--ac->avail]; } static inline void cache_alloc_debugcheck_before(struct kmem_cache *cachep, @@ -3157,15 +3224,15 @@ static inline void cache_alloc_debugcheck_before(struct kmem_cache *cachep, #if DEBUG static void *cache_alloc_debugcheck_after(struct kmem_cache *cachep, - gfp_t flags, void *objp, unsigned long caller) + gfp_t flags, void *objp, void *caller) { if (!objp) return objp; if (cachep->flags & SLAB_POISON) { #ifdef CONFIG_DEBUG_PAGEALLOC - if ((cachep->size % PAGE_SIZE) == 0 && OFF_SLAB(cachep)) + if ((cachep->buffer_size % PAGE_SIZE) == 0 && OFF_SLAB(cachep)) kernel_map_pages(virt_to_page(objp), - cachep->size / PAGE_SIZE, 1); + cachep->buffer_size / PAGE_SIZE, 1); else check_poison_obj(cachep, objp); #else @@ -3174,7 +3241,7 @@ static void *cache_alloc_debugcheck_after(struct kmem_cache *cachep, poison_obj(cachep, objp, POISON_INUSE); } if (cachep->flags & SLAB_STORE_USER) - *dbg_userword(cachep, objp) = (void *)caller; + *dbg_userword(cachep, objp) = caller; if (cachep->flags & SLAB_RED_ZONE) { if (*dbg_redzone1(cachep, objp) != RED_INACTIVE || @@ -3194,8 +3261,8 @@ static void *cache_alloc_debugcheck_after(struct kmem_cache *cachep, struct slab *slabp; unsigned objnr; - slabp = virt_to_head_page(objp)->slab_page; - objnr = (unsigned)(objp - slabp->s_mem) / cachep->size; + slabp = page_get_slab(virt_to_head_page(objp)); + objnr = (unsigned)(objp - slabp->s_mem) / cachep->buffer_size; slab_bufctl(slabp)[objnr] = BUFCTL_ACTIVE; } #endif @@ -3215,45 +3282,33 @@ static void *cache_alloc_debugcheck_after(struct kmem_cache *cachep, static bool slab_should_failslab(struct kmem_cache *cachep, gfp_t flags) { - if (cachep == kmem_cache) + if (cachep == &cache_cache) return false; - return should_failslab(cachep->object_size, flags, cachep->flags); + return should_failslab(obj_size(cachep), flags, cachep->flags); } static inline void *____cache_alloc(struct kmem_cache *cachep, gfp_t flags) { void *objp; struct array_cache *ac; - bool force_refill = false; check_irq_off(); ac = cpu_cache_get(cachep); if (likely(ac->avail)) { + STATS_INC_ALLOCHIT(cachep); ac->touched = 1; - objp = ac_get_obj(cachep, ac, flags, false); - + objp = ac->entry[--ac->avail]; + } else { + STATS_INC_ALLOCMISS(cachep); + objp = cache_alloc_refill(cachep, flags); /* - * Allow for the possibility all avail objects are not allowed - * by the current flags + * the 'ac' may be updated by cache_alloc_refill(), + * and kmemleak_erase() requires its correct value. */ - if (objp) { - STATS_INC_ALLOCHIT(cachep); - goto out; - } - force_refill = true; + ac = cpu_cache_get(cachep); } - - STATS_INC_ALLOCMISS(cachep); - objp = cache_alloc_refill(cachep, flags, force_refill); - /* - * the 'ac' may be updated by cache_alloc_refill(), - * and kmemleak_erase() requires its correct value. - */ - ac = cpu_cache_get(cachep); - -out: /* * To avoid a false negative, if an object that is in one of the * per-CPU caches is leaked, we need to make sure kmemleak doesn't @@ -3281,7 +3336,7 @@ static void *alternate_node_alloc(struct kmem_cache *cachep, gfp_t flags) if (cpuset_do_slab_mem_spread() && (cachep->flags & SLAB_MEM_SPREAD)) nid_alloc = cpuset_slab_spread_node(); else if (current->mempolicy) - nid_alloc = slab_node(); + nid_alloc = slab_node(current->mempolicy); if (nid_alloc != nid_here) return ____cache_alloc_node(cachep, flags, nid_alloc); return NULL; @@ -3313,7 +3368,7 @@ static void *fallback_alloc(struct kmem_cache *cache, gfp_t flags) retry_cpuset: cpuset_mems_cookie = get_mems_allowed(); - zonelist = node_zonelist(slab_node(), flags); + zonelist = node_zonelist(slab_node(current->mempolicy), flags); retry: /* @@ -3448,8 +3503,8 @@ static void *____cache_alloc_node(struct kmem_cache *cachep, gfp_t flags, * Fallback to other node is possible if __GFP_THISNODE is not set. */ static __always_inline void * -slab_alloc_node(struct kmem_cache *cachep, gfp_t flags, int nodeid, - unsigned long caller) +__cache_alloc_node(struct kmem_cache *cachep, gfp_t flags, int nodeid, + void *caller) { unsigned long save_flags; void *ptr; @@ -3490,14 +3545,14 @@ slab_alloc_node(struct kmem_cache *cachep, gfp_t flags, int nodeid, out: local_irq_restore(save_flags); ptr = cache_alloc_debugcheck_after(cachep, flags, ptr, caller); - kmemleak_alloc_recursive(ptr, cachep->object_size, 1, cachep->flags, + kmemleak_alloc_recursive(ptr, obj_size(cachep), 1, cachep->flags, flags); if (likely(ptr)) - kmemcheck_slab_alloc(cachep, flags, ptr, cachep->object_size); + kmemcheck_slab_alloc(cachep, flags, ptr, obj_size(cachep)); if (unlikely((flags & __GFP_ZERO) && ptr)) - memset(ptr, 0, cachep->object_size); + memset(ptr, 0, obj_size(cachep)); return ptr; } @@ -3535,7 +3590,7 @@ __do_cache_alloc(struct kmem_cache *cachep, gfp_t flags) #endif /* CONFIG_NUMA */ static __always_inline void * -slab_alloc(struct kmem_cache *cachep, gfp_t flags, unsigned long caller) +__cache_alloc(struct kmem_cache *cachep, gfp_t flags, void *caller) { unsigned long save_flags; void *objp; @@ -3552,15 +3607,15 @@ slab_alloc(struct kmem_cache *cachep, gfp_t flags, unsigned long caller) objp = __do_cache_alloc(cachep, flags); local_irq_restore(save_flags); objp = cache_alloc_debugcheck_after(cachep, flags, objp, caller); - kmemleak_alloc_recursive(objp, cachep->object_size, 1, cachep->flags, + kmemleak_alloc_recursive(objp, obj_size(cachep), 1, cachep->flags, flags); prefetchw(objp); if (likely(objp)) - kmemcheck_slab_alloc(cachep, flags, objp, cachep->object_size); + kmemcheck_slab_alloc(cachep, flags, objp, obj_size(cachep)); if (unlikely((flags & __GFP_ZERO) && objp)) - memset(objp, 0, cachep->object_size); + memset(objp, 0, obj_size(cachep)); return objp; } @@ -3575,12 +3630,9 @@ static void free_block(struct kmem_cache *cachep, void **objpp, int nr_objects, struct kmem_list3 *l3; for (i = 0; i < nr_objects; i++) { - void *objp; + void *objp = objpp[i]; struct slab *slabp; - clear_obj_pfmemalloc(&objpp[i]); - objp = objpp[i]; - slabp = virt_to_slab(objp); l3 = cachep->nodelists[node]; list_del(&slabp->list); @@ -3671,7 +3723,7 @@ static void cache_flusharray(struct kmem_cache *cachep, struct array_cache *ac) * be in this state _before_ it is released. Called with disabled ints. */ static inline void __cache_free(struct kmem_cache *cachep, void *objp, - unsigned long caller) + void *caller) { struct array_cache *ac = cpu_cache_get(cachep); @@ -3679,7 +3731,7 @@ static inline void __cache_free(struct kmem_cache *cachep, void *objp, kmemleak_free_recursive(objp, cachep->flags); objp = cache_free_debugcheck(cachep, objp, caller); - kmemcheck_slab_free(cachep, objp, cachep->object_size); + kmemcheck_slab_free(cachep, objp, obj_size(cachep)); /* * Skip calling cache_free_alien() when the platform is not numa. @@ -3698,7 +3750,7 @@ static inline void __cache_free(struct kmem_cache *cachep, void *objp, cache_flusharray(cachep, ac); } - ac_put_obj(cachep, ac, objp); + ac->entry[ac->avail++] = objp; } /** @@ -3711,10 +3763,10 @@ static inline void __cache_free(struct kmem_cache *cachep, void *objp, */ void *kmem_cache_alloc(struct kmem_cache *cachep, gfp_t flags) { - void *ret = slab_alloc(cachep, flags, _RET_IP_); + void *ret = __cache_alloc(cachep, flags, __builtin_return_address(0)); trace_kmem_cache_alloc(_RET_IP_, ret, - cachep->object_size, cachep->size, flags); + obj_size(cachep), cachep->buffer_size, flags); return ret; } @@ -3722,14 +3774,14 @@ EXPORT_SYMBOL(kmem_cache_alloc); #ifdef CONFIG_TRACING void * -kmem_cache_alloc_trace(struct kmem_cache *cachep, gfp_t flags, size_t size) +kmem_cache_alloc_trace(size_t size, struct kmem_cache *cachep, gfp_t flags) { void *ret; - ret = slab_alloc(cachep, flags, _RET_IP_); + ret = __cache_alloc(cachep, flags, __builtin_return_address(0)); trace_kmalloc(_RET_IP_, ret, - size, cachep->size, flags); + size, slab_buffer_size(cachep), flags); return ret; } EXPORT_SYMBOL(kmem_cache_alloc_trace); @@ -3738,10 +3790,11 @@ EXPORT_SYMBOL(kmem_cache_alloc_trace); #ifdef CONFIG_NUMA void *kmem_cache_alloc_node(struct kmem_cache *cachep, gfp_t flags, int nodeid) { - void *ret = slab_alloc_node(cachep, flags, nodeid, _RET_IP_); + void *ret = __cache_alloc_node(cachep, flags, nodeid, + __builtin_return_address(0)); trace_kmem_cache_alloc_node(_RET_IP_, ret, - cachep->object_size, cachep->size, + obj_size(cachep), cachep->buffer_size, flags, nodeid); return ret; @@ -3749,17 +3802,17 @@ void *kmem_cache_alloc_node(struct kmem_cache *cachep, gfp_t flags, int nodeid) EXPORT_SYMBOL(kmem_cache_alloc_node); #ifdef CONFIG_TRACING -void *kmem_cache_alloc_node_trace(struct kmem_cache *cachep, +void *kmem_cache_alloc_node_trace(size_t size, + struct kmem_cache *cachep, gfp_t flags, - int nodeid, - size_t size) + int nodeid) { void *ret; - ret = slab_alloc_node(cachep, flags, nodeid, _RET_IP_); - + ret = __cache_alloc_node(cachep, flags, nodeid, + __builtin_return_address(0)); trace_kmalloc_node(_RET_IP_, ret, - size, cachep->size, + size, slab_buffer_size(cachep), flags, nodeid); return ret; } @@ -3767,33 +3820,34 @@ EXPORT_SYMBOL(kmem_cache_alloc_node_trace); #endif static __always_inline void * -__do_kmalloc_node(size_t size, gfp_t flags, int node, unsigned long caller) +__do_kmalloc_node(size_t size, gfp_t flags, int node, void *caller) { struct kmem_cache *cachep; cachep = kmem_find_general_cachep(size, flags); if (unlikely(ZERO_OR_NULL_PTR(cachep))) return cachep; - return kmem_cache_alloc_node_trace(cachep, flags, node, size); + return kmem_cache_alloc_node_trace(size, cachep, flags, node); } #if defined(CONFIG_DEBUG_SLAB) || defined(CONFIG_TRACING) void *__kmalloc_node(size_t size, gfp_t flags, int node) { - return __do_kmalloc_node(size, flags, node, _RET_IP_); + return __do_kmalloc_node(size, flags, node, + __builtin_return_address(0)); } EXPORT_SYMBOL(__kmalloc_node); void *__kmalloc_node_track_caller(size_t size, gfp_t flags, int node, unsigned long caller) { - return __do_kmalloc_node(size, flags, node, caller); + return __do_kmalloc_node(size, flags, node, (void *)caller); } EXPORT_SYMBOL(__kmalloc_node_track_caller); #else void *__kmalloc_node(size_t size, gfp_t flags, int node) { - return __do_kmalloc_node(size, flags, node, 0); + return __do_kmalloc_node(size, flags, node, NULL); } EXPORT_SYMBOL(__kmalloc_node); #endif /* CONFIG_DEBUG_SLAB || CONFIG_TRACING */ @@ -3806,7 +3860,7 @@ EXPORT_SYMBOL(__kmalloc_node); * @caller: function caller for debug tracking of the caller */ static __always_inline void *__do_kmalloc(size_t size, gfp_t flags, - unsigned long caller) + void *caller) { struct kmem_cache *cachep; void *ret; @@ -3819,10 +3873,10 @@ static __always_inline void *__do_kmalloc(size_t size, gfp_t flags, cachep = __find_general_cachep(size, flags); if (unlikely(ZERO_OR_NULL_PTR(cachep))) return cachep; - ret = slab_alloc(cachep, flags, caller); + ret = __cache_alloc(cachep, flags, caller); - trace_kmalloc(caller, ret, - size, cachep->size, flags); + trace_kmalloc((unsigned long) caller, ret, + size, cachep->buffer_size, flags); return ret; } @@ -3831,20 +3885,20 @@ static __always_inline void *__do_kmalloc(size_t size, gfp_t flags, #if defined(CONFIG_DEBUG_SLAB) || defined(CONFIG_TRACING) void *__kmalloc(size_t size, gfp_t flags) { - return __do_kmalloc(size, flags, _RET_IP_); + return __do_kmalloc(size, flags, __builtin_return_address(0)); } EXPORT_SYMBOL(__kmalloc); void *__kmalloc_track_caller(size_t size, gfp_t flags, unsigned long caller) { - return __do_kmalloc(size, flags, caller); + return __do_kmalloc(size, flags, (void *)caller); } EXPORT_SYMBOL(__kmalloc_track_caller); #else void *__kmalloc(size_t size, gfp_t flags) { - return __do_kmalloc(size, flags, 0); + return __do_kmalloc(size, flags, NULL); } EXPORT_SYMBOL(__kmalloc); #endif @@ -3860,15 +3914,12 @@ EXPORT_SYMBOL(__kmalloc); void kmem_cache_free(struct kmem_cache *cachep, void *objp) { unsigned long flags; - cachep = cache_from_obj(cachep, objp); - if (!cachep) - return; local_irq_save(flags); - debug_check_no_locks_freed(objp, cachep->object_size); + debug_check_no_locks_freed(objp, obj_size(cachep)); if (!(cachep->flags & SLAB_DEBUG_OBJECTS)) - debug_check_no_obj_freed(objp, cachep->object_size); - __cache_free(cachep, objp, _RET_IP_); + debug_check_no_obj_freed(objp, obj_size(cachep)); + __cache_free(cachep, objp, __builtin_return_address(0)); local_irq_restore(flags); trace_kmem_cache_free(_RET_IP_, objp); @@ -3896,14 +3947,19 @@ void kfree(const void *objp) local_irq_save(flags); kfree_debugcheck(objp); c = virt_to_cache(objp); - debug_check_no_locks_freed(objp, c->object_size); - - debug_check_no_obj_freed(objp, c->object_size); - __cache_free(c, (void *)objp, _RET_IP_); + debug_check_no_locks_freed(objp, obj_size(c)); + debug_check_no_obj_freed(objp, obj_size(c)); + __cache_free(c, (void *)objp, __builtin_return_address(0)); local_irq_restore(flags); } EXPORT_SYMBOL(kfree); +unsigned int kmem_cache_size(struct kmem_cache *cachep) +{ + return obj_size(cachep); +} +EXPORT_SYMBOL(kmem_cache_size); + /* * This initializes kmem_list3 or resizes various caches for all nodes. */ @@ -3974,7 +4030,7 @@ static int alloc_kmemlist(struct kmem_cache *cachep, gfp_t gfp) return 0; fail: - if (!cachep->list.next) { + if (!cachep->next.next) { /* Cache is not active yet. Roll back what we did */ node--; while (node >= 0) { @@ -4009,7 +4065,7 @@ static void do_ccupdate_local(void *info) new->new[smp_processor_id()] = old; } -/* Always called with the slab_mutex held */ +/* Always called with the cache_chain_mutex held */ static int do_tune_cpucache(struct kmem_cache *cachep, int limit, int batchcount, int shared, gfp_t gfp) { @@ -4053,7 +4109,7 @@ static int do_tune_cpucache(struct kmem_cache *cachep, int limit, return alloc_kmemlist(cachep, gfp); } -/* Called with slab_mutex held always */ +/* Called with cache_chain_mutex held always */ static int enable_cpucache(struct kmem_cache *cachep, gfp_t gfp) { int err; @@ -4068,13 +4124,13 @@ static int enable_cpucache(struct kmem_cache *cachep, gfp_t gfp) * The numbers are guessed, we should auto-tune as described by * Bonwick. */ - if (cachep->size > 131072) + if (cachep->buffer_size > 131072) limit = 1; - else if (cachep->size > PAGE_SIZE) + else if (cachep->buffer_size > PAGE_SIZE) limit = 8; - else if (cachep->size > 1024) + else if (cachep->buffer_size > 1024) limit = 24; - else if (cachep->size > 256) + else if (cachep->buffer_size > 256) limit = 54; else limit = 120; @@ -4089,7 +4145,7 @@ static int enable_cpucache(struct kmem_cache *cachep, gfp_t gfp) * to a larger limit. Thus disabled by default. */ shared = 0; - if (cachep->size <= PAGE_SIZE && num_possible_cpus() > 1) + if (cachep->buffer_size <= PAGE_SIZE && num_possible_cpus() > 1) shared = 8; #if DEBUG @@ -4155,11 +4211,11 @@ static void cache_reap(struct work_struct *w) int node = numa_mem_id(); struct delayed_work *work = to_delayed_work(w); - if (!mutex_trylock(&slab_mutex)) + if (!mutex_trylock(&cache_chain_mutex)) /* Give up. Setup the next iteration. */ goto out; - list_for_each_entry(searchp, &slab_caches, list) { + list_for_each_entry(searchp, &cache_chain, next) { check_irq_on(); /* @@ -4197,7 +4253,7 @@ static void cache_reap(struct work_struct *w) cond_resched(); } check_irq_on(); - mutex_unlock(&slab_mutex); + mutex_unlock(&cache_chain_mutex); next_reap_node(); out: /* Set up the next iteration */ @@ -4205,8 +4261,54 @@ static void cache_reap(struct work_struct *w) } #ifdef CONFIG_SLABINFO -void get_slabinfo(struct kmem_cache *cachep, struct slabinfo *sinfo) + +static void print_slabinfo_header(struct seq_file *m) { + /* + * Output format version, so at least we can change it + * without _too_ many complaints. + */ +#if STATS + seq_puts(m, "slabinfo - version: 2.1 (statistics)\n"); +#else + seq_puts(m, "slabinfo - version: 2.1\n"); +#endif + seq_puts(m, "# name " + " "); + seq_puts(m, " : tunables "); + seq_puts(m, " : slabdata "); +#if STATS + seq_puts(m, " : globalstat " + " "); + seq_puts(m, " : cpustat "); +#endif + seq_putc(m, '\n'); +} + +static void *s_start(struct seq_file *m, loff_t *pos) +{ + loff_t n = *pos; + + mutex_lock(&cache_chain_mutex); + if (!n) + print_slabinfo_header(m); + + return seq_list_start(&cache_chain, *pos); +} + +static void *s_next(struct seq_file *m, void *p, loff_t *pos) +{ + return seq_list_next(p, &cache_chain, pos); +} + +static void s_stop(struct seq_file *m, void *p) +{ + mutex_unlock(&cache_chain_mutex); +} + +static int s_show(struct seq_file *m, void *p) +{ + struct kmem_cache *cachep = list_entry(p, struct kmem_cache, next); struct slab *slabp; unsigned long active_objs; unsigned long num_objs; @@ -4261,20 +4363,13 @@ void get_slabinfo(struct kmem_cache *cachep, struct slabinfo *sinfo) if (error) printk(KERN_ERR "slab: cache %s error: %s\n", name, error); - sinfo->active_objs = active_objs; - sinfo->num_objs = num_objs; - sinfo->active_slabs = active_slabs; - sinfo->num_slabs = num_slabs; - sinfo->shared_avail = shared_avail; - sinfo->limit = cachep->limit; - sinfo->batchcount = cachep->batchcount; - sinfo->shared = cachep->shared; - sinfo->objects_per_slab = cachep->num; - sinfo->cache_order = cachep->gfporder; -} - -void slabinfo_show_stats(struct seq_file *m, struct kmem_cache *cachep) -{ + seq_printf(m, "%-17s %6lu %6lu %6u %4u %4d", + name, active_objs, num_objs, cachep->buffer_size, + cachep->num, (1 << cachep->gfporder)); + seq_printf(m, " : tunables %4u %4u %4u", + cachep->limit, cachep->batchcount, cachep->shared); + seq_printf(m, " : slabdata %6lu %6lu %6lu", + active_slabs, num_slabs, shared_avail); #if STATS { /* list3 stats */ unsigned long high = cachep->high_mark; @@ -4304,8 +4399,31 @@ void slabinfo_show_stats(struct seq_file *m, struct kmem_cache *cachep) allochit, allocmiss, freehit, freemiss); } #endif + seq_putc(m, '\n'); + return 0; } +/* + * slabinfo_op - iterator that generates /proc/slabinfo + * + * Output layout: + * cache-name + * num-active-objs + * total-objs + * object size + * num-active-slabs + * total-slabs + * num-pages-per-slab + * + further values on SMP and with statistics enabled + */ + +static const struct seq_operations slabinfo_op = { + .start = s_start, + .next = s_next, + .stop = s_stop, + .show = s_show, +}; + #define MAX_SLABINFO_WRITE 128 /** * slabinfo_write - Tuning for the slab allocator @@ -4314,7 +4432,7 @@ void slabinfo_show_stats(struct seq_file *m, struct kmem_cache *cachep) * @count: data length * @ppos: unused */ -ssize_t slabinfo_write(struct file *file, const char __user *buffer, +static ssize_t slabinfo_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) { char kbuf[MAX_SLABINFO_WRITE + 1], *tmp; @@ -4336,9 +4454,9 @@ ssize_t slabinfo_write(struct file *file, const char __user *buffer, return -EINVAL; /* Find the cache in the chain of caches. */ - mutex_lock(&slab_mutex); + mutex_lock(&cache_chain_mutex); res = -EINVAL; - list_for_each_entry(cachep, &slab_caches, list) { + list_for_each_entry(cachep, &cache_chain, next) { if (!strcmp(cachep->name, kbuf)) { if (limit < 1 || batchcount < 1 || batchcount > limit || shared < 0) { @@ -4351,18 +4469,31 @@ ssize_t slabinfo_write(struct file *file, const char __user *buffer, break; } } - mutex_unlock(&slab_mutex); + mutex_unlock(&cache_chain_mutex); if (res >= 0) res = count; return res; } +static int slabinfo_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &slabinfo_op); +} + +static const struct file_operations proc_slabinfo_operations = { + .open = slabinfo_open, + .read = seq_read, + .write = slabinfo_write, + .llseek = seq_lseek, + .release = seq_release, +}; + #ifdef CONFIG_DEBUG_SLAB_LEAK static void *leaks_start(struct seq_file *m, loff_t *pos) { - mutex_lock(&slab_mutex); - return seq_list_start(&slab_caches, *pos); + mutex_lock(&cache_chain_mutex); + return seq_list_start(&cache_chain, *pos); } static inline int add_caller(unsigned long *n, unsigned long v) @@ -4401,7 +4532,7 @@ static void handle_slab(unsigned long *n, struct kmem_cache *c, struct slab *s) int i; if (n[0] == n[1]) return; - for (i = 0, p = s->s_mem; i < c->num; i++, p += c->size) { + for (i = 0, p = s->s_mem; i < c->num; i++, p += c->buffer_size) { if (slab_bufctl(s)[i] != BUFCTL_ACTIVE) continue; if (!add_caller(n, (unsigned long)*dbg_userword(c, p))) @@ -4427,7 +4558,7 @@ static void show_symbol(struct seq_file *m, unsigned long address) static int leaks_show(struct seq_file *m, void *p) { - struct kmem_cache *cachep = list_entry(p, struct kmem_cache, list); + struct kmem_cache *cachep = list_entry(p, struct kmem_cache, next); struct slab *slabp; struct kmem_list3 *l3; const char *name; @@ -4461,17 +4592,17 @@ static int leaks_show(struct seq_file *m, void *p) name = cachep->name; if (n[0] == n[1]) { /* Increase the buffer size */ - mutex_unlock(&slab_mutex); + mutex_unlock(&cache_chain_mutex); m->private = kzalloc(n[0] * 4 * sizeof(unsigned long), GFP_KERNEL); if (!m->private) { /* Too bad, we are really out */ m->private = n; - mutex_lock(&slab_mutex); + mutex_lock(&cache_chain_mutex); return -ENOMEM; } *(unsigned long *)m->private = n[0] * 2; kfree(n); - mutex_lock(&slab_mutex); + mutex_lock(&cache_chain_mutex); /* Now make sure this entry will be retried */ m->count = m->size; return 0; @@ -4485,16 +4616,6 @@ static int leaks_show(struct seq_file *m, void *p) return 0; } -static void *s_next(struct seq_file *m, void *p, loff_t *pos) -{ - return seq_list_next(p, &slab_caches, pos); -} - -static void s_stop(struct seq_file *m, void *p) -{ - mutex_unlock(&slab_mutex); -} - static const struct seq_operations slabstats_op = { .start = leaks_start, .next = s_next, @@ -4529,6 +4650,7 @@ static const struct file_operations proc_slabstats_operations = { static int __init slab_proc_init(void) { + proc_create("slabinfo",S_IWUSR|S_IRUSR,NULL,&proc_slabinfo_operations); #ifdef CONFIG_DEBUG_SLAB_LEAK proc_create("slab_allocators", 0, NULL, &proc_slabstats_operations); #endif @@ -4555,6 +4677,6 @@ size_t ksize(const void *objp) if (unlikely(objp == ZERO_SIZE_PTR)) return 0; - return virt_to_cache(objp)->object_size; + return obj_size(virt_to_cache(objp)); } EXPORT_SYMBOL(ksize); diff --git a/mm/slab.h b/mm/slab.h deleted file mode 100644 index d6d8456b556..00000000000 --- a/mm/slab.h +++ /dev/null @@ -1,128 +0,0 @@ -#ifndef MM_SLAB_H -#define MM_SLAB_H -/* - * Internal slab definitions - */ - -/* - * State of the slab allocator. - * - * This is used to describe the states of the allocator during bootup. - * Allocators use this to gradually bootstrap themselves. Most allocators - * have the problem that the structures used for managing slab caches are - * allocated from slab caches themselves. - */ -enum slab_state { - DOWN, /* No slab functionality yet */ - PARTIAL, /* SLUB: kmem_cache_node available */ - PARTIAL_ARRAYCACHE, /* SLAB: kmalloc size for arraycache available */ - PARTIAL_L3, /* SLAB: kmalloc size for l3 struct available */ - UP, /* Slab caches usable but not all extras yet */ - FULL /* Everything is working */ -}; - -extern enum slab_state slab_state; - -/* The slab cache mutex protects the management structures during changes */ -extern struct mutex slab_mutex; - -/* The list of all slab caches on the system */ -extern struct list_head slab_caches; - -/* The slab cache that manages slab cache information */ -extern struct kmem_cache *kmem_cache; - -unsigned long calculate_alignment(unsigned long flags, - unsigned long align, unsigned long size); - -/* Functions provided by the slab allocators */ -extern int __kmem_cache_create(struct kmem_cache *, unsigned long flags); - -extern struct kmem_cache *create_kmalloc_cache(const char *name, size_t size, - unsigned long flags); -extern void create_boot_cache(struct kmem_cache *, const char *name, - size_t size, unsigned long flags); - -#ifdef CONFIG_SLUB -struct kmem_cache *__kmem_cache_alias(const char *name, size_t size, - size_t align, unsigned long flags, void (*ctor)(void *)); -#else -static inline struct kmem_cache *__kmem_cache_alias(const char *name, size_t size, - size_t align, unsigned long flags, void (*ctor)(void *)) -{ return NULL; } -#endif - - -/* Legal flag mask for kmem_cache_create(), for various configurations */ -#define SLAB_CORE_FLAGS (SLAB_HWCACHE_ALIGN | SLAB_CACHE_DMA | SLAB_PANIC | \ - SLAB_DESTROY_BY_RCU | SLAB_DEBUG_OBJECTS ) - -#if defined(CONFIG_DEBUG_SLAB) -#define SLAB_DEBUG_FLAGS (SLAB_RED_ZONE | SLAB_POISON | SLAB_STORE_USER) -#elif defined(CONFIG_SLUB_DEBUG) -#define SLAB_DEBUG_FLAGS (SLAB_RED_ZONE | SLAB_POISON | SLAB_STORE_USER | \ - SLAB_TRACE | SLAB_DEBUG_FREE) -#else -#define SLAB_DEBUG_FLAGS (0) -#endif - -#if defined(CONFIG_SLAB) -#define SLAB_CACHE_FLAGS (SLAB_MEM_SPREAD | SLAB_NOLEAKTRACE | \ - SLAB_RECLAIM_ACCOUNT | SLAB_TEMPORARY | SLAB_NOTRACK) -#elif defined(CONFIG_SLUB) -#define SLAB_CACHE_FLAGS (SLAB_NOLEAKTRACE | SLAB_RECLAIM_ACCOUNT | \ - SLAB_TEMPORARY | SLAB_NOTRACK) -#else -#define SLAB_CACHE_FLAGS (0) -#endif - -#define CACHE_CREATE_MASK (SLAB_CORE_FLAGS | SLAB_DEBUG_FLAGS | SLAB_CACHE_FLAGS) - -int __kmem_cache_shutdown(struct kmem_cache *); - -struct seq_file; -struct file; - -struct slabinfo { - unsigned long active_objs; - unsigned long num_objs; - unsigned long active_slabs; - unsigned long num_slabs; - unsigned long shared_avail; - unsigned int limit; - unsigned int batchcount; - unsigned int shared; - unsigned int objects_per_slab; - unsigned int cache_order; -}; - -void get_slabinfo(struct kmem_cache *s, struct slabinfo *sinfo); -void slabinfo_show_stats(struct seq_file *m, struct kmem_cache *s); -ssize_t slabinfo_write(struct file *file, const char __user *buffer, - size_t count, loff_t *ppos); - -static inline bool slab_equal_or_root(struct kmem_cache *s, - struct kmem_cache *p) -{ - return true; -} - -static inline struct kmem_cache *cache_from_obj(struct kmem_cache *s, void *x) -{ - struct kmem_cache *cachep; - struct page *page; - - if (!unlikely(s->flags & SLAB_DEBUG_FREE)) - return s; - - page = virt_to_head_page(x); - cachep = page->slab_cache; - if (slab_equal_or_root(cachep, s)) - return cachep; - - pr_err("%s: Wrong slab cache. %s but object is from %s\n", - __FUNCTION__, cachep->name, s->name); - WARN_ON_ONCE(1); - return s; -} -#endif diff --git a/mm/slab_common.c b/mm/slab_common.c deleted file mode 100644 index 7e0cdca704e..00000000000 --- a/mm/slab_common.c +++ /dev/null @@ -1,371 +0,0 @@ -/* - * Slab allocator functions that are independent of the allocator strategy - * - * (C) 2012 Christoph Lameter - */ -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "slab.h" - -enum slab_state slab_state; -LIST_HEAD(slab_caches); -DEFINE_MUTEX(slab_mutex); -struct kmem_cache *kmem_cache; - -#ifdef CONFIG_DEBUG_VM -static int kmem_cache_sanity_check(const char *name, size_t size) -{ - struct kmem_cache *s = NULL; - - if (!name || in_interrupt() || size < sizeof(void *) || - size > KMALLOC_MAX_SIZE) { - pr_err("kmem_cache_create(%s) integrity check failed\n", name); - return -EINVAL; - } - - list_for_each_entry(s, &slab_caches, list) { - char tmp; - int res; - - /* - * This happens when the module gets unloaded and doesn't - * destroy its slab cache and no-one else reuses the vmalloc - * area of the module. Print a warning. - */ - res = probe_kernel_address(s->name, tmp); - if (res) { - pr_err("Slab cache with size %d has lost its name\n", - s->object_size); - continue; - } - - if (!strcmp(s->name, name)) { - pr_err("%s (%s): Cache name already exists.\n", - __func__, name); - dump_stack(); - s = NULL; - return -EINVAL; - } - } - - WARN_ON(strchr(name, ' ')); /* It confuses parsers */ - return 0; -} -#else -static inline int kmem_cache_sanity_check(const char *name, size_t size) -{ - return 0; -} -#endif - -/* - * Figure out what the alignment of the objects will be given a set of - * flags, a user specified alignment and the size of the objects. - */ -unsigned long calculate_alignment(unsigned long flags, - unsigned long align, unsigned long size) -{ - /* - * If the user wants hardware cache aligned objects then follow that - * suggestion if the object is sufficiently large. - * - * The hardware cache alignment cannot override the specified - * alignment though. If that is greater then use it. - */ - if (flags & SLAB_HWCACHE_ALIGN) { - unsigned long ralign = cache_line_size(); - while (size <= ralign / 2) - ralign /= 2; - align = max(align, ralign); - } - - if (align < ARCH_SLAB_MINALIGN) - align = ARCH_SLAB_MINALIGN; - - return ALIGN(align, sizeof(void *)); -} - - -/* - * kmem_cache_create - Create a cache. - * @name: A string which is used in /proc/slabinfo to identify this cache. - * @size: The size of objects to be created in this cache. - * @align: The required alignment for the objects. - * @flags: SLAB flags - * @ctor: A constructor for the objects. - * - * Returns a ptr to the cache on success, NULL on failure. - * Cannot be called within a interrupt, but can be interrupted. - * The @ctor is run when new pages are allocated by the cache. - * - * The flags are - * - * %SLAB_POISON - Poison the slab with a known test pattern (a5a5a5a5) - * to catch references to uninitialised memory. - * - * %SLAB_RED_ZONE - Insert `Red' zones around the allocated memory to check - * for buffer overruns. - * - * %SLAB_HWCACHE_ALIGN - Align the objects in this cache to a hardware - * cacheline. This can be beneficial if you're counting cycles as closely - * as davem. - */ - -struct kmem_cache *kmem_cache_create(const char *name, size_t size, size_t align, - unsigned long flags, void (*ctor)(void *)) -{ - struct kmem_cache *s = NULL; - int err = 0; - - get_online_cpus(); - mutex_lock(&slab_mutex); - - if (!kmem_cache_sanity_check(name, size) == 0) - goto out_locked; - - /* - * Some allocators will constraint the set of valid flags to a subset - * of all flags. We expect them to define CACHE_CREATE_MASK in this - * case, and we'll just provide them with a sanitized version of the - * passed flags. - */ - flags &= CACHE_CREATE_MASK; - - s = __kmem_cache_alias(name, size, align, flags, ctor); - if (s) - goto out_locked; - - s = kmem_cache_zalloc(kmem_cache, GFP_KERNEL); - if (s) { - s->object_size = s->size = size; - s->align = calculate_alignment(flags, align, size); - s->ctor = ctor; - s->name = kstrdup(name, GFP_KERNEL); - if (!s->name) { - kmem_cache_free(kmem_cache, s); - err = -ENOMEM; - goto out_locked; - } - - err = __kmem_cache_create(s, flags); - if (!err) { - - s->refcount = 1; - list_add(&s->list, &slab_caches); - - } else { - kfree(s->name); - kmem_cache_free(kmem_cache, s); - } - } else - err = -ENOMEM; - -out_locked: - mutex_unlock(&slab_mutex); - put_online_cpus(); - - if (err) { - - if (flags & SLAB_PANIC) - panic("kmem_cache_create: Failed to create slab '%s'. Error %d\n", - name, err); - else { - printk(KERN_WARNING "kmem_cache_create(%s) failed with error %d", - name, err); - dump_stack(); - } - - return NULL; - } - - return s; -} -EXPORT_SYMBOL(kmem_cache_create); - -void kmem_cache_destroy(struct kmem_cache *s) -{ - get_online_cpus(); - mutex_lock(&slab_mutex); - s->refcount--; - if (!s->refcount) { - list_del(&s->list); - - if (!__kmem_cache_shutdown(s)) { - if (s->flags & SLAB_DESTROY_BY_RCU) - rcu_barrier(); - - kfree(s->name); - kmem_cache_free(kmem_cache, s); - } else { - list_add(&s->list, &slab_caches); - printk(KERN_ERR "kmem_cache_destroy %s: Slab cache still has objects\n", - s->name); - dump_stack(); - } - } - mutex_unlock(&slab_mutex); - put_online_cpus(); -} -EXPORT_SYMBOL(kmem_cache_destroy); - -int slab_is_available(void) -{ - return slab_state >= UP; -} - -#ifndef CONFIG_SLOB -/* Create a cache during boot when no slab services are available yet */ -void __init create_boot_cache(struct kmem_cache *s, const char *name, size_t size, - unsigned long flags) -{ - int err; - - s->name = name; - s->size = s->object_size = size; - s->align = calculate_alignment(flags, ARCH_KMALLOC_MINALIGN, size); - err = __kmem_cache_create(s, flags); - - if (err) - panic("Creation of kmalloc slab %s size=%zd failed. Reason %d\n", - name, size, err); - - s->refcount = -1; /* Exempt from merging for now */ -} - -struct kmem_cache *__init create_kmalloc_cache(const char *name, size_t size, - unsigned long flags) -{ - struct kmem_cache *s = kmem_cache_zalloc(kmem_cache, GFP_NOWAIT); - - if (!s) - panic("Out of memory when creating slab %s\n", name); - - create_boot_cache(s, name, size, flags); - list_add(&s->list, &slab_caches); - s->refcount = 1; - return s; -} - -#endif /* !CONFIG_SLOB */ - - -#ifdef CONFIG_SLABINFO -static void print_slabinfo_header(struct seq_file *m) -{ - /* - * Output format version, so at least we can change it - * without _too_ many complaints. - */ -#ifdef CONFIG_DEBUG_SLAB - seq_puts(m, "slabinfo - version: 2.1 (statistics)\n"); -#else - seq_puts(m, "slabinfo - version: 2.1\n"); -#endif - seq_puts(m, "# name " - " "); - seq_puts(m, " : tunables "); - seq_puts(m, " : slabdata "); -#ifdef CONFIG_DEBUG_SLAB - seq_puts(m, " : globalstat " - " "); - seq_puts(m, " : cpustat "); -#endif - seq_putc(m, '\n'); -} - -static void *s_start(struct seq_file *m, loff_t *pos) -{ - loff_t n = *pos; - - mutex_lock(&slab_mutex); - if (!n) - print_slabinfo_header(m); - - return seq_list_start(&slab_caches, *pos); -} - -static void *s_next(struct seq_file *m, void *p, loff_t *pos) -{ - return seq_list_next(p, &slab_caches, pos); -} - -static void s_stop(struct seq_file *m, void *p) -{ - mutex_unlock(&slab_mutex); -} - -static int s_show(struct seq_file *m, void *p) -{ - struct kmem_cache *s = list_entry(p, struct kmem_cache, list); - struct slabinfo sinfo; - - memset(&sinfo, 0, sizeof(sinfo)); - get_slabinfo(s, &sinfo); - - seq_printf(m, "%-17s %6lu %6lu %6u %4u %4d", - s->name, sinfo.active_objs, sinfo.num_objs, s->size, - sinfo.objects_per_slab, (1 << sinfo.cache_order)); - - seq_printf(m, " : tunables %4u %4u %4u", - sinfo.limit, sinfo.batchcount, sinfo.shared); - seq_printf(m, " : slabdata %6lu %6lu %6lu", - sinfo.active_slabs, sinfo.num_slabs, sinfo.shared_avail); - slabinfo_show_stats(m, s); - seq_putc(m, '\n'); - return 0; -} - -/* - * slabinfo_op - iterator that generates /proc/slabinfo - * - * Output layout: - * cache-name - * num-active-objs - * total-objs - * object size - * num-active-slabs - * total-slabs - * num-pages-per-slab - * + further values on SMP and with statistics enabled - */ -static const struct seq_operations slabinfo_op = { - .start = s_start, - .next = s_next, - .stop = s_stop, - .show = s_show, -}; - -static int slabinfo_open(struct inode *inode, struct file *file) -{ - return seq_open(file, &slabinfo_op); -} - -static const struct file_operations proc_slabinfo_operations = { - .open = slabinfo_open, - .read = seq_read, - .write = slabinfo_write, - .llseek = seq_lseek, - .release = seq_release, -}; - -static int __init slab_proc_init(void) -{ - proc_create("slabinfo", S_IRUSR, NULL, &proc_slabinfo_operations); - return 0; -} -module_init(slab_proc_init); -#endif /* CONFIG_SLABINFO */ diff --git a/mm/slob.c b/mm/slob.c index 4eb5eca47f2..8105be42cad 100644 --- a/mm/slob.c +++ b/mm/slob.c @@ -28,8 +28,9 @@ * from kmalloc are prepended with a 4-byte header with the kmalloc size. * If kmalloc is asked for objects of PAGE_SIZE or larger, it calls * alloc_pages() directly, allocating compound pages so the page order - * does not have to be separately tracked. - * These objects are detected in kfree() because PageSlab() + * does not have to be separately tracked, and also stores the exact + * allocation size in page->private so that it can be used to accurately + * provide ksize(). These objects are detected in kfree() because slob_page() * is false for them. * * SLAB is emulated on top of SLOB by simply calling constructors and @@ -58,7 +59,6 @@ #include #include - #include #include /* struct reclaim_state */ #include @@ -72,7 +72,6 @@ #include -#include "slab.h" /* * slob_block has a field 'units', which indicates size of block if +ve, * or offset of next block if -ve (in SLOB_UNITs). @@ -92,6 +91,36 @@ struct slob_block { }; typedef struct slob_block slob_t; +/* + * We use struct page fields to manage some slob allocation aspects, + * however to avoid the horrible mess in include/linux/mm_types.h, we'll + * just define our own struct page type variant here. + */ +struct slob_page { + union { + struct { + unsigned long flags; /* mandatory */ + atomic_t _count; /* mandatory */ + slobidx_t units; /* free units left in page */ + unsigned long pad[2]; + slob_t *free; /* first free slob_t in page */ + struct list_head list; /* linked list of free pages */ + }; + struct page page; + }; +}; +static inline void struct_slob_page_wrong_size(void) +{ BUILD_BUG_ON(sizeof(struct slob_page) != sizeof(struct page)); } + +/* + * free_slob_page: call before a slob_page is returned to the page allocator. + */ +static inline void free_slob_page(struct slob_page *sp) +{ + reset_page_mapcount(&sp->page); + sp->page.mapping = NULL; +} + /* * All partially free slob pages go on these lists. */ @@ -101,28 +130,52 @@ static LIST_HEAD(free_slob_small); static LIST_HEAD(free_slob_medium); static LIST_HEAD(free_slob_large); +/* + * is_slob_page: True for all slob pages (false for bigblock pages) + */ +static inline int is_slob_page(struct slob_page *sp) +{ + return PageSlab((struct page *)sp); +} + +static inline void set_slob_page(struct slob_page *sp) +{ + __SetPageSlab((struct page *)sp); +} + +static inline void clear_slob_page(struct slob_page *sp) +{ + __ClearPageSlab((struct page *)sp); +} + +static inline struct slob_page *slob_page(const void *addr) +{ + return (struct slob_page *)virt_to_page(addr); +} + /* * slob_page_free: true for pages on free_slob_pages list. */ -static inline int slob_page_free(struct page *sp) +static inline int slob_page_free(struct slob_page *sp) { - return PageSlobFree(sp); + return PageSlobFree((struct page *)sp); } -static void set_slob_page_free(struct page *sp, struct list_head *list) +static void set_slob_page_free(struct slob_page *sp, struct list_head *list) { list_add(&sp->list, list); - __SetPageSlobFree(sp); + __SetPageSlobFree((struct page *)sp); } -static inline void clear_slob_page_free(struct page *sp) +static inline void clear_slob_page_free(struct slob_page *sp) { list_del(&sp->list); - __ClearPageSlobFree(sp); + __ClearPageSlobFree((struct page *)sp); } #define SLOB_UNIT sizeof(slob_t) #define SLOB_UNITS(size) (((size) + SLOB_UNIT - 1)/SLOB_UNIT) +#define SLOB_ALIGN L1_CACHE_BYTES /* * struct slob_rcu is inserted at the tail of allocated slob blocks, which @@ -192,7 +245,7 @@ static void *slob_new_pages(gfp_t gfp, int order, int node) void *page; #ifdef CONFIG_NUMA - if (node != NUMA_NO_NODE) + if (node != -1) page = alloc_pages_exact_node(node, gfp, order); else #endif @@ -214,12 +267,12 @@ static void slob_free_pages(void *b, int order) /* * Allocate a slob block within a given slob_page sp. */ -static void *slob_page_alloc(struct page *sp, size_t size, int align) +static void *slob_page_alloc(struct slob_page *sp, size_t size, int align) { slob_t *prev, *cur, *aligned = NULL; int delta = 0, units = SLOB_UNITS(size); - for (prev = NULL, cur = sp->freelist; ; prev = cur, cur = slob_next(cur)) { + for (prev = NULL, cur = sp->free; ; prev = cur, cur = slob_next(cur)) { slobidx_t avail = slob_units(cur); if (align) { @@ -243,12 +296,12 @@ static void *slob_page_alloc(struct page *sp, size_t size, int align) if (prev) set_slob(prev, slob_units(prev), next); else - sp->freelist = next; + sp->free = next; } else { /* fragment */ if (prev) set_slob(prev, slob_units(prev), cur + units); else - sp->freelist = cur + units; + sp->free = cur + units; set_slob(cur + units, avail - units, next); } @@ -267,7 +320,7 @@ static void *slob_page_alloc(struct page *sp, size_t size, int align) */ static void *slob_alloc(size_t size, gfp_t gfp, int align, int node) { - struct page *sp; + struct slob_page *sp; struct list_head *prev; struct list_head *slob_list; slob_t *b = NULL; @@ -288,7 +341,7 @@ static void *slob_alloc(size_t size, gfp_t gfp, int align, int node) * If there's a node specification, search for a partial * page with a matching node id in the freelist. */ - if (node != NUMA_NO_NODE && page_to_nid(sp) != node) + if (node != -1 && page_to_nid(&sp->page) != node) continue; #endif /* Enough room on this page? */ @@ -316,12 +369,12 @@ static void *slob_alloc(size_t size, gfp_t gfp, int align, int node) b = slob_new_pages(gfp & ~__GFP_ZERO, 0, node); if (!b) return NULL; - sp = virt_to_page(b); - __SetPageSlab(sp); + sp = slob_page(b); + set_slob_page(sp); spin_lock_irqsave(&slob_lock, flags); sp->units = SLOB_UNITS(PAGE_SIZE); - sp->freelist = b; + sp->free = b; INIT_LIST_HEAD(&sp->list); set_slob(b, SLOB_UNITS(PAGE_SIZE), b + SLOB_UNITS(PAGE_SIZE)); set_slob_page_free(sp, slob_list); @@ -339,7 +392,7 @@ static void *slob_alloc(size_t size, gfp_t gfp, int align, int node) */ static void slob_free(void *block, int size) { - struct page *sp; + struct slob_page *sp; slob_t *prev, *next, *b = (slob_t *)block; slobidx_t units; unsigned long flags; @@ -349,7 +402,7 @@ static void slob_free(void *block, int size) return; BUG_ON(!size); - sp = virt_to_page(block); + sp = slob_page(block); units = SLOB_UNITS(size); spin_lock_irqsave(&slob_lock, flags); @@ -359,8 +412,8 @@ static void slob_free(void *block, int size) if (slob_page_free(sp)) clear_slob_page_free(sp); spin_unlock_irqrestore(&slob_lock, flags); - __ClearPageSlab(sp); - reset_page_mapcount(sp); + clear_slob_page(sp); + free_slob_page(sp); slob_free_pages(b, 0); return; } @@ -368,7 +421,7 @@ static void slob_free(void *block, int size) if (!slob_page_free(sp)) { /* This slob page is about to become partially free. Easy! */ sp->units = units; - sp->freelist = b; + sp->free = b; set_slob(b, units, (void *)((unsigned long)(b + SLOB_UNITS(PAGE_SIZE)) & PAGE_MASK)); @@ -388,15 +441,15 @@ static void slob_free(void *block, int size) */ sp->units += units; - if (b < (slob_t *)sp->freelist) { - if (b + units == sp->freelist) { - units += slob_units(sp->freelist); - sp->freelist = slob_next(sp->freelist); + if (b < sp->free) { + if (b + units == sp->free) { + units += slob_units(sp->free); + sp->free = slob_next(sp->free); } - set_slob(b, units, sp->freelist); - sp->freelist = b; + set_slob(b, units, sp->free); + sp->free = b; } else { - prev = sp->freelist; + prev = sp->free; next = slob_next(prev); while (b > next) { prev = next; @@ -423,8 +476,7 @@ static void slob_free(void *block, int size) * End of slob allocator proper. Begin kmem_cache_alloc and kmalloc frontend. */ -static __always_inline void * -__do_kmalloc_node(size_t size, gfp_t gfp, int node, unsigned long caller) +void *__kmalloc_node(size_t size, gfp_t gfp, int node) { unsigned int *m; int align = max(ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN); @@ -445,7 +497,7 @@ __do_kmalloc_node(size_t size, gfp_t gfp, int node, unsigned long caller) *m = size; ret = (void *)m + align; - trace_kmalloc_node(caller, ret, + trace_kmalloc_node(_RET_IP_, ret, size, size + align, gfp, node); } else { unsigned int order = get_order(size); @@ -453,39 +505,24 @@ __do_kmalloc_node(size_t size, gfp_t gfp, int node, unsigned long caller) if (likely(order)) gfp |= __GFP_COMP; ret = slob_new_pages(gfp, order, node); + if (ret) { + struct page *page; + page = virt_to_page(ret); + page->private = size; + } - trace_kmalloc_node(caller, ret, + trace_kmalloc_node(_RET_IP_, ret, size, PAGE_SIZE << order, gfp, node); } kmemleak_alloc(ret, size, 1, gfp); return ret; } - -void *__kmalloc_node(size_t size, gfp_t gfp, int node) -{ - return __do_kmalloc_node(size, gfp, node, _RET_IP_); -} EXPORT_SYMBOL(__kmalloc_node); -#ifdef CONFIG_TRACING -void *__kmalloc_track_caller(size_t size, gfp_t gfp, unsigned long caller) -{ - return __do_kmalloc_node(size, gfp, NUMA_NO_NODE, caller); -} - -#ifdef CONFIG_NUMA -void *__kmalloc_node_track_caller(size_t size, gfp_t gfp, - int node, unsigned long caller) -{ - return __do_kmalloc_node(size, gfp, node, caller); -} -#endif -#endif - void kfree(const void *block) { - struct page *sp; + struct slob_page *sp; trace_kfree(_RET_IP_, block); @@ -493,46 +530,81 @@ void kfree(const void *block) return; kmemleak_free(block); - sp = virt_to_page(block); - if (PageSlab(sp)) { + sp = slob_page(block); + if (is_slob_page(sp)) { int align = max(ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN); unsigned int *m = (unsigned int *)(block - align); slob_free(m, *m + align); } else - put_page(sp); + put_page(&sp->page); } EXPORT_SYMBOL(kfree); /* can't use ksize for kmem_cache_alloc memory, only kmalloc */ size_t ksize(const void *block) { - struct page *sp; - int align; - unsigned int *m; + struct slob_page *sp; BUG_ON(!block); if (unlikely(block == ZERO_SIZE_PTR)) return 0; - sp = virt_to_page(block); - if (unlikely(!PageSlab(sp))) - return PAGE_SIZE << compound_order(sp); - - align = max(ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN); - m = (unsigned int *)(block - align); - return SLOB_UNITS(*m) * SLOB_UNIT; + sp = slob_page(block); + if (is_slob_page(sp)) { + int align = max(ARCH_KMALLOC_MINALIGN, ARCH_SLAB_MINALIGN); + unsigned int *m = (unsigned int *)(block - align); + return SLOB_UNITS(*m) * SLOB_UNIT; + } else + return sp->page.private; } EXPORT_SYMBOL(ksize); -int __kmem_cache_create(struct kmem_cache *c, unsigned long flags) +struct kmem_cache { + unsigned int size, align; + unsigned long flags; + const char *name; + void (*ctor)(void *); +}; + +struct kmem_cache *kmem_cache_create(const char *name, size_t size, + size_t align, unsigned long flags, void (*ctor)(void *)) { - if (flags & SLAB_DESTROY_BY_RCU) { - /* leave room for rcu footer at the end of object */ - c->size += sizeof(struct slob_rcu); - } - c->flags = flags; - return 0; + struct kmem_cache *c; + + c = slob_alloc(sizeof(struct kmem_cache), + GFP_KERNEL, ARCH_KMALLOC_MINALIGN, -1); + + if (c) { + c->name = name; + c->size = size; + if (flags & SLAB_DESTROY_BY_RCU) { + /* leave room for rcu footer at the end of object */ + c->size += sizeof(struct slob_rcu); + } + c->flags = flags; + c->ctor = ctor; + /* ignore alignment unless it's forced */ + c->align = (flags & SLAB_HWCACHE_ALIGN) ? SLOB_ALIGN : 0; + if (c->align < ARCH_SLAB_MINALIGN) + c->align = ARCH_SLAB_MINALIGN; + if (c->align < align) + c->align = align; + } else if (flags & SLAB_PANIC) + panic("Cannot create slab cache %s\n", name); + + kmemleak_alloc(c, sizeof(struct kmem_cache), 1, GFP_KERNEL); + return c; } +EXPORT_SYMBOL(kmem_cache_create); + +void kmem_cache_destroy(struct kmem_cache *c) +{ + kmemleak_free(c); + if (c->flags & SLAB_DESTROY_BY_RCU) + rcu_barrier(); + slob_free(c, sizeof(struct kmem_cache)); +} +EXPORT_SYMBOL(kmem_cache_destroy); void *kmem_cache_alloc_node(struct kmem_cache *c, gfp_t flags, int node) { @@ -544,12 +616,12 @@ void *kmem_cache_alloc_node(struct kmem_cache *c, gfp_t flags, int node) if (c->size < PAGE_SIZE) { b = slob_alloc(c->size, flags, c->align, node); - trace_kmem_cache_alloc_node(_RET_IP_, b, c->object_size, + trace_kmem_cache_alloc_node(_RET_IP_, b, c->size, SLOB_UNITS(c->size) * SLOB_UNIT, flags, node); } else { b = slob_new_pages(flags, get_order(c->size), node); - trace_kmem_cache_alloc_node(_RET_IP_, b, c->object_size, + trace_kmem_cache_alloc_node(_RET_IP_, b, c->size, PAGE_SIZE << get_order(c->size), flags, node); } @@ -594,11 +666,11 @@ void kmem_cache_free(struct kmem_cache *c, void *b) } EXPORT_SYMBOL(kmem_cache_free); -int __kmem_cache_shutdown(struct kmem_cache *c) +unsigned int kmem_cache_size(struct kmem_cache *c) { - /* No way to check for remaining objects */ - return 0; + return c->size; } +EXPORT_SYMBOL(kmem_cache_size); int kmem_cache_shrink(struct kmem_cache *d) { @@ -606,20 +678,19 @@ int kmem_cache_shrink(struct kmem_cache *d) } EXPORT_SYMBOL(kmem_cache_shrink); -struct kmem_cache kmem_cache_boot = { - .name = "kmem_cache", - .size = sizeof(struct kmem_cache), - .flags = SLAB_PANIC, - .align = ARCH_KMALLOC_MINALIGN, -}; +static unsigned int slob_ready __read_mostly; + +int slab_is_available(void) +{ + return slob_ready; +} void __init kmem_cache_init(void) { - kmem_cache = &kmem_cache_boot; - slab_state = UP; + slob_ready = 1; } void __init kmem_cache_init_late(void) { - slab_state = FULL; + /* Nothing to do */ } diff --git a/mm/slub.c b/mm/slub.c index 5a4128830cb..4941dc9cf72 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -16,7 +16,6 @@ #include #include #include -#include "slab.h" #include #include #include @@ -34,17 +33,15 @@ #include -#include "internal.h" - /* * Lock order: - * 1. slab_mutex (Global Mutex) + * 1. slub_lock (Global Semaphore) * 2. node->list_lock * 3. slab_lock(page) (Only on some arches and for debugging) * - * slab_mutex + * slub_lock * - * The role of the slab_mutex is to protect the list of all the slabs + * The role of the slub_lock is to protect the list of all the slabs * and to synchronize major metadata changes to slab cache structures. * * The slab_lock is only used for debugging and on arches that do not @@ -112,6 +109,9 @@ * the fast path and disables lockless freelists. */ +#define SLAB_DEBUG_FLAGS (SLAB_RED_ZONE | SLAB_POISON | SLAB_STORE_USER | \ + SLAB_TRACE | SLAB_DEBUG_FREE) + static inline int kmem_cache_debug(struct kmem_cache *s) { #ifdef CONFIG_SLUB_DEBUG @@ -176,10 +176,23 @@ static inline int kmem_cache_debug(struct kmem_cache *s) #define __OBJECT_POISON 0x80000000UL /* Poison object */ #define __CMPXCHG_DOUBLE 0x40000000UL /* Use cmpxchg_double */ +static int kmem_size = sizeof(struct kmem_cache); + #ifdef CONFIG_SMP static struct notifier_block slab_notifier; #endif +static enum { + DOWN, /* No slab functionality available */ + PARTIAL, /* Kmem_cache_node works */ + UP, /* Everything works but does not show up in sysfs */ + SYSFS /* Sysfs up */ +} slab_state = DOWN; + +/* A list of all slab caches on the system */ +static DECLARE_RWSEM(slub_lock); +static LIST_HEAD(slab_caches); + /* * Tracking user of a slab. */ @@ -205,7 +218,11 @@ static void sysfs_slab_remove(struct kmem_cache *); static inline int sysfs_slab_add(struct kmem_cache *s) { return 0; } static inline int sysfs_slab_alias(struct kmem_cache *s, const char *p) { return 0; } -static inline void sysfs_slab_remove(struct kmem_cache *s) { } +static inline void sysfs_slab_remove(struct kmem_cache *s) +{ + kfree(s->name); + kfree(s); +} #endif @@ -220,6 +237,11 @@ static inline void stat(const struct kmem_cache *s, enum stat_item si) * Core slab cache functions *******************************************************************/ +int slab_is_available(void) +{ + return slab_state >= UP; +} + static inline struct kmem_cache_node *get_node(struct kmem_cache *s, int node) { return s->node[node]; @@ -289,7 +311,7 @@ static inline size_t slab_ksize(const struct kmem_cache *s) * and whatever may come after it. */ if (s->flags & (SLAB_RED_ZONE | SLAB_POISON)) - return s->object_size; + return s->objsize; #endif /* @@ -559,8 +581,6 @@ static void slab_bug(struct kmem_cache *s, char *fmt, ...) printk(KERN_ERR "BUG %s (%s): %s\n", s->name, print_tainted(), buf); printk(KERN_ERR "----------------------------------------" "-------------------------------------\n\n"); - - add_taint(TAINT_BAD_PAGE); } static void slab_fix(struct kmem_cache *s, char *fmt, ...) @@ -589,11 +609,11 @@ static void print_trailer(struct kmem_cache *s, struct page *page, u8 *p) if (p > addr + 16) print_section("Bytes b4 ", p - 16, 16); - print_section("Object ", p, min_t(unsigned long, s->object_size, + print_section("Object ", p, min_t(unsigned long, s->objsize, PAGE_SIZE)); if (s->flags & SLAB_RED_ZONE) - print_section("Redzone ", p + s->object_size, - s->inuse - s->object_size); + print_section("Redzone ", p + s->objsize, + s->inuse - s->objsize); if (s->offset) off = s->offset + sizeof(void *); @@ -617,7 +637,7 @@ static void object_err(struct kmem_cache *s, struct page *page, print_trailer(s, page, object); } -static void slab_err(struct kmem_cache *s, struct page *page, const char *fmt, ...) +static void slab_err(struct kmem_cache *s, struct page *page, char *fmt, ...) { va_list args; char buf[100]; @@ -635,12 +655,12 @@ static void init_object(struct kmem_cache *s, void *object, u8 val) u8 *p = object; if (s->flags & __OBJECT_POISON) { - memset(p, POISON_FREE, s->object_size - 1); - p[s->object_size - 1] = POISON_END; + memset(p, POISON_FREE, s->objsize - 1); + p[s->objsize - 1] = POISON_END; } if (s->flags & SLAB_RED_ZONE) - memset(p + s->object_size, val, s->inuse - s->object_size); + memset(p + s->objsize, val, s->inuse - s->objsize); } static void restore_bytes(struct kmem_cache *s, char *message, u8 data, @@ -685,10 +705,10 @@ static int check_bytes_and_report(struct kmem_cache *s, struct page *page, * Poisoning uses 0x6b (POISON_FREE) and the last byte is * 0xa5 (POISON_END) * - * object + s->object_size + * object + s->objsize * Padding to reach word boundary. This is also used for Redzoning. * Padding is extended by another word if Redzoning is enabled and - * object_size == inuse. + * objsize == inuse. * * We fill with 0xbb (RED_INACTIVE) for inactive objects and with * 0xcc (RED_ACTIVE) for objects in use. @@ -707,7 +727,7 @@ static int check_bytes_and_report(struct kmem_cache *s, struct page *page, * object + s->size * Nothing is used beyond s->size. * - * If slabcaches are merged then the object_size and inuse boundaries are mostly + * If slabcaches are merged then the objsize and inuse boundaries are mostly * ignored. And therefore no slab options that rely on these boundaries * may be used with merged slabcaches. */ @@ -767,25 +787,25 @@ static int check_object(struct kmem_cache *s, struct page *page, void *object, u8 val) { u8 *p = object; - u8 *endobject = object + s->object_size; + u8 *endobject = object + s->objsize; if (s->flags & SLAB_RED_ZONE) { if (!check_bytes_and_report(s, page, object, "Redzone", - endobject, val, s->inuse - s->object_size)) + endobject, val, s->inuse - s->objsize)) return 0; } else { - if ((s->flags & SLAB_POISON) && s->object_size < s->inuse) { + if ((s->flags & SLAB_POISON) && s->objsize < s->inuse) { check_bytes_and_report(s, page, p, "Alignment padding", - endobject, POISON_INUSE, s->inuse - s->object_size); + endobject, POISON_INUSE, s->inuse - s->objsize); } } if (s->flags & SLAB_POISON) { if (val != SLUB_RED_ACTIVE && (s->flags & __OBJECT_POISON) && (!check_bytes_and_report(s, page, p, "Poison", p, - POISON_FREE, s->object_size - 1) || + POISON_FREE, s->objsize - 1) || !check_bytes_and_report(s, page, p, "Poison", - p + s->object_size - 1, POISON_END, 1))) + p + s->objsize - 1, POISON_END, 1))) return 0; /* * check_pad_bytes cleans up on its own. @@ -906,7 +926,7 @@ static void trace(struct kmem_cache *s, struct page *page, void *object, page->freelist); if (!alloc) - print_section("Object ", (void *)object, s->object_size); + print_section("Object ", (void *)object, s->objsize); dump_stack(); } @@ -922,14 +942,14 @@ static inline int slab_pre_alloc_hook(struct kmem_cache *s, gfp_t flags) lockdep_trace_alloc(flags); might_sleep_if(flags & __GFP_WAIT); - return should_failslab(s->object_size, flags, s->flags); + return should_failslab(s->objsize, flags, s->flags); } static inline void slab_post_alloc_hook(struct kmem_cache *s, gfp_t flags, void *object) { flags &= gfp_allowed_mask; kmemcheck_slab_alloc(s, flags, object, slab_ksize(s)); - kmemleak_alloc_recursive(object, s->object_size, 1, s->flags, flags); + kmemleak_alloc_recursive(object, s->objsize, 1, s->flags, flags); } static inline void slab_free_hook(struct kmem_cache *s, void *x) @@ -946,13 +966,13 @@ static inline void slab_free_hook(struct kmem_cache *s, void *x) unsigned long flags; local_irq_save(flags); - kmemcheck_slab_free(s, x, s->object_size); - debug_check_no_locks_freed(x, s->object_size); + kmemcheck_slab_free(s, x, s->objsize); + debug_check_no_locks_freed(x, s->objsize); local_irq_restore(flags); } #endif if (!(s->flags & SLAB_DEBUG_OBJECTS)) - debug_check_no_obj_freed(x, s->object_size); + debug_check_no_obj_freed(x, s->objsize); } /* @@ -1062,13 +1082,13 @@ static noinline int alloc_debug_processing(struct kmem_cache *s, struct page *pa return 0; } -static noinline struct kmem_cache_node *free_debug_processing( - struct kmem_cache *s, struct page *page, void *object, - unsigned long addr, unsigned long *flags) +static noinline int free_debug_processing(struct kmem_cache *s, + struct page *page, void *object, unsigned long addr) { - struct kmem_cache_node *n = get_node(s, page_to_nid(page)); + unsigned long flags; + int rc = 0; - spin_lock_irqsave(&n->list_lock, *flags); + local_irq_save(flags); slab_lock(page); if (!check_slab(s, page)) @@ -1087,11 +1107,11 @@ static noinline struct kmem_cache_node *free_debug_processing( if (!check_object(s, page, object, SLUB_RED_ACTIVE)) goto out; - if (unlikely(s != page->slab_cache)) { + if (unlikely(s != page->slab)) { if (!PageSlab(page)) { slab_err(s, page, "Attempt to free object(0x%p) " "outside of slab", object); - } else if (!page->slab_cache) { + } else if (!page->slab) { printk(KERN_ERR "SLUB : no slab for object 0x%p.\n", object); @@ -1106,19 +1126,15 @@ static noinline struct kmem_cache_node *free_debug_processing( set_track(s, object, TRACK_FREE, addr); trace(s, page, object, 0); init_object(s, object, SLUB_RED_INACTIVE); + rc = 1; out: slab_unlock(page); - /* - * Keep node_lock to preserve integrity - * until the object is actually freed - */ - return n; + local_irq_restore(flags); + return rc; fail: - slab_unlock(page); - spin_unlock_irqrestore(&n->list_lock, *flags); slab_fix(s, "Object at 0x%p not freed", object); - return NULL; + goto out; } static int __init setup_slub_debug(char *str) @@ -1191,7 +1207,7 @@ static int __init setup_slub_debug(char *str) __setup("slub_debug", setup_slub_debug); -static unsigned long kmem_cache_flags(unsigned long object_size, +static unsigned long kmem_cache_flags(unsigned long objsize, unsigned long flags, const char *name, void (*ctor)(void *)) { @@ -1211,9 +1227,8 @@ static inline void setup_object_debug(struct kmem_cache *s, static inline int alloc_debug_processing(struct kmem_cache *s, struct page *page, void *object, unsigned long addr) { return 0; } -static inline struct kmem_cache_node *free_debug_processing( - struct kmem_cache *s, struct page *page, void *object, - unsigned long addr, unsigned long *flags) { return NULL; } +static inline int free_debug_processing(struct kmem_cache *s, + struct page *page, void *object, unsigned long addr) { return 0; } static inline int slab_pad_check(struct kmem_cache *s, struct page *page) { return 1; } @@ -1222,7 +1237,7 @@ static inline int check_object(struct kmem_cache *s, struct page *page, static inline void add_full(struct kmem_cache *s, struct kmem_cache_node *n, struct page *page) {} static inline void remove_full(struct kmem_cache *s, struct page *page) {} -static inline unsigned long kmem_cache_flags(unsigned long object_size, +static inline unsigned long kmem_cache_flags(unsigned long objsize, unsigned long flags, const char *name, void (*ctor)(void *)) { @@ -1299,7 +1314,13 @@ static struct page *allocate_slab(struct kmem_cache *s, gfp_t flags, int node) stat(s, ORDER_FALLBACK); } - if (kmemcheck_enabled && page + if (flags & __GFP_WAIT) + local_irq_disable(); + + if (!page) + return NULL; + + if (kmemcheck_enabled && !(s->flags & (SLAB_NOTRACK | DEBUG_DEFAULT_FLAGS))) { int pages = 1 << oo_order(oo); @@ -1315,11 +1336,6 @@ static struct page *allocate_slab(struct kmem_cache *s, gfp_t flags, int node) kmemcheck_mark_unallocated_pages(page, pages); } - if (flags & __GFP_WAIT) - local_irq_disable(); - if (!page) - return NULL; - page->objects = oo_objects(oo); mod_zone_page_state(page_zone(page), (s->flags & SLAB_RECLAIM_ACCOUNT) ? @@ -1352,10 +1368,8 @@ static struct page *new_slab(struct kmem_cache *s, gfp_t flags, int node) goto out; inc_slabs_node(s, page_to_nid(page), page->objects); - page->slab_cache = s; - __SetPageSlab(page); - if (page->pfmemalloc) - SetPageSlabPfmemalloc(page); + page->slab = s; + page->flags |= 1 << PG_slab; start = page_address(page); @@ -1399,7 +1413,6 @@ static void __free_slab(struct kmem_cache *s, struct page *page) NR_SLAB_RECLAIMABLE : NR_SLAB_UNRECLAIMABLE, -pages); - __ClearPageSlabPfmemalloc(page); __ClearPageSlab(page); reset_page_mapcount(page); if (current->reclaim_state) @@ -1419,7 +1432,7 @@ static void rcu_free_slab(struct rcu_head *h) else page = container_of((struct list_head *)h, struct page, lru); - __free_slab(page->slab_cache, page); + __free_slab(page->slab, page); } static void free_slab(struct kmem_cache *s, struct page *page) @@ -1477,12 +1490,12 @@ static inline void remove_partial(struct kmem_cache_node *n, } /* - * Remove slab from the partial list, freeze it and - * return the pointer to the freelist. + * Lock slab, remove from the partial list and put the object into the + * per cpu freelist. * * Returns a list of objects or NULL if it fails. * - * Must hold list_lock since we modify the partial list. + * Must hold list_lock. */ static inline void *acquire_slab(struct kmem_cache *s, struct kmem_cache_node *n, struct page *page, @@ -1497,38 +1510,36 @@ static inline void *acquire_slab(struct kmem_cache *s, * The old freelist is the list of objects for the * per cpu allocation list. */ - freelist = page->freelist; - counters = page->counters; - new.counters = counters; - if (mode) { - new.inuse = page->objects; - new.freelist = NULL; - } else { - new.freelist = freelist; - } - VM_BUG_ON(new.frozen); - new.frozen = 1; + do { + freelist = page->freelist; + counters = page->counters; + new.counters = counters; + if (mode) { + new.inuse = page->objects; + new.freelist = NULL; + } else { + new.freelist = freelist; + } - if (!__cmpxchg_double_slab(s, page, + VM_BUG_ON(new.frozen); + new.frozen = 1; + + } while (!__cmpxchg_double_slab(s, page, freelist, counters, new.freelist, new.counters, - "acquire_slab")) - - return NULL; + "lock and freeze")); remove_partial(n, page); - WARN_ON(!freelist); return freelist; } static int put_cpu_partial(struct kmem_cache *s, struct page *page, int drain); -static inline bool pfmemalloc_match(struct page *page, gfp_t gfpflags); /* * Try to allocate a partial slab from a specific node. */ -static void *get_partial_node(struct kmem_cache *s, struct kmem_cache_node *n, - struct kmem_cache_cpu *c, gfp_t flags) +static void *get_partial_node(struct kmem_cache *s, + struct kmem_cache_node *n, struct kmem_cache_cpu *c) { struct page *page, *page2; void *object = NULL; @@ -1544,18 +1555,15 @@ static void *get_partial_node(struct kmem_cache *s, struct kmem_cache_node *n, spin_lock(&n->list_lock); list_for_each_entry_safe(page, page2, &n->partial, lru) { - void *t; + void *t = acquire_slab(s, n, page, object == NULL); int available; - if (!pfmemalloc_match(page, flags)) - continue; - - t = acquire_slab(s, n, page, object == NULL); if (!t) break; if (!object) { c->page = page; + c->node = page_to_nid(page); stat(s, ALLOC_FROM_PARTIAL); object = t; available = page->objects - page->inuse; @@ -1609,7 +1617,7 @@ static struct page *get_any_partial(struct kmem_cache *s, gfp_t flags, do { cpuset_mems_cookie = get_mems_allowed(); - zonelist = node_zonelist(slab_node(), flags); + zonelist = node_zonelist(slab_node(current->mempolicy), flags); for_each_zone_zonelist(zone, z, zonelist, high_zoneidx) { struct kmem_cache_node *n; @@ -1617,7 +1625,7 @@ static struct page *get_any_partial(struct kmem_cache *s, gfp_t flags, if (n && cpuset_zone_allowed_hardwall(zone, flags) && n->nr_partial > s->min_partial) { - object = get_partial_node(s, n, c, flags); + object = get_partial_node(s, n, c); if (object) { /* * Return the object even if @@ -1646,7 +1654,7 @@ static void *get_partial(struct kmem_cache *s, gfp_t flags, int node, void *object; int searchnode = (node == NUMA_NO_NODE) ? numa_node_id() : node; - object = get_partial_node(s, get_node(s, searchnode), c, flags); + object = get_partial_node(s, get_node(s, searchnode), c); if (object || node != NUMA_NO_NODE) return object; @@ -1712,7 +1720,7 @@ static inline void note_cmpxchg_failure(const char *n, stat(s, CMPXCHG_DOUBLE_CPU_FAIL); } -static void init_kmem_cache_cpus(struct kmem_cache *s) +void init_kmem_cache_cpus(struct kmem_cache *s) { int cpu; @@ -1723,12 +1731,14 @@ static void init_kmem_cache_cpus(struct kmem_cache *s) /* * Remove the cpu slab */ -static void deactivate_slab(struct kmem_cache *s, struct page *page, void *freelist) +static void deactivate_slab(struct kmem_cache *s, struct kmem_cache_cpu *c) { enum slab_modes { M_NONE, M_PARTIAL, M_FULL, M_FREE }; + struct page *page = c->page; struct kmem_cache_node *n = get_node(s, page_to_nid(page)); int lock = 0; enum slab_modes l = M_NONE, m = M_NONE; + void *freelist; void *nextfree; int tail = DEACTIVATE_TO_HEAD; struct page new; @@ -1739,6 +1749,11 @@ static void deactivate_slab(struct kmem_cache *s, struct page *page, void *freel tail = DEACTIVATE_TO_TAIL; } + c->tid = next_tid(c->tid); + c->page = NULL; + freelist = c->freelist; + c->freelist = NULL; + /* * Stage one: Free all available per cpu objects back * to the page freelist while it is still frozen. Leave the @@ -1864,33 +1879,21 @@ static void deactivate_slab(struct kmem_cache *s, struct page *page, void *freel } } -/* - * Unfreeze all the cpu partial slabs. - * - * This function must be called with interrupts disabled - * for the cpu using c (or some other guarantee must be there - * to guarantee no concurrent accesses). - */ -static void unfreeze_partials(struct kmem_cache *s, - struct kmem_cache_cpu *c) +/* Unfreeze all the cpu partial slabs */ +static void unfreeze_partials(struct kmem_cache *s) { - struct kmem_cache_node *n = NULL, *n2 = NULL; + struct kmem_cache_node *n = NULL; + struct kmem_cache_cpu *c = this_cpu_ptr(s->cpu_slab); struct page *page, *discard_page = NULL; while ((page = c->partial)) { + enum slab_modes { M_PARTIAL, M_FREE }; + enum slab_modes l, m; struct page new; struct page old; c->partial = page->next; - - n2 = get_node(s, page_to_nid(page)); - if (n != n2) { - if (n) - spin_unlock(&n->list_lock); - - n = n2; - spin_lock(&n->list_lock); - } + l = M_FREE; do { @@ -1903,17 +1906,43 @@ static void unfreeze_partials(struct kmem_cache *s, new.frozen = 0; - } while (!__cmpxchg_double_slab(s, page, + if (!new.inuse && (!n || n->nr_partial > s->min_partial)) + m = M_FREE; + else { + struct kmem_cache_node *n2 = get_node(s, + page_to_nid(page)); + + m = M_PARTIAL; + if (n != n2) { + if (n) + spin_unlock(&n->list_lock); + + n = n2; + spin_lock(&n->list_lock); + } + } + + if (l != m) { + if (l == M_PARTIAL) { + remove_partial(n, page); + stat(s, FREE_REMOVE_PARTIAL); + } else { + add_partial(n, page, + DEACTIVATE_TO_TAIL); + stat(s, FREE_ADD_PARTIAL); + } + + l = m; + } + + } while (!cmpxchg_double_slab(s, page, old.freelist, old.counters, new.freelist, new.counters, "unfreezing slab")); - if (unlikely(!new.inuse && n->nr_partial > s->min_partial)) { + if (m == M_FREE) { page->next = discard_page; discard_page = page; - } else { - add_partial(n, page, DEACTIVATE_TO_TAIL); - stat(s, FREE_ADD_PARTIAL); } } @@ -1939,7 +1968,7 @@ static void unfreeze_partials(struct kmem_cache *s, * If we did not find a slot then simply move all the partials to the * per node partial list. */ -static int put_cpu_partial(struct kmem_cache *s, struct page *page, int drain) +int put_cpu_partial(struct kmem_cache *s, struct page *page, int drain) { struct page *oldpage; int pages; @@ -1960,9 +1989,8 @@ static int put_cpu_partial(struct kmem_cache *s, struct page *page, int drain) * set to the per node partial list. */ local_irq_save(flags); - unfreeze_partials(s, this_cpu_ptr(s->cpu_slab)); + unfreeze_partials(s); local_irq_restore(flags); - oldpage = NULL; pobjects = 0; pages = 0; stat(s, CPU_PARTIAL_DRAIN); @@ -1983,11 +2011,7 @@ static int put_cpu_partial(struct kmem_cache *s, struct page *page, int drain) static inline void flush_slab(struct kmem_cache *s, struct kmem_cache_cpu *c) { stat(s, CPUSLAB_FLUSH); - deactivate_slab(s, c->page, c->freelist); - - c->tid = next_tid(c->tid); - c->page = NULL; - c->freelist = NULL; + deactivate_slab(s, c); } /* @@ -2003,7 +2027,7 @@ static inline void __flush_cpu_slab(struct kmem_cache *s, int cpu) if (c->page) flush_slab(s, c); - unfreeze_partials(s, c); + unfreeze_partials(s); } } @@ -2031,10 +2055,10 @@ static void flush_all(struct kmem_cache *s) * Check if the objects in a per cpu structure fit numa * locality expectations. */ -static inline int node_match(struct page *page, int node) +static inline int node_match(struct kmem_cache_cpu *c, int node) { #ifdef CONFIG_NUMA - if (node != NUMA_NO_NODE && page_to_nid(page) != node) + if (node != NUMA_NO_NODE && c->node != node) return 0; #endif return 1; @@ -2077,10 +2101,10 @@ slab_out_of_memory(struct kmem_cache *s, gfp_t gfpflags, int nid) "SLUB: Unable to allocate memory on node %d (gfp=0x%x)\n", nid, gfpflags); printk(KERN_WARNING " cache: %s, object size: %d, buffer size: %d, " - "default order: %d, min order: %d\n", s->name, s->object_size, + "default order: %d, min order: %d\n", s->name, s->objsize, s->size, oo_order(s->oo), oo_order(s->min)); - if (oo_order(s->min) > get_order(s->object_size)) + if (oo_order(s->min) > get_order(s->objsize)) printk(KERN_WARNING " %s debugging increased min order, use " "slub_debug=O to disable.\n", s->name); @@ -2106,16 +2130,10 @@ slab_out_of_memory(struct kmem_cache *s, gfp_t gfpflags, int nid) static inline void *new_slab_objects(struct kmem_cache *s, gfp_t flags, int node, struct kmem_cache_cpu **pc) { - void *freelist; - struct kmem_cache_cpu *c = *pc; - struct page *page; - - freelist = get_partial(s, flags, node, c); - - if (freelist) - return freelist; + void *object; + struct kmem_cache_cpu *c; + struct page *page = new_slab(s, flags, node); - page = new_slab(s, flags, node); if (page) { c = __this_cpu_ptr(s->cpu_slab); if (c->page) @@ -2125,24 +2143,17 @@ static inline void *new_slab_objects(struct kmem_cache *s, gfp_t flags, * No other reference to the page yet so we can * muck around with it freely without cmpxchg */ - freelist = page->freelist; + object = page->freelist; page->freelist = NULL; stat(s, ALLOC_SLAB); + c->node = page_to_nid(page); c->page = page; *pc = c; } else - freelist = NULL; + object = NULL; - return freelist; -} - -static inline bool pfmemalloc_match(struct page *page, gfp_t gfpflags) -{ - if (unlikely(PageSlabPfmemalloc(page))) - return gfp_pfmemalloc_allowed(gfpflags); - - return true; + return object; } /* @@ -2152,8 +2163,6 @@ static inline bool pfmemalloc_match(struct page *page, gfp_t gfpflags) * The page is still frozen if the return value is not NULL. * * If this function returns NULL then the page has been unfrozen. - * - * This function must be called with interrupt disabled. */ static inline void *get_freelist(struct kmem_cache *s, struct page *page) { @@ -2164,14 +2173,13 @@ static inline void *get_freelist(struct kmem_cache *s, struct page *page) do { freelist = page->freelist; counters = page->counters; - new.counters = counters; VM_BUG_ON(!new.frozen); new.inuse = page->objects; new.frozen = freelist != NULL; - } while (!__cmpxchg_double_slab(s, page, + } while (!cmpxchg_double_slab(s, page, freelist, counters, NULL, new.counters, "get_freelist")); @@ -2198,8 +2206,7 @@ static inline void *get_freelist(struct kmem_cache *s, struct page *page) static void *__slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node, unsigned long addr, struct kmem_cache_cpu *c) { - void *freelist; - struct page *page; + void **object; unsigned long flags; local_irq_save(flags); @@ -2212,41 +2219,25 @@ static void *__slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node, c = this_cpu_ptr(s->cpu_slab); #endif - page = c->page; - if (!page) + if (!c->page) goto new_slab; redo: - - if (unlikely(!node_match(page, node))) { + if (unlikely(!node_match(c, node))) { stat(s, ALLOC_NODE_MISMATCH); - deactivate_slab(s, page, c->freelist); - c->page = NULL; - c->freelist = NULL; - goto new_slab; - } - - /* - * By rights, we should be searching for a slab page that was - * PFMEMALLOC but right now, we are losing the pfmemalloc - * information when the page leaves the per-cpu allocator - */ - if (unlikely(!pfmemalloc_match(page, gfpflags))) { - deactivate_slab(s, page, c->freelist); - c->page = NULL; - c->freelist = NULL; + deactivate_slab(s, c); goto new_slab; } /* must check again c->freelist in case of cpu migration or IRQ */ - freelist = c->freelist; - if (freelist) + object = c->freelist; + if (object) goto load_freelist; stat(s, ALLOC_SLOWPATH); - freelist = get_freelist(s, page); + object = get_freelist(s, c->page); - if (!freelist) { + if (!object) { c->page = NULL; stat(s, DEACTIVATE_BYPASS); goto new_slab; @@ -2255,50 +2246,50 @@ static void *__slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node, stat(s, ALLOC_REFILL); load_freelist: - /* - * freelist is pointing to the list of objects to be used. - * page is pointing to the page from which the objects are obtained. - * That page must be frozen for per cpu allocations to work. - */ - VM_BUG_ON(!c->page->frozen); - c->freelist = get_freepointer(s, freelist); + c->freelist = get_freepointer(s, object); c->tid = next_tid(c->tid); local_irq_restore(flags); - return freelist; + return object; new_slab: if (c->partial) { - page = c->page = c->partial; - c->partial = page->next; + c->page = c->partial; + c->partial = c->page->next; + c->node = page_to_nid(c->page); stat(s, CPU_PARTIAL_ALLOC); c->freelist = NULL; goto redo; } - freelist = new_slab_objects(s, gfpflags, node, &c); + /* Then do expensive stuff like retrieving pages from the partial lists */ + object = get_partial(s, gfpflags, node, c); - if (unlikely(!freelist)) { - if (!(gfpflags & __GFP_NOWARN) && printk_ratelimit()) - slab_out_of_memory(s, gfpflags, node); + if (unlikely(!object)) { - local_irq_restore(flags); - return NULL; + object = new_slab_objects(s, gfpflags, node, &c); + + if (unlikely(!object)) { + if (!(gfpflags & __GFP_NOWARN) && printk_ratelimit()) + slab_out_of_memory(s, gfpflags, node); + + local_irq_restore(flags); + return NULL; + } } - page = c->page; - if (likely(!kmem_cache_debug(s) && pfmemalloc_match(page, gfpflags))) + if (likely(!kmem_cache_debug(s))) goto load_freelist; /* Only entered in the debug case */ - if (kmem_cache_debug(s) && !alloc_debug_processing(s, page, freelist, addr)) + if (!alloc_debug_processing(s, c->page, object, addr)) goto new_slab; /* Slab failed checks. Next slab needed */ - deactivate_slab(s, page, get_freepointer(s, freelist)); - c->page = NULL; - c->freelist = NULL; + c->freelist = get_freepointer(s, object); + deactivate_slab(s, c); + c->node = NUMA_NO_NODE; local_irq_restore(flags); - return freelist; + return object; } /* @@ -2311,12 +2302,11 @@ static void *__slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node, * * Otherwise we can simply pick the next object from the lockless free list. */ -static __always_inline void *slab_alloc_node(struct kmem_cache *s, +static __always_inline void *slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node, unsigned long addr) { void **object; struct kmem_cache_cpu *c; - struct page *page; unsigned long tid; if (slab_pre_alloc_hook(s, gfpflags)) @@ -2342,8 +2332,8 @@ static __always_inline void *slab_alloc_node(struct kmem_cache *s, barrier(); object = c->freelist; - page = c->page; - if (unlikely(!object || !node_match(page, node))) + if (unlikely(!object || !node_match(c, node))) + object = __slab_alloc(s, gfpflags, node, addr, c); else { @@ -2374,24 +2364,18 @@ static __always_inline void *slab_alloc_node(struct kmem_cache *s, } if (unlikely(gfpflags & __GFP_ZERO) && object) - memset(object, 0, s->object_size); + memset(object, 0, s->objsize); slab_post_alloc_hook(s, gfpflags, object); return object; } -static __always_inline void *slab_alloc(struct kmem_cache *s, - gfp_t gfpflags, unsigned long addr) -{ - return slab_alloc_node(s, gfpflags, NUMA_NO_NODE, addr); -} - void *kmem_cache_alloc(struct kmem_cache *s, gfp_t gfpflags) { - void *ret = slab_alloc(s, gfpflags, _RET_IP_); + void *ret = slab_alloc(s, gfpflags, NUMA_NO_NODE, _RET_IP_); - trace_kmem_cache_alloc(_RET_IP_, ret, s->object_size, s->size, gfpflags); + trace_kmem_cache_alloc(_RET_IP_, ret, s->objsize, s->size, gfpflags); return ret; } @@ -2400,7 +2384,7 @@ EXPORT_SYMBOL(kmem_cache_alloc); #ifdef CONFIG_TRACING void *kmem_cache_alloc_trace(struct kmem_cache *s, gfp_t gfpflags, size_t size) { - void *ret = slab_alloc(s, gfpflags, _RET_IP_); + void *ret = slab_alloc(s, gfpflags, NUMA_NO_NODE, _RET_IP_); trace_kmalloc(_RET_IP_, ret, size, s->size, gfpflags); return ret; } @@ -2418,10 +2402,10 @@ EXPORT_SYMBOL(kmalloc_order_trace); #ifdef CONFIG_NUMA void *kmem_cache_alloc_node(struct kmem_cache *s, gfp_t gfpflags, int node) { - void *ret = slab_alloc_node(s, gfpflags, node, _RET_IP_); + void *ret = slab_alloc(s, gfpflags, node, _RET_IP_); trace_kmem_cache_alloc_node(_RET_IP_, ret, - s->object_size, s->size, gfpflags, node); + s->objsize, s->size, gfpflags, node); return ret; } @@ -2432,7 +2416,7 @@ void *kmem_cache_alloc_node_trace(struct kmem_cache *s, gfp_t gfpflags, int node, size_t size) { - void *ret = slab_alloc_node(s, gfpflags, node, _RET_IP_); + void *ret = slab_alloc(s, gfpflags, node, _RET_IP_); trace_kmalloc_node(_RET_IP_, ret, size, s->size, gfpflags, node); @@ -2456,6 +2440,7 @@ static void __slab_free(struct kmem_cache *s, struct page *page, void *prior; void **object = (void *)x; int was_frozen; + int inuse; struct page new; unsigned long counters; struct kmem_cache_node *n = NULL; @@ -2463,22 +2448,17 @@ static void __slab_free(struct kmem_cache *s, struct page *page, stat(s, FREE_SLOWPATH); - if (kmem_cache_debug(s) && - !(n = free_debug_processing(s, page, x, addr, &flags))) + if (kmem_cache_debug(s) && !free_debug_processing(s, page, x, addr)) return; do { - if (unlikely(n)) { - spin_unlock_irqrestore(&n->list_lock, flags); - n = NULL; - } prior = page->freelist; counters = page->counters; set_freepointer(s, object, prior); new.counters = counters; was_frozen = new.frozen; new.inuse--; - if ((!new.inuse || !prior) && !was_frozen) { + if ((!new.inuse || !prior) && !was_frozen && !n) { if (!kmem_cache_debug(s) && !prior) @@ -2503,6 +2483,7 @@ static void __slab_free(struct kmem_cache *s, struct page *page, } } + inuse = new.inuse; } while (!cmpxchg_double_slab(s, page, prior, counters, @@ -2528,17 +2509,25 @@ static void __slab_free(struct kmem_cache *s, struct page *page, return; } - if (unlikely(!new.inuse && n->nr_partial > s->min_partial)) - goto slab_empty; - /* - * Objects left in the slab. If it was not on the partial list before - * then add it. + * was_frozen may have been set after we acquired the list_lock in + * an earlier loop. So we need to check it here again. */ - if (kmem_cache_debug(s) && unlikely(!prior)) { - remove_full(s, page); - add_partial(n, page, DEACTIVATE_TO_TAIL); - stat(s, FREE_ADD_PARTIAL); + if (was_frozen) + stat(s, FREE_FROZEN); + else { + if (unlikely(!inuse && n->nr_partial > s->min_partial)) + goto slab_empty; + + /* + * Objects left in the slab. If it was not on the partial list before + * then add it. + */ + if (unlikely(!prior)) { + remove_full(s, page); + add_partial(n, page, DEACTIVATE_TO_TAIL); + stat(s, FREE_ADD_PARTIAL); + } } spin_unlock_irqrestore(&n->list_lock, flags); return; @@ -2610,10 +2599,12 @@ static __always_inline void slab_free(struct kmem_cache *s, void kmem_cache_free(struct kmem_cache *s, void *x) { - s = cache_from_obj(s, x); - if (!s) - return; - slab_free(s, virt_to_head_page(x), x, _RET_IP_); + struct page *page; + + page = virt_to_head_page(x); + + slab_free(s, page, x, _RET_IP_); + trace_kmem_cache_free(_RET_IP_, x); } EXPORT_SYMBOL(kmem_cache_free); @@ -2751,6 +2742,32 @@ static inline int calculate_order(int size, int reserved) return -ENOSYS; } +/* + * Figure out what the alignment of the objects will be. + */ +static unsigned long calculate_alignment(unsigned long flags, + unsigned long align, unsigned long size) +{ + /* + * If the user wants hardware cache aligned objects then follow that + * suggestion if the object is sufficiently large. + * + * The hardware cache alignment cannot override the specified + * alignment though. If that is greater then use it. + */ + if (flags & SLAB_HWCACHE_ALIGN) { + unsigned long ralign = cache_line_size(); + while (size <= ralign / 2) + ralign /= 2; + align = max(align, ralign); + } + + if (align < ARCH_SLAB_MINALIGN) + align = ARCH_SLAB_MINALIGN; + + return ALIGN(align, sizeof(void *)); +} + static void init_kmem_cache_node(struct kmem_cache_node *n, struct kmem_cache *s) { @@ -2883,7 +2900,8 @@ static void set_min_partial(struct kmem_cache *s, unsigned long min) static int calculate_sizes(struct kmem_cache *s, int forced_order) { unsigned long flags = s->flags; - unsigned long size = s->object_size; + unsigned long size = s->objsize; + unsigned long align = s->align; int order; /* @@ -2911,7 +2929,7 @@ static int calculate_sizes(struct kmem_cache *s, int forced_order) * end of the object and the free pointer. If not then add an * additional word to have some bytes to store Redzone information. */ - if ((flags & SLAB_RED_ZONE) && size == s->object_size) + if ((flags & SLAB_RED_ZONE) && size == s->objsize) size += sizeof(void *); #endif @@ -2954,12 +2972,20 @@ static int calculate_sizes(struct kmem_cache *s, int forced_order) size += sizeof(void *); #endif + /* + * Determine the alignment based on various parameters that the + * user specified and the dynamic determination of cache line size + * on bootup. + */ + align = calculate_alignment(flags, align, s->objsize); + s->align = align; + /* * SLUB stores one object immediately after another beginning from * offset 0. In order to align the objects we have to simply size * each object to conform to the alignment. */ - size = ALIGN(size, s->align); + size = ALIGN(size, align); s->size = size; if (forced_order >= 0) order = forced_order; @@ -2988,11 +3014,20 @@ static int calculate_sizes(struct kmem_cache *s, int forced_order) s->max = s->oo; return !!oo_objects(s->oo); + } -static int kmem_cache_open(struct kmem_cache *s, unsigned long flags) +static int kmem_cache_open(struct kmem_cache *s, + const char *name, size_t size, + size_t align, unsigned long flags, + void (*ctor)(void *)) { - s->flags = kmem_cache_flags(s->size, flags, s->name, s->ctor); + memset(s, 0, kmem_size); + s->name = name; + s->ctor = ctor; + s->objsize = size; + s->align = align; + s->flags = kmem_cache_flags(size, flags, name, ctor); s->reserved = 0; if (need_reserve_slab_rcu && (s->flags & SLAB_DESTROY_BY_RCU)) @@ -3005,7 +3040,7 @@ static int kmem_cache_open(struct kmem_cache *s, unsigned long flags) * Disable debugging flags that store metadata if the min slab * order increased. */ - if (get_order(s->size) > get_order(s->object_size)) { + if (get_order(s->size) > get_order(s->objsize)) { s->flags &= ~DEBUG_METADATA_FLAGS; s->offset = 0; if (!calculate_sizes(s, -1)) @@ -3054,6 +3089,7 @@ static int kmem_cache_open(struct kmem_cache *s, unsigned long flags) else s->cpu_partial = 30; + s->refcount = 1; #ifdef CONFIG_NUMA s->remote_node_defrag_ratio = 1000; #endif @@ -3061,17 +3097,26 @@ static int kmem_cache_open(struct kmem_cache *s, unsigned long flags) goto error; if (alloc_kmem_cache_cpus(s)) - return 0; + return 1; free_kmem_cache_nodes(s); error: if (flags & SLAB_PANIC) panic("Cannot create slab %s size=%lu realsize=%u " "order=%u offset=%u flags=%lx\n", - s->name, (unsigned long)s->size, s->size, oo_order(s->oo), + s->name, (unsigned long)size, s->size, oo_order(s->oo), s->offset, flags); - return -EINVAL; + return 0; +} + +/* + * Determine the size of a slab object + */ +unsigned int kmem_cache_size(struct kmem_cache *s) +{ + return s->objsize; } +EXPORT_SYMBOL(kmem_cache_size); static void list_slab_objects(struct kmem_cache *s, struct page *page, const char *text) @@ -3083,7 +3128,7 @@ static void list_slab_objects(struct kmem_cache *s, struct page *page, sizeof(long), GFP_ATOMIC); if (!map) return; - slab_err(s, page, text, s->name); + slab_err(s, page, "%s", text); slab_lock(page); get_map(s, page, map); @@ -3115,7 +3160,7 @@ static void free_partial(struct kmem_cache *s, struct kmem_cache_node *n) discard_slab(s, page); } else { list_slab_objects(s, page, - "Objects remaining in %s on kmem_cache_close()"); + "Objects remaining on kmem_cache_close()"); } } } @@ -3128,6 +3173,7 @@ static inline int kmem_cache_close(struct kmem_cache *s) int node; flush_all(s); + free_percpu(s->cpu_slab); /* Attempt to free all objects */ for_each_node_state(node, N_NORMAL_MEMORY) { struct kmem_cache_node *n = get_node(s, node); @@ -3136,20 +3182,33 @@ static inline int kmem_cache_close(struct kmem_cache *s) if (n->nr_partial || slabs_node(s, node)) return 1; } - free_percpu(s->cpu_slab); free_kmem_cache_nodes(s); return 0; } -int __kmem_cache_shutdown(struct kmem_cache *s) -{ - int rc = kmem_cache_close(s); - - if (!rc) +/* + * Close a cache and release the kmem_cache structure + * (must be used for caches created using kmem_cache_create) + */ +void kmem_cache_destroy(struct kmem_cache *s) +{ + down_write(&slub_lock); + s->refcount--; + if (!s->refcount) { + list_del(&s->list); + up_write(&slub_lock); + if (kmem_cache_close(s)) { + printk(KERN_ERR "SLUB %s: %s called for cache that " + "still has objects.\n", s->name, __func__); + dump_stack(); + } + if (s->flags & SLAB_DESTROY_BY_RCU) + rcu_barrier(); sysfs_slab_remove(s); - - return rc; + } else + up_write(&slub_lock); } +EXPORT_SYMBOL(kmem_cache_destroy); /******************************************************************** * Kmalloc subsystem @@ -3158,6 +3217,8 @@ int __kmem_cache_shutdown(struct kmem_cache *s) struct kmem_cache *kmalloc_caches[SLUB_PAGE_SHIFT]; EXPORT_SYMBOL(kmalloc_caches); +static struct kmem_cache *kmem_cache; + #ifdef CONFIG_ZONE_DMA static struct kmem_cache *kmalloc_dma_caches[SLUB_PAGE_SHIFT]; #endif @@ -3198,6 +3259,29 @@ static int __init setup_slub_nomerge(char *str) __setup("slub_nomerge", setup_slub_nomerge); +static struct kmem_cache *__init create_kmalloc_cache(const char *name, + int size, unsigned int flags) +{ + struct kmem_cache *s; + + s = kmem_cache_alloc(kmem_cache, GFP_NOWAIT); + + /* + * This function is called with IRQs disabled during early-boot on + * single CPU so there's no need to take slub_lock here. + */ + if (!kmem_cache_open(s, name, size, ARCH_KMALLOC_MINALIGN, + flags, NULL)) + goto panic; + + list_add(&s->list, &slab_caches); + return s; + +panic: + panic("Creation of kmalloc slab %s size=%d failed.\n", name, size); + return NULL; +} + /* * Conversion table for small slabs sizes / 8 to the index in the * kmalloc array. This is necessary for slabs < 192 since we have non power @@ -3269,7 +3353,7 @@ void *__kmalloc(size_t size, gfp_t flags) if (unlikely(ZERO_OR_NULL_PTR(s))) return s; - ret = slab_alloc(s, flags, _RET_IP_); + ret = slab_alloc(s, flags, NUMA_NO_NODE, _RET_IP_); trace_kmalloc(_RET_IP_, ret, size, s->size, flags); @@ -3312,7 +3396,7 @@ void *__kmalloc_node(size_t size, gfp_t flags, int node) if (unlikely(ZERO_OR_NULL_PTR(s))) return s; - ret = slab_alloc_node(s, flags, node, _RET_IP_); + ret = slab_alloc(s, flags, node, _RET_IP_); trace_kmalloc_node(_RET_IP_, ret, size, s->size, flags, node); @@ -3335,7 +3419,7 @@ size_t ksize(const void *object) return PAGE_SIZE << compound_order(page); } - return slab_ksize(page->slab_cache); + return slab_ksize(page->slab); } EXPORT_SYMBOL(ksize); @@ -3360,8 +3444,8 @@ bool verify_mem_not_deleted(const void *x) } slab_lock(page); - if (on_freelist(page->slab_cache, page, object)) { - object_err(page->slab_cache, page, object, "Object is on free-list"); + if (on_freelist(page->slab, page, object)) { + object_err(page->slab, page, object, "Object is on free-list"); rv = false; } else { rv = true; @@ -3389,10 +3473,10 @@ void kfree(const void *x) if (unlikely(!PageSlab(page))) { BUG_ON(!PageCompound(page)); kmemleak_free(x); - __free_pages(page, compound_order(page)); + put_page(page); return; } - slab_free(page->slab_cache, page, object, _RET_IP_); + slab_free(page->slab, page, object, _RET_IP_); } EXPORT_SYMBOL(kfree); @@ -3469,10 +3553,10 @@ static int slab_mem_going_offline_callback(void *arg) { struct kmem_cache *s; - mutex_lock(&slab_mutex); + down_read(&slub_lock); list_for_each_entry(s, &slab_caches, list) kmem_cache_shrink(s); - mutex_unlock(&slab_mutex); + up_read(&slub_lock); return 0; } @@ -3484,7 +3568,7 @@ static void slab_mem_offline_callback(void *arg) struct memory_notify *marg = arg; int offline_node; - offline_node = marg->status_change_nid_normal; + offline_node = marg->status_change_nid; /* * If the node still has available memory. we need kmem_cache_node @@ -3493,7 +3577,7 @@ static void slab_mem_offline_callback(void *arg) if (offline_node < 0) return; - mutex_lock(&slab_mutex); + down_read(&slub_lock); list_for_each_entry(s, &slab_caches, list) { n = get_node(s, offline_node); if (n) { @@ -3509,7 +3593,7 @@ static void slab_mem_offline_callback(void *arg) kmem_cache_free(kmem_cache_node, n); } } - mutex_unlock(&slab_mutex); + up_read(&slub_lock); } static int slab_mem_going_online_callback(void *arg) @@ -3517,7 +3601,7 @@ static int slab_mem_going_online_callback(void *arg) struct kmem_cache_node *n; struct kmem_cache *s; struct memory_notify *marg = arg; - int nid = marg->status_change_nid_normal; + int nid = marg->status_change_nid; int ret = 0; /* @@ -3532,7 +3616,7 @@ static int slab_mem_going_online_callback(void *arg) * allocate a kmem_cache_node structure in order to bring the node * online. */ - mutex_lock(&slab_mutex); + down_read(&slub_lock); list_for_each_entry(s, &slab_caches, list) { /* * XXX: kmem_cache_alloc_node will fallback to other nodes @@ -3548,7 +3632,7 @@ static int slab_mem_going_online_callback(void *arg) s->node[nid] = n; } out: - mutex_unlock(&slab_mutex); + up_read(&slub_lock); return ret; } @@ -3587,16 +3671,15 @@ static int slab_memory_callback(struct notifier_block *self, /* * Used for early kmem_cache structures that were allocated using - * the page allocator. Allocate them properly then fix up the pointers - * that may be pointing to the wrong kmem_cache structure. + * the page allocator */ -static struct kmem_cache * __init bootstrap(struct kmem_cache *static_cache) +static void __init kmem_cache_bootstrap_fixup(struct kmem_cache *s) { int node; - struct kmem_cache *s = kmem_cache_zalloc(kmem_cache, GFP_NOWAIT); - memcpy(s, static_cache, kmem_cache->object_size); + list_add(&s->list, &slab_caches); + s->refcount = -1; for_each_node_state(node, N_NORMAL_MEMORY) { struct kmem_cache_node *n = get_node(s, node); @@ -3604,52 +3687,75 @@ static struct kmem_cache * __init bootstrap(struct kmem_cache *static_cache) if (n) { list_for_each_entry(p, &n->partial, lru) - p->slab_cache = s; + p->slab = s; #ifdef CONFIG_SLUB_DEBUG list_for_each_entry(p, &n->full, lru) - p->slab_cache = s; + p->slab = s; #endif } } - list_add(&s->list, &slab_caches); - return s; } void __init kmem_cache_init(void) { - static __initdata struct kmem_cache boot_kmem_cache, - boot_kmem_cache_node; int i; - int caches = 2; + int caches = 0; + struct kmem_cache *temp_kmem_cache; + int order; + struct kmem_cache *temp_kmem_cache_node; + unsigned long kmalloc_size; if (debug_guardpage_minorder()) slub_max_order = 0; - kmem_cache_node = &boot_kmem_cache_node; - kmem_cache = &boot_kmem_cache; + kmem_size = offsetof(struct kmem_cache, node) + + nr_node_ids * sizeof(struct kmem_cache_node *); + + /* Allocate two kmem_caches from the page allocator */ + kmalloc_size = ALIGN(kmem_size, cache_line_size()); + order = get_order(2 * kmalloc_size); + kmem_cache = (void *)__get_free_pages(GFP_NOWAIT, order); + + /* + * Must first have the slab cache available for the allocations of the + * struct kmem_cache_node's. There is special bootstrap code in + * kmem_cache_open for slab_state == DOWN. + */ + kmem_cache_node = (void *)kmem_cache + kmalloc_size; - create_boot_cache(kmem_cache_node, "kmem_cache_node", - sizeof(struct kmem_cache_node), SLAB_HWCACHE_ALIGN); + kmem_cache_open(kmem_cache_node, "kmem_cache_node", + sizeof(struct kmem_cache_node), + 0, SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL); hotplug_memory_notifier(slab_memory_callback, SLAB_CALLBACK_PRI); /* Able to allocate the per node structures */ slab_state = PARTIAL; - create_boot_cache(kmem_cache, "kmem_cache", - offsetof(struct kmem_cache, node) + - nr_node_ids * sizeof(struct kmem_cache_node *), - SLAB_HWCACHE_ALIGN); - - kmem_cache = bootstrap(&boot_kmem_cache); + temp_kmem_cache = kmem_cache; + kmem_cache_open(kmem_cache, "kmem_cache", kmem_size, + 0, SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL); + kmem_cache = kmem_cache_alloc(kmem_cache, GFP_NOWAIT); + memcpy(kmem_cache, temp_kmem_cache, kmem_size); /* * Allocate kmem_cache_node properly from the kmem_cache slab. * kmem_cache_node is separately allocated so no need to * update any list pointers. */ - kmem_cache_node = bootstrap(&boot_kmem_cache_node); + temp_kmem_cache_node = kmem_cache_node; + + kmem_cache_node = kmem_cache_alloc(kmem_cache, GFP_NOWAIT); + memcpy(kmem_cache_node, temp_kmem_cache_node, kmem_size); + + kmem_cache_bootstrap_fixup(kmem_cache_node); + + caches++; + kmem_cache_bootstrap_fixup(kmem_cache); + caches++; + /* Free temporary boot structure */ + free_pages((unsigned long)temp_kmem_cache, order); /* Now we can use the kmem_cache to allocate kmalloc slabs */ @@ -3737,11 +3843,11 @@ void __init kmem_cache_init(void) if (s && s->size) { char *name = kasprintf(GFP_NOWAIT, - "dma-kmalloc-%d", s->object_size); + "dma-kmalloc-%d", s->objsize); BUG_ON(!name); kmalloc_dma_caches[i] = create_kmalloc_cache(name, - s->object_size, SLAB_CACHE_DMA); + s->objsize, SLAB_CACHE_DMA); } } #endif @@ -3818,11 +3924,16 @@ static struct kmem_cache *find_mergeable(size_t size, return NULL; } -struct kmem_cache *__kmem_cache_alias(const char *name, size_t size, +struct kmem_cache *kmem_cache_create(const char *name, size_t size, size_t align, unsigned long flags, void (*ctor)(void *)) { struct kmem_cache *s; + char *n; + if (WARN_ON(!name)) + return NULL; + + down_write(&slub_lock); s = find_mergeable(size, align, flags, name, ctor); if (s) { s->refcount++; @@ -3830,39 +3941,49 @@ struct kmem_cache *__kmem_cache_alias(const char *name, size_t size, * Adjust the object sizes so that we clear * the complete object on kzalloc. */ - s->object_size = max(s->object_size, (int)size); + s->objsize = max(s->objsize, (int)size); s->inuse = max_t(int, s->inuse, ALIGN(size, sizeof(void *))); if (sysfs_slab_alias(s, name)) { s->refcount--; - s = NULL; + goto err; } + up_write(&slub_lock); + return s; } - return s; -} - -int __kmem_cache_create(struct kmem_cache *s, unsigned long flags) -{ - int err; - - err = kmem_cache_open(s, flags); - if (err) - return err; - - /* Mutex is not taken during early boot */ - if (slab_state <= UP) - return 0; + n = kstrdup(name, GFP_KERNEL); + if (!n) + goto err; - mutex_unlock(&slab_mutex); - err = sysfs_slab_add(s); - mutex_lock(&slab_mutex); - - if (err) - kmem_cache_close(s); + s = kmalloc(kmem_size, GFP_KERNEL); + if (s) { + if (kmem_cache_open(s, n, + size, align, flags, ctor)) { + list_add(&s->list, &slab_caches); + up_write(&slub_lock); + if (sysfs_slab_add(s)) { + down_write(&slub_lock); + list_del(&s->list); + kfree(n); + kfree(s); + goto err; + } + return s; + } + kfree(s); + } + kfree(n); +err: + up_write(&slub_lock); - return err; + if (flags & SLAB_PANIC) + panic("Cannot create slabcache %s\n", name); + else + s = NULL; + return s; } +EXPORT_SYMBOL(kmem_cache_create); #ifdef CONFIG_SMP /* @@ -3881,13 +4002,13 @@ static int slab_cpuup_callback(struct notifier_block *nfb, case CPU_UP_CANCELED_FROZEN: case CPU_DEAD: case CPU_DEAD_FROZEN: - mutex_lock(&slab_mutex); + down_read(&slub_lock); list_for_each_entry(s, &slab_caches, list) { local_irq_save(flags); __flush_cpu_slab(s, cpu); local_irq_restore(flags); } - mutex_unlock(&slab_mutex); + up_read(&slub_lock); break; default: break; @@ -3914,7 +4035,7 @@ void *__kmalloc_track_caller(size_t size, gfp_t gfpflags, unsigned long caller) if (unlikely(ZERO_OR_NULL_PTR(s))) return s; - ret = slab_alloc(s, gfpflags, caller); + ret = slab_alloc(s, gfpflags, NUMA_NO_NODE, caller); /* Honor the call site pointer we received. */ trace_kmalloc(caller, ret, size, s->size, gfpflags); @@ -3944,7 +4065,7 @@ void *__kmalloc_node_track_caller(size_t size, gfp_t gfpflags, if (unlikely(ZERO_OR_NULL_PTR(s))) return s; - ret = slab_alloc_node(s, gfpflags, node, caller); + ret = slab_alloc(s, gfpflags, node, caller); /* Honor the call site pointer we received. */ trace_kmalloc_node(caller, ret, size, s->size, gfpflags, node); @@ -4379,31 +4500,30 @@ static ssize_t show_slab_objects(struct kmem_cache *s, for_each_possible_cpu(cpu) { struct kmem_cache_cpu *c = per_cpu_ptr(s->cpu_slab, cpu); - int node; + int node = ACCESS_ONCE(c->node); struct page *page; - page = ACCESS_ONCE(c->page); - if (!page) + if (node < 0) continue; + page = ACCESS_ONCE(c->page); + if (page) { + if (flags & SO_TOTAL) + x = page->objects; + else if (flags & SO_OBJECTS) + x = page->inuse; + else + x = 1; - node = page_to_nid(page); - if (flags & SO_TOTAL) - x = page->objects; - else if (flags & SO_OBJECTS) - x = page->inuse; - else - x = 1; - - total += x; - nodes[node] += x; + total += x; + nodes[node] += x; + } + page = c->partial; - page = ACCESS_ONCE(c->partial); if (page) { x = page->pobjects; total += x; nodes[node] += x; } - per_cpu[node]++; } } @@ -4503,7 +4623,7 @@ SLAB_ATTR_RO(align); static ssize_t object_size_show(struct kmem_cache *s, char *buf) { - return sprintf(buf, "%d\n", s->object_size); + return sprintf(buf, "%d\n", s->objsize); } SLAB_ATTR_RO(object_size); @@ -5091,6 +5211,14 @@ static ssize_t slab_attr_store(struct kobject *kobj, return err; } +static void kmem_cache_release(struct kobject *kobj) +{ + struct kmem_cache *s = to_slab(kobj); + + kfree(s->name); + kfree(s); +} + static const struct sysfs_ops slab_sysfs_ops = { .show = slab_attr_show, .store = slab_attr_store, @@ -5098,6 +5226,7 @@ static const struct sysfs_ops slab_sysfs_ops = { static struct kobj_type slab_ktype = { .sysfs_ops = &slab_sysfs_ops, + .release = kmem_cache_release }; static int uevent_filter(struct kset *kset, struct kobject *kobj) @@ -5155,8 +5284,13 @@ static int sysfs_slab_add(struct kmem_cache *s) { int err; const char *name; - int unmergeable = slab_unmergeable(s); + int unmergeable; + + if (slab_state < SYSFS) + /* Defer until later */ + return 0; + unmergeable = slab_unmergeable(s); if (unmergeable) { /* * Slabcache can never be merged so we can use the name proper. @@ -5197,7 +5331,7 @@ static int sysfs_slab_add(struct kmem_cache *s) static void sysfs_slab_remove(struct kmem_cache *s) { - if (slab_state < FULL) + if (slab_state < SYSFS) /* * Sysfs has not been setup yet so no need to remove the * cache from sysfs. @@ -5225,7 +5359,7 @@ static int sysfs_slab_alias(struct kmem_cache *s, const char *name) { struct saved_alias *al; - if (slab_state == FULL) { + if (slab_state == SYSFS) { /* * If we have a leftover link then remove it. */ @@ -5249,16 +5383,16 @@ static int __init slab_sysfs_init(void) struct kmem_cache *s; int err; - mutex_lock(&slab_mutex); + down_write(&slub_lock); slab_kset = kset_create_and_add("slab", &slab_uevent_ops, kernel_kobj); if (!slab_kset) { - mutex_unlock(&slab_mutex); + up_write(&slub_lock); printk(KERN_ERR "Cannot register slab subsystem.\n"); return -ENOSYS; } - slab_state = FULL; + slab_state = SYSFS; list_for_each_entry(s, &slab_caches, list) { err = sysfs_slab_add(s); @@ -5274,11 +5408,11 @@ static int __init slab_sysfs_init(void) err = sysfs_slab_alias(al->s, al->name); if (err) printk(KERN_ERR "SLUB: Unable to add boot slab alias" - " %s to sysfs\n", al->name); + " %s to sysfs\n", s->name); kfree(al); } - mutex_unlock(&slab_mutex); + up_write(&slub_lock); resiliency_test(); return 0; } @@ -5290,14 +5424,49 @@ __initcall(slab_sysfs_init); * The /proc/slabinfo ABI */ #ifdef CONFIG_SLABINFO -void get_slabinfo(struct kmem_cache *s, struct slabinfo *sinfo) +static void print_slabinfo_header(struct seq_file *m) +{ + seq_puts(m, "slabinfo - version: 2.1\n"); + seq_puts(m, "# name " + " "); + seq_puts(m, " : tunables "); + seq_puts(m, " : slabdata "); + seq_putc(m, '\n'); +} + +static void *s_start(struct seq_file *m, loff_t *pos) +{ + loff_t n = *pos; + + down_read(&slub_lock); + if (!n) + print_slabinfo_header(m); + + return seq_list_start(&slab_caches, *pos); +} + +static void *s_next(struct seq_file *m, void *p, loff_t *pos) +{ + return seq_list_next(p, &slab_caches, pos); +} + +static void s_stop(struct seq_file *m, void *p) +{ + up_read(&slub_lock); +} + +static int s_show(struct seq_file *m, void *p) { unsigned long nr_partials = 0; unsigned long nr_slabs = 0; + unsigned long nr_inuse = 0; unsigned long nr_objs = 0; unsigned long nr_free = 0; + struct kmem_cache *s; int node; + s = list_entry(p, struct kmem_cache, list); + for_each_online_node(node) { struct kmem_cache_node *n = get_node(s, node); @@ -5310,21 +5479,41 @@ void get_slabinfo(struct kmem_cache *s, struct slabinfo *sinfo) nr_free += count_partial(n, count_free); } - sinfo->active_objs = nr_objs - nr_free; - sinfo->num_objs = nr_objs; - sinfo->active_slabs = nr_slabs; - sinfo->num_slabs = nr_slabs; - sinfo->objects_per_slab = oo_objects(s->oo); - sinfo->cache_order = oo_order(s->oo); + nr_inuse = nr_objs - nr_free; + + seq_printf(m, "%-17s %6lu %6lu %6u %4u %4d", s->name, nr_inuse, + nr_objs, s->size, oo_objects(s->oo), + (1 << oo_order(s->oo))); + seq_printf(m, " : tunables %4u %4u %4u", 0, 0, 0); + seq_printf(m, " : slabdata %6lu %6lu %6lu", nr_slabs, nr_slabs, + 0UL); + seq_putc(m, '\n'); + return 0; } -void slabinfo_show_stats(struct seq_file *m, struct kmem_cache *s) +static const struct seq_operations slabinfo_op = { + .start = s_start, + .next = s_next, + .stop = s_stop, + .show = s_show, +}; + +static int slabinfo_open(struct inode *inode, struct file *file) { + return seq_open(file, &slabinfo_op); } -ssize_t slabinfo_write(struct file *file, const char __user *buffer, - size_t count, loff_t *ppos) +static const struct file_operations proc_slabinfo_operations = { + .open = slabinfo_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; + +static int __init slab_proc_init(void) { - return -EIO; + proc_create("slabinfo", S_IRUSR, NULL, &proc_slabinfo_operations); + return 0; } +module_init(slab_proc_init); #endif /* CONFIG_SLABINFO */ From 0e10e6c50c5d9198d6b84c2af3ba27880738114f Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Mon, 13 Jan 2014 03:29:31 +0100 Subject: [PATCH 137/215] Buildscript : Cleanup Signed-off-by: Tk-Glitch --- glitch.sh | 33 ---------- release/Flashable-flo-AOSP4CM/.gitignore | 1 - .../META-INF/com/google/android/update-binary | Bin 194596 -> 0 bytes .../com/google/android/updater-script | 39 ----------- release/zimage/kernel/busybox | Bin 478912 -> 0 bytes release/zimage/kernel/compatibility.sh | 9 --- release/zimage/kernel/edit_ramdisk.sh | 61 ------------------ release/zimage/kernel/mkbootimg | Bin 64076 -> 0 bytes release/zimage/kernel/mkbootimg.sh | 6 -- release/zimage/kernel/unpackbootimg | Bin 58952 -> 0 bytes 10 files changed, 149 deletions(-) delete mode 100644 release/Flashable-flo-AOSP4CM/.gitignore delete mode 100755 release/zimage/META-INF/com/google/android/update-binary delete mode 100755 release/zimage/META-INF/com/google/android/updater-script delete mode 100644 release/zimage/kernel/busybox delete mode 100644 release/zimage/kernel/compatibility.sh delete mode 100644 release/zimage/kernel/edit_ramdisk.sh delete mode 100644 release/zimage/kernel/mkbootimg delete mode 100644 release/zimage/kernel/mkbootimg.sh delete mode 100644 release/zimage/kernel/unpackbootimg diff --git a/glitch.sh b/glitch.sh index ffca2dac8f1..0475be7b485 100755 --- a/glitch.sh +++ b/glitch.sh @@ -81,16 +81,6 @@ cd release/aroma . $KERNEL_DIR/../rev -if [ "$cm" = "y" ] ; then - -mkdir -p $KERNEL_DIR/release/Flashable-flo-AOSP4CM -REL=Glitch-N7-r$counter-AOSP4CM.zip - - zip -q -r ${REL} boot config META-INF system - #sha256sum ${REL} > ${REL}.sha256sum - mv ${REL}* $KERNEL_DIR/release/Flashable-flo-AOSP4CM/ -else - counter=$((counter + 1)) mkdir -p $KERNEL_DIR/release/Flashable-flo-AOSP @@ -102,8 +92,6 @@ REL=Glitch-N7-r$counter.zip echo counter=$counter > $KERNEL_DIR/../rev; -fi - rm boot/glitch.zImage rm -r system/lib/modules/* cd $KERNEL_DIR @@ -131,26 +119,6 @@ if [ "$1" = cleank ] ; then else -if [ "$1" = cm ] ; then - -cm="y" - - git apply ../AOSPpatch - echo "--------------------------------------------------------" - echo "--------------Patched tree for CM compat----------------" - echo "--------------------------------------------------------" - -time { - build flo -} - - git apply --reverse ../AOSPpatch - echo "--------------------------------------------------------" - echo "---------------Patched tree back to AOSP----------------" - echo "--------------------------------------------------------" - -else - time { build flo @@ -158,4 +126,3 @@ time { } fi fi -fi diff --git a/release/Flashable-flo-AOSP4CM/.gitignore b/release/Flashable-flo-AOSP4CM/.gitignore deleted file mode 100644 index c4c4ffc6aa4..00000000000 --- a/release/Flashable-flo-AOSP4CM/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*.zip diff --git a/release/zimage/META-INF/com/google/android/update-binary b/release/zimage/META-INF/com/google/android/update-binary deleted file mode 100755 index cb5fefe55b57ff337165a1f49c05bc4d42e45134..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 194596 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

        |Op$sg6ZA9Y&&;4ARlY#HsNZFe5lu~7eD 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 N{^(I_T~9r^{{a);no$4% diff --git a/release/zimage/META-INF/com/google/android/updater-script b/release/zimage/META-INF/com/google/android/updater-script deleted file mode 100755 index c9839fc1e0d..00000000000 --- a/release/zimage/META-INF/com/google/android/updater-script +++ /dev/null @@ -1,39 +0,0 @@ -ui_print("---------------------------------------"); -ui_print("| Glitch kernel for flo |"); -ui_print("---------------------------------------"); -ui_print("Nexus 7 (2013) Kernel..."); -set_progress(1.000000); -ui_print("Mount /System Folder..."); -mount("ext4", "EMMC", "/dev/block/mmcblk0p22", "/system"); -ui_print("Extracting System Files..."); -package_extract_dir("system", "/system"); -ui_print("Extracting Kernel files..."); -package_extract_dir("kernel", "/tmp"); -set_perm(0, 0, 0777, "/tmp/compatibility.sh"); -set_perm(0, 0, 0777, "/tmp/edit_ramdisk.sh"); -set_perm(0, 0, 0777, "/tmp/mkbootimg.sh"); -set_perm(0, 0, 0777, "/tmp/mkbootimg"); -set_perm(0, 0, 0777, "/tmp/unpackbootimg"); -set_perm(0, 0, 0777, "/tmp/busybox"); - -ui_print("Installing kernel..."); -run_program("/tmp/busybox", "dd", "if=/dev/block/mmcblk0p14", "of=/tmp/boot.img"); -run_program("/tmp/unpackbootimg", "-i", "/tmp/boot.img", "-o", "/tmp/"); - -################RAMDISK EDITS -ui_print("Fixing your ramdisk..."); -ui_print(" removing governor overrides..."); -ui_print(" Looking for busybox..."); -run_program("/tmp/edit_ramdisk.sh"); -set_progress(0.65); - -run_program("/tmp/mkbootimg.sh"); -run_program("/tmp/busybox", "dd", "if=/tmp/newboot.img", "of=/dev/block/mmcblk0p14"); - - -################RENAME thermald & mpdecision -ui_print("Renaming binaries..."); -ui_print(" /system/bin/mpdecision -> mpdecision_bck"); -run_program("/tmp/compatibility.sh"); - -unmount("/system"); diff --git a/release/zimage/kernel/busybox b/release/zimage/kernel/busybox deleted file mode 100644 index e7acacfb6249eb7eefa5e3f41edb2e41ca3d3198..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 478912 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%0DXC$1QXP&&&C zMuntpndYO&YsdmIT>(jobb^fy-y6-T_?|EQN2c+pZNlfO5v7B&DHuHy{6VF(hWCQu zWxtzZv-VdfBaVE3I8$an$1=By#ZF_^bLAfnq2Xw>me*ygJiU zjEu!*`2;d}g_I*bJl4F-xC7$m%pcG8at?}UPm}NG$V^D89kG4G5bFhrypJQz*nW!b z%h={%YdbVMo;Z8Qc>eZ*m2JxX$bH40Bla-)zk|%ggs9Exk}+nW!-!*}x}={;>ml6j z15e_vV`JPgqOCjw)}<p(-;)TaVXdZqiob zPR|N3TN5*lV_J?q274$?&$7a0xy!YvH_9uauQt>qLeGnAm;pV5Y&FZXdy4ShZ-vsm zQ$=$;o_Q6X%i(lyRF^Ufq5skB797o)7k;qA%)@4#0K28e#IhNd61w(_rFm6+$;l`E zqxwc;V{LNZcnm;-k4c>iKF9BS48ZVN#NERDSdw6NKTNOLXF)ba+&r^Hn3+5j8R)0u ze}3{TUsf_FJ(fJ!$DUrCJlJoLmL;>k70Lbm7OM9?mo6PIUF@}#9;2&=Zfk(ZIToyLX6n2Jay6^c>!;oN%4%(^1hkn zZ@N>3+?;V*$)@K(XVDmgoL;*&7KHZ{xAsOrU?u$clR{zJjaA=Xg`KVGtpIU;dzE)` zjU>R1)zuyojnJjo;Q6aOQ`q*1)z)rhGdc)o6X^NT!jp)|I<5@5y04WST`-#?3n6d5 z%aTV>&r2YSASn>4XOm-%Q*sNTXG10&3ePtKbAqw74v|m-#j*SzH0LuyP8=QQ=6WLS zB%q_?T#{{dl$XxGX8DnBmvHaLCuVV^GL|PEY|)m$Q@KePluL%wSph4jaTxC(<0qJa z=x|}~&s1$*k}}|@aRM_wa)OZa`$>|bJ8Q`;hW2Nc@9wrpG!LFx-iRpL&^VfPHUsVG zeOMJJs*iFp<6gDB_XCHlJKWY@dAFT}Rg{Ev7|nE#eP>GXe2;B)E%NMAHFQl}o-VQF}ostRX>V+Gn;oi}YkN3Jt+e(&|vH{Y~1*~_N zd)rr# z(6Plt$L%GPN(MwPh|5q%r`sh*#g!Epk&U<_qB*QwHGZ|eyc#Q=LA+kGR4^?MVx6LI z563D6*N}QwD%5%rzC<6*+H^A=g5Ef8>f#%t=A8apm2s`0JUgc>=%u2K{#eGcKd2O;tfI04m z_3|;L9`=LG*fnB0a>NoR_^QELf2A}POnq%48(=ziWllWmK-LLdo1d2x)i<9!@85(x zEnaxV2AqGVB+_vyh6$J+czVW{uvv#-y%CmIrzc>z}RFE{)DEoPqi! zU_wR>o8|u9S4!>PvB>;vM`?xQ%GRBBPY)@7!^(PpjVeVHSP1((l6BoGg3=# zDC0Ys_%BtrncV)*N^-k()t8u^zf_ARKd&xHvJGtp%Tj`aV)=fA4`PAF(n~#jk@9TS zaC_^2X<4GNe!O_5*WUZd5O9V(%aVwhn3EwENU#7HxoFsCAs^&(WDI01FpZBI ztgUO_7ImYzbEnj~W^VOaj~&l;MU9NdbFG5rl8t9u2_8E$T}e<396$LBy!-4}Qy$d= z>3sQ$I6wAfw_ck&H;Ee@)W)!`r|jdYxJUOO;JYAnF5jO23NUWlXR+_UK5tENir8J; zsNMffv4-^P2q$*gz`fhfg<+&K(k=TQ<+-6qfOOehm5v$?D$fS_+xBJDOZ;lyt6Ic> zrNe5uD0I3HyDtc9-Oor5!!PArO_G=U<`2W{jg=Bs;9A58Nm}H4KH2R9UalmlxI#EH z1=cXlmReuV@U{v%u0dC{o1*CGR;22nxmt@iMb&3=-yepz$SjZPEMEQQ>PxG0g{S6` z%|YecP}w}3XUmKQTDW;`%yHpOWa!={jF9M2WQ?=dWU?pI<{>l0nU(WW=T&76K3$VJ z@FX3v=L@Q6mW`eCES%kvHgDy;SI}dlg+)0jM?Y<6nNQoT%*#OWFeZN7#FDC`^Q!&;Cguk6oqT@{+ktW+3U3+*U)iIKzf`~w}EdB~( zp%xTe^{J{(rQ#AP!5UqODh^P z`I8T-i8j0iO5)-&RbzSv|I!dLI#nfU;=c${uIl40gbMJ#i z#w@Q=_0j>v`*J>NFEY!^)UFch4_Qt9A&4oY{bPXK5=0;W(;sr`RB!+I2yO85JdSLE zY|5o^E64*6se-^iGF>M`2sMJUz#w02r)&M>DE{_OPr-MTq8Dgx zVkK`K34a1h+mIcW;VjyI;AI${els*Fyqz&RN{sCmF)t_LG`U@g8B4gj0nyBKY|p$p zPgsxrV@mDSm*9Ewz)Dsn41&GCCh0T5958l;HLi?x0~tI%lvKV^FnjG|IjIsk4wK@i z#Y?4lqSz^7*+B-n1@wyMYL%4=+rnpsw_8Tn0GEg@15KkD>(0k7h^w-r1Y@nK?putX z82_)D8ZZ}Fn0BM}f~d_pN8Q4H*kz9?cdi&4={#{BXU0hXe^>t*F`gW~M={gRSuF5w z^j@W2cniO!bxjd0$%yf@n_R1j1L%@5l-J>f9LCS2>48;qNsp)uFeNwr)+P>&%*BGG z{$ZdNNF`dpPPB_^;08i2ZJayPO|{Tn;$JgEcP798R_UB0sIw(8u=B@B6eSOagW-u{ z(&{%ou)~Cps=$gEt6~PBBy?TOwj1o3(K``kZ(YO!9BRA=F;>NF8QBn}>01P-n*s)sEJwt{IUYCJ{&GNB13>S_;ml5javYXeNi4r%_mWL>eC$ z@r3+_|Byw99z&S-0y!ysEwriXepepS>S ztY5~`)f;h=dK37L3UAfj$L$*+|Dy}`Unf_`)$5uG>h{V0eB}aMS2!6rbg#co4Q1?0nd~RH>wo@B4=)(z@^GfzV71<6)^1n%)U%%Lst&V~K9w2E$3IDhqTF3h0gh=6J>mzN1@cv^< zX!}Go=+dE@t#;1xWbeu4L%ega0x}*AIZqZxX~*kue87q!-a760H0OXty>^X|a(@V1 zACJCST)fQWahASS9IlPIbf&^Q6|_ID3xs!kqkMnEy~yZ|U%qHj@M9b5{ zagbOD525Xdcj|t&pm+!=lSfW6G!W}f_{Fl68^WL&JFO97+$xn4- z?eW-{SwZE80FO+}&t*>(x&KdlpV_}pQ#J(JVqjpnV&D}~X z&OsdS;#iYByc@qSu2LgkZiRj0!!Y1vA!ib|v$yp;JRjbn za;|W-Hljk{|5h5m%ZfMEhZFOv7xf zBWN~cE9uCzWMV3JiqmAmS}#kuQ@UspQl5>L6J-CMYMEDA}mgi^5av*R8Nm$M!YJ` zMbqD(A~1JHj_1MoL_h0%Ce7w#k^@~PsdwC;5#SN|$|ED}e`&lFWgnk1VZAq%BTr{h zU*Wdq^qCoX&t{87oH(#9sAL0kzRXW^=p~4!)F@c%`J`%UroPzqIF}A#P38Ug@f0EW0*}zok*A;`jF4QU`jiCSE z8!-d;r0m&_;e{qSw|iZ7D*BwR|XF%fIT?^&dgmI8iQnkmn%JL$*L#AQTIgkWWUyq9`#F=BOhOnb8FnBsKw&pvLkc z$bA>hO#Mc=);=mKSJltv$J08w=_iR%g;BGBe636tQUtSu^3no@iX0ARhu!gz>P$@) z(5jM6vb~Gn%d~Igm~n`co64r>&pjNC&(;O1HKh(~LFR6fkSyfnNGHwqYl?!|JOta} zQwKRR4x-01()j3z0y+||&88#QOsy1Muu3oQ!#5W6c{lo@#I}a6wc6q@gTo}`YCT@+^gWrq`UHCwhBL|o*5vus9%F(JdGa4i8JUM;dgV=d0($Kc&amA3XS^LxtyFhU)zD= z*s&}7!*T+zbef@jTPEYrisdD_h`8?f!_e-MgfOi|F734DM>?o(#>6x5dt&@cqIyyh z$|4J8@i1g132SGhY26dx~?o&p95pz0cZm@H-k|avtZd< z#rEP|?n{dr@p;15hdKM#&RagU#MG|t#nOvigBVQz7~rj6XUydW-^ z!ki%qbC+zUFU#g8i4owHS^-Ih&& z#rq3E?o!|aKF9V)$O`8Fl=lDa*zeeX8sB$f8-nPtAJ%t1y~aT74}laz9)s*G6^}6X zU1-%e0+ESTf-XP`U`3yw+^Z4%UmkLUe`NVc?+mcqF$~ouW~oW#@Ec%d2}~a}ED{bY zUEcFptufA*Fk5bDO-HNJOK+79@FFi&Xie)qS}Pl?KGWKJ*B?uU%%q9<=KVR*E%b)zcWLYi!^J^zx}No2Q$_{nNP4-et&(u5h4SOZ zYf3?IL_FdSF-|+gNP)RU3Klq~NF%@nHcUWvisX4^Yho+P=9gI{Iu|DU97)FBZ}NM; zSy0BN#Y<*niHQ-w7&v5u%2dvYjh5c*Fqsy1y`&7jOVimko*(`$cm#wzAn>Mnw6k%I zIkE5m<)N~(t@H_)@%#Qll3M&D9P`Vf%P5{;3EqWrG-u^!7rYGK6m2xCt`X*e$tOLJ z#Jh{2fel9=t$aFeu4*hJTkb`Vl`E$f-ZSf-nZ5m$Mu#xqc%CgV@OT>Jt6dwkF@KV8 zS|5Mg%lBNm}9?@j^9*LUJ}HEQ~pyI^rp%9Wh#ELJ@`@U5N+HVV2D0NSN=x1HW-nc zSVXPPW(mBDjrXfarQ-&tDSl(eZ`OmqdrnTrS=w7lyGcD-F>KuR3^=imLZ?F8rR}#A zpB-qU?}L}-J>Z)oacm*>PZ7lEp=}zlFCWqiFE-O&OGZqcX+`X}ZX3VNBEJ@5Mw|RD z&qVEcb_6F1OQrGH&y*I4BZl@X_jHWXvZp}DJsKroCL@R8XZxt-uDotA&C(1+S;!)b z@qYGF@I8df4Ix+5HAU@S8OI|2$PJwI6p4Q)QESV(ecbzG+po%xszLZ%&;G#Ghm_U9 z!^lR<+mj?+!)n+I%PlZ}) z8srbUslGvV_UD^l67ps;)z4;MRz42p&f>v+H@#2~{Qq?Dk;PV(XWKerIkpDtA>bSy z2IA~Kl-@O9s4gpp&VPafkw$45&)EgG;j*#^_j^c9wq1sw{=<%}2rHOVGVmPRar|zK zC6|?Lp>bLn8>J6BmV!?U88+bc0UIHBhAu0cLPhUF4RQW4i=6Q7VtW;?jwfON-q&w%}vINt&|pnh}?ne zQ3_4xE{J(v`j&P)-ONxw?U^oX+$B?K%@G!!J5&35<`*TVrx#rTe8Wf3ON&|3vJdru z?I-sFPXT!cLfi6aY-v5AT(d0kFE)c0Szz}FcyH*vH3GCD8vA{ZsN3?j;<}QRmo;NG zv=C$laA)Q*`&Oe3?Lcf~dMNY(mwwaDBXP*;$_Q0fM_VjCNztqdEx(3Sf8P$TQYV;PGH@m-lyvsmWUmIw- z(REk#5!m{`3-LHUm-m%n`#rE>LIxZ%nSUzG3=<8TVPT)k!uC!3kgZOU*J zZT#b>aPDJ}!O%fyyM8F|znf`$JKOc3HiunRUR6!ic41CoEcoDPUe??yNDXAy{rN`Z zi{m%zHtRPh3d4nU;M?oW?#edQWx)EI(wrd_VGbPKX7^g_uPHxw>4dwbBCIvPRubA$ zam?muSH=X1SzkR8$M3`OsJ7YQJG7$K5`#8}t~v~R_8?y!jqeQ&Un|BxzaNP2joSA% ztPo97YF?2x%c=;H3B%p~7jj>j>MeWYXG}r)Q*7ZOzp4JJGEg0X_cDpc4Avj`CfLF2 zm|7>WAr#RI4D@EBd^li4o;dW2n)2-4<3{!x1r=yr?+o7?Txt_C#zNT6{ z1J)^uhBealKgRNnoi2+q_QO~Mzha zR;#}&%6`NG+l9MOe}}qAg8m(3L9B#SLw53;-x3l9UELowHv;?^40!4F^%#$s zsBg>zN`R~VTA6W`YfAT;QMR4nHMU@TyK@8l&rw>pzrbKj>QBK2*K|&bfp_5>99R?)N zzl~ohyMGHgGEo{|DLa2-oO;>78h|$$(8b;md=iGof^a>6T4+#Dp_tQ&zTce`6))cB_jy0RKi)r1&dC|} zu=d_-uf6tK-<7x}KN#y6%2lplo{~Z0`~tO0+5%psJnH+fHLZ%Y7fpKqded|b@R;m( z(7rj4m7T==s)W1`31u+65x(;&fv&`1J}(qrORv+y+p^%lk* z_07Lb*U6DcYYg5bw!>@)(lYm#VU@?2uJ{&6O6bkU@+_{$OKY@5_;bUD*U50z@ei+O zE>5FW@v!*(Mru+}`8QjrQHGs5Cq=?xq_eK+J^AB1{W8=1ci8 zg^zVk;jNkh&Ud=x%rPJLqdq>uIk8iF9q6f}bwf8d>IQ=f>t$`b$!LC{ldFiX8q23f z8+c>IG2bY!vATqZmr>Wt*#oNKpN&259F!=@JD?`gNv)PXhj*jJ7`ZN&kEjWP7qQNy z=PU3=e{Vbw?c}uwVBf-+LzAi+_1tb)*sS9B!D?C8MR~5=3!AF8IoT6=`VOweW4_MT zc;E-92&}HJ8k~AQ3}aes4XZ8V@w|Ir^@eQht*84-5)@a?)t-=cky5nBTWxZgbec_I zgvjd8j7HQU4CPPphSiR61+}HKCk&XKjz1ComzMV|3Q*E0UlK!Sz{n0mRctNRnQd7$ z5#?;TykbCgWUXSI3_A$DIjXLZtCOl#>t58(T4OU1Y7HCf{f(PjJRmJ9kbo z*0lw(gDMQwUq~Aq%cJZ0bJEnhVSJ?X5q|Kx#EP^0Lx|8UPh0;>t3!$s5^7>=j~hOP z#wX8MZiJOEL4-H`z}m>F>*!#_C>h+E2p}x53{3eX01gxN9dbYwIY7f>0hFUXU6CKYd0@)+3N5+jn z@9_GD0C`YHV7tK_Lu7>5T4U9jsDm*BYh%|jqtC<`%e8HscHp{mNc-OG;1i?yi~M`2 znXQTEAHjJ8yvB(3FfZ~J!BqQN3$5Wg^p`-t9xbF$JOtSnmkkMqYH*Hu7%>TNVnkB} zL#nHjVO8+Olh7`UI=`nXertf|TwwlbHwARy+5=s2ICF|-B;VF&*wT0T$!fjTs^>X3k*6E@w zkr}H7W{t)M>wvhy}**seTdmB4TF=l>yg6TQBVpbN_NOE9D{ zZ8Y6aPMyMTU5+U67D;{=2fU=ZrX>IR8tZC3l}Eqx-PMseorzC`?)nl?w`NO;;039` z)?tC+>Fyf0;>oK41k_}Oq^d?1{5qv_|O@NYy zzEtQ%Ja-PBpwru#r8J#)+7Leg&%C~T+}E0@2cXyY46cv(4*h`GQ&``^I*0sSl#$`( zEb)#CwDqRy+XIAlTMIs%r(NAL}## zf%1g!{hlG`**7SD%!eHzWIePYb$kvGQZ0O#c)gS7$>7j0;}`;UHF%{@I=;bgQpr0om?vMiB52lg!%BYAmYIRUC<9+y-e>gSTm`_ zXL_{YoL=9PU2K&~yxw(m=RX2E=*~TeWXm=WKp#B16Ok^e=J0#){zE++*0*%$K|4I4 z?Ru!3_$hy70Yn>}> zgIw}E?a;BUY&Y)6^5eol5_E7j+GoCoKl$Lk@pa{08F6l8NhbQ_5S9?%NbL1K4;?J} z>ed%o@*@6E#*u^rK64nIA9gCH&>n>-zp(~en7FHh;k2Tw2m9EU=o(6be7~l5((q4~9=cPJ`CF2DrEK5hRs46Pu|OVkfDE z99Y&X#Pmyv!&vu3Eg61oQzG?PPK35e`6KWiiE|oklPTIz4zCc6KmfstK{Q+% zX~^NLjb7i(t})g`7P@0E{RJ^P z$vZgc8i?vrNb)d`S$GoYqx0;GDQ@v7W(e>DhR`})0_Hc*D`L#3NeUk=2K87QmOOY9 z***=sn1OazyY6x6p~a$9c#$Hw8^3G0$2IT41Q#=UepCW*E57tF97QFdtE7Oxp8|PP zEURpH44#koOcY@0hvf^yY((=z4l!T)l4OT2YP|4<=~TSF=7_t8xhB*DC}#D3PhhtgC(`pqQw3k zE#m=?3}x{8sydUbR0B;Kqs_FF)0cU^e%pD z2l^}rEp(%dH2yqXMr6xa(t6iT|8VLv@rpBHT1VDBm?bpVzeF^3&2^zTiEs5y>vr(@ zd(9~O2wq`|7RPkk8mz_jh>CuC=YT#+$&(Q!%0EWy!F4bDcHfZM6Z-Z~Q~LH#a~meP zyuPST22^YD#ddLgjJUNk6S}<1SgVtyFFoO-@6G<$!%$6hS;jP$RH2;cN0Uh6#(Lws z*^>MTIx1qsV&JhWtpaq63&2n7;8C&!-1Vq$%w^J0XQlt2^#3x!)aO2 zq6H{RKp&s(F0xlyhI`mM=I5HhNrT1th)GR(^Cm}s^a?sEi1>zs#E+P51{E4_C}A^5 zpI18MW{S7V@P7iIMf*!JTY7!*H)c=C7BiXU7_DzvV<2^f1Llr_UciN7N67`BVOsC7>Iuo;2Az$?s>=7zabl|V~mW%Ivdx3{B?>} z9lWFItW3+;bi={N3KZqQk8!|7!w%r*8_*&U@MkAxp)o zL@2o%GHW8O5jb$75`1Nti?g-(7Iyk^ea6Iye@B!6eX`6mfbuT2IuM2HOmI%T&7L(E zZ*J(#K$nZ)3>`D!5H*@q^nJd=Tr2&DcIG}=I04=ZF#iF)P^`JKf! zlKg{*{!8NDnf8y|=b=F{Y#U*HJGcLP#aZe6fE_dy^7^;F?cFL~2@cePI06j#MX&FR zp8kj!cimI0lAo%{joMs{J^GJ&GVrge@87;2tn5p%cf_0A>dak%968K9nTY#b)$po+@9kS)2OFxRT)L_wzAt|&Y6!08cv2pOxZb*2mH3Yi zg|KR>cE^gW#Mm-OGZX_fozJ}5Gm?lifNOK!BM8cxS+;pDty8<*P^H5vEvO=@Hn@U_ z6&Q0Q{!8Jq?{GJXFXf}KM*>?kUf(Vb40SI-FCtDB`uk-45ns*az-ZX(pk;0WK642o znJt7qoDppJwfRSlQoPuya&ip|{2p#CzUCX+?Ihj|8SjWM?MFlog#KsM!NMus*k99K zCrjlO59fBF&Oz77Q|egSAF7S=HiL>yS66DBigLApc!)KX7F8p?tEf@`O;e)+w&V2n z-lvFozB{R*%wIl|e4pnDL0N^~?#IlFb0^sH;k6^HIN}@ildP5`opI;k{}JCXpsSyB z&&AU)XcCY368%p<>w6l9r$;=85sk)B-2zN#lGNxHU`^la8{4fHo9@}|sk6zegT?;v zv)qX%1FHS&qonO_P*U^)>7vzF-#eBUtX6Q}S3At$e$)nFQ;*t3qt^?V7sg2ITgG7Y znR3#hJ^0qwElIZB;3$>7Ig&0ks+#tuce=HkiTDw4-)Y{fG1F)AF@7oI%G-$P*CHcV z(q!Zkj-xo9uVDRq7F)-$q_Tu1rMPFm0RLi~|Mg!i=}m>4oWYW2$kHON51f~gPjLvi z-iPxyDO4Vz)=uC09sxgwZ#^d$sAg9sK8v+BwOt$f3`_3Ad*lP~UZ6}r9t>1TaVetW zuv=Pv%{>%505)vJPXeVM*01p&`^-PG*z@?Yey9qVDZSif!S9T>M%9th8k zm|C1g?QE3dQRs0EF8wrWTNs47rNy_WXE!jZkN9T8wtozG`=Q=J2CTcpOpHB}Bw`N? z@(gs&fjNE?d{Dy$Uujnoa`_8#LBs@L1O_4|XkTH8@Md7$ffxb&z#PuMZ!s{JwH9NvFiZX>`rf_&>5H(lUd3W_A8p)ME~*Efc$FpP z^@uz$sMYuS4gFRHUEkgNcy1o%vTuE}J0F|w;2*;{y*ft^oEZnhI%VaL=GgqR1`w)c zZ(_fIQ3kgS3VH)xFmY&+8`wFmZ;nL*RfGz*}4a8dkW`d@w74dGZ zR&CXrDBq|X9Cl#mKypLcSxF8KC!%BnpW%cHPHiMJuWnU{Q*x}$({NkVOio0iPW zYK^h7O1)U#Jr$80>03v9nLlLW{X$%2{9tfx0wVBL4^Pe zgsoRd(kpIS#-BZFTiB|wzBR=9q(EOgUMC}C?u5N4{L0dCZ`l%-+>NsV#|*T+>I0R3 z7idz0vTr91wks7(#U-Dklj0jZj`7b|vgADWV~Rdd@S3T;zVCXeO`-t!U#^^g3=*1NT+js+4QQOG?K;PwqZaJq zds0bu-csu@T&pY$?*n;1$9EokwupB6#Fo30a{KG5eXc)88Le`1Of8!6>z%;{c@p!M%MD{+_7vkrH^ z1fNNT)iU<1IaZLn(yR>PrfeS!T@wz9)t2cZ=uyHIN{@lq`HU8a^-vy5pRGmBTY%0- z|3`d4xyRa()V~xGu^5AQiD>SizcR^c%d{BxQ~V0DkPME-dT?;z+g9tsXi)_|LJ}S+ z{LXs#vND10KS|T&h%wop&x;z!PiiB~n+^5X*G>p)PFR@GfE*ydKG)3^j?SvHxp>5H zcdWK#oqpR&63LK30?^ndjB7rLlo0dXvDcz+W;{DB!ObTnT~oMMr$u@}bFvkizEw%H4&pNoBgd-ToB59#za%K3y!U+*K^E zY%j)+v$*HRF#nq|x#@WGDf=$u(|(&bM=euUKD|s;xoeravVEDRa@2Bd<f_G zZ?hlx*uQ?F=-E2))1F9SQrrc@I*HS}0@%4gQSf8(0-s|atUX?7)bj9`1(K=(v*{(z zAlSIC!bmPczq|7TXd0fPvs9qx^&&pJg5T_NN@K{Zq%hBVX{`RIu`| z!#u2LvoSOlPny5YuvRcroITlO!pYE1wTNy~1iQo}=tAzVfgHgV-9!J=xH;84`yNS1 z0?xh;wLpY`yQ;8%pM>4{nHbeZSUQY{bpn-Zskfd^`~q_APj1GZkbK3>Sr4OE!bjGT z>3>5f9_X=Jx%Y4W`)5y`^^)u6zxp1*YG|N4y@E9Y(aC6O57P#UQ2&^b z(3{4rO%9E8hs))sR?syo$8aHmcM|Z9EU3YNbqKMqp!Q{W1}+O}P5eM^Q@rttWr#ac zVvUHj`GDNI#RA)Z8FwlcZy1EncCxM$1z+oZhQQTX{bxJ-OY$a}sFH`fP8P^<)_2O= znGqLvP68s?_@XVAZ%;EqkYB4Jq7F~NhDk>4_$mxMYLm)1bt&p*O$vWpnG)hwr;K-# zluY*|p4MVogqufXdW#vn@#+Kb|U^+iiCv`g=jLZ->t!RU=%#x(GxY-E*zaSjm97@2j{KX_dSld1E{WnOKLz=X-QJ(ilH|b=LbN?JMGIuoW~4aBj`S#6i>b`O zR4CAH$>zB*CGv+okyTE5KKpN9tGu4za|l`_#CnlcGq`=^bJ z^L|>IOr|{CD<3rQ)ZOs>qp~aQ!%R&?6jKonI`3->4IR*zH?1eF4Je2&n5ZyGcI5z~ z4>N9Bk_&N6Rf(ajASCq+>XHsxvqpUfbA|DS;N4!|`d$a5Yk3q?sS((b3^&e7=l6;J z(hu#0k6i7f>~~L4O;~pc`YlgjbsR1J+<`fKVS;s@^(`y?|6>O@^GZ|U+-n~Z?pfz>ysk+Snyq$c=86d{hlRpMTpuhYJcR7&$-^SXijtdV{v1_vvlH9 zUGSHHmj~5vjRjX~2UntV_)Dwk{73z|;%%C}7(q+rqc}Y0ek#Nc<%QYI$mN*(b(1F| z1`-o5Pxs)?1GuA}Vm86cfiuQ3@pZFj8ZuHkJ!R57eH3O%_Zb;^561=^emU6iZoSr- ziik~Ikp`AQ?%WDkbB0zL`3Dy&*GG$su+C6GZ^MY1)s^r$C7e$DCkwCo`o-6>!|SZ3 zXX^@kVW%?BR?)yA_8Au+Ek4%)FD5Qpytjk1#@pf%?LAt&uY(aU?c)*`SZPFIs&(c< z5brM;hh|xp9oAyjvBzNZ^aWz~e=YBPtm2rF|H+)fhF~Qk@!Cn53=S z(>5&hPIpZ69*lM(?phs;t3kN>i(^k)63*|erW)>v;@&bMZri`7Ed}>Hc$SKLuCl|h zkwZLf@x9e*d^Z7C`|#`mJbSBb+J!xB%W5t5ip${FWT!LFc-;HpEB=vZ>SZNwX#) zOVHF-S?=(cd!#1{@^`OqMo$q+GNi90QGZyHid#w|LrEfONkV8zh&M#-FAKvP{AH1S zZ1_)QIo7OA(14>e;>Nw1SJ|mStvc+xOccK@y{jQchpfBVLsCM&byLgeAP;>X{2ntoO(TGN zL6T2-@RWh}4R`%*=0`qkaA~SvvJmmDRZKcKOcBzdPh zwSo*~#4%;m#_|cbNeHy*(`7RWXA87xbYGiBiDEBpPuiAq%U-aAxQSP*IqFqwaaM=8 zevVlaHQ4n-Om?6JM-H*gwH*c8skTiP^4IL+&8fA@sw7v0#IA5k!_0>sWPumWrVUF_ zRo75tVSkA(yHaa4H5Hbq$TIxP^}8NE{hq* z%Y*?E^Fc98`1592!o2S_HBL){C-_33t`l!t*Zuz7 zXfGRHx*EL`g#!LM)?9F{*T^KOM-kt(s7^JIDTD zlG2S>#$r`ZPy%{F!zI^SZET3PYE8EM1o#GKss}4(1ErGL;Jb6SrD#d`J^&do12al~rwp9% zMdU57h!W@Yz#BjmcYk)xK_2jzkXql;eW3SBGLkdJZ6!37Zye0X)CyYrH?gyyTC)}R zPC3@`(V+ep()Kz^i;Oc^jAIAx!gUS>mZTfI)_m4$>z##f?caA@=N+CqpzpfIJ2cnOcU|dC&5i22e$AVl8{K!k);lCO zrtiAcJ2=t$q69QJ;2B;r^) z0RB<^uN>Zx_`%?f_ci=UVkzF3b53Vj zH}$%V6IG!}o{+$kCU~0&4|SGxR6{y9in7ocPvpi&8aS-M=vbhAUxQYHhmk*~xX#mW z>?J*MH;S28yu1uT2x0e0spfCukbK z%lma8Fc=}3MY#=uvN^E>*HqA1b_19r&M1+Ehep(GbASDR$vyhEb=8L^dSY&y6UyK* z2A=$matz84yK(<*N}mOUu|5hYKmjIFQaJUUOj~X%!xY}fjKt35N*a6Nf4)ntVMaFZ z42w=JuLL%!P&`#sBSN{Hy}0zkk|4oNIfpC~twK46?CP{uRwGC2(bm}eU4ERtNQEdu zs+ugG`~+|@H-;ZAwC01J1Nuxl*v79Lohy1uO{Ndklm?-zs)bZXNv!gd!OLmc-%9u z+S7J7-uoE$=Iz_lHW&A5SLyKepP`rD(`LngCDOFuo%iw15xnzkXo$N>+>X0c#{Zy% z%J`Y$rq!d*2WGu5E(Xr)F48(@im$K!`@%e9U7@;0Ut43*d6ME4Rq%amixPvn=&Fc_ z&#zH$Tuk(@tE+&zwvi(J#UrxQL9d!@GwjZba}BW_1;+D-2KZF?dG!}knsA`4H}oOv zVB1HqZo|yWoVJc=rth)r^mfOcEVOr3)_!ykdIAyi);s_?@_ql>U>rZs8pTJ6UvzR- zns?@!H5SP+dSJ5uSRj%SZ%q`e2iCeG$sp44B7}8E^n>GSk=IFQvZ!4E;Akj z($HxBPUuAcwLehHL95l+Z@~40Ofhct6lw=P{-M2h_mv=Y&HcYfvVqkJU7JLSFQF6x z8IOovt4o2DuBr~K2$)}21ix9G_@$b_Y+IMZV_m|i$|oD=0SW8V=19}QIIIX#LlRz! z8Cj$cUs_aOq^`31%OrD87n8L_JhhMZr4gNa^rd6_)mRlpHa!>@IYhl))uoV3Hl0_^ z6u|nQ^(xiVY$2|qxc-L!wgoLb71axG-$z$J3=R-f^`h-dFVQ~S`BL{)>J`}(kYnbct?1!4(lyr!=di4v?yh3X4TZIMW_FJS!zbt#ac{;D+;HepeHmG|6 zd8yC_L^Ofw^68o4!c~wY7SnTVAEobK{VSzs`qvCm;#XKh)3%R zNzT94%NUIIM^939p#7VhkD(__;aiQ6T@^Aax&8pjSzyK;%a%N$2?N5{!Xg2Ef?F%G zMR&M%#DthS;?j%M;Y&dEVN}K+Yv?Oc*y>+<-;}=I_gY_x7|=luIa;jc9zn#*W!mbO5tWfjv_!m6mRh5! zg3UUWuQ2jnE_p}@LqxVPtP@kqiR+^RXh_FT7q!}8A+7bw3Qd)^OJ_{2F0p9bfp?TZ zmHn&$vjd|^{^4|5s-f`$pXf=g)>M^PxLe*qN*Q7Be$jF%t*y&Qmo_Dkx5kYXmmlthCcI`YCj z1*r~%)cptmmBhf>s5qn3+S{kE*nrK;T&sjOcK?b(MVE#7@#-xK~daNzqrQZVk# z*hg2xkef=tooM@vq$Nsl-{qHtiFo&_+eyNE{3~|achXjsWb6DZFsuSp|1JmrvIe6o zO{Uy(qWO>3UBTRd@Fc9db`%}BxCfqek&TfF+5}ZaVqZx*ezPY0{U}=c8w~<&Z@LP@ zDEdW%aJzA&s){m{Tinf4ctq!71397(fclD%KgYDeL#`n!ntwPJ(U7n{%Ui-^ylUz2 z^fPTnq#FkOWHn~|R$~aFf+Qyc1wdRavChx0snUYishlaXmx@$v3XN{vYG@cUc)5Vq zzfvl}^DtvQ)|dlK3NEEcT@+GSdZXMF@@5(4V9H#J*&! z@zZOnlux`Y8#)qWp3{dv%VYgaqM?U3HX)h}4td?j-VmLpO{@8Rem_JHNLYSf3DO<| zkEb+K$lo%GRMo+?QAOENh#lJW3RXk1i!xgh z?H%NH8_m_tx-r=S&6Vt^;dWZIW6jaX^Uc0IOaCy>?%%A9iTF73{J+uL&4EVblja!Y zXge?)`#^!3-t&jK9=s*j5x1}DZ|M4;b#zALo7Pv;;6Kdsg``$=;w za=f-bP|K4gzs|?E_S9*&RLcRQWU z&5>|Z4|U79s|L+JYyOf~Cxl?81dnS9f$v*`5QA0K^X=Tb$||)>4_)bWSB5>$ILEadTml>VM_@acwtmX>3<2EUdz6M6!b zklLr!n1EG3y+e|kAt8{Ji`{-2en5OTIK7gd~6UqyFu%k zfQ0;*y9B)ynkdY6EVR8;Uk*Jey9PSHfF5*spDqgaH}F!RGjbvHQCfDE@ny)z|HEJ4 z+jvOGpN+9kG>$F8{@jp&p7;6oCEM^kMM_~t9-Jmm%6XGYc37hldbLTE}V@AZ92oYIdyb4SlO=T9e z5703%p>d6m<%ipj7qBB=gVkLFR>mzJg9wb3mB+3%sdbIkYeyp{i4NHqKH=H;m9}g0 zu=r<QDfgveBlVokh42woDr_&(@`--`4?5WFb4x1d_ADR4et77nB_+9@MGyjpv zSet8l3Kw4^nq`G+B%|}ADIfXc{zb*Iv11FD18t3JNIIwNybND{!5SbOnnCSQTHiV`zwKJsS;nq)z@^AV6a0^N3wp}P- zz&8RZP|eA8&u-jjOk);euMQlC!9LQjPp^5lv{V6=gX+IC*1Brq)c;Y zVn>A_8j&0tnzPxaMp}kxNE!V}7<{~Q;d*HP>wq?IOrI|S5rSglyDLw_OXx#$$6Yr?bH^KfXKUYi ze&2a^-#OoZ_VV=YCqT~}|NqOlTIK#q>c%{E@M__zuOun&D`}H{5m4EgYjaisdE>Ku z_(3xXy6dG&48Y5u-!v5nI$udvXRiOeAurp1uJYe!Mk;LCqD+%4>J*Ew$@?j+a`XPh z+bkDOd?nQpq^_4y8%+QcVGqIY?K%ZsNt>)kCCLh32o7|k^uwEVv>ayo#U;a223+SI zm3EV^1=}skvv>*$S6X#Z-H)nKrcEf%ZZa=gdi1&h_vx3Js8b$EJL$KYdE4?i&QyUJmdt_7;NdVtm0_5E&1i%O8Ybr)7hYaD^P)a3>6UhiJ~f#sDxOV$*Wd^cI+|Ie7d zLg{-zS3_edY`jujcQ4-6=RK!Dowk#X#g=H$*+kdfCimVa%Yf-WlkQq$?fsQhrDsgb z(Gxf11qshT0iX6zUNVvUB$M?kDIe`Y^;^?y-w0)dDTGo7)0Z0L-BN81vnW%TZ4HPltS&1iGuOZj|#4Pk_Ri_9t`#aO^U9#$%$eq-Cz8nbiHJ(XAdyImLA`c7m>meq(G2@95WJpqjASZ)71OZOlHI*{xm--rC-<4 zXjdHVb^WZ=kD9hn$6~54q7<4JBNNcJq%7v5A;S8NMAo9loP=?uzFxWlZ`9YJwwp4? z2vr1h$%B2lz7T%n$02u|&(?Tou1FQy@ZQn6z{d*Cix+UundN#pTiJ}Bk+;QC)d;_L zhB>W?dNBs?_}`!Enqm9>8|>*Bwwv!zUucwGzkBgoScNnE%a#KtvUrv+BgkolisnIU zp2wtL&O4YVA4zLkYPp8d+^t6q0h->0J}h_BG4u?^Pn{KYvDU>f;$3_C@rcYD6PwIj z{Yy#cRUI%okr5K1BzOrpg=o5L9E)&_ z4GtWyYcQ|l|66d<_h|`v8);DaU?f5tJ%XbQ$G~vN5I8RD33)b*5Et%E!Sz?tF0(BD ze&cj8Lg$QuH|(`BYtEI!W&pPnOSs994JBI#bG zU+M$zlg&W0q3=F$V5XfJ{gw2Jc~%1*Rh3Qg!u)I^E-yuIZ<>m|_`qGz3vpc9K&w}< zL(0TVEJ(7i#rS`+lo=fkG>jiT5&rKU?)xtA{&m>+F)@KR=k&eV=2;Fp?*qo-%J#GG z26@*o>HKn=LQo^_L#AjT6XEZS@}s4$pI&Z-{31TmpygiyhZ#{i6?!9Dp6wh;s;{(M zbuS0^rT?7f)3zL?>ZHj|>mq|ChBk$WiKSYl>XiQ;2w7S{aL-tZ-1Q`RqWCw*f6g7Y zP`g=v6>@Gbxg}@v+nir9o9r|{1)UXO^|Bt4$xiR*p+UzFT{}ur4f%GuH}E)X3s%9}%QR`bq3K%q(WiF=4cyJvaX~q|u-Muk$nP z%aKn!@+r~LJisL&JH+c{ZfQ{o-iha_7k?63XoG$tB(J`d&5N&<%8;@dsp(&{gt?RK zlj2VATn>wSX6z?BC%Wi7hIC;wIko8espVFsu-uAS?it*-q7?m;?65sI8-Rsa{CGL~ zq`73PkrhkJI-1#Z z>}q57JjR8&*mQdSN;;<38b}hoc3dSTnu1X5rguBsb|o~*k|Uxx#a@G)uQ@n%!lvL%XOm>K!demyX`l-7&^|8Ou>46na_Jo^AvNL3j`&}jk#jwn3(OYu z5YXf>nI*AJnK&>Po2&Az*@GItk~U+eV+k`tp1vNvA=Qo&lM>5!;BEDJ&skAkl5ISQ z$TP?CEU0@EYOsr2WM|QjWP_0_@;jzK;?>Ds%T;vAM3hHQ+T`p+*az2vFGM46M^gm8 z+Q$`0tT_gezh&Lv3s<+jAP_wwdA{pqga1ybY^!t6Cm;F5ONiToeI~hXJMfEFSf{tH z(V?b!S+Ff$3qL-!_a&JYZ|^fJkSl7Ohg$ltpF^G3n$JQ$*_=n~T%WfsANl4j%A@sX z%nyP-Yt6b5wfT#zv@G)UZC2DK5889>X3O`dK@0uXHW?|l!q-`w1HE^Sl!9*$qx4On zA6l-BQBLnH?N;JBjYp~lesdy+w=yZpNJK!c$-ICVK?FSuoCRguo|gvO<>f&5^UFZi z3;gqRBxWuL&s=+e9Zg#l|AEo6Z0}4vZBu46to@tH$+*WiWM6iphGZh-xq5vbMjCDB z8q2?McawP*mEyR$ftio2qLKB$HE90>ZvbUB>Cs;1CG;&qYvHu0n=wb4YpC>uH$f*o zD-aXyDS;Xu)`JG5b8#8QSQxMzkefc0r<~;xP<*ZaqAWVjY`a0rf19N7F%hXVV7B$c2ks zXqbQ*EKQpt2VI*ebSS3?zwYc9{SfVGiXNU z7$38LBk4bFT`pu84&x!if^0QB3Ne>( zaVT*;2fC56-_R`mKhW%%A8*nu($6_|5n22szl2r;35^wDZyhZ|yVPS$95&xoG6pfwp*-hPvb>LuP}u3;(Lo4!NT#Z?#2vTy0-H z@X}5uiD^D&Y-?E?``qHqhyxgGj~LntISs9!w|p_UKdH9RR-t$W<(P5z0X0={Mz_Uu-qwHD)}Nx$6s3UrlB@hgZN6~^g{KvO-HT3(IY*A@m# ztl)%*qR9eA54#l@Z+UT;b+!4BjlPmr5!wSO56p)=0?)nH63kzl>uC8=n!MeQKWD?W z7Ns%k>3oqFffm?|FYB9P4b0g4q{#8QF_1aT_eqA&Cqo*!PcjzZoF~tq^E7Q;*|;re z*?r~<$7xv!*7zHgtb-f^es^_Q z*&p+$16OX2x8L%pU!)C^MoVt}g-7`%j>BeJM>-!<4neQ&wg8u^r(6r1ifV>7-$)Oj?7Vxj2ipTH+-!Jwi>tD*LTPWY*chKCO1h|o@2&t zDGCn1uV}sThVS$Nd1F`+cHH$7+GF0m;qx3=kN$-(%tr8exjQe84c}bUT6FGv`RE(I zLkDIcHHK_8GG4+(K*l;|rtd>?&(nDo@nN&U@6DR<^~O0xH+wB07&N-BYu*=%>5Q;r0kf0^dkgayrl3 zvr6H=NPVTKT?XM8j>-@83$>e~LslXRIQ`1h_tkvF<9*2xQOxvVyOdhW(d+yr<7mky z-z*t{EW%NpbYTB&W&7c+v}6<7o3{RMC6oVOl?Al(M{Su z-~Q>lh<3K8k5>9Xy0jGyR2K`X>-w~#BxyqXus@C|kQNHk{D@nm^}t|BF@vTA2jO=b2GAd|ms97~K`n zbFO#5J_oJ8FAsB0=EOLXW@sGDPm9C5c}wH+rT9F|N+cf$HgsO1t9o$dOw31Cx|(UK zqw^5vB|JH7o}Crs)nbOK&jiLD4x5`|qv(u8=Oa2d8OGCjO6UKN zd1*Z6B{Ogp$G9xtV=h{oM0UVpQ};0eKy3 ztA)l(RC3gpcQDXW&|M>Wd=}+2nG*}Nu71fx2u-Ft4_FUU8lxU{W@+&TfAr>ne*2YQ zbl)V!&?o}}1FhqBIs=KysRJ!aw18-=GM|D)vsEVeNSNbi4oiGHb%{li4^{)jZuJ)52m?fBmY=e zT}(9Q23T-I&rba-XgXuxkL4G)DrD1JPdqiBdRO@Olu})qnrK>2a!|#c>R%I88(mG- zu@$m%8Y?xOp9T9iLlc7t!*QK{Dkg=Wp%i62I$G+XN;i9MQ5-Ysp_WBPX8Z#!(1nj; zX#bJ}NzQLIFo$2;LjAmT{F-_-(q<~ya!sv#ovebyCm<4bukWWD%KARv+I!^uYxQdA zg+gIfa!$&xBjQ7sf`J$6;JK9!QLhaB{Kz%Z|2<$)`tjZqDXLZ_{=J5SHEooV%#U5m zj`;LiruMOGYa-@ev&de>y^;KruI&V9PwV@OVi(1I>MvgD(!nnz_x;TGgSIghvdv?8 z3#>qB6ja2C18&9txJXj?*TfV7O@^*ogNTpVeIdcsxzL2E)9E!c66;E`4SO)Us{Z2f zu3-HBcb5=~cH}~6-Qg#%cHet}i0!=z( zdIBM>jJfQBjB^N#ekR_Taq%v^FXvwUPR?!o4rs0yf9~y#mJx^G;M5l#T+T(g-uW$J zfe4vM|L-476xb%6z%-pbkNa{H()|6s*xTGQ+~!`yZSIBK<{q{f{w)vrZSMU~Z!hXy zCiIf9iwe|<*0Wa^b`jecfopXb=us9fBX#H1?pH6w^$tG|FRTlly}hma%%PV-i}NJ2 z?mTO*0}2VLk>foXS9e~Yx&P8rs@_&aWD;1CcV6o4O=0j%uCF`);6mc1@97=;p@Wt0 zX1IgC4VOuy`GX;oU#K54Me*)(AS+bo%S}2P-NQNLvtC-Uu)^zAEgeq@=a z8Xk8g@Dv%Q%abI0Z5s*fuK7*OpzbW_m@}*H3C|tEAr8)9e9@|mKj_Qkqwq-SJ@A)W2W{9Z0D=W+MVchc&{cy6%_});5aBtkjz1v?Iw*?SfA^ zlKA2Ah+)w+2C-CCZDT^7E1V{&$B!$VD?A0v2ZcDb+kvQQh*whLj}zTCMu~p^<3!$K z3^fCfT=TA16U7pUF1*j+cabBI)9V_DS0_!=ez`K zgUp|AtT<$to2@^mYBMluPH)PwerBCqxYu@2BK5CXg9=$rW;*1PT9*oIfI(KykHl`m z7(~iN3~O~dZ-BQxY!`%nVsO`RlUh=8umJ$JW)iRVDw(Wg#D7EF!Bo}R$W+7wfdzJOYML7>Kw(g7iaRNFnr8@R+Xz_U(7im# zR${<@E@DgjJhem)6x99-dB$K^o(#)<*BcTHl#_CH%kqUxML+RKXVT=9oVW59^3gWn z(er4(OG5-E@$N#DUJHbK$JREr27XobIO-B|BzV1dW_4xlw&tKlYO%fxJNCd#E!>f@ zFxu5$e5WHAKIQ%W_a}1MCk~=-+B&;ojHTBs|sM@(>N25 zw<4=KiMfPIDFujHJF|g4BSS~JhYyugsUZ}I0o*Vl!u7b(AVucM?L*U|JX!XAt_Rcl zxmj~Tn#>d4Ah(}Iei1Ha6yC{vl}dS#P~N2HL69`$kqxZys)cx%AvE;|hkoJ#KO!%* zD*L26^b=s3zBgM&ZrZu^=U=E-imV#3Ey@*qN7hTgnPEjeYs*z^!(2-4;Sr;`oUKrb z@*tVBp6*L8nlNmDTi!g)l`faZf!X14>mbC z``rRXbtPh*V|c2}LxvOabw{-@EHzWCa8TSbismpI`@T*GefFXQT5sKO>}{=btPzs! zsXPPkcV=Kpa+lj=kL8B}n}mL)a?j3w#y!M^x8cn?JhaHYq=DwYcIm=XD8*9?P9mPl z2(_r_2x#pKh2hDOp1%RnQ!RG+qeZ>$`4ggd#$%@M_1S?#axYo~*i^%&AiAzX$VNPp zBvGzbh^%t39c%*L;PA$aa>RXa~C2*+bb-3pqDs-*G#II^f}N&Xlx@oBARYq zg>#kJGL&ax3jtOO!}((i{pHJ9fi|SLC5OO$2DJ)LbG+V;uG>;n-*oGQH+^# zXl4*o;3M$*yW-h(YB5uS+~z`5Ee%Bm4$K(O0I&B8Nc`Y!cap(%dT#jcxqXx%e%XHK@}FGKp_ZANA!YQl&q z9b0YFri3?K%x|?#6)xrzQ?8I7$0R-7Y(Xl64l=2fXJSrtgt;FRm{gnR8%cLiQH{IY z3@Md-BYi9At(3b3L8lQ7D;SaTIzmyKXX4$@{hUr~TSm)a&PWXc74``uC)0NVCCP%F z10#MfZLy_I3G!qJ+kt!hCAPpbjeZMI9cRF}a@ z@!uw(KWFsy=gJuYY`>(Lfp~fp7d%e_m3<7Ek82u#Yyqyje`fmRpR-vnqu0rt6je%I zaZZ};p!OAWO23hgJ-sq(9Q-JIC(!t7`{alcES~EP@PIL>Z#}eO8e3RHsy!7b+esqr zi9@M=4tx++0XMDFp>1hs8;brlfTA_4R6x*144=c4RtB57ff)koR1UO)zw1Mh>ij{7 z-*fmM`IJ7yB(r5$$GK+2AxceUN7g5>LHY!CjNeG(@m5ylKk{K$EXQ$}qTytYQmp` z8%cf`M^-n`LSY>>ib|l%vkGi9K5&qGBT&ebfE6|pqo}PX!}hKrEoMCSm8)$oJU29s zwYEc|eNp(6lv1Rq9cUd3-~SNLbH>*t#*Y@8<55+80c%l}IQPamoT2AJ)F}h3`RU9O z}bYG<0JE5PO zB4W~#(e!(Le+LGz;Ug;HPzu|uQ8t?2GQ($HR<*<0nEPmchAq!H##+>p%6~FhwQ*V2 z>;7~V?mQdiujs~at$(wQIARHphYdqvI!O=N&~HTMyT9PX+n|~c>WBobV;Cm z2GKsPlqz8^N;_VdY0pS8qwa^BXnSeVd(>7LJk|F#{z>A9!8-cu$&)ANE(69gB4G(( z7|E2Qmbs{95Y2B77j1ofuxgr&wBsPSFXH^#K$d)n^JJV8ahC1{o+b_pj!ifc z<5(ic`NCAhufw?$=htFcK#cs#YxA!K`0O3H_oJ%Ai{y&tx30xFcwm*KW zx_WP*S=43`dvReAZ3TB@pn(!Z14fgWfGT}u~CzVW@Z32VKEV7CgYL? zjLgVH1KBfK=5lcKw8xpnWk=bn4+x#xTj zj@9`6JA6jr(~9#^`2I>f&2`7^LVml^%#NUc%FTph+7`;=%=Vyv!cB^^YHlG|&93UA zwj6WIJN_qt?7pw9-4{d5$ILAhZFp;wsbCfQ78%JifqPa>bB`G1wt&7KwtHnS!lA5o zjIyoQpxA`y`k^>qMMkw~>PU4g&mMfozYgUdh0knoGLCfS?77RV!;ICW8i>l%TC}^y zs5PEp^7Y=~SX1E+r&`jyFxp6VGCSV!Ki)Oxn4^uH? z)K7h8nEWPk5OB#?J){|5OwN}SnkHgBC~J0 zYPZXX$m(eFiZ2@Z@Ay7zbBXw8;Scc-LVgdEpY0t!Mh)~>noB~ipxCX%XM&Y2M(*yW z`EHLO+Z6q^8o$bcg{nqv){tTHnqH2t1*$82*s_BDil9{>N!%IWrjDl9H1GuCd?r#N z>=9z*^T1&(Kjv?-%qL?gJ}xJ%6gR}m2UMKcO;87F#OwXWH^A3|| zE3Nf;?Bd8)JuD0?{F_n)O0C>pIv+rvs%5;iKPcv{>-Q?c;c&K8HmR!EYTcS9-=m7o z_2jLbug2E-YeqK@lOuYE+Ze$nnXJR)NMNdKUm$5uc+~sa{ahz)i?((Q-V)WjT6)Jn zzcZA%gz*$NX91hI-GAt^27j9_YinUU=p|#8NE3j%HyS>m4~R6sOuPT3%ha;t_p%g~ z2$JAY;EJhhHM`LJmznWq;F&YFcK<&wV;uop^>+W(%W9ys*!Xt;34Ck!Z@e6z7q6g4 z$InwWtji&z2}a1%feqGn|NWQPdhD4)qCOg-L8+0T+VjBO)6{}1YuP%ifhY~T z$Y4ivs05vuyK3oJGPl5fb$8I;1x!zrVP#NCyFcpI^BDh0rTme$U&$nsREdM7e9<`_ zeKrM|4LDfTmGba518;6AhGlGir}>z=U{uoj9QHItRaZ&eyoO>RD3bEIi*tdu{9i0t zjWJ)|k~VK^(>hqXn3~iA)vN1sB0k*=8*f-EGdf=~><2eHbq7LiQtxc{f86qdGtnYW|FtC!1BKII`y zHoc9NR#{LX#|2Pe(t6F1D;)n+Wm@YnIVZr}p@)P`gKW~Nk=a*XA5im-Rq4%AY3WWTT6$@Spi#_PRwlPe3@(&Y+A#B|L-UxR*N94wxFhy0>oBwKLPIh zOBF8(D+D5ciF~b89;uNdn%QriPvj?&(Sq92rg>C0Vh4VpGMAHXS)fSlF7NJIC}-K z*r8pFhyD;wwNmQ`740SOtk|@IU4b#7h;^!rz zXH#6lOKq%({V8Ldz@D*SWft8-?F8~%lI%ua*7w^OUvP$+pWHDG(w(GgIw0TV>VUa9 zH#gOrCY^v*Jx=^2_i)?2{9V|eGT0^q0Uz2(b5=qU|BrZ^@F8MXXCSh4GI(q}ydw79 z6C>dqc`H^B96|`4__f$}e_|JKYZOeVPrSsITuyf!i7u1QU(b}cmy_yf0)-Mi>Hq8|lXUxz2-mA>J&xojlxn)E?%^i>W ziAH3FsS6I9_i}L~u=Z3E<%DI;i(v~0P7a)Oi1E1oSIoJ!&7;NdE;40^7i3k!CcIl! zl3lW?1id*s`~FS$Z>(qxgtr@o0^qpPw$)@Jw*@}STU0!|=FyZW&yy*vrzAz^Wr5*i zev~2@Y+1pK)>(B@jQqO+%ICxy1^YH^0Z8q(82O7!0wQ8L zryF$o1anQdGXKQLlOfls&Jpx~5o~H!%fDeJ^#g^{}S-A zW8_%_Dk%Tn#9=8Gt<72De&jACVh^&A1pS`|Rgw<9+JD)v zJmUxMa?oE7y+?RcgJ)7LqedC?{e*W!y4iS`-P_Gr2W`lz%mM}dNBWHFFK>lbI`4jX{55_Lg@W0K0Y)ne^ z1pU3paXtOb={!?cc>V07Xgg5%xijE$73AgUI4NSDRIwjx|LIc63S@aFR0o#u&Ez!B z+q+_aF;n|W#kVE471@wUm}zV*;!jos*?!_C@Lvz5>$fnFy4Pe)d*{`ZnS8@9o?42?W78!FieRS8hqSD*~{9u(nmD;nZ zTw0^x_tP<0v|uY}6~ia;@JKj^+(th!V9$5zRh#ST?2_#yZklEfl2l!0%q&~%vKjbml;e)dpBw3HT?>bcW$ z;o@{y{o4JnT$&^@K=^VBPM${o6ZyhTU29>E7D!+^vJiK0-*bqx$mPEba8;AU1-a)> zr9i^A!=76%P8PG{?}>d(m?9{i89;-ka&q+@DnjMKBpk?xR#>5M;(ZHZK-r*QMm8KP zay#UJ0+ah+mzL&>gEFb`<|~yGT7ksOLc&aYslqHxLQZr#iuUz8Rw0vOc_Ou_jwKUS zXNF_OCSz;oA}`(`AOEsvBR{;;^Vo1us;FNhj+mgqw}O6^XhADCvj%TXo9!9U+*J)Zob%GdqT0e1&EprHt zlD)!8VP(nQ5@$$52rtj2{WPxMT820T!Cpqj3ajrG%;4&g{SV$x#=dg@p}_?F3|bdc!qbBMuUf7AL@OnGV_Nx z6XkZ2oC)js-D>LzSX94W0{T4f3iHwooFqw)ydrJ>IaiWef6UXS_RxNvf1L=86?GE6 zOW_T7A#1`n_rFvThFu!HM4zS4+0i4J@)o!0MLvgG?_#`rDnI4&+N=+2PB3<%$&~UDK)8=MUCzEaaW7R1j=}qinE@L7x45u#7#Gf9cX|Y_ip) zYjg78toDgmOA`5PUuNq{@lBWdxJ}#|`(nIZcu=q_eSM}^YL!Z97LX7PhIxKk_U>Mc z1X$4aR60uWew6JH1c8J?xs-v1)g8pLzbX~Y<700K8*Bpww&my{!<}oF{ZEp6qr@?uR zhU=U2j@;N>=s5_*{O^9fk96M;@+6(cx(~drnLg3xulde~dBQ-f0v+EPygL)|>>fTwS^=a7 z?b#3oYUjG4Wf(fvNR%3F{wMGjyOPlOk(BM;`!6)`&56<{um(ieWRl{eR!J5BOJb+PhoIl8~D0P&wT|{RU zm3rG4+k3R$3hsCb>g_@erlQ`M{XrMI09~r*NOOv`J@?=18`fb(eV5|y#P3e=dr@QT zDl%-Bk?awy!ry?0u2y#Vw)F_DwEqU%LC_8&G>2NT=OU%|U2>+0@-(C8yA8hf+D=;$#e1pRMebm7l#p6yGnLu{ek=Ag=E@c7mnw&4 z|EYr7?*g!K&~+G{+eT1LVqCM2=#+V1_d?T%P90E!!gyU9%d0VqPYBTY<_LC5U<*@l z3VOU>#%Zt)-IJ^SB1TROPzzrXe?WTM-}`--WUv*1{&Tt_eNF;&BK@A+uqEYHF%h+X!-phvO?FZ1T$YK!3Tdv$Hg$8&R8gy=&7cw_q>ZdT!q)$A06<2)Sm>K ztM2Sf=^^+c6keAeY4dw7VXxa0E$<03VkCBs=v==9qvr4>UF#xVD@DsYf<$BobJ-*! zkIN^`OH+W)t>V0Ix}rUsuy1tz;!A^g$+d0t_q(UpQT%K>>vj}YlO6DW&|xQ?`Vhd5XJ__Dq(?fSRgZ@txTX)d^Ei$N;AEP#8H6Jnmra!OiH#xB6RdLms7E`{qN+?$EM|}@4 zJJmIMSPI~Y=g?rkVjuD-g=~`sYsjwJ@5Fi+?HFfZ$xqib1O9Nu)?#kSDB!Srkq+Ao zUHM~O6ePC2l_glC{0wW9c&t&>C!*!Q4p6(;-pYAcotU6=5BR$WV8HcKsn$qWC#J>{ zD%oDDbOF(-u_98UcCm757gJUz(ekSUHq7$p%XH9BqMG+YKTejcrDn{fLBDAL)BPKxYO4sJH zDS5Xt*VXZ`z@_X^q}ig*(~nV!5S+OlGJn8dhF0Bf|BIHV4}|Q0#CEvHFJ26RC=^*ovr@}@p@rqO{x|!EWbkvKA1yVj&1)B)2k9;eSqEQ*5 z<$;@O-qT7mz*dMG#(vX9W6f5=-qdcnOH^O6;EFj?|aE9lHT*{x&h z#|YKAV@fP-dDn>uZJ>%lw)Q-D4p?LzL!Z*M?GX&v0cL>KLeb7R)m6WOO^UOYVLDbImIk7to z+gaHdpkk0}AgXzOjPNOmF)SU!k@v*!`7XyRf!+yKQeJEp=}N zd)D@_(c)0bqY^cuR(?yLqs3i8lJg8O?%|@mj-4YSaD_@`?ApUb#;g z3x3;IvcKYBB@i-9f5OPWa45AbLEPLdic7^R7k8G*L*xcT=HygydE$5hmYmh4VnKpK z+EpucuNrL- zlFD*WlIvHg0+vZa20Zf664)fDJpRS_kj#)_@2hK~Ed+NGx0Q^}xvFzS!2fL6{$V>z z)x*JM(97r=AH3bzyumK=Y>m2xW|{-KQolx_1#ptVfmsP$ZM1wBGT0|ky{OhSHd;esfQp6X{G!p0M_UQvHt zz1-egh>;+}|5BG4ii7dD7)3Sz3u5B6qAoSUOR$rqvZH0lYUxO4U}tLt)_IaJgMZua z{yv6Md>XNi@HtfUKJq-h8J{p&4A!y&grLo{V zs-sce3^VxCe?&HL)DV#-*gM${k5xgnW3os_8~5uRVKs(o{dVIH(~b%yGkB6tyHh2N zNu_9v)aQa=b>a8EbY8!Y;uvxUu8K&*`B?ZfGK$u-*Jnk>hNThY>K`_;dlmw*g~`!D zC-@3uKT=HyJ#PO#bZ+SLVdlr{^uBHQJ@gD#>EwSqhRXThK1)%SLlr7}==1hxY`8x3 zdoK6m_n~w2^Y-%v|HD1E-#_&I0hIml;QQ&j=`n8b+|WID48H$oxJJt!fn(9&xrz9` z1mACe=g{~2aQ;*H&Tz;B1z$mGucy1%ve)Zol*E18U;yc9*GfN8KN8-7$0Uju`udulH%fPwH!*zIAQ+Ppe=Ey~^~t)ka%qs@zh*M`|^q+!75{rCF+aqz0ezUj95 zZyr3Wv9FPCult(8^Je>M`+idQy9TdC+FerV zPwJjIcrDtV@gH=YJb2A$ANwD496fkVXSblwXm8)%XTt`svUdG#Z8i*^Roe|O9Jq&> zy7XTJd|&*U_66rdJb{oe_{%)=H)SP5+*o>N*|fTXo$?DO}{?g$*QA zj08(W%&D&~ndGQj|H8te@PFuEbaWKCG!hXzYTXnfaZ{M|y)HxTKhHUvjjuMkR2~g{ zOWXYB%VBl!w`^DKf)#V@dv*4F9s0QGD8W?6zV2Gfi1nEJpLL z@P>#N9~{qkRX}EaV0>uJojX2+USnuwCo>W=g|)YIw{P=xn|oC!o4fP2rP*MyvBj2i z`_%i{DyBM>Ux>2Eb1M0G&tcy~D%cAgb7@9!hYGfOV{4yw>6i^*4xsZ zsg#z`_5orWrwEh8WtO3HKu6r}w6PL0e8h7#Tz$Q(=Qvjv*A5pvk zbmDk^XH^__O-=>O&Xuj1*d_l(Fta&I{^-_f)>OsFhg)$!JjCNL4;ms2-XlHXm@_qy zq~UeQb}L^+cFaAk#1ZB@svq%snD3G)%qJQC9v}kn6N{do7yiQY`TCt}bDl4Z^qI*9 z8d2sP;WKNfWe2e${8y9Z~dv)tkS%1Vl-)id)6~Qu#~2(f?KeqjnYdXYxA!#xe>2@!!yW zw}1YMd7oLu(IfQVoyxcE?9lI3+;kQFzU<%LG<0l;^AQ_g+T-d~}0$_xhYuym9-KZ;mLd$p|T|J{lC>;*IuMiMf39MH&ZGanWF- zdLe@hBel29x1&>Iy{BQ{zOPkRkA4nEKU>3Vkz30=kDqZ6ev^H;>NGYl0?v&?LVIOq&(*$rTS6iJym%_H5>s= zk?7`1Z(Jj8%G>ncC&Ye_r5ax8}nKA(b8LTI_X5f&qEx<}!kc>!p)8%I34b#+uU&wj&%FmO%v!S=ND4e6h&Nn+ z`E_O*FIzRcag98&i{9~I-39&gr+DpdaJcd8U=Pv02=fJy;fxrWDV6ZTg9Y&@m!bbA zbT2Ip+5eR1u5rwXCQZaiJa0I2>v?SkGi5X~eK9^A=eck;6bK)^Ib8_ZE zi&U=Bot$|fTBIB?CX<|C#thR!*_C-ulC^38fK zLy3+$lV+W>|BR0q%DM`S$dCdw*|F#K&ui+nyHD|lu-az58d$#~q@%uvsO{9sSdaSV z!hS)qKdjC0uT9n=W2&Z_j`E>CACsxgc|QkWKysl zSV^;=iN~%!@{v3veZ388(Q9e}!dsc(Yt#i&1AZ-`Qxj@c+z{H{*4@4w%g!$y~ z6+A|mbLze&iT?oKeh&Lf(0?Tm=DT7tSAmnQG@lej=Vwxw4xe_?NyG;jCgAx8vHOU3 zC>H6CHcc(@u?9QlXI<-6Z6dwPsHrQIA2b<}J#x5&H<@M~KzWVPVtp=m_8Rt}Xh~X$ zB2s*YnlXk?P(nR+S|5Ux{~`QE)G8kP9G0pEzV~bN&q4YfQWY&AM&H-}$wx4>oM`@E z`Dmha6@2t2_^4drqmj}hnlQ?HxAE>_)RUR=1(jjO;r|^+;X1wcBS+c6Q8mi_Tm~`# zpmr$HM7alTR%F%~$gI>na2=jolfz8mWmdyw7^_%Ep$t$+j0MU&^obw&hnd3pI3r>q z5obf~bzcR_t9o)Y^&}Q}` z_bPGM0848T2ec94G?~%?cMT zNK974I-n06fWDQWsnyi&JODXSv#)I|B#52S(2{dYhZIskPL_|F6=zRIMcH_3mz@(JWDDA%O=(En|QjDvb2-1-+A>n zUSE4vJNu+Fb*9Hjb5w*)m5Q)OVz3hj_98E7>ztE|c*wal#J5))>~!}e<Nou!G` z{*HZPO?BL$q^Aho$V#|*XlB5?&`#$CI{J@Xpd$kjX|+_!QO@kiIRjjfg{b$O1KMhM zWtz;*%p`3!C%p;HQd_$zLA!mpyqS%x`I*;HtF6n9(`_fI){Y{{Yz?a`MjXjYq98{3 z%#15x4|W5zkYKuWBdkz1WmF*U9=IHkZjhOaHb)_|Oq0*d>S|2V#Dnl`(Z%v>az-4O z#fMc*uSwO|J7lK{7tfq=hx;;;pZUoH5xeUGlUvM#V-}>goO!91TA*Y zbkpd&Vh7)~_}05dZXWT*oPDlD#2wF0Z)R*Wg|))O{aeLF3Gl#zHh;%{r@aD}Q$smx zogu8jwQVAso+oY-vJ(mfZ7MC{*4ygt#Ur!6xN`tYgTBX11&}zu<&6uvydB+(g5Dvb>`#~ zAsT4MgGNI%SSy(EOf91M4Ddj#7qb3aI(T}9XkLf2;u7r7m9IiqAgZ>1il#3fj9HeESgmUIiGSSwNfBwAy*F>Yf;6Ff4 zgSxcW@)EFSvSQ6dv`IswB!7_B{=iU=wQqFr<~xnp_0DV=vA-|pW!~sB8|dn+P&OM) zym_Lh<30g)Q#Hy4^4bOqE&G1VXdHC_fzW?jl2dVZ$uKix2 zk34#<(yp1pHgTRC*P2A6758{cl>jcVqTf_n}%EF{? z{SVsMlya_AfOihiejh=3$Gjnq_I!c#f9v@He{XQ8=ijRs>iOk+N9^xK&(mHvp!aX@ zd2inT*6%}Y&c{y8r&vX2%Fm&$GWdD`{r_&>kA2BZ{uhw6LgTE~QhCHUK=WBAPw4)OBzvBn&11L`|#Z&q&Ejt@yh*HWxDMcpkew4AlgQsnj)@ad+6ZNef&Hvh<{1O8>o zd&c5DR0_;GKy5r`Pm~DDELoUn5tg8iTf~i)qQoD$cJ8@l(g-m$Qh$DXe_82B#au?_ z(UA(DpCJyS(ke7k2mJP1{nh0j>aU~C|MN&Kok#m?9mXjwSsAB@D52xDh>p`iSrDtd z!7Nc^W>OWJs|r9{CjF;lbHM*KcIz|cSKT8HPCa0*jT4H|Msw{}v~nx#DgQn)2mGHX zckjgAk7{R}G}LKpBfzPaj&$1cM#}$(#7F21j#f7bkKQKVCV_tr;^`;6%OH`okVqX> z6JPJa>Ve9m07tBUTurA z+-;e--&C_rbN~f=!2cUupX()KDW7ZVK@EYV%(?#6>t;SuUNVJh-%jEZ>lESU~| z7{C%v!ePL11xQY-zh_7aj-`<*G8@OEW))eAL(>r5Y(WiX49tAhDi$@5J6P+|dcu6) zhEqGqG5_DXiPb8=s%AFTB0>|my3`hBs@jQtwjJ#eb*9>du+ULloSB|!(sKvsigfM| z^12n5?`IALG)<{;glZYL%(N)?&g)-b_W6OCwU1O|H@qGz{U_+%p%`?kdtk&tPvaT~ z{2OmlIZ?q6u8!f2MOVi$ZE<`yeD?_QM;zG~^nY+fDtqls<#VrCLD;BDyj8sHC?wX&c!Il7ooSoPcqLwi-q0S_%#@9EquG7JL0 zDTT-po7r0WB;7Y=tCxds^x_r^qQ#K~UZ>X}7asP<6S5MSsii`SKyf^{jwI}wj>L#K z3!f2Fd#cFQ#;plGxfSTD4E0KX^qUi(T^y70OYD{zU^URWEuc;`|4_=5QxBxL8D#w}U+)<}irDS`wr^FOqd8QOsKXWHY zzr@u)y6-==8o%Fl=SYvI6ymN&Qu39%9>dvI_e0W}l;xgvDY?qIU*p^x?uE!KcvyMk zDv_jUK@Vm-JUQS2Lgih_rW7%9O`VH=D}`2AH*gvRnTo{<8YV zkx7m2(1{V6HfmAK2gUPcPA}5)*3~Jd!Ly8h1JL^OWwU-6En{slp3c$6b8@e@-50Y&ap&d9Y2#Q_p#WW+&h4K)?#15aTmRN zEpg1lr*1ASWv*=1o5y7-PsJh!H{ERnM?@sRUo)|s^Tx`+Y(QQ|jhoB(e-~omzoW*v zOxPuG_XgHu6T=1H#aQHIR(tHCllP5y_cCEF;fy;1b_^BQW*3JG+-=tq_%|=mH&bL& z%0r($$(*FEGK^C>MA)*1=q&Yz==|EoSa=beJ>#S@acSZzNM!aLGbtIk0F*yJhv!G8 z+^~_E3IvrpuC|dk6eGiMRSe&XH5%Rf*R6q{t}65{Q+daUS&059#3)LrT9T+rR-gLn zQlxwbEbWoZHw;|~Q{O4ZNNHjBG*Qcqek{LQOc9son$JYXCh@7lo}8Qh>V9+U`&~w( z?_vhe^VCw4DL1?CJ^wPlG$(`q6gcWUe>z9RSo#yZ?XlkHQz4N|7)?aZ*~n!)9jn;X zE)2afI4krupDouAF$%g;qFvASG?x9jU<(Xgg*IZ5j9{&=Mo=to5UrUKDz8CcUR zNdK%9s>KhMcmDP7EgS7o)pNB?e01?xg{BE;9UV2y47z7c+jlxQ9PLvnQs+E8{!`#1 z9=RrakV{ODTs%qJcUR7ie}S(|Ts^grsp^jK+luGIOZ*|UG?9-6#j+D=E6bEta!M-grzpIfE}kt7{OAL^QoI_Y&?OSEQhf2Oa!;-*UU%`J2gFd+!xMdi)VA2rhanI zi1LxAQj^De(vpk34yiaf8Q5TZd|5=Dly}M^l_cjLe=s@b^qS->$lwvJ7@zsNY2XFK zNGIb>R&Vn4qWqDPx*;7U=_V4%F!4r5s)Rf4OY$UNcQ3&cOTzG*6k0v_3(sg4bFpmM z?6Tlll5ZXdD#VLoR${3D`kqUMuT!d^#pnt3`S?EC=jK*QwHLre_hNjU=TUy4-lIFP z9r?3;Zg}>Xk}=vcZgx^H9}}!Yv(`{wTll>f!!I@q7BGEl1M*SPyKFb{^vX>6Q};I5 zK~bj?-9F9}%g;n)!=@fqnh6B8HwI#5YeY0;3FL&wAyUnl%XmYglEkk_7|0naVep-S zhofCI3*C?^oFbVl?n^kYi?G2vjZ?+6>B@CNm4qHjZ{pEM@niXA=%HnN{`E^UiW9 zpy{g|aAuh>N~vf2_vQvpWh%d$d=F47qAi#DXWJN1)YeSzS=T>w_pkd=LdhsEsA|^j zW95-OvA`M1x-!B@CA9lHvi|3w5c18o{k8j}^>&3ey0(qqk#&@Q_*|a=+a6=k9sD8g z7x06X-=cPS1!H2S3cKCb_9C8Yihr+*Q}(+x@(;l<=pR&TD-H|okI@{kLJLFg#bItS zz%s<;bMO={F1GQDodfO&dw;=J95lln%gsx{Tj zzDSHFXsxs1b@@1aF5BTdnK|HpA4mdBLmWIe&CrR4{H3>)#%r-MJgG;tOcFffQUliJ zNO?zqM$1^GBr&I-|15ANl$9n6^)8KPU!{TW z&|Be~OOg-|(eM9%0bMidp?L0@TShBBh>k(u!+!tlp1qY8Z36t3r=DD@jX8PCKUax{ zibM{-kbiDtC9zrM(Iz|9R@+MiyFh)Hb?_pl5k9zjee?XIH^_!)c{K_!S<+9QPgA}I~dKY#KgorNAXB;MA|*) z(hAQni4^tCTDiUtc!gC!-YN$Yma>na_Rt*$0^4vM-$PM{)3KMZU1fKqCsR34br;{~ z@9D2lJPb#97+aR`C!m~|Y{&erPV5@e^&z1MK6Et*j|d=qk>*5!*#90dx&ID4n7;>N zta(5sV(iEK8!u5@fDl^HBGjg!kM2n%!zb?;yzofU_ulgt5uLJWHrg^9ZKg=2@( zF1c`OK2~<_Y4a=4x@Vf;e`ghnzX%Yw3R>wh@8kur7dHt@`f}7Fb{?$@VaX%rLfK>t zgI$r?K3@8jXzbJ8Ynti+YL{ttUo)MZRi1kToT(z$;(f(uGB6GG$REB5M-uQxRd!(6 zH6HViz2s~~6uT)4KJ&C4iI<9a;33U5&7l!8r%tAcB+a8>QChGolh@v#L#+p{M0g-r z*R`7RR~ExtR?6bl;!(f+JvcKdfcq>!M=&7*Erd%*+eq8|3syyFn`?kaWX3`L!d>&V zXt4|ZxrHAo*6<_JPSKUzl*i8je~I>{HPpKYd%p@?p`|)08WwF`IC__ZwLoVsLZ(UW znGm&)`j383k_x<2BtRvh$KewRge}_R%yWHycCfc+0mW&T(p!v})vBkxZa?aO{0d{k z`q#`zbQNr}QEoWqpM5zYpK`)V#AvT>w}{{jLRajxE^(rvnMMMlCQg%eNdj_`y+}*= z2XF$D`F{jV<^Kr8G$LjerI&w?2n9OMfEcIXp(;;n<*A4U3i*GphBN+8d4t%f#0mOK z5nVuIGYr7s+SV7sY5-;rbUJHQ1iVthq+gnWJ=3RoViNx`qT*ENH1IfP?jVxN^RStu zeea!syl0SV@H3}=&SBKP%|{~U=$L=PTmdj;W5zk2+GGbHY zWA9mt6XMt0k$TPBeerNGgkh^~Vcal7k@_Rtrp;!BE(#R2t z1EdFdUlYSx&2tgfAildQ5@lu9E z8>bP921I{NLbN8u3QrpRW;kO+G*9R()&4`@m^0(yGn0Y0Q>s(nTs3^GSQ)mJ?Uno@ zR}4=PH4kdFUUgk^>tWy_)3rW4OyJ$YBGy3@G5(ag3m&+A`XxZcH&Q7#k&l;Xv=Qe` zT{2lrS(py`(y?Oav%y!@!Kv~4`PN+R>G!+z>U?kk+d%95ua1{;_U16P8*|-qT*WVV zFMs7?VdoM}t4|xj^=aB7#_;cNrf7w%8uFUP98=CVQm z+Tce%V%*GMjh)165aGu*06iT$?+*umgvBy^j)S4*C z?48mInMo##keOB|o-aoEcC1Z;{;1$y8u6^38vC}(amop~7;1e?$2S)v@!Sj%JO5-l z^};f%feO2D@VOrbRQ2?^nw&f1-*#zEO~3WzH)l3Tufk55i;-yt^euX#ha}(OHA_x$ zrZ`!cj`uqebsl>E7Xzw>sj)!|E$i4tb(h}A?EXApYHH=*@6sB7?78G6PBCdAZF|wJ zo;y4+HU0qqH>Kwc>V>rD>Z_EV+k>7{HPq$a@x?FrPx$XH?$7z4%g9n*__Rx-pNAdu zd9aUg=bGb^_?4i-9|u0_GH96w#5^0oHSFJzBVeX-M_rs#;ga7C?8()iv+;TSQUBp? z#B+d7G^XJ7fj_$p=a{G76HGl3DqLOQ|kF+EWv z6Z*XGcBz1Ed;-2Q`*giIIv=Z|y*0P4DVX%-rBw4P@ZhBOw_$7CYv!d&%C9 ze5~o~oV=Wvd>VUne=*i{ZnON?KIA7NP0d(0*CRip^KU<|zbCGlnR*A>z|49v_6|pS zIdNQC4#@QMymFG%gUEo8h7_7RoP#vWn+qIm96-IvXRT{!e=866;DhohuIIci091KXn8{+%XEx2T1b#;b!LIJTBN!|`qp?8Ej~l{v>aIO#p#C>3Lm>Q!B{@U#pn!_x}3Ad;`v#e&w!`Gpc&N_;Vz z$dRP0f-6Gq7&-#h2gmX4KC8-*^f7eJn2vUzk)6`Z`VYJ2%D?;BmNvvj&7XT+Qq>}k za+outm-RiBnboOg$4ZA?%qheyN!;w8VH_Bzv&hTwyL$|LF76)TL7D8ZUUJRW%l033 zW#dYyEL>I7vT{33DwO7r>?QJC_(D)@LuIBWfeqtK_tzSsjT}ph-kA8%K4Xbigg#M=U)yjgWn$`pRCIauIILmeT+v+x!vZeK|_N#~8 zj4wv_i^S6j+epB2-l874NX!y}KQ)O(1_aI*qdw~2jQFg1h?HY??85q}IH1bBC!mrF zJ7e;rdjD{BRPW|KV;}ic-$(jK^=|W-y5e&d#^G$Q!SqR2Vm?Vm?G0FUb+RrzGoOBo zaNx>Vth=YISJvrE;mvXw)g(nudREhJ_RH|wB_ zJsk&IXuvbJ#8x`9bXy!rjq*m0+)DOZ+ALf;Hx05Z0ev{0`b%dYhxRgyyYmHP^(NA6 zNF&Cnw4(9*V)&EXHLCZSo>9G9`~T53V(w>MdIq&MRay)tl6+LDGp%i#Wv1!X09#Hb zhHA*V*xk3+^vT>Wzepd+b!}2D6_>U`6S-B-SXj1bJ!vewTJhQrWGh%#SsFeHsJm*P zg+$1gzEgKSt?DR^X|{`JN}&CW`)lT!k#5Mp$9td^wvLB4G%q|O5Qn4W8$peXOp(fS zcYhbsO9U5!MsYxY&*FH-T8k*|;ozoEgUJfN)w=RMc7BY!A&03MeZ8C+Ba>WGofekR zmUZ17Nvc0-X0S^#0Go1gGpPrsb5XsVFRN3u_d4^Pg@!UGjNinx)-0g-j7J{z#bAc;o36+OEyv+Y{4;e+JA1 zI_u5$uACTL&76)A(hps>H%p;O;lhGvz^jM~R(KWY^WfDTZnjicy3zG^TM}BOOHQ; zIdxYh%WjVXcf*%`rxu^ut}WV_Y3k<-q$vUFy-y-Wd4LYT8#a*b;G~9Vaa3<*->BYA z1ExM>C%E>mtvRtK6||)A*xfFDS6n_MbrsHM*#q3ce;sEUB8AT4`#PiM+dNl`ffzZC z*^ayw4Mzg3la{nEK&&WfCZ5Ru8+3zx0k*L?z)c+0yAf~DU(|NRxki}kT;HN3P|C`s zcUshS8qAZ`uGda+4dAfZWW4GeIDI7LFs_7=C^BPcj;DBQW_kdRjADE&F3>>gY*DDX zOQC9=+fd4tz6||16Da?~MuKL{K9X+HAxjcQ&}5Xm95Jb;r!a!d$D`>8npsCj5Y`-x z16km}Ev_{l#<4U}RpKgnOgao+;CYEJ7ZKMuFjKiMdfpc_plwE}2B`J$#}`0xt*+~7 zBlEn{M|K^48+|cGL}l_n3$X5cFx!pl-7+w$_u1ZmbQ$!8otC@ma{kekkOw+tQ+Ywh zq$>MYozdB~IaCY99oc*EBpr>a?6HHABs!a$%uUjEvEkQpzc_Wk0#8aYy7%cDsV0*4 zV+q`3Ro8Gn-E^0mOt2wK#*bH+7Y-m#Hl;E8ERCe}D)iNWz7)@5%ULpd>&5GL0$&%$ z(>R(a?ib=&w>0Z9ruVtRJQ&v+Cm$jA0;5gcRcFD86AB=$#$^NZ#04yfF^UTq+&Q^&kh&@k;bB5ARqf%=khN0eJ zn8j4ypx+%F18c6n)a2Znp!S&nHt-hm#n83dE5O2{Z4FtmhU1w#J!&8+;#eHyg#LTybYtU^hSL|M|_x zd@cOowje6jik*U>e@-w;vOyy-k!=Y;$7SkKhre{v==({***w?vl!=-0Ss+FjgSLg* zRF1kO4%RPK86zgtZ-FNgSd@r}p9#GZ_Lb#8h$i+Ra04{_%epxpN8yH?n-90NG8hYS z=$j)hy(jbPBaXlWdv7E>l3l`-E|9{NdQ)s8~d&ohpqw_tdL;{8J)lHvYW^*+)+U=_Pkqsn8eTK2wp@+o^su~8fkws9w@J9X{^VC2b z*zTI(bzO}pKNl#M*j><`$@ta}u0^YdweACoAS3-5f319v|M5;LX&d{$3RJz@pCcd_ z$VX4v;PdvDf5nwV_y!aCou_nlpC)|1W>~Xs7qIwLi7%uI*n2(p0%CTCJksL440dVD zCHfwU-@2y1T9Mp{kbkNQl7p5v^GaeZ-KDBSdGiujl(FMj#6ju>5Pl%&-`4-ZHNzsH zIyBQWdvE;i37fp3;M%Cv>*dt%-;@tc4>}&>0G?Guy~jdsJS}WWu%_zIHTe=X?C$q` znas3ajr{w}q-?5bS_xYZG$EPmt}-0yzQ17aji*;)1!z*uT6iVKxW^ZGH&?ZH`Z zb*YT=+CD{;09r>6BblH&`(_Seeh@=S?7;CfJn7QcXd3jXrqi&XOu{|k%owhE3)bHj zNxd`5@d!U2h}!Bjrh^%ylHkcb#ym<>rK#JNs7h5~|4}6m8yyjaXD8FOFJ_#YDm)ug z73GUoX{$zonCk5uJaN?3W~$3nY0=;64#q~`VdS;d;gYt2+g{5Xpv9}Jwe?Mw>;%Le zr~ad@7FIFFff8+0s^t^L7aa~Ma~3PKcGx3eC0^WK!Bc*sdqATxnuGpgM1H}iR<1ir z_1HH*7PcjA{qW9`>|d??^D|%E*|&CgQFPAnI|+Qog>@|9alAYWel9rXf6I`&pJ&M8 z87iWyI^qkDc=lF?KX@QikO`^hKF!y_pLlIfx}NE3SD(@B1pS#4tW5`<`n|F(-I@Xw zyiruP-+#vzyfbfI&c~B=(m9}K)qF?F#!=mS(lVWHGD*Ge1z#_Fs$07ZcP>km9(5tM z&K4)Ja)kPDL6jc$IGd{LgYb{jX%8oLYY_?JK{?xRm2j-sFj=l+D*z( zCb;24g<}>gXgPGIJ28lhwxXE>gEg7-P!_rhpKLmuc%yA^=@l(Hy4lhluhf-S|3(3^tShra#4pJEsh7n02%Jqj+Y@ zk?yZkBfG0Q!)Y8bEH=}+UAJ0Bd^f7y}lf6W?(5lei|aD4zVbyIe_rgdkpAK^tUmo3Pd+O0H{-gw^(QZaLfgXYu}*=P`|-!ZCww*-=}1x^ z^5iVg*8Vo=52OpJD>I~~RjC1r`rX1Kv zTm7Eac;f2$0^r|`AI(a(*W_%+zTa3#wkn<$+u48tU^oU1doH}Vn zskW;EzQ1NN;73M4o;=A>CR<=QtqNf%pzBX7Feji8DV!XpfqCU(4tjyi04?FVq zb%pM@@z%P6mDC+rBahS8E#N=JoV%*UX$<=B4lLvg0;aHH+;N~ctd_9_{qt}q+o12#g{zQf^{as7R_}E2 z)ADIf5qRm~U2F|kO*v!0|6q`cX+SohY@JtKKe_cS-;9XaO8?!_F-O^lP$N#S zxRYVWBhx|ATO>6dyhrKwde7sErcdogXWhH;_mq2PDWlk1D5udiBc;a7Ax^tOY4J2T zE$X=LR?i-j*be9fsm62k%_{E<8+tXq9DWkWeHLKeS}W1N+J+ZgQ?a_CJQ?&~>TBVh?N<=-@IDd?XC&q^Bt~c^8(r+!^qZf}(Qjss6x9o$k7lrePp(A?RFzk-K<(E4# z-tCNZH(}DNu>Q1QRQ!1$TG7z0kdkw;zR^zzKgap>I{mowKR4K%Gnr{Ye^}37f&Z@S z(sH`ljAY2rkNY-WBYlJGZvwZ6-q9a;!}S9)(#aKvfvZLT(e=uQ1!>pZqo4Y z&nMQnCF*L-12*{IUN$fpJR(aaCd0nwDNE^^NZ=|3ylE-G-^u`DoRkXWJSKyyrg{J1 zskwPo0(KGJrFeHLF})|sS(<9`Hs@QhN(5#Da-ET+4DY`ZUe8a$88y!QIiPFBDh2b> z-h%Nw-sd3luaEvR)#iQW)>AtJp4MIYhALzA`GgB=l8`}h<^RXro5wd*?0@5PPWGiu z3N554JAVok^L=5243ocPq(t?W1)k0aiAcCkD1+if-imih8 za=qMp6GbmjxE{PJ(3YAMVnPee^PZF9MW5&S{$8)=uV4F`%vomU%$b=p^O?``{;V}U z&5YRZOBZ}dQ|s2-9;CZH>9B^KwHB6`-kG16vspJFW3~Y6J;+QnXZE`399FoN0TMTz z7nDhpA*G7o<I~X-aGFJQtbxN!Z zInY}&aC@MW+ssYlfe@>#C5#Y4I@UY>QPMcFI5Cc2=_phrMh8hOmZ z`WW%gZSoA!c}T%gdoi!g!q=W6>6ITzLRpX~({~Xovc5k1G3=6}1y7iZQSU-%I8v|I zBzuP2(k>ITZ>CI!ukSUeX&GuN%|zQ}XNx=%jA+qD>~Zib;<0ntG$_d2|E^Hx+Lp!K zP)>CQduv=XXZO0__2nu@a7Xc0?Aaw8Nip(Bi7R*y70a9NQb96`7QG+-BQK1}{^i1Z z@z!64EI&svQ{kago^w*DlV}_DQay)T$Vpv~Se9@Z&20VLb_SE};x!Nc2YW>9_!cjx zcGppyHse6cAWl1!B8Mw-{&-cnJn{nR(!O$}t6&xN(0o8Q_x=;OwyzY*YMtL<- z;%#ys@;9v3T)=o%%-~MK_XGh4A=0buOG^5%82fhNE8fVDR*)R*=A0kWTCRE?GF}pS za+H!Ej9E$K-rT<*iu5s&tL5@h%&_kBw5?Qc{mD1`N!8}8_@#yfF?7x`N#kZ}vUs*k1I1I2dB(^e_;)nx10jg>$;C{XqV{?(hym4NCg z!(2VA5B1)yfqg}sDsp#Uz~Acxt=kv)qF1z4#%-sRu4!_Gr~;H!8!>(Ws`^z(7pTQN zQN9Wpzos#AD`;RyL3Xt;;5$5aef85vTE2=qRk*k1gm08s!rFciT19W*Q zXM&#NF6cQ@%K12ahx`CkZKx8duZzpmsj zUJTPzq0rB(S$too*D>S+garsg5eV7-?3tGsvJc@kgp3UMap_*`WVh1#7kI5zN_e>{ z@D^05=x#y4V;@@uZ6jk}KnBl=ou7yK9K<`UihyQc1Ig7Ok5;H(HR{KTj)9iSxPwY& z-L2l(Dnow_yT2ZAG48zfqN-tMX_9yKB;)l;a8eAgx}~^`de63L#Kg8s)M~$TfNH}4 zUR6&K8rC!`>nfYKl&b2Pc9DcqlkfVS`p4S!_dV7gdADkVvi1_Mtosa>a6dTdd%!y? z#!g=#`NpKqSk>4r#cqt`-QV!xtFir8i>Ymya3{Pg{j;K-b@d^z1j-y}ugC6Z|$^`}8vCqNYezsCG7MdPuqzcwC0ptWN>uCC(7@DpG7^@-u9jV=bZD`c7`&#|tP ztByc7Hot4it2CF`qud(ZjPb&*aJ_Xk^;b?{{OPx@ru=#)yD$*kDbug#>eJL#>_l%w zU0>j{Uiz(l+FOL*k9)8E$Znv21&- zJ4f6?uYvn07r8TYGKbdi%TbIw5c$D#Ni4p0=Bw}9WwsE!KQ z(hIm!SUu@ok2`0(NB6XH0jvqHfojFn9a>^!5m@sHUDt;$S7(?hjR^kyQqo2n< z=CzfUgVLZg;S3zl6m~~ak33b@f4{P{h?l3{PElD}(4Rsnq&Nk6!6&ZKyfPJQt60;$ zJ-!XN6gfhg0`JGp7VHM;Q%EU&stCTl1YU0GSgv<4#Yh0Z-gGpu`Dc0@%~Ah|M+2|_ z%yO@B6d!@+QMgH#^a3&d5YHIk(M>rO{-YOLW)`C)wQPMpcVjR~LMaR}RdCFf_k3nx z@YJzDVm*s)8Eu$r7!}6=EpFjCI_l>NJHvE$W1;3e zlNwW z?j^L;*hwgrG14*f@+B#_7YY}1mt+&9q;HJ@zIQBq@6jF5?cQ>fF1@7b??*@J;!AWq zkH{1LuEm`V(^;oZol?{5RAwsS7EWDQ^sJSvHWewgO`oQ7 zmlrD9$_qiSr!uJ}ls-x>)3mlvwe3ptD!9lgXL za!K|6!w>O#n{P;G|7-N3g4h{ zu5o5uaiL!5fkCwG&j>9EzS~UN_5$ACIJDw}!P~8Fx z8~@*62YNONvdsQAMN2Wj)~9V+!ok9hjdMNd z&<rNe5wT~lke5?%rosFk%74sTS)9nr zG2h7g&uztnAY=6nrZXOGeL7d8 zgo`*U+je9gu^05ulVk3fC$lk6zF;v6^JIp*v`}+~@mMgMEu?+aKSNqDLzec>kVh5n9VGh&3?peMqBytrPnx;PRm43!UNOYmIpc} zi=_2qT$D!-Pfp_{8{z46oB7UJPT<$qhyP-q{W{#&=7ZI`u$KYxw^4&@4$d@3((h0sWi@ScNzHyym6WN^)b{GVct z&$#YfA%Ya!2uq!@LFkenD@zdQ6X@rvp{-xfvFA7olgjYul~gmv4frzxR^ZWq_zJb5 zD74DpTYg$0^L3H|@)6SmbC|o#;7%S5lw2`$=G=-oK)<`|XrSvdN=Wm8H$K>vZLrO` zt>aJY7=d*?!du-ZvPXfR7H41NlIQKS^mxD(*XP3W2RsvRY;e0p`&9(EE((E9MZDS| zi+!8)E2=qQ0(bD85HS!w$xwN0!KW;_aW4yhykncyJk@$<@=}^#(G7@Kg1RFnYWsD~ zBjc4ET5cR|=f6%a)0vNbsXH;-e~IeRzwLq^ZgRvz$()7Flk{2KE4p;A_E!?LxI+O?A8}dZ4gLD~QuO4T7Nz@-3rO}2j3!|Y8K;6R zh95mh#}M>W4RMZF;0XnDS99eQCNFSF#CZ=Ad!0*6-+UA6cZHh-P4LLXK># zjI%-JJcT2d~o#+E(2xAIb`Mv_nzH z0wVnY-7W6-k)om|rlEhsg(YOQ*&6~5Ay!}YM%i*BhfOfn3Jv$Tt& z?{zSF=P%^|zg3-G>@EsQ3d;5OI>aLnU0Tjv)s1zLvxKbbFR+#iZp~W>RRBfa`BL}CjJ1d6b-_)gfmQIC^PPiR$2fpEe#*a ziatZ?LTOQF803gN1G|Du)fs}j?9{34BGcq{u~^|sKB~4c80pX)pp;w{Y+n8mp4TuN zrQPQiIbe?tx~BXLNv1qU@d)$yKV{84k5-$AJ3w|-Xs(?_8)Z#tgNYS--XF zW8rgtf`>7WcS{`MxqlQb1Gv}X+2--%vWA_16Rm2Nygph*Ekr8O)lh}jCU!%@CtlVS|MG|Nt=vzu-x(7akum0xzdagzj-c`7su}t z*4nf)ke}LgzqX!1XuUh%cJO(8eVW@XNHR2SCARr4onu&<9=?<=mdPu`c(OJ(6bSa+ z*{0c7f-@Qf@5qC=S7i)1@ETsuEjBg>yj|EKq{<-!o^k!;ADRP~yF5Te#qKgS4@f(S zK)hq!%UvYp3Eph{78Zqfl|ZIF<{2yGA-%Gs{NlmSQX7~g(hC$|{v^0cseEOj z=o~Yg;ogQMMqDcDW#$ZDy1}aKkdR}SgKs!zG6YBnM2A4XF)^oZd(8U)(;WEWDs3~; z@s5Pn_TN|2bRxcWGUU^t*2$IBzG_Ay_d?S^yJ)@0e`s-qp6&RI8OuxTGlTNyj#);w zWqIRbj|1&n-q zp~el1;02J1KFf^!$RhV>Xt@jNaTjFzbgf3t2iT6|?7!?1o~~A(eM7HK0e6sW-&0%$ zWRfEr&_-7ay7xW42BYJKH47HfGp--TIC%1^p_ybKpmJ6-V-UqspI5eoUMfGc}uUKIr#6CHL?T{$o@w`{HMa;|myYiU3ME=&N$gp6Wg#VL&mzf#4 zou2cLl)h#81zz677|}Zl$+dqwW3dAX*RV*a;iCQ;!W)n9b=>=F4VB><7G%dx#jXQf z_Z>Y}l6|%w8zF1o)-U+3b7A z|H}g`Co|S1G8h3}ov&J%`g2xz-6S&f%TJxI3Tj<>GNB1LJXj$rngfq^(zwZ%kCFau zrv_G;tArSzv8uQle2Yw8bnY5x1rbv$ zKSw9=f3n~_Y;Y+(7sdZk_lWkRgtB02<;N&Dom-}V#d5tZfl8X8vAOxaZNb6j=+wAr zGRPfaDdGR5OzV@g%&vdwJmnbzC4BtWD!XZs#Gi9_GqAek5^c#NI#>B5VDP{DtM7N` zJe$|~-dma@U$EqHU|cOmn2In0fko&B=2bhwUW5jOcOYw{`pS{m2S-qCxEyht8FsnN zfkho+-aDBd-Ph4NS=Osvl4CR3Ki848B%8RcfzBA%1&Xkb3hxKQG>g1c0l$aZgVg)j zWQ=z`l?nRqu84xnUF~g$hb7XYKfw}efBtD6r455KrWH*uby!zf;p4ArTFER}R6k>t zgT?(7d{&hdlO*Wh`E%wE!frwf97H*gg5S^~)pl99eaoP2)Jn3cz3+KzNie0AxDuLi zZ|T@tPqKC|z2{Ssh1f!r~O zn1<<^EcxJ^M%A*L3VFscK3&&BIJIZF9{k2(RMYvFstFlEPgk5>&(`Xp*D7*+>;jD> z-S5j{(eg=(oQ?e&oAfWE(zS%MYg*H9f+r@ z#-rc!QPWj=aE64M?htBvE6$;3Y7>N-9;Y>pL`?+^hEG8!qpm3u$m19OU+VfF&lmB` z7Lg-Xzzxo#Zz1sZcDTl64siF^J@wbRr)p96Eci$z-bGcTUD}3O7M71{-081)KwAr2 zOv)4Qx0L=AYe+OolY?ueaD4!6Jdq;{c1Co~9fy{%P&xcD&in%1zuy7*#Akn_N`|uCxPO?8lxI^*u?(L z^BCjFU@|!g_0a5WKgfohyAFw>7^pE&mebL6}~tHD2JycwW6Bc zTnP|g#SKx7R8!|T8e^lpt$3Afg;F`{|5bC1Zx_4Op?yy zu2_xH0sYJe>~HFuWe?iI>t4RF3U9j-UO(tsL}}E`S8lH#qQ;665msWkPcEnQg2Klt z*j}=8R$;-lSDeh~2Cl+h(7ktRMd3#ms-SOG;C2{+xT@Pdqk*QviLX5B@eDnv;)RJ*5o? z3i1THHmA=6#$q{3zJwzzI)4C__Aej$4Zs8$fB0Y%FhPJdz-)-{8w%!A)D7P$2EGDp zG0i}?nfshI-7z*jx+RBuR1b*&|0%qeCcDj;;Z9u9`r<|V{m#co_u@4X{_hLE3tk_j z^|@tFTc4enk9n^NzR)iZ%7^w+U*P_}T#icp=J&zQ#5e&*i~I6j6JS*$HXf#Ej2QWo z)|kPs2?Q#7sC-z;=~||A7wHOsLq~vLyItzA1_HB$8K$*6bIm=F3ZCFJr{3fCT-K0J z5oo;aGUiLa!SWj70lt&s0&Xq(I~}#T+<{%Shu$mc-oy;>Z4^axFa&55PKl$WdrM@7 zIHDs`ZE2T3xD`EybdwS$NBK6>(kA1}bq@5^u_fL0ky;1RF(uuNB8r6-0YBe`?eY|i zD%hB+i)M518u>8t6ijW8lxuwrjLK2eE=r5xajh5u=;Pbv503)9uXvjqkwk6R4+mCs zj!4_$o=y3`Bk4QmRa>|bADX#$ zeJ5mNaCK^@6RmnUV22%SYxkCFDv2w&R$E%NNtI4%jt4U64_qyss{>_h( zYip}%+N$c|Y2@1T)e&^oOsThE))Z!0sw1$nI!3tK@SCgl>RrApHQT{Nf(x#Q?D&gJ z(JOsQI#k*#TB*~mEo|+cTRmd;L-6Q4l&c$;z}Ma&JjM5*v#79x8AIEF89B9Gky9IF zTG3|dwL!MEHYnn8EnS>9y9KtoU+JXLEKZ zS5y72(?NNww{3nbNy*`c(P!1*S^WJDO7#j)8;hqYr?)HVGx#a(iVQrb=Al?z$)NN` zal10-FF`qKD6aX7@U1iOIrmFdZBSAZJ@PMD!7tgHu^YKsCCy_-Eh+qa+a=UT3Un_? ztMDa`d=WJ`Wf7CrBMLp`S6{+^ox9imUYmFwLMv?UW>3h@nr|rP@ zw}VJH=YrzS+8biLi}-i>!nq`9Eve92wLw`c+ACe2N6X=Y@{VJcFX-$vhqg@gNHSE( zE1D?^;1I_!8&=!ybye8;kBT0-q_CT&oB1cZE|<2jvRR2#iH=AclS8_nps7Yi=N_|k zw=J@-Pb5h){>7!3{md^c1;_ltA{zq)P=8y5&mFnfcY;X_wyNoh_KtHMR{rB1a=937 z#I`at47Y&Gu$kX-L#K@i?in8w+}#-y{NUM`;QOaYy3k9*Nz&wYc4*9vrmUD?)A;G_ zQbSDeqlZa`a93zCSgb>mx>r59Ju-D_JC&+_I6mgau1>C9hCI6-{&jqfCaDGO>ZF+9 zpVago%Ej@!561-G8;|QbG(WDVrrKg|yrYf@zH=%jxN|&7`|p!tf^VzQ&O>8@J31$~ zOS6z`C~7ox336;l?YAS>Tb(3R$T1$hsYVJ@OmLfedb=nqCirG2J;$+WCvt2>>aC~l zEPwbgl#cgnJT7&7=AXEBkLC;c zs4@0*8`2hfM{54A`7=_9GVD8T!)?T1sIXOpS5AuRhMC$*SHn{yjP`-{ddP)Xuj0l? z;M*FeQ8_)ux6Oe(W8EB<+=o!Oo*_oW(`K{aMKMWYPBzU5FX{G?6y?Es(*Svi5jakv zKw=N&`A=BP5Ot{*7)W0SvtYBUZNuC@Tru@H&LG7%7&&%$D3Eqj>!S8$-@@^F$ql;q zvJDlH1;B}`JU9}xXK$bpwh(2_c}00s9oA>9V*jkg$mvb%C24am3_}WcFzYUoDZ4=Y zon;c(*3UFc% zNU0cLHY3Q*YEUt1e-0=YwHZ_lg4QfI55`V-pwG@64jh1A(dcOgygh?;3V6o7HkT1p zgal7bhZa2e95-~X2-J?^QiTE+f(#G4$`Earis>x52O%2o$s(Ld5s@!NB2xAMLpCCQ z9N~Z3qpG}#S7|#r4u(BT< z?)qsRC{0LAZ#AiGEHpKtAG`;c27lL_pkWj6-qs>aaB1HkpCnJ{3!D_t+ILrJ_l!@X z+UUjv+M36NtJ|w!$xPBYT~c4*fN*6?RZM;2t^(Noi{UvS6nIy-`dU>&9r1TAk^0n< z7reRI~Q{y zsF)E|Kg1pIA6|Xo{MH%K+g5{9pq8fz^-1hVgU$r4%ln+fD^eW^M0ZgAPwbLRa-Qxf zAOSatc+^tR43qbY7EwOhR*T}o4{^*WRnDag;HM3phNm!9r!T$h@2rU4>;ji?;70oX z0jG9rOzpTVV7(-(`NB;3`FDKd*tc<~-8n8VYXgfPR0Wb}FxYP%*! z_#Re704wD&FPS3k__k8g@y&`^T2Y5h6kod=DBAIx*tY$^qKMxNOhZ^j^#z9anVaL` zpX(I-CSoqi8w@SWn8xFA13ij{==xc48jrkgAkI}DS;GLF%RJJ$D4av4WX@7|ioCv0D;n#f}C(pH{DHSZ^8To*j(V$JZ%!_aH8dBSwAASgst%)O~@& zKoJSLVj7fn&^z!%*D30&EQ37*8|2^~4)hEVFz+>fYr!-4Lv#EtwjsV&k7qx9 zOYUM!u%)Y4*+mWUbpt_1(Vg3nuqIfGw1OcAY~Z6Jlmmk<9|3ZXr0{H(+-I_zfaMup zRTBEbat+b45B=m3G51mvyfIv042DGpU?Y=?Xv}ICsn>&iy4T+1Oj<@VTD#XfOQuKo z*F5;VHDgGVJr?|OOVFfc^43^-uzs(3=)0h{YTS^ZRr)@-Y=op(5}DM3BJmi9Rl~oi zlZN-{wpqcU0tN}ZF9lOJm@$HNy8CTCqcaNMtWC)(WXhbP!Bl#+D*;rq+x{RM2 zOw&eF9&@h!@HTBKWMT!t(6o`c@>I!gwy zTj4c?f6+>j*|1k91{=OG0ttnof}`&&+Q8O^Ew-1?x7LXoSa@0j1ubB?8SRsF)a!^M z&aljAbN9~}*ZlTdEIEa66v2s5jX?dvV=sFv z6c}}ruGDu4^Y&gGQ(Z9cE6iF4zPs%qAy7>qL4b zC4EM;5U0%m6_rd4)Rp6?v;XKw;GWB>ZGY3K--L8>7${{y7cJfu zvqwrqv@BL;)dp~Am55=KfO}s9#S+D{^K*jxrCi=D26v@ zE8O>Ii(%s<_r$`&TgL0~D;9nkelU*nVT+K5cYGpLEm#Z0y4SYjlqR1DcS;G7gme1lzNd$1o)!OH*8oOds3OvA_Ohd?jM&Qt&01D{|-E-Cp!Pe~;f+uQ}8&tLG zO;PKoK$mCKCn=a4GS`wM&4w6A{R=qid496vnM~3>WG(f)ZZbr{^ZIBxAtV2P60WlU zb6ryV>v?CoJCFZg-{UGaU?kt1W`*z(GIG%;D3gH-n4}qqoWzg&N_*K;57{Y%L zit(IP{m*@&KR%53XL^i0D-r&VXGh_gsR;KYxM*0a*(6Qh+5)*R;|cB|1>L8s;U^5d zxPN}XpWe$9orPx&od4zf(F+{n+F{OBe2Y~P4EwOYb+nW zI~8~Le6NOYr#zGtzBV4$-u|AZf9rd)k=ep-s$5#o{qP?c*c~N)5A4tFnAK~NxU)ew z$>ql3i+cw8a}<9O`{8R}S2L#h-vjv<{Ic6=DOM*DHLHL% z?2dWbI{V^x!BdFK5T8Um74ZqgMHdseRX@=@*|6|4XNxg6Vz$PeaY(TT@o2=m5a%I& z2TwhINwcZxcTcFneG~4#hIk0#b%^5;uSGogqT1MG*K9f*2wtT&dTQfuYqxmhD(eh9 z(}uVd@dCtC5SJsK%y*;R%Jjd@QGilAkzzdJ%ZT$4|A2S|Vjlg|^qY4{#?^0d*MQiA zSdaMc{OvmJ?XT0FZ+~;dDytMJgNUho{W@Yf^w;;H?8@K0`T6Llt?wbt8N_cRK8<)A zVmIOjJ{Pqw`d#fm!JR)M#Sz3WBR+um1;kB=s}S!IYc@Ho)fe}p%~Ze|JR3Yi&IV7D zbr<*9jhrfD#&ze)|6U!-{rM;09Eia^MeIO)4ZUgpT`d=*>{%$=hM2bX0>ref%Mnk( zTSfS$szzc*v>W{8y&UB<)1z(J6}^fu5Z-^DRWaVATP%=e$}tBgBVQn3zgf=RglQE9ZN0Ea97$_7oHN43HU~ zwuVRZq?=oQ`omKBdbzOo&}`~n3XF^m2bUfWobLR>r;#@&v;}Gb9F5q6X+7=ne<=cBXMVd?L9F z>34NX8b9lh1KUufp?W*hVs~34ZSV@>R6$ROF=X(PHwz2pZId`V-i}^B958e;=0xgc zU>w~e(Y1Q5P>bEa*5cVaYVl;a7Au8X43so{qmyiU>rzDHJwQy>?o-^?h{T+X4 z8-B+KzoRa_S=_YrY3uMyw`ZKQ!IR|pk3->W4H(HmLjs+#NG+YM&IV7BP{4RIu~E#4 zG8s>KVq#5VBSng>wLE?SH8%f&7n$gMM~`pMf7>tJJ_^r-1G#!S%PiBm=$x9#&HgcO z8Ofa8_Fd5Xne;K7edRNm}_@jB5W)n%XwtX8+hV=lf+uBy*twnrP9Wa{U zV^`BiQ-%V6>KSijF@nV#4hO6qqF;kc6_Pa=LC;Yr-fKs*#75kZHb zLD&UMw9Xoaygh*>+YuTNPT~CXHyGl$3;7T#5uQPqj%#AXEW*w4EE$1wsyonAMRnO< zXc_`NW{RZQ7kH-+ly7ZhvkJDp%DM+*MehR`V*P({qxqg)&=DpE7HC|+35^fa;(N!k zWZ*%ncTP4^o}(VTp>-PtT60RcHG>>mjXyFRx1WH1JP{Yc^;aw2s)@ zSO4HY&5SyKkr|beVeuedx3RFm`#K~+j|$TImvOZ563JZeUUM-I`XL2gXO*T-U7sS{eWvOQ z%#T1`!+zrNs^d7Om?{O{N2@-=u~;~^SGC|6dH8UC8}h5_CH-gfaHg!M8eM&Y|EHN% znwq?e1NTq82<%g6Vd{aN%xtn_TDagp{=Yqk?>mFCBGvPQS^du%|C?vI`+oZ@mF62fOO0oBI8Okr=;S55H(TKS!Kv95 z`The~ol1o_J@0&`bTRnxkqt~Q>($wg@aJU2=Rqn(J(D!V^rp~ye|6@0S>*l#*TwaN zO&f%(pE}!+_G951lcYAiBwXE(b2;*g{D)VD0y^O-?>qmqv^dYnQ8MiubrwzEcqRD6t zmR;!4>@sq9nKFf1-Gj5p_eYwNg|itrgSDh70cQ+bB-{fEB;M#FAio#5K{E>6vp#EN z{Xf91+Trh9v=4mL2Py{hCLm;Lc16_FR<66{Xin!Re+kDD!F0h0GK1cw(2ct@&rVoJ3rM~>FdFplSy1UkK>t?Kj2K^ja zFMAXI430N}-zDmZf$pF57jdt8@$2g(PH8VYX|j{)7-*?>da3*Yb)tCem0N{*ev*jW z+>}(ze3*n)z*b&nWbJ8O%mxG6;g`VIeM4qAxz*M*@N@iu_xhyVuI53zclo69g6>;U zbyj(BwmOYF7}$7~q-ooR4Nc>4QR`x>9L=}~?Zcjzy09iq5W|)l=>JV&8hmsuL;~#_n>kv8VSfsMN>qaJ*ls)NQZC{cClOf_B-I zDeclFT)SGZ5z`inP`A929Zkxwz919bKHRx2-KG! zK9-hZy%scG+|Hzffyxd8+V1rZ5s<2h@lYVxc@Wgrqnx3XU^dV@jtAw;qQtmLy`$W* zNY8jztH0XEQ(b4$48ZGD=&La@4L5hiJlm}`-VUp z@>2(6KB#Nm*S_yfA=M`6LA->pxAJF?s90ZlZ{_izI?6~nbIWvOMUjYX2d$KdSbH!E zBSP$7SE=w`{`quJ&4`Aa2&!{QrW_Jjaa6hsa@a`+1JgU!g1<-oc7y`yAxVjtqf#}R z>+YW^Pqc1|h%7>YOm3MCNl1)v+Rb08-XonNnAW7TRVz85Q z)B@#R)WeDZngIS$BEcop?iV>k`>zF_|9Mj4avi1I1+;a?u#6k--Kd8iwtv(HqsJ37 zgGpX(jo{w}UlTS^&kY*}zX&5zxrO?yc$U`)cT>3cT-!l~qyX<<>6P|^lRrYR?j9+! z!IHgg4D@P}&__RXK`(j^^}6G&I`%L_^iNXzgWtbTSI_^~`@D{Ja3Ik4p}fyQ(C(QA z3m1}E;=UG${+Y=)(09t;Zc&_N9K+IYxWi}cS(d(`M+7@Nxkv06mc_c`(L1?3{mnru z>;&d~f@4_r4fhEjLlSfc{m%QPZOKEG-o_p&ol!;&;x)}V@cp+JGN2qziuZlJ=ZQq& zZAam4v!!iD=xb%*Z6C(lJ{`6TtP-PqCgmb*@fJYO`|NV)dqc+?^A>DB^E(a&9&M+# zjMNfzIL7h8z^E&s!0B7G-y;u*4vIbiib?#y1aSjXdnlmmICfcGAZnual1(m=Fv||` zFv(@X2?(skav16@N3S8@z^XME*+;vmLcaf}LJc6uaGGrWfXhd~X$qohDJ0##U zE4+X1NV)#J4PF|C8@xjlcJ6(Da7-~bXqv+7?s(36C@`VD6y8Uc!Q07zsS59kpC!KW zkXJryRd`Q!D!u9+`Dl2_;6%2Sc2%`x3L+h7~+qG3u?2evGfNI&u1Z6oH0#RgANs2ouAKJArsu3q?t^&|{_3)Ub~X3d46QGVS#4E8 zH=h`<2Rbk_!h!>MZ)3PafkBrKz!#Q*EBGa}0x}T!&ARkhz{heGaj}g#P#A)2~xqB1ewn)#y3hC4*(9sK98KMmM|AilJ^o60Fq&?k6 zcj}EnqMf)9(`J9}Min*N(4v=Jmjt8zk*6 zH>|9oJBfP1!b!|8a(vZq%LIv@dXG=6(8H$m3UnQ=1?sLkxgx|Hufo%bsLtxN9>M4p zpH+JAx{+)``}3*IMgi~aW?)2*eit)@`hy$RV@CT;K>bALl-{%(V!Hy?)&~PWT~_l- zuL0-ueoi~RcK))`JNSm!21`{b1m=%TnXPKuO1H!-2p(KhyQ|d(avwY!J~@ypsZL{Du-Rc zGuHC*UFI3r53HnKA^gxsCWf%@!xObE`9n5K-bH}NGVek`zhY4FAj~+n@!pJ~eL=X2*kpPrLG)Q*HmTKM^~`w$xs3gQhkwABov^^;Hi^zHOr$d@)R0Y5uqT z+q!JcPsA#Vmf6Aewkb-N+E-aqZ5M5ZiU%rgmvs5pl8&Gp;}V99O`!X9agv7arBI8- z?RCwD1mn}#mx~mc5oeT1%=^88qoBm&9K)N5Utb0~`B|;mRwzEB@HT{4BV!{5{jtAi zh3iGBXsXFlXOZCkDb3-mS1LBS}LS zNo*F(V{{!{jIyXcOel~Xl7OzUqepb&T(os4Pyqu$>MiEo5Y-0yGbE&8otsL?PD258 zh~b)D>Jnml#`=xUZpUf|FTJJ9Ua7!yNt{i+h$P)>lk#$bmbwbdXKGVU$KLiA=rd{U zCH-~J3cK@HQqZ!r>wDt<2=4PShD{e?jWJS+d9oC_?B0 zI-ZtEwS`*y%HT_s*3gLhQ!TE-kP*MXum7GthVww1iI^PL&vkR`?^@Izc*e7@wK29? zc6sq}8!+NanF{dhD{j9e_bT$ zP@wg4%CZjZOmZTNxE1s-8TLf1msGk-4B5OM^UICE z)F5V({lUQJp)7C{&G47GG<4a;n1g}l5R-(JZ(}Z`;R7)qn2py1vwG<~6ydJ2%S+b7 zuKqK-thC-DZb?HQiQT!V;lI1+-102?zU=N9WlzqST-g2wWTL3!xA1GBLI2TrpHULQ z4S-LyP_CGp)FBa>nk}&NCa|-saTZU<_0gkZr*ueU@KtzT={exqzJu14+LP6t^Boi z_|DN+(8pwJ9+mJi%p*)kHBg_=z^>N&(zIYGWJaj$gB{X%V96m+TpRQS_=`0_p8%4+ zr^dpbK`qBoofSq!+cE}iIq0zgv@M5EC?c_z4hgWG!u70fr~H3d8DIM$?!k`#JQ2s! z91`R>`55~(8A?)%`QgwJ360go(i|m1-a}Z?aQ2j}m;CZhY+=VwPh?D=LOvTT?PXSM z@0C9Euh<-5Tl}{*rlU0&4`YhvMX(W(w-dFZT@<;XJ(9twG%0x6jx_b5z*wY&emgL0 z?hTsEgGzu0>Z7fH@u>^&#jfih^5PCgL8W~K+wbLOw0ErRvHtxEF z%iRaBsoM8?RS$gzt1%5H688Vwe+h+JZ-hdEE#FLru;b{OOLr`3&2laaI*|th_qEG; z&EH3Gztys<#J+xLN#RnoL$1W%xp+&Hdc==|2LNqFBASm;tT?0EL+79~& z|Bdq>aE|W}x`dmWUgg+5v0O6$ub_SXzk(0vmIc*L`KU8N;*^gTwaew7Q55x&_Y`({ zn8p<6*T7JP?#@s_KSS_zm*X07gFW>i5F4QvV}gIL5%UVw=Qacv&xBvr_L#WA=#wv% zBk>EZzuI$`=I@`ENIKStu^W&?z~+dlG4LWEDKK)D#2ilEVPOZa+lM{9rst&|P0wpL zzATKmKz-QFb$akS+Rl!Jp8a2$x=BIt(^Zzs9wtvbQaoaQ;rX^0p-;gV=fu#wVs^!H z2Lj*!OiXdy_rNbv0;L4KWoF*rzJgyNPNMpc2LfOHOnK*(2iJh&AH=blsh;C@ab~io zAwjZqeL}VEGg~}wf)=#MD^hpIo$`qp#-|}Quu3JSLLg~t_<1^`Z4PX&LYO;~?6{T% zkEYO|G}#D6F^np}*#lHBH|IABQ)JrrFP0fseTHyP!QqRy$x*6{wXR<#PMq zgKNbiZ+jnnVEDzeBpiG>Wz;Q}xb+!wHGuv4bwL#vZYK*Osw@7QF+{ka%anjoEz}lbT-32m#W3{wi;uqhi(fuP>q=nq9 z68=8?;sw>P(R^*C#J7%(@W1}h--F|uz6jP3iLXYLW*bzi+b}LcUX!>7K8d3d#7~1J z0K$LrT<|MS1*bNh3YM2eY*LROxIVHrx+Z4B2iz+cO?E|n5%>4F;ox?XO~m_jAKDUj zGtX2R>}tVxCIPqm$yljRDcM!n>OEZrdnWJnJ`vZXha|yU+y{hyYRR=F2iGm|0Xj@4 zshLv9Hj?g7s~GUd=T^nmQ67LKqtr8~{?$UKcSeenSzSoPoUKQ6_!z zT~%zY1YGxZQ&0xDv?Hs!be~$_BdaRKUJ4&kDd66914&|vJ~WJ68(Q^qtfVg0)*bk% zt5C0~`#gRVwf)5$7|K4`0^~PXc@}sFRsko!o~`W-WZpE{m1xQPV^0N(%xpudZ7?Uh zD63b)9*h_mgCv8-)D~fI4X~=+|EHQ>x)rYJWv8T$MH@8V3fGi(hHGl6lGJqvwsk4q zD%2b7W8;Jx0mY5hXbLdg$gl$MmrhB2Z{UYsgS{|TRg+@-f|u35Vu^FV4X;&9PC@r4 zPS`PTAl?e}hpdixUqH)B!SM&uTVG5)QzLCiF=TRNv%(wQ_b#u_pd-IX82OD(E51Wj z9W)>DzW?cA8znXQt`x(-dTGN1a1(Cc8vNGlyrMpXI~j*QuYsDx%$B5&a>QL@-3sXNEZ-^^}C>)n@R$G9{|`9Y11=+ARb1ML}AxMz~O=op@N zK1Vmyc8W*pS&*c)HauK`+J`k5wXMB@Ej?lFMQv*u>K0x90BZKptpdLM5vq+k-lJ_? z4oX#<6j^s5u=#3az0#i1Tx8cZziJ-{Oq(pXyuPB@NPF@=IebbNY1#D{0aw{Zcox(p z*^=y%`XsN2C>q4($vT6r!4h>gqEWYPzeV#EymqP5VJ{j{dmv!HYC_6|x)j?}e0SjG zK8ijy0rEdhLs_DxhEi?{_eHBd5n6R2>($ znT}gnErfu9JqcR1zGf*#$k#o%n{{;Y=2&Y`{qTUT+wE(_@^4Veti<;R`ih8pjG`eF z7;#JFT|vv91KFodg6m>lT)6VGeeSKM>t(=H-~L z9$zo^JC|uv-{GjQfE(7!3*mE@VHNNe1a}GsNLkAMb^1+(vzRB_~t8gYsXs4*CMRkm}do4fA|XV1G8$z>>iTmxn+OpGRro zYm;j2PHwQB%@nznnI#_mP;h34(zcU(yRpBeZCB9Wc5!IC5xo+$9sH|%een85(~aSn z8YU@?dO+I9cn@I@Ok0ko;6rJs@0K31VF)}aj0OEhHiZHTcowF2J;L2}JxlNeO@FH? z&-CLobW}6zmWz3KV8r`D>TC%6tK^10iGgukHrY_L#D@G&?YHOiFl7(w1dLifop%eAoBjPhw@Axc027=V)nE+ zi8V?1aKC5u(i~=ZNMUM4UjGfC-86`|<=Pdlddpt;3t@1y-txXD)kchX`?(diPab^c z!Eq0w_eKJv7ZPCuweH9ILph-G{uRjULE8Joz8a~a81pCWo~B|?pN2Pq4!Mf}88m*H z*#Da2IiRn{@P>Xg00rWKoCT|@3Oil}&lRR~`7NL_RlR{vgK0uOt&4K|fAo-)kv5Sx zwFl3+M`9})W#+=3F-c1scs*wj4kIkOk0B@Y;6Wk)i_6ROfbZoO&*qmITq(G z_5BE|BFcvmdAs2`#7XbZxx6gDSz09P@4GL9mlrWS_(1e&vxh!Vd8`+_hxZl;V`LI$ zE95+%dsjsLxHbD3Vx@3H+JU6rNcS7eGzk1zTN?tMXgWf|QbIlQ%| zc}4QfrS0|t@Q*?NUtvbTA`;r;lR=ZnT}fH5UkC+Kuxle(ock|8f}QlsEy$81&eED( zx+VAi^OhcMCGw{9*M(pnl!DG4!(Gs)V0Ata*mXsMxl`_S-;$zVURVrdk9d;a>yi3u zSPASl#Pe}QMbdgbnHW>Qcm~>Nx(xVAoy}l!kZPrtV!j-p=x1Jqpa5tNk+j4hI#>*3%>J;$>~pid<3(vOeZ$L-$_ zOul4z!&S?~DN#I|5$RUKbBc`9n$*19JMmTp_ ztllE;i~V;=vJv-{L$xX3@%wagpjb>3d7q+phes5%_*?K0A=+fARI^fl*Z19`LQD*L0H30(3$LyORJ}AS4iW z)TEOX3Hv4nL~R126=g6k;|nfh2UOxRP8OC^-{~NTet2#_uO-S=XY3&@};>%a4!F}M?DK|8o3Is$#zn< z6P4G_a%!0LKaW2^kMrPYiSV}Eyo=FuZ?@K-3}hWv%-IM0bOwm-I!kq z7=J!mMzVgzahj*x{H`{TfXGtVlLdA+^u1^c;@FZ^1_tXWZW^mEb1Yv|Og26zG8;=ob|VqFI-77!{yJoX?92V&vuuuphp2i~q0z1p+OBfu zL-Kt;Ymf;s20W&RWarN@V6?hZvFEO|b3i!c3Q@BT$7Q4y8Wzm?bOzOe zD=HJEZ$;@;8j+(7*$kP7d+fnIs@{zPvP>_rBBEaWkX~tN&H^!3GUd{KdeyI;tt)#P z^IrM*WLQP7$xnuO&j@FR8aK+Lj0L}A2qQ#12w;OMrxC6vfzkL1I-&Fg`ivUq%L+{YZ`FJce_8IQIm$iSNP-1G{bX47=biXOKO#6`XBPdMP_4`;CFx zUL^f&gIb?e<5Si8j0@%=x`tNs5i&oxk9)IfPNP~I7o zcPGk8M|pSPo5ni@<h`qujw6t>7ao%uku+_N-OCT!-Z5i@!*PRsze-Osi0Ruho>hw0d@RLc zIIUaj!P5Z5omAEtwd&8+h>mx-6|NPTc)*&VmD~zrp4l0*%B`?AumMc3Q#i0Yu-T1@ zu?;fGHK)^be@*rDPJPje8AY8;njuKaqJm^*Bm5orf>-M0n$MG=<4AXd8RglU?~;^A zuJ>zCJbd`*-@!{>D(nH<-W)`wEi@jI)31~YL+a<^=pniF@-%x5`dTvfS?Z^uSMC_t z6OTPf>YlBaDdsjFIpZnXmR?t`mRDk!8@SVONbb8_E+h_=SBtCHp}b$PZ;*PmYhX_& z_6%0{Jbrm4&Y>Exba|2xTfY)_U3Hm5pN|8>-~FK;`5(vxNc|Pd@%!(+u;hf8G~HBBpyAV!F>@t@#&W1paN1LdD-I1RR5dylGS-ik9ZoGSXmZ9MT+J$26=d z9t@N&-;mTYs9DpH*sKNK(by2*{I#M-Jcg+iDD%3n6`Sj8WmMbOO0INGzSuVeehGbG zP0wIYF24WJGspuxP~hPnn=n+hsF9=3Y;qG9-74=7AIL-=xWOzLI*TETXE5Z&-?QW? zY*pBtgCgrGm+&II>M#Eu9@_&o@HM{(Psv@1*4(Z*?Rqhx05TRh(z6O!C$eDMRqcph zE6aFuqiGWWyn*js&`+KEfW1c}n7wQ8oJXLw8-r$@e$yo(_8*i#W;3>zu{C4E+4pM# z&OX!DxVqJ450z3I(dwBGseViovVO%h#x~4@HF>NMzgrX7(3f#gAL#04#RS;Z^nstc ziP$42^{y;q!GO~snOhD9NsP*?6+;k}Oh&{67%f4bp+*;;fcZ#M5PZdDwAmqH4)@eb z=H@txo3#`0m1C`oS#-Gv=jC;1^e5wBhk`!VZ)##8-LA^%eRMrF%pboy)*Zi#a?wx* z4E<47IH<5ZjqwW0J^fKl&k7!e=jmGt%U|@L#W$&oX#$&e^9nEodx7hZM;W;0llOy} zu_pgnWgdS};qz+_v|ZIXNIm3v(^dI$??m8+=LzvU!N$Ci*{lnE1r2`qX?QwW3xklMt9wHKkW(kbyI8EGuQ6hZ$r!5QER5pf|-4R+D^~)Sk-o-PxC>q zL84LcSLHx2ZI7#RTQ4)A>^v=Xe)n0#XHbtc*coyyVh#LFA$gjT^qX~CI1FwD$gRi! zizR0hS@JD5Bl^%!_zo;&NIkw+B(UTgY}8(@5t>@{LNs!3#UYCCJH@olDk#O8z}+8GFZ)h|K?KdwC^qbX~8%uhT>nKJi7;O4F8Zi?4 z+1B5jp$Uxd{XlW#exOXUMKyk)OxyN>a$DU8NXV*u@ z2D(n2uZ(nt<-hkCn>k?%#^;)18+sq!e=of*$}>#Eot&!npv~QMPlCsdUiDX(U8qN! zug00vk?R08GwJK_yfM^U5c}B{d_Iqj)=(3;&|~wgSMdl}<=kF2RXw|5wd!H`&$*`E zv0rKe$8qk{1Lr39a(4CH`v3jh_i^r{1LyLv3q)%1zn}Xy&aE6c_eziE|ExnD&b@cw z-1Z*r|5=A8aPA!g=YG_q`#nTiYKi}a5d}@@&z3*HKaFuBVLW{m4?P9jPHZ*UmSD@n zX25nXjwN1f_1OM^Z8f&scZZY?ncdVn1ap1Gk~ndA`H=c-#H=TxFNWkjN`@1NdLXOl zIGzW;@&kxmcv|^Aqy%@CMi0M(86O&Z?vNY!(A;FP9^<_q7~&-8h(DrEbewf zo6t214-VZ=7>wJF17J)(p&X;R7V>NXj{8LUB<>UCSl)0%USr=xqjXYfXQyHdp^j)8r^I(TPC?D_Cck$|PWL}iN>U2$DCeAHEoC9o@?5M8>$ z`-bJM;S(rH@6o}Q_PR*Y?69qWqWqY*%}MpAgm;Nu6b>TVnY1ulmK7Y3H(hzQlMvSd zEBuCeWlgPlv$d3Sro2+%M9Tg$1S|uo%0p<;!n4|-ldnWigZ1f=9{E<-=ZyAl`Sma? z7>EJU28$VOaG42fhmmP&21}c2-DhkDFu50?9(29^kq0Y;nP!O|Lo0ywi-~bs4fywn zFb8Xwc+bcxL^era$OnSD%fF)J^f$!zlEdO;PEoE=VtXF^991jn8%=COl#*&;rEm1E z{-m4n;P+Iq?p|A8Hc7v_g)EyQ^pJVcYK?6?#weZ}iJLOzYJo+fDJA5A$ zTT&=!Q?-HT!-u`wQhr5#-Hpmhdu+x|@x)Q*RgQH8V%b{VbJ$l9>~_6eilcdmqzc3` zgC&{)S&wVQu$yM-B)@_)W>`i$&mwcz26M*IWtp(sFe# zE!T*>JH&!(Wa0DD-RfT28sU(|yGwLja}_-)m8*MWu=g7F;(pgiQI)jlW(gOu7v%RzU?TXu%*!tELPM|HyOBRTgJ zpaEp|yo@d0> z8$)egWBzFMKYhkO4b+Xy&V*3%ts}StH58q?)y$0V~?q@I~t zgwof_rSS*k=PzmNW_!IeG$Yv&Bc1m-w>!h~nf^DG0`ivFsbf!4EY(N-rv1cDrNX3J z4$ASJR5~I<&9z0#Mgo&LQenShY#Wr7HISL(Fb4ELIiJP9PZZ~JNYp$?RD2)C_WtrW z72oo?*Opf40#$vGT1-2#n&AH<2j!nGLaxn6tQ8mg<#W(7+-3NW^*=^%)j=R2@z1`Y zjJ-aiYEAJ$c|#}ecaBMY=&Ej*X$S6hj$%CFmtGr|C-$QhEpk)zy*T$SML!SG2u>Zc zW)l7Snd?=}e0`Z_^P1x4OG^Z11l!0VSGK-xBzz+2t$QQ}x^%Hn3Y*mlkG3iL`r!(u zK0avTZFas{gV~jAx{Cfs8B=yG@0Xv0z4;hq1*5l|p?1T9fZJuW55H(9817AM;Hf^!l%&tWtOlPw zJDPq|s~3%+nZAFLFin7`r4{+P`!;}0NhhrHF4`Bi!@?bSsBfM(2fw=IdysF_=HY|j zZpy>^zevW+_tSrT5Jb`|`CzH`ot0C;PLo43C{O%o8OJ$4)uc20Z8oV5 zv@9!EMSOANGuISACL~0YJ8q8JXDow!muktC>KEl)XcHeN% zcJbd%YV&;Ec~-eJh}ggxFWoiZOQbX1Pu)-dX07s6EMh*fy@c%*Y*e2yW1bJo=Fou6 zq;Qbn1`ctZ7$Y?6xRb-wd;hg}f6`}QRy>Rz(vChF&K*s&+UnO>GvPzgy7<79aJTgX z#X>?Ud>}u(UeUPLWB(gs!Zl*n`C3pCwS8Wd8+x(MEr5PGfe+Zi1ils?bH%C`R=)S< z0VaRtd+dZ&HC02QrPPc-{W@bJa_6C0O<*2DjZm)|_^Qt;b*>Swo>jKAHt7;hR?gT~ zJ`X%VG{fsA_y$su_3^#X$}&=i+}6!{@S;sdi!!|@2TC&i8~*-1uE~N4zOe)H z7e9yPXW@5T`QGm8QLg*0e#Tv@-d%P7RgMQAubIiYRQ2Iim-XJBb=?|_$5mH};W>q^ z(;(X`zfrS!iI0b0m9G5PxjyMKuw2$3&myHN;`Pl@q|T0rwYyNiI*i#zI!0PjTP6$c z1AJg>h@E&#&x^`rWPnA^Fcp`?2O6<=?lsp_Y0YmTs*0c=3hL^8q5pGau=8R>&pT_` zxibinU7zNjEYOlypyZN{+bu@hWZ``)A9y%a0M9lb_-Ke z%CVZ7R;+&oUA?}M_IV$)=qM2$?AJ~3Keu|$D&;F-L&!JO^}yrBPwOqN7d9ze+e245 z)ARV=CDuVxnJvZu1y|7DcL=T>!_Tao8Ch$TZhp0hZ z!P^B=Hx5@YfkEB0#Gc3R(KV@NnXWhC_m1Fj;C(F?z zO+C%$>xCwioUfM5qvU0MY}%(vTOQ{ukgiqN2&p>Wf322|4l-(@f4A78OFW6EuQR|h z9g=(duGKQ=uiFpgV+6f%;4yrrqAZ-f;i_EQP20&7h~?Q)Iv+QR@h$R1OH3fEkAati z35@8&oeFuU0l#g1d>V^yE1oQJe~j|Uu-Q=Shg2$*BVHl09_o|d4@dt-rr?DZP&s0` z5Ax5%lB8$|Mtt9gZ5%fGu5|+9Q+_{bPE9LV?2%EdS(q^6i0A=Y3=y4&VAJDUbf%M8 zLbNvzv44n`&Ce|*jnrAyQo-u=YZPbZG#Q+a#PV7iOMc^T3 z1XzS_IlV`(80HOwt{aedU2@^g1mw3bsZkvd={uOf9@q^&SK8tj8kdwiSfbYsE-S#? zl?rZytMVs3MB0Wqq<}Ak&wK$apR_h$7r>nIX6US9QoZ<#Z+h|juMjEiPcRGvb}=+d)%;UlA|Dh-i@f69O^qB!Hjs#TZVO(aTo9vMPYd!P!aRgz6_Le zqqbSsLYWc5vJmo1_x3!mK-Xb_-H7?GlKi6%s++LMUVQ`FVv^ zi?y01Co!*T4V%b_@q%X4L0}N_gaRp{dZ;G{to{qDIWIF_*F?t>sb}lxop0Rtdw6^v zKcfv)hgtEVEUljjeBHwiw9K6nYLLff>wWNv_?T?7pP3p9<_{*yAT=wT6a%==`{1wT z{hFpytEP@1E}lu-F4k+x;UT~*Za28sE;$e+1GxtX^`j5u9%w~gH*isJ+zrfh4SnV@ z78Ums=Y2yw&BmS3yYJ{EY_wl(uSB#LER|(9YrP(|9tsUEd^_-tfya9ACTkEq11&9_ z8!J)kJn9<|d-yb7(llpzm_WtNrz${ii;OtFc>zY;P?Za|Pv%1Z8F6D*MEV$88&zw5 zx6yHnpXO#VW)Jm8Nv#UoHnVn1$sm7$I0GEHcqSWTi@mwu;MeEs^USFSWYaRz2RGB%7zk*2O=70kAtrm*AsX&O@nO$=ST_#Hqb`^g=82N{yyM#rMv8bG zBlZl8vFX;-+SV8$b9N@YRW*WGj;t}FDCimw$lrEF5Knr%*S!jHnnxPdZ|g{{q{VzT z9lmh-c1B2Zq0@9?F0BdA{WS#L@X`h5x@#qq&*m`xmG2R0<$I-wW1AxERan?V244_q ze7~v{{pgPzK?x=tZ95?AFX*TxNkXL8fZd@_zNKGJ?Of}>xHs|+scg6f`B5o$D|>cL z>(j-2eO8&KL4;f=-N1>uph*jFNB;Ym0f3~M@#X>QU(N#lg!%!Bu+AXcLh>ru!_zw^ zSjMK*m)O1m9tFCUvxk9?hO6fTclB^BSZ_2n(%t~{Wv%)RJO`KUDS$;lgLNm9q4lv7 zm}$q4qradPkS|oRLekl&)ntGrrB80_Gu)JPup#~C88l!eZ4vUzsFVk{Roy!9XABmQ z&l+n(=t??Z#Pavx8G!6n?kt(s4#r=$v1HOWyQ{fCHO6TM#;K>82~?Aej9lL#b-vqH zGTNUCejwHX+hN0ew0aue%&&;iwL;68n$lci`DT*9LYwLAW+12Ov;MoAgO6eyWC&UY z5_>Kf7}$wK;`bcJdul(=o`1B{z);fRODAfe^SP+ zoP;`>Lfc#mlt!RRo2_^JaoQav4~Nh>koWnj^l+6SO(r-`MX#DSbV>mtJgH#BA7OcE%&_| zTNm93-m+)u%5E{(z~eCM*VQkn=Uz;s5+#o5`qYvHin&9J6i+4d_|LHttN1fs11^9&De51N}v0}8v13eRz_kd3awKs81ismh;Ln03 zAc~H5u;~X@V!toSeF3>Eg2(hP;hPi2Hx&q^e&Yo#(FMx;=5{`iU<};CGWMv(xE?m3 z-T2YWqp){;SoYEEHN{UC$H4z;cIg`R4TgH-Mpn|gb%7R?S{g;{uGDg@rP41(HOIVq zmy&9Za+ko;&o|FhY`NN38*sOc7fiTwL6k0V7p;k&WEjp)bn~y0x(Pt_Me2~>$4kUs zE*S9~roI+jmA|_dpHxCqbQVM6cRExF$h))wZ(l)4tRJ(xPJgl)?YZcC+MY4yMR`G4 z6Jl)9uVy$Wo;RZP7xZ$7jd&aFIJ>uAZO0_M@9DiRJDsB^?V422z{@%rx?~Z2bU#K> zIdTA+B=shmpo@&{eRiPrOVC@cBHBD8_w;@P-6Gl@HJWqAodGgbXFLhkxeuQ#gPv$x zQ;fGtvVdc#?O$p$p(a27G_{s%^1yGpwFJy0SRL~xPQa^N$3Js@>3)4npd2VFz0sW@ zEzt}+L9Mo7Ik)eamzEqkvk_;O+&t6ZE=1||{j(9jl7*Vn=sa^L^P80$x)2k4 z3wThS#)+{Q;Xf#(BGq@Wqq3VB>@J=^;8g@s3*TC{NzwxJSBC8p4f&*V0 z=Wep-z@$Q%yh42<>h{uaowwfDmlfCZ6zC*XrW%T!xc&`u5xC+c(V{ zq>d&{f2^Asu5r>UhxaaN26`391KK+x>|cHIqVBr}Fak4{MP%Cx97}$WZ85en*s`%v z86J)AL~Q?JS@J2iUtoCpC$@L6J&SE9woeF4+}P;c{+%MdvG@9rr+W}NOC_QkcEuBo z+gp}`Ethn0=E>sgTQ}CTFJ@6W`0x;quIu9=@MnM}%GAXTnOX}?%x_NP8xda&8?ZH% zr1A|U?cZhpR?z|aMs2;W?u6=rO76g$iu*!0_@rxi!mdHiL3=YX3U5Oe8oq6u)K6uD=8t!3$JNl#wCdGg>Z;J&LUKb71KB#M)+2A~g4LDzk92*mM;q{T zmqTBQ+%*j&YA3w#cTeTBW018pzK09OL9S9c^=daf*aK4a-o95b$~NH4aZbq5$=bjx z-G8}xbY5TPIc?xMU=fL7axKQ8`b=S9&`V1UxI=X}Bj!OCKi0iVy~YgP{}YDhneu>n zJ|czh0}^5^&Z+3$uAalYr($JJC3;EU<2e6V9=zLXFV-|g2g{>s59|(Vqm~G!yXk9pLZC~Sg_s= z$$tR?R^RaJPxNR%)vahT@lo0t2=LK?(_g7C2e!h39zP#$+ggm$G8UVkA+Uhq|q{(9T~`0OCF(R zWuPq0*{s^Q69tHaQL- zrLj^|5ob6vyyW~TVI%bKm9SmliBt_d-Dj7gUegBVDIBeDt~M}J0S-j%qjS(xOzOKx z=+-x#f)0X}pGicF810qFNvB%RpSd=3|J?Jv^3-rNMm4lMa5YT2Ga@s74KpMP<30`F z8f<4m3~9qg<;F;Sf6>PfcRxeE#W$4=Jhc8+XviyeKICGIL|Z(UJzuzu<4;O zJv)47`46HRQKuQ|)da4ExwI|cBl2!M*lW*d0++&r(>8qnw)j^aN9T`+L;PU8!9|~9 z(@?#=x)|?Kn}-%!hkiXzKX{i-04IudoY0Ot^vj1s?}*9!KEK+=Ao zYhwL#zBg`-+5`_bB+P7|B(8H5`N;_Cmr33qeSPb4ZKE+|yYRZuDjXC{x9b{mB`+-f z1@M(X8rqRZl+-7M<(HI#gQo|4=YxH&H1LKwr=Z7FU&K1QgI-}%wMc{Kg(PSq%`7-W zb-7C{k8<2I^~ECe`5ze_YEHU7v&4Q`3$GG0!4zaoF+o1YJn;u{tK;7tC@Jq9 zQFqOJ+uy)evdsUJh^ykXVCc{EAS$rJoZ^DU+SeInA@wDl>{WX~g3rt32^)Admty-w-`cFbf9+G3aq6g%_1K#^nrQqIJAl@rY8 zN_*T+c$8Y&&};LTJjMklSA7b zs2{HD(*&YM&XC-p19O)7H*=P`A$cFwBXpZm1A&;ggS>uDrzT<8PKu8}?g^437@$v1 zYdxVHo`35>Itna1;;5G`DxvN^tbJO?Cp3{prXEoME%cmH;KFuH=Q7AI7H}Jy12Ke$ zQh1ug!6PuO^>ftRYg8 z=o=61umQG&oYop0 zbegt{82zMPr==sBA=mhO{&t(E&J$o5$~sAW8}S{EgG4+=w_TTKTf1lb1cfF z?`B5(cNa(?n$<h@&6Xl!ucsBF9`8!JBV7h|6`%)mFM)WxUtfOY_}|o z$aX5jheB?j>1N0uWrk2Jd)2$ezkE`l3FP%t1`@>s3*&XuV$M14z8F~Gd*w$%RrevX z;eovSGLXk+7V=*4r(wxR*91oN>m|)~(;dXF35vw=%d&Wn{Boxa2=5EOqU?85%Tm=< zRt9V{BRWNq4{+;U^>I(!1D4gbj={e82W%r74AR=rH5alzZ6PoxS}1+6oqN1LdwIevci zpz5un`)FaOX82Oklae&2-mwA4nw=x0X7OI}J;&hVagQx!HW*%n`S3-D;fRIGt}Zkj^1*& zNdqc7=27|#Kv8+*(#sSH#z{ru?iHHA@V*@nk_^R95nwJ@_3bG(@bK7|J6Ak~cq$Fv z%~QoTvDPyRttMVTev1c@L)sUX{}r~0niZ7I$RNfAM-e{o?a%Z*4eNtn4IA35jGu*! zn8mgf^oom!;{V_-9Flq?wkI91WzWIF#Miwn`W4a~t| zzi3@X1eRZv^`ca~sK#2Vz@jJ40_PG>SALDLQD%rhah8Pw502K?GVW(X2V_< zk9^>jl`p}jom%O)P(+BPp;E}I^jR20{*VT?AuO*0@@Yg$zDP#>=+7O9`l0>(93rB= z4s+rPPqTPR^gB<9FFKcstdmB`L?I%*Xjqzx&6CkbVuixWIPg$0c9&%^jvL^)KJ3XB zAE+!)GNxu$RxGzIZ^5jAw2u{BPD@E!{sUIfbo}Z{&F@k+uZ_qScTF}S*IZcsF3f@9 z#S*~{{=$$|-89Yx5rN_g@j2_O4sAP&9w1ycd*4D2xbg1SAqK2ae94h>96WN_4)2iJ zZ#bWZ6^=53NND{e^gG*`77La17p;^d+JzPD&J^Hr!sYm-2^x^&>&tM4`rCxxpN645 zs(7lfd^AiZ0o9^fdg;4cjJd{)4Y7=3p~z7dXW>Q1$aZ(NInWoI=08ax?8I82!qb8+W7q z`uSEcEZQ?tk#$Pm`t$1Lqn3-p+ewJO-NeEVy|q8X$?f1a@S8OF_ik9*dZT}#R;?m1 z7^_io2Rv_Me0U4GN$}uTT(QCX5SHIZlpiN@M{MHlu$<8voC{H`C1f*>Fk+Ke#5%}~ z=<}|S=*e&{e=s#=rgg2;Ub$k$ht8r3+wwHA*16Q03N|f1@VCoGYW+aWB*nA7jCr>0)I9hvoWpJyhb)|ia-}09i5GAMMSSm~}oD;#pnU3BI=M1hh@O#AY)-#ug(Li|Oz2foBR@gQ2;+FWtnIrSmU? zm!8GFVrUDH&`z2cst8gkS}4V8wIJ}O3)otWy)bf1*~PU&Z6zJ6nxJ00wnViIz%RiV zYv5_4vBlZoS8(HuH^b{9N293K-6fnZu^jyZdB>hcByd>n52d1{&FJ-ESq=@9qn=4i zxq>+14DtC&`uoC-qv~D0K`CE$8Oc($lnmr=qUWTC*Q%uxGROZRejV#FkTU-Ycvp*j ze^n94#@O5Zl^6|EeSc9Sb&RnSfMqkADEFvU;cVT@UUZmzHJvbL+TyhANqBdOUSe|f z8H{fMxqcr0-0V)j%LXjEPCtR9^(+gjSIjRUsc`{UEbC*tKIU-6SbY}bDq>ofv?^{ea#c8d?xgc;H9 zWm*zE$<@F$sB;nJV59Ph&U%olnUj4*B7LvM?0n4SFwb^?8{sUMJqEo#2i{S{8$ohv zJ7BrIefV*T=z8Nl@C*k+G##; zD#VGF>|8%1?FWLN&aN~sY=wnlE z_y_-t8L>$i2kymjvtNQImD=ETmcwQ#<_XcT)t*(H+w_PXGveJ9`LW&xzK6u#=F3Fn zZNWrVDk?!8Cr-ut?)Hz9$e27I^=KJ(X##`#nG73xeGz!RqCA=rx1g4jaU?9~g!OfY zfefZmvfqLis?M7xZbkco-J)p$>L`FaqQJ}S?x-Z$eSZB`)Cn4(c7z_xFqDH4y2^-X z>c?-(6<|{vz(DoLQ~F~EdzRfE`G%Ca!pr+*@pq4C#8q%Z42Hko=w zk4U+2tieC?35w!pGkL_W(Y2|~+2-W~e8`vz|A-T4vYo%maoCHMWuUtsmTioOG>@g) zjM{^98ksAhpP@g}I9&9>A``OW#R<=~QkFwEo~jZUlso*7;B7AOWkWM77{^NW^bLFu{*H1Ac(v&{5^#bH zNi7l_i*nJ6rr7QP6(>lKipK0%|6eOh@eb&G`B<37z0haXA%g#% zego#y!^?lIBsmwc4;aXPJWD$CIohJ@8YZdzr7#v6R3e^=GQ1MK23h|w-@3wbFY;JU z7jmWK(xGZ30ts$ll4c&x1^Z;3W(SR|2X9UvGf9^*NVP%e`9y7EVxol~887KZnvpd~ zr)v0W+;qQAnB=`&Nk(7yYg))isyVPDHEuoL{dAxnZ^Yvtp2(8Drx>#Ne8hHJE4+%j zv30i8#2vtyG`7lnI@xAu7=}rzy_oh}incHSWfA4krx%|yHAXigg0s=w7}przn9xX> z8Pd?_3Id~RoRuV_Adp$}dL>0y4X^pWl4KPiM}$qZU30A(1bxEEj{L3>{q6}v7c^$q@j5Cn5GXsvCRiO>t{v3`c!dZu$?nW&w=N3 zp~BC~_gF-m=XD3`UyJ$eXIJ95h0vHt#+B32E#SrD!Hbtp{d6OQVqmypyvA&spWln< zJ(C)}_bH9uqxUd*jA_x0rhSFzGgO}B_CxyMDgN#P-qko!cn{~qeon2M)V4`6urvZN zaX*btjO4S5L@?f4%I|_@F_;@=4z@E)Lky54g2Zfz{pw9&8Tbn6{hq}()fesFfgXHN z?9h!rNixRyW17IlJBs$|gW?ul_DRMw<4Ek5apD$-*7r}0G>W;j`FPJ&FY!iiGC5 z%PaU?S(5ILaYIWTRfk$rET{D(@f`QYHf00n#ryV%E8&@CJTH0mYHj~h*V2KSJqihS zvtHw&>wfh<>hk&Nd|_x)5@K7RZKmsx1(s_j>1N3kTo>fUVguQJ62~RQ?vPWEuINc2F`tZ6F`>AA9NEy1eBAV?=1d~IV>?3}P0zy`3?S@cyf{R#j_A_hR2RV;~mnxOC5uo@eD9%SQuqvD<$eq7BY_-vi3f z=z9;*%p5)mFeN4_1ne-A7KQJ}LKIJ@-z6k!{Z9}ICor$B<|>kt#-8jJYyHbiq_ zZlS#3MscW`ld4BH^r)D>TOkwwJOy(ooo68Hr)STmC@UbvV9RM1GRwsBI;;lK8u@?2 zI{31j`!oD&vmDln5^H<;L7Jr)NZG2KF~j}re#){x12Vn7Pp251DR{$|Wy{Z$!QwJ9 z0N}d9sg~EQe+ILANFJiL5uIsbBzC`f#w2hRrXgk}AZsD7N1`N(YYEFy$at%wVyPW< zz^C3L@9GBDi1L=L{|WM()_t5rWv4t>3-oIu;{J@4qyhS0kIosA&-GL0mvI#Bs>WO} z{8ynPPoaof{F6jDEV8^81GSZJsh@NeIiwLT(Az);I<$g!PVT zR0>0<4v&xih9Kr+2C!pc*$KUZAYKOVzn^O68gU2^oypqh6XbSS3c$joN^O-Jj*OY% z+b%Y0rc?B)j@e8`P8ALd?_u7#QQBmbcF!3;klDkC4`C(`$$#u;@e~fc<2C&pw8#H9 zHkI17krUQU`66zhQ#qCY{suO+E`m*+$hbdT;`v{Zscq0!>1_CsKyjox*p8MAJlijj zSwqgei+NUq2=&SR8r1?8qvizXum|!vO(W4Kr2jJ2n$nRP`ZM|za0(|rPJur%{_bnD zUTS@+IJP1Bdi+8l#j5bVpawlHAvlkj3SVS=FrCrWL5e_A$=We#Qq+e1a?a1z(XdXA z#yV@X*-v>qRis}}gu@e+Z8_=|qJaY6q2Cd- z=nK%7_gxmO;hZx^1!UHm=KAPN)~>Xa1Hp1o0DP_FZzE~jgOiN<`uFC(H{%&ZcMb^_ z5O0~WaZPbTow*^dp4*swu2e8Jr2YO%}hb`b@mQY zXC5E9Q#Q(}MLF~y9WKiDrBUy362F%fUzUq6BRg)?k&+Xtz4i#S$cT5AY7ig0BKnx7 zu@z%`ea}6`nij9by%ru5h5IpTY}b*XmBx0d%nr=KS0t{vvBc`z9kjs8z{D2(^1O?& z^~y4yfOBi=d*x(kM&*JQPd=z$+k$*WsvI*+#U=blp7liCRB?qDzvr2Q7B)c~hwR$=sv%h80iByvAQ@Y- zAr)Hb`@d9ZecYmZE%qPp3;Ne$Kc`v*)k6$!eKUbipG`BSB{VH`a<9>q4;VTJRzBQj zqR`>>+!FGgPD4QFEl}To=M!GCd?Kd{hw;Jmy zzC8N1>S56;J7tW|)bz4r6qQ42+;Rk84h{}P{yuZfx6ioceNWbIIv$bb)xA)$T4S3z zDe{ZzAU#S*UfhfITyTepbuLq^CLVHSb}u(l=QO%$7Kx}WXo)*1Z)Ez!$zmjzQ8(-d z+3;VP@20ax1i$(s=K06Ru;kjm3Hiy#5V{7B5eOp5ff~;kk9DCL*m!Fio&T9eXaE;^ zHBXQZyi`YEi(Z~>IcgK^z)q-Z$L9U=u8UNk*WmbWtkwCbl?mkcFG957F);cmAh}`kWvWA=;B(~e1VI#eo z02g=`>k5i1|CeIjrWIVkslcAN?U<5Yr$;2yX~jaqvOBB~X6Wf1Q+=gMx{0nx@TRuy zEVs?NOx?ikhSaZP+b!>SC@{r3N%&oX%D(-oG#gfy@ zDSzV~VLEe>qnTGC`Bk1P+uLd#p{YBr5Et?-Z9@d?fw72yrO~exXFhmGHd=1iC1M{d z#O~OSh!bMBrABvY$$oj;C1@bITp&eVF-Lw6!HSupu{gxQh2)AJ%v57pXRUNv;j7p& zOMJ#Lcl*eg-+@~k=jT}(heGRF<~pqqTk?kam?bR2_>Tg0%dxOhLJPY@S6gE- zTEt7pkq90F8`-PWng67?3B`&VZCF>s%lnvtucPOc;>-n?CIewlf6cjMPGxOic@OBv z0fS^3*0@)BtPQ!pRP6X89_xstO&JH7wAdY}&)C6rUn>PJbse)Yu^~yyJ($!uSYqt7 zj+XkQdR}5u)!z+Cn{fVwtpIQc?_=*#E8>R1W{`rw^o(cgc8{$)I! z3*BsfH$8KMdS-oyx805_txZFklhjBS-G0~=;B$znyP*dUZkg!;lTeenIesA4Wm6yV zDC&EBSS@9BD8^j}$qK{(>R9q9W@@WC{Mzh544;jXc5ijX=w5>l1;OH#wuhXPt{#wwTd7DLP=GcX8>R z1LdVF=>NbolfcWa_`M5Cvu>#_UQo7R<{B`|y%o&R=^D5?c$*s8%{n*c(D}IDb_Mz- z)!rZRffWeRIxy~Zy>Sn+JXm0(BPOH5e5pm2+w1b{hx0jQ#8v75PGKW4xW+`W7s@dGJOo7g%^L<^bdWsvoPHrHMkC#T58i7i#M|>1YQ-aT0`<5LNA;TSCTQ8z$2utV{l!)~*6$SIPuXKjwF!oL z!@m9Ud&uZR?NhuYE&l=QLo3#YxzK~D6)XWQc-4;?#&bnJ*{64BIDr_3^&i=)XkV$J z_Pb~y?Fm<9D4X|JP&+l_$~5{mD0=Wjgu#Ebf?9=Q{)Y90){k5uf#>02yDXPpG*b@O zhu^5w&B%Zb{xfV=;fxI`l6HQl?@=0e70#{tV5~OMw}zo#6+Jy-)>=dt3=)RVAUWI0 zIq}2BaUINlqfKQ=f0Pd_?$LXra%m*VWqI&L=oSW-;3=`UXQ*v_U0xZY^3@0267%Fd zXqjR8wJ=>jnL7xwQFyH$M^w88w&o>}9t{_Ur@_yInDEOq79zZ*;M4JJvwg<*)n4QQQ;k(c}Dy(qpQpp=#FqLFZiPH$XhUAFRSJ zy#UlR(R)e)EQ~h8{6nR2Pdw=bM>}^w+~qA7-SCjaLz{{7Ju=|aFe0Wa1RM3kPcVTt zXlkxlP~*UlLrXXnWLT`hQ^^?pQAB_v0)By?bLU$I1z2OUZ%}|Y3V!O3Gs1(Y-HS-z zTk#Z+W}#n|1A#OJ>-5WV@&zXMuwx5ydSwcu+cDOF4CKLZMr`10f$xwP>GNvwyhj`< z?WORGPr=hJ?w=>5NDt};pNN!C*CBSSLx8x2?d^k5tQ7gj2hzF=pd;}%#97(EY6{Oz zl&S?F@&<9GR+Uxj#`vu7`A_7HWuT92JwwR+lMI=Qt&L~ME${NR>?rUMA(mBR(@9z| zMe4RN8}wVKPxYT6zBPgki3M7wU)~Xdoq|IfrBU5IvSQ%8IpAQO+e^|1W384T0fDk$ z;R@h#0&&RfRPG_LMemo5$n15^FNu@!o5$}f{)l~^`iCf=tWH?=V4`;#P#UacL(tM{ zjAG)_gYy7*I_7)JPs^CGf3T9Yy`<8@OXg~D7Umi(@s@+&E!17-mz+|j5z5(2GUoem zh4JtBzua1oJt@XEBFW7W_3oTuYB+I z1G?*)rN}{G2F|wNG34d5z}Cx1^b>cvlcYbn5_Qt+g42v|0D)X6K!YGay0jD^>)i|? z1De>OD@?vdF|<;>X?F3k;zN$Ej-CgJT^F209Lfmu=Ssed>TT3}Lynf7Cge}Y8L|!= zm6I{xwC$I#^&@iq|I^Od;9%X-6KQ2+<{fBd*x6Jq$c0Ej8SP8kdJ%A(!GZSW1X4`` zZERbX$ybnN@)u_4{Yzm9Kr|2-L;NYn%uH@1K8@z_qZSY%nk5cb6d+T3TbAC}?7d*o zN#JvbG>-1burQKn)k&=m&2fzY#@eYQ`#fyUt*~%#fmuCEBbFGHX>(FM3bjul>qcD* zyg3UYJBagE=>cm3BsJ@6%N*?=4$E;Eb7d1|HMe7wec7DSl_KjK} zFc*NY{KmT8SiHU!Jcfc59M!`Rp?8b$AlQug2ZwpBu(wSVv=WeWv6RJkr0@pLB58J^ z1m7Eh!8fQ9r!DqrND5LPmh-}-iRQcG0OsIL;cy zs)st)uA=?&q0TLG9xp`SUw~NueRBR~(iG?M70(uSoTvBx0&|)X z{s~~*DBnBu_Q~BhdP&5GkA6S5L0I3q4)c}SeH!@(=E5RFZBogW7lETfl(e2}pewss z{w9hh9{*(*!+e1evRI(n*%)EEM19l+h+A&UzQsqfCqaG!l?q(YGa;sl$||-wr=!Tq zxeZ;M$yt(dYEIJIj^W1*K*?l5bEh$<`{edZJBoJ}+ojhXmg8g$8@OF__^75uUw!!K zKP&~Eni2OD-$QdFV0HaAaB*~oNcHN2te$VGEzx#xfv+h)@p$@dQBoeozh#rG1O8hD zGUf%y|HJTDGa7hoR6UnIGxEHA_(E$R*x8#X`lRmTE{1(cV6qCXzTqP2x($}_yGY!reg2;a#h~`uOHej{Ku{2{Tm>&r+Kmb#BKx zIqK|(Ry*?Syje2DpPu|lP|v?pFeDI;HT(G{c%y;uAhsy6Fg3XfHO#eCQGX*WE|5M% z8f-JDtxb-uPDk!U=%|OU5GrTq&a}SJ`mzPA_+ZJ+(e)%4@91=i%mIV zb@ioIZ5@z|Q#B1F`;WdH=odw>&ai>^5nu2UBwiur{7)2Wn_BE^Rv0tJq@McXNah-} z_;vX&%32(I)Q8rlJm#FHkz}q?kL-jdf4}e3uBez#yNpI%Zw#^&7)|&eW$HB^1}g*f z-ce^4!!EfDIYgPX(fE}EES9cG>vjxVkQ@)GH{JibqvW`;O4DShuJn%eXq&ggzRRM% z+J?!;wJlqRhI7UPc{N!gS$V#kOlUiZ_(wa{LF;IF!!hzWr!X&R8%Y|pj%|J+3I9<0 zI@*^gKPX}sn~R3EBtyz0M}!Wg#~e?n8t0+c8jfRikG`gDjNFGg13eclGbVgPCPd!Y z-_H^nW)&*1jIULH=3f);UB$*nJfXFEytgzCVTLOm;Lyl5Rb(EE$9 z!c_I;fk<&hHik-QUqH^+S@xUy@^t7mz>bWsCa`~EM*PD?>kH-;qnWdYG)^*r3rU}* zODnfbwKO|~Q^U(9fz<+RyRLn5>g7H}eJI61+Dl7;swjjmJGXl#-rCrXbc_BrT@Ia@ zf@k;~!`Y?PNoAh_;Sx@RJ+w#r>)3)QX_IGA8Rk6OXF;CCs{6^W+RpfRsuO2Jn~d$C zays2&Qn7bg*lWXHzQYctC{lN9Xk^Zg*i=@0#gHY~GO-QD*7s#(-SQ{PbFGW#!i%O~ zJR=4Y0xas$Ch+Vr4K>Ig&=z$B@|*rsqd{D(Z=-X8<5CY zHFvGF@5jpE&K}n$B^TAx)x(FJcViiI}r~BFGx#d9)0H88io~OIE`BQZxu;n z(ME1>Hd^P;eLB^GXTS)~6J}sNo~!m+8j&5IScH{bB36yCJLX2#c8YwcuLNw0bWOc& z7~&vXX_neiZQS0dS=3VuZ$dNf0ruI!WT7(FtS{iYK4NBy?FAoP$SvTJk(nI5glnha zTF5$Jd}tOkH#Ez5+{cdG3>P3p;yQTbRk+P_BxQ>u>YFFlOkM-MY2>{`eCu41ORz2b+8Hy(J+5p}jV zS$bf(NPE@m=v9w*{P4g#6&8zBL49e6%&z|)N5|nAnyDo0`2Klo*1=RwDm_Q}=N)my9uolNQ> zM^??)_RXj%p4?@cSlVey+aWwylP$3MhaAJ(6BX739`{keZ0Ee8m?U=G`;MT0C%lDT z^q>UqF(nbXO{ia*T3jx`=M~$5eFfY_(UL0H&4PFFMcu2S+9|<7`9@g3} zq1jQZ+FDHQl|rt#Pky{J4_Gc5r*^E1V{@HZn8l;%_@I`L0Z*ucnBy4L{zJz{-B6ZH z{yZY@UIbo;1IIeD$JFfuo}O~C?~|8ZvDjVIUVcSqpEg?uloYJxSF}Lj@Pbad)6VT; zcSrhKMF*2UNzmE%$?hvJ2!$TK!0jrw)1wXOi3>ZJ`~ty(qc2_oQd~V+svcd3qs2H{ zE=7CA3)M64#hEsG=BT8z zBrU!)zAR3P2OcomKdL-keABYBIx)b+YJJSuRrsIZ9d9!#oDH5`e3Gn-uvL7~MM$I% z-H=hCt1`$34x@r=bD+O-%U#uloorF$2xlyOf8{gj zgCt|JY0jO){#YE=Gw@$W&Ug=JXiviiT=yx;P|uW@+pio~Z4>LSVr~DEYG0P;rVP}V zX=LmpO0$J(u(80N*-HH-@ThdW&Kh`_R!`P{pfzAzUaP^Q5#%>$<|1kc?q7N)8IqxUZG=Z_ll#a#S=(#I!jOmbu z8lW$2?y;sZ&7AWy)FDgtOh@v-Jn{)c1Z<_)cx=dZHNDVc+!FQb3FxOM@uWj2lS|z& zAzmy3yO-QgXZZ=phL?vs#DvqtQ`N$;>`g0IfPrEU#j6Ez)hCvDI0goU8=j z!__Z%l9xTPX2$``V#o2s_g&!US5`_p-pM2N!rqM z0SXihI~0_Vrh&F7EfgqNoEH{-5s?b02rB8qq9B$Uxl8C+-)WLy|0r7*+d z=u2Y-S{f6iBot`=-}_P+X8yl^KDRIL-TmHk&pr3tvlKC=G(lf90xMZ9>n)7rQK~ML zR~vA{&FhP3`-inBrk+HLSRNx^g^@SG*A?!EFt<1tk&=UL!)Lr|-Ev6zc9*uSB7`Xw zws?P{9KQ;rA#`j@61OCV_!BvqcXA@jFN7DsY`yilMDIQ01S@5@HOh6mNV zSS7uGU1qBpw0ICKbS1bJEdIVmv3bmlnxl%Xlk}iLq%n+k>Gnb@G7?_ESy+&OozkpH z>4RVkT*|+zY<{9{AHEfQg7X>bl~u|XUGV_&jfVrXr33#kgf!AnHqn3lvamv(~b?AH2DemUaZ=TdqH^L zNgUm!ZRqq{u(inIlqp-U_6zD;fttHA*s;ec)=&Vt*bBcEkyVjf3c$Cdt4{;lZmK$3 zhqWwnn>M9bKNGg80DDf@Ka=`2yiC0rwM^{lkCXQna&&Q-i(TpGHJMMjV$LfviSIq9 z@;saQCzm{PhKtD@V-)Bp5{F3(IU;ha{2ivJpWQbu1A#@i(TRcd7ZDlOotMNJBcs;t3-UOM*5TG27K%9R5$j-m(?pH z&Zpt|LwOJUAGsn0aYpADPwz~|$2eu@d*NN@>?+^DE0X~$9Oi=ThI|%o|2G!fxGlu@&swUtNyqvlze%Zr-|#1cnHnk!nr-_C zdLqz`fK{C1*LR`(#+3uGX4N_-Wg!1c@P;Z2cmZ<9Qv7;n9K5$)FEa^yEW~$e} za5km6FG%TTIAzG~RHb(2)=6I{I)@AW4RQU=zPDDwpV*y|f;=TDNnv}0PX&Y&6=!4L zrJO!SNmvL@#LL!kpbI{3PX(7b8`M9=Mb{v$ar}BurxtK-0%s!( zIpO>X&Iq(Yb-xY&l+tR^2JF>$MhFU@jnX-NElnIjE1mHf>U>Z7gDdCtg|xsrXRf6)F8^w9FE-jjp~F z0jtj#3T%;DwRdGIZB=2cE`2~6uNGnrBsCIkN|V<7t5WWFR;n-#8YP_zx>jkw!;Hp{OiDH5h(971m%P?r2%yWh#GmQEGSG z$}o(;M=UrpKIxl!C3X>oTA~FoV!q+WXsN(7Sex*3e0|gk9dw*C;h%XC?$L%q>LW9e zwY`}r46_C^OJGB_8$Ih|HK@FSS+^Ftk$Y0CKaMjBkUzSfv_f}qvXpzWl$*5)!{~ci z;&59IN&<9rqZrY4>jRX)*i4Vm+K1B-=fW+2Rchs5R?rnn<$K_V1#Qoe#_7Ncx<1Ft z`(RdSFP}!*_iJg2y6f+)80DrIqc^aFiKV!Lwk&-Ra0M5Fjbl2BYgQ27>E%6yKG<`? z`~RwUCq~{T#lDKzua=J#^tuuJUQ3rVl=cW?>_Lc^UnIU~k3o9PnmPIv>u_L`UmAdk zzd|hqx`SGO9K132DbfnUVDvXJ71pR%g&r1Z@95a-1uf*Q*Dlu`P#fupVm32r`{;@R zCFeVN8(&H?Y%PHmu$z!o*hhyM&WypRqzOre9%!utHT98d5;!`dDWFkKv>TD*+2#+> zWBA$hJw{tY>w`HF8Rl{d>I={1+IBogIc=L0F^d?PKGR`;xSj4+v^6rw&aX-g<-lkt-u!HPmi!*kAki1c8Uk-SpK%0mfRaT>GyVMde>e5X*uyFF3%E} zlsH|!Z4_^@wNUM1#IKj)PcI)X+{@vXzMMb~+42#B#il}z;XEDlP++MPcjST8-%DQ( zAoaCMsZXP5JCbx~$5E(UY$d*fU!tv$){0}}1UdSCKAaA4tZgp?4-nmYSF73+?U zN2c6XC5?wL47yUc@MTny9p-Nh_6#v-=TJV8E>@h!=Bg@D7_j_@v;talQcq}1XDu` zQw_+ii3LAckp!&pa9%L;*%-f|U|(LHYr@)X4Xg}h*%;snDq-*qxMy|OLzT!gili4~ zg=)$X)+3juC-`{scWznxiJ--n0vk+3O;2?73k+gMaqA-e>5*9q{kic+<)GW;Tj>qU zyHa`os#Fgi1InG-+!`ndLAC|AFB~YvwNmW2mCPt+=t3pqT1I}pOl#h6`Fq3D=g*1$ud zJoGQyR)F?QmTG(p&|tZF2pp(P&HMfgwzq-x-GEgi+V>L`(HZPdxq#GYkxdyl4v>#l zpaqjDg$TdOQVGvhW+MgWCjv23_hNOB9_hpO`ZFT*;1aY1_Fb`{&XJOCY=V?ya^>?0 zRBpl4drz$?#ez8OJyOiLO4E=d7SE;V{$2jfrt}}DgIqKHXov+NQAX`o6jh?VM z6P-KwR;z>VQ;^PU8E6wTr3Er?1++o*y_khfW=d%bDpG~B$3xV1GAOPp)Hl5q_Wvox z&e+ucbTzfeJjn*?0=T|J8of;wip{qIaX}S4iIeN~`=zH&^r{;Ao>I&Rl=5c@Mk&OyzG`?# zj?Rb$q`(J^LU&-X^)Mh5V<5q2N8neSe(SDxuYi0PxJq)|4%Jw-a2XMsiX&X zMOFH+k2>MC8FG>L;I$)gLMq{I`TxQz?0iWvzVdtUYW|}KO4cbBTThD^ZB4OlW+x@B zf`2@zAE1W|gW(fS-SviY%xoq}|H$C%HKF-bB*tX&Q=oVaqDMOr)<%E=N~X3mf9Nb) z=>G)+aiQMu2UUO(8zPMuUBexLg;FaHmNSD(avCpr+~HjfGIk+~vz7nZ)r#Q~1yY)V zieh(}ZBt@B#qZBnEv6Vf%SNGSb~g$|tpWL6taGKb!%Z>U(uYzk-4S?Hs%de#ECnTO z|E@)@n$Wz891LW%%91{9tNWAU0_0(F!dz^n>9@EkE*XbA4%YW~*hHWszr8FvL-x}z zL2fcEZ2_PB61>CF^9U_HS}HvkBY3Td+TnTtm-M`cOEPTDfl6<9ZZeRk4JSg-f8{$9 z6#s=wIwYQC-SyOR)6fqoF3B|iF|`b|C%4$DJIJOS0gU9hb$bCP1voh?>B)E}*2g`l zgJ1KvI|8prEh6QVuHvP3_C=jvNOiVBD-5e}3YC2WpCTz0E8w-e!cZ3Hmf@9fEnyvl zd9vT3dkH9Ml<{{%)X29k@P&uvwU&m33aU@#!xK!&Z)T)wdU{UjiM4gV-cIR$S;Sk!;pRW14=Ov$bR9nS&J4IN9 z@0pNLY7TtXiV>ZduA|xsnK%(88Z`V?O6Sr23Un92$#<)hV!iKj*~OHaYQ_2g-hKpG zPpJiC%l<>f;5G)57tZL{e!|TdDErJ&kGLi@UsTCjR8cSFEWAKcw5j0BOpEZ3kATO{ zzya^K(5a39FL6|9b+Tzx`Va=EMhYMMaaOIn z-sHST`GnWbl#W=8!_cBPbA`cFx=ppUH8AnEZa-tA+#u?E<{rjcE#?2lsoOUZr<$+C zGStCH|2y$j5$N~KIE?2$LzEDIbg3k3ME?`u{-IM|&J~8fY^8IPdRupZ0gYy2O|*Q_ z`yGK2lDg!WkJi)MS!`-#Y>W@HL;7Iw?O_1`I{_1u7$PAh60y(#GcE21@w4M5|Dr zg*|K$9=Hh+oI2`xI??w|G^y{Ossh)U8T6^8`4R^{-Oz%sVSP?8(Z1j7`7byn=`R6u zC9c&|yr+iD@wbNtjvJW27;?LGMsHi?Rf-K+!ahsrM(M|Z4Nb(m=FU4)*iEieLehWu zWZWqjONR9Bl=QzDxCKu;`d7QOnL1_t4}Qjwxd8>EaBu(0y_q1O}A7NwmnrG zga2BNtvU?P53;JL&5Ek%&B`j+_<$dkjzH1f2;3+3hfFo)y*~sCK^m-;lPwjA3fmXB z2?d4$GLj_E;sQ$a_mH@v^!3f;4+AHLUsW}J@dj?=jdYiQgIBy~`K5oDeZ z_hyu4T*a`slZEcEBth2&TKr{}u&g5K`(k~WW$2kP%|!F3<~0iqu+l)dICxi&vq4|2 zhpf+L$+vgXQJmLgC;S}OHG!mQLB}yP4BBo9)_2i!`YM&$g_CI7Z^hmMZcvOrG~iZ! z8JVq{r|asIu~rvJ6HBfXF@v^R+Up+?ox0a`s8POO8Go-nnN(jIhx(|G&`4SzH^8QCepkiO z#1k4l!80iIu$v=QO>S}(d000pAWz~>qdk%R|u*0XvtSs zx+Bl&)37m~b;!+_s$*I8L=R)C7(~bNYen+BF`ct!Se4 z%S`4*IzFRNFEP`0R99eZR*A_NujC1y0Z4b|o!xBl6T$ zyA|4Mj4Of(Z7^?ds`#{{g%lJtqC=k_Lpox1HpvlRigG@u?*&y&fBm2D_sVBbehn=f zWnxU+MzXPqm^U>2v$IU}=kt4I{kgNO5B{etI-Xjo-xv?f2h%wp#Iz3MDQnc4VjJ14 z>R38HDrvmKPl9)hoq?GC|FLF9RCt1zM;6bUcw(NLhLbYPiL;5N{Wey6WGT+efQ?2o z#`AV4WSIA92Todr9;X&_tF4aRjd!V^bll8UO$2>q^SDMjc8s>t^D^xt+RpNoXd5v^ z5Yh~lB55oXNJHZ}j0;B!+zMI->ZN1RhPwXbTh>O$m)6Iit}@iQ@LqkWhsM)7C!!2m zCu6Gg$WRXQsEB#FG(WU#2K^{Ce{}^i7R^37=f;9Yjq5SMnUe(|sY$_l%*XmB*|ctr zw482e=e_plcD6qX-)Mar*PD$#w5g8Y(WKzt5@{beaEF z^Gwt<{tUir0n5MBF-F>`&UD67j2F_TsiwM{(O))VvL_9&-xLa|XOkUh(_5khgUIti zXCC@4m0wrUxGd>}=gw%xGfI0LYt8JDnc&l?t^)8|-gE@%=^8=Z&5T%qbzSXNE?(;< zrR7Z@b;kXGIOjo@7!kCcYvD5~uE2BJ#K;al`k0KED&<=AHw?>kZ8}+LeEE${46kS; z#*Kg#OCyW&8SM!VXQXSV%zgWl@OlAU8A#nmj0cU^G}5_v19i|jMmbk}@PtM9aJjyf zblx^Kk2l2Ra%ql%r!a3TnrOf1x}xPSLbWYktQrK$?uSU0iwt}Au!Xi_=f5>-fl=TD61G1~6}vxih~YLXYIMM5S6 z4vCt^bJcl`qF8A!AV=1kn<@eW663V2o zP3xiY5^f=r@2?>`4)@j&g#%hQ#j*7H932zW#wMe)3b0q~PD4A+SM6w`eTpamO!F(< zOjURtDrujqH#X6>D9Cg-T`w|G-3X7Eo-X*EfOxf$u3x|x+C$gxO_a|fKh}A(N?75J zs9NDBRh3P!Au7QnZG)`3kJLX>UD>3jWsoUutWOL{=lDiUk=6pzs?2mPpk1^L9@=)m z6aBrc-)Rr0UDG(q__eeSq%}~-h^%%E_Lj<~8#HZac?b5vZasno$0n>hGsd<6?FC)~ zUP8BkBLI(swL7rKyd}OZwH0%Napw?ktlQC~!S{)seV}QFU@sv?5qPq)Ny4AE7;+61 za(Jy&yH&t3vyzyDIMVIn+Qvup+`_ppl#S>{B&;jM$Xdk$O zjooshosAS1rX#HixQn)1Wqh+S5%W*SkTaz=U8(74X~bM<#2rmh;#=Z5`g<>Yq3&VH z#*?rYNO1%Dv6;?;nc}3%Mh1NvPs>C(l^7d3j+(l+#AH(i%ZSw;4e$no{a=Nr3^0K` zsQKPL(iP)yBDLC`td%vgW7de>W2)U6<3@~cWg}~j5pPgjXe@Kf+-pQ)bT-BDYk?=1 zHyJSoGStD5HH|)u3xzq_AC0-%6F{5SpuMFC8u~<=DJ?+fnbHEZz47Mi3e5G^d-)a@ z?7&*5`w%UNQ2OVk*b%bDX9B4ezUX~^~_6@AD2BpbQL zn1Nam<;s973?|w>j2}nVHh%j+`^0~M_V~vH&nQZJ*qxWrCeI&e@0WjuZ&`$A5kR#b zk@2t>nOebHc$q!huCnPt^Ka-7d8#{Edc@+8IXFmQ#a@C0njZqwcB9>yD&pp1e?Scl z5_%If8=9S5?>}5BQRy<;XF1%u>51#0|2oqirpBqgQO?G|Y6-O^NividMPYwHb2Tg* z=HU&nnBTWX4gGLpL~r@#%c+7L7D)Hhe!%~FQJulHunY%HmB<&(LET6hwRrYoD*vy` zv|MfOsY6s^j9P7^GB(Ub#uzI`K1R}?17{8P{NZ_df8bOLIm!$ckcP_g+^A2JY;c{4`i_lz<0^=a$i!3$=D|HkGmn)A%~Idf(#2!B~He}?q)nHdun&74EO&70Sm zls*cJrcR$_97DA%3m(P)C8Z-p^YzQ7;o@xLP%#cR4=3DcFC9SR`TpX3A2Gvkrm;7E znaw>#voT$S50s7+{7(sW$N%x61pI#?q!WqH5bT*I<2A@jc<9#|qi89nNcz82C352w zR5H;7STX`e;Tcu?)uApREswDIo5!kPRhiU^(V-BR2kl~TTDBGI!5i8*S?y=IMrr2o>p z&{}|o=jO3E-Hj%F+v_htdicNJIlNcV_=icKc4+Z(OR4u%C3FVlEvr=e8hO62`1e3@ zklr~Cw^fh*J&Mf5DB1%11!5Ao1F z;-!y38{jGJ_jkfH0cQ;F!-R+)4JmJ;c(=${-e?3KYzJ;tQTz>@3_RXcgnFuEQP5?o zXjIj$mC|U8m6+YKrXp=wBk-yL^<5eMewc1q!_&POv;dFxm_VzcOu9#NWJTj5w3X4~ zJMddN-M2tXsY$h4%~!jR-wm}CRaJYoa4O)_O-;i~S2Z%`%0^}B8zMs%;EYJ=3!?rD z(y5$p0Eez@v=*#t;_*)77Sa6t3be1t(~36Ha(!b#%iIk$@7c|g;TSv0E76Vr6}$_D zZIzArI6jw$-tTbRtPT4EhEA&tF|IMt4!auY-eQIh5M&Oi9rPjbsVvWlmc$X@3mngC@J_0!UMbVIxD>1Fd8O$}u+~dh@v~2laYPD_Gl?o@*K`i-tybci9E^QRbuPAlbw8+8_9=Sk~C8l{$1#x{9qTkPf2z<3fsvamy~AzGiC5McK7(>-EO?LOev^p zXE|Q8s%n$6xp$~0f@a?*uzb@D+fbVQNAq;aORT_V_P)4-{axC@uxkUSh8CN1_S8at zXx}fvlb>`;zHRNVt7{{3N^)ZBcOm~DfdzN==gFY`LHD>Df#1QOg)K58EAGKAEOZ~L z>u0zO%fJu$jIe4m06vv6Aj|0d8vO)zOSPvtX4TM~+re>c349VVHjAbI$>|opRYsrN z7Z})z{nNHF&xCqf0y}7`mp(@M^Sj^Fw;|pOW!ArJ&7(f}p5ANQL$%7*eQJBbHbU$Hdz(`d3m4Dp{Sb6Cl=a+Z ze;~hO1ZrisnqlS23@v+RE4Qr$HmOki!Y@$!((aqBA%j6=A3jU9%rwv_)b!{LS|kPD zXP7atl);WBXwRx3END|~Dl!kp+fLSk13i)%y&y3bdZS<0ufh!jTKROYEh||LZ))B^ zmphNyP{;F6+H!L=`}fp3x;F~R$uH_|CahD$o|A3f?bk6`hU}nDQ>CAjmmQ4LEU_}i z?4UL?n|g6EvcL&%wC;lKUZcY;Pzj$s(1H&Irgmud8wGvxKyds*fl;_YDY%HW2|s&| zeqCHfL9znl+7~E+J(AFX6rR9}!c0B{e+`<0AHdQZV{E22j?#<*wNC=wG~6+fjQ%LY zc}FHV`g)FFgwR27lnCyEpZW=>zm)kRb=X z$O*=cO3O22ZgbEFHZ>=x$=r{-LbGjOApRQeV?_%6EN(X8SKu!Et>R8Nu`Ucj)KWxS zVEk=rdCg3%mv!3E`QFQr46N14cfkioXvF&xJge~>gXdwa<-5lS@oZcd_1YfDum2fnoOdLWwz2I#0X2;_1kqy>|#ke=s1rjnQiqY-P3hF zY`+@1Cg@;y0DfPA^;55?MW#<;t(-zk7Gt7zN^jQpEj1g6z7+To(%*HfVWTy1d>7nO z1N)a|3G$C4*6Z_Ri^nWpVkPU!7BlOPFNW96bpy~Q7IO~mTlfz+1YJm-4ZLBJQIpsM zwjyrJVGWjp?jW_;;SW4=Hv)S~9NwwDqA(}CEwH&gvQuwpMKfd~j)rv|aZ9`FUEnab zO16Hr&6xUH?sR(Z0xLVpJqg&$f>%gdiB<+J+b;f6XbeZRRI>jlnHVf8`PPryi9x5x zL+y$inc3RDmSEBNtMw!e@Ha3CmPBAT8Rga3?c zKkSmnKqrLeVqgWisXp399vZQr%1SXi@% zm7h=`3Apxg*ErjiK<4jd)?Tn!c(O&MfnKv{hYZX_+mpebCP+2ZwFJ@u`5fe(hyI(- z8GO;GgC`1`vOi`sg-Nke9oQ7e4ns+AH|n7+|G}nl?Xog8P)(VfXM zLR*;77I!^Edh{rb-YeVsgkgh4ejyat-oD>P^(2(AtSQ^-4`kh8#fumz5}5!kne@71 zc;*W0$;e%-NXNYRa$DfdTVeZ@3cv*2BM)q*>xQ$bY%DAss58~|9MV#ooga2YbpG;m zaGK@Q5%Y}Dre_+~eX4|S7 z*lws(-`4oQPjKo&8R_RK<-$T+pX=BCCu1qq?2Z(VO4bK)dk8)1tuEAJ9(u{g^*18gj}`(z9UPY2289Y9o-7*ZPgJ zPoTlCJP5zH8+O8KrVL&n>D)4d{ejkYI=d?Pu8R=4&hP#}qx5xg4Y%zJSgV}#Q=I{@ zw7}e~h~H#+@;vkosb;e}6FRtA(ed^4-kGf@4;R*_h-ttSkGb|HuF1)37^v$YXpXC}?g8Fs!mRvU0V;PKnq9=5oj`inbl58J4f3_7}d z>fJV4zRI;Hu@XLud)o%78DOR7N*_yHS<{-J+_y~6q>&Vb_z?6Bm_g-1ZJjd6Br#e0 zEp7j1M0g^pmv2_?)ncTJTEipF0;Y5#^_m?CA4hLUnEdHr7is({92qY&q&wz8X44)4 zEJ@Z{s7L4+wDYnANufZ$kQ{JizD3~(D_S~#fxgP7bR+y4JG(%>VqoqrM=>yxOi=Vm z+Q43T7}lvd@!`j1y!>aBlH^oO>hib10dP2=t1d z1E-IUOYKI6e0G?Sy?9pR`4*l|gq;W(@32^VELsKm&ye=3lbdi3I$}&+eMoN8=Q1Db zA$`Y7p0@^|+I@~%YCxvP^-9G!Y|Hv+GR=;=myHj#5^HI2F zlT`DyR@Mkx2R8ZJ`vO_bR9ggeV^4!P?xr?oAnLmbN>XuY08SO!RDU3*T>(w#P#{0Z z3bB1;^{@jTRPT;9(sGR~&UZs%xgP ztvb{VmO~hBkWtWLf$4-I!V!cYT$(QzLIs>8-a@*GSE1ZpKIw9 z5gzCBjnbKaOm=th$@+G&h4mfN&Ub|@NJk*`nkF>{zu4OxvkLOWSK(I-wkj@lkt9Jh z_^)|fBdr21;Mf0AIF65y@~vt4V;Z#`xEUu_Um5%b6D#^Nh7i)y0o&>LeP$zgmPaD< zyTDqXCWX0826KaDI8jmV-uNq&qs3i>E!_|+aDA@3Op_Zm%G@kDSJ`LC`dcJ?{+-PVy0=4G}k zwvsJB7&cm%OS=s4#G1>DwCmn5{8z5;w~kCc!XBsu2U`G_(s@NgWSe1OWLtv)_x1+T zmwHN%|Ei~4Rh(2#R~EK&HP6%qaEdBueD$}r7S)+wdb zUJk6i)<2oJ!g8$kQS1>6?BG;b{teEpw$x~&YdUiS)%6Z!j{r~eRcmjtXA*Scom8%7 z<>L1&v(8Uw-W(w_bqhvRseCdO3+YnXh&cU(=0rXG2vaF5(77sSWsq@BXnseh^o>@k zTGnWOpV2L-sk>ZS8D#4Q+t}U>=SlBjE?AfR=*^&_;LV`CKoR6-jGgh)WM;^lkab8& zdN;_CcY!P44Jt~vz!%Vj<|<9MTu3(%U~QCznz5fwXpT?RfX}2V(N5+QnSMBZaZLRq zDex13{(luAhxez~XT%gek`gnS8NA&hJA+e=Ep~F4>kLiDiZ4GVq$h&*2p#9M@DsW8 z3t5|UfGmw^3u;focjHMo4>}nX2XJlIOFIJ3HJ=Thj+u6Jg0FZG*Y;EC$>8Y$kPEzW zHYlc?3?5EVqm*#UpRZ;ZI|7coW4fOVx=_MdhQZEvCE#nPbkIqxtJe^Q9q9pD<4o{u zOumKjCv)k#M02HO)CFP$qz;m$k_{=gv_VYO)xfvy^xXEaOAB7X`+lulS9<~)i_inA z)78rG?T+bvR!)3cKxlb#5N^)#NkyBKJ&uRl&3LEc-#-2Ye1F z*%^h?_;KzD!sklj-|y_@lPM=O{|gq?lA|-vuNA%*{u$IbSLK*}L(0wovgj{U*(Q|C zr1lipcFmoh%^Eh9Ukz_a=_*yrY0XnPGFQ6eLra}6v213J(goeHukTnf0_I)#*0t<9 zzlmQYelM(bykUuR)kC@uRwblzx%)MQoav7DbJ8(h8spbUk#?p{%yTf%+sQhr##74~ zj_O4g?=zvj8wV?aBsx%k2DA|U1@9$D;lB)Nva%qo;Ax%KoI2k*C-hY7NdKXzGqLX3 z@fv?#1Yo7*b;uraRk=Cp`fr1r@r|R*z^Cr_YbKv8hWqlFbFgC#d;<-%FR<^cc~XK^ zZQV?iyVtqNu5qN-%*OBC&N%xn`}oec?am^+eW!2L=Ly$Tsqh*wqwsM)Ig^h1G+uX} z>G>F7kAkF&72M(FC;Xj$B_n)mSA`3w9DVsCZ2tA<+j zZAeZ@7I(He7xmI8eXu%c{+mBaiT8=|8ikKj)R>PY;LVz3n=mE*WU^VFoA_Mxp;L zOI(8`m~Pr?zr=3?zdvUDI^h*-x?`6`)vyzq;~V%N_$~ZJ@ItoYPU=b^>6XfbJ#po0 zfdA(8*aHzJBIpoY>sXS9;H_fGSp;f(ZfU*}JLD?ccE<*rtnKH824SN`)-X+&sM}~^ z8@9nSN?ZLj=*YppkD6^^BKG(*WPAM&6RaymVlB1mqQI{e`YAcX;o;#SpHdF%gKAyv zH+~g<=`^}p@ciUU^u-A?AB)w!YBggHukicqg?xfB1FKw)I?n}vN@=#2^3gxM0r{$L zf?q!WO|Y))o8Y%K-vm$YRHkbDoMx6S8}!JQoZ$HnEyTCQIW%FX-iEcACwy242qEKm zziJMj+#Ar*V;txP8MJD2f~Ms-+pV4PGt`Gxww{jxbgUB+99t|eG;HKg^E>%Qet|ep zo#y%^3>~T6#a(UA=eua+K9zi*`5S+f9Pg8K8t_MDTg_JtcpE!H!}wU`=jIa$vX(PL zt|kp_XM9A0jT{!I++L0L-udsCms;)i8A6KvVGHZeBg*=*&2nH8S&LJKo=iv;@k^83 z=cgcNVqFteU;Fh;d^>Y}ngCl*U_?0TPs11xVMzOQ5O&G)lvE{w%)>@K4fqOK=eb?k=^rSBZHyAbj!`OZp@H zb1h50M1Y<=?4-aS0UYzy)C=4R^?&F8U;P46CWk-K&#T-Oy_*k&R-t@|W*jm2^v)UGf2&LMC( z;9bWzwk!v>^v*KW7N?Y-+4J}s11;mQB~wZpA!)%b79w@;Sw-#p&Q-JNCPwZ&8So`e^pjn#Q8vncWT`3e ze!x^+2@J&@E3J$8esMCXy)l|MUK$QNi0k29iSg~e4SLnc_;x_|fPRglbqs>MX4+xo z(ZHq{cvmdxLwtvwA6lHg8t3~7a(@PTXuiJRN%|7s9w$i^q)ctBG%!iK`W~ucj{yqEi{7`)@Zi56}%Wl+vm12O|D&+!*(NxaV2;P zmFss-xMkh>_=Vuf!kxKz|Kw%s&ishBpI>IGmRVo3vg;rnzM+?UuaF_g)}0G-)h&X| z7s0~ro-d*7zv(56uFw@Unb{XrmI}IgpFe})!2h%8He%Q2%9dcC?rAk^Efz}q|XSK+rg~^ zN3zb53)&PW4j>DD?8_6_!#oo_3h)A3e_lTYx<;-k#F@@=pI z37D6?+YmgE!mRtgg@vtERRLBQvk<;tbgBQlyTCh=Pesbjb^a(qcNabO6OMVqY^J+Q zc7jHR5kGF&YGzu_40I(y|MU*-Ya$|AEZAKdfp3_oQX#6Hy<@khfa(C<=FgK+s)MkK zmI~Pdp6)NnB7R3C_qibLF9oVP>@TW&`-|pePOQrn&CvZt^Wgq+DX2AW%<1;P&JqLP z<0^PH4v)+KwYOXjc<$`A$=)UXmfbk_5wkgL-|>?-Sh5viGs61_8xhQ}1AY-cLs)`9 z@0Yc(r$(;tbQVAMs&zlSSHVJsGsDy@lml134tp(U?Vu1|=nbE)vW91c2>oj8EC=B$ zr>*{XVU+Tvv+MNv-3QoohJAr6S1sLdDHXTb8!_huq1xhT=!2Uz?eQ2Ltg!bdlzz7WLuRCnitt=et_blx1--S?&@OXfH;#pW@E?PwqgZ+A^t5+4W;LjSUxJ5E z(lPxBd%6X_n#{iO22E!Ek#;Na`{<|(Ts$X!2^Z5#wQH4oY?YtI^IzMns0;iv?@8X z@A=K}V|)s}pv^vc`D)=)Jel%U7Tme_#0|hnoCSOoM-aXzG#gF_iP;J5813xWtm#7) zEho8Z3+wtT%Dr5+6Tgn)S7X_6eic7YydZ1_T^QxsF8n5y{?D?t((_E&mzMNeH@}A0 zpZURE;)nxIic@f+#$i1Q?GXG)?4u6mnKPfdvBPJKb~TOv z*+I|On_ik4>{&MpcxfywA-{f<834Ya&n~1i6U9?}U!0k$(V{J7oMSui5@R1@kN6a4 zffEweGw(#)>ataKox@l|(=9Jk*~{$3j>ULOuN{Zq>N88+g#rT#QkKC&#*B_~A>Yrn z0aU?rWret{rnl}fINO+gXPn1zqF&+n#1dbBT&S?m(~WW9gvGA5e8a11t@i2oU&$ZE zUU(6Hbj{Zb%BXFQ9v%5^D?NSGmkZfA3ooZ=!NJSzgK$PrSyB=v{o-QBZ>0 zaMIH{%J3dlM(4mG)(abP7LRegBmAqg2IhVZcbvqr5@T_Te~V8#b3-h2;H*nV9F4(K zOY}!$>3oq9wh6HCf2%&)@erLaauam5CR}qJkDcX$Q^}Le!LHZF{mZe~O4>HPQWEUt zv|!f82YX@G#yrr2vDi(BqY~{q<}^C0Fl#AxyS)axN#|ZwN@47fbB$e#S)-7*&q-%( zB6gF{@wVHUXJ2POsGpNZ$8m|Zn4eKtNU8YRw|Qm#+ajGo#Bhc9Ucz5dC1>c)(_0>T z`h^9AmO6&%(XAbJesIDuW@~v^QxjL={9A<+&T9SyzZvJ>1vvkv-9P_!r{~{N1y3?~V zcX)3f^iz@voB#%Ej%~?i|4BJ;E#sq6HXJv!l24%&vGdB>u z-K8(m$yzEkB#rhnQk43`#u!o^do81C;myLv9-ZlcH@8gq+6Fbyy=*<8eVq_tcoR76 zA#l31z@K$KZJ9wwv6`mrg797^-o7mCz-}NbdrNwTobZk);q8PoL2(*A-+=F>6!ngE zl&a)diVL{^!3EsS%d=r|yBBcx&yZiGT(4go3&tz`c`7m@!$bzRw5ytHcMxdtsEs2Rj5l7~ZTY6ka(k z=8f{f>WALAhY2VjjF5Dfy?-v{gS`ws7`Zb+D6+>%d@ypK4>o~kT2?S)AiJ3&(qG9L zx!{ADDLqR0V7~G9`CzBO2V=koE0p+PW->s+27DMBzyn`=!LA!`u$FGw3 zU^^}9hHA?5;J@ap_nudy7!Hg0k($#w(Sv&PbC}NF7v;udqc$nwkbUK(@#=?PUrgS zDO4Z-!_1!5)tl$&lr76;4Z+NqJOSq=F5RHSZSZ444{(RG47)7MnK)Y{{2!A(f7Iu~ zH>d8g?>e@E7TF^FDA6G6otvcRTBjW_{XM^qPdKwuoGzV@ z;uxi9aIBY3N-X8=G6QW>;0gCueY_*S2Kye)Pj}~IdXNCX7Vr_Wau6O8b zYAmB0V(f3&r%As@G!)`@bY{ePvqP`Rnq7mj(Jn5I=2ER5IJ^@JAw19sv6Sc zj(8)JTtDE1XOQ#Sbodz=oQ@lWM%Ampg~`IOcGka2ndG9llJXkMuzQ#3z;7g#xNSct zd|-LCz6#!C7^4=au3pWoG8q!F37FOAu^wIgcjN={U4e3h*23!f0v9mtP1<)&I~!EB zYkWDDoMxg@H7n$Tg*40ADcuJ|GCr+*XuJG+K?Kf^%s_A*AJ>;th?JY~^+kPZyC$ge zvCIoP8dnFHG@+Fr>Cis%qK>qjVnB&G;oZh~PRPmWSHBKpi!r{_t64)^=Sp^bZb`*T zs^?F(oMNq*A)G;E4n9*qi{DjXM!$Cmf2-*(gs5)<4X8FU&7r}rGz{fDn%$jO*yOGi z;I6(0IR7nh{%#rX=htGM24d99d8<8JoGyF<%c-HjICyl4!^uy&4IZpHA33;BE*;&M zt&a))q!be*?}(=Q9;kJTu*UMxd3C}JM|26^V98PfH57q zXZU;pH%Z_IcL6<*dxtaXgm)bm`3yZ$Gn8M1UUARzsv$DmaCQVLVFfbkf2f8#xJwUv zoZSq#S%vTlLJ>mA65tMm_LqS-5GoO<{zn%ZFZq;D!Aa)B<~{HXayKwGNYW{PC|2a) z1&;DhkHHr`UsDj|G+!%aXNzzS`a#K^#hp5Ax$S|y38QoeP4Q3+Mh4!|ZQO;sfwUkk zrJFbnn7$tOaausGyglRS6hP}aaA`M4=dl9pF!VfjC$Quih272K`{2J%m;hfKiOZ~y zI*wRoG*IdscuKZMznq?3CBKQJZ=ow&_(l2nxxf0=(JN|I{zzFGcy8LX@0DF?8#Di< zj5-(WYrddMT48ylAz*+_6KUzTyUet@>;)2SxEOX-0pQ3`(o9-^UI4<|d> zQmhpYxV+{L=><;`BI%VBp0AX3omAePz>1cBH4oKLJA2!Msv!o*!opuSe2nj@LH{w@ za@vzom#AOmRCq5={lt)Avj8Jn!0+1=C~2V(xhxo-^Pd;9e-=_7>5ycRcyMD>8Q6Kx(=?~<{zZ(=*j%ekpVd9hB6n%i zi1-BAZMoBsXq)dF&1w_MEL_7K__~LD0$(kvdvkt`0(PDJk;+~^rBd6=rw;{oOV+EX zw+mSRljw*r_LAMAr*fUdu{z9DD3#}|7*$q+fyFqJFP1zg;Z!c)8~EgE#L+0o5Zk-Y zv@F!cnpGo<6KKm4^f;rBpPqo5DCTtoY%3E@J2U|lEK3}OlF z_%KnA`+!rkr|F9M@dEHTR@xpNEhPzFpcu_~V4s+5=;tR|1gtpD%Fh+fE7`MsgnFg^ zY#P?65;jd{=EPpOsy~weuC)dbLssjMFY0m7Q1kh5e2G+U3~p?TdCJv@4$pVY8~5jX zZF4+ivO5AFgyMiJI$$SV-gyH|cL7p+@kQ+K2wx)n`U0Id>T5;|ovN<+UB@eIuUMOk zGX(9?y@6v_GWagJbLbnr!}cX}AA%!{5xYXU@oLv0oFy}ONI;wcR_M^AvOG90rc%uH z9mqo5f!!_o=gaAL^`XAm*R-qqwGt!MErD)aLg!;B^fTC$6CRlp@h0N&jUEeK+==eKRIi_h?m1sAqk6NXv|7fLDxl^!)sqgr zI2kE)r_waAHGsO1rld2COiGi0G_bhgnFKv}#x z@FqW$7VzS$}cuuA>LI9|l9w#RqE3Z0%p_c(@J42_QV z{4Vu$L>{)Z`oy0@q3`Lp-np`4qTi@ypQ`a`EM%k)BAZ$4eUpKiBvBs z8Syy(d#n1Wz5BN9Xx$&VqxC?-j@E;HceH*qa!0F+Ipy}Te|NiBJjvhP`A>}YHh=L~ zuj{%xtL5IEw|BI1KMe6kZ&P>`KfKwhxZTs6 zhwt(qdUzF)5njc%cUz-YXL!5pALUgf5U(n-w^z}Z@hV2LURh+cm+a5-8ZcHk>APbA zqmNx0y;cU!r+M(^wSJ6dIPRo>UpR>l5-_w#f^9!uXLUM|0f z*Mj+x&F$$eM;h5&xtEN5w^f60iYEqpWls$8Ms6G8)pyoK^W}dr#GAc;q}Q6C<+aju zb9;Fo>g-<}`ez0FhLWQ_^89q~TUx6}K3D1GmJXHDz><)gt%Hs;+AY&oyI;Y4)ef#` zR1U3Z)R;E7Ph*YD#MoM&80KY14)uOBGQ1|)l)46(w*gMLw|*xAr(nK~)%7pqJ6)S} zu4B+XYyJT5q-{G|Betb@C#~MmT7>f0$P{l;!j9I-_&o*vr0t%PzoS)!@t=Y;5lc;8 zCHi5G9OhLe#Cy$8jPQ=#cE~G#LfJX)UA>BY8OG+2*S3xGM&$SMX3rggzE^s4o*3$- z>vHV=A>KUNPYT1P3NhONn1X(G9r`HYN%WWE6K?;zSZ{s2%^jg;Y3&a!Ym}q!Socv) z9U*n-A6Rey$i}*z=w67tbe;av5!%;(>5kTaBaf{UhXDT^Q!HJ1>^!~^pV71Z1+r?? zuftxWIGYf2_MA)KZOB{k_tDIlq`my2`q7W|e5-Ks*~UpF$K4atkss??hjl$J zf3TMrXMO@ZC~gX$^MIc^0Jpy0!d<#;vs4eL%CELHJR?K*u$q_zH**{jU&({ zf5JC-Tk?e7|JoD!ldW;*!_|z8&uJ{vRx_Y=JUg*3N5A;J=M<0f6e~gVV1FUyqzvUd zO_d@W51R(SaZIUG+=a9Srcq{k+Qk$scQIt8s{-kEq7Ct&U&@gWI{pR%;yl*(-tl7{DFMaXNRw2FJc@cxSQxXgqlK z9<-Mw)zvas9Z)kyb)&kvT-=BDF{GPEp{{m+gT9A`I2+lWZ^W|k6^+!shul;qQks#@ zxlbOpA;k{(#>1gp&`i>J%T3h`2s*>g9@Xw{rtHQt313d6I>%~;uV`e3c5O7m{tEDX zENC(VZ8Oz7W)xkiZ6URh%xWB9EO#sTSz=6VwR=6FT$0`2!bEqB?;(!oWeGhe}^J9)FT+)414%|k^ z2XMb41{#lj1nUTY1=;u3Tj#Um z-Z~7&SB>g?FXMd4O-Ihk34NY>jFp}T`-I<7;1lnB4I>6H`)B$ehKC7T9Mk zBE<2mV<8@kW-XXwUo?l1`A^MXFwee-FymgFvtZ`@h4}R1^Dj8&AWdk|{C*1;&7S`P zes>UUOjn{(Mkv(sNKPZ`!bUOCXa-?$X(5wwoLsI@D3!387@=0f2cM=3ZLIXi;E%h&ipI5qI&O-EV_6yHF@Um!*)Q!%jKL3=R zz7CiveI0SH>ibVt20EC$K7RTH(nSp&cZ^?n819eD;@OS`bI_UvFB2yFDaW&O2=mkf zZJY2M#=<^tPQUptJvRsY>wM{@bk2f#j)e;y^PfZeO8?XBxpU@}_M89gY(nPV8|PWG z=Pa1>6vA_~i^9w$j?#g!uuN-O*zc(Y^XCz!XwKqU&%Q8wPUma!(@69G2zw8JrkZ8} z^duql-n*fM-aAO|y@PZJDG&$=B%xVp0s<kI=eHoWHu1Al}Ss*0}h`=O-&-w$@qU-@avxz{kKN^rh!(Z)5-AE z{`p%Tgjk0ly^ZJp!f@(8X)Hf$=yc!~=!CiX0^24)foO;w;($0I@H?gu51>W?NC*;v zBp?}R6Ql(GNn;3Yh8&;(2oEu!T&M=R3(Y`Cn0Wv5{J+uy9uFuS`L_lRP&ywdR|-;q z^dUP42W3N@fXcD~5g}0E+wtrOP6RJP5Fv@cfM4vjMZ~~`|9?>-u%`m8765Iufp$Ub z&^lrrwa&3Fu)b;CW_=g98RGwiun|ap0T3@DDkd%=DJ3l9#5oVXnHe zB89+!=p?+hnE{|if7oZR;bnjw0KrIQ;vp!N0PhqC!oT#3phK*1S65n?0)A|jK(P6Lra3XPRYO#`zA%4Y3t=>P+s3B>|{J&BGG z1k6$(Ff6Q%56Fis>;>X&!MzM#a2N0q;f7@5GK(uj0A zjSi7mAt)u420B9_QsbEM5ZL&@(jrp{#0-d$8p~jUl})vPxUH310KXotq=Z$(Dk(u&Wvmhwi-B;IbX+C_$^^r*G3&TgCJkaT zGr>q`!w8HJ1+)se4mscmWQu+qm673Rmxw1aQv*WiY0k->{_%kp=@zVNIWYi%0Rd|e zUQWlPZ6Sy=2KXQd0{|X7csw?qe->Pp9*b#!Ap`LW0N@NU05}2ovV0ieW4#VXv2tf6 z<5OedL7Rh5bP&#nT7ZV0TzK4G>b$Frp15g1b+YDaezC@#>)oyBmDfInALTV{ty2D%l}XM zKl%T`|HS_vm^Hd^SJ(isCQJ`*7I^gj&YT_?@QpAl1>hIz{S8}cJSH2 zpa51F6b#ZqEGsMtN&dy4V2~~eR|wKUEGvwGD*|EQvck4-M?o04tZ){T#R>x#tg655 zhcVoK7{lo>hWi0yxcw+F4lE497&r`CWBV6p{l##9;dr?gEDA_1b~(m@Ue!wg6`KyqM0_*fw6B|>;Q69Uo{40t9b1!CgBK1{*m zfWYVJU>D#77fYnZ!U&WM;TgsNOaPbyFoWV#lkpVT1tBIaITn;h#DQ!S8XiZ13uoW~ z+abqMW9f+y0Knql5GV~UF$qMHsmXZYf;|>y2UH544rhQ}JRNj{oI#_)4v7Ss1~%j* zh@6V2;6W6Q3O3CoTt+OB0@0FbK+dC4@Tqu+#(EF1Hc$qQ3PQl8&;i?`0ig+45k6Vzi)uafB^ib zz(iJwiEt18<%fV&U>dUji(v#mSO)mBz))!z26-zHL#A%X@<1HL03U`KPi9~U#56LH zII)z}4OYfTCK3r45X8jdQVE;EOaP__q-Z9z(I!^SM8Kw#(@A(#MI$A_*ZiMM>ggMvZf%|w)r4&ARF^QqL3JHxgkj)vPvPO z!OzRfg6jt45t|SggaSecA&d|~C?b_m$|x+G3LB1+9FMbz1Ofz*_W>r5A_RKoe1p&&qIAixClOQaGoG!h2hOsH{iVH=ME=q4EHbO74{ zB~k^uMu@B#oyAkk=1lq$3d<*unH;;s!q1As07EC3Y%nt~#7+5lj`ilB&quAqn% z769zm0GJKDkAlkpfB=95pdgRd-U$F~;iixrVzUhvVQV1_R3RA-eMm&W7s7C0HC2!z z+5i*){L|e3hV?*59{`ZUS&Ro9iU2umgNdSnp9cWUOO!wyw-5vw0zY_og`iwMA;^v& zU;zMv0E7VWilf0{4I1JB0Mw~mq__}-0ssME0{|`@htL4C1KkNNp>mh80rR3W>EsMp=R1JJ3dHfCvo@gf0S$h(c%} z6|9ifR!B=LP>v;1VJBiIQbh&1eLKPiVX=-RQ`Zq%>!1SoO@zWaB61zEZ5^>=9kF>G z!41+$NCFK72no$%f}B7<0lH5rksYuGB9n+t2IRwJXSpOccn{-*9atx42aF_@PGuuz zkeTb~^mq`p&PJp#i0df8ozU<>1ce>!@MIDbNu#sVSw2(-s0pw{29bS(=GjTCJrRuq zEX@Fgr!i1~f>EGO6onSYMh7LK7-T9NBZbaHGvFY59FYnX5w>t`BUwoM1(eU=MpzB8)hgK+6Cd2f(b2W1S<8$b|Rhbv6>% zFgRg{30C$x+TO{<&3hf?i5!OdwQHAvaiIrQ#@<4OPmU#>C*L7#y9B%Y=Ms z-~c3+Lc{?5iiykko5ca_IT$7llL}Zl3DgIc^WUlcIuipp6wuZ%@OXkD zCIB7=Ig--=#|1nrHWRazNT)%8G#Z9POb7MFfg=#0-m&dUi32(k}w@&$yhVdoD9 z!4U$;0d|5RCx3r$AIRC;AAE5S%>z zm!k>5VbZl(r)Q8ioe0mcHW~04CXk*eta$J?gC$CUeS0G#A^=DXK)wSkiU8ybSUN-` z17Q(}t_W}>2eTf~H-E5*0f!+#kT>uFfd(QG=$YC;%?HPx&}Ixb9~aMG#taxVYkmAh zdO#u|CIe+3#HPZ$otOc{U^T$gVMeG;-ayHKC?Rb+F%FyrXfrdDK?;1X25Bd;WEt%w zSgZk}0a!~ws$jrw938AFAX&iT%>O>iU{M8-^T7bI6pMe(GFb7z(I(L-U}*xm1xRS1 z8hEj@S_vfG4Ic!BL*d~N4#-rvbRbj%-pp!iY%JKuNI)cwO{KC<5o5RF!2#~Zi6ToH z2O$uX2I1r5=s;kPPoe=y9ZW41xO5tjWAKTL)FdFh6M=XR=nulfe`Fej2ZPQ!*dYK# zfdF)cWcXFkz$C!G2_ztl0P!5?|EzWpl8B5rh(Kc)07A+D$FnQ}7b3=iiHC^bfCtbF zICjB-O%qHOnUM&QSV>?zAb>*=a5_q&6G0Mi=(wbf46Km_TNEvs39&NAvHA$HjzZ&M zjU%3zK}ZEnCKG_@%7B{(5EGVgSduI3{1X7!_@9#=aLNkQ9V!r`z`+)nHXx5uSZ`Ap z$#^pGr!rz8%2pty!wx*2Nd#kfkdhKXe}PLhAc2#vL=u@qgAqdqtRVy719B8_8R@uW zfPk0-5RCw2qgW#F&|wEY2xGa)G_dnSNof!jmdL3zSepWG1JVQXbuz2F$z%c$y^~p8 zVG%JrjvKo@l+1vV(}98q(+jM8fz_M{dnhd01a7kn+1F(^egE`i+*;t-v)~T~NI3retw1H@43Qn?ZA!o=F@`pm9Xov^_ z8i7DVpsmmjC<`ip_CaOPA?O5D3tfPkpexWV=nm8k{+pHbEh{ z5dsKNAoFiRs33H}bwQgEjtCEgFCqXD4kR1`A_0+%NJZ>GWr#||X+%BZ65=Z2 z4x$_J05O6XLrfxO5VME{#3yi(*&hT4k{>CA6hlfQmB6)ihDdXyCDI=0iu6YYBg2q5 zBmqf5rXjPC`N(2q8S)VF1hNKs9@&DthHOW6A$ySzkx!As$mhsOT=Q)BBDczNw#PAd{A%m@;ZC&+@jwV z1H>u#e`e&ooWQMhS^B^{6Xk_cI0aAn5SP(u&g@d$`(>~^n$W5o`U@@r;eWcaqiq}V`HNv zFQb0GQ$D^!!#{qt@0!>&Ztz?8)bz*_erD5so=HwGO9Ru^f@!7k@+U99Zkt@&z9rzA zZ_Ss`sx$QG-I=mi!;3xJc|K6A&vzx(P@{iq-uPVCR@dS3>8E>3ds-29xp?DbdWWe{^cz zb;_)*l*Y=CJHOU_7wOThc@b**+pIZ0Uv8!-QNP0*I>PU)j}iX;@>Pp(?XK0K$^B2# z)1)Z7?*D9yT&u~sm^dxt5ny&Ei#PgI%IZgg%ECAMNdDdR#UP6>~Xi+gTrm=gy?0f#o>i3K6e;NZ495V zhg8ojUIQy<_aB3&*_`#9xa7qySS|MUra8T}US?bk&%OGLuv2CDu&&+YG2_FDJ9nr# zjxt>EJ(Jh@CumQt1&^F1e>{p4U(Tx+rIFn0(<>JlpFxxz=aq-mT2MQ*Hn6wGfLNUy4

          >?B?3T(p+c59%8BIcFJmeN$&$R6RPT3U+QLWw|p(jJ)wj7u0n?B3)EBf8J zt)0^dSt;|-?uQP%jMbZMq|3yDdy*&p8)S$r7e1A!6?a1AJ(dO+*m53;e&5O@?=}B* zL^D0oDYNs#CwaX=kMDDLg8Pksto?eYCiJGf;E;S{?Lh;p;yWX}HUiaW-%r=>`@Y&e zr>phbsban8#MEowKRj8rTTfcIsL^et`=>r^cY8cefBf*})VsI&>2^j*lt+aMy^Q#^ zpU=+mx)h!A@7}F<_rP9hgjMZT3(wYxh#JNrH`gOsH)A%RdtmxAy;a*E*`@Y%g!}Fs zLE*F;in9gTZB`glsW+P6{wH8->WtBJ=%+7F6nThK&Mr^`%b>XYpajOq1BU5sXH0uYTF}K2;k}T~z zK@arTmS2qt4Af=o+I!@^cL`QqoaTHhHE`Pt@vMc{XV!5Gw_fIrLc-LMRqhuyuKkmA zBWJJL1g{Si^(@|U)P*LErr%oThP_=EG$NSRJF$^u0+!Mgc}bR|*YthW+qKBA;bld? z<3|b+`)(aR$kS1^AQ)@E+DR$ffrz_bdu4w>_bW!quCwBGt1;gmHB0-iUOFq^VWbhR zp?}dh)AUFD(=U5%fBEoTQrI#|uzM4+bC{odyXEKm+rDl8GqI!T+}MY``?!R~f}CFR zcoolY%G!Qc=`4HfP|2gu{Q4nv*2&7X!(YXo7^_~oM_RmoZ*@!j^B;kJYp-le6ZVwn zKhDNAK3I-RnSFV8V7xor7kA7B<#|!5^iiM2XOFYSWuXBI0n5r=#nLz4=DnTG%ytdW zd(p(!kVK58Ob_tl9!l5BN&P4&5>!BQ@A0#$Y0Zoc8dg7DiSS<>SFNdTJ#;)v!9disX)-1fK3&Z|y)e)7NW2+GY>9b;Zp)vOxrc=&i! zPi~v*q#kKCLv9VbRrC3doi^RCTw2b5#mjpe>zvs9%J??(!cAu;>dxm29M_&T@uxng zHPl^xAN5{iPn0LL&lg`catvBim z>YLZHTmIzp8%OMaWfR|Mc0D`(^%l~htoVAcPdJ}hm?G9^AG?Hn!m*QcG@Cd3UL|EO zwST)q8jMWH13x5_t>+*dp*m_Eef z>gF(Ay#3-yj^ZWS+$;4N!M?L+hU1L|C5=KOQeIhXx@BDT4sm>KTX^v3WyH|3?ki-% z;!6W{yVfvcL9=UlFIUf5f5=@OM$`|6Avsk1TD!d%12S@M8a%ig9GN z6H1iZE0`8a?}y4S&z!WXK0!*kY!rr?x0fY4%2mB>6q!I|&dZQFlXY{?IP@75~>iVnYZXHQHXuyBEa5|>u`C%bxhV&B(?aXD1eMM`>8^*Wc=_iGL zSvmMveQBo6|MtwuIur09)GBH{f69@ZGQ=Y^@lEd2IX3-Q*O3F5VSz9#;TGmj{iR?{KNN1n|sA#0rzt8SlBg+^%9#yCz5J}jFoV{;eCtaC~`&_Yi7u&=Ar zH$gYXxw~4Kaby#Eurc+Cf{A@V|A!iz{PTJ0vt{VD4O!n2Jp2kbe%v~;`>v#V}? zh^=%H`@TFA9=%gE!FLL0jg*-4TYf>N(rG(Sz(l z7k-%kz9#XmUH6HYvC`!0Q?^z)O)_o$2~I_~4>7s?4Ft^*nv(~!t2Z}b>`mPeEKT)R+E82h|WjRrH|!U_bSrGo3z8NBd5MesOz2|x_XHDN_@CU zva8GT-tH|^aUWEh=5E_Oyp(#`@Zo3 z_pV>4uUtsQJ+L6gKcdR?V3@DQUVItVLA0zII7r7f>Z9L zXN4q6OYGa7PgZ?sO&Cd=^|@PE(3*AffzkZc`?$7~jo~{z9&*uI+bChzTlMc}*^I|( zC9>JqdvUJ`8Vi=YwYPFcmd>^lV#+V#` zsE_w~v{?RSZ!}SqcCKe}f_Vw4|U()3= z`Q5Jsxu=t4qtke2-yEk#?8vpPB!!kJFk59qZ7l4kE+0Pr%oxXq&6kzd(>N__)LF2i zxBK_OhI@>(d%l~ls9p4avGv{u8Uk%_%uu;{MNOzg(breGyik5;@*A8XgRQYj=G>+{ zd#BkTwUq`@gC>7^A)AL=5<$v7V&T2!-FGXW6W#7yN6&cuJ{&A*9q=x7^4%eca2jd#`8!kHtUkX` zx6@lp_9yqI&qZ`*^1i<_+-|fbQfgCsC7)oGPVJ_zd{>m-@@%@pb^F!oTNAb1<+m7J z)aOT!UTxj9rpW%=aogsxT7~zm`%q$BXLui}-t+mm$3?jJoq3^Qpt zn$I#eSINu2zeswPBl_sY_diBgEu2n;VtUPwNU<%v$UA+lH1O)toDXxyg3W(N^(+X{A{**VwdqUim+)jw~nO5l6fzV*-P`4Q{8=c<2=zwi6; zq=lQ^`S<*k9WO;vlPy+BvQf}!=ZjT==p6@UdSAZnUm^&xkpkw&ckv_2=$mhpD2?7N zU2?lrqZ1SCEoAYqGi6l9LBa=GwiHh9krxVS_6s&}J7@jbT7cs#=INKuaq1J^XFv2` zAIy2jRl;-Wc*p$%agy1~X9S<$HPCZW&Q2l3 z>?4+GTv6TCH3#-n96Rm}P7;|> zfzZ+^wQX1B4YoTI9(yjS?0Eln+N`=Juj{*LMY+-)t;y%tX6ue1d#XdG67_@#XxZn( z@{*)OX)0NXLKVKwY?9gwl=#Fe2@?Bfh9mCq#MsQ^DC>8PKiEy4#>+TtTIDR5oMfLq zf&HX)vmc^*pdV%#+(*llXTJ{24AiraDP82K>#^qz;Oy2pQ`t>hh{)TyS7|}tFXh|W zv2WUQpGBU=MAK3lC`*GfLPM6q@4eELD+K#P^Yrw=zw9*Jo|wG+sTC*O&Bs3s!BfDNpWZ>Wn#uRnq*^(LJVmF#|XRshsPgYtgsKr5GhCQ=cE%L6iH195LVb{Z>sl;0^=)*j(gakx26}u&i za+-o1g-SRc9TDt$d34*$qJ3hj=5OO;=I8rN<@fq`%jFUG=FFy*W7!pjFUAx(L;YQ0 zqIuRr@AIGBO89tKWUD{l;}6WuT=#{t>IcbtruggvdX)LaKRe3rW9-U()he4r5-VT8 z9PQj}G_sSI-^n>D^`OfwQ4+So!dWl#V^9n2<>xHidn4|IuO8krk^NuBMe-JA)~>&p z_u=T!vf|ZSy8rC;Rkn#b`Rt+`H;a7X>Yu{RcCy9=J5QWUnw~o=(r_S}Pehhir%tT= z6WR7k>RpGnBT+R`lI1e}vI8m9%~jO2?vRiuR}vTRpYSEaCG;@`@mi-+nLTw+E(DqN z$W|PQiAj0)+u%Zfdc>m=&HJ)XI0Mb^B)oRw91}KlR7v)DWm+LK+~6d5QTl>+h=iC> za{o}$UXI3_rVj6>7D^+;e#P%ffBu3ZlzwU{e5=n5alYHu(ew7d9f`YZ(hs8Wl4E1J z2t*0H&6$INu{@IcVnxMOAqxE!l9%R}?)2`NSRo~Jh}(wR_;YX|d2{-lwairgQ``<) z_?;OcsaihlG;y()#%mR_e{6}~DYrT3hGMQ^X*1=OV#@cjzBhM9Ecfkcdm!ykdQwyv zKl95ovy$WKacBJ>k9LZ*sbKx1x-E{LV)~m632C_T?Fzkh|4sVh=78GdO}w5vy5Cvp z@I7^m#@0!UC8QPn99-6%J>TS6rM%Ph@un5t?vn{6VL_KnyiS;8z0vFn$2Go}| z>#*rq14*9E{@HuR!Fy=S!>9?7bK`@9jHZ042Tvjc7pV4ZarLa>+uRd0UaIz&YRjHU_)Sb1ME()zCo4xo=%M z{V33LSNdYbqBD7KCFbQl(xLCDSvk9{>Ztp7TDfNU-c@mFhDhd9@+-Br@5*N*-!g4_ zmu-P{{S)oYylKQ!rm^AB0wM@!S-c+veOLNNAZ`~4m1DiQY_sF*f6 zY+@1@c5lrazYjtPm8aTGgsfo&F|lXQI?os7#%oMFmZ~=y$tjl|I-4B5E1&zT$~B6G zoPiLj>|zh?^U*4!(3euCxZ#s&ou~Es+r%pM#?yTcEgcwFQc^fI6P3Y%O!r|w?dp48 z*h6R3$_Y1q_ZjHV3$y)# zy02sXxN@N{OYfuB*|r-gs8PNqPR&-ht#3JYD$vK)fqmiUaXuB~?k6$V4lUXl-{;SB zJNT?Dy2^xMj`iD{pCe2b5;t@-vHcLY2^7-+SgHg>%#7w$~+JL<#Nic z$4O;cbMGIO#}c#)-kgp&?2(t0qNlrUOv}rGUH^i;5GQw6zQMUXm|OXXNxoJbfEh{37e`*W!0B*(~Q z!EHCb_}}+ikdgI|x$; z%A4OZ)kQJg_V@fe34b#189dJW>UfsYW}9ZPMK!rEo_2gR#cWBh*!wHrMDlvdgy;1d zkCD`CC0A_O8$ZE?PCVBc0LB1_pOCqN=kL+*BE>v zW8Q^f} z`x}1cbvj?GIlWU3mc$Ob9uAbXOfecP;>@-eJzW~**fxib8>GYsUcTMG!&FOwSE@>q z``E?$bj7fEo!4US3E7R8t6t6-rb?)ti)*`^FTHn>O|Oe%SZv5uuhuubSWUa zG)%~EuV`Di(t)Y6>#KOUoNVxcGnX4`?!?73E2Wp@`(13%B|Txcj|nTvYHU8nStFFv zc-@&<0lm_B?5WUdQoeBi;C82MWhZYPGi`?yaWm4u3E`~$`g2aM7g~+@-lr}usZ?dK zSvo_hXG)ScNkd}3gqdsW_7igRSHDMzqbmBX{R2xHeK=fsB(RD;D) zN3QFcQwz6R%t$4h@JiXs>c-wxj*8vq97^TSwa@F0&eT|b=oGM+zJ*GWbjW+@kmtbN zeQ^4kk$9WxIsa*OrEQ803T_0!t|xQbekVMP`xGc^UD02dpKm^>M~l7Ac}#AG*D+uC z=tK19v6<}X4Bcu;_M=ip)X@5#`$o&z87Gv{uRl!{s2XTE8DQ<7y_(}~p&M0OM!h%h z%Ij5nsgAxB+46+jugr5>B{RRYp?Xwm@}b+UN0odcb@?Y+=0`a@Zdyf)r;tLN^rYvA zBkK4pjn?yhb;v_cc8mEBO0P5~yN_)?K=$amVU~Hg#ZYx>^Zqzm=o25+lw+M!yNhbW zg>#w-^7X}xAN)_1N}jo7INW5vKDDNIKu09$>fA)LmqXX50`1)HwteS{V?$(a2BZ7> zK1M8DQj_2`4qA;hN(ks%4zcJ=r_h zF~Kn@%|d%E5)ymf@JEYrCL+ocln0Wq%HN zUs^d=<<)+jm$xTKD`o2F&5;&6Y*!F}EanRTgWZo0B|2+eyuY^|N0^TIE`6X(T@hK> zaH_DhG#`W?ShU~f>;%8^eug3qalRuny4 zdV2-YcPVcF#N;={{KUaZ@3u`9y=_$m(VpKgaSh(6Z!=UbYL1YL(4Tz!=*bqHM)Ll2 zr;kl8Dng5x+V`bDpIF%@6Hds>z4;g`uv_%h?Kq#2M<=Sqnanuv`>#V)`*VtrjX`d$ z63tj%8T)ygbh}UI&#IdggxSXIl)B*Ez1h2yt$D7t@?7ulg*?rFc=c*x5PW4vZ@f}-)ebU^=gXN?2^j*d-Hfntf`ijWQl{l1GeCs)i z)bZwVK=;xM<%P{Io!KXDos--uh1zv2rdFA9s&_wX@%tL1deo0iFjiTpSQO*2S)k=x zqu!^VypL4 z#pJHUVZQDQqGs7lD#>LZvLgB z@3KZt3l0UNh$}^^A3RqcUOsYJ}Zp5$Z0O|=jE;C-~01yx}s-<2lvmSEiWnvc1}V@Exp>zQ|;Nj1_}0}D#0`P z4@O7)L#4jq0;!e`^*f(9f2!A(@$kZ_hL#*xlv&c~j_rJ8wS{oMxPcwLyM(8T`tC+pBwaBK}JtP5=eV<*a$_!@6;C%@-_CqN>ghQh>~`Z0 z-$55a_oC*s?#-VPVi(V)K8z4o&%sJ)K?@E=dP7WM&WP@`h%A%9vP!Z@8k>>JzH2yJ zF&Vy_W_A9!o@w5}5~7DkiAPDC*hNBF-uNtjyN6NBp1s$9lV(@(ADyaB5no-(GwvBH z7Dp+ibEBpCDK}j%T2}cO)HG@zT)8!$`f$zua9qM%b`hWTH_j^uZM#Hc@0zLWX9>d<0)IaUOk0@rN;JLE$(`4}8p2j-Ir2Kehl0$169yAO<6`Xsx`t4h5L_6^8 z$Jq$`1iYh_PxPy0k$=;M)I z6BMcEcl%!M)9SL%m2+nzFDf5ET?ji<7+iSKBRNQX{PgZKS&h|h@dw=pVz@Q5wI5n# z@;=I+_K-6q>GSC0vf>->Rd0P$fFqU8$B=o|x(OBh>rrz4>pQ&3OiY**jl?!(hvJtI;lxCk7ux6e4{IG!FzK3>H;X<_TH7rAl_V}(byV#Ih`wBWj-UnFwbbPv-sW7)sT|3dprR*7T#%`7jts9#~qB!Nfzg?4BGO( zNVu<9@3Ec8%jkQDgD+>u;At0``F#fr5?iYrU5;9pei&9%=&V`Z*;y?=o3nCjU+4h8 zn`2i*wzBaRJ=y8O5?B3@W-+vCnp=m$=j2y+B6&}oxTtNv!_+ zmKsC*KyjgmPEJlCO|gBai$<$*vfYX+XC(zpYZV`#`i6k{&?w}F-LHI+SS*jmTMtl z?_>0a=}kY67Vg;+Al2Pil^mj>>?f#L#ugJpQh0v$sel7s#4fLoUV(SNzZ0RHr>{`c zgylWey*aJGGp4DSFSpAzfcKri;lqig%Ln#MG`g{98>=18;eENe!2H3J@cZ9)aorU>>ic^7^iwncA?rN#I0wCR0&2fh z!+sw~6x>#s1itR1{3llQ?0JL(GtBe=%GzD zO%hT%K8y{^_bX8AQS;^vxW6fzQo`SNq($G7BOr_fG4mB=Z&rgKU6+eHNc0U-6EMYUMF5p`!epDFs zY(Cv;;vkQ_s)3z%Mbdr4mVS>IH=e82KPo%K`7FPGyg<{R@G4y1x5K&rnzJF@!cx{G zmw|G1o7^#OyJYJdidtRgt+uR`Ig0+M-EG}EQ|1^MzQ@X>veTuEI(*HnPkFTbyls(* z;lSzF#Z&hA<@`#@=svXQP=Na%sW*K?d8cCgPp2D)oEXT=ar0aWAQW=4mKB@27lBeFn&GA?->g|IpQiCL?1&>cD8%N2? zh-m)g9*4b^p5l^F#9$sb^^Uoo(Zbn4{Uk$vg+Li@Gec0G>Ua}U@bg+%+Rm^k08 zJ5F_Z5GdkRUYg!*mL-*~YLSDqlne}*J{ntGbf!n4K3$SGX^q_~|~$^JZWRU+dMM zI#}_p2{Spi`T9sNBN4e@n}@dKoDI+B#z%4Je{iSrf zv`6p}smVJ8$l8C=~QG=dONAdK%f&d&>md z75l5uUs1A3D1iE5Iw$Cwtc7T!r>I{^R1(5N5v5XERqrRUZNzfCMLO<8v*uA z`cqE@I(jq&l@4VaXw0oDT?kiBZ>^i*zMyvKco!l&BF45*sHEDo;E23Io-n6;$nC}` zLqR-(P3XFHKx}WF!+_&{(MIO0LxXncDYxJ=nR~eirP7LR5!nu&6&TEg$D0WF`N_Gg zEuXEYBdktT6ypcezxmw1=F6;y6Mpa;X68gEQk)C;);er*4pCDn;0w*L zIb#MygaLdTo=8oBaKJVdwt)cV4bkyTD4IfoqSF8dUu}*CmZi}Q8UQjBO#l{w1YikE zz#9NC1YiVFfq5-3egWkHvsfI!NgywSTtjPaT5Xfui?+s`7aB}i> zbn^!`rgmBwEHD_g$6!Mttg8jq%K{q!_X1e;v!OSP`g!^I1rY2!5Sm+njf)?}$%o|N zMRW4-BiJ~&`G6%f7q0*k;^0T~qPP*90_=QjJV>sL+JtAp*LvqBk}=9lPue;!32gtO z(No|8ekZgZQQ`c1tTKyy>6>G5bNKpt`?H8WibAD{2U043?{mnkQ{ZfMi^a-+wY_ZH z;TIOA($IVLeWal7Xn?3AGJCdqtZ!}T-R$FOg;5UEy9InBpBF{LoY3!Q&V8?0{`DM5 zi!1Wf*lTb8b3OZON`WHocoMJK+ux2K+H21}ed!V7aqDaH?K|x~JFC=ws#bs4t+zak zmMdg4?;n2t_Q=HS_wA=Q5rZ4M9Tn9-A70mRIIDEi)*n#^L`}62r+3cIfN#d1EZS}jKGP^0%Ae=p6%t2t@r$zY2uiSX3y9gL zGBWLH8JIME9eooW17HhAr;!PNO=B=>273B>+IoiIb`FezfrX)wg|R-y$uUqJ0+t!z z&Ke9cBOaFu%q(GZhz;{e*p36Eie;!mtm|O@+GW9p1Ao10sZ?OSkWN+qd&k4ZO*I%` zK#pP1@QJ{T;NP2NfEh6rmczwoSy8YJ6rBjniGdx$ zhKbmQ$<}{b^^Xk~t7Wi(7^{WAu7FAa);*XFyPy9Af&Dsc2Lw#WaH+ry_uqAHXYb(X z8P^fdGtZSpE(BoDJ`PjZdO6L2h70p$j$x3Zx4gvg$I36p}8m z41%|^*u>gs+fZy6Ha0f&^o)Q&V86amCCkczwI$$E<7jXR>jE8IW^5b~$QJ^#LCT17 zU|{J6+kGN|g%*iQXQo9!9Go(|u(?x2giq%mpRV6NcYpbGule--^y&E#-uWlI>v#Cw zU*X+r;e9{DL5%*NpWz07zK0wB`4(>U=SR5lpReI2f4+p9f_O6!*57P=_crWyv+kOL z+o5<-?OCO6k^N)hvQn9&X^QS;9anBo?8!beapk?)71!19u3&Sie)QFkLLWn` ze55Yb=Gc@=W+#o0M9H4FN1|#f8#u<=X~|BA@Lb`NmN(w*yY-b{x2})e-N73~+q3Nx zGqRoDd`NurpXQfY#=^bWv+OUb4yur!GCx*z4!VCl(Mhg)GlTUp%XevCzA{o$+;hBB zfOxDi{ZTcqaw<|Yl&1AwJNHc;wIPq`KD=hv_TpSq#FYS{-0{L6Y3E;&mi+y!D+LW& zwUc`E>unU)D*IGXO>g*@+k1C~-s#$3Z?(!Z)q_3DeZZyc>=)9ZznySiul?XEh8J$Iq?yz4;T3)X%R~#4NGYfc$zf>H^;3n3$q+8zNPDq=* zxagvDzbkvQagOM2EqXZt_0h9>?#^k1p8ahPl5~C9;qU#)#U5RH?Sbqyew1EG|K(As zx$*(QbHpHJ_9LSjn3OHMjrl)cAGl?Zd@4b(uYd5mcxSCtzs_m+uiS1j!iU|zcbQk#{9%#ZjC;eFH)95$?(^VSc+K^e(N&sG{I8bf$fcb9%otq> z2O9oN2L1d>wP;3P-hw$nniJVuq9%`5`nld-`o1maSaDD+;>ACRA)dOW&g{6oe7b!nH+jxRT967+_+752KyzSH-1;JGjI z{b*;av=NeVkrgrKNs-Ch!KU;jeM0SkaS^A8Mex8E1zZa-n^$tQTMJ5J8ws=f8Y z_ThV;8as)G9pD6POM#tjfIn>Q?d!(MW9RAb1ww&NEEEvv;p`a*Ikdc@8b+Y zTim=ITtR(4toHhD0qh-=8Omy>fUtt_FLAVlkc6xRO0q-hxXgJOOIb%*wDO9w5!MB} z2V73DqQaqSq`F5Ht+t|uR+m%PQSVeoYpiIeq|G(kKHKNE zZ)|aP+r8W)9z?iB-j5uJl8k0X>%`Q?<`9k(`Utax$aoZ`pRz*XO!|?Yn@#M3P&8B- zx(zMJF2?S`9>qS&{)SzT!=0m!qlsglW0k{>%ayB>`yRIuzXiVwzc+s?{|){={>S_& z0y_n=1o8w*1r7@w5x6Z7BeX7bO`=WWzQmA(iHwCzq6|Z(L+*hb4@Ll^fziPvU}%_r z%rZtpPgjqig3zK4wzxy#3<5+}wvYFt<^d&mkc(#aud zYggs;=ISnI7X|EQ7pzlvfCyTJeSni)K%|-C=01RC7ogqX{OUe{Yl#zcg`G;RQ$wQS zu%=X&W1IWn=DHaj2-lYUo~6pCt$-%2kR4t)<29wyDqvwtCOHjQg%jukR;(5(NTBOp z!CT{qZh0^4QsTt*MwRoe1td_ht)M8wDp+x&EO~7wPGHRAAc!Ju%n4EfzL7XFjR^qH zieFX|l<;hCxD^Q{Vu7?Or+OSj_Njyqe(KWt{{9#$Q^wpLB$sRv%dvRQB_q{V38b|N z-h`&K`NfpZ>9ED0f|9TS;n9lij(m1UDcnnzmBNKgDY3_#sJY&eSy2)bZk*U{sF5bl zg*Q3tUzG#@hyIuo3GdY>U!$ElHEjDYed>+RzxgfXJHT{nfcch~(Ztovz!45?CI;?1 z0t^3}4`4CzWk2$wWwYHpa_q(LeDS+Zo?m<8J6@=_R@-ZZt(~U>t{?^yj(W!vFEZI` zwY(11VPs}itQBBNNdMl<$#jD$M{FgEskz`%*M!9?ju!asVVcq~yno~Yhqn)jOeiNu!J zY7u(^wQ|_=jhGKOy(<0HKVzhG(f`gcVW$`AQ;}oUas)htu~Q(8lT`HGNQg62BLaBC_Po*3j*T1Vv42QpT&)+Ayzn8xB_*nWKpZ3|;DNjNIqmdw<2i7}{BFrqL%Ke>R6 z@z`Ty=Eoj?e9XN6vB%7d9)H}NC$nQ@dJlGx&Jwvv+%?Q1C7vHM6R#aJC(n+VBg13n z!Q`09oEtN5OO2VYPjOKC4P$2Y+&S~|vuDlltIfz`=Dx=b@q^EsdtYl#oHZ{QHbY4> zf6lx(Wm0c2$KPUJdfp5?VUDKFYtEQU6ke1ZW8MkuV5p%%u^4GBVYmRDu!?UPpOfdLVT zfxCfmvLEs?YDvTQwy`2W(psTXhY>k)qFB}4^9jYP&Ve~^4qKKF3^~|N8A{NDrfN+N!87nTb~0s5ch=K> zddr+ljyyE7mjg>bsjM#^hsO~aEbW&dM-M; z`LA3z2C(h{;r}+*=U|7f0Py7(8S`}{I6-#bJZ{XNAl`oKpTQX}445zc`2q7!?;bRN z{NZEfZyz{r{@XiWWPUaGiKhJCPcggyG-H1BA8weB41THE{JY;VSATeYaQrvlIr#f8 z`OCo{fBSdd`})^?-b?;A{TnaMe&PN1|L(h|r@qwxv6(Ob>fh~r;RC<+zTA!R#oXd} zW(tY8+Q2@5oAmqiT(zC)Z>y03ldqTCVgjMw@H=9{Kz{7I{Hk#eOn!=u4>kBn57K+V z{;I_Qa@0F<_5mXf!K271h=7AKTWg)PgWaa7Ht^?Yk-riB{#`cu0jp-G#%*(*!GYfoJx7gp|d*d zxR6q#>`UKhW2!8wJPJV_T%3YQVI(uB)QWyZzY!B&1RRTkTAIFj3Qz(J1onvoD{o=} zS!}#nYi|H~!QW~53tqbSckCH3tfE?eUBtNliG}37e->au|HP8^-am=&eyGor`^x{Z z8z>NdBYZ}9OZV?Xh!XPmnkV&UZrS^jUtsU=_;GuG_8;~B!lw_78~%RjJg^;=*5oxk$ck6rxcZ~65H{~`Ox*f;QrPKHP zOhS6zVHET-^YPfy7F&U0HSiO`<0r$f|CRX^gXL-CnOB>W$YHNRB6}@1O2qi!S;VyS zNNY^Bu_1c_eaA&?S6nt%uwL@8c?5awQH&anVb<^o^CWihSe(GZ5(an7Iu>>-=2`6K zR!t54NW(O-ZPLOHZyO6ITgYTP*qDC~`$JEgXUrS0fAYqEQTjI_puE|<1*_XHV8#1w z*aZJ{^LBJGpK0D)omzQDW_Ybsx4zSw+;`BL;WUv9p_e5Ls+^KZ;o zo3Fvf%Ga8AnXfZnk45osFyCmt$$Yc<7W1v<+swC{@4))Xzc>E@3oQT9e5ZN0`7SK6 ze2@8F^L^$&;Wp|A%zMlanjgY4%a33~{Kv31_!H(Q%}<%1Mi2C}*lPKC^9$y^<`>QT zu-fv==2y(GnqM=&j{TP3G{0qj8+S6lYktrCzWD?5huCxZWAlEjng1zvUH;7cx%mt8 zm*%g`Uz`78{>FU3e9(LdYcGGtc>4F|!{#5b`|^+GBj&%Ge=`3A<5d3>TV(w0Sufc; zwMOzkcp~3lC15A={o~)n1maU)c8K3!%&-(1o`P|R@{4aRt7k<$ff614A z*_VICSANyM`RcFvzrOZeU-$L@_8Y$Oo4)y5zV+L_{X72MzyA;a_kaA(cYoJ+f6w=R z-+%i4A9&9X{?HHq$dCTmkN?C^{?t$Z%+LPZ&;P=EfAM|4^vl2UtH1W^zww*D_1nMm zyTAAQfAEKY^vCc2lRy2>fA;5p@t1$~*Z<{jKJdX0{q5iV*T4VpKm50U{K$X*r~mQK z|MR1-0tJ|5gO&{x-FxpB_9=Vdf^>24wE+ZYuB#Y(vomhy2`w=Z#8^{8C=|PqX|J$~ zH6w;<6TtHcEfa#Z5seuW7U<7FM+R!JGSbV)cZ6%6OaA2hk8$1R+U5ERuJ7Ucb*{hX z`gq_FmCORyFCc)um+Kd~-p%!0T;I+0JzU?*^?h9biR=5het_#eTtCS5LtH=1^&?zA z%JpMhKhE_NTtCV6Q(QmI^)p;Q%k^_yKhO0?Tz|~+ zS6qM1^pJzOsMJTDp}ed@|9f!rd^EmK>_MeWhQ^pr90 z`V0(7V}t&MFQe5(2*&38|eL4Q&lc&QnXGKqX8xD(lGkW0!O z$Xq=3{N2+oHfx<7Gtf310Kjtbz2QU0+>7P4qFB~D(H=aCHOkGSvMkmO?LBR zUwhz~==c14ONCt(rC;18qu`lL5z<9tVm^*9-H`>imytwm?;ojQJ^16>#@+!HLy4HZ zG%s%t-h&x1(%s|ZSD;w##&q_?9A9fUQ=%F$uOK5{%q!(i#;@!Q9OaH(O_uIHfk3@? z%suTgMvB|!e#+z5NbpJRfuqdtszNt6^kP$gz$E~pa;I?}2(&8g17aa3$twuBfb zv*6||S;;GALK_v|oNEu;^Q}=lc{pAuwy@+_E0_&vvQ)wLXe6i;1QmU1nZjOmg$ftRr0yT@hIN9l zdl^oYvNq`f;WL$QHgND#YY!&GWH~1Cu+Ddku+*rF;X~o;MN_9J@_JEXd3CWDsbIa; z#Mn91Am%h{1+o7ehC&V9(4)+gH_V;(k(bB=s!*(M%J6rjU1%Ot1@ci}+Lxu}6P-@6 ziA_M@SzkX|uM@o89)!FLC6polQM4S*BNF;18dvWS1?C5(qrMfQ2p;Lb=-g6%Ys-8l zRls0mq1g?g78;TOm8+G8FX;R%C_ehyG4})WD^I~IoIqZW`gIoLzfStSK6K0pc}U?8scF6*N|85ti3ZctgW%)ETBS*Ut($+_ zHjx+lvBsb?#;W5tP^;)GrIIdw$Nc+t_(a%Fsa9;7|45j7>KHXS%+8Ib`A!;OzI<~z z#|sZTZG8}n#5TGU6MbZLy=mS}8|j_g(05`n8>_iLOli9>blys}^g?E~S;bYvYUN_rRPqDo>Q4S=bg9JaCH= zgwK+*hCT(XdjfW?(ALn~z=qGz7M*LTT74@NGUR1-OLc?#YwHXcuez3haK++W8g?}z-^no_3_=U|{bKvi3v)~ap zEQU4*&jM#3prQI5e-K`4@AQCrlb!?vC{zbm+XF8t-SJuG&EKivjjP=1iS6u-J+5ij zJC(s=d*DSbrReQSk(kb&n2j3WL#sAeY7e~BrNOAGtOZu9$Gfqe{jpF|b8uTJiaWKF zZw)fzJ-Uij+d(57y;1WE?PKiVsniDt0A)ZQ#5U(q?xkb?2HzMQY!4hM)=DA?0XH}( zWGGg|%dNp9jC6jp(Wr_DQK)VX9;3}z9OLO8o-h~OE)O0@meD7ShD$){m;N3@si@|r(*o^h|W=I3o~j_`O)#u$I_B02f;7`!t?=zD@4lg^jg z;5BlNzJfgI75?D!kiL7O*qEU%4t@a*XdejiE7js4JkCAP8A7R|P^u074Sj#RjGHIW z_|MU2X&uoIAHl|L@I?P+u=G{TJo5YGDQ`#qfMj;S_mBKh^qDM#G5JUSm@M2AC4$-d zN8V3r`v8=T@BWcL0m?lQCj0IDqYo42o@gp~H!e($PSFa%qZAWiu5=W!EO>(cWJzPI zSwH%1lqY-^)>dO1-nw{P**ywMd*8`xv+!J@aP)`B%RTW`41{9}`RH%+)!-3CR2!^) zVyC@)Yz8?beDk9b&~G>5c+F4wcQ8YK>?;|Dx-Za(d#N4!s%{J~FcYLn#A{i?I|d`_ zd8IbNSeB|ckA0Zh^t=-<(}5atX{G4jQ=^m^m`=5Dt<~{+qbO%2$}gm9{(4GAfP0X^ z?sHKEoaEfs6W8g9y9c_eRoeG3VuX*d$Li?XJ>N)Ytd1f*=?lz5Uhc6axtHlm_$V!; z~75=B@IL$Sc^ZHR=iGXZB9tK{RhCn4q`^Le`sp>Ap`R z#6BoP^Yf+E`~C{Nu9xg1rL7d3Tca;Z!zp6h@P@SR*+Yvq@Jc5o-1UunMlCxScJZ7t$NsiH)_*|B5f|rnMn9Z4lc{YeS9~*YKvtg7qs9Ln1G_)AU=49dnh~(XCFYGjJyOXnb#xrJn+UKW$+%vw`y%fum@mO_RGOLxL;!@ zlCnjn+z-45wC=3=dji2JfeBFAp%q#Deem<(N6}YCJ@>j+dhqiR*CTJ;IKT8D0!R=i zZ*Y%-EFKq5QS|VU-n_BdJikdV);ru}wb?3N{tCE>eSp$do2Av-Wd_XPiMp;fpDk?3 z7`0Wr%z)YZPMR&GyVB*aCXIX2oQtK)zo9wH10~vOG}*m>`8O$1@Ce*?y?*5e1B82^ zR)Ms1Y48J`!TW-@RAuYPW~msBZSRZyxBxnDh5x}1LgV|wpd`Cp-${mpAA%B4|Ku6X zn}dJX9y}qsAbmTwAz|`vn||;g8CW+FXzty#Sqy$e0#HO8^|ADSZQ1n?6@=ZtS*1L2>*F9Lc>FtL@_tQDOJGQ9J%HjJ0ef-{X(8&EV$F@h8ZrB851f zB_lLVy2jnwIE}<@E&Wt)A_eo{AFnmo zc)$pD5HxIkrRBx1yJcD_etVrp;kJAO7&O+(XMsmG@2=WDg^;dVr;;@MNVZf zojLNCG6VakZ7 zBoEuiPRf8|9rqmj2%&zZyj8yUm*fjp6?pHjlBiy4H}Cx&9@w?BBd9xGcP=_m+eTk# z`sd24_|9u>B~Fu_z9i0&5+^XF#9647hx&RcagJEj8f&G*d16s@loBaoCFn{iF+>66 zvCym}hJnO;kY7qLc*9ocwVR#hec#dZLcJ#*J_pS!+&Bag@43CyYzBq>GoaR-SE!Xc(hq; zm0ls!D!dgUy1fD+Bz&Z4L}iH#^oqZhF9y$)r-fIw-B-T5`y?1@wwtf~E;_M&Af%2K z{}T`=j@DZ3(kBS=z>{C8eS#p5%~kcnCxDU@;ww@`k5Bq0(f9LqOnyo-K`DLmec%cI zC%B+)H(y0ZI?i+n4faO)RqrH2_BA$kc3<^{g6|qzU|OrMf`N6PJLaXhY)pw~rV{fe zCWG|{|264$5Dwa<2R|E>2y4WR7TTKnYrX(6$-b|)8ttR<-Q>@b-=<@r@b>Prw3+hN zN@?d5eT+Ar&}^1Z6{(7I*)(nOUqKuvX;YaT>)pJ|P))y7U~9*PW}2xB|XW;0L29x3?EXFm|! zDLsQsQStW&-$DwUjFlRH{W6+MA6_m?X6()R*#5d}$}XMVwcS6H!{Ym={C_1T*rv)k zPFYgZzu@j(HGFTF#KnaLY5Lvc(!_=JOaK2wxPI>iT|CsqXW17ji+QrfCkuPBcTXxO z>wGV8vE<5b4x`R+J?^sSCRq1l0rG$IkDMek_xJyWeJkU5J-he4M`~+@^$I?%)}J%tb~o5j=yzD$+woGK^|gnqHJlkT>6ODL zqLlK)!C`kBGs;J1`-SRxj}>$;wI=(A*^E$>UCXApwpD85rcG{mbi?`XsC@~sedjrG z`a2|Xs&x*%GIC10=cF&b{P3@+JCoT}8lL(cd5C`(k|Ph_{8+9L_m}jOMLy5j0Nf(C zM><=j+U#_?F_SjxQCM_$90t(h-wBJ1k4Aq8q-k&%nwiF>9b5GUr|uX6?&-?vn$De2 zRtLr+bn9MkJi+3F%o7J-o&>6=Hhp4mwQlucUr+c%SWhe9IId7CxAL}a!BsEz_Po-X zL3-IgB>VEoyf+CjvU#*tc}`bZ1E7t{`bJM;X@1E}vhY~grvicyl>c&*H|x4jecWw9 z3b-p?bGzSVjRIAJ-LUR<$Rkd&MYd&eV5=iuN@eeRVOMsx$Y%L)+qs=_;|s0Q#KB-OQx*jr z^g#XP*)0K*g+0|Cc2fxoh)Z_ryBa;}`I{^i$#(^X8R{0^3=WQD>P}3`|}Ogm!w~_4cblAAPBVLtX~O#5Fo0u?t2&5U|sSarqX5Q zPa(8PKGLCVBcq*E_@l3BdFAU;>GHWKF&qtUo zqttQz!-FIp8@DBsqaH#MWT;&u4S>ZUEW6pL!;^0(i_g$B4)KEVy?-t$k$j{oDB1g$ z>?mP{h*BCYd#o*3f`frZFc<`zr1OPK6?Ly7MTLIZr{+^$PfzIyFSKZNIXI&YNniHY zSh^=0h7`WRzA6}^Qe#cF)PsEq_IGjpsi7{hxB{05cA9V`WxY-hbOqIZmRZUK^sasv z?Te5T{u=i<?$<>)2t-(ifYD_gbWgk@Zm z+R}zFF+2K4LoBElj9M_+7Wx3XK)^vf2XQJ{JVpJ~+=eGel}?!UMs_$&I6O2oY=j~? zbp#_gH8gYz_vWnj%9^rlS=AmEd{zbtR}$Je*%^k`lnRrVVmqwuwKT4mdR!Y{&R5BB z*1zpbo+~7aD0(!`HzkKLP?bt$)7ccbU-Hu((3j4p z)01hl{M6XWa%LnVum=pOj2r>?G09u0WG$5}Er%w5k_BrBXca?1UJ&X*5?+!Z7>KhC z^bfI)D=`cGnEDX1S!`#hOZ6aMuO>CwoQkylixmc)7q&I39KFDQn&fdyr z7MAegy=;_k=U{j8lod88vUSRyJvE$4Pnt}jStwTM4AbxscQjd(=}$6s;j#~0$s6CI zPsv#?$kv&^yKJ>+@-70pMC1aPx4|X znIuDS;NR3g(@7y|(7+w>x18i;J&_w!GQFAFs8Q#Q&GbxaHa(k~q0b1UpDvvblRM&bkYVhJK}0MS!EIta4~5mra3~$-l;d7V&k;-sx?m3 zA<+h%AwdTzczCBqj1Puh@%+pLNJM8&X^H?W3+#fPN15eFSTI+Tj=&k@GRyYJBF=4>Xk4Lk6_+wJ8ht% zGvhroUI&-ytMbF^Re8NCuj}d76P@*|>AL)yR$YEMX*g!Qb^R^d7q(YO7@^_} z+#hq@hz;N_#K5_b9-LOYi?}Kfm4S%93jPrnn5W66tnTL-E=u0~ z!ZIHfH{G<9Cw;D##szs~FtaR;;c6{aNmrP^tyS>!o%Uq2lsz3Rz3GXr6sse?@5NgI;W~5FGwZS!xUQ2P7$xO)a$j&{xWSQO_grXr9xoy1 z>W%Oo9vf~L0S63oz9gW16cm6(DkM`s@jTCK|L%h$=~Koe21ak!mNQLA1rPm`kyt&z8LDR#}n&!b>;`6Y^{+ zVTbfSDTwEzB5E=R!U!ixuppIhYxX zvWFH+rY=`I#Fd5Mnl({BUA~UzD_!9sBE@zBr-+&k*(&CD_~IXoq{~iS$bi->|(LPQ6vexFB2a zum{k<7C~**>|jHYPPglCUD97vyI3Oa0J2jlZ~}w}R+jl~l`E{#^H9X+}1D6n!2e2|8VZv|5dA2($AjV_3CQtLw7?!|BMCtTPwe;Wr#pK?zN`Z$vez z>2P=phh6R9jAv}xk@NW_PiBcJnZc{z>&76Tvp%p8Q7qLu?G783#5!fM%J7W3P$qsd z)!9|iKqfVaN;>r0*^Q3Fw91j-1+IhT4>8bjr^5`7(Hdo&SaLvnv$w`l zU-OtE>T&70V-Uup(suF$vSiD(eMBw+wdc~)jNL_yZ`{H9#x(7yUBox5WyBMwwJI4I zdDWr=S#BT~lPT(oYPGQ~vI~Q<$P=P!(*EUuR++2tHD;tr>J_mJLBmV!_%t<^M6Cj6 zs#G)X#+nfQ!NkIJ71+zNZfq=8S~6D-Ir%H|3LSkh{9?`agF0o=Q2g+ zues$VWS~)xp+^u*lPIsD=56G9(F3@|=IZ>)Fg=>XB2wP9b7`=Jv{x*3)-Y9qV4YO9 z{=@}?e7lNhTu(7AC||kc**8zHc}gQr>6{nKyCox&Uj&z62+~yx#aik@`U$$3ahcdW zKxI;uTZu9L&^){`K_&@P-7d~bv0$+%FgcZ5OPkW2b~7zqYRFBVmgm%_?Jz;ZW^|N+ zm~k*|T7`5c-L8TtkjX5*WHmADPGvSnTdN6B+s&Yv$p4byHd)c;1JIcmE~~v^EV^tP z_5pET%1x0OW_qW{SbG~^S~g3wQ}b7`>6<*e<5XU@_ecYD)w09%)M3Akv}bLX@(9I* z&*(DERvKk}+DxanxZhxkQ7a8uJcm=d9u=Q6eQ_#v1H_#Qr(}g~79a%oUDb=7{Q{-k zo*O)t!v~3d;nM5%q!~xgsfxrP z1-f*1v=wP9NXQBYy?C3xt;)PIG&arX>(UnFuBMf=hetvaW^6P)n@+DV4WbmY>3MAT z<2$iOp7N4vC%LLoh;FjRPh;6exM>LBdLJrXR+WV)zU#lK4yhUX-%3ByO*2P7)6VymMaItpP)GUxO#2_^ao;dz916>C~D_QdIeo$NMZ z?A>ORww4Pu8y0PutjlcF=3&yS?PXJ%T)(<8Q?1W87w_zhz3I)MAndv_sg%4RZUf?B zois0;Fen6Pu*xX51t?_OE{TAJD|t{V$RKCH8Ng(Xz873q3 zJ6nEnx-zpNWtwGdPmiZ3(wX#BA!|;vdKfVbeZ~^Bj7i=TOr=0)x`$=URy!;Vjb6U| zXz%J_1Z7mgSMz_u+t0OIVrGkCP2mF3=o!Xz^Rg-HX z5z#RXMlD0V%`MV7U?F-U-UPa7v1KKF0#k3Bw7U$}RjOLU_BDIfMC4(68MYRO;H>af z&Z9Lwb_ZL5U^^vX{Jm-dn=3<}58yE$^O3jIU$x@OqV@y}sE<2xT`= zg14}rHj6BY`nu$az}51uF3xU^4kdDBx|p7thr5a{ixt6O(un#8BZLi(DvJ>`SA17u z@Ag`!UKG%0yxRe8{by)+nOQb4gEzzCIh=j_aAvP=uJ~+#CSXQgI z83>&fyzm>MkUO7X2N|mJKmbHvDXcqq6@rVrsuq*cp&QRUMBYW$sJFfvEmwDC=klZV zu@4M$vPhz-fCL!gK+x{Htt7Xge;6Os0{TQU0Nw4un$Ug}ZyONG0nw`ojh?83%Yxo-L~S zc+$KWEplmGelli{gN}0#^e05pm}@7juc`@5H7Fk9VU0sOGLp=t24otwRT4>pm7hSh+LwgYqGXyu9 zGnVckL%fg$J|v6 z$~-7eJ^=I+%$CrYsG;UOU0Zs|>A3||?+f!;1}C=%iNImJ#W1M#PJ{Q7QhP) zj&^$f6LM*9NG^NT&@VT!!BLa_Lr{g|FEY`9h=+#c*G<#|?XLq?Wc5i{(u5_K5adXo zqe*0GOhr)JI1&_yh7R|#?iqUNXw>VnivolTZs8MhRKQWN7?YG3-Ke%^_t#kJ=%82N z?6;ZC&QIkqCqKI~H=i@PsacuN2h&WcC?m8CZ*&@35Btz=>jz_fsogLl@i3#6@3>FO z47Z1Q+7&HX*^E#GWumsl4d_7YLRVzyksir_WH>`s-aL(h^o)H}4TspIM$`|!gOwLl zmvmOkRfY069Kv2AR}ROF#fq*A5zCxfGQo&qGUx{yqq43BLu^GHh=^Fkvc2WzT7BRp zPg%i|NXQ{*%`6@_v| zn4TJ6URj#TPpnK&Pc7y0l4fpvc6K2XE$CjTs|)#s`8?{2%(ZBqVZ~zLv-A0hTrLXj zN|2jbxWQ+~uTJsBJ*B!nwKTCniTXqfc9y1cQfixgUjef76mphrKhY0|P}Fi9)Z|tc z1x-?kB0N?!`X%TtNDe+4IlT+7;iKYrm z8Xz|FM#cud`xT3TA@>5r~#^9y;K9$ZCISxXfI~$NL$~VTtVagj<5k=WfkGqt|-6W02H=fa*zwi7mh$;9O=YySSXcfhU+n z*y-IQnOvBU?><4+c!cXM?SZ*=p@V|oC3tVqqlp~q0%GZLkhQuRlFTAp^2Wl_WPUC? zk4k&&N`UjZ$;4d4|Ghy9aSo%bEQA)G}FL>p`e1 zRtPqk#UGB0ukjHKYd7;!t_vfhm-@k6&-PD0lg0hc(yg)4%U8O6Vb9m|IYxU27=yw9 znju*`Av`a;FdtWG#^I&;amF0!s}}5l{HAQ(^V8$=89W3ok!CqA*8pxjcP%e|hO+a$ zjAjq!<{9L5&s;te+cLrMoLS7z(dQY14=7`1VeuAHM*iBwScv{myr(1P7>j4S*v~Fx zmS^)bQ#VIhpvo)Hh^x`ejqF79qal+DP@S6^pPLmKVfLxH@hIe;x`uEQPmOjz3t?Htd)QqV9ArMegzrY=0vWWW&Eu$iVr8Dw1Cf$V^uA^mvkUu+Eunb{ z-}g<8i5DX#7q9iwnhG-)u5|&YXxQ#skj#$8y>Uzn0SwzT042Dm#iH#T0#Dss1edWC$mL)+UywoY-Xo4NjqJnCW+OBc zV1G8JWBBqdWqp^5iT(}X;INTQ_@tjInS;}RvN3raxL*6-*6e1(U=Pi7cjx@Iz z9~}skvE@P^xX?opkuqr<3?b+OF*roPx4g>LXzm(aFRo2A;xOu*yEdJjj&!Fv_6J5d z%v@{-n(N$%T%SnXk1yxj!(**IhIl55H=GbuH`rh76Epa3A-|r{iR~Ygf2G%KivthUyL+=$g_-^k==*`D7cv4#k_G1D_w z2r`;k7@v!13U0-*78SyjFoVhIeu^!L z?3?YvBCI#A>@r{I=?4V#(=i4}vLGl#;ONng9hQ?UY17<7ueLml4)W=O^`+7<4X}M{ z9?4H&(81hXM%Rn%)q`V4W`WGH? zeR%HL^3UxOO<0%uYun zjQ}GO+Jiklu?J}ivPW{5ij$v_Jfh{zp^uG}_j)#p(LLX|o(;9ABm1jJ?86h;_>LA- z1Q-!04{kPqZjH~wB9;zbUIY%!+fpW8*%SGsjIee(+C#ki8i@>brIsy^5n&+?Oc?WC z%~l*7eN>kF4$BU(!$5G}&Tw!j%cBaSDwE}xyi6uyms$eU2=l+8OKTB&Vht+t7EIO% zwS07>Pvo3aol7&QGxb zMbdqZrLnA6#`VyiV#!KmpKr?~t54L`rG@B(qbEo9xb#VNP)*>stY+-v16mIulRi<4 zuw#jfN5JG1iw!-pP+WWVPF{NIvNUydN)#;d*^`-!c?Z(ER$$+Xn=1wbP|VCkLi1Dl zJ3gBokCC)AZu(FNSH3RlZXz1SWT(NQwnWP&Qw+P90UQ7IaM~iu>&RA?#QfqX4lW75&n_#=DlCorU|%EnJTsQi7@~7$h`)Yb<7b zkPqc^8RiTJe#?R#zJ#v}3 zUYxsDb1`lULqv*0Ytu6i-j^|R_Q{1Cy1F_UUwoZFPUKNb%vqE?imXVwe^n-z73GfvX}C* z+Hyc<0leMKBbvW>gi{yEF1A2H9uB5&b%WlVOJ^&HkLIuB7gm-R zSK^0(puVw%2r>+SQ1`KQa+VDxvEWF3{R$oAG@8F8+Lskp1EN_3Or^U90#JT==@ugR zc+ZSJ$jG8D&sGju{I%VJ)w*b=A)5E3xyJ6Pg@r{Z_14_PLLXAylSUem4Oeqh@eCsd zdarV%Uuh&~fz3~^%pSaZ&XN`CS!7YwVS&X1>nn&}&awid!sXq8#^A&?PN3GYt*k3X zV<$Nq(&5Q_g_GV5hWj+ZB(#^vOcS?p}4Ne;xhbnP&Wa9HO)^S4uvLT&!(aH+$@cJHO`Iti2}c% z_6M9;Uh3`e{XuP?yIbfz9k744Gk2Tg>+Tlt=G_9$FW)UB`<))Sa%JT1aJn*iFhz&0 zG`rHfW4S+)5QtZ93YFbm2{Q2NyR8~C-n#{5dU9}&4r{iMna;(t?|r1IRm1jfd=FWf zk7d_$3q&A6Tu&U-huu#q4zslF2^7*vc-+_Pl6}E6$SDmWSvQiHphG-a|s&_~p!veyF#T z`RGT&WHt&_Ec(BAfGJk*dRJ>)35E1I>Zwa#VSYi2*hpD@h|l##mIbYSSaCV8C@SMd zb{m6C-y_Jyw%{z&oVYCJWFvpf@v*Q9Zj_D_pC%^kr=s~zu&t#|LTcRh&Eaw)o88p6`J}L(% z3hL)+VqJ#`ktLUtU1pTog3vkp8KlwG><*yLo@A$v0w zBHzOX_qT=Ql2=tS8Z}MTzolg zlxQAAXo|&<1DU>>pYNgNu&xf^Zn(CBM!ynNWa>H^glL(kUbknfefYV6C=~)-WUdeG zPO$TAyx&YyVlwg7frE4As=uJG(d=69rtcc&vPQ`VDU7XVr3qjpoU~=0Iph?$L_E3!oCZJ)0OJSaCWKV&PoFQw z4No+b}jdC4wbzY?1|AR{>}B8$9P&E@3XK=ct3Uh#1cm+53G?w>~FHLh(VPsoLFjz&2DnOkGL?kJOd{B&Lw1i zr%Wz>_?li`>=O}eN?KmzsCBk?&ankzX30zj}xSYym~*B=Th68DCHX3r=6(qtV)jR13)Q zxok$xI`&b}yLPg`0+wgnay)i>Kr>hS2x+}g*1!tWKMpS0gZHwev$S~dgd?mYJ#UW9 zIBFwBHW{$-_%6z3ca`T?mS)+8dN*Ivv&-!JxVxreUVbxv_MDxztn|P#20-pi-Ce@Y zX8Xvt4&Py}NZoc%Z5Hu=5+=9w`n&tYOg!fZ=q~&K9dvv$BVy?y>pro0XR-N^o8_E+ zpI8!JjprNL>6Jyc()5h0Zg>i!^5|+*NYO2B(cRYFqS{Pg@UaDmfx}Qob{69VcM0#> z`D0AQaC4XWA2!Z~xL`H4@8Ghpny943WWj8HvfoSz$#^-wVZzJ=B2cIV_0P)*%7d#G zn~cS*47NM|1t~>V`4=Rc9KZE1Oo>*56DWt!hgPzm$(qB6aq&P=B*Z`GhFP6IxbBOn z+Exx3b2+uYyfQ!EM-GjAZt1YKcXC4RKzSo;z3~honjI@RC~~Zl9KS{8IAnfkL99W5ej9Fj z5Bhd<&md-Ss6QUP^BKu>DSjdcbqnK-ZI_^d9Za4hQwR6Y0B~_Bej^Lx$HKz3K06BM z4->uw;GlZ;<(U$3@D#(I9PFQg%j9sbVDmKRe=@ul6 z!d`mgux=&*ZgSJFPXzT=P?>d#8Wrm;Xjo#u*#m#*2>Mi}kF2$vSQeAhuaF$V>5E6$Ki?-k!3ABodS+ggR*Z<3X!v?0Ji<1<02A?yH<+>3u`DxG&%` zAz``Z=Quglg8+xVMLBlVP0N0BmoZ3bR^6f2ToZ$~P=Zdft zEoOi|q7I#{0E4iMUA+aF*dbDj)!>7h7-OvSD>*sTY|k|GfV+aTi>t>N#{`S$*neA& zAlTXh+(UnI>Nm5vV$Ho`W|EPGmCiWBu>s`O*@X#;;y`T9LDy5i(UxcCt!7;JyRVIQ8vCSRSoCSOg9I?b3?ODB%GktfVI~}Rb1CyCOva$P+&AR)7 zJP-U{LuwNCx&<)}I={TM5aEUrvFBi`1VK@lq|_3yv=QfHF;s zV9DrwKnDF6EcNrCT(oQPOhX}h8!Q$Dvd1MhVy-vbQHjz|*VuQrL96_PBnQQ$Pr>_AV zpBoWZd*ocQl^Ck`m_0TLFw(-e0bc$G-5 zNMy+m%v#!;I`CN6uEOHxuex=FyRv2X0^E@u6CB=&Y~a z&yx>{>*5jp^=)V*7I1N!B+2z5e8jCfE^9O=o6l($XV16*@3eKpRuQ*E$;ui1kaM~| zWAOVGdW2JFN(9vLVQU@r@nT)?IVUw{uF%45g~0?*0c6*PH6}KnBt;^mcZdiU43w@s$XO4nwH>U_4I}Vk%ao_AViuo z>EqZ-TqHFcxI0OhOZfP0;66vPG2&5)8xBbup4l!`0tYFrjyQ`{Kat{ZE8Z;}Wyv^~ zeNlg);-_7l?0C-0oR;}%oC}F3#0`k7hRgBM4$iXV3HLPaC7Co&aJdk3ZcBXlZPpvx zcsf*%%(!czCUX8yJT?U$WpEFPmqTf&AjH8~r%~cbS5k=g+3gnIyMxS}rzjV%CklsF zSDimeabbf;G}lLlHXD1uhVU{eo}J3-o{Ng|1@Kj%pIal5dZH|xzR-4G|| z>*9}C{7U0*wJh%FfwSJi@N_6mW}U7$_blW!jJK6xcieH9cgn+W;PPC2h`X9eH&%jB zUv*}+3KJ0jGe#oR?}~K<;qo$pUHWQeHOSx83*+VK^qp46+`*sn*0y|2d~Ul^Rd80< zvdGX3lUMxYg^T;Hguy{u$*kdO-1zFN38#AE0F}~fifV~u`+gE;u8bSn{U8aG+b-am z)_O9BGKQ0vK#V$(s+Ze}m9sd#PF}fmdnEP9cxt+kT6+dh#vVRm)8Z%AUBPp3Cmern za^a!KY*z5C*R&qqV1Y(`O(oBQ@8BXcaZ(PfIKUB~J!VZj@~(>S)hm~}bZQ+YDq|J@ zH_m~gbYaVFB`|O&D@`cx@?}l2+vvce@K*=BabBKrY1gR9yOfbek)AIe55)zzhJkKN zIMGV%4S|bORcH)H#Ea+5R&{L$7tra&G!BT<#>WeBk_GHZ+{$)LD!sjJmbYn`dGydMVhL=b{8um~GzZkin~BS^7#hjlNtHr-~(9i-TBOu|8X*98BRDiaG%19+Vv9Hz`_e1U=lqDmk5++@HWVDnHf4ol9Gthd;D;0K=K8`PwE?OQ- z9(2irG;X9(t0ft$t4bF89~0sXyME4`E47g>rXU6C+ks=L+ri|mRI-L2<bwtU#i%LiePLrF(+=a2Hx4oxd;~C|( zw_x@gbQq+hhESdNY-1HSrH-Y*^*r47hK*^RrJYXJ&X{%!*;|0AEXb|l!LW&hi3?2Z zBKYF5weF3WQe_MO;^K!`L@|L8N6zBxvgk9yKz zT>QM+RMsSfVW2MeGVbl_p7l;>7B){)%r;OaJbFW_Z&z0*K2CIlR7fvr3k zI0}{s2B3DUQ8lS5u231UabK*|Z<^^&y48jc_=e4S(IyYt(S6pT!Q>$LOHAv6Dk30S z-aV5mwAV_0u~u!?kpcH`D<-0tg`FB$)fsQlo%X@CsP-YRwjCgtsstNPKRilstb%n5$B6LP*>!NNWU39HN52pK_ zI&(%`iAN@7>K+?eNih@79#6g53Ybwp@n&iP9UI=<8T&LI4fmVsVMhwExP5ZOt&V=&FF>sD$+R@c@X z3LaRTF?mylG^DO(t=?F#!Vt2|92g0~yQ!#GQk+^>w#sN)8uf~J@5IBVIMp`3btAm9 zBgHS9EymeZ{4JYIy@5;ERXnkp0v^!m^5}2ODt)7}whOhO0T9#=h#OiOR|_?8#tc0A zs2O;p87MX6g3S(;tCcnRCC>rnr~@$M0b$Z+;LYaZkhz#Pqqq5g+g!2iZgh3sTwH~c zH_d3VWJc6|DUVh+U@i*B!hLGljH=)Gi)BQ8b5U!o%8AeUQs&lc{xk&5SgemyOCuZXS|f9nLSd@SfVLn~PHMi~dGs zO>XL7-HfWs_lwrW^hM=AqwN-D9BJ?38Fi#%J=KqPYT}J}G~nzPEfz;rRU$*W4ClGg zvB%|hY3!WmhWoJ#IvcTboFkY` zKdjwELyEgdPvYtxN9j&<4Z+}*3U0bU30%a(vBxNoYUn!NS;?38phyX`SZKBJA1`vX zh(qF5SM&ukOg1-meH__VhlTTU_g2erU{S64-f7V>sY~7`&fvTq$SwYvvidO!gsibJY5(i@*vv zbv$TUDXv!7snk?QwinzY`(sED7Vz%B5o%9e%gWcp=`ls5^6IEPAOfcu-Uu9gL*nRW zhMB%s3Z__U;ZM0;pjWLpb)HW3Py6_)MlE10&6$AUOo&YpI_bLT(GbMp@}e(5gWD>2 z0Z;b5TDgulWIPjjs3Mz%c4f6vtspqBRSWCF#ii@_j}^&5Am;H8oemnuuRO=+7za8+ zXKfF!A7>I~0x<>o0B9)+Y=_}-SBe7(AXG5OSwc293N0a0ar*7lgJB%Q&>EvQIVZYc zwnpMM84uUW`t<`rex9vNeWdN5)fajGHCD# z%~dAduE_z}!iTodnVBtU4kDtQQ%VRP=E9(B-NqB)742`UoocM5_P0Y%t97eEv1C!E zickAU<@y6t2gOuERvVNT_T(i*Dq~8kT;1)Z1Icn(wHIOC!zxpV9&RJOE6Q<*mr>85 zEJ&7MX6YmFQe~4otCJ_@0%-Olk7!LN#I3ph4q#5B-~vr3*BL*^-yr#aDVQ zVJ6F46(kzRB!n6fzP;py3+RD@9|;&m6)VHpVo1xji-3Yw1=dtRp&%%sn^M+InvF3l zT&WnhB5dJAyRp6wUn#(|!H}>R;TdN21YE1_t@@}&NDWbxtEL!03zA9=pDD#&W@Abx zw8Kk|Ve6Rc3DLxRb`>KG_JraQ_fO!z9&pwYB1sx2+!}z5uw6u0SR}bpYV(8&Kgt&O z#@#t_r$a4-OH1GM3tPf2it2Nog^0LMn z;VXSA->QkyN;NH`Z@4%b^o{dO0qdvQlD+U65qhAPni18ta!Hnb;BTVH(CUbg8j!tC zQdLB#muWNxiGnE5kr!i{{yg;E@@TO09_AB;FJbvG(s&7}k!8M8h+y#7Ne)F4E-D>^ zy9{R_m^C*^L!}6#?`#Mv?P{4F=r;;&)`+1bO$|^LT>ynt9EhXf^9gA{L|Cv&$1Ad2 zL~SJh4ot3C5S%atqMOyM@Q_YiIOF+^wf463SMq6lEIQJA>3hOFME*tRG_*c+UYiPn z67`jelC#;_g)@oKGYTn1m2ZbFC;?%{YX~166{4&QIX?mKad`?_)e_`+B8ErpGb3VF z=3$bB9b5Mg@H+B^Lt3!rsPcxagOBcQCjSf+3kr%OT^tbd^Ql<73|fR1kaw5Wyo zx|FKh2`8;M563C{LRe0W3`t{8_K0D!G&CFrBS68$-T&KfNO;fKCH$ms#wkT0#B|}U zMpEfM7-!w!`D!CH6^svE+UiN`x{T9V8BuZ8Ia79eLUhBTSWOIE68vrN`coR$tJBN-7o**P=h%~(zzmRkBlLW?pYeOI~|JWcrU zcEv9bX&b?J7F80t||XRbJ7%Kg&e#GYg8m!sIaoq8fmI#hf}9t zU=xBAQMxQWXYWv?WkXsRzz*YuQFByoSG>nAj?S55Q%-m{_h_iOcV=-qH!Q{wO+tBs zN-=YVI;%r1bKi|h{gKNapchBYiy|-H>Dh_#Gv*~>5FfBXA7_L3&Z&|Mdf7~+gaSaa zp*SC}la@Oaya3x_a4P!d6%hzm(ocv6nfu*ax3mwqkgx=l@LvUCL780v{&jD7Sk}j+ z1%~Dd$d`;xMd?|)hI7psZ*i%-r~;jt$bp(7UXZ<+m8D4`6lAyS=7j~A{#>PA*)ea` zn>Va1TWQw3O>dsh5}f%o8}#Xl-3^P03^S#csJh;60RvhzpP^vQI7Cvua+3pw+yWyY?}Cc?r-1zlL386gVGZ=6Qh2f}>Q0%Nc|e9L5^waoyv zLXEz4zTB3uZ+Brb{+RD2BKB^flS zD8BgLF7hK+K=@YgC{o3Fui*O~7VFkg=mNolK#`x6u{&Pf#@Q^}k3*$!SAiaA^G%9H zy9RosJFoZC%N=tvIl@|getai!GI%cRc-~3x;o%Ex3Sorf`Q+XJL&)D)#Wmh950k$6pQ0hA}8PscN`$EWvOdgT08$=IP-vR?>ABhn8bQ`dL{jA z{mvHsOa>vQTQc)QB+$v86_^=v*^TGvE;SL5+4W|J8#Xh^G*J{X3^UU4Q1Hs)s(Z9~ zsp2#glGd2_(6JHAS7j=q8)_aO^DtU#Gh>^ZQ_zs54Pr<^J}t2xJso};3746ltRK=> zWzA5EEUkMwtFo$}lZ@?q zlM&l{eOl+hOKE?jvCRylEI4kTp|_mZEfe$_$Vlg+DdZ-*41V5Hp>R~0qos5qL0WIi z2x~UQ3JibvX;W#+E+I?4I?1t%VUDbok|htmp?gN$Jk&ffDm$(k>2|ucU8t{Z`IUt< z`^o4UfKoCCtx^_mR;1FMfNQ9kR^116_6WQVO0El`nU}9Y`8K2BgjuVW>aD_7shzHb z3AJPb*sUEeFs@xMMOe@UyRr1mVnrlMmjxS}f;^1a^Byy50(i`L_O2Yq(-?hZytpY> zDtIu#L%+KK=tL^GOHvIu;2{7B?#4TjFoh~IJ-^M3f?-=^ebW?CQdCW;vd*g0IvXiA zpw;bi%cv&BG-chAbv{{GV*@ndI~Fw8(IsV3M(VcVaQ4tDuXhj$5TJwo6=77dQLU=< zA%Zt+br5SeE(r08%Hnm8?=k`age*fjJdf~=5MDxP9bFkw6`9?_xGHYZA(mu2RYUdK8%)_{TSz!hLMTKtru|}H zofn~;0&8vP=OIIKkHO2*K2#x_H(=81k+PoA(w|}E^jpKLm3mr!j4TyyHJL7?nLf5R zG+mXgybQy3oDitt2)=@Smz|odhmKqry?E*Jm4_aFWPBonR}t#OieVU7SS>QyHK%1o z`iz+`%tI6P^=E5Mgtc~YgXL%7k#5_&hCNkW@>DO>15Kq}=BISXmMz=jGScxPx_3|r z)r8CXQa`(p4w}OlnYOb%hYvv|txi+a0=8xzD_>QU9bRyo34**VqmkU0Ld(`3Gu~Q9 zP^NKJ<0z<=YOwLVT$Cvn?c=hLl?+`?v=d$_L~)~n2=7W!_RTURP*^X3`UR$-v?n_i zrM!z$C%cV^Nlb;hNoGL_?8xX!)+)n&86ccmS4v7Tb@5f%jSjW+8>Yp+$+Q~2pK>Yb z1Dhdc97CN~(V>gDEHlIi9s?o`MOqohoz5jZ{;&*6bbhUSDsoy7b>ia;iv?tM)O3o< z*t!@Bis8N%&|Z1RDp=^mR&gsm0D(iQTx?aEvWa8L!O*7kYQ9kr(PCc;(Itg}ewEp% z_F0&>B`MpTgPtYL!OoX9V|GpQR5`I*++`H0IzVY}bp6>vixgnHqz@6o1dyT-i6ld4 zTO=lS*|U>o6Qx#hQ(91>SjT2RY!xIetUk*`Rgy^av9DEe9jeZK+Dj;4yu`hYI?6Gi zT+2!jc6-$SYVZA{t18a@{|N~pV8p0VqeeX{u|Y!!5Hui4A_0Q(BS4U#SO^>>Xb6!6 zh?e$@7F%qw#TF~Jw8fU*9!?J7Kxr@b#!s=uUbw{;EmpL6o3>Q3rIjiwXpqnAJ+n^| zP}|$jTHm$4f7~n{Ui+DOX7=pav*-8ThbfSStQxQ|r)>bvO=qWUhfU`#@}?6g{R?W@ zw8(8z0VHnyYKPw|PvP@c6J36|TnGxD@e7rm&#{|=N=|S(L)8FO{Y*6I3P}#PPN_&< zzpGEWZlt7eg@fAPy*|-tREV`^3|t;@@|r>|>u3(ynVT}7A&P~`I6Z_)qAu9aD0YvHHL~PO zNNQMBcDj4t8`P`phfP*%+CakD$&-3|A0N|55sRyHnA@gQY1NP0Gu4$!h8Nl(=WkDE zouQ!(E49==EJ9Ex2W_Wvo!uRc&Yd#OteBt0>CE8Hre#7T_yC-xUs6v@R9ag0PCBz$!|g_k6t@{Q}(sYaceT(xoTTJ`C)t(l`;XQR3t zTpjGLgDr2Wo%AvR^^qS1cB`d6ly6FL@>+v4P@w1}pO(ML8mr5O2hZiP`l5cr1$#zL z57k(^q{(GSXL;=GUo+vspvpzjK$}J$cU_N`rRd?ZF{_&+AvJ$sDj4^6Wi(AJc637) zg=+EW);&yK7LO>mmsNPWZ{5q(GCjPVK2zP>W%>aX*K1?4n^#HnWCbmgsuh;l*fFVn zC*-l3gK9n*|3{Ucz!Y9k;oz zHdB<^=fgH7Kj5G4-mwduT(#PDW!#v#?DC-24myYK{TpR;S3$Ui*LB?1kmd&0U?p|8 zD7ARrQo2oHBgbW|&@P^*28i_XplJF;H*3B#Q``a=bs`VWfC2OmL-)~8Q7JFMO4AgkVNv6P z=EeF^LsKxJxNuNmQNe^kMTJ8Pix`Ixm!j$%=V(~uYU_cDT(5Zi1Fue-!Uf^x|B)SS zp{csfP!~7SFE6C)TBy_OTxLL#-VxE@oc|UM%nJ|9Q}^Fn!5A+ES=f~h2Hykpm!F!CBmC!uNJk_BXHcwiG-P8-d#Ys`pX#{b4( zVYhK!-JJtzv&|Tu?FpkV@9Lj3qr+ASrfT!p+%$)d)PlJK=`ze^VC;@5$h=)L_ag$b zOJ0xsti@g7KOB2t^p8x~ue;DqF8mXt`K-w-?6TpFt64_>F>N?dT`}H6(RLuSnEf1! zn6+8L#(&oD{cMfa#}?E#Q2W*_k@s9uzPN_xWWI4ba;QgL*U~IwgRKeI&TTL?;W-4M zKSGCFwNj0#zmr|m+PY0}`uawTZ%h+6&6?9Rt0v51N}!m=@Z6fk;aQ89nWYW&hE3&e z%9A$|=9u{nN(gPC!Y!^@=I8@6K%Q&r7tL7|rT|VXpE7A&xxTc@r-FU1h+ZVtxp=FQy|TTHKkiI`BIrtv3WM>3<8XbWnLLe;kC|~E zqZ}p}&uM0&`%M+Ycb@rXgSpmRXG+X4GpNW68e~}A95lq-#%EsiL+|c@50SYiURB8H zLM_2H6%OVV+wi?ZM@d-FgNnnl)HKk34qCfrn>L|I#kp& zDD?~G&{G<0MzX)7u6d-ni4Sm(FPl2mxc~E*3n?piODg&gl{cFFd#}lLJ3jLenli<$ ztMgRqT{SM)|EKrbIAV9(M>;m<>CLyn;f0ikPBFLF+{tTi#x=4&CAig&&srtrQtftdcQr5JLg%gF09}L&WQP|~t{q?=|HlQnP+PKY@CO1K;V|+uS z`3ZyJ$txfVc3Lk9GZhZC1BUmlSawRDsnN}`8*kLFbc~)dV#EN3 z0UG1h0ltiK97~I-NB-eFkw7Kb1gj-T6T`S9n<=8_h3@ zO&d3r-%&7Arj|)Uw~U_Qw?gZC{d8MuO?d?~C3mvDKU6^#Lql)Mu`Sn(GcEp9N~>Cj zd7-kp`Rp@ls$FRKvdp+CqbE(|RRB6uHJ$E!e&|*`SDlujMRT;NN)?25HBqsc%3H=& zyZ=J@)rCWghAkb^KQu~%?K?G~rk99;`_JvjO1f5#tu)9fZhWWTAfZau;uTV{Bb|B~ zHL0IyoXAQZm4xeX(UwjqH_TKqi_&eRmd_^+cp{01cR44F@dngtEWNQ8GjxjgD7V~6 zhg%I5S>ztUsgufhh#5m_&WMEV`Z+=45`DVnN&T# z{4_7lx^$9rs!z2~MRG=nS;guq)5Of8nNmqj#rUwkku?=IL($P9sxp2?>?Tt_YP4oa zQIc6(J$R@=I>&P3rj}1M`mfVvN)@X|3^M4_Of9Q4^^Lrn+;yM$k#Aj;n+;c?GZa^~ zW2RCmY-rGQLHA1e*BiC{~cra>v5 zu2b)98OEA2d7tWZo1D}e(XftZ^;BPd53I8gv#XUQB5d3o)G1Ge?8;)sL#sG50!O3BDYk#(NS`y(ePR0D$~76D7)6*yRzVME_cr#-_yLs+_Hf6 z4rZmNYW~Q*?@LqbF1x?pYci_+Lz5bGmmAF$yb*c@b*KB;4%)|HdPiR*#mV>wC2-Wo z&c|>?$-AT`X&#fT)qLTMpO;r?w?fkG@pGMv2^4AiKHaCG=|u2RigF$!Kjxm1jH6rF zM8mJt65Bo$ApYuYnXV7V{&Vy^VB)j0JxJTYaO0;HYeeuz6>?ACP3XyReP_3 z<0b-=^|~BYuH>kqr9J^4rgXX+$*Fh7wmWqg3+ZSCbH;&I*f`G(WN4NtJ+nx)e?he| zUp>D9x1FOuZ$9_o;aO_x!;6||3Td<5(G6-Kbq*>7=NcS4_h81Ilyx-#M9 zF^{y>lgAKEImAy+SOG^3OgBtxVri3%Ln1pe1?aD2$Dhnw^cT}?ehJGyWBzhR6u)IKn$3fJMJwE( z@tyhwZpJ96`IA%58f|Jw=o)Hee&>X?sbZC7kya^O%GGV9?sIlrKN~Y$d!JnIqPb_$ zM6uN@nB}_Z)Ry(Mac(oIrr!QhEDG}xQ{X1pknrL0jO#4>HcY!97tLMZno{?^Lh^E4 zuPwMPU!a`A)T+LY!P7xvb;Yh%=*roLGa-3JdLG z5L0~`7UqSSSi8dXxnic7X?pkWZA$eYk2e2!v9gccaJXJ2Z9z>P#g`Ex=8CeYnTQm1q8GMnUxn$fhoCGeE~#!Q}?rX_iey)_Kv z^e$^c!7SR`h9&MXAh)&Yf@Rrm-)_P)P#IDGl~W$M!6Vn(hXJ886oGO)WkKF!ydAU^Z+p;^cfxhBM9WT2wR2?f1~@ zR(PE7RnLJO;W+by0 zc}$BJ4&l+@KW5Z<*O5t|;obh{jTW{!(>nhXv%CSt7*$k_nl*)9w>ulxHc*4xF3nG| z8e=}UHRb+9Vsk2orp+Ix=(yJwxtkUL)8oJSusvko(Jh``-Hz{f$F03ikMmV;6_~%jWCu{`&IJJ^tNUif6NxO>pe;VVf@xljPq0IqaU!b>7C6U2n6|9e>BWyL|pa zx8t?lj=MjHtGciCW+`rSaFL$4w7We!s-^hKJKSBIGWz#)R^xS1`>Gs?uQo5eI;COc*@_g2c&ns;Ayc&6x z?!_z@|I9OwM|4pK&-FZTfoIdjo+Y`S8v?Ev#OW1J!)&k%^5Z;UwXpkK>3Rsdu_4h{k>fj z#`Ct?+N+O8c7AX&viurvw;CoAG20GXvbNgg1>SuPl>0Hb9{ak%$0O0Rw%Aor@ryct z0=D8Fy4L&WUXT0cG`o7_@yKS*zh;!T+wT~+{mQ*wA#T3PCPqt-+4W<*yJxE{9!vNs zTkZI9$0J3@Pe%6NBL5b>lm{K;pUNP zc6pVz&zUC1?FP7cWVWrEf!>mC+eEHwm$*68?wu)~V^`P6J!Z@2V4tzYj+pE1njBkg zW*EIC!`6wLueNFP$(PhEc73h%G#k20_N_J{Zcew&bz+8HUr&7G)9OX?kJ%%Raa(Z@ zI`NHYl6%}{F7f^u%fzVd=g55%iGOdi+*@t=z0%X|?EAdken;~CQ$F2^<^FsJKg0dz zyelHu#V)iXtituN>mTs$<)8I>^g*wW|D57$weg37pRO{-;}W=kIx)9uc$ z`EbpTDO}X9a*Wx1Fitt_xAu4>26wy>ux;|iB)bJoc|W><^c=R<*B@J;d~ZL7`v z7VNRrHm#Rkt8IHijM{b>AMe;|cR9vvzwO5(EAek?^YN7Y#HZ^h zRJ^Nqz?L){ecG41bwBm-tanVJM+41~|Ek(BK=f@)@xUYtr)3@6A zfBAU!LFGf}7hdn@nDBb^T)QH0Z-cr%v&Y9<zu?ci1|~M8+p6ElpYu9$y-?5D z`WNM2Z1?Y%f5LNfmfiO zHSfwl%~l;33vK25-oHsCA38duZ?q*RV9P~ztw{Lwj&Xa;F=lf=kbB&&7dPkHXpi?` zAG>gd(V~Q+Vka4`E-og zwNTH&_P~8FEO?9O_vIJ87wHGvE|!1X=H|jp8MgTn$ocXw^X{wR znJX@_Hss@v!o;QmTX3cPTWsc4V$4=JMs3)!)gFa=-#i&v_X!`a1G;)P-`lSdH}$dE z{UQ0kdVs&Koly6;ZJ_L;c87=_E%N$7k$SCq5cx)ZcW|iBzpU%zAG6~fqjoh^J+@bR zOR)_N^Zsi^!ncbXFS7fG%RO$}uNR{>cZ5j3i?kE#Zt!~MjqgQTN2b^YsPwEaMJK=e z-6VhN8^@@vfbpJNZNVtn^|9;9;|WiDvSNbw-{%;&B@_L54nv){e3BTqM;)WKq|)oV99wPaWUn_n za=s}(-`b%IKh^thaHL%c^lepgr+pJQo@0xrdHYIu@Cfyzbn5-mTOs9X)pYsO-a1C@ zHmLGYTJ7D#;+ZR~b$ZmU6*p(w4Yzs!{UZ6fZKm|Nop}fOeE)7+@JYF6*rqw&|5#Z5 zQJX(cq&&a4I#_XyE=(M*-VJYbyvDEt~MEXfHo5hgbyIjn)_A~OQT#5Aa z8XoZOM?Wj~O?LeXF=6A5QG3)eZbJ{so%`Szw>HpMiNss^dHK^0h{U_=3nK0K7sc~! z;!9$ttyt~#5nqL^J#G1;kn1@hZXRsMKQ6t+u5^sq(y#k+(g0n*0lMe!8`5KTCyY~$ z+SWmpqi=b;_HTRts`X;ru5`rSvDH>Qfji}Y_IKnTwGB}59Cdo!HhowAnRZQ7yuu!d zdAkm%_OrZ2dctmZjN0tD*Rvd>w$3qbcZlTw@-5<3_Sjb0QP2H==Ro}^sPpf2jM=Ph zKK^Fdn(~;<{h{|Saio9i7`H2ar1<*S@RMRcYuaQNv)dh`HtQ+5_qEkO5vkXAh#9u+ zY1t+04#%iH=oqv4KlRV$YN+(&{7j77b&fGxu+u+}Bc73a%&v5#oeT6tQvbR4-v{-4 z=lrL?U)4~0J5>CK9BE%1Cf%;_2`D@){BIwAr6c#> zvDMD}o!n`+;rhe$N8tw845M({K_5@?tNwmeyyoMnIs{3V6;-|*=`T3O?Lo&@yYI04 zqjtYz%x3(}>$4rH2j4)a+^=|3?s1#{me^|R9BKED%0Fbczb$6i=sRM%&3;#QF*^b( ze;WdQrz7Po&~x9H9rd?k+^!AuJ&rMJI=p|bBlT>cAA;NeLj88~y+|93L&cM0-goWE z2$sjbX_q$BJ|zar4r2l|0P?|_>}US&7*!9I4q%{W8hb8Wv&h3ENlq+c&mf0y)? zd#lYl%loeu$){sk(xbNcZ0YoG&V4_UPx^|X+)H6U^l+dzJ0`4!Ik+dBPC3rTKHkel zMZ)cJjM?h*-j8(rnf~#`awlDmv^#;Gm5ckPi|huG>)z?e{S9<;iH|QEsvoh|=`p)Y zB;I{c^vZZL zsOyRcdIGBa?Q!}>TRK4DVz$mPYMULYw*$T1vBmZ)^mgTrQ9Bd5cmsW>NO{j4ws34Rv3ep{}>x=`p*b*yn%0q4KBQgYsW_t+!w67`JUO z^YxRFBT(0$f1USFI1*2w=a;{CQWw_Cxevp~6Ms0rYK9>DeB*?+o+r?&D!O>1cu#x{km-qg4Je8*+?V3yblO2l|n~Kc~#cQ|?H=FwoZo zdOXl~1p59!kKg3uZyzPn4wUyFIbwSm4GM(u99D{wy) z=%p3@x>rE;YYswP*N$;MzI~1{dkCtZKKmBACv2S~^*mI6JbOIul+QyGeYk>2+=o7o z*$tJ_spltqyc+9Sw>g_rlskf`VzS2?sVXv>7=EIv?y`JmHJYArtP50$(57c>% zIr98ed;Nf8t8JL!!#6q7E<4h%z0JF?bL4t%N2gy{aEA|{F^lwaeW4n3>Y?Zy?|wj} zoz4$?eWhdErp=Rkx@}khW9QoJyW}6WRZ#Ux<=x(Xts~>4I$z!^q3-hk3Ig$?|`MG_iw?76I-`a=do@*0d5Q}Zo zD)Az_<4fMIU8Fx>_lWeUT@Dp)?^nEjP~4njXFlfjI+1*{)YS+KdkfdjCYJ#>lnBDq4HG!=}=h$lZI?}I-diU8Iy`6=s&+B4dZxZ8Y+5Iiv zt|0E+8yvYV$G9!n|#_b+>><=d+rq#O_h?I-bB`KMuU* z!-bAg{-`&q#F0Ji+IM_CQu;3bt^IBFF-U#3`aN&o{JwAJvpb~IjzaZ&4mh28nG>>4 zvqh%E#TSRVo)IZ9+S9HRDR%`uy!#rc>uF1cBa7_1EbpFwPKWC+v_pm8b*@N1AR9aK zYx@P#dH!;|e_SM;br*@*Hs><2k1f3%YX0jAi2Zg)`r}tBeJOS|RJfh}n&USynqBiBd2C#S5#)!R)_@g^J-_Apd^xZx(bCv4^@k$IJJ zakH%+?d@x!p1+bY=)}8Ytk37B3UuaSi^qApBT)Ch;AXEEJGNRgz9Vw%m6MSosOxVK zxvvK%db^@Y()-wg$v!=GQ1@vc+(WpATcy(vgKF1nXOLgCL)o_}TwmKfQ~r!6?(pHV zK1n+8pAFTIjL!1zi5hR$Z%#+V5^o%C9(j>%nk#qKK}6c!qhX(4tLFvoj&XbVPM;6C zclqlqg*xv#N9HT;CO*!$u1@i!+ieSd_+uj1Td@eTUbL#ghu;pB{_%^wUJEsju55&) zC+tZ305vb({waSwiRH5EXR9N!qyGa{?n|unxMjr@w%W@3eR^vjK&M`5S^?>oBt9>H z$|p1{a&6X1>D2R%%#%Zvi}HtLpJj`_*b$j|fcgb0UCW{J^?=jqXRZqJ1ImB9BlT(E zek^d$e%PmTA56r~wC!K=_61+|=WBo}hby6;hvL=JnP+t*KLWkYvBl;*(&6fhw6Ac# zuy2F1KkUf(`Kw-EA#N_PdpAjMrJW`nJQp2XU@_yfU&uex9)1>5uVnlZww`JCiHQ`O zwO5SV@s0^wDQ--+$KcH0GQaWbj>v2nhhgdaIwG~O0%{&P=LJYTzwb9bo&!+#tNcap zo_I;@V~c+0^RWaL6TTGcyj5bfw_PQF%5@y-{_KJ|*d3HV`EJ@p`U{TCYe3zng5Tr5 zF~ipWLH>*n;o+BAM}mqk8o0+{JMP=zL3ki=Z+A@C4l&l-w*9dqvKRk7a39aW-+QbW=;xQ{sQ?Q0#`XAtOdN7k?3lRx7bu_edOexG`Pb|S08r>_~R z-r3OOM5KxM!>K1+I+w!+^qm)Y_l6v~Q}4pfH*d8KmwUUFBJ-IJ zE72+MtNNXA&v7)*`)_w_wTB(!Hs>n2v(Dz&V%Ne9&cDv-+;2zvgN_?*_9tY|{IN*< zSy!KM_qiOZzG%M2pJ#<5^OXhOK0LtN?SZO?XAbo4aj1G@c9GoEZDJ7DN&2&f$e-(S zjN3zjo?Yz2H4QxxsoPIF%eb==%b_c#-!ncZ}H;BIE!3#vneJLHyAs zZ`bCy$*x&~PCsowRQk;_g}cgT-0$5hpzEhfr#;vuYMu6T(rFhRTWs#<(c|aY?IQD$ z<5$9#kPSWL?P?vlZ;q@Fd_nFpJJT_4v%l!=ieTMuPDaX|PX9-wACR`{L}WJZhaNr= z3BxsC^5G9UChSp1_FsM3yRUR)yynRHR{QIyg}M)MN5*ZBNN=^xUlF5rB~-sU>#N>< z_8MOv*FGwp_FAOhQ~5P-Un^>!|1lqb7|N~}Jg>Ztp2C~!Y0($41po9vkHccdP7WW4nK z6RsUx3l;w!k$T(2PDDzS&bag(yJ0ijm}4^&veWonr2p>7a|YdcrBh#S+XA_sJ=;!1 zI`;9LZnB61M!dFn*u5X{}-!-XANZO+r^t-b6n zxDWpoKRprI4`=^OcI;b$a&Op4zR@pTz8jvu)vkV)e8;`w*ZzFvjxk%b&&S{7$ohAn zuXkjB;tT%1*FoLC^^UY>j;%K1H{Sh_$bA{{qK|JjRQnkX^rMc=zzM;{r@e}{yNfc`JH!PE2=-=?(geCsPT8= z_mK3J|3Ut_HuF!AcxJ-3U-SIGdLps|&VJ38x5J0L`@X~eyj6ddJ^NQg`hnR;q%&U+ z*As5f-_g0A+&ASOv(0exOIU z{fJ|@lOOgyk#^w(?IZg_k3v`Pd?0tmujT{BaqM4&iPVjDyU2OcQgBzh(L*}>K2u@* zOlw8LtxJ=8!tQgVedsBj{)r>=ZBXf`P5;2Pk6FDwi0pcveUrJ^vEOsHi2Y93hI`2+ z(p&6^OT~@0%8~s)j_d6z$AqoEO#aMcIx>$JlAf^J9Ah@~a<6AQGXEpC^sv=e_;3x5 zJjaf$Ha}19)bC;}#g4zq>(Nhm`yGyyulx@pG3FK4!4~G#jyS!SUDMy&WnCju?>RnRB?A>#q-17sy)RA1op~Hb z`t^$xt2r-42q(W`%n&#gmcX0G zOdWI+@R&1lG{0L&$D9uBX(*uyjjY#`hX#CIpW5H5lWNy_-tFMSp~OzHr0GZ?o(6ETKLVTRI?uL=DgpBioXRev8iSo+(djo zhL0~xH9O#$@aOQAdsEFX;Jitx=6Se;^SlhFElD-MgJMAUhA*>45;fp8;&baH94^CGpXiMsQl;$2a%4e;r+`~&0zR8*FOyQB>tP=mPYao z9w+`(;{WA>bn_x|5cxCmSL6tC6gh^xk7QwYE^-0#0eZ?^>E4VJM2;gpDtehSkPDE@kOE{VQi@DOrX#bFCS)b@7^1&N z#`Q9rk!O*^NS~W~nPHXOPvmA~9&$hOEo2L_3waqij2uVKp4`h^i4-F&gv+2_{Cota!6%?<=O>|Rgr7l$d za}m4}UJM6As&>9Q*2`Q1XTVG0o$xZa9ERW*;pOl#cm@0qcqM!ZQe~TWq3WtW(|Vb! zU_bZ?cmvFblcDOsB~W$cYFGfj3sqPC1Qx>mP<7*Lun4{l2f@C#_A-OvHE;+V1B>A_ zI27IquZ8!+>)@AR30w<@!AK9Nq*g;V4)G z%i%IO8h##*fsewma0{$}JK#9@Yj`t!72X1m!}0L4>RyH>&J2eW;dD3&*27BpD5PmK zKZaA_%Wx{}GozQOf<EYWfotF#_!OKA_rWkc3g^MJ+k3e-=3+P>eJrenwUDOT+z;=9-+*_+pTRo# z8e9m^o7v0M!xE@AY64W-H5=Xo7ebmk^BLF(*TE+EBe(?aflJ|^;4+wUM=#S1FN62O zVt5}M4L=2|;Bpv-pN31}XW&CH0yjVlx54}2ZukKF6Z|YZ0uQC~9Dh$UtNWavgFbG8&nHOh;xT^N~++-f>6+#}VWKWchb!bKw6=eE(nPOEQfQl0Kzd z>AwpZoA2+<_iFsTio@5rXItT)VH^Aldkl?j&p5pQQ57hd+h`;k$$z29LoT;Bhzx zz6WoHC*VZ*AJ|WYZSZ#Z6r2b9e!`f$;90Q$T+UB&1_lg@sTqPk3@Jq_kV<4a@=0Vi zG6xAGcOnarI%E;D82J?P%>SXkLS!fAaS{BHBr4vnHep9p2zJ)MDe@{-$fKp#(dg(MDgUp5TbYrU=h;&Pw|Yv z?M6iLjDh12#WM|7Bg*Hc@LoiHk4ND*5cNM|uoY3PPs5#v`XPJZuMqV`eh&{K>W>_O zZzB{Z^B(*FQNQHUTH1R=eUoe92t@sp32-W+KFWM}7ovX3z3|hB`YI2=2NCsG*1~Tg z>a!%^HbniF9q<`MeV6Cq3yAtJ2jK4!^oBFCih0x56ip%Q@Z;44*yPJa`wP`~F$@5Tg6u0=FPna=aV<3hBr3LHHV? z{?t);98sUD=iS^x!d}@#%k4al0K+84JTYL}lz= z_yD3Zwi-T;sElob+Yptpop2ALGPV!Cg6IrK;4wsHtY;nN1yLEh9QH?4#;%8>5S6jT zYZ*%;Dl?OCyA@HH3B$V)m6=BPDWvb_i=Ty z(xdb0+TU&Pc_}xgM`wPko15-S@=s?_xYNT*KRvA6P7jOIhr-J3^ssU}J#2DLN`Bq{ zZf)ZELgpiNh(#Vm9!4HR63D+J&mj8|jVWG*Zz3m<-b;A)k;{-Gqy!m{)F4ZdFCpJY zo1gxny#RIeS_PA52d% zHMgdiN0E)wk?It4=8P2crwJ)$TAv=~1&*Ki6J_^~6!Xj{Q_SC)r+Iu%iur3=s#(HZ z%Kdkyn8z>fVJ0s~F;5>zHIwh+Ty-gC!on2OdsGiItUkr`Uz%bzA%E|Y=G=AkdFwG3R zJk4x+tA}|SzlC2(F_(Nb#hmwOiWzrl4|Dc8sU{_x`4QOjYq)(q#T-W;`i&Ix>3(Tu z8oXp3={-NyoFL!s;P~us`nbROJoz)Ihj|qJhPQhd-4mrLDVKjc#XPs3u;0P{yWBTy z%33)`UYe7XA99Z_N;PM~r+$PmcQ^Sz{QVu!f$b+!&4Qn$mIF*%b5pf>iVNFH_79_obNE_hL7uhv`Ya=su{; zdy2Uc{pt9QJJQXt(W&lu(zU)WlKZXQj_>Gp9OigNRjMiAq01+p0aLi&)DLHm?W!N{ zxap(ohcm}@*$gZHu#M7m`rm+*bTi?dp60>SbaPM7bko1rsr6Ouf6}Hb%P@z<-Wg`~ zgS5ZM?9UlfisaxH`aJdb3dUd@=OR&T)1W~*GBV6V$I?s~x1+nLNJV! zE&YWUaQh?wf6{*>Hlfr0icb5JEheV#kY`(pX`~judicM4szsyGP`OZyrZgaW_dlgd z?Q&#&y4g#*)&A*Eb^qEkPffGhpYDIUf67z(4J^7YR5W<_ zpkc#{hw<}=i}_IZqQ=nZ=7vx|(><*F;g2BjU>~?>=)l2691b5cba>Iwe-yZ>sqX(Z zDBnlsL%Sannp77R{i74RZ_fsShyJUV+(>r$uX2CP>HqO{&s#dneeIOrZgN?EO0JRe zp@WAH8T7G2)T(Pp`6!l-@o1q@I(OopN5v1*thH7xlO})fBp4bShlD$g{DQMR5J;&-Dy8tXz9^7{w`_U3%Fe({1i{MJRIDdcCo__3eDIgR|shn)GG zKB4)~{l-QRxqkDkP`}$et7h?HevFH+?l0g6p8PRC&d^QeQvOGO4OpqpQcbhNA~5%> zU2Ti{y86>oBRlmK+s{om?br;RD;NKltexDr3n$s-@T}#$n{GO~RaVJE&B+nEL3Y{8 z8S8bhX2HEk#wa_*`8c99=-D?3Qc>i`5K{G*w11dmjXPzRfn5f6s&A8j$@AWigT|z? z%f>GIW8%{ssp6JhE_S&eV|RTwyHe~*v2z1d-1Qf7{~I^AnT)TLx~g;xZKxcAzhwI4 zl(Z|SZYv*4+x8K5v#?YCD19ZgZ6)KV7k`Kn{3Y*47`m4#~rQ*!h~#N05Ju nA5RC-x#vd56$s~4v2lN;*cBxen2ax($4RdS?4n7fo8A8fobbrz diff --git a/release/zimage/kernel/compatibility.sh b/release/zimage/kernel/compatibility.sh deleted file mode 100644 index da1d32a2db9..00000000000 --- a/release/zimage/kernel/compatibility.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/sbin/sh -# - -#remove the binaries as they are no longer needed. (kernel handled) -if [ -e /system/bin/mpdecision_bck ] ; then - busybox mv /system/bin/mpdecision_bck /system/bin/mpdecision -fi - -return $? diff --git a/release/zimage/kernel/edit_ramdisk.sh b/release/zimage/kernel/edit_ramdisk.sh deleted file mode 100644 index 09fb2538403..00000000000 --- a/release/zimage/kernel/edit_ramdisk.sh +++ /dev/null @@ -1,61 +0,0 @@ -#!/sbin/sh -#ramdisk_gov_sed.sh by show-p1984 -#Features: -#extracts ramdisk -#finds busbox in /system or sets default location if it cannot be found -#add init.d support if not already supported -#removes governor overrides -#repacks the ramdisk - -mkdir /tmp/ramdisk -cp /tmp/boot.img-ramdisk.gz /tmp/ramdisk/ -cd /tmp/ramdisk/ -gunzip -c /tmp/ramdisk/boot.img-ramdisk.gz | cpio -i -cd / - -#add init.d support if not already supported -found=$(find /tmp/ramdisk/init.rc -type f | xargs grep -oh "run-parts /system/etc/init.d"); -if [ "$found" != 'run-parts /system/etc/init.d' ]; then - #find busybox in /system - bblocation=$(find /system/ -name 'busybox') - if [ -n "$bblocation" ] && [ -e "$bblocation" ] ; then - echo "BUSYBOX FOUND!"; - #strip possible leading '.' - bblocation=${bblocation#.}; - else - echo "NO BUSYBOX NOT FOUND! init.d support will not work without busybox!"; - echo "Setting busybox location to /system/xbin/busybox! (install it and init.d will work)"; - #set default location since we couldn't find busybox - bblocation="/system/xbin/busybox"; - fi - #append the new lines for this option at the bottom - echo "" >> /tmp/ramdisk/init.rc - echo "service userinit $bblocation run-parts /system/etc/init.d" >> /tmp/ramdisk/init.rc - echo " oneshot" >> /tmp/ramdisk/init.rc - echo " class late_start" >> /tmp/ramdisk/init.rc - echo " user root" >> /tmp/ramdisk/init.rc - echo " group root" >> /tmp/ramdisk/init.rc -fi - -#remove governor overrides, use kernel default -sed -i '/\/sys\/devices\/system\/cpu\/cpu0\/cpufreq\/scaling_governor/d' /tmp/ramdisk/init.flo.rc -sed -i '/\/sys\/devices\/system\/cpu\/cpu1\/cpufreq\/scaling_governor/d' /tmp/ramdisk/init.flo.rc -sed -i '/\/sys\/devices\/system\/cpu\/cpu2\/cpufreq\/scaling_governor/d' /tmp/ramdisk/init.flo.rc -sed -i '/\/sys\/devices\/system\/cpu\/cpu3\/cpufreq\/scaling_governor/d' /tmp/ramdisk/init.flo.rc - -#add line for CIFs -tmpfs=$(find /tmp/ramdisk/init.rc -type f | xargs grep -oh "mount tmpfs /storage mode=050,uid=0,gid=1028"); -if [ "$tmpfs" != 'mount tmpfs /storage mode=050,uid=0,gid=1028' ]; then - echo "CIF hack found!"; -else -sed '/mkdir /storage 0050 root sdcard_r/a \ -> mount tmpfs /storage mode=0050,uid=0,gid=1028' /tmp/ramdisk/init.flo.rc; - echo "CIF hack added"; -fi - -rm /tmp/ramdisk/boot.img-ramdisk.gz -rm /tmp/boot.img-ramdisk.gz -cd /tmp/ramdisk/ -find . | cpio -o -H newc | gzip > ../boot.img-ramdisk.gz -cd / - diff --git a/release/zimage/kernel/mkbootimg b/release/zimage/kernel/mkbootimg deleted file mode 100644 index 5b90622cf457c9c4594d15ffa08b4397b62b83ee..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 64076 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 SPG$5OT=zV3Pq`lGrtu&DFs(5F diff --git a/release/zimage/kernel/mkbootimg.sh b/release/zimage/kernel/mkbootimg.sh deleted file mode 100644 index a09f6588371..00000000000 --- a/release/zimage/kernel/mkbootimg.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/sbin/sh -echo \#!/sbin/sh > /tmp/createnewboot.sh -echo /tmp/mkbootimg --kernel /tmp/zImage --ramdisk /tmp/boot.img-ramdisk.gz --cmdline \"$(cat /tmp/boot.img-cmdline)\" --base 0x$(cat /tmp/boot.img-base) --pagesize 2048 --ramdiskaddr 0x82200000 --output /tmp/newboot.img >> /tmp/createnewboot.sh -chmod 777 /tmp/createnewboot.sh -/tmp/createnewboot.sh -return $? diff --git a/release/zimage/kernel/unpackbootimg b/release/zimage/kernel/unpackbootimg deleted file mode 100644 index 25ac61d16cc34da290e0b2b385aafb0e1da720f2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 58952 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 Y>Nt3A8jfflk^7+K33!in0jPOD0cv52rT_o{ From 50e7a8d6abcc66a8c99f4e7fe8bfb06dd45b18c5 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Mon, 13 Jan 2014 03:36:29 +0100 Subject: [PATCH 138/215] mm: Lower read-ahead buffer to fix stuttering introduced with recent commits Signed-off-by: Tk-Glitch --- include/linux/mm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/mm.h b/include/linux/mm.h index cb67f136a6a..cd9c5f6e0bb 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -1425,7 +1425,7 @@ int write_one_page(struct page *page, int wait); void task_dirty_inc(struct task_struct *tsk); /* readahead.c */ -#define VM_MAX_READAHEAD 256 /* kbytes */ +#define VM_MAX_READAHEAD 128 /* kbytes */ #define VM_MIN_READAHEAD 16 /* kbytes (includes current page) */ int force_page_cache_readahead(struct address_space *mapping, struct file *filp, From 491fbe5cc69ceea6065a383804d3829f2ba20821 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 13 Oct 2013 16:02:48 -0700 Subject: [PATCH 139/215] Linux 3.4.66 - 47 commits squashed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cpqarray: fix info leak in ida_locked_ioctl() commit 627aad1c01da6f881e7f98d71fd928ca0c316b1a upstream. The pciinfo struct has a two byte hole after ->dev_fn so stack information could be leaked to the user. This was assigned CVE-2013-2147. Signed-off-by: Dan Carpenter Acked-by: Mike Miller Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman cciss: fix info leak in cciss_ioctl32_passthru() commit 58f09e00ae095e46ef9edfcf3a5fd9ccdfad065e upstream. The arg64 struct has a hole after ->buf_size which isn't cleared. Or if any of the calls to copy_from_user() fail then that would cause an information leak as well. This was assigned CVE-2013-2147. Signed-off-by: Dan Carpenter Acked-by: Mike Miller Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman gianfar: Change default HW Tx queue scheduling mode commit b98b8babd6e3370fadb7c6eaacb00eb2f6344a6c upstream. This is primarily to address transmission timeout occurrences, when multiple H/W Tx queues are being used concurrently. Because in the priority scheduling mode the controller does not service the Tx queues equally (but in ascending index order), Tx timeouts are being triggered rightaway for a basic test with multiple simultaneous connections like: iperf -c -n 100M -P 8 resulting in kernel trace: NETDEV WATCHDOG: eth1 (fsl-gianfar): transmit queue timed out ------------[ cut here ]------------ WARNING: at net/sched/sch_generic.c:255 ... and controller reset during intense traffic, and possibly further complications. This patch changes the default H/W Tx scheduling setting (TXSCHED) for multi-queue devices, from priority scheduling mode to a weighted round robin mode with equal weights for all H/W Tx queues, and addresses the issue above. Signed-off-by: Claudiu Manoil Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman caif: Add missing braces to multiline if in cfctrl_linkup_request [ Upstream commit 0c1db731bfcf3a9fd6c58132134f8b0f423552f0 ] The indentation here implies this was meant to be a multi-line if. Introduced several years back in commit c85c2951d4da1236e32f1858db418221e624aba5 ("caif: Handle dev_queue_xmit errors.") Signed-off-by: Dave Jones Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman net: sctp: fix smatch warning in sctp_send_asconf_del_ip [ Upstream commit 88362ad8f9a6cea787420b57cc27ccacef000dbe ] This was originally reported in [1] and posted by Neil Horman [2], he said: Fix up a missed null pointer check in the asconf code. If we don't find a local address, but we pass in an address length of more than 1, we may dereference a NULL laddr pointer. Currently this can't happen, as the only users of the function pass in the value 1 as the addrcnt parameter, but its not hot path, and it doesn't hurt to check for NULL should that ever be the case. The callpath from sctp_asconf_mgmt() looks okay. But this could be triggered from sctp_setsockopt_bindx() call with SCTP_BINDX_REM_ADDR and addrcnt > 1 while passing all possible addresses from the bind list to SCTP_BINDX_REM_ADDR so that we do *not* find a single address in the association's bind address list that is not in the packed array of addresses. If this happens when we have an established association with ASCONF-capable peers, then we could get a NULL pointer dereference as we only check for laddr == NULL && addrcnt == 1 and call later sctp_make_asconf_update_ip() with NULL laddr. BUT: this actually won't happen as sctp_bindx_rem() will catch such a case and return with an error earlier. As this is incredably unintuitive and error prone, add a check to catch at least future bugs here. As Neil says, its not hot path. Introduced by 8a07eb0a5 ("sctp: Add ASCONF operation on the single-homed host"). [1] http://www.spinics.net/lists/linux-sctp/msg02132.html [2] http://www.spinics.net/lists/linux-sctp/msg02133.html Reported-by: Dan Carpenter Signed-off-by: Neil Horman Signed-off-by: Daniel Borkmann Cc: Michio Honda Acked-By: Neil Horman Acked-by: Vlad Yasevich Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman net: flow_dissector: fix thoff for IPPROTO_AH [ Upstream commit b86783587b3d1d552326d955acee37eac48800f1 ] In commit 8ed781668dd49 ("flow_keys: include thoff into flow_keys for later usage"), we missed that existing code was using nhoff as a temporary variable that could not always contain transport header offset. This is not a problem for TCP/UDP because port offset (@poff) is 0 for these protocols. Signed-off-by: Eric Dumazet Cc: Daniel Borkmann Cc: Nikolay Aleksandrov Acked-by: Nikolay Aleksandrov Acked-by: Daniel Borkmann Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman netpoll: fix NULL pointer dereference in netpoll_cleanup [ Upstream commit d0fe8c888b1fd1a2f84b9962cabcb98a70988aec ] I've been hitting a NULL ptr deref while using netconsole because the np->dev check and the pointer manipulation in netpoll_cleanup are done without rtnl and the following sequence happens when having a netconsole over a vlan and we remove the vlan while disabling the netconsole: CPU 1 CPU2 removes vlan and calls the notifier enters store_enabled(), calls netdev_cleanup which checks np->dev and then waits for rtnl executes the netconsole netdev release notifier making np->dev == NULL and releases rtnl continues to dereference a member of np->dev which at this point is == NULL Signed-off-by: Nikolay Aleksandrov Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman net: sctp: fix ipv6 ipsec encryption bug in sctp_v6_xmit [ Upstream commit 95ee62083cb6453e056562d91f597552021e6ae7 ] Alan Chester reported an issue with IPv6 on SCTP that IPsec traffic is not being encrypted, whereas on IPv4 it is. Setting up an AH + ESP transport does not seem to have the desired effect: SCTP + IPv4: 22:14:20.809645 IP (tos 0x2,ECT(0), ttl 64, id 0, offset 0, flags [DF], proto AH (51), length 116) 192.168.0.2 > 192.168.0.5: AH(spi=0x00000042,sumlen=16,seq=0x1): ESP(spi=0x00000044,seq=0x1), length 72 22:14:20.813270 IP (tos 0x2,ECT(0), ttl 64, id 0, offset 0, flags [DF], proto AH (51), length 340) 192.168.0.5 > 192.168.0.2: AH(spi=0x00000043,sumlen=16,seq=0x1): SCTP + IPv6: 22:31:19.215029 IP6 (class 0x02, hlim 64, next-header SCTP (132) payload length: 364) fe80::222:15ff:fe87:7fc.3333 > fe80::92e6:baff:fe0d:5a54.36767: sctp 1) [INIT ACK] [init tag: 747759530] [rwnd: 62464] [OS: 10] [MIS: 10] Moreover, Alan says: This problem was seen with both Racoon and Racoon2. Other people have seen this with OpenSwan. When IPsec is configured to encrypt all upper layer protocols the SCTP connection does not initialize. After using Wireshark to follow packets, this is because the SCTP packet leaves Box A unencrypted and Box B believes all upper layer protocols are to be encrypted so it drops this packet, causing the SCTP connection to fail to initialize. When IPsec is configured to encrypt just SCTP, the SCTP packets are observed unencrypted. In fact, using `socat sctp6-listen:3333 -` on one end and transferring "plaintext" string on the other end, results in cleartext on the wire where SCTP eventually does not report any errors, thus in the latter case that Alan reports, the non-paranoid user might think he's communicating over an encrypted transport on SCTP although he's not (tcpdump ... -X): ... 0x0030: 5d70 8e1a 0003 001a 177d eb6c 0000 0000 ]p.......}.l.... 0x0040: 0000 0000 706c 6169 6e74 6578 740a 0000 ....plaintext... Only in /proc/net/xfrm_stat we can see XfrmInTmplMismatch increasing on the receiver side. Initial follow-up analysis from Alan's bug report was done by Alexey Dobriyan. Also thanks to Vlad Yasevich for feedback on this. SCTP has its own implementation of sctp_v6_xmit() not calling inet6_csk_xmit(). This has the implication that it probably never really got updated along with changes in inet6_csk_xmit() and therefore does not seem to invoke xfrm handlers. SCTP's IPv4 xmit however, properly calls ip_queue_xmit() to do the work. Since a call to inet6_csk_xmit() would solve this problem, but result in unecessary route lookups, let us just use the cached flowi6 instead that we got through sctp_v6_get_dst(). Since all SCTP packets are being sent through sctp_packet_transmit(), we do the route lookup / flow caching in sctp_transport_route(), hold it in tp->dst and skb_dst_set() right after that. If we would alter fl6->daddr in sctp_v6_xmit() to np->opt->srcrt, we possibly could run into the same effect of not having xfrm layer pick it up, hence, use fl6_update_dst() in sctp_v6_get_dst() instead to get the correct source routed dst entry, which we assign to the skb. Also source address routing example from 625034113 ("sctp: fix sctp to work with ipv6 source address routing") still works with this patch! Nevertheless, in RFC5095 it is actually 'recommended' to not use that anyway due to traffic amplification [1]. So it seems we're not supposed to do that anyway in sctp_v6_xmit(). Moreover, if we overwrite the flow destination here, the lower IPv6 layer will be unable to put the correct destination address into IP header, as routing header is added in ipv6_push_nfrag_opts() but then probably with wrong final destination. Things aside, result of this patch is that we do not have any XfrmInTmplMismatch increase plus on the wire with this patch it now looks like: SCTP + IPv6: 08:17:47.074080 IP6 2620:52:0:102f:7a2b:cbff:fe27:1b0a > 2620:52:0:102f:213:72ff:fe32:7eba: AH(spi=0x00005fb4,seq=0x1): ESP(spi=0x00005fb5,seq=0x1), length 72 08:17:47.074264 IP6 2620:52:0:102f:213:72ff:fe32:7eba > 2620:52:0:102f:7a2b:cbff:fe27:1b0a: AH(spi=0x00003d54,seq=0x1): ESP(spi=0x00003d55,seq=0x1), length 296 This fixes Kernel Bugzilla 24412. This security issue seems to be present since 2.6.18 kernels. Lets just hope some big passive adversary in the wild didn't have its fun with that. lksctp-tools IPv6 regression test suite passes as well with this patch. [1] http://www.secdev.org/conf/IPv6_RH_security-csw07.pdf Reported-by: Alan Chester Reported-by: Alexey Dobriyan Signed-off-by: Daniel Borkmann Cc: Steffen Klassert Cc: Hannes Frederic Sowa Acked-by: Vlad Yasevich Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman resubmit bridge: fix message_age_timer calculation [ Upstream commit 9a0620133ccce9dd35c00a96405c8d80938c2cc0 ] This changes the message_age_timer calculation to use the BPDU's max age as opposed to the local bridge's max age. This is in accordance with section 8.6.2.3.2 Step 2 of the 802.1D-1998 sprecification. With the current implementation, when running with very large bridge diameters, convergance will not always occur even if a root bridge is configured to have a longer max age. Tested successfully on bridge diameters of ~200. Signed-off-by: Chris Healy Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman bridge: Clamp forward_delay when enabling STP [ Upstream commit be4f154d5ef0ca147ab6bcd38857a774133f5450 ] At some point limits were added to forward_delay. However, the limits are only enforced when STP is enabled. This created a scenario where you could have a value outside the allowed range while STP is disabled, which then stuck around even after STP is enabled. This patch fixes this by clamping the value when we enable STP. I had to move the locking around a bit to ensure that there is no window where someone could insert a value outside the range while we're in the middle of enabling STP. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman ip: use ip_hdr() in __ip_make_skb() to retrieve IP header [ Upstream commit 749154aa56b57652a282cbde57a57abc278d1205 ] skb->data already points to IP header, but for the sake of consistency we can also use ip_hdr() to retrieve it. Signed-off-by: Ansis Atteka Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman ip: generate unique IP identificator if local fragmentation is allowed [ Upstream commit 703133de331a7a7df47f31fb9de51dc6f68a9de8 ] If local fragmentation is allowed, then ip_select_ident() and ip_select_ident_more() need to generate unique IDs to ensure correct defragmentation on the peer. For example, if IPsec (tunnel mode) has to encrypt large skbs that have local_df bit set, then all IP fragments that belonged to different ESP datagrams would have used the same identificator. If one of these IP fragments would get lost or reordered, then peer could possibly stitch together wrong IP fragments that did not belong to the same datagram. This would lead to a packet loss or data corruption. Signed-off-by: Ansis Atteka Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman ipv6: udp packets following an UFO enqueued packet need also be handled by UFO [ Upstream commit 2811ebac2521ceac84f2bdae402455baa6a7fb47 ] In the following scenario the socket is corked: If the first UDP packet is larger then the mtu we try to append it to the write queue via ip6_ufo_append_data. A following packet, which is smaller than the mtu would be appended to the already queued up gso-skb via plain ip6_append_data. This causes random memory corruptions. In ip6_ufo_append_data we also have to be careful to not queue up the same skb multiple times. So setup the gso frame only when no first skb is available. This also fixes a shortcoming where we add the current packet's length to cork->length but return early because of a packet > mtu with dontfrag set (instead of sutracting it again). Found with trinity. Cc: YOSHIFUJI Hideaki Signed-off-by: Hannes Frederic Sowa Reported-by: Dmitry Vyukov Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman via-rhine: fix VLAN priority field (PCP, IEEE 802.1p) [ Upstream commit 207070f5221e2a901d56a49df9cde47d9b716cd7 ] Outgoing packets sent by via-rhine have their VLAN PCP field off by one (when hardware acceleration is enabled). The TX descriptor expects only VID and PCP (without a CFI/DEI bit). Peter Boström noticed and reported the bug. Signed-off-by: Roger Luethi Cc: Peter Boström Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman dm9601: fix IFF_ALLMULTI handling [ Upstream commit bf0ea6380724beb64f27a722dfc4b0edabff816e ] Pass-all-multicast is controlled by bit 3 in RX control, not bit 2 (pass undersized frames). Reported-by: Joseph Chang Signed-off-by: Peter Korsgaard Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman bonding: Fix broken promiscuity reference counting issue [ Upstream commit 5a0068deb611109c5ba77358be533f763f395ee4 ] Recently grabbed this report: https://bugzilla.redhat.com/show_bug.cgi?id=1005567 Of an issue in which the bonding driver, with an attached vlan encountered the following errors when bond0 was taken down and back up: dummy1: promiscuity touches roof, set promiscuity failed. promiscuity feature of device might be broken. The error occurs because, during __bond_release_one, if we release our last slave, we take on a random mac address and issue a NETDEV_CHANGEADDR notification. With an attached vlan, the vlan may see that the vlan and bond mac address were in sync, but no longer are. This triggers a call to dev_uc_add and dev_set_rx_mode, which enables IFF_PROMISC on the bond device. Then, when we complete __bond_release_one, we use the current state of the bond flags to determine if we should decrement the promiscuity of the releasing slave. But since the bond changed promiscuity state during the release operation, we incorrectly decrement the slave promisc count when it wasn't in promiscuous mode to begin with, causing the above error Fix is pretty simple, just cache the bonding flags at the start of the function and use those when determining the need to set promiscuity. This is also needed for the ALLMULTI flag Reported-by: Mark Wu CC: Jay Vosburgh CC: Andy Gospodarek CC: Mark Wu CC: "David S. Miller" Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman ipv4 igmp: use in_dev_put in timer handlers instead of __in_dev_put [ Upstream commit e2401654dd0f5f3fb7a8d80dad9554d73d7ca394 ] It is possible for the timer handlers to run after the call to ip_mc_down so use in_dev_put instead of __in_dev_put in the handler function in order to do proper cleanup when the refcnt reaches 0. Otherwise, the refcnt can reach zero without the in_device being destroyed and we end up leaking a reference to the net_device and see messages like the following, unregister_netdevice: waiting for eth0 to become free. Usage count = 1 Tested on linux-3.4.43. Signed-off-by: Salam Noureddine Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman ipv6 mcast: use in6_dev_put in timer handlers instead of __in6_dev_put [ Upstream commit 9260d3e1013701aa814d10c8fc6a9f92bd17d643 ] It is possible for the timer handlers to run after the call to ipv6_mc_down so use in6_dev_put instead of __in6_dev_put in the handler function in order to do proper cleanup when the refcnt reaches 0. Otherwise, the refcnt can reach zero without the inet6_dev being destroyed and we end up leaking a reference to the net_device and see messages like the following, unregister_netdevice: waiting for eth0 to become free. Usage count = 1 Tested on linux-3.4.43. Signed-off-by: Salam Noureddine Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman ll_temac: Reset dma descriptors indexes on ndo_open [ Upstream commit 7167cf0e8cd10287b7912b9ffcccd9616f382922 ] The dma descriptors indexes are only initialized on the probe function. If a packet is on the buffer when temac_stop is called, the dma descriptors indexes can be left on a incorrect state where no other package can be sent. So an interface could be left in an usable state after ifdow/ifup. This patch makes sure that the descriptors indexes are in a proper status when the device is open. Signed-off-by: Ricardo Ribalda Delgado Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman ASoC: max98095: a couple array underflows commit f8d7b13e14357ed19d2ca2799539600418dc3939 upstream. The ->put() function are called from snd_ctl_elem_write() with user supplied data. The limit checks here could underflow leading to a crash. Signed-off-by: Dan Carpenter Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman ASoC: 88pm860x: array overflow in snd_soc_put_volsw_2r_st() commit d967967e8d1116fb38bad25e58714b5dddd03cca upstream. This is called from snd_ctl_elem_write() with user supplied data so we need to add some bounds checking. Signed-off-by: Dan Carpenter Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman powerpc/iommu: Use GFP_KERNEL instead of GFP_ATOMIC in iommu_init_table() commit 1cf389df090194a0976dc867b7fffe99d9d490cb upstream. Under heavy (DLPAR?) stress, we tripped this panic() in arch/powerpc/kernel/iommu.c::iommu_init_table(): page = alloc_pages_node(nid, GFP_ATOMIC, get_order(sz)); if (!page) panic("iommu_init_table: Can't allocate %ld bytes\n", sz); Before the panic() we got a page allocation failure for an order-2 allocation. There appears to be memory free, but perhaps not in the ATOMIC context. I looked through all the call-sites of iommu_init_table() and didn't see any obvious reason to need an ATOMIC allocation. Most call-sites in fact have an explicit GFP_KERNEL allocation shortly before the call to iommu_init_table(), indicating we are not in an atomic context. There is some indirection for some paths, but I didn't see any locks indicating that GFP_KERNEL is inappropriate. With this change under the same conditions, we have not been able to reproduce the panic. Signed-off-by: Nishanth Aravamudan Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Greg Kroah-Hartman powerpc/vio: Fix modalias_show return values commit e82b89a6f19bae73fb064d1b3dd91fcefbb478f4 upstream. modalias_show() should return an empty string on error, not -ENODEV. This causes the following false and annoying error: > find /sys/devices -name modalias -print0 | xargs -0 cat >/dev/null cat: /sys/devices/vio/4000/modalias: No such device cat: /sys/devices/vio/4001/modalias: No such device cat: /sys/devices/vio/4002/modalias: No such device cat: /sys/devices/vio/4004/modalias: No such device cat: /sys/devices/vio/modalias: No such device Signed-off-by: Prarit Bhargava Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Greg Kroah-Hartman powerpc: Fix parameter clobber in csum_partial_copy_generic() commit d9813c3681a36774b254c0cdc9cce53c9e22c756 upstream. The csum_partial_copy_generic() uses register r7 to adjust the remaining bytes to process. Unfortunately, r7 also holds a parameter, namely the address of the flag to set in case of access exceptions while reading the source buffer. Lacking a quantum implementation of PowerPC, this commit instead uses register r9 to do the adjusting, leaving r7's pointer uncorrupted. Signed-off-by: Paul E. McKenney Signed-off-by: Anton Blanchard Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Greg Kroah-Hartman Bluetooth: Fix security level for peripheral role commit f8776218e8546397be64ad2bc0ebf4748522d6e3 upstream. While playing the peripheral role, the host gets a LE Long Term Key Request Event from the controller when a connection is established with a bonded device. The host then informs the LTK which should be used for the connection. Once the link is encrypted, the host gets an Encryption Change Event. Therefore we should set conn->pending_sec_level instead of conn-> sec_level in hci_le_ltk_request_evt. This way, conn->sec_level is properly updated in hci_encrypt_change_evt. Moreover, since we have a LTK associated to the device, we have at least BT_SECURITY_MEDIUM security level. Signed-off-by: Andre Guedes Signed-off-by: Gustavo Padovan Signed-off-by: Greg Kroah-Hartman Conflicts: net/bluetooth/hci_event.c Bluetooth: Fix encryption key size for peripheral role commit 89cbb4da0abee2f39d75f67f9fd57f7410c8b65c upstream. This patch fixes the connection encryption key size information when the host is playing the peripheral role. We should set conn->enc_key_ size in hci_le_ltk_request_evt, otherwise it is left uninitialized. Signed-off-by: Andre Guedes Signed-off-by: Gustavo Padovan Signed-off-by: Greg Kroah-Hartman esp_scsi: Fix tag state corruption when autosensing. [ Upstream commit 21af8107f27878813d0364733c0b08813c2c192a ] Meelis Roos reports a crash in esp_free_lun_tag() in the presense of a disk which has died. The issue is that when we issue an autosense command, we do so by hijacking the original command that caused the check-condition. When we do so we clear out the ent->tag[] array when we issue it via find_and_prep_issuable_command(). This is so that the autosense command is forced to be issued non-tagged. That is problematic, because it is the value of ent->tag[] which determines whether we issued the original scsi command as tagged vs. non-tagged (see esp_alloc_lun_tag()). And that, in turn, is what trips up the sanity checks in esp_free_lun_tag(). That function needs the original ->tag[] values in order to free up the tag slot properly. Fix this by remembering the original command's tag values, and having esp_alloc_lun_tag() and esp_free_lun_tag() use them. Reported-by: Meelis Roos Tested-by: Meelis Roos Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman sparc64: Fix ITLB handler of null page [ Upstream commit 1c2696cdaad84580545a2e9c0879ff597880b1a9 ] 1)Use kvmap_itlb_longpath instead of kvmap_dtlb_longpath. 2)Handle page #0 only, don't handle page #1: bleu -> blu (KERNBASE is 0x400000, so #1 does not exist too. But everything is possible in the future. Fix to not to have problems later.) 3)Remove unused kvmap_itlb_nonlinear. Signed-off-by: Kirill Tkhai CC: David Miller Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman sparc64: Remove RWSEM export leftovers [ Upstream commit 61d9b9355b0d427bd1e732bd54628ff9103e496f ] The functions __down_read __down_read_trylock __down_write __down_write_trylock __up_read __up_write __downgrade_write are implemented inline, so remove corresponding EXPORT_SYMBOLs (They lead to compile errors on RT kernel). Signed-off-by: Kirill Tkhai CC: David Miller Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman sparc64: Fix off by one in trampoline TLB mapping installation loop. [ Upstream commit 63d499662aeec1864ec36d042aca8184ea6a938e ] Reported-by: Kirill Tkhai Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman sparc64: Fix not SRA'ed %o5 in 32-bit traced syscall [ Upstream commit ab2abda6377723e0d5fbbfe5f5aa16a5523344d1 ] (From v1 to v2: changed comment) On the way linux_sparc_syscall32->linux_syscall_trace32->goto 2f, register %o5 doesn't clear its second 32-bit. Fix that. Signed-off-by: Kirill Tkhai CC: David Miller Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman sparc32: Fix exit flag passed from traced sys_sigreturn [ Upstream commit 7a3b0f89e3fea680f93932691ca41a68eee7ab5e ] Pass 1 in %o1 to indicate that syscall_trace accounts exit. Signed-off-by: Kirill Tkhai CC: David Miller Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman USB: serial: option: Ignore card reader interface on Huawei E1750 commit eb2addd4044b4b2ce77693bde5bc810536dd96ee upstream. Hi, my Huawei 3G modem has an embedded Smart Card reader which causes trouble when the modem is being detected (a bunch of " (ttyUSBx): open blocked by driver for more than 7 seconds!" in messages.log). This trivial patch corrects the problem for me. The modem identifies itself as "12d1:1406 Huawei Technologies Co., Ltd. E1750" in lsusb although the description on the body says "Model E173u-1" Signed-off-by: Michal Malý Cc: Bjørn Mork Signed-off-by: Greg Kroah-Hartman ib_srpt: Destroy cm_id before destroying QP. commit 0b41d6ca616ddeb3b6c0a80e8770b6f53cd42806 upstream. This patch fixes a bug where ib_destroy_cm_id() was incorrectly being called after srpt_destroy_ch_ib() had destroyed the active QP. This would result in the following failed SRP_LOGIN_REQ messages: Received SRP_LOGIN_REQ with i_port_id 0x0:0x2590ffff1762bd, t_port_id 0x2c903009f8f40:0x2c903009f8f40 and it_iu_len 260 on port 1 (guid=0xfe80000000000000:0x2c903009f8f41) Received SRP_LOGIN_REQ with i_port_id 0x0:0x2590ffff1758f9, t_port_id 0x2c903009f8f40:0x2c903009f8f40 and it_iu_len 260 on port 2 (guid=0xfe80000000000000:0x2c903009f8f42) Received SRP_LOGIN_REQ with i_port_id 0x0:0x2590ffff175941, t_port_id 0x2c903009f8f40:0x2c903009f8f40 and it_iu_len 260 on port 2 (guid=0xfe80000000000000:0x2c90300a3cfb2) Received SRP_LOGIN_REQ with i_port_id 0x0:0x2590ffff176299, t_port_id 0x2c903009f8f40:0x2c903009f8f40 and it_iu_len 260 on port 1 (guid=0xfe80000000000000:0x2c90300a3cfb1) mlx4_core 0000:84:00.0: command 0x19 failed: fw status = 0x9 rejected SRP_LOGIN_REQ because creating a new RDMA channel failed. Received SRP_LOGIN_REQ with i_port_id 0x0:0x2590ffff176299, t_port_id 0x2c903009f8f40:0x2c903009f8f40 and it_iu_len 260 on port 1 (guid=0xfe80000000000000:0x2c90300a3cfb1) mlx4_core 0000:84:00.0: command 0x19 failed: fw status = 0x9 rejected SRP_LOGIN_REQ because creating a new RDMA channel failed. Received SRP_LOGIN_REQ with i_port_id 0x0:0x2590ffff176299, t_port_id 0x2c903009f8f40:0x2c903009f8f40 and it_iu_len 260 on port 1 (guid=0xfe80000000000000:0x2c90300a3cfb1) Reported-by: Navin Ahuja Signed-off-by: Nicholas Bellinger Signed-off-by: Greg Kroah-Hartman ib_srpt: always set response for task management commit c807f64340932e19f0d2ac9b30c8381e1f60663a upstream. The SRP specification requires: "Response data shall be provided in any SRP_RSP response that is sent in response to an SRP_TSK_MGMT request (see 6.7). The information in the RSP_CODE field (see table 24) shall indicate the completion status of the task management function." So fix this to avoid the SRP initiator interprets task management functions that succeeded as failed. Signed-off-by: Jack Wang Signed-off-by: Nicholas Bellinger Signed-off-by: Greg Kroah-Hartman rtlwifi: Align private space in rtl_priv struct commit 60ce314d1750fef843e9db70050e09e49f838b69 upstream. The private array at the end of the rtl_priv struct is not aligned. On ARM architecture, this causes an alignment trap and is fixed by aligning that array with __align(sizeof(void *)). That should properly align that space according to the requirements of all architectures. Reported-by: Jason Andrews Tested-by: Jason Andrews Signed-off-by: Larry Finger Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman p54usb: add USB ID for Corega WLUSB2GTST USB adapter commit 1e43692cdb7cc445d6347d8a5207d9cef0c71434 upstream. Added USB ID for Corega WLUSB2GTST USB adapter. Reported-by: Joerg Kalisch Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman dmaengine: imx-dma: fix lockdep issue between irqhandler and tasklet commit 5a276fa6bdf82fd442046969603968c83626ce0b upstream. The tasklet and irqhandler are using spin_lock while other routines are using spin_lock_irqsave/restore. This leads to lockdep issues as described bellow. This patch is changing the code to use spinlock_irq_save/restore in both code pathes. As imxdma_xfer_desc always gets called with spin_lock_irqsave lock held, this patch also removes the spare call inside the routine to avoid double locking. [ 403.358162] ================================= [ 403.362549] [ INFO: inconsistent lock state ] [ 403.366945] 3.10.0-20130823+ #904 Not tainted [ 403.371331] --------------------------------- [ 403.375721] inconsistent {IN-HARDIRQ-W} -> {HARDIRQ-ON-W} usage. [ 403.381769] swapper/0 [HC0[0]:SC1[1]:HE1:SE0] takes: [ 403.386762] (&(&imxdma->lock)->rlock){?.-...}, at: [] imxdma_tasklet+0x20/0x134 [ 403.395201] {IN-HARDIRQ-W} state was registered at: [ 403.400108] [] mark_lock+0x2a0/0x6b4 [ 403.404798] [] __lock_acquire+0x650/0x1a64 [ 403.410004] [] lock_acquire+0x94/0xa8 [ 403.414773] [] _raw_spin_lock+0x54/0x8c [ 403.419720] [] dma_irq_handler+0x78/0x254 [ 403.424845] [] handle_irq_event_percpu+0x38/0x1b4 [ 403.430670] [] handle_irq_event+0x44/0x64 [ 403.435789] [] handle_level_irq+0xd8/0xf0 [ 403.440903] [] generic_handle_irq+0x28/0x38 [ 403.446194] [] handle_IRQ+0x68/0x8c [ 403.450789] [] avic_handle_irq+0x3c/0x48 [ 403.455811] [] __irq_svc+0x44/0x74 [ 403.460314] [] cpu_startup_entry+0x88/0xf4 [ 403.465525] [] rest_init+0xb8/0xe0 [ 403.470045] [] start_kernel+0x28c/0x2d4 [ 403.474986] [] 0xa0008040 [ 403.478709] irq event stamp: 50854 [ 403.482140] hardirqs last enabled at (50854): [] tasklet_action+0x38/0xdc [ 403.489954] hardirqs last disabled at (50853): [] tasklet_action+0x20/0xdc [ 403.497761] softirqs last enabled at (50850): [] _local_bh_enable+0x14/0x18 [ 403.505741] softirqs last disabled at (50851): [] irq_exit+0x88/0xdc [ 403.513026] [ 403.513026] other info that might help us debug this: [ 403.519593] Possible unsafe locking scenario: [ 403.519593] [ 403.525548] CPU0 [ 403.528020] ---- [ 403.530491] lock(&(&imxdma->lock)->rlock); [ 403.534828] [ 403.537474] lock(&(&imxdma->lock)->rlock); [ 403.541983] [ 403.541983] *** DEADLOCK *** [ 403.541983] [ 403.547951] no locks held by swapper/0. [ 403.551813] [ 403.551813] stack backtrace: [ 403.556222] CPU: 0 PID: 0 Comm: swapper Not tainted 3.10.0-20130823+ #904 [ 403.563039] Backtrace: [ 403.565581] [] (dump_backtrace+0x0/0x10c) from [] (show_stack+0x18/0x1c) [ 403.574054] r6:00000000 r5:c05c51d8 r4:c040bd58 r3:00200000 [ 403.579872] [] (show_stack+0x0/0x1c) from [] (dump_stack+0x20/0x28) [ 403.587955] [] (dump_stack+0x0/0x28) from [] (print_usage_bug.part.28+0x224/0x28c) [ 403.597340] [] (print_usage_bug.part.28+0x0/0x28c) from [] (mark_lock+0x440/0x6b4) [ 403.606682] r8:c004a41c r7:00000000 r6:c040bd58 r5:c040c040 r4:00000002 [ 403.613566] [] (mark_lock+0x0/0x6b4) from [] (__lock_acquire+0x6cc/0x1a64) [ 403.622244] [] (__lock_acquire+0x0/0x1a64) from [] (lock_acquire+0x94/0xa8) [ 403.631010] [] (lock_acquire+0x0/0xa8) from [] (_raw_spin_lock+0x54/0x8c) [ 403.639614] [] (_raw_spin_lock+0x0/0x8c) from [] (imxdma_tasklet+0x20/0x134) [ 403.648434] r6:c3847010 r5:c040e890 r4:c38470d4 [ 403.653194] [] (imxdma_tasklet+0x0/0x134) from [] (tasklet_action+0x8c/0xdc) [ 403.662013] r8:c0599160 r7:00000000 r6:00000000 r5:c040e890 r4:c3847114 r3:c019d75c [ 403.670042] [] (tasklet_action+0x0/0xdc) from [] (__do_softirq+0xe4/0x1f0) [ 403.678687] r7:00000101 r6:c0402000 r5:c059919c r4:00000001 [ 403.684498] [] (__do_softirq+0x0/0x1f0) from [] (irq_exit+0x88/0xdc) [ 403.692652] [] (irq_exit+0x0/0xdc) from [] (handle_IRQ+0x6c/0x8c) [ 403.700514] r4:00000030 r3:00000110 [ 403.704192] [] (handle_IRQ+0x0/0x8c) from [] (avic_handle_irq+0x3c/0x48) [ 403.712664] r5:c0403f28 r4:c0593ebc [ 403.716343] [] (avic_handle_irq+0x0/0x48) from [] (__irq_svc+0x44/0x74) [ 403.724733] Exception stack(0xc0403f28 to 0xc0403f70) [ 403.729841] 3f20: 00000001 00000004 00000000 20000013 c0402000 c04104a8 [ 403.738078] 3f40: 00000002 c0b69620 a0004000 41069264 a03fb5f4 c0403f7c c0403f40 c0403f70 [ 403.746301] 3f60: c004b92c c0009e74 20000013 ffffffff [ 403.751383] r6:ffffffff r5:20000013 r4:c0009e74 r3:c004b92c [ 403.757210] [] (arch_cpu_idle+0x0/0x4c) from [] (cpu_startup_entry+0x88/0xf4) [ 403.766161] [] (cpu_startup_entry+0x0/0xf4) from [] (rest_init+0xb8/0xe0) [ 403.774753] [] (rest_init+0x0/0xe0) from [] (start_kernel+0x28c/0x2d4) [ 403.783051] r6:c03fc484 r5:ffffffff r4:c040a0e0 [ 403.787797] [] (start_kernel+0x0/0x2d4) from [] (0xa0008040) Signed-off-by: Michael Grzeschik Signed-off-by: Vinod Koul Cc: Jonghwan Choi Signed-off-by: Greg Kroah-Hartman dmaengine: imx-dma: fix callback path in tasklet commit fcaaba6c7136fe47e5a13352f99a64b019b6d2c5 upstream. We need to free the ld_active list head before jumping into the callback routine. Otherwise the callback could run into issue_pending and change our ld_active list head we just going to free. This will run the channel list into an currupted and undefined state. Signed-off-by: Michael Grzeschik Signed-off-by: Vinod Koul Cc: Jonghwan Choi Signed-off-by: Greg Kroah-Hartman dmaengine: imx-dma: fix slow path issue in prep_dma_cyclic commit edc530fe7ee5a562680615d2e7cd205879c751a7 upstream. When perparing cyclic_dma buffers by the sound layer, it will dump the following lockdep trace. The leading snd_pcm_action_single get called with read_lock_irq called. To fix this, we change the kcalloc call from GFP_KERNEL to GFP_ATOMIC. WARNING: at kernel/lockdep.c:2740 lockdep_trace_alloc+0xcc/0x114() DEBUG_LOCKS_WARN_ON(irqs_disabled_flags(flags)) Modules linked in: CPU: 0 PID: 832 Comm: aplay Not tainted 3.11.0-20130823+ #903 Backtrace: [] (dump_backtrace+0x0/0x10c) from [] (show_stack+0x18/0x1c) r6:c004c090 r5:00000009 r4:c2e0bd18 r3:00404000 [] (show_stack+0x0/0x1c) from [] (dump_stack+0x20/0x28) [] (dump_stack+0x0/0x28) from [] (warn_slowpath_common+0x54/0x70) [] (warn_slowpath_common+0x0/0x70) from [] (warn_slowpath_fmt+0x38/0x40) r8:00004000 r7:a3b90000 r6:000080d0 r5:60000093 r4:c2e0a000 r3:00000009 [] (warn_slowpath_fmt+0x0/0x40) from [] (lockdep_trace_alloc+0xcc/0x114) r3:c03955d8 r2:c03907db [] (lockdep_trace_alloc+0x0/0x114) from [] (__kmalloc+0x34/0x118) r6:000080d0 r5:c3800120 r4:000080d0 r3:c040a0f8 [] (__kmalloc+0x0/0x118) from [] (imxdma_prep_dma_cyclic+0x64/0x168) r7:a3b90000 r6:00000004 r5:c39d8420 r4:c3847150 [] (imxdma_prep_dma_cyclic+0x0/0x168) from [] (snd_dmaengine_pcm_trigger+0xa8/0x160) [] (snd_dmaengine_pcm_trigger+0x0/0x160) from [] (soc_pcm_trigger+0x90/0xb4) r8:c058c7b0 r7:c3b8140c r6:c39da560 r5:00000001 r4:c3b81000 [] (soc_pcm_trigger+0x0/0xb4) from [] (snd_pcm_do_start+0x2c/0x38) r7:00000000 r6:00000003 r5:c058c7b0 r4:c3b81000 [] (snd_pcm_do_start+0x0/0x38) from [] (snd_pcm_action_single+0x40/0x6c) [] (snd_pcm_action_single+0x0/0x6c) from [] (snd_pcm_action_lock_irq+0x7c/0x9c) r7:00000003 r6:c3b810f0 r5:c3b810f0 r4:c3b81000 [] (snd_pcm_action_lock_irq+0x0/0x9c) from [] (snd_pcm_common_ioctl1+0x7f8/0xfd0) r8:c3b7f888 r7:005407b8 r6:c2c991c0 r5:c3b81000 r4:c3b81000 r3:00004142 [] (snd_pcm_common_ioctl1+0x0/0xfd0) from [] (snd_pcm_playback_ioctl1+0x464/0x488) [] (snd_pcm_playback_ioctl1+0x0/0x488) from [] (snd_pcm_playback_ioctl+0x34/0x40) r8:c3b7f888 r7:00004142 r6:00000004 r5:c2c991c0 r4:005407b8 [] (snd_pcm_playback_ioctl+0x0/0x40) from [] (vfs_ioctl+0x30/0x44) [] (vfs_ioctl+0x0/0x44) from [] (do_vfs_ioctl+0x55c/0x5c0) [] (do_vfs_ioctl+0x0/0x5c0) from [] (SyS_ioctl+0x40/0x68) [] (SyS_ioctl+0x0/0x68) from [] (ret_fast_syscall+0x0/0x44) r8:c0009544 r7:00000036 r6:bedeaa58 r5:00000000 r4:000000c0 Signed-off-by: Michael Grzeschik Signed-off-by: Vinod Koul Cc: Jonghwan Choi Signed-off-by: Greg Kroah-Hartman staging: comedi: ni_65xx: (bug fix) confine insn_bits to one subdevice commit 677a31565692d596ef42ea589b53ba289abf4713 upstream. The `insn_bits` handler `ni_65xx_dio_insn_bits()` has a `for` loop that currently writes (optionally) and reads back up to 5 "ports" consisting of 8 channels each. It reads up to 32 1-bit channels but can only read and write a whole port at once - it needs to handle up to 5 ports as the first channel it reads might not be aligned on a port boundary. It breaks out of the loop early if the next port it handles is beyond the final port on the card. It also breaks out early on the 5th port in the loop if the first channel was aligned. Unfortunately, it doesn't check that the current port it is dealing with belongs to the comedi subdevice the `insn_bits` handler is acting on. That's a bug. Redo the `for` loop to terminate after the final port belonging to the subdevice, changing the loop variable in the process to simplify things a bit. The `for` loop could now try and handle more than 5 ports if the subdevice has more than 40 channels, but the test `if (bitshift >= 32)` ensures it will break out early after 4 or 5 ports (depending on whether the first channel is aligned on a port boundary). (`bitshift` will be between -7 and 7 inclusive on the first iteration, increasing by 8 for each subsequent operation.) Signed-off-by: Ian Abbott Signed-off-by: Greg Kroah-Hartman mm, show_mem: suppress page counts in non-blockable contexts commit 4b59e6c4730978679b414a8da61514a2518da512 upstream. On large systems with a lot of memory, walking all RAM to determine page types may take a half second or even more. In non-blockable contexts, the page allocator will emit a page allocation failure warning unless __GFP_NOWARN is specified. In such contexts, irqs are typically disabled and such a lengthy delay may even result in NMI watchdog timeouts. To fix this, suppress the page walk in such contexts when printing the page allocation failure warning. Signed-off-by: David Rientjes Cc: Mel Gorman Acked-by: Michal Hocko Cc: Dave Hansen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Cc: Xishi Qiu Signed-off-by: Greg Kroah-Hartman ACPI / IPMI: Fix atomic context requirement of ipmi_msg_handler() commit 06a8566bcf5cf7db9843a82cde7a33c7bf3947d9 upstream. This patch fixes the issues indicated by the test results that ipmi_msg_handler() is invoked in atomic context. BUG: scheduling while atomic: kipmi0/18933/0x10000100 Modules linked in: ipmi_si acpi_ipmi ... CPU: 3 PID: 18933 Comm: kipmi0 Tainted: G AW 3.10.0-rc7+ #2 Hardware name: QCI QSSC-S4R/QSSC-S4R, BIOS QSSC-S4R.QCI.01.00.0027.070120100606 07/01/2010 ffff8838245eea00 ffff88103fc63c98 ffffffff814c4a1e ffff88103fc63ca8 ffffffff814bfbab ffff88103fc63d28 ffffffff814c73e0 ffff88103933cbd4 0000000000000096 ffff88103fc63ce8 ffff88102f618000 ffff881035c01fd8 Call Trace: [] dump_stack+0x19/0x1b [] __schedule_bug+0x46/0x54 [] __schedule+0x83/0x59c [] __cond_resched+0x22/0x2d [] _cond_resched+0x14/0x1d [] mutex_lock+0x11/0x32 [] ? __default_send_IPI_dest_field.constprop.0+0x53/0x58 [] ipmi_msg_handler+0x23/0x166 [ipmi_si] [] deliver_response+0x55/0x5a [] handle_new_recv_msgs+0xb67/0xc65 [] ? read_tsc+0x9/0x19 [] ? _raw_spin_lock_irq+0xa/0xc [] ipmi_thread+0x5c/0x146 [ipmi_si] ... Also Tony Camuso says: We were getting occasional "Scheduling while atomic" call traces during boot on some systems. Problem was first seen on a Cisco C210 but we were able to reproduce it on a Cisco c220m3. Setting CONFIG_LOCKDEP and LOCKDEP_SUPPORT to 'y' exposed a lockdep around tx_msg_lock in acpi_ipmi.c struct acpi_ipmi_device. ================================= [ INFO: inconsistent lock state ] 2.6.32-415.el6.x86_64-debug-splck #1 --------------------------------- inconsistent {SOFTIRQ-ON-W} -> {IN-SOFTIRQ-W} usage. ksoftirqd/3/17 [HC0[0]:SC1[1]:HE1:SE0] takes: (&ipmi_device->tx_msg_lock){+.?...}, at: [] ipmi_msg_handler+0x71/0x126 {SOFTIRQ-ON-W} state was registered at: [] __lock_acquire+0x63c/0x1570 [] lock_acquire+0xa4/0x120 [] __mutex_lock_common+0x4c/0x400 [] mutex_lock_nested+0x4a/0x60 [] acpi_ipmi_space_handler+0x11b/0x234 [] acpi_ev_address_space_dispatch+0x170/0x1be The fix implemented by this change has been tested by Tony: Tested the patch in a boot loop with lockdep debug enabled and never saw the problem in over 400 reboots. Reported-and-tested-by: Tony Camuso Signed-off-by: Lv Zheng Reviewed-by: Huang Ying Signed-off-by: Rafael J. Wysocki Cc: Jonghwan Choi Signed-off-by: Greg Kroah-Hartman tile: use a more conservative __my_cpu_offset in CONFIG_PREEMPT commit f862eefec0b68e099a9fa58d3761ffb10bad97e1 upstream. It turns out the kernel relies on barrier() to force a reload of the percpu offset value. Since we can't easily modify the definition of barrier() to include "tp" as an output register, we instead provide a definition of __my_cpu_offset as extended assembly that includes a fake stack read to hazard against barrier(), forcing gcc to know that it must reread "tp" and recompute anything based on "tp" after a barrier. This fixes observed hangs in the slub allocator when we are looping on a percpu cmpxchg_double. A similar fix for ARMv7 was made in June in change 509eb76ebf97. Signed-off-by: Chris Metcalf Signed-off-by: Greg Kroah-Hartman Btrfs: change how we queue blocks for backref checking commit b6c60c8018c4e9beb2f83fc82c09f9d033766571 upstream. Previously we only added blocks to the list to have their backrefs checked if the level of the block is right above the one we are searching for. This is because we want to make sure we don't add the entire path up to the root to the lists to make sure we process things one at a time. This assumes that if any blocks in the path to the root are going to be not checked (shared in other words) then they will be in the level right above the current block on up. This isn't quite right though since we can have blocks higher up the list that are shared because they are attached to a reloc root. But we won't add this block to be checked and then later on we will BUG_ON(!upper->checked). So instead keep track of wether or not we've queued a block to be checked in this current search, and if we haven't go ahead and queue it to be checked. This patch fixed the panic I was seeing where we BUG_ON(!upper->checked). Thanks, Signed-off-by: Josef Bacik Signed-off-by: Chris Mason Signed-off-by: Greg Kroah-Hartman ext4: avoid hang when mounting non-journal filesystems with orphan list commit 0e9a9a1ad619e7e987815d20262d36a2f95717ca upstream. When trying to mount a file system which does not contain a journal, but which does have a orphan list containing an inode which needs to be truncated, the mount call with hang forever in ext4_orphan_cleanup() because ext4_orphan_del() will return immediately without removing the inode from the orphan list, leading to an uninterruptible loop in kernel code which will busy out one of the CPU's on the system. This can be trivially reproduced by trying to mount the file system found in tests/f_orphan_extents_inode/image.gz from the e2fsprogs source tree. If a malicious user were to put this on a USB stick, and mount it on a Linux desktop which has automatic mounts enabled, this could be considered a potential denial of service attack. (Not a big deal in practice, but professional paranoids worry about such things, and have even been known to allocate CVE numbers for such problems.) -js: This is a fix for CVE-2013-2015. Signed-off-by: "Theodore Ts'o" Reviewed-by: Zheng Liu Acked-by: Jan Kara Signed-off-by: Greg Kroah-Hartman Linux 3.4.66 --- Makefile | 2 +- arch/arm/mm/init.c | 3 ++ arch/ia64/mm/contig.c | 2 + arch/ia64/mm/discontig.c | 2 + arch/parisc/mm/init.c | 2 + arch/powerpc/kernel/iommu.c | 2 +- arch/powerpc/kernel/vio.c | 12 +++-- arch/powerpc/lib/checksum_64.S | 4 +- arch/sparc/kernel/entry.S | 2 +- arch/sparc/kernel/ktlb.S | 3 +- arch/sparc/kernel/syscalls.S | 8 ++-- arch/sparc/kernel/trampoline_64.S | 2 - arch/sparc/lib/ksyms.c | 9 ---- arch/tile/include/asm/percpu.h | 34 +++++++++++-- arch/unicore32/mm/init.c | 3 ++ drivers/acpi/acpi_ipmi.c | 24 ++++++---- drivers/block/cciss.c | 1 + drivers/block/cpqarray.c | 1 + drivers/dma/imx-dma.c | 31 ++++++------ drivers/infiniband/ulp/srpt/ib_srpt.c | 14 +++--- drivers/net/bonding/bond_main.c | 13 +++-- drivers/net/ethernet/freescale/gianfar.c | 11 ++++- drivers/net/ethernet/freescale/gianfar.h | 11 ++++- drivers/net/ethernet/via/via-rhine.c | 9 +++- drivers/net/ethernet/xilinx/ll_temac_main.c | 6 +++ drivers/net/ppp/pptp.c | 2 +- drivers/net/usb/dm9601.c | 2 +- drivers/net/wireless/p54/p54usb.c | 1 + drivers/net/wireless/rtlwifi/wifi.h | 2 +- drivers/scsi/esp_scsi.c | 14 +++--- drivers/scsi/esp_scsi.h | 1 + drivers/staging/comedi/drivers/ni_65xx.c | 26 +++++----- drivers/usb/serial/option.c | 3 ++ fs/btrfs/relocation.c | 14 +++--- fs/ext4/namei.c | 3 +- include/linux/mm.h | 3 +- include/net/ip.h | 12 +++-- include/net/ipip.h | 2 +- lib/show_mem.c | 3 ++ mm/page_alloc.c | 7 +++ net/bluetooth/hci_event.c | 5 ++ net/bridge/br_private.h | 1 + net/bridge/br_stp.c | 23 ++++++--- net/bridge/br_stp_if.c | 12 ++++- net/caif/cfctrl.c | 3 +- net/core/flow_dissector.c | 4 +- net/core/netpoll.c | 9 ++-- net/ipv4/igmp.c | 8 ++-- net/ipv4/inetpeer.c | 4 +- net/ipv4/ip_output.c | 8 ++-- net/ipv4/ipmr.c | 2 +- net/ipv4/raw.c | 2 +- net/ipv4/xfrm4_mode_tunnel.c | 2 +- net/ipv6/ip6_output.c | 53 +++++++++------------ net/ipv6/mcast.c | 4 +- net/netfilter/ipvs/ip_vs_xmit.c | 2 +- net/sctp/ipv6.c | 42 +++++----------- net/sctp/socket.c | 3 ++ sound/soc/codecs/88pm860x-codec.c | 3 ++ sound/soc/codecs/max98095.c | 4 +- 60 files changed, 297 insertions(+), 203 deletions(-) diff --git a/Makefile b/Makefile index 3464e548208..f0066e4c9bb 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 4 -SUBLEVEL = 65 +SUBLEVEL = 66 EXTRAVERSION = NAME = Saber-toothed Squirrel diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 57f41ca92d6..33361437cb9 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -104,6 +104,9 @@ void show_mem(unsigned int filter) printk("Mem-info:\n"); show_free_areas(filter); + if (filter & SHOW_MEM_FILTER_PAGE_COUNT) + return; + for_each_bank (i, mi) { struct membank *bank = &mi->bank[i]; unsigned int pfn1, pfn2; diff --git a/arch/ia64/mm/contig.c b/arch/ia64/mm/contig.c index 8d32e16a6dd..3359f1a1c43 100644 --- a/arch/ia64/mm/contig.c +++ b/arch/ia64/mm/contig.c @@ -47,6 +47,8 @@ void show_mem(unsigned int filter) printk(KERN_INFO "Mem-info:\n"); show_free_areas(filter); printk(KERN_INFO "Node memory in pages:\n"); + if (filter & SHOW_MEM_FILTER_PAGE_COUNT) + return; for_each_online_pgdat(pgdat) { unsigned long present; unsigned long flags; diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c index fb7548badcd..632e54d1cd7 100644 --- a/arch/ia64/mm/discontig.c +++ b/arch/ia64/mm/discontig.c @@ -623,6 +623,8 @@ void show_mem(unsigned int filter) printk(KERN_INFO "Mem-info:\n"); show_free_areas(filter); + if (filter & SHOW_MEM_FILTER_PAGE_COUNT) + return; printk(KERN_INFO "Node memory in pages:\n"); for_each_online_pgdat(pgdat) { unsigned long present; diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c index 82f364e209f..0b621625a6f 100644 --- a/arch/parisc/mm/init.c +++ b/arch/parisc/mm/init.c @@ -685,6 +685,8 @@ void show_mem(unsigned int filter) printk(KERN_INFO "Mem-info:\n"); show_free_areas(filter); + if (filter & SHOW_MEM_FILTER_PAGE_COUNT) + return; #ifndef CONFIG_DISCONTIGMEM i = max_mapnr; while (i-- > 0) { diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c index 359f078571c..b2f4a8ed098 100644 --- a/arch/powerpc/kernel/iommu.c +++ b/arch/powerpc/kernel/iommu.c @@ -501,7 +501,7 @@ struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid) /* number of bytes needed for the bitmap */ sz = (tbl->it_size + 7) >> 3; - page = alloc_pages_node(nid, GFP_ATOMIC, get_order(sz)); + page = alloc_pages_node(nid, GFP_KERNEL, get_order(sz)); if (!page) panic("iommu_init_table: Can't allocate %ld bytes\n", sz); tbl->it_map = page_address(page); diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c index a3a99901c8e..cfe0069bcfc 100644 --- a/arch/powerpc/kernel/vio.c +++ b/arch/powerpc/kernel/vio.c @@ -1341,11 +1341,15 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, const char *cp; dn = dev->of_node; - if (!dn) - return -ENODEV; + if (!dn) { + strcat(buf, "\n"); + return strlen(buf); + } cp = of_get_property(dn, "compatible", NULL); - if (!cp) - return -ENODEV; + if (!cp) { + strcat(buf, "\n"); + return strlen(buf); + } return sprintf(buf, "vio:T%sS%s\n", vio_dev->type, cp); } diff --git a/arch/powerpc/lib/checksum_64.S b/arch/powerpc/lib/checksum_64.S index 18245af38ae..afa2ebaee17 100644 --- a/arch/powerpc/lib/checksum_64.S +++ b/arch/powerpc/lib/checksum_64.S @@ -272,8 +272,8 @@ _GLOBAL(csum_partial_copy_generic) rldicl. r6,r3,64-1,64-2 /* r6 = (r3 & 0x3) >> 1 */ beq .Lcopy_aligned - li r7,4 - sub r6,r7,r6 + li r9,4 + sub r6,r9,r6 mtctr r6 1: diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S index f445e98463e..cfabc3d8821 100644 --- a/arch/sparc/kernel/entry.S +++ b/arch/sparc/kernel/entry.S @@ -1177,7 +1177,7 @@ sys_sigreturn: nop call syscall_trace - nop + mov 1, %o1 1: /* We don't want to muck with user registers like a diff --git a/arch/sparc/kernel/ktlb.S b/arch/sparc/kernel/ktlb.S index 79f31036484..7c007350017 100644 --- a/arch/sparc/kernel/ktlb.S +++ b/arch/sparc/kernel/ktlb.S @@ -25,11 +25,10 @@ kvmap_itlb: */ kvmap_itlb_4v: -kvmap_itlb_nonlinear: /* Catch kernel NULL pointer calls. */ sethi %hi(PAGE_SIZE), %g5 cmp %g4, %g5 - bleu,pn %xcc, kvmap_dtlb_longpath + blu,pn %xcc, kvmap_itlb_longpath nop KERN_TSB_LOOKUP_TL1(%g4, %g6, %g5, %g1, %g2, %g3, kvmap_itlb_load) diff --git a/arch/sparc/kernel/syscalls.S b/arch/sparc/kernel/syscalls.S index 7f5f65d0b3f..817187d4277 100644 --- a/arch/sparc/kernel/syscalls.S +++ b/arch/sparc/kernel/syscalls.S @@ -147,7 +147,7 @@ linux_syscall_trace32: srl %i4, 0, %o4 srl %i1, 0, %o1 srl %i2, 0, %o2 - ba,pt %xcc, 2f + ba,pt %xcc, 5f srl %i3, 0, %o3 linux_syscall_trace: @@ -177,13 +177,13 @@ linux_sparc_syscall32: srl %i1, 0, %o1 ! IEU0 Group ldx [%g6 + TI_FLAGS], %l0 ! Load - srl %i5, 0, %o5 ! IEU1 + srl %i3, 0, %o3 ! IEU0 srl %i2, 0, %o2 ! IEU0 Group andcc %l0, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT|_TIF_SYSCALL_TRACEPOINT), %g0 bne,pn %icc, linux_syscall_trace32 ! CTI mov %i0, %l5 ! IEU1 - call %l7 ! CTI Group brk forced - srl %i3, 0, %o3 ! IEU0 +5: call %l7 ! CTI Group brk forced + srl %i5, 0, %o5 ! IEU1 ba,a,pt %xcc, 3f /* Linux native system calls enter here... */ diff --git a/arch/sparc/kernel/trampoline_64.S b/arch/sparc/kernel/trampoline_64.S index da1b781b5e6..8fa84a3897c 100644 --- a/arch/sparc/kernel/trampoline_64.S +++ b/arch/sparc/kernel/trampoline_64.S @@ -131,7 +131,6 @@ startup_continue: clr %l5 sethi %hi(num_kernel_image_mappings), %l6 lduw [%l6 + %lo(num_kernel_image_mappings)], %l6 - add %l6, 1, %l6 mov 15, %l7 BRANCH_IF_ANY_CHEETAH(g1,g5,2f) @@ -224,7 +223,6 @@ niagara_lock_tlb: clr %l5 sethi %hi(num_kernel_image_mappings), %l6 lduw [%l6 + %lo(num_kernel_image_mappings)], %l6 - add %l6, 1, %l6 1: mov HV_FAST_MMU_MAP_PERM_ADDR, %o5 diff --git a/arch/sparc/lib/ksyms.c b/arch/sparc/lib/ksyms.c index f73c2240fe6..0b59bd3b977 100644 --- a/arch/sparc/lib/ksyms.c +++ b/arch/sparc/lib/ksyms.c @@ -125,15 +125,6 @@ EXPORT_SYMBOL(___copy_from_user); EXPORT_SYMBOL(___copy_in_user); EXPORT_SYMBOL(__clear_user); -/* RW semaphores */ -EXPORT_SYMBOL(__down_read); -EXPORT_SYMBOL(__down_read_trylock); -EXPORT_SYMBOL(__down_write); -EXPORT_SYMBOL(__down_write_trylock); -EXPORT_SYMBOL(__up_read); -EXPORT_SYMBOL(__up_write); -EXPORT_SYMBOL(__downgrade_write); - /* Atomic counter implementation. */ EXPORT_SYMBOL(atomic_add); EXPORT_SYMBOL(atomic_add_ret); diff --git a/arch/tile/include/asm/percpu.h b/arch/tile/include/asm/percpu.h index 63294f5a8ef..4f7ae39fa20 100644 --- a/arch/tile/include/asm/percpu.h +++ b/arch/tile/include/asm/percpu.h @@ -15,9 +15,37 @@ #ifndef _ASM_TILE_PERCPU_H #define _ASM_TILE_PERCPU_H -register unsigned long __my_cpu_offset __asm__("tp"); -#define __my_cpu_offset __my_cpu_offset -#define set_my_cpu_offset(tp) (__my_cpu_offset = (tp)) +register unsigned long my_cpu_offset_reg asm("tp"); + +#ifdef CONFIG_PREEMPT +/* + * For full preemption, we can't just use the register variable + * directly, since we need barrier() to hazard against it, causing the + * compiler to reload anything computed from a previous "tp" value. + * But we also don't want to use volatile asm, since we'd like the + * compiler to be able to cache the value across multiple percpu reads. + * So we use a fake stack read as a hazard against barrier(). + * The 'U' constraint is like 'm' but disallows postincrement. + */ +static inline unsigned long __my_cpu_offset(void) +{ + unsigned long tp; + register unsigned long *sp asm("sp"); + asm("move %0, tp" : "=r" (tp) : "U" (*sp)); + return tp; +} +#define __my_cpu_offset __my_cpu_offset() +#else +/* + * We don't need to hazard against barrier() since "tp" doesn't ever + * change with PREEMPT_NONE, and with PREEMPT_VOLUNTARY it only + * changes at function call points, at which we are already re-reading + * the value of "tp" due to "my_cpu_offset_reg" being a global variable. + */ +#define __my_cpu_offset my_cpu_offset_reg +#endif + +#define set_my_cpu_offset(tp) (my_cpu_offset_reg = (tp)) #include diff --git a/arch/unicore32/mm/init.c b/arch/unicore32/mm/init.c index de186bde897..644482882ba 100644 --- a/arch/unicore32/mm/init.c +++ b/arch/unicore32/mm/init.c @@ -66,6 +66,9 @@ void show_mem(unsigned int filter) printk(KERN_DEFAULT "Mem-info:\n"); show_free_areas(filter); + if (filter & SHOW_MEM_FILTER_PAGE_COUNT) + return; + for_each_bank(i, mi) { struct membank *bank = &mi->bank[i]; unsigned int pfn1, pfn2; diff --git a/drivers/acpi/acpi_ipmi.c b/drivers/acpi/acpi_ipmi.c index f40acef8026..a6977e12d57 100644 --- a/drivers/acpi/acpi_ipmi.c +++ b/drivers/acpi/acpi_ipmi.c @@ -39,6 +39,7 @@ #include #include #include +#include MODULE_AUTHOR("Zhao Yakui"); MODULE_DESCRIPTION("ACPI IPMI Opregion driver"); @@ -57,7 +58,7 @@ struct acpi_ipmi_device { struct list_head head; /* the IPMI request message list */ struct list_head tx_msg_list; - struct mutex tx_msg_lock; + spinlock_t tx_msg_lock; acpi_handle handle; struct pnp_dev *pnp_dev; ipmi_user_t user_interface; @@ -147,6 +148,7 @@ static void acpi_format_ipmi_msg(struct acpi_ipmi_msg *tx_msg, struct kernel_ipmi_msg *msg; struct acpi_ipmi_buffer *buffer; struct acpi_ipmi_device *device; + unsigned long flags; msg = &tx_msg->tx_message; /* @@ -177,10 +179,10 @@ static void acpi_format_ipmi_msg(struct acpi_ipmi_msg *tx_msg, /* Get the msgid */ device = tx_msg->device; - mutex_lock(&device->tx_msg_lock); + spin_lock_irqsave(&device->tx_msg_lock, flags); device->curr_msgid++; tx_msg->tx_msgid = device->curr_msgid; - mutex_unlock(&device->tx_msg_lock); + spin_unlock_irqrestore(&device->tx_msg_lock, flags); } static void acpi_format_ipmi_response(struct acpi_ipmi_msg *msg, @@ -242,6 +244,7 @@ static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) int msg_found = 0; struct acpi_ipmi_msg *tx_msg; struct pnp_dev *pnp_dev = ipmi_device->pnp_dev; + unsigned long flags; if (msg->user != ipmi_device->user_interface) { dev_warn(&pnp_dev->dev, "Unexpected response is returned. " @@ -250,7 +253,7 @@ static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) ipmi_free_recv_msg(msg); return; } - mutex_lock(&ipmi_device->tx_msg_lock); + spin_lock_irqsave(&ipmi_device->tx_msg_lock, flags); list_for_each_entry(tx_msg, &ipmi_device->tx_msg_list, head) { if (msg->msgid == tx_msg->tx_msgid) { msg_found = 1; @@ -258,7 +261,7 @@ static void ipmi_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) } } - mutex_unlock(&ipmi_device->tx_msg_lock); + spin_unlock_irqrestore(&ipmi_device->tx_msg_lock, flags); if (!msg_found) { dev_warn(&pnp_dev->dev, "Unexpected response (msg id %ld) is " "returned.\n", msg->msgid); @@ -378,6 +381,7 @@ acpi_ipmi_space_handler(u32 function, acpi_physical_address address, struct acpi_ipmi_device *ipmi_device = handler_context; int err, rem_time; acpi_status status; + unsigned long flags; /* * IPMI opregion message. * IPMI message is firstly written to the BMC and system software @@ -395,9 +399,9 @@ acpi_ipmi_space_handler(u32 function, acpi_physical_address address, return AE_NO_MEMORY; acpi_format_ipmi_msg(tx_msg, address, value); - mutex_lock(&ipmi_device->tx_msg_lock); + spin_lock_irqsave(&ipmi_device->tx_msg_lock, flags); list_add_tail(&tx_msg->head, &ipmi_device->tx_msg_list); - mutex_unlock(&ipmi_device->tx_msg_lock); + spin_unlock_irqrestore(&ipmi_device->tx_msg_lock, flags); err = ipmi_request_settime(ipmi_device->user_interface, &tx_msg->addr, tx_msg->tx_msgid, @@ -413,9 +417,9 @@ acpi_ipmi_space_handler(u32 function, acpi_physical_address address, status = AE_OK; end_label: - mutex_lock(&ipmi_device->tx_msg_lock); + spin_lock_irqsave(&ipmi_device->tx_msg_lock, flags); list_del(&tx_msg->head); - mutex_unlock(&ipmi_device->tx_msg_lock); + spin_unlock_irqrestore(&ipmi_device->tx_msg_lock, flags); kfree(tx_msg); return status; } @@ -457,7 +461,7 @@ static void acpi_add_ipmi_device(struct acpi_ipmi_device *ipmi_device) INIT_LIST_HEAD(&ipmi_device->head); - mutex_init(&ipmi_device->tx_msg_lock); + spin_lock_init(&ipmi_device->tx_msg_lock); INIT_LIST_HEAD(&ipmi_device->tx_msg_list); ipmi_install_space_handler(ipmi_device); diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index d3446f628d5..d7ad86536b3 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -1186,6 +1186,7 @@ static int cciss_ioctl32_passthru(struct block_device *bdev, fmode_t mode, int err; u32 cp; + memset(&arg64, 0, sizeof(arg64)); err = 0; err |= copy_from_user(&arg64.LUN_info, &arg32->LUN_info, diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c index 9125bbeacd4..504bc16e450 100644 --- a/drivers/block/cpqarray.c +++ b/drivers/block/cpqarray.c @@ -1195,6 +1195,7 @@ static int ida_locked_ioctl(struct block_device *bdev, fmode_t mode, unsigned in ida_pci_info_struct pciinfo; if (!arg) return -EINVAL; + memset(&pciinfo, 0, sizeof(pciinfo)); pciinfo.bus = host->pci_dev->bus->number; pciinfo.dev_fn = host->pci_dev->devfn; pciinfo.board_id = host->board_id; diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c index 180f5235acc..d5ce45339b1 100644 --- a/drivers/dma/imx-dma.c +++ b/drivers/dma/imx-dma.c @@ -373,17 +373,18 @@ static void dma_irq_handle_channel(struct imxdma_channel *imxdmac) struct imxdma_engine *imxdma = imxdmac->imxdma; int chno = imxdmac->channel; struct imxdma_desc *desc; + unsigned long flags; - spin_lock(&imxdma->lock); + spin_lock_irqsave(&imxdma->lock, flags); if (list_empty(&imxdmac->ld_active)) { - spin_unlock(&imxdma->lock); + spin_unlock_irqrestore(&imxdma->lock, flags); goto out; } desc = list_first_entry(&imxdmac->ld_active, struct imxdma_desc, node); - spin_unlock(&imxdma->lock); + spin_unlock_irqrestore(&imxdma->lock, flags); if (desc->sg) { u32 tmp; @@ -455,7 +456,6 @@ static int imxdma_xfer_desc(struct imxdma_desc *d) { struct imxdma_channel *imxdmac = to_imxdma_chan(d->desc.chan); struct imxdma_engine *imxdma = imxdmac->imxdma; - unsigned long flags; int slot = -1; int i; @@ -463,7 +463,6 @@ static int imxdma_xfer_desc(struct imxdma_desc *d) switch (d->type) { case IMXDMA_DESC_INTERLEAVED: /* Try to get a free 2D slot */ - spin_lock_irqsave(&imxdma->lock, flags); for (i = 0; i < IMX_DMA_2D_SLOTS; i++) { if ((imxdma->slots_2d[i].count > 0) && ((imxdma->slots_2d[i].xsr != d->x) || @@ -473,10 +472,8 @@ static int imxdma_xfer_desc(struct imxdma_desc *d) slot = i; break; } - if (slot < 0) { - spin_unlock_irqrestore(&imxdma->lock, flags); + if (slot < 0) return -EBUSY; - } imxdma->slots_2d[slot].xsr = d->x; imxdma->slots_2d[slot].ysr = d->y; @@ -485,7 +482,6 @@ static int imxdma_xfer_desc(struct imxdma_desc *d) imxdmac->slot_2d = slot; imxdmac->enabled_2d = true; - spin_unlock_irqrestore(&imxdma->lock, flags); if (slot == IMX_DMA_2D_SLOT_A) { d->config_mem &= ~CCR_MSEL_B; @@ -561,18 +557,17 @@ static void imxdma_tasklet(unsigned long data) struct imxdma_channel *imxdmac = (void *)data; struct imxdma_engine *imxdma = imxdmac->imxdma; struct imxdma_desc *desc; + unsigned long flags; - spin_lock(&imxdma->lock); + spin_lock_irqsave(&imxdma->lock, flags); if (list_empty(&imxdmac->ld_active)) { /* Someone might have called terminate all */ - goto out; + spin_unlock_irqrestore(&imxdma->lock, flags); + return; } desc = list_first_entry(&imxdmac->ld_active, struct imxdma_desc, node); - if (desc->desc.callback) - desc->desc.callback(desc->desc.callback_param); - /* If we are dealing with a cyclic descriptor keep it on ld_active * and dont mark the descripor as complete. * Only in non-cyclic cases it would be marked as complete @@ -599,7 +594,11 @@ static void imxdma_tasklet(unsigned long data) __func__, imxdmac->channel); } out: - spin_unlock(&imxdma->lock); + spin_unlock_irqrestore(&imxdma->lock, flags); + + if (desc->desc.callback) + desc->desc.callback(desc->desc.callback_param); + } static int imxdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, @@ -823,7 +822,7 @@ static struct dma_async_tx_descriptor *imxdma_prep_dma_cyclic( kfree(imxdmac->sg_list); imxdmac->sg_list = kcalloc(periods + 1, - sizeof(struct scatterlist), GFP_KERNEL); + sizeof(struct scatterlist), GFP_ATOMIC); if (!imxdmac->sg_list) return NULL; diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c index 78fc3ec79db..c34d362a0a3 100644 --- a/drivers/infiniband/ulp/srpt/ib_srpt.c +++ b/drivers/infiniband/ulp/srpt/ib_srpt.c @@ -1610,7 +1610,7 @@ static int srpt_build_tskmgmt_rsp(struct srpt_rdma_ch *ch, int resp_data_len; int resp_len; - resp_data_len = (rsp_code == SRP_TSK_MGMT_SUCCESS) ? 0 : 4; + resp_data_len = 4; resp_len = sizeof(*srp_rsp) + resp_data_len; srp_rsp = ioctx->ioctx.buf; @@ -1622,11 +1622,9 @@ static int srpt_build_tskmgmt_rsp(struct srpt_rdma_ch *ch, + atomic_xchg(&ch->req_lim_delta, 0)); srp_rsp->tag = tag; - if (rsp_code != SRP_TSK_MGMT_SUCCESS) { - srp_rsp->flags |= SRP_RSP_FLAG_RSPVALID; - srp_rsp->resp_data_len = cpu_to_be32(resp_data_len); - srp_rsp->data[3] = rsp_code; - } + srp_rsp->flags |= SRP_RSP_FLAG_RSPVALID; + srp_rsp->resp_data_len = cpu_to_be32(resp_data_len); + srp_rsp->data[3] = rsp_code; return resp_len; } @@ -2373,6 +2371,8 @@ static void srpt_release_channel_work(struct work_struct *w) transport_deregister_session(ch->sess); ch->sess = NULL; + ib_destroy_cm_id(ch->cm_id); + srpt_destroy_ch_ib(ch); srpt_free_ioctx_ring((struct srpt_ioctx **)ch->ioctx_ring, @@ -2383,8 +2383,6 @@ static void srpt_release_channel_work(struct work_struct *w) list_del(&ch->list); spin_unlock_irq(&sdev->spinlock); - ib_destroy_cm_id(ch->cm_id); - if (ch->release_done) complete(ch->release_done); diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 80103bb47ca..098581afdd9 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1933,6 +1933,7 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) struct bonding *bond = netdev_priv(bond_dev); struct slave *slave, *oldcurrent; struct sockaddr addr; + int old_flags = bond_dev->flags; netdev_features_t old_features = bond_dev->features; /* slave is not a slave or master is not master of this slave */ @@ -2066,12 +2067,18 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) * already taken care of above when we detached the slave */ if (!USES_PRIMARY(bond->params.mode)) { - /* unset promiscuity level from slave */ - if (bond_dev->flags & IFF_PROMISC) + /* unset promiscuity level from slave + * NOTE: The NETDEV_CHANGEADDR call above may change the value + * of the IFF_PROMISC flag in the bond_dev, but we need the + * value of that flag before that change, as that was the value + * when this slave was attached, so we cache at the start of the + * function and use it here. Same goes for ALLMULTI below + */ + if (old_flags & IFF_PROMISC) dev_set_promiscuity(slave_dev, -1); /* unset allmulti level from slave */ - if (bond_dev->flags & IFF_ALLMULTI) + if (old_flags & IFF_ALLMULTI) dev_set_allmulti(slave_dev, -1); /* flush master's mc_list from slave */ diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c index 0819a740384..d5de9a474ae 100644 --- a/drivers/net/ethernet/freescale/gianfar.c +++ b/drivers/net/ethernet/freescale/gianfar.c @@ -394,7 +394,13 @@ static void gfar_init_mac(struct net_device *ndev) if (ndev->features & NETIF_F_IP_CSUM) tctrl |= TCTRL_INIT_CSUM; - tctrl |= TCTRL_TXSCHED_PRIO; + if (priv->prio_sched_en) + tctrl |= TCTRL_TXSCHED_PRIO; + else { + tctrl |= TCTRL_TXSCHED_WRRS; + gfar_write(®s->tr03wt, DEFAULT_WRRS_WEIGHT); + gfar_write(®s->tr47wt, DEFAULT_WRRS_WEIGHT); + } gfar_write(®s->tctrl, tctrl); @@ -1153,6 +1159,9 @@ static int gfar_probe(struct platform_device *ofdev) priv->rx_filer_enable = 1; /* Enable most messages by default */ priv->msg_enable = (NETIF_MSG_IFUP << 1 ) - 1; + /* use pritority h/w tx queue scheduling for single queue devices */ + if (priv->num_tx_queues == 1) + priv->prio_sched_en = 1; /* Carrier starts down, phylib will bring it up */ netif_carrier_off(dev); diff --git a/drivers/net/ethernet/freescale/gianfar.h b/drivers/net/ethernet/freescale/gianfar.h index 4c9f8d487db..348b6dd08f5 100644 --- a/drivers/net/ethernet/freescale/gianfar.h +++ b/drivers/net/ethernet/freescale/gianfar.h @@ -301,8 +301,16 @@ extern const char gfar_driver_version[]; #define TCTRL_TFCPAUSE 0x00000008 #define TCTRL_TXSCHED_MASK 0x00000006 #define TCTRL_TXSCHED_INIT 0x00000000 +/* priority scheduling */ #define TCTRL_TXSCHED_PRIO 0x00000002 +/* weighted round-robin scheduling (WRRS) */ #define TCTRL_TXSCHED_WRRS 0x00000004 +/* default WRRS weight and policy setting, + * tailored to the tr03wt and tr47wt registers: + * equal weight for all Tx Qs, measured in 64byte units + */ +#define DEFAULT_WRRS_WEIGHT 0x18181818 + #define TCTRL_INIT_CSUM (TCTRL_TUCSEN | TCTRL_IPCSEN) #define IEVENT_INIT_CLEAR 0xffffffff @@ -1098,7 +1106,8 @@ struct gfar_private { extended_hash:1, bd_stash_en:1, rx_filer_enable:1, - wol_en:1; /* Wake-on-LAN enabled */ + wol_en:1, /* Wake-on-LAN enabled */ + prio_sched_en:1; /* Enable priorty based Tx scheduling in Hw */ unsigned short padding; /* PHY stuff */ diff --git a/drivers/net/ethernet/via/via-rhine.c b/drivers/net/ethernet/via/via-rhine.c index 4c76db4f058..5fa0880e342 100644 --- a/drivers/net/ethernet/via/via-rhine.c +++ b/drivers/net/ethernet/via/via-rhine.c @@ -32,7 +32,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #define DRV_NAME "via-rhine" -#define DRV_VERSION "1.5.0" +#define DRV_VERSION "1.5.1" #define DRV_RELDATE "2010-10-09" #include @@ -1684,7 +1684,12 @@ static netdev_tx_t rhine_start_tx(struct sk_buff *skb, cpu_to_le32(TXDESC | (skb->len >= ETH_ZLEN ? skb->len : ETH_ZLEN)); if (unlikely(vlan_tx_tag_present(skb))) { - rp->tx_ring[entry].tx_status = cpu_to_le32((vlan_tx_tag_get(skb)) << 16); + u16 vid_pcp = vlan_tx_tag_get(skb); + + /* drop CFI/DEI bit, register needs VID and PCP */ + vid_pcp = (vid_pcp & VLAN_VID_MASK) | + ((vid_pcp & VLAN_PRIO_MASK) >> 1); + rp->tx_ring[entry].tx_status = cpu_to_le32((vid_pcp) << 16); /* request tagging */ rp->tx_ring[entry].desc_length |= cpu_to_le32(0x020000); } diff --git a/drivers/net/ethernet/xilinx/ll_temac_main.c b/drivers/net/ethernet/xilinx/ll_temac_main.c index d21591a2c59..5e5b791f12e 100644 --- a/drivers/net/ethernet/xilinx/ll_temac_main.c +++ b/drivers/net/ethernet/xilinx/ll_temac_main.c @@ -308,6 +308,12 @@ static int temac_dma_bd_init(struct net_device *ndev) lp->rx_bd_p + (sizeof(*lp->rx_bd_v) * (RX_BD_NUM - 1))); lp->dma_out(lp, TX_CURDESC_PTR, lp->tx_bd_p); + /* Init descriptor indexes */ + lp->tx_bd_ci = 0; + lp->tx_bd_next = 0; + lp->tx_bd_tail = 0; + lp->rx_bd_ci = 0; + return 0; out: diff --git a/drivers/net/ppp/pptp.c b/drivers/net/ppp/pptp.c index f617566bbba..8327cc596c3 100644 --- a/drivers/net/ppp/pptp.c +++ b/drivers/net/ppp/pptp.c @@ -281,7 +281,7 @@ static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb) nf_reset(skb); skb->ip_summed = CHECKSUM_NONE; - ip_select_ident(iph, &rt->dst, NULL); + ip_select_ident(skb, &rt->dst, NULL); ip_send_check(iph); ip_local_out(skb); diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c index b97226318ea..905b16faee4 100644 --- a/drivers/net/usb/dm9601.c +++ b/drivers/net/usb/dm9601.c @@ -384,7 +384,7 @@ static void dm9601_set_multicast(struct net_device *net) rx_ctl |= 0x02; } else if (net->flags & IFF_ALLMULTI || netdev_mc_count(net) > DM_MAX_MCAST) { - rx_ctl |= 0x04; + rx_ctl |= 0x08; } else if (!netdev_mc_empty(net)) { struct netdev_hw_addr *ha; diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index af30777ce31..c31ac08d647 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c @@ -83,6 +83,7 @@ static struct usb_device_id p54u_table[] = { {USB_DEVICE(0x06a9, 0x000e)}, /* Westell 802.11g USB (A90-211WG-01) */ {USB_DEVICE(0x06b9, 0x0121)}, /* Thomson SpeedTouch 121g */ {USB_DEVICE(0x0707, 0xee13)}, /* SMC 2862W-G version 2 */ + {USB_DEVICE(0x07aa, 0x0020)}, /* Corega WLUSB2GTST USB */ {USB_DEVICE(0x0803, 0x4310)}, /* Zoom 4410a */ {USB_DEVICE(0x083a, 0x4521)}, /* Siemens Gigaset USB Adapter 54 version 2 */ {USB_DEVICE(0x083a, 0x4531)}, /* T-Com Sinus 154 data II */ diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h index 717d3bad17d..38c51ea483a 100644 --- a/drivers/net/wireless/rtlwifi/wifi.h +++ b/drivers/net/wireless/rtlwifi/wifi.h @@ -1638,7 +1638,7 @@ struct rtl_priv { that it points to the data allocated beyond this structure like: rtl_pci_priv or rtl_usb_priv */ - u8 priv[0]; + u8 priv[0] __aligned(sizeof(void *)); }; #define rtl_priv(hw) (((struct rtl_priv *)(hw)->priv)) diff --git a/drivers/scsi/esp_scsi.c b/drivers/scsi/esp_scsi.c index 394ed9e79fd..4aa30d86ca9 100644 --- a/drivers/scsi/esp_scsi.c +++ b/drivers/scsi/esp_scsi.c @@ -530,7 +530,7 @@ static int esp_need_to_nego_sync(struct esp_target_data *tp) static int esp_alloc_lun_tag(struct esp_cmd_entry *ent, struct esp_lun_data *lp) { - if (!ent->tag[0]) { + if (!ent->orig_tag[0]) { /* Non-tagged, slot already taken? */ if (lp->non_tagged_cmd) return -EBUSY; @@ -564,9 +564,9 @@ static int esp_alloc_lun_tag(struct esp_cmd_entry *ent, return -EBUSY; } - BUG_ON(lp->tagged_cmds[ent->tag[1]]); + BUG_ON(lp->tagged_cmds[ent->orig_tag[1]]); - lp->tagged_cmds[ent->tag[1]] = ent; + lp->tagged_cmds[ent->orig_tag[1]] = ent; lp->num_tagged++; return 0; @@ -575,9 +575,9 @@ static int esp_alloc_lun_tag(struct esp_cmd_entry *ent, static void esp_free_lun_tag(struct esp_cmd_entry *ent, struct esp_lun_data *lp) { - if (ent->tag[0]) { - BUG_ON(lp->tagged_cmds[ent->tag[1]] != ent); - lp->tagged_cmds[ent->tag[1]] = NULL; + if (ent->orig_tag[0]) { + BUG_ON(lp->tagged_cmds[ent->orig_tag[1]] != ent); + lp->tagged_cmds[ent->orig_tag[1]] = NULL; lp->num_tagged--; } else { BUG_ON(lp->non_tagged_cmd != ent); @@ -667,6 +667,8 @@ static struct esp_cmd_entry *find_and_prep_issuable_command(struct esp *esp) ent->tag[0] = 0; ent->tag[1] = 0; } + ent->orig_tag[0] = ent->tag[0]; + ent->orig_tag[1] = ent->tag[1]; if (esp_alloc_lun_tag(ent, lp) < 0) continue; diff --git a/drivers/scsi/esp_scsi.h b/drivers/scsi/esp_scsi.h index 28e22acf87e..cd68805e8d7 100644 --- a/drivers/scsi/esp_scsi.h +++ b/drivers/scsi/esp_scsi.h @@ -271,6 +271,7 @@ struct esp_cmd_entry { #define ESP_CMD_FLAG_AUTOSENSE 0x04 /* Doing automatic REQUEST_SENSE */ u8 tag[2]; + u8 orig_tag[2]; u8 status; u8 message; diff --git a/drivers/staging/comedi/drivers/ni_65xx.c b/drivers/staging/comedi/drivers/ni_65xx.c index 403fc0997d3..8b564ad1731 100644 --- a/drivers/staging/comedi/drivers/ni_65xx.c +++ b/drivers/staging/comedi/drivers/ni_65xx.c @@ -411,29 +411,25 @@ static int ni_65xx_dio_insn_bits(struct comedi_device *dev, struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data) { - unsigned base_bitfield_channel; - const unsigned max_ports_per_bitfield = 5; + int base_bitfield_channel; unsigned read_bits = 0; - unsigned j; + int last_port_offset = ni_65xx_port_by_channel(s->n_chan - 1); + int port_offset; + if (insn->n != 2) return -EINVAL; base_bitfield_channel = CR_CHAN(insn->chanspec); - for (j = 0; j < max_ports_per_bitfield; ++j) { - const unsigned port_offset = - ni_65xx_port_by_channel(base_bitfield_channel) + j; - const unsigned port = - sprivate(s)->base_port + port_offset; - unsigned base_port_channel; + for (port_offset = ni_65xx_port_by_channel(base_bitfield_channel); + port_offset <= last_port_offset; port_offset++) { + unsigned port = sprivate(s)->base_port + port_offset; + int base_port_channel = port_offset * ni_65xx_channels_per_port; unsigned port_mask, port_data, port_read_bits; - int bitshift; - if (port >= ni_65xx_total_num_ports(board(dev))) + int bitshift = base_port_channel - base_bitfield_channel; + + if (bitshift >= 32) break; - base_port_channel = port_offset * ni_65xx_channels_per_port; port_mask = data[0]; port_data = data[1]; - bitshift = base_port_channel - base_bitfield_channel; - if (bitshift >= 32 || bitshift <= -32) - break; if (bitshift > 0) { port_mask >>= bitshift; port_data >>= bitshift; diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index a37f14ce52f..9def72f018e 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -81,6 +81,7 @@ static void option_instat_callback(struct urb *urb); #define HUAWEI_VENDOR_ID 0x12D1 #define HUAWEI_PRODUCT_E173 0x140C +#define HUAWEI_PRODUCT_E1750 0x1406 #define HUAWEI_PRODUCT_K4505 0x1464 #define HUAWEI_PRODUCT_K3765 0x1465 #define HUAWEI_PRODUCT_K4605 0x14C6 @@ -581,6 +582,8 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x1c23, USB_CLASS_COMM, 0x02, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E173, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t) &net_intf1_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1750, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t) &net_intf2_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x1441, USB_CLASS_COMM, 0x02, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x1442, USB_CLASS_COMM, 0x02, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_K4505, 0xff, 0xff, 0xff), diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index 646ee21bb03..92841a73c0e 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c @@ -684,6 +684,7 @@ struct backref_node *build_backref_tree(struct reloc_control *rc, int cowonly; int ret; int err = 0; + bool need_check = true; path1 = btrfs_alloc_path(); path2 = btrfs_alloc_path(); @@ -906,6 +907,7 @@ struct backref_node *build_backref_tree(struct reloc_control *rc, cur->bytenr); lower = cur; + need_check = true; for (; level < BTRFS_MAX_LEVEL; level++) { if (!path2->nodes[level]) { BUG_ON(btrfs_root_bytenr(&root->root_item) != @@ -949,14 +951,12 @@ struct backref_node *build_backref_tree(struct reloc_control *rc, /* * add the block to pending list if we - * need check its backrefs. only block - * at 'cur->level + 1' is added to the - * tail of pending list. this guarantees - * we check backrefs from lower level - * blocks to upper level blocks. + * need check its backrefs, we only do this once + * while walking up a tree as we will catch + * anything else later on. */ - if (!upper->checked && - level == cur->level + 1) { + if (!upper->checked && need_check) { + need_check = false; list_add_tail(&edge->list[UPPER], &list); } else diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 9fb3fae4898..54ad9a54cd8 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -2054,7 +2054,8 @@ int ext4_orphan_del(handle_t *handle, struct inode *inode) int err = 0; /* ext4_handle_valid() assumes a valid handle_t pointer */ - if (handle && !ext4_handle_valid(handle)) + if (handle && !ext4_handle_valid(handle) && + !(EXT4_SB(inode->i_sb)->s_mount_state & EXT4_ORPHAN_FS)) return 0; mutex_lock(&EXT4_SB(inode->i_sb)->s_orphan_lock); diff --git a/include/linux/mm.h b/include/linux/mm.h index cb67f136a6a..d8d2dbf0482 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -869,7 +869,8 @@ extern void pagefault_out_of_memory(void); * Flags passed to show_mem() and show_free_areas() to suppress output in * various contexts. */ -#define SHOW_MEM_FILTER_NODES (0x0001u) /* filter disallowed nodes */ +#define SHOW_MEM_FILTER_NODES (0x0001u) /* disallowed nodes */ +#define SHOW_MEM_FILTER_PAGE_COUNT (0x0002u) /* page type count */ extern void show_free_areas(unsigned int flags); extern bool skip_free_areas_node(unsigned int flags, int nid); diff --git a/include/net/ip.h b/include/net/ip.h index b53d65f24f7..0750bf7d424 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -266,9 +266,11 @@ int ip_dont_fragment(struct sock *sk, struct dst_entry *dst) extern void __ip_select_ident(struct iphdr *iph, struct dst_entry *dst, int more); -static inline void ip_select_ident(struct iphdr *iph, struct dst_entry *dst, struct sock *sk) +static inline void ip_select_ident(struct sk_buff *skb, struct dst_entry *dst, struct sock *sk) { - if (iph->frag_off & htons(IP_DF)) { + struct iphdr *iph = ip_hdr(skb); + + if ((iph->frag_off & htons(IP_DF)) && !skb->local_df) { /* This is only to work around buggy Windows95/2000 * VJ compression implementations. If the ID field * does not change, they drop every other packet in @@ -280,9 +282,11 @@ static inline void ip_select_ident(struct iphdr *iph, struct dst_entry *dst, str __ip_select_ident(iph, dst, 0); } -static inline void ip_select_ident_more(struct iphdr *iph, struct dst_entry *dst, struct sock *sk, int more) +static inline void ip_select_ident_more(struct sk_buff *skb, struct dst_entry *dst, struct sock *sk, int more) { - if (iph->frag_off & htons(IP_DF)) { + struct iphdr *iph = ip_hdr(skb); + + if ((iph->frag_off & htons(IP_DF)) && !skb->local_df) { if (sk && inet_sk(sk)->inet_daddr) { iph->id = htons(inet_sk(sk)->inet_id); inet_sk(sk)->inet_id += 1 + more; diff --git a/include/net/ipip.h b/include/net/ipip.h index a32654d5273..4dccfe3bf73 100644 --- a/include/net/ipip.h +++ b/include/net/ipip.h @@ -50,7 +50,7 @@ struct ip_tunnel_prl_entry { int pkt_len = skb->len - skb_transport_offset(skb); \ \ skb->ip_summed = CHECKSUM_NONE; \ - ip_select_ident(iph, &rt->dst, NULL); \ + ip_select_ident(skb, &rt->dst, NULL); \ \ err = ip_local_out(skb); \ if (likely(net_xmit_eval(err) == 0)) { \ diff --git a/lib/show_mem.c b/lib/show_mem.c index 4407f8c9b1f..b7c72311ad0 100644 --- a/lib/show_mem.c +++ b/lib/show_mem.c @@ -18,6 +18,9 @@ void show_mem(unsigned int filter) printk("Mem-Info:\n"); show_free_areas(filter); + if (filter & SHOW_MEM_FILTER_PAGE_COUNT) + return; + for_each_online_pgdat(pgdat) { unsigned long i, flags; diff --git a/mm/page_alloc.c b/mm/page_alloc.c index ffa73b550f7..338c6fc720b 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -1994,6 +1994,13 @@ void warn_alloc_failed(gfp_t gfp_mask, int order, const char *fmt, ...) debug_guardpage_minorder() > 0) return; + /* + * Walking all memory to count page types is very expensive and should + * be inhibited in non-blockable contexts. + */ + if (!(gfp_mask & __GFP_WAIT)) + filter |= SHOW_MEM_FILTER_PAGE_COUNT; + /* * This documents exceptions given to allocations in certain * contexts that are allowed to allocate outside current's set diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 50dfe0371a5..214117ca644 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -3311,6 +3311,11 @@ static inline void hci_le_ltk_request_evt(struct hci_dev *hdev, memcpy(cp.ltk, ltk->val, sizeof(ltk->val)); cp.handle = cpu_to_le16(conn->handle); conn->pin_length = ltk->pin_len; + conn->pending_sec_level = BT_SECURITY_HIGH; + else + conn->pending_sec_level = BT_SECURITY_MEDIUM; + + conn->enc_key_size = ltk->enc_size; hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp); diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 51e8826e78c..123700612da 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -501,6 +501,7 @@ extern struct net_bridge_port *br_get_port(struct net_bridge *br, extern void br_init_port(struct net_bridge_port *p); extern void br_become_designated_port(struct net_bridge_port *p); +extern void __br_set_forward_delay(struct net_bridge *br, unsigned long t); extern int br_set_forward_delay(struct net_bridge *br, unsigned long x); extern int br_set_hello_time(struct net_bridge *br, unsigned long x); extern int br_set_max_age(struct net_bridge *br, unsigned long x); diff --git a/net/bridge/br_stp.c b/net/bridge/br_stp.c index 8c836d96ba7..eca1c946ed1 100644 --- a/net/bridge/br_stp.c +++ b/net/bridge/br_stp.c @@ -189,7 +189,7 @@ static void br_record_config_information(struct net_bridge_port *p, p->designated_age = jiffies - bpdu->message_age; mod_timer(&p->message_age_timer, jiffies - + (p->br->max_age - bpdu->message_age)); + + (bpdu->max_age - bpdu->message_age)); } /* called under bridge lock */ @@ -517,18 +517,27 @@ int br_set_max_age(struct net_bridge *br, unsigned long val) } +void __br_set_forward_delay(struct net_bridge *br, unsigned long t) +{ + br->bridge_forward_delay = t; + if (br_is_root_bridge(br)) + br->forward_delay = br->bridge_forward_delay; +} + int br_set_forward_delay(struct net_bridge *br, unsigned long val) { unsigned long t = clock_t_to_jiffies(val); + int err = -ERANGE; + spin_lock_bh(&br->lock); if (br->stp_enabled != BR_NO_STP && (t < BR_MIN_FORWARD_DELAY || t > BR_MAX_FORWARD_DELAY)) - return -ERANGE; + goto unlock; - spin_lock_bh(&br->lock); - br->bridge_forward_delay = t; - if (br_is_root_bridge(br)) - br->forward_delay = br->bridge_forward_delay; + __br_set_forward_delay(br, t); + err = 0; + +unlock: spin_unlock_bh(&br->lock); - return 0; + return err; } diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c index f494496373d..f774796f7e5 100644 --- a/net/bridge/br_stp_if.c +++ b/net/bridge/br_stp_if.c @@ -129,6 +129,14 @@ static void br_stp_start(struct net_bridge *br) char *envp[] = { NULL }; r = call_usermodehelper(BR_STP_PROG, argv, envp, UMH_WAIT_PROC); + + spin_lock_bh(&br->lock); + + if (br->bridge_forward_delay < BR_MIN_FORWARD_DELAY) + __br_set_forward_delay(br, BR_MIN_FORWARD_DELAY); + else if (br->bridge_forward_delay < BR_MAX_FORWARD_DELAY) + __br_set_forward_delay(br, BR_MAX_FORWARD_DELAY); + if (r == 0) { br->stp_enabled = BR_USER_STP; br_debug(br, "userspace STP started\n"); @@ -137,10 +145,10 @@ static void br_stp_start(struct net_bridge *br) br_debug(br, "using kernel STP\n"); /* To start timers on any ports left in blocking */ - spin_lock_bh(&br->lock); br_port_state_selection(br); - spin_unlock_bh(&br->lock); } + + spin_unlock_bh(&br->lock); } static void br_stp_stop(struct net_bridge *br) diff --git a/net/caif/cfctrl.c b/net/caif/cfctrl.c index 5cf52225692..84efbe4aa06 100644 --- a/net/caif/cfctrl.c +++ b/net/caif/cfctrl.c @@ -288,9 +288,10 @@ int cfctrl_linkup_request(struct cflayer *layer, count = cfctrl_cancel_req(&cfctrl->serv.layer, user_layer); - if (count != 1) + if (count != 1) { pr_err("Could not remove request (%d)", count); return -ENODEV; + } } return 0; } diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index 96c5f0edb4c..0df746079a5 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c @@ -135,8 +135,8 @@ bool skb_flow_dissect(const struct sk_buff *skb, struct flow_keys *flow) if (poff >= 0) { __be32 *ports, _ports; - nhoff += poff; - ports = skb_header_pointer(skb, nhoff, sizeof(_ports), &_ports); + ports = skb_header_pointer(skb, nhoff + poff, + sizeof(_ports), &_ports); if (ports) flow->ports = *ports; } diff --git a/net/core/netpoll.c b/net/core/netpoll.c index f9f40b932e4..5e81c495fde 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -920,15 +920,14 @@ EXPORT_SYMBOL_GPL(__netpoll_cleanup); void netpoll_cleanup(struct netpoll *np) { - if (!np->dev) - return; - rtnl_lock(); + if (!np->dev) + goto out; __netpoll_cleanup(np); - rtnl_unlock(); - dev_put(np->dev); np->dev = NULL; +out: + rtnl_unlock(); } EXPORT_SYMBOL(netpoll_cleanup); diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 5dfecfd7d5e..c8e26992742 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -343,7 +343,7 @@ static struct sk_buff *igmpv3_newpack(struct net_device *dev, int size) pip->saddr = fl4.saddr; pip->protocol = IPPROTO_IGMP; pip->tot_len = 0; /* filled in later */ - ip_select_ident(pip, &rt->dst, NULL); + ip_select_ident(skb, &rt->dst, NULL); ((u8*)&pip[1])[0] = IPOPT_RA; ((u8*)&pip[1])[1] = 4; ((u8*)&pip[1])[2] = 0; @@ -687,7 +687,7 @@ static int igmp_send_report(struct in_device *in_dev, struct ip_mc_list *pmc, iph->daddr = dst; iph->saddr = fl4.saddr; iph->protocol = IPPROTO_IGMP; - ip_select_ident(iph, &rt->dst, NULL); + ip_select_ident(skb, &rt->dst, NULL); ((u8*)&iph[1])[0] = IPOPT_RA; ((u8*)&iph[1])[1] = 4; ((u8*)&iph[1])[2] = 0; @@ -709,7 +709,7 @@ static void igmp_gq_timer_expire(unsigned long data) in_dev->mr_gq_running = 0; igmpv3_send_report(in_dev, NULL); - __in_dev_put(in_dev); + in_dev_put(in_dev); } static void igmp_ifc_timer_expire(unsigned long data) @@ -721,7 +721,7 @@ static void igmp_ifc_timer_expire(unsigned long data) in_dev->mr_ifc_count--; igmp_ifc_start_timer(in_dev, IGMP_Unsolicited_Report_Interval); } - __in_dev_put(in_dev); + in_dev_put(in_dev); } static void igmp_ifc_event(struct in_device *in_dev) diff --git a/net/ipv4/inetpeer.c b/net/ipv4/inetpeer.c index dfba343b250..d63a9268cff 100644 --- a/net/ipv4/inetpeer.c +++ b/net/ipv4/inetpeer.c @@ -32,8 +32,8 @@ * At the moment of writing this notes identifier of IP packets is generated * to be unpredictable using this code only for packets subjected * (actually or potentially) to defragmentation. I.e. DF packets less than - * PMTU in size uses a constant ID and do not use this code (see - * ip_select_ident() in include/net/ip.h). + * PMTU in size when local fragmentation is disabled use a constant ID and do + * not use this code (see ip_select_ident() in include/net/ip.h). * * Route cache entries hold references to our nodes. * New cache entries get references via lookup by destination IP address in diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 4910176d24e..3bc4c978d7a 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -161,7 +161,7 @@ int ip_build_and_send_pkt(struct sk_buff *skb, struct sock *sk, iph->daddr = (opt && opt->opt.srr ? opt->opt.faddr : daddr); iph->saddr = saddr; iph->protocol = sk->sk_protocol; - ip_select_ident(iph, &rt->dst, sk); + ip_select_ident(skb, &rt->dst, sk); if (opt && opt->opt.optlen) { iph->ihl += opt->opt.optlen>>2; @@ -403,7 +403,7 @@ int ip_queue_xmit(struct sk_buff *skb, struct flowi *fl) ip_options_build(skb, &inet_opt->opt, inet->inet_daddr, rt, 0); } - ip_select_ident_more(iph, &rt->dst, sk, + ip_select_ident_more(skb, &rt->dst, sk, (skb_shinfo(skb)->gso_segs ?: 1) - 1); skb->priority = sk->sk_priority; @@ -1342,12 +1342,12 @@ struct sk_buff *__ip_make_skb(struct sock *sk, else ttl = ip_select_ttl(inet, &rt->dst); - iph = (struct iphdr *)skb->data; + iph = ip_hdr(skb); iph->version = 4; iph->ihl = 5; iph->tos = inet->tos; iph->frag_off = df; - ip_select_ident(iph, &rt->dst, sk); + ip_select_ident(skb, &rt->dst, sk); iph->ttl = ttl; iph->protocol = sk->sk_protocol; ip_copy_addrs(iph, fl4); diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 8626b645ec6..a0b7166badb 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c @@ -1573,7 +1573,7 @@ static void ip_encap(struct sk_buff *skb, __be32 saddr, __be32 daddr) iph->protocol = IPPROTO_IPIP; iph->ihl = 5; iph->tot_len = htons(skb->len); - ip_select_ident(iph, skb_dst(skb), NULL); + ip_select_ident(skb, skb_dst(skb), NULL); ip_send_check(iph); memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index 2fe0dc28ea9..c6b9ca651ab 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -384,7 +384,7 @@ static int raw_send_hdrinc(struct sock *sk, struct flowi4 *fl4, iph->check = 0; iph->tot_len = htons(length); if (!iph->id) - ip_select_ident(iph, &rt->dst, NULL); + ip_select_ident(skb, &rt->dst, NULL); iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl); } diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c index ed4bf11ef9f..938553efbf8 100644 --- a/net/ipv4/xfrm4_mode_tunnel.c +++ b/net/ipv4/xfrm4_mode_tunnel.c @@ -54,7 +54,7 @@ static int xfrm4_mode_tunnel_output(struct xfrm_state *x, struct sk_buff *skb) top_iph->frag_off = (flags & XFRM_STATE_NOPMTUDISC) ? 0 : (XFRM_MODE_SKB_CB(skb)->frag_off & htons(IP_DF)); - ip_select_ident(top_iph, dst->child, NULL); + ip_select_ident(skb, dst->child, NULL); top_iph->ttl = ip4_dst_hoplimit(dst->child); diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index f741f1cc8f7..f1bf29063cd 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -1129,6 +1129,8 @@ static inline int ip6_ufo_append_data(struct sock *sk, * udp datagram */ if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL) { + struct frag_hdr fhdr; + skb = sock_alloc_send_skb(sk, hh_len + fragheaderlen + transhdrlen + 20, (flags & MSG_DONTWAIT), &err); @@ -1149,12 +1151,6 @@ static inline int ip6_ufo_append_data(struct sock *sk, skb->ip_summed = CHECKSUM_PARTIAL; skb->csum = 0; - } - - err = skb_append_datato_frags(sk,skb, getfrag, from, - (length - transhdrlen)); - if (!err) { - struct frag_hdr fhdr; /* Specify the length of each IPv6 datagram fragment. * It has to be a multiple of 8. @@ -1165,15 +1161,10 @@ static inline int ip6_ufo_append_data(struct sock *sk, ipv6_select_ident(&fhdr, rt); skb_shinfo(skb)->ip6_frag_id = fhdr.identification; __skb_queue_tail(&sk->sk_write_queue, skb); - - return 0; } - /* There is not enough support do UPD LSO, - * so follow normal path - */ - kfree_skb(skb); - return err; + return skb_append_datato_frags(sk, skb, getfrag, from, + (length - transhdrlen)); } static inline struct ipv6_opt_hdr *ip6_opt_dup(struct ipv6_opt_hdr *src, @@ -1346,27 +1337,27 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, * --yoshfuji */ - cork->length += length; - if (length > mtu) { - int proto = sk->sk_protocol; - if (dontfrag && (proto == IPPROTO_UDP || proto == IPPROTO_RAW)){ - ipv6_local_rxpmtu(sk, fl6, mtu-exthdrlen); - return -EMSGSIZE; - } - - if (proto == IPPROTO_UDP && - (rt->dst.dev->features & NETIF_F_UFO)) { + if ((length > mtu) && dontfrag && (sk->sk_protocol == IPPROTO_UDP || + sk->sk_protocol == IPPROTO_RAW)) { + ipv6_local_rxpmtu(sk, fl6, mtu-exthdrlen); + return -EMSGSIZE; + } - err = ip6_ufo_append_data(sk, getfrag, from, length, - hh_len, fragheaderlen, - transhdrlen, mtu, flags, rt); - if (err) - goto error; - return 0; - } + skb = skb_peek_tail(&sk->sk_write_queue); + cork->length += length; + if (((length > mtu) || + (skb && skb_is_gso(skb))) && + (sk->sk_protocol == IPPROTO_UDP) && + (rt->dst.dev->features & NETIF_F_UFO)) { + err = ip6_ufo_append_data(sk, getfrag, from, length, + hh_len, fragheaderlen, + transhdrlen, mtu, flags, rt); + if (err) + goto error; + return 0; } - if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL) + if (!skb) goto alloc_new_skb; while (length > 0) { diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 6a4ab24a5d6..9728df5c569 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c @@ -2149,7 +2149,7 @@ static void mld_gq_timer_expire(unsigned long data) idev->mc_gq_running = 0; mld_send_report(idev, NULL); - __in6_dev_put(idev); + in6_dev_put(idev); } static void mld_ifc_timer_expire(unsigned long data) @@ -2162,7 +2162,7 @@ static void mld_ifc_timer_expire(unsigned long data) if (idev->mc_ifc_count) mld_ifc_start_timer(idev, idev->mc_maxdelay); } - __in6_dev_put(idev); + in6_dev_put(idev); } static void mld_ifc_event(struct inet6_dev *idev) diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c index 7fd66dec859..ec78ab63dd4 100644 --- a/net/netfilter/ipvs/ip_vs_xmit.c +++ b/net/netfilter/ipvs/ip_vs_xmit.c @@ -853,7 +853,7 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, iph->daddr = cp->daddr.ip; iph->saddr = saddr; iph->ttl = old_iph->ttl; - ip_select_ident(iph, &rt->dst, NULL); + ip_select_ident(skb, &rt->dst, NULL); /* Another hack: avoid icmp_send in ip_fragment */ skb->local_df = 1; diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 91f479121c5..53a7f032eaf 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -205,45 +205,24 @@ SCTP_STATIC void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, in6_dev_put(idev); } -/* Based on tcp_v6_xmit() in tcp_ipv6.c. */ static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport) { struct sock *sk = skb->sk; struct ipv6_pinfo *np = inet6_sk(sk); - struct flowi6 fl6; - - memset(&fl6, 0, sizeof(fl6)); - - fl6.flowi6_proto = sk->sk_protocol; - - /* Fill in the dest address from the route entry passed with the skb - * and the source address from the transport. - */ - fl6.daddr = transport->ipaddr.v6.sin6_addr; - fl6.saddr = transport->saddr.v6.sin6_addr; - - fl6.flowlabel = np->flow_label; - IP6_ECN_flow_xmit(sk, fl6.flowlabel); - if (ipv6_addr_type(&fl6.saddr) & IPV6_ADDR_LINKLOCAL) - fl6.flowi6_oif = transport->saddr.v6.sin6_scope_id; - else - fl6.flowi6_oif = sk->sk_bound_dev_if; - - if (np->opt && np->opt->srcrt) { - struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt; - fl6.daddr = *rt0->addr; - } + struct flowi6 *fl6 = &transport->fl.u.ip6; SCTP_DEBUG_PRINTK("%s: skb:%p, len:%d, src:%pI6 dst:%pI6\n", __func__, skb, skb->len, - &fl6.saddr, &fl6.daddr); + &fl6->saddr, &fl6->daddr); - SCTP_INC_STATS(SCTP_MIB_OUTSCTPPACKS); + IP6_ECN_flow_xmit(sk, fl6->flowlabel); if (!(transport->param_flags & SPP_PMTUD_ENABLE)) skb->local_df = 1; - return ip6_xmit(sk, skb, &fl6, np->opt, np->tclass); + SCTP_INC_STATS(SCTP_MIB_OUTSCTPPACKS); + + return ip6_xmit(sk, skb, fl6, np->opt, np->tclass); } /* Returns the dst cache entry for the given source and destination ip @@ -256,10 +235,12 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr, struct dst_entry *dst = NULL; struct flowi6 *fl6 = &fl->u.ip6; struct sctp_bind_addr *bp; + struct ipv6_pinfo *np = inet6_sk(sk); struct sctp_sockaddr_entry *laddr; union sctp_addr *baddr = NULL; union sctp_addr *daddr = &t->ipaddr; union sctp_addr dst_saddr; + struct in6_addr *final_p, final; __u8 matchlen = 0; __u8 bmatchlen; sctp_scope_t scope; @@ -282,7 +263,8 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr, SCTP_DEBUG_PRINTK("SRC=%pI6 - ", &fl6->saddr); } - dst = ip6_dst_lookup_flow(sk, fl6, NULL, false); + final_p = fl6_update_dst(fl6, np->opt, &final); + dst = ip6_dst_lookup_flow(sk, fl6, final_p, false); if (!asoc || saddr) goto out; @@ -333,10 +315,12 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr, } } rcu_read_unlock(); + if (baddr) { fl6->saddr = baddr->v6.sin6_addr; fl6->fl6_sport = baddr->v6.sin6_port; - dst = ip6_dst_lookup_flow(sk, fl6, NULL, false); + final_p = fl6_update_dst(fl6, np->opt, &final); + dst = ip6_dst_lookup_flow(sk, fl6, final_p, false); } out: diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 4bc6e0bbf97..e9e50cadd52 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -814,6 +814,9 @@ static int sctp_send_asconf_del_ip(struct sock *sk, goto skip_mkasconf; } + if (laddr == NULL) + return -EINVAL; + /* We do not need RCU protection throughout this loop * because this is done under a socket lock from the * setsockopt call. diff --git a/sound/soc/codecs/88pm860x-codec.c b/sound/soc/codecs/88pm860x-codec.c index 9fd3b6827bb..3ff2b94e11c 100644 --- a/sound/soc/codecs/88pm860x-codec.c +++ b/sound/soc/codecs/88pm860x-codec.c @@ -351,6 +351,9 @@ static int snd_soc_put_volsw_2r_st(struct snd_kcontrol *kcontrol, val = ucontrol->value.integer.value[0]; val2 = ucontrol->value.integer.value[1]; + if (val >= ARRAY_SIZE(st_table) || val2 >= ARRAY_SIZE(st_table)) + return -EINVAL; + err = snd_soc_update_bits(codec, reg, 0x3f, st_table[val].m); if (err < 0) return err; diff --git a/sound/soc/codecs/max98095.c b/sound/soc/codecs/max98095.c index 0bb511a0388..196dfa3e817 100644 --- a/sound/soc/codecs/max98095.c +++ b/sound/soc/codecs/max98095.c @@ -1860,7 +1860,7 @@ static int max98095_put_eq_enum(struct snd_kcontrol *kcontrol, struct max98095_pdata *pdata = max98095->pdata; int channel = max98095_get_eq_channel(kcontrol->id.name); struct max98095_cdata *cdata; - int sel = ucontrol->value.integer.value[0]; + unsigned int sel = ucontrol->value.integer.value[0]; struct max98095_eq_cfg *coef_set; int fs, best, best_val, i; int regmask, regsave; @@ -2013,7 +2013,7 @@ static int max98095_put_bq_enum(struct snd_kcontrol *kcontrol, struct max98095_pdata *pdata = max98095->pdata; int channel = max98095_get_bq_channel(codec, kcontrol->id.name); struct max98095_cdata *cdata; - int sel = ucontrol->value.integer.value[0]; + unsigned int sel = ucontrol->value.integer.value[0]; struct max98095_biquad_cfg *coef_set; int fs, best, best_val, i; int regmask, regsave; From 6cf5bf378bbdddb598fca84f97377514713b3a42 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 22 Oct 2013 09:19:41 +0100 Subject: [PATCH 140/215] Linux 3.4.67 - 11 commits squashed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ALSA: snd-usb-usx2y: remove bogus frame checks commit a9d14bc0b188a822e42787d01e56c06fe9750162 upstream. The frame check in i_usX2Y_urb_complete() and i_usX2Y_usbpcm_urb_complete() is bogus and produces false positives as described in this LAU thread: http://linuxaudio.org/mailarchive/lau/2013/5/20/200177 This patch removes the check code entirely. Cc: fzu@wemgehoertderstaat.de Reported-by: Dr Nicholas J Bailey Suggested-by: Takashi Iwai Signed-off-by: Daniel Mack Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman ALSA: hda - Add fixup for ASUS N56VZ commit c6cc3d58b4042f5cadae653ff8d3df26af1a0169 upstream. ASUS N56VZ needs a fixup for the bass speaker pin, which was already provided via model=asus-mode4. Bugzilla: https://bugzilla.novell.com/show_bug.cgi?id=841645 Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman random: run random_int_secret_init() run after all late_initcalls commit 47d06e532e95b71c0db3839ebdef3fe8812fca2c upstream. The some platforms (e.g., ARM) initializes their clocks as late_initcalls for some unknown reason. So make sure random_int_secret_init() is run after all of the late_initcalls are run. Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman vfs: allow O_PATH file descriptors for fstatfs() commit 9d05746e7b16d8565dddbe3200faa1e669d23bbf upstream. Olga reported that file descriptors opened with O_PATH do not work with fstatfs(), found during further development of ksh93's thread support. There is no reason to not allow O_PATH file descriptors here (fstatfs is very much a path operation), so use "fdget_raw()". See commit 55815f70147d ("vfs: make O_PATH file descriptors usable for 'fstat()'") for a very similar issue reported for fstat() by the same team. Reported-and-tested-by: ольга крыжановÑÐºÐ°Ñ Acked-by: Al Viro Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman ext4: fix memory leak in xattr commit 6e4ea8e33b2057b85d75175dd89b93f5e26de3bc upstream. If we take the 2nd retry path in ext4_expand_extra_isize_ea, we potentionally return from the function without having freed these allocations. If we don't do the return, we over-write the previous allocation pointers, so we leak either way. Spotted with Coverity. [ Fixed by tytso to set is and bs to NULL after freeing these pointers, in case in the retry loop we later end up triggering an error causing a jump to cleanup, at which point we could have a double free bug. -- Ted ] Signed-off-by: Dave Jones Signed-off-by: "Theodore Ts'o" Reviewed-by: Eric Sandeen Signed-off-by: Greg Kroah-Hartman KVM: PPC: Book3S HV: Fix typo in saving DSCR commit cfc860253abd73e1681696c08ea268d33285a2c4 upstream. This fixes a typo in the code that saves the guest DSCR (Data Stream Control Register) into the kvm_vcpu_arch struct on guest exit. The effect of the typo was that the DSCR value was saved in the wrong place, so changes to the DSCR by the guest didn't persist across guest exit and entry, and some host kernel memory got corrupted. Signed-off-by: Paul Mackerras Acked-by: Alexander Graf Signed-off-by: Paolo Bonzini Signed-off-by: Greg Kroah-Hartman parisc: fix interruption handler to respect pagefault_disable() commit 59b33f148cc08fb33cbe823fca1e34f7f023765e upstream. Running an "echo t > /proc/sysrq-trigger" crashes the parisc kernel. The problem is, that in print_worker_info() we try to read the workqueue info via the probe_kernel_read() functions which use pagefault_disable() to avoid crashes like this: probe_kernel_read(&pwq, &worker->current_pwq, sizeof(pwq)); probe_kernel_read(&wq, &pwq->wq, sizeof(wq)); probe_kernel_read(name, wq->name, sizeof(name) - 1); The problem here is, that the first probe_kernel_read(&pwq) might return zero in pwq and as such the following probe_kernel_reads() try to access contents of the page zero which is read protected and generate a kernel segfault. With this patch we fix the interruption handler to call parisc_terminate() directly only if pagefault_disable() was not called (in which case preempt_count()==0). Otherwise we hand over to the pagefault handler which will try to look up the faulting address in the fixup tables. Signed-off-by: Helge Deller Signed-off-by: John David Anglin Signed-off-by: Helge Deller Signed-off-by: Greg Kroah-Hartman watchdog: ts72xx_wdt: locking bug in ioctl commit 8612ed0d97abcf1c016d34755b7cf2060de71963 upstream. Calling the WDIOC_GETSTATUS & WDIOC_GETBOOTSTATUS and twice will cause a interruptible deadlock. Signed-off-by: Dan Carpenter Reviewed-by: Guenter Roeck Signed-off-by: Wim Van Sebroeck Cc: Jonghwan Choi Signed-off-by: Greg Kroah-Hartman drm/radeon: fix hw contexts for SUMO2 asics commit 50b8f5aec04ebec7dbdf2adb17220b9148c99e63 upstream. They have 4 rather than 8. Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=63599 Signed-off-by: wojciech kapuscinski Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman mm/mmap: check for RLIMIT_AS before unmapping commit e8420a8ece80b3fe810415ecf061d54ca7fab266 upstream. Fix a corner case for MAP_FIXED when requested mapping length is larger than rlimit for virtual memory. In such case any overlapping mappings are unmapped before we check for the limit and return ENOMEM. The check is moved before the loop that unmaps overlapping parts of existing mappings. When we are about to hit the limit (currently mapped pages + len > limit) we scan for overlapping pages and check again accounting for them. This fixes situation when userspace program expects that the previous mappings are preserved after the mmap() syscall has returned with error. (POSIX clearly states that successfull mapping shall replace any previous mappings.) This corner case was found and can be tested with LTP testcase: testcases/open_posix_testsuite/conformance/interfaces/mmap/24-2.c In this case the mmap, which is clearly over current limit, unmaps dynamic libraries and the testcase segfaults right after returning into userspace. I've also looked at the second instance of the unmapping loop in the do_brk(). The do_brk() is called from brk() syscall and from vm_brk(). The brk() syscall checks for overlapping mappings and bails out when there are any (so it can't be triggered from the brk syscall). The vm_brk() is called only from binmft handlers so it shouldn't be triggered unless binmft handler created overlapping mappings. Signed-off-by: Cyril Hrubis Reviewed-by: Mel Gorman Reviewed-by: Wanpeng Li Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Cc: Xishi Qiu Signed-off-by: Greg Kroah-Hartman mm: do not grow the stack vma just because of an overrun on preceding vma commit 09884964335e85e897876d17783c2ad33cf8a2e0 upstream. The stack vma is designed to grow automatically (marked with VM_GROWSUP or VM_GROWSDOWN depending on architecture) when an access is made beyond the existing boundary. However, particularly if you have not limited your stack at all ("ulimit -s unlimited"), this can cause the stack to grow even if the access was really just one past *another* segment. And that's wrong, especially since we first grow the segment, but then immediately later enforce the stack guard page on the last page of the segment. So _despite_ first growing the stack segment as a result of the access, the kernel will then make the access cause a SIGSEGV anyway! So do the same logic as the guard page check does, and consider an access to within one page of the next segment to be a bad access, rather than growing the stack to abut the next segment. Reported-and-tested-by: Heiko Carstens Signed-off-by: Linus Torvalds Cc: Xishi Qiu Signed-off-by: Greg Kroah-Hartman --- Makefile | 2 +- arch/parisc/kernel/traps.c | 6 +- arch/powerpc/kvm/book3s_hv_rmhandlers.S | 2 +- drivers/gpu/drm/radeon/evergreen.c | 2 +- drivers/watchdog/ts72xx_wdt.c | 3 +- fs/ext4/xattr.c | 2 + fs/statfs.c | 2 +- include/linux/random.h | 1 + init/main.c | 2 + mm/mmap.c | 77 +++++++++++++++++++++++-- sound/pci/hda/patch_realtek.c | 1 + sound/usb/usx2y/usbusx2yaudio.c | 22 +------ sound/usb/usx2y/usx2yhwdeppcm.c | 7 +-- 13 files changed, 92 insertions(+), 37 deletions(-) diff --git a/Makefile b/Makefile index f0066e4c9bb..0774f1871de 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 4 -SUBLEVEL = 66 +SUBLEVEL = 67 EXTRAVERSION = NAME = Saber-toothed Squirrel diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c index 45ba99f5080..71d7d729397 100644 --- a/arch/parisc/kernel/traps.c +++ b/arch/parisc/kernel/traps.c @@ -810,14 +810,14 @@ void notrace handle_interruption(int code, struct pt_regs *regs) else { /* - * The kernel should never fault on its own address space. + * The kernel should never fault on its own address space, + * unless pagefault_disable() was called before. */ - if (fault_space == 0) + if (fault_space == 0 && !in_atomic()) { pdc_chassis_send_status(PDC_CHASSIS_DIRECT_PANIC); parisc_terminate("Kernel Fault", regs, code, fault_address); - } } diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S index b70bf22a3ff..3e95aa5c2ef 100644 --- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S +++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S @@ -935,7 +935,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206) BEGIN_FTR_SECTION mfspr r8, SPRN_DSCR ld r7, HSTATE_DSCR(r13) - std r8, VCPU_DSCR(r7) + std r8, VCPU_DSCR(r9) mtspr SPRN_DSCR, r7 END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206) diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 15d1f08b81e..ad72295403a 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -1912,7 +1912,7 @@ static void evergreen_gpu_init(struct radeon_device *rdev) rdev->config.evergreen.sx_max_export_size = 256; rdev->config.evergreen.sx_max_export_pos_size = 64; rdev->config.evergreen.sx_max_export_smx_size = 192; - rdev->config.evergreen.max_hw_contexts = 8; + rdev->config.evergreen.max_hw_contexts = 4; rdev->config.evergreen.sq_num_cf_insts = 2; rdev->config.evergreen.sc_prim_fifo_size = 0x40; diff --git a/drivers/watchdog/ts72xx_wdt.c b/drivers/watchdog/ts72xx_wdt.c index 8df050d800e..1c53745ffb2 100644 --- a/drivers/watchdog/ts72xx_wdt.c +++ b/drivers/watchdog/ts72xx_wdt.c @@ -310,7 +310,8 @@ static long ts72xx_wdt_ioctl(struct file *file, unsigned int cmd, case WDIOC_GETSTATUS: case WDIOC_GETBOOTSTATUS: - return put_user(0, p); + error = put_user(0, p); + break; case WDIOC_KEEPALIVE: ts72xx_wdt_kick(wdt); diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c index e712a8cb165..b1aa7fd4701 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c @@ -1268,6 +1268,8 @@ int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize, s_min_extra_isize) { tried_min_extra_isize++; new_extra_isize = s_min_extra_isize; + kfree(is); is = NULL; + kfree(bs); bs = NULL; goto retry; } error = -1; diff --git a/fs/statfs.c b/fs/statfs.c index 43e6b6fe4e8..d1812b2840e 100644 --- a/fs/statfs.c +++ b/fs/statfs.c @@ -87,7 +87,7 @@ int user_statfs(const char __user *pathname, struct kstatfs *st) int fd_statfs(int fd, struct kstatfs *st) { - struct file *file = fget(fd); + struct file *file = fget_raw(fd); int error = -EBADF; if (file) { error = vfs_statfs(&file->f_path, st); diff --git a/include/linux/random.h b/include/linux/random.h index ac621ce886c..7e58ad27b7f 100644 --- a/include/linux/random.h +++ b/include/linux/random.h @@ -56,6 +56,7 @@ extern void add_interrupt_randomness(int irq, int irq_flags); extern void get_random_bytes(void *buf, int nbytes); extern void get_random_bytes_arch(void *buf, int nbytes); void generate_random_uuid(unsigned char uuid_out[16]); +extern int random_int_secret_init(void); #ifndef MODULE extern const struct file_operations random_fops, urandom_fops; diff --git a/init/main.c b/init/main.c index 5633c12372b..abcb6818dbb 100644 --- a/init/main.c +++ b/init/main.c @@ -68,6 +68,7 @@ #include #include #include +#include #include #include @@ -781,6 +782,7 @@ static void __init do_basic_setup(void) do_ctors(); usermodehelper_enable(); do_initcalls(); + random_int_secret_init(); } static void __init do_pre_smp_initcalls(void) diff --git a/mm/mmap.c b/mm/mmap.c index d8e55886494..74a2de81822 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -6,6 +6,7 @@ * Address space accounting code */ +#include #include #include #include @@ -392,6 +393,34 @@ find_vma_prepare(struct mm_struct *mm, unsigned long addr, return vma; } +static unsigned long count_vma_pages_range(struct mm_struct *mm, + unsigned long addr, unsigned long end) +{ + unsigned long nr_pages = 0; + struct vm_area_struct *vma; + + /* Find first overlaping mapping */ + vma = find_vma_intersection(mm, addr, end); + if (!vma) + return 0; + + nr_pages = (min(end, vma->vm_end) - + max(addr, vma->vm_start)) >> PAGE_SHIFT; + + /* Iterate over the rest of the overlaps */ + for (vma = vma->vm_next; vma; vma = vma->vm_next) { + unsigned long overlap_len; + + if (vma->vm_start > end) + break; + + overlap_len = min(end, vma->vm_end) - vma->vm_start; + nr_pages += overlap_len >> PAGE_SHIFT; + } + + return nr_pages; +} + void __vma_link_rb(struct mm_struct *mm, struct vm_area_struct *vma, struct rb_node **rb_link, struct rb_node *rb_parent) { @@ -1251,6 +1280,23 @@ unsigned long mmap_region(struct file *file, unsigned long addr, unsigned long charged = 0; struct inode *inode = file ? file->f_path.dentry->d_inode : NULL; + /* Check against address space limit. */ + if (!may_expand_vm(mm, len >> PAGE_SHIFT)) { + unsigned long nr_pages; + + /* + * MAP_FIXED may remove pages of mappings that intersects with + * requested mapping. Account for the pages it would unmap. + */ + if (!(vm_flags & MAP_FIXED)) + return -ENOMEM; + + nr_pages = count_vma_pages_range(mm, addr, addr + len); + + if (!may_expand_vm(mm, (len >> PAGE_SHIFT) - nr_pages)) + return -ENOMEM; + } + /* Clear old maps */ error = -ENOMEM; munmap_back: @@ -1261,10 +1307,6 @@ unsigned long mmap_region(struct file *file, unsigned long addr, goto munmap_back; } - /* Check against address space limit. */ - if (!may_expand_vm(mm, len >> PAGE_SHIFT)) - return -ENOMEM; - /* * Set 'VM_NORESERVE' if we should not account for the * memory use of this mapping. @@ -1840,9 +1882,28 @@ int expand_downwards(struct vm_area_struct *vma, return error; } +/* + * Note how expand_stack() refuses to expand the stack all the way to + * abut the next virtual mapping, *unless* that mapping itself is also + * a stack mapping. We want to leave room for a guard page, after all + * (the guard page itself is not added here, that is done by the + * actual page faulting logic) + * + * This matches the behavior of the guard page logic (see mm/memory.c: + * check_stack_guard_page()), which only allows the guard page to be + * removed under these circumstances. + */ #ifdef CONFIG_STACK_GROWSUP int expand_stack(struct vm_area_struct *vma, unsigned long address) { + struct vm_area_struct *next; + + address &= PAGE_MASK; + next = vma->vm_next; + if (next && next->vm_start == address + PAGE_SIZE) { + if (!(next->vm_flags & VM_GROWSUP)) + return -ENOMEM; + } return expand_upwards(vma, address); } @@ -1865,6 +1926,14 @@ find_extend_vma(struct mm_struct *mm, unsigned long addr) #else int expand_stack(struct vm_area_struct *vma, unsigned long address) { + struct vm_area_struct *prev; + + address &= PAGE_MASK; + prev = vma->vm_prev; + if (prev && prev->vm_end == address) { + if (!(prev->vm_flags & VM_GROWSDOWN)) + return -ENOMEM; + } return expand_downwards(vma, address); } diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 353b32a34b1..33abb782a54 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -6832,6 +6832,7 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = { SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE), SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE), SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800), + SND_PCI_QUIRK(0x1043, 0x1477, "ASUS N56VZ", ALC662_FIXUP_ASUS_MODE4), SND_PCI_QUIRK(0x1043, 0x8469, "ASUS mobo", ALC662_FIXUP_NO_JACK_DETECT), SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_FIXUP_ASUS_MODE2), SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD), diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c index 520ef96d7c7..711299ccf26 100644 --- a/sound/usb/usx2y/usbusx2yaudio.c +++ b/sound/usb/usx2y/usbusx2yaudio.c @@ -295,19 +295,6 @@ static void usX2Y_error_urb_status(struct usX2Ydev *usX2Y, usX2Y_clients_stop(usX2Y); } -static void usX2Y_error_sequence(struct usX2Ydev *usX2Y, - struct snd_usX2Y_substream *subs, struct urb *urb) -{ - snd_printk(KERN_ERR -"Sequence Error!(hcd_frame=%i ep=%i%s;wait=%i,frame=%i).\n" -"Most probably some urb of usb-frame %i is still missing.\n" -"Cause could be too long delays in usb-hcd interrupt handling.\n", - usb_get_current_frame_number(usX2Y->dev), - subs->endpoint, usb_pipein(urb->pipe) ? "in" : "out", - usX2Y->wait_iso_frame, urb->start_frame, usX2Y->wait_iso_frame); - usX2Y_clients_stop(usX2Y); -} - static void i_usX2Y_urb_complete(struct urb *urb) { struct snd_usX2Y_substream *subs = urb->context; @@ -324,12 +311,9 @@ static void i_usX2Y_urb_complete(struct urb *urb) usX2Y_error_urb_status(usX2Y, subs, urb); return; } - if (likely((urb->start_frame & 0xFFFF) == (usX2Y->wait_iso_frame & 0xFFFF))) - subs->completed_urb = urb; - else { - usX2Y_error_sequence(usX2Y, subs, urb); - return; - } + + subs->completed_urb = urb; + { struct snd_usX2Y_substream *capsubs = usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE], *playbacksubs = usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK]; diff --git a/sound/usb/usx2y/usx2yhwdeppcm.c b/sound/usb/usx2y/usx2yhwdeppcm.c index 8e40b6e67e9..1da1eca6977 100644 --- a/sound/usb/usx2y/usx2yhwdeppcm.c +++ b/sound/usb/usx2y/usx2yhwdeppcm.c @@ -244,13 +244,8 @@ static void i_usX2Y_usbpcm_urb_complete(struct urb *urb) usX2Y_error_urb_status(usX2Y, subs, urb); return; } - if (likely((urb->start_frame & 0xFFFF) == (usX2Y->wait_iso_frame & 0xFFFF))) - subs->completed_urb = urb; - else { - usX2Y_error_sequence(usX2Y, subs, urb); - return; - } + subs->completed_urb = urb; capsubs = usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE]; capsubs2 = usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE + 2]; playbacksubs = usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK]; From 129ff1073dd58898834f01b4457b325b9312853c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 4 Nov 2013 04:23:59 -0800 Subject: [PATCH 141/215] Linux 3.4.68 - Squashed 32 commits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit tcp: must unclone packets before mangling them [ Upstream commit c52e2421f7368fd36cbe330d2cf41b10452e39a9 ] TCP stack should make sure it owns skbs before mangling them. We had various crashes using bnx2x, and it turned out gso_size was cleared right before bnx2x driver was populating TC descriptor of the _previous_ packet send. TCP stack can sometime retransmit packets that are still in Qdisc. Of course we could make bnx2x driver more robust (using ACCESS_ONCE(shinfo->gso_size) for example), but the bug is TCP stack. We have identified two points where skb_unclone() was needed. This patch adds a WARN_ON_ONCE() to warn us if we missed another fix of this kind. Kudos to Neal for finding the root cause of this bug. Its visible using small MSS. Signed-off-by: Eric Dumazet Signed-off-by: Neal Cardwell Cc: Yuchung Cheng Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman tcp: do not forget FIN in tcp_shifted_skb() [ Upstream commit 5e8a402f831dbe7ee831340a91439e46f0d38acd ] Yuchung found following problem : There are bugs in the SACK processing code, merging part in tcp_shift_skb_data(), that incorrectly resets or ignores the sacked skbs FIN flag. When a receiver first SACK the FIN sequence, and later throw away ofo queue (e.g., sack-reneging), the sender will stop retransmitting the FIN flag, and hangs forever. Following packetdrill test can be used to reproduce the bug. $ cat sack-merge-bug.pkt `sysctl -q net.ipv4.tcp_fack=0` // Establish a connection and send 10 MSS. 0.000 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3 +.000 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 +.000 bind(3, ..., ...) = 0 +.000 listen(3, 1) = 0 +.050 < S 0:0(0) win 32792 +.000 > S. 0:0(0) ack 1 +.001 < . 1:1(0) ack 1 win 1024 +.000 accept(3, ..., ...) = 4 +.100 write(4, ..., 12000) = 12000 +.000 shutdown(4, SHUT_WR) = 0 +.000 > . 1:10001(10000) ack 1 +.050 < . 1:1(0) ack 2001 win 257 +.000 > FP. 10001:12001(2000) ack 1 +.050 < . 1:1(0) ack 2001 win 257 +.050 < . 1:1(0) ack 2001 win 257 // SACK reneg +.050 < . 1:1(0) ack 12001 win 257 +0 %{ print "unacked: ",tcpi_unacked }% +5 %{ print "" }% First, a typo inverted left/right of one OR operation, then code forgot to advance end_seq if the merged skb carried FIN. Bug was added in 2.6.29 by commit 832d11c5cd076ab ("tcp: Try to restore large SKBs while SACK processing") Signed-off-by: Eric Dumazet Signed-off-by: Yuchung Cheng Acked-by: Neal Cardwell Cc: Ilpo Järvinen Acked-by: Ilpo Järvinen Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman net: do not call sock_put() on TIMEWAIT sockets [ Upstream commit 80ad1d61e72d626e30ebe8529a0455e660ca4693 ] commit 3ab5aee7fe84 ("net: Convert TCP & DCCP hash tables to use RCU / hlist_nulls") incorrectly used sock_put() on TIMEWAIT sockets. We should instead use inet_twsk_put() Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman net: mv643xx_eth: update statistics timer from timer context only [ Upstream commit 041b4ddb84989f06ff1df0ca869b950f1ee3cb1c ] Each port driver installs a periodic timer to update port statistics by calling mib_counters_update. As mib_counters_update is also called from non-timer context, we should not reschedule the timer there but rather move it to timer-only context. Signed-off-by: Sebastian Hesselbarth Acked-by: Jason Cooper Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman net: mv643xx_eth: fix orphaned statistics timer crash [ Upstream commit f564412c935111c583b787bcc18157377b208e2e ] The periodic statistics timer gets started at port _probe() time, but is stopped on _stop() only. In a modular environment, this can cause the timer to access already deallocated memory, if the module is unloaded without starting the eth device. To fix this, we add the timer right before the port is started, instead of at _probe() time. Signed-off-by: Sebastian Hesselbarth Acked-by: Jason Cooper Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman net: heap overflow in __audit_sockaddr() [ Upstream commit 1661bf364ae9c506bc8795fef70d1532931be1e8 ] We need to cap ->msg_namelen or it leads to a buffer overflow when we to the memcpy() in __audit_sockaddr(). It requires CAP_AUDIT_CONTROL to exploit this bug. The call tree is: ___sys_recvmsg() move_addr_to_user() audit_sockaddr() __audit_sockaddr() Reported-by: Jüri Aedla Signed-off-by: Dan Carpenter Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman proc connector: fix info leaks [ Upstream commit e727ca82e0e9616ab4844301e6bae60ca7327682 ] Initialize event_data for all possible message types to prevent leaking kernel stack contents to userland (up to 20 bytes). Also set the flags member of the connector message to 0 to prevent leaking two more stack bytes this way. Signed-off-by: Mathias Krause Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman ipv4: fix ineffective source address selection [ Upstream commit 0a7e22609067ff524fc7bbd45c6951dd08561667 ] When sending out multicast messages, the source address in inet->mc_addr is ignored and rewritten by an autoselected one. This is caused by a typo in commit 813b3b5db831 ("ipv4: Use caller's on-stack flowi as-is in output route lookups"). Signed-off-by: Jiri Benc Acked-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman can: dev: fix nlmsg size calculation in can_get_size() [ Upstream commit fe119a05f8ca481623a8d02efcc984332e612528 ] This patch fixes the calculation of the nlmsg size, by adding the missing nla_total_size(). Signed-off-by: Marc Kleine-Budde Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman ipv6: restrict neighbor entry creation to output flow This patch is based on 3.2.y branch, the one used by reporter. Please let me know if it should be different. Thanks. The patch which introduced the regression was applied on stables: 3.0.64 3.4.31 3.7.8 3.2.39 The patch which introduced the regression was for stable trees only. ---8<--- Commit 0d6a77079c475033cb622c07c5a880b392ef664e "ipv6: do not create neighbor entries for local delivery" introduced a regression on which routes to local delivery would not work anymore. Like this: $ ip -6 route add local 2001::/64 dev lo $ ping6 -c1 2001::9 PING 2001::9(2001::9) 56 data bytes ping: sendmsg: Invalid argument As this is a local delivery, that commit would not allow the creation of a neighbor entry and thus the packet cannot be sent. But as TPROXY scenario actually needs to avoid the neighbor entry creation only for input flow, this patch now limits previous patch to input flow, keeping output as before that patch. Reported-by: Debabrata Banerjee Signed-off-by: Marcelo Ricardo Leitner Signed-off-by: Jiri Pirko Acked-by: Hannes Frederic Sowa CC: Hannes Frederic Sowa Signed-off-by: Greg Kroah-Hartman bridge: Correctly clamp MAX forward_delay when enabling STP [ Upstream commit 4b6c7879d84ad06a2ac5b964808ed599187a188d ] Commit be4f154d5ef0ca147ab6bcd38857a774133f5450 bridge: Clamp forward_delay when enabling STP had a typo when attempting to clamp maximum forward delay. It is possible to set bridge_forward_delay to be higher then permitted maximum when STP is off. When turning STP on, the higher then allowed delay has to be clamed down to max value. Signed-off-by: Vlad Yasevich CC: Herbert Xu CC: Stephen Hemminger Reviewed-by: Veaceslav Falico Acked-by: Herbert Xu Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman net: vlan: fix nlmsg size calculation in vlan_get_size() [ Upstream commit c33a39c575068c2ea9bffb22fd6de2df19c74b89 ] This patch fixes the calculation of the nlmsg size, by adding the missing nla_total_size(). Cc: Patrick McHardy Signed-off-by: Marc Kleine-Budde Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman l2tp: must disable bh before calling l2tp_xmit_skb() [ Upstream commit 455cc32bf128e114455d11ad919321ab89a2c312 ] François Cachereul made a very nice bug report and suspected the bh_lock_sock() / bh_unlok_sock() pair used in l2tp_xmit_skb() from process context was not good. This problem was added by commit 6af88da14ee284aaad6e4326da09a89191ab6165 ("l2tp: Fix locking in l2tp_core.c"). l2tp_eth_dev_xmit() runs from BH context, so we must disable BH from other l2tp_xmit_skb() users. [ 452.060011] BUG: soft lockup - CPU#1 stuck for 23s! [accel-pppd:6662] [ 452.061757] Modules linked in: l2tp_ppp l2tp_netlink l2tp_core pppoe pppox ppp_generic slhc ipv6 ext3 mbcache jbd virtio_balloon xfs exportfs dm_mod virtio_blk ata_generic virtio_net floppy ata_piix libata virtio_pci virtio_ring virtio [last unloaded: scsi_wait_scan] [ 452.064012] CPU 1 [ 452.080015] BUG: soft lockup - CPU#2 stuck for 23s! [accel-pppd:6643] [ 452.080015] CPU 2 [ 452.080015] [ 452.080015] Pid: 6643, comm: accel-pppd Not tainted 3.2.46.mini #1 Bochs Bochs [ 452.080015] RIP: 0010:[] [] do_raw_spin_lock+0x17/0x1f [ 452.080015] RSP: 0018:ffff88007125fc18 EFLAGS: 00000293 [ 452.080015] RAX: 000000000000aba9 RBX: ffffffff811d0703 RCX: 0000000000000000 [ 452.080015] RDX: 00000000000000ab RSI: ffff8800711f6896 RDI: ffff8800745c8110 [ 452.080015] RBP: ffff88007125fc18 R08: 0000000000000020 R09: 0000000000000000 [ 452.080015] R10: 0000000000000000 R11: 0000000000000280 R12: 0000000000000286 [ 452.080015] R13: 0000000000000020 R14: 0000000000000240 R15: 0000000000000000 [ 452.080015] FS: 00007fdc0cc24700(0000) GS:ffff8800b6f00000(0000) knlGS:0000000000000000 [ 452.080015] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 452.080015] CR2: 00007fdb054899b8 CR3: 0000000074404000 CR4: 00000000000006a0 [ 452.080015] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 452.080015] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 [ 452.080015] Process accel-pppd (pid: 6643, threadinfo ffff88007125e000, task ffff8800b27e6dd0) [ 452.080015] Stack: [ 452.080015] ffff88007125fc28 ffffffff81256559 ffff88007125fc98 ffffffffa01b2bd1 [ 452.080015] ffff88007125fc58 000000000000000c 00000000029490d0 0000009c71dbe25e [ 452.080015] 000000000000005c 000000080000000e 0000000000000000 ffff880071170600 [ 452.080015] Call Trace: [ 452.080015] [] _raw_spin_lock+0xe/0x10 [ 452.080015] [] l2tp_xmit_skb+0x189/0x4ac [l2tp_core] [ 452.080015] [] pppol2tp_sendmsg+0x15e/0x19c [l2tp_ppp] [ 452.080015] [] __sock_sendmsg_nosec+0x22/0x24 [ 452.080015] [] sock_sendmsg+0xa1/0xb6 [ 452.080015] [] ? __schedule+0x5c1/0x616 [ 452.080015] [] ? __dequeue_signal+0xb7/0x10c [ 452.080015] [] ? fget_light+0x75/0x89 [ 452.080015] [] ? sockfd_lookup_light+0x20/0x56 [ 452.080015] [] sys_sendto+0x10c/0x13b [ 452.080015] [] system_call_fastpath+0x16/0x1b [ 452.080015] Code: 81 48 89 e5 72 0c 31 c0 48 81 ff 45 66 25 81 0f 92 c0 5d c3 55 b8 00 01 00 00 48 89 e5 f0 66 0f c1 07 0f b6 d4 38 d0 74 06 f3 90 <8a> 07 eb f6 5d c3 90 90 55 48 89 e5 9c 58 0f 1f 44 00 00 5d c3 [ 452.080015] Call Trace: [ 452.080015] [] _raw_spin_lock+0xe/0x10 [ 452.080015] [] l2tp_xmit_skb+0x189/0x4ac [l2tp_core] [ 452.080015] [] pppol2tp_sendmsg+0x15e/0x19c [l2tp_ppp] [ 452.080015] [] __sock_sendmsg_nosec+0x22/0x24 [ 452.080015] [] sock_sendmsg+0xa1/0xb6 [ 452.080015] [] ? __schedule+0x5c1/0x616 [ 452.080015] [] ? __dequeue_signal+0xb7/0x10c [ 452.080015] [] ? fget_light+0x75/0x89 [ 452.080015] [] ? sockfd_lookup_light+0x20/0x56 [ 452.080015] [] sys_sendto+0x10c/0x13b [ 452.080015] [] system_call_fastpath+0x16/0x1b [ 452.064012] [ 452.064012] Pid: 6662, comm: accel-pppd Not tainted 3.2.46.mini #1 Bochs Bochs [ 452.064012] RIP: 0010:[] [] do_raw_spin_lock+0x19/0x1f [ 452.064012] RSP: 0018:ffff8800b6e83ba0 EFLAGS: 00000297 [ 452.064012] RAX: 000000000000aaa9 RBX: ffff8800b6e83b40 RCX: 0000000000000002 [ 452.064012] RDX: 00000000000000aa RSI: 000000000000000a RDI: ffff8800745c8110 [ 452.064012] RBP: ffff8800b6e83ba0 R08: 000000000000c802 R09: 000000000000001c [ 452.064012] R10: ffff880071096c4e R11: 0000000000000006 R12: ffff8800b6e83b18 [ 452.064012] R13: ffffffff8125d51e R14: ffff8800b6e83ba0 R15: ffff880072a589c0 [ 452.064012] FS: 00007fdc0b81e700(0000) GS:ffff8800b6e80000(0000) knlGS:0000000000000000 [ 452.064012] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 452.064012] CR2: 0000000000625208 CR3: 0000000074404000 CR4: 00000000000006a0 [ 452.064012] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 452.064012] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 [ 452.064012] Process accel-pppd (pid: 6662, threadinfo ffff88007129a000, task ffff8800744f7410) [ 452.064012] Stack: [ 452.064012] ffff8800b6e83bb0 ffffffff81256559 ffff8800b6e83bc0 ffffffff8121c64a [ 452.064012] ffff8800b6e83bf0 ffffffff8121ec7a ffff880072a589c0 ffff880071096c62 [ 452.064012] 0000000000000011 ffffffff81430024 ffff8800b6e83c80 ffffffff8121f276 [ 452.064012] Call Trace: [ 452.064012] [ 452.064012] [] _raw_spin_lock+0xe/0x10 [ 452.064012] [] spin_lock+0x9/0xb [ 452.064012] [] udp_queue_rcv_skb+0x186/0x269 [ 452.064012] [] __udp4_lib_rcv+0x297/0x4ae [ 452.064012] [] ? raw_rcv+0xe9/0xf0 [ 452.064012] [] udp_rcv+0x1a/0x1c [ 452.064012] [] ip_local_deliver_finish+0x12b/0x1a5 [ 452.064012] [] ip_local_deliver+0x53/0x84 [ 452.064012] [] ip_rcv_finish+0x2bc/0x2f3 [ 452.064012] [] ip_rcv+0x210/0x269 [ 452.064012] [] ? kvm_clock_get_cycles+0x9/0xb [ 452.064012] [] __netif_receive_skb+0x3a5/0x3f7 [ 452.064012] [] netif_receive_skb+0x57/0x5e [ 452.064012] [] ? __netdev_alloc_skb+0x1f/0x3b [ 452.064012] [] virtnet_poll+0x4ba/0x5a4 [virtio_net] [ 452.064012] [] net_rx_action+0x73/0x184 [ 452.064012] [] ? l2tp_xmit_skb+0x27a/0x4ac [l2tp_core] [ 452.064012] [] __do_softirq+0xc3/0x1a8 [ 452.064012] [] ? ack_APIC_irq+0x10/0x12 [ 452.064012] [] ? _raw_spin_lock+0xe/0x10 [ 452.064012] [] call_softirq+0x1c/0x26 [ 452.064012] [] do_softirq+0x45/0x82 [ 452.064012] [] irq_exit+0x42/0x9c [ 452.064012] [] do_IRQ+0x8e/0xa5 [ 452.064012] [] common_interrupt+0x6e/0x6e [ 452.064012] [ 452.064012] [] ? kfree+0x8a/0xa3 [ 452.064012] [] ? l2tp_xmit_skb+0x27a/0x4ac [l2tp_core] [ 452.064012] [] ? l2tp_xmit_skb+0x1dd/0x4ac [l2tp_core] [ 452.064012] [] pppol2tp_sendmsg+0x15e/0x19c [l2tp_ppp] [ 452.064012] [] __sock_sendmsg_nosec+0x22/0x24 [ 452.064012] [] sock_sendmsg+0xa1/0xb6 [ 452.064012] [] ? __schedule+0x5c1/0x616 [ 452.064012] [] ? __dequeue_signal+0xb7/0x10c [ 452.064012] [] ? fget_light+0x75/0x89 [ 452.064012] [] ? sockfd_lookup_light+0x20/0x56 [ 452.064012] [] sys_sendto+0x10c/0x13b [ 452.064012] [] system_call_fastpath+0x16/0x1b [ 452.064012] Code: 89 e5 72 0c 31 c0 48 81 ff 45 66 25 81 0f 92 c0 5d c3 55 b8 00 01 00 00 48 89 e5 f0 66 0f c1 07 0f b6 d4 38 d0 74 06 f3 90 8a 07 f6 5d c3 90 90 55 48 89 e5 9c 58 0f 1f 44 00 00 5d c3 55 48 [ 452.064012] Call Trace: [ 452.064012] [] _raw_spin_lock+0xe/0x10 [ 452.064012] [] spin_lock+0x9/0xb [ 452.064012] [] udp_queue_rcv_skb+0x186/0x269 [ 452.064012] [] __udp4_lib_rcv+0x297/0x4ae [ 452.064012] [] ? raw_rcv+0xe9/0xf0 [ 452.064012] [] udp_rcv+0x1a/0x1c [ 452.064012] [] ip_local_deliver_finish+0x12b/0x1a5 [ 452.064012] [] ip_local_deliver+0x53/0x84 [ 452.064012] [] ip_rcv_finish+0x2bc/0x2f3 [ 452.064012] [] ip_rcv+0x210/0x269 [ 452.064012] [] ? kvm_clock_get_cycles+0x9/0xb [ 452.064012] [] __netif_receive_skb+0x3a5/0x3f7 [ 452.064012] [] netif_receive_skb+0x57/0x5e [ 452.064012] [] ? __netdev_alloc_skb+0x1f/0x3b [ 452.064012] [] virtnet_poll+0x4ba/0x5a4 [virtio_net] [ 452.064012] [] net_rx_action+0x73/0x184 [ 452.064012] [] ? l2tp_xmit_skb+0x27a/0x4ac [l2tp_core] [ 452.064012] [] __do_softirq+0xc3/0x1a8 [ 452.064012] [] ? ack_APIC_irq+0x10/0x12 [ 452.064012] [] ? _raw_spin_lock+0xe/0x10 [ 452.064012] [] call_softirq+0x1c/0x26 [ 452.064012] [] do_softirq+0x45/0x82 [ 452.064012] [] irq_exit+0x42/0x9c [ 452.064012] [] do_IRQ+0x8e/0xa5 [ 452.064012] [] common_interrupt+0x6e/0x6e [ 452.064012] [] ? kfree+0x8a/0xa3 [ 452.064012] [] ? l2tp_xmit_skb+0x27a/0x4ac [l2tp_core] [ 452.064012] [] ? l2tp_xmit_skb+0x1dd/0x4ac [l2tp_core] [ 452.064012] [] pppol2tp_sendmsg+0x15e/0x19c [l2tp_ppp] [ 452.064012] [] __sock_sendmsg_nosec+0x22/0x24 [ 452.064012] [] sock_sendmsg+0xa1/0xb6 [ 452.064012] [] ? __schedule+0x5c1/0x616 [ 452.064012] [] ? __dequeue_signal+0xb7/0x10c [ 452.064012] [] ? fget_light+0x75/0x89 [ 452.064012] [] ? sockfd_lookup_light+0x20/0x56 [ 452.064012] [] sys_sendto+0x10c/0x13b [ 452.064012] [] system_call_fastpath+0x16/0x1b Reported-by: François Cachereul Tested-by: François Cachereul Signed-off-by: Eric Dumazet Cc: James Chapman Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman farsync: fix info leak in ioctl [ Upstream commit 96b340406724d87e4621284ebac5e059d67b2194 ] The fst_get_iface() code fails to initialize the two padding bytes of struct sync_serial_settings after the ->loopback member. Add an explicit memset(0) before filling the structure to avoid the info leak. Signed-off-by: Dan Carpenter Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman unix_diag: fix info leak [ Upstream commit 6865d1e834be84ddd5808d93d5035b492346c64a ] When filling the netlink message we miss to wipe the pad field, therefore leak one byte of heap memory to userland. Fix this by setting pad to 0. Signed-off-by: Mathias Krause Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman connector: use nlmsg_len() to check message length [ Upstream commit 162b2bedc084d2d908a04c93383ba02348b648b0 ] The current code tests the length of the whole netlink message to be at least as long to fit a cn_msg. This is wrong as nlmsg_len includes the length of the netlink message header. Use nlmsg_len() instead to fix this "off-by-NLMSG_HDRLEN" size check. Signed-off-by: Mathias Krause Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman bnx2x: record rx queue for LRO packets [ Upstream commit 60e66fee56b2256dcb1dc2ea1b2ddcb6e273857d ] RPS support is kind of broken on bnx2x, because only non LRO packets get proper rx queue information. This triggers reorders, as it seems bnx2x like to generate a non LRO packet for segment including TCP PUSH flag : (this might be pure coincidence, but all the reorders I've seen involve segments with a PUSH) 11:13:34.335847 IP A > B: . 415808:447136(31328) ack 1 win 457 11:13:34.335992 IP A > B: . 447136:448560(1424) ack 1 win 457 11:13:34.336391 IP A > B: . 448560:479888(31328) ack 1 win 457 11:13:34.336425 IP A > B: P 511216:512640(1424) ack 1 win 457 11:13:34.336423 IP A > B: . 479888:511216(31328) ack 1 win 457 11:13:34.336924 IP A > B: . 512640:543968(31328) ack 1 win 457 11:13:34.336963 IP A > B: . 543968:575296(31328) ack 1 win 457 We must call skb_record_rx_queue() to properly give to RPS (and more generally for TX queue selection on forward path) the receive queue information. Similar fix is needed for skb_mark_napi_id(), but will be handled in a separate patch to ease stable backports. Signed-off-by: Eric Dumazet Cc: Willem de Bruijn Cc: Eilon Greenstein Acked-by: Dmitry Kravkov Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman net: dst: provide accessor function to dst->xfrm [ Upstream commit e87b3998d795123b4139bc3f25490dd236f68212 ] dst->xfrm is conditionally defined. Provide accessor funtion that is always available. Signed-off-by: Vlad Yasevich Acked-by: Neil Horman Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman sctp: Use software crc32 checksum when xfrm transform will happen. [ Upstream commit 27127a82561a2a3ed955ce207048e1b066a80a2a ] igb/ixgbe have hardware sctp checksum support, when this feature is enabled and also IPsec is armed to protect sctp traffic, ugly things happened as xfrm_output checks CHECKSUM_PARTIAL to do checksum operation(sum every thing up and pack the 16bits result in the checksum field). The result is fail establishment of sctp communication. Signed-off-by: Fan Du Cc: Neil Horman Cc: Steffen Klassert Signed-off-by: Vlad Yasevich Acked-by: Neil Horman Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman sctp: Perform software checksum if packet has to be fragmented. [ Upstream commit d2dbbba77e95dff4b4f901fee236fef6d9552072 ] IP/IPv6 fragmentation knows how to compute only TCP/UDP checksum. This causes problems if SCTP packets has to be fragmented and ipsummed has been set to PARTIAL due to checksum offload support. This condition can happen when retransmitting after MTU discover, or when INIT or other control chunks are larger then MTU. Check for the rare fragmentation condition in SCTP and use software checksum calculation in this case. CC: Fan Du Signed-off-by: Vlad Yasevich Acked-by: Neil Horman Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman wanxl: fix info leak in ioctl [ Upstream commit 2b13d06c9584b4eb773f1e80bbaedab9a1c344e1 ] The wanxl_ioctl() code fails to initialize the two padding bytes of struct sync_serial_settings after the ->loopback member. Add an explicit memset(0) before filling the structure to avoid the info leak. Signed-off-by: Salva Peiró Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman net: unix: inherit SOCK_PASS{CRED, SEC} flags from socket to fix race [ Upstream commit 90c6bd34f884cd9cee21f1d152baf6c18bcac949 ] In the case of credentials passing in unix stream sockets (dgram sockets seem not affected), we get a rather sparse race after commit 16e5726 ("af_unix: dont send SCM_CREDENTIALS by default"). We have a stream server on receiver side that requests credential passing from senders (e.g. nc -U). Since we need to set SO_PASSCRED on each spawned/accepted socket on server side to 1 first (as it's not inherited), it can happen that in the time between accept() and setsockopt() we get interrupted, the sender is being scheduled and continues with passing data to our receiver. At that time SO_PASSCRED is neither set on sender nor receiver side, hence in cmsg's SCM_CREDENTIALS we get eventually pid:0, uid:65534, gid:65534 (== overflow{u,g}id) instead of what we actually would like to see. On the sender side, here nc -U, the tests in maybe_add_creds() invoked through unix_stream_sendmsg() would fail, as at that exact time, as mentioned, the sender has neither SO_PASSCRED on his side nor sees it on the server side, and we have a valid 'other' socket in place. Thus, sender believes it would just look like a normal connection, not needing/requesting SO_PASSCRED at that time. As reverting 16e5726 would not be an option due to the significant performance regression reported when having creds always passed, one way/trade-off to prevent that would be to set SO_PASSCRED on the listener socket and allow inheriting these flags to the spawned socket on server side in accept(). It seems also logical to do so if we'd tell the listener socket to pass those flags onwards, and would fix the race. Before, strace: recvmsg(4, {msg_name(0)=NULL, msg_iov(1)=[{"blub\n", 4096}], msg_controllen=32, {cmsg_len=28, cmsg_level=SOL_SOCKET, cmsg_type=SCM_CREDENTIALS{pid=0, uid=65534, gid=65534}}, msg_flags=0}, 0) = 5 After, strace: recvmsg(4, {msg_name(0)=NULL, msg_iov(1)=[{"blub\n", 4096}], msg_controllen=32, {cmsg_len=28, cmsg_level=SOL_SOCKET, cmsg_type=SCM_CREDENTIALS{pid=11580, uid=1000, gid=1000}}, msg_flags=0}, 0) = 5 Signed-off-by: Daniel Borkmann Cc: Eric Dumazet Cc: Eric W. Biederman Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman net: fix cipso packet validation when !NETLABEL [ Upstream commit f2e5ddcc0d12f9c4c7b254358ad245c9dddce13b ] When CONFIG_NETLABEL is disabled, the cipso_v4_validate() function could loop forever in the main loop if opt[opt_iter +1] == 0, this will causing a kernel crash in an SMP system, since the CPU executing this function will stall /not respond to IPIs. This problem can be reproduced by running the IP Stack Integrity Checker (http://isic.sourceforge.net) using the following command on a Linux machine connected to DUT: "icmpsic -s rand -d -r 123456" wait (1-2 min) Signed-off-by: Seif Mazareeb Acked-by: Paul Moore Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman inet: fix possible memory corruption with UDP_CORK and UFO [ This is a simplified -stable version of a set of upstream commits. ] This is a replacement patch only for stable which does fix the problems handled by the following two commits in -net: "ip_output: do skb ufo init for peeked non ufo skb as well" (e93b7d748be887cd7639b113ba7d7ef792a7efb9) "ip6_output: do skb ufo init for peeked non ufo skb as well" (c547dbf55d5f8cf615ccc0e7265e98db27d3fb8b) Three frames are written on a corked udp socket for which the output netdevice has UFO enabled. If the first and third frame are smaller than the mtu and the second one is bigger, we enqueue the second frame with skb_append_datato_frags without initializing the gso fields. This leads to the third frame appended regulary and thus constructing an invalid skb. This fixes the problem by always using skb_append_datato_frags as soon as the first frag got enqueued to the skb without marking the packet as SKB_GSO_UDP. The problem with only two frames for ipv6 was fixed by "ipv6: udp packets following an UFO enqueued packet need also be handled by UFO" (2811ebac2521ceac84f2bdae402455baa6a7fb47). Cc: Jiri Pirko Cc: Eric Dumazet Cc: David Miller Signed-off-by: Hannes Frederic Sowa Signed-off-by: Greg Kroah-Hartman davinci_emac.c: Fix IFF_ALLMULTI setup [ Upstream commit d69e0f7ea95fef8059251325a79c004bac01f018 ] When IFF_ALLMULTI flag is set on interface and IFF_PROMISC isn't, emac_dev_mcast_set should only enable RX of multicasts and reset MACHASH registers. It does this, but afterwards it either sets up multicast MACs filtering or disables RX of multicasts and resets MACHASH registers again, rendering IFF_ALLMULTI flag useless. This patch fixes emac_dev_mcast_set, so that multicast MACs filtering and disabling of RX of multicasts are skipped when IFF_ALLMULTI flag is set. Tested with kernel 2.6.37. Signed-off-by: Mariusz Ceier Acked-by: Mugunthan V N Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman ext3: return 32/64-bit dir name hash according to usage type commit d7dab39b6e16d5eea78ed3c705d2a2d0772b4f06 upstream. This is based on commit d1f5273e9adb40724a85272f248f210dc4ce919a ext4: return 32/64-bit dir name hash according to usage type by Fan Yong Traditionally ext2/3/4 has returned a 32-bit hash value from llseek() to appease NFSv2, which can only handle a 32-bit cookie for seekdir() and telldir(). However, this causes problems if there are 32-bit hash collisions, since the NFSv2 server can get stuck resending the same entries from the directory repeatedly. Allow ext3 to return a full 64-bit hash (both major and minor) for telldir to decrease the chance of hash collisions. This patch does implement a new ext3_dir_llseek op, because with 64-bit hashes, nfs will attempt to seek to a hash "offset" which is much larger than ext3's s_maxbytes. So for dx dirs, we call generic_file_llseek_size() with the appropriate max hash value as the maximum seekable size. Otherwise we just pass through to generic_file_llseek(). Patch-updated-by: Bernd Schubert Patch-updated-by: Eric Sandeen (blame us if something is not correct) Signed-off-by: Eric Sandeen Signed-off-by: Jan Kara Cc: Benjamin LaHaise Signed-off-by: Greg Kroah-Hartman dm snapshot: fix data corruption commit e9c6a182649f4259db704ae15a91ac820e63b0ca upstream. This patch fixes a particular type of data corruption that has been encountered when loading a snapshot's metadata from disk. When we allocate a new chunk in persistent_prepare, we increment ps->next_free and we make sure that it doesn't point to a metadata area by further incrementing it if necessary. When we load metadata from disk on device activation, ps->next_free is positioned after the last used data chunk. However, if this last used data chunk is followed by a metadata area, ps->next_free is positioned erroneously to the metadata area. A newly-allocated chunk is placed at the same location as the metadata area, resulting in data or metadata corruption. This patch changes the code so that ps->next_free skips the metadata area when metadata are loaded in function read_exceptions. The patch also moves a piece of code from persistent_prepare_exception to a separate function skip_metadata to avoid code duplication. CVE-2013-4299 Signed-off-by: Mikulas Patocka Cc: Mike Snitzer Signed-off-by: Alasdair G Kergon Signed-off-by: Greg Kroah-Hartman writeback: fix negative bdi max pause commit e3b6c655b91e01a1dade056cfa358581b47a5351 upstream. Toralf runs trinity on UML/i386. After some time it hangs and the last message line is BUG: soft lockup - CPU#0 stuck for 22s! [trinity-child0:1521] It's found that pages_dirtied becomes very large. More than 1000000000 pages in this case: period = HZ * pages_dirtied / task_ratelimit; BUG_ON(pages_dirtied > 2000000000); BUG_ON(pages_dirtied > 1000000000); <--------- UML debug printf shows that we got negative pause here: ick: pause : -984 ick: pages_dirtied : 0 ick: task_ratelimit: 0 pause: + if (pause < 0) { + extern int printf(char *, ...); + printf("ick : pause : %li\n", pause); + printf("ick: pages_dirtied : %lu\n", pages_dirtied); + printf("ick: task_ratelimit: %lu\n", task_ratelimit); + BUG_ON(1); + } trace_balance_dirty_pages(bdi, Since pause is bounded by [min_pause, max_pause] where min_pause is also bounded by max_pause. It's suspected and demonstrated that the max_pause calculation goes wrong: ick: pause : -717 ick: min_pause : -177 ick: max_pause : -717 ick: pages_dirtied : 14 ick: task_ratelimit: 0 The problem lies in the two "long = unsigned long" assignments in bdi_max_pause() which might go negative if the highest bit is 1, and the min_t(long, ...) check failed to protect it falling under 0. Fix all of them by using "unsigned long" throughout the function. Signed-off-by: Fengguang Wu Reported-by: Toralf Förster Tested-by: Toralf Förster Reviewed-by: Jan Kara Cc: Richard Weinberger Cc: Geert Uytterhoeven Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman wireless: radiotap: fix parsing buffer overrun commit f5563318ff1bde15b10e736e97ffce13be08bc1a upstream. When parsing an invalid radiotap header, the parser can overrun the buffer that is passed in because it doesn't correctly check 1) the minimum radiotap header size 2) the space for extended bitmaps The first issue doesn't affect any in-kernel user as they all check the minimum size before calling the radiotap function. The second issue could potentially affect the kernel if an skb is passed in that consists only of the radiotap header with a lot of extended bitmaps that extend past the SKB. In that case a read-only buffer overrun by at most 4 bytes is possible. Fix this by adding the appropriate checks to the parser. Reported-by: Evan Huus Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman USB: serial: ti_usb_3410_5052: add Abbott strip port ID to combined table as well. commit c9d09dc7ad106492c17c587b6eeb99fe3f43e522 upstream. Without this change, the USB cable for Freestyle Option and compatible glucometers will not be detected by the driver. Signed-off-by: Diego Elio Pettenò Signed-off-by: Greg Kroah-Hartman USB: serial: option: add support for Inovia SEW858 device commit f4c19b8e165cff1a6607c21f8809441d61cab7ec upstream. This patch adds the device id for the Inovia SEW858 device to the option driver. Reported-by: Pavel Parkhomenko Tested-by: Pavel Parkhomenko Signed-off-by: Greg Kroah-Hartman usb: serial: option: blacklist Olivetti Olicard200 commit fd8573f5828873343903215f203f14dc82de397c upstream. Interface 6 of this device speaks QMI as per tests done by us. Credits go to Antonella for providing the hardware. Signed-off-by: Enrico Mioso Signed-off-by: Antonella Pellizzari Tested-by: Dan Williams Signed-off-by: Greg Kroah-Hartman --- Makefile | 2 +- drivers/connector/cn_proc.c | 16 ++ drivers/connector/connector.c | 7 +- drivers/md/dm-snap-persistent.c | 18 +- drivers/net/can/dev.c | 10 +- .../net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | 1 + drivers/net/ethernet/marvell/mv643xx_eth.c | 6 +- drivers/net/ethernet/ti/davinci_emac.c | 3 +- drivers/net/wan/farsync.c | 1 + drivers/net/wan/wanxl.c | 1 + drivers/usb/serial/option.c | 9 +- drivers/usb/serial/ti_usb_3410_5052.c | 1 + fs/ext3/dir.c | 167 +++++++++++++----- fs/ext3/ext3.h | 6 +- fs/ext3/hash.c | 4 +- include/linux/skbuff.h | 15 ++ include/net/cipso_ipv4.h | 6 +- include/net/dst.h | 12 ++ mm/page-writeback.c | 10 +- net/8021q/vlan_netlink.c | 2 +- net/bridge/br_stp_if.c | 2 +- net/compat.c | 2 + net/ipv4/inet_hashtables.c | 2 +- net/ipv4/ip_output.c | 2 +- net/ipv4/route.c | 2 +- net/ipv4/tcp_input.c | 5 +- net/ipv4/tcp_output.c | 9 +- net/ipv6/inet6_hashtables.c | 2 +- net/ipv6/ip6_output.c | 2 +- net/ipv6/route.c | 11 +- net/l2tp/l2tp_ppp.c | 4 + net/sctp/output.c | 3 +- net/socket.c | 24 ++- net/unix/af_unix.c | 10 ++ net/unix/diag.c | 1 + net/wireless/radiotap.c | 7 +- 36 files changed, 287 insertions(+), 98 deletions(-) diff --git a/Makefile b/Makefile index 0774f1871de..9d74b73729f 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 4 -SUBLEVEL = 67 +SUBLEVEL = 68 EXTRAVERSION = NAME = Saber-toothed Squirrel diff --git a/drivers/connector/cn_proc.c b/drivers/connector/cn_proc.c index 77e1e6cd66c..2894461e0bd 100644 --- a/drivers/connector/cn_proc.c +++ b/drivers/connector/cn_proc.c @@ -64,6 +64,7 @@ void proc_fork_connector(struct task_struct *task) msg = (struct cn_msg*)buffer; ev = (struct proc_event*)msg->data; + memset(&ev->event_data, 0, sizeof(ev->event_data)); get_seq(&msg->seq, &ev->cpu); ktime_get_ts(&ts); /* get high res monotonic timestamp */ put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); @@ -79,6 +80,7 @@ void proc_fork_connector(struct task_struct *task) memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); msg->ack = 0; /* not used */ msg->len = sizeof(*ev); + msg->flags = 0; /* not used */ /* If cn_netlink_send() failed, the data is not sent */ cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); } @@ -95,6 +97,7 @@ void proc_exec_connector(struct task_struct *task) msg = (struct cn_msg*)buffer; ev = (struct proc_event*)msg->data; + memset(&ev->event_data, 0, sizeof(ev->event_data)); get_seq(&msg->seq, &ev->cpu); ktime_get_ts(&ts); /* get high res monotonic timestamp */ put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); @@ -105,6 +108,7 @@ void proc_exec_connector(struct task_struct *task) memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); msg->ack = 0; /* not used */ msg->len = sizeof(*ev); + msg->flags = 0; /* not used */ cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); } @@ -121,6 +125,7 @@ void proc_id_connector(struct task_struct *task, int which_id) msg = (struct cn_msg*)buffer; ev = (struct proc_event*)msg->data; + memset(&ev->event_data, 0, sizeof(ev->event_data)); ev->what = which_id; ev->event_data.id.process_pid = task->pid; ev->event_data.id.process_tgid = task->tgid; @@ -144,6 +149,7 @@ void proc_id_connector(struct task_struct *task, int which_id) memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); msg->ack = 0; /* not used */ msg->len = sizeof(*ev); + msg->flags = 0; /* not used */ cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); } @@ -159,6 +165,7 @@ void proc_sid_connector(struct task_struct *task) msg = (struct cn_msg *)buffer; ev = (struct proc_event *)msg->data; + memset(&ev->event_data, 0, sizeof(ev->event_data)); get_seq(&msg->seq, &ev->cpu); ktime_get_ts(&ts); /* get high res monotonic timestamp */ put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); @@ -169,6 +176,7 @@ void proc_sid_connector(struct task_struct *task) memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); msg->ack = 0; /* not used */ msg->len = sizeof(*ev); + msg->flags = 0; /* not used */ cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); } @@ -184,6 +192,7 @@ void proc_ptrace_connector(struct task_struct *task, int ptrace_id) msg = (struct cn_msg *)buffer; ev = (struct proc_event *)msg->data; + memset(&ev->event_data, 0, sizeof(ev->event_data)); get_seq(&msg->seq, &ev->cpu); ktime_get_ts(&ts); /* get high res monotonic timestamp */ put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); @@ -202,6 +211,7 @@ void proc_ptrace_connector(struct task_struct *task, int ptrace_id) memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); msg->ack = 0; /* not used */ msg->len = sizeof(*ev); + msg->flags = 0; /* not used */ cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); } @@ -217,6 +227,7 @@ void proc_comm_connector(struct task_struct *task) msg = (struct cn_msg *)buffer; ev = (struct proc_event *)msg->data; + memset(&ev->event_data, 0, sizeof(ev->event_data)); get_seq(&msg->seq, &ev->cpu); ktime_get_ts(&ts); /* get high res monotonic timestamp */ put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); @@ -228,6 +239,7 @@ void proc_comm_connector(struct task_struct *task) memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); msg->ack = 0; /* not used */ msg->len = sizeof(*ev); + msg->flags = 0; /* not used */ cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); } @@ -243,6 +255,7 @@ void proc_exit_connector(struct task_struct *task) msg = (struct cn_msg*)buffer; ev = (struct proc_event*)msg->data; + memset(&ev->event_data, 0, sizeof(ev->event_data)); get_seq(&msg->seq, &ev->cpu); ktime_get_ts(&ts); /* get high res monotonic timestamp */ put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); @@ -255,6 +268,7 @@ void proc_exit_connector(struct task_struct *task) memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); msg->ack = 0; /* not used */ msg->len = sizeof(*ev); + msg->flags = 0; /* not used */ cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); } @@ -278,6 +292,7 @@ static void cn_proc_ack(int err, int rcvd_seq, int rcvd_ack) msg = (struct cn_msg*)buffer; ev = (struct proc_event*)msg->data; + memset(&ev->event_data, 0, sizeof(ev->event_data)); msg->seq = rcvd_seq; ktime_get_ts(&ts); /* get high res monotonic timestamp */ put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); @@ -287,6 +302,7 @@ static void cn_proc_ack(int err, int rcvd_seq, int rcvd_ack) memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); msg->ack = rcvd_ack + 1; msg->len = sizeof(*ev); + msg->flags = 0; /* not used */ cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); } diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c index dde6a0fad40..ea6efe86468 100644 --- a/drivers/connector/connector.c +++ b/drivers/connector/connector.c @@ -157,17 +157,18 @@ static int cn_call_callback(struct sk_buff *skb) static void cn_rx_skb(struct sk_buff *__skb) { struct nlmsghdr *nlh; - int err; struct sk_buff *skb; + int len, err; skb = skb_get(__skb); if (skb->len >= NLMSG_SPACE(0)) { nlh = nlmsg_hdr(skb); + len = nlmsg_len(nlh); - if (nlh->nlmsg_len < sizeof(struct cn_msg) || + if (len < (int)sizeof(struct cn_msg) || skb->len < nlh->nlmsg_len || - nlh->nlmsg_len > CONNECTOR_MAX_MSG_SIZE) { + len > CONNECTOR_MAX_MSG_SIZE) { kfree_skb(skb); return; } diff --git a/drivers/md/dm-snap-persistent.c b/drivers/md/dm-snap-persistent.c index 4caa8e6d59d..2d2b1b7588d 100644 --- a/drivers/md/dm-snap-persistent.c +++ b/drivers/md/dm-snap-persistent.c @@ -269,6 +269,14 @@ static chunk_t area_location(struct pstore *ps, chunk_t area) return NUM_SNAPSHOT_HDR_CHUNKS + ((ps->exceptions_per_area + 1) * area); } +static void skip_metadata(struct pstore *ps) +{ + uint32_t stride = ps->exceptions_per_area + 1; + chunk_t next_free = ps->next_free; + if (sector_div(next_free, stride) == NUM_SNAPSHOT_HDR_CHUNKS) + ps->next_free++; +} + /* * Read or write a metadata area. Remembering to skip the first * chunk which holds the header. @@ -502,6 +510,8 @@ static int read_exceptions(struct pstore *ps, ps->current_area--; + skip_metadata(ps); + return 0; } @@ -616,8 +626,6 @@ static int persistent_prepare_exception(struct dm_exception_store *store, struct dm_exception *e) { struct pstore *ps = get_info(store); - uint32_t stride; - chunk_t next_free; sector_t size = get_dev_size(dm_snap_cow(store->snap)->bdev); /* Is there enough room ? */ @@ -630,10 +638,8 @@ static int persistent_prepare_exception(struct dm_exception_store *store, * Move onto the next free pending, making sure to take * into account the location of the metadata chunks. */ - stride = (ps->exceptions_per_area + 1); - next_free = ++ps->next_free; - if (sector_div(next_free, stride) == 1) - ps->next_free++; + ps->next_free++; + skip_metadata(ps); atomic_inc(&ps->pending_count); return 0; diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c index e86f4c37f98..c2cdefa1651 100644 --- a/drivers/net/can/dev.c +++ b/drivers/net/can/dev.c @@ -665,14 +665,14 @@ static size_t can_get_size(const struct net_device *dev) size_t size; size = nla_total_size(sizeof(u32)); /* IFLA_CAN_STATE */ - size += sizeof(struct can_ctrlmode); /* IFLA_CAN_CTRLMODE */ + size += nla_total_size(sizeof(struct can_ctrlmode)); /* IFLA_CAN_CTRLMODE */ size += nla_total_size(sizeof(u32)); /* IFLA_CAN_RESTART_MS */ - size += sizeof(struct can_bittiming); /* IFLA_CAN_BITTIMING */ - size += sizeof(struct can_clock); /* IFLA_CAN_CLOCK */ + size += nla_total_size(sizeof(struct can_bittiming)); /* IFLA_CAN_BITTIMING */ + size += nla_total_size(sizeof(struct can_clock)); /* IFLA_CAN_CLOCK */ if (priv->do_get_berr_counter) /* IFLA_CAN_BERR_COUNTER */ - size += sizeof(struct can_berr_counter); + size += nla_total_size(sizeof(struct can_berr_counter)); if (priv->bittiming_const) /* IFLA_CAN_BITTIMING_CONST */ - size += sizeof(struct can_bittiming_const); + size += nla_total_size(sizeof(struct can_bittiming_const)); return size; } diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index acd82466036..e45b8b6d684 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -547,6 +547,7 @@ static inline void bnx2x_tpa_stop(struct bnx2x *bp, struct bnx2x_fastpath *fp, skb, cqe, cqe_idx)) { if (tpa_info->parsing_flags & PARSING_FLAGS_VLAN) __vlan_hwaccel_put_tag(skb, tpa_info->vlan_tag); + skb_record_rx_queue(skb, fp->rx_queue); napi_gro_receive(&fp->napi, skb); } else { DP(NETIF_MSG_RX_STATUS, diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c index 5e1ca0f0509..ffa6a72dcc6 100644 --- a/drivers/net/ethernet/marvell/mv643xx_eth.c +++ b/drivers/net/ethernet/marvell/mv643xx_eth.c @@ -1274,15 +1274,13 @@ static void mib_counters_update(struct mv643xx_eth_private *mp) p->rx_discard += rdlp(mp, RX_DISCARD_FRAME_CNT); p->rx_overrun += rdlp(mp, RX_OVERRUN_FRAME_CNT); spin_unlock_bh(&mp->mib_counters_lock); - - mod_timer(&mp->mib_counters_timer, jiffies + 30 * HZ); } static void mib_counters_timer_wrapper(unsigned long _mp) { struct mv643xx_eth_private *mp = (void *)_mp; - mib_counters_update(mp); + mod_timer(&mp->mib_counters_timer, jiffies + 30 * HZ); } @@ -2370,6 +2368,7 @@ static int mv643xx_eth_open(struct net_device *dev) mp->int_mask |= INT_TX_END_0 << i; } + add_timer(&mp->mib_counters_timer); port_start(mp); wrlp(mp, INT_MASK_EXT, INT_EXT_LINK_PHY | INT_EXT_TX); @@ -2911,7 +2910,6 @@ static int mv643xx_eth_probe(struct platform_device *pdev) mp->mib_counters_timer.data = (unsigned long)mp; mp->mib_counters_timer.function = mib_counters_timer_wrapper; mp->mib_counters_timer.expires = jiffies + 30 * HZ; - add_timer(&mp->mib_counters_timer); spin_lock_init(&mp->mib_counters_lock); diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c index 43fada57259..c336d36cf5c 100644 --- a/drivers/net/ethernet/ti/davinci_emac.c +++ b/drivers/net/ethernet/ti/davinci_emac.c @@ -875,8 +875,7 @@ static void emac_dev_mcast_set(struct net_device *ndev) netdev_mc_count(ndev) > EMAC_DEF_MAX_MULTICAST_ADDRESSES) { mbp_enable = (mbp_enable | EMAC_MBP_RXMCAST); emac_add_mcast(priv, EMAC_ALL_MULTI_SET, NULL); - } - if (!netdev_mc_empty(ndev)) { + } else if (!netdev_mc_empty(ndev)) { struct netdev_hw_addr *ha; mbp_enable = (mbp_enable | EMAC_MBP_RXMCAST); diff --git a/drivers/net/wan/farsync.c b/drivers/net/wan/farsync.c index 1a623183cbe..3710427c3fe 100644 --- a/drivers/net/wan/farsync.c +++ b/drivers/net/wan/farsync.c @@ -1972,6 +1972,7 @@ fst_get_iface(struct fst_card_info *card, struct fst_port_info *port, } i = port->index; + memset(&sync, 0, sizeof(sync)); sync.clock_rate = FST_RDL(card, portConfig[i].lineSpeed); /* Lucky card and linux use same encoding here */ sync.clock_type = FST_RDB(card, portConfig[i].internalClock) == diff --git a/drivers/net/wan/wanxl.c b/drivers/net/wan/wanxl.c index feb7541b33f..ccd496bf32d 100644 --- a/drivers/net/wan/wanxl.c +++ b/drivers/net/wan/wanxl.c @@ -355,6 +355,7 @@ static int wanxl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) ifr->ifr_settings.size = size; /* data size wanted */ return -ENOBUFS; } + memset(&line, 0, sizeof(line)); line.clock_type = get_status(port)->clocking; line.clock_rate = 0; line.loopback = 0; diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 9def72f018e..b3440c66a99 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -457,6 +457,10 @@ static void option_instat_callback(struct urb *urb); #define CHANGHONG_VENDOR_ID 0x2077 #define CHANGHONG_PRODUCT_CH690 0x7001 +/* Inovia */ +#define INOVIA_VENDOR_ID 0x20a6 +#define INOVIA_SEW858 0x1105 + /* some devices interfaces need special handling due to a number of reasons */ enum option_blacklist_reason { OPTION_BLACKLIST_NONE = 0, @@ -1279,7 +1283,9 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD100) }, { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD145) }, - { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD200) }, + { USB_DEVICE(OLIVETTI_VENDOR_ID, OLIVETTI_PRODUCT_OLICARD200), + .driver_info = (kernel_ulong_t)&net_intf6_blacklist + }, { USB_DEVICE(CELOT_VENDOR_ID, CELOT_PRODUCT_CT680M) }, /* CT-650 CDMA 450 1xEVDO modem */ { USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_GT_B3730, USB_CLASS_CDC_DATA, 0x00, 0x00) }, /* Samsung GT-B3730 LTE USB modem.*/ { USB_DEVICE(YUGA_VENDOR_ID, YUGA_PRODUCT_CEM600) }, @@ -1367,6 +1373,7 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x7d03, 0xff, 0x00, 0x00) }, { USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3e01, 0xff, 0xff, 0xff) }, /* D-Link DWM-152/C1 */ { USB_DEVICE_AND_INTERFACE_INFO(0x07d1, 0x3e02, 0xff, 0xff, 0xff) }, /* D-Link DWM-156/C1 */ + { USB_DEVICE(INOVIA_VENDOR_ID, INOVIA_SEW858) }, { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, option_ids); diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index a7492ba5371..1b0430e00b7 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -210,6 +210,7 @@ static struct usb_device_id ti_id_table_combined[19+2*TI_EXTRA_VID_PID_COUNT+1] { USB_DEVICE(IBM_VENDOR_ID, IBM_454B_PRODUCT_ID) }, { USB_DEVICE(IBM_VENDOR_ID, IBM_454C_PRODUCT_ID) }, { USB_DEVICE(ABBOTT_VENDOR_ID, ABBOTT_PRODUCT_ID) }, + { USB_DEVICE(ABBOTT_VENDOR_ID, ABBOTT_STRIP_PORT_ID) }, { USB_DEVICE(TI_VENDOR_ID, FRI2_PRODUCT_ID) }, { } }; diff --git a/fs/ext3/dir.c b/fs/ext3/dir.c index cc761ad8fa5..92490e9f85c 100644 --- a/fs/ext3/dir.c +++ b/fs/ext3/dir.c @@ -21,30 +21,15 @@ * */ +#include #include "ext3.h" static unsigned char ext3_filetype_table[] = { DT_UNKNOWN, DT_REG, DT_DIR, DT_CHR, DT_BLK, DT_FIFO, DT_SOCK, DT_LNK }; -static int ext3_readdir(struct file *, void *, filldir_t); static int ext3_dx_readdir(struct file * filp, void * dirent, filldir_t filldir); -static int ext3_release_dir (struct inode * inode, - struct file * filp); - -const struct file_operations ext3_dir_operations = { - .llseek = generic_file_llseek, - .read = generic_read_dir, - .readdir = ext3_readdir, /* we take BKL. needed?*/ - .unlocked_ioctl = ext3_ioctl, -#ifdef CONFIG_COMPAT - .compat_ioctl = ext3_compat_ioctl, -#endif - .fsync = ext3_sync_file, /* BKL held */ - .release = ext3_release_dir, -}; - static unsigned char get_dtype(struct super_block *sb, int filetype) { @@ -55,6 +40,25 @@ static unsigned char get_dtype(struct super_block *sb, int filetype) return (ext3_filetype_table[filetype]); } +/** + * Check if the given dir-inode refers to an htree-indexed directory + * (or a directory which chould potentially get coverted to use htree + * indexing). + * + * Return 1 if it is a dx dir, 0 if not + */ +static int is_dx_dir(struct inode *inode) +{ + struct super_block *sb = inode->i_sb; + + if (EXT3_HAS_COMPAT_FEATURE(inode->i_sb, + EXT3_FEATURE_COMPAT_DIR_INDEX) && + ((EXT3_I(inode)->i_flags & EXT3_INDEX_FL) || + ((inode->i_size >> sb->s_blocksize_bits) == 1))) + return 1; + + return 0; +} int ext3_check_dir_entry (const char * function, struct inode * dir, struct ext3_dir_entry_2 * de, @@ -94,18 +98,13 @@ static int ext3_readdir(struct file * filp, unsigned long offset; int i, stored; struct ext3_dir_entry_2 *de; - struct super_block *sb; int err; struct inode *inode = filp->f_path.dentry->d_inode; + struct super_block *sb = inode->i_sb; int ret = 0; int dir_has_error = 0; - sb = inode->i_sb; - - if (EXT3_HAS_COMPAT_FEATURE(inode->i_sb, - EXT3_FEATURE_COMPAT_DIR_INDEX) && - ((EXT3_I(inode)->i_flags & EXT3_INDEX_FL) || - ((inode->i_size >> sb->s_blocksize_bits) == 1))) { + if (is_dx_dir(inode)) { err = ext3_dx_readdir(filp, dirent, filldir); if (err != ERR_BAD_DX_DIR) { ret = err; @@ -227,22 +226,87 @@ static int ext3_readdir(struct file * filp, return ret; } +static inline int is_32bit_api(void) +{ +#ifdef CONFIG_COMPAT + return is_compat_task(); +#else + return (BITS_PER_LONG == 32); +#endif +} + /* * These functions convert from the major/minor hash to an f_pos - * value. + * value for dx directories * - * Currently we only use major hash numer. This is unfortunate, but - * on 32-bit machines, the same VFS interface is used for lseek and - * llseek, so if we use the 64 bit offset, then the 32-bit versions of - * lseek/telldir/seekdir will blow out spectacularly, and from within - * the ext2 low-level routine, we don't know if we're being called by - * a 64-bit version of the system call or the 32-bit version of the - * system call. Worse yet, NFSv2 only allows for a 32-bit readdir - * cookie. Sigh. + * Upper layer (for example NFS) should specify FMODE_32BITHASH or + * FMODE_64BITHASH explicitly. On the other hand, we allow ext3 to be mounted + * directly on both 32-bit and 64-bit nodes, under such case, neither + * FMODE_32BITHASH nor FMODE_64BITHASH is specified. */ -#define hash2pos(major, minor) (major >> 1) -#define pos2maj_hash(pos) ((pos << 1) & 0xffffffff) -#define pos2min_hash(pos) (0) +static inline loff_t hash2pos(struct file *filp, __u32 major, __u32 minor) +{ + if ((filp->f_mode & FMODE_32BITHASH) || + (!(filp->f_mode & FMODE_64BITHASH) && is_32bit_api())) + return major >> 1; + else + return ((__u64)(major >> 1) << 32) | (__u64)minor; +} + +static inline __u32 pos2maj_hash(struct file *filp, loff_t pos) +{ + if ((filp->f_mode & FMODE_32BITHASH) || + (!(filp->f_mode & FMODE_64BITHASH) && is_32bit_api())) + return (pos << 1) & 0xffffffff; + else + return ((pos >> 32) << 1) & 0xffffffff; +} + +static inline __u32 pos2min_hash(struct file *filp, loff_t pos) +{ + if ((filp->f_mode & FMODE_32BITHASH) || + (!(filp->f_mode & FMODE_64BITHASH) && is_32bit_api())) + return 0; + else + return pos & 0xffffffff; +} + +/* + * Return 32- or 64-bit end-of-file for dx directories + */ +static inline loff_t ext3_get_htree_eof(struct file *filp) +{ + if ((filp->f_mode & FMODE_32BITHASH) || + (!(filp->f_mode & FMODE_64BITHASH) && is_32bit_api())) + return EXT3_HTREE_EOF_32BIT; + else + return EXT3_HTREE_EOF_64BIT; +} + + +/* + * ext3_dir_llseek() calls generic_file_llseek[_size]() to handle both + * non-htree and htree directories, where the "offset" is in terms + * of the filename hash value instead of the byte offset. + * + * Because we may return a 64-bit hash that is well beyond s_maxbytes, + * we need to pass the max hash as the maximum allowable offset in + * the htree directory case. + * + * NOTE: offsets obtained *before* ext3_set_inode_flag(dir, EXT3_INODE_INDEX) + * will be invalid once the directory was converted into a dx directory + */ +loff_t ext3_dir_llseek(struct file *file, loff_t offset, int origin) +{ + struct inode *inode = file->f_mapping->host; + int dx_dir = is_dx_dir(inode); + + if (likely(dx_dir)) + return generic_file_llseek_size(file, offset, origin, + ext3_get_htree_eof(file)); + else + return generic_file_llseek(file, offset, origin); +} /* * This structure holds the nodes of the red-black tree used to store @@ -303,15 +367,16 @@ static void free_rb_tree_fname(struct rb_root *root) } -static struct dir_private_info *ext3_htree_create_dir_info(loff_t pos) +static struct dir_private_info *ext3_htree_create_dir_info(struct file *filp, + loff_t pos) { struct dir_private_info *p; p = kzalloc(sizeof(struct dir_private_info), GFP_KERNEL); if (!p) return NULL; - p->curr_hash = pos2maj_hash(pos); - p->curr_minor_hash = pos2min_hash(pos); + p->curr_hash = pos2maj_hash(filp, pos); + p->curr_minor_hash = pos2min_hash(filp, pos); return p; } @@ -401,7 +466,7 @@ static int call_filldir(struct file * filp, void * dirent, printk("call_filldir: called with null fname?!?\n"); return 0; } - curr_pos = hash2pos(fname->hash, fname->minor_hash); + curr_pos = hash2pos(filp, fname->hash, fname->minor_hash); while (fname) { error = filldir(dirent, fname->name, fname->name_len, curr_pos, @@ -426,13 +491,13 @@ static int ext3_dx_readdir(struct file * filp, int ret; if (!info) { - info = ext3_htree_create_dir_info(filp->f_pos); + info = ext3_htree_create_dir_info(filp, filp->f_pos); if (!info) return -ENOMEM; filp->private_data = info; } - if (filp->f_pos == EXT3_HTREE_EOF) + if (filp->f_pos == ext3_get_htree_eof(filp)) return 0; /* EOF */ /* Some one has messed with f_pos; reset the world */ @@ -440,8 +505,8 @@ static int ext3_dx_readdir(struct file * filp, free_rb_tree_fname(&info->root); info->curr_node = NULL; info->extra_fname = NULL; - info->curr_hash = pos2maj_hash(filp->f_pos); - info->curr_minor_hash = pos2min_hash(filp->f_pos); + info->curr_hash = pos2maj_hash(filp, filp->f_pos); + info->curr_minor_hash = pos2min_hash(filp, filp->f_pos); } /* @@ -473,7 +538,7 @@ static int ext3_dx_readdir(struct file * filp, if (ret < 0) return ret; if (ret == 0) { - filp->f_pos = EXT3_HTREE_EOF; + filp->f_pos = ext3_get_htree_eof(filp); break; } info->curr_node = rb_first(&info->root); @@ -493,7 +558,7 @@ static int ext3_dx_readdir(struct file * filp, info->curr_minor_hash = fname->minor_hash; } else { if (info->next_hash == ~0) { - filp->f_pos = EXT3_HTREE_EOF; + filp->f_pos = ext3_get_htree_eof(filp); break; } info->curr_hash = info->next_hash; @@ -512,3 +577,15 @@ static int ext3_release_dir (struct inode * inode, struct file * filp) return 0; } + +const struct file_operations ext3_dir_operations = { + .llseek = ext3_dir_llseek, + .read = generic_read_dir, + .readdir = ext3_readdir, + .unlocked_ioctl = ext3_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = ext3_compat_ioctl, +#endif + .fsync = ext3_sync_file, + .release = ext3_release_dir, +}; diff --git a/fs/ext3/ext3.h b/fs/ext3/ext3.h index b6515fd7e56..fe5bef7914e 100644 --- a/fs/ext3/ext3.h +++ b/fs/ext3/ext3.h @@ -920,7 +920,11 @@ struct dx_hash_info u32 *seed; }; -#define EXT3_HTREE_EOF 0x7fffffff + +/* 32 and 64 bit signed EOF for dx directories */ +#define EXT3_HTREE_EOF_32BIT ((1UL << (32 - 1)) - 1) +#define EXT3_HTREE_EOF_64BIT ((1ULL << (64 - 1)) - 1) + /* * Control parameters used by ext3_htree_next_block diff --git a/fs/ext3/hash.c b/fs/ext3/hash.c index d10231ddcf8..ede315cdf12 100644 --- a/fs/ext3/hash.c +++ b/fs/ext3/hash.c @@ -198,8 +198,8 @@ int ext3fs_dirhash(const char *name, int len, struct dx_hash_info *hinfo) return -1; } hash = hash & ~1; - if (hash == (EXT3_HTREE_EOF << 1)) - hash = (EXT3_HTREE_EOF-1) << 1; + if (hash == (EXT3_HTREE_EOF_32BIT << 1)) + hash = (EXT3_HTREE_EOF_32BIT - 1) << 1; hinfo->hash = hash; hinfo->minor_hash = minor_hash; return 0; diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index dc4d49a0c07..42b919c36da 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -760,6 +760,16 @@ static inline int skb_cloned(const struct sk_buff *skb) (atomic_read(&skb_shinfo(skb)->dataref) & SKB_DATAREF_MASK) != 1; } +static inline int skb_unclone(struct sk_buff *skb, gfp_t pri) +{ + might_sleep_if(pri & __GFP_WAIT); + + if (skb_cloned(skb)) + return pskb_expand_head(skb, 0, 0, pri); + + return 0; +} + /** * skb_header_cloned - is the header a clone * @skb: buffer to check @@ -1198,6 +1208,11 @@ static inline int skb_pagelen(const struct sk_buff *skb) return len + skb_headlen(skb); } +static inline bool skb_has_frags(const struct sk_buff *skb) +{ + return skb_shinfo(skb)->nr_frags; +} + /** * __skb_fill_page_desc - initialise a paged fragment in an skb * @skb: buffer containing fragment to be initialised diff --git a/include/net/cipso_ipv4.h b/include/net/cipso_ipv4.h index a7a683e30b6..a8c2ef6d3b9 100644 --- a/include/net/cipso_ipv4.h +++ b/include/net/cipso_ipv4.h @@ -290,6 +290,7 @@ static inline int cipso_v4_validate(const struct sk_buff *skb, unsigned char err_offset = 0; u8 opt_len = opt[1]; u8 opt_iter; + u8 tag_len; if (opt_len < 8) { err_offset = 1; @@ -302,11 +303,12 @@ static inline int cipso_v4_validate(const struct sk_buff *skb, } for (opt_iter = 6; opt_iter < opt_len;) { - if (opt[opt_iter + 1] > (opt_len - opt_iter)) { + tag_len = opt[opt_iter + 1]; + if ((tag_len == 0) || (opt[opt_iter + 1] > (opt_len - opt_iter))) { err_offset = opt_iter + 1; goto out; } - opt_iter += opt[opt_iter + 1]; + opt_iter += tag_len; } out: diff --git a/include/net/dst.h b/include/net/dst.h index 8197eadca81..1efe71aad08 100644 --- a/include/net/dst.h +++ b/include/net/dst.h @@ -464,10 +464,22 @@ static inline struct dst_entry *xfrm_lookup(struct net *net, { return dst_orig; } + +static inline struct xfrm_state *dst_xfrm(const struct dst_entry *dst) +{ + return NULL; +} + #else extern struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig, const struct flowi *fl, struct sock *sk, int flags); + +/* skb attached with this dst needs transformation if dst->xfrm is valid */ +static inline struct xfrm_state *dst_xfrm(const struct dst_entry *dst) +{ + return dst->xfrm; +} #endif #endif /* _NET_DST_H */ diff --git a/mm/page-writeback.c b/mm/page-writeback.c index dfe58f4e4fd..91ed7ed5182 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c @@ -1072,11 +1072,11 @@ static unsigned long dirty_poll_interval(unsigned long dirty, return 1; } -static long bdi_max_pause(struct backing_dev_info *bdi, - unsigned long bdi_dirty) +static unsigned long bdi_max_pause(struct backing_dev_info *bdi, + unsigned long bdi_dirty) { - long bw = bdi->avg_write_bandwidth; - long t; + unsigned long bw = bdi->avg_write_bandwidth; + unsigned long t; /* * Limit pause time for small memory systems. If sleeping for too long @@ -1088,7 +1088,7 @@ static long bdi_max_pause(struct backing_dev_info *bdi, t = bdi_dirty / (1 + bw / roundup_pow_of_two(1 + HZ / 8)); t++; - return min_t(long, t, MAX_PAUSE); + return min_t(unsigned long, t, MAX_PAUSE); } static long bdi_min_pause(struct backing_dev_info *bdi, diff --git a/net/8021q/vlan_netlink.c b/net/8021q/vlan_netlink.c index 50711368ad6..7f046b4c06b 100644 --- a/net/8021q/vlan_netlink.c +++ b/net/8021q/vlan_netlink.c @@ -152,7 +152,7 @@ static size_t vlan_get_size(const struct net_device *dev) struct vlan_dev_priv *vlan = vlan_dev_priv(dev); return nla_total_size(2) + /* IFLA_VLAN_ID */ - sizeof(struct ifla_vlan_flags) + /* IFLA_VLAN_FLAGS */ + nla_total_size(sizeof(struct ifla_vlan_flags)) + /* IFLA_VLAN_FLAGS */ vlan_qos_map_size(vlan->nr_ingress_mappings) + vlan_qos_map_size(vlan->nr_egress_mappings); } diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c index f774796f7e5..2f100ccef86 100644 --- a/net/bridge/br_stp_if.c +++ b/net/bridge/br_stp_if.c @@ -134,7 +134,7 @@ static void br_stp_start(struct net_bridge *br) if (br->bridge_forward_delay < BR_MIN_FORWARD_DELAY) __br_set_forward_delay(br, BR_MIN_FORWARD_DELAY); - else if (br->bridge_forward_delay < BR_MAX_FORWARD_DELAY) + else if (br->bridge_forward_delay > BR_MAX_FORWARD_DELAY) __br_set_forward_delay(br, BR_MAX_FORWARD_DELAY); if (r == 0) { diff --git a/net/compat.c b/net/compat.c index 014e1c78ecc..ee84d82d728 100644 --- a/net/compat.c +++ b/net/compat.c @@ -71,6 +71,8 @@ int get_compat_msghdr(struct msghdr *kmsg, struct compat_msghdr __user *umsg) __get_user(kmsg->msg_controllen, &umsg->msg_controllen) || __get_user(kmsg->msg_flags, &umsg->msg_flags)) return -EFAULT; + if (kmsg->msg_namelen > sizeof(struct sockaddr_storage)) + return -EINVAL; kmsg->msg_name = compat_ptr(tmp1); kmsg->msg_iov = compat_ptr(tmp2); kmsg->msg_control = compat_ptr(tmp3); diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c index 984ec656b03..4afcf31bdfe 100644 --- a/net/ipv4/inet_hashtables.c +++ b/net/ipv4/inet_hashtables.c @@ -268,7 +268,7 @@ struct sock * __inet_lookup_established(struct net *net, } if (unlikely(!INET_TW_MATCH(sk, net, hash, acookie, saddr, daddr, ports, dif))) { - sock_put(sk); + inet_twsk_put(inet_twsk(sk)); goto begintw; } goto out; diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 3bc4c978d7a..d6407b563fd 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -846,7 +846,7 @@ static int __ip_append_data(struct sock *sk, csummode = CHECKSUM_PARTIAL; cork->length += length; - if (((length > mtu) || (skb && skb_is_gso(skb))) && + if (((length > mtu) || (skb && skb_has_frags(skb))) && (sk->sk_protocol == IPPROTO_UDP) && (rt->dst.dev->features & NETIF_F_UFO) && !rt->dst.header_len) { err = ip_ufo_append_data(sk, queue, getfrag, from, length, diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 167ea10b521..108c73d760d 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -2713,7 +2713,7 @@ static struct rtable *ip_route_output_slow(struct net *net, struct flowi4 *fl4) RT_SCOPE_LINK); goto make_route; } - if (fl4->saddr) { + if (!fl4->saddr) { if (ipv4_is_multicast(fl4->daddr)) fl4->saddr = inet_select_addr(dev_out, 0, fl4->flowi4_scope); diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 8b53df66155..51e4301eb48 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -1468,7 +1468,10 @@ static int tcp_shifted_skb(struct sock *sk, struct sk_buff *skb, tp->lost_cnt_hint -= tcp_skb_pcount(prev); } - TCP_SKB_CB(skb)->tcp_flags |= TCP_SKB_CB(prev)->tcp_flags; + TCP_SKB_CB(prev)->tcp_flags |= TCP_SKB_CB(skb)->tcp_flags; + if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN) + TCP_SKB_CB(prev)->end_seq++; + if (skb == tcp_highest_sack(sk)) tcp_advance_highest_sack(sk, skb); diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 12999a3aaf9..987f5cc706b 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -933,6 +933,9 @@ static void tcp_queue_skb(struct sock *sk, struct sk_buff *skb) static void tcp_set_skb_tso_segs(const struct sock *sk, struct sk_buff *skb, unsigned int mss_now) { + /* Make sure we own this skb before messing gso_size/gso_segs */ + WARN_ON_ONCE(skb_cloned(skb)); + if (skb->len <= mss_now || !sk_can_gso(sk) || skb->ip_summed == CHECKSUM_NONE) { /* Avoid the costly divide in the normal @@ -1014,9 +1017,7 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, if (nsize < 0) nsize = 0; - if (skb_cloned(skb) && - skb_is_nonlinear(skb) && - pskb_expand_head(skb, 0, 0, GFP_ATOMIC)) + if (skb_unclone(skb, GFP_ATOMIC)) return -ENOMEM; /* Get a new skb... force flag on. */ @@ -2129,6 +2130,8 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) int oldpcount = tcp_skb_pcount(skb); if (unlikely(oldpcount > 1)) { + if (skb_unclone(skb, GFP_ATOMIC)) + return -ENOMEM; tcp_init_tso_segs(sk, skb, cur_mss); tcp_adjust_pcount(sk, skb, oldpcount - tcp_skb_pcount(skb)); } diff --git a/net/ipv6/inet6_hashtables.c b/net/ipv6/inet6_hashtables.c index 73f1a00a96a..e38290b7c7a 100644 --- a/net/ipv6/inet6_hashtables.c +++ b/net/ipv6/inet6_hashtables.c @@ -110,7 +110,7 @@ struct sock *__inet6_lookup_established(struct net *net, goto out; } if (!INET6_TW_MATCH(sk, net, hash, saddr, daddr, ports, dif)) { - sock_put(sk); + inet_twsk_put(inet_twsk(sk)); goto begintw; } goto out; diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index f1bf29063cd..04e9b882c12 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -1346,7 +1346,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, skb = skb_peek_tail(&sk->sk_write_queue); cork->length += length; if (((length > mtu) || - (skb && skb_is_gso(skb))) && + (skb && skb_has_frags(skb))) && (sk->sk_protocol == IPPROTO_UDP) && (rt->dst.dev->features & NETIF_F_UFO)) { err = ip6_ufo_append_data(sk, getfrag, from, length, diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 016ed7c22fc..4f768a4c290 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -818,7 +818,7 @@ static struct rt6_info *rt6_alloc_clone(struct rt6_info *ort, } static struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table, int oif, - struct flowi6 *fl6, int flags) + struct flowi6 *fl6, int flags, bool input) { struct fib6_node *fn; struct rt6_info *rt, *nrt; @@ -826,8 +826,11 @@ static struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table, int attempts = 3; int err; int reachable = net->ipv6.devconf_all->forwarding ? 0 : RT6_LOOKUP_F_REACHABLE; + int local = RTF_NONEXTHOP; strict |= flags & RT6_LOOKUP_F_IFACE; + if (input) + local |= RTF_LOCAL; relookup: read_lock_bh(&table->tb6_lock); @@ -847,7 +850,7 @@ static struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table, read_unlock_bh(&table->tb6_lock); if (!dst_get_neighbour_noref_raw(&rt->dst) && - !(rt->rt6i_flags & (RTF_NONEXTHOP | RTF_LOCAL))) + !(rt->rt6i_flags & local)) nrt = rt6_alloc_cow(rt, &fl6->daddr, &fl6->saddr); else if (!(rt->dst.flags & DST_HOST)) nrt = rt6_alloc_clone(rt, &fl6->daddr); @@ -891,7 +894,7 @@ static struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table, static struct rt6_info *ip6_pol_route_input(struct net *net, struct fib6_table *table, struct flowi6 *fl6, int flags) { - return ip6_pol_route(net, table, fl6->flowi6_iif, fl6, flags); + return ip6_pol_route(net, table, fl6->flowi6_iif, fl6, flags, true); } static struct dst_entry *ip6_route_input_lookup(struct net *net, @@ -924,7 +927,7 @@ void ip6_route_input(struct sk_buff *skb) static struct rt6_info *ip6_pol_route_output(struct net *net, struct fib6_table *table, struct flowi6 *fl6, int flags) { - return ip6_pol_route(net, table, fl6->flowi6_oif, fl6, flags); + return ip6_pol_route(net, table, fl6->flowi6_oif, fl6, flags, false); } struct dst_entry * ip6_route_output(struct net *net, const struct sock *sk, diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c index b2982f4214d..904bc098790 100644 --- a/net/l2tp/l2tp_ppp.c +++ b/net/l2tp/l2tp_ppp.c @@ -357,7 +357,9 @@ static int pppol2tp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msgh goto error_put_sess_tun; } + local_bh_disable(); l2tp_xmit_skb(session, skb, session->hdr_len); + local_bh_enable(); sock_put(ps->tunnel_sock); sock_put(sk); @@ -432,7 +434,9 @@ static int pppol2tp_xmit(struct ppp_channel *chan, struct sk_buff *skb) skb->data[0] = ppph[0]; skb->data[1] = ppph[1]; + local_bh_disable(); l2tp_xmit_skb(session, skb, session->hdr_len); + local_bh_enable(); sock_put(sk_tun); sock_put(sk); diff --git a/net/sctp/output.c b/net/sctp/output.c index 32ba8d0e50e..cf3e22c586a 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c @@ -518,7 +518,8 @@ int sctp_packet_transmit(struct sctp_packet *packet) * by CRC32-C as described in . */ if (!sctp_checksum_disable) { - if (!(dst->dev->features & NETIF_F_SCTP_CSUM)) { + if (!(dst->dev->features & NETIF_F_SCTP_CSUM) || + (dst_xfrm(dst) != NULL) || packet->ipfragok) { __u32 crc32 = sctp_start_cksum((__u8 *)sh, cksum_buf_len); /* 3) Put the resultant value into the checksum field in the diff --git a/net/socket.c b/net/socket.c index eb0f15d6b81..2bef7dba7c1 100644 --- a/net/socket.c +++ b/net/socket.c @@ -1899,6 +1899,16 @@ struct used_address { unsigned int name_len; }; +static int copy_msghdr_from_user(struct msghdr *kmsg, + struct msghdr __user *umsg) +{ + if (copy_from_user(kmsg, umsg, sizeof(struct msghdr))) + return -EFAULT; + if (kmsg->msg_namelen > sizeof(struct sockaddr_storage)) + return -EINVAL; + return 0; +} + static int ___sys_sendmsg(struct socket *sock, struct msghdr __user *msg, struct msghdr *msg_sys, unsigned flags, struct used_address *used_address) @@ -1917,8 +1927,11 @@ static int ___sys_sendmsg(struct socket *sock, struct msghdr __user *msg, if (MSG_CMSG_COMPAT & flags) { if (get_compat_msghdr(msg_sys, msg_compat)) return -EFAULT; - } else if (copy_from_user(msg_sys, msg, sizeof(struct msghdr))) - return -EFAULT; + } else { + err = copy_msghdr_from_user(msg_sys, msg); + if (err) + return err; + } /* do not move before msg_sys is valid */ err = -EMSGSIZE; @@ -2129,8 +2142,11 @@ static int ___sys_recvmsg(struct socket *sock, struct msghdr __user *msg, if (MSG_CMSG_COMPAT & flags) { if (get_compat_msghdr(msg_sys, msg_compat)) return -EFAULT; - } else if (copy_from_user(msg_sys, msg, sizeof(struct msghdr))) - return -EFAULT; + } else { + err = copy_msghdr_from_user(msg_sys, msg); + if (err) + return err; + } err = -EMSGSIZE; if (msg_sys->msg_iovlen > UIO_MAXIOV) diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 7b5f7751201..0916022366a 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -1248,6 +1248,15 @@ static int unix_socketpair(struct socket *socka, struct socket *sockb) return 0; } +static void unix_sock_inherit_flags(const struct socket *old, + struct socket *new) +{ + if (test_bit(SOCK_PASSCRED, &old->flags)) + set_bit(SOCK_PASSCRED, &new->flags); + if (test_bit(SOCK_PASSSEC, &old->flags)) + set_bit(SOCK_PASSSEC, &new->flags); +} + static int unix_accept(struct socket *sock, struct socket *newsock, int flags) { struct sock *sk = sock->sk; @@ -1282,6 +1291,7 @@ static int unix_accept(struct socket *sock, struct socket *newsock, int flags) /* attach accepted sock to socket */ unix_state_lock(tsk); newsock->state = SS_CONNECTED; + unix_sock_inherit_flags(sock, newsock); sock_graft(tsk, newsock); unix_state_unlock(tsk); return 0; diff --git a/net/unix/diag.c b/net/unix/diag.c index f0486ae9ebe..2656840cf20 100644 --- a/net/unix/diag.c +++ b/net/unix/diag.c @@ -134,6 +134,7 @@ static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, struct unix_diag_r rep->udiag_family = AF_UNIX; rep->udiag_type = sk->sk_type; rep->udiag_state = sk->sk_state; + rep->pad = 0; rep->udiag_ino = sk_ino; sock_diag_save_cookie(sk, rep->udiag_cookie); diff --git a/net/wireless/radiotap.c b/net/wireless/radiotap.c index c4ad7958af5..617a310025b 100644 --- a/net/wireless/radiotap.c +++ b/net/wireless/radiotap.c @@ -95,6 +95,10 @@ int ieee80211_radiotap_iterator_init( struct ieee80211_radiotap_header *radiotap_header, int max_length, const struct ieee80211_radiotap_vendor_namespaces *vns) { + /* check the radiotap header can actually be present */ + if (max_length < sizeof(struct ieee80211_radiotap_header)) + return -EINVAL; + /* Linux only supports version 0 radiotap format */ if (radiotap_header->it_version) return -EINVAL; @@ -129,7 +133,8 @@ int ieee80211_radiotap_iterator_init( */ if ((unsigned long)iterator->_arg - - (unsigned long)iterator->_rtheader > + (unsigned long)iterator->_rtheader + + sizeof(uint32_t) > (unsigned long)iterator->_max_length) return -EINVAL; } From bbb9b79a698bd9582fb1d8f5d964767b5a610a66 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 13 Nov 2013 12:02:08 +0900 Subject: [PATCH 142/215] Linux 3.4.69 - 26 commits squashed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit USB: support new huawei devices in option.c commit d544db293a44a2a3b09feab7dbd59668b692de71 upstream. Add new supporting declarations to option.c, to support Huawei new devices with new bInterfaceSubClass value. Signed-off-by: fangxiaozhi Signed-off-by: Greg Kroah-Hartman USB: quirks.c: add one device that cannot deal with suspension commit 4294bca7b423d1a5aa24307e3d112a04075e3763 upstream. The device is not responsive when resumed, unless it is reset. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman USB: quirks: add touchscreen that is dazzeled by remote wakeup commit 614ced91fc6fbb5a1cdd12f0f1b6c9197d9f1350 upstream. The device descriptors are messed up after remote wakeup Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman USB: serial: ftdi_sio: add id for Z3X Box device commit e1466ad5b1aeda303f9282463d55798d2eda218c upstream. Custom VID/PID for Z3X Box device, popular tool for cellphone flashing. Signed-off-by: Alexey E. Kramarenko Signed-off-by: Greg Kroah-Hartman mac80211: correctly close cancelled scans commit a754055a1296fcbe6f32de3a5eaca6efb2fd1865 upstream. __ieee80211_scan_completed is called from a worker. This means that the following flow is possible. * driver calls ieee80211_scan_completed * mac80211 cancels the scan (that is already complete) * __ieee80211_scan_completed runs When scan_work will finally run, it will see that the scan hasn't been aborted and might even trigger another scan on another band. This leads to a situation where cfg80211's scan is not done and no further scan can be issued. Fix this by setting a new flag when a HW scan is being cancelled so that no other scan will be triggered. Signed-off-by: Emmanuel Grumbach Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman mac80211: update sta->last_rx on acked tx frames commit 0c5b93290b2f3c7a376567c03ae8d385b0e99851 upstream. When clients are idle for too long, hostapd sends nullfunc frames for probing. When those are acked by the client, the idle time needs to be updated. To make this work (and to avoid unnecessary probing), update sta->last_rx whenever an ACK was received for a tx packet. Only do this if the flag IEEE80211_HW_REPORTS_TX_ACK_STATUS is set. Signed-off-by: Felix Fietkau Signed-off-by: Johannes Berg Signed-off-by: Greg Kroah-Hartman rtlwifi: rtl8192cu: Fix error in pointer arithmetic commit 9473ca6e920a3b9ca902753ce52833657f9221cc upstream. An error in calculating the offset in an skb causes the driver to read essential device info from the wrong locations. The main effect is that automatic gain calculations are nonsense. Signed-off-by: Mark Cave-Ayland Signed-off-by: Larry Finger Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman jfs: fix error path in ialloc commit 8660998608cfa1077e560034db81885af8e1e885 upstream. If insert_inode_locked() fails, we shouldn't be calling unlock_new_inode(). Signed-off-by: Dave Kleikamp Tested-by: Michael L. Semon Signed-off-by: Greg Kroah-Hartman can: flexcan: flexcan_chip_start: fix regression, mark one MB for TX and abort pending TX commit d5a7b406c529e4595ce03dc8f6dcf7fa36f106fa upstream. In patch 0d1862e can: flexcan: fix flexcan_chip_start() on imx6 the loop in flexcan_chip_start() that iterates over all mailboxes after the soft reset of the CAN core was removed. This loop put all mailboxes (even the ones marked as reserved 1...7) into EMPTY/INACTIVE mode. On mailboxes 8...63, this aborts any pending TX messages. After a cold boot there is random garbage in the mailboxes, which leads to spontaneous transmit of CAN frames during first activation. Further if the interface was disabled with a pending message (usually due to an error condition on the CAN bus), this message is retransmitted after enabling the interface again. This patch fixes the regression by: 1) Limiting the maximum number of used mailboxes to 8, 0...7 are used by the RX FIFO, 8 is used by TX. 2) Marking the TX mailbox as EMPTY/INACTIVE, so that any pending TX of that mailbox is aborted. Cc: Lothar Waßmann Signed-off-by: Marc Kleine-Budde Signed-off-by: Greg Kroah-Hartman libata: make ata_eh_qc_retry() bump scmd->allowed on bogus failures commit f13e220161e738c2710b9904dcb3cf8bb0bcce61 upstream. libata EH decrements scmd->retries when the command failed for reasons unrelated to the command itself so that, for example, commands aborted due to suspend / resume cycle don't get penalized; however, decrementing scmd->retries isn't enough for ATA passthrough commands. Without this fix, ATA passthrough commands are not resend to the drive, and no error is signalled to the caller because: - allowed retry count is 1 - ata_eh_qc_complete fill the sense data, so result is valid - sense data is filled with untouched ATA registers. Signed-off-by: Gwendal Grignou Signed-off-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman md: Fix skipping recovery for read-only arrays. commit 61e4947c99c4494336254ec540c50186d186150b upstream. Since: commit 7ceb17e87bde79d285a8b988cfed9eaeebe60b86 md: Allow devices to be re-added to a read-only array. spares are activated on a read-only array. In case of raid1 and raid10 personalities it causes that not-in-sync devices are marked in-sync without checking if recovery has been finished. If a read-only array is degraded and one of its devices is not in-sync (because the array has been only partially recovered) recovery will be skipped. This patch adds checking if recovery has been finished before marking a device in-sync for raid1 and raid10 personalities. In case of raid5 personality such condition is already present (at raid5.c:6029). Bug was introduced in 3.10 and causes data corruption. Signed-off-by: Pawel Baldysiak Signed-off-by: Lukasz Dorau Signed-off-by: NeilBrown Signed-off-by: Greg Kroah-Hartman clockevents: Sanitize ticks to nsec conversion commit 97b9410643475d6557d2517c2aff9fd2221141a9 upstream. Marc Kleine-Budde pointed out, that commit 77cc982 "clocksource: use clockevents_config_and_register() where possible" caused a regression for some of the converted subarchs. The reason is, that the clockevents core code converts the minimal hardware tick delta to a nanosecond value for core internal usage. This conversion is affected by integer math rounding loss, so the backwards conversion to hardware ticks will likely result in a value which is less than the configured hardware limitation. The affected subarchs used their own workaround (SIGH!) which got lost in the conversion. The solution for the issue at hand is simple: adding evt->mult - 1 to the shifted value before the integer divison in the core conversion function takes care of it. But this only works for the case where for the scaled math mult/shift pair "mult <= 1 << shift" is true. For the case where "mult > 1 << shift" we can apply the rounding add only for the minimum delta value to make sure that the backward conversion is not less than the given hardware limit. For the upper bound we need to omit the rounding add, because the backwards conversion is always larger than the original latch value. That would violate the upper bound of the hardware device. Though looking closer at the details of that function reveals another bogosity: The upper bounds check is broken as well. Checking for a resulting "clc" value greater than KTIME_MAX after the conversion is pointless. The conversion does: u64 clc = (latch << evt->shift) / evt->mult; So there is no sanity check for (latch << evt->shift) exceeding the 64bit boundary. The latch argument is "unsigned long", so on a 64bit arch the handed in argument could easily lead to an unnoticed shift overflow. With the above rounding fix applied the calculation before the divison is: u64 clc = (latch << evt->shift) + evt->mult - 1; So we need to make sure, that neither the shift nor the rounding add is overflowing the u64 boundary. [ukl: move assignment to rnd after eventually changing mult, fix build issue and correct comment with the right math] Signed-off-by: Thomas Gleixner Cc: Russell King - ARM Linux Cc: Marc Kleine-Budde Cc: nicolas.ferre@atmel.com Cc: Marc Pignat Cc: john.stultz@linaro.org Cc: kernel@pengutronix.de Cc: Ronald Wahl Cc: LAK Cc: Ludovic Desroches Link: http://lkml.kernel.org/r/1380052223-24139-1-git-send-email-u.kleine-koenig@pengutronix.de Signed-off-by: Uwe Kleine-König Signed-off-by: Greg Kroah-Hartman parisc: Do not crash 64bit SMP kernels on machines with >= 4GB RAM commit 54e181e073fc1415e41917d725ebdbd7de956455 upstream. Since the beginning of the parisc-linux port, sometimes 64bit SMP kernels were not able to bring up other CPUs than the monarch CPU and instead crashed the kernel. The reason was unclear, esp. since it involved various machines (e.g. J5600, J6750 and SuperDome). Testing showed, that those crashes didn't happened when less than 4GB were installed, or if a 32bit Linux kernel was booted. In the end, the fix for those SMP problems is trivial: During the early phase of the initialization of the CPUs, including the monarch CPU, the PDC_PSW firmware function to enable WIDE (=64bit) mode is called. It's documented that this firmware function may clobber various registers, and one one of those possibly clobbered registers is %cr30 which holds the task thread info pointer. Now, if %cr30 would always have been clobbered, then this bug would have been detected much earlier. But lots of testing finally showed, that - at least for %cr30 - on some machines only the upper 32bits of the 64bit register suddenly turned zero after the firmware call. So, after finding the root cause, the explanation for the various crashes became clear: - On 32bit SMP Linux kernels all upper 32bit were zero, so we didn't faced this problem. - Monarch CPUs in 64bit mode always booted sucessfully, because the inital task thread info pointer was below 4GB. - Secondary CPUs booted sucessfully on machines with less than 4GB RAM because the upper 32bit were zero anyay. - Secondary CPus failed to boot if we had more than 4GB RAM and the task thread info pointer was located above the 4GB boundary. Finally, the patch to fix this problem is trivial by saving the %cr30 register before the firmware call and restoring it afterwards. Signed-off-by: Helge Deller Signed-off-by: John David Anglin Signed-off-by: Helge Deller Signed-off-by: Greg Kroah-Hartman ALSA: hda - Add a fixup for ASUS N76VZ commit 6fc16e58adf50c0f1e4478538983fb5ff6f453d4 upstream. ASUS N76VZ needs the same fixup as N56VZ for supporting the boost speaker. Bugzilla: https://bugzilla.novell.com/show_bug.cgi?id=846529 Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman ALSA: fix oops in snd_pcm_info() caused by ASoC DPCM commit a4461f41b94cb52e0141af717dcf4ef6558c8e2e upstream. Unable to handle kernel NULL pointer dereference at virtual address 00000008 pgd = d5300000 [00000008] *pgd=0d265831, *pte=00000000, *ppte=00000000 Internal error: Oops: 17 [#1] PREEMPT ARM CPU: 0 PID: 2295 Comm: vlc Not tainted 3.11.0+ #755 task: dee74800 ti: e213c000 task.ti: e213c000 PC is at snd_pcm_info+0xc8/0xd8 LR is at 0x30232065 pc : [] lr : [<30232065>] psr: a0070013 sp : e213dea8 ip : d81cb0d0 fp : c05f7678 r10: c05f7770 r9 : fffffdfd r8 : 00000000 r7 : d8a968a8 r6 : d8a96800 r5 : d8a96200 r4 : d81cb000 r3 : 00000000 r2 : d81cb000 r1 : 00000001 r0 : d8a96200 Flags: NzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user Control: 10c5387d Table: 15300019 DAC: 00000015 Process vlc (pid: 2295, stack limit = 0xe213c248) [] (snd_pcm_info) from [] (snd_pcm_info_user+0x34/0x9c) [] (snd_pcm_info_user) from [] (snd_pcm_control_ioctl+0x274/0x280) [] (snd_pcm_control_ioctl) from [] (snd_ctl_ioctl+0xc0/0x55c) [] (snd_ctl_ioctl) from [] (do_vfs_ioctl+0x80/0x31c) [] (do_vfs_ioctl) from [] (SyS_ioctl+0x3c/0x60) [] (SyS_ioctl) from [] (ret_fast_syscall+0x0/0x48) Code: e1a00005 e59530dc e3a01001 e1a02004 (e5933008) ---[ end trace cb3d9bdb8dfefb3c ]--- This is provoked when the ASoC front end is open along with its backend, (which causes the backend to have a runtime assigned to it) and then the SNDRV_CTL_IOCTL_PCM_INFO is requested for the (visible) backend device. Resolve this by ensuring that ASoC internal backend devices are not visible to userspace, just as the commentry for snd_pcm_new_internal() says it should be. Signed-off-by: Russell King Acked-by: Mark Brown Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman ASoC: wm_hubs: Add missing break in hp_supply_event() commit 268ff14525edba31da29a12a9dd693cdd6a7872e upstream. Spotted by coverity CID 115170. Signed-off-by: Takashi Iwai Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman ASoC: dapm: Fix source list debugfs outputs commit ff18620c2157671a8ee21ebb8e6a3520ea209b1f upstream. ... due to a copy & paste error. Spotted by coverity CID 710923. Signed-off-by: Takashi Iwai Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman staging: ozwpan: prevent overflow in oz_cdev_write() commit c2c65cd2e14ada6de44cb527e7f1990bede24e15 upstream. We need to check "count" so we don't overflow the ei->data buffer. Reported-by: Nico Golde Reported-by: Fabian Yamaguchi Signed-off-by: Dan Carpenter Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman Staging: bcm: info leak in ioctl commit 8d1e72250c847fa96498ec029891de4dc638a5ba upstream. The DevInfo.u32Reserved[] array isn't initialized so it leaks kernel information to user space. Reported-by: Nico Golde Reported-by: Fabian Yamaguchi Signed-off-by: Dan Carpenter Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman uml: check length in exitcode_proc_write() commit 201f99f170df14ba52ea4c52847779042b7a623b upstream. We don't cap the size of buffer from the user so we could write past the end of the array here. Only root can write to this file. Reported-by: Nico Golde Reported-by: Fabian Yamaguchi Signed-off-by: Dan Carpenter Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman xtensa: don't use alternate signal stack on threads commit cba9a90053e3b7973eff4f1946f33032e98eeed5 upstream. According to create_thread(3): "The new thread does not inherit the creating thread's alternate signal stack". Since commit f9a3879a (Fix sigaltstack corruption among cloned threads), current->sas_ss_size is set to 0 for cloned processes sharing VM with their parent. Don't use the (nonexistent) alternate signal stack in this case. This has been broken since commit 29c4dfd9 ([XTENSA] Remove non-rt signal handling). Fixes the SA_ONSTACK part of the nptl/tst-cancel20 test from uClibc. Signed-off-by: Baruch Siach Signed-off-by: Max Filippov Signed-off-by: Chris Zankel Signed-off-by: Greg Kroah-Hartman lib/scatterlist.c: don't flush_kernel_dcache_page on slab page commit 3d77b50c5874b7e923be946ba793644f82336b75 upstream. Commit b1adaf65ba03 ("[SCSI] block: add sg buffer copy helper functions") introduces two sg buffer copy helpers, and calls flush_kernel_dcache_page() on pages in SG list after these pages are written to. Unfortunately, the commit may introduce a potential bug: - Before sending some SCSI commands, kmalloc() buffer may be passed to block layper, so flush_kernel_dcache_page() can see a slab page finally - According to cachetlb.txt, flush_kernel_dcache_page() is only called on "a user page", which surely can't be a slab page. - ARCH's implementation of flush_kernel_dcache_page() may use page mapping information to do optimization so page_mapping() will see the slab page, then VM_BUG_ON() is triggered. Aaro Koskinen reported the bug on ARM/kirkwood when DEBUG_VM is enabled, and this patch fixes the bug by adding test of '!PageSlab(miter->page)' before calling flush_kernel_dcache_page(). Signed-off-by: Ming Lei Reported-by: Aaro Koskinen Tested-by: Simon Baatz Cc: Russell King - ARM Linux Cc: Will Deacon Cc: Aaro Koskinen Acked-by: Catalin Marinas Cc: FUJITA Tomonori Cc: Tejun Heo Cc: "James E.J. Bottomley" Cc: Jens Axboe Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman aacraid: missing capable() check in compat ioctl commit f856567b930dfcdbc3323261bf77240ccdde01f5 upstream. In commit d496f94d22d1 ('[SCSI] aacraid: fix security weakness') we added a check on CAP_SYS_RAWIO to the ioctl. The compat ioctls need the check as well. Signed-off-by: Dan Carpenter Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman mm: fix aio performance regression for database caused by THP commit 7cb2ef56e6a8b7b368b2e883a0a47d02fed66911 upstream. I am working with a tool that simulates oracle database I/O workload. This tool (orion to be specific - ) allocates hugetlbfs pages using shmget() with SHM_HUGETLB flag. It then does aio into these pages from flash disks using various common block sizes used by database. I am looking at performance with two of the most common block sizes - 1M and 64K. aio performance with these two block sizes plunged after Transparent HugePages was introduced in the kernel. Here are performance numbers: pre-THP 2.6.39 3.11-rc5 1M read 8384 MB/s 5629 MB/s 6501 MB/s 64K read 7867 MB/s 4576 MB/s 4251 MB/s I have narrowed the performance impact down to the overheads introduced by THP in __get_page_tail() and put_compound_page() routines. perf top shows >40% of cycles being spent in these two routines. Every time direct I/O to hugetlbfs pages starts, kernel calls get_page() to grab a reference to the pages and calls put_page() when I/O completes to put the reference away. THP introduced significant amount of locking overhead to get_page() and put_page() when dealing with compound pages because hugepages can be split underneath get_page() and put_page(). It added this overhead irrespective of whether it is dealing with hugetlbfs pages or transparent hugepages. This resulted in 20%-45% drop in aio performance when using hugetlbfs pages. Since hugetlbfs pages can not be split, there is no reason to go through all the locking overhead for these pages from what I can see. I added code to __get_page_tail() and put_compound_page() to bypass all the locking code when working with hugetlbfs pages. This improved performance significantly. Performance numbers with this patch: pre-THP 3.11-rc5 3.11-rc5 + Patch 1M read 8384 MB/s 6501 MB/s 8371 MB/s 64K read 7867 MB/s 4251 MB/s 6510 MB/s Performance with 64K read is still lower than what it was before THP, but still a 53% improvement. It does mean there is more work to be done but I will take a 53% improvement for now. Please take a look at the following patch and let me know if it looks reasonable. [akpm@linux-foundation.org: tweak comments] Signed-off-by: Khalid Aziz Cc: Pravin B Shelar Cc: Christoph Lameter Cc: Andrea Arcangeli Cc: Johannes Weiner Cc: Mel Gorman Cc: Rik van Riel Cc: Minchan Kim Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman drm: Prevent overwriting from userspace underallocating core ioctl structs commit b062672e305ce071f21eb9e18b102c2a430e0999 upstream. Apply the protections from commit 1b2f1489633888d4a06028315dc19d65768a1c05 Author: Dave Airlie Date: Sat Aug 14 20:20:34 2010 +1000 drm: block userspace under allocating buffer and having drivers overwrite it (v2) to the core ioctl structs as well, for we found one instance where there is a 32-/64-bit size mismatch and were guilty of writing beyond the end of the user's buffer. Signed-off-by: Chris Wilson Cc: Dave Airlie Reviewed-by: Ville Syrjälä Cc: dri-devel@lists.freedesktop.org Signed-off-by: Dave Airlie Signed-off-by: Greg Kroah-Hartman drm/radeon/atom: workaround vbios bug in transmitter table on rs780 commit c23632d4e57c0dd20bf50eca08fa0eb8ad3ff680 upstream. Some rs780 asics seem to be affected as well. See: http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=91f3a6aaf280294b07c05dfe606e6c27b7ba3c72 Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=60791 Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman --- Makefile | 2 +- arch/parisc/kernel/head.S | 4 + arch/um/kernel/exitcode.c | 4 +- arch/xtensa/kernel/signal.c | 2 +- drivers/ata/libata-eh.c | 6 +- drivers/gpu/drm/drm_drv.c | 9 +- drivers/gpu/drm/radeon/atombios_encoders.c | 2 +- drivers/md/raid1.c | 1 + drivers/md/raid10.c | 1 + drivers/net/can/flexcan.c | 10 +- drivers/net/wireless/rtlwifi/rtl8192cu/trx.c | 3 +- drivers/scsi/aacraid/linit.c | 2 + drivers/staging/bcm/Bcmchar.c | 1 + drivers/staging/ozwpan/ozcdev.c | 3 + drivers/usb/core/quirks.c | 6 + drivers/usb/serial/ftdi_sio.c | 1 + drivers/usb/serial/ftdi_sio_ids.h | 6 + drivers/usb/serial/option.c | 216 +++++++++++++++++++ fs/jfs/jfs_inode.c | 3 +- kernel/time/clockevents.c | 65 ++++-- lib/scatterlist.c | 3 +- mm/swap.c | 31 ++- net/mac80211/ieee80211_i.h | 3 + net/mac80211/scan.c | 19 ++ net/mac80211/status.c | 3 + sound/core/pcm.c | 4 + sound/pci/hda/patch_realtek.c | 1 + sound/soc/codecs/wm_hubs.c | 1 + sound/soc/soc-dapm.c | 2 +- 29 files changed, 382 insertions(+), 32 deletions(-) diff --git a/Makefile b/Makefile index 9d74b73729f..4b35233dc21 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 4 -SUBLEVEL = 68 +SUBLEVEL = 69 EXTRAVERSION = NAME = Saber-toothed Squirrel diff --git a/arch/parisc/kernel/head.S b/arch/parisc/kernel/head.S index 37aabd772fb..d2d58258aea 100644 --- a/arch/parisc/kernel/head.S +++ b/arch/parisc/kernel/head.S @@ -195,6 +195,8 @@ common_stext: ldw MEM_PDC_HI(%r0),%r6 depd %r6, 31, 32, %r3 /* move to upper word */ + mfctl %cr30,%r6 /* PCX-W2 firmware bug */ + ldo PDC_PSW(%r0),%arg0 /* 21 */ ldo PDC_PSW_SET_DEFAULTS(%r0),%arg1 /* 2 */ ldo PDC_PSW_WIDE_BIT(%r0),%arg2 /* 2 */ @@ -203,6 +205,8 @@ common_stext: copy %r0,%arg3 stext_pdc_ret: + mtctl %r6,%cr30 /* restore task thread info */ + /* restore rfi target address*/ ldd TI_TASK-THREAD_SZ_ALGN(%sp), %r10 tophys_r1 %r10 diff --git a/arch/um/kernel/exitcode.c b/arch/um/kernel/exitcode.c index 829df49dee9..41ebbfebb33 100644 --- a/arch/um/kernel/exitcode.c +++ b/arch/um/kernel/exitcode.c @@ -40,9 +40,11 @@ static ssize_t exitcode_proc_write(struct file *file, const char __user *buffer, size_t count, loff_t *pos) { char *end, buf[sizeof("nnnnn\0")]; + size_t size; int tmp; - if (copy_from_user(buf, buffer, count)) + size = min(count, sizeof(buf)); + if (copy_from_user(buf, buffer, size)) return -EFAULT; tmp = simple_strtol(buf, &end, 0); diff --git a/arch/xtensa/kernel/signal.c b/arch/xtensa/kernel/signal.c index d78869a00b1..b08caaa5981 100644 --- a/arch/xtensa/kernel/signal.c +++ b/arch/xtensa/kernel/signal.c @@ -343,7 +343,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, siginfo_t *info, sp = regs->areg[1]; - if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! on_sig_stack(sp)) { + if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && sas_ss_flags(sp) == 0) { sp = current->sas_ss_sp + current->sas_ss_size; } diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index e47c224d7c2..37fb4d6069a 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -1287,14 +1287,14 @@ void ata_eh_qc_complete(struct ata_queued_cmd *qc) * should be retried. To be used from EH. * * SCSI midlayer limits the number of retries to scmd->allowed. - * scmd->retries is decremented for commands which get retried + * scmd->allowed is incremented for commands which get retried * due to unrelated failures (qc->err_mask is zero). */ void ata_eh_qc_retry(struct ata_queued_cmd *qc) { struct scsi_cmnd *scmd = qc->scsicmd; - if (!qc->err_mask && scmd->retries) - scmd->retries--; + if (!qc->err_mask) + scmd->allowed++; __ata_eh_qc_complete(qc); } diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 6116e3b7539..e9f1ef5d934 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -420,9 +420,16 @@ long drm_ioctl(struct file *filp, asize = drv_size; } else if ((nr >= DRM_COMMAND_END) || (nr < DRM_COMMAND_BASE)) { + u32 drv_size; + ioctl = &drm_ioctls[nr]; - cmd = ioctl->cmd; + + drv_size = _IOC_SIZE(ioctl->cmd); usize = asize = _IOC_SIZE(cmd); + if (drv_size > asize) + asize = drv_size; + + cmd = ioctl->cmd; } else goto err_i1; diff --git a/drivers/gpu/drm/radeon/atombios_encoders.c b/drivers/gpu/drm/radeon/atombios_encoders.c index 2f755e2aeb8..6f4627fe24a 100644 --- a/drivers/gpu/drm/radeon/atombios_encoders.c +++ b/drivers/gpu/drm/radeon/atombios_encoders.c @@ -1430,7 +1430,7 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode) * does the same thing and more. */ if ((rdev->family != CHIP_RV710) && (rdev->family != CHIP_RV730) && - (rdev->family != CHIP_RS880)) + (rdev->family != CHIP_RS780) && (rdev->family != CHIP_RS880)) atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); } if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) { diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index ce36dee6b16..72a87a8b51a 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -1357,6 +1357,7 @@ static int raid1_spare_active(struct mddev *mddev) } } if (rdev + && rdev->recovery_offset == MaxSector && !test_bit(Faulty, &rdev->flags) && !test_and_set_bit(In_sync, &rdev->flags)) { count++; diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index dd6d1faaa03..da20f0fa1b5 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -1524,6 +1524,7 @@ static int raid10_spare_active(struct mddev *mddev) } sysfs_notify_dirent_safe(tmp->replacement->sysfs_state); } else if (tmp->rdev + && tmp->rdev->recovery_offset == MaxSector && !test_bit(Faulty, &tmp->rdev->flags) && !test_and_set_bit(In_sync, &tmp->rdev->flags)) { count++; diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index 00baa7e094f..e2131ca64a5 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -60,7 +60,7 @@ #define FLEXCAN_MCR_BCC BIT(16) #define FLEXCAN_MCR_LPRIO_EN BIT(13) #define FLEXCAN_MCR_AEN BIT(12) -#define FLEXCAN_MCR_MAXMB(x) ((x) & 0xf) +#define FLEXCAN_MCR_MAXMB(x) ((x) & 0x1f) #define FLEXCAN_MCR_IDAM_A (0 << 8) #define FLEXCAN_MCR_IDAM_B (1 << 8) #define FLEXCAN_MCR_IDAM_C (2 << 8) @@ -701,9 +701,11 @@ static int flexcan_chip_start(struct net_device *dev) * */ reg_mcr = flexcan_read(®s->mcr); + reg_mcr &= ~FLEXCAN_MCR_MAXMB(0xff); reg_mcr |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_FEN | FLEXCAN_MCR_HALT | FLEXCAN_MCR_SUPV | FLEXCAN_MCR_WRN_EN | - FLEXCAN_MCR_IDAM_C | FLEXCAN_MCR_SRX_DIS; + FLEXCAN_MCR_IDAM_C | FLEXCAN_MCR_SRX_DIS | + FLEXCAN_MCR_MAXMB(FLEXCAN_TX_BUF_ID); netdev_dbg(dev, "%s: writing mcr=0x%08x", __func__, reg_mcr); flexcan_write(reg_mcr, ®s->mcr); @@ -744,6 +746,10 @@ static int flexcan_chip_start(struct net_device *dev) ®s->cantxfg[i].can_ctrl); } + /* Abort any pending TX, mark Mailbox as INACTIVE */ + flexcan_write(FLEXCAN_MB_CNT_CODE(0x4), + ®s->cantxfg[FLEXCAN_TX_BUF_ID].can_ctrl); + /* acceptance mask/acceptance code (accept everything) */ flexcan_write(0x0, ®s->rxgmask); flexcan_write(0x0, ®s->rx14mask); diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c index 21bc827c5fa..9adb21a1133 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c @@ -343,7 +343,8 @@ bool rtl92cu_rx_query_desc(struct ieee80211_hw *hw, (bool)GET_RX_DESC_PAGGR(pdesc)); rx_status->mactime = GET_RX_DESC_TSFL(pdesc); if (phystatus) { - p_drvinfo = (struct rx_fwinfo_92c *)(pdesc + RTL_RX_DESC_SIZE); + p_drvinfo = (struct rx_fwinfo_92c *)(skb->data + + stats->rx_bufshift); rtl92c_translate_rx_signal_stuff(hw, skb, stats, pdesc, p_drvinfo); } diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 0d279c445a3..e9313f85bc7 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -777,6 +777,8 @@ static long aac_compat_do_ioctl(struct aac_dev *dev, unsigned cmd, unsigned long static int aac_compat_ioctl(struct scsi_device *sdev, int cmd, void __user *arg) { struct aac_dev *dev = (struct aac_dev *)sdev->host->hostdata; + if (!capable(CAP_SYS_RAWIO)) + return -EPERM; return aac_compat_do_ioctl(dev, cmd, (unsigned long)arg); } diff --git a/drivers/staging/bcm/Bcmchar.c b/drivers/staging/bcm/Bcmchar.c index cf305921695..c0d612ff851 100644 --- a/drivers/staging/bcm/Bcmchar.c +++ b/drivers/staging/bcm/Bcmchar.c @@ -1957,6 +1957,7 @@ static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg) BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Called IOCTL_BCM_GET_DEVICE_DRIVER_INFO\n"); + memset(&DevInfo, 0, sizeof(DevInfo)); DevInfo.MaxRDMBufferSize = BUFFER_4K; DevInfo.u32DSDStartOffset = EEPROM_CALPARAM_START; DevInfo.u32RxAlignmentCorrection = 0; diff --git a/drivers/staging/ozwpan/ozcdev.c b/drivers/staging/ozwpan/ozcdev.c index 1c380d68796..1c924511956 100644 --- a/drivers/staging/ozwpan/ozcdev.c +++ b/drivers/staging/ozwpan/ozcdev.c @@ -153,6 +153,9 @@ ssize_t oz_cdev_write(struct file *filp, const char __user *buf, size_t count, struct oz_app_hdr *app_hdr; struct oz_serial_ctx *ctx; + if (count > sizeof(ei->data) - sizeof(*elt) - sizeof(*app_hdr)) + return -EINVAL; + spin_lock_bh(&g_cdev.lock); pd = g_cdev.active_pd; if (pd) diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index 5e88ccea05f..1ae34d08c55 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -119,6 +119,9 @@ static const struct usb_device_id usb_quirk_list[] = { /* Alcor Micro Corp. Hub */ { USB_DEVICE(0x058f, 0x9254), .driver_info = USB_QUIRK_RESET_RESUME }, + /* MicroTouch Systems touchscreen */ + { USB_DEVICE(0x0596, 0x051e), .driver_info = USB_QUIRK_RESET_RESUME }, + /* appletouch */ { USB_DEVICE(0x05ac, 0x021a), .driver_info = USB_QUIRK_RESET_RESUME }, @@ -152,6 +155,9 @@ static const struct usb_device_id usb_quirk_list[] = { /* Broadcom BCM92035DGROM BT dongle */ { USB_DEVICE(0x0a5c, 0x2021), .driver_info = USB_QUIRK_RESET_RESUME }, + /* MAYA44USB sound device */ + { USB_DEVICE(0x0a92, 0x0091), .driver_info = USB_QUIRK_RESET_RESUME }, + /* Action Semiconductor flash disk */ { USB_DEVICE(0x10d6, 0x2200), .driver_info = USB_QUIRK_STRING_FETCH_255 }, diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 3e4c27dd159..904e8341b2c 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -916,6 +916,7 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_LUMEL_PD12_PID) }, /* Crucible Devices */ { USB_DEVICE(FTDI_VID, FTDI_CT_COMET_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_Z3X_PID) }, { }, /* Optional parameter entry */ { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 1b8af461b52..a7019d1e305 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -1307,3 +1307,9 @@ * Manufacturer: Crucible Technologies */ #define FTDI_CT_COMET_PID 0x8e08 + +/* + * Product: Z3X Box + * Manufacturer: Smart GSM Team + */ +#define FTDI_Z3X_PID 0x0011 diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index b3440c66a99..57277bccb9e 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -707,6 +707,222 @@ static const struct usb_device_id option_ids[] = { { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x7A) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x7B) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x7C) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x01) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x02) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x03) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x04) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x05) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x06) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x0A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x0B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x0D) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x0E) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x0F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x10) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x12) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x13) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x14) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x15) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x17) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x18) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x19) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x1A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x1B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x1C) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x31) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x32) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x33) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x34) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x35) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x36) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x3A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x3B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x3D) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x3E) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x3F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x48) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x49) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x4A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x4B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x4C) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x61) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x62) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x63) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x64) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x65) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x66) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x6A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x6B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x6D) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x6E) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x6F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x78) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x79) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x7A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x7B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x7C) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x01) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x02) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x03) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x04) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x05) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x06) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x0A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x0B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x0D) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x0E) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x0F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x10) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x12) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x13) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x14) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x15) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x17) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x18) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x19) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x1A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x1B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x1C) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x31) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x32) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x33) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x34) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x35) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x36) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x3A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x3B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x3D) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x3E) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x3F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x48) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x49) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x4A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x4B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x4C) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x61) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x62) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x63) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x64) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x65) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x66) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x6A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x6B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x6D) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x6E) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x6F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x78) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x79) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x7A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x7B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x7C) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x01) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x02) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x03) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x04) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x05) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x06) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x0A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x0B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x0D) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x0E) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x0F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x10) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x12) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x13) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x14) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x15) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x17) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x18) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x19) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x1A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x1B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x1C) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x31) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x32) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x33) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x34) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x35) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x36) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x3A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x3B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x3D) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x3E) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x3F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x48) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x49) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x4A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x4B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x4C) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x61) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x62) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x63) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x64) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x65) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x66) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x6A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x6B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x6D) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x6E) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x6F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x78) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x79) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x7A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x7B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x7C) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x01) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x02) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x03) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x04) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x05) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x06) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x0A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x0B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x0D) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x0E) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x0F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x10) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x12) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x13) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x14) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x15) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x17) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x18) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x19) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x1A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x1B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x1C) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x31) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x32) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x33) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x34) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x35) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x36) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x3A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x3B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x3D) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x3E) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x3F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x48) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x49) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x4A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x4B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x4C) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x61) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x62) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x63) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x64) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x65) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x66) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x6A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x6B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x6D) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x6E) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x6F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x78) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x79) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x7A) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x7B) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x7C) }, { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_V640) }, diff --git a/fs/jfs/jfs_inode.c b/fs/jfs/jfs_inode.c index c1a3e603279..7f464c513ba 100644 --- a/fs/jfs/jfs_inode.c +++ b/fs/jfs/jfs_inode.c @@ -95,7 +95,7 @@ struct inode *ialloc(struct inode *parent, umode_t mode) if (insert_inode_locked(inode) < 0) { rc = -EINVAL; - goto fail_unlock; + goto fail_put; } inode_init_owner(inode, parent, mode); @@ -156,7 +156,6 @@ struct inode *ialloc(struct inode *parent, umode_t mode) fail_drop: dquot_drop(inode); inode->i_flags |= S_NOQUOTA; -fail_unlock: clear_nlink(inode); unlock_new_inode(inode); fail_put: diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c index 9cd928f7a7c..0d37a6fd18a 100644 --- a/kernel/time/clockevents.c +++ b/kernel/time/clockevents.c @@ -30,29 +30,64 @@ static RAW_NOTIFIER_HEAD(clockevents_chain); /* Protection for the above */ static DEFINE_RAW_SPINLOCK(clockevents_lock); -/** - * clockevents_delta2ns - Convert a latch value (device ticks) to nanoseconds - * @latch: value to convert - * @evt: pointer to clock event device descriptor - * - * Math helper, returns latch value converted to nanoseconds (bound checked) - */ -u64 clockevent_delta2ns(unsigned long latch, struct clock_event_device *evt) +static u64 cev_delta2ns(unsigned long latch, struct clock_event_device *evt, + bool ismax) { u64 clc = (u64) latch << evt->shift; + u64 rnd; if (unlikely(!evt->mult)) { evt->mult = 1; WARN_ON(1); } + rnd = (u64) evt->mult - 1; + + /* + * Upper bound sanity check. If the backwards conversion is + * not equal latch, we know that the above shift overflowed. + */ + if ((clc >> evt->shift) != (u64)latch) + clc = ~0ULL; + + /* + * Scaled math oddities: + * + * For mult <= (1 << shift) we can safely add mult - 1 to + * prevent integer rounding loss. So the backwards conversion + * from nsec to device ticks will be correct. + * + * For mult > (1 << shift), i.e. device frequency is > 1GHz we + * need to be careful. Adding mult - 1 will result in a value + * which when converted back to device ticks can be larger + * than latch by up to (mult - 1) >> shift. For the min_delta + * calculation we still want to apply this in order to stay + * above the minimum device ticks limit. For the upper limit + * we would end up with a latch value larger than the upper + * limit of the device, so we omit the add to stay below the + * device upper boundary. + * + * Also omit the add if it would overflow the u64 boundary. + */ + if ((~0ULL - clc > rnd) && + (!ismax || evt->mult <= (1U << evt->shift))) + clc += rnd; do_div(clc, evt->mult); - if (clc < 1000) - clc = 1000; - if (clc > KTIME_MAX) - clc = KTIME_MAX; - return clc; + /* Deltas less than 1usec are pointless noise */ + return clc > 1000 ? clc : 1000; +} + +/** + * clockevents_delta2ns - Convert a latch value (device ticks) to nanoseconds + * @latch: value to convert + * @evt: pointer to clock event device descriptor + * + * Math helper, returns latch value converted to nanoseconds (bound checked) + */ +u64 clockevent_delta2ns(unsigned long latch, struct clock_event_device *evt) +{ + return cev_delta2ns(latch, evt, false); } EXPORT_SYMBOL_GPL(clockevent_delta2ns); @@ -318,8 +353,8 @@ static void clockevents_config(struct clock_event_device *dev, sec = 600; clockevents_calc_mult_shift(dev, freq, sec); - dev->min_delta_ns = clockevent_delta2ns(dev->min_delta_ticks, dev); - dev->max_delta_ns = clockevent_delta2ns(dev->max_delta_ticks, dev); + dev->min_delta_ns = cev_delta2ns(dev->min_delta_ticks, dev, false); + dev->max_delta_ns = cev_delta2ns(dev->max_delta_ticks, dev, true); } /** diff --git a/lib/scatterlist.c b/lib/scatterlist.c index 6096e89bee5..8c2f278e5eb 100644 --- a/lib/scatterlist.c +++ b/lib/scatterlist.c @@ -419,7 +419,8 @@ void sg_miter_stop(struct sg_mapping_iter *miter) if (miter->addr) { miter->__offset += miter->consumed; - if (miter->__flags & SG_MITER_TO_SG) + if ((miter->__flags & SG_MITER_TO_SG) && + !PageSlab(miter->page)) flush_kernel_dcache_page(miter->page); if (miter->__flags & SG_MITER_ATOMIC) { diff --git a/mm/swap.c b/mm/swap.c index 5c13f133897..f689e9a0320 100644 --- a/mm/swap.c +++ b/mm/swap.c @@ -30,6 +30,7 @@ #include #include #include +#include #include "internal.h" @@ -68,13 +69,26 @@ static void __put_compound_page(struct page *page) { compound_page_dtor *dtor; - __page_cache_release(page); + if (!PageHuge(page)) + __page_cache_release(page); dtor = get_compound_page_dtor(page); (*dtor)(page); } static void put_compound_page(struct page *page) { + /* + * hugetlbfs pages cannot be split from under us. If this is a + * hugetlbfs page, check refcount on head page and release the page if + * the refcount becomes zero. + */ + if (PageHuge(page)) { + page = compound_head(page); + if (put_page_testzero(page)) + __put_compound_page(page); + return; + } + if (unlikely(PageTail(page))) { /* __split_huge_page_refcount can run under us */ struct page *page_head = compound_trans_head(page); @@ -159,8 +173,20 @@ bool __get_page_tail(struct page *page) */ unsigned long flags; bool got = false; - struct page *page_head = compound_trans_head(page); + struct page *page_head; + + /* + * If this is a hugetlbfs page it cannot be split under us. Simply + * increment refcount for the head page. + */ + if (PageHuge(page)) { + page_head = compound_head(page); + atomic_inc(&page_head->_count); + got = true; + goto out; + } + page_head = compound_trans_head(page); if (likely(page != page_head && get_page_unless_zero(page_head))) { /* * page_head wasn't a dangling pointer but it @@ -178,6 +204,7 @@ bool __get_page_tail(struct page *page) if (unlikely(!got)) put_page(page_head); } +out: return got; } EXPORT_SYMBOL(__get_page_tail); diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 1196f36bc36..da515b52d64 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -790,12 +790,15 @@ struct tpt_led_trigger { * that the scan completed. * @SCAN_ABORTED: Set for our scan work function when the driver reported * a scan complete for an aborted scan. + * @SCAN_HW_CANCELLED: Set for our scan work function when the scan is being + * cancelled. */ enum { SCAN_SW_SCANNING, SCAN_HW_SCANNING, SCAN_COMPLETED, SCAN_ABORTED, + SCAN_HW_CANCELLED, }; /** diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index bcc57f93adc..9520749bd1e 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -259,6 +259,9 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local) enum ieee80211_band band; int i, ielen, n_chans; + if (test_bit(SCAN_HW_CANCELLED, &local->scanning)) + return false; + do { if (local->hw_scan_band == IEEE80211_NUM_BANDS) return false; @@ -844,7 +847,23 @@ void ieee80211_scan_cancel(struct ieee80211_local *local) if (!local->scan_req) goto out; + /* + * We have a scan running and the driver already reported completion, + * but the worker hasn't run yet or is stuck on the mutex - mark it as + * cancelled. + */ + if (test_bit(SCAN_HW_SCANNING, &local->scanning) && + test_bit(SCAN_COMPLETED, &local->scanning)) { + set_bit(SCAN_HW_CANCELLED, &local->scanning); + goto out; + } + if (test_bit(SCAN_HW_SCANNING, &local->scanning)) { + /* + * Make sure that __ieee80211_scan_completed doesn't trigger a + * scan on another band. + */ + set_bit(SCAN_HW_CANCELLED, &local->scanning); if (local->ops->cancel_hw_scan) drv_cancel_hw_scan(local, local->scan_sdata); goto out; diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 47b117f3f56..b992a49fbe0 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c @@ -183,6 +183,9 @@ static void ieee80211_frame_acked(struct sta_info *sta, struct sk_buff *skb) struct ieee80211_local *local = sta->local; struct ieee80211_sub_if_data *sdata = sta->sdata; + if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) + sta->last_rx = jiffies; + if (ieee80211_is_data_qos(mgmt->frame_control)) { struct ieee80211_hdr *hdr = (void *) skb->data; u8 *qc = ieee80211_get_qos_ctl(hdr); diff --git a/sound/core/pcm.c b/sound/core/pcm.c index bdf30cf3775..f150067a248 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -49,6 +49,8 @@ static struct snd_pcm *snd_pcm_get(struct snd_card *card, int device) struct snd_pcm *pcm; list_for_each_entry(pcm, &snd_pcm_devices, list) { + if (pcm->internal) + continue; if (pcm->card == card && pcm->device == device) return pcm; } @@ -60,6 +62,8 @@ static int snd_pcm_next(struct snd_card *card, int device) struct snd_pcm *pcm; list_for_each_entry(pcm, &snd_pcm_devices, list) { + if (pcm->internal) + continue; if (pcm->card == card && pcm->device > device) return pcm->device; else if (pcm->card->number > card->number) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 33abb782a54..810f1fc2c3f 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -6833,6 +6833,7 @@ static const struct snd_pci_quirk alc662_fixup_tbl[] = { SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE), SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800), SND_PCI_QUIRK(0x1043, 0x1477, "ASUS N56VZ", ALC662_FIXUP_ASUS_MODE4), + SND_PCI_QUIRK(0x1043, 0x1bf3, "ASUS N76VZ", ALC662_FIXUP_ASUS_MODE4), SND_PCI_QUIRK(0x1043, 0x8469, "ASUS mobo", ALC662_FIXUP_NO_JACK_DETECT), SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_FIXUP_ASUS_MODE2), SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD), diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index cd2dfe8db58..d3eac124c97 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c @@ -413,6 +413,7 @@ static int hp_supply_event(struct snd_soc_dapm_widget *w, hubs->hp_startup_mode); break; } + break; case SND_SOC_DAPM_PRE_PMD: snd_soc_update_bits(codec, WM8993_CHARGE_PUMP_1, diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index c642fce3717..3f329106ef7 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -1741,7 +1741,7 @@ static ssize_t dapm_widget_power_read_file(struct file *file, w->active ? "active" : "inactive"); list_for_each_entry(p, &w->sources, list_sink) { - if (p->connected && !p->connected(w, p->sink)) + if (p->connected && !p->connected(w, p->source)) continue; if (p->connect) From 89186d11e941f75b4df793bc18415a2ee8bec30a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 20 Nov 2013 10:43:41 -0800 Subject: [PATCH 143/215] Linux 3.4.70 - 10 commites squashed xen-netback: use jiffies_64 value to calculate credit timeout [ Upstream commit 059dfa6a93b779516321e5112db9d7621b1367ba ] time_after_eq() only works if the delta is < MAX_ULONG/2. For a 32bit Dom0, if netfront sends packets at a very low rate, the time between subsequent calls to tx_credit_exceeded() may exceed MAX_ULONG/2 and the test for timer_after_eq() will be incorrect. Credit will not be replenished and the guest may become unable to send packets (e.g., if prior to the long gap, all credit was exhausted). Use jiffies_64 variant to mitigate this problem for 32bit Dom0. Suggested-by: Jan Beulich Signed-off-by: Wei Liu Reviewed-by: David Vrabel Cc: Ian Campbell Cc: Jason Luan Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman net: flow_dissector: fail on evil iph->ihl [ Upstream commit 6f092343855a71e03b8d209815d8c45bf3a27fcd ] We don't validate iph->ihl which may lead a dead loop if we meet a IPIP skb whose iph->ihl is zero. Fix this by failing immediately when iph->ihl is evil (less than 5). This issue were introduced by commit ec5efe7946280d1e84603389a1030ccec0a767ae (rps: support IPIP encapsulation). Signed-off-by: Jason Wang Cc: Eric Dumazet Cc: Petr Matousek Cc: Michael S. Tsirkin Cc: Daniel Borkmann Acked-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman Conflicts: net/core/flow_dissector.c PCI: fix truncation of resource size to 32 bits commit d6776e6d5c2f8db0252f447b09736075e1bbe387 upstream. _pci_assign_resource() took an int "size" argument, which meant that sizes larger than 4GB were truncated. Change type to resource_size_t. [bhelgaas: changelog] Signed-off-by: Nikhil P Rao Signed-off-by: Bjorn Helgaas Cc: Jiri Slaby Signed-off-by: Greg Kroah-Hartman USB: add new zte 3g-dongle's pid to option.c commit 0636fc507a976cdc40f21bdbcce6f0b98ff1dfe9 upstream. Signed-off-by: Rui li Cc: stable Signed-off-by: Greg Kroah-Hartman ALSA: hda - Move one-time init codes from generic_hdmi_init() commit 8b8d654b55648561287bd8baca0f75f964a17038 upstream. The codes to initialize work struct or create a proc interface should be called only once and never although it's called many times through the init callback. Move that stuff into patch_generic_hdmi() so that it's called only once. Signed-off-by: Takashi Iwai BugLink: https://bugs.launchpad.net/bugs/1212160 Signed-off-by: David Henningsson Signed-off-by: Greg Kroah-Hartman netfilter: nf_ct_sip: don't drop packets with offsets pointing outside the packet commit 3a7b21eaf4fb3c971bdb47a98f570550ddfe4471 upstream. Some Cisco phones create huge messages that are spread over multiple packets. After calculating the offset of the SIP body, it is validated to be within the packet and the packet is dropped otherwise. This breaks operation of these phones. Since connection tracking is supposed to be passive, just let those packets pass unmodified and untracked. Signed-off-by: Patrick McHardy Signed-off-by: Pablo Neira Ayuso Cc: William Roberts Signed-off-by: Greg Kroah-Hartman tracing: Fix potential out-of-bounds in trace_get_user() commit 057db8488b53d5e4faa0cedb2f39d4ae75dfbdbb upstream. Andrey reported the following report: ERROR: AddressSanitizer: heap-buffer-overflow on address ffff8800359c99f3 ffff8800359c99f3 is located 0 bytes to the right of 243-byte region [ffff8800359c9900, ffff8800359c99f3) Accessed by thread T13003: #0 ffffffff810dd2da (asan_report_error+0x32a/0x440) #1 ffffffff810dc6b0 (asan_check_region+0x30/0x40) #2 ffffffff810dd4d3 (__tsan_write1+0x13/0x20) #3 ffffffff811cd19e (ftrace_regex_release+0x1be/0x260) #4 ffffffff812a1065 (__fput+0x155/0x360) #5 ffffffff812a12de (____fput+0x1e/0x30) #6 ffffffff8111708d (task_work_run+0x10d/0x140) #7 ffffffff810ea043 (do_exit+0x433/0x11f0) #8 ffffffff810eaee4 (do_group_exit+0x84/0x130) #9 ffffffff810eafb1 (SyS_exit_group+0x21/0x30) #10 ffffffff81928782 (system_call_fastpath+0x16/0x1b) Allocated by thread T5167: #0 ffffffff810dc778 (asan_slab_alloc+0x48/0xc0) #1 ffffffff8128337c (__kmalloc+0xbc/0x500) #2 ffffffff811d9d54 (trace_parser_get_init+0x34/0x90) #3 ffffffff811cd7b3 (ftrace_regex_open+0x83/0x2e0) #4 ffffffff811cda7d (ftrace_filter_open+0x2d/0x40) #5 ffffffff8129b4ff (do_dentry_open+0x32f/0x430) #6 ffffffff8129b668 (finish_open+0x68/0xa0) #7 ffffffff812b66ac (do_last+0xb8c/0x1710) #8 ffffffff812b7350 (path_openat+0x120/0xb50) #9 ffffffff812b8884 (do_filp_open+0x54/0xb0) #10 ffffffff8129d36c (do_sys_open+0x1ac/0x2c0) #11 ffffffff8129d4b7 (SyS_open+0x37/0x50) #12 ffffffff81928782 (system_call_fastpath+0x16/0x1b) Shadow bytes around the buggy address: ffff8800359c9700: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd ffff8800359c9780: fd fd fd fd fd fd fd fd fa fa fa fa fa fa fa fa ffff8800359c9800: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa ffff8800359c9880: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa ffff8800359c9900: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 =>ffff8800359c9980: 00 00 00 00 00 00 00 00 00 00 00 00 00 00[03]fb ffff8800359c9a00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa ffff8800359c9a80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa ffff8800359c9b00: fa fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00 ffff8800359c9b80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ffff8800359c9c00: 00 00 00 00 00 00 00 00 fa fa fa fa fa fa fa fa Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap redzone: fa Heap kmalloc redzone: fb Freed heap region: fd Shadow gap: fe The out-of-bounds access happens on 'parser->buffer[parser->idx] = 0;' Although the crash happened in ftrace_regex_open() the real bug occurred in trace_get_user() where there's an incrementation to parser->idx without a check against the size. The way it is triggered is if userspace sends in 128 characters (EVENT_BUF_SIZE + 1), the loop that reads the last character stores it and then breaks out because there is no more characters. Then the last character is read to determine what to do next, and the index is incremented without checking size. Then the caller of trace_get_user() usually nulls out the last character with a zero, but since the index is equal to the size, it writes a nul character after the allocated space, which can corrupt memory. Luckily, only root user has write access to this file. Link: http://lkml.kernel.org/r/20131009222323.04fd1a0d@gandalf.local.home Reported-by: Andrey Konovalov Signed-off-by: Steven Rostedt Signed-off-by: Greg Kroah-Hartman PCI/PM: Clear state_saved during suspend commit 82fee4d67ab86d6fe5eb0f9a9e988ca9d654d765 upstream. This patch clears pci_dev->state_saved at the beginning of suspending. PCI config state may be saved long before that. Some drivers call pci_save_state() from the ->probe() callback to get snapshot of sane configuration space to use in the ->slot_reset() callback. [wangyj: adjust context] Signed-off-by: Konstantin Khlebnikov # add comment Signed-off-by: Bjorn Helgaas Signed-off-by: Yijing Wang Signed-off-by: Greg Kroah-Hartman usb: fix cleanup after failure in hub_configure() commit d0308d4b6b02597f39fc31a9bddf7bb3faad5622 upstream. If the hub_configure() fails after setting the hdev->maxchild the hub->ports might be NULL or point to uninitialized kzallocated memory causing NULL pointer dereference in hub_quiesce() during cleanup. Now after such error the hdev->maxchild is set to 0 to avoid cleanup of uninitialized ports. Signed-off-by: Krzysztof Mazur Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- Makefile | 2 +- drivers/net/xen-netback/common.h | 1 + drivers/net/xen-netback/interface.c | 3 +-- drivers/net/xen-netback/netback.c | 10 +++++----- drivers/pci/pci-driver.c | 4 ++++ drivers/pci/setup-res.c | 3 ++- drivers/usb/core/hub.c | 1 + drivers/usb/serial/option.c | 17 +++++++++++++++++ kernel/trace/trace.c | 5 ++++- net/core/flow_dissector.c | 2 +- net/netfilter/nf_conntrack_sip.c | 2 +- sound/pci/hda/patch_hdmi.c | 22 +++++++++++++++++----- 12 files changed, 55 insertions(+), 17 deletions(-) diff --git a/Makefile b/Makefile index 4b35233dc21..a41d1e32e53 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 4 -SUBLEVEL = 69 +SUBLEVEL = 70 EXTRAVERSION = NAME = Saber-toothed Squirrel diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h index 9d7f1723dd8..093bf0a2fc8 100644 --- a/drivers/net/xen-netback/common.h +++ b/drivers/net/xen-netback/common.h @@ -88,6 +88,7 @@ struct xenvif { unsigned long credit_usec; unsigned long remaining_credit; struct timer_list credit_timeout; + u64 credit_window_start; /* Statistics */ unsigned long rx_gso_checksum_fixup; diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index 221f4265f7d..cfaaf68588a 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c @@ -273,8 +273,7 @@ struct xenvif *xenvif_alloc(struct device *parent, domid_t domid, vif->credit_bytes = vif->remaining_credit = ~0UL; vif->credit_usec = 0UL; init_timer(&vif->credit_timeout); - /* Initialize 'expires' now: it's used to track the credit window. */ - vif->credit_timeout.expires = jiffies; + vif->credit_window_start = get_jiffies_64(); dev->netdev_ops = &xenvif_netdev_ops; dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO; diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index 0d22cff02de..d8ffbf84e3d 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c @@ -1197,9 +1197,8 @@ static int checksum_setup(struct xenvif *vif, struct sk_buff *skb) static bool tx_credit_exceeded(struct xenvif *vif, unsigned size) { - unsigned long now = jiffies; - unsigned long next_credit = - vif->credit_timeout.expires + + u64 now = get_jiffies_64(); + u64 next_credit = vif->credit_window_start + msecs_to_jiffies(vif->credit_usec / 1000); /* Timer could already be pending in rare cases. */ @@ -1207,8 +1206,8 @@ static bool tx_credit_exceeded(struct xenvif *vif, unsigned size) return true; /* Passed the point where we can replenish credit? */ - if (time_after_eq(now, next_credit)) { - vif->credit_timeout.expires = now; + if (time_after_eq64(now, next_credit)) { + vif->credit_window_start = now; tx_add_credit(vif); } @@ -1220,6 +1219,7 @@ static bool tx_credit_exceeded(struct xenvif *vif, unsigned size) tx_credit_callback; mod_timer(&vif->credit_timeout, next_credit); + vif->credit_window_start = next_credit; return true; } diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index 2ab18ec45eb..92f38e78ff0 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -663,6 +663,7 @@ static int pci_pm_suspend(struct device *dev) goto Fixup; } + pci_dev->state_saved = false; if (pm->suspend) { pci_power_t prev = pci_dev->current_state; int error; @@ -809,6 +810,7 @@ static int pci_pm_freeze(struct device *dev) return 0; } + pci_dev->state_saved = false; if (pm->freeze) { int error; @@ -897,6 +899,7 @@ static int pci_pm_poweroff(struct device *dev) goto Fixup; } + pci_dev->state_saved = false; if (pm->poweroff) { int error; @@ -1015,6 +1018,7 @@ static int pci_pm_runtime_suspend(struct device *dev) if (!pm || !pm->runtime_suspend) return -ENOSYS; + pci_dev->state_saved = false; error = pm->runtime_suspend(dev); suspend_report_result(pm->runtime_suspend, error); if (error) diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c index eea85dafc76..be76ebacf48 100644 --- a/drivers/pci/setup-res.c +++ b/drivers/pci/setup-res.c @@ -206,7 +206,8 @@ static int pci_revert_fw_address(struct resource *res, struct pci_dev *dev, return ret; } -static int _pci_assign_resource(struct pci_dev *dev, int resno, int size, resource_size_t min_align) +static int _pci_assign_resource(struct pci_dev *dev, int resno, + resource_size_t size, resource_size_t min_align) { struct resource *res = dev->resource + resno; struct pci_bus *bus; diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 965b1771e0f..ed6c3617952 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1373,6 +1373,7 @@ static int hub_configure(struct usb_hub *hub, return 0; fail: + hdev->maxchild = 0; dev_err (hub_dev, "config failed, %s (err %d)\n", message, ret); /* hub_disconnect() frees urb and descriptor */ diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 57277bccb9e..a5477554ecb 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -1391,6 +1391,23 @@ static const struct usb_device_id option_ids[] = { .driver_info = (kernel_ulong_t)&net_intf2_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1426, 0xff, 0xff, 0xff), /* ZTE MF91 */ .driver_info = (kernel_ulong_t)&net_intf2_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1533, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1534, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1535, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1545, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1546, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1547, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1565, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1566, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1567, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1589, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1590, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1591, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1592, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1594, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1596, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1598, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1600, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2002, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t)&zte_k3765_z_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x2003, 0xff, 0xff, 0xff) }, diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index d3a66a67abb..5bf249ae86f 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -591,9 +591,12 @@ int trace_get_user(struct trace_parser *parser, const char __user *ubuf, if (isspace(ch)) { parser->buffer[parser->idx] = 0; parser->cont = false; - } else { + } else if (parser->idx < parser->size - 1) { parser->cont = true; parser->buffer[parser->idx++] = ch; + } else { + ret = -EINVAL; + goto out; } *ppos += read; diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index 0df746079a5..7540aa7daf5 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c @@ -35,7 +35,7 @@ bool skb_flow_dissect(const struct sk_buff *skb, struct flow_keys *flow) struct iphdr _iph; ip: iph = skb_header_pointer(skb, nhoff, sizeof(_iph), &_iph); - + if (!iph || iph->ihl < 5) /* CVE-2013-4348 issue : make sure iph->ihl is not zero ... */ if (!iph || iph->ihl < 5) return false; diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c index 93faf6a3a63..4a8c55bd60e 100644 --- a/net/netfilter/nf_conntrack_sip.c +++ b/net/netfilter/nf_conntrack_sip.c @@ -1468,7 +1468,7 @@ static int sip_help_tcp(struct sk_buff *skb, unsigned int protoff, msglen = origlen = end - dptr; if (msglen > datalen) - return NF_DROP; + return NF_ACCEPT; ret = process_sip_msg(skb, ct, dataoff, &dptr, &msglen); if (ret != NF_ACCEPT) diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 02a6e3f481e..ef917bf2450 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c @@ -1282,23 +1282,34 @@ static int generic_hdmi_build_controls(struct hda_codec *codec) return 0; } -static int generic_hdmi_init(struct hda_codec *codec) +static int generic_hdmi_init_per_pins(struct hda_codec *codec) { struct hdmi_spec *spec = codec->spec; int pin_idx; for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; - hda_nid_t pin_nid = per_pin->pin_nid; struct hdmi_eld *eld = &per_pin->sink_eld; - hdmi_init_pin(codec, pin_nid); - snd_hda_jack_detect_enable(codec, pin_nid, pin_nid); - per_pin->codec = codec; INIT_DELAYED_WORK(&per_pin->work, hdmi_repoll_eld); snd_hda_eld_proc_new(codec, eld, pin_idx); } + return 0; +} + +static int generic_hdmi_init(struct hda_codec *codec) +{ + struct hdmi_spec *spec = codec->spec; + int pin_idx; + + for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { + struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx]; + hda_nid_t pin_nid = per_pin->pin_nid; + + hdmi_init_pin(codec, pin_nid); + snd_hda_jack_detect_enable(codec, pin_nid, pin_nid); + } snd_hda_jack_report_sync(codec); return 0; } @@ -1343,6 +1354,7 @@ static int patch_generic_hdmi(struct hda_codec *codec) return -EINVAL; } codec->patch_ops = generic_hdmi_patch_ops; + generic_hdmi_init_per_pins(codec); init_channel_allocations(); From 584efba7d6d35aa029d232f955604c2c84ef2399 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 29 Nov 2013 10:50:58 -0800 Subject: [PATCH 144/215] Linux 3.4.71 - 40 commits squashed vfs,proc: guarantee unique inodes in /proc commit 51f0885e5415b4cc6535e9cdcc5145bfbc134353 upstream. Dave Jones found another /proc issue with his Trinity tool: thanks to the namespace model, we can have multiple /proc dentries that point to the same inode, aliasing directories in /proc//net/ for example. This ends up being a total disaster, because it acts like hardlinked directories, and causes locking problems. We rely on the topological sort of the inodes pointed to by dentries, and if we have aliased directories, that odering becomes unreliable. In short: don't do this. Multiple dentries with the same (directory) inode is just a bad idea, and the namespace code should never have exposed things this way. But we're kind of stuck with it. This solves things by just always allocating a new inode during /proc dentry lookup, instead of using "iget_locked()" to look up existing inodes by superblock and number. That actually simplies the code a bit, at the cost of potentially doing more inode [de]allocations. That said, the inode lookup wasn't free either (and did a lot of locking of inodes), so it is probably not that noticeable. We could easily keep the old lookup model for non-directory entries, but rather than try to be excessively clever this just implements the minimal and simplest workaround for the problem. Reported-and-tested-by: Dave Jones Analyzed-by: Al Viro Signed-off-by: Linus Torvalds [bwh: Backported to 3.2: - Adjust context - Never drop the pde reference in proc_get_inode(), as callers only expect this when we return an existing inode, and we never do that now] Signed-off-by: Ben Hutchings Cc: Rui Xiang Signed-off-by: Greg Kroah-Hartman nfs: don't allow nfs_find_actor to match inodes of the wrong type commit f6488c9ba51d65410e2dbc4345413c0d9120971e upstream. Benny Halevy reported the following oops when testing RHEL6: <7>nfs_update_inode: inode 892950 mode changed, 0040755 to 0100644 <1>BUG: unable to handle kernel NULL pointer dereference at (null) <1>IP: [] nfs_closedir+0x15/0x30 [nfs] <4>PGD 81448a067 PUD 831632067 PMD 0 <4>Oops: 0000 [#1] SMP <4>last sysfs file: /sys/kernel/mm/redhat_transparent_hugepage/enabled <4>CPU 6 <4>Modules linked in: fuse bonding 8021q garp ebtable_nat ebtables be2iscsi iscsi_boot_sysfs bnx2i cnic uio cxgb4i cxgb4 cxgb3i libcxgbi cxgb3 mdio ib_iser rdma_cm ib_cm iw_cm ib_sa ib_mad ib_core ib_addr iscsi_tcp libiscsi_tcp libiscsi scsi_transport_iscsi softdog bridge stp llc xt_physdev ipt_REJECT nf_conntrack_ipv4 nf_defrag_ipv4 xt_multiport iptable_filter ip_tables ip6t_REJECT nf_conntrack_ipv6 nf_defrag_ipv6 xt_state nf_conntrack ip6table_filter ip6_tables ipv6 dm_round_robin dm_multipath objlayoutdriver2(U) nfs(U) lockd fscache auth_rpcgss nfs_acl sunrpc vhost_net macvtap macvlan tun kvm_intel kvm be2net igb dca ptp pps_core microcode serio_raw sg iTCO_wdt iTCO_vendor_support i7core_edac edac_core shpchp ext4 mbcache jbd2 sd_mod crc_t10dif ahci dm_mirror dm_region_hash dm_log dm_mod [last unloaded: scsi_wait_scan] <4> <4>Pid: 6332, comm: dd Not tainted 2.6.32-358.el6.x86_64 #1 HP ProLiant DL170e G6 /ProLiant DL170e G6 <4>RIP: 0010:[] [] nfs_closedir+0x15/0x30 [nfs] <4>RSP: 0018:ffff88081458bb98 EFLAGS: 00010292 <4>RAX: ffffffffa02a52b0 RBX: 0000000000000000 RCX: 0000000000000003 <4>RDX: ffffffffa02e45a0 RSI: ffff88081440b300 RDI: ffff88082d5f5760 <4>RBP: ffff88081458bba8 R08: 0000000000000000 R09: 0000000000000000 <4>R10: 0000000000000772 R11: 0000000000400004 R12: 0000000040000008 <4>R13: ffff88082d5f5760 R14: ffff88082d6e8800 R15: ffff88082f12d780 <4>FS: 00007f728f37e700(0000) GS:ffff8800456c0000(0000) knlGS:0000000000000000 <4>CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b <4>CR2: 0000000000000000 CR3: 0000000831279000 CR4: 00000000000007e0 <4>DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 <4>DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 <4>Process dd (pid: 6332, threadinfo ffff88081458a000, task ffff88082fa0e040) <4>Stack: <4> 0000000040000008 ffff88081440b300 ffff88081458bbf8 ffffffff81182745 <4> ffff88082d5f5760 ffff88082d6e8800 ffff88081458bbf8 ffffffffffffffea <4> ffff88082f12d780 ffff88082d6e8800 ffffffffa02a50a0 ffff88082d5f5760 <4>Call Trace: <4> [] __fput+0xf5/0x210 <4> [] ? do_open+0x0/0x20 [nfs] <4> [] fput+0x25/0x30 <4> [] __dentry_open+0x27e/0x360 <4> [] ? inotify_d_instantiate+0x2a/0x60 <4> [] lookup_instantiate_filp+0x69/0x90 <4> [] nfs_intent_set_file+0x59/0x90 [nfs] <4> [] nfs_atomic_lookup+0x1bb/0x310 [nfs] <4> [] __lookup_hash+0x102/0x160 <4> [] ? selinux_inode_permission+0x72/0xb0 <4> [] lookup_hash+0x3a/0x50 <4> [] do_filp_open+0x2eb/0xdd0 <4> [] ? __do_page_fault+0x1ec/0x480 <4> [] ? alloc_fd+0x92/0x160 <4> [] do_sys_open+0x69/0x140 <4> [] ? sys_lseek+0x66/0x80 <4> [] sys_open+0x20/0x30 <4> [] system_call_fastpath+0x16/0x1b <4>Code: 65 48 8b 04 25 c8 cb 00 00 83 a8 44 e0 ff ff 01 5b 41 5c c9 c3 90 55 48 89 e5 53 48 83 ec 08 0f 1f 44 00 00 48 8b 9e a0 00 00 00 <48> 8b 3b e8 13 0c f7 ff 48 89 df e8 ab 3d ec e0 48 83 c4 08 31 <1>RIP [] nfs_closedir+0x15/0x30 [nfs] <4> RSP <4>CR2: 0000000000000000 I think this is ultimately due to a bug on the server. The client had previously found a directory dentry. It then later tried to do an atomic open on a new (regular file) dentry. The attributes it got back had the same filehandle as the previously found directory inode. It then tried to put the filp because it failed the aops tests for O_DIRECT opens, and oopsed here because the ctx was still NULL. Obviously the root cause here is a server issue, but we can take steps to mitigate this on the client. When nfs_fhget is called, we always know what type of inode it is. In the event that there's a broken or malicious server on the other end of the wire, the client can end up crashing because the wrong ops are set on it. Have nfs_find_actor check that the inode type is correct after checking the fileid. The fileid check should rarely ever match, so it should only rarely ever get to this check. In the case where we have a broken server, we may see two different inodes with the same i_ino, but the client should be able to cope with them without crashing. This should fix the oops reported here: https://bugzilla.redhat.com/show_bug.cgi?id=913660 Reported-by: Benny Halevy Signed-off-by: Jeff Layton Signed-off-by: Trond Myklebust Cc: Rui Xiang Signed-off-by: Greg Kroah-Hartman libertas: potential oops in debugfs commit a497e47d4aec37aaf8f13509f3ef3d1f6a717d88 upstream. If we do a zero size allocation then it will oops. Also we can't be sure the user passes us a NUL terminated string so I've added a terminator. This code can only be triggered by root. Reported-by: Nico Golde Reported-by: Fabian Yamaguchi Signed-off-by: Dan Carpenter Acked-by: Dan Williams Signed-off-by: John W. Linville Cc: Kees Cook Signed-off-by: Greg Kroah-Hartman aacraid: prevent invalid pointer dereference commit b4789b8e6be3151a955ade74872822f30e8cd914 upstream. It appears that driver runs into a problem here if fibsize is too small because we allocate user_srbcmd with fibsize size only but later we access it until user_srbcmd->sg.count to copy it over to srbcmd. It is not correct to test (fibsize < sizeof(*user_srbcmd)) because this structure already includes one sg element and this is not needed for commands without data. So, we would recommend to add the following (instead of test for fibsize == 0). Signed-off-by: Mahesh Rajashekhara Reported-by: Nico Golde Reported-by: Fabian Yamaguchi Signed-off-by: Linus Torvalds Cc: Kees Cook Signed-off-by: Greg Kroah-Hartman ACPICA: Interpreter: Fix Store() when implicit conversion is not possible. commit 3f654bad3257427bea7ba1c4d43a23d99a03622b upstream. For the cases such as a store of a string to an existing package object, implement the store as a CopyObject(). This is a small departure from the ACPI specification which states that the control method should be aborted in this case. However, ASLTS suite depends on this behavior. Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman ACPICA: DeRefOf operator: Update to fully resolve FieldUnit and BufferField refs. commit 63660e05ec719613b518547b40a1c501c10f0bc4 upstream. Previously, references to these objects were resolved only to the actual FieldUnit or BufferField object. The correct behavior is to resolve these references to an actual value. The problem is that DerefOf did not resolve these objects to actual values. An "Integer" object is simple, return the value. But a field in an operation region will require a read operation. For a BufferField, the appropriate data must be extracted from the parent buffer. NOTE: It appears that this issues is present in Windows7 but not Windows8. Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman ACPICA: Return error if DerefOf resolves to a null package element. commit a50abf4842dd7d603a2ad6dcc7f1467fd2a66f03 upstream. Disallow the dereference of a reference (via index) to an uninitialized package element. Provides compatibility with other ACPI implementations. ACPICA BZ 1003. References: https://bugs.acpica.org/show_bug.cgi?id=431 Signed-off-by: Bob Moore Signed-off-by: Lv Zheng Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman ACPICA: Fix for a Store->ArgX when ArgX contains a reference to a field. commit 4be4be8fee2ee99a52f94f90d03d2f287ee1db86 upstream. This change fixes a problem where a Store operation to an ArgX object that contained a reference to a field object did not complete the automatic dereference and then write to the actual field object. Instead, the object type of the field object was inadvertently changed to match the type of the source operand. The new behavior will actually write to the field object (buffer field or field unit), thus matching the correct ACPI-defined behavior. Signed-off-by: Bob Moore Signed-off-by: Rafael J. Wysocki Signed-off-by: Lv Zheng Signed-off-by: Greg Kroah-Hartman USB: mos7840: fix tiocmget error handling commit a91ccd26e75235d86248d018fe3779732bcafd8d upstream. Make sure to return errors from tiocmget rather than rely on uninitialised stack data. Signed-off-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman crypto: ansi_cprng - Fix off by one error in non-block size request commit 714b33d15130cbb5ab426456d4e3de842d6c5b8a upstream. Stephan Mueller reported to me recently a error in random number generation in the ansi cprng. If several small requests are made that are less than the instances block size, the remainder for loop code doesn't increment rand_data_valid in the last iteration, meaning that the last bytes in the rand_data buffer gets reused on the subsequent smaller-than-a-block request for random data. The fix is pretty easy, just re-code the for loop to make sure that rand_data_valid gets incremented appropriately Signed-off-by: Neil Horman Reported-by: Stephan Mueller CC: Stephan Mueller CC: Petr Matousek CC: Herbert Xu CC: "David S. Miller" Signed-off-by: Herbert Xu Cc: Luis Henriques Signed-off-by: Greg Kroah-Hartman can: c_can: Fix RX message handling, handle lost message before EOB commit 5d0f801a2ccec3b1fdabc3392c8d99ed0413d216 upstream. If we handle end of block messages with higher priority than a lost message, we can run into an endless interrupt loop. This is reproducable with a am335x processor and "cansequence -r" at 1Mbit. As soon as we loose a packet we can't escape from an interrupt loop. This patch fixes the problem by handling lost packets before EOB packets. Signed-off-by: Markus Pargmann Signed-off-by: Marc Kleine-Budde Signed-off-by: Greg Kroah-Hartman 8139cp: re-enable interrupts after tx timeout commit 01ffc0a7f1c1801a2354719dedbc32aff45b987d upstream. Recovery doesn't work too well if we leave interrupts disabled... Signed-off-by: David Woodhouse Acked-by: Francois Romieu Signed-off-by: David S. Miller Cc: Luis Henriques Signed-off-by: Greg Kroah-Hartman Fix a few incorrectly checked [io_]remap_pfn_range() calls commit 7314e613d5ff9f0934f7a0f74ed7973b903315d1 upstream. Nico Golde reports a few straggling uses of [io_]remap_pfn_range() that really should use the vm_iomap_memory() helper. This trivially converts two of them to the helper, and comments about why the third one really needs to continue to use remap_pfn_range(), and adds the missing size check. Reported-by: Nico Golde Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman SUNRPC handle EKEYEXPIRED in call_refreshresult commit eb96d5c97b0825d542e9c4ba5e0a22b519355166 upstream. Currently, when an RPCSEC_GSS context has expired or is non-existent and the users (Kerberos) credentials have also expired or are non-existent, the client receives the -EKEYEXPIRED error and tries to refresh the context forever. If an application is performing I/O, or other work against the share, the application hangs, and the user is not prompted to refresh/establish their credentials. This can result in a denial of service for other users. Users are expected to manage their Kerberos credential lifetimes to mitigate this issue. Move the -EKEYEXPIRED handling into the RPC layer. Try tk_cred_retry number of times to refresh the gss_context, and then return -EACCES to the application. Signed-off-by: Andy Adamson Signed-off-by: Trond Myklebust [bwh: Backported to 3.2: - Adjust context - Drop change to nfs4_handle_reclaim_lease_error()] Signed-off-by: Ben Hutchings Signed-off-by: Greg Kroah-Hartman SUNRPC: don't map EKEYEXPIRED to EACCES in call_refreshresult commit f1ff0c27fd9987c59d707cd1a6b6c1fc3ae0a250 upstream. The NFS layer needs to know when a key has expired. This change also returns -EKEYEXPIRED to the application, and the informative "Key has expired" error message is displayed. The user then knows that credential renewal is required. Signed-off-by: Andy Adamson Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman Nest rename_lock inside vfsmount_lock commit 7ea600b5314529f9d1b9d6d3c41cb26fce6a7a4a upstream. ... lest we get livelocks between path_is_under() and d_path() and friends. The thing is, wrt fairness lglocks are more similar to rwsems than to rwlocks; it is possible to have thread B spin on attempt to take lock shared while thread A is already holding it shared, if B is on lower-numbered CPU than A and there's a thread C spinning on attempt to take the same lock exclusive. As the result, we need consistent ordering between vfsmount_lock (lglock) and rename_lock (seq_lock), even though everything that takes both is going to take vfsmount_lock only shared. Spotted-by: Brad Spengler Cc: stable@vger.kernel.org Signed-off-by: Al Viro [ zhj: backport to 3.4: - Adjust context - s/&vfsmount_lock/vfsmount_lock/] Signed-off-by: Zhao Hongjiang Signed-off-by: Greg Kroah-Hartman exec: do not abuse ->cred_guard_mutex in threadgroup_lock() commit e56fb2874015370e3b7f8d85051f6dce26051df9 upstream. threadgroup_lock() takes signal->cred_guard_mutex to ensure that thread_group_leader() is stable. This doesn't look nice, the scope of this lock in do_execve() is huge. And as Dave pointed out this can lead to deadlock, we have the following dependencies: do_execve: cred_guard_mutex -> i_mutex cgroup_mount: i_mutex -> cgroup_mutex attach_task_by_pid: cgroup_mutex -> cred_guard_mutex Change de_thread() to take threadgroup_change_begin() around the switch-the-leader code and change threadgroup_lock() to avoid ->cred_guard_mutex. Note that de_thread() can't sleep with ->group_rwsem held, this can obviously deadlock with the exiting leader if the writer is active, so it does threadgroup_change_end() before schedule(). Reported-by: Dave Jones Acked-by: Tejun Heo Acked-by: Li Zefan Signed-off-by: Oleg Nesterov Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds [ zhj: adjust context ] Signed-off-by: Zhao Hongjiang Signed-off-by: Greg Kroah-Hartman include/linux/fs.h: disable preempt when acquire i_size_seqcount write lock commit 74e3d1e17b2e11d175970b85acd44f5927000ba2 upstream. Two rt tasks bind to one CPU core. The higher priority rt task A preempts a lower priority rt task B which has already taken the write seq lock, and then the higher priority rt task A try to acquire read seq lock, it's doomed to lockup. rt task A with lower priority: call write i_size_write rt task B with higher priority: call sync, and preempt task A write_seqcount_begin(&inode->i_size_seqcount); i_size_read inode->i_size = i_size; read_seqcount_begin <-- lockup here... So disable preempt when acquiring every i_size_seqcount *write* lock will cure the problem. Signed-off-by: Fan Du Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Cc: Zhao Hongjiang Signed-off-by: Greg Kroah-Hartman perf/ftrace: Fix paranoid level for enabling function tracer commit 12ae030d54ef250706da5642fc7697cc60ad0df7 upstream. The current default perf paranoid level is "1" which has "perf_paranoid_kernel()" return false, and giving any operations that use it, access to normal users. Unfortunately, this includes function tracing and normal users should not be allowed to enable function tracing by default. The proper level is defined at "-1" (full perf access), which "perf_paranoid_tracepoint_raw()" will only give access to. Use that check instead for enabling function tracing. Reported-by: Dave Jones Reported-by: Vince Weaver Tested-by: Vince Weaver Cc: Peter Zijlstra Cc: Ingo Molnar Cc: Jiri Olsa Cc: Frederic Weisbecker CVE: CVE-2013-2930 Fixes: ced39002f5ea ("ftrace, perf: Add support to use function tracepoint in perf") Signed-off-by: Steven Rostedt Signed-off-by: Greg Kroah-Hartman rt2x00: check if device is still available on rt2x00mac_flush() commit 5671ab05cf2a579218985ef56595387932d78ee4 upstream. Fix random kernel panic with below messages when remove dongle. [ 2212.355447] BUG: unable to handle kernel NULL pointer dereference at 0000000000000250 [ 2212.355527] IP: [] rt2x00usb_kick_tx_entry+0x12/0x160 [rt2x00usb] [ 2212.355599] PGD 0 [ 2212.355626] Oops: 0000 [#1] SMP [ 2212.355664] Modules linked in: rt2800usb rt2x00usb rt2800lib crc_ccitt rt2x00lib mac80211 cfg80211 tun arc4 fuse rfcomm bnep snd_hda_codec_realtek snd_hda_intel snd_hda_codec btusb uvcvideo bluetooth snd_hwdep x86_pkg_temp_thermal snd_seq coretemp aesni_intel aes_x86_64 snd_seq_device glue_helper snd_pcm ablk_helper videobuf2_vmalloc sdhci_pci videobuf2_memops videobuf2_core sdhci videodev mmc_core serio_raw snd_page_alloc microcode i2c_i801 snd_timer hid_multitouch thinkpad_acpi lpc_ich mfd_core snd tpm_tis wmi tpm tpm_bios soundcore acpi_cpufreq i915 i2c_algo_bit drm_kms_helper drm i2c_core video [last unloaded: cfg80211] [ 2212.356224] CPU: 0 PID: 34 Comm: khubd Not tainted 3.12.0-rc3-wl+ #3 [ 2212.356268] Hardware name: LENOVO 3444CUU/3444CUU, BIOS G6ET93WW (2.53 ) 02/04/2013 [ 2212.356319] task: ffff880212f687c0 ti: ffff880212f66000 task.ti: ffff880212f66000 [ 2212.356392] RIP: 0010:[] [] rt2x00usb_kick_tx_entry+0x12/0x160 [rt2x00usb] [ 2212.356481] RSP: 0018:ffff880212f67750 EFLAGS: 00010202 [ 2212.356519] RAX: 000000000000000c RBX: 000000000000000c RCX: 0000000000000293 [ 2212.356568] RDX: ffff8801f4dc219a RSI: 0000000000000000 RDI: 0000000000000240 [ 2212.356617] RBP: ffff880212f67778 R08: ffffffffa02667e0 R09: 0000000000000002 [ 2212.356665] R10: 0001f95254ab4b40 R11: ffff880212f675be R12: ffff8801f4dc2150 [ 2212.356712] R13: 0000000000000000 R14: ffffffffa02667e0 R15: 000000000000000d [ 2212.356761] FS: 0000000000000000(0000) GS:ffff88021e200000(0000) knlGS:0000000000000000 [ 2212.356813] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 2212.356852] CR2: 0000000000000250 CR3: 0000000001a0c000 CR4: 00000000001407f0 [ 2212.356899] Stack: [ 2212.356917] 000000000000000c ffff8801f4dc2150 0000000000000000 ffffffffa02667e0 [ 2212.356980] 000000000000000d ffff880212f677b8 ffffffffa03a31ad ffff8801f4dc219a [ 2212.357038] ffff8801f4dc2150 0000000000000000 ffff8800b93217a0 ffff8801f49bc800 [ 2212.357099] Call Trace: [ 2212.357122] [] ? rt2x00usb_interrupt_txdone+0x90/0x90 [rt2x00usb] [ 2212.357174] [] rt2x00queue_for_each_entry+0xed/0x170 [rt2x00lib] [ 2212.357244] [] rt2x00usb_kick_queue+0x5c/0x60 [rt2x00usb] [ 2212.357314] [] rt2x00queue_flush_queue+0x62/0xa0 [rt2x00lib] [ 2212.357386] [] rt2x00mac_flush+0x30/0x70 [rt2x00lib] [ 2212.357470] [] ieee80211_flush_queues+0xbd/0x140 [mac80211] [ 2212.357555] [] ieee80211_set_disassoc+0x2d2/0x3d0 [mac80211] [ 2212.357645] [] ieee80211_mgd_deauth+0x1d3/0x240 [mac80211] [ 2212.357718] [] ? try_to_wake_up+0xec/0x290 [ 2212.357788] [] ieee80211_deauth+0x18/0x20 [mac80211] [ 2212.357872] [] cfg80211_mlme_deauth+0x9c/0x140 [cfg80211] [ 2212.357913] [] cfg80211_mlme_down+0x5c/0x60 [cfg80211] [ 2212.357962] [] cfg80211_disconnect+0x188/0x1a0 [cfg80211] [ 2212.358014] [] ? __cfg80211_stop_sched_scan+0x1c/0x130 [cfg80211] [ 2212.358067] [] cfg80211_leave+0xc4/0xe0 [cfg80211] [ 2212.358124] [] cfg80211_netdev_notifier_call+0x3ab/0x5e0 [cfg80211] [ 2212.358177] [] ? inetdev_event+0x38/0x510 [ 2212.358217] [] ? __wake_up+0x44/0x50 [ 2212.358254] [] notifier_call_chain+0x4c/0x70 [ 2212.358293] [] raw_notifier_call_chain+0x16/0x20 [ 2212.358361] [] call_netdevice_notifiers_info+0x35/0x60 [ 2212.358429] [] __dev_close_many+0x49/0xd0 [ 2212.358487] [] dev_close_many+0x88/0x100 [ 2212.358546] [] rollback_registered_many+0xb0/0x220 [ 2212.358612] [] unregister_netdevice_many+0x19/0x60 [ 2212.358694] [] ieee80211_remove_interfaces+0x112/0x190 [mac80211] [ 2212.358791] [] ieee80211_unregister_hw+0x4f/0x100 [mac80211] [ 2212.361994] [] rt2x00lib_remove_dev+0x161/0x1a0 [rt2x00lib] [ 2212.365240] [] rt2x00usb_disconnect+0x2e/0x70 [rt2x00usb] [ 2212.368470] [] usb_unbind_interface+0x64/0x1c0 [ 2212.371734] [] __device_release_driver+0x7f/0xf0 [ 2212.374999] [] device_release_driver+0x23/0x30 [ 2212.378131] [] bus_remove_device+0x108/0x180 [ 2212.381358] [] device_del+0x135/0x1d0 [ 2212.384454] [] usb_disable_device+0xb0/0x270 [ 2212.387451] [] usb_disconnect+0xad/0x1d0 [ 2212.390294] [] hub_thread+0x63d/0x1660 [ 2212.393034] [] ? wake_up_atomic_t+0x30/0x30 [ 2212.395728] [] ? hub_port_debounce+0x130/0x130 [ 2212.398412] [] kthread+0xc0/0xd0 [ 2212.401058] [] ? insert_kthread_work+0x40/0x40 [ 2212.403639] [] ret_from_fork+0x7c/0xb0 [ 2212.406193] [] ? insert_kthread_work+0x40/0x40 [ 2212.408732] Code: 24 58 08 00 00 bf 80 00 00 00 e8 3a c3 e0 e0 5b 41 5c 5d c3 0f 1f 44 00 00 0f 1f 44 00 00 55 48 89 e5 41 57 41 56 41 55 41 54 53 <48> 8b 47 10 48 89 fb 4c 8b 6f 28 4c 8b 20 49 8b 04 24 4c 8b 30 [ 2212.414671] RIP [] rt2x00usb_kick_tx_entry+0x12/0x160 [rt2x00usb] [ 2212.417646] RSP [ 2212.420547] CR2: 0000000000000250 [ 2212.441024] ---[ end trace 5442918f33832bce ]--- Signed-off-by: Stanislaw Gruszka Acked-by: Helmut Schaa Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman Revert "ima: policy for RAMFS" commit 08de59eb144d7c41351a467442f898d720f0f15f upstream. This reverts commit 4c2c392763a682354fac65b6a569adec4e4b5387. Everything in the initramfs should be measured and appraised, but until the initramfs has extended attribute support, at least measured. Signed-off-by: Mimi Zohar Signed-off-by: Greg Kroah-Hartman exec/ptrace: fix get_dumpable() incorrect tests commit d049f74f2dbe71354d43d393ac3a188947811348 upstream. The get_dumpable() return value is not boolean. Most users of the function actually want to be testing for non-SUID_DUMP_USER(1) rather than SUID_DUMP_DISABLE(0). The SUID_DUMP_ROOT(2) is also considered a protected state. Almost all places did this correctly, excepting the two places fixed in this patch. Wrong logic: if (dumpable == SUID_DUMP_DISABLE) { /* be protective */ } or if (dumpable == 0) { /* be protective */ } or if (!dumpable) { /* be protective */ } Correct logic: if (dumpable != SUID_DUMP_USER) { /* be protective */ } or if (dumpable != 1) { /* be protective */ } Without this patch, if the system had set the sysctl fs/suid_dumpable=2, a user was able to ptrace attach to processes that had dropped privileges to that user. (This may have been partially mitigated if Yama was enabled.) The macros have been moved into the file that declares get/set_dumpable(), which means things like the ia64 code can see them too. CVE-2013-2929 Reported-by: Vasily Kulikov Signed-off-by: Kees Cook Cc: "Luck, Tony" Cc: Oleg Nesterov Cc: "Eric W. Biederman" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman ALSA: 6fire: Fix probe of multiple cards commit 9b389a8a022110b4bc055a19b888283544d9eba6 upstream. The probe code of snd-usb-6fire driver overrides the devices[] pointer wrongly without checking whether it's already occupied or not. This would screw up the device disconnection later. Spotted by coverity CID 141423. Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman ALSA: msnd: Avoid duplicated driver name commit 092f9cd16aac7d054af1755c945f37c1b33399e6 upstream. msnd_pinnacle.c is used for both snd-msnd-pinnacle and snd-msnd-classic drivers, and both should have different driver names. Using the same driver name results in the sysfs warning for duplicated entries like kobject: 'msnd-pinnacle.7' (cec33408): kobject_release, parent (null) (delayed) kobject: 'msnd-pinnacle' (cecd4980): kobject_release, parent cf3ad9b0 (delayed) ------------[ cut here ]------------ WARNING: CPU: 0 PID: 1 at fs/sysfs/dir.c:486 sysfs_warn_dup+0x7d/0xa0() sysfs: cannot create duplicate filename '/bus/isa/drivers/msnd-pinnacle' ...... Reported-by: Fengguang Wu Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman NFSv4: Fix a use-after-free situation in _nfs4_proc_getlk() commit a6f951ddbdfb7bd87d31a44f61abe202ed6ce57f upstream. In nfs4_proc_getlk(), when some error causes a retry of the call to _nfs4_proc_getlk(), we can end up with Oopses of the form BUG: unable to handle kernel NULL pointer dereference at 0000000000000134 IP: [] _raw_spin_lock+0xe/0x30 Call Trace: [] _atomic_dec_and_lock+0x4d/0x70 [] nfs4_put_lock_state+0x32/0xb0 [nfsv4] [] nfs4_fl_release_lock+0x15/0x20 [nfsv4] [] _nfs4_proc_getlk.isra.40+0x146/0x170 [nfsv4] [] nfs4_proc_lock+0x399/0x5a0 [nfsv4] The problem is that we don't clear the request->fl_ops after the first try and so when we retry, nfs4_set_lock_state() exits early without setting the lock stateid. Regression introduced by commit 70cc6487a4e08b8698c0e2ec935fb48d10490162 (locks: make ->lock release private data before returning in GETLK case) Reported-by: Weston Andros Adamson Reported-by: Jorge Mora Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman nfsd: split up nfsd_setattr commit 818e5a22e907fbae75e9c1fd78233baec9fa64b6 upstream. Split out two helpers to make the code more readable and easier to verify for correctness. Signed-off-by: Christoph Hellwig Signed-off-by: J. Bruce Fields Signed-off-by: Greg Kroah-Hartman nfsd: make sure to balance get/put_write_access commit 987da4791052fa298b7cfcde4dea9f6f2bbc786b upstream. Use a straight goto error label style in nfsd_setattr to make sure we always do the put_write_access call after we got it earlier. Note that the we have been failing to do that in the case nfsd_break_lease() returns an error, a bug introduced into 2.6.38 with 6a76bebefe15d9a08864f824d7f8d5beaf37c997 "nfsd4: break lease on nfsd setattr". Signed-off-by: Christoph Hellwig Signed-off-by: J. Bruce Fields Signed-off-by: Greg Kroah-Hartman x86/microcode/amd: Tone down printk(), don't treat a missing firmware file as an error commit 11f918d3e2d3861b6931e97b3aa778e4984935aa upstream. Do it the same way as done in microcode_intel.c: use pr_debug() for missing firmware files. There seem to be CPUs out there for which no microcode update has been submitted to kernel-firmware repo yet resulting in scary sounding error messages in dmesg: microcode: failed to load file amd-ucode/microcode_amd_fam16h.bin Signed-off-by: Thomas Renninger Acked-by: Borislav Petkov Link: http://lkml.kernel.org/r/1384274383-43510-1-git-send-email-trenn@suse.de Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman hwmon: (lm90) Fix max6696 alarm handling commit e41fae2b1ed8c78283d73651cd65be0228c0dd1c upstream. Bit 2 of status register 2 on MAX6696 (external diode 2 open) sets ALERT; the bit thus has to be listed in alert_alarms. Also display a message in the alert handler if the condition is encountered. Even though not all overtemperature conditions cause ALERT to be set, we should not ignore them in the alert handler. Display messages for all out-of-range conditions. Reported-by: Jean Delvare Signed-off-by: Guenter Roeck Signed-off-by: Jean Delvare Signed-off-by: Greg Kroah-Hartman block: fix race between request completion and timeout handling commit 4912aa6c11e6a5d910264deedbec2075c6f1bb73 upstream. crocode i2c_i801 i2c_core iTCO_wdt iTCO_vendor_support shpchp ioatdma dca be2net sg ses enclosure ext4 mbcache jbd2 sd_mod crc_t10dif ahci megaraid_sas(U) dm_mirror dm_region_hash dm_log dm_mod [last unloaded: scsi_wait_scan] Pid: 491, comm: scsi_eh_0 Tainted: G W ---------------- 2.6.32-220.13.1.el6.x86_64 #1 IBM -[8722PAX]-/00D1461 RIP: 0010:[] [] blk_requeue_request+0x94/0xa0 RSP: 0018:ffff881057eefd60 EFLAGS: 00010012 RAX: ffff881d99e3e8a8 RBX: ffff881d99e3e780 RCX: ffff881d99e3e8a8 RDX: ffff881d99e3e8a8 RSI: ffff881d99e3e780 RDI: ffff881d99e3e780 RBP: ffff881057eefd80 R08: ffff881057eefe90 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000000 R12: ffff881057f92338 R13: 0000000000000000 R14: ffff881057f92338 R15: ffff883058188000 FS: 0000000000000000(0000) GS:ffff880040200000(0000) knlGS:0000000000000000 CS: 0010 DS: 0018 ES: 0018 CR0: 000000008005003b CR2: 00000000006d3ec0 CR3: 000000302cd7d000 CR4: 00000000000406b0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Process scsi_eh_0 (pid: 491, threadinfo ffff881057eee000, task ffff881057e29540) Stack: 0000000000001057 0000000000000286 ffff8810275efdc0 ffff881057f16000 <0> ffff881057eefdd0 ffffffff81362323 ffff881057eefe20 ffffffff8135f393 <0> ffff881057e29af8 ffff8810275efdc0 ffff881057eefe78 ffff881057eefe90 Call Trace: [] __scsi_queue_insert+0xa3/0x150 [] ? scsi_eh_ready_devs+0x5e3/0x850 [] scsi_queue_insert+0x13/0x20 [] scsi_eh_flush_done_q+0x104/0x160 [] scsi_error_handler+0x35b/0x660 [] ? scsi_error_handler+0x0/0x660 [] kthread+0x96/0xa0 [] child_rip+0xa/0x20 [] ? kthread+0x0/0xa0 [] ? child_rip+0x0/0x20 Code: 00 00 eb d1 4c 8b 2d 3c 8f 97 00 4d 85 ed 74 bf 49 8b 45 00 49 83 c5 08 48 89 de 4c 89 e7 ff d0 49 8b 45 00 48 85 c0 75 eb eb a4 <0f> 0b eb fe 0f 1f 84 00 00 00 00 00 55 48 89 e5 0f 1f 44 00 00 RIP [] blk_requeue_request+0x94/0xa0 RSP The RIP is this line: BUG_ON(blk_queued_rq(rq)); After digging through the code, I think there may be a race between the request completion and the timer handler running. A timer is started for each request put on the device's queue (see blk_start_request->blk_add_timer). If the request does not complete before the timer expires, the timer handler (blk_rq_timed_out_timer) will mark the request complete atomically: static inline int blk_mark_rq_complete(struct request *rq) { return test_and_set_bit(REQ_ATOM_COMPLETE, &rq->atomic_flags); } and then call blk_rq_timed_out. The latter function will call scsi_times_out, which will return one of BLK_EH_HANDLED, BLK_EH_RESET_TIMER or BLK_EH_NOT_HANDLED. If BLK_EH_RESET_TIMER is returned, blk_clear_rq_complete is called, and blk_add_timer is again called to simply wait longer for the request to complete. Now, if the request happens to complete while this is going on, what happens? Given that we know the completion handler will bail if it finds the REQ_ATOM_COMPLETE bit set, we need to focus on the completion handler running after that bit is cleared. So, from the above paragraph, after the call to blk_clear_rq_complete. If the completion sets REQ_ATOM_COMPLETE before the BUG_ON in blk_add_timer, we go boom there (I haven't seen this in the cores). Next, if we get the completion before the call to list_add_tail, then the timer will eventually fire for an old req, which may either be freed or reallocated (there is evidence that this might be the case). Finally, if the completion comes in *after* the addition to the timeout list, I think it's harmless. The request will be removed from the timeout list, req_atom_complete will be set, and all will be well. This will only actually explain the coredumps *IF* the request structure was freed, reallocated *and* queued before the error handler thread had a chance to process it. That is possible, but it may make sense to keep digging for another race. I think that if this is what was happening, we would see other instances of this problem showing up as null pointer or garbage pointer dereferences, for example when the request structure was not re-used. It looks like we actually do run into that situation in other reports. This patch moves the BUG_ON(test_bit(REQ_ATOM_COMPLETE, &req->atomic_flags)); from blk_add_timer to the only caller that could trip over it (blk_start_request). It then inverts the calls to blk_clear_rq_complete and blk_add_timer in blk_rq_timed_out to address the race. I've boot tested this patch, but nothing more. Signed-off-by: Jeff Moyer Acked-by: Hannes Reinecke Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman block: fix a probe argument to blk_register_region commit a207f5937630dd35bd2550620bef416937a1365e upstream. The probe function is supposed to return NULL on failure (as we can see in kobj_lookup: kobj = probe(dev, index, data); ... if (kobj) return kobj; However, in loop and brd, it returns negative error from ERR_PTR. This causes a crash if we simulate disk allocation failure and run less -f /dev/loop0 because the negative number is interpreted as a pointer: BUG: unable to handle kernel NULL pointer dereference at 00000000000002b4 IP: [] __blkdev_get+0x28/0x450 PGD 23c677067 PUD 23d6d1067 PMD 0 Oops: 0000 [#1] PREEMPT SMP Modules linked in: loop hpfs nvidia(PO) ip6table_filter ip6_tables uvesafb cfbcopyarea cfbimgblt cfbfillrect fbcon font bitblit fbcon_rotate fbcon_cw fbcon_ud fbcon_ccw softcursor fb fbdev msr ipt_MASQUERADE iptable_nat nf_nat_ipv4 nf_conntrack_ipv4 nf_defrag_ipv4 xt_state ipt_REJECT xt_tcpudp iptable_filter ip_tables x_tables bridge stp llc tun ipv6 cpufreq_stats cpufreq_ondemand cpufreq_userspace cpufreq_powersave cpufreq_conservative hid_generic spadfs usbhid hid fuse raid0 snd_usb_audio snd_pcm_oss snd_mixer_oss md_mod snd_pcm snd_timer snd_page_alloc snd_hwdep snd_usbmidi_lib dmi_sysfs snd_rawmidi nf_nat_ftp nf_nat nf_conntrack_ftp nf_conntrack snd soundcore lm85 hwmon_vid ohci_hcd ehci_pci ehci_hcd serverworks sata_svw libata acpi_cpufreq freq_table mperf ide_core usbcore kvm_amd kvm tg3 i2c_piix4 libphy microcode e100 usb_common ptp skge i2c_core pcspkr k10temp evdev floppy hwmon pps_core mii rtc_cmos button processor unix [last unloaded: nvidia] CPU: 1 PID: 6831 Comm: less Tainted: P W O 3.10.15-devel #18 Hardware name: empty empty/S3992-E, BIOS 'V1.06 ' 06/09/2009 task: ffff880203cc6bc0 ti: ffff88023e47c000 task.ti: ffff88023e47c000 RIP: 0010:[] [] __blkdev_get+0x28/0x450 RSP: 0018:ffff88023e47dbd8 EFLAGS: 00010286 RAX: ffffffffffffff74 RBX: ffffffffffffff74 RCX: 0000000000000000 RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000001 RBP: ffff88023e47dc18 R08: 0000000000000002 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000000 R12: ffff88023f519658 R13: ffffffff8118c300 R14: 0000000000000000 R15: ffff88023f519640 FS: 00007f2070bf7700(0000) GS:ffff880247400000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00000000000002b4 CR3: 000000023da1d000 CR4: 00000000000007e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Stack: 0000000000000002 0000001d00000000 000000003e47dc50 ffff88023f519640 ffff88043d5bb668 ffffffff8118c300 ffff88023d683550 ffff88023e47de60 ffff88023e47dc98 ffffffff8118c10d 0000001d81605698 0000000000000292 Call Trace: [] ? blkdev_get_by_dev+0x60/0x60 [] blkdev_get+0x1dd/0x370 [] ? blkdev_get_by_dev+0x60/0x60 [] ? _raw_spin_unlock+0x2c/0x50 [] ? blkdev_get_by_dev+0x60/0x60 [] blkdev_open+0x65/0x80 [] do_dentry_open.isra.18+0x23e/0x2f0 [] finish_open+0x34/0x50 [] do_last.isra.62+0x2d2/0xc50 [] path_openat.isra.63+0xb8/0x4d0 [] ? might_fault+0x4e/0xa0 [] do_filp_open+0x40/0x90 [] ? _raw_spin_unlock+0x2c/0x50 [] ? __alloc_fd+0xa5/0x1f0 [] do_sys_open+0xef/0x1d0 [] SyS_open+0x19/0x20 [] system_call_fastpath+0x1a/0x1f Code: 44 00 00 55 48 89 e5 41 57 49 89 ff 41 56 41 89 d6 41 55 41 54 4c 8d 67 18 53 48 83 ec 18 89 75 cc e9 f2 00 00 00 0f 1f 44 00 00 <48> 8b 80 40 03 00 00 48 89 df 4c 8b 68 58 e8 d5 a4 07 00 44 89 RIP [] __blkdev_get+0x28/0x450 RSP CR2: 00000000000002b4 ---[ end trace bb7f32dbf02398dc ]--- The brd change should be backported to stable kernels starting with 2.6.25. The loop change should be backported to stable kernels starting with 2.6.22. Signed-off-by: Mikulas Patocka Acked-by: Tejun Heo Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman block: properly stack underlying max_segment_size to DM device commit d82ae52e68892338068e7559a0c0657193341ce4 upstream. Without this patch all DM devices will default to BLK_MAX_SEGMENT_SIZE (65536) even if the underlying device(s) have a larger value -- this is due to blk_stack_limits() using min_not_zero() when stacking the max_segment_size limit. 1073741824 before patch: 65536 after patch: 1073741824 Reported-by: Lukasz Flis Signed-off-by: Mike Snitzer Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman powerpc/vio: use strcpy in modalias_show commit 411cabf79e684171669ad29a0628c400b4431e95 upstream. Commit e82b89a6f19bae73fb064d1b3dd91fcefbb478f4 used strcat instead of strcpy which can result in an overflow of newlines on the buffer. Signed-off-by: Prarit Bhargava Cc: benh@kernel.crashing.org Cc: ben@decadent.org.uk Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Greg Kroah-Hartman powerpc/powernv: Add PE to its own PELTV commit 631ad691b5818291d89af9be607d2fe40be0886e upstream. We need add PE to its own PELTV. Otherwise, the errors originated from the PE might contribute to other PEs. In the result, we can't clear up the error successfully even we're checking and clearing errors during access to PCI config space. Reported-by: kalshett@in.ibm.com Signed-off-by: Gavin Shan Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Greg Kroah-Hartman powerpc/signals: Mark VSX not saved with small contexts commit c13f20ac48328b05cd3b8c19e31ed6c132b44b42 upstream. The VSX MSR bit in the user context indicates if the context contains VSX state. Currently we set this when the process has touched VSX at any stage. Unfortunately, if the user has not provided enough space to save the VSX state, we can't save it but we currently still set the MSR VSX bit. This patch changes this to clear the MSR VSX bit when the user doesn't provide enough space. This indicates that there is no valid VSX state in the user context. This is needed to support get/set/make/swapcontext for applications that use VSX but only provide a small context. For example, getcontext in glibc provides a smaller context since the VSX registers don't need to be saved over the glibc function call. But since the program calling getcontext may have used VSX, the kernel currently says the VSX state is valid when it's not. If the returned context is then used in setcontext (ie. a small context without VSX but with MSR VSX set), the kernel will refuse the context. This situation has been reported by the glibc community. Based on patch from Carlos O'Donell. Tested-by: Haren Myneni Signed-off-by: Michael Neuling Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Greg Kroah-Hartman SUNRPC: Fix a data corruption issue when retransmitting RPC calls commit a6b31d18b02ff9d7915c5898c9b5ca41a798cd73 upstream. The following scenario can cause silent data corruption when doing NFS writes. It has mainly been observed when doing database writes using O_DIRECT. 1) The RPC client uses sendpage() to do zero-copy of the page data. 2) Due to networking issues, the reply from the server is delayed, and so the RPC client times out. 3) The client issues a second sendpage of the page data as part of an RPC call retransmission. 4) The reply to the first transmission arrives from the server _before_ the client hardware has emptied the TCP socket send buffer. 5) After processing the reply, the RPC state machine rules that the call to be done, and triggers the completion callbacks. 6) The application notices the RPC call is done, and reuses the pages to store something else (e.g. a new write). 7) The client NIC drains the TCP socket send buffer. Since the page data has now changed, it reads a corrupted version of the initial RPC call, and puts it on the wire. This patch fixes the problem in the following manner: The ordering guarantees of TCP ensure that when the server sends a reply, then we know that the _first_ transmission has completed. Using zero-copy in that situation is therefore safe. If a time out occurs, we then send the retransmission using sendmsg() (i.e. no zero-copy), We then know that the socket contains a full copy of the data, and so it will retransmit a faithful reproduction even if the RPC call completes, and the application reuses the O_DIRECT buffer in the meantime. Signed-off-by: Trond Myklebust Signed-off-by: Greg Kroah-Hartman rt2800usb: slow down TX status polling commit 36165fd5b00bf8163f89c21bb16a3e9834555b10 upstream. Polling TX statuses too frequently has two negative effects. First is randomly peek CPU usage, causing overall system functioning delays. Second bad effect is that device is not able to fill TX statuses in H/W register on some workloads and we get lot of timeouts like below: ieee80211 phy4: rt2800usb_entry_txstatus_timeout: Warning - TX status timeout for entry 7 in queue 2 ieee80211 phy4: rt2800usb_entry_txstatus_timeout: Warning - TX status timeout for entry 7 in queue 2 ieee80211 phy4: rt2800usb_txdone: Warning - Got TX status for an empty queue 2, dropping This not only cause flood of messages in dmesg, but also bad throughput, since rate scaling algorithm can not work optimally. In the future, we should probably make polling interval be adjusted automatically, but for now just increase values, this make mentioned problems gone. Resolve: https://bugzilla.kernel.org/show_bug.cgi?id=62781 Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman configfs: fix race between dentry put and lookup commit 76ae281f6307331aa063288edb6422ae99f435f0 upstream. A race window in configfs, it starts from one dentry is UNHASHED and end before configfs_d_iput is called. In this window, if a lookup happen, since the original dentry was UNHASHED, so a new dentry will be allocated, and then in configfs_attach_attr(), sd->s_dentry will be updated to the new dentry. Then in configfs_d_iput(), BUG_ON(sd->s_dentry != dentry) will be triggered and system panic. sys_open: sys_close: ... fput dput dentry_kill __d_drop <--- dentry unhashed here, but sd->dentry still point to this dentry. lookup_real configfs_lookup configfs_attach_attr---> update sd->s_dentry to new allocated dentry here. d_kill configfs_d_iput <--- BUG_ON(sd->s_dentry != dentry) triggered here. To fix it, change configfs_d_iput to not update sd->s_dentry if sd->s_count > 2, that means there are another dentry is using the sd beside the one that is going to be put. Use configfs_dirent_lock in configfs_attach_attr to sync with configfs_d_iput. With the following steps, you can reproduce the bug. 1. enable ocfs2, this will mount configfs at /sys/kernel/config and fill configure in it. 2. run the following script. while [ 1 ]; do cat /sys/kernel/config/cluster/$your_cluster_name/idle_timeout_ms > /dev/null; done & while [ 1 ]; do cat /sys/kernel/config/cluster/$your_cluster_name/idle_timeout_ms > /dev/null; done & Signed-off-by: Junxiao Bi Cc: Joel Becker Cc: Al Viro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman cris: media platform drivers: fix build commit 72a0c5571351f5184195754d23db3e14495b2080 upstream. On cris arch, the functions below aren't defined: drivers/media/platform/sh_veu.c: In function 'sh_veu_reg_read': drivers/media/platform/sh_veu.c:228:2: error: implicit declaration of function 'ioread32' [-Werror=implicit-function-declaration] drivers/media/platform/sh_veu.c: In function 'sh_veu_reg_write': drivers/media/platform/sh_veu.c:234:2: error: implicit declaration of function 'iowrite32' [-Werror=implicit-function-declaration] drivers/media/platform/vsp1/vsp1.h: In function 'vsp1_read': drivers/media/platform/vsp1/vsp1.h:66:2: error: implicit declaration of function 'ioread32' [-Werror=implicit-function-declaration] drivers/media/platform/vsp1/vsp1.h: In function 'vsp1_write': drivers/media/platform/vsp1/vsp1.h:71:2: error: implicit declaration of function 'iowrite32' [-Werror=implicit-function-declaration] drivers/media/platform/vsp1/vsp1.h: In function 'vsp1_read': drivers/media/platform/vsp1/vsp1.h:66:2: error: implicit declaration of function 'ioread32' [-Werror=implicit-function-declaration] drivers/media/platform/vsp1/vsp1.h: In function 'vsp1_write': drivers/media/platform/vsp1/vsp1.h:71:2: error: implicit declaration of function 'iowrite32' [-Werror=implicit-function-declaration] drivers/media/platform/soc_camera/rcar_vin.c: In function 'rcar_vin_setup': drivers/media/platform/soc_camera/rcar_vin.c:284:3: error: implicit declaration of function 'iowrite32' [-Werror=implicit-function-declaration] drivers/media/platform/soc_camera/rcar_vin.c: In function 'rcar_vin_request_capture_stop': drivers/media/platform/soc_camera/rcar_vin.c:353:2: error: implicit declaration of function 'ioread32' [-Werror=implicit-function-declaration] Yet, they're available, as CONFIG_GENERIC_IOMAP is defined. What happens is that asm/io.h was not including asm-generic/iomap.h. Suggested-by: Ben Hutchings Signed-off-by: Mauro Carvalho Chehab Cc: Mikael Starvik Cc: Jesper Nilsson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman --- Makefile | 2 +- arch/cris/include/asm/io.h | 1 + arch/ia64/include/asm/processor.h | 2 +- arch/powerpc/kernel/signal_32.c | 10 +- arch/powerpc/kernel/vio.c | 4 +- arch/powerpc/platforms/powernv/pci-ioda.c | 12 +- arch/x86/kernel/microcode_amd.c | 2 +- block/blk-core.c | 1 + block/blk-settings.c | 1 + block/blk-timeout.c | 3 +- crypto/ansi_cprng.c | 4 +- drivers/acpi/acpica/exoparg1.c | 48 +++++- drivers/acpi/acpica/exstore.c | 151 +++++++++++++------ drivers/block/brd.c | 2 +- drivers/block/loop.c | 2 +- drivers/hwmon/lm90.c | 11 +- drivers/net/can/c_can/c_can.c | 6 +- drivers/net/ethernet/realtek/8139cp.c | 1 + drivers/net/wireless/libertas/debugfs.c | 6 +- drivers/net/wireless/rt2x00/rt2800usb.c | 12 +- drivers/net/wireless/rt2x00/rt2x00mac.c | 3 + drivers/scsi/aacraid/commctrl.c | 3 +- drivers/uio/uio.c | 16 +- drivers/usb/serial/mos7840.c | 4 + drivers/video/au1100fb.c | 26 +--- drivers/video/au1200fb.c | 23 +-- fs/configfs/dir.c | 16 +- fs/dcache.c | 16 +- fs/exec.c | 9 ++ fs/nfs/inode.c | 2 + fs/nfs/nfs3proc.c | 6 +- fs/nfs/nfs4filelayout.c | 1 - fs/nfs/nfs4proc.c | 19 +-- fs/nfs/nfs4state.c | 21 --- fs/nfs/proc.c | 43 ------ fs/nfsd/vfs.c | 173 +++++++++++++--------- fs/proc/inode.c | 12 +- include/linux/binfmts.h | 3 - include/linux/fs.h | 2 + include/linux/sched.h | 22 +-- kernel/ptrace.c | 3 +- kernel/trace/trace_event_perf.c | 2 +- net/sunrpc/clnt.c | 1 + net/sunrpc/xprtsock.c | 28 +++- security/integrity/ima/ima_policy.c | 1 - sound/isa/msnd/msnd_pinnacle.c | 4 +- sound/usb/6fire/chip.c | 2 +- 47 files changed, 410 insertions(+), 332 deletions(-) diff --git a/Makefile b/Makefile index a41d1e32e53..aba4f850401 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 4 -SUBLEVEL = 70 +SUBLEVEL = 71 EXTRAVERSION = NAME = Saber-toothed Squirrel diff --git a/arch/cris/include/asm/io.h b/arch/cris/include/asm/io.h index ac12ae2b928..db9a16c704f 100644 --- a/arch/cris/include/asm/io.h +++ b/arch/cris/include/asm/io.h @@ -3,6 +3,7 @@ #include /* for __va, __pa */ #include +#include #include struct cris_io_operations diff --git a/arch/ia64/include/asm/processor.h b/arch/ia64/include/asm/processor.h index 483f6c6a423..2d0cb8e8eed 100644 --- a/arch/ia64/include/asm/processor.h +++ b/arch/ia64/include/asm/processor.h @@ -322,7 +322,7 @@ struct thread_struct { regs->loadrs = 0; \ regs->r8 = get_dumpable(current->mm); /* set "don't zap registers" flag */ \ regs->r12 = new_sp - 16; /* allocate 16 byte scratch area */ \ - if (unlikely(!get_dumpable(current->mm))) { \ + if (unlikely(get_dumpable(current->mm) != SUID_DUMP_USER)) { \ /* \ * Zap scratch regs to avoid leaking bits between processes with different \ * uid/privileges. \ diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index 45eb998557f..e6de787956c 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c @@ -459,7 +459,15 @@ static int save_user_regs(struct pt_regs *regs, struct mcontext __user *frame, if (copy_vsx_to_user(&frame->mc_vsregs, current)) return 1; msr |= MSR_VSX; - } + } else if (!ctx_has_vsx_region) + /* + * With a small context structure we can't hold the VSX + * registers, hence clear the MSR value to indicate the state + * was not saved. + */ + msr &= ~MSR_VSX; + + #endif /* CONFIG_VSX */ #ifdef CONFIG_SPE /* save spe registers */ diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c index cfe0069bcfc..fcf89bff117 100644 --- a/arch/powerpc/kernel/vio.c +++ b/arch/powerpc/kernel/vio.c @@ -1342,12 +1342,12 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, dn = dev->of_node; if (!dn) { - strcat(buf, "\n"); + strcpy(buf, "\n"); return strlen(buf); } cp = of_get_property(dn, "compatible", NULL); if (!cp) { - strcat(buf, "\n"); + strcpy(buf, "\n"); return strlen(buf); } diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index fbdd74dac3a..5da8e8df592 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c @@ -613,13 +613,23 @@ static int __devinit pnv_ioda_configure_pe(struct pnv_phb *phb, rid_end = pe->rid + 1; } - /* Associate PE in PELT */ + /* + * Associate PE in PELT. We need add the PE into the + * corresponding PELT-V as well. Otherwise, the error + * originated from the PE might contribute to other + * PEs. + */ rc = opal_pci_set_pe(phb->opal_id, pe->pe_number, pe->rid, bcomp, dcomp, fcomp, OPAL_MAP_PE); if (rc) { pe_err(pe, "OPAL error %ld trying to setup PELT table\n", rc); return -ENXIO; } + + rc = opal_pci_set_peltv(phb->opal_id, pe->pe_number, + pe->pe_number, OPAL_ADD_PE_TO_DOMAIN); + if (rc) + pe_warn(pe, "OPAL error %d adding self to PELTV\n", rc); opal_pci_eeh_freeze_clear(phb->opal_id, pe->pe_number, OPAL_EEH_ACTION_CLEAR_FREEZE_ALL); diff --git a/arch/x86/kernel/microcode_amd.c b/arch/x86/kernel/microcode_amd.c index 5d8cf0d6796..b316ffe8ab5 100644 --- a/arch/x86/kernel/microcode_amd.c +++ b/arch/x86/kernel/microcode_amd.c @@ -338,7 +338,7 @@ static enum ucode_state request_microcode_amd(int cpu, struct device *device) snprintf(fw_name, sizeof(fw_name), "amd-ucode/microcode_amd_fam%.2xh.bin", c->x86); if (request_firmware(&fw, (const char *)fw_name, device)) { - pr_err("failed to load file %s\n", fw_name); + pr_debug("failed to load file %s\n", fw_name); goto out; } diff --git a/block/blk-core.c b/block/blk-core.c index cd37dea6772..7641d1e372c 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -2129,6 +2129,7 @@ void blk_start_request(struct request *req) if (unlikely(blk_bidi_rq(req))) req->next_rq->resid_len = blk_rq_bytes(req->next_rq); + BUG_ON(test_bit(REQ_ATOM_COMPLETE, &req->atomic_flags)); blk_add_timer(req); } EXPORT_SYMBOL(blk_start_request); diff --git a/block/blk-settings.c b/block/blk-settings.c index 579328cff6d..0be72a0c907 100644 --- a/block/blk-settings.c +++ b/block/blk-settings.c @@ -155,6 +155,7 @@ void blk_set_stacking_limits(struct queue_limits *lim) lim->discard_zeroes_data = 1; lim->max_segments = USHRT_MAX; lim->max_hw_sectors = UINT_MAX; + lim->max_segment_size = UINT_MAX; lim->max_sectors = BLK_DEF_MAX_SECTORS; } diff --git a/block/blk-timeout.c b/block/blk-timeout.c index 78035488895..b1182ea5242 100644 --- a/block/blk-timeout.c +++ b/block/blk-timeout.c @@ -90,8 +90,8 @@ static void blk_rq_timed_out(struct request *req) __blk_complete_request(req); break; case BLK_EH_RESET_TIMER: - blk_clear_rq_complete(req); blk_add_timer(req); + blk_clear_rq_complete(req); break; case BLK_EH_NOT_HANDLED: /* @@ -173,7 +173,6 @@ void blk_add_timer(struct request *req) return; BUG_ON(!list_empty(&req->timeout_list)); - BUG_ON(test_bit(REQ_ATOM_COMPLETE, &req->atomic_flags)); /* * Some LLDs, like scsi, peek at the timeout to prevent a diff --git a/crypto/ansi_cprng.c b/crypto/ansi_cprng.c index 6ddd99e6114..c21f761b65b 100644 --- a/crypto/ansi_cprng.c +++ b/crypto/ansi_cprng.c @@ -230,11 +230,11 @@ static int get_prng_bytes(char *buf, size_t nbytes, struct prng_context *ctx, */ if (byte_count < DEFAULT_BLK_SZ) { empty_rbuf: - for (; ctx->rand_data_valid < DEFAULT_BLK_SZ; - ctx->rand_data_valid++) { + while (ctx->rand_data_valid < DEFAULT_BLK_SZ) { *ptr = ctx->rand_data[ctx->rand_data_valid]; ptr++; byte_count--; + ctx->rand_data_valid++; if (byte_count == 0) goto done; } diff --git a/drivers/acpi/acpica/exoparg1.c b/drivers/acpi/acpica/exoparg1.c index 9ba8c73cea1..fe2f9d95d0f 100644 --- a/drivers/acpi/acpica/exoparg1.c +++ b/drivers/acpi/acpica/exoparg1.c @@ -970,10 +970,17 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) */ return_desc = *(operand[0]->reference.where); - if (return_desc) { - acpi_ut_add_reference - (return_desc); + if (!return_desc) { + /* + * Element is NULL, do not allow the dereference. + * This provides compatibility with other ACPI + * implementations. + */ + return_ACPI_STATUS + (AE_AML_UNINITIALIZED_ELEMENT); } + + acpi_ut_add_reference(return_desc); break; default: @@ -998,11 +1005,40 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state) acpi_namespace_node *) return_desc); - } + if (!return_desc) { + break; + } - /* Add another reference to the object! */ + /* + * June 2013: + * buffer_fields/field_units require additional resolution + */ + switch (return_desc->common.type) { + case ACPI_TYPE_BUFFER_FIELD: + case ACPI_TYPE_LOCAL_REGION_FIELD: + case ACPI_TYPE_LOCAL_BANK_FIELD: + case ACPI_TYPE_LOCAL_INDEX_FIELD: - acpi_ut_add_reference(return_desc); + status = + acpi_ex_read_data_from_field + (walk_state, return_desc, + &temp_desc); + if (ACPI_FAILURE(status)) { + goto cleanup; + } + + return_desc = temp_desc; + break; + + default: + + /* Add another reference to the object */ + + acpi_ut_add_reference + (return_desc); + break; + } + } break; default: diff --git a/drivers/acpi/acpica/exstore.c b/drivers/acpi/acpica/exstore.c index c6cf843cc4c..9806f4be7b8 100644 --- a/drivers/acpi/acpica/exstore.c +++ b/drivers/acpi/acpica/exstore.c @@ -57,6 +57,11 @@ acpi_ex_store_object_to_index(union acpi_operand_object *val_desc, union acpi_operand_object *dest_desc, struct acpi_walk_state *walk_state); +static acpi_status +acpi_ex_store_direct_to_node(union acpi_operand_object *source_desc, + struct acpi_namespace_node *node, + struct acpi_walk_state *walk_state); + /******************************************************************************* * * FUNCTION: acpi_ex_store @@ -376,7 +381,11 @@ acpi_ex_store_object_to_index(union acpi_operand_object *source_desc, * When storing into an object the data is converted to the * target object type then stored in the object. This means * that the target object type (for an initialized target) will - * not be changed by a store operation. + * not be changed by a store operation. A copy_object can change + * the target type, however. + * + * The implicit_conversion flag is set to NO/FALSE only when + * storing to an arg_x -- as per the rules of the ACPI spec. * * Assumes parameters are already validated. * @@ -400,7 +409,7 @@ acpi_ex_store_object_to_node(union acpi_operand_object *source_desc, target_type = acpi_ns_get_type(node); target_desc = acpi_ns_get_attached_object(node); - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Storing %p(%s) into node %p(%s)\n", + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Storing %p (%s) to node %p (%s)\n", source_desc, acpi_ut_get_object_type_name(source_desc), node, acpi_ut_get_type_name(target_type))); @@ -414,46 +423,31 @@ acpi_ex_store_object_to_node(union acpi_operand_object *source_desc, return_ACPI_STATUS(status); } - /* If no implicit conversion, drop into the default case below */ - - if ((!implicit_conversion) || - ((walk_state->opcode == AML_COPY_OP) && - (target_type != ACPI_TYPE_LOCAL_REGION_FIELD) && - (target_type != ACPI_TYPE_LOCAL_BANK_FIELD) && - (target_type != ACPI_TYPE_LOCAL_INDEX_FIELD))) { - /* - * Force execution of default (no implicit conversion). Note: - * copy_object does not perform an implicit conversion, as per the ACPI - * spec -- except in case of region/bank/index fields -- because these - * objects must retain their original type permanently. - */ - target_type = ACPI_TYPE_ANY; - } - /* Do the actual store operation */ switch (target_type) { - case ACPI_TYPE_BUFFER_FIELD: - case ACPI_TYPE_LOCAL_REGION_FIELD: - case ACPI_TYPE_LOCAL_BANK_FIELD: - case ACPI_TYPE_LOCAL_INDEX_FIELD: - - /* For fields, copy the source data to the target field. */ - - status = acpi_ex_write_data_to_field(source_desc, target_desc, - &walk_state->result_obj); - break; - case ACPI_TYPE_INTEGER: case ACPI_TYPE_STRING: case ACPI_TYPE_BUFFER: /* - * These target types are all of type Integer/String/Buffer, and - * therefore support implicit conversion before the store. - * - * Copy and/or convert the source object to a new target object + * The simple data types all support implicit source operand + * conversion before the store. */ + + if ((walk_state->opcode == AML_COPY_OP) || !implicit_conversion) { + /* + * However, copy_object and Stores to arg_x do not perform + * an implicit conversion, as per the ACPI specification. + * A direct store is performed instead. + */ + status = acpi_ex_store_direct_to_node(source_desc, node, + walk_state); + break; + } + + /* Store with implicit source operand conversion support */ + status = acpi_ex_store_object_to_object(source_desc, target_desc, &new_desc, walk_state); @@ -467,13 +461,12 @@ acpi_ex_store_object_to_node(union acpi_operand_object *source_desc, * the Name's type to that of the value being stored in it. * source_desc reference count is incremented by attach_object. * - * Note: This may change the type of the node if an explicit store - * has been performed such that the node/object type has been - * changed. + * Note: This may change the type of the node if an explicit + * store has been performed such that the node/object type + * has been changed. */ - status = - acpi_ns_attach_object(node, new_desc, - new_desc->common.type); + status = acpi_ns_attach_object(node, new_desc, + new_desc->common.type); ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Store %s into %s via Convert/Attach\n", @@ -484,19 +477,83 @@ acpi_ex_store_object_to_node(union acpi_operand_object *source_desc, } break; + case ACPI_TYPE_BUFFER_FIELD: + case ACPI_TYPE_LOCAL_REGION_FIELD: + case ACPI_TYPE_LOCAL_BANK_FIELD: + case ACPI_TYPE_LOCAL_INDEX_FIELD: + /* + * For all fields, always write the source data to the target + * field. Any required implicit source operand conversion is + * performed in the function below as necessary. Note, field + * objects must retain their original type permanently. + */ + status = acpi_ex_write_data_to_field(source_desc, target_desc, + &walk_state->result_obj); + break; + default: + /* + * No conversions for all other types. Directly store a copy of + * the source object. This is the ACPI spec-defined behavior for + * the copy_object operator. + * + * NOTE: For the Store operator, this is a departure from the + * ACPI spec, which states "If conversion is impossible, abort + * the running control method". Instead, this code implements + * "If conversion is impossible, treat the Store operation as + * a CopyObject". + */ + status = acpi_ex_store_direct_to_node(source_desc, node, + walk_state); + break; + } - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Storing %s (%p) directly into node (%p) with no implicit conversion\n", - acpi_ut_get_object_type_name(source_desc), - source_desc, node)); + return_ACPI_STATUS(status); +} - /* No conversions for all other types. Just attach the source object */ +/******************************************************************************* + * + * FUNCTION: acpi_ex_store_direct_to_node + * + * PARAMETERS: source_desc - Value to be stored + * node - Named object to receive the value + * walk_state - Current walk state + * + * RETURN: Status + * + * DESCRIPTION: "Store" an object directly to a node. This involves a copy + * and an attach. + * + ******************************************************************************/ - status = acpi_ns_attach_object(node, source_desc, - source_desc->common.type); - break; +static acpi_status +acpi_ex_store_direct_to_node(union acpi_operand_object *source_desc, + struct acpi_namespace_node *node, + struct acpi_walk_state *walk_state) +{ + acpi_status status; + union acpi_operand_object *new_desc; + + ACPI_FUNCTION_TRACE(ex_store_direct_to_node); + + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "Storing [%s] (%p) directly into node [%s] (%p)" + " with no implicit conversion\n", + acpi_ut_get_object_type_name(source_desc), + source_desc, acpi_ut_get_type_name(node->type), + node)); + + /* Copy the source object to a new object */ + + status = + acpi_ut_copy_iobject_to_iobject(source_desc, &new_desc, walk_state); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); } + /* Attach the new object to the node */ + + status = acpi_ns_attach_object(node, new_desc, new_desc->common.type); + acpi_ut_remove_reference(new_desc); return_ACPI_STATUS(status); } diff --git a/drivers/block/brd.c b/drivers/block/brd.c index 4e8213aa02f..a7d70e2a8d7 100644 --- a/drivers/block/brd.c +++ b/drivers/block/brd.c @@ -546,7 +546,7 @@ static struct kobject *brd_probe(dev_t dev, int *part, void *data) mutex_lock(&brd_devices_mutex); brd = brd_init_one(MINOR(dev) >> part_shift); - kobj = brd ? get_disk(brd->brd_disk) : ERR_PTR(-ENOMEM); + kobj = brd ? get_disk(brd->brd_disk) : NULL; mutex_unlock(&brd_devices_mutex); *part = 0; diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 179b5b408cb..a4ddbae2e10 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -1743,7 +1743,7 @@ static struct kobject *loop_probe(dev_t dev, int *part, void *data) if (err < 0) err = loop_add(&lo, MINOR(dev) >> part_shift); if (err < 0) - kobj = ERR_PTR(err); + kobj = NULL; else kobj = get_disk(lo->lo_disk); mutex_unlock(&loop_index_mutex); diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c index 22b14a68e35..1f4f94103c5 100644 --- a/drivers/hwmon/lm90.c +++ b/drivers/hwmon/lm90.c @@ -278,7 +278,7 @@ static const struct lm90_params lm90_params[] = { [max6696] = { .flags = LM90_HAVE_EMERGENCY | LM90_HAVE_EMERGENCY_ALARM | LM90_HAVE_TEMP3, - .alert_alarms = 0x187c, + .alert_alarms = 0x1c7c, .max_convrate = 6, .reg_local_ext = MAX6657_REG_R_LOCAL_TEMPL, }, @@ -1504,19 +1504,22 @@ static void lm90_alert(struct i2c_client *client, unsigned int flag) if ((alarms & 0x7f) == 0 && (alarms2 & 0xfe) == 0) { dev_info(&client->dev, "Everything OK\n"); } else { - if (alarms & 0x61) + if ((alarms & 0x61) || (alarms2 & 0x80)) dev_warn(&client->dev, "temp%d out of range, please check!\n", 1); - if (alarms & 0x1a) + if ((alarms & 0x1a) || (alarms2 & 0x20)) dev_warn(&client->dev, "temp%d out of range, please check!\n", 2); if (alarms & 0x04) dev_warn(&client->dev, "temp%d diode open, please check!\n", 2); - if (alarms2 & 0x18) + if (alarms2 & 0x5a) dev_warn(&client->dev, "temp%d out of range, please check!\n", 3); + if (alarms2 & 0x04) + dev_warn(&client->dev, + "temp%d diode open, please check!\n", 3); /* * Disable ALERT# output, because these chips don't implement diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c index 21a3d77ea7e..77405b4e863 100644 --- a/drivers/net/can/c_can/c_can.c +++ b/drivers/net/can/c_can/c_can.c @@ -760,9 +760,6 @@ static int c_can_do_rx_poll(struct net_device *dev, int quota) msg_ctrl_save = priv->read_reg(priv, &priv->regs->ifregs[0].msg_cntrl); - if (msg_ctrl_save & IF_MCONT_EOB) - return num_rx_pkts; - if (msg_ctrl_save & IF_MCONT_MSGLST) { c_can_handle_lost_msg_obj(dev, 0, msg_obj); num_rx_pkts++; @@ -770,6 +767,9 @@ static int c_can_do_rx_poll(struct net_device *dev, int quota) continue; } + if (msg_ctrl_save & IF_MCONT_EOB) + return num_rx_pkts; + if (!(msg_ctrl_save & IF_MCONT_NEWDAT)) continue; diff --git a/drivers/net/ethernet/realtek/8139cp.c b/drivers/net/ethernet/realtek/8139cp.c index 1b4404725b8..effb3b71ce7 100644 --- a/drivers/net/ethernet/realtek/8139cp.c +++ b/drivers/net/ethernet/realtek/8139cp.c @@ -1232,6 +1232,7 @@ static void cp_tx_timeout(struct net_device *dev) cp_clean_rings(cp); rc = cp_init_rings(cp); cp_start_hw(cp); + cp_enable_irq(cp); netif_wake_queue(dev); diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c index a06cc283e23..0b48430d6ad 100644 --- a/drivers/net/wireless/libertas/debugfs.c +++ b/drivers/net/wireless/libertas/debugfs.c @@ -913,7 +913,10 @@ static ssize_t lbs_debugfs_write(struct file *f, const char __user *buf, char *p2; struct debug_data *d = f->private_data; - pdata = kmalloc(cnt, GFP_KERNEL); + if (cnt == 0) + return 0; + + pdata = kmalloc(cnt + 1, GFP_KERNEL); if (pdata == NULL) return 0; @@ -922,6 +925,7 @@ static ssize_t lbs_debugfs_write(struct file *f, const char __user *buf, kfree(pdata); return 0; } + pdata[cnt] = '\0'; p0 = pdata; for (i = 0; i < num_of_items; i++) { diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 65cb4250259..6eec862fea2 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -143,6 +143,8 @@ static bool rt2800usb_txstatus_timeout(struct rt2x00_dev *rt2x00dev) return false; } +#define TXSTATUS_READ_INTERVAL 1000000 + static bool rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev, int urb_status, u32 tx_status) { @@ -170,8 +172,9 @@ static bool rt2800usb_tx_sta_fifo_read_completed(struct rt2x00_dev *rt2x00dev, queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work); if (rt2800usb_txstatus_pending(rt2x00dev)) { - /* Read register after 250 us */ - hrtimer_start(&rt2x00dev->txstatus_timer, ktime_set(0, 250000), + /* Read register after 1 ms */ + hrtimer_start(&rt2x00dev->txstatus_timer, + ktime_set(0, TXSTATUS_READ_INTERVAL), HRTIMER_MODE_REL); return false; } @@ -196,8 +199,9 @@ static void rt2800usb_async_read_tx_status(struct rt2x00_dev *rt2x00dev) if (test_and_set_bit(TX_STATUS_READING, &rt2x00dev->flags)) return; - /* Read TX_STA_FIFO register after 500 us */ - hrtimer_start(&rt2x00dev->txstatus_timer, ktime_set(0, 500000), + /* Read TX_STA_FIFO register after 2 ms */ + hrtimer_start(&rt2x00dev->txstatus_timer, + ktime_set(0, 2*TXSTATUS_READ_INTERVAL), HRTIMER_MODE_REL); } diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index a8885f06006..6701f2d7127 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c @@ -771,6 +771,9 @@ void rt2x00mac_flush(struct ieee80211_hw *hw, bool drop) struct rt2x00_dev *rt2x00dev = hw->priv; struct data_queue *queue; + if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) + return; + tx_queue_for_each(rt2x00dev, queue) rt2x00queue_flush_queue(queue, drop); } diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c index 0bd38da4ada..05fbc3ded9b 100644 --- a/drivers/scsi/aacraid/commctrl.c +++ b/drivers/scsi/aacraid/commctrl.c @@ -508,7 +508,8 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg) goto cleanup; } - if (fibsize > (dev->max_fib_size - sizeof(struct aac_fibhdr))) { + if ((fibsize < (sizeof(struct user_aac_srb) - sizeof(struct user_sgentry))) || + (fibsize > (dev->max_fib_size - sizeof(struct aac_fibhdr)))) { rcode = -EINVAL; goto cleanup; } diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c index a783d533a1a..71507529183 100644 --- a/drivers/uio/uio.c +++ b/drivers/uio/uio.c @@ -650,16 +650,30 @@ static int uio_mmap_physical(struct vm_area_struct *vma) { struct uio_device *idev = vma->vm_private_data; int mi = uio_find_mem_index(vma); + struct uio_mem *mem; if (mi < 0) return -EINVAL; + mem = idev->info->mem + mi; + + if (vma->vm_end - vma->vm_start > mem->size) + return -EINVAL; vma->vm_flags |= VM_IO | VM_RESERVED; vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); + /* + * We cannot use the vm_iomap_memory() helper here, + * because vma->vm_pgoff is the map index we looked + * up above in uio_find_mem_index(), rather than an + * actual page offset into the mmap. + * + * So we just do the physical mmap without a page + * offset. + */ return remap_pfn_range(vma, vma->vm_start, - idev->info->mem[mi].addr >> PAGE_SHIFT, + mem->addr >> PAGE_SHIFT, vma->vm_end - vma->vm_start, vma->vm_page_prot); } diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index c8542356898..91293b68df5 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -1664,7 +1664,11 @@ static int mos7840_tiocmget(struct tty_struct *tty) return -ENODEV; status = mos7840_get_uart_reg(port, MODEM_STATUS_REGISTER, &msr); + if (status != 1) + return -EIO; status = mos7840_get_uart_reg(port, MODEM_CONTROL_REGISTER, &mcr); + if (status != 1) + return -EIO; result = ((mcr & MCR_DTR) ? TIOCM_DTR : 0) | ((mcr & MCR_RTS) ? TIOCM_RTS : 0) | ((mcr & MCR_LOOPBACK) ? TIOCM_LOOP : 0) diff --git a/drivers/video/au1100fb.c b/drivers/video/au1100fb.c index ffbce452546..612c1c7cb31 100644 --- a/drivers/video/au1100fb.c +++ b/drivers/video/au1100fb.c @@ -375,39 +375,15 @@ void au1100fb_fb_rotate(struct fb_info *fbi, int angle) int au1100fb_fb_mmap(struct fb_info *fbi, struct vm_area_struct *vma) { struct au1100fb_device *fbdev; - unsigned int len; - unsigned long start=0, off; fbdev = to_au1100fb_device(fbi); - if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) { - return -EINVAL; - } - - start = fbdev->fb_phys & PAGE_MASK; - len = PAGE_ALIGN((start & ~PAGE_MASK) + fbdev->fb_len); - - off = vma->vm_pgoff << PAGE_SHIFT; - - if ((vma->vm_end - vma->vm_start + off) > len) { - return -EINVAL; - } - - off += start; - vma->vm_pgoff = off >> PAGE_SHIFT; - vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); pgprot_val(vma->vm_page_prot) |= (6 << 9); //CCA=6 vma->vm_flags |= VM_IO; - if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, - vma->vm_end - vma->vm_start, - vma->vm_page_prot)) { - return -EAGAIN; - } - - return 0; + return vm_iomap_memory(vma, fbdev->fb_phys, fbdev->fb_len); } static struct fb_ops au1100fb_ops = diff --git a/drivers/video/au1200fb.c b/drivers/video/au1200fb.c index 7ca79f02056..117be3d9b85 100644 --- a/drivers/video/au1200fb.c +++ b/drivers/video/au1200fb.c @@ -1233,36 +1233,15 @@ static int au1200fb_fb_blank(int blank_mode, struct fb_info *fbi) * method mainly to allow the use of the TLB streaming flag (CCA=6) */ static int au1200fb_fb_mmap(struct fb_info *info, struct vm_area_struct *vma) - { - unsigned int len; - unsigned long start=0, off; struct au1200fb_device *fbdev = info->par; - if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) { - return -EINVAL; - } - - start = fbdev->fb_phys & PAGE_MASK; - len = PAGE_ALIGN((start & ~PAGE_MASK) + fbdev->fb_len); - - off = vma->vm_pgoff << PAGE_SHIFT; - - if ((vma->vm_end - vma->vm_start + off) > len) { - return -EINVAL; - } - - off += start; - vma->vm_pgoff = off >> PAGE_SHIFT; - vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); pgprot_val(vma->vm_page_prot) |= _CACHE_MASK; /* CCA=7 */ vma->vm_flags |= VM_IO; - return io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT, - vma->vm_end - vma->vm_start, - vma->vm_page_prot); + return vm_iomap_memory(vma, fbdev->fb_phys, fbdev->fb_len); return 0; } diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c index 7e6c52d8a20..c91f6d1bf64 100644 --- a/fs/configfs/dir.c +++ b/fs/configfs/dir.c @@ -56,10 +56,19 @@ static void configfs_d_iput(struct dentry * dentry, struct configfs_dirent *sd = dentry->d_fsdata; if (sd) { - BUG_ON(sd->s_dentry != dentry); /* Coordinate with configfs_readdir */ spin_lock(&configfs_dirent_lock); - sd->s_dentry = NULL; + /* Coordinate with configfs_attach_attr where will increase + * sd->s_count and update sd->s_dentry to new allocated one. + * Only set sd->dentry to null when this dentry is the only + * sd owner. + * If not do so, configfs_d_iput may run just after + * configfs_attach_attr and set sd->s_dentry to null + * even it's still in use. + */ + if (atomic_read(&sd->s_count) <= 2) + sd->s_dentry = NULL; + spin_unlock(&configfs_dirent_lock); configfs_put(sd); } @@ -426,8 +435,11 @@ static int configfs_attach_attr(struct configfs_dirent * sd, struct dentry * den struct configfs_attribute * attr = sd->s_element; int error; + spin_lock(&configfs_dirent_lock); dentry->d_fsdata = configfs_get(sd); sd->s_dentry = dentry; + spin_unlock(&configfs_dirent_lock); + error = configfs_create(dentry, (attr->ca_mode & S_IALLUGO) | S_IFREG, configfs_init_file); if (error) { diff --git a/fs/dcache.c b/fs/dcache.c index 9d39de40909..09e2eda55c5 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -2513,7 +2513,6 @@ static int prepend_path(const struct path *path, bool slash = false; int error = 0; - br_read_lock(vfsmount_lock); while (dentry != root->dentry || vfsmnt != root->mnt) { struct dentry * parent; @@ -2543,8 +2542,6 @@ static int prepend_path(const struct path *path, if (!error && !slash) error = prepend(buffer, buflen, "/", 1); -out: - br_read_unlock(vfsmount_lock); return error; global_root: @@ -2561,7 +2558,7 @@ static int prepend_path(const struct path *path, error = prepend(buffer, buflen, "/", 1); if (!error) error = real_mount(vfsmnt)->mnt_ns ? 1 : 2; - goto out; + return error; } /** @@ -2588,9 +2585,11 @@ char *__d_path(const struct path *path, int error; prepend(&res, &buflen, "\0", 1); + br_read_lock(vfsmount_lock); write_seqlock(&rename_lock); error = prepend_path(path, root, &res, &buflen); write_sequnlock(&rename_lock); + br_read_unlock(vfsmount_lock); if (error < 0) return ERR_PTR(error); @@ -2607,9 +2606,11 @@ char *d_absolute_path(const struct path *path, int error; prepend(&res, &buflen, "\0", 1); + br_read_lock(vfsmount_lock); write_seqlock(&rename_lock); error = prepend_path(path, &root, &res, &buflen); write_sequnlock(&rename_lock); + br_read_unlock(vfsmount_lock); if (error > 1) error = -EINVAL; @@ -2673,11 +2674,13 @@ char *d_path(const struct path *path, char *buf, int buflen) return path->dentry->d_op->d_dname(path->dentry, buf, buflen); get_fs_root(current->fs, &root); + br_read_lock(vfsmount_lock); write_seqlock(&rename_lock); error = path_with_deleted(path, &root, &res, &buflen); + write_sequnlock(&rename_lock); + br_read_unlock(vfsmount_lock); if (error < 0) res = ERR_PTR(error); - write_sequnlock(&rename_lock); path_put(&root); return res; } @@ -2832,6 +2835,7 @@ SYSCALL_DEFINE2(getcwd, char __user *, buf, unsigned long, size) get_fs_root_and_pwd(current->fs, &root, &pwd); error = -ENOENT; + br_read_lock(vfsmount_lock); write_seqlock(&rename_lock); if (!d_unlinked(pwd.dentry)) { unsigned long len; @@ -2841,6 +2845,7 @@ SYSCALL_DEFINE2(getcwd, char __user *, buf, unsigned long, size) prepend(&cwd, &buflen, "\0", 1); error = prepend_path(&pwd, &root, &cwd, &buflen); write_sequnlock(&rename_lock); + br_read_unlock(vfsmount_lock); if (error < 0) goto out; @@ -2861,6 +2866,7 @@ SYSCALL_DEFINE2(getcwd, char __user *, buf, unsigned long, size) } } else { write_sequnlock(&rename_lock); + br_read_unlock(vfsmount_lock); } out: diff --git a/fs/exec.c b/fs/exec.c index 0ea0b4c476d..5b9dfbe84b1 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -909,11 +909,13 @@ static int de_thread(struct task_struct *tsk) sig->notify_count = -1; /* for exit_notify() */ for (;;) { + threadgroup_change_begin(tsk); write_lock_irq(&tasklist_lock); if (likely(leader->exit_state)) break; __set_current_state(TASK_UNINTERRUPTIBLE); write_unlock_irq(&tasklist_lock); + threadgroup_change_end(tsk); schedule(); } @@ -969,6 +971,7 @@ static int de_thread(struct task_struct *tsk) if (unlikely(leader->ptrace)) __wake_up_parent(leader, leader->parent); write_unlock_irq(&tasklist_lock); + threadgroup_change_end(tsk); release_task(leader); } @@ -2024,6 +2027,12 @@ static int __get_dumpable(unsigned long mm_flags) return (ret >= 2) ? 2 : ret; } +/* + * This returns the actual value of the suid_dumpable flag. For things + * that are using this for checking for privilege transitions, it must + * test against SUID_DUMP_USER rather than treating it as a boolean + * value. + */ int get_dumpable(struct mm_struct *mm) { return __get_dumpable(mm->flags); diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index a55d0c8a3fd..2faed2f3876 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -224,6 +224,8 @@ nfs_find_actor(struct inode *inode, void *opaque) if (NFS_FILEID(inode) != fattr->fileid) return 0; + if ((S_IFMT & inode->i_mode) != (S_IFMT & fattr->mode)) + return 0; if (nfs_compare_fh(NFS_FH(inode), fh)) return 0; if (is_bad_inode(inode) || NFS_STALE(inode)) diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index 7374c77aba1..5e652f4143e 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c @@ -24,14 +24,14 @@ #define NFSDBG_FACILITY NFSDBG_PROC -/* A wrapper to handle the EJUKEBOX and EKEYEXPIRED error messages */ +/* A wrapper to handle the EJUKEBOX error messages */ static int nfs3_rpc_wrapper(struct rpc_clnt *clnt, struct rpc_message *msg, int flags) { int res; do { res = rpc_call_sync(clnt, msg, flags); - if (res != -EJUKEBOX && res != -EKEYEXPIRED) + if (res != -EJUKEBOX) break; freezable_schedule_timeout_killable_unsafe(NFS_JUKEBOX_RETRY_TIME); res = -ERESTARTSYS; @@ -44,7 +44,7 @@ nfs3_rpc_wrapper(struct rpc_clnt *clnt, struct rpc_message *msg, int flags) static int nfs3_async_handle_jukebox(struct rpc_task *task, struct inode *inode) { - if (task->tk_status != -EJUKEBOX && task->tk_status != -EKEYEXPIRED) + if (task->tk_status != -EJUKEBOX) return 0; if (task->tk_status == -EJUKEBOX) nfs_inc_stats(inode, NFSIOS_DELAY); diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c index 5acfd9ea8a3..4d64d5b85e5 100644 --- a/fs/nfs/nfs4filelayout.c +++ b/fs/nfs/nfs4filelayout.c @@ -122,7 +122,6 @@ static int filelayout_async_handle_error(struct rpc_task *task, break; case -NFS4ERR_DELAY: case -NFS4ERR_GRACE: - case -EKEYEXPIRED: rpc_delay(task, FILELAYOUT_POLL_RETRY_MAX); break; case -NFS4ERR_RETRY_UNCACHED_REP: diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 7c97bd89df3..c1b6b911016 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -319,7 +319,6 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc } case -NFS4ERR_GRACE: case -NFS4ERR_DELAY: - case -EKEYEXPIRED: ret = nfs4_delay(server->client, &exception->timeout); if (ret != 0) break; @@ -1352,13 +1351,6 @@ int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state nfs_inode_find_state_and_recover(state->inode, stateid); nfs4_schedule_stateid_recovery(server, state); - case -EKEYEXPIRED: - /* - * User RPCSEC_GSS context has expired. - * We cannot recover this stateid now, so - * skip it and allow recovery thread to - * proceed. - */ case -ENOMEM: err = 0; goto out; @@ -3924,7 +3916,6 @@ nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, case -NFS4ERR_DELAY: nfs_inc_server_stats(server, NFSIOS_DELAY); case -NFS4ERR_GRACE: - case -EKEYEXPIRED: rpc_delay(task, NFS4_POLL_RETRY_MAX); task->tk_status = 0; return -EAGAIN; @@ -4216,6 +4207,7 @@ static int _nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock status = 0; } request->fl_ops->fl_release_private(request); + request->fl_ops = NULL; out: return status; } @@ -4871,15 +4863,6 @@ int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl) nfs4_schedule_stateid_recovery(server, state); err = 0; goto out; - case -EKEYEXPIRED: - /* - * User RPCSEC_GSS context has expired. - * We cannot recover this stateid now, so - * skip it and allow recovery thread to - * proceed. - */ - err = 0; - goto out; case -ENOMEM: case -NFS4ERR_DENIED: /* kill_proc(fl->fl_pid, SIGLOST, 1); */ diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 7f0fcfc1fe9..e46579471cc 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c @@ -1298,14 +1298,6 @@ static int nfs4_reclaim_open_state(struct nfs4_state_owner *sp, const struct nfs /* Mark the file as being 'closed' */ state->state = 0; break; - case -EKEYEXPIRED: - /* - * User RPCSEC_GSS context has expired. - * We cannot recover this stateid now, so - * skip it and allow recovery thread to - * proceed. - */ - break; case -NFS4ERR_ADMIN_REVOKED: case -NFS4ERR_STALE_STATEID: case -NFS4ERR_BAD_STATEID: @@ -1458,14 +1450,6 @@ static void nfs4_state_start_reclaim_nograce(struct nfs_client *clp) nfs4_state_mark_reclaim_helper(clp, nfs4_state_mark_reclaim_nograce); } -static void nfs4_warn_keyexpired(const char *s) -{ - printk_ratelimited(KERN_WARNING "Error: state manager" - " encountered RPCSEC_GSS session" - " expired against NFSv4 server %s.\n", - s); -} - static int nfs4_recovery_handle_error(struct nfs_client *clp, int error) { switch (error) { @@ -1497,10 +1481,6 @@ static int nfs4_recovery_handle_error(struct nfs_client *clp, int error) set_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state); /* Zero session reset errors */ break; - case -EKEYEXPIRED: - /* Nothing we can do */ - nfs4_warn_keyexpired(clp->cl_hostname); - break; default: return error; } @@ -1745,7 +1725,6 @@ static void nfs4_set_lease_expired(struct nfs_client *clp, int status) break; case -EKEYEXPIRED: - nfs4_warn_keyexpired(clp->cl_hostname); case -NFS4ERR_NOT_SAME: /* FixMe: implement recovery * in nfs4_exchange_id */ default: diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c index b63b6f4d14f..af9947e35fc 100644 --- a/fs/nfs/proc.c +++ b/fs/nfs/proc.c @@ -46,39 +46,6 @@ #define NFSDBG_FACILITY NFSDBG_PROC -/* - * wrapper to handle the -EKEYEXPIRED error message. This should generally - * only happen if using krb5 auth and a user's TGT expires. NFSv2 doesn't - * support the NFSERR_JUKEBOX error code, but we handle this situation in the - * same way that we handle that error with NFSv3. - */ -static int -nfs_rpc_wrapper(struct rpc_clnt *clnt, struct rpc_message *msg, int flags) -{ - int res; - do { - res = rpc_call_sync(clnt, msg, flags); - if (res != -EKEYEXPIRED) - break; - freezable_schedule_timeout_killable(NFS_JUKEBOX_RETRY_TIME); - res = -ERESTARTSYS; - } while (!fatal_signal_pending(current)); - return res; -} - -#define rpc_call_sync(clnt, msg, flags) nfs_rpc_wrapper(clnt, msg, flags) - -static int -nfs_async_handle_expired_key(struct rpc_task *task) -{ - if (task->tk_status != -EKEYEXPIRED) - return 0; - task->tk_status = 0; - rpc_restart_call(task); - rpc_delay(task, NFS_JUKEBOX_RETRY_TIME); - return 1; -} - /* * Bare-bones access to getattr: this is for nfs_read_super. */ @@ -365,8 +332,6 @@ static void nfs_proc_unlink_rpc_prepare(struct rpc_task *task, struct nfs_unlink static int nfs_proc_unlink_done(struct rpc_task *task, struct inode *dir) { - if (nfs_async_handle_expired_key(task)) - return 0; nfs_mark_for_revalidate(dir); return 1; } @@ -386,8 +351,6 @@ static int nfs_proc_rename_done(struct rpc_task *task, struct inode *old_dir, struct inode *new_dir) { - if (nfs_async_handle_expired_key(task)) - return 0; nfs_mark_for_revalidate(old_dir); nfs_mark_for_revalidate(new_dir); return 1; @@ -641,9 +604,6 @@ nfs_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle, static int nfs_read_done(struct rpc_task *task, struct nfs_read_data *data) { - if (nfs_async_handle_expired_key(task)) - return -EAGAIN; - nfs_invalidate_atime(data->inode); if (task->tk_status >= 0) { nfs_refresh_inode(data->inode, data->res.fattr); @@ -668,9 +628,6 @@ static void nfs_proc_read_rpc_prepare(struct rpc_task *task, struct nfs_read_dat static int nfs_write_done(struct rpc_task *task, struct nfs_write_data *data) { - if (nfs_async_handle_expired_key(task)) - return -EAGAIN; - if (task->tk_status >= 0) nfs_post_op_update_inode_force_wcc(data->inode, data->res.fattr); return 0; diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index f03160106b9..026a873e3f6 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -297,41 +297,12 @@ commit_metadata(struct svc_fh *fhp) } /* - * Set various file attributes. - * N.B. After this call fhp needs an fh_put + * Go over the attributes and take care of the small differences between + * NFS semantics and what Linux expects. */ -__be32 -nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap, - int check_guard, time_t guardtime) +static void +nfsd_sanitize_attrs(struct inode *inode, struct iattr *iap) { - struct dentry *dentry; - struct inode *inode; - int accmode = NFSD_MAY_SATTR; - umode_t ftype = 0; - __be32 err; - int host_err; - int size_change = 0; - - if (iap->ia_valid & (ATTR_ATIME | ATTR_MTIME | ATTR_SIZE)) - accmode |= NFSD_MAY_WRITE|NFSD_MAY_OWNER_OVERRIDE; - if (iap->ia_valid & ATTR_SIZE) - ftype = S_IFREG; - - /* Get inode */ - err = fh_verify(rqstp, fhp, ftype, accmode); - if (err) - goto out; - - dentry = fhp->fh_dentry; - inode = dentry->d_inode; - - /* Ignore any mode updates on symlinks */ - if (S_ISLNK(inode->i_mode)) - iap->ia_valid &= ~ATTR_MODE; - - if (!iap->ia_valid) - goto out; - /* * NFSv2 does not differentiate between "set-[ac]time-to-now" * which only requires access, and "set-[ac]time-to-X" which @@ -341,8 +312,7 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap, * convert to "set to now" instead of "set to explicit time" * * We only call inode_change_ok as the last test as technically - * it is not an interface that we should be using. It is only - * valid if the filesystem does not define it's own i_op->setattr. + * it is not an interface that we should be using. */ #define BOTH_TIME_SET (ATTR_ATIME_SET | ATTR_MTIME_SET) #define MAX_TOUCH_TIME_ERROR (30*60) @@ -368,30 +338,6 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap, iap->ia_valid &= ~BOTH_TIME_SET; } } - - /* - * The size case is special. - * It changes the file as well as the attributes. - */ - if (iap->ia_valid & ATTR_SIZE) { - if (iap->ia_size < inode->i_size) { - err = nfsd_permission(rqstp, fhp->fh_export, dentry, - NFSD_MAY_TRUNC|NFSD_MAY_OWNER_OVERRIDE); - if (err) - goto out; - } - - host_err = get_write_access(inode); - if (host_err) - goto out_nfserr; - - size_change = 1; - host_err = locks_verify_truncate(inode, NULL, iap->ia_size); - if (host_err) { - put_write_access(inode); - goto out_nfserr; - } - } /* sanitize the mode change */ if (iap->ia_valid & ATTR_MODE) { @@ -414,32 +360,111 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap, iap->ia_valid |= (ATTR_KILL_SUID | ATTR_KILL_SGID); } } +} - /* Change the attributes. */ +static __be32 +nfsd_get_write_access(struct svc_rqst *rqstp, struct svc_fh *fhp, + struct iattr *iap) +{ + struct inode *inode = fhp->fh_dentry->d_inode; + int host_err; - iap->ia_valid |= ATTR_CTIME; + if (iap->ia_size < inode->i_size) { + __be32 err; - err = nfserr_notsync; - if (!check_guard || guardtime == inode->i_ctime.tv_sec) { - host_err = nfsd_break_lease(inode); - if (host_err) - goto out_nfserr; - fh_lock(fhp); + err = nfsd_permission(rqstp, fhp->fh_export, fhp->fh_dentry, + NFSD_MAY_TRUNC | NFSD_MAY_OWNER_OVERRIDE); + if (err) + return err; + } - host_err = notify_change(dentry, iap); - err = nfserrno(host_err); - fh_unlock(fhp); + host_err = get_write_access(inode); + if (host_err) + goto out_nfserrno; + + host_err = locks_verify_truncate(inode, NULL, iap->ia_size); + if (host_err) + goto out_put_write_access; + return 0; + +out_put_write_access: + put_write_access(inode); +out_nfserrno: + return nfserrno(host_err); +} + +/* + * Set various file attributes. After this call fhp needs an fh_put. + */ +__be32 +nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap, + int check_guard, time_t guardtime) +{ + struct dentry *dentry; + struct inode *inode; + int accmode = NFSD_MAY_SATTR; + umode_t ftype = 0; + __be32 err; + int host_err; + int size_change = 0; + + if (iap->ia_valid & (ATTR_ATIME | ATTR_MTIME | ATTR_SIZE)) + accmode |= NFSD_MAY_WRITE|NFSD_MAY_OWNER_OVERRIDE; + if (iap->ia_valid & ATTR_SIZE) + ftype = S_IFREG; + + /* Get inode */ + err = fh_verify(rqstp, fhp, ftype, accmode); + if (err) + goto out; + + dentry = fhp->fh_dentry; + inode = dentry->d_inode; + + /* Ignore any mode updates on symlinks */ + if (S_ISLNK(inode->i_mode)) + iap->ia_valid &= ~ATTR_MODE; + + if (!iap->ia_valid) + goto out; + + nfsd_sanitize_attrs(inode, iap); + + /* + * The size case is special, it changes the file in addition to the + * attributes. + */ + if (iap->ia_valid & ATTR_SIZE) { + err = nfsd_get_write_access(rqstp, fhp, iap); + if (err) + goto out; + size_change = 1; } + + iap->ia_valid |= ATTR_CTIME; + + if (check_guard && guardtime != inode->i_ctime.tv_sec) { + err = nfserr_notsync; + goto out_put_write_access; + } + + host_err = nfsd_break_lease(inode); + if (host_err) + goto out_put_write_access_nfserror; + + fh_lock(fhp); + host_err = notify_change(dentry, iap); + fh_unlock(fhp); + +out_put_write_access_nfserror: + err = nfserrno(host_err); +out_put_write_access: if (size_change) put_write_access(inode); if (!err) commit_metadata(fhp); out: return err; - -out_nfserr: - err = nfserrno(host_err); - goto out; } #if defined(CONFIG_NFSD_V2_ACL) || \ diff --git a/fs/proc/inode.c b/fs/proc/inode.c index 205c9228083..6c61f119f60 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c @@ -443,12 +443,10 @@ static const struct file_operations proc_reg_file_ops_no_compat = { struct inode *proc_get_inode(struct super_block *sb, struct proc_dir_entry *de) { - struct inode * inode; + struct inode *inode = new_inode_pseudo(sb); - inode = iget_locked(sb, de->low_ino); - if (!inode) - return NULL; - if (inode->i_state & I_NEW) { + if (inode) { + inode->i_ino = de->low_ino; inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; PROC_I(inode)->fd = 0; PROC_I(inode)->pde = de; @@ -477,9 +475,7 @@ struct inode *proc_get_inode(struct super_block *sb, struct proc_dir_entry *de) inode->i_fop = de->proc_fops; } } - unlock_new_inode(inode); - } else - pde_put(de); + } return inode; } diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h index 5bab59b1034..424b381c96f 100644 --- a/include/linux/binfmts.h +++ b/include/linux/binfmts.h @@ -113,9 +113,6 @@ extern void setup_new_exec(struct linux_binprm * bprm); extern void would_dump(struct linux_binprm *, struct file *); extern int suid_dumpable; -#define SUID_DUMP_DISABLE 0 /* No setuid dumping */ -#define SUID_DUMP_USER 1 /* Dump as user of process */ -#define SUID_DUMP_ROOT 2 /* Dump as root */ /* Stack area protections */ #define EXSTACK_DEFAULT 0 /* Whatever the arch defaults to */ diff --git a/include/linux/fs.h b/include/linux/fs.h index 2e787eb7d1d..71deeb3780a 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -916,9 +916,11 @@ static inline loff_t i_size_read(const struct inode *inode) static inline void i_size_write(struct inode *inode, loff_t i_size) { #if BITS_PER_LONG==32 && defined(CONFIG_SMP) + preempt_disable(); write_seqcount_begin(&inode->i_size_seqcount); inode->i_size = i_size; write_seqcount_end(&inode->i_size_seqcount); + preempt_enable(); #elif BITS_PER_LONG==32 && defined(CONFIG_PREEMPT) preempt_disable(); inode->i_size = i_size; diff --git a/include/linux/sched.h b/include/linux/sched.h index e449798ae63..a12fbf42aa0 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -408,6 +408,10 @@ static inline void arch_pick_mmap_layout(struct mm_struct *mm) {} extern void set_dumpable(struct mm_struct *mm, int value); extern int get_dumpable(struct mm_struct *mm); +#define SUID_DUMP_DISABLE 0 /* No setuid dumping */ +#define SUID_DUMP_USER 1 /* Dump as user of process */ +#define SUID_DUMP_ROOT 2 /* Dump as root */ + /* mm flags */ /* dumpable bits */ #define MMF_DUMPABLE 0 /* core dump is permitted */ @@ -2476,27 +2480,18 @@ static inline void threadgroup_change_end(struct task_struct *tsk) * * Lock the threadgroup @tsk belongs to. No new task is allowed to enter * and member tasks aren't allowed to exit (as indicated by PF_EXITING) or - * perform exec. This is useful for cases where the threadgroup needs to - * stay stable across blockable operations. + * change ->group_leader/pid. This is useful for cases where the threadgroup + * needs to stay stable across blockable operations. * * fork and exit paths explicitly call threadgroup_change_{begin|end}() for * synchronization. While held, no new task will be added to threadgroup * and no existing live task will have its PF_EXITING set. * - * During exec, a task goes and puts its thread group through unusual - * changes. After de-threading, exclusive access is assumed to resources - * which are usually shared by tasks in the same group - e.g. sighand may - * be replaced with a new one. Also, the exec'ing task takes over group - * leader role including its pid. Exclude these changes while locked by - * grabbing cred_guard_mutex which is used to synchronize exec path. + * de_thread() does threadgroup_change_{begin|end}() when a non-leader + * sub-thread becomes a new leader. */ static inline void threadgroup_lock(struct task_struct *tsk) { - /* - * exec uses exit for de-threading nesting group_rwsem inside - * cred_guard_mutex. Grab cred_guard_mutex first. - */ - mutex_lock(&tsk->signal->cred_guard_mutex); down_write(&tsk->signal->group_rwsem); } @@ -2509,7 +2504,6 @@ static inline void threadgroup_lock(struct task_struct *tsk) static inline void threadgroup_unlock(struct task_struct *tsk) { up_write(&tsk->signal->group_rwsem); - mutex_unlock(&tsk->signal->cred_guard_mutex); } #else static inline void threadgroup_change_begin(struct task_struct *tsk) {} diff --git a/kernel/ptrace.c b/kernel/ptrace.c index daf4394d1ab..a1432369be5 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -254,7 +254,8 @@ int __ptrace_may_access(struct task_struct *task, unsigned int mode) smp_rmb(); if (task->mm) dumpable = get_dumpable(task->mm); - if (!dumpable && !ptrace_has_cap(task_user_ns(task), mode)) + if (dumpable != SUID_DUMP_USER && + !ptrace_has_cap(task_user_ns(task), mode)) return -EPERM; return security_ptrace_access_check(task, mode); diff --git a/kernel/trace/trace_event_perf.c b/kernel/trace/trace_event_perf.c index fee3752ae8f..d01adb77449 100644 --- a/kernel/trace/trace_event_perf.c +++ b/kernel/trace/trace_event_perf.c @@ -26,7 +26,7 @@ static int perf_trace_event_perm(struct ftrace_event_call *tp_event, { /* The ftrace function trace is allowed only for root. */ if (ftrace_event_is_function(tp_event) && - perf_paranoid_kernel() && !capable(CAP_SYS_ADMIN)) + perf_paranoid_tracepoint_raw() && !capable(CAP_SYS_ADMIN)) return -EPERM; /* No tracing, just counting, so no obvious leak */ diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index a28a2111297..f21486a2ac4 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c @@ -1338,6 +1338,7 @@ call_refreshresult(struct rpc_task *task) rpc_delay(task, 3*HZ); case -EAGAIN: status = -EACCES; + case -EKEYEXPIRED: if (!task->tk_cred_retry) break; task->tk_cred_retry--; diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 79064471cd0..31f981d700a 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -390,8 +390,10 @@ static int xs_send_kvec(struct socket *sock, struct sockaddr *addr, int addrlen, return kernel_sendmsg(sock, &msg, NULL, 0, 0); } -static int xs_send_pagedata(struct socket *sock, struct xdr_buf *xdr, unsigned int base, int more) +static int xs_send_pagedata(struct socket *sock, struct xdr_buf *xdr, unsigned int base, int more, bool zerocopy) { + ssize_t (*do_sendpage)(struct socket *sock, struct page *page, + int offset, size_t size, int flags); struct page **ppage; unsigned int remainder; int err, sent = 0; @@ -400,6 +402,9 @@ static int xs_send_pagedata(struct socket *sock, struct xdr_buf *xdr, unsigned i base += xdr->page_base; ppage = xdr->pages + (base >> PAGE_SHIFT); base &= ~PAGE_MASK; + do_sendpage = sock->ops->sendpage; + if (!zerocopy) + do_sendpage = sock_no_sendpage; for(;;) { unsigned int len = min_t(unsigned int, PAGE_SIZE - base, remainder); int flags = XS_SENDMSG_FLAGS; @@ -407,7 +412,7 @@ static int xs_send_pagedata(struct socket *sock, struct xdr_buf *xdr, unsigned i remainder -= len; if (remainder != 0 || more) flags |= MSG_MORE; - err = sock->ops->sendpage(sock, *ppage, base, len, flags); + err = do_sendpage(sock, *ppage, base, len, flags); if (remainder == 0 || err != len) break; sent += err; @@ -428,9 +433,10 @@ static int xs_send_pagedata(struct socket *sock, struct xdr_buf *xdr, unsigned i * @addrlen: UDP only -- length of destination address * @xdr: buffer containing this request * @base: starting position in the buffer + * @zerocopy: true if it is safe to use sendpage() * */ -static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen, struct xdr_buf *xdr, unsigned int base) +static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen, struct xdr_buf *xdr, unsigned int base, bool zerocopy) { unsigned int remainder = xdr->len - base; int err, sent = 0; @@ -458,7 +464,7 @@ static int xs_sendpages(struct socket *sock, struct sockaddr *addr, int addrlen, if (base < xdr->page_len) { unsigned int len = xdr->page_len - base; remainder -= len; - err = xs_send_pagedata(sock, xdr, base, remainder != 0); + err = xs_send_pagedata(sock, xdr, base, remainder != 0, zerocopy); if (remainder == 0 || err != len) goto out; sent += err; @@ -561,7 +567,7 @@ static int xs_local_send_request(struct rpc_task *task) req->rq_svec->iov_base, req->rq_svec->iov_len); status = xs_sendpages(transport->sock, NULL, 0, - xdr, req->rq_bytes_sent); + xdr, req->rq_bytes_sent, true); dprintk("RPC: %s(%u) = %d\n", __func__, xdr->len - req->rq_bytes_sent, status); if (likely(status >= 0)) { @@ -617,7 +623,7 @@ static int xs_udp_send_request(struct rpc_task *task) status = xs_sendpages(transport->sock, xs_addr(xprt), xprt->addrlen, xdr, - req->rq_bytes_sent); + req->rq_bytes_sent, true); dprintk("RPC: xs_udp_send_request(%u) = %d\n", xdr->len - req->rq_bytes_sent, status); @@ -688,6 +694,7 @@ static int xs_tcp_send_request(struct rpc_task *task) struct rpc_xprt *xprt = req->rq_xprt; struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); struct xdr_buf *xdr = &req->rq_snd_buf; + bool zerocopy = true; int status; xs_encode_stream_record_marker(&req->rq_snd_buf); @@ -695,13 +702,20 @@ static int xs_tcp_send_request(struct rpc_task *task) xs_pktdump("packet data:", req->rq_svec->iov_base, req->rq_svec->iov_len); + /* Don't use zero copy if this is a resend. If the RPC call + * completes while the socket holds a reference to the pages, + * then we may end up resending corrupted data. + */ + if (task->tk_flags & RPC_TASK_SENT) + zerocopy = false; /* Continue transmitting the packet/record. We must be careful * to cope with writespace callbacks arriving _after_ we have * called sendmsg(). */ while (1) { status = xs_sendpages(transport->sock, - NULL, 0, xdr, req->rq_bytes_sent); + NULL, 0, xdr, req->rq_bytes_sent, + zerocopy); dprintk("RPC: xs_tcp_send_request(%u) = %d\n", xdr->len - req->rq_bytes_sent, status); diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index d8edff209bf..d6aab27c858 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -62,7 +62,6 @@ static struct ima_measure_rule_entry default_rules[] = { {.action = DONT_MEASURE,.fsmagic = SYSFS_MAGIC,.flags = IMA_FSMAGIC}, {.action = DONT_MEASURE,.fsmagic = DEBUGFS_MAGIC,.flags = IMA_FSMAGIC}, {.action = DONT_MEASURE,.fsmagic = TMPFS_MAGIC,.flags = IMA_FSMAGIC}, - {.action = DONT_MEASURE,.fsmagic = RAMFS_MAGIC,.flags = IMA_FSMAGIC}, {.action = DONT_MEASURE,.fsmagic = SECURITYFS_MAGIC,.flags = IMA_FSMAGIC}, {.action = DONT_MEASURE,.fsmagic = SELINUX_MAGIC,.flags = IMA_FSMAGIC}, {.action = MEASURE,.func = FILE_MMAP,.mask = MAY_EXEC, diff --git a/sound/isa/msnd/msnd_pinnacle.c b/sound/isa/msnd/msnd_pinnacle.c index 29cc8e162b0..a7d6a52a4f8 100644 --- a/sound/isa/msnd/msnd_pinnacle.c +++ b/sound/isa/msnd/msnd_pinnacle.c @@ -73,9 +73,11 @@ #ifdef MSND_CLASSIC # include "msnd_classic.h" # define LOGNAME "msnd_classic" +# define DEV_NAME "msnd-classic" #else # include "msnd_pinnacle.h" # define LOGNAME "snd_msnd_pinnacle" +# define DEV_NAME "msnd-pinnacle" #endif static void __devinit set_default_audio_parameters(struct snd_msnd *chip) @@ -1068,8 +1070,6 @@ static int __devexit snd_msnd_isa_remove(struct device *pdev, unsigned int dev) return 0; } -#define DEV_NAME "msnd-pinnacle" - static struct isa_driver snd_msnd_driver = { .match = snd_msnd_isa_match, .probe = snd_msnd_isa_probe, diff --git a/sound/usb/6fire/chip.c b/sound/usb/6fire/chip.c index fc8cc823e43..f8033485db9 100644 --- a/sound/usb/6fire/chip.c +++ b/sound/usb/6fire/chip.c @@ -101,7 +101,7 @@ static int __devinit usb6fire_chip_probe(struct usb_interface *intf, usb_set_intfdata(intf, chips[i]); mutex_unlock(®ister_mutex); return 0; - } else if (regidx < 0) + } else if (!devices[i] && regidx < 0) regidx = i; } if (regidx < 0) { From 87b39de006dbbd3babc23cf84b94595f25466dc3 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 4 Dec 2013 10:50:53 -0800 Subject: [PATCH 145/215] Linux 3.4.72 - 60 commits squashed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ARM: sa11x0/assabet: ensure CS2 is configured appropriately commit f3964fe1c9d9a887d65faf594669852e4dec46e0 upstream. The CS2 region contains the Assabet board configuration and status registers, which are 32-bit. Unfortunately, some boot loaders do not configure this region correctly, leaving it setup as a 16-bit region. Fix this. Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman ARM: integrator_cp: Set LCD{0,1} enable lines when turning on CLCD commit 30aeadd44deea3f3b0df45b9a70ee0fd5f8d6dc2 upstream. This turns on the internal integrator LCD display(s). It seems that the code to do this got lost in refactoring of the CLCD driver. Signed-off-by: Jonathan Austin Acked-by: Linus Walleij Signed-off-by: Olof Johansson Signed-off-by: Greg Kroah-Hartman Staging: tidspbridge: disable driver commit 930ba4a374b96560ef9fde2145cdc454a164ddcc upstream. There seems to be no active maintainer for the driver, and there is an unfixed security bug, so disable the driver for now. Hopefully someone steps up to be the maintainer, and works to get this out of staging, otherwise it will be deleted soon. Reported-by: Nico Golde Reported-by: Dan Carpenter Cc: Omar Ramirez Luna Cc: Omar Ramirez Luna Cc: Kanigeri, Hari Cc: Ameya Palande Cc: Guzman Lugo, Fernando Cc: Hebbar, Shivananda Cc: Ramos Falcon, Ernesto Cc: Felipe Contreras Cc: Anna, Suman Cc: Gupta, Ramesh Cc: Gomez Castellanos, Ivan Cc: Andy Shevchenko Cc: Armando Uribe De Leon Cc: Deepak Chitriki Cc: Menon, Nishanth Cc: Phil Carmody Cc: Ohad Ben-Cohen Cc: stable Signed-off-by: Greg Kroah-Hartman backlight: atmel-pwm-bl: fix reported brightness commit 185d91442550110db67a7dc794a32efcea455a36 upstream. The driver supports 16-bit brightness values, but the value returned from get_brightness was truncated to eight bits. Signed-off-by: Johan Hovold Cc: Jingoo Han Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman ASoC: ak4642: prevent un-necessary changes to SG_SL1 commit 7b5bfb82882b9b1c8423ce0ed6852ca3762d967a upstream. If you record the sound during playback, the playback sound becomes silent. Modify so that the codec driver does not clear SG_SL1::DACL bit which is controlled under widget Signed-off-by: Phil Edworthy Signed-off-by: Kuninori Morimoto Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman ASoC: wm8962: Turn on regcache_cache_only before disabling regulator commit 50bfcf2df2fadf77e143d6099150e6fa7ef4d78c upstream. It's safer to turn on regcache_cache_only before disabling regulator since the driver will turn off the regcache_cache_only after enabling regulator. If we remain cache_only false, some command like 'amixer cset' would get failure if being run before wm8962_resume(). Signed-off-by: Nicolin Chen Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman ASoC: blackfin: Fix missing break commit afed4dbe3a043dbd833a53b6b4951e155708afd2 upstream. Fixes: 4b2ffc205cb9 ('ASoC: Blackfin I2S: add 8-bit sample support') Reported-by: David Binderman Signed-off-by: Takashi Iwai Signed-off-by: Mark Brown Signed-off-by: Greg Kroah-Hartman alarmtimer: return EINVAL instead of ENOTSUPP if rtcdev doesn't exist commit 98d6f4dd84a134d942827584a3c5f67ffd8ec35f upstream. Fedora Ruby maintainer reported latest Ruby doesn't work on Fedora Rawhide on ARM. (http://bugs.ruby-lang.org/issues/9008) Because of, commit 1c6b39ad3f (alarmtimers: Return -ENOTSUPP if no RTC device is present) intruduced to return ENOTSUPP when clock_get{time,res} can't find a RTC device. However this is incorrect. First, ENOTSUPP isn't exported to userland (ENOTSUP or EOPNOTSUP are the closest userland equivlents). Second, Posix and Linux man pages agree that clock_gettime and clock_getres should return EINVAL if clk_id argument is invalid. While the arugment that the clockid is valid, but just not supported on this hardware could be made, this is just a technicality that doesn't help userspace applicaitons, and only complicates error handling. Thus, this patch changes the code to use EINVAL. Cc: Thomas Gleixner Cc: Frederic Weisbecker Reported-by: Vit Ondruch Signed-off-by: KOSAKI Motohiro [jstultz: Tweaks to commit message to include full rational] Signed-off-by: John Stultz Signed-off-by: Greg Kroah-Hartman devpts: plug the memory leak in kill_sb commit 66da0e1f9034140ae2f571ef96e254a25083906c upstream. When devpts is unmounted, there may be a no-longer-used IDR tree hanging off the superblock we are about to kill. This needs to be cleaned up before destroying the SB. The leak is usually not a big deal because unmounting devpts is typically done when shutting down the whole machine. However, shutting down an LXC container instead of a physical machine exposes the problem (the garbage is detectable with kmemleak). Signed-off-by: Ilija Hadzic Cc: Sukadev Bhattiprolu Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman can: flexcan: fix flexcan_chip_start() on imx6 commit 0d1862ea1a5bb876cf05555a7307080cb75bf379 upstream. In the flexcan_chip_start() function first the flexcan core is going through the soft reset sequence, then the RX FIFO is enabled. With the hardware is put into FIFO mode, message buffers 1...7 are reserved by the FIFO engine. The remaining message buffers are in reset default values. This patch removes the bogus initialization of the message buffers, as it causes an imprecise external abort on imx6. Reported-by: Lothar Waßmann Tested-by: Lothar Waßmann [mkl: adjusted context for stable] Signed-off-by: Marc Kleine-Budde Signed-off-by: Greg Kroah-Hartman libata: Fix display of sata speed commit 3e85c3ecbc520751324a191d23bb94873ed01b10 upstream. 6.0 Gbps link speed was not decoded properly: speed was reported at 3.0 Gbps only. Tested: On a machine where libata reports 6.0 Gbps in /var/log/messages: ata1: SATA link up 6.0 Gbps (SStatus 133 SControl 300) Before: cat /sys/class/ata_link/link1/sata_spd 3.0 Gbps After: cat /sys/class/ata_link/link1/sata_spd 6.0 Gbps Signed-off-by: Gwendal Grignou Signed-off-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman drivers/libata: Set max sector to 65535 for Slimtype DVD A DS8A9SH drive commit 0523f037f65dba10191b0fa9c51266f90ba64630 upstream. The "Slimtype DVD A DS8A9SH" drive locks up with following backtrace when the max sector is smaller than 65535 bytes, fix it by adding a quirk to set the max sector to 65535 bytes. INFO: task flush-11:0:663 blocked for more than 120 seconds. "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. flush-11:0 D 00000000ffff5ceb 0 663 2 0x00000000 ffff88026d3b1710 0000000000000046 0000000000000001 0000000000000000 ffff88026f2530c0 ffff88026d365860 ffff88026d3b16e0 ffffffff812ffd52 ffff88026d4fd3d0 0000000100000001 ffff88026d3b16f0 ffff88026d3b1fd8 Call Trace: [] ? cfq_may_queue+0x52/0xf0 [] schedule+0x18/0x30 [] io_schedule+0x42/0x60 [] get_request_wait+0xeb/0x1f0 [] ? autoremove_wake_function+0x0/0x40 [] ? elv_merge+0x42/0x210 [] __make_request+0x8e/0x4e0 [] generic_make_request+0x21e/0x5e0 [] submit_bio+0x5d/0xd0 [] submit_bh+0xf2/0x130 [] __block_write_full_page+0x1dc/0x3a0 [] ? end_buffer_async_write+0x0/0x120 [] ? blkdev_get_block+0x0/0x70 [] ? blkdev_get_block+0x0/0x70 [] ? end_buffer_async_write+0x0/0x120 [] block_write_full_page_endio+0xde/0x100 [] block_write_full_page+0x10/0x20 [] blkdev_writepage+0x13/0x20 [] __writepage+0x15/0x40 [] write_cache_pages+0x1cf/0x3e0 [] ? __writepage+0x0/0x40 [] generic_writepages+0x22/0x30 [] do_writepages+0x1f/0x40 [] writeback_single_inode+0xe7/0x3b0 [] writeback_sb_inodes+0x184/0x280 [] writeback_inodes_wb+0x6b/0x1a0 [] wb_writeback+0x23b/0x2a0 [] wb_do_writeback+0x17d/0x190 [] bdi_writeback_task+0x4b/0xe0 [] ? bdi_start_fn+0x0/0x100 [] bdi_start_fn+0x81/0x100 [] ? bdi_start_fn+0x0/0x100 [] kthread+0x8e/0xa0 [] ? finish_task_switch+0x54/0xc0 [] kernel_thread_helper+0x4/0x10 [] ? kthread+0x0/0xa0 [] ? kernel_thread_helper+0x0/0x10 The above trace was triggered by "dd if=/dev/zero of=/dev/sr0 bs=2048 count=32768" Signed-off-by: Shan Hai Signed-off-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman vsprintf: check real user/group id for %pK commit 312b4e226951f707e120b95b118cbc14f3d162b2 upstream. Some setuid binaries will allow reading of files which have read permission by the real user id. This is problematic with files which use %pK because the file access permission is checked at open() time, but the kptr_restrict setting is checked at read() time. If a setuid binary opens a %pK file as an unprivileged user, and then elevates permissions before reading the file, then kernel pointer values may be leaked. This happens for example with the setuid pppd application on Ubuntu 12.04: $ head -1 /proc/kallsyms 00000000 T startup_32 $ pppd file /proc/kallsyms pppd: In file /proc/kallsyms: unrecognized option 'c1000000' This will only leak the pointer value from the first line, but other setuid binaries may leak more information. Fix this by adding a check that in addition to the current process having CAP_SYSLOG, that effective user and group ids are equal to the real ids. If a setuid binary reads the contents of a file which uses %pK then the pointer values will be printed as NULL if the real user is unprivileged. Update the sysctl documentation to reflect the changes, and also correct the documentation to state the kptr_restrict=0 is the default. This is a only temporary solution to the issue. The correct solution is to do the permission check at open() time on files, and to replace %pK with a function which checks the open() time permission. %pK uses in printk should be removed since no sane permission check can be done, and instead protected by using dmesg_restrict. Signed-off-by: Ryan Mallon Cc: Kees Cook Cc: Alexander Viro Cc: Joe Perches Cc: "Eric W. Biederman" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman rtlwifi: rtl8192se: Fix wrong assignment commit 3aef7dde8dcf09e0124f0a2665845a507331972b upstream. There is a typo in the struct member name on assignment when checking rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20_40, the check uses pwrgroup_ht40 for bound limit and uses pwrgroup_ht20 when assigning instead. Signed-off-by: Felipe Pena Acked-by: Larry Finger Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman rtlwifi: rtl8192cu: Fix more pointer arithmetic errors commit eafbdde9c5629bea58df07275c5917eb42afbbe7 upstream. This driver uses a number of macros to get and set various fields in the RX and TX descriptors. To work correctly, a u8 pointer to the descriptor must be used; however, in some cases a descriptor structure pointer is used instead. In addition, a duplicated statement is removed. Signed-off-by: Larry Finger Reported-by: Mark Cave-Ayland Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman ahci: disabled FBS prior to issuing software reset commit 89dafa20f3daab5b3e0c13d0068a28e8e64e2102 upstream. Tested with Marvell 88se9125, attached with one port mulitplier(5 ports) and one disk, we will get following boot log messages if using current code: ata8: SATA link up 6.0 Gbps (SStatus 133 SControl 330) ata8.15: Port Multiplier 1.2, 0x1b4b:0x9715 r160, 5 ports, feat 0x1/0x1f ahci 0000:03:00.0: FBS is enabled ata8.00: hard resetting link ata8.00: SATA link down (SStatus 0 SControl 330) ata8.01: hard resetting link ata8.01: SATA link down (SStatus 0 SControl 330) ata8.02: hard resetting link ata8.02: SATA link down (SStatus 0 SControl 330) ata8.03: hard resetting link ata8.03: SATA link up 6.0 Gbps (SStatus 133 SControl 133) ata8.04: hard resetting link ata8.04: failed to resume link (SControl 133) ata8.04: failed to read SCR 0 (Emask=0x40) ata8.04: failed to read SCR 0 (Emask=0x40) ata8.04: failed to read SCR 1 (Emask=0x40) ata8.04: failed to read SCR 0 (Emask=0x40) ata8.03: native sectors (2) is smaller than sectors (976773168) ata8.03: ATA-8: ST3500413AS, JC4B, max UDMA/133 ata8.03: 976773168 sectors, multi 0: LBA48 NCQ (depth 31/32) ata8.03: configured for UDMA/133 ata8.04: failed to IDENTIFY (I/O error, err_mask=0x100) ata8.15: hard resetting link ata8.15: SATA link up 6.0 Gbps (SStatus 133 SControl 330) ata8.15: Port Multiplier vendor mismatch '0x1b4b' != '0x133' ata8.15: PMP revalidation failed (errno=-19) ata8.15: hard resetting link ata8.15: SATA link up 6.0 Gbps (SStatus 133 SControl 330) ata8.15: Port Multiplier vendor mismatch '0x1b4b' != '0x133' ata8.15: PMP revalidation failed (errno=-19) ata8.15: limiting SATA link speed to 3.0 Gbps ata8.15: hard resetting link ata8.15: SATA link up 3.0 Gbps (SStatus 123 SControl 320) ata8.15: Port Multiplier vendor mismatch '0x1b4b' != '0x133' ata8.15: PMP revalidation failed (errno=-19) ata8.15: failed to recover PMP after 5 tries, giving up ata8.15: Port Multiplier detaching ata8.03: disabled ata8.00: disabled ata8: EH complete The reason is that current detection code doesn't follow AHCI spec: First,the port multiplier detection process look like this: ahci_hardreset(link, class, deadline) if (class == ATA_DEV_PMP) { sata_pmp_attach(dev) /* will enable FBS */ sata_pmp_init_links(ap, nr_ports); ata_for_each_link(link, ap, EDGE) { sata_std_hardreset(link, class, deadline); if (link_is_online) /* do soft reset */ ahci_softreset(link, class, deadline); } } But, according to chapter 9.3.9 in AHCI spec: Prior to issuing software reset, software shall clear PxCMD.ST to '0' and then clear PxFBS.EN to '0'. The patch test ok with kernel 3.11.1. tj: Patch white space contaminated, applied manually with trivial updates. Signed-off-by: Xiangliang Yu Signed-off-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman ahci: add Marvell 9230 to the AHCI PCI device list commit 6d5278a68a75891db1df5ae1ecf83d288fc58c65 upstream. Tested with a DAWICONTROL DC-624e on 3.10.10 Signed-off-by: Samir Benmendil Signed-off-by: Tejun Heo Reviewed-by: Levente Kurusa Signed-off-by: Greg Kroah-Hartman iscsi-target: fix extract_param to handle buffer length corner case commit 369653e4fb511928511b0ce81f41c812ff1f28b6 upstream. extract_param() is called with max_length set to the total size of the output buffer. It's not safe to allow a parameter length equal to the buffer size as the terminating null would be written one byte past the end of the output buffer. Signed-off-by: Eric Seppanen Signed-off-by: Nicholas Bellinger Signed-off-by: Greg Kroah-Hartman iscsi-target: chap auth shouldn't match username with trailing garbage commit 86784c6bdeeef78eed94d298be7a8879f6a97ee2 upstream. In iSCSI negotiations with initiator CHAP enabled, usernames with trailing garbage are permitted, because the string comparison only checks the strlen of the configured username. e.g. "usernameXXXXX" will be permitted to match "username". Just check one more byte so the trailing null char is also matched. Signed-off-by: Eric Seppanen Signed-off-by: Nicholas Bellinger Signed-off-by: Greg Kroah-Hartman IB/ipath: Convert ipath_user_sdma_pin_pages() to use get_user_pages_fast() commit 4adcf7fb6783e354aab38824d803fa8c4f8e8a27 upstream. ipath_user_sdma_queue_pkts() gets called with mmap_sem held for writing. Except for get_user_pages() deep down in ipath_user_sdma_pin_pages() we don't seem to need mmap_sem at all. Even more interestingly the function ipath_user_sdma_queue_pkts() (and also ipath_user_sdma_coalesce() called somewhat later) call copy_from_user() which can hit a page fault and we deadlock on trying to get mmap_sem when handling that fault. So just make ipath_user_sdma_pin_pages() use get_user_pages_fast() and leave mmap_sem locking for mm. This deadlock has actually been observed in the wild when the node is under memory pressure. Signed-off-by: Jan Kara Signed-off-by: Mike Marciniszyn [ Merged in fix for call to get_user_pages_fast from Tetsuo Handa . - Roland ] Signed-off-by: Roland Dreier Signed-off-by: Greg Kroah-Hartman loop: fix crash if blk_alloc_queue fails commit 3ec981e30fae1f3c8728a05c730acaa1f627bcfb upstream. loop: fix crash if blk_alloc_queue fails If blk_alloc_queue fails, loop_add cleans up, but it doesn't clean up the identifier allocated with idr_alloc. That causes crash on module unload in idr_for_each(&loop_index_idr, &loop_exit_cb, NULL); where we attempt to remove non-existed device with that id. BUG: unable to handle kernel NULL pointer dereference at 0000000000000380 IP: [] del_gendisk+0x19/0x2d0 PGD 43d399067 PUD 43d0ad067 PMD 0 Oops: 0000 [#1] PREEMPT SMP Modules linked in: loop(-) dm_snapshot dm_zero dm_mirror dm_region_hash dm_log dm_loop dm_mod ip6table_filter ip6_tables uvesafb cfbcopyarea cfbimgblt cfbfillrect fbcon font bitblit fbcon_rotate fbcon_cw fbcon_ud fbcon_ccw softcursor fb fbdev msr ipt_MASQUERADE iptable_nat nf_nat_ipv4 nf_conntrack_ipv4 nf_defrag_ipv4 xt_state ipt_REJECT xt_tcpudp iptable_filter ip_tables x_tables bridge stp llc tun ipv6 cpufreq_userspace cpufreq_stats cpufreq_ondemand cpufreq_conservative cpufreq_powersave spadfs fuse hid_generic usbhid hid raid0 md_mod dmi_sysfs nf_nat_ftp nf_nat nf_conntrack_ftp nf_conntrack snd_usb_audio snd_pcm_oss snd_mixer_oss snd_pcm snd_timer snd_page_alloc lm85 hwmon_vid snd_hwdep snd_usbmidi_lib snd_rawmidi snd soundcore acpi_cpufreq ohci_hcd freq_table tg3 ehci_pci mperf ehci_hcd kvm_amd kvm sata_svw serverworks libphy libata ide_core k10temp usbcore hwmon microcode ptp pcspkr pps_core e100 skge mii usb_common i2c_piix4 floppy evdev rtc_cmos i2c_core processor but! ton unix CPU: 7 PID: 2735 Comm: rmmod Tainted: G W 3.10.15-devel #15 Hardware name: empty empty/S3992-E, BIOS 'V1.06 ' 06/09/2009 task: ffff88043d38e780 ti: ffff88043d21e000 task.ti: ffff88043d21e000 RIP: 0010:[] [] del_gendisk+0x19/0x2d0 RSP: 0018:ffff88043d21fe10 EFLAGS: 00010282 RAX: ffffffffa05102e0 RBX: 0000000000000000 RCX: 0000000000000000 RDX: 0000000000000000 RSI: ffff88043ea82800 RDI: 0000000000000000 RBP: ffff88043d21fe48 R08: 0000000000000000 R09: 0000000000000001 R10: 0000000000000001 R11: 0000000000000000 R12: 00000000000000ff R13: 0000000000000080 R14: 0000000000000000 R15: ffff88043ea82800 FS: 00007ff646534700(0000) GS:ffff880447000000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b CR2: 0000000000000380 CR3: 000000043e9bf000 CR4: 00000000000007e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 Stack: ffffffff8100aba4 0000000000000092 ffff88043d21fe48 ffff88043ea82800 00000000000000ff ffff88043d21fe98 0000000000000000 ffff88043d21fe60 ffffffffa05102b4 0000000000000000 ffff88043d21fe70 ffffffffa05102ec Call Trace: [] ? native_sched_clock+0x24/0x80 [] loop_remove+0x14/0x40 [loop] [] loop_exit_cb+0xc/0x10 [loop] [] idr_for_each+0x104/0x190 [] ? loop_remove+0x40/0x40 [loop] [] ? trace_hardirqs_on_caller+0x105/0x1d0 [] loop_exit+0x34/0xa58 [loop] [] SyS_delete_module+0x13a/0x260 [] ? trace_hardirqs_on_thunk+0x3a/0x3f [] system_call_fastpath+0x1a/0x1f Code: f0 4c 8b 6d f8 c9 c3 66 66 2e 0f 1f 84 00 00 00 00 00 55 48 89 e5 41 56 41 55 4c 8d af 80 00 00 00 41 54 53 48 89 fb 48 83 ec 18 <48> 83 bf 80 03 00 00 00 74 4d e8 98 fe ff ff 31 f6 48 c7 c7 20 RIP [] del_gendisk+0x19/0x2d0 RSP CR2: 0000000000000380 ---[ end trace 64ec069ec70f1309 ]--- Signed-off-by: Mikulas Patocka Acked-by: Tejun Heo Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman mtd: nand: hack ONFI for non-power-of-2 dimensions commit 4355b70cf48363c50a9de450b01178c83aba8f6a upstream. Some bright specification writers decided to write this in the ONFI spec (from ONFI 3.0, Section 3.1): "The number of blocks and number of pages per block is not required to be a power of two. In the case where one of these values is not a power of two, the corresponding address shall be rounded to an integral number of bits such that it addresses a range up to the subsequent power of two value. The host shall not access upper addresses in a range that is shown as not supported." This breaks every assumption MTD makes about NAND block/chip-size dimensions -- they *must* be a power of two! And of course, an enterprising manufacturer has made use of this lovely freedom. Exhibit A: Micron MT29F32G08CBADAWP "- Plane size: 2 planes x 1064 blocks per plane - Device size: 32Gb: 2128 blockss [sic]" This quickly hits a BUG() in nand_base.c, since the extra dimensions overflow so we think it's a second chip (on my single-chip setup): ONFI param page 0 valid ONFI flash detected NAND device: Manufacturer ID: 0x2c, Chip ID: 0x44 (Micron MT29F32G08CBADAWP), 4256MiB, page size: 8192, OOB size: 744 ------------[ cut here ]------------ kernel BUG at drivers/mtd/nand/nand_base.c:203! Internal error: Oops - BUG: 0 [#1] SMP ARM [... trim ...] [] (nand_select_chip+0x18/0x2c) from [] (nand_do_read_ops+0x90/0x424) [] (nand_do_read_ops+0x90/0x424) from [] (nand_read+0x54/0x78) [] (nand_read+0x54/0x78) from [] (mtd_read+0x84/0xbc) [] (mtd_read+0x84/0xbc) from [] (scan_read.clone.4+0x4c/0x64) [] (scan_read.clone.4+0x4c/0x64) from [] (search_bbt+0x148/0x290) [] (search_bbt+0x148/0x290) from [] (nand_scan_bbt+0xd4/0x5c0) [... trim ...] ---[ end trace 0c9363860d865ff2 ]--- So to fix this, just truncate these dimensions down to the greatest power-of-2 dimension that is less than or equal to the specified dimension. Signed-off-by: Brian Norris Signed-off-by: Greg Kroah-Hartman mtd: map: fixed bug in 64-bit systems commit a4d62babf988fe5dfde24437fa135ef147bc7aa0 upstream. Hardware: CPU: XLP832,the 64-bit OS NOR Flash:S29GL128S 128M Software: Kernel:2.6.32.41 Filesystem:JFFS2 When writing files, errors appear: Write len 182 but return retlen 180 Write of 182 bytes at 0x072c815c failed. returned -5, retlen 180 Write len 186 but return retlen 184 Write of 186 bytes at 0x072caff4 failed. returned -5, retlen 184 These errors exist only in 64-bit systems,not in 32-bit systems. After analysis, we found that the left shift operation is wrong in map_word_load_partial. For instance: unsigned char buf[3] ={0x9e,0x3a,0xea}; map_bankwidth(map) is 4; for (i=0; i < 3; i++) { int bitpos; bitpos = (map_bankwidth(map)-1-i)*8; orig.x[0] &= ~(0xff << bitpos); orig.x[0] |= buf[i] << bitpos; } The value of orig.x[0] is expected to be 0x9e3aeaff, but in this situation(64-bit System) we'll get the wrong value of 0xffffffff9e3aeaff due to the 64-bit sign extension: buf[i] is defined as "unsigned char" and the left-shift operation will convert it to the type of "signed int", so when left-shift buf[i] by 24 bits, the final result will get the wrong value: 0xffffffff9e3aeaff. If the left-shift bits are less than 24, then sign extension will not occur. Whereas the bankwidth of the nor flash we used is 4, therefore this BUG emerges. Signed-off-by: Pang Xunlei Signed-off-by: Zhang Yi Signed-off-by: Lu Zhongjun Signed-off-by: Brian Norris Signed-off-by: Greg Kroah-Hartman mtd: gpmi: fix kernel BUG due to racing DMA operations commit 7b3d2fb92067bcb29f0f085a9fa9fa64920a6646 upstream. [1] The gpmi uses the nand_command_lp to issue the commands to NAND chips. The gpmi issues a DMA operation with gpmi_cmd_ctrl when it handles a NAND_CMD_NONE control command. So when we read a page(NAND_CMD_READ0) from the NAND, we may send two DMA operations back-to-back. If we do not serialize the two DMA operations, we will meet a bug when 1.1) we enable CONFIG_DMA_API_DEBUG, CONFIG_DMADEVICES_DEBUG, and CONFIG_DEBUG_SG. 1.2) Use the following commands in an UART console and a SSH console: cmd 1: while true;do dd if=/dev/mtd0 of=/dev/null;done cmd 1: while true;do dd if=/dev/mmcblk0 of=/dev/null;done The kernel log shows below: ----------------------------------------------------------------- kernel BUG at lib/scatterlist.c:28! Unable to handle kernel NULL pointer dereference at virtual address 00000000 ......................... [<80044a0c>] (__bug+0x18/0x24) from [<80249b74>] (sg_next+0x48/0x4c) [<80249b74>] (sg_next+0x48/0x4c) from [<80255398>] (debug_dma_unmap_sg+0x170/0x1a4) [<80255398>] (debug_dma_unmap_sg+0x170/0x1a4) from [<8004af58>] (dma_unmap_sg+0x14/0x6c) [<8004af58>] (dma_unmap_sg+0x14/0x6c) from [<8027e594>] (mxs_dma_tasklet+0x18/0x1c) [<8027e594>] (mxs_dma_tasklet+0x18/0x1c) from [<8007d444>] (tasklet_action+0x114/0x164) ----------------------------------------------------------------- 1.3) Assume the two DMA operations is X (first) and Y (second). The root cause of the bug: Assume process P issues DMA X, and sleep on the completion @this->dma_done. X's tasklet callback is dma_irq_callback. It firstly wake up the process sleeping on the completion @this->dma_done, and then trid to unmap the scatterlist S. The waked process P will issue Y in another ARM core. Y initializes S->sg_magic to zero with sg_init_one(), while dma_irq_callback is unmapping S at the same time. See the diagram: ARM core 0 | ARM core 1 ------------------------------------------------------------- (P issues DMA X, then sleep) --> | | (X's tasklet wakes P) --> | | | <-- (P begin to issue DMA Y) | (X's tasklet unmap the | scatterlist S with dma_unmap_sg) --> | <-- (Y calls sg_init_one() to init | scatterlist S) | [2] This patch serialize both the X and Y in the following way: Unmap the DMA scatterlist S firstly, and wake up the process at the end of the DMA callback, in such a way, Y will be executed after X. After this patch: ARM core 0 | ARM core 1 ------------------------------------------------------------- (P issues DMA X, then sleep) --> | | (X's tasklet unmap the | scatterlist S with dma_unmap_sg) --> | | (X's tasklet wakes P) --> | | | <-- (P begin to issue DMA Y) | | <-- (Y calls sg_init_one() to init | scatterlist S) | Signed-off-by: Huang Shijie Signed-off-by: Brian Norris Signed-off-by: Greg Kroah-Hartman ext4: avoid bh leak in retry path of ext4_expand_extra_isize_ea() commit dcb9917ba041866686fe152850364826c4622a36 upstream. Reported-by: Dave Jones Signed-off-by: "Theodore Ts'o" Signed-off-by: Greg Kroah-Hartman xen/blkback: fix reference counting commit ea5ec76d76da9279d12027c1828544c5ccbe7932 upstream. If the permission check fails, we drop a reference to the blkif without having taken it in the first place. The bug was introduced in commit 604c499cbbcc3d5fe5fb8d53306aa0fae1990109 (xen/blkback: Check device permissions before allowing OP_DISCARD). Cc: Jan Beulich Cc: Konrad Rzeszutek Wilk Signed-off-by: Vegard Nossum Signed-off-by: Konrad Rzeszutek Wilk Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman staging: vt6656: [BUG] Fix for TX USB resets from vendors driver. commit 9df682927c2e3a92f43803d6b52095992e3b2ab8 upstream. This fixes resets on heavy TX data traffic. Vendor driver VT6656_Linux_src_v1.21.03_x86_11.04.zip http://www.viaembedded.com/servlet/downloadSvl?id=1890&download_file_id=14704 This is GPL-licensed code. original code BBbVT3184Init ... //2007-0725, RobertChang add, Enable Squelch detect reset option(SQ_RST_Opt), USB (register4, bit1) CONTROLnsRequestIn(pDevice, MESSAGE_TYPE_READ, (WORD)0x600+4, // USB's Reg4's bit1 MESSAGE_REQUEST_MEM, 1, (PBYTE) &byData); byData = byData|2 ; CONTROLnsRequestOut(pDevice, MESSAGE_TYPE_WRITE, (WORD)0x600+4, // USB's Reg4's bit1 MESSAGE_REQUEST_MEM, 1, (PBYTE) &byData); return TRUE;//ntStatus; .... A back port patch is needed for kernels less than 3.10. Signed-off-by: Malcolm Priestley Signed-off-by: Greg Kroah-Hartman rtlwifi: rtl8192de: Fix incorrect signal strength for unassociated AP commit 3545f3d5f4af715c914394123ce7725a9cf0a1c4 upstream. The routine that processes received frames was returning the RSSI value for the signal strength; however, that value is available only for associated APs. As a result, the strength was the absurd value of 10 dBm. As a result, scans return incorrect values for the strength, which causes unwanted attempts to roam. Signed-off-by: Larry Finger Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman rtlwifi: rtl8192se: Fix incorrect signal strength for unassociated AP commit b4ade797668e33b4e8353c2701ce01d7084dfafa upstream. The routine that processes received frames was returning the RSSI value for the signal strength; however, that value is available only for associated APs. As a result, the strength was the absurd value of 10 dBm. As a result, scans return incorrect values for the strength, which causes unwanted attempts to roam. This patch fixes https://bugzilla.kernel.org/show_bug.cgi?id=63881. Signed-off-by: Larry Finger Reported-by: Matthieu Baerts Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman rtlwifi: rtl8192cu: Fix incorrect signal strength for unassociated AP commit 78dbfecb95be4635b995af3bd29fa10013409fcd upstream. The routine that processes received frames was returning the RSSI value for the signal strength; however, that value is available only for associated APs. As a result, the strength was the absurd value of 10 dBm. As a result, scans return incorrect values for the strength, which causes unwanted attempts to roam. Signed-off-by: Larry Finger Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman qeth: avoid buffer overflow in snmp ioctl commit 6fb392b1a63ae36c31f62bc3fc8630b49d602b62 upstream. Check user-defined length in snmp ioctl request and allow request only if it fits into a qeth command buffer. Signed-off-by: Ursula Braun Signed-off-by: Frank Blaschka Reviewed-by: Heiko Carstens Reported-by: Nico Golde Reported-by: Fabian Yamaguchi Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman rt2400pci: fix RSSI read commit 2bf127a5cc372b9319afcbae10b090663b621c8b upstream. RSSI value is provided on word3 not on word2. Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman dm: allocate buffer for messages with small number of arguments using GFP_NOIO commit f36afb3957353d2529cb2b00f78fdccd14fc5e9c upstream. dm-mpath and dm-thin must process messages even if some device is suspended, so we allocate argv buffer with GFP_NOIO. These messages have a small fixed number of arguments. On the other hand, dm-switch needs to process bulk data using messages so excessive use of GFP_NOIO could cause trouble. The patch also lowers the default number of arguments from 64 to 8, so that there is smaller load on GFP_NOIO allocations. Signed-off-by: Mikulas Patocka Acked-by: Alasdair G Kergon Signed-off-by: Mike Snitzer Signed-off-by: Greg Kroah-Hartman PM / hibernate: Avoid overflow in hibernate_preallocate_memory() commit fd432b9f8c7c88428a4635b9f5a9c6e174df6e36 upstream. When system has a lot of highmem (e.g. 16GiB using a 32 bits kernel), the code to calculate how much memory we need to preallocate in normal zone may cause overflow. As Leon has analysed: It looks that during computing 'alloc' variable there is overflow: alloc = (3943404 - 1970542) - 1978280 = -5418 (signed) And this function goes to err_out. Fix this by avoiding that overflow. References: https://bugzilla.kernel.org/show_bug.cgi?id=60817 Reported-and-tested-by: Leon Drugi Signed-off-by: Aaron Lu Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman mwifiex: correct packet length for packets from SDIO interface commit d03b4aa77e1187b77dfe37d14a923547f00baa66 upstream. While receiving a packet on SDIO interface, we allocate skb with size multiple of SDIO block size. We need to resize this skb after RX using packet length from RX header. Signed-off-by: Avinash Patil Signed-off-by: Bing Zhao Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman audit: printk USER_AVC messages when audit isn't enabled commit 0868a5e150bc4c47e7a003367cd755811eb41e0b upstream. When the audit=1 kernel parameter is absent and auditd is not running, AUDIT_USER_AVC messages are being silently discarded. AUDIT_USER_AVC messages should be sent to userspace using printk(), as mentioned in the commit message of 4a4cd633 ("AUDIT: Optimise the audit-disabled case for discarding user messages"). When audit_enabled is 0, audit_receive_msg() discards all user messages except for AUDIT_USER_AVC messages. However, audit_log_common_recv_msg() refuses to allocate an audit_buffer if audit_enabled is 0. The fix is to special case AUDIT_USER_AVC messages in both functions. It looks like commit 50397bd1 ("[AUDIT] clean up audit_receive_msg()") introduced this bug. Signed-off-by: Tyler Hicks Cc: Al Viro Cc: Eric Paris Cc: linux-audit@redhat.com Acked-by: Kees Cook Signed-off-by: Richard Guy Briggs Signed-off-by: Eric Paris Signed-off-by: Greg Kroah-Hartman audit: use nlmsg_len() to get message payload length commit 4d8fe7376a12bf4524783dd95cbc00f1fece6232 upstream. Using the nlmsg_len member of the netlink header to test if the message is valid is wrong as it includes the size of the netlink header itself. Thereby allowing to send short netlink messages that pass those checks. Use nlmsg_len() instead to test for the right message length. The result of nlmsg_len() is guaranteed to be non-negative as the netlink message already passed the checks of nlmsg_ok(). Also switch to min_t() to please checkpatch.pl. Cc: Al Viro Cc: Eric Paris Signed-off-by: Mathias Krause Signed-off-by: Richard Guy Briggs Signed-off-by: Eric Paris Signed-off-by: Greg Kroah-Hartman audit: fix info leak in AUDIT_GET requests commit 64fbff9ae0a0a843365d922e0057fc785f23f0e3 upstream. We leak 4 bytes of kernel stack in response to an AUDIT_GET request as we miss to initialize the mask member of status_set. Fix that. Cc: Al Viro Cc: Eric Paris Signed-off-by: Mathias Krause Signed-off-by: Richard Guy Briggs Signed-off-by: Eric Paris Signed-off-by: Greg Kroah-Hartman PCI: Remove duplicate pci_disable_device() from pcie_portdrv_remove() commit e7cc5cf74544d97d7b69e2701595037474db1f96 upstream. The pcie_portdrv .probe() method calls pci_enable_device() once, in pcie_port_device_register(), but the .remove() method calls pci_disable_device() twice, in pcie_port_device_remove() and in pcie_portdrv_remove(). That causes a "disabling already-disabled device" warning when removing a PCIe port device. This happens all the time when removing Thunderbolt devices, but is also easy to reproduce with, e.g., "echo 0000:00:1c.3 > /sys/bus/pci/drivers/pcieport/unbind" This patch removes the disable from pcie_portdrv_remove(). [bhelgaas: changelog, tag for stable] Reported-by: David Bulkow Reported-by: Mika Westerberg Signed-off-by: Yinghai Lu Signed-off-by: Bjorn Helgaas Signed-off-by: Greg Kroah-Hartman selinux: correct locking in selinux_netlbl_socket_connect) commit 42d64e1add3a1ce8a787116036163b8724362145 upstream. The SELinux/NetLabel glue code has a locking bug that affects systems with NetLabel enabled, see the kernel error message below. This patch corrects this problem by converting the bottom half socket lock to a more conventional, and correct for this call-path, lock_sock() call. =============================== [ INFO: suspicious RCU usage. ] 3.11.0-rc3+ #19 Not tainted ------------------------------- net/ipv4/cipso_ipv4.c:1928 suspicious rcu_dereference_protected() usage! other info that might help us debug this: rcu_scheduler_active = 1, debug_locks = 0 2 locks held by ping/731: #0: (slock-AF_INET/1){+.-...}, at: [...] selinux_netlbl_socket_connect #1: (rcu_read_lock){.+.+..}, at: [<...>] netlbl_conn_setattr stack backtrace: CPU: 1 PID: 731 Comm: ping Not tainted 3.11.0-rc3+ #19 Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011 0000000000000001 ffff88006f659d28 ffffffff81726b6a ffff88003732c500 ffff88006f659d58 ffffffff810e4457 ffff88006b845a00 0000000000000000 000000000000000c ffff880075aa2f50 ffff88006f659d90 ffffffff8169bec7 Call Trace: [] dump_stack+0x54/0x74 [] lockdep_rcu_suspicious+0xe7/0x120 [] cipso_v4_sock_setattr+0x187/0x1a0 [] netlbl_conn_setattr+0x187/0x190 [] ? netlbl_conn_setattr+0x5/0x190 [] selinux_netlbl_socket_connect+0xae/0xc0 [] selinux_socket_connect+0x135/0x170 [] ? might_fault+0x57/0xb0 [] security_socket_connect+0x16/0x20 [] SYSC_connect+0x73/0x130 [] ? sysret_check+0x22/0x5d [] ? trace_hardirqs_on_caller+0xfd/0x1c0 [] ? trace_hardirqs_on_thunk+0x3a/0x3f [] SyS_connect+0xe/0x10 [] system_call_fastpath+0x16/0x1b Signed-off-by: Paul Moore Signed-off-by: Greg Kroah-Hartman avr32: setup crt for early panic() commit 7a2a74f4b856993218aa7cdeeb6c3103101340db upstream. Before the CRT was (fully) set up in kernel_entry (bss cleared before in _start, but also not before jump to panic() in no_tag_table case). This patch fixes this up to have a fully working CRT when branching to panic() in no_tag_table. Signed-off-by: Andreas Bießmann Acked-by: Hans-Christian Egtvedt Cc: Haavard Skinnemoen Signed-off-by: Greg Kroah-Hartman avr32: fix out-of-range jump in large kernels commit d617b338bbfdd77e9cbd8e7dc949cee3dd73d575 upstream. This patch fixes following error (for big kernels): ---8<--- arch/avr32/boot/u-boot/head.o: In function `no_tag_table': (.init.text+0x44): relocation truncated to fit: R_AVR32_22H_PCREL against symbol `panic' defined in .text.unlikely section in kernel/built-in.o arch/avr32/kernel/built-in.o: In function `bad_return': (.ex.text+0x236): relocation truncated to fit: R_AVR32_22H_PCREL against symbol `panic' defined in .text.unlikely section in kernel/built-in.o --->8--- It comes up when the kernel increases and 'panic()' is too far away to fit in the +/- 2MiB range. Which in turn issues from the 21-bit displacement in 'br{cond4}' mnemonic which is one of the two ways to do jumps (rjmp has just 10-bit displacement and therefore a way smaller range). This fact was stated before in 8d29b7b9f81d6b83d869ff054e6c189d6da73f1f. One solution to solve this is to add a local storage for the symbol address and just load the $pc with that value. Signed-off-by: Andreas Bießmann Acked-by: Hans-Christian Egtvedt Cc: Haavard Skinnemoen Signed-off-by: Greg Kroah-Hartman prism54: set netdev type to "wlan" commit 8e3ffa471091c560deb6738ed9ab7445b7a5fd04 upstream. Userspace uses the netdev devtype for stuff like device naming and type detection. Be nice and set it. Remove the pointless #if/#endif around SET_NETDEV_DEV too. Signed-off-by: Dan Williams Signed-off-by: John W. Linville Signed-off-by: Greg Kroah-Hartman drm/ttm: Handle in-memory region copies commit 9a0599ddeae012a771bba5e23393fc52d8a59d89 upstream. Fix the case where the ttm pointer may be NULL causing a NULL pointer dereference. Signed-off-by: Jakob Bornecrantz Signed-off-by: Thomas Hellström Signed-off-by: Greg Kroah-Hartman drm/i915: flush cursors harder commit b2ea8ef559b4d94190009f3651b5b3ab7c05afd3 upstream. Apparently they need the same treatment as primary planes. This fixes modesetting failures because of stuck cursors (!) on Thomas' i830M machine. I've figured while at it I'll also roll it out for the ivb 3 pipe version of this function. I didn't do this for i845/i865 since Bspec says the update mechanism works differently, and there's some additional rules about what can be updated in which order. Tested-by: Thomas Richter Cc: Thomas Richter Cc: Ville Syrjälä Signed-off-by: Daniel Vetter Signed-off-by: Greg Kroah-Hartman drm/nouveau: when bailing out of a pushbuf ioctl, do not remove previous fence commit 9360bd1112d8874d21942e2ae74f5416b00a8db6 upstream. Signed-off-by: Ben Skeggs Signed-off-by: Greg Kroah-Hartman drm/radeon/si: fix define for MC_SEQ_TRAIN_WAKEUP_CNTL commit d5693761b2b4ff530c8af8af9ec55b6eae76e617 upstream. Typo in the register offset. Noticed-by: Sylvain BERTRAND Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman radeon: workaround pinning failure on low ram gpu commit 97b6ff6be9da7675aab339334fda996d6c5077d9 upstream. GPU with low amount of ram can fails at pinning new framebuffer before unpinning old one. On such failure, retry with unpinning old one before pinning new one allowing to work around the issue. This is somewhat ugly but only affect those old GPU we care about. Signed-off-by: Jerome Glisse Signed-off-by: Alex Deucher Signed-off-by: Greg Kroah-Hartman md: fix calculation of stacking limits on level change. commit 02e5f5c0a0f726e66e3d8506ea1691e344277969 upstream. The various ->run routines of md personalities assume that the 'queue' has been initialised by the blk_set_stacking_limits() call in md_alloc(). However when the level is changed (by level_store()) the ->run routine for the new level is called for an array which has already had the stacking limits modified. This can result in incorrect final settings. So call blk_set_stacking_limits() before ->run in level_store(). A specific consequence of this bug is that it causes discard_granularity to be set incorrectly when reshaping a RAID4 to a RAID0. This is suitable for any -stable kernel since 3.3 in which blk_set_stacking_limits() was introduced. Reported-and-tested-by: "Baldysiak, Pawel" Signed-off-by: NeilBrown Signed-off-by: Greg Kroah-Hartman powerpc/signals: Improved mark VSX not saved with small contexts fix commit ec67ad82814bee92251fd963bf01c7a173856555 upstream. In a recent patch: commit c13f20ac48328b05cd3b8c19e31ed6c132b44b42 Author: Michael Neuling powerpc/signals: Mark VSX not saved with small contexts We fixed an issue but an improved solution was later discussed after the patch was merged. Firstly, this patch doesn't handle the 64bit signals case, which could also hit this issue (but has never been reported). Secondly, the original patch isn't clear what MSR VSX should be set to. The new approach below always clears the MSR VSX bit (to indicate no VSX is in the context) and sets it only in the specific case where VSX is available (ie. when VSX has been used and the signal context passed has space to provide the state). This reverts the original patch and replaces it with the improved solution. It also adds a 64 bit version. Signed-off-by: Michael Neuling Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Greg Kroah-Hartman cpuset: Fix memory allocator deadlock commit 0fc0287c9ed1ffd3706f8b4d9b314aa102ef1245 upstream. Juri hit the below lockdep report: [ 4.303391] ====================================================== [ 4.303392] [ INFO: SOFTIRQ-safe -> SOFTIRQ-unsafe lock order detected ] [ 4.303394] 3.12.0-dl-peterz+ #144 Not tainted [ 4.303395] ------------------------------------------------------ [ 4.303397] kworker/u4:3/689 [HC0[0]:SC0[0]:HE0:SE1] is trying to acquire: [ 4.303399] (&p->mems_allowed_seq){+.+...}, at: [] new_slab+0x6c/0x290 [ 4.303417] [ 4.303417] and this task is already holding: [ 4.303418] (&(&q->__queue_lock)->rlock){..-...}, at: [] blk_execute_rq_nowait+0x5b/0x100 [ 4.303431] which would create a new lock dependency: [ 4.303432] (&(&q->__queue_lock)->rlock){..-...} -> (&p->mems_allowed_seq){+.+...} [ 4.303436] [ 4.303898] the dependencies between the lock to be acquired and SOFTIRQ-irq-unsafe lock: [ 4.303918] -> (&p->mems_allowed_seq){+.+...} ops: 2762 { [ 4.303922] HARDIRQ-ON-W at: [ 4.303923] [] __lock_acquire+0x65a/0x1ff0 [ 4.303926] [] lock_acquire+0x93/0x140 [ 4.303929] [] kthreadd+0x86/0x180 [ 4.303931] [] ret_from_fork+0x7c/0xb0 [ 4.303933] SOFTIRQ-ON-W at: [ 4.303933] [] __lock_acquire+0x68c/0x1ff0 [ 4.303935] [] lock_acquire+0x93/0x140 [ 4.303940] [] kthreadd+0x86/0x180 [ 4.303955] [] ret_from_fork+0x7c/0xb0 [ 4.303959] INITIAL USE at: [ 4.303960] [] __lock_acquire+0x344/0x1ff0 [ 4.303963] [] lock_acquire+0x93/0x140 [ 4.303966] [] kthreadd+0x86/0x180 [ 4.303969] [] ret_from_fork+0x7c/0xb0 [ 4.303972] } Which reports that we take mems_allowed_seq with interrupts enabled. A little digging found that this can only be from cpuset_change_task_nodemask(). This is an actual deadlock because an interrupt doing an allocation will hit get_mems_allowed()->...->__read_seqcount_begin(), which will spin forever waiting for the write side to complete. Cc: John Stultz Cc: Mel Gorman Reported-by: Juri Lelli Signed-off-by: Peter Zijlstra Tested-by: Juri Lelli Acked-by: Li Zefan Acked-by: Mel Gorman Signed-off-by: Tejun Heo Signed-off-by: Greg Kroah-Hartman ALSA: hda/realtek - Set pcbeep amp for ALC668 commit 9ad54547cf6f4410eba83bb95dfd2a0966718d6d upstream. Set the missing pcbeep default amp for ALC668. Signed-off-by: Kailang Yang Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman tracing: Allow events to have NULL strings commit 4e58e54754dc1fec21c3a9e824bc108b05fdf46e upstream. If an TRACE_EVENT() uses __assign_str() or __get_str on a NULL pointer then the following oops will happen: BUG: unable to handle kernel NULL pointer dereference at (null) IP: [] strlen+0x10/0x1a *pde = 00000000 ^M Oops: 0000 [#1] PREEMPT SMP Modules linked in: CPU: 1 PID: 0 Comm: swapper/1 Not tainted 3.13.0-rc1-test+ #2 Hardware name: /DG965MQ, BIOS MQ96510J.86A.0372.2006.0605.1717 06/05/2006^M task: f5cde9f0 ti: f5e5e000 task.ti: f5e5e000 EIP: 0060:[] EFLAGS: 00210046 CPU: 1 EIP is at strlen+0x10/0x1a EAX: 00000000 EBX: c2472da8 ECX: ffffffff EDX: c2472da8 ESI: c1c5e5fc EDI: 00000000 EBP: f5e5fe84 ESP: f5e5fe80 DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068 CR0: 8005003b CR2: 00000000 CR3: 01f32000 CR4: 000007d0 Stack: f5f18b90 f5e5feb8 c10687a8 0759004f 00000005 00000005 00000005 00200046 00000002 00000000 c1082a93 f56c7e28 c2472da8 c1082a93 f5e5fee4 c106bc61^M 00000000 c1082a93 00000000 00000000 00000001 00200046 00200082 00000000 Call Trace: [] ftrace_raw_event_lock+0x39/0xc0 [] ? ktime_get+0x29/0x69 [] ? ktime_get+0x29/0x69 [] lock_release+0x57/0x1a5 [] ? ktime_get+0x29/0x69 [] read_seqcount_begin.constprop.7+0x4d/0x75 [] ? ktime_get+0x29/0x69^M [] ktime_get+0x29/0x69 [] __tick_nohz_idle_enter+0x1e/0x426 [] ? lock_release_holdtime.part.19+0x48/0x4d [] ? time_hardirqs_off+0xe/0x28 [] ? trace_hardirqs_off_caller+0x3f/0xaf [] tick_nohz_idle_enter+0x59/0x62 [] cpu_startup_entry+0x64/0x192 [] start_secondary+0x277/0x27c Code: 90 89 c6 89 d0 88 c4 ac 38 e0 74 09 84 c0 75 f7 be 01 00 00 00 89 f0 48 5e 5d c3 55 89 e5 57 66 66 66 66 90 83 c9 ff 89 c7 31 c0 ae f7 d1 8d 41 ff 5f 5d c3 55 89 e5 57 66 66 66 66 90 31 ff EIP: [] strlen+0x10/0x1a SS:ESP 0068:f5e5fe80 CR2: 0000000000000000 ---[ end trace 01bc47bf519ec1b2 ]--- New tracepoints have been added that have allowed for NULL pointers being assigned to strings. To fix this, change the TRACE_EVENT() code to check for NULL and if it is, it will assign "(null)" to it instead (similar to what glibc printf does). Reported-by: Shuah Khan Reported-by: Jovi Zhangwei Link: http://lkml.kernel.org/r/CAGdX0WFeEuy+DtpsJzyzn0343qEEjLX97+o1VREFkUEhndC+5Q@mail.gmail.com Link: http://lkml.kernel.org/r/528D6972.9010702@samsung.com Fixes: 9cbf117662e2 ("tracing/events: provide string with undefined size support") Signed-off-by: Steven Rostedt Signed-off-by: Greg Kroah-Hartman Input: i8042 - add PNP modaliases commit 78551277e4df57864b0b0e7f85c23ede2be2edb8 upstream. This allows the module to be autoloaded in the common case. In order to work on non-PnP systems the module should be compiled in or loaded unconditionally at boot (c.f. modules-load.d(5)), as before. Signed-off-by: Tom Gundersen Signed-off-by: Dmitry Torokhov Signed-off-by: Greg Kroah-Hartman KVM: perform an invalid memslot step for gpa base change commit 12d6e7538e2d418c08f082b1b44ffa5fb7270ed8 upstream. PPC must flush all translations before the new memory slot is visible. Signed-off-by: Marcelo Tosatti Signed-off-by: Avi Kivity Cc: Luis Henriques Signed-off-by: Greg Kroah-Hartman KVM: Fix iommu map/unmap to handle memory slot moves commit e40f193f5bb022e927a57a4f5d5194e4f12ddb74 upstream. The iommu integration into memory slots expects memory slots to be added or removed and doesn't handle the move case. We can unmap slots from the iommu after we mark them invalid and map them before installing the final memslot array. Also re-order the kmemdup vs map so we don't leave iommu mappings if we get ENOMEM. Reviewed-by: Gleb Natapov Signed-off-by: Alex Williamson Signed-off-by: Marcelo Tosatti Cc: Luis Henriques Signed-off-by: Greg Kroah-Hartman ftrace: Fix function graph with loading of modules commit 8a56d7761d2d041ae5e8215d20b4167d8aa93f51 upstream. Commit 8c4f3c3fa9681 "ftrace: Check module functions being traced on reload" fixed module loading and unloading with respect to function tracing, but it missed the function graph tracer. If you perform the following # cd /sys/kernel/debug/tracing # echo function_graph > current_tracer # modprobe nfsd # echo nop > current_tracer You'll get the following oops message: ------------[ cut here ]------------ WARNING: CPU: 2 PID: 2910 at /linux.git/kernel/trace/ftrace.c:1640 __ftrace_hash_rec_update.part.35+0x168/0x1b9() Modules linked in: nfsd exportfs nfs_acl lockd ipt_MASQUERADE sunrpc ip6t_REJECT nf_conntrack_ipv6 nf_defrag_ipv6 ip6table_filter ip6_tables uinput snd_hda_codec_idt CPU: 2 PID: 2910 Comm: bash Not tainted 3.13.0-rc1-test #7 Hardware name: To Be Filled By O.E.M. To Be Filled By O.E.M./To be filled by O.E.M., BIOS SDBLI944.86P 05/08/2007 0000000000000668 ffff8800787efcf8 ffffffff814fe193 ffff88007d500000 0000000000000000 ffff8800787efd38 ffffffff8103b80a 0000000000000668 ffffffff810b2b9a ffffffff81a48370 0000000000000001 ffff880037aea000 Call Trace: [] dump_stack+0x4f/0x7c [] warn_slowpath_common+0x81/0x9b [] ? __ftrace_hash_rec_update.part.35+0x168/0x1b9 [] warn_slowpath_null+0x1a/0x1c [] __ftrace_hash_rec_update.part.35+0x168/0x1b9 [] ? __mutex_lock_slowpath+0x364/0x364 [] ftrace_shutdown+0xd7/0x12b [] unregister_ftrace_graph+0x49/0x78 [] graph_trace_reset+0xe/0x10 [] tracing_set_tracer+0xa7/0x26a [] tracing_set_trace_write+0x8b/0xbd [] ? ftrace_return_to_handler+0xb2/0xde [] ? __sb_end_write+0x5e/0x5e [] vfs_write+0xab/0xf6 [] ftrace_graph_caller+0x85/0x85 [] SyS_write+0x59/0x82 [] ftrace_graph_caller+0x85/0x85 [] system_call_fastpath+0x16/0x1b ---[ end trace 940358030751eafb ]--- The above mentioned commit didn't go far enough. Well, it covered the function tracer by adding checks in __register_ftrace_function(). The problem is that the function graph tracer circumvents that (for a slight efficiency gain when function graph trace is running with a function tracer. The gain was not worth this). The problem came with ftrace_startup() which should always be called after __register_ftrace_function(), if you want this bug to be completely fixed. Anyway, this solution moves __register_ftrace_function() inside of ftrace_startup() and removes the need to call them both. Reported-by: Dave Wysochanski Fixes: ed926f9b35cd ("ftrace: Use counters to enable functions to trace") Signed-off-by: Steven Rostedt Signed-off-by: Greg Kroah-Hartman media: lirc_zilog: Don't use dynamic static allocation commit ac5b4b6bf0c84c48d7e2e3fce22e35b04282ba76 upstream. Dynamic static allocation is evil, as Kernel stack is too low, and ompilation complains about it on some archs: drivers/staging/media/lirc/lirc_zilog.c:967:1: warning: 'read' uses dynamic stack allocation [enabled by default] Instead, let's enforce a limit for the buffer to be 64. That should be more than enough. Signed-off-by: Mauro Carvalho Chehab Reviewed-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman HID: roccat: fix Coverity CID 141438 commit 7be63f20b00840a6f1c718dcee00855688d64acd upstream. Add missing switch breaks. Signed-off-by: Stefan Achatz Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman HID: apple: option to swap the 'Option' ("Alt") and 'Command' ("Flag") keys. commit 43c831468b3d26dbe8f2e061ccaf1abaf9cc1b8b upstream. Use case: people who use both Apple and PC keyboards regularly, and desire to keep&use their PC muscle memory. A particular use case: an Apple compact external keyboard connected to a PC laptop. (This use case can't be covered well by X.org key remappings etc.) Signed-off-by: Nanno Langstraat Signed-off-by: Jiri Kosina Signed-off-by: Greg Kroah-Hartman --- Documentation/sysctl/kernel.txt | 25 +++++-- Makefile | 2 +- arch/arm/mach-integrator/integrator_cp.c | 3 +- arch/arm/mach-sa1100/assabet.c | 3 + arch/avr32/boot/u-boot/head.S | 35 ++++++++-- arch/avr32/kernel/entry-avr32b.S | 3 +- arch/avr32/kernel/head.S | 20 ------ arch/powerpc/kernel/signal_32.c | 16 ++--- arch/powerpc/kernel/signal_64.c | 6 ++ drivers/ata/ahci.c | 2 + drivers/ata/libahci.c | 16 +++++ drivers/ata/libata-core.c | 1 + drivers/ata/libata-transport.c | 16 ++--- drivers/block/loop.c | 4 +- drivers/block/xen-blkback/blkback.c | 3 +- drivers/gpu/drm/i915/intel_display.c | 4 ++ drivers/gpu/drm/nouveau/nouveau_gem.c | 3 +- drivers/gpu/drm/radeon/radeon_legacy_crtc.c | 28 ++++++++ drivers/gpu/drm/radeon/sid.h | 2 +- drivers/gpu/drm/ttm/ttm_bo_util.c | 4 +- drivers/hid/hid-apple.c | 22 ++++++ drivers/hid/hid-roccat-kovaplus.c | 4 ++ drivers/infiniband/hw/ipath/ipath_user_sdma.c | 7 +- drivers/input/serio/i8042-x86ia64io.h | 2 + drivers/md/dm-table.c | 18 ++++- drivers/md/md.c | 1 + drivers/mtd/nand/gpmi-nand/gpmi-nand.c | 4 +- drivers/mtd/nand/nand_base.c | 15 +++- drivers/net/can/flexcan.c | 12 ---- drivers/net/wireless/mwifiex/sdio.c | 3 + drivers/net/wireless/prism54/islpci_dev.c | 7 +- drivers/net/wireless/rt2x00/rt2400pci.c | 2 +- drivers/net/wireless/rtlwifi/rtl8192cu/mac.c | 6 +- drivers/net/wireless/rtlwifi/rtl8192cu/trx.c | 8 +-- drivers/net/wireless/rtlwifi/rtl8192de/trx.c | 2 +- drivers/net/wireless/rtlwifi/rtl8192se/rf.c | 2 +- drivers/net/wireless/rtlwifi/rtl8192se/trx.c | 2 +- drivers/pci/pcie/portdrv_pci.c | 1 - drivers/s390/net/qeth_core_main.c | 6 +- drivers/staging/media/lirc/lirc_zilog.c | 12 +++- drivers/staging/tidspbridge/Kconfig | 2 +- drivers/staging/vt6656/baseband.c | 11 +++ drivers/staging/vt6656/rndis.h | 1 + drivers/target/iscsi/iscsi_target_auth.c | 5 +- drivers/target/iscsi/iscsi_target_nego.c | 2 +- drivers/video/backlight/atmel-pwm-bl.c | 4 +- fs/devpts/inode.c | 1 + fs/ext4/xattr.c | 1 + include/linux/mtd/map.h | 4 +- include/trace/ftrace.h | 5 +- kernel/audit.c | 5 +- kernel/cpuset.c | 8 ++- kernel/power/snapshot.c | 6 +- kernel/time/alarmtimer.c | 4 +- kernel/trace/ftrace.c | 68 +++++++++---------- lib/vsprintf.c | 33 ++++++++- security/selinux/netlabel.c | 6 +- sound/pci/hda/patch_realtek.c | 1 + sound/soc/blackfin/bf5xx-i2s.c | 1 + sound/soc/codecs/ak4642.c | 2 +- sound/soc/codecs/wm8962.c | 2 + virt/kvm/kvm_main.c | 25 ++++--- 62 files changed, 362 insertions(+), 167 deletions(-) diff --git a/Documentation/sysctl/kernel.txt b/Documentation/sysctl/kernel.txt index a419f5e3143..ff11aae7c0b 100644 --- a/Documentation/sysctl/kernel.txt +++ b/Documentation/sysctl/kernel.txt @@ -298,13 +298,24 @@ Default value is "/sbin/hotplug". kptr_restrict: This toggle indicates whether restrictions are placed on -exposing kernel addresses via /proc and other interfaces. When -kptr_restrict is set to (0), there are no restrictions. When -kptr_restrict is set to (1), the default, kernel pointers -printed using the %pK format specifier will be replaced with 0's -unless the user has CAP_SYSLOG. When kptr_restrict is set to -(2), kernel pointers printed using %pK will be replaced with 0's -regardless of privileges. +exposing kernel addresses via /proc and other interfaces. + +When kptr_restrict is set to (0), the default, there are no restrictions. + +When kptr_restrict is set to (1), kernel pointers printed using the %pK +format specifier will be replaced with 0's unless the user has CAP_SYSLOG +and effective user and group ids are equal to the real ids. This is +because %pK checks are done at read() time rather than open() time, so +if permissions are elevated between the open() and the read() (e.g via +a setuid binary) then %pK will not leak kernel pointers to unprivileged +users. Note, this is a temporary solution only. The correct long-term +solution is to do the permission checks at open() time. Consider removing +world read permissions from files that use %pK, and using dmesg_restrict +to protect against uses of %pK in dmesg(8) if leaking kernel pointer +values to unprivileged users is a concern. + +When kptr_restrict is set to (2), kernel pointers printed using +%pK will be replaced with 0's regardless of privileges. ============================================================== diff --git a/Makefile b/Makefile index aba4f850401..cc33c605162 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 4 -SUBLEVEL = 71 +SUBLEVEL = 72 EXTRAVERSION = NAME = Saber-toothed Squirrel diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c index 48a115a91d9..ecc33bc4c96 100644 --- a/arch/arm/mach-integrator/integrator_cp.c +++ b/arch/arm/mach-integrator/integrator_cp.c @@ -366,7 +366,8 @@ static AMBA_APB_DEVICE(aaci, "mb:1d", 0, INTEGRATOR_CP_AACI_BASE, static void cp_clcd_enable(struct clcd_fb *fb) { struct fb_var_screeninfo *var = &fb->fb.var; - u32 val = CM_CTRL_STATIC1 | CM_CTRL_STATIC2; + u32 val = CM_CTRL_STATIC1 | CM_CTRL_STATIC2 + | CM_CTRL_LCDEN0 | CM_CTRL_LCDEN1; if (var->bits_per_pixel <= 8 || (var->bits_per_pixel == 16 && var->green.length == 5)) diff --git a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-sa1100/assabet.c index 375d3f779a8..82636701bf0 100644 --- a/arch/arm/mach-sa1100/assabet.c +++ b/arch/arm/mach-sa1100/assabet.c @@ -509,6 +509,9 @@ static void __init assabet_map_io(void) * Its called GPCLKR0 in my SA1110 manual. */ Ser1SDCR0 |= SDCR0_SUS; + MSC1 = (MSC1 & ~0xffff) | + MSC_NonBrst | MSC_32BitStMem | + MSC_RdAcc(2) | MSC_WrAcc(2) | MSC_Rec(0); if (!machine_has_neponset()) sa1100_register_uart_fns(&assabet_port_fns); diff --git a/arch/avr32/boot/u-boot/head.S b/arch/avr32/boot/u-boot/head.S index 4488fa27fe9..2ffc298f061 100644 --- a/arch/avr32/boot/u-boot/head.S +++ b/arch/avr32/boot/u-boot/head.S @@ -8,6 +8,8 @@ * published by the Free Software Foundation. */ #include +#include +#include /* * The kernel is loaded where we want it to be and all caches @@ -20,11 +22,6 @@ .section .init.text,"ax" .global _start _start: - /* Check if the boot loader actually provided a tag table */ - lddpc r0, magic_number - cp.w r12, r0 - brne no_tag_table - /* Initialize .bss */ lddpc r2, bss_start_addr lddpc r3, end_addr @@ -34,6 +31,25 @@ _start: cp r2, r3 brlo 1b + /* Initialize status register */ + lddpc r0, init_sr + mtsr SYSREG_SR, r0 + + /* Set initial stack pointer */ + lddpc sp, stack_addr + sub sp, -THREAD_SIZE + +#ifdef CONFIG_FRAME_POINTER + /* Mark last stack frame */ + mov lr, 0 + mov r7, 0 +#endif + + /* Check if the boot loader actually provided a tag table */ + lddpc r0, magic_number + cp.w r12, r0 + brne no_tag_table + /* * Save the tag table address for later use. This must be done * _after_ .bss has been initialized... @@ -53,8 +69,15 @@ bss_start_addr: .long __bss_start end_addr: .long _end +init_sr: + .long 0x007f0000 /* Supervisor mode, everything masked */ +stack_addr: + .long init_thread_union +panic_addr: + .long panic no_tag_table: sub r12, pc, (. - 2f) - bral panic + /* branch to panic() which can be far away with that construct */ + lddpc pc, panic_addr 2: .asciz "Boot loader didn't provide correct magic number\n" diff --git a/arch/avr32/kernel/entry-avr32b.S b/arch/avr32/kernel/entry-avr32b.S index 169268c40ae..a91e8980a59 100644 --- a/arch/avr32/kernel/entry-avr32b.S +++ b/arch/avr32/kernel/entry-avr32b.S @@ -399,9 +399,10 @@ handle_critical: /* We should never get here... */ bad_return: sub r12, pc, (. - 1f) - bral panic + lddpc pc, 2f .align 2 1: .asciz "Return from critical exception!" +2: .long panic .align 1 do_bus_error_write: diff --git a/arch/avr32/kernel/head.S b/arch/avr32/kernel/head.S index 6163bd0acb9..59eae6dfbed 100644 --- a/arch/avr32/kernel/head.S +++ b/arch/avr32/kernel/head.S @@ -10,33 +10,13 @@ #include #include -#include -#include .section .init.text,"ax" .global kernel_entry kernel_entry: - /* Initialize status register */ - lddpc r0, init_sr - mtsr SYSREG_SR, r0 - - /* Set initial stack pointer */ - lddpc sp, stack_addr - sub sp, -THREAD_SIZE - -#ifdef CONFIG_FRAME_POINTER - /* Mark last stack frame */ - mov lr, 0 - mov r7, 0 -#endif - /* Start the show */ lddpc pc, kernel_start_addr .align 2 -init_sr: - .long 0x007f0000 /* Supervisor mode, everything masked */ -stack_addr: - .long init_thread_union kernel_start_addr: .long start_kernel diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index e6de787956c..32e2c81106e 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c @@ -447,6 +447,12 @@ static int save_user_regs(struct pt_regs *regs, struct mcontext __user *frame, #endif /* CONFIG_ALTIVEC */ if (copy_fpr_to_user(&frame->mc_fregs, current)) return 1; + + /* + * Clear the MSR VSX bit to indicate there is no valid state attached + * to this context, except in the specific case below where we set it. + */ + msr &= ~MSR_VSX; #ifdef CONFIG_VSX /* * Copy VSR 0-31 upper half from thread_struct to local @@ -459,15 +465,7 @@ static int save_user_regs(struct pt_regs *regs, struct mcontext __user *frame, if (copy_vsx_to_user(&frame->mc_vsregs, current)) return 1; msr |= MSR_VSX; - } else if (!ctx_has_vsx_region) - /* - * With a small context structure we can't hold the VSX - * registers, hence clear the MSR value to indicate the state - * was not saved. - */ - msr &= ~MSR_VSX; - - + } #endif /* CONFIG_VSX */ #ifdef CONFIG_SPE /* save spe registers */ diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c index 2692efdb154..3ad1b508b3c 100644 --- a/arch/powerpc/kernel/signal_64.c +++ b/arch/powerpc/kernel/signal_64.c @@ -117,6 +117,12 @@ static long setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, flush_fp_to_thread(current); /* copy fpr regs and fpscr */ err |= copy_fpr_to_user(&sc->fp_regs, current); + + /* + * Clear the MSR VSX bit to indicate there is no valid state attached + * to this context, except in the specific case below where we set it. + */ + msr &= ~MSR_VSX; #ifdef CONFIG_VSX /* * Copy VSX low doubleword to local buffer for formatting, diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index aeb8220072d..60662545cd1 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -402,6 +402,8 @@ static const struct pci_device_id ahci_pci_tbl[] = { .driver_data = board_ahci_yes_fbs }, /* 88se9172 on some Gigabyte */ { PCI_DEVICE(0x1b4b, 0x91a3), .driver_data = board_ahci_yes_fbs }, + { PCI_DEVICE(0x1b4b, 0x9230), + .driver_data = board_ahci_yes_fbs }, /* Promise */ { PCI_VDEVICE(PROMISE, 0x3f20), board_ahci }, /* PDC42819 */ diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index 47a1fb85ff0..60f41cd2c33 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c @@ -1249,9 +1249,11 @@ int ahci_do_softreset(struct ata_link *link, unsigned int *class, { struct ata_port *ap = link->ap; struct ahci_host_priv *hpriv = ap->host->private_data; + struct ahci_port_priv *pp = ap->private_data; const char *reason = NULL; unsigned long now, msecs; struct ata_taskfile tf; + bool fbs_disabled = false; int rc; DPRINTK("ENTER\n"); @@ -1261,6 +1263,16 @@ int ahci_do_softreset(struct ata_link *link, unsigned int *class, if (rc && rc != -EOPNOTSUPP) ata_link_warn(link, "failed to reset engine (errno=%d)\n", rc); + /* + * According to AHCI-1.2 9.3.9: if FBS is enable, software shall + * clear PxFBS.EN to '0' prior to issuing software reset to devices + * that is attached to port multiplier. + */ + if (!ata_is_host_link(link) && pp->fbs_enabled) { + ahci_disable_fbs(ap); + fbs_disabled = true; + } + ata_tf_init(link->device, &tf); /* issue the first D2H Register FIS */ @@ -1301,6 +1313,10 @@ int ahci_do_softreset(struct ata_link *link, unsigned int *class, } else *class = ahci_dev_classify(ap); + /* re-enable FBS if disabled before */ + if (fbs_disabled) + ahci_enable_fbs(ap); + DPRINTK("EXIT, class=%u\n", *class); return 0; diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 9cf09ae8cf1..cd20cf1ef3e 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4074,6 +4074,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { { "TORiSAN DVD-ROM DRD-N216", NULL, ATA_HORKAGE_MAX_SEC_128 }, { "QUANTUM DAT DAT72-000", NULL, ATA_HORKAGE_ATAPI_MOD16_DMA }, { "Slimtype DVD A DS8A8SH", NULL, ATA_HORKAGE_MAX_SEC_LBA48 }, + { "Slimtype DVD A DS8A9SH", NULL, ATA_HORKAGE_MAX_SEC_LBA48 }, /* Devices we expect to fail diagnostics */ diff --git a/drivers/ata/libata-transport.c b/drivers/ata/libata-transport.c index c3419048537..92156774904 100644 --- a/drivers/ata/libata-transport.c +++ b/drivers/ata/libata-transport.c @@ -319,25 +319,25 @@ int ata_tport_add(struct device *parent, /* * ATA link attributes */ +static int noop(int x) { return x; } - -#define ata_link_show_linkspeed(field) \ +#define ata_link_show_linkspeed(field, format) \ static ssize_t \ show_ata_link_##field(struct device *dev, \ struct device_attribute *attr, char *buf) \ { \ struct ata_link *link = transport_class_to_link(dev); \ \ - return sprintf(buf,"%s\n", sata_spd_string(fls(link->field))); \ + return sprintf(buf, "%s\n", sata_spd_string(format(link->field))); \ } -#define ata_link_linkspeed_attr(field) \ - ata_link_show_linkspeed(field) \ +#define ata_link_linkspeed_attr(field, format) \ + ata_link_show_linkspeed(field, format) \ static DEVICE_ATTR(field, S_IRUGO, show_ata_link_##field, NULL) -ata_link_linkspeed_attr(hw_sata_spd_limit); -ata_link_linkspeed_attr(sata_spd_limit); -ata_link_linkspeed_attr(sata_spd); +ata_link_linkspeed_attr(hw_sata_spd_limit, fls); +ata_link_linkspeed_attr(sata_spd_limit, fls); +ata_link_linkspeed_attr(sata_spd, noop); static DECLARE_TRANSPORT_CLASS(ata_link_class, diff --git a/drivers/block/loop.c b/drivers/block/loop.c index a4ddbae2e10..462fd182180 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -1636,7 +1636,7 @@ static int loop_add(struct loop_device **l, int i) lo->lo_queue = blk_alloc_queue(GFP_KERNEL); if (!lo->lo_queue) - goto out_free_dev; + goto out_free_idr; disk = lo->lo_disk = alloc_disk(1 << part_shift); if (!disk) @@ -1680,6 +1680,8 @@ static int loop_add(struct loop_device **l, int i) out_free_queue: blk_cleanup_queue(lo->lo_queue); +out_free_idr: + idr_remove(&loop_index_idr, i); out_free_dev: kfree(lo); out: diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index 4ed7bf9b4fd..0ed5df4d3e9 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c @@ -401,6 +401,8 @@ static int dispatch_discard_io(struct xen_blkif *blkif, unsigned long secure; struct phys_req preq; + xen_blkif_get(blkif); + preq.sector_number = req->u.discard.sector_number; preq.nr_sects = req->u.discard.nr_sectors; @@ -413,7 +415,6 @@ static int dispatch_discard_io(struct xen_blkif *blkif, } blkif->st_ds_req++; - xen_blkif_get(blkif); secure = (blkif->vbd.discard_secure && (req->u.discard.flag & BLKIF_DISCARD_SECURE)) ? BLKDEV_DISCARD_SECURE : 0; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 0e359225a19..5647ce4b3ec 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -6377,7 +6377,9 @@ static void i9xx_update_cursor(struct drm_crtc *crtc, u32 base) intel_crtc->cursor_visible = visible; } /* and commit changes on next vblank */ + POSTING_READ(CURCNTR(pipe)); I915_WRITE(CURBASE(pipe), base); + POSTING_READ(CURBASE(pipe)); } static void ivb_update_cursor(struct drm_crtc *crtc, u32 base) @@ -6402,7 +6404,9 @@ static void ivb_update_cursor(struct drm_crtc *crtc, u32 base) intel_crtc->cursor_visible = visible; } /* and commit changes on next vblank */ + POSTING_READ(CURCNTR_IVB(pipe)); I915_WRITE(CURBASE_IVB(pipe), base); + POSTING_READ(CURBASE_IVB(pipe)); } /* If no-part of the cursor is visible on the framebuffer, then the GPU may hang... */ diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index ed52a6f4161..2f46bbfbb1f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -281,7 +281,8 @@ validate_fini_list(struct list_head *list, struct nouveau_fence *fence) list_for_each_safe(entry, tmp, list) { nvbo = list_entry(entry, struct nouveau_bo, entry); - nouveau_bo_fence(nvbo, fence); + if (likely(fence)) + nouveau_bo_fence(nvbo, fence); if (unlikely(nvbo->validate_mapped)) { ttm_bo_kunmap(&nvbo->kmap); diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c index 9760e5addcc..b44bbf50760 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c @@ -416,6 +416,7 @@ int radeon_crtc_do_set_base(struct drm_crtc *crtc, /* Pin framebuffer & get tilling informations */ obj = radeon_fb->obj; rbo = gem_to_radeon_bo(obj); +retry: r = radeon_bo_reserve(rbo, false); if (unlikely(r != 0)) return r; @@ -424,6 +425,33 @@ int radeon_crtc_do_set_base(struct drm_crtc *crtc, &base); if (unlikely(r != 0)) { radeon_bo_unreserve(rbo); + + /* On old GPU like RN50 with little vram pining can fails because + * current fb is taking all space needed. So instead of unpining + * the old buffer after pining the new one, first unpin old one + * and then retry pining new one. + * + * As only master can set mode only master can pin and it is + * unlikely the master client will race with itself especialy + * on those old gpu with single crtc. + * + * We don't shutdown the display controller because new buffer + * will end up in same spot. + */ + if (!atomic && fb && fb != crtc->fb) { + struct radeon_bo *old_rbo; + unsigned long nsize, osize; + + old_rbo = gem_to_radeon_bo(to_radeon_framebuffer(fb)->obj); + osize = radeon_bo_size(old_rbo); + nsize = radeon_bo_size(rbo); + if (nsize <= osize && !radeon_bo_reserve(old_rbo, false)) { + radeon_bo_unpin(old_rbo); + radeon_bo_unreserve(old_rbo); + fb = NULL; + goto retry; + } + } return -EINVAL; } radeon_bo_get_tiling_flags(rbo, &tiling_flags, NULL); diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h index 1767ae7f76c..a9fcbe44b3e 100644 --- a/drivers/gpu/drm/radeon/sid.h +++ b/drivers/gpu/drm/radeon/sid.h @@ -165,7 +165,7 @@ #define NOOFGROUPS_SHIFT 12 #define NOOFGROUPS_MASK 0x00001000 -#define MC_SEQ_TRAIN_WAKEUP_CNTL 0x2808 +#define MC_SEQ_TRAIN_WAKEUP_CNTL 0x28e8 #define TRAIN_DONE_D0 (1 << 30) #define TRAIN_DONE_D1 (1 << 31) diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index f8187ead7b3..2d692626903 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -342,7 +342,9 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo, if (old_iomap == NULL && ttm == NULL) goto out2; - if (ttm->state == tt_unpopulated) { + /* TTM might be null for moves within the same region. + */ + if (ttm && ttm->state == tt_unpopulated) { ret = ttm->bdev->driver->ttm_tt_populate(ttm); if (ret) goto out1; diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c index 899c71200bd..9421f643544 100644 --- a/drivers/hid/hid-apple.c +++ b/drivers/hid/hid-apple.c @@ -48,6 +48,12 @@ module_param(iso_layout, uint, 0644); MODULE_PARM_DESC(iso_layout, "Enable/Disable hardcoded ISO-layout of the keyboard. " "(0 = disabled, [1] = enabled)"); +static unsigned int swap_opt_cmd = 0; +module_param(swap_opt_cmd, uint, 0644); +MODULE_PARM_DESC(swap_opt_cmd, "Swap the Option (\"Alt\") and Command (\"Flag\") keys. " + "(For people who want to keep Windows PC keyboard muscle memory. " + "[0] = as-is, Mac layout. 1 = swapped, Windows layout.)"); + struct apple_sc { unsigned long quirks; unsigned int fn_on; @@ -152,6 +158,14 @@ static const struct apple_key_translation apple_iso_keyboard[] = { { } }; +static const struct apple_key_translation swapped_option_cmd_keys[] = { + { KEY_LEFTALT, KEY_LEFTMETA }, + { KEY_LEFTMETA, KEY_LEFTALT }, + { KEY_RIGHTALT, KEY_RIGHTMETA }, + { KEY_RIGHTMETA,KEY_RIGHTALT }, + { } +}; + static const struct apple_key_translation *apple_find_translation( const struct apple_key_translation *table, u16 from) { @@ -244,6 +258,14 @@ static int hidinput_apple_event(struct hid_device *hid, struct input_dev *input, } } + if (swap_opt_cmd) { + trans = apple_find_translation(swapped_option_cmd_keys, usage->code); + if (trans) { + input_event(input, usage->type, trans->to, value); + return 1; + } + } + return 0; } diff --git a/drivers/hid/hid-roccat-kovaplus.c b/drivers/hid/hid-roccat-kovaplus.c index 112d934132c..1973cff8ee3 100644 --- a/drivers/hid/hid-roccat-kovaplus.c +++ b/drivers/hid/hid-roccat-kovaplus.c @@ -623,9 +623,13 @@ static void kovaplus_keep_values_up_to_date(struct kovaplus_device *kovaplus, break; case KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_CPI: kovaplus->actual_cpi = kovaplus_convert_event_cpi(button_report->data1); + break; case KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_SENSITIVITY: kovaplus->actual_x_sensitivity = button_report->data1; kovaplus->actual_y_sensitivity = button_report->data2; + break; + default: + break; } } diff --git a/drivers/infiniband/hw/ipath/ipath_user_sdma.c b/drivers/infiniband/hw/ipath/ipath_user_sdma.c index f5cb13b2144..cc04b7ba348 100644 --- a/drivers/infiniband/hw/ipath/ipath_user_sdma.c +++ b/drivers/infiniband/hw/ipath/ipath_user_sdma.c @@ -280,9 +280,7 @@ static int ipath_user_sdma_pin_pages(const struct ipath_devdata *dd, int j; int ret; - ret = get_user_pages(current, current->mm, addr, - npages, 0, 1, pages, NULL); - + ret = get_user_pages_fast(addr, npages, 0, pages); if (ret != npages) { int i; @@ -811,10 +809,7 @@ int ipath_user_sdma_writev(struct ipath_devdata *dd, while (dim) { const int mxp = 8; - down_write(¤t->mm->mmap_sem); ret = ipath_user_sdma_queue_pkts(dd, pq, &list, iov, dim, mxp); - up_write(¤t->mm->mmap_sem); - if (ret <= 0) goto done_unlock; else { diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index 5f306f79da0..0ec9abbe31f 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -765,6 +765,7 @@ static struct pnp_device_id pnp_kbd_devids[] = { { .id = "CPQA0D7", .driver_data = 0 }, { .id = "", }, }; +MODULE_DEVICE_TABLE(pnp, pnp_kbd_devids); static struct pnp_driver i8042_pnp_kbd_driver = { .name = "i8042 kbd", @@ -786,6 +787,7 @@ static struct pnp_device_id pnp_aux_devids[] = { { .id = "SYN0801", .driver_data = 0 }, { .id = "", }, }; +MODULE_DEVICE_TABLE(pnp, pnp_aux_devids); static struct pnp_driver i8042_pnp_aux_driver = { .name = "i8042 aux", diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 2e227fbf162..b9e9ed4df80 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -581,14 +581,28 @@ static int adjoin(struct dm_table *table, struct dm_target *ti) /* * Used to dynamically allocate the arg array. + * + * We do first allocation with GFP_NOIO because dm-mpath and dm-thin must + * process messages even if some device is suspended. These messages have a + * small fixed number of arguments. + * + * On the other hand, dm-switch needs to process bulk data using messages and + * excessive use of GFP_NOIO could cause trouble. */ static char **realloc_argv(unsigned *array_size, char **old_argv) { char **argv; unsigned new_size; + gfp_t gfp; - new_size = *array_size ? *array_size * 2 : 64; - argv = kmalloc(new_size * sizeof(*argv), GFP_KERNEL); + if (*array_size) { + new_size = *array_size * 2; + gfp = GFP_KERNEL; + } else { + new_size = 8; + gfp = GFP_NOIO; + } + argv = kmalloc(new_size * sizeof(*argv), gfp); if (argv) { memcpy(argv, old_argv, *array_size * sizeof(*argv)); *array_size = new_size; diff --git a/drivers/md/md.c b/drivers/md/md.c index 69c616f2ae5..a4782e324b5 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -3497,6 +3497,7 @@ level_store(struct mddev *mddev, const char *buf, size_t len) mddev->in_sync = 1; del_timer_sync(&mddev->safemode_timer); } + blk_set_stacking_limits(&mddev->queue->limits); pers->run(mddev); mddev_resume(mddev); set_bit(MD_CHANGE_DEVS, &mddev->flags); diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c index 9ec51cec2e1..0f000e607cd 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c +++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c @@ -227,8 +227,6 @@ static void dma_irq_callback(void *param) struct gpmi_nand_data *this = param; struct completion *dma_c = &this->dma_done; - complete(dma_c); - switch (this->dma_type) { case DMA_FOR_COMMAND: dma_unmap_sg(this->dev, &this->cmd_sgl, 1, DMA_TO_DEVICE); @@ -253,6 +251,8 @@ static void dma_irq_callback(void *param) default: pr_err("in wrong DMA operation.\n"); } + + complete(dma_c); } int start_dma_without_bch_irq(struct gpmi_nand_data *this, diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index eb9f5fb02ee..e50a0b48145 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -2888,10 +2888,21 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip, sanitize_string(p->model, sizeof(p->model)); if (!mtd->name) mtd->name = p->model; + mtd->writesize = le32_to_cpu(p->byte_per_page); - mtd->erasesize = le32_to_cpu(p->pages_per_block) * mtd->writesize; + + /* + * pages_per_block and blocks_per_lun may not be a power-of-2 size + * (don't ask me who thought of this...). MTD assumes that these + * dimensions will be power-of-2, so just truncate the remaining area. + */ + mtd->erasesize = 1 << (fls(le32_to_cpu(p->pages_per_block)) - 1); + mtd->erasesize *= mtd->writesize; + mtd->oobsize = le16_to_cpu(p->spare_bytes_per_page); - chip->chipsize = le32_to_cpu(p->blocks_per_lun); + + /* See erasesize comment */ + chip->chipsize = 1 << (fls(le32_to_cpu(p->blocks_per_lun)) - 1); chip->chipsize *= (uint64_t)mtd->erasesize * p->lun_count; *busw = 0; if (le16_to_cpu(p->features) & 1) diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index e2131ca64a5..eb4014a25d3 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -667,7 +667,6 @@ static int flexcan_chip_start(struct net_device *dev) { struct flexcan_priv *priv = netdev_priv(dev); struct flexcan_regs __iomem *regs = priv->base; - unsigned int i; int err; u32 reg_mcr, reg_ctrl; @@ -735,17 +734,6 @@ static int flexcan_chip_start(struct net_device *dev) netdev_dbg(dev, "%s: writing ctrl=0x%08x", __func__, reg_ctrl); flexcan_write(reg_ctrl, ®s->ctrl); - for (i = 0; i < ARRAY_SIZE(regs->cantxfg); i++) { - flexcan_write(0, ®s->cantxfg[i].can_ctrl); - flexcan_write(0, ®s->cantxfg[i].can_id); - flexcan_write(0, ®s->cantxfg[i].data[0]); - flexcan_write(0, ®s->cantxfg[i].data[1]); - - /* put MB into rx queue */ - flexcan_write(FLEXCAN_MB_CNT_CODE(0x4), - ®s->cantxfg[i].can_ctrl); - } - /* Abort any pending TX, mark Mailbox as INACTIVE */ flexcan_write(FLEXCAN_MB_CNT_CODE(0x4), ®s->cantxfg[FLEXCAN_TX_BUF_ID].can_ctrl); diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c index 4be8ccc8e9a..daf55ba81c6 100644 --- a/drivers/net/wireless/mwifiex/sdio.c +++ b/drivers/net/wireless/mwifiex/sdio.c @@ -938,7 +938,10 @@ static int mwifiex_decode_rx_packet(struct mwifiex_adapter *adapter, struct sk_buff *skb, u32 upld_typ) { u8 *cmd_buf; + __le16 *curr_ptr = (__le16 *)skb->data; + u16 pkt_len = le16_to_cpu(*curr_ptr); + skb_trim(skb, pkt_len); skb_pull(skb, INTF_HEADER_LEN); switch (upld_typ) { diff --git a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c index 5970ff6f40c..d498b02f2d0 100644 --- a/drivers/net/wireless/prism54/islpci_dev.c +++ b/drivers/net/wireless/prism54/islpci_dev.c @@ -811,6 +811,10 @@ static const struct net_device_ops islpci_netdev_ops = { .ndo_validate_addr = eth_validate_addr, }; +static struct device_type wlan_type = { + .name = "wlan", +}; + struct net_device * islpci_setup(struct pci_dev *pdev) { @@ -821,9 +825,8 @@ islpci_setup(struct pci_dev *pdev) return ndev; pci_set_drvdata(pdev, ndev); -#if defined(SET_NETDEV_DEV) SET_NETDEV_DEV(ndev, &pdev->dev); -#endif + SET_NETDEV_DEVTYPE(ndev, &wlan_type); /* setup the structure members */ ndev->base_addr = pci_resource_start(pdev, 0); diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c index 0ea85f46659..131b22b8512 100644 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ b/drivers/net/wireless/rt2x00/rt2400pci.c @@ -1253,7 +1253,7 @@ static void rt2400pci_fill_rxdone(struct queue_entry *entry, */ rxdesc->timestamp = ((u64)rx_high << 32) | rx_low; rxdesc->signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL) & ~0x08; - rxdesc->rssi = rt2x00_get_field32(word2, RXD_W3_RSSI) - + rxdesc->rssi = rt2x00_get_field32(word3, RXD_W3_RSSI) - entry->queue->rt2x00dev->rssi_offset; rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c b/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c index 025bdc2eba4..4f7f822b893 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c @@ -762,7 +762,7 @@ static long _rtl92c_signal_scale_mapping(struct ieee80211_hw *hw, static void _rtl92c_query_rxphystatus(struct ieee80211_hw *hw, struct rtl_stats *pstats, - struct rx_desc_92c *pdesc, + struct rx_desc_92c *p_desc, struct rx_fwinfo_92c *p_drvinfo, bool packet_match_bssid, bool packet_toself, @@ -777,11 +777,11 @@ static void _rtl92c_query_rxphystatus(struct ieee80211_hw *hw, u32 rssi, total_rssi = 0; bool in_powersavemode = false; bool is_cck_rate; + u8 *pdesc = (u8 *)p_desc; - is_cck_rate = RX_HAL_IS_CCK_RATE(pdesc); + is_cck_rate = RX_HAL_IS_CCK_RATE(p_desc); pstats->packet_matchbssid = packet_match_bssid; pstats->packet_toself = packet_toself; - pstats->is_cck = is_cck_rate; pstats->packet_beacon = packet_beacon; pstats->is_cck = is_cck_rate; pstats->RX_SIGQ[0] = -1; diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c index 9adb21a1133..2fd82970954 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c @@ -303,10 +303,10 @@ static enum rtl_desc_qsel _rtl8192cu_mq_to_descq(struct ieee80211_hw *hw, bool rtl92cu_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats, struct ieee80211_rx_status *rx_status, - u8 *p_desc, struct sk_buff *skb) + u8 *pdesc, struct sk_buff *skb) { struct rx_fwinfo_92c *p_drvinfo; - struct rx_desc_92c *pdesc = (struct rx_desc_92c *)p_desc; + struct rx_desc_92c *p_desc = (struct rx_desc_92c *)pdesc; u32 phystatus = GET_RX_DESC_PHY_STATUS(pdesc); stats->length = (u16) GET_RX_DESC_PKT_LEN(pdesc); @@ -345,11 +345,11 @@ bool rtl92cu_rx_query_desc(struct ieee80211_hw *hw, if (phystatus) { p_drvinfo = (struct rx_fwinfo_92c *)(skb->data + stats->rx_bufshift); - rtl92c_translate_rx_signal_stuff(hw, skb, stats, pdesc, + rtl92c_translate_rx_signal_stuff(hw, skb, stats, p_desc, p_drvinfo); } /*rx_status->qual = stats->signal; */ - rx_status->signal = stats->rssi + 10; + rx_status->signal = stats->recvsignalpower + 10; /*rx_status->noise = -stats->noise; */ return true; } diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/trx.c b/drivers/net/wireless/rtlwifi/rtl8192de/trx.c index a7f6126e2f8..1a2bbc2ba3a 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192de/trx.c @@ -529,7 +529,7 @@ bool rtl92de_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats, p_drvinfo); } /*rx_status->qual = stats->signal; */ - rx_status->signal = stats->rssi + 10; + rx_status->signal = stats->recvsignalpower + 10; /*rx_status->noise = -stats->noise; */ return true; } diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/rf.c b/drivers/net/wireless/rtlwifi/rtl8192se/rf.c index 08c2f562512..c405f9678b8 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/rf.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/rf.c @@ -268,7 +268,7 @@ static void _rtl92s_get_txpower_writeval_byregulatory(struct ieee80211_hw *hw, rtlefuse->pwrgroup_ht40 [RF90_PATH_A][chnl - 1]) { pwrdiff_limit[i] = - rtlefuse->pwrgroup_ht20 + rtlefuse->pwrgroup_ht40 [RF90_PATH_A][chnl - 1]; } } else { diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c index 2fd3d13b7ce..94bbce824b5 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c @@ -582,7 +582,7 @@ bool rtl92se_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats, } /*rx_status->qual = stats->signal; */ - rx_status->signal = stats->rssi + 10; + rx_status->signal = stats->recvsignalpower + 10; /*rx_status->noise = -stats->noise; */ return true; diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index e0610bda1de..7e41b70aaab 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c @@ -151,7 +151,6 @@ static int __devinit pcie_portdrv_probe(struct pci_dev *dev, static void pcie_portdrv_remove(struct pci_dev *dev) { pcie_port_device_remove(dev); - pci_disable_device(dev); } static int error_detected_iter(struct device *device, void *data) diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 8334dadc681..be56590b750 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -4357,7 +4357,7 @@ int qeth_snmp_command(struct qeth_card *card, char __user *udata) struct qeth_cmd_buffer *iob; struct qeth_ipa_cmd *cmd; struct qeth_snmp_ureq *ureq; - int req_len; + unsigned int req_len; struct qeth_arp_query_info qinfo = {0, }; int rc = 0; @@ -4373,6 +4373,10 @@ int qeth_snmp_command(struct qeth_card *card, char __user *udata) /* skip 4 bytes (data_len struct member) to get req_len */ if (copy_from_user(&req_len, udata + sizeof(int), sizeof(int))) return -EFAULT; + if (req_len > (QETH_BUFSIZE - IPA_PDU_HEADER_SIZE - + sizeof(struct qeth_ipacmd_hdr) - + sizeof(struct qeth_ipacmd_setadpparms_hdr))) + return -EINVAL; ureq = memdup_user(udata, req_len + sizeof(struct qeth_snmp_ureq_hdr)); if (IS_ERR(ureq)) { QETH_CARD_TEXT(card, 2, "snmpnome"); diff --git a/drivers/staging/media/lirc/lirc_zilog.c b/drivers/staging/media/lirc/lirc_zilog.c index 76ea4a8f2c7..56a96d32d04 100644 --- a/drivers/staging/media/lirc/lirc_zilog.c +++ b/drivers/staging/media/lirc/lirc_zilog.c @@ -61,6 +61,9 @@ #include #include +/* Max transfer size done by I2C transfer functions */ +#define MAX_XFER_SIZE 64 + struct IR; struct IR_rx { @@ -942,7 +945,14 @@ static ssize_t read(struct file *filep, char *outbuf, size_t n, loff_t *ppos) schedule(); set_current_state(TASK_INTERRUPTIBLE); } else { - unsigned char buf[rbuf->chunk_size]; + unsigned char buf[MAX_XFER_SIZE]; + + if (rbuf->chunk_size > sizeof(buf)) { + zilog_error("chunk_size is too big (%d)!\n", + rbuf->chunk_size); + ret = -EINVAL; + break; + } m = lirc_buffer_read(rbuf, buf); if (m == rbuf->chunk_size) { ret = copy_to_user((void *)outbuf+written, buf, diff --git a/drivers/staging/tidspbridge/Kconfig b/drivers/staging/tidspbridge/Kconfig index 0dd479f5638..f67c78e5056 100644 --- a/drivers/staging/tidspbridge/Kconfig +++ b/drivers/staging/tidspbridge/Kconfig @@ -4,7 +4,7 @@ menuconfig TIDSPBRIDGE tristate "DSP Bridge driver" - depends on ARCH_OMAP3 + depends on ARCH_OMAP3 && BROKEN select OMAP_MBOX_FWK help DSP/BIOS Bridge is designed for platforms that contain a GPP and diff --git a/drivers/staging/vt6656/baseband.c b/drivers/staging/vt6656/baseband.c index 06f27f624db..858e2a8ee26 100644 --- a/drivers/staging/vt6656/baseband.c +++ b/drivers/staging/vt6656/baseband.c @@ -976,6 +976,7 @@ BOOL BBbVT3184Init(PSDevice pDevice) PBYTE pbyAgc; WORD wLengthAgc; BYTE abyArray[256]; + u8 data; ntStatus = CONTROLnsRequestIn(pDevice, MESSAGE_TYPE_READ, @@ -1144,6 +1145,16 @@ else { ControlvWriteByte(pDevice,MESSAGE_REQUEST_BBREG,0x0D,0x01); RFbRFTableDownload(pDevice); + + /* Fix for TX USB resets from vendors driver */ + CONTROLnsRequestIn(pDevice, MESSAGE_TYPE_READ, USB_REG4, + MESSAGE_REQUEST_MEM, sizeof(data), &data); + + data |= 0x2; + + CONTROLnsRequestOut(pDevice, MESSAGE_TYPE_WRITE, USB_REG4, + MESSAGE_REQUEST_MEM, sizeof(data), &data); + return TRUE;//ntStatus; } diff --git a/drivers/staging/vt6656/rndis.h b/drivers/staging/vt6656/rndis.h index fccf7e98eb6..dcf7bf54fb3 100644 --- a/drivers/staging/vt6656/rndis.h +++ b/drivers/staging/vt6656/rndis.h @@ -69,6 +69,7 @@ #define VIAUSB20_PACKET_HEADER 0x04 +#define USB_REG4 0x604 /*--------------------- Export Classes ----------------------------*/ diff --git a/drivers/target/iscsi/iscsi_target_auth.c b/drivers/target/iscsi/iscsi_target_auth.c index a0fc7b9eea6..b54f6ecf90d 100644 --- a/drivers/target/iscsi/iscsi_target_auth.c +++ b/drivers/target/iscsi/iscsi_target_auth.c @@ -174,6 +174,7 @@ static int chap_server_compute_md5( unsigned char client_digest[MD5_SIGNATURE_SIZE]; unsigned char server_digest[MD5_SIGNATURE_SIZE]; unsigned char chap_n[MAX_CHAP_N_SIZE], chap_r[MAX_RESPONSE_LENGTH]; + size_t compare_len; struct iscsi_chap *chap = conn->auth_protocol; struct crypto_hash *tfm; struct hash_desc desc; @@ -212,7 +213,9 @@ static int chap_server_compute_md5( goto out; } - if (memcmp(chap_n, auth->userid, strlen(auth->userid)) != 0) { + /* Include the terminating NULL in the compare */ + compare_len = strlen(auth->userid) + 1; + if (strncmp(chap_n, auth->userid, compare_len) != 0) { pr_err("CHAP_N values do not match!\n"); goto out; } diff --git a/drivers/target/iscsi/iscsi_target_nego.c b/drivers/target/iscsi/iscsi_target_nego.c index 2dba448cac1..60470ee98fe 100644 --- a/drivers/target/iscsi/iscsi_target_nego.c +++ b/drivers/target/iscsi/iscsi_target_nego.c @@ -89,7 +89,7 @@ int extract_param( if (len < 0) return -1; - if (len > max_length) { + if (len >= max_length) { pr_err("Length of input: %d exceeds max_length:" " %d\n", len, max_length); return -1; diff --git a/drivers/video/backlight/atmel-pwm-bl.c b/drivers/video/backlight/atmel-pwm-bl.c index 0443a4f7185..4d2bbd893e8 100644 --- a/drivers/video/backlight/atmel-pwm-bl.c +++ b/drivers/video/backlight/atmel-pwm-bl.c @@ -70,7 +70,7 @@ static int atmel_pwm_bl_set_intensity(struct backlight_device *bd) static int atmel_pwm_bl_get_intensity(struct backlight_device *bd) { struct atmel_pwm_bl *pwmbl = bl_get_data(bd); - u8 intensity; + u32 intensity; if (pwmbl->pdata->pwm_active_low) { intensity = pwm_channel_readl(&pwmbl->pwmc, PWM_CDTY) - @@ -80,7 +80,7 @@ static int atmel_pwm_bl_get_intensity(struct backlight_device *bd) pwm_channel_readl(&pwmbl->pwmc, PWM_CDTY); } - return intensity; + return intensity & 0xffff; } static int atmel_pwm_bl_init_pwm(struct atmel_pwm_bl *pwmbl) diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c index 10f5e0b484d..901c3d74ad8 100644 --- a/fs/devpts/inode.c +++ b/fs/devpts/inode.c @@ -475,6 +475,7 @@ static void devpts_kill_sb(struct super_block *sb) { struct pts_fs_info *fsi = DEVPTS_SB(sb); + ida_destroy(&fsi->allocated_ptys); kfree(fsi); kill_litter_super(sb); } diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c index b1aa7fd4701..01f2cf3409f 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c @@ -1270,6 +1270,7 @@ int ext4_expand_extra_isize_ea(struct inode *inode, int new_extra_isize, new_extra_isize = s_min_extra_isize; kfree(is); is = NULL; kfree(bs); bs = NULL; + brelse(bh); goto retry; } error = -1; diff --git a/include/linux/mtd/map.h b/include/linux/mtd/map.h index 3595a0236b0..292645fc6ba 100644 --- a/include/linux/mtd/map.h +++ b/include/linux/mtd/map.h @@ -362,7 +362,7 @@ static inline map_word map_word_load_partial(struct map_info *map, map_word orig bitpos = (map_bankwidth(map)-1-i)*8; #endif orig.x[0] &= ~(0xff << bitpos); - orig.x[0] |= buf[i-start] << bitpos; + orig.x[0] |= (unsigned long)buf[i-start] << bitpos; } } return orig; @@ -381,7 +381,7 @@ static inline map_word map_word_ff(struct map_info *map) if (map_bankwidth(map) < MAP_FF_LIMIT) { int bw = 8 * map_bankwidth(map); - r.x[0] = (1 << bw) - 1; + r.x[0] = (1UL << bw) - 1; } else { for (i=0; inlmsg_len < sizeof(struct audit_status)) + if (nlmsg_len(nlh) < sizeof(struct audit_status)) return -EINVAL; status_get = (struct audit_status *)data; if (status_get->mask & AUDIT_STATUS_ENABLED) { diff --git a/kernel/cpuset.c b/kernel/cpuset.c index 8fe6f6b6500..e372d9495e4 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c @@ -983,8 +983,10 @@ static void cpuset_change_task_nodemask(struct task_struct *tsk, need_loop = task_has_mempolicy(tsk) || !nodes_intersects(*newmems, tsk->mems_allowed); - if (need_loop) + if (need_loop) { + local_irq_disable(); write_seqcount_begin(&tsk->mems_allowed_seq); + } nodes_or(tsk->mems_allowed, tsk->mems_allowed, *newmems); mpol_rebind_task(tsk, newmems, MPOL_REBIND_STEP1); @@ -992,8 +994,10 @@ static void cpuset_change_task_nodemask(struct task_struct *tsk, mpol_rebind_task(tsk, newmems, MPOL_REBIND_STEP2); tsk->mems_allowed = *newmems; - if (need_loop) + if (need_loop) { write_seqcount_end(&tsk->mems_allowed_seq); + local_irq_enable(); + } task_unlock(tsk); } diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c index 0de28576807..91c04f16e79 100644 --- a/kernel/power/snapshot.c +++ b/kernel/power/snapshot.c @@ -1398,7 +1398,11 @@ int hibernate_preallocate_memory(void) * highmem and non-highmem zones separately. */ pages_highmem = preallocate_image_highmem(highmem / 2); - alloc = (count - max_size) - pages_highmem; + alloc = count - max_size; + if (alloc > pages_highmem) + alloc -= pages_highmem; + else + alloc = 0; pages = preallocate_image_memory(alloc, avail_normal); if (pages < alloc) { /* We have exhausted non-highmem pages, try highmem. */ diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c index b07241cc809..6e4cb9836b1 100644 --- a/kernel/time/alarmtimer.c +++ b/kernel/time/alarmtimer.c @@ -445,7 +445,7 @@ static int alarm_clock_getres(const clockid_t which_clock, struct timespec *tp) clockid_t baseid = alarm_bases[clock2alarm(which_clock)].base_clockid; if (!alarmtimer_get_rtcdev()) - return -ENOTSUPP; + return -EINVAL; return hrtimer_get_res(baseid, tp); } @@ -462,7 +462,7 @@ static int alarm_clock_get(clockid_t which_clock, struct timespec *tp) struct alarm_base *base = &alarm_bases[clock2alarm(which_clock)]; if (!alarmtimer_get_rtcdev()) - return -ENOTSUPP; + return -EINVAL; *tp = ktime_to_timespec(base->gettime()); return 0; diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index e101cf9acc0..8c8169bf502 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -312,9 +312,6 @@ static int remove_ftrace_list_ops(struct ftrace_ops **list, static int __register_ftrace_function(struct ftrace_ops *ops) { - if (ftrace_disabled) - return -ENODEV; - if (FTRACE_WARN_ON(ops == &global_ops)) return -EINVAL; @@ -348,9 +345,6 @@ static int __unregister_ftrace_function(struct ftrace_ops *ops) { int ret; - if (ftrace_disabled) - return -ENODEV; - if (WARN_ON(!(ops->flags & FTRACE_OPS_FL_ENABLED))) return -EBUSY; @@ -1940,10 +1934,15 @@ static void ftrace_startup_enable(int command) static int ftrace_startup(struct ftrace_ops *ops, int command) { bool hash_enable = true; + int ret; if (unlikely(ftrace_disabled)) return -ENODEV; + ret = __register_ftrace_function(ops); + if (ret) + return ret; + ftrace_start_up++; command |= FTRACE_UPDATE_CALLS; @@ -1965,12 +1964,17 @@ static int ftrace_startup(struct ftrace_ops *ops, int command) return 0; } -static void ftrace_shutdown(struct ftrace_ops *ops, int command) +static int ftrace_shutdown(struct ftrace_ops *ops, int command) { bool hash_disable = true; + int ret; if (unlikely(ftrace_disabled)) - return; + return -ENODEV; + + ret = __unregister_ftrace_function(ops); + if (ret) + return ret; ftrace_start_up--; /* @@ -2005,9 +2009,10 @@ static void ftrace_shutdown(struct ftrace_ops *ops, int command) } if (!command || !ftrace_enabled) - return; + return 0; ftrace_run_update_code(command); + return 0; } static void ftrace_startup_sysctl(void) @@ -2873,16 +2878,13 @@ static void __enable_ftrace_function_probe(void) if (i == FTRACE_FUNC_HASHSIZE) return; - ret = __register_ftrace_function(&trace_probe_ops); - if (!ret) - ret = ftrace_startup(&trace_probe_ops, 0); + ret = ftrace_startup(&trace_probe_ops, 0); ftrace_probe_registered = 1; } static void __disable_ftrace_function_probe(void) { - int ret; int i; if (!ftrace_probe_registered) @@ -2895,9 +2897,7 @@ static void __disable_ftrace_function_probe(void) } /* no more funcs left */ - ret = __unregister_ftrace_function(&trace_probe_ops); - if (!ret) - ftrace_shutdown(&trace_probe_ops, 0); + ftrace_shutdown(&trace_probe_ops, 0); ftrace_probe_registered = 0; } @@ -3948,12 +3948,15 @@ device_initcall(ftrace_nodyn_init); static inline int ftrace_init_dyn_debugfs(struct dentry *d_tracer) { return 0; } static inline void ftrace_startup_enable(int command) { } /* Keep as macros so we do not need to define the commands */ -# define ftrace_startup(ops, command) \ - ({ \ - (ops)->flags |= FTRACE_OPS_FL_ENABLED; \ - 0; \ +# define ftrace_startup(ops, command) \ + ({ \ + int ___ret = __register_ftrace_function(ops); \ + if (!___ret) \ + (ops)->flags |= FTRACE_OPS_FL_ENABLED; \ + ___ret; \ }) -# define ftrace_shutdown(ops, command) do { } while (0) +# define ftrace_shutdown(ops, command) __unregister_ftrace_function(ops) + # define ftrace_startup_sysctl() do { } while (0) # define ftrace_shutdown_sysctl() do { } while (0) @@ -4323,15 +4326,8 @@ int register_ftrace_function(struct ftrace_ops *ops) mutex_lock(&ftrace_lock); - if (unlikely(ftrace_disabled)) - goto out_unlock; - - ret = __register_ftrace_function(ops); - if (!ret) - ret = ftrace_startup(ops, 0); - + ret = ftrace_startup(ops, 0); - out_unlock: mutex_unlock(&ftrace_lock); return ret; } @@ -4348,9 +4344,7 @@ int unregister_ftrace_function(struct ftrace_ops *ops) int ret; mutex_lock(&ftrace_lock); - ret = __unregister_ftrace_function(ops); - if (!ret) - ftrace_shutdown(ops, 0); + ret = ftrace_shutdown(ops, 0); mutex_unlock(&ftrace_lock); return ret; @@ -4544,6 +4538,12 @@ ftrace_suspend_notifier_call(struct notifier_block *bl, unsigned long state, return NOTIFY_DONE; } +/* Just a place holder for function graph */ +static struct ftrace_ops fgraph_ops __read_mostly = { + .func = ftrace_stub, + .flags = FTRACE_OPS_FL_GLOBAL, +}; + int register_ftrace_graph(trace_func_graph_ret_t retfunc, trace_func_graph_ent_t entryfunc) { @@ -4570,7 +4570,7 @@ int register_ftrace_graph(trace_func_graph_ret_t retfunc, ftrace_graph_return = retfunc; ftrace_graph_entry = entryfunc; - ret = ftrace_startup(&global_ops, FTRACE_START_FUNC_RET); + ret = ftrace_startup(&fgraph_ops, FTRACE_START_FUNC_RET); out: mutex_unlock(&ftrace_lock); @@ -4587,7 +4587,7 @@ void unregister_ftrace_graph(void) ftrace_graph_active--; ftrace_graph_return = (trace_func_graph_ret_t)ftrace_stub; ftrace_graph_entry = ftrace_graph_entry_stub; - ftrace_shutdown(&global_ops, FTRACE_STOP_FUNC_RET); + ftrace_shutdown(&fgraph_ops, FTRACE_STOP_FUNC_RET); unregister_pm_notifier(&ftrace_suspend_notifier); unregister_trace_sched_switch(ftrace_graph_probe_sched_switch, NULL); diff --git a/lib/vsprintf.c b/lib/vsprintf.c index f5dfe0ca34f..184315a9d59 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include /* for PAGE_SIZE */ @@ -930,11 +931,37 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr, spec.field_width = 2 * sizeof(void *); return string(buf, end, "pK-error", spec); } - if (!((kptr_restrict == 0) || - (kptr_restrict == 1 && - has_capability_noaudit(current, CAP_SYSLOG)))) + + switch (kptr_restrict) { + case 0: + /* Always print %pK values */ + break; + case 1: { + /* + * Only print the real pointer value if the current + * process has CAP_SYSLOG and is running with the + * same credentials it started with. This is because + * access to files is checked at open() time, but %pK + * checks permission at read() time. We don't want to + * leak pointer values if a binary opens a file using + * %pK and then elevates privileges before reading it. + */ + const struct cred *cred = current_cred(); + + if (!has_capability_noaudit(current, CAP_SYSLOG) || + (cred->euid != cred->uid) || + (cred->egid != cred->gid)) + ptr = NULL; + break; + } + case 2: + default: + /* Always print 0's for %pK */ ptr = NULL; + break; + } break; + case 'N': switch (fmt[1]) { case 'F': diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c index da4b8b23328..6235d052338 100644 --- a/security/selinux/netlabel.c +++ b/security/selinux/netlabel.c @@ -442,8 +442,7 @@ int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr) sksec->nlbl_state != NLBL_CONNLABELED) return 0; - local_bh_disable(); - bh_lock_sock_nested(sk); + lock_sock(sk); /* connected sockets are allowed to disconnect when the address family * is set to AF_UNSPEC, if that is what is happening we want to reset @@ -464,7 +463,6 @@ int selinux_netlbl_socket_connect(struct sock *sk, struct sockaddr *addr) sksec->nlbl_state = NLBL_CONNLABELED; socket_connect_return: - bh_unlock_sock(sk); - local_bh_enable(); + release_sock(sk); return rc; } diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 810f1fc2c3f..c32ae4d5f97 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -6969,6 +6969,7 @@ static int patch_alc662(struct hda_codec *codec) case 0x10ec0272: case 0x10ec0663: case 0x10ec0665: + case 0x10ec0668: set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT); break; case 0x10ec0273: diff --git a/sound/soc/blackfin/bf5xx-i2s.c b/sound/soc/blackfin/bf5xx-i2s.c index 4dccf0374fe..f59a961b6bb 100644 --- a/sound/soc/blackfin/bf5xx-i2s.c +++ b/sound/soc/blackfin/bf5xx-i2s.c @@ -111,6 +111,7 @@ static int bf5xx_i2s_hw_params(struct snd_pcm_substream *substream, bf5xx_i2s->tcr2 |= 7; bf5xx_i2s->rcr2 |= 7; sport_handle->wdsize = 1; + break; case SNDRV_PCM_FORMAT_S16_LE: bf5xx_i2s->tcr2 |= 15; bf5xx_i2s->rcr2 |= 15; diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c index b3e24f28942..7e4245f19d0 100644 --- a/sound/soc/codecs/ak4642.c +++ b/sound/soc/codecs/ak4642.c @@ -262,7 +262,7 @@ static int ak4642_dai_startup(struct snd_pcm_substream *substream, * This operation came from example code of * "ASAHI KASEI AK4642" (japanese) manual p94. */ - snd_soc_write(codec, SG_SL1, PMMP | MGAIN0); + snd_soc_update_bits(codec, SG_SL1, PMMP | MGAIN0, PMMP | MGAIN0); snd_soc_write(codec, TIMER, ZTM(0x3) | WTM(0x3)); snd_soc_write(codec, ALC_CTL1, ALC | LMTH0); snd_soc_update_bits(codec, PW_MGMT1, PMADL, PMADL); diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index e96c6ede7fd..0b5132f7975 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -3675,6 +3675,8 @@ static __devinit int wm8962_i2c_probe(struct i2c_client *i2c, if (ret < 0) goto err_regmap; + regcache_cache_only(wm8962->regmap, true); + /* The drivers should power up as needed */ regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies), wm8962->supplies); diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index bdfbc1be740..91a0a2f8cbc 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -774,7 +774,7 @@ int __kvm_set_memory_region(struct kvm *kvm, /* destroy any largepage mappings for dirty tracking */ } - if (!npages) { + if (!npages || base_gfn != old.base_gfn) { struct kvm_memory_slot *slot; r = -ENOMEM; @@ -790,8 +790,10 @@ int __kvm_set_memory_region(struct kvm *kvm, old_memslots = kvm->memslots; rcu_assign_pointer(kvm->memslots, slots); synchronize_srcu_expedited(&kvm->srcu); - /* From this point no new shadow pages pointing to a deleted - * memslot will be created. + /* slot was deleted or moved, clear iommu mapping */ + kvm_iommu_unmap_pages(kvm, &old); + /* From this point no new shadow pages pointing to a deleted, + * or moved, memslot will be created. * * validation of sp->gfn happens in: * - gfn_to_hva (kvm_read_guest, gfn_to_pfn) @@ -805,20 +807,19 @@ int __kvm_set_memory_region(struct kvm *kvm, if (r) goto out_free; - /* map/unmap the pages in iommu page table */ - if (npages) { - r = kvm_iommu_map_pages(kvm, &new); - if (r) - goto out_free; - } else - kvm_iommu_unmap_pages(kvm, &old); - r = -ENOMEM; slots = kmemdup(kvm->memslots, sizeof(struct kvm_memslots), GFP_KERNEL); if (!slots) goto out_free; + /* map new memory slot into the iommu */ + if (npages) { + r = kvm_iommu_map_pages(kvm, &new); + if (r) + goto out_slots; + } + /* actual memory is freed via old in kvm_free_physmem_slot below */ if (!npages) { new.rmap = NULL; @@ -845,6 +846,8 @@ int __kvm_set_memory_region(struct kvm *kvm, return 0; +out_slots: + kfree(slots); out_free: kvm_free_physmem_slot(&new, &old); out: From cb644266dd166ea05c5925fde82484990ab56b69 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 8 Dec 2013 08:12:17 -0800 Subject: [PATCH 146/215] Linux 3.4.73 - 30 commits squashed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit net: Fix "ip rule delete table 256" [ Upstream commit 13eb2ab2d33c57ebddc57437a7d341995fc9138c ] When trying to delete a table >= 256 using iproute2 the local table will be deleted. The table id is specified as a netlink attribute when it needs more then 8 bits and iproute2 then sets the table field to RT_TABLE_UNSPEC (0). Preconditions to matching the table id in the rule delete code doesn't seem to take the "table id in netlink attribute" into condition so the frh_get_table helper function never gets to do its job when matching against current rule. Use the helper function twice instead of peaking at the table value directly. Originally reported at: http://bugs.debian.org/724783 Reported-by: Nicolas HICHER Signed-off-by: Andreas Henriksson Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman ipv6: use rt6_get_dflt_router to get default router in rt6_route_rcv [ Upstream commit f104a567e673f382b09542a8dc3500aa689957b4 ] As the rfc 4191 said, the Router Preference and Lifetime values in a ::/0 Route Information Option should override the preference and lifetime values in the Router Advertisement header. But when the kernel deals with a ::/0 Route Information Option, the rt6_get_route_info() always return NULL, that means that overriding will not happen, because those default routers were added without flag RTF_ROUTEINFO in rt6_add_dflt_router(). In order to deal with that condition, we should call rt6_get_dflt_router when the prefix length is 0. Signed-off-by: Duan Jiong Acked-by: Hannes Frederic Sowa Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman random32: fix off-by-one in seeding requirement [ Upstream commit 51c37a70aaa3f95773af560e6db3073520513912 ] For properly initialising the Tausworthe generator [1], we have a strict seeding requirement, that is, s1 > 1, s2 > 7, s3 > 15. Commit 697f8d0348 ("random32: seeding improvement") introduced a __seed() function that imposes boundary checks proposed by the errata paper [2] to properly ensure above conditions. However, we're off by one, as the function is implemented as: "return (x < m) ? x + m : x;", and called with __seed(X, 1), __seed(X, 7), __seed(X, 15). Thus, an unwanted seed of 1, 7, 15 would be possible, whereas the lower boundary should actually be of at least 2, 8, 16, just as GSL does. Fix this, as otherwise an initialization with an unwanted seed could have the effect that Tausworthe's PRNG properties cannot not be ensured. Note that this PRNG is *not* used for cryptography in the kernel. [1] http://www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme.ps [2] http://www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme2.ps Joint work with Hannes Frederic Sowa. Fixes: 697f8d0348a6 ("random32: seeding improvement") Cc: Stephen Hemminger Cc: Florian Weimer Cc: Theodore Ts'o Signed-off-by: Daniel Borkmann Signed-off-by: Hannes Frederic Sowa Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman bonding: don't permit to use ARP monitoring in 802.3ad mode [ Upstream commit ec9f1d15db8185f63a2c3143dc1e90ba18541b08 ] Currently the ARP monitoring is not supported with 802.3ad, and it's prohibited to use it via the module params. However we still can set it afterwards via sysfs, cause we only check for *LB modes there. To fix this - add a check for 802.3ad mode in bonding_store_arp_interval. Signed-off-by: Veaceslav Falico CC: Jay Vosburgh CC: Andy Gospodarek Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman 6lowpan: Uncompression of traffic class field was incorrect [ Upstream commit 1188f05497e7bd2f2614b99c54adfbe7413d5749 ] If priority/traffic class field in IPv6 header is set (seen when using ssh), the uncompression sets the TC and Flow fields incorrectly. Example: This is IPv6 header of a sent packet. Note the priority/TC (=1) in the first byte. 00000000: 61 00 00 00 00 2c 06 40 fe 80 00 00 00 00 00 00 00000010: 02 02 72 ff fe c6 42 10 fe 80 00 00 00 00 00 00 00000020: 02 1e ab ff fe 4c 52 57 This gets compressed like this in the sending side 00000000: 72 31 04 06 02 1e ab ff fe 4c 52 57 ec c2 00 16 00000010: aa 2d fe 92 86 4e be c6 .... In the receiving end, the packet gets uncompressed to this IPv6 header 00000000: 60 06 06 02 00 2a 1e 40 fe 80 00 00 00 00 00 00 00000010: 02 02 72 ff fe c6 42 10 fe 80 00 00 00 00 00 00 00000020: ab ff fe 4c 52 57 ec c2 First four bytes are set incorrectly and we have also lost two bytes from destination address. The fix is to switch the case values in switch statement when checking the TC field. Signed-off-by: Jukka Rissanen Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman bonding: fix two race conditions in bond_store_updelay/downdelay [ Upstream commit b869ccfab1e324507fa3596e3e1308444fb68227 ] This patch fixes two race conditions between bond_store_updelay/downdelay and bond_store_miimon which could lead to division by zero as miimon can be set to 0 while either updelay/downdelay are being set and thus miss the zero check in the beginning, the zero div happens because updelay/downdelay are stored as new_value / bond->params.miimon. Use rtnl to synchronize with miimon setting. Signed-off-by: Nikolay Aleksandrov CC: Jay Vosburgh CC: Andy Gospodarek CC: Veaceslav Falico Acked-by: Veaceslav Falico Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman isdnloop: use strlcpy() instead of strcpy() [ Upstream commit f9a23c84486ed350cce7bb1b2828abd1f6658796 ] These strings come from a copy_from_user() and there is no way to be sure they are NUL terminated. Signed-off-by: Dan Carpenter Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman connector: improved unaligned access error fix [ Upstream commit 1ca1a4cf59ea343a1a70084fe7cc96f37f3cf5b1 ] In af3e095a1fb4, Erik Jacobsen fixed one type of unaligned access bug for ia64 by converting a 64-bit write to use put_unaligned(). Unfortunately, since gcc will convert a short memset() to a series of appropriately-aligned stores, the problem is now visible again on tilegx, where the memset that zeros out proc_event is converted to three 64-bit stores, causing an unaligned access panic. A better fix for the original problem is to ensure that proc_event is aligned to 8 bytes here. We can do that relatively easily by arranging to start the struct cn_msg aligned to 8 bytes and then offset by 4 bytes. Doing so means that the immediately following proc_event structure is then correctly aligned to 8 bytes. The result is that the memset() stores are now aligned, and as an added benefit, we can remove the put_unaligned() calls in the code. Signed-off-by: Chris Metcalf Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman ipv4: fix possible seqlock deadlock [ Upstream commit c9e9042994d37cbc1ee538c500e9da1bb9d1bcdf ] ip4_datagram_connect() being called from process context, it should use IP_INC_STATS() instead of IP_INC_STATS_BH() otherwise we can deadlock on 32bit arches, or get corruptions of SNMP counters. Fixes: 584bdf8cbdf6 ("[IPV4]: Fix "ipOutNoRoutes" counter error for TCP and UDP") Signed-off-by: Eric Dumazet Reported-by: Dave Jones Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman net: rework recvmsg handler msg_name and msg_namelen logic [ Upstream commit f3d3342602f8bcbf37d7c46641cb9bca7618eb1c ] This patch now always passes msg->msg_namelen as 0. recvmsg handlers must set msg_namelen to the proper size <= sizeof(struct sockaddr_storage) to return msg_name to the user. This prevents numerous uninitialized memory leaks we had in the recvmsg handlers and makes it harder for new code to accidentally leak uninitialized memory. Optimize for the case recvfrom is called with NULL as address. We don't need to copy the address at all, so set it to NULL before invoking the recvmsg handler. We can do so, because all the recvmsg handlers must cope with the case a plain read() is called on them. read() also sets msg_name to NULL. Also document these changes in include/linux/net.h as suggested by David Miller. Changes since RFC: Set msg->msg_name = NULL if user specified a NULL in msg_name but had a non-null msg_namelen in verify_iovec/verify_compat_iovec. This doesn't affect sendto as it would bail out earlier while trying to copy-in the address. It also more naturally reflects the logic by the callers of verify_iovec. With this change in place I could remove " if (!uaddr || msg_sys->msg_namelen == 0) msg->msg_name = NULL ". This change does not alter the user visible error logic as we ignore msg_namelen as long as msg_name is NULL. Also remove two unnecessary curly brackets in ___sys_recvmsg and change comments to netdev style. Cc: David Miller Suggested-by: Eric Dumazet Signed-off-by: Hannes Frederic Sowa Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman net: add BUG_ON if kernel advertises msg_namelen > sizeof(struct sockaddr_storage) [ Upstream commit 68c6beb373955da0886d8f4f5995b3922ceda4be ] In that case it is probable that kernel code overwrote part of the stack. So we should bail out loudly here. The BUG_ON may be removed in future if we are sure all protocols are conformant. Suggested-by: Eric Dumazet Signed-off-by: Hannes Frederic Sowa Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman net: clamp ->msg_namelen instead of returning an error [ Upstream commit db31c55a6fb245fdbb752a2ca4aefec89afabb06 ] If kmsg->msg_namelen > sizeof(struct sockaddr_storage) then in the original code that would lead to memory corruption in the kernel if you had audit configured. If you didn't have audit configured it was harmless. There are some programs such as beta versions of Ruby which use too large of a buffer and returning an error code breaks them. We should clamp the ->msg_namelen value instead. Fixes: 1661bf364ae9 ("net: heap overflow in __audit_sockaddr()") Reported-by: Eric Wong Signed-off-by: Dan Carpenter Tested-by: Eric Wong Acked-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman ipv6: fix leaking uninitialized port number of offender sockaddr [ Upstream commit 1fa4c710b6fe7b0aac9907240291b6fe6aafc3b8 ] Offenders don't have port numbers, so set it to 0. Signed-off-by: Hannes Frederic Sowa Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman atm: idt77252: fix dev refcnt leak [ Upstream commit b5de4a22f157ca345cdb3575207bf46402414bc1 ] init_card() calls dev_get_by_name() to get a network deceive. But it doesn't decrease network device reference count after the device is used. Signed-off-by: Ying Xue Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman net: core: Always propagate flag changes to interfaces [ Upstream commit d2615bf450694c1302d86b9cc8a8958edfe4c3a4 ] The following commit: b6c40d68ff6498b7f63ddf97cf0aa818d748dee7 net: only invoke dev->change_rx_flags when device is UP tried to fix a problem with VLAN devices and promiscuouse flag setting. The issue was that VLAN device was setting a flag on an interface that was down, thus resulting in bad promiscuity count. This commit blocked flag propagation to any device that is currently down. A later commit: deede2fabe24e00bd7e246eb81cd5767dc6fcfc7 vlan: Don't propagate flag changes on down interfaces fixed VLAN code to only propagate flags when the VLAN interface is up, thus fixing the same issue as above, only localized to VLAN. The problem we have now is that if we have create a complex stack involving multiple software devices like bridges, bonds, and vlans, then it is possible that the flags would not propagate properly to the physical devices. A simple examle of the scenario is the following: eth0----> bond0 ----> bridge0 ---> vlan50 If bond0 or eth0 happen to be down at the time bond0 is added to the bridge, then eth0 will never have promisc mode set which is currently required for operation as part of the bridge. As a result, packets with vlan50 will be dropped by the interface. The only 2 devices that implement the special flag handling are VLAN and DSA and they both have required code to prevent incorrect flag propagation. As a result we can remove the generic solution introduced in b6c40d68ff6498b7f63ddf97cf0aa818d748dee7 and leave it to the individual devices to decide whether they will block flag propagation or not. Reported-by: Stefan Priebe Suggested-by: Veaceslav Falico Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman bridge: flush br's address entry in fdb when remove the bridge dev [ Upstream commit f873042093c0b418d2351fe142222b625c740149 ] When the following commands are executed: brctl addbr br0 ifconfig br0 hw ether rmmod bridge The calltrace will occur: [ 563.312114] device eth1 left promiscuous mode [ 563.312188] br0: port 1(eth1) entered disabled state [ 563.468190] kmem_cache_destroy bridge_fdb_cache: Slab cache still has objects [ 563.468197] CPU: 6 PID: 6982 Comm: rmmod Tainted: G O 3.12.0-0.7-default+ #9 [ 563.468199] Hardware name: Bochs Bochs, BIOS Bochs 01/01/2007 [ 563.468200] 0000000000000880 ffff88010f111e98 ffffffff814d1c92 ffff88010f111eb8 [ 563.468204] ffffffff81148efd ffff88010f111eb8 0000000000000000 ffff88010f111ec8 [ 563.468206] ffffffffa062a270 ffff88010f111ed8 ffffffffa063ac76 ffff88010f111f78 [ 563.468209] Call Trace: [ 563.468218] [] dump_stack+0x6a/0x78 [ 563.468234] [] kmem_cache_destroy+0xfd/0x100 [ 563.468242] [] br_fdb_fini+0x10/0x20 [bridge] [ 563.468247] [] br_deinit+0x4e/0x50 [bridge] [ 563.468254] [] SyS_delete_module+0x199/0x2b0 [ 563.468259] [] system_call_fastpath+0x16/0x1b [ 570.377958] Bridge firewalling registered --------------------------- cut here ------------------------------- The reason is that when the bridge dev's address is changed, the br_fdb_change_mac_address() will add new address in fdb, but when the bridge was removed, the address entry in the fdb did not free, the bridge_fdb_cache still has objects when destroy the cache, Fix this by flushing the bridge address entry when removing the bridge. v2: according to the Toshiaki Makita and Vlad's suggestion, I only delete the vlan0 entry, it still have a leak here if the vlan id is other number, so I need to call fdb_delete_by_port(br, NULL, 1) to flush all entries whose dst is NULL for the bridge. Suggested-by: Toshiaki Makita Suggested-by: Vlad Yasevich Signed-off-by: Ding Tianhong Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman packet: fix use after free race in send path when dev is released [ Upstream commit e40526cb20b5ee53419452e1f03d97092f144418 ] Salam reported a use after free bug in PF_PACKET that occurs when we're sending out frames on a socket bound device and suddenly the net device is being unregistered. It appears that commit 827d9780 introduced a possible race condition between {t,}packet_snd() and packet_notifier(). In the case of a bound socket, packet_notifier() can drop the last reference to the net_device and {t,}packet_snd() might end up suddenly sending a packet over a freed net_device. To avoid reverting 827d9780 and thus introducing a performance regression compared to the current state of things, we decided to hold a cached RCU protected pointer to the net device and maintain it on write side via bind spin_lock protected register_prot_hook() and __unregister_prot_hook() calls. In {t,}packet_snd() path, we access this pointer under rcu_read_lock through packet_cached_dev_get() that holds reference to the device to prevent it from being freed through packet_notifier() while we're in send path. This is okay to do as dev_put()/dev_hold() are per-cpu counters, so this should not be a performance issue. Also, the code simplifies a bit as we don't need need_rls_dev anymore. Fixes: 827d978037d7 ("af-packet: Use existing netdev reference for bound sockets.") Reported-by: Salam Noureddine Signed-off-by: Daniel Borkmann Signed-off-by: Salam Noureddine Cc: Ben Greear Cc: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman af_packet: block BH in prb_shutdown_retire_blk_timer() [ Upstream commit ec6f809ff6f19fafba3212f6aff0dda71dfac8e8 ] Currently we're using plain spin_lock() in prb_shutdown_retire_blk_timer(), however the timer might fire right in the middle and thus try to re-aquire the same spinlock, leaving us in a endless loop. To fix that, use the spin_lock_bh() to block it. Fixes: f6fb8f100b80 ("af-packet: TPACKET_V3 flexible buffer implementation.") CC: "David S. Miller" CC: Daniel Borkmann CC: Willem de Bruijn CC: Phil Sutter CC: Eric Dumazet Reported-by: Jan Stancek Tested-by: Jan Stancek Signed-off-by: Veaceslav Falico Acked-by: Daniel Borkmann Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman net: update consumers of MSG_MORE to recognize MSG_SENDPAGE_NOTLAST [ Upstream commit d3f7d56a7a4671d395e8af87071068a195257bf6 ] Commit 35f9c09fe (tcp: tcp_sendpages() should call tcp_push() once) added an internal flag MSG_SENDPAGE_NOTLAST, similar to MSG_MORE. algif_hash, algif_skcipher, and udp used MSG_MORE from tcp_sendpages() and need to see the new flag as identical to MSG_MORE. This fixes sendfile() on AF_ALG. v3: also fix udp Reported-and-tested-by: Shawn Landden Cc: Tom Herbert Cc: Eric Dumazet Cc: David S. Miller Original-patch: Richard Weinberger Signed-off-by: Shawn Landden Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman inet: fix possible seqlock deadlocks [ Upstream commit f1d8cba61c3c4b1eb88e507249c4cb8d635d9a76 ] In commit c9e9042994d3 ("ipv4: fix possible seqlock deadlock") I left another places where IP_INC_STATS_BH() were improperly used. udp_sendmsg(), ping_v4_sendmsg() and tcp_v4_connect() are called from process context, not from softirq context. This was detected by lockdep seqlock support. Reported-by: jongman heo Fixes: 584bdf8cbdf6 ("[IPV4]: Fix "ipOutNoRoutes" counter error for TCP and UDP") Fixes: c319b4d76b9e ("net: ipv4: add IPPROTO_ICMP socket kind") Signed-off-by: Eric Dumazet Cc: Hannes Frederic Sowa Acked-by: Hannes Frederic Sowa Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman ipv6: fix possible seqlock deadlock in ip6_finish_output2 [ Upstream commit 7f88c6b23afbd31545c676dea77ba9593a1a14bf ] IPv6 stats are 64 bits and thus are protected with a seqlock. By not disabling bottom-half we could deadlock here if we don't disable bh and a softirq reentrantly updates the same mib. Cc: Eric Dumazet Signed-off-by: Hannes Frederic Sowa Acked-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman {pktgen, xfrm} Update IPv4 header total len and checksum after tranformation [ Upstream commit 3868204d6b89ea373a273e760609cb08020beb1a ] commit a553e4a6317b2cfc7659542c10fe43184ffe53da ("[PKTGEN]: IPSEC support") tried to support IPsec ESP transport transformation for pktgen, but acctually this doesn't work at all for two reasons(The orignal transformed packet has bad IPv4 checksum value, as well as wrong auth value, reported by wireshark) - After transpormation, IPv4 header total length needs update, because encrypted payload's length is NOT same as that of plain text. - After transformation, IPv4 checksum needs re-caculate because of payload has been changed. With this patch, armmed pktgen with below cofiguration, Wireshark is able to decrypted ESP packet generated by pktgen without any IPv4 checksum error or auth value error. pgset "flag IPSEC" pgset "flows 1" Signed-off-by: Fan Du Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman HID: picolcd_core: validate output report details commit 1e87a2456b0227ca4ab881e19a11bb99d164e792 upstream. A HID device could send a malicious output report that would cause the picolcd HID driver to trigger a NULL dereference during attr file writing. [jkosina@suse.cz: changed report->maxfield < 1 to report->maxfield != 1 as suggested by Bruno]. CVE-2013-2899 Signed-off-by: Kees Cook Cc: stable@kernel.org Reviewed-by: Bruno Prémont Acked-by: Bruno Prémont Signed-off-by: Jiri Kosina [Kefeng: backported to stable 3.4: adjust filename] Signed-off-by: Kefeng Wang Signed-off-by: Greg Kroah-Hartman mmc: block: fix a bug of error handling in MMC driver commit c8760069627ad3b0dbbea170f0c4c58b16e18d3d upstream. Current MMC driver doesn't handle generic error (bit19 of device status) in write sequence. As a result, write data gets lost when generic error occurs. For example, a generic error when updating a filesystem management information causes a loss of write data and corrupts the filesystem. In the worst case, the system will never boot. This patch includes the following functionality: 1. To enable error checking for the response of CMD12 and CMD13 in write command sequence 2. To retry write sequence when a generic error occurs Messages are added for v2 to show what occurs. Signed-off-by: KOBAYASHI Yoshitake Signed-off-by: Chris Ball Signed-off-by: Greg Kroah-Hartman Conflicts: drivers/mmc/card/block.c nfsd: use "init_net" for portmapper commit f7fb86c6e639360ad9c253cec534819ef928a674 upstream. There could be a situation, when NFSd was started in one network namespace, but stopped in another one. This will trigger kernel panic, because RPCBIND client is stored on per-net NFSd data, and will be NULL on NFSd shutdown. Signed-off-by: Stanislav Kinsbursky Signed-off-by: J. Bruce Fields Signed-off-by: Weng Meiling Signed-off-by: Greg Kroah-Hartman video: kyro: fix incorrect sizes when copying to userspace commit 2ab68ec927310dc488f3403bb48f9e4ad00a9491 upstream. kyro would copy u32s and specify sizeof(unsigned long) as the size to copy. This would copy more data than intended and cause memory corruption and might leak kernel memory. Signed-off-by: Sasha Levin Signed-off-by: Tomi Valkeinen Signed-off-by: Greg Kroah-Hartman iommu/vt-d: Fixed interaction of VFIO_IOMMU_MAP_DMA with IOMMU address limits commit f9423606ade08653dd8a43334f0a7fb45504c5cc upstream. The BUG_ON in drivers/iommu/intel-iommu.c:785 can be triggered from userspace via VFIO by calling the VFIO_IOMMU_MAP_DMA ioctl on a vfio device with any address beyond the addressing capabilities of the IOMMU. The problem is that the ioctl code calls iommu_iova_to_phys before it calls iommu_map. iommu_map handles the case that it gets addresses beyond the addressing capabilities of its IOMMU. intel_iommu_iova_to_phys does not. This patch fixes iommu_iova_to_phys to return NULL for addresses beyond what the IOMMU can handle. This in turn causes the ioctl call to fail in iommu_map and (correctly) return EFAULT to the user with a helpful warning message in the kernel log. Signed-off-by: Julian Stecklina Acked-by: Alex Williamson Signed-off-by: Joerg Roedel Signed-off-by: Greg Kroah-Hartman elevator: acquire q->sysfs_lock in elevator_change() commit 7c8a3679e3d8e9d92d58f282161760a0e247df97 upstream. Add locking of q->sysfs_lock into elevator_change() (an exported function) to ensure it is held to protect q->elevator from elevator_init(), even if elevator_change() is called from non-sysfs paths. sysfs path (elv_iosched_store) uses __elevator_change(), non-locking version, as the lock is already taken by elv_iosched_store(). Signed-off-by: Tomoki Sekiyama Signed-off-by: Jens Axboe Cc: Josh Boyer Signed-off-by: Greg Kroah-Hartman dm: fix truncated status strings commit fd7c092e711ebab55b2688d3859d95dfd0301f73 upstream. Avoid returning a truncated table or status string instead of setting the DM_BUFFER_FULL_FLAG when the last target of a table fills the buffer. When processing a table or status request, the function retrieve_status calls ti->type->status. If ti->type->status returns non-zero, retrieve_status assumes that the buffer overflowed and sets DM_BUFFER_FULL_FLAG. However, targets don't return non-zero values from their status method on overflow. Most targets returns always zero. If a buffer overflow happens in a target that is not the last in the table, it gets noticed during the next iteration of the loop in retrieve_status; but if a buffer overflow happens in the last target, it goes unnoticed and erroneously truncated data is returned. In the current code, the targets behave in the following way: * dm-crypt returns -ENOMEM if there is not enough space to store the key, but it returns 0 on all other overflows. * dm-thin returns errors from the status method if a disk error happened. This is incorrect because retrieve_status doesn't check the error code, it assumes that all non-zero values mean buffer overflow. * all the other targets always return 0. This patch changes the ti->type->status function to return void (because most targets don't use the return code). Overflow is detected in retrieve_status: if the status method fills up the remaining space completely, it is assumed that buffer overflow happened. Signed-off-by: Mikulas Patocka Signed-off-by: Alasdair G Kergon Signed-off-by: Greg Kroah-Hartman Conflicts: drivers/md/dm-crypt.c blk-core: Fix memory corruption if blkcg_init_queue fails commit fff4996b7db7955414ac74386efa5e07fd766b50 upstream. If blkcg_init_queue fails, blk_alloc_queue_node doesn't call bdi_destroy to clean up structures allocated by the backing dev. ------------[ cut here ]------------ WARNING: at lib/debugobjects.c:260 debug_print_object+0x85/0xa0() ODEBUG: free active (active state 0) object type: percpu_counter hint: (null) Modules linked in: dm_loop dm_mod ip6table_filter ip6_tables uvesafb cfbcopyarea cfbimgblt cfbfillrect fbcon font bitblit fbcon_rotate fbcon_cw fbcon_ud fbcon_ccw softcursor fb fbdev ipt_MASQUERADE iptable_nat nf_nat_ipv4 msr nf_conntrack_ipv4 nf_defrag_ipv4 xt_state ipt_REJECT xt_tcpudp iptable_filter ip_tables x_tables bridge stp llc tun ipv6 cpufreq_userspace cpufreq_stats cpufreq_powersave cpufreq_ondemand cpufreq_conservative spadfs fuse hid_generic usbhid hid raid0 md_mod dmi_sysfs nf_nat_ftp nf_nat nf_conntrack_ftp nf_conntrack lm85 hwmon_vid snd_usb_audio snd_pcm_oss snd_mixer_oss snd_pcm snd_timer snd_page_alloc snd_hwdep snd_usbmidi_lib snd_rawmidi snd soundcore acpi_cpufreq freq_table mperf sata_svw serverworks kvm_amd ide_core ehci_pci ohci_hcd libata ehci_hcd kvm usbcore tg3 usb_common libphy k10temp pcspkr ptp i2c_piix4 i2c_core evdev microcode hwmon rtc_cmos pps_core e100 skge floppy mii processor button unix CPU: 0 PID: 2739 Comm: lvchange Tainted: G W 3.10.15-devel #14 Hardware name: empty empty/S3992-E, BIOS 'V1.06 ' 06/09/2009 0000000000000009 ffff88023c3c1ae8 ffffffff813c8fd4 ffff88023c3c1b20 ffffffff810399eb ffff88043d35cd58 ffffffff81651940 ffff88023c3c1bf8 ffffffff82479d90 0000000000000005 ffff88023c3c1b80 ffffffff81039a67 Call Trace: [] dump_stack+0x19/0x1b [] warn_slowpath_common+0x6b/0xa0 [] warn_slowpath_fmt+0x47/0x50 [] ? debug_check_no_obj_freed+0xcf/0x250 [] debug_print_object+0x85/0xa0 [] debug_check_no_obj_freed+0x203/0x250 [] kmem_cache_free+0x20c/0x3a0 [] blk_alloc_queue_node+0x2a9/0x2c0 [] blk_alloc_queue+0xe/0x10 [] dm_create+0x1a3/0x530 [dm_mod] [] ? list_version_get_info+0xe0/0xe0 [dm_mod] [] dev_create+0x57/0x2b0 [dm_mod] [] ? list_version_get_info+0xe0/0xe0 [dm_mod] [] ? list_version_get_info+0xe0/0xe0 [dm_mod] [] ctl_ioctl+0x268/0x500 [dm_mod] [] ? get_lock_stats+0x22/0x70 [] dm_ctl_ioctl+0xe/0x20 [dm_mod] [] do_vfs_ioctl+0x2ed/0x520 [] ? fget_light+0x377/0x4e0 [] SyS_ioctl+0x4b/0x90 [] system_call_fastpath+0x1a/0x1f ---[ end trace 4b5ff0d55673d986 ]--- ------------[ cut here ]------------ This fix should be backported to stable kernels starting with 2.6.37. Note that in the kernels prior to 3.5 the affected code is different, but the bug is still there - bdi_init is called and bdi_destroy isn't. Signed-off-by: Mikulas Patocka Acked-by: Tejun Heo Signed-off-by: Jens Axboe Signed-off-by: Greg Kroah-Hartman --- Makefile | 2 +- block/blk-core.c | 4 +- block/elevator.c | 16 +++++- crypto/algif_hash.c | 5 +- crypto/algif_skcipher.c | 4 +- drivers/atm/idt77252.c | 2 +- drivers/connector/cn_proc.c | 66 +++++++++++++--------- drivers/hid/hid-picolcd.c | 2 +- drivers/iommu/intel-iommu.c | 6 +- drivers/isdn/isdnloop/isdnloop.c | 8 ++- drivers/isdn/mISDN/socket.c | 13 ++--- drivers/md/dm-crypt.c | 37 +++--------- drivers/md/dm-delay.c | 6 +- drivers/md/dm-flakey.c | 5 +- drivers/md/dm-ioctl.c | 18 +++--- drivers/md/dm-linear.c | 5 +- drivers/md/dm-mpath.c | 6 +- drivers/md/dm-raid.c | 6 +- drivers/md/dm-raid1.c | 6 +- drivers/md/dm-snap.c | 12 ++-- drivers/md/dm-stripe.c | 5 +- drivers/md/dm-thin.c | 74 ++++++++++++++---------- drivers/md/dm-verity.c | 6 +- drivers/mmc/card/block.c | 7 +++ drivers/net/bonding/bond_sysfs.c | 11 +++- drivers/net/ppp/pppoe.c | 2 - drivers/video/kyro/fbdev.c | 6 +- fs/nfsd/nfssvc.c | 3 +- include/linux/device-mapper.h | 4 +- include/linux/net.h | 8 +++ include/linux/random.h | 6 +- lib/random32.c | 14 ++--- net/appletalk/ddp.c | 16 +++--- net/atm/common.c | 2 - net/ax25/af_ax25.c | 4 +- net/bluetooth/af_bluetooth.c | 4 -- net/bluetooth/hci_sock.c | 2 - net/bluetooth/rfcomm/sock.c | 1 - net/bridge/br_if.c | 2 + net/caif/caif_socket.c | 4 -- net/compat.c | 5 +- net/core/dev.c | 2 +- net/core/fib_rules.c | 3 +- net/core/iovec.c | 3 +- net/core/pktgen.c | 7 +++ net/ieee802154/6lowpan.c | 4 +- net/ipv4/datagram.c | 2 +- net/ipv4/ping.c | 2 +- net/ipv4/tcp_ipv4.c | 2 +- net/ipv4/udp.c | 5 +- net/ipv6/datagram.c | 1 + net/ipv6/ip6_output.c | 4 +- net/ipv6/route.c | 7 ++- net/ipx/af_ipx.c | 3 +- net/irda/af_irda.c | 4 -- net/iucv/af_iucv.c | 2 - net/key/af_key.c | 1 - net/l2tp/l2tp_ppp.c | 2 - net/llc/af_llc.c | 2 - net/netlink/af_netlink.c | 2 - net/netrom/af_netrom.c | 3 +- net/nfc/rawsock.c | 2 - net/packet/af_packet.c | 96 ++++++++++++++++++-------------- net/rds/recv.c | 2 - net/rose/af_rose.c | 8 ++- net/rxrpc/ar-recvmsg.c | 9 ++- net/socket.c | 24 ++++---- net/tipc/socket.c | 6 -- net/unix/af_unix.c | 5 -- net/x25/af_x25.c | 3 +- 70 files changed, 329 insertions(+), 302 deletions(-) diff --git a/Makefile b/Makefile index cc33c605162..9fdac86057c 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 4 -SUBLEVEL = 72 +SUBLEVEL = 73 EXTRAVERSION = NAME = Saber-toothed Squirrel diff --git a/block/blk-core.c b/block/blk-core.c index 7641d1e372c..95a6b4a5341 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -513,7 +513,7 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id) goto fail_id; if (blk_throtl_init(q)) - goto fail_id; + goto fail_bdi; setup_timer(&q->backing_dev_info.laptop_mode_wb_timer, laptop_mode_timer_fn, (unsigned long) q); @@ -538,6 +538,8 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id) return q; +fail_bdi: + bdi_destroy(&q->backing_dev_info); fail_id: ida_simple_remove(&blk_queue_ida, q->id); fail_q: diff --git a/block/elevator.c b/block/elevator.c index 4368180a8df..eb326af2bb6 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -1036,7 +1036,7 @@ static int elevator_switch(struct request_queue *q, struct elevator_type *new_e) /* * Switch this queue to the given IO scheduler. */ -int elevator_change(struct request_queue *q, const char *name) +static int __elevator_change(struct request_queue *q, const char *name) { char elevator_name[ELV_NAME_MAX]; struct elevator_type *e; @@ -1058,6 +1058,18 @@ int elevator_change(struct request_queue *q, const char *name) return elevator_switch(q, e); } + +int elevator_change(struct request_queue *q, const char *name) +{ + int ret; + + /* Protect q->elevator from elevator_init() */ + mutex_lock(&q->sysfs_lock); + ret = __elevator_change(q, name); + mutex_unlock(&q->sysfs_lock); + + return ret; +} EXPORT_SYMBOL(elevator_change); ssize_t elv_iosched_store(struct request_queue *q, const char *name, @@ -1068,7 +1080,7 @@ ssize_t elv_iosched_store(struct request_queue *q, const char *name, if (!q->elevator) return count; - ret = elevator_change(q, name); + ret = __elevator_change(q, name); if (!ret) return count; diff --git a/crypto/algif_hash.c b/crypto/algif_hash.c index 0262210cad3..850246206b1 100644 --- a/crypto/algif_hash.c +++ b/crypto/algif_hash.c @@ -114,6 +114,9 @@ static ssize_t hash_sendpage(struct socket *sock, struct page *page, struct hash_ctx *ctx = ask->private; int err; + if (flags & MSG_SENDPAGE_NOTLAST) + flags |= MSG_MORE; + lock_sock(sk); sg_init_table(ctx->sgl.sg, 1); sg_set_page(ctx->sgl.sg, page, size, offset); @@ -161,8 +164,6 @@ static int hash_recvmsg(struct kiocb *unused, struct socket *sock, else if (len < ds) msg->msg_flags |= MSG_TRUNC; - msg->msg_namelen = 0; - lock_sock(sk); if (ctx->more) { ctx->more = 0; diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c index a1c4f0a5558..a19c027b29b 100644 --- a/crypto/algif_skcipher.c +++ b/crypto/algif_skcipher.c @@ -378,6 +378,9 @@ static ssize_t skcipher_sendpage(struct socket *sock, struct page *page, struct skcipher_sg_list *sgl; int err = -EINVAL; + if (flags & MSG_SENDPAGE_NOTLAST) + flags |= MSG_MORE; + lock_sock(sk); if (!ctx->more && ctx->used) goto unlock; @@ -432,7 +435,6 @@ static int skcipher_recvmsg(struct kiocb *unused, struct socket *sock, long copied = 0; lock_sock(sk); - msg->msg_namelen = 0; for (iov = msg->msg_iov, iovlen = msg->msg_iovlen; iovlen > 0; iovlen--, iov++) { unsigned long seglen = iov->iov_len; diff --git a/drivers/atm/idt77252.c b/drivers/atm/idt77252.c index 1c052127548..b0e75ce3c8f 100644 --- a/drivers/atm/idt77252.c +++ b/drivers/atm/idt77252.c @@ -3513,7 +3513,7 @@ init_card(struct atm_dev *dev) tmp = dev_get_by_name(&init_net, tname); /* jhs: was "tmp = dev_get(tname);" */ if (tmp) { memcpy(card->atmdev->esi, tmp->dev_addr, 6); - + dev_put(tmp); printk("%s: ESI %pM\n", card->name, card->atmdev->esi); } /* diff --git a/drivers/connector/cn_proc.c b/drivers/connector/cn_proc.c index 2894461e0bd..ff18e41f5b2 100644 --- a/drivers/connector/cn_proc.c +++ b/drivers/connector/cn_proc.c @@ -31,11 +31,23 @@ #include #include -#include - #include -#define CN_PROC_MSG_SIZE (sizeof(struct cn_msg) + sizeof(struct proc_event)) +/* + * Size of a cn_msg followed by a proc_event structure. Since the + * sizeof struct cn_msg is a multiple of 4 bytes, but not 8 bytes, we + * add one 4-byte word to the size here, and then start the actual + * cn_msg structure 4 bytes into the stack buffer. The result is that + * the immediately following proc_event structure is aligned to 8 bytes. + */ +#define CN_PROC_MSG_SIZE (sizeof(struct cn_msg) + sizeof(struct proc_event) + 4) + +/* See comment above; we test our assumption about sizeof struct cn_msg here. */ +static inline struct cn_msg *buffer_to_cn_msg(__u8 *buffer) +{ + BUILD_BUG_ON(sizeof(struct cn_msg) != 20); + return (struct cn_msg *)(buffer + 4); +} static atomic_t proc_event_num_listeners = ATOMIC_INIT(0); static struct cb_id cn_proc_event_id = { CN_IDX_PROC, CN_VAL_PROC }; @@ -55,19 +67,19 @@ void proc_fork_connector(struct task_struct *task) { struct cn_msg *msg; struct proc_event *ev; - __u8 buffer[CN_PROC_MSG_SIZE]; + __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8); struct timespec ts; struct task_struct *parent; if (atomic_read(&proc_event_num_listeners) < 1) return; - msg = (struct cn_msg*)buffer; + msg = buffer_to_cn_msg(buffer); ev = (struct proc_event*)msg->data; memset(&ev->event_data, 0, sizeof(ev->event_data)); get_seq(&msg->seq, &ev->cpu); ktime_get_ts(&ts); /* get high res monotonic timestamp */ - put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); + ev->timestamp_ns = timespec_to_ns(&ts); ev->what = PROC_EVENT_FORK; rcu_read_lock(); parent = rcu_dereference(task->real_parent); @@ -90,17 +102,17 @@ void proc_exec_connector(struct task_struct *task) struct cn_msg *msg; struct proc_event *ev; struct timespec ts; - __u8 buffer[CN_PROC_MSG_SIZE]; + __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8); if (atomic_read(&proc_event_num_listeners) < 1) return; - msg = (struct cn_msg*)buffer; + msg = buffer_to_cn_msg(buffer); ev = (struct proc_event*)msg->data; memset(&ev->event_data, 0, sizeof(ev->event_data)); get_seq(&msg->seq, &ev->cpu); ktime_get_ts(&ts); /* get high res monotonic timestamp */ - put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); + ev->timestamp_ns = timespec_to_ns(&ts); ev->what = PROC_EVENT_EXEC; ev->event_data.exec.process_pid = task->pid; ev->event_data.exec.process_tgid = task->tgid; @@ -116,14 +128,14 @@ void proc_id_connector(struct task_struct *task, int which_id) { struct cn_msg *msg; struct proc_event *ev; - __u8 buffer[CN_PROC_MSG_SIZE]; + __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8); struct timespec ts; const struct cred *cred; if (atomic_read(&proc_event_num_listeners) < 1) return; - msg = (struct cn_msg*)buffer; + msg = buffer_to_cn_msg(buffer); ev = (struct proc_event*)msg->data; memset(&ev->event_data, 0, sizeof(ev->event_data)); ev->what = which_id; @@ -144,7 +156,7 @@ void proc_id_connector(struct task_struct *task, int which_id) rcu_read_unlock(); get_seq(&msg->seq, &ev->cpu); ktime_get_ts(&ts); /* get high res monotonic timestamp */ - put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); + ev->timestamp_ns = timespec_to_ns(&ts); memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); msg->ack = 0; /* not used */ @@ -158,17 +170,17 @@ void proc_sid_connector(struct task_struct *task) struct cn_msg *msg; struct proc_event *ev; struct timespec ts; - __u8 buffer[CN_PROC_MSG_SIZE]; + __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8); if (atomic_read(&proc_event_num_listeners) < 1) return; - msg = (struct cn_msg *)buffer; + msg = buffer_to_cn_msg(buffer); ev = (struct proc_event *)msg->data; memset(&ev->event_data, 0, sizeof(ev->event_data)); get_seq(&msg->seq, &ev->cpu); ktime_get_ts(&ts); /* get high res monotonic timestamp */ - put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); + ev->timestamp_ns = timespec_to_ns(&ts); ev->what = PROC_EVENT_SID; ev->event_data.sid.process_pid = task->pid; ev->event_data.sid.process_tgid = task->tgid; @@ -185,17 +197,17 @@ void proc_ptrace_connector(struct task_struct *task, int ptrace_id) struct cn_msg *msg; struct proc_event *ev; struct timespec ts; - __u8 buffer[CN_PROC_MSG_SIZE]; + __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8); if (atomic_read(&proc_event_num_listeners) < 1) return; - msg = (struct cn_msg *)buffer; + msg = buffer_to_cn_msg(buffer); ev = (struct proc_event *)msg->data; memset(&ev->event_data, 0, sizeof(ev->event_data)); get_seq(&msg->seq, &ev->cpu); ktime_get_ts(&ts); /* get high res monotonic timestamp */ - put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); + ev->timestamp_ns = timespec_to_ns(&ts); ev->what = PROC_EVENT_PTRACE; ev->event_data.ptrace.process_pid = task->pid; ev->event_data.ptrace.process_tgid = task->tgid; @@ -220,17 +232,17 @@ void proc_comm_connector(struct task_struct *task) struct cn_msg *msg; struct proc_event *ev; struct timespec ts; - __u8 buffer[CN_PROC_MSG_SIZE]; + __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8); if (atomic_read(&proc_event_num_listeners) < 1) return; - msg = (struct cn_msg *)buffer; + msg = buffer_to_cn_msg(buffer); ev = (struct proc_event *)msg->data; memset(&ev->event_data, 0, sizeof(ev->event_data)); get_seq(&msg->seq, &ev->cpu); ktime_get_ts(&ts); /* get high res monotonic timestamp */ - put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); + ev->timestamp_ns = timespec_to_ns(&ts); ev->what = PROC_EVENT_COMM; ev->event_data.comm.process_pid = task->pid; ev->event_data.comm.process_tgid = task->tgid; @@ -247,18 +259,18 @@ void proc_exit_connector(struct task_struct *task) { struct cn_msg *msg; struct proc_event *ev; - __u8 buffer[CN_PROC_MSG_SIZE]; + __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8); struct timespec ts; if (atomic_read(&proc_event_num_listeners) < 1) return; - msg = (struct cn_msg*)buffer; + msg = buffer_to_cn_msg(buffer); ev = (struct proc_event*)msg->data; memset(&ev->event_data, 0, sizeof(ev->event_data)); get_seq(&msg->seq, &ev->cpu); ktime_get_ts(&ts); /* get high res monotonic timestamp */ - put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); + ev->timestamp_ns = timespec_to_ns(&ts); ev->what = PROC_EVENT_EXIT; ev->event_data.exit.process_pid = task->pid; ev->event_data.exit.process_tgid = task->tgid; @@ -284,18 +296,18 @@ static void cn_proc_ack(int err, int rcvd_seq, int rcvd_ack) { struct cn_msg *msg; struct proc_event *ev; - __u8 buffer[CN_PROC_MSG_SIZE]; + __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8); struct timespec ts; if (atomic_read(&proc_event_num_listeners) < 1) return; - msg = (struct cn_msg*)buffer; + msg = buffer_to_cn_msg(buffer); ev = (struct proc_event*)msg->data; memset(&ev->event_data, 0, sizeof(ev->event_data)); msg->seq = rcvd_seq; ktime_get_ts(&ts); /* get high res monotonic timestamp */ - put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); + ev->timestamp_ns = timespec_to_ns(&ts); ev->cpu = -1; ev->what = PROC_EVENT_NONE; ev->event_data.ack.err = err; diff --git a/drivers/hid/hid-picolcd.c b/drivers/hid/hid-picolcd.c index 45c3433f798..95f90479f28 100644 --- a/drivers/hid/hid-picolcd.c +++ b/drivers/hid/hid-picolcd.c @@ -1424,7 +1424,7 @@ static ssize_t picolcd_operation_mode_store(struct device *dev, buf += 10; cnt -= 10; } - if (!report) + if (!report || report->maxfield != 1) return -EINVAL; while (cnt > 0 && (buf[cnt-1] == '\n' || buf[cnt-1] == '\r')) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index a60a54d8593..abc6ac85559 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -778,7 +778,11 @@ static struct dma_pte *pfn_to_dma_pte(struct dmar_domain *domain, int offset; BUG_ON(!domain->pgd); - BUG_ON(addr_width < BITS_PER_LONG && pfn >> addr_width); + + if (addr_width < BITS_PER_LONG && pfn >> addr_width) + /* Address beyond IOMMU's addressing capabilities. */ + return NULL; + parent = domain->pgd; while (level > 0) { diff --git a/drivers/isdn/isdnloop/isdnloop.c b/drivers/isdn/isdnloop/isdnloop.c index baf2686aa8e..02125e6a910 100644 --- a/drivers/isdn/isdnloop/isdnloop.c +++ b/drivers/isdn/isdnloop/isdnloop.c @@ -1083,8 +1083,10 @@ isdnloop_start(isdnloop_card *card, isdnloop_sdef *sdefp) spin_unlock_irqrestore(&card->isdnloop_lock, flags); return -ENOMEM; } - for (i = 0; i < 3; i++) - strcpy(card->s0num[i], sdef.num[i]); + for (i = 0; i < 3; i++) { + strlcpy(card->s0num[i], sdef.num[i], + sizeof(card->s0num[0])); + } break; case ISDN_PTYPE_1TR6: if (isdnloop_fake(card, "DRV1.04TC-1TR6-CAPI-CNS-BASIS-29.11.95", @@ -1097,7 +1099,7 @@ isdnloop_start(isdnloop_card *card, isdnloop_sdef *sdefp) spin_unlock_irqrestore(&card->isdnloop_lock, flags); return -ENOMEM; } - strcpy(card->s0num[0], sdef.num[0]); + strlcpy(card->s0num[0], sdef.num[0], sizeof(card->s0num[0])); card->s0num[1][0] = '\0'; card->s0num[2][0] = '\0'; break; diff --git a/drivers/isdn/mISDN/socket.c b/drivers/isdn/mISDN/socket.c index abe2d699b6f..ade1bcfb0e6 100644 --- a/drivers/isdn/mISDN/socket.c +++ b/drivers/isdn/mISDN/socket.c @@ -117,7 +117,6 @@ mISDN_sock_recvmsg(struct kiocb *iocb, struct socket *sock, { struct sk_buff *skb; struct sock *sk = sock->sk; - struct sockaddr_mISDN *maddr; int copied, err; @@ -135,9 +134,9 @@ mISDN_sock_recvmsg(struct kiocb *iocb, struct socket *sock, if (!skb) return err; - if (msg->msg_namelen >= sizeof(struct sockaddr_mISDN)) { - msg->msg_namelen = sizeof(struct sockaddr_mISDN); - maddr = (struct sockaddr_mISDN *)msg->msg_name; + if (msg->msg_name) { + struct sockaddr_mISDN *maddr = msg->msg_name; + maddr->family = AF_ISDN; maddr->dev = _pms(sk)->dev->id; if ((sk->sk_protocol == ISDN_P_LAPD_TE) || @@ -150,11 +149,7 @@ mISDN_sock_recvmsg(struct kiocb *iocb, struct socket *sock, maddr->sapi = _pms(sk)->ch.addr & 0xFF; maddr->tei = (_pms(sk)->ch.addr >> 8) & 0xFF; } - } else { - if (msg->msg_namelen) - printk(KERN_WARNING "%s: too small namelen %d\n", - __func__, msg->msg_namelen); - msg->msg_namelen = 0; + msg->msg_namelen = sizeof(*maddr); } copied = skb->len + MISDN_HEADER_LEN; diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index d749d9257a2..36cf561d299 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -1236,20 +1236,6 @@ static int crypt_decode_key(u8 *key, char *hex, unsigned int size) return 0; } -/* - * Encode key into its hex representation - */ -static void crypt_encode_key(char *hex, u8 *key, unsigned int size) -{ - unsigned int i; - - for (i = 0; i < size; i++) { - sprintf(hex, "%02x", *key); - hex += 2; - key++; - } -} - static void crypt_free_tfms(struct crypt_config *cc) { unsigned i; @@ -1699,11 +1685,11 @@ static int crypt_map(struct dm_target *ti, struct bio *bio, return DM_MAPIO_SUBMITTED; } -static int crypt_status(struct dm_target *ti, status_type_t type, - char *result, unsigned int maxlen) +static void crypt_status(struct dm_target *ti, status_type_t type, + char *result, unsigned int maxlen) { struct crypt_config *cc = ti->private; - unsigned int sz = 0; + unsigned i, sz = 0; switch (type) { case STATUSTYPE_INFO: @@ -1713,17 +1699,11 @@ static int crypt_status(struct dm_target *ti, status_type_t type, case STATUSTYPE_TABLE: DMEMIT("%s ", cc->cipher_string); - if (cc->key_size > 0) { - if ((maxlen - sz) < ((cc->key_size << 1) + 1)) - return -ENOMEM; - - crypt_encode_key(result + sz, cc->key, cc->key_size); - sz += cc->key_size << 1; - } else { - if (sz >= maxlen) - return -ENOMEM; - result[sz++] = '-'; - } + if (cc->key_size > 0) + for (i = 0; i < cc->key_size; i++) + DMEMIT("%02x", cc->key[i]); + else + DMEMIT("-"); DMEMIT(" %llu %s %llu", (unsigned long long)cc->iv_offset, cc->dev->name, (unsigned long long)cc->start); @@ -1733,7 +1713,6 @@ static int crypt_status(struct dm_target *ti, status_type_t type, break; } - return 0; } static void crypt_postsuspend(struct dm_target *ti) diff --git a/drivers/md/dm-delay.c b/drivers/md/dm-delay.c index 2dc22dddb2a..ee99912596c 100644 --- a/drivers/md/dm-delay.c +++ b/drivers/md/dm-delay.c @@ -294,8 +294,8 @@ static int delay_map(struct dm_target *ti, struct bio *bio, return delay_bio(dc, dc->read_delay, bio); } -static int delay_status(struct dm_target *ti, status_type_t type, - char *result, unsigned maxlen) +static void delay_status(struct dm_target *ti, status_type_t type, + char *result, unsigned maxlen) { struct delay_c *dc = ti->private; int sz = 0; @@ -315,8 +315,6 @@ static int delay_status(struct dm_target *ti, status_type_t type, dc->write_delay); break; } - - return 0; } static int delay_iterate_devices(struct dm_target *ti, diff --git a/drivers/md/dm-flakey.c b/drivers/md/dm-flakey.c index ac49c01f1a4..f29d665fe83 100644 --- a/drivers/md/dm-flakey.c +++ b/drivers/md/dm-flakey.c @@ -332,8 +332,8 @@ static int flakey_end_io(struct dm_target *ti, struct bio *bio, return error; } -static int flakey_status(struct dm_target *ti, status_type_t type, - char *result, unsigned int maxlen) +static void flakey_status(struct dm_target *ti, status_type_t type, + char *result, unsigned int maxlen) { unsigned sz = 0; struct flakey_c *fc = ti->private; @@ -363,7 +363,6 @@ static int flakey_status(struct dm_target *ti, status_type_t type, break; } - return 0; } static int flakey_ioctl(struct dm_target *ti, unsigned int cmd, unsigned long arg) diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index a1a3e6df17b..6a0432086e3 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c @@ -1066,6 +1066,7 @@ static void retrieve_status(struct dm_table *table, num_targets = dm_table_get_num_targets(table); for (i = 0; i < num_targets; i++) { struct dm_target *ti = dm_table_get_target(table, i); + size_t l; remaining = len - (outptr - outbuf); if (remaining <= sizeof(struct dm_target_spec)) { @@ -1089,15 +1090,18 @@ static void retrieve_status(struct dm_table *table, } /* Get the status/table string from the target driver */ - if (ti->type->status) { - if (ti->type->status(ti, type, outptr, remaining)) { - param->flags |= DM_BUFFER_FULL_FLAG; - break; - } - } else + if (ti->type->status) + ti->type->status(ti, type, outptr, remaining); + else outptr[0] = '\0'; - outptr += strlen(outptr) + 1; + l = strlen(outptr) + 1; + if (l == remaining) { + param->flags |= DM_BUFFER_FULL_FLAG; + break; + } + + outptr += l; used = param->data_start + (outptr - outbuf); outptr = align_ptr(outptr); diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c index 3639eeab604..5a5e9c8b29a 100644 --- a/drivers/md/dm-linear.c +++ b/drivers/md/dm-linear.c @@ -95,8 +95,8 @@ static int linear_map(struct dm_target *ti, struct bio *bio, return DM_MAPIO_REMAPPED; } -static int linear_status(struct dm_target *ti, status_type_t type, - char *result, unsigned int maxlen) +static void linear_status(struct dm_target *ti, status_type_t type, + char *result, unsigned int maxlen) { struct linear_c *lc = (struct linear_c *) ti->private; @@ -110,7 +110,6 @@ static int linear_status(struct dm_target *ti, status_type_t type, (unsigned long long)lc->start); break; } - return 0; } static int linear_ioctl(struct dm_target *ti, unsigned int cmd, diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index 754f38f8a69..b74cb796c17 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c @@ -1343,8 +1343,8 @@ static void multipath_resume(struct dm_target *ti) * [priority selector-name num_ps_args [ps_args]* * num_paths num_selector_args [path_dev [selector_args]* ]+ ]+ */ -static int multipath_status(struct dm_target *ti, status_type_t type, - char *result, unsigned int maxlen) +static void multipath_status(struct dm_target *ti, status_type_t type, + char *result, unsigned int maxlen) { int sz = 0; unsigned long flags; @@ -1447,8 +1447,6 @@ static int multipath_status(struct dm_target *ti, status_type_t type, } spin_unlock_irqrestore(&m->lock, flags); - - return 0; } static int multipath_message(struct dm_target *ti, unsigned argc, char **argv) diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c index 68965e66324..ead5ca99a74 100644 --- a/drivers/md/dm-raid.c +++ b/drivers/md/dm-raid.c @@ -1067,8 +1067,8 @@ static int raid_map(struct dm_target *ti, struct bio *bio, union map_info *map_c return DM_MAPIO_SUBMITTED; } -static int raid_status(struct dm_target *ti, status_type_t type, - char *result, unsigned maxlen) +static void raid_status(struct dm_target *ti, status_type_t type, + char *result, unsigned maxlen) { struct raid_set *rs = ti->private; unsigned raid_param_cnt = 1; /* at least 1 for chunksize */ @@ -1203,8 +1203,6 @@ static int raid_status(struct dm_target *ti, status_type_t type, DMEMIT(" -"); } } - - return 0; } static int raid_iterate_devices(struct dm_target *ti, iterate_devices_callout_fn fn, void *data) diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index d039de8322f..19d08e28429 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c @@ -1361,8 +1361,8 @@ static char device_status_char(struct mirror *m) } -static int mirror_status(struct dm_target *ti, status_type_t type, - char *result, unsigned int maxlen) +static void mirror_status(struct dm_target *ti, status_type_t type, + char *result, unsigned int maxlen) { unsigned int m, sz = 0; struct mirror_set *ms = (struct mirror_set *) ti->private; @@ -1397,8 +1397,6 @@ static int mirror_status(struct dm_target *ti, status_type_t type, if (ms->features & DM_RAID1_HANDLE_ERRORS) DMEMIT(" 1 handle_errors"); } - - return 0; } static int mirror_iterate_devices(struct dm_target *ti, diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index 448050c87be..db77ac69332 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c @@ -1845,8 +1845,8 @@ static void snapshot_merge_resume(struct dm_target *ti) start_merge(s); } -static int snapshot_status(struct dm_target *ti, status_type_t type, - char *result, unsigned int maxlen) +static void snapshot_status(struct dm_target *ti, status_type_t type, + char *result, unsigned int maxlen) { unsigned sz = 0; struct dm_snapshot *snap = ti->private; @@ -1892,8 +1892,6 @@ static int snapshot_status(struct dm_target *ti, status_type_t type, maxlen - sz); break; } - - return 0; } static int snapshot_iterate_devices(struct dm_target *ti, @@ -2148,8 +2146,8 @@ static void origin_resume(struct dm_target *ti) ti->split_io = get_origin_minimum_chunksize(dev->bdev); } -static int origin_status(struct dm_target *ti, status_type_t type, char *result, - unsigned int maxlen) +static void origin_status(struct dm_target *ti, status_type_t type, char *result, + unsigned int maxlen) { struct dm_dev *dev = ti->private; @@ -2162,8 +2160,6 @@ static int origin_status(struct dm_target *ti, status_type_t type, char *result, snprintf(result, maxlen, "%s", dev->name); break; } - - return 0; } static int origin_merge(struct dm_target *ti, struct bvec_merge_data *bvm, diff --git a/drivers/md/dm-stripe.c b/drivers/md/dm-stripe.c index 35c94ff24ad..58ffcda3dab 100644 --- a/drivers/md/dm-stripe.c +++ b/drivers/md/dm-stripe.c @@ -302,8 +302,8 @@ static int stripe_map(struct dm_target *ti, struct bio *bio, * */ -static int stripe_status(struct dm_target *ti, - status_type_t type, char *result, unsigned int maxlen) +static void stripe_status(struct dm_target *ti, + status_type_t type, char *result, unsigned int maxlen) { struct stripe_c *sc = (struct stripe_c *) ti->private; char buffer[sc->stripes + 1]; @@ -330,7 +330,6 @@ static int stripe_status(struct dm_target *ti, (unsigned long long)sc->stripe[i].physical_start); break; } - return 0; } static int stripe_end_io(struct dm_target *ti, struct bio *bio, diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c index 79b7b715e6c..4847f65498d 100644 --- a/drivers/md/dm-thin.c +++ b/drivers/md/dm-thin.c @@ -2321,8 +2321,8 @@ static int pool_message(struct dm_target *ti, unsigned argc, char **argv) * / * / */ -static int pool_status(struct dm_target *ti, status_type_t type, - char *result, unsigned maxlen) +static void pool_status(struct dm_target *ti, status_type_t type, + char *result, unsigned maxlen) { int r, count; unsigned sz = 0; @@ -2339,32 +2339,41 @@ static int pool_status(struct dm_target *ti, status_type_t type, switch (type) { case STATUSTYPE_INFO: - r = dm_pool_get_metadata_transaction_id(pool->pmd, - &transaction_id); - if (r) - return r; + r = dm_pool_get_metadata_transaction_id(pool->pmd, &transaction_id); + if (r) { + DMERR("dm_pool_get_metadata_transaction_id returned %d", r); + goto err; + } - r = dm_pool_get_free_metadata_block_count(pool->pmd, - &nr_free_blocks_metadata); - if (r) - return r; + r = dm_pool_get_free_metadata_block_count(pool->pmd, &nr_free_blocks_metadata); + if (r) { + DMERR("dm_pool_get_free_metadata_block_count returned %d", r); + goto err; + } r = dm_pool_get_metadata_dev_size(pool->pmd, &nr_blocks_metadata); - if (r) - return r; + if (r) { + DMERR("dm_pool_get_metadata_dev_size returned %d", r); + goto err; + } - r = dm_pool_get_free_block_count(pool->pmd, - &nr_free_blocks_data); - if (r) - return r; + r = dm_pool_get_free_block_count(pool->pmd, &nr_free_blocks_data); + if (r) { + DMERR("dm_pool_get_free_block_count returned %d", r); + goto err; + } r = dm_pool_get_data_dev_size(pool->pmd, &nr_blocks_data); - if (r) - return r; + if (r) { + DMERR("dm_pool_get_data_dev_size returned %d", r); + goto err; + } r = dm_pool_get_held_metadata_root(pool->pmd, &held_root); - if (r) - return r; + if (r) { + DMERR("dm_pool_get_metadata_snap returned %d", r); + goto err; + } DMEMIT("%llu %llu/%llu %llu/%llu ", (unsigned long long)transaction_id, @@ -2402,8 +2411,10 @@ static int pool_status(struct dm_target *ti, status_type_t type, break; } + return; - return 0; +err: + DMEMIT("Error"); } static int pool_iterate_devices(struct dm_target *ti, @@ -2654,8 +2665,8 @@ static void thin_postsuspend(struct dm_target *ti) /* * */ -static int thin_status(struct dm_target *ti, status_type_t type, - char *result, unsigned maxlen) +static void thin_status(struct dm_target *ti, status_type_t type, + char *result, unsigned maxlen) { int r; ssize_t sz = 0; @@ -2669,12 +2680,16 @@ static int thin_status(struct dm_target *ti, status_type_t type, switch (type) { case STATUSTYPE_INFO: r = dm_thin_get_mapped_count(tc->td, &mapped); - if (r) - return r; + if (r) { + DMERR("dm_thin_get_mapped_count returned %d", r); + goto err; + } r = dm_thin_get_highest_mapped_block(tc->td, &highest); - if (r < 0) - return r; + if (r < 0) { + DMERR("dm_thin_get_highest_mapped_block returned %d", r); + goto err; + } DMEMIT("%llu ", mapped * tc->pool->sectors_per_block); if (r) @@ -2694,7 +2709,10 @@ static int thin_status(struct dm_target *ti, status_type_t type, } } - return 0; + return; + +err: + DMEMIT("Error"); } static int thin_iterate_devices(struct dm_target *ti, diff --git a/drivers/md/dm-verity.c b/drivers/md/dm-verity.c index 1f1b4a47ee4..4e9a327d04e 100644 --- a/drivers/md/dm-verity.c +++ b/drivers/md/dm-verity.c @@ -514,8 +514,8 @@ static int verity_map(struct dm_target *ti, struct bio *bio, /* * Status: V (valid) or C (corruption found) */ -static int verity_status(struct dm_target *ti, status_type_t type, - char *result, unsigned maxlen) +static void verity_status(struct dm_target *ti, status_type_t type, + char *result, unsigned maxlen) { struct dm_verity *v = ti->private; unsigned sz = 0; @@ -546,8 +546,6 @@ static int verity_status(struct dm_target *ti, status_type_t type, DMEMIT("%02x", v->salt[x]); break; } - - return 0; } static int verity_ioctl(struct dm_target *ti, unsigned cmd, diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 15bebc861ac..8998e179a2e 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -1217,6 +1217,13 @@ static int mmc_blk_err_check(struct mmc_card *card, (R1_CURRENT_STATE(status) == R1_STATE_PRG)); } + /* if general error occurs, retry the write operation. */ + if (gen_err) { + pr_warning("%s: retrying write for general error\n", + req->rq_disk->disk_name); + return MMC_BLK_RETRY; + } + /* if general error occurs, retry the write operation. */ if (gen_err) { pr_warn("%s: retrying write for general error\n", diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index c40c0a87181..f42a00ac38d 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -533,8 +533,9 @@ static ssize_t bonding_store_arp_interval(struct device *d, goto out; } if (bond->params.mode == BOND_MODE_ALB || - bond->params.mode == BOND_MODE_TLB) { - pr_info("%s: ARP monitoring cannot be used with ALB/TLB. Only MII monitoring is supported on %s.\n", + bond->params.mode == BOND_MODE_TLB || + bond->params.mode == BOND_MODE_8023AD) { + pr_info("%s: ARP monitoring cannot be used with ALB/TLB/802.3ad. Only MII monitoring is supported on %s.\n", bond->dev->name, bond->dev->name); ret = -EINVAL; goto out; @@ -692,6 +693,8 @@ static ssize_t bonding_store_downdelay(struct device *d, int new_value, ret = count; struct bonding *bond = to_bond(d); + if (!rtnl_trylock()) + return restart_syscall(); if (!(bond->params.miimon)) { pr_err("%s: Unable to set down delay as MII monitoring is disabled\n", bond->dev->name); @@ -725,6 +728,7 @@ static ssize_t bonding_store_downdelay(struct device *d, } out: + rtnl_unlock(); return ret; } static DEVICE_ATTR(downdelay, S_IRUGO | S_IWUSR, @@ -747,6 +751,8 @@ static ssize_t bonding_store_updelay(struct device *d, int new_value, ret = count; struct bonding *bond = to_bond(d); + if (!rtnl_trylock()) + return restart_syscall(); if (!(bond->params.miimon)) { pr_err("%s: Unable to set up delay as MII monitoring is disabled\n", bond->dev->name); @@ -780,6 +786,7 @@ static ssize_t bonding_store_updelay(struct device *d, } out: + rtnl_unlock(); return ret; } static DEVICE_ATTR(updelay, S_IRUGO | S_IWUSR, diff --git a/drivers/net/ppp/pppoe.c b/drivers/net/ppp/pppoe.c index 2e0d8762bb5..bac88c22d99 100644 --- a/drivers/net/ppp/pppoe.c +++ b/drivers/net/ppp/pppoe.c @@ -985,8 +985,6 @@ static int pppoe_recvmsg(struct kiocb *iocb, struct socket *sock, if (error < 0) goto end; - m->msg_namelen = 0; - if (skb) { total_len = min_t(size_t, total_len, skb->len); error = skb_copy_datagram_iovec(skb, 0, m->msg_iov, total_len); diff --git a/drivers/video/kyro/fbdev.c b/drivers/video/kyro/fbdev.c index acb9370fdb1..7aa8668f0a0 100644 --- a/drivers/video/kyro/fbdev.c +++ b/drivers/video/kyro/fbdev.c @@ -625,15 +625,15 @@ static int kyrofb_ioctl(struct fb_info *info, } break; case KYRO_IOCTL_UVSTRIDE: - if (copy_to_user(argp, &deviceInfo.ulOverlayUVStride, sizeof(unsigned long))) + if (copy_to_user(argp, &deviceInfo.ulOverlayUVStride, sizeof(deviceInfo.ulOverlayUVStride))) return -EFAULT; break; case KYRO_IOCTL_STRIDE: - if (copy_to_user(argp, &deviceInfo.ulOverlayStride, sizeof(unsigned long))) + if (copy_to_user(argp, &deviceInfo.ulOverlayStride, sizeof(deviceInfo.ulOverlayStride))) return -EFAULT; break; case KYRO_IOCTL_OVERLAY_OFFSET: - if (copy_to_user(argp, &deviceInfo.ulOverlayOffset, sizeof(unsigned long))) + if (copy_to_user(argp, &deviceInfo.ulOverlayOffset, sizeof(deviceInfo.ulOverlayOffset))) return -EFAULT; break; } diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index 53459b055cf..25d839ed0ae 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include @@ -330,7 +329,7 @@ static int nfsd_get_default_max_blksize(void) int nfsd_create_serv(void) { int error; - struct net *net = current->nsproxy->net_ns; + struct net *net = &init_net; WARN_ON(!mutex_is_locked(&nfsd_mutex)); if (nfsd_serv) { diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h index 98f34b886f9..fa09b579f67 100644 --- a/include/linux/device-mapper.h +++ b/include/linux/device-mapper.h @@ -72,8 +72,8 @@ typedef void (*dm_postsuspend_fn) (struct dm_target *ti); typedef int (*dm_preresume_fn) (struct dm_target *ti); typedef void (*dm_resume_fn) (struct dm_target *ti); -typedef int (*dm_status_fn) (struct dm_target *ti, status_type_t status_type, - char *result, unsigned int maxlen); +typedef void (*dm_status_fn) (struct dm_target *ti, status_type_t status_type, + char *result, unsigned int maxlen); typedef int (*dm_message_fn) (struct dm_target *ti, unsigned argc, char **argv); diff --git a/include/linux/net.h b/include/linux/net.h index 95fea1432dd..45232814fc0 100644 --- a/include/linux/net.h +++ b/include/linux/net.h @@ -198,6 +198,14 @@ struct proto_ops { #endif int (*sendmsg) (struct kiocb *iocb, struct socket *sock, struct msghdr *m, size_t total_len); + /* Notes for implementing recvmsg: + * =============================== + * msg->msg_namelen should get updated by the recvmsg handlers + * iff msg_name != NULL. It is by default 0 to prevent + * returning uninitialized memory to user space. The recvfrom + * handlers can assume that msg.msg_name is either NULL or has + * a minimum size of sizeof(struct sockaddr_storage). + */ int (*recvmsg) (struct kiocb *iocb, struct socket *sock, struct msghdr *m, size_t total_len, int flags); diff --git a/include/linux/random.h b/include/linux/random.h index 7e58ad27b7f..54b1fd3efdf 100644 --- a/include/linux/random.h +++ b/include/linux/random.h @@ -87,9 +87,9 @@ static inline void prandom32_seed(struct rnd_state *state, u64 seed) { u32 i = (seed >> 32) ^ (seed << 10) ^ seed; - state->s1 = __seed(i, 1); - state->s2 = __seed(i, 7); - state->s3 = __seed(i, 15); + state->s1 = __seed(i, 2); + state->s2 = __seed(i, 8); + state->s3 = __seed(i, 16); } #ifdef CONFIG_ARCH_RANDOM diff --git a/lib/random32.c b/lib/random32.c index 938bde5876a..aa95712c143 100644 --- a/lib/random32.c +++ b/lib/random32.c @@ -92,7 +92,7 @@ void srandom32(u32 entropy) */ for_each_possible_cpu (i) { struct rnd_state *state = &per_cpu(net_rand_state, i); - state->s1 = __seed(state->s1 ^ entropy, 1); + state->s1 = __seed(state->s1 ^ entropy, 2); } } EXPORT_SYMBOL(srandom32); @@ -109,9 +109,9 @@ static int __init random32_init(void) struct rnd_state *state = &per_cpu(net_rand_state,i); #define LCG(x) ((x) * 69069) /* super-duper LCG */ - state->s1 = __seed(LCG(i + jiffies), 1); - state->s2 = __seed(LCG(state->s1), 7); - state->s3 = __seed(LCG(state->s2), 15); + state->s1 = __seed(LCG(i + jiffies), 2); + state->s2 = __seed(LCG(state->s1), 8); + state->s3 = __seed(LCG(state->s2), 16); /* "warm it up" */ prandom32(state); @@ -138,9 +138,9 @@ static int __init random32_reseed(void) u32 seeds[3]; get_random_bytes(&seeds, sizeof(seeds)); - state->s1 = __seed(seeds[0], 1); - state->s2 = __seed(seeds[1], 7); - state->s3 = __seed(seeds[2], 15); + state->s1 = __seed(seeds[0], 2); + state->s2 = __seed(seeds[1], 8); + state->s3 = __seed(seeds[2], 16); /* mix it in */ prandom32(state); diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c index bfa9ab93eda..334d4cd7612 100644 --- a/net/appletalk/ddp.c +++ b/net/appletalk/ddp.c @@ -1740,7 +1740,6 @@ static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr size_t size, int flags) { struct sock *sk = sock->sk; - struct sockaddr_at *sat = (struct sockaddr_at *)msg->msg_name; struct ddpehdr *ddp; int copied = 0; int offset = 0; @@ -1769,14 +1768,13 @@ static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr } err = skb_copy_datagram_iovec(skb, offset, msg->msg_iov, copied); - if (!err) { - if (sat) { - sat->sat_family = AF_APPLETALK; - sat->sat_port = ddp->deh_sport; - sat->sat_addr.s_node = ddp->deh_snode; - sat->sat_addr.s_net = ddp->deh_snet; - } - msg->msg_namelen = sizeof(*sat); + if (!err && msg->msg_name) { + struct sockaddr_at *sat = msg->msg_name; + sat->sat_family = AF_APPLETALK; + sat->sat_port = ddp->deh_sport; + sat->sat_addr.s_node = ddp->deh_snode; + sat->sat_addr.s_net = ddp->deh_snet; + msg->msg_namelen = sizeof(*sat); } skb_free_datagram(sk, skb); /* Free the datagram. */ diff --git a/net/atm/common.c b/net/atm/common.c index f0a9b7eb373..0c0ad930a63 100644 --- a/net/atm/common.c +++ b/net/atm/common.c @@ -520,8 +520,6 @@ int vcc_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, struct sk_buff *skb; int copied, error = -EINVAL; - msg->msg_namelen = 0; - if (sock->state != SS_CONNECTED) return -ENOTCONN; diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index 68b39927ecd..ca1820cf22f 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c @@ -1640,11 +1640,11 @@ static int ax25_recvmsg(struct kiocb *iocb, struct socket *sock, skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); - if (msg->msg_namelen != 0) { - struct sockaddr_ax25 *sax = (struct sockaddr_ax25 *)msg->msg_name; + if (msg->msg_name) { ax25_digi digi; ax25_address src; const unsigned char *mac = skb_mac_header(skb); + struct sockaddr_ax25 *sax = msg->msg_name; memset(sax, 0, sizeof(struct full_sockaddr_ax25)); ax25_addr_parse(mac + 1, skb->data - mac - 1, &src, NULL, diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index 0d16fddee38..984f9f6bf5c 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c @@ -283,8 +283,6 @@ int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock, if (flags & (MSG_OOB)) return -EOPNOTSUPP; - msg->msg_namelen = 0; - skb = skb_recv_datagram(sk, flags, noblock, &err); if (!skb) { if (sk->sk_shutdown & RCV_SHUTDOWN) @@ -349,8 +347,6 @@ int bt_sock_stream_recvmsg(struct kiocb *iocb, struct socket *sock, if (flags & MSG_OOB) return -EOPNOTSUPP; - msg->msg_namelen = 0; - BT_DBG("sk %p size %zu", sk, size); lock_sock(sk); diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index 41b490669c3..cb8c25e6142 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c @@ -500,8 +500,6 @@ static int hci_sock_recvmsg(struct kiocb *iocb, struct socket *sock, if (!skb) return err; - msg->msg_namelen = 0; - copied = skb->len; if (len < copied) { msg->msg_flags |= MSG_TRUNC; diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index 40d3ea37b96..2578f916d4b 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c @@ -625,7 +625,6 @@ static int rfcomm_sock_recvmsg(struct kiocb *iocb, struct socket *sock, if (test_and_clear_bit(RFCOMM_DEFER_SETUP, &d->flags)) { rfcomm_dlc_accept(d); - msg->msg_namelen = 0; return 0; } diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index e1144e1617b..ff44f5f1678 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -170,6 +170,8 @@ void br_dev_delete(struct net_device *dev, struct list_head *head) del_nbp(p); } + br_fdb_delete_by_port(br, NULL, 1); + del_timer_sync(&br->gc_timer); br_sysfs_delbr(br->dev); diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c index 24a68861881..9e8351598f8 100644 --- a/net/caif/caif_socket.c +++ b/net/caif/caif_socket.c @@ -287,8 +287,6 @@ static int caif_seqpkt_recvmsg(struct kiocb *iocb, struct socket *sock, if (m->msg_flags&MSG_OOB) goto read_error; - m->msg_namelen = 0; - skb = skb_recv_datagram(sk, flags, 0 , &ret); if (!skb) goto read_error; @@ -362,8 +360,6 @@ static int caif_stream_recvmsg(struct kiocb *iocb, struct socket *sock, if (flags&MSG_OOB) goto out; - msg->msg_namelen = 0; - /* * Lock the socket to prevent queue disordering * while sleeps in memcpy_tomsg diff --git a/net/compat.c b/net/compat.c index ee84d82d728..17f997e14f6 100644 --- a/net/compat.c +++ b/net/compat.c @@ -72,7 +72,7 @@ int get_compat_msghdr(struct msghdr *kmsg, struct compat_msghdr __user *umsg) __get_user(kmsg->msg_flags, &umsg->msg_flags)) return -EFAULT; if (kmsg->msg_namelen > sizeof(struct sockaddr_storage)) - return -EINVAL; + kmsg->msg_namelen = sizeof(struct sockaddr_storage); kmsg->msg_name = compat_ptr(tmp1); kmsg->msg_iov = compat_ptr(tmp2); kmsg->msg_control = compat_ptr(tmp3); @@ -93,7 +93,8 @@ int verify_compat_iovec(struct msghdr *kern_msg, struct iovec *kern_iov, if (err < 0) return err; } - kern_msg->msg_name = kern_address; + if (kern_msg->msg_name) + kern_msg->msg_name = kern_address; } else kern_msg->msg_name = NULL; diff --git a/net/core/dev.c b/net/core/dev.c index 7db83d64e4f..cebdc15ce32 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -4443,7 +4443,7 @@ static void dev_change_rx_flags(struct net_device *dev, int flags) { const struct net_device_ops *ops = dev->netdev_ops; - if ((dev->flags & IFF_UP) && ops->ndo_change_rx_flags) + if (ops->ndo_change_rx_flags) ops->ndo_change_rx_flags(dev, flags); } diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c index c02e63c908d..c0c21b1ce1e 100644 --- a/net/core/fib_rules.c +++ b/net/core/fib_rules.c @@ -443,7 +443,8 @@ static int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) if (frh->action && (frh->action != rule->action)) continue; - if (frh->table && (frh_get_table(frh, tb) != rule->table)) + if (frh_get_table(frh, tb) && + (frh_get_table(frh, tb) != rule->table)) continue; if (tb[FRA_PRIORITY] && diff --git a/net/core/iovec.c b/net/core/iovec.c index 7e7aeb01de4..7fd34a56aeb 100644 --- a/net/core/iovec.c +++ b/net/core/iovec.c @@ -48,7 +48,8 @@ int verify_iovec(struct msghdr *m, struct iovec *iov, struct sockaddr_storage *a if (err < 0) return err; } - m->msg_name = address; + if (m->msg_name) + m->msg_name = address; } else { m->msg_name = NULL; } diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 114d8a9e857..546b1334fad 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -2521,6 +2521,8 @@ static int process_ipsec(struct pktgen_dev *pkt_dev, if (x) { int ret; __u8 *eth; + struct iphdr *iph; + nhead = x->props.header_len - skb_headroom(skb); if (nhead > 0) { ret = pskb_expand_head(skb, nhead, 0, GFP_ATOMIC); @@ -2542,6 +2544,11 @@ static int process_ipsec(struct pktgen_dev *pkt_dev, eth = (__u8 *) skb_push(skb, ETH_HLEN); memcpy(eth, pkt_dev->hh, 12); *(u16 *) ð[12] = protocol; + + /* Update IPv4 header len as well as checksum value */ + iph = ip_hdr(skb); + iph->tot_len = htons(skb->len - ETH_HLEN); + ip_send_check(iph); } } return 1; diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c index 840821b90bc..ddbdceb9594 100644 --- a/net/ieee802154/6lowpan.c +++ b/net/ieee802154/6lowpan.c @@ -803,7 +803,7 @@ lowpan_process_data(struct sk_buff *skb) * Traffic class carried in-line * ECN + DSCP (1 byte), Flow Label is elided */ - case 1: /* 10b */ + case 2: /* 10b */ if (!skb->len) goto drop; tmp = lowpan_fetch_skb_u8(skb); @@ -816,7 +816,7 @@ lowpan_process_data(struct sk_buff *skb) * Flow Label carried in-line * ECN + 2-bit Pad + Flow Label (3 bytes), DSCP is elided */ - case 2: /* 01b */ + case 1: /* 01b */ if (!skb->len) goto drop; tmp = lowpan_fetch_skb_u8(skb); diff --git a/net/ipv4/datagram.c b/net/ipv4/datagram.c index 424fafbc8cb..ec0751051db 100644 --- a/net/ipv4/datagram.c +++ b/net/ipv4/datagram.c @@ -57,7 +57,7 @@ int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) if (IS_ERR(rt)) { err = PTR_ERR(rt); if (err == -ENETUNREACH) - IP_INC_STATS_BH(sock_net(sk), IPSTATS_MIB_OUTNOROUTES); + IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTNOROUTES); goto out; } diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index b4c71ed0fc7..4f46cbf2da1 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c @@ -773,7 +773,7 @@ int ping_v4_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, err = PTR_ERR(rt); rt = NULL; if (err == -ENETUNREACH) - IP_INC_STATS_BH(net, IPSTATS_MIB_OUTNOROUTES); + IP_INC_STATS(net, IPSTATS_MIB_OUTNOROUTES); goto out; } diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index ae03b7b75af..727678dc796 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -176,7 +176,7 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) if (IS_ERR(rt)) { err = PTR_ERR(rt); if (err == -ENETUNREACH) - IP_INC_STATS_BH(sock_net(sk), IPSTATS_MIB_OUTNOROUTES); + IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTNOROUTES); return err; } diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 0b6136d578f..6670ad3b7eb 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -940,7 +940,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, err = PTR_ERR(rt); rt = NULL; if (err == -ENETUNREACH) - IP_INC_STATS_BH(net, IPSTATS_MIB_OUTNOROUTES); + IP_INC_STATS(net, IPSTATS_MIB_OUTNOROUTES); goto out; } @@ -1039,6 +1039,9 @@ int udp_sendpage(struct sock *sk, struct page *page, int offset, struct udp_sock *up = udp_sk(sk); int ret; + if (flags & MSG_SENDPAGE_NOTLAST) + flags |= MSG_MORE; + if (!up->pending) { struct msghdr msg = { .msg_flags = flags|MSG_MORE }; diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index 76832c8dc89..6d94674cad9 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c @@ -374,6 +374,7 @@ int ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len) if (serr->ee.ee_origin != SO_EE_ORIGIN_LOCAL) { sin->sin6_family = AF_INET6; sin->sin6_flowinfo = 0; + sin->sin6_port = 0; sin->sin6_scope_id = 0; if (skb->protocol == htons(ETH_P_IPV6)) { sin->sin6_addr = ipv6_hdr(skb)->saddr; diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 04e9b882c12..8d2a0bb65a8 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -144,8 +144,8 @@ static int ip6_finish_output2(struct sk_buff *skb) return res; } rcu_read_unlock(); - IP6_INC_STATS_BH(dev_net(dst->dev), - ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES); + IP6_INC_STATS(dev_net(dst->dev), + ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES); kfree_skb(skb); return -EINVAL; } diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 4f768a4c290..6ac8bc29b43 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -617,8 +617,11 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len, prefix = &prefix_buf; } - rt = rt6_get_route_info(net, prefix, rinfo->prefix_len, gwaddr, - dev->ifindex); + if (rinfo->prefix_len == 0) + rt = rt6_get_dflt_router(gwaddr, dev); + else + rt = rt6_get_route_info(net, prefix, rinfo->prefix_len, + gwaddr, dev->ifindex); if (rt && !lifetime) { ip6_del_rt(rt); diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c index 9680226640e..8c06a506577 100644 --- a/net/ipx/af_ipx.c +++ b/net/ipx/af_ipx.c @@ -1835,8 +1835,6 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock, if (skb->tstamp.tv64) sk->sk_stamp = skb->tstamp; - msg->msg_namelen = sizeof(*sipx); - if (sipx) { sipx->sipx_family = AF_IPX; sipx->sipx_port = ipx->ipx_source.sock; @@ -1844,6 +1842,7 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock, sipx->sipx_network = IPX_SKB_CB(skb)->ipx_source_net; sipx->sipx_type = ipx->ipx_type; sipx->sipx_zero = 0; + msg->msg_namelen = sizeof(*sipx); } rc = copied; diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c index bd25678b1d5..12218f70531 100644 --- a/net/irda/af_irda.c +++ b/net/irda/af_irda.c @@ -1386,8 +1386,6 @@ static int irda_recvmsg_dgram(struct kiocb *iocb, struct socket *sock, IRDA_DEBUG(4, "%s()\n", __func__); - msg->msg_namelen = 0; - skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, flags & MSG_DONTWAIT, &err); if (!skb) @@ -1452,8 +1450,6 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock, target = sock_rcvlowat(sk, flags & MSG_WAITALL, size); timeo = sock_rcvtimeo(sk, noblock); - msg->msg_namelen = 0; - do { int chunk; struct sk_buff *skb = skb_dequeue(&sk->sk_receive_queue); diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index 625bc50391c..cd6f7a991d8 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c @@ -1331,8 +1331,6 @@ static int iucv_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct sk_buff *skb, *rskb, *cskb; int err = 0; - msg->msg_namelen = 0; - if ((sk->sk_state == IUCV_DISCONN) && skb_queue_empty(&iucv->backlog_skb_q) && skb_queue_empty(&sk->sk_receive_queue) && diff --git a/net/key/af_key.c b/net/key/af_key.c index 2f3ce93d3fc..d5cd43920cc 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c @@ -3595,7 +3595,6 @@ static int pfkey_recvmsg(struct kiocb *kiocb, if (flags & ~(MSG_PEEK|MSG_DONTWAIT|MSG_TRUNC|MSG_CMSG_COMPAT)) goto out; - msg->msg_namelen = 0; skb = skb_recv_datagram(sk, flags, flags & MSG_DONTWAIT, &err); if (skb == NULL) goto out; diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c index 904bc098790..22112754ba0 100644 --- a/net/l2tp/l2tp_ppp.c +++ b/net/l2tp/l2tp_ppp.c @@ -200,8 +200,6 @@ static int pppol2tp_recvmsg(struct kiocb *iocb, struct socket *sock, if (sk->sk_state & PPPOX_BOUND) goto end; - msg->msg_namelen = 0; - err = 0; skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, flags & MSG_DONTWAIT, &err); diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index e4d2fbb59a7..df08d7779e1 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c @@ -721,8 +721,6 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock, int target; /* Read at least this many bytes */ long timeo; - msg->msg_namelen = 0; - lock_sock(sk); copied = -ENOTCONN; if (unlikely(sk->sk_type == SOCK_STREAM && sk->sk_state == TCP_LISTEN)) diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index a40409053ed..adbd9e3b4d5 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -1435,8 +1435,6 @@ static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock, } #endif - msg->msg_namelen = 0; - copied = data_skb->len; if (len < copied) { msg->msg_flags |= MSG_TRUNC; diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c index 7ed9b1d0c10..dcf6791ec76 100644 --- a/net/netrom/af_netrom.c +++ b/net/netrom/af_netrom.c @@ -1181,10 +1181,9 @@ static int nr_recvmsg(struct kiocb *iocb, struct socket *sock, sax->sax25_family = AF_NETROM; skb_copy_from_linear_data_offset(skb, 7, sax->sax25_call.ax25_call, AX25_ADDR_LEN); + msg->msg_namelen = sizeof(*sax); } - msg->msg_namelen = sizeof(*sax); - skb_free_datagram(sk, skb); release_sock(sk); diff --git a/net/nfc/rawsock.c b/net/nfc/rawsock.c index e879dce5281..44835ceb556 100644 --- a/net/nfc/rawsock.c +++ b/net/nfc/rawsock.c @@ -235,8 +235,6 @@ static int rawsock_recvmsg(struct kiocb *iocb, struct socket *sock, if (!skb) return rc; - msg->msg_namelen = 0; - copied = skb->len; if (len < copied) { msg->msg_flags |= MSG_TRUNC; diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 8ed5d9302e8..dbe1715c629 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -294,6 +294,7 @@ struct packet_sock { unsigned int tp_reserve; unsigned int tp_loss:1; unsigned int tp_tstamp; + struct net_device __rcu *cached_dev; struct packet_type prot_hook ____cacheline_aligned_in_smp; }; @@ -349,11 +350,15 @@ static void __fanout_link(struct sock *sk, struct packet_sock *po); static void register_prot_hook(struct sock *sk) { struct packet_sock *po = pkt_sk(sk); + if (!po->running) { - if (po->fanout) + if (po->fanout) { __fanout_link(sk, po); - else + } else { dev_add_pack(&po->prot_hook); + rcu_assign_pointer(po->cached_dev, po->prot_hook.dev); + } + sock_hold(sk); po->running = 1; } @@ -371,10 +376,13 @@ static void __unregister_prot_hook(struct sock *sk, bool sync) struct packet_sock *po = pkt_sk(sk); po->running = 0; - if (po->fanout) + if (po->fanout) { __fanout_unlink(sk, po); - else + } else { __dev_remove_pack(&po->prot_hook); + RCU_INIT_POINTER(po->cached_dev, NULL); + } + __sock_put(sk); if (sync) { @@ -496,9 +504,9 @@ static void prb_shutdown_retire_blk_timer(struct packet_sock *po, pkc = tx_ring ? &po->tx_ring.prb_bdqc : &po->rx_ring.prb_bdqc; - spin_lock(&rb_queue->lock); + spin_lock_bh(&rb_queue->lock); pkc->delete_blk_timer = 1; - spin_unlock(&rb_queue->lock); + spin_unlock_bh(&rb_queue->lock); prb_del_retire_blk_timer(pkc); } @@ -2044,12 +2052,24 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb, return tp_len; } +static struct net_device *packet_cached_dev_get(struct packet_sock *po) +{ + struct net_device *dev; + + rcu_read_lock(); + dev = rcu_dereference(po->cached_dev); + if (dev) + dev_hold(dev); + rcu_read_unlock(); + + return dev; +} + static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) { struct sk_buff *skb; struct net_device *dev; __be16 proto; - bool need_rls_dev = false; int err, reserve = 0; void *ph; struct sockaddr_ll *saddr = (struct sockaddr_ll *)msg->msg_name; @@ -2063,7 +2083,7 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) err = -EBUSY; if (saddr == NULL) { - dev = po->prot_hook.dev; + dev = packet_cached_dev_get(po); proto = po->num; addr = NULL; } else { @@ -2077,19 +2097,17 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) proto = saddr->sll_protocol; addr = saddr->sll_addr; dev = dev_get_by_index(sock_net(&po->sk), saddr->sll_ifindex); - need_rls_dev = true; } err = -ENXIO; if (unlikely(dev == NULL)) goto out; - - reserve = dev->hard_header_len; - err = -ENETDOWN; if (unlikely(!(dev->flags & IFF_UP))) goto out_put; + reserve = dev->hard_header_len; + size_max = po->tx_ring.frame_size - (po->tp_hdrlen - sizeof(struct sockaddr_ll)); @@ -2166,8 +2184,7 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) __packet_set_status(po, ph, status); kfree_skb(skb); out_put: - if (need_rls_dev) - dev_put(dev); + dev_put(dev); out: mutex_unlock(&po->pg_vec_lock); return err; @@ -2205,7 +2222,6 @@ static int packet_snd(struct socket *sock, struct sk_buff *skb; struct net_device *dev; __be16 proto; - bool need_rls_dev = false; unsigned char *addr; int err, reserve = 0; struct virtio_net_hdr vnet_hdr = { 0 }; @@ -2221,7 +2237,7 @@ static int packet_snd(struct socket *sock, */ if (saddr == NULL) { - dev = po->prot_hook.dev; + dev = packet_cached_dev_get(po); proto = po->num; addr = NULL; } else { @@ -2233,19 +2249,17 @@ static int packet_snd(struct socket *sock, proto = saddr->sll_protocol; addr = saddr->sll_addr; dev = dev_get_by_index(sock_net(sk), saddr->sll_ifindex); - need_rls_dev = true; } err = -ENXIO; - if (dev == NULL) + if (unlikely(dev == NULL)) goto out_unlock; - if (sock->type == SOCK_RAW) - reserve = dev->hard_header_len; - err = -ENETDOWN; - if (!(dev->flags & IFF_UP)) + if (unlikely(!(dev->flags & IFF_UP))) goto out_unlock; + if (sock->type == SOCK_RAW) + reserve = dev->hard_header_len; if (po->has_vnet_hdr) { vnet_hdr_len = sizeof(vnet_hdr); @@ -2378,15 +2392,14 @@ static int packet_snd(struct socket *sock, if (err > 0 && (err = net_xmit_errno(err)) != 0) goto out_unlock; - if (need_rls_dev) - dev_put(dev); + dev_put(dev); return len; out_free: kfree_skb(skb); out_unlock: - if (dev && need_rls_dev) + if (dev) dev_put(dev); out: return err; @@ -2603,6 +2616,7 @@ static int packet_create(struct net *net, struct socket *sock, int protocol, po = pkt_sk(sk); sk->sk_family = PF_PACKET; po->num = proto; + RCU_INIT_POINTER(po->cached_dev, NULL); sk->sk_destruct = packet_sock_destruct; sk_refcnt_debug_inc(sk); @@ -2691,7 +2705,6 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock, struct sock *sk = sock->sk; struct sk_buff *skb; int copied, err; - struct sockaddr_ll *sll; int vnet_hdr_len = 0; err = -EINVAL; @@ -2774,22 +2787,10 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock, goto out_free; } - /* - * If the address length field is there to be filled in, we fill - * it in now. + /* You lose any data beyond the buffer you gave. If it worries + * a user program they can ask the device for its MTU + * anyway. */ - - sll = &PACKET_SKB_CB(skb)->sa.ll; - if (sock->type == SOCK_PACKET) - msg->msg_namelen = sizeof(struct sockaddr_pkt); - else - msg->msg_namelen = sll->sll_halen + offsetof(struct sockaddr_ll, sll_addr); - - /* - * You lose any data beyond the buffer you gave. If it worries a - * user program they can ask the device for its MTU anyway. - */ - copied = skb->len; if (copied > len) { copied = len; @@ -2802,9 +2803,20 @@ static int packet_recvmsg(struct kiocb *iocb, struct socket *sock, sock_recv_ts_and_drops(msg, sk, skb); - if (msg->msg_name) + if (msg->msg_name) { + /* If the address length field is there to be filled + * in, we fill it in now. + */ + if (sock->type == SOCK_PACKET) { + msg->msg_namelen = sizeof(struct sockaddr_pkt); + } else { + struct sockaddr_ll *sll = &PACKET_SKB_CB(skb)->sa.ll; + msg->msg_namelen = sll->sll_halen + + offsetof(struct sockaddr_ll, sll_addr); + } memcpy(msg->msg_name, &PACKET_SKB_CB(skb)->sa, msg->msg_namelen); + } if (pkt_sk(sk)->auxdata) { struct tpacket_auxdata aux; diff --git a/net/rds/recv.c b/net/rds/recv.c index 9f0f17cf6bf..de339b24ca1 100644 --- a/net/rds/recv.c +++ b/net/rds/recv.c @@ -410,8 +410,6 @@ int rds_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, rdsdebug("size %zu flags 0x%x timeo %ld\n", size, msg_flags, timeo); - msg->msg_namelen = 0; - if (msg_flags & MSG_OOB) goto out; diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index 7f645d11579..ce5f5b934ea 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c @@ -1220,7 +1220,6 @@ static int rose_recvmsg(struct kiocb *iocb, struct socket *sock, { struct sock *sk = sock->sk; struct rose_sock *rose = rose_sk(sk); - struct sockaddr_rose *srose = (struct sockaddr_rose *)msg->msg_name; size_t copied; unsigned char *asmptr; struct sk_buff *skb; @@ -1256,8 +1255,11 @@ static int rose_recvmsg(struct kiocb *iocb, struct socket *sock, skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); - if (srose != NULL) { - memset(srose, 0, msg->msg_namelen); + if (msg->msg_name) { + struct sockaddr_rose *srose; + + memset(msg->msg_name, 0, sizeof(struct full_sockaddr_rose)); + srose = msg->msg_name; srose->srose_family = AF_ROSE; srose->srose_addr = rose->dest_addr; srose->srose_call = rose->dest_call; diff --git a/net/rxrpc/ar-recvmsg.c b/net/rxrpc/ar-recvmsg.c index 4b48687c389..898492a8d61 100644 --- a/net/rxrpc/ar-recvmsg.c +++ b/net/rxrpc/ar-recvmsg.c @@ -143,10 +143,13 @@ int rxrpc_recvmsg(struct kiocb *iocb, struct socket *sock, /* copy the peer address and timestamp */ if (!continue_call) { - if (msg->msg_name && msg->msg_namelen > 0) + if (msg->msg_name) { + size_t len = + sizeof(call->conn->trans->peer->srx); memcpy(msg->msg_name, - &call->conn->trans->peer->srx, - sizeof(call->conn->trans->peer->srx)); + &call->conn->trans->peer->srx, len); + msg->msg_namelen = len; + } sock_recv_ts_and_drops(msg, &rx->sk, skb); } diff --git a/net/socket.c b/net/socket.c index 2bef7dba7c1..1a296cb224f 100644 --- a/net/socket.c +++ b/net/socket.c @@ -215,12 +215,13 @@ static int move_addr_to_user(struct sockaddr_storage *kaddr, int klen, int err; int len; + BUG_ON(klen > sizeof(struct sockaddr_storage)); err = get_user(len, ulen); if (err) return err; if (len > klen) len = klen; - if (len < 0 || len > sizeof(struct sockaddr_storage)) + if (len < 0) return -EINVAL; if (len) { if (audit_sockaddr(klen, kaddr)) @@ -1775,8 +1776,10 @@ SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size, msg.msg_iov = &iov; iov.iov_len = size; iov.iov_base = ubuf; - msg.msg_name = (struct sockaddr *)&address; - msg.msg_namelen = sizeof(address); + /* Save some cycles and don't copy the address if not needed */ + msg.msg_name = addr ? (struct sockaddr *)&address : NULL; + /* We assume all kernel code knows the size of sockaddr_storage */ + msg.msg_namelen = 0; if (sock->file->f_flags & O_NONBLOCK) flags |= MSG_DONTWAIT; err = sock_recvmsg(sock, &msg, size, flags); @@ -1905,7 +1908,7 @@ static int copy_msghdr_from_user(struct msghdr *kmsg, if (copy_from_user(kmsg, umsg, sizeof(struct msghdr))) return -EFAULT; if (kmsg->msg_namelen > sizeof(struct sockaddr_storage)) - return -EINVAL; + kmsg->msg_namelen = sizeof(struct sockaddr_storage); return 0; } @@ -2161,16 +2164,14 @@ static int ___sys_recvmsg(struct socket *sock, struct msghdr __user *msg, goto out; } - /* - * Save the user-mode address (verify_iovec will change the - * kernel msghdr to use the kernel address space) + /* Save the user-mode address (verify_iovec will change the + * kernel msghdr to use the kernel address space) */ - uaddr = (__force void __user *)msg_sys->msg_name; uaddr_len = COMPAT_NAMELEN(msg); - if (MSG_CMSG_COMPAT & flags) { + if (MSG_CMSG_COMPAT & flags) err = verify_compat_iovec(msg_sys, iov, &addr, VERIFY_WRITE); - } else + else err = verify_iovec(msg_sys, iov, &addr, VERIFY_WRITE); if (err < 0) goto out_freeiov; @@ -2179,6 +2180,9 @@ static int ___sys_recvmsg(struct socket *sock, struct msghdr __user *msg, cmsg_ptr = (unsigned long)msg_sys->msg_control; msg_sys->msg_flags = flags & (MSG_CMSG_CLOEXEC|MSG_CMSG_COMPAT); + /* We assume all kernel code knows the size of sockaddr_storage */ + msg_sys->msg_namelen = 0; + if (sock->file->f_flags & O_NONBLOCK) flags |= MSG_DONTWAIT; err = (nosec ? sock_recvmsg_nosec : sock_recvmsg)(sock, msg_sys, diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 1441ab70b98..64b847008ee 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -949,9 +949,6 @@ static int recv_msg(struct kiocb *iocb, struct socket *sock, goto exit; } - /* will be updated in set_orig_addr() if needed */ - m->msg_namelen = 0; - timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT); restart: @@ -1078,9 +1075,6 @@ static int recv_stream(struct kiocb *iocb, struct socket *sock, goto exit; } - /* will be updated in set_orig_addr() if needed */ - m->msg_namelen = 0; - target = sock_rcvlowat(sk, flags & MSG_WAITALL, buf_len); timeout = sock_rcvtimeo(sk, flags & MSG_DONTWAIT); restart: diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 0916022366a..4b49578260e 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -1756,7 +1756,6 @@ static void unix_copy_addr(struct msghdr *msg, struct sock *sk) { struct unix_sock *u = unix_sk(sk); - msg->msg_namelen = 0; if (u->addr) { msg->msg_namelen = u->addr->len; memcpy(msg->msg_name, u->addr->name, u->addr->len); @@ -1780,8 +1779,6 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock, if (flags&MSG_OOB) goto out; - msg->msg_namelen = 0; - err = mutex_lock_interruptible(&u->readlock); if (err) { err = sock_intr_errno(sock_rcvtimeo(sk, noblock)); @@ -1923,8 +1920,6 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, target = sock_rcvlowat(sk, flags&MSG_WAITALL, size); timeo = sock_rcvtimeo(sk, flags&MSG_DONTWAIT); - msg->msg_namelen = 0; - /* Lock the socket to prevent queue disordering * while sleeps in memcpy_tomsg */ diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c index b943e3e71bd..92aed9e45c7 100644 --- a/net/x25/af_x25.c +++ b/net/x25/af_x25.c @@ -1343,10 +1343,9 @@ static int x25_recvmsg(struct kiocb *iocb, struct socket *sock, if (sx25) { sx25->sx25_family = AF_X25; sx25->sx25_addr = x25->dest_addr; + msg->msg_namelen = sizeof(*sx25); } - msg->msg_namelen = sizeof(struct sockaddr_x25); - x25_check_rbuf(sk); rc = copied; out_free_dgram: From 3ad130524979fe3af34e830bfc948a32a984be02 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Mon, 13 Jan 2014 18:47:57 +0100 Subject: [PATCH 147/215] Fix compilation for previous merge Signed-off-by: Tk-Glitch --- net/bluetooth/hci_event.c | 5 ----- release/Flashable-flo-AOSP4CM/.gitignore | 1 + sound/core/pcm.c | 4 ---- 3 files changed, 1 insertion(+), 9 deletions(-) create mode 100644 release/Flashable-flo-AOSP4CM/.gitignore diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 214117ca644..50dfe0371a5 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -3311,11 +3311,6 @@ static inline void hci_le_ltk_request_evt(struct hci_dev *hdev, memcpy(cp.ltk, ltk->val, sizeof(ltk->val)); cp.handle = cpu_to_le16(conn->handle); conn->pin_length = ltk->pin_len; - conn->pending_sec_level = BT_SECURITY_HIGH; - else - conn->pending_sec_level = BT_SECURITY_MEDIUM; - - conn->enc_key_size = ltk->enc_size; hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp); diff --git a/release/Flashable-flo-AOSP4CM/.gitignore b/release/Flashable-flo-AOSP4CM/.gitignore new file mode 100644 index 00000000000..c4c4ffc6aa4 --- /dev/null +++ b/release/Flashable-flo-AOSP4CM/.gitignore @@ -0,0 +1 @@ +*.zip diff --git a/sound/core/pcm.c b/sound/core/pcm.c index f150067a248..bdf30cf3775 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -49,8 +49,6 @@ static struct snd_pcm *snd_pcm_get(struct snd_card *card, int device) struct snd_pcm *pcm; list_for_each_entry(pcm, &snd_pcm_devices, list) { - if (pcm->internal) - continue; if (pcm->card == card && pcm->device == device) return pcm; } @@ -62,8 +60,6 @@ static int snd_pcm_next(struct snd_card *card, int device) struct snd_pcm *pcm; list_for_each_entry(pcm, &snd_pcm_devices, list) { - if (pcm->internal) - continue; if (pcm->card == card && pcm->device > device) return pcm->device; else if (pcm->card->number > card->number) From 4982be1795fbb9ffc97e8bce28aa71677ae284ff Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Mon, 13 Jan 2014 21:43:33 +0100 Subject: [PATCH 148/215] edac: Don't try to cancel workqueue when it's never setup We only setup a workqueue for edac devices that use the polling method. We still try to cancel the workqueue if an edac_device uses the irq method though. This causes a warning from debug objects when we remove an edac device: WARNING: CPU: 0 PID: 56 at lib/debugobjects.c:260 debug_print_object+0x98/0xc0() ODEBUG: assert_init not available (active state 0) object type: timer_list hint: stub_timer+0x0/0x28 Modules linked in: krait_edac(-) CPU: 0 PID: 56 Comm: rmmod Not tainted 3.12.0-rc2-00035-g15292a0 #69 [] (unwind_backtrace+0x0/0x144) from [] (show_stack+0x20/0x24) [] (show_stack+0x20/0x24) from [] (dump_stack+0x74/0xb4) [] (dump_stack+0x74/0xb4) from [] (warn_slowpath_common+0x78/0x9c) [] (warn_slowpath_common+0x78/0x9c) from [] (warn_slowpath_fmt+0x40/0x48) [] (warn_slowpath_fmt+0x40/0x48) from [] (debug_print_object+0x98/0xc0) [] (debug_print_object+0x98/0xc0) from [] (debug_object_assert_init+0xdc/0xec) [] (debug_object_assert_init+0xdc/0xec) from [] (del_timer+0x24/0x7c) [] (del_timer+0x24/0x7c) from [] (try_to_grab_pending+0xc0/0x1b0) [] (try_to_grab_pending+0xc0/0x1b0) from [] (cancel_delayed_work+0x2c/0xa0) [] (cancel_delayed_work+0x2c/0xa0) from [] (edac_device_workq_teardown+0x1c/0x38) [] (edac_device_workq_teardown+0x1c/0x38) from [] (edac_device_del_device+0xb8/0xe4) [] (edac_device_del_device+0xb8/0xe4) from [] (krait_edac_remove+0x50/0x70 [krait_edac]) [] (krait_edac_remove+0x50/0x70 [krait_edac]) from [] (platform_drv_remove+0x24/0x28) [] (platform_drv_remove+0x24/0x28) from [] (__device_release_driver+0x68/0xc0) [] (__device_release_driver+0x68/0xc0) from [] (driver_detach+0xc4/0xc8) [] (driver_detach+0xc4/0xc8) from [] (bus_remove_driver+0xac/0x114) [] (bus_remove_driver+0xac/0x114) from [] (driver_unregister+0x38/0x58) [] (driver_unregister+0x38/0x58) from [] (platform_driver_unregister+0x1c/0x20) [] (platform_driver_unregister+0x1c/0x20) from [] (krait_edac_driver_exit+0x14/0x1c [krait_edac]) [] (krait_edac_driver_exit+0x14/0x1c [krait_edac]) from [] (SyS_delete_module+0x178/0x2b4) [] (SyS_delete_module+0x178/0x2b4) from [] (ret_fast_syscall+0x0/0x48) Fix it by skipping the workqueue teardown for such devices. Signed-off-by: Stephen Boyd --- drivers/edac/edac_device.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/edac/edac_device.c b/drivers/edac/edac_device.c index 4b154593343..dc11dc064a8 100644 --- a/drivers/edac/edac_device.c +++ b/drivers/edac/edac_device.c @@ -445,6 +445,9 @@ void edac_device_workq_teardown(struct edac_device_ctl_info *edac_dev) { int status; + if (!edac_dev->edac_check) + return; + status = cancel_delayed_work(&edac_dev->work); if (status == 0) { /* workq instance might be running, wait for it */ From 9c79d2b23ea375c184d9e75fe27106e46a91051f Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Mon, 13 Jan 2014 21:44:37 +0100 Subject: [PATCH 149/215] msm: kgsl: Protect against a potential overflow in kgsl_sg_alloc Avoid allocating a scatterlist so large that it overflows the size passed to the memory allocators. CRs-fixed: 564448 Change-Id: Ic0dedbad2ab421ddec8f3be38d61c9bdf9ae5bd4 Signed-off-by: Jordan Crouse --- drivers/gpu/msm/kgsl_sharedmem.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/msm/kgsl_sharedmem.h b/drivers/gpu/msm/kgsl_sharedmem.h index 339575f55e1..ca13b255c05 100644 --- a/drivers/gpu/msm/kgsl_sharedmem.h +++ b/drivers/gpu/msm/kgsl_sharedmem.h @@ -141,6 +141,9 @@ kgsl_sharedmem_map_vma(struct vm_area_struct *vma, static inline void *kgsl_sg_alloc(unsigned int sglen) { + if (sglen >= ULONG_MAX / sizeof(struct scatterlist)) + return NULL; + if ((sglen * sizeof(struct scatterlist)) < PAGE_SIZE) return kzalloc(sglen * sizeof(struct scatterlist), GFP_KERNEL); else { From 1241fbca79646440114461396491cf01f5f5ca86 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Mon, 13 Jan 2014 21:45:28 +0100 Subject: [PATCH 150/215] msm: kgsl: avoid zero length scatterlist allocation During sglist allocation we calculate sglen as per below sglen_alloc = PAGE_ALIGN(size) >> PAGE_SHIFT; sglen_alloc can be zero if size falls within the last page. For example, when size = 0xFFFF_FF7B, PAGE_ALIGN(0xFFFF_FF7B) will be 0, considering 0x1000 (4kb) PAGE_SIZE. if kzalloc() with zero size, it will return ZERO_SIZE_PTR which is not NULL and we always do NULL check. Dereferencing ZERO_SIZE_PTR will lead to a distinct access fault. Signed-off-by: Gaurav Gagrani Change-Id: Ibcc6198438c13b5111be0faa736328db92511597 CRs-Fixed: 563106 Signed-off-by: Prakash Kamliya --- drivers/gpu/msm/kgsl_sharedmem.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/msm/kgsl_sharedmem.h b/drivers/gpu/msm/kgsl_sharedmem.h index ca13b255c05..4a43d148097 100644 --- a/drivers/gpu/msm/kgsl_sharedmem.h +++ b/drivers/gpu/msm/kgsl_sharedmem.h @@ -141,7 +141,7 @@ kgsl_sharedmem_map_vma(struct vm_area_struct *vma, static inline void *kgsl_sg_alloc(unsigned int sglen) { - if (sglen >= ULONG_MAX / sizeof(struct scatterlist)) + if ((sglen == 0) || (sglen >= ULONG_MAX / sizeof(struct scatterlist))) return NULL; if ((sglen * sizeof(struct scatterlist)) < PAGE_SIZE) From 05061ed213b0201336c9c36928931846daf552c3 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Thu, 16 Jan 2014 02:03:52 +0100 Subject: [PATCH 151/215] Linux 3.4.73 - 3.4.76 --- Documentation/i2c/busses/i2c-i801 | 1 + Makefile | 2 +- arch/arm/kernel/process.c | 7 +- arch/arm/kernel/stacktrace.c | 2 +- arch/arm/mach-omap2/omap_hwmod.c | 43 +++++- arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 13 +- arch/arm/mach-pxa/tosa.c | 102 ++++++------ arch/mips/mm/dma-default.c | 16 +- arch/powerpc/include/asm/exception-64s.h | 2 +- arch/powerpc/kernel/head_64.S | 1 + arch/powerpc/kvm/book3s_64_mmu_hv.c | 6 +- arch/powerpc/kvm/book3s_hv_rm_mmu.c | 4 + arch/sh/lib/Makefile | 2 +- arch/um/os-Linux/start_up.c | 2 + arch/x86/platform/efi/efi.c | 7 - crypto/authenc.c | 7 +- crypto/ccm.c | 3 +- drivers/ata/ahci.c | 24 +++ drivers/ata/libata-core.c | 3 + drivers/char/i8k.c | 7 + drivers/dma/Kconfig | 1 + drivers/gpio/gpio-mpc8xxx.c | 8 +- drivers/gpu/drm/drm_edid.c | 8 + drivers/gpu/drm/radeon/ni.c | 20 ++- drivers/gpu/drm/radeon/si.c | 11 +- drivers/hwmon/w83l786ng.c | 13 +- drivers/i2c/busses/Kconfig | 1 + drivers/i2c/busses/i2c-i801.c | 3 + drivers/idle/intel_idle.c | 38 +++++ drivers/input/Kconfig | 2 +- drivers/input/input.c | 4 + drivers/input/keyboard/Kconfig | 4 +- drivers/input/serio/Kconfig | 6 +- drivers/input/touchscreen/usbtouchscreen.c | 22 ++- drivers/md/dm-bufio.c | 5 + drivers/md/dm-delay.c | 23 ++- drivers/md/dm-table.c | 5 + drivers/misc/enclosure.c | 7 + drivers/net/usb/dm9601.c | 34 ++-- drivers/net/wireless/ath/ath9k/ar9002_mac.c | 52 +++++-- drivers/net/wireless/ath/ath9k/htc_drv_main.c | 25 ++- drivers/net/wireless/ath/ath9k/main.c | 5 +- drivers/net/wireless/rtlwifi/pci.c | 4 +- drivers/rtc/rtc-at91rm9200.c | 2 + drivers/scsi/hpsa.c | 4 +- drivers/scsi/libsas/sas_ata.c | 2 +- drivers/staging/comedi/drivers/pcmuio.c | 12 +- drivers/staging/comedi/drivers/ssv_dnp.c | 6 +- drivers/tty/serial/pmac_zilog.c | 3 + drivers/usb/class/cdc-acm.c | 2 + drivers/usb/class/cdc-wdm.c | 8 +- drivers/usb/core/hub.c | 5 +- drivers/usb/dwc3/ep0.c | 2 + drivers/usb/dwc3/gadget.c | 5 +- drivers/usb/gadget/composite.c | 1 + drivers/usb/serial/generic.c | 9 +- drivers/usb/serial/mos7840.c | 32 ++-- drivers/usb/serial/option.c | 27 ++++ drivers/usb/serial/pl2303.c | 32 ++-- drivers/usb/serial/spcp8x5.c | 30 ++-- drivers/watchdog/sc1200wdt.c | 3 +- fs/ceph/addr.c | 8 +- fs/ceph/mds_client.c | 8 +- fs/ext4/extents.c | 19 ++- fs/ext4/mballoc.c | 11 +- fs/gfs2/aops.c | 30 ++++ fs/gfs2/ops_fstype.c | 12 +- fs/hpfs/file.c | 5 +- fs/jbd2/transaction.c | 6 +- fs/nfs/blocklayout/extents.c | 2 +- fs/nfs/nfs4proc.c | 10 +- fs/xfs/xfs_ioctl.c | 3 +- fs/xfs/xfs_ioctl32.c | 3 +- include/crypto/scatterwalk.h | 3 +- include/drm/drm_pciids.h | 2 +- include/sound/memalloc.h | 2 +- kernel/futex.c | 2 +- kernel/irq/pm.c | 2 +- kernel/sched/debug.c | 8 + kernel/sched/fair.c | 2 + kernel/sched/rt.c | 14 ++ kernel/trace/ftrace.c | 2 +- mm/rmap.c | 4 + net/mac80211/rx.c | 3 +- net/wireless/radiotap.c | 4 + security/selinux/hooks.c | 146 ++++++++++++++---- security/selinux/include/xfrm.h | 9 +- security/selinux/xfrm.c | 53 +++++-- sound/core/pcm_lib.c | 2 + sound/soc/codecs/wm8731.c | 4 +- sound/soc/codecs/wm8904.c | 2 +- sound/soc/codecs/wm8990.c | 2 + tools/power/cpupower/utils/cpupower-set.c | 6 +- virt/kvm/kvm_main.c | 3 + 94 files changed, 828 insertions(+), 304 deletions(-) diff --git a/Documentation/i2c/busses/i2c-i801 b/Documentation/i2c/busses/i2c-i801 index 99d4e442b77..8bb57d7c12e 100644 --- a/Documentation/i2c/busses/i2c-i801 +++ b/Documentation/i2c/busses/i2c-i801 @@ -22,6 +22,7 @@ Supported adapters: * Intel Panther Point (PCH) * Intel Lynx Point (PCH) * Intel Lynx Point-LP (PCH) + * Intel Avoton (SOC) Datasheets: Publicly available at the Intel website On Intel Patsburg and later chipsets, both the normal host SMBus controller diff --git a/Makefile b/Makefile index 9fdac86057c..3252d1a09b4 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 4 -SUBLEVEL = 73 +SUBLEVEL = 76 EXTRAVERSION = NAME = Saber-toothed Squirrel diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 691ddcfb839..c8b5ecca532 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -651,6 +651,7 @@ EXPORT_SYMBOL(kernel_thread); unsigned long get_wchan(struct task_struct *p) { struct stackframe frame; + unsigned long stack_page; int count = 0; if (!p || p == current || p->state == TASK_RUNNING) return 0; @@ -659,9 +660,11 @@ unsigned long get_wchan(struct task_struct *p) frame.sp = thread_saved_sp(p); frame.lr = 0; /* recovered from the stack */ frame.pc = thread_saved_pc(p); + stack_page = (unsigned long)task_stack_page(p); do { - int ret = unwind_frame(&frame); - if (ret < 0) + if (frame.sp < stack_page || + frame.sp >= stack_page + THREAD_SIZE || + unwind_frame(&frame) < 0) return 0; if (!in_sched_functions(frame.pc)) return frame.pc; diff --git a/arch/arm/kernel/stacktrace.c b/arch/arm/kernel/stacktrace.c index 00f79e59985..af4e8c8a542 100644 --- a/arch/arm/kernel/stacktrace.c +++ b/arch/arm/kernel/stacktrace.c @@ -31,7 +31,7 @@ int notrace unwind_frame(struct stackframe *frame) high = ALIGN(low, THREAD_SIZE); /* check current frame pointer is within bounds */ - if (fp < (low + 12) || fp + 4 >= high) + if (fp < low + 12 || fp > high - 4) return -EINVAL; /* restore the registers from the stack frame */ diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 7144ae651d3..bb7ed98ab9a 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -317,7 +317,7 @@ static int _set_clockactivity(struct omap_hwmod *oh, u8 clockact, u32 *v) } /** - * _set_softreset: set OCP_SYSCONFIG.CLOCKACTIVITY bits in @v + * _set_softreset: set OCP_SYSCONFIG.SOFTRESET bit in @v * @oh: struct omap_hwmod * * @v: pointer to register contents to modify * @@ -1377,6 +1377,36 @@ static int _read_hardreset(struct omap_hwmod *oh, const char *name) } } +/** + * _clear_softreset: clear OCP_SYSCONFIG.SOFTRESET bit in @v + * @oh: struct omap_hwmod * + * @v: pointer to register contents to modify + * + * Clear the SOFTRESET bit in @v for hwmod @oh. Returns -EINVAL upon + * error or 0 upon success. + */ +static int _clear_softreset(struct omap_hwmod *oh, u32 *v) +{ + u32 softrst_mask; + + if (!oh->class->sysc || + !(oh->class->sysc->sysc_flags & SYSC_HAS_SOFTRESET)) + return -EINVAL; + + if (!oh->class->sysc->sysc_fields) { + WARN(1, + "omap_hwmod: %s: sysc_fields absent for sysconfig class\n", + oh->name); + return -EINVAL; + } + + softrst_mask = (0x1 << oh->class->sysc->sysc_fields->srst_shift); + + *v &= ~softrst_mask; + + return 0; +} + /** * _ocp_softreset - reset an omap_hwmod via the OCP_SYSCONFIG bit * @oh: struct omap_hwmod * @@ -1420,6 +1450,12 @@ static int _ocp_softreset(struct omap_hwmod *oh) ret = _set_softreset(oh, &v); if (ret) goto dis_opt_clks; + + _write_sysconfig(v, oh); + ret = _clear_softreset(oh, &v); + if (ret) + goto dis_opt_clks; + _write_sysconfig(v, oh); if (oh->class->sysc->srst_udelay) @@ -1918,6 +1954,11 @@ int omap_hwmod_softreset(struct omap_hwmod *oh) goto error; _write_sysconfig(v, oh); + ret = _clear_softreset(oh, &v); + if (ret) + goto error; + _write_sysconfig(v, oh); + error: return ret; } diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c index db86ce90c69..a875de49aa9 100644 --- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c @@ -3347,7 +3347,8 @@ static struct omap_hwmod_class_sysconfig omap3xxx_usb_host_hs_sysc = { .syss_offs = 0x0014, .sysc_flags = (SYSC_HAS_MIDLEMODE | SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE | SYSC_HAS_ENAWAKEUP | - SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE), + SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE | + SYSS_HAS_RESET_STATUS), .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART | MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART), .sysc_fields = &omap_hwmod_sysc_type1, @@ -3465,15 +3466,7 @@ static struct omap_hwmod omap3xxx_usb_host_hs_hwmod = { * hence HWMOD_SWSUP_MSTANDBY */ - /* - * During system boot; If the hwmod framework resets the module - * the module will have smart idle settings; which can lead to deadlock - * (above Errata Id:i660); so, dont reset the module during boot; - * Use HWMOD_INIT_NO_RESET. - */ - - .flags = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY | - HWMOD_INIT_NO_RESET, + .flags = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY, }; /* diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c index 4d4eb60bad1..aeb7c10daf5 100644 --- a/arch/arm/mach-pxa/tosa.c +++ b/arch/arm/mach-pxa/tosa.c @@ -424,57 +424,57 @@ static struct platform_device tosa_power_device = { * Tosa Keyboard */ static const uint32_t tosakbd_keymap[] = { - KEY(0, 2, KEY_W), - KEY(0, 6, KEY_K), - KEY(0, 7, KEY_BACKSPACE), - KEY(0, 8, KEY_P), - KEY(1, 1, KEY_Q), - KEY(1, 2, KEY_E), - KEY(1, 3, KEY_T), - KEY(1, 4, KEY_Y), - KEY(1, 6, KEY_O), - KEY(1, 7, KEY_I), - KEY(1, 8, KEY_COMMA), - KEY(2, 1, KEY_A), - KEY(2, 2, KEY_D), - KEY(2, 3, KEY_G), - KEY(2, 4, KEY_U), - KEY(2, 6, KEY_L), - KEY(2, 7, KEY_ENTER), - KEY(2, 8, KEY_DOT), - KEY(3, 1, KEY_Z), - KEY(3, 2, KEY_C), - KEY(3, 3, KEY_V), - KEY(3, 4, KEY_J), - KEY(3, 5, TOSA_KEY_ADDRESSBOOK), - KEY(3, 6, TOSA_KEY_CANCEL), - KEY(3, 7, TOSA_KEY_CENTER), - KEY(3, 8, TOSA_KEY_OK), - KEY(3, 9, KEY_LEFTSHIFT), - KEY(4, 1, KEY_S), - KEY(4, 2, KEY_R), - KEY(4, 3, KEY_B), - KEY(4, 4, KEY_N), - KEY(4, 5, TOSA_KEY_CALENDAR), - KEY(4, 6, TOSA_KEY_HOMEPAGE), - KEY(4, 7, KEY_LEFTCTRL), - KEY(4, 8, TOSA_KEY_LIGHT), - KEY(4, 10, KEY_RIGHTSHIFT), - KEY(5, 1, KEY_TAB), - KEY(5, 2, KEY_SLASH), - KEY(5, 3, KEY_H), - KEY(5, 4, KEY_M), - KEY(5, 5, TOSA_KEY_MENU), - KEY(5, 7, KEY_UP), - KEY(5, 11, TOSA_KEY_FN), - KEY(6, 1, KEY_X), - KEY(6, 2, KEY_F), - KEY(6, 3, KEY_SPACE), - KEY(6, 4, KEY_APOSTROPHE), - KEY(6, 5, TOSA_KEY_MAIL), - KEY(6, 6, KEY_LEFT), - KEY(6, 7, KEY_DOWN), - KEY(6, 8, KEY_RIGHT), + KEY(0, 1, KEY_W), + KEY(0, 5, KEY_K), + KEY(0, 6, KEY_BACKSPACE), + KEY(0, 7, KEY_P), + KEY(1, 0, KEY_Q), + KEY(1, 1, KEY_E), + KEY(1, 2, KEY_T), + KEY(1, 3, KEY_Y), + KEY(1, 5, KEY_O), + KEY(1, 6, KEY_I), + KEY(1, 7, KEY_COMMA), + KEY(2, 0, KEY_A), + KEY(2, 1, KEY_D), + KEY(2, 2, KEY_G), + KEY(2, 3, KEY_U), + KEY(2, 5, KEY_L), + KEY(2, 6, KEY_ENTER), + KEY(2, 7, KEY_DOT), + KEY(3, 0, KEY_Z), + KEY(3, 1, KEY_C), + KEY(3, 2, KEY_V), + KEY(3, 3, KEY_J), + KEY(3, 4, TOSA_KEY_ADDRESSBOOK), + KEY(3, 5, TOSA_KEY_CANCEL), + KEY(3, 6, TOSA_KEY_CENTER), + KEY(3, 7, TOSA_KEY_OK), + KEY(3, 8, KEY_LEFTSHIFT), + KEY(4, 0, KEY_S), + KEY(4, 1, KEY_R), + KEY(4, 2, KEY_B), + KEY(4, 3, KEY_N), + KEY(4, 4, TOSA_KEY_CALENDAR), + KEY(4, 5, TOSA_KEY_HOMEPAGE), + KEY(4, 6, KEY_LEFTCTRL), + KEY(4, 7, TOSA_KEY_LIGHT), + KEY(4, 9, KEY_RIGHTSHIFT), + KEY(5, 0, KEY_TAB), + KEY(5, 1, KEY_SLASH), + KEY(5, 2, KEY_H), + KEY(5, 3, KEY_M), + KEY(5, 4, TOSA_KEY_MENU), + KEY(5, 6, KEY_UP), + KEY(5, 10, TOSA_KEY_FN), + KEY(6, 0, KEY_X), + KEY(6, 1, KEY_F), + KEY(6, 2, KEY_SPACE), + KEY(6, 3, KEY_APOSTROPHE), + KEY(6, 4, TOSA_KEY_MAIL), + KEY(6, 5, KEY_LEFT), + KEY(6, 6, KEY_DOWN), + KEY(6, 7, KEY_RIGHT), }; static struct matrix_keymap_data tosakbd_keymap_data = { diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c index 3fab2046c8a..0eea2d2e856 100644 --- a/arch/mips/mm/dma-default.c +++ b/arch/mips/mm/dma-default.c @@ -30,16 +30,20 @@ static inline struct page *dma_addr_to_page(struct device *dev, } /* + * The affected CPUs below in 'cpu_needs_post_dma_flush()' can + * speculatively fill random cachelines with stale data at any time, + * requiring an extra flush post-DMA. + * * Warning on the terminology - Linux calls an uncached area coherent; * MIPS terminology calls memory areas with hardware maintained coherency * coherent. */ - -static inline int cpu_is_noncoherent_r10000(struct device *dev) +static inline int cpu_needs_post_dma_flush(struct device *dev) { return !plat_device_is_coherent(dev) && (current_cpu_type() == CPU_R10000 || - current_cpu_type() == CPU_R12000); + current_cpu_type() == CPU_R12000 || + current_cpu_type() == CPU_BMIPS5000); } static gfp_t massage_gfp_flags(const struct device *dev, gfp_t gfp) @@ -209,7 +213,7 @@ static inline void __dma_sync(struct page *page, static void mips_dma_unmap_page(struct device *dev, dma_addr_t dma_addr, size_t size, enum dma_data_direction direction, struct dma_attrs *attrs) { - if (cpu_is_noncoherent_r10000(dev)) + if (cpu_needs_post_dma_flush(dev)) __dma_sync(dma_addr_to_page(dev, dma_addr), dma_addr & ~PAGE_MASK, size, direction); @@ -260,7 +264,7 @@ static void mips_dma_unmap_sg(struct device *dev, struct scatterlist *sg, static void mips_dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size, enum dma_data_direction direction) { - if (cpu_is_noncoherent_r10000(dev)) + if (cpu_needs_post_dma_flush(dev)) __dma_sync(dma_addr_to_page(dev, dma_handle), dma_handle & ~PAGE_MASK, size, direction); } @@ -281,7 +285,7 @@ static void mips_dma_sync_sg_for_cpu(struct device *dev, /* Make sure that gcc doesn't leave the empty loop body. */ for (i = 0; i < nelems; i++, sg++) { - if (cpu_is_noncoherent_r10000(dev)) + if (cpu_needs_post_dma_flush(dev)) __dma_sync(sg_page(sg), sg->offset, sg->length, direction); } diff --git a/arch/powerpc/include/asm/exception-64s.h b/arch/powerpc/include/asm/exception-64s.h index 6afb13ad161..241d2f30530 100644 --- a/arch/powerpc/include/asm/exception-64s.h +++ b/arch/powerpc/include/asm/exception-64s.h @@ -163,7 +163,7 @@ do_kvm_##n: \ subi r1,r1,INT_FRAME_SIZE; /* alloc frame on kernel stack */ \ beq- 1f; \ ld r1,PACAKSAVE(r13); /* kernel stack to use */ \ -1: cmpdi cr1,r1,0; /* check if r1 is in userspace */ \ +1: cmpdi cr1,r1,-INT_FRAME_SIZE; /* check if r1 is in userspace */ \ blt+ cr1,3f; /* abort if it is */ \ li r1,(n); /* will be reloaded later */ \ sth r1,PACA_TRAP_SAVE(r13); \ diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 1a3607b9663..1a5b6878ac6 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -447,6 +447,7 @@ _STATIC(__after_prom_start) mtctr r8 bctr +.balign 8 p_end: .llong _end - _stext 4: /* Now copy the rest of the kernel up to _end */ diff --git a/arch/powerpc/kvm/book3s_64_mmu_hv.c b/arch/powerpc/kvm/book3s_64_mmu_hv.c index c3beaeef3f6..87135be0868 100644 --- a/arch/powerpc/kvm/book3s_64_mmu_hv.c +++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c @@ -393,11 +393,14 @@ static int kvmppc_mmu_book3s_64_hv_xlate(struct kvm_vcpu *vcpu, gva_t eaddr, slb_v = vcpu->kvm->arch.vrma_slb_v; } + preempt_disable(); /* Find the HPTE in the hash table */ index = kvmppc_hv_find_lock_hpte(kvm, eaddr, slb_v, HPTE_V_VALID | HPTE_V_ABSENT); - if (index < 0) + if (index < 0) { + preempt_enable(); return -ENOENT; + } hptep = (unsigned long *)(kvm->arch.hpt_virt + (index << 4)); v = hptep[0] & ~HPTE_V_HVLOCK; gr = kvm->arch.revmap[index].guest_rpte; @@ -405,6 +408,7 @@ static int kvmppc_mmu_book3s_64_hv_xlate(struct kvm_vcpu *vcpu, gva_t eaddr, /* Unlock the HPTE */ asm volatile("lwsync" : : : "memory"); hptep[0] = v; + preempt_enable(); gpte->eaddr = eaddr; gpte->vpage = ((v & HPTE_V_AVPN) << 4) | ((eaddr >> 12) & 0xfff); diff --git a/arch/powerpc/kvm/book3s_hv_rm_mmu.c b/arch/powerpc/kvm/book3s_hv_rm_mmu.c index cec4daddbf3..eacf164eabb 100644 --- a/arch/powerpc/kvm/book3s_hv_rm_mmu.c +++ b/arch/powerpc/kvm/book3s_hv_rm_mmu.c @@ -649,6 +649,10 @@ static int slb_base_page_shift[4] = { 20, /* 1M, unsupported */ }; +/* When called from virtmode, this func should be protected by + * preempt_disable(), otherwise, the holding of HPTE_V_HVLOCK + * can trigger deadlock issue. + */ long kvmppc_hv_find_lock_hpte(struct kvm *kvm, gva_t eaddr, unsigned long slb_v, unsigned long valid) { diff --git a/arch/sh/lib/Makefile b/arch/sh/lib/Makefile index 7b95f29e317..3baff31e58c 100644 --- a/arch/sh/lib/Makefile +++ b/arch/sh/lib/Makefile @@ -6,7 +6,7 @@ lib-y = delay.o memmove.o memchr.o \ checksum.o strlen.o div64.o div64-generic.o # Extracted from libgcc -lib-y += movmem.o ashldi3.o ashrdi3.o lshrdi3.o \ +obj-y += movmem.o ashldi3.o ashrdi3.o lshrdi3.o \ ashlsi3.o ashrsi3.o ashiftrt.o lshrsi3.o \ udiv_qrnnd.o diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c index 425162e22af..2f53b892fd8 100644 --- a/arch/um/os-Linux/start_up.c +++ b/arch/um/os-Linux/start_up.c @@ -15,6 +15,8 @@ #include #include #include +#include +#include #include #include "init.h" #include "os.h" diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 454548c309f..8a67b7c019b 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -744,13 +744,6 @@ void __init efi_init(void) set_bit(EFI_MEMMAP, &x86_efi_facility); -#ifdef CONFIG_X86_32 - if (efi_is_native()) { - x86_platform.get_wallclock = efi_get_time; - x86_platform.set_wallclock = efi_set_rtc_mmss; - } -#endif - #if EFI_DEBUG print_efi_memmap(); #endif diff --git a/crypto/authenc.c b/crypto/authenc.c index 5ef7ba6b6a7..d21da2f0f50 100644 --- a/crypto/authenc.c +++ b/crypto/authenc.c @@ -368,9 +368,10 @@ static void crypto_authenc_encrypt_done(struct crypto_async_request *req, if (!err) { struct crypto_aead *authenc = crypto_aead_reqtfm(areq); struct crypto_authenc_ctx *ctx = crypto_aead_ctx(authenc); - struct ablkcipher_request *abreq = aead_request_ctx(areq); - u8 *iv = (u8 *)(abreq + 1) + - crypto_ablkcipher_reqsize(ctx->enc); + struct authenc_request_ctx *areq_ctx = aead_request_ctx(areq); + struct ablkcipher_request *abreq = (void *)(areq_ctx->tail + + ctx->reqoff); + u8 *iv = (u8 *)abreq - crypto_ablkcipher_ivsize(ctx->enc); err = crypto_authenc_genicv(areq, iv, 0); } diff --git a/crypto/ccm.c b/crypto/ccm.c index 32fe1bb5dec..18d64ad0433 100644 --- a/crypto/ccm.c +++ b/crypto/ccm.c @@ -271,7 +271,8 @@ static int crypto_ccm_auth(struct aead_request *req, struct scatterlist *plain, } /* compute plaintext into mac */ - get_data_to_compute(cipher, pctx, plain, cryptlen); + if (cryptlen) + get_data_to_compute(cipher, pctx, plain, cryptlen); out: return err; diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 60662545cd1..c20f1578d39 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -268,6 +268,30 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(INTEL, 0x8c07), board_ahci }, /* Lynx Point RAID */ { PCI_VDEVICE(INTEL, 0x8c0e), board_ahci }, /* Lynx Point RAID */ { PCI_VDEVICE(INTEL, 0x8c0f), board_ahci }, /* Lynx Point RAID */ + { PCI_VDEVICE(INTEL, 0x9c02), board_ahci }, /* Lynx Point-LP AHCI */ + { PCI_VDEVICE(INTEL, 0x9c03), board_ahci }, /* Lynx Point-LP AHCI */ + { PCI_VDEVICE(INTEL, 0x9c04), board_ahci }, /* Lynx Point-LP RAID */ + { PCI_VDEVICE(INTEL, 0x9c05), board_ahci }, /* Lynx Point-LP RAID */ + { PCI_VDEVICE(INTEL, 0x9c06), board_ahci }, /* Lynx Point-LP RAID */ + { PCI_VDEVICE(INTEL, 0x9c07), board_ahci }, /* Lynx Point-LP RAID */ + { PCI_VDEVICE(INTEL, 0x9c0e), board_ahci }, /* Lynx Point-LP RAID */ + { PCI_VDEVICE(INTEL, 0x9c0f), board_ahci }, /* Lynx Point-LP RAID */ + { PCI_VDEVICE(INTEL, 0x1f22), board_ahci }, /* Avoton AHCI */ + { PCI_VDEVICE(INTEL, 0x1f23), board_ahci }, /* Avoton AHCI */ + { PCI_VDEVICE(INTEL, 0x1f24), board_ahci }, /* Avoton RAID */ + { PCI_VDEVICE(INTEL, 0x1f25), board_ahci }, /* Avoton RAID */ + { PCI_VDEVICE(INTEL, 0x1f26), board_ahci }, /* Avoton RAID */ + { PCI_VDEVICE(INTEL, 0x1f27), board_ahci }, /* Avoton RAID */ + { PCI_VDEVICE(INTEL, 0x1f2e), board_ahci }, /* Avoton RAID */ + { PCI_VDEVICE(INTEL, 0x1f2f), board_ahci }, /* Avoton RAID */ + { PCI_VDEVICE(INTEL, 0x1f32), board_ahci }, /* Avoton AHCI */ + { PCI_VDEVICE(INTEL, 0x1f33), board_ahci }, /* Avoton AHCI */ + { PCI_VDEVICE(INTEL, 0x1f34), board_ahci }, /* Avoton RAID */ + { PCI_VDEVICE(INTEL, 0x1f35), board_ahci }, /* Avoton RAID */ + { PCI_VDEVICE(INTEL, 0x1f36), board_ahci }, /* Avoton RAID */ + { PCI_VDEVICE(INTEL, 0x1f37), board_ahci }, /* Avoton RAID */ + { PCI_VDEVICE(INTEL, 0x1f3e), board_ahci }, /* Avoton RAID */ + { PCI_VDEVICE(INTEL, 0x1f3f), board_ahci }, /* Avoton RAID */ /* JMicron 360/1/3/5/6, match class to avoid IDE function */ { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index cd20cf1ef3e..400b8c6eb8e 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4104,6 +4104,9 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { { "ST3320[68]13AS", "SD1[5-9]", ATA_HORKAGE_NONCQ | ATA_HORKAGE_FIRMWARE_WARN }, + /* Seagate Momentus SpinPoint M8 seem to have FPMDA_AA issues */ + { "ST1000LM024 HN-M101MBB", "2AR10001", ATA_HORKAGE_BROKEN_FPDMA_AA }, + /* Blacklist entries taken from Silicon Image 3124/3132 Windows driver .inf file - also several Linux problem reports */ { "HTS541060G9SA00", "MB3OC60D", ATA_HORKAGE_NONCQ, }, diff --git a/drivers/char/i8k.c b/drivers/char/i8k.c index 40cc0cf2ded..e6939e13e33 100644 --- a/drivers/char/i8k.c +++ b/drivers/char/i8k.c @@ -664,6 +664,13 @@ static struct dmi_system_id __initdata i8k_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Vostro"), }, }, + { + .ident = "Dell XPS421", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "XPS L421X"), + }, + }, { } }; diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index ef378b5b17e..7de7a656c50 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -269,6 +269,7 @@ config NET_DMA bool "Network: TCP receive copy offload" depends on DMA_ENGINE && NET default (INTEL_IOATDMA || FSL_DMA) + depends on BROKEN help This enables the use of DMA engines in the network stack to offload receive copy-to-user operations, freeing CPU cycles. diff --git a/drivers/gpio/gpio-mpc8xxx.c b/drivers/gpio/gpio-mpc8xxx.c index 5a1817eedd1..c81b8da669e 100644 --- a/drivers/gpio/gpio-mpc8xxx.c +++ b/drivers/gpio/gpio-mpc8xxx.c @@ -69,10 +69,14 @@ static int mpc8572_gpio_get(struct gpio_chip *gc, unsigned int gpio) u32 val; struct of_mm_gpio_chip *mm = to_of_mm_gpio_chip(gc); struct mpc8xxx_gpio_chip *mpc8xxx_gc = to_mpc8xxx_gpio_chip(mm); + u32 out_mask, out_shadow; - val = in_be32(mm->regs + GPIO_DAT) & ~in_be32(mm->regs + GPIO_DIR); + out_mask = in_be32(mm->regs + GPIO_DIR); - return (val | mpc8xxx_gc->data) & mpc8xxx_gpio2mask(gpio); + val = in_be32(mm->regs + GPIO_DAT) & ~out_mask; + out_shadow = mpc8xxx_gc->data & out_mask; + + return (val | out_shadow) & mpc8xxx_gpio2mask(gpio); } static int mpc8xxx_gpio_get(struct gpio_chip *gc, unsigned int gpio) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index efe172f3360..d75dccb562f 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -68,6 +68,8 @@ #define EDID_QUIRK_DETAILED_SYNC_PP (1 << 6) /* Force reduced-blanking timings for detailed modes */ #define EDID_QUIRK_FORCE_REDUCED_BLANKING (1 << 7) +/* Force 8bpc */ +#define EDID_QUIRK_FORCE_8BPC (1 << 8) struct detailed_mode_closure { struct drm_connector *connector; @@ -128,6 +130,9 @@ static struct edid_quirk { /* Medion MD 30217 PG */ { "MED", 0x7b8, EDID_QUIRK_PREFER_LARGE_75 }, + + /* Panel in Samsung NP700G7A-S01PL notebook reports 6bpc */ + { "SEC", 0xd033, EDID_QUIRK_FORCE_8BPC }, }; /*** DDC fetch and block validation ***/ @@ -1782,6 +1787,9 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid) drm_add_display_info(edid, &connector->display_info); + if (quirks & EDID_QUIRK_FORCE_8BPC) + connector->display_info.bpc = 8; + return num_modes; } EXPORT_SYMBOL(drm_add_edid_modes); diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index f5387b3e699..f481da3a4f2 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c @@ -672,6 +672,10 @@ static void cayman_gpu_init(struct radeon_device *rdev) (rdev->pdev->device == 0x999C)) { rdev->config.cayman.max_simds_per_se = 6; rdev->config.cayman.max_backends_per_se = 2; + rdev->config.cayman.max_hw_contexts = 8; + rdev->config.cayman.sx_max_export_size = 256; + rdev->config.cayman.sx_max_export_pos_size = 64; + rdev->config.cayman.sx_max_export_smx_size = 192; } else if ((rdev->pdev->device == 0x9903) || (rdev->pdev->device == 0x9904) || (rdev->pdev->device == 0x990A) || @@ -682,6 +686,10 @@ static void cayman_gpu_init(struct radeon_device *rdev) (rdev->pdev->device == 0x999D)) { rdev->config.cayman.max_simds_per_se = 4; rdev->config.cayman.max_backends_per_se = 2; + rdev->config.cayman.max_hw_contexts = 8; + rdev->config.cayman.sx_max_export_size = 256; + rdev->config.cayman.sx_max_export_pos_size = 64; + rdev->config.cayman.sx_max_export_smx_size = 192; } else if ((rdev->pdev->device == 0x9919) || (rdev->pdev->device == 0x9990) || (rdev->pdev->device == 0x9991) || @@ -692,9 +700,17 @@ static void cayman_gpu_init(struct radeon_device *rdev) (rdev->pdev->device == 0x99A0)) { rdev->config.cayman.max_simds_per_se = 3; rdev->config.cayman.max_backends_per_se = 1; + rdev->config.cayman.max_hw_contexts = 4; + rdev->config.cayman.sx_max_export_size = 128; + rdev->config.cayman.sx_max_export_pos_size = 32; + rdev->config.cayman.sx_max_export_smx_size = 96; } else { rdev->config.cayman.max_simds_per_se = 2; rdev->config.cayman.max_backends_per_se = 1; + rdev->config.cayman.max_hw_contexts = 4; + rdev->config.cayman.sx_max_export_size = 128; + rdev->config.cayman.sx_max_export_pos_size = 32; + rdev->config.cayman.sx_max_export_smx_size = 96; } rdev->config.cayman.max_texture_channel_caches = 2; rdev->config.cayman.max_gprs = 256; @@ -702,10 +718,6 @@ static void cayman_gpu_init(struct radeon_device *rdev) rdev->config.cayman.max_gs_threads = 32; rdev->config.cayman.max_stack_entries = 512; rdev->config.cayman.sx_num_of_sets = 8; - rdev->config.cayman.sx_max_export_size = 256; - rdev->config.cayman.sx_max_export_pos_size = 64; - rdev->config.cayman.sx_max_export_smx_size = 192; - rdev->config.cayman.max_hw_contexts = 8; rdev->config.cayman.sq_num_cf_insts = 2; rdev->config.cayman.sc_prim_fifo_size = 0x40; diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index bd1f18c341d..c22b5e7849f 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c @@ -2479,8 +2479,15 @@ static int si_mc_init(struct radeon_device *rdev) rdev->mc.aper_base = pci_resource_start(rdev->pdev, 0); rdev->mc.aper_size = pci_resource_len(rdev->pdev, 0); /* size in MB on si */ - rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE) * 1024ULL * 1024ULL; - rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE) * 1024ULL * 1024ULL; + tmp = RREG32(CONFIG_MEMSIZE); + /* some boards may have garbage in the upper 16 bits */ + if (tmp & 0xffff0000) { + DRM_INFO("Probable bad vram size: 0x%08x\n", tmp); + if (tmp & 0xffff) + tmp &= 0xffff; + } + rdev->mc.mc_vram_size = tmp * 1024ULL * 1024ULL; + rdev->mc.real_vram_size = rdev->mc.mc_vram_size; rdev->mc.visible_vram_size = rdev->mc.aper_size; si_vram_gtt_location(rdev, &rdev->mc); radeon_update_bandwidth_info(rdev); diff --git a/drivers/hwmon/w83l786ng.c b/drivers/hwmon/w83l786ng.c index 5850b770608..284d469af32 100644 --- a/drivers/hwmon/w83l786ng.c +++ b/drivers/hwmon/w83l786ng.c @@ -481,9 +481,11 @@ store_pwm(struct device *dev, struct device_attribute *attr, if (err) return err; val = SENSORS_LIMIT(val, 0, 255); + val = DIV_ROUND_CLOSEST(val, 0x11); mutex_lock(&data->update_lock); - data->pwm[nr] = val; + data->pwm[nr] = val * 0x11; + val |= w83l786ng_read_value(client, W83L786NG_REG_PWM[nr]) & 0xf0; w83l786ng_write_value(client, W83L786NG_REG_PWM[nr], val); mutex_unlock(&data->update_lock); return count; @@ -510,7 +512,7 @@ store_pwm_enable(struct device *dev, struct device_attribute *attr, mutex_lock(&data->update_lock); reg = w83l786ng_read_value(client, W83L786NG_REG_FAN_CFG); data->pwm_enable[nr] = val; - reg &= ~(0x02 << W83L786NG_PWM_ENABLE_SHIFT[nr]); + reg &= ~(0x03 << W83L786NG_PWM_ENABLE_SHIFT[nr]); reg |= (val - 1) << W83L786NG_PWM_ENABLE_SHIFT[nr]; w83l786ng_write_value(client, W83L786NG_REG_FAN_CFG, reg); mutex_unlock(&data->update_lock); @@ -781,9 +783,10 @@ static struct w83l786ng_data *w83l786ng_update_device(struct device *dev) ((pwmcfg >> W83L786NG_PWM_MODE_SHIFT[i]) & 1) ? 0 : 1; data->pwm_enable[i] = - ((pwmcfg >> W83L786NG_PWM_ENABLE_SHIFT[i]) & 2) + 1; - data->pwm[i] = w83l786ng_read_value(client, - W83L786NG_REG_PWM[i]); + ((pwmcfg >> W83L786NG_PWM_ENABLE_SHIFT[i]) & 3) + 1; + data->pwm[i] = + (w83l786ng_read_value(client, W83L786NG_REG_PWM[i]) + & 0x0f) * 0x11; } diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index ac2e1e1d3e0..f5d2ab7de4d 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -105,6 +105,7 @@ config I2C_I801 Panther Point (PCH) Lynx Point (PCH) Lynx Point-LP (PCH) + Avoton (SOC) This driver can also be built as a module. If so, the module will be called i2c-i801. diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index d88ec812160..d63e130690e 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -53,6 +53,7 @@ Panther Point (PCH) 0x1e22 32 hard yes yes yes Lynx Point (PCH) 0x8c22 32 hard yes yes yes Lynx Point-LP (PCH) 0x9c22 32 hard yes yes yes + Avoton (SOC) 0x1f3c 32 hard yes yes yes Features supported by this driver: Software PEC no @@ -145,6 +146,7 @@ #define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF1 0x1d71 #define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF2 0x1d72 #define PCI_DEVICE_ID_INTEL_PANTHERPOINT_SMBUS 0x1e22 +#define PCI_DEVICE_ID_INTEL_AVOTON_SMBUS 0x1f3c #define PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS 0x2330 #define PCI_DEVICE_ID_INTEL_5_3400_SERIES_SMBUS 0x3b30 #define PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS 0x8c22 @@ -639,6 +641,7 @@ static DEFINE_PCI_DEVICE_TABLE(i801_ids) = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PANTHERPOINT_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_SMBUS) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_AVOTON_SMBUS) }, { 0, } }; diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index d0f59c3f87e..8d1ebd33229 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c @@ -169,6 +169,38 @@ static struct cpuidle_state snb_cstates[MWAIT_MAX_NUM_CSTATES] = { .enter = &intel_idle }, }; +static struct cpuidle_state ivb_cstates[MWAIT_MAX_NUM_CSTATES] = { + { /* MWAIT C0 */ }, + { /* MWAIT C1 */ + .name = "C1-IVB", + .desc = "MWAIT 0x00", + .flags = CPUIDLE_FLAG_TIME_VALID, + .exit_latency = 1, + .target_residency = 1, + .enter = &intel_idle }, + { /* MWAIT C2 */ + .name = "C3-IVB", + .desc = "MWAIT 0x10", + .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, + .exit_latency = 59, + .target_residency = 156, + .enter = &intel_idle }, + { /* MWAIT C3 */ + .name = "C6-IVB", + .desc = "MWAIT 0x20", + .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, + .exit_latency = 80, + .target_residency = 300, + .enter = &intel_idle }, + { /* MWAIT C4 */ + .name = "C7-IVB", + .desc = "MWAIT 0x30", + .flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED, + .exit_latency = 87, + .target_residency = 300, + .enter = &intel_idle }, +}; + static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = { { /* MWAIT C0 */ }, { /* MWAIT C1 */ @@ -347,6 +379,10 @@ static const struct idle_cpu idle_cpu_snb = { .state_table = snb_cstates, }; +static const struct idle_cpu idle_cpu_ivb = { + .state_table = ivb_cstates, +}; + #define ICPU(model, cpu) \ { X86_VENDOR_INTEL, 6, model, X86_FEATURE_MWAIT, (unsigned long)&cpu } @@ -362,6 +398,8 @@ static const struct x86_cpu_id intel_idle_ids[] = { ICPU(0x2f, idle_cpu_nehalem), ICPU(0x2a, idle_cpu_snb), ICPU(0x2d, idle_cpu_snb), + ICPU(0x3a, idle_cpu_ivb), + ICPU(0x3e, idle_cpu_ivb), {} }; MODULE_DEVICE_TABLE(x86cpu, intel_idle_ids); diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig index 8a9ad947d28..f5ab8b49c56 100644 --- a/drivers/input/Kconfig +++ b/drivers/input/Kconfig @@ -71,7 +71,7 @@ config INPUT_SPARSEKMAP comment "Userland interfaces" config INPUT_MOUSEDEV - tristate "Mouse interface" if EXPERT + tristate "Mouse interface" default y help Say Y here if you want your mouse to be accessible as char devices diff --git a/drivers/input/input.c b/drivers/input/input.c index 9566a67a2be..d4e854d702a 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -1784,6 +1784,10 @@ void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int break; case EV_ABS: + input_alloc_absinfo(dev); + if (!dev->absinfo) + return; + __set_bit(code, dev->absbit); break; diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index dc1e8b5df30..0a9f4b24282 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -2,7 +2,7 @@ # Input core configuration # menuconfig INPUT_KEYBOARD - bool "Keyboards" if EXPERT || !X86 + bool "Keyboards" default y help Say Y here, and a list of supported keyboards will be displayed. @@ -67,7 +67,7 @@ config KEYBOARD_ATARI module will be called atakbd. config KEYBOARD_ATKBD - tristate "AT keyboard" if EXPERT || !X86 + tristate "AT keyboard" default y select SERIO select SERIO_LIBPS2 diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig index 55f2c2293ec..93d4182a891 100644 --- a/drivers/input/serio/Kconfig +++ b/drivers/input/serio/Kconfig @@ -2,7 +2,7 @@ # Input core configuration # config SERIO - tristate "Serial I/O support" if EXPERT || !X86 + tristate "Serial I/O support" default y help Say Yes here if you have any input device that uses serial I/O to @@ -19,7 +19,7 @@ config SERIO if SERIO config SERIO_I8042 - tristate "i8042 PC Keyboard controller" if EXPERT || !X86 + tristate "i8042 PC Keyboard controller" default y depends on !PARISC && (!ARM || ARCH_SHARK || FOOTBRIDGE_HOST) && \ (!SUPERH || SH_CAYMAN) && !M68K && !BLACKFIN @@ -168,7 +168,7 @@ config SERIO_MACEPS2 module will be called maceps2. config SERIO_LIBPS2 - tristate "PS/2 driver library" if EXPERT + tristate "PS/2 driver library" depends on SERIO_I8042 || SERIO_I8042=n help Say Y here if you are using a driver for device connected diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c index 22cd96f58c9..ce384a449a6 100644 --- a/drivers/input/touchscreen/usbtouchscreen.c +++ b/drivers/input/touchscreen/usbtouchscreen.c @@ -106,6 +106,7 @@ struct usbtouch_device_info { struct usbtouch_usb { unsigned char *data; dma_addr_t data_dma; + int data_size; unsigned char *buffer; int buf_len; struct urb *irq; @@ -1474,7 +1475,7 @@ static int usbtouch_reset_resume(struct usb_interface *intf) static void usbtouch_free_buffers(struct usb_device *udev, struct usbtouch_usb *usbtouch) { - usb_free_coherent(udev, usbtouch->type->rept_size, + usb_free_coherent(udev, usbtouch->data_size, usbtouch->data, usbtouch->data_dma); kfree(usbtouch->buffer); } @@ -1519,7 +1520,20 @@ static int usbtouch_probe(struct usb_interface *intf, if (!type->process_pkt) type->process_pkt = usbtouch_process_pkt; - usbtouch->data = usb_alloc_coherent(udev, type->rept_size, + usbtouch->data_size = type->rept_size; + if (type->get_pkt_len) { + /* + * When dealing with variable-length packets we should + * not request more than wMaxPacketSize bytes at once + * as we do not know if there is more data coming or + * we filled exactly wMaxPacketSize bytes and there is + * nothing else. + */ + usbtouch->data_size = min(usbtouch->data_size, + usb_endpoint_maxp(endpoint)); + } + + usbtouch->data = usb_alloc_coherent(udev, usbtouch->data_size, GFP_KERNEL, &usbtouch->data_dma); if (!usbtouch->data) goto out_free; @@ -1578,12 +1592,12 @@ static int usbtouch_probe(struct usb_interface *intf, if (usb_endpoint_type(endpoint) == USB_ENDPOINT_XFER_INT) usb_fill_int_urb(usbtouch->irq, udev, usb_rcvintpipe(udev, endpoint->bEndpointAddress), - usbtouch->data, type->rept_size, + usbtouch->data, usbtouch->data_size, usbtouch_irq, usbtouch, endpoint->bInterval); else usb_fill_bulk_urb(usbtouch->irq, udev, usb_rcvbulkpipe(udev, endpoint->bEndpointAddress), - usbtouch->data, type->rept_size, + usbtouch->data, usbtouch->data_size, usbtouch_irq, usbtouch); usbtouch->irq->dev = udev; diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c index cc06a1e5242..4c260dc7910 100644 --- a/drivers/md/dm-bufio.c +++ b/drivers/md/dm-bufio.c @@ -1642,6 +1642,11 @@ static int __init dm_bufio_init(void) { __u64 mem; + dm_bufio_allocated_kmem_cache = 0; + dm_bufio_allocated_get_free_pages = 0; + dm_bufio_allocated_vmalloc = 0; + dm_bufio_current_allocated = 0; + memset(&dm_bufio_caches, 0, sizeof dm_bufio_caches); memset(&dm_bufio_cache_names, 0, sizeof dm_bufio_cache_names); diff --git a/drivers/md/dm-delay.c b/drivers/md/dm-delay.c index ee99912596c..fb4bf9bac1a 100644 --- a/drivers/md/dm-delay.c +++ b/drivers/md/dm-delay.c @@ -20,6 +20,7 @@ struct delay_c { struct timer_list delay_timer; struct mutex timer_lock; + struct workqueue_struct *kdelayd_wq; struct work_struct flush_expired_bios; struct list_head delayed_bios; atomic_t may_delay; @@ -45,14 +46,13 @@ struct dm_delay_info { static DEFINE_MUTEX(delayed_bios_lock); -static struct workqueue_struct *kdelayd_wq; static struct kmem_cache *delayed_cache; static void handle_delayed_timer(unsigned long data) { struct delay_c *dc = (struct delay_c *)data; - queue_work(kdelayd_wq, &dc->flush_expired_bios); + queue_work(dc->kdelayd_wq, &dc->flush_expired_bios); } static void queue_timeout(struct delay_c *dc, unsigned long expires) @@ -191,6 +191,12 @@ static int delay_ctr(struct dm_target *ti, unsigned int argc, char **argv) goto bad_dev_write; } + dc->kdelayd_wq = alloc_workqueue("kdelayd", WQ_MEM_RECLAIM, 0); + if (!dc->kdelayd_wq) { + DMERR("Couldn't start kdelayd"); + goto bad_queue; + } + setup_timer(&dc->delay_timer, handle_delayed_timer, (unsigned long)dc); INIT_WORK(&dc->flush_expired_bios, flush_expired_bios); @@ -203,6 +209,8 @@ static int delay_ctr(struct dm_target *ti, unsigned int argc, char **argv) ti->private = dc; return 0; +bad_queue: + mempool_destroy(dc->delayed_pool); bad_dev_write: if (dc->dev_write) dm_put_device(ti, dc->dev_write); @@ -217,7 +225,7 @@ static void delay_dtr(struct dm_target *ti) { struct delay_c *dc = ti->private; - flush_workqueue(kdelayd_wq); + destroy_workqueue(dc->kdelayd_wq); dm_put_device(ti, dc->dev_read); @@ -351,12 +359,6 @@ static int __init dm_delay_init(void) { int r = -ENOMEM; - kdelayd_wq = alloc_workqueue("kdelayd", WQ_MEM_RECLAIM, 0); - if (!kdelayd_wq) { - DMERR("Couldn't start kdelayd"); - goto bad_queue; - } - delayed_cache = KMEM_CACHE(dm_delay_info, 0); if (!delayed_cache) { DMERR("Couldn't create delayed bio cache."); @@ -374,8 +376,6 @@ static int __init dm_delay_init(void) bad_register: kmem_cache_destroy(delayed_cache); bad_memcache: - destroy_workqueue(kdelayd_wq); -bad_queue: return r; } @@ -383,7 +383,6 @@ static void __exit dm_delay_exit(void) { dm_unregister_target(&delay_target); kmem_cache_destroy(delayed_cache); - destroy_workqueue(kdelayd_wq); } /* Module hooks */ diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index b9e9ed4df80..c39ad839bd1 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -215,6 +215,11 @@ int dm_table_create(struct dm_table **result, fmode_t mode, num_targets = dm_round_up(num_targets, KEYS_PER_NODE); + if (!num_targets) { + kfree(t); + return -ENOMEM; + } + if (alloc_targets(t, num_targets)) { kfree(t); t = NULL; diff --git a/drivers/misc/enclosure.c b/drivers/misc/enclosure.c index 00e5fcac8fd..cbee842f8b6 100644 --- a/drivers/misc/enclosure.c +++ b/drivers/misc/enclosure.c @@ -198,6 +198,13 @@ static void enclosure_remove_links(struct enclosure_component *cdev) { char name[ENCLOSURE_NAME_SIZE]; + /* + * In odd circumstances, like multipath devices, something else may + * already have removed the links, so check for this condition first. + */ + if (!cdev->dev->kobj.sd) + return; + enclosure_link_name(cdev, name); sysfs_remove_link(&cdev->dev->kobj, name); sysfs_remove_link(&cdev->cdev.kobj, "device"); diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c index 905b16faee4..17851833f83 100644 --- a/drivers/net/usb/dm9601.c +++ b/drivers/net/usb/dm9601.c @@ -445,7 +445,12 @@ static int dm9601_bind(struct usbnet *dev, struct usb_interface *intf) dev->net->ethtool_ops = &dm9601_ethtool_ops; dev->net->hard_header_len += DM_TX_OVERHEAD; dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len; - dev->rx_urb_size = dev->net->mtu + ETH_HLEN + DM_RX_OVERHEAD; + + /* dm9620/21a require room for 4 byte padding, even in dm9601 + * mode, so we need +1 to be able to receive full size + * ethernet frames. + */ + dev->rx_urb_size = dev->net->mtu + ETH_HLEN + DM_RX_OVERHEAD + 1; dev->mii.dev = dev->net; dev->mii.mdio_read = dm9601_mdio_read; @@ -531,7 +536,7 @@ static int dm9601_rx_fixup(struct usbnet *dev, struct sk_buff *skb) static struct sk_buff *dm9601_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags) { - int len; + int len, pad; /* format: b1: packet length low @@ -539,12 +544,23 @@ static struct sk_buff *dm9601_tx_fixup(struct usbnet *dev, struct sk_buff *skb, b3..n: packet data */ - len = skb->len; + len = skb->len + DM_TX_OVERHEAD; - if (skb_headroom(skb) < DM_TX_OVERHEAD) { + /* workaround for dm962x errata with tx fifo getting out of + * sync if a USB bulk transfer retry happens right after a + * packet with odd / maxpacket length by adding up to 3 bytes + * padding. + */ + while ((len & 1) || !(len % dev->maxpacket)) + len++; + + len -= DM_TX_OVERHEAD; /* hw header doesn't count as part of length */ + pad = len - skb->len; + + if (skb_headroom(skb) < DM_TX_OVERHEAD || skb_tailroom(skb) < pad) { struct sk_buff *skb2; - skb2 = skb_copy_expand(skb, DM_TX_OVERHEAD, 0, flags); + skb2 = skb_copy_expand(skb, DM_TX_OVERHEAD, pad, flags); dev_kfree_skb_any(skb); skb = skb2; if (!skb) @@ -553,10 +569,10 @@ static struct sk_buff *dm9601_tx_fixup(struct usbnet *dev, struct sk_buff *skb, __skb_push(skb, DM_TX_OVERHEAD); - /* usbnet adds padding if length is a multiple of packet size - if so, adjust length value in header */ - if ((skb->len % dev->maxpacket) == 0) - len++; + if (pad) { + memset(skb->data + skb->len, 0, pad); + __skb_put(skb, pad); + } skb->data[0] = len; skb->data[1] = len >> 8; diff --git a/drivers/net/wireless/ath/ath9k/ar9002_mac.c b/drivers/net/wireless/ath/ath9k/ar9002_mac.c index aa2abaf31cb..fa7581a5049 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c @@ -76,9 +76,16 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) mask2 |= ATH9K_INT_CST; if (isr2 & AR_ISR_S2_TSFOOR) mask2 |= ATH9K_INT_TSFOOR; + + if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) { + REG_WRITE(ah, AR_ISR_S2, isr2); + isr &= ~AR_ISR_BCNMISC; + } } - isr = REG_READ(ah, AR_ISR_RAC); + if (pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED) + isr = REG_READ(ah, AR_ISR_RAC); + if (isr == 0xffffffff) { *masked = 0; return false; @@ -97,11 +104,23 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) *masked |= ATH9K_INT_TX; - s0_s = REG_READ(ah, AR_ISR_S0_S); + if (pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED) { + s0_s = REG_READ(ah, AR_ISR_S0_S); + s1_s = REG_READ(ah, AR_ISR_S1_S); + } else { + s0_s = REG_READ(ah, AR_ISR_S0); + REG_WRITE(ah, AR_ISR_S0, s0_s); + s1_s = REG_READ(ah, AR_ISR_S1); + REG_WRITE(ah, AR_ISR_S1, s1_s); + + isr &= ~(AR_ISR_TXOK | + AR_ISR_TXDESC | + AR_ISR_TXERR | + AR_ISR_TXEOL); + } + ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXOK); ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXDESC); - - s1_s = REG_READ(ah, AR_ISR_S1_S); ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXERR); ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXEOL); } @@ -114,13 +133,15 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) *masked |= mask2; } - if (AR_SREV_9100(ah)) - return true; - - if (isr & AR_ISR_GENTMR) { + if (!AR_SREV_9100(ah) && (isr & AR_ISR_GENTMR)) { u32 s5_s; - s5_s = REG_READ(ah, AR_ISR_S5_S); + if (pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED) { + s5_s = REG_READ(ah, AR_ISR_S5_S); + } else { + s5_s = REG_READ(ah, AR_ISR_S5); + } + ah->intr_gen_timer_trigger = MS(s5_s, AR_ISR_S5_GENTIMER_TRIG); @@ -133,8 +154,21 @@ static bool ar9002_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) if ((s5_s & AR_ISR_S5_TIM_TIMER) && !(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) *masked |= ATH9K_INT_TIM_TIMER; + + if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) { + REG_WRITE(ah, AR_ISR_S5, s5_s); + isr &= ~AR_ISR_GENTMR; + } } + if (!(pCap->hw_caps & ATH9K_HW_CAP_RAC_SUPPORTED)) { + REG_WRITE(ah, AR_ISR, isr); + REG_READ(ah, AR_ISR); + } + + if (AR_SREV_9100(ah)) + return true; + if (sync_cause) { fatal_int = (sync_cause & diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index abbd6effd60..204619e29a1 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c @@ -139,21 +139,26 @@ static void ath9k_htc_bssid_iter(void *data, u8 *mac, struct ieee80211_vif *vif) struct ath9k_vif_iter_data *iter_data = data; int i; - for (i = 0; i < ETH_ALEN; i++) - iter_data->mask[i] &= ~(iter_data->hw_macaddr[i] ^ mac[i]); + if (iter_data->hw_macaddr != NULL) { + for (i = 0; i < ETH_ALEN; i++) + iter_data->mask[i] &= ~(iter_data->hw_macaddr[i] ^ mac[i]); + } else { + iter_data->hw_macaddr = mac; + } } -static void ath9k_htc_set_bssid_mask(struct ath9k_htc_priv *priv, +static void ath9k_htc_set_mac_bssid_mask(struct ath9k_htc_priv *priv, struct ieee80211_vif *vif) { struct ath_common *common = ath9k_hw_common(priv->ah); struct ath9k_vif_iter_data iter_data; /* - * Use the hardware MAC address as reference, the hardware uses it - * together with the BSSID mask when matching addresses. + * Pick the MAC address of the first interface as the new hardware + * MAC address. The hardware will use it together with the BSSID mask + * when matching addresses. */ - iter_data.hw_macaddr = common->macaddr; + iter_data.hw_macaddr = NULL; memset(&iter_data.mask, 0xff, ETH_ALEN); if (vif) @@ -164,6 +169,10 @@ static void ath9k_htc_set_bssid_mask(struct ath9k_htc_priv *priv, &iter_data); memcpy(common->bssidmask, iter_data.mask, ETH_ALEN); + + if (iter_data.hw_macaddr) + memcpy(common->macaddr, iter_data.hw_macaddr, ETH_ALEN); + ath_hw_setbssidmask(common); } @@ -1091,7 +1100,7 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw, goto out; } - ath9k_htc_set_bssid_mask(priv, vif); + ath9k_htc_set_mac_bssid_mask(priv, vif); priv->vif_slot |= (1 << avp->index); priv->nvifs++; @@ -1154,7 +1163,7 @@ static void ath9k_htc_remove_interface(struct ieee80211_hw *hw, ath9k_htc_set_opmode(priv); - ath9k_htc_set_bssid_mask(priv, vif); + ath9k_htc_set_mac_bssid_mask(priv, vif); /* * Stop ANI only if there are no associated station interfaces. diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index f6a095f8ffc..b6d1ac9fb32 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1290,8 +1290,9 @@ void ath9k_calculate_iter_data(struct ieee80211_hw *hw, struct ath_common *common = ath9k_hw_common(ah); /* - * Use the hardware MAC address as reference, the hardware uses it - * together with the BSSID mask when matching addresses. + * Pick the MAC address of the first interface as the new hardware + * MAC address. The hardware will use it together with the BSSID mask + * when matching addresses. */ memset(iter_data, 0, sizeof(*iter_data)); iter_data->hw_macaddr = common->macaddr; diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index 67f9430ee19..5c1379c43d1 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c @@ -678,6 +678,8 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw) }; int index = rtlpci->rx_ring[rx_queue_idx].idx; + if (rtlpci->driver_is_goingto_unload) + return; /*RX NORMAL PKT */ while (count--) { /*rx descriptor */ @@ -1553,6 +1555,7 @@ static void rtl_pci_stop(struct ieee80211_hw *hw) */ set_hal_stop(rtlhal); + rtlpci->driver_is_goingto_unload = true; rtlpriv->cfg->ops->disable_interrupt(hw); cancel_work_sync(&rtlpriv->works.lps_leave_work); @@ -1570,7 +1573,6 @@ static void rtl_pci_stop(struct ieee80211_hw *hw) ppsc->rfchange_inprogress = true; spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flags); - rtlpci->driver_is_goingto_unload = true; rtlpriv->cfg->ops->hw_disable(hw); /* some things are not needed if firmware not available */ if (!rtlpriv->max_fw_size) diff --git a/drivers/rtc/rtc-at91rm9200.c b/drivers/rtc/rtc-at91rm9200.c index dc474bc6522..7029c8016dd 100644 --- a/drivers/rtc/rtc-at91rm9200.c +++ b/drivers/rtc/rtc-at91rm9200.c @@ -162,6 +162,8 @@ static int at91_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) at91_alarm_year = tm.tm_year; + tm.tm_mon = alrm->time.tm_mon; + tm.tm_mday = alrm->time.tm_mday; tm.tm_hour = alrm->time.tm_hour; tm.tm_min = alrm->time.tm_min; tm.tm_sec = alrm->time.tm_sec; diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index b0fefc435c0..599240af224 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -1219,7 +1219,7 @@ static void complete_scsi_command(struct CommandList *cp) "has check condition: aborted command: " "ASC: 0x%x, ASCQ: 0x%x\n", cp, asc, ascq); - cmd->result = DID_SOFT_ERROR << 16; + cmd->result |= DID_SOFT_ERROR << 16; break; } /* Must be some other type of check condition */ @@ -4466,7 +4466,7 @@ static int __devinit hpsa_init_one(struct pci_dev *pdev, hpsa_hba_inquiry(h); hpsa_register_scsi(h); /* hook ourselves into SCSI subsystem */ start_controller_lockup_detector(h); - return 1; + return 0; clean4: hpsa_free_sg_chain_blocks(h); diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c index d109cc3a17b..51ee663c131 100644 --- a/drivers/scsi/libsas/sas_ata.c +++ b/drivers/scsi/libsas/sas_ata.c @@ -211,7 +211,7 @@ static unsigned int sas_ata_qc_issue(struct ata_queued_cmd *qc) qc->tf.nsect = 0; } - ata_tf_to_fis(&qc->tf, 1, 0, (u8*)&task->ata_task.fis); + ata_tf_to_fis(&qc->tf, qc->dev->link->pmp, 1, (u8 *)&task->ata_task.fis); task->uldd_task = qc; if (ata_is_atapi(qc->tf.protocol)) { memcpy(task->ata_task.atapi_packet, qc->cdb, qc->dev->cdb_len); diff --git a/drivers/staging/comedi/drivers/pcmuio.c b/drivers/staging/comedi/drivers/pcmuio.c index 661ba2e0389..6e936c54f11 100644 --- a/drivers/staging/comedi/drivers/pcmuio.c +++ b/drivers/staging/comedi/drivers/pcmuio.c @@ -464,13 +464,13 @@ static int pcmuio_detach(struct comedi_device *dev) if (dev->iobase) release_region(dev->iobase, ASIC_IOSIZE * thisboard->num_asics); - for (i = 0; i < MAX_ASICS; ++i) { - if (devpriv->asics[i].irq) - free_irq(devpriv->asics[i].irq, dev); - } - - if (devpriv && devpriv->sprivs) + if (devpriv) { + for (i = 0; i < MAX_ASICS; ++i) { + if (devpriv->asics[i].irq) + free_irq(devpriv->asics[i].irq, dev); + } kfree(devpriv->sprivs); + } return 0; } diff --git a/drivers/staging/comedi/drivers/ssv_dnp.c b/drivers/staging/comedi/drivers/ssv_dnp.c index 526de2efa12..0316780103b 100644 --- a/drivers/staging/comedi/drivers/ssv_dnp.c +++ b/drivers/staging/comedi/drivers/ssv_dnp.c @@ -251,11 +251,11 @@ static int dnp_dio_insn_bits(struct comedi_device *dev, /* on return, data[1] contains the value of the digital input lines. */ outb(PADR, CSCIR); - data[0] = inb(CSCDR); + data[1] = inb(CSCDR); outb(PBDR, CSCIR); - data[0] += inb(CSCDR) << 8; + data[1] += inb(CSCDR) << 8; outb(PCDR, CSCIR); - data[0] += ((inb(CSCDR) & 0xF0) << 12); + data[1] += ((inb(CSCDR) & 0xF0) << 12); return 2; diff --git a/drivers/tty/serial/pmac_zilog.c b/drivers/tty/serial/pmac_zilog.c index 333c8d012b0..3f93c47d50b 100644 --- a/drivers/tty/serial/pmac_zilog.c +++ b/drivers/tty/serial/pmac_zilog.c @@ -2051,6 +2051,9 @@ static int __init pmz_console_init(void) /* Probe ports */ pmz_probe(); + if (pmz_ports_count == 0) + return -ENODEV; + /* TODO: Autoprobe console based on OF */ /* pmz_console.index = i; */ register_console(&pmz_console); diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index e411f186529..4a9dd86bce8 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1542,6 +1542,8 @@ static int acm_reset_resume(struct usb_interface *intf) static const struct usb_device_id acm_ids[] = { /* quirky and broken devices */ + { USB_DEVICE(0x17ef, 0x7000), /* Lenovo USB modem */ + .driver_info = NO_UNION_NORMAL, },/* has no union descriptor */ { USB_DEVICE(0x0870, 0x0001), /* Metricom GS Modem */ .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ }, diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 1434ee9ecb3..e5fa34e5423 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -822,13 +822,11 @@ static int wdm_manage_power(struct usb_interface *intf, int on) { /* need autopm_get/put here to ensure the usbcore sees the new value */ int rv = usb_autopm_get_interface(intf); - if (rv < 0) - goto err; intf->needs_remote_wakeup = on; - usb_autopm_put_interface(intf); -err: - return rv; + if (!rv) + usb_autopm_put_interface(intf); + return 0; } static int wdm_probe(struct usb_interface *intf, const struct usb_device_id *id) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index ed6c3617952..cd3d82769c5 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -4209,8 +4209,9 @@ static void hub_events(void) hub->hdev->children[i - 1]; dev_dbg(hub_dev, "warm reset port %d\n", i); - if (!udev || !(portstatus & - USB_PORT_STAT_CONNECTION)) { + if (!udev || + !(portstatus & USB_PORT_STAT_CONNECTION) || + udev->state == USB_STATE_NOTATTACHED) { status = hub_port_reset(hub, i, NULL, HUB_BH_RESET_TIME, true); diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 3584a169886..25150ca80e9 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -380,6 +380,8 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc, dep = dwc3_wIndex_to_dep(dwc, wIndex); if (!dep) return -EINVAL; + if (set == 0 && (dep->flags & DWC3_EP_WEDGE)) + break; ret = __dwc3_gadget_ep_set_halt(dep, set); if (ret) return -EINVAL; diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index c4df80cda53..9f7307ebc32 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1099,9 +1099,6 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value) else dep->flags |= DWC3_EP_STALL; } else { - if (dep->flags & DWC3_EP_WEDGE) - return 0; - ret = dwc3_send_gadget_ep_cmd(dwc, dep->number, DWC3_DEPCMD_CLEARSTALL, ¶ms); if (ret) @@ -1109,7 +1106,7 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value) value ? "set" : "clear", dep->name); else - dep->flags &= ~DWC3_EP_STALL; + dep->flags &= ~(DWC3_EP_STALL | DWC3_EP_WEDGE); } return ret; diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 3b983571e13..e485cf84950 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -584,6 +584,7 @@ static void reset_config(struct usb_composite_dev *cdev) bitmap_zero(f->endpoints, 32); } cdev->config = NULL; + cdev->delayed_status = 0; } static int set_config(struct usb_composite_dev *cdev, diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 664deb63807..546177fa7cf 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -223,14 +223,7 @@ static int usb_serial_generic_write_start(struct usb_serial_port *port) return result; } - /* Try sending off another urb, unless in irq context (in which case - * there will be no free urb). */ - if (!in_irq()) - goto retry; - - clear_bit_unlock(USB_SERIAL_WRITE_BUSY, &port->flags); - - return 0; + goto retry; /* try sending off another urb */ } /** diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 91293b68df5..8ccbf5e6b54 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -1962,25 +1962,25 @@ static void mos7840_change_port_settings(struct tty_struct *tty, iflag = tty->termios->c_iflag; /* Change the number of bits */ - if (cflag & CSIZE) { - switch (cflag & CSIZE) { - case CS5: - lData = LCR_BITS_5; - break; + switch (cflag & CSIZE) { + case CS5: + lData = LCR_BITS_5; + break; - case CS6: - lData = LCR_BITS_6; - break; + case CS6: + lData = LCR_BITS_6; + break; - case CS7: - lData = LCR_BITS_7; - break; - default: - case CS8: - lData = LCR_BITS_8; - break; - } + case CS7: + lData = LCR_BITS_7; + break; + + default: + case CS8: + lData = LCR_BITS_8; + break; } + /* Change the Parity bit */ if (cflag & PARENB) { if (cflag & PARODD) { diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index a5477554ecb..66f5e5472c1 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -85,6 +85,7 @@ static void option_instat_callback(struct urb *urb); #define HUAWEI_PRODUCT_K4505 0x1464 #define HUAWEI_PRODUCT_K3765 0x1465 #define HUAWEI_PRODUCT_K4605 0x14C6 +#define HUAWEI_PRODUCT_E173S6 0x1C07 #define QUANTA_VENDOR_ID 0x0408 #define QUANTA_PRODUCT_Q101 0xEA02 @@ -586,6 +587,8 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x1c23, USB_CLASS_COMM, 0x02, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E173, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t) &net_intf1_blacklist }, + { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E173S6, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t) &net_intf1_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E1750, 0xff, 0xff, 0xff), .driver_info = (kernel_ulong_t) &net_intf2_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x1441, USB_CLASS_COMM, 0x02, 0xff) }, @@ -648,6 +651,10 @@ static const struct usb_device_id option_ids[] = { { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6D) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6E) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x6F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x72) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x73) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x74) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x75) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x78) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x79) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x01, 0x7A) }, @@ -702,6 +709,10 @@ static const struct usb_device_id option_ids[] = { { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6D) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6E) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x6F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x72) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x73) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x74) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x75) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x78) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x79) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x02, 0x7A) }, @@ -756,6 +767,10 @@ static const struct usb_device_id option_ids[] = { { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x6D) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x6E) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x6F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x72) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x73) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x74) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x75) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x78) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x79) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x03, 0x7A) }, @@ -810,6 +825,10 @@ static const struct usb_device_id option_ids[] = { { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x6D) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x6E) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x6F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x72) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x73) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x74) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x75) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x78) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x79) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x04, 0x7A) }, @@ -864,6 +883,10 @@ static const struct usb_device_id option_ids[] = { { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x6D) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x6E) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x6F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x72) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x73) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x74) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x75) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x78) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x79) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x05, 0x7A) }, @@ -918,6 +941,10 @@ static const struct usb_device_id option_ids[] = { { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x6D) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x6E) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x6F) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x72) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x73) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x74) }, + { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x75) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x78) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x79) }, { USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0xff, 0x06, 0x7A) }, diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index a1a9062954c..1dcccd43d62 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -290,24 +290,22 @@ static void pl2303_set_termios(struct tty_struct *tty, dbg("0xa1:0x21:0:0 %d - %x %x %x %x %x %x %x", i, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6]); - if (cflag & CSIZE) { - switch (cflag & CSIZE) { - case CS5: - buf[6] = 5; - break; - case CS6: - buf[6] = 6; - break; - case CS7: - buf[6] = 7; - break; - default: - case CS8: - buf[6] = 8; - break; - } - dbg("%s - data bits = %d", __func__, buf[6]); + switch (cflag & CSIZE) { + case CS5: + buf[6] = 5; + break; + case CS6: + buf[6] = 6; + break; + case CS7: + buf[6] = 7; + break; + default: + case CS8: + buf[6] = 8; + break; } + dbg("%s - data bits = %d", __func__, buf[6]); /* For reference buf[0]:buf[3] baud rate value */ /* NOTE: Only the values defined in baud_sup are supported ! diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c index f06c9a8f3d3..003ef9019ad 100644 --- a/drivers/usb/serial/spcp8x5.c +++ b/drivers/usb/serial/spcp8x5.c @@ -396,22 +396,20 @@ static void spcp8x5_set_termios(struct tty_struct *tty, } /* Set Data Length : 00:5bit, 01:6bit, 10:7bit, 11:8bit */ - if (cflag & CSIZE) { - switch (cflag & CSIZE) { - case CS5: - buf[1] |= SET_UART_FORMAT_SIZE_5; - break; - case CS6: - buf[1] |= SET_UART_FORMAT_SIZE_6; - break; - case CS7: - buf[1] |= SET_UART_FORMAT_SIZE_7; - break; - default: - case CS8: - buf[1] |= SET_UART_FORMAT_SIZE_8; - break; - } + switch (cflag & CSIZE) { + case CS5: + buf[1] |= SET_UART_FORMAT_SIZE_5; + break; + case CS6: + buf[1] |= SET_UART_FORMAT_SIZE_6; + break; + case CS7: + buf[1] |= SET_UART_FORMAT_SIZE_7; + break; + default: + case CS8: + buf[1] |= SET_UART_FORMAT_SIZE_8; + break; } /* Set Stop bit2 : 0:1bit 1:2bit */ diff --git a/drivers/watchdog/sc1200wdt.c b/drivers/watchdog/sc1200wdt.c index 3fb83b0c28c..ab6d3f56cbc 100644 --- a/drivers/watchdog/sc1200wdt.c +++ b/drivers/watchdog/sc1200wdt.c @@ -409,8 +409,9 @@ static int __init sc1200wdt_init(void) #if defined CONFIG_PNP /* now that the user has specified an IO port and we haven't detected * any devices, disable pnp support */ + if (isapnp) + pnp_unregister_driver(&scl200wdt_pnp_driver); isapnp = 0; - pnp_unregister_driver(&scl200wdt_pnp_driver); #endif if (!request_region(io, io_len, SC1200_MODULE_NAME)) { diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index bb01881cb1f..9fdc0513fb4 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c @@ -213,9 +213,13 @@ static int readpage_nounlock(struct file *filp, struct page *page) if (err < 0) { SetPageError(page); goto out; - } else if (err < PAGE_CACHE_SIZE) { + } else { + if (err < PAGE_CACHE_SIZE) { /* zero fill remainder of page */ - zero_user_segment(page, err, PAGE_CACHE_SIZE); + zero_user_segment(page, err, PAGE_CACHE_SIZE); + } else { + flush_dcache_page(page); + } } SetPageUptodate(page); diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index cf1b9e043b0..ae3ca035bad 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -609,6 +609,8 @@ static void __unregister_request(struct ceph_mds_client *mdsc, req->r_unsafe_dir = NULL; } + complete_all(&req->r_safe_completion); + ceph_mdsc_put_request(req); } @@ -1815,8 +1817,11 @@ static int __do_request(struct ceph_mds_client *mdsc, int mds = -1; int err = -EAGAIN; - if (req->r_err || req->r_got_result) + if (req->r_err || req->r_got_result) { + if (req->r_aborted) + __unregister_request(mdsc, req); goto out; + } if (req->r_timeout && time_after_eq(jiffies, req->r_started + req->r_timeout)) { @@ -2129,7 +2134,6 @@ static void handle_reply(struct ceph_mds_session *session, struct ceph_msg *msg) if (head->safe) { req->r_got_safe = true; __unregister_request(mdsc, req); - complete_all(&req->r_safe_completion); if (req->r_got_unsafe) { /* diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index b9a3726ea04..c883561e9b6 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -317,8 +317,10 @@ static int ext4_valid_extent(struct inode *inode, struct ext4_extent *ext) { ext4_fsblk_t block = ext4_ext_pblock(ext); int len = ext4_ext_get_actual_len(ext); + ext4_lblk_t lblock = le32_to_cpu(ext->ee_block); + ext4_lblk_t last = lblock + len - 1; - if (len == 0) + if (lblock > last) return 0; return ext4_data_block_valid(EXT4_SB(inode->i_sb), block, len); } @@ -344,11 +346,26 @@ static int ext4_valid_extent_entries(struct inode *inode, if (depth == 0) { /* leaf entries */ struct ext4_extent *ext = EXT_FIRST_EXTENT(eh); + struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es; + ext4_fsblk_t pblock = 0; + ext4_lblk_t lblock = 0; + ext4_lblk_t prev = 0; + int len = 0; while (entries) { if (!ext4_valid_extent(inode, ext)) return 0; + + /* Check for overlapping extents */ + lblock = le32_to_cpu(ext->ee_block); + len = ext4_ext_get_actual_len(ext); + if ((lblock <= prev) && prev) { + pblock = ext4_ext_pblock(ext); + es->s_last_error_block = cpu_to_le64(pblock); + return 0; + } ext++; entries--; + prev = lblock + len - 1; } } else { struct ext4_extent_idx *ext_idx = EXT_FIRST_INDEX(eh); diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 878484256a6..2941ee6ef24 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -3326,6 +3326,9 @@ static void ext4_mb_pa_callback(struct rcu_head *head) { struct ext4_prealloc_space *pa; pa = container_of(head, struct ext4_prealloc_space, u.pa_rcu); + + BUG_ON(atomic_read(&pa->pa_count)); + BUG_ON(pa->pa_deleted == 0); kmem_cache_free(ext4_pspace_cachep, pa); } @@ -3339,11 +3342,13 @@ static void ext4_mb_put_pa(struct ext4_allocation_context *ac, ext4_group_t grp; ext4_fsblk_t grp_blk; - if (!atomic_dec_and_test(&pa->pa_count) || pa->pa_free != 0) - return; - /* in this short window concurrent discard can set pa_deleted */ spin_lock(&pa->pa_lock); + if (!atomic_dec_and_test(&pa->pa_count) || pa->pa_free != 0) { + spin_unlock(&pa->pa_lock); + return; + } + if (pa->pa_deleted == 1) { spin_unlock(&pa->pa_lock); return; diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c index 9b2ff0e851b..40bd9999250 100644 --- a/fs/gfs2/aops.c +++ b/fs/gfs2/aops.c @@ -1012,6 +1012,7 @@ static ssize_t gfs2_direct_IO(int rw, struct kiocb *iocb, { struct file *file = iocb->ki_filp; struct inode *inode = file->f_mapping->host; + struct address_space *mapping = inode->i_mapping; struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_holder gh; int rv; @@ -1032,6 +1033,35 @@ static ssize_t gfs2_direct_IO(int rw, struct kiocb *iocb, if (rv != 1) goto out; /* dio not valid, fall back to buffered i/o */ + /* + * Now since we are holding a deferred (CW) lock at this point, you + * might be wondering why this is ever needed. There is a case however + * where we've granted a deferred local lock against a cached exclusive + * glock. That is ok provided all granted local locks are deferred, but + * it also means that it is possible to encounter pages which are + * cached and possibly also mapped. So here we check for that and sort + * them out ahead of the dio. The glock state machine will take care of + * everything else. + * + * If in fact the cached glock state (gl->gl_state) is deferred (CW) in + * the first place, mapping->nr_pages will always be zero. + */ + if (mapping->nrpages) { + loff_t lstart = offset & (PAGE_CACHE_SIZE - 1); + loff_t len = iov_length(iov, nr_segs); + loff_t end = PAGE_ALIGN(offset + len) - 1; + + rv = 0; + if (len == 0) + goto out; + if (test_and_clear_bit(GIF_SW_PAGED, &ip->i_flags)) + unmap_shared_mapping_range(ip->i_inode.i_mapping, offset, len); + rv = filemap_write_and_wait_range(mapping, lstart, end); + if (rv) + return rv; + truncate_inode_pages_range(mapping, lstart, end); + } + rv = __blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov, offset, nr_segs, gfs2_get_block_direct, NULL, NULL, 0); diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index 6f3a18f9e17..c0c529dc34a 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c @@ -1298,8 +1298,18 @@ static struct dentry *gfs2_mount(struct file_system_type *fs_type, int flags, if (IS_ERR(s)) goto error_bdev; - if (s->s_root) + if (s->s_root) { + /* + * s_umount nests inside bd_mutex during + * __invalidate_device(). blkdev_put() acquires + * bd_mutex and can't be called under s_umount. Drop + * s_umount temporarily. This is safe as we're + * holding an active reference. + */ + up_write(&s->s_umount); blkdev_put(bdev, mode); + down_write(&s->s_umount); + } memset(&args, 0, sizeof(args)); args.ar_quota = GFS2_QUOTA_DEFAULT; diff --git a/fs/hpfs/file.c b/fs/hpfs/file.c index 89d2a5803ae..5ecfffe2533 100644 --- a/fs/hpfs/file.c +++ b/fs/hpfs/file.c @@ -116,9 +116,12 @@ static int hpfs_write_begin(struct file *file, struct address_space *mapping, hpfs_get_block, &hpfs_i(mapping->host)->mmu_private); if (unlikely(ret)) { - loff_t isize = mapping->host->i_size; + loff_t isize; + hpfs_lock(mapping->host->i_sb); + isize = mapping->host->i_size; if (pos + len > isize) vmtruncate(mapping->host, isize); + hpfs_unlock(mapping->host->i_sb); } return ret; diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c index b1631dd3d04..baedf6a8610 100644 --- a/fs/jbd2/transaction.c +++ b/fs/jbd2/transaction.c @@ -1125,7 +1125,10 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh) * once a transaction -bzzz */ jh->b_modified = 1; - J_ASSERT_JH(jh, handle->h_buffer_credits > 0); + if (handle->h_buffer_credits <= 0) { + ret = -ENOSPC; + goto out_unlock_bh; + } handle->h_buffer_credits--; } @@ -1208,7 +1211,6 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh) jbd2_journal_put_journal_head(jh); out: JBUFFER_TRACE(jh, "exit"); - WARN_ON(ret); /* All errors are bugs, so dump the stack */ return ret; } diff --git a/fs/nfs/blocklayout/extents.c b/fs/nfs/blocklayout/extents.c index 1f9a6032796..51f9ff25d47 100644 --- a/fs/nfs/blocklayout/extents.c +++ b/fs/nfs/blocklayout/extents.c @@ -44,7 +44,7 @@ static inline sector_t normalize(sector_t s, int base) { sector_t tmp = s; /* Since do_div modifies its argument */ - return s - do_div(tmp, base); + return s - sector_div(tmp, base); } static inline sector_t normalize_up(sector_t s, int base) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index c1b6b911016..18e09e402f1 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -4041,11 +4041,17 @@ static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata) return; switch (task->tk_status) { - case -NFS4ERR_STALE_STATEID: - case -NFS4ERR_EXPIRED: case 0: renew_lease(data->res.server, data->timestamp); break; + case -NFS4ERR_ADMIN_REVOKED: + case -NFS4ERR_DELEG_REVOKED: + case -NFS4ERR_BAD_STATEID: + case -NFS4ERR_OLD_STATEID: + case -NFS4ERR_STALE_STATEID: + case -NFS4ERR_EXPIRED: + task->tk_status = 0; + break; default: if (nfs4_async_handle_error(task, data->res.server, NULL) == -EAGAIN) { diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index 91f8ff547ab..6a6c1fdb789 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c @@ -400,7 +400,8 @@ xfs_attrlist_by_handle( return -XFS_ERROR(EPERM); if (copy_from_user(&al_hreq, arg, sizeof(xfs_fsop_attrlist_handlereq_t))) return -XFS_ERROR(EFAULT); - if (al_hreq.buflen > XATTR_LIST_MAX) + if (al_hreq.buflen < sizeof(struct attrlist) || + al_hreq.buflen > XATTR_LIST_MAX) return -XFS_ERROR(EINVAL); /* diff --git a/fs/xfs/xfs_ioctl32.c b/fs/xfs/xfs_ioctl32.c index a849a5473af..745ea4ea98a 100644 --- a/fs/xfs/xfs_ioctl32.c +++ b/fs/xfs/xfs_ioctl32.c @@ -361,7 +361,8 @@ xfs_compat_attrlist_by_handle( if (copy_from_user(&al_hreq, arg, sizeof(compat_xfs_fsop_attrlist_handlereq_t))) return -XFS_ERROR(EFAULT); - if (al_hreq.buflen > XATTR_LIST_MAX) + if (al_hreq.buflen < sizeof(struct attrlist) || + al_hreq.buflen > XATTR_LIST_MAX) return -XFS_ERROR(EINVAL); /* diff --git a/include/crypto/scatterwalk.h b/include/crypto/scatterwalk.h index 3744d2a642d..2cddd2b92c1 100644 --- a/include/crypto/scatterwalk.h +++ b/include/crypto/scatterwalk.h @@ -36,6 +36,7 @@ static inline void scatterwalk_sg_chain(struct scatterlist *sg1, int num, { sg_set_page(&sg1[num - 1], (void *)sg2, 0, 0); sg1[num - 1].page_link &= ~0x02; + sg1[num - 1].page_link |= 0x01; } static inline struct scatterlist *scatterwalk_sg_next(struct scatterlist *sg) @@ -43,7 +44,7 @@ static inline struct scatterlist *scatterwalk_sg_next(struct scatterlist *sg) if (sg_is_last(sg)) return NULL; - return (++sg)->length ? sg : (void *)sg_page(sg); + return (++sg)->length ? sg : sg_chain_ptr(sg); } static inline void scatterwalk_crypto_chain(struct scatterlist *head, diff --git a/include/drm/drm_pciids.h b/include/drm/drm_pciids.h index 1a13caac89d..757f98066d6 100644 --- a/include/drm/drm_pciids.h +++ b/include/drm/drm_pciids.h @@ -544,7 +544,7 @@ {0x1002, 0x9645, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO2|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x9647, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP},\ {0x1002, 0x9648, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP},\ - {0x1002, 0x9649, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP},\ + {0x1002, 0x9649, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO2|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP},\ {0x1002, 0x964a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x964b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ {0x1002, 0x964c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_SUMO|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \ diff --git a/include/sound/memalloc.h b/include/sound/memalloc.h index c4250621264..ab240bb608a 100644 --- a/include/sound/memalloc.h +++ b/include/sound/memalloc.h @@ -101,7 +101,7 @@ static inline unsigned int snd_sgbuf_aligned_pages(size_t size) static inline dma_addr_t snd_sgbuf_get_addr(struct snd_sg_buf *sgbuf, size_t offset) { dma_addr_t addr = sgbuf->table[offset >> PAGE_SHIFT].addr; - addr &= PAGE_MASK; + addr &= ~((dma_addr_t)PAGE_SIZE - 1); return addr + offset % PAGE_SIZE; } diff --git a/kernel/futex.c b/kernel/futex.c index 6a8253de6ad..f4bcf482359 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -286,7 +286,7 @@ get_futex_key(u32 __user *uaddr, int fshared, union futex_key *key, int rw) put_page(page); /* serialize against __split_huge_page_splitting() */ local_irq_disable(); - if (likely(__get_user_pages_fast(address, 1, 1, &page) == 1)) { + if (likely(__get_user_pages_fast(address, 1, !ro, &page) == 1)) { page_head = compound_head(page); /* * page_head is valid pointer but we must pin diff --git a/kernel/irq/pm.c b/kernel/irq/pm.c index 0e3b91916c7..cfa724d747b 100644 --- a/kernel/irq/pm.c +++ b/kernel/irq/pm.c @@ -50,7 +50,7 @@ static void resume_irqs(bool want_early) bool is_early = desc->action && desc->action->flags & IRQF_EARLY_RESUME; - if (is_early != want_early) + if (!is_early && want_early) continue; raw_spin_lock_irqsave(&desc->lock, flags); diff --git a/kernel/sched/debug.c b/kernel/sched/debug.c index 06d172eb5ce..5d3f9fbefeb 100644 --- a/kernel/sched/debug.c +++ b/kernel/sched/debug.c @@ -215,6 +215,14 @@ void print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq) SEQ_printf(m, " .%-30s: %d\n", "load_tg", atomic_read(&cfs_rq->tg->load_weight)); #endif +#ifdef CONFIG_CFS_BANDWIDTH + SEQ_printf(m, " .%-30s: %d\n", "tg->cfs_bandwidth.timer_active", + cfs_rq->tg->cfs_bandwidth.timer_active); + SEQ_printf(m, " .%-30s: %d\n", "throttled", + cfs_rq->throttled); + SEQ_printf(m, " .%-30s: %d\n", "throttle_count", + cfs_rq->throttle_count); +#endif print_cfs_group_stats(m, cpu, cfs_rq->tg); #endif diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 5c5722a1993..6294062e831 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -1661,6 +1661,8 @@ static void throttle_cfs_rq(struct cfs_rq *cfs_rq) cfs_rq->throttled_timestamp = rq->clock; raw_spin_lock(&cfs_b->lock); list_add_tail_rcu(&cfs_rq->throttled_list, &cfs_b->throttled_cfs_rq); + if (!cfs_b->timer_active) + __start_cfs_bandwidth(cfs_b); raw_spin_unlock(&cfs_b->lock); } diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c index 29bcc83b3db..e40841f18a8 100644 --- a/kernel/sched/rt.c +++ b/kernel/sched/rt.c @@ -902,6 +902,13 @@ inc_rt_prio_smp(struct rt_rq *rt_rq, int prio, int prev_prio) { struct rq *rq = rq_of_rt_rq(rt_rq); +#ifdef CONFIG_RT_GROUP_SCHED + /* + * Change rq's cpupri only if rt_rq is the top queue. + */ + if (&rq->rt != rt_rq) + return; +#endif if (rq->online && prio < prev_prio) cpupri_set(&rq->rd->cpupri, rq->cpu, prio); } @@ -911,6 +918,13 @@ dec_rt_prio_smp(struct rt_rq *rt_rq, int prio, int prev_prio) { struct rq *rq = rq_of_rt_rq(rt_rq); +#ifdef CONFIG_RT_GROUP_SCHED + /* + * Change rq's cpupri only if rt_rq is the top queue. + */ + if (&rq->rt != rt_rq) + return; +#endif if (rq->online && rt_rq->highest_prio.curr != prev_prio) cpupri_set(&rq->rd->cpupri, rq->cpu, rt_rq->highest_prio.curr); } diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 8c8169bf502..f0e76e93aee 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -688,7 +688,7 @@ static int ftrace_profile_init(void) int cpu; int ret = 0; - for_each_online_cpu(cpu) { + for_each_possible_cpu(cpu) { ret = ftrace_profile_init_cpu(cpu); if (ret) break; diff --git a/mm/rmap.c b/mm/rmap.c index bfca52c9699..f02c862fab6 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -623,7 +623,11 @@ pte_t *__page_check_address(struct page *page, struct mm_struct *mm, spinlock_t *ptl; if (unlikely(PageHuge(page))) { + /* when pud is not present, pte will be NULL */ pte = huge_pte_offset(mm, address); + if (!pte) + return NULL; + ptl = &mm->page_table_lock; goto check; } diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 067aa2a2305..6937a84bef3 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -763,7 +763,8 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx) u16 sc; u8 tid, ack_policy; - if (!ieee80211_is_data_qos(hdr->frame_control)) + if (!ieee80211_is_data_qos(hdr->frame_control) || + is_multicast_ether_addr(hdr->addr1)) goto dont_reorder; /* diff --git a/net/wireless/radiotap.c b/net/wireless/radiotap.c index 617a310025b..60549a4a2f9 100644 --- a/net/wireless/radiotap.c +++ b/net/wireless/radiotap.c @@ -122,6 +122,10 @@ int ieee80211_radiotap_iterator_init( /* find payload start allowing for extended bitmap(s) */ if (iterator->_bitmap_shifter & (1<_arg - + (unsigned long)iterator->_rtheader + sizeof(uint32_t) > + (unsigned long)iterator->_max_length) + return -EINVAL; while (get_unaligned_le32(iterator->_arg) & (1 << IEEE80211_RADIOTAP_EXT)) { iterator->_arg += sizeof(uint32_t); diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 1ae096ed7dc..6c8c416b874 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -52,6 +52,7 @@ #include #include /* for local_port_range[] */ #include /* struct or_callable used in sock_rcv_skb */ +#include #include #include #include @@ -3780,7 +3781,7 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid) u32 nlbl_sid; u32 nlbl_type; - selinux_skb_xfrm_sid(skb, &xfrm_sid); + selinux_xfrm_skb_sid(skb, &xfrm_sid); selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid); err = security_net_peersid_resolve(nlbl_sid, nlbl_type, xfrm_sid, sid); @@ -3794,6 +3795,30 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid) return 0; } +/** + * selinux_conn_sid - Determine the child socket label for a connection + * @sk_sid: the parent socket's SID + * @skb_sid: the packet's SID + * @conn_sid: the resulting connection SID + * + * If @skb_sid is valid then the user:role:type information from @sk_sid is + * combined with the MLS information from @skb_sid in order to create + * @conn_sid. If @skb_sid is not valid then then @conn_sid is simply a copy + * of @sk_sid. Returns zero on success, negative values on failure. + * + */ +static int selinux_conn_sid(u32 sk_sid, u32 skb_sid, u32 *conn_sid) +{ + int err = 0; + + if (skb_sid != SECSID_NULL) + err = security_sid_mls_copy(sk_sid, skb_sid, conn_sid); + else + *conn_sid = sk_sid; + + return err; +} + /* socket security operations */ static int socket_sockcreate_sid(const struct task_security_struct *tsec, @@ -4276,8 +4301,10 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) } err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER, PEER__RECV, &ad); - if (err) + if (err) { selinux_netlbl_err(skb, err, 0); + return err; + } } if (secmark_active) { @@ -4415,7 +4442,7 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb, struct sk_security_struct *sksec = sk->sk_security; int err; u16 family = sk->sk_family; - u32 newsid; + u32 connsid; u32 peersid; /* handle mapped IPv4 packets arriving via IPv6 sockets */ @@ -4425,16 +4452,11 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb, err = selinux_skb_peerlbl_sid(skb, family, &peersid); if (err) return err; - if (peersid == SECSID_NULL) { - req->secid = sksec->sid; - req->peer_secid = SECSID_NULL; - } else { - err = security_sid_mls_copy(sksec->sid, peersid, &newsid); - if (err) - return err; - req->secid = newsid; - req->peer_secid = peersid; - } + err = selinux_conn_sid(sksec->sid, peersid, &connsid); + if (err) + return err; + req->secid = connsid; + req->peer_secid = peersid; return selinux_netlbl_inet_conn_request(req, family); } @@ -4666,6 +4688,7 @@ static unsigned int selinux_ipv6_forward(unsigned int hooknum, static unsigned int selinux_ip_output(struct sk_buff *skb, u16 family) { + struct sock *sk; u32 sid; if (!netlbl_enabled()) @@ -4674,8 +4697,27 @@ static unsigned int selinux_ip_output(struct sk_buff *skb, /* we do this in the LOCAL_OUT path and not the POST_ROUTING path * because we want to make sure we apply the necessary labeling * before IPsec is applied so we can leverage AH protection */ - if (skb->sk) { - struct sk_security_struct *sksec = skb->sk->sk_security; + sk = skb->sk; + if (sk) { + struct sk_security_struct *sksec; + + if (sk->sk_state == TCP_LISTEN) + /* if the socket is the listening state then this + * packet is a SYN-ACK packet which means it needs to + * be labeled based on the connection/request_sock and + * not the parent socket. unfortunately, we can't + * lookup the request_sock yet as it isn't queued on + * the parent socket until after the SYN-ACK is sent. + * the "solution" is to simply pass the packet as-is + * as any IP option based labeling should be copied + * from the initial connection request (in the IP + * layer). it is far from ideal, but until we get a + * security label in the packet itself this is the + * best we can do. */ + return NF_ACCEPT; + + /* standard practice, label using the parent socket */ + sksec = sk->sk_security; sid = sksec->sid; } else sid = SECINITSID_KERNEL; @@ -4748,27 +4790,37 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, * as fast and as clean as possible. */ if (!selinux_policycap_netpeer) return selinux_ip_postroute_compat(skb, ifindex, family); + + secmark_active = selinux_secmark_enabled(); + peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled(); + if (!secmark_active && !peerlbl_active) + return NF_ACCEPT; + + sk = skb->sk; + #ifdef CONFIG_XFRM /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec * packet transformation so allow the packet to pass without any checks * since we'll have another chance to perform access control checks * when the packet is on it's final way out. * NOTE: there appear to be some IPv6 multicast cases where skb->dst - * is NULL, in this case go ahead and apply access control. */ - if (skb_dst(skb) != NULL && skb_dst(skb)->xfrm != NULL) + * is NULL, in this case go ahead and apply access control. + * is NULL, in this case go ahead and apply access control. + * NOTE: if this is a local socket (skb->sk != NULL) that is in the + * TCP listening state we cannot wait until the XFRM processing + * is done as we will miss out on the SA label if we do; + * unfortunately, this means more work, but it is only once per + * connection. */ + if (skb_dst(skb) != NULL && skb_dst(skb)->xfrm != NULL && + !(sk != NULL && sk->sk_state == TCP_LISTEN)) return NF_ACCEPT; #endif - secmark_active = selinux_secmark_enabled(); - peerlbl_active = netlbl_enabled() || selinux_xfrm_enabled(); - if (!secmark_active && !peerlbl_active) - return NF_ACCEPT; - /* if the packet is being forwarded then get the peer label from the - * packet itself; otherwise check to see if it is from a local - * application or the kernel, if from an application get the peer label - * from the sending socket, otherwise use the kernel's sid */ - sk = skb->sk; if (sk == NULL) { + /* Without an associated socket the packet is either coming + * from the kernel or it is being forwarded; check the packet + * to determine which and if the packet is being forwarded + * query the packet directly to determine the security label. */ if (skb->skb_iif) { secmark_perm = PACKET__FORWARD_OUT; if (selinux_skb_peerlbl_sid(skb, family, &peer_sid)) @@ -4777,7 +4829,45 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, secmark_perm = PACKET__SEND; peer_sid = SECINITSID_KERNEL; } + } else if (sk->sk_state == TCP_LISTEN) { + /* Locally generated packet but the associated socket is in the + * listening state which means this is a SYN-ACK packet. In + * this particular case the correct security label is assigned + * to the connection/request_sock but unfortunately we can't + * query the request_sock as it isn't queued on the parent + * socket until after the SYN-ACK packet is sent; the only + * viable choice is to regenerate the label like we do in + * selinux_inet_conn_request(). See also selinux_ip_output() + * for similar problems. */ + u32 skb_sid; + struct sk_security_struct *sksec = sk->sk_security; + if (selinux_skb_peerlbl_sid(skb, family, &skb_sid)) + return NF_DROP; + /* At this point, if the returned skb peerlbl is SECSID_NULL + * and the packet has been through at least one XFRM + * transformation then we must be dealing with the "final" + * form of labeled IPsec packet; since we've already applied + * all of our access controls on this packet we can safely + * pass the packet. */ + if (skb_sid == SECSID_NULL) { + switch (family) { + case PF_INET: + if (IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) + return NF_ACCEPT; + break; + case PF_INET6: + if (IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) + return NF_ACCEPT; + default: + return NF_DROP_ERR(-ECONNREFUSED); + } + } + if (selinux_conn_sid(sksec->sid, skb_sid, &peer_sid)) + return NF_DROP; + secmark_perm = PACKET__SEND; } else { + /* Locally generated packet, fetch the security label from the + * associated socket. */ struct sk_security_struct *sksec = sk->sk_security; peer_sid = sksec->sid; secmark_perm = PACKET__SEND; @@ -5445,11 +5535,11 @@ static int selinux_setprocattr(struct task_struct *p, /* Check for ptracing, and update the task SID if ok. Otherwise, leave SID unchanged and fail. */ ptsid = 0; - task_lock(p); + rcu_read_lock(); tracer = ptrace_parent(p); if (tracer) ptsid = task_sid(tracer); - task_unlock(p); + rcu_read_unlock(); if (tracer) { error = avc_has_perm(ptsid, sid, SECCLASS_PROCESS, diff --git a/security/selinux/include/xfrm.h b/security/selinux/include/xfrm.h index c220f314709..d1c980cee5d 100644 --- a/security/selinux/include/xfrm.h +++ b/security/selinux/include/xfrm.h @@ -47,6 +47,7 @@ int selinux_xfrm_sock_rcv_skb(u32 sid, struct sk_buff *skb, int selinux_xfrm_postroute_last(u32 isec_sid, struct sk_buff *skb, struct common_audit_data *ad, u8 proto); int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall); +int selinux_xfrm_skb_sid(struct sk_buff *skb, u32 *sid); static inline void selinux_xfrm_notify_policyload(void) { @@ -79,12 +80,12 @@ static inline int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int static inline void selinux_xfrm_notify_policyload(void) { } -#endif -static inline void selinux_skb_xfrm_sid(struct sk_buff *skb, u32 *sid) +static inline int selinux_xfrm_skb_sid(struct sk_buff *skb, u32 *sid) { - int err = selinux_xfrm_decode_session(skb, sid, 0); - BUG_ON(err); + *sid = SECSID_NULL; + return 0; } +#endif #endif /* _SELINUX_XFRM_H_ */ diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c index 8ab29515451..1552b910d9e 100644 --- a/security/selinux/xfrm.c +++ b/security/selinux/xfrm.c @@ -152,21 +152,13 @@ int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, struct xfrm_policy * return rc; } -/* - * LSM hook implementation that checks and/or returns the xfrm sid for the - * incoming packet. - */ - -int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall) +static int selinux_xfrm_skb_sid_ingress(struct sk_buff *skb, + u32 *sid, int ckall) { - struct sec_path *sp; + struct sec_path *sp = skb->sp; *sid = SECSID_NULL; - if (skb == NULL) - return 0; - - sp = skb->sp; if (sp) { int i, sid_set = 0; @@ -190,6 +182,45 @@ int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall) return 0; } +static u32 selinux_xfrm_skb_sid_egress(struct sk_buff *skb) +{ + struct dst_entry *dst = skb_dst(skb); + struct xfrm_state *x; + + if (dst == NULL) + return SECSID_NULL; + x = dst->xfrm; + if (x == NULL || !selinux_authorizable_xfrm(x)) + return SECSID_NULL; + + return x->security->ctx_sid; +} + +/* + * LSM hook implementation that checks and/or returns the xfrm sid for the + * incoming packet. + */ + +int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall) +{ + if (skb == NULL) { + *sid = SECSID_NULL; + return 0; + } + return selinux_xfrm_skb_sid_ingress(skb, sid, ckall); +} + +int selinux_xfrm_skb_sid(struct sk_buff *skb, u32 *sid) +{ + int rc; + + rc = selinux_xfrm_skb_sid_ingress(skb, sid, 0); + if (rc == 0 && *sid == SECSID_NULL) + *sid = selinux_xfrm_skb_sid_egress(skb); + + return rc; +} + /* * Security blob allocation for xfrm_policy and xfrm_state * CTX does not have a meaningful value on input diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index b5d5a7596c1..8e469162093 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -1846,6 +1846,8 @@ static int wait_for_avail(struct snd_pcm_substream *substream, case SNDRV_PCM_STATE_DISCONNECTED: err = -EBADFD; goto _endloop; + case SNDRV_PCM_STATE_PAUSED: + continue; } if (!tout) { snd_printd("%s write error (DMA or IRQ trouble?)\n", diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c index a32caa72bd7..8b5afc1d2e6 100644 --- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c @@ -406,10 +406,10 @@ static int wm8731_set_dai_fmt(struct snd_soc_dai *codec_dai, iface |= 0x0001; break; case SND_SOC_DAIFMT_DSP_A: - iface |= 0x0003; + iface |= 0x0013; break; case SND_SOC_DAIFMT_DSP_B: - iface |= 0x0013; + iface |= 0x0003; break; default: return -EINVAL; diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index 4e190b5950b..c93e360b670 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c @@ -1456,7 +1456,7 @@ static int wm8904_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_DSP_B: - aif1 |= WM8904_AIF_LRCLK_INV; + aif1 |= 0x3 | WM8904_AIF_LRCLK_INV; case SND_SOC_DAIFMT_DSP_A: aif1 |= 0x3; break; diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c index 9d242351e6e..d5ab3351c2b 100644 --- a/sound/soc/codecs/wm8990.c +++ b/sound/soc/codecs/wm8990.c @@ -1265,6 +1265,8 @@ static int wm8990_set_bias_level(struct snd_soc_codec *codec, /* disable POBCTRL, SOFT_ST and BUFDCOPEN */ snd_soc_write(codec, WM8990_ANTIPOP2, 0x0); + + codec->cache_sync = 1; break; } diff --git a/tools/power/cpupower/utils/cpupower-set.c b/tools/power/cpupower/utils/cpupower-set.c index dc4de376211..bcf1d2f0b79 100644 --- a/tools/power/cpupower/utils/cpupower-set.c +++ b/tools/power/cpupower/utils/cpupower-set.c @@ -18,9 +18,9 @@ #include "helpers/bitmask.h" static struct option set_opts[] = { - { .name = "perf-bias", .has_arg = optional_argument, .flag = NULL, .val = 'b'}, - { .name = "sched-mc", .has_arg = optional_argument, .flag = NULL, .val = 'm'}, - { .name = "sched-smt", .has_arg = optional_argument, .flag = NULL, .val = 's'}, + { .name = "perf-bias", .has_arg = required_argument, .flag = NULL, .val = 'b'}, + { .name = "sched-mc", .has_arg = required_argument, .flag = NULL, .val = 'm'}, + { .name = "sched-smt", .has_arg = required_argument, .flag = NULL, .val = 's'}, { }, }; diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 91a0a2f8cbc..bc5ed141238 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -1668,6 +1668,9 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, u32 id) int r; struct kvm_vcpu *vcpu, *v; + if (id >= KVM_MAX_VCPUS) + return -EINVAL; + vcpu = kvm_arch_vcpu_create(kvm, id); if (IS_ERR(vcpu)) return PTR_ERR(vcpu); From 1578e9375ce47f1d477d778e0fd550eaa59b4277 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Thu, 16 Jan 2014 19:47:21 +0100 Subject: [PATCH 152/215] ARM: mm: implement LoUIS API for cache maintenance ops ARM v7 architecture introduced the concept of cache levels and related control registers. New processors like A7 and A15 embed an L2 unified cache controller that becomes part of the cache level hierarchy. Some operations in the kernel like cpu_suspend and __cpu_disable do not require a flush of the entire cache hierarchy to DRAM but just the cache levels belonging to the Level of Unification Inner Shareable (LoUIS), which in most of ARM v7 systems correspond to L1. The current cache flushing API used in cpu_suspend and __cpu_disable, flush_cache_all(), ends up flushing the whole cache hierarchy since for v7 it cleans and invalidates all cache levels up to Level of Coherency (LoC) which cripples system performance when used in hot paths like hotplug and cpuidle. Therefore a new kernel cache maintenance API must be added to cope with latest ARM system requirements. This patch adds flush_cache_louis() to the ARM kernel cache maintenance API. This function cleans and invalidates all data cache levels up to the Level of Unification Inner Shareable (LoUIS) and invalidates the instruction cache for processors that support it (> v7). This patch also creates an alias of the cache LoUIS function to flush_kern_all for all processor versions prior to v7, so that the current cache flushing behaviour is unchanged for those processors. v7 cache maintenance code implements a cache LoUIS function that cleans and invalidates the D-cache up to LoUIS and invalidates the I-cache, according to the new API. Reviewed-by: Santosh Shilimkar Signed-off-by: Lorenzo Pieralisi --- arch/arm/include/asm/cacheflush.h | 15 +++++++++++++ arch/arm/include/asm/glue-cache.h | 1 + arch/arm/mm/cache-fa.S | 3 +++ arch/arm/mm/cache-v3.S | 3 +++ arch/arm/mm/cache-v4.S | 3 +++ arch/arm/mm/cache-v4wb.S | 3 +++ arch/arm/mm/cache-v4wt.S | 3 +++ arch/arm/mm/cache-v6.S | 3 +++ arch/arm/mm/cache-v7.S | 36 +++++++++++++++++++++++++++++++ arch/arm/mm/proc-arm1020.S | 3 +++ arch/arm/mm/proc-arm1020e.S | 3 +++ arch/arm/mm/proc-arm1022.S | 3 +++ arch/arm/mm/proc-arm1026.S | 3 +++ arch/arm/mm/proc-arm920.S | 3 +++ arch/arm/mm/proc-arm922.S | 3 +++ arch/arm/mm/proc-arm925.S | 3 +++ arch/arm/mm/proc-arm926.S | 3 +++ arch/arm/mm/proc-arm940.S | 3 +++ arch/arm/mm/proc-arm946.S | 3 +++ arch/arm/mm/proc-feroceon.S | 3 +++ arch/arm/mm/proc-macros.S | 1 + arch/arm/mm/proc-mohawk.S | 3 +++ arch/arm/mm/proc-xsc3.S | 3 +++ arch/arm/mm/proc-xscale.S | 3 +++ 24 files changed, 113 insertions(+) diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h index 28b52a7a578..8d23fac2bb0 100644 --- a/arch/arm/include/asm/cacheflush.h +++ b/arch/arm/include/asm/cacheflush.h @@ -50,6 +50,13 @@ * * Unconditionally clean and invalidate the entire cache. * + * flush_kern_louis() + * + * Flush data cache levels up to the level of unification + * inner shareable and invalidate the I-cache. + * Only needed from v7 onwards, falls back to flush_cache_all() + * for all other processor versions. + * * flush_user_all() * * Clean and invalidate all user space cache entries @@ -113,6 +120,7 @@ struct cpu_cache_fns { void (*flush_icache_all)(void); void (*flush_kern_all)(void); + void (*flush_kern_louis)(void); void (*flush_user_all)(void); void (*flush_user_range)(unsigned long, unsigned long, unsigned int); @@ -137,6 +145,7 @@ extern struct cpu_cache_fns cpu_cache; #define __cpuc_flush_icache_all cpu_cache.flush_icache_all #define __cpuc_flush_kern_all cpu_cache.flush_kern_all +#define __cpuc_flush_kern_louis cpu_cache.flush_kern_louis #define __cpuc_flush_user_all cpu_cache.flush_user_all #define __cpuc_flush_user_range cpu_cache.flush_user_range #define __cpuc_coherent_kern_range cpu_cache.coherent_kern_range @@ -159,6 +168,7 @@ extern struct cpu_cache_fns cpu_cache; extern void __cpuc_flush_icache_all(void); extern void __cpuc_flush_kern_all(void); +extern void __cpuc_flush_kern_louis(void); extern void __cpuc_flush_user_all(void); extern void __cpuc_flush_user_range(unsigned long, unsigned long, unsigned int); extern void __cpuc_coherent_kern_range(unsigned long, unsigned long); @@ -226,6 +236,11 @@ static inline void __flush_icache_all(void) __flush_icache_preferred(); } +/* + * Flush caches up to Level of Unification Inner Shareable + */ +#define flush_cache_louis() __cpuc_flush_kern_louis() + #define flush_cache_all() __cpuc_flush_kern_all() static inline void vivt_flush_cache_mm(struct mm_struct *mm) diff --git a/arch/arm/include/asm/glue-cache.h b/arch/arm/include/asm/glue-cache.h index 7e30874377e..2d6a7de87a8 100644 --- a/arch/arm/include/asm/glue-cache.h +++ b/arch/arm/include/asm/glue-cache.h @@ -132,6 +132,7 @@ #ifndef MULTI_CACHE #define __cpuc_flush_icache_all __glue(_CACHE,_flush_icache_all) #define __cpuc_flush_kern_all __glue(_CACHE,_flush_kern_cache_all) +#define __cpuc_flush_kern_louis __glue(_CACHE,_flush_kern_cache_louis) #define __cpuc_flush_user_all __glue(_CACHE,_flush_user_cache_all) #define __cpuc_flush_user_range __glue(_CACHE,_flush_user_cache_range) #define __cpuc_coherent_kern_range __glue(_CACHE,_coherent_kern_range) diff --git a/arch/arm/mm/cache-fa.S b/arch/arm/mm/cache-fa.S index 07201637109..e505befe51b 100644 --- a/arch/arm/mm/cache-fa.S +++ b/arch/arm/mm/cache-fa.S @@ -240,6 +240,9 @@ ENTRY(fa_dma_unmap_area) mov pc, lr ENDPROC(fa_dma_unmap_area) + .globl fa_flush_kern_cache_louis + .equ fa_flush_kern_cache_louis, fa_flush_kern_cache_all + __INITDATA @ define struct cpu_cache_fns (see and proc-macros.S) diff --git a/arch/arm/mm/cache-v3.S b/arch/arm/mm/cache-v3.S index c2301f22610..d99c00c54ee 100644 --- a/arch/arm/mm/cache-v3.S +++ b/arch/arm/mm/cache-v3.S @@ -127,6 +127,9 @@ ENTRY(v3_dma_map_area) ENDPROC(v3_dma_unmap_area) ENDPROC(v3_dma_map_area) + .globl v3_flush_kern_cache_louis + .equ v3_flush_kern_cache_louis, v3_flush_kern_cache_all + __INITDATA @ define struct cpu_cache_fns (see and proc-macros.S) diff --git a/arch/arm/mm/cache-v4.S b/arch/arm/mm/cache-v4.S index fd9bb7addc8..548b892a79a 100644 --- a/arch/arm/mm/cache-v4.S +++ b/arch/arm/mm/cache-v4.S @@ -139,6 +139,9 @@ ENTRY(v4_dma_map_area) ENDPROC(v4_dma_unmap_area) ENDPROC(v4_dma_map_area) + .globl v4_flush_kern_cache_louis + .equ v4_flush_kern_cache_louis, v4_flush_kern_cache_all + __INITDATA @ define struct cpu_cache_fns (see and proc-macros.S) diff --git a/arch/arm/mm/cache-v4wb.S b/arch/arm/mm/cache-v4wb.S index 4f2c14151cc..63b7e4952fd 100644 --- a/arch/arm/mm/cache-v4wb.S +++ b/arch/arm/mm/cache-v4wb.S @@ -251,6 +251,9 @@ ENTRY(v4wb_dma_unmap_area) mov pc, lr ENDPROC(v4wb_dma_unmap_area) + .globl v4wb_flush_kern_cache_louis + .equ v4wb_flush_kern_cache_louis, v4wb_flush_kern_cache_all + __INITDATA @ define struct cpu_cache_fns (see and proc-macros.S) diff --git a/arch/arm/mm/cache-v4wt.S b/arch/arm/mm/cache-v4wt.S index 4d7b467631c..198d424b320 100644 --- a/arch/arm/mm/cache-v4wt.S +++ b/arch/arm/mm/cache-v4wt.S @@ -195,6 +195,9 @@ ENTRY(v4wt_dma_map_area) ENDPROC(v4wt_dma_unmap_area) ENDPROC(v4wt_dma_map_area) + .globl v4wt_flush_kern_cache_louis + .equ v4wt_flush_kern_cache_louis, v4wt_flush_kern_cache_all + __INITDATA @ define struct cpu_cache_fns (see and proc-macros.S) diff --git a/arch/arm/mm/cache-v6.S b/arch/arm/mm/cache-v6.S index 2edb6f67f69..6a5674d3021 100644 --- a/arch/arm/mm/cache-v6.S +++ b/arch/arm/mm/cache-v6.S @@ -345,6 +345,9 @@ ENTRY(v6_dma_unmap_area) mov pc, lr ENDPROC(v6_dma_unmap_area) + .globl v6_flush_kern_cache_louis + .equ v6_flush_kern_cache_louis, v6_flush_kern_cache_all + __INITDATA @ define struct cpu_cache_fns (see and proc-macros.S) diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S index 82ab2c5b4ac..7d22db36d27 100644 --- a/arch/arm/mm/cache-v7.S +++ b/arch/arm/mm/cache-v7.S @@ -32,6 +32,24 @@ ENTRY(v7_flush_icache_all) mov pc, lr ENDPROC(v7_flush_icache_all) + /* + * v7_flush_dcache_louis() + * + * Flush the D-cache up to the Level of Unification Inner Shareable + * + * Corrupted registers: r0-r7, r9-r11 (r6 only in Thumb mode) + */ + +ENTRY(v7_flush_dcache_louis) + dmb @ ensure ordering with previous memory accesses + mrc p15, 1, r0, c0, c0, 1 @ read clidr, r0 = clidr + ands r3, r0, #0xe00000 @ extract LoUIS from clidr + mov r3, r3, lsr #20 @ r3 = LoUIS * 2 + moveq pc, lr @ return if level == 0 + mov r10, #0 @ r10 (starting level) = 0 + b loop1 @ start flushing cache levels +ENDPROC(v7_flush_dcache_louis) + /* * v7_flush_dcache_all() * @@ -119,6 +137,24 @@ ENTRY(v7_flush_kern_cache_all) mov pc, lr ENDPROC(v7_flush_kern_cache_all) + /* + * v7_flush_kern_cache_louis(void) + * + * Flush the data cache up to Level of Unification Inner Shareable. + * Invalidate the I-cache to the point of unification. + */ +ENTRY(v7_flush_kern_cache_louis) + ARM( stmfd sp!, {r4-r5, r7, r9-r11, lr} ) + THUMB( stmfd sp!, {r4-r7, r9-r11, lr} ) + bl v7_flush_dcache_louis + mov r0, #0 + ALT_SMP(mcr p15, 0, r0, c7, c1, 0) @ invalidate I-cache inner shareable + ALT_UP(mcr p15, 0, r0, c7, c5, 0) @ I+BTB cache invalidate + ARM( ldmfd sp!, {r4-r5, r7, r9-r11, lr} ) + THUMB( ldmfd sp!, {r4-r7, r9-r11, lr} ) + mov pc, lr +ENDPROC(v7_flush_kern_cache_louis) + /* * v7_flush_cache_all() * diff --git a/arch/arm/mm/proc-arm1020.S b/arch/arm/mm/proc-arm1020.S index 234951345eb..c11e32ef056 100644 --- a/arch/arm/mm/proc-arm1020.S +++ b/arch/arm/mm/proc-arm1020.S @@ -367,6 +367,9 @@ ENTRY(arm1020_dma_unmap_area) mov pc, lr ENDPROC(arm1020_dma_unmap_area) + .globl arm1020_flush_kern_cache_louis + .equ arm1020_flush_kern_cache_louis, arm1020_flush_kern_cache_all + @ define struct cpu_cache_fns (see and proc-macros.S) define_cache_functions arm1020 diff --git a/arch/arm/mm/proc-arm1020e.S b/arch/arm/mm/proc-arm1020e.S index c244b06caac..9624a35cd42 100644 --- a/arch/arm/mm/proc-arm1020e.S +++ b/arch/arm/mm/proc-arm1020e.S @@ -353,6 +353,9 @@ ENTRY(arm1020e_dma_unmap_area) mov pc, lr ENDPROC(arm1020e_dma_unmap_area) + .globl arm1020e_flush_kern_cache_louis + .equ arm1020e_flush_kern_cache_louis, arm1020e_flush_kern_cache_all + @ define struct cpu_cache_fns (see and proc-macros.S) define_cache_functions arm1020e diff --git a/arch/arm/mm/proc-arm1022.S b/arch/arm/mm/proc-arm1022.S index 38fe22efd18..f2b45ee05fc 100644 --- a/arch/arm/mm/proc-arm1022.S +++ b/arch/arm/mm/proc-arm1022.S @@ -342,6 +342,9 @@ ENTRY(arm1022_dma_unmap_area) mov pc, lr ENDPROC(arm1022_dma_unmap_area) + .globl arm1022_flush_kern_cache_louis + .equ arm1022_flush_kern_cache_louis, arm1022_flush_kern_cache_all + @ define struct cpu_cache_fns (see and proc-macros.S) define_cache_functions arm1022 diff --git a/arch/arm/mm/proc-arm1026.S b/arch/arm/mm/proc-arm1026.S index 3eb9c3c26c7..95934d2e0cf 100644 --- a/arch/arm/mm/proc-arm1026.S +++ b/arch/arm/mm/proc-arm1026.S @@ -336,6 +336,9 @@ ENTRY(arm1026_dma_unmap_area) mov pc, lr ENDPROC(arm1026_dma_unmap_area) + .globl arm1026_flush_kern_cache_louis + .equ arm1026_flush_kern_cache_louis, arm1026_flush_kern_cache_all + @ define struct cpu_cache_fns (see and proc-macros.S) define_cache_functions arm1026 diff --git a/arch/arm/mm/proc-arm920.S b/arch/arm/mm/proc-arm920.S index aeeb1265860..1981fad6f13 100644 --- a/arch/arm/mm/proc-arm920.S +++ b/arch/arm/mm/proc-arm920.S @@ -318,6 +318,9 @@ ENTRY(arm920_dma_unmap_area) mov pc, lr ENDPROC(arm920_dma_unmap_area) + .globl arm920_flush_kern_cache_louis + .equ arm920_flush_kern_cache_louis, arm920_flush_kern_cache_all + @ define struct cpu_cache_fns (see and proc-macros.S) define_cache_functions arm920 #endif diff --git a/arch/arm/mm/proc-arm922.S b/arch/arm/mm/proc-arm922.S index 4ec0e074dd5..142bace0a17 100644 --- a/arch/arm/mm/proc-arm922.S +++ b/arch/arm/mm/proc-arm922.S @@ -320,6 +320,9 @@ ENTRY(arm922_dma_unmap_area) mov pc, lr ENDPROC(arm922_dma_unmap_area) + .globl arm922_flush_kern_cache_louis + .equ arm922_flush_kern_cache_louis, arm922_flush_kern_cache_all + @ define struct cpu_cache_fns (see and proc-macros.S) define_cache_functions arm922 #endif diff --git a/arch/arm/mm/proc-arm925.S b/arch/arm/mm/proc-arm925.S index 9dccd9a365b..3028390aea5 100644 --- a/arch/arm/mm/proc-arm925.S +++ b/arch/arm/mm/proc-arm925.S @@ -375,6 +375,9 @@ ENTRY(arm925_dma_unmap_area) mov pc, lr ENDPROC(arm925_dma_unmap_area) + .globl arm925_flush_kern_cache_louis + .equ arm925_flush_kern_cache_louis, arm925_flush_kern_cache_all + @ define struct cpu_cache_fns (see and proc-macros.S) define_cache_functions arm925 diff --git a/arch/arm/mm/proc-arm926.S b/arch/arm/mm/proc-arm926.S index ee29dc46537..305d0adc981 100644 --- a/arch/arm/mm/proc-arm926.S +++ b/arch/arm/mm/proc-arm926.S @@ -338,6 +338,9 @@ ENTRY(arm926_dma_unmap_area) mov pc, lr ENDPROC(arm926_dma_unmap_area) + .globl arm926_flush_kern_cache_louis + .equ arm926_flush_kern_cache_louis, arm926_flush_kern_cache_all + @ define struct cpu_cache_fns (see and proc-macros.S) define_cache_functions arm926 diff --git a/arch/arm/mm/proc-arm940.S b/arch/arm/mm/proc-arm940.S index 9fdc0a17097..e5af9598ad3 100644 --- a/arch/arm/mm/proc-arm940.S +++ b/arch/arm/mm/proc-arm940.S @@ -267,6 +267,9 @@ ENTRY(arm940_dma_unmap_area) mov pc, lr ENDPROC(arm940_dma_unmap_area) + .globl arm940_flush_kern_cache_louis + .equ arm940_flush_kern_cache_louis, arm940_flush_kern_cache_all + @ define struct cpu_cache_fns (see and proc-macros.S) define_cache_functions arm940 diff --git a/arch/arm/mm/proc-arm946.S b/arch/arm/mm/proc-arm946.S index f684cfedcca..3599b379853 100644 --- a/arch/arm/mm/proc-arm946.S +++ b/arch/arm/mm/proc-arm946.S @@ -309,6 +309,9 @@ ENTRY(arm946_dma_unmap_area) mov pc, lr ENDPROC(arm946_dma_unmap_area) + .globl arm946_flush_kern_cache_louis + .equ arm946_flush_kern_cache_louis, arm946_flush_kern_cache_all + @ define struct cpu_cache_fns (see and proc-macros.S) define_cache_functions arm946 diff --git a/arch/arm/mm/proc-feroceon.S b/arch/arm/mm/proc-feroceon.S index ba3c500584a..26a998423dc 100644 --- a/arch/arm/mm/proc-feroceon.S +++ b/arch/arm/mm/proc-feroceon.S @@ -414,6 +414,9 @@ ENTRY(feroceon_dma_unmap_area) mov pc, lr ENDPROC(feroceon_dma_unmap_area) + .globl feroceon_flush_kern_cache_louis + .equ feroceon_flush_kern_cache_louis, feroceon_flush_kern_cache_all + @ define struct cpu_cache_fns (see and proc-macros.S) define_cache_functions feroceon diff --git a/arch/arm/mm/proc-macros.S b/arch/arm/mm/proc-macros.S index 5829bb379b2..2ea177ac399 100644 --- a/arch/arm/mm/proc-macros.S +++ b/arch/arm/mm/proc-macros.S @@ -299,6 +299,7 @@ ENTRY(\name\()_processor_functions) ENTRY(\name\()_cache_fns) .long \name\()_flush_icache_all .long \name\()_flush_kern_cache_all + .long \name\()_flush_kern_cache_louis .long \name\()_flush_user_cache_all .long \name\()_flush_user_cache_range .long \name\()_coherent_kern_range diff --git a/arch/arm/mm/proc-mohawk.S b/arch/arm/mm/proc-mohawk.S index cdfedc5b8ad..224d0f5471a 100644 --- a/arch/arm/mm/proc-mohawk.S +++ b/arch/arm/mm/proc-mohawk.S @@ -302,6 +302,9 @@ ENTRY(mohawk_dma_unmap_area) mov pc, lr ENDPROC(mohawk_dma_unmap_area) + .globl mohawk_flush_kern_cache_louis + .equ mohawk_flush_kern_cache_louis, mohawk_flush_kern_cache_all + @ define struct cpu_cache_fns (see and proc-macros.S) define_cache_functions mohawk diff --git a/arch/arm/mm/proc-xsc3.S b/arch/arm/mm/proc-xsc3.S index a2d1e8646ef..e8efd83b6f2 100644 --- a/arch/arm/mm/proc-xsc3.S +++ b/arch/arm/mm/proc-xsc3.S @@ -337,6 +337,9 @@ ENTRY(xsc3_dma_unmap_area) mov pc, lr ENDPROC(xsc3_dma_unmap_area) + .globl xsc3_flush_kern_cache_louis + .equ xsc3_flush_kern_cache_louis, xsc3_flush_kern_cache_all + @ define struct cpu_cache_fns (see and proc-macros.S) define_cache_functions xsc3 diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S index 98821530ae7..5f0d39d5e09 100644 --- a/arch/arm/mm/proc-xscale.S +++ b/arch/arm/mm/proc-xscale.S @@ -410,6 +410,9 @@ ENTRY(xscale_dma_unmap_area) mov pc, lr ENDPROC(xscale_dma_unmap_area) + .globl xscale_flush_kern_cache_louis + .equ xscale_flush_kern_cache_louis, xscale_flush_kern_cache_all + @ define struct cpu_cache_fns (see and proc-macros.S) define_cache_functions xscale From 3b90d02630a5783aa9b1c082456d4061f34c6f21 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Thu, 16 Jan 2014 19:47:58 +0100 Subject: [PATCH 153/215] ARM: mm: rename jump labels in v7_flush_dcache_all function This patch renames jump labels in v7_flush_dcache_all in order to define a specific flush cache levels entry point. TODO: factor out the level flushing loop if considered worthwhile and define the input registers requirements. Signed-off-by: Lorenzo Pieralisi --- arch/arm/mm/cache-v7.S | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S index 7d22db36d27..202a5721b70 100644 --- a/arch/arm/mm/cache-v7.S +++ b/arch/arm/mm/cache-v7.S @@ -47,7 +47,7 @@ ENTRY(v7_flush_dcache_louis) mov r3, r3, lsr #20 @ r3 = LoUIS * 2 moveq pc, lr @ return if level == 0 mov r10, #0 @ r10 (starting level) = 0 - b loop1 @ start flushing cache levels + b flush_levels @ start flushing cache levels ENDPROC(v7_flush_dcache_louis) /* @@ -66,7 +66,7 @@ ENTRY(v7_flush_dcache_all) mov r3, r3, lsr #23 @ left align loc bit field beq finished @ if loc is 0, then no need to clean mov r10, #0 @ start clean at cache level 0 -loop1: +flush_levels: add r2, r10, r10, lsr #1 @ work out 3x current cache level mov r1, r0, lsr r2 @ extract cache type bits from clidr and r1, r1, #7 @ mask of the bits for current cache only @@ -88,9 +88,9 @@ loop1: clz r5, r4 @ find bit position of way size increment ldr r7, =0x7fff ands r7, r7, r1, lsr #13 @ extract max number of the index size -loop2: +loop1: mov r9, r4 @ create working copy of max way size -loop3: +loop2: ARM( orr r11, r10, r9, lsl r5 ) @ factor way and cache number into r11 THUMB( lsl r6, r9, r5 ) THUMB( orr r11, r10, r6 ) @ factor way and cache number into r11 @@ -99,13 +99,13 @@ loop3: THUMB( orr r11, r11, r6 ) @ factor index number into r11 mcr p15, 0, r11, c7, c14, 2 @ clean & invalidate by set/way subs r9, r9, #1 @ decrement the way - bge loop3 - subs r7, r7, #1 @ decrement the index bge loop2 + subs r7, r7, #1 @ decrement the index + bge loop1 skip: add r10, r10, #2 @ increment cache number cmp r3, r10 - bgt loop1 + bgt flush_levels finished: mov r10, #0 @ swith back to cache level 0 mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr From cb52c0dd65d1c4bdc56401d7b7ab12313ab39783 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Thu, 16 Jan 2014 19:48:28 +0100 Subject: [PATCH 154/215] ARM: kernel: update cpu_suspend code to use cache LoUIS operations In processors like A15/A7 L2 cache is unified and integrated within the processor cache hierarchy, so that it is not considered an outer cache anymore. For processors like A15/A7 flush_cache_all() ends up cleaning all cache levels up to Level of Coherency (LoC) that includes the L2 unified cache. When a single CPU is suspended (CPU idle) a complete L2 clean is not required, so generic cpu_suspend code must clean the data cache using the newly introduced cache LoUIS function. The context and stack pointer (context pointer) are cleaned to main memory using cache area functions that operate on MVA and guarantee that the data is written back to main memory (perform cache cleaning up to the Point of Coherency - PoC) so that the processor can fetch the context when the MMU is off in the cpu_resume code path. outer_cache management remains unchanged. Reviewed-by: Santosh Shilimkar Signed-off-by: Lorenzo Pieralisi --- arch/arm/kernel/suspend.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/arch/arm/kernel/suspend.c b/arch/arm/kernel/suspend.c index 1794cc3b0f1..358bca3a995 100644 --- a/arch/arm/kernel/suspend.c +++ b/arch/arm/kernel/suspend.c @@ -17,6 +17,8 @@ extern void cpu_resume_mmu(void); */ void __cpu_suspend_save(u32 *ptr, u32 ptrsz, u32 sp, u32 *save_ptr) { + u32 *ctx = ptr; + *save_ptr = virt_to_phys(ptr); /* This must correspond to the LDM in cpu_resume() assembly */ @@ -26,7 +28,20 @@ void __cpu_suspend_save(u32 *ptr, u32 ptrsz, u32 sp, u32 *save_ptr) cpu_do_suspend(ptr); - flush_cache_all(); + flush_cache_louis(); + + /* + * flush_cache_louis does not guarantee that + * save_ptr and ptr are cleaned to main memory, + * just up to the Level of Unification Inner Shareable. + * Since the context pointer and context itself + * are to be retrieved with the MMU off that + * data must be cleaned from all cache levels + * to main memory using "area" cache primitives. + */ + __cpuc_flush_dcache_area(ctx, ptrsz); + __cpuc_flush_dcache_area(save_ptr, sizeof(*save_ptr)); + outer_clean_range(*save_ptr, *save_ptr + ptrsz); outer_clean_range(virt_to_phys(save_ptr), virt_to_phys(save_ptr) + sizeof(*save_ptr)); From 3688de12e379ca8c590bd27603629f31d51b387b Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Thu, 16 Jan 2014 19:48:53 +0100 Subject: [PATCH 155/215] ARM: kernel: update __cpu_disable to use cache LoUIS maintenance API When a CPU is hotplugged out caches that reside in its power domain lose their contents and so must be cleaned to the next memory level. Currently, __cpu_disable calls flush_cache_all() that for new generation processor like A15/A7 ends up cleaning and invalidating all cache levels up to Level of Coherency, which includes the unified L2. This ends up being a waste of cycles since the L2 cache contents are not lost on power down. This patch updates __cpu_disable to use the new LoUIS API cache operations. Reviewed-by: Santosh Shilimkar Signed-off-by: Lorenzo Pieralisi --- arch/arm/kernel/smp.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index bf28ac064e7..89929c2773e 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -138,8 +138,11 @@ int __cpu_disable(void) /* * Flush user cache and TLB mappings, and then remove this CPU * from the vm mask set of all processes. + * + * Caches are flushed to the Level of Unification Inner Shareable + * to write-back dirty lines to unified caches shared by all CPUs. */ - flush_cache_all(); + flush_cache_louis(); local_flush_tlb_all(); read_lock(&tasklist_lock); From 6557cc38c8ee32d145c297f88b5508f19cecd3aa Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Thu, 16 Jan 2014 19:49:25 +0100 Subject: [PATCH 156/215] ARM: mm: update __v7_setup() to the new LoUIS cache maintenance API The ARMv7 processor setup function __v7_setup() cleans and invalidates the CPU cache before enabling MMU to start the CPU with a clean CPU local cache. But on ARMv7 architectures like Cortex-[A15/A8], this code will end up flushing the L2 caches(up to level of Coherency) which is undesirable and expensive. The setup functions are used in the CPU hotplug scenario too and hence flushing all cache levels should be avoided. This patch replaces the cache flushing call with the newly introduced v7 dcache LoUIS API where only cache levels up to LoUIS are cleaned and invalidated when a processors executes __v7_setup which is the expected behavior. For processors like A9 and A5 where the L2 cache is an outer one the behavior should be unchanged. Signed-off-by: Santosh Shilimkar Signed-off-by: Lorenzo Pieralisi --- arch/arm/mm/proc-v7.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S index 47dab27f62f..ce4743ead6c 100644 --- a/arch/arm/mm/proc-v7.S +++ b/arch/arm/mm/proc-v7.S @@ -175,7 +175,7 @@ __v7_ca15mp_setup: __v7_setup: adr r12, __v7_setup_stack @ the local stack stmia r12, {r0-r5, r7, r9, r11, lr} - bl v7_flush_dcache_all + bl v7_flush_dcache_louis ldmia r12, {r0-r5, r7, r9, r11, lr} mrc p15, 0, r0, c0, c0, 0 @ read main ID register From 5dce31e05d43a8240f5a227c78ad1f3d4b090477 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Thu, 16 Jan 2014 23:12:38 +0100 Subject: [PATCH 157/215] Update Faux123's color control driver to unlock gamma settings, update defconfig, and restore LGE Kconfig as it doesn't interfere anymore. --- arch/arm/configs/flo_defconfig | 8 +- arch/arm/mach-msm/Kconfig | 6 +- arch/arm/mach-msm/Makefile | 2 +- arch/arm/mach-msm/lge/Kconfig | 14 ++ arch/arm/mach-msm/msm_kcal_ctrl.c | 293 +++++++++++++++++++++++++++++- 5 files changed, 309 insertions(+), 14 deletions(-) diff --git a/arch/arm/configs/flo_defconfig b/arch/arm/configs/flo_defconfig index c8466a2b1c1..be14b6983e6 100644 --- a/arch/arm/configs/flo_defconfig +++ b/arch/arm/configs/flo_defconfig @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/arm 3.4.60 Kernel Configuration +# Linux/arm 3.4.76 Kernel Configuration # CONFIG_ARM=y CONFIG_ARM_HAS_SG_CHAIN=y @@ -390,6 +390,7 @@ CONFIG_BOARD_HEADER_FILE="" # # LGE Specific Patches # +CONFIG_UPDATE_LCDC_LUT=y # CONFIG_LGE_CRASH_HANDLER is not set CONFIG_MACH_ASUSTEK=y @@ -463,8 +464,6 @@ CONFIG_MSM_IPC_ROUTER_SECURITY=y CONFIG_MSM_MPDEC=y CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN=y # CONFIG_MSM_CPU_FREQ_SET_MIN_MAX is not set -# CONFIG_MSM_CPU_FREQ_MAX is not set -# CONFIG_MSM_CPU_FREQ_MIN is not set CONFIG_INTELLI_PLUG=y CONFIG_CPU_VOLTAGE_TABLE=y CONFIG_GPU_VOLTAGE_TABLE=y @@ -558,8 +557,7 @@ CONFIG_MSM_HSIC_SYSMON=y # CONFIG_MSM_HSIC_SYSMON_TEST is not set CONFIG_MSM_CPU_PWRCTL=y CONFIG_FORCE_FAST_CHARGE=y -CONFIG_UPDATE_LCDC_LUT=y -CONFIG_LCD_KCAL=y +CONFIG_LCD_KCAL_STANDALONE=y # # System MMU diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig index 9890b16292c..a219a864aed 100644 --- a/arch/arm/mach-msm/Kconfig +++ b/arch/arm/mach-msm/Kconfig @@ -2661,13 +2661,13 @@ config FORCE_FAST_CHARGE config UPDATE_LCDC_LUT bool "Set initial Qualcomm LCDC lut" - default y + default n help Set initial Qualcomm LCDC Look Up Table. -config LCD_KCAL +config LCD_KCAL_STANDALONE tristate "MSM generic LCDC Calibration" - default y + default n help Enable MSM generic LCDC temperature Calibration. diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile index 34cda636653..71105f75dde 100644 --- a/arch/arm/mach-msm/Makefile +++ b/arch/arm/mach-msm/Makefile @@ -400,4 +400,4 @@ obj-$(CONFIG_DEBUG_FS) += msm_cpr-debug.o endif obj-$(CONFIG_MSM_CPU_PWRCTL) += msm_cpu_pwrctl.o - +obj-$(CONFIG_LCD_KCAL_STANDALONE) += msm_kcal_ctrl.o diff --git a/arch/arm/mach-msm/lge/Kconfig b/arch/arm/mach-msm/lge/Kconfig index 908c370c576..30ce6bf7c6c 100644 --- a/arch/arm/mach-msm/lge/Kconfig +++ b/arch/arm/mach-msm/lge/Kconfig @@ -15,6 +15,20 @@ config LGE_QFPROM_INTERFACE help LGE QFPROM DRIVER. +config UPDATE_LCDC_LUT + bool "Set initial Qualcomm LCDC lut" + default n + depends on MACH_LGE + help + Set initial Qualcomm LCDC Look Up Table. + +config LCD_KCAL + bool "Interface to calibrate LCD color temperature" + default n + depends on MACH_LGE && UPDATE_LCDC_LUT + help + Interface to calibrate LCD color temperature + config EARJACK_DEBUGGER bool "Earjack UART debugger support" depends on MACH_APQ8064_MAKO diff --git a/arch/arm/mach-msm/msm_kcal_ctrl.c b/arch/arm/mach-msm/msm_kcal_ctrl.c index 06fcf88399e..6e1b657f305 100644 --- a/arch/arm/mach-msm/msm_kcal_ctrl.c +++ b/arch/arm/mach-msm/msm_kcal_ctrl.c @@ -22,6 +22,7 @@ #include #include #include +#include #include "../../../drivers/video/msm/mdp.h" @@ -41,11 +42,12 @@ struct kcal_platform_data { int (*refresh_display) (void); }; +static bool lut_updated = false; static struct kcal_platform_data *kcal_ctrl_pdata; static int last_status_kcal_ctrl; /* pixel order : RBG */ -static unsigned int lcd_color_preset_lut[256] = { +static unsigned int lcd_rgb_linear_lut[256] = { /* default linear qlut */ 0x00000000, 0x00010101, 0x00020202, 0x00030303, 0x00040404, 0x00050505, 0x00060606, 0x00070707, @@ -113,6 +115,243 @@ static unsigned int lcd_color_preset_lut[256] = { 0x00fcfcfc, 0x00fdfdfd, 0x00fefefe, 0x00ffffff }; +/* pixel order : RBG */ +static unsigned int lcd_rgb_working_lut[256] = { + /* default linear qlut */ + 0x00000000, 0x00010101, 0x00020202, 0x00030303, + 0x00040404, 0x00050505, 0x00060606, 0x00070707, + 0x00080808, 0x00090909, 0x000a0a0a, 0x000b0b0b, + 0x000c0c0c, 0x000d0d0d, 0x000e0e0e, 0x000f0f0f, + 0x00101010, 0x00111111, 0x00121212, 0x00131313, + 0x00141414, 0x00151515, 0x00161616, 0x00171717, + 0x00181818, 0x00191919, 0x001a1a1a, 0x001b1b1b, + 0x001c1c1c, 0x001d1d1d, 0x001e1e1e, 0x001f1f1f, + 0x00202020, 0x00212121, 0x00222222, 0x00232323, + 0x00242424, 0x00252525, 0x00262626, 0x00272727, + 0x00282828, 0x00292929, 0x002a2a2a, 0x002b2b2b, + 0x002c2c2c, 0x002d2d2d, 0x002e2e2e, 0x002f2f2f, + 0x00303030, 0x00313131, 0x00323232, 0x00333333, + 0x00343434, 0x00353535, 0x00363636, 0x00373737, + 0x00383838, 0x00393939, 0x003a3a3a, 0x003b3b3b, + 0x003c3c3c, 0x003d3d3d, 0x003e3e3e, 0x003f3f3f, + 0x00404040, 0x00414141, 0x00424242, 0x00434343, + 0x00444444, 0x00454545, 0x00464646, 0x00474747, + 0x00484848, 0x00494949, 0x004a4a4a, 0x004b4b4b, + 0x004c4c4c, 0x004d4d4d, 0x004e4e4e, 0x004f4f4f, + 0x00505050, 0x00515151, 0x00525252, 0x00535353, + 0x00545454, 0x00555555, 0x00565656, 0x00575757, + 0x00585858, 0x00595959, 0x005a5a5a, 0x005b5b5b, + 0x005c5c5c, 0x005d5d5d, 0x005e5e5e, 0x005f5f5f, + 0x00606060, 0x00616161, 0x00626262, 0x00636363, + 0x00646464, 0x00656565, 0x00666666, 0x00676767, + 0x00686868, 0x00696969, 0x006a6a6a, 0x006b6b6b, + 0x006c6c6c, 0x006d6d6d, 0x006e6e6e, 0x006f6f6f, + 0x00707070, 0x00717171, 0x00727272, 0x00737373, + 0x00747474, 0x00757575, 0x00767676, 0x00777777, + 0x00787878, 0x00797979, 0x007a7a7a, 0x007b7b7b, + 0x007c7c7c, 0x007d7d7d, 0x007e7e7e, 0x007f7f7f, + 0x00808080, 0x00818181, 0x00828282, 0x00838383, + 0x00848484, 0x00858585, 0x00868686, 0x00878787, + 0x00888888, 0x00898989, 0x008a8a8a, 0x008b8b8b, + 0x008c8c8c, 0x008d8d8d, 0x008e8e8e, 0x008f8f8f, + 0x00909090, 0x00919191, 0x00929292, 0x00939393, + 0x00949494, 0x00959595, 0x00969696, 0x00979797, + 0x00989898, 0x00999999, 0x009a9a9a, 0x009b9b9b, + 0x009c9c9c, 0x009d9d9d, 0x009e9e9e, 0x009f9f9f, + 0x00a0a0a0, 0x00a1a1a1, 0x00a2a2a2, 0x00a3a3a3, + 0x00a4a4a4, 0x00a5a5a5, 0x00a6a6a6, 0x00a7a7a7, + 0x00a8a8a8, 0x00a9a9a9, 0x00aaaaaa, 0x00ababab, + 0x00acacac, 0x00adadad, 0x00aeaeae, 0x00afafaf, + 0x00b0b0b0, 0x00b1b1b1, 0x00b2b2b2, 0x00b3b3b3, + 0x00b4b4b4, 0x00b5b5b5, 0x00b6b6b6, 0x00b7b7b7, + 0x00b8b8b8, 0x00b9b9b9, 0x00bababa, 0x00bbbbbb, + 0x00bcbcbc, 0x00bdbdbd, 0x00bebebe, 0x00bfbfbf, + 0x00c0c0c0, 0x00c1c1c1, 0x00c2c2c2, 0x00c3c3c3, + 0x00c4c4c4, 0x00c5c5c5, 0x00c6c6c6, 0x00c7c7c7, + 0x00c8c8c8, 0x00c9c9c9, 0x00cacaca, 0x00cbcbcb, + 0x00cccccc, 0x00cdcdcd, 0x00cecece, 0x00cfcfcf, + 0x00d0d0d0, 0x00d1d1d1, 0x00d2d2d2, 0x00d3d3d3, + 0x00d4d4d4, 0x00d5d5d5, 0x00d6d6d6, 0x00d7d7d7, + 0x00d8d8d8, 0x00d9d9d9, 0x00dadada, 0x00dbdbdb, + 0x00dcdcdc, 0x00dddddd, 0x00dedede, 0x00dfdfdf, + 0x00e0e0e0, 0x00e1e1e1, 0x00e2e2e2, 0x00e3e3e3, + 0x00e4e4e4, 0x00e5e5e5, 0x00e6e6e6, 0x00e7e7e7, + 0x00e8e8e8, 0x00e9e9e9, 0x00eaeaea, 0x00ebebeb, + 0x00ececec, 0x00ededed, 0x00eeeeee, 0x00efefef, + 0x00f0f0f0, 0x00f1f1f1, 0x00f2f2f2, 0x00f3f3f3, + 0x00f4f4f4, 0x00f5f5f5, 0x00f6f6f6, 0x00f7f7f7, + 0x00f8f8f8, 0x00f9f9f9, 0x00fafafa, 0x00fbfbfb, + 0x00fcfcfc, 0x00fdfdfd, 0x00fefefe, 0x00ffffff +}; + +/* pixel order : sRBG */ +//static unsigned int lcd_srgb_preset_lut[256] = { + /* default linear qlut */ +/* + 0x00000000, 0x00141414, 0x001c1c1c, 0x00212121, + 0x00262626, 0x002a2a2a, 0x002e2e2e, 0x00313131, + 0x00343434, 0x00373737, 0x003a3a3a, 0x003d3d3d, + 0x003f3f3f, 0x00414141, 0x00444444, 0x00464646, + 0x00484848, 0x004a4a4a, 0x004c4c4c, 0x004e4e4e, + 0x00505050, 0x00515151, 0x00535353, 0x00555555, + 0x00575757, 0x00585858, 0x005a5a5a, 0x005b5b5b, + 0x005d5d5d, 0x005e5e5e, 0x00606060, 0x00616161, + 0x00636363, 0x00646464, 0x00666666, 0x00676767, + 0x00686868, 0x006a6a6a, 0x006b6b6b, 0x006c6c6c, + 0x006d6d6d, 0x006f6f6f, 0x00707070, 0x00717171, + 0x00727272, 0x00737373, 0x00757575, 0x00767676, + 0x00777777, 0x00787878, 0x00797979, 0x007a7a7a, + 0x007b7b7b, 0x007c7c7c, 0x007d7d7d, 0x007e7e7e, + 0x00808080, 0x00818181, 0x00828282, 0x00838383, + 0x00848484, 0x00858585, 0x00868686, 0x00878787, + 0x00888888, 0x00888888, 0x00898989, 0x008a8a8a, + 0x008b8b8b, 0x008c8c8c, 0x008d8d8d, 0x008e8e8e, + 0x008f8f8f, 0x00909090, 0x00919191, 0x00929292, + 0x00939393, 0x00939393, 0x00949494, 0x00959595, + 0x00969696, 0x00979797, 0x00989898, 0x00999999, + 0x00999999, 0x009a9a9a, 0x009b9b9b, 0x009c9c9c, + 0x009d9d9d, 0x009e9e9e, 0x009e9e9e, 0x009f9f9f, + 0x00a0a0a0, 0x00a1a1a1, 0x00a2a2a2, 0x00a2a2a2, + 0x00a3a3a3, 0x00a4a4a4, 0x00a5a5a5, 0x00a5a5a5, + 0x00a6a6a6, 0x00a7a7a7, 0x00a8a8a8, 0x00a8a8a8, + 0x00a9a9a9, 0x00aaaaaa, 0x00ababab, 0x00ababab, + 0x00acacac, 0x00adadad, 0x00aeaeae, 0x00aeaeae, + 0x00afafaf, 0x00b0b0b0, 0x00b0b0b0, 0x00b1b1b1, + 0x00b2b2b2, 0x00b2b2b2, 0x00b3b3b3, 0x00b4b4b4, + 0x00b5b5b5, 0x00b5b5b5, 0x00b6b6b6, 0x00b7b7b7, + 0x00b7b7b7, 0x00b8b8b8, 0x00b9b9b9, 0x00b9b9b9, + 0x00bababa, 0x00bbbbbb, 0x00bbbbbb, 0x00bcbcbc, + 0x00bdbdbd, 0x00bdbdbd, 0x00bebebe, 0x00bebebe, + 0x00bfbfbf, 0x00c0c0c0, 0x00c0c0c0, 0x00c1c1c1, + 0x00c2c2c2, 0x00c2c2c2, 0x00c3c3c3, 0x00c4c4c4, + 0x00c4c4c4, 0x00c5c5c5, 0x00c5c5c5, 0x00c6c6c6, + 0x00c7c7c7, 0x00c7c7c7, 0x00c8c8c8, 0x00c8c8c8, + 0x00c9c9c9, 0x00cacaca, 0x00cacaca, 0x00cbcbcb, + 0x00cbcbcb, 0x00cccccc, 0x00cdcdcd, 0x00cdcdcd, + 0x00cecece, 0x00cecece, 0x00cfcfcf, 0x00d0d0d0, + 0x00d0d0d0, 0x00d1d1d1, 0x00d1d1d1, 0x00d2d2d2, + 0x00d2d2d2, 0x00d3d3d3, 0x00d4d4d4, 0x00d4d4d4, + 0x00d5d5d5, 0x00d5d5d5, 0x00d6d6d6, 0x00d6d6d6, + 0x00d7d7d7, 0x00d8d8d8, 0x00d8d8d8, 0x00d9d9d9, + 0x00d9d9d9, 0x00dadada, 0x00dadada, 0x00dbdbdb, + 0x00dbdbdb, 0x00dcdcdc, 0x00dcdcdc, 0x00dddddd, + 0x00dedede, 0x00dedede, 0x00dfdfdf, 0x00dfdfdf, + 0x00e0e0e0, 0x00e0e0e0, 0x00e1e1e1, 0x00e1e1e1, + 0x00e2e2e2, 0x00e2e2e2, 0x00e3e3e3, 0x00e3e3e3, + 0x00e4e4e4, 0x00e4e4e4, 0x00e5e5e5, 0x00e5e5e5, + 0x00e6e6e6, 0x00e6e6e6, 0x00e7e7e7, 0x00e7e7e7, + 0x00e8e8e8, 0x00e8e8e8, 0x00e9e9e9, 0x00e9e9e9, + 0x00eaeaea, 0x00eaeaea, 0x00ebebeb, 0x00ebebeb, + 0x00ececec, 0x00ececec, 0x00ededed, 0x00ededed, + 0x00eeeeee, 0x00eeeeee, 0x00efefef, 0x00efefef, + 0x00f0f0f0, 0x00f0f0f0, 0x00f1f1f1, 0x00f1f1f1, + 0x00f2f2f2, 0x00f2f2f2, 0x00f3f3f3, 0x00f3f3f3, + 0x00f4f4f4, 0x00f4f4f4, 0x00f5f5f5, 0x00f5f5f5, + 0x00f6f6f6, 0x00f6f6f6, 0x00f7f7f7, 0x00f7f7f7, + 0x00f8f8f8, 0x00f8f8f8, 0x00f9f9f9, 0x00f9f9f9, + 0x00f9f9f9, 0x00fafafa, 0x00fafafa, 0x00fbfbfb, + 0x00fbfbfb, 0x00fcfcfc, 0x00fcfcfc, 0x00fdfdfd, + 0x00fdfdfd, 0x00fefefe, 0x00fefefe, 0x00ffffff +}; +*/ + +void static resetWorkingLut(void) +{ + memcpy((void *)lcd_rgb_working_lut, (void *)lcd_rgb_linear_lut, + sizeof(lcd_rgb_linear_lut)); +} + +void static updateLUT(unsigned int lut_val, unsigned int color, + unsigned int posn) +{ + int offset, mask; + + if (lut_val > 0xff) + return; + + if (color == 0) { + offset = 16; + mask = 0x0000ffff; + } else if (color == 1) { + offset = 8; + mask = 0x00ff00ff; + } else if (color == 2) { + offset = 0; + mask = 0x00ffff00; + } else + // bad color select! + return; + + lcd_rgb_working_lut[posn] = (lcd_rgb_working_lut[posn] & mask) | + (lut_val << offset); +} + +static ssize_t kgamma_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + int lut, color, posn, key, tmp; + + if (!count) + return -EINVAL; + + sscanf(buf, "%u %u %u %u", &lut, &color, &posn, &key); + + if (lut > 0xff) + return count; + + if (posn > 0xff) + return count; + + if (color > 2) + return count; + + tmp = (lut + color + posn) & 0xff; + if (key == tmp) { + updateLUT(lut, color, posn); + lut_updated = true; + } + return count; +} + +static ssize_t kgamma_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int res = 0; + + if (lut_updated) { + res = sprintf(buf, "OK\n"); + lut_updated = false; + } else + res = sprintf(buf, "NG\n"); + + return res; + +} + +static ssize_t kgamma_reset_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + int reset; + + if (!count) + return -EINVAL; + + sscanf(buf, "%u", &reset); + + if (reset) + resetWorkingLut(); + + return count; +} + +static ssize_t kgamma_reset_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return 0; +} + static struct kcal_data kcal_value = {255, 255, 255}; static int update_lcdc_lut(void) @@ -128,7 +367,7 @@ static int update_lcdc_lut(void) cmap.green = (uint16_t *)&(kcal_value.green); cmap.blue = (uint16_t *)&(kcal_value.blue); - ret = mdp_preset_lut_update_lcdc(&cmap, lcd_color_preset_lut); + ret = mdp_preset_lut_update_lcdc(&cmap, lcd_rgb_working_lut); //if (ret) // pr_err("%s: failed to set lut! %d\n", __func__, ret); @@ -157,18 +396,36 @@ static int kcal_refresh_values(void) return update_lcdc_lut(); } +static bool calc_checksum(unsigned int a, unsigned int b, + unsigned int c, unsigned int d) +{ + unsigned char chksum = 0; + + chksum = ~((a & 0xff) + (b & 0xff) + (c & 0xff)); + + if (chksum == (d & 0xff)) { + return true; + } else { + return false; + } +} + static ssize_t kcal_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int kcal_r = 0; int kcal_g = 0; int kcal_b = 0; + int chksum = 0; if (!count) return -EINVAL; - sscanf(buf, "%d %d %d", &kcal_r, &kcal_g, &kcal_b); - kcal_ctrl_pdata->set_values(kcal_r, kcal_g, kcal_b); + sscanf(buf, "%d %d %d %d", &kcal_r, &kcal_g, &kcal_b, &chksum); + chksum = (chksum & 0x0000ff00) >> 8; + + if (calc_checksum(kcal_r, kcal_g, kcal_b, chksum)) + kcal_ctrl_pdata->set_values(kcal_r, kcal_g, kcal_b); return count; } @@ -221,6 +478,8 @@ static ssize_t kcal_version_show(struct device *dev, KCAL_CTRL_MINOR_VERSION); } +static DEVICE_ATTR(power_reset, 0644, kgamma_reset_show, kgamma_reset_store); +static DEVICE_ATTR(power_line, 0644, kgamma_show, kgamma_store); static DEVICE_ATTR(power_rail, 0644, kcal_show, kcal_store); static DEVICE_ATTR(power_rail_ctrl, 0644, kcal_ctrl_show, kcal_ctrl_store); static DEVICE_ATTR(power_rail_version, 0444, kcal_version_show, NULL); @@ -236,6 +495,12 @@ static int kcal_ctrl_probe(struct platform_device *pdev) return -1; } + rc = device_create_file(&pdev->dev, &dev_attr_power_reset); + if(rc !=0) + return -1; + rc = device_create_file(&pdev->dev, &dev_attr_power_line); + if(rc !=0) + return -1; rc = device_create_file(&pdev->dev, &dev_attr_power_rail); if(rc !=0) return -1; @@ -275,6 +540,23 @@ static struct platform_driver this_driver = { typedef int (*funcPtr)(void); +static void msm_kcal_early_suspend(struct early_suspend *handler) +{ + +} + +static void msm_kcal_late_resume(struct early_suspend *handler) +{ + kcal_ctrl_pdata->refresh_display(); + pr_info("msm kcal late resume update!\n"); +} + +static struct early_suspend msm_kcal_early_suspend_struct_driver = { + .level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN - 20, + .suspend = msm_kcal_early_suspend, + .resume = msm_kcal_late_resume, +}; + int __init kcal_ctrl_init(void) { #if 0 @@ -295,6 +577,8 @@ int __init kcal_ctrl_init(void) platform_add_devices(msm_panel_devices, ARRAY_SIZE(msm_panel_devices)); + register_early_suspend(&msm_kcal_early_suspend_struct_driver); + //pr_info("generic kcal ctrl initialized\n"); //pr_info("generic kcal ctrl version %d.%d\n", // KCAL_CTRL_MAJOR_VERSION, @@ -306,4 +590,3 @@ device_initcall(kcal_ctrl_init); //MODULE_DESCRIPTION("Generic MSM KCAL driver"); MODULE_LICENSE("GPL and additional rights"); - From 5d453fb7b3c1e19a66bc1c093797dae5aa3eb8d2 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Thu, 16 Jan 2014 23:13:53 +0100 Subject: [PATCH 158/215] arch/arm/mach-msm/Kconfig: decouple QCACHE from MSM board selection Signed-off-by: Paul Reioux --- arch/arm/mach-msm/Kconfig | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig index a219a864aed..9ea96d20634 100644 --- a/arch/arm/mach-msm/Kconfig +++ b/arch/arm/mach-msm/Kconfig @@ -34,7 +34,6 @@ config ARCH_MSM7X27 select MULTI_IRQ_HANDLER select MSM_PROC_COMM_REGULATOR select CLEANCACHE - select QCACHE select MSM_PM2 if PM select MSM_RUN_QUEUE_STATS if MSM_SOC_REV_A select DONT_MAP_HOLE_AFTER_MEMBANK0 @@ -168,7 +167,6 @@ config ARCH_MSM8960 select ARCH_SPARSEMEM_ENABLE select ARCH_HAS_HOLES_MEMORYMODEL select CLEANCACHE - select QCACHE select MSM_MULTIMEDIA_USE_ION select MULTI_IRQ_HANDLER select MSM_PM8X60 if PM @@ -234,7 +232,6 @@ config ARCH_APQ8064 select CPU_HAS_L2_PMU select HOLES_IN_ZONE if SPARSEMEM select CLEANCACHE - select QCACHE select MIGHT_HAVE_PCI select ARCH_SUPPORTS_MSI select ARM_HAS_SG_CHAIN From a7c6e3aa984f19ef52f0c051bd8ef68a3a478eed Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Thu, 16 Jan 2014 23:17:21 +0100 Subject: [PATCH 159/215] jiffies conversions: Use compile time constants when possible Date Fri, 04 Jan 2013 13:15:43 -0800 Do the multiplications and divisions at compile time instead of runtime when the converted value is a constant. Make the calculation functions static __always_inline to jiffies.h. Add #defines with __builtin_constant_p to test and use the static inline or the runtime functions as appropriate. Prefix the old exported symbols/functions with __ Signed-off-by: Paul Reioux --- include/linux/jiffies.h | 136 ++++++++++++++++++++++++++++++++++++++-- kernel/time.c | 106 ++++--------------------------- 2 files changed, 144 insertions(+), 98 deletions(-) diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h index 265e2c3cbd1..94c7b4ddbfd 100644 --- a/include/linux/jiffies.h +++ b/include/linux/jiffies.h @@ -293,10 +293,138 @@ extern unsigned long preset_lpj; /* * Convert various time units to each other: */ -extern unsigned int jiffies_to_msecs(const unsigned long j); -extern unsigned int jiffies_to_usecs(const unsigned long j); -extern unsigned long msecs_to_jiffies(const unsigned int m); -extern unsigned long usecs_to_jiffies(const unsigned int u); + +/* + * Avoid unnecessary multiplications/divisions in the + * two most common HZ cases: + */ +static __always_inline unsigned int +__inline_jiffies_to_msecs(const unsigned long j) +{ +#if HZ <= MSEC_PER_SEC && !(MSEC_PER_SEC % HZ) + return (MSEC_PER_SEC / HZ) * j; +#elif HZ > MSEC_PER_SEC && !(HZ % MSEC_PER_SEC) + return (j + (HZ / MSEC_PER_SEC) - 1)/(HZ / MSEC_PER_SEC); +#else +# if BITS_PER_LONG == 32 + return (HZ_TO_MSEC_MUL32 * j) >> HZ_TO_MSEC_SHR32; +# else + return (j * HZ_TO_MSEC_NUM) / HZ_TO_MSEC_DEN; +# endif +#endif +} +extern unsigned int __jiffies_to_msecs(const unsigned long j); + +#define jiffies_to_msecs(x) \ + (__builtin_constant_p(x) ? \ + __inline_jiffies_to_msecs(x) : \ + __jiffies_to_msecs(x)) + +static __always_inline unsigned int +__inline_jiffies_to_usecs(const unsigned long j) +{ +#if HZ <= USEC_PER_SEC && !(USEC_PER_SEC % HZ) + return (USEC_PER_SEC / HZ) * j; +#elif HZ > USEC_PER_SEC && !(HZ % USEC_PER_SEC) + return (j + (HZ / USEC_PER_SEC) - 1)/(HZ / USEC_PER_SEC); +#else +# if BITS_PER_LONG == 32 + return (HZ_TO_USEC_MUL32 * j) >> HZ_TO_USEC_SHR32; +# else + return (j * HZ_TO_USEC_NUM) / HZ_TO_USEC_DEN; +# endif +#endif +} +extern unsigned int __jiffies_to_usecs(const unsigned long j); + +#define jiffies_to_usecs(x) \ + (__builtin_constant_p(x) ? \ + __inline_jiffies_to_usecs(x) : \ + __jiffies_to_usecs(x)) + +/* + * When we convert to jiffies then we interpret incoming values + * the following way: + * + * - negative values mean 'infinite timeout' (MAX_JIFFY_OFFSET) + * + * - 'too large' values [that would result in larger than + * MAX_JIFFY_OFFSET values] mean 'infinite timeout' too. + * + * - all other values are converted to jiffies by either multiplying + * the input value by a factor or dividing it with a factor + * + * We must also be careful about 32-bit overflows. + */ +static __always_inline unsigned long +__inline_msecs_to_jiffies(const unsigned int m) +{ + /* + * Negative value, means infinite timeout: + */ + if ((int)m < 0) + return MAX_JIFFY_OFFSET; + +#if HZ <= MSEC_PER_SEC && !(MSEC_PER_SEC % HZ) + /* + * HZ is equal to or smaller than 1000, and 1000 is a nice + * round multiple of HZ, divide with the factor between them, + * but round upwards: + */ + return (m + (MSEC_PER_SEC / HZ) - 1) / (MSEC_PER_SEC / HZ); +#elif HZ > MSEC_PER_SEC && !(HZ % MSEC_PER_SEC) + /* + * HZ is larger than 1000, and HZ is a nice round multiple of + * 1000 - simply multiply with the factor between them. + * + * But first make sure the multiplication result cannot + * overflow: + */ + if (m > jiffies_to_msecs(MAX_JIFFY_OFFSET)) + return MAX_JIFFY_OFFSET; + + return m * (HZ / MSEC_PER_SEC); +#else + /* + * Generic case - multiply, round and divide. But first + * check that if we are doing a net multiplication, that + * we wouldn't overflow: + */ + if (HZ > MSEC_PER_SEC && m > jiffies_to_msecs(MAX_JIFFY_OFFSET)) + return MAX_JIFFY_OFFSET; + + return (MSEC_TO_HZ_MUL32 * m + MSEC_TO_HZ_ADJ32) + >> MSEC_TO_HZ_SHR32; +#endif +} +extern unsigned long __msecs_to_jiffies(const unsigned int m); + +#define msecs_to_jiffies(x) \ + (__builtin_constant_p(x) ? \ + __inline_msecs_to_jiffies(x) : \ + __msecs_to_jiffies(x)) + +static __always_inline unsigned long +__inline_usecs_to_jiffies(const unsigned int u) +{ + if (u > jiffies_to_usecs(MAX_JIFFY_OFFSET)) + return MAX_JIFFY_OFFSET; +#if HZ <= USEC_PER_SEC && !(USEC_PER_SEC % HZ) + return (u + (USEC_PER_SEC / HZ) - 1) / (USEC_PER_SEC / HZ); +#elif HZ > USEC_PER_SEC && !(HZ % USEC_PER_SEC) + return u * (HZ / USEC_PER_SEC); +#else + return (USEC_TO_HZ_MUL32 * u + USEC_TO_HZ_ADJ32) + >> USEC_TO_HZ_SHR32; +#endif +} +extern unsigned long __usecs_to_jiffies(const unsigned int u); + +#define usecs_to_jiffies(x) \ + (__builtin_constant_p(x) ? \ + __inline_usecs_to_jiffies(x) : \ + __usecs_to_jiffies(x)) + extern unsigned long timespec_to_jiffies(const struct timespec *value); extern void jiffies_to_timespec(const unsigned long jiffies, struct timespec *value); diff --git a/kernel/time.c b/kernel/time.c index ba744cf8069..0016049799e 100644 --- a/kernel/time.c +++ b/kernel/time.c @@ -228,41 +228,18 @@ EXPORT_SYMBOL(current_fs_time); /* * Convert jiffies to milliseconds and back. - * - * Avoid unnecessary multiplications/divisions in the - * two most common HZ cases: */ -inline unsigned int jiffies_to_msecs(const unsigned long j) +unsigned int __jiffies_to_msecs(const unsigned long j) { -#if HZ <= MSEC_PER_SEC && !(MSEC_PER_SEC % HZ) - return (MSEC_PER_SEC / HZ) * j; -#elif HZ > MSEC_PER_SEC && !(HZ % MSEC_PER_SEC) - return (j + (HZ / MSEC_PER_SEC) - 1)/(HZ / MSEC_PER_SEC); -#else -# if BITS_PER_LONG == 32 - return (HZ_TO_MSEC_MUL32 * j) >> HZ_TO_MSEC_SHR32; -# else - return (j * HZ_TO_MSEC_NUM) / HZ_TO_MSEC_DEN; -# endif -#endif + return __inline_jiffies_to_msecs(j); } -EXPORT_SYMBOL(jiffies_to_msecs); +EXPORT_SYMBOL(__jiffies_to_msecs); -inline unsigned int jiffies_to_usecs(const unsigned long j) +unsigned int __jiffies_to_usecs(const unsigned long j) { -#if HZ <= USEC_PER_SEC && !(USEC_PER_SEC % HZ) - return (USEC_PER_SEC / HZ) * j; -#elif HZ > USEC_PER_SEC && !(HZ % USEC_PER_SEC) - return (j + (HZ / USEC_PER_SEC) - 1)/(HZ / USEC_PER_SEC); -#else -# if BITS_PER_LONG == 32 - return (HZ_TO_USEC_MUL32 * j) >> HZ_TO_USEC_SHR32; -# else - return (j * HZ_TO_USEC_NUM) / HZ_TO_USEC_DEN; -# endif -#endif + return __inline_jiffies_to_usecs(j); } -EXPORT_SYMBOL(jiffies_to_usecs); +EXPORT_SYMBOL(__jiffies_to_usecs); /** * timespec_trunc - Truncate timespec to a granularity @@ -411,76 +388,17 @@ struct timeval ns_to_timeval(const s64 nsec) } EXPORT_SYMBOL(ns_to_timeval); -/* - * When we convert to jiffies then we interpret incoming values - * the following way: - * - * - negative values mean 'infinite timeout' (MAX_JIFFY_OFFSET) - * - * - 'too large' values [that would result in larger than - * MAX_JIFFY_OFFSET values] mean 'infinite timeout' too. - * - * - all other values are converted to jiffies by either multiplying - * the input value by a factor or dividing it with a factor - * - * We must also be careful about 32-bit overflows. - */ -unsigned long msecs_to_jiffies(const unsigned int m) +unsigned long __msecs_to_jiffies(const unsigned int m) { - /* - * Negative value, means infinite timeout: - */ - if ((int)m < 0) - return MAX_JIFFY_OFFSET; - -#if HZ <= MSEC_PER_SEC && !(MSEC_PER_SEC % HZ) - /* - * HZ is equal to or smaller than 1000, and 1000 is a nice - * round multiple of HZ, divide with the factor between them, - * but round upwards: - */ - return (m + (MSEC_PER_SEC / HZ) - 1) / (MSEC_PER_SEC / HZ); -#elif HZ > MSEC_PER_SEC && !(HZ % MSEC_PER_SEC) - /* - * HZ is larger than 1000, and HZ is a nice round multiple of - * 1000 - simply multiply with the factor between them. - * - * But first make sure the multiplication result cannot - * overflow: - */ - if (m > jiffies_to_msecs(MAX_JIFFY_OFFSET)) - return MAX_JIFFY_OFFSET; - - return m * (HZ / MSEC_PER_SEC); -#else - /* - * Generic case - multiply, round and divide. But first - * check that if we are doing a net multiplication, that - * we wouldn't overflow: - */ - if (HZ > MSEC_PER_SEC && m > jiffies_to_msecs(MAX_JIFFY_OFFSET)) - return MAX_JIFFY_OFFSET; - - return (MSEC_TO_HZ_MUL32 * m + MSEC_TO_HZ_ADJ32) - >> MSEC_TO_HZ_SHR32; -#endif + return __inline_msecs_to_jiffies(m); } -EXPORT_SYMBOL(msecs_to_jiffies); +EXPORT_SYMBOL(__msecs_to_jiffies); -unsigned long usecs_to_jiffies(const unsigned int u) +unsigned long __usecs_to_jiffies(const unsigned int u) { - if (u > jiffies_to_usecs(MAX_JIFFY_OFFSET)) - return MAX_JIFFY_OFFSET; -#if HZ <= USEC_PER_SEC && !(USEC_PER_SEC % HZ) - return (u + (USEC_PER_SEC / HZ) - 1) / (USEC_PER_SEC / HZ); -#elif HZ > USEC_PER_SEC && !(HZ % USEC_PER_SEC) - return u * (HZ / USEC_PER_SEC); -#else - return (USEC_TO_HZ_MUL32 * u + USEC_TO_HZ_ADJ32) - >> USEC_TO_HZ_SHR32; -#endif + return __inline_usecs_to_jiffies(u); } -EXPORT_SYMBOL(usecs_to_jiffies); +EXPORT_SYMBOL(__usecs_to_jiffies); /* * The TICK_NSEC - 1 rounds up the value to the next resolution. Note From 2599f7b34b9343f813696fded64fd4d4c7f1454a Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Fri, 17 Jan 2014 09:39:56 +0100 Subject: [PATCH 160/215] We don't need this hack anymore --- kernel/workqueue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/workqueue.c b/kernel/workqueue.c index a032953e45e..b537accaee8 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -3570,7 +3570,7 @@ __acquires(&gcwq->lock) } } -static int __devinit workqueue_cpu_callback(struct notifier_block *nfb, +static int workqueue_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { From 488f1221d4940e20fdfe1483fdfa62029fd52491 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 2 Dec 2013 08:51:13 -0800 Subject: [PATCH 161/215] net: do not pretend FRAGLIST support [ Upstream commit 28e24c62ab3062e965ef1b3bcc244d50aee7fa85 ] Few network drivers really supports frag_list : virtual drivers. Some drivers wrongly advertise NETIF_F_FRAGLIST feature. If skb with a frag_list is given to them, packet on the wire will be corrupt. Remove this flag, as core networking stack will make sure to provide packets that can be sent without corruption. Signed-off-by: Eric Dumazet Cc: Thadeu Lima de Souza Cascardo Cc: Anirudha Sarangi Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/net/ethernet/calxeda/xgmac.c | 2 +- drivers/net/ethernet/ibm/ehea/ehea_main.c | 2 +- drivers/net/ethernet/tehuti/tehuti.c | 1 - drivers/net/ethernet/xilinx/ll_temac_main.c | 2 +- drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 2 +- 5 files changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c index 4ebbe6f609d..5699105112d 100644 --- a/drivers/net/ethernet/calxeda/xgmac.c +++ b/drivers/net/ethernet/calxeda/xgmac.c @@ -1776,7 +1776,7 @@ static int xgmac_probe(struct platform_device *pdev) if (device_can_wakeup(priv->device)) priv->wolopts = WAKE_MAGIC; /* Magic Frame as default */ - ndev->hw_features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA; + ndev->hw_features = NETIF_F_SG | NETIF_F_HIGHDMA; if (readl(priv->base + XGMAC_DMA_HW_FEATURE) & DMA_HW_FEAT_TXCOESEL) ndev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM; diff --git a/drivers/net/ethernet/ibm/ehea/ehea_main.c b/drivers/net/ethernet/ibm/ehea/ehea_main.c index f4d2da0db1b..8b3da6eb5bc 100644 --- a/drivers/net/ethernet/ibm/ehea/ehea_main.c +++ b/drivers/net/ethernet/ibm/ehea/ehea_main.c @@ -3029,7 +3029,7 @@ static struct ehea_port *ehea_setup_single_port(struct ehea_adapter *adapter, dev->hw_features = NETIF_F_SG | NETIF_F_TSO | NETIF_F_IP_CSUM | NETIF_F_HW_VLAN_TX | NETIF_F_LRO; - dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_TSO + dev->features = NETIF_F_SG | NETIF_F_TSO | NETIF_F_HIGHDMA | NETIF_F_IP_CSUM | NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER | NETIF_F_RXCSUM; diff --git a/drivers/net/ethernet/tehuti/tehuti.c b/drivers/net/ethernet/tehuti/tehuti.c index ad973ffc9ff..32f0bcd5e30 100644 --- a/drivers/net/ethernet/tehuti/tehuti.c +++ b/drivers/net/ethernet/tehuti/tehuti.c @@ -1995,7 +1995,6 @@ bdx_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ndev->features = NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_TSO | NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER | NETIF_F_RXCSUM - /*| NETIF_F_FRAGLIST */ ; ndev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_TSO | NETIF_F_HW_VLAN_TX; diff --git a/drivers/net/ethernet/xilinx/ll_temac_main.c b/drivers/net/ethernet/xilinx/ll_temac_main.c index 5e5b791f12e..d240c0624d4 100644 --- a/drivers/net/ethernet/xilinx/ll_temac_main.c +++ b/drivers/net/ethernet/xilinx/ll_temac_main.c @@ -1026,7 +1026,7 @@ static int __devinit temac_of_probe(struct platform_device *op) dev_set_drvdata(&op->dev, ndev); SET_NETDEV_DEV(ndev, &op->dev); ndev->flags &= ~IFF_MULTICAST; /* clear multicast */ - ndev->features = NETIF_F_SG | NETIF_F_FRAGLIST; + ndev->features = NETIF_F_SG; ndev->netdev_ops = &temac_netdev_ops; ndev->ethtool_ops = &temac_ethtool_ops; #if 0 diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c index 9c365e192a3..fde716dec19 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c @@ -1494,7 +1494,7 @@ static int __devinit axienet_of_probe(struct platform_device *op) SET_NETDEV_DEV(ndev, &op->dev); ndev->flags &= ~IFF_MULTICAST; /* clear multicast */ - ndev->features = NETIF_F_SG | NETIF_F_FRAGLIST; + ndev->features = NETIF_F_SG; ndev->netdev_ops = &axienet_netdev_ops; ndev->ethtool_ops = &axienet_ethtool_ops; From c7d5aeb788d714a1f2aa3d743bde142b67bd5ad9 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 15 Jan 2014 15:27:19 -0800 Subject: [PATCH 162/215] Linux 3.4.77 - 26 commits squashed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit rds: prevent BUG_ON triggered on congestion update to loopback [ Upstream commit 18fc25c94eadc52a42c025125af24657a93638c0 ] After congestion update on a local connection, when rds_ib_xmit returns less bytes than that are there in the message, rds_send_xmit calls back rds_ib_xmit with an offset that causes BUG_ON(off & RDS_FRAG_SIZE) to trigger. For a 4Kb PAGE_SIZE rds_ib_xmit returns min(8240,4096)=4096 when actually the message contains 8240 bytes. rds_send_xmit thinks there is more to send and calls rds_ib_xmit again with a data offset "off" of 4096-48(rds header) =4048 bytes thus hitting the BUG_ON(off & RDS_FRAG_SIZE) [RDS_FRAG_SIZE=4k]. The commit 6094628bfd94323fc1cea05ec2c6affd98c18f7f "rds: prevent BUG_ON triggering on congestion map updates" introduced this regression. That change was addressing the triggering of a different BUG_ON in rds_send_xmit() on PowerPC architecture with 64Kbytes PAGE_SIZE: BUG_ON(ret != 0 && conn->c_xmit_sg == rm->data.op_nents); This was the sequence it was going through: (rds_ib_xmit) /* Do not send cong updates to IB loopback */ if (conn->c_loopback && rm->m_inc.i_hdr.h_flags & RDS_FLAG_CONG_BITMAP) { rds_cong_map_updated(conn->c_fcong, ~(u64) 0); return sizeof(struct rds_header) + RDS_CONG_MAP_BYTES; } rds_ib_xmit returns 8240 rds_send_xmit: c_xmit_data_off = 0 + 8240 - 48 (rds header accounted only the first time) = 8192 c_xmit_data_off < 65536 (sg->length), so calls rds_ib_xmit again rds_ib_xmit returns 8240 rds_send_xmit: c_xmit_data_off = 8192 + 8240 = 16432, calls rds_ib_xmit again and so on (c_xmit_data_off 24672,32912,41152,49392,57632) rds_ib_xmit returns 8240 On this iteration this sequence causes the BUG_ON in rds_send_xmit: while (ret) { tmp = min_t(int, ret, sg->length - conn->c_xmit_data_off); [tmp = 65536 - 57632 = 7904] conn->c_xmit_data_off += tmp; [c_xmit_data_off = 57632 + 7904 = 65536] ret -= tmp; [ret = 8240 - 7904 = 336] if (conn->c_xmit_data_off == sg->length) { conn->c_xmit_data_off = 0; sg++; conn->c_xmit_sg++; BUG_ON(ret != 0 && conn->c_xmit_sg == rm->data.op_nents); [c_xmit_sg = 1, rm->data.op_nents = 1] What the current fix does: Since the congestion update over loopback is not actually transmitted as a message, all that rds_ib_xmit needs to do is let the caller think the full message has been transmitted and not return partial bytes. It will return 8240 (RDS_CONG_MAP_BYTES+48) when PAGE_SIZE is 4Kb. And 64Kb+48 when page size is 64Kb. Reported-by: Josh Hunt Tested-by: Honggang Li Acked-by: Bang Nguyen Signed-off-by: Venkat Venkatsubra Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman macvtap: Do not double-count received packets [ Upstream commit 006da7b07bc4d3a7ffabad17cf639eec6849c9dc ] Currently macvlan will count received packets after calling each vlans receive handler. Macvtap attempts to count the packet yet again when the user reads the packet from the tap socket. This code doesn't do this consistently either. Remove the counting from macvtap and let only macvlan count received packets. Signed-off-by: Vlad Yasevich Acked-by: Michael S. Tsirkin Acked-by: Jason Wang Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman macvtap: update file current position [ Upstream commit e6ebc7f16ca1434a334647aa56399c546be4e64b ] Signed-off-by: Zhi Yong Wu Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman tun: update file current position [ Upstream commit d0b7da8afa079ffe018ab3e92879b7138977fc8f ] Signed-off-by: Zhi Yong Wu Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman macvtap: signal truncated packets [ Upstream commit ce232ce01d61b184202bb185103d119820e1260c ] macvtap_put_user() never return a value grater than iov length, this in fact bypasses the truncated checking in macvtap_recvmsg(). Fix this by always returning the size of packet plus the possible vlan header to let the trunca checking work. Cc: Vlad Yasevich Cc: Zhi Yong Wu Cc: Michael S. Tsirkin Signed-off-by: Jason Wang Acked-by: Vlad Yasevich Acked-by: Michael S. Tsirkin Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman ipv6: don't count addrconf generated routes against gc limit [ Upstream commit a3300ef4bbb1f1e33ff0400e1e6cf7733d988f4f ] Brett Ciphery reported that new ipv6 addresses failed to get installed because the addrconf generated dsts where counted against the dst gc limit. We don't need to count those routes like we currently don't count administratively added routes. Because the max_addresses check enforces a limit on unbounded address generation first in case someone plays with router advertisments, we are still safe here. Reported-by: Brett Ciphery Signed-off-by: Hannes Frederic Sowa Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman net: drop_monitor: fix the value of maxattr [ Upstream commit d323e92cc3f4edd943610557c9ea1bb4bb5056e8 ] maxattr in genl_family should be used to save the max attribute type, but not the max command type. Drop monitor doesn't support any attributes, so we should leave it as zero. Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman net: unix: allow set_peek_off to fail [ Upstream commit 12663bfc97c8b3fdb292428105dd92d563164050 ] unix_dgram_recvmsg() will hold the readlock of the socket until recv is complete. In the same time, we may try to setsockopt(SO_PEEK_OFF) which will hang until unix_dgram_recvmsg() will complete (which can take a while) without allowing us to break out of it, triggering a hung task spew. Instead, allow set_peek_off to fail, this way userspace will not hang. Signed-off-by: Sasha Levin Acked-by: Pavel Emelyanov Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman tg3: Initialize REG_BASE_ADDR at PCI config offset 120 to 0 [ Upstream commit 388d3335575f4c056dcf7138a30f1454e2145cd8 ] The new tg3 driver leaves REG_BASE_ADDR (PCI config offset 120) uninitialized. From power on reset this register may have garbage in it. The Register Base Address register defines the device local address of a register. The data pointed to by this location is read or written using the Register Data register (PCI config offset 128). When REG_BASE_ADDR has garbage any read or write of Register Data Register (PCI 128) will cause the PCI bus to lock up. The TCO watchdog will fire and bring down the system. Signed-off-by: Nat Gurumoorthy Acked-by: Michael Chan Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman netvsc: don't flush peers notifying work during setting mtu [ Upstream commit 50dc875f2e6e2e04aed3b3033eb0ac99192d6d02 ] There's a possible deadlock if we flush the peers notifying work during setting mtu: [ 22.991149] ====================================================== [ 22.991173] [ INFO: possible circular locking dependency detected ] [ 22.991198] 3.10.0-54.0.1.el7.x86_64.debug #1 Not tainted [ 22.991219] ------------------------------------------------------- [ 22.991243] ip/974 is trying to acquire lock: [ 22.991261] ((&(&net_device_ctx->dwork)->work)){+.+.+.}, at: [] flush_work+0x5/0x2e0 [ 22.991307] but task is already holding lock: [ 22.991330] (rtnl_mutex){+.+.+.}, at: [] rtnetlink_rcv+0x1b/0x40 [ 22.991367] which lock already depends on the new lock. [ 22.991398] the existing dependency chain (in reverse order) is: [ 22.991426] -> #1 (rtnl_mutex){+.+.+.}: [ 22.991449] [] __lock_acquire+0xb19/0x1260 [ 22.991477] [] lock_acquire+0xa2/0x1f0 [ 22.991501] [] mutex_lock_nested+0x89/0x4f0 [ 22.991529] [] rtnl_lock+0x17/0x20 [ 22.991552] [] netdev_notify_peers+0x12/0x30 [ 22.991579] [] netvsc_send_garp+0x22/0x30 [hv_netvsc] [ 22.991610] [] process_one_work+0x211/0x6e0 [ 22.991637] [] worker_thread+0x11b/0x3a0 [ 22.991663] [] kthread+0xed/0x100 [ 22.991686] [] ret_from_fork+0x7c/0xb0 [ 22.991715] -> #0 ((&(&net_device_ctx->dwork)->work)){+.+.+.}: [ 22.991715] [] check_prevs_add+0x967/0x970 [ 22.991715] [] __lock_acquire+0xb19/0x1260 [ 22.991715] [] lock_acquire+0xa2/0x1f0 [ 22.991715] [] flush_work+0x4e/0x2e0 [ 22.991715] [] __cancel_work_timer+0x95/0x130 [ 22.991715] [] cancel_delayed_work_sync+0x13/0x20 [ 22.991715] [] netvsc_change_mtu+0x84/0x200 [hv_netvsc] [ 22.991715] [] dev_set_mtu+0x34/0x80 [ 22.991715] [] do_setlink+0x23a/0xa00 [ 22.991715] [] rtnl_newlink+0x394/0x5e0 [ 22.991715] [] rtnetlink_rcv_msg+0x9c/0x260 [ 22.991715] [] netlink_rcv_skb+0xa9/0xc0 [ 22.991715] [] rtnetlink_rcv+0x2a/0x40 [ 22.991715] [] netlink_unicast+0xdd/0x190 [ 22.991715] [] netlink_sendmsg+0x337/0x750 [ 22.991715] [] sock_sendmsg+0x99/0xd0 [ 22.991715] [] ___sys_sendmsg+0x39e/0x3b0 [ 22.991715] [] __sys_sendmsg+0x42/0x80 [ 22.991715] [] SyS_sendmsg+0x12/0x20 [ 22.991715] [] system_call_fastpath+0x16/0x1b This is because we hold the rtnl_lock() before ndo_change_mtu() and try to flush the work in netvsc_change_mtu(), in the mean time, netdev_notify_peers() may be called from worker and also trying to hold the rtnl_lock. This will lead the flush won't succeed forever. Solve this by not canceling and flushing the work, this is safe because the transmission done by NETDEV_NOTIFY_PEERS was synchronized with the netif_tx_disable() called by netvsc_change_mtu(). Reported-by: Yaju Cao Tested-by: Yaju Cao Cc: K. Y. Srinivasan Cc: Haiyang Zhang Signed-off-by: Jason Wang Acked-by: Haiyang Zhang Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman net: unix: allow bind to fail on mutex lock [ Upstream commit 37ab4fa7844a044dc21fde45e2a0fc2f3c3b6490 ] This is similar to the set_peek_off patch where calling bind while the socket is stuck in unix_dgram_recvmsg() will block and cause a hung task spew after a while. This is also the last place that did a straightforward mutex_lock(), so there shouldn't be any more of these patches. Signed-off-by: Sasha Levin Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman net: inet_diag: zero out uninitialized idiag_{src,dst} fields [ Upstream commit b1aac815c0891fe4a55a6b0b715910142227700f ] Jakub reported while working with nlmon netlink sniffer that parts of the inet_diag_sockid are not initialized when r->idiag_family != AF_INET6. That is, fields of r->id.idiag_src[1 ... 3], r->id.idiag_dst[1 ... 3]. In fact, it seems that we can leak 6 * sizeof(u32) byte of kernel [slab] memory through this. At least, in udp_dump_one(), we allocate a skb in ... rep = nlmsg_new(sizeof(struct inet_diag_msg) + ..., GFP_KERNEL); ... and then pass that to inet_sk_diag_fill() that puts the whole struct inet_diag_msg into the skb, where we only fill out r->id.idiag_src[0], r->id.idiag_dst[0] and leave the rest untouched: r->id.idiag_src[0] = inet->inet_rcv_saddr; r->id.idiag_dst[0] = inet->inet_daddr; struct inet_diag_msg embeds struct inet_diag_sockid that is correctly / fully filled out in IPv6 case, but for IPv4 not. So just zero them out by using plain memset (for this little amount of bytes it's probably not worth the extra check for idiag_family == AF_INET). Similarly, fix also other places where we fill that out. Reported-by: Jakub Zawadzki Signed-off-by: Daniel Borkmann Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman drivers/net/hamradio: Integer overflow in hdlcdrv_ioctl() [ Upstream commit e9db5c21d3646a6454fcd04938dd215ac3ab620a ] The local variable 'bi' comes from userspace. If userspace passed a large number to 'bi.data.calibrate', there would be an integer overflow in the following line: s->hdlctx.calibrate = bi.data.calibrate * s->par.bitrate / 16; Signed-off-by: Wenliang Fan Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman hamradio/yam: fix info leak in ioctl [ Upstream commit 8e3fbf870481eb53b2d3a322d1fc395ad8b367ed ] The yam_ioctl() code fails to initialise the cmd field of the struct yamdrv_ioctl_cfg. Add an explicit memset(0) before filling the structure to avoid the 4-byte info leak. Signed-off-by: Salva Peiró Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman rds: prevent dereference of a NULL device [ Upstream commit c2349758acf1874e4c2b93fe41d072336f1a31d0 ] Binding might result in a NULL device, which is dereferenced causing this BUG: [ 1317.260548] BUG: unable to handle kernel NULL pointer dereference at 000000000000097 4 [ 1317.261847] IP: [] rds_ib_laddr_check+0x82/0x110 [ 1317.263315] PGD 418bcb067 PUD 3ceb21067 PMD 0 [ 1317.263502] Oops: 0000 [#1] PREEMPT SMP DEBUG_PAGEALLOC [ 1317.264179] Dumping ftrace buffer: [ 1317.264774] (ftrace buffer empty) [ 1317.265220] Modules linked in: [ 1317.265824] CPU: 4 PID: 836 Comm: trinity-child46 Tainted: G W 3.13.0-rc4- next-20131218-sasha-00013-g2cebb9b-dirty #4159 [ 1317.267415] task: ffff8803ddf33000 ti: ffff8803cd31a000 task.ti: ffff8803cd31a000 [ 1317.268399] RIP: 0010:[] [] rds_ib_laddr_check+ 0x82/0x110 [ 1317.269670] RSP: 0000:ffff8803cd31bdf8 EFLAGS: 00010246 [ 1317.270230] RAX: 0000000000000000 RBX: ffff88020b0dd388 RCX: 0000000000000000 [ 1317.270230] RDX: ffffffff8439822e RSI: 00000000000c000a RDI: 0000000000000286 [ 1317.270230] RBP: ffff8803cd31be38 R08: 0000000000000000 R09: 0000000000000000 [ 1317.270230] R10: 0000000000000000 R11: 0000000000000001 R12: 0000000000000000 [ 1317.270230] R13: 0000000054086700 R14: 0000000000a25de0 R15: 0000000000000031 [ 1317.270230] FS: 00007ff40251d700(0000) GS:ffff88022e200000(0000) knlGS:000000000000 0000 [ 1317.270230] CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b [ 1317.270230] CR2: 0000000000000974 CR3: 00000003cd478000 CR4: 00000000000006e0 [ 1317.270230] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 1317.270230] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000090602 [ 1317.270230] Stack: [ 1317.270230] 0000000054086700 5408670000a25de0 5408670000000002 0000000000000000 [ 1317.270230] ffffffff84223542 00000000ea54c767 0000000000000000 ffffffff86d26160 [ 1317.270230] ffff8803cd31be68 ffffffff84223556 ffff8803cd31beb8 ffff8800c6765280 [ 1317.270230] Call Trace: [ 1317.270230] [] ? rds_trans_get_preferred+0x42/0xa0 [ 1317.270230] [] rds_trans_get_preferred+0x56/0xa0 [ 1317.270230] [] rds_bind+0x73/0xf0 [ 1317.270230] [] SYSC_bind+0x92/0xf0 [ 1317.270230] [] ? context_tracking_user_exit+0xb8/0x1d0 [ 1317.270230] [] ? trace_hardirqs_on+0xd/0x10 [ 1317.270230] [] ? syscall_trace_enter+0x32/0x290 [ 1317.270230] [] SyS_bind+0xe/0x10 [ 1317.270230] [] tracesys+0xdd/0xe2 [ 1317.270230] Code: 00 8b 45 cc 48 8d 75 d0 48 c7 45 d8 00 00 00 00 66 c7 45 d0 02 00 89 45 d4 48 89 df e8 78 49 76 ff 41 89 c4 85 c0 75 0c 48 8b 03 <80> b8 74 09 00 00 01 7 4 06 41 bc 9d ff ff ff f6 05 2a b6 c2 02 [ 1317.270230] RIP [] rds_ib_laddr_check+0x82/0x110 [ 1317.270230] RSP [ 1317.270230] CR2: 0000000000000974 Signed-off-by: Sasha Levin Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman net: rose: restore old recvmsg behavior [ Upstream commit f81152e35001e91997ec74a7b4e040e6ab0acccf ] recvmsg handler in net/rose/af_rose.c performs size-check ->msg_namelen. After commit f3d3342602f8bcbf37d7c46641cb9bca7618eb1c (net: rework recvmsg handler msg_name and msg_namelen logic), we now always take the else branch due to namelen being initialized to 0. Digging in netdev-vger-cvs git repo shows that msg_namelen was initialized with a fixed-size since at least 1995, so the else branch was never taken. Compile tested only. Signed-off-by: Florian Westphal Acked-by: Hannes Frederic Sowa Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman vlan: Fix header ops passthru when doing TX VLAN offload. [ Upstream commit 2205369a314e12fcec4781cc73ac9c08fc2b47de ] When the vlan code detects that the real device can do TX VLAN offloads in hardware, it tries to arrange for the real device's header_ops to be invoked directly. But it does so illegally, by simply hooking the real device's header_ops up to the VLAN device. This doesn't work because we will end up invoking a set of header_ops routines which expect a device type which matches the real device, but will see a VLAN device instead. Fix this by providing a pass-thru set of header_ops which will arrange to pass the proper real device instead. To facilitate this add a dev_rebuild_header(). There are implementations which provide a ->cache and ->create but not a ->rebuild (f.e. PLIP). So we need a helper function just like dev_hard_header() to avoid crashes. Use this helper in the one existing place where the header_ops->rebuild was being invoked, the neighbour code. With lots of help from Florian Westphal. Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman net: llc: fix use after free in llc_ui_recvmsg [ Upstream commit 4d231b76eef6c4a6bd9c96769e191517765942cb ] While commit 30a584d944fb fixes datagram interface in LLC, a use after free bug has been introduced for SOCK_STREAM sockets that do not make use of MSG_PEEK. The flow is as follow ... if (!(flags & MSG_PEEK)) { ... sk_eat_skb(sk, skb, false); ... } ... if (used + offset < skb->len) continue; ... where sk_eat_skb() calls __kfree_skb(). Therefore, cache original length and work on skb_len to check partial reads. Fixes: 30a584d944fb ("[LLX]: SOCK_DGRAM interface fixes") Signed-off-by: Daniel Borkmann Cc: Stephen Hemminger Cc: Arnaldo Carvalho de Melo Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman bridge: use spin_lock_bh() in br_multicast_set_hash_max [ Upstream commit fe0d692bbc645786bce1a98439e548ae619269f5 ] br_multicast_set_hash_max() is called from process context in net/bridge/br_sysfs_br.c by the sysfs store_hash_max() function. br_multicast_set_hash_max() calls spin_lock(&br->multicast_lock), which can deadlock the CPU if a softirq that also tries to take the same lock interrupts br_multicast_set_hash_max() while the lock is held . This can happen quite easily when any of the bridge multicast timers expire, which try to take the same lock. The fix here is to use spin_lock_bh(), preventing other softirqs from executing on this CPU. Steps to reproduce: 1. Create a bridge with several interfaces (I used 4). 2. Set the "multicast query interval" to a low number, like 2. 3. Enable the bridge as a multicast querier. 4. Repeatedly set the bridge hash_max parameter via sysfs. # brctl addbr br0 # brctl addif br0 eth1 eth2 eth3 eth4 # brctl setmcqi br0 2 # brctl setmcquerier br0 1 # while true ; do echo 4096 > /sys/class/net/br0/bridge/hash_max; done Signed-off-by: Curt Brune Signed-off-by: Scott Feldman Signed-off-by: David S. Miller Signed-off-by: Greg Kroah-Hartman ARM: shmobile: mackerel: Fix coherent DMA mask commit b6328a6b7ba57fc84c38248f6f0e387e1170f1a8 upstream. Commit 4dcfa60071b3d23f0181f27d8519f12e37cefbb9 ("ARM: DMA-API: better handing of DMA masks for coherent allocations") added an additional check to the coherent DMA mask that results in an error when the mask is larger than what dma_addr_t can address. Set the LCDC coherent DMA mask to DMA_BIT_MASK(32) instead of ~0 to fix the problem. Signed-off-by: Laurent Pinchart Signed-off-by: Simon Horman Signed-off-by: Greg Kroah-Hartman x86, fpu, amd: Clear exceptions in AMD FXSAVE workaround commit 26bef1318adc1b3a530ecc807ef99346db2aa8b0 upstream. Before we do an EMMS in the AMD FXSAVE information leak workaround we need to clear any pending exceptions, otherwise we trap with a floating-point exception inside this code. Reported-by: halfdog Tested-by: Borislav Petkov Link: http://lkml.kernel.org/r/CA%2B55aFxQnY_PCG_n4=0w-VG=YLXL-yr7oMxyy0WU2gCBAf3ydg@mail.gmail.com Signed-off-by: H. Peter Anvin Signed-off-by: Greg Kroah-Hartman sched: Fix race on toggling cfs_bandwidth_used commit 1ee14e6c8cddeeb8a490d7b54cd9016e4bb900b4 upstream. When we transition cfs_bandwidth_used to false, any currently throttled groups will incorrectly return false from cfs_rq_throttled. While tg_set_cfs_bandwidth will unthrottle them eventually, currently running code (including at least dequeue_task_fair and distribute_cfs_runtime) will cause errors. Fix this by turning off cfs_bandwidth_used only after unthrottling all cfs_rqs. Tested: toggle bandwidth back and forth on a loaded cgroup. Caused crashes in minutes without the patch, hasn't crashed with it. Signed-off-by: Ben Segall Signed-off-by: Peter Zijlstra Cc: pjt@google.com Link: http://lkml.kernel.org/r/20131016181611.22647.80365.stgit@sword-of-the-dawn.mtv.corp.google.com Signed-off-by: Ingo Molnar Cc: Chris J Arges Signed-off-by: Greg Kroah-Hartman sched: Fix cfs_bandwidth misuse of hrtimer_expires_remaining commit db06e78cc13d70f10877e0557becc88ab3ad2be8 upstream. hrtimer_expires_remaining does not take internal hrtimer locks and thus must be guarded against concurrent __hrtimer_start_range_ns (but returning HRTIMER_RESTART is safe). Use cfs_b->lock to make it safe. Signed-off-by: Ben Segall Signed-off-by: Peter Zijlstra Cc: pjt@google.com Link: http://lkml.kernel.org/r/20131016181617.22647.73829.stgit@sword-of-the-dawn.mtv.corp.google.com Signed-off-by: Ingo Molnar Cc: Chris J Arges Signed-off-by: Greg Kroah-Hartman sched: Fix hrtimer_cancel()/rq->lock deadlock commit 927b54fccbf04207ec92f669dce6806848cbec7d upstream. __start_cfs_bandwidth calls hrtimer_cancel while holding rq->lock, waiting for the hrtimer to finish. However, if sched_cfs_period_timer runs for another loop iteration, the hrtimer can attempt to take rq->lock, resulting in deadlock. Fix this by ensuring that cfs_b->timer_active is cleared only if the _latest_ call to do_sched_cfs_period_timer is returning as idle. Then __start_cfs_bandwidth can just call hrtimer_try_to_cancel and wait for that to succeed or timer_active == 1. Signed-off-by: Ben Segall Signed-off-by: Peter Zijlstra Cc: pjt@google.com Link: http://lkml.kernel.org/r/20131016181622.22647.16643.stgit@sword-of-the-dawn.mtv.corp.google.com Signed-off-by: Ingo Molnar Cc: Chris J Arges Signed-off-by: Greg Kroah-Hartman sched: Guarantee new group-entities always have weight commit 0ac9b1c21874d2490331233b3242085f8151e166 upstream. Currently, group entity load-weights are initialized to zero. This admits some races with respect to the first time they are re-weighted in earlty use. ( Let g[x] denote the se for "g" on cpu "x". ) Suppose that we have root->a and that a enters a throttled state, immediately followed by a[0]->t1 (the only task running on cpu[0]) blocking: put_prev_task(group_cfs_rq(a[0]), t1) put_prev_entity(..., t1) check_cfs_rq_runtime(group_cfs_rq(a[0])) throttle_cfs_rq(group_cfs_rq(a[0])) Then, before unthrottling occurs, let a[0]->b[0]->t2 wake for the first time: enqueue_task_fair(rq[0], t2) enqueue_entity(group_cfs_rq(b[0]), t2) enqueue_entity_load_avg(group_cfs_rq(b[0]), t2) account_entity_enqueue(group_cfs_ra(b[0]), t2) update_cfs_shares(group_cfs_rq(b[0])) < skipped because b is part of a throttled hierarchy > enqueue_entity(group_cfs_rq(a[0]), b[0]) ... We now have b[0] enqueued, yet group_cfs_rq(a[0])->load.weight == 0 which violates invariants in several code-paths. Eliminate the possibility of this by initializing group entity weight. Signed-off-by: Paul Turner Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/20131016181627.22647.47543.stgit@sword-of-the-dawn.mtv.corp.google.com Signed-off-by: Ingo Molnar Cc: Chris J Arges Signed-off-by: Greg Kroah-Hartman --- Makefile | 2 +- arch/arm/mach-shmobile/board-mackerel.c | 4 +-- arch/x86/include/asm/fpu-internal.h | 13 +++---- drivers/net/ethernet/broadcom/tg3.c | 3 ++ drivers/net/hamradio/hdlcdrv.c | 2 ++ drivers/net/hamradio/yam.c | 1 + drivers/net/hyperv/netvsc_drv.c | 1 - drivers/net/macvtap.c | 20 +++++------ drivers/net/tun.c | 2 ++ include/linux/net.h | 2 +- include/linux/netdevice.h | 9 +++++ kernel/sched/core.c | 9 ++++- kernel/sched/fair.c | 48 +++++++++++++++++-------- kernel/sched/sched.h | 3 +- net/8021q/vlan_dev.c | 19 +++++++++- net/bridge/br_multicast.c | 4 +-- net/core/drop_monitor.c | 1 - net/core/sock.c | 2 +- net/ipv4/inet_diag.c | 16 +++++++++ net/ipv6/route.c | 8 ++--- net/llc/af_llc.c | 5 +-- net/rds/ib.c | 3 +- net/rds/ib_send.c | 5 ++- net/rose/af_rose.c | 16 +++------ net/unix/af_unix.c | 16 ++++++--- 25 files changed, 141 insertions(+), 73 deletions(-) diff --git a/Makefile b/Makefile index 3252d1a09b4..0577a3e6aea 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 4 -SUBLEVEL = 76 +SUBLEVEL = 77 EXTRAVERSION = NAME = Saber-toothed Squirrel diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c index 8c6202bb6ae..9c19b45db36 100644 --- a/arch/arm/mach-shmobile/board-mackerel.c +++ b/arch/arm/mach-shmobile/board-mackerel.c @@ -422,7 +422,7 @@ static struct platform_device lcdc_device = { .resource = lcdc_resources, .dev = { .platform_data = &lcdc_info, - .coherent_dma_mask = ~0, + .coherent_dma_mask = DMA_BIT_MASK(32), }, }; @@ -498,7 +498,7 @@ static struct platform_device hdmi_lcdc_device = { .id = 1, .dev = { .platform_data = &hdmi_lcdc_info, - .coherent_dma_mask = ~0, + .coherent_dma_mask = DMA_BIT_MASK(32), }, }; diff --git a/arch/x86/include/asm/fpu-internal.h b/arch/x86/include/asm/fpu-internal.h index 92e05b6c84f..a65708f2f01 100644 --- a/arch/x86/include/asm/fpu-internal.h +++ b/arch/x86/include/asm/fpu-internal.h @@ -266,12 +266,13 @@ static inline int restore_fpu_checking(struct task_struct *tsk) /* AMD K7/K8 CPUs don't save/restore FDP/FIP/FOP unless an exception is pending. Clear the x87 state here by setting it to fixed values. "m" is a random variable that should be in L1 */ - alternative_input( - ASM_NOP8 ASM_NOP2, - "emms\n\t" /* clear stack tags */ - "fildl %P[addr]", /* set F?P to defined value */ - X86_FEATURE_FXSAVE_LEAK, - [addr] "m" (tsk->thread.fpu.has_fpu)); + if (unlikely(static_cpu_has(X86_FEATURE_FXSAVE_LEAK))) { + asm volatile( + "fnclex\n\t" + "emms\n\t" + "fildl %P[addr]" /* set F?P to defined value */ + : : [addr] "m" (tsk->thread.fpu.has_fpu)); + } return fpu_restore_checking(&tsk->thread.fpu); } diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index 3551ad82ba8..650286be8da 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -14671,6 +14671,9 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) /* Clear this out for sanity. */ tw32(TG3PCI_MEM_WIN_BASE_ADDR, 0); + /* Clear TG3PCI_REG_BASE_ADDR to prevent hangs. */ + tw32(TG3PCI_REG_BASE_ADDR, 0); + pci_read_config_dword(tp->pdev, TG3PCI_PCISTATE, &pci_state_reg); if ((pci_state_reg & PCISTATE_CONV_PCI_MODE) == 0 && diff --git a/drivers/net/hamradio/hdlcdrv.c b/drivers/net/hamradio/hdlcdrv.c index a4a3516b6bb..3b3a7e07bbf 100644 --- a/drivers/net/hamradio/hdlcdrv.c +++ b/drivers/net/hamradio/hdlcdrv.c @@ -571,6 +571,8 @@ static int hdlcdrv_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) case HDLCDRVCTL_CALIBRATE: if(!capable(CAP_SYS_RAWIO)) return -EPERM; + if (bi.data.calibrate > INT_MAX / s->par.bitrate) + return -EINVAL; s->hdlctx.calibrate = bi.data.calibrate * s->par.bitrate / 16; return 0; diff --git a/drivers/net/hamradio/yam.c b/drivers/net/hamradio/yam.c index 5a6412ecce7..d8faeb628aa 100644 --- a/drivers/net/hamradio/yam.c +++ b/drivers/net/hamradio/yam.c @@ -1058,6 +1058,7 @@ static int yam_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) break; case SIOCYAMGCFG: + memset(&yi, 0, sizeof(yi)); yi.cfg.mask = 0xffffffff; yi.cfg.iobase = yp->iobase; yi.cfg.irq = yp->irq; diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index 2d59138db7f..a6ed3828413 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -321,7 +321,6 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu) return -EINVAL; nvdev->start_remove = true; - cancel_delayed_work_sync(&ndevctx->dwork); cancel_work_sync(&ndevctx->work); netif_tx_disable(ndev); rndis_filter_device_remove(hdev); diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index 77ce8b2bee6..f5b9de48bb8 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -797,11 +797,10 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q, const struct sk_buff *skb, const struct iovec *iv, int len) { - struct macvlan_dev *vlan; int ret; int vnet_hdr_len = 0; int vlan_offset = 0; - int copied; + int copied, total; if (q->flags & IFF_VNET_HDR) { struct virtio_net_hdr vnet_hdr; @@ -816,7 +815,8 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q, if (memcpy_toiovecend(iv, (void *)&vnet_hdr, 0, sizeof(vnet_hdr))) return -EFAULT; } - copied = vnet_hdr_len; + total = copied = vnet_hdr_len; + total += skb->len; if (!vlan_tx_tag_present(skb)) len = min_t(int, skb->len, len); @@ -831,6 +831,7 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q, vlan_offset = offsetof(struct vlan_ethhdr, h_vlan_proto); len = min_t(int, skb->len + VLAN_HLEN, len); + total += VLAN_HLEN; copy = min_t(int, vlan_offset, len); ret = skb_copy_datagram_const_iovec(skb, 0, iv, copied, copy); @@ -848,16 +849,9 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q, } ret = skb_copy_datagram_const_iovec(skb, vlan_offset, iv, copied, len); - copied += len; done: - rcu_read_lock_bh(); - vlan = rcu_dereference_bh(q->vlan); - if (vlan) - macvlan_count_rx(vlan, copied - vnet_hdr_len, ret == 0, 0); - rcu_read_unlock_bh(); - - return ret ? ret : copied; + return ret ? ret : total; } static ssize_t macvtap_do_read(struct macvtap_queue *q, struct kiocb *iocb, @@ -911,7 +905,9 @@ static ssize_t macvtap_aio_read(struct kiocb *iocb, const struct iovec *iv, } ret = macvtap_do_read(q, iocb, iv, len, file->f_flags & O_NONBLOCK); - ret = min_t(ssize_t, ret, len); /* XXX copied from tun.c. Why? */ + ret = min_t(ssize_t, ret, len); + if (ret > 0) + iocb->ki_pos = ret; out: return ret; } diff --git a/drivers/net/tun.c b/drivers/net/tun.c index b463b84dcd6..19e451b2f9a 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -903,6 +903,8 @@ static ssize_t tun_chr_aio_read(struct kiocb *iocb, const struct iovec *iv, ret = tun_do_read(tun, iocb, iv, len, file->f_flags & O_NONBLOCK); ret = min_t(ssize_t, ret, len); + if (ret > 0) + iocb->ki_pos = ret; out: tun_put(tun); return ret; diff --git a/include/linux/net.h b/include/linux/net.h index 45232814fc0..ff8097592f1 100644 --- a/include/linux/net.h +++ b/include/linux/net.h @@ -215,7 +215,7 @@ struct proto_ops { int offset, size_t size, int flags); ssize_t (*splice_read)(struct socket *sock, loff_t *ppos, struct pipe_inode_info *pipe, size_t len, unsigned int flags); - void (*set_peek_off)(struct sock *sk, int val); + int (*set_peek_off)(struct sock *sk, int val); }; #define DECLARE_SOCKADDR(type, dst, src) \ diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index dc6c6878700..5b465010f10 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -1702,6 +1702,15 @@ static inline int dev_parse_header(const struct sk_buff *skb, return dev->header_ops->parse(skb, haddr); } +static inline int dev_rebuild_header(struct sk_buff *skb) +{ + const struct net_device *dev = skb->dev; + + if (!dev->header_ops || !dev->header_ops->rebuild) + return 0; + return dev->header_ops->rebuild(skb); +} + typedef int gifconf_func_t(struct net_device * dev, char __user * bufptr, int len); extern int register_gifconf(unsigned int family, gifconf_func_t * gifconf); static inline int unregister_gifconf(unsigned int family) diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 478875b1bc9..0f0180f8b89 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -8032,7 +8032,12 @@ static int tg_set_cfs_bandwidth(struct task_group *tg, u64 period, u64 quota) runtime_enabled = quota != RUNTIME_INF; runtime_was_enabled = cfs_b->quota != RUNTIME_INF; - account_cfs_bandwidth_used(runtime_enabled, runtime_was_enabled); + /* + * If we need to toggle cfs_bandwidth_used, off->on must occur + * before making related changes, and on->off must occur afterwards + */ + if (runtime_enabled && !runtime_was_enabled) + cfs_bandwidth_usage_inc(); raw_spin_lock_irq(&cfs_b->lock); cfs_b->period = ns_to_ktime(period); cfs_b->quota = quota; @@ -8058,6 +8063,8 @@ static int tg_set_cfs_bandwidth(struct task_group *tg, u64 period, u64 quota) unthrottle_cfs_rq(cfs_rq); raw_spin_unlock_irq(&rq->lock); } + if (runtime_was_enabled && !runtime_enabled) + cfs_bandwidth_usage_dec(); out_unlock: mutex_unlock(&cfs_constraints_mutex); diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 6294062e831..8d8cff9d26c 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -1399,13 +1399,14 @@ static inline bool cfs_bandwidth_used(void) return static_key_false(&__cfs_bandwidth_used); } -void account_cfs_bandwidth_used(int enabled, int was_enabled) +void cfs_bandwidth_usage_inc(void) { - /* only need to count groups transitioning between enabled/!enabled */ - if (enabled && !was_enabled) - static_key_slow_inc(&__cfs_bandwidth_used); - else if (!enabled && was_enabled) - static_key_slow_dec(&__cfs_bandwidth_used); + static_key_slow_inc(&__cfs_bandwidth_used); +} + +void cfs_bandwidth_usage_dec(void) +{ + static_key_slow_dec(&__cfs_bandwidth_used); } #else /* HAVE_JUMP_LABEL */ static bool cfs_bandwidth_used(void) @@ -1413,7 +1414,8 @@ static bool cfs_bandwidth_used(void) return true; } -void account_cfs_bandwidth_used(int enabled, int was_enabled) {} +void cfs_bandwidth_usage_inc(void) {} +void cfs_bandwidth_usage_dec(void) {} #endif /* HAVE_JUMP_LABEL */ /* @@ -1775,6 +1777,13 @@ static int do_sched_cfs_period_timer(struct cfs_bandwidth *cfs_b, int overrun) if (idle) goto out_unlock; + /* + * if we have relooped after returning idle once, we need to update our + * status as actually running, so that other cpus doing + * __start_cfs_bandwidth will stop trying to cancel us. + */ + cfs_b->timer_active = 1; + __refill_cfs_bandwidth_runtime(cfs_b); if (!throttled) { @@ -1835,7 +1844,13 @@ static const u64 min_bandwidth_expiration = 2 * NSEC_PER_MSEC; /* how long we wait to gather additional slack before distributing */ static const u64 cfs_bandwidth_slack_period = 5 * NSEC_PER_MSEC; -/* are we near the end of the current quota period? */ +/* + * Are we near the end of the current quota period? + * + * Requires cfs_b->lock for hrtimer_expires_remaining to be safe against the + * hrtimer base being cleared by __hrtimer_start_range_ns. In the case of + * migrate_hrtimers, base is never cleared, so we are fine. + */ static int runtime_refresh_within(struct cfs_bandwidth *cfs_b, u64 min_expire) { struct hrtimer *refresh_timer = &cfs_b->period_timer; @@ -1911,10 +1926,12 @@ static void do_sched_cfs_slack_timer(struct cfs_bandwidth *cfs_b) u64 expires; /* confirm we're still not at a refresh boundary */ - if (runtime_refresh_within(cfs_b, min_bandwidth_expiration)) + raw_spin_lock(&cfs_b->lock); + if (runtime_refresh_within(cfs_b, min_bandwidth_expiration)) { + raw_spin_unlock(&cfs_b->lock); return; + } - raw_spin_lock(&cfs_b->lock); if (cfs_b->quota != RUNTIME_INF && cfs_b->runtime > slice) { runtime = cfs_b->runtime; cfs_b->runtime = 0; @@ -2039,11 +2056,11 @@ void __start_cfs_bandwidth(struct cfs_bandwidth *cfs_b) * (timer_active==0 becomes visible before the hrtimer call-back * terminates). In either case we ensure that it's re-programmed */ - while (unlikely(hrtimer_active(&cfs_b->period_timer))) { + while (unlikely(hrtimer_active(&cfs_b->period_timer)) && + hrtimer_try_to_cancel(&cfs_b->period_timer) < 0) { + /* bounce the lock to allow do_sched_cfs_period_timer to run */ raw_spin_unlock(&cfs_b->lock); - /* ensure cfs_b->lock is available while we wait */ - hrtimer_cancel(&cfs_b->period_timer); - + cpu_relax(); raw_spin_lock(&cfs_b->lock); /* if someone else restarted the timer then we're done */ if (cfs_b->timer_active) @@ -5515,7 +5532,8 @@ void init_tg_cfs_entry(struct task_group *tg, struct cfs_rq *cfs_rq, se->cfs_rq = parent->my_q; se->my_q = cfs_rq; - update_load_set(&se->load, 0); + /* guarantee group entities always have weight */ + update_load_set(&se->load, NICE_0_LOAD); se->parent = parent; } diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index 762f52a0397..97e12247945 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -1192,7 +1192,8 @@ extern void init_cfs_rq(struct cfs_rq *cfs_rq); extern void init_rt_rq(struct rt_rq *rt_rq, struct rq *rq); extern void unthrottle_offline_cfs_rqs(struct rq *rq); -extern void account_cfs_bandwidth_used(int enabled, int was_enabled); +extern void cfs_bandwidth_usage_inc(void); +extern void cfs_bandwidth_usage_dec(void); #ifdef CONFIG_NO_HZ enum rq_nohz_flag_bits { diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 8f453927cc5..c2029f73212 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c @@ -525,6 +525,23 @@ static const struct header_ops vlan_header_ops = { .parse = eth_header_parse, }; +static int vlan_passthru_hard_header(struct sk_buff *skb, struct net_device *dev, + unsigned short type, + const void *daddr, const void *saddr, + unsigned int len) +{ + struct vlan_dev_priv *vlan = vlan_dev_priv(dev); + struct net_device *real_dev = vlan->real_dev; + + return dev_hard_header(skb, real_dev, type, daddr, saddr, len); +} + +static const struct header_ops vlan_passthru_header_ops = { + .create = vlan_passthru_hard_header, + .rebuild = dev_rebuild_header, + .parse = eth_header_parse, +}; + static const struct net_device_ops vlan_netdev_ops; static int vlan_dev_init(struct net_device *dev) @@ -564,7 +581,7 @@ static int vlan_dev_init(struct net_device *dev) dev->needed_headroom = real_dev->needed_headroom; if (real_dev->features & NETIF_F_HW_VLAN_TX) { - dev->header_ops = real_dev->header_ops; + dev->header_ops = &vlan_passthru_header_ops; dev->hard_header_len = real_dev->hard_header_len; } else { dev->header_ops = &vlan_header_ops; diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index ca670d96bae..cef202a9411 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -1744,7 +1744,7 @@ int br_multicast_set_hash_max(struct net_bridge *br, unsigned long val) u32 old; struct net_bridge_mdb_htable *mdb; - spin_lock(&br->multicast_lock); + spin_lock_bh(&br->multicast_lock); if (!netif_running(br->dev)) goto unlock; @@ -1776,7 +1776,7 @@ int br_multicast_set_hash_max(struct net_bridge *br, unsigned long val) } unlock: - spin_unlock(&br->multicast_lock); + spin_unlock_bh(&br->multicast_lock); return err; } diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c index b856f87e63d..1d9a52929ba 100644 --- a/net/core/drop_monitor.c +++ b/net/core/drop_monitor.c @@ -61,7 +61,6 @@ static struct genl_family net_drop_monitor_family = { .hdrsize = 0, .name = "NET_DM", .version = 2, - .maxattr = NET_DM_CMD_MAX, }; static DEFINE_PER_CPU(struct per_cpu_dm_data, dm_cpu_data); diff --git a/net/core/sock.c b/net/core/sock.c index 561eb57f590..832cf043a8f 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -795,7 +795,7 @@ int sock_setsockopt(struct socket *sock, int level, int optname, case SO_PEEK_OFF: if (sock->ops->set_peek_off) - sock->ops->set_peek_off(sk, val); + ret = sock->ops->set_peek_off(sk, val); else ret = -EOPNOTSUPP; break; diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index d7b862ad4be..5fcc8df3f17 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c @@ -110,6 +110,10 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk, r->id.idiag_sport = inet->inet_sport; r->id.idiag_dport = inet->inet_dport; + + memset(&r->id.idiag_src, 0, sizeof(r->id.idiag_src)); + memset(&r->id.idiag_dst, 0, sizeof(r->id.idiag_dst)); + r->id.idiag_src[0] = inet->inet_rcv_saddr; r->id.idiag_dst[0] = inet->inet_daddr; @@ -227,12 +231,19 @@ static int inet_twsk_diag_fill(struct inet_timewait_sock *tw, r->idiag_family = tw->tw_family; r->idiag_retrans = 0; + r->id.idiag_if = tw->tw_bound_dev_if; sock_diag_save_cookie(tw, r->id.idiag_cookie); + r->id.idiag_sport = tw->tw_sport; r->id.idiag_dport = tw->tw_dport; + + memset(&r->id.idiag_src, 0, sizeof(r->id.idiag_src)); + memset(&r->id.idiag_dst, 0, sizeof(r->id.idiag_dst)); + r->id.idiag_src[0] = tw->tw_rcv_saddr; r->id.idiag_dst[0] = tw->tw_daddr; + r->idiag_state = tw->tw_substate; r->idiag_timer = 3; r->idiag_expires = DIV_ROUND_UP(tmo * 1000, HZ); @@ -714,8 +725,13 @@ static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk, r->id.idiag_sport = inet->inet_sport; r->id.idiag_dport = ireq->rmt_port; + + memset(&r->id.idiag_src, 0, sizeof(r->id.idiag_src)); + memset(&r->id.idiag_dst, 0, sizeof(r->id.idiag_dst)); + r->id.idiag_src[0] = ireq->loc_addr; r->id.idiag_dst[0] = ireq->rmt_addr; + r->idiag_expires = jiffies_to_msecs(tmo); r->idiag_rqueue = 0; r->idiag_wqueue = 0; diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 6ac8bc29b43..335b16fccb9 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -2114,15 +2114,11 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, { struct net *net = dev_net(idev->dev); struct rt6_info *rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, - net->loopback_dev, 0); + net->loopback_dev, DST_NOCOUNT); int err; - if (!rt) { - if (net_ratelimit()) - pr_warning("IPv6: Maximum number of routes reached," - " consider increasing route/max_size.\n"); + if (!rt) return ERR_PTR(-ENOMEM); - } in6_dev_hold(idev); diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index df08d7779e1..1c2dc50c9b4 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c @@ -716,7 +716,7 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock, unsigned long cpu_flags; size_t copied = 0; u32 peek_seq = 0; - u32 *seq; + u32 *seq, skb_len; unsigned long used; int target; /* Read at least this many bytes */ long timeo; @@ -814,6 +814,7 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock, } continue; found_ok_skb: + skb_len = skb->len; /* Ok so how much can we use? */ used = skb->len - offset; if (len < used) @@ -846,7 +847,7 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock, } /* Partial read */ - if (used + offset < skb->len) + if (used + offset < skb_len) continue; } while (len > 0); diff --git a/net/rds/ib.c b/net/rds/ib.c index b4c8b0022fe..ba2dffeff60 100644 --- a/net/rds/ib.c +++ b/net/rds/ib.c @@ -338,7 +338,8 @@ static int rds_ib_laddr_check(__be32 addr) ret = rdma_bind_addr(cm_id, (struct sockaddr *)&sin); /* due to this, we will claim to support iWARP devices unless we check node_type. */ - if (ret || cm_id->device->node_type != RDMA_NODE_IB_CA) + if (ret || !cm_id->device || + cm_id->device->node_type != RDMA_NODE_IB_CA) ret = -EADDRNOTAVAIL; rdsdebug("addr %pI4 ret %d node type %d\n", diff --git a/net/rds/ib_send.c b/net/rds/ib_send.c index e5909498117..37be6e226d1 100644 --- a/net/rds/ib_send.c +++ b/net/rds/ib_send.c @@ -552,9 +552,8 @@ int rds_ib_xmit(struct rds_connection *conn, struct rds_message *rm, && rm->m_inc.i_hdr.h_flags & RDS_FLAG_CONG_BITMAP) { rds_cong_map_updated(conn->c_fcong, ~(u64) 0); scat = &rm->data.op_sg[sg]; - ret = sizeof(struct rds_header) + RDS_CONG_MAP_BYTES; - ret = min_t(int, ret, scat->length - conn->c_xmit_data_off); - return ret; + ret = max_t(int, RDS_CONG_MAP_BYTES, scat->length); + return sizeof(struct rds_header) + ret; } /* FIXME we may overallocate here */ diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index ce5f5b934ea..bde7d69b440 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c @@ -1257,6 +1257,7 @@ static int rose_recvmsg(struct kiocb *iocb, struct socket *sock, if (msg->msg_name) { struct sockaddr_rose *srose; + struct full_sockaddr_rose *full_srose = msg->msg_name; memset(msg->msg_name, 0, sizeof(struct full_sockaddr_rose)); srose = msg->msg_name; @@ -1264,18 +1265,9 @@ static int rose_recvmsg(struct kiocb *iocb, struct socket *sock, srose->srose_addr = rose->dest_addr; srose->srose_call = rose->dest_call; srose->srose_ndigis = rose->dest_ndigis; - if (msg->msg_namelen >= sizeof(struct full_sockaddr_rose)) { - struct full_sockaddr_rose *full_srose = (struct full_sockaddr_rose *)msg->msg_name; - for (n = 0 ; n < rose->dest_ndigis ; n++) - full_srose->srose_digis[n] = rose->dest_digis[n]; - msg->msg_namelen = sizeof(struct full_sockaddr_rose); - } else { - if (rose->dest_ndigis >= 1) { - srose->srose_ndigis = 1; - srose->srose_digi = rose->dest_digis[0]; - } - msg->msg_namelen = sizeof(struct sockaddr_rose); - } + for (n = 0 ; n < rose->dest_ndigis ; n++) + full_srose->srose_digis[n] = rose->dest_digis[n]; + msg->msg_namelen = sizeof(struct full_sockaddr_rose); } skb_free_datagram(sk, skb); diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 4b49578260e..43d3c6ab77d 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -525,13 +525,17 @@ static int unix_seqpacket_sendmsg(struct kiocb *, struct socket *, static int unix_seqpacket_recvmsg(struct kiocb *, struct socket *, struct msghdr *, size_t, int); -static void unix_set_peek_off(struct sock *sk, int val) +static int unix_set_peek_off(struct sock *sk, int val) { struct unix_sock *u = unix_sk(sk); - mutex_lock(&u->readlock); + if (mutex_lock_interruptible(&u->readlock)) + return -EINTR; + sk->sk_peek_off = val; mutex_unlock(&u->readlock); + + return 0; } @@ -709,7 +713,9 @@ static int unix_autobind(struct socket *sock) int err; unsigned int retries = 0; - mutex_lock(&u->readlock); + err = mutex_lock_interruptible(&u->readlock); + if (err) + return err; err = 0; if (u->addr) @@ -842,7 +848,9 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) goto out; addr_len = err; - mutex_lock(&u->readlock); + err = mutex_lock_interruptible(&u->readlock); + if (err) + goto out; err = -EINVAL; if (u->addr) From 850a3f4c31729de75fbf4f4fc7b8730fb43bf353 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Fri, 17 Jan 2014 11:32:09 +0100 Subject: [PATCH 163/215] mm: remove swap token code The swap token code no longer fits in with the current VM model. It does not play well with cgroups or the better NUMA placement code in development, since we have only one swap token globally. It also has the potential to mess with scalability of the system, by increasing the number of non-reclaimable pages on the active and inactive anon LRU lists. Last but not least, the swap token code has been broken for a year without complaints, as reported by Konstantin Khlebnikov. This suggests we no longer have much use for it. The days of sub-1G memory systems with heavy use of swap are over. If we ever need thrashing reducing code in the future, we will have to implement something that does scale. Change-Id: I6d287cfc3c3206ca24da2de0c1392e5fdfcfabe8 Signed-off-by: Rik van Riel Cc: Konstantin Khlebnikov Acked-by: Johannes Weiner Cc: Mel Gorman Cc: Hugh Dickins Acked-by: Bob Picco Acked-by: KOSAKI Motohiro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Git-commit: e709ffd6169ccd259eb5874e853303e91e94e829 Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git Signed-off-by: Laura Abbott --- include/linux/mm_types.h | 11 --- include/linux/swap.h | 35 -------- include/trace/events/vmscan.h | 82 ------------------ kernel/fork.c | 9 -- mm/Makefile | 2 +- mm/memcontrol.c | 1 - mm/memory.c | 2 +- mm/rmap.c | 6 -- mm/thrash.c | 155 ---------------------------------- mm/vmscan.c | 6 -- 10 files changed, 2 insertions(+), 307 deletions(-) delete mode 100644 mm/thrash.c diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h index 4fc12b203f0..5788ad6778f 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h @@ -359,17 +359,6 @@ struct mm_struct { /* Architecture-specific MM context */ mm_context_t context; - /* Swap token stuff */ - /* - * Last value of global fault stamp as seen by this process. - * In other words, this value gives an indication of how long - * it has been since this task got the token. - * Look at mm/thrash.c - */ - unsigned int faultstamp; - unsigned int token_priority; - unsigned int last_interval; - unsigned long flags; /* Must use atomic bitops to access the bits */ struct core_state *core_state; /* coredumping support */ diff --git a/include/linux/swap.h b/include/linux/swap.h index b1fd5c7925f..bc3073ce95c 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -355,23 +355,6 @@ extern int reuse_swap_page(struct page *); extern int try_to_free_swap(struct page *); struct backing_dev_info; -/* linux/mm/thrash.c */ -extern struct mm_struct *swap_token_mm; -extern void grab_swap_token(struct mm_struct *); -extern void __put_swap_token(struct mm_struct *); -extern void disable_swap_token(struct mem_cgroup *memcg); - -static inline int has_swap_token(struct mm_struct *mm) -{ - return (mm == swap_token_mm); -} - -static inline void put_swap_token(struct mm_struct *mm) -{ - if (has_swap_token(mm)) - __put_swap_token(mm); -} - #ifdef CONFIG_CGROUP_MEM_RES_CTLR extern void mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent, bool swapout); @@ -476,24 +459,6 @@ static inline swp_entry_t get_swap_page(void) return entry; } -/* linux/mm/thrash.c */ -static inline void put_swap_token(struct mm_struct *mm) -{ -} - -static inline void grab_swap_token(struct mm_struct *mm) -{ -} - -static inline int has_swap_token(struct mm_struct *mm) -{ - return 0; -} - -static inline void disable_swap_token(struct mem_cgroup *memcg) -{ -} - static inline void mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent) { diff --git a/include/trace/events/vmscan.h b/include/trace/events/vmscan.h index f64560e204b..572195459d5 100644 --- a/include/trace/events/vmscan.h +++ b/include/trace/events/vmscan.h @@ -395,88 +395,6 @@ TRACE_EVENT(mm_vmscan_lru_shrink_inactive, show_reclaim_flags(__entry->reclaim_flags)) ); -TRACE_EVENT(replace_swap_token, - TP_PROTO(struct mm_struct *old_mm, - struct mm_struct *new_mm), - - TP_ARGS(old_mm, new_mm), - - TP_STRUCT__entry( - __field(struct mm_struct*, old_mm) - __field(unsigned int, old_prio) - __field(struct mm_struct*, new_mm) - __field(unsigned int, new_prio) - ), - - TP_fast_assign( - __entry->old_mm = old_mm; - __entry->old_prio = old_mm ? old_mm->token_priority : 0; - __entry->new_mm = new_mm; - __entry->new_prio = new_mm->token_priority; - ), - - TP_printk("old_token_mm=%p old_prio=%u new_token_mm=%p new_prio=%u", - __entry->old_mm, __entry->old_prio, - __entry->new_mm, __entry->new_prio) -); - -DECLARE_EVENT_CLASS(put_swap_token_template, - TP_PROTO(struct mm_struct *swap_token_mm), - - TP_ARGS(swap_token_mm), - - TP_STRUCT__entry( - __field(struct mm_struct*, swap_token_mm) - ), - - TP_fast_assign( - __entry->swap_token_mm = swap_token_mm; - ), - - TP_printk("token_mm=%p", __entry->swap_token_mm) -); - -DEFINE_EVENT(put_swap_token_template, put_swap_token, - TP_PROTO(struct mm_struct *swap_token_mm), - TP_ARGS(swap_token_mm) -); - -DEFINE_EVENT_CONDITION(put_swap_token_template, disable_swap_token, - TP_PROTO(struct mm_struct *swap_token_mm), - TP_ARGS(swap_token_mm), - TP_CONDITION(swap_token_mm != NULL) -); - -TRACE_EVENT_CONDITION(update_swap_token_priority, - TP_PROTO(struct mm_struct *mm, - unsigned int old_prio, - struct mm_struct *swap_token_mm), - - TP_ARGS(mm, old_prio, swap_token_mm), - - TP_CONDITION(mm->token_priority != old_prio), - - TP_STRUCT__entry( - __field(struct mm_struct*, mm) - __field(unsigned int, old_prio) - __field(unsigned int, new_prio) - __field(struct mm_struct*, swap_token_mm) - __field(unsigned int, swap_token_prio) - ), - - TP_fast_assign( - __entry->mm = mm; - __entry->old_prio = old_prio; - __entry->new_prio = mm->token_priority; - __entry->swap_token_mm = swap_token_mm; - __entry->swap_token_prio = swap_token_mm ? swap_token_mm->token_priority : 0; - ), - - TP_printk("mm=%p old_prio=%u new_prio=%u swap_token_mm=%p token_prio=%u", - __entry->mm, __entry->old_prio, __entry->new_prio, - __entry->swap_token_mm, __entry->swap_token_prio) -); - #endif /* _TRACE_VMSCAN_H */ /* This part must be outside protection */ diff --git a/kernel/fork.c b/kernel/fork.c index e775c328172..788e72d4ae2 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -598,7 +598,6 @@ int mmput(struct mm_struct *mm) list_del(&mm->mmlist); spin_unlock(&mmlist_lock); } - put_swap_token(mm); if (mm->binfmt) module_put(mm->binfmt->module); mmdrop(mm); @@ -816,10 +815,6 @@ struct mm_struct *dup_mm(struct task_struct *tsk) memcpy(mm, oldmm, sizeof(*mm)); mm_init_cpumask(mm); - /* Initializing for Swap token stuff */ - mm->token_priority = 0; - mm->last_interval = 0; - #ifdef CONFIG_TRANSPARENT_HUGEPAGE mm->pmd_huge_pte = NULL; #endif @@ -897,10 +892,6 @@ static int copy_mm(unsigned long clone_flags, struct task_struct *tsk) goto fail_nomem; good_mm: - /* Initializing for Swap token stuff */ - mm->token_priority = 0; - mm->last_interval = 0; - tsk->mm = mm; tsk->active_mm = mm; return 0; diff --git a/mm/Makefile b/mm/Makefile index 8aada89efbb..ccecbf9818f 100644 --- a/mm/Makefile +++ b/mm/Makefile @@ -25,7 +25,7 @@ endif obj-$(CONFIG_HAVE_MEMBLOCK) += memblock.o obj-$(CONFIG_BOUNCE) += bounce.o -obj-$(CONFIG_SWAP) += page_io.o swap_state.o swapfile.o thrash.o +obj-$(CONFIG_SWAP) += page_io.o swap_state.o swapfile.o obj-$(CONFIG_HAS_DMA) += dmapool.o obj-$(CONFIG_HUGETLBFS) += hugetlb.o obj-$(CONFIG_NUMA) += mempolicy.o diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 3d914da3f1f..3949df3484c 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -5625,7 +5625,6 @@ static void mem_cgroup_move_task(struct cgroup *cont, if (mm) { if (mc.to) mem_cgroup_move_charge(mm); - put_swap_token(mm); mmput(mm); } if (mc.to) diff --git a/mm/memory.c b/mm/memory.c index 4da9f55df49..768f62337a5 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -2927,7 +2927,6 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, delayacct_set_flag(DELAYACCT_PF_SWAPIN); page = lookup_swap_cache(entry); if (!page) { - grab_swap_token(mm); /* Contend for token _before_ read-in */ page = swapin_readahead(entry, GFP_HIGHUSER_MOVABLE, vma, address); if (!page) { @@ -2957,6 +2956,7 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, } locked = lock_page_or_retry(page, mm, flags); + delayacct_clear_flag(DELAYACCT_PF_SWAPIN); if (!locked) { ret |= VM_FAULT_RETRY; diff --git a/mm/rmap.c b/mm/rmap.c index f02c862fab6..2b03b317ee2 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -760,12 +760,6 @@ int page_referenced_one(struct page *page, struct vm_area_struct *vma, pte_unmap_unlock(pte, ptl); } - /* Pretend the page is referenced if the task has the - swap token and is in the middle of a page fault. */ - if (mm != current->mm && has_swap_token(mm) && - rwsem_is_locked(&mm->mmap_sem)) - referenced++; - (*mapcount)--; if (referenced) diff --git a/mm/thrash.c b/mm/thrash.c deleted file mode 100644 index 57ad495dbd5..00000000000 --- a/mm/thrash.c +++ /dev/null @@ -1,155 +0,0 @@ -/* - * mm/thrash.c - * - * Copyright (C) 2004, Red Hat, Inc. - * Copyright (C) 2004, Rik van Riel - * Released under the GPL, see the file COPYING for details. - * - * Simple token based thrashing protection, using the algorithm - * described in: http://www.cse.ohio-state.edu/hpcs/WWW/HTML/publications/abs05-1.html - * - * Sep 2006, Ashwin Chaugule - * Improved algorithm to pass token: - * Each task has a priority which is incremented if it contended - * for the token in an interval less than its previous attempt. - * If the token is acquired, that task's priority is boosted to prevent - * the token from bouncing around too often and to let the task make - * some progress in its execution. - */ - -#include -#include -#include -#include -#include - -#include - -#define TOKEN_AGING_INTERVAL (0xFF) - -static DEFINE_SPINLOCK(swap_token_lock); -struct mm_struct *swap_token_mm; -static struct mem_cgroup *swap_token_memcg; - -#ifdef CONFIG_CGROUP_MEM_RES_CTLR -static struct mem_cgroup *swap_token_memcg_from_mm(struct mm_struct *mm) -{ - struct mem_cgroup *memcg; - - memcg = try_get_mem_cgroup_from_mm(mm); - if (memcg) - css_put(mem_cgroup_css(memcg)); - - return memcg; -} -#else -static struct mem_cgroup *swap_token_memcg_from_mm(struct mm_struct *mm) -{ - return NULL; -} -#endif - -void grab_swap_token(struct mm_struct *mm) -{ - int current_interval; - unsigned int old_prio = mm->token_priority; - static unsigned int global_faults; - static unsigned int last_aging; - - global_faults++; - - current_interval = global_faults - mm->faultstamp; - - if (!spin_trylock(&swap_token_lock)) - return; - - /* First come first served */ - if (!swap_token_mm) - goto replace_token; - - /* - * Usually, we don't need priority aging because long interval faults - * makes priority decrease quickly. But there is one exception. If the - * token owner task is sleeping, it never make long interval faults. - * Thus, we need a priority aging mechanism instead. The requirements - * of priority aging are - * 1) An aging interval is reasonable enough long. Too short aging - * interval makes quick swap token lost and decrease performance. - * 2) The swap token owner task have to get priority aging even if - * it's under sleep. - */ - if ((global_faults - last_aging) > TOKEN_AGING_INTERVAL) { - swap_token_mm->token_priority /= 2; - last_aging = global_faults; - } - - if (mm == swap_token_mm) { - mm->token_priority += 2; - goto update_priority; - } - - if (current_interval < mm->last_interval) - mm->token_priority++; - else { - if (likely(mm->token_priority > 0)) - mm->token_priority--; - } - - /* Check if we deserve the token */ - if (mm->token_priority > swap_token_mm->token_priority) - goto replace_token; - -update_priority: - trace_update_swap_token_priority(mm, old_prio, swap_token_mm); - -out: - mm->faultstamp = global_faults; - mm->last_interval = current_interval; - spin_unlock(&swap_token_lock); - return; - -replace_token: - mm->token_priority += 2; - trace_replace_swap_token(swap_token_mm, mm); - swap_token_mm = mm; - swap_token_memcg = swap_token_memcg_from_mm(mm); - last_aging = global_faults; - goto out; -} - -/* Called on process exit. */ -void __put_swap_token(struct mm_struct *mm) -{ - spin_lock(&swap_token_lock); - if (likely(mm == swap_token_mm)) { - trace_put_swap_token(swap_token_mm); - swap_token_mm = NULL; - swap_token_memcg = NULL; - } - spin_unlock(&swap_token_lock); -} - -static bool match_memcg(struct mem_cgroup *a, struct mem_cgroup *b) -{ - if (!a) - return true; - if (!b) - return true; - if (a == b) - return true; - return false; -} - -void disable_swap_token(struct mem_cgroup *memcg) -{ - /* memcg reclaim don't disable unrelated mm token. */ - if (match_memcg(memcg, swap_token_memcg)) { - spin_lock(&swap_token_lock); - if (match_memcg(memcg, swap_token_memcg)) { - trace_disable_swap_token(swap_token_mm); - swap_token_mm = NULL; - swap_token_memcg = NULL; - } - spin_unlock(&swap_token_lock); - } -} diff --git a/mm/vmscan.c b/mm/vmscan.c index 81ae3756cb8..233794549b2 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -2352,8 +2352,6 @@ static unsigned long do_try_to_free_pages(struct zonelist *zonelist, for (priority = DEF_PRIORITY; priority >= 0; priority--) { sc->nr_scanned = 0; - if (!priority) - disable_swap_token(sc->target_mem_cgroup); aborted_reclaim = shrink_zones(priority, zonelist, sc); /* @@ -2704,10 +2702,6 @@ static unsigned long balance_pgdat(pg_data_t *pgdat, int order, unsigned long lru_pages = 0; int has_under_min_watermark_zone = 0; - /* The swap token gets in the way of swapout... */ - if (!priority) - disable_swap_token(NULL); - all_zones_ok = 1; balanced = 0; From e5ea1a4aca7252709f5e8f71fba45be4e7d8cf94 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Fri, 17 Jan 2014 11:33:03 +0100 Subject: [PATCH 164/215] mm: pass readahead info down to the i/o scheduler Some i/o schedulers (i.e. row-iosched, cfq-iosched) deploy an idling algorithm in order to be better synced with the readahead algorithm. Idling is a prediction algorithm for incoming read requests. In this patch we mark pages which are part of a readahead window, by setting a newly introduced flag. With this flag, the i/o scheduler can identify a request which is associated with a readahead page. This enables the i/o scheduler's idling mechanism to be en-sync with the readahead mechanism and, in turn, can increase read throughput. Change-Id: I0654f23315b6d19d71bcc9cc029c6b281a44b196 Signed-off-by: Lee Susman From 1ba0c6d753b54d7633182cc7b67581fff293e8af Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Fri, 17 Jan 2014 14:46:09 +0100 Subject: [PATCH 165/215] ARM: fix "bad mode in ... handler" message for undefined instructions The array was missing the final entry for the undefined instruction exception handler; this commit adds it. Signed-off-by: Russell King Signed-off-by: Greg Kroah-Hartman --- arch/arm/kernel/traps.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 0d4e5daa4c1..a6a8c4769be 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c @@ -39,7 +39,13 @@ #include -static const char *handler[]= { "prefetch abort", "data abort", "address exception", "interrupt" }; +static const char *handler[]= { + "prefetch abort", + "data abort", + "address exception", + "interrupt", + "undefined instruction", +}; #ifdef CONFIG_LGE_CRASH_HANDLER static int first_call_chain = 0; From 38b4bf599560d7874c5af91a1237d64714859a66 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Tue, 30 Apr 2013 15:27:38 -0700 Subject: [PATCH 166/215] epoll: trim epitem by one cache line It is common for epoll users to have thousands of epitems, so saving a cache line on every allocation leads to large memory savings. Since epitem allocations are cache-aligned, reducing sizeof(struct epitem) from 136 bytes to 128 bytes will allow it to squeeze under a cache line boundary on x86_64. Via /sys/kernel/slab/eventpoll_epi, I see the following changes on my x86_64 Core2 Duo (which has 64-byte cache alignment): object_size : 192 => 128 objs_per_slab: 21 => 32 Also, add a BUILD_BUG_ON() to check for future accidental breakage. [akpm@linux-foundation.org: use __packed, for all architectures] Signed-off-by: Eric Wong Cc: Davide Libenzi Cc: Al Viro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/eventpoll.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/fs/eventpoll.c b/fs/eventpoll.c index 9dba98a0b31..c8a19aba1cb 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -103,7 +103,7 @@ struct epoll_filefd { struct file *file; int fd; -}; +} __packed; /* * Structure used to track possible nested calls, for too deep recursions @@ -127,6 +127,8 @@ struct nested_calls { /* * Each file descriptor added to the eventpoll interface will * have an entry of this type linked to the "rbr" RB tree. + * Avoid increasing the size of this struct, there can be many thousands + * of these on a server and we do not want this to take another cache line. */ struct epitem { union { @@ -1923,6 +1925,12 @@ static int __init eventpoll_init(void) /* Initialize the structure used to perform file's f_op->poll() calls */ ep_nested_calls_init(&poll_readywalk_ncalls); + /* + * We can have many thousands of epitems, so prevent this from + * using an extra cache line on 64-bit (and smaller) CPUs + */ + BUILD_BUG_ON(sizeof(void *) <= 8 && sizeof(struct epitem) > 128); + /* Allocates slab cache used to allocate "struct epitem" items */ epi_cache = kmem_cache_create("eventpoll_epi", sizeof(struct epitem), 0, SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL); From 0c95dd7b4d9d9ce86f8289f3de255097a5b6193c Mon Sep 17 00:00:00 2001 From: liguang Date: Tue, 30 Apr 2013 15:27:25 -0700 Subject: [PATCH 167/215] kernel/smp.c: use '|=' for csd_lock csd_lock() uses assignment to data->flags rather than |=. That is not buggy at present because only one bit (CSD_FLAG_LOCK) is defined in call_single_data.flags. But it will become buggy if we later add another flag, so fix it now. Signed-off-by: liguang Cc: Peter Zijlstra Cc: Oleg Nesterov Cc: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/smp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/smp.c b/kernel/smp.c index b32ac0a2b27..5e93d99069e 100644 --- a/kernel/smp.c +++ b/kernel/smp.c @@ -113,7 +113,7 @@ static void csd_lock_wait(struct call_single_data *data) static void csd_lock(struct call_single_data *data) { csd_lock_wait(data); - data->flags = CSD_FLAG_LOCK; + data->flags |= CSD_FLAG_LOCK; /* * prevent CPU from reordering the above assignment From c70a6f6575fc54aca529c624c5e0bb4bf8475eeb Mon Sep 17 00:00:00 2001 From: Andrey Sidorov Date: Wed, 19 Sep 2012 18:14:53 +0000 Subject: [PATCH 168/215] ext4: speed up truncate/unlink by not using bforget() unless needed Do not iterate over data blocks scanning for bh's to forget as they're never exist. This improves time taken by unlink / truncate syscall. Tested by continuously truncating file that is being written by dd. Another test is rm -rf of linux tree while tar unpacks it. With ordered data mode condition unlikely(!tbh) was always met in ext4_free_blocks. With journal data mode tbh was found only few times, so optimisation is also possible. Unlinking fallocated 60G file after doing sync && echo 3 > /proc/sys/vm/drop_caches && time rm --help X86 before (linux 3.6-rc4): # time rm -f test1 real 0m2.710s user 0m0.000s sys 0m1.530s X86 after: # time rm -f test1 real 0m0.644s user 0m0.003s sys 0m0.060s MIPS before (linux 2.6.37): # time rm -f test1 real 0m 4.93s user 0m 0.00s sys 0m 4.61s MIPS after: # time rm -f test1 real 0m 0.16s user 0m 0.00s sys 0m 0.06s Signed-off-by: "Theodore Ts'o" Signed-off-by: Andrey Sidorov Signed-off-by: franciscofranco --- fs/ext4/extents.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index c883561e9b6..d4248058ed8 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -2242,10 +2242,13 @@ static int ext4_remove_blocks(handle_t *handle, struct inode *inode, struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); unsigned short ee_len = ext4_ext_get_actual_len(ex); ext4_fsblk_t pblk; - int flags = EXT4_FREE_BLOCKS_FORGET; + int flags = 0; if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) - flags |= EXT4_FREE_BLOCKS_METADATA; + flags |= EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET; + else if (ext4_should_journal_data(inode)) + flags |= EXT4_FREE_BLOCKS_FORGET; + /* * For bigalloc file systems, we never free a partial cluster * at the beginning of the extent. Instead, we make a note From 1bc9f9f58bb6fd62dba66856e0cdf58943ac3582 Mon Sep 17 00:00:00 2001 From: mrg666 Date: Sun, 22 Dec 2013 20:52:32 -0500 Subject: [PATCH 169/215] jbd2: optimize jbd2_journal_force_commit Current implementation of jbd2_journal_force_commit() is suboptimal because result in empty and useless commits. But callers just want to force and wait any unfinished commits. We already have jbd2_journal_force_commit_nested() which does exactly what we want, except we are guaranteed that we do not hold journal transaction open. Signed-off-by: Dmitry Monakhov Signed-off-by: "Theodore Ts'o" Signed-off-by: franciscofranco --- fs/jbd2/journal.c | 62 +++++++++++++++++++++++++++++++++---------- fs/jbd2/transaction.c | 23 ---------------- include/linux/jbd2.h | 2 +- 3 files changed, 49 insertions(+), 38 deletions(-) diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index d343ac76909..6a924e9ddde 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c @@ -518,20 +518,17 @@ int jbd2_log_start_commit(journal_t *journal, tid_t tid) } /* - * Force and wait upon a commit if the calling process is not within - * transaction. This is used for forcing out undo-protected data which contains - * bitmaps, when the fs is running out of space. - * - * We can only force the running transaction if we don't have an active handle; - * otherwise, we will deadlock. - * - * Returns true if a transaction was started. + * Force and wait any uncommitted transactions. We can only force the running + * transaction if we don't have an active handle, otherwise, we will deadlock. + * Returns: <0 in case of error, + * 0 if nothing to commit, + * 1 if transaction was successfully committed. */ -int jbd2_journal_force_commit_nested(journal_t *journal) +static int __jbd2_journal_force_commit(journal_t *journal) { transaction_t *transaction = NULL; tid_t tid; - int need_to_start = 0; + int need_to_start = 0, ret = 0; read_lock(&journal->j_state_lock); if (journal->j_running_transaction && !current->journal_info) { @@ -542,16 +539,53 @@ int jbd2_journal_force_commit_nested(journal_t *journal) transaction = journal->j_committing_transaction; if (!transaction) { + /* Nothing to commit */ read_unlock(&journal->j_state_lock); - return 0; /* Nothing to retry */ + return 0; } - tid = transaction->t_tid; read_unlock(&journal->j_state_lock); if (need_to_start) jbd2_log_start_commit(journal, tid); - jbd2_log_wait_commit(journal, tid); - return 1; + ret = jbd2_log_wait_commit(journal, tid); + if (!ret) + ret = 1; + + return ret; +} + +/** + * Force and wait upon a commit if the calling process is not within + * transaction. This is used for forcing out undo-protected data which contains + * bitmaps, when the fs is running out of space. + * + * @journal: journal to force + * Returns true if progress was made. + */ +int jbd2_journal_force_commit_nested(journal_t *journal) +{ + int ret; + + ret = __jbd2_journal_force_commit(journal); + return ret > 0; +} + +/** + * int journal_force_commit() - force any uncommitted transactions + * @journal: journal to force + * + * Caller want unconditional commit. We can only force the running transaction + * if we don't have an active handle, otherwise, we will deadlock. + */ +int jbd2_journal_force_commit(journal_t *journal) +{ + int ret; + + J_ASSERT(!current->journal_info); + ret = __jbd2_journal_force_commit(journal); + if (ret > 0) + ret = 0; + return ret; } /* diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c index baedf6a8610..f7b884d40a0 100644 --- a/fs/jbd2/transaction.c +++ b/fs/jbd2/transaction.c @@ -1502,29 +1502,6 @@ int jbd2_journal_stop(handle_t *handle) return err; } -/** - * int jbd2_journal_force_commit() - force any uncommitted transactions - * @journal: journal to force - * - * For synchronous operations: force any uncommitted transactions - * to disk. May seem kludgy, but it reuses all the handle batching - * code in a very simple manner. - */ -int jbd2_journal_force_commit(journal_t *journal) -{ - handle_t *handle; - int ret; - - handle = jbd2_journal_start(journal, 1); - if (IS_ERR(handle)) { - ret = PTR_ERR(handle); - } else { - handle->h_sync = 1; - ret = jbd2_journal_stop(handle); - } - return ret; -} - /* * * List management code snippets: various functions for manipulating the diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h index dd6444f67ed..c9b45c9c8f6 100644 --- a/include/linux/jbd2.h +++ b/include/linux/jbd2.h @@ -1102,6 +1102,7 @@ extern void jbd2_journal_ack_err (journal_t *); extern int jbd2_journal_clear_err (journal_t *); extern int jbd2_journal_bmap(journal_t *, unsigned long, unsigned long long *); extern int jbd2_journal_force_commit(journal_t *); +extern int jbd2_journal_force_commit_nested(journal_t *); extern int jbd2_journal_file_inode(handle_t *handle, struct jbd2_inode *inode); extern int jbd2_journal_begin_ordered_truncate(journal_t *journal, struct jbd2_inode *inode, loff_t new_size); @@ -1176,7 +1177,6 @@ int __jbd2_log_space_left(journal_t *); /* Called with journal locked */ int jbd2_log_start_commit(journal_t *journal, tid_t tid); int __jbd2_log_start_commit(journal_t *journal, tid_t tid); int jbd2_journal_start_commit(journal_t *journal, tid_t *tid); -int jbd2_journal_force_commit_nested(journal_t *journal); int jbd2_log_wait_commit(journal_t *journal, tid_t tid); int jbd2_log_do_checkpoint(journal_t *journal); int jbd2_trans_will_send_data_barrier(journal_t *journal, tid_t tid); From 696bf60ffdf4c8bcacc82503ff2d96054dd3f6e0 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sun, 23 Sep 2012 22:28:59 +0000 Subject: [PATCH 170/215] net: loopback: set default mtu to 64K loopback current mtu of 16436 bytes allows no more than 3 MSS TCP segments per frame, or 48 Kbytes. Changing mtu to 64K allows TCP stack to build large frames and significantly reduces stack overhead. Performance boost on bulk TCP transferts can be up to 30 %, partly because we now have one ACK message for two 64KB segments, and a lower probability of hitting /proc/sys/net/ipv4/tcp_reordering default limit. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller Signed-off-by: franciscofranco --- drivers/net/loopback.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index a3d4707505a..baa9b36b4b2 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c @@ -162,7 +162,7 @@ static const struct net_device_ops loopback_ops = { */ static void loopback_setup(struct net_device *dev) { - dev->mtu = (16 * 1024) + 20 + 20 + 12; + dev->mtu = 64 * 1024; dev->hard_header_len = ETH_HLEN; /* 14 */ dev->addr_len = ETH_ALEN; /* 6 */ dev->tx_queue_len = 0; From a91218afc9b0ec71cd52955ad060e5a10efd2325 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 12 Jul 2012 14:46:37 -0700 Subject: [PATCH 171/215] workqueue: don't use WQ_HIGHPRI for unbound workqueues Unbound wqs aren't concurrency-managed and try to execute work items as soon as possible. This is currently achieved by implicitly setting %WQ_HIGHPRI on all unbound workqueues; however, WQ_HIGHPRI implementation is about to be restructured and this usage won't be valid anymore. Add an explicit chain-wakeup path for unbound workqueues in process_one_work() instead of piggy backing on %WQ_HIGHPRI. Change-Id: Iecd17a9935ee28f856d8b726bb4c296762922bed Signed-off-by: Tejun Heo Git-commit: 974271c485a4d8bb801decc616748f90aafb07ec Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git Signed-off-by: Matt Wagantall Conflicts: kernel/workqueue.c --- kernel/workqueue.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/workqueue.c b/kernel/workqueue.c index b537accaee8..a9f3a011428 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -1881,8 +1881,8 @@ __acquires(&gcwq->lock) * Unbound gcwq isn't concurrency managed and work items should be * executed ASAP. Wake up another worker if necessary. */ - if ((worker->flags & WORKER_UNBOUND) && need_more_worker(pool)) - wake_up_worker(pool); + if ((worker->flags & WORKER_UNBOUND) && need_more_worker(gcwq)) + wake_up_worker(gcwq); spin_unlock_irq(&gcwq->lock); From 5e2550f0a12009e0953f708c2d693a72f89e91a5 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Fri, 17 Jan 2014 18:25:38 +0100 Subject: [PATCH 172/215] cpufreq: Fix policy getting stuck when user & kernel min/max don't overlap Every __cpufreq_set_policy starts with checking the new policy min/max has some overlap with the current policy min/max. This works out fine until we end up with the policy min/max being set to a range that doesn't overlap with the user policy min/max. Once we get into this situation, the check at the start of __cpufreq_set_policy fails and prevents us from getting out of this state. This only happens when one of the CPUFREQ_ADJUST/CPUFREQ_INCOMPATIBLE notifiers called inside __cpufreq_set_policy pick a min/max outside the range of user policy min/max. The real intent of the check at the start of __cpufreq_set_policy is to make sure userspace can't set user policy min > user policy max. Since __cpufreq_set_policy always gets called only with current user policy min/max except when the actual user space policy min/max is changed, we can fix the issue by simply checking the new policy min/max against current user policy min/max. Change-Id: Iaac805825e64d7985c41fb9052bd96baacdf3d6f Signed-off-by: Saravana Kannan --- drivers/cpufreq/cpufreq.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 5ed2e84cd11..7399fd0e83b 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -1865,7 +1865,8 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, memcpy(&policy->cpuinfo, &data->cpuinfo, sizeof(struct cpufreq_cpuinfo)); - if (policy->min > data->max || policy->max < data->min) { + if (policy->min > data->user_policy.max + || policy->max < data->user_policy.min) { ret = -EINVAL; goto error_out; } From f754e2aada3aac3cec9b42355d82d7b79612d5dc Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Fri, 17 Jan 2014 18:28:48 +0100 Subject: [PATCH 173/215] ARM: 7880/1: Clear the IT state independent of the Thumb-2 mode The ARM architecture reference specifies that the IT state bits in the PSR must be all zeros in ARM mode or behavior is unspecified. On the Qualcomm Snapdragon S4/Krait architecture CPUs the processor continues to consider the IT state bits while in ARM mode. This makes it so that some instructions are skipped by the CPU. Signed-off-by: T.J. Purtell [rmk+kernel@arm.linux.org.uk: fixed whitespace formatting in patch] Signed-off-by: Russell King Git-commit: 6ecf830e5029598732e04067e325d946097519cb Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git Change-Id: I74275a3d98aef291d6f41b1905acc3aeecb50b47 Signed-off-by: Stepan Moskovchenko --- arch/arm/kernel/signal.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c index eb3a2912cb9..c84776f6e0d 100644 --- a/arch/arm/kernel/signal.c +++ b/arch/arm/kernel/signal.c @@ -437,12 +437,18 @@ setup_return(struct pt_regs *regs, struct k_sigaction *ka, */ thumb = handler & 1; - if (thumb) { - cpsr |= PSR_T_BIT; #if __LINUX_ARM_ARCH__ >= 7 - /* clear the If-Then Thumb-2 execution state */ - cpsr &= ~PSR_IT_MASK; + /* + * Clear the If-Then Thumb-2 execution state + * ARM spec requires this to be all 000s in ARM mode + * Snapdragon S4/Krait misbehaves on a Thumb=>ARM + * signal transition without this. + */ + cpsr &= ~PSR_IT_MASK; #endif + + if (thumb) { + cpsr |= PSR_T_BIT; } else cpsr &= ~PSR_T_BIT; } From 54eb4e207928e8936dbfd77140628380cbe657ad Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Thu, 23 Jan 2014 03:12:21 +0100 Subject: [PATCH 174/215] Revert "mm: Lower read-ahead buffer to fix stuttering introduced with recent commits" This reverts commit 50e7a8d6abcc66a8c99f4e7fe8bfb06dd45b18c5. --- include/linux/mm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/mm.h b/include/linux/mm.h index 4c168d001e4..d8d2dbf0482 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -1426,7 +1426,7 @@ int write_one_page(struct page *page, int wait); void task_dirty_inc(struct task_struct *tsk); /* readahead.c */ -#define VM_MAX_READAHEAD 128 /* kbytes */ +#define VM_MAX_READAHEAD 256 /* kbytes */ #define VM_MIN_READAHEAD 16 /* kbytes (includes current page) */ int force_page_cache_readahead(struct address_space *mapping, struct file *filp, From fe17f4afc60d941edcfe33698327cb37c64f86d9 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Thu, 23 Jan 2014 03:15:09 +0100 Subject: [PATCH 175/215] Update Aroma "changelog" (features list) --- .../aroma/META-INF/com/google/android/aroma/changelog.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/release/aroma/META-INF/com/google/android/aroma/changelog.txt b/release/aroma/META-INF/com/google/android/aroma/changelog.txt index aa78f3b7c50..fbbdf4a5913 100755 --- a/release/aroma/META-INF/com/google/android/aroma/changelog.txt +++ b/release/aroma/META-INF/com/google/android/aroma/changelog.txt @@ -1,6 +1,6 @@ Glitch kernel "AOSP" for N7 2013 -- Based on AOSP 3.4.0 kernel source for MSM devices updated to linux 3.4.60 +- Based on AOSP 3.4.0 kernel source for MSM devices updated to linux 3.4.77 - CPU OC up to 2.3Ghz with OV/UV support - L2/bus speed OC up to 1.49GHz / 4.96GBPS - GPU OC up to 627 MHz @@ -18,7 +18,7 @@ - Magnetic on/off - FauxSound support -- Panel color tweaking by Faux123 +- Panel color/gamma tweaking by Faux123 - Dynamic Fsync by Faux123 - USB fast charging support - USB OTG charge hack support by flar2 @@ -26,6 +26,6 @@ - Optimized algorithms and libraries - Various performance and power saving tweaks - NTFS and exFAT support -- Kexec-hardboot support +- Kexec-hardboot (Multiboot) support -- Compiled with latest SaberMod 4.8.x toolchain / -O3 (optimize a lot) +- Compiled with latest SaberMod 4.8.3 toolchain with -O3 optimizations From 9b77889381dec01521d1a439d624d9d67aefdcae Mon Sep 17 00:00:00 2001 From: animania260 Date: Sat, 25 Jan 2014 00:53:14 -0500 Subject: [PATCH 176/215] Revert "workqueue: don't use WQ_HIGHPRI for unbound workqueues" This reverts commit a91218afc9b0ec71cd52955ad060e5a10efd2325. --- kernel/workqueue.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/workqueue.c b/kernel/workqueue.c index a9f3a011428..b537accaee8 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -1881,8 +1881,8 @@ __acquires(&gcwq->lock) * Unbound gcwq isn't concurrency managed and work items should be * executed ASAP. Wake up another worker if necessary. */ - if ((worker->flags & WORKER_UNBOUND) && need_more_worker(gcwq)) - wake_up_worker(gcwq); + if ((worker->flags & WORKER_UNBOUND) && need_more_worker(pool)) + wake_up_worker(pool); spin_unlock_irq(&gcwq->lock); From 2017219766413f7607c06c798fde0d4986412da5 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Thu, 23 Jan 2014 03:11:59 +0100 Subject: [PATCH 177/215] Revert "mm: pass readahead info down to the i/o scheduler" This reverts commit 726e99a128747be9fc05bcffd044c18e5b2fe470. --- include/linux/page-flags.h | 1 - mm/page_alloc.c | 1 - mm/readahead.c | 3 --- 3 files changed, 5 deletions(-) diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h index 5bc4fa5c6f1..4dabf0fe527 100644 --- a/include/linux/page-flags.h +++ b/include/linux/page-flags.h @@ -108,7 +108,6 @@ enum pageflags { #ifdef CONFIG_TRANSPARENT_HUGEPAGE PG_compound_lock, #endif - PG_readahead, /* page in a readahead window */ __NR_PAGEFLAGS, /* Filesystems */ diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 8e5bbf01db2..a3610d16cec 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -6118,7 +6118,6 @@ static struct trace_print_flags pageflag_names[] = { #ifdef CONFIG_MEMORY_FAILURE {1UL << PG_hwpoison, "hwpoison" }, #endif - {1UL << PG_readahead, "PG_readahead" }, {-1UL, NULL }, }; diff --git a/mm/readahead.c b/mm/readahead.c index cae9a44ab22..d3a19647b3f 100644 --- a/mm/readahead.c +++ b/mm/readahead.c @@ -184,9 +184,6 @@ __do_page_cache_readahead(struct address_space *mapping, struct file *filp, if (!page) break; page->index = page_offset; - - page->flags |= (1L << PG_readahead); - list_add(&page->lru, &page_pool); if (page_idx == nr_to_read - lookahead_size) SetPageReadahead(page); From 4f2686cdebe6a288741fb24122864a8c22c86ca0 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Thu, 23 Jan 2014 03:16:28 +0100 Subject: [PATCH 178/215] Update defconfig --- arch/arm/configs/flo_defconfig | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm/configs/flo_defconfig b/arch/arm/configs/flo_defconfig index be14b6983e6..a2463a61697 100644 --- a/arch/arm/configs/flo_defconfig +++ b/arch/arm/configs/flo_defconfig @@ -1,6 +1,6 @@ # # Automatically generated file; DO NOT EDIT. -# Linux/arm 3.4.76 Kernel Configuration +# Linux/arm 3.4.77 Kernel Configuration # CONFIG_ARM=y CONFIG_ARM_HAS_SG_CHAIN=y @@ -80,7 +80,7 @@ CONFIG_TREE_PREEMPT_RCU=y CONFIG_PREEMPT_RCU=y CONFIG_RCU_FANOUT=32 # CONFIG_RCU_FANOUT_EXACT is not set -# CONFIG_RCU_FAST_NO_HZ is not set +CONFIG_RCU_FAST_NO_HZ=y # CONFIG_TREE_RCU_TRACE is not set # CONFIG_RCU_BOOST is not set CONFIG_IKCONFIG=y @@ -163,7 +163,6 @@ CONFIG_PROFILING=y CONFIG_HAVE_OPROFILE=y # CONFIG_KPROBES is not set # CONFIG_JUMP_LABEL is not set -CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y CONFIG_HAVE_KPROBES=y CONFIG_HAVE_KRETPROBES=y CONFIG_HAVE_DMA_ATTRS=y @@ -2805,6 +2804,7 @@ CONFIG_FB_MSM_OVERLAY1_WRITEBACK=y CONFIG_FB_MSM_MIPI_NOVATEK_VIDEO_MODE=y CONFIG_FB_MSM_MIPI_LG_VIDEO_MODE=y CONFIG_FB_MSM_MIPI_JDI_CMD_MODE=y +# CONFIG_FB_MSM_MIPI_LGIT_VIDEO_WXGA_PT_PANEL is not set CONFIG_FB_MSM_EXT_INTERFACE_COMMON=y CONFIG_FB_MSM_HDMI_COMMON=y CONFIG_FB_MSM_HDMI_3D=y @@ -3813,7 +3813,7 @@ CONFIG_RCU_CPU_STALL_VERBOSE=y CONFIG_HAVE_C_RECORDMCOUNT=y CONFIG_TRACING_SUPPORT=y # CONFIG_FTRACE is not set -CONFIG_DYNAMIC_DEBUG=y +# CONFIG_DYNAMIC_DEBUG is not set # CONFIG_DMA_API_DEBUG is not set # CONFIG_ATOMIC64_SELFTEST is not set # CONFIG_PANIC_ON_DATA_CORRUPTION is not set From c12f04b00f21a3ec5b7bb5ea1ec61c6b57d8d9c3 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Fri, 24 Jan 2014 12:17:58 +0100 Subject: [PATCH 179/215] ARM: hw_breakpoint: Clear breakpoints before enabling monitor mode The reset value of the BCR, BVR, WCR, and WVR registers are all UNKNOWN on ARMv7. Unfortunately, reset_ctrl_regs() clears these registers *after* enabling monitor mode, not before, and so some implementations may experience UNPREDICTABLE behavior if the reset values of these registers are non-zero. Clear the breakpoints before enabling monitor mode so that we don't experience boot hangs/loops due to breakpoints being enabled out of reset. Change-Id: I029fbe40725e803183544ddd6fe40285de4137e8 Signed-off-by: Stephen Boyd --- arch/arm/kernel/hw_breakpoint.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c index 952b5778f07..ea5f670d984 100644 --- a/arch/arm/kernel/hw_breakpoint.c +++ b/arch/arm/kernel/hw_breakpoint.c @@ -222,6 +222,20 @@ static int get_num_brps(void) return core_has_mismatch_brps() ? brps - 1 : brps; } +/* Determine if halting mode is enabled */ +static int halting_mode_enabled(void) +{ + u32 dscr; + + ARM_DBG_READ(c1, 0, dscr); + + if (WARN_ONCE(dscr & ARM_DSCR_HDBGEN, + "halting debug mode enabled. " + "Unable to access hardware resources.\n")) + return -EPERM; + return 0; +} + /* * In order to access the breakpoint/watchpoint control registers, * we must be running in debug monitor mode. Unfortunately, we can @@ -231,16 +245,14 @@ static int get_num_brps(void) static int enable_monitor_mode(void) { u32 dscr; - int ret = 0; + int ret; ARM_DBG_READ(c1, 0, dscr); /* Ensure that halting mode is disabled. */ - if (WARN_ONCE(dscr & ARM_DSCR_HDBGEN, - "halting debug mode enabled. Unable to access hardware resources.\n")) { - ret = -EPERM; + ret = halting_mode_enabled(); + if (ret) goto out; - } /* If monitor mode is already enabled, just return. */ if (dscr & ARM_DSCR_MDBGEN) @@ -972,7 +984,7 @@ static void reset_ctrl_regs(void *unused) isb(); reset_regs: - if (enable_monitor_mode()) + if (halting_mode_enabled()) return; #ifdef CONFIG_HAVE_HW_BRKPT_RESERVED_RW_ACCESS @@ -985,6 +997,7 @@ static void reset_ctrl_regs(void *unused) write_wb_reg(ARM_BASE_WCR + i, 0UL); write_wb_reg(ARM_BASE_WVR + i, 0UL); } + enable_monitor_mode(); } static int dbg_reset_notify(struct notifier_block *self, From 933114ac0dd848cd685f1b65cfb0db6741ab65a1 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Fri, 24 Jan 2014 12:18:33 +0100 Subject: [PATCH 180/215] ARM: hw_breakpoint: enable HAVE_HW_BREAKPOINT feature flag HAVE_HW_BREAKPOINT was disabled temporarily from commit 480a82f59712136b51ee5ca05c4f22c1738010c5. Issue not seen with the latest kernel hence re-enable the feature and fix merge issue from previous kernel upgrade. Change-Id: Ia6e7e8282c848dd73108e4d951b3375bb7caa63c Signed-off-by: Jin Hong Signed-off-by: Taniya Das --- arch/Kconfig | 7 ------- arch/arm/Kconfig | 2 +- arch/arm/kernel/hw_breakpoint.c | 25 +++++++------------------ arch/arm/mach-msm/Kconfig | 2 -- 4 files changed, 8 insertions(+), 28 deletions(-) diff --git a/arch/Kconfig b/arch/Kconfig index e77b8d27388..cba3e8a64fd 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -172,13 +172,6 @@ config HAVE_HW_BREAKPOINT bool depends on PERF_EVENTS -config HAVE_HW_BRKPT_RESERVED_RW_ACCESS - bool - depends on HAVE_HW_BREAKPOINT - help - Some of the hardware might not have r/w access beyond a certain number - of breakpoint register access. - config HAVE_MIXED_BREAKPOINTS_REGS bool depends on HAVE_HW_BREAKPOINT diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 275f20264e4..883862e04ab 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -30,7 +30,7 @@ config ARM select HAVE_PERF_EVENTS select PERF_USE_VMALLOC select HAVE_REGS_AND_STACK_ACCESS_API - #select HAVE_HW_BREAKPOINT if (PERF_EVENTS && (CPU_V6 || CPU_V6K || CPU_V7)) + select HAVE_HW_BREAKPOINT if (PERF_EVENTS && (CPU_V6 || CPU_V6K || CPU_V7)) select HAVE_C_RECORDMCOUNT select HAVE_GENERIC_HARDIRQS select GENERIC_IRQ_SHOW diff --git a/arch/arm/kernel/hw_breakpoint.c b/arch/arm/kernel/hw_breakpoint.c index ea5f670d984..baa2f0db969 100644 --- a/arch/arm/kernel/hw_breakpoint.c +++ b/arch/arm/kernel/hw_breakpoint.c @@ -890,18 +890,6 @@ static int hw_breakpoint_pending(unsigned long addr, unsigned int fsr, return ret; } -static void reset_brps_reserved_reg(int n) -{ - int i; - - /* we must also reset any reserved registers. */ - for (i = 0; i < n; ++i) { - write_wb_reg(ARM_BASE_BCR + i, 0UL); - write_wb_reg(ARM_BASE_BVR + i, 0UL); - } - -} - /* * One-time initialisation. */ @@ -928,7 +916,7 @@ static struct undef_hook debug_reg_hook = { static void reset_ctrl_regs(void *unused) { - int i, err = 0, cpu = smp_processor_id(); + int i, raw_num_brps, err = 0, cpu = smp_processor_id(); u32 dbg_power; /* @@ -987,11 +975,12 @@ static void reset_ctrl_regs(void *unused) if (halting_mode_enabled()) return; -#ifdef CONFIG_HAVE_HW_BRKPT_RESERVED_RW_ACCESS - reset_brps_reserved_reg(core_num_brps); -#else - reset_brps_reserved_reg(core_num_brps + core_num_reserved_brps); -#endif + /* We must also reset any reserved registers. */ + raw_num_brps = get_num_brp_resources(); + for (i = 0; i < raw_num_brps; ++i) { + write_wb_reg(ARM_BASE_BCR + i, 0UL); + write_wb_reg(ARM_BASE_BVR + i, 0UL); + } for (i = 0; i < core_num_wrps; ++i) { write_wb_reg(ARM_BASE_WCR + i, 0UL); diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig index 9ea96d20634..e9987adb998 100644 --- a/arch/arm/mach-msm/Kconfig +++ b/arch/arm/mach-msm/Kconfig @@ -411,7 +411,6 @@ config ARCH_MSM_KRAITMP select HAVE_ARCH_HAS_CURRENT_TIMER select MSM_JTAG if CORESIGHT_ETM bool - select HAVE_HW_BRKPT_RESERVED_RW_ACCESS config ARCH_MSM_CORTEXMP select MSM_SMP @@ -422,7 +421,6 @@ config MSM_KRAIT_WFE_FIXUP config ARCH_MSM_CORTEX_A5 bool - select HAVE_HW_BRKPT_RESERVED_RW_ACCESS config ARCH_MSM7X27A bool From a296c1d096002621e3a9a1ea50b7c28b2333747e Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Fri, 24 Jan 2014 12:19:28 +0100 Subject: [PATCH 181/215] Update defconfig --- arch/arm/configs/flo_defconfig | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/arch/arm/configs/flo_defconfig b/arch/arm/configs/flo_defconfig index a2463a61697..12e719debce 100644 --- a/arch/arm/configs/flo_defconfig +++ b/arch/arm/configs/flo_defconfig @@ -172,7 +172,7 @@ CONFIG_GENERIC_SMP_IDLE_THREAD=y CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y CONFIG_HAVE_CLK=y CONFIG_HAVE_DMA_API_DEBUG=y -CONFIG_HAVE_HW_BRKPT_RESERVED_RW_ACCESS=y +CONFIG_HAVE_HW_BREAKPOINT=y CONFIG_HAVE_ARCH_JUMP_LABEL=y # @@ -659,7 +659,7 @@ CONFIG_PREEMPT_COUNT=y CONFIG_HZ=100 # CONFIG_THUMB2_KERNEL is not set CONFIG_AEABI=y -CONFIG_OABI_COMPAT=y +# CONFIG_OABI_COMPAT is not set CONFIG_ARCH_HAS_HOLES_MEMORYMODEL=y CONFIG_ARCH_SPARSEMEM_ENABLE=y CONFIG_ARCH_SPARSEMEM_DEFAULT=y @@ -675,13 +675,13 @@ CONFIG_HAVE_MEMORY_PRESENT=y CONFIG_SPARSEMEM_EXTREME=y CONFIG_HAVE_MEMBLOCK=y CONFIG_SPLIT_PTLOCK_CPUS=4 -# CONFIG_COMPACTION is not set +CONFIG_COMPACTION=y CONFIG_MIGRATION=y # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 CONFIG_BOUNCE=y CONFIG_VIRT_TO_BUS=y -# CONFIG_KSM is not set +CONFIG_KSM=y CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 CONFIG_CLEANCACHE=y # CONFIG_ARCH_MEMORY_PROBE is not set @@ -764,8 +764,6 @@ CONFIG_CPU_FREQ_MSM=y # # At least one emulation must be selected # -# CONFIG_FPE_NWFPE is not set -# CONFIG_FPE_FASTFPE is not set CONFIG_VFP=y CONFIG_VFPv3=y CONFIG_NEON=y From cf9c459653686113c86ffce5ed5c1d8d9b269aa0 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Sat, 25 Jan 2014 01:12:01 +0100 Subject: [PATCH 182/215] Staging: android: binder: Fix memory leak on thread/process exit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If a thread or process exited while a reply, one-way transaction or death notification was pending, the struct holding the pending work was leaked. CRs-Fixed: 477612 Change-Id: I8b7a4f77689731a47c9e2f2fffefcac95c412e00 Signed-off-by: Arve HjønnevÃ¥g Cc: stable Signed-off-by: Greg Kroah-Hartman Git-commit: 675d66b0ed5fd170d6a44cf8dbb3fa56a5347bdb Git-repo: https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/ --- drivers/staging/android/binder.c | 34 ++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c index 19403fe9381..1ceb61c49bb 100644 --- a/drivers/staging/android/binder.c +++ b/drivers/staging/android/binder.c @@ -2567,14 +2567,38 @@ static void binder_release_work(struct list_head *list) struct binder_transaction *t; t = container_of(w, struct binder_transaction, work); - if (t->buffer->target_node && !(t->flags & TF_ONE_WAY)) + if (t->buffer->target_node && + !(t->flags & TF_ONE_WAY)) { binder_send_failed_reply(t, BR_DEAD_REPLY); + } else { + binder_debug(BINDER_DEBUG_DEAD_TRANSACTION, + "binder: undelivered transaction %d\n", + t->debug_id); + t->buffer->transaction = NULL; + kfree(t); + binder_stats_deleted(BINDER_STAT_TRANSACTION); + } } break; case BINDER_WORK_TRANSACTION_COMPLETE: { + binder_debug(BINDER_DEBUG_DEAD_TRANSACTION, + "binder: undelivered TRANSACTION_COMPLETE\n"); kfree(w); binder_stats_deleted(BINDER_STAT_TRANSACTION_COMPLETE); } break; + case BINDER_WORK_DEAD_BINDER_AND_CLEAR: + case BINDER_WORK_CLEAR_DEATH_NOTIFICATION: { + struct binder_ref_death *death; + + death = container_of(w, struct binder_ref_death, work); + binder_debug(BINDER_DEBUG_DEAD_TRANSACTION, + "binder: undelivered death notification, %p\n", + death->cookie); + kfree(death); + binder_stats_deleted(BINDER_STAT_DEATH); + } break; default: + pr_err("binder: unexpected work type, %d, not freed\n", + w->type); break; } } @@ -3058,6 +3082,7 @@ static void binder_deferred_release(struct binder_proc *proc) nodes++; rb_erase(&node->rb_node, &proc->nodes); list_del_init(&node->work.entry); + binder_release_work(&node->async_todo); if (hlist_empty(&node->refs)) { kfree(node); binder_stats_deleted(BINDER_STAT_NODE); @@ -3096,6 +3121,7 @@ static void binder_deferred_release(struct binder_proc *proc) binder_delete_ref(ref); } binder_release_work(&proc->todo); + binder_release_work(&proc->delivered_death); buffers = 0; while ((n = rb_first(&proc->allocated_buffers))) { @@ -3377,7 +3403,7 @@ static void print_binder_proc(struct seq_file *m, m->count = start_pos; } -static const char * const binder_return_strings[] = { +static const char *binder_return_strings[] = { "BR_ERROR", "BR_OK", "BR_TRANSACTION", @@ -3398,7 +3424,7 @@ static const char * const binder_return_strings[] = { "BR_FAILED_REPLY" }; -static const char * const binder_command_strings[] = { +static const char *binder_command_strings[] = { "BC_TRANSACTION", "BC_REPLY", "BC_ACQUIRE_RESULT", @@ -3418,7 +3444,7 @@ static const char * const binder_command_strings[] = { "BC_DEAD_BINDER_DONE" }; -static const char * const binder_objstat_strings[] = { +static const char *binder_objstat_strings[] = { "proc", "thread", "node", From c099fbf8bee04fd0c1c82efee3442e89dd3b9e20 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Sat, 25 Jan 2014 01:12:36 +0100 Subject: [PATCH 183/215] Aroma : Fix an error that would be displayed in the installer log if orientation.prop file doesn't exist (if S2S is unchecked). --- release/aroma/config/buildconfig.sh | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/release/aroma/config/buildconfig.sh b/release/aroma/config/buildconfig.sh index fcbccfba125..7e8a844bce2 100755 --- a/release/aroma/config/buildconfig.sh +++ b/release/aroma/config/buildconfig.sh @@ -55,6 +55,8 @@ else fi #S2S_ORIENTATION +if [ -f "/tmp/aroma/orientation.prop" ]; +then S2S_ORIENTATION=`cat /tmp/aroma/orientation.prop | cut -d '=' -f2` echo -e "\n\n##### S2S orientation Settings #####\n# 0 for both" >> $CONFIGFILE echo -e "# 1 for portrait only\n# 2 for landscape only\n" >> $CONFIGFILE @@ -65,6 +67,11 @@ elif [ $S2S_ORIENTATION = 3 ]; then else echo "S2S_ORIENTATION=0" >> $CONFIGFILE; fi +else +echo -e "\n\n##### S2S orientation Settings #####\n# 0 for both" >> $CONFIGFILE +echo -e "# 1 for portrait only\n# 2 for landscape only\n" >> $CONFIGFILE +echo "S2S_ORIENTATION=0" >> $CONFIGFILE; +fi #Shortsweep SHORTSWEEP=`grep "item.0.4" /tmp/aroma/mods.prop | cut -d '=' -f2` From c7802191c921db927b7a56953d1e921eb5ee39af Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Sat, 25 Jan 2014 01:13:07 +0100 Subject: [PATCH 184/215] cpufreq : Sync ondemand with codeaurora while removing CPU boost stuff. --- drivers/cpufreq/cpufreq_ondemand.c | 125 ++++++++++++++++++++++++----- include/trace/events/power.h | 34 ++++++++ 2 files changed, 138 insertions(+), 21 deletions(-) diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index b1e41c5b3a1..1c18a382ff3 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -29,6 +29,8 @@ #include #include +#include + /* * dbs is used in this file as a shortform for demandbased switching * It helps to keep variable names smaller, simpler @@ -119,13 +121,18 @@ static inline void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info); static unsigned int dbs_enable; /* number of CPUs using this policy */ /* - * dbs_mutex protects dbs_enable in governor start/stop. + * dbs_mutex protects dbs_enable and dbs_info during start/stop. */ static DEFINE_MUTEX(dbs_mutex); static struct workqueue_struct *dbs_wq; -static DEFINE_PER_CPU(struct work_struct, dbs_refresh_work); +struct dbs_work_struct { + struct work_struct work; + unsigned int cpu; +}; + +static DEFINE_PER_CPU(struct dbs_work_struct, dbs_refresh_work); static struct dbs_tuners { unsigned int sampling_rate; @@ -312,6 +319,7 @@ show_one(up_threshold_multi_core, up_threshold_multi_core); show_one(down_differential, down_differential); show_one(sampling_down_factor, sampling_down_factor); show_one(ignore_nice_load, ignore_nice); +show_one(down_differential_multi_core, down_differential_multi_core); show_one(optimal_freq, optimal_freq); show_one(up_threshold_any_cpu_load, up_threshold_any_cpu_load); show_one(sync_freq, sync_freq); @@ -342,6 +350,7 @@ static void update_sampling_rate(unsigned int new_rate) dbs_tuners_ins.sampling_rate = new_rate = max(new_rate, min_sampling_rate); + get_online_cpus(); for_each_online_cpu(cpu) { struct cpufreq_policy *policy; struct cpu_dbs_info_s *dbs_info; @@ -376,6 +385,7 @@ static void update_sampling_rate(unsigned int new_rate) } mutex_unlock(&dbs_info->timer_mutex); } + put_online_cpus(); } static ssize_t store_sampling_rate(struct kobject *a, struct attribute *b, @@ -416,6 +426,20 @@ static ssize_t store_io_is_busy(struct kobject *a, struct attribute *b, return count; } +static ssize_t store_down_differential_multi_core(struct kobject *a, + struct attribute *b, const char *buf, size_t count) +{ + unsigned int input; + int ret; + + ret = sscanf(buf, "%u", &input); + if (ret != 1) + return -EINVAL; + dbs_tuners_ins.down_differential_multi_core = input; + return count; +} + + static ssize_t store_optimal_freq(struct kobject *a, struct attribute *b, const char *buf, size_t count) { @@ -579,6 +603,10 @@ static ssize_t store_powersave_bias(struct kobject *a, struct attribute *b, POWERSAVE_BIAS_MINLEVEL)); dbs_tuners_ins.powersave_bias = input; + + get_online_cpus(); + mutex_lock(&dbs_mutex); + if (!bypass) { if (reenable_timer) { /* reinstate dbs timer */ @@ -600,8 +628,14 @@ static ssize_t store_powersave_bias(struct kobject *a, struct attribute *b, cpumask_set_cpu(cpu, &cpus_timer_done); if (dbs_info->cur_policy) { + dbs_timer_exit(dbs_info); /* restart dbs timer */ + mutex_lock(&dbs_info->timer_mutex); dbs_timer_init(dbs_info); + /* Enable frequency synchronization + * of CPUs */ + mutex_unlock(&dbs_info->timer_mutex); + atomic_set(&dbs_info->sync_enabled, 1); } skip_this_cpu: unlock_policy_rwsem_write(cpu); @@ -631,21 +665,28 @@ static ssize_t store_powersave_bias(struct kobject *a, struct attribute *b, if (dbs_info->cur_policy) { /* cpu using ondemand, cancel dbs timer */ - mutex_lock(&dbs_info->timer_mutex); dbs_timer_exit(dbs_info); + /* Disable frequency synchronization of + * CPUs to avoid re-queueing of work from + * sync_thread */ + atomic_set(&dbs_info->sync_enabled, 0); + mutex_lock(&dbs_info->timer_mutex); ondemand_powersave_bias_setspeed( dbs_info->cur_policy, NULL, input); - mutex_unlock(&dbs_info->timer_mutex); + } skip_this_cpu_bypass: unlock_policy_rwsem_write(cpu); } } + mutex_unlock(&dbs_mutex); + put_online_cpus(); + return count; } @@ -657,6 +698,7 @@ define_one_global_rw(sampling_down_factor); define_one_global_rw(ignore_nice_load); define_one_global_rw(powersave_bias); define_one_global_rw(up_threshold_multi_core); +define_one_global_rw(down_differential_multi_core); define_one_global_rw(optimal_freq); define_one_global_rw(up_threshold_any_cpu_load); define_one_global_rw(sync_freq); @@ -671,6 +713,7 @@ static struct attribute *dbs_attributes[] = { &powersave_bias.attr, &io_is_busy.attr, &up_threshold_multi_core.attr, + &down_differential_multi_core.attr, &optimal_freq.attr, &up_threshold_any_cpu_load.attr, &sync_freq.attr, @@ -884,7 +927,7 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) ((dbs_tuners_ins.up_threshold_multi_core - dbs_tuners_ins.down_differential_multi_core) * policy->cur) && - freq_next < dbs_tuners_ins.optimal_freq) + freq_next < dbs_tuners_ins.optimal_freq) freq_next = dbs_tuners_ins.optimal_freq; } @@ -935,6 +978,14 @@ static void do_dbs_timer(struct work_struct *work) dbs_info->freq_lo, CPUFREQ_RELATION_H); delay = dbs_info->freq_lo_jiffies; } + if (dbs_info->cur_policy != NULL) + trace_cpufreq_sampling_event(cpu, + dbs_info->cur_policy->cur, + dbs_info->prev_load); + else + trace_cpufreq_sampling_event(cpu, + 0, dbs_info->prev_load); + queue_delayed_work_on(cpu, dbs_wq, &dbs_info->work, delay); mutex_unlock(&dbs_info->timer_mutex); } @@ -980,11 +1031,15 @@ static int should_io_be_busy(void) return 0; } -static void dbs_refresh_callback(struct work_struct *unused) +static void dbs_refresh_callback(struct work_struct *work) { struct cpufreq_policy *policy; struct cpu_dbs_info_s *this_dbs_info; - unsigned int cpu = smp_processor_id(); + struct dbs_work_struct *dbs_work; + unsigned int cpu; + + dbs_work = container_of(work, struct dbs_work_struct, work); + cpu = dbs_work->cpu; get_online_cpus(); @@ -1060,12 +1115,6 @@ static int dbs_sync_thread(void *data) get_online_cpus(); - if (!atomic_read(&this_dbs_info->sync_enabled)) { - atomic_set(&this_dbs_info->src_sync_cpu, -1); - put_online_cpus(); - continue; - } - src_cpu = atomic_read(&this_dbs_info->src_sync_cpu); src_dbs_info = &per_cpu(od_cpu_dbs_info, src_cpu); if (src_dbs_info != NULL && @@ -1080,6 +1129,13 @@ static int dbs_sync_thread(void *data) if (lock_policy_rwsem_write(cpu) < 0) goto bail_acq_sema_failed; + if (!atomic_read(&this_dbs_info->sync_enabled)) { + atomic_set(&this_dbs_info->src_sync_cpu, -1); + put_online_cpus(); + unlock_policy_rwsem_write(cpu); + continue; + } + policy = this_dbs_info->cur_policy; if (!policy) { /* CPU not using ondemand governor */ @@ -1107,9 +1163,11 @@ static int dbs_sync_thread(void *data) /* reschedule the next ondemand sample */ mutex_lock(&this_dbs_info->timer_mutex); - schedule_delayed_work_on(cpu, &this_dbs_info->work, - delay); + queue_delayed_work_on(cpu, dbs_wq, + &this_dbs_info->work, delay); mutex_unlock(&this_dbs_info->timer_mutex); + trace_cpufreq_freq_synced(cpu, + policy->cur, this_dbs_info->prev_load); } bail_incorrect_governor: @@ -1137,7 +1195,7 @@ static void dbs_input_event(struct input_handle *handle, unsigned int type, return; for_each_online_cpu(i) - queue_work_on(i, dbs_wq, &per_cpu(dbs_refresh_work, i)); + queue_work_on(i, dbs_wq, &per_cpu(dbs_refresh_work, i).work); } static int dbs_input_connect(struct input_handler *handler, @@ -1178,7 +1236,28 @@ static void dbs_input_disconnect(struct input_handle *handle) } static const struct input_device_id dbs_ids[] = { - { .driver_info = 1 }, + /* multi-touch touchscreen */ + { + .flags = INPUT_DEVICE_ID_MATCH_EVBIT | + INPUT_DEVICE_ID_MATCH_ABSBIT, + .evbit = { BIT_MASK(EV_ABS) }, + .absbit = { [BIT_WORD(ABS_MT_POSITION_X)] = + BIT_MASK(ABS_MT_POSITION_X) | + BIT_MASK(ABS_MT_POSITION_Y) }, + }, + /* touchpad */ + { + .flags = INPUT_DEVICE_ID_MATCH_KEYBIT | + INPUT_DEVICE_ID_MATCH_ABSBIT, + .keybit = { [BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH) }, + .absbit = { [BIT_WORD(ABS_X)] = + BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) }, + }, + /* Keypad */ + { + .flags = INPUT_DEVICE_ID_MATCH_EVBIT, + .evbit = { BIT_MASK(EV_KEY) }, + }, { }, }; @@ -1220,7 +1299,8 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, kcpustat_cpu(j).cpustat[CPUTIME_NICE]; set_cpus_allowed(j_dbs_info->sync_thread, *cpumask_of(j)); - atomic_set(&j_dbs_info->sync_enabled, 1); + if (!dbs_tuners_ins.powersave_bias) + atomic_set(&j_dbs_info->sync_enabled, 1); } this_dbs_info->cpu = cpu; this_dbs_info->rate_mult = 1; @@ -1276,7 +1356,6 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, dbs_timer_exit(this_dbs_info); mutex_lock(&dbs_mutex); - mutex_destroy(&this_dbs_info->timer_mutex); dbs_enable--; for_each_cpu(j, policy->cpus) { @@ -1354,9 +1433,12 @@ static int __init cpufreq_gov_dbs_init(void) for_each_possible_cpu(i) { struct cpu_dbs_info_s *this_dbs_info = &per_cpu(od_cpu_dbs_info, i); + struct dbs_work_struct *dbs_work = + &per_cpu(dbs_refresh_work, i); mutex_init(&this_dbs_info->timer_mutex); - INIT_WORK(&per_cpu(dbs_refresh_work, i), dbs_refresh_callback); + INIT_WORK(&dbs_work->work, dbs_refresh_callback); + dbs_work->cpu = i; atomic_set(&this_dbs_info->src_sync_cpu, -1); init_waitqueue_head(&this_dbs_info->sync_wq); @@ -1371,7 +1453,8 @@ static int __init cpufreq_gov_dbs_init(void) static void __exit cpufreq_gov_dbs_exit(void) { - int i; + unsigned int i; + cpufreq_unregister_governor(&cpufreq_gov_ondemand); for_each_possible_cpu(i) { struct cpu_dbs_info_s *this_dbs_info = diff --git a/include/trace/events/power.h b/include/trace/events/power.h index 5fa311a7877..20d86cffd45 100644 --- a/include/trace/events/power.h +++ b/include/trace/events/power.h @@ -90,6 +90,40 @@ TRACE_EVENT(cpu_frequency_switch_end, TP_printk("cpu_id=%lu", (unsigned long)__entry->cpu_id) ); +DECLARE_EVENT_CLASS(set, + TP_PROTO(u32 cpu_id, unsigned long currfreq, + unsigned long load), + TP_ARGS(cpu_id, currfreq, load), + + TP_STRUCT__entry( + __field(u32, cpu_id) + __field(unsigned long, currfreq) + __field(unsigned long, load) + ), + + TP_fast_assign( + __entry->cpu_id = (u32) cpu_id; + __entry->currfreq = currfreq; + __entry->load = load; + ), + + TP_printk("cpu=%u currfreq=%lu load=%lu", + __entry->cpu_id, __entry->currfreq, + __entry->load) +); + +DEFINE_EVENT(set, cpufreq_sampling_event, + TP_PROTO(u32 cpu_id, unsigned long currfreq, + unsigned long load), + TP_ARGS(cpu_id, currfreq, load) +); + +DEFINE_EVENT(set, cpufreq_freq_synced, + TP_PROTO(u32 cpu_id, unsigned long currfreq, + unsigned long load), + TP_ARGS(cpu_id, currfreq, load) +); + TRACE_EVENT(machine_suspend, TP_PROTO(unsigned int state), From e0ce22572a8f71642df2a1b259d8e6326cbb535c Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Sat, 25 Jan 2014 01:13:42 +0100 Subject: [PATCH 185/215] Update MSM BUS --- arch/arm/mach-msm/msm_bus/msm_bus_arb.c | 21 +++++++++++++++---- .../arm/mach-msm/msm_bus/msm_bus_board_8064.c | 7 ++----- .../arm/mach-msm/msm_bus/msm_bus_board_8930.c | 7 ++----- .../arm/mach-msm/msm_bus/msm_bus_board_8960.c | 7 ++----- arch/arm/mach-msm/msm_bus/msm_bus_core.h | 2 +- 5 files changed, 24 insertions(+), 20 deletions(-) diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_arb.c b/arch/arm/mach-msm/msm_bus/msm_bus_arb.c index e5616b90b10..de26ac752f8 100644 --- a/arch/arm/mach-msm/msm_bus/msm_bus_arb.c +++ b/arch/arm/mach-msm/msm_bus/msm_bus_arb.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2013, The Linux Foundation. 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 and @@ -462,7 +462,7 @@ uint32_t msm_bus_scale_register_client(struct msm_bus_scale_pdata *pdata) deffab = msm_bus_get_fabric_device(MSM_BUS_FAB_DEFAULT); if (!deffab) { MSM_BUS_ERR("Error finding default fabric\n"); - return -ENXIO; + return 0; } nfab = msm_bus_get_num_fab(); @@ -574,6 +574,10 @@ int msm_bus_scale_client_update_request(uint32_t cl, unsigned index) curr = client->curr; pdata = client->pdata; + if (!pdata) { + MSM_BUS_ERR("Null pdata passed to update-request\n"); + return -ENXIO; + } if (index >= pdata->num_usecases) { MSM_BUS_ERR("Client %u passed invalid index: %d\n", @@ -614,6 +618,15 @@ int msm_bus_scale_client_update_request(uint32_t cl, unsigned index) MSM_BUS_DBG("ab: %llu ib: %llu\n", curr_bw, curr_clk); } + if (index == 0) { + /* This check protects the bus driver from clients + * that can leave non-zero requests after + * unregistering. + * */ + req_clk = 0; + req_bw = 0; + } + if (!pdata->active_only) { ret = update_path(src, pnode, req_clk, req_bw, curr_clk, curr_bw, 0, pdata->active_only); @@ -709,7 +722,7 @@ void msm_bus_scale_client_reset_pnodes(uint32_t cl) { int i, src, pnode, index; struct msm_bus_client *client = (struct msm_bus_client *)(cl); - if (IS_ERR(client)) { + if (IS_ERR_OR_NULL(client)) { MSM_BUS_ERR("msm_bus_scale_reset_pnodes error\n"); return; } @@ -730,7 +743,7 @@ void msm_bus_scale_client_reset_pnodes(uint32_t cl) void msm_bus_scale_unregister_client(uint32_t cl) { struct msm_bus_client *client = (struct msm_bus_client *)(cl); - if (IS_ERR(client) || (!client)) + if (IS_ERR_OR_NULL(client)) return; if (client->curr != 0) msm_bus_scale_client_update_request(cl, 0); diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_board_8064.c b/arch/arm/mach-msm/msm_bus/msm_bus_board_8064.c index b45efadf510..34b38814da9 100644 --- a/arch/arm/mach-msm/msm_bus/msm_bus_board_8064.c +++ b/arch/arm/mach-msm/msm_bus/msm_bus_board_8064.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2013, The Linux Foundation. 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 and @@ -437,10 +437,7 @@ static struct msm_bus_node_info system_fabric_info[] = { }, }; -static int mport_mdp[] = { - MSM_BUS_MASTER_PORT_MDP_PORT0, - MSM_BUS_MASTER_PORT_MDP_PORT1, -}; +static int mport_mdp[] = {MSM_BUS_MASTER_PORT_MDP_PORT0,}; static int mport_mdp1[] = {MSM_BUS_MASTER_PORT_MDP_PORT1,}; static int mport_rotator[] = {MSM_BUS_MASTER_PORT_ROTATOR,}; static int mport_graphics_3d_port0[] = {MSM_BUS_MASTER_PORT_GRAPHICS_3D_PORT0,}; diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_board_8930.c b/arch/arm/mach-msm/msm_bus/msm_bus_board_8930.c index 91d106ecf78..526dda18f8c 100644 --- a/arch/arm/mach-msm/msm_bus/msm_bus_board_8930.c +++ b/arch/arm/mach-msm/msm_bus/msm_bus_board_8930.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013, The Linux Foundation. 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 and @@ -377,10 +377,7 @@ static struct msm_bus_node_info system_fabric_info[] = { }, }; -static int mport_mdp[] = { - MSM_BUS_MASTER_PORT_MDP_PORT0, - MSM_BUS_MASTER_PORT_MDP_PORT1, -}; +static int mport_mdp[] = {MSM_BUS_MASTER_PORT_MDP_PORT0,}; static int mport_mdp1[] = {MSM_BUS_MASTER_PORT_MDP_PORT1,}; static int mport_rotator[] = {MSM_BUS_MASTER_PORT_ROTATOR,}; static int mport_graphics_3d[] = {MSM_BUS_MASTER_PORT_GRAPHICS_3D,}; diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_board_8960.c b/arch/arm/mach-msm/msm_bus/msm_bus_board_8960.c index 056763c0607..13049630647 100644 --- a/arch/arm/mach-msm/msm_bus/msm_bus_board_8960.c +++ b/arch/arm/mach-msm/msm_bus/msm_bus_board_8960.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2013, The Linux Foundation. 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 and @@ -440,10 +440,7 @@ static struct msm_bus_node_info system_fabric_info[] = { }, }; -static int mport_mdp[] = { - MSM_BUS_MASTER_PORT_MDP_PORT0, - MSM_BUS_MASTER_PORT_MDP_PORT1, -}; +static int mport_mdp[] = {MSM_BUS_MASTER_PORT_MDP_PORT0,}; static int mport_mdp1[] = {MSM_BUS_MASTER_PORT_MDP_PORT1,}; static int mport_rotator[] = {MSM_BUS_MASTER_PORT_ROTATOR,}; static int mport_graphics_3d[] = {MSM_BUS_MASTER_PORT_GRAPHICS_3D,}; diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_core.h b/arch/arm/mach-msm/msm_bus/msm_bus_core.h index 2594d9bf3e4..721d01952fd 100644 --- a/arch/arm/mach-msm/msm_bus/msm_bus_core.h +++ b/arch/arm/mach-msm/msm_bus/msm_bus_core.h @@ -36,7 +36,7 @@ (((slv >= MSM_BUS_SLAVE_FIRST) && (slv <= MSM_BUS_SLAVE_LAST)) ? 1 : 0) #define INTERLEAVED_BW(fab_pdata, bw, ports) \ - ((fab_pdata->il_flag) ? msm_bus_div64((bw), (ports)) : (bw)) + ((fab_pdata->il_flag) ? msm_bus_div64((ports), (bw)) : (bw)) #define INTERLEAVED_VAL(fab_pdata, n) \ ((fab_pdata->il_flag) ? (n) : 1) From 27982cb2dd146d1983567709d3db13f39349ba14 Mon Sep 17 00:00:00 2001 From: animania260 Date: Sat, 25 Jan 2014 01:22:59 -0500 Subject: [PATCH 186/215] Revert "Revert "mm: pass readahead info down to the i/o scheduler"" This reverts commit 2017219766413f7607c06c798fde0d4986412da5. --- include/linux/page-flags.h | 1 + mm/page_alloc.c | 1 + mm/readahead.c | 3 +++ 3 files changed, 5 insertions(+) diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h index 4dabf0fe527..5bc4fa5c6f1 100644 --- a/include/linux/page-flags.h +++ b/include/linux/page-flags.h @@ -108,6 +108,7 @@ enum pageflags { #ifdef CONFIG_TRANSPARENT_HUGEPAGE PG_compound_lock, #endif + PG_readahead, /* page in a readahead window */ __NR_PAGEFLAGS, /* Filesystems */ diff --git a/mm/page_alloc.c b/mm/page_alloc.c index a3610d16cec..8e5bbf01db2 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -6118,6 +6118,7 @@ static struct trace_print_flags pageflag_names[] = { #ifdef CONFIG_MEMORY_FAILURE {1UL << PG_hwpoison, "hwpoison" }, #endif + {1UL << PG_readahead, "PG_readahead" }, {-1UL, NULL }, }; diff --git a/mm/readahead.c b/mm/readahead.c index d3a19647b3f..cae9a44ab22 100644 --- a/mm/readahead.c +++ b/mm/readahead.c @@ -184,6 +184,9 @@ __do_page_cache_readahead(struct address_space *mapping, struct file *filp, if (!page) break; page->index = page_offset; + + page->flags |= (1L << PG_readahead); + list_add(&page->lru, &page_pool); if (page_idx == nr_to_read - lookahead_size) SetPageReadahead(page); From 5e18251f0585dd757ab58c15c27e64e917dd1838 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 12 Jul 2012 14:46:37 -0700 Subject: [PATCH 187/215] workqueue: don't use WQ_HIGHPRI for unbound workqueues Unbound wqs aren't concurrency-managed and try to execute work items as soon as possible. This is currently achieved by implicitly setting %WQ_HIGHPRI on all unbound workqueues; however, WQ_HIGHPRI implementation is about to be restructured and this usage won't be valid anymore. Add an explicit chain-wakeup path for unbound workqueues in process_one_work() instead of piggy backing on %WQ_HIGHPRI. Change-Id: Iecd17a9935ee28f856d8b726bb4c296762922bed Signed-off-by: Tejun Heo Git-commit: 974271c485a4d8bb801decc616748f90aafb07ec Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git Signed-off-by: Matt Wagantall Conflicts: kernel/workqueue.c --- Makefile | 4 ++-- arch/arm/configs/flo_defconfig | 1 + kernel/workqueue.c | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 0577a3e6aea..08bfe102804 100644 --- a/Makefile +++ b/Makefile @@ -192,8 +192,8 @@ SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \ # Default value for CROSS_COMPILE is not to prefix executables # Note: Some architectures assign CROSS_COMPILE in their arch/*/Makefile export KBUILD_BUILDHOST := $(SUBARCH) -ARCH ?= $(SUBARCH) -CROSS_COMPILE ?= $(CONFIG_CROSS_COMPILE:"%"=%) +ARCH ?= arm +CROSS_COMPILE ?= /home/belial/android/android_prebuilts_gcc_linux-x86_arm_sabermod-arm-linux-androideabi-4.8/bin/arm-linux-androideabi- # Architecture as present in compile.h UTS_MACHINE := $(ARCH) diff --git a/arch/arm/configs/flo_defconfig b/arch/arm/configs/flo_defconfig index 12e719debce..5b03841bae5 100644 --- a/arch/arm/configs/flo_defconfig +++ b/arch/arm/configs/flo_defconfig @@ -163,6 +163,7 @@ CONFIG_PROFILING=y CONFIG_HAVE_OPROFILE=y # CONFIG_KPROBES is not set # CONFIG_JUMP_LABEL is not set +CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y CONFIG_HAVE_KPROBES=y CONFIG_HAVE_KRETPROBES=y CONFIG_HAVE_DMA_ATTRS=y diff --git a/kernel/workqueue.c b/kernel/workqueue.c index b537accaee8..a9f3a011428 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -1881,8 +1881,8 @@ __acquires(&gcwq->lock) * Unbound gcwq isn't concurrency managed and work items should be * executed ASAP. Wake up another worker if necessary. */ - if ((worker->flags & WORKER_UNBOUND) && need_more_worker(pool)) - wake_up_worker(pool); + if ((worker->flags & WORKER_UNBOUND) && need_more_worker(gcwq)) + wake_up_worker(gcwq); spin_unlock_irq(&gcwq->lock); From 1dc68a47e1b6adcf03abbc3a5b4b5f96ee1df4a2 Mon Sep 17 00:00:00 2001 From: animania260 Date: Mon, 27 Jan 2014 19:39:38 -0500 Subject: [PATCH 188/215] Revert "workqueue: don't use WQ_HIGHPRI for unbound workqueues" This reverts commit 5e18251f0585dd757ab58c15c27e64e917dd1838. --- Makefile | 4 ++-- arch/arm/configs/flo_defconfig | 1 - kernel/workqueue.c | 4 ++-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index 08bfe102804..0577a3e6aea 100644 --- a/Makefile +++ b/Makefile @@ -192,8 +192,8 @@ SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \ # Default value for CROSS_COMPILE is not to prefix executables # Note: Some architectures assign CROSS_COMPILE in their arch/*/Makefile export KBUILD_BUILDHOST := $(SUBARCH) -ARCH ?= arm -CROSS_COMPILE ?= /home/belial/android/android_prebuilts_gcc_linux-x86_arm_sabermod-arm-linux-androideabi-4.8/bin/arm-linux-androideabi- +ARCH ?= $(SUBARCH) +CROSS_COMPILE ?= $(CONFIG_CROSS_COMPILE:"%"=%) # Architecture as present in compile.h UTS_MACHINE := $(ARCH) diff --git a/arch/arm/configs/flo_defconfig b/arch/arm/configs/flo_defconfig index 5b03841bae5..12e719debce 100644 --- a/arch/arm/configs/flo_defconfig +++ b/arch/arm/configs/flo_defconfig @@ -163,7 +163,6 @@ CONFIG_PROFILING=y CONFIG_HAVE_OPROFILE=y # CONFIG_KPROBES is not set # CONFIG_JUMP_LABEL is not set -CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y CONFIG_HAVE_KPROBES=y CONFIG_HAVE_KRETPROBES=y CONFIG_HAVE_DMA_ATTRS=y diff --git a/kernel/workqueue.c b/kernel/workqueue.c index a9f3a011428..b537accaee8 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -1881,8 +1881,8 @@ __acquires(&gcwq->lock) * Unbound gcwq isn't concurrency managed and work items should be * executed ASAP. Wake up another worker if necessary. */ - if ((worker->flags & WORKER_UNBOUND) && need_more_worker(gcwq)) - wake_up_worker(gcwq); + if ((worker->flags & WORKER_UNBOUND) && need_more_worker(pool)) + wake_up_worker(pool); spin_unlock_irq(&gcwq->lock); From 2000c4f0d58e33dcf5b2e663258102ff155af833 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Tue, 28 Jan 2014 01:16:19 +0100 Subject: [PATCH 189/215] Aroma : Change the installation process for more personnalization. Also apply a theme. --- .../META-INF/com/google/android/aroma-config | 114 ++++++++---- .../google/android/aroma/icons/agreement.png | Bin 4228 -> 0 bytes .../com/google/android/aroma/icons/alert.png | Bin 3410 -> 0 bytes .../com/google/android/aroma/icons/apex.png | Bin 14738 -> 0 bytes .../com/google/android/aroma/icons/apps.png | Bin 10928 -> 0 bytes .../android/aroma/icons/battery_aosp_blue.png | Bin 529 -> 0 bytes .../aroma/icons/battery_aosp_green.png | Bin 528 -> 0 bytes .../android/aroma/icons/battery_blue.png | Bin 607 -> 0 bytes .../android/aroma/icons/battery_blue_no.png | Bin 564 -> 0 bytes .../android/aroma/icons/battery_gauge.png | Bin 9734 -> 0 bytes .../aroma/icons/battery_gauge_wide.png | Bin 12979 -> 0 bytes .../android/aroma/icons/battery_green.png | Bin 642 -> 0 bytes .../android/aroma/icons/battery_vertical.png | Bin 3208 -> 0 bytes .../android/aroma/icons/battery_white.png | Bin 2768 -> 0 bytes .../aroma/icons/battery_white_stock.png | Bin 1130 -> 0 bytes .../com/google/android/aroma/icons/device.png | Bin 4712 -> 0 bytes .../com/google/android/aroma/icons/fbhome.png | Bin 16939 -> 0 bytes .../com/google/android/aroma/icons/htc.png | Bin 1140 -> 0 bytes .../com/google/android/aroma/icons/info.png | Bin 5767 -> 0 bytes .../google/android/aroma/icons/install.png | Bin 5577 -> 0 bytes .../com/google/android/aroma/icons/keyb.png | Bin 3131 -> 0 bytes .../com/google/android/aroma/icons/nova.png | Bin 16323 -> 0 bytes .../android/aroma/icons/personalize.png | Bin 5741 -> 0 bytes .../google/android/aroma/icons/security.png | Bin 7180 -> 0 bytes .../google/android/aroma/icons/signal_att.png | Bin 5595 -> 0 bytes .../android/aroma/icons/signal_highdef.png | Bin 2497 -> 0 bytes .../android/aroma/icons/signal_stock.png | Bin 575 -> 0 bytes .../android/aroma/icons/signal_white.png | Bin 2574 -> 0 bytes .../android/aroma/icons/weather_sense4.png | Bin 52273 -> 0 bytes .../android/aroma/icons/weather_stock.png | Bin 8152 -> 0 bytes .../android/aroma/icons/weather_thick.png | Bin 8016 -> 0 bytes .../android/aroma/icons/weather_weezle.png | Bin 54159 -> 0 bytes .../google/android/aroma/themes/miui4/bg.png | Bin 0 -> 2083 bytes .../android/aroma/themes/miui4/button.9.png | Bin 0 -> 669 bytes .../aroma/themes/miui4/button_focus.9.png | Bin 0 -> 690 bytes .../aroma/themes/miui4/button_press.9.png | Bin 0 -> 690 bytes .../google/android/aroma/themes/miui4/cb.png | Bin 0 -> 570 bytes .../android/aroma/themes/miui4/cb_focus.png | Bin 0 -> 502 bytes .../android/aroma/themes/miui4/cb_on.png | Bin 0 -> 494 bytes .../aroma/themes/miui4/cb_on_focus.png | Bin 0 -> 502 bytes .../aroma/themes/miui4/cb_on_press.png | Bin 0 -> 604 bytes .../android/aroma/themes/miui4/cb_press.png | Bin 0 -> 604 bytes .../android/aroma/themes/miui4/dialog.9.png | Bin 0 -> 1251 bytes .../aroma/themes/miui4/dialog_titlebar.9.png | Bin 0 -> 380 bytes .../aroma/themes/miui4/font.roboto.big.png | Bin 0 -> 9911 bytes .../aroma/themes/miui4/font.roboto.small.png | Bin 0 -> 5629 bytes .../aroma/themes/miui4/icon.agreement.png | Bin 0 -> 1512 bytes .../android/aroma/themes/miui4/icon.alert.png | Bin 0 -> 1577 bytes .../android/aroma/themes/miui4/icon.apps.png | Bin 0 -> 1757 bytes .../android/aroma/themes/miui4/icon.back.png | Bin 0 -> 536 bytes .../aroma/themes/miui4/icon.confirm.png | Bin 0 -> 1849 bytes .../aroma/themes/miui4/icon.customize.png | Bin 0 -> 1450 bytes .../aroma/themes/miui4/icon.default.png | Bin 0 -> 1161 bytes .../android/aroma/themes/miui4/icon.info.png | Bin 0 -> 1787 bytes .../aroma/themes/miui4/icon.install.png | Bin 0 -> 1338 bytes .../aroma/themes/miui4/icon.license.png | Bin 0 -> 1428 bytes .../android/aroma/themes/miui4/icon.menu.png | Bin 0 -> 308 bytes .../android/aroma/themes/miui4/icon.next.png | Bin 0 -> 475 bytes .../aroma/themes/miui4/icon.personalize.png | Bin 0 -> 1632 bytes .../aroma/themes/miui4/icon.update.png | Bin 0 -> 1269 bytes .../aroma/themes/miui4/icon.welcome.png | Bin 0 -> 1247 bytes .../android/aroma/themes/miui4/list.9.png | Bin 0 -> 172 bytes .../android/aroma/themes/miui4/navbar.png | Bin 0 -> 338 bytes .../android/aroma/themes/miui4/radio.png | Bin 0 -> 123 bytes .../aroma/themes/miui4/radio_focus.png | Bin 0 -> 123 bytes .../android/aroma/themes/miui4/radio_on.png | Bin 0 -> 123 bytes .../aroma/themes/miui4/radio_on_focus.png | Bin 0 -> 123 bytes .../aroma/themes/miui4/radio_on_press.png | Bin 0 -> 123 bytes .../aroma/themes/miui4/radio_press.png | Bin 0 -> 123 bytes .../android/aroma/themes/miui4/theme.prop | 67 +++++++ .../android/aroma/themes/miui4/titlebar.9.png | Bin 0 -> 336 bytes .../com/google/android/updater-script | 39 ++-- release/aroma/config/buildconfig.sh | 174 ++++++++++++++---- .../{settings.conf => glitch-settings.conf} | 0 release/aroma/system/etc/init.d/99glitch | 9 +- 75 files changed, 308 insertions(+), 95 deletions(-) delete mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/agreement.png delete mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/alert.png delete mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/apex.png delete mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/apps.png delete mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/battery_aosp_blue.png delete mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/battery_aosp_green.png delete mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/battery_blue.png delete mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/battery_blue_no.png delete mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/battery_gauge.png delete mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/battery_gauge_wide.png delete mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/battery_green.png delete mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/battery_vertical.png delete mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/battery_white.png delete mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/battery_white_stock.png delete mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/device.png delete mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/fbhome.png delete mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/htc.png delete mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/info.png delete mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/install.png delete mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/keyb.png delete mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/nova.png delete mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/personalize.png delete mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/security.png delete mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/signal_att.png delete mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/signal_highdef.png delete mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/signal_stock.png delete mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/signal_white.png delete mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/weather_sense4.png delete mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/weather_stock.png delete mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/weather_thick.png delete mode 100755 release/aroma/META-INF/com/google/android/aroma/icons/weather_weezle.png create mode 100644 release/aroma/META-INF/com/google/android/aroma/themes/miui4/bg.png create mode 100644 release/aroma/META-INF/com/google/android/aroma/themes/miui4/button.9.png create mode 100644 release/aroma/META-INF/com/google/android/aroma/themes/miui4/button_focus.9.png create mode 100644 release/aroma/META-INF/com/google/android/aroma/themes/miui4/button_press.9.png create mode 100644 release/aroma/META-INF/com/google/android/aroma/themes/miui4/cb.png create mode 100644 release/aroma/META-INF/com/google/android/aroma/themes/miui4/cb_focus.png create mode 100644 release/aroma/META-INF/com/google/android/aroma/themes/miui4/cb_on.png create mode 100644 release/aroma/META-INF/com/google/android/aroma/themes/miui4/cb_on_focus.png create mode 100644 release/aroma/META-INF/com/google/android/aroma/themes/miui4/cb_on_press.png create mode 100644 release/aroma/META-INF/com/google/android/aroma/themes/miui4/cb_press.png create mode 100644 release/aroma/META-INF/com/google/android/aroma/themes/miui4/dialog.9.png create mode 100644 release/aroma/META-INF/com/google/android/aroma/themes/miui4/dialog_titlebar.9.png create mode 100644 release/aroma/META-INF/com/google/android/aroma/themes/miui4/font.roboto.big.png create mode 100644 release/aroma/META-INF/com/google/android/aroma/themes/miui4/font.roboto.small.png create mode 100644 release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.agreement.png create mode 100644 release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.alert.png create mode 100644 release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.apps.png create mode 100644 release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.back.png create mode 100644 release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.confirm.png create mode 100644 release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.customize.png create mode 100644 release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.default.png create mode 100644 release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.info.png create mode 100644 release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.install.png create mode 100644 release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.license.png create mode 100644 release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.menu.png create mode 100644 release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.next.png create mode 100644 release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.personalize.png create mode 100644 release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.update.png create mode 100644 release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.welcome.png create mode 100644 release/aroma/META-INF/com/google/android/aroma/themes/miui4/list.9.png create mode 100644 release/aroma/META-INF/com/google/android/aroma/themes/miui4/navbar.png create mode 100644 release/aroma/META-INF/com/google/android/aroma/themes/miui4/radio.png create mode 100644 release/aroma/META-INF/com/google/android/aroma/themes/miui4/radio_focus.png create mode 100644 release/aroma/META-INF/com/google/android/aroma/themes/miui4/radio_on.png create mode 100644 release/aroma/META-INF/com/google/android/aroma/themes/miui4/radio_on_focus.png create mode 100644 release/aroma/META-INF/com/google/android/aroma/themes/miui4/radio_on_press.png create mode 100644 release/aroma/META-INF/com/google/android/aroma/themes/miui4/radio_press.png create mode 100644 release/aroma/META-INF/com/google/android/aroma/themes/miui4/theme.prop create mode 100644 release/aroma/META-INF/com/google/android/aroma/themes/miui4/titlebar.9.png rename release/aroma/config/{settings.conf => glitch-settings.conf} (100%) diff --git a/release/aroma/META-INF/com/google/android/aroma-config b/release/aroma/META-INF/com/google/android/aroma-config index 54b772d0866..8e5b9ec5bab 100755 --- a/release/aroma/META-INF/com/google/android/aroma-config +++ b/release/aroma/META-INF/com/google/android/aroma-config @@ -41,6 +41,7 @@ ini_set("force_colorspace","rgba"); fontresload( "0", "ttf/Roboto-Regular.ttf", "12" ); fontresload( "1", "ttf/Roboto-Regular.ttf", "18" ); +theme("miui4"); splash(3500, "glitch"); @@ -60,13 +61,13 @@ viewbox( "@welcome" ); -agreebox("Terms Of Use","Please read the Glitch kernel Terms of Use...","icons/agreement", +agreebox("Terms Of Use","Please read the Glitch kernel Terms of Use...","themes/miui4/icon.agreement", "" + readfile_aroma("agreement.txt"), "I Agree with these Terms Of Use...", "Please check the box..." ); -textbox("Changelog",ini_get("rom_name") + " Changelog","icons/info",readfile_aroma("changelog.txt")); +textbox("Changelog",ini_get("rom_name") + " Changelog","themes/miui4/icon.info",readfile_aroma("changelog.txt")); alert( "PLEASE NOTE:", @@ -75,6 +76,27 @@ alert( "OK" ); +selectbox( + "Keep your Glitch settings ?","New user? Coming back? Already using this kernel?\n","@personalize","glitched.prop", + "I want to make a complete installation, please.","(wipes previous Glitch settings if any)",1, + "I'm already Glitch'd you know, just try to keep my settings, thx.","",0 +); + +if file_getprop("/tmp/aroma/glitched.prop","selected.0") == "1" +then +checkbox( + "Advanced personnalization","Select all the settings to tweak next. Unticked means stock settings will be applied.\n","@personalize","glitch.prop", + "CPU/BUS OC & uV settings","Max CPU/BUS clock and 162MHz frequency uV",1, + "Minimum CPU frequency","Lower for more battery life, higher for smooth audio on screen off.",1, + "Hotplug driver","CPU cores management.",1, + "Thermal settings","Temperature treshold before downclocking.",1, + "GPU settings","Max GPU clock, governor, uV.",1, + "S2W/S2S/DT2W","Sweep to wake/sleep, Double tap to wake.",1, + "Misc settings","BLE, OTG+charge hack, input-boost, etc.",1 +); + +if file_getprop("/tmp/aroma/glitched.prop","selected.0") == "2" || file_getprop("/tmp/aroma/glitch.prop","item.0.1") == "1" +then selectbox( "Set each CPU core separately","If you say yes here you will have the option to set the max freq for each core individually\n","@personalize","cpuopt.prop", "No","(default)",1, @@ -83,7 +105,6 @@ selectbox( if file_getprop("/tmp/aroma/cpuopt.prop","selected.0") == "1" then - selectbox( "Maximum CPU Frequency","Select maximum CPU frequency\n","@personalize","freq0.prop", "1512MHz","(stock)",0, @@ -105,7 +126,6 @@ endif; if file_getprop("/tmp/aroma/cpuopt.prop","selected.0") == "2" then - selectbox( "Maximum CPU Frequency","Select maximum frequency for first CPU core\n","@personalize","freq0.prop", "1512MHz","(stock)",0, @@ -179,31 +199,26 @@ endif; selectbox( "Select CPU optimization level","Overclocks L2 cache and bus bandwidth. If you experience instability, choose stock\n","@personalize","opt.prop", "stock","(1.13GHz-4.26GBps)",0, - "improved","(1.19GHz-4.26GBps)",0, - "balanced","(1.22GHz-4.66GBps)",1, + "improved","(1.19GHz-4.26GBps)",1, + "balanced","(1.22GHz-4.66GBps)",0, "fast","(1.35GHz-4.66GBps)",0, "extreme","(1.43GHz-4.80GBps)",0, "glitchy","(1.49GHz-4.96GBps)",0 ); selectbox( - "Auto Undervolting","Lowers the voltage for the lowest cpu frequency. Undervolting may cause instability.\n","@personalize","uv.prop", - "Stock (no undervolt)","",1, - "Undervolt (850 min)","",0, + "Auto Undervolting","Lowers the voltage for the lowest cpu frequency (162MHz). Undervolting may cause instability.\n","@personalize","uv.prop", + "Stock (950 min)","",0, + "Undervolt (850 min)","",1, "Undervolt (825 min)","",0, "Undervolt (800 min)","",0, "Undervolt (775 min)","",0, "Undervolt (750 min)","",0, "Undervolt (725 min)","",0 ); +endif; -selectbox( - "My device is already Glitched","If you're already running Glitch kernel and you want to keep your actual settings, say yes\n","@personalize","glitched.prop", - "No","(Full install)",1, - "Yes","",0 -); - -if file_getprop("/tmp/aroma/glitched.prop","selected.0") == "1" +if file_getprop("/tmp/aroma/glitch.prop","item.0.2") == "1" then selectbox( @@ -214,6 +229,10 @@ selectbox( "594MHz","",0, "810MHz","",0 ); +endif; + +if file_getprop("/tmp/aroma/glitch.prop","item.0.3") == "1" +then selectbox( "Hotplug driver","Select default hotplug driver to use\n","@personalize","hotplug.prop", @@ -221,14 +240,20 @@ selectbox( "Showp1984 msm_mpdecision","",1, "Faux123 Intelli-plug","",0 ); +endif; +if file_getprop("/tmp/aroma/glitch.prop","item.0.4") == "1" +then selectbox( "Select thermal settings","Determines the amount of thermal throttling for the CPU\n","@personalize","thermal.prop", "run cool","more thermal throttling",0, "default","default thermal throttling",1, "run hot","less thermal throttling",0 ); +endif; +if file_getprop("/tmp/aroma/glitch.prop","item.0.5") == "1" +then selectbox( "GPU max frequency","Select the GPU's max frequency\n","@personalize","gpuclock.prop", "320MHz","(powersaving)",0, @@ -248,37 +273,29 @@ selectbox( selectbox( "GPU Undervolting","Lowers the GPU voltage for all steps. Undervolting may cause instability.\n","@personalize","gpuuv.prop", - "No undervolting","(stock)",1, - "Undervolt -25mV","",0, + "No undervolting","(stock)",0, + "Undervolt -25mV","",1, "Undervolt -50mV","",0, "Undervolt -75mV","",0, "Undervolt -100mV","",0, "Undervolt -125mV","",0, "Undervolt -150mV","",0 ); +endif; -selectbox( - "Battery life eXtender settings","Sets the charge voltage of the battery to extend its lifespan\n","@personalize","ble.prop", - "4.3V","(100% - stock)",1, - "4.2V","(93% - balanced)",0, - "4.1V","(83% - conservative)",0, - "4.0V","(73% - very conservative)",0 -); - +if file_getprop("/tmp/aroma/glitch.prop","item.0.6") == "1" +then checkbox( - "Other settings","Select the mods you want to install\n","@personalize","mods.prop", + "S2W/S2S/DT2W settings","Select the mods you want to enable\n","@personalize","S2WS.prop", "Sweep2Wake","Sweep across buttons to sleep/wake device",0, "Sweep2Sleep Only","Sweep across buttons to sleep device",1, "S2W/DT2W power toggle","Makes the power button toggle s2w/dt2w",1, - "Shortsweep","Shorter sweep distance for Sweep2Wake",0, - "DoubleTap2Wake","Double tap screen to wake device",1, - "Disable magnetic on/off","",0, - "Enable USB OTG+Charge mode","Allows charging in USB host mode (disables self-powered OTG)",0, - "Enable input-boost","Improves smoothness with kernel-side hotplug drivers",1, - "Enable Gentle Fair Sleepers","Disable for UI smoothness, but more battery consumption (enabled by default)",1 + "Shortsweep","Shorter sweep distance for Sweep2Wake",1, + "DoubleTap2Wake","Double tap screen to wake device",1 ); +endif; -if file_getprop("/tmp/aroma/mods.prop","item.0.1") == "1" && file_getprop("/tmp/aroma/mods.prop","item.0.2") == "1" +if file_getprop("/tmp/aroma/S2WS.prop","item.0.1") == "1" && file_getprop("/tmp/aroma/S2WS.prop","item.0.2") == "1" then alert( "PLEASE NOTE:", @@ -289,7 +306,7 @@ alert( back("1"); endif; -if file_getprop("/tmp/aroma/mods.prop","item.0.2") == "1" +if file_getprop("/tmp/aroma/S2WS.prop","item.0.2") == "1" then selectbox( "Select S2S orientation settings","Controls whether sweep2sleep works in portrait, landscape, or both\n","@personalize","orientation.prop", @@ -299,18 +316,35 @@ selectbox( ); endif; +if file_getprop("/tmp/aroma/glitch.prop","item.0.7") == "1" +then +selectbox( + "Battery life eXtender settings","Sets the charge voltage of the battery to extend its lifespan\n","@personalize","ble.prop", + "4.3V","(100% - stock)",1, + "4.2V","(93% - balanced)",0, + "4.1V","(83% - conservative)",0, + "4.0V","(73% - very conservative)",0 +); + +checkbox( + "Misc settings","Select the mods you want to enable/disable\n","@personalize","misc.prop", + "Disable magnetic on/off","",0, + "Enable USB OTG+Charge mode","Allows charging in USB host mode (disables self-powered OTG)",0, + "Enable input-boost","Improves smoothness with kernel-side hotplug drivers",1, + "Enable Gentle Fair Sleepers","Disable for UI smoothness, but more battery consumption (enabled by default)",1 +); +endif; + endif; if file_getprop("/tmp/aroma/glitched.prop","selected.0") == "2" then - alert( "WARNING:", - "You MUST already have Glitch kernel installed and running on this device or this will fail !", + "You MUST already have Glitch kernel installed and running on this device or default settings will be enforced !", "@alert", "OK" ); - endif; menubox( @@ -339,9 +373,9 @@ ini_set("text_next", "Finish"); if getvar("retstatus")=="0" then viewbox( "Installation Completed", - "<#080>Congratulations...\n\n"+ + "<#080>Congratulations !\n\n"+ "Glitch kernel has been installed successfully!\n\n"+ - "Please let your phone boot completely...\n\n"+ + "Please let your device boot completely...\n\n"+ "Enjoy!", "@info" ); diff --git a/release/aroma/META-INF/com/google/android/aroma/icons/agreement.png b/release/aroma/META-INF/com/google/android/aroma/icons/agreement.png deleted file mode 100755 index e3bbe5efdf10a17760f82ccf2b6623d28909b831..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4228 zcmV-~5PR>5P)*h$0jsB#5v=Adx^x2ukv{h#(-C;N7*?cy?!}d#1a(tL{B{ zxVNgSXLde%zIGIGR(HGV)~%{r|2`l8b8hvBs`3ljS(5v4(^qbSZGlyoOV*j?hKObY z8CVN81>b@+fiw~I31IO?a1K;K1Q0N)YE|%{2JiwHFp44$p@gyo=YSIC&Q3Mg`vMRa ztRTjKH7Zhy0Sm?oCKY@OYyxR2>Jq@Ifs9hipu}6ji{OVAT@rj&qNNpYtx<7_l6b{g#jDc21q%=DYtC}YeUNE1*}A_9 z79fGq5=0xK-1Dm4p9_AZEIqvE&?C{HFMR&YemEu zV@&v{28E7lTOghx#$b#A#g(q~-Z}4`^R9H>m)<+)ymMYv)qC%qE7dtyEX>Y+?)|^@ zY!{pWduqp#0F-6f^H-j^@~3n2^QhnBp0Z^#f?EF{I>*Cg@|XZ30x}+>swmX=R`p@O zvJO>@vAq29%lz{{e&eg}|KJC^^j?Rx>u~1cuG2jbKq6uZYL2QF*RNk6J$3mhy!UwT zCkHDeGc%;^nGk*^t`i@;+TXGv$hPrxBqH+COE3NHx4-@EcUOJ?{+;iXSDtz1{Mwy0*6*%wKgn2b{pY{& z@^`<3X=mX9jUXb37%EFK)*{AYti_nvZ!N|ej7_jfO4@3Xw%Vkv7FoMZ)@m_aJjcqT zkI~LDO6PEm=ACC_qsQ#r9B+BcTL8#fSwLM?FmmK3X5aDlx4+}j#~yofnv;gU&-K@S z0$B#eMDq|ZCYXych_#{L*bx84Al8HcXDyPXm@LDz+DMwwnqQzh$oY?3ukp)Qp5eje zdx!4p*RS(~AN+tvAA1yl_DtIVpa^>OK1jUxxvEl@dj|^u(v)O=frl?%L~Q~_#w;&t z5fLPfnnR;ctOa8sNsu&ytOaRGHakz*AJEBNZHUgf@a)l)lO(~%J|F#4nxxUC84zXNxfb3}fqUqWNKi29YF4)(S1nK$T)MCm#%O&hKLq6=*hg zc<|-X`XJ)fRF!G?la2-y-8D3Afe0#NA2b1owGFVUV`CGObcnQri5ZllyUE?#w<*dZ zVlbXlwXMy4RZY{>#I8z}j~1W<$)L~Z?i#MuMu^&Dq9!%KsLZJbCpvDiHf*OEW|$*c z3*#I`cY|KHOBv0mk|t0UH}mQN#25o0pt3Ej-a`%q&@>t(fDZcPYj<$%**b#Nrq%?= z7)a6pN@B-mW-MY&)S?W@G8hdhHU|tg``dg^bB=ZM!6PTeMwjKmA90w!mzXLN?E+Al z=M3(y;bvXHrFOzqs2^*Mq$!f5QOm}DsfuVONyC_7PB9qJ@4Fh9s2$t5n5xICN4+0Y ztYC6`KHtGKDE>2I=ytmlMX@7DI@6)Gw#KN}qfn`N5Dgy`KoG0=BZkNr? z&HCHhHgw)`w%eu1`wVRwoO6{nG)yaiQ-LD&{&-9P(IhD|8xh?;Spv+W33)PQV>+nD^eZyu8fv^777RmS(6rx<9*3vDC#><7$!^ z{EJB}m?ZcbiGC-snAFw)R$wZE7egV2VriDe#YL8vmqWUtN|Gcv=SY(9cwQCt9tD+( zJo_PqX={3109AIMrs=Le$h0zsu4L3NC|U)kN-|9aghaD4h}bcE7K0=KxGMZtBvM64 z#NZ^w&pV7Uv|24jqftFK@BMa1t%`c5fR2)LnzL|x05yTyE21e?&@wR{k50OdWKuir z+DXK8SmU=pnb#T+hk6M)S9HqT66G*KG$zris)Y-Nw_(ny)nkfc(}elJJ_KvQ8zMoZ zPB$j7s^%&h^T<$J6_rqHbv|SV#$z<{8#j((Tjx~G(^nehz4V9T0gNK$G2~(g5;2fj zf`6f^=TJ8j>xE(f33Uu33Zl^*m1I`%Bhb>LDkKOarS>~Ji9%h5@v1l%${h;o{BZ!( zuxF?=Vs{=S#*if-Hl`RbVP;~h&>t1cXe5*x=>V9j2qqeQ5FrSaWjQgIFhv~~(JBWW z`$|_TKwh9Dcgz|jBHX@xn>^2V=0OWfEcScMWMFLr%-Y>Va7?4mL~|1fCM6znjaBL3 zHd-Q>kX~_TZH-&EZZQ}P@ZK{!JIm72QcVQC_d(OV#|I~k(-0pxP9G#942MJVJl~NA z`FzNn_p}=t6aX?~(q_W3aZNQ2k&4*)sBz^NT@y=tdWtivpoU8X97d5CXgOfI}hj9ft_ApCSs`SV;ei-<~=J4(A=)e9|pa+j|J9~sRt>P zJ~U}|HkT(*q$Dl{dQ8&6&OO5B4}Xj#mBR?*6i6+o3ud!x5pR+x*4^cBe^Wm(4H`Kp zy-qIV)H@m#!;CY196s++sD~ng7%8~|se*Tt4}VXh2u-4hcfkiGd*v8W4y8e=x@SEo z41}SB(rp2#b^?(LSqT+K3=}2#8~=+)5*GyP(1xN|0XI^-3u%a{7FuDOwp3xhN;d$8 zC!s+i!W(bAu{#f1T;j~yI;FyJ8$eM+!@8Inq^^V-R5H{#wDjY5UNo%O7*SjaVuUwV zS9#@?SIF}m=N$9%^PD|FOLjUcKI#V+T^0F7fHsRR>4mEmw$7tG4CWNvP*E_qDkVzDMP&9fc~Ama)@R!fNO4HZKuacDCNOVdFjBsyZEnBk zS#Hdp<6nQ{DvNJ@oV4d@*?8_fnw6cih330K90H(26UBR$Ih*1=h^H;#foih=G6VgQ z@{Ka%#;^Q3qqNQW%<}tx{An&G%8eI(hw?`+!@?vI3bdoiR&!{+n^Z;EW~H&7^K=$= zIDm{X+`M^{jg5^RznOA=l}Farm`foyV^5L_l%?_yL(BiX=UK|m9GQ1q{m4g_F>CbLXfTX~TKq6p_<<(bT<%hGKI?OLGFSD|;vYkl>A2ijo9>~O+--w8i zrs<9?ODs0Av@Oh-&=xGrpnR=w_})9;OF4grmU>=%@kK6Ox z_Bb;=WhP#uV_?RHj2;cIxis(D>2$Ex292srEPhVuqmPCMwOXy62hT2$EuW>UV69?+ zmckc%@ZGolD*o(w81(t0PkoACd+&Sc_xsH|!Q+qP{^p+;z4#pZ-#><>&^;61Z*bo6 z@WU5)^2sO3W4S{_$nzX)?e-{kKYY;SLrscLJ1n?@PF&UK0DpG}zWKxz{DTkUH+p>H zlb_`2D_2-uUEO|x%|0xhNB-(1+JE=~%=dqUE(U;XEVkwOkilTUU@)lXCn5o$Xl7KO zCt+eu**lVj(B3kzXyBW7;meOag}?9^Wv|OeKlU-+_rCYh?RM{dx(IBn;~#hv!@v9* z$-6Gm?gagipJNDBMB{T3Zci?kxdMD+hZ)McI%kRDL0?$47 z9P8`ryI%vKw~jlvLiaEJ9(mW>p&OTrbUPQCxObB*o)iz73Lv0e4!L#*{`!}mX7Jc0 zMtAS<;j35q(1$)muh-l6b=X+PoqLEofBsc?_dBrb)F!j*c`+Y5h)fMolS%KVnbDBf z&%BveKK^mu`n!KX@AcPs{`u#*di5$B8yh>Xq3@ze#hC|K|Lj-DpL#dN`kig#{MI5` z|V$+O=!D7yEY;Rm|)>`6oWj zQ(yl&KYRHn%(b$5+2?@=9^j#e9vbIoQ-acz14prDa@cCMcKv2DW6-kT^5v(vc=2K# zVRl_E+DnQdOBXKk;g5cd{>BC(LY8HeWy$>fJl0zBJU_5$RdS$gzNx}1D=W;-&hFzh zl){GL&EcR5ft-^_bPqY=aX7I;rkDu#dZ8U*!kAx^VY zOyBz*%DnrO1DTj}jrd0Dg@hGNSqS$Gcijo{gjzoh_vs9@@wG1>ZB{?(?I?d87wH8Hz z5t&JnWGXNEyMZM?dtFL}B%d-FKbUNk2;^N(D&i{XJVqTT+fA4!={>*1S^Ob{~ zKQ%xmQs&c`UTl?Wj&lnOi_N9zX=GY}w7AuV9NWo9B`~sjo ap!hrv<3p7sA)K*+8 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 osA#R;y(y|_crLW?_XaVQQ&TdYtVf&{nXP`o%4 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 diff --git a/release/aroma/META-INF/com/google/android/aroma/icons/apps.png b/release/aroma/META-INF/com/google/android/aroma/icons/apps.png deleted file mode 100755 index ca75fff16d2513a6017d98fb25e4cd5b4285959d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10928 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 F697V_1YH0C diff --git a/release/aroma/META-INF/com/google/android/aroma/icons/battery_aosp_green.png b/release/aroma/META-INF/com/google/android/aroma/icons/battery_aosp_green.png deleted file mode 100755 index bfd824b9493c0ab3fbfc8e929c1ca4894c555112..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 528 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 diff --git a/release/aroma/META-INF/com/google/android/aroma/icons/battery_vertical.png b/release/aroma/META-INF/com/google/android/aroma/icons/battery_vertical.png deleted file mode 100755 index 9bbf5251fc83e0aef851f70c67292c32345d1c29..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3208 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 VR34Dh4TDwzNQAjTjh@@R{{W|&OvwNM diff --git a/release/aroma/META-INF/com/google/android/aroma/icons/battery_white_stock.png b/release/aroma/META-INF/com/google/android/aroma/icons/battery_white_stock.png deleted file mode 100755 index ba99de5192e2eeea3765ab528b22865e6a687473..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1130 zcmeAS@N?(olHy`uVBq!ia0vp^J|N7&3?x5zE|g?oU`z_|332`Z|34QO7at#=u&}VC zq@(*`Cwr$_Oedo@dt5>gHx^(IC<;zc;II(~K{sRXN96o&b!i5VL zFJ3%%?%ctH2ag^-diLyDAos?N8`rK~yLIc({S8e*6Fi?<$_TZa_zrmIV0)Gt9&e=EDHcFKgDU z0eS%w0A0Hi=*0cUAm9u#xO@`|fDU>F18;!f^XH#GQ`el)Wnf@(@^o=g!=jA^xdo^3|4<$A4>gEcYq0dz<&o z@8hEa3mLv&>i_OI*|B+|J*jUp4@Mk&Cl!~zSyjMUj3tRPeMN#~w~Nx^+qb97 z+;ii(ER?x5B>Cm4Bd0Ta&5wCp*qCAR>uO7RU}`UqdaBH6zY`nO(oaX|i2Y7Gl;HE@ zgz?UWx+nP0QbuN}9$LODW*w<*yPVhlBHid`cZRz$-+RSr8=rd_uSzR4 zF1Ynp=o*j;c-RzMacCI}R> z@K9gnSLh8C6Osj4%9->t!zOT7Kxt=m+vUFWGujU}@NDc^IwddU?jyScndL5DY^VP6 zEmTBv&tDEu`tU8_Y zN{{%$Rz}n-)t^zGQ~AZh{-N`yIY9BLbuD#|%}*A@o!$6r4$thO zZGUp^2ivglYx(?QSr?XNa&1ja;Wu^DTgRL-KiKHc5R_JE?YX(Lb)(Xc^??lU<|i9I d0LFe_w$9@%s{RaavaDGB`T6;uKYH}& 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 z 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 FV1oIWD|Y|@ diff --git a/release/aroma/META-INF/com/google/android/aroma/icons/install.png b/release/aroma/META-INF/com/google/android/aroma/icons/install.png deleted file mode 100755 index 44caaf5d553bde9f584768cfe76caad873fd6041..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5577 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 XCWCjN-V2+b00000NkvXXu0mjf4sz+Q diff --git a/release/aroma/META-INF/com/google/android/aroma/icons/keyb.png b/release/aroma/META-INF/com/google/android/aroma/icons/keyb.png deleted file mode 100755 index fdfb11fe0d490d1230738f7ad0c17e6154848cd2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3131 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 BoMX)O1hJnWw6! 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 diff --git a/release/aroma/META-INF/com/google/android/aroma/icons/personalize.png b/release/aroma/META-INF/com/google/android/aroma/icons/personalize.png deleted file mode 100755 index c6f679800bc949371451f679000dc16ab8062954..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5741 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 diff --git a/release/aroma/META-INF/com/google/android/aroma/icons/signal_highdef.png b/release/aroma/META-INF/com/google/android/aroma/icons/signal_highdef.png deleted file mode 100755 index d25ac4f0667c7c6c4bd50b0915c3767c5e18a0a5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2497 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 diff --git a/release/aroma/META-INF/com/google/android/aroma/icons/signal_stock.png b/release/aroma/META-INF/com/google/android/aroma/icons/signal_stock.png deleted file mode 100755 index 4f2a6b8b5e1dccec859822fd652dd3de41f3e939..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 575 zcmeAS@N?(olHy`uVBq!ia0vp^Mj*_=3?wxlRx|^tEdf3uuK$N1kPu1V19ZPlNswPK z!{PsDX8xHofAXTw2hJa3*|>*e*2?U9=ih$=mEL{QHTC7W@kr$O#KqU_RaMMcT^NrD zdfPHPv6*=AI`T=k-kxI%H0PhEi(`n#@weBm^EDZWuqD`Z34f1U@E~r-^WXcYPm78c zUbDPY+3=tFoM|-+xto^#brxpexTM8$y~X4C)=%6!ower*#y*}p=YZ~>8mB`w32VA+ z6rCPFWRCMQ(0=Cp#b3bo*HcmD&Yx#hl~fz%*TuN~ai12I%qHjf>kWHOc(m0Yu+kKH*)&0} z>x*mBW41EuH*3Du8Et6c2}seHB$$_wtT*e#PM>8yGmIq*I}0*x;{!IvXv$dnuQAtR xudWu{z4y{>W6KC`_m8r+@BIGnpZ$9dW3GsJ(KLnib-<8d@O1TaS?83{1OV#BReS&d diff --git a/release/aroma/META-INF/com/google/android/aroma/icons/signal_white.png b/release/aroma/META-INF/com/google/android/aroma/icons/signal_white.png deleted file mode 100755 index 23d37cfca5b8eb3d2163b406378b287a00214cec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2574 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 Jtj+|V@P97c?9u=L diff --git a/release/aroma/META-INF/com/google/android/aroma/icons/weather_sense4.png b/release/aroma/META-INF/com/google/android/aroma/icons/weather_sense4.png deleted file mode 100755 index b93f8f89482050c49135ee1f3a3fb413d2dfe4bc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 52273 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≫wk+f-j)@ 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 CtOP&+ diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/bg.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/bg.png new file mode 100644 index 0000000000000000000000000000000000000000..496cb8558f623fbf83f33ad73fac64625c00995f GIT binary patch literal 2083 zcmah~Ur19?82|3w?%d|oB}0aYTeWOOlu@h1kS!;=aOOV<9|EJ&+>>ZvqTrklSr3^d z1d<@WG>C$P9(u_}59Pq#CyyWhX_eZTKJx0{>l z3#_G904NAG1X}@k^p^)ShN05hrwH8j$Gz!k zZ$m<3cOV=9cs`N8b6G%U^Pym%{bnltDKWXvZ#N`H@9iEv-Ss2hnE(Cald+zffnV@V z{Il(X*CS@|PXPoiT39}7G+dttm@|U=ydFe02hFDDs~iNE0ElK6z{w7P79Q*eRIu(a z`lkd*y6!9^M}}CrJjMmHZJPq1lvcZV@MLSDc-jc{Yuwxsh{nZj*X$w>oel*k|z%g|Tga3_&XpOsgk!iTJkgz=eMoe(NP1-#M=Eg1FciG^agGwRI;ccdF~ z-D9s)St*~3%ars4z%)*p20k`QuE&l@%95o?rbIiqH5aG0?Edt)V6oY+;U=!`LRdHX zDpMZOs1i7WlqyUtGiUj;=ycA$QO#-0FS{ukE0$y;bZa zEy7(8UG8WFF0Kju4-{lmS5!gF>Q!E7P%!*a48|2lnfH-bg7pI?db$y!9uz`%9JTH?~tplQAss1d-cn-t9Nk<&mw zW*@zGYUmXBClNtdiqwA=#AhDTxkjV=QZOpXPf5=Pnl>Zyb$>2`FlNZC!Zu}N21dDL zZKc#mwGuid51FNp`ktuC&y^SuPH$|EkZGWqWka@`q_0^Dg4{(mMF)^+p5}niU!HWf z;n>1!v#S;#6KCzg^l*_wxt4S~#r6>mwsa6OYe^FVxz_9>YLFhbn57UocRXr#e9)A+ x)_!cG+z13>nS1OgWLZNV1tyc9^Dn$h;l}e>_ zCX+eE81Fz}$uxhqL4=U-bxl(TU}H2IJ(bJl<9t4U1Gf!J5UYl4HXF|6awoDZCn31# zbP6Xi1CXJuZns;h*Xup2zSycE91h3)e!mLA(6oaN3k8G0{b)401NE1=A&0{uhLmi$ z2>2-&W3$)mVY@!Ijl@M)2`8MhI?RGx0^>}Xwve!*mqG!n+_oLtJ;;cYe$zJcoH{khHr|AXA2>X%}QHDklShz-uHDxq={GMNy8t zUhnR7>H+?HD$vvigTZ6F-M)^+VwYqrJ4o9!!mnMc)oO`GqY>|PItn?GhTDfwZpm@- zx30~mz0bktg8r3J#7|9lZ-L{j}9TG)^)_J@W0 z{gbC3S6;hvt41q#?^|bQXVM+HDv?1{O-p;Dyc~}O563S?=KsH_8ajU&*%-e3VEg~@ z(dXmW&Rz45TF&qWms%EF62knv1&UJtEqGYoFf#o9i&9Ec128dsW#D6BW>k=3w|w`M zH=lvwb1iPQIDn)$cPuB%S4M_^e{N&+ECr|2dik3UWR8x(00pCf_M{f{ngBp7439r=%rAxR)GhC&g9w=kz$bd#OC zK{5T0PSH)snxP%t5J%F*jYQ>ckP1d@8V7wj$w0@#oKTfBWYQ$oehw%U|Iw?)`A2Sz zGc@XM`Z*ex=R$Jc84aVkW`;pIGIte)+-p@8945R3DoJnF%ucBhU^}Mbb zUZ2}$diT)Wx?hivTmS$1T9BI2%*ZYJo=w*BsJvZrlcbT?X=<813P!;wV4(iQIZYPx# literal 0 HcmV?d00001 diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/button_press.9.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/button_press.9.png new file mode 100644 index 0000000000000000000000000000000000000000..13c6ebf1853b584c029cf9386384e581df26cbe6 GIT binary patch literal 690 zcmV;j0!{siP)x30~mz0bktg8r3J#7|9lZ-L{j}9TG)^)_J@W0 z{gbC3S6;hvt41q#?^|bQXVM+HDv?1{O-p;Dyc~}O563S?=KsH_8ajU&*%-e3VEg~@ z(dXmW&Rz45TF&qWms%EF62knv1&UJtEqGYoFf#o9i&9Ec128dsW#D6BW>k=3w|w`M zH=lvwb1iPQIDn)$cPuB%S4M_^e{N&+ECr|2dik3UWR8x(00pCf_M{f{ngBp7439r=%rAxR)GhC&g9w=kz$bd#OC zK{5T0PSH)snxP%t5J%F*jYQ>ckP1d@8V7wj$w0@#oKTfBWYQ$oehw%U|Iw?)`A2Sz zGc@XM`Z*ex=R$Jc84aVkW`;pIGIte)+-p@8945R3DoJnF%ucBhU^}Mbb zUZ2}$diT)Wx?hivTmS$1T9BI2%*ZYJo=w*BsJvZrlcbT?X=<813P!;wV4(iQIZYF#tO8@`> literal 0 HcmV?d00001 diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/cb.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/cb.png new file mode 100644 index 0000000000000000000000000000000000000000..62640b09f41c7375272fe021517d1224c9e872d3 GIT binary patch literal 570 zcmV-A0>%A_P)Vrk(Zkbh96zqmR9GXdSwUFVewE zH>o1o3X0Y0xzI`o5$?%T@ciH`;pW``FOQQX5(GgI1VIp<5fE$BQ0q`qh6{scal^S+bOJmQ5dO4UtzIMcidMiO zu>}%~uk5Vb?VeRC6-@Ye1Z)!KTp|tO&tbe?A;ZTfV3$axQjhg|{mw&plt5&^5=f%| zm52)xh?{>U@DWia)IOLo`VJ){rM-lIhMM|qL=Xf)5JVJw0~zVNL7fhdZU6uP07*qo IM6N<$f=gZWcmMzZ literal 0 HcmV?d00001 diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/cb_focus.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/cb_focus.png new file mode 100644 index 0000000000000000000000000000000000000000..eb65efa41e1e19e9263067ec986c8414cf97d6c4 GIT binary patch literal 502 zcmVv=mYVMZrqJ%HGPyKZu~%1{B0f1sg5>0b;Mj2i6in zZA68XA_z9R-b;4z5wpx>=WaH54-A1MJ9EyG%nqO^ilQir(l9C0FM7KeqnC9WIYFOG z8imvXj!iFUx0w8ZMvtI8lk?Zfm|l>!m|R-Ep>=Em5{U*h8x61~I}gm<0iAs<7{K!5 z+dy{~m?}Amh%X?JPy3Iau6~L*0opne5->1ZU*@+w<9z^ETfqBU0s;n?fQda|vQ!&U zPyVz3TyI2PI(h)h=ZkczqNy^&KO=x*LYOtf7nETVTBxZM$zXJn2N91(-OTtJLyK(qN*0Z%bG sS*>FeFh`>zEMM{0Q4~c{6s0Bj1hLF$I-o8iO#lD@07*qoM6N<$g0f4=WdHyG literal 0 HcmV?d00001 diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/cb_on.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/cb_on.png new file mode 100644 index 0000000000000000000000000000000000000000..e622573282583994a579fb4de5d8eb26c1dafe06 GIT binary patch literal 494 zcmV9pmv@}b9hNd70#368qprEBG8iJt62!i&8#)iiF5EelM4OTP-4Gk?3 zga!2p0>il_P&+TzgHkEy^`7@$rT2k@T=m}bJXbv&0Yy<1MNyQFNw~hTwuf2sa9~DO z(C5L7-NZibTuQ+8VL^E!Tc2md^@Kjg#iivtnuin6m1scRXaJjuMPU087)qm%V(XN}6#xJL07*qoM6N<$f&;G0I{*Lx literal 0 HcmV?d00001 diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/cb_on_focus.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/cb_on_focus.png new file mode 100644 index 0000000000000000000000000000000000000000..f6cccccae7d6070626a4d246ee2dcc7534228a29 GIT binary patch literal 502 zcmVv=mYVMZrqJ%HGPyKZu~%1{B0f1sg5>0b;Mj2i6in zZA68XA_z9R-b;4z5wpx>=WaH54-A1MJ9EyG%nqO^ilQir(l9C0FM7KeqnC9WIYFOG z8imvXj!iFUx0w8ZMvtI8lk?Zfm|l>!m|R-Ep>=Em5{U*h8x61~I}gm<0iAs<7{K!5 z+dy{~m?}Amh%X?JPy3Iau6~L*0opne5->1ZU*@+w<9z^ETfqBU0s;n?fQda|vQ!&U zPyVz3TyI2PI(h)h=ZkczqNy^&KO=x*LYOtf7nETVTBxZM$zXJn2N91(-OTtJLyK(qN*0Z%bG sS*>FeFh`>zEMM{0Q4~c{6s0Bj1hLF$I-o8iO#lD@07*qoM6N<$g8wPW00000 literal 0 HcmV?d00001 diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/cb_on_press.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/cb_on_press.png new file mode 100644 index 0000000000000000000000000000000000000000..8487d93b14eca2961bee5248fd29e2708642d46f GIT binary patch literal 604 zcmV-i0;BzjP)4W}&)Uv) z9%xB~V-euzZ{ ztgz7;VEF*(_Zs`yBEX7ma*W7_*J+;_2bT7M0k45?FIHeQ1k4k8mq#Z#=m(;E`g2cI zz&AzFJO-H$>6v#ojGS5pUao=aM-NmW5T$I=0UFtE&8WzHc%xaIAfLVjlm`cAz>xeR zFuMlrTIHJt7IwZx)X8hlHU3p1pSl3D$sQPDk=5V|5o`z}L_|r1e~v1$+1fT~BCjOz zdrR6}G{-6+tXu>VXCy)~_7UW@p8qTJ z-5TN&iMTxl3QBuEDI%Xq$Zxrh3-}U2m3V(^SW_EVGvvE^5|;}={6rT~Z<|b9Zf%Dx zWc_WlL?UjEfsqLy_hgDpC$Q%>Dk_nCw4J;;0sMQQ+XA=(-4~Fjk6{Nm<;^&oILHtq qE7<$LmKHzeK#~{?27|$1Sb|SSO$!z14?X1o00004W}&)Uv) z9%xB~V-euzZ{ ztgz7;VEF*(_Zs`yBEX7ma*W7_*J+;_2bT7M0k45?FIHeQ1k4k8mq#Z#=m(;E`g2cI zz&AzFJO-H$>6v#ojGS5pUao=aM-NmW5T$I=0UFtE&8WzHc%xaIAfLVjlm`cAz>xeR zFuMlrTIHJt7IwZx)X8hlHU3p1pSl3D$sQPDk=5V|5o`z}L_|r1e~v1$+1fT~BCjOz zdrR6}G{-6+tXu>VXCy)~_7UW@p8qTJ z-5TN&iMTxl3QBuEDI%Xq$Zxrh3-}U2m3V(^SW_EVGvvE^5|;}={6rT~Z<|b9Zf%Dx zWc_WlL?UjEfsqLy_hgDpC$Q%>Dk_nCw4J;;0sMQQ+XA=(-4~Fjk6{Nm<;^&oILHtq qE7<$LmKHzeK#~{?27|$1Sb|SSO$!z14?X1o0000EaktaqI1z?7Z6s0xh1F{mV`$ ze%kJ!H)-=18(VLEp#}BD9Sd^j+*mawqx)mU&kIr0jx;a}q$Ncw*}tDO<;}wU+t++` z-~au>ZtEB;|My94PvdI_m;2V=VxAu?TC!0->cdwL0Mz`+#@j#TM z?#O05zTum5^!E?;b@3wiW`v|V1etyLF7=>wLE=qEX+e#B_8Ovh3}&|l1v%tSS;QD4 zHHR(7e2f1pxqsi~=ly56n6)|EZ&i|`hj@V52Mq?+Z<8JvOk%ktZL^Qjgk9jL#o~jC z4nAl9)lLr)SR__j%)2cuAE30w^H+xKd@nXL&v-AH8{rGN&aFU28Z6&u zUQ0_4@3mO0MF2HdbqBMii!?<~EzEtpN-%wj=$-T~zu(%mI&*JY@cFL^tt+B~u9cOJ(nZt+e=9yS# z$d#Q9*!DKp&U^BSs~4`l4PcokRv1`e=q>b5C;m@#t>EF=5tEnHJ-wFSG?_p8jeCY` zRpWJ;hAk13Zv4={*tU$TQr1nWx!Cy7<(#J$TRgUO=5sIZOTV!o>A{8dozLnwCNC}x zTrf51%iUciyB@VqU|+}YYxs#-=Ht4}t0NA0E}5F7dt4}L){X{I)7$N;y$+Ab3cqP$!gW-;l$l2Gk&nye+dv!6xyUF{&^WEIddp1-6 literal 0 HcmV?d00001 diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/dialog_titlebar.9.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/dialog_titlebar.9.png new file mode 100644 index 0000000000000000000000000000000000000000..2f70c227cd2e105a7ecc0a81f4e564a9e7d2a5fe GIT binary patch literal 380 zcmeAS@N?(olHy`uVBq!ia0vp^ejv=j1|<7dDaZmT_7YEDSN1zh{5%q>-hB-_fI^%F z9+AZi4BUbs%vhfiKM^R%lJ4m1$iT3%pZiZDD+2=~x2KC^NX4zUcN#Mf8;Cd@)GFch zkG5KSykNEHI{Pb%@7V;dIkPG2tbM)9ZrR$c&)EMq-?v=%(b7)&j&;SK@63Bv9a@MT zogO3DQyR>w*Z5Q N!PC{xWt~$(698O6m?{7O literal 0 HcmV?d00001 diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/font.roboto.big.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/font.roboto.big.png new file mode 100644 index 0000000000000000000000000000000000000000..3a66db5d109c05ee35e97122be3401c1390c69f2 GIT binary patch literal 9911 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 Xw-(&p>i?$000000NkvXXu0mjf{X;Q& literal 0 HcmV?d00001 diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.agreement.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.agreement.png new file mode 100644 index 0000000000000000000000000000000000000000..f85b0159a44b499205e63e2d433f8e3701c3b6ba GIT binary patch literal 1512 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY3?!3`olAifbFq_W2nPqp?T7vk7#J991AIbU z|AWDgA3vTwdv@*Gwf+0|FI%=uQBhG+Qc_S*5U3ca52yqpd*;lUqeqVd)okCseae(6 zMMXtXQBj_ro=#3qT3TAj>fr`rYDr5=18PAw8KMSg=DKz3fVO96X9Lv)1_lC^VRZ&j z&CHoIfevVHZmzDb208<%9_SK?7Aq?&V`F28`9Nm_UE9^w1yKeu8KM&CW{65;D}V+< zJOwcdt_Bhy5HsNl;Icr!qlFm6WK417Pyz<5_OA*@AXQ%y0-eHH;1OBOz`*qygc+NSe|Air=5H{vOxzZOiii@v~Yzn>H->_aRMu?C_CQqk?zj5rx1zKu;D<>>Snk$fQAooNdXs7wi1-s)p8cS?C-bLJkRlayPr@B$1j{RkleyIUe&Y4}ap>Qa!<~A;ZH+QOlXbLX>>Pj-uim^IZliiFKMbe(P5g8n^oC$S1n*wEkbbA`~?#S8kYrgQC#Yms|u?rfS{ z{J2X%W2xV&FN>Zo^azyp;%uz2<0{+wUfK0Buk-b@-y9~TU6{xI&vzSR5YMG2YzB|2 zRpggM?w>1i;Y@^(_>zrFI+CC7uZ_~bl5w}WLWqA!!t{pV6Mp@xUftZ-ZaKSE%w6e7 zF6*mJF;1^eD{p$LuI#`}LFQ1-kUS%Y4G9<4 zn0&d`$W|VZ!6~)CbB)}BX3Bbbh_Ch6DR=pI|2E!v>-?oTZ`Sf% za(P`|q3}!n+9Bs#C)Gtdl0L9_W^8TgqUXJ`3YtmNl0cJ1;Pgg&e IbxsLQ0DH-Jy8r+H literal 0 HcmV?d00001 diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.alert.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.alert.png new file mode 100644 index 0000000000000000000000000000000000000000..5b2e08a5b806b3af4d7f1367093ca08c0774f093 GIT binary patch literal 1577 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 QfN{j&>FVdQ&MBb@029#8TL1t6 literal 0 HcmV?d00001 diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.confirm.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.confirm.png new file mode 100644 index 0000000000000000000000000000000000000000..304c14a8754a17b935e366dcbe18e1900cf7eafa GIT binary patch literal 1849 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 E0Af3O%K!iX literal 0 HcmV?d00001 diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.default.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.default.png new file mode 100644 index 0000000000000000000000000000000000000000..084528c1c9bf388c79bbc5648f605ad4bf7ded29 GIT binary patch literal 1161 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY3?!3`olAifbFq_W2nPqp?T7vk7#J8W0(?ST z|AWEn*RT8f`btVljE#*I6%~PMfXaa~*REaLzJ2@5nKR)cckkW>3Z6N0rn$K}CnpD} zUQ$vLF8l1+Gl+ttM~?zEu3ftps26Cgm6a7-4NyB!7AUo3$r7OKj9z1_sJeKnENELk9|0ty;Bv_Zi)-$F2bFkc!~^w370~qErUQl>DSr1-Hzi)bjkI z>|zDyVAH~_kIfhun6x}y977^n-%g7Tzw97zymN($hUNl~0D&V483(!7oVu#;fK|mQ z`u5i#k86D&f7dgo2j6(>V?{O^<};qB^u?9g*d zrD-x8o`nYr*jkwQ7PEd7;FY?5(?qIwSL6@#qYKQLRbD6_yYhWo{G_UA*9(fgLJ>C( zb{v1vy6)^#hYhab{ZgBmU3D_{gfCdY@KIp{n|^$KU?o}fyU?>Z=5x{8_;XL1SAU6`_wSdJgr}p(j=K&~FLF=a@miR2X@+_5)tZ`3K(Vwa>T;3<|9+TA5|2kVKZ>`^RKBxPpCDQW?rPcHMye-1?7>$-p zKlRjoPI|YG=Da7~u5VsTa?~By(Kxe$`O-;^&5{%LGDm({5iWU@Dem89^%sjJ)ouDuJ~I_6dCc6D6EfS-DlGbPwJ*2NueE2Qzg_<8 ywKQmH$j$pR9^G%Zxckh)cZ!ZhE7xD)U(6be2Fu<)@k#}zE(T9mKbLh*2~7aNz~55< literal 0 HcmV?d00001 diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.info.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.info.png new file mode 100644 index 0000000000000000000000000000000000000000..491030aaf630589e3e841a4439862458851f6b43 GIT binary patch literal 1787 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY3?!3`olAifbFq_W2nPqp?T7vk7#JAm1^9%x z{s)8i@83Up^5p8(t9$nB*}8S>x^?T8E?sJDY^7<=9DQ@+S=L_6%~;c-@A7Ys1m3QsHV8MI4373EiKK-$;ryf3e8xcN;KPn z23A*B!*zLic|kN{brnQA&@Q;+A?^X10Mv!41>)x3-d>=a;kHCYMFj-~0o?{s5A+MN zBOxwqXP{0u96_XUoo{7Hg)qx0R_cMTq8=H zi&7IyGV}8kLNaqx84Qf{jZF0ojf_26%YZ6mKq`Xs(@M${i&7aJQ}UBi72Gn5Qp@v; zvWpd*gG~#!J~m@uU=i_jaSVxQeLMYa{1rEW2H|tlo%+3(My*wCPl~r~SrqYm*^;hH zN#4Ctfh<+iwVo-tuUPct-6X9P^UMFP&%L|Ye zKmSErDyxX<1|8@7#z(i@VQ6g*h&g?Sdv%itmx-Fg#L$~t%^BM#YnHzo+l{@$zLX`DJ@%75%ZPT&2){BiXj7d!C_mE!Vw(04rJ?T2QT)Tvd<9-Fl2T+53~H+ck# zU!43nWmEaIqpy$4TKsF-sq&m>m%~X{$G;2t9p-;K7Anrk8Xo7f{lk$t!cDsjHvc=G zfAYxOf)7vfPFgGtUGTP3kNeh(49lrII?Y-`BXxP%7 z`%;@rK3+*6W@5uC#ujtoSwTk)crG7G)0DY*R-kDWOH1PRb1Ei#@9RA1XJx48sy?^H zV4=_i|AimJoQhxUefV>N>FE#4w|soa77)*L=$3%pnygY5$Jf~hcXgSnGd^sawZJCi z>4N^2R;gD{6}$sBWi8)O5)rYXjC0o;;|pst<}xbXb+F%jPAc{t*QBQ%jlV9PlCs~D z&-!>DPr&R0uTE~6w6w#_UaZG|9n-|C7r7YiWu5KMf4%&jHTjHe;48=IDC6DGhpw%-&nuwx@G8E%IlH&ar$DKdGT_)3phEWV%Axl;(47v&yz~S5-(g zWQx*ObKoue^^pBc`;PTTrCKvQj|HlI=wHS;y{ot5?t{rU0?t%OU)~rJb$3>#`;}IX z16}drwcR=-7qQOWnE$lI$67M*#xJjPfqge8 z>`J>g_x6!}Y$-oK->^7Pm$IQhwP6b9HeJKbdp`fYb?bfh{yBX|8^bLQEVFU;;k&0^ zA*rTjw6#ZQ{)L!l?!+?kqwC=2Pj<+aB+A`zTZW x&n>bhLkXEiDb%B4k;h zX|1iTH8nL5Wk6#gW&*Xt#evoVO$ZDO^z!mDHZ}&j9HIuI7pM`U0H_zJz|qms($W&B zOi@u0ZYe|!ngXCXKsCsL0JH_D2B;k^aNy2}tvgx9t->e*9nW%auH3ndTMSxR1LVmp`fe`N=d>m`iul38m-4u2*>&7>-CVIR`UI zUb?`r;O2`m!>Jley%`sH^V@~gZP$v9mcE%&xB1dSv4d_C79A?;aoZ*weX>MgagTzj zWl{3oB?4@j=LILNl8(Fh(tp>oTaTYuCC<&NGMvR|D9FZqcUc$DA+h_NuPUZF=!%3k z{#|>z{ZfG%$Kf4G);Fx4SaB_Qy6A7w$}O)a2CclhZMIFxhOfQcPct0%W*MoSS{%}Q zuOi8uWAZU>y%fist3rwW(uQ6Z)fV%VZaw5*W?#Bl{D|L+MCRUw$#sq*O4oc17r%P2 z=6S~NMd~c;cC4HCmdW$tffd%> zb*}k!8yP*3lZkWEtOXu)Ms9RlUwJ=HPGtKFSKoF&R^`ug6J~x;ILkTb*q;}c`gS6w z5+=P9zeP_x++4J$=)%EO6+d??t~@z2a{I3%>C!tDMRzT{_bhpT?vo}Z*YN5OfpwNL zK_>PbRtqd;!FImHdjp*y(M>4;tc!UEI-R#e+>>fI~XzkB6)uRj{u`SVNqL|3tg&-L%6@9NlkAmJ7;=`(n``njxg HN@xNA|FkiR literal 0 HcmV?d00001 diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.license.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.license.png new file mode 100644 index 0000000000000000000000000000000000000000..0ea1fc0e04742cc44cb80fdc258a79635474b80c GIT binary patch literal 1428 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY3?!3`olAifbFq_W2nPqp?T7vk7#J7}1AIbU z|AWE%_wSpUnj#`1yu7@eoSdwztTZ$<6crUEB_#y}1b|wAx`7IT%AP%YcJJQ3GiT0B zo;=yu*chk=Q^D1%SC1Y&x^3IGHEY%^S+Zp2%$aZ#e*E|WGz6#sXaZ2pzJ2?EYJduW zrj?e0+z7M{(+%k(&%kzt}ixr%M zO$)a^He+C5dgmogy%lyll^|ZyhqXEnc)KS+FS2c_y4YWxZ|-|*Q+Iy{~HQAim|MFpKq~B=X6Yh zyPFo@q-NXT4r3Xel`8`n+NXzVI~|#SN!;_Mq|D6zE!O)3R-E_HIP|fp>zp&k$(pXs z#{?7_{jV-oK9QopaADJxUlM-u&J9<@7=t!`sNNs?n6oLV%1o?#`R1z)7tRH@9ZS6N z-R~rK$sB{#4{dlD4#w<{EcLazH<^9KpEIxW@|o@n+EeH!H>6ZATCLxh&vA0w`<2h#KmV$32)TXGqN0JxVd?I4+3PhD6}N5{Tv_u@ z*1}6)K!~k(+4rr_Sc_`>R((5};r8@d=gJ8TjO{H_>Zb1tIwm}7d2n3%mvq)ghX#hX zme1Sxsy@n9vCh39$N1~kp30Bjw~p`reX41(L&9W+)N}pE?HN{l`X;2OW@hsG`U1vO zjtg_X#=i3Sn(;b4DMJ56=lT6dk`oRGRQ56SPPuTCx4*pWeVY8{Ef*gI|2{eU(6$g$ z%@8R?hc8{%B-qU^UDi2#;oGFd#pjEAzdGFFs#R<@u1|9CGArvY>syk4FaFLtdts|e z$D$SNLA4?$_~T3L)ihtGn@^GxQnU)bJXfD5(PL9re%NV&bhp4@(LF{F4$J;gUl`h} zUv7Wvdihb2n+w^vDnwYA&Of%7>s#_6bs^8k35OcEU3z6+MxT#J*=hMJa{2UI7njU- zE>$g?m|Z3uyH4P!j&@$(CZ7l%?Zk_`LWkd4{NNTf6 z+-kjQi^Nwm-QZXK>$^-Ruk2j?u`a&PZ{x-{VXXQKf^MEV7O~%FZqlNYs-96^ZZj2n n95-J6@rCbH$)%I_v+YxsPgn5X@!SoVIT$=${an^LB{Ts5^~GJ4 literal 0 HcmV?d00001 diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.menu.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.menu.png new file mode 100644 index 0000000000000000000000000000000000000000..ce48992bf49ad5259953fba28e8b07eee95fbd7d GIT binary patch literal 308 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTCmSQK*5Dp-y;YjHK@;M7UB8wRq zxDJCbqlu=IQ+eo=O@f^)EG;nv4yKy_ju zbIGv0Hw|%;Q;mSDice_t^XfMiY?4 zrr+&q#?xQF{q6f-`S)YBxOL_A8@@GkMDz&>KGY~oXE@6+i_yfLbJpS`%x;TbpG`^j=H|wy0Nb7lB#`4Xn zjcmz(;^yrtdn;^`eXx09TZ&fQ7CtkT{0V$+Gr3}C@$9u1dB+~re=a@6^Tw3oWA)Dt z?m7@($e0~-KuUbWG1fH@W?7@eV;`3t<~tI^HM$_0dthcs>PE8Q!P+Z~F zvFFGvp`_gtrnS5He6cr7 zzIq0ya@J1IpY_baMf_Y&A>+wU4I3ItDjfnG7TYMOEC`ijm{6Q1TYG>0wbI&?miAd^ wyqW4V<}sf6KF{X*9wDYxKhi}}{WVLQefPFVdQ&MBb@0Noe16#xJL literal 0 HcmV?d00001 diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.personalize.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.personalize.png new file mode 100644 index 0000000000000000000000000000000000000000..f1a411d9b4f4a7484ef8ba8739857e7aa1ff979d GIT binary patch literal 1632 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY3?!3`olAifbFq_W2nPqp?T7vk7#JA)1AIbU z|AWEz@893QfB)>+vwQdMUAuN|>C&ay+1Y7nX;D#8R#sM$l9B=f0zi#GGl0s0Dj~|w zoH=v&@Zp}Go|cvtV`F19H9*sVMnTl<-Me?&wrxOTCr_RXQD0qMU0hu3?CgxJ3#bL6 za?P4G$cll^Kvo8HEyQrRu`_4RL^BzvB`7G!+uIxHenmw^h~t6o0ct@u8R86}XMrk# zjsf~YQ&SUe7f==+4iM9TYJdg;)gXrnB%qKLK+FN!i>wT&5vw@FZ9q$b!Mk$iKTROj zS`y?J%piygl#l?>AT;2D3_`I0pes>8IWp)#2Efn+gH@|`@BaP0`V7!PoCO|{#S9Ew zuR)lxshc+nC@5Cq8d2h0l$uzQnV+W+l9`*zU|^(gWU6myWbDaW22>#fQW2b=R#Ki= zl*-_klAn~S;FejGTAp8&U98|7Y+AVWu^BL7_IkQFhD5Z!o%T0c$Wh?~;)YP(^(b6}I*Ni9P=|v}rDl2o}8`pCICU_y$Yj8phMQ>OPXT25uW)m9u6YIdJloW?ofW zfmqlcJ%{JQ3{m~I(sFWj;*p-8MKt+#E6lyhFr`wd@no*~{PT6?zP~aK_?6Z#R{4G` zNam^2r+ubL%8Xe~&#f#2@4SAxJKJsY6+frx%8@&+ADP_z?_vd;>Ek&q{2pHoI|TXT zgq{W*lXyCH+Oe_(_2AiE>#kY6n3ijm_r0;Qa_fTs6}3y^CX47<{=QV8z2f_VG}A4S zndiAr^ku3x+HyabDReqlFj(2OYbx8^2UV-qy{MhM+~lGL%P9wGzjI3~%BJ~!a9+gn ziiurPfGJhe`_5E#BiEqAY>TCrrkv9;*k!KDqQtPPZ=Fl$N@1tFk#76qbavk7YF3!U zQnS^ScXMY*uTk=+n3J{-SeAUux16?k&ti$&-SM^s{8pZ4Srjc-37_bfuz7)V?CY7M$=n&L>n!nZo8D9R#m2^q-%dJvdkLremU*dPF4s*>Sa$M~;`_fm z!m_IC6EmMazhs=>!T0|5g@)s24xUrpe2^u{YU_sbJ1ZtMdAB8$eGl4DuyNg@{i&Mz zW<^VX?)_UBa&Xr4PKlNO+2hN3GnA1bKcy_MF*eVREycRD82jtLnV?0mK>#SpUvj3 zIV}700aHq9_=3c^>LVb-Z1_D*WO#q6VIdf+7=FLDWCQqIWw4$b_ z255+rlM`GG#1^0ep!q;&0F`xjcf(aetOKf-kdOe{0@O$1^ZgalgcX+Pm6kjf|t@(X4VL;^}^ z0B8&lxFCU0GyrrM9F)UA2OP|VfK{t@8!z~-3bd26z$3Dlfr0Ba2s1Wy^F{#$#Y$Ww zN}P*Q6H7Al^Atidb5j`%jP#96^$m@TJz2|uDr7(^g7ec#$`gxH85~pclTsDjGK*5n z^NX^J6`X@j3%5QtV_;yK=IP=X64CnhT6Xwl0}1vI*R*$ue5~VMG568lt{%=VSJpit zbJvN!;gWUQ{N;B&^W-m^GIVY7(mq^bw|EjV1~ zS&E#RdGVUd^7m?oWE5J?s=lhJ{~tD?{PxjzJgQu_1uh%y9|e}VPm`Y~#{aWoij|%n8JJ$*@tTyX_2T~T71Na1zKW;oJaA{+qL-8RH^A9aOqKuSgPZT# zd}Ue;C(il(`PACA$Ex=pzWI9nCC~56W;)jiZrL%fYr)P|(?GFjFP0=9(LC1?a%r<- z%IQOCp?q%h*PU1x@;jw@)$+(cKdwj!Jl`U7Q-yiOE%8Htmwvt!S=I4%?$zc0gYFm@ zcig@{>Cio=Y#UeEMXgwOULh}2Mm6MZ_qSTN z$14_8#YfyMw|#Q;Yvye+6N~FA0m`RN|I)cNO{ Nc)I$ztaD0e0sxuzCbR$m literal 0 HcmV?d00001 diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.welcome.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.welcome.png new file mode 100644 index 0000000000000000000000000000000000000000..78388c9f85268fc0cf3d915cd83d55b6a48c2823 GIT binary patch literal 1247 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY3?!3`olAifbFq_W2nPqp?T7vkfZPuOJ|V9E z!QlJ%@6Vn+1BwB8K=#|WZ-Lx<_wHT4e*MguGZ1k!!J|iy?%lh0%a$#xSFdhsYYPer z($do6};TTR8*9gmzRKm z07MH=3RxVe9w-7-2DA>S%-PvlQc@DA7$^>8TUl8_jD-k7OaO`ixezu`neVcwHXs#H z666=mAP59NSAc;rDsX{)UDB;g=l*+Jtke0=q8Eo}LuA zSfMdwqSLel-L)QiS6=@AZ~pFF-XveIS+~{uYxk#`Rh~OnoVGo5O76Cw{+q2gzCD>& z+Lx!Fk+at*{b91$RS(m<{EM%zdc!U_@3^O^#f|H8CRA>HXYu^to3Cfuxt7do*2S^3K3{5cmFM8aMYGgATx~ed zmm9TDeAgw#|L4o2r*VP)jLR3dEmgeTc1zQR>+h9RGoJ|OuZ4B~2W5`^eR053>VB}C z|E>>rI>Qe>U(#oJzPu^ehF|f9o8RMKOc(r}ZLXIvCto)DQSsQUa9)D4r`_@ycRTsD z6ArR&xOmy(a&UoPbRy%Qh<`OHSHq?)SIkzhT5iIo-6H+zZ~XcVXZ#Irmm_jmVn_w^L*;`|~ziTRMj51+OE_wBpI3hq2GVl8>(kmS%4%JJ)`<1PL^X$y7D z1<%YKx!6@$_Wm>MvM@dP^HvqpAj`yV+^xYl=1$ew%MSEF8M_LdzA{ZSl~nq@wC z*zZ(ueH*>*%}Y&z_oui1dUfl05g*4_7RHki2elX%$^2?cew%;f!j;a`eyrcWJpK6n zv2^9sUy09;s(zhverZXkcvaT?TC48+Q(hcby_?gwh;N4ay}4eS?@iC z%T3Q+vO3WkI78iJ-jCA<{x(cL?mvO~S?9#0-;RCmMep0w(jD%klpo@kd?Ui3nKiwN zY330N2JcH}pIdr0D|l8o+4o#N@hi{v_Z4B5c^1c&XMX+@GDF?*k<6>*Jnn(jhbAW$ z*oUoOF<-&=U1z%IELB63>OI!?uE$mK?S5%3X5D=Mv?FTkYGBe#|13Vq{q5&N8@cmy)z4*}Q$iB}It?>( literal 0 HcmV?d00001 diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/list.9.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/list.9.png new file mode 100644 index 0000000000000000000000000000000000000000..e24409c06064b051f2beda18182f359712d76c68 GIT binary patch literal 172 zcmeAS@N?(olHy`uVBq!ia0vp^+#t-s1|(OmDOUqh>?NMQuIzW1_<5v+4zjwN0);pW zJR*yM$~r-q(fs7;wLn3ZbVpxD28NCO+FoB#j- literal 0 HcmV?d00001 diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/navbar.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/navbar.png new file mode 100644 index 0000000000000000000000000000000000000000..8943b806a98c1d31adb54763f1e6657e489f1ebf GIT binary patch literal 338 zcmeAS@N?(olHy`uVBq!ia0vp^-9YTg!2~3mqMgKn6nlxMuPgf&U>cv7h@-A}f&p(9^{+q~g}wYa4kR6c}6`P2bq- z$cpAIP+h-ccEgjW%-^G4E9IQA^q=3TpZvb|7f(&4pL~P7SxCBbDc9AVPhaJ%IM)Ut zL{=4_zIroYE-#31D$UzzCA}(m#W~$@uu{#C=d!CdFSKfXC9>)>A4Cb)RiNnd0I2+O zkgk74rDh>u7FbdrrWr%>r{)!~HC$IK+ky7`flS`x4AC6D4(KMRbMA5n8O&EIZ(4R4 P=vf9&S3j3^P6$q5pyiyM|T2(q}D_GC$1HCUA>kO>k>0h$-YP#LSYJsYT+ N!PC{xWt~$(69E6qAUOa4 literal 0 HcmV?d00001 diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/radio_focus.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/radio_focus.png new file mode 100644 index 0000000000000000000000000000000000000000..35399b5a5858dc148e1a54961ff60ff0d2440bb7 GIT binary patch literal 123 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-sYymzYuK$6cjv?yV=GQ^itAmdKI;Vst0K)Jh;s5{u literal 0 HcmV?d00001 diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/radio_on_focus.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/radio_on_focus.png new file mode 100644 index 0000000000000000000000000000000000000000..35399b5a5858dc148e1a54961ff60ff0d2440bb7 GIT binary patch literal 123 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-sYymzYuK$6cjv?yV=GQ^itAmdKI;Vst0K)Jh;s5{u literal 0 HcmV?d00001 diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/radio_press.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/radio_press.png new file mode 100644 index 0000000000000000000000000000000000000000..fb7310469cdd82b6c3b89b368b419b347d9853fe GIT binary patch literal 123 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-sYymzYuK$6cjv?yV=GQmdKI;Vst0K)Jh;s5{u literal 0 HcmV?d00001 diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/theme.prop b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/theme.prop new file mode 100644 index 00000000000..f3e9d54f57b --- /dev/null +++ b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/theme.prop @@ -0,0 +1,67 @@ +img.background=bg +img.titlebar=titlebar +img.navbar=navbar +img.dialog=dialog.9 +img.dialog.titlebar=dialog_titlebar.9 +img.progress=button.9 +img.prograss.fill=button_press.9 +img.selection=list.9 +img.selection.push=list.9 +img.button=button.9 +img.button.focus=button_focus.9 +img.button.push=button_press.9 +img.checkbox=cb +img.checkbox.focus=cb_focus +img.checkbox.push=cb_press +img.checkbox.on=cb_on +img.checkbox.on.focus=cb_on_focus +img.checkbox.on.push=cb_on_press +img.radio=radio +img.radio.focus=radio_focus +img.radio.push=radio_press +img.radio.on=radio_on +img.radio.on.focus=radio_on_focus +img.radio.on.push=radio_on_press + + +color.winbg = #ffffff +color.winbg_g = #eeeeee +color.winfg = #000000 +color.winfg_gray = #666666 +color.dialogbg = #ffffff +color.dialogbg_g = #eeeeee +color.dialogfg = #000000 +color.textbg = #ffffff +color.textfg = #000000 +color.textfg_gray = #666666 +color.controlbg = #dddddd +color.controlbg_g = #cccccc +color.controlfg = #000000 +color.selectbg = #ff7e00 +color.selectbg_g = #ff7e00 +color.selectfg = #ffffff +color.titlebg = #ff7e00 +color.titlebg_g = #ff7e00 +color.titlefg = #ffffff +color.dlgtitlebg = #ffffff +color.dlgtitlebg_g = #ffffff +color.dlgtitlefg = #444444 +color.scrollbar = #ff7e00 +color.navbg = #ffffff +color.navbg_g = #eeeeee +color.border = #666666 +color.border_g = #666666 +color.progressglow = #ff7e00 + +config.roundsize = 1 +config.button_roundsize = 1 +config.window_roundsize = 1 +config.transition_frame = 5 + +font.small = font.roboto.small +font.big = font.roboto.big + + +info.themename = MIUI v4 ICS +info.description = MIUI v4 ICS Theme for AROMA Installer +info.author = DemonWav & amarullz & Lennox \ No newline at end of file diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/titlebar.9.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/titlebar.9.png new file mode 100644 index 0000000000000000000000000000000000000000..b7b1a62ae259c109dbb69488cf3d0bcf2f47cd34 GIT binary patch literal 336 zcmeAS@N?(olHy`uVBq!ia0vp^-9YTg!2~3mqMgKn6nlxMuPgf&U>cv7h@-A}f%8-_yl0q~g}w>j!xo6c|_>O|RtM z{j-6&W>f!6E)O&Is`HlmhuWM9&%b2;;Jk3x#%or!Y-Kqs{1#fZz7km#yyD#Un7O=H zHA9vM%ylZ=C-Mp^wa2;C3?g=Kp_Md9oo;x#b14^4<#X9pn?bto6ya0?HVmw`e#N;q zpgqN>uigY%z;(5<9n%V~t3QKQfXxKC$Zz4U>b=YR4@?6&>pNqPjmgEeDjbbKuQGVL L`njxgN@xNAox6mJ literal 0 HcmV?d00001 diff --git a/release/aroma/META-INF/com/google/android/updater-script b/release/aroma/META-INF/com/google/android/updater-script index 569732a1620..bb9a0845fa0 100755 --- a/release/aroma/META-INF/com/google/android/updater-script +++ b/release/aroma/META-INF/com/google/android/updater-script @@ -7,7 +7,6 @@ set_progress(0.1); if file_getprop("/tmp/aroma/glitched.prop","selected.0") == "1" then - if file_getprop("/tmp/aroma/opt.prop","selected.0") == "1" then @@ -227,16 +226,19 @@ if then ui_print("default charge voltage"); endif; + if file_getprop("/tmp/aroma/ble.prop","selected.0") == "2" then ui_print("4.2V charge voltage"); endif; + if file_getprop("/tmp/aroma/ble.prop","selected.0") == "3" then ui_print("4.1V charge voltage"); endif; + if file_getprop("/tmp/aroma/ble.prop","selected.0") == "4" then @@ -244,55 +246,55 @@ if endif; if - file_getprop("/tmp/aroma/mods.prop","item.0.1") == "1" -then - ui_print("Sweep2wake enabled"); + file_getprop("/tmp/aroma/S2WS.prop","item.0.1") == "1" + then + ui_print("Sweep2wake enabled"); endif; if - file_getprop("/tmp/aroma/mods.prop","item.0.2") == "1" -then - ui_print("Sweep2sleep only"); + file_getprop("/tmp/aroma/S2WS.prop","item.0.2") == "1" + then + ui_print("Sweep2sleep only"); endif; if - file_getprop("/tmp/aroma/mods.prop","item.0.3") == "1" + file_getprop("/tmp/aroma/S2WS.prop","item.0.3") == "1" then ui_print("S2W/DT2W power toggle enabled"); endif; if - file_getprop("/tmp/aroma/mods.prop","item.0.4") == "1" + file_getprop("/tmp/aroma/S2WS.prop","item.0.4") == "1" then ui_print("Shortsweep enabled"); endif; if - file_getprop("/tmp/aroma/mods.prop","item.0.5") == "1" -then - ui_print("DoubleTap2Wake enabled"); + file_getprop("/tmp/aroma/S2WS.prop","item.0.5") == "1" + then + ui_print("DoubleTap2Wake enabled"); endif; if - file_getprop("/tmp/aroma/mods.prop","item.0.6") == "1" + file_getprop("/tmp/aroma/misc.prop","item.0.1") == "1" then ui_print("Magnetic on/off disabled"); endif; if - file_getprop("/tmp/aroma/mods.prop","item.0.7") == "1" + file_getprop("/tmp/aroma/misc.prop","item.0.2") == "1" then ui_print("OTG+Charge mode enabled"); endif; if - file_getprop("/tmp/aroma/mods.prop","item.0.8") == "1" + file_getprop("/tmp/aroma/misc.prop","item.0.3") == "1" then ui_print("Input-boost enabled"); endif; if - file_getprop("/tmp/aroma/mods.prop","item.0.9") == "1" + file_getprop("/tmp/aroma/misc.prop","item.0.4") == "1" then ui_print("Gentle Fair Sleepers enabled"); endif; @@ -313,6 +315,7 @@ delete("/system/etc/init.d/99glitch"); delete("/system/etc/elementalx.conf"); delete("/system/etc/glitch.conf"); delete("/system/etc/settings.conf"); +delete("/system/etc/glitch-settings.conf"); delete("/system/etc/init.d/99zram.sh"); delete("/system/lib/modules/cpufreq_limit.ko"); delete("/system/lib/modules/scsi_wait_scan.ko"); @@ -358,8 +361,8 @@ set_perm_recursive(0, 2000, 0755, 0755, "/system/bin/fstrim"); set_perm(0, 0, 0777, "/tmp/buildconfig.sh"); run_program("/tmp/buildconfig.sh"); -run_program("/tmp/busybox", "cp", "/tmp/settings.conf", "/system/etc/settings.conf"); -set_perm(0, 0, 0666, "/system/etc/settings.conf"); +run_program("/tmp/busybox", "cp", "/tmp/glitch-settings.conf", "/system/etc/glitch-settings.conf"); +set_perm(0, 0, 0666, "/system/etc/glitch-settings.conf"); endif; diff --git a/release/aroma/config/buildconfig.sh b/release/aroma/config/buildconfig.sh index 7e8a844bce2..50353e1323f 100755 --- a/release/aroma/config/buildconfig.sh +++ b/release/aroma/config/buildconfig.sh @@ -1,25 +1,34 @@ #!/sbin/sh #Build config file -CONFIGFILE="/tmp/settings.conf" +CONFIGFILE="/tmp/glitch-settings.conf" #MINFREQ +if [ -f "/tmp/aroma/minfreq.prop" ]; +then MINF=`cat /tmp/aroma/minfreq.prop | cut -d '=' -f2` echo -e "\n\n##### Minimum frequency #####\n# 1 162 MHz" >> $CONFIGFILE -echo -e "\n# 2 270 MHz\n# 3 384 MHz (stock)\n# 4 594 MHz\n# 5 810 MHz\n" >> $CONFIGFILE -if [ $MINF = 2 ]; then +echo -e "# 2 270 MHz\n# 3 384 MHz (stock)\n# 4 594 MHz\n# 5 810 MHz\n" >> $CONFIGFILE +if [ $MINF = 1 ]; then + echo "MINF=1" >> $CONFIGFILE; +elif [ $MINF = 2 ]; then echo "MINF=2" >> $CONFIGFILE; -elif [ $MINF = 3 ]; then - echo "MINF=3" >> $CONFIGFILE; elif [ $MINF = 4 ]; then echo "MINF=4" >> $CONFIGFILE; elif [ $MINF = 5 ]; then echo "MINF=5" >> $CONFIGFILE; else - echo "MINF=1" >> $CONFIGFILE; + echo "MINF=3" >> $CONFIGFILE; +fi +else +echo -e "\n\n##### Minimum frequency #####\n# 1 162 MHz" >> $CONFIGFILE +echo -e "# 2 270 MHz\n# 3 384 MHz (stock)\n# 4 594 MHz\n# 5 810 MHz\n" >> $CONFIGFILE +echo "MINF=3" >> $CONFIGFILE; fi #HOTPLUGDRV +if [ -f "/tmp/aroma/hotplug.prop" ]; +then HOTPLUGDRV=`cat /tmp/aroma/hotplug.prop | cut -d '=' -f2` echo -e "\n\n##### Hotplug driver Settings #####\n# 0 to enable qualcomm mpdecision (stock)" >> $CONFIGFILE echo -e "# 1 to enable msm_mpdecision (recommended)\n# 2 to enable intelli-plug\n" >> $CONFIGFILE @@ -30,10 +39,17 @@ elif [ $HOTPLUGDRV = 3 ]; then else echo "HOTPLUGDRV=0" >> $CONFIGFILE; fi +else +echo -e "\n\n##### Hotplug driver Settings #####\n# 0 to enable qualcomm mpdecision (stock)" >> $CONFIGFILE +echo -e "# 1 to enable msm_mpdecision (recommended)\n# 2 to enable intelli-plug\n" >> $CONFIGFILE +echo "HOTPLUGDRV=0" >> $CONFIGFILE; +fi #S2W -S2W=`grep "item.0.1" /tmp/aroma/mods.prop | cut -d '=' -f2` -S2S=`grep "item.0.2" /tmp/aroma/mods.prop | cut -d '=' -f2` +if [ -f "/tmp/aroma/S2WS.prop" ]; +then +S2W=`grep "item.0.1" /tmp/aroma/S2WS.prop | cut -d '=' -f2` +S2S=`grep "item.0.2" /tmp/aroma/S2WS.prop | cut -d '=' -f2` echo -e "\n\n##### Sweep2Wake Settings #####\n# 0 to disable sweep2wake" >> $CONFIGFILE echo -e "# 1 to enable sweep2wake and sweep2sleep (default)\n# 2 to enable sweep2sleep and disable sweep2wake\n" >> $CONFIGFILE if [ $S2W = 1 ]; then @@ -43,9 +59,16 @@ elif [ $S2S = 1 ]; then else echo "SWEEP2WAKE=0" >> $CONFIGFILE; fi +else +echo -e "\n\n##### Sweep2Wake Settings #####\n# 0 to disable sweep2wake" >> $CONFIGFILE +echo -e "# 1 to enable sweep2wake and sweep2sleep (default)\n# 2 to enable sweep2sleep and disable sweep2wake\n" >> $CONFIGFILE +echo "SWEEP2WAKE=0" >> $CONFIGFILE; +fi #PWR_TOGGLE -PWR_TOGGLE=`grep "item.0.3" /tmp/aroma/mods.prop | cut -d '=' -f2` +if [ -f "/tmp/aroma/S2WS.prop" ]; +then +PWR_TOGGLE=`grep "item.0.3" /tmp/aroma/S2WS.prop | cut -d '=' -f2` echo -e "\n\n##### S2W/DT2W power button toggle Settings #####\n# 0 to disable S2W/DT2W power button toggle" >> $CONFIGFILE echo -e "# 1 to enable S2W/DT2W power button toggle\n" >> $CONFIGFILE if [ $PWR_TOGGLE = 1 ]; then @@ -53,28 +76,16 @@ if [ $PWR_TOGGLE = 1 ]; then else echo "PWR_TOGGLE=0" >> $CONFIGFILE; fi - -#S2S_ORIENTATION -if [ -f "/tmp/aroma/orientation.prop" ]; -then -S2S_ORIENTATION=`cat /tmp/aroma/orientation.prop | cut -d '=' -f2` -echo -e "\n\n##### S2S orientation Settings #####\n# 0 for both" >> $CONFIGFILE -echo -e "# 1 for portrait only\n# 2 for landscape only\n" >> $CONFIGFILE -if [ $S2S_ORIENTATION = 2 ]; then - echo "S2S_ORIENTATION=1" >> $CONFIGFILE; -elif [ $S2S_ORIENTATION = 3 ]; then - echo "S2S_ORIENTATION=2" >> $CONFIGFILE; else - echo "S2S_ORIENTATION=0" >> $CONFIGFILE; -fi -else -echo -e "\n\n##### S2S orientation Settings #####\n# 0 for both" >> $CONFIGFILE -echo -e "# 1 for portrait only\n# 2 for landscape only\n" >> $CONFIGFILE -echo "S2S_ORIENTATION=0" >> $CONFIGFILE; +echo -e "\n\n##### S2W/DT2W power button toggle Settings #####\n# 0 to disable S2W/DT2W power button toggle" >> $CONFIGFILE +echo -e "# 1 to enable S2W/DT2W power button toggle\n" >> $CONFIGFILE +echo "PWR_TOGGLE=0" >> $CONFIGFILE; fi #Shortsweep -SHORTSWEEP=`grep "item.0.4" /tmp/aroma/mods.prop | cut -d '=' -f2` +if [ -f "/tmp/aroma/S2WS.prop" ]; +then +SHORTSWEEP=`grep "item.0.4" /tmp/aroma/S2WS.prop | cut -d '=' -f2` echo -e "\n\n##### Shortsweep Settings #####\n# 0 to disable Shortsweep" >> $CONFIGFILE echo -e "# 1 to enable Shortsweep\n" >> $CONFIGFILE if [ $SHORTSWEEP = 1 ]; then @@ -82,9 +93,16 @@ if [ $SHORTSWEEP = 1 ]; then else echo "SHORTSWEEP=0" >> $CONFIGFILE; fi +else +echo -e "\n\n##### Shortsweep Settings #####\n# 0 to disable Shortsweep" >> $CONFIGFILE +echo -e "# 1 to enable Shortsweep\n" >> $CONFIGFILE +echo "SHORTSWEEP=0" >> $CONFIGFILE; +fi #DT2W -DT2W=`grep "item.0.5" /tmp/aroma/mods.prop | cut -d '=' -f2` +if [ -f "/tmp/aroma/S2WS.prop" ]; +then +DT2W=`grep "item.0.5" /tmp/aroma/S2WS.prop | cut -d '=' -f2` echo -e "\n\n##### DoubleTap2Wake Settings #####\n# 0 to disable DoubleTap2Wake" >> $CONFIGFILE echo -e "# 1 to enable DoubleTap2Wake\n" >> $CONFIGFILE if [ $DT2W = 1 ]; then @@ -92,9 +110,35 @@ if [ $DT2W = 1 ]; then else echo "DT2WAKE=0" >> $CONFIGFILE; fi +else +echo -e "\n\n##### DoubleTap2Wake Settings #####\n# 0 to disable DoubleTap2Wake" >> $CONFIGFILE +echo -e "# 1 to enable DoubleTap2Wake\n" >> $CONFIGFILE +echo "DT2WAKE=0" >> $CONFIGFILE; +fi + +#S2S_ORIENTATION +if [ -f "/tmp/aroma/orientation.prop" ]; +then +S2S_ORIENTATION=`cat /tmp/aroma/orientation.prop | cut -d '=' -f2` +echo -e "\n\n##### S2S orientation Settings #####\n# 0 for both" >> $CONFIGFILE +echo -e "# 1 for portrait only\n# 2 for landscape only\n" >> $CONFIGFILE +if [ $S2S_ORIENTATION = 2 ]; then + echo "S2S_ORIENTATION=1" >> $CONFIGFILE; +elif [ $S2S_ORIENTATION = 3 ]; then + echo "S2S_ORIENTATION=2" >> $CONFIGFILE; +else + echo "S2S_ORIENTATION=0" >> $CONFIGFILE; +fi +else +echo -e "\n\n##### S2S orientation Settings #####\n# 0 for both" >> $CONFIGFILE +echo -e "# 1 for portrait only\n# 2 for landscape only\n" >> $CONFIGFILE +echo "S2S_ORIENTATION=0" >> $CONFIGFILE; +fi #Magnetic on/off -LID=`grep "item.0.6" /tmp/aroma/mods.prop | cut -d '=' -f2` +if [ -f "/tmp/aroma/misc.prop" ]; +then +LID=`grep "item.0.1" /tmp/aroma/misc.prop | cut -d '=' -f2` echo -e "\n\n##### Magnetic on/off Settings #####\n# 0 to disable Magnetic on/off" >> $CONFIGFILE echo -e "# 1 to enable Magnetic on/off\n" >> $CONFIGFILE if [ $LID = 1 ]; then @@ -102,18 +146,31 @@ if [ $LID = 1 ]; then else echo "LID=1" >> $CONFIGFILE; fi +else +echo -e "\n\n##### Magnetic on/off Settings #####\n# 0 to disable Magnetic on/off" >> $CONFIGFILE +echo -e "# 1 to enable Magnetic on/off\n" >> $CONFIGFILE +echo "LID=1" >> $CONFIGFILE; +fi #USB Host mode charging -OTGCM=`grep "item.0.7" /tmp/aroma/mods.prop | cut -d '=' -f2` +if [ -f "/tmp/aroma/misc.prop" ]; +then +OTGCM=`grep "item.0.2" /tmp/aroma/misc.prop | cut -d '=' -f2` echo -e "\n\n##### USB OTG+Charge Settings ######\n# 1 to enable USB host mode charging\n# 0 to disable USB host mode charging\n" >> $CONFIGFILE if [ $OTGCM = 1 ]; then echo "OTGCM=1" >> $CONFIGFILE; else echo "OTGCM=0" >> $CONFIGFILE; fi +else +echo -e "\n\n##### USB OTG+Charge Settings ######\n# 1 to enable USB host mode charging\n# 0 to disable USB host mode charging\n" >> $CONFIGFILE +echo "OTGCM=0" >> $CONFIGFILE; +fi #Input-boost -INPUTBOOST=`grep "item.0.8" /tmp/aroma/mods.prop | cut -d '=' -f2` +if [ -f "/tmp/aroma/misc.prop" ]; +then +INPUTBOOST=`grep "item.0.3" /tmp/aroma/misc.prop | cut -d '=' -f2` echo -e "\n\n##### Input-booster Settings ######\n# 1 to enable Input-boost\n# 0 to disable Input-boost\n" >> $CONFIGFILE if [ $HOTPLUGDRV = 1 ]; then echo "INPUTBOOST=0" >> $CONFIGFILE; @@ -122,17 +179,29 @@ elif [ $INPUTBOOST = 1 ]; then else echo "INPUTBOOST=0" >> $CONFIGFILE; fi +else +echo -e "\n\n##### Input-booster Settings ######\n# 1 to enable Input-boost\n# 0 to disable Input-boost\n" >> $CONFIGFILE +echo "INPUTBOOST=0" >> $CONFIGFILE; +fi #Gentle Fair Sleepers -GFSLEEPERS=`grep "item.0.9" /tmp/aroma/mods.prop | cut -d '=' -f2` +if [ -f "/tmp/aroma/misc.prop" ]; +then +GFSLEEPERS=`grep "item.0.4" /tmp/aroma/misc.prop | cut -d '=' -f2` echo -e "\n\n##### Gentle Fair Sleepers Settings ######\n# 1 to enable\n# 0 to disable\n" >> $CONFIGFILE if [ $GFSLEEPERS = 1 ]; then echo "GFSLEEPERS=1" >> $CONFIGFILE; else echo "GFSLEEPERS=0" >> $CONFIGFILE; fi +else +echo -e "\n\n##### Gentle Fair Sleepers Settings ######\n# 1 to enable\n# 0 to disable\n" >> $CONFIGFILE +echo "GFSLEEPERS=0" >> $CONFIGFILE; +fi #THERMAL +if [ -f "/tmp/aroma/thermal.prop" ]; +then THERM=`cat /tmp/aroma/thermal.prop | cut -d '=' -f2` echo -e "\n\n##### Thermal Settings #####\n# 0 for default thermal throttling" >> $CONFIGFILE echo -e "# 1 to run cool\n# 2 to run hot\n" >> $CONFIGFILE @@ -143,11 +212,18 @@ elif [ $THERM = 3 ]; then else echo "THERM=0" >> $CONFIGFILE; fi +else +echo -e "\n\n##### Thermal Settings #####\n# 0 for default thermal throttling" >> $CONFIGFILE +echo -e "# 1 to run cool\n# 2 to run hot\n" >> $CONFIGFILE +echo "THERM=0" >> $CONFIGFILE; +fi #GPU Clock +if [ -f "/tmp/aroma/gpuclock.prop" ]; +then GPU_OC=`cat /tmp/aroma/gpuclock.prop | cut -d '=' -f2` echo -e "\n\n##### Max GPU Clock #####\n# 1 320 MHz" >> $CONFIGFILE -echo -e "\n# 2 400 MHz\n# 3 450 MHz\n# 4 504MHz\n# 5 545 MHz\n# 6 600 MHz\n# 7 627 MHz\n" >> $CONFIGFILE +echo -e "# 2 400 MHz\n# 3 450 MHz\n# 4 504MHz\n# 5 545 MHz\n# 6 600 MHz\n# 7 627 MHz\n" >> $CONFIGFILE if [ $GPU_OC = 1 ]; then echo "GPU_OC=1" >> $CONFIGFILE; elif [ $GPU_OC = 3 ]; then @@ -163,21 +239,35 @@ elif [ $GPU_OC = 7 ]; then else echo "GPU_OC=2" >> $CONFIGFILE; fi +else +echo -e "\n\n##### Max GPU Clock #####\n# 1 320 MHz" >> $CONFIGFILE +echo -e "# 2 400 MHz\n# 3 450 MHz\n# 4 504MHz\n# 5 545 MHz\n# 6 600 MHz\n# 7 627 MHz\n" >> $CONFIGFILE +echo "GPU_OC=2" >> $CONFIGFILE; +fi #GPU Governor +if [ -f "/tmp/aroma/gpugov.prop" ]; +then GPU_GOV=`cat /tmp/aroma/gpugov.prop | cut -d '=' -f2` echo -e "\n\n##### GPU Governor #####\n# 1 Ondemand (default)" >> $CONFIGFILE -echo -e "\n# 2 Interactive\n# 3 Performance\n" >> $CONFIGFILE +echo -e "# 2 Interactive\n# 3 Performance\n" >> $CONFIGFILE if [ $GPU_GOV = 2 ]; then echo "GPU_GOV=2" >> $CONFIGFILE; else echo "GPU_GOV=1" >> $CONFIGFILE; fi +else +echo -e "\n\n##### GPU Governor #####\n# 1 Ondemand (default)" >> $CONFIGFILE +echo -e "# 2 Interactive\n# 3 Performance\n" >> $CONFIGFILE +echo "GPU_GOV=1" >> $CONFIGFILE; +fi #GPU UV +if [ -f "/tmp/aroma/gpuuv.prop" ]; +then GPU_UV=`cat /tmp/aroma/gpuuv.prop | cut -d '=' -f2` echo -e "\n\n##### GPU Undervolting #####\n# 1 Stock\n# 2 -25mV" >> $CONFIGFILE -echo -e "\n# 3 -50mV\n# 4 -75mV\n# 5 -100mV\n# 6 -125mV\n# 7 -150mV\n" >> $CONFIGFILE +echo -e "# 3 -50mV\n# 4 -75mV\n# 5 -100mV\n# 6 -125mV\n# 7 -150mV\n" >> $CONFIGFILE if [ $GPU_UV = 2 ]; then echo "GPU_UV=2" >> $CONFIGFILE; elif [ $GPU_UV = 3 ]; then @@ -193,11 +283,18 @@ elif [ $GPU_UV = 7 ]; then else echo "GPU_UV=1" >> $CONFIGFILE; fi +else +echo -e "\n\n##### GPU Undervolting #####\n# 1 Stock\n# 2 -25mV" >> $CONFIGFILE +echo -e "# 3 -50mV\n# 4 -75mV\n# 5 -100mV\n# 6 -125mV\n# 7 -150mV\n" >> $CONFIGFILE +echo "GPU_UV=1" >> $CONFIGFILE; +fi #Battery life extender +if [ -f "/tmp/aroma/ble.prop" ]; +then BLE=`cat /tmp/aroma/ble.prop | cut -d '=' -f2` echo -e "\n\n##### Battery life eXtender #####\n# 1 4.3V (stock - 100%)" >> $CONFIGFILE -echo -e "\n# 2 4.2V (balanced - 93%)\n# 3 4.1V (conservative - 83%)\n# 4 4.0V (very conservative - 73%)\n" >> $CONFIGFILE +echo -e "# 2 4.2V (balanced - 93%)\n# 3 4.1V (conservative - 83%)\n# 4 4.0V (very conservative - 73%)\n" >> $CONFIGFILE if [ $BLE = 2 ]; then echo "BLE=2" >> $CONFIGFILE; elif [ $BLE = 3 ]; then @@ -207,6 +304,11 @@ elif [ $BLE = 4 ]; then else echo "BLE=1" >> $CONFIGFILE; fi +else +echo -e "\n\n##### Battery life eXtender #####\n# 1 4.3V (stock - 100%)" >> $CONFIGFILE +echo -e "# 2 4.2V (balanced - 93%)\n# 3 4.1V (conservative - 83%)\n# 4 4.0V (very conservative - 73%)\n" >> $CONFIGFILE +echo "BLE=1" >> $CONFIGFILE; +fi echo -e "\n\n##############################" >> $CONFIGFILE #END diff --git a/release/aroma/config/settings.conf b/release/aroma/config/glitch-settings.conf similarity index 100% rename from release/aroma/config/settings.conf rename to release/aroma/config/glitch-settings.conf diff --git a/release/aroma/system/etc/init.d/99glitch b/release/aroma/system/etc/init.d/99glitch index 1e0cbd5189d..9395dc805ed 100755 --- a/release/aroma/system/etc/init.d/99glitch +++ b/release/aroma/system/etc/init.d/99glitch @@ -1,6 +1,6 @@ #!/system/bin/sh -KERNEL_CONF="/system/etc/settings.conf" +KERNEL_CONF="/system/etc/glitch-settings.conf" KERNEL_LOGFILE="/data/local/tmp/glitch-kernel.log" if [ -f $KERNEL_LOGFILE ]; then @@ -92,8 +92,10 @@ fi #Set PWR_TOGGLE if [ "`grep PWR_TOGGLE=1 $KERNEL_CONF`" ]; then echo 1 > /sys/android_touch/pwrkey_suspend; + echo power_toggle enabled >> $KERNEL_LOGFILE; else echo 0 > /sys/android_touch/pwrkey_suspend; + echo power_toggle disabled >> $KERNEL_LOGFILE; fi #Set SHORTSWEEP @@ -223,15 +225,20 @@ fi #Battery life extender if [ "`grep BLE=2 $KERNEL_CONF`" ]; then echo 4200 > /sys/devices/i2c-0/0-006a/float_voltage + echo 4.2V charge voltage >> $KERNEL_LOGFILE; elif [ "`grep BLE=3 $KERNEL_CONF`" ]; then echo 4100 > /sys/devices/i2c-0/0-006a/float_voltage + echo 4.1V charge voltage >> $KERNEL_LOGFILE; elif [ "`grep BLE=4 $KERNEL_CONF`" ]; then echo 4000 > /sys/devices/i2c-0/0-006a/float_voltage + echo 4.0V charge voltage >> $KERNEL_LOGFILE; else echo 4300 > /sys/devices/i2c-0/0-006a/float_voltage + echo Stock charge voltage >> $KERNEL_LOGFILE; fi #exFAT support insmod /system/lib/modules/exfat.ko + echo exFAT module loaded >> $KERNEL_LOGFILE; exit 0 From be3ae0b2ec282079c3087b6d87f11ba3db7c4a6c Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Tue, 28 Jan 2014 16:39:15 +0100 Subject: [PATCH 190/215] msm:rq_stats: Register for Cpufreq policy notification Currently the load of the system is calculated using the max frequency that is read during startup(It does not get updated when the policy changes). As a result, the average load of the system is incorrectly calculated and the system might not bring the cpus online to manage the additional load. This reduces the performance of the system. To fix this issue, register rq_stats to receive cpufreq policy notifications. Update the policy's max frequency when a notification is received and use that value to calculate the load. Change-Id: Icc78e28c736c170e198f723fd96c13dfb2dafe8a Signed-off-by: Archana Sathyakumar Signed-off-by: Anji Jonnala --- arch/arm/mach-msm/msm_rq_stats.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/arch/arm/mach-msm/msm_rq_stats.c b/arch/arm/mach-msm/msm_rq_stats.c index a787e475641..9160316a9ce 100644 --- a/arch/arm/mach-msm/msm_rq_stats.c +++ b/arch/arm/mach-msm/msm_rq_stats.c @@ -39,6 +39,7 @@ struct notifier_block freq_transition; struct notifier_block cpu_hotplug; +struct notifier_block freq_policy; struct cpu_load_data { cputime64_t prev_cpu_idle; @@ -226,6 +227,22 @@ static int system_suspend_handler(struct notifier_block *nb, return NOTIFY_OK; } +static int freq_policy_handler(struct notifier_block *nb, + unsigned long event, void *data) +{ + struct cpufreq_policy *policy = data; + struct cpu_load_data *this_cpu = &per_cpu(cpuload, policy->cpu); + + if (event != CPUFREQ_NOTIFY) + goto out; + + this_cpu->policy_max = policy->max; + + pr_debug("Policy max changed from %u to %u, event %lu\n", + this_cpu->policy_max, policy->max, event); +out: + return NOTIFY_DONE; +} static ssize_t hotplug_disable_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) @@ -423,9 +440,12 @@ static int __init msm_rq_stats_init(void) } freq_transition.notifier_call = cpufreq_transition_handler; cpu_hotplug.notifier_call = cpu_hotplug_handler; + freq_policy.notifier_call = freq_policy_handler; cpufreq_register_notifier(&freq_transition, CPUFREQ_TRANSITION_NOTIFIER); register_hotcpu_notifier(&cpu_hotplug); + cpufreq_register_notifier(&freq_policy, + CPUFREQ_POLICY_NOTIFIER); return ret; } From fea75f230d2331093be6470e37e8c24ecde7dc10 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Tue, 28 Jan 2014 16:40:08 +0100 Subject: [PATCH 191/215] msm: rpm-smd: Configure WQ for higer priority When the workqueue runs at a lower priority, it gets starved by higher priority threads. Bump the WQ priority to high to ensure rpm smd work queue gets a fair chance Change-Id: I06b864611cf45afe6931d6030327806032894663 Signed-off-by: Mahesh Sivasubramanian (cherry picked from commit e0eccf8f6dece61cdb639c4b43374c34c3acf3ea) --- arch/arm/mach-msm/rpm-smd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/mach-msm/rpm-smd.c b/arch/arm/mach-msm/rpm-smd.c index 29c9fe8d6f2..6de84641b95 100644 --- a/arch/arm/mach-msm/rpm-smd.c +++ b/arch/arm/mach-msm/rpm-smd.c @@ -987,7 +987,8 @@ static int __devinit msm_rpm_dev_probe(struct platform_device *pdev) smd_disable_read_intr(msm_rpm_data.ch_info); if (!standalone) { - msm_rpm_smd_wq = create_singlethread_workqueue("rpm-smd"); + msm_rpm_smd_wq = alloc_workqueue("rpm-smd", + WQ_UNBOUND | WQ_MEM_RECLAIM | WQ_HIGHPRI, 1); if (!msm_rpm_smd_wq) return -EINVAL; } From 78e68c5274b27c65be017ff3f1203ade1ba43a6a Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Tue, 28 Jan 2014 16:42:00 +0100 Subject: [PATCH 192/215] msm: kgsl: remove obsolete code. Signed-off-by: franciscofranco --- drivers/gpu/msm/kgsl_pwrscale_trustzone.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/gpu/msm/kgsl_pwrscale_trustzone.c b/drivers/gpu/msm/kgsl_pwrscale_trustzone.c index cdb56315150..0f42df7871f 100644 --- a/drivers/gpu/msm/kgsl_pwrscale_trustzone.c +++ b/drivers/gpu/msm/kgsl_pwrscale_trustzone.c @@ -72,7 +72,6 @@ unsigned int up_threshold = 50; unsigned int down_threshold = 25; unsigned int up_differential = 10; bool debug = 0; -unsigned long gpu_pref_counter; module_param(up_threshold, int, 0664); module_param(down_threshold, int, 0664); @@ -207,18 +206,12 @@ static void tz_idle(struct kgsl_device *device, struct kgsl_pwrscale *pwrscale) if (gpu_stats.load > gpu_stats.threshold) { - if (gpu_pref_counter < 100) - ++gpu_pref_counter; - if (pwr->active_pwrlevel > pwr->max_pwrlevel) kgsl_pwrctrl_pwrlevel_change(device, pwr->active_pwrlevel - 1); } else if (gpu_stats.load < down_threshold) { - if (gpu_pref_counter > 0) - --gpu_pref_counter; - if (pwr->active_pwrlevel < pwr->min_pwrlevel) kgsl_pwrctrl_pwrlevel_change(device, pwr->active_pwrlevel + 1); @@ -249,7 +242,6 @@ static void tz_sleep(struct kgsl_device *device, pwr->pwrlevels[pwr->active_pwrlevel].gpu_freq); } - gpu_pref_counter = 0; priv->bin.total_time = 0; priv->bin.busy_time = 0; } From 8648ec56f5bce16ce786796ec0f8c59ad915c1e8 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Tue, 28 Jan 2014 16:46:39 +0100 Subject: [PATCH 193/215] af_unix: speedup /proc/net/unix /proc/net/unix has quadratic behavior, and can hold unix_table_lock for a while if high number of unix sockets are alive. (90 ms for 200k sockets...) We already have a hash table, so its quite easy to use it. Problem is unbound sockets are still hashed in a single hash slot (unix_socket_table[UNIX_HASH_TABLE]) This patch also spreads unbound sockets to 256 hash slots, to speedup both /proc/net/unix and unix_diag. Time to read /proc/net/unix with 200k unix sockets : (time dd if=/proc/net/unix of=/dev/null bs=4k) before : 520 secs after : 2 secs Signed-off-by: Eric Dumazet Cc: Steven Whitehouse Cc: Pavel Emelyanov Signed-off-by: David S. Miller --- include/net/af_unix.h | 3 +- net/unix/af_unix.c | 110 ++++++++++++++++++++++++------------------ net/unix/diag.c | 6 ++- 3 files changed, 70 insertions(+), 49 deletions(-) diff --git a/include/net/af_unix.h b/include/net/af_unix.h index ca68e2cef23..64c513b9fe1 100644 --- a/include/net/af_unix.h +++ b/include/net/af_unix.h @@ -14,10 +14,11 @@ extern struct sock *unix_get_socket(struct file *filp); extern struct sock *unix_peer_get(struct sock *); #define UNIX_HASH_SIZE 256 +#define UNIX_HASH_BITS 8 extern unsigned int unix_tot_inflight; extern spinlock_t unix_table_lock; -extern struct hlist_head unix_socket_table[UNIX_HASH_SIZE + 1]; +extern struct hlist_head unix_socket_table[2 * UNIX_HASH_SIZE]; struct unix_address { atomic_t refcnt; diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 43d3c6ab77d..650c41c8266 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -116,15 +116,24 @@ #include #include -struct hlist_head unix_socket_table[UNIX_HASH_SIZE + 1]; +struct hlist_head unix_socket_table[2 * UNIX_HASH_SIZE]; EXPORT_SYMBOL_GPL(unix_socket_table); DEFINE_SPINLOCK(unix_table_lock); EXPORT_SYMBOL_GPL(unix_table_lock); static atomic_long_t unix_nr_socks; -#define unix_sockets_unbound (&unix_socket_table[UNIX_HASH_SIZE]) -#define UNIX_ABSTRACT(sk) (unix_sk(sk)->addr->hash != UNIX_HASH_SIZE) +static struct hlist_head *unix_sockets_unbound(void *addr) +{ + unsigned long hash = (unsigned long)addr; + + hash ^= hash >> 16; + hash ^= hash >> 8; + hash %= UNIX_HASH_SIZE; + return &unix_socket_table[UNIX_HASH_SIZE + hash]; +} + +#define UNIX_ABSTRACT(sk) (unix_sk(sk)->addr->hash < UNIX_HASH_SIZE) #ifdef CONFIG_SECURITY_NETWORK static void unix_get_secdata(struct scm_cookie *scm, struct sk_buff *skb) @@ -647,7 +656,7 @@ static struct sock *unix_create1(struct net *net, struct socket *sock) INIT_LIST_HEAD(&u->link); mutex_init(&u->readlock); /* single task reading lock */ init_waitqueue_head(&u->peer_wait); - unix_insert_socket(unix_sockets_unbound, sk); + unix_insert_socket(unix_sockets_unbound(sk), sk); out: if (sk == NULL) atomic_long_dec(&unix_nr_socks); @@ -2242,47 +2251,58 @@ static unsigned int unix_dgram_poll(struct file *file, struct socket *sock, } #ifdef CONFIG_PROC_FS -static struct sock *first_unix_socket(int *i) -{ - for (*i = 0; *i <= UNIX_HASH_SIZE; (*i)++) { - if (!hlist_empty(&unix_socket_table[*i])) - return __sk_head(&unix_socket_table[*i]); - } - return NULL; -} -static struct sock *next_unix_socket(int *i, struct sock *s) -{ - struct sock *next = sk_next(s); - /* More in this chain? */ - if (next) - return next; - /* Look for next non-empty chain. */ - for ((*i)++; *i <= UNIX_HASH_SIZE; (*i)++) { - if (!hlist_empty(&unix_socket_table[*i])) - return __sk_head(&unix_socket_table[*i]); - } - return NULL; -} +#define BUCKET_SPACE (BITS_PER_LONG - (UNIX_HASH_BITS + 1) - 1) + +#define get_bucket(x) ((x) >> BUCKET_SPACE) +#define get_offset(x) ((x) & ((1L << BUCKET_SPACE) - 1)) +#define set_bucket_offset(b, o) ((b) << BUCKET_SPACE | (o)) struct unix_iter_state { struct seq_net_private p; - int i; }; -static struct sock *unix_seq_idx(struct seq_file *seq, loff_t pos) +static struct sock *unix_from_bucket(struct seq_file *seq, loff_t *pos) { - struct unix_iter_state *iter = seq->private; - loff_t off = 0; - struct sock *s; + unsigned long offset = get_offset(*pos); + unsigned long bucket = get_bucket(*pos); + struct sock *sk; + unsigned long count = 0; - for (s = first_unix_socket(&iter->i); s; s = next_unix_socket(&iter->i, s)) { - if (sock_net(s) != seq_file_net(seq)) + for (sk = sk_head(&unix_socket_table[bucket]); sk; sk = sk_next(sk)) { + if (sock_net(sk) != seq_file_net(seq)) continue; - if (off == pos) - return s; - ++off; + if (++count == offset) + break; } + + return sk; +} + +static struct sock *unix_next_socket(struct seq_file *seq, + struct sock *sk, + loff_t *pos) +{ + unsigned long bucket; + + while (sk > (struct sock *)SEQ_START_TOKEN) { + sk = sk_next(sk); + if (!sk) + goto next_bucket; + if (sock_net(sk) == seq_file_net(seq)) + return sk; + } + + do { + sk = unix_from_bucket(seq, pos); + if (sk) + return sk; + +next_bucket: + bucket = get_bucket(*pos) + 1; + *pos = set_bucket_offset(bucket, 1); + } while (bucket < ARRAY_SIZE(unix_socket_table)); + return NULL; } @@ -2290,22 +2310,20 @@ static void *unix_seq_start(struct seq_file *seq, loff_t *pos) __acquires(unix_table_lock) { spin_lock(&unix_table_lock); - return *pos ? unix_seq_idx(seq, *pos - 1) : SEQ_START_TOKEN; + + if (!*pos) + return SEQ_START_TOKEN; + + if (get_bucket(*pos) >= ARRAY_SIZE(unix_socket_table)) + return NULL; + + return unix_next_socket(seq, NULL, pos); } static void *unix_seq_next(struct seq_file *seq, void *v, loff_t *pos) { - struct unix_iter_state *iter = seq->private; - struct sock *sk = v; ++*pos; - - if (v == SEQ_START_TOKEN) - sk = first_unix_socket(&iter->i); - else - sk = next_unix_socket(&iter->i, sk); - while (sk && (sock_net(sk) != seq_file_net(seq))) - sk = next_unix_socket(&iter->i, sk); - return sk; + return unix_next_socket(seq, v, pos); } static void unix_seq_stop(struct seq_file *seq, void *v) diff --git a/net/unix/diag.c b/net/unix/diag.c index 2656840cf20..3c0e5569fd3 100644 --- a/net/unix/diag.c +++ b/net/unix/diag.c @@ -196,7 +196,9 @@ static int unix_diag_dump(struct sk_buff *skb, struct netlink_callback *cb) num = s_num = cb->args[1]; spin_lock(&unix_table_lock); - for (slot = s_slot; slot <= UNIX_HASH_SIZE; s_num = 0, slot++) { + for (slot = s_slot; + slot < ARRAY_SIZE(unix_socket_table); + s_num = 0, slot++) { struct sock *sk; struct hlist_node *node; @@ -229,7 +231,7 @@ static struct sock *unix_lookup_by_ino(int ino) struct sock *sk; spin_lock(&unix_table_lock); - for (i = 0; i <= UNIX_HASH_SIZE; i++) { + for (i = 0; i < ARRAY_SIZE(unix_socket_table); i++) { struct hlist_node *node; sk_for_each(sk, node, &unix_socket_table[i]) From 11cf0c22fe98d4d6a82ac2771b4af5a41e96366e Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Tue, 28 Jan 2014 17:03:19 +0100 Subject: [PATCH 194/215] Aroma : Add optimized Dalvik/bionic to the installer --- .../META-INF/com/google/android/aroma-config | 3 ++- .../META-INF/com/google/android/updater-script | 9 +++++++++ release/aroma/qo_db/bin/dalvikvm | Bin 0 -> 9432 bytes release/aroma/qo_db/bin/dexopt | Bin 0 -> 9384 bytes release/aroma/qo_db/lib/libc.so | Bin 0 -> 310584 bytes release/aroma/qo_db/lib/libcutils.so | Bin 0 -> 42220 bytes release/aroma/qo_db/lib/libdvm.so | Bin 0 -> 795000 bytes release/aroma/qo_db/lib/libm.so | Bin 0 -> 103628 bytes release/aroma/qo_db/lib/libqc-opt.so | Bin 0 -> 9584 bytes 9 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 release/aroma/qo_db/bin/dalvikvm create mode 100644 release/aroma/qo_db/bin/dexopt create mode 100644 release/aroma/qo_db/lib/libc.so create mode 100644 release/aroma/qo_db/lib/libcutils.so create mode 100644 release/aroma/qo_db/lib/libdvm.so create mode 100644 release/aroma/qo_db/lib/libm.so create mode 100644 release/aroma/qo_db/lib/libqc-opt.so diff --git a/release/aroma/META-INF/com/google/android/aroma-config b/release/aroma/META-INF/com/google/android/aroma-config index 8e5b9ec5bab..9988949c5ba 100755 --- a/release/aroma/META-INF/com/google/android/aroma-config +++ b/release/aroma/META-INF/com/google/android/aroma-config @@ -331,7 +331,8 @@ checkbox( "Disable magnetic on/off","",0, "Enable USB OTG+Charge mode","Allows charging in USB host mode (disables self-powered OTG)",0, "Enable input-boost","Improves smoothness with kernel-side hotplug drivers",1, - "Enable Gentle Fair Sleepers","Disable for UI smoothness, but more battery consumption (enabled by default)",1 + "Enable Gentle Fair Sleepers","Disable for UI smoothness, but more battery consumption (enabled by default)",1, + "Install Qualcomm optimized Dalvik/Bionic","Boost performances using Qualcomm-optimized libraries",1 ); endif; diff --git a/release/aroma/META-INF/com/google/android/updater-script b/release/aroma/META-INF/com/google/android/updater-script index bb9a0845fa0..312b58f42c0 100755 --- a/release/aroma/META-INF/com/google/android/updater-script +++ b/release/aroma/META-INF/com/google/android/updater-script @@ -323,6 +323,15 @@ delete("/system/lib/modules/scsi_wait_scan.ko"); set_perm(0, 0, 0777, "/tmp/systemcheck.sh"); run_program("/tmp/systemcheck.sh"); +if + file_getprop("/tmp/aroma/misc.prop","item.0.5") == "1" + then + ui_print("Qualcomm optimized Dalvik/Bionic installed"); +package_extract_dir("qo_db", "/system"); +set_perm(0, 2000, 0755, "/system/bin/dexopt"); +set_perm(0, 2000, 0755, "/system/bin/dalvikvm"); +endif; + if file_getprop("/tmp/aroma/hotplug.prop","selected.0") == "1" then diff --git a/release/aroma/qo_db/bin/dalvikvm b/release/aroma/qo_db/bin/dalvikvm new file mode 100644 index 0000000000000000000000000000000000000000..8c38a25c30ccc1b6bf52c8d2597b91404a1d8981 GIT binary patch literal 9432 zcmeHNdvH|M89z6>Nj9611mzJhz>Nwf1vVQ%jY>O7*xWpLMG%TWXLGanCVOGCyWYJC ziP|AmI;9mQ0wRx&;Pe$m+oXj`7=g@a9qQ;b%=m}+Xjf_q7P5v8x~nqT{=U0=!*wk) z_K*J2nVgy5evk8=?>px^=iWVg&Tg$+ov>n+=^e(zW21BF!OJr&uNEOTHHiq z@OxT=M2R#9RmHD0gSKfQCN>3BjCuWvvW4}2rOw|T@Q9ic@GmK=)<=+{UQ~w^Ra1=m z6?N_JdkW>N8dP0`XOsuF1g=9VQ<6TvryLezvhFZ(5i`ICH(P=FXeM$j&MWnWNMlPcsY zh=C?0&zM&7%$=JQT8T17>uDB%S0*b2=sh+CAU!?zw*Zp?J3xij^9*1bfY%tk(pV;t z1ALo8@7L6lom9}fF)PXEg609ndymw#tfvB#0D1?}`;Okt1wdD6qHbG~Zcox3N!krM z8IAT3#h`u(It31Uh$8SyMA5lkq6m7FC z@S&mH@XoMp?OQd#&Bza*p17%zDJ?T^+N|eJ6INg4=z#=H$h~inQKf z&DZP7tITy4p+ebLWgq1GgEed<;{+SYIWf(fHNC6ki*uh}2-ZZ8t(k5WyoI^KRAJWH zY2mJ7t~>2qJo!zXW`?b` z9jMFTQ;4!waJ)+38JqFw2ik5GuV^;mIoN;KV-WjYpr2%Z=qH|Frat`bS*z zKN(q>Cp@<y-ysHX@ygto-L07LUFeVYgZL z&J;2QOSmFt^Hs#GK5n7Sd88_Omd*Y{{n6T^bq~8bTyMv6dOKYX;RWGE;Uyt`S4MZ{ z)Axie2Uf+b_Z4(lcFiwN8+`Q&%Ue8{zP~`oy!GvvZGhVyj~4tnopshLJ*-~nM4mb#nc?c{%(G9_LdQ|&+9TYYPs2iW*84xHTOceE$d)Xn zNIdF~OvEe%@p(UTp+?I4x9YxD>AqG){t|wu*8ale7pLr<`Yf9>xjU=p$yj4!)?WMG zc(f^!-=|@2`os3;vM>EOZQ=|kd~A$l@6GAv`<((eCm#Lt=p<}($j zKQ&q@*el9}0KcIBiOxVi_x$w6^ z?^mZQH|+F2SpVSC!Px6hKkRY}kGRg%{76{WzcyJv^8i-YF!kh#QEtxia2Y(+3+%SD zvD>?H_Yc(M?d=lsyYu^(qUTv*ic?p2KaDC2^FEaJIZ2RuqpO8$FI0v7Wsr*_&4`IECE(^+L|Ucyz-k z_2q1=d*QyCjKYG`+?)w|n}eg2i}j<~y0m9BYai#W$H<+1CHfq4b7&TK4QK7Mc+Yva zLx1~NFSieKb7%&8hNt$G!^?}q)`L!A)`4l>pH*>#q%Z0{d2wWC2EN%on2mQm-XGV1 zPw_qU8So|04D14SCb18+5eNW5pc8lmp!(;4W56lkIB*8|6>tLRs2LF0z@eeMksaZW zzlg`payUi)05a_d==+tvb1VIl8c-ztyLRJO@vXhRyBbj|&BcLzX`nuRP=zqs|9gfGhl5bld_oLokwhippcnj%s`g%xj=9|Qj;=xXc zwq0!gx^>w9+{@;Bd}1gR6g4l{Ae$ZHTiZe!-z4+R0qjG!$P(Yw$%}qolq7|=d!mmQ z)t0ta*{|^}N;`bs%95RV+EmpY2x`T%r4s&o-{rx= zjoTAw^Xoc06R?Xz94)}pwptN=%EK~`4IxBhlgU>$)bY(~pp~B;xx6J%|6+qVR)^w<_#bp*CQnB zN|)<3rZnhb61^j92ldC1w00z{?F`G=`n7%Kne$4c}eA`$KDX$){-j2s_3t7a_#>|YlkQ7Px7xK1gycF2t zN6ux@@9Q-7#I#1o%XkLHGccZk@eGV-U_1lk85qyNcm~EZFrI<&4E+CP07o!!>UAo` zF$&vHrApT~@gn-nisG1&hVSk00p_wvOxE7p|oiyU|B zd82Mn{-9(n0iVQ|Im*f)SKf&a{Z^B4bHS!pu3FBw-_0`YnUyv!E6r}n;cl`{;wE!b zEd|{4v|B7QGj8RWBjm+dlO{GX2W}B%HOL%Nr$5x$nxLA>99}WxWjNUIQB8sg`ZVUi zjVeBI5FtCn!~vQ^k#OL|90={eb*t22u)2RWpkMVlf~rg>NN$lX6)Eg>9!DyQp+_*W zRq-%KO8_o$J;)rMKr5YSC4;v3+fe6|=C|W)1&39MV4{Yjv!*sp4j~EOvd}uE^+D_2 z{J#jJxv_R=y^}53(fTHg0QB6D4b2O!cUq66BRg96`r0QUS;&^kZ2;XzQWZT9gfmGQ zME6HNO8}a8vZLpZK+m7yl5A+5F8~ZXdTt5y9Fra0VH$RKfu}y8dTi|$8=Xqpfw21k z!;b!QLa3k)Cky$bQVEb9#o35ELIT}c8pW_%0|o4YkAa&1-$8w+V)U;Oyy5S4_#)7F zjbixQ3Of)|4k6DmC}QR-JNKz8)pH{QVRDb(jB z?daX$y@A~U*ieqipZcN(%0_iZQ;Gid1N!H(9DQOFk+qI%zS PiLoZ0u@93x5yS4^3%S}( literal 0 HcmV?d00001 diff --git a/release/aroma/qo_db/bin/dexopt b/release/aroma/qo_db/bin/dexopt new file mode 100644 index 0000000000000000000000000000000000000000..c7f76c8a8f2a743a03d74938af87f732d3fd3dec GIT binary patch literal 9384 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

          `$F!2SgIEtJNL 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 literal 0 HcmV?d00001 diff --git a/release/aroma/qo_db/lib/libcutils.so b/release/aroma/qo_db/lib/libcutils.so new file mode 100644 index 0000000000000000000000000000000000000000..6b65366a7dd8e88fefef659338ffb44ad7207549 GIT binary patch literal 42220 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�Z}eZAk^ck!c~du%|Q5kxC1g! z#0wD4L+BL~KGD~n%%w9>9j|qztZfzl=uXNtjmWSpax+8^{<{8ns9ljmQxxYE%w<*% z(kcF#0hpgYD&P`)ziQJd;^7B4?O%W=28wt{*SpVw#F%)zq02X?9XGt*eqhv4I_E#% z{|N8XH{!6XTmT=G#;NS~lK2kx?(%{6U&i}B%pUy!{c%a$)L?z91MbWPI_ICYt>euXKEui|tL z?oQ>pEtbQLXlJzF&Uf*~A<)qDyS&x5CokJE$$nX?LhAFtd?KDVjz#B2dr0ytLO5E! z1JC~fgue^w;Bzn9XpcUNdOaKK<2ph280i0(r9!0A3+1ZNb0xNTSeNG^O zy*}h7*%3G`?l|qw%D$ zH*YlOZ`bFKHVAnRP}yHg);07T=-9j$ErJB4Xb8?!M7uD57pSJ+THejWI7IIAv`?mt z&o4|-Z_|`MC?v+5mGUZ)ESQgDrTB-oZpegdqq zVVfS#zi3leFxxLl2JHHkEjjtB@?lx;N!n_aK>a4~$cdF8rlW)Q3 zpH|FFqdUjm^`)urG>-1x(z`0v-%0rjK&>B+YwX~NG6}~m`U^tdezGF}XYqUVN*cyt z-f)_dA3HGnTcWQ;uQ3U4uctj9?%XTqlQrBoisp@_J-?`B$TfA3qI*TYu%5X6RmoCh z)|K@PbhZ`6%w%|?h}i}1VAPuT^3?Xj`R}eHQICbI1YunktO=MYCHbL-0~WE7ehJ0q zb2ypC0#jUqUSb?4tf>)4wM?+@$@`56`CsMNh>@In9 z*AMg6>sX9$bgNq`ZRf>%`+vRKoKH+=q{5=P(yRok10EtY->)hasU9_xGfY5?*K z;EsZdICsHvRn@8WQ|(4w+qNo3IzrI@iC%@Es<fa7Gfo@S zr4OWf|9s|SGM;#}n_e65kNwFol*PCUyRF7CH?FKtjM}?C*0B#WcgdVr$D4qi5L*jIG z85yhD?!PTjPy<=PukwPFVBBwC!fAG?fdQefw~OC*K+2eKLDK8hM*m%8+Y)ZK%`Tqm zxB&bp%Ej~VObl8Ke2T@AGT`s2uvrS|0z%i+2#s5-;H1QP%#0W*VO;V}GKZ6<&Q6?e z%}is&Eeji)j>rB*r2JRC5CY}B3t~`kM=Bu>l`ZAJncF?{#SDLEZmpxa~M=(cDiJ_-vsCB2lzbb1rxWS($9kIL`7q%F9oaM{G6&Uq7q zAfepOhj3b?7>#ENXV|QH6IHG>c_&m-3@t@fYI{=%-hN4+7O`w1@*@o1)Vi2yUrBl^ zN;3Mpx2Shoz6U40#JJNE<@|@nbPk-TgfJ7+qndGqCxsc{lBAf4Gf-e=F+GY&LBP6Y zW*P8Yi|1;1$?AtU(YseL)0ER$A#CP;OGlH4GE2bC3JXB3r3ItL(-s&NZY^zrKA1o)_?cxzozYn;8Q&K}|#+R(9 zlYdXjWLlqsB^)FIg$)uci^X?35|2W{cK83Jj&>rAxsC$Ao1b&23Qt&nIP9uDf z3;y>{&_WLW;tTxeAm!Q*)VKsb(Hi)1@V~1Nr_a&P0&^Gm71L@hU!!MV(!)2dt0-M< zEXv44tu~-uue7g$l<%VWR9B+oDg5%3e9Ezlo7$IQ7xcIPAngFBX@~Kwv?Gfhe+SUU zN};WZys|LIxgmnyrcK;v4rnMs>v!m5x=C-?`Z=0DhUqdT=ht}$8&{!$CBqR$AXFo)AI_3uqFhVbtQ|2k9H#pUh) zd8QcaISVaQ%H0dGh2aaqdxOIa?|Hrx$5_v2|MBbWb~8{R!+?}O)^kr!lEr5)qT)8^ zmT&X(lqglOT&kEy;M7(*m3vW zrmW0~0#TEnrP#oa6U5t?ksz>8{xVry}OD&pLb`H9>TNu}SD zGuHFJT?%MlpQ$m#s~RYmxi=-E3wVqTX-E~B^uaH zO3Z9rNAL|Acll&R71gEOpYt`P+HEb+?fhrToIEvm!2bI@wefdgYHM&VH=%b=xIM5= zr*t}25I6KCA@y&CRTOyay_#|+Qd`k4&H}bEzq`nzXl8M zm$oyVI{&93d5jQz{s%)`O4z9@XP=SGMJ$ay{S)k48lVBAsfh8gK;SdmV+A#kyfaXT zr``T|f2qv3y@XufF_u9OnWpT3ZH3j2Co+n$#u+RO=5YnTBstE(ib`jH{L$*Gn)35v zN7v@74jWD3Xa6jBp+UE;*siN;5W{-IN@=L?9V&;q-eGd6?Hyi9h>Qbe7bD%9uV~+x?RYPpjtU80 z0B~we(h6a_4A3njJqk}H^xX^H=(};mvmTz8@Vn6{<6B)6KLzG;zj&?Bl=~E~-Id(N zl2cgAjXCp7bgiuEaqtq)M4m$bf$vv&HD}MGdPi7As{^v#-4}90-Na9HhGc8Y_pI6q zX~Kc-J?j>8!YZ}k=bnQTW>E>at5_jl1jTW!d1wWR{iky>_FMu_lW*w1=3<4wD%G|I z@%f(OltA>%=AON|KS-oHpwwU_J^r1IlAcg%vvSf(gWq=I{)&Ax3m)8g^>(+I?^W;e zt4OoL^LvR~e9Y^&TUAkR4JdE0zL0vR@if*ulV@39F_(y)URfHpA6l9ffd@{{oh=OA zMfXW<`Pbl{l^6qh6rFx$*TnhVRQ3~x8Z|(-!&jd>d%~~-l@kqfrdcE~fa_!Q6wPToA)_H9`{q?Wf&9tROuulJSx0u%t&I0!BazZ&; zJEh6S9Q$&+cDK@4nEqr2bj6FFOkrewHapJ$KZ18n*9?CroeLL==-A%~E))3N;)7jP z;P9EiiQLfhk6a_SW@SHY*fj9SW8$nU!KVe1#5zb5`o-0FVphlz)E_y5BUM39kNmQ4MtdMcD5tE)+eF*~PnC zeW}7EDw8yFS9AKsNnIxB?9kGi#e0COOvCtI@Mn_9xDBopyiYBW=^APWK3v*B{o@8w z4(mN99bxybk6ND`@ws$l$T{iQ5T^mOTY|sgoK(+#E**>d6tPnn<8P49rFx_Y3mIbg zTsk!+pzwweW_aFR44D1>U`x9F8@4+ck#9qDlOS1trH$aETN14^b#~tnW6Frr- z2J!y>tIgzf^!Mv%JG8i(#pk-egJ%Mo;=`Wro5`57nA_npE%Ue^bR`I6;#%lF0B3Rs z!cv6$lcDRNVTq?7`{}kl5wU7SSqE z1XVT8t^M!|PWPJoT!}dEm3421w}u9Il$XFo1ABQ+ege3O zPe)SQgvIcj7{@6N+!Xo#i_nz(MSMvb9Cv}vB=G%O#U5`W#>(T5Hi*CW({nfUg zeZ1KdYL;~Nu_PRQK;=9`xvyZ8V)1LNa^TnZy%Z5e2|VaQ zEN2zIeyKN>Yl0+w6XI1}?p$U3G>kgdMLn_a=zs3YkHB?#A)kpeI~70{aObg(D8Zat z%m$xx&Qlqkpf(O*rkS{E`2YJJXcg3dN42==hDuPH%v@_ur+Ba{%Ta|f7~;Jkr5Mdz zf+>{02x9 z+|-J5rfc>U+u94#7@z_W&x~T4=VW^_Y>iaLYLUBf9$2cxh%r|Rc|s|P%0j#JT}Y*0 zXn!C2Iqzc>&>B~Z2}m2;WxC?dRmZDcdoz@fIMU~1ZUhO;lq8Q|@mumZS=Y~A0UG3{ zH|~9Nfs{hgc3X4RvB#X55nA*t&0hyk1@Ltb?T?@^FP{VxwBFU`Jl1!yDG4i3+3OU+0{Z)>^{2jK{ z84B>7rMy+?tjy~@j}oeZ5||_RiKcIhEG?pEeWE?Oz8utnv-v>&Tb5IePYV>M+n@SU zhKC=ly9u#eOAhU)LTRZ$d#a?5V)s$5?S>TMnbyO=<~ob65}4nGz4%t7(!S3|^|aHW zS(u(qIpnl;4|JRtvm`oaq1zy@=xsTZ07KjY~2F&d00%fXB2^{h6AjdETSn_0xHXLOkL_!IY9(6@ZlXsOCFt>A6z})L)i2-ZM5hY6+5xv$9q92#nwN9I*3WpyYzM?XdE`2rrLRXL5qTP6%>7V`nCWHW-B~ z>ys!SV|Y5yr@dl_q(4Zpvk5dr`B~b!o)R6=9sIFe5ggAw723 z4=J(A21{({53#ZFSVOs3vr8u|#yD0q%!`c#muhLO607MQE>>Vnqrnv!Caj3iam=J0 z*qXOeL}P@S``| zaWD3!d*!{UTKx6;M&a6sCE=NOzyg9fKt6Ocf&Nnv*Rq_AqdF!<+?P_AGeRh|0WC+b zrye+W)6yZ`-mTzX;{J3xI_CvzUB2gc{`K6&Oj*Gp)r$v!)}AHI0#3eXy?s3+6s(`L zzH3F1e0I50IKqF*VKvcLi_f$d90gx0ARD{MH{F<{SmPgWHy)+;-*s16M!Ud^>@<=X zPkVQv?EuG&cB}{yj@Ys!<-{W^=r0?rF&?JpDV_lmhyickhx0t;1Jm!=<_Zy*C~aq= z_JEzz$33=Psr9aIJ`^hk@e2?R=aC5?xTI!Z375KkR@T2Zr=iTL!0*OR3GC!Z!jeyL zj;4EYFjop&kkTZlRAMF30g$w>;H$+E?M6ouw+FFd?M94~u&K3{&PJ*?LigGNSubW7 z+7^o)#49#>^$t36{)8`t!8}Q4C6F85xGhi5^}#%^U#EE*{v%I1*45lrt_*rdF`&_W zTJ8;?Se=eTc{=;M`9z2YO;A|9pzU+5zwmoLO|cj{j@nKwd=8xSnjOrvhf;q7F3=?x z5j3Ekz-Pc1rgNx-db)r&I!YI3pvE6il>DQEcTeHY>3AJL4QTms$h$~Pg4~zBH(B{j4c?^p$ft}_iuVlM1Em|@9K66v@#ReI!AkM_ zDbQL)@G0rZ2euZM1^Ec5OK$@Df!6F`{+slh0a3;G)##V`|M#X`$ALQifjao=Og&7% zhs>>eU+do;xF2l8o40=VrQeDB#M(?)c>A*xT>iGu!r5_Au2|tz{(aJvq#f{INwKWN zMx`r6-ZQ6lg$keL+aWbjxKHA2yAWO~h~T$137Y68eFnc+6>yFi8^rmrLRAa?d{}N6 zB#<4>E%}YjTIdIK|G^TLKZ8?Q!CdqJ>_o{I%HJvQ70S(E`76#oC}5d0OwHN$qGDa_$B z;6+}WG==+=S8Pk>i0$QeWdJLe{6t%%kP*wet{4LN4EPCI8mn=INo+mPFj(xT&;d~h zSF?w3KMYUiUv5z((Hs^c2US^82F*c9SsWLlKppH}d99Xbi2f$gMfae@9!fjrN-YdhFGrzHOwC0h*Y#S!^0%DUCf%>#w%` zHhc=~KwoZ2N~#A3V>l=^7E~J5E=uR>6y#fc->(riAp8KK z8{y@F>m}SjhWPj03bGdA34{d*KS3CQ5aR*9Xr9k~9{B&;xE^?kG+D`nG*=?uCcfIw z6voOPRkWbJtlbLGonA2#cs0a49lHeyPH>rXPqO3BRoc#BZ)Rb=p{u*LHVRsh=K3qC zCg=IQE_+*^0utiT1r&>Hmu+K;avP+J^{}oh3(D}((1j7sUb!=AO+Zkx_g&eE58+o+QoC!yg*f zv<5po#uWXHPr|A0j{d)u6vK;en;6-j4oqH^C0h)Sa&G>V#X*3S3}Ofz3<6^{D14C`BNRep`e4nspg+V z{uldx62J5Y3xub1l?HTGc9+r7)NG^Pdy-gai=G4ytSH+gNt?x5X8)GlAkNH31H+W5 zXc32DC!l(EI#~0C14Dpf(YA`8Nw8IR9ss`19OMF=WTG_dW!-xn8>;prv?mMZYH#~b z5v&U4`u?lsIH~*WcZ?xiLBFu%o<~?xkN5#xbiD||_;{guT;@1vB+bMKQ52ELd6c7? zpmcwsnu`ATl=Fj}_q@yzp6(>M`kNp=!EZ_Beu8fD1OYOmN*fQl7PMk+$#;^nQc=e2 zr?#QV=%cCl21gt=j;*>XzSy_N##Vg`3-8c$7P@TT!ooWlzkDmU^=Zq066bhn{A{06 zxD&pYV!#JiaeftM`6L3ZcxN@R>;36k2HYaI1=u`yLcz-VgUcesExr1%Hqi>(wwk>_efwmR(O_JO8wA{9H z{j_bX`+|iz{1VmhbFsN0H;YyUJ3}!t=!hAL5p$1J>iAc)-!3CZCAhmRq2PWepqCf) zeb7uxZgtMYXfh|YH~U6YtLx9^YG@_|$Q&9{_w-p`pEyEU=nXHpS!Df2T-B$VN4*_h z$^KOOV89nRbkpi`&-m#1L0#!H`1Knx_xQYl=RnqsdNyB$y=jp&#rOi%HlFe})sGm^ zHXhWC{vCVnZg@#6ZhMWPdAy{0U#H;DLYqKWL{B_tmK?N%x~zPaCD`>oa7P|_)!<=* zukehkBsB~gl+e1OwNECV=||`t@l1wBC2Zy}^XNVGI`fSf*O%x^R~$A_zae@0+6oKi zsmlc$c-BenExh6(oWAtOgD$$(YUMAi2Mt1>m)Di$Z5@$mS$s<~PY-)cU9LYzchkYQ zx6~EOc-6tKZE~oBRs0VleA>VI;|*)WWvdRa_-WntTNd;1c7L3f>CfTaT0hv?vMwgC zel0Tzd=+4p|38F%33wDm`hIoyT$v2Xa8E*jnF)jmmkDP$bSIOf$$=6;G^p!#z@sM| z2G0ntOcGE$R>L6%L`86wAV&hCgu?_y#a(r063_r19j=57$Aqgp_y4V)0de>DJb!pP zHQilZU0uglUwy~>ebN=gi!jjmsA9sNXui9`WN89Rwc1whx_)%8fF}}>HQ1{@MlkaU z*guijR0}jp3iI!N#*`-0TzfPbDxWyi%rQquN-GJN4^qrhqX@gxRXr4D5*HZAkW~ZY zCx9+6f#f70N+l&H-Ta3W`cH+KG7n5m6)`9GfxhX$3DbyO$Ge!xq|z=??iQ#-+fo(H z2uj$_VRYa)7$QY(w9=!iI@6COshJVF9IB-cxardl{ z@~SOBxJKI+=P^J72?u2~AB+JV?2?G zV(9wlQ5dOR{th;lh7#-=?GEtq?edqcdRW*FKnVk=92}An$}R1bjhFgJ&&;=B57E1_ zUEZZWdmiYCIY4vMsc3HWO*bx53FRGpqx^5xhrUt%wu7RModZrl93oJE1}TRJE96eO z8v6cEy=9QeQoIXNRepsfyDxEMKGG7TsYu^JdI~-hpzYIME+3f%Y{gZPd{N$#)ZyvS z_jvlj`{5BLhNsdP#@ng-dWg)|dHNCbtg{2Uy^Yjg?Dg{2RBB702X1AG7+X;XzLfEE zVMJQTuLEbqfUDJR32SCF>?-XV>>N7T^&DTGMit>osT{vT8d2 z0KeO3}9WRWwz!=Jkq-EntV4d_oLU!fe5;MdV2O zrfn_B_{LAwJ#2!w9A2ZrJ#0IT&pK^&c`v>{&#lx$O7(F&_s;K%b#*i}#)+&ny5wg&g3rVhW?0WO5a{hNPT(;}!a@Bar!~dIXEcT9{h(Mk zayrnT)zg~##p+6)Obc5Lf51-=JLQ$kCW9%fDJ=Y)?@+Uz75LeF4JntGHBzh^`lgGX zOzY>gWD|)+nF9^FIcZK%5e0}(^#1Q)Wo zr5fd#Z9^NF5!1chwv0mzkhj{29kvV!#h~XFW;VWHGU%IOe*)-RLgs_2EO#et$S0tz zZe-zZOgdS3mrh@)fQ~J9TkWkX|oc^SXu<1 z4=RE&*dbL9{}7}*b1t&vA?WBYTwqCeq;x*LQ(lC< z@YGe|E6>SYt>NoiQhSQVlISf?Wze1ak}f#{{GcB3l8lg6JIp_bvy?&EhLU$Hvq5`k z?~F%e3!!ou+GbfMSwm}i0yec+0h)}ZX^&i&4DY{R@gnw0vlTXh*lU&fOq;w0`-1e! z#du~hR#^k|k2?{A?LWx-93p5wm-$>4EhnsGNou#15vw9se~5LXq80CV4iY_TZN6&L zuj_-BFNRj43%s`u>(4yM2IggsLI3Q=ejgO1iLvX}=1G0tdpJY4cDBM;iLD0a2&Pqy zGHIO+Y+fo0hHnm9{x_wVkAWqX4LY*6&SiW7^f&JRsU0IJhll@~ZtEh}@01^F z>Mup{x>7AxlbCks{7be}nBD=7T8R^-l5%z>x29G((xcZWSLH{PI#u&C99 z@ntl+s}^6`PfcW@GPhmCT5 zOZU?7^=4sgrEy)>{C+A<;m@+7IQV|*I@jx8u;IcO+t(P>=l8;I_j%ZQ!Q<=0M-rNrQy6b<;bk2(=!9k_W+V${^v;8&*y z?nr-CBRIQVTaq3^ltsKebtLXYtTGE`skTg~&eGr8S5#0B>fNqzuL+~Yl*s^hg2u{Y z*ABy)v*A4A)0Sc`rH8}Qj#M#(m>1g-Yv?>nQcmhMIgiF-#d#l7m`voh(@cN-zn=ZKk_Z`5WvExn>?y!h{eDhu&?j@=Bx@0WG zswN6|Rb-Mb`9a*ZR@^LcOcnNksxNz&d=KtW$piKK?6hT;xb6f#dn{_tB+{qOqa3cp8H&sr zoR_JHyf73zB3Gt?CtR2O1mgcDRYqZCM}>ATqZ&;Tu!a+&hZ()SGor!q-SlVKiRgdC z8jhzmusc746;bvAMH_Zo4Y0ki@?nVhO~>zp_?Esn9>TG9ATVpsu_Oh*4Wa(9jKVoZS?Q7s)$egsjzn!os{xx6%%I}=HK-o@rtZPHp~IMlKREhj>z5iLpu8t>P@AbBE)OTZ zn@2`W^Nti@t4X;!L%#U(0_HDzzd^gmoxm?JU>|^p-DAz?Wu*;~V%CGb1s-!Ap#rk{eyPwkb6P$F+fU= z83puJW+kL23am_kY=yHjM2EpFrMzDP5a&5H%I|2{nw*BE6%#m)Rgo?2ly`RNs0~il z>!|y^uo2&I3UdIzJxJe0Iu+^LNY!{t)0UTS$ODaAO@{NZo+lnMgjzF0LtD~k0dv=Z zC@24jVS+No9Oge9eqLVJ%B}M$mW|Uf!rr@-y&tw7h$MerE^c*;I}qK`uzx=+tLT+w zt!23KI^+z@iO1oI+}-=wfG=D>)rjIJB8@vkDI&G;n~9OTLtcOJXSsW)R{Fxl)m+4A zZ9H)XvI(uq*Ob(=q#Nq{zhkvi4g()a$Es5utG$5I7Enj&%C6l1bClNqX_TG_jnbN1 zqqI}5`Qqj%tp_G4q=M=wJ@j9rbl(2kN9nFxqqGxq?!QOr=0ApPp3hEV-`SV9J@GIAzhkClWS!E2Bo zcYnH&DV>!+YY+1;XJ?AVux0=jmnyOO&O&@{$R8jn!5+_9X~R>t%zM>+ z*$#Q%g^|F*M!b3;ah#CjV8=2WE7}U6=aaz)UB`R_rA~MEsrfNGaqGoRfmVZ9t(mLKm!z6j8cH_gyp##-mQjmS59JtF8pPs^=Tkf7 zA|(twNg;M}g`s|H_5Um{YEJ+XT!d1H89@TIka;tK|G+v>hxH<888|2)w>+EiY-XC; zYmnSpV=<3^@mult8~;Awa>bMn3PiRNJ4MiApxw8iZwf%ch~uwb`rZ09WY7=F@bb<4 zGzqBr-0@ve@tJjq614074ARQAo0=FdrE*rfsR@P?!^Zkzt`#lq;hO*}{$a2sp+0uH zm2L7p?cLU~*oQHJzOC>KwYii*q@QH;zs7WHc1DCZv*89YL)-!Wo#DHe>Q-u3cPlaT zZStsg-8=M23%;ziMGv1m`ecKAZyPfP8d7-k(KqPdNx@ZSOn50I-*<$=JiN^J0&Ffa zeTH`+qj)Q99kj=6#3#n}SL8)4KSQpu4|_(dH=92uzYj~eao*A5iG{UFIr%KQ*&KV% zq7>pU+2t+RCgm5XDH?3y^H7%gs>kNo1^piXpvI#`7fn9Qgd<8asG`-Xci9Mb?CO_5L z+;CHtu$r(8OlH~77o7ZzJrJA&%P=0F!jXxwc>rlIr0*e}D{%xkSwx$OSbMN-BjODB z&L8dZfOtawa6hTqR~dYsj=8sCv(yKYh{N|)&S{WSTK=B8cWwfFX7}o7-H$3?%)9&a zUU($zmq$@w1dJ$*J5Q2FbsST2g7~(1 z6tx3Z{d3Z7C*()lMuA351=dGu$q7hA8GDk=4lhPYcEfAm3t#>8acpxh(~?x-F-V(p zVV4@N5vmo9X9LEA3S(YW zNh6g(;%|NxS~lRcg^@UmggeqpX)>&}dWr&ne13;~wJl!!Za#~7(JFMv7uwpyD4=zf zw-Cn}^{J!<)Sjy-ZKoRDj07SI$w(5g7gFA}t5wGzsaP(4UC|}Sca)3u@>-y{ZUmB* z*+9QcFXbrl=I+?r)KRy)cOfR8GRFeBWxf1F`+P`KkG0d^^V^F_!CWOzwZ>!G@~CBAk!T*>$S=ul&D8<_ zispK-JssL?X591h-T=iRai8)drAfJ{LBE!Y97PB1D(7o;uS&D}Vk9$q3cXR?Dx8qJ zx3q{$5I53LO&phew8kf7eM|6)xgyDpnBo#`)fV@wz$7NNbVX-2!O~DOu3+9W@E1$m zXg%X)>>x;7z1*{1hjxq$wd1UIX58X=Yf&F1kG9-Dl)Liw@QgGm?_K`+1;o0~y(0Ur z1+=Xz;3NIO&asgA)yvl~BFWWO&p=>w>VVNn_trZQEuPdHo6TW(8>nou`pxxi8SufT z2ms}2*H0GACs-%4`9qK+)3@EHbk4^+=3|YWjP=&!K5684nxYx*RE7!knF;eJEx0GEAmx}JhihzqI0dxb>-w2^Z!2o#W_q|!GayKqmhhs2Fg5p=YzLzESR4NI&M@J z0ZG%)S&#?I(<@AmY{ikl_#<>!jZO4hl9dQ2W==$ud-R+qg~Z(VK;2%)Q3nbq0H6B7 z&Tn8VlM=Ij*OkI23n})&&nFA=wj&Ds-n^GYY5qr#ent}c-|0RiR(ez;O_+CT!I2zq zwgyy9@ug)jv1yq`>+`Ab*~0D|$T-f!%7^B|$`&g{WCHF|c5m#f8e~r^8)xOu&1sV- zL7tm*TeRfuKnRS)4!#Y(96Csj$Dp6apr5Gc%XYc?GJ`o2$M2oDUEXr}zDg_KDu3E_ zMlS72nLi9VyJPYvos2}a^cXX?b8-=+8#H~fYY_Sb{omR)kHBxE7IAG8@oZW<)f_Cn zMt0sfhu#mTls6l8&q>C^pnWRpfWg=n-uydontoTZOIlK;$DYEzN8kKV$XfGttZVJR z2ls2W(1S$*tLrbnair*Hmh3!<*p)awIl+-Taa=pbk^-bBkUov{-#5CtN`NZ{Tf0a@ z7WD4!u!70)THo}Au4u10C#4#QZZ!)%(bf2!4{SHO4y*g8WG&xQVZtAD^!CNjU-KRu z+3KANRJRzO89k(6(jBe9G-5o66Po{cj01G7RsL9s1loLeHHW=m($H3*&CxtU{yppfSxK;0!Kx0+ zy?1k7EssQdA5+qqGU)75P$DFAgVUvr*pZrUBzCO^vhueo{Y=CClif{NH zQk6-*@G)^2G|KmOc`DAwdIyEhQgN2xwS~^^!r3tIz|h$^oW*%#LT3p$vw5RKXAYdj zc>9LV>^SQSxnA%M(Ks_z>8(`iNe>o>7KZ^x7!D4H28Rv@shWj)Ps5RkV+sx@j)^!% z;TVP^4hOX_@bH7OUcvs53|f*3Iq_Qf0gQRj!Mw|P9k3(N`1F!HhFK{VTx(!TT`|lm zoy4r4jw`bYCXHx8{1s-sxgg$g#@7@3y$5q_>MU!OS3^QaM?r6i-8n_kEFf{zia7&4 zw+^yt;%N5LRpz+NcQWHXf)s~Y580lT>bN^$Bhb3@557^uPriF+`DCEqUCv1oEBO&6 z-L}LA2Dc?;zltM3u zZi+b0L(0(!EN?AF(bI@C81(y#_0h4F&{+iDu@iMG#@$CdVu1^;-@v~0kH!_msE#vW zR+JxA4q&9c)OJR`w=>~Q zUjF!QYA3c`UUTsdRSJQ5hVQ?L1s3OHNzqT#AEGBDikitW60x<*Tfl2LDFADC zXX@~aCJ7ef*cTYRcI-8c*l9kW8V2;|?a==NpBM;~nn>dK&Bs{pI(TG{hV1gPWHicN zi*zVb60be+U5W)3vJ9aJrLaLy=mk$(2ESo<2%GKntQCAZ=03%vOlJm!G#k*Mc2FNd zI;%M^iM7Ly!U*4t73O4%MXFJ@WnZKb!xNd&mQls<^~D_^i1r$6pr{X4Z5wB=5oG+h(c}6a$ACrQwDB7gy5v0_l&X(Y z#}#A)w(NYwLgyT_1#4iy?m)6C`d!rzq zM_DTn>C-`_3@GVpd$6QgDj(NtJjJ(I2`^X;)))GQjCL|OXmd`gyxW6gm&9X5;WQ^) z3%^U@+Gu=|>V-%twkPHtZOgHkcVk0s>16ufYRk3lG>RgN5!w#@6N!ymm^37cH%r1o zeH+J8D_7Q=EmkA4y4g(%COcT)3`C0>e~j)jE}T53q^fOKqwb~0pzTnP@V$JjGCX4~NH|;dS`8oM$ z8#CU%@NHM!Nxj4*ehuCG2+(^-(R}sb*r;v)vTe7|-I;gqE}x0HdkJ`syZOYDGqA0> zIok~0yCK=RJLIVjis~M6~;YBUf-S{Y< z710%bZ1Et+aOA-JhjbJAk(Hg`6pX0xBWJTP}p)tp4R4^FI4oyn$s^Nui7rp@oT{8-@~Uuhd*4c?T?C69W^7{f|Oxs8{G$- zljGWAz^l_0$<~&*9=bc#o|00A75>pGW!U&hkS+v%V9Cd|LH;8ezkB0%a7<0Z{G1jV zQ`xtTsrhZE77`nfK}LncN-H>rW&ro58d1z>N;LD2F^Nf|D&TcA2RSk3Mgd(@ozKC1 z8su}B=y;p$3+B9xv34&L1?gG~R(3j5AM`c=;hlut!zYc83Ox<9oyjNkk;f?N4sgh_ zCVRuw9Y%0w@vxnkjW6EPO1bu=@tYQY+?+&Krb#CsrzIKts->{rCE`ha#IXr(BRmsq zzF-NN>f9XMmaewm%dK=*ku=`Auqf@!Ny?4WHhrO$3^v0DvZMiWON`b}LEDMr3*TjU zQ(=G9NykN=o7%zE){z4JWSyzrG|tfyZ;tJuhyT zNBSM1CuZOYcx55i#gi2MbGw|-q|U2iX-lwf=B)1M-+XA9C=JfOWfj*hFK*p|T{mo4 z!R5BdHIVN*shpFXU$Bd8mj^Y0_m;nahkE|O>`+VmAyobakX&jMtLm(G4;GHTbP_aCNcx9sUq2 z;YlDB8ivs*fLuUp=+>j}fVdIkNN;hl5HBIRrW*CDkJLl-^|cGRLU(D^MG~!CIuvfC zcbV;Ssv3_=D^YI@8QvH)t|f~YA2?sU7v2oZa9tD1>o{+P+%*5-Px27p1#~6kAJp8h zA@pdz54e|*#ojZ&H@^^j^!{yT)q^wtU?Naj4D8K_B7d(+sDK<4a)J)|GIstKyu;NJ zslHRk&zc{}-&u*V0IjenpkdFr4c)Os+VjF##!5W$Dm&r1 zoOJMQriUs^9EbONP>-ZN#w=rqI+gUORbHQwnv*u0u5&RhR5KTh3l04nbRMhz865A3 zV#fE#V#FTlOH!#lg_9|S9aE6VL< zjz>Ibif{hFt#Z+;S%}vgs?Q&D`zP4B*wpXtl3%T4Z{;`f2DdrGd^c_3d(TILDxA;B zsq~>n)JuZFNT>uJeNd0PX`c_ZqBipM`u1DbpFZ&ZFD&`jhkwu+SY5z&avkEejO8N{ zNyg^hF2|jBRsw@ZqdiJF*$lL{9rnx2xTG;(AYO$Q{o(*RH&)ve;B{09;$Z$O&GloK zf>f-SkUJ=5|Fph5MQ-0*PA!O;E%1^kK}>h(jIo|$WwEWc2Z|_9I`}N&`9WTTh-NxS zwy7q>gF0+z^rZeZ?S?NI&)NgCI>_K(AsvOE6J(E0=w4tuS3Vp4Z8@KVzsrz&FKjt4 z*D~)z^13j0Aswl2VpT|}+_-QQU$36OOwajk@;8@hnVB87b(H&c@In5!S7U65|BXZY zQ2w_MP}?bDb)Tv0%HPR(A=M`K=Pl3x_buspqDQ)$?~z%c^4mp?BI;l`&+%3vp&|ml z@j+enHhI(KzUvS-9sKb+msw=I+vHQ1qhR>}-{8%`cU%I^U;8~rR@AWMRiq_2cHx?S z4_gN7cWbg@xYLbzAE2O(OeuLslXnAx~k$8q$pEC~Q zuU+!*U0QJ7KY*fXtQ=_LHu<5;5qR%Nl;0P}K+JpCQ6P8JuVlChPkhrAp2@;iDfmp7 z`i$$c5puiAF8!^twCeS7mj|LOC(4P(u^2~p9OgaSHj3v23tD7AQ%a16kMyB! z8i`ndal`sO3?xyLH@NzoU=qR|H+)9y77?Ky7I1-vZLkX<;x<{itjo};a~pDfEB#8k z&&2zt11sw=OL)Ai=bmlyZ4B|OZl7#Zf zE1);A-nlLgX>RKGewHoFbpf&cOCd{m#lmGd?3u!n)F}6%T-x_94%DK(d+~bcdj8Sa zgXpbvy`eo6xX5J12(*8;@7w;{`G0X_9O?jmG^H>9h9wiaPZM7Ybj{PA5`DNx0tbq| zkB)bDSzdQl2ab9~_c9j=eB+tcRBNKP+_80=;Q#c!!O-k5oEBY>h0iE@6*;FAdBu$` zXCS30;}iqmH@4Ljhy}uJyzrTnf?O#@uOU}T(K_)1Y`dk*5SVs4Pb%>SK$Jf}@8O3P(9#XJB|y6m%fHtneKtWT-PR z1kagqW>(Lvcq3CAE$AiqqiS&UDnNU{X1R;*vF3SCySe76WR_wzzwR>o(iE#F$WJ@m zo-|uc8rEm%F`MU!u}ut{C(M+Fx>u$dYAHI!W|yf7*ovO-5UbdL((l#KsFT^D@+WuE za!&dtN;dZqeBbjGh3I9VA({^<7B&BHHNPX2e^A$4ckJ$=ZutKoSFePxkShkInowtx znr8!0K@2!EsAq50KP7Sjj^&1i`F29v!Z3@3!BSg#dj|c!pX=k@Z@A>zr{FEjvd+L+ z&ldMft_Yvo?H6BnZOa{)dRdqfVDyg*&cL^YdAVB!tW(8#?zOHkUzs>Rcd2D3y-x(8 zVLH77L;%y{sneQ%3HAQ2TfKi(?fpfCwD+GZ^or%^uZ4wTJ!5y!-oI)EuM#h;S9|~Q zLfZR}7p@a4kZW$?!}UL*_kTj`l%w~{)!v^|cu2kba3SseUC1}Pa7KN;8**~B_h%RW zgf@r%Ce-`cg?<0j`&oGIkKRwk8)@%rrO(qpS6c@5d7ZT9r+cs7>iIYRr{@ROO#H8& zpKx2x@4l_)b<(DEV&4=hJ6Xlt`PFBa64hRJ|Ebq?(mLc_7s@-V^C|aJ6@Tt=owPcA zwR)fW!$)_{bE6m7hUptza|GJY!MH9_6 zqf9IZ?<6*5s9=6?9@%9%(Z@>R{$ECOh)EJLdPpl9Ac(eP z@~5yw8fc#fJH}JFxw)~pZp*FKhaY8Z41P}?#ih&>(iFQ>>n~zA<=P~+d8%pP&{@E> zWxdl4hnk}peJcY%WRA}ftr&R+(t3KmkuwO>AAZJ!IIj4Hx~bN5PTF5?ytE?)9yXhE z&j=r?-x2R#FTUoQS^KIhqb6HQNl(4inoo5+eQq^uuJ>=RI9n^M7Z#kmEB!9@?&XGR zjKd>}fm}N~32ihcc7Fz)T`f|qor&=7c8ah+y>#Out_*Akl4++v^R&O4^i_GL=mK%qV*uXN*4eE7FIM>W*;4H5GBgzU9cdEDd=P={}?nBVCV_ zAf1fV{0;2AGBxDN*T4ov`U_GE(gR4948$Bo+K6;5(i)@-k#0qbsM(Nf#)`F-4y<>j zi2Hy@NKU%WWnQ3IG#?1L!nA9o=P4mJSIEVBdC?P?m6#kb5cD5w7Z`9RmMAS5MR{H| zPE{m$L_=klT+`LJIXQAh9U_&*PlKe-PtZtNK9?2I~aGb!-o!V$t2Il#4j# z;%WCfmt04z!8ILh@6sPFTJjMND$_CXcf)IvahLFPy?ne-8{j}G8R(013kRbGKC*o3 z@&q0%r1Y4*7aNIpj2JNHZ1YWcJRZI&o+P@0c`n{m^y?t$Bjm4Gb zyb@oC{2ZRsq7;%AV3}k*;{;WCRCqwxpQ{Mt>I?A12;Y9#m2sxSY1M(q!Xti@`b^}o z9>?)Ki|0%}OA1zmsp=cEg>JKMN5s~Zi+capCR4M+bX62o94g8O)OfxWDgFP^ za|E<_l1N&$*JI(&I#F05%|)(nJ+C3xx1Qi?@|EWc>AFbQl0Cr84z4AKJi)c(pl7RE zQl;lp=^1q;>0db(shQhek>{o{C@9}h?iq^TL9Ssd$_}m@_ov^l&QI7gx6ySYGqi5p z502pttf*5IYj%HV%$K_c)QkfUzYB+i4sD`NYDE0dOhOdND zVShv4^uFr(?uM_0EyAM>z3~mb)hmB((25+-t3IX*{1eLiYRQj>I5LyhkY|y$rD;eu z(ql-+Agx6DYc)r*knTV_8tHpTW0Ag&v^!G69t|Rl1}Vw*4q}Bbbd{%`p6l$=%;S!XICwQ>ilx!ZT`4uXW`n*jaF1B;3oZ@Pr!CX21)jvW>S^4YZE|*F z|19T~(>>;Z!v-Zt{3zEVKH#QN)sEy!b6i*x4=V?zA6E9__vQKk8u;`hnyyzs}F|kYT-fFPpJ$U}8O@W>eN0rji)%6JKo{b|0 z2i+UM{sg;$cI*ZSxfUOk9+NA-7aHSNR58urT1I@m3iL&59_%;RTDdDF`ZzC(xxPHW z=&oBd{;yfbsI}s5alK3DW9)3Jw%yib;$np`aHVwi+<3W8<=C#gOad3GE`mOA%rjAo z1X0B71;4uj`r+j+=as5rGL*&@WGFY>!nSf(!&=FW=Uh{obOu8cr+d=HHtDzr2J{Kn z1m#j(D>g{F{;2hqP^~{it>3Gf)^vo?`L$tR`x(P#P(hBQqwe`a z25d5EOrM^+?czzpqi&7=E4>{&i(@=EqfO2nQH71Z(u0b4406b5!xeE**H>%mLxw+>;>| z^`>7`Vjuwxy^e3yanlVv&aX36Uv-+SttR9%aqBEo6Ym8w&pl#XKu;q0uYnk6 zlyYG0M0udEfm-WI8(!t&2S5@P?k2;UeOdT>37V0Y(33xU&<4i)(ma9hJhDm$KX-NW zR)~eT7xnTHwU>LpyicWr-O+A+s-9CR;lRrADkZF{SnSpV7n@Q-)5{a_+pPZ9yyf;J*Qx$9ezzVAyYjVv5Np0cgxhgfBBTSU+|4j|^K@Ici z-YF-Hw)(xHvVo6t$1f@m{VgaW<)PWy3Au0P(wt+|oMS>cUr{IzZC9z{lHB*z95HGR zODIQyvKN$5SGOfK9b;REwQ!M8T7PStfQ$YYY}PZ;x05hV>VOO1t3>0k#z-N-k#ZX^ zO-IUpjFi`cBgH`Lyw?(Jk5pxnYU}nDv`#dh)pv?1KQv-CMw|l9kpYLAx5ugO;CRTD zo<&YXbPw0k`AZxm(5+~w@#|(1b{il5+yu&p>)BTQ6>#PEji!7!!?rT*&r?3!)yJd@ z@!|ineChvXoUXYy7cp)y_N$D_hw~~Q4(?iauM(FqbN9fZT#&!kL;4SmBQa@P_3~r< zY|#elm(ec+z9Fw*e3AH>-f2xg7tD5pH!;kFrBe5bbuPxo!r!uI#q0c1a<(BHxtu;S z@-E*KSm(J`_DT=f_zv;rxCrRMQv;&HnShx9A>qc8loDXhn{Jr=gsZ^#*RZ7)(1NQE z8&H2!EXF?p_W&vYbuwV;E$gC4oH`d0BBcR*H|YUj=s=cDFe6OgV-9?eIx>~B-Qj#a z;?`b9Ehr}TCNaBTA;!PEFgPP-7d{vD1-PzR*fFZR%#Gz~5uq9J&*i}x@xk(&yUY#C zNnp*vMe3ZumjyN~|MNa`_3~R%26bM%i6_;4rh2ww`5&|7Qyror^`WDpQ=ZU8ZHe#y z(=0LjFiS#G2CFJ%xa+@W%3m;3Rzb>u7z*%`G*uyvg6Cf$DZ@iLI_e$@l^+(8GQ0BXIvFB^B zC*7B84ed$qRrjRXhU(@hf)y`7q@Mf(BE}+>Bu?Gmb>H$(I+$ZWn>Wj0tr57^zM;%d<37nYS^Y%W?x0?!@jgB8UY_;p!0a({^2 z9|m&+lR64EbKpG2ejxtCWvR>RC%7Yr8IHT6HVbod!LKp3+0zAl`GI8Y1(Ge0L(uC& zrbs1(S%Px99?y}Q^QS>upI(}Jml%N^S5yl;&BrWBeP7f!-x2;TD2^8VAZZHI?QoI0 z`qM|1y@^@Czbfyp10up3*hAD6zn4aiAH|&mHsH2x?h(*n4>Nk%2W}hmL7no34i8_x zpTKL830!F}M=W?~-2(lWwL%J>F1iL-n%KxNFIIkiitC797oo>`8R2I@g~szcU3e4Y zyrNrne;T>MEu(LrRH4UAUxqig6>q>*rI=!MGl9eH&NSE*2QC!PkQ&5q{o&|W@JUT! zdiw0yP_ByhQtSY0Eu}7+_ow3joW4J8Vx6`*fqmOGuI8r~g~&Ku zMf!<;Y!hSfq{Y=yzilS)W;>I>c&DTefW0H|4+1Z@?>U`_9V8PdYDbh)_1E9qEAgcy zkWrixLjrs;r9COd-}#AN+w5T81lKgV7~htQh_{J*qdsz%y6En5MHM1jGUN7J-G++7 zG^XY-JgasgRs`K?9#*PXQVY$)i@;AN8b#}zIdd?l{=`SZI%xQ`R7wpENj3|7S)&~j zdrO+@(o@m=szw$_DyE3$G-u%P;=I#uxWa4iNeinn0cm!+a0(bViTpkbe45&SJ!N%= z`Sr%av?SEWToNtLz%vgO&pMqWex;C-Z=?Pugf$zup5Qztm{>xb#R_zupk$*XqmDzQaE8YwYeo8?@lNvJJjd;>Wp0Kg-k$bO%x(?5m&aE=>#b zeIP!L>#$ye^pW9~2ua!7>nXws1FFJ6!pjw6Jqn-Jbdn5o#MMy>jTKpoz{`p$VJqa& z-HL5)DsSvo>=Tnw@33O-G~!Z1-bmVG5zWOa{Ei4NG}@NcU5tE8@j5kMN0D+0Wn|YW z79kC50ZKN5CqWLS=!ob z_wPmYJ;D8=Gu^4~b~@!r?Q~sw$5W@o5Yjv~;$CH>c|}?TsQ*ap7_Hbb_NyrZlG9v~ z0cC-doSh>SgYvI+X=_KjQ_@UTV{@OuK5qneP$NQRc5f#m>V5g3rDpSvToOOqTj;t+ z-7VfLQJKVvgB&rqG^F|fNA6G7kVlZVIW=S=QXf(a(w#`l_ru;0=`y7Kkgl(Uf5=_P zhxDI!YKRf(Gf22%2vY5@NklYeQ$*rWs*^|kSby^WxyqQ-y0Pt3M@#5pdA@-R;yDZG0k%Yc=b5#QOJu)`_v{D5=0|7Z#v8LHQO;Cwuk1!E3K3GFNEKO z-GVGUB^iyk@eI#RYwDZA1$hSAn={OmXV6Eq>aQM1-3;!Tp0g2LYs6KPKSKYlzn1b0 zY(#<$oGAw>NyHyK!;mYv&rzPCeS9wEYeN0mId#-MH~Ukde8a9F-#`Wq#eN8~?E4Mh zHb?0h@YuKb2C~A{$E!pxC7OhpidE$sZ0JvqzS2ec2CJ|;_lEG9&`o+a{aN)Jf5c9m zO0=s3Uwd9ffA05GLmK%HSGSst?#zC4oj)ZcM}3f+B~ZGXCKwXv-t-gsRHG@D6R5mW zdGmy@TIiC^d*`C%=7w7CLQ9vd-y6L1@ZN`U=i$(u-*IQw-iL7IA@xd^Y^eN?P>B+B zm62jNq(e=64}nVq$7Y80z`mKtIWv^=rG3dj4DOQiU|B&tH1DJP-WMoe*9M6?~Ou;?@@)g^CX>Zp#&#V&3(52Vj*tY46 zS0wtS*H>=LfxD|YAJ)nLb6 zd+6?zmT?WVm0#M$k<;TqbCDiGYC!rZ(zpuXZ;b_QEr+arjE3B|lOqMAA(KZs66v`e z@YO?l6zM#qTaorgx)|x%Q5w<*=~GB`NarHGwjJ@lkRC;vi1ah0b%``i6ZIixR-5=K zS*v){yFuAkr)+BHad zJN~`{IW@6(ffgwkM{>v2yWwig(r`^%_zg2GOsr;OJnkf7t>%bij=f=F5{RVZH@X5o z>@CB)4@}};K{QrisC1I`G};F9&PK@Avf=&ujvh}Lw8yqIYdB(CAH7vxe<`igkh!Gu-i1-C>MOl zZ!jzom{ChDry8*1*Zy6&8}}&MwEE4EJBo}dvxn^nRQtzlzY-iCZD$h}W zPefgqTBAU9-$${&9#z-C4*8O*`+m&pry5Wb_Be>NNBNTB!hi}J^v2d2C-@Qu>mHTe zn4ksD2451AWRopH?WX|QjX+oKW$OCs36)*lMMnPOOOl4Uzrpv+t9T8vo6))NscXET z<`hCXKj{+P*4=h@33BA;zLYxvWu>E*>FWKjpzU_z%&DFos9zG&c8B|@R3#Rp6H-2= z0D44&$1Py~6(0n3EGb+fo`9~Qy71Nd58Q9M`uHUApScFe9R&Ajf$o@=yWE1NYEJGZ z;S{7s&MUtZT495V=Tkc6@_lpMZ@Y}(PanlI47Zs+fl=tsrsYF>p({^qHVlj(RJRYk zehB*3HptUR;0;I|iqL0oK>xiL{rPI)GU>8@*~1Z9w?43a?4Kk*~NgD0M9=ELHQp zSonN>C%o`1C0{^RS1AU0(SpJw>fNUccZ>T`T7Kcv^)FJ{95@^UvHZdDIUt8%vG#Je zaePg=qAFK#{9kf~Y|0;O{XgXjhClIp$^XOesd5Efxym2dvOmeaC~SxK_^k9<>h~3( zuc$=fiP{p^V>R<7TVDDA>m1^E0`WYL*oZ{e&34e^uFl59NcaFCFt8a^pel zB@H!tt>1uE_2umko_iIVo$cEHIwjm)sQ7x(UTmpJ4xH^A) z?nj|Q_~={&R^->uy{q<`A8YO>xvLufSdlw`%kwH-bBi^faOCfIXvmhWSVoY(h*Ta4 zy*JXIk!BqV}CRZu`rQ7gY@V} z@SR8c1=8_Iw;>&jbQ#i)q1YE8y@*sqT94F)bU#vx57V1pRN-o32%^7UV@*9ZDUg+H zl^?mV#bv2Ne~clL33iqgd!h&I$&)JRy7-D7o;fx<^7ZgLU;|F|SiSgeybUpn@x9JY zxqV*`NRPG0x5`)irXhNP3>hLBhhha|UaATog}!9XkQ?n$%&;mq=%ZA0(oVS^II^V` zvtU!$Gr&cHlCh>LgH2+xGc`{AAKW z<4~;n>YK3U+CRkFNn={Qpun!wXGPoq1N2mZWDo4gGov_L z_VubEkUN-%_@X-HXIeSfcl*7M4ghDNbGVYcX;Fep>!cpdhC9ppfjfwxZypil(SPID zvS0cm7%lvr4fEZ?s;HsDKuHv#5j9Q4PT(H&mD?ghcMYio^x7yRhQTkVswrie6rAt2 zsB%!o$=kJFn!stISQq615;kJJSRX`j}p~q zNsi#eldkrl9w|@=8&ee<+0K*I9PoVlwP|4SsNX|Y6P)#GgFUKhrw801f052aaa#<- zsh8NKtljiGH>2-?T>CmK(_Eu!3HT;v=n&rsX^4nezhTqTdis7*H2L^S^-E~m?X$dM z!LEwni%hDl5Os?cSXj(=$T!+Pb$NZ~ML+BvdLF0#86B`?kB~lfQA-X6+PfNGQ-c;W zR;$k54*A=*h6Z(?0iVFnHo>NG2<1hU6h!fGBX-CgNnU6&pBW0I3{{>)Snoqr+e&&_ z`bz9Tss+_aiepU`Ec%G1*-D7L+{M-;@>zWKlmjk}Z@WlFP*fD9cnlv8>$MxTc_OXH zBWcYwb4C5IOJ3N)F|_@ec#WUvjsk6p=I)S>d@&+qZ=waJMY+c!DyfFb4!N{*r~8TB z#~_>2UY8afQ$Dp_6hCTqXddZjfKz(J~kU}%T=_KfAB7XF1G*nmfU{oXxw%%rK9? zTgE7GqR*#pl^6TNGbq~L^Qm-(3<`7}(1vVAzW06G@bC@TurkZi7yU^m2Qk>u-e=KHt3f(U()m|Q_Seh1zefkTJm$~6t}__PaiD~R17F{6mz z)$<|u2jKoT;4fFZ)pZS?&k4ZhP5|}khSFnTpHrG`1HRT)`N(;MVY7JHQkSM~llv1$ zcO6x*4}%7MLqZztb~a{HzkzDJgHoSD*fx?u@Okr3u?&XAyuqJpMg*ih;4XKKu#8@K zDr&v!S}pb22^99i7`Y0YBz7C*;vQn_FQzJn{z_`NbWaSiJ;yZ8rZEbV`Nr9KppL6L z6ZxSFSGoeV#JW{pdja<6us+vx(*hBI_Nt2iTr~sr=*JLpo~YPPDF)k!X~bGDm$nR_ zx-^xJMI0qBq$XiRwxpIPY?YsGoFuJO_6kh%r=&dbo(i%$`O1n>B=&dt_s)e$2vU>G zfGT<#2WC8)^Oo{mtbPAya()wHlFWQdNzMKhK52}tUKU%%!HZ^X7q!?gQubz3jY4+y zy^xz)#Lwg{O|VZUjLoC$HN#c{`LkO-lV5C_Ag+X`CK>jHmsn{jX)Sa*-b9S9Tdv)u18|K3((49CScUfR_4gd2_Nblq#*urm>Uux85 zXhXK?I%}Ey#$_wkCQ|k6TP&%054Iqg0bqc}W-Tx8Eov}gFG0`U@3=L+AENuU^en5K zc5QL~H&3R|^lhE;+Rm^KVpM?(keK&`L|M zXvl9*2HR-^>h}?jOk6VnpWX}~i6GAWj?PVaAGi@G)+Au|Qyk8Bst|t>c3@ut$N&3i zCf06zqUoqs)|G))%k6a>VD|T~ola_O0FPw1jEAhK%PBbE~54}o|mtxAm zL#W-_WWsu7H`Dn{=L7YViv)KD%tPR?CwVqw+-duFOMlljrs``yhlboNfKr)#%8J+t zKzPoFudcT%)*W7vGr*dgDBc}47QAzyaMz;Xx5Z>CXm=CO@!drdXIK~}F@Ciill_bcUhIL!V>TpA!O+Av0rUV@wjzqZOBHg@D1 zB|W^Q^_gS{^$I9M{J$ExTi36^bx;mk(LP11;g9vMin}$fg!g1R)0USP1G(`Po~c`r zW;*@?o_+!7&_S&HAK(i^OL_9reS3%8*~;WGmnbUc<9O5K>d2fgG1ddP z?zlwJ=;z}4T=jaHJnoVMUueJdy7d0VnM+Pw)P-9wy}aZEBqwyt%*lle>9N9G#J#mH zL!9bm%0I2^Q7d4Am1B=vvP^j-VOmobcNnrZ=xA_l1CEUeA3fIa*nvymhI`;)hxmUa zJx$7;l1}wXF(n15thf>yKSVVGH$aYW%H`I<=7HdSD0h(O^c+odzTwU+9ps_5IgD-N z+$E`}=E9%pv5EX+a})VJ@=u7MJ`Ue7F7ypYFOEQrxn*Iavl6kQrDKlmkq;wJ5QjV1 zOJ5?-X3=CTC1pUH9G1!17N>5R^NV~=*;`SD7&zjb6wA;#{#=c{O#bEKp!Bb?<1I)X zE@*__;7=!@jlRD~21i0l(@hG-Itcat#dOrD=AsjSf4q1eo>N*Xw}K1@WEKBPoagd2 z#ECI69%F*irnU{hF~skOkeZREBJGRx>F1!kz;Dkxz{IC1j)(A@rt~;<2|WEumSp4i z&a1?ezlXM1)YPbZUO)uS!Q#AJ2i6W}d!G#G-mBqTDSDzC=iCRnx>|X~e7wR6Tj%nG zGWoNM^w+2O#a|i>G)@xREmPaPg)9esrQZY$8pSRySN=&>;mAKoy&@;#-76Mioy2-i zzu_&^>uO6^*8^D(!kg~FOw8YDz(s^S^|kU|BE?B6RX%)*+~Ewo z&`{#Fgsp^KhJoU)(>IJwPv#3S=f1o|rMgAD)|ZHPB&wqc-l=vrmXtul`Zk>zuUR82H=S{3dsoytkdjjQ#~t=zzVe zjwln_pSJy{7d3=00gf#CV9h!>93XW(qamN;_pUct(zTu=uOc<#`m;#mkoL^#1)n7I z9_s14f(ujxM+CK(wu&W~(_1U($XIs4Dl)Mii~~A4?!q{sS3S5&fbzA4&~+d-Fcav> zkIWC&g?*dHw+SE&{I^@h3BwCoS9^5%3z;!-~yl^15fbtD|*NeomMCIU;?Ph}hS;=`N1( zrh_((urOmrEnMTO5Aj-eq3rOiRV0A5u)j!RhXaA)G50sw$CNd~$8P2?pS#vn{U`fJ zpcYxjtOnvp0QEi9bhCc>l+Uf&b?bbYdcFzgrYu_G%jGd5vjgpWLN6yXH*?;*A+`wwDp3(e}i&redzz@||TB+CAOBd)`rH4Y(hwPhXS3jGZjTB8up* zwV+o;q{@Y|$6_WcDT`A*{FtoX;*!)YdGpPXiSCGC9HjE%fhn4Fe5s zDo1}oCxB@hg z4Oe4VAug^^`Ihoeb4JD1Jb&JLm-aY~{zXJOf`0)@B;93^s;2WAGAb`PW{2XpvgiLX z_9x&`6zLy0UOiW4l1VZ-fFuN%Ndim~j&KLWb(l<=9LVJr6m@cdJ(CClJOD)|fXXE% z0Wk+^5P<;|GAO%bl_f6d*Tq$51Y9nc26b~x5;}r(=bYcCW&-Z_`~Ux*=a=WHbWeA6 zbyaoMTW`I`=M7>9V|)z*AN4Bb>OLE1<81Y2^+nLs35X2@EzlZT6PJ#+*(qIpA6Ay| z%kho1E5Hr=eYTfhhi+IAU7ld{D0rI`R_7S zKI|YV|GTRhdl$4NmfN~)10-7FVc{dU1u>e?k05g-nn z)K4Zu131Uj_u3~u*+u;W(@&mlg8yqSuc#z1vJ zK5=EkbN=7-S0hK~(o+1^9X~G4X$zb4XK`&yDB^kXd7+?Pz^IARb7zY;a$5_D;WV^= z4*|bpE0V45jtC-ElpnvqRS%a{j&cu#npwrVt$0(kow|5;|tDW%z6DA#0I> zM|af4^>%y_*9b%c`X0Jo*HqKLe>@O4wmk6dKj+Z&Cqf*SAMrj)?_#;l`85B^f!{Hl z!(Yz={AO@J##%ai2G#-pIeKRt&PU~zqJQJL19k&PXW475zuKOUb;z99h3>UIALGO> z6qp*Yd_o*m$rOv2=v`KuU#D@2u1sU4A^tZrzmtjOkQ!hHr11qYysASNe4>LzdqVA` zqdabO$EaYb!@BmYP1u*^)gouUa(hQI%P@WYj{^|ST&lQB0TRT0W| z;Q7FMK>X{$Li~<#1+JK|BAD=-Vl+&iJLSPwEbAOV@pYgt+z_AZ zvO?1~*>hY}dH*a84&;}R*;pT)RlU3PI^40jy(q{l^__lB6&mBt}&f&(>7ZfI)yG>txyC=C9r6!T*Y z+O~EH`VYt7V5V{csS$iY>G6;U*I82i?~RBHJzq5mEt&_(n`#$q+0>`duEAv7ZO<-q z8zT3@=Niw&=EmLgO@23To?s+15p{QdBk9p{>fhs@rz;OlB=N0gAjX$`EtO2%gfrkO zGDXQTr$X5I!zV47%$63dLNpH*xS2y@O3VAtBCc>rh55{>f|B=_(C@XlNI^U*`??F~6oLxAY#Gn~C+|n8w0r|_nzsQ9@ISt%vJ811Nt+SD=W}u%a*CH1NYU{m zxy$qOayjDZ>M3tG>n~zK^Lgo`3^K;+xhB5ld&Bjkv`P0P@Si3vH^+Yk9Hlp!RYb0z zlRd}Ji#f%!H(%#fos&_+nC4^49*+NXsghSYed0Qwy2=UszZXl$_&Xj|r$ea}jsnl} zkf>;$xJ+0+X}PSGXcJlqf!#k7g#CcCrE}TjWfPZMV;00k2=cB;%hQ(4V84io5PGD^ zctV*lVYvd&B;lESi>fnS0VzO>k#zzi;P++IQUA3Cs^8;EUwmfDGfr_e5EHWlUA2HfogC?4DLqzO7Y}MUtp7}W);8SwI&ygn*SxVY2#nG zCSL9@C|MBSoX?l!7Xf3Sb0!It@-up;_h#VDf4Uj)bX!tlOh|n8`=-Fv$%wZ=$J)e# zdt+_(prk?b9R4`d>n$`M`a;mWw|&hGx?E;vUtWmkF3uVDe&Sy{82zhg3(9z1**RI2 zhW=FCRH6nGa29`){+8Xmg4rv){z87>9cMQJD*$~Y9=|58>yMZdfwkxt+CNHg_CYjS zCcb%xwM37Vagu$#2oK4EAu8SdN?it zZJ5}h74GYm82Ex-*AeJUihM#1*!E4S(TzB%$LW>LtpR2L&$M*KyJp{wA1kOv}8jAuK4O?1yz91c?{JR}1uHGX)C!LWNgXeWZszBFZCn6rw|KGJgW7EQe%PBt9PGhm`K>zI+ z=)aQoa2}qjR;QQ)`9k~je;#{BvrULt&nVcvEzpS0~ zxw*^3=;z(uu)-;hYcFqj3D3VY@cf_r&!@E0(LJiYBuieS%X5l5+LL)(HZxOR1Iz9& z9s(X>Zo;MfC#`$(Yl`Hx4@p|nF6nHP#zhhpK-$wKk(4gaBt#KgJV(1|pOv?c%2x_w z!TUOaSg3^zd5fgg^Wxe5hqL8Xro72%PVv$9Cvq0&A{J8ROBUtM7x;pbg$;B!>_nVM z`W4V~pkD>;HqhwVb9~}qMC^;F{fQiZYTqS|*2Okl6HoVE6V3e(pw`iO`L>^Jd%YE8 zqgj0^iztQsE>I@Dsa3{ol2+@c;+x4A(QlaIlIxY#iW<<*wz2$9+*|OO?xXNsboUw7 zqWetc)C!+<$!nEta#s8Rtt0JW)$c=s9^!cfaiG%D?rYFgC%Zzbf@?@QVsQyF*r%^X z{Kki*FhX0`(Z&dm_}7(}+lI`MS8E4qezmQjgrvOXiS%CsO#tOAa|hbJqdm|%cN^rQ z`fK9VzTg~rZFOFSG>N3S5F=P0Iq=Pj+K7IEKhD&rPya!;-DNT&!+c4@(Xj*eSp&!O z4jIYEZw=BMoa@&^7VrjaZjY;SRiNp$7}=|d8oQRX-jj$)9xj+pKD9VdZY*TLvB*<; zoQ(9-eLq#)(}u{UKvQ$VtD2rUa8}tyM^K6XH=SpCjP5|Y;xV>HF8Q@+2`G3$TTr&5 zGmWSQ;zv@x=9=g@HDlm?Pi==-x7X)eb)4uE9!vxhQd?e~Rgcl6>egp3%iE3UyAy$X zHh-clRpvGnulNK~TwyyRSu6FBayCyZZo<9vAif12;%)^yMocr0rV-Xp5Aa_cpr_O(D=k3{d{(vj9l3!Cns?H6-Vj# zsN7NLqdj?g8!=`8sr4yvG`h)8faV+LXEqr55R84b4_1Rc^lUcbnmWZFy?eRc(%DI& z@z^JgoYa6PlHwZfZ_wN7tV$l%ZzK0xnURDagk3Q>0B@)(T)2quBbk(f12ZMivQNDS zmobpS8p+!DXOejSrwup6IGE=YKOWP!2Rz%hc>muk;&8T>h>`i#g+keBfpO0Hui zHEETdCep$O5+gmZn2lM#OG%W|nW?1TK}rxhoo#Get9AiadoCrOr~ znMKsjh;jb|8qYE82p~@$g5}5RqpMuBExGZl(3ZW3`b67eKwCEVQA@56J|2=e6{u(c z%g8D2Y4wOvJ+Iu2_p))vOEPk4O8^H~#VR*%W(OfA_aMQiSZ^8O8HpY52!2eY<+kHF z8ja5&eB4dz5ehpB6FmN7dV&#MX3{_`I;LE%cZ&Abpj;{M3r_u{jQ5TC*>lam+waJO zeiHB6fp?W+%|tAxS@G;n8V#pnA3QpO-y4*Suk47p$iQ=yxik3o%Of-%{GTWHtO!!M zBO&{WwC#-v;TLi}O~cTlVFNT~B3g8~8*NUIAAv@FcN93M8~yUyST3)CegRW|NcFa$ z&7B!@6_FPjLWGUn+&ny@W4IV=6S6-eourE89?(X zmGiXZGoHpK(?HzCGr%>R4PS1$N2B9tn|*m|qFZ-$MCxR>>S|o7>B`X5$v?%X&h(7o z6H-&$=~t}xg#w9D%fFbay81$D{N)v?aX&quI>w{syYFLCjTggs!sT!q?Tc*jybO_0 zcG}BJ{E>yzW-X7~5{YX&OLDkH%R_lN@>SUxn;O^3?K#{R*!2aTtw!|Z1ade24V7Qr z$o(0VmTDJNY*pU3_0QQt+0f3JYB{GWr-*jBJBJBP{Xa@c5tnm=?Jrp~BEbkX=NccqKn`EaU#uScX0^23YJ*P@IKB z*;%l;a3Urpm8=pWy=;G$fptP>fj77A!#O=W(TdnN%-(F!Dp?&61A-6*Rb3fe5wbH1 zm_?Qa>Z(T&hxHud5>Z4|cqEm{Y(Xh9&u+*$3IuhC|9g(&F0l9_j@XV4}KUr z6({uVM{OzG5Z4aKOBkO1-+_BO=0Puu-K0}o*1FyTTj2UGOFVx?%F z1o-yinvo0>+Ir={p0$vWYGTy0+EX*w98iOWc;nnwT(75g($_p|QH#%-LQ;Y}(?G`$ z09Q1)dfH(p;+quPS0U;}BCgi;UhC!l zD@RK{i$njUE;^n_O!^cQ)?rV~w;xl&I z(Jl+EM@e@na7CxnNJPPmFu0ez{RDV~Y<#J6c#E^8t;xU!g9?5MYdl)IvN!SY1oT0a ze+*T%IPF<3+IL+&V{vsF`YsWDx4nhpF$aNS`|dO!89h+L9WAuxyP8!sxm8hIm6>rL z6qnt6(64{`=#c0gtMvr$!y_Un)0IZ zc+@+-E8eN8W`vk71FOc}(ZKk9&1zujy|AuiZcG7qW`XSn{&e|>s&is>Z@r{)C|RmC z8{|Rc+mY9#G10I?1KNUdGEx%gk2gE$C2-d2w|_zm@Q8}Yol%w5*S{0L?Egvn+$CdW z-mjR2($qSaq$u}*|6ai6Aucf^M0G1`DB|*2L`q?%vYD+{z%z`B7fO3+jE8vPWklJ~ zLofQBSl8dWnRx#mGRPSM4=t?T>Kni{ALP6N4YM2=#Z(d!=UfC?FXcBjc6T-nawemM zO^Ej5U?0uAdS!1DW5`2$6D5K;9$&(mfJV7Z>M3LE5ko5Oqg@h*9U44k%Vu4to~WP# zeY#rMT%8W_W{0?-`J!Av#^TFCs-2-1)K%b@c24wLa-_0y#KMO3t==b2?onP>)yRM? zaQaxSOH*wqQ2Tk?ce~UzJ2M>u+=+m}7zG~5Bs^M1QcXgKV}bt(HTnB7lCsi0;=OeC zocQmaWNj2!_2O0O+%|g^z-6}zRd_Bz(}_iOvkt(!f(El)BGV*gS-xTc!hRnV#y>|M72sES#wbQ zuFWm7ebGmc*=JEJ)Zlb3H6{9#JW-Y?FS4WoKfyN|vCWu-D3(TtLfhZA#Q?tx?G7!c z?H=s=#2#9cnhFhsb!g1v}W z!;s22Cmnm4UD5AO;L`k@@ji^T2QBnYvY%_72J0QpWw0-3pkqX)eY$)5twdL#Pq4R@ zCbR0QjhVjNhmZXEKhTg0FZuFqFo4)HCA*-KB&@MSVU0b9RZ=c=OIRy~@9|$Q{0+NI zxA?D~pMkeB%boh*n7Qj<6{2T@s>6i;Nc^)H*}9DQpO;K`z5i^Ai&V<}D53|&scrk7 zWl~!q)#VWLO3#K16Z(Q`BDgLWNeZqayO_j2fApy`?i{m0t zKCGY8g8u<6$ilthU7J7)NW*=+#%t0{g4WUqu7$4gIw2hqV<=5H(370?iJh+Qk5g*T zMM!c-j4+u5xi3gY#sHsqQcQ${zF0m6ej_n%dAWhoh(;O*Ug4nhLS0T#jrCpmb{f|U zF?@Z7fwRp%W>h@?48{xHV^Lef5fa^xINb^M#~ajwO#O8C=FSNiFPpGyA()dySm~Rz zhNRx`OlIGr(S`iI4!vqFbYlKJqA<@_e@%KW2Yetmq~c}E;GGe>LMzXSN4i=zk6**U z<~gh)s+@Q;NOZYeSnro`wr>ipiFk>kj5Kc|!tKw&`Nh!{Xt;BYMavb&hggZ>AUptS zr8%+`PHh;x=M9M`sm{d8yj@9e5rOX;=cM+2SNqfkJ*dOQzAMtFkl|gC>UH^_{gWSh zgjz3+;Z|5bv4-*IfGpbx%V7od;|F0^Z{TF?X4@>B&uq&AUwKYE)3uVT=OTc=*?fg0 z5}rv!d63Wk=&qICfK9^>unQ%^>CeY-qqut8LDA|}fzv-IF7`5pNilgqKS=IN!Sh>e z3Y2=oJB}g^;Qnq{q444w=_kq3NaKw#7-#b}i{Vp9cA~Ci68pXQ3!B_D7L0!k>mZeJf&RBLiAp{RZ;0-U4*#czpx5g4GyJ7gndNRK;SK4! zUdf}>v?v#2z&8XhpB4EyVzq|yc|h>jUj9KkLBjTIg7xzc(&uE8S#?P^Nj-6!`Q{ZS z`2o>#6e|W+R28HqdZz*Os-rjTUB;l+AFw_H?xY*kPVYqIRN+Q%SoJ#+uOC(5vOexg z<>Yz-?nfGpG-R!1sBI1ED}ZO7U-vmARq2i~!(^jf*z*r6r}Ok%$=FDQ*}b#`727Dy zbW8xJjo3QAY<3bG>@@{z%j*k=I~TG#p-383t*yyox5Z3g2km5p@4ALp0TX0&MD48j zv?aqUs`8Fu_8J?@xY+V-i?N@_K76HXpN%o-^qQSSi0<9XX=)j3f^8#KztSZ%@9=kr zRJ~@FT_H)jU3E8ro2X6j6s$fMbmzQ!@-9gMFa7Uc=(>=&nxwY7r~7%TbzQH-m!a+1 zXnRrbr&!IRs^F0xv-n=NlN>7BajAH?at(>856NhLzbhHCpc z?5f@^E=|Tr@v2C8xyc=Uby~9a>cr$Zmq#Zra4W9v?F<9DuHj-XpOQTM>I3|;~l+rv_VDc)t} z8kMHbmJN?$t!30&emE!NhuaAM6!)lwB-OFl*(YJ1PpxBPYs$GV~5 z{NwEx9px!aLYLzwDT^Nt?p%hkuvCY7Oj0YmlGo{Y;w9KJ&JM<;p1y+KasO_)d=u;~|?^lD|#bZ#d2ULu_Bg(ONzDT3Uv!U|eYs(qWlf=OFV*WN*0)Iu0|`Mos$ z({G*?oWd_TWCW~2D2dL2lAaY@u>LD4ZB|bFN-HD02#P`9Va4^V_)=>K-u~>p+>i9E zK*aSK>{rs5S-D%TNw=fFlJpbSSnk8y{w<~9{}fPQCUmDi@4^R`0 z@I4~xVExDWAmI&M4-qc+?v_dom9E_qXNqsAmF9xxJm7w252X-$qLIL@?*o$kK{35~ z66i-c_D$u_y=+-;Nn=B+Lxt~pg=g_B_=Q{G7mf|^3kKBipg6qw6FoH_X8s=HLyr{x_(ahdaZCpsr7@6X8tv<~>H%0uNVGF{FC`^`9hDIgQpb zj;FIkv-1bBp>HF%iGA0ssSWmMYvvcga=SP%^GPqAg__!{@aPY(+H8)*{i{+M`MacV zjNmjo1G(CJVyZQ@G-rg1(QlUq5n8^XrXus(bCIA45yF)4YJ0TbI!gEa-p*9`A>{#? z7&EOrkNZK=W7Q|JFt1rQf3wN>>8VW^*Cy=nXEtuij6W6T%?|rk+I~GX8JwkN@F@Z+ zFc0Vr^IErS3oJvZrDi3i9}eFpeC>R!^OR;S?GC94)Cmzd{q?z2Y>N3O>{ox1X5xK8 zOlRixD}Tc*_~=v+e7~m06HuXfSg{r(I%$A@Sh_W}HN}^T=f{9@kdgeryuW0eE=wMM zNn0IkzuYkTx*BaJya`+bt;PL5P3=6K$xucF8v=ty18NdprL8Wv1{dgxH5?Hh>Cx0` zYZibrn&hdq8}E~)nts!jX|At|Pjx?<83UbuiEAl0__pJPL=Wt9^+bsD1wn4`8s^s- ztB;?~f{F`j|FuoHc88DLGac~_8MPwdDJ1)$lY~75R97PW-XDZL=C8c&-IejWN<%fi ze&crVxf?#74*3NUe(nD}J}^tZ?OGEbf-6@M5h}2Doav%;-?lsQ6C)R$7B95-redEQ zV<+XY+@Pu*wy0`mcbv_;Sqa&>tWvRaRj&N)?_hDaGJ92yYB%<#yRgD=2gJsXboPLF zxMRewVBs6ACBK*!mCtltk@8k{spRK}J4369@MPccj|yz_w=9Jehd~|ae-|P_YJ|8R z%0)+jO9uVv(z8#_l?yU(-ywpb=ZSf*VE*X+^JiSo&y?TRGn0N^GQ(B(tkFfvC!nWh z;N7ou?0uF=_Ve3mr(JXB%Jp+|Ua>^it_5!J0kO10&xQ%5z7#}O*V%?}S+JC*QCVRB zzw0yG0nyqqxmuPS>LJ4LuHm(GHp#u`R+3!{bfGnaYpMO=EdCwohA!C!?v0CZ4R?kK zv*EiN)D^l1R=obm;%WTkIh3|721ZKgo|u*2(p-4Ln0so#t#7}=7cJeqDKL_~|jv4qp9f``ZGay&~A!Z|&W8DhN!5?D2;kH`iVu=1M zZ02;wXWgkUJs`f{PVFCI?`btPXrcYk`n4Yi#8075*PRT`CJDj0v+jIQipY$>Q)Tp8 zYXOk3W31FpG3FF}Z1ZKLe-(6qi0R&jBu~TMWR@Nn4tVN?bn%@^O5dYWn>+GtDxt7$r8s!u?)Y+S_@>79*+!iSQ+gr z&G6g-DvGZT{UE{0j$-qKu{+HXp7p8B)h7wV%V9;u7@Wi>zTivX_HvaZ2rUY0A89>k zE#&IBMe!yn(F!E^lWKTMo48!-X1odUB-k=;t6AkHT$x|?&rEzA*QwPi2nPI$|McKn z_3Dq-S?=1Uy#=k`CZtui>DkkBV!$(wz}%p7gw76k+X`C_7kRsGxyqxpe+m==xf?#H zGYL-;$3H07kB86BI`GBGsM}xL#^kI*>>Ig$tp(q|4e~+x9ZvPO@xh?o#(C>3#<}ZZ zr|^nJ35&50{Wi&yAmE}%Pcf_)c?KS0^2(t(RC_0@KewG~32S%o(Z!dzZ!fkX{-=;gK~I~n74?*$jEL!6Se7F~8CB<}~rWo=(J4f5;y z*-Ql?_+E!s!d~WS#FW8tBa##6Taaes+>G=f(j!O{aV_ommU?1{PB6@oI}eEFHa+Z< z^bh`$x6Z;ZBjpLpBjSeV(49gu{E-Tm9}v^qFm6|ooylx$u3S$w{{cEVrmgPT!8wo^ zmIQkDfSAxG6HfF83-+$_(7&yA>9XaJB!4dsmlQRsYFJp*l1eSgrX?Q`wQU-IY@B7l za|B$I!CMv@MQFL>8ms2?ZgDeJ|y4x>w@pAJ{bM2sEI%S`^r+<7H1pIN-)7n_XC z#IXSHQe_9_=#C?98hTu%KOipjo|l?2Q!$!v_Ai!^$;cyzPhFf%cRVCz82lk1k&O5M zskEB-=ur5(V zX-E?X5|z@7V290du)}hz>tD8nu@&sl>|gUHu|v_1;Hc|Jk`c4@np9Ljj_tO{KORy} z>wTxS#}WnYD{X&C2j_xkPg*kj5Ii${;(I>wmP$|M@U%bpR%Y_&=9Vi%Y9@ecFzy4Q z-W%&*Y3@u9$k_AH?hZ~ySR5~v2ITA&&@pd=oR%>}+4J<}>^l-yeof-`lB9RwXEVG{ zc1X3W8K9*xT%QQ06X#HMP^}LUWqTO58Y?0S~0WWaak%m!yzuXhz-NEG8sD4aG z!oX?DD+`07F7$5sixk|bs`{r_0kjVCM_xsKAg?|Q2!*PORL~!_b}}p5`8jA{_?iFy zzlU1s)>2#DQCU9_wTwiE{p;jCxvInJ3@&4KVz?hz*{=W?<*m4EZq;%-uIi%-AzuFVdhL zbM$6G$9yBrLB0$~yqk+4X@<0(@On1F|827HZC-dnMw;%ixPR zeBvVPy3+U3SXru_-4^I)@jYS(zQ<9Cevi%mo*(V+d7Yc~uk4+N;}l+{mhvWYkIK6p zy({Az zcQI8LvG=8Yf2{`^hy>dAt6R|b5v~H-62@b-rR8U#*Xg&~+Vyh@qeuVCZWO8bTR7h$ zMHBS3?6;yo50g_TfMIyIZ@0kP6q*?#uTUQHiL=qGMek$3qVD#uWtsk6D-n{Q4OXZ8 z?m1(t%-U~9?RDF@C`s9<4Oln)MpByGZ_tqh??I!k8aPzfJaX@^G9@q!c1qjRDy26Y z=X4W_FvDy!dps|WRb734toHK$&gDdA%)hAMyT{7hJ!2Qc=Aq!(-O%wbeU{1y{>+ha z3*96!53!%rh%cGI-Up8N5M+)f;j&{T=TVLVrd}HSif;BZHbj$Es@!OQ0v%g?(TwN+ zhmR2Sa!KPv_9@4Mob5xoOe_Zv6!2Us*^^QwYUgS0v>HN^Kin|DDMWtgu zpJtZ{VSU6^2D&S+?iZ(Z(<@3`S-wR<&w=N(n>OVB2w{ur$*^tbLE;6OZZJNGCvinhtCcqr`67{kM8+q2z_0jqkx(yAZ((J3RV$2BFQ5hpIu7t(coqb;$a zEdPuA+@g@8(%FAU?1BYF!9}@6U%(UQf8UEOA_=*;SB5*eB@smr73CByDABlr>2tVt z8YO*^&lDim2)Ia@9VJ<}T63*T0ZQT);cAw(40kfP&A2)XC@S=qTf!ih5`d792)>i9 z*5NF!S*!40Fg+?I%rA^@l!P?5bekk=Llw&39W&>&D&#;XVOaRM`+)E=TQZvHDouS* z+)^(I_4~0O=s7Qu2^rEz_%xQHN8%C9n)M)W4gnVAoq-wbOC081u zDuxPCz4QvhQtt7C=B-)#>@)HL`VDHKq;$)j3;fR`SLeyNbBh;^ z2umIZE(03rv8iL#W9eTEQYt~2D`<(wTI7clIr>W%^Bmf=ANJ}++z8k@2kyV$vV>cn z6WXcO(ktXGpdN5mN^Gtk>Mft@(gd8f_6ZY?yt3$_l*s`diQx9 z`jDRMV#cBe3%UJbC7w?Duct|iF-QJkpbjzculnz&e``+2k$)VxXN*a-?Fa6_-I9N4 zCI(A9^%C19C9v{CO0<4lM@Eg2Mwa(S4BRhr9Tqy|0DmcmRZGpWq1yeT7G5#BlNq>A zc}j|lleP2X-)FD$0P&^EvctYek`oyxEB~@G!Ug_T7~V?^%A>w<(@W?4^kbY_KlG0=8fjY21_6nDKQIXDO8h;?r9)o%%asG7rTHVYB0Xlm zc&uam^~1TK-n)?l^J~9YdUMqEG|aEUZhD0QW#11Jg7>o*Net$@eCLKIBLyb7z#YTw zv!C|QqzwN|GMPCVjqB`eYT%)@2=+!o)fc&@G_11(&H-kIqu^FKWaeL>2Dyc)D`Y5Pc92tSh3 z@B!}uGLmYP_KU;YzY}-&(RV4G`{85tOY!p<&(Z!Fn;J_;{ZW2zNr>%q!$|-8_rpgC zb+s*owmtJO)u2em3nbO0yQW zpiFLGgZv#Mx8cci!(&rlLI22w>~;RX?CeL@6|5^*wrt(H>~)XOOWDe!w2l}BYbn=3 zd*Qj8cfV=`NBx4n=+C*=XY`w1lj2?b#n!eSNOI}3^qI$RE@aCFdI~Wnbkt_bCw|aR z?+5Bm`^w!$Ygd)|^OYk_^bYNrnKzXK^K>HSX|TUUdOhvt_#EZE8Cb~0+`E%>GbKlP zZ`Oz0yB>3MrI{Yz(URomV7sBZ>lZNJ#iuRN3h1e^Wh!Zum8k^QnJ1Sp-1d%w87 zEfli{^Y+bmfj>v%;kuuZlS@c%cFRcL(!l&3jNeyrzH7dWe2wF2q}P#xkp>}syF^a@ zf^-mR8`3HyQ|_#QP1bA`Vx69;mmh^Tua1n=!o#zgy}z{El2IPR7eKqQ5dO_rqPA9WPk=C#Jmq87UkNh9?mx;NiqrqKDLZ8reF^ye!RT&Y;I@PvO1%x|VPUSwpq z#mGMcPgm*_?Gu*{lqg5vZs;iV(_xg<+S8rlW7Vy(i2;SBCso zxk=45PI?0OmigQjT02_OQyq7EHLPDg(5p^w26~m!LLio+S8sR&v``C7KH8`MD3X&M zNY5jE{Wy(VN+ZC2YuB=L7g^>Yz);XL{o?CBVmL32aTu*CM0%%JUcnV0RuiTFH@(*{ zKIi+u7DOXXkf*SdiW5HS(g_cQJJ{K79du+0=z@~L1155zyiQPuYw!K`iDzN6O7Ak0 zW?+<`?uij(_wu8EV3VM`m%k9R|5#7qf93xW`4#u_C)#L!{k{B&*fH1iB;tGCEq^ES zH)8bxN5l1tV|_7#15Z;tEM`K#IMP>CLdLx73Ha{?u&jb|X{78e_S(E!?(xMkLGQPK zq1tDMR01@hi^+HQG88NLYx@>x*@*CL*>-B_pGl2MpZe;GX#d1_ z!NMAL@Ppm^ONe08teW3flFlaB7IBATQW2xtC$@DTH{ZSzaea{RK*&UQOOW#XAlmOhU6PH0 zHNvRFLCghas*LxlvQEjSa{gZm{*a2fAe&0~?+~jZtBx4z$yte5`^BHJVj-pvNn`2t ze({R`xBA}ibG>IJEg2*<5~h5(dl34R=8HZh8^w&GPwM=wYxF-AeebCg{@*e8e%GUv zctWjgiLl!-2w0$D?gJ%X-ZIT1iS^uX98;RkMwPDMm{AEB2QPIG&LI&8`T{xZ-LzL~xJBHfrT+#}NCNko#5kCV@b~YQp$8%^>?;AjQplIL9J8vp z%UszbM8Ale#Fjsj&K7V_VKioU8_+`|kPmrs3OJg(io3)SNmZB5GO#hE`F-LPyh%2- zhP#M&J;BPPkh%io2|+#R+eUSBL0W$qjsHLINw5t^uMZF0%}IwekqN0rT~Kx%En9|n zBw!RP@CJ%X%1oqh5AnY}1aE%=Z@<&U)c)++>+c1U_~os}L0fHK+p=wgOO@y`+7oSE zOI)-sMsn4*%eJ|t8_*B-_(e8q74`2fI_B5k{_x04HUsFznE82I92ko&J!@_FrF&=# zfTr`+wtq>IZol|)3!NMNZ>ZqIcwSmIIg@0S?ahinC0ELVsTYeX+EvT3;S`~=mL$U8V)Zd`>dgxgAtB2NbhySa7-Ml=>x(z|~}**7u6X6@44U6=urZOj>DXr)OVDo=wip=R&Xt-wDbRX`33e&H9}+oej?K z7tePG=FBpDaXs|t!!fckt}t5qMft$HvN2;BHjk5W!B*H_>A!%j?bmod*BXWrKIukn zBhGRU#eZY9G|?Hg9((Z&8!vX1^$Q@dfQo>rX;+rVm-+mnO`66?Wbf*RGm<7k+$!a$fG9!qSpn>1Ocl*SO7V zNXi|Lo;@*JnbCf%vxylOL-Fa==cV|)cqSwhsAK0POGF;#T7V06i-~>Emg5Oy#+S$3 znK!RI%FD*Z{hz18=~EN(zysZVNrDI%#Kj=ok06n9D zpv-)fxVcM)ad$>CF&gMwsrQ5pcu^yu_dgHsBH(fP&Pygl5Q#UWLl?Zz0KGPNzHjVz z>$uUC$1#VFigUe;^Qic^HzQsHYtTG{fx~RTn5*mlttkdlacG}V2Rb%G+0F1vMUShF zij)0M{mE;F1w;^dIk!03-&=@d;p=Qt{Qf~{GU_<1tJr>@iz|-BJpQo-_EYc#EhZRk zWK=ejQ0mtOkwmu?pZ_J=`$a!$J|VC8sJOd@wjm1^AN}IuZs_kKl7Yq9FPbqA79%o& znmsCRY8jl3=)tjI^n@}R9xA@7#XL+b5uOi$^egg5Kr#_YZyKKL2D4ZCO(Y~hSi;0tcJzB z3FTz95M#`#``PxUWL(|RW8mrv9L4?OPhAWwWC*^20ErwTA{T$ft!qd|nf>BtUCFGq zke>Y+XLbHFR~KKXhGguhc)Pg{<^I;p<9|o9wRnR68hq67Ekm&?B~74h`GR}LjP}f8 zfD$_r^!_MfoEY(ykBUIqMs0!L3~v;T{|jgI7=Uu4XBVQxr7bs`l3|hB4_qldYr~Z` zwBV|nD>k5vc<=~{`qGo&5wOpC4Zgf?sb~S-7rfn;!|(I2YFSu6X4!rOJ=1V*aZpbX zcG*Y8n&ykJk+R`T*810DZxaq@+EzNsH17H68K&p79kavsk0<)Yd0jVwUU*de95^dk z<F-x$cUJ zPxIGsW(#(jYkvSeqPuc(Y60elbbK)M+X^-ZI_{l_@KDMjl90!+`Yo)a+cRaJNvjJp z)$TtKOg<3v+P)Rtkfew6PVO%pVoOSiy2qr%QYtGpv<7KSKv*^78Z)T?==*KwV14lb zumT=|>=@255R z7tn9@$frTA&x6|66)P|rUTaq1`;|A-?-va^;}&1*3Odw?k+8Zs2zNF$)A`Wmzq1CY zZnX5{pt@MWsSSgFAJ5Re`w9g+Y%Upjg1lns6J`Bpq&!B=TY-&;5mVMD*7~xfk%XCY z68pqx_zmjW&OGWR-Pc1BB0v`dYug>@1Y#JOF$&t%2e+Kv@^Rb|qVbPvI!clZn-?jj zMsR)NW?!K#Z_BF#+W)wr!1>2|^F1&(sgA)X?tuqLhJk9}qW)cV}{22*q+5x@8$Dff?tK)#3jPj57P~2o%eo60$ z2We?P;63XsMEDvS*vYV6@&QjCR&D|dyEjM|aPAXx{BJMzzdg7=GWU;nufO+htuOR{ zy&D+*J;7PYK)aZm5ZO>6&6$|!qN~RmOE30jj6VHj%0Qi_qfS((R5wRX=(?#c4rPx( z63rZf?6dfYxceqEPT^skN5pq;GHe96plI+iNfV4%Cy$6`SQOBE<+w*zG>ScY$4&V# zx41!~YXPOKb)6Gs>f>_uuAPL+s1DYK=^~>C$HYxS#O^6blaZz&O+}iHl#X;C(hQ{g zk!B+Off4Y5xV80L&{vA4ran0l_w4tI2`<-q#R z+>ajG(~kB=&|eyiCo9(O#msb^J<(72DXiU|YX7Slk*iZ*!A@f_6U(Xi&&(PRNufKB z#Y_bH?t^w>EcPq|@BiFDo+DxnuH}15Fk)%BN5o3}UgQ~PAMUERJAneFM}Q}TXWgspPoOko#5VH~citMcYgqo1D`JZ28=Lzk z+2Ip|dK(QpL0=ZF(frrlOMMrbh&~kDSO}1V)hZxJjHdd|`rZ$lY@lFodfozU7Eb;P z@Bng9*3;wA-)Wn3#_5m38?$&t`)GmPN)7!jg-4ig^Vo+a<7fBkNZGOf>(y3 z(Ev0pIi$4PZ+!rcWN40o9nrn*7PV;mK#XpQ!EZ#7Obh(hwhY4WPhjms?T}s zX$R66v?~S2bR_zHsFwNF`Z4-zl5SU@I1!Ym3sya6Bn1$wU4%}GmiyL)(1FQrACk$-53bWcHvyl|UgD*ROiWnF}^7FuKnpBwC z=9%SRb;|o3ep%;^GLs$nnZTZScpvT4Mc_o;)4Nq^A@K70O)%1(N|BS<0EcehdR-ugKb;+)Sol^*7B)`oni{KA-P6mR32GPN1 zlwE5cE(DWwCY=fV5A~mik`dioZh7;M=F{H9K33BQ*`dNvj~+db{YTP*_j2m8$AiYf zf2mSlane=>{v$@1(SOwb*)d=0nv0h)vpi2SK*H#OcjyX8!1#0-c9@K&m_PA5nHTLo z@w?*zIsFf06KGciS%{Wb>1EaOntgs$y*_byFWwwNwrQ^1rOA zfp5NtXVNyCuVU8^zfj@3o@Yx4tV&)wx&^I7ACn?-VaYKQl z8KQJZA=PP@;K{7cueasqZ_WQYpGJGR4`pd}ZKsWmyC<&8@mni_ zCjob4`c1A2wQeqm;$61M$&7nivd$CWe%Evzv*B*kw3Lkn413GwXx>aBJoJDnKhuU28cXH@dZH6~mgXjhF}U`)O?|{n|>Y2O@WM%^%>fR}NB; ztDxmH04>#3o2SAq`awBKnJgn8I-E%fyNF%gtRy@2^*P;h zK}w6ru=55D5|d)7*JUyWlZI0Usny~7(IKeOM!9qS^o(KjYvrA`i8mvN)Z3* zVluYTbGC^dfAC!Oua1bl(I_Vm=gt$fTDmu_U>BkX9j&^_TVeh4PTq&MT(h+jo*Nr6|H#PlfAOq|ZO%lx}1mfr6Pj+w=kHAG7CM%yi-mElOAvvaKVTuigA+Bz%#DQinU;b*dc z)bxk;&&^6VeO}(9fF3}2-H&PcdVhFeTusWI9MG@Md%b>7ULkj@VG$qF6VzS60joxy z$7Q*yIcBP|B1m9+lrys+jk;N4bW;D}dn#}r*bWu$*B8t zx-Bu#=P?y)fnw9;=a=`v|38IWZwY#vuEk34SBiZcqJ#!zxD(bOc5^+c?6EX$o{+=5 zO>JjR-y#Ni#klO#w^%*eh902pKhkz%GyT%4U23m6XgKJ-`VjU1ju(FDjjW0l%DTSx z2FZh}A7`J?z0q7o=rg<8hUY}W?<~4;ktCyNx!Nzdvx|f9ys9>4%_bmE#ID_+b^^Mb7U$>c4B8Q*M|?#zLK^fe#yXa^vfgY6B&-Lg(^tvc;JWN_ZvtH zkdEOurDsEMJ`U$YaU7hB88}e@CiI{=+EK$6eP}D;A9Clg>ZSuJmU?l&hFSdMKz%|y z7cg>|^`TQaY~8a0jj$87Y^vyCx<^Hb3S?V@6_8t!Ns2;_L7jES-&CX;BUI&U*iEj8rqVav#Aa0^^Q>j%-bzjE}{7alcQ= zscOcs&)gyk+pRAZ1-G_FQ))23nLL28#q4ZVf{K`$$t;q5+w-Bh$@7{Owc3yd>|HVA zB@1js*zxoBY1pib6xcx*29E&*mD`wX|#whwahpSg`dJ>)@aUuCj5J$i87ZO6iW zVsk4q#WeOe&(F|0##xCWoz*6+%-APhZJiFUbjmRsXnQ7ng7y$SpHJl&l4+PQ8sqbZ zCh%_Q_@LZDc;7pDUU*<_3NBO1y_;ljhCamABHoh2sz4vT->QPYRVX-)(1BT3-}+C{ z*wc&}ZDQtHy;yBFDdITH*!Wm0@xD%^lPd?xKanaUahceU<8M}5TFABb=%ExHUVWS* zqw6le*B%Lc_(nfkeAuPi9ajHYsAnHM@?~rYB1(YQp152f8A@PkU_@jvIFdviEJW34 z2gQr`7f$$$f#Ye4NB>@X)Y{t}|Fiaw_vnK09zO;>ea|!gGy0z1mj5sBLD^3uT~p-- zp|=9OPZ@9lPD}G;!9vw%kTaaJr~`ef&ehz_BV&wm^u5A>SSfr=gTf$7=oTM9Zv8-B zO>XeLyz+s(OoD=!85RELWNf!M8u@Pr1M8p`d5`7h;c6KomnguesJLQyz!71)qg+ZMu&#@RmR9mU)_QL zptWqO!n=|2NEh|HK}V zo~jPu=kwnCz0V&$m9FL1t$WWs_uRAJ0%j|NbO-;T0$Xms_dcm+#o-mZktM(gNpq`} zcH1ZcCpqfVOlS$o>n$JFx3qTcsTDF$Jnr2QT+(sf9HRq1pRhk|b!psh&DT+RA9{v; zI&!C+L-y0pjkzx5aeo%k=5|PzD9OwQkOS!GeZEu`W&Y*^OZF8;67vY{) zmI-$b%;x5UKYCbM3Jw}OmAiob#b=am*BRwQ*Tc$^{D+m>(AFLo*=t7oGCPN1J`9V^ zhwQKE?uYWz9a@X)Ix!3TOmkQ-hg2=P&z6j-^o`|j&bYondk$Ds{{G@v7!4N3;GCBO zU(gc7tY!1;Zv1+Y;hxs_XWPC|EE_DM7yYXjl`^l=Q{h$iRqC427G}(4mv4e>In;Lx zH(&j4V*g;baO6jIPkpwiKbYaOAP%kDHN8D)XKo>|@l%5e@mnq&o0BajwJuS(x>w!* zbz27F;y+eCv|*oF*9OqLj~R#DLM3ct$s2u!_yxT+@uMIWzeZ52SeTJF84$9=M;Wl)xd04f{2GDb?K|{o=b-a@>FFqE6$*@Xc4~jp|v6d z5N2Fo0{_lHQOXMLvv``{=q7Q~` z%5AGg__!pIZ;VRFSVTt+GWe7 z?d>+?NlEFb=JUf2#M#qDtHLe#b$eMJ*E2WI zFnE!X}PBJJIC01rPa$aDzH}{LtHP`pdxFh4*k-p{Tl5f zI(o>-vuA&f5GPA2#0kR2pm8oe$}oX|eHdK>MbC#0`(b#hZO3Z5vre2#X;)a)fm z;+VOc+Q!V$i(}My$2D5KW9EK2@^6ZF94ntRk(>13m z$usmVixrE-fcU`0iaEpBG*w&-+1b=wg5Qi8`{nch&X{ttc!Q_ z<0T37m0R~>zjJPK1MXkd>hG7I{Fj~}c7I}B<;wE@NbzUk&EXeGx zLd1edHs)}h%y3q?M~ix?$*m9SQn-S|RU1kaNCrdV;FjC0G13|9+e`?^jUmPZ3xd~Y-#y`XifI_g*lNVQk4 zOY6vA=WoA%U2i+f%CG*_>TL0Mt3&ePhyd@@Y(V10NY{xCC$hz7N=|i65ryiIyf@o3uQRj|EPxPTeT21xe>EhT@)=x5l5L05r#oX~9yo4EF#4(uy|_f9|u zc<-va(sJmnqHOK0DfHIGb0*9dQ;cd&`?e6H_qm^XuI-Wap^ax7rfc&A(hkP!7I%x= zB#nkIHt)??eOuL@D$bQr&{p!pxnbB-joGcDNyX(rPEF|BeLPG)n{rXs*{brg93)e1WJhBvE&+9Jg z(bDRX)oHj&r7O^r1k9XU+*`rl8NrQ$Zh)RJZvrxlx0n2QF130g;1mZBn}te7?bFcD zFo$kc=_;j@o4g+yKm$fZ+dFo@eE&D(AFULHSfgKl^4aT~NY zqK;(HwnLz88P&@Wac9u##=FP~R)B1#!1g-O^8b4usIlrwO(HS38W*) zQmggynNzH5@fe=XnF^ce$tZlaVco3SP-X5MdXhh)|Jukh5Ub5Wzc-UZuDtM_ZvF1k zs)niz&=UU07{Hy%TrH6t-mCD?CeGwE8g@3i+HKrVYC_y@Cb^^{|eQvHHo>%)h}6zHp2%tv}SEKT_X$VLR>$F zRkwCkZPnqbb*t7@ovuRN*82t;xGnhIdP&DN;V43XL-mZ^aFRcaJnd-nkaH{U5S6H{OqdLO?k0F9)Z5X~3klO95GpiI(yi}}j zCfxr3eqGqn1!r#uImeO8(p8UC)?&sJj>8wjQM%f!p1*>pgXiry*R3)GPvughil@nh zr?!p*vw0oSoS}9^4+|fV#ePb zC>oR6#cZ7Iky)Siu-xap2QF%JlO)p3ZN{UNQ#$pTji3^Hl{6gb-OQ&4h0RtwV2Cdgx8Tke zJUOa3VGpvfC^8rBL_0U)*sIt80l|eVy9s!kVeXkbVTWBNaC(YoW}Cs^)v-f7|+1KqG(>wSrlQrPX;z6HIuygLFOc>dW$$YB1ZxNGU2D;j(i(GuKS z3OF4OEW#OOw|+4|Hs=I<34Wcyg*cDHm#}wy@N>L{ys?=7=rQzv%@MQ>y|Z__2Mj#= zVXHyUZjc6BphKqW55j1txqHBnWm7q)sQkN#ZWr-0Lwk|~^{|vvHeN1)Vks9yIuI( z7mu-N19q8j7P(vppq6nB)L!ZsY_Z+3e1~yz$wj&*7KFX<1IMff_qnIn&zL; zyut-KRN=<1cMD-rb{YEK;@bWCZbRRPd^7NYa!L%tEltGA$LLD5Sxo0?Ma5&dE7y=uZJeZcjfzV* z1$&T_$#tvwGgI&^c@pX;|8bKYIq4qWRJy6G*HH44=;LC$s52YU)~9}N{#+F8HL z2>ow=q4ATi*{tW_i$+}eec#um=!+7I-o`!M_z{TX;eAFvJ_$R&ea{^6u!BRF=YUO* zeut9xI_?kEmyRx_H|nnOMSE5*`wlfu#!-N0j=Ijjr}8W?iR|9whn^x%hV7yQ9)~Y1 zUt%oln&o4&URVzMHe0k}C`v49Z$t(h4jFLZFXpg`Ez4;)mn6wdQQPlrQ7IT>cMiOz zt}lCI7;FVK?T8Rf?a(A6i>x&ey%ypw?rK z)njIZGr=a3$2{wL^I08B0H-#VUuvXvoI8u$gA!(*Fw}<#MPyxK$i`?zCdU18QQybt zr?oV_^vu_cv#K)KE?|D5*a+<36QmhD%zI}wCzRX9)CA>Geq-M(W4(AE@bx_%8 zpRKef8LrYQg7U-ucOjp#Ozf?~0OhiH-)G@RYTx}jY1U=qyI)&o>5&bfsDwFi$1(hS z-+jDyH9zFzk&?-2?uV!!(D%PzhN_yY0)Gz&GYbUN&%M5gnUU*|IVjtHNr-kUd zg;Ri?HIYlExU*NW*y4B_Z_yi+@$_E5yW^lqe-?XhvQ^;c`XbQut5@x~`YMuZGN1hf z<;ljxDiTV0%#kF=C1g%f@6rsKuPZI-weWQRpwV=8RW&_{FD>o8u$u1G;9i@0kHv^bvczd^_4UjJ!f9?IXp z05;8ZFUrlb7jeA?-6CL4cF%q4lW4xamuH4v&cYlhTL!E$=mCGrEE+vP`I>i<=$$%@ z@(g{Eq1R%dH`q<1OUrtb^nk4T2K1FWEoWT0jT3eo9cKgZT{>2x7saZLRYq^4;$%h8 z(Lby>ttrxKMBus|@D1}-8f_CzUW2dFV4INIbujZ+nT9G(I^b}?f(VcA$XF>LkBB0_ z5#&cBvK+O6?>`8CpL^{2cAaz(tBlJ&*?td7zffhb0u_lIgTKmF$Y!vxB;jk2t?QuQ zGl06Mphn6XNSt#JnSyO%VGQdNMQZg3aVIp*QpDJ5+NBrYsxnl~uIg6OJRB%%9WwmV zTRT;m#8*!;K_a*nqE$O#Z4St1B15s`Fx4LK+aBCdyHuC>v9-M1p1;IsW83(kVQAu< zBvsFIuJ&13{3d>9X4M(kddXIL249KFKaWrpbr8|>B==;mzk5WHwgkv00ol5EigAI8b(_4+7r z_S0ZTrW{4!1944H%+jqLy%%RAGZxF0dWw;ajPwA$VnpzF9Tv)PKO32#jN7$)8@oUw zX4fMRxYILS94(rkp=h%tFLs*KwUk&eiY9gd{*)%4iT`NSl9Gx(ogOQolSyTwZfZ(S zJXTB2Cpa>*;)ab*k4wn0j*S}?7dIlsIYwf6mabZ-9(k_mY=v`{GgW%TIYfHYX_X#x zCP|MwEz*=QxuU+}dN}qlkKcR#y6S*~9}d ztaWDo$eP7@sa<8_40ty&=e=tdPfYC+#h)V&C3B7wbJr}+P3xL1TBH={mr_(rcvddy zs{rnN6{QkcB)_p|jXZXy*v&?K- zf0_LS_&;px()9e$>E4(O$-xt)n1jTdh6vv-d8q6b*iFXYI|SZjX85DLhPWAH)r8**C{o(=(QG~GG$55oQv;JJZUOt7bt z{g)wHpb#2(i&)%FvnwDMgzfHGRV9@+c$3+d06{6U4 zA{#S)u=J-_N{rQ%LXXN^>8UmwiiZr#{ZQ(t2up%}V4a#MqDyJy}SF zz6HDHz;fb%J&^Pfln*QOH1)**tqP54BXGAoR9$_aZ-_3w2D+}QHaFtu`ie~Zs(yvm z7NNE6@bE6TC1+v$L#8St;;<~Bb??G=Q=hMLddmayIQ0o~SIe)_eNJ3X{ZmeI4v$jf zA{)*y^x*DrVLQop5jh?dl791|FV^U!`(gF6^!ye%?EGFm_FJS_1&XvZic(E+#)akd zm4N(x@OcL`eN}H)&aR5en~?2`6AHk?m;-gyIpTrkHemEYe>O0hBo^Y1Wp5fJk2+|VMgmHS_}b%GA1JS!2Bi(iFA9UGlWnDauZdR1 zBdB$$fqklB~w_7}4T#EA*h>kn%s=l`=wPNDD z)yZpq(Nx^jls;xz6aHo z6v7BQokksQ2ctwriO7RCNjq_HNvLUvB9u%pGtOHAS>tj5{<5?W2(IIO}tIITNH?NDqqHNV>4>#=#M(I!#v;*OIqSdph`}@bqW>oDp7#-9AKwDA)sUr)V07oc7n{)b)@ z4e?;1ei z7b+A8a@RuP@2_491$sINg_ExW3I;$SbLT|?P{;xlasY))=VuqQou6Kmu`Uxu%m7vS z2c(k;?x$v--6@L(<>-8NaA6iGd%nStjXwk|tSt_(@~Dm}NPW zyonQB-j{!ftedp+5Re_tm|IEN2XOaK5!;8JJKq*^1V{?o>PeEVId|Ny$r^xrXXI5{6wW#;4p}+2E z6Q;rQkSs#!LAJvsF2FVI-!wU35H~?`YZGQj*n`w#Ktxz-#SwUPBSOSO9P5u>x1_BJ zy~-R%GBSMXu)%z?-l`9bBG+b*?pXJM3|=h$*@;{5h9+yI_%| zQbZ@kuImK7^xTQ(5FPveh>>D4Q(aP9d?D<;HR@t?}`*bk74wIM1`Q)p$P zTmY|93mC0VF0^17UAdlvX9W3^P80tz65|rV?8|%H`#VHW8~dFcY46K|9`VU*u4mx- zJy@w!{6aQNk{O1h_D+8xwDSVamZQ(~`>>h=b8>7I%Tl>yaQEiMSz5M?(U2$#I=CGD zr<76qPT?+L94r9fFrsaT??fO`ipX~Vc+rD$ z#kg}Cya`c5npy5plECaXj32NKFmt_HhxJ$gv|%r-GvHg&^5JVI4)=bnOyOqL{H#64 zU7q=|vLfFQf;dcVwGn%2=cnoA6XOF>CVW$|shk;Z2_a$WdAwLk;9OO<5P^`^X&o> zk|#B34SW&e0rXh!t$Q2AF<3?7e2-vv4Z>u;zBk$IGnrDm{@BkF4vVvAnY<*;){pY` zv-o9woDMV8k&T@f^@u)feQNkk4r4)*h$VYjYH-#ADJHX1=I-I@2tlMBgXdf@^mbMBzCG9FtXpy!FO|dJB@PxEocwD{OAv_|@ zo;AvwI5Ez9@`v^7ho3)aO7$MKBG==#I3Zq2o|vfKkH>wp*9^|`sMWe{nz%wr$%2o( zRGYO&*wBt$k#)DuvUofCE!Z)cjkk31LaBg=Ae@y7ypSy2fvCh=;SYYb#NEPu0x$$6 z?i217tS!Zu=el$Be7aXBbzpDg0xy#q#1&aj3lpW4S31OtX)E;^jKD_ zV3#Or19lM=%Wf96*oLTV?Fh@?M6cr7#)yV#WL~+TG2Z(8J%@0EG`W3!-r%)Om?ZUe zT!(uzWB2Z{j>EXU)R8Nl?#PiwwvWx@@NVj7FLl^)$0ivjU5~h;XRVw)BL6<*lE#UZ zLL&Y?2s|7o{$4QQuM<>uocNHyN$Z7iSZ&z$B2W$FiiV5_UIB3SMeG=>B6X}DgZIKz z>Ln`zB_KQ3XTdq((x_Z-XGzxM4sp;ix=63U}M5AQ-RjOMc)d=u82?eJ6qcbg=2`ZKKAp!I*G81>1pS~MH%;DWc4 zH&-j8YyxT>^)l$A`RTFfn~|lXH}%LkkT0&p*@HME+30D7?nLC>ig~+D+>3J4udK~m zRZR}{OMk2$Hb55tF#6*Xt*wc~hwfu7)W3-QGynFhy@M4ky^eY|#HZt6{no)IXF~6c zuG;@__e1NEErx7rcykJ}6ARqd$s*r` z^$S>#6QN85zLOi<_#*~Tb+?KE+W6mxFZM?VEh~EwQG@a4xSV*5f1Hb24x2HrVi;DS z&Q3lDYp~ZSSnVc^v&9;a{~92#yli;a6=;|UzNw>Y^~urdxEf)PT7hr0Kns$C-;>x! zjK&fExxiYI#$TdwT);9nwh>p=jBHkUC|3-ro=d>41m{6cAAQ@tlO+kME|VP`vC38L2$4M|zNcda!!B#{+^jj>9jt}U zKSUX5s6}ee7DVKkUFz9WzLQx0j_}8@=Gh3JuzyG^*XV-OqhZr<ZOTefJm)6;DAX&AfZ5>{AaSYcJM;!$7) z(OI9mqLXZ%3W)p*`SmH2z?aBcHlD`$x&-hc#5+D2Gzx|G>7W>N6^xi1dV#gjP9NZ> zobV_Mm4M468j^-SPgijSJ`R4Ds{e@~>+Dn!x|3P&Au}X>p$lVGtj)91uzcz@l3Y@W z*5ALiWHiZbI#7B$XWtx?-SQe$Jpd~nbyLYLF+QN9-<0fzv=Zmb(r4+XPAx43osU;% z%G6@$7;@1XW+Y#ho+zE+-st#N?3IB#??mqc)vnapa<8rjCFl2BZxXJTj>V|^G+f_^ zHMQUhwcc-?0Z#6(9TRYGkXkRd77H2D?hc1EDn_ZTpEY-6NT>P@$&*z&%`l%1`tu~a zcn4^+UG#u9+r^on&Gpbhv*too@{7pT$Pr->zr0uo_y{4p*npNUL|b1)PPbz8#mp~4 zpS1Qrr7T2QDmgOr9(Y*DypIk&sm{!;deCS1R)bp`3hz6H^ULbF9<-Zt(z9}vlk?5q z)TTd1oS5-Af3#WTfX}RjawjlHM7~2InRKqmJ3#l$$Ye)*dV-@9#2vs{vLKLW0O1iY zfZ{QVa3ueN?RZMGX?d8QPeTsL87}hF0rv-*O?AM64?SgAJ|46P(?LhsKGFw}9N8b( zs|+EG@6N$`KU0U@rhsF#BG7Is(mn)q;dd37IhWEG>~s&*t}h!>^RAKx7;Ei& z)=yBiAgV7}?ZK>o1yN4P4oGkK20e?)(*slHkTkbuNu!eOYCwBfuBA&a3_~WDI_M3H z(Uu9}qaAlwm)rVl$D`-PW=`f2AlU|zuit3r05fFp2$AU#mstDpw z2o}2CgX_#oud%KVy&5cthsK(Gl=^^Ol$*%kD=dEsk3AcFk&MibOf|QLEQjG2fh!a6 ze{smS0#RfKD1b1J)l_@Qj(4ne(b{|zlq8Gxl0ly~va`=D$OYhRY zEn3aX!S~VEDa+JnL4t+W_K#5?>HS$|M4qE^m&7UQ1=9SR?6iInRoH@D6uJ2N2cQ=8 z-CyE6^xd2Bi|o>Nbu3Dwas|f1g0c7pIEk^CZ4etp^PaKd2OVPr5BvX-d}hD{eNGW{ zJCELSX239?c!>mWTKn9Nu@m_oqcpyKT*v%g&yW)6atQj-g2#=s&cXs|T;K8Qj&|q; z9N-=!a&Ev3j<5pP1*998jr@omEZ2ArzJ|D`-ARAdT{9KyBJ>L(WHCn;MFTV;B=umX z;|}S16#4sTvSThZwHvCqDzR#uYKNe#c?8D-dsx;ZcUZQ%4*2C4u!GAq_4_YGXvL*` z{t@{Z==kx)M@fq{Rvd~wtB1KaiBALXHU-#r!T@;1V1)_5j-#LOau;IaY_Qy2zGcj4 z*e!?`e|rD;Op=Y@iRT0sW_ z2@{5XK548$$bwCX?u^boACZZ85omc46{6CD`++U=-Hqzo;0n!2g2AqL zJgls#r#e0hlhy@S0#U_t{&y;wl=zbN&ftEG$O-#)jkRg7sVk0=zFO*xJ>T0bQ}^>at$H`RI}Sc{fAX+13EBl0(4ZIvZm zZ$xg2&?;-8mCA!sTalSHLNx#G@}(37BW}Z(}jiw&VV4 z4z-utQfu^mr3OWw6baN~H=D*AtH`tK@hWqb5i6|%&P%t8-ue%}8S5%>(~f8y)^|D^ z6OBh)Go7U)7l3w_ih1?`vgAjQRf!kwNB;YW+!&@^n-knRVRubLek}a6xh801A1I5+ z8?bs)iFdGfv&r`t*mF5t55=7)!oRK#gNoV#yXX|+obZb*TU6Q&KY)0wO*i8$ZMGc- zCa4mE;={s8=kw@VO-T`q*mt8Jydy`I1E^L=d{?v%*{D6mhI%~UnvJxo6^OIZ=Npvd zz@yMv=R?aDf()Jy`W%+WDyUhN!TFqIFU5AVCac|u2(~Cq9u-O;-r6`Kc7YA$8 z@>FkWGalE&%4a@WC_)Dnr)w6_XXXgY|B1F}=WJY9{vl8fUD%)uGfmlruYumjeWC1Z zqj3^Q8^wZUY&*s(9y*@J_ygp#9Y)rzy-JRiZO1-3kaB4KA$f*Yhu?(K=Gj1PZdG)) z>Ed6NDWLT=pos^tnuX*U;RHxISUZ}C>m>@eQNdM}#vvuD)|iO=q(5O7IGa}1M4Sj& z<&oi!bZ*G6`r|t~H6H-!Ft)UjhAk$u9czZhLX+3Ra)Doy*Ek2u49j_bwvD_`cB1VO z`Ryoa6eymD`j^7kHo`=b<7l?LqCPbrn+wjEU;yojl1`CJ2?8L08)BU~NBjW}k|D`< zA=Cy)*s!yK0Bkd9eHx_grUewjX+!D8*Q$944vMc!2O*dyaSFsYj&Q zvwRSe7onf&l}2D7ab;%pdwG5x_^Ij8iDiqqknve^u6p0*j|T_i5gU5-z?F1A+d($q zcl#J(MX>9tZVz;Q+*Y%%+7G+n4rnsB((~!)!PgSDp#;OdMonsyAjzs0)g3hY15s@j z83fXdL}YKESVBB*a56F+YuN)cz}bc52ZBaihveU0`&}K$BYJfd@Lih$@(V$lzI#;r zuG+E!j0*Hu>UZJupnmt2s99|VzTT#4GNKH+<0Q2eVfg^zO*iC$)*(kI+61H1&037D zL^qM!7cyoX#>OO-qX&9rbhbxaFP9zv;bLqrLX{VMOr7T>`ELRgH`ly4_qqOc+yiAZ zbMA)5D+Lh+4(=}YfB9boi&r`Ojt#K+tb#3OOW19!^8fUvR{MYdK6XjUnkZgCPOc>U zevaQ1{QeEUX8fMTZybKT_>IT!pCm4mjnielr~VqU{;2-yv)+(a!6Lb8E{t?7lsROg z__RF#J9x{<-vvixosbBdxJ=^#ZktBQLh>fWNv7LKS_g(1ZUtwGRX02zF-;Zm8fD+D z;^vKEqU?|3*sCn0bvJGT`1KHWI~*&_1BRK2_rTkretxzcUl<3h-A>dJk+k#;*d=Zy zeU_2IPB4Yy^4r*8)co{j|K@;tG3#*Lw&J23Th4wb8(T4_lo7%QNa)hXFt8=_nh2o(QK@ra^PpFWbqpk{U;`;9=AD@LB zv>L|#$6Gpf`74gCVmc(^h(^DU$-2!dy&+1ox#r2adzET-DE9$mW1bo3>`6ZVpSjHU zj>m9*eeUR<7juhz=K4sa-c=P36<3Y z1|#CUDv2T{9itW$Vce(I2_l}Dw&09|mlmy`5sW3-!l;ZDtIt#$^rkz2%|>pAMlpwj zx)-~Ue_tTGNCB{DM&MqlxsHPjWz?a zao9N|Nc|pph+0UkYDAqLVdCc54lSDncKZV5pl?S&NvJgezoQ0Y)iO_gcaRGY$t|adj_@|7!Y2+k z$JqKGAR1B%j)Q2i))tkn?jX#ex(P~)#9smr?8gRiUKatO4}K@{?|zpdtl>=bB4p364(JfA(rYnIMr8+-nk zZR&X|djv+@1RD$>4jW9II!9zhug;2Xib18u`c{n({}cFdk{XS$Zi4@YjT>1@#3X3( zLh^NfZUTSQ0-25cA(KqP`SZ+P1gi3>$X>Fh+2N3q;7k5lE!EF%l0a}Tzi$>Hq1@V)I@8n0kT4R zecJgw$cofeA9wztN#>&yds=bzQvL5IQ5NRp3s2)Jr{Ndpp22Tc!#>=-sXi#Zj;k>Z zmh-3aySJV@zkgD)^cv3h)OVu9&+30Bb>r%ir~7hZ!y7pJm*-8~&#(VV8h4BVa%_ht zaYW=93Q=>Sm}#JxyDHE^E8Bq#0dX|TxJ<0w+q89fjeoDQ+_qP#a;X+1NGC*P<^i_v z1GXfE5IsHPpLc<1umx*IqdBp^Fg~$=r^R}dq#wGEbYpQz}n_YU~B@dB#;K; z2$RVRdO^g9)jlZCgZC2s&IYGD4d0$>1zqM7`)zTEp2l38W&{1luGmBki90ch#QFU- zO7p_BTl>mXKz$lRTM?~Y4Ej;hO1y<-rrGhvpVCzN>XiR_E5^ zu)>u9GR2JGf--HW!9W>ZAcJByy(AcSPY30)=|gfFu1|pTy_wq7$ZZeF$q|B#4c@F< zE_t|+Y(fd5Cw*Z-Ogmuo#et`-vKn_2eOun0uC`0Rha#P~;QkieV=ZYahxL?N`%K>0 z3jWVO99bUmG=(rMN1R8`DP9{=LRdcLPv4oQ%Coc*+od#66Ql3mh%R>a6mX*o{aY^K z*M*iN(tf!Wbz3mP$Y@aI0*44(S#BMyN8<*!gkA=hmPnazEy&b2E*WP@7Q)dXguB4o z3h-__lL&Kn<4EjZ5>L>48pmFx$phSNBMhVUcoA@HAw~4-fSU06r9Kn2F74i{EVI%W7#j&I4Li5s9x?`SS}n`0OGLtR z(jMHQ)DQHtOv4s-hP>EKhD#Ajj-X9eYl zBI6Dc{WQMEL#s11;yeTy7s=^~Cl1RAk>T@_KtquW-$vQ-;{*$=x0JO>=@sF=e29B|{masy z!O#8$=OOTyi?fbO^Ro{BgrCihJDy8aZ;+SGIH-G%#)Ej-Be|8}Rz2Wl>1*dazr@#4 z)vuieFZ(Bzm;E4jeh+=?L(kkR-+CM0y8Fgb9K|?h#(3GJV=+!v%^E;?5{Q$fZ_|iP ztpm20h~L#X*&@th;$@MiK0L_Fs^u8l0o(>Bt8sflxea(vyzDXJWi6twNH-tRav}Mn z(C;J>9IbfcFP0MRd@4+%M-o#h@wPT?YzaqUYg1ce#MjcoI>N z!o`6e*F|+SBbw7Z*H;u&>yL4{Mz5AXjB3t`n!x)MgSVIlX@Ks`h#u@e&6#r8 zr-&-;Z{W zc_T4+6W(a!;$vTFkn1$*80ACBwj*C$_j>woA?FihN_nh670XMD5uG$x)#WCWF7NEQ$Dx9P^_ z2FmoGT2;*(_TcNYR4l6iMTuMYH{TB3gCTZS~YPP#$$Xo z%ER(OV&_arl)sor+}RR4p?!|``rvgdL)JoojupHi>K9q9Lb ziyIm)oPwtm^R2Hx)i2=AyoR_hPxU{POfqEAK&R&~&|^N49FOuFlZSkEs((W=8<>l- z4ao_g{fK8z;@!^r?#uV#-cxu#x8bP^r)!?;Z=eyn>}()?R5_o_?EFwRl+DNA1U3$T zov;sa=B1f4zog$=GN*s}$aF()h8kZoQI{4s47;YZeZ@JJDM>aPc7{3N`YuW&*`uexYogqQ}!l=XV$JcgiwQcn-9JHSzE_`v&(sXO>|<2vB?IJf@2Oz@54? zKU}mN(_p1av5i6bi!fH5M$+gf9U#o4$jmB8+EZbHxS4nfP?{2zHf;>NAzghtC_fLc z%A^CVWl#eilxNX<-SnP~ypurBY6Ho;k|4jHl>k+VKMW2~&HF-ggYb`j3CpR4^!12r ziF|ZnP=2SUyo%d&Mz}p#4qkkLuAh_}oM}{&X4+uM2%;1ZUHHF!9k$HSRw`?a+l@AW z?+~o!R@Pijt*;{sg8<6{o8L6^%hLk_a*h!8DJwJ3l+gt<0_|iC%3Ye zBuG1&g}|)jsjVB-s0elXW1tHT5KVBfQ}(I61Y?v8MXtx2bIxyZKv9MP1~*Z9=r_va7oi`p#FpYqxVy7HgU8t z_Zm176x9q$bqpFHt*%IbR!wRzC*Z3UNe4Lco+F7SR#$4Qt_;EX|ETNJpVrkqSQqdz zR@c7)>#4R;fHiTeBoCAYlXn7JF~hMk$!k_ zgolj|dMS*ahW`VQgmb|0k5^@R@*D!i1bp}wvT{(&B#p#yRTmYI0#5H%IdXc_UeE<6j|?lj0rztt){s4^MAm;88{l+U~NCheGRWF)#A=w zbH$IRcx}#G+|EfH_E#iWQ5?}i($lDey5qX{=xp@Pv|R?w4c3&8$iXSW z4XXC=zdWR2zAf$mb`55YulDPbk>APA?C_$-noe>P{O?toLtJ7ZxWwCC>P%`Q+M~^T z{t8XAW3;Vd|QYoFTi;&v?uwf?H^&iMD-B07W}52qmFTQXkVHc z?Bp61d_}dB1Mg^M&;jrAdB|PR(t-9M0}}d4bmB8eUKA~OI-EdQ*Am~VQKDgCyY%1H z`h+ri7x1~8G@(RAXcrf<#yo;vQawAugZNAJKmv@a_`BfRQQst{AKR;}v;wCvJ6DkI zh{ZJ$U*8O?=&##Gv=C*}9i=&_(YUl-*gK_-H5CI7mIv!qJowfVe{{rg>>Ul%(dBA5 zfM^Zi079fsWc&k{gxlrd^0U5gB56z$@cM|l(g=E z91cwd&X|DBrq&R6f1(=Xi5ZgX0-vJ<#ax+oqmA7}T}Ts*>sb$cvyiN~!+HYpUqU+A(g^EF|1}MDri2J%h`t~XEGP^0=KWYrgn4Ggyld2Pi~-hR z@)w8h18eb0*tH3EA-P=jDQ9+qUOu36FX-3GZp(f&;CbEbIW^XkPq@9c zPn5)cI;sPn<@sE$-b>jytVMvx>sI8i(2ED;L*F{M?j>6MlU{tHtsMK`CiyOfJfgM3 zCjKaIhGZI$ZNPSeFDI-Abg!GNiEiV>;XNjJei|m`dmR#g zoZ`NX4&rf271Au()Y&)>^%V*pdr*EOtOuV<9^@{<5%|zh852fr>XkCb!$!3py;{#$ zz>jL8GFg#Ap^@akaY1n{v~>o&DwID2y z>P$LrRk68Hh3WfhE~)W=DP@h)upc}$FocJ`hVY!jc?dS|8L$RW{|S4K`7KzJI{jr< ztuG<@1<*7L@Wl|CuJU8FPeOk*9=alf@4H|Eq>T91e_t>kkH6;IPh9iuM=+D<>+oGX z9+J;M6Qq6HdMqS&B6BUx3?6N~Uu`4HA}dq~yRl9KjdofwyLR+pO<#^yB%&2>BCdnp zn2uH)izcb9I1)U3!2%vN4cyy!l}8Q0s=%^NS_Dxi@G9p6;jE_|n)2-Gn~I<2o0k zbzOM$1%Ge4ihz8O+64Z(#0st_0WF99Pix=7So?0h(!M_M5&7K~_|y>Phu*zO!zF*1eCBQ? z-F`h_yDcdD!ttu-4Pn}Ug>r%2)RUm>4W(dgt*vPn$RnRaWbjp7Tl!ie^3-wTXodpH z4n!kt56J%vgWAG_Pym$;$Q$xi(#cx_&#J$pu(LMlJcr`>`~b~mgD(v;_rM!G?%oQGMi4Rm z1;|sz?8HM*@0R$7!_Sw_{)ifxbi5DT(kP+tijO-*%8-})pw^Kv7+$wZt3+c< z{ia!_QLAC-H;pIFw7Vi)CLjWj8*TkOpvt}4c+y>N8}WGo>?(<|v|)@~h;=7VK%QoN z5SAAW>a!#b!i3RRAw108W^6jnQwDVcrM9(49n@a0geAMe3MxpD&5yfg7sEaY0ai4_rkKvMs)#Xg&?E)K7BL7-AR9D(o}YXzY7O z*Am0ioNDa=9i}F|BnM4omD&fjObis@AcBlV~qe zg4sU6jIS37LYr~8-M?I8#NI;YV+6;TEN)x62HYjDKMra|{(Lsd%ELhO$WMywWg$6L zg$1p0R15L`=>!oMl_MBa=JGVHYEPKH6V1h}rU~iPf-6#^ZadNcVFV zS<6j*Z|hhVjRSE>J2x#`gWBN9f*hG@o@Z4<2W-^%shh9pf{0@hx{-x^AJz_|Uw$Am zS0oBco+WO0;5^0DfUat zfz7&KX}&b zy(=X8y&JiGzEHmR{5k`F8@Wsc`<73XmH@KmcJ8`tiJQP3Sn$24D$ct{zW&?m=5U86 zV^{mMv_0~kzIbVmocC@19PZF>($|*NjQ#FOQH zT5I;mzHchqhheYLVRN~|%LGl(pq^lun7G58$}~4aGr$oCAi-hyI+C(J+b@cRK7|pUqt0`PUQ=! zeC)o9%E#_!Q~Bjuc^j3-Ih9YN^0E6?Dj&OVrt)`cJFGF}s&kR5d=)RAuhS z7MdPTsVUFky$SP%E{~InJ2J~hVJGXYR$UJ7<<)(|{;Dh)QtY#_HhMgws zMz9kYmk%+nWmt>Lakw!)^YL4OV=;~;IBvsHiQ_IDZX7Fc)ZzFwjx{(Q#Nom5Fpf<) zp1{$FV=IoGIQHP6{E@ULql}39lpBZK^!u`h%7|mTPARQ@u7v2W!8b{H2NH9@r zZ>>%fj&EM!SO&_(iyeabWB{IGgOV=sc4{_i#3}PfjL;)*0K&`e}8&^b;D@Rp_= zJ8G<0K>iyfpkzc!Z;Rd)D~V@Q(6)PlWHUCXJL%&|>Z>j!cUp3nF4LZBAYF zQiXG&g!MDG4$*qe%II!OAID=?PeghLWm~}DFx#pG=;#nh20dfYXrHRqyhZ(bK#qV* zr0)gb?@hJ84?NXk!=$ZR+&;rU;_W7U%WvM;_RP0;Y}VqaHLtwMu&x{9{KyeZHZAha zhJ3HCCBsxb56kq+^Me|s$rpQpkB+8EIR#0Fqi6d__OA#o0(_ImD`^#7FF}?KoG+yFO`&9gw8+RY z8`0ZMu$58^e~cufwt##-25UP1B(%JGpmq?_o^O*j6Qrs1@BPklldwc#HoE$)KL-(& z^hRGmhp1f2a>bgeur^v^8m*(yHfr(p(8>5g*}CtnUIIyGREjUyrr4kGJHA zy1w}sr5mxf#^e1$c&}<>(HNp}pf)I#7>#fE&7j|ifx;A2|2@>AL-GR5U(Chh*k_i; z$0$Bgvl$ln1HVWXf0g%pc$jC`r=GXxG2eIf@#i!0e%7NqKQgcTa%Y1>8k<+->u4zb zvIiJ8Rx_ zFG9)RWB(x-hoJimV7l%?*C)#P2i#` z_y6(doY{u~1|&msnSl{uP+43nZ^D2hiwkOX(Ym)mtvds#*osRwXqs6Tpeak5W!+1f z3btI=#M08%nX=N2-*g{_fpSn=mq$J&$`^{wo8SR)l-iaFD!DYoNwo6xn@bxw|sLHzPTxaa<|Ds zxvLg8boO@{$TmawCuYXdvg3h-O!K0%Lp!>_St)=^=Vm=+MA!RShY5z=Ci_NAtxm3zs|d zk>hC#C%a;uCA~Rbc(azi6FM+2cF34@)#5$K?FX36wD0)EQusULbb-2}u|o8nA6zqN z0FxYy@5|%j&Oq*DtF|J{bl@utWbmMZ++yAt4ceUJAfezl5;`KyZ!fl!mM!Ks+18VE z2e)3N8vd)lqj0HnE^@nU;iIkyXNi4#{^9&I7p$dgi6?4*S)#^_3Cl) zf$rZ&=uyMns(jn5CY9DTLIe2=gA^uUs|K7FfwO3L-(^?sB`Zx9?H9AUcoS+L2%rIp z-Y*?QfzOq-J*hNi;t8rUF&^LUnF>2?zo_1Z2Lc*nYeGn zoZbQ6P$F=@{6Jyoi$U}8mz@kFVMGbpu+BoP7R;105$m!v_@ZAtBl!!bsh@UEJ-T$^ z5|yY;$;W6alvEDpbkcVpYLqGU1v<5(9s%v2e{H5m7$`AxQ=_q++P{U3dR?N7^!D51* zO@=+M(l<@!N0SXSq-i}*xH`d)jwc)Fv5Ka2vVk5$7)kBo@93E{n|XUtkJ`n!_CWun z^+o$m0K3F5uIN8@z!RA*KGx6av;C1ol}8c+hcCe4os9pZ-0`QW3N z^nU2ylSDZRdlC9pZFdf8lI98G$oU}wlI?cfN%CH(L;SK=>z?*aa&0p7bJ#3I;oX{U zGx&ZstY1B22+s*)qTQOAXwT2(k^9x~Cv3iI48%iNKnMB$R5}Nyef^M#|5VWeSPv zkam;?s5D9BGmQ?Nrw7Ps0A3#@Ai2Go+DclIa|Chob7PI^skm-{j+@ z9}MgysT><>wa^&|wd;2$%C^fJ?N!M4f7;eAqm9zFU;KMVpq&F8m=5u*tTBL@Fr=?6 z*!7lT^g!!Kn?fa`xkFt8s}ny)vW&};iF|Z`QpNrS8jAy<0o;=e)I&E$8wW{l8EHNn zpdXM7E^9k9{)n^CSC&KVnhMO|piGGB=@b`AvdoOI8f7}^-<&z}!i5azGQwOLd%2TiuQ$7JS!k4BtRKde(ZAPf)})-OIUTX9a5pZa0B7a{y4 zEtnf_Hf(!3J#kS%;YX2ycu({sEy@RfPC0D7>=VEbX^*~wMPp|+aM(YVrt3RNs?V|}-lf~-b}HkG@jDE4$r^Gtm4{|wOi+#atm&=&P;(>>@W|O21%d8ufp8@`FoPD%YzYU(6fC>M(^pkX4r+tMD zD^3r2rC;f1f)2V8x^0Vn1}-U&^Zj&KYwhQCEoE`3zF(i!RiU*Ljd^5aITBQtBv$s~ z-M=ONeD!QYkdWi06E-9X>6M2m=O( zN>{zu$7}Qzdgnh2hUTd{cpX5L(~fY z=rB}xu*c1S&uhB=s@qV7J#X@W-s{)l4Kfx!c6&lq7pN@V;zymF@6@56B#$O&TT{D^cc7;qssk%cdlMc|VfMaw>DQ5F%#7>-D_jX|_+T{kY-TL^_e$m}+r~sxq z$C@tlrP7O-<;$g)9rkvvGY%9gr~PDditkd%CdrkksQcxj%9qj3VpDyEtHUZnD|4V} zl|AJCK`Bz4V{kmzGF6t#{)K(dEn+_cyVt`FVU_CV`9b{8+#quo}N&kEiWYp-xX5?zw7Uz&U%$fb=} zc+mo3oG_|Xtmy>R*lk}`AJ&WpXlUuun}1XkKfDUgU&CFkN7bJ z`ukH$9)m7FjY{2W&ew9V8Cv{3@u|M6tCT1`tp>5uouIUHd7(fw^A- z;^S87M7_zL@1&i;l8byaH=JUu1NWJD%#zrQ`Ta!ER_PNXs9l}TXX3GbX*~NJbpBak?I?^DnXY01~(svEL8$pHSj==cc%B*4sVqXgO`6ikvtlb zKf?_;Pp(YDPUicDYlZ#gG!#gKgJu*fBdS9Z|AjPi$54vP)3u}fWHP-e8Ih9C)%r0s zZ;ykD|KvbIuk;EQ*_$Qtb-Zg*;$1^=I?z&22K0RKt|<{(P{&I@YOPnmW1Wtb;r-Ht zYLcjTiciUU8-8&P%69m`Ptvce1F1^sELs9aP|}`0TMbG@E|CfOP_Qzj1!)@6G9}1* zSRGV<8R+`&eh%x>p8xc730jA|iHjzCS{+O3ZP6`VyYkV~+_%MR(W@1n0qFlJB`Se> z>_F@Wilo$re9WTgiKRv*{C@I8jc~rG18;*S=hTax{o^vc!Oe%YBts0y9?^H8A4y{) z17m~axso^^`{)yB)lbM8i^c{A`bYiQzIpQ4fPCP;#)ipHV}tb1Kod)Sco8OfY`g+p z%M$|9s!y)Q=m-h;fIT5#bighS{lqu#a6hcS=iQXAK)+5wA9?D3Wi>$Wp7-^SRH!t%Aag%KZw`azO{fqI?C8bVEiKMU1BZWEdKIKiCeU1?fVGD` zDfE+1BnGS~NmjZZ8eAFC)ARL}$xcNF-~SVbwt|O5D$J>`QgqOI+7Ii})BDZxcp|AP z^1EFUe?__06j5F=69pvz`)>luFG4HS=-%1v;f~wGF?URrk=vDAKb8$i=uW2N9PDBC z-`DxdUoG2PCY zlVqK1k}yl+-@wN>;ULe{XTG144LWmC2z5~t)L(X*CfAyZ}wQmSo-%$8>cSKb+{ zWGi(_cE{$Po_H{wiMN&U3D3sjNX9X@hGW4ecv#SJ?DOM1yEGa+FdPeTm~brG!LgKj z@R4tR1N?+Zp6rClq#P9Xzi1s+u9+)L*)}IFY zCliwB->?ff2X4i|=5IswpxBF>KxtKjj*kIf-{gn=kd~N2SzP>%*JaY(2} zwOX_&wL97zl4ypzK^t&K)<3DGk_2=fXUG~T+|9k+8dDPC($vbj`szT7FQC=TNNqa`;;n)e1) zJJSD<#M^IbO8{}MbG|E9&hh8qN0?ws#6m;iO(Kx%707kz0Lt}?ae-VviCkZkcM*HR z8>X4@d0A|HzRkYLkW)AJfbGk1VK$9togA|sPDKT$UVJAkK zFMiS1P4WEVT5yLIzL$U_M;=S)PIh-w!JT%u-Ql7+hYfT5OhJL z0yR((8>oRlnx6WV#!Ld_-lQQ$<$l)>)MU8?7rJOC0V!ZH@$dbxriMmHv>qj(c)9+* z8u5!K=?Qjre(_^q0ni!6FG3B{y*IGS<)TPG0=u>zUe=D3fbSisrxxrSd0%@Em7Zc> zlm1-(5<8WCnM4!|)i#ap4p5w^m(ovhFyC88Xr;dkbMvR5&VholCUBiC1j01?@ZK|x zZ(Ik(c(FG|rhqZx4#Z;7mRqg{3vcI-a<$y4f{mDC4S6(F+@T1vLPvvQ6Q)uL);8x6 zx@H^cjtcT^Xaxd=3F|o!6oTT2;WEx1 zX~f93WZMIpQLxL9?~`T}Az&Y=rxoW!B32w(6Uq-=h_{=QIaM63yqqs`U|{9F4J&Uy zth`}Zc|$Rx?v-~5_r_%RuD)M1LRus)23L|+Uu{LkaDBB6y}iFv)1e**^v518EH$w1 z=JTM4H1J=S{_C!MT|8^q{Vd^+DtyMaw5OC_qt6lA&&zyo93FggEtbT4+Og}1zN5y9 zo;0w1P~{z<%e2TXQ(|p#hs|}g2Q_YQR8~^p1WOlI*0C!KcoP{Ao1nsdq2wvb)?TJiRZyX zq`Q2yQRv$Vu zv?Yz`oxR_n@4e~YSs3P$tuUjZv3oOx(|(l@$REA2*I&~-lDAk{i$>;w3=RxwLT3v*kFAMhmrv_Ay&bR>jFWq+*5~YG zvCQ}3>Y98mW+Xh2vz8s$Q5$`o${yvr$`6#CGhWAh@=QAFU-n}k0UT1&*uM)kAJu&d zvL8vD-SIc*{SzlZ5*g-JN&KOkVFso%BeZ0gJWCaUE{u25)rQ1RAB9AAG$yM0B zp{E4U3$hQy)o4mJRl&{g=mItHo|bYtDON>xHH1MtJTf?ryHk878_JG87rHfO1DVT)UBnJ+K7C-at?L1ey_Y zF~_!cQ7cfMY1F@OLJl3!dkYf9^iELjw1OuS_m$)we(`KOA>-1TKs2BPH02rZY8<6c{Kiu_Fme#y1J+KO7ccrxSj82AkEqZ%I zR~EiQZ@dW#OA@=mpP{utf>jS;3I>@=>?BjAJNDjnLISFBa`(P{>-YaA#|+s1{--Pf3|ZKX_#h3;8F< zdRtD;Jr|?=f6aZrKjogGJ#KB~TXWwj&g@!yaZi5CD2=DSWnsxb!3yKB5;;q91mb+q zEKT~=BD|QBKI^OC2~sb8vPWJ=u=4wXHx*O~34lru=@VV2`5$o=Kzh&!3B@>I=<^0O zbOrq4c-g;#BrXTN$@^AAdz$tZ#J5lJH$ft&{u5Pb0yU^NOJWdW(^$ZMAAI9mZA7dW zlVqzH+KGzdCOLmov1eAxx*UGdgEvJ`#7cAgD6&lnuj*Ij2Og)x<#IL_D6k^G6bXdo zCOh(WSt8tLqSYkm6OuiQBo3GJ3AqriLV;i}0cF`I&|0aj(pN)Iru|#tGJMALFaJ!< zntyc@2Tf8d;JfOS?7NERSFF%hWkl;M7CXc8wN)X`nfZziwOUX6Zf(KBGfuJ>3#2BA zWu3c_qc~b;?^Z3rm5L{fF4nPI{HA&<^bin}qDM3n0bu5YVI`ZHFBj7J14Z5<_PK%`o=%SDXyd+*}r?cDSxW7Z@ zN%ul;*8D#^`f9#cHW(f7ve3VhcGL_w;Gk`q5iU+o7aoF>;SStP{@;KRX!JHT0GTSW0^=mgx#7Zt^aJ1;pg z=amx21{@@A7jaN!J`!n8B@>klu1$bW{zAG<*j|?bzagQ%pW8#LzRg6Qfkw)gFHQGm zElcN0)uu|ZkY%)RHipjQYlBj^C0%|cz!XDK znBLO8gwBiQoeiXVy zCt^Mt>MzIszvs??-VCS=puYsP!yV}3k@bG@M?Y~Jh@(ujo&!|FE3n!E_aTTl5@z)4 zQ#WG-C>YXH1`PP9w9<>~-&a#)s(n;OW` zgWWq&i*vD;ki@f6kNDxi@i(=)YOzkGlymI$y*wL_V_O-=6vdE4@ouNWH-Xc_|Mw>Q z8_k@-kzO=~MH}BAXjjCSIC;9PGU$Dg<x&iiWGRnBpU`)2#FH0GS#$Y7n%7+KPit^gko3CI0qvLDc=)0G~#t4B2Ts7qm` z6{FsKTDk)FPQSZAEo)Dqtg%9(YrKQS4mh`2veZA+_{F0`PV>H}+V{PfQkcdRJ~gB= z>%#Xv%L9cV_5k7t(|w#_E#f{CsS{L*8t?5so>zGI@t;T$ZYDgMM_$lR6L-g~7!OY& zoD#YMA)eFHnZ&4qAM^OOU`LO~389bg$c)t69wFYnwC*jeVm{b(V{E!&cyV$&mQM z&&mqU+#=rHh4uIm2P8HTvOZvhtPfZzo^0eyh{vA#`7ev^SqyDK)!PGpk~+uWSWuh} zsZ!a>^xs^%QvJrD%{wkyUCbKvqbeEPn-Z6ci-VqGN$MXXZB~ho-+1vA=;nW}Va+d> zL|KD8Z(4O8tySa6g02)NWLnd`HLlRuRPSZyC})r}d2kfG4h$JstI>LBM%7o1#+>Q~ zU!nz4q&U}`*oVVY+sY>=8!nJsSaDzt_!xx|#1|{Hu+7973xSovGtUImbHH~$0Xg)& z^7DJ4cgQv`OOJOxBD~(5$wSxa%m>D6dDX(3ajBjUjFW^nn&*Rt{L7gpKjWX=JDL#)S|7#HE?$YSe8&oiNCkyg%qb*xNb`X%!hS*QEtx@!nluG`S6qbQX179 z&|2>5pY~Uw6!%u~54F3yr{iv_;AMCZanxz{MqA7jp#qdVmk94ZzOznl0^iQH7*o_~ zcMFcYDxI^mAGNX}$PpjX&f&TIH0^o=4@q|=@|f0pU!8_0zF!)U%TXRV<(KmG0$q9c zr8cTrO5;n&wc;LoV@N7;7=_%9(+dvt1I0$jI_i1fbVzBm^@?hB8fk|ZMjrx3)-!GS zd(T5O%E$8FBm+jt9XJXWI@!o)+UD#5?`;@2@~ww?4?i;8`+@MwLS4M>JaNK#a9H-b zRokF-H2blH~|`+4LUH1b>hY z8qcxzFxld{pKrvWyBFWJNZX{~Jdut^G|-Z{^B>GJ$V?TZzSydk;~Qk^CPr-`bB z9gumEW0A6|QvB#r@nYm8DRt1&fAI0~n6+wiG}Wi2_Z%CfF*&ED^EmdKPD8?bTB-*& z=beecyEaH;9ea!qFACkP+_pg)XWAf*XFCUMkR})vpV!Qs>A*b4MLJ6z^A_bqzV1@v zD=%G&TIg7GF@JTWa&$?~8~F-hrfZfnO;X;$tbXsj|GH*PT8{I5cq$gAf{{7N3%|Cb@oIUY8%R zx%vGCjVOZ z_U%p<`xj4C<^!-Tu|zZLcu?ZSvWz3y+ptj8tke|`5*`NDdKdJSG)V(bHK`fREIs0* zK#-n*_MCO;m&M>RG%C1ZjS8krsubHV$3i}4!yE&dqHmV}=f$cqHefK7z40== zH}Mkfc=GswU#t-e0_7rm67ugi1hmNW_QGiz`&m_l{ps`}-{nu=JxA5-Rwv@!$V-ij zm5n@SL7K)S>IwCi9hpswRZ)2kC30dxPK?OOdzUG;_7ZwzKD5Yy5$1zd_RcWm}{>P z&s_iS9IU+jFUN6|_-N}xFLT%}DVvSlBaVTX{k+m8q4|r_OW0jAc zee7LVbK%E%HIa|yznzoj2-L-b>srBq-ZH7}k-an8Snh%b`aOl(n*aom?p``-+5A8| zg2qc5m7RdT_G<3@g)IJFk5aDDiPuT*twNk|J!X-B@(y3DM!m$KUQP{Q!z;z}mtq!0 z!5bv6yF+-I+=HTn4A4TV7$OTJ4)iDwQ{4|gf{s8THyU}uKjmOSj?#bmEx0^-nEanJFwp{ zuskR0P`7hUdc|BPv)<$5v%>RlCqu~%rzOX67-1M{VaB^_gI7Mc^&qiznsq4yShG=ndm}7zE5tXhl9Wt|vwG}r;b9biTeG+Iw%N$5$`{INx8)iv z@LMc)Uxlx-4wVS2ZgK5Zw>%fz0H=`&OGpPmW6?Lqh?Dvq@+{gWvNPRP>=f)bwKjzwMYxtIp&>rP1q#+z}bSAh- zE2a^BX0pF_^@$fScCS61zBDTiRF1-~Fja_uzpA-r%-Vc)kY2hrrRp&}QJB*4RJxY3 z?9{b?>BVb;{>!T@s6x!Tx-es5W^uZqbZL5U+0*i9e9H5dbL0V6ro!ZsDK0JY7T2-H zrtv<4dymNXDqxv9AAExzafn}c&4`@zh+6Ohd&F;~HS08kpBbRRN*7etnAP zj%DjX8eZTn*7(YSo$ovZB?`Pl818-S0bt>?-^b}GuNT)SLf!sl49 zFQto8{g<@=+NpsXuCl6-s*-DQRSNsRubr|+UDMvZ;VOUk()G%+2`kj)s?s>;I#+O| zrc`0F;(bf4w)}4Jjxe&W&KL`Q)Cq zm3x^b7!uMeADTrU9a1Dl_srGkrpNlQY(c>WlEzWFSSvjOm9>~ zYlJkPTT$P7+^C%}P#x9IS|f>nBHKGw+MBZb+nch!tc4Xc>=M+?J=#}uqn+6sQA<~T z&-@)dM7?Pl_Mf`)*hp3B?u)U-X6OXGRpKf($Em$PWd_yoW0#_Lzj$Tq#ht~PrV^!M zY;g04AlqH{O7Bb^1Nmw(5HG@gS?o#fN$ykTK{!@Er|Y9P&&G4RZ=TbW|NhTsXMx-l zxcl#$F*mT4@_8kGcR+`105_UjQFka)=~ILp%zo3jG@aWtqs{&3^7NU~CI{?!Y+ajubnmBKqX=j7j9 zd+^0wayk`a$Q4D@d3!kMeI@oY3ydMyLGqHp7~b5I-1<$2JV(Vq%1=4@IE~O{gKD;B zFGsEIzj8%>dV5b*cHsH)bm+Yzm%fJW6E|l=T4{dMNbj*t%hO*J%Cq5NOo_Xj`eLsV z91~xX<1M%uuUJ@5cW%Zh5}y0hwNrRD`%RLB-i+~(P?EjiPj~JYP{I*$a_wmJ17Zga zjg5^OW(@Av|0&eL%L4trC_IVZ=jGqE!V@@OE&sZO$8r9&{JRYHSxeKOl7Al;9>w_* z`FD|Uw^P>y>)UK@a4sxG)0J#fJ7(wQ>0CLLx2WN6=Q0P3OBuXb7Y#x8hozN&I%(XAC!}pg2!9%37yh42E3VJhquPLh>Xs?JSMYUF7 zae2(J^=J3lne#h|(4gtpn96#dt0mo?^UL0TH_-+};>JS#OcGXT+*aI2)CdtB@ z1{?!VH?tBG8rl4p%7#VpM7YEL@Sr&#ojaaUOsb{+Rb zrG(sk{+C;x$6O_1NB{?Av2-}05VE0hcOps19-)YTr-Ezf_wLf>co3@L+C?rl`@ zYR|x1o}Rw4Rf;gFYHYyl$hO~>#d=$+LY#YPawTL@iIs9oRb8^9FBhRN^Sy2L@9iAR zMH{JcG;ZbD4jctfaqJz0WjLP1@pl{s+^dERfp`Legi{|gE3?A~ULl*n)&XvB8}1*#-FcuN=gD+WkdTM-Jo$W^;J~>S<&{D;BzL~w}@@m=VmEjsk-H?MX<=`3dPPd4kT_0Q*?~HX-LmzZ%_SB5!>BZ?&GpF9Hzf2)(dbB+Y zZ};V4-}N}x2&ckCn6=h?t~@(oCm(*LjxeXZ4CXYr9Oxu7b?4pz&@%j-UwStx@dXi)BzKZz^;nxUr z5uQevg7755qc|)$e+MDm*W$bsp@8Gc6C8US;UR=Q>v{GC!tZc>7-2fX?{Spl+>h{C zgc|Bc2!|qcA{>P<7okwi%l9VZdJL{DI2PhO1mR{pBfsWKd(1S2DJJV_v=_8B#FlFo z>}KXK!cNDuMQprgMm^EKXa2%1;;+{lTuSJrW0ff5RviDr(fJt1st|e*u0a^?t2n5)|BpG`x8lI_`R@Gn`&RGco4hMF z+O(eelhqzYlc#9)z&W;=v=UF@ATMLA6uk4I_e0>1{7{`?s={Q*T7i;76HTJxXE2(o1+4!!bgy2w7LhlSX_O} zbvIX`@_i@;G`%jlwN*wJ^F7kFx}cx0{u$=`$t_%5+{SE++lu<7T?vb4*UOG!-m6HF4n2HWJ>q`CHi{gu>(RG`t7&)=03OgvSF7O zR&lmQJ)hPXq)5ARTfFM}9eEF2>A&mHjiRC2qck^fxT-9e?@?bLxMcQ~+vEGC;d=Q4 z9xd`Uu@!Cr0k!TgH+Rkjr0J0(k9C5An0%sU45HC@ekc_ z_r``EcZs%Ye|}m1I$N|il3(iT{~h9o3_*OC_idZTlLGyR4)L814t&dI;2P>Gk$aMg z@g*q5@{4>0i@n!d4yjNoBxS20DVru3f!C`j?-6gnV>C^gosAl{>{%sY@EP;ESLWzeo$pEY}@U*xOwhsYAxC!U1fYDSa_J!alj zT}2#nwW&*6P3@Qhk0q;-6N8|x&K;yK&46|J*&bchY^QFcuCfkNd)r=ZMTt{ermfzA zD{ikwwvDVrTjZ9!hdy#&iNiT$_hczI_!6~}EFomgf?E%nSbfWRH~HYL?P1uXeDBs) zN1_Ghbh--|pVIu5o4+WpvzghAd{9=SPT$uTf*KXNv?~MR4>`9$Lr!~rK#9JQhi`z) zD+6En^0M;z*RI}Pt=nk59{Kv;g;Lb1SM%4?x*DZ#Mb8Dv;+}bBK+qY~31UX`DM2ak z%DsYFhk0(PA#RB0UAaveWRK`=At6oADbl2z7eTAae-qi-oWR~rTX6;}`Re>iTcalx zyV7WQ2>;D{2CXskN@P$U)uHpEpK!CU42-955={a9UpEI$VrHh^tZRCX=f+1Q*zk=o z&yoYW%5_d%sjgzXZL7Cmg7!S(==Dv{aj8co}MZdq+t@5WnC% zZc>=wxoqJ2a>#qRgtqg!!g$T?DSCZrV>Y2Y@`8xH~No^PQ zbp582d)zV2q#IxFdF6K+(cj?wlRd|N*S;oGQjtGkY;)-0+CUFy&$M0N)Asur%3bWy zKOWe-pg}!pbpt=Cqyc3Q0g`0XbD9j(U!|NCKJotUj3{lT8-3i@Gy!%a&0EKgc>d3?Yv&7@-284xtXA3SkgJ!VEMZ z>;m^H1T(ZTrA-uNEbAWeEHqh^cy=AnGzgmzY7sUdq%?j(sPBE}0(b=z-Z$8d*(y-Z zWZf7*OlOGqHR4fTK1ayRH^i&3Pv8(P zu$>>ShzX=eI3SMV*9mu#If_U#HP-%m(VZykYhC1{z73cjv6!)Lh)0l062b!r3ANyc zxCLL7j;uqvq|=~9x_vg7lq#)FZQ=^NO}X2KxD$?yL0m(2(fbsSs7P)Ym5E}<*&W3X z%Xvt|H}ilaLYCyK@fNLX2D~@(5|^NGo@4V`dBx&Z8xTR@H|#*_B`%TVBSlmCp7TKX zr03rZ3_n0mG8{%bt*v|IwUE}ppQQc!B8y+B?MSEjcX|nL*3|gKN+7=v3aiP6gPro_ z>B=(I#xC%S(#?D|dZiJ_Cv2u<+WwL;yoq2o?iyqyv`Qp zH9H;7m$52+=zb2rhurXA3`4rb(5&z@;m%w3d zX1?R@ETA8dN8O;MOXE{~hutTOi!c}Ocdsul#{Ku)*~NLdU+dNtFNnkH=dKm%@?UR` zg=|)HW>$U}unV5?axwjvY`OLP8h7mlfsI;46?QpT@TOhvs@q)FV8{G~9PdP9O(rv{vHrf+&CQ2)OB3n$)Xj}87VslE1 zrhl?M!O2X8h1$|F4XO&hIQ-pN_T__)K{qJK=jjQ}R#Yh*Hb+f?*~!JmISzaO4gX0g z^(-pI{zzdz!XY-cz~?I$y&f`Kl1Q=GXWIJh1yY2}eQ0ObyLWu4U{7YkUmilTU3?FE zU1ZxBjD31oab;ai-3xV9`95oiH^o(42Y}T&9+tX{gY7lbc-GsL=PKvPR3>33VnlrP znF2JnG(!t&b13xWVxgxwqE_pR@2bUWvdaFXN9zmjnwZaGBVoPHbm?_(y2jM)$k)fK zJO3}?;-u^y7sEkP{lQc8=;STm1O=e>~m zo2+@`>V7GlU{8Zx@x=v@jDY@6gjQ zlHJdqW4E#GYys|M;Sga%gWJBB+-!v5=o$-W*&)#NI{EsfCCCDsSX_g)!1GfUqh%wm zS9s{^Gs_Umi^8xvI7HiMLG0 zRhoR|v5d4#!PPzTmDdt%0i8DTPWkE^%bk`xdvjS}QCddJ7Plj*J~`yoP-atl-kTh8 zRAW(Fh6!}0vV3GQ2{+_&6`ElOddg%>_Xs~oprod?a{+^wj>UZ;&s(s~9?n*fdKIg-j4Txhn}OtA=a z6cOLmyMRa`Xk+I{A&F`)>0M8-{|(Pa+m*oa4V?Ew>|o&zh5kDo(rvEfn*w?R$^ zRHR8pNCckh=u--&N8j3yu}(S+L+vxN)#z0d>q@cKqFin*}3Mc_7bzPl!+ zXD%F+7_(4!yK(Ho_=OA2Y=q52ElstJb^yvBT~STmi7Ug=Pc3UKW8|~7mXnqQ`RqB% zDT`G;d*1RH+JWLxPcg}7FIm2_+##Qxuq;G7(9=@O*OoB(tjyv;JJ7vyi`Sx&&o)}V zxuqS9(|W{_-495r#8m~PBOcy{-JJ(E>4uSB@PTFnkjd|aoMr%Uh|DaRrLpl`GizWS2&b}d*+O=K&8t(u z;)}fkdL&0*XT?tATWIOmOi|f~US#n7K=(J9Z!~1pDWFFlh^MO?0Zs4I=EjD;7_XRr zr5LxQWH6s=_|AOxW{l0|Z*QLK>%KRC(Xhq*S%dWuU$xIR#~U0UzMmZIH6)N^fI%~XH>a8J76RvKX5Ktjc&L4S_n+guYTjm!>y5L`{Hi%xV6lpG zhJ+Mfg_{>b5+3q0;aOOK73#J{&4I4O$GUTnEo9jPDTUwiwTI1%&C1@C7MmY7qc=e! zM0w6>V6i;XTm*abkc4r)DIV8dh)NWg)qwTzQ{4>T8lBBU5#JAfO0r@dlI2KK1`>Qq%@m%YU(j{{}~Y!BL) zFv$MZI9XW8QHG*v5XSg~)CV+D;`5Fe|gK=0@8`7S>GZKC<*9 z1-tj2K$#5DMehSUL%F~iGEp_+K3TdJn`~3`Hyeg+zf0A@ahtUBpjXKvpew03>3qql zXlE_Tc6H~}MxGTNfzIP?(1r}dQ#MKo-Oc%tX+=lqigYn;jVXwO^s(pS)So+HA>3(b zW5&Qe#DK0g$6j)N=0u9EtewA+20p%iT8Mympc(4MbA{q<=OsMn{!mTBw>#~P2A*$J zAzf(GA4y>*=Djr z4Eqm0KG>@S?q!fr=$bTw!|%!wr;jqw2fPqrN84HY`;=;mGOuj%|+jFfRHN>xk2+;m^Igv;>>p`V(~_-+QY{tK*xEKl^0f8nQ+*OH=?*G z>${|t^UofcU+9TN{&G4}oq@0D@f8CkcHpi?rA*KvR7ANas1Sxm)lc9sWApYqp{>eV zAx&o!944W_^;*30!VcI&hnkq#DCDXYz~bP(Q-IFoaHpToggFE~Fl2_$2riF--y%-E z^c}b)#?zK zeKpjV_nO|k*YxHc`rSA4o^&(siOBn||H}KE|7+eii`TB-ns?f3la{3$?R*Tix(hZv znrNFn*uJ*F-mYki05|tGPkQ76rvfOmVI$D)Bjk1;rWfv&+x^~~?aoF(<8l~uw~~~} zLGeF%*~nrKvlxa8gYD2)KB+1EjyN$r;?j0ahY}iQfto_8t$#s_k+$umShXCkjOFF< za4cHf#F?D$rXX*-yGbuH6LwIP%KelIm(`n!0jY$dKT;}ObjpMv`AiY*o)AbeG&<1w z3j2?e(nwVjX-tL$do^(fhS^ z#8>rP<|n_D9}$qSaRyJS>%Dz5!8g?&pwZ_+@2RwDkCxg*V2TwTc_H5ijPh;!X0*A7 zshhriia55t?;6sb_C}>D@+hS`xlyA`cTn0YvorLMPe=Wm<~$OF*Ysce|qUTQbk6YOC^^zsMl9LqE6<}C$f;~ZG`hO<>1 z4XeFYabD*?^0=}8${RFh^5mv-C{+n;%rQ@Rq{o*8+qDJTfjW5G^p)vc>@aV^)1&M9 zWhCXA?CT522CZ~TyfeeJ6Z(XTCCJNYaIo^S^5P!$i7wb~2_}=h%sI>1Bkq?G4B<<{ zH4x*tt_R3&GbQk5)=mh_uM+rF@EU23H1)@R^18ShIJXLq_8fZSd4-^KtaW_q;N&p) z0Lzn(#Jd!Eu?UMWbA{L=<=M>DNxm;@*mZG1XH3zsJV#zY1CMk+RrVm4!9Fd1ghzdT zQv3i#P|VTgYZy1`qcU9@%_-N-0^x(NqmSmNXUwb6ihMw1xHMT5EBzFtcWoR zmY5J>WsE_H0uobH*5MeE18x>Sfp+nA_@-b&Cib!!(CLnFL-V_|!Sz=Dbs!vqR~-gk zYP8a>&SNpKgm5bwIYT{Se40nC$ETnd3{Os*+Ne>yH7~_}9C6#k=Q~dK&OFD_cecCQ zL^tjP`XOR)@GS_fP->syPz1JE{}s$7goQ_Xv{n@>v`5eb#m;JAjbHeu-!Ogj_+K$v?1p!LO?YRMu zTicLc_oCV8+ffc_^_-u+xuc(fW1r~qHUh+orbUt zj`$ZC&jD|Lmi@!Uwb&IfH~B{+`zyk{A`ID98SNns8n|qGwtXe=PcOHXm#+4b$$8ElJkf8JUW0Hr>_a*Z3U1h;*3Z!5hd1^G%5@aHNNr#9f-eppyL1v3d^F6sy+ zG#kXV!M2&o8;EJL|BO3na!h=a1yxR3?36Jn;u!WFW%_DD#@#>VbHOs6>BHd~U>^@lXKKy;Q=X+Y9h}s2QY`#%N9xWcaGq}y#sbeS z7qkP@%jmz`&2nsU(SEr`@ytLL`c$8UQ9FPZR`z7;srHaosl z6hK$oKLx$Z&6xvifgA3?M4(?0JC`W*#GRe zmG*Bx9~`CvlHkoIn=v@tk9fB&xQ9i2kKx` z_d7GJc0%G~(LnC$&V}q1HGp$hw-x>&&6q2~cVjK={$mbg4)B-D$_Z7IVN;MS zf<_AYlj^(AqRCR2P)N|Ogiak4K&S3|&JCw=%z!R6TYvVKH1qtIOrnqkQnWP4Z*8eDDpH?rsG- z%wsdCBy_hG(xU+GAeB+<%9Za2%INF5U(!I{%Eh3Rn<>9%q{5;=IVra&C+woB^#8dZ zC_hRWu!q)B9hk9C?0b)DVNlHlDZQTRA}>+4P*!o9X?|-Jp8>uv?^MdO3R|z zmf+?LZL4?&C058S$46T+zC7?_r!qrZvP_AYs1^8K@fl|OxZD&V$xx}ESX?uOuxO~v zbT3fmzPnW76lzzpwpPPI{T`?r1DB=;6_cF@II$z4G5qY_ z{Pz-6=if~j{^Q0;T*5PFqJ?i0R-8MXz+X6r>!;2{!UuK{)*$i=Nj*X8?8DJ&6^&hl z>%;Hr!zK#M6#;CbnLX9@ut@CwX7hA!D0+ ze!ya!b!u>@?9fLlTl2EjHHDM|m3I)I&183Q--jpj--qwyqZC^e8s&>Bqo!W_jXp0ZEHr|R>_`6tus>QS z4M^mD5kR1R4-|V!iz4jFIsY!$KjjRh+$;)DL9JTC&NxFBa%RoK4AV97({7^TL!kr0 z=f$CQdy+qew_Zau;Y%li;(HOe3MZvOIW3~lm4ZC}4fqPJVx}LozESIZO)S6813{V6 zU*tIg+FWfbnUT0FT{ov=y1TaLT;;qIH(Xip8!XRNvpTArsh?LhT?sQvlY zaVY1wLgt$Y6u^2-EA9@x8Td+&Yr)UDYiK0 zp2Ag_qh^7cnDIwRQjb8C+G*k5k zgoE~g@_;87tZF%gR9Z8I=1SCZP9Ik7l6uK}58hw!1RF;0Yuw@RvAD#+UinWN|KIQX z%tP?LWf)NeON#E7csJhE4BCV57lrR7>Vm#LK}JRU^Y?$HH?U@8$-Z_u-&|l3oR7dg z_fxq@Lpx{>(R5vlkdm9$Lspv7n@S&|G@+m^NyJK~Z2^MiUkcv_jjTpL9}P<5FQC(Y zg%4>u=X_QB|EsqcW=SK^TR!jYEf4zt+*>I2e!0Kg>|gp>lJ%BRpZ2FWXnwFdCCm`$ zW4F!4EaAp1VcK2=>*7-yy*y7?{qP%L>YFJ(gZ**46L%8Jt(Ymo!Z1UW(fD_((7s`4 zUz;z}9U-)2&D|ptPfvGMbyanBbyY*~-mkcKNvsXtJBNGc zVCVj`+3{s?yuZl*>v+R&k#Fb%p~Kfb@t?-~d2qbDgEaA1uhz+&ze=u>-phR|p(!JS=1vkRRtyIGV^IzWL&6 zaJ6u7pm1;?k+|Br>$uuT;owDmulp`)!Sxnb_fxnVIGbwM6<8-5_J_X+4nuK!z}GUs z*Vw^8)Oh$Hmdaw~KL8a6Vw(PjH9D|V-NFf&yHBmFFm~x z5z)6kO&NLJVOOO)+XJ#-%&E^^4Uu`m962UqRBp4r$5Fjs1L=2U7s2d>7J^xEODsv0 z9z;R#9@UQ`Dd6Fvvo3N5jLv}3d13*t)mQgl^r#WtUV$LNOB*>zEPgMb|5Bz|eE?oe zkBq>c9=0BlAw<1?NM;<3!+0|95D)2N#65Vyc(WXcI zC6cIQ!67)#>42k}q$)7c*%~6kELAK_VUTs@0a)C*;q80;E z2Cz3k(x^D0Ia$qEIMC*@>75BZ!r|oym0ME%70C@r))iD#) zL7k+l*16ji&^eP7opZUOb0+zRt(*v*(-PD<2jXgRT#|pl%7>wIs-bfx`TMNw{^LwG zurM)VFf3n#HdEifmfhtSaE=ublltE-bDsUM>KqWKqgI4ci|P#8K-ylQrW!Tn2&x&- z_g09^a%dM(MJTV54JK~%=lxA_`*+EpnIGh@N-jwCh?vbnZg zQ$Ixek8Zh6N2Ghu5lgP=h|mlHM;~+0(WW%5JVhglXBYG0fHvbFS?L9fP%SOGq){k#} zFNjgE)3`{xg$_|M2^##r)qSbOa2i`ji^hiV-?jLi?@=-8?R%8yxVK-YO#@o!rvlAC zXw_ZYr5?f~7cHN_T)x)VBR<*>zaWjcV%m0N&RO)CsFx(ooqGm>G6-UW5i8bR9>Du! zpb-5P^6P5V5nm$AN9`mnpT;^z!RLQ5R_OTw=sl8rJ?xGHOB4CMKb!ewka8F~tF2HMX2>bANb2p%E>it85(l;=7 zuh5DymS%30H|+E+u~{^4A*Ip^dW&-*x!&<)#$sOszh3uX?&8kWf(%5iV*Y8WR@w{5BSKi6kkf|DdSuHC{P!EM-SN9# z`3)-6|7^K&>LmEJOy(a4XWF6I=&xEH&$$I&MZy2e$yRUX-_JRq@U1`{gE}Z2<~%?&x}%R$Yf6=o2MDxlg|hHSC5Fs1f_omnFjPJEeIJ}nV<)S2P`BtI$%V; zZUfMRcL914!o`ps=XTlPe6`7AU>iDYwy!oV=O9~(rt^QznG?j% z-}G}V%dW!@+dKz-pq&C5FKKfGg*g_AG)fp$-d`3)R@mZk50|0`oWJ*nEkf~#(9=aD z!cWc_vHwDN{w*Uy&dfyyoRECz=J0LZj^FD1OJYFV+}}(VwZL2)ed-&`#ekg0Tr9u0 z{!4eyqoIBc_5;Xz(W|maYQq}3NxJwaYiK9t;Y%Q)~UHcPsBv_U)DVqFHgc z3wakSfHYhK?_RtPF#&0Xyq`2bV_?pL%jP_b|Cv7-RvlVbe1+_vglQT#VcK;K)8f7L z|A4h5yo*-XBpH;^Uv2xNR_82KFdYKSga9*zw61uj%evwZn5GdIsvExeBc>7YsuR

          hewzqu;pTy-Z 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 TNv!Du$@?4g_p`*&$<+H_5WZWc literal 0 HcmV?d00001 diff --git a/release/aroma/qo_db/lib/libm.so b/release/aroma/qo_db/lib/libm.so new file mode 100644 index 0000000000000000000000000000000000000000..d3b58c531beb44b87ca29d1ce0e76c97291e3c3d GIT binary patch literal 103628 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 literal 0 HcmV?d00001 diff --git a/release/aroma/qo_db/lib/libqc-opt.so b/release/aroma/qo_db/lib/libqc-opt.so new file mode 100644 index 0000000000000000000000000000000000000000..27fa571e4f9b6669a7ade8d1dc592d7e384a9b31 GIT binary patch literal 9584 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 literal 0 HcmV?d00001 From 234785a68754c108b27a15e1d27c95a6b22a2764 Mon Sep 17 00:00:00 2001 From: animania260 Date: Wed, 29 Jan 2014 00:13:07 -0500 Subject: [PATCH 195/215] Makefile: update toolchain path. Defconfig: re-add CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y --- Makefile | 4 ++-- arch/arm/configs/flo_defconfig | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 0577a3e6aea..08bfe102804 100644 --- a/Makefile +++ b/Makefile @@ -192,8 +192,8 @@ SUBARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ \ # Default value for CROSS_COMPILE is not to prefix executables # Note: Some architectures assign CROSS_COMPILE in their arch/*/Makefile export KBUILD_BUILDHOST := $(SUBARCH) -ARCH ?= $(SUBARCH) -CROSS_COMPILE ?= $(CONFIG_CROSS_COMPILE:"%"=%) +ARCH ?= arm +CROSS_COMPILE ?= /home/belial/android/android_prebuilts_gcc_linux-x86_arm_sabermod-arm-linux-androideabi-4.8/bin/arm-linux-androideabi- # Architecture as present in compile.h UTS_MACHINE := $(ARCH) diff --git a/arch/arm/configs/flo_defconfig b/arch/arm/configs/flo_defconfig index 12e719debce..5b03841bae5 100644 --- a/arch/arm/configs/flo_defconfig +++ b/arch/arm/configs/flo_defconfig @@ -163,6 +163,7 @@ CONFIG_PROFILING=y CONFIG_HAVE_OPROFILE=y # CONFIG_KPROBES is not set # CONFIG_JUMP_LABEL is not set +CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y CONFIG_HAVE_KPROBES=y CONFIG_HAVE_KRETPROBES=y CONFIG_HAVE_DMA_ATTRS=y From 03f74e43954e7d3f498a043f6a403aa013a9e843 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 29 Jan 2014 05:11:12 -0800 Subject: [PATCH 196/215] Linux 3.4.78 - 9 commits squashed KVM: x86: Convert vapic synchronization to _cached functions (CVE-2013-6368) commit fda4e2e85589191b123d31cdc21fd33ee70f50fd upstream. In kvm_lapic_sync_from_vapic and kvm_lapic_sync_to_vapic there is the potential to corrupt kernel memory if userspace provides an address that is at the end of a page. This patches concerts those functions to use kvm_write_guest_cached and kvm_read_guest_cached. It also checks the vapic_address specified by userspace during ioctl processing and returns an error to userspace if the address is not a valid GPA. This is generally not guest triggerable, because the required write is done by firmware that runs before the guest. Also, it only affects AMD processors and oldish Intel that do not have the FlexPriority feature (unless you disable FlexPriority, of course; then newer processors are also affected). Fixes: b93463aa59d6 ('KVM: Accelerated apic support') Reported-by: Andrew Honig Cc: stable@vger.kernel.org Signed-off-by: Andrew Honig Signed-off-by: Paolo Bonzini [ lizf: backported to 3.4: based on Paolo's backport hints for <3.10 ] Signed-off-by: Li Zefan Signed-off-by: Greg Kroah-Hartman staging: comedi: 8255_pci: fix for newer PCI-DIO48H commit 0283f7a100882684ad32b768f9f1ad81658a0b92 upstream. At some point, Measurement Computing / ComputerBoards redesigned the PCI-DIO48H to use a PLX PCI interface chip instead of an AMCC chip. This meant they had to put their hardware registers in the PCI BAR 2 region instead of PCI BAR 1. Unfortunately, they kept the same PCI device ID for the new design. This means the driver recognizes the newer cards, but doesn't work (and is likely to screw up the local configuration registers of the PLX chip) because it's using the wrong region. Since the PCI subvendor and subdevice IDs were both zero on the old design, but are the same as the vendor and device on the new design, we can tell the old design and new design apart easily enough. Split the existing entry for the PCI-DIO48H in `pci_8255_boards[]` into two new entries, referenced by different entries in the PCI device ID table `pci_8255_pci_table[]`. Use the same board name for both entries. Signed-off-by: Ian Abbott Acked-by: H Hartley Sweeten Signed-off-by: Greg Kroah-Hartman perf/x86/amd/ibs: Fix waking up from S3 for AMD family 10h commit bee09ed91cacdbffdbcd3b05de8409c77ec9fcd6 upstream. On AMD family 10h we see following error messages while waking up from S3 for all non-boot CPUs leading to a failed IBS initialization: Enabling non-boot CPUs ... smpboot: Booting Node 0 Processor 1 APIC 0x1 [Firmware Bug]: cpu 1, try to use APIC500 (LVT offset 0) for vector 0x400, but the register is already in use for vector 0xf9 on another cpu perf: IBS APIC setup failed on cpu #1 process: Switch to broadcast mode on CPU1 CPU1 is up ... ACPI: Waking up from system sleep state S3 Reason for this is that during suspend the LVT offset for the IBS vector gets lost and needs to be reinialized while resuming. The offset is read from the IBSCTL msr. On family 10h the offset needs to be 1 as offset 0 is used for the MCE threshold interrupt, but firmware assings it for IBS to 0 too. The kernel needs to reprogram the vector. The msr is a readonly node msr, but a new value can be written via pci config space access. The reinitialization is implemented for family 10h in setup_ibs_ctl() which is forced during IBS setup. This patch fixes IBS setup after waking up from S3 by adding resume/supend hooks for the boot cpu which does the offset reinitialization. Marking it as stable to let distros pick up this fix. Signed-off-by: Robert Richter Signed-off-by: Peter Zijlstra Cc: Linus Torvalds Link: http://lkml.kernel.org/r/1389797849-5565-1-git-send-email-rric.net@gmail.com Signed-off-by: Ingo Molnar Signed-off-by: Greg Kroah-Hartman Conflicts: arch/x86/kernel/cpu/perf_event_amd_ibs.c mm/memory-failure.c: recheck PageHuge() after hugetlb page migrate successfully commit a49ecbcd7b0d5a1cda7d60e03df402dd0ef76ac8 upstream. After a successful hugetlb page migration by soft offline, the source page will either be freed into hugepage_freelists or buddy(over-commit page). If page is in buddy, page_hstate(page) will be NULL. It will hit a NULL pointer dereference in dequeue_hwpoisoned_huge_page(). BUG: unable to handle kernel NULL pointer dereference at 0000000000000058 IP: [] dequeue_hwpoisoned_huge_page+0x131/0x1d0 PGD c23762067 PUD c24be2067 PMD 0 Oops: 0000 [#1] SMP So check PageHuge(page) after call migrate_pages() successfully. [wujg: backport to 3.4: - adjust context - s/num_poisoned_pages/mce_bad_pages/] Signed-off-by: Jianguo Wu Tested-by: Naoya Horiguchi Reviewed-by: Naoya Horiguchi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman hwmon: (coretemp) Fix truncated name of alarm attributes commit 3f9aec7610b39521c7c69d754de7265f6994c194 upstream. When the core number exceeds 9, the size of the buffer storing the alarm attribute name is insufficient and the attribute name is truncated. This causes libsensors to skip these attributes as the truncated name is not recognized. Reported-by: Andreas Hollmann Signed-off-by: Jean Delvare Signed-off-by: Guenter Roeck Signed-off-by: Greg Kroah-Hartman SELinux: Fix possible NULL pointer dereference in selinux_inode_permission() commit 3dc91d4338d698ce77832985f9cb183d8eeaf6be upstream. While running stress tests on adding and deleting ftrace instances I hit this bug: BUG: unable to handle kernel NULL pointer dereference at 0000000000000020 IP: selinux_inode_permission+0x85/0x160 PGD 63681067 PUD 7ddbe067 PMD 0 Oops: 0000 [#1] PREEMPT CPU: 0 PID: 5634 Comm: ftrace-test-mki Not tainted 3.13.0-rc4-test-00033-gd2a6dde-dirty #20 Hardware name: /DG965MQ, BIOS MQ96510J.86A.0372.2006.0605.1717 06/05/2006 task: ffff880078375800 ti: ffff88007ddb0000 task.ti: ffff88007ddb0000 RIP: 0010:[] [] selinux_inode_permission+0x85/0x160 RSP: 0018:ffff88007ddb1c48 EFLAGS: 00010246 RAX: 0000000000000000 RBX: 0000000000800000 RCX: ffff88006dd43840 RDX: 0000000000000001 RSI: 0000000000000081 RDI: ffff88006ee46000 RBP: ffff88007ddb1c88 R08: 0000000000000000 R09: ffff88007ddb1c54 R10: 6e6576652f6f6f66 R11: 0000000000000003 R12: 0000000000000000 R13: 0000000000000081 R14: ffff88006ee46000 R15: 0000000000000000 FS: 00007f217b5b6700(0000) GS:ffffffff81e21000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033^M CR2: 0000000000000020 CR3: 000000006a0fe000 CR4: 00000000000007f0 Call Trace: security_inode_permission+0x1c/0x30 __inode_permission+0x41/0xa0 inode_permission+0x18/0x50 link_path_walk+0x66/0x920 path_openat+0xa6/0x6c0 do_filp_open+0x43/0xa0 do_sys_open+0x146/0x240 SyS_open+0x1e/0x20 system_call_fastpath+0x16/0x1b Code: 84 a1 00 00 00 81 e3 00 20 00 00 89 d8 83 c8 02 40 f6 c6 04 0f 45 d8 40 f6 c6 08 74 71 80 cf 02 49 8b 46 38 4c 8d 4d cc 45 31 c0 <0f> b7 50 20 8b 70 1c 48 8b 41 70 89 d9 8b 78 04 e8 36 cf ff ff RIP selinux_inode_permission+0x85/0x160 CR2: 0000000000000020 Investigating, I found that the inode->i_security was NULL, and the dereference of it caused the oops. in selinux_inode_permission(): isec = inode->i_security; rc = avc_has_perm_noaudit(sid, isec->sid, isec->sclass, perms, 0, &avd); Note, the crash came from stressing the deletion and reading of debugfs files. I was not able to recreate this via normal files. But I'm not sure they are safe. It may just be that the race window is much harder to hit. What seems to have happened (and what I have traced), is the file is being opened at the same time the file or directory is being deleted. As the dentry and inode locks are not held during the path walk, nor is the inodes ref counts being incremented, there is nothing saving these structures from being discarded except for an rcu_read_lock(). The rcu_read_lock() protects against freeing of the inode, but it does not protect freeing of the inode_security_struct. Now if the freeing of the i_security happens with a call_rcu(), and the i_security field of the inode is not changed (it gets freed as the inode gets freed) then there will be no issue here. (Linus Torvalds suggested not setting the field to NULL such that we do not need to check if it is NULL in the permission check). Note, this is a hack, but it fixes the problem at hand. A real fix is to restructure the destroy_inode() to call all the destructor handlers from the RCU callback. But that is a major job to do, and requires a lot of work. For now, we just band-aid this bug with this fix (it works), and work on a more maintainable solution in the future. Link: http://lkml.kernel.org/r/20140109101932.0508dec7@gandalf.local.home Link: http://lkml.kernel.org/r/20140109182756.17abaaa8@gandalf.local.home Signed-off-by: Steven Rostedt Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman nilfs2: fix segctor bug that causes file system corruption commit 70f2fe3a26248724d8a5019681a869abdaf3e89a upstream. There is a bug in the function nilfs_segctor_collect, which results in active data being written to a segment, that is marked as clean. It is possible, that this segment is selected for a later segment construction, whereby the old data is overwritten. The problem shows itself with the following kernel log message: nilfs_sufile_do_cancel_free: segment 6533 must be clean Usually a few hours later the file system gets corrupted: NILFS: bad btree node (blocknr=8748107): level = 0, flags = 0x0, nchildren = 0 NILFS error (device sdc1): nilfs_bmap_last_key: broken bmap (inode number=114660) The issue can be reproduced with a file system that is nearly full and with the cleaner running, while some IO intensive task is running. Although it is quite hard to reproduce. This is what happens: 1. The cleaner starts the segment construction 2. nilfs_segctor_collect is called 3. sc_stage is on NILFS_ST_SUFILE and segments are freed 4. sc_stage is on NILFS_ST_DAT current segment is full 5. nilfs_segctor_extend_segments is called, which allocates a new segment 6. The new segment is one of the segments freed in step 3 7. nilfs_sufile_cancel_freev is called and produces an error message 8. Loop around and the collection starts again 9. sc_stage is on NILFS_ST_SUFILE and segments are freed including the newly allocated segment, which will contain active data and can be allocated at a later time 10. A few hours later another segment construction allocates the segment and causes file system corruption This can be prevented by simply reordering the statements. If nilfs_sufile_cancel_freev is called before nilfs_segctor_extend_segments the freed segments are marked as dirty and cannot be allocated any more. Signed-off-by: Andreas Rohner Reviewed-by: Ryusuke Konishi Tested-by: Andreas Rohner Signed-off-by: Ryusuke Konishi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Signed-off-by: Greg Kroah-Hartman md/raid10: fix bug when raid10 recovery fails to recover a block. commit e8b849158508565e0cd6bc80061124afc5879160 upstream. commit e875ecea266a543e643b19e44cf472f1412708f9 md/raid10 record bad blocks as needed during recovery. added code to the "cannot recover this block" path to record a bad block rather than fail the whole recovery. Unfortunately this new case was placed *after* r10bio was freed rather than *before*, yet it still uses r10bio. This is will crash with a null dereference. So move the freeing of r10bio down where it is safe. Fixes: e875ecea266a543e643b19e44cf472f1412708f9 Reported-by: Damian Nowak URL: https://bugzilla.kernel.org/show_bug.cgi?id=68181 Signed-off-by: NeilBrown Signed-off-by: Greg Kroah-Hartman md/raid10: fix two bugs in handling of known-bad-blocks. commit b50c259e25d9260b9108dc0c2964c26e5ecbe1c1 upstream. If we discover a bad block when reading we split the request and potentially read some of it from a different device. The code path of this has two bugs in RAID10. 1/ we get a spin_lock with _irq, but unlock without _irq!! 2/ The calculation of 'sectors_handled' is wrong, as can be clearly seen by comparison with raid1.c This leads to at least 2 warnings and a probable crash is a RAID10 ever had known bad blocks. Fixes: 856e08e23762dfb92ffc68fd0a8d228f9e152160 Reported-by: Damian Nowak URL: https://bugzilla.kernel.org/show_bug.cgi?id=68181 Signed-off-by: NeilBrown Signed-off-by: Greg Kroah-Hartman --- Makefile | 2 +- arch/x86/kernel/cpu/perf_event_amd_ibs.c | 55 ++++++++++++++++++---- arch/x86/kvm/lapic.c | 24 ++++++---- arch/x86/kvm/lapic.h | 4 +- arch/x86/kvm/x86.c | 33 +------------ drivers/hwmon/coretemp.c | 2 +- drivers/md/raid10.c | 12 ++--- drivers/staging/comedi/drivers/cb_pcidio.c | 21 ++++----- fs/nilfs2/segment.c | 10 ++-- mm/memory-failure.c | 16 +++++-- security/selinux/hooks.c | 20 +++++++- security/selinux/include/objsec.h | 5 +- 12 files changed, 119 insertions(+), 85 deletions(-) diff --git a/Makefile b/Makefile index 08bfe102804..ef659e27009 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 4 -SUBLEVEL = 77 +SUBLEVEL = 78 EXTRAVERSION = NAME = Saber-toothed Squirrel diff --git a/arch/x86/kernel/cpu/perf_event_amd_ibs.c b/arch/x86/kernel/cpu/perf_event_amd_ibs.c index 522de7e068e..ea34253cb9c 100644 --- a/arch/x86/kernel/cpu/perf_event_amd_ibs.c +++ b/arch/x86/kernel/cpu/perf_event_amd_ibs.c @@ -9,6 +9,7 @@ #include #include #include +#include #include @@ -209,6 +210,18 @@ static int force_ibs_eilvt_setup(void) return ret; } +static void ibs_eilvt_setup(void) +{ + /* + * Force LVT offset assignment for family 10h: The offsets are + * not assigned by the BIOS for this family, so the OS is + * responsible for doing it. If the OS assignment fails, fall + * back to BIOS settings and try to setup this. + */ + if (boot_cpu_data.x86 == 0x10) + force_ibs_eilvt_setup(); +} + static inline int get_ibs_lvt_offset(void) { u64 val; @@ -244,7 +257,37 @@ static void clear_APIC_ibs(void *dummy) setup_APIC_eilvt(offset, 0, APIC_EILVT_MSG_FIX, 1); } -static int +#ifdef CONFIG_PM + +static int perf_ibs_suspend(void) +{ + clear_APIC_ibs(NULL); + return 0; +} + +static void perf_ibs_resume(void) +{ + ibs_eilvt_setup(); + setup_APIC_ibs(NULL); +} + +static struct syscore_ops perf_ibs_syscore_ops = { + .resume = perf_ibs_resume, + .suspend = perf_ibs_suspend, +}; + +static void perf_ibs_pm_init(void) +{ + register_syscore_ops(&perf_ibs_syscore_ops); +} + +#else + +static inline void perf_ibs_pm_init(void) { } + +#endif + +static int __cpuinit perf_ibs_cpu_notifier(struct notifier_block *self, unsigned long action, void *hcpu) { switch (action & ~CPU_TASKS_FROZEN) { @@ -270,18 +313,12 @@ static __init int amd_ibs_init(void) if (!caps) return -ENODEV; /* ibs not supported by the cpu */ - /* - * Force LVT offset assignment for family 10h: The offsets are - * not assigned by the BIOS for this family, so the OS is - * responsible for doing it. If the OS assignment fails, fall - * back to BIOS settings and try to setup this. - */ - if (boot_cpu_data.x86 == 0x10) - force_ibs_eilvt_setup(); + ibs_eilvt_setup(); if (!ibs_eilvt_valid()) goto out; + perf_ibs_pm_init(); get_online_cpus(); ibs_caps = caps; /* make ibs_caps visible to other cpus: */ diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index 858432287ab..2bf03a99c2f 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -1278,14 +1278,12 @@ void __kvm_migrate_apic_timer(struct kvm_vcpu *vcpu) void kvm_lapic_sync_from_vapic(struct kvm_vcpu *vcpu) { u32 data; - void *vapic; if (!irqchip_in_kernel(vcpu->kvm) || !vcpu->arch.apic->vapic_addr) return; - vapic = kmap_atomic(vcpu->arch.apic->vapic_page); - data = *(u32 *)(vapic + offset_in_page(vcpu->arch.apic->vapic_addr)); - kunmap_atomic(vapic); + kvm_read_guest_cached(vcpu->kvm, &vcpu->arch.apic->vapic_cache, &data, + sizeof(u32)); apic_set_tpr(vcpu->arch.apic, data & 0xff); } @@ -1295,7 +1293,6 @@ void kvm_lapic_sync_to_vapic(struct kvm_vcpu *vcpu) u32 data, tpr; int max_irr, max_isr; struct kvm_lapic *apic; - void *vapic; if (!irqchip_in_kernel(vcpu->kvm) || !vcpu->arch.apic->vapic_addr) return; @@ -1310,17 +1307,24 @@ void kvm_lapic_sync_to_vapic(struct kvm_vcpu *vcpu) max_isr = 0; data = (tpr & 0xff) | ((max_isr & 0xf0) << 8) | (max_irr << 24); - vapic = kmap_atomic(vcpu->arch.apic->vapic_page); - *(u32 *)(vapic + offset_in_page(vcpu->arch.apic->vapic_addr)) = data; - kunmap_atomic(vapic); + kvm_write_guest_cached(vcpu->kvm, &vcpu->arch.apic->vapic_cache, &data, + sizeof(u32)); } -void kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr) +int kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr) { if (!irqchip_in_kernel(vcpu->kvm)) - return; + return -EINVAL; + + if (vapic_addr) { + if (kvm_gfn_to_hva_cache_init(vcpu->kvm, + &vcpu->arch.apic->vapic_cache, + vapic_addr, sizeof(u32))) + return -EINVAL; + } vcpu->arch.apic->vapic_addr = vapic_addr; + return 0; } int kvm_x2apic_msr_write(struct kvm_vcpu *vcpu, u32 msr, u64 data) diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h index 6f4ce2575d0..6aec0714398 100644 --- a/arch/x86/kvm/lapic.h +++ b/arch/x86/kvm/lapic.h @@ -15,7 +15,7 @@ struct kvm_lapic { bool irr_pending; void *regs; gpa_t vapic_addr; - struct page *vapic_page; + struct gfn_to_hva_cache vapic_cache; }; int kvm_create_lapic(struct kvm_vcpu *vcpu); void kvm_free_lapic(struct kvm_vcpu *vcpu); @@ -46,7 +46,7 @@ int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu); u64 kvm_get_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu); void kvm_set_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu, u64 data); -void kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr); +int kvm_lapic_set_vapic_addr(struct kvm_vcpu *vcpu, gpa_t vapic_addr); void kvm_lapic_sync_from_vapic(struct kvm_vcpu *vcpu); void kvm_lapic_sync_to_vapic(struct kvm_vcpu *vcpu); diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 3663e0b3897..4b1be290f6e 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -2728,8 +2728,7 @@ long kvm_arch_vcpu_ioctl(struct file *filp, r = -EFAULT; if (copy_from_user(&va, argp, sizeof va)) goto out; - r = 0; - kvm_lapic_set_vapic_addr(vcpu, va.vapic_addr); + r = kvm_lapic_set_vapic_addr(vcpu, va.vapic_addr); break; } case KVM_X86_SETUP_MCE: { @@ -5075,33 +5074,6 @@ static void post_kvm_run_save(struct kvm_vcpu *vcpu) !kvm_event_needs_reinjection(vcpu); } -static void vapic_enter(struct kvm_vcpu *vcpu) -{ - struct kvm_lapic *apic = vcpu->arch.apic; - struct page *page; - - if (!apic || !apic->vapic_addr) - return; - - page = gfn_to_page(vcpu->kvm, apic->vapic_addr >> PAGE_SHIFT); - - vcpu->arch.apic->vapic_page = page; -} - -static void vapic_exit(struct kvm_vcpu *vcpu) -{ - struct kvm_lapic *apic = vcpu->arch.apic; - int idx; - - if (!apic || !apic->vapic_addr) - return; - - idx = srcu_read_lock(&vcpu->kvm->srcu); - kvm_release_page_dirty(apic->vapic_page); - mark_page_dirty(vcpu->kvm, apic->vapic_addr >> PAGE_SHIFT); - srcu_read_unlock(&vcpu->kvm->srcu, idx); -} - static void update_cr8_intercept(struct kvm_vcpu *vcpu) { int max_irr, tpr; @@ -5385,7 +5357,6 @@ static int __vcpu_run(struct kvm_vcpu *vcpu) } vcpu->srcu_idx = srcu_read_lock(&kvm->srcu); - vapic_enter(vcpu); r = 1; while (r > 0) { @@ -5442,8 +5413,6 @@ static int __vcpu_run(struct kvm_vcpu *vcpu) srcu_read_unlock(&kvm->srcu, vcpu->srcu_idx); - vapic_exit(vcpu); - return r; } diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c index 07291e1d4fa..75eabb412db 100644 --- a/drivers/hwmon/coretemp.c +++ b/drivers/hwmon/coretemp.c @@ -53,7 +53,7 @@ MODULE_PARM_DESC(tjmax, "TjMax value in degrees Celsius"); #define BASE_SYSFS_ATTR_NO 2 /* Sysfs Base attr no for coretemp */ #define NUM_REAL_CORES 32 /* Number of Real cores per cpu */ -#define CORETEMP_NAME_LENGTH 17 /* String Length of attrs */ +#define CORETEMP_NAME_LENGTH 19 /* String Length of attrs */ #define MAX_CORE_ATTRS 4 /* Maximum no of basic attrs */ #define TOTAL_ATTRS (MAX_CORE_ATTRS + 1) #define MAX_CORE_DATA (NUM_REAL_CORES + BASE_SYSFS_ATTR_NO) diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index da20f0fa1b5..e5105a0b8f2 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -1113,7 +1113,7 @@ static void make_request(struct mddev *mddev, struct bio * bio) /* Could not read all from this device, so we will * need another r10_bio. */ - sectors_handled = (r10_bio->sectors + max_sectors + sectors_handled = (r10_bio->sector + max_sectors - bio->bi_sector); r10_bio->sectors = max_sectors; spin_lock_irq(&conf->device_lock); @@ -1121,7 +1121,7 @@ static void make_request(struct mddev *mddev, struct bio * bio) bio->bi_phys_segments = 2; else bio->bi_phys_segments++; - spin_unlock(&conf->device_lock); + spin_unlock_irq(&conf->device_lock); /* Cannot call generic_make_request directly * as that will be queued in __generic_make_request * and subsequent mempool_alloc might block @@ -2927,10 +2927,6 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr, if (j == conf->copies) { /* Cannot recover, so abort the recovery or * record a bad block */ - put_buf(r10_bio); - if (rb2) - atomic_dec(&rb2->remaining); - r10_bio = rb2; if (any_working) { /* problem is that there are bad blocks * on other device(s) @@ -2962,6 +2958,10 @@ static sector_t sync_request(struct mddev *mddev, sector_t sector_nr, mirror->recovery_disabled = mddev->recovery_disabled; } + put_buf(r10_bio); + if (rb2) + atomic_dec(&rb2->remaining); + r10_bio = rb2; break; } } diff --git a/drivers/staging/comedi/drivers/cb_pcidio.c b/drivers/staging/comedi/drivers/cb_pcidio.c index 8f3215239a1..453ea2d5734 100644 --- a/drivers/staging/comedi/drivers/cb_pcidio.c +++ b/drivers/staging/comedi/drivers/cb_pcidio.c @@ -56,10 +56,6 @@ struct pcidio_board { const char *name; /* name of the board */ int dev_id; int n_8255; /* number of 8255 chips on board */ - - /* indices of base address regions */ - int pcicontroler_badrindex; - int dioregs_badrindex; }; static const struct pcidio_board pcidio_boards[] = { @@ -67,22 +63,16 @@ static const struct pcidio_board pcidio_boards[] = { .name = "pci-dio24", .dev_id = 0x0028, .n_8255 = 1, - .pcicontroler_badrindex = 1, - .dioregs_badrindex = 2, }, { .name = "pci-dio24h", .dev_id = 0x0014, .n_8255 = 1, - .pcicontroler_badrindex = 1, - .dioregs_badrindex = 2, }, { .name = "pci-dio48h", .dev_id = 0x000b, .n_8255 = 2, - .pcicontroler_badrindex = 0, - .dioregs_badrindex = 1, }, }; @@ -239,10 +229,15 @@ static int pcidio_attach(struct comedi_device *dev, struct comedi_devconfig *it) if (comedi_pci_enable(pcidev, thisboard->name)) return -EIO; - devpriv->dio_reg_base - = + /* + * Use PCI BAR 2 region if non-zero length, else use PCI BAR 1 region. + * PCI BAR 1 is only used for older PCI-DIO48H boards. At some point + * the PCI-DIO48H was redesigned to use the same PCI interface chip + * (and same PCI BAR region) as the other boards. + */ + devpriv->dio_reg_base = pci_resource_start(devpriv->pci_dev, - pcidio_boards[index].dioregs_badrindex); + (pci_resource_len(pcidev, 2) ? 2 : 1)); /* * Allocate the subdevice structures. alloc_subdevice() is a diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c index 88e11fb346b..d4ca8925f01 100644 --- a/fs/nilfs2/segment.c +++ b/fs/nilfs2/segment.c @@ -1436,17 +1436,19 @@ static int nilfs_segctor_collect(struct nilfs_sc_info *sci, nilfs_clear_logs(&sci->sc_segbufs); - err = nilfs_segctor_extend_segments(sci, nilfs, nadd); - if (unlikely(err)) - return err; - if (sci->sc_stage.flags & NILFS_CF_SUFREED) { err = nilfs_sufile_cancel_freev(nilfs->ns_sufile, sci->sc_freesegs, sci->sc_nfreesegs, NULL); WARN_ON(err); /* do not happen */ + sci->sc_stage.flags &= ~NILFS_CF_SUFREED; } + + err = nilfs_segctor_extend_segments(sci, nilfs, nadd); + if (unlikely(err)) + return err; + nadd = min_t(int, nadd << 1, SC_MAX_SEGDELTA); sci->sc_stage = prev_stage; } diff --git a/mm/memory-failure.c b/mm/memory-failure.c index b68c8f66e4d..ea84800d0c5 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c @@ -1447,10 +1447,18 @@ static int soft_offline_huge_page(struct page *page, int flags) return ret; } done: - if (!PageHWPoison(hpage)) - atomic_long_add(1 << compound_trans_order(hpage), &mce_bad_pages); - set_page_hwpoison_huge_page(hpage); - dequeue_hwpoisoned_huge_page(hpage); + /* overcommit hugetlb page will be freed to buddy */ + if (PageHuge(hpage)) { + if (!PageHWPoison(hpage)) + atomic_long_add(1 << compound_trans_order(hpage), + &mce_bad_pages); + set_page_hwpoison_huge_page(hpage); + dequeue_hwpoisoned_huge_page(hpage); + } else { + SetPageHWPoison(page); + atomic_long_inc(&mce_bad_pages); + } + /* keep elevated page count for bad page */ return ret; } diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 6c8c416b874..1505ebda1dc 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -218,6 +218,14 @@ static int inode_alloc_security(struct inode *inode) return 0; } +static void inode_free_rcu(struct rcu_head *head) +{ + struct inode_security_struct *isec; + + isec = container_of(head, struct inode_security_struct, rcu); + kmem_cache_free(sel_inode_cache, isec); +} + static void inode_free_security(struct inode *inode) { struct inode_security_struct *isec = inode->i_security; @@ -228,8 +236,16 @@ static void inode_free_security(struct inode *inode) list_del_init(&isec->list); spin_unlock(&sbsec->isec_lock); - inode->i_security = NULL; - kmem_cache_free(sel_inode_cache, isec); + /* + * The inode may still be referenced in a path walk and + * a call to selinux_inode_permission() can be made + * after inode_free_security() is called. Ideally, the VFS + * wouldn't do this, but fixing that is a much harder + * job. For now, simply free the i_security via RCU, and + * leave the current inode->i_security pointer intact. + * The inode will be freed after the RCU grace period too. + */ + call_rcu(&isec->rcu, inode_free_rcu); } static int file_alloc_security(struct file *file) diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h index 26c7eee1c30..7b1830bde1c 100644 --- a/security/selinux/include/objsec.h +++ b/security/selinux/include/objsec.h @@ -38,7 +38,10 @@ struct task_security_struct { struct inode_security_struct { struct inode *inode; /* back pointer to inode object */ - struct list_head list; /* list of inode_security_struct */ + union { + struct list_head list; /* list of inode_security_struct */ + struct rcu_head rcu; /* for freeing the inode_security_struct */ + }; u32 task_sid; /* SID of creating task */ u32 sid; /* SID of this object */ u16 sclass; /* security class of this object */ From 46c49e5c7b7944efd024add1e60012f6ba7364a2 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Tue, 28 Jan 2014 17:13:12 +0100 Subject: [PATCH 197/215] Aroma : Fix skip of needed settings when keeping settings. --- release/aroma/META-INF/com/google/android/aroma-config | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/release/aroma/META-INF/com/google/android/aroma-config b/release/aroma/META-INF/com/google/android/aroma-config index 9988949c5ba..700a1f8311e 100755 --- a/release/aroma/META-INF/com/google/android/aroma-config +++ b/release/aroma/META-INF/com/google/android/aroma-config @@ -94,6 +94,7 @@ checkbox( "S2W/S2S/DT2W","Sweep to wake/sleep, Double tap to wake.",1, "Misc settings","BLE, OTG+charge hack, input-boost, etc.",1 ); +endif; if file_getprop("/tmp/aroma/glitched.prop","selected.0") == "2" || file_getprop("/tmp/aroma/glitch.prop","item.0.1") == "1" then @@ -121,7 +122,6 @@ selectbox( "2268MHz","",0, "2322MHz","(glitchy)",0 ); - endif; if file_getprop("/tmp/aroma/cpuopt.prop","selected.0") == "2" @@ -193,7 +193,6 @@ selectbox( "2268MHz","",0, "2322MHz","(glitchy)",0 ); - endif; selectbox( @@ -218,6 +217,9 @@ selectbox( ); endif; +if file_getprop("/tmp/aroma/glitched.prop","selected.0") == "1" +then + if file_getprop("/tmp/aroma/glitch.prop","item.0.2") == "1" then From 00992bcf281f729fcf462aa7526b777c2b471070 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Wed, 29 Jan 2014 22:22:38 +0100 Subject: [PATCH 198/215] Buildscript : Zip optimized Dalvik/bionic with everything else. --- glitch.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glitch.sh b/glitch.sh index 0475be7b485..468ed7b74f4 100755 --- a/glitch.sh +++ b/glitch.sh @@ -86,7 +86,7 @@ counter=$((counter + 1)) mkdir -p $KERNEL_DIR/release/Flashable-flo-AOSP REL=Glitch-N7-r$counter.zip - zip -q -r ${REL} boot config META-INF system + zip -q -r ${REL} boot config META-INF qo_db system #sha256sum ${REL} > ${REL}.sha256sum mv ${REL}* $KERNEL_DIR/release/Flashable-flo-AOSP/ From eea733b2b9e8ff3bda7c49a59a3086bc2b88101a Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Thu, 30 Jan 2014 04:14:51 +0100 Subject: [PATCH 199/215] Change the way min clock and auto-uV are applied to get more control, and add support for them in Aroma. Also add a basic backup/restore mechanism and fix some inconcistencies. Signed-off-by: Tk-Glitch --- arch/arm/mach-msm/acpuclock-krait.c | 52 +++- .../META-INF/com/google/android/aroma-config | 63 ++--- .../com/google/android/updater-script | 38 ++- release/aroma/boot/max_oc.sh | 31 ++- release/aroma/boot/restore.sh | 19 ++ release/aroma/config/buildconfig.sh | 254 ++++++++++++++++-- release/aroma/config/restore.plz | 1 + release/aroma/system/etc/init.d/99glitch | 49 ++-- 8 files changed, 401 insertions(+), 106 deletions(-) create mode 100644 release/aroma/boot/restore.sh create mode 100644 release/aroma/config/restore.plz diff --git a/arch/arm/mach-msm/acpuclock-krait.c b/arch/arm/mach-msm/acpuclock-krait.c index 0ff56fb251f..fd585d832ea 100644 --- a/arch/arm/mach-msm/acpuclock-krait.c +++ b/arch/arm/mach-msm/acpuclock-krait.c @@ -56,6 +56,7 @@ uint32_t arg_max_oc0 = 1512000; uint32_t arg_max_oc1 = 1512000; uint32_t arg_max_oc2 = 1512000; uint32_t arg_max_oc3 = 1512000; +uint32_t arg_min_clock = 384000; /* boot arg max_oc */ static int __init cpufreq_read_arg_max_oc0(char *max_oc0) @@ -126,6 +127,24 @@ static int __init cpufreq_read_arg_max_oc3(char *max_oc3) } __setup("max_oc3=", cpufreq_read_arg_max_oc3); +/* boot arg min_clock */ +static int __init cpufreq_read_arg_min_clock(char *min_clock) +{ + unsigned long idle_khz; + int err; + err = strict_strtoul(min_clock, 0, &idle_khz); + if (err) { + arg_min_clock = 384000; + printk(KERN_INFO "[glitch]: min_clock='%i'\n", arg_min_clock); + return 1; + } + + arg_min_clock = idle_khz; + + return 0; +} +__setup("min_clock=", cpufreq_read_arg_min_clock); + static int __init get_uv_level(char *vdd_uv) { if (strcmp(vdd_uv, "0") == 0) { @@ -1085,13 +1104,15 @@ static void __init cpufreq_table_init(void) int cpu; uint32_t limit_max_oc[4] = {arg_max_oc0, arg_max_oc1, arg_max_oc2, arg_max_oc3}; + uint32_t limit_min_clock = arg_min_clock; for_each_possible_cpu(cpu) { int i, freq_cnt = 0; /* Construct the freq_table tables from acpu_freq_tbl. */ for (i = 0; drv.acpu_freq_tbl[i].speed.khz != 0 && freq_cnt < ARRAY_SIZE(*freq_table); i++) { - if (drv.acpu_freq_tbl[i].speed.khz <= limit_max_oc[cpu]) { + if (drv.acpu_freq_tbl[i].speed.khz <= limit_max_oc[cpu] + && drv.acpu_freq_tbl[i].speed.khz >= limit_min_clock) { freq_table[cpu][freq_cnt].index = freq_cnt; freq_table[cpu][freq_cnt].frequency = drv.acpu_freq_tbl[i].speed.khz; @@ -1191,34 +1212,39 @@ static void krait_apply_vmin(struct acpu_level *tbl) static void apply_undervolting(void) { + int i; + + for (i = 0; drv.acpu_freq_tbl[i].speed.khz <= arg_min_clock; i++) { + if (uv_bin == 6) { - drv.acpu_freq_tbl[0].vdd_core = 725000; - printk(KERN_INFO "[glitch]: min_voltage='%i'\n", drv.acpu_freq_tbl[0].vdd_core ); + drv.acpu_freq_tbl[i].vdd_core = (drv.acpu_freq_tbl[i].vdd_core - 175000); + printk(KERN_INFO "[glitch]: min_voltage='%i'\n", drv.acpu_freq_tbl[i].vdd_core ); } if (uv_bin == 5) { - drv.acpu_freq_tbl[0].vdd_core = 750000; - printk(KERN_INFO "[glitch]: min_voltage='%i'\n", drv.acpu_freq_tbl[0].vdd_core ); + drv.acpu_freq_tbl[i].vdd_core = (drv.acpu_freq_tbl[i].vdd_core - 150000); + printk(KERN_INFO "[glitch]: min_voltage='%i'\n", drv.acpu_freq_tbl[i].vdd_core ); } if (uv_bin == 4) { - drv.acpu_freq_tbl[0].vdd_core = 775000; - printk(KERN_INFO "[glitch]: min_voltage='%i'\n", drv.acpu_freq_tbl[0].vdd_core ); + drv.acpu_freq_tbl[i].vdd_core = (drv.acpu_freq_tbl[i].vdd_core - 125000); + printk(KERN_INFO "[glitch]: min_voltage='%i'\n", drv.acpu_freq_tbl[i].vdd_core ); } if (uv_bin == 3) { - drv.acpu_freq_tbl[0].vdd_core = 800000; - printk(KERN_INFO "[glitch]: min_voltage='%i'\n", drv.acpu_freq_tbl[0].vdd_core ); + drv.acpu_freq_tbl[i].vdd_core = (drv.acpu_freq_tbl[i].vdd_core - 100000); + printk(KERN_INFO "[glitch]: min_voltage='%i'\n", drv.acpu_freq_tbl[i].vdd_core ); } if (uv_bin == 2) { - drv.acpu_freq_tbl[0].vdd_core = 825000; - printk(KERN_INFO "[glitch]: min_voltage='%i'\n", drv.acpu_freq_tbl[0].vdd_core ); + drv.acpu_freq_tbl[i].vdd_core = (drv.acpu_freq_tbl[i].vdd_core - 75000); + printk(KERN_INFO "[glitch]: min_voltage='%i'\n", drv.acpu_freq_tbl[i].vdd_core ); } if (uv_bin == 1) { - drv.acpu_freq_tbl[0].vdd_core = 850000; - printk(KERN_INFO "[glitch]: min_voltage='%i'\n", drv.acpu_freq_tbl[0].vdd_core ); + drv.acpu_freq_tbl[i].vdd_core = (drv.acpu_freq_tbl[i].vdd_core - 50000); + printk(KERN_INFO "[glitch]: min_voltage='%i'\n", drv.acpu_freq_tbl[i].vdd_core); + } } } diff --git a/release/aroma/META-INF/com/google/android/aroma-config b/release/aroma/META-INF/com/google/android/aroma-config index 700a1f8311e..e6d06bd5f7c 100755 --- a/release/aroma/META-INF/com/google/android/aroma-config +++ b/release/aroma/META-INF/com/google/android/aroma-config @@ -79,15 +79,15 @@ alert( selectbox( "Keep your Glitch settings ?","New user? Coming back? Already using this kernel?\n","@personalize","glitched.prop", "I want to make a complete installation, please.","(wipes previous Glitch settings if any)",1, - "I'm already Glitch'd you know, just try to keep my settings, thx.","",0 + "I'm already Glitch'd, just try to keep my settings, thx.","",0 ); if file_getprop("/tmp/aroma/glitched.prop","selected.0") == "1" then checkbox( "Advanced personnalization","Select all the settings to tweak next. Unticked means stock settings will be applied.\n","@personalize","glitch.prop", - "CPU/BUS OC & uV settings","Max CPU/BUS clock and 162MHz frequency uV",1, - "Minimum CPU frequency","Lower for more battery life, higher for smooth audio on screen off.",1, + "CPU/BUS OC","Max CPU/BUS clock and 162MHz frequency uV",1, + "Minimum CPU frequency & uV","Lower for more battery life, higher for smooth audio on screen off.",1, "Hotplug driver","CPU cores management.",1, "Thermal settings","Temperature treshold before downclocking.",1, "GPU settings","Max GPU clock, governor, uV.",1, @@ -96,7 +96,23 @@ checkbox( ); endif; -if file_getprop("/tmp/aroma/glitched.prop","selected.0") == "2" || file_getprop("/tmp/aroma/glitch.prop","item.0.1") == "1" +if file_getprop("/tmp/aroma/glitched.prop","selected.0") == "2" +then +alert( + "WARNING:", + "You MUST already have either Glitch kernel installed and running on this device or a backup of your settings on your SDcard root. Else, stock settings will be enforced.", + "@alert", + "OK" +); + +checkbox( + "Glitched already ?","You may want to reinstall optimized libraries or restore your settings. Tick what you want.\n","@personalize","galready.prop", + "Install/Restore Qualcomm optimized libraries","In case of rom update. Safe to overwrite.",1, + "Restore your settings from SDcard","If you have a glitch-settings.conf backup from a previous installation (on SDcard root)",0 +); +endif; + +if file_getprop("/tmp/aroma/glitch.prop","item.0.1") == "1" then selectbox( "Set each CPU core separately","If you say yes here you will have the option to set the max freq for each core individually\n","@personalize","cpuopt.prop", @@ -196,7 +212,7 @@ selectbox( endif; selectbox( - "Select CPU optimization level","Overclocks L2 cache and bus bandwidth. If you experience instability, choose stock\n","@personalize","opt.prop", + "Select CPU optimization level","Overclocks L2 cache and bus bandwidth. If you experience instability, choose a lower value\n","@personalize","opt.prop", "stock","(1.13GHz-4.26GBps)",0, "improved","(1.19GHz-4.26GBps)",1, "balanced","(1.22GHz-4.66GBps)",0, @@ -204,22 +220,8 @@ selectbox( "extreme","(1.43GHz-4.80GBps)",0, "glitchy","(1.49GHz-4.96GBps)",0 ); - -selectbox( - "Auto Undervolting","Lowers the voltage for the lowest cpu frequency (162MHz). Undervolting may cause instability.\n","@personalize","uv.prop", - "Stock (950 min)","",0, - "Undervolt (850 min)","",1, - "Undervolt (825 min)","",0, - "Undervolt (800 min)","",0, - "Undervolt (775 min)","",0, - "Undervolt (750 min)","",0, - "Undervolt (725 min)","",0 -); endif; -if file_getprop("/tmp/aroma/glitched.prop","selected.0") == "1" -then - if file_getprop("/tmp/aroma/glitch.prop","item.0.2") == "1" then @@ -231,6 +233,17 @@ selectbox( "594MHz","",0, "810MHz","",0 ); + +selectbox( + "Auto Undervolting","Lowers the voltage for the lowest cpu frequency you just set. Undervolting may cause instability.\n","@personalize","uv.prop", + "No undervolting","(Stock)",0, + "Undervolt -50 mV","",1, + "Undervolt -75 mV","",0, + "Undervolt -100 mV","",0, + "Undervolt -125 mV","",0, + "Undervolt -150 mV","",0, + "Undervolt -175 mV","",0 +); endif; if file_getprop("/tmp/aroma/glitch.prop","item.0.3") == "1" @@ -338,18 +351,6 @@ checkbox( ); endif; -endif; - -if file_getprop("/tmp/aroma/glitched.prop","selected.0") == "2" -then -alert( - "WARNING:", - "You MUST already have Glitch kernel installed and running on this device or default settings will be enforced !", - "@alert", - "OK" -); -endif; - menubox( "Glitch Kernel Installer", "Ready to install", diff --git a/release/aroma/META-INF/com/google/android/updater-script b/release/aroma/META-INF/com/google/android/updater-script index 312b58f42c0..cc986df86b1 100755 --- a/release/aroma/META-INF/com/google/android/updater-script +++ b/release/aroma/META-INF/com/google/android/updater-script @@ -373,6 +373,15 @@ run_program("/tmp/buildconfig.sh"); run_program("/tmp/busybox", "cp", "/tmp/glitch-settings.conf", "/system/etc/glitch-settings.conf"); set_perm(0, 0, 0666, "/system/etc/glitch-settings.conf"); +package_extract_dir("boot", "/tmp"); +set_perm(0, 0, 0777, "/tmp/max_oc.sh"); +set_perm(0, 0, 0777, "/tmp/edit_ramdisk.sh"); +set_perm(0, 0, 0777, "/tmp/abootimg"); + +ui_print("Applying init settings"); +run_program("/tmp/busybox", "dd", "if=/dev/block/mmcblk0p14", "of=/tmp/boot.img"); +run_program("/tmp/abootimg", "-x", "/tmp/boot.img", "/tmp/bootimg.cfg", "/tmp/zImage", "/tmp/initrd.img"); +run_program("/tmp/max_oc.sh"); endif; if @@ -389,27 +398,46 @@ ui_print("Installing system files to be a good boy."); package_extract_dir("system", "/system"); set_perm_recursive(0, 0, 0644, 0644, "/system/lib/modules"); +if + file_getprop("/tmp/aroma/galready.prop","item.0.2") == "1" + then + ui_print("Pray Cthulhu to get your settings backup in place.."); + ui_print("He may need another reboot to do it as your device is too fast now !"); +run_program("/tmp/busybox", "cp", "/tmp/restore.plz", "/system/etc/restore.plz"); +set_perm(0, 0, 0666, "/system/etc/restore.plz"); +endif; + ui_print("Do some useless cleaning in case something didn't went wrong..."); delete("/system/lib/modules/cpufreq_limit.ko"); delete("/system/lib/modules/scsi_wait_scan.ko"); -ui_print("Try not to destroy your old settings.. too much."); - set_perm(0, 0, 0777, "/tmp/systemcheck.sh"); run_program("/tmp/systemcheck.sh"); +if + file_getprop("/tmp/aroma/galready.prop","item.0.1") == "1" + then + ui_print("Optimize some stuff because it's nice."); +package_extract_dir("qo_db", "/system"); +set_perm(0, 2000, 0755, "/system/bin/dexopt"); +set_perm(0, 2000, 0755, "/system/bin/dalvikvm"); endif; -set_progress(0.6); +ui_print("Try not to destroy your other settings.. too much."); package_extract_dir("boot", "/tmp"); -set_perm(0, 0, 0777, "/tmp/max_oc.sh"); +set_perm(0, 0, 0777, "/tmp/restore.sh"); set_perm(0, 0, 0777, "/tmp/edit_ramdisk.sh"); set_perm(0, 0, 0777, "/tmp/abootimg"); run_program("/tmp/busybox", "dd", "if=/dev/block/mmcblk0p14", "of=/tmp/boot.img"); run_program("/tmp/abootimg", "-x", "/tmp/boot.img", "/tmp/bootimg.cfg", "/tmp/zImage", "/tmp/initrd.img"); -run_program("/tmp/max_oc.sh"); +run_program("/tmp/restore.sh"); + +endif; + +set_progress(0.6); + run_program("/tmp/edit_ramdisk.sh"); run_program("/tmp/abootimg", "-u", "/tmp/boot.img", "-f", "/tmp/cmdline.cfg", "-k", "/tmp/glitch.zImage", "-r", "/tmp/initrd.img"); diff --git a/release/aroma/boot/max_oc.sh b/release/aroma/boot/max_oc.sh index faf5c1763f0..32d297a27cd 100755 --- a/release/aroma/boot/max_oc.sh +++ b/release/aroma/boot/max_oc.sh @@ -184,10 +184,31 @@ case $val3 in ;; esac -#set optimization level -val4=$(cat /tmp/aroma-data/opt.prop | cut -d '=' -f2) +#set min_clock +val4=$(cat /tmp/aroma-data/minfreq.prop | cut -d '=' -f2) case $val4 in + 1) + min_clock="min_clock=162000" + ;; + 2) + min_clock="min_clock=270000" + ;; + 3) + min_clock="min_clock=384000" + ;; + 4) + min_clock="min_clock=594000" + ;; + 5) + min_clock="min_clock=810000" + ;; +esac + +#set optimization level +val5=$(cat /tmp/aroma-data/opt.prop | cut -d '=' -f2) + +case $val5 in 1) l2_opt="l2_opt=0" ;; @@ -209,9 +230,9 @@ case $val4 in esac #set undervolting -val7=$(cat /tmp/aroma-data/uv.prop | cut -d '=' -f2) +val6=$(cat /tmp/aroma-data/uv.prop | cut -d '=' -f2) -case $val7 in +case $val6 in 1) vdd_uv="vdd_uv=0" ;; @@ -237,4 +258,4 @@ esac null="abc" -echo "cmdline = console=ttyHSL0,115200,n8 androidboot.hardware=flo user_debug=31 msm_rtb.filter=0x3F ehci-hcd.park=3" $l2_opt $vdd_uv $max_oc0 $max_oc1 $max_oc2 $max_oc3 $null >> /tmp/cmdline.cfg +echo "cmdline = console=ttyHSL0,115200,n8 androidboot.hardware=flo user_debug=31 msm_rtb.filter=0x3F ehci-hcd.park=3" $l2_opt $vdd_uv $max_oc0 $max_oc1 $max_oc2 $max_oc3 $min_clock $null >> /tmp/cmdline.cfg diff --git a/release/aroma/boot/restore.sh b/release/aroma/boot/restore.sh new file mode 100644 index 00000000000..af584efab40 --- /dev/null +++ b/release/aroma/boot/restore.sh @@ -0,0 +1,19 @@ +#!/sbin/sh + +# Read the settings file +if [ -f "/system/etc/glitch-settings.conf" ]; +then +. /system/etc/glitch-settings.conf + +$l2_opt = "l2_opt="$L2_OC; +$vdd_uv = "vdd_uv="$UV_LEVEL; +$min_clock = "min_clock="($MINF * 1000); +$max_oc0 = "max_oc0="($MAXF_CPU0 * 1000); +$max_oc1 = "max_oc1="($MAXF_CPU1 * 1000); +$max_oc2 = "max_oc2="($MAXF_CPU2 * 1000); +$max_oc3 = "max_oc3="($MAXF_CPU3 * 1000); + +null="abc" + +echo "cmdline = console=ttyHSL0,115200,n8 androidboot.hardware=flo user_debug=31 msm_rtb.filter=0x3F ehci-hcd.park=3" $l2_opt $vdd_uv $max_oc0 $max_oc1 $max_oc2 $max_oc3 $min_clock $null >> /tmp/cmdline.cfg +fi diff --git a/release/aroma/config/buildconfig.sh b/release/aroma/config/buildconfig.sh index 50353e1323f..7ddee84ec4d 100755 --- a/release/aroma/config/buildconfig.sh +++ b/release/aroma/config/buildconfig.sh @@ -2,28 +2,15 @@ #Build config file CONFIGFILE="/tmp/glitch-settings.conf" +RESTORE_BACKUP="/tmp/restore.plz" -#MINFREQ -if [ -f "/tmp/aroma/minfreq.prop" ]; +#Restore SDcard backup +if [ -f "/tmp/aroma/galready.prop" ]; then -MINF=`cat /tmp/aroma/minfreq.prop | cut -d '=' -f2` -echo -e "\n\n##### Minimum frequency #####\n# 1 162 MHz" >> $CONFIGFILE -echo -e "# 2 270 MHz\n# 3 384 MHz (stock)\n# 4 594 MHz\n# 5 810 MHz\n" >> $CONFIGFILE -if [ $MINF = 1 ]; then - echo "MINF=1" >> $CONFIGFILE; -elif [ $MINF = 2 ]; then - echo "MINF=2" >> $CONFIGFILE; -elif [ $MINF = 4 ]; then - echo "MINF=4" >> $CONFIGFILE; -elif [ $MINF = 5 ]; then - echo "MINF=5" >> $CONFIGFILE; -else - echo "MINF=3" >> $CONFIGFILE; +RESTORE=`grep "item.0.2" /tmp/aroma/galready.prop | cut -d '=' -f2` +if [ $RESTORE = 1 ]; then + echo "RESTORE MY BACKUP PLZ" >> $RESTORE_BACKUP; fi -else -echo -e "\n\n##### Minimum frequency #####\n# 1 162 MHz" >> $CONFIGFILE -echo -e "# 2 270 MHz\n# 3 384 MHz (stock)\n# 4 594 MHz\n# 5 810 MHz\n" >> $CONFIGFILE -echo "MINF=3" >> $CONFIGFILE; fi #HOTPLUGDRV @@ -223,7 +210,7 @@ if [ -f "/tmp/aroma/gpuclock.prop" ]; then GPU_OC=`cat /tmp/aroma/gpuclock.prop | cut -d '=' -f2` echo -e "\n\n##### Max GPU Clock #####\n# 1 320 MHz" >> $CONFIGFILE -echo -e "# 2 400 MHz\n# 3 450 MHz\n# 4 504MHz\n# 5 545 MHz\n# 6 600 MHz\n# 7 627 MHz\n" >> $CONFIGFILE +echo -e "# 2 400 MHz\n# 3 450 MHz\n# 4 504 MHz\n# 5 545 MHz\n# 6 600 MHz\n# 7 627 MHz\n" >> $CONFIGFILE if [ $GPU_OC = 1 ]; then echo "GPU_OC=1" >> $CONFIGFILE; elif [ $GPU_OC = 3 ]; then @@ -241,7 +228,7 @@ else fi else echo -e "\n\n##### Max GPU Clock #####\n# 1 320 MHz" >> $CONFIGFILE -echo -e "# 2 400 MHz\n# 3 450 MHz\n# 4 504MHz\n# 5 545 MHz\n# 6 600 MHz\n# 7 627 MHz\n" >> $CONFIGFILE +echo -e "# 2 400 MHz\n# 3 450 MHz\n# 4 504 MHz\n# 5 545 MHz\n# 6 600 MHz\n# 7 627 MHz\n" >> $CONFIGFILE echo "GPU_OC=2" >> $CONFIGFILE; fi @@ -310,5 +297,230 @@ echo -e "# 2 4.2V (balanced - 93%)\n# 3 4.1V (conservative - 83%)\n# 4 4.0V (ver echo "BLE=1" >> $CONFIGFILE; fi +echo -e "\n\n##############################################################" >> $CONFIGFILE +echo -e "\n\n!!! Don't edit past this unless you know what you're doing !!!" >> $CONFIGFILE +echo -e " These are a backup of initialization settings " >> $CONFIGFILE +echo -e "\n\n##############################################################" >> $CONFIGFILE + +if [ ! -e /tmp/aroma-data/freq1.prop ]; then + cp /tmp/aroma-data/freq0.prop /tmp/aroma-data/freq1.prop; + cp /tmp/aroma-data/freq0.prop /tmp/aroma-data/freq2.prop; + cp /tmp/aroma-data/freq0.prop /tmp/aroma-data/freq3.prop; +fi + +#MAXFREQ +if [ -f "/tmp/aroma/freq0.prop" ]; +then +MAXF_CPU0=`cat /tmp/aroma/freq0.prop | cut -d '=' -f2` +echo -e "\n\n##### Maximum CPU0 frequency (MHz) #####\n" >> $CONFIGFILE +if [ $MAXF_CPU0 = 2 ]; then + echo "MAXF_CPU0=1620" >> $CONFIGFILE; +elif [ $MAXF_CPU0 = 3 ]; then + echo "MAXF_CPU0=1728" >> $CONFIGFILE; +elif [ $MAXF_CPU0 = 4 ]; then + echo "MAXF_CPU0=1836" >> $CONFIGFILE; +elif [ $MAXF_CPU0 = 5 ]; then + echo "MAXF_CPU0=1890" >> $CONFIGFILE; +elif [ $MAXF_CPU0 = 6 ]; then + echo "MAXF_CPU0=1944" >> $CONFIGFILE; +elif [ $MAXF_CPU0 = 7 ]; then + echo "MAXF_CPU0=1998" >> $CONFIGFILE; +elif [ $MAXF_CPU0 = 8 ]; then + echo "MAXF_CPU0=2052" >> $CONFIGFILE; +elif [ $MAXF_CPU0 = 9 ]; then + echo "MAXF_CPU0=2106" >> $CONFIGFILE; +elif [ $MAXF_CPU0 = 10 ]; then + echo "MAXF_CPU0=2160" >> $CONFIGFILE; +elif [ $MAXF_CPU0 = 11 ]; then + echo "MAXF_CPU0=2214" >> $CONFIGFILE; +elif [ $MAXF_CPU0 = 12 ]; then + echo "MAXF_CPU0=2268" >> $CONFIGFILE; +elif [ $MAXF_CPU0 = 13 ]; then + echo "MAXF_CPU0=2322" >> $CONFIGFILE; +else + echo "MAXF_CPU0=1512" >> $CONFIGFILE; +fi +else +echo -e "\n\n##### Maximum CPU0 frequency (MHz) #####\n" >> $CONFIGFILE +echo "MAXF_CPU0=1512" >> $CONFIGFILE; +fi + +if [ -f "/tmp/aroma/freq1.prop" ]; +then +MAXF_CPU1=`cat /tmp/aroma/freq1.prop | cut -d '=' -f2` +echo -e "\n\n##### Maximum CPU1 frequency (MHz) #####\n" >> $CONFIGFILE +if [ $MAXF_CPU1 = 2 ]; then + echo "MAXF_CPU1=1620" >> $CONFIGFILE; +elif [ $MAXF_CPU1 = 3 ]; then + echo "MAXF_CPU1=1728" >> $CONFIGFILE; +elif [ $MAXF_CPU1 = 4 ]; then + echo "MAXF_CPU1=1836" >> $CONFIGFILE; +elif [ $MAXF_CPU1 = 5 ]; then + echo "MAXF_CPU1=1890" >> $CONFIGFILE; +elif [ $MAXF_CPU1 = 6 ]; then + echo "MAXF_CPU1=1944" >> $CONFIGFILE; +elif [ $MAXF_CPU1 = 7 ]; then + echo "MAXF_CPU1=1998" >> $CONFIGFILE; +elif [ $MAXF_CPU1 = 8 ]; then + echo "MAXF_CPU1=2052" >> $CONFIGFILE; +elif [ $MAXF_CPU1 = 9 ]; then + echo "MAXF_CPU1=2106" >> $CONFIGFILE; +elif [ $MAXF_CPU1 = 10 ]; then + echo "MAXF_CPU1=2160" >> $CONFIGFILE; +elif [ $MAXF_CPU1 = 11 ]; then + echo "MAXF_CPU1=2214" >> $CONFIGFILE; +elif [ $MAXF_CPU1 = 12 ]; then + echo "MAXF_CPU1=2268" >> $CONFIGFILE; +elif [ $MAXF_CPU1 = 13 ]; then + echo "MAXF_CPU1=2322" >> $CONFIGFILE; +else + echo "MAXF_CPU1=1512" >> $CONFIGFILE; +fi +else +echo -e "\n\n##### Maximum CPU1 frequency (MHz) #####\n" >> $CONFIGFILE +echo "MAXF_CPU1=1512" >> $CONFIGFILE; +fi + +if [ -f "/tmp/aroma/freq2.prop" ]; +then +MAXF_CPU2=`cat /tmp/aroma/freq2.prop | cut -d '=' -f2` +echo -e "\n\n##### Maximum CPU2 frequency (MHz) #####\n" >> $CONFIGFILE +if [ $MAXF_CPU2 = 2 ]; then + echo "MAXF_CPU2=1620" >> $CONFIGFILE; +elif [ $MAXF_CPU2 = 3 ]; then + echo "MAXF_CPU2=1728" >> $CONFIGFILE; +elif [ $MAXF_CPU2 = 4 ]; then + echo "MAXF_CPU2=1836" >> $CONFIGFILE; +elif [ $MAXF_CPU2 = 5 ]; then + echo "MAXF_CPU2=1890" >> $CONFIGFILE; +elif [ $MAXF_CPU2 = 6 ]; then + echo "MAXF_CPU2=1944" >> $CONFIGFILE; +elif [ $MAXF_CPU2 = 7 ]; then + echo "MAXF_CPU2=1998" >> $CONFIGFILE; +elif [ $MAXF_CPU2 = 8 ]; then + echo "MAXF_CPU2=2052" >> $CONFIGFILE; +elif [ $MAXF_CPU2 = 9 ]; then + echo "MAXF_CPU2=2106" >> $CONFIGFILE; +elif [ $MAXF_CPU2 = 10 ]; then + echo "MAXF_CPU2=2160" >> $CONFIGFILE; +elif [ $MAXF_CPU2 = 11 ]; then + echo "MAXF_CPU2=2214" >> $CONFIGFILE; +elif [ $MAXF_CPU2 = 12 ]; then + echo "MAXF_CPU2=2268" >> $CONFIGFILE; +elif [ $MAXF_CPU2 = 13 ]; then + echo "MAXF_CPU2=2322" >> $CONFIGFILE; +else + echo "MAXF_CPU2=1512" >> $CONFIGFILE; +fi +else +echo -e "\n\n##### Maximum CPU2 frequency (MHz) #####\n" >> $CONFIGFILE +echo "MAXF_CPU2=1512" >> $CONFIGFILE; +fi + +if [ -f "/tmp/aroma/freq3.prop" ]; +then +MAXF_CPU3=`cat /tmp/aroma/freq3.prop | cut -d '=' -f2` +echo -e "\n\n##### Maximum CPU3 frequency (MHz) #####\n" >> $CONFIGFILE +if [ $MAXF_CPU3 = 2 ]; then + echo "MAXF_CPU3=1620" >> $CONFIGFILE; +elif [ $MAXF_CPU3 = 3 ]; then + echo "MAXF_CPU3=1728" >> $CONFIGFILE; +elif [ $MAXF_CPU3 = 4 ]; then + echo "MAXF_CPU3=1836" >> $CONFIGFILE; +elif [ $MAXF_CPU3 = 5 ]; then + echo "MAXF_CPU3=1890" >> $CONFIGFILE; +elif [ $MAXF_CPU3 = 6 ]; then + echo "MAXF_CPU3=1944" >> $CONFIGFILE; +elif [ $MAXF_CPU3 = 7 ]; then + echo "MAXF_CPU3=1998" >> $CONFIGFILE; +elif [ $MAXF_CPU3 = 8 ]; then + echo "MAXF_CPU3=2052" >> $CONFIGFILE; +elif [ $MAXF_CPU3 = 9 ]; then + echo "MAXF_CPU3=2106" >> $CONFIGFILE; +elif [ $MAXF_CPU3 = 10 ]; then + echo "MAXF_CPU3=2160" >> $CONFIGFILE; +elif [ $MAXF_CPU3 = 11 ]; then + echo "MAXF_CPU3=2214" >> $CONFIGFILE; +elif [ $MAXF_CPU3 = 12 ]; then + echo "MAXF_CPU3=2268" >> $CONFIGFILE; +elif [ $MAXF_CPU3 = 13 ]; then + echo "MAXF_CPU3=2322" >> $CONFIGFILE; +else + echo "MAXF_CPU3=1512" >> $CONFIGFILE; +fi +else +echo -e "\n\n##### Maximum CPU3 frequency (MHz) #####\n" >> $CONFIGFILE +echo "MAXF_CPU3=1512" >> $CONFIGFILE; +fi + +#MINFREQ +if [ -f "/tmp/aroma/minfreq.prop" ]; +then +MINF=`cat /tmp/aroma/minfreq.prop | cut -d '=' -f2` +echo -e "\n\n##### Minimum CPU frequency (MHz) #####\n" >> $CONFIGFILE +if [ $MINF = 1 ]; then + echo "MINF=162" >> $CONFIGFILE; +elif [ $MINF = 2 ]; then + echo "MINF=270" >> $CONFIGFILE; +elif [ $MINF = 4 ]; then + echo "MINF=595" >> $CONFIGFILE; +elif [ $MINF = 5 ]; then + echo "MINF=810" >> $CONFIGFILE; +else + echo "MINF=384" >> $CONFIGFILE; +fi +else +echo -e "\n\n##### Minimum CPU frequency (MHz) #####\n" >> $CONFIGFILE +echo "MINF=384" >> $CONFIGFILE; +fi + +#UV +if [ -f "/tmp/aroma/uv.prop" ]; +then +UV_LEVEL=`cat /tmp/aroma/uv.prop | cut -d '=' -f2` +echo -e "\n\n##### Level of uV to apply to min frequency #####\n" >> $CONFIGFILE +if [ $UV_LEVEL = 2 ]; then + echo "UV_LEVEL=1" >> $CONFIGFILE; +elif [ $UV_LEVEL = 3 ]; then + echo "UV_LEVEL=2" >> $CONFIGFILE; +elif [ $UV_LEVEL = 4 ]; then + echo "UV_LEVEL=3" >> $CONFIGFILE; +elif [ $UV_LEVEL = 5 ]; then + echo "UV_LEVEL=4" >> $CONFIGFILE; +elif [ $UV_LEVEL = 6 ]; then + echo "UV_LEVEL=5" >> $CONFIGFILE; +elif [ $UV_LEVEL = 7 ]; then + echo "UV_LEVEL=6" >> $CONFIGFILE; +else + echo "UV_LEVEL=0" >> $CONFIGFILE; +fi +else +echo -e "\n\n##### Level of uV to apply to min frequency #####\n" >> $CONFIGFILE +echo "UV_LEVEL=0" >> $CONFIGFILE; +fi + +#L2/CACHE OC +if [ -f "/tmp/aroma/opt.prop" ]; +then +L2_OC=`cat /tmp/aroma/opt.prop | cut -d '=' -f2` +echo -e "\n\n##### L2/cache OC settings #####\n" >> $CONFIGFILE +if [ $L2_OC = 2 ]; then + echo "L2_OC=1" >> $CONFIGFILE; +elif [ $L2_OC = 3 ]; then + echo "L2_OC=2" >> $CONFIGFILE; +elif [ $L2_OC = 4 ]; then + echo "L2_OC=3" >> $CONFIGFILE; +elif [ $L2_OC = 5 ]; then + echo "L2_OC=4" >> $CONFIGFILE; +elif [ $L2_OC = 6 ]; then + echo "L2_OC=5" >> $CONFIGFILE; +else + echo "L2_OC=0" >> $CONFIGFILE; +fi +else +echo -e "\n\n##### Level of uV to apply to min frequency #####\n" >> $CONFIGFILE +echo "L2_OC=0" >> $CONFIGFILE; +fi + echo -e "\n\n##############################" >> $CONFIGFILE #END diff --git a/release/aroma/config/restore.plz b/release/aroma/config/restore.plz new file mode 100644 index 00000000000..e4fee92461e --- /dev/null +++ b/release/aroma/config/restore.plz @@ -0,0 +1 @@ +Please Cthulhu ! Get my Glitch settings back from my SDcard ! diff --git a/release/aroma/system/etc/init.d/99glitch b/release/aroma/system/etc/init.d/99glitch index 9395dc805ed..ec52ffa565a 100755 --- a/release/aroma/system/etc/init.d/99glitch +++ b/release/aroma/system/etc/init.d/99glitch @@ -9,6 +9,14 @@ fi echo $(date) >> $KERNEL_LOGFILE +#Restore settings from sdcard +if [ -f "/system/etc/restore.plz" ]; +then + cp /sdcard/glitch-settings.conf /system/etc/glitch-settings.conf + echo "Your SDcard backup has been restored. You may need to reboot." >> $KERNEL_LOGFILE; + rm /system/etc/restore.plz +fi + #Max CPU_FREQ MAXF="`cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq`" echo $MAXF > /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq; @@ -18,37 +26,12 @@ echo $MAXF > /sys/devices/system/cpu/cpu3/cpufreq/scaling_max_freq; echo Max CPU Frequency: $MAXF >> $KERNEL_LOGFILE #Min CPU_FREQ -if [ "`grep MINF=1 $KERNEL_CONF`" ]; then -echo 162000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq; -echo 162000 > /sys/devices/system/cpu/cpu1/cpufreq/scaling_min_freq; -echo 162000 > /sys/devices/system/cpu/cpu2/cpufreq/scaling_min_freq; -echo 162000 > /sys/devices/system/cpu/cpu3/cpufreq/scaling_min_freq; -echo Min CPU Frequency: 162000 >> $KERNEL_LOGFILE -elif [ "`grep MINF=2 $KERNEL_CONF`" ]; then -echo 270000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq; -echo 270000 > /sys/devices/system/cpu/cpu1/cpufreq/scaling_min_freq; -echo 270000 > /sys/devices/system/cpu/cpu2/cpufreq/scaling_min_freq; -echo 270000 > /sys/devices/system/cpu/cpu3/cpufreq/scaling_min_freq; -echo Min CPU Frequency: 270000 >> $KERNEL_LOGFILE -elif [ "`grep MINF=4 $KERNEL_CONF`" ]; then -echo 594000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq; -echo 594000 > /sys/devices/system/cpu/cpu1/cpufreq/scaling_min_freq; -echo 594000 > /sys/devices/system/cpu/cpu2/cpufreq/scaling_min_freq; -echo 594000 > /sys/devices/system/cpu/cpu3/cpufreq/scaling_min_freq; -echo Min CPU Frequency: 594000 >> $KERNEL_LOGFILE -elif [ "`grep MINF=5 $KERNEL_CONF`" ]; then -echo 810000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq; -echo 810000 > /sys/devices/system/cpu/cpu1/cpufreq/scaling_min_freq; -echo 810000 > /sys/devices/system/cpu/cpu2/cpufreq/scaling_min_freq; -echo 810000 > /sys/devices/system/cpu/cpu3/cpufreq/scaling_min_freq; -echo Min CPU Frequency: 810000 >> $KERNEL_LOGFILE -else -echo 384000 > /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq; -echo 384000 > /sys/devices/system/cpu/cpu1/cpufreq/scaling_min_freq; -echo 384000 > /sys/devices/system/cpu/cpu2/cpufreq/scaling_min_freq; -echo 384000 > /sys/devices/system/cpu/cpu3/cpufreq/scaling_min_freq; -echo Min CPU Frequency: 384000 >> $KERNEL_LOGFILE -fi +MINF="`cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_min_freq`" +echo $MINF > /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq; +echo $MINF > /sys/devices/system/cpu/cpu1/cpufreq/scaling_min_freq; +echo $MINF > /sys/devices/system/cpu/cpu2/cpufreq/scaling_min_freq; +echo $MINF > /sys/devices/system/cpu/cpu3/cpufreq/scaling_min_freq; +echo Min CPU Frequency: $MINF >> $KERNEL_LOGFILE #Set HOTPLUGDRV if [ "`grep HOTPLUGDRV=1 $KERNEL_CONF`" ]; then @@ -241,4 +224,8 @@ fi insmod /system/lib/modules/exfat.ko echo exFAT module loaded >> $KERNEL_LOGFILE; +#Backup settings to sdcard + cp /system/etc/glitch-settings.conf /sdcard/glitch-settings.conf + echo "A backup of your settings has been created on sdcard root" >> $KERNEL_LOGFILE; + exit 0 From 61fd004461cd6d5892e1386d66713602a2f70956 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Thu, 30 Jan 2014 04:18:23 +0100 Subject: [PATCH 200/215] Aroma : This doesn't apply anymore. --- release/aroma/META-INF/com/google/android/aroma-config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release/aroma/META-INF/com/google/android/aroma-config b/release/aroma/META-INF/com/google/android/aroma-config index e6d06bd5f7c..2bea7066345 100755 --- a/release/aroma/META-INF/com/google/android/aroma-config +++ b/release/aroma/META-INF/com/google/android/aroma-config @@ -86,7 +86,7 @@ if file_getprop("/tmp/aroma/glitched.prop","selected.0") == "1" then checkbox( "Advanced personnalization","Select all the settings to tweak next. Unticked means stock settings will be applied.\n","@personalize","glitch.prop", - "CPU/BUS OC","Max CPU/BUS clock and 162MHz frequency uV",1, + "CPU/BUS OC","Max CPU and bus clocks",1, "Minimum CPU frequency & uV","Lower for more battery life, higher for smooth audio on screen off.",1, "Hotplug driver","CPU cores management.",1, "Thermal settings","Temperature treshold before downclocking.",1, From 610b5b4011d00989018949c9a53380a68ca8bbf8 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Thu, 30 Jan 2014 04:20:13 +0100 Subject: [PATCH 201/215] Aroma : Copy/paste fail --- release/aroma/config/buildconfig.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release/aroma/config/buildconfig.sh b/release/aroma/config/buildconfig.sh index 7ddee84ec4d..d4f35fef3dc 100755 --- a/release/aroma/config/buildconfig.sh +++ b/release/aroma/config/buildconfig.sh @@ -518,7 +518,7 @@ else echo "L2_OC=0" >> $CONFIGFILE; fi else -echo -e "\n\n##### Level of uV to apply to min frequency #####\n" >> $CONFIGFILE +echo -e "\n\n##### L2/cache OC settings #####\n" >> $CONFIGFILE echo "L2_OC=0" >> $CONFIGFILE; fi From 987f9c0c4eff9a821bdcfc8b30330cf1a9165c0a Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Thu, 30 Jan 2014 04:24:33 +0100 Subject: [PATCH 202/215] Aroma : fix permissions after backup restoration. --- release/aroma/system/etc/init.d/99glitch | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/release/aroma/system/etc/init.d/99glitch b/release/aroma/system/etc/init.d/99glitch index ec52ffa565a..1178a83aed2 100755 --- a/release/aroma/system/etc/init.d/99glitch +++ b/release/aroma/system/etc/init.d/99glitch @@ -12,7 +12,8 @@ echo $(date) >> $KERNEL_LOGFILE #Restore settings from sdcard if [ -f "/system/etc/restore.plz" ]; then - cp /sdcard/glitch-settings.conf /system/etc/glitch-settings.conf + cp /sdcard/glitch-settings.conf /system/etc/glitch-settings.conf + chmod 666 /system/etc/glitch-settings.conf echo "Your SDcard backup has been restored. You may need to reboot." >> $KERNEL_LOGFILE; rm /system/etc/restore.plz fi From e3348edd022e68283d0bc627254dd8cc1e3d6243 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Fri, 31 Jan 2014 22:13:03 +0100 Subject: [PATCH 203/215] Aroma : More features Signed-off-by: Tk-Glitch Conflicts: release/aroma/META-INF/com/google/android/updater-script --- .../META-INF/com/google/android/aroma-config | 36 ++++++- .../com/google/android/updater-script | 97 ++++++++++++++++++- release/aroma/config/buildconfig.sh | 88 +++++++++++++++++ release/aroma/system/etc/init.d/99glitch | 93 +++++++++++++++--- 4 files changed, 297 insertions(+), 17 deletions(-) diff --git a/release/aroma/META-INF/com/google/android/aroma-config b/release/aroma/META-INF/com/google/android/aroma-config index 2bea7066345..3bfae19bbd5 100755 --- a/release/aroma/META-INF/com/google/android/aroma-config +++ b/release/aroma/META-INF/com/google/android/aroma-config @@ -91,6 +91,7 @@ checkbox( "Hotplug driver","CPU cores management.",1, "Thermal settings","Temperature treshold before downclocking.",1, "GPU settings","Max GPU clock, governor, uV.",1, + "Advanced settings","CPU governor, I/O scheduler, Read-ahead buffer.",1, "S2W/S2S/DT2W","Sweep to wake/sleep, Double tap to wake.",1, "Misc settings","BLE, OTG+charge hack, input-boost, etc.",1 ); @@ -300,6 +301,36 @@ endif; if file_getprop("/tmp/aroma/glitch.prop","item.0.6") == "1" then +selectbox( + "CPU governor","Select the CPU frequency scaling driver\n","@personalize","cpugov.prop", + "ondemand","(stock)",1, + "interactive","",0, + "intellidemand","",0, + "smartmax","",0 +); + +selectbox( + "I/O scheduler","Select the I/O scheduling mechanism.\n","@personalize","iosched.prop", + "cfq","(stock)",0, + "row","",1, + "deadline","",0, + "fiops","",0, + "sio","",0, + "noop","",0 +); + +selectbox( + "Read-ahead","Select the read-ahead buffer size.\n","@personalize","readahead.prop", + "128 KB","(stock)",0, + "256 KB","",1, + "512 KB","",0, + "1024 KB","",0, + "2048 KB","",0 +); +endif; + +if file_getprop("/tmp/aroma/glitch.prop","item.0.7") == "1" +then checkbox( "S2W/S2S/DT2W settings","Select the mods you want to enable\n","@personalize","S2WS.prop", "Sweep2Wake","Sweep across buttons to sleep/wake device",0, @@ -331,7 +362,7 @@ selectbox( ); endif; -if file_getprop("/tmp/aroma/glitch.prop","item.0.7") == "1" +if file_getprop("/tmp/aroma/glitch.prop","item.0.8") == "1" then selectbox( "Battery life eXtender settings","Sets the charge voltage of the battery to extend its lifespan\n","@personalize","ble.prop", @@ -347,7 +378,8 @@ checkbox( "Enable USB OTG+Charge mode","Allows charging in USB host mode (disables self-powered OTG)",0, "Enable input-boost","Improves smoothness with kernel-side hotplug drivers",1, "Enable Gentle Fair Sleepers","Disable for UI smoothness, but more battery consumption (enabled by default)",1, - "Install Qualcomm optimized Dalvik/Bionic","Boost performances using Qualcomm-optimized libraries",1 + "Install Qualcomm optimized Dalvik/Bionic","Boost performances using Qualcomm-optimized libraries",1, + "Force USB fast-charge","Always charge in AC mode",0 ); endif; diff --git a/release/aroma/META-INF/com/google/android/updater-script b/release/aroma/META-INF/com/google/android/updater-script index cc986df86b1..ab8ccec4ff9 100755 --- a/release/aroma/META-INF/com/google/android/updater-script +++ b/release/aroma/META-INF/com/google/android/updater-script @@ -221,6 +221,96 @@ if ui_print("-150mV GPU uV"); endif; +if + file_getprop("/tmp/aroma/cpugov.prop","selected.0") == "1" + then + ui_print("Ondemand CPU governor"); +endif; + +if + file_getprop("/tmp/aroma/cpugov.prop","selected.0") == "2" + then + ui_print("Interactive CPU governor"); +endif; + +if + file_getprop("/tmp/aroma/cpugov.prop","selected.0") == "3" + then + ui_print("Intelli-demand CPU governor"); +endif; + +if + file_getprop("/tmp/aroma/cpugov.prop","selected.0") == "4" + then + ui_print("SmartMax CPU governor"); +endif; + +if + file_getprop("/tmp/aroma/iosched.prop","selected.0") == "1" + then + ui_print("CFQ ioscheduler"); +endif; + +if + file_getprop("/tmp/aroma/iosched.prop","selected.0") == "2" + then + ui_print("ROW ioscheduler"); +endif; + +if + file_getprop("/tmp/aroma/iosched.prop","selected.0") == "3" + then + ui_print("DEADLINE ioscheduler"); +endif; + +if + file_getprop("/tmp/aroma/iosched.prop","selected.0") == "4" + then + ui_print("FIOPS ioscheduler"); +endif; + +if + file_getprop("/tmp/aroma/iosched.prop","selected.0") == "5" + then + ui_print("SIO ioscheduler"); +endif; + +if + file_getprop("/tmp/aroma/iosched.prop","selected.0") == "6" + then + ui_print("NOOP ioscheduler"); +endif; + +if + file_getprop("/tmp/aroma/readahead.prop","selected.0") == "1" + then + ui_print("128KB read-ahead buffer"); +endif; + +if + file_getprop("/tmp/aroma/readahead.prop","selected.0") == "2" + then + ui_print("256KB read-ahead buffer"); +endif; + +if + file_getprop("/tmp/aroma/readahead.prop","selected.0") == "3" + then + ui_print("512KB read-ahead buffer"); +endif; + +if + file_getprop("/tmp/aroma/readahead.prop","selected.0") == "4" + then + ui_print("1024KB read-ahead buffer"); +endif; + +if + file_getprop("/tmp/aroma/readahead.prop","selected.0") == "5" + then + ui_print("2048KB read-ahead buffer"); +endif; + if file_getprop("/tmp/aroma/ble.prop","selected.0") == "1" then @@ -299,6 +389,12 @@ if ui_print("Gentle Fair Sleepers enabled"); endif; +if + file_getprop("/tmp/aroma/misc.prop","item.0.6") == "1" + then + ui_print("Force fast-charge enabled"); +endif; + set_progress(0.3); @@ -402,7 +498,6 @@ if file_getprop("/tmp/aroma/galready.prop","item.0.2") == "1" then ui_print("Pray Cthulhu to get your settings backup in place.."); - ui_print("He may need another reboot to do it as your device is too fast now !"); run_program("/tmp/busybox", "cp", "/tmp/restore.plz", "/system/etc/restore.plz"); set_perm(0, 0, 0666, "/system/etc/restore.plz"); endif; diff --git a/release/aroma/config/buildconfig.sh b/release/aroma/config/buildconfig.sh index d4f35fef3dc..950ce28d0d5 100755 --- a/release/aroma/config/buildconfig.sh +++ b/release/aroma/config/buildconfig.sh @@ -276,6 +276,94 @@ echo -e "# 3 -50mV\n# 4 -75mV\n# 5 -100mV\n# 6 -125mV\n# 7 -150mV\n" >> $CONFIGF echo "GPU_UV=1" >> $CONFIGFILE; fi +#CPU governor +if [ -f "/tmp/aroma/cpugov.prop" ]; +then +CPU_GOV=`cat /tmp/aroma/cpugov.prop | cut -d '=' -f2` +echo -e "\n\n##### CPU governor #####\n# 1 ondemand (stock)" >> $CONFIGFILE +echo -e "# 2 interactive\n# 3 intellidemand\n# 4 smartmax\n" >> $CONFIGFILE +if [ $CPU_GOV = 2 ]; then + echo "CPU_GOV=2" >> $CONFIGFILE; +elif [ $CPU_GOV = 3 ]; then + echo "CPU_GOV=3" >> $CONFIGFILE; +elif [ $CPU_GOV = 4 ]; then + echo "CPU_GOV=4" >> $CONFIGFILE; +else + echo "CPU_GOV=1" >> $CONFIGFILE; +fi +else +echo -e "\n\n##### CPU governor #####\n# 1 ondemand (stock)" >> $CONFIGFILE +echo -e "# 2 interactive\n# 3 intellidemand\n# 4 smartmax\n" >> $CONFIGFILE +echo "CPU_GOV=1" >> $CONFIGFILE; +fi + +#I/O scheduler +if [ -f "/tmp/aroma/iosched.prop" ]; +then +IOSCHED=`cat /tmp/aroma/iosched.prop | cut -d '=' -f2` +echo -e "\n\n##### I/O scheduler #####\n# 1 cfq (stock)\n# 2 row" >> $CONFIGFILE +echo -e "# 3 deadline\n# 4 fiops\n# 5 sio# 6 noop\n" >> $CONFIGFILE +if [ $IOSCHED = 2 ]; then + echo "IOSCHED=2" >> $CONFIGFILE; +elif [ $IOSCHED = 3 ]; then + echo "IOSCHED=3" >> $CONFIGFILE; +elif [ $IOSCHED = 4 ]; then + echo "IOSCHED=4" >> $CONFIGFILE; +elif [ $IOSCHED = 5 ]; then + echo "IOSCHED=5" >> $CONFIGFILE; +elif [ $IOSCHED = 6 ]; then + echo "IOSCHED=6" >> $CONFIGFILE; +else + echo "IOSCHED=1" >> $CONFIGFILE; +fi +else +echo -e "\n\n##### I/O scheduler #####\n# 1 cfq (stock)\n# 2 row" >> $CONFIGFILE +echo -e "# 3 deadline\n# 4 fiops\n# 5 sio# 6 noop\n" >> $CONFIGFILE +echo "IOSCHED=1" >> $CONFIGFILE; +fi + +#read-ahead +if [ -f "/tmp/aroma/readahead.prop" ]; +then +READAHEAD=`cat /tmp/aroma/readahead.prop | cut -d '=' -f2` +echo -e "\n\n##### Read-ahead buffer size (KB) #####\n# 1 128 (stock)\n# 2 256" >> $CONFIGFILE +echo -e "# 3 512\n# 4 1024\n# 5 2048\n" >> $CONFIGFILE +if [ $READAHEAD = 2 ]; then + echo "READAHEAD=2" >> $CONFIGFILE; +elif [ $READAHEAD = 3 ]; then + echo "READAHEAD=3" >> $CONFIGFILE; +elif [ $READAHEAD = 4 ]; then + echo "READAHEAD=4" >> $CONFIGFILE; +elif [ $READAHEAD = 5 ]; then + echo "READAHEAD=5" >> $CONFIGFILE; +elif [ $READAHEAD = 6 ]; then + echo "READAHEAD=6" >> $CONFIGFILE; +else + echo "READAHEAD=1" >> $CONFIGFILE; +fi +else +echo -e "\n\n##### Read-ahead buffer size (KB) #####\n# 1 128 (stock)\n# 2 256" >> $CONFIGFILE +echo -e "# 3 512\n# 4 1024\n# 5 2048\n" >> $CONFIGFILE +echo "READAHEAD=1" >> $CONFIGFILE; +fi + +#Fast Charge +if [ -f "/tmp/aroma/misc.prop" ]; +then +FAST_CHARGE=`grep "item.0.6" /tmp/aroma/misc.prop | cut -d '=' -f2` +echo -e "\n\n##### Force fast-charge Settings #####\n# 0 to disable fast-charge" >> $CONFIGFILE +echo -e "# 1 to enable fast-charge\n" >> $CONFIGFILE +if [ $FAST_CHARGE = 1 ]; then + echo "FAST_CHARGE=1" >> $CONFIGFILE; +else + echo "FAST_CHARGE=0" >> $CONFIGFILE; +fi +else +echo -e "\n\n##### Force fast-charge Settings #####\n# 0 to disable fast-charge" >> $CONFIGFILE +echo -e "# 1 to enable fast-charge\n" >> $CONFIGFILE +echo "FAST_CHARGE=0" >> $CONFIGFILE; +fi + #Battery life extender if [ -f "/tmp/aroma/ble.prop" ]; then diff --git a/release/aroma/system/etc/init.d/99glitch b/release/aroma/system/etc/init.d/99glitch index 1178a83aed2..778d8ec464d 100755 --- a/release/aroma/system/etc/init.d/99glitch +++ b/release/aroma/system/etc/init.d/99glitch @@ -1,13 +1,13 @@ #!/system/bin/sh -KERNEL_CONF="/system/etc/glitch-settings.conf" -KERNEL_LOGFILE="/data/local/tmp/glitch-kernel.log" +KERNEL_CONF="/system/etc/glitch-settings.conf"; +KERNEL_LOGFILE="/data/local/tmp/glitch-kernel.log"; if [ -f $KERNEL_LOGFILE ]; then mv $KERNEL_LOGFILE $KERNEL_LOGFILE.2; fi -echo $(date) >> $KERNEL_LOGFILE +echo $(date) >> $KERNEL_LOGFILE; #Restore settings from sdcard if [ -f "/system/etc/restore.plz" ]; @@ -24,7 +24,7 @@ echo $MAXF > /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq; echo $MAXF > /sys/devices/system/cpu/cpu1/cpufreq/scaling_max_freq; echo $MAXF > /sys/devices/system/cpu/cpu2/cpufreq/scaling_max_freq; echo $MAXF > /sys/devices/system/cpu/cpu3/cpufreq/scaling_max_freq; -echo Max CPU Frequency: $MAXF >> $KERNEL_LOGFILE +echo Max CPU Frequency: $MAXF >> $KERNEL_LOGFILE; #Min CPU_FREQ MINF="`cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_min_freq`" @@ -32,7 +32,55 @@ echo $MINF > /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq; echo $MINF > /sys/devices/system/cpu/cpu1/cpufreq/scaling_min_freq; echo $MINF > /sys/devices/system/cpu/cpu2/cpufreq/scaling_min_freq; echo $MINF > /sys/devices/system/cpu/cpu3/cpufreq/scaling_min_freq; -echo Min CPU Frequency: $MINF >> $KERNEL_LOGFILE +echo Min CPU Frequency: $MINF >> $KERNEL_LOGFILE; + +#I/O scheduler +if [ "`grep IOSCHED=1 $KERNEL_CONF`" ]; then +echo "cfq" > /sys/block/mmcblk0/queue/scheduler; +echo io scheduler: cfq >> $KERNEL_LOGFILE; +elif [ "`grep IOSCHED=2 $KERNEL_CONF`" ]; then +echo "row" > /sys/block/mmcblk0/queue/scheduler; +echo io scheduler: row >> $KERNEL_LOGFILE; +elif [ "`grep IOSCHED=3 $KERNEL_CONF`" ]; then +echo "deadline" > /sys/block/mmcblk0/queue/scheduler; +echo io scheduler: deadline >> $KERNEL_LOGFILE; +elif [ "`grep IOSCHED=4 $KERNEL_CONF`" ]; then +echo "fiops" > /sys/block/mmcblk0/queue/scheduler; +echo io scheduler: fiops >> $KERNEL_LOGFILE; +elif [ "`grep IOSCHED=5 $KERNEL_CONF`" ]; then +echo "sio" > /sys/block/mmcblk0/queue/scheduler; +echo io scheduler: sio >> $KERNEL_LOGFILE; +elif [ "`grep IOSCHED=6 $KERNEL_CONF`" ]; then +echo "noop" > /sys/block/mmcblk0/queue/scheduler; +echo io scheduler: noop >> $KERNEL_LOGFILE; +fi + +#Read-ahead +if [ "`grep READAHEAD=1 $KERNEL_CONF`" ]; then +echo 128 > /sys/block/mmcblk0/queue/read_ahead_kb; +echo Read-ahead: 128 >> $KERNEL_LOGFILE; +elif [ "`grep READAHEAD=2 $KERNEL_CONF`" ]; then +echo 256 > /sys/block/mmcblk0/queue/read_ahead_kb; +echo Read-ahead: 256 >> $KERNEL_LOGFILE; +elif [ "`grep READAHEAD=3 $KERNEL_CONF`" ]; then +echo 512 > /sys/block/mmcblk0/queue/read_ahead_kb; +echo Read-ahead: 512 >> $KERNEL_LOGFILE; +elif [ "`grep READAHEAD=4 $KERNEL_CONF`" ]; then +echo 1024 > /sys/block/mmcblk0/queue/read_ahead_kb; +echo Read-ahead: 1024 >> $KERNEL_LOGFILE; +elif [ "`grep READAHEAD=5 $KERNEL_CONF`" ]; then +echo 2048 > /sys/block/mmcblk0/queue/read_ahead_kb; +echo Read-ahead: 2048 >> $KERNEL_LOGFILE; +fi + +#FAST CHARGE +if [ "`grep FAST_CHARGE=1 $KERNEL_CONF`" ]; then + echo 1 > /sys/kernel/fast_charge/force_fast_charge; + echo fast charge enabled >> $KERNEL_LOGFILE; +else + echo 0 > /sys/kernel/fast_charge/force_fast_charge; + echo fast charge disabled >> $KERNEL_LOGFILE; +fi #Set HOTPLUGDRV if [ "`grep HOTPLUGDRV=1 $KERNEL_CONF`" ]; then @@ -134,8 +182,8 @@ else fi #fstrim -fstrim -v /cache | tee -a $KERNEL_LOGFILE; -fstrim -v /data | tee -a $KERNEL_LOGFILE; +fstrim -v /cache | tee -a $KERNEL_LOGFILE +fstrim -v /data | tee -a $KERNEL_LOGFILE #thermal settings if [ "`grep THERM=1 $KERNEL_CONF`" ]; then @@ -208,25 +256,42 @@ fi #Battery life extender if [ "`grep BLE=2 $KERNEL_CONF`" ]; then - echo 4200 > /sys/devices/i2c-0/0-006a/float_voltage + echo 4200 > /sys/devices/i2c-0/0-006a/float_voltage; echo 4.2V charge voltage >> $KERNEL_LOGFILE; elif [ "`grep BLE=3 $KERNEL_CONF`" ]; then - echo 4100 > /sys/devices/i2c-0/0-006a/float_voltage + echo 4100 > /sys/devices/i2c-0/0-006a/float_voltage; echo 4.1V charge voltage >> $KERNEL_LOGFILE; elif [ "`grep BLE=4 $KERNEL_CONF`" ]; then - echo 4000 > /sys/devices/i2c-0/0-006a/float_voltage + echo 4000 > /sys/devices/i2c-0/0-006a/float_voltage; echo 4.0V charge voltage >> $KERNEL_LOGFILE; else - echo 4300 > /sys/devices/i2c-0/0-006a/float_voltage + echo 4300 > /sys/devices/i2c-0/0-006a/float_voltage; echo Stock charge voltage >> $KERNEL_LOGFILE; fi #exFAT support - insmod /system/lib/modules/exfat.ko + insmod /system/lib/modules/exfat.ko; echo exFAT module loaded >> $KERNEL_LOGFILE; #Backup settings to sdcard - cp /system/etc/glitch-settings.conf /sdcard/glitch-settings.conf - echo "A backup of your settings has been created on sdcard root" >> $KERNEL_LOGFILE; + cp /system/etc/glitch-settings.conf /sdcard/glitch-settings.conf; + echo "Settings backup created on sdcard root" >> $KERNEL_LOGFILE; + +#Wait a bit before applying governor changes +sleep 30 + +#CPU governor +if [ "`grep CPU_GOV=2 $KERNEL_CONF`" ]; then + echo "interactive" > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor; + echo CPU Governor: interactive >> $KERNEL_LOGFILE; +elif [ "`grep CPU_GOV=3 $KERNEL_CONF`" ]; then + echo "intellidemand" > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor; + echo CPU Governor: intellidemand >> $KERNEL_LOGFILE; +elif [ "`grep CPU_GOV=4 $KERNEL_CONF`" ]; then + echo "smartmax" > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor; + echo CPU Governor: smartmax >> $KERNEL_LOGFILE; +else + echo CPU Governor: ondemand >> $KERNEL_LOGFILE; +fi exit 0 From 5223e7787c9ea7dcef7cc1376e2236ef521a35c9 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Thu, 30 Jan 2014 19:07:59 +0100 Subject: [PATCH 204/215] Aroma : Fix syntax of a few things, fix permissions, add a check for hotplug driver so it's restored as well. Conflicts: release/aroma/META-INF/com/google/android/updater-script --- .../com/google/android/updater-script | 6 +- release/aroma/boot/restore.sh | 42 +++++-- release/aroma/config/buildconfig.sh | 110 ++++++++++-------- release/aroma/config/restore.plz | 1 - release/aroma/system/etc/init.d/99glitch | 9 -- 5 files changed, 101 insertions(+), 67 deletions(-) delete mode 100644 release/aroma/config/restore.plz diff --git a/release/aroma/META-INF/com/google/android/updater-script b/release/aroma/META-INF/com/google/android/updater-script index ab8ccec4ff9..262ff1cdd4b 100755 --- a/release/aroma/META-INF/com/google/android/updater-script +++ b/release/aroma/META-INF/com/google/android/updater-script @@ -492,14 +492,16 @@ run_program("/tmp/busybox", "mount", "/system"); ui_print("Installing system files to be a good boy."); package_extract_dir("system", "/system"); +set_perm_recursive(0, 2000, 0777, 0777, "/system/etc/init.d/99glitch"); set_perm_recursive(0, 0, 0644, 0644, "/system/lib/modules"); +set_perm_recursive(0, 2000, 0755, 0755, "/system/bin/fstrim"); if file_getprop("/tmp/aroma/galready.prop","item.0.2") == "1" then ui_print("Pray Cthulhu to get your settings backup in place.."); -run_program("/tmp/busybox", "cp", "/tmp/restore.plz", "/system/etc/restore.plz"); -set_perm(0, 0, 0666, "/system/etc/restore.plz"); +run_program("/tmp/busybox", "cp", "/sdcard/glitch-settings.conf", "/system/etc/glitch-settings.conf"); +set_perm(0, 0, 0666, "/system/etc/glitch-settings.conf"); endif; ui_print("Do some useless cleaning in case something didn't went wrong..."); diff --git a/release/aroma/boot/restore.sh b/release/aroma/boot/restore.sh index af584efab40..3146835a515 100644 --- a/release/aroma/boot/restore.sh +++ b/release/aroma/boot/restore.sh @@ -3,17 +3,45 @@ # Read the settings file if [ -f "/system/etc/glitch-settings.conf" ]; then + . /system/etc/glitch-settings.conf -$l2_opt = "l2_opt="$L2_OC; -$vdd_uv = "vdd_uv="$UV_LEVEL; -$min_clock = "min_clock="($MINF * 1000); -$max_oc0 = "max_oc0="($MAXF_CPU0 * 1000); -$max_oc1 = "max_oc1="($MAXF_CPU1 * 1000); -$max_oc2 = "max_oc2="($MAXF_CPU2 * 1000); -$max_oc3 = "max_oc3="($MAXF_CPU3 * 1000); +if [ "$HOTPLUGDRV" == "0" ] ; then +if [ -e /system/bin/mpdecision_bck ] ; then +busybox mv /system/bin/mpdecision_bck /system/bin/mpdecision +fi +fi + +if [ "$HOTPLUGDRV" == "1" ] ; then +if [ -e /system/bin/mpdecision ] ; then +busybox mv /system/bin/mpdecision /system/bin/mpdecision_bck +fi +fi + +if [ "$HOTPLUGDRV" == "2" ] ; then +if [ -e /system/bin/mpdecision ] ; then +busybox mv /system/bin/mpdecision /system/bin/mpdecision_bck +fi +fi + +if [ -e /system/bin/thermald ] ; then +busybox mv /system/bin/thermald /system/bin/thermald_bck +fi + +l2_opt="l2_opt="$L2_OC; +vdd_uv="vdd_uv="$UV_LEVEL; +min_clock="min_clock="$MINF"000"; +max_oc0="max_oc0="$MAXF_CPU0"000"; +max_oc1="max_oc1="$MAXF_CPU1"000"; +max_oc2="max_oc2="$MAXF_CPU2"000"; +max_oc3="max_oc3="$MAXF_CPU3"000"; null="abc" echo "cmdline = console=ttyHSL0,115200,n8 androidboot.hardware=flo user_debug=31 msm_rtb.filter=0x3F ehci-hcd.park=3" $l2_opt $vdd_uv $max_oc0 $max_oc1 $max_oc2 $max_oc3 $min_clock $null >> /tmp/cmdline.cfg + +else + +echo "glitch-settings.conf file not found. If you have one, please restore your backup from SDcard or do a complete installation."; + fi diff --git a/release/aroma/config/buildconfig.sh b/release/aroma/config/buildconfig.sh index 950ce28d0d5..dde3ae5d487 100755 --- a/release/aroma/config/buildconfig.sh +++ b/release/aroma/config/buildconfig.sh @@ -2,35 +2,6 @@ #Build config file CONFIGFILE="/tmp/glitch-settings.conf" -RESTORE_BACKUP="/tmp/restore.plz" - -#Restore SDcard backup -if [ -f "/tmp/aroma/galready.prop" ]; -then -RESTORE=`grep "item.0.2" /tmp/aroma/galready.prop | cut -d '=' -f2` -if [ $RESTORE = 1 ]; then - echo "RESTORE MY BACKUP PLZ" >> $RESTORE_BACKUP; -fi -fi - -#HOTPLUGDRV -if [ -f "/tmp/aroma/hotplug.prop" ]; -then -HOTPLUGDRV=`cat /tmp/aroma/hotplug.prop | cut -d '=' -f2` -echo -e "\n\n##### Hotplug driver Settings #####\n# 0 to enable qualcomm mpdecision (stock)" >> $CONFIGFILE -echo -e "# 1 to enable msm_mpdecision (recommended)\n# 2 to enable intelli-plug\n" >> $CONFIGFILE -if [ $HOTPLUGDRV = 2 ]; then - echo "HOTPLUGDRV=1" >> $CONFIGFILE; -elif [ $HOTPLUGDRV = 3 ]; then - echo "HOTPLUGDRV=2" >> $CONFIGFILE; -else - echo "HOTPLUGDRV=0" >> $CONFIGFILE; -fi -else -echo -e "\n\n##### Hotplug driver Settings #####\n# 0 to enable qualcomm mpdecision (stock)" >> $CONFIGFILE -echo -e "# 1 to enable msm_mpdecision (recommended)\n# 2 to enable intelli-plug\n" >> $CONFIGFILE -echo "HOTPLUGDRV=0" >> $CONFIGFILE; -fi #S2W if [ -f "/tmp/aroma/S2WS.prop" ]; @@ -385,10 +356,12 @@ echo -e "# 2 4.2V (balanced - 93%)\n# 3 4.1V (conservative - 83%)\n# 4 4.0V (ver echo "BLE=1" >> $CONFIGFILE; fi -echo -e "\n\n##############################################################" >> $CONFIGFILE -echo -e "\n\n!!! Don't edit past this unless you know what you're doing !!!" >> $CONFIGFILE -echo -e " These are a backup of initialization settings " >> $CONFIGFILE -echo -e "\n\n##############################################################" >> $CONFIGFILE +echo -e "\n\n####################################################################" >> $CONFIGFILE +echo -e "# Anything past this is a backup of your initialization settings #" >> $CONFIGFILE +echo -e "# for Aroma Installer to restore them if asked. #" >> $CONFIGFILE +echo -e "# Edit these lines only if you're planning to reinstall the kernel #" >> $CONFIGFILE +echo -e "# and restore settings, as they won't be applied outside of Aroma. #" >> $CONFIGFILE +echo -e "####################################################################\n\n" >> $CONFIGFILE if [ ! -e /tmp/aroma-data/freq1.prop ]; then cp /tmp/aroma-data/freq0.prop /tmp/aroma-data/freq1.prop; @@ -400,7 +373,9 @@ fi if [ -f "/tmp/aroma/freq0.prop" ]; then MAXF_CPU0=`cat /tmp/aroma/freq0.prop | cut -d '=' -f2` -echo -e "\n\n##### Maximum CPU0 frequency (MHz) #####\n" >> $CONFIGFILE +echo -e "\n\n##### Maximum CPU0 frequency (MHz) #####" >> $CONFIGFILE +echo -e "1512, 1620, 1728, 1836, 1890, 1944, 1998" >> $CONFIGFILE; +echo -e "2052, 2106, 2160, 2214, 2268, 2322\n" >> $CONFIGFILE; if [ $MAXF_CPU0 = 2 ]; then echo "MAXF_CPU0=1620" >> $CONFIGFILE; elif [ $MAXF_CPU0 = 3 ]; then @@ -429,14 +404,18 @@ else echo "MAXF_CPU0=1512" >> $CONFIGFILE; fi else -echo -e "\n\n##### Maximum CPU0 frequency (MHz) #####\n" >> $CONFIGFILE +echo -e "\n\n##### Maximum CPU0 frequency (MHz) #####" >> $CONFIGFILE +echo -e "1512, 1620, 1728, 1836, 1890, 1944, 1998" >> $CONFIGFILE; +echo -e "2052, 2106, 2160, 2214, 2268, 2322\n" >> $CONFIGFILE; echo "MAXF_CPU0=1512" >> $CONFIGFILE; fi if [ -f "/tmp/aroma/freq1.prop" ]; then MAXF_CPU1=`cat /tmp/aroma/freq1.prop | cut -d '=' -f2` -echo -e "\n\n##### Maximum CPU1 frequency (MHz) #####\n" >> $CONFIGFILE +echo -e "\n\n##### Maximum CPU1 frequency (MHz) #####" >> $CONFIGFILE +echo -e "1512, 1620, 1728, 1836, 1890, 1944, 1998" >> $CONFIGFILE; +echo -e "2052, 2106, 2160, 2214, 2268, 2322\n" >> $CONFIGFILE; if [ $MAXF_CPU1 = 2 ]; then echo "MAXF_CPU1=1620" >> $CONFIGFILE; elif [ $MAXF_CPU1 = 3 ]; then @@ -465,14 +444,18 @@ else echo "MAXF_CPU1=1512" >> $CONFIGFILE; fi else -echo -e "\n\n##### Maximum CPU1 frequency (MHz) #####\n" >> $CONFIGFILE +echo -e "\n\n##### Maximum CPU1 frequency (MHz) #####" >> $CONFIGFILE +echo -e "1512, 1620, 1728, 1836, 1890, 1944, 1998" >> $CONFIGFILE; +echo -e "2052, 2106, 2160, 2214, 2268, 2322\n" >> $CONFIGFILE; echo "MAXF_CPU1=1512" >> $CONFIGFILE; fi if [ -f "/tmp/aroma/freq2.prop" ]; then MAXF_CPU2=`cat /tmp/aroma/freq2.prop | cut -d '=' -f2` -echo -e "\n\n##### Maximum CPU2 frequency (MHz) #####\n" >> $CONFIGFILE +echo -e "\n\n##### Maximum CPU2 frequency (MHz) #####" >> $CONFIGFILE +echo -e "1512, 1620, 1728, 1836, 1890, 1944, 1998" >> $CONFIGFILE; +echo -e "2052, 2106, 2160, 2214, 2268, 2322\n" >> $CONFIGFILE; if [ $MAXF_CPU2 = 2 ]; then echo "MAXF_CPU2=1620" >> $CONFIGFILE; elif [ $MAXF_CPU2 = 3 ]; then @@ -490,7 +473,7 @@ elif [ $MAXF_CPU2 = 8 ]; then elif [ $MAXF_CPU2 = 9 ]; then echo "MAXF_CPU2=2106" >> $CONFIGFILE; elif [ $MAXF_CPU2 = 10 ]; then - echo "MAXF_CPU2=2160" >> $CONFIGFILE; + echo "MAXF_CPU2=2160'" >> $CONFIGFILE; elif [ $MAXF_CPU2 = 11 ]; then echo "MAXF_CPU2=2214" >> $CONFIGFILE; elif [ $MAXF_CPU2 = 12 ]; then @@ -501,14 +484,18 @@ else echo "MAXF_CPU2=1512" >> $CONFIGFILE; fi else -echo -e "\n\n##### Maximum CPU2 frequency (MHz) #####\n" >> $CONFIGFILE +echo -e "\n\n##### Maximum CPU2 frequency (MHz) #####" >> $CONFIGFILE +echo -e "1512, 1620, 1728, 1836, 1890, 1944, 1998" >> $CONFIGFILE; +echo -e "2052, 2106, 2160, 2214, 2268, 2322\n" >> $CONFIGFILE; echo "MAXF_CPU2=1512" >> $CONFIGFILE; fi if [ -f "/tmp/aroma/freq3.prop" ]; then MAXF_CPU3=`cat /tmp/aroma/freq3.prop | cut -d '=' -f2` -echo -e "\n\n##### Maximum CPU3 frequency (MHz) #####\n" >> $CONFIGFILE +echo -e "\n\n##### Maximum CPU3 frequency (MHz) #####" >> $CONFIGFILE +echo -e "1512, 1620, 1728, 1836, 1890, 1944, 1998" >> $CONFIGFILE; +echo -e "2052, 2106, 2160, 2214, 2268, 2322\n" >> $CONFIGFILE; if [ $MAXF_CPU3 = 2 ]; then echo "MAXF_CPU3=1620" >> $CONFIGFILE; elif [ $MAXF_CPU3 = 3 ]; then @@ -537,7 +524,9 @@ else echo "MAXF_CPU3=1512" >> $CONFIGFILE; fi else -echo -e "\n\n##### Maximum CPU3 frequency (MHz) #####\n" >> $CONFIGFILE +echo -e "\n\n##### Maximum CPU3 frequency (MHz) #####" >> $CONFIGFILE +echo -e "1512, 1620, 1728, 1836, 1890, 1944, 1998" >> $CONFIGFILE; +echo -e "2052, 2106, 2160, 2214, 2268, 2322\n" >> $CONFIGFILE; echo "MAXF_CPU3=1512" >> $CONFIGFILE; fi @@ -545,7 +534,7 @@ fi if [ -f "/tmp/aroma/minfreq.prop" ]; then MINF=`cat /tmp/aroma/minfreq.prop | cut -d '=' -f2` -echo -e "\n\n##### Minimum CPU frequency (MHz) #####\n" >> $CONFIGFILE +echo -e "\n\n##### Minimum CPU frequency (MHz) ##### 162, 270, 595 or 810 are valid frequencies.\n" >> $CONFIGFILE if [ $MINF = 1 ]; then echo "MINF=162" >> $CONFIGFILE; elif [ $MINF = 2 ]; then @@ -558,7 +547,7 @@ else echo "MINF=384" >> $CONFIGFILE; fi else -echo -e "\n\n##### Minimum CPU frequency (MHz) #####\n" >> $CONFIGFILE +echo -e "\n\n##### Minimum CPU frequency (MHz) ##### 162, 270, 595 or 810 are valid frequencies.\n" >> $CONFIGFILE echo "MINF=384" >> $CONFIGFILE; fi @@ -566,7 +555,8 @@ fi if [ -f "/tmp/aroma/uv.prop" ]; then UV_LEVEL=`cat /tmp/aroma/uv.prop | cut -d '=' -f2` -echo -e "\n\n##### Level of uV to apply to min frequency #####\n" >> $CONFIGFILE +echo -e "\n\n##### Level of uV to apply to min frequency #####\n# 0 stock(no uV)\n# 1 -50 mV" >> $CONFIGFILE +echo -e "# 2 -75 mV\n# 3 -100 mV\n# 4 -125 mV\n# 5 -150 mV\n# 6 -175 mV\n" >> $CONFIGFILE if [ $UV_LEVEL = 2 ]; then echo "UV_LEVEL=1" >> $CONFIGFILE; elif [ $UV_LEVEL = 3 ]; then @@ -583,7 +573,8 @@ else echo "UV_LEVEL=0" >> $CONFIGFILE; fi else -echo -e "\n\n##### Level of uV to apply to min frequency #####\n" >> $CONFIGFILE +echo -e "\n\n##### Level of uV to apply to min frequency #####\n# 0 stock(no uV)\n# 1 -50 mV" >> $CONFIGFILE +echo -e "# 2 -75 mV\n# 3 -100 mV\n# 4 -125 mV\n# 5 -150 mV\n" >> $CONFIGFILE echo "UV_LEVEL=0" >> $CONFIGFILE; fi @@ -591,7 +582,9 @@ fi if [ -f "/tmp/aroma/opt.prop" ]; then L2_OC=`cat /tmp/aroma/opt.prop | cut -d '=' -f2` -echo -e "\n\n##### L2/cache OC settings #####\n" >> $CONFIGFILE +echo -e "\n\n##### L2/cache OC settings #####\n# 0 stock(1.13GHz-4.26GBps)\n# 1 improved(1.19GHz-4.26GBps)" >> $CONFIGFILE +echo -e "# 2 balanced(1.22GHz-4.66GBps)\n# 3 fast(1.35GHz-4.66GBps)\n# 4 extreme(1.43GHz-4.80GBps)" >> $CONFIGFILE +echo -e "# 5 glitchy(1.49GHz-4.96GBps)\n" >> $CONFIGFILE if [ $L2_OC = 2 ]; then echo "L2_OC=1" >> $CONFIGFILE; elif [ $L2_OC = 3 ]; then @@ -606,9 +599,30 @@ else echo "L2_OC=0" >> $CONFIGFILE; fi else -echo -e "\n\n##### L2/cache OC settings #####\n" >> $CONFIGFILE +echo -e "\n\n##### L2/cache OC settings #####\n# 0 stock(1.13GHz-4.26GBps)\n# 1 improved(1.19GHz-4.26GBps)" >> $CONFIGFILE +echo -e "# 2 balanced(1.22GHz-4.66GBps)\n# 3 fast(1.35GHz-4.66GBps)\n# 4 extreme(1.43GHz-4.80GBps)" >> $CONFIGFILE +echo -e "# 5 glitchy(1.49GHz-4.96GBps)\n" >> $CONFIGFILE echo "L2_OC=0" >> $CONFIGFILE; fi +#HOTPLUGDRV +if [ -f "/tmp/aroma/hotplug.prop" ]; +then +HOTPLUGDRV=`cat /tmp/aroma/hotplug.prop | cut -d '=' -f2` +echo -e "\n\n##### Hotplug driver Settings #####\n# 0 to enable qualcomm mpdecision (stock)" >> $CONFIGFILE +echo -e "# 1 to enable msm_mpdecision (recommended)\n# 2 to enable intelli-plug\n" >> $CONFIGFILE +if [ $HOTPLUGDRV = 2 ]; then + echo "HOTPLUGDRV=1" >> $CONFIGFILE; +elif [ $HOTPLUGDRV = 3 ]; then + echo "HOTPLUGDRV=2" >> $CONFIGFILE; +else + echo "HOTPLUGDRV=0" >> $CONFIGFILE; +fi +else +echo -e "\n\n##### Hotplug driver Settings #####\n# 0 to enable qualcomm mpdecision (stock)" >> $CONFIGFILE +echo -e "# 1 to enable msm_mpdecision (recommended)\n# 2 to enable intelli-plug\n" >> $CONFIGFILE +echo "HOTPLUGDRV=0" >> $CONFIGFILE; +fi + echo -e "\n\n##############################" >> $CONFIGFILE #END diff --git a/release/aroma/config/restore.plz b/release/aroma/config/restore.plz deleted file mode 100644 index e4fee92461e..00000000000 --- a/release/aroma/config/restore.plz +++ /dev/null @@ -1 +0,0 @@ -Please Cthulhu ! Get my Glitch settings back from my SDcard ! diff --git a/release/aroma/system/etc/init.d/99glitch b/release/aroma/system/etc/init.d/99glitch index 778d8ec464d..ca629e0d28d 100755 --- a/release/aroma/system/etc/init.d/99glitch +++ b/release/aroma/system/etc/init.d/99glitch @@ -9,15 +9,6 @@ fi echo $(date) >> $KERNEL_LOGFILE; -#Restore settings from sdcard -if [ -f "/system/etc/restore.plz" ]; -then - cp /sdcard/glitch-settings.conf /system/etc/glitch-settings.conf - chmod 666 /system/etc/glitch-settings.conf - echo "Your SDcard backup has been restored. You may need to reboot." >> $KERNEL_LOGFILE; - rm /system/etc/restore.plz -fi - #Max CPU_FREQ MAXF="`cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq`" echo $MAXF > /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq; From 489934ee925aa3a4044cdcc515097c1769b1abe0 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Fri, 31 Jan 2014 22:22:58 +0100 Subject: [PATCH 205/215] Aroma : END --- release/aroma/system/etc/init.d/99glitch | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/release/aroma/system/etc/init.d/99glitch b/release/aroma/system/etc/init.d/99glitch index ca629e0d28d..0c2fcc356f3 100755 --- a/release/aroma/system/etc/init.d/99glitch +++ b/release/aroma/system/etc/init.d/99glitch @@ -173,8 +173,8 @@ else fi #fstrim -fstrim -v /cache | tee -a $KERNEL_LOGFILE -fstrim -v /data | tee -a $KERNEL_LOGFILE +fstrim -v /cache | tee -a $KERNEL_LOGFILE; +fstrim -v /data | tee -a $KERNEL_LOGFILE; #thermal settings if [ "`grep THERM=1 $KERNEL_CONF`" ]; then From 142fcdd8fbc12fd7638341f68471224154eef461 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Sat, 1 Feb 2014 00:30:39 +0100 Subject: [PATCH 206/215] Add support for Flar2's MSM_SLEEPER (max screen off frequency). Add it to Aroma as well with presets. --- arch/arm/configs/flo_defconfig | 2 +- arch/arm/mach-msm/Kconfig | 6 ++ arch/arm/mach-msm/Makefile | 1 + arch/arm/mach-msm/cpufreq.c | 95 +++++++++++++++++++ arch/arm/mach-msm/msm-sleeper.c | 84 ++++++++++++++++ .../META-INF/com/google/android/aroma-config | 16 +++- .../com/google/android/updater-script | 6 ++ release/aroma/config/buildconfig.sh | 25 +++++ release/aroma/system/etc/init.d/99glitch | 21 ++++ 9 files changed, 254 insertions(+), 2 deletions(-) create mode 100644 arch/arm/mach-msm/msm-sleeper.c diff --git a/arch/arm/configs/flo_defconfig b/arch/arm/configs/flo_defconfig index 5b03841bae5..71e8e3b1288 100644 --- a/arch/arm/configs/flo_defconfig +++ b/arch/arm/configs/flo_defconfig @@ -464,6 +464,7 @@ CONFIG_MSM_IPC_ROUTER_SECURITY=y CONFIG_MSM_MPDEC=y CONFIG_MSM_MPDEC_INPUTBOOST_CPUMIN=y # CONFIG_MSM_CPU_FREQ_SET_MIN_MAX is not set +CONFIG_MSM_SLEEPER=y CONFIG_INTELLI_PLUG=y CONFIG_CPU_VOLTAGE_TABLE=y CONFIG_GPU_VOLTAGE_TABLE=y @@ -2803,7 +2804,6 @@ CONFIG_FB_MSM_OVERLAY1_WRITEBACK=y CONFIG_FB_MSM_MIPI_NOVATEK_VIDEO_MODE=y CONFIG_FB_MSM_MIPI_LG_VIDEO_MODE=y CONFIG_FB_MSM_MIPI_JDI_CMD_MODE=y -# CONFIG_FB_MSM_MIPI_LGIT_VIDEO_WXGA_PT_PANEL is not set CONFIG_FB_MSM_EXT_INTERFACE_COMMON=y CONFIG_FB_MSM_HDMI_COMMON=y CONFIG_FB_MSM_HDMI_3D=y diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig index e9987adb998..7987f41f7af 100644 --- a/arch/arm/mach-msm/Kconfig +++ b/arch/arm/mach-msm/Kconfig @@ -1639,6 +1639,12 @@ config MSM_CPU_FREQ_MIN endif # CPU_FREQ_MSM +config MSM_SLEEPER + bool "Limit max frequency while screen is off" + default y + help + Limit max frequency while screen is off + config INTELLI_PLUG bool "Enable intelli-plug cpu hotplug driver" default n diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile index 71105f75dde..5f2a1fca610 100644 --- a/arch/arm/mach-msm/Makefile +++ b/arch/arm/mach-msm/Makefile @@ -394,6 +394,7 @@ obj-$(CONFIG_MSM_RPM_SMD) += rpm-smd.o obj-$(CONFIG_MSM_CPR) += msm_cpr.o obj-$(CONFIG_MSM_VP_REGULATOR) += msm_vp.o obj-$(CONFIG_FORCE_FAST_CHARGE) += fastchg.o +obj-$(CONFIG_MSM_SLEEPER) += msm-sleeper.o ifdef CONFIG_MSM_CPR obj-$(CONFIG_DEBUG_FS) += msm_cpr-debug.o diff --git a/arch/arm/mach-msm/cpufreq.c b/arch/arm/mach-msm/cpufreq.c index 0e8e0cb8a90..60dff38b90a 100644 --- a/arch/arm/mach-msm/cpufreq.c +++ b/arch/arm/mach-msm/cpufreq.c @@ -32,6 +32,10 @@ #include "acpuclock.h" +/* maxscroff */ +uint32_t maxscroff_freq = 1026000; +uint32_t maxscroff = 1; + struct cpufreq_suspend_t { struct mutex suspend_mutex; int device_suspended; @@ -49,6 +53,22 @@ struct cpu_freq { static DEFINE_PER_CPU(struct cpu_freq, cpu_freq_info); +/**maxscroff**/ +static int __init cpufreq_read_arg_maxscroff(char *max_so) +{ + if (strcmp(max_so, "0") == 0) { + maxscroff = 0; + } else if (strcmp(max_so, "1") == 0) { + maxscroff = 1; + } else { + maxscroff = 0; + } + return 1; +} + +__setup("max_so=", cpufreq_read_arg_maxscroff); +/**end maxscroff**/ + static int set_cpu_freq(struct cpufreq_policy *policy, unsigned int new_freq) { int ret = 0; @@ -306,8 +326,83 @@ static int msm_cpufreq_resume(struct cpufreq_policy *policy) return 0; } +/** maxscreen off sysfs interface **/ + +static ssize_t show_max_screen_off_khz(struct cpufreq_policy *policy, char *buf) +{ + return sprintf(buf, "%u\n", maxscroff_freq); +} + +static ssize_t store_max_screen_off_khz(struct cpufreq_policy *policy, + const char *buf, size_t count) +{ + unsigned int freq = 0; + int ret; + int index; + struct cpufreq_frequency_table *freq_table = cpufreq_frequency_get_table(policy->cpu); + + if (!freq_table) + return -EINVAL; + + ret = sscanf(buf, "%u", &freq); + if (ret != 1) + return -EINVAL; + + mutex_lock(&per_cpu(cpufreq_suspend, policy->cpu).suspend_mutex); + + ret = cpufreq_frequency_table_target(policy, freq_table, freq, + CPUFREQ_RELATION_H, &index); + if (ret) + goto out; + + maxscroff_freq = freq_table[index].frequency; + + ret = count; + +out: + mutex_unlock(&per_cpu(cpufreq_suspend, policy->cpu).suspend_mutex); + return ret; +} + +struct freq_attr msm_cpufreq_attr_max_screen_off_khz = { + .attr = { .name = "screen_off_max_freq", + .mode = 0644, + }, + .show = show_max_screen_off_khz, + .store = store_max_screen_off_khz, +}; + +static ssize_t show_max_screen_off(struct cpufreq_policy *policy, char *buf) +{ + return sprintf(buf, "%u\n", maxscroff); +} + +static ssize_t store_max_screen_off(struct cpufreq_policy *policy, + const char *buf, size_t count) +{ + if (buf[0] >= '0' && buf[0] <= '1' && buf[1] == '\n') + if (maxscroff != buf[0] - '0') + maxscroff = buf[0] - '0'; + + return count; +} + +struct freq_attr msm_cpufreq_attr_max_screen_off = { + .attr = { .name = "screen_off_max", + .mode = 0644, + }, + .show = show_max_screen_off, + .store = store_max_screen_off, +}; + +/** end maxscreen off sysfs interface **/ + + static struct freq_attr *msm_freq_attr[] = { &cpufreq_freq_attr_scaling_available_freqs, +/** maxscreen off sysfs interface **/ + &msm_cpufreq_attr_max_screen_off_khz, + &msm_cpufreq_attr_max_screen_off, NULL, }; diff --git a/arch/arm/mach-msm/msm-sleeper.c b/arch/arm/mach-msm/msm-sleeper.c new file mode 100644 index 00000000000..91ba847adda --- /dev/null +++ b/arch/arm/mach-msm/msm-sleeper.c @@ -0,0 +1,84 @@ +/* + * ElementalX msm-sleeper by flar2 + * + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include +#include +#include + +#define MSM_SLEEPER_MAJOR_VERSION 1 +#define MSM_SLEEPER_MINOR_VERSION 1 + +extern uint32_t maxscroff; +extern uint32_t maxscroff_freq; +static int limit_set = 0; + +#ifdef CONFIG_HAS_EARLYSUSPEND +static void msm_sleeper_early_suspend(struct early_suspend *h) +{ + int cpu; + + if (maxscroff) { + for_each_possible_cpu(cpu) { + msm_cpufreq_set_freq_limits(cpu, MSM_CPUFREQ_NO_LIMIT, maxscroff_freq); + pr_info("msm-sleeper: limit max frequency to: %d\n", maxscroff_freq); + } + limit_set = 1; + } + return; +} + +static void msm_sleeper_late_resume(struct early_suspend *h) +{ + int cpu; + + if (!limit_set) + return; + + for_each_possible_cpu(cpu) { + msm_cpufreq_set_freq_limits(cpu, MSM_CPUFREQ_NO_LIMIT, MSM_CPUFREQ_NO_LIMIT); + pr_info("msm-sleeper: restore max frequency.\n"); + } + limit_set = 0; + return; +} + +static struct early_suspend msm_sleeper_early_suspend_driver = { + .level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 10, + .suspend = msm_sleeper_early_suspend, + .resume = msm_sleeper_late_resume, +}; +#endif + +static int __init msm_sleeper_init(void) +{ + pr_info("msm-sleeper version %d.%d\n", + MSM_SLEEPER_MAJOR_VERSION, + MSM_SLEEPER_MINOR_VERSION); + +#ifdef CONFIG_HAS_EARLYSUSPEND + register_early_suspend(&msm_sleeper_early_suspend_driver); +#endif + return 0; +} + +MODULE_AUTHOR("flar2 "); +MODULE_DESCRIPTION("'msm-sleeper' - Limit max frequency while screen is off"); +MODULE_LICENSE("GPL"); + +late_initcall(msm_sleeper_init); + diff --git a/release/aroma/META-INF/com/google/android/aroma-config b/release/aroma/META-INF/com/google/android/aroma-config index 3bfae19bbd5..f9fe0943fd8 100755 --- a/release/aroma/META-INF/com/google/android/aroma-config +++ b/release/aroma/META-INF/com/google/android/aroma-config @@ -379,7 +379,21 @@ checkbox( "Enable input-boost","Improves smoothness with kernel-side hotplug drivers",1, "Enable Gentle Fair Sleepers","Disable for UI smoothness, but more battery consumption (enabled by default)",1, "Install Qualcomm optimized Dalvik/Bionic","Boost performances using Qualcomm-optimized libraries",1, - "Force USB fast-charge","Always charge in AC mode",0 + "Force USB fast-charge","Always charge in AC mode",0, + "Enable max screen off frequency","Limits max frequency when the screen is off",0 +); +endif; + +if file_getprop("/tmp/aroma/misc.prop","item.0.7") == "1" +then + +selectbox( + "Max screen off CPU Frequency","Select max CPU frequency when the screen is off\n","@personalize","maxscroff.prop", + "594MHz","",0, + "702MHz","",0, + "810MHz","",0, + "1026MHz","",1, + "1242MHz","",0 ); endif; diff --git a/release/aroma/META-INF/com/google/android/updater-script b/release/aroma/META-INF/com/google/android/updater-script index 262ff1cdd4b..107e6b65c76 100755 --- a/release/aroma/META-INF/com/google/android/updater-script +++ b/release/aroma/META-INF/com/google/android/updater-script @@ -395,6 +395,12 @@ if ui_print("Force fast-charge enabled"); endif; +if + file_getprop("/tmp/aroma/misc.prop","item.0.7") == "1" + then + ui_print("Max screen off frequency enabled"); +endif; + set_progress(0.3); diff --git a/release/aroma/config/buildconfig.sh b/release/aroma/config/buildconfig.sh index dde3ae5d487..a8994d9dc44 100755 --- a/release/aroma/config/buildconfig.sh +++ b/release/aroma/config/buildconfig.sh @@ -335,6 +335,31 @@ echo -e "# 1 to enable fast-charge\n" >> $CONFIGFILE echo "FAST_CHARGE=0" >> $CONFIGFILE; fi +#Max screen off frequency +if [ -f "/tmp/aroma/maxscroff.prop" ]; +then +SCROFF=`cat /tmp/aroma/maxscroff.prop | cut -d '=' -f2` +echo -e "\n\n##### Max screen off frequency ######\n# 0 disabled\n# 1 594MHz\n# 2 702MHz" >> $CONFIGFILE +echo -e "# 3 810MHz\n# 4 1026MHz\n# 5 1242MHz\n" >> $CONFIGFILE +if [ $SCROFF = 1 ]; then + echo "SCROFF=1" >> $CONFIGFILE; +elif [ $SCROFF = 2 ]; then + echo "SCROFF=2" >> $CONFIGFILE; +elif [ $SCROFF = 3 ]; then + echo "SCROFF=3" >> $CONFIGFILE; +elif [ $SCROFF = 4 ]; then + echo "SCROFF=4" >> $CONFIGFILE; +elif [ $SCROFF = 5 ]; then + echo "SCROFF=5" >> $CONFIGFILE; +else + echo "SCROFF=0" >> $CONFIGFILE; +fi +else +echo -e "\n\n##### Max screen off frequency ######\n# 0 disabled\n# 1 594MHz\n# 2 702MHz" >> $CONFIGFILE +echo -e "# 3 810MHz\n# 4 1026MHz\n#5 1242MHz\n" >> $CONFIGFILE +echo "SCROFF=0" >> $CONFIGFILE; +fi + #Battery life extender if [ -f "/tmp/aroma/ble.prop" ]; then diff --git a/release/aroma/system/etc/init.d/99glitch b/release/aroma/system/etc/init.d/99glitch index 0c2fcc356f3..70957f36a05 100755 --- a/release/aroma/system/etc/init.d/99glitch +++ b/release/aroma/system/etc/init.d/99glitch @@ -245,6 +245,27 @@ else echo Stock GPU voltage >> $KERNEL_LOGFILE; fi +#max scroff +if [ "`grep SCROFF=1 $KERNEL_CONF`" ]; then + echo 594000 > /sys/devices/system/cpu/cpu0/cpufreq/screen_off_max_freq; + echo 594MHz max screen off >> $KERNEL_LOGFILE; +elif [ "`grep SCROFF=2 $KERNEL_CONF`" ]; then + echo 702000 > /sys/devices/system/cpu/cpu0/cpufreq/screen_off_max_freq; + echo 702MHz max screen off >> $KERNEL_LOGFILE; +elif [ "`grep SCROFF=3 $KERNEL_CONF`" ]; then + echo 810000 > /sys/devices/system/cpu/cpu0/cpufreq/screen_off_max_freq; + echo 810MHz max screen off >> $KERNEL_LOGFILE; +elif [ "`grep SCROFF=4 $KERNEL_CONF`" ]; then + echo 1026000 > /sys/devices/system/cpu/cpu0/cpufreq/screen_off_max_freq; + echo 1026MHz max screen off >> $KERNEL_LOGFILE; +elif [ "`grep SCROFF=5 $KERNEL_CONF`" ]; then + echo 1242000 > /sys/devices/system/cpu/cpu0/cpufreq/screen_off_max_freq; + echo 1242MHz max screen off >> $KERNEL_LOGFILE; +else + echo 0 > /sys/devices/system/cpu/cpu0/cpufreq/screen_off_max; + echo max screen off freq disabled >> $KERNEL_LOGFILE; +fi + #Battery life extender if [ "`grep BLE=2 $KERNEL_CONF`" ]; then echo 4200 > /sys/devices/i2c-0/0-006a/float_voltage; From 91c382952e432b6fe1d8a5674826b31073b453d1 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Sat, 1 Feb 2014 17:08:21 +0100 Subject: [PATCH 207/215] Aroma : This should be enough --- release/aroma/system/etc/init.d/99glitch | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/release/aroma/system/etc/init.d/99glitch b/release/aroma/system/etc/init.d/99glitch index 70957f36a05..bf34a39555d 100755 --- a/release/aroma/system/etc/init.d/99glitch +++ b/release/aroma/system/etc/init.d/99glitch @@ -290,20 +290,19 @@ fi echo "Settings backup created on sdcard root" >> $KERNEL_LOGFILE; #Wait a bit before applying governor changes -sleep 30 +sleep 20 #CPU governor if [ "`grep CPU_GOV=2 $KERNEL_CONF`" ]; then - echo "interactive" > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor; - echo CPU Governor: interactive >> $KERNEL_LOGFILE; + governor=interactive elif [ "`grep CPU_GOV=3 $KERNEL_CONF`" ]; then - echo "intellidemand" > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor; - echo CPU Governor: intellidemand >> $KERNEL_LOGFILE; + governor=intellidemand elif [ "`grep CPU_GOV=4 $KERNEL_CONF`" ]; then - echo "smartmax" > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor; - echo CPU Governor: smartmax >> $KERNEL_LOGFILE; + governor=smartmax else - echo CPU Governor: ondemand >> $KERNEL_LOGFILE; + governor=ondemand fi + echo $governor > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor; + echo CPU Governor: $governor >> $KERNEL_LOGFILE; exit 0 From f3ce4cd517337052b63e9ac6e1f2267ea62e6831 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Mon, 3 Feb 2014 16:29:46 +0100 Subject: [PATCH 208/215] Aroma : Prevent configuration menu displaying independently of the choice made previously if coming back to it. --- release/aroma/META-INF/com/google/android/aroma-config | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/release/aroma/META-INF/com/google/android/aroma-config b/release/aroma/META-INF/com/google/android/aroma-config index f9fe0943fd8..035cbd66d8f 100755 --- a/release/aroma/META-INF/com/google/android/aroma-config +++ b/release/aroma/META-INF/com/google/android/aroma-config @@ -113,6 +113,9 @@ checkbox( ); endif; +if file_getprop("/tmp/aroma/glitched.prop","selected.0") == "1" +then + if file_getprop("/tmp/aroma/glitch.prop","item.0.1") == "1" then selectbox( @@ -397,6 +400,8 @@ selectbox( ); endif; +endif; + menubox( "Glitch Kernel Installer", "Ready to install", From f342e58596e464d459fa8b1d400a3c3538440201 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Mon, 3 Feb 2014 16:43:45 +0100 Subject: [PATCH 209/215] Add a folder for Qualcomm optimized Dalvik only - for CM. --- release/aroma/qo_d/bin/dalvikvm | Bin 0 -> 9432 bytes release/aroma/qo_d/bin/dexopt | Bin 0 -> 9384 bytes release/aroma/qo_d/bin/installd | Bin 0 -> 30220 bytes release/aroma/qo_d/lib/libcutils.so | Bin 0 -> 42220 bytes release/aroma/qo_d/lib/libdvm.so | Bin 0 -> 795000 bytes release/aroma/qo_d/lib/libqc-opt.so | Bin 0 -> 9584 bytes 6 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 release/aroma/qo_d/bin/dalvikvm create mode 100644 release/aroma/qo_d/bin/dexopt create mode 100644 release/aroma/qo_d/bin/installd create mode 100644 release/aroma/qo_d/lib/libcutils.so create mode 100644 release/aroma/qo_d/lib/libdvm.so create mode 100644 release/aroma/qo_d/lib/libqc-opt.so diff --git a/release/aroma/qo_d/bin/dalvikvm b/release/aroma/qo_d/bin/dalvikvm new file mode 100644 index 0000000000000000000000000000000000000000..8c38a25c30ccc1b6bf52c8d2597b91404a1d8981 GIT binary patch literal 9432 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 PiLoZ0u@93x5yS4^3%S}( literal 0 HcmV?d00001 diff --git a/release/aroma/qo_d/bin/dexopt b/release/aroma/qo_d/bin/dexopt new file mode 100644 index 0000000000000000000000000000000000000000..c7f76c8a8f2a743a03d74938af87f732d3fd3dec GIT binary patch literal 9384 zcmeHNeQ;aVmB0G5`~h}89J0iPXD4o)CKfg%#JEYv#>&I;N9@HRg+SMlr6=nplAcC- zGLn;p5ZW2G6NsCny9t3I%Vb;gFX5&bjB@bI(2Z-uK>pPmgZu;!P$K(~5=FF_PXXW^666sanz4 z)-sMcpj*N!nH^Q6(@1H6Mpo1jSx5(2qeYO3NQY{L0CUA($rzE1YAOnP$1RLGoCV6E z(Nz%jOL{YagPwz)s2w^Y(o-LQIVJl5|E(zPQ47<^@db=&v=ntj)RyR8v^VxoF=+m8 zizQ>S5V~zZ4Br+M!#jm28W{@A=gLBGH_S$|Byj`%pm`RL4MI7|Ii@6Ymk3#kS`kKPYm*mLCzZFKNw^iEh4oj z^J9<~8RVq~`BsBmtCO*`*jGqyD0EQ4X7h~(c_U=2PS5)LgW`aU2*m`M1!ID+ll5=A{SKdy=!wW} zQ30Mdg(7mYUGVsXs0d}_dMLMvk>02fX^naV;*cQrc6xgo8&IiMklDI|883!?o5FH5 z+1shNKnpTzDj3}($cl|S?3WC7L%m|}j=r`1y}`b9{rIEs))rcAO2|=K!^ld%Hxj{YG%%zd zD0zigtUv4t2~;sO5ckvUcta5aSqc^)u3%6Ivydkkl)N-`-bj-9m1*?@<8q8i5g0^- zXjF+{YegHkiWKR_9MF{&CmQO4ebjBp&FkF@MMw1a)QU%c)k9+5N zv9T$vnZ;!>7*hoy5%I_>kJYAf!z#w)U_^>)dd*!-_IX#YR!x-78SR4=pe3Mc5N;{# zR!|kF9K?a>x=7bTT+Z2-Ks6w`S1boD135s8LB>M&7_I2GwpPVT=Qzenz|(b|N*Rda z((VOx&$$t#72IBw`wQI<{z9$135eU1a^0q?B2eHq#;881Vnjt*#RRaDW9$jw5(K!9 z5PN=v5WycJL{Ntb5yUfu2P^>?9!)`W_($^#LI!=mH@Ilp@67KO#f|J|V;er3o=1GlZDHD}QpIHVrQU|;rYsHnQ(fG1Q)ceq$BVhrDVNGu zfZw3V;8O5-b)Vfi_djlar6{;Kvr|%NmYd+?UT^K3t2nkk995 zKvzIHkk+pQ{W@6bl-7Q!8UwZ8gSHGlEDU{3c3xsny!HwCs{eGR$IAar`@yktzLHP4 zj_~>HmCPQ#ed1egJNK=Qo|*jGq-)rf&t@{8r&d8blgW+0b(xjCI?Kw7e&M)WVp)_k zl{MEnUN4!=H@CpzKQpZQ;f`S!%av5v`60K3yMrI&ldhf_Q%OGilZ+{~m$&n*dPPm~ zXg>R1rU|^cCZByjQ#Za7z3%Lw9yg|%;OpItiD%=dQl=V`-pH^z+sL_JpV(9UBF9rS zZ)MDU-S~F5joYrYs!8>C6^~jE>~>W{dp2Wz`f{!jSL*%(SRrHc$)O_#( z-ZEl;i5(~&H66%jPh?ug`(W3n_*sqCLz!f%c=Q3j8T|J$?c?3hc6ThtNZ5BNBmRt- zI+9~8Y)#8#ySp9r`RqWZcl@zL_^!8Kv97j#@E^H~@h@Dg zr|FGXZdgNBGv}_ls&ZD2rOY+Wu(2K>UmG$_ZuC{R_;qdtThWdvZpU~6^y!5OE8j8x&w&>HefQ5g*ukXh{mx<6E>}gW z^o3j?pS>_$`mBksOWZ&HJJ?KiobP1c8Fo#&ce!Y80@L?j)=lh@fR=$z!Kyi_0As-b4&<&c)C*ZN6B;7ovC>QB)=@d^e)7b7$RWl_<_CQ9P2W zswNwR|Se3h6oru3l zyd74%r%R8NB_8Ly#_tmC+=-48$_P#co*m1ypu;U<&VPqI%-GvPQARS7b zo-J|M&Og;oYv9$im2XI`SYO58!cXuI~(XErH0|kb6Ke|Q%$v{8a34%PuGX%({}8z0LB?m_RgY|O#uHDxD!bHKY@P*xF6UEd=*pxXguu2Y0+melqGIuZEWSdVOV&W^Lo4if%D_UrYJcv zrZ^Pnq&aUH4|@h+0S|PZ;fBQs=P4XG3ogBMS`%VUpOBbuWVGUZl2Gt2hP}bKPvB}} z|FgCJ5X$*I2+qez;cLu=!if{7KTh&P!}+69NI}J%4Q*u7Mi$zbWbuvjoowyq=xna~ zWcov-R)---5t-H3BYgJts1zRL!tv065T$-R(LwYiML9*y)%m4(*vHlSRxw1NBzM5$ zQ_|!2F=Ey9`rwapvl(+Ggr)dkfLz5xLRi-PL9O>kjfXWtSNc`Em;8QO8srQI)j>I+up!C!^#G2gN`O&sp+V3y7{hA5HbM3E zk*GlF_+JuHu+YU`f|OI*!)%i%2avdxkXLfZ8kq1(E)lwJ7f$JH#o`LHbxSoOkZyCU`DNivO5yus_8}D{;gkduvdgr|z?@#ER zJiSLJYJyDP(CR?+?w-yupXc)uon`2~ITakqly9{3UY_2u<5S{IutO*dJV znr=2Pv)p2@F|9GVOw1Vz&<8Nj0COtO*b(ORCBv~~sDSv0=?r*c0p^SfLDCeMNKj@@ zd6Josrc!$v49B4h`s&qVLZLH{EJwwGxGdnf^M5R~-f6vH$zAh%2(7uc zmT2FQE!k4*X# z$~UQ$-=W|Fp!q_T;*aoQ(2XFnqy1g+N9-PlzFf7VYrxV!Vz(bQlsodL{JsTtv>r&N zqK)G)c#4zi1K5lKe0!rht!R0978Mk?(!K!NFmvRll zx~z+Cxv1r)=(77QH*HarDhOUa>h9`(T6Fzjku_dP?*YLCXq)f*JkOI7vikY$e*gOY z;lpbW4<|MmcXO@ROT0RQm-e?x%(Oo0Et0{njq@P88E|2n|m65zia;J+T=SNJs$)qiM! zf2^N>AmZ=!^Ar8_0KYN7pBdnv6X0JM;Li*2TLS#$0sfT%{`CR=%>n)=0{q(p{LlLN zslLzq`Ki8t3h*Bd@P8QK|2V+!4DeqI@OKCJL($)SAC<2Q@J9sr`2hcz0DnS&|Ly>P zT7W-0z&}60zbL?85a722_{#$Pl>z>B0sc(^{@(`pp9=8r4e-Ah;6EDRKM~+R72y9k z!2d~r|DOT=?*ja70sbrSpS4RZs$-YE*8}`Pu;pjPi>rR{)e2l>$ROtOTeY1=cFItf;c6Y$bUi8dg$_fep1QC_{3pkX58C zD7CTz;)~@LR90Dwa#;zAtz;|8#ERL909LH-lOOV5T3k|8P+m3>8H4WU3B(GJM5#)| z1@T0cBE%O4AG66V2)vBgfrOS8LPp3Q1&|N{tQ9~iDywo)E6PPmBW6PssF&Cv0Mt55 z%PY_*Xw*j`w4#C%wkp54(h5mgS5(^AippZN4l!aO-GKCb9FVm{eY&L3D#N(X6#Qzx^060O$3C#7wXUO>dfM&Q%*-vvTnwv(!(Yz}Ij=tFv_<#N% zCh8|Ynz#B5Um^{rskePYWuN-CP-!k35OkY2{5GHD(E^N?!}|k9v;RKNtdNZCIgPy@GZ0~7V5 zT86u1SR=!IGCUx|gEFj@;ZYgZ$?#PfGP{(oT83H~hRZNQhP(`8WjJ1j1{o&HaGDH_ zGR%-+whZUVaFGo2WN49Li3}@cxLSsG8E%o`HW^mSuttXaWOz`9wKA-e;j1z{CBu`D z!w_`1Qv}B|_7Nb>R~rdp9Q~A_im~$q(O6#)M2B(^R5SK1K`4onAR4NjAdG;Epq8<# z1kq7E1ffvf1gYa~1k|B_6NKWZ2|{_a1fd{0g5ivX6NIsdAP7Z|BnU&n6O4e3APD8u z6GZ16PY{Y~AQ*|hN^lfx1i?FDdkFHd0R+*BjRc{@83duMGYQ7R&JaXLm`4!CBZnXi z+#-T{#_|ZluoV)70kaTalZ5riTBkf0ImPY}khk)VL~CkP{Wo?r&rpP&itPY{OjTY@l-PJ%Ph{sbRD z`xBgn_9vKy_9vK)_9qBqsd7yCPUU$1yZ(+pIMlAUzS~s>op}EbUkCqn+t<5#PkraZ zxB1~){P1;tc%>g+;)fUd;fwt6d4BjzKiuetPxHek`QhXJ@K`@Q(hm>!!?k|6$`9}E zxmCxjet5ed{;ePWg&+Q@AO4Xa{+=Ix$`60l4?pUMAN0fb`Qf|#@NIth7C(HQA71H) zm-yj@e)u9ke4ZaZ(+@ZL;nV!^Nq+cvKRnhCkMzUC{cx=xuJXgXyZz+vhqwFT-}>QS z_~D=W;UD?o@A=`U{P0)(@S}eCK|g$-AHK^E-{yyJ@x#~o;gx=Pi636*hcEKO=lS6? z{cxinKFtrGL^ypJ6IxVtPkyayeBkSB!}H%M4S#UV(=k`nP+!-21Qd%bPvAAt?>dcBQspTeDo z^OdVcxoXz$J74+;nFmUL1!)=bP%@O&nE5r^dfGX!1U&QB`_(6y#q0i}D#b||(ThuWhw`kzBaQ$Pv?&mtgLbH@4_n$SdJE_J;l@QVjUwhE(tO+!9206@V+;~5wy3#}TNrn-MGL6n zcp>YmeYw}Yrb90btTUX}!`>6m#MdKzd~vSH4N}cZ;p0Q~4q1ia+I(;6yo}1iySZSHUT(%uTc$KML{RSR@%+A+al` zJST>X3Kj+kaTi!@jKd(@J8awtuRF4X=?67?-J?2`7FGNmjb8Wg4u)Dqc4$pu<|^YF zqf!XwDKyLx(iCb6=0n9$uX|93$`KoJH0|>XjQ5<*a(NA&(*}%(li`NLCBga1qF?93^Qz31VQPq5g~OpST1aeq#* z!(z$yOk(PKulrm(H!0q-FYVeV7E!;HuHaK2F2gtqy|$jXXXZVb>x}o9zRRgH>IJ3i z@7J+NYEE(7H7icID`SI^&zXqOcRfsh&jo|YV9v`~V~j({8wi3`|7<|FMSLF?&JCdy|s@=>5wp7j23smPKf=q*au+c%b2bVys)USt`Psf}7| zwB+SkHs`&ahaPvDop}azbfAu#A)9q@-vW2Sl>%=ETngv{d}eZ}|1fDMUdz#24hgzEWo=~+dc*7{bBtw;(d%}# zDQgvnUKG6UG3}gzYhq&+&;Bi|*@FqEQL+DC$gc3lhp3fGpfIIt@s0P*_X=x_cG+*c z5hAD>{^>Y*8OuZ01v}cqb>6Ou;*p~Yni70L6_pIUw~gtCHIH)eLduoD4D`CY;Xixj zU3=EmHOqNH0}78A@`l|<@gw|>=6VO(=$!=~ZQifyUvi`f_kz-em>(JsB4*cdCI2V$ zP3ZYTgx9vET=7mcShB8mFCPs5*KM4ExwhN)n<0m6t%2&j#)x_tyza_2DJ%|jb)Xy6 z1pjPD1dLH}l=Cv?r)<(fUiKGmpx=1i zOCiB?O@vw6xX}s+wD;~R$3n3lJ~>ftj#h5My-i#XL;!~|8>6+FQ{J*P}^mGU6VNca2=>?7Db7;z*G>$A>Yfv4+ zA2{uF{ehiXx)in%eUJLRH{oC9l= zsWLtoa0&bbBLG`LEB50ng^R!R%zNb@nKzC9nE9FcA&-)+1Mi$g#eeKsG$acACbW9p zwjQQeHUGC6_6Sl8aiDi0MBV&1IRy5N?2X*bsubDQJQEjkJ?aZwd4OiElSJa2C_x{P`_Pb z+0V38o3{7$ul}$hL6E_u);#3!m`L$>%M*V3x245$DMe63anZ1etvY`2p^)m3!=xc& zT0=&KAzzD_>XDZ9rVV}hQmFHiluFxLg&wWqtBhfn7lo3QeXwOEY-rH-WFh#F0{KRC z>+5aMYMYpTxZ|`Z!jN*MchZBSo;m*Kw2;rs5LYH^{Ir(6j$|QD7!D4)Zzk6lBd%DE zOK5r0vCO17g7jyDh2OzKj~7PfJuU=cM0?1?@dGVG9qNd*)e4tdn|ouM%UaLfqw;WV z>V$O9n3RyFg~)56oR_*~ii4ZPuV(u1nl5_uXCD)^F+sbPH#Jx0=Hv^C9UptNXCnmF zPT1KN#U9n(i|`+42&#E3Vz%X}w9v*UooOtX7fkod`8k|}9M4$#)tZF5`;|g}hvqV; zdE>Hfz$Z=jq15}#1p@U$SX(Eo&t1DcEN@o*R5LGp>|xcgrTG+hz!~hAj4+?S##wjG zUamg_e_q(-;oLFLaHfc+etYO`C7kvQho--Hlj-lfn(=a+NyW#>{M0y!F1uyO zrRX3v|Kbv<4==)=K^FSk47i8j7Q-!tTLWi>OTpek8C)z}5d1p0kFf7>4gItZ&r<{=O1hD=Elp>s7A{tEpFfora(*);xY-;duxChyGho?OFS3}CwQ<4? z;~YWZ()KEajQVw;S|`_jI7!*?xueRw7*uPF3fGMuef=s>tP&|YE`8}a|Mvdcal%~T z*B-4-;X2q8BIxUvgJQWz@x`T)wJBFx24c49WcvQiz3y+jn5EbKeb*zVN6jPqtSW_n z*hd>K)BatgZS2Z7ExC>M?_Ezg7GnnDb#Dcw4!NELr9z+B*z0~(O!HdT0@JTW4#-0B zj^Mq@tJbvR*X&u^CN64m?G)5kgBjP*=2_r%mPn~}9KXhAg*7e4D6juCK5%w%emcuAPG06^+tyzeH2Bjds z2+$Xb^p>v4rpdR}sIZGl)jLPx|5#_QJG+asWTZtRhbUnp%G-kS!jax6rqAe#GsWGO z-YBM5i|JL)m`jYmxaYh)67{*nPI!7g#N(U#O5TFj~yuEuVxSsJ)nE=u7_@o+S+Fr@B|vFyeu+UuU)m5$XH zJ2PmJ#PQ4Cq%xkbcUf^*Xg$&lK9equkqM}d>DOxdZz0{xG){-lwcuD__B_AV@=MJ zX-Z3ouy`l;`L?vs^OK=llg;r0+eJD9&FJj!m}DMVnz>z1 zH4&f@ibK8bQP77UFR1ru8bY6YxIT1mFwb_-JcZjyxs8OjPV4+$?oYk$64bIEYB@%% zrM~k{6EEgU^O=F7mPSJsb3io&RD(pSp`8(?h(0RHaZu;T+Fti(kcUE+he24pdx~Yd zD33=vbL(7aCtjAvTiBOPhK)*rdk%OKpcU{#$SDJ`68>nwsqp{r`f>IqC+HhAX08@( z;!5-eYRLFb(vT|)rFOUn`b&Gfu#4#`VI8z1cm3MT?ZSHF+N}Pt_47SS`$l7?FhxNB zU>B<)PuCw{`BPk<*lp(h(27ja(*5S9zTOJ?TSXa!Im%6oYomp!LUE45m2@*mNUkqI zY>C`DTRL8W9Ldu4x@)n%CQDa_RduhsqNC7Mcw1jB>!|6YeNLv$5os57JY;(4Hrkwy zjgI|di-)6i$kG|HYFEUQrJF9MN$bcqWs6*pr5of3-lMo`op}nDZU8JD*=El5bT3)D z4Dg#FQtn4OM-uyC7q$$H>`O}Yp- z3g-mp0Lh-wLF6~U&yU9#40sgqJm4C@Ug%9WpcgO!a1``Y4R|l$d7L>kf$liq-vA>s zN1|_APaM0pb@9HO$FL_Ac5Q1mH(eg}J6*05*A=q$33rff<6P%@RIohPno=<; zaIU+0I73$>7nKUF;#}{+=WOIDpE-j^4zo;@d(~U*X|#q|Y&~uKwWQzwdtVuM13PB0 zr5fb9rzfzd)U->s^!)`=US!{;wg0BYTd?-ulDWZ%9WgHK+NRm=9BopvMV-gFHuQ!* ztAZV4<5yf}inCX~v0uclnTlUy`nW|g1AAsMRmRn@#&mL62{T$HuDu)-KMP9zoHg`w!=cTz1ODZQhw}RmmU$c zyI_X;d9(?x8LHxG1 zDI-{$LJPjETV@P7zfhojXSVagZ1801aWxoBJZ86?Ye~=9hJ-#TUF#X>!0fgzh))&g z620zOBES3WUwZac!yWJ#iDLtDdj|ZTX_7E%BRz6n)=U5Q_mVzPSasU+Hl^~+kA|0N zJV8s(3Ei!oILOk^LaWwZ_v3A0qQ=pxwM^ENZk)lDLsuS#qxGvDXK@&5O0(_d~h2x^SL4+C#&Qe*UZ zF)VW{5O1+w=`YvG96q#EdpBCld1z@0k7j z9MiAcBOYA??XNNh?+DqxNhpUlLxa_-cmaJbVO&TPx1PlnHYUU=(Bqgs7d1^4)Q8a< zY}CS1eZTUgwh!yaIiByBwwK}&o7Rh+73>dOP`F%(9WKV+eI!K)+1=~j)0*5cr7KiD zw_O*15Ry^`-GvqRLezg->l%dX8j`#Ct#OXI?S}Z*BJOWfhQv5D@q?REgkYpz(`s$- z=i>d=1ESQQ^GH$;bNI)eY?XNYgXbRP#D!#|lp8Hf|3s67DZ%xC-;*4;y^1}`-S4)r z89{sBX<^GYb+F&7YU~~C&4N9QA12QOJ6nqCPPeOnPyOZPADEqvaOm4QSF*9R|LQ`2 zIg7EU4&w=pIYc)sb2!Ej!-@Z@+lLu(j3s?1=Q`HI>W9nwPzAj>H)&9!wIZ=AQhP=( zh@(Gt5qjMjEn1V-Z%+!df)?t{-b?Abqves~#g-Z3yqPY|(7w}_SjI|G_MMr$Ja(zp zV;3DgGv2ZpWtXGuSnMHku19*&ee9|mdE4FZd=MmFUkq4S(_PVvs zH2&fxy$~FQd1#BhzQ^ss%CyIQqw9~RgMBro`CgCv$F6k#gGB+QsxNUF6A?rd$jbpUlVya*|pX5JM%-L93&2~8{qhjU-^f{^36?c!h3aLmvx~V zGvBLA5{5*tHOjm|8m~FmX0lyLIC&T_Xss~=nxR+sx(_>7X0oRx+7zMkfnN8EPUN7m zWv(|8Z9mYWl`6BbuIqL0a*{^r6q&-4P8OsW6yWnEXODY{$Y){KQqwZ50DW^_3co0D zjv2h+l95lq-pZExo5p)bvgi!dzs8x0eQkA9k2?)}1FAS>6U{1iI6E)RnxSj#aVLv; zPU)Iwns3gO_jtJKAjtooE-psrSZjGOSkd(E4N5o`;9KLME~RYHX3Ipx+l^!jUmwJ9`{RKl$P44?NX0>4t!HrofgPyvNN=|)}AHV zg+IY2jKcikDByc=@4y|0?NY;DPCRX`hH4d5ogG8xVR+yQ?$;MYj!#QmfB z@RQq%yGGG~ad1l!9tzkG?nl_?RyZdd;a|YL#WR)<_$r(Q_%nb;z-IyVfUf{fXmMu+ z3DDvLTKsRRy94u!EEfx<`D3gjF+Qs4aqLU#g|OW{?nzj&4{g?C7orEd4f+N>#zpNO z!uvUT+&NfL_qZ2z&c+NCdjev+J=n=jO5_bzoNX>n7{=m1YdY=h{X;wMS?$KWi)`j^ z>$JjNLAfIcc`oV6@tNtGMI5F>p&c&w1Vh^U=vmFEXjw&8{)hr=-QSL~3jz_W})Lx-CK)!1Yrgtq>i+E4%&-H zdv)Xf-&fG<&j1?%UjqC9@DafMfOT-aky5)JyRz>A%sqEDW?nZg^e9t!%g3Hws=sHf zMqhodBY2mxn#M5OrXIJs^Dm~qn$hEut57$!eT`AQJ#fJx6EfUF~fd(jd3kq$?wajdYx_@qad3Ops`ndw-Q z7H(h;?w&uV*{{spG}P1Ipow=kP5p|SoaN#)ucrlH0L8jUPlzriPTTa2;|`DVEC)%7 zCkXv>Z#?BmT+vF#b(#-0#svJ=maa3sF9A;&uk{&!g3!hh-&h&N}vc zs?o`q>n-~-Ba11ljXg9)V6Intl;Vi@iv3`%Q4BeP6RQ;05u69xmmjR{aUbY-467fgGN6@@gvkF$Y$e zLWqYu(&IkfzEK}^-iR5rJ-Wxep`*WJ4d~aH*ZR>zPA@=C2YTFF+NtCkF->gky<(ce zjsXr9V>N*)DToK1p~_flF3WtuQrNbZ())RkxBG8&7`R8QLb<6QUOcuYuXD8$)V zk2?Z7HL#h==X8XG49(Oy= zt6>Y;?nTd@(x-8f9cXP+Ih2jD5iBZc{$IaW)%3Xcv@7xdMBD+`c=frLBs_RG_Ifcz%OjzpFp~70U+OccN>q9W(o?N>>=U!p8IUctu zYK7N#-i2BB1K0KSm6)YfiuNzeVKc9S7TqQ8l-zfn_8V{QM)tU8w!P(;jD5i#_i)JS z?3I(~1M8Ph#=cLFy9|==56LHplAqW{`;U{4+?r)1v>ia&tgDXYXfv5MLZppsqy0yJ z+K9G$9jj_1QO>7wd#c(L7R9(E%s6^+5{!P-=D+{QJNO!Q)tXw5{YO~qs8!g1WUl$$ zbovqQsKVvnB1POintrmn~B!n$c7(j6Alz0^A1H2$`_9Y(5s ztxC(Hw8^!k+db}cND+<{JH!;bTBA(Sx24#D6k8ByOcVDVCcVC!r(I-m53w&H-IE;IH8y z1vnE>Y0+46EVC_J)07uJJ;Qho_wH!6WxZdSWIYk(QU;y4W=~WJ13uS}MBUod4J>Aq zqIOlpU)h^lIFM=y8u~O^jhtG4uEc=Hc#4 zJ}r%5zo{D_C^6RFXbm29_R16XFFlc)SSK3n7q(w@~SM?Z{CiS^Q~=ov`AtZ}br zkU$FiX&f0*32Y+!BoWO5j6aD;Hr0CQjT_fTeH6s;pl>wAo3lj4}IcF_@$i z6Pk~tIeOfD+t!92oIX?R(Uy2q{B1Mt+7=oM@>&fJ7Nw}h8L*c|chWuu?9kN~sU!w_ zrhs(rL^)f;oE~o(E}s5VDX{U;L?>xn7-%X)n#va1u_Fqa$yCw`eG*x;cUm@M9NQ%A zT}|SJAaS1X*CC7vnB%?=SORwf^VgYx#{eIL^PJEM!-PA8kyx{;y}_^tlj?DDoi^#r zIGkmW{u>03D0?@~J#@JBHx!}SE$s3@w3XN0iTwnoH#M@Dki7J~Bw=&jyLk+^C3@VN z)+H9+Qk^#PljGOcY~%%;l((jZzFQq96 z@H=6L5WF+tdDsA2M^~S{vT)NJ%!5s+@fzK#~y^iS(#N{0DIR>rC^iy#oEM73| zPOPC7*>tC2_tvzqbBTKly9Yxt)NGuPjx-y*F&GD3_3;>2g7}+8_AK3I z!wk>KqUhGi^j?W?(p=nl(G%BWM4rYut+<&MkJcm21TW4Mq}$*;;ZQ>!b@qflzM6Z3 z1xY%r>5mSUz+4CI@j_yaVYhlux4W~;u(u{{)wyJWW+|Uxw_yGSy>QX9x~|7P)X6S~ zidy$dj~#WpuhH&IQO61FvKsn!&KX_&jb&$AgulM^%P$u7Z7u2B@1bwM?bSC3&0}xxgg#4>~SG#tndI zM-U%^u>xzfXS>}`bopl1SCB5eIT14zwYA$_A*QbEy3@>_jmHkBbe2rv3P&AyuFngu z>BgFwWV7+=>n|~Wv}gmWpxcX}<0H`Ddk5j32iBQi0R9T_1Gsg-p9Xv%bCBl-V$BM; z1TYG49^hX9QvfdlhF~7j1Q?nba$>D9)Vwz*)Xc;amNmu^s9XQ8x@-2_kI2>;Fq=AE zGfmpVFF=|JEkC4&VAnnz``X>^gsuUzHW=;Dy>7R@D=hPeoChu2N8&z^HqYqQ_dCy? zPR1UL+BDpv#{6!rvDFOb_kO705a>wZ!sZZ`sQ#P7cCyZl_X$?crfnR&{@22-x~` z+$`EvsI_k}dW>T&EYZ*yg>}8xo!qVBlY}(%;cj;~S#MWtEh zj!Mt_DlgWOXJPuUF2+01ZektAciv%6>g)U6*clk<;G!7rmTkef=V%=2_@jlz556ds zqv|GGO*hiWT6E+5pT=q2oFQFJ#Vz#;Ie<` z=!hX6ZdzizqLI5hF)C`F0ilY{aU*aVX46H~q=kMSg|$@_q$Ax<>c%e#COL2m8gy@9 zPeE}AJrt`~?5?nJ&3Y@zHv;XmwIRwudjm;A20}8>qf#17VyXk3)E0v}Q-ndd3D@mb zBXvuY2Bl~)(nzz%Zk*Lq920e9B-Ly4OJNv?Vf-@y2cjO~nL{vh*PW=rKE2`)k9Hj1 zmE54*t*$w6lZy$h;cl|K203C8z7l&F-T1wL#-zEel~;B^117@VrNamwQKvhdbFb7N zu+_#sjKo}!*GFM}d&)>_g{*2JU0f?{TKt%>3A3nuIatqRM;c-*F9^y!HTd1vK_kZe zrhLclb*i}eP0ixTOa#tjvKkZgil&7)qcJz$OXJoY%rAC!yGKEW@Xhvbi=e%##>D98 zd5pJMxw{A7^-1cnj(6Xp_=<2v`YQgLdB}S{1x{#wcaZcIoPV1nR`~jR)5{}x< ziJYjTo3pyDID_oQ9f#1qGsy3grMdKQ$mtx`WF(=HLS|;TkZC@Klkv62-xBTY5Mi!I zQ5~Li)*_hc4(=LbzdWOfRg?ZsMZ3J(o|dVKUR`|MLKbRz=XC6;Xsd%Sqh(qjQ-?WD z;@1Rfo!P?1slNCd?t=zl$6#tNH@)_ z|5Fe%9&3CpMx6z?;n3~QX&;UeI=yeySO+@O%pal73wwukh|@YG~UhL1vi5BFp2bsX0A2kgPRbvwos`lZR)Vx=Pp zrH{usIn!Tn;xPwH#;-{7-^5vN<{i*TNFG*cZw`z71hvSujBtdsy~lp-nWPh7gC?RL zz3ujfLyK#NVXoeo7)9-Fsh8$<(k?f2r%i$TqQ)6tHIdb)wbDG?52N2CoDaqQXYfPz zSBG)u4&-;Gt;}K{mX{|)lBP`R;PDFz4Q#tcw(Wmyqg*tO5Lh*u0mXy=7u)i&K5A=X zeDCQekmogwgCA-{y#e0kwI|odpv)Mt%mfE|o`V~s7ZQh2S&310(dIX|)9qqoAzCLmH zt>1Rgc_RH5_!R2Ztj2s8@HM~}0F!an9xgD;Ajsh(tXDJ_Vk|XjA?M;Onuu|EF_wto zd>-SI#b55wI*rcewF1{L#X(kOig<%zQX`$vCpGaAIu93_7#9Lf=yo4%*XJd_QijxH z9CeXgbvJ&KqR(^HD_)8cxWj@+9cF<(p1~**((FI_dRny(jmZLEL!h61hDs=v+AH!bQ6Nj=?lyVaDF=UW(N# zccC_|rSVp4cDq;8P6qV6d(%sI;Vc8Z#-gowIGPU`z(4H?r~$VDJ_v`42JAP0I9o`! zV}%or5p*P^QPR3eoPk+d?fMXbeI6;4uLofj;0D-*tp@Lj^)9a@3S11~y}7dmUW zYZi9vU*2H+olp&q=0eVi<}W>G>m)gU-*OYb_aQr9R~ISVG{&2c=Pa;TM+OhGMb<}# z-g7-~j4Ola<=VIh~b3OZ|CoA-f7jbBRqv9}C1C#d;OaCxUF+2Ia~Ux?E)t-|Zx z37%XRj@1vt3hAWfI(E%4hsUZ$aeG^B& z&CsI--jK_YA-*#wy8rqW^&`~rH8^UImx8d?#$HS7P{vjQF9lBPZp?)n=spOGyNS{1 z&n>}XOT5@(h~QwuovpO8?!Babau zCz4IGx8S}s;JTLkjmcte@8EX|Xn{r(LZ`PT392?V>vku%I)>3IWfFE=PCGrD@jH=B zPLO6MGz!u!G#UdG;vKZXd0w~j2L0ki`mGCBi`faz-|e&ejT~-?veaGn-iI@2XeQ(7 zHY?_`Eedh8(4D5cJak{caDpq@@@PtlS&^>bh4j{@MJ#Gv{h(n;HECuWrxmfgXSM|? zQ_}L=QaMG6vX#^7gnYq(db`s1*4e>tUTcW3`pp!9#lnWPu+fto!I-V32#?Ub!A5m- zwdfnjc6{KKZfm@PbBl;3*SZ9KP*c+S-Sr7^TvNsRHT5Z2Eh9}DW`=0_kPG+?fSiKE zo*x@c^SGgC8K(ajH?|0;llu|koNo2~X9afl`R@j}wmB-__ImyOR`}5!nF@}BOO@Ub zVpxVT{eO8k*45S7V*$r2uwMswNL_C?is7~Pd2)QV?9U^3NM}DU`@aWdNY@ES>4M*v z@>7Yh);>t~4+W(71kr!ko&k6Se%%LB_%y(}y2JLI54{^tfys!Eyc^E~sv5l;Us`a_^)81hN(r0`h#qRZZm$;f9b;8F150Hk!4 zS3nOs7a)Zn{Q>mHBJCwt0c-EDe@GDRLr{hE-(K@>R0A5^Qu++Qy1JwGqkxo8x9mUf zk>c5PsovWFsl1bbRL+(g5`XHOsBiGI_HICG4?{P?0k;4ig?@YiSXXz*uIm9jHr##^ z5XIv+sobWzI<^JqZTObs6#g<+!MIZ@;Y7~f7V*Ov1uzas;Ua!tEa+d}{1*y8{;ZgG z3gLhDOB>=>)>gl?kNe@9M7&naGj*16PL|1-J2xvmbH=<}%I-hx|mfipF~I%Xkf?g2ZDJ0-M(39njX=w&ldCiv48;1xEsAlj{{pt8K8xac-I@fkFI_MF_g zP}R&CGqTfDv**U~^m1BJp`>D9A8(}T#fbCgW{*a|}R~DPCVIt|%`nEh?*&IGQQG!N!-D^^y6pn<~D^c3akEMXPu`wN?fJ zKn*oasvSw1UZ~@3kf8=$Y$c>A`S{U=|3XzzURsLh?=-Bk9156UR)tQnYy~leZaCV8 ztd_5UjBQAJD~8v@x2zc5B2I(1;A|_bR&*Tbmz*0vcC>9QlB2^zbqmEO4X(du%%I7b}-C_S4-{}+)TKzuH5Y4K`$%#NPqE66XfAiPw9kSkRce$qhkDK$z* z57F81Y+Bi)unBmauP;)f>k|wzO@tz#3BWDnfOqoBND*ZPv*Ojg{AEQv^+XNBtFKFb zh5#|V{NNuCeOy*tCa3x7{QSuai)@uYNet~4MJefrFC%)&juhWN%4gc>eL0@;M!cNL z7gbnPf+zockz%i@;tN-ZeNgU`WTq$;EASzq|0r~HKJ{v1nEzV%{Y zV2$Kfpa=VYI!e-uzBtl*Qah>E&=%3QK=aF&!myN0s3=FHS|43T@fe3zkkddv(4M}^ z`U_9A*pv=7p)|ju>iM_)Zaz#{619BXn zzY>;49Go@KZt7gwP}LrHFcI{RNn>4Me#y$>M<<9` zB(lVUl6;%3$d*8zxo_~5D=rNNvPCBYEDnCYP${E?m8FyxmSMuulKf>hhBqE#) zhB@ID3AG_yA*k`@VL~|-*Eh(>orYd)lmtRjDlWrIk3QX(N+3%qO-5)yAOmoF5)AnN zMjG*%NvRyUXZ>96;!Bi2NhuFZqtPz1MTaTrV=f?Dd2IUkh{Y!_^`mXRj3u3xM92K! zww9P?6DF)Fwn|TA{!}V@s8S@Eu(a@3u<{a)XEpO_Jo**1V#0*-e6*b$OSpe*K#3C( z?|X?8^{vEoaD^3v%6N=Hl@(PqT*&Wq_Kkw8@fkGEzcQ>IZJ4xrJcj#ndbw53P9u*(DEn7rNO&~4gkbnX{WNTTS^koe zA~H0k`H$Y3dsM-qNTR$&Aes_iaG&8OTjmSAMJpRJn5Di+l7Ct9W21cu=a#RiD3Asu zBq--g%FC8beOC;&ytgUa5hP8tHwB^XV1fm}X1j zU?JB0R`qUU{?_E`R?n3hYWQ@#s*ITg&HO|X zTR9{^QwVW_;+vU|C%-fw^W`ir!TK_%hmmtJF@|xbe4)WC-B&2JY-PoYGT0RqgjS)s z7y_sA;*^H+K*3GH4Z8X{<)}KSN_%u>{I_ z-_H~HaX5pXBd6&{d0BA*t$|6ki5Hg0vMb6l_LQO<;n8peV^z1JNbE0u>qvxF6pLdN zNoI6mB9pRQvZA;|OeJwECKH$IV&(xfff15as7#8%gc{=dsdTB?nLiosS7rdot(@nZ zjFfF({C~8w^b7GX68J>|zewO03H%~~UnKC01pfac0UU>WiJL&EMA+F4(%*ofzZZn- z0_;`X8^pDB@$WR?DlVIeJASxgg@=8mzsW#n%{RQ>a{TO+;hLfN;rao~Ks>Hw(Vs_S zxO%{95QtrDHWP)=+4Q%#t3Zc^8u$s`A;TycCdzQK42^(1=;&{-MFCQ|xL(6b;KwyE z(U0p^tP*})trPvY!YRU=;E&4qPd_S)@~1q*km*%B_=bBA?o+sr;J$!shx@575|#hO z{bw?;n1YLp|9)fbRoNZTsKAUzEcefFF|aSAf?6 zr?fkPzb?~n2L858Qwsbqz)5dAP;QeP{tw_^0H?1B`1immp9bKaGQJ!5b>PIq?|`%W z)6=K$`uk_ikK-pLOcwcvs*4bTY#FWSk`j`V5SDs3{uBQ+596r+1f|Y-fL}S81#3c5 z)m*4TqttSPRN>qZ?ha)HH(W77IVw1s^X<7J0eg3vu$3j)EcjDCmHA6pg1A3vWeJ5< zW!Q+9ApTfUf+gQ(VF?vQB@`ne){;t=fWKgc|FQTiO2BCw{jsTp;zAs`P^fCJ9L z)jm|rzoJ~)V8`N#PDFFXZ5Jx`7LJu*u`e8j<>Sv$u>@>`f*JaALJ9b5LM(yy>cnEi zqL-De07XgR1mDrMSbBaX)}TvPR2G3A6uE^(OI9qST`j8kzx9#*p>`o%nFNF!-GlLc z6h|M05iQY?-6EF_qeX2^G^B%M$H>l57}1eEBS-ek_xbXRK>*o2q9Z#;j_fJ<>7)F} z#lewoP&nCDa%5Ni>B!FEYF8f}*<*6P{OA${(Ki*&M@N5G zlUyYQ${*!LUn(5Y5kJN($>I83-{;G3K0-ieeGJh5Z&>>B@$r`@(TVx(nvH%8w+~^y z&zB#yu&-Rh9Nd3_E2Tk4{wR)|4UXD{swn<#&QeJZ@QR-=KjI75_(eLh=OsTw_Y`RG z(*==^Y<}g>(Cq;Y$(YI&|K=y?bYRFQYF~Z-h-{%Ya((J?zb zR*b^{zRySZ5&}r3l;2r99O$M2_kBLPR}et?8RQ6})A@+xIEp_7CtjkF;~GJSVXp7< v<@X6fP$pufuN@fan(y;f=^F(2aEgmw{;%ayIMGlYeBVUSUGaGUeR=#}Pyi*^ literal 0 HcmV?d00001 diff --git a/release/aroma/qo_d/lib/libcutils.so b/release/aroma/qo_d/lib/libcutils.so new file mode 100644 index 0000000000000000000000000000000000000000..6b65366a7dd8e88fefef659338ffb44ad7207549 GIT binary patch literal 42220 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�Z}eZAk^ck!c~du%|Q5kxC1g! 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

          hewzqu;pTy-Z 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 TNv!Du$@?4g_p`*&$<+H_5WZWc literal 0 HcmV?d00001 diff --git a/release/aroma/qo_d/lib/libqc-opt.so b/release/aroma/qo_d/lib/libqc-opt.so new file mode 100644 index 0000000000000000000000000000000000000000..27fa571e4f9b6669a7ade8d1dc592d7e384a9b31 GIT binary patch literal 9584 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 literal 0 HcmV?d00001 From 3fc382e357774de99fd14395b10ec9319aec11cf Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Mon, 3 Feb 2014 16:56:57 +0100 Subject: [PATCH 210/215] Aroma : Date update. --- release/aroma/META-INF/com/google/android/aroma-config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release/aroma/META-INF/com/google/android/aroma-config b/release/aroma/META-INF/com/google/android/aroma-config index 035cbd66d8f..f99299a6253 100755 --- a/release/aroma/META-INF/com/google/android/aroma-config +++ b/release/aroma/META-INF/com/google/android/aroma-config @@ -34,7 +34,7 @@ ini_set("rom_name", "Glitch kernel"); ini_set("rom_version", "N7-AOSP"); ini_set("rom_author", "Tk-Glitch"); ini_set("rom_device", "Nexus 7 (2013)"); -ini_set("rom_date", "January 2014"); +ini_set("rom_date", "February 2014"); ini_set("force_colorspace","rgba"); #ini_set("dp","6"); From d23ffc836599e1c6cf6fb55ebe1b1f7a68bd6346 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Mon, 3 Feb 2014 17:42:24 +0100 Subject: [PATCH 211/215] Aroma : Update features list --- release/aroma/META-INF/com/google/android/aroma-config | 2 +- .../com/google/android/aroma/{changelog.txt => features.txt} | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) rename release/aroma/META-INF/com/google/android/aroma/{changelog.txt => features.txt} (95%) diff --git a/release/aroma/META-INF/com/google/android/aroma-config b/release/aroma/META-INF/com/google/android/aroma-config index f99299a6253..7e7255c0a6b 100755 --- a/release/aroma/META-INF/com/google/android/aroma-config +++ b/release/aroma/META-INF/com/google/android/aroma-config @@ -67,7 +67,7 @@ agreebox("Terms Of Use","Please read the Glitch kernel Terms of Use...","themes/ "Please check the box..." ); -textbox("Changelog",ini_get("rom_name") + " Changelog","themes/miui4/icon.info",readfile_aroma("changelog.txt")); +textbox("Features",ini_get("rom_name") + " Features","themes/miui4/icon.info",readfile_aroma("features.txt")); alert( "PLEASE NOTE:", diff --git a/release/aroma/META-INF/com/google/android/aroma/changelog.txt b/release/aroma/META-INF/com/google/android/aroma/features.txt similarity index 95% rename from release/aroma/META-INF/com/google/android/aroma/changelog.txt rename to release/aroma/META-INF/com/google/android/aroma/features.txt index fbbdf4a5913..1ea53037639 100755 --- a/release/aroma/META-INF/com/google/android/aroma/changelog.txt +++ b/release/aroma/META-INF/com/google/android/aroma/features.txt @@ -22,6 +22,7 @@ - Dynamic Fsync by Faux123 - USB fast charging support - USB OTG charge hack support by flar2 +- Max screen off frequency support by flar2 - Optimized algorithms and libraries - Various performance and power saving tweaks From 1c5d309b7e9fd73c3cdd549e37c18a3f046d22d3 Mon Sep 17 00:00:00 2001 From: animania260 Date: Tue, 4 Feb 2014 09:46:19 -0500 Subject: [PATCH 212/215] Fix derp- static integer- from Linux 3.4.78 merge --- arch/x86/kernel/cpu/perf_event_amd_ibs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/cpu/perf_event_amd_ibs.c b/arch/x86/kernel/cpu/perf_event_amd_ibs.c index ea34253cb9c..2763b21402c 100644 --- a/arch/x86/kernel/cpu/perf_event_amd_ibs.c +++ b/arch/x86/kernel/cpu/perf_event_amd_ibs.c @@ -287,7 +287,7 @@ static inline void perf_ibs_pm_init(void) { } #endif -static int __cpuinit +static int perf_ibs_cpu_notifier(struct notifier_block *self, unsigned long action, void *hcpu) { switch (action & ~CPU_TASKS_FROZEN) { From 0dfecee494de8a95cbe0e80c81f40e17be1f8e01 Mon Sep 17 00:00:00 2001 From: animania260 Date: Tue, 4 Feb 2014 09:49:38 -0500 Subject: [PATCH 213/215] prima: udate prima WiFi driver to 3.2.3.16 stable version. Changlog copy/pasted: ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- commit bbb00be0b838eb0812c0a97c95ee6787fada85e4 Author: Hardik Kantilal Patel Date: Fri Jan 24 09:19:21 2014 +0530 wlan : Revision 3.2.3.16 wlan : Revision 3.2.3.16 commit e5cb4d6074f64fd9c064926230e703b005ca3e35 Author: Hardik Kantilal Patel Date: Sat Jan 18 01:28:34 2014 +0530 wlan: Initilize country IE prefrence flag Initialize country IE prefrence flag to disable country IE hints issued by the CORE CRs-Fixed: 542802 commit 04b4db0bfbd919b71ca444abe519ed51020697f5 Author: Hardik Kantilal Patel Date: Sat Jan 18 01:37:03 2014 +0530 wlan: VOS ASSERT in csrRoamCompletion due to Assoc ref count. While switching between two AP, csr will reissue roam command again to the nextbss if it was interrupted by the dissconnect req for the previous bss.During this csr is incrementing bRefAssocStartCnt twice. When CSR will reissue the roam command it will reset the bRefAssocStartCnt if it was already set. CRs-fixed: 554723 commit 10801e4d01f01ca3a6296b4ccaba8a3790851501 Author: Hardik Kantilal Patel Date: Sat Jan 18 01:53:45 2014 +0530 wifi: Scan list not updated with correct APs on band change. To support P2P functionality driver will add 1, 6 and 11 irrespective of selected bands. When we set 5G band scan list is updated with APs on channel 1, 6 and 11 as well. Hence we are able to see APs on channel 1,6 and 11 when we receive beacons during p2p functionality. To mitigate this issue for P2P search don't consider beacons and probe responses which doesn't contain P2P IE. CRs-Fixed: 505337 commit 6157d557d2dbacf7fdacf59f4f4686c7dcfc1700 Author: Hardik Kantilal Patel Date: Mon Jan 20 22:14:54 2014 +0530 wlan : Revision 3.2.3.15 wlan : Revision 3.2.3.15 commit 118d50bf7b9c4af57961c3e8524293b0848b8a24 Author: Hardik Kantilal Patel Date: Mon Jan 20 21:55:07 2014 +0530 wlan: Fix to pass global temporary dynamic IPv6 addr Fix to pass global temporary dynamic IPv6 addr while configuring NS offload CRs-Fixed: 592499 commit 9c5a1899b286d9a1115fa5c7487eb5bd3ae1263b Author: Hardik Kantilal Patel Date: Mon Jan 20 11:44:58 2014 +0530 wlan: Fix for handling IPv6 notifier block rightly. Correct the register and unregister sequence of IPv6 notifier block. CRs-Fixed: 600300 commit ff6ea2ce4cfebfbe2b01c86c79079a951b2089d9 Author: Vinay Krishna Eranna Date: Sun Dec 1 17:00:15 2013 +0530 Registering IPv6 notifier to notify change in IP. Not able to retrieve IPv6 addresses on the interface when queried during the re-connection in suspend mode and thus failing to set NS offload during SETSUSPEND. Registering IPv6 notifier to get notification if any change in IP, so that we can reconfigure the offload parameters for new IP. CRs-Fixed: 557306 Change-Id: Id90112f346349fe48aa36de104efb532433af2aa commit 8482b3606c8dc6f434837ce135c7b220764c9c8b Author: Madan Mohan Koyyalamudi Date: Thu Nov 21 09:40:35 2013 -0800 wlan : Revision 3.2.3.14 wlan : Revision 3.2.3.14 commit 515bf61908be2615a29163b9c638d45b23d792c8 Author: pratik Bhalgat Date: Thu Nov 21 17:13:49 2013 +0530 wlan : Updated TDLS parameters in ini CRs-fixed: 575365 commit 8178e94c4cc9505524b360791bab6f443b7250ae Author: pratik Bhalgat Date: Thu Nov 21 17:09:20 2013 +0530 wlan: Flush scan results on PNO indication event. Flush scan results during PNO indication, so as to avoid indication/updation of stale entries to above layers, which may not have aged out during APPS collapse. --- .../prima/CORE/HDD/inc/wlan_hdd_main.h | 11 +- .../prima/CORE/HDD/inc/wlan_hdd_power.h | 2 +- .../CORE/HDD/src/wlan_hdd_early_suspend.c | 219 ++++++++++++++++-- .../prima/CORE/HDD/src/wlan_hdd_main.c | 19 +- .../prima/CORE/MAC/inc/qwlan_version.h | 4 +- .../prima/CORE/MAC/src/include/sirParams.h | 1 + .../MAC/src/pe/lim/limProcessBeaconFrame.c | 19 +- .../CORE/MAC/src/pe/lim/limScanResultUtils.c | 31 ++- .../CORE/MAC/src/pe/lim/limScanResultUtils.h | 4 +- .../prima/CORE/SME/src/csr/csrApiRoam.c | 12 +- .../prima/CORE/SME/src/csr/csrNeighborRoam.c | 2 +- .../prima/CORE/SME/src/sme_common/sme_Api.c | 5 + drivers/staging/prima/Kbuild | 2 +- .../prima/firmware_bin/WCNSS_qcom_cfg.ini | 14 ++ drivers/staging/prima/riva/inc/wlan_hal_msg.h | 1 + 15 files changed, 293 insertions(+), 53 deletions(-) diff --git a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_main.h b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_main.h index 33fb44e8cbf..4c8c3075131 100755 --- a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_main.h +++ b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_main.h @@ -682,6 +682,13 @@ struct hdd_adapter_s /** Handle to the network device */ struct net_device *dev; + +#ifdef WLAN_NS_OFFLOAD + /** IPv6 notifier callback for handling NS offload on change in IP */ + struct notifier_block ipv6_notifier; + bool ipv6_notifier_registered; + struct work_struct ipv6NotifierWorkQueue; +#endif //TODO Move this to sta Ctx struct wireless_dev wdev ; @@ -1100,5 +1107,7 @@ int wlan_hdd_validate_context(hdd_context_t *pHddCtx); int wlan_hdd_setIPv6Filter(hdd_context_t *pHddCtx, tANI_U8 filterType, tANI_U8 sessionId); #endif VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx); - +#ifdef WLAN_NS_OFFLOAD +void hdd_ipv6_notifier_work_queue(struct work_struct *work); +#endif #endif // end #if !defined( WLAN_HDD_MAIN_H ) diff --git a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_power.h b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_power.h index a1498a12ebc..0810397b29b 100644 --- a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_power.h +++ b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_power.h @@ -102,6 +102,6 @@ void hdd_conf_hostoffload(hdd_adapter_t * pAdapter, v_BOOL_t fenable); void hdd_conf_gtk_offload(hdd_adapter_t *pAdapter, v_BOOL_t fenable); #endif #ifdef WLAN_NS_OFFLOAD -void hdd_conf_ns_offload(hdd_adapter_t *pAdapter, v_BOOL_t fenable); +void hdd_conf_ns_offload(hdd_adapter_t *pAdapter, int fenable); #endif #endif // if !defined __WLAN_QCT_DRIVER_H diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_early_suspend.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_early_suspend.c index b3e798efe53..4c7a2275454 100644 --- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_early_suspend.c +++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_early_suspend.c @@ -107,6 +107,8 @@ #include "wlan_hdd_packet_filtering.h" #define HDD_SSR_BRING_UP_TIME 180000 +#define NS_DEFAULT_SLOT_INDEX 4 +#define NS_EXTENDED_SLOT_INDEX 18 static eHalStatus g_full_pwr_status; static eHalStatus g_standby_status; @@ -560,22 +562,135 @@ void hdd_conf_hostoffload(hdd_adapter_t *pAdapter, v_BOOL_t fenable) } #ifdef WLAN_NS_OFFLOAD -void hdd_conf_ns_offload(hdd_adapter_t *pAdapter, v_BOOL_t fenable) +void hdd_ipv6_notifier_work_queue(struct work_struct *work) +{ + hdd_adapter_t* pAdapter = + container_of(work, hdd_adapter_t, ipv6NotifierWorkQueue); + hdd_context_t *pHddCtx; + int status; + + hddLog(LOG1, FL("Reconfiguring NS Offload")); + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) + { + hddLog(LOGE, FL("HDD context is invalid")); + return; + } + + if ((eConnectionState_Associated == + (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) + && (VOS_TRUE == pHddCtx->sus_res_mcastbcast_filter_valid)) + { + // This invocation being part of the IPv6 registration callback, + // we are passing second parameter as 2 to avoid registration + // of IPv6 notifier again. + hdd_conf_ns_offload(pAdapter, 2); + } +} + +static int wlan_hdd_ipv6_changed(struct notifier_block *nb, + unsigned long data, void *arg) +{ + struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)arg; + struct net_device *ndev = ifa->idev->dev; + hdd_adapter_t *pAdapter = + container_of(nb, struct hdd_adapter_s, ipv6_notifier); + hdd_context_t *pHddCtx; + int status; + + if (pAdapter && pAdapter->dev == ndev) + { + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) + { + hddLog(LOGE, FL("HDD context is invalid")); + return NOTIFY_DONE; + } + + schedule_work(&pAdapter->ipv6NotifierWorkQueue); + } + + return NOTIFY_DONE; +} + +/**---------------------------------------------------------------------------- + + \brief hdd_conf_ns_offload() - Configure NS offload + + Called during SUSPEND to configure the NS offload (MC BC filter) which + reduces power consumption. + + \param - pAdapter - Adapter context for which NS offload is to be configured + \param - fenable - 0 - disable. + 1 - enable. (with IPv6 notifier registration) + 2 - enable. (without IPv6 notifier registration) + + \return - void + + ---------------------------------------------------------------------------*/ +void hdd_conf_ns_offload(hdd_adapter_t *pAdapter, int fenable) { struct inet6_dev *in6_dev; struct inet6_ifaddr *ifp; struct list_head *p; - tANI_U8 selfIPv6Addr[SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA][SIR_MAC_IPV6_ADDR_LEN] = {{0,}}; - tANI_BOOLEAN selfIPv6AddrValid[SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA] = {0}; tSirHostOffloadReq offLoadRequest; + int slot_index = NS_DEFAULT_SLOT_INDEX; + tANI_U32 **selfIPv6Addr; + tANI_U32 *selfIPv6AddrValid; hdd_context_t *pHddCtx; - int i =0; + int i = 0, j = 0; + int ret = 0; eHalStatus returnStatus; + ENTER(); + hddLog(LOG1, FL(" fenable = %d"), fenable); + + if (sme_IsFeatureSupportedByFW(EXTENDED_NSOFFLOAD_SLOT)) + { + slot_index = NS_EXTENDED_SLOT_INDEX; + } + + hddLog(VOS_TRACE_LEVEL_INFO, FL("slot_idex = %d"), slot_index); + + selfIPv6AddrValid = + (tANI_U32 *)vos_mem_malloc(sizeof(tANI_U32) * slot_index); + selfIPv6Addr = (tANI_U32 **)vos_mem_malloc(sizeof(tANI_U32 *) * slot_index); + + if (NULL == selfIPv6Addr || NULL == selfIPv6AddrValid) + { + hddLog (VOS_TRACE_LEVEL_ERROR, FL("Failed to allocate memory")); + goto end; + } + + for (j = 0; j < slot_index; j++) + { + selfIPv6Addr[j] = + (tANI_U32 *)vos_mem_malloc(sizeof(tANI_U32) * SIR_MAC_IPV6_ADDR_LEN); + if (NULL == selfIPv6Addr[j]) + { + hddLog (VOS_TRACE_LEVEL_ERROR, FL("Failed to allocate memory")); + goto end; + } + } + + memset(selfIPv6AddrValid, 0, slot_index * sizeof(tANI_U32)); + + for(i = 0; i < slot_index; i++) + { + for(j = 0; j < SIR_MAC_IPV6_ADDR_LEN; j++) + { + selfIPv6Addr[i][j] = 0; + } + } + + i = 0; + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); - ENTER(); if (fenable) { in6_dev = __in6_dev_get(pAdapter->dev); @@ -584,34 +699,46 @@ void hdd_conf_ns_offload(hdd_adapter_t *pAdapter, v_BOOL_t fenable) //read_lock_bh(&in6_dev->lock); list_for_each(p, &in6_dev->addr_list) { + if (i >= slot_index) + { + hddLog (VOS_TRACE_LEVEL_ERROR, + FL("IPv6 address list is greater than IPv6 address supported" + " by firmware")); + hddLog (VOS_TRACE_LEVEL_ERROR, FL("FW supported IPv6 address = %d"), slot_index); + break; + } ifp = list_entry(p, struct inet6_ifaddr, if_list); switch(ipv6_addr_src_scope(&ifp->addr)) { case IPV6_ADDR_SCOPE_LINKLOCAL: - vos_mem_copy(&selfIPv6Addr[0], &ifp->addr.s6_addr, + vos_mem_copy(selfIPv6Addr[i], &ifp->addr.s6_addr, sizeof(ifp->addr.s6_addr)); - selfIPv6AddrValid[0] = SIR_IPV6_ADDR_VALID; + selfIPv6AddrValid[i] = SIR_IPV6_ADDR_VALID; hddLog (VOS_TRACE_LEVEL_INFO, - "Found IPV6_ADDR_SCOPE_LINKLOCAL Address : %pI6", - selfIPv6Addr[0]); + FL("Found IPV6_ADDR_SCOPE_LINKLOCAL Address : %pI6"), + selfIPv6Addr[i]); break; case IPV6_ADDR_SCOPE_GLOBAL: - vos_mem_copy(&selfIPv6Addr[1], &ifp->addr.s6_addr, + vos_mem_copy(selfIPv6Addr[i], &ifp->addr.s6_addr, sizeof(ifp->addr.s6_addr)); - selfIPv6AddrValid[1] = SIR_IPV6_ADDR_VALID; + selfIPv6AddrValid[i] = SIR_IPV6_ADDR_VALID; hddLog (VOS_TRACE_LEVEL_INFO, - "Found IPV6_ADDR_SCOPE_GLOBAL Address : %pI6", - selfIPv6Addr[1]); + FL("Found IPV6_ADDR_SCOPE_GLOBAL Address : %pI6"), + selfIPv6Addr[i]); break; default: - hddLog(LOGE, "The Scope %d is not supported", + hddLog(VOS_TRACE_LEVEL_ERROR, FL("The Scope %d is not supported"), ipv6_addr_src_scope(&ifp->addr)); } + if(selfIPv6AddrValid[i] == SIR_IPV6_ADDR_VALID) + { + i++; + } } //read_unlock_bh(&in6_dev->lock); vos_mem_zero(&offLoadRequest, sizeof(offLoadRequest)); - for (i =0; imacAddressCurrent.bytes, sizeof(tANI_U8)*SIR_MAC_ADDR_LEN); @@ -645,7 +772,9 @@ void hdd_conf_ns_offload(hdd_adapter_t *pAdapter, v_BOOL_t fenable) offLoadRequest.enableOrDisable = SIR_OFFLOAD_ENABLE; hddLog (VOS_TRACE_LEVEL_INFO, - "configuredMcastBcastFilter: %d",pHddCtx->configuredMcastBcastFilter); + FL("configuredMcastBcastFilter: %d" + "NSOffload Slot = %d"), + pHddCtx->configuredMcastBcastFilter, i); if ((VOS_TRUE == pHddCtx->sus_res_mcastbcast_filter_valid) && ((HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST == @@ -654,7 +783,8 @@ void hdd_conf_ns_offload(hdd_adapter_t *pAdapter, v_BOOL_t fenable) pHddCtx->sus_res_mcastbcast_filter))) { hddLog (VOS_TRACE_LEVEL_INFO, - "Set offLoadRequest with SIR_OFFLOAD_NS_AND_MCAST_FILTER_ENABLE \n", __func__); + FL("Set offLoadRequest with" + "SIR_OFFLOAD_NS_AND_MCAST_FILTER_ENABLE")); offLoadRequest.enableOrDisable = SIR_OFFLOAD_NS_AND_MCAST_FILTER_ENABLE; } @@ -664,7 +794,8 @@ void hdd_conf_ns_offload(hdd_adapter_t *pAdapter, v_BOOL_t fenable) sizeof(tANI_U8)*SIR_MAC_IPV6_ADDR_LEN); hddLog (VOS_TRACE_LEVEL_INFO, - "Setting NSOffload with solicitedIp: %pI6, targetIp: %pI6", + FL("Setting NSOffload with solicitedIp: %pI6," + "targetIp: %pI6"), offLoadRequest.nsOffloadInfo.selfIPv6Addr, offLoadRequest.nsOffloadInfo.targetIPv6Addr[0]); @@ -680,29 +811,69 @@ void hdd_conf_ns_offload(hdd_adapter_t *pAdapter, v_BOOL_t fenable) vos_mem_zero(&offLoadRequest, sizeof(offLoadRequest)); } } + if (fenable == 1 && !pAdapter->ipv6_notifier_registered) + { + // Register IPv6 notifier to notify if any change in IP + // So that we can reconfigure the offload parameters + pAdapter->ipv6_notifier.notifier_call = + wlan_hdd_ipv6_changed; + ret = register_inet6addr_notifier(&pAdapter->ipv6_notifier); + if (ret) + { + hddLog(LOGE, FL("Failed to register IPv6 notifier")); + } + else + { + hddLog(LOG1, FL("Registered IPv6 notifier")); + pAdapter->ipv6_notifier_registered = true; + } + } } else { hddLog(VOS_TRACE_LEVEL_ERROR, FL("IPv6 dev does not exist. Failed to request NSOffload")); - return; + goto end; } } else { //Disable NSOffload + if (pAdapter->ipv6_notifier_registered) + { + hddLog(LOG1, FL("Unregistered IPv6 notifier")); + unregister_inet6addr_notifier(&pAdapter->ipv6_notifier); + pAdapter->ipv6_notifier_registered = false; + } vos_mem_zero((void *)&offLoadRequest, sizeof(tSirHostOffloadReq)); offLoadRequest.enableOrDisable = SIR_OFFLOAD_DISABLE; offLoadRequest.offloadType = SIR_IPV6_NS_OFFLOAD; - if (eHAL_STATUS_SUCCESS != + for (i = 0; i < slot_index; i++) + { + hddLog(VOS_TRACE_LEVEL_INFO, FL("Disable Slot= %d"), i); + offLoadRequest.nsOffloadInfo.slotIdx = i; + if (eHAL_STATUS_SUCCESS != sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, &offLoadRequest)) - { - hddLog(VOS_TRACE_LEVEL_ERROR, FL("Failure to disable" - "NSOffload feature")); + { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Fail to disable Slot= %d"), i); + } } } +end: + while (j > 0 && selfIPv6Addr[--j]) + { + vos_mem_free(selfIPv6Addr[j]); + } + if (selfIPv6Addr) + { + vos_mem_free(selfIPv6Addr); + } + if (selfIPv6AddrValid) + { + vos_mem_free(selfIPv6AddrValid); + } return; } #endif diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_main.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_main.c index 5a53219454d..2c7fe8032d6 100755 --- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_main.c +++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_main.c @@ -101,6 +101,8 @@ #include #endif // WLAN_BTAMP_FEATURE +#include +#include #include #include #include "wlan_hdd_cfg80211.h" @@ -3770,6 +3772,11 @@ hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type, hdd_deinit_adapter(pHddCtx, pAdapter); goto err_free_netdev; } + +#ifdef WLAN_NS_OFFLOAD + // Workqueue which gets scheduled in IPv6 notification callback. + INIT_WORK(&pAdapter->ipv6NotifierWorkQueue, hdd_ipv6_notifier_work_queue); +#endif //Stop the Interface TX queue. netif_tx_disable(pAdapter->dev); //netif_tx_disable(pWlanDev); @@ -3863,7 +3870,6 @@ hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type, } } - if( VOS_STATUS_SUCCESS == status ) { //Add it to the hdd's session list. @@ -4060,6 +4066,17 @@ VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter ) { hdd_abort_mac_scan(pHddCtx); } +#ifdef WLAN_NS_OFFLOAD +#ifdef WLAN_OPEN_SOURCE + cancel_work_sync(&pAdapter->ipv6NotifierWorkQueue); +#endif + if (pAdapter->ipv6_notifier_registered) + { + hddLog(LOG1, FL("Unregistered IPv6 notifier")); + unregister_inet6addr_notifier(&pAdapter->ipv6_notifier); + pAdapter->ipv6_notifier_registered = false; + } +#endif if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags)) { diff --git a/drivers/staging/prima/CORE/MAC/inc/qwlan_version.h b/drivers/staging/prima/CORE/MAC/inc/qwlan_version.h index 50398427319..f7f6d141533 100644 --- a/drivers/staging/prima/CORE/MAC/inc/qwlan_version.h +++ b/drivers/staging/prima/CORE/MAC/inc/qwlan_version.h @@ -60,9 +60,9 @@ BRIEF DESCRIPTION: #define QWLAN_VERSION_MINOR 2 #define QWLAN_VERSION_PATCH 3 #define QWLAN_VERSION_EXTRA "" -#define QWLAN_VERSION_BUILD 13 +#define QWLAN_VERSION_BUILD 16 -#define QWLAN_VERSIONSTR "3.2.3.13" +#define QWLAN_VERSIONSTR "3.2.3.16" #endif /* QWLAN_VERSION_H */ diff --git a/drivers/staging/prima/CORE/MAC/src/include/sirParams.h b/drivers/staging/prima/CORE/MAC/src/include/sirParams.h index f539fb274f5..42144cf372b 100644 --- a/drivers/staging/prima/CORE/MAC/src/include/sirParams.h +++ b/drivers/staging/prima/CORE/MAC/src/include/sirParams.h @@ -97,6 +97,7 @@ typedef enum { #ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD WLAN_ROAM_SCAN_OFFLOAD = 23, #endif + EXTENDED_NSOFFLOAD_SLOT = 24, //MAX_FEATURE_SUPPORTED = 128 } placeHolderInCapBitmap; diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessBeaconFrame.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessBeaconFrame.c index bebfa11b842..c6ece4d95c9 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessBeaconFrame.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessBeaconFrame.c @@ -157,14 +157,9 @@ limProcessBeaconFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession ps if ((pMac->lim.gLimMlmState == eLIM_MLM_WT_PROBE_RESP_STATE) || (pMac->lim.gLimMlmState == eLIM_MLM_PASSIVE_SCAN_STATE)) { - //If we are scanning for P2P, only accept probe rsp - if((pMac->lim.gLimHalScanState != eLIM_HAL_SCANNING_STATE) || (NULL == pMac->lim.gpLimMlmScanReq) - || !pMac->lim.gpLimMlmScanReq->p2pSearch ) - { - limCheckAndAddBssDescription(pMac, pBeacon, pRxPacketInfo, - ((pMac->lim.gLimHalScanState == eLIM_HAL_SCANNING_STATE) ? eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE), - eANI_BOOLEAN_FALSE); - } + limCheckAndAddBssDescription(pMac, pBeacon, pRxPacketInfo, + ((pMac->lim.gLimHalScanState == eLIM_HAL_SCANNING_STATE) ? eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE), + eANI_BOOLEAN_FALSE); } else if (pMac->lim.gLimMlmState == eLIM_MLM_LEARN_STATE) { @@ -281,12 +276,8 @@ limProcessBeaconFrameNoSession(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo) if ( (pMac->lim.gLimMlmState == eLIM_MLM_WT_PROBE_RESP_STATE) || (pMac->lim.gLimMlmState == eLIM_MLM_PASSIVE_SCAN_STATE) ) { - //If we are scanning for P2P, only accept probe rsp - if((pMac->lim.gLimHalScanState != eLIM_HAL_SCANNING_STATE) || (NULL == pMac->lim.gpLimMlmScanReq) - || !pMac->lim.gpLimMlmScanReq->p2pSearch ) - { - limCheckAndAddBssDescription(pMac, pBeacon, pRxPacketInfo, eANI_BOOLEAN_TRUE, eANI_BOOLEAN_FALSE); - } + limCheckAndAddBssDescription(pMac, pBeacon, pRxPacketInfo, + eANI_BOOLEAN_TRUE, eANI_BOOLEAN_FALSE); } else if (pMac->lim.gLimMlmState == eLIM_MLM_LEARN_STATE) { diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limScanResultUtils.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limScanResultUtils.c index abd96363fb0..4ce22cc09d3 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limScanResultUtils.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limScanResultUtils.c @@ -139,14 +139,14 @@ limDeactivateMinChannelTimerDuringScan(tpAniSirGlobal pMac) * @return None */ #if defined WLAN_FEATURE_VOWIFI -void +eHalStatus limCollectBssDescription(tpAniSirGlobal pMac, tSirBssDescription *pBssDescr, tpSirProbeRespBeacon pBPR, tANI_U8 *pRxPacketInfo, tANI_U8 fScanning) #else -void +eHalStatus limCollectBssDescription(tpAniSirGlobal pMac, tSirBssDescription *pBssDescr, tpSirProbeRespBeacon pBPR, @@ -165,6 +165,17 @@ limCollectBssDescription(tpAniSirGlobal pMac, rxChannel = WDA_GET_RX_CH(pRxPacketInfo); pBody = WDA_GET_RX_MPDU_DATA(pRxPacketInfo); + /** + * Drop all the beacons and probe response without P2P IE during P2P search + */ + if (NULL != pMac->lim.gpLimMlmScanReq && pMac->lim.gpLimMlmScanReq->p2pSearch) + { + if (NULL == limGetP2pIEPtr(pMac, (pBody + SIR_MAC_B_PR_SSID_OFFSET), ieLen)) + { + limLog( pMac, LOG3, MAC_ADDRESS_STR, MAC_ADDR_ARRAY(pHdr->bssId)); + return eHAL_STATUS_FAILURE; + } + } /** * Length of BSS desription is without length of @@ -283,7 +294,7 @@ limCollectBssDescription(tpAniSirGlobal pMac, pBssDescr->aniIndicator, ieLen ); - return; + return eHAL_STATUS_SUCCESS; } /*** end limCollectBssDescription() ***/ /** @@ -497,11 +508,19 @@ limCheckAndAddBssDescription(tpAniSirGlobal pMac, // In scan state, store scan result. #if defined WLAN_FEATURE_VOWIFI - limCollectBssDescription(pMac, &pBssDescr->bssDescription, + status = limCollectBssDescription(pMac, &pBssDescr->bssDescription, pBPR, pRxPacketInfo, fScanning); + if (eHAL_STATUS_SUCCESS != status) + { + goto last; + } #else - limCollectBssDescription(pMac, &pBssDescr->bssDescription, + status = limCollectBssDescription(pMac, &pBssDescr->bssDescription, pBPR, pRxPacketInfo); + if (eHAL_STATUS_SUCCESS != status) + { + goto last; + } #endif /* Calling dfsChannelList which will convert DFS channel * to Active channel for x secs if this channel is DFS channel */ @@ -595,10 +614,12 @@ limCheckAndAddBssDescription(tpAniSirGlobal pMac, } }//(eANI_BOOLEAN_TRUE == fScanning) +last: if( eHAL_STATUS_SUCCESS != status ) { palFreeMemory( pMac->hHdd, pBssDescr ); } + return; } /****** end limCheckAndAddBssDescription() ******/ diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limScanResultUtils.h b/drivers/staging/prima/CORE/MAC/src/pe/lim/limScanResultUtils.h index b16147dd9a3..13aa8f4ec71 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limScanResultUtils.h +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limScanResultUtils.h @@ -76,13 +76,13 @@ void limReInitLfrScanResults(tpAniSirGlobal); tANI_U32 limDeactivateMinChannelTimerDuringScan(tpAniSirGlobal); void limCheckAndAddBssDescription(tpAniSirGlobal, tpSirProbeRespBeacon, tANI_U8 *, tANI_BOOLEAN, tANI_U8); #if defined WLAN_FEATURE_VOWIFI -void limCollectBssDescription(tpAniSirGlobal, +eHalStatus limCollectBssDescription(tpAniSirGlobal, tSirBssDescription *, tpSirProbeRespBeacon, tANI_U8 *, tANI_U8); #else -void limCollectBssDescription(tpAniSirGlobal, +eHalStatus limCollectBssDescription(tpAniSirGlobal, tSirBssDescription *, tpSirProbeRespBeacon, tANI_U8 *); diff --git a/drivers/staging/prima/CORE/SME/src/csr/csrApiRoam.c b/drivers/staging/prima/CORE/SME/src/csr/csrApiRoam.c index 5f5653b9700..8c9838470bc 100644 --- a/drivers/staging/prima/CORE/SME/src/csr/csrApiRoam.c +++ b/drivers/staging/prima/CORE/SME/src/csr/csrApiRoam.c @@ -6953,7 +6953,17 @@ void csrRoamReissueRoamCommand(tpAniSirGlobal pMac) smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); return; } - + + /* While switching between two AP, csr will reissue roam command again + to the nextbss if it was interrupted by the dissconnect req for the + previous bss.During this csr is incrementing bRefAssocStartCnt twice. + so reset the bRefAssocStartCnt. + */ + if(pSession->bRefAssocStartCnt > 0) + { + pSession->bRefAssocStartCnt--; + } + if( pCommand->u.roamCmd.fStopWds ) { palZeroMemory(pMac->hHdd, &roamInfo, sizeof(tCsrRoamInfo)); diff --git a/drivers/staging/prima/CORE/SME/src/csr/csrNeighborRoam.c b/drivers/staging/prima/CORE/SME/src/csr/csrNeighborRoam.c index 694e5cfc21e..6f487426c24 100644 --- a/drivers/staging/prima/CORE/SME/src/csr/csrNeighborRoam.c +++ b/drivers/staging/prima/CORE/SME/src/csr/csrNeighborRoam.c @@ -86,7 +86,7 @@ #include "csrCcx.h" #endif -/* #define WLAN_FEATURE_NEIGHBOR_ROAMING_DEBUG 1 */ +#define WLAN_FEATURE_NEIGHBOR_ROAMING_DEBUG 1 #ifdef WLAN_FEATURE_NEIGHBOR_ROAMING_DEBUG #define NEIGHBOR_ROAM_DEBUG smsLog #else diff --git a/drivers/staging/prima/CORE/SME/src/sme_common/sme_Api.c b/drivers/staging/prima/CORE/SME/src/sme_common/sme_Api.c index 1f50bc871f1..ccedacffa44 100755 --- a/drivers/staging/prima/CORE/SME/src/sme_common/sme_Api.c +++ b/drivers/staging/prima/CORE/SME/src/sme_common/sme_Api.c @@ -5960,6 +5960,11 @@ eHalStatus sme_PreferredNetworkFoundInd (tHalHandle hHal, void* pMsg) smsLog(pMac, LOG2, "%s:SSID=%s frame length %d", __func__, dumpSsId, pPrefNetworkFoundInd->frameLength); + /* Flush scan results, So as to avoid indication/updation of + * stale entries, which may not have aged out during APPS collapse + */ + sme_ScanFlushResult(hHal,0); + //Save the frame to scan result if (pPrefNetworkFoundInd->mesgLen > sizeof(tSirPrefNetworkFoundInd)) { diff --git a/drivers/staging/prima/Kbuild b/drivers/staging/prima/Kbuild index ce33a11b232..c23afb1aa82 100644 --- a/drivers/staging/prima/Kbuild +++ b/drivers/staging/prima/Kbuild @@ -628,7 +628,7 @@ CDEFINES += -DWLAN_OPEN_SOURCE endif # Fix build for GCC 4.7 -EXTRA_CFLAGS += -Wno-maybe-uninitialized -Wno-unused-function -Wno-array-bounds +EXTRA_CFLAGS += -Wno-maybe-uninitialized -Wno-unused-function KBUILD_CPPFLAGS += $(CDEFINES) diff --git a/drivers/staging/prima/firmware_bin/WCNSS_qcom_cfg.ini b/drivers/staging/prima/firmware_bin/WCNSS_qcom_cfg.ini index 8b32fbd0c1b..ae2894a18dd 100644 --- a/drivers/staging/prima/firmware_bin/WCNSS_qcom_cfg.ini +++ b/drivers/staging/prima/firmware_bin/WCNSS_qcom_cfg.ini @@ -396,6 +396,20 @@ gRrmOperChanMax=8 gRrmNonOperChanMax=8 gRrmRandIntvl=100 +# TDLS Support +gEnableTDLSSupport=1 +gEnableTDLSImplicitTrigger=1 +gTDLSExternalControl=1 +gTDLSTxStatsPeriod=500 +gTDLSTxPacketThreshold=10 +gTDLSDiscoveryPeriod=20000 +gTDLSMaxDiscoveryAttempt=5 +gTDLSIdleTimeout=40000 +gTDLSRssiHysteresis=100 +gTDLSRSSITriggerThreshold=-60 +gTDLSIdlePacketThreshold=5 +gTDLSRSSITeardownThreshold=-70 + END # Note: Configuration parser would not read anything past the END marker diff --git a/drivers/staging/prima/riva/inc/wlan_hal_msg.h b/drivers/staging/prima/riva/inc/wlan_hal_msg.h index 3526e330cd2..ff26657ce95 100644 --- a/drivers/staging/prima/riva/inc/wlan_hal_msg.h +++ b/drivers/staging/prima/riva/inc/wlan_hal_msg.h @@ -5666,6 +5666,7 @@ typedef enum { RATECTRL = 21, WOW = 22, WLAN_ROAM_SCAN_OFFLOAD = 23, + EXTENDED_NSOFFLOAD_SLOT = 24, //MAX_FEATURE_SUPPORTED = 128 } placeHolderInCapBitmap; From 119a55c8da824866c34f959ae816c7c9eaf7388e Mon Sep 17 00:00:00 2001 From: animania260 Date: Tue, 4 Feb 2014 20:04:58 -0500 Subject: [PATCH 214/215] Change glitch.sh buildscript toolchain path --- glitch.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/glitch.sh b/glitch.sh index 468ed7b74f4..0ff887d43a5 100755 --- a/glitch.sh +++ b/glitch.sh @@ -13,7 +13,7 @@ repo=~/android/system export ARCH="arm" #export CROSS_PREFIX="$repo/prebuilts/gcc/linux-x86/arm/arm-eabi-4.6/bin/arm-eabi-" #export CROSS_PREFIX="$repo/prebuilts/gcc/linux-x86/arm/linaro_4.8.2-2013.09/bin/arm-gnueabi-" -export CROSS_PREFIX="$repo/prebuilts/gcc/linux-x86/arm/sabermod-androideabi-4.8.3/bin/arm-linux-androideabi-" +export CROSS_PREFIX="/home/belial/android/android_prebuilts_gcc_linux-x86_arm_sabermod-arm-linux-androideabi-4.8/bin/arm-linux-androideabi-" setup () { @@ -60,8 +60,8 @@ build () rm -fr "$target_dir" mkdir -p "$target_dir" - mka -C "$KERNEL_DIR" O="$target_dir" flo_defconfig HOSTCC="$CCACHE gcc" - mka -C "$KERNEL_DIR" O="$target_dir" HOSTCC="$CCACHE gcc" CROSS_COMPILE="$CCACHE $CROSS_PREFIX" zImage modules + make -j5 -o3 -C "$KERNEL_DIR" O="$target_dir" flo_defconfig HOSTCC="$CCACHE gcc" + make -j5 -o3 -C "$KERNEL_DIR" O="$target_dir" HOSTCC="$CCACHE gcc" CROSS_COMPILE="$CCACHE $CROSS_PREFIX" zImage modules [[ -d release ]] || { echo "must be in kernel root dir" From 2ba384b410ee03b0937da2def22f72822d643769 Mon Sep 17 00:00:00 2001 From: Tk-Glitch Date: Wed, 5 Feb 2014 00:11:22 +0100 Subject: [PATCH 215/215] Workqueue : Fix section mismatches Signed-off-by: Tk-Glitch --- kernel/workqueue.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/kernel/workqueue.c b/kernel/workqueue.c index b537accaee8..2a11e26183e 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -3688,7 +3688,7 @@ static int workqueue_cpu_callback(struct notifier_block *nfb, * Workqueues should be brought up before normal priority CPU notifiers. * This will be registered high priority CPU notifier. */ -static int __devinit workqueue_cpu_up_callback(struct notifier_block *nfb, +static int workqueue_cpu_up_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { @@ -3706,7 +3706,7 @@ static int __devinit workqueue_cpu_up_callback(struct notifier_block *nfb, * Workqueues should be brought down after normal priority CPU notifiers. * This will be registered as low priority CPU notifier. */ -static int __devinit workqueue_cpu_down_callback(struct notifier_block *nfb, +static int workqueue_cpu_down_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) {

        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�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

      2. F|K?3fmSe6B~ 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 z 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 literal 196355 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�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

      |Op$sg6ZA9Y&&;4ARlY#HsNZFe5lu~7eD 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 N{^(I_T~9r^{{a);no$4% literal 0 HcmV?d00001 diff --git a/release/zimage/META-INF/com/google/android/updater-script b/release/zimage/META-INF/com/google/android/updater-script new file mode 100755 index 00000000000..c9839fc1e0d --- /dev/null +++ b/release/zimage/META-INF/com/google/android/updater-script @@ -0,0 +1,39 @@ +ui_print("---------------------------------------"); +ui_print("| Glitch kernel for flo |"); +ui_print("---------------------------------------"); +ui_print("Nexus 7 (2013) Kernel..."); +set_progress(1.000000); +ui_print("Mount /System Folder..."); +mount("ext4", "EMMC", "/dev/block/mmcblk0p22", "/system"); +ui_print("Extracting System Files..."); +package_extract_dir("system", "/system"); +ui_print("Extracting Kernel files..."); +package_extract_dir("kernel", "/tmp"); +set_perm(0, 0, 0777, "/tmp/compatibility.sh"); +set_perm(0, 0, 0777, "/tmp/edit_ramdisk.sh"); +set_perm(0, 0, 0777, "/tmp/mkbootimg.sh"); +set_perm(0, 0, 0777, "/tmp/mkbootimg"); +set_perm(0, 0, 0777, "/tmp/unpackbootimg"); +set_perm(0, 0, 0777, "/tmp/busybox"); + +ui_print("Installing kernel..."); +run_program("/tmp/busybox", "dd", "if=/dev/block/mmcblk0p14", "of=/tmp/boot.img"); +run_program("/tmp/unpackbootimg", "-i", "/tmp/boot.img", "-o", "/tmp/"); + +################RAMDISK EDITS +ui_print("Fixing your ramdisk..."); +ui_print(" removing governor overrides..."); +ui_print(" Looking for busybox..."); +run_program("/tmp/edit_ramdisk.sh"); +set_progress(0.65); + +run_program("/tmp/mkbootimg.sh"); +run_program("/tmp/busybox", "dd", "if=/tmp/newboot.img", "of=/dev/block/mmcblk0p14"); + + +################RENAME thermald & mpdecision +ui_print("Renaming binaries..."); +ui_print(" /system/bin/mpdecision -> mpdecision_bck"); +run_program("/tmp/compatibility.sh"); + +unmount("/system"); diff --git a/release/zimage/kernel/busybox b/release/zimage/kernel/busybox new file mode 100644 index 0000000000000000000000000000000000000000..e7acacfb6249eb7eefa5e3f41edb2e41ca3d3198 GIT binary patch literal 478912 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%0DXC$1QXP&&&C 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